fltk-1.4.3/0000755000175000017500000000000015004146477012621 5ustar albrechtalbrechtfltk-1.4.3/CMake/0000755000175000017500000000000015004135251013565 5ustar albrechtalbrechtfltk-1.4.3/CMake/variables.cmake0000644000175000017500000001232115004135251016536 0ustar albrechtalbrecht# # This file sets variables for common use in export.cmake and install.cmake # Originally written by Michael Surette # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ####################################################################### set(DEBUG_VARIABLES_CMAKE 0) if(DEBUG_VARIABLES_CMAKE) message(STATUS "[** variables.cmake **]") fl_debug_var(HAVE_DLSYM) fl_debug_var(CMAKE_DL_LIBS) fl_debug_var(CMAKE_EXE_LINKER_FLAGS) fl_debug_var(LDFLAGS) fl_debug_var(GLLIBS) fl_debug_var(IMAGELIBS) fl_debug_var(STATICIMAGELIBS) fl_debug_var(FLTK_LDLIBS) fl_debug_var(LIB_jpeg) fl_debug_var(LIB_png) fl_debug_var(LIB_zlib) fl_debug_var(FLTK_LIBRARIES) endif(DEBUG_VARIABLES_CMAKE) ####################################################################### # add several libraries # FIXME: libraries may need reordering. # FIXME: check fontconfig conditions (only if Xft is used or ...) if(WIN32) list(APPEND FLTK_LDLIBS -lole32 -luuid -lcomctl32 -lws2_32 -lwinspool) elseif(APPLE AND NOT FLTK_BACKEND_X11) list(APPEND FLTK_LDLIBS ${FLTK_COCOA_FRAMEWORKS}) elseif(FLTK_BACKEND_WAYLAND) foreach(_lib WLDCURSOR WLDCLIENT XKBCOMMON DBUS) list(APPEND FLTK_LDLIBS "${${_lib}_LDFLAGS}") endforeach() if(USE_SYSTEM_LIBDECOR) list(APPEND FLTK_LDLIBS ${SYSTEM_LIBDECOR_LDFLAGS}) endif(USE_SYSTEM_LIBDECOR) else() list(APPEND FLTK_LDLIBS -lm) endif(WIN32) if(LIB_fontconfig) list(APPEND FLTK_LDLIBS -lfontconfig) endif(LIB_fontconfig) # add "-ldl" or whatever is necessary according to CMake (CMAKE_DL_LIBS) if(HAVE_DLSYM) foreach(LIB ${CMAKE_DL_LIBS}) list(APPEND FLTK_LDLIBS "-l${LIB}") endforeach() endif(HAVE_DLSYM) ####################################################################### # Set variables for fltk-config (generated from fltk-config.in) ####################################################################### # Variables in fltk-config.in (@VAR@) are used in configure(.ac) # and in CMake so their names and usage must be synchronized. # CMake generates two instances of fltk-config, one that can be used # directly in the build tree (see export.cmake) and one that is copied # to the installation directory (see install.cmake). Common variables # should be set here, whereas variables with different values should # be set in install.cmake or export.cmake, respectively. if(WIN32) set(LDFLAGS "${CMAKE_EXE_LINKER_FLAGS} -mwindows") endif() set(IMAGELIBS) set(STATICIMAGELIBS) if(FLTK_USE_BUNDLED_JPEG) list(APPEND IMAGELIBS -lfltk_jpeg) list(APPEND STATICIMAGELIBS \$libdir/libfltk_jpeg.a) else() if(LIB_jpeg) # fl_debug_var(LIB_jpeg) list(APPEND IMAGELIBS ${LIB_jpeg}) list(APPEND STATICIMAGELIBS ${LIB_jpeg}) endif(LIB_jpeg) endif(FLTK_USE_BUNDLED_JPEG) if(FLTK_USE_BUNDLED_PNG) list(APPEND IMAGELIBS -lfltk_png) list(APPEND STATICIMAGELIBS \$libdir/libfltk_png.a) else() if(LIB_png) # fl_debug_var(LIB_png) list(APPEND IMAGELIBS ${LIB_png}) list(APPEND STATICIMAGELIBS ${LIB_png}) endif(LIB_png) endif(FLTK_USE_BUNDLED_PNG) if(FLTK_USE_BUNDLED_ZLIB) list(APPEND IMAGELIBS -lfltk_z) list(APPEND STATICIMAGELIBS \$libdir/libfltk_z.a) else() if(LIB_zlib) list(APPEND IMAGELIBS ${LIB_zlib}) list(APPEND STATICIMAGELIBS ${LIB_zlib}) endif(LIB_zlib) endif(FLTK_USE_BUNDLED_ZLIB) # remove duplicates from CMake "list" variables for fltk-config list(REMOVE_DUPLICATES GLLIBS) list(REMOVE_DUPLICATES FLTK_LDLIBS) list(REMOVE_DUPLICATES IMAGELIBS) list(REMOVE_DUPLICATES STATICIMAGELIBS) # convert CMake lists to strings with spaces for fltk-config string(REPLACE ";" " " GLLIBS "${GLLIBS}") string(REPLACE ";" " " LIBS "${FLTK_LDLIBS}") string(REPLACE ";" " " IMAGELIBS "${IMAGELIBS}") string(REPLACE ";" " " STATICIMAGELIBS "${STATICIMAGELIBS}") ####################################################################### set(CC ${CMAKE_C_COMPILER}) set(CXX ${CMAKE_CXX_COMPILER}) set(ARCHFLAGS ${FLTK_ARCHFLAGS}) string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_UPPER) if(${BUILD_UPPER}) set(CFLAGS "${CMAKE_C_FLAGS_${BUILD_UPPER}} ${CFLAGS}") endif(${BUILD_UPPER}) set(CFLAGS "${FLTK_OPTION_OPTIM} ${CMAKE_C_FLAGS} ${CFLAGS}") foreach(arg ${FLTK_CFLAGS}) set(CFLAGS "${CFLAGS} ${arg}") endforeach(arg ${FLTK_CFLAGS}) set(CXXFLAGS "${CFLAGS}") if(${CMAKE_SYSTEM_NAME} STREQUAL "AIX") set(SHAREDSUFFIX "_s") else() set(SHAREDSUFFIX "") endif(${CMAKE_SYSTEM_NAME} STREQUAL "AIX") if(DEBUG_VARIABLES_CMAKE) message(STATUS "") # empty line fl_debug_var(HAVE_DLSYM) fl_debug_var(CMAKE_DL_LIBS) fl_debug_var(CMAKE_EXE_LINKER_FLAGS) fl_debug_var(LDFLAGS) fl_debug_var(FLTK_LDLIBS) fl_debug_var(LIBS) fl_debug_var(GLLIBS) fl_debug_var(IMAGELIBS) fl_debug_var(STATICIMAGELIBS) fl_debug_var(LIB_jpeg) fl_debug_var(LIB_png) fl_debug_var(LIB_zlib) fl_debug_var(FLTK_LIBRARIES) message(STATUS "[** end of variables.cmake **]") endif(DEBUG_VARIABLES_CMAKE) unset(DEBUG_VARIABLES_CMAKE) fltk-1.4.3/CMake/macOS-bundle-wrapper.in0000644000175000017500000000143515004135251020047 0ustar albrechtalbrecht#!/bin/sh # # Run the executable of a macOS bundle for the Fast Light Tool Kit (FLTK). # # Copyright 1998-2020 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # # # Install this script side by side with the macOS bundle with the same name: # # - dir/prog.app macOS bundle (directory) # - dir/prog this script: runs the executable 'prog' inside the bundle # prog="`basename \"$0\"`" dir="`dirname \"$0\"`" exec "$dir/$prog.app/Contents/MacOS/$prog" "$@" fltk-1.4.3/CMake/setup.cmake0000644000175000017500000001702315004135251015732 0ustar albrechtalbrecht# # CMakeLists.txt to build the FLTK project using CMake (www.cmake.org) # Originally written by Michael Surette # # Copyright 1998-2025 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ####################################################################### # basic setup ####################################################################### set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin) set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib) set(ARCHIVE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib) # Search for modules in the FLTK source dir first set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake") # Setup install locations (requires CMake 2.8.4) include(GNUInstallDirs) set(FLTK_BINDIR ${CMAKE_INSTALL_BINDIR} CACHE PATH "Binary install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.") set(FLTK_LIBDIR ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Library install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.") set(FLTK_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH "Public header install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.") set(FLTK_DATADIR ${CMAKE_INSTALL_DATADIR} CACHE PATH "Non-arch data install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.") set(FLTK_MANDIR ${CMAKE_INSTALL_MANDIR} CACHE PATH "Manual install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.") set(FLTK_DOCDIR ${CMAKE_INSTALL_DATADIR}/doc CACHE PATH "Non-arch doc install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.") ####################################################################### # Initialize variables needed to collect include directories etc.. # Some of these variables are used to *append* other values later ####################################################################### set(FLTK_BUILD_INCLUDE_DIRECTORIES "") set(FLTK_IMAGE_INCLUDE_DIRECTORIES "") set(FLTK_IMAGE_LIBRARIES "") set(FLTK_IMAGE_LIBRARIES_SHARED "") set(FLTK_CFLAGS "") set(FLTK_LIBRARIES "") set(FLTK_LIBRARIES_SHARED "") # Remember root of FLTK source directory in case we're later in a subdirectory. # Used for instance to find the source directory for doxygen docs set(FLTK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) if(FLTK_SOURCE_DIR STREQUAL ${CMAKE_SOURCE_DIR}) set(FLTK_IS_TOPLEVEL TRUE) else() set(FLTK_IS_TOPLEVEL FALSE) endif() # Note: FLTK_INCLUDE_DIRS is used to export the required include directories # in FLTKConfig.cmake etc. # ### FIXME ### check if we really need this ... set(FLTK_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) # FLTK_BUILD_INCLUDE_DIRECTORIES is used to build the main FLTK lib set(FLTK_BUILD_INCLUDE_DIRECTORIES) # Some of these variables are used to *append* other values later set(FLTK_LDLIBS "") set(FLTK_LIBRARIES "") set(IMAGELIBS "") set(LDFLAGS "") set(LINK_LIBS "") set(STATICIMAGELIBS "") ####################################################################### # platform dependent information ####################################################################### # set where config files go if(WIN32 AND NOT CYGWIN) set(FLTK_CONFIG_PATH CMake) elseif(APPLE AND NOT FLTK_BACKEND_X11) set(FLTK_CONFIG_PATH ${FLTK_DATADIR}/fltk) else() set(FLTK_CONFIG_PATH ${FLTK_DATADIR}/fltk) endif(WIN32 AND NOT CYGWIN) include(TestBigEndian) TEST_BIG_ENDIAN(WORDS_BIGENDIAN) if(CMAKE_GENERATOR MATCHES "Xcode") # Tell Xcode to regenerate scheme information automatically whenever the # CMake configuration changes without asking the user set(CMAKE_XCODE_GENERATE_SCHEME 1) endif() if(APPLE) # Check if the __MAC_OS_X_VERSION_MAX_ALLOWED compile time macro is at least # the version encoded in SDK_VERSION and return TRUE or FALSE in RESULT. # Note 1: try_compile() always creates an *internal* CMake cache variable for # the result which we set to 'FLTK_CHECK_OSX_MAX_ALLOWED_${SDK_VERSION}'. # Note 2: 'FLTK_' to avoid polluting the cache if FLTK is built as a subproject. # Note 3: We don't care about the cache, i.e. we run try_compile() unconditionally # so users can switch SDK's, particularly if they *upgrade* Xcode. function(CHECK_OSX_MAX_ALLOWED SDK_VERSION RESULT) set(_result FLTK_CHECK_OSX_MAX_ALLOWED_${SDK_VERSION}) try_compile(${_result} ${CMAKE_CURRENT_BINARY_DIR}/CHECK_OSX_MAX_ALLOWED_${SDK_VERSION} SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMake/macOSMaxAllowed.c COMPILE_DEFINITIONS -DSDK_VERSION_CHECK=${SDK_VERSION} ) set(${RESULT} ${${_result}} PARENT_SCOPE) endfunction() # APPLE macOS setup set(HAVE_STRCASECMP 1) set(HAVE_DIRENT_H 1) set(HAVE_SNPRINTF 1) set(HAVE_VSNPRINTF 1) set(HAVE_SCANDIR 1) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated") if(FLTK_BACKEND_X11) if(NOT(${CMAKE_SYSTEM_VERSION} VERSION_LESS 17.0.0)) # a.k.a. macOS version ≥ 10.13 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_LIBCPP_HAS_THREAD_API_PTHREAD") endif(NOT(${CMAKE_SYSTEM_VERSION} VERSION_LESS 17.0.0)) else() set(FLTK_COCOA_FRAMEWORKS "-framework Cocoa") if (NOT (CMAKE_OSX_ARCHITECTURES STREQUAL "ppc" OR CMAKE_OSX_ARCHITECTURES STREQUAL "i386")) CHECK_OSX_MAX_ALLOWED(150000 SDK_15_AVAILABLE) # at least SDK 15.0.0 ? if (SDK_15_AVAILABLE) list(APPEND FLTK_COCOA_FRAMEWORKS "-weak_framework ScreenCaptureKit") # 15.0 list(APPEND FLTK_COCOA_FRAMEWORKS "-weak_framework UniformTypeIdentifiers") # 11.0 else(SDK_15_AVAILABLE) CHECK_OSX_MAX_ALLOWED(110000 SDK_11_AVAILABLE) # at least SDK 11.0.0 ? if (SDK_11_AVAILABLE) list(APPEND FLTK_COCOA_FRAMEWORKS "-weak_framework UniformTypeIdentifiers") endif(SDK_11_AVAILABLE) endif(SDK_15_AVAILABLE) endif() endif(FLTK_BACKEND_X11) endif(APPLE) if(WIN32) # we do no longer define WIN32 or _WIN32 (since FLTK 1.4.0) # ... but if we did, we'd define _WIN32 (since FLTK 1.4.0) # add_definitions (-D_WIN32) if(MSVC) add_definitions (-DWIN32_LEAN_AND_MEAN) add_definitions (-D_CRT_SECURE_NO_WARNINGS) if(NOT MSVC_VERSION VERSION_LESS 1900) # Visual Studio 2015 add_compile_options (/utf-8) # equivalent to `/source-charset:utf-8 /execution-charset:utf-8` endif() set(BORDER_WIDTH 2) endif(MSVC) # Don't use the following code, it breaks building with MSYS2/UCRT64 # See GitHub PR #1167. Solution is to remove the entire block! ### if(MINGW AND EXISTS /mingw) ### list(APPEND CMAKE_PREFIX_PATH /mingw) ### endif(MINGW AND EXISTS /mingw) endif(WIN32) ####################################################################### # size of ints include(CheckTypeSize) CHECK_TYPE_SIZE(short SIZEOF_SHORT) CHECK_TYPE_SIZE(int SIZEOF_INT) CHECK_TYPE_SIZE(long SIZEOF_LONG) CHECK_TYPE_SIZE("long long" HAVE_LONG_LONG) if(${SIZEOF_SHORT} MATCHES "^2$") set(U16 "unsigned short") endif(${SIZEOF_SHORT} MATCHES "^2$") if(${SIZEOF_INT} MATCHES "^4$") set(U32 "unsigned") else() if(${SIZEOF_LONG} MATCHES "^4$") set(U32 "unsigned long") endif(${SIZEOF_LONG} MATCHES "^4$") endif(${SIZEOF_INT} MATCHES "^4$") if(${SIZEOF_INT} MATCHES "^8$") set(U64 "unsigned") else() if(${SIZEOF_LONG} MATCHES "^8$") set(U64 "unsigned long") endif(${SIZEOF_LONG} MATCHES "^8$") endif(${SIZEOF_INT} MATCHES "^8$") fltk-1.4.3/CMake/MacOSXBundleInfo.plist.in0000644000175000017500000000235315004135251020312 0ustar albrechtalbrecht CFBundleDevelopmentRegion English CFBundleExecutable ${MACOSX_BUNDLE_EXECUTABLE_NAME} CFBundleGetInfoString ${MACOSX_BUNDLE_INFO_STRING} CFBundleIconFile ${MACOSX_BUNDLE_ICON_FILE} CFBundleIdentifier ${MACOSX_BUNDLE_GUI_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString ${MACOSX_BUNDLE_LONG_VERSION_STRING} CFBundleName ${MACOSX_BUNDLE_BUNDLE_NAME} CFBundlePackageType APPL CFBundleShortVersionString ${MACOSX_BUNDLE_SHORT_VERSION_STRING} CFBundleSignature ???? CFBundleVersion ${MACOSX_BUNDLE_BUNDLE_VERSION} CSResourcesFileMapped NSHumanReadableCopyright ${MACOSX_BUNDLE_COPYRIGHT} NSHighResolutionCapable fltk-1.4.3/CMake/fl_debug_var.cmake0000644000175000017500000001031315004135251017204 0ustar albrechtalbrecht# # Function used by the CMake build system for the Fast Light Tool Kit (FLTK). # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ####################################################################### # fl_expand_name - a function to expand a variable name with spaces ####################################################################### # # This function returns a string comprising of the given name and # enough spaces to have at least the given minimal length (min_len). # Currently min_len must not be greater than 50. # # If the string is already at least min_len it is not changed, # otherwise the string is returned to the given variable (out) # in the parent scope. # # Syntax: # fl_expand_name (out in min_len) # # Example: # fl_expand_name (var WIN32 30) # fl_expand_name (var UNIX 40) # ####################################################################### function(fl_expand_name out in min_len) string(LENGTH "${in}" len) if(len LESS min_len) set(spaces " ") set(temp "${in}") set(temp "${in}${spaces}${spaces}") string(SUBSTRING "${temp}" 0 ${min_len} temp) set(${out} "${temp}" PARENT_SCOPE) else() set(${out} "${in}" PARENT_SCOPE) endif() endfunction(fl_expand_name) ####################################################################### # fl_debug_var - a function to output debugging info ####################################################################### # # This function displays the name and value of a CMake variable. # The variable name is expanded with spaces to be (at least) # (currently 30) characters wide for better readability. # VARNAME must be a string literal, e.g. WIN32 or "WIN32". # # Syntax: # fl_debug_var(VARNAME) # # Example: # fl_debug_var(WIN32) # fl_debug_var("UNIX") # ####################################################################### function(fl_debug_var name) set(var "${name}") fl_expand_name(var "${name}" 40) message(STATUS "${var} = '${${name}}'") endfunction(fl_debug_var) ####################################################################### # fl_debug_target - a function to output info about a target ####################################################################### # # This function displays properties of a CMake target. # # Currently there's a fixed number of properties. # # Syntax: # fl_debug_target(target) # # Example: # fl_debug_target(fltk) # fl_debug_target(fluid) # fl_debug_target(fltk_image) # fl_debug_target(fltk::forms) # ####################################################################### function(fl_debug_target name) message(STATUS "+++ fl_debug_target(${name})") set(var "${name}") fl_expand_name(var "${name}" 40) if(NOT TARGET ${name}) message(STATUS "${var} = ") message(STATUS "") return() endif() get_target_property(_type ${name} TYPE) # message(STATUS "${var} = target, type = ${_type}") # these properties are always supported: set(_props NAME TYPE ALIASED_TARGET) # these properties can't be read from executable target types ### if(NOT _type STREQUAL "EXECUTABLE") ### list(APPEND _props ### LOCATION ### IMPORTED_LOCATION ### INTERFACE_LOCATION) ### endif() if(NOT _type STREQUAL "INTERFACE_LIBRARY" OR CMAKE_VERSION VERSION_GREATER_EQUAL "3.19") # Before 3.19: "INTERFACE_LIBRARY targets may only have whitelisted properties" list(APPEND _props INCLUDE_DIRECTORIES LINK_DIRECTORIES LINK_LIBRARIES COMPILE_DEFINITIONS) endif() list(APPEND _props INTERFACE_COMPILE_DEFINITIONS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_DIRECTORIES INTERFACE_LINK_LIBRARIES) foreach(prop ${_props}) get_target_property(${prop} ${name} ${prop}) if(NOT ${prop}) set(${prop} "") endif() fl_debug_var(${prop}) endforeach() message(STATUS "") endfunction(fl_debug_target) fltk-1.4.3/CMake/fl_debug_pkg.cmake0000644000175000017500000000417015004135251017201 0ustar albrechtalbrecht# # Macro used by the CMake build system for the Fast Light Tool Kit (FLTK). # # Copyright 2022 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ####################################################################### # fl_debug_pkg - a macro to output pkgconfig debugging info ####################################################################### # # This macro displays the name and value of some CMake variables # defined by pkg_check_modules(). # # Syntax: # # fl_debug_pkg(PREFIX NAME) # # Example for package "cairo": # # pkg_check_modules (CAIRO cairo) # fl_debug_pkg(CAIRO cairo) # # The first command searches for pkg 'cairo' and stores the results # in CMake variables with prefix 'CAIRO_'. # # The second command displays all relevant variables if the package has # been found, otherwise only 'CAIRO_FOUND' (empty or false). # ####################################################################### macro(fl_debug_pkg PREFIX NAME) message("") message(STATUS "Results of pkg_check_modules(${PREFIX}, ${NAME}):") fl_debug_var(${PREFIX}_FOUND) if(${PREFIX}_FOUND) fl_debug_var(${PREFIX}_INCLUDE_DIRS) fl_debug_var(${PREFIX}_CFLAGS) fl_debug_var(${PREFIX}_LIBRARIES) fl_debug_var(${PREFIX}_LINK_LIBRARIES) fl_debug_var(${PREFIX}_LIBRARY_DIRS) fl_debug_var(${PREFIX}_LDFLAGS) fl_debug_var(${PREFIX}_LDFLAGS_OTHER) fl_debug_var(${PREFIX}_CFLAGS_OTHER) fl_debug_var(${PREFIX}_STATIC_INCLUDE_DIRS) fl_debug_var(${PREFIX}_STATIC_CFLAGS) fl_debug_var(${PREFIX}_STATIC_LIBRARIES) fl_debug_var(${PREFIX}_STATIC_LINK_LIBRARIES) fl_debug_var(${PREFIX}_STATIC_LIBRARY_DIRS) fl_debug_var(${PREFIX}_VERSION) fl_debug_var(${PREFIX}_PREFIX) fl_debug_var(${PREFIX}_INCLUDEDIR) fl_debug_var(${PREFIX}_LIBDIR) endif() message("") endmacro(fl_debug_pkg) fltk-1.4.3/CMake/cmake_uninstall.cmake.in0000644000175000017500000000351415004135251020350 0ustar albrechtalbrecht# # Support file to uninstall the FLTK project using CMake # # Originally written by Michael Surette # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") endif() file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") # Note 1: 'cmake -E remove [-f]' is deprecated since CMake 3.17 and the docs # state: "The implementation was buggy and always returned 0. It cannot be # fixed without breaking backwards compatibility. Use rm instead." # Note 2: 'cmake -E rm [-f]' has been added in CMake 3.17 # Note 3: # Remove this distinction if: cmake_minimum_required(VERSION 3.17) or higher. if(CMAKE_VERSION VERSION_LESS 3.17) set(rm_cmd remove) else() set(rm_cmd rm) endif() foreach(file ${files}) message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") execute_process( COMMAND "${CMAKE_COMMAND}" -E ${rm_cmd} -f "$ENV{DESTDIR}${file}" OUTPUT_VARIABLE rm_out ERROR_VARIABLE rm_err RESULT_VARIABLE rm_retval ) if(NOT "${rm_retval}" STREQUAL 0) message(STATUS "Error removing \"$ENV{DESTDIR}${file}\"") message(STATUS " Status = '${rm_retval}'") message(STATUS " Output = '${rm_out}'") message(STATUS " Error = '${rm_err}'") message(FATAL_ERROR "Exiting - uninstall may be incomplete.") endif() endforeach(file) fltk-1.4.3/CMake/fl_create_example.cmake0000644000175000017500000001526315004135251020235 0ustar albrechtalbrecht# # A function used by the CMake build system for the Fast Light Tool Kit (FLTK). # Originally written by Michael Surette # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ################################################################################ # # function fl_create_example - Create a test/demo (example) program # # Input: # # - NAME: program name, e.g. 'hello' # # - SOURCES: list of source files, separated by ';' (needs quotes) # Sources can be: # - .c/.cxx files, e.g. 'hello.cxx' # - .fl (fluid) files, e.g. 'radio.fl' # - .plist file(macOS), e.g. 'editor.plist' # - .icns file(macOS Icon), e.g. 'checkers.icns' # - .rc file(Windows resource file, e.g. icon definition) # # Order of sources doesn't matter, multiple .cxx and .fl files are # supported, but only one .plist and one .icns file. # # File name (type), e.g. '.icns' matters, it is parsed internally: # File types .fl, .plist, and .icns are treated specifically, # all other file types are added to the target's source files. # # macOS specific .icns and .plist files are ignored on other platforms. # These files must reside in the subdirectory 'mac-resources'. # # - LIBRARIES: # List of libraries (CMake target names), separated by ';'. Must be # quoted if more than one library is required, e.g. "fltk::gl;fltk::images" # ################################################################################ function(fl_create_example NAME SOURCES LIBRARIES) set(srcs) # source files set(flsrcs) # fluid source (.fl) files set(TARGET_NAME ${NAME}) # CMake target name set(ICON_NAME) # macOS icon (max. one) set(PLIST) # macOS .plist file(max. one) set(ICON_PATH) # macOS icon resource path # create macOS bundle? 0 = no, 1 = yes if(APPLE AND NOT FLTK_BACKEND_X11) set(MAC_BUNDLE 1) else() set(MAC_BUNDLE 0) endif() # filter input files for different handling (fluid, icon, plist, source) foreach(src ${SOURCES}) if("${src}" MATCHES "\\.fl$") list(APPEND flsrcs ${src}) elseif("${src}" MATCHES "\\.icns$") set(ICON_NAME "${src}") elseif("${src}" MATCHES "\\.plist$") set(PLIST "${src}") else() list(APPEND srcs ${src}) endif("${src}" MATCHES "\\.fl$") endforeach(src) # generate source files from .fl files, add output to sources if(flsrcs) if(NOT FLTK_FLUID_EXECUTABLE) message(STATUS "Example app \"${NAME}\" will not be built. FLUID executable not found.") return () endif() FLTK_RUN_FLUID (FLUID_SOURCES "${flsrcs}") list(APPEND srcs ${FLUID_SOURCES}) unset(FLUID_SOURCES) endif(flsrcs) # set macOS (icon) resource path if applicable if(MAC_BUNDLE AND ICON_NAME) set(ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/mac-resources/${ICON_NAME}") endif(MAC_BUNDLE AND ICON_NAME) ############################################################################## # add executable target and set properties (all platforms) ############################################################################## if(MAC_BUNDLE) add_executable (${TARGET_NAME} MACOSX_BUNDLE ${srcs} ${ICON_PATH}) else() add_executable (${TARGET_NAME} WIN32 ${srcs}) endif(MAC_BUNDLE) set_target_properties (${TARGET_NAME} PROPERTIES OUTPUT_NAME ${NAME}) target_link_libraries (${TARGET_NAME} PRIVATE ${LIBRARIES}) # make sure we're "exporting" global symbols like 'fl_disable_wayland', # see also README.Wayland.txt and CMake policy CMP0065. set_target_properties (${TARGET_NAME} PROPERTIES ENABLE_EXPORTS TRUE) ### *FIXME* Remove the entire 'if' block below when verified: if(0) # This should no longer be necessary (implied by linking the libs) # we must link all programs with Cairo if option CAIROEXT is enabled if(FLTK_HAVE_CAIROEXT) target_link_libraries(${TARGET_NAME} PRIVATE ${PKG_CAIRO_LIBRARIES}) endif() if(FLTK_HAVE_CAIRO AND PKG_CAIRO_LIBRARY_DIRS) target_link_directories(${TARGET_NAME} PRIVATE ${PKG_CAIRO_LIBRARY_DIRS}) endif() endif() # This should no longer be necessary (implied by linking the libs) # Search the current binary directory for header files created by CMake # or fluid and the source folder for other headers included by test programs target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ) if(MAC_BUNDLE) if(PLIST) set_target_properties(${TARGET_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/mac-resources/${PLIST}") endif() string(REPLACE "_" "-" FLTK_BUNDLE_ID "org.fltk.${TARGET_NAME}") set_target_properties(${TARGET_NAME} PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "${TARGET_NAME}") set_target_properties(${TARGET_NAME} PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER "${FLTK_BUNDLE_ID}") set_target_properties(${TARGET_NAME} PROPERTIES XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${FLTK_BUNDLE_ID}") if(ICON_NAME) set_target_properties(${TARGET_NAME} PROPERTIES MACOSX_BUNDLE_ICON_FILE ${ICON_NAME}) set_target_properties(${TARGET_NAME} PROPERTIES RESOURCE ${ICON_PATH}) endif() endif() ############################################################################## # Copy macOS "bundle wrapper" (shell script) to target directory. # The "custom command" will be executed "POST_BUILD". ############################################################################## if(MAC_BUNDLE) set(WRAPPER "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/${TARGET_NAME}") add_custom_command( TARGET ${TARGET_NAME} POST_BUILD COMMAND cp ${FLTK_SOURCE_DIR}/CMake/macOS-bundle-wrapper.in ${WRAPPER} COMMAND chmod u+x,g+x,o+x ${WRAPPER} BYPRODUCTS ${WRAPPER} # COMMENT "Creating macOS bundle wrapper script ${WRAPPER}" VERBATIM ) unset(WRAPPER) endif(MAC_BUNDLE) ############################################################################## # MSVC: Add fltk-shared (DLL) path to Environment 'PATH' for debugging ############################################################################## if(MSVC AND TARGET fltk-shared) set(DllDir "$>") set_target_properties(${TARGET_NAME} PROPERTIES VS_DEBUGGER_ENVIRONMENT "PATH=${DllDir};$ENV{PATH}" ) endif() endfunction() fltk-1.4.3/CMake/fl_add_library.cmake0000644000175000017500000002004415004135251017524 0ustar albrechtalbrecht# # Macro used by the CMake build system for the Fast Light Tool Kit (FLTK). # Originally written by Michael Surette # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ####################################################################### # fl_add_library - add a static or shared library to the build #====================================================================== # # Input: # # LIBNAME: name of the library, including 'fltk_' prefix if applicable. # # LIBTYPE: either "STATIC" or "SHARED" # # SOURCES: Files needed to build the library # # Output: # # FLTK_LIBRARIES or FLTK_LIBRARIES_SHARED (in parent scope) # # This function adds the given library to the build, adds it to # either FLTK_LIBRARIES or FLTK_LIBRARIES_SHARED, respectively, # and "exports" the modified variable to the parent scope. # # For each library an alias is defined (see comment below). # ####################################################################### function(fl_add_library LIBNAME LIBTYPE SOURCES) # message(STATUS "Building library **************** ${LIBNAME} ${LIBTYPE}") set(suffix "") if(LIBTYPE STREQUAL "SHARED") set(suffix "-shared") endif() set(TARGET_NAME ${LIBNAME}${suffix}) ## Strip 'fltk_' from target name (if it exists in the name) ## and use the result as EXPORT_NAME property. This makes it ## easy to export library targets fltk::fltk and fltk::images ## rather than fltk::fltk_images. string(REPLACE "fltk_" "" EXPORT_NAME ${TARGET_NAME}) if(MSVC) set(OUTPUT_NAME_DEBUG "${LIBNAME}d") else() set(OUTPUT_NAME_DEBUG "${LIBNAME}") endif(MSVC) set(OUTPUT_NAME_RELEASE "${LIBNAME}") add_library(${TARGET_NAME} ${LIBTYPE} ${SOURCES}) # Create an alias 'fltk::alias_name' for the library # where 'alias_name' is the library name without the prefix 'fltk_' # # e.g. 'fltk' -> 'fltk::fltk' # and 'fltk-shared' -> 'fltk::fltk-shared' # but 'fltk_images' -> 'fltk::images' # and 'fltk_images-shared' -> 'fltk::images-shared' if(NOT (LIBNAME STREQUAL "fltk")) string(REPLACE "fltk_" "" alias_name ${LIBNAME}) else() set(alias_name ${LIBNAME}) endif() set(alias_name "fltk::${alias_name}${suffix}") add_library(${alias_name} ALIAS ${TARGET_NAME}) if(0) fl_debug_var(TARGET_NAME) fl_debug_var(LIBTYPE) fl_debug_var(alias_name) # fl_debug_var(SOURCES) endif() # Target properties for all libraries # Set 'PRIVATE' target compile definitions for the library # so they are not inherited by consumers target_compile_definitions(${TARGET_NAME} PRIVATE "FL_LIBRARY") # Set PUBLIC include and linker directories if(0) # DEBUG message(STATUS "fl_add_library and alias : fltk::${alias_name} ALIAS ${TARGET_NAME}") fl_debug_var(TARGET_NAME) fl_debug_var(FLTK_INCLUDE_DIRS) fl_debug_var(CMAKE_CURRENT_BINARY_DIR) fl_debug_var(CMAKE_CURRENT_SOURCE_DIR) fl_debug_var(FLTK_BUILD_INCLUDE_DIRECTORIES) endif() # Special handling for the core 'fltk' library, # no matter if it's SHARED or STATIC # FIXME: maybe this should be in src/CMakeLists.txt (?) if(LIBNAME STREQUAL "fltk") target_include_directories(${TARGET_NAME} PUBLIC $ $ $ ) ### FIXME: why does the simplified else() block not work? ### Needs investigation, using 'if(1)' for now... if(1) foreach(dir ${FLTK_BUILD_INCLUDE_DIRECTORIES}) target_include_directories(${TARGET_NAME} PRIVATE $ ) endforeach() else() ### This generates a wrong string in property INTERFACE_INCLUDE_DIRECTORIES: ### ... $;/git/fltk/modern-cmake/src/$') ### I don't see anything wrong with this statement though but ### maybe I'm missing something. Albrecht, Jan 22 2024 target_include_directories(${TARGET_NAME} PRIVATE $ ) endif() target_link_directories(${TARGET_NAME} PUBLIC $ $ ) if(APPLE AND NOT FLTK_BACKEND_X11) foreach(item ${FLTK_COCOA_FRAMEWORKS}) target_link_libraries(${TARGET_NAME} PUBLIC "${item}") endforeach() endif() # we must link fltk with cairo if Cairo or Wayland is enabled (or both) if(FLTK_HAVE_CAIRO OR FLTK_USE_CAIRO) target_include_directories(${TARGET_NAME} PUBLIC ${PKG_CAIRO_INCLUDE_DIRS}) target_link_directories (${TARGET_NAME} PUBLIC ${PKG_CAIRO_LIBRARY_DIRS}) target_link_libraries (${TARGET_NAME} PUBLIC ${PKG_CAIRO_LIBRARIES}) endif() endif(LIBNAME STREQUAL "fltk") # Set additional target properties for static libraries if(LIBTYPE STREQUAL "STATIC") set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${LIBNAME} OUTPUT_NAME_DEBUG ${OUTPUT_NAME_DEBUG} OUTPUT_NAME_RELEASE ${OUTPUT_NAME_RELEASE} EXPORT_NAME ${EXPORT_NAME} ) endif(LIBTYPE STREQUAL "STATIC") # Set additional target properties for shared (dynamic) libraries (DLL's) if(LIBTYPE STREQUAL "SHARED") set_target_properties(${TARGET_NAME} PROPERTIES VERSION ${FLTK_VERSION} SOVERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR} OUTPUT_NAME ${LIBNAME} OUTPUT_NAME_DEBUG ${OUTPUT_NAME_DEBUG} OUTPUT_NAME_RELEASE ${OUTPUT_NAME_RELEASE} EXPORT_NAME ${EXPORT_NAME} ) # Visual Studio only: if(MSVC) set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${LIBNAME}_dll OUTPUT_NAME_DEBUG ${LIBNAME}_dlld OUTPUT_NAME_RELEASE ${LIBNAME}_dll ) target_compile_definitions(${TARGET_NAME} PUBLIC FL_DLL) endif(MSVC) endif(LIBTYPE STREQUAL "SHARED") # Debug library output names (optional) set(DEBUG_ONAME 0) if(DEBUG_ONAME) get_target_property(XX_NAME ${TARGET_NAME} NAME) get_target_property(XX_ONAME ${TARGET_NAME} OUTPUT_NAME) get_target_property(XX_ONAME_DEBUG ${TARGET_NAME} OUTPUT_NAME_DEBUG) get_target_property(XX_ONAME_RELEASE ${TARGET_NAME} OUTPUT_NAME_RELEASE) get_target_property(XX_EXPORT_NAME ${TARGET_NAME} EXPORT_NAME) message(STATUS "--- DEBUG_ONAME ---") fl_debug_var(TARGET_NAME) fl_debug_var(XX_NAME) fl_debug_var(XX_ONAME) fl_debug_var(XX_ONAME_DEBUG) fl_debug_var(XX_ONAME_RELEASE) fl_debug_var(XX_EXPORT_NAME) message(STATUS "--- /DEBUG_ONAME ---") endif(DEBUG_ONAME) if(MSVC) if(FLTK_OPTION_LARGE_FILE) set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS /LARGEADDRESSAWARE ) endif(FLTK_OPTION_LARGE_FILE) endif(MSVC) install(TARGETS ${TARGET_NAME} EXPORT FLTK-Targets RUNTIME DESTINATION ${FLTK_BINDIR} LIBRARY DESTINATION ${FLTK_LIBDIR} ARCHIVE DESTINATION ${FLTK_LIBDIR} ) if(LIBTYPE STREQUAL "SHARED") list(APPEND FLTK_LIBRARIES_SHARED "${TARGET_NAME}") set(FLTK_LIBRARIES_SHARED "${FLTK_LIBRARIES_SHARED}" PARENT_SCOPE) else() list(APPEND FLTK_LIBRARIES "${TARGET_NAME}") set(FLTK_LIBRARIES "${FLTK_LIBRARIES}" PARENT_SCOPE) endif() if(0) fl_debug_var(fl_add_library_DEBUG) fl_debug_var(FLTK_LIBRARIES) fl_debug_var(FLTK_LIBRARIES_SHARED) fl_debug_var(fl_add_library_END) message("") endif() endfunction(fl_add_library LIBNAME LIBTYPE SOURCES) fltk-1.4.3/CMake/install.cmake0000644000175000017500000000756315004135251016250 0ustar albrechtalbrecht# # Installation support for building the FLTK project using CMake (www.cmake.org) # Originally written by Michael Surette # # Copyright 1998-2025 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ####################################################################### # installation ####################################################################### # generate uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" @ONLY ) add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" ) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/FL DESTINATION ${FLTK_INCLUDEDIR} USE_SOURCE_PERMISSIONS FILES_MATCHING PATTERN "*.[hH]" PATTERN "fl_config.h" EXCLUDE ) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/FL DESTINATION ${FLTK_INCLUDEDIR} USE_SOURCE_PERMISSIONS FILES_MATCHING PATTERN "*.[hH]" ) if(FLTK_INSTALL_LINKS) install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/install-symlinks.cmake) endif(FLTK_INSTALL_LINKS) # generate FLTKConfig.cmake for installed directory use set(INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/include) if(FLTK_HAVE_CAIRO) list(APPEND INCLUDE_DIRS ${PKG_CAIRO_INCLUDE_DIRS}) endif() set(CONFIG_PATH ${CMAKE_INSTALL_PREFIX}/${FLTK_CONFIG_PATH}) install(EXPORT FLTK-Targets DESTINATION ${FLTK_CONFIG_PATH} FILE FLTK-Targets.cmake NAMESPACE fltk:: ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/CMake/FLTKConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/etc/FLTKConfig.cmake @ONLY ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/etc/FLTKConfig.cmake DESTINATION ${FLTK_CONFIG_PATH} ) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/CMake/FLTK-Functions.cmake DESTINATION ${FLTK_CONFIG_PATH} ) # Generate fltk-config set(prefix ${CMAKE_INSTALL_PREFIX}) set(exec_prefix "\${prefix}") set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") set(BINARY_DIR) set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") set(srcdir ".") set(LIBNAME "${libdir}/libfltk.a") configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/fltk-config.in" "${CMAKE_CURRENT_BINARY_DIR}/bin/fltk-config" @ONLY ) # Install fltk-config # Note: no need to set execute perms, install(PROGRAMS) does this install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/fltk-config DESTINATION ${FLTK_BINDIR} ) # Install man pages of fluid and fltk-options macro(INSTALL_MAN FILE LEVEL) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/documentation/src/${FILE}.man DESTINATION ${FLTK_MANDIR}/man${LEVEL} RENAME ${FILE}.${LEVEL} ) endmacro(INSTALL_MAN FILE LEVEL) if(FLTK_BUILD_FLUID) INSTALL_MAN (fluid 1) endif(FLTK_BUILD_FLUID) if(FLTK_BUILD_FLTK_OPTIONS) INSTALL_MAN (fltk-options 1) endif(FLTK_BUILD_FLTK_OPTIONS) INSTALL_MAN (fltk-config 1) INSTALL_MAN (fltk 3) # Install the games if(FLTK_BUILD_TEST) # "OR FLTK_BUILD_GAMES" (not yet implemented) set(games_ blocks checkers sudoku) if(FLTK_USE_GL) list(APPEND games_ glpuzzle) endif() foreach(game_ ${games_}) if(FLTK_BUILD_SHARED_LIBS) set(tgt_ "${game_}-shared") set_target_properties(${tgt_} PROPERTIES RUNTIME_OUTPUT_NAME ${game_}) else() set(tgt_ ${game_}) endif() install(TARGETS ${tgt_} EXPORT FLTK-Targets RUNTIME DESTINATION ${FLTK_BINDIR} LIBRARY DESTINATION ${FLTK_LIBDIR} ARCHIVE DESTINATION ${FLTK_LIBDIR} BUNDLE DESTINATION ${FLTK_BINDIR} # macOS: bundles ) # install man page INSTALL_MAN (${game_} 6) endforeach() unset(game_) unset(games_) endif() fltk-1.4.3/CMake/fl_summary.cmake0000644000175000017500000000702315004135251016747 0ustar albrechtalbrecht# # Macros used by the CMake build system for the Fast Light Tool Kit (FLTK). # # Copyright 2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ######################################################################## # The macros in this file are used to generate the CMake build summary. # Fixed widths of title fields are intentionally hard coded in two of # these macros so we can easily change the alignment. ######################################################################## include(${CMAKE_CURRENT_LIST_DIR}/fl_debug_var.cmake) ######################################################################## # Output a summary line like " <value>" ######################################################################## # <title> will be expanded to a fixed width (can be empty) # <value> text to be displayed ######################################################################## macro(fl_summary title value) fl_expand_name(label "${title}" 24) message(STATUS "${label} ${value}") endmacro(fl_summary title value) ######################################################################## # Output a summary line like "<title> will be built ..." # or "<title> will not be built ..." ######################################################################## # title will be expanded to a fixed width (must not be empty) # subdir = relative build directory (e.g. lib or bin/test) # build = CMake variable name (bool): whether <title> is built # option = option name the user can set to build <title> ######################################################################## macro(fl_summary_build title subdir build option) if(${build}) set(value "will be built in: ${CMAKE_CURRENT_BINARY_DIR}/${subdir}") else() set(value "will not be built (set ${option}=ON to build)") endif() fl_expand_name(label "${title}" 19) message(STATUS "${label} ${value}") endmacro(fl_summary_build title var subdir) ######################################################################## # Output a simple summary line like "<title> {Yes|No}" ######################################################################## # title will be expanded to a fixed width (must not be empty) # var = CMake variable name, must evaluate to true or false ######################################################################## macro(fl_summary_yn title var) if(${var}) set(value "Yes") else() set(value "No") endif() fl_summary("${title}" ${value}) endmacro(fl_summary_yn title var) ######################################################################## # Output summary line for image libs (bundled or system libs) ######################################################################## # title = "Image Libraries" or empty # name = displayed name = { JPEG | PNG | ZLIB } # lib = CMake library name (system library, if it was found) ######################################################################## macro(fl_summary_image title name lib) fl_expand_name(name4 "${name}" 8) if(FLTK_USE_BUNDLED_${name}) set(value "${name4} = Bundled") else() set(value "${name4} = System: ${${lib}}") endif() fl_summary("${title}" "${value}") endmacro(fl_summary_image title name lib) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/CMake/FLTK-Functions.cmake���������������������������������������������������������������0000644�0001750�0001750�00000005563�15004135251�017306� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # FLTK-Functions.cmake # Originally written by Michael Surette # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ################################################################################ # functions used by the build system and exported for the end-user ################################################################################ ################################################################################ # # fltk_run_fluid: Run fluid to compile fluid (.fl) files # # Usage: fltk_run_fluid(SOURCES "FLUID_SOURCE [.. FLUID_SOURCE]") # # Input: The CMake variable "FL_FILES" must contain a list of input # file names. Only names ending in ".fl" are considered and # compiled to their ".cxx" and ".h" files which are stored # in the current build directory. # # Output: "SOURCES" is used as a CMake variable name that is assigned the # names of the compiled ".cxx" files as a ";" separated list in the # parent scope (the caller's scope). # ################################################################################ function(fltk_run_fluid SOURCES FL_FILES) if(NOT FLTK_FLUID_EXECUTABLE) message(WARNING "Not building ${FL_FILES}. FLUID executable not found.") return() endif() set(CXX_FILES) foreach(src ${FL_FILES}) if("${src}" MATCHES "\\.fl$") string(REGEX REPLACE "(.*).fl" \\1 basename ${src}) add_custom_command( OUTPUT "${basename}.cxx" "${basename}.h" COMMAND ${FLTK_FLUID_EXECUTABLE} -c ${CMAKE_CURRENT_SOURCE_DIR}/${src} DEPENDS ${src} MAIN_DEPENDENCY ${src} ) list(APPEND CXX_FILES "${basename}.cxx") endif() endforeach() set(${SOURCES} ${CXX_FILES} PARENT_SCOPE) endfunction(fltk_run_fluid SOURCES FL_FILES) ################################################################################ # # fltk_set_bundle_icon: Set the bundle icon for macOS bundles # # This function sets macOS specific target properties. These properties are # ignored on other platforms. # # Usage: fltk_set_bundle_icon(TARGET ICON_PATH) # # TARGET must be a valid CMake target that has been created before this # function is called. It must not be an alias name. # ################################################################################ function(fltk_set_bundle_icon TARGET ICON_PATH) get_filename_component(ICON_NAME "${ICON_PATH}" NAME) set_target_properties(${TARGET} PROPERTIES MACOSX_BUNDLE_ICON_FILE "${ICON_NAME}" RESOURCE "${ICON_PATH}" ) endfunction(fltk_set_bundle_icon TARGET ICON_PATH) ���������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/CMake/posixScandir.cxx�������������������������������������������������������������������0000644�0001750�0001750�00000000306�15004135251�016756� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� #include <dirent.h> int func (const char *d, dirent ***list, void *sort) { int n = scandir(d, list, 0, (int(*)(const dirent **, const dirent **))sort); return n; } int main() { return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/CMake/pthread_mutex_recursive.c����������������������������������������������������������0000644�0001750�0001750�00000000206�15004135251�020667� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* FLTK feature test: do we have PTHREAD_MUTEX_RECURSIVE ? */ #include <pthread.h> int main() { return PTHREAD_MUTEX_RECURSIVE; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/CMake/macOSMaxAllowed.c������������������������������������������������������������������0000644�0001750�0001750�00000000303�15004135251�016705� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� #include <AvailabilityMacros.h> #if MAC_OS_X_VERSION_MAX_ALLOWED < SDK_VERSION_CHECK #error MAC_OS_X_VERSION_MAX_ALLOWED < SDK_VERSION_CHECK #endif int main(int argc, char** argv) { return 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/CMake/FLTKConfig.cmake.in����������������������������������������������������������������0000644�0001750�0001750�00000011433�15004135251�017064� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # FLTKConfig.cmake - FLTK CMake configuration file for external projects. # # This file is generated by CMake and used to load FLTK's settings for # an external project, i.e. a project using FLTK. # # It defines the following variables: # # FLTK_VERSION - FLTK version string ("x.y.z") # FLTK_INCLUDE_DIRS - FLTK include directories # FLTK_LIBRARIES - list of built FLTK libraries # FLTK_FLUID_EXECUTABLE - needed by the function FLTK_RUN_FLUID # (or the deprecated fltk_wrap_ui() CMake command) # # It defines the following deprecated variables for backwards # compatibility (do not use for new projects): # # FLTK_INCLUDE_DIR - FLTK include directories (same as FLTK_INCLUDE_DIRS) # # Important note: FLTK's CMake build files are not yet complete and may be # changed in future versions. This includes the list of defined variables # above that may be changed if necessary. # # Note: FLTK 1.4.0 introduced "Modern CMake", therefore usage of most if not # all of the variables mentioned above is no longer needed in user projects. # Please use the CMake target names fltk::fltk, fltk::images, etc. instead. # Please see README.CMake.txt for mor info on how to do this. # # Optional: Create backwards compatible aliases for libraries and fluid. # This is enabled in FLTK 1.4.0 to simplify migration of user projects # from "classic" (1.3.x) to "modern" CMake and will likely be removed # in a later FLTK version (maybe 1.4.x, x>2, or 1.5.0). set(FLTK_CREATE_COMPATIBILITY_ALIASES TRUE) set(FLTK_VERSION @FLTK_VERSION@) include(${CMAKE_CURRENT_LIST_DIR}/FLTK-Targets.cmake) set(FLTK_INCLUDE_DIRS "@INCLUDE_DIRS@") set(FLTK_LIBRARIES "@FLTK_LIBRARIES@") # For compatibility with CMake's FindFLTK.cmake: set(FLTK_INCLUDE_DIR "${FLTK_INCLUDE_DIRS}") if(CMAKE_CROSSCOMPILING) # Find a fluid executable on the build host to be able to build fluid programs find_program(FLTK_FLUID_HOST NAMES fluid fluid.exe PATHS ENV PATH NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) if(FLTK_FLUID_HOST) if(0) # Experimental: currently not used # Import a special 'fluid' target called 'fluid-host' (fltk::fluid-host) # Note: this is "the same as" the CMake variable FLTK_FLUID_EXECUTABLE add_executable(fluid-host IMPORTED) set_target_properties(fluid-host PROPERTIES IMPORTED_LOCATION ${FLTK_FLUID_HOST} ) add_executable(fltk::fluid-host ALIAS fluid-host) set(FLTK_FLUID_EXECUTABLE fltk::fluid-host) else() set(FLTK_FLUID_EXECUTABLE "${FLTK_FLUID_HOST}") endif() else() # fluid not found on build host message(STATUS "FLTKConfig.cmake (cross-compiling): fluid not found on the build host") # note: this assigns "FLTK_FLUID_HOST-NOTFOUND" and running fluid will fail set(FLTK_FLUID_EXECUTABLE "${FLTK_FLUID_HOST}") endif() else(CMAKE_CROSSCOMPILING) if(FLTK_CREATE_COMPATIBILITY_ALIASES) function(_fltk_make_alias target from) if(TARGET ${from} AND NOT TARGET ${target}) # message(STATUS "FLTKConfig.cmake - create alias: ${target} from ${from}") # promote imported target to global visibility (CMake < 3.18 only) if(CMAKE_VERSION VERSION_LESS "3.18") set_target_properties(${from} PROPERTIES IMPORTED_GLOBAL TRUE) endif() get_target_property(ttype ${from} TYPE) if(ttype STREQUAL "EXECUTABLE") add_executable(${target} ALIAS ${from}) else() add_library(${target} ALIAS ${from}) endif() endif() endfunction(_fltk_make_alias target) if(NOT TARGET fltk::fltk) message(FATAL "FLTKConfig.cmake: target fltk::fltk does not exist!") endif() _fltk_make_alias(fltk fltk::fltk) _fltk_make_alias(fltk-shared fltk::fltk-shared) _fltk_make_alias(fluid fltk::fluid) _fltk_make_alias(fluid-cmd fltk::fluid-cmd) _fltk_make_alias(fltk-options fltk::options) _fltk_make_alias(fltk-options-cmd fltk::options-cmd) foreach(target cairo forms gl images jpeg png z) _fltk_make_alias(fltk_${target} fltk::${target}) _fltk_make_alias(fltk_${target}-shared fltk::${target}-shared) endforeach() endif() # Create aliases ... # set FLTK_FLUID_EXECUTABLE: try to use the fltk::target name if it # exists and fall back to 'fluid-cmd' or 'fluid' if not. This will # eventually call the build host's fluid if found in the users's PATH if(TARGET fltk::fluid-cmd) # Windows only set(FLTK_FLUID_EXECUTABLE fltk::fluid-cmd) elseif(TARGET fltk::fluid) set(FLTK_FLUID_EXECUTABLE fltk::fluid) elseif(WIN32) set(FLTK_FLUID_EXECUTABLE fluid-cmd) else() set(FLTK_FLUID_EXECUTABLE fluid) endif() endif(CMAKE_CROSSCOMPILING) # Debug: should be commented out # message(STATUS "FLTKConfig.cmake: FLTK_FLUID_EXECUTABLE = '${FLTK_FLUID_EXECUTABLE}'") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/CMake/compatibility.cmake����������������������������������������������������������������0000644�0001750�0001750�00000005122�15004135251�017440� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # CMake compatibility functions and macros for the Fast Light Tool Kit (FLTK) # # Copyright 1998-2023 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ################################################################################ # # The functions and maybe macros in this file are defined to simplify CMake # code that uses features not available in all supported CMake versions. # Functions should be preferred (rather than macros) because functions # have their own variable scope. # # The function must apply a workaround for older versions or not add code # at all if there is no suitable workaround. # # The functions included here may be removed (with according changes of the # calling code) or the workaround code may be removed from the implementation # after cmake_minimum_required() has been raised to a version number greater # than or equal to the required version. # # Current cmake_minimum_required() version: see <fltk-root>/CMakeLists.txt # ################################################################################ # Right now we don't need compatibility functions # This file is currently "empty" but left for documentation purposes # An example function documentation follows... ################################################################################ # # function fl_target_link_directories - add link directories to target # # Requires CMake version: 3.13 # https://cmake.org/cmake/help/latest/command/target_link_directories.html # # Input: # # - TARGET: target to add link directories to, e.g. fluid # # - SCOPE: one of <INTERFACE|PUBLIC|PRIVATE> (see CMake docs) # # - DIRS: quoted list of link directories (separated by ';') # # The 'DIRS' argument takes a standard CMake list of directories, i.e. the # individual members must be separated by ';'. The list may be empty (""). # If more than one directory is to be added or if the list of directories # can be empty it *must* be quoted. This function may be called more than # once. Each invocation adds zero, one, or more directories. # # Example: # # fl_target_link_directories(fluid PRIVATE "${PKG_CAIRO_LIBRARY_DIRS}") # # In this example 'PKG_CAIRO_LIBRARY_DIRS' is platform dependent and # can be an empty list. # ################################################################################ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/CMake/export.cmake�����������������������������������������������������������������������0000644�0001750�0001750�00000012537�15004135251�016120� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # Export CMake file to build the FLTK project using CMake (www.cmake.org) # # Originally written by Michael Surette # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ####################################################################### # final config and export ####################################################################### # Set the fluid executable path used to create .cxx/.h from .fl files if(FLTK_BUILD_FLUID AND NOT CMAKE_CROSSCOMPILING) # Use the fluid executable we build using its namespaced target name if(WIN32) set(FLTK_FLUID_EXECUTABLE fltk::fluid-cmd) set(FLUID_EXPORT fluid fluid-cmd) # export fluid and fluid-cmd else() set(FLTK_FLUID_EXECUTABLE fltk::fluid) set(FLUID_EXPORT fluid) # export fluid endif() else() # We don't build fluid /or/ we are cross-compiling (or both): # we need to find a fluid executable on the build host. # The search is restricted to the user's PATH (environment). find_program(FLTK_FLUID_HOST NAMES fluid fluid.exe PATHS ENV PATH NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) if(NOT FLTK_FLUID_HOST) message(STATUS "Warning: fluid not found on the build system!") endif() # Note: this *may* assign "FLTK_FLUID_HOST-NOTFOUND" set(FLTK_FLUID_EXECUTABLE "${FLTK_FLUID_HOST}") set(FLUID_EXPORT "") # don't export fluid endif(FLTK_BUILD_FLUID AND NOT CMAKE_CROSSCOMPILING) if(0) # Debug message(STATUS "##############################################################") message(STATUS "[export.cmake] INFO: Did we find fluid?") fl_debug_var(FLTK_FLUID_HOST) fl_debug_var(FLTK_FLUID_EXECUTABLE) fl_debug_var(FLTK_BUILD_FLUID) fl_debug_var(CMAKE_CROSSCOMPILING) message(STATUS "##############################################################") endif() # set fltk-options export names (built or not, Windows) if(FLTK_BUILD_FLTK_OPTIONS) set(FLTK_OPTIONS_EXPORT fltk-options) if(WIN32) list(APPEND FLTK_OPTIONS_EXPORT fltk-options-cmd) endif() else() set(FLTK_OPTIONS_EXPORT) endif() # generate FLTK-Targets.cmake for build directory use set(export_targets ${FLTK_LIBRARIES} ${FLTK_LIBRARIES_SHARED} ${FLUID_EXPORT} ${FLTK_OPTIONS_EXPORT} ) export(TARGETS ${export_targets} FILE ${CMAKE_CURRENT_BINARY_DIR}/FLTK-Targets.cmake NAMESPACE fltk::) # generate FLTK-Functions.cmake for build directory use configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/CMake/FLTK-Functions.cmake ${CMAKE_CURRENT_BINARY_DIR}/FLTK-Functions.cmake COPYONLY ) # generate FLTKConfig.cmake for build directory use set(INCLUDE_DIRS "${FLTK_INCLUDE_DIRS}") if(FLTK_HAVE_CAIRO OR FLTK_USE_CAIRO) list(APPEND INCLUDE_DIRS ${PKG_CAIRO_INCLUDE_DIRS}) endif() list(REMOVE_DUPLICATES INCLUDE_DIRS) set(CONFIG_PATH ${CMAKE_CURRENT_BINARY_DIR}) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/CMake/FLTKConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FLTKConfig.cmake @ONLY ) # generate fltk-config for build directory use set(prefix ${CMAKE_CURRENT_BINARY_DIR}) set(exec_prefix "\${prefix}") set(includedir "${CMAKE_CURRENT_SOURCE_DIR}") set(BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") set(libdir "\${exec_prefix}/lib") set(srcdir ".") set(LIBNAME "${libdir}/libfltk.a") configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/fltk-config.in" "${CMAKE_CURRENT_BINARY_DIR}/fltk-config" @ONLY ) # Set execute permissions on fltk-config in the build directory. # Note: file(CHMOD) is available since CMake 3.19, # use fallback before CMake 3.19 if(CMAKE_VERSION VERSION_LESS 3.19) if(UNIX OR MSYS OR MINGW) execute_process(COMMAND chmod 755 fltk-config WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") endif() else(CMAKE_VERSION VERSION_LESS 3.19) file(CHMOD "${CMAKE_CURRENT_BINARY_DIR}/fltk-config" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif(CMAKE_VERSION VERSION_LESS 3.19) # prepare some variables for config.h if(IS_ABSOLUTE "${FLTK_DATADIR}") set(PREFIX_DATA "${FLTK_DATADIR}/fltk") else(IS_ABSOLUTE "${FLTK_DATADIR}") set(PREFIX_DATA "${CMAKE_INSTALL_PREFIX}/${FLTK_DATADIR}/fltk") endif(IS_ABSOLUTE "${FLTK_DATADIR}") if(IS_ABSOLUTE "${FLTK_DOCDIR}") set(PREFIX_DOC "${FLTK_DOCDIR}/fltk") else(IS_ABSOLUTE "${FLTK_DOCDIR}") set(PREFIX_DOC "${CMAKE_INSTALL_PREFIX}/${FLTK_DOCDIR}/fltk") endif(IS_ABSOLUTE "${FLTK_DOCDIR}") set(CONFIG_H_IN configh.cmake.in) set(CONFIG_H config.h) # generate config.h configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/${CONFIG_H_IN}" "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_H}" @ONLY ) if(FLTK_INSTALL_LINKS) # Set PREFIX_INCLUDE to the proper value. if(IS_ABSOLUTE ${FLTK_INCLUDEDIR}) set(PREFIX_INCLUDE ${FLTK_INCLUDEDIR}) else() set(PREFIX_INCLUDE "${CMAKE_INSTALL_PREFIX}/${FLTK_INCLUDEDIR}") endif(IS_ABSOLUTE ${FLTK_INCLUDEDIR}) configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/CMake/install-symlinks.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/install-symlinks.cmake" @ONLY) endif(FLTK_INSTALL_LINKS) �����������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/CMake/options.cmake����������������������������������������������������������������������0000644�0001750�0001750�00000111407�15004135251�016266� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # Main CMakeLists.txt to build the FLTK project using CMake (www.cmake.org) # Originally written by Michael Surette # # Copyright 1998-2025 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ####################################################################### # Important implementation note for FLTK developers ####################################################################### # # *FIXME* In the current version of FLTK's CMake build files we're # using 'include_directories()' to define directories that must be # used in compile commands (typically "-Idirectories"). # # include_directories() is a global command that affects *all* source # files in the current directory and all subdirectories. This can lead # to conflicts and should be replaced with target_include_directories() # which can be applied to particular targets and source files only. # # This could remove some of these potential build conflicts, for # instance # if the bundled image libs and Cairo or Pango are used # together (Pango depends on Cairo and Cairo depends on libpng). # However, this is not a proper solution! # # That said, order of "-I..." switches matters, and therefore the # bundled libraries (png, jpeg, zlib) *must* appear before any other # include_directories() statements that might introduce conflicts. # Currently 'resources.cmake' is included before this file and thus # 'include_directories(${FREETYPE_PATH})' is executed before this # file but this doesn't matter. # # This *MUST* be fixed using target_include_directories() as # appropriate but this would need a major rework. # # Albrecht-S April 6, 2022 # ####################################################################### set(DEBUG_OPTIONS_CMAKE 0) if(DEBUG_OPTIONS_CMAKE) message(STATUS "[** options.cmake **]") fl_debug_var(WIN32) fl_debug_var(FLTK_LDLIBS) endif(DEBUG_OPTIONS_CMAKE) ####################################################################### # options ####################################################################### set(FLTK_OPTION_OPTIM "" CACHE STRING "custom optimization flags" ) # *FIXME* add_definitions() add_definitions(${FLTK_OPTION_OPTIM}) ####################################################################### set(FLTK_ARCHFLAGS "" CACHE STRING "custom architecture flags" ) # *FIXME* add_definitions() add_definitions(${FLTK_ARCHFLAGS}) ####################################################################### set(FLTK_ABI_VERSION "" CACHE STRING "FLTK ABI Version FL_ABI_VERSION: 1xxyy for 1.x.y (xx,yy with leading zero)" ) set(FL_ABI_VERSION ${FLTK_ABI_VERSION}) ####################################################################### # Select MSVC (Visual Studio) Runtime: DLL (/MDx) or static (/MTx) # where x = 'd' for Debug builds, empty ('') for non-Debug builds. # Note: this might be handled better by the 'MSVC_RUNTIME_LIBRARY' # target property for each target rather than setting a global # CMake variable - but this version does the latter. # This also applies when using LLVM/clang on Windows (#1058). ####################################################################### if(WIN32 AND NOT MINGW AND NOT MSYS) option(FLTK_MSVC_RUNTIME_DLL "use MSVC Runtime-DLL (/MDx)" ON) if(FLTK_MSVC_RUNTIME_DLL) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL") else() set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") endif() else(WIN32 AND NOT MINGW AND NOT MSYS) # suppress CMake warning if the user sets FLTK_MSVC_RUNTIME_DLL on other platforms if(DEFINED FLTK_MSVC_RUNTIME_DLL) unset(FLTK_MSVC_RUNTIME_DLL) unset(FLTK_MSVC_RUNTIME_DLL CACHE) endif() endif(WIN32 AND NOT MINGW AND NOT MSYS) ####################################################################### if(APPLE) option(FLTK_BACKEND_X11 "use X11" OFF) if(CMAKE_OSX_SYSROOT) list(APPEND FLTK_CFLAGS "-isysroot ${CMAKE_OSX_SYSROOT}") endif(CMAKE_OSX_SYSROOT) elseif(UNIX) option(FLTK_BACKEND_X11 "use X11" ON) endif(APPLE) ####################################################################### # Bundled Library Options ####################################################################### if(WIN32 OR (APPLE AND NOT FLTK_BACKEND_X11)) option(FLTK_USE_SYSTEM_LIBJPEG "use system libjpeg" OFF) option(FLTK_USE_SYSTEM_LIBPNG "use system libpng" OFF) option(FLTK_USE_SYSTEM_ZLIB "use system zlib" OFF) else() option(FLTK_USE_SYSTEM_LIBJPEG "use system libjpeg" ON) option(FLTK_USE_SYSTEM_LIBPNG "use system libpng" ON) option(FLTK_USE_SYSTEM_ZLIB "use system zlib" ON) endif() # Set default values of internal build options set(FLTK_USE_BUNDLED_JPEG FALSE) set(FLTK_USE_BUNDLED_PNG FALSE) set(FLTK_USE_BUNDLED_ZLIB FALSE) # Collect libraries to build fltk_images (starting empty) set(FLTK_IMAGE_LIBRARIES "") ####################################################################### # Ensure that png and zlib are both system or both local for compatibility ####################################################################### if(FLTK_USE_SYSTEM_ZLIB) find_package(ZLIB) if(NOT ZLIB_FOUND) set(FLTK_USE_BUNDLED_ZLIB TRUE) endif() else() set(FLTK_USE_BUNDLED_ZLIB TRUE) endif() if(FLTK_USE_SYSTEM_LIBPNG AND NOT FLTK_USE_BUNDLED_ZLIB) find_package(PNG) if(NOT PNG_FOUND) set(FLTK_USE_BUNDLED_PNG TRUE) set(FLTK_USE_BUNDLED_ZLIB TRUE) endif() else() set(FLTK_USE_BUNDLED_PNG TRUE) set(FLTK_USE_BUNDLED_ZLIB TRUE) endif() # Issue warnings if we deviate from the user's choice if(FLTK_USE_SYSTEM_LIBPNG AND FLTK_USE_BUNDLED_PNG) message(STATUS "System PNG or ZLIB not usable, falling back to local PNG for compatibility.") endif() if(FLTK_USE_SYSTEM_ZLIB AND FLTK_USE_BUNDLED_ZLIB) message(STATUS "System PNG or ZLIB not usable, falling back to local ZLIB for compatibility.") endif() ####################################################################### # Bundled Compression Library : zlib ####################################################################### if(FLTK_USE_BUNDLED_ZLIB) add_subdirectory(zlib) set(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zlib) # FIXME - include_directories() include_directories(${ZLIB_INCLUDE_DIR}) endif() set(HAVE_LIBZ 1) ####################################################################### # Bundled Image Library : libpng ####################################################################### if(FLTK_USE_BUNDLED_PNG) add_subdirectory(png) set(FLTK_PNG_LIBRARIES fltk::png) list(APPEND FLTK_IMAGE_LIBRARIES fltk::png) # Definitions for 'config.h' - do we still need this? # See also png/CMakeLists.txt (target_compile_definitions). # Note: config.h is generated by either configure or CMake, # hence we should support it in 1.4.x (may be changed in 1.5.0) set(HAVE_PNG_H 1) set(HAVE_PNG_GET_VALID 1) set(HAVE_PNG_SET_TRNS_TO_ALPHA 1) # *FIXME* include_directories() include_directories(${FLTK_SOURCE_DIR}/png) else() # use system libpng and zlib set(FLTK_PNG_LIBRARIES ${PNG_LIBRARIES}) list(APPEND FLTK_IMAGE_LIBRARIES ${PNG_LIBRARIES}) # *FIXME* include_directories() include_directories(${PNG_INCLUDE_DIRS}) set(_INCLUDE_SAVED ${CMAKE_REQUIRED_INCLUDES}) list(APPEND CMAKE_REQUIRED_INCLUDES ${PNG_INCLUDE_DIRS}) # Note: we do not check for <libpng/png.h> explicitly. # This is assumed to exist if we have PNG_FOUND and don't find <png.h> # FIXME - Force search by unsetting the chache variable. Maybe use # FIXME - another cache variable to check for option changes? # unset(HAVE_PNG_H CACHE) # force search check_include_file(png.h HAVE_PNG_H) mark_as_advanced(HAVE_PNG_H) set(CMAKE_REQUIRED_INCLUDES ${_INCLUDE_SAVED}) unset(_INCLUDE_SAVED) endif() set(HAVE_LIBPNG 1) ####################################################################### # Bundled Image Library : libjpeg ####################################################################### if(FLTK_USE_SYSTEM_LIBJPEG) find_package(JPEG) if(NOT JPEG_FOUND) set(FLTK_USE_BUNDLED_JPEG TRUE) message(STATUS "cannot find system jpeg library - using built-in") endif() else() set(FLTK_USE_BUNDLED_JPEG TRUE) endif() if(FLTK_USE_BUNDLED_JPEG) add_subdirectory(jpeg) set(FLTK_JPEG_LIBRARIES fltk::jpeg) # list(APPEND FLTK_IMAGE_LIBRARIES fltk::jpeg) # *FIXME* include_directories include_directories(${FLTK_SOURCE_DIR}/jpeg) else() set(FLTK_JPEG_LIBRARIES ${JPEG_LIBRARIES}) list(APPEND FLTK_IMAGE_LIBRARIES ${JPEG_LIBRARIES}) endif() set(HAVE_LIBJPEG 1) ####################################################################### if(UNIX) option(FLTK_INSTALL_LINKS "create backwards compatibility links" OFF) list(APPEND FLTK_LDLIBS -lm) if(NOT APPLE) option(FLTK_BACKEND_WAYLAND "support the Wayland backend" ON) endif(NOT APPLE) if(FLTK_BACKEND_WAYLAND) pkg_check_modules(WLDCLIENT IMPORTED_TARGET wayland-client>=1.18) pkg_check_modules(WLDCURSOR IMPORTED_TARGET wayland-cursor) pkg_check_modules(WLDPROTO IMPORTED_TARGET wayland-protocols>=1.15) pkg_check_modules(XKBCOMMON IMPORTED_TARGET xkbcommon) if(NOT(WLDCLIENT_FOUND AND WLDCURSOR_FOUND AND WLDPROTO_FOUND AND XKBCOMMON_FOUND)) message(STATUS "Not all software modules 'wayland-client>=1.18 wayland-cursor wayland-protocols>=1.15 xkbcommon' are present") message(STATUS "Consequently, FLTK_BACKEND_WAYLAND is turned off.") unset(FLTK_BACKEND_WAYLAND CACHE) set(FLTK_BACKEND_WAYLAND 0) endif(NOT(WLDCLIENT_FOUND AND WLDCURSOR_FOUND AND WLDPROTO_FOUND AND XKBCOMMON_FOUND)) endif(FLTK_BACKEND_WAYLAND) if(FLTK_BACKEND_WAYLAND) set(FLTK_USE_WAYLAND 1) if(FLTK_BACKEND_X11) include(FindX11) endif() if(FLTK_BACKEND_X11 AND X11_FOUND) set(FLTK_USE_X11 1) # build a hybrid Wayland/X11 library else() set(FLTK_USE_X11 0) # build a Wayland-only library endif() unset(FLTK_GRAPHICS_CAIRO CACHE) set(FLTK_GRAPHICS_CAIRO TRUE CACHE BOOL "all drawing to X11 windows uses Cairo") option(FLTK_USE_SYSTEM_LIBDECOR "use libdecor from the system" ON) set(USE_SYSTEM_LIBDECOR 1) unset(FLTK_USE_XRENDER CACHE) unset(FLTK_USE_XINERAMA CACHE) unset(FLTK_USE_XFT CACHE) unset(FLTK_USE_XCURSOR CACHE) unset(FLTK_USE_XFIXES CACHE) if(X11_FOUND) if(NOT X11_Xfixes_FOUND) message(WARNING "Install development headers for libXfixes (e.g., libxfixes-dev)") endif() set(HAVE_XFIXES 1) if(NOT X11_Xrender_FOUND) message(WARNING "Install development headers for libXrender (e.g., libxrender-dev)") endif() set(HAVE_XRENDER 1) if(NOT X11_Xft_FOUND) message(WARNING "Install development headers for libXft (e.g., libxft-dev)") endif() set(USE_XFT 1) if(NOT X11_Xcursor_FOUND) message(WARNING "Install development headers for libXcursor (e.g., libxcursor-dev)") endif() set(HAVE_XCURSOR 1) if(NOT X11_Xinerama_FOUND) message(WARNING "Install development headers for libXinerama (e.g., libxinerama-dev)") endif() set(HAVE_XINERAMA 1) if(NOT (X11_Xfixes_FOUND AND X11_Xrender_FOUND AND X11_Xft_FOUND AND X11_Xcursor_FOUND AND X11_Xinerama_FOUND)) message(FATAL_ERROR "*** Terminating: one or more required software package(s) missing.") endif() endif(X11_FOUND) unset(FLTK_USE_PANGO CACHE) set(FLTK_USE_PANGO TRUE CACHE BOOL "use lib Pango") if(FLTK_USE_SYSTEM_LIBDECOR) pkg_check_modules(SYSTEM_LIBDECOR IMPORTED_TARGET libdecor-0>=0.2.0 QUIET) if(NOT SYSTEM_LIBDECOR_FOUND) message(STATUS "Warning: system libdecor doesn't satisfy version ≥ 0.2.0,") message(STATUS " using bundled libdecor library instead.") set(USE_SYSTEM_LIBDECOR 0) else() pkg_get_variable(LIBDECOR_LIBDIR libdecor-0 libdir) set(LIBDECOR_PLUGIN_DIR ${LIBDECOR_LIBDIR}/libdecor/plugins-1) if(EXISTS ${LIBDECOR_PLUGIN_DIR} AND IS_DIRECTORY ${LIBDECOR_PLUGIN_DIR}) set(LIBDECOR_PLUGIN_DIR "\"${LIBDECOR_PLUGIN_DIR}\"" ) else() set(USE_SYSTEM_LIBDECOR 0) endif() endif(NOT SYSTEM_LIBDECOR_FOUND) else() set(USE_SYSTEM_LIBDECOR 0) endif(FLTK_USE_SYSTEM_LIBDECOR) if(USE_SYSTEM_LIBDECOR) set(FLTK_USE_LIBDECOR_GTK ON) else() option(FLTK_USE_LIBDECOR_GTK "Allow to use libdecor's GTK plugin" ON) endif(USE_SYSTEM_LIBDECOR) if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "FreeBSD") check_include_file(linux/input.h LINUX_INPUT_H) if(NOT LINUX_INPUT_H) message(FATAL_ERROR "Required include file 'linux/input.h' is missing. Please install package 'evdev-proto'") endif(NOT LINUX_INPUT_H) endif(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "FreeBSD") endif(FLTK_BACKEND_WAYLAND) endif(UNIX) if(WIN32) option(FLTK_GRAPHICS_GDIPLUS "use GDI+ when possible for antialiased graphics" ON) if(FLTK_GRAPHICS_GDIPLUS) set(USE_GDIPLUS TRUE) if(NOT MSVC) list(APPEND FLTK_LDLIBS "-lgdiplus") endif(NOT MSVC) endif(FLTK_GRAPHICS_GDIPLUS) endif(WIN32) ####################################################################### option(FLTK_OPTION_STD "allow FLTK to use some std:: features" OFF) if(FLTK_OPTION_STD) set(FLTK_USE_STD 1) else() set(FLTK_USE_STD 0) endif() ####################################################################### # find X11 libraries and headers set(PATH_TO_XLIBS) if((NOT APPLE OR FLTK_BACKEND_X11) AND NOT WIN32 AND NOT FLTK_BACKEND_WAYLAND) include(FindX11) if(X11_FOUND) set(FLTK_USE_X11 1) list(APPEND FLTK_LDLIBS -lX11) if(X11_Xext_FOUND) list(APPEND FLTK_LDLIBS -lXext) endif(X11_Xext_FOUND) get_filename_component(PATH_TO_XLIBS ${X11_X11_LIB} PATH) endif(X11_FOUND) endif() if(APPLE AND FLTK_BACKEND_X11) if(NOT(${CMAKE_SYSTEM_VERSION} VERSION_LESS 17.0.0)) # a.k.a. macOS version ≥ 10.13 list(APPEND FLTK_CFLAGS "-D_LIBCPP_HAS_THREAD_API_PTHREAD") endif(NOT(${CMAKE_SYSTEM_VERSION} VERSION_LESS 17.0.0)) # FIXME: include_directories(!) # FIXME: how can we implement "AFTER SYSTEM" ? include_directories(AFTER SYSTEM /opt/X11/include/freetype2) include_directories(AFTER SYSTEM /opt/X11/include) # for Xft.h if(PATH_TO_XLIBS) set(LDFLAGS "-L${PATH_TO_XLIBS} ${LDFLAGS}") endif(PATH_TO_XLIBS) if(X11_INCLUDE_DIR) set(TEMP_INCLUDE_DIR ${X11_INCLUDE_DIR}) list(TRANSFORM TEMP_INCLUDE_DIR PREPEND "-I") list(APPEND FLTK_CFLAGS "${TEMP_INCLUDE_DIR}") endif(X11_INCLUDE_DIR) endif(APPLE AND FLTK_BACKEND_X11) ####################################################################### option(FLTK_USE_POLL "use poll if available" OFF) mark_as_advanced(FLTK_USE_POLL) if(FLTK_USE_POLL) check_symbol_exists(poll "poll.h" USE_POLL) endif(FLTK_USE_POLL) ####################################################################### option(FLTK_BUILD_SHARED_LIBS "Build shared libraries in addition to static libraries" OFF ) ####################################################################### option(FLTK_OPTION_PRINT_SUPPORT "allow print support" ON) option(FLTK_OPTION_FILESYSTEM_SUPPORT "allow file system support" ON) option(FLTK_BUILD_FORMS "Build forms compatibility library" ON) option(FLTK_BUILD_FLUID "Build FLUID" ON) option(FLTK_BUILD_FLTK_OPTIONS "Build fltk-options" ON) option(FLTK_BUILD_EXAMPLES "Build example programs" OFF) if(FLTK_IS_TOPLEVEL) option(FLTK_BUILD_TEST "Build test/demo programs" ON) else() option(FLTK_BUILD_TEST "Build test/demo programs" OFF) endif() if(FLTK_BUILD_FORMS) set(FLTK_HAVE_FORMS 1) else() set(FLTK_HAVE_FORMS 0) endif() ####################################################################### if(DOXYGEN_FOUND) option(FLTK_BUILD_HTML_DOCS "build html docs" ON) option(FLTK_INSTALL_HTML_DOCS "install html docs" OFF) option(FLTK_BUILD_FLUID_DOCS "build FLUID docs" OFF) option(FLTK_INSTALL_FLUID_DOCS "install FLUID docs" OFF) option(FLTK_INCLUDE_DRIVER_DOCS "include driver (developer) docs" OFF) mark_as_advanced(FLTK_INCLUDE_DRIVER_DOCS) if(LATEX_FOUND) option(FLTK_BUILD_PDF_DOCS "build pdf docs" ON) option(FLTK_INSTALL_PDF_DOCS "install pdf docs" OFF) endif(LATEX_FOUND) endif(DOXYGEN_FOUND) if(FLTK_BUILD_HTML_DOCS OR FLTK_BUILD_PDF_DOCS) add_subdirectory(documentation) endif(FLTK_BUILD_HTML_DOCS OR FLTK_BUILD_PDF_DOCS) if(FLTK_BUILD_FLUID_DOCS) add_subdirectory(fluid/documentation) endif(FLTK_BUILD_FLUID_DOCS) ####################################################################### # Include optional Cairo support ####################################################################### option(FLTK_OPTION_CAIRO_WINDOW "add support for Fl_Cairo_Window" OFF) option(FLTK_OPTION_CAIRO_EXT "use FLTK code instrumentation for Cairo extended use" OFF ) set(FLTK_HAVE_CAIRO 0) set(FLTK_HAVE_CAIROEXT 0) if(FLTK_OPTION_CAIRO_WINDOW OR FLTK_OPTION_CAIRO_EXT) # On Windows we don't use pkg-config *if* FLTK_CAIRO_DIR is set # to prevent that CMake finds the system lib(s). if(WIN32 AND FLTK_CAIRO_DIR) set(PKG_CAIRO_FOUND FALSE) else() pkg_search_module(PKG_CAIRO cairo) endif() if(PKG_CAIRO_FOUND) set(FLTK_HAVE_CAIRO 1) if(FLTK_OPTION_CAIRO_EXT) set(FLTK_HAVE_CAIROEXT 1) endif(FLTK_OPTION_CAIRO_EXT) list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${PKG_CAIRO_INCLUDE_DIRS}) # Cairo libs and flags for fltk-config # Hint: use either PKG_CAIRO_* or PKG_CAIRO_STATIC_* variables to # create the list of libraries used to link programs with Cairo # by running fltk-config --use-cairo --compile ... # Currently we're using the non-STATIC variables to link Cairo shared. set(CAIROLIBS) foreach(lib ${PKG_CAIRO_LIBRARIES}) list(APPEND CAIROLIBS "-l${lib}") endforeach() string(REPLACE ";" " " CAIROLIBS "${CAIROLIBS}") string(REPLACE ";" " " CAIROFLAGS "${PKG_CAIRO_CFLAGS}") else(PKG_CAIRO_FOUND) if(NOT WIN32) message(STATUS "*** Cairo was requested but not found - please check your Cairo installation") message(STATUS "*** or disable options FLTK_OPTION_CAIRO_WINDOW and FLTK_OPTION_CAIRO_EXT.") message(FATAL_ERROR "*** Terminating: missing Cairo libs or headers.") endif() # Tweak Cairo includes / libs / paths for Windows (TEMPORARY solution). # Todo: find a better way to set the required variables and flags! # The current version was tested with 32-bit (MinGW) and 64-bit (Visual # Studio and MSYS2). The latter can also be used with the Cairo library # provided by MSYS2, but then the build depends on the MSYS2 installation. # AlbrechtS (05/2024) message(STATUS "--- Cairo not found: trying to find Cairo for Windows ...") if(CMAKE_SIZEOF_VOID_P STREQUAL "8") set(_cairo_suffix x64) else() set(_cairo_suffix x86) endif() find_library(FLTK_CAIRO_LIB cairo PATHS ${FLTK_CAIRO_DIR} PATH_SUFFIXES lib lib/${_cairo_suffix} NO_DEFAULT_PATH ) if(NOT FLTK_CAIRO_DIR AND NOT FLTK_CAIRO_LIB) message(STATUS "--- Please set FLTK_CAIRO_DIR to point to the Cairo installation folder ...") message(STATUS " ... with files 'include/cairo.h' and 'lib/${_cairo_suffix}/cairo.lib'") message(STATUS "--- Example: cmake -DFLTK_CAIRO_DIR=\"C:/cairo-windows\" ...") message(STATUS "--- Note: this may be changed in the future.") message(FATAL_ERROR "*** Terminating: missing Cairo libs or headers.") endif() set(CAIROLIBS "-lcairo") # should be correct: needs cairo.lib # Simulate results of 'pkg_search_module (PKG_CAIRO cairo)' and more (above). # These variables will be used later set(PKG_CAIRO_LIBRARIES "cairo") set(PKG_CAIRO_INCLUDE_DIRS "${FLTK_CAIRO_DIR}/include") set(PKG_CAIRO_LIBRARY_DIRS "${FLTK_CAIRO_DIR}/lib/${_cairo_suffix}/") # FIXME - include_directories() include_directories(${PKG_CAIRO_INCLUDE_DIRS}) set(FLTK_HAVE_CAIRO 1) if(FLTK_OPTION_CAIRO_EXT) set(FLTK_HAVE_CAIROEXT 1) endif(FLTK_OPTION_CAIRO_EXT) endif(PKG_CAIRO_FOUND) if(0) # 1 = DEBUG, 0 = no output message(STATUS "--- options.cmake: Cairo related variables ---") if(WIN32) fl_debug_var(FLTK_CAIRO_DIR) fl_debug_var(_cairo_suffix) endif() fl_debug_pkg(PKG_CAIRO cairo) message(STATUS "--- fltk-config/Cairo variables ---") fl_debug_var(FLTK_LDLIBS) fl_debug_var(CAIROFLAGS) fl_debug_var(CAIROLIBS) message(STATUS "--- End of Cairo related variables ---") endif() # 1 = DEBUG, ... unset(_cairo_suffix) endif(FLTK_OPTION_CAIRO_WINDOW OR FLTK_OPTION_CAIRO_EXT) ####################################################################### option(FLTK_OPTION_SVG "read/write SVG image files" ON) if(FLTK_OPTION_SVG) set(FLTK_USE_SVG 1) else() set(FLTK_USE_SVG 0) endif(FLTK_OPTION_SVG) ####################################################################### # FIXME: GLU libs have already been searched in resources.cmake set(HAVE_GL LIB_GL OR LIB_MesaGL) set(FLTK_USE_GL FALSE) if(HAVE_GL) option(FLTK_BUILD_GL "use OpenGL and build fltk_gl library" ON) if(FLTK_BUILD_GL) set(FLTK_USE_GL TRUE) endif() endif() if(FLTK_BUILD_GL) if(FLTK_BACKEND_WAYLAND) pkg_check_modules(WLD_EGL IMPORTED_TARGET wayland-egl) pkg_check_modules(PKG_EGL IMPORTED_TARGET egl) pkg_check_modules(PKG_GL IMPORTED_TARGET gl) pkg_check_modules(PKG_GLU IMPORTED_TARGET glu) if(NOT (WLD_EGL_FOUND AND PKG_EGL_FOUND AND PKG_GL_FOUND AND PKG_GLU_FOUND)) message(STATUS "Modules 'wayland-egl, egl, gl, and glu' are required to build for the Wayland backend.") message(FATAL_ERROR "*** Aborting ***") endif() endif(FLTK_BACKEND_WAYLAND) if(FLTK_BACKEND_X11) set(OPENGL_FOUND TRUE) find_library(OPENGL_LIB GL) get_filename_component(PATH_TO_GLLIB ${OPENGL_LIB} DIRECTORY) find_library(GLU_LIB GLU) get_filename_component(PATH_TO_GLULIB ${GLU_LIB} DIRECTORY) # FIXME: we should find a better way to resolve this issue: # with GL, must use XQuartz libX11 else "Insufficient GL support" set(OPENGL_LIBRARIES -L${PATH_TO_GLULIB} -L${PATH_TO_GLLIB} -lX11 -lGLU -lGL) find_path(OPENGL_INCLUDE_DIR NAMES GL/gl.h OpenGL/gl.h HINTS ${X11_INCLUDE_DIR}) unset(HAVE_GL_GLU_H CACHE) find_file(HAVE_GL_GLU_H GL/glu.h PATHS ${X11_INCLUDE_DIR}) else() find_package(OpenGL) if(APPLE) set(HAVE_GL_GLU_H ${HAVE_OPENGL_GLU_H}) endif(APPLE) endif(FLTK_BACKEND_X11) else(FLTK_BUILD_GL) set(OPENGL_FOUND FALSE) set(HAVE_GL FALSE) set(HAVE_GL_GLU_H FALSE) set(HAVE_GLXGETPROCADDRESSARB FALSE) endif(FLTK_BUILD_GL) mark_as_advanced(OPENGL_LIB) # internal cache variable, not relevant for users # FIXME: the following is necessary because this variable may have been removed # from the cache above. It has been marked "advanced" before in resources.cmake. mark_as_advanced(HAVE_GL_GLU_H) # Note: GLLIBS is a CMake 'list' and is used exclusively to generate fltk-config ! # FIXME, this should be improved! # We should probably deduct this from OPENGL_LIBRARIES but it turned # out to be difficult since FindOpenGL seems to return different # syntax depending on the platform (and maybe also CMake version). # Hence we use the following code... set(GLLIBS) set(FLTK_GL_FOUND FALSE) if(OPENGL_FOUND) set(FLTK_GL_FOUND TRUE) find_path(FLTK_OPENGL_GLU_INCLUDE_DIR NAMES GL/glu.h OpenGL/glu.h HINTS ${OPENGL_INCLUDE_DIR} ${X11_INCLUDE_DIR}) set(CMAKE_REQUIRED_INCLUDES ${OPENGL_INCLUDE_DIR}/GL ${FLTK_OPENGL_GLU_INCLUDE_DIR}) if(WIN32) list(APPEND GLLIBS -lglu32 -lopengl32) elseif(APPLE AND NOT FLTK_BACKEND_X11) list(APPEND GLLIBS "-framework OpenGL") elseif(FLTK_BACKEND_WAYLAND) foreach(_lib WLD_EGL PKG_EGL PKG_GLU PKG_GL) list(APPEND GLLIBS ${${_lib}_LDFLAGS}) endforeach(_lib ) else() list(APPEND GLLIBS -lGLU -lGL) endif(WIN32) # check if function glXGetProcAddressARB exists set(TEMP_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) set(CMAKE_REQUIRED_LIBRARIES ${OPENGL_LIBRARIES}) check_symbol_exists(glXGetProcAddressARB "glx.h" HAVE_GLXGETPROCADDRESSARB) set(CMAKE_REQUIRED_LIBRARIES ${TEMP_REQUIRED_LIBRARIES}) unset(TEMP_REQUIRED_LIBRARIES) endif(OPENGL_FOUND) ####################################################################### option(FLTK_OPTION_LARGE_FILE "enable large file support" ON) if(FLTK_OPTION_LARGE_FILE) if(NOT MSVC) add_definitions(-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64) list(APPEND FLTK_CFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64) endif(NOT MSVC) endif(FLTK_OPTION_LARGE_FILE) ####################################################################### # Create an option whether we want to check for pthreads. # We must not do it on Windows unless we run under Cygwin, since we # always use native threads on Windows (even if libpthread is available). # Note: HAVE_PTHREAD_H has already been determined in resources.cmake # before this file is included (or set to 0 for WIN32). if(WIN32 AND NOT CYGWIN) # set(HAVE_PTHREAD_H 0) # (see resources.cmake) set(FLTK_USE_PTHREADS FALSE) else() option(FLTK_USE_PTHREADS "use multi-threading with pthreads" ON) endif(WIN32 AND NOT CYGWIN) # initialize more variables set(USE_THREADS 0) set(HAVE_PTHREAD 0) set(FLTK_PTHREADS_FOUND FALSE) if(FLTK_USE_PTHREADS) include(FindThreads) if(Threads_FOUND) add_definitions("-D_THREAD_SAFE -D_REENTRANT") set(USE_THREADS 1) set(FLTK_THREADS_FOUND TRUE) endif(Threads_FOUND) if(CMAKE_USE_PTHREADS_INIT AND NOT WIN32) set(HAVE_PTHREAD 1) if(NOT APPLE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread") endif(NOT APPLE) list(APPEND FLTK_LDLIBS -lpthread) list(APPEND FLTK_CFLAGS -D_THREAD_SAFE -D_REENTRANT) set(FLTK_PTHREADS_FOUND TRUE) else() set(HAVE_PTHREAD 0) set(HAVE_PTHREAD_H 0) set(FLTK_PTHREADS_FOUND FALSE) endif(CMAKE_USE_PTHREADS_INIT AND NOT WIN32) else(FLTK_USE_PTHREADS) set(HAVE_PTHREAD_H 0) endif(FLTK_USE_PTHREADS) set(debug_threads 0) # set to 1 to show debug info if(debug_threads) message("") message(STATUS "options.cmake: set debug_threads to 0 to disable the following info:") fl_debug_var(FLTK_USE_PTHREADS) fl_debug_var(HAVE_PTHREAD) fl_debug_var(HAVE_PTHREAD_H) fl_debug_var(FLTK_THREADS_FOUND) fl_debug_var(CMAKE_EXE_LINKER_FLAGS) message(STATUS "options.cmake: end of debug_threads info.") endif(debug_threads) unset(debug_threads) ####################################################################### if(X11_Xinerama_FOUND) option(FLTK_USE_XINERAMA "use lib Xinerama" ON) endif(X11_Xinerama_FOUND) if(FLTK_USE_XINERAMA) set(HAVE_XINERAMA ${X11_Xinerama_FOUND}) list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${X11_Xinerama_INCLUDE_PATH}) list(APPEND FLTK_LDLIBS -lXinerama) set(FLTK_XINERAMA_FOUND TRUE) else() set(FLTK_XINERAMA_FOUND FALSE) endif(FLTK_USE_XINERAMA) ####################################################################### if(X11_Xfixes_FOUND) option(FLTK_USE_XFIXES "use lib Xfixes" ON) endif(X11_Xfixes_FOUND) if(FLTK_USE_XFIXES) set(HAVE_XFIXES ${X11_Xfixes_FOUND}) list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${X11_Xfixes_INCLUDE_PATH}) list(APPEND FLTK_LDLIBS -lXfixes) set(FLTK_XFIXES_FOUND TRUE) else() set(FLTK_XFIXES_FOUND FALSE) endif(FLTK_USE_XFIXES) ####################################################################### if(X11_Xcursor_FOUND) option(FLTK_USE_XCURSOR "use lib Xcursor" ON) endif(X11_Xcursor_FOUND) if(FLTK_USE_XCURSOR) set(HAVE_XCURSOR ${X11_Xcursor_FOUND}) list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${X11_Xcursor_INCLUDE_PATH}) list(APPEND FLTK_LDLIBS -lXcursor) set(FLTK_XCURSOR_FOUND TRUE) else() set(FLTK_XCURSOR_FOUND FALSE) endif(FLTK_USE_XCURSOR) ####################################################################### if(X11_Xft_FOUND) option(FLTK_USE_XFT "use lib Xft" ON) option(FLTK_USE_PANGO "use lib Pango" OFF) if(NOT FLTK_BACKEND_WAYLAND) option(FLTK_GRAPHICS_CAIRO "all drawing to X11 windows uses Cairo" OFF) endif(NOT FLTK_BACKEND_WAYLAND) endif(X11_Xft_FOUND) # test option compatibility: Cairo for Xlib requires Pango if(FLTK_GRAPHICS_CAIRO) unset(FLTK_USE_PANGO CACHE) set(FLTK_USE_PANGO TRUE CACHE BOOL "use lib Pango") endif(FLTK_GRAPHICS_CAIRO) if(FLTK_USE_X11 AND (FLTK_USE_PANGO OR FLTK_GRAPHICS_CAIRO)) # implies to use PANGOXFT set(USE_PANGOXFT true) endif() # test option compatibility: Pango requires Xft if(USE_PANGOXFT) if(NOT X11_Xft_FOUND) message(STATUS "Pango requires Xft but Xft library or headers could not be found.") message(STATUS "Please install Xft development files and try again or disable FLTK_USE_PANGO.") message(FATAL_ERROR "*** Aborting ***") else() if(NOT FLTK_USE_XFT) message(STATUS "Pango requires Xft but usage of Xft was disabled.") message(STATUS "Please enable FLTK_USE_XFT and try again or disable FLTK_USE_PANGO.") message(FATAL_ERROR "*** Aborting ***") endif(NOT FLTK_USE_XFT) endif(NOT X11_Xft_FOUND) endif(USE_PANGOXFT) ####################################################################### if((X11_Xft_FOUND OR NOT USE_PANGOXFT) AND FLTK_USE_PANGO) pkg_check_modules(CAIRO IMPORTED_TARGET cairo) if(USE_PANGOXFT) pkg_check_modules(PANGOXFT IMPORTED_TARGET pangoxft) endif(USE_PANGOXFT) pkg_check_modules(PANGOCAIRO IMPORTED_TARGET pangocairo) if((PANGOXFT_FOUND OR NOT USE_PANGOXFT) AND PANGOCAIRO_FOUND AND CAIRO_FOUND) if(USE_PANGOXFT) list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${PANGOXFT_INCLUDE_DIRS}) else() list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${PANGOCAIRO_INCLUDE_DIRS}) endif(USE_PANGOXFT) list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${CAIRO_INCLUDE_DIRS}) find_library(HAVE_LIB_PANGO pango-1.0 ${CMAKE_LIBRARY_PATH}) mark_as_advanced(HAVE_LIB_PANGO) if(USE_PANGOXFT) find_library(HAVE_LIB_PANGOXFT pangoxft-1.0 ${CMAKE_LIBRARY_PATH}) mark_as_advanced(HAVE_LIB_PANGOXFT) endif(USE_PANGOXFT) find_library(HAVE_LIB_PANGOCAIRO pangocairo-1.0 ${CMAKE_LIBRARY_PATH}) mark_as_advanced(HAVE_LIB_PANGOCAIRO) find_library(HAVE_LIB_CAIRO cairo ${CMAKE_LIBRARY_PATH}) mark_as_advanced(HAVE_LIB_CAIRO) find_library(HAVE_LIB_GOBJECT gobject-2.0 ${CMAKE_LIBRARY_PATH}) mark_as_advanced(HAVE_LIB_GOBJECT) set(USE_PANGO TRUE) # add required libraries to fltk-config ... if(USE_PANGOXFT) list(APPEND FLTK_LDLIBS ${PANGOXFT_LDFLAGS}) endif(USE_PANGOXFT) list(APPEND FLTK_LDLIBS ${PANGOCAIRO_LDFLAGS}) # *FIXME* Libraries should not be added explicitly if possible if(FLTK_BACKEND_WAYLAND AND FLTK_USE_LIBDECOR_GTK AND NOT USE_SYSTEM_LIBDECOR) list(APPEND FLTK_LDLIBS -lgtk-3 -lgdk-3 -lgio-2.0) endif() if(FLTK_BACKEND_X11) list(APPEND FLTK_LDLIBS -lX11) endif() if(APPLE) get_filename_component(PANGO_L_PATH ${HAVE_LIB_PANGO} PATH) set(LDFLAGS "${LDFLAGS} -L${PANGO_L_PATH}") endif(APPLE) else() # this covers Debian, Ubuntu, FreeBSD, NetBSD, Darwin if(APPLE AND FLTK_BACKEND_X11) find_file(FINK_PREFIX NAMES /opt/sw /sw) if(FINK_PREFIX) list(APPEND CMAKE_INCLUDE_PATH ${FINK_PREFIX}/include) list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${FINK_PREFIX}/include/cairo) list(APPEND CMAKE_LIBRARY_PATH ${FINK_PREFIX}/lib) endif(FINK_PREFIX) endif(APPLE AND FLTK_BACKEND_X11) find_file(HAVE_PANGO_H pango-1.0/pango/pango.h ${CMAKE_INCLUDE_PATH}) find_file(HAVE_PANGOXFT_H pango-1.0/pango/pangoxft.h ${CMAKE_INCLUDE_PATH}) if(HAVE_PANGO_H AND HAVE_PANGOXFT_H) find_library(HAVE_LIB_PANGO pango-1.0 ${CMAKE_LIBRARY_PATH}) find_library(HAVE_LIB_PANGOXFT pangoxft-1.0 ${CMAKE_LIBRARY_PATH}) if(APPLE) set(HAVE_LIB_GOBJECT TRUE) else() find_library(HAVE_LIB_GOBJECT gobject-2.0 ${CMAKE_LIBRARY_PATH}) endif(APPLE) endif(HAVE_PANGO_H AND HAVE_PANGOXFT_H) if(HAVE_LIB_PANGO AND HAVE_LIB_PANGOXFT AND HAVE_LIB_GOBJECT) set(USE_PANGO TRUE) # remove last 3 components of HAVE_PANGO_H and put in PANGO_H_PREFIX get_filename_component(PANGO_H_PREFIX ${HAVE_PANGO_H} PATH) get_filename_component(PANGO_H_PREFIX ${PANGO_H_PREFIX} PATH) get_filename_component(PANGO_H_PREFIX ${PANGO_H_PREFIX} PATH) get_filename_component(PANGOLIB_DIR ${HAVE_LIB_PANGO} PATH) # glib.h is usually in ${PANGO_H_PREFIX}/glib-2.0/ ... find_path(GLIB_H_PATH glib.h PATHS ${PANGO_H_PREFIX}/glib-2.0 ${PANGO_H_PREFIX}/glib/glib-2.0) list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${PANGO_H_PREFIX}/pango-1.0 ${GLIB_H_PATH} ${PANGOLIB_DIR}/glib-2.0/include) # *FIXME* Libraries should not be added explicitly if possible list(APPEND FLTK_LDLIBS -lpango-1.0 -lpangoxft-1.0 -lgobject-2.0) endif(HAVE_LIB_PANGO AND HAVE_LIB_PANGOXFT AND HAVE_LIB_GOBJECT) endif((PANGOXFT_FOUND OR NOT USE_PANGOXFT) AND PANGOCAIRO_FOUND AND CAIRO_FOUND) if(USE_PANGO AND (FLTK_GRAPHICS_CAIRO OR FLTK_BACKEND_WAYLAND)) set(FLTK_USE_CAIRO 1) # fl_debug_var(FLTK_USE_CAIRO) endif() endif((X11_Xft_FOUND OR NOT USE_PANGOXFT) AND FLTK_USE_PANGO) if(FLTK_BACKEND_WAYLAND) # Note: Disable FLTK_USE_LIBDECOR_GTK to get cairo titlebars rather than GTK if(FLTK_USE_LIBDECOR_GTK AND NOT USE_SYSTEM_LIBDECOR) pkg_check_modules(GTK IMPORTED_TARGET gtk+-3.0) if(GTK_FOUND) list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${GTK_INCLUDE_DIRS}) else() message(WARNING "Installation of the development files for the GTK library " "(e.g., libgtk-3-dev) is recommended when using the gnome desktop.") endif(GTK_FOUND) endif(FLTK_USE_LIBDECOR_GTK AND NOT USE_SYSTEM_LIBDECOR) endif() if(FLTK_USE_XFT) set(USE_XFT X11_Xft_FOUND) list(APPEND FLTK_LDLIBS -lXft) set(FLTK_XFT_FOUND TRUE) if(APPLE AND FLTK_BACKEND_X11) find_library(LIB_fontconfig fontconfig "/opt/X11/lib") endif() else() set(FLTK_XFT_FOUND FALSE) endif(FLTK_USE_XFT) ####################################################################### if(X11_Xrender_FOUND) option(FLTK_USE_XRENDER "use lib Xrender" ON) endif(X11_Xrender_FOUND) if(FLTK_USE_XRENDER) set(HAVE_XRENDER ${X11_Xrender_FOUND}) if(HAVE_XRENDER) list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${X11_Xrender_INCLUDE_PATH}) list(APPEND FLTK_LDLIBS -lXrender) set(FLTK_XRENDER_FOUND TRUE) else(HAVE_XRENDER) set(FLTK_XRENDER_FOUND FALSE) endif(HAVE_XRENDER) else(FLTK_USE_XRENDER) set(FLTK_XRENDER_FOUND FALSE) endif(FLTK_USE_XRENDER) ####################################################################### set(FL_NO_PRINT_SUPPORT FALSE) if(X11_FOUND AND NOT FLTK_OPTION_PRINT_SUPPORT) set(FL_NO_PRINT_SUPPORT TRUE) endif(X11_FOUND AND NOT FLTK_OPTION_PRINT_SUPPORT) ####################################################################### ####################################################################### set(FL_CFG_NO_FILESYSTEM_SUPPORT TRUE) if(FLTK_OPTION_FILESYSTEM_SUPPORT) set(FL_CFG_NO_FILESYSTEM_SUPPORT FALSE) endif(FLTK_OPTION_FILESYSTEM_SUPPORT) ####################################################################### ####################################################################### option(CMAKE_SUPPRESS_REGENERATION "suppress rules to re-run CMake on rebuild" OFF) mark_as_advanced(CMAKE_SUPPRESS_REGENERATION) ####################################################################### # Clean up ... # *** FIXME *** Do we need all these variables ? list(REMOVE_DUPLICATES FLTK_BUILD_INCLUDE_DIRECTORIES) list(REMOVE_DUPLICATES FLTK_IMAGE_INCLUDE_DIRECTORIES) list(REMOVE_DUPLICATES FLTK_IMAGE_LIBRARIES) ####################################################################### # Debugging ... if(DEBUG_OPTIONS_CMAKE) message(STATUS "") # empty line fl_debug_var(WIN32) fl_debug_var(LIBS) fl_debug_var(GLLIBS) fl_debug_var(FLTK_LDLIBS) fl_debug_var(OPENGL_FOUND) fl_debug_var(OPENGL_INCLUDE_DIR) fl_debug_var(OPENGL_LIBRARIES) fl_debug_var(CMAKE_MSVC_RUNTIME_LIBRARY) message("--- bundled libraries ---") fl_debug_var(FLTK_USE_SYSTEM_LIBJPEG) fl_debug_var(FLTK_USE_SYSTEM_LIBPNG) fl_debug_var(FLTK_USE_SYSTEM_ZLIB) fl_debug_var(FLTK_USE_BUNDLED_JPEG) fl_debug_var(FLTK_USE_BUNDLED_PNG) fl_debug_var(FLTK_USE_BUNDLED_ZLIB) message(STATUS "--- *FIXME* include directories ---") fl_debug_var(FLTK_BUILD_INCLUDE_DIRECTORIES) fl_debug_var(FLTK_IMAGE_INCLUDE_DIRECTORIES) message("--- X11 ---") fl_debug_var(X11_FOUND) fl_debug_var(X11_INCLUDE_DIR) fl_debug_var(X11_LIBRARIES) fl_debug_var(X11_X11_LIB) fl_debug_var(X11_X11_INCLUDE_PATH) fl_debug_var(X11_Xft_INCLUDE_PATH) fl_debug_var(X11_Xft_LIB) fl_debug_var(X11_Xft_FOUND) fl_debug_var(PATH_TO_XLIBS) message(STATUS "[** end of options.cmake **]") endif(DEBUG_OPTIONS_CMAKE) unset(DEBUG_OPTIONS_CMAKE) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/CMake/install-symlinks.cmake.in����������������������������������������������������������0000644�0001750�0001750�00000002201�15004135251�020504� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # Installation script to create symlinks for the FLTK project using CMake # # Copyright 1998-2021 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # On UNIX create backward compatibility symlinks if(NOT EXISTS $ENV{DESTDIR}@PREFIX_INCLUDE@/Fl) EXECUTE_PROCESS( COMMAND ln -s FL Fl WORKING_DIRECTORY $ENV{DESTDIR}@PREFIX_INCLUDE@ ) endif(NOT EXISTS $ENV{DESTDIR}@PREFIX_INCLUDE@/Fl) file(GLOB FLTK_HEADER_FILES $ENV{DESTDIR}@PREFIX_INCLUDE@/FL/*.H) foreach(file ${FLTK_HEADER_FILES}) GET_FILENAME_COMPONENT(nameWE ${file} NAME_WE) if(NOT EXISTS $ENV{DESTDIR}@PREFIX_INCLUDE@/FL/${nameWE}.h) EXECUTE_PROCESS( COMMAND ln -s ${nameWE}.H ${nameWE}.h WORKING_DIRECTORY $ENV{DESTDIR}@PREFIX_INCLUDE@/FL ) endif(NOT EXISTS $ENV{DESTDIR}@PREFIX_INCLUDE@/FL/${nameWE}.h) endforeach(file) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/CMake/resources.cmake��������������������������������������������������������������������0000644�0001750�0001750�00000026150�15004135251�016605� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # Resource definitions to build the FLTK project using CMake (www.cmake.org) # Originally written by Michael Surette # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ####################################################################### # check for headers, libraries and functions ####################################################################### # If CMAKE_REQUIRED_QUIET is 1 (default) the search is mostly quiet, # if it is 0 (or not defined) check_include_files() is more verbose # and the result of the search is logged with fl_debug_var(). # This is useful for debugging. set(CMAKE_REQUIRED_QUIET 1) include(CheckIncludeFiles) include(CheckSymbolExists) macro(fl_find_header VAR HEADER) check_include_files("${HEADER}" ${VAR}) if(NOT CMAKE_REQUIRED_QUIET) fl_debug_var(${VAR}) endif(NOT CMAKE_REQUIRED_QUIET) endmacro(fl_find_header) ####################################################################### # find git revision and store it in the CMake cache for reference ####################################################################### # (1) Get current Git revision from `git rev-parse ...` # (2) Read Git revision from file `fltk_git_rev.dat` # # (1) This can fail if the FLTK source directory is not a Git checkout, # i.e. FLTK was downloaded as a distro (tarball). # (2) If (1) fails the file `fltk_git_rev.dat` is read. This file is # generated by the process to generate the distribution (makesrcdist). # set(git_rev_file ${FLTK_SOURCE_DIR}/fltk_git_rev.dat) set(git_revision "") # temporary variable execute_process(COMMAND git rev-parse HEAD # --short=${git_rev_size} HEAD OUTPUT_VARIABLE git_revision OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${FLTK_SOURCE_DIR} ERROR_QUIET ) if(git_revision STREQUAL "") # Read git revision from a file generated by makesrcdist. # This file is located in the FLTK source directory if(EXISTS ${git_rev_file}) file(READ ${git_rev_file} git_revision) string(STRIP "${git_revision}" git_revision) else() set(git_revision "unknown") endif() endif() set(FLTK_GIT_REVISION "${git_revision}" CACHE STRING "FLTK Git revision (do not change)" FORCE) # debug and unset temporary variables # fl_debug_var(git_revision) unset(git_rev_file) unset(git_revision) ####################################################################### # Include FindPkgConfig for later use of pkg-config ####################################################################### include(FindPkgConfig) # fl_debug_var(PKG_CONFIG_FOUND) # fl_debug_var(PKG_CONFIG_EXECUTABLE) # fl_debug_var(PKG_CONFIG_VERSION_STRING) ####################################################################### # GitHub Issue #1001: try to "repair" the CMake Cache # GitHub Issue #1046: don't try "too hard" (see GitHub Issue) ####################################################################### # # Note: we renamed "our" CMake cache variable OPENGL_GLU_INCLUDE_DIR # to FLTK_OPENGL_GLU_INCLUDE_DIR because the former is now defined # in find_package(OpenGL) (FindOpenGL.cmake) since CMake 3.29.0. # # We remove "our" cache variable if OPENGL_GLU_INCLUDE_DIR is defined # but FLTK_OPENGL_GLU_INCLUDE_DIR is not yet defined which indicates # the first execution after the rename. # # FIXME: we can remove this code some time after the release of FLTK 1.4.0. if(DEFINED OPENGL_GLU_INCLUDE_DIR AND NOT DEFINED FLTK_OPENGL_GLU_INCLUDE_DIR) unset(OPENGL_GLU_INCLUDE_DIR) unset(OPENGL_GLU_INCLUDE_DIR CACHE) endif() # (DEFINED OPENGL_GLU_INCLUDE_DIR AND NOT ...) ####################################################################### # Find header files... ####################################################################### if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "FreeBSD") list(APPEND CMAKE_REQUIRED_INCLUDES /usr/local/include) endif(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "FreeBSD") fl_find_header(HAVE_ALSA_ASOUNDLIB_H alsa/asoundlib.h) fl_find_header(HAVE_DLFCN_H dlfcn.h) fl_find_header(HAVE_GL_GLU_H GL/glu.h) fl_find_header(HAVE_LOCALE_H locale.h) fl_find_header(HAVE_OPENGL_GLU_H OpenGL/glu.h) fl_find_header(HAVE_STDIO_H stdio.h) fl_find_header(HAVE_STRINGS_H strings.h) fl_find_header(HAVE_SYS_SELECT_H sys/select.h) fl_find_header(HAVE_SYS_STDTYPES_H sys/stdtypes.h) fl_find_header(HAVE_X11_XREGION_H "X11/Xlib.h;X11/Xregion.h") if(WIN32 AND NOT CYGWIN) # we don't use pthreads on Windows (except for Cygwin, see options.cmake) set(HAVE_PTHREAD_H 0) else() fl_find_header(HAVE_PTHREAD_H pthread.h) endif(WIN32 AND NOT CYGWIN) # Do we have PTHREAD_MUTEX_RECURSIVE ? if(HAVE_PTHREAD_H) try_compile(HAVE_PTHREAD_MUTEX_RECURSIVE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/CMake/pthread_mutex_recursive.c ) else() set(HAVE_PTHREAD_MUTEX_RECURSIVE 0) endif() # Special case for Microsoft Visual Studio generator (MSVC): # # The header files <GL/glu.h> and <locale.h> are located in the SDK's # for Visual Studio. If CMake is invoked from a desktop icon or the Windows # menu it doesn't have the correct paths to find these header files. # The CMake folks recommend not to search for these files at all, because # they must always be there, but we do anyway. # If we don't find them we issue a warning and continue anyway. # # Note: these cache variables can only be seen in "advanced" mode. if(MSVC) if(NOT HAVE_GL_GLU_H) message(STATUS "Info: Header file GL/glu.h was not found. Continuing...") set(HAVE_GL_GLU_H 1) endif(NOT HAVE_GL_GLU_H) if(NOT HAVE_LOCALE_H) message(STATUS "Info: Header file locale.h was not found. Continuing...") set(HAVE_LOCALE_H 1) endif(NOT HAVE_LOCALE_H) endif(MSVC) # Simulate the behavior of autoconf macro AC_HEADER_DIRENT, see: # https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Headers.html # "Check for the following header files. For the first one that is found # and defines 'DIR', define the listed C preprocessor macro ..." # # Note: we don't check if it really defines 'DIR', but we stop processing # once we found the first suitable header file. fl_find_header(HAVE_DIRENT_H dirent.h) if(NOT HAVE_DIRENT_H) fl_find_header(HAVE_SYS_NDIR_H sys/ndir.h) if(NOT HAVE_SYS_NDIR_H) fl_find_header(HAVE_SYS_DIR_H sys/dir.h) if(NOT HAVE_SYS_DIR_H) fl_find_header(HAVE_NDIR_H ndir.h) endif(NOT HAVE_SYS_DIR_H) endif(NOT HAVE_SYS_NDIR_H) endif(NOT HAVE_DIRENT_H) #---------------------------------------------------------------------- # The following code is used to find the include path for freetype # headers to be able to #include <ft2build.h> in Xft.h. # where to find freetype headers find_path(FREETYPE_PATH freetype.h PATH_SUFFIXES freetype2) find_path(FREETYPE_PATH freetype/freetype.h PATH_SUFFIXES freetype2) if(FREETYPE_PATH AND ((NOT APPLE) OR FLTK_BACKEND_X11)) list(APPEND FLTK_BUILD_INCLUDE_DIRECTORIES ${FREETYPE_PATH}) endif(FREETYPE_PATH AND ((NOT APPLE) OR FLTK_BACKEND_X11)) mark_as_advanced(FREETYPE_PATH) ####################################################################### # libraries find_library(LIB_dl dl) if((NOT APPLE) OR FLTK_BACKEND_X11) find_library(LIB_fontconfig fontconfig) endif((NOT APPLE) OR FLTK_BACKEND_X11) find_library(LIB_freetype freetype) find_library(LIB_GL GL) find_library(LIB_MesaGL MesaGL) find_library(LIB_jpeg jpeg) find_library(LIB_png png) find_library(LIB_zlib z) find_library(LIB_m m) mark_as_advanced(LIB_dl LIB_fontconfig LIB_freetype) mark_as_advanced(LIB_GL LIB_MesaGL) mark_as_advanced(LIB_jpeg LIB_png LIB_zlib) mark_as_advanced(LIB_m) ####################################################################### # functions include(CheckFunctionExists) # Save CMAKE_REQUIRED_LIBRARIES # Note: CMAKE_REQUIRED_LIBRARIES must be set for each search and # reset after the search to avoid to influence subsequent searches. # The original value is restored after all searches. if(DEFINED CMAKE_REQUIRED_LIBRARIES) set(SAVED_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) else() unset(SAVED_REQUIRED_LIBRARIES) endif() set(CMAKE_REQUIRED_LIBRARIES) if(HAVE_DLFCN_H) set(HAVE_DLFCN_H 1) endif(HAVE_DLFCN_H) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS}) check_symbol_exists(dlsym "dlfcn.h" HAVE_DLSYM) set(CMAKE_REQUIRED_LIBRARIES) check_symbol_exists(localeconv "locale.h" HAVE_LOCALECONV) if(LIB_png) set(CMAKE_REQUIRED_LIBRARIES ${LIB_png}) check_symbol_exists(png_get_valid "png.h" HAVE_PNG_GET_VALID) check_symbol_exists(png_set_tRNS_to_alpha "png.h" HAVE_PNG_SET_TRNS_TO_ALPHA) set(CMAKE_REQUIRED_LIBRARIES) endif(LIB_png) check_symbol_exists(scandir "dirent.h" HAVE_SCANDIR) check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF) # not really true but we convert strcasecmp calls to _stricmp calls in flstring.h if(MSVC) set(HAVE_STRCASECMP 1) endif(MSVC) check_symbol_exists(strcasecmp "strings.h" HAVE_STRCASECMP) check_symbol_exists(strlcat "string.h" HAVE_STRLCAT) check_symbol_exists(strlcpy "string.h" HAVE_STRLCPY) check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF) check_symbol_exists(setenv "stdlib.h" HAVE_SETENV) # Windows doesn't require '-lm' for trunc(), other platforms do if(LIB_m AND NOT WIN32) set(CMAKE_REQUIRED_LIBRARIES ${LIB_m}) endif() check_symbol_exists(trunc "math.h" HAVE_TRUNC) set(CMAKE_REQUIRED_LIBRARIES) if(HAVE_SCANDIR AND NOT HAVE_SCANDIR_POSIX) set(MSG "POSIX compatible scandir") message(STATUS "Looking for ${MSG}") try_compile(V ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/CMake/posixScandir.cxx ) if(V) message(STATUS "${MSG} - found") set(HAVE_SCANDIR_POSIX 1 CACHE INTERNAL "") else() message(STATUS "${MSG} - not found") set(HAVE_SCANDIR_POSIX HAVE_SCANDIR_POSIX-NOTFOUND) endif(V) endif(HAVE_SCANDIR AND NOT HAVE_SCANDIR_POSIX) mark_as_advanced(HAVE_SCANDIR_POSIX) # restore CMAKE_REQUIRED_LIBRARIES if(DEFINED SAVED_REQUIRED_LIBRARIES) set(CMAKE_REQUIRED_LIBRARIES ${SAVED_REQUIRED_LIBRARIES}) unset(SAVED_REQUIRED_LIBRARIES) else() unset(CMAKE_REQUIRED_LIBRARIES) endif() ####################################################################### # packages # Doxygen: necessary for HTML and PDF docs find_package(Doxygen) # LaTex: necessary for PDF docs (note: FindLATEX doesn't return LATEX_FOUND) # Note: we only check existence of `latex' (LATEX_COMPILER), hence # building the pdf docs may still fail because of other missing tools. set(LATEX_FOUND) if(DOXYGEN_FOUND) find_package(LATEX) if(LATEX_COMPILER AND NOT LATEX_FOUND) set(LATEX_FOUND YES) endif(LATEX_COMPILER AND NOT LATEX_FOUND) endif(DOXYGEN_FOUND) # message("Doxygen found : ${DOXYGEN_FOUND}") # message("LaTex found : ${LATEX_FOUND}") # message("LaTex Compiler : ${LATEX_COMPILER}") # Cleanup: unset local variables unset(CMAKE_REQUIRED_QUIET) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/forms.h����������������������������������������������������������������������������������0000644�0001750�0001750�00000000175�15004135251�014107� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// this file allows some forms programs to be compiled with no change. // put it in your include path. #include <FL/forms.H> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/CHANGES_1.0.txt��������������������������������������������������������������������������0000644�0001750�0001750�00000100065�15004135251�014776� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Changes in FLTK 1.0, up to FLTK 1.0.11 (May 7, 2001) CHANGES IN FLTK 1.0.11 - CHANGED THE DEFAULT RUN-TIME LINKING TO "MULTITHREADED DLL". You'll need to change your project settings to use this as well or you'll get errors. - Added new --disable-gl option to configure script. - Added new const const pointer versions of pixmap functions to eliminate an annoying pointer warning message that was generated by the Sun and other C++ compilers. - Eliminated all "var hides class::var" warnings. - Eliminated all "string literal converted to char *" warnings. - OS/2 updates from Alexander Mai. - Tidied up the HTML documentation to be more standards compliant. - Compiling with -DBOXX_BUGS will work around some problems with the newest X drivers that BoXX delivers, the problems all affect use of Overlays for normal X drawing and OpenGL drawing. Normal compilation is unchanged. - The file chooser buttons use user_data() rather than the label to decide what to do, allowing the label to be somewhat cleaner. - Selection color on X changed to blue, to match what happens on Windows now. - Added support for AIX (static library only). - Added support for SunOS 4.x - Now process WIN32 WM_ACTIVATEAPP message to reset the key and button states in Fl::e_state. - Fl_has_idle only tested N-1 callbacks and missed one. - Restored WM_SYNCPAINT handling under WIN32; this fixed a refresh bug under some versions of Windows. - Check for OpenGL headers before checking to see if OpenGL is supported. This should eliminate compile errors due to missing non-FLTK header files... - Add -D_INCLUDE_POSIX_SOURCE option when compiling with the HP compilers. - Replaced remaining _WIN32 symbols with WIN32 - Removed reference to unused GL/glu.h header file, which is missing on some Linux systems. - Fl_Gl_Window has a new method to allow you to get and set the context: void Fl_Gl_Window::context(void*, int destroy = 0) void* Fl_Gl_Window::context() const; Return or set a pointer to the GLContext that this window is using. This is a system-dependent structure, but it is portable to copy the context from one window to another. You can also set it to NULL, which will force FLTK to recreate the context the next time make_current() is called, this is useful for getting around bugs in OpenGL implementations. If destroy_flag is true the context will be destroyed by fltk when the window is destroyed, or when the mode() is changed, or the next time context(x) is called. - Some cleanup of Fl_Gl_Choice to move most of the system dependent #ifdefs into Fl_Gl_Choice.cxx. - Fl_Gl_Window does not set drawbuffer(BACKBUFFER) for single-buffered windows. - Fl_Input::replace(...) correctly updates the display if the replaced region does not include the mark, point, or selected region. - Added Fl::add_check(...), Fl::remove_check, and Fl::has_check. These are similar to idle callbacks but are only called just before it waits for new events. They can be used to watch for changes in global state and respond to them. - "accu-timer": some changes to repeat_timeout that seem to make it accurate on Unix and WIN32 at speeds up to 500000 timeouts/second (and 700000 on Linux), and within about .001% as accurate as the system clock. - Fix to Fl_Valuator::step() by Guillermo Andrade. - Fixed the FLUID write-menu bug introduced in 1.0.10 - Fl::flush() now calls GdiFlush() under WIN32 to ensure that all graphics are drawn. - fl_curve() now uses a much better algorithim to figure out how many pieces to cut the curve into. - FLUID now uses GetTempPath() under WIN32 to determine where to store the clipboard. - Right-ctrl does not delete selected text in Fl_Input, until you type a composed character. - Added simple FLTK and FLUID manual pages. - Fl_Gl_Window leaked memory under WIN32. - The colbrowser demo was missing an include file when compiled under OS/2. CHANGES IN FLTK 1.0.10 - Added a strcasecmp() function to FLUID; AIX doesn't have it. - Bug #115509: Fl_Scroll not repainting background. - Updated the configure script and makeinclude.in file to work with the Sun PRO compilers. - Disabled the WIN32 async socket select code by default: it doesn't seem to work anymore... - Fl::below_mouse() was incorrectly clearing e_is_click; this prevented any double-clicks from getting through... - No longer clear Fl::keysym on every event, this makes better back compatability and fixes Win2000 - FLUID now restores which tab in an Fl_Tabs was selected when loads .fl files. - Hack to fix the annoying "raise another application when a modal window is closed" problem on WIN32. - Fl_Tabs now draws the background behind the tabs. - Fl::set_fonts() on WIN32 fixed to work before the first window is shown. - CUA function keys, code submitted by George Yohng <yohng@drivex.dosware.8m.com> - Another attempt to get glut.h to work on WIN32. - Fl_Menu_::add() ignores '&' signs when comparing menu items, so you don't have to make the shortcuts the same all the time. - Fixed bit-flipping patterns in WIN32 bitmap code. - Fixed size of data written by gif images to .C files - Menu titles and buttons in the menubar can be images (allows it to be used as a toolbar) - Reads selectBackground from the xrdb database to set the selection color. Adding this to your .Xdefaults will make fltk and Motif programs look much more Windoze-like: *selectForeground: white *selectBackground: #000080 - FL_WHEN_RELEASE on Fl_Input will now do the callback when the input field is hidden, for instance when it is on a tab and the user switches to another tab. - Fl_Gl_Window with an overlay on X always resized any child windows even if you turned resizable() off because it turned it back on to resize the overlay window. This patch avoids changing resizable(). - Fix so multiple Fl::add_idle() calls works - The input focus got messed up if you called Fl_Tabs::value(x) and there was something that took focus on an earlier tab. - Removed some (not all) of the warnings when compiled with -Wwrite-strings, this should also get similar warnings Solaris produces. - Made Fl_Browser not hide the Fl_Widget::show() method - Changes & additions for OS/2 from Alexander Mai - Patch from Mike Lindner to make the turning on/off of scrollbars on Fl_Scroll smarter. - Added missing FL_EXPORT for Fl_Valuator::format() - Shortcuts for "buttons" in a Fl_Menu_Bar work again. - Fix for cut/paste support and Xdnd. - Shortcuts for submenu titles in a menubar pop up the submenu (rather than calling the callback) - Added documentation for GL_SWAP_TYPE - Buttons with box(FL_NO_BOX) did not draw. Apparently they did in older versions of fltk, I restored this. (bug 108771) - Removed 8-bit colormap drawing code that was not doing anything in fl_draw_image due to the colormap allocation changes. I also made fl_color(r,g,b) actually allocate the requested color rather than the nearest fltk color-cube color (this is only done for the first color that maps to a given entry in the fltk color cube), the result is that pixmaps with a small number of colors are drawn much more accurately. The resulting code seems to produce better images and is a good deal smaller! - Fixed makeinclude.in so CFLAGS are used for c source code instead of CXXFLAGS. (bug 108694) - Better fix for gif files suggested by pauly (bug 108770) - Performance of Fl_Gl_Window may be improved on some types of OpenGL implementations, in particular MESA or other software emulators, by setting the GL_SWAP_TYPE environment variable. This variable declares what is in the back buffer after you do a swapbuffers: setenv GL_SWAP_TYPE COPY This indicates that the back buffer is copied to the front buffer, and still contains it's old data. This is true of many hardware implementations. Setting this will speed up emulation of overlays, and widgets that can do partial update can take advantage of this as damage() will not be cleared to -1. setenv GL_SWAP_TYPE NODAMAGE This indicates that nothing changes the back buffer except drawing into it. This is true of MESA and Win32 software emulation and perhaps some hardware emulation on systems with lots of memory. All other values for GL_SWAP_TYPE, and not setting the variable, cause fltk to assume that the back buffer must be completely redrawn after a swap. This is easily tested by running the gl_overlay demo program and seeing if the display is correct when you drag another window over it or if you drag the window off the screen and back on. You have to exit and run the program again for it to see any changes to the environment variable. - Optimized colormap usage on 8-bit displays with images. New code only allocates colors as they are needed (still converts indexed images to full RGB and dithers, tho...) - Fixed .gif files in FLUID, they were broken by the fix for large .xpm files in version 1.0.9. - Fix for OpenGL hardware overlays with the transparent index != 0. Tested on the brand new HP Linux Workstations, this is the only bug encountered. Both X and OpenGL hardware overlay works perfectly on these, though configue may not enable it by default...) - Fl_Choice and all other Fl_Menu_ subclasses draw the items using textcolor() as the default color of the text. - Fix suggested by Stuart Levy to fix scrolling when deleting items from the browser. - Replaced the -$(MAKEFLAGS) with $(MFLAGS) as per the gmake documenation. Apperntly this works with other make programs and MAKEFLAGS is passed invisibly by gmake, though the documenation is not too clear... CHANGES IN FLTK 1.0.9 - More documentation fixes. - GLUT_STROKE_*_ROMAN in glut.h are defined as 0,1 on WIN32 to match the glut header files there. - Added Fl::has_timeout() and Fl::has_idle() functions. - Added new Fl::repeat_timeout() method that measures time from when the last timeout was called. This has slightly less overhead and allows accurate spacing of timeouts. - More Cygwin changes - FLUID could crash with identifiers with trailing whitespace. - Fixed the XPM loading code in FLUID to handle files longer than 2048 lines. - Added a bunch of missing FL_EXTERN's to glut.h to eliminate GLUT linking errors under WIN32. - Fix for sliders so that clicking on one with a small (or zero) slider_size will not move the slider. - fl_shortcut.cxx didn't export fl_old_shortcut() in the WIN32 DLL. - Fixed xpaint link in the documentation. - Included Fl_Input word-wrap fixes from Alexander Rabi Beels. This will not affect things much because word-wrap is normally disabled. - Patch from Stuart Levy so the *last* widget in an Fl_Pack may be resizable. This should be compatable because resizable didn't do anything before so there was no reason to set it. - Cleaned up the timeout and Fl::wait() code. The new code calls the clock function less than half as much, which results in a noticable performance improvement in some apps. - Fl::wait(time) with a time greater than the system can handle (24.855 days on NT, the same on some Unix systems) will now act as though the time is infinity. Before it would do unpredictable things. - "USE_POLL" now compiles and works, although it is disabled by default. poll() is an alternative to the UNIX select() call which is available on some version of UNIX and may be faster depending on the platform; try it by editing config.h. - The WIN32 USE_ASYNC_SELECT code now does translation and dispatching of the select events; this makes Windows a lot happier. - Added a check for an open display in Fl::wait() so that you don't need an open window under X to call it. [changes in snapshot 2] - fl_old_shortcut() wasn't being exported in the WIN32 DLL project. - Updated Cygwin and Mingw makefiles. - Updated the BC++ project file. - You can no longer insert control chars into Fl_Int/Float_Input. - Fl_Multiline_Input now resets the horizontal position when focus is changed; this caused problems when multiple multiline widgets were used in an application. - All handle() methods are now public, and all draw() methods are now protected in FLTK widgets. - More fixes to the OpenGL overlay code on win32. This now seems to work quite reliably on several different pieces of hardware. Apparently doing SetLayerPaletteEntries with a palette larger than the overlay size caused the drivers to screw up in unpredictable ways. Also SwapBuffers swapped both the overlay and main window, which is not what fltk's interface wanted, this was easy to fix however. - Patch for full scrollbars so that clicking on them does not move anything. - Documentation fixes. - Better horizontal scrolling of Fl_Input when cursor is near the end of the line. - Fl_Input::value(x) selects all text. - Fl_Output and Fl_Multiline_Output would scroll to the end of the text. - filename_isdir() now drops any trailing slash from the filename (needed for Windows) - Added return type for main() function in line_style demo. - Running FLUID with the "-cs" option writes the I18N message file. - The WIN32 version of XParseGeometry() didn't initialize some variables. This caused a compiler warning but did not affect the actual code. [changes in snapshot 1] - EMail changes - fltk-bugs@easysw.com now officially fltk-bugs@fltk.org. - The FLTK DLL project file didn't include fl_compose.cxx - Dropped the GCC -fno-rtti option since it caused problems with existing programs. - Moved the .fl rules back to the test directory. - Fixed some makefile and spec file problems. - Fixed hardware overlays. The problem was the new fl_clipped() code, which tests against the current window size. The hardware overlay code did not set the current window when drawing the overlay. I needed hardware overlay for DD's code, I'm not sure if these fixes are good enough to enable this in our general release. Hardware overlay still only works on SGI Irix. - Some patches to turn off the MSVC++ -Oa (assume no aliasing) optimization flag. Suprisingly this only broke a few parts of fltk, or at least these are the only ones I found. - Does not unmap child windows when the main window is iconized. This reduces flashing when the window is deiconized. - Fl::key() is set to zero by all events except key down/up. This will allow you to reliably test if an event or callback was produced by a keystroke. Fixes the bug posted about stopping Escape from closing the window. - User defined cursors on OpenGL windows slowed down NT a *LOT*. Some attempts to fix this by turning off the cursor while drawing the window. - Filename completion in the file chooser works better on NT. Typing TAB fixes the case of everything you typed to match the shortest name that can be completed. CHANGES IN FLTK 1.0.8 - Many documentation changes/fixes/improvements. - FLUID didn't save Fl_Double_Window's as double-buffered windows. - Fl_Menu_ text color is used if Fl_Menu_Item text color is not set. - Added Fl::first_window(window) method to change the "top" window that is used when showing modal windows. By default it is the window the user last clicked/typed in. - The Fl_Menu::global() handler now uses the current top window instead of the menu bar for modal stuff. - Added fl_line_style() function to set the line style. Note that user-defined line styles ONLY WORK UNDER X11 and Windows NT/2000. Windows 95/98 do, however, support the "standard" line styles. - Fl::wait() does not return immediately when no windows - XForms keyboard shortcuts using hex keycode constants now work. - Updated the configure script for *BSD and to turn off exceptions and RTTI in the FLTK library itself (does not affect applications which use these things) - FLUID now supports I18N using the POSIX or GNU mechanisms. - Fixed definition of glutBitmapWidth to match header file. - Does not turn visible() on when a window is iconized() or if a modal window is shown and it's parent is iconized. This allows the code "while (w->visible() && w->damage()) Fl::check();" to reliably wait for the window to be mapped and drawn the first time. - Setting box(FL_NO_BOX) on a button makes it an invisible overlay - FL_NORMAL_SIZE is now a global variable so you can change the default text size prior to creating your widgets. - Menus now draw properly with a box type of FL_FLAT_BOX. - Cygwin fixes to compile in POSIX mode. - Fl_Value_Input callback can call value() or destructor. - OpenGL overlays now work under Windows NT! - Fl_Slider and Fl_Scrollbar could cause a divide by zero. - Clicking in an Fl_Input field no longer selects the whole field, it just moves the text cursor. - Tru64 UNIX fixes for filename_list() - Fl_Browser now draws itself properly when deactivated. - FLUID GUIs now use Courier font for all code input. - The FLUID OK and Cancel buttons are now all shown in the same order in all windows. - Fixes to compile under GCC 2.95.2 - Fixed the BC5 project files. - FL_LEFT_MOUSE and friends are now in <FL/Enumerations.H> - Fixes for fake OpenGL overlay code under WIN32. - Message windows are now resizeable. - On WIN32 non_modal (but not modal) windows have the close and size boxes. - Fl_Button and friends didn't honor the FL_WHEN_NOT_CHANGED condition. - Disabled XDBE on all platforms. - XGetDefault patch from James Roth - New fl_open_display(Display *) function to allow FLTK to share a display connection with another toolkit (like Xt, GTK, etc.) - Shortcut labels for special keys should now display properly under WIN32. - fl_set_fonts() did not reuse fonts. - Fixed shortcut problem under WIN32 when the focus window changes. - "dead" keys should now work under X11. - Fixes to make FLTK compile with GCC 2.95.2 - FL_SHORTCUT fix for I18N. - Fixed cut/paste problems under WIN32 - FLUID now produces correct code for nested class destructors. - Nested windows should now redraw properly under WIN32. - "table" is now static in fl_cursor.cxx - Fl_Chart used the textcolor() and not the color() for horizontal bar charts. - Now set the input hint for TWM and TWM-derived window managers. - Now look for TrueColor visual if FLTK is compiled with USE_COLORMAP == 0. - Fl_Scrollbar could generate a divide-by-0 error if the min and max values were the same. - Fl_Menu_::remove() now removes whole submenus if needed. - Scrollbar buttons now draw themselves pushed in as needed. - Fixed the gl_overlay demo (and gl overlays in general) when they are faked with no hardware and the window is resized. - Selections weren't shown in Fl_Browser widgets when an item used the @B (background) format. - Windows can now be resized by the program under X11 for more window managers. - OS/2 makeinclude updates. - Added Fl.H required by an inline function in Fl_Repeat_Button.H - Fl_add_idle adds new functions to the end of the queue ring, rather than the start, so they are executed in the order added, and a callback that adds itself does not prevent others from being called. - FLUID lets you type in code that starts with '#' for cpp directives. - XBell() could be called before the X11 display was opened, causing a segfault. - Fixed Fl_Gl_Window::ortho() - Borland C++ doesn't define GLint to "int", but instead to "long"... - Fixed Fl_Browser scrollbars within an Fl_Scroll widget. - Fl_Output (and non-focused Fl_Input) now scroll in response to position() - Fl_Input now does not scroll horizontally if the entire string will fit in the widget. - Fl_Scrollbar didn't push the right arrow buttons when you clicked outside the scroller. - Now use WSAAsyncSelect() for better socket performance with Fl::add_fd() CHANGES IN FLTK 1.0.7 - Fixed Fl_Input_ bug under WIN32 - no longer stop accepting input when one of the "Windows" keys is pressed. - Now call TranslateEvent for all events under WIN32. - Fixes for OpenBSD and NetBSD - The FL_CURSOR_HAND cursor now uses the IDC_HAND cursor instead of IDC_UPARROW under Windows 98 and 2000. - Fl_Scrollbar now does a page-up/down when you click outside the scroller. - Fl_Window::show(0, NULL) causes core dump - Fixed a compile-time error in fl_call_main.c for Borland C++. - "fluid -c filename.fl" would try to open an X display if the FLUID file contained an Fl_Browser widget. - Fl_Browser now correctly measures items with @C or @B color formatting commands. - Fixed a bitmap drawing bug for WIN32 (bit reversal table was wrong) - fl_xyz() dialogs now set a title in the title bar. - fl_alert() sounds the bell under X11. - fl_xyz() dialogs now call MessageBeep() under WIN32. - Fl_Browser_ didn't draw the selection box with the inactive color when the browser wasn't activated. - Fl_Browser now responds to FL_KEYBOARD as well as FL_SHORTCUT. If you subclass it to accept focus then keyboard navigation will work. - Fl_Tile and Fl_Tabs do their callback when the user changes their display. - Made some of the private methods of Fl_Browser protected. - Now set win_gravity correctly, this helps some X window managers that use it position the window where FLTK wants it to be. - 0-width browsers crashed. - Minor change: if the X window manager does not do anything else with windows that don't have their position specified, the windows appear centered in the screen, rather than in the top-left corner. This happened with modal windows under Irix 4Dwm. This also causes windows to be centered when no window manager is running, which might be useful for installation gui programs? - Clicking in an Fl_Input field the first time selects the entire field. - Clicking the middle mouse button in an Fl_Input field now inserts the text at the indicated position instead of the cursor position. - Drag-selecting text in an Fl_Input field now copies the text automatically. - Fl::flush() no longer calls the draw() method for invisible windows. - Calling deactivate() on an invisible widget could cause an infinite loop in some obscure cases. - Added #pragma's for SGI C++ compilers - the 6.{23} X headers had errors in them. - Fl_Gl_Window::ortho() changed so that text and images are not erased if the origin is off the left/bottom of the window. - Small change to Fl_Input so that a click that gives it the focus also selects all the text. - Fixed a slider drawing problem. - You can now add/delete children of Fl_Tabs widgets whether or not they are visible. - Now embed woff options for SGI C++ compilers (gets rid of X11 header warnings) - draw_pixmap used a cast that the Digital UNIX C++ compiler didn't like. - The GLUT function key constants were off by one. - The XPM reading code didn't handle RGB colors other than #rrggbb. CHANGES IN FLTK 1.0.6 - Fl_win32.cxx defined WM_MOUSE_LEAVE instead of WM_MOUSELEAVE. - Fl_get_key_win32.cxx needed to include <ctype.h> - gl_draw_pixmap.cxx needed a pointer cast for ANSI C++. - Fl_Repeat_Button didn't always delete its timeout. - Now keep track of the current OpenGL context; this provides significant performance improvements for OpenGL applications with a single context. CHANGES IN FLTK 1.0.5 - Fl_Roller didn't handle a width and height of 0. - filename_list() fix for FreeBSD. - Fixed RPM install docos - needed "--install" option... - Fl_Browser_ wouldn't draw the vertical scrollbar right away if it added a horizontal one which covered the last line. - Fl_Tabs problems - single-character labels don't show up (problem in measure_tabs() or measure_label() methods?), and doesn't clear top tab area before drawing tabs. - Fl_Browser needs a destructor. - fl_draw_label() quoted characters between 0x80 and 0xa0, which caused problems for some programs using the WinANSI character set. - FLUID didn't handle declared class destructors. - Fixed another WIN32 cut/paste bug. - Fl_Tabs didn't work properly when there was only 1 tab. - Fl_Menu::add() didn't delete the old array. - Fl_Repeat_Button didn't delete its timeout when disabled. - fl_draw() would crash if no font was set (now defaults to a 14-pixel Helvetica font) - Can't forward declare classes; need to check for "class ", "struct ", "union ", etc. See Bill's message - Added #pragma around xlib.h for IRIX - FL_KEYBOARD events have the correct x/y when sent to child X windows. Note that if you worked around this bug by adjusting the x/y yourself you will have to change your code. In addition all events have the correct x/y when sent to the grab() widget. And the code to do all this was simplified a lot. - The XPM code didn't handle named colors with spaces in the names. - Pressing ESCape closed the window with pointer focus, even if there was a modal window open (now closes the modal window). - FLUID no longer produces trigraphs accidentally in the image data. - FLUID uses string constant concatenation to produce shorter image data. - The Fl_Group deletion code crashed if there was exactly one child widget. - Simulated overlays in single-buffered Fl_Gl_Windows now draw correctly (though very slowly as it requires the entire window to be redrawn to erase the overlay). This fix ported our Digital Domain programs better to systems with no overlay hardware. - Added support for extern "C" declarations in FLUID. - Added Fl_Pack support to FLUID. - Fixed the order of #include's in FLUID generated header files. - Fixed detection of vsnprintf and snprintf under HP-UX 10.20 once and for all. - The checkers demo did not compile with GCC 2.95 - FLUID didn't output virtual destructors properly. - Added inline "make_visible()" method to Fl_Browser. - Fl::wait() now returns immediately if any timeouts are called. - 16-bit XPM files are now properly handled. - Fl_Window::resize() was missing FL_EXPORT (caused problems with Windows DLLs) - FLUID was writing extern declarations twice. - New FLUID arrow key functionality: arrows move by one pixel, shift+arrow resizes, ctrl+arrow steps by grid CHANGES IN FLTK 1.0.4 - Documentation updates - Fl_Browser::bottomline(size) didn't scroll to the bottom if the second-to-last line was visible. - fl_wait() didn't poll FDs properly for WIN32. - Fixed DLL definitions for BC++. - FLUID now handles nested classes properly. - The "connect" demo now does a wait() for the PPP process so that you aren't left with a lot of zombie processes. - Fixed the FLTK colormap to use FF instead of F4 for full intensity values. - Minor change to scrollbar drawing code to match other toolkits. - New selections would cancel themselves out in WIN32. - The header file links were broken in the IRIX distributions. - fl_elapsed() now always uses GetClockTick() for WIN32. - fl_display is now initialized to GetModuleHandle(NULL) - this fixes problems people had with Cygwin and MingW32. - WinMain() is no longer compiled in with Cygwin and MingW32; it wasn't being used for those compilers anyways. - Added Solaris compiler options to configure script. - Fl_Value_Input wouldn't update properly if you set the value from a callback. - Fl_Tile wouldn't resize if the resizeable widget was the last child. - Was missing #include <ctype.h> and #include <stdlib.h> in several files, which caused problems on some platforms. - Fixed another case where Fl_Browser_ could get in an infinite resizing loop. - Fl_win32.cxx now includes <FL/filename.H> to export missing DLL symbols. - FLUID didn't handle member functions that include the scope operator. - Fl_Chart was dividing by 0 if there were no data samples or if they were all the same (min == max). CHANGES IN FLTK 1.0.3 - XDBE is now enabled for IRIX 6.[234] as well as 6.5. - FLUID didn't write the when() condition properly. - Tab/space/backtab/backspace can be used to navigate through menus. - Changed $(DSONAME) in the src/Makefile to "libfltk.so.1 libfltk.sl.1". - Fl_Browser could read past the end of the string when computing the item height. - Fl_Browser could get in an infinite loop when checking to see if scrollbars needed to be displayed. - FLUID now honors the return type of the outermost widget. This was a problem when substituting Fl_Group in an Fl_Window widget. - Fl_Menu_::copy() wasn't allocating a power of 2 for the array size. - FLWM would crash if fl_xmousewin was deleted. - The fast_slow demo now uses output widgets. - Timers under WIN32 were unreliable. CHANGES IN FLTK 1.0.2 - Documentation updates - The Visual C++ project files didn't include fl_add_idle.cxx. - LIBRARY/DSO name inconsistencies in src/Makefile. - src/Makefile didn't clean the DSO. - The valuator demo now has only a single callback. - The code looked for HAVE_SYS_SELECT_H, but the config file uses HAVE_SYS_SELECT. - Fl_Image redraw not quite right under X11 or WIN32 - Problems with timeouts & cube demo under WIN32 - FLUID problems with inline functions. - Documentation fixes... - Fl_Browser::item_height() didn't handle blank lines or non-default fonts properly. - FL/math.h didn't have #ifndef...#define...#endif guards against multiple inclusion... - Fl_Menu_::copy() fix - didn't allocate power of 2... - Fl::damage() now remains true until all windows are actually redrawn. - Fl_Widget destructor, hide(), and deactivate() methods no longer send FL_LEAVE, FL_RELEASE, or FL_UNFOCUS events to the widget (which could cause applications to crash). - FLUID now outputs symbolic names for align() and when(). - Fixed select() to use maxfd + 1 instead of maxfd. - Added "Fl::remove_fd(fd, when)" function so you can remove the read and write callbacks separately. - The Fl::add_fd() and Fl::add_timeout() arrays are now dynamically allocated. - FLUID didn't always turn the FL_SUBMENU flag on for submenu titles. - The "extra code" in FLUID now is placed before the "o->end()" call for Fl_Group and its derived classes. - You can now set a FL_Window widget's class in FLUID to Fl_Group to generate a function or class that builds part of a GUI (i.e. no window). - FLUID now displays "Save file before exiting?" with the standard yes, no, and cancel buttons rather than "Discard changes?". - Fl_Menu_::add() now works with any type of menu, even one set with the menu() method. - The keypad keys were not always decoded properly under X11. - Some pointers were not being turned off when widgets were deleted, which caused some applications (like FLWM) to crash. CHANGES IN FLTK 1.0.1 - Documentation fixes. - Fl::check() didn't return the correct value, breaking a number of applications. - Fixed FLUID bug that caused styles patch to crash when you delete a menu item. - Updated valuators demo to put the values in the gui box. - Fl_Browser_::item_height() didn't always compute the correct value. - Fixed the alignment of Fl_Choice text. - Fixes for OS/2. - Fl_Menu_Item::clear() didn't clear value. - Added some changes to make FLTK work with Borland C++. - ANSI C++ fixes. - Plugged a memory leak in the fractal demo. - Fl::add_timeout() didn't work under WIN32 with small values. - The configure script and makefiles now define DSONAME and use the static library for all example programs. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/fluid/�����������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�15004135251�013710� 5����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/fluid/fluid.xml��������������������������������������������������������������������������0000644�0001750�0001750�00000000371�15004135251�015536� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info"> <mime-type type="application/x-fluid"> <comment>FLUID GUI Design</comment> <glob pattern="*.fl"/> </mime-type> </mime-info> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/fluid/makedepend�������������������������������������������������������������������������0000644�0001750�0001750�00000171523�15004135251�015741� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# DO NOT DELETE THIS LINE -- make depend depends on it. about_panel.o: ../config.h about_panel.o: ../FL/Enumerations.H about_panel.o: ../FL/Fl.H about_panel.o: ../FL/Fl_Anim_GIF_Image.H about_panel.o: ../FL/fl_attr.h about_panel.o: ../FL/Fl_Bitmap.H about_panel.o: ../FL/Fl_Box.H about_panel.o: ../FL/Fl_Button.H about_panel.o: ../FL/Fl_Cairo.H about_panel.o: ../FL/fl_casts.H about_panel.o: ../FL/fl_config.h about_panel.o: ../FL/Fl_Double_Window.H about_panel.o: ../FL/Fl_Export.H about_panel.o: ../FL/Fl_GIF_Image.H about_panel.o: ../FL/Fl_Group.H about_panel.o: ../FL/Fl_Image.H about_panel.o: ../FL/Fl_Pixmap.H about_panel.o: ../FL/Fl_Return_Button.H about_panel.o: ../FL/fl_string_functions.h about_panel.o: ../FL/fl_types.h about_panel.o: ../FL/fl_utf8.h about_panel.o: ../FL/Fl_Widget.H about_panel.o: ../FL/Fl_Window.H about_panel.o: ../FL/platform_types.h about_panel.o: ../src/flstring.h about_panel.o: about_panel.h align_widget.o: ../FL/Enumerations.H align_widget.o: ../FL/filename.H align_widget.o: ../FL/Fl.H align_widget.o: ../FL/fl_attr.h align_widget.o: ../FL/Fl_Bitmap.H align_widget.o: ../FL/Fl_Cairo.H align_widget.o: ../FL/fl_casts.H align_widget.o: ../FL/fl_config.h align_widget.o: ../FL/Fl_Device.H align_widget.o: ../FL/fl_draw.H align_widget.o: ../FL/Fl_Export.H align_widget.o: ../FL/Fl_Flex.H align_widget.o: ../FL/Fl_Graphics_Driver.H align_widget.o: ../FL/Fl_Group.H align_widget.o: ../FL/Fl_Image.H align_widget.o: ../FL/Fl_Menu_Item.H align_widget.o: ../FL/Fl_Multi_Label.H align_widget.o: ../FL/Fl_Pack.H align_widget.o: ../FL/Fl_Pixmap.H align_widget.o: ../FL/Fl_Plugin.H align_widget.o: ../FL/Fl_Preferences.H align_widget.o: ../FL/Fl_Rect.H align_widget.o: ../FL/Fl_RGB_Image.H align_widget.o: ../FL/Fl_Tabs.H align_widget.o: ../FL/fl_types.h align_widget.o: ../FL/fl_utf8.h align_widget.o: ../FL/Fl_Widget.H align_widget.o: ../FL/Fl_Window.H align_widget.o: ../FL/Fl_Wizard.H align_widget.o: ../FL/platform_types.h align_widget.o: ../src/Fl_String.H align_widget.o: align_widget.h align_widget.o: code.h align_widget.o: fluid.h align_widget.o: fluid_filename.h align_widget.o: Fl_Group_Type.h align_widget.o: Fl_Type.h align_widget.o: Fl_Widget_Type.h align_widget.o: undo.h autodoc.o: ../FL/Enumerations.H autodoc.o: ../FL/filename.H autodoc.o: ../FL/Fl.H autodoc.o: ../FL/fl_ask.H autodoc.o: ../FL/fl_attr.h autodoc.o: ../FL/Fl_Bitmap.H autodoc.o: ../FL/Fl_Box.H autodoc.o: ../FL/Fl_Browser.H autodoc.o: ../FL/Fl_Browser_.H autodoc.o: ../FL/Fl_Button.H autodoc.o: ../FL/Fl_Cairo.H autodoc.o: ../FL/fl_casts.H autodoc.o: ../FL/Fl_Check_Button.H autodoc.o: ../FL/Fl_Choice.H autodoc.o: ../FL/fl_config.h autodoc.o: ../FL/Fl_Device.H autodoc.o: ../FL/Fl_Double_Window.H autodoc.o: ../FL/fl_draw.H autodoc.o: ../FL/Fl_Export.H autodoc.o: ../FL/Fl_File_Browser.H autodoc.o: ../FL/Fl_File_Chooser.H autodoc.o: ../FL/Fl_File_Icon.H autodoc.o: ../FL/Fl_File_Input.H autodoc.o: ../FL/Fl_Flex.H autodoc.o: ../FL/Fl_Graphics_Driver.H autodoc.o: ../FL/Fl_Group.H autodoc.o: ../FL/Fl_Image.H autodoc.o: ../FL/Fl_Image_Surface.H autodoc.o: ../FL/Fl_Input.H autodoc.o: ../FL/Fl_Input_.H autodoc.o: ../FL/Fl_Input_Choice.H autodoc.o: ../FL/Fl_Int_Input.H autodoc.o: ../FL/Fl_Light_Button.H autodoc.o: ../FL/Fl_Menu_.H autodoc.o: ../FL/Fl_Menu_Bar.H autodoc.o: ../FL/Fl_Menu_Button.H autodoc.o: ../FL/Fl_Menu_Item.H autodoc.o: ../FL/Fl_Multi_Label.H autodoc.o: ../FL/Fl_Native_File_Chooser.H autodoc.o: ../FL/Fl_Pack.H autodoc.o: ../FL/Fl_Pixmap.H autodoc.o: ../FL/Fl_Plugin.H autodoc.o: ../FL/Fl_PNG_Image.H autodoc.o: ../FL/Fl_Preferences.H autodoc.o: ../FL/Fl_Rect.H autodoc.o: ../FL/Fl_Repeat_Button.H autodoc.o: ../FL/Fl_Return_Button.H autodoc.o: ../FL/Fl_RGB_Image.H autodoc.o: ../FL/Fl_Scheme.H autodoc.o: ../FL/Fl_Scheme_Choice.H autodoc.o: ../FL/Fl_Scrollbar.H autodoc.o: ../FL/Fl_Shared_Image.H autodoc.o: ../FL/Fl_Shortcut_Button.H autodoc.o: ../FL/fl_show_colormap.H autodoc.o: ../FL/Fl_Slider.H autodoc.o: ../FL/Fl_Spinner.H autodoc.o: ../FL/fl_string_functions.h autodoc.o: ../FL/Fl_Tabs.H autodoc.o: ../FL/Fl_Terminal.H autodoc.o: ../FL/Fl_Text_Buffer.H autodoc.o: ../FL/Fl_Text_Display.H autodoc.o: ../FL/Fl_Text_Editor.H autodoc.o: ../FL/Fl_Tile.H autodoc.o: ../FL/fl_types.h autodoc.o: ../FL/fl_utf8.h autodoc.o: ../FL/Fl_Valuator.H autodoc.o: ../FL/Fl_Value_Input.H autodoc.o: ../FL/Fl_Widget.H autodoc.o: ../FL/Fl_Widget_Surface.H autodoc.o: ../FL/Fl_Window.H autodoc.o: ../FL/Fl_Wizard.H autodoc.o: ../FL/platform_types.h autodoc.o: ../src/Fl_String.H autodoc.o: autodoc.h autodoc.o: code.h autodoc.o: CodeEditor.h autodoc.o: codeview_panel.h autodoc.o: custom_widgets.h autodoc.o: factory.h autodoc.o: Fd_Snap_Action.h autodoc.o: fluid.h autodoc.o: fluid_filename.h autodoc.o: Fl_Group_Type.h autodoc.o: Fl_Type.h autodoc.o: Fl_Widget_Type.h autodoc.o: Fl_Window_Type.h autodoc.o: function_panel.h autodoc.o: settings_panel.h autodoc.o: shell_command.h autodoc.o: StyleParse.h autodoc.o: widget_browser.h autodoc.o: widget_panel.h code.o: ../config.h code.o: ../FL/Enumerations.H code.o: ../FL/filename.H code.o: ../FL/Fl.H code.o: ../FL/fl_ask.H code.o: ../FL/fl_attr.h code.o: ../FL/Fl_Bitmap.H code.o: ../FL/Fl_Cairo.H code.o: ../FL/fl_casts.H code.o: ../FL/fl_config.h code.o: ../FL/Fl_Device.H code.o: ../FL/fl_draw.H code.o: ../FL/Fl_Export.H code.o: ../FL/Fl_Flex.H code.o: ../FL/Fl_Graphics_Driver.H code.o: ../FL/Fl_Group.H code.o: ../FL/Fl_Image.H code.o: ../FL/Fl_Menu.H code.o: ../FL/Fl_Menu_Item.H code.o: ../FL/Fl_Multi_Label.H code.o: ../FL/Fl_Pack.H code.o: ../FL/Fl_Pixmap.H code.o: ../FL/Fl_Plugin.H code.o: ../FL/Fl_Preferences.H code.o: ../FL/Fl_Rect.H code.o: ../FL/Fl_RGB_Image.H code.o: ../FL/Fl_Shared_Image.H code.o: ../FL/fl_string_functions.h code.o: ../FL/Fl_Tabs.H code.o: ../FL/fl_types.h code.o: ../FL/fl_utf8.h code.o: ../FL/Fl_Widget.H code.o: ../FL/Fl_Wizard.H code.o: ../FL/platform_types.h code.o: ../src/flstring.h code.o: ../src/Fl_String.H code.o: code.h code.o: ExternalCodeEditor_UNIX.h code.o: file.h code.o: fluid.h code.o: fluid_filename.h code.o: Fluid_Image.h code.o: Fl_Function_Type.h code.o: Fl_Group_Type.h code.o: Fl_Type.h code.o: Fl_Widget_Type.h code.o: Fl_Window_Type.h code.o: undo.h CodeEditor.o: ../FL/Enumerations.H CodeEditor.o: ../FL/Fl.H CodeEditor.o: ../FL/fl_attr.h CodeEditor.o: ../FL/Fl_Bitmap.H CodeEditor.o: ../FL/Fl_Cairo.H CodeEditor.o: ../FL/fl_casts.H CodeEditor.o: ../FL/fl_config.h CodeEditor.o: ../FL/Fl_Device.H CodeEditor.o: ../FL/fl_draw.H CodeEditor.o: ../FL/Fl_Export.H CodeEditor.o: ../FL/Fl_Graphics_Driver.H CodeEditor.o: ../FL/Fl_Group.H CodeEditor.o: ../FL/Fl_Image.H CodeEditor.o: ../FL/Fl_Pixmap.H CodeEditor.o: ../FL/Fl_Plugin.H CodeEditor.o: ../FL/Fl_Preferences.H CodeEditor.o: ../FL/Fl_Rect.H CodeEditor.o: ../FL/Fl_RGB_Image.H CodeEditor.o: ../FL/Fl_Scrollbar.H CodeEditor.o: ../FL/Fl_Slider.H CodeEditor.o: ../FL/Fl_Text_Buffer.H CodeEditor.o: ../FL/Fl_Text_Display.H CodeEditor.o: ../FL/Fl_Text_Editor.H CodeEditor.o: ../FL/fl_types.h CodeEditor.o: ../FL/fl_utf8.h CodeEditor.o: ../FL/Fl_Valuator.H CodeEditor.o: ../FL/Fl_Widget.H CodeEditor.o: ../FL/platform_types.h CodeEditor.o: CodeEditor.h CodeEditor.o: StyleParse.h codeview_panel.o: ../config.h codeview_panel.o: ../FL/Enumerations.H codeview_panel.o: ../FL/filename.H codeview_panel.o: ../FL/Fl.H codeview_panel.o: ../FL/fl_attr.h codeview_panel.o: ../FL/Fl_Bitmap.H codeview_panel.o: ../FL/Fl_Box.H codeview_panel.o: ../FL/Fl_Button.H codeview_panel.o: ../FL/Fl_Cairo.H codeview_panel.o: ../FL/fl_casts.H codeview_panel.o: ../FL/Fl_Choice.H codeview_panel.o: ../FL/fl_config.h codeview_panel.o: ../FL/Fl_Device.H codeview_panel.o: ../FL/Fl_Double_Window.H codeview_panel.o: ../FL/fl_draw.H codeview_panel.o: ../FL/Fl_Export.H codeview_panel.o: ../FL/Fl_Graphics_Driver.H codeview_panel.o: ../FL/Fl_Group.H codeview_panel.o: ../FL/Fl_Image.H codeview_panel.o: ../FL/Fl_Input.H codeview_panel.o: ../FL/Fl_Input_.H codeview_panel.o: ../FL/Fl_Light_Button.H codeview_panel.o: ../FL/Fl_Menu_.H codeview_panel.o: ../FL/Fl_Menu_Item.H codeview_panel.o: ../FL/Fl_Multi_Label.H codeview_panel.o: ../FL/Fl_Pixmap.H codeview_panel.o: ../FL/Fl_Plugin.H codeview_panel.o: ../FL/Fl_Preferences.H codeview_panel.o: ../FL/Fl_Rect.H codeview_panel.o: ../FL/Fl_RGB_Image.H codeview_panel.o: ../FL/Fl_Scrollbar.H codeview_panel.o: ../FL/Fl_Slider.H codeview_panel.o: ../FL/fl_string_functions.h codeview_panel.o: ../FL/Fl_Tabs.H codeview_panel.o: ../FL/Fl_Text_Buffer.H codeview_panel.o: ../FL/Fl_Text_Display.H codeview_panel.o: ../FL/Fl_Text_Editor.H codeview_panel.o: ../FL/fl_types.h codeview_panel.o: ../FL/fl_utf8.h codeview_panel.o: ../FL/Fl_Valuator.H codeview_panel.o: ../FL/Fl_Widget.H codeview_panel.o: ../FL/Fl_Window.H codeview_panel.o: ../FL/platform_types.h codeview_panel.o: ../src/flstring.h codeview_panel.o: ../src/Fl_String.H codeview_panel.o: code.h codeview_panel.o: CodeEditor.h codeview_panel.o: codeview_panel.h codeview_panel.o: file.h codeview_panel.o: fluid.h codeview_panel.o: fluid_filename.h codeview_panel.o: Fl_Type.h codeview_panel.o: StyleParse.h custom_widgets.o: ../config.h custom_widgets.o: ../FL/Enumerations.H custom_widgets.o: ../FL/filename.H custom_widgets.o: ../FL/Fl.H custom_widgets.o: ../FL/fl_attr.h custom_widgets.o: ../FL/Fl_Bitmap.H custom_widgets.o: ../FL/Fl_Box.H custom_widgets.o: ../FL/Fl_Browser_.H custom_widgets.o: ../FL/Fl_Button.H custom_widgets.o: ../FL/Fl_Cairo.H custom_widgets.o: ../FL/fl_casts.H custom_widgets.o: ../FL/Fl_Check_Button.H custom_widgets.o: ../FL/Fl_Choice.H custom_widgets.o: ../FL/fl_config.h custom_widgets.o: ../FL/Fl_Device.H custom_widgets.o: ../FL/Fl_Double_Window.H custom_widgets.o: ../FL/fl_draw.H custom_widgets.o: ../FL/Fl_Export.H custom_widgets.o: ../FL/Fl_Flex.H custom_widgets.o: ../FL/Fl_Graphics_Driver.H custom_widgets.o: ../FL/Fl_Group.H custom_widgets.o: ../FL/Fl_Image.H custom_widgets.o: ../FL/Fl_Input.H custom_widgets.o: ../FL/Fl_Input_.H custom_widgets.o: ../FL/Fl_Input_Choice.H custom_widgets.o: ../FL/Fl_Light_Button.H custom_widgets.o: ../FL/Fl_Menu_.H custom_widgets.o: ../FL/Fl_Menu_Button.H custom_widgets.o: ../FL/Fl_Menu_Item.H custom_widgets.o: ../FL/Fl_Multi_Label.H custom_widgets.o: ../FL/Fl_Pack.H custom_widgets.o: ../FL/Fl_Pixmap.H custom_widgets.o: ../FL/Fl_Plugin.H custom_widgets.o: ../FL/Fl_Preferences.H custom_widgets.o: ../FL/Fl_Rect.H custom_widgets.o: ../FL/Fl_Return_Button.H custom_widgets.o: ../FL/Fl_RGB_Image.H custom_widgets.o: ../FL/Fl_Scrollbar.H custom_widgets.o: ../FL/Fl_Shared_Image.H custom_widgets.o: ../FL/Fl_Shortcut_Button.H custom_widgets.o: ../FL/Fl_Slider.H custom_widgets.o: ../FL/fl_string_functions.h custom_widgets.o: ../FL/Fl_Tabs.H custom_widgets.o: ../FL/Fl_Text_Buffer.H custom_widgets.o: ../FL/Fl_Text_Display.H custom_widgets.o: ../FL/Fl_Text_Editor.H custom_widgets.o: ../FL/Fl_Tile.H custom_widgets.o: ../FL/fl_types.h custom_widgets.o: ../FL/fl_utf8.h custom_widgets.o: ../FL/Fl_Valuator.H custom_widgets.o: ../FL/Fl_Value_Input.H custom_widgets.o: ../FL/Fl_Widget.H custom_widgets.o: ../FL/Fl_Window.H custom_widgets.o: ../FL/Fl_Wizard.H custom_widgets.o: ../FL/platform.H custom_widgets.o: ../FL/platform_types.h custom_widgets.o: ../FL/x11.H custom_widgets.o: ../src/flstring.h custom_widgets.o: ../src/Fl_String.H custom_widgets.o: code.h custom_widgets.o: CodeEditor.h custom_widgets.o: custom_widgets.h custom_widgets.o: factory.h custom_widgets.o: fluid.h custom_widgets.o: fluid_filename.h custom_widgets.o: Fl_Group_Type.h custom_widgets.o: Fl_Type.h custom_widgets.o: Fl_Widget_Type.h custom_widgets.o: Fl_Window_Type.h custom_widgets.o: StyleParse.h custom_widgets.o: widget_browser.h custom_widgets.o: widget_panel.h ExternalCodeEditor_UNIX.o: ../FL/Enumerations.H ExternalCodeEditor_UNIX.o: ../FL/filename.H ExternalCodeEditor_UNIX.o: ../FL/Fl.H ExternalCodeEditor_UNIX.o: ../FL/fl_ask.H ExternalCodeEditor_UNIX.o: ../FL/fl_attr.h ExternalCodeEditor_UNIX.o: ../FL/Fl_Cairo.H ExternalCodeEditor_UNIX.o: ../FL/fl_casts.H ExternalCodeEditor_UNIX.o: ../FL/fl_config.h ExternalCodeEditor_UNIX.o: ../FL/Fl_Export.H ExternalCodeEditor_UNIX.o: ../FL/Fl_Image.H ExternalCodeEditor_UNIX.o: ../FL/Fl_Menu_Item.H ExternalCodeEditor_UNIX.o: ../FL/Fl_Multi_Label.H ExternalCodeEditor_UNIX.o: ../FL/Fl_Preferences.H ExternalCodeEditor_UNIX.o: ../FL/fl_string_functions.h ExternalCodeEditor_UNIX.o: ../FL/fl_types.h ExternalCodeEditor_UNIX.o: ../FL/fl_utf8.h ExternalCodeEditor_UNIX.o: ../FL/Fl_Widget.H ExternalCodeEditor_UNIX.o: ../FL/platform_types.h ExternalCodeEditor_UNIX.o: ../src/Fl_String.H ExternalCodeEditor_UNIX.o: ExternalCodeEditor_UNIX.h ExternalCodeEditor_UNIX.o: fluid.h ExternalCodeEditor_UNIX.o: fluid_filename.h factory.o: ../config.h factory.o: ../FL/Enumerations.H factory.o: ../FL/filename.H factory.o: ../FL/Fl.H factory.o: ../FL/Fl_Adjuster.H factory.o: ../FL/fl_attr.h factory.o: ../FL/Fl_Bitmap.H factory.o: ../FL/Fl_Box.H factory.o: ../FL/Fl_Browser.H factory.o: ../FL/Fl_Browser_.H factory.o: ../FL/Fl_Button.H factory.o: ../FL/Fl_Cairo.H factory.o: ../FL/fl_casts.H factory.o: ../FL/Fl_Check_Browser.H factory.o: ../FL/Fl_Choice.H factory.o: ../FL/Fl_Clock.H factory.o: ../FL/fl_config.h factory.o: ../FL/Fl_Counter.H factory.o: ../FL/Fl_Device.H factory.o: ../FL/Fl_Dial.H factory.o: ../FL/fl_draw.H factory.o: ../FL/Fl_Export.H factory.o: ../FL/Fl_File_Browser.H factory.o: ../FL/Fl_File_Icon.H factory.o: ../FL/Fl_File_Input.H factory.o: ../FL/Fl_Flex.H factory.o: ../FL/Fl_Graphics_Driver.H factory.o: ../FL/Fl_Grid.H factory.o: ../FL/Fl_Group.H factory.o: ../FL/Fl_Help_View.H factory.o: ../FL/Fl_Image.H factory.o: ../FL/Fl_Input.H factory.o: ../FL/Fl_Input_.H factory.o: ../FL/Fl_Input_Choice.H factory.o: ../FL/Fl_Menu_.H factory.o: ../FL/Fl_Menu_Bar.H factory.o: ../FL/Fl_Menu_Button.H factory.o: ../FL/Fl_Menu_Item.H factory.o: ../FL/Fl_Multi_Label.H factory.o: ../FL/Fl_Output.H factory.o: ../FL/Fl_Pack.H factory.o: ../FL/Fl_Pixmap.H factory.o: ../FL/Fl_Plugin.H factory.o: ../FL/Fl_Preferences.H factory.o: ../FL/Fl_Progress.H factory.o: ../FL/Fl_Rect.H factory.o: ../FL/Fl_Repeat_Button.H factory.o: ../FL/Fl_RGB_Image.H factory.o: ../FL/Fl_Roller.H factory.o: ../FL/Fl_Scrollbar.H factory.o: ../FL/Fl_Slider.H factory.o: ../FL/Fl_Spinner.H factory.o: ../FL/fl_string_functions.h factory.o: ../FL/Fl_Tabs.H factory.o: ../FL/Fl_Terminal.H factory.o: ../FL/Fl_Text_Buffer.H factory.o: ../FL/Fl_Text_Display.H factory.o: ../FL/Fl_Text_Editor.H factory.o: ../FL/Fl_Tree.H factory.o: ../FL/Fl_Tree_Item.H factory.o: ../FL/Fl_Tree_Item_Array.H factory.o: ../FL/Fl_Tree_Prefs.H factory.o: ../FL/fl_types.h factory.o: ../FL/fl_utf8.h factory.o: ../FL/Fl_Valuator.H factory.o: ../FL/Fl_Value_Input.H factory.o: ../FL/Fl_Value_Output.H factory.o: ../FL/Fl_Value_Slider.H factory.o: ../FL/Fl_Widget.H factory.o: ../FL/Fl_Window.H factory.o: ../FL/Fl_Wizard.H factory.o: ../FL/platform_types.h factory.o: ../src/flstring.h factory.o: ../src/Fl_String.H factory.o: code.h factory.o: factory.h factory.o: Fd_Snap_Action.h factory.o: fluid.h factory.o: fluid_filename.h factory.o: Fl_Button_Type.h factory.o: Fl_Grid_Type.h factory.o: Fl_Group_Type.h factory.o: Fl_Menu_Type.h factory.o: Fl_Type.h factory.o: Fl_Widget_Type.h factory.o: Fl_Window_Type.h factory.o: pixmaps.h factory.o: undo.h Fd_Snap_Action.o: ../FL/Enumerations.H Fd_Snap_Action.o: ../FL/filename.H Fd_Snap_Action.o: ../FL/Fl.H Fd_Snap_Action.o: ../FL/fl_ask.H Fd_Snap_Action.o: ../FL/fl_attr.h Fd_Snap_Action.o: ../FL/Fl_Bitmap.H Fd_Snap_Action.o: ../FL/Fl_Box.H Fd_Snap_Action.o: ../FL/Fl_Browser.H Fd_Snap_Action.o: ../FL/Fl_Browser_.H Fd_Snap_Action.o: ../FL/Fl_Button.H Fd_Snap_Action.o: ../FL/Fl_Cairo.H Fd_Snap_Action.o: ../FL/fl_casts.H Fd_Snap_Action.o: ../FL/Fl_Check_Button.H Fd_Snap_Action.o: ../FL/Fl_Choice.H Fd_Snap_Action.o: ../FL/fl_config.h Fd_Snap_Action.o: ../FL/Fl_Device.H Fd_Snap_Action.o: ../FL/Fl_Double_Window.H Fd_Snap_Action.o: ../FL/fl_draw.H Fd_Snap_Action.o: ../FL/Fl_Export.H Fd_Snap_Action.o: ../FL/Fl_File_Browser.H Fd_Snap_Action.o: ../FL/Fl_File_Chooser.H Fd_Snap_Action.o: ../FL/Fl_File_Icon.H Fd_Snap_Action.o: ../FL/Fl_File_Input.H Fd_Snap_Action.o: ../FL/Fl_Flex.H Fd_Snap_Action.o: ../FL/Fl_Graphics_Driver.H Fd_Snap_Action.o: ../FL/Fl_Group.H Fd_Snap_Action.o: ../FL/Fl_Image.H Fd_Snap_Action.o: ../FL/Fl_Input.H Fd_Snap_Action.o: ../FL/Fl_Input_.H Fd_Snap_Action.o: ../FL/Fl_Int_Input.H Fd_Snap_Action.o: ../FL/Fl_Light_Button.H Fd_Snap_Action.o: ../FL/Fl_Menu_.H Fd_Snap_Action.o: ../FL/Fl_Menu_Bar.H Fd_Snap_Action.o: ../FL/Fl_Menu_Button.H Fd_Snap_Action.o: ../FL/Fl_Menu_Item.H Fd_Snap_Action.o: ../FL/Fl_Multi_Label.H Fd_Snap_Action.o: ../FL/Fl_Native_File_Chooser.H Fd_Snap_Action.o: ../FL/Fl_Pack.H Fd_Snap_Action.o: ../FL/Fl_Pixmap.H Fd_Snap_Action.o: ../FL/Fl_Plugin.H Fd_Snap_Action.o: ../FL/Fl_Preferences.H Fd_Snap_Action.o: ../FL/Fl_Rect.H Fd_Snap_Action.o: ../FL/Fl_Repeat_Button.H Fd_Snap_Action.o: ../FL/Fl_Return_Button.H Fd_Snap_Action.o: ../FL/Fl_RGB_Image.H Fd_Snap_Action.o: ../FL/Fl_Scheme.H Fd_Snap_Action.o: ../FL/Fl_Scheme_Choice.H Fd_Snap_Action.o: ../FL/Fl_Scrollbar.H Fd_Snap_Action.o: ../FL/Fl_Shortcut_Button.H Fd_Snap_Action.o: ../FL/fl_show_colormap.H Fd_Snap_Action.o: ../FL/Fl_Slider.H Fd_Snap_Action.o: ../FL/Fl_Spinner.H Fd_Snap_Action.o: ../FL/fl_string_functions.h Fd_Snap_Action.o: ../FL/Fl_Tabs.H Fd_Snap_Action.o: ../FL/Fl_Terminal.H Fd_Snap_Action.o: ../FL/Fl_Text_Buffer.H Fd_Snap_Action.o: ../FL/Fl_Text_Display.H Fd_Snap_Action.o: ../FL/Fl_Text_Editor.H Fd_Snap_Action.o: ../FL/Fl_Tile.H Fd_Snap_Action.o: ../FL/fl_types.h Fd_Snap_Action.o: ../FL/fl_utf8.h Fd_Snap_Action.o: ../FL/Fl_Valuator.H Fd_Snap_Action.o: ../FL/Fl_Value_Input.H Fd_Snap_Action.o: ../FL/Fl_Widget.H Fd_Snap_Action.o: ../FL/Fl_Window.H Fd_Snap_Action.o: ../FL/Fl_Wizard.H Fd_Snap_Action.o: ../FL/platform_types.h Fd_Snap_Action.o: ../src/Fl_String.H Fd_Snap_Action.o: code.h Fd_Snap_Action.o: Fd_Snap_Action.h Fd_Snap_Action.o: file.h Fd_Snap_Action.o: fluid.h Fd_Snap_Action.o: fluid_filename.h Fd_Snap_Action.o: Fl_Group_Type.h Fd_Snap_Action.o: Fl_Type.h Fd_Snap_Action.o: Fl_Widget_Type.h Fd_Snap_Action.o: Fl_Window_Type.h Fd_Snap_Action.o: settings_panel.h Fd_Snap_Action.o: shell_command.h Fd_Snap_Action.o: widget_browser.h file.o: ../config.h file.o: ../FL/Enumerations.H file.o: ../FL/filename.H file.o: ../FL/Fl.H file.o: ../FL/fl_ask.H file.o: ../FL/fl_attr.h file.o: ../FL/Fl_Bitmap.H file.o: ../FL/Fl_Box.H file.o: ../FL/Fl_Browser.H file.o: ../FL/Fl_Browser_.H file.o: ../FL/Fl_Button.H file.o: ../FL/Fl_Cairo.H file.o: ../FL/fl_casts.H file.o: ../FL/Fl_Check_Button.H file.o: ../FL/Fl_Choice.H file.o: ../FL/fl_config.h file.o: ../FL/Fl_Device.H file.o: ../FL/Fl_Double_Window.H file.o: ../FL/fl_draw.H file.o: ../FL/Fl_Export.H file.o: ../FL/Fl_File_Browser.H file.o: ../FL/Fl_File_Chooser.H file.o: ../FL/Fl_File_Icon.H file.o: ../FL/Fl_File_Input.H file.o: ../FL/Fl_Flex.H file.o: ../FL/Fl_Graphics_Driver.H file.o: ../FL/Fl_Grid.H file.o: ../FL/Fl_Group.H file.o: ../FL/Fl_Image.H file.o: ../FL/Fl_Input.H file.o: ../FL/Fl_Input_.H file.o: ../FL/Fl_Int_Input.H file.o: ../FL/Fl_Light_Button.H file.o: ../FL/Fl_Menu.H file.o: ../FL/Fl_Menu_.H file.o: ../FL/Fl_Menu_Button.H file.o: ../FL/Fl_Menu_Item.H file.o: ../FL/fl_message.H file.o: ../FL/Fl_Multi_Label.H file.o: ../FL/Fl_Native_File_Chooser.H file.o: ../FL/Fl_Pack.H file.o: ../FL/Fl_Pixmap.H file.o: ../FL/Fl_Plugin.H file.o: ../FL/Fl_Preferences.H file.o: ../FL/Fl_Rect.H file.o: ../FL/Fl_Repeat_Button.H file.o: ../FL/Fl_Return_Button.H file.o: ../FL/Fl_RGB_Image.H file.o: ../FL/Fl_Scheme.H file.o: ../FL/Fl_Scheme_Choice.H file.o: ../FL/Fl_Scrollbar.H file.o: ../FL/Fl_Shared_Image.H file.o: ../FL/Fl_Shortcut_Button.H file.o: ../FL/fl_show_colormap.H file.o: ../FL/Fl_Slider.H file.o: ../FL/Fl_Spinner.H file.o: ../FL/fl_string_functions.h file.o: ../FL/Fl_Tabs.H file.o: ../FL/Fl_Terminal.H file.o: ../FL/Fl_Text_Buffer.H file.o: ../FL/Fl_Text_Display.H file.o: ../FL/Fl_Text_Editor.H file.o: ../FL/Fl_Tile.H file.o: ../FL/fl_types.h file.o: ../FL/fl_utf8.h file.o: ../FL/Fl_Valuator.H file.o: ../FL/Fl_Value_Input.H file.o: ../FL/Fl_Widget.H file.o: ../FL/Fl_Window.H file.o: ../FL/Fl_Wizard.H file.o: ../FL/platform_types.h file.o: ../src/flstring.h file.o: ../src/Fl_String.H file.o: code.h file.o: ExternalCodeEditor_UNIX.h file.o: factory.h file.o: Fd_Snap_Action.h file.o: file.h file.o: fluid.h file.o: fluid_filename.h file.o: Fluid_Image.h file.o: Fl_Function_Type.h file.o: Fl_Grid_Type.h file.o: Fl_Group_Type.h file.o: Fl_Type.h file.o: Fl_Widget_Type.h file.o: Fl_Window_Type.h file.o: settings_panel.h file.o: shell_command.h file.o: undo.h file.o: widget_browser.h fluid.o: ../config.h fluid.o: ../FL/Enumerations.H fluid.o: ../FL/filename.H fluid.o: ../FL/Fl.H fluid.o: ../FL/fl_ask.H fluid.o: ../FL/fl_attr.h fluid.o: ../FL/Fl_Bitmap.H fluid.o: ../FL/Fl_Box.H fluid.o: ../FL/Fl_Browser.H fluid.o: ../FL/Fl_Browser_.H fluid.o: ../FL/Fl_Button.H fluid.o: ../FL/Fl_Cairo.H fluid.o: ../FL/fl_casts.H fluid.o: ../FL/Fl_Check_Button.H fluid.o: ../FL/Fl_Choice.H fluid.o: ../FL/fl_config.h fluid.o: ../FL/Fl_Device.H fluid.o: ../FL/Fl_Double_Window.H fluid.o: ../FL/fl_draw.H fluid.o: ../FL/Fl_Export.H fluid.o: ../FL/Fl_File_Browser.H fluid.o: ../FL/Fl_File_Chooser.H fluid.o: ../FL/Fl_File_Icon.H fluid.o: ../FL/Fl_File_Input.H fluid.o: ../FL/Fl_Flex.H fluid.o: ../FL/Fl_Graphics_Driver.H fluid.o: ../FL/Fl_Group.H fluid.o: ../FL/Fl_Help_Dialog.H fluid.o: ../FL/Fl_Help_View.H fluid.o: ../FL/Fl_Image.H fluid.o: ../FL/Fl_Input.H fluid.o: ../FL/Fl_Input_.H fluid.o: ../FL/Fl_Int_Input.H fluid.o: ../FL/Fl_Light_Button.H fluid.o: ../FL/Fl_Menu.H fluid.o: ../FL/Fl_Menu_.H fluid.o: ../FL/Fl_Menu_Bar.H fluid.o: ../FL/Fl_Menu_Button.H fluid.o: ../FL/Fl_Menu_Item.H fluid.o: ../FL/Fl_Multi_Label.H fluid.o: ../FL/Fl_Native_File_Chooser.H fluid.o: ../FL/Fl_Pack.H fluid.o: ../FL/Fl_Paged_Device.H fluid.o: ../FL/Fl_Pixmap.H fluid.o: ../FL/Fl_Plugin.H fluid.o: ../FL/Fl_PNG_Image.H fluid.o: ../FL/Fl_Preferences.H fluid.o: ../FL/Fl_Printer.H fluid.o: ../FL/Fl_Rect.H fluid.o: ../FL/Fl_Repeat_Button.H fluid.o: ../FL/Fl_Return_Button.H fluid.o: ../FL/Fl_RGB_Image.H fluid.o: ../FL/Fl_Scheme.H fluid.o: ../FL/Fl_Scheme_Choice.H fluid.o: ../FL/Fl_Scrollbar.H fluid.o: ../FL/Fl_Shared_Image.H fluid.o: ../FL/Fl_Shortcut_Button.H fluid.o: ../FL/fl_show_colormap.H fluid.o: ../FL/Fl_Slider.H fluid.o: ../FL/Fl_Spinner.H fluid.o: ../FL/fl_string_functions.h fluid.o: ../FL/Fl_Tabs.H fluid.o: ../FL/Fl_Terminal.H fluid.o: ../FL/Fl_Text_Buffer.H fluid.o: ../FL/Fl_Text_Display.H fluid.o: ../FL/Fl_Text_Editor.H fluid.o: ../FL/Fl_Tile.H fluid.o: ../FL/fl_types.h fluid.o: ../FL/fl_utf8.h fluid.o: ../FL/Fl_Valuator.H fluid.o: ../FL/Fl_Value_Input.H fluid.o: ../FL/Fl_Widget.H fluid.o: ../FL/Fl_Widget_Surface.H fluid.o: ../FL/Fl_Window.H fluid.o: ../FL/Fl_Wizard.H fluid.o: ../FL/platform_types.h fluid.o: ../src/flstring.h fluid.o: ../src/Fl_String.H fluid.o: about_panel.h fluid.o: autodoc.h fluid.o: code.h fluid.o: CodeEditor.h fluid.o: codeview_panel.h fluid.o: ExternalCodeEditor_UNIX.h fluid.o: factory.h fluid.o: Fd_Snap_Action.h fluid.o: file.h fluid.o: fluid.h fluid.o: fluid_filename.h fluid.o: Fluid_Image.h fluid.o: Fl_Function_Type.h fluid.o: Fl_Group_Type.h fluid.o: Fl_Type.h fluid.o: Fl_Widget_Type.h fluid.o: Fl_Window_Type.h fluid.o: function_panel.h fluid.o: mergeback.h fluid.o: pixmaps.h fluid.o: settings_panel.h fluid.o: shell_command.h fluid.o: StyleParse.h fluid.o: template_panel.h fluid.o: undo.h fluid.o: widget_browser.h fluid_filename.o: ../config.h fluid_filename.o: ../FL/Enumerations.H fluid_filename.o: ../FL/filename.H fluid_filename.o: ../FL/Fl.H fluid_filename.o: ../FL/fl_attr.h fluid_filename.o: ../FL/Fl_Cairo.H fluid_filename.o: ../FL/fl_casts.H fluid_filename.o: ../FL/fl_config.h fluid_filename.o: ../FL/Fl_Export.H fluid_filename.o: ../FL/fl_string_functions.h fluid_filename.o: ../FL/fl_types.h fluid_filename.o: ../FL/fl_utf8.h fluid_filename.o: ../FL/platform_types.h fluid_filename.o: ../src/flstring.h fluid_filename.o: ../src/Fl_String.H Fluid_Image.o: ../config.h Fluid_Image.o: ../FL/Enumerations.H Fluid_Image.o: ../FL/filename.H Fluid_Image.o: ../FL/Fl.H Fluid_Image.o: ../FL/Fl_Anim_GIF_Image.H Fluid_Image.o: ../FL/fl_ask.H Fluid_Image.o: ../FL/fl_attr.h Fluid_Image.o: ../FL/Fl_Bitmap.H Fluid_Image.o: ../FL/Fl_Box.H Fluid_Image.o: ../FL/Fl_Browser.H Fluid_Image.o: ../FL/Fl_Browser_.H Fluid_Image.o: ../FL/Fl_Button.H Fluid_Image.o: ../FL/Fl_Cairo.H Fluid_Image.o: ../FL/fl_casts.H Fluid_Image.o: ../FL/Fl_Check_Button.H Fluid_Image.o: ../FL/Fl_Choice.H Fluid_Image.o: ../FL/fl_config.h Fluid_Image.o: ../FL/Fl_Device.H Fluid_Image.o: ../FL/Fl_Double_Window.H Fluid_Image.o: ../FL/fl_draw.H Fluid_Image.o: ../FL/Fl_Export.H Fluid_Image.o: ../FL/Fl_File_Browser.H Fluid_Image.o: ../FL/Fl_File_Chooser.H Fluid_Image.o: ../FL/Fl_File_Icon.H Fluid_Image.o: ../FL/Fl_File_Input.H Fluid_Image.o: ../FL/Fl_Flex.H Fluid_Image.o: ../FL/Fl_GIF_Image.H Fluid_Image.o: ../FL/Fl_Graphics_Driver.H Fluid_Image.o: ../FL/Fl_Group.H Fluid_Image.o: ../FL/Fl_Image.H Fluid_Image.o: ../FL/Fl_Input.H Fluid_Image.o: ../FL/Fl_Input_.H Fluid_Image.o: ../FL/Fl_Light_Button.H Fluid_Image.o: ../FL/Fl_Menu_.H Fluid_Image.o: ../FL/Fl_Menu_Button.H Fluid_Image.o: ../FL/Fl_Menu_Item.H Fluid_Image.o: ../FL/Fl_Multi_Label.H Fluid_Image.o: ../FL/Fl_Pack.H Fluid_Image.o: ../FL/Fl_Pixmap.H Fluid_Image.o: ../FL/Fl_Plugin.H Fluid_Image.o: ../FL/Fl_Preferences.H Fluid_Image.o: ../FL/Fl_Rect.H Fluid_Image.o: ../FL/Fl_Return_Button.H Fluid_Image.o: ../FL/Fl_RGB_Image.H Fluid_Image.o: ../FL/Fl_Shared_Image.H Fluid_Image.o: ../FL/fl_string_functions.h Fluid_Image.o: ../FL/Fl_SVG_Image.H Fluid_Image.o: ../FL/Fl_Tabs.H Fluid_Image.o: ../FL/Fl_Tile.H Fluid_Image.o: ../FL/fl_types.h Fluid_Image.o: ../FL/fl_utf8.h Fluid_Image.o: ../FL/Fl_Widget.H Fluid_Image.o: ../FL/Fl_Window.H Fluid_Image.o: ../FL/Fl_Wizard.H Fluid_Image.o: ../FL/platform_types.h Fluid_Image.o: ../src/flstring.h Fluid_Image.o: ../src/Fl_String.H Fluid_Image.o: code.h Fluid_Image.o: file.h Fluid_Image.o: fluid.h Fluid_Image.o: fluid_filename.h Fluid_Image.o: Fluid_Image.h Fluid_Image.o: Fl_Group_Type.h Fluid_Image.o: Fl_Type.h Fluid_Image.o: Fl_Widget_Type.h Fluid_Image.o: Fl_Window_Type.h Fl_Button_Type.o: ../FL/Enumerations.H Fl_Button_Type.o: ../FL/filename.H Fl_Button_Type.o: ../FL/Fl.H Fl_Button_Type.o: ../FL/fl_attr.h Fl_Button_Type.o: ../FL/Fl_Bitmap.H Fl_Button_Type.o: ../FL/Fl_Button.H Fl_Button_Type.o: ../FL/Fl_Cairo.H Fl_Button_Type.o: ../FL/fl_casts.H Fl_Button_Type.o: ../FL/Fl_Check_Button.H Fl_Button_Type.o: ../FL/fl_config.h Fl_Button_Type.o: ../FL/Fl_Device.H Fl_Button_Type.o: ../FL/fl_draw.H Fl_Button_Type.o: ../FL/Fl_Export.H Fl_Button_Type.o: ../FL/Fl_Flex.H Fl_Button_Type.o: ../FL/Fl_Graphics_Driver.H Fl_Button_Type.o: ../FL/Fl_Group.H Fl_Button_Type.o: ../FL/Fl_Image.H Fl_Button_Type.o: ../FL/Fl_Light_Button.H Fl_Button_Type.o: ../FL/Fl_Menu_Item.H Fl_Button_Type.o: ../FL/Fl_Multi_Label.H Fl_Button_Type.o: ../FL/Fl_Pack.H Fl_Button_Type.o: ../FL/Fl_Pixmap.H Fl_Button_Type.o: ../FL/Fl_Plugin.H Fl_Button_Type.o: ../FL/Fl_Preferences.H Fl_Button_Type.o: ../FL/Fl_Rect.H Fl_Button_Type.o: ../FL/Fl_Repeat_Button.H Fl_Button_Type.o: ../FL/Fl_Return_Button.H Fl_Button_Type.o: ../FL/Fl_RGB_Image.H Fl_Button_Type.o: ../FL/Fl_Round_Button.H Fl_Button_Type.o: ../FL/Fl_Tabs.H Fl_Button_Type.o: ../FL/fl_types.h Fl_Button_Type.o: ../FL/fl_utf8.h Fl_Button_Type.o: ../FL/Fl_Widget.H Fl_Button_Type.o: ../FL/Fl_Wizard.H Fl_Button_Type.o: ../FL/platform_types.h Fl_Button_Type.o: ../src/Fl_String.H Fl_Button_Type.o: code.h Fl_Button_Type.o: Fd_Snap_Action.h Fl_Button_Type.o: file.h Fl_Button_Type.o: fluid.h Fl_Button_Type.o: fluid_filename.h Fl_Button_Type.o: Fl_Button_Type.h Fl_Button_Type.o: Fl_Group_Type.h Fl_Button_Type.o: Fl_Type.h Fl_Button_Type.o: Fl_Widget_Type.h Fl_Button_Type.o: Fl_Window_Type.h Fl_Function_Type.o: ../config.h Fl_Function_Type.o: ../FL/Enumerations.H Fl_Function_Type.o: ../FL/filename.H Fl_Function_Type.o: ../FL/Fl.H Fl_Function_Type.o: ../FL/fl_ask.H Fl_Function_Type.o: ../FL/fl_attr.h Fl_Function_Type.o: ../FL/Fl_Bitmap.H Fl_Function_Type.o: ../FL/Fl_Box.H Fl_Function_Type.o: ../FL/Fl_Browser.H Fl_Function_Type.o: ../FL/Fl_Browser_.H Fl_Function_Type.o: ../FL/Fl_Button.H Fl_Function_Type.o: ../FL/Fl_Cairo.H Fl_Function_Type.o: ../FL/fl_casts.H Fl_Function_Type.o: ../FL/Fl_Check_Button.H Fl_Function_Type.o: ../FL/Fl_Choice.H Fl_Function_Type.o: ../FL/fl_config.h Fl_Function_Type.o: ../FL/Fl_Device.H Fl_Function_Type.o: ../FL/Fl_Double_Window.H Fl_Function_Type.o: ../FL/fl_draw.H Fl_Function_Type.o: ../FL/Fl_Export.H Fl_Function_Type.o: ../FL/Fl_File_Browser.H Fl_Function_Type.o: ../FL/Fl_File_Chooser.H Fl_Function_Type.o: ../FL/Fl_File_Icon.H Fl_Function_Type.o: ../FL/Fl_File_Input.H Fl_Function_Type.o: ../FL/Fl_Flex.H Fl_Function_Type.o: ../FL/Fl_Graphics_Driver.H Fl_Function_Type.o: ../FL/Fl_Group.H Fl_Function_Type.o: ../FL/Fl_Image.H Fl_Function_Type.o: ../FL/Fl_Input.H Fl_Function_Type.o: ../FL/Fl_Input_.H Fl_Function_Type.o: ../FL/Fl_Light_Button.H Fl_Function_Type.o: ../FL/Fl_Menu.H Fl_Function_Type.o: ../FL/Fl_Menu_.H Fl_Function_Type.o: ../FL/Fl_Menu_Button.H Fl_Function_Type.o: ../FL/Fl_Menu_Item.H Fl_Function_Type.o: ../FL/Fl_Multi_Label.H Fl_Function_Type.o: ../FL/Fl_Pack.H Fl_Function_Type.o: ../FL/Fl_Pixmap.H Fl_Function_Type.o: ../FL/Fl_Plugin.H Fl_Function_Type.o: ../FL/Fl_Preferences.H Fl_Function_Type.o: ../FL/Fl_Rect.H Fl_Function_Type.o: ../FL/Fl_Return_Button.H Fl_Function_Type.o: ../FL/Fl_RGB_Image.H Fl_Function_Type.o: ../FL/Fl_Scrollbar.H Fl_Function_Type.o: ../FL/Fl_Shared_Image.H Fl_Function_Type.o: ../FL/Fl_Slider.H Fl_Function_Type.o: ../FL/fl_string_functions.h Fl_Function_Type.o: ../FL/Fl_Tabs.H Fl_Function_Type.o: ../FL/Fl_Text_Buffer.H Fl_Function_Type.o: ../FL/Fl_Text_Display.H Fl_Function_Type.o: ../FL/Fl_Text_Editor.H Fl_Function_Type.o: ../FL/Fl_Tile.H Fl_Function_Type.o: ../FL/fl_types.h Fl_Function_Type.o: ../FL/fl_utf8.h Fl_Function_Type.o: ../FL/Fl_Valuator.H Fl_Function_Type.o: ../FL/Fl_Widget.H Fl_Function_Type.o: ../FL/Fl_Window.H Fl_Function_Type.o: ../FL/Fl_Wizard.H Fl_Function_Type.o: ../FL/platform_types.h Fl_Function_Type.o: ../src/flstring.h Fl_Function_Type.o: ../src/Fl_String.H Fl_Function_Type.o: code.h Fl_Function_Type.o: CodeEditor.h Fl_Function_Type.o: comments.h Fl_Function_Type.o: ExternalCodeEditor_UNIX.h Fl_Function_Type.o: file.h Fl_Function_Type.o: fluid.h Fl_Function_Type.o: fluid_filename.h Fl_Function_Type.o: Fluid_Image.h Fl_Function_Type.o: Fl_Function_Type.h Fl_Function_Type.o: Fl_Group_Type.h Fl_Function_Type.o: Fl_Type.h Fl_Function_Type.o: Fl_Widget_Type.h Fl_Function_Type.o: Fl_Window_Type.h Fl_Function_Type.o: function_panel.h Fl_Function_Type.o: mergeback.h Fl_Function_Type.o: StyleParse.h Fl_Function_Type.o: undo.h Fl_Function_Type.o: widget_browser.h Fl_Grid_Type.o: ../config.h Fl_Grid_Type.o: ../FL/Enumerations.H Fl_Grid_Type.o: ../FL/filename.H Fl_Grid_Type.o: ../FL/Fl.H Fl_Grid_Type.o: ../FL/fl_attr.h Fl_Grid_Type.o: ../FL/Fl_Bitmap.H Fl_Grid_Type.o: ../FL/Fl_Browser_.H Fl_Grid_Type.o: ../FL/Fl_Button.H Fl_Grid_Type.o: ../FL/Fl_Cairo.H Fl_Grid_Type.o: ../FL/fl_casts.H Fl_Grid_Type.o: ../FL/Fl_Choice.H Fl_Grid_Type.o: ../FL/fl_config.h Fl_Grid_Type.o: ../FL/Fl_Device.H Fl_Grid_Type.o: ../FL/fl_draw.H Fl_Grid_Type.o: ../FL/Fl_Export.H Fl_Grid_Type.o: ../FL/Fl_Flex.H Fl_Grid_Type.o: ../FL/Fl_Graphics_Driver.H Fl_Grid_Type.o: ../FL/Fl_Grid.H Fl_Grid_Type.o: ../FL/Fl_Group.H Fl_Grid_Type.o: ../FL/Fl_Image.H Fl_Grid_Type.o: ../FL/Fl_Input.H Fl_Grid_Type.o: ../FL/Fl_Input_.H Fl_Grid_Type.o: ../FL/Fl_Menu_.H Fl_Grid_Type.o: ../FL/Fl_Menu_Item.H Fl_Grid_Type.o: ../FL/Fl_Multi_Label.H Fl_Grid_Type.o: ../FL/Fl_Pack.H Fl_Grid_Type.o: ../FL/Fl_Pixmap.H Fl_Grid_Type.o: ../FL/Fl_Plugin.H Fl_Grid_Type.o: ../FL/Fl_Preferences.H Fl_Grid_Type.o: ../FL/Fl_Rect.H Fl_Grid_Type.o: ../FL/Fl_RGB_Image.H Fl_Grid_Type.o: ../FL/Fl_Scrollbar.H Fl_Grid_Type.o: ../FL/Fl_Slider.H Fl_Grid_Type.o: ../FL/fl_string_functions.h Fl_Grid_Type.o: ../FL/Fl_Tabs.H Fl_Grid_Type.o: ../FL/fl_types.h Fl_Grid_Type.o: ../FL/fl_utf8.h Fl_Grid_Type.o: ../FL/Fl_Valuator.H Fl_Grid_Type.o: ../FL/Fl_Value_Input.H Fl_Grid_Type.o: ../FL/Fl_Widget.H Fl_Grid_Type.o: ../FL/Fl_Wizard.H Fl_Grid_Type.o: ../FL/platform_types.h Fl_Grid_Type.o: ../src/flstring.h Fl_Grid_Type.o: ../src/Fl_String.H Fl_Grid_Type.o: code.h Fl_Grid_Type.o: custom_widgets.h Fl_Grid_Type.o: Fd_Snap_Action.h Fl_Grid_Type.o: file.h Fl_Grid_Type.o: fluid.h Fl_Grid_Type.o: fluid_filename.h Fl_Grid_Type.o: Fl_Grid_Type.h Fl_Grid_Type.o: Fl_Group_Type.h Fl_Grid_Type.o: Fl_Type.h Fl_Grid_Type.o: Fl_Widget_Type.h Fl_Grid_Type.o: Fl_Window_Type.h Fl_Grid_Type.o: undo.h Fl_Grid_Type.o: widget_browser.h Fl_Group_Type.o: ../config.h Fl_Group_Type.o: ../FL/Enumerations.H Fl_Group_Type.o: ../FL/filename.H Fl_Group_Type.o: ../FL/Fl.H Fl_Group_Type.o: ../FL/fl_ask.H Fl_Group_Type.o: ../FL/fl_attr.h Fl_Group_Type.o: ../FL/Fl_Bitmap.H Fl_Group_Type.o: ../FL/Fl_Browser_.H Fl_Group_Type.o: ../FL/Fl_Cairo.H Fl_Group_Type.o: ../FL/fl_casts.H Fl_Group_Type.o: ../FL/fl_config.h Fl_Group_Type.o: ../FL/Fl_Device.H Fl_Group_Type.o: ../FL/fl_draw.H Fl_Group_Type.o: ../FL/Fl_Export.H Fl_Group_Type.o: ../FL/Fl_Flex.H Fl_Group_Type.o: ../FL/Fl_Graphics_Driver.H Fl_Group_Type.o: ../FL/Fl_Group.H Fl_Group_Type.o: ../FL/Fl_Image.H Fl_Group_Type.o: ../FL/Fl_Menu_Item.H Fl_Group_Type.o: ../FL/fl_message.H Fl_Group_Type.o: ../FL/Fl_Multi_Label.H Fl_Group_Type.o: ../FL/Fl_Pack.H Fl_Group_Type.o: ../FL/Fl_Pixmap.H Fl_Group_Type.o: ../FL/Fl_Plugin.H Fl_Group_Type.o: ../FL/Fl_Preferences.H Fl_Group_Type.o: ../FL/Fl_Rect.H Fl_Group_Type.o: ../FL/Fl_RGB_Image.H Fl_Group_Type.o: ../FL/Fl_Scroll.H Fl_Group_Type.o: ../FL/Fl_Scrollbar.H Fl_Group_Type.o: ../FL/Fl_Slider.H Fl_Group_Type.o: ../FL/fl_string_functions.h Fl_Group_Type.o: ../FL/Fl_Table.H Fl_Group_Type.o: ../FL/Fl_Tabs.H Fl_Group_Type.o: ../FL/fl_types.h Fl_Group_Type.o: ../FL/fl_utf8.h Fl_Group_Type.o: ../FL/Fl_Valuator.H Fl_Group_Type.o: ../FL/Fl_Widget.H Fl_Group_Type.o: ../FL/Fl_Wizard.H Fl_Group_Type.o: ../FL/platform_types.h Fl_Group_Type.o: ../src/flstring.h Fl_Group_Type.o: ../src/Fl_String.H Fl_Group_Type.o: code.h Fl_Group_Type.o: Fd_Snap_Action.h Fl_Group_Type.o: file.h Fl_Group_Type.o: fluid.h Fl_Group_Type.o: fluid_filename.h Fl_Group_Type.o: Fl_Group_Type.h Fl_Group_Type.o: Fl_Type.h Fl_Group_Type.o: Fl_Widget_Type.h Fl_Group_Type.o: Fl_Window_Type.h Fl_Group_Type.o: undo.h Fl_Group_Type.o: widget_browser.h Fl_Menu_Type.o: ../config.h Fl_Menu_Type.o: ../FL/Enumerations.H Fl_Menu_Type.o: ../FL/filename.H Fl_Menu_Type.o: ../FL/Fl.H Fl_Menu_Type.o: ../FL/fl_ask.H Fl_Menu_Type.o: ../FL/fl_attr.h Fl_Menu_Type.o: ../FL/Fl_Bitmap.H Fl_Menu_Type.o: ../FL/Fl_Browser_.H Fl_Menu_Type.o: ../FL/Fl_Button.H Fl_Menu_Type.o: ../FL/Fl_Cairo.H Fl_Menu_Type.o: ../FL/fl_casts.H Fl_Menu_Type.o: ../FL/Fl_Choice.H Fl_Menu_Type.o: ../FL/fl_config.h Fl_Menu_Type.o: ../FL/Fl_Device.H Fl_Menu_Type.o: ../FL/fl_draw.H Fl_Menu_Type.o: ../FL/Fl_Export.H Fl_Menu_Type.o: ../FL/Fl_Flex.H Fl_Menu_Type.o: ../FL/Fl_Graphics_Driver.H Fl_Menu_Type.o: ../FL/Fl_Group.H Fl_Menu_Type.o: ../FL/Fl_Image.H Fl_Menu_Type.o: ../FL/Fl_Input.H Fl_Menu_Type.o: ../FL/Fl_Input_.H Fl_Menu_Type.o: ../FL/Fl_Input_Choice.H Fl_Menu_Type.o: ../FL/Fl_Menu_.H Fl_Menu_Type.o: ../FL/Fl_Menu_Bar.H Fl_Menu_Type.o: ../FL/Fl_Menu_Button.H Fl_Menu_Type.o: ../FL/Fl_Menu_Item.H Fl_Menu_Type.o: ../FL/fl_message.H Fl_Menu_Type.o: ../FL/Fl_Multi_Label.H Fl_Menu_Type.o: ../FL/Fl_Output.H Fl_Menu_Type.o: ../FL/Fl_Pack.H Fl_Menu_Type.o: ../FL/Fl_Pixmap.H Fl_Menu_Type.o: ../FL/Fl_Plugin.H Fl_Menu_Type.o: ../FL/Fl_Preferences.H Fl_Menu_Type.o: ../FL/Fl_Rect.H Fl_Menu_Type.o: ../FL/Fl_RGB_Image.H Fl_Menu_Type.o: ../FL/Fl_Scrollbar.H Fl_Menu_Type.o: ../FL/Fl_Shared_Image.H Fl_Menu_Type.o: ../FL/Fl_Shortcut_Button.H Fl_Menu_Type.o: ../FL/Fl_Slider.H Fl_Menu_Type.o: ../FL/fl_string_functions.h Fl_Menu_Type.o: ../FL/Fl_Tabs.H Fl_Menu_Type.o: ../FL/Fl_Text_Buffer.H Fl_Menu_Type.o: ../FL/Fl_Text_Display.H Fl_Menu_Type.o: ../FL/fl_types.h Fl_Menu_Type.o: ../FL/fl_utf8.h Fl_Menu_Type.o: ../FL/Fl_Valuator.H Fl_Menu_Type.o: ../FL/Fl_Value_Input.H Fl_Menu_Type.o: ../FL/Fl_Widget.H Fl_Menu_Type.o: ../FL/Fl_Window.H Fl_Menu_Type.o: ../FL/Fl_Wizard.H Fl_Menu_Type.o: ../FL/platform_types.h Fl_Menu_Type.o: ../src/flstring.h Fl_Menu_Type.o: ../src/Fl_String.H Fl_Menu_Type.o: code.h Fl_Menu_Type.o: custom_widgets.h Fl_Menu_Type.o: Fd_Snap_Action.h Fl_Menu_Type.o: file.h Fl_Menu_Type.o: fluid.h Fl_Menu_Type.o: fluid_filename.h Fl_Menu_Type.o: Fluid_Image.h Fl_Menu_Type.o: Fl_Button_Type.h Fl_Menu_Type.o: Fl_Group_Type.h Fl_Menu_Type.o: Fl_Menu_Type.h Fl_Menu_Type.o: Fl_Type.h Fl_Menu_Type.o: Fl_Widget_Type.h Fl_Menu_Type.o: Fl_Window_Type.h Fl_Menu_Type.o: mergeback.h Fl_Menu_Type.o: undo.h Fl_Menu_Type.o: widget_browser.h Fl_Type.o: ../config.h Fl_Type.o: ../FL/Enumerations.H Fl_Type.o: ../FL/filename.H Fl_Type.o: ../FL/Fl.H Fl_Type.o: ../FL/fl_attr.h Fl_Type.o: ../FL/Fl_Bitmap.H Fl_Type.o: ../FL/Fl_Browser_.H Fl_Type.o: ../FL/Fl_Cairo.H Fl_Type.o: ../FL/fl_casts.H Fl_Type.o: ../FL/fl_config.h Fl_Type.o: ../FL/Fl_Device.H Fl_Type.o: ../FL/fl_draw.H Fl_Type.o: ../FL/Fl_Export.H Fl_Type.o: ../FL/Fl_Flex.H Fl_Type.o: ../FL/Fl_Graphics_Driver.H Fl_Type.o: ../FL/Fl_Group.H Fl_Type.o: ../FL/Fl_Image.H Fl_Type.o: ../FL/Fl_Menu.H Fl_Type.o: ../FL/Fl_Menu_Item.H Fl_Type.o: ../FL/Fl_Multi_Label.H Fl_Type.o: ../FL/Fl_Pack.H Fl_Type.o: ../FL/Fl_Pixmap.H Fl_Type.o: ../FL/Fl_Plugin.H Fl_Type.o: ../FL/Fl_Preferences.H Fl_Type.o: ../FL/Fl_Rect.H Fl_Type.o: ../FL/Fl_RGB_Image.H Fl_Type.o: ../FL/Fl_Scrollbar.H Fl_Type.o: ../FL/Fl_Shared_Image.H Fl_Type.o: ../FL/Fl_Slider.H Fl_Type.o: ../FL/fl_string_functions.h Fl_Type.o: ../FL/Fl_Tabs.H Fl_Type.o: ../FL/fl_types.h Fl_Type.o: ../FL/fl_utf8.h Fl_Type.o: ../FL/Fl_Valuator.H Fl_Type.o: ../FL/Fl_Widget.H Fl_Type.o: ../FL/Fl_Wizard.H Fl_Type.o: ../FL/platform_types.h Fl_Type.o: ../src/flstring.h Fl_Type.o: ../src/Fl_String.H Fl_Type.o: code.h Fl_Type.o: ExternalCodeEditor_UNIX.h Fl_Type.o: Fd_Snap_Action.h Fl_Type.o: file.h Fl_Type.o: fluid.h Fl_Type.o: fluid_filename.h Fl_Type.o: Fluid_Image.h Fl_Type.o: Fl_Function_Type.h Fl_Type.o: Fl_Group_Type.h Fl_Type.o: Fl_Type.h Fl_Type.o: Fl_Widget_Type.h Fl_Type.o: Fl_Window_Type.h Fl_Type.o: pixmaps.h Fl_Type.o: shell_command.h Fl_Type.o: undo.h Fl_Type.o: widget_browser.h Fl_Widget_Type.o: ../config.h Fl_Widget_Type.o: ../FL/Enumerations.H Fl_Widget_Type.o: ../FL/filename.H Fl_Widget_Type.o: ../FL/Fl.H Fl_Widget_Type.o: ../FL/fl_ask.H Fl_Widget_Type.o: ../FL/fl_attr.h Fl_Widget_Type.o: ../FL/Fl_Bitmap.H Fl_Widget_Type.o: ../FL/Fl_Box.H Fl_Widget_Type.o: ../FL/Fl_Browser.H Fl_Widget_Type.o: ../FL/Fl_Browser_.H Fl_Widget_Type.o: ../FL/Fl_Button.H Fl_Widget_Type.o: ../FL/Fl_Cairo.H Fl_Widget_Type.o: ../FL/fl_casts.H Fl_Widget_Type.o: ../FL/Fl_Check_Button.H Fl_Widget_Type.o: ../FL/Fl_Choice.H Fl_Widget_Type.o: ../FL/fl_config.h Fl_Widget_Type.o: ../FL/Fl_Device.H Fl_Widget_Type.o: ../FL/Fl_Double_Window.H Fl_Widget_Type.o: ../FL/fl_draw.H Fl_Widget_Type.o: ../FL/Fl_Export.H Fl_Widget_Type.o: ../FL/Fl_File_Browser.H Fl_Widget_Type.o: ../FL/Fl_File_Chooser.H Fl_Widget_Type.o: ../FL/Fl_File_Icon.H Fl_Widget_Type.o: ../FL/Fl_File_Input.H Fl_Widget_Type.o: ../FL/Fl_Flex.H Fl_Widget_Type.o: ../FL/Fl_Graphics_Driver.H Fl_Widget_Type.o: ../FL/Fl_Group.H Fl_Widget_Type.o: ../FL/Fl_Image.H Fl_Widget_Type.o: ../FL/Fl_Input.H Fl_Widget_Type.o: ../FL/Fl_Input_.H Fl_Widget_Type.o: ../FL/Fl_Input_Choice.H Fl_Widget_Type.o: ../FL/Fl_Int_Input.H Fl_Widget_Type.o: ../FL/Fl_Light_Button.H Fl_Widget_Type.o: ../FL/Fl_Menu.H Fl_Widget_Type.o: ../FL/Fl_Menu_.H Fl_Widget_Type.o: ../FL/Fl_Menu_Bar.H Fl_Widget_Type.o: ../FL/Fl_Menu_Button.H Fl_Widget_Type.o: ../FL/Fl_Menu_Item.H Fl_Widget_Type.o: ../FL/fl_message.H Fl_Widget_Type.o: ../FL/Fl_Multi_Label.H Fl_Widget_Type.o: ../FL/Fl_Native_File_Chooser.H Fl_Widget_Type.o: ../FL/Fl_Pack.H Fl_Widget_Type.o: ../FL/Fl_Pixmap.H Fl_Widget_Type.o: ../FL/Fl_Plugin.H Fl_Widget_Type.o: ../FL/Fl_Preferences.H Fl_Widget_Type.o: ../FL/Fl_Rect.H Fl_Widget_Type.o: ../FL/Fl_Repeat_Button.H Fl_Widget_Type.o: ../FL/Fl_Return_Button.H Fl_Widget_Type.o: ../FL/Fl_RGB_Image.H Fl_Widget_Type.o: ../FL/Fl_Scheme.H Fl_Widget_Type.o: ../FL/Fl_Scheme_Choice.H Fl_Widget_Type.o: ../FL/Fl_Scroll.H Fl_Widget_Type.o: ../FL/Fl_Scrollbar.H Fl_Widget_Type.o: ../FL/Fl_Shared_Image.H Fl_Widget_Type.o: ../FL/Fl_Shortcut_Button.H Fl_Widget_Type.o: ../FL/fl_show_colormap.H Fl_Widget_Type.o: ../FL/Fl_Slider.H Fl_Widget_Type.o: ../FL/Fl_Spinner.H Fl_Widget_Type.o: ../FL/fl_string_functions.h Fl_Widget_Type.o: ../FL/Fl_Table.H Fl_Widget_Type.o: ../FL/Fl_Tabs.H Fl_Widget_Type.o: ../FL/Fl_Terminal.H Fl_Widget_Type.o: ../FL/Fl_Text_Buffer.H Fl_Widget_Type.o: ../FL/Fl_Text_Display.H Fl_Widget_Type.o: ../FL/Fl_Text_Editor.H Fl_Widget_Type.o: ../FL/Fl_Tile.H Fl_Widget_Type.o: ../FL/fl_types.h Fl_Widget_Type.o: ../FL/fl_utf8.h Fl_Widget_Type.o: ../FL/Fl_Valuator.H Fl_Widget_Type.o: ../FL/Fl_Value_Input.H Fl_Widget_Type.o: ../FL/Fl_Widget.H Fl_Widget_Type.o: ../FL/Fl_Window.H Fl_Widget_Type.o: ../FL/Fl_Wizard.H Fl_Widget_Type.o: ../FL/platform_types.h Fl_Widget_Type.o: ../src/flstring.h Fl_Widget_Type.o: ../src/Fl_String.H Fl_Widget_Type.o: code.h Fl_Widget_Type.o: CodeEditor.h Fl_Widget_Type.o: custom_widgets.h Fl_Widget_Type.o: ExternalCodeEditor_UNIX.h Fl_Widget_Type.o: Fd_Snap_Action.h Fl_Widget_Type.o: file.h Fl_Widget_Type.o: fluid.h Fl_Widget_Type.o: fluid_filename.h Fl_Widget_Type.o: Fluid_Image.h Fl_Widget_Type.o: Fl_Button_Type.h Fl_Widget_Type.o: Fl_Function_Type.h Fl_Widget_Type.o: Fl_Group_Type.h Fl_Widget_Type.o: Fl_Menu_Type.h Fl_Widget_Type.o: Fl_Type.h Fl_Widget_Type.o: Fl_Widget_Type.h Fl_Widget_Type.o: Fl_Window_Type.h Fl_Widget_Type.o: mergeback.h Fl_Widget_Type.o: settings_panel.h Fl_Widget_Type.o: shell_command.h Fl_Widget_Type.o: StyleParse.h Fl_Widget_Type.o: undo.h Fl_Widget_Type.o: widget_browser.h Fl_Widget_Type.o: widget_panel.h Fl_Window_Type.o: ../config.h Fl_Window_Type.o: ../FL/Enumerations.H Fl_Window_Type.o: ../FL/filename.H Fl_Window_Type.o: ../FL/Fl.H Fl_Window_Type.o: ../FL/fl_ask.H Fl_Window_Type.o: ../FL/fl_attr.h Fl_Window_Type.o: ../FL/Fl_Bitmap.H Fl_Window_Type.o: ../FL/Fl_Box.H Fl_Window_Type.o: ../FL/Fl_Browser.H Fl_Window_Type.o: ../FL/Fl_Browser_.H Fl_Window_Type.o: ../FL/Fl_Button.H Fl_Window_Type.o: ../FL/Fl_Cairo.H Fl_Window_Type.o: ../FL/fl_casts.H Fl_Window_Type.o: ../FL/Fl_Check_Button.H Fl_Window_Type.o: ../FL/Fl_Choice.H Fl_Window_Type.o: ../FL/fl_config.h Fl_Window_Type.o: ../FL/Fl_Device.H Fl_Window_Type.o: ../FL/Fl_Double_Window.H Fl_Window_Type.o: ../FL/fl_draw.H Fl_Window_Type.o: ../FL/Fl_Export.H Fl_Window_Type.o: ../FL/Fl_File_Browser.H Fl_Window_Type.o: ../FL/Fl_File_Chooser.H Fl_Window_Type.o: ../FL/Fl_File_Icon.H Fl_Window_Type.o: ../FL/Fl_File_Input.H Fl_Window_Type.o: ../FL/Fl_Flex.H Fl_Window_Type.o: ../FL/Fl_Graphics_Driver.H Fl_Window_Type.o: ../FL/Fl_Grid.H Fl_Window_Type.o: ../FL/Fl_Group.H Fl_Window_Type.o: ../FL/Fl_Image.H Fl_Window_Type.o: ../FL/Fl_Input.H Fl_Window_Type.o: ../FL/Fl_Input_.H Fl_Window_Type.o: ../FL/Fl_Input_Choice.H Fl_Window_Type.o: ../FL/Fl_Int_Input.H Fl_Window_Type.o: ../FL/Fl_Light_Button.H Fl_Window_Type.o: ../FL/Fl_Menu_.H Fl_Window_Type.o: ../FL/Fl_Menu_Button.H Fl_Window_Type.o: ../FL/Fl_Menu_Item.H Fl_Window_Type.o: ../FL/fl_message.H Fl_Window_Type.o: ../FL/Fl_Multi_Label.H Fl_Window_Type.o: ../FL/Fl_Native_File_Chooser.H Fl_Window_Type.o: ../FL/Fl_Overlay_Window.H Fl_Window_Type.o: ../FL/Fl_Pack.H Fl_Window_Type.o: ../FL/Fl_Pixmap.H Fl_Window_Type.o: ../FL/Fl_Plugin.H Fl_Window_Type.o: ../FL/Fl_Preferences.H Fl_Window_Type.o: ../FL/Fl_Rect.H Fl_Window_Type.o: ../FL/Fl_Repeat_Button.H Fl_Window_Type.o: ../FL/Fl_Return_Button.H Fl_Window_Type.o: ../FL/Fl_RGB_Image.H Fl_Window_Type.o: ../FL/Fl_Round_Button.H Fl_Window_Type.o: ../FL/Fl_Scheme.H Fl_Window_Type.o: ../FL/Fl_Scheme_Choice.H Fl_Window_Type.o: ../FL/Fl_Scrollbar.H Fl_Window_Type.o: ../FL/Fl_Shared_Image.H Fl_Window_Type.o: ../FL/Fl_Shortcut_Button.H Fl_Window_Type.o: ../FL/fl_show_colormap.H Fl_Window_Type.o: ../FL/Fl_Slider.H Fl_Window_Type.o: ../FL/Fl_Spinner.H Fl_Window_Type.o: ../FL/fl_string_functions.h Fl_Window_Type.o: ../FL/Fl_Tabs.H Fl_Window_Type.o: ../FL/Fl_Terminal.H Fl_Window_Type.o: ../FL/Fl_Text_Buffer.H Fl_Window_Type.o: ../FL/Fl_Text_Display.H Fl_Window_Type.o: ../FL/Fl_Text_Editor.H Fl_Window_Type.o: ../FL/Fl_Tile.H Fl_Window_Type.o: ../FL/Fl_Tooltip.H Fl_Window_Type.o: ../FL/fl_types.h Fl_Window_Type.o: ../FL/fl_utf8.h Fl_Window_Type.o: ../FL/Fl_Valuator.H Fl_Window_Type.o: ../FL/Fl_Value_Input.H Fl_Window_Type.o: ../FL/Fl_Widget.H Fl_Window_Type.o: ../FL/Fl_Window.H Fl_Window_Type.o: ../FL/Fl_Wizard.H Fl_Window_Type.o: ../FL/platform.H Fl_Window_Type.o: ../FL/platform_types.h Fl_Window_Type.o: ../FL/x11.H Fl_Window_Type.o: ../src/flstring.h Fl_Window_Type.o: ../src/Fl_String.H Fl_Window_Type.o: code.h Fl_Window_Type.o: CodeEditor.h Fl_Window_Type.o: custom_widgets.h Fl_Window_Type.o: factory.h Fl_Window_Type.o: Fd_Snap_Action.h Fl_Window_Type.o: file.h Fl_Window_Type.o: fluid.h Fl_Window_Type.o: fluid_filename.h Fl_Window_Type.o: Fl_Grid_Type.h Fl_Window_Type.o: Fl_Group_Type.h Fl_Window_Type.o: Fl_Type.h Fl_Window_Type.o: Fl_Widget_Type.h Fl_Window_Type.o: Fl_Window_Type.h Fl_Window_Type.o: settings_panel.h Fl_Window_Type.o: shell_command.h Fl_Window_Type.o: StyleParse.h Fl_Window_Type.o: undo.h Fl_Window_Type.o: widget_browser.h Fl_Window_Type.o: widget_panel.h function_panel.o: ../FL/Enumerations.H function_panel.o: ../FL/filename.H function_panel.o: ../FL/Fl.H function_panel.o: ../FL/fl_attr.h function_panel.o: ../FL/Fl_Bitmap.H function_panel.o: ../FL/Fl_Box.H function_panel.o: ../FL/Fl_Browser_.H function_panel.o: ../FL/Fl_Button.H function_panel.o: ../FL/Fl_Cairo.H function_panel.o: ../FL/fl_casts.H function_panel.o: ../FL/Fl_Check_Button.H function_panel.o: ../FL/Fl_Choice.H function_panel.o: ../FL/fl_config.h function_panel.o: ../FL/Fl_Device.H function_panel.o: ../FL/Fl_Double_Window.H function_panel.o: ../FL/fl_draw.H function_panel.o: ../FL/Fl_Export.H function_panel.o: ../FL/Fl_Graphics_Driver.H function_panel.o: ../FL/Fl_Group.H function_panel.o: ../FL/Fl_Image.H function_panel.o: ../FL/Fl_Input.H function_panel.o: ../FL/Fl_Input_.H function_panel.o: ../FL/Fl_Light_Button.H function_panel.o: ../FL/Fl_Menu_.H function_panel.o: ../FL/Fl_Menu_Button.H function_panel.o: ../FL/Fl_Menu_Item.H function_panel.o: ../FL/Fl_Multi_Label.H function_panel.o: ../FL/Fl_Pixmap.H function_panel.o: ../FL/Fl_Plugin.H function_panel.o: ../FL/Fl_Preferences.H function_panel.o: ../FL/Fl_Rect.H function_panel.o: ../FL/Fl_Return_Button.H function_panel.o: ../FL/Fl_RGB_Image.H function_panel.o: ../FL/Fl_Scrollbar.H function_panel.o: ../FL/Fl_Slider.H function_panel.o: ../FL/Fl_Text_Buffer.H function_panel.o: ../FL/Fl_Text_Display.H function_panel.o: ../FL/Fl_Text_Editor.H function_panel.o: ../FL/Fl_Tile.H function_panel.o: ../FL/fl_types.h function_panel.o: ../FL/fl_utf8.h function_panel.o: ../FL/Fl_Valuator.H function_panel.o: ../FL/Fl_Widget.H function_panel.o: ../FL/Fl_Window.H function_panel.o: ../FL/platform_types.h function_panel.o: ../src/Fl_String.H function_panel.o: code.h function_panel.o: CodeEditor.h function_panel.o: custom_widgets.h function_panel.o: factory.h function_panel.o: fluid.h function_panel.o: fluid_filename.h function_panel.o: Fl_Type.h function_panel.o: function_panel.h function_panel.o: pixmaps.h function_panel.o: StyleParse.h function_panel.o: undo.h function_panel.o: widget_browser.h pixmaps.o: ../FL/Enumerations.H pixmaps.o: ../FL/Fl.H pixmaps.o: ../FL/fl_attr.h pixmaps.o: ../FL/Fl_Bitmap.H pixmaps.o: ../FL/fl_config.h pixmaps.o: ../FL/Fl_Device.H pixmaps.o: ../FL/fl_draw.H pixmaps.o: ../FL/Fl_Export.H pixmaps.o: ../FL/Fl_Graphics_Driver.H pixmaps.o: ../FL/Fl_Image.H pixmaps.o: ../FL/Fl_Pixmap.H pixmaps.o: ../FL/Fl_Plugin.H pixmaps.o: ../FL/Fl_Preferences.H pixmaps.o: ../FL/Fl_Rect.H pixmaps.o: ../FL/Fl_RGB_Image.H pixmaps.o: ../FL/fl_types.h pixmaps.o: ../FL/Fl_Widget.H pixmaps.o: ../FL/platform_types.h pixmaps.o: ../src/Fl_String.H pixmaps.o: code.h pixmaps.o: Fl_Type.h pixmaps.o: pixmaps.h pixmaps.o: pixmaps/bind.xpm pixmaps.o: pixmaps/compressed.xpm pixmaps.o: pixmaps/flAdjuster.xpm pixmaps.o: pixmaps/flBox.xpm pixmaps.o: pixmaps/flBrowser.xpm pixmaps.o: pixmaps/flButton.xpm pixmaps.o: pixmaps/flCheckBrowser.xpm pixmaps.o: pixmaps/flCheckButton.xpm pixmaps.o: pixmaps/flCheckMenuitem.xpm pixmaps.o: pixmaps/flChoice.xpm pixmaps.o: pixmaps/flClass.xpm pixmaps.o: pixmaps/flClock.xpm pixmaps.o: pixmaps/flCode.xpm pixmaps.o: pixmaps/flCodeBlock.xpm pixmaps.o: pixmaps/flComment.xpm pixmaps.o: pixmaps/flCounter.xpm pixmaps.o: pixmaps/flData.xpm pixmaps.o: pixmaps/flDeclaration.xpm pixmaps.o: pixmaps/flDeclarationBlock.xpm pixmaps.o: pixmaps/flDial.xpm pixmaps.o: pixmaps/flFileBrowser.xpm pixmaps.o: pixmaps/flFileInput.xpm pixmaps.o: pixmaps/flFlex.xpm pixmaps.o: pixmaps/flFunction.xpm pixmaps.o: pixmaps/flGrid.xpm pixmaps.o: pixmaps/flGroup.xpm pixmaps.o: pixmaps/flHelp.xpm pixmaps.o: pixmaps/flInput.xpm pixmaps.o: pixmaps/flInputChoice.xpm pixmaps.o: pixmaps/flLightButton.xpm pixmaps.o: pixmaps/flMenubar.xpm pixmaps.o: pixmaps/flMenuButton.xpm pixmaps.o: pixmaps/flMenuitem.xpm pixmaps.o: pixmaps/flOutput.xpm pixmaps.o: pixmaps/flPack.xpm pixmaps.o: pixmaps/flProgress.xpm pixmaps.o: pixmaps/flRadioMenuitem.xpm pixmaps.o: pixmaps/flRepeatButton.xpm pixmaps.o: pixmaps/flReturnButton.xpm pixmaps.o: pixmaps/flRoller.xpm pixmaps.o: pixmaps/flRoundButton.xpm pixmaps.o: pixmaps/flScroll.xpm pixmaps.o: pixmaps/flScrollBar.xpm pixmaps.o: pixmaps/flSimpleTerminal.xpm pixmaps.o: pixmaps/flSlider.xpm pixmaps.o: pixmaps/flSpinner.xpm pixmaps.o: pixmaps/flSubmenu.xpm pixmaps.o: pixmaps/flTable.xpm pixmaps.o: pixmaps/flTabs.xpm pixmaps.o: pixmaps/flTextDisplay.xpm pixmaps.o: pixmaps/flTextEdit.xpm pixmaps.o: pixmaps/flTile.xpm pixmaps.o: pixmaps/flTree.xpm pixmaps.o: pixmaps/flValueInput.xpm pixmaps.o: pixmaps/flValueOutput.xpm pixmaps.o: pixmaps/flValueSlider.xpm pixmaps.o: pixmaps/flWidgetClass.xpm pixmaps.o: pixmaps/flWindow.xpm pixmaps.o: pixmaps/flWizard.xpm pixmaps.o: pixmaps/invisible.xpm pixmaps.o: pixmaps/lock.xpm pixmaps.o: pixmaps/protected.xpm settings_panel.o: ../config.h settings_panel.o: ../FL/Enumerations.H settings_panel.o: ../FL/filename.H settings_panel.o: ../FL/Fl.H settings_panel.o: ../FL/fl_ask.H settings_panel.o: ../FL/fl_attr.h settings_panel.o: ../FL/Fl_Bitmap.H settings_panel.o: ../FL/Fl_Box.H settings_panel.o: ../FL/Fl_Browser.H settings_panel.o: ../FL/Fl_Browser_.H settings_panel.o: ../FL/Fl_Button.H settings_panel.o: ../FL/Fl_Cairo.H settings_panel.o: ../FL/fl_casts.H settings_panel.o: ../FL/Fl_Check_Button.H settings_panel.o: ../FL/Fl_Choice.H settings_panel.o: ../FL/fl_config.h settings_panel.o: ../FL/Fl_Device.H settings_panel.o: ../FL/Fl_Double_Window.H settings_panel.o: ../FL/fl_draw.H settings_panel.o: ../FL/Fl_Export.H settings_panel.o: ../FL/Fl_File_Browser.H settings_panel.o: ../FL/Fl_File_Chooser.H settings_panel.o: ../FL/Fl_File_Icon.H settings_panel.o: ../FL/Fl_File_Input.H settings_panel.o: ../FL/Fl_Flex.H settings_panel.o: ../FL/Fl_Graphics_Driver.H settings_panel.o: ../FL/Fl_Group.H settings_panel.o: ../FL/Fl_Image.H settings_panel.o: ../FL/Fl_Input.H settings_panel.o: ../FL/Fl_Input_.H settings_panel.o: ../FL/Fl_Int_Input.H settings_panel.o: ../FL/Fl_Light_Button.H settings_panel.o: ../FL/Fl_Menu_.H settings_panel.o: ../FL/Fl_Menu_Button.H settings_panel.o: ../FL/Fl_Menu_Item.H settings_panel.o: ../FL/Fl_Multi_Label.H settings_panel.o: ../FL/Fl_Native_File_Chooser.H settings_panel.o: ../FL/Fl_Pack.H settings_panel.o: ../FL/Fl_Pixmap.H settings_panel.o: ../FL/Fl_Plugin.H settings_panel.o: ../FL/Fl_PNG_Image.H settings_panel.o: ../FL/Fl_Preferences.H settings_panel.o: ../FL/Fl_Rect.H settings_panel.o: ../FL/Fl_Repeat_Button.H settings_panel.o: ../FL/Fl_Return_Button.H settings_panel.o: ../FL/Fl_RGB_Image.H settings_panel.o: ../FL/Fl_Scheme.H settings_panel.o: ../FL/Fl_Scheme_Choice.H settings_panel.o: ../FL/Fl_Scrollbar.H settings_panel.o: ../FL/Fl_Shortcut_Button.H settings_panel.o: ../FL/fl_show_colormap.H settings_panel.o: ../FL/Fl_Slider.H settings_panel.o: ../FL/Fl_Spinner.H settings_panel.o: ../FL/fl_string_functions.h settings_panel.o: ../FL/Fl_Tabs.H settings_panel.o: ../FL/Fl_Terminal.H settings_panel.o: ../FL/Fl_Text_Buffer.H settings_panel.o: ../FL/Fl_Text_Display.H settings_panel.o: ../FL/Fl_Text_Editor.H settings_panel.o: ../FL/Fl_Tile.H settings_panel.o: ../FL/Fl_Tooltip.H settings_panel.o: ../FL/fl_types.h settings_panel.o: ../FL/fl_utf8.h settings_panel.o: ../FL/Fl_Valuator.H settings_panel.o: ../FL/Fl_Value_Input.H settings_panel.o: ../FL/Fl_Widget.H settings_panel.o: ../FL/Fl_Window.H settings_panel.o: ../FL/Fl_Wizard.H settings_panel.o: ../FL/platform_types.h settings_panel.o: ../src/flstring.h settings_panel.o: ../src/Fl_String.H settings_panel.o: code.h settings_panel.o: Fd_Snap_Action.h settings_panel.o: fluid.h settings_panel.o: fluid_filename.h settings_panel.o: Fl_Group_Type.h settings_panel.o: Fl_Type.h settings_panel.o: Fl_Widget_Type.h settings_panel.o: Fl_Window_Type.h settings_panel.o: settings_panel.h settings_panel.o: shell_command.h settings_panel.o: undo.h settings_panel.o: widget_browser.h shell_command.o: ../FL/Enumerations.H shell_command.o: ../FL/filename.H shell_command.o: ../FL/Fl.H shell_command.o: ../FL/fl_ask.H shell_command.o: ../FL/fl_attr.h shell_command.o: ../FL/Fl_Bitmap.H shell_command.o: ../FL/Fl_Box.H shell_command.o: ../FL/Fl_Browser.H shell_command.o: ../FL/Fl_Browser_.H shell_command.o: ../FL/Fl_Button.H shell_command.o: ../FL/Fl_Cairo.H shell_command.o: ../FL/fl_casts.H shell_command.o: ../FL/Fl_Check_Button.H shell_command.o: ../FL/Fl_Choice.H shell_command.o: ../FL/fl_config.h shell_command.o: ../FL/Fl_Device.H shell_command.o: ../FL/Fl_Double_Window.H shell_command.o: ../FL/fl_draw.H shell_command.o: ../FL/Fl_Export.H shell_command.o: ../FL/Fl_File_Browser.H shell_command.o: ../FL/Fl_File_Chooser.H shell_command.o: ../FL/Fl_File_Icon.H shell_command.o: ../FL/Fl_File_Input.H shell_command.o: ../FL/Fl_Flex.H shell_command.o: ../FL/Fl_Graphics_Driver.H shell_command.o: ../FL/Fl_Group.H shell_command.o: ../FL/Fl_Image.H shell_command.o: ../FL/Fl_Input.H shell_command.o: ../FL/Fl_Input_.H shell_command.o: ../FL/Fl_Int_Input.H shell_command.o: ../FL/Fl_Light_Button.H shell_command.o: ../FL/Fl_Menu_.H shell_command.o: ../FL/Fl_Menu_Bar.H shell_command.o: ../FL/Fl_Menu_Button.H shell_command.o: ../FL/Fl_Menu_Item.H shell_command.o: ../FL/fl_message.H shell_command.o: ../FL/Fl_Multi_Label.H shell_command.o: ../FL/Fl_Native_File_Chooser.H shell_command.o: ../FL/Fl_Pack.H shell_command.o: ../FL/Fl_Pixmap.H shell_command.o: ../FL/Fl_Plugin.H shell_command.o: ../FL/Fl_Preferences.H shell_command.o: ../FL/Fl_Rect.H shell_command.o: ../FL/Fl_Repeat_Button.H shell_command.o: ../FL/Fl_Return_Button.H shell_command.o: ../FL/Fl_RGB_Image.H shell_command.o: ../FL/Fl_Scheme.H shell_command.o: ../FL/Fl_Scheme_Choice.H shell_command.o: ../FL/Fl_Scrollbar.H shell_command.o: ../FL/Fl_Shortcut_Button.H shell_command.o: ../FL/fl_show_colormap.H shell_command.o: ../FL/Fl_Slider.H shell_command.o: ../FL/Fl_Spinner.H shell_command.o: ../FL/fl_string_functions.h shell_command.o: ../FL/Fl_Tabs.H shell_command.o: ../FL/Fl_Terminal.H shell_command.o: ../FL/Fl_Text_Buffer.H shell_command.o: ../FL/Fl_Text_Display.H shell_command.o: ../FL/Fl_Text_Editor.H shell_command.o: ../FL/Fl_Tile.H shell_command.o: ../FL/fl_types.h shell_command.o: ../FL/fl_utf8.h shell_command.o: ../FL/Fl_Valuator.H shell_command.o: ../FL/Fl_Value_Input.H shell_command.o: ../FL/Fl_Widget.H shell_command.o: ../FL/Fl_Window.H shell_command.o: ../FL/Fl_Wizard.H shell_command.o: ../FL/platform_types.h shell_command.o: ../src/Fl_String.H shell_command.o: code.h shell_command.o: Fd_Snap_Action.h shell_command.o: file.h shell_command.o: fluid.h shell_command.o: fluid_filename.h shell_command.o: Fl_Group_Type.h shell_command.o: Fl_Type.h shell_command.o: Fl_Widget_Type.h shell_command.o: Fl_Window_Type.h shell_command.o: settings_panel.h shell_command.o: shell_command.h shell_command.o: widget_browser.h StyleParse.o: StyleParse.h template_panel.o: ../config.h template_panel.o: ../FL/Enumerations.H template_panel.o: ../FL/filename.H template_panel.o: ../FL/Fl.H template_panel.o: ../FL/fl_ask.H template_panel.o: ../FL/fl_attr.h template_panel.o: ../FL/Fl_Bitmap.H template_panel.o: ../FL/Fl_Box.H template_panel.o: ../FL/Fl_Browser.H template_panel.o: ../FL/Fl_Button.H template_panel.o: ../FL/Fl_Cairo.H template_panel.o: ../FL/fl_casts.H template_panel.o: ../FL/fl_config.h template_panel.o: ../FL/Fl_Double_Window.H template_panel.o: ../FL/Fl_Export.H template_panel.o: ../FL/Fl_Group.H template_panel.o: ../FL/Fl_Image.H template_panel.o: ../FL/Fl_Input.H template_panel.o: ../FL/Fl_Input_.H template_panel.o: ../FL/Fl_Menu_Item.H template_panel.o: ../FL/Fl_Multi_Label.H template_panel.o: ../FL/Fl_Preferences.H template_panel.o: ../FL/Fl_Return_Button.H template_panel.o: ../FL/Fl_Shared_Image.H template_panel.o: ../FL/fl_string_functions.h template_panel.o: ../FL/fl_types.h template_panel.o: ../FL/fl_utf8.h template_panel.o: ../FL/Fl_Widget.H template_panel.o: ../FL/Fl_Window.H template_panel.o: ../FL/platform_types.h template_panel.o: ../src/flstring.h template_panel.o: ../src/Fl_String.H template_panel.o: fluid.h template_panel.o: fluid_filename.h template_panel.o: template_panel.h undo.o: ../config.h undo.o: ../FL/Enumerations.H undo.o: ../FL/filename.H undo.o: ../FL/Fl.H undo.o: ../FL/fl_ask.H undo.o: ../FL/fl_attr.h undo.o: ../FL/Fl_Bitmap.H undo.o: ../FL/Fl_Browser_.H undo.o: ../FL/Fl_Cairo.H undo.o: ../FL/fl_casts.H undo.o: ../FL/fl_config.h undo.o: ../FL/Fl_Device.H undo.o: ../FL/fl_draw.H undo.o: ../FL/Fl_Export.H undo.o: ../FL/Fl_Graphics_Driver.H undo.o: ../FL/Fl_Image.H undo.o: ../FL/Fl_Menu_.H undo.o: ../FL/Fl_Menu_Bar.H undo.o: ../FL/Fl_Menu_Item.H undo.o: ../FL/Fl_Multi_Label.H undo.o: ../FL/Fl_Pixmap.H undo.o: ../FL/Fl_Plugin.H undo.o: ../FL/Fl_Preferences.H undo.o: ../FL/Fl_Rect.H undo.o: ../FL/Fl_RGB_Image.H undo.o: ../FL/Fl_Scrollbar.H undo.o: ../FL/Fl_Slider.H undo.o: ../FL/fl_string_functions.h undo.o: ../FL/fl_types.h undo.o: ../FL/fl_utf8.h undo.o: ../FL/Fl_Valuator.H undo.o: ../FL/Fl_Widget.H undo.o: ../FL/Fl_Window.H undo.o: ../FL/platform_types.h undo.o: ../src/flstring.h undo.o: ../src/Fl_String.H undo.o: code.h undo.o: file.h undo.o: fluid.h undo.o: fluid_filename.h undo.o: Fl_Type.h undo.o: Fl_Widget_Type.h undo.o: undo.h undo.o: widget_browser.h widget_browser.o: ../FL/Enumerations.H widget_browser.o: ../FL/filename.H widget_browser.o: ../FL/Fl.H widget_browser.o: ../FL/fl_attr.h widget_browser.o: ../FL/Fl_Bitmap.H widget_browser.o: ../FL/Fl_Browser_.H widget_browser.o: ../FL/Fl_Cairo.H widget_browser.o: ../FL/fl_casts.H widget_browser.o: ../FL/fl_config.h widget_browser.o: ../FL/Fl_Device.H widget_browser.o: ../FL/fl_draw.H widget_browser.o: ../FL/Fl_Export.H widget_browser.o: ../FL/Fl_Graphics_Driver.H widget_browser.o: ../FL/Fl_Image.H widget_browser.o: ../FL/Fl_Menu_Item.H widget_browser.o: ../FL/Fl_Multi_Label.H widget_browser.o: ../FL/Fl_Pixmap.H widget_browser.o: ../FL/Fl_Plugin.H widget_browser.o: ../FL/Fl_Preferences.H widget_browser.o: ../FL/Fl_Rect.H widget_browser.o: ../FL/Fl_RGB_Image.H widget_browser.o: ../FL/Fl_Scrollbar.H widget_browser.o: ../FL/Fl_Slider.H widget_browser.o: ../FL/fl_types.h widget_browser.o: ../FL/fl_utf8.h widget_browser.o: ../FL/Fl_Valuator.H widget_browser.o: ../FL/Fl_Widget.H widget_browser.o: ../FL/platform_types.h widget_browser.o: ../src/Fl_String.H widget_browser.o: code.h widget_browser.o: fluid.h widget_browser.o: fluid_filename.h widget_browser.o: Fl_Type.h widget_browser.o: Fl_Widget_Type.h widget_browser.o: pixmaps.h widget_browser.o: widget_browser.h widget_panel.o: ../FL/Enumerations.H widget_panel.o: ../FL/Fl.H widget_panel.o: ../FL/fl_attr.h widget_panel.o: ../FL/Fl_Bitmap.H widget_panel.o: ../FL/Fl_Box.H widget_panel.o: ../FL/Fl_Button.H widget_panel.o: ../FL/Fl_Cairo.H widget_panel.o: ../FL/fl_casts.H widget_panel.o: ../FL/Fl_Check_Button.H widget_panel.o: ../FL/Fl_Choice.H widget_panel.o: ../FL/fl_config.h widget_panel.o: ../FL/Fl_Device.H widget_panel.o: ../FL/Fl_Double_Window.H widget_panel.o: ../FL/fl_draw.H widget_panel.o: ../FL/Fl_Export.H widget_panel.o: ../FL/Fl_Flex.H widget_panel.o: ../FL/Fl_Graphics_Driver.H widget_panel.o: ../FL/Fl_Grid.H widget_panel.o: ../FL/Fl_Group.H widget_panel.o: ../FL/Fl_Image.H widget_panel.o: ../FL/Fl_Input.H widget_panel.o: ../FL/Fl_Input_.H widget_panel.o: ../FL/Fl_Input_Choice.H widget_panel.o: ../FL/Fl_Light_Button.H widget_panel.o: ../FL/Fl_Menu_.H widget_panel.o: ../FL/Fl_Menu_Button.H widget_panel.o: ../FL/Fl_Menu_Item.H widget_panel.o: ../FL/Fl_Pack.H widget_panel.o: ../FL/Fl_Pixmap.H widget_panel.o: ../FL/Fl_Plugin.H widget_panel.o: ../FL/Fl_Preferences.H widget_panel.o: ../FL/Fl_Rect.H widget_panel.o: ../FL/Fl_Return_Button.H widget_panel.o: ../FL/Fl_RGB_Image.H widget_panel.o: ../FL/Fl_Scrollbar.H widget_panel.o: ../FL/Fl_Shared_Image.H widget_panel.o: ../FL/Fl_Shortcut_Button.H widget_panel.o: ../FL/Fl_Slider.H widget_panel.o: ../FL/Fl_Tabs.H widget_panel.o: ../FL/Fl_Text_Buffer.H widget_panel.o: ../FL/Fl_Text_Display.H widget_panel.o: ../FL/Fl_Text_Editor.H widget_panel.o: ../FL/Fl_Tile.H widget_panel.o: ../FL/fl_types.h widget_panel.o: ../FL/fl_utf8.h widget_panel.o: ../FL/Fl_Valuator.H widget_panel.o: ../FL/Fl_Value_Input.H widget_panel.o: ../FL/Fl_Widget.H widget_panel.o: ../FL/Fl_Window.H widget_panel.o: ../FL/Fl_Wizard.H widget_panel.o: ../FL/platform_types.h widget_panel.o: ../src/Fl_String.H widget_panel.o: code.h widget_panel.o: CodeEditor.h widget_panel.o: custom_widgets.h widget_panel.o: Fl_Grid_Type.h widget_panel.o: Fl_Group_Type.h widget_panel.o: Fl_Type.h widget_panel.o: Fl_Widget_Type.h widget_panel.o: StyleParse.h widget_panel.o: undo.h widget_panel.o: widget_panel.h �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/fluid/file.cxx���������������������������������������������������������������������������0000644�0001750�0001750�00000067534�15004135251�015372� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // Fluid file routines for the Fast Light Tool Kit (FLTK). // // You may find the basic read_* and write_* routines to // be useful for other programs. I have used them many times. // They are somewhat similar to tcl, using matching { and } // to quote strings. // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "file.h" #include "fluid.h" #include "factory.h" #include "Fl_Function_Type.h" #include "Fl_Widget_Type.h" #include "Fl_Grid_Type.h" #include "Fl_Window_Type.h" #include "settings_panel.h" #include "widget_browser.h" #include "shell_command.h" #include "code.h" #include "undo.h" #include <FL/Fl.H> #include <FL/Fl_Group.H> #include <FL/fl_string_functions.h> #include <FL/fl_message.H> #include "../src/flstring.h" #include <stdio.h> #include <stdlib.h> #include <stdarg.h> /// \defgroup flfile .fl Project File Operations /// \{ // This file contains code to read and write .fl files. /// If set, we read an old fdesign file and widget y coordinates need to be flipped. int fdesign_flip = 0; /** \brief Read a .fl project file. The .fl file format is documented in `fluid/README_fl.txt`. \param[in] filename read this file \param[in] merge if this is set, merge the file into an existing project at Fl_Type::current \param[in] strategy add new nodes after current or as last child \return 0 if the operation failed, 1 if it succeeded */ int read_file(const char *filename, int merge, Strategy strategy) { Fd_Project_Reader f; strategy.source(Strategy::FROM_FILE); return f.read_project(filename, merge, strategy); } /** \brief Write an .fl design description file. The .fl file format is documented in `fluid/README_fl.txt`. \param[in] filename create this file, and if it exists, overwrite it \param[in] selected_only write only the selected nodes in the widget_tree. This is used to implement copy and paste. \return 0 if the operation failed, 1 if it succeeded */ int write_file(const char *filename, int selected_only, bool to_codeview) { Fd_Project_Writer out; return out.write_project(filename, selected_only, to_codeview); } /** Convert a single ASCII char, assumed to be a hex digit, into its decimal value. \param[in] x ASCII character \return decimal value or 20 if character is not a valid hex digit (0..9,a..f,A..F) */ static int hexdigit(int x) { if ((x < 0) || (x > 127)) return 20; if (isdigit(x)) return x-'0'; if (isupper(x)) return x-'A'+10; if (islower(x)) return x-'a'+10; return 20; } // ---- Fd_Project_Reader ---------------------------------------------- MARK: - /** A simple growing buffer. Oh how I wish sometimes we would upgrade to modern C++. \param[in] length minimum length in bytes */ void Fd_Project_Reader::expand_buffer(int length) { if (length >= buflen) { if (!buflen) { buflen = length+1; buffer = (char*)malloc(buflen); } else { buflen = 2*buflen; if (length >= buflen) buflen = length+1; buffer = (char *)realloc((void *)buffer,buflen); } } } /** \brief Construct local project reader. */ Fd_Project_Reader::Fd_Project_Reader() : fin(NULL), lineno(0), fname(NULL), buffer(NULL), buflen(0), read_version(0.0) { } /** \brief Release project reader resources. */ Fd_Project_Reader::~Fd_Project_Reader() { // fname is not copied, so do not free it if (buffer) ::free(buffer); } /** Open an .fl file for reading. \param[in] s filename, if NULL, read from stdin instead \return 0 if the operation failed, 1 if it succeeded */ int Fd_Project_Reader::open_read(const char *s) { lineno = 1; if (!s) { fin = stdin; fname = "stdin"; } else { FILE *f = fl_fopen(s, "rb"); if (!f) return 0; fin = f; fname = s; } return 1; } /** Close the .fl file. \return 0 if the operation failed, 1 if it succeeded */ int Fd_Project_Reader::close_read() { if (fin != stdin) { int x = fclose(fin); fin = 0; return x >= 0; } return 1; } /** Return the name part of the current filename and path. \return a pointer into a string that is not owned by this class */ const char *Fd_Project_Reader::filename_name() { return fl_filename_name(fname); } /** Convert an ASCII sequence from the \.fl file following a previously read `\\` into a single character. Conversion includes the common C style \\ characters like \\n, \\x## hex values, and \\o### octal values. \return a character in the ASCII range */ int Fd_Project_Reader::read_quoted() { // read whatever character is after a \ . int c,d,x; switch(c = nextchar()) { case '\n': lineno++; return -1; case 'a' : return('\a'); case 'b' : return('\b'); case 'f' : return('\f'); case 'n' : return('\n'); case 'r' : return('\r'); case 't' : return('\t'); case 'v' : return('\v'); case 'x' : /* read hex */ for (c=x=0; x<3; x++) { int ch = nextchar(); d = hexdigit(ch); if (d > 15) {ungetc(ch,fin); break;} c = (c<<4)+d; } break; default: /* read octal */ if (c<'0' || c>'7') break; c -= '0'; for (x=0; x<2; x++) { int ch = nextchar(); d = hexdigit(ch); if (d>7) {ungetc(ch,fin); break;} c = (c<<3)+d; } break; } return(c); } /** Recursively read child nodes in the .fl design file. If this is the first call, also read the global settings for this design. \param[in] p parent node or NULL \param[in] merge if set, merge into existing design, else replace design \param[in] strategy add nodes after current or as last child \param[in] skip_options this is set if the options were already found in a previous call, and there is no need to waste time searching for them. \return the last type that was created */ Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options) { Fl_Type::current = p; Fl_Type *last_child_read = NULL; Fl_Type *t = NULL; for (;;) { const char *c = read_word(); REUSE_C: if (!c) { if (p && !merge) read_error("Missing '}'"); break; } if (!strcmp(c,"}")) { if (!p) read_error("Unexpected '}'"); break; } // Make sure that we don't go through the list of options for child nodes if (!skip_options) { // this is the first word in a .fd file: if (!strcmp(c,"Magic:")) { read_fdesign(); return NULL; } if (!strcmp(c,"version")) { c = read_word(); read_version = strtod(c,0); if (read_version<=0 || read_version>double(FL_VERSION+0.00001)) read_error("unknown version '%s'",c); continue; } // back compatibility with Vincent Penne's original class code: if (!p && !strcmp(c,"define_in_struct")) { Fl_Type *t = add_new_widget_from_file("class", Strategy::FROM_FILE_AS_LAST_CHILD); t->name(read_word()); Fl_Type::current = p = t; merge = 1; // stops "missing }" error continue; } if (!strcmp(c,"do_not_include_H_from_C")) { g_project.include_H_from_C=0; goto CONTINUE; } if (!strcmp(c,"use_FL_COMMAND")) { g_project.use_FL_COMMAND=1; goto CONTINUE; } if (!strcmp(c,"utf8_in_src")) { g_project.utf8_in_src=1; goto CONTINUE; } if (!strcmp(c,"avoid_early_includes")) { g_project.avoid_early_includes=1; goto CONTINUE; } if (!strcmp(c,"i18n_type")) { g_project.i18n_type = static_cast<Fd_I18n_Type>(atoi(read_word())); goto CONTINUE; } if (!strcmp(c,"i18n_gnu_function")) { g_project.i18n_gnu_function = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_gnu_static_function")) { g_project.i18n_gnu_static_function = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_pos_file")) { g_project.i18n_pos_file = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_pos_set")) { g_project.i18n_pos_set = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_include")) { if (g_project.i18n_type == FD_I18N_GNU) g_project.i18n_gnu_include = read_word(); else if (g_project.i18n_type == FD_I18N_POSIX) g_project.i18n_pos_include = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_conditional")) { if (g_project.i18n_type == FD_I18N_GNU) g_project.i18n_gnu_conditional = read_word(); else if (g_project.i18n_type == FD_I18N_POSIX) g_project.i18n_pos_conditional = read_word(); goto CONTINUE; } if (!strcmp(c,"header_name")) { if (!g_project.header_file_set) g_project.header_file_name = read_word(); else read_word(); goto CONTINUE; } if (!strcmp(c,"code_name")) { if (!g_project.code_file_set) g_project.code_file_name = read_word(); else read_word(); goto CONTINUE; } if (!strcmp(c, "snap")) { g_layout_list.read(this); goto CONTINUE; } if (!strcmp(c, "gridx") || !strcmp(c, "gridy")) { // grid settings are now global read_word(); goto CONTINUE; } if (strcmp(c, "shell_commands")==0) { if (g_shell_config) { g_shell_config->read(this); } else { read_word(); } goto CONTINUE; } if (!strcmp(c, "mergeback")) { g_project.write_mergeback_data = read_int(); goto CONTINUE; } } t = add_new_widget_from_file(c, strategy); if (!t) { read_error("Unknown word \"%s\"", c); continue; } last_child_read = t; // After reading the first widget, we no longer need to look for options skip_options = 1; t->name(read_word()); c = read_word(1); if (strcmp(c,"{") && t->is_class()) { // <prefix> <name> ((Fl_Class_Type*)t)->prefix(t->name()); t->name(c); c = read_word(1); } if (strcmp(c,"{")) { read_error("Missing property list for %s\n",t->title()); goto REUSE_C; } t->folded_ = 1; for (;;) { const char *cc = read_word(); if (!cc || !strcmp(cc,"}")) break; t->read_property(*this, cc); } if (t->can_have_children()) { c = read_word(1); if (strcmp(c,"{")) { read_error("Missing child list for %s\n",t->title()); goto REUSE_C; } read_children(t, 0, Strategy::FROM_FILE_AS_LAST_CHILD, skip_options); t->postprocess_read(); // FIXME: this has no business in the file reader! // TODO: this is called whenever something is pasted from the top level into a grid // It makes sense to make this more universal for other widget types too. if (merge && t && t->parent && t->parent->is_a(ID_Grid)) { if (Fl_Window_Type::popupx != 0x7FFFFFFF) { ((Fl_Grid_Type*)t->parent)->insert_child_at(((Fl_Widget_Type*)t)->o, Fl_Window_Type::popupx, Fl_Window_Type::popupy); } else { ((Fl_Grid_Type*)t->parent)->insert_child_at_next_free_cell(((Fl_Widget_Type*)t)->o); } } t->layout_widget(); } if (strategy.placement() == Strategy::AS_FIRST_CHILD) { strategy.placement(Strategy::AFTER_CURRENT); } if (strategy.placement() == Strategy::AFTER_CURRENT) { Fl_Type::current = t; } else { Fl_Type::current = p; } CONTINUE:; } if (merge && last_child_read && last_child_read->parent) { last_child_read->parent->postprocess_read(); last_child_read->parent->layout_widget(); } return last_child_read; } /** \brief Read a .fl project file. \param[in] filename read this file \param[in] merge if this is set, merge the file into an existing project at Fl_Type::current \param[in] strategy add new nodes after current or as last child \return 0 if the operation failed, 1 if it succeeded */ int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy strategy) { Fl_Type *o; undo_suspend(); read_version = 0.0; if (!open_read(filename)) { undo_resume(); return 0; } if (merge) deselect(); else g_project.reset(); read_children(Fl_Type::current, merge, strategy); // clear this Fl_Type::current = 0; // Force menu items to be rebuilt... for (o = Fl_Type::first; o; o = o->next) { if (o->is_a(ID_Menu_Manager_)) { o->add_child(0,0); } } for (o = Fl_Type::first; o; o = o->next) { if (o->selected) { Fl_Type::current = o; break; } } selection_changed(Fl_Type::current); if (g_shell_config) { g_shell_config->rebuild_shell_menu(); g_shell_config->update_settings_dialog(); } g_layout_list.update_dialogs(); g_project.update_settings_dialog(); int ret = close_read(); undo_resume(); return ret; } /** Display an error while reading the file. If the .fl file isn't opened for reading, pop up an FLTK dialog, otherwise print to stdout. \note Matt: I am not sure why it is done this way. Shouldn't this depend on \c batch_mode? \todo Not happy about this function. Output channel should depend on `batch_mode` as the note above already states. I want to make all file readers and writers depend on an error handling base class that outputs a useful analysis of file operations. \param[in] format printf style format string, followed by an argument list */ void Fd_Project_Reader::read_error(const char *format, ...) { va_list args; va_start(args, format); if (!fin) { // FIXME: this line suppresses any error messages in interactive mode char buffer[1024]; // TODO: hides class member "buffer" vsnprintf(buffer, sizeof(buffer), format, args); fl_message("%s", buffer); } else { fprintf(stderr, "%s:%d: ", fname, lineno); vfprintf(stderr, format, args); fprintf(stderr, "\n"); } va_end(args); } /** Return a word read from the .fl file, or NULL at the EOF. This will skip all comments (# to end of line), and evaluate all \\xxx sequences and use \\ at the end of line to remove the newline. A word is any one of: - a continuous string of non-space chars except { and } and # - everything between matching {...} (unless wantbrace != 0) - the characters '{' and '}' \param[in] wantbrace if set, reading a `{` as the first non-space character will return the string `"{"`, if clear, a `{` is seen as the start of a word \return a pointer to the internal buffer, containing a copy of the word. Don't free the buffer! Note that most (all?) other file operations will overwrite this buffer. If wantbrace is not set, but we read a leading '{', the returned string will be stripped of its leading and trailing braces. */ const char *Fd_Project_Reader::read_word(int wantbrace) { int x; // skip all the whitespace before it: for (;;) { x = nextchar(); if (x < 0 && feof(fin)) { // eof return 0; } else if (x == '#') { // comment do x = nextchar(); while (x >= 0 && x != '\n'); lineno++; continue; } else if (x == '\n') { lineno++; } else if (!isspace(x & 255)) { break; } } expand_buffer(100); if (x == '{' && !wantbrace) { // read in whatever is between braces int length = 0; int nesting = 0; for (;;) { x = nextchar(); if (x<0) {read_error("Missing '}'"); break;} else if (x == '#') { // embedded comment do x = nextchar(); while (x >= 0 && x != '\n'); lineno++; continue; } else if (x == '\n') lineno++; else if (x == '\\') {x = read_quoted(); if (x<0) continue;} else if (x == '{') nesting++; else if (x == '}') {if (!nesting--) break;} buffer[length++] = x; expand_buffer(length); } buffer[length] = 0; return buffer; } else if (x == '{' || x == '}') { // all the punctuation is a word: buffer[0] = x; buffer[1] = 0; return buffer; } else { // read in an unquoted word: int length = 0; for (;;) { if (x == '\\') {x = read_quoted(); if (x<0) continue;} else if (x<0 || isspace(x & 255) || x=='{' || x=='}' || x=='#') break; buffer[length++] = x; expand_buffer(length); x = nextchar(); } ungetc(x, fin); buffer[length] = 0; return buffer; } } /** Read a word and interpret it as an integer value. \return integer value, or 0 if the word is not an integer */ int Fd_Project_Reader::read_int() { const char *word = read_word(); if (word) { return atoi(word); } else { return 0; } } /** Read fdesign name/value pairs. Fdesign is the file format of the XForms UI designer. It stores lists of name and value pairs separated by a colon: `class: FL_LABELFRAME`. \param[out] name string \param[out] value string \return 0 if end of file, else 1 */ int Fd_Project_Reader::read_fdesign_line(const char*& name, const char*& value) { int length = 0; int x; // find a colon: for (;;) { x = nextchar(); if (x < 0 && feof(fin)) return 0; if (x == '\n') {length = 0; continue;} // no colon this line... if (!isspace(x & 255)) { buffer[length++] = x; expand_buffer(length); } if (x == ':') break; } int valueoffset = length; buffer[length-1] = 0; // skip to start of value: for (;;) { x = nextchar(); if ((x < 0 && feof(fin)) || x == '\n' || !isspace(x & 255)) break; } // read the value: for (;;) { if (x == '\\') {x = read_quoted(); if (x<0) continue;} else if (x == '\n') break; buffer[length++] = x; expand_buffer(length); x = nextchar(); } buffer[length] = 0; name = buffer; value = buffer+valueoffset; return 1; } /// Lookup table from fdesign .fd files to .fl files static const char *class_matcher[] = { "FL_CHECKBUTTON", "Fl_Check_Button", "FL_ROUNDBUTTON", "Fl_Round_Button", "FL_ROUND3DBUTTON", "Fl_Round_Button", "FL_LIGHTBUTTON", "Fl_Light_Button", "FL_FRAME", "Fl_Box", "FL_LABELFRAME", "Fl_Box", "FL_TEXT", "Fl_Box", "FL_VALSLIDER", "Fl_Value_Slider", "FL_MENU", "Fl_Menu_Button", "3", "FL_BITMAP", "1", "FL_BOX", "71","FL_BROWSER", "11","FL_BUTTON", "4", "FL_CHART", "42","FL_CHOICE", "61","FL_CLOCK", "25","FL_COUNTER", "22","FL_DIAL", "101","FL_FREE", "31","FL_INPUT", "12","Fl_Light_Button", "41","FL_MENU", "23","FL_POSITIONER", "13","Fl_Round_Button", "21","FL_SLIDER", "2", "FL_BOX", // was FL_TEXT "62","FL_TIMER", "24","Fl_Value_Slider", 0}; /** Finish a group of widgets and optionally transform its children's coordinates. Implements the same functionality as Fl_Group::forms_end() from the forms compatibility library would have done: - resize the group to surround its children if the group's w() == 0 - optionally flip the \p y coordinates of all children relative to the group's window - Fl_Group::end() the group \note Copied from forms_compatibility.cxx and modified as a static fluid function so we don't have to link to fltk_forms. \param[in] g the Fl_Group widget \param[in] flip flip children's \p y coordinates if true (non-zero) */ static void forms_end(Fl_Group *g, int flip) { // set the dimensions of a group to surround its contents const int nc = g->children(); if (nc && !g->w()) { Fl_Widget*const* a = g->array(); Fl_Widget* o = *a++; int rx = o->x(); int ry = o->y(); int rw = rx+o->w(); int rh = ry+o->h(); for (int i = nc - 1; i--;) { o = *a++; if (o->x() < rx) rx = o->x(); if (o->y() < ry) ry = o->y(); if (o->x() + o->w() > rw) rw = o->x() + o->w(); if (o->y() + o->h() > rh) rh = o->y() + o->h(); } g->Fl_Widget::resize(rx, ry, rw-rx, rh-ry); } // flip all the children's coordinate systems: if (nc && flip) { Fl_Widget* o = (g->as_window()) ? g : g->window(); int Y = o->h(); Fl_Widget*const* a = g->array(); for (int i = nc; i--;) { Fl_Widget* ow = *a++; int newy = Y - ow->y() - ow->h(); ow->Fl_Widget::resize(ow->x(), newy, ow->w(), ow->h()); } } g->end(); } /** Read a XForms design file. .fl and .fd file start with the same header. Fluid can recognize .fd XForms Design files by a magic number. It will read them and map XForms widgets onto FLTK widgets. \see http://xforms-toolkit.org */ void Fd_Project_Reader::read_fdesign() { int fdesign_magic = atoi(read_word()); fdesign_flip = (fdesign_magic < 13000); Fl_Widget_Type *window = 0; Fl_Widget_Type *group = 0; Fl_Widget_Type *widget = 0; if (!Fl_Type::current) { Fl_Type *t = add_new_widget_from_file("Function", Strategy::FROM_FILE_AS_LAST_CHILD); t->name("create_the_forms()"); Fl_Type::current = t; } for (;;) { const char *name; const char *value; if (!read_fdesign_line(name, value)) break; if (!strcmp(name,"Name")) { window = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Window", Strategy::FROM_FILE_AS_LAST_CHILD); window->name(value); window->label(value); Fl_Type::current = widget = window; } else if (!strcmp(name,"class")) { if (!strcmp(value,"FL_BEGIN_GROUP")) { group = widget = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Group", Strategy::FROM_FILE_AS_LAST_CHILD); Fl_Type::current = group; } else if (!strcmp(value,"FL_END_GROUP")) { if (group) { Fl_Group* g = (Fl_Group*)(group->o); g->begin(); forms_end(g, fdesign_flip); Fl_Group::current(0); } group = widget = 0; Fl_Type::current = window; } else { for (int i = 0; class_matcher[i]; i += 2) if (!strcmp(value,class_matcher[i])) { value = class_matcher[i+1]; break;} widget = (Fl_Widget_Type*)add_new_widget_from_file(value, Strategy::FROM_FILE_AS_LAST_CHILD); if (!widget) { printf("class %s not found, using Fl_Button\n", value); widget = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Button", Strategy::FROM_FILE_AS_LAST_CHILD); } } } else if (widget) { if (!widget->read_fdesign(name, value)) printf("Ignoring \"%s: %s\"\n", name, value); } } } // ---- Fd_Project_Writer ---------------------------------------------- MARK: - /** \brief Construct local project writer. */ Fd_Project_Writer::Fd_Project_Writer() : fout(NULL), needspace(0), write_codeview_(false) { } /** \brief Release project writer resources. */ Fd_Project_Writer::~Fd_Project_Writer() { } /** Open the .fl design file for writing. If the filename is NULL, associate stdout instead. \param[in] s the filename or NULL for stdout \return 1 if successful. 0 if the operation failed */ int Fd_Project_Writer::open_write(const char *s) { if (!s) { fout = stdout; } else { FILE *f = fl_fopen(s,"wb"); if (!f) return 0; fout = f; } return 1; } /** Close the .fl design file. Don't close, if data was sent to stdout. \return 1 if succeeded, 0 if fclose failed */ int Fd_Project_Writer::close_write() { if (fout != stdout) { int x = fclose(fout); fout = stdout; return x >= 0; } return 1; } /** \brief Write an .fl design description file. \param[in] filename create this file, and if it exists, overwrite it \param[in] selected_only write only the selected nodes in the widget_tree. This is used to implement copy and paste. \param[in] sv if set, this file will be used by codeview \return 0 if the operation failed, 1 if it succeeded */ int Fd_Project_Writer::write_project(const char *filename, int selected_only, bool sv) { write_codeview_ = sv; undo_suspend(); if (!open_write(filename)) { undo_resume(); return 0; } write_string("# data file for the Fltk User Interface Designer (fluid)\n" "version %.4f",FL_VERSION); if(!g_project.include_H_from_C) write_string("\ndo_not_include_H_from_C"); if(g_project.use_FL_COMMAND) write_string("\nuse_FL_COMMAND"); if (g_project.utf8_in_src) write_string("\nutf8_in_src"); if (g_project.avoid_early_includes) write_string("\navoid_early_includes"); if (g_project.i18n_type) { write_string("\ni18n_type %d", g_project.i18n_type); switch (g_project.i18n_type) { case FD_I18N_NONE: break; case FD_I18N_GNU : /* GNU gettext */ write_string("\ni18n_include"); write_word(g_project.i18n_gnu_include.c_str()); write_string("\ni18n_conditional"); write_word(g_project.i18n_gnu_conditional.c_str()); write_string("\ni18n_gnu_function"); write_word(g_project.i18n_gnu_function.c_str()); write_string("\ni18n_gnu_static_function"); write_word(g_project.i18n_gnu_static_function.c_str()); break; case FD_I18N_POSIX : /* POSIX catgets */ write_string("\ni18n_include"); write_word(g_project.i18n_pos_include.c_str()); write_string("\ni18n_conditional"); write_word(g_project.i18n_pos_conditional.c_str()); if (!g_project.i18n_pos_file.empty()) { write_string("\ni18n_pos_file"); write_word(g_project.i18n_pos_file.c_str()); } write_string("\ni18n_pos_set"); write_word(g_project.i18n_pos_set.c_str()); break; } } if (!selected_only) { write_string("\nheader_name"); write_word(g_project.header_file_name.c_str()); write_string("\ncode_name"); write_word(g_project.code_file_name.c_str()); g_layout_list.write(this); if (g_shell_config) g_shell_config->write(this); if (g_project.write_mergeback_data) write_string("\nmergeback %d", g_project.write_mergeback_data); } for (Fl_Type *p = Fl_Type::first; p;) { if (!selected_only || p->selected) { p->write(*this); write_string("\n"); int q = p->level; for (p = p->next; p && p->level > q; p = p->next) {/*empty*/} } else { p = p->next; } } int ret = close_write(); undo_resume(); return ret; } /** Write a string to the .fl file, quoting characters if necessary. \param[in] w NUL terminated text */ void Fd_Project_Writer::write_word(const char *w) { if (needspace) putc(' ', fout); needspace = 1; if (!w || !*w) {fprintf(fout,"{}"); return;} const char *p; // see if it is a single word: for (p = w; is_id(*p); p++) ; if (!*p) {fprintf(fout,"%s",w); return;} // see if there are matching braces: int n = 0; for (p = w; *p; p++) { if (*p == '{') n++; else if (*p == '}') {n--; if (n<0) break;} } int mismatched = (n != 0); // write out brace-quoted string: putc('{', fout); for (; *w; w++) { switch (*w) { case '{': case '}': if (!mismatched) break; case '\\': case '#': putc('\\',fout); break; } putc(*w,fout); } putc('}', fout); } /** Write an arbitrary formatted word to the .fl file, or a comment, etc . If needspace is set, then one space is written before the string unless the format starts with a newline character \\n. \param[in] format printf style formatting string followed by a list of arguments */ void Fd_Project_Writer::write_string(const char *format, ...) { va_list args; va_start(args, format); if (needspace && *format != '\n') fputc(' ',fout); vfprintf(fout, format, args); va_end(args); needspace = !isspace(format[strlen(format)-1] & 255); } /** Start a new line in the .fl file and indent it for a given nesting level. \param[in] n indent level */ void Fd_Project_Writer::write_indent(int n) { fputc('\n',fout); while (n--) {fputc(' ',fout); fputc(' ',fout);} needspace = 0; } /** Write a '{' to the .fl file at the given indenting level. */ void Fd_Project_Writer::write_open() { if (needspace) fputc(' ',fout); fputc('{',fout); needspace = 0; } /** Write a '}' to the .fl file at the given indenting level. \param[in] n indent level */ void Fd_Project_Writer::write_close(int n) { if (needspace) write_indent(n); fputc('}',fout); needspace = 1; } /// \} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/fluid/ExternalCodeEditor_UNIX.h����������������������������������������������������������0000644�0001750�0001750�00000003324�15004135251�020452� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // External code editor management class for Unix // // Handles starting and keeping track of an external text editor, // including process start, temp file creation/removal, bookkeeping, killing.. // #ifndef _EXTCODEEDITOR_H #define _EXTCODEEDITOR_H #include <FL/Fl.H> #include "fluid.h" #include <errno.h> /* errno */ #include <string.h> /* strerror() */ #include <sys/types.h> /* stat().. */ #include <sys/stat.h> #include <unistd.h> // ---- ExternalCodeEditor declaration class ExternalCodeEditor { int pid_; time_t file_mtime_; // last modify time of the file (used to determine if file changed) size_t file_size_; // last file size (used to determine if changed) const char *filename_; Fl_String command_line_; int last_error_; int alert_pipe_[2]; bool alert_pipe_open_; static void alert_pipe_cb(FL_SOCKET, void*); protected: void kill_editor(); const char *create_tmpdir(); const char *tmp_filename(); int start_editor(const char *cmd, const char *filename); void set_filename(const char *val); void open_alert_pipe(); public: ExternalCodeEditor(); ~ExternalCodeEditor(); int is_editing(); int reap_editor(pid_t *pid_reaped=NULL); void close_editor(); const char *filename() { return filename_; } int open_editor(const char *editor_cmd, const char *code); int handle_changes(const char **code, int force=0); int remove_tmpfile(); // Public static methods static void start_update_timer(); static void stop_update_timer(); static const char* tmpdir_name(); static void tmpdir_clear(); static int editors_open(); static void set_update_timer_callback(Fl_Timeout_Handler); }; #endif /*_EXTCODEEDITOR_H */ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/fluid/code.h�����������������������������������������������������������������������������0000644�0001750�0001750�00000007532�15004135251�015002� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // Code output routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_CODE_H #define _FLUID_CODE_H #include <FL/fl_attr.h> #include "../src/Fl_String.H" #include <stdarg.h> #include <stdio.h> class Fl_Type; struct Fd_Identifier_Tree; struct Fd_Text_Tree; struct Fd_Pointer_Tree; int is_id(char c); int write_strings(const Fl_String &filename); class Fd_Code_Writer { protected: /// file pointer for the C++ code file FILE *code_file; /// file pointer for the C++ header file FILE *header_file; /// tree of unique but human-readable identifiers Fd_Identifier_Tree* id_root; /// searchable text tree for text that is only written once to the header file Fd_Text_Tree *text_in_header; /// searchable text tree for text that is only written once to the code file Fd_Text_Tree *text_in_code; /// searchable tree for pointers that are only written once to the code file Fd_Pointer_Tree *ptr_in_code; /// crc32 for blocks of text written to the code file unsigned long block_crc_; /// if set, we are at the start of a line and can ignore leading spaces in crc bool block_line_start_; /// expanding buffer for vsnprintf char *block_buffer_; /// size of expanding buffer for vsnprintf int block_buffer_size_; void crc_add(const void *data, int n=-1); int crc_printf(const char *format, ...); int crc_vprintf(const char *format, va_list args); int crc_puts(const char *text); int crc_putc(int c); public: /// current level of source code indentation int indentation; /// set if we write abbreviated file for the source code previewer /// (disables binary data blocks, for example) bool write_codeview; /// silly thing to prevent declaring unused variables: /// When this symbol is on, all attempts to write code don't write /// anything, but set a variable if it looks like the variable "o" is used: int varused_test; /// set to 1 if varused_test found that a variable is actually used int varused; public: Fd_Code_Writer(); ~Fd_Code_Writer(); const char* unique_id(void* o, const char*, const char*, const char*); /// Increment source code indentation level. void indent_more() { indentation++; } /// Decrement source code indentation level. void indent_less() { indentation--; } const char *indent(); const char *indent(int set); const char *indent_plus(int offset); int write_h_once(const char *, ...) __fl_attr((__format__ (__printf__, 2, 3))); int write_c_once(const char *, ...) __fl_attr((__format__ (__printf__, 2, 3))); bool c_contains(void* ptr); void write_cstring(const char *,int length); void write_cstring(const char *); void write_cdata(const char *,int length); void vwrite_c(const char* format, va_list args); void write_c(const char*, ...) __fl_attr((__format__ (__printf__, 2, 3))); void write_cc(const char *, int, const char*, const char*); void write_h(const char*, ...) __fl_attr((__format__ (__printf__, 2, 3))); void write_hc(const char *, int, const char*, const char*); void write_c_indented(const char *textlines, int inIndent, char inTrailwWith); Fl_Type* write_static(Fl_Type* p); Fl_Type* write_code(Fl_Type* p); int write_code(const char *cfile, const char *hfile, bool to_codeview=false); void write_public(int state); // writes pubic:/private: as needed void tag(int type, unsigned short uid); static unsigned long block_crc(const void *data, int n=-1, unsigned long in_crc=0, bool *inout_line_start=NULL); }; #endif // _FLUID_CODE_H ����������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/fluid/widget_panel.fl��������������������������������������������������������������������0000644�0001750�0001750�00000175435�15004135251�016714� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} snap { ver 1 current_suite FLTK current_preset 1 } comment {// // Widget panel for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // } {in_source in_header } decl {\#include "undo.h"} {private global } decl {\#include "Fl_Widget_Type.h"} {private global } decl {\#include "Fl_Grid_Type.h"} {private global } decl {\#include <FL/Fl_Grid.H>} {private global } decl {\#include "custom_widgets.h"} {public global } decl {extern void set_modflag(int mf, int mfc=-1);} {private local } Function {make_image_panel()} { comment {Create a panel for editing widget image data} open } { Fl_Window image_panel_window { label {Image Options} callback {propagate_load(o, v);} open xywh {527 684 260 332} type Double modal visible } { Fl_Group image_panel_imagegroup { callback propagate_load open xywh {10 15 235 125} } { Fl_Box {} { label { ---- Active Image ----} xywh {75 15 170 20} labelfont 1 labelsize 11 align 20 } Fl_Box image_panel_data { label {... x ... pixels, ...} callback {if (v == LOAD) { Fl_Shared_Image *img = Fl_Shared_Image::get(widget_image_input->value()); o->user_data(img); if (img) { char buf[256]; snprintf(buf, 255, "%d x %d pixels, %d channels", img->data_w(), img->data_h(), img->d()); o->copy_label(buf); image_panel_imagegroup->activate(); } else if (widget_image_input->value() && widget_image_input->value()[0]) { o->label("Can't load image"); image_panel_imagegroup->activate(); } else { o->label("... x ... pixels, ..."); image_panel_imagegroup->deactivate(); } }} xywh {75 35 170 20} labelsize 11 align 20 code0 {\#include <FL/Fl_Shared_Image.H>} } Fl_Group {} { callback propagate_load open xywh {75 75 170 20} } { Fl_Input image_panel_imagew { label {Width:} callback {if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { o->value(current_widget->scale_image_w_); } } else { int mod = 0; for (Fl_Type *t = Fl_Type::first; t; t = t->next) { if (t->selected && t->is_widget()) { Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); wt->scale_image_w_ = o->value(); Fl_Image *img = wt->o->image(); if (img) { int iw = wt->scale_image_w_; if (iw<=0) iw = img->data_w(); int ih = wt->scale_image_h_; if (ih<=0) ih = img->data_w(); img->scale(iw, ih, 0, 1); wt->o->redraw(); if (wt->o->parent()) wt->o->parent()->redraw(); } mod = 1; } } if (mod) set_modflag(1); }} tooltip {Scale image to this width in pixel units} xywh {75 75 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Input image_panel_imageh { label {Height:} callback {if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { o->value(current_widget->scale_image_h_); } } else { int mod = 0; for (Fl_Type *t = Fl_Type::first; t; t = t->next) { if (t->selected && t->is_widget()) { Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); wt->scale_image_h_ = o->value(); Fl_Image *img = wt->o->image(); if (img) { int iw = wt->scale_image_w_; if (iw<=0) iw = img->data_w(); int ih = wt->scale_image_h_; if (ih<=0) ih = img->data_w(); img->scale(iw, ih, 0, 1); wt->o->redraw(); if (wt->o->parent()) wt->o->parent()->redraw(); } mod = 1; } } if (mod) set_modflag(1); }} tooltip {Scale image to this height in pixel units} xywh {135 75 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Button {} { label Reset callback {if (v != LOAD) { image_panel_imagew->value(0); image_panel_imageh->value(0); image_panel_imagew->do_callback(); image_panel_imageh->do_callback(); }} tooltip {Reset scale to original size} xywh {195 75 50 20} labelsize 11 } } Fl_Box {} { label {Scale:} xywh {10 75 60 20} labelfont 1 labelsize 11 align 24 } Fl_Box {} { label {Storage:} xywh {10 100 60 20} labelfont 1 labelsize 11 align 24 } Fl_Check_Button {} { label {convert to raw pixel data} callback compress_image_cb tooltip {if unchecked, keep the image in its original format and store the data as is; if checked, convert the image and store it as uncompressed RGB or grayscale pixel data} xywh {75 100 170 20} down_box DOWN_BOX labelsize 11 } Fl_Check_Button {} { label {bind to widget} callback bind_image_cb tooltip {bind the image to the widget, so it will be deleted automatically} xywh {75 120 170 20} down_box DOWN_BOX labelsize 11 hotspot } } Fl_Group image_panel_deimagegroup { callback propagate_load open xywh {10 155 235 125} } { Fl_Box {} { label { ---- Inactive Image ----} xywh {75 155 170 20} labelfont 1 labelsize 11 align 20 } Fl_Box image_panel_dedata { label {... x ... pixels, ...} callback {if (v == LOAD) { Fl_Shared_Image *img = Fl_Shared_Image::get(widget_deimage_input->value()); o->user_data(img); if (img) { char buf[256]; snprintf(buf, 255, "%d x %d pixels, %d channels", img->data_w(), img->data_h(), img->d()); o->copy_label(buf); image_panel_deimagegroup->activate(); } else if (widget_deimage_input->value() && widget_deimage_input->value()[0]) { o->label("Can't load image"); image_panel_deimagegroup->activate(); } else { o->label("... x ... pixels, ..."); image_panel_deimagegroup->deactivate(); } }} xywh {75 175 170 20} labelsize 11 align 20 } Fl_Group {} { callback propagate_load open xywh {75 215 170 20} } { Fl_Input image_panel_deimagew { label {Width:} callback {if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { o->value(current_widget->scale_deimage_w_); } } else { int mod = 0; for (Fl_Type *t = Fl_Type::first; t; t = t->next) { if (t->selected && t->is_widget()) { Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); wt->scale_deimage_w_ = o->value(); Fl_Image *img = wt->o->deimage(); if (img) { int iw = wt->scale_deimage_w_; if (iw<=0) iw = img->data_w(); int ih = wt->scale_deimage_h_; if (ih<=0) ih = img->data_w(); img->scale(iw, ih, 0, 1); wt->o->redraw(); if (wt->o->parent()) wt->o->parent()->redraw(); } mod = 1; } } if (mod) set_modflag(1); }} tooltip {Scale image to this width in pixel units} xywh {75 215 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Input image_panel_deimageh { label {Height:} callback {if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { o->value(current_widget->scale_deimage_h_); } } else { int mod = 0; for (Fl_Type *t = Fl_Type::first; t; t = t->next) { if (t->selected && t->is_widget()) { Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); wt->scale_deimage_h_ = o->value(); Fl_Image *img = wt->o->deimage(); if (img) { int iw = wt->scale_deimage_w_; if (iw<=0) iw = img->data_w(); int ih = wt->scale_deimage_h_; if (ih<=0) ih = img->data_w(); img->scale(iw, ih, 0, 1); wt->o->redraw(); if (wt->o->parent()) wt->o->parent()->redraw(); } mod = 1; } } if (mod) set_modflag(1); }} tooltip {Scale image to this height in pixel units} xywh {135 215 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Button {} { label Reset callback {if (v != LOAD) { image_panel_deimagew->value(0); image_panel_deimageh->value(0); image_panel_deimagew->do_callback(); image_panel_deimageh->do_callback(); }} tooltip {Reset scale to original size} xywh {195 215 50 20} labelsize 11 } } Fl_Box {} { label {Scale:} xywh {10 215 60 20} labelfont 1 labelsize 11 align 24 } Fl_Box {} { label {Storage:} xywh {10 240 60 20} labelfont 1 labelsize 11 align 24 } Fl_Check_Button {} { label {convert to raw pixel data} callback compress_deimage_cb tooltip {if unchecked, keep the image in its original format and store the data as is; if checked, convert the image and store it as uncompressed RGB or grayscale pixel data} xywh {75 240 170 20} down_box DOWN_BOX labelsize 11 } Fl_Check_Button {} { label {bind to widget} callback bind_deimage_cb tooltip {bind the image to the widget, so it will be deleted automatically} xywh {75 260 170 20} down_box DOWN_BOX labelsize 11 } } Fl_Button image_panel_close { label Close callback {if (v != LOAD) image_panel_window->hide();} xywh {165 295 80 20} labelsize 11 } } } Function {run_image_panel()} {open return_type void } { code {if (!image_panel_window) make_image_panel(); image_panel_window->do_callback(image_panel_window, LOAD); Fl::pushed(0); Fl_Window *g = Fl::grab(); if (g) Fl::grab(0); image_panel_window->show(); while (image_panel_window->shown()) Fl::wait(); if (g) Fl::grab(g); Fl_Shared_Image *img = (Fl_Shared_Image*)image_panel_data->user_data(); if (img) { img->release(); image_panel_data->user_data(NULL); }} {} } Function {make_widget_panel()} { comment {Create a panel that can be used with all known widgets} open } { Fl_Window {} { comment {Use a Double Window to avoid flickering.} open selected xywh {372 208 420 400} type Double labelsize 11 align 80 resizable hotspot code0 {o->size_range(o->w(), o->h());} size_range {420 400 0 0} visible } { Fl_Tabs widget_tabs { callback {propagate_load((Fl_Group *)o,v);} open xywh {10 10 400 350} selection_color 12 labelsize 11 labelcolor 7 when 0 resizable code0 {o->show();} } { Fl_Group wp_gui_tab { label GUI callback propagate_load open xywh {10 30 400 330} labelsize 11 when 0 resizable } { Fl_Group {} { label {Label:} callback propagate_load open xywh {95 40 309 20} labelfont 1 labelsize 11 align 4 } { Fl_Input wp_gui_label { callback label_cb tooltip {The label text for the widget. Use Ctrl-J for newlines.} xywh {95 40 190 20} labelfont 1 labelsize 11 when 15 textsize 11 resizable } Fl_Choice {} { callback labeltype_cb open tooltip {The label style for the widget.} xywh {285 40 119 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 code0 {extern Fl_Menu_Item labeltypemenu[];} code1 {o->menu(labeltypemenu);} } {} } Fl_Group {} { label {Image:} callback propagate_load open xywh {95 65 309 20} labelfont 1 labelsize 11 align 4 } { Fl_Input widget_image_input { callback image_cb tooltip {The active image for the widget.} xywh {95 65 200 20} labelfont 1 labelsize 11 textsize 11 resizable } Fl_Button {} { label {Browse...} callback image_browse_cb tooltip {Click to choose the active image.} xywh {295 65 89 20} labelsize 11 align 256 } Fl_Button {} { label {...} callback {if (v != LOAD) { run_image_panel(); }} tooltip {more image options} bind_image 1 xywh {384 65 20 20} } } Fl_Group {} { label {Inactive:} callback propagate_load open xywh {95 90 309 20} labelfont 1 labelsize 11 align 4 } { Fl_Input widget_deimage_input { callback inactive_cb tooltip {The inactive image for the widget.} xywh {95 90 200 20} labelfont 1 labelsize 11 textsize 11 resizable } Fl_Button {} { label {Browse...} callback inactive_browse_cb tooltip {Click to choose the inactive image.} xywh {295 90 89 20} labelsize 11 } } Fl_Group wp_gui_alignment { label {Alignment:} callback propagate_load open xywh {95 115 312 20} labelfont 1 labelsize 11 align 4 } { Fl_Button {} { label Clip user_data {(fl_intptr_t)FL_ALIGN_CLIP} callback align_cb tooltip {Clip the label to the inside of the widget.} xywh {95 115 30 20} type Toggle selection_color 8 labelsize 11 align 16 } Fl_Button {} { label Wrap user_data {(fl_intptr_t)FL_ALIGN_WRAP} callback align_cb tooltip {Wrap the label text.} xywh {130 115 38 20} type Toggle selection_color 8 labelsize 11 } Fl_Button {} { label {@-1<-} user_data {(fl_intptr_t)FL_ALIGN_LEFT} callback align_cb tooltip {Left-align the label.} xywh {278 115 20 20} type Toggle selection_color 8 labelsize 11 labelcolor 8 hide } Fl_Button {} { label {@-1->} user_data {(fl_intptr_t)FL_ALIGN_RIGHT} callback align_cb tooltip {Right-align the label.} xywh {303 115 20 20} type Toggle selection_color 8 labelsize 11 labelcolor 8 hide } Fl_Button {} { label {@-18} user_data {(fl_intptr_t)FL_ALIGN_TOP} callback align_cb tooltip {Top-align the label.} xywh {328 115 20 20} type Toggle selection_color 8 labelsize 11 labelcolor 8 hide } Fl_Button {} { label {@-12} user_data {(fl_intptr_t)FL_ALIGN_BOTTOM} callback align_cb tooltip {Bottom-align the label.} xywh {353 115 20 20} type Toggle selection_color 8 labelsize 11 labelcolor 8 hide } Fl_Choice {} { callback align_text_image_cb xywh {172 115 116 20} down_box BORDER_BOX labelsize 11 textsize 11 } { MenuItem {} { label { Image Alignment } user_data {(fl_intptr_t)0xFFFFFFFF} xywh {145 145 100 20} labelfont 2 labelsize 10 deactivate } MenuItem {} { label {image over text} user_data {(fl_intptr_t)FL_ALIGN_IMAGE_OVER_TEXT} xywh {25 25 100 20} labelsize 9 } MenuItem {} { label {text over image} user_data {(fl_intptr_t)FL_ALIGN_TEXT_OVER_IMAGE} xywh {15 15 100 20} labelsize 9 } MenuItem {} { label {text next to image} user_data {(fl_intptr_t)FL_ALIGN_TEXT_NEXT_TO_IMAGE} xywh {35 35 100 20} labelsize 9 } MenuItem {} { label {image next to text} user_data {(fl_intptr_t)FL_ALIGN_IMAGE_NEXT_TO_TEXT} xywh {45 45 100 20} labelsize 9 } MenuItem {} { label {image is backdrop} user_data {(fl_intptr_t)FL_ALIGN_IMAGE_BACKDROP} xywh {55 55 100 20} labelsize 9 } } Fl_Choice {} { callback align_position_cb xywh {293 115 86 20} down_box BORDER_BOX labelsize 11 textsize 11 } { MenuItem {} { label { Inside && Outside } user_data {(fl_intptr_t)0xFFFFFFFF} xywh {135 135 100 20} labelfont 2 labelsize 10 deactivate } MenuItem {} { label {top left} user_data {(fl_intptr_t)FL_ALIGN_TOP_LEFT} xywh {45 45 100 20} labelsize 9 } MenuItem {} { label top user_data {(fl_intptr_t)FL_ALIGN_TOP} xywh {55 55 100 20} labelsize 9 } MenuItem {} { label {top right} user_data {(fl_intptr_t)FL_ALIGN_TOP_RIGHT} xywh {65 65 100 20} labelsize 9 } MenuItem {} { label left user_data {(fl_intptr_t)FL_ALIGN_LEFT} xywh {75 75 100 20} labelsize 9 } MenuItem {} { label center user_data {(fl_intptr_t)FL_ALIGN_CENTER} xywh {35 35 100 20} labelsize 9 } MenuItem {} { label right user_data {(fl_intptr_t)FL_ALIGN_RIGHT} xywh {85 85 100 20} labelsize 9 } MenuItem {} { label {bottom left} user_data {(fl_intptr_t)FL_ALIGN_BOTTOM_LEFT} xywh {95 95 100 20} labelsize 9 } MenuItem {} { label bottom user_data {(fl_intptr_t)FL_ALIGN_BOTTOM} xywh {105 105 100 20} labelsize 9 } MenuItem {} { label {bottom right} user_data {(fl_intptr_t)FL_ALIGN_BOTTOM_RIGHT} xywh {115 115 100 20} labelsize 9 } MenuItem {} { label { Outside Alignment } user_data {(fl_intptr_t)0xFFFFFFFF} xywh {125 125 100 20} labelfont 2 labelsize 10 deactivate } MenuItem {} { label {left top} user_data {(fl_intptr_t)FL_ALIGN_LEFT_TOP} xywh {135 135 100 20} labelsize 9 } MenuItem {} { label {right top} user_data {(fl_intptr_t)FL_ALIGN_RIGHT_TOP} xywh {145 145 100 20} labelsize 9 } MenuItem {} { label {left bottom} user_data {(fl_intptr_t)FL_ALIGN_LEFT_BOTTOM} xywh {155 155 100 20} labelsize 9 } MenuItem {} { label {right bottom} user_data {(fl_intptr_t)FL_ALIGN_RIGHT_BOTTOM} xywh {45 45 100 20} labelsize 9 } } Fl_Button {} { label {@-3square} user_data {(fl_intptr_t)FL_ALIGN_INSIDE} callback align_cb tooltip {Show the label inside the widget.} xywh {384 115 20 20} type Toggle selection_color 8 labelsize 11 labelcolor 8 } Fl_Box {} { xywh {406 115 1 20} labelsize 11 resizable } } Fl_Group {} { label {Position:} callback position_group_cb open xywh {95 150 314 20} labelfont 1 labelsize 11 align 4 } { Fl_Input widget_x_input { label {X:} callback x_cb tooltip {The X position of the widget as a number or formula. Formulas can be simple math, including the variables x, px, sx, cx, and i} xywh {95 150 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Input widget_y_input { label {Y:} callback y_cb tooltip {The Y position of the widget as a number or formula. Formulas can be simple math, including the variables y, py, sy, cy, and i} xywh {155 150 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Input widget_w_input { label {Width:} callback w_cb tooltip {The width of the widget as a number or formula. Formulas can be simple math, including the variables w, pw, sw, cw, and i} xywh {215 150 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Input widget_h_input { label {Height:} callback h_cb tooltip {The height of the widget as a number or formula. Formulas can be simple math, including the variables h, ph, sh, ch, and i} xywh {275 150 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Choice {} { label {Children:} callback wc_relative_cb open tooltip {When instantiating a widget class, the children can either be fixed in their original position, automatically be repositioned, or both repsositioned and resized to fit the container.} xywh {335 150 64 20} down_box BORDER_BOX labelsize 11 align 5 textsize 11 } { MenuItem {} { label Fixed xywh {0 0 31 20} labelsize 11 } MenuItem {} { label Reposition xywh {0 0 31 20} labelsize 11 } MenuItem {} { label Resize xywh {0 0 31 20} labelsize 11 } } Fl_Box {} { xywh {399 150 1 20} hide resizable } } Fl_Group wp_gui_flexp { label {Flex Parent:} callback flex_size_group_cb comment {This group is only visible if the parent is an Fl_Flex widget} xywh {95 150 314 20} labelfont 1 labelsize 11 align 4 hide } { Fl_Value_Input widget_flex_size { label {Size:} callback flex_size_cb tooltip {Fixed Width or Height for a horizontal or vertical Fl_Flex Parent.} xywh {95 150 55 20} labelsize 11 align 5 textsize 11 } Fl_Check_Button widget_flex_fixed { label fixed callback flex_fixed_cb tooltip {If checked, the size of the widget stays fixed.} xywh {155 150 55 20} down_box DOWN_BOX labelsize 11 } Fl_Box {} { xywh {398 150 1 20} resizable } } Fl_Group wp_gui_values { label {Values:} callback values_group_cb open xywh {95 185 300 20} labelfont 1 labelsize 11 align 4 } { Fl_Value_Input {} { label {Size:} callback slider_size_cb tooltip {The size of the slider.} xywh {95 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Minimum:} callback min_cb tooltip {The minimum value of the widget.} xywh {155 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Maximum:} callback max_cb tooltip {The maximum value of the widget.} xywh {215 185 55 20} labelsize 11 align 5 value 1 textsize 11 } Fl_Value_Input {} { label {Step:} callback step_cb tooltip {The resolution of the widget value.} xywh {275 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Value:} callback value_cb tooltip {The current widget value.} xywh {335 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Box {} { xywh {395 185 0 20} resizable } } Fl_Group wp_gui_margins { label {Margins:} callback flex_margin_group_cb comment {This group is only visible for Fl_Flex widgets} xywh {95 185 300 20} labelfont 1 labelsize 11 align 4 hide } { Fl_Value_Input {} { label {Left:} callback flex_margin_left_cb tooltip {Left margin in group.} xywh {95 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Top:} callback flex_margin_top_cb tooltip {Top margin in group.} xywh {155 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Right:} callback flex_margin_right_cb tooltip {Right margin in group.} xywh {215 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Bottom:} callback flex_margin_bottom_cb tooltip {Bottom margin in group.} xywh {275 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Gap:} callback flex_margin_gap_cb tooltip {Gap between children.} xywh {335 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Box {} { xywh {395 185 0 20} resizable } } Fl_Group wp_gui_sizerange { label {Size Range:} callback size_range_group_cb open xywh {95 185 300 20} labelfont 1 labelsize 11 align 4 hide } { Fl_Value_Input {} { label {Minimum Size:} callback min_w_cb tooltip {The size of the slider.} xywh {95 185 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 } Fl_Value_Input {} { callback min_h_cb tooltip {The minimum value of the widget.} xywh {155 185 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 } Fl_Button {} { label set callback set_min_size_cb xywh {215 185 25 20} labelsize 11 } Fl_Value_Input {} { label {Maximum Size:} callback max_w_cb tooltip {The maximum value of the widget.} xywh {245 185 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 } Fl_Value_Input {} { callback max_h_cb tooltip {The resolution of the widget value.} xywh {305 185 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 } Fl_Button {} { label set callback set_max_size_cb xywh {365 185 25 20} labelsize 11 } Fl_Box {} { xywh {395 185 0 20} resizable } } Fl_Group {} { label {Shortcut:} callback propagate_load open xywh {95 210 310 20} labelfont 1 labelsize 11 align 4 } { Fl_Button wp_gui_shortcut { callback shortcut_in_cb comment {This is a special button that grabs keystrokes directly} tooltip {The shortcut key for the widget. Use 'Backspace' key to clear.} xywh {95 210 310 20} box DOWN_BOX color 7 selection_color 12 labelsize 11 when 1 code0 {\#include <FL/Fl_Shortcut_Button.H>} class Fl_Shortcut_Button } } Fl_Group wp_gui_xclass { label {X Class:} callback propagate_load xywh {95 235 300 20} labelfont 1 labelsize 11 align 4 } { Fl_Input {} { label {:} callback xclass_cb tooltip {The X resource class.} xywh {95 235 95 20} labelfont 1 labelsize 11 textsize 11 resizable } Fl_Light_Button {} { label Border callback border_cb tooltip {Add a border around the window.} xywh {195 235 60 20} selection_color 1 labelsize 11 } Fl_Light_Button {} { label Modal callback modal_cb tooltip {Make the window modal.} xywh {260 235 55 20} selection_color 1 labelsize 11 } Fl_Light_Button {} { label Nonmodal callback non_modal_cb tooltip {Make the window non-modal.} xywh {320 235 75 20} selection_color 1 labelsize 11 align 148 } } Fl_Group wp_gui_attributes { label {Attributes:} callback propagate_load xywh {95 260 305 20} labelfont 1 labelsize 11 align 4 } { Fl_Light_Button {} { label Visible callback visible_cb tooltip {Show the widget.} xywh {95 260 60 20} selection_color 1 labelsize 11 } Fl_Light_Button {} { label Active callback active_cb tooltip {Activate the widget.} xywh {160 260 60 20} selection_color 1 labelsize 11 } Fl_Light_Button {} { label Resizable callback resizable_cb tooltip {Make the widget resizable.} xywh {225 260 75 20} selection_color 1 labelsize 11 when 1 } Fl_Light_Button {} { label Hotspot callback hotspot_cb tooltip {Center the window under this widget.} xywh {305 260 70 20} selection_color 1 labelsize 11 when 1 } Fl_Box {} { xywh {395 260 0 20} labelsize 11 resizable } } Fl_Input wp_gui_tooltip { label {Tooltip:} callback tooltip_cb tooltip {The tooltip text for the widget. Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize 11 } Fl_Box {} { xywh {95 305 300 5} hide resizable } } Fl_Group wp_style_tab { label Style callback propagate_load open xywh {10 30 400 330} labelsize 11 when 0 hide } { Fl_Group wp_style_label { label {Label Font:} callback propagate_load open xywh {99 40 305 20} labelfont 1 labelsize 11 align 4 } { Fl_Choice {} { callback labelfont_cb open tooltip {The style of the label text.} xywh {99 40 148 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item fontmenu[];} code1 {o->menu(fontmenu);} } {} Fl_Value_Input {} { callback labelsize_cb tooltip {The size of the label text.} xywh {247 40 49 20} labelsize 11 maximum 100 step 1 value 14 textsize 11 } Fl_Button w_labelcolor { label {Label Color} callback labelcolor_cb tooltip {The color of the label text.} xywh {296 40 90 20} labelsize 11 } Fl_Menu_Button {} { callback labelcolor_menu_cb open xywh {386 40 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} } {} } Fl_Group wp_style_box { label {Box:} callback propagate_load open xywh {99 65 305 20} labelfont 1 labelsize 11 align 4 } { Fl_Choice {} { callback box_cb open tooltip {The "up" box of the widget.} xywh {100 65 196 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item boxmenu[];} code1 {o->menu(boxmenu);} } {} Fl_Button w_color { label Color callback color_cb tooltip {The background color of the widget.} xywh {296 65 90 20} labelsize 11 } Fl_Menu_Button {} { callback color_menu_cb open xywh {386 65 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} } {} } Fl_Group wp_style_downbox { label {Down Box:} callback propagate_load open xywh {99 90 305 20} labelfont 1 labelsize 11 align 4 } { Fl_Choice {} { callback down_box_cb open tooltip {The "down" box of the widget.} xywh {99 90 197 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item boxmenu[];} code1 {o->menu(boxmenu);} } {} Fl_Button w_selectcolor { label {Select Color} callback color2_cb tooltip {The selection color of the widget.} xywh {296 90 90 20} labelsize 11 } Fl_Menu_Button {} { callback color2_menu_cb open xywh {386 90 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} } {} } Fl_Group wp_style_text { label {Text Font:} callback propagate_load open xywh {99 115 305 20} labelfont 1 labelsize 11 align 4 } { Fl_Choice {} { callback textfont_cb open tooltip {The value text style.} xywh {99 115 148 20} box DOWN_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item fontmenu[];} code1 {o->menu(fontmenu);} } {} Fl_Value_Input {} { callback textsize_cb tooltip {The value text size.} xywh {247 115 49 20} labelsize 11 maximum 100 step 1 value 14 textsize 11 } Fl_Button w_textcolor { label {Text Color} callback textcolor_cb tooltip {The value text color.} xywh {296 115 90 20} labelsize 11 } Fl_Menu_Button {} { callback textcolor_menu_cb open xywh {386 115 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} } {} } Fl_Group {} { label {Label Margin:} callback propagate_load open xywh {99 150 242 20} labelfont 1 labelsize 11 align 4 } { Fl_Value_Input {} { label {Horizontal:} callback h_label_margin_cb tooltip {Spacing between label and the horizontally aligned side of the widget.} xywh {99 150 55 20} labelsize 11 align 5 minimum -127 maximum 128 step 1 textsize 11 } Fl_Value_Input {} { label {Vertical:} callback v_label_margin_cb tooltip {Spacing between label and the vertically aligned side of the widget.} xywh {159 150 55 20} labelsize 11 align 5 minimum -127 maximum 127 step 1 textsize 11 } Fl_Value_Input {} { label {Text to Image:} callback image_spacing_cb tooltip {Gap between label image and text in pixels} xywh {219 150 55 20} labelsize 11 align 5 maximum 255 step 1 textsize 11 } Fl_Box {} { xywh {281 150 60 20} labelsize 11 hide resizable } } Fl_Light_Button {} { label Compact callback compact_cb tooltip {use compact box types for closely set buttons} xywh {99 175 90 20} selection_color 1 labelsize 11 } Fl_Box {} { xywh {195 205 40 40} labelsize 11 resizable } } Fl_Group wp_cpp_tab { label {C++} callback propagate_load open xywh {10 30 400 330} labelsize 11 when 0 hide } { Fl_Group wp_cpp_class { label {Class:} callback propagate_load open xywh {95 40 310 20} labelfont 1 labelsize 11 align 4 } { Fl_Input {} { user_data 4 callback subclass_cb tooltip {The widget subclass.} xywh {95 40 172 20} labelfont 1 labelsize 11 textfont 4 textsize 11 resizable } Fl_Choice {} { callback subtype_cb open tooltip {The widget subtype.} xywh {267 40 138 20} box THIN_UP_BOX down_box BORDER_BOX labelsize 11 textsize 11 } {} } Fl_Group wp_cpp_name { label {Name:} callback propagate_load xywh {95 65 310 20} labelfont 1 labelsize 11 align 4 } { Fl_Input {} { callback name_cb tooltip {The name of the widget.} xywh {95 65 235 20} labelfont 1 labelsize 11 textsize 11 resizable } Fl_Choice {} { callback name_public_member_cb open tooltip {Change member access attribute.} xywh {330 65 75 20} down_box BORDER_BOX labelsize 11 when 1 textsize 11 } { MenuItem {} { label private user_data 0 user_data_type long xywh {0 0 100 20} labelsize 11 } MenuItem {} { label public user_data 1 user_data_type long xywh {0 0 100 20} labelsize 11 } MenuItem {} { label protected user_data 2 user_data_type long xywh {0 0 100 20} labelsize 11 } } Fl_Choice {} { callback name_public_cb open tooltip {Change widget accessibility.} xywh {330 65 75 20} down_box BORDER_BOX labelsize 11 when 1 textsize 11 hide } { MenuItem {} { label local user_data 0 user_data_type long xywh {10 10 100 20} labelsize 11 } MenuItem {} { label global user_data 1 user_data_type long xywh {10 10 100 20} labelsize 11 } } } Fl_Input {v_input[0]} { label {Extra Code:} user_data 0 callback v_input_cb tooltip {Extra initialization code for the widget.} xywh {95 90 310 20} labelfont 1 labelsize 11 textfont 4 textsize 11 } Fl_Input {v_input[1]} { user_data 1 callback v_input_cb tooltip {Extra initialization code for the widget.} xywh {95 110 310 20} labelsize 11 textfont 4 textsize 11 } Fl_Input {v_input[2]} { user_data 2 callback v_input_cb tooltip {Extra initialization code for the widget.} xywh {95 130 310 20} labelsize 11 textfont 4 textsize 11 } Fl_Input {v_input[3]} { user_data 3 callback v_input_cb tooltip {Extra initialization code for the widget.} xywh {95 150 310 20} labelsize 11 textfont 4 textsize 11 } Fl_Tile {} { callback {wComment->do_callback(wComment, v); wCallback->do_callback(wCallback, v);} open xywh {95 175 310 130} resizable } { Fl_Group {} {open xywh {95 175 310 48} box FLAT_BOX } { Fl_Text_Editor wComment { label {Comment:} tooltip {Write a comment that will appear in the source code and in the widget tree overview.} xywh {95 175 310 45} box DOWN_BOX labelfont 1 labelsize 11 align 4 when 1 textfont 6 textsize 11 textcolor 59 resizable code0 {wComment->buffer(new Fl_Text_Buffer());} code1 {wComment->callback((Fl_Callback*)comment_cb);} } } Fl_Group {} {open xywh {95 223 310 82} box FLAT_BOX } { Fl_Text_Editor wCallback { label {Callback:} callback callback_cb tooltip {The callback function or code for the widget. Use the variable name 'o' to access the Widget pointer and 'v' to access the user value.} xywh {95 225 310 80} box DOWN_BOX labelfont 1 labelsize 11 align 4 textfont 4 textsize 11 resizable code0 {\#include "CodeEditor.h"} class CodeEditor } } } Fl_Group wp_cpp_callback { label {User Data:} callback propagate_load open xywh {95 310 310 20} labelfont 1 labelsize 11 align 4 } { Fl_Input {} { callback user_data_cb tooltip {The user data to pass into the callback code.} xywh {95 310 158 20} labelfont 1 labelsize 11 textfont 4 textsize 11 resizable } Fl_Menu_Button {} { label When callback when_cb open tooltip {When to call the callback function.} xywh {260 310 145 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 when 1 textsize 11 code0 {extern Fl_Menu_Item whenmenu[];} code1 {o->menu(whenmenu);} } {} } Fl_Group {} { label {Type:} callback propagate_load open xywh {95 332 310 26} labelfont 1 labelsize 11 align 4 } { Fl_Input_Choice {} { callback user_data_type_cb open tooltip {The type of the user data.} xywh {95 335 158 20} labelfont 1 labelsize 11 textfont 4 textsize 11 resizable } { MenuItem {} { label {void*} xywh {0 0 31 20} labelfont 4 labelsize 11 } MenuItem {} { label long xywh {0 0 31 20} labelfont 4 labelsize 11 } } Fl_Box w_when_box { label FL_WHEN_NEVER xywh {260 332 145 26} box FLAT_BOX selection_color 1 labelsize 8 align 209 } } } Fl_Group widget_tab_grid_child { label {Grid Child} callback propagate_load open xywh {10 30 400 330} labelsize 11 hide } { Fl_Group {} { label {Location:} callback propagate_load open xywh {95 60 315 20} box FLAT_BOX labelfont 1 labelsize 11 align 4 } { Fl_Input widget_grid_row_input { label {Row:} callback grid_set_row_cb xywh {95 60 40 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Group {} {open xywh {135 60 30 20} } { Fl_Button {} { label {-} callback grid_dec_row_cb xywh {135 60 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } Fl_Button {} { label {+} callback grid_inc_row_cb xywh {150 60 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } } Fl_Input widget_grid_col_input { label {Column:} callback grid_set_col_cb xywh {175 60 40 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Group {} {open xywh {215 60 30 20} } { Fl_Button {} { label {-} callback grid_dec_col_cb xywh {215 60 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } Fl_Button {} { label {+} callback grid_inc_col_cb xywh {230 60 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } } Fl_Box {} { xywh {395 60 1 20} hide resizable } Fl_Box widget_grid_transient { label TRANSIENT callback {if (v==LOAD) { Fl_Widget *child = ((Fl_Widget_Type*)current_widget)->o; Fl_Grid_Proxy *g = ((Fl_Grid_Proxy*)((Fl_Widget_Type*)current_widget->parent)->o); // Fl_Grid::Cell *cell = g->cell(child); // Fl_Grid::Cell *tcell = g->transient_cell(child); widget_grid_transient->hide(); widget_grid_unlinked->hide(); if (g->transient_cell(child)) { widget_grid_transient->show(); } else if (!g->cell(child)) { widget_grid_unlinked->show(); } }} xywh {250 60 80 20} labelsize 11 labelcolor 1 } Fl_Box widget_grid_unlinked { label UNLINKED xywh {250 60 80 20} labelsize 11 labelcolor 1 hide } } Fl_Group wp_gridc_align { label {Align:} callback propagate_load open xywh {95 100 315 20} labelfont 1 labelsize 11 align 4 } { Fl_Choice {} { label Horizontal callback grid_align_horizontal_cb open xywh {95 100 115 20} down_box BORDER_BOX labelsize 11 align 5 textsize 11 } { MenuItem GRID_LEFT { label GRID_LEFT user_data {(fl_intptr_t)FL_GRID_LEFT} user_data_type long xywh {10 10 31 20} labelsize 11 } MenuItem {} { label GRID_CENTER user_data {(fl_intptr_t)FL_GRID_CENTER} user_data_type long xywh {10 10 31 20} labelsize 11 } MenuItem {} { label GRID_RIGHT user_data {(fl_intptr_t)FL_GRID_RIGHT} user_data_type long xywh {10 10 31 20} labelsize 11 } MenuItem {} { label GRID_FILL user_data {(fl_intptr_t)FL_GRID_HORIZONTAL} user_data_type long xywh {10 10 31 20} labelsize 11 } } Fl_Choice {} { label Vertical callback grid_align_vertical_cb open xywh {215 100 115 20} down_box BORDER_BOX labelsize 11 align 5 textsize 11 } { MenuItem {} { label GRID_TOP user_data {(fl_intptr_t)FL_GRID_TOP} user_data_type long xywh {10 10 31 20} labelsize 11 } MenuItem {} { label GRID_CENTER user_data {(fl_intptr_t)FL_GRID_CENTER} user_data_type long xywh {10 10 31 20} labelsize 11 } MenuItem {} { label GRID_BOTTOM user_data {(fl_intptr_t)FL_GRID_BOTTOM} user_data_type long xywh {10 10 31 20} labelsize 11 } MenuItem {} { label GRID_FILL user_data {(fl_intptr_t)FL_GRID_VERTICAL} user_data_type long xywh {10 10 31 20} labelsize 11 } } Fl_Box {} { xywh {395 100 1 20} hide resizable } } Fl_Group wp_gridc_size { label {Min. Size:} callback propagate_load open xywh {95 135 315 20} labelfont 1 labelsize 11 align 4 } { Fl_Input {} { label {Width:} callback grid_set_min_wdt_cb xywh {95 135 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Input {} { label {Height:} callback grid_set_min_hgt_cb xywh {155 135 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Box {} { xywh {395 135 1 20} hide resizable } } Fl_Group {} { label {Span:} callback propagate_load open xywh {95 170 315 20} labelfont 1 labelsize 11 align 4 } { Fl_Input widget_grid_rowspan_input { label {Row Span:} callback grid_set_rowspan_cb xywh {95 170 40 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Group {} {open xywh {135 170 30 20} } { Fl_Button {} { label {-} callback grid_dec_rowspan_cb xywh {135 170 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } Fl_Button {} { label {+} callback grid_inc_rowspan_cb xywh {150 170 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } } Fl_Input widget_grid_colspan_input { label {Col. Span:} callback grid_set_colspan_cb xywh {175 170 40 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Group {} {open xywh {215 170 30 20} } { Fl_Button {} { label {-} callback grid_dec_colspan_cb xywh {215 170 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } Fl_Button {} { label {+} callback grid_inc_colspan_cb xywh {230 170 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } } Fl_Box {} { xywh {395 170 1 20} hide resizable } } Fl_Box {} { xywh {95 350 300 5} labelsize 11 hide resizable } } Fl_Group widget_tab_grid { label Grid callback propagate_load open xywh {10 30 400 330} labelsize 11 hide } { Fl_Group {} { label {Grid Layout:} callback propagate_load open xywh {95 60 315 20} labelfont 1 labelsize 11 align 4 } { Fl_Input widget_grid_rows { label {Rows:} callback {// grid_rows_cb Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; if (v == LOAD) { o->value(grid->rows()); } else { int m = o->value(), old_m = grid->rows(); if (m < 1) { m = 1; o->value(m); } if (m < old_m) { // TODO: verify that this will not unlink existings cells // Offer a dialog with "delete children", "unlink cells", "cancel" } if (m != old_m) { undo_checkpoint(); grid->layout(m, grid->cols()); grid->need_layout(true); set_modflag(1); widget_tab_grid->do_callback(widget_tab_grid, LOAD); } }} tooltip {Number of horizontal rows in the Grid group} xywh {95 60 40 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Group {} {open xywh {135 60 30 20} } { Fl_Button {} { label {-} callback {if (v != LOAD) { widget_grid_rows->value( widget_grid_rows->value()-1 ); widget_grid_rows->do_callback(); }} xywh {135 60 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } Fl_Button {} { label {+} callback {if (v != LOAD) { widget_grid_rows->value( widget_grid_rows->value()+1 ); widget_grid_rows->do_callback(); }} xywh {150 60 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } } Fl_Input widget_grid_cols { label {Columns:} callback {// grid_rows_cb Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; if (v == LOAD) { o->value(grid->cols()); } else { int m = o->value(), old_m = grid->cols(); if (m < 1) { m = 1; o->value(m); } if (m < old_m) { // TODO: verify that this will not unlink existings cells // Offer a dialog with "delete children", "unlink cells", "cancel" } if (m != old_m) { undo_checkpoint(); grid->layout(grid->rows(), m); grid->need_layout(true); set_modflag(1); widget_tab_grid->do_callback(widget_tab_grid, LOAD); } }} tooltip {Number of vertical columns in the Grid group} xywh {175 60 40 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Group {} {open xywh {215 60 30 20} } { Fl_Button {} { label {-} callback {if (v != LOAD) { widget_grid_cols->value( widget_grid_cols->value()-1 ); widget_grid_cols->do_callback(); }} xywh {215 60 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } Fl_Button {} { label {+} callback {if (v != LOAD) { widget_grid_cols->value( widget_grid_cols->value()+1 ); widget_grid_cols->do_callback(); }} xywh {230 60 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } } Fl_Box {} { xywh {396 60 0 20} resizable } } Fl_Group wp_grid_margin { label {Margins:} callback propagate_load open xywh {95 100 315 20} labelfont 1 labelsize 11 align 4 } { Fl_Value_Input {} { label {Left:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int m = 0; if (v == LOAD) { grid->margin(&m, NULL, NULL, NULL); o->value(m); } else { int m = (int)o->value(), old_m; grid->margin(&old_m, NULL, NULL, NULL); if (m != old_m) { undo_checkpoint(); grid->margin(m, -1, -1, -1); grid->need_layout(true); set_modflag(1); } }} tooltip {Left margin in group.} xywh {95 100 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 } Fl_Value_Input {} { label {Top:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int m = 0; if (v == LOAD) { grid->margin(NULL, &m, NULL, NULL); o->value(m); } else { int m = (int)o->value(), old_m; grid->margin(NULL, &old_m, NULL, NULL); if (m != old_m) { undo_checkpoint(); grid->margin(-1, m, -1, -1); grid->need_layout(true); set_modflag(1); } }} tooltip {Top margin in group.} xywh {155 100 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 } Fl_Value_Input {} { label {Right:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int m = 0; if (v == LOAD) { grid->margin(NULL, NULL, &m, NULL); o->value(m); } else { int m = (int)o->value(), old_m; grid->margin(NULL, NULL, &old_m, NULL); if (m != old_m) { undo_checkpoint(); grid->margin(-1, -1, m, -1); grid->need_layout(true); set_modflag(1); } }} tooltip {Right margin in group.} xywh {215 100 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 } Fl_Value_Input {} { label {Bottom:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int m = 0; if (v == LOAD) { grid->margin(NULL, NULL, NULL, &m); o->value(m); } else { int m = (int)o->value(), old_m; grid->margin(NULL, NULL, NULL, &old_m); if (m != old_m) { undo_checkpoint(); grid->margin(-1, -1, -1, m); grid->need_layout(true); set_modflag(1); } }} tooltip {Bottom margin in group.} xywh {275 100 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 } Fl_Box {} { xywh {396 100 0 20} resizable } } Fl_Group wp_grid_gaps { label {Gaps:} callback propagate_load open xywh {95 135 315 20} labelfont 1 labelsize 11 align 4 } { Fl_Value_Input {} { label {Row:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; if (v == LOAD) { int m = 0; grid->gap(&m, NULL); o->value(m); } else { int m = (int)o->value(), old_m, m2; grid->gap(&old_m, &m2); if (m != old_m) { undo_checkpoint(); grid->gap(m, m2); grid->need_layout(true); set_modflag(1); } }} tooltip {Gap between children.} xywh {95 135 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 } Fl_Value_Input {} { label {Col:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; if (v == LOAD) { int m = 0; grid->gap(NULL, &m); o->value(m); } else { int m = (int)o->value(), old_m, m2; grid->gap(&m2, &old_m); if (m != old_m) { undo_checkpoint(); grid->gap(m2, m); grid->need_layout(true); set_modflag(1); } }} tooltip {Gap between children.} xywh {155 135 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 } Fl_Box {} { xywh {396 135 0 20} resizable } } Fl_Group {} { label {Row:} callback {if (v == LOAD) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (grid) o->activate(); else o->deactivate(); propagate_load(o, v); }} open xywh {95 175 315 20} labelfont 1 labelsize 11 align 4 } { Fl_Input widget_grid_curr_row { label Index callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int r = o->value(), old_r = r; if (r < 0) r = 0; if (r >= grid->rows()) r = grid->rows()-1; if (r != old_r) o->value(r); if (v == LOAD) { // will automatically propagate } else { widget_grid_curr_row_attributes->do_callback(widget_grid_curr_row_attributes, LOAD); }} xywh {95 175 40 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Group {} { callback propagate_load open xywh {135 175 30 20} } { Fl_Button {} { label {-} callback {if (v != LOAD) { widget_grid_curr_row->value( widget_grid_curr_row->value()-1 ); widget_grid_curr_row->do_callback(); }} xywh {135 175 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } Fl_Button {} { label {+} callback {if (v != LOAD) { widget_grid_curr_row->value( widget_grid_curr_row->value()+1 ); widget_grid_curr_row->do_callback(); }} xywh {150 175 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } } Fl_Box {} { label {:} xywh {165 175 15 20} labelsize 11 } Fl_Group widget_grid_curr_row_attributes { callback propagate_load open xywh {180 175 175 20} } { Fl_Input {} { label {Height:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int r = widget_grid_curr_row->value(); if (v == LOAD) { o->value(grid->row_height(r)); } else { int h = o->value(), old_h = grid->row_height(r); if (h < 0) h = 0; if (h != old_h) { undo_checkpoint(); grid->row_height(r, h); grid->need_layout(true); set_modflag(1); } }} xywh {180 175 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Input {} { label {Weight:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int r = widget_grid_curr_row->value(); if (v == LOAD) { o->value(grid->row_weight(r)); } else { int h = o->value(), old_h = grid->row_weight(r); if (h < 0) h = 0; if (h != old_h) { undo_checkpoint(); grid->row_weight(r, h); grid->need_layout(true); set_modflag(1); } }} xywh {240 175 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Input {} { label {Gap:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int r = widget_grid_curr_row->value(); if (v == LOAD) { o->value(grid->row_gap(r)); } else { int h = o->value(), old_h = grid->row_gap(r); if (h < -1) h = -1; if (h != old_h) { undo_checkpoint(); grid->row_gap(r, h); grid->need_layout(true); set_modflag(1); } }} xywh {300 175 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } } Fl_Box {} { xywh {400 175 1 20} hide resizable } } Fl_Group {} { label {Column:} callback propagate_load open xywh {95 210 315 20} labelfont 1 labelsize 11 align 4 } { Fl_Input widget_grid_curr_col { label Index callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int c = o->value(), old_c = c; if (c < 0) c = 0; if (c >= grid->cols()) c = grid->cols()-1; if (c != old_c) o->value(c); if (v == LOAD) { // will automatically propagate } else { widget_grid_curr_col_attributes->do_callback(widget_grid_curr_col_attributes, LOAD); }} xywh {95 210 40 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Group {} {open xywh {135 210 30 20} } { Fl_Button {} { label {-} callback {if (v != LOAD) { widget_grid_curr_col->value( widget_grid_curr_col->value()-1 ); widget_grid_curr_col->do_callback(); }} xywh {135 210 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } Fl_Button {} { label {+} callback {if (v != LOAD) { widget_grid_curr_col->value( widget_grid_curr_col->value()+1 ); widget_grid_curr_col->do_callback(); }} xywh {150 210 15 20} labelsize 11 code0 {o->clear_visible_focus();} compact 1 } } Fl_Box {} { label {:} xywh {165 210 15 20} labelsize 11 } Fl_Group widget_grid_curr_col_attributes { callback propagate_load open xywh {180 210 175 20} } { Fl_Input {} { label {Width:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int c = widget_grid_curr_col->value(); if (v == LOAD) { o->value(grid->col_width(c)); } else { int h = o->value(), old_h = grid->col_width(c); if (h < 0) h = 0; if (h != old_h) { undo_checkpoint(); grid->col_width(c, h); grid->need_layout(true); set_modflag(1); } }} xywh {180 210 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Input {} { label {Weight:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int c = widget_grid_curr_col->value(); if (v == LOAD) { o->value(grid->col_weight(c)); } else { int h = o->value(), old_h = grid->col_weight(c); if (h < 0) h = 0; if (h != old_h) { undo_checkpoint(); grid->col_weight(c, h); grid->need_layout(true); set_modflag(1); } }} xywh {240 210 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } Fl_Input {} { label {Gap:} callback {Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int c = widget_grid_curr_col->value(); if (v == LOAD) { o->value(grid->col_gap(c)); } else { int h = o->value(), old_h = grid->col_gap(c); if (h < -1) h = -1; if (h != old_h) { undo_checkpoint(); grid->col_gap(c, h); grid->need_layout(true); set_modflag(1); } }} xywh {300 210 55 20} labelsize 11 align 5 textsize 11 class Fluid_Coord_Input } } Fl_Box {} { xywh {400 210 1 20} hide resizable } } Fl_Box {} { xywh {95 350 300 5} labelsize 11 hide resizable } } } Fl_Tabs widget_tabs_repo { xywh {10 10 400 350} hide code0 {o->hide();} } { Fl_Group {} {open xywh {10 30 400 330} resizable } {} } Fl_Group {} { xywh {10 370 400 20} labelsize 11 } { Fl_Button wLiveMode { label {Live &Resize} callback live_mode_cb tooltip {Create a live duplicate of the selected widgets to test resizing and menu behavior.} xywh {10 370 80 20} type Toggle labelsize 10 } Fl_Button overlay_button { label {Hide &Overlays} callback overlay_cb tooltip {Hide the widget overlay box.} xywh {94 370 80 20} labelsize 10 } Fl_Box {} { comment {Hidden resizable box} xywh {258 370 72 20} labelsize 11 hide resizable } Fl_Return_Button {} { label Close callback ok_cb xywh {330 370 80 20} labelsize 11 } } } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/fluid/Fl_Type.cxx������������������������������������������������������������������������0000644�0001750�0001750�00000113751�15004135251�016006� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // Widget type code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /// \defgroup fl_type Basic Node for all Widgets and Functions /// \{ /** \class Fl_Type Each object described by Fluid is one of these objects. They are all stored in a double-linked list. The "type" of the object is covered by the virtual functions. There will probably be a lot of these virtual functions. The type browser is also a list of these objects, but they are "factory" instances, not "real" ones. These objects exist only so the "make" method can be called on them. They are not in the linked list and are not written to files or copied or otherwise examined. The Fl_Type inheritance is currently: --+-- Fl_Type +-- Fl_Function_Type +-- Fl_Code_Type +-- Fl_CodeBlock_Type +-+ Fl_Decl_Type | +-- Fl_Data +-- Fl_DeclBlock_Type +-- Fl_Comment_Type +-- Fl_Class_Type +-+ Fl_Widget_Type, 'o' points to a class derived from Fl_Widget +-+ Fl_Browser_Base_Type, 'o' is Fl_Browser | +-+ Fl_Browser | | +-- Fl_File_Browser | +-- Fl_Check_Browser +-- Fl_Tree_Type +-- Fl_Help_View_Type +-+ Fl_Valuator_Type, 'o' is Fl_Valuator_ | +-- Fl_Counter_Type | +-- Fl_Adjuster_Type | +-- Fl_Dial_Type | +-- Fl_Roller_Type | +-- Fl_Slider_Type | +-- Fl_Value_Input_Type | +-- Fl_Value_Output_Type +-+ Fl_Input_Type | +-- Fl_Output_Type +-+ Fl_Text_Display_Type | +-- Fl_Text_Editor_Type +-- Fl_Terminal_Type +-- Fl_Box_Type +-- Fl_Clock_Type +-- Fl_Progress_Type +-- Fl_Spinner_Type +-+ Fl_Group_Type | +-- Fl_Pack_Type | +-- Fl_Flex_Type | +-- Fl_Grid_Type | +-- Fl_Table_Type | +-- Fl_Tabs_Type | +-- Fl_Scroll_Type | +-- Fl_Tile_Type | +-- Fl_Wizard_Type | +-+ Fl_Window_Type | +-- Fl_Widget_Class_Type +-+ Fl_Menu_Manager_Type, 'o' is based on Fl_Widget | +-+ Fl_Menu_Base_Type, 'o' is based on Fl_Menu_ | | +-- Fl_Menu_Button_Type | | +-- Fl_Choice_Type | | +-- Fl_Menu_Bar_Type | +-- Fl_Input_Choice_Type, 'o' is based on Fl_Input_Choice which is Fl_Group +-+ Fl_Button_Type +-- Fl_Return_Button_Type +-- Fl_Repeat_Button_Type +-- Fl_Light_Button_Type +-- Fl_Check_Button_Type +-- Fl_Round_Button_Type +-+ Fl_Menu_Item_Type, 'o' is derived from Fl_Button in FLUID +-- Fl_Radio_Menu_Item_Type +-- Fl_Checkbox_Menu_Item_Type +-- Fl_Submenu_Item_Type */ #include "Fl_Type.h" #include "fluid.h" #include "Fd_Snap_Action.h" #include "Fl_Function_Type.h" #include "Fl_Widget_Type.h" #include "Fl_Window_Type.h" #include "Fl_Group_Type.h" #include "widget_browser.h" #include "file.h" #include "code.h" #include "undo.h" #include "pixmaps.h" #include "shell_command.h" #include <FL/Fl.H> #include <FL/Fl_Browser_.H> #include <FL/fl_draw.H> #include "../src/flstring.h" #include <stdlib.h> #include <stdio.h> // ---- global variables Fl_Type *Fl_Type::first = NULL; Fl_Type *Fl_Type::last = NULL; Fl_Type *Fl_Type::current = NULL; Fl_Type *Fl_Type::current_dnd = NULL; int Fl_Type::allow_layout = 0; Fl_Type *in_this_only; // set if menu popped-up in window // ---- various functions #if 0 #ifndef NDEBUG /** Print the current project tree to stderr. */ void print_project_tree() { fprintf(stderr, "---- %s --->\n", g_project.projectfile_name().c_str()); for (Fl_Type *t = Fl_Type::first; t; t = t->next) { for (int i = t->level; i > 0; i--) fprintf(stderr, ". "); fprintf(stderr, "%s\n", subclassname(t)); } } #endif #ifndef NDEBUG /** Check the validity of the project tree. Write problems with the project tree to stderr. \return true if the project tree is valid */ bool validate_project_tree() { // Validate `first` and `last` if (Fl_Type::first == NULL) { if (Fl_Type::last == NULL) { return true; } else { fprintf(stderr, "ERROR: `first` is NULL, but `last` is not!\n"); return false; } } if (Fl_Type::last == NULL) { fprintf(stderr, "ERROR: `last` is NULL, but `first` is not!\n"); return false; } // Validate the branch linkage, parent links, etc. return validate_branch(Fl_Type::first); } #endif #ifndef NDEBUG /** Check the validity of a Type branch that is not connected to the project. Write problems with the branch to stderr. \param[in] root the first node in a branch \return true if the branch is correctly separated and valid */ bool validate_independent_branch(class Fl_Type *root) { // Make sure that `first` and `last` do not point at any node in this branch if (Fl_Type::first) { for (Fl_Type *t = root; t; t = t->next) { if (Fl_Type::first == t) { fprintf(stderr, "ERROR: Branch is not independent, `first` is pointing to branch member!\n"); return false; } } } if (Fl_Type::last) { for (Fl_Type *t = root; t; t = t->next) { if (Fl_Type::last == t) { fprintf(stderr, "ERROR: Branch is not independent, `last` is pointing to branch member!\n"); return false; } } } // Validate the branch linkage, parent links, etc. return validate_branch(root); } #endif #ifndef NDEBUG /** Check the validity of a Type branch. Write problems with the branch to stderr. \param[in] root the first node in a branch \return true if the branch is valid */ bool validate_branch(class Fl_Type *root) { // Only check real branches if (!root) { fprintf(stderr, "WARNING: Branch is empty!\n"); return false; } // Check relation between this and next node for (Fl_Type *t = root; t; t = t->next) { if (t->level < root->level) { fprintf(stderr, "ERROR: Node in tree is above root level!\n"); return false; } if (t->next) { // Make sure that all `next` types have the `prev` member link back if (t->next->prev != t) { fprintf(stderr, "ERROR: Doubly linked list broken!\n"); return false; } if (t->next->level > t->level) { // Validate `level` changes if (t->next->level - t->level > 1) { fprintf(stderr, "ERROR: Child level increment greater than one!\n"); return false; } // Ensure that this node can actually have children if (!t->can_have_children()) { fprintf(stderr, "ERROR: This parent must not have children!\n"); return false; } } } // Validate the `parent` entry for (Fl_Type *p = t->prev; ; p = p->prev) { if (p == NULL) { if (t->parent != NULL) { fprintf(stderr, "ERROR: `parent` pointer should be NULL!\n"); return false; } break; } if (p->level < t->level) { if (t->parent != p) { fprintf(stderr, "ERROR: `parent` points to wrong parent!\n"); return false; } break; } } } return true; } #endif #endif void select_all_cb(Fl_Widget *,void *) { Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0; if (in_this_only) { Fl_Type *t = p; for (; t && t != in_this_only; t = t->parent) {/*empty*/} if (t != in_this_only) p = in_this_only; } for (;;) { if (p) { int foundany = 0; for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) { if (!t->new_selected) {widget_browser->select(t,1,0); foundany = 1;} } if (foundany) break; p = p->parent; } else { for (Fl_Type *t = Fl_Type::first; t; t = t->next) widget_browser->select(t,1,0); break; } } selection_changed(p); } void select_none_cb(Fl_Widget *,void *) { Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0; if (in_this_only) { Fl_Type *t = p; for (; t && t != in_this_only; t = t->parent) {/*empty*/} if (t != in_this_only) p = in_this_only; } for (;;) { if (p) { int foundany = 0; for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) { if (t->new_selected) {widget_browser->select(t,0,0); foundany = 1;} } if (foundany) break; p = p->parent; } else { for (Fl_Type *t = Fl_Type::first; t; t = t->next) widget_browser->select(t,0,0); break; } } selection_changed(p); } /** Callback to move all selected items before their previous unselected sibling. */ void earlier_cb(Fl_Widget*,void*) { Fl_Type *f; int mod = 0; for (f = Fl_Type::first; f; ) { Fl_Type* nxt = f->next; if (f->selected) { Fl_Type* g; for (g = f->prev; g && g->level > f->level; g = g->prev) {/*empty*/} if (g && g->level == f->level && !g->selected) { if (!mod) undo_checkpoint(); f->move_before(g); if (f->parent) f->parent->layout_widget(); mod = 1; } } f = nxt; } if (mod) set_modflag(1); widget_browser->display(Fl_Type::current); widget_browser->rebuild(); } /** Callback to move all selected items after their next unselected sibling. */ void later_cb(Fl_Widget*,void*) { Fl_Type *f; int mod = 0; for (f = Fl_Type::last; f; ) { Fl_Type* prv = f->prev; if (f->selected) { Fl_Type* g; for (g = f->next; g && g->level > f->level; g = g->next) {/*empty*/} if (g && g->level == f->level && !g->selected) { if (!mod) undo_checkpoint(); g->move_before(f); if (f->parent) f->parent->layout_widget(); mod = 1; } } f = prv; } if (mod) set_modflag(1); widget_browser->display(Fl_Type::current); widget_browser->rebuild(); } /** \brief Delete all children of a Type. */ static void delete_children(Fl_Type *p) { Fl_Type *f; // find all types following p that are higher in level, effectively finding // the last child of the last child for (f = p; f && f->next && f->next->level > p->level; f = f->next) {/*empty*/} // now loop back up to p, deleting all children on the way for (; f != p; ) { Fl_Type *g = f->prev; delete f; f = g; } } /** Delete all nodes in the Types tree and reset project settings, or delete selected nodes. Also calls the browser to refresh. \note Please refactor this into two separate methods of Fluid_Project. \param[in] selected_only if set, delete only the selected widgets and don't reset the project. */ void delete_all(int selected_only) { if (widget_browser) { if (selected_only) widget_browser->save_scroll_position(); widget_browser->new_list(); } for (Fl_Type *f = Fl_Type::first; f;) { if (f->selected || !selected_only) { delete_children(f); Fl_Type *g = f->next; delete f; f = g; } else { f = f->next; } } if(!selected_only) { // reset the setting for the external shell command if (g_shell_config) { g_shell_config->clear(FD_STORE_PROJECT); g_shell_config->rebuild_shell_menu(); g_shell_config->update_settings_dialog(); } if (widget_browser) { widget_browser->hposition(0); widget_browser->vposition(0); } g_layout_list.remove_all(FD_STORE_PROJECT); g_layout_list.current_suite(0); g_layout_list.current_preset(0); g_layout_list.update_dialogs(); } selection_changed(0); if (widget_browser) { if (selected_only) widget_browser->restore_scroll_position(); widget_browser->rebuild(); } } /** Update a string. Replace a string pointer with new value, strips leading/trailing blanks. As a side effect, this call also sets the mod flags. \param[in] n new string, can be NULL \param[out] p update this pointer, possibly reallocate memory \param[in] nostrip if set, do not strip leading and trailing spaces and tabs \return 1 if the string in p changed */ int storestring(const char *n, const char * & p, int nostrip) { if (n == p) return 0; undo_checkpoint(); int length = 0; if (n) { // see if blank, strip leading & trailing blanks if (!nostrip) while (isspace((int)(unsigned char)*n)) n++; const char *e = n + strlen(n); if (!nostrip) while (e > n && isspace((int)(unsigned char)*(e-1))) e--; length = int(e-n); if (!length) n = 0; } if (n == p) return 0; if (n && p && !strncmp(n,p,length) && !p[length]) return 0; if (p) free((void *)p); if (!n || !*n) { p = 0; } else { char *q = (char *)malloc(length+1); strlcpy(q,n,length+1); p = q; } set_modflag(1); return 1; } /** Update the `visible` flag for `p` and all its descendants. \param[in] p start here and update all descendants */ void update_visibility_flag(Fl_Type *p) { Fl_Type *t = p; for (;;) { if (t->parent) t->visible = t->parent->visible && !t->parent->folded_; else t->visible = 1; t = t->next; if (!t || t->level <= p->level) break; } } // ---- implementation of Fl_Type /** \var Fl_Type *Fl_Type::parent Link to the parent node in the tree structure. Used for simulating a tree structure via a doubly linked list. */ /** \var Fl_Type *Fl_Type::level Zero based depth of the node within the tree structure. Level is used to emulate a tree structure: the first node with a lower level in the prev list would be the parent of this node. If the next member has a higher level value, it is this nodes first child. At the same level, it would be the first sibling. */ /** \var Fl_Type *Fl_Type::next Points to the next node in the doubly linked list. If this is NULL, we are at the end of the list. Used for simulating a tree structure via a doubly linked list. */ /** \var Fl_Type *Fl_Type::prev Link to the next node in the tree structure. If this is NULL, we are at the beginning of the list. Used for simulating a tree structure via a doubly linked list. */ /** Constructor and base for any node in the widget tree. */ Fl_Type::Fl_Type() : name_(NULL), label_(NULL), callback_(NULL), user_data_(NULL), user_data_type_(NULL), comment_(NULL), uid_(0), parent(NULL), new_selected(0), selected(0), folded_(0), visible(0), level(0), next(NULL), prev(NULL), factory(NULL), code_static_start(-1), code_static_end(-1), code1_start(-1), code1_end(-1), code2_start(-1), code2_end(-1), header1_start(-1), header1_end(-1), header2_start(-1), header2_end(-1), header_static_start(-1), header_static_end(-1), proj1_start(-1), proj1_end(-1), proj2_start(-1), proj2_end(-1) { } /** Destructor for any node in the tree. The destructor removes itself from the doubly linked list. This is dangerous, because the node does not know if it is part of the widget tree, or if it is in a separate tree. We try to take care of that as well as possible. */ Fl_Type::~Fl_Type() { // warning: destructor only works for widgets that have been add()ed. if (prev) prev->next = next; // else first = next; // don't do that! The Type may not be part of the main list if (next) next->prev = prev; // else last = prev; if (Fl_Type::last == this) Fl_Type::last = prev; if (Fl_Type::first == this) Fl_Type::first = next; if (current == this) current = NULL; if (parent) parent->remove_child(this); if (name_) free((void*)name_); if (label_) free((void*)label_); if (callback_) free((void*)callback_); if (user_data_) free((void*)user_data_); if (user_data_type_) free((void*)user_data_type_); if (comment_) free((void*)comment_); } // Return the previous sibling in the tree structure or NULL. Fl_Type *Fl_Type::prev_sibling() { Fl_Type *n; for (n = prev; n && n->level > level; n = n->prev) ; if (n && (n->level == level)) return n; return 0; } // Return the next sibling in the tree structure or NULL. Fl_Type *Fl_Type::next_sibling() { Fl_Type *n; for (n = next; n && n->level > level; n = n->next) ; if (n && (n->level == level)) return n; return 0; } // Return the first child or NULL Fl_Type *Fl_Type::first_child() { Fl_Type *n = next; if (n->level > level) return n; return NULL; } // Generate a descriptive text for this item, to put in browser & window titles const char* Fl_Type::title() { const char* c = name(); if (c) return c; return type_name(); } /** Return the window that contains this widget. \return NULL if this is not a widget. */ Fl_Window_Type *Fl_Type::window() { if (!is_widget()) return NULL; for (Fl_Type *t = this; t; t=t->parent) if (t->is_a(ID_Window)) return (Fl_Window_Type*)t; return NULL; } /** Return the group that contains this widget. \return NULL if this is not a widget. */ Fl_Group_Type *Fl_Type::group() { if (!is_widget()) return NULL; for (Fl_Type *t = this; t; t=t->parent) if (t->is_a(ID_Group)) return (Fl_Group_Type*)t; return NULL; } /** Add this list/tree of widgets as a new last child of p. \c this must not be part of the widget browser. \c p however must be in the widget_browser, so \c Fl_Type::first and \c Fl_Type::last are valid for \c p. This methods updates the widget_browser. \param[in] p insert \c this tree as a child of \c p \param[in] strategy is Strategy::AS_LAST_CHILD or Strategy::AFTER_CURRENT */ void Fl_Type::add(Fl_Type *anchor, Strategy strategy) { #if 0 #ifndef NDEBUG // print_project_tree(); // fprintf(stderr, "Validating project\n"); validate_project_tree(); // fprintf(stderr, "Validating branch\n"); validate_independent_branch(this); #endif #endif Fl_Type *target = NULL; // insert self before target node, if NULL, insert last Fl_Type *target_parent = NULL; // this will be the new parent for branch int target_level = 0; // adjust self to this new level // Find the node after our insertion position switch (strategy.placement()) { case Strategy::AS_FIRST_CHILD: default: if (anchor == NULL) { target = Fl_Type::first; } else { target = anchor->next; target_level = anchor->level + 1; target_parent = anchor; } break; case Strategy::AS_LAST_CHILD: if (anchor == NULL) { /* empty */ } else { for (target = anchor->next; target && target->level > anchor->level; target = target->next) {/*empty*/} target_level = anchor->level + 1; target_parent = anchor; } break; case Strategy::AFTER_CURRENT: if (anchor == NULL) { target = Fl_Type::first; } else { for (target = anchor->next; target && target->level > anchor->level; target = target->next) {/*empty*/} target_level = anchor->level; target_parent = anchor->parent; } break; } // Find the last node of our tree Fl_Type *end = this; while (end->next) end = end->next; // Everything is prepared, now insert ourself in front of the target node undo_checkpoint(); // Walk the tree to update parent pointers and levels int source_level = level; for (Fl_Type *t = this; t; t = t->next) { t->level += (target_level-source_level); if (t->level == target_level) t->parent = target_parent; } // Now link ourselves and our children before 'target', or last, if 'target' is NULL if (target) { prev = target->prev; target->prev = end; end->next = target; } else { prev = Fl_Type::last; end->next = NULL; Fl_Type::last = end; } if (prev) { prev->next = this; } else { Fl_Type::first = this; } #if 0 { // make sure that we have no duplicate uid's Fl_Type *tp = this; do { tp->set_uid(tp->uid_); tp = tp->next; } while (tp!=end && tp!=NULL); } #endif // Give the widgets in our tree a chance to update themselves for (Fl_Type *t = this; t && t!=end->next; t = t->next) { if (target_parent && (t->level == target_level)) target_parent->add_child(t, 0); update_visibility_flag(t); } set_modflag(1); widget_browser->redraw(); #if 0 #ifndef NDEBUG // fprintf(stderr, "Validating project after adding branch\n"); validate_project_tree(); #endif #endif } /** Add `this` list/tree of widgets as a new sibling before `g`. `This` is not part of the widget browser. `g` must be in the widget_browser, so `Fl_Type::first` and `Fl_Type::last` are valid for `g . This methods updates the widget_browser. \param[in] g pointer to a node within the tree */ void Fl_Type::insert(Fl_Type *g) { // 'this' is not in the Widget_Browser, so we must run the linked list to find the last entry Fl_Type *end = this; while (end->next) end = end->next; // 'this' will get the same parent as 'g' parent = g->parent; // run the list again to set the future node levels int newlevel = g->level; visible = g->visible; for (Fl_Type *t = this->next; t; t = t->next) t->level += newlevel-level; level = newlevel; // insert this in the list before g prev = g->prev; if (prev) prev->next = this; else first = this; end->next = g; g->prev = end; update_visibility_flag(this); { // make sure that we have no duplicate uid's Fl_Type *tp = this; do { tp->set_uid(tp->uid_); tp = tp->next; } while (tp!=end && tp!=NULL); } // tell parent that it has a new child, so it can update itself if (parent) parent->add_child(this, g); widget_browser->redraw(); } // Return message number for I18N... int Fl_Type::msgnum() { int count; Fl_Type *p; for (count = 0, p = this; p;) { if (p->label()) count ++; if (p != this && p->is_widget() && ((Fl_Widget_Type *)p)->tooltip()) count ++; if (p->prev) p = p->prev; else p = p->parent; } return count; } /** Remove this node and all its children from the parent node. This does not delete anything. The resulting list//tree will no longer be in the widget_browser, so \c Fl_Type::first and \c Fl_Type::last do not apply to it. \return the node that follows this node after the operation; can be NULL */ Fl_Type *Fl_Type::remove() { // find the last child of this node Fl_Type *end = this; for (;;) { if (!end->next || end->next->level <= level) break; end = end->next; } // unlink this node from the previous one if (prev) prev->next = end->next; else first = end->next; // unlink the last child from their next node if (end->next) end->next->prev = prev; else last = prev; Fl_Type *r = end->next; prev = end->next = 0; // allow the parent to update changes in the UI if (parent) parent->remove_child(this); parent = 0; // tell the widget_browser that we removed some nodes widget_browser->redraw(); selection_changed(0); return r; } void Fl_Type::name(const char *n) { int nostrip = is_a(ID_Comment); if (storestring(n,name_,nostrip)) { if (visible) widget_browser->redraw(); } } void Fl_Type::label(const char *n) { if (storestring(n,label_,1)) { setlabel(label_); if (visible && !name_) widget_browser->redraw(); } } void Fl_Type::callback(const char *n) { storestring(n,callback_); } void Fl_Type::user_data(const char *n) { storestring(n,user_data_); } void Fl_Type::user_data_type(const char *n) { storestring(n,user_data_type_); } void Fl_Type::comment(const char *n) { if (storestring(n,comment_,1)) { if (visible) widget_browser->redraw(); } } void Fl_Type::open() { printf("Open of '%s' is not yet implemented\n",type_name()); } // returns pointer to whatever is after f & children /** Move this node (and its children) into list before g. Both `this` and `g` must be in the widget browser. The caller must make sure that the widget browser is rebuilt correctly. \param[in] g move \c this tree before \c g */ void Fl_Type::move_before(Fl_Type* g) { if (level != g->level) printf("move_before levels don't match! %d %d\n", level, g->level); // Find the last child in the list Fl_Type *n; for (n = next; n && n->level > level; n = n->next) ; if (n == g) return; // now link this tree before g Fl_Type *l = n ? n->prev : Fl_Type::last; prev->next = n; if (n) n->prev = prev; else Fl_Type::last = prev; prev = g->prev; l->next = g; if (prev) prev->next = this; else Fl_Type::first = this; g->prev = l; // tell parent that it has a new child, so it can update itself if (parent && is_widget()) parent->move_child(this,g); } // write a widget and all its children: void Fl_Type::write(Fd_Project_Writer &f) { if (f.write_codeview()) proj1_start = (int)ftell(f.file()) + 1; if (f.write_codeview()) proj2_start = (int)ftell(f.file()) + 1; f.write_indent(level); f.write_word(type_name()); if (is_class()) { const char * p = ((Fl_Class_Type*)this)->prefix(); if (p && strlen(p)) f.write_word(p); } f.write_word(name()); f.write_open(); write_properties(f); if (parent) parent->write_parent_properties(f, this, true); f.write_close(level); if (f.write_codeview()) proj1_end = (int)ftell(f.file()); if (!can_have_children()) { if (f.write_codeview()) proj2_end = (int)ftell(f.file()); return; } // now do children: f.write_open(); Fl_Type *child; for (child = next; child && child->level > level; child = child->next) if (child->level == level+1) child->write(f); if (f.write_codeview()) proj2_start = (int)ftell(f.file()) + 1; f.write_close(level); if (f.write_codeview()) proj2_end = (int)ftell(f.file()); } void Fl_Type::write_properties(Fd_Project_Writer &f) { // repeat this for each attribute: if (g_project.write_mergeback_data && uid_) { f.write_word("uid"); f.write_string("%04x", uid_); } if (label()) { f.write_indent(level+1); f.write_word("label"); f.write_word(label()); } if (user_data()) { f.write_indent(level+1); f.write_word("user_data"); f.write_word(user_data()); } if (user_data_type()) { f.write_word("user_data_type"); f.write_word(user_data_type()); } if (callback()) { f.write_indent(level+1); f.write_word("callback"); f.write_word(callback()); } if (comment()) { f.write_indent(level+1); f.write_word("comment"); f.write_word(comment()); } if (can_have_children() && !folded_) f.write_word("open"); if (selected) f.write_word("selected"); } void Fl_Type::read_property(Fd_Project_Reader &f, const char *c) { if (!strcmp(c,"uid")) { const char *hex = f.read_word(); int x = 0; if (hex) x = sscanf(hex, "%04x", &x); set_uid(x); } else if (!strcmp(c,"label")) label(f.read_word()); else if (!strcmp(c,"user_data")) user_data(f.read_word()); else if (!strcmp(c,"user_data_type")) user_data_type(f.read_word()); else if (!strcmp(c,"callback")) callback(f.read_word()); else if (!strcmp(c,"comment")) comment(f.read_word()); else if (!strcmp(c,"open")) folded_ = 0; else if (!strcmp(c,"selected")) select(this,1); else if (!strcmp(c,"parent_properties")) if (parent) { const char *cc = f.read_word(1); if (strcmp(cc, "{")==0) { for (;;) { cc = f.read_word(); if (!cc || cc[0]==0 || strcmp(cc, "}")==0) break; parent->read_parent_property(f, this, cc); } } else { f.read_error("'parent_properties' must be followed by '{'"); } } else { f.read_error("Types using 'parent_properties' must have a parent"); f.read_word(); // skip the entire block (this should generate a warning) } else f.read_error("Unknown property \"%s\"", c); } /** Write parent properties into the child property list. Some widgets store information for every child they manage. For example, Fl_Grid stores the row and column position of every child. This method stores this information with the child, but it is read and written by the parent. Parent properties solve several issues. A child will keep parent properties if copied from on grid into another. The parent does not have to keep lists of properties that may diverge from the actual order or number of children. And lastly, properties are read when they are actually needed and don't have to be stored in some temporary array. Parent properties are written as their own block at the end of the child's property list. The block starts with the `parent_properties` keyword, followed by a list of property/value pairs. The order of properties is significant, however individual properties can be left out. To avoid writing the `parent_properties` block unnecessarily, this method should only generate it if `encapsulate` is set *and* the contained properties are not at their default. Lastly, this method should call the super class to give it a chance to append its own properties. \see Fl_Grid_Type::write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate) \param[in] f the project file writer \param[in] child write properties for this child, make sure it has the correct type \param[in] encapsulate write the `parent_properties {}` block if true before writing any properties */ void Fl_Type::write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate) { (void)f; (void)child; (void)encapsulate; // nothing to do here // put the following code into your implementation of write_parent_properties // if there are actual non-default properties to write // if (encapsulate) { // f.write_indent(level+2); // f.write_string("parent_properties {"); // } // now write your properties as name/value pairs // f.write_indent(level+3); // f.write_string("location {%d %d}", cell->row(), cell->col()); // give the super class a chance to write its properties as well // super::write_parent_properties(f, child, false); // close the encapsulation // if (encapsulate) { // f.write_indent(level+2); // f.write_string("}"); // } } /** Read one parent per-child property. A parent widget can store properties for every child that it manages. This method reads back those properties. This function is virtual, so if a Type does not support a property, it will propagate to its super class. \see Fl_Type::write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate) \see Fl_Grid_Type::read_parent_property(Fd_Project_Reader &f, Fl_Type *child, const char *property) \param[in] f the project file writer \param[in] child read properties for this child \param[in] property the name of a property, or "}" when we reach the end of the list */ void Fl_Type::read_parent_property(Fd_Project_Reader &f, Fl_Type *child, const char *property) { (void)child; f.read_error("Unknown parent property \"%s\"", property); } int Fl_Type::read_fdesign(const char*, const char*) {return 0;} /** Write a comment into the header file. \param[in] pre indent the comment by this string */ void Fl_Type::write_comment_h(Fd_Code_Writer& f, const char *pre) { if (comment() && *comment()) { f.write_h("%s/**\n", pre); const char *s = comment(); f.write_h("%s ", pre); while(*s) { if (*s=='\n') { if (s[1]) { f.write_h("\n%s ", pre); } } else { f.write_h("%c", *s); // FIXME this is much too slow! } s++; } f.write_h("\n%s*/\n", pre); } } /** Write a comment into the source file. */ void Fl_Type::write_comment_c(Fd_Code_Writer& f, const char *pre) { if (comment() && *comment()) { f.write_c("%s/**\n", pre); const char *s = comment(); if (*s && *s!='\n') f.write_c("%s ", pre); while(*s) { if (*s=='\n') { f.write_c("\n"); if (s[1] && s[1]!='\n') { f.write_c("%s ", pre); } } else { f.write_c("%c", *s); // FIXME this is much too slow! } s++; } f.write_c("\n%s*/\n", pre); } } /** Write a comment into the source file. */ void Fl_Type::write_comment_inline_c(Fd_Code_Writer& f, const char *pre) { if (comment() && *comment()) { const char *s = comment(); if (strchr(s, '\n')==0L) { // single line comment if (pre) f.write_c("%s", pre); f.write_c("// %s\n", s); if (!pre) f.write_c("%s", f.indent_plus(1)); } else { f.write_c("%s/*\n", pre?pre:""); if (*s && *s!='\n') { if (pre) f.write_c("%s ", pre); else f.write_c("%s ", f.indent_plus(1)); } while(*s) { if (*s=='\n') { f.write_c("\n"); if (s[1] && s[1]!='\n') { if (pre) f.write_c("%s ", pre); else f.write_c("%s ", f.indent_plus(1)); } } else { f.write_c("%c", *s); // FIXME this is much too slow! } s++; } if (pre) f.write_c("\n%s */\n", pre); else f.write_c("\n%s */\n", f.indent_plus(1)); if (!pre) f.write_c("%s", f.indent_plus(1)); } } } /** Build widgets and dataset needed in live mode. \return a widget pointer that the live mode initiator can 'show()' \see leave_live_mode() */ Fl_Widget *Fl_Type::enter_live_mode(int) { return 0L; } /** Release all resources created when entering live mode. \see enter_live_mode() */ void Fl_Type::leave_live_mode() { } /** Copy all needed properties for this type into the live object. */ void Fl_Type::copy_properties() { } /** Check whether callback \p cbname is declared anywhere else by the user. \b Warning: this just checks that the name is declared somewhere, but it should probably also check that the name corresponds to a plain function or a member function within the same class and that the parameter types match. */ int Fl_Type::user_defined(const char* cbname) const { for (Fl_Type* p = Fl_Type::first; p ; p = p->next) if (p->is_a(ID_Function) && p->name() != 0) if (strncmp(p->name(), cbname, strlen(cbname)) == 0) if (p->name()[strlen(cbname)] == '(') return 1; return 0; } const char *Fl_Type::callback_name(Fd_Code_Writer& f) { if (is_name(callback())) return callback(); return f.unique_id(this, "cb", name(), label()); } /** \brief Return the class name if this type is inside a Class or Widget Class. This methods traverses up the hirarchy to find out if this Type is located inside a Class or Widget Class. It then return the name of that class. If need_nest is set, class_name searches all the way up the tree and concatenates the names of classes within classes, separated by a "::". \param need_nest if clear, search up one level to the first enclosing class. If set, recurse all the way up to the top node. \return the name of the enclosing class, or names of the enclosing classes in a static buffe (don't call free), or NULL if this Type is not inside a class */ const char* Fl_Type::class_name(const int need_nest) const { Fl_Type* p = parent; while (p) { if (p->is_class()) { // see if we are nested in another class, we must fully-qualify name: // this is lame but works... const char* q = 0; if(need_nest) q=p->class_name(need_nest); if (q) { static char s[256]; if (q != s) strlcpy(s, q, sizeof(s)); strlcat(s, "::", sizeof(s)); strlcat(s, p->name(), sizeof(s)); return s; } return p->name(); } p = p->parent; } return 0; } /** Check if this is inside a Fl_Class_Type or Fl_Widget_Class_Type. \return true if any of the parents is Fl_Class_Type or Fl_Widget_Class_Type */ bool Fl_Type::is_in_class() const { Fl_Type* p = parent; while (p) { if (p->is_class()) return true; p = p->parent; } return false; } void Fl_Type::write_static(Fd_Code_Writer&) { } void Fl_Type::write_static_after(Fd_Code_Writer&) { } void Fl_Type::write_code1(Fd_Code_Writer& f) { f.write_h("// Header for %s\n", title()); f.write_c("// Code for %s\n", title()); } void Fl_Type::write_code2(Fd_Code_Writer&) { } /** Set a uid that is unique within the project. Try to set the given id as the unique id for this node. If the suggested id is 0, or it is already taken inside this project, we try another random id until we find one that is unique. \param[in] suggested_uid the preferred uid for this node \return the actualt uid that was given to the node */ unsigned short Fl_Type::set_uid(unsigned short suggested_uid) { if (suggested_uid==0) suggested_uid = (unsigned short)rand(); for (;;) { Fl_Type *tp = Fl_Type::first; for ( ; tp; tp = tp->next) if (tp!=this && tp->uid_==suggested_uid) break; if (tp==NULL) break; suggested_uid = (unsigned short)rand(); } uid_ = suggested_uid; return suggested_uid; } /** Find a node by its unique id. Every node in a type tree has an id that is unique for the current project. Walk the tree and return the node with this uid. \param[in] uid any number between 0 and 65535 \return the node with this uid, or NULL if not found */ Fl_Type *Fl_Type::find_by_uid(unsigned short uid) { for (Fl_Type *tp = Fl_Type::first; tp; tp = tp->next) { if (tp->uid_ == uid) return tp; } return NULL; } /** Find a type node by using the codeview text positions. \param[in] text_type 0=source file, 1=header, 2=.fl project file \param[in] crsr cursor position in text \return the node we found or NULL */ Fl_Type *Fl_Type::find_in_text(int text_type, int crsr) { for (Fl_Type *node = first; node; node = node->next) { switch (text_type) { case 0: if (crsr >= node->code1_start && crsr < node->code1_end) return node; if (crsr >= node->code2_start && crsr < node->code2_end) return node; if (crsr >= node->code_static_start && crsr < node->code_static_end) return node; break; case 1: if (crsr >= node->header1_start && crsr < node->header1_end) return node; if (crsr >= node->header2_start && crsr < node->header2_end) return node; if (crsr >= node->header_static_start && crsr < node->header_static_end) return node; break; case 2: if (crsr >= node->proj1_start && crsr < node->proj1_end) return node; if (crsr >= node->proj2_start && crsr < node->proj2_end) return node; break; } } return 0; } /// \} �����������������������fltk-1.4.3/fluid/comments.h�������������������������������������������������������������������������0000644�0001750�0001750�00000005313�15004135251�015710� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� static const char * const comment_text[] = { // GNU Public License/GPL Header "//\n" "// NameOfProgram, ShortDescription\n" "// Copyright (C) YYYY NameOfAuthor\n" "//\n" "// This program is free software: you can redistribute it and/or\n" "// modify it under the terms of the GNU General Public License\n" "// as published by the Free Software Foundation, either version 3\n" "// of the License, or (at your option) any later version.\n" "//\n" "// This program is distributed in the hope that it will be useful,\n" "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "// GNU General Public License for more details.\n" "//\n" "// You should have received a copy of the GNU General Public License\n" "// along with this program. If not, see <https://www.gnu.org/licenses/>.\n" "//\n", // GNU Public License/GPL Footer "\n//\n" "// NameOfProgram, ShortDescription\n" "// Copyright (C) YYYY NameOfAuthor\n" "//", // GNU Public License/LGPL Header "//\n" "// NameOfLibrary, ShortDescription\n" "// Copyright (C) YYYY NameOfAuthor\n" "//\n" "// This library is free software: you can redistribute it and/or\n" "// modify it under the terms of the GNU Lesser General Public License\n" "// as published by the Free Software Foundation, either version 3\n" "// of the License, or (at your option) any later version.\n" "//\n" "// This library is distributed in the hope that it will be useful,\n" "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "// GNU Lesser General Public License for more details.\n" "//\n" "// You should have received a copy of the GNU Lesser General Public License\n" "// along with this library. If not, see <https://www.gnu.org/licenses/>.\n" "//\n", // GNU Public License/LGPL Footer "\n//\n" "// NameOfLibrary, ShortDescription\n" "// Copyright (C) YYYY NameOfAuthor\n" "//", // FLTK/Header "//\n" "// ... for the Fast Light Tool Kit (FLTK).\n" "//\n" "// Copyright 1998-2023 by Bill Spitzak and others.\n" "//\n" "// This library is free software. Distribution and use rights are outlined in\n" "// the file \"COPYING\" which should have been included with this file. If this\n" "// file is missing or damaged, see the license at:\n" "//\n" "// https://www.fltk.org/COPYING.php\n" "//\n" "// Please see the following page on how to report bugs and issues:\n" "//\n" "// https://www.fltk.org/bugs.php\n" "//\n" }; ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/fluid/Fd_Snap_Action.cxx�����������������������������������������������������������������0000644�0001750�0001750�00000152043�15004135251�017250� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // Snap action code file for the Fast Light Tool Kit (FLTK). // // Copyright 2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fd_Snap_Action.h" #include "Fl_Group_Type.h" #include "settings_panel.h" #include "shell_command.h" // get and set Fl_String preferences #include "file.h" #include <FL/fl_draw.H> #include <FL/Fl_Menu_Bar.H> #include <FL/fl_string_functions.h> #include <math.h> #include <string.h> #include <assert.h> // TODO: warning if the user wants to change builtin layouts // TODO: move panel to global settings panel (move load & save to main pulldown, or to toolbox?) // INFO: how about a small tool box for quick preset selection and disabling of individual snaps? void select_layout_suite_cb(Fl_Widget *, void *user_data); int Fd_Snap_Action::eex = 0; int Fd_Snap_Action::eey = 0; static Fd_Layout_Preset fltk_app = { 15, 15, 15, 15, 0, 0, // window: l, r, t, b, gx, gy 10, 10, 10, 10, 0, 0, // group: l, r, t, b, gx, gy 25, 25, // tabs: t, b 20, 10, 4, // widget_x: min, inc, gap 20, 4, 8, // widget_y: min, inc, gap 0, 14, -1, 14 // labelfont/size, textfont/size }; static Fd_Layout_Preset fltk_dlg = { 10, 10, 10, 10, 0, 0, // window: l, r, t, b, gx, gy 10, 10, 10, 10, 0, 0, // group: l, r, t, b, gx, gy 20, 20, // tabs: t, b 20, 10, 5, // widget_x: min, inc, gap 20, 5, 5, // widget_y: min, inc, gap 0, 11, -1, 11 // labelfont/size, textfont/size }; static Fd_Layout_Preset fltk_tool = { 10, 10, 10, 10, 0, 0, // window: l, r, t, b, gx, gy 10, 10, 10, 10, 0, 0, // group: l, r, t, b, gx, gy 18, 18, // tabs: t, b 16, 8, 2, // widget_x: min, inc, gap 16, 4, 2, // widget_y: min, inc, gap 0, 10, -1, 10 // labelfont/size, textfont/size }; static Fd_Layout_Preset grid_app = { 12, 12, 12, 12, 12, 12, // window: l, r, t, b, gx, gy 12, 12, 12, 12, 12, 12, // group: l, r, t, b, gx, gy 24, 24, // tabs: t, b 12, 6, 6, // widget_x: min, inc, gap 12, 6, 6, // widget_y: min, inc, gap 0, 14, -1, 14 // labelfont/size, textfont/size }; static Fd_Layout_Preset grid_dlg = { 10, 10, 10, 10, 10, 10, // window: l, r, t, b, gx, gy 10, 10, 10, 10, 10, 10, // group: l, r, t, b, gx, gy 20, 20, // tabs: t, b 10, 5, 5, // widget_x: min, inc, gap 10, 5, 5, // widget_y: min, inc, gap 0, 12, -1, 12 // labelfont/size, textfont/size }; static Fd_Layout_Preset grid_tool = { 8, 8, 8, 8, 8, 8, // window: l, r, t, b, gx, gy 8, 8, 8, 8, 8, 8, // group: l, r, t, b, gx, gy 16, 16, // tabs: t, b 8, 4, 4, // widget_x: min, inc, gap 8, 4, 4, // widget_y: min, inc, gap 0, 10, -1, 10 // labelfont/size, textfont/size }; static Fd_Layout_Suite static_suite_list[] = { { (char*)"FLTK", (char*)"@fd_beaker FLTK", { &fltk_app, &fltk_dlg, &fltk_tool }, FD_STORE_INTERNAL }, { (char*)"Grid", (char*)"@fd_beaker Grid", { &grid_app, &grid_dlg, &grid_tool }, FD_STORE_INTERNAL } }; Fl_Menu_Item main_layout_submenu_[] = { { static_suite_list[0].menu_label, 0, select_layout_suite_cb, (void*)0, FL_MENU_RADIO|FL_MENU_VALUE }, { static_suite_list[1].menu_label, 0, select_layout_suite_cb, (void*)1, FL_MENU_RADIO }, { NULL } }; static Fl_Menu_Item static_choice_menu[] = { { static_suite_list[0].menu_label }, { static_suite_list[1].menu_label }, { NULL } }; Fd_Layout_Preset *layout = &fltk_app; Fd_Layout_List g_layout_list; // ---- Callbacks ------------------------------------------------------ MARK: - void layout_suite_marker(Fl_Widget *, void *) { // intentionally left empty } void select_layout_suite_cb(Fl_Widget *, void *user_data) { int index = (int)(fl_intptr_t)user_data; assert(index >= 0); assert(index < g_layout_list.list_size_); g_layout_list.current_suite(index); g_layout_list.update_dialogs(); } void select_layout_preset_cb(Fl_Widget *, void *user_data) { int index = (int)(fl_intptr_t)user_data; assert(index >= 0); assert(index < 3); g_layout_list.current_preset(index); g_layout_list.update_dialogs(); } void edit_layout_preset_cb(Fl_Button *w, long user_data) { int index = (int)w->argument(); assert(index >= 0); assert(index < 3); if (user_data == (long)(fl_intptr_t)LOAD) { w->value(g_layout_list.current_preset() == index); } else { g_layout_list.current_preset(index); g_layout_list.update_dialogs(); } } // ---- Fd_Layout_Suite ------------------------------------------------ MARK: - /** Write presets to a Preferences database. */ void Fd_Layout_Preset::write(Fl_Preferences &prefs) { assert(this); Fl_Preferences p_win(prefs, "Window"); p_win.set("left_margin", left_window_margin); p_win.set("right_margin", right_window_margin); p_win.set("top_margin", top_window_margin); p_win.set("bottom_margin", bottom_window_margin); p_win.set("grid_x", window_grid_x); p_win.set("grid_y", window_grid_y); Fl_Preferences p_grp(prefs, "Group"); p_grp.set("left_margin", left_group_margin); p_grp.set("right_margin", right_group_margin); p_grp.set("top_margin", top_group_margin); p_grp.set("bottom_margin", bottom_group_margin); p_grp.set("grid_x", group_grid_x); p_grp.set("grid_y", group_grid_y); Fl_Preferences p_tbs(prefs, "Tabs"); p_tbs.set("top_margin", top_tabs_margin); p_tbs.set("bottom_margin", bottom_tabs_margin); Fl_Preferences p_wgt(prefs, "Widget"); p_wgt.set("min_w", widget_min_w); p_wgt.set("inc_w", widget_inc_w); p_wgt.set("gap_x", widget_gap_x); p_wgt.set("min_h", widget_min_h); p_wgt.set("inc_h", widget_inc_h); p_wgt.set("gap_y", widget_gap_y); Fl_Preferences p_lyt(prefs, "Layout"); p_lyt.set("labelfont", labelfont); p_lyt.set("labelsize", labelsize); p_lyt.set("textfont", textfont); p_lyt.set("textsize", textsize); } /** Read presets from a Preferences database. */ void Fd_Layout_Preset::read(Fl_Preferences &prefs) { assert(this); Fl_Preferences p_win(prefs, "Window"); p_win.get("left_margin", left_window_margin, 15); p_win.get("right_margin", right_window_margin, 15); p_win.get("top_margin", top_window_margin, 15); p_win.get("bottom_margin", bottom_window_margin, 15); p_win.get("grid_x", window_grid_x, 0); p_win.get("grid_y", window_grid_y, 0); Fl_Preferences p_grp(prefs, "Group"); p_grp.get("left_margin", left_group_margin, 10); p_grp.get("right_margin", right_group_margin, 10); p_grp.get("top_margin", top_group_margin, 10); p_grp.get("bottom_margin", bottom_group_margin, 10); p_grp.get("grid_x", group_grid_x, 0); p_grp.get("grid_y", group_grid_y, 0); Fl_Preferences p_tbs(prefs, "Tabs"); p_tbs.get("top_margin", top_tabs_margin, 25); p_tbs.get("bottom_margin", bottom_tabs_margin, 25); Fl_Preferences p_wgt(prefs, "Widget"); p_wgt.get("min_w", widget_min_w, 20); p_wgt.get("inc_w", widget_inc_w, 10); p_wgt.get("gap_x", widget_gap_x, 4); p_wgt.get("min_h", widget_min_h, 20); p_wgt.get("inc_h", widget_inc_h, 4); p_wgt.get("gap_y", widget_gap_y, 8); Fl_Preferences p_lyt(prefs, "Layout"); p_lyt.get("labelfont", labelfont, 0); p_lyt.get("labelsize", labelsize, 14); p_lyt.get("textfont", textfont, 0); p_lyt.get("textsize", textsize, 14); } /** Write presets to an .fl project file. */ void Fd_Layout_Preset::write(Fd_Project_Writer *out) { out->write_string(" preset { 1\n"); // preset format version out->write_string(" %d %d %d %d %d %d\n", left_window_margin, right_window_margin, top_window_margin, bottom_window_margin, window_grid_x, window_grid_y); out->write_string(" %d %d %d %d %d %d\n", left_group_margin, right_group_margin, top_group_margin, bottom_group_margin, group_grid_x, group_grid_y); out->write_string(" %d %d\n", top_tabs_margin, bottom_tabs_margin); out->write_string(" %d %d %d %d %d %d\n", widget_min_w, widget_inc_w, widget_gap_x, widget_min_h, widget_inc_h, widget_gap_y); out->write_string(" %d %d %d %d\n", labelfont, labelsize, textfont, textsize); out->write_string(" }\n"); // preset format version } /** Read presets from an .fl project file. */ void Fd_Layout_Preset::read(Fd_Project_Reader *in) { const char *key; key = in->read_word(1); if (key && !strcmp(key, "{")) { for (;;) { key = in->read_word(); if (!key) return; if (key[0] == '}') break; int ver = atoi(key); if (ver == 0) { continue; } else if (ver == 1) { left_window_margin = in->read_int(); right_window_margin = in->read_int(); top_window_margin = in->read_int(); bottom_window_margin = in->read_int(); window_grid_x = in->read_int(); window_grid_y = in->read_int(); left_group_margin = in->read_int(); right_group_margin = in->read_int(); top_group_margin = in->read_int(); bottom_group_margin = in->read_int(); group_grid_x = in->read_int(); group_grid_y = in->read_int(); top_tabs_margin = in->read_int(); bottom_tabs_margin = in->read_int(); widget_min_w = in->read_int(); widget_inc_w = in->read_int(); widget_gap_x = in->read_int(); widget_min_h = in->read_int(); widget_inc_h = in->read_int(); widget_gap_y = in->read_int(); labelfont = in->read_int(); labelsize = in->read_int(); textfont = in->read_int(); textsize = in->read_int(); } else { // skip unknown chunks for (;;) { key = in->read_word(1); if (key && (key[0] == '}')) return; } } } } else { // format error } } /** Return the preferred text size, but make sure it's not 0. */ int Fd_Layout_Preset::textsize_not_null() { // try the user selected text size if (textsize > 0) return textsize; // if the user did not set one, try the label size if (labelsize > 0) return labelsize; // if that doesn;t work, fall back to the default value return 14; } // ---- Fd_Layout_Suite ------------------------------------------------ MARK: - /** Write a presets suite to a Preferences database. */ void Fd_Layout_Suite::write(Fl_Preferences &prefs) { assert(this); assert(name_); prefs.set("name", name_); for (int i = 0; i < 3; ++i) { Fl_Preferences prefs_preset(prefs, Fl_Preferences::Name(i)); assert(layout[i]); layout[i]->write(prefs_preset); } } /** Read a presets suite from a Preferences database. */ void Fd_Layout_Suite::read(Fl_Preferences &prefs) { assert(this); for (int i = 0; i < 3; ++i) { Fl_Preferences prefs_preset(prefs, Fl_Preferences::Name(i)); assert(layout[i]); layout[i]->read(prefs_preset); } } /** Write a presets suite to an .fl project file. */ void Fd_Layout_Suite::write(Fd_Project_Writer *out) { out->write_string(" suite {\n"); out->write_string(" name "); out->write_word(name_); out->write_string("\n"); for (int i = 0; i < 3; ++i) { layout[i]->write(out); } out->write_string(" }\n"); } /** Read a presets suite from an .fl project file. */ void Fd_Layout_Suite::read(Fd_Project_Reader *in) { const char *key; key = in->read_word(1); if (key && !strcmp(key, "{")) { int ix = 0; for (;;) { key = in->read_word(); if (!key) return; if (!strcmp(key, "name")) { name(in->read_word()); } else if (!strcmp(key, "preset")) { if (ix >= 3) return; // file format error layout[ix++]->read(in); } else if (!strcmp(key, "}")) { break; } else { in->read_word(); // unknown key, ignore, hopefully a key-value pair } } } else { // file format error } } /** \brief Update the menu_label to show a symbol representing the storage location. Also updates the FLUID user interface. */ void Fd_Layout_Suite::update_label() { Fl_String sym; switch (storage_) { case FD_STORE_INTERNAL: sym.assign("@fd_beaker "); break; case FD_STORE_USER: sym.assign("@fd_user "); break; case FD_STORE_PROJECT: sym.assign("@fd_project "); break; case FD_STORE_FILE: sym.assign("@fd_file "); break; } sym.append(name_); if (menu_label) ::free(menu_label); menu_label = fl_strdup(sym.c_str()); g_layout_list.update_menu_labels(); } /** \brief Update the Suite name and the Suite menu_label. Also updates the FLUID user interface. */ void Fd_Layout_Suite::name(const char *n) { if (name_) ::free(name_); if (n) name_ = fl_strdup(n); else name_ = NULL; update_label(); } /** Initialize the class for first use. */ void Fd_Layout_Suite::init() { name_ = NULL; menu_label = NULL; layout[0] = layout[1] = layout[2] = NULL; storage_ = FD_STORE_INTERNAL; } /** Free all allocated resources. */ Fd_Layout_Suite::~Fd_Layout_Suite() { if (storage_ == FD_STORE_INTERNAL) return; if (name_) ::free(name_); for (int i = 0; i < 3; ++i) { delete layout[i]; } } // ---- Fd_Layout_List ------------------------------------------------- MARK: - /** Draw a little FLUID beaker symbol. */ static void fd_beaker(Fl_Color c) { fl_color(221); fl_begin_polygon(); fl_vertex(-0.6, 0.2); fl_vertex(-0.9, 0.8); fl_vertex(-0.8, 0.9); fl_vertex( 0.8, 0.9); fl_vertex( 0.9, 0.8); fl_vertex( 0.6, 0.2); fl_end_polygon(); fl_color(c); fl_begin_line(); fl_vertex(-0.3, -0.9); fl_vertex(-0.2, -0.8); fl_vertex(-0.2, -0.2); fl_vertex(-0.9, 0.8); fl_vertex(-0.8, 0.9); fl_vertex( 0.8, 0.9); fl_vertex( 0.9, 0.8); fl_vertex( 0.2, -0.2); fl_vertex( 0.2, -0.8); fl_vertex( 0.3, -0.9); fl_end_line(); } /** Draw a user silhouette symbol */ static void fd_user(Fl_Color c) { fl_color(245); fl_begin_complex_polygon(); fl_arc( 0.1, 0.9, 0.8, 0.0, 80.0); fl_arc( 0.0, -0.5, 0.4, -65.0, 245.0); fl_arc(-0.1, 0.9, 0.8, 100.0, 180.0); fl_end_complex_polygon(); fl_color(c); fl_begin_line(); fl_arc( 0.1, 0.9, 0.8, 0.0, 80.0); fl_arc( 0.0, -0.5, 0.4, -65.0, 245.0); fl_arc(-0.1, 0.9, 0.8, 100.0, 180.0); fl_end_line(); } /** Draw a document symbol. */ static void fd_project(Fl_Color c) { Fl_Color fc = FL_LIGHT2; fl_color(fc); fl_begin_complex_polygon(); fl_vertex(-0.7, -1.0); fl_vertex(0.1, -1.0); fl_vertex(0.1, -0.4); fl_vertex(0.7, -0.4); fl_vertex(0.7, 1.0); fl_vertex(-0.7, 1.0); fl_end_complex_polygon(); fl_color(fl_lighter(fc)); fl_begin_polygon(); fl_vertex(0.1, -1.0); fl_vertex(0.1, -0.4); fl_vertex(0.7, -0.4); fl_end_polygon(); fl_color(fl_darker(c)); fl_begin_loop(); fl_vertex(-0.7, -1.0); fl_vertex(0.1, -1.0); fl_vertex(0.1, -0.4); fl_vertex(0.7, -0.4); fl_vertex(0.7, 1.0); fl_vertex(-0.7, 1.0); fl_end_loop(); fl_begin_line(); fl_vertex(0.1, -1.0); fl_vertex(0.7, -0.4); fl_end_line(); } /** Draw a 3 1/2" floppy symbol. */ void fd_file(Fl_Color c) { Fl_Color fl = FL_LIGHT2; Fl_Color fc = FL_DARK3; fl_color(fc); fl_begin_polygon(); // case fl_vertex(-0.9, -1.0); fl_vertex(0.9, -1.0); fl_vertex(1.0, -0.9); fl_vertex(1.0, 0.9); fl_vertex(0.9, 1.0); fl_vertex(-0.9, 1.0); fl_vertex(-1.0, 0.9); fl_vertex(-1.0, -0.9); fl_end_polygon(); fl_color(fl_lighter(fl)); fl_begin_polygon(); fl_vertex(-0.7, -1.0); // slider fl_vertex(0.7, -1.0); fl_vertex(0.7, -0.4); fl_vertex(-0.7, -0.4); fl_end_polygon(); fl_begin_polygon(); // label fl_vertex(-0.7, 0.0); fl_vertex(0.7, 0.0); fl_vertex(0.7, 1.0); fl_vertex(-0.7, 1.0); fl_end_polygon(); fl_color(fc); fl_begin_polygon(); fl_vertex(-0.5, -0.9); // slot fl_vertex(-0.3, -0.9); fl_vertex(-0.3, -0.5); fl_vertex(-0.5, -0.5); fl_end_polygon(); fl_color(fl_darker(c)); fl_begin_loop(); fl_vertex(-0.9, -1.0); fl_vertex(0.9, -1.0); fl_vertex(1.0, -0.9); fl_vertex(1.0, 0.9); fl_vertex(0.9, 1.0); fl_vertex(-0.9, 1.0); fl_vertex(-1.0, 0.9); fl_vertex(-1.0, -0.9); fl_end_loop(); } /** Instantiate the class that holds a list of all layouts and manages the UI. */ Fd_Layout_List::Fd_Layout_List() : main_menu_(main_layout_submenu_), choice_menu_(static_choice_menu), list_(static_suite_list), list_size_(2), list_capacity_(2), list_is_static_(true), current_suite_(0), current_preset_(0) { fl_add_symbol("fd_beaker", fd_beaker, 1); fl_add_symbol("fd_user", fd_user, 1); fl_add_symbol("fd_project", fd_project, 1); fl_add_symbol("fd_file", fd_file, 1); } /** Release allocated resources. */ Fd_Layout_List::~Fd_Layout_List() { assert(this); if (!list_is_static_) { ::free(main_menu_); ::free(choice_menu_); for (int i = 0; i < list_size_; i++) { Fd_Layout_Suite &suite = list_[i]; if (suite.storage_ != FD_STORE_INTERNAL) suite.~Fd_Layout_Suite(); } ::free(list_); } } /** Update the Setting dialog and menus to reflect the current Layout selection state. */ void Fd_Layout_List::update_dialogs() { static Fl_Menu_Item *preset_menu = NULL; if (!preset_menu) { preset_menu = (Fl_Menu_Item*)main_menubar->find_item(select_layout_preset_cb); assert(preset_menu); } assert(this); assert(current_suite_ >= 0 ); assert(current_suite_ < list_size_); assert(current_preset_ >= 0 ); assert(current_preset_ < 3); layout = list_[current_suite_].layout[current_preset_]; assert(layout); if (w_settings_layout_tab) { w_settings_layout_tab->do_callback(w_settings_layout_tab, LOAD); layout_choice->redraw(); } preset_menu[current_preset_].setonly(preset_menu); main_menu_[current_suite_].setonly(main_menu_); } /** Refresh the label pointers for both pulldown menus. */ void Fd_Layout_List::update_menu_labels() { for (int i=0; i<list_size_; i++) { main_menu_[i].label(list_[i].menu_label); choice_menu_[i].label(list_[i].menu_label); } } /** Load all user layouts from the FLUID user preferences. */ int Fd_Layout_List::load(const Fl_String &filename) { remove_all(FD_STORE_FILE); Fl_Preferences prefs(filename.c_str(), "layout.fluid.fltk.org", NULL, Fl_Preferences::C_LOCALE); read(prefs, FD_STORE_FILE); return 0; } /** Save all user layouts to the FLUID user preferences. */ int Fd_Layout_List::save(const Fl_String &filename) { assert(this); Fl_Preferences prefs(filename.c_str(), "layout.fluid.fltk.org", NULL, (Fl_Preferences::Root)(Fl_Preferences::C_LOCALE|Fl_Preferences::CLEAR)); prefs.clear(); write(prefs, FD_STORE_FILE); return 0; } /** Write Suite and Layout selection and selected layout data to Preferences database. */ void Fd_Layout_List::write(Fl_Preferences &prefs, Fd_Tool_Store storage) { Fl_Preferences prefs_list(prefs, "Layouts"); prefs_list.clear(); prefs_list.set("current_suite", list_[current_suite()].name_); prefs_list.set("current_preset", current_preset()); int n = 0; for (int i = 0; i < list_size_; ++i) { Fd_Layout_Suite &suite = list_[i]; if (suite.storage_ == storage) { Fl_Preferences prefs_suite(prefs_list, Fl_Preferences::Name(n++)); suite.write(prefs_suite); } } } /** Read Suite and Layout selection and selected layout data to Preferences database. */ void Fd_Layout_List::read(Fl_Preferences &prefs, Fd_Tool_Store storage) { Fl_Preferences prefs_list(prefs, "Layouts"); Fl_String cs; int cp = 0; preferences_get(prefs_list, "current_suite", cs, ""); prefs_list.get("current_preset", cp, 0); for (int i = 0; i < prefs_list.groups(); ++i) { Fl_Preferences prefs_suite(prefs_list, Fl_Preferences::Name(i)); char *new_name = NULL; prefs_suite.get("name", new_name, NULL); if (new_name) { int n = add(new_name); list_[n].read(prefs_suite); list_[n].storage(storage); ::free(new_name); } } current_suite(cs); current_preset(cp); update_dialogs(); } /** Write Suite and Layout selection and project layout data to an .fl project file. */ void Fd_Layout_List::write(Fd_Project_Writer *out) { // Don't write the Snap field if no custom layout was used if ((current_suite()==0) && (current_preset()==0)) { int nSuite = 0; for (int i=0; i<list_size_; i++) { if (list_[i].storage_ == FD_STORE_PROJECT) nSuite++; } if (nSuite == 0) return; } out->write_string("\nsnap {\n ver 1\n"); out->write_string(" current_suite "); out->write_word(list_[current_suite()].name_); out->write_string("\n"); out->write_string(" current_preset %d\n", current_preset()); for (int i=0; i<list_size_; i++) { Fd_Layout_Suite &suite = list_[i]; if (suite.storage_ == FD_STORE_PROJECT) suite.write(out); } out->write_string("}"); } /** Read Suite and Layout selection and project layout data from an .fl project file. */ void Fd_Layout_List::read(Fd_Project_Reader *in) { const char *key; key = in->read_word(1); if (key && !strcmp(key, "{")) { Fl_String cs; int cp = 0; for (;;) { key = in->read_word(); if (!key) return; if (!strcmp(key, "ver")) { in->read_int(); } else if (!strcmp(key, "current_suite")) { cs = in->read_word(); } else if (!strcmp(key, "current_preset")) { cp = in->read_int(); } else if (!strcmp(key, "suite")) { int n = add(in->filename_name()); list_[n].read(in); list_[n].storage(FD_STORE_PROJECT); } else if (!strcmp(key, "}")) { break; } else { in->read_word(); // unknown key, ignore, hopefully a key-value pair } } current_suite(cs); current_preset(cp); update_dialogs(); } else { // old style "snap" is followed by an integer. Ignore. } } /** Set the current Suite. \param[in] ix index into list of suites */ void Fd_Layout_List::current_suite(int ix) { assert(ix >= 0); assert(ix < list_size_); current_suite_ = ix; layout = list_[current_suite_].layout[current_preset_]; } /** Set the current Suite. \param[in] arg_name name of the selected suite \return if no name is given or the name is not found, keep the current suite selected */ void Fd_Layout_List::current_suite(Fl_String arg_name) { if (arg_name.empty()) return; for (int i = 0; i < list_size_; ++i) { Fd_Layout_Suite &suite = list_[i]; if (suite.name_ && (strcmp(suite.name_, arg_name.c_str()) == 0)) { current_suite(i); break; } } } /** Select a Preset within the current Suite. \param[in] ix 0 = application, 1 = dialog, 2 = toolbox */ void Fd_Layout_List::current_preset(int ix) { assert(ix >= 0); assert(ix < 3); current_preset_ = ix; layout = list_[current_suite_].layout[current_preset_]; } /** Allocate enough space for n entries in the list. */ void Fd_Layout_List::capacity(int n) { static Fl_Menu_Item *suite_menu = NULL; if (!suite_menu) suite_menu = (Fl_Menu_Item*)main_menubar->find_item(layout_suite_marker); int old_n = list_size_; int i; Fd_Layout_Suite *new_list = (Fd_Layout_Suite*)::calloc(n, sizeof(Fd_Layout_Suite)); for (i = 0; i < old_n; i++) new_list[i] = list_[i]; if (!list_is_static_) ::free(list_); list_ = new_list; Fl_Menu_Item *new_main_menu = (Fl_Menu_Item*)::calloc(n+1, sizeof(Fl_Menu_Item)); for (i = 0; i < old_n; i++) new_main_menu[i] = main_menu_[i]; if (!list_is_static_) ::free(main_menu_); main_menu_ = new_main_menu; suite_menu->user_data(main_menu_); Fl_Menu_Item *new_choice_menu = (Fl_Menu_Item*)::calloc(n+1, sizeof(Fl_Menu_Item)); for (i = 0; i < old_n; i++) new_choice_menu[i] = choice_menu_[i]; if (!list_is_static_) ::free(choice_menu_); choice_menu_ = new_choice_menu; if (layout_choice) layout_choice->menu(choice_menu_); list_capacity_ = n; list_is_static_ = false; } /** \brief Clone the currently selected suite and append it to the list. Selects the new layout and updates the UI. */ int Fd_Layout_List::add(const char *name) { if (list_size_ == list_capacity_) { capacity(list_capacity_ * 2); } int n = list_size_; Fd_Layout_Suite &old_suite = list_[current_suite_]; Fd_Layout_Suite &new_suite = list_[n]; new_suite.init(); new_suite.name(name); for (int i=0; i<3; ++i) { new_suite.layout[i] = new Fd_Layout_Preset; ::memcpy(new_suite.layout[i], old_suite.layout[i], sizeof(Fd_Layout_Preset)); } Fd_Tool_Store new_storage = old_suite.storage_; if (new_storage == FD_STORE_INTERNAL) new_storage = FD_STORE_USER; new_suite.storage(new_storage); main_menu_[n].label(new_suite.menu_label); main_menu_[n].callback(main_menu_[0].callback()); main_menu_[n].argument(n); main_menu_[n].flags = main_menu_[0].flags; choice_menu_[n].label(new_suite.menu_label); list_size_++; current_suite(n); return n; } /** Rename the current Suite. */ void Fd_Layout_List::rename(const char *name) { int n = current_suite(); list_[n].name(name); main_menu_[n].label(list_[n].menu_label); choice_menu_[n].label(list_[n].menu_label); } /** Remove the given suite. \param[in] ix index into list of suites */ void Fd_Layout_List::remove(int ix) { int tail = list_size_-ix-1; if (tail) { for (int i = ix; i < list_size_-1; i++) list_[i] = list_[i+1]; } ::memmove(main_menu_+ix, main_menu_+ix+1, (tail+1) * sizeof(Fl_Menu_Item)); ::memmove(choice_menu_+ix, choice_menu_+ix+1, (tail+1) * sizeof(Fl_Menu_Item)); list_size_--; if (current_suite() >= list_size_) current_suite(list_size_ - 1); } /** Remove all Suites that use the given storage attribute. \param[in] storage storage attribute, see FD_STORE_INTERNAL, etc. */ void Fd_Layout_List::remove_all(Fd_Tool_Store storage) { for (int i=list_size_-1; i>=0; --i) { if (list_[i].storage_ == storage) remove(i); } } // ---- Helper --------------------------------------------------------- MARK: - static void draw_h_arrow(int, int, int); static void draw_v_arrow(int x, int y1, int y2); static void draw_left_brace(const Fl_Widget *w); static void draw_right_brace(const Fl_Widget *w); static void draw_top_brace(const Fl_Widget *w); static void draw_bottom_brace(const Fl_Widget *w); static void draw_grid(int x, int y, int dx, int dy); void draw_width(int x, int y, int r, Fl_Align a); void draw_height(int x, int y, int b, Fl_Align a); static int nearest(int x, int left, int grid, int right=0x7fff) { int grid_x = ((x-left+grid/2)/grid)*grid+left; if (grid_x < left+grid/2) return left; // left+grid/2; if (grid_x > right-grid/2) return right; // right-grid/2; return grid_x; } static bool in_window(Fd_Snap_Data &d) { return (d.wgt && d.wgt->parent == d.win); } static bool in_group(Fd_Snap_Data &d) { return (d.wgt && d.wgt->parent && d.wgt->parent->is_a(ID_Group) && d.wgt->parent != d.win); } static bool in_tabs(Fd_Snap_Data &d) { return (d.wgt && d.wgt->parent && d.wgt->parent->is_a(ID_Tabs)); } static Fl_Group *parent(Fd_Snap_Data &d) { return (d.wgt->o->parent()); } // ---- Fd_Snap_Action ------------------------------------------------- MARK: - /** \class Fd_Snap_Action When a user drags one or more widgets, snap actions can be defined that provide hints if a preferred widget position or size is nearby. The user's motion is then directed towards the nearest preferred position, and the widget selection snaps into place. FLUID provides a list of various snap actions. Every snap action uses the data from the motion event and combines it with the sizes and positions of all other widgets in the layout. Common snap actions include gaps and margins, but also alignments and simple grid positions. */ /** \brief Check if a snap action has reached a preferred x position. \param[inout] d current event data \param[in] x_ref position of moving point \param[in] x_snap position of target point \return 1 if the points are not within range and won;t be considered \return 0 if the point is as close as another in a previous action \return -1 if this point is closer than any previous check, and this is the new distance to beat. */ int Fd_Snap_Action::check_x_(Fd_Snap_Data &d, int x_ref, int x_snap) { int dd = x_ref + d.dx - x_snap; int d2 = abs(dd); if (d2 > d.x_dist) return 1; dx = d.dx_out = d.dx - dd; ex = d.ex_out = x_snap; if (d2 == d.x_dist) return 0; d.x_dist = d2; return -1; } /** \brief Check if a snap action has reached a preferred y position. \see Fd_Snap_Action::check_x_(Fd_Snap_Data &d, int x_ref, int x_snap) */ int Fd_Snap_Action::check_y_(Fd_Snap_Data &d, int y_ref, int y_snap) { int dd = y_ref + d.dy - y_snap; int d2 = abs(dd); if (d2 > d.y_dist) return 1; dy = d.dy_out = d.dy - dd; ey = d.ey_out = y_snap; if (d2 == d.y_dist) return 0; d.y_dist = d2; return -1; } /** \brief Check if a snap action has reached a preferred x and y position. \see Fd_Snap_Action::check_x_(Fd_Snap_Data &d, int x_ref, int x_snap) */ void Fd_Snap_Action::check_x_y_(Fd_Snap_Data &d, int x_ref, int x_snap, int y_ref, int y_snap) { int ddx = x_ref + d.dx - x_snap; int d2x = abs(ddx); int ddy = y_ref + d.dy - y_snap; int d2y = abs(ddy); if ((d2x <= d.x_dist) && (d2y <= d.y_dist)) { dx = d.dx_out = d.dx - ddx; ex = d.ex_out = x_snap; d.x_dist = d2x; dy = d.dy_out = d.dy - ddy; ey = d.ey_out = y_snap; d.y_dist = d2y; } } /** \brief Check if a snap action was applied to the current event. This method is used to determine if a visual indicator for this snap action should be drawn. \param[inout] d current event data */ bool Fd_Snap_Action::matches(Fd_Snap_Data &d) { switch (type) { case 1: return (d.drag & mask) && (eex == ex) && (d.dx == dx); case 2: return (d.drag & mask) && (eey == ey) && (d.dy == dy); case 3: return (d.drag & mask) && (eex == ex) && (d.dx == dx) && (eey == ey) && (d.dy == dy); } return false; } /** \brief Run through all possible snap actions and store the winning coordinates in eex and eey. \param[inout] d current event data */ void Fd_Snap_Action::check_all(Fd_Snap_Data &data) { for (int i=0; list[i]; i++) { if (list[i]->mask & data.drag) list[i]->check(data); } eex = data.ex_out; eey = data.ey_out; } /** \brief Draw a visual indicator for all snap actions that were applied during the last check. Only one snap coordinate can win. FLUID chooses the one that is closest to the current user event. If two or more snap actions suggest the same coordinate, all of them will be drawn. \param[inout] d current event data */ void Fd_Snap_Action::draw_all(Fd_Snap_Data &data) { for (int i=0; list[i]; i++) { if (list[i]->matches(data)) list[i]->draw(data); } } /** Return a sensible step size for resizing a widget. */ void Fd_Snap_Action::get_resize_stepsize(int &x_step, int &y_step) { if ((layout->widget_inc_w > 1) && (layout->widget_inc_h > 1)) { x_step = layout->widget_inc_w; y_step = layout->widget_inc_h; } else if ((layout->group_grid_x > 1) && (layout->group_grid_y > 1)) { x_step = layout->group_grid_x; y_step = layout->group_grid_y; } else { x_step = layout->window_grid_x; y_step = layout->window_grid_y; } } /** Return a sensible step size for moving a widget. */ void Fd_Snap_Action::get_move_stepsize(int &x_step, int &y_step) { if ((layout->group_grid_x > 1) && (layout->group_grid_y > 1)) { x_step = layout->group_grid_x; y_step = layout->group_grid_y; } else if ((layout->window_grid_x > 1) && (layout->window_grid_y > 1)) { x_step = layout->window_grid_x; y_step = layout->window_grid_y; } else { x_step = layout->widget_gap_x; y_step = layout->widget_gap_y; } } /** Fix the given size to the same or next bigger snap position. */ void Fd_Snap_Action::better_size(int &w, int &h) { int x_min = 1, y_min = 1, x_inc = 1, y_inc = 1; get_resize_stepsize(x_inc, y_inc); if (x_inc < 1) x_inc = 1; if (y_inc < 1) y_inc = 1; if ((layout->widget_min_w > 1) && (layout->widget_min_h > 1)) { x_min = layout->widget_min_w; y_min = layout->widget_min_h; } else if ((layout->group_grid_x > 1) && (layout->group_grid_y > 1)) { x_min = layout->group_grid_x; y_min = layout->group_grid_y; } else { x_min = x_inc; y_min = y_inc; } int ww = fd_max(w - x_min, 0); w = (w - ww + x_inc - 1) / x_inc; w = w * x_inc; w = w + ww; int hh = fd_max(h - y_min, 0); h = (h - hh + y_inc - 1) / y_inc; h = h * y_inc; h = h + hh; } // ---- snapping prototypes -------------------------------------------- MARK: - /** Base class for all actions that drag the left side or the entire widget. */ class Fd_Snap_Left : public Fd_Snap_Action { public: Fd_Snap_Left() { type = 1; mask = FD_LEFT|FD_DRAG; } }; /** Base class for all actions that drag the right side or the entire widget. */ class Fd_Snap_Right : public Fd_Snap_Action { public: Fd_Snap_Right() { type = 1; mask = FD_RIGHT|FD_DRAG; } }; /** Base class for all actions that drag the top side or the entire widget. */ class Fd_Snap_Top : public Fd_Snap_Action { public: Fd_Snap_Top() { type = 2; mask = FD_TOP|FD_DRAG; } }; /** Base class for all actions that drag the bottom side or the entire widget. */ class Fd_Snap_Bottom : public Fd_Snap_Action { public: Fd_Snap_Bottom() { type = 2; mask = FD_BOTTOM|FD_DRAG; } }; // ---- window snapping ------------------------------------------------ MARK: - /** Check if the widget hits the left window edge. */ class Fd_Snap_Left_Window_Edge : public Fd_Snap_Left { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); check_x_(d, d.bx, 0); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_left_brace(d.win->o); }; }; Fd_Snap_Left_Window_Edge snap_left_window_edge; /** Check if the widget hits the right window edge. */ class Fd_Snap_Right_Window_Edge : public Fd_Snap_Right { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); check_x_(d, d.br, d.win->o->w()); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_right_brace(d.win->o); }; }; Fd_Snap_Right_Window_Edge snap_right_window_edge; /** Check if the widget hits the top window edge. */ class Fd_Snap_Top_Window_Edge : public Fd_Snap_Top { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); check_y_(d, d.by, 0); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_top_brace(d.win->o); }; }; Fd_Snap_Top_Window_Edge snap_top_window_edge; /** Check if the widget hits the bottom window edge. */ class Fd_Snap_Bottom_Window_Edge : public Fd_Snap_Bottom { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); check_y_(d, d.bt, d.win->o->h()); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_bottom_brace(d.win->o); }; }; Fd_Snap_Bottom_Window_Edge snap_bottom_window_edge; /** Check if the widget hits the left window edge plus a user defined margin. */ class Fd_Snap_Left_Window_Margin : public Fd_Snap_Left { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_window(d)) check_x_(d, d.bx, layout->left_window_margin); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_h_arrow(d.bx, (d.by+d.bt)/2, 0); }; }; Fd_Snap_Left_Window_Margin snap_left_window_margin; class Fd_Snap_Right_Window_Margin : public Fd_Snap_Right { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_window(d)) check_x_(d, d.br, d.win->o->w()-layout->right_window_margin); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_h_arrow(d.br, (d.by+d.bt)/2, d.win->o->w()-1); }; }; Fd_Snap_Right_Window_Margin snap_right_window_margin; class Fd_Snap_Top_Window_Margin : public Fd_Snap_Top { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_window(d)) check_y_(d, d.by, layout->top_window_margin); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_v_arrow((d.bx+d.br)/2, d.by, 0); }; }; Fd_Snap_Top_Window_Margin snap_top_window_margin; class Fd_Snap_Bottom_Window_Margin : public Fd_Snap_Bottom { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_window(d)) check_y_(d, d.bt, d.win->o->h()-layout->bottom_window_margin); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_v_arrow((d.bx+d.br)/2, d.bt, d.win->o->h()-1); }; }; Fd_Snap_Bottom_Window_Margin snap_bottom_window_margin; // ---- group snapping ------------------------------------------------- MARK: - /** Check if the widget hits the left group edge. */ class Fd_Snap_Left_Group_Edge : public Fd_Snap_Left { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_group(d)) check_x_(d, d.bx, parent(d)->x()); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_left_brace(parent(d)); }; }; Fd_Snap_Left_Group_Edge snap_left_group_edge; class Fd_Snap_Right_Group_Edge : public Fd_Snap_Right { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_group(d)) check_x_(d, d.br, parent(d)->x() + parent(d)->w()); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_right_brace(parent(d)); }; }; Fd_Snap_Right_Group_Edge snap_right_group_edge; class Fd_Snap_Top_Group_Edge : public Fd_Snap_Top { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_group(d)) check_y_(d, d.by, parent(d)->y()); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_top_brace(parent(d)); }; }; Fd_Snap_Top_Group_Edge snap_top_group_edge; class Fd_Snap_Bottom_Group_Edge : public Fd_Snap_Bottom { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_group(d)) check_y_(d, d.bt, parent(d)->y() + parent(d)->h()); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_bottom_brace(parent(d)); }; }; Fd_Snap_Bottom_Group_Edge snap_bottom_group_edge; /** Check if the widget hits the left group edge plus a user defined margin. */ class Fd_Snap_Left_Group_Margin : public Fd_Snap_Left { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_group(d)) check_x_(d, d.bx, parent(d)->x() + layout->left_group_margin); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_left_brace(parent(d)); draw_h_arrow(d.bx, (d.by+d.bt)/2, parent(d)->x()); }; }; Fd_Snap_Left_Group_Margin snap_left_group_margin; class Fd_Snap_Right_Group_Margin : public Fd_Snap_Right { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_group(d)) check_x_(d, d.br, parent(d)->x()+parent(d)->w()-layout->right_group_margin); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_right_brace(parent(d)); draw_h_arrow(d.br, (d.by+d.bt)/2, parent(d)->x()+parent(d)->w()-1); }; }; Fd_Snap_Right_Group_Margin snap_right_group_margin; class Fd_Snap_Top_Group_Margin : public Fd_Snap_Top { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_group(d) && !in_tabs(d)) check_y_(d, d.by, parent(d)->y()+layout->top_group_margin); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_top_brace(parent(d)); draw_v_arrow((d.bx+d.br)/2, d.by, parent(d)->y()); }; }; Fd_Snap_Top_Group_Margin snap_top_group_margin; class Fd_Snap_Bottom_Group_Margin : public Fd_Snap_Bottom { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_group(d) && !in_tabs(d)) check_y_(d, d.bt, parent(d)->y()+parent(d)->h()-layout->bottom_group_margin); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_bottom_brace(parent(d)); draw_v_arrow((d.bx+d.br)/2, d.bt, parent(d)->y()+parent(d)->h()-1); }; }; Fd_Snap_Bottom_Group_Margin snap_bottom_group_margin; // ----- tabs snapping ------------------------------------------------- MARK: - /** Check if the widget top hits the Fl_Tabs group top edge plus a user defined margin. */ class Fd_Snap_Top_Tabs_Margin : public Fd_Snap_Top_Group_Margin { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_tabs(d)) check_y_(d, d.by, parent(d)->y()+layout->top_tabs_margin); } }; Fd_Snap_Top_Tabs_Margin snap_top_tabs_margin; class Fd_Snap_Bottom_Tabs_Margin : public Fd_Snap_Bottom_Group_Margin { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_tabs(d)) check_y_(d, d.bt, parent(d)->y()+parent(d)->h()-layout->bottom_tabs_margin); } }; Fd_Snap_Bottom_Tabs_Margin snap_bottom_tabs_margin; // ----- grid snapping ------------------------------------------------- MARK: - /** Base class for grid based snapping. */ class Fd_Snap_Grid : public Fd_Snap_Action { protected: int nearest_x, nearest_y; public: Fd_Snap_Grid() { type = 3; mask = FD_LEFT|FD_TOP|FD_DRAG; } void check_grid(Fd_Snap_Data &d, int left, int grid_x, int right, int top, int grid_y, int bottom) { if ((grid_x <= 1) || (grid_y <= 1)) return; int suggested_x = d.bx + d.dx; nearest_x = nearest(suggested_x, left, grid_x, right); int suggested_y = d.by + d.dy; nearest_y = nearest(suggested_y, top, grid_y, bottom); if (d.drag == FD_LEFT) check_x_(d, d.bx, nearest_x); else if (d.drag == FD_TOP) check_y_(d, d.by, nearest_y); else check_x_y_(d, d.bx, nearest_x, d.by, nearest_y); } bool matches(Fd_Snap_Data &d) FL_OVERRIDE { if (d.drag == FD_LEFT) return (eex == ex); if (d.drag == FD_TOP) return (eey == ey) && (d.dx == dx); return (d.drag & mask) && (eex == ex) && (d.dx == dx) && (eey == ey) && (d.dy == dy); } }; /** Check if the widget hits window grid coordinates. */ class Fd_Snap_Window_Grid : public Fd_Snap_Grid { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (in_window(d)) check_grid(d, layout->left_window_margin, layout->window_grid_x, d.win->o->w()-layout->right_window_margin, layout->top_window_margin, layout->window_grid_y, d.win->o->h()-layout->bottom_window_margin); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_grid(nearest_x, nearest_y, layout->window_grid_x, layout->window_grid_y); }; }; Fd_Snap_Window_Grid snap_window_grid; /** Check if the widget hits group grid coordinates. */ class Fd_Snap_Group_Grid : public Fd_Snap_Grid { public: void check(Fd_Snap_Data &d) FL_OVERRIDE { if (in_group(d)) { clr(); Fl_Widget *g = parent(d); check_grid(d, g->x()+layout->left_group_margin, layout->group_grid_x, g->x()+g->w()-layout->right_group_margin, g->y()+layout->top_group_margin, layout->group_grid_y, g->y()+g->h()-layout->bottom_group_margin); } } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_grid(nearest_x, nearest_y, layout->group_grid_x, layout->group_grid_y); }; }; Fd_Snap_Group_Grid snap_group_grid; // ----- sibling snapping ---------------------------------------------- MARK: - /** Base class the check distance to other widgets in the same group. */ class Fd_Snap_Sibling : public Fd_Snap_Action { protected: Fl_Widget *best_match; public: Fd_Snap_Sibling() : best_match(NULL) { } virtual int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) = 0; void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); best_match = NULL; if (!d.wgt) return; if (!d.wgt->parent->is_a(ID_Group)) return; int dsib_min = 1024; Fl_Group_Type *gt = (Fl_Group_Type*)d.wgt->parent; Fl_Group *g = (Fl_Group*)gt->o; Fl_Widget *w = d.wgt->o; for (int i=0; i<g->children(); i++) { Fl_Widget *c = g->child(i); if (c == w) continue; int sret = sibling_check(d, c); if (sret < 1) { int dsib; if (type==1) dsib = abs( ((d.by+d.bt)/2+d.dy) - (c->y()+c->h()/2) ); else dsib = abs( ((d.bx+d.br)/2+d.dx) - (c->x()+c->w()/2) ); if (sret == -1 || (dsib < dsib_min)) { dsib_min = dsib; best_match = c; } } } } }; /** Check if widgets have the same x coordinate, so they can be vertically aligned. */ class Fd_Snap_Siblings_Left_Same : public Fd_Snap_Sibling { public: Fd_Snap_Siblings_Left_Same() { type = 1; mask = FD_LEFT|FD_DRAG; } int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE { return check_x_(d, d.bx, s->x()); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { if (best_match) draw_left_brace(best_match); }; }; Fd_Snap_Siblings_Left_Same snap_siblings_left_same; /** Check if widgets touch left to right, or have a user selected gap left to right. */ class Fd_Snap_Siblings_Left : public Fd_Snap_Sibling { public: Fd_Snap_Siblings_Left() { type = 1; mask = FD_LEFT|FD_DRAG; } int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE { return fd_min(check_x_(d, d.bx, s->x()+s->w()), check_x_(d, d.bx, s->x()+s->w()+layout->widget_gap_x) ); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { if (best_match) draw_right_brace(best_match); }; }; Fd_Snap_Siblings_Left snap_siblings_left; class Fd_Snap_Siblings_Right_Same : public Fd_Snap_Sibling { public: Fd_Snap_Siblings_Right_Same() { type = 1; mask = FD_RIGHT|FD_DRAG; } int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE { return check_x_(d, d.br, s->x()+s->w()); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { if (best_match) draw_right_brace(best_match); }; }; Fd_Snap_Siblings_Right_Same snap_siblings_right_same; class Fd_Snap_Siblings_Right : public Fd_Snap_Sibling { public: Fd_Snap_Siblings_Right() { type = 1; mask = FD_RIGHT|FD_DRAG; } int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE { return fd_min(check_x_(d, d.br, s->x()), check_x_(d, d.br, s->x()-layout->widget_gap_x)); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { if (best_match) draw_left_brace(best_match); }; }; Fd_Snap_Siblings_Right snap_siblings_right; class Fd_Snap_Siblings_Top_Same : public Fd_Snap_Sibling { public: Fd_Snap_Siblings_Top_Same() { type = 2; mask = FD_TOP|FD_DRAG; } int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE { return check_y_(d, d.by, s->y()); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { if (best_match) draw_top_brace(best_match); }; }; Fd_Snap_Siblings_Top_Same snap_siblings_top_same; class Fd_Snap_Siblings_Top : public Fd_Snap_Sibling { public: Fd_Snap_Siblings_Top() { type = 2; mask = FD_TOP|FD_DRAG; } int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE { return fd_min(check_y_(d, d.by, s->y()+s->h()), check_y_(d, d.by, s->y()+s->h()+layout->widget_gap_y)); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { if (best_match) draw_bottom_brace(best_match); }; }; Fd_Snap_Siblings_Top snap_siblings_top; class Fd_Snap_Siblings_Bottom_Same : public Fd_Snap_Sibling { public: Fd_Snap_Siblings_Bottom_Same() { type = 2; mask = FD_BOTTOM|FD_DRAG; } int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE { return check_y_(d, d.bt, s->y()+s->h()); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { if (best_match) draw_bottom_brace(best_match); }; }; Fd_Snap_Siblings_Bottom_Same snap_siblings_bottom_same; class Fd_Snap_Siblings_Bottom : public Fd_Snap_Sibling { public: Fd_Snap_Siblings_Bottom() { type = 2; mask = FD_BOTTOM|FD_DRAG; } int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE { return fd_min(check_y_(d, d.bt, s->y()), check_y_(d, d.bt, s->y()-layout->widget_gap_y)); } void draw(Fd_Snap_Data &d) FL_OVERRIDE { if (best_match) draw_top_brace(best_match); }; }; Fd_Snap_Siblings_Bottom snap_siblings_bottom; // ------ widget snapping ---------------------------------------------- MARK: - /** Snap horizontal resizing to min_w or min_w and a multiple of inc_w. */ class Fd_Snap_Widget_Ideal_Width : public Fd_Snap_Action { public: Fd_Snap_Widget_Ideal_Width() { type = 1; mask = FD_LEFT|FD_RIGHT; } void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (!d.wgt) return; int iw = 15, ih = 15; d.wgt->ideal_size(iw, ih); if (d.drag == FD_RIGHT) { check_x_(d, d.br, d.bx+iw); iw = layout->widget_min_w; if (iw > 0) iw = nearest(d.br-d.bx+d.dx, layout->widget_min_w, layout->widget_inc_w); check_x_(d, d.br, d.bx+iw); } else { check_x_(d, d.bx, d.br-iw); iw = layout->widget_min_w; if (iw > 0) iw = nearest(d.br-d.bx-d.dx, layout->widget_min_w, layout->widget_inc_w); check_x_(d, d.bx, d.br-iw); } } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_width(d.bx, d.bt+7, d.br, 0); }; }; Fd_Snap_Widget_Ideal_Width snap_widget_ideal_width; class Fd_Snap_Widget_Ideal_Height : public Fd_Snap_Action { public: Fd_Snap_Widget_Ideal_Height() { type = 2; mask = FD_TOP|FD_BOTTOM; } void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); if (!d.wgt) return; int iw, ih; d.wgt->ideal_size(iw, ih); if (d.drag == FD_BOTTOM) { check_y_(d, d.bt, d.by+ih); ih = layout->widget_min_h; if (ih > 0) ih = nearest(d.bt-d.by+d.dy, layout->widget_min_h, layout->widget_inc_h); check_y_(d, d.bt, d.by+ih); } else { check_y_(d, d.by, d.bt-ih); ih = layout->widget_min_h; if (ih > 0) ih = nearest(d.bt-d.by-d.dy, layout->widget_min_h, layout->widget_inc_h); check_y_(d, d.by, d.bt-ih); } } void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_height(d.br+7, d.by, d.bt, 0); }; }; Fd_Snap_Widget_Ideal_Height snap_widget_ideal_height; // ---- snap actions list ---------------------------------------------- MARK: - /** /brief The list of all snap actions available to FLUID. New snap actions can be appended to the list. If multiple snap actions with different coordinates, but the same snap distance are found, the last action in the list wins. All snap actions with the same distance and same winning coordinates are drawn in the overlay plane. */ Fd_Snap_Action *Fd_Snap_Action::list[] = { &snap_left_window_edge, &snap_right_window_edge, &snap_top_window_edge, &snap_bottom_window_edge, &snap_left_window_margin, &snap_right_window_margin, &snap_top_window_margin, &snap_bottom_window_margin, &snap_window_grid, &snap_group_grid, &snap_left_group_edge, &snap_right_group_edge, &snap_top_group_edge, &snap_bottom_group_edge, &snap_left_group_margin, &snap_right_group_margin, &snap_top_group_margin, &snap_bottom_group_margin, &snap_top_tabs_margin, &snap_bottom_tabs_margin, &snap_siblings_left_same, &snap_siblings_left, &snap_siblings_right_same, &snap_siblings_right, &snap_siblings_top_same, &snap_siblings_top, &snap_siblings_bottom_same, &snap_siblings_bottom, &snap_widget_ideal_width, &snap_widget_ideal_height, NULL }; // ---- draw alignment marks ------------------------------------------- MARK: - static void draw_v_arrow(int x, int y1, int y2) { int dy = (y1>y2) ? -1 : 1 ; fl_yxline(x, y1, y2); fl_xyline(x-4, y2, x+4); fl_line(x-2, y2-dy*5, x, y2-dy); fl_line(x+2, y2-dy*5, x, y2-dy); } static void draw_h_arrow(int x1, int y, int x2) { int dx = (x1>x2) ? -1 : 1 ; fl_xyline(x1, y, x2); fl_yxline(x2, y-4, y+4); fl_line(x2-dx*5, y-2, x2-dx, y); fl_line(x2-dx*5, y+2, x2-dx, y); } static void draw_top_brace(const Fl_Widget *w) { int x = w->as_window() ? 0 : w->x(); int y = w->as_window() ? 0 : w->y(); fl_yxline(x, y-2, y+6); fl_yxline(x+w->w()-1, y-2, y+6); fl_xyline(x-2, y, x+w->w()+1); } static void draw_left_brace(const Fl_Widget *w) { int x = w->as_window() ? 0 : w->x(); int y = w->as_window() ? 0 : w->y(); fl_xyline(x-2, y, x+6); fl_xyline(x-2, y+w->h()-1, x+6); fl_yxline(x, y-2, y+w->h()+1); } static void draw_right_brace(const Fl_Widget *w) { int x = w->as_window() ? w->w() - 1 : w->x() + w->w() - 1; int y = w->as_window() ? 0 : w->y(); fl_xyline(x-6, y, x+2); fl_xyline(x-6, y+w->h()-1, x+2); fl_yxline(x, y-2, y+w->h()+1); } static void draw_bottom_brace(const Fl_Widget *w) { int x = w->as_window() ? 0 : w->x(); int y = w->as_window() ? w->h() - 1 : w->y() + w->h() - 1; fl_yxline(x, y-6, y+2); fl_yxline(x+w->w()-1, y-6, y+2); fl_xyline(x-2, y, x+w->w()+1); } void draw_height(int x, int y, int b, Fl_Align a) { char buf[16]; int h = b - y; sprintf(buf, "%d", h); fl_font(FL_HELVETICA, 9); int lw = (int)fl_width(buf); int lx; b --; if (h < 30) { // Move height to the side... if (a == FL_ALIGN_LEFT) lx = x - lw - 2; else lx = x + 2; fl_yxline(x, y, b); } else { // Put height inside the arrows... if (a == FL_ALIGN_LEFT) lx = x - lw + 2; else lx = x - lw / 2; fl_yxline(x, y, y + (h - 11) / 2); fl_yxline(x, y + (h + 11) / 2, b); } // Draw the height... fl_draw(buf, lx, y + (h + 7) / 2); // Draw the arrowheads... fl_line(x-2, y+5, x, y+1, x+2, y+5); fl_line(x-2, b-5, x, b-1, x+2, b-5); // Draw the end lines... fl_xyline(x - 4, y, x + 4); fl_xyline(x - 4, b, x + 4); } void draw_width(int x, int y, int r, Fl_Align a) { char buf[16]; int w = r-x; sprintf(buf, "%d", w); fl_font(FL_HELVETICA, 9); int lw = (int)fl_width(buf); int ly = y + 4; r--; if (lw > (w - 20)) { // Move width above/below the arrows... if (a == FL_ALIGN_TOP) ly -= 10; else ly += 10; fl_xyline(x, y, r); } else { // Put width inside the arrows... fl_xyline(x, y, x + (w - lw - 2) / 2); fl_xyline(x + (w + lw + 2) / 2, y, r); } // Draw the width... fl_draw(buf, x + (w - lw) / 2, ly-2); // Draw the arrowheads... fl_line(x+5, y-2, x+1, y, x+5, y+2); fl_line(r-5, y-2, r-1, y, r-5, y+2); // Draw the end lines... fl_yxline(x, y - 4, y + 4); fl_yxline(r, y - 4, y + 4); } static void draw_grid(int x, int y, int dx, int dy) { int dx2 = 1, dy2 = 1; const int n = 2; for (int i=-n; i<=n; i++) { for (int j=-n; j<=n; j++) { if (abs(i)+abs(j) < 4) { int xx = x + i*dx , yy = y + j*dy; fl_xyline(xx-dx2, yy, xx+dx2); fl_yxline(xx, yy-dy2, yy+dy2); } } } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/fluid/template_panel.fl������������������������������������������������������������������0000644�0001750�0001750�00000020130�15004135251�017221� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} comment {// // FLUID template support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // } {in_source in_header } decl {\#include "fluid.h"} {private local } decl {\#include <FL/Fl_Shared_Image.H>} {private local } decl {\#include <FL/fl_ask.H>} {private local } decl {\#include <FL/fl_string_functions.h>} {private local } decl {\#include "fluid_filename.h"} {private local } decl {\#include "../src/flstring.h"} {private local } decl {\#include <stdio.h>} {private local } decl {\#include <stdlib.h>} {private local } decl {\#include <errno.h>} {private local } decl {\#include <zlib.h>} {private local } declblock {\#if defined(_WIN32) && !defined(__CYGWIN__)} {after {\#endif // _WIN32 && !__CYGWIN__} } { decl {\#include <io.h>} {private local } decl {\#else} {private local } decl {\#include <unistd.h>} {private local } } Function {make_template_panel()} {open } { Fl_Window template_panel { label {New/Save Template} callback {Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); if (img) img->release(); template_preview->image(0); template_browser->deselect(); template_name->value(""); template_instance->value(""); template_panel->hide();} open xywh {478 284 460 355} type Double resizable modal visible } { Fl_Browser template_browser { label {Available Templates:} callback {if (Fl::event_clicks()) { template_panel->hide(); return; } Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); if (img) img->release(); template_preview->image(0); template_preview->redraw(); int item = template_browser->value(); if (item <= 1) template_instance->deactivate(); else template_instance->activate(); if (item < 1) { template_submit->deactivate(); template_delete->deactivate(); return; } template_submit->activate(); const char *flfile = (const char *)template_browser->data(item); if (!flfile) { template_delete->deactivate(); return; } template_name->value(template_browser->text(item)); template_delete->activate(); char pngfile[1024], *ext; strlcpy(pngfile, flfile, sizeof(pngfile)); if ((ext = strrchr(pngfile, '.')) == NULL) return; strcpy(ext, ".png"); img = Fl_Shared_Image::get(pngfile); if (img) { template_preview->image(img); template_preview->redraw(); }} xywh {10 28 180 250} type Hold labelfont 1 align 5 when 3 } Fl_Box template_preview { xywh {200 28 250 250} box THIN_DOWN_BOX align 80 resizable } Fl_Input template_name { label {Template Name:} callback {if (strlen(template_name->value())) { template_submit->activate(); if (Fl::event_key() == FL_Enter) template_panel->hide(); } else template_submit->deactivate();} xywh {198 288 252 25} labelfont 1 when 3 textfont 4 } Fl_Input template_instance { label {Instance Name:} xywh {198 288 252 25} labelfont 1 textfont 4 hide } Fl_Group {} {open xywh {10 323 440 25} } { Fl_Button template_delete { label {Delete Template} callback template_delete_cb xywh {10 323 143 25} } Fl_Box {} { xywh {153 323 126 25} resizable } Fl_Button {} { label Cancel callback {Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); if (img) img->release(); template_preview->image(0); template_browser->deselect(); template_name->value(""); template_instance->value(""); template_panel->hide();} xywh {289 323 72 25} } Fl_Return_Button template_submit { label Save callback {Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); if (img) img->release(); template_preview->image(0); template_panel->hide();} xywh {371 323 79 25} } } } } Function {template_clear()} {return_type void } { code {int i; void *filename; for (i = 1; i <= template_browser->size(); i ++) { if ((filename = template_browser->data(i)) != NULL) free(filename); } template_browser->deselect(); template_browser->clear();} {} } Function {template_delete_cb(Fl_Button *, void *)} {open return_type void } { code {int item = template_browser->value(); if (item < 1) return; const char *name = template_browser->text(item); const char *flfile = (const char *)template_browser->data(item); if (!flfile) return; if (!fl_choice("Are you sure you want to delete the template \\"%s\\"?", "Cancel", "Delete", 0, name)) return; if (fl_unlink(flfile)) { fl_alert("Unable to delete template \\"%s\\":\\n%s", name, strerror(errno)); return; } char pngfile[1024], *ext; strlcpy(pngfile, flfile, sizeof(pngfile)); if ((ext = strrchr(pngfile, '.')) != NULL) { strcpy(ext, ".png"); fl_unlink(pngfile); } template_browser->remove(item); template_browser->do_callback();} {selected } } data tmpl_FLTK_License_fl {private local filename {templates/FLTK_License.fl} compressed } data tmpl_1of7GUIs_fl {private local filename {templates/1of7GUIs.fl} compressed } Function {template_install(const char *path, const char *name, const uchar *inSrc, int inSrcLen, int inDstLen)} {open return_type void } { code {char filename[FL_PATH_MAX]; strcpy(filename, path); strcat(filename, name); FILE *f = fopen(filename, "wb"); if (!f) return; uLong dstLen = inDstLen; Bytef *dst = (Bytef*)::malloc(inDstLen); if (uncompress(dst, &dstLen, (Bytef*)inSrc, (uLong)inSrcLen) != Z_OK) { /* error */ } if (fwrite(dst, dstLen, 1, f) <= 0) { /* error */ } fclose(f);} {} } Function {template_load()} {open return_type void } { code {int i; char name[1024], filename[1400], path[1024], *ptr; struct dirent **files; int num_files; fluid_prefs.getUserdataPath(path, sizeof(path)); strlcat(path, "templates", sizeof(path)); fl_make_path(path); int sample_templates_generated = 0; fluid_prefs.get("sample_templates_generated", sample_templates_generated, 0); if (sample_templates_generated < 2) { strcpy(filename, path); strcat(filename, "/FLTK_License.fl"); FILE *f = fopen(filename, "wb"); if (f) { fputs( "\# data file for the Fltk User Interface Designer (fluid)\\nversion 1.0400\\nheader_name {.h}\\n" "code_name {.cxx}\\ncomment {//\\n// @INSTANCE@ for the Fast Light Tool Kit (FLT" "K).\\n//\\n// Copyright 1998-2023 by Bill Spitzak and others.\\n//\\n// This library is free sof" "tware. Distribution and use rights are outlined in\\n// the file \\"COPYING\\" which should have " "been included with this file. If this\\n// file is missing or damaged, see the license at:\\n" "//\\n// https://www.fltk.org/COPYING.php\\n//\\n// Please see the following page on how to report " "bugs and issues:\\n//\\n// https://www.fltk.org/bugs.php\\n//\\n} {selected in_source in_head" "er\\n}\\n", f); fclose(f); } template_install(path, "/FLTK_License.fl", tmpl_FLTK_License_fl, sizeof(tmpl_FLTK_License_fl), tmpl_FLTK_License_fl_size); template_install(path, "/1of7GUIs.fl", tmpl_1of7GUIs_fl, sizeof(tmpl_1of7GUIs_fl), tmpl_1of7GUIs_fl_size); sample_templates_generated = 2; fluid_prefs.set("sample_templates_generated", sample_templates_generated); fluid_prefs.flush(); } num_files = fl_filename_list(path, &files); for (i = 0; i < num_files; i ++) { if (fl_filename_match(files[i]->d_name, "*.fl")) { // Format the name as the filename with "_" replaced with " " // and without the trailing ".fl"... strlcpy(name, files[i]->d_name, sizeof(name)); *strstr(name, ".fl") = '\\0'; for (ptr = name; *ptr; ptr ++) { if (*ptr == '_') *ptr = ' '; } // Add the template to the browser... snprintf(filename, sizeof(filename), "%s/%s", path, files[i]->d_name); template_browser->add(name, fl_strdup(filename)); } free(files[i]); } if (num_files > 0) free(files);} {} } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fltk-1.4.3/fluid/fluid.cxx��������������������������������������������������������������������������0000644�0001750�0001750�00000217704�15004135251�015552� 0����������������������������������������������������������������������������������������������������ustar �albrecht������������������������albrecht���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // FLUID main entry for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "fluid.h" #include "Fl_Type.h" #include "Fl_Function_Type.h" #include "Fl_Group_Type.h" #include "Fl_Window_Type.h" #include "widget_browser.h" #include "shell_command.h" #include "factory.h" #include "pixmaps.h" #include "undo.h" #include "file.h" #include "code.h" #include "mergeback.h" #include "settings_panel.h" #include "function_panel.h" #include "codeview_panel.h" #include "template_panel.h" #include "about_panel.h" #include "autodoc.h" #include <FL/Fl.H> #ifdef __APPLE__ #include <FL/platform.H> // for fl_open_callback #endif #include <FL/Fl_Help_Dialog.H> #include <FL/Fl_Menu_Bar.H> #include <FL/Fl_PNG_Image.H> #include <FL/Fl_Native_File_Chooser.H> #include <FL/Fl_Printer.H> #include <FL/fl_string_functions.h> #include <locale.h> // setlocale().. #include "../src/flstring.h" extern "C" { #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) # include <zlib.h> # ifdef HAVE_PNG_H # include <png.h> # else # include <libpng/png.h> # endif // HAVE_PNG_H #endif // HAVE_LIBPNG && HAVE_LIBZ } /// \defgroup globals Fluid Global Variables, Functions and Callbacks /// \{ // // Globals.. // /// FLUID-wide help dialog. static Fl_Help_Dialog *help_dialog = NULL; /// Main app window menu bar. Fl_Menu_Bar *main_menubar = NULL; /// Main app window. Fl_Window *main_window; /// Fluid application preferences, always accessible, will be flushed when app closes. Fl_Preferences fluid_prefs(Fl_Preferences::USER_L, "fltk.org", "fluid"); /// Show guides in the design window when positioning widgets, saved in app preferences. int show_guides = 1; /// Show areas of restricted use in overlay plane. /// Restricted areas are widget that overlap each other, widgets that are outside /// of their parent's bounds (except children of Scroll groups), and areas /// within an Fl_Tile that are not covered by children. int show_restricted = 1; /// Show a ghosted outline for groups that have very little contrast. /// This makes groups with NO_BOX or FLAT_BOX better editable. int show_ghosted_outline = 1; /// Show widget comments in the browser, saved in app preferences. int show_comments = 1; /// Use external editor for editing Fl_Code_Type, saved in app preferences. int G_use_external_editor = 0; /// Debugging help for external Fl_Code_Type editor. int G_debug = 0; /// Run this command to load an Fl_Code_Type into an external editor, save in app preferences. char G_external_editor_command[512]; // File history info... /// Stores the absolute filename of the last 10 design files, saved in app preferences. char absolute_history[10][FL_PATH_MAX]; /// This list of filenames is computed from \c absolute_history and displayed in the main menu. char relative_history[10][FL_PATH_MAX]; /// Menuitem to save a .fl design file, will be deactivated if the design is unchanged. Fl_Menu_Item *save_item = NULL; /// First Menuitem that shows the .fl design file history. Fl_Menu_Item *history_item = NULL; /// Menuitem to show or hide the widget bin, label will change if bin is visible. Fl_Menu_Item *widgetbin_item = NULL; /// Menuitem to show or hide the code view, label will change if view is visible. Fl_Menu_Item *codeview_item = NULL; /// Menuitem to show or hide the editing overlay, label will change if overlay visibility changes. Fl_Menu_Item *overlay_item = NULL; /// Menuitem to show or hide the editing guides, label will change if overlay visibility changes. Fl_Menu_Item *guides_item = NULL; /// Menuitem to show or hide the restricted area overlys, label will change if overlay visibility changes. Fl_Menu_Item *restricted_item = NULL; //////////////////////////////////////////////////////////////// /// Filename of the current .fl project file static const char *filename = NULL; /// Set if the current design has been modified compared to the associated .fl design file. int modflag = 0; /// Set if the code files are older than the current design. int modflag_c = 0; /// Application work directory, stored here when temporarily changing to the source code directory. /// \see goto_source_dir() static Fl_String app_work_dir; /// Used as a counter to set the .fl project dir as the current directory. /// \see enter_project_dir(), leave_project_dir() static char in_project_dir = 0; /// Set, if Fluid was started with the command line argument -u int update_file = 0; // fluid -u /// Set, if Fluid was started with the command line argument -c int compile_file = 0; // fluid -c /// Set, if Fluid was started with the command line argument -cs int compile_strings = 0; // fluid -cs /// Set, if Fluid was started with the command line argument -v int show_version = 0; // fluid -v /// Set, if Fluid runs in batch mode, and no user interface is activated. int batch_mode = 0; // if set (-c, -u) don't open display /// command line arguments that overrides the generate code file extension or name Fl_String g_code_filename_arg; /// command line arguments that overrides the generate header file extension or name Fl_String g_header_filename_arg; /// current directory path at application launch Fl_String g_launch_path; /// if set, generate images for automatic documentation in this directory Fl_String g_autodoc_path; /// path to store temporary files during app run /// \see tmpdir_create_called Fl_String tmpdir_path; /// true if the temporary file path was already created /// \see tmpdir_path bool tmpdir_create_called = false; /// Offset in pixels when adding widgets from an .fl file. int pasteoffset = 0; /// Paste offset incrementing at every paste command. static int ipasteoffset = 0; // ---- project settings /// The current project, possibly a new, empty roject Fluid_Project g_project; /** Initialize a new project. */ Fluid_Project::Fluid_Project() : i18n_type(FD_I18N_NONE), include_H_from_C(1), use_FL_COMMAND(0), utf8_in_src(0), avoid_early_includes(0), header_file_set(0), code_file_set(0), write_mergeback_data(0), header_file_name(".h"), code_file_name(".cxx") { } /** Clear all project resources. Not implemented. */ Fluid_Project::~Fluid_Project() { } /** Reset all project setting to create a new empty project. */ void Fluid_Project::reset() { ::delete_all(); i18n_type = FD_I18N_NONE; i18n_gnu_include = "<libintl.h>"; i18n_gnu_conditional = ""; i18n_gnu_function = "gettext"; i18n_gnu_static_function = "gettext_noop"; i18n_pos_include = "<nl_types.h>"; i18n_pos_conditional = ""; i18n_pos_file = ""; i18n_pos_set = "1"; include_H_from_C = 1; use_FL_COMMAND = 0; utf8_in_src = 0; avoid_early_includes = 0; header_file_set = 0; code_file_set = 0; header_file_name = ".h"; code_file_name = ".cxx"; write_mergeback_data = 0; } /** Tell the project and i18n tab of the settings dialog to refresh themselves. */ void Fluid_Project::update_settings_dialog() { if (settings_window) { w_settings_project_tab->do_callback(w_settings_project_tab, LOAD); w_settings_i18n_tab->do_callback(w_settings_i18n_tab, LOAD); } } /** Make sure that a path name ends with a forward slash. \param[in] str directory or path name \return a new string, ending with a '/' */ static Fl_String end_with_slash(const Fl_String &str) { char last = str[str.size()-1]; if (last !='/' && last != '\\') return str + "/"; else return str; } /** Generate a path to a directory for temporary data storage. The path is stored in g_tmpdir. */ static void create_tmpdir() { if (tmpdir_create_called) return; tmpdir_create_called = true; char buf[128]; #if _WIN32 // The usual temp file locations on Windows are // %system%\Windows\Temp // %userprofiles%\AppData\Local // usually resolving into // C:/Windows/Temp/ // C:\Users\<username>\AppData\Local\Temp fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", (long)GetCurrentProcessId()); Fl_String name = buf; wchar_t tempdirW[FL_PATH_MAX+1]; char tempdir[FL_PATH_MAX+1]; unsigned len = GetTempPathW(FL_PATH_MAX, tempdirW); if (len == 0) { strcpy(tempdir, "c:/windows/temp/"); } else { unsigned wn = fl_utf8fromwc(tempdir, FL_PATH_MAX, tempdirW, len); tempdir[wn] = 0; } Fl_String path = tempdir; end_with_slash(path); path += name; fl_make_path(path.c_str()); if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; #else fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", getpid()); Fl_String name = buf; Fl_String path = fl_getenv("TMPDIR"); if (!path.empty()) { end_with_slash(path); path += name; fl_make_path(path.c_str()); if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; } if (tmpdir_path.empty()) { path = Fl_String("/tmp/") + name; fl_make_path(path.c_str()); if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; } #endif if (tmpdir_path.empty()) { char pbuf[FL_PATH_MAX+1]; fluid_prefs.get_userdata_path(pbuf, FL_PATH_MAX); path = Fl_String(pbuf); end_with_slash(path); path += name; fl_make_path(path.c_str()); if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; } if (tmpdir_path.empty()) { if (batch_mode) { fprintf(stderr, "ERROR: Can't create directory for temporary data storage.\n"); } else { fl_alert("Can't create directory for temporary data storage."); } } } /** Delete the temporary directory that was created in set_tmpdir. */ static void delete_tmpdir() { // was a temporary directory created if (!tmpdir_create_called) return; if (tmpdir_path.empty()) return; // first delete all files that may still be left in the temp directory struct dirent **de; int n_de = fl_filename_list(tmpdir_path.c_str(), &de); if (n_de >= 0) { for (int i=0; i<n_de; i++) { Fl_String path = tmpdir_path + de[i]->d_name; fl_unlink(path.c_str()); } fl_filename_free_list(&de, n_de); } // then delete the directory itself if (fl_rmdir(tmpdir_path.c_str()) < 0) { if (batch_mode) { fprintf(stderr, "WARNING: Can't delete tmpdir '%s': %s", tmpdir_path.c_str(), strerror(errno)); } else { fl_alert("WARNING: Can't delete tmpdir '%s': %s", tmpdir_path.c_str(), strerror(errno)); } } } /** Return the path to a temporary directory for this instance of FLUID. Fluid will do its best to clear and delete this directory when exiting. \return the path to the temporary directory, ending in a '/', or and empty string if no directory could be created. */ const Fl_String &get_tmpdir() { if (!tmpdir_create_called) create_tmpdir(); return tmpdir_path; } /** Give the user the opportunity to save a project before clearing it. If the project has unsaved changes, this function pops up a dialog, that allows the user to save the project, continue without saving the project, or to cancel the operation. If the user chooses to save, and no filename was set, a file dialog allows the user to pick a name and location, or to cancel the operation. \return false if the user aborted the operation and the calling function should abort as well */ bool confirm_project_clear() { if (modflag == 0) return true; switch (fl_choice("This project has unsaved changes. Do you want to save\n" "the project file before proceeding?", "Cancel", "Save", "Don't Save")) { case 0 : /* Cancel */ return false; case 1 : /* Save */ save_cb(NULL, NULL); if (modflag) return false; // user canceled the "Save As" dialog } return true; } // ---- extern Fl_Window *the_panel; /** Ensure that text widgets in the widget panel propagates apply current changes. By temporarily clearing the text focus, all text widgets with changed text will unfocus and call their respective callbacks, propagating those changes to their data set. */ void flush_text_widgets() { if (Fl::focus() && (Fl::focus()->top_window() == the_panel)) { Fl_Widget *old_focus = Fl::focus(); Fl::focus(NULL); // trigger callback of the widget that is losing focus Fl::focus(old_focus); } } // ---- /** Change the current working directory to the .fl project directory. Every call to enter_project_dir() must have a corresponding leave_project_dir() call. Enter and leave calls can be nested. The first call to enter_project_dir() remembers the original directory, usually the launch directory of the application. Nested calls will increment a nesting counter. When the nesting counter is back to 0, leave_project_dir() will return to the original directory. The global variable 'filename' must be set to the current project file with absolute or relative path information. \see leave_project_dir(), pwd, in_project_dir */ void enter_project_dir() { if (in_project_dir<0) { fprintf(stderr, "** Fluid internal error: enter_project_dir() calls unmatched\n"); return; } in_project_dir++; // check if we are already in the project dir and do nothing if so if (in_project_dir>1) return; // check if there is an active project, and do nothing if there is none if (!filename || !*filename) { fprintf(stderr, "** Fluid internal error: enter_project_dir() no filename set\n"); return; } // store the current working directory for later app_work_dir = fl_getcwd(); // set the current directory to the path of our .fl file Fl_String project_path = fl_filename_path(fl_filename_absolute(filename)); if (fl_chdir(project_path.c_str()) == -1) { fprintf(stderr, "** Fluid internal error: enter_project_dir() can't chdir to %s: %s\n", project_path.c_str(), strerror(errno)); return; } //fprintf(stderr, "chdir from %s to %s\n", app_work_dir.c_str(), fl_getcwd().c_str()); } /** Change the current working directory to the previous directory. \see enter_project_dir(), pwd, in_project_dir */ void leave_project_dir() { if (in_project_dir == 0) { fprintf(stderr, "** Fluid internal error: leave_project_dir() calls unmatched\n"); return; } in_project_dir--; // still nested, stay in the project directory if (in_project_dir > 0) return; // no longer nested, return to the original, usually the application working directory if (fl_chdir(app_work_dir.c_str()) < 0) { fprintf(stderr, "** Fluid internal error: leave_project_dir() can't chdir back to %s : %s\n", app_work_dir.c_str(), strerror(errno)); } } /** Position the given window window based on entries in the app preferences. Customisable by user; feature can be switched off. The window is not shown or hidden by this function, but a value is returned to indicate the state to the caller. \param[in] w position this window \param[in] prefsName name of the preferences item that stores the window settings \param[in] Visible default value if window is hidden or shown \param[in] X, Y, W, H default size and position if nothing is specified in the preferences \return 1 if the caller should make the window visible, 0 if hidden. */ char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W, int H) { Fl_Preferences pos(fluid_prefs, prefsName); if (prevpos_button->value()) { pos.get("x", X, X); pos.get("y", Y, Y); if ( W!=0 ) { pos.get("w", W, W); pos.get("h", H, H); w->resize( X, Y, W, H ); } else w->position( X, Y ); } pos.get("visible", Visible, Visible); return Visible; } /** Save the position and visibility state of a window to the app preferences. \param[in] w save this window data \param[in] prefsName name of the preferences item that stores the window settings */ void save_position(Fl_Window *w, const char *prefsName) { Fl_Preferences pos(fluid_prefs, prefsName); pos.set("x", w->x()); pos.set("y", w->y()); pos.set("w", w->w()); pos.set("h", w->h()); pos.set("visible", (int)(w->shown() && w->visible())); } /** Return the path and filename of a temporary file for cut or duplicated data. \param[in] which 0 gets the cut/copy/paste buffer, 1 gets the duplication buffer \return a pointer to a string in a static buffer */ static char* cutfname(int which = 0) { static char name[2][FL_PATH_MAX]; static char beenhere = 0; if (!beenhere) { beenhere = 1; fluid_prefs.getUserdataPath(name[0], sizeof(name[0])); strlcat(name[0], "cut_buffer", sizeof(name[0])); fluid_prefs.getUserdataPath(name[1], sizeof(name[1])); strlcat(name[1], "dup_buffer", sizeof(name[1])); } return name[which]; } /** Timer to watch for external editor modifications. If one or more external editors open, check if their files were modified. If so: reload to ram, update size/mtime records, and change fluid's 'modified' state. */ static void external_editor_timer(void*) { int editors_open = ExternalCodeEditor::editors_open(); if ( G_debug ) printf("--- TIMER --- External editors open=%d\n", editors_open); if ( editors_open > 0 ) { // Walk tree looking for files modified by external editors. int modified = 0; for (Fl_Type *p = Fl_Type::first; p; p = p->next) { if ( p->is_a(ID_Code) ) { Fl_Code_Type *code = (Fl_Code_Type*)p; // Code changed by external editor? if ( code->handle_editor_changes() ) { // updates ram, file size/mtime modified++; } if ( code->is_editing() ) { // editor open? code->reap_editor(); // Try to reap; maybe it recently closed } } } if ( modified ) set_modflag(1); } // Repeat timeout if editors still open // The ExternalCodeEditor class handles start/stopping timer, we just // repeat_timeout() if it's already on. NOTE: above code may have reaped // only open editor, which would disable further timeouts. So *recheck* // if editors still open, to ensure we don't accidentally re-enable them. // if ( ExternalCodeEditor::editors_open() ) { Fl::repeat_timeout(2.0, external_editor_timer); } } /** Save the current design to the file given by \c filename. If automatic, this overwrites an existing file. If interactive, if will verify with the user. \param[in] v if v is not NULL, or no filename is set, open a filechooser. */ void save_cb(Fl_Widget *, void *v) { flush_text_widgets(); Fl_Native_File_Chooser fnfc; const char *c = filename; if (v || !c || !*c) { fnfc.title("Save To:"); fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); fnfc.filter("FLUID Files\t*.f[ld]"); if (fnfc.show() != 0) return; c = fnfc.filename(); if (!fl_access(c, 0)) { Fl_String basename = fl_filename_name(Fl_String(c)); if (fl_choice("The file \"%s\" already exists.\n" "Do you want to replace it?", "Cancel", "Replace", NULL, basename.c_str()) == 0) return; } if (v != (void *)2) set_filename(c); } if (!write_file(c)) { fl_alert("Error writing %s: %s", c, strerror(errno)); return; } if (v != (void *)2) { set_modflag(0, 1); undo_save = undo_current; } } /** Save a design template. \todo We should document the concept of templates. */ void save_template_cb(Fl_Widget *, void *) { // Setup the template panel... if (!template_panel) make_template_panel(); template_clear(); template_browser->add("New Template"); template_load(); template_name->show(); template_name->value(""); template_instance->hide(); template_delete->show(); template_delete->deactivate(); template_submit->label("Save"); template_submit->deactivate(); template_panel->label("Save Template"); // Show the panel and wait for the user to do something... template_panel->show(); while (template_panel->shown()) Fl::wait(); // Get the template name, return if it is empty... const char *c = template_name->value(); if (!c || !*c) return; // Convert template name to filename_with_underscores char savename[FL_PATH_MAX], *saveptr; strlcpy(savename, c, sizeof(savename)); for (saveptr = savename; *saveptr; saveptr ++) { if (isspace(*saveptr)) *saveptr = '_'; } // Find the templates directory... char filename[FL_PATH_MAX]; fluid_prefs.getUserdataPath(filename, sizeof(filename)); strlcat(filename, "templates", sizeof(filename)); if (fl_access(filename, 0)) fl_make_path(filename); strlcat(filename, "/", sizeof(filename)); strlcat(filename, savename, sizeof(filename)); char *ext = filename + strlen(filename); if (ext >= (filename + sizeof(filename) - 5)) { fl_alert("The template name \"%s\" is too long!", c); return; } // Save the .fl file... strcpy(ext, ".fl"); if (!fl_access(filename, 0)) { if (fl_choice("The template \"%s\" already exists.\n" "Do you want to replace it?", "Cancel", "Replace", NULL, c) == 0) return; } if (!write_file(filename)) { fl_alert("Error writing %s: %s", filename, strerror(errno)); return; } #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) // Get the screenshot, if any... Fl_Type *t; for (t = Fl_Type::first; t; t = t->next) { // Find the first window... if (t->is_a(ID_Window)) break; } if (!t) return; // Grab a screenshot... Fl_Window_Type *wt = (Fl_Window_Type *)t; uchar *pixels; int w, h; if ((pixels = wt->read_image(w, h)) == NULL) return; // Save to a PNG file... strcpy(ext, ".png"); errno = 0; if (fl_write_png(filename, pixels, w, h, 3) != 0) { delete[] pixels; fl_alert("Error writing %s: %s", filename, strerror(errno)); return; } # if 0 // The original PPM output code... strcpy(ext, ".ppm"); fp = fl_fopen(filename, "wb"); fprintf(fp, "P6\n%d %d 255\n", w, h); fwrite(pixels, w * h, 3, fp); fclose(fp); # endif // 0 delete[] pixels; #endif // HAVE_LIBPNG && HAVE_LIBZ } /** Reload the file set by \c filename, replacing the current design. If the design was modified, a dialog will ask for confirmation. */ void revert_cb(Fl_Widget *,void *) { if (modflag) { if (!fl_choice("This user interface has been changed. Really revert?", "Cancel", "Revert", NULL)) return; } undo_suspend(); if (!read_file(filename, 0)) { undo_resume(); widget_browser->rebuild(); g_project.update_settings_dialog(); fl_message("Can't read %s: %s", filename, strerror(errno)); return; } widget_browser->rebuild(); undo_resume(); set_modflag(0, 0); undo_clear(); g_project.update_settings_dialog(); } /** Exit Fluid; we hope you had a nice experience. If the design was modified, a dialog will ask for confirmation. */ void exit_cb(Fl_Widget *,void *) { if (shell_command_running()) { int choice = fl_choice("Previous shell command still running!", "Cancel", "Exit", NULL); if (choice == 0) { // user chose to cancel the exit operation return; } } flush_text_widgets(); // verify user intention if (confirm_project_clear() == false) return; // Stop any external editor update timers ExternalCodeEditor::stop_update_timer(); save_position(main_window,"main_window_pos"); if (widgetbin_panel) { save_position(widgetbin_panel,"widgetbin_pos"); delete widgetbin_panel; } if (codeview_panel) { Fl_Preferences svp(fluid_prefs, "codeview"); svp.set("autorefresh", cv_autorefresh->value()); svp.set("autoposition", cv_autoposition->value()); svp.set("tab", cv_tab->find(cv_tab->value())); svp.set("code_choice", cv_code_choice); save_position(codeview_panel,"codeview_pos"); delete codeview_panel; codeview_panel = 0; } if (shell_run_window) { save_position(shell_run_window,"shell_run_Window_pos"); } if (about_panel) delete about_panel; if (help_dialog) delete help_dialog; if (g_shell_config) g_shell_config->write(fluid_prefs, FD_STORE_USER); g_layout_list.write(fluid_prefs, FD_STORE_USER); undo_clear(); // Destroy tree // Doing so causes dtors to automatically close all external editors // and cleans up editor tmp files. Then remove fluid tmpdir /last/. g_project.reset(); ExternalCodeEditor::tmpdir_clear(); delete_tmpdir(); exit(0); } /** Clear the current project and create a new, empty one. If the current project was modified, FLUID will give the user the opportunity to save the old project first. \param[in] user_must_confirm if set, a confimation dialog is presented to the user before resetting the project. Default is `true`. \return false if the operation was canceled */ bool new_project(bool user_must_confirm) { // verify user intention if ((user_must_confirm) && (confirm_project_clear() == false)) return false; // clear the current project g_project.reset(); set_filename(NULL); set_modflag(0, 0); widget_browser->rebuild(); g_project.update_settings_dialog(); // all is clear to continue return true; } /** Open the template browser and load a new file from templates. If the current project was modified, FLUID will give the user the opportunity to save the old project first. \return false if the operation was canceled or failed otherwise */ bool new_project_from_template() { // clear the current project first if (new_project() == false) return false; // Setup the template panel... if (!template_panel) make_template_panel(); template_clear(); template_browser->add("Blank"); template_load(); template_name->hide(); template_name->value(""); template_instance->show(); template_instance->deactivate(); template_instance->value(""); template_delete->show(); template_submit->label("New"); template_submit->deactivate(); template_panel->label("New"); //if ( template_browser->size() == 1 ) { // only one item? template_browser->value(1); // select it template_browser->do_callback(); //} // Show the panel and wait for the user to do something... template_panel->show(); while (template_panel->shown()) Fl::wait(); // See if the user chose anything... int item = template_browser->value(); if (item < 1) return false; // Load the template, if any... const char *tname = (const char *)template_browser->data(item); if (tname) { // Grab the instance name... const char *iname = template_instance->value(); if (iname && *iname) { // Copy the template to a temp file, then read it in... char line[1024], *ptr, *next; FILE *infile, *outfile; if ((infile = fl_fopen(tname, "rb")) == NULL) { fl_alert("Error reading template file \"%s\":\n%s", tname, strerror(errno)); set_modflag(0); undo_clear(); return false; } if ((outfile = fl_fopen(cutfname(1), "wb")) == NULL) { fl_alert("Error writing buffer file \"%s\":\n%s", cutfname(1), strerror(errno)); fclose(infile); set_modflag(0); undo_clear(); return false; } while (fgets(line, sizeof(line), infile)) { // Replace @INSTANCE@ with the instance name... for (ptr = line; (next = strstr(ptr, "@INSTANCE@")) != NULL; ptr = next + 10) { fwrite(ptr, next - ptr, 1, outfile); fputs(iname, outfile); } fputs(ptr, outfile); } fclose(infile); fclose(outfile); undo_suspend(); read_file(cutfname(1), 0); fl_unlink(cutfname(1)); undo_resume(); } else { // No instance name, so read the template without replacements... undo_suspend(); read_file(tname, 0); undo_resume(); } } widget_browser->rebuild(); g_project.update_settings_dialog(); set_modflag(0); undo_clear(); return true; } /** Open a native file chooser to allow choosing a project file for reading. Path and filename are preset with the current project filename, if there is one. \param title a text describing the action after selecting a file (load, merge, ...) \return the file path and name, or an empty string if the operation was canceled */ Fl_String open_project_filechooser(const Fl_String &title) { Fl_Native_File_Chooser dialog; dialog.title(title.c_str()); dialog.type(Fl_Native_File_Chooser::BROWSE_FILE); dialog.filter("FLUID Files\t*.f[ld]\n"); if (filename) { Fl_String current_project_file = filename; dialog.directory(fl_filename_path(current_project_file).c_str()); dialog.preset_file(fl_filename_name(current_project_file).c_str()); } if (dialog.show() != 0) return Fl_String(); return Fl_String(dialog.filename()); } /** Load a project from the give file name and path. The project file is inserted at the currently selected type. If no filename is given, FLUID will open a file chooser dialog. \param[in] filename_arg path and name of the new project file \return false if the operation failed */ bool merge_project_file(const Fl_String &filename_arg) { bool is_a_merge = (Fl_Type::first != NULL); Fl_String title = is_a_merge ? "Merge Project File" : "Open Project File"; // ask for a filename if none was given Fl_String new_filename = filename_arg; if (new_filename.empty()) { new_filename = open_project_filechooser(title); if (new_filename.empty()) { return false; } } const char *c = new_filename.c_str(); const char *oldfilename = filename; filename = NULL; set_filename(c); if (is_a_merge) undo_checkpoint(); undo_suspend(); if (!read_file(c, is_a_merge)) { undo_resume(); widget_browser->rebuild(); g_project.update_settings_dialog(); fl_message("Can't read %s: %s", c, strerror(errno)); free((void *)filename); filename = oldfilename; if (main_window) set_modflag(modflag); return false; } undo_resume(); widget_browser->rebuild(); if (is_a_merge) { // Inserting a file; restore the original filename... set_filename(oldfilename); set_modflag(1); } else { // Loaded a file; free the old filename... set_modflag(0, 0); undo_clear(); } if (oldfilename) free((void *)oldfilename); return true; } /** Open a file chooser and load an exiting project file. If the current project was modified, FLUID will give the user the opportunity to save the old project first. If no filename is given, FLUID will open a file chooser dialog. \param[in] filename_arg load from this file, or show file chooser if empty \return false if the operation was canceled or failed otherwise */ bool open_project_file(const Fl_String &filename_arg) { // verify user intention if (confirm_project_clear() == false) return false; // ask for a filename if none was given Fl_String new_filename = filename_arg; if (new_filename.empty()) { new_filename = open_project_filechooser("Open Project File"); if (new_filename.empty()) { return false; } } // clear the project and merge a file by the given name new_project(false); return merge_project_file(new_filename); } #ifdef __APPLE__ /** Handle app launch with an associated filename (macOS only). Should there be a modified design already, Fluid asks for user confirmation. \param[in] c the filename of the new design */ void apple_open_cb(const char *c) { open_project_file(Fl_String(c)); } #endif // __APPLE__ /** Get the absolute path of the project file, for example `/Users/matt/dev/`. \return the path ending in '/' */ Fl_String Fluid_Project::projectfile_path() const { return end_with_slash(fl_filename_absolute(fl_filename_path(filename), g_launch_path)); } /** Get the project file name including extension, for example `test.fl`. \return the file name without path */ Fl_String Fluid_Project::projectfile_name() const { return fl_filename_name(filename); } /** Get the absolute path of the generated C++ code file, for example `/Users/matt/dev/src/`. \return the path ending in '/' */ Fl_String Fluid_Project::codefile_path() const { Fl_String path = fl_filename_path(code_file_name); if (batch_mode) return end_with_slash(fl_filename_absolute(path, g_launch_path)); else return end_with_slash(fl_filename_absolute(path, projectfile_path())); } /** Get the generated C++ code file name including extension, for example `test.cxx`. \return the file name without path */ Fl_String Fluid_Project::codefile_name() const { Fl_String name = fl_filename_name(code_file_name); if (name.empty()) { return fl_filename_setext(fl_filename_name(filename), ".cxx"); } else if (name[0] == '.') { return fl_filename_setext(fl_filename_name(filename), code_file_name); } else { return name; } } /** Get the absolute path of the generated C++ header file, for example `/Users/matt/dev/src/`. \return the path ending in '/' */ Fl_String Fluid_Project::headerfile_path() const { Fl_String path = fl_filename_path(header_file_name); if (batch_mode) return end_with_slash(fl_filename_absolute(path, g_launch_path)); else return end_with_slash(fl_filename_absolute(path, projectfile_path())); } /** Get the generated C++ header file name including extension, for example `test.cxx`. \return the file name without path */ Fl_String Fluid_Project::headerfile_name() const { Fl_String name = fl_filename_name(header_file_name); if (name.empty()) { return fl_filename_setext(fl_filename_name(filename), ".h"); } else if (name[0] == '.') { return fl_filename_setext(fl_filename_name(filename), header_file_name); } else { return name; } } /** Get the absolute path of the generated i18n strings file, for example `/Users/matt/dev/`. Although it may be more useful to put the text file into the same directory with the source and header file, historically, the text is always saved with the project file in interactive mode, and in the FLUID launch directory in batch mode. \return the path ending in '/' */ Fl_String Fluid_Project::stringsfile_path() const { if (batch_mode) return g_launch_path; else return projectfile_path(); } /** Get the generated i18n text file name including extension, for example `test.po`. \return the file name without path */ Fl_String Fluid_Project::stringsfile_name() const { switch (i18n_type) { default: return fl_filename_setext(fl_filename_name(filename), ".txt"); case FD_I18N_GNU: return fl_filename_setext(fl_filename_name(filename), ".po"); case FD_I18N_POSIX: return fl_filename_setext(fl_filename_name(filename), ".msg"); } } /** Get the name of the project file without the filename extension. \return the file name without path or extension */ Fl_String Fluid_Project::basename() const { return fl_filename_setext(fl_filename_name(filename), ""); } /** Generate the C++ source and header filenames and write those files. This function creates the source filename by setting the file extension to \c code_file_name and a header filename with the extension \c code_file_name which are both settable by the user. If the code filename has not been set yet, a "save file as" dialog will be presented to the user. In batch_mode, the function will either be silent, or, if opening or writing the files fails, write an error message to \c stderr and exit with exit code 1. In interactive mode, it will pop up an error message, or, if the user hasn't disabled that, pop up a confirmation message. \param[in] dont_show_completion_dialog don't show the completion dialog \return 1 if the operation failed, 0 if it succeeded */ int write_code_files(bool dont_show_completion_dialog) { // -- handle user interface issues flush_text_widgets(); if (!filename) { save_cb(0,0); if (!filename) return 1; } // -- generate the file names with absolute paths Fd_Code_Writer f; Fl_String code_filename = g_project.codefile_path() + g_project.codefile_name(); Fl_String header_filename = g_project.headerfile_path() + g_project.headerfile_name(); // -- write the code and header files if (!batch_mode) enter_project_dir(); int x = f.write_code(code_filename.c_str(), header_filename.c_str()); Fl_String code_filename_rel = fl_filename_relative(code_filename); Fl_String header_filename_rel = fl_filename_relative(header_filename); if (!batch_mode) leave_project_dir(); // -- print error message in batch mode or pop up an error or confirmation dialog box if (batch_mode) { if (!x) { fprintf(stderr, "%s and %s: %s\n", code_filename_rel.c_str(), header_filename_rel.c_str(), strerror(errno)); exit(1); } } else { if (!x) { fl_message("Can't write %s or %s: %s", code_filename_rel.c_str(), header_filename_rel.c_str(), strerror(errno)); } else { set_modflag(-1, 0); if (dont_show_completion_dialog==false && completion_button->value()) { fl_message("Wrote %s and %s", code_filename_rel.c_str(), header_filename_rel.c_str()); } } } return 0; } /** Callback to write C++ code and header files. */ void write_cb(Fl_Widget *, void *) { write_code_files(); } #if 0 // Matt: disabled /** Merge the possibly modified content of code files back into the project. */ int mergeback_code_files() { flush_text_widgets(); if (!filename) return 1; if (!g_project.write_mergeback_data) { fl_message("MergeBack is not enabled for this project.\n" "Please enable MergeBack in the project settings\n" "dialog and re-save the project file and the code."); return 0; } Fl_String proj_filename = g_project.projectfile_path() + g_project.projectfile_name(); Fl_String code_filename; #if 1 if (!batch_mode) { Fl_Preferences build_records(Fl_Preferences::USER_L, "fltk.org", "fluid-build"); Fl_Preferences path(build_records, proj_filename.c_str()); int i, n = proj_filename.size(); for (i=0; i<n; i++) if (proj_filename[i]=='\\') proj_filename[i] = '/'; preferences_get(path, "code", code_filename, ""); } #endif if (code_filename.empty()) code_filename = g_project.codefile_path() + g_project.codefile_name(); if (!batch_mode) enter_project_dir(); int c = merge_back(code_filename, proj_filename, FD_MERGEBACK_INTERACTIVE); if (!batch_mode) leave_project_dir(); if (c==0) fl_message("Comparing\n \"%s\"\nto\n \"%s\"\n\n" "MergeBack found no external modifications\n" "in the source code.", code_filename.c_str(), proj_filename.c_str()); if (c==-2) fl_message("No corresponding source code file found."); return c; } void mergeback_cb(Fl_Widget *, void *) { mergeback_code_files(); } #endif /** Write the strings that are used in i18n. */ void write_strings_cb(Fl_Widget *, void *) { flush_text_widgets(); if (!filename) { save_cb(0,0); if (!filename) return; } Fl_String filename = g_project.stringsfile_path() + g_project.stringsfile_name(); int x = write_strings(filename); if (batch_mode) { if (x) { fprintf(stderr, "%s : %s\n", filename.c_str(), strerror(errno)); exit(1); } } else { if (x) { fl_message("Can't write %s: %s", filename.c_str(), strerror(errno)); } else if (completion_button->value()) { fl_message("Wrote %s", g_project.stringsfile_name().c_str()); } } } /** Show the editor for the \c current Fl_Type. */ void openwidget_cb(Fl_Widget *, void *) { if (!Fl_Type::current) { fl_message("Please select a widget"); return; } Fl_Type::current->open(); } /** User chose to copy the currently selected widgets. */ void copy_cb(Fl_Widget*, void*) { flush_text_widgets(); if (!Fl_Type::current) { fl_beep(); return; } flush_text_widgets(); ipasteoffset = 10; if (!write_file(cutfname(),1)) { fl_message("Can't write %s: %s", cutfname(), strerror(errno)); return; } } /** User chose to cut the currently selected widgets. */ void cut_cb(Fl_Widget *, void *) { if (!Fl_Type::current) { fl_beep(); return; } flush_text_widgets(); if (!write_file(cutfname(),1)) { fl_message("Can't write %s: %s", cutfname(), strerror(errno)); return; } undo_checkpoint(); set_modflag(1); ipasteoffset = 0; Fl_Type *p = Fl_Type::current->parent; while (p && p->selected) p = p->parent; delete_all(1); if (p) select_only(p); widget_browser->rebuild(); } /** User chose to delete the currently selected widgets. */ void delete_cb(Fl_Widget *, void *) { if (!Fl_Type::current) { fl_beep(); return; } undo_checkpoint(); set_modflag(1); ipasteoffset = 0; Fl_Type *p = Fl_Type::current->parent; while (p && p->selected) p = p->parent; delete_all(1); if (p) select_only(p); widget_browser->rebuild(); } /** User chose to paste the widgets from the cut buffer. This function will paste the widgets in the cut buffer after the currently selected widget. If the currently selected widget is a group widget and it is not folded, the new widgets will be added inside the group. */ void paste_cb(Fl_Widget*, void*) { pasteoffset = ipasteoffset; undo_checkpoint(); undo_suspend(); Strategy strategy = Strategy::FROM_FILE_AFTER_CURRENT; if (Fl_Type::current && Fl_Type::current->can_have_children()) { if (Fl_Type::current->folded_ == 0) { // If the current widget is a group widget and it is not folded, // add the new widgets inside the group. strategy = Strategy::FROM_FILE_AS_LAST_CHILD; // The following alternative also works quite nicely //strategy = Strategy::FROM_FILE_AS_FIRST_CHILD; } } if (!read_file(cutfname(), 1, strategy)) { widget_browser->rebuild(); fl_message("Can't read %s: %s", cutfname(), strerror(errno)); } undo_resume(); widget_browser->display(Fl_Type::current); widget_browser->rebuild(); pasteoffset = 0; ipasteoffset += 10; } /** Duplicate the selected widgets. This code is a bit complex because it needs to find the last selected widget with the lowest level, so that the new widgets are inserted after this one. */ void duplicate_cb(Fl_Widget*, void*) { if (!Fl_Type::current) { fl_beep(); return; } // flush the text widgets to make sure the user's changes are saved: flush_text_widgets(); // find the last selected node with the lowest level: int lowest_level = 9999; Fl_Type *new_insert = NULL; if (Fl_Type::current->selected) { for (Fl_Type *t = Fl_Type::first; t; t = t->next) { if (t->selected && (t->level <= lowest_level)) { lowest_level = t->level; new_insert = t; } } } if (new_insert) Fl_Type::current = new_insert; // write the selected widgets to a file: if (!write_file(cutfname(1),1)) { fl_message("Can't write %s: %s", cutfname(1), strerror(errno)); return; } // read the file and add the widgets after the current one: pasteoffset = 0; undo_checkpoint(); undo_suspend(); if (!read_file(cutfname(1), 1, Strategy::FROM_FILE_AFTER_CURRENT)) { fl_message("Can't read %s: %s", cutfname(1), strerror(errno)); } fl_unlink(cutfname(1)); widget_browser->display(Fl_Type::current); widget_browser->rebuild(); undo_resume(); } /** User wants to sort selected widgets by y coordinate. */ static void sort_cb(Fl_Widget *,void *) { undo_checkpoint(); sort((Fl_Type*)NULL); widget_browser->rebuild(); set_modflag(1); } /** Open the "About" dialog. */ void about_cb(Fl_Widget *, void *) { if (!about_panel) make_about_panel(); about_panel->show(); } /** Open a dialog to show the HTML help page form the FLTK documentation folder. \param[in] name name of the HTML help file. */ void show_help(const char *name) { const char *docdir; char helpname[FL_PATH_MAX]; if (!help_dialog) help_dialog = new Fl_Help_Dialog(); if ((docdir = fl_getenv("FLTK_DOCDIR")) == NULL) { docdir = FLTK_DOCDIR; } snprintf(helpname, sizeof(helpname), "%s/%s", docdir, name); // make sure that we can read the file FILE *f = fopen(helpname, "rb"); if (f) { fclose(f); help_dialog->load(helpname); } else { // if we can not read the file, we display the canned version instead // or ask the native browser to open the page on www.fltk.org if (strcmp(name, "fluid.html")==0) { if (!Fl_Shared_Image::find("embedded:/fluid_flow_chart_800.png")) new Fl_PNG_Image("embedded:/fluid_flow_chart_800.png", fluid_flow_chart_800_png, sizeof(fluid_flow_chart_800_png)); help_dialog->value ( "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" "<html><head><title>FLTK: Programming with FLUID\n" "

What is FLUID?

\n" "The Fast Light User Interface Designer, or FLUID, is a graphical editor " "that is used to produce FLTK source code. FLUID edits and saves its state " "in .fl files. These files are text, and you can (with care) " "edit them in a text editor, perhaps to get some special effects.

\n" "FLUID can \"compile\" the .fl file into a .cxx " "and a .h file. The .cxx file defines all the " "objects from the .fl file and the .h file " "declares all the global ones. FLUID also supports localization " "(Internationalization) of label strings using message files and the GNU " "gettext or POSIX catgets interfaces.

\n" "A simple program can be made by putting all your code (including a " "main() function) into the .fl file and thus making the " ".cxx file a single source file to compile. Most programs are " "more complex than this, so you write other .cxx files that " "call the FLUID functions. These .cxx files must " "#include the .h file or they can #include " "the .cxx file so it still appears to be a single source file.

" "

" "

More information is available online at https://www.fltk.org/" "" ); } else if (strcmp(name, "license.html")==0) { fl_open_uri("https://www.fltk.org/doc-1.4/license.html"); return; } else if (strcmp(name, "index.html")==0) { fl_open_uri("https://www.fltk.org/doc-1.4/index.html"); return; } else { snprintf(helpname, sizeof(helpname), "https://www.fltk.org/%s", name); fl_open_uri(helpname); return; } } help_dialog->show(); } /** User wants help on Fluid. */ void help_cb(Fl_Widget *, void *) { show_help("fluid.html"); } /** User wants to see the Fluid manual. */ void manual_cb(Fl_Widget *, void *) { show_help("index.html"); } // ---- Printing /** Open the dialog to allow the user to print the current window. */ void print_menu_cb(Fl_Widget *, void *) { int w, h, ww, hh; int frompage, topage; Fl_Type *t; // Current widget int num_windows; // Number of windows Fl_Window_Type *windows[1000]; // Windows to print int winpage; // Current window page Fl_Window *win; for (t = Fl_Type::first, num_windows = 0; t; t = t->next) { if (t->is_a(ID_Window)) { windows[num_windows] = (Fl_Window_Type *)t; if (!((Fl_Window*)(windows[num_windows]->o))->shown()) continue; num_windows ++; } } Fl_Printer printjob; if ( printjob.start_job(num_windows, &frompage, &topage) ) return; int pagecount = 0; for (winpage = 0; winpage < num_windows; winpage++) { float scale = 1, scale_x = 1, scale_y = 1; if (winpage+1 < frompage || winpage+1 > topage) continue; printjob.start_page(); printjob.printable_rect(&w, &h); // Get the time and date... time_t curtime = time(NULL); struct tm *curdate = localtime(&curtime); char date[1024]; strftime(date, sizeof(date), "%c", curdate); fl_font(FL_HELVETICA, 12); fl_color(FL_BLACK); fl_draw(date, (w - (int)fl_width(date))/2, fl_height()); sprintf(date, "%d/%d", ++pagecount, topage-frompage+1); fl_draw(date, w - (int)fl_width(date), fl_height()); // Get the base filename... Fl_String basename = fl_filename_name(Fl_String(filename)); fl_draw(basename.c_str(), 0, fl_height()); // print centered and scaled to fit in the page win = (Fl_Window*)windows[winpage]->o; ww = win->decorated_w(); if(ww > w) scale_x = float(w)/ww; hh = win->decorated_h(); if(hh > h) scale_y = float(h)/hh; if (scale_x < scale) scale = scale_x; if (scale_y < scale) scale = scale_y; if (scale < 1) { printjob.scale(scale); printjob.printable_rect(&w, &h); } printjob.origin(w/2, h/2); printjob.print_window(win, -ww/2, -hh/2); printjob.end_page(); } printjob.end_job(); } // ---- Main menu bar extern void select_layout_preset_cb(Fl_Widget *, void *user_data); extern void layout_suite_marker(Fl_Widget *, void *user_data); static void menu_file_new_cb(Fl_Widget *, void *) { new_project(); } static void menu_file_new_from_template_cb(Fl_Widget *, void *) { new_project_from_template(); } static void menu_file_open_cb(Fl_Widget *, void *) { open_project_file(""); } static void menu_file_insert_cb(Fl_Widget *, void *) { merge_project_file(""); } static void menu_file_open_history_cb(Fl_Widget *, void *v) { open_project_file(Fl_String((const char*)v)); } static void menu_layout_sync_resize_cb(Fl_Menu_ *m, void*) { if (m->mvalue()->value()) Fl_Type::allow_layout = 1; else Fl_Type::allow_layout = 0; } /** This is the main Fluid menu. Design history is manipulated right inside this menu structure. Some menu items change or deactivate correctly, but most items just trigger various callbacks. \c New_Menu creates new widgets and is explained in detail in another location. \see New_Menu \todo This menu needs some major modernization. Menus are too long and their sorting is not always obvious. \todo Shortcuts are all over the place (Alt, Ctrl, Command, Shift-Ctrl, function keys), and there should be a help page listing all shortcuts. */ Fl_Menu_Item Main_Menu[] = { {"&File",0,0,0,FL_SUBMENU}, {"&New", FL_COMMAND+'n', menu_file_new_cb}, {"&Open...", FL_COMMAND+'o', menu_file_open_cb}, {"&Insert...", FL_COMMAND+'i', menu_file_insert_cb, 0, FL_MENU_DIVIDER}, {"&Save", FL_COMMAND+'s', save_cb, 0}, {"Save &As...", FL_COMMAND+FL_SHIFT+'s', save_cb, (void*)1}, {"Sa&ve A Copy...", 0, save_cb, (void*)2}, {"&Revert...", 0, revert_cb, 0, FL_MENU_DIVIDER}, {"New &From Template...", FL_COMMAND+'N', menu_file_new_from_template_cb, 0}, {"Save As &Template...", 0, save_template_cb, 0, FL_MENU_DIVIDER}, {"&Print...", FL_COMMAND+'p', print_menu_cb}, {"Write &Code", FL_COMMAND+FL_SHIFT+'c', write_cb, 0}, // Matt: disabled {"MergeBack Code", FL_COMMAND+FL_SHIFT+'m', mergeback_cb, 0}, {"&Write Strings", FL_COMMAND+FL_SHIFT+'w', write_strings_cb, 0, FL_MENU_DIVIDER}, {relative_history[0], FL_COMMAND+'1', menu_file_open_history_cb, absolute_history[0]}, {relative_history[1], FL_COMMAND+'2', menu_file_open_history_cb, absolute_history[1]}, {relative_history[2], FL_COMMAND+'3', menu_file_open_history_cb, absolute_history[2]}, {relative_history[3], FL_COMMAND+'4', menu_file_open_history_cb, absolute_history[3]}, {relative_history[4], FL_COMMAND+'5', menu_file_open_history_cb, absolute_history[4]}, {relative_history[5], FL_COMMAND+'6', menu_file_open_history_cb, absolute_history[5]}, {relative_history[6], FL_COMMAND+'7', menu_file_open_history_cb, absolute_history[6]}, {relative_history[7], FL_COMMAND+'8', menu_file_open_history_cb, absolute_history[7]}, {relative_history[8], FL_COMMAND+'9', menu_file_open_history_cb, absolute_history[8]}, {relative_history[9], 0, menu_file_open_history_cb, absolute_history[9], FL_MENU_DIVIDER}, {"&Quit", FL_COMMAND+'q', exit_cb}, {0}, {"&Edit",0,0,0,FL_SUBMENU}, {"&Undo", FL_COMMAND+'z', undo_cb}, {"&Redo", FL_COMMAND+FL_SHIFT+'z', redo_cb, 0, FL_MENU_DIVIDER}, {"C&ut", FL_COMMAND+'x', cut_cb}, {"&Copy", FL_COMMAND+'c', copy_cb}, {"&Paste", FL_COMMAND+'v', paste_cb}, {"Dup&licate", FL_COMMAND+'u', duplicate_cb}, {"&Delete", FL_Delete, delete_cb, 0, FL_MENU_DIVIDER}, {"Select &All", FL_COMMAND+'a', select_all_cb}, {"Select &None", FL_COMMAND+FL_SHIFT+'a', select_none_cb, 0, FL_MENU_DIVIDER}, {"Pr&operties...", FL_F+1, openwidget_cb}, {"&Sort",0,sort_cb}, {"&Earlier", FL_F+2, earlier_cb}, {"&Later", FL_F+3, later_cb}, {"&Group", FL_F+7, group_cb}, {"Ung&roup", FL_F+8, ungroup_cb,0, FL_MENU_DIVIDER}, {"Hide O&verlays",FL_COMMAND+FL_SHIFT+'o',toggle_overlays}, {"Hide Guides",FL_COMMAND+FL_SHIFT+'g',toggle_guides}, {"Hide Restricted",FL_COMMAND+FL_SHIFT+'r',toggle_restricted}, {"Show Widget &Bin...",FL_ALT+'b',toggle_widgetbin_cb}, {"Show Code View",FL_ALT+'c', (Fl_Callback*)toggle_codeview_cb, 0, FL_MENU_DIVIDER}, {"Settings...",FL_ALT+'p',show_settings_cb}, {0}, {"&New", 0, 0, (void *)New_Menu, FL_SUBMENU_POINTER}, {"&Layout",0,0,0,FL_SUBMENU}, {"&Align",0,0,0,FL_SUBMENU}, {"&Left",0,(Fl_Callback *)align_widget_cb,(void*)10}, {"&Center",0,(Fl_Callback *)align_widget_cb,(void*)11}, {"&Right",0,(Fl_Callback *)align_widget_cb,(void*)12}, {"&Top",0,(Fl_Callback *)align_widget_cb,(void*)13}, {"&Middle",0,(Fl_Callback *)align_widget_cb,(void*)14}, {"&Bottom",0,(Fl_Callback *)align_widget_cb,(void*)15}, {0}, {"&Space Evenly",0,0,0,FL_SUBMENU}, {"&Across",0,(Fl_Callback *)align_widget_cb,(void*)20}, {"&Down",0,(Fl_Callback *)align_widget_cb,(void*)21}, {0}, {"&Make Same Size",0,0,0,FL_SUBMENU}, {"&Width",0,(Fl_Callback *)align_widget_cb,(void*)30}, {"&Height",0,(Fl_Callback *)align_widget_cb,(void*)31}, {"&Both",0,(Fl_Callback *)align_widget_cb,(void*)32}, {0}, {"&Center In Group",0,0,0,FL_SUBMENU}, {"&Horizontal",0,(Fl_Callback *)align_widget_cb,(void*)40}, {"&Vertical",0,(Fl_Callback *)align_widget_cb,(void*)41}, {0}, {"Synchronized Resize", 0, (Fl_Callback*)menu_layout_sync_resize_cb, NULL, FL_MENU_TOGGLE|FL_MENU_DIVIDER }, {"&Grid and Size Settings...",FL_COMMAND+'g',show_grid_cb, NULL, FL_MENU_DIVIDER}, {"Presets", 0, layout_suite_marker, (void*)main_layout_submenu_, FL_SUBMENU_POINTER }, {"Application", 0, select_layout_preset_cb, (void*)0, FL_MENU_RADIO|FL_MENU_VALUE }, {"Dialog", 0, select_layout_preset_cb, (void*)1, FL_MENU_RADIO }, {"Toolbox", 0, select_layout_preset_cb, (void*)2, FL_MENU_RADIO }, {0}, {"&Shell", 0, Fd_Shell_Command_List::menu_marker, (void*)Fd_Shell_Command_List::default_menu, FL_SUBMENU_POINTER}, {"&Help",0,0,0,FL_SUBMENU}, {"&Rapid development with FLUID...",0,help_cb}, {"&FLTK Programmers Manual...",0,manual_cb, 0, FL_MENU_DIVIDER}, {"&About FLUID...",0,about_cb}, {0}, {0}}; /** Change the app's and hence preview the design's scheme. The scheme setting is stored in the app preferences - in key \p 'scheme_name' since 1.4.0 - in key \p 'scheme' (index: 0 - 4) in 1.3.x This callback is triggered by changing the scheme in the Fl_Scheme_Choice widget (\p Edit/GUI Settings). \param[in] choice the calling widget \see init_scheme() for choice values and backwards compatibility */ void scheme_cb(Fl_Scheme_Choice *choice, void *) { if (batch_mode) return; // set the new scheme only if the scheme was changed const char *new_scheme = choice->text(choice->value()); if (Fl::is_scheme(new_scheme)) return; Fl::scheme(new_scheme); fluid_prefs.set("scheme_name", new_scheme); // Backwards compatibility: store 1.3 scheme index (1-4). // We assume that index 0-3 (base, plastic, gtk+, gleam) are in the // same order as in 1.3.x (index 1-4), higher values are ignored int scheme_index = scheme_choice->value(); if (scheme_index <= 3) // max. index for 1.3.x (Gleam) fluid_prefs.set("scheme", scheme_index + 1); // compensate for different indexing } /** Read Fluid's scheme preferences and set the app's scheme. Since FLTK 1.4.0 the scheme \b name is stored as a character string with key "scheme_name" in the preference database. In FLTK 1.3.x the scheme preference was stored as an integer index with key "scheme" in the database. The known schemes were hardcoded in Fluid's sources (here for reference): | Index | 1.3 Scheme Name | Choice | 1.4 Scheme Name | |-------|-----------------|-------|-----------------| | 0 | Default (same as None) | n/a | n/a | | 1 | None (same as Default) | 0 | base | | 2 | Plastic | 1 | plastic | | 3 | GTK+ | 2 | gtk+ | | 4 | Gleam | 3 | gleam | | n/a | n/a | 4 | oxy | The new Fluid tries to keep backwards compatibility and reads both keys (\p scheme and \p scheme_name). If the latter is defined, it is used. If not the old \p scheme (index) is used - but we need to subtract one to get the new Fl_Scheme_Choice index (column "Choice" above). */ void init_scheme() { int scheme_index = 0; // scheme index for backwards compatibility (1.3.x) char *scheme_name = 0; // scheme name since 1.4.0 fluid_prefs.get("scheme_name", scheme_name, "XXX"); // XXX means: not set => fallback 1.3.x if (!strcmp(scheme_name, "XXX")) { fluid_prefs.get("scheme", scheme_index, 0); if (scheme_index > 0) { scheme_index--; scheme_choice->value(scheme_index); // set the choice value } if (scheme_index < 0) scheme_index = 0; else if (scheme_index > scheme_choice->size() - 1) scheme_index = 0; scheme_name = const_cast(scheme_choice->text(scheme_index)); fluid_prefs.set("scheme_name", scheme_name); } // Set the new scheme only if it was not overridden by the -scheme // command line option if (Fl::scheme() == NULL) { Fl::scheme(scheme_name); } free(scheme_name); } /** Show or hide the widget bin. The state is stored in the app preferences. */ void toggle_widgetbin_cb(Fl_Widget *, void *) { if (!widgetbin_panel) { make_widgetbin(); if (!position_window(widgetbin_panel,"widgetbin_pos", 1, 320, 30)) return; } if (widgetbin_panel->visible()) { widgetbin_panel->hide(); widgetbin_item->label("Show Widget &Bin..."); } else { widgetbin_panel->show(); widgetbin_item->label("Hide Widget &Bin"); } } /** Show or hide the code preview window. */ void toggle_codeview_cb(Fl_Double_Window *, void *) { codeview_toggle_visibility(); } /** Show or hide the code preview window, button callback. */ void toggle_codeview_b_cb(Fl_Button*, void *) { codeview_toggle_visibility(); } /** Build the main app window and create a few other dialogs. */ void make_main_window() { if (!batch_mode) { fluid_prefs.get("show_guides", show_guides, 1); fluid_prefs.get("show_restricted", show_restricted, 1); fluid_prefs.get("show_ghosted_outline", show_ghosted_outline, 0); fluid_prefs.get("show_comments", show_comments, 1); make_shell_window(); } if (!main_window) { Fl_Widget *o; loadPixmaps(); main_window = new Fl_Double_Window(WINWIDTH,WINHEIGHT,"fluid"); main_window->box(FL_NO_BOX); o = make_widget_browser(0,MENUHEIGHT,BROWSERWIDTH,BROWSERHEIGHT); o->box(FL_FLAT_BOX); o->tooltip("Double-click to view or change an item."); main_window->resizable(o); main_menubar = new Fl_Menu_Bar(0,0,BROWSERWIDTH,MENUHEIGHT); main_menubar->menu(Main_Menu); // quick access to all dynamic menu items save_item = (Fl_Menu_Item*)main_menubar->find_item(save_cb); history_item = (Fl_Menu_Item*)main_menubar->find_item(menu_file_open_history_cb); widgetbin_item = (Fl_Menu_Item*)main_menubar->find_item(toggle_widgetbin_cb); codeview_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_codeview_cb); overlay_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_overlays); guides_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_guides); restricted_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_restricted); main_menubar->global(); fill_in_New_Menu(); main_window->end(); } if (!batch_mode) { load_history(); g_shell_config = new Fd_Shell_Command_List; widget_browser->load_prefs(); make_settings_window(); } } /** Load file history from preferences. This loads the absolute filepaths of the last 10 used design files. It also computes and stores the relative filepaths for display in the main menu. */ void load_history() { int i; // Looping var int max_files; fluid_prefs.get("recent_files", max_files, 5); if (max_files > 10) max_files = 10; for (i = 0; i < max_files; i ++) { fluid_prefs.get( Fl_Preferences::Name("file%d", i), absolute_history[i], "", sizeof(absolute_history[i])); if (absolute_history[i][0]) { // Make a shortened version of the filename for the menu... Fl_String fn = fl_filename_shortened(absolute_history[i], 48); strncpy(relative_history[i], fn.c_str(), sizeof(relative_history[i]) - 1); if (i == 9) history_item[i].flags = FL_MENU_DIVIDER; else history_item[i].flags = 0; } else break; } for (; i < 10; i ++) { if (i) history_item[i-1].flags |= FL_MENU_DIVIDER; history_item[i].hide(); } } /** Update file history from preferences. Add this new filepath to the history and update the main menu. Writes the new file history to the app preferences. \param[in] flname path or filename of .fl file, will be converted into an absolute file path based on the current working directory. */ void update_history(const char *flname) { int i; // Looping var char absolute[FL_PATH_MAX]; int max_files; fluid_prefs.get("recent_files", max_files, 5); if (max_files > 10) max_files = 10; fl_filename_absolute(absolute, sizeof(absolute), flname); #ifdef _WIN32 // Make path canonical. for (char *s = absolute; *s; s++) { if (*s == '\\') *s = '/'; } #endif for (i = 0; i < max_files; i ++) #if defined(_WIN32) || defined(__APPLE__) if (!strcasecmp(absolute, absolute_history[i])) break; #else if (!strcmp(absolute, absolute_history[i])) break; #endif // _WIN32 || __APPLE__ if (i == 0) return; if (i >= max_files) i = max_files - 1; // Move the other flnames down in the list... memmove(absolute_history + 1, absolute_history, i * sizeof(absolute_history[0])); memmove(relative_history + 1, relative_history, i * sizeof(relative_history[0])); // Put the new file at the top... strlcpy(absolute_history[0], absolute, sizeof(absolute_history[0])); Fl_String fn = fl_filename_shortened(absolute_history[0], 48); strncpy(relative_history[0], fn.c_str(), sizeof(relative_history[0]) - 1); // Update the menu items as needed... for (i = 0; i < max_files; i ++) { fluid_prefs.set( Fl_Preferences::Name("file%d", i), absolute_history[i]); if (absolute_history[i][0]) { if (i == 9) history_item[i].flags = FL_MENU_DIVIDER; else history_item[i].flags = 0; } else break; } for (; i < 10; i ++) { fluid_prefs.set( Fl_Preferences::Name("file%d", i), ""); if (i) history_item[i-1].flags |= FL_MENU_DIVIDER; history_item[i].hide(); } fluid_prefs.flush(); } /** Set the filename of the current .fl design. \param[in] c the new absolute filename and path */ void set_filename(const char *c) { if (filename) free((void *)filename); filename = c ? fl_strdup(c) : NULL; if (filename && !batch_mode) update_history(filename); set_modflag(modflag); } /** Set the "modified" flag and update the title of the main window. The first argument sets the modification state of the current design against the corresponding .fl design file. Any change to the widget tree will mark the design 'modified'. Saving the design will mark it clean. The second argument is optional and set the modification state of the current design against the source code and header file. Any change to the tree, including saving the tree, will mark the code 'outdated'. Generating source code and header files will clear this flag until the next modification. \param[in] mf 0 to clear the modflag, 1 to mark the design "modified", -1 to ignore this parameter \param[in] mfc default -1 to let \c mf control \c modflag_c, 0 to mark the code files current, 1 to mark it out of date. -2 to ignore changes to mf. */ void set_modflag(int mf, int mfc) { const char *code_ext = NULL; char new_title[FL_PATH_MAX]; // Update the modflag_c to the worst possible condition. We could be a bit // more graceful and compare modification times of the files, but C++ has // no API for that until C++17. if (mf!=-1) { modflag = mf; if (mfc==-1 && mf==1) mfc = mf; } if (mfc>=0) { modflag_c = mfc; } if (main_window) { Fl_String basename; if (!filename) basename = "Untitled.fl"; else basename = fl_filename_name(Fl_String(filename)); code_ext = fl_filename_ext(g_project.code_file_name.c_str()); char mod_star = modflag ? '*' : ' '; char mod_c_star = modflag_c ? '*' : ' '; snprintf(new_title, sizeof(new_title), "%s%c %s%c", basename.c_str(), mod_star, code_ext, mod_c_star); const char *old_title = main_window->label(); // only update the title if it actually changed if (!old_title || strcmp(old_title, new_title)) main_window->copy_label(new_title); } // if the UI was modified in any way, update the Code View panel if (codeview_panel && codeview_panel->visible() && cv_autorefresh->value()) codeview_defer_update(); } // ---- Main program entry point /** Handle command line arguments. \param[in] argc number of arguments in the list \param[in] argv pointer to an array of arguments \param[inout] i current argument index \return number of arguments used; if 0, the argument is not supported */ static int arg(int argc, char** argv, int& i) { if (argv[i][0] != '-') return 0; if (argv[i][1] == 'd' && !argv[i][2]) { G_debug=1; i++; return 1; } if (argv[i][1] == 'u' && !argv[i][2]) { update_file++; batch_mode++; i++; return 1; } if (argv[i][1] == 'c' && !argv[i][2]) { compile_file++; batch_mode++; i++; return 1; } if ((strcmp(argv[i], "-v")==0) || (strcmp(argv[i], "--version")==0)) { show_version = 1; i++; return 1; } if (argv[i][1] == 'c' && argv[i][2] == 's' && !argv[i][3]) { compile_file++; compile_strings++; batch_mode++; i++; return 1; } if (argv[i][1] == 'o' && !argv[i][2] && i+1 < argc) { g_code_filename_arg = argv[i+1]; batch_mode++; i += 2; return 2; } #ifndef NDEBUG if ((i+1 < argc) && (strcmp(argv[i], "--autodoc") == 0)) { g_autodoc_path = argv[i+1]; i += 2; return 2; } #endif if (strcmp(argv[i], "--help")==0) { return 0; } if (argv[i][1] == 'h' && !argv[i][2]) { if ( (i+1 < argc) && (argv[i+1][0] != '-') ) { g_header_filename_arg = argv[i+1]; batch_mode++; i += 2; return 2; } else { // a lone "-h" without a filename will output the help string return 0; } } return 0; } #if ! (defined(_WIN32) && !defined (__CYGWIN__)) int quit_flag = 0; #include #ifdef _sigargs #define SIGARG _sigargs #else #ifdef __sigargs #define SIGARG __sigargs #else #define SIGARG int // you may need to fix this for older systems #endif #endif extern "C" { static void sigint(SIGARG) { signal(SIGINT,sigint); quit_flag = 1; } } #endif /** Start Fluid. Fluid can run in interactive mode with a full user interface to design new user interfaces and write the C++ files to manage them, Fluid can run form the command line in batch mode to convert .fl design files into C++ source and header files. In batch mode, no display is needed, particularly no X11 connection will be attempted on Linux/Unix. \param[in] argc number of arguments in the list \param[in] argv pointer to an array of arguments \return in batch mode, an error code will be returned via \c exit() . This function return 1, if there was an error in the parameters list. \todo On Windows, Fluid can under certain conditions open a dialog box, even in batch mode. Is that intentional? Does it circumvent issues with Windows' stderr and stdout? */ int main(int argc,char **argv) { int i = 1; setlocale(LC_ALL, ""); // enable multi-language errors in file chooser setlocale(LC_NUMERIC, "C"); // make sure numeric values are written correctly g_launch_path = end_with_slash(fl_getcwd()); // store the current path at launch Fl::args_to_utf8(argc, argv); // for MSYS2/MinGW if ( (Fl::args(argc,argv,i,arg) == 0) // unsupported argument found || (batch_mode && (i != argc-1)) // .fl filename missing || (!batch_mode && (i < argc-1)) // more than one filename found || (argv[i] && (argv[i][0] == '-'))) { // unknown option static const char *msg = "usage: %s name.fl\n" " -u : update .fl file and exit (may be combined with '-c' or '-cs')\n" " -c : write .cxx and .h and exit\n" " -cs : write .cxx and .h and strings and exit\n" " -o : .cxx output filename, or extension if starts with '.'\n" " -h : .h output filename, or extension if starts with '.'\n" " --help : brief usage information\n" " --version, -v : print fluid version number\n" " -d : enable internal debugging\n"; const char *app_name = NULL; if ( (argc > 0) && argv[0] && argv[0][0] ) app_name = fl_filename_name(argv[0]); if ( !app_name || !app_name[0]) app_name = "fluid"; #ifdef _MSC_VER // TODO: if this is fluid-cmd, use stderr and not fl_message fl_message(msg, app_name); #else fprintf(stderr, msg, app_name); #endif return 1; } if (show_version) { printf("fluid v%d.%d.%d\n", FL_MAJOR_VERSION, FL_MINOR_VERSION, FL_PATCH_VERSION); ::exit(0); } const char *c = NULL; if (g_autodoc_path.empty()) c = argv[i]; fl_register_images(); make_main_window(); if (c) set_filename(c); if (!batch_mode) { #ifdef __APPLE__ fl_open_callback(apple_open_cb); #endif // __APPLE__ Fl::visual((Fl_Mode)(FL_DOUBLE|FL_INDEX)); Fl_File_Icon::load_system_icons(); main_window->callback(exit_cb); position_window(main_window,"main_window_pos", 1, 10, 30, WINWIDTH, WINHEIGHT ); if (g_shell_config) { g_shell_config->read(fluid_prefs, FD_STORE_USER); g_shell_config->update_settings_dialog(); g_shell_config->rebuild_shell_menu(); } g_layout_list.read(fluid_prefs, FD_STORE_USER); main_window->show(argc,argv); toggle_widgetbin_cb(0,0); toggle_codeview_cb(0,0); if (!c && openlast_button->value() && absolute_history[0][0] && g_autodoc_path.empty()) { // Open previous file when no file specified... open_project_file(absolute_history[0]); } } undo_suspend(); if (c && !read_file(c,0)) { if (batch_mode) { fprintf(stderr,"%s : %s\n", c, strerror(errno)); exit(1); } fl_message("Can't read %s: %s", c, strerror(errno)); } undo_resume(); // command line args override code and header filenames from the project file // in batch mode only if (batch_mode) { if (!g_code_filename_arg.empty()) { g_project.code_file_set = 1; g_project.code_file_name = g_code_filename_arg; } if (!g_header_filename_arg.empty()) { g_project.header_file_set = 1; g_project.header_file_name = g_header_filename_arg; } } if (update_file) { // fluid -u write_file(c,0); if (!compile_file) exit(0); } if (compile_file) { // fluid -c[s] if (compile_strings) write_strings_cb(0,0); write_cb(0,0); exit(0); } // don't lock up if inconsistent command line arguments were given if (batch_mode) exit(0); set_modflag(0); undo_clear(); #ifndef _WIN32 signal(SIGINT,sigint); #endif // Set (but do not start) timer callback for external editor updates ExternalCodeEditor::set_update_timer_callback(external_editor_timer); #ifndef NDEBUG // check if the user wants FLUID to generate image for the user documentation if (!g_autodoc_path.empty()) { run_autodoc(g_autodoc_path); set_modflag(0, 0); exit_cb(0,0); return 0; } #endif #ifdef _WIN32 Fl::run(); #else while (!quit_flag) Fl::wait(); if (quit_flag) exit_cb(0,0); #endif // _WIN32 undo_clear(); return (0); } /// \} fltk-1.4.3/fluid/icons/0000755000175000017500000000000015004135251015023 5ustar albrechtalbrechtfltk-1.4.3/fluid/icons/language_64.png0000644000175000017500000000265215004135251017632 0ustar albrechtalbrechtPNG  IHDR`@O=qIDAThkLU ,tKKAj[(b5hbBC&6~0~0&ƄVb b[ZZ X` ,f.̚xÞ{g{uY+@Y`/H4f]N?KH4`4$KRQJ:p*1J"'`Zŵ挀,\Ht|f3$q9ZXծPXW`rEG48rM+Ie8ͼEVSUN"T!-~%.96>ǝ&er\̦0rzI;0(0̉5Ќ?i i`eJsMA*t*+ؽ5.YY(JP#st\vx@1ۼɼnq f/j4Mcj4P`?9]A/8oqA =CC1jI'@x,gD)ICv]&  Y8]%ۻy !RX~q?h'+\!Es> b2ĘBR 8V6ke N "%EkD5xE1\.TTv mBoqls[̄1Ȟ%ud B y N,~=AG9݌ U2~B[ JJ^ݣ&ޡI?~2nήD/_r-Jxڞ d*TVw#jatqO.$@3y=9(<+ʝ|#]Q~G 9ce(ò6r|5 }5Q)%|:) Iv{zfN4jp97B/#݃n~>ɴC!l\d=9l^BI{8-o iV.4e,PtfI2UK1.L bJ@6faN!0[qo~p@4H+Acs0$Z6kj~۾^4 @&!0=r0~XͿ8K{TIENDB`fltk-1.4.3/fluid/icons/fluid.animated.gif0000644000175000017500000000476115004135251020406 0ustar albrechtalbrechtGIF89a``?.0-6lNPM@{t|~{}bkt?*Se,pX`m[D&-/l! NETSCAPE2.0! ,``'dihlp,tmxn|G$"=V N[ZW?vp z-x۴ߤy.loWvw`]_deZ_k]hxZ|yaPmocWqBlZp~Aw]@poŽwyl9x|[6xw4}i1/-Xڡ#/޳Nnĥ+dj1՛iҶo3 NS&x4b.6A $L=zxA Tp 8)9bC/&l(J.:*D`4p&JAP :AE6+ $0 ,0* AjV (ZROb`oJŲJ`iz :A L똽ʱdi.\/&(?3R|[@43em#3`> zAR4'.`}&QG+R6*/K*~@}(#/]Cm#CdKN&-.퀆Ͷ>adF۱^sx:}Gpm nxv>p4 <7m[^&;N~#̀69ہRuZv$0 e;ոANo (7$Q z)0s 2ɂ Q xԀ׉K[ WŀhRچxC*V :"\JL YXC R€.@3>VOz⍞h1H3h %;6V$)DWã '*m R7FJ (`:cBHLb'Gy" H*WV򕰌,g ̥.w^R$ 0IL"LLf1K! ,&9'`hdpήg8ẚl$<#P`oǰCZۀ=1D]1 Cɓ&3! ,""6'^i9욾h+pͳ -_ ƈ4 IRM'tJ*'4{zxL.9<^k4>qrUS~P|Lp+ZPrm]}{:H\K@'jL?Epw.=\YA\ĆNsdpDxftZ]r"w!! ,$ 0'frcd+kh뼞 TMK7jX,g{͖ϱ363gNO.s9{|,{}*)]df.bG/)o9hLae'NTValSGvOo*.G4r6J&Vۈf²+*p)!! ,&8'P4hebi ,}}8] `aYjcCfۮ 9ٺoQmL[iRO0myGU@D'4pL9:/y"\9vz9vRA5:O'v7Ixyo8uF-ṷn'׿'nI`uG|J.8U%CQcǰ=#J;fltk-1.4.3/fluid/icons/general_64.png0000644000175000017500000000416215004135251017462 0ustar albrechtalbrechtPNG  IHDR`@O=9IDATh͚kpU<$B̃xR)$u:mga*CNT;v)>JM* ⴠ "h4ȃy/~H<'p.s{kZk%QH ćAܴSC!IDxˢrlY"ҀīWI$? wHS>c} ,`*gX'" 1FڹR4@+/eEdu'ah'ecBYP)aiJw 駕Xh xN=M L\$YU""` ]i' t)\#my< j@T{l` K,E'YCS@a2ģX9aGJyJo2"f.sPR.d6!l?weJ[fmAOuZiA Iǰ'gJVV%L51^3Uo++crH~"4q_.T69UB+g PI.ddXk[TH)ﲉh&Z,yN^*n$ Q zKtRl- _ETrt"2RE7$B(f=Fߍ=<<٫;Dye'3L|\9 AC<'e\32d:*#VJisL6rCLg*Cv^y^q)Vaexl7)5)V'M's&[ ć.Y,R(YAA>My4|D>|dcZ)p Ѩál*8cp@(v/3`HCGVUeZU鴳_FvݙJpAV^93iԝѺP槲Kg>O9 uNSx IbVw2O@Nsz8]G @9nmq8gr" (|JDLʃ}lf҅1D(xI%ﰖf{?aIENDB`fltk-1.4.3/fluid/icons/fluid-256.png0000644000175000017500000005635115004135251017160 0ustar albrechtalbrechtPNG  IHDR+ubKGD3 pHYs  tIME 3^7YtEXtComment̖ IDATxwE?ݓv6'vaAT@I0b:3) 'TD Tb@9y%)˒X6Lݙ>O?]]]}z߷ު(B+^YĹ ^6V2[|C2w?'kFT^N4|vAT4-g)/*šk]wvi\6 IW}!DXhIeYzᙉNFؾ}YQPdY&R4`:aO 6 ]9t9);cH3t|%>bҴo/7O`{ 书gqc$aaT!_<$5 (Άߓc}2[ \-у+{uI?I9_{ew^/VI2jk @qdMkUgrduO@-q)i9Y~7g4ҸEH):zujl~9 U?_ \5^6h1R;pґ[k[yįP=aoCډaMy:oUjn;b)Tp)S3pE{vߩ[W\0LsBY@~jH- }y%hBoW2jR=eoų ی F .rgO[8 ʝƘAw@$ӼOhs5c|advETлx NU[fSAnJnŇ vCQ?B`Z6a_ΉƚjBjw0I =MynhIw@}%t,iKno9-lݺ0hN/Uy'7Ze`Ӛ)@7/*Mzkr0Th&$I~鿉, %\w6ehB& ( yPZKӫŭayya]$IJC/h1xx1_0=HF+?4a6J B䁒0_gAGiӦX*ebř} nNCl.ux᝟V]ƍ%PaƪE1zbӦM\ *lҡeCYv3栀`WTt~$ pWf%5I7vԊĜlE,"HÒH}>F=^ v'˄խ!Ł^TF̑aR$#EY)|V\-7 c(pC!F@m9]Y"A"6%N1+z )t;W'L܁oo1E"v?ʽbte82P~OzBjAEMgƂNa ;@l2>,Sr8wF6g`s+p65^Gwn;ϑQ7J+Q@: M|?ԧv>/ú/̀=r ,?M i(woz +K<н+&FB믻*֋7Ma,**|5}A.TFy}Z}>tXl`foC:1gMĈ+ WB\`O=P_%5[|J|֮aFJxS- nOS#% l0 Wb k^G>> z /ILRCͥpb#E\d 98:*ȍoƝi*;֯`Bs`eD8?o<1t% 4R ]X؛[ UI-+䖨<@}@@~L$ >ZMR(K < m`F$m8y 5~SC+"esV‹Hy=CHr0, 5eKZ| ]m`-U&\խW,4y ?Go?z85z@s^ ytDe|g6\.P= ℉Ar(k~$6S"񢀈p#[i(@u)㢀OAcŢ* 'Ղ;z6PNz!#ͳhz8E".H55rӸ2ł(TyPpt_LlB)6'RwN3o'0eBT,h?~(smb5mNe,(]!GD;GU}2VVV3XPWQMMYpئWK/.^YB7VHg/R[Jׁ;nuA 5CeupG&|)Vh`g TlHd=([6VL'rzXy{OC6㴇!% V)4[CTv[v⮳@ru*RcP?"M~:aVV d#%g&cZbQU鴅mPDE74J.()g?PyY:2wDy8!|-S0߾S#hRhz1PR: (ZE(.;5sBNطYq]*w(RP2; o3{# p |]1dFz;8G~]3M%35|88[š6>6Hnу^H})^5M(H"[##THA;p?Q(aA^Ŗ2ff_dmGYM2ª?rԳa)H"/SvIh"ЂMIٝ۴-౔!9G`SWePǴc mE5[4uj1U_~3 IZv/.hYD IIlt$ڵkkV9rҥKfE&D'D8#ն t,@( dYǒ-^O6NϏ*\pBe9T”٭zH"rSqmѪu6`t}i+ [knYŚ4a_M0Z9-jТ44K$ !e;:,hY9{mh۽1Ol? oBŴ,`i.N#E{Q7e!آDeޖ9{F,E D8VOʉj7yGɢzZq۳O U!!e[dҜ(k͍Fm:ÞW{L&?|y 'Y3qXY"X~z<@Gmm Ϯ])h)gFT!q)pZ[ @x؞ m#f&ek*C&Ne^~.I%%6Bf*&y=Hg<-!8FG%sWxk :mH3xS |U@]8D P;=K^Er{կÛƵ&Fh2wјϞvєꘪ4 |橇Is*\=h\2^ڡ}PU*-e+ezx@1*qaZn'o\WYeonu2oհ8N%Ifs>bH*+WBU){C%GA"ũK4OJ,ܕtۼzeqH]K=vէcH(?rjo3;//?e_tiఁ"#SfvE)َlذd Ij$}`&]͉8wn,t3wu6n'eu0hdGH?Km׊s+2oGyz8.{\rzdʛɣ_O {.C5(sbH~n;OgCqH>CuUǛ'ˠxkurh4B*>V^1DWOcoJ4tdmB Z9Tv5/ RǗOԥSa\!e;?8?Ȩ93!#_y7zNY5JqRSL9 *u}^`iP:(ᆺr}>vڗ)NR+UQ>E?;?Np$y Ő?r)<$ha#'Ʃ+t0{]\|1d]]A)=npxc Co^DR~~sSL -Dy߃;/c?6'( 3GޡKO}(\wYÊեYM?U׌2(>LK{慎uiR=(:6P=ցv"߭릑"Yw\:S!b!;n,mS!šTUAVh ) ѣ~7G@f& /Z2;N]!#RrX5^>28aL#隭wK簳Kc7j,teljN6Y#8!# wG_B16NHFkh`aQ*/9 ݭ3o(8ʝ+.Sxqa∃Eyd{*yz)ͷ<~Cxk2WQ\Ś D^jO<.G؀\L}m*O 7Q!у7z&}o~\(޺ΤJ̮wJ?FcʂR t<<\yISvRq^3y>Bj7H6>p'!z : ბ`ϟ+Ovy^WoCs!#>%{(pV`d ׅTHəVsWae@ɑ f{:%I(\>q<3̑Nh§|Œg1:OU}W%"3]t)̼J7<ܑJA|x4֫*>᳨G)",QI8|nQ:P{mLsFw G='y^n 7;YD=Opf FjW%HLH0f؟V_cՐFߕ`:smsg $A|BEi/Vt?S.Ji 9Mi ixic}L MH qxj vc}Uكbו%:?"Y6 ɇR`zoD$[8*޺nWu8luqd+M2QnZ2]ڡJHx'˫!-+Mrmw,X` ,9<[Ղ&^>Wx1{j!I0e6{yV|+-|j"hK -h9<+$IHĄ PԵ}v.\ȸqׯN#i ▅N$Ki[5DneufP83U-@-<~8 n!iӦ6Gm.,YSl)>uE?^كBͿvCI^.tRDk IDATXhN$ BwcPa\@MZekD6j7d"(b:K-h~b'PVC!mtHO' ME?;E"}]֒ɮv_ I Io֭$@t݋Hv8]__o:XЎ-Hb@`prDL& B飖h4c#"ޡcBSLj0:f9ZбƜtn@3cĈ ~ln@ҋNбD9q7̆Vpw%Zg!=@"Z PP@IOOqq1EEE D YDHwm`k  "EYs~lĉFgF`#{&L1bD #DR?@ff&eeϏ},Yxrž}deeE29[U6%p<X<BB0h]nRXreZWFeҭ! ~6|.iľ~DKknE[&m@f%wŋng˭!iֺ#F`OAy V1 +**յq@}i.eD^ BCevby\쉶 JYY)b@ͱ_F6m^N7K/>ӧOG[,e߾sn|NPca6"(Pcϊ$(_Ji7vDh3W_U!(mΏJ޽{3j(G3-h0?P_qޑot޽M$]FR GA28(jO.&y"**Ilٲe3J`h{ |~8:NbL>ѐ(22:wt ;m&e}^ZpvKJb#9;ߏBlٲHFIxBWKF'4(Þ2%Qۻ=Hڲ^{ѣG7WAtNb^Q"CF!`n?~|2YQC:ΠRoʝ;wjTn`ט Q.~s%,p ]px[#EW\X-iKJLw#8iU%2o|rRSS;7}ޮLѴЮXNVRo~ +%jaÌ+ɝ*DEHz8RAvoa^Bp25Jv1ǚ MFO2I0QJെ?epF1<JCa)^ENu46:4L9)aT~sd#dD@z6'z:UAQ WyDrV*Jþ-zqyA$,m$$q祣{+ˮwo6{ $39`)6EY; v7' yϼ+Wy/؜`O d[C V1Ǘ{9,DY(4}~. H˒0Ű=٣p;x1=qW ;]4G(q[<e\>Em9\ \maǪ#d_.@ZAT&6h! 0I<7J#M4*w@;xà=/Hɰ[ {}3 ;Rݭ~EAE OQ!?ss|j3mL61ʙQWn1.Ѩr`ֳ׮aYowԯd}DSV| ](+/  ھ73se4o8*!Ì_eq $`H(6'PMW<$I]'ݦH]3կ(uMCr E+ [_[y'M I6%Q&W(GV7E-0(0!/ۍOS- *b𭵑oYK@b*ӷyx>Lfͩjv@td;me?^zףv@"K=j&B%LH͇ l4O6ewW]a<67l0|bo-U`yC-^y>5Kq1=~YM;(Ц뫐3v *BW ev?U{~Be eSCs'c@mGQbi5WBC1pi aN5 ~ #3 ;?(*+s)jU@Jdst3Xq52P{WWv"? MGf\ғ~w,f)i|}yhAǝC %KHIQˎbxޫM!9ɀA?{Qns:.ey8U6\qe#ۭ &>2)od\3eǖ #-`1lAv]87Ò]% xms>Ƈp;x;NuA=hWԤ0p}"=[\ʜZ69kQ8 p7Q`ǟf4@]v~jnQw$a灱7>puOJ~뻊Zt< f!#;Pw$ق:c-( I*[/5uv1#qf\I c'C)Dp%-"@ Bz.+K(Z) xqď%8Z |K{ å4sl2\Ao;_2ؕy3녱tE}k4HwEpްIEX|uȻt@s WOϟ%^2tVgVvcyyd z뿘qJq \nt\5#N9Zլ/8E}'T;\ N%K<P+[-W;ˡ$ߎץ)ٓ)י|nI.'oiejkX_7ܟKMqfȿFcK O7=3NՊOCJe]MDZk/+>:aVwb&lߪ[qe #;uiAOHF /tgdKS`4Ij3!-":+AURw&An4NaM-W/P{Ϭ?sk׫QoW!s?º]hag{wӯo(t'aҥٰO_s_ƿHOa1=}=˿>~- I|ĹΣZ5 ֩m%7`a4&@4ɜml-X` ,X` kZK`/lp47$D*;;^_ʭ.#@PH"1LVZ/*0>@x-Xh:Z* HB{D0ҎjVtZv Z SeYFREAQ$I!rilkZd`+Lq$IȲ$//|tBVV C᠃̎;سgX|9/w",Ж1k$zr6 /*Sױi q'l6<%,LQb0PҢ HvXNXXjjjgkv=Sj:Dy ;$b}d X=#&laO ƗYg '4*L3 !I߅X0o Yl@Qx,@{FU ~ U9|݄%,֔͌IC8̢JO V %5:J` nV=K5O<[Q"j? E-kqd,3 ??{$4Wof6,О!f/H(lݺL2@Q[[k&j)Kk>!.G,X",YG*Z@3VVY1KE`%%c%p8bf9, ,.P69tp:fY$` m& 8ZV$Řd 4@ɾŘhrLZc,@b & Izӛdb̂%"Jp衇6KA؆ ̘?[,@{Fz2Dl1w^3Y|e%3(,&b1j,4 brIs-L kSPKkĜlAŘ%KX&@{GT.$)ـI/̅[[2ȭT4,mҾǴ0Lh"Xh[ejjj_-HbB&eYniDi1r , B3VD"}^ Xo,3(8${(H N`]u 3S~'`O/%eە (}b3EEY&6@IFP E)fB[Rğ[Nikؽ{xheXh Xfm6o+m|ҽ{b,FWmژD+ >t: @ERZF#2EC Q3yYHfEueXP#F4$PB`J\3 W_VxF'DB~M6q!P]mzXDha$lSxkG-R@s7?m&qAA;vhO8(L3PY5:+//={M5pE  8,6a4֭[b̿f`~;g~iwgfJKYnÔUYi 0Œ7PQQA߾-"I_so߾t+3H=@?3-[8䙵*mwѣGeOnuGZ ^Ю܋yfnQQw令(9VVO; nh~͍`3 8pZX02BxGm>}9١u؄JPYAfGtFCǎS!B-XZߴ"ds/ _Z ސ=HkдIR^oĉcҏ - KfbŊu5F$c Pc͛;hHVB+ '"u :ʽViӦ)$^`J{'n^:I`oi3mUE.aj1رcYti)$XjC 1cK$7 1\PÆ om6ոS؊QVyp5_ >dy<\{x^3wH>4h,̛7oYmd[+ =w,h= `z˭kּK&bja0Z0rg:\&E7&BB3`Oh8xY,vܒ ƿ #oxo )&ů1Ux%01;&ֱr!Pʎ/kM`41tW$`aDU,vZ ~h= 芺t7_ÅI@xH[@QZB1Cm޾JMZ @eM9ᚍM'^ܔ]us }7>vw`UTe4> M$Y \tHŐ5G~5vCϫ1Z )rC 2u%;*: lOg{kjZ8ߨIO#Lg`S#ՓBg?GQEONLLWlX A^Dl{d[<j\6Oh<^ϏS \vMi R~nݾTn|@_l)c `!ίƶ/ L>w,v jE%IczGƳVQݾbȗӠV]dw %,(eeǤX d9h4n{[k>1bkl!{7&=q1xkۜH9oyw']v0*n%Q`ڢ3T"L؟6r Io?5;s颾>OGٍwfy^ d;uLZzXfMH]dO S։biR/ @_}L〱p~Vjɽ_./jsٙ V/{jԊd=EdU_>Xy8ݟTm#0Z{OdE\yԳTSy~~Qӑתv4JP9>ȋ{=2pZP %!.ٸ D8qRv5qo>U/pocۍ=1߯|>$lqW&d˙!vu !E%~Tb r?n=@w>?I~tc<5"ZzDHl.hT\qv^ RqsϨo}~,wq:2 E)Yl6WӜ_=`lRd-c&ׯ1$W_n{u:84v}} ˆ=H^4虖Xn,UAD/j؜NjlVͶTp 7)L7N# sH6A;a-9 ͷrO{8k`~ZI?/,ĨR#FbMYg~IG$WK QGC2VÂ-/A^ Bf 57w={%jx4<*ȵRxt*lx׌mZ`as S)ipƯSR-gfh eds:J|!F1sa~͔Bݲ37rPFmVla/ >a k~.fۿdsYO]6/2rSvStJD#̽=` bJpuƗןL7>3Ev}Eno1_aX&К}U@!rO3(O5WrbȎ[=;^?EC*CiGk/¦+/\'wOɕ!̾z2mw1:_Hӕ!,vH2*/{Y<*k\]Z)S-? Q}®0wQvcx'eT @ݖf̣o3o]I4vgmPX<+7tfԙw爿D٢+ [Р($ڢzPQQ҃LgЀڡQ_9l^2:zGC;ĩ(\f泧NSqS3鳩|:"K@BaFMw햎^ٗO~yq70bFR&찒x Jeo@pD5K'_Wc~{;6]n}7^vga &=&zGٚ~~'bS<)q6? :wpqyQSiØ_||8 Z\xM%^]ӓtAoF-Weϟ4ulb#Fyϊw7픩?Oࡱ7DuJLZ/Ʃ;@FBQx/G>ĭ/HeJGLH3 :#"F13boDliF(>tZzDߵ偷DŽ)Aq\/ߌn />GN},vUW&vYO!l[;Z_jЇ)4u\rK1{z?˵ˏ>{=|A]S}p3g^{[[HG%xWo,O0Ss6eW|\sQ>TefJMh$rZ?^\E*+r}+,ڜX+dDMl1b>ȒQaڎl@d]'wz"35ӈ.rҫyd_='m`_+l՜nc+qǫ'XN->@T/I7aqeM ٷFtT!S?us6,!FMv+hlZ]>[ßU 띔6'l Mǰ*_QS r#NVQn}h??Io[z~]hJ? =ŹqƎ|Wj9J$fw5>ڴÇ/xGI|6( ٘$m )(MMEԕ\0GT^5<Ļ}!~Y{pT?HB1Ħ6@lTPZ;RQ3&C,aT,`X҇dH,86 ƀ#A jM$!}sws<ߙ!s{|&Azg2-|V}_SzY{"T嗔{i|>I+I''uVZ@R~>o #,8gÉey"&~"fIF >/+n op/՟P7xC#mxبvշ=t<Orgh.ażr$ߴof5`$4`#3^_R/AͤDǁIy-֊)C d^Ii퍓?dRq>1z/x՚Mm|gf=7OJAS)Aكpn:wD7I ^sGpsa~P;K5UV]q˶3{ݳtwUW(>.NBqi Q_Rl8gIfs[$]m46Iu꒠Y'ע*S$x)?6ϝhć6Ud$dYGH8 z;b@'SX. v\>^.ЩΩd $qREx5LNVi"M,w2ǹXޮKχf . ϼW@%Rrng藍; ;>O=c9KTry%dO:NtXK6|dہ[ig+}R.%Y0%,^{b(}+h2^"6<:cL Duq8jꓩΤȭt Q|'ScN;JtXZb9^53_[/eXؽj[sд.gmVrH^opbevpUҒ5^⃋PcQ둜[ҽSYOʬ8Zor7KԶ[)]V>:mјd]^Qt^0!iڣY0Ic}kPՐ(y2|iĴ2]uT}?ܤdO6U;̽W2ק.!'ÜkO'_p8INݷK} =}=ڗ-WBGwȆ -*shY>>-yc鬜Cohwmŷ1Qw@WK@´PPh(.Vzˠb] !pm:\Y0 N6l|)v}pNWD_h5z>6lTˁ@VdƨC% PS !/GF;0W]VGW >U:=cztvbqpct>+~b}цx~~~(wl~pmkq~siuv{lo|zloyomz}pmyzmmvnp|`֬d}kw pzw{o @cs. ~#p#n#m*_-\,\,\-\-\;T?S?SMPPWUi-;Y%.G]$  CơܯX MY>8 <% ǶG = R y餗mW yl ȢGy.QހS(* 7U d S<ʁ|X޺o 4&.gJ||sve]&Ǝ{|UE^ {:'Qtp /4mOKf vT mV٠NaRn {  ҁ 5w; ks$߁ h8mk :OOOOL6 9/---%###$#+u;T-=\ uB<  w>NpIN }PExsgiit32% 9dۯp=%   232E B3 232 3 232 3 232 E   ## !#" /  # 232E#B3 232" 3 2232L 3R 232 R E  QRSRbz>T=0Nə,  tƋdB?((;T#3#E<u36 (3(Tʍ(3(|B3 ގ#3# TƏ ;((*E N /  &q232E+TB38232X҈ 3 $E& 232 z.3.  3 )3) 232  ȉ3E  03)3)@9.3.&Bnn; "T,X>Tr|K' •Dv \{ |wCˀ 0 6DY+>>R5|yϼJce  F?(Oց 'Hnk 0R|QT )փ)M؀@։N˄܀JJׁ vA+x$ F< 3`k*49o>+*whrhi-0k,Dee@@J"7| ?؃{^۽ӀP̀^1];2΀KI z*UBۃU"b E(z*G,X(8'\€dzo#i^€fu ݋ \ĸ|ڎ|гƳZt|ʝ˄ЁMm%ȁ ʂgRz8 m. P v" 'v Q [Mn+#Z@ ܓ 9dۯp=   Ƈ ֈ ## !#" # # "2LƈR R QRSRbz>T=0Nə,  tƋಀ?ցT<6ƊTʍ| ގƀTƏ ֍*֏N &q+T8X҈$֑ zƇƐ  ȉ֊00k|~"zjeÀ\BŀYr~}}|}}~~~ ~~}}~~-b~vwz{|{z{}~|zz{} }|zzy|~p[~֐wtz~~rw|qx}x+ ~bcmw}qnx}~_iu|8x ~^]`[iv}~ft|~{tWft|'u W_t_rZjw}~dbrz~|xVgv}|A~nXfnt^O\my~ ~zXfs|~[Zkx~c+ P]ltsolQaq{ |vlc`dnx}~O^oz~>~RapyzxvۀUft|~{upoqw|~~~|܀Rcs|=g~{ȀTcrz|}`Yjw|~}||{{|}~}| }~~}{ywwy|~~|{zx||Vhv}x Yv|},O^nxޭuz}yx|~}}ux|~}ʝS[lx~^Wцqx|ȀRbr}lu{iqykt{~P`pz~~4'~{uJS^hpxzVgtYfrzʀ^kv{ boy~~`^{Sdt|z${|wN[fnuzT[lwzwVeszZjw|zV_ny}\ZckoXiv}|4~zۀTcpw{|P`pz|pWhuS\mx}|Q`pz}ڀ{ValN\my~z&}iYjv|~}րTdt|}N\lwÀP`pz~}ՀTet{Q\jtQaq{:|P\nz~nXiv}}ԀRbqzTet|~~kXiv|UdrxՀUfu|!z~P`q{~~O\my~~xVgtdXjw}~O\nxN[kvbYjw}{e~ˀSdt|~Qbq{~P[lv؀N^nz~~RbqzRbqzN^nz~XB}Whv}}Ufu|~QapRbr{~}܀UftnWhuz܀Rbr{*r\Zlx~~^Yjw||Vfsہ~Vgu|~]YjuN\lxUfu|zc~O^oz~~N]x{RZjTZkv|}N]ẁO`px̀ZYkv|~dZ~Rbr|~~ŀQlwP^Na܀yzQlԀQbqNtty}_U}րVgu|}߀UӲosQtPpuxހVӮmǀS`케Uޞpv|~J, |]Zkx~}hlrgnlrwfjиemu{~x tO^oz~|centbepcmtxbelrb]dow|nY~BTds|}Z^irxxYajxb\gqx{Z^jrv|؊[cnV^jtz~YLG~eXiv}~zqf^\airy||ula\]bjrvri`]`hpx|}zqf^\airy{xqg`\^dlqoh`^bjsz})BK~}|}|P^nz~}xrnmpuz}~~{vplmqvz{ztomoty}~}xsnmpuz}~}ytomnrvyxtpnpuz}"|ζvw}Ves|7}{yyz|~~|zyyz|~~}|zyz|}}{zyz|~~|zyy{|~}|zyz|~{~mS\lx}~~~~~~~~~}bqXer{ր }mZbnx}׀ }|r`dmv|׀ ~zsjdcegjpv|~؀ ~zvqppruy|~ـ!V~|z|~ـ=9Y~~ـe> 9dۯp=   ## !#" ## "2LRRQRSRbz>T=0Nə,  tƞ?T<6Tʥ| ިTƩ*N &q+T8Xҵ$ z ȼ0S=D0 [ Ą Ѣ$M. s[B%V {c>-^q, XU,<N TDz c<tס q pV m2 |+7:\ >Cz΃`Z m|x:Tb,άa8|zwváys@ TXdA&`EY&hOꖀ k㦁`L{ "9NHj<ҀIs"ʁx<g<]&ǁx뻀*D{ٺ  L JPk,JR+芀2t=ˀ {M?V~rIZB0% p骁}6Ɋ_Ft5 E6J)h/^s9@>`蹁y><T .j=j| ́d*ƋՍT$Z8j</!1q>D.4K`9Y2o悀G~BFP8Y2sRb9"X'$4wG Ph.'#8֊*Orj F&ۀ,$餂;v2%.Tv10BO$Nh^7 A*MP $t<XrB̽ù;οRK:&F\l8)ڞ" iCWv  f Q  B zs|t8mk@p~~~~{mZ8 0b֜A~ H`~{xxxwvxxp_^``\\``^\^``\\T8.....-"  r7 h-[wl{ MAb1 SG\Df 4@" p>\4L9p"c 5 hR-Abe @M}"24kBK7 P [ h- lQTLS1$K|; M={|~~~~r%9'NFB4a~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~efltk-1.4.3/fluid/icons/document_64.png0000644000175000017500000000163715004135251017667 0ustar albrechtalbrechtPNG  IHDR`@O=fIDAThKSQ?s:*Ks)EI=CDzA{Z QDA/Ad_^^A>D'͜ӵ]vq윇}9{{݁Z' βqaGfǗqo£,AV)SkF2J3_WA4/Sf1*ֲ? Yb*!pf9H!Uz9D/_<j:Z:+@< <3V;`oLg7W([@fX2wxb 0k/-?^!W49ktqJ4k!C8pZ s ӥ\^ȫ@GF\xœ+ gA>38 giJTeylY8N60AGK>*~|)` -SOP 0iԈb^΀QNL,Oko$̓O1(˨'˳7jslGwQ W/D| |6v^xP/+/ ݲ{p!NerZ )ǐE[ ZԴ<9**y:{0 M~N 5QrZvm j'uk%KZ9Ī ށ߶ Oh.w pHYs;;̶ }IDATx^՜ V `т(R֋IMK@QJH8e=Rh@4ڂ \\^}߻?lٙٙ-#ΈܼL2ZjZjiYey>fDՔDWFWV,rJ ҵQч-z5 3Z倥/$4%YPbk 0~O y4XeR>G = WxrʕW^)*Ur}w7ȡCO?uʷ~3Wa;HgzY .%2e`ZB/[lRڵk'w}4lP~'ٹslذA֬Y#7nVa \>u.*( EZ1YF իtMjՊkÇŋW_/@ۅV aO\!\4PBQilbv2d޽TjΟ?/-Yfɑ#XF8_;6ġQ~ʕ+'={'xBΜ9#͓ٳgo5’(zJb-̰Ν;W5jgQ~߾} 4Hod<j)W8aN:; >,5nX}]СCLEC˔jV4+(nR*:_~3Hs1ٽ{wgnРTR%JXH>K u%5< gj~taDe˖… e˖-?z\r%r]w9IǎS w̙2eaяL&ji\%xfرcFGrDYjUy;Lukm'R%%KLc77p%53?sG@ʕEI޽ۢ v-mz(v[;|V'|;٦Mgv%֭3y뭷z gumZAlҫV2CsvcGDs2 % tO& d%{8!'(j鏀*⃰LbM 0Cs,~ϟ/lq`ҥΊmN&MLmov,l!]c!U%?sꫯ7ߌԩSUuAB~|?`9پ/ MVK$ܩ~&a>7_ԩSjN>=> 0%s`ENb~ :cFI q7.~ >?$1Bjrڴi33a]Іk?,m8BůD 8}/" տ=yDe2~0$ơw'h ء 뭄Z[3l‰=N*i$ q7Hl}&)"Ib\~pZ~}iѢ4G!}) az|3vtfNo߾2n8gfj/;|5_}՞ CTLqVPIQ 7ePO<GYB݄1w; ߢ4 tXݢ:< ĔǼӐ&q³s+Ǵ (T?~|f!Q;p3&qH㉭OQƬi^c h_QqrgS2*bŊr!а ':a sf5VF2l/_38_f~/*7SPGnظG]V b <)MV1?\$.}.D{a*^Ls~`. wzD. <\RA׎j 6tsSyjY<&qIENDB`fltk-1.4.3/fluid/icons/fluid-32.xpm0000644000175000017500000000324315004135251017100 0ustar albrechtalbrecht/* XPM */ static const char * const fluid_32_xpm[] = { "32 32 32 1", " c None", ". c #000200", "+ c #01162D", "@ c #01356A", "# c #2F312E", "$ c #035FB1", "% c #0061C0", "& c #0071E1", "* c #007FFF", "= c #247ABD", "- c #626E6F", "; c #777976", "> c #2A90E9", ", c #3291D2", "' c #2690FC", ") c #449EAD", "! c #5A9D87", "~ c #70AD78", "{ c #7EA3C4", "] c #87B556", "^ c #6EB8FF", "/ c #A8ABA9", "( c #A2C443", "_ c #8BC3F9", ": c #BED831", "< c #CDDF1B", "[ c #CACDCB", "} c #ACD7FF", "| c #ECF408", "1 c #E5E7E4", "2 c #DDEDFD", "3 c #FCFFFC", " ", " ....... ", " .-//[//. ", " ./^^333. ", " .{''231. ", " .[^^331. ", " .[33331. ", " .[33331. ", " .[33^'_. ", " .[33^',. ", " .[332}2. ", " .133331. ", " .133331. ", " .-333333;. ", " .#1332_333#. ", " .[333''^333. ", " ./3333>'}333/. ", " .-333333232_}3;. ", " .#132}23333_'>33#. ", " .[33^'^33332>^331. ", " .$'''*'*''''''''''$. ", " .@*')>{******,***>)&@. ", " .+&':~(:&*****:)**)|&*+. ", " .%*!:&~(&,'>'*>**,~(**&. ", " .$*':]>:!!|&|=~<&]~:!(]!:%*****+. ", " .&***):&!:=<]((&|!~:]<=*****&. ", ".$&**)~!**&**&&&*&&*&*&*******$.", ".%***]~%*****************'****%.", ".@%%%%%%%%%%%%%%%%%%%%%$%%%$%%@.", " .............................. "}; fltk-1.4.3/fluid/icons/fluid-64.png0000644000175000017500000000754615004135251017077 0ustar albrechtalbrechtPNG  IHDR@@nAHbKGD3 pHYs  tIME 3/ tEXtComment̖IDATx{XպpaAA1+dGs']][EDTe>dy;iSwv׶ڊR%M󂗼r30hyַz/]z/ h&lp\sADDn8:8~$) ;g?3R*ŻsU}* D>,r Z%g!;͇bMt?FrVJW瑙)(R".'2E̍**V > @a7Ńr-]v, o.:@`Xs9|3#WV\H)dƗ=.4P`8o%01;R_Ym[rFsg&?P=ֆf1>،Y(ˇ0~1 fYRSSY=;[h} bף(L#@Z8A۶mB fff:of *<1?W 4X(u|%aY'*mB6)Jq:"NyJ $E&y6OPo'ކYY)rd㑡2bM0_ˮ#Ukd&0:,EJ+y!%SMDgXz-*qQ)3h!$tp' 0+)Q}Y1.(v !.Mi]խmgdQ4vhL^^^<^Vϭz`id~xiZ˽>Ʌe-@Kn:]B[#<ŋO4¤TKȥ$^Vl']D &LzqցXRS!pg Gk"QA\K\")*r$Us{<îW>j1kԶ;:AKUϱ`ݽv31!JRs[52~I+u&vs:?Y745jDnY{ ZLǗ1#qK&Nʅ]3;:nʋS0 ;zwho:K#Eu $9;=2a'ѵ6+(`ynx $kjnZh?DEEpi9xEZWQQ"HXYVTT"nZD@r/ m~+ػw[k ?aE1U@{=`W0ASU¬뢄MUZ oik!߯j1X,"\k]}RjVXq̓# 999n (*&@5[s!zgLz^ށ5Y/? 4FXmJ-IVsKT>>SzSa9MӉwkFlCvXk!i+)௦x]FO_?ox'J~ f\7)`i;@b^/_I1]Py[s?dk5۞=ANeS?c@e P|Ҟ-W7`/]JW5w j [mnr%Rө70q d qsm* ~nnCBX 6Ճ3f`Z;Z@R@i "*_Bp=… 9!P'n: !v _{zh@@`` OAA½%-BBL7]<~5 Qm"X+JzA&6~p^篴jZl߄ h\z\oqo7u jl#'c<7a)Is3)"db: 2cȣ[X.ƙX:9ARkP6 %BZtgڻyO(6n 4=! .${'(``7"K$b`>*ŴAX}}0.>^z wPA˨hI0v V(t640g7֦$@PϿ1vl^׏CLQ`^b-@(͠Ѻ7.|;fw @(^Gf]N[;XyfXcY,GgST˟59vpbDs *nT@!tUOIENDB`fltk-1.4.3/fluid/icons/fluid-96.xpm0000644000175000017500000002364315004135251017120 0ustar albrechtalbrecht/* XPM */ static const char * const fluid_96_xpm[] = { "96 96 32 1", " c None", ". c #000100", "+ c #031F3F", "@ c #00366C", "# c #2E302D", "$ c #0058AC", "% c #0060BF", "& c #4E504D", "* c #14659F", "= c #006DDC", "- c #2C7087", "; c #0080FF", "> c #407B74", ", c #0F85F9", "' c #268CCD", ") c #7C7E7B", "! c #2D92EC", "~ c #4498A9", "{ c #2F94FE", "] c #5BA18C", "^ c #6BA674", "/ c #7DAD62", "( c #93BD53", "_ c #A4A6A2", ": c #6CB6FF", "< c #ABCC3F", "[ c #C4DA2A", "} c #CACCC9", "| c #DCE913", "1 c #BBDEFF", "2 c #FDFE00", "3 c #FDFFFC", " ", " ", " ", " ........... ", " ...................... ", " ........................ ", " ........#&#&#&#&##...... ", " ....)__}33333333333}_... ", " ...&33333333333333333... ", " ...#33311133333333333... ", " ...&33!,{,;:333333333... ", " ...&3:,{{{{,13333333}... ", " ...&3!{{!{{,13333333}... ", " ...&3:!{{!{;13333333}... ", " ...&3{{{{{{;133333333... ", " ...&31,{{{;,33333333}... ", " ...&331{{{:133333333}... ", " ...&3333333333333333_... ", " ...&3333333333333333}... ", " ...&3333333333333333_... ", " ...&3333333333333333}... ", " ...&3333333333333333_... ", " ...&3333333333333333}... ", " ...&3333333333333333_... ", " ...&3333333331!,,;:3}... ", " ...&333333333{{{{{;:_... ", " ...&333333331,{!{!{{}... ", " ...&333333331{{{{{{,_... ", " ...)333333331{{!{{{{_... ", " ...)333333333{{{!{;:_... ", " ...)3333333331{;;;:3_... ", " ...)3333333333331333_... ", " ...)3333333333333333_... ", " ...)3333333333333333_... ", " ..._3333333333333333_... ", " ..._3333333333333333_... ", " ..._3333333333333333_... ", " ..._3333333333333333}.... ", " ...._33333333333333333#... ", " ....&333333333333333333_.... ", " ....&33333333333333333333).... ", " ....333333333333333333333}&.... ", " ...._33333333333333333333333.... ", " ....&333333333331:11333333333_.... ", " ....#33333333333:,,,;:333333333&.... ", " ....}3333333333:,!{{{;1333333333&.... ", " ....}33333333333{{{!{{,!3333333333.... ", " ....)333333333333{{{{!{{{3333333333_.... ", " ....#3333333333333!{{{{{,:33333333333&.... ", " ...._33333333333331{{!{,;1333333333333#.... ", " ...._333333333333333:;,;,13333333333333_.... ", " ...._333333333333333333113333333333333333_.... ", " ....&33333333333333333333333333331::1333333&.... ", " ...._333333333333333333333333333{,{{;{133333#... ", " ...._3333333333333333333333333331,{!{{,:33333}.... ", " ....&3333333333133333333333333333:{{{{{{:333333).... ", " ...#333333331{,,;:333333333333333:{!{!{{:3333333&.... ", " ....}33333333,{{{{;:333333333333331,{!{{;:33333333#... ", " ...._333333331,!{!{{,333333333333333{,{{;{1333333333.... ", " ....&3333333331{{{{{{{3333333333333333::::33333333333).... ", " ....+!:::::::::{{{{!{{;::::::::::::::::::::::::::!:::::+.... ", " ...+=;;;;;;;;;;;;{{{{;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=.... ", " ....%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%.... ", " ....@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$.... ", " ...+%;;;;;;!!!;;;;;,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;!=;;;+.... ", " ....%;;;;;!([<|^~]^([%;;;;;;;;;;;;;;;;;,(<'=;;;;;;;!^/<[|'=;;=+... ", " ....$;;;;;'|2>]22<|22[%=;;;;;;;;;;;;;;;;^22[%=;;;;;;!][22|%=;;;$.... ", " ....@;;;;;;[2[%^2|*[22(%=;;;;;;;;;;;;;;;,/22|$=;;;;;;;;<22<%=;;;;$.... ", " ....+=;;;;;~22^$%]~$|22>%=;;;;;;;;;;;;;;;;'||^%=;;;;;;;,[22^$=;;;;;+.... ", " ....%;;;;;,[22-%==='22|*==;;;;;;;;;;;;;;;;;;=%=;;;;;;;;'22|*%=;;;;;=+... ", " ....$;;;;;;!22|$%;,;^22<$=;;;;;;;;;;;;;;;;;;===;;;;;;;;;^22|$==;;;;;;%.... ", " ....@;;;;;'](22[^]=;;<22^$==!~]/~=;!]]~;;;;{'~]==;;;;~<<]<22($=;;;;;;;;@.... ", " ....@;;;;;;]<|22|[<%;!|22-%'[2222*=;/22(%;~|222(=;;;!<2|^[222>$=;;;;;;;;;+.... ", " ....=;;;;;;;,[22>$===~22|$==,[22[%=;[22]%=,!|22]%=;![2|*%]22|*==;;;;;;;;;%+... ", " ....@;;;;;;;;!|22*$=;;/22($=;,[22/$='222*%=;!|22-%;;<22>%=]22[$%;;;;;;;;;;;=.... ", " ....@;;;;;;;;;~22[*==;;[22>%=;'22|-%,^22[$=;,~22[$%;]22<$%=(22/$=;;;;;;;;;;;;@.... ", " ....+;;;;;;;;;;^22<$=;;!222*$=;]22[$==[22/$=;;(22/$=![22]$=;|22-%=;;;;;;;;;;;;;+... ", " ....;;;;;;;;;;;<22^%=;;]22[$=;;(22/$=~222-%=;;[22>%=]22|$%;~22|$==;;;;;;;;;;;;;;.... ", " ....%;;;;;;;;;;;|22-%=;;(22/$=;{|22-%=<22|$%;;'22|*%;<22<$==(22<$=;=;;;;;;;;;;;;;$.... ", " ....+;;;;;;;;;;;!222$==;,|22>%=;~22|$=]|22($=;;]22[$%,|22^%=!|22^$=;;;;;;;;;;;;;;;;@.... ", " ....+=;;;;;;;;;;;~22[$%;;'22|*-/;]22($*[<22^$^=;(22/$(-222>$=(222->~;;;;;;;;;;;;;;;;=+.... ", " ...+;;;;;;;;;;;;;(22/$=;;]22|*<'=(22/*[~[22>(]=;|22>//=|22/$^(|2|-[%=;;;;;;;;;;;;;;;;=.... ", " ....$;;;;;;;;;;;;;<22>%=;;]222|>==(222|^=|22|<%=;|222<%=(222|<-222|-==;;;;;;;;;;;;;;;;;$.... ", " ....@;;;;;;;;;;;;;!|2|$=;;;'[2[>%=;'|2[]%=/2|/$==;^2|(*%=!(2|($%<2[-%=;;;;;;;;;;;;;;;;;;;@.... ", "....@;;;;;;;;;;;;;;'22($%;;;;=%%==;;;=%%%==;=%%==;;;=%===;;==%%====%%=,;;;;;;;;;;;;;;;;;;;;+... ", "...+=;;;;;;;;;;!'=,]22-%=;;;;;;==;=;;;===;=;;===;;;;;===;;;;=;=,;;,=;=;;;;;;;;;;;;;;;;;;;;;=....", "...+;;;;;;;;;;;[2^=<2<$==;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+...", "...+;;;;;;;;;;;22('2|*%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+...", "...+;;;;;;;;;;;^|<[[-%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+...", "...+;;;;;;;;;;;;*~*%===;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@...", "...+;;;;;;;;;;;;;====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+...", "....$=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=$....", " .....++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++..... ", " ............................................................................................. ", " ............................................................................................ ", " ...................................................................................... "}; fltk-1.4.3/fluid/icons/fluid-128.png0000644000175000017500000002370315004135251017151 0ustar albrechtalbrechtPNG  IHDR9Q]bKGD3 pHYs  tIME 3=[tEXtComment̖ IDATxwxTEw[v7M#zGH^ XyWQ{ "A@j ;sn I <ݻsΜ99gf΁rEQ@tET͛I]!,i >,i /+pۦ \R \~].ө *J4nhD"d*~ߛB${(J Z\'6b@W>ue>`J+$ !9fdu$A~A 1qoL*Cx o]AT$9Pdj 5.V6_@VNgT"N%K<%A!pPyt:P\VЦMZK.9 "8R[PJ = T4QdD Yffe@Yd!&-þ$ AYf/Or! Dwܷsd!Z$J`f(Q⛇bODZ2#)=#L$%EMy a mS((]rBA6BgYYD̩93UQsJgJR heXPR[p@y十= F2C)S-{[Q:thQhU]0K70|>)i+_bE`o a"꠾ 6&tJ(|^s;0)?A8O~S\þrdj} HzlyV[~`$!00ZlF],ƣGc҆C:m&\E3Xmȍy1j/|42QԽ$ׯ?ר}V^Ɋ&(;OZ޻kbFK0t,Xld9hWi(\ѕޖB y(f @YY7`rmA뚐5 UDX1CjEi%jZUJԈP@?(Wk׮nbtU]n먈lٰ2/YY1)t,n4/LK+|o-V,2_6_ژ60Q7DMz$ p:~f~72}_.&)|6GGGKK(t`tMR^7&96n _ngx4CU0oU< k{f}6 FJC?&\^s{Rq!3 Rp4C`ν EJSmy䝡xͧ~-:8UGȿ?LZz1!yh^\«3<+m|Tn = }9.[`gݹ ugl<Ԉg{=;tWA[=-hwOUcOG CrU+* N ;AoWk'vB5#&I(w OIVf cȃZ*:&&+R^R\.ZucINN|'g @#Ʉl0.!Wy,T Pn^ZCmB3]"11C+䕕_y)*; (:~gegᏀA. 9 z2aC@EP@-f͚&)hÏ75SiR{*3Ln  +xe*)333Ei`РAMv',D!+Eֻ\ӃO+\mjIr_Ç]Q=@[o)i4pk6++ !r&lQVpBDL٣qƾla= ]nko6z8OI SaXXf :tXo[%f#Y:Dlݺ56l(uJcepb n=F3twUki>.=\?9t@ w: ?֍Fr!!]mgͲB@Zᕘ;'NB Y*cH`\3IJyr~X'R9O< gj٥`"_: ǟiqxݑ/tme\Ab_4T `"x\=~zMz"k>kΕ|&ž.<laYd愱s9 Wvڗ \YW.n'aze* 5cuc1"i 5yவpYl?N9sN4ߕu!:( z<@#M鸲OӹԄl<>/FuI鐛Njo@Ъ^ gm&?L+̓&9U҇IBȺ <ѫ3_^:rQotLAL%vX wxۼMñs'6mhuE `/ .E@>N 0~3K;w;y}n2^NUP F~Zs)7`ͅ䌳ŕ#uNQυ64UAb% V B@  CBʫ P&Rܶm*MG,0 !7J0>|pTX*TL}H*RTZ$yiYehd^pJ:[΋ބݧwxLOgA'Uᒨ͕=F.`E(k,+.#O8!?^Wؒ`\fƐ({ȀJT2.?pڵ>;(iq`0*gX.+NQQҐ?dff"`\eիepE޽/zRv=Ç3dLx:vF_?r>#@oߞkY٫i7M1>< m#9?ygJ .t #@Hs] V^Mba:hCҼysٜG;IVc|[''BPID@vVvJ/C&u.f%}Th䄨]:78`Mi(4psg+m-ܣwpF CK?z'3oWAQ483S{+ 8PB.O{鼖".y; ߱_^<hy%msoe(ȡq !3K* ^!/K>fͦFw k%wOAr8/~?ρG#XS62 P=bj?~TXi8'[qN$8]%0C_9I2'%dcPBFG~d癟#+Ov`\.CC@/1-8 o_iI3l5QfC tlM!,ҝp'=rjZt_:9RDx$~EA@ՕS&z#b؉?f|鋞`e)D 1*y֑+y=5L"wEbaZ2oFCx]Nmh X)Y u |^R,:L?o!ӗ7tAktzFuxW  k _!dU_ y&r`5Rfvl.v=А@-sR֌9,1U0 _y0 !^: W `O4&j2 ބ;ظ(f\$Kֵ<粀ʽm_a[߂lbeXfy-y" @ˠ&)caH$i=0Z1* s,#5|V d<|.5yc\<"EL(LۋCw.*6fKzL$^]'um&='QTtL#g;'yj|quĂ!ߨ=!ۯEz] iդ$VCI W~i.<} XbFh0pѳ*iܯF:Ǹ;P0O Fg~t,e  ]^))ڪ_'I)sȃ:*a:nh%`jRλw,C#xɬg`K]"4rvsc%2Ȃ+DCC; y. iK =QF>!!5`Άt1""接=/_d@LVooD?h&F^鎟Ix]k6T*% /{>-ZЮ];FR||8͛IOO'--?~*<-LHN'HIUBw.F.[.AkÇ9"s FwD{ςf~_&#ecǎ:]gh]v/$SEL'g?)OG XM a Hazl|?쑻:KTt@$Cn[a=Í ;ɪ)܂F +[AB܂f3XF*H$@%PEUJ `~5 !>›%- d2y!JC/(Y!OJ8`Sn/ 26-h2֭[$w?HB'23wVMl"aBwyگ]0+r!mp"c;WMfE?22^UETn/t{O' `yiߕFa "$[hQ ֭[cFUC+ZеkW+HMM )_t(֮]+*<(Zl~&HT*8;ƌJD9OM`F+ k-UmS-PMt<gC:-%.w^ڶm˩SJZ U#NtҥKC:>IA%!d=Y2"Xd  d hdݺuO|gW{>u0]vE"@*( }޴X,ر/_0/l?!V o>`ޅT0_/,s-+_+?[|/4!n-YF@JB}!$ 4H\(ꫯ;ZŮ>s<m,޽e@Ft0hs;v_=/Ŕ~rmcn6݋F'|۩A |wu:oVȃ@f0B+Ӑ ?osX45[/H ` ózͮjعs'ѡاCm<TvO])׌<L,bI| . d- #vA={67\ Pya1xKMt֯_Oǎ5H+;o]P[ 8FfSfɭl]Qس4np%< Vԫq᎟!} QABykˀ@rI3Y[9\hcsgmWxIPԶ7.6}z+gX -􊛾FW!|^8 4>Z7qT#m´GQ=*ĘԏOiYs;֓T guXQԋ.wM屮38} Rj{_h..yGq:ԍ9(4MZ#F]SB]5~ڟoP_4wW0A{s=?:K/p'M78H,&4aL?`#ٽ,y:O&3m _%Cq|z.`YnabZs.8pj='C ErSgl[RƐ= Û:8o$ݚn +] 6Ϡ7yV=r4VE  6BـF.M3B hUsL ҈/ApyoQ?Qӹ Xpb9|u5[--> SD&|4^&sAh]yA2È=FmOjQ^?#3 ̓cR;wǑ}=f,ͣsnz2;XQɲq49Wh=nXMU'gҏrpO'Ef瓭#~ 0wv&-1rz10`zQ{hq;iYs5w ):?+V8AZ"ҫC<Îcмv J>?\ fu/K\3FN X?K6u ~nIsDnq? z쾪 ǐn{7XUT4 #;r[K5X@>ހKݯ('SrԴ;FON27yYbSvs]~;nԔ~(\ jJH^ w]>S楯{h DMk/ۨӃK!ɾe# VY{';<uaZe6-;s,]9ݏ z儇YRT lL'f %#db\3E,Hn[\` Ηż~`fuFk4J.wå0EHKсp3,Er6l"/ fPttOZ5-LuJVŷ^O̎y~K* fl>H"tl_;Oӟ[H fs$Ǡx}ixgiIph/r2szW)  S)Bҹrn<~qq_YH:=3al4fc33SrՏjm8M>fc]п2.~ P2){aQinQ;5Ty%X N!2ߪ9F~exx2[y!OR@nN7.'3vwxݓb:r4 צJb\iԣo~݅Ù5d_4 gWw17z}˥|=iJlh9ϏA2߻#=&f}mI7d$.)ih[.EBkYqG_n_k:$+[j|ՁVSܷEJfv7>yE:KmZޖ7gHGi%RvYmjJd64$Ee)WBUO{:ǒ?0/,wϙ&uWQkOO48}D+^F35_{'+ x>L՜GqKLN\RLEǦUi N 7h .-dC*z94)N.f =0~`ԆjLʊCf{CK{H;͚]M:r ,%)+Ν`dBc5vl\j`1ښl=Ʃ31X~֭{F咄9ڿjȂv;Nό撥XLYξQCl5ibX j0NsuzSoe? 2ADGO`0nJj&\ꥮ nEzҙrSczL/2{qP#MG~cD [-/`X=כrJih(\(Ȓ^G~]-St.E.vG5Z{ө}|w)~]N׊妼?1ҟ=nW}zLnOެ]StArfٔHY$x֐5{ݳ2u u/jd9S:}fWB+n7oe$Jr.vnl.,# "#gΪA6CEf( 4)SҲŕ+;;h 2VɮR/ȃtj:?KAA^n1U* /ԅ3h>Yֶyϳ⦓ vTAòq ڑEyВ{;VULP% h ri|JMx2|UL-uHIENDB`fltk-1.4.3/fluid/icons/fluid-48.png0000644000175000017500000000531315004135251017067 0ustar albrechtalbrechtPNG  IHDR00 bKGD3 pHYs  tIME 4a/UtEXtComment̖ DIDAThՙyXUe?^.pAE DB0)MRkrl!0kHs4l rtʱ2vsdܲ.ٸ!f";7܅q}sy=Um 0&M$m{9|a)My2#M`d?2/W,"SNmɕTWW.Cc9EovapnNzq7Es=Rt>6U#"`iS#ͱ3rrr:96 &I9vX1DNZ&D%n*5B,ݗJߞEj^LW|WxI(a$KousvtDݿ:iJKE`l@>W &HGvl:%g]_a' !DFc* V_')-%}2&{}ɦ3F9QƾfȈw6JºOce,BZ< [&IQUk/_dVlʲ ޾JVw]6uVl?(]e"gΜ)@?GfHJJ J:Hvz*GI\ILL.d_4׊ ;vtt˷¬,i /yvKi- vFV^j()=yK5'<̫4eZtORX_etac8_i]pr$ :g|<1p[ s=0?'Gّqs˔C8{^5<})p֦}L?:Ζ=+S@2pR ~P]dgKEGyϮGr!͂Q ::\Uki Z͘gCŅE#:PTC!DfWC;dOOqqq-#n41-$>}^E;v/Ȁw\Se(66 סDhW]*f4E>ltT_zLXذ7Rm>my2e:KmHK毴1)0Ct.F^2b?K|7`^%P;#;#t+{T]u-T9@Y/Q*;if!Mb$fʒOʥ:q_DgE!J.K?-MA L;h7[yH1xV%sϭ\wgS_ᖐjnk`3sPif6/7+]٪P^WiR4~OR5k|b~-6UhyRq mqNYʑK %BUEɹYGu½sC5]@ f8JFQƐ!Ch4/^۷sQa>n 3DfIY)RkhSRRl! ʁ~hԐ_dr֜nnn _ioi!oGZ@i\ې\pm8!IӍfU_ M\}X@C^q)Slޏc(+/[Φ$kv~`\$==d>Zt?)pjp)))i2C?0)//6J!w+ -j6?Bj  D2,V\_gޭZflվ#1 &L喋2m`IF$}_XK޽m_#;uc"wf0;$ Ȁ-^ў#xv0x`'rT'""F=qQ'(E6A`m2{"|~, }c{&`׋[\6ZFM|YLYߗ]l88Ͼbϩ{TI( /U1.Z)Id5+` Tj\KI; 'gWPk>㖩-8_hQ{م{6lXTƬre]sv8myvp&%T=sJ38CŹ (όd2b8t'NV'=h>IENDB`fltk-1.4.3/fluid/icons/fluid-32i.png0000644000175000017500000000070215004135251017226 0ustar albrechtalbrechtPNG  IHDR Tg0PLTE F~fbno/@WwquH |E(tRNS@fbKGDH pHYs  tIME | IDAT(c`"e(޽G&wwU,^&& {$ޭ{bS+d==z; xЄwKÔjxt;PS Ї*266N6N7(o||qeH@mfflml֡lu{NơF =m\uh:hl,TF:퇌?u1?vbwLʼnc =ەr}E13|TBxGQ&lTIENDB`fltk-1.4.3/fluid/icons/fluid.xcf_gz0000644000175000017500000005373215004135251017342 0ustar albrechtalbrechtZ xEyIdx $$$QPP 0 dyKȠFbE (Ey* ",t=uU?ut9z&3+gkNz+#+th.h$ \* __-_e/'S'5|P c 4!'jJԊ("Ox ٻf:7,=zr<:"YW9,zvQ_%/OYt}M7Zc5nx\ 7LYt#MLnD#1j ʃ4 c:4;k̠go%ΰ%]ڠfKMnaz;˃N2}Xjy\ŘxܩzMGW;}x\Zc:|ZGMYNi+!}QB˚+%gWI/w 풑".yS\=zOLtShTx5sggy3]IemH Y|t)p[_-$uڏ].*mm"K]0Fwsc+;R-68"lNވ'i%(!:O3&>7mIg. yKzr2C>E?':Msιܥ5*7;$:Dt<,E#Efs2 sYkNlz.Y6Զ6L'+~'Ɋ?"+pdA+pI '+<"+pdٸaJJ\0Qb)LZeT e=b/vY2S˸e,Cy(WDH*K`j"j"6AKIAɦ>{|I zXdzEd$w?fԗY}h2꓀LA &TWFT)b}YM}U%jSaJt^ne[ ï7BGuS9ݽY!OEcrS9!bEvANN}> =z,VݶPt)U z3;WbP Yjmu.\ FLSdȳyKF^y$0}g"ŗ0姞粖7#(~(FI@y;"F @9qئ B)rallF'g4~O'|n{ʤ^Zu߮KFўe1uuѝz1֘'dяdvciO|JZ7m'zb?Y/EY4ӧ2ltjZ}Nfi@nUP"LYЏ4$ b>d85]m@nUK=r_%')Q*qx)*xEkg;Sx#.V^M80W+i-+8wuK)i ўȺ[_>, Ȧj9Wqv5Ep/!->Z}~QQ&o:5vL i.갱{`L˱K\BW1qhVPI Sl%ăخ_w- tELWd!2Й+F]Iz0[ DC*:P2\1sbv")m+Rڀ ĐzI Wǐ u(﩯nL$M<*+~mK?Rƙ*]vu5НK_N/S*p\4&TD'#$у5"Z}tIj稓#d+m}EޜiY=wsu j Fhu%Ũ24E^EJ+m|d^U5 ٨h`CCCC&٨c`aC3t yٽǘ7޵5!\+uQXBc,jH,ΓcOΌ¬iCOe8tg+h?xg) d$Kc=yYA\egyWJrA{̬9l1=[=6i´L{0?5-?-+O Ǖ]G_KL?__1ו(99v)fچç?\6JI4ڳ@+qxEpIjo겷S1jǔ ){s;]"!rb"(}'oȏM̅T3){K^r\Ut0XO֖) SK9}M@-#~70f Ҫd@' h2l6 w` :JguK~UK\j6v5U6aS3LA /;HEC %Я*p U(n.ODd+p3)vE#d=wNNA T3K5BWVpkiR6`|2ut?&m!]#)Pr1}Ju5!P~#TP 8U3xHU7s6J鞏jNbqӟZiSvp;n17MN8Lz.R[)g~\}LZ >a @,,\-jO_"d- e[ qjt藂HW4K(N?-P?=a(S Q,go; 2!PN-_C}Y+``Fnf$0$̇īN' h<)71ADTZ(~Rhl3|kz\,#hIsfO9)s[.w/UZۧUF' @ߡN&K[ _3YTc/ZFRGcu'`T-"%L_ 4o4Sj04p۠/6!vՃT3jP4lcnĒz:} eM(4$&I V&jSZuByRĻ6D/~r#r*kNTJ \0OkU<C+C7.Ȉ$:B[-=dsPQ2MV\(E;hXDSa"prPj+J (Еk,-!B4X}-52 t EGz v |% BѹȂhZuk3MyQ C/O*y>ApH,b k|Gj9 1Uks~8Xwk"9s=bBhX4^$Tn;Yx-td'Š:iE]MC8;FX'T`_ Yx JUEDOj PEI v!bYF.\ &A%ޥU Iiף^is= FHƒvZ+wvL)~ ΄N"EG#4~`m V3W'@{a/'Q~~noA8 cez:zy^b!eYu!fWmJ ]NQ:0) .mcyT߀qWp1F#O4TU~5%zKf8TTu=Jxc(&s/Wf 펲SLx)TnixQ/ܙiFK%>$/wfirg_ ^t xW'W '&z.2_cl.<@AZb',dIJ-V!;6Ē,,LG+l;"EQUNB+v8;Ӭe붱m[lM8)&,"QDEikb h9.!Nѽs-5m֢Uv\mZ+bn>gCG5!{'vrc׸Dw^=ؗ oܦkz2S7WS}zjkG2w蝚Z(FZj`r3YtG.2=uښGV'5PVY{Gv23]Mmf&mSy/ޯXOK=x$MC>8zdjcmM]z:z=W+ʯ7B)-gKjn^9&~YKK^g?꽃7>;anJ6B-:sWk+yXiiS4 9qڻPIr[CM55 }k߮pU;|Z:Afl9[Zu7&Z_CM kЌ_ aogZq6_=,t! j(߿{J{k3tkue>REja9{' to%M~ڒ3Cjo_x܇vK\%FvAɓןwst6Px-c>6W EY7_;/{@{B;Ejqx/K4𓲺ꛇߟا,]c1ڿιP:jXD( A}E<aX^Ƭ,][_q$F}}oWU1DKĽ+>Y1uHN8z v{װ8PU͐7O|0{TZr\RO8g*hAZe ե2OFp1KwtA>b٣ ]sނ%{9Å=FC I;@XL f1x:Y\LujDKŚ|#4{-JWQWhTWcU  8&'Df~aPD ~M[GWO_E=-tJi47SWS׾B ԜyP.5021XYI,L tԾ34137736Ħ#:[UKc#csHN# G<&Dj/!>Kl=#wu43wnK70$]P?D+CAkofo"68o|)@73ohǸb8:yGt?tLnђEa2[xIN*X;tO;yFٽ;xcݫٹw06oܸdR d3KGyB -%5561QlMkJ;Pײu=kΣ\>omnzԣw= S:|zK~!u 1b~OK>~|6Vw; 112G|ɫn\ط*tZ|t^ÚⓛfDH]#Opf݋/ڣ}RZy&%ۛ@M9ɃckrCvޝuRZBX@sP=xK8ldWc`+ݨd|)ᚮCP oW!vŇ7oaǏ+.;8ALJikjC1qm}9nF{*\jգJid6ޝ3B| bDu'Q<dnl0L_;,ꆚVI tq߬:P0gJj`w37zER'5`!s8۹vM}e P` hxݓuY}往a?^ <!PR졣m LIMRO (0rkU _KkO o|~my!IWo33 |jn_FkOCU nNr>gR,/s +Nn[| ѿeU1fx;NJj|@;cmhPafc֔]18jyCy[ϗV_ݛ?"1ǿ}IYXO5k`G[Pˆתf/Z]z~"KH@X!s.yJx2c| L샒,cM˯]y;2ʪ w\extlA1.R3ccKk|}q37*y,~9):vϘj_Q;a核PogK /U|o~]ڵ2']wqFO xq]=\bʐ~I=z]C6p1'qk^qݝ &dwڦ3 ԯW#Oݫ2t0;-1nİf,xo3;O5|:5J*ܣwՇnT?ʢ-UMɅL,rVu}WJ ppϾf%C%vwK><]\Yyee>cվ˥UwY={DR~6]YSvV (=;EDv8uޓVtL3eԼ-G޹}趥Su qZX:'np`_Є9_˚aɳ'n[9{TJ׎S'o=t+s532ɘ㌶Ň;:z$}ni]Brټy͒C؛aq1|_һXXzD& ]4dbc3݃;eTZ(o\ ພf Fjj``j-}gX=c¼ͥ.MM1>ϰؤ8т&uwf"u l.\,537t pA$'(R;JaKD,sq23b`Fbk{'JaQU3-m܃oh dPOi?@E8DFmxw*hȏahW_鲛}I"QsK+kk/|XX9=}|}<]lw`X.CP c$q g`#R#=F#:lҬK.VL/w0E,JFYp\꘼6Ɏ gWl/}lݔ!h?vdJ! CkZ>e/N 6p>3=l@ĺ8TZOPμ[/=/=YٝFRSBF(G!ܨ~lPb8lAT50w NDв>HjB%Y{4PWr D= 7OV>v~:`V򐰈v{d?v!!-tՑ»k$q-W>N]}D+[g+{J=S#UF~5zBҭ'nf,2pܕ6|lnY7s-f$NASlіU9aΚW+|&`LZ<<{aQΐ9?)|8{k'bҧq˧ۥȅ.W +32yŮN[7;[dPx<pM(t˗O|xLRG@猹;.׳QU[]tp}}c0W(sAMI < %!/nR#pKY7-%Qc#1dO43w߻{ɈUK2{bo*"U99wbsky;/߯)D<).~pr s;CzHK;evwچw )oE]- i}Ü-/]qSo\1:ЊC\.>s'pC=%Ȕ`<). [.WĤ {cmzNr P3;H;WNw9iã݋8c$y`8?I>yT~qܬ &HbrGP-Qb'=8G`1Kv_xEC-:{ؙvɩq _v+gd'fP;lY>gĜYK^V]~Ԏe\ nݹ~֕Q#澷䧷o *ջ=v]M+:~tE8tn\9/'O|.əSް~7~` Gf1 }`d9ӧ9N$Q}(=CB~}{F8Z.8,]d?$,Tbc*_mޓ'/Ō6*ty|S'(Ν:,WHņGogCɞ4`?d@0M2lʒͻ?0|p:)(9f];/6~RM[7/ƺc%ܬ*3O)'62jzޜ)Ǎ>Ol23w NN6tȠJ\X8Vڭ[B|Lw;~dZf6.^ yĄ"HNŽt#3+agcenL'"/i7HF8hvfh 4!RTUdXE/Z8Q:Kh+1wÓ^)h(jGW4sAj"Q>~ xFv3;Og'0$1X6O(/5( 3,q)cGv`z! YO}YM]] dfB26 e O'd?.K :+#dւ, U_OKOm[.*pWno(A~O4V xu^4qި IDŽ#mݛc!\Op[G ba,k[iʉ4n+e`A1D&[#5NA+M0 lqA%.pN,dq=Rڿw!J%6g"Fb\V!TQH@D S#l90iE& A F6 9tI PH@N΀/ꌈꌉ7LPH@xΔxΌx;,,+$($ d".&ΨpB pa]u38v,Njpug18^ pD؆_%qk"QY}u)P X}u:]@@~+QĄ‡VCr`₹MdF+ PH ކRҚב VZlkKkZi mӿ[spiK@h@CZ [J&z1_f*ҿZoVM1X+z/VT+y b 8G[LqͧWSB`K-EF F_80_z+f~t0&+ݎBV{oүNڬEhq9 Sº_S2uS2aǘ)@ 13cX/BCk< mW'qk!UO)WWa g,*e듫4=a_.D+_YンrVG1ދ@yL+ +izz_V vv =AJAw<=33x<<6=> 31565x;mBCB`K$'Ó<*X(j3DWU\5RTC! 1\@"&.W*j!6` tpm Qلr@Qb }"pE q9B?\ $(ʺ޸UK4#K%sxE;W hkDkevAB :6^Ytms@f!H5?Dx-0Ƃ37`hJ;xgwV?cuh=X9 Dk(oŒV)Wκ_?M϶ӂBmЉ5f j26F {`M^7bbzEϼG;UK¾j:?IU1blO؄a)p'V NOqplf왿^)9F+_ 6lk JXƿ& 5TCl^3s\SdYߔS! k:L҇'>](Y:8 }P߰CȧT1P &5Is[<`% k&it@-jDat |n ;Bo̳wsCJsp߳rpYDspDM1RpE,}Iӂe↰\hW}EspE17Y X n4K]d\gܡ^dL_4w};y"ׁ\?gS?K%pb{ﱇ#V ΎdG61;M,l 񁭁_ -(l3FZRcUE2W?\Ptyk'Mo\M\_`ם6>+Xi?[2{{_.l>MU8ZeǂWA g@ 7Z* b֣y1SSO7 Q%$D  $~@ I פ{33]ZqfrP{{6M{]aK%d)BV[;B}׿$de!ٞLȮ6A937U_uĞed;a򴙳(ҽOy HFqV-i3c*gI 9q@8\8 zp(&!`9-ؒf g9?Fmp-p^e_F^@[-[ V˶(kD-D(KE$xD;9-׀.`nk/BVɛ5s cGfg313qSea}wZsyӒ皦fDl3g&k"] }NA,QLzCsZqM޾ZKןW޻v][,__66:eh-Ķeh-[棵D^Mh{VsZqM޾~Im׫=b#|T*,@!slP #(QҙF 4A#Jt,QYҝ3JPəҋ3JQҗ3J P2ӣJ tQ)tPiS%JPsZ ޶GlE+* 8`"@tF>4RD JgL@SkJ4D JW̝nPEsD JLDD Jo>}mD J?LbUe D9f Q*Q2LbmVC8~j4NLNc J)6Sq%+l18'E6S Yw8~B41#0'$S|^'I㢉1T/c8~ @pB<GoqhwrN"qh$[' ],Dl~`S5/ KH0KZ[H lDkF^Lǐ,Bk@g|i13 fW+ڢpkt_@k pTJȿX@% 6~QW-Gk :ʎ@k(,ŏ4Z{*Bc :C: ,gI M*A(DqTPR%JPjr!QQ%JP'8]Gsz\U>J/UJc&U)J3;UJKNF(AiŹҚsFsJJ[x9Ai(AI#O<4F,yX䉥4eȓZO;3qBQl+6E%KЏ)R%JP?P|`AT:-S2z8(A:v䋆/U/܋*Q D3PEwD J {*-1Y/Jp(Q 5fE)&A8𲂒QQG4ƥ" X<ʧ4.xTH=ZϘ dF*d6f6Qڪ(HFmJjBflf#* dF*d6f6Qڪ(HFmJjBfl聡@a:z`8N*Q2SAeǓXvW4Ѡn@(1bJ(A? ('84D87 & K)C9>7shᜐ "Þ$℞@⣸&E,!Q3%Qp } t\2]x[lհ: Vm&?%6C}MGo'aZӏr(FЛc> @L8eOhA9:ՂWt$1D D.:D @ :qFp$Ď(/#؃@#P3N {RI@D@qX%pOW{BCbVSfu,/da*cXaG7-ªZz YE/糡0PX1qe:w7V~%S~U! ;*K;U`UPaU`Ƭ;WV~3tb2NJJDqJ3/8 V~n'C PuAU! )#e,2LTD ƪFR 3P>E` JFkɩXB KmìuZYk4;S͆0ouR hl' Zxގް?߉F㛭 tU*:4hUFLƿ4a*Qe<@E%YC&1K9$*)b2qX!QIdICRJ%Lb2rHTR.8dq!5 9$XZTZ'6$6F'q 9bۚxIx8Gq3JQW#xpcپy𳚤s)X:UbМY (\GZ>e(3,b1|QIacSFJo #̧1FXa>ḛ1#-|\5 sYB9HUq4s[0fi@W `XEDDQdžD-ɯeޥ!=M`B=Zs#.&#>@ d3#2̀qTRB^̞.fG%5!3{632jvTR2g3R Ze[3ytWF+sf蠇? mx :Zo ~ 5:%<ylGTp6]P CwðE y<#3;3B>\I{3B9gJȇ* y/*0SF9gC$Isb#2ȅLJB+D`9`g1 63` %3 6+a &b!O"I?#T׊Tv2fD${H4*! e"I"sC"h FPb%h2F!nS]ISlZB6Cs.`aF67/a<)%#Qyq%֑?% { 6,`}:hO+A:9ggs~D=*6p+V0o:KXGPWM_p1ԑhDQ|¿0d `O2¦MaӆV3:Yp nV7WmZ8HV7ֳTsig Jyi`` e:CZa0U ?Vݕh =zCPfqfo&sd8sўwG }(T'BkaMݾqr!GaFYr\)Dؠ%jƺ\2 `m{W K7)79y_{#P^}fl9_(A9Fl(Zb[n:,즓M~)~3~PPPN:t/x߿+[߿듚'lX<%#!Њl;eF/xg?֧;.@v_]2H?!ZZAfGpTNs>9F7 8Гn AWS fm]ߕ\pRMXMK!R6KX 4Tl٬IlM)2X 6e^&%m*dM٬I:@I{ YoS6eN>PަB۔-oߴlk ^- 7\ 8*] &tQҽ$^J22S) ҽ zߕ]&<3gra &Kgtfgy5ZJXgN_֙#HYgN:)`9YgN%̩Vc9kXgN,i2c9UYg2Ё2fvŪl(# a/볻f>@ϡFǖ"6Y7?N4B v/t "83'-4QcL7_SnpݼN ;tCnFp5-ѭ%µ]N#YIggf#ydlbtDO!ɓFHT=l$O6#SR1 tnzKݴ .k ;51FJpiޜ?4? ƠB(fIO Y,'e,? Y,d,= J:e'YvRFd!f'q:o( Ӄ* ӆi -Y4,`;{Z@ҁ"K\Ta,ͺa]]#Y*ƕ?b=X}Y& M֯D(| /زL#uJhR$%B"$DlUT-`m[( [@C[0Z@9m Y0-?mMh -mi -'m%tЍmίwO~j5|utQxO9TXf4aQNBOi4: bN oa-[ oa1RD)πcޕkY zCZhhh@V{_3dCG] Kn0Οu0 !9jq@#ԮM]{R ,}m܇CB*<` SBfR}{=9?_L ZM ؠ "IglE}lE lE7D [r-iYW$hYγYͳW<{4a%y"XfU>xCykfvo߾yʹoi9h2l3el8(),d83LJ7 f8S怃B3Δ9ࠤxl3el8(),d83LJ7 YZ626n6s>9: &Ig3$5$]lN_d)Sޚ6rf% jlH69V93ٌlH263rf1 Ūlf<639L93ـk*lfL639P93YEՋ*lflB<ҤPP͢0*#DjUAᢱPҚ hEblV.# $fiݺk^DQ01󘹞w70w,e&/>t8]'@=4JNz{hÏRU5?6S;XI*UPuMwTc%T=@=4JRz{hÏRUhp_M,)j7<}JRs8{E.Ny>^xVngAs W3>'ME+4iH>4X T&;Oئd^ќ s?n  ܺT}hpÊV>tJ H/fV??7ǛmyLy F A\fK3oUW(g>}SҖ$@@Y<3/zTVnu\vđK&5ܼn 2)=. cZxN/v8-^IENDB`fltk-1.4.3/fluid/icons/fluid-32.png0000644000175000017500000000306315004135251017060 0ustar albrechtalbrechtPNG  IHDR }JbbKGD3 pHYs  tIME 4'OtEXtComment̖IDATXýkpol.$,ę@!c)LS,tGZZiR/4t[i8Z J0Gd2X$!41ʲ$$dwsYv.!Ɇn=9ss΁hxH g7qڅjأ"BmJ7o EwL&;,0L0ƒݏe6HD/<Ot%C{{?ܹ307k31ӓ%k'ty39^9$ e|}Xr:*//kغN?^~ # KWzhIiEaaytJ>I~wng}jNf*R{Тb,ݘޯ8 $OGv3? rl}^x^atN'mψ!HNSUUU)C`saM{5ObP[[~ )7 Un`-Ϟ=qb3fHH=R0 k^ݻW1xt潾 vo<5iqsA^>8 9Ɲ2?ydf3qw7pw2`(T|X_~A篤6=w`XӢw<qŗ+pK_*wLwQ{r^ƽYǁS44>g dv0xMeτP s,d&gmv;/-| iS8x*H R+<&>ǀ5kˆu~%GnK0n$Z`T=Ox?X x~Dop ZɊ}p ¤^Ff ׀u' %%%u 8ʗۥoI]*##C@-9ށCz ]-GC.svZgwXfSCCCD}k6˼=oE? <U06"s&xLƧs\>Q 6&6îB՛_n+=<ِgYyV&';R 2vĸ.tA>Hece,2^XJ]$t+V8D8oSvlSKڝ$ۓN%V=OBuMuzKR5JgMm.6ɔ >UX=rYXh'.c!vk2c,%Xf3(ʫLdr3lLӒn%!f3y/,᫶>)&0zGę]6B-@&_LoujʫIENDB`fltk-1.4.3/fluid/undo.cxx0000644000175000017500000001646715004135251015417 0ustar albrechtalbrecht// // FLUID undo support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "undo.h" #include "fluid.h" #include "file.h" #include "Fl_Type.h" #include "Fl_Widget_Type.h" #include "widget_browser.h" #include #include #include #include #include #include "fluid_filename.h" #include "../src/flstring.h" #if defined(_WIN32) && !defined(__CYGWIN__) # include # include # define getpid (int)GetCurrentProcessId #else # include #endif // _WIN32 && !__CYGWIN__ // // This file implements an undo system using temporary files; ideally // we'd like to do this in memory, however the current data structures // and design aren't well-suited... Instead, we save and restore // checkpoint files. // extern Fl_Window* the_panel; int undo_current = 0; // Current undo level in buffer int undo_last = 0; // Last undo level in buffer int undo_max = 0; // Maximum undo level used int undo_save = -1; // Last undo level that was saved static int undo_paused = 0; // Undo checkpointing paused? int undo_once_type = 0; // Suspend further undos of the same type // Return the undo filename. // The filename is constructed in a static internal buffer and // this buffer is overwritten by every call of this function. // The return value is a pointer to this internal string. static char *undo_filename(int level) { static char undo_path[FL_PATH_MAX] = ""; // Undo path static unsigned int undo_path_len = 0; // length w/o filename if (!undo_path_len) { fluid_prefs.getUserdataPath(undo_path, sizeof(undo_path)); undo_path_len = (unsigned int)strlen(undo_path); } // append filename: "undo_PID_LEVEL.fl" snprintf(undo_path + undo_path_len, sizeof(undo_path) - undo_path_len - 1, "undo_%d_%d.fl", getpid(), level); return undo_path; } // Redo menu callback void redo_cb(Fl_Widget *, void *) { // int undo_item = main_menubar->find_index(undo_cb); // int redo_item = main_menubar->find_index(redo_cb); undo_once_type = 0; if (undo_current >= undo_last) { fl_beep(); return; } undo_suspend(); if (widget_browser) { widget_browser->save_scroll_position(); widget_browser->new_list(); } int reload_panel = (the_panel && the_panel->visible()); if (!read_file(undo_filename(undo_current + 1), 0)) { // Unable to read checkpoint file, don't redo... widget_browser->rebuild(); g_project.update_settings_dialog(); undo_resume(); return; } if (reload_panel) { for (Fl_Type *t = Fl_Type::first; t; t=t->next) { if (t->is_widget() && t->selected) t->open(); } } if (widget_browser) widget_browser->restore_scroll_position(); undo_current ++; // Update modified flag... set_modflag(undo_current != undo_save); widget_browser->rebuild(); g_project.update_settings_dialog(); // Update undo/redo menu items... // if (undo_current >= undo_last) Main_Menu[redo_item].deactivate(); // Main_Menu[undo_item].activate(); undo_resume(); } // Undo menu callback void undo_cb(Fl_Widget *, void *) { // int undo_item = main_menubar->find_index(undo_cb); // int redo_item = main_menubar->find_index(redo_cb); undo_once_type = 0; if (undo_current <= 0) { fl_beep(); return; } if (undo_current == undo_last) { write_file(undo_filename(undo_current)); } undo_suspend(); // Undo first deletes all widgets which resets the widget_tree browser. // Save the current scroll position, so we don't scroll back to 0 at undo. // TODO: make the scroll position part of the .fl project file if (widget_browser) { widget_browser->save_scroll_position(); widget_browser->new_list(); } int reload_panel = (the_panel && the_panel->visible()); if (!read_file(undo_filename(undo_current - 1), 0)) { // Unable to read checkpoint file, don't undo... widget_browser->rebuild(); g_project.update_settings_dialog(); set_modflag(0, 0); undo_resume(); return; } if (reload_panel) { for (Fl_Type *t = Fl_Type::first; t; t=t->next) { if (t->is_widget() && t->selected) { t->open(); break; } } } // Restore old browser position. // Ideally, we would save the browser position inside the undo file. if (widget_browser) widget_browser->restore_scroll_position(); undo_current --; // Update modified flag... set_modflag(undo_current != undo_save); // Update undo/redo menu items... // if (undo_current <= 0) Main_Menu[undo_item].deactivate(); // Main_Menu[redo_item].activate(); widget_browser->rebuild(); g_project.update_settings_dialog(); undo_resume(); } /** \param[in] type set a new type, or set to 0 to clear the once_type without setting a checkpoint \return 1 if the checkpoint was set, 0 if this is a repeating event */ int undo_checkpoint_once(int type) { if (type == 0) { undo_once_type = 0; return 0; } if (undo_paused) return 0; if (undo_once_type != type) { undo_checkpoint(); undo_once_type = type; return 1; } else { // do not add more checkpoints for the same undo type return 0; } } // Save current file to undo buffer void undo_checkpoint() { // printf("undo_checkpoint(): undo_current=%d, undo_paused=%d, modflag=%d\n", // undo_current, undo_paused, modflag); // Don't checkpoint if undo_suspend() has been called... if (undo_paused) return; // int undo_item = main_menubar->find_index(undo_cb); // int redo_item = main_menubar->find_index(redo_cb); undo_once_type = 0; // Save the current UI to a checkpoint file... const char *filename = undo_filename(undo_current); if (!write_file(filename)) { // Don't attempt to do undo stuff if we can't write a checkpoint file... perror(filename); return; } // Update the saved level... if (modflag && undo_current <= undo_save) undo_save = -1; else if (!modflag) undo_save = undo_current; // Update the current undo level... undo_current ++; undo_last = undo_current; if (undo_current > undo_max) undo_max = undo_current; // Enable the Undo and disable the Redo menu items... // Main_Menu[undo_item].activate(); // Main_Menu[redo_item].deactivate(); } // Clear undo buffer void undo_clear() { // int undo_item = main_menubar->find_index(undo_cb); // int redo_item = main_menubar->find_index(redo_cb); // Remove old checkpoint files... for (int i = 0; i <= undo_max; i ++) { fl_unlink(undo_filename(i)); } // Reset current, last, and save indices... undo_current = undo_last = undo_max = 0; if (modflag) undo_save = -1; else undo_save = 0; // Disable the Undo and Redo menu items... // Main_Menu[undo_item].deactivate(); // Main_Menu[redo_item].deactivate(); } // Resume undo checkpoints void undo_resume() { undo_paused--; } // Suspend undo checkpoints void undo_suspend() { undo_paused++; } fltk-1.4.3/fluid/CodeEditor.cxx0000644000175000017500000002302115004135251016453 0ustar albrechtalbrecht// // Code editor widget for the Fast Light Tool Kit (FLTK). // Syntax highlighting rewritten by erco@seriss.com 09/15/20. // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // Include necessary headers... // #include "CodeEditor.h" #include #include #include #include // ---- CodeEditor implementation /** Lookup table for all supported styles. Every table entry describes a rendering style for the corresponding text. */ Fl_Text_Display::Style_Table_Entry CodeEditor::styletable[] = { // Style table { FL_FOREGROUND_COLOR, FL_COURIER, 11 }, // A - Plain { FL_DARK_GREEN, FL_COURIER_ITALIC, 11 }, // B - Line comments { FL_DARK_GREEN, FL_COURIER_ITALIC, 11 }, // C - Block comments { FL_BLUE, FL_COURIER, 11 }, // D - Strings { FL_DARK_RED, FL_COURIER, 11 }, // E - Directives { FL_DARK_RED, FL_COURIER_BOLD, 11 }, // F - Types { FL_BLUE, FL_COURIER_BOLD, 11 }, // G - Keywords { 220, /* med cyan */ FL_COURIER, 11 } // H - Single quote chars }; /** Parse text and produce style data. \param[in] in_tbuff text buffer to parse \param[inout] in_sbuff style buffer we modify \param[in] in_len byte length to parse \param[in] in_style starting style letter */ void CodeEditor::style_parse(const char *in_tbuff, // text buffer to parse char *in_sbuff, // style buffer we modify int in_len, // byte length to parse char in_style) { // starting style letter // Style letters: // // 'A' - Plain // 'B' - Line comments // .. // 'C' - Block comments /*..*/ // 'D' - Strings "xxx" // 'E' - Directives #define, #include.. // 'F' - Types void, char.. // 'G' - Keywords if, while.. // 'H' - Chars 'x' StyleParse sp; sp.tbuff = in_tbuff; sp.sbuff = in_sbuff; sp.len = in_len; sp.style = in_style; sp.lwhite = 1; // 1:while parsing over leading white and first char past, 0:past white sp.col = 0; sp.last = 0; // Loop through the code, updating style buffer char c; while ( sp.len > 0 ) { c = sp.tbuff[0]; // current char if ( sp.style == 'C' ) { // Started in middle of comment block? if ( !sp.parse_block_comment() ) break; } else if ( strncmp(sp.tbuff, "/*", 2)==0 ) { // C style comment block? if ( !sp.parse_block_comment() ) break; } else if ( c == '\\' ) { // Backslash escape char? if ( !sp.parse_escape() ) break; } else if ( strncmp(sp.tbuff, "//", 2)==0 ) { // Line comment? if ( !sp.parse_line_comment() ) break; } else if ( c == '"' ) { // Start of double quoted string? if ( !sp.parse_quoted_string('"', 'D') ) break; } else if ( c == '\'' ) { // Start of single quoted string? if ( !sp.parse_quoted_string('\'', 'H') ) break; } else if ( c == '#' && sp.lwhite ) { // Start of '#' directive? if ( !sp.parse_directive() ) break; } else if ( !sp.last && (islower(c) || c == '_') ) { // Possible C/C++ keyword? if ( !sp.parse_keyword() ) break; } else { // All other chars? if ( !sp.parse_all_else() ) break; } } } /** Update unfinished styles. */ void CodeEditor::style_unfinished_cb(int, void*) { } /** Update the style buffer. \param[in] pos insert position in text \param[in] nInserted number of bytes inserted \param[in] nDeleted number of bytes deleted \param[in] cbArg pointer back to the code editor */ void CodeEditor::style_update(int pos, int nInserted, int nDeleted, int /*nRestyled*/, const char * /*deletedText*/, void *cbArg) { CodeEditor *editor = (CodeEditor*)cbArg; char *style, // Style data *text; // Text data // If this is just a selection change, just unselect the style buffer... if (nInserted == 0 && nDeleted == 0) { editor->mStyleBuffer->unselect(); return; } // Track changes in the text buffer... if (nInserted > 0) { // Insert characters into the style buffer... style = new char[nInserted + 1]; memset(style, 'A', nInserted); style[nInserted] = '\0'; editor->mStyleBuffer->replace(pos, pos + nDeleted, style); delete[] style; } else { // Just delete characters in the style buffer... editor->mStyleBuffer->remove(pos, pos + nDeleted); } // Select the area that was just updated to avoid unnecessary // callbacks... editor->mStyleBuffer->select(pos, pos + nInserted - nDeleted); // Reparse whole buffer, don't get cute. Maybe optimize range later int len = editor->buffer()->length(); text = editor->mBuffer->text_range(0, len); style = editor->mStyleBuffer->text_range(0, len); style_parse(text, style, editor->mBuffer->length(), 'A'); editor->mStyleBuffer->replace(0, len, style); editor->redisplay_range(0, len); editor->redraw(); free(text); free(style); } /** Find the right indentation depth after pressing the Enter key. \param[in] e pointer back to the code editor */ int CodeEditor::auto_indent(int, CodeEditor* e) { if (e->buffer()->selected()) { e->insert_position(e->buffer()->primary_selection()->start()); e->buffer()->remove_selection(); } int pos = e->insert_position(); int start = e->line_start(pos); char *text = e->buffer()->text_range(start, pos); char *ptr; for (ptr = text; isspace(*ptr); ptr ++) {/*empty*/} *ptr = '\0'; if (*text) { // use only a single 'insert' call to avoid redraw issues size_t n = strlen(text); char *b = (char*)malloc(n+2); *b = '\n'; strcpy(b+1, text); e->insert(b); free(b); } else { e->insert("\n"); } e->show_insert_position(); e->set_changed(); if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED); free(text); return 1; } /** Create a CodeEditor widget. \param[in] X, Y, W, H position and size of the widget \param[in] L optional label */ CodeEditor::CodeEditor(int X, int Y, int W, int H, const char *L) : Fl_Text_Editor(X, Y, W, H, L) { buffer(new Fl_Text_Buffer); char *style = new char[mBuffer->length() + 1]; char *text = mBuffer->text(); memset(style, 'A', mBuffer->length()); style[mBuffer->length()] = '\0'; highlight_data(new Fl_Text_Buffer(mBuffer->length()), styletable, sizeof(styletable) / sizeof(styletable[0]), 'A', style_unfinished_cb, this); style_parse(text, style, mBuffer->length(), 'A'); mStyleBuffer->text(style); delete[] style; free(text); mBuffer->add_modify_callback(style_update, this); add_key_binding(FL_Enter, FL_TEXT_EDITOR_ANY_STATE, (Fl_Text_Editor::Key_Func)auto_indent); } /** Destroy a CodeEditor widget. */ CodeEditor::~CodeEditor() { Fl_Text_Buffer *buf = mStyleBuffer; mStyleBuffer = 0; delete buf; buf = mBuffer; buffer(0); delete buf; } /** Attempt to make the fluid code editor widget honor textsize setting. This works by updating the fontsizes in the style table. \param[in] s the new general height of the text font */ void CodeEditor::textsize(Fl_Fontsize s) { Fl_Text_Editor::textsize(s); // call base class method // now attempt to update our styletable to honor the new size... int entries = sizeof(styletable) / sizeof(styletable[0]); for(int iter = 0; iter < entries; iter++) { styletable[iter].size = s; } } // textsize // ---- CodeViewer implementation /** Create a CodeViewer widget. \param[in] X, Y, W, H position and size of the widget \param[in] L optional label */ CodeViewer::CodeViewer(int X, int Y, int W, int H, const char *L) : CodeEditor(X, Y, W, H, L) { default_key_function(kf_ignore); remove_all_key_bindings(&key_bindings); cursor_style(CARET_CURSOR); } /** Tricking Fl_Text_Display into using bearable colors for this specific task. */ void CodeViewer::draw() { Fl_Color c = Fl::get_color(FL_SELECTION_COLOR); Fl::set_color(FL_SELECTION_COLOR, fl_color_average(FL_BACKGROUND_COLOR, FL_FOREGROUND_COLOR, 0.9f)); CodeEditor::draw(); Fl::set_color(FL_SELECTION_COLOR, c); } // ---- TextViewer implementation /** Create a TextViewer widget. \param[in] X, Y, W, H position and size of the widget \param[in] L optional label */ TextViewer::TextViewer(int X, int Y, int W, int H, const char *L) : Fl_Text_Display(X, Y, W, H, L) { buffer(new Fl_Text_Buffer); } /** Avoid memory leaks. */ TextViewer::~TextViewer() { Fl_Text_Buffer *buf = mBuffer; buffer(0); delete buf; } /** Tricking Fl_Text_Display into using bearable colors for this specific task. */ void TextViewer::draw() { Fl_Color c = Fl::get_color(FL_SELECTION_COLOR); Fl::set_color(FL_SELECTION_COLOR, fl_color_average(FL_BACKGROUND_COLOR, FL_FOREGROUND_COLOR, 0.9f)); Fl_Text_Display::draw(); Fl::set_color(FL_SELECTION_COLOR, c); } fltk-1.4.3/fluid/template_panel.cxx0000644000175000017500000003110515004135251017426 0ustar albrechtalbrecht// // FLUID template support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #include "template_panel.h" #include "fluid.h" #include #include #include #include "fluid_filename.h" #include "../src/flstring.h" #include #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #else #include #endif // _WIN32 && !__CYGWIN__ Fl_Double_Window *template_panel=(Fl_Double_Window *)0; static void cb_template_panel(Fl_Double_Window*, void*) { Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); if (img) img->release(); template_preview->image(0); template_browser->deselect(); template_name->value(""); template_instance->value(""); template_panel->hide(); } Fl_Browser *template_browser=(Fl_Browser *)0; static void cb_template_browser(Fl_Browser*, void*) { if (Fl::event_clicks()) { template_panel->hide(); return; } Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); if (img) img->release(); template_preview->image(0); template_preview->redraw(); int item = template_browser->value(); if (item <= 1) template_instance->deactivate(); else template_instance->activate(); if (item < 1) { template_submit->deactivate(); template_delete->deactivate(); return; } template_submit->activate(); const char *flfile = (const char *)template_browser->data(item); if (!flfile) { template_delete->deactivate(); return; } template_name->value(template_browser->text(item)); template_delete->activate(); char pngfile[1024], *ext; strlcpy(pngfile, flfile, sizeof(pngfile)); if ((ext = strrchr(pngfile, '.')) == NULL) return; strcpy(ext, ".png"); img = Fl_Shared_Image::get(pngfile); if (img) { template_preview->image(img); template_preview->redraw(); } } Fl_Box *template_preview=(Fl_Box *)0; Fl_Input *template_name=(Fl_Input *)0; static void cb_template_name(Fl_Input*, void*) { if (strlen(template_name->value())) { template_submit->activate(); if (Fl::event_key() == FL_Enter) template_panel->hide(); } else template_submit->deactivate(); } Fl_Input *template_instance=(Fl_Input *)0; Fl_Button *template_delete=(Fl_Button *)0; static void cb_Cancel(Fl_Button*, void*) { Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); if (img) img->release(); template_preview->image(0); template_browser->deselect(); template_name->value(""); template_instance->value(""); template_panel->hide(); } Fl_Return_Button *template_submit=(Fl_Return_Button *)0; static void cb_template_submit(Fl_Return_Button*, void*) { Fl_Shared_Image *img = (Fl_Shared_Image *)template_preview->image(); if (img) img->release(); template_preview->image(0); template_panel->hide(); } Fl_Double_Window* make_template_panel() { { template_panel = new Fl_Double_Window(460, 355, "New/Save Template"); template_panel->callback((Fl_Callback*)cb_template_panel); { template_browser = new Fl_Browser(10, 28, 180, 250, "Available Templates:"); template_browser->type(2); template_browser->labelfont(1); template_browser->callback((Fl_Callback*)cb_template_browser); template_browser->align(Fl_Align(FL_ALIGN_TOP_LEFT)); template_browser->when(FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED); } // Fl_Browser* template_browser { template_preview = new Fl_Box(200, 28, 250, 250); template_preview->box(FL_THIN_DOWN_BOX); template_preview->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); Fl_Group::current()->resizable(template_preview); } // Fl_Box* template_preview { template_name = new Fl_Input(198, 288, 252, 25, "Template Name:"); template_name->labelfont(1); template_name->textfont(4); template_name->callback((Fl_Callback*)cb_template_name); template_name->when(FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED); } // Fl_Input* template_name { template_instance = new Fl_Input(198, 288, 252, 25, "Instance Name:"); template_instance->labelfont(1); template_instance->textfont(4); template_instance->hide(); } // Fl_Input* template_instance { Fl_Group* o = new Fl_Group(10, 323, 440, 25); { template_delete = new Fl_Button(10, 323, 143, 25, "Delete Template"); template_delete->callback((Fl_Callback*)template_delete_cb); } // Fl_Button* template_delete { Fl_Box* o = new Fl_Box(153, 323, 126, 25); Fl_Group::current()->resizable(o); } // Fl_Box* o { Fl_Button* o = new Fl_Button(289, 323, 72, 25, "Cancel"); o->callback((Fl_Callback*)cb_Cancel); } // Fl_Button* o { template_submit = new Fl_Return_Button(371, 323, 79, 25, "Save"); template_submit->callback((Fl_Callback*)cb_template_submit); } // Fl_Return_Button* template_submit o->end(); } // Fl_Group* o template_panel->set_modal(); template_panel->end(); } // Fl_Double_Window* template_panel return template_panel; } void template_clear() { int i; void *filename; for (i = 1; i <= template_browser->size(); i ++) { if ((filename = template_browser->data(i)) != NULL) free(filename); } template_browser->deselect(); template_browser->clear(); } void template_delete_cb(Fl_Button *, void *) { int item = template_browser->value(); if (item < 1) return; const char *name = template_browser->text(item); const char *flfile = (const char *)template_browser->data(item); if (!flfile) return; if (!fl_choice("Are you sure you want to delete the template \"%s\"?", "Cancel", "Delete", 0, name)) return; if (fl_unlink(flfile)) { fl_alert("Unable to delete template \"%s\":\n%s", name, strerror(errno)); return; } char pngfile[1024], *ext; strlcpy(pngfile, flfile, sizeof(pngfile)); if ((ext = strrchr(pngfile, '.')) != NULL) { strcpy(ext, ".png"); fl_unlink(pngfile); } template_browser->remove(item); template_browser->do_callback(); } static int tmpl_FLTK_License_fl_size = 614; static unsigned char tmpl_FLTK_License_fl[397] = /* data compressed and inlined from templates/FLTK_License.fl */ {120,156,133,82,77,79,27,49,16,189,239,175,120,162,23,144,202,110,130,56,20, 78,208,80,170,8,148,34,17,14,61,33,239,122,118,61,194,177,87,246,44,75,26,229, 191,215,94,18,245,88,159,236,241,251,154,177,191,64,43,81,104,217,18,90,31,32, 134,112,111,229,13,47,145,2,150,78,40,180,170,33,220,81,228,206,165,210,105,107, 7,214,103,197,59,133,200,222,97,94,206,46,103,243,194,144,210,20,94,157,218, 16,118,165,217,23,141,215,116,60,54,31,31,185,176,217,144,19,236,170,170,168, 42,220,44,87,207,235,219,213,226,199,205,63,95,21,5,143,220,25,193,218,123,139, 7,22,156,222,63,174,31,206,202,226,147,180,240,253,54,76,128,249,213,213,183, 243,139,217,197,37,234,45,190,179,181,120,238,89,254,168,55,40,167,225,147,92, 136,71,214,218,112,132,229,58,168,176,69,218,182,129,8,209,183,50,170,64,37,238, 56,74,224,122,144,220,78,102,15,145,48,185,68,36,0,252,32,150,29,105,176,203, 106,57,233,52,174,147,197,175,167,223,203,213,207,19,140,134,27,131,104,252,96, 53,140,122,39,212,68,46,225,27,59,232,68,28,89,76,226,101,235,68,44,129,101,59, 29,179,220,36,149,110,54,28,35,187,14,105,22,90,109,84,71,250,43,98,202,153, 237,44,55,228,82,40,37,215,135,150,242,50,34,125,188,174,170,113,28,203,54,61, 89,233,67,87,29,50,149,189,233,15,208,39,75,42,113,143,90,173,183,214,143,217, 169,79,38,72,45,27,63,66,60,2,245,62,8,234,161,139,211,20,82,158,129,226,127,13, 51,254,232,182,199,142,221,107,244,67,72,63,38,237,62,63,69,177,47,254,2,228, 190,201,192}; static int tmpl_1of7GUIs_fl_size = 763; static unsigned char tmpl_1of7GUIs_fl[486] = /* data compressed and inlined from templates/1of7GUIs.fl */ {120,156,109,82,203,138,219,64,16,188,207,87,52,228,178,102,177,45,25,59, 187,142,73,14,121,56,187,36,224,92,76,142,102,36,181,164,206,142,102,196,60,252, 88,33,216,223,200,61,127,146,63,201,151,164,37,69,176,9,97,4,163,26,122,170, 170,171,231,5,100,210,75,200,73,33,228,198,130,47,17,182,202,63,192,222,161,133, 123,237,209,230,50,69,120,143,142,10,205,71,87,185,10,148,77,4,28,209,58,50,26, 226,89,180,140,34,1,37,202,12,237,65,203,10,161,153,149,173,72,77,134,35,76,207, 231,86,64,106,170,10,181,135,70,196,96,114,184,249,184,191,119,66,244,27,156, 164,131,4,81,67,106,81,122,204,128,177,4,87,147,158,154,60,239,202,59,107,149, 116,236,232,215,211,119,39,24,58,114,240,206,84,181,180,228,216,9,215,236,146, 111,152,250,233,206,18,235,116,36,58,131,109,208,169,103,167,82,137,47,214,20, 86,86,21,233,162,239,150,149,185,179,35,42,83,247,198,146,11,124,8,5,155,248, 68,142,229,125,167,41,238,66,37,245,180,211,9,126,204,68,246,140,80,88,19,234, 209,219,103,164,68,211,163,216,107,234,179,241,63,127,120,184,147,90,27,134,64, 26,22,81,188,156,9,81,122,95,187,87,243,249,77,17,200,205,10,242,101,72,102, 100,6,60,23,45,52,14,21,119,193,246,73,31,156,9,150,243,215,198,31,24,13,33,139, 86,136,177,43,104,248,130,169,81,119,23,197,86,29,190,146,206,204,169,63,22,74, 38,168,56,162,208,121,134,190,234,124,57,149,208,44,111,95,194,98,189,128,120, 189,132,213,170,5,127,169,121,198,38,36,252,12,44,231,250,40,187,191,35,57,226, 125,100,222,5,207,17,240,20,123,186,195,137,178,2,187,97,14,148,241,10,248,187, 141,96,177,24,102,31,65,243,119,233,244,205,81,170,128,87,209,100,211,114,11, 204,248,54,120,255,167,133,231,94,69,42,149,74,100,250,0,13,241,84,8,94,195,191, 76,52,80,77,54,130,174,175,55,226,255,66,212,9,13,238,214,235,103,238,134,245, 27,226,34,7,2}; void template_install(const char *path, const char *name, const uchar *inSrc, int inSrcLen, int inDstLen) { char filename[FL_PATH_MAX]; strcpy(filename, path); strcat(filename, name); FILE *f = fopen(filename, "wb"); if (!f) return; uLong dstLen = inDstLen; Bytef *dst = (Bytef*)::malloc(inDstLen); if (uncompress(dst, &dstLen, (Bytef*)inSrc, (uLong)inSrcLen) != Z_OK) { /* error */ } if (fwrite(dst, dstLen, 1, f) <= 0) { /* error */ } fclose(f); } void template_load() { int i; char name[1024], filename[1400], path[1024], *ptr; struct dirent **files; int num_files; fluid_prefs.getUserdataPath(path, sizeof(path)); strlcat(path, "templates", sizeof(path)); fl_make_path(path); int sample_templates_generated = 0; fluid_prefs.get("sample_templates_generated", sample_templates_generated, 0); if (sample_templates_generated < 2) { strcpy(filename, path); strcat(filename, "/FLTK_License.fl"); FILE *f = fopen(filename, "wb"); if (f) { fputs( "# data file for the Fltk User Interface Designer (fluid)\nversion 1.0400\nheader_name {.h}\n" "code_name {.cxx}\ncomment {//\n// @INSTANCE@ for the Fast Light Tool Kit (FLT" "K).\n//\n// Copyright 1998-2023 by Bill Spitzak and others.\n//\n// This library is free sof" "tware. Distribution and use rights are outlined in\n// the file \"COPYING\" which should have " "been included with this file. If this\n// file is missing or damaged, see the license at:\n" "//\n// https://www.fltk.org/COPYING.php\n//\n// Please see the following page on how to report " "bugs and issues:\n//\n// https://www.fltk.org/bugs.php\n//\n} {selected in_source in_head" "er\n}\n", f); fclose(f); } template_install(path, "/FLTK_License.fl", tmpl_FLTK_License_fl, sizeof(tmpl_FLTK_License_fl), tmpl_FLTK_License_fl_size); template_install(path, "/1of7GUIs.fl", tmpl_1of7GUIs_fl, sizeof(tmpl_1of7GUIs_fl), tmpl_1of7GUIs_fl_size); sample_templates_generated = 2; fluid_prefs.set("sample_templates_generated", sample_templates_generated); fluid_prefs.flush(); } num_files = fl_filename_list(path, &files); for (i = 0; i < num_files; i ++) { if (fl_filename_match(files[i]->d_name, "*.fl")) { // Format the name as the filename with "_" replaced with " " // and without the trailing ".fl"... strlcpy(name, files[i]->d_name, sizeof(name)); *strstr(name, ".fl") = '\0'; for (ptr = name; *ptr; ptr ++) { if (*ptr == '_') *ptr = ' '; } // Add the template to the browser... snprintf(filename, sizeof(filename), "%s/%s", path, files[i]->d_name); template_browser->add(name, fl_strdup(filename)); } free(files[i]); } if (num_files > 0) free(files); } fltk-1.4.3/fluid/Fd_Snap_Action.h0000644000175000017500000001450315004135251016673 0ustar albrechtalbrecht// // Snap action header file for the Fast Light Tool Kit (FLTK). // // Copyright 2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_FD_SNAP_ACTION_H #define _FLUID_FD_SNAP_ACTION_H #include "fluid.h" #include "Fl_Window_Type.h" #include "../src/Fl_String.H" struct Fl_Menu_Item; extern Fl_Menu_Item main_layout_submenu_[]; /** \brief Collection of layout settings. Presets contain default fonts and font sizes for labels and text. They can be used to guide widget positions using margins, grids, and gap sizes. There are three Presets available in one Suite, marked "application", "dialog", and "toolbox". */ class Fd_Layout_Preset { public: int left_window_margin; ///< gap between the window border and the widget int right_window_margin; int top_window_margin; int bottom_window_margin; int window_grid_x; ///< a regular grid across the window with its origin in the top left window corner int window_grid_y; int left_group_margin; ///< gap between the border of a widget and its parent group int right_group_margin; int top_group_margin; int bottom_group_margin; int group_grid_x; ///< a regular grid across the group with its origin in the top left group corner int group_grid_y; int top_tabs_margin; ///< preferred top edge tab size inside Fl_Tabs int bottom_tabs_margin; ///< preferred bottom edge tab size inside Fl_Tabs int widget_min_w; ///< minimum widget width int widget_inc_w; ///< widget width increments starting from widget_min_w int widget_gap_x; ///< preferred horizontal gap between widgets int widget_min_h; int widget_inc_h; int widget_gap_y; int labelfont; ///< preferred font for labels int labelsize; ///< preferred size for labels int textfont; ///< preferred font for text elements int textsize; ///< preferred size for text elements void write(Fl_Preferences &prefs); void read(Fl_Preferences &prefs); void write(Fd_Project_Writer*); void read(Fd_Project_Reader*); int textsize_not_null(); }; extern Fd_Layout_Preset *layout; /** \brief A collection of layout presets. A suite of layout presets is designed to cover various use cases when designing UI layouts for applications. There are three Presets available in one Suite, marked "application", "dialog", and "toolbox". */ class Fd_Layout_Suite { public: char *name_; ///< name of the suite char *menu_label; ///< label text used in pulldown menu Fd_Layout_Preset *layout[3]; ///< presets for application, dialog, and toolbox windows Fd_Tool_Store storage_; ///< storage location (see FD_STORE_INTERNAL, etc.) void write(Fl_Preferences &prefs); void read(Fl_Preferences &prefs); void write(Fd_Project_Writer*); void read(Fd_Project_Reader*); void update_label(); void storage(Fd_Tool_Store s) { storage_ = s; update_label(); } void name(const char *n); void init(); ~Fd_Layout_Suite(); public: }; /** \brief Manage all layout suites that are available to the user. FLUID has two built-in suites. More suites can be cloned or added and stored as a user preference, as part of an .fl project file, or in a separate file for import/export and sharing. */ class Fd_Layout_List { public: Fl_Menu_Item *main_menu_; Fl_Menu_Item *choice_menu_; Fd_Layout_Suite *list_; int list_size_; int list_capacity_; bool list_is_static_; int current_suite_; int current_preset_; Fl_String filename_; public: Fd_Layout_List(); ~Fd_Layout_List(); void update_dialogs(); void update_menu_labels(); int current_suite() const { return current_suite_; } void current_suite(int ix); void current_suite(Fl_String); int current_preset() const { return current_preset_; } void current_preset(int ix); Fd_Layout_Suite &operator[](int ix) { return list_[ix]; } int add(const char *name); void rename(const char *name); void capacity(int); int load(const Fl_String &filename); int save(const Fl_String &filename); void write(Fl_Preferences &prefs, Fd_Tool_Store storage); void read(Fl_Preferences &prefs, Fd_Tool_Store storage); void write(Fd_Project_Writer*); void read(Fd_Project_Reader*); int add(Fd_Layout_Suite*); void remove(int index); void remove_all(Fd_Tool_Store storage); Fd_Layout_Preset *at(int); int size(); }; extern Fd_Layout_List g_layout_list; /** \brief Structure holding all the data to perform interactive alignment operations. */ typedef struct Fd_Snap_Data { int dx, dy; ///< distance of the mouse from its initial PUSH event int bx, by, br, bt; ///< bounding box of the original push event or current bounding box when drawing int drag; ///< drag event mask int x_dist, y_dist; ///< current closest snapping distance in x and y int dx_out, dy_out; ///< current closest snapping point as a delta Fl_Widget_Type *wgt; ///< first selected widget Fl_Window_Type *win; ///< window that handles the drag action int ex_out, ey_out; ///< chosen snap position } Fd_Snap_Data; /** \brief Find points of interest when moving the bounding box of all selected widgets. */ class Fd_Snap_Action { protected: int check_x_(Fd_Snap_Data &d, int x_ref, int x_snap); int check_y_(Fd_Snap_Data &d, int y_ref, int y_snap); void check_x_y_(Fd_Snap_Data &d, int x_ref, int x_snap, int y_ref, int y_snap); void clr() { ex = dx = 0x7fff; } public: int ex, ey, dx, dy, type, mask; Fd_Snap_Action() : ex(0x7fff), ey(0x7fff), dx(128), dy(128), type(0), mask(0) { } virtual ~Fd_Snap_Action() { } virtual void check(Fd_Snap_Data &d) = 0; virtual void draw(Fd_Snap_Data &d) { } virtual bool matches(Fd_Snap_Data &d); public: static int eex, eey; static Fd_Snap_Action *list[]; static void check_all(Fd_Snap_Data &d); static void draw_all(Fd_Snap_Data &d); static void get_resize_stepsize(int &x_step, int &y_step); static void get_move_stepsize(int &x_step, int &y_step); static void better_size(int &w, int &h); }; #endif // _FLUID_FD_SNAP_ACTION_H fltk-1.4.3/fluid/Fl_Grid_Type.cxx0000644000175000017500000010017715004135251016751 0ustar albrechtalbrecht// // Fl_Grid object code for the Fast Light Tool Kit (FLTK). // // Copyright 2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Grid_Type.h" #include "fluid.h" #include "file.h" #include "code.h" #include "widget_browser.h" #include "undo.h" #include "Fd_Snap_Action.h" #include "custom_widgets.h" #include #include #include #include #include "../src/flstring.h" #include #include #include // ---- Fl_Grid_Proxy --------------------------------------------------- MARK: - /** An implementation of the Fl_Grid widget with additional functionality. Fl_Grid_Proxy add a list of transient children, i.e. children that are temporarily assigned to a cell that is already taken by another child. */ Fl_Grid_Proxy::Fl_Grid_Proxy(int X,int Y,int W,int H) : Fl_Grid(X,Y,W,H), transient_(NULL), num_transient_(0), cap_transient_(0) { } Fl_Grid_Proxy::~Fl_Grid_Proxy() { int i; if (transient_) { for (i=0; i 0) { Fl_Grid::resize(X, Y, W, H); } else { Fl_Widget::resize(X, Y, W, H); } redraw(); } /** Override draw() to make groups with no box or flat box background visible. */ void Fl_Grid_Proxy::draw() { if (show_ghosted_outline && (box() == FL_NO_BOX)) { fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f))); } Fl_Grid::draw(); } /** Draw additional markings in the overlay plane when a grid is selected. */ void Fl_Grid_Proxy::draw_overlay() { fl_line_style(FL_DOT); grid_color = fl_color(); draw_grid(); fl_color(grid_color); } /** Move a cell into the grid or within the grid. If the target cell is already taken, \p how will determine what to do: If \p how is 0, the existing cell at \p to_row, \p to_col will be deleted, unlinking the occupant from the grid. \p in_child will the be inserted at the given location. If \p how is 1, the old cell will remain intact, however \p in_child will be unlinked from the grid. If \p how is 2, the old cell will remain intact, and \p in_child will be removed from the grid, but it will be stored in the transient list and resized to the target cell position and size. If \p in_child is later moved to an unoccupied cell, it will be removed from the transient list and relinked to the grid. Rowspan and colspan are ignored here. \param[in] in_child must already be a child of grid \param[in] to_row, to_col move the child into this cell \param[in] how 0: replace occupant, 1: don't replace, 2: make transient if occupied */ void Fl_Grid_Proxy::move_cell(Fl_Widget *in_child, int to_row, int to_col, int how) { // the child must already be a true child of grid assert(find(in_child)row() == to_row && old_cell->col() == to_col) return; rowspan = old_cell->rowspan(); colspan = old_cell->colspan(); align = old_cell->align(); old_cell->minimum_size(&w, &h); } if ((to_row < 0) || (to_row+rowspan > rows())) return; if ((to_col < 0) || (to_col+colspan > cols())) return; Fl_Grid::Cell *new_cell = NULL; if (how == 0) { // replace old occupant in cell, making that one homeless new_cell = widget(in_child, to_row, to_col, rowspan, colspan, align); } else if (how == 1) { // don't replace an old occupant, making ourselves homeless // todo: colspan, rowspan? if (cell(to_row, to_col) == NULL) { new_cell = widget(in_child, to_row, to_col, rowspan, colspan, align); } else { if (old_cell) remove_cell(old_cell->row(), old_cell->col()); } } else if (how == 2) { Cell *current = cell(to_row, to_col); if (current == NULL) { new_cell = widget(in_child, to_row, to_col, rowspan, colspan, align); } else { if (old_cell) remove_cell(old_cell->row(), old_cell->col()); new_cell = transient_widget(in_child, to_row, to_col, rowspan, colspan, align); Fl_Widget *w = current->widget(); Fl_Type::allow_layout++; in_child->resize(w->x(), w->y(), w->w(), w->h()); Fl_Type::allow_layout--; } } if (new_cell) new_cell->minimum_size(w, h); } /** Generate or replace a transient widget entry. If the widget is in the cell list, it will be removed there. If the widget is already transient, the cell will be replaced. \param[in] wi a child of this Fl_Grid_Proxy, that may be linked to a cell or transient cell \param[in] row, col, row_span, col_span, align cell parameters */ Fl_Grid::Cell* Fl_Grid_Proxy::transient_widget(Fl_Widget *wi, int row, int col, int row_span, int col_span, Fl_Grid_Align align) { int i = 0; bool remove_old_cell = false; Cell *old_cell = cell(wi); if (old_cell) { remove_old_cell = true; } else { for (i=0; irowspan(row_span); new_cell->colspan(col_span); new_cell->align(align); if (old_cell) { int mw, mh; old_cell->minimum_size(&mw, &mh); new_cell->minimum_size(mw, mh); if (remove_old_cell) { remove_cell(old_cell->row(), old_cell->col()); } else { delete old_cell; } } if (i == num_transient_) { transient_make_room_(num_transient_ + 1); transient_[i].widget = wi; num_transient_++; } transient_[i].cell = new_cell; return new_cell; } /** Make room for at least n transient widgets in the array. \param[in] n minimum number of entries */ void Fl_Grid_Proxy::transient_make_room_(int n) { if (n > cap_transient_) { cap_transient_ = n + 10; transient_ = (Cell_Widget_Pair*)::realloc(transient_, cap_transient_ * sizeof(Cell_Widget_Pair)); } } /** Remove a widget form the list and deallocate the transient cell. \param[in] w remove the transient cell for this widget */ void Fl_Grid_Proxy::transient_remove_(Fl_Widget *w) { for (int i=0; ilayout(3, 3); Fl_Group::current(0); return g; } Fl_Widget *Fl_Grid_Type::enter_live_mode(int top) { Fl_Grid *grid = new Fl_Grid(o->x(), o->y(), o->w(), o->h()); return propagate_live_mode(grid); } void Fl_Grid_Type::leave_live_mode() { } void Fl_Grid_Type::copy_properties() { super::copy_properties(); Fl_Grid *d = (Fl_Grid*)live_widget, *s =(Fl_Grid*)o; d->layout(s->rows(), s->cols()); int lm, tm, rm, bm; s->margin(&lm, &tm, &rm, &bm); d->margin(lm, tm, rm, bm); int rg, cg; s->gap(&rg, &cg); d->gap(rg, cg); // copy col widths, heights, and gaps for (int c=0; ccols(); c++) { d->col_width(c, s->col_width(c)); d->col_gap(c, s->col_gap(c)); d->col_weight(c, s->col_weight(c)); } // copy row widths, heights, and gaps for (int r=0; rrows(); r++) { d->row_height(r, s->row_height(r)); d->row_gap(r, s->row_gap(r)); d->row_weight(r, s->row_weight(r)); } } void Fl_Grid_Type::copy_properties_for_children() { Fl_Grid *d = (Fl_Grid*)live_widget, *s =(Fl_Grid*)o; for (int i=0; ichildren(); i++) { Fl_Grid::Cell *cell = s->cell(s->child(i)); if (cell && ichildren()) { d->widget(d->child(i), cell->row(), cell->col(), cell->rowspan(), cell->colspan(), cell->align()); } } d->layout(); } void Fl_Grid_Type::write_properties(Fd_Project_Writer &f) { super::write_properties(f); Fl_Grid* grid = (Fl_Grid*)o; int i, rows = grid->rows(), cols = grid->cols(); f.write_indent(level+1); f.write_string("dimensions {%d %d}", rows, cols); int lm, tm, rm, bm; grid->margin(&lm, &tm, &rm, &bm); if (lm!=0 || tm!=0 || rm!=0 || bm!=0) f.write_string("margin {%d %d %d %d}", lm, tm, rm, bm); int rg, cg; grid->gap(&rg, &cg); if (rg!=0 || cg!=0) f.write_string("gap {%d %d}", rg, cg); // -- write all row heights if one of them is not the default 0 for (i=0; irow_height(i)!=0) break; if (irow_height(i)); f.write_string("}"); } // -- write all row weights if one of them is not the default 50 for (i=0; irow_weight(i)!=50) break; if (irow_weight(i)); f.write_string("}"); } // -- write all row gaps if one of them is not the default -1 for (i=0; irow_gap(i)!=-1) break; if (irow_gap(i)); f.write_string("}"); } // -- write all col widths if one of them is not the default 0 for (i=0; icol_width(i)!=0) break; if (icol_width(i)); f.write_string("}"); } // -- write all col weights if one of them is not the default 50 for (i=0; icol_weight(i)!=50) break; if (icol_weight(i)); f.write_string("}"); } // -- write all col gaps if one of them is not the default -1 for (i=0; icol_gap(i)!=-1) break; if (icol_gap(i)); f.write_string("}"); } } void Fl_Grid_Type::read_property(Fd_Project_Reader &f, const char *c) { Fl_Grid* grid = (Fl_Grid*)o; if (!strcmp(c,"dimensions")) { int rows = 3, cols = 3; if (sscanf(f.read_word(),"%d %d", &rows, &cols) == 2) grid->layout(rows, cols); } else if (!strcmp(c,"margin")) { int lm, tm, rm, bm; if (sscanf(f.read_word(),"%d %d %d %d", &lm, &tm, &rm, &bm) == 4) grid->margin(lm, tm, rm, bm); } else if (!strcmp(c,"gap")) { int rg, cg; if (sscanf(f.read_word(),"%d %d", &rg, &cg) == 2) grid->gap(rg, cg); } else if (!strcmp(c,"rowheights")) { int rows = grid->rows(); f.read_word(1); // "{" for (int i=0; irow_height(i, f.read_int()); f.read_word(1); // "}" } else if (!strcmp(c,"rowweights")) { int rows = grid->rows(); f.read_word(1); // "{" for (int i=0; irow_weight(i, f.read_int()); f.read_word(1); // "}" } else if (!strcmp(c,"rowgaps")) { int rows = grid->rows(); f.read_word(1); // "{" for (int i=0; irow_gap(i, f.read_int()); f.read_word(1); // "}" } else if (!strcmp(c,"colwidths")) { int cols = grid->cols(); f.read_word(1); // "{" for (int i=0; icol_width(i, f.read_int()); f.read_word(1); // "}" } else if (!strcmp(c,"colweights")) { int cols = grid->cols(); f.read_word(1); // "{" for (int i=0; icol_weight(i, f.read_int()); f.read_word(1); // "}" } else if (!strcmp(c,"colgaps")) { int cols = grid->cols(); f.read_word(1); // "{" for (int i=0; icol_gap(i, f.read_int()); f.read_word(1); // "}" } else { super::read_property(f, c); } } void Fl_Grid_Type::write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate) { Fl_Grid *grid; Fl_Widget *child_widget; Fl_Grid::Cell *cell; if (!child->is_true_widget()) return super::write_parent_properties(f, child, true); grid = (Fl_Grid*)o; child_widget = ((Fl_Widget_Type*)child)->o; cell = grid->cell(child_widget); if (!cell) return super::write_parent_properties(f, child, true); if (encapsulate) { f.write_indent(level+2); f.write_string("parent_properties {"); } f.write_indent(level+3); f.write_string("location {%d %d}", cell->row(), cell->col()); int v = cell->colspan(); if (v>1) { f.write_indent(level+3); f.write_string("colspan %d", v); } v = cell->rowspan(); if (v>1) { f.write_indent(level+3); f.write_string("rowspan %d", v); } v = (int)cell->align(); if (v!=FL_GRID_FILL) { f.write_indent(level+3); f.write_string("align %d", v); } int min_w = 0, min_h = 0; cell->minimum_size(&min_w, &min_h); if (min_w!=20 || min_h!=20) { f.write_indent(level+3); f.write_string("minsize {%d %d}", min_w, min_h); } super::write_parent_properties(f, child, false); if (encapsulate) { f.write_indent(level+2); f.write_string("}"); } return; } // NOTE: we have to do this in a loop just as ::read_property() in case a new // property is added. In the current setup, all the remaining properties // will be skipped void Fl_Grid_Type::read_parent_property(Fd_Project_Reader &f, Fl_Type *child, const char *property) { if (!child->is_true_widget()) { super::read_parent_property(f, child, property); return; } Fl_Grid *grid = (Fl_Grid*)o; Fl_Widget *child_widget = ((Fl_Widget_Type*)child)->o; if (!strcmp(property, "location")) { int row = -1, col = -1; const char *value = f.read_word(); sscanf(value, "%d %d", &row, &col); Fl_Grid::Cell *cell = grid->widget(child_widget, row, col); if (cell) { int min_w = 20, min_h = 20; cell->minimum_size(min_w, min_h); } } else if (!strcmp(property, "colspan")) { int colspan = atoi(f.read_word()); Fl_Grid::Cell *cell = grid->cell(child_widget); if (cell) cell->colspan(colspan); } else if (!strcmp(property, "rowspan")) { int rowspan = atoi(f.read_word()); Fl_Grid::Cell *cell = grid->cell(child_widget); if (cell) cell->rowspan(rowspan); } else if (!strcmp(property, "align")) { int align = atoi(f.read_word()); Fl_Grid::Cell *cell = grid->cell(child_widget); if (cell) cell->align((Fl_Grid_Align)align); } if (!strcmp(property, "minsize")) { int min_w = 20, min_h = 20; const char *value = f.read_word(); sscanf(value, "%d %d", &min_w, &min_h); Fl_Grid::Cell *cell = grid->cell(child_widget); if (cell) cell->minimum_size(min_w, min_h); } else { super::read_parent_property(f, child, property); } } void Fl_Grid_Type::write_code1(Fd_Code_Writer& f) { const char *var = name() ? name() : "o"; Fl_Grid* grid = (Fl_Grid*)o; Fl_Widget_Type::write_code1(f); int i, rows = grid->rows(), cols = grid->cols(); f.write_c("%s%s->layout(%d, %d);\n", f.indent(), var, rows, cols); int lm, tm, rm, bm; grid->margin(&lm, &tm, &rm, &bm); if (lm!=0 || tm!=0 || rm!=0 || bm!=0) f.write_c("%s%s->margin(%d, %d, %d, %d);\n", f.indent(), var, lm, tm, rm, bm); int rg, cg; grid->gap(&rg, &cg); if (rg!=0 || cg!=0) f.write_c("%s%s->gap(%d, %d);\n", f.indent(), var, rg, cg); // -- write all row heights if one of them is not the default 0 for (i=0; irow_height(i)!=0) break; if (irow_height(0)); for (i=1; irow_height(i)); f.write_c(" };\n"); f.write_c("%s%s->row_height(rowheights, %d);\n", f.indent(), var, rows); } // -- write all row weights if one of them is not the default 50 for (i=0; irow_weight(i)!=50) break; if (irow_weight(0)); for (i=1; irow_weight(i)); f.write_c(" };\n"); f.write_c("%s%s->row_weight(rowweights, %d);\n", f.indent(), var, rows); } // -- write all row gaps if one of them is not the default -1 for (i=0; irow_gap(i)!=-1) break; if (irow_gap(0)); for (i=1; irow_gap(i)); f.write_c(" };\n"); f.write_c("%s%s->row_gap(rowgaps, %d);\n", f.indent(), var, rows); } // -- write all col widths if one of them is not the default 0 for (i=0; icol_width(i)!=0) break; if (icol_width(0)); for (i=1; icol_width(i)); f.write_c(" };\n"); f.write_c("%s%s->col_width(colwidths, %d);\n", f.indent(), var, cols); } // -- write all col weights if one of them is not the default 50 for (i=0; icol_weight(i)!=50) break; if (icol_weight(0)); for (i=1; icol_weight(i)); f.write_c(" };\n"); f.write_c("%s%s->col_weight(colweights, %d);\n", f.indent(), var, cols); } // -- write all col gaps if one of them is not the default -1 for (i=0; icol_gap(i)!=-1) break; if (icol_gap(0)); for (i=1; icol_gap(i)); f.write_c(" };\n"); f.write_c("%s%s->col_gap(colgaps, %d);\n", f.indent(), var, cols); } } void Fl_Grid_Type::write_code2(Fd_Code_Writer& f) { const char *var = name() ? name() : "o"; Fl_Grid* grid = (Fl_Grid*)o; bool first_cell = true; for (int i=0; ichildren(); i++) { Fl_Widget *c = grid->child(i); Fl_Grid::Cell *cell = grid->cell(c); if (cell) { if (first_cell) { f.write_c("%sFl_Grid::Cell *cell = NULL;\n", f.indent()); first_cell = false; } f.write_c("%scell = %s->widget(%s->child(%d), %d, %d, %d, %d, %d);\n", f.indent(), var, var, i, cell->row(), cell->col(), cell->rowspan(), cell->colspan(), cell->align()); int min_w = 20, min_h = 20; cell->minimum_size(&min_w, &min_h); f.write_c("%sif (cell) cell->minimum_size(%d, %d);\n", f.indent(), min_w, min_h); } } super::write_code2(f); } void Fl_Grid_Type::add_child(Fl_Type* a, Fl_Type* b) { super::add_child(a, b); Fl_Grid* grid = (Fl_Grid*)o; grid->need_layout(1); grid->redraw(); } void Fl_Grid_Type::move_child(Fl_Type* a, Fl_Type* b) { super::move_child(a, b); Fl_Grid* grid = (Fl_Grid*)o; grid->need_layout(1); grid->redraw(); } void Fl_Grid_Type::remove_child(Fl_Type* a) { super::remove_child(a); Fl_Grid* grid = (Fl_Grid*)o; grid->need_layout(1); grid->redraw(); } /** Update the initial size of a child widget. Fl_Grid keeps track of the size of children when they are first added. In FLUID, users will want to resize children. So we need to trick Fl_Grid into taking the new size as the initial size. */ void Fl_Grid_Type::child_resized(Fl_Widget_Type *child_type) { Fl_Grid *grid = (Fl_Grid*)o; Fl_Widget *child = child_type->o; Fl_Grid::Cell *cell = grid->cell(child); if (cell && ((cell->align()&FL_GRID_VERTICAL)==0)) { int min_w = 0, min_h = 0; cell->minimum_size(&min_w, &min_h); cell->minimum_size(min_w, child->h()); } if (cell && ((cell->align()&FL_GRID_HORIZONTAL)==0)) { int min_w = 0, min_h = 0; cell->minimum_size(&min_w, &min_h); cell->minimum_size(child->w(), min_h); } // TODO: if the user resizes an FL_GRID_FILL widget, should we change the alignment? } /** Return the currently selected Grid widget if is a Grid Type. */ Fl_Grid *Fl_Grid_Type::selected() { if (current_widget && current_widget->is_a(ID_Grid)) return ((Fl_Grid*)((Fl_Grid_Type*)current_widget)->o); return NULL; } /** Insert a child widget into the cell at the x, y position inside the window. /param[in] child /param[in] x, y pixels from the top left of the window */ void Fl_Grid_Type::insert_child_at(Fl_Widget *child, int x, int y) { Fl_Grid_Proxy *grid = (Fl_Grid_Proxy*)o; int row = -1, col = -1, ml, mt, grg, gcg; grid->margin(&ml, &mt, NULL, NULL); grid->gap(&grg, &gcg); int x0 = grid->x() + Fl::box_dx(grid->box()) + ml; int y0 = grid->y() + Fl::box_dy(grid->box()) + mt; for (int r = 0; r < grid->rows(); r++) { if (y>y0) row = r; int gap = grid->row_gap(r)>=0 ? grid->row_gap(r) : grg; y0 += grid->computed_row_height(r); y0 += gap; } for (int c = 0; c < grid->cols(); c++) { if (x>x0) col = c; int gap = grid->col_gap(c)>=0 ? grid->col_gap(c) : gcg; x0 += grid->computed_col_width(c); x0 += gap; } grid->move_cell(child, row, col, 2); } /** Insert a child widget into the first new cell we can find . There are many other possible strategies. How about inserting to the right of the last added child. Also, what happens if the grid is full? Should we add a new row at the bottom? /param[in] child */ void Fl_Grid_Type::insert_child_at_next_free_cell(Fl_Widget *child) { Fl_Grid_Proxy *grid = (Fl_Grid_Proxy*)o; if (grid->cell(child)) return; // The code below would insert the new widget after the last selected one, but // unfortunately the current_widget is already invalid. // if (current_widget && (current_widget->parent == this)) { // Fl_Grid::Cell *current_cell = grid->any_cell(current_widget->o); // if (current_cell) { // r = current_cell->row(); // c = current_cell->col(); // } // } for (int r = 0; r < grid->rows(); r++) { for (int c = 0; c < grid->cols(); c++) { if (!grid->cell(r, c)) { grid->move_cell(child, r, c); return; } } } grid->layout(grid->rows() + 1, grid->cols()); grid->move_cell(child, grid->rows() - 1, 0); } /** Move cells around using the keyboard. \note this fails if we have two children selected side by side and press 'right', which will move the left child first, removing the right child from the cell system. When trying to move the second child, it has no longer an assigned row or column. \param[in] child pointer to the child type \param[in] key code of the last keypress when handling a FL_KEYBOARD event. */ void Fl_Grid_Type::keyboard_move_child(Fl_Widget_Type *child, int key) { Fl_Grid_Proxy *grid = ((Fl_Grid_Proxy*)o); Fl_Grid::Cell *cell = grid->any_cell(child->o); if (!cell) return; if (key == FL_Right) { grid->move_cell(child->o, cell->row(), cell->col()+1, 2); } else if (key == FL_Left) { grid->move_cell(child->o, cell->row(), cell->col()-1, 2); } else if (key == FL_Up) { grid->move_cell(child->o, cell->row()-1, cell->col(), 2); } else if (key == FL_Down) { grid->move_cell(child->o, cell->row()+1, cell->col(), 2); } } void Fl_Grid_Type::layout_widget() { allow_layout++; ((Fl_Grid*)o)->layout(); allow_layout--; } // ---- Widget Panel Callbacks ---------------------------------------- MARK: - // TODO: better grid overlay? // TODO: grid_child_cb should move all selected cells, not just the current_selected. // TODO: buttons to add and delete rows and columns in the widget dialog // TODO: ways to resize rows and columns, add and delete them in the project window, pulldown menu? // TODO: alignment can be FL_GRID_LEFT|FL_GRID_VERTICAL? extern Fluid_Coord_Input *widget_grid_row_input, *widget_grid_col_input, *widget_grid_rowspan_input, *widget_grid_colspan_input; extern Fl_Group *widget_tab_grid_child; void grid_child_cb(Fluid_Coord_Input* i, void* v, int what) { if ( !current_widget || !current_widget->parent || !current_widget->parent->is_a(ID_Grid)) { return; } Fl_Widget *child = ((Fl_Widget_Type*)current_widget)->o; Fl_Grid_Proxy *g = ((Fl_Grid_Proxy*)((Fl_Widget_Type*)current_widget->parent)->o); Fl_Grid::Cell *cell = g->any_cell(child); if (v == LOAD) { int v = -1; if (cell) { switch (what & 0x00ff) { case 8: v = cell->row(); break; case 9: v = cell->col(); break; case 10: v = cell->rowspan(); break; case 11: v = cell->colspan(); break; case 12: cell->minimum_size(&v, NULL); break; case 13: cell->minimum_size(NULL, &v); break; } } i->value(v); } else { undo_checkpoint(); int v2 = -2, old_v = -2, v = i->value(); if (i==widget_grid_row_input) v2 = widget_grid_col_input->value(); if (i==widget_grid_col_input) v2 = widget_grid_row_input->value(); Fl_Grid::Cell *new_cell = NULL; if (cell) { switch (what & 0x00ff) { case 8: old_v = cell->row(); v2 = cell->col(); break; case 9: old_v = cell->col(); v2 = cell->row(); break; case 10: old_v = cell->rowspan(); break; case 11: old_v = cell->colspan(); break; case 12: cell->minimum_size(&old_v, &v2); break; case 13: cell->minimum_size(&v2, &old_v); break; } } switch (what & 0xff00) { case 0x0100: v--; break; case 0x0200: v++; break; } if (old_v != v) { switch (what & 0x00ff) { case 8: if (v2 == -1 && v >= 0) v2 = 0; g->move_cell(current_widget->o, v, v2, 2); i->value(v); break; case 9: if (v2 == -1 && v >= 0) v2 = 0; g->move_cell(current_widget->o, v2, v, 2); i->value(v); break; case 10: if (cell && cell->row()+v<=g->rows() && v>0) cell->rowspan(v); break; case 11: if (cell && cell->col()+v<=g->cols() && v>0) cell->colspan(v); break; case 12: if (cell && v>=0) cell->minimum_size(v, v2); break; case 13: if (cell && v>=0) cell->minimum_size(v2, v); break; } if (!cell && new_cell) new_cell->minimum_size(20, 20); g->need_layout(true); set_modflag(1); } } } void grid_set_row_cb(Fluid_Coord_Input* i, void* v) { grid_child_cb(i, v, 8); if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } void grid_dec_row_cb(Fl_Button* i, void* v) { if (v!=LOAD) { grid_child_cb(widget_grid_row_input, v, 0x0100 + 8); widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } } void grid_inc_row_cb(Fl_Button* i, void* v) { if (v!=LOAD) { grid_child_cb(widget_grid_row_input, v, 0x0200 + 8); widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } } void grid_set_col_cb(Fluid_Coord_Input* i, void* v) { grid_child_cb(i, v, 9); if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } void grid_dec_col_cb(Fl_Button* i, void* v) { if (v!=LOAD) { grid_child_cb(widget_grid_col_input, v, 0x0100 + 9); widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } } void grid_inc_col_cb(Fl_Button* i, void* v) { if (v!=LOAD) { grid_child_cb(widget_grid_col_input, v, 0x0200 + 9); widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } } void grid_set_rowspan_cb(Fluid_Coord_Input* i, void* v) { grid_child_cb(i, v, 10); if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } void grid_dec_rowspan_cb(Fl_Button* i, void* v) { if (v!=LOAD) { grid_child_cb(widget_grid_rowspan_input, v, 0x0100 + 10); widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } } void grid_inc_rowspan_cb(Fl_Button* i, void* v) { if (v!=LOAD) { grid_child_cb(widget_grid_rowspan_input, v, 0x0200 + 10); widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } } void grid_set_colspan_cb(Fluid_Coord_Input* i, void* v) { grid_child_cb(i, v, 11); if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } void grid_dec_colspan_cb(Fl_Button* i, void* v) { if (v!=LOAD) { grid_child_cb(widget_grid_colspan_input, v, 0x0100 + 11); widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } } void grid_inc_colspan_cb(Fl_Button* i, void* v) { if (v!=LOAD) { grid_child_cb(widget_grid_colspan_input, v, 0x0200 + 11); widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); } } void grid_set_min_wdt_cb(Fluid_Coord_Input* i, void* v) { grid_child_cb(i, v, 12); } void grid_set_min_hgt_cb(Fluid_Coord_Input* i, void* v) { grid_child_cb(i, v, 13); } void grid_align_horizontal_cb(Fl_Choice* i, void* v) { if ( !current_widget || !current_widget->parent || !current_widget->parent->is_a(ID_Grid)) { return; } int mask = (FL_GRID_LEFT | FL_GRID_RIGHT | FL_GRID_HORIZONTAL); Fl_Grid *g = ((Fl_Grid*)((Fl_Widget_Type*)current_widget->parent)->o); if (v == LOAD) { int a = FL_GRID_FILL & mask; Fl_Grid::Cell *cell = g->cell(current_widget->o); if (cell) { a = cell->align() & mask; } const Fl_Menu_Item *mi = i->find_item_with_argument(a); if (mi) i->value(mi); } else { undo_checkpoint(); int v = FL_GRID_FILL & mask, old_v = FL_GRID_FILL & mask; const Fl_Menu_Item *mi = i->mvalue(); if (mi) v = (int)mi->argument(); Fl_Grid::Cell *cell = g->cell(current_widget->o); if (cell) { old_v = cell->align() & mask; if (old_v != v) { cell->align((Fl_Grid_Align)(v | (cell->align() & ~mask))); g->need_layout(true); g->redraw(); set_modflag(1); } } } } void grid_align_vertical_cb(Fl_Choice* i, void* v) { if ( !current_widget || !current_widget->parent || !current_widget->parent->is_a(ID_Grid)) { return; } int mask = (FL_GRID_TOP | FL_GRID_BOTTOM | FL_GRID_VERTICAL); Fl_Grid *g = ((Fl_Grid*)((Fl_Widget_Type*)current_widget->parent)->o); if (v == LOAD) { int a = FL_GRID_FILL & mask; Fl_Grid::Cell *cell = g->cell(current_widget->o); if (cell) { a = cell->align() & mask; } const Fl_Menu_Item *mi = i->find_item_with_argument(a); if (mi) i->value(mi); } else { undo_checkpoint(); int v = FL_GRID_FILL & mask, old_v = FL_GRID_FILL & mask; const Fl_Menu_Item *mi = i->mvalue(); if (mi) v = (int)mi->argument(); Fl_Grid::Cell *cell = g->cell(current_widget->o); if (cell) { old_v = cell->align() & mask; if (old_v != v) { cell->align((Fl_Grid_Align)(v | (cell->align() & ~mask))); g->need_layout(true); g->redraw(); set_modflag(1); } } } } fltk-1.4.3/fluid/about_panel.cxx0000644000175000017500000046653215004135251016745 0ustar albrechtalbrecht// // About dialog for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #include "about_panel.h" void show_help(const char *name); Fl_Double_Window *about_panel=(Fl_Double_Window *)0; #include static const unsigned char idata_fluid[] = {71,73,70,56,57,97,96,0,96,0,132,31,0,0,1,0,3,31,63,46,48,45,0,54,108,78,80, 77,64,123,116,124,126,123,125,173,98,107,166,116,171,204,63,220,233,19,253,254, 0,196,218,42,147,189,83,20,101,159,44,112,135,0,88,172,0,96,191,0,109,220,91, 161,140,68,152,169,38,140,205,0,128,255,15,133,249,45,146,236,47,148,254,108, 182,255,164,166,162,187,222,255,202,204,201,253,255,252,0,0,0,33,255,11,78,69, 84,83,67,65,80,69,50,46,48,3,1,0,0,0,33,249,4,5,10,0,31,0,44,0,0,0,0,96,0,96,0, 0,5,254,224,39,142,100,105,158,104,170,174,108,235,190,112,44,207,116,109,223, 120,110,2,124,239,3,186,160,238,71,36,14,34,61,161,18,86,244,13,32,78,139,5,201, 91,90,87,63,143,118,171,201,112,184,25,11,180,122,45,239,120,219,180,135,147, 241,174,219,223,164,121,46,234,169,211,108,111,87,163,149,211,205,118,119,96,28, 93,95,28,3,100,127,101,129,130,90,95,107,26,93,22,136,138,128,104,120,28,143, 90,124,121,97,80,149,139,151,142,109,164,111,134,153,99,160,87,140,155,145,153, 142,142,113,137,170,66,172,130,108,90,112,126,180,65,182,119,93,163,26,136,64, 188,181,162,183,112,111,25,169,197,189,199,119,121,143,108,204,205,57,190,120, 25,124,91,28,187,213,54,215,120,119,221,222,52,224,141,125,179,228,229,207,231, 105,227,234,49,230,231,239,240,47,242,141,244,245,45,247,130,249,250,88,236,218, 161,35,246,47,222,179,78,110,196,165,43,184,239,24,194,100,106,252,49,60,193, 232,33,41,77,3,39,50,17,101,17,226,22,137,26,73,84,36,69,50,225,199,133,33,254, 81,140,44,233,49,99,74,22,172,186,148,212,230,14,229,203,18,172,44,98,116,121, 51,133,47,66,26,118,158,36,216,147,98,64,129,32,95,242,83,72,180,40,206,163, 237,124,56,61,3,245,156,128,164,19,125,16,16,40,104,131,212,169,31,180,114,109, 100,224,171,83,31,99,149,37,236,64,192,236,77,31,27,198,178,204,48,180,105,72, 177,92,59,62,242,138,213,155,15,1,105,231,182,217,210,182,111,51,31,29,2,11,78, 83,216,38,60,196,105,61,8,166,91,211,49,57,31,6,34,171,37,185,147,175,229,195, 61,0,107,222,108,146,177,219,199,61,226,142,134,228,202,234,105,191,169,87,107, 246,108,23,52,15,213,178,35,211,86,135,55,183,230,198,181,85,193,245,189,250, 234,103,58,195,183,93,36,126,174,195,235,74,189,37,179,100,78,246,249,159,208, 216,88,10,165,238,1,56,45,200,91,38,115,23,100,60,120,168,219,106,196,143,103, 106,126,73,244,92,139,215,171,41,107,184,134,143,0,24,34,233,143,116,161,191, 255,11,251,5,40,224,128,4,6,24,128,117,198,0,254,16,128,4,82,52,232,224,131,16, 70,40,225,132,16,74,128,224,16,61,68,64,225,134,28,118,8,33,21,199,217,215,195, 0,30,150,104,226,132,99,132,56,67,15,1,104,248,32,6,48,62,120,193,137,52,98, 192,160,20,7,214,215,16,15,46,54,136,65,3,12,36,160,0,2,20,76,128,0,144,61,122, 120,65,3,9,84,112,227,139,8,28,144,0,3,10,56,41,133,4,57,182,183,98,15,16,60,88, 129,2,11,20,48,193,2,11,8,73,38,3,17,60,217,33,2,103,166,9,33,6,19,48,64,166,2, 110,74,145,162,150,27,241,64,226,131,114,162,201,166,2,14,200,185,64,3,117,118, 120,193,1,115,66,160,166,131,9,144,153,64,161,98,92,104,15,139,139,82,64,38,2, 16,68,48,1,5,16,128,25,38,164,28,126,57,36,168,82,92,32,40,166,139,102,137,39, 76,25,202,40,232,3,105,74,32,65,5,115,58,32,43,141,18,144,42,5,173,11,0,10,42, 150,58,62,197,67,151,47,38,170,225,140,108,150,169,40,174,183,74,152,172,2,138, 46,58,133,164,42,254,68,225,96,5,19,52,112,38,2,19,220,216,232,2,168,74,128,65, 145,7,80,192,32,156,155,58,152,65,5,69,54,43,5,5,9,36,48,193,183,13,44,27,225, 48,42,10,11,192,158,14,206,235,169,2,65,106,136,129,167,176,86,32,40,153,182, 90,128,232,160,26,82,224,233,160,79,98,208,232,144,7,23,96,111,132,170,202,224, 131,180,22,152,74,166,197,178,74,96,105,175,209,122,188,0,154,12,10,58,65,154, 23,12,76,230,202,231,202,233,235,152,189,218,202,177,20,17,100,105,144,158,18, 186,188,128,3,246,46,92,47,131,38,31,160,40,175,63,187,233,51,172,82,124,91,64, 154,52,51,144,233,134,22,246,101,109,132,35,51,96,179,20,130,62,205,32,175,10, 192,122,65,178,82,19,157,245,212,52,39,144,169,4,218,46,96,244,205,14,226,187, 234,125,20,38,171,246,141,24,144,249,243,178,81,71,43,232,219,82,180,253,54,6, 42,47,75,176,174,16,234,204,42,15,27,126,139,64,157,125,223,40,184,162,35,47,0, 235,141,93,67,109,172,5,35,67,235,238,134,254,146,250,144,100,132,135,75,78,38, 224,25,148,254,45,180,46,130,237,128,134,223,222,205,182,163,203,194,237,224, 157,62,177,184,97,222,100,70,219,177,167,94,115,158,168,4,19,120,58,180,20,125, 71,112,129,167,143,139,203,252,197,29,202,109,20,15,11,110,120,118,235,181,62, 112,128,5,52,215,27,168,227,16,32,192,224,228,13,60,160,55,200,109,91,94,0,5,38, 2,59,142,238,28,78,126,35,205,128,54,57,187,219,129,82,208,117,3,221,90,0,252, 1,7,144,128,167,140,118,36,48,133,13,101,237,59,141,15,136,213,184,143,65,78, 111,10,40,128,172,210,55,36,1,206,233,81,12,122,24,6,41,152,0,243,205,233,1,159, 235,16,238,234,48,162,14,185,204,115,13,50,216,201,130,247,165,147,193,12,81,10, 120,27,131,254,212,128,215,137,75,91,10,168,87,4,26,197,128,203,209,104,18,82, 185,218,134,120,165,67,7,229,42,86,13,58,34,18,143,232,174,92,133,236,74,76,12, 89,4,88,246,67,11,232,140,82,20,194,128,147,46,64,51,31,62,232,86,79,122,148, 226,141,158,104,196,207,49,72,2,51,234,216,25,171,104,129,170,253,32,0,27,146, 147,248,26,37,59,54,218,241,142,86,36,2,28,41,68,166,6,208,202,87,182,195,163, 32,39,164,42,234,109,8,1,10,152,82,15,17,55,200,70,74,168,144,10,226,144,3,40, 96,195,16,58,242,146,247,210,99,135,66,22,72,76,98,18,146,0,128,158,39,71,121, 34,9,224,238,141,1,72,165,42,87,201,202,86,186,242,149,176,140,165,44,103,201, 202,31,144,176,9,184,204,165,46,119,201,203,94,246,82,36,190,12,166,48,135,73, 76,34,76,175,152,200,76,102,49,75,16,2,0,33,249,4,5,10,0,31,0,44,30,0,4,0,38,0, 57,0,0,5,254,224,39,142,31,96,158,104,170,2,100,235,174,112,236,206,174,103, 223,56,158,210,60,205,113,185,91,111,152,201,136,56,25,100,50,232,25,246,126,71, 227,143,233,57,57,121,72,13,105,169,51,93,105,154,204,141,243,225,222,172,95, 151,70,227,209,126,128,65,116,186,85,92,127,168,115,44,156,218,204,147,236,111, 100,83,113,94,126,128,69,101,98,132,44,115,124,124,114,126,45,123,57,145,88,102, 56,149,60,110,153,156,157,158,159,160,161,162,149,142,120,145,165,76,164,168, 148,167,171,152,173,174,54,170,177,125,126,180,178,176,177,179,76,28,107,26,100, 163,34,97,69,69,192,162,74,196,197,163,201,201,155,160,204,196,206,159,208,117, 163,195,204,198,160,200,209,66,161,189,35,147,184,78,183,169,227,228,229,78,189, 191,231,226,62,208,225,186,154,208,108,231,150,212,240,174,238,247,236,181,36, 219,201,217,60,253,35,22,80,224,187,96,111,0,130,226,199,176,161,67,90,219,128, 61,196,49,144,204,68,27,3,139,93,244,144,49,137,175,143,32,67,138,244,149,225, 130,201,147,38,3,51,132,0,0,33,249,4,5,10,0,31,0,44,34,0,7,0,34,0,54,0,0,5,202, 224,39,138,94,105,158,168,57,174,236,154,190,104,43,143,112,237,205,179,13,227, 178,254,242,45,95,10,200,18,198,136,52,163,10,73,82,150,152,77,39,116,74,141,42, 167,206,39,52,123,171,122,191,224,176,120,76,46,155,207,232,244,151,195,230,156, 57,154,140,60,227,94,107,52,245,185,190,62,229,232,229,113,127,114,85,129,130, 134,83,1,126,130,23,134,25,136,138,127,140,135,80,137,141,134,124,76,144,127, 112,43,28,90,80,154,114,158,30,109,163,93,125,123,58,72,92,75,64,172,39,106,177, 76,175,63,69,175,112,119,152,46,172,133,162,61,92,161,190,182,89,141,26,65,92, 197,199,196,134,198,195,78,189,115,186,31,172,193,205,100,112,209,68,144,120, 102,208,116,180,90,193,25,26,224,93,222,114,229,34,231,25,233,31,25,23,240,241, 240,119,244,245,246,247,244,33,0,33,249,4,5,10,0,31,0,44,36,0,13,0,26,0,48,0,0, 5,196,224,39,138,156,102,114,99,170,174,100,230,186,26,43,143,220,107,163,243, 26,104,182,157,235,188,158,235,167,218,9,135,196,84,77,24,75,166,130,55,167, 106,153,209,224,164,88,44,103,123,205,150,162,217,207,177,155,164,246,178,208, 51,54,237,211,30,51,225,177,103,78,247,252,190,175,79,189,46,219,115,57,123, 124,44,129,132,123,125,133,136,42,0,139,136,137,41,139,0,141,30,93,100,31,144, 141,102,46,28,1,131,133,98,71,14,157,132,153,47,26,156,41,152,111,149,57,164, 154,104,76,97,164,171,101,39,78,84,86,97,31,108,25,128,146,83,71,26,146,118,79, 111,194,42,187,46,198,196,71,202,52,114,190,191,54,193,205,74,38,86,194,216,217, 218,219,136,102,171,194,178,43,146,173,188,42,227,170,199,214,234,214,25,23,238, 239,238,112,41,33,0,33,249,4,5,10,0,31,0,44,38,0,5,0,21,0,56,0,0,5,232,224,39, 142,80,52,158,104,202,101,25,151,190,98,166,105,172,11,167,44,171,125,156,125, 139,171,26,173,245,27,245,56,195,93,17,185,11,250,96,131,97,203,89,20,205,106, 181,170,199,99,67,102,127,219,174,231,11,3,132,129,231,159,57,204,217,186,223, 111,145,185,7,175,199,81,109,207,76,249,91,105,182,82,79,48,109,121,71,85,64,68, 135,39,52,127,112,76,26,130,136,132,133,57,58,47,121,34,92,149,57,28,1,153,118, 122,155,57,3,159,118,82,155,164,31,160,161,162,25,169,171,65,155,26,175,171,167, 53,158,170,171,154,58,79,186,160,138,192,193,194,39,190,118,55,73,160,0,0,120, 162,121,111,2,56,173,117,27,203,70,173,45,117,204,173,206,110,218,205,198,39, 215,191,39,177,156,197,110,73,96,231,235,117,71,189,190,167,124,240,162,74,186, 229,149,46,246,215,249,176,251,185,160,247,56,85,177,37,67,81,188,17,231,220,17, 99,199,176,225,186,61,16,35,74,220,19,2,0,59}; static Fl_Image *image_fluid() { Fl_GIF_Image::animate = true; static Fl_Image *image = NULL; if (!image) image = new Fl_Anim_GIF_Image("fluid.animated.gif", idata_fluid, 2545); return image; } static void cb_View(Fl_Button*, void*) { show_help("license.html"); } static void cb_Close(Fl_Return_Button* o, void*) { ((Fl_Window*)(o->parent()))->hide(); } Fl_Double_Window* make_about_panel() { static char cbuf[200] = ""; if (!cbuf[0]) { time_t t = time(0); struct tm *lt = localtime(&t); sprintf(cbuf, "Copyright © 1998 - %d\nby Bill Spitzak and others", lt->tm_year+1900); } { about_panel = new Fl_Double_Window(345, 180, "About FLUID"); about_panel->color(FL_LIGHT1); about_panel->selection_color(FL_DARK1); about_panel->hotspot(about_panel); { Fl_Box* o = new Fl_Box(10, 10, 115, 120); o->image( image_fluid() ); ((Fl_Anim_GIF_Image*)(image_fluid()))->canvas(o, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS); ((Fl_Anim_GIF_Image*)(o->image()))->speed(0.5f); } // Fl_Box* o { Fl_Box* o = new Fl_Box(135, 10, 205, 75, "FLTK User\nInterface Designer\nVersion x.x.x"); o->color((Fl_Color)12); o->selection_color(FL_DARK1); o->labelfont(1); o->labelsize(18); o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE)); char about[80]; // uses less than 60 snprintf(about,sizeof(about),"FLTK User\nInterface Designer\nVersion %d.%d.%d",FL_MAJOR_VERSION,FL_MINOR_VERSION,FL_PATCH_VERSION); o->copy_label(about); } // Fl_Box* o { // Label edited dynamically: Fl_Box* o = new Fl_Box(135, 90, 200, 45, "(Copyright)"); o->align(Fl_Align(132|FL_ALIGN_INSIDE)); o->label(cbuf); } // Fl_Box* o { Fl_Button* o = new Fl_Button(115, 145, 123, 25, "View License..."); o->labelcolor(FL_DARK_BLUE); o->callback((Fl_Callback*)cb_View); } // Fl_Button* o { Fl_Return_Button* o = new Fl_Return_Button(250, 145, 83, 25, "Close"); o->callback((Fl_Callback*)cb_Close); } // Fl_Return_Button* o about_panel->set_non_modal(); about_panel->end(); } // Fl_Double_Window* about_panel return about_panel; } /** Embedded image for internal fluid.html web page. */ unsigned char fluid_flow_chart_800_png[41559] = /* data inlined from documentation/src/fluid_flow_chart_800.png */ {137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,3,32,0,0,1,41,8,6,0,0,0, 107,224,70,137,0,0,1,110,105,67,67,80,105,99,99,0,0,40,145,117,145,187,75,195, 80,20,198,127,173,79,172,226,160,131,136,67,6,149,14,22,124,128,56,106,29,92, 138,72,85,176,234,210,196,180,21,210,26,146,20,17,87,193,197,65,112,16,93,124, 13,254,7,186,10,174,10,130,160,8,34,110,238,190,22,41,241,92,83,104,17,189,225, 230,252,248,238,253,14,39,95,32,156,176,140,188,91,59,10,249,130,231,36,39,226, 218,92,106,94,107,120,33,66,61,109,68,25,72,27,174,61,54,53,149,224,223,245,121, 71,72,213,219,152,234,245,255,189,63,87,100,201,116,13,8,53,10,15,27,182,227,9, 203,52,36,86,61,91,241,150,112,187,145,75,47,9,31,10,247,57,50,160,240,149,210, 245,128,159,21,103,3,126,87,236,204,36,199,33,172,122,106,217,42,214,171,216, 200,57,121,225,168,112,119,222,42,26,229,121,212,151,52,155,133,217,105,169,157, 178,187,112,73,50,65,28,13,157,34,203,88,120,196,164,22,36,179,191,125,253,63, 190,73,86,196,99,200,219,102,13,71,28,89,114,226,237,19,181,40,93,77,169,25,209, 77,121,44,214,84,238,191,243,116,51,67,131,65,247,230,56,212,61,249,254,91,15, 52,236,64,105,219,247,191,142,124,191,116,12,53,143,112,81,168,248,87,36,167, 145,15,209,183,43,90,247,1,180,110,192,217,101,69,211,119,225,124,19,58,30,236, 180,147,254,145,106,100,135,51,25,120,61,133,150,20,180,221,64,211,66,144,85, 249,156,147,123,152,89,151,95,116,13,123,251,208,43,247,91,23,191,1,66,94,104, 40,91,243,153,39,0,0,0,9,112,72,89,115,0,0,11,17,0,0,11,17,1,127,100,95,145,0, 0,0,163,116,69,88,116,82,97,119,32,112,114,111,102,105,108,101,32,116,121,112, 101,32,101,120,105,102,0,10,101,120,105,102,10,32,32,32,32,32,32,54,50,10,52,53, 55,56,54,57,54,54,48,48,48,48,52,57,52,57,50,97,48,48,48,56,48,48,48,48,48,48, 48,49,48,48,54,57,56,55,48,52,48,48,48,49,48,48,48,48,48,48,49,97,48,48,48,48, 48,48,48,48,48,48,48,48,48,48,48,50,48,48,48,50,97,48,10,48,52,48,48,48,49,48, 48,48,48,48,48,102,54,48,54,48,48,48,48,48,51,97,48,48,52,48,48,48,49,48,48,48, 48,48,48,57,54,48,50,48,48,48,48,48,48,48,48,48,48,48,48,10,88,22,108,60,0,0,0, 90,116,69,88,116,82,97,119,32,112,114,111,102,105,108,101,32,116,121,112,101, 32,105,112,116,99,0,10,105,112,116,99,10,32,32,32,32,32,32,50,54,10,53,48,54, 56,54,102,55,52,54,102,55,51,54,56,54,102,55,48,50,48,51,51,50,101,51,48,48,48, 51,56,52,50,52,57,52,100,48,52,48,52,48,48,48,48,48,48,48,48,48,48,48,48,10, 199,209,105,220,0,0,19,85,116,69,88,116,82,97,119,32,112,114,111,102,105,108, 101,32,116,121,112,101,32,120,109,112,0,10,120,109,112,10,32,32,32,32,50,52,50, 51,10,51,99,51,102,55,56,55,48,54,49,54,51,54,98,54,53,55,52,50,48,54,50,54,53, 54,55,54,57,54,101,51,100,50,50,101,102,98,98,98,102,50,50,50,48,54,57,54,52, 51,100,50,50,53,55,51,53,52,100,51,48,52,100,55,48,52,51,54,53,54,56,54,57,10, 52,56,55,97,55,50,54,53,53,51,55,97,52,101,53,52,54,51,55,97,54,98,54,51,51,57, 54,52,50,50,51,102,51,101,48,97,51,99,55,56,51,97,55,56,54,100,55,48,54,100,54, 53,55,52,54,49,50,48,55,56,54,100,54,99,54,101,55,51,51,97,55,56,10,51,100,50, 50,54,49,54,52,54,102,54,50,54,53,51,97,54,101,55,51,51,97,54,100,54,53,55,52, 54,49,50,102,50,50,50,48,55,56,51,97,55,56,54,100,55,48,55,52,54,98,51,100,50, 50,53,56,52,100,53,48,50,48,52,51,54,102,55,50,54,53,50,48,10,51,52,50,101,51, 52,50,101,51,48,50,100,52,53,55,56,54,57,55,54,51,50,50,50,51,101,48,97,50,48, 51,99,55,50,54,52,54,54,51,97,53,50,52,52,52,54,50,48,55,56,54,100,54,99,54, 101,55,51,51,97,55,50,54,52,54,54,51,100,50,50,54,56,10,55,52,55,52,55,48,51,97, 50,102,50,102,55,55,55,55,55,55,50,101,55,55,51,51,50,101,54,102,55,50,54,55, 50,102,51,49,51,57,51,57,51,57,50,102,51,48,51,50,50,102,51,50,51,50,50,100,55, 50,54,52,54,54,50,100,55,51,55,57,54,101,55,52,10,54,49,55,56,50,100,54,101,55, 51,50,51,50,50,51,101,48,97,50,48,50,48,51,99,55,50,54,52,54,54,51,97,52,52,54, 53,55,51,54,51,55,50,54,57,55,48,55,52,54,57,54,102,54,101,50,48,55,50,54,52, 54,54,51,97,54,49,54,50,54,102,55,53,10,55,52,51,100,50,50,50,50,48,97,50,48, 50,48,50,48,50,48,55,56,54,100,54,99,54,101,55,51,51,97,54,53,55,56,54,57,54, 54,51,100,50,50,54,56,55,52,55,52,55,48,51,97,50,102,50,102,54,101,55,51,50, 101,54,49,54,52,54,102,54,50,54,53,10,50,101,54,51,54,102,54,100,50,102,54,53, 55,56,54,57,54,54,50,102,51,49,50,101,51,48,50,102,50,50,48,97,50,48,50,48,50, 48,54,53,55,56,54,57,54,54,51,97,53,48,54,57,55,56,54,53,54,99,53,56,52,52,54, 57,54,100,54,53,54,101,55,51,10,54,57,54,102,54,101,51,100,50,50,51,49,51,55, 51,56,51,50,50,50,48,97,50,48,50,48,50,48,54,53,55,56,54,57,54,54,51,97,53,48, 54,57,55,56,54,53,54,99,53,57,52,52,54,57,54,100,54,53,54,101,55,51,54,57,54, 102,54,101,51,100,50,50,10,51,54,51,54,51,50,50,50,50,102,51,101,48,97,50,48,51, 99,50,102,55,50,54,52,54,54,51,97,53,50,52,52,52,54,51,101,48,97,51,99,50,102, 55,56,51,97,55,56,54,100,55,48,54,100,54,53,55,52,54,49,51,101,48,97,50,48,50, 48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,10,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,48,97,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48, 97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,10,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50, 48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48, 97,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 10,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,48,97,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,51,99,51,102,55,56,55,48,54,49, 54,51,54,98,54,53,10,55,52,50,48,54,53,54,101,54,52,51,100,50,50,55,55,50,50, 51,102,51,101,10,162,250,209,144,0,0,32,0,73,68,65,84,120,94,236,221,7,88,20, 199,251,7,240,57,122,81,20,81,81,236,96,5,197,222,27,246,222,107,108,49,49,150, 159,61,26,141,105,127,53,150,88,18,99,139,189,247,222,123,5,197,216,69,80,172, 128,8,82,21,145,222,217,255,188,43,103,8,65,6,241,238,56,184,239,231,121,230, 185,54,123,28,123,123,59,243,238,52,133,36,73,12,0,0,0,0,0,64,19,244,68,25,0,0, 0,0,0,0,84,5,1,8,0,0,0,0,0,104,12,2,16,0,0,0,0,0,208,24,4,32,0,0,0,0,0,160,49, 8,64,0,0,0,0,0,64,99,12,68,25,136,66,161,16,101,1,0,0,80,185,62,125,250,212, 113,117,117,181,141,140,140,180,138,139,139,43,204,159,42,196,147,5,79,5,120,50, 79,75,102,105,201,148,39,227,116,201,40,237,214,144,189,47,239,242,122,97,150, 202,83,18,79,137,105,41,33,237,54,62,45,197,241,20,147,118,27,157,118,63,138, 167,72,61,61,189,119,133,10,21,10,183,182,182,14,155,50,101,202,173,81,163,70, 133,102,246,7,0,0,62,87,118,102,216,85,100,43,19,2,16,0,0,208,160,211,167,79, 151,92,185,114,229,239,215,174,93,235,245,238,221,59,83,19,19,19,102,96,144,173, 107,102,144,9,42,235,227,227,227,89,106,106,42,179,181,181,125,209,183,111,223, 5,220,122,94,190,139,43,1,0,0,159,32,59,177,5,206,230,0,0,160,85,60,60,60,204, 126,252,241,199,109,231,207,159,111,91,170,84,41,246,195,15,63,176,142,29,59,50, 75,75,75,209,166,240,17,41,41,41,236,233,211,167,108,235,214,173,108,223,190, 125,21,118,238,220,185,150,7,35,177,252,165,29,162,109,1,0,84,142,162,20,81,2,0, 0,208,148,62,156,169,169,169,100,103,103,39,185,187,187,75,160,58,60,232,144, 126,251,237,55,42,216,37,91,91,91,247,213,171,87,23,22,125,31,0,0,159,66,202,78, 108,33,202,32,33,0,1,0,0,13,178,176,176,248,75,95,95,95,58,120,240,96,198,250, 51,168,0,5,33,157,58,117,146,244,244,244,82,120,144,87,67,244,125,0,0,124,10, 41,27,177,5,102,193,2,0,0,173,18,25,25,105,92,161,66,5,214,174,93,59,81,86,200, 1,26,215,57,120,240,96,26,15,34,133,134,134,154,137,242,3,0,168,26,2,16,0,0, 208,26,134,134,134,52,235,137,169,149,149,21,43,88,176,160,40,59,228,80,185,114, 229,232,70,17,29,29,141,0,4,0,52,14,1,8,0,0,104,141,148,148,20,125,126,99,130, 217,23,213,43,109,255,210,76,152,166,162,188,0,0,170,134,89,176,0,0,64,107,164, 166,166,210,133,49,99,9,227,15,53,129,162,16,19,81,38,0,128,79,145,157,11,72, 104,1,1,0,0,109,66,229,146,145,40,19,168,140,177,40,3,0,128,170,33,0,1,0,0,109, 34,183,128,100,231,10,26,168,4,130,61,0,208,56,4,32,0,0,160,77,168,92,50,20, 101,2,149,65,11,8,0,104,28,2,16,0,0,208,38,212,244,129,0,68,115,176,175,1,64, 227,16,128,0,0,128,54,65,11,136,102,161,5,4,0,52,14,1,8,0,0,104,19,4,32,154,133, 125,13,0,26,135,0,4,0,0,180,9,117,193,194,20,241,154,131,125,13,0,26,135,0,4,0, 0,180,9,2,16,205,194,190,6,0,141,67,0,2,0,0,218,4,1,136,102,97,95,3,128,198, 225,196,3,0,249,218,205,155,55,205,198,142,29,235,228,230,230,86,128,63,52,72, 77,77,165,62,239,148,104,240,45,173,129,96,146,118,223,36,195,125,229,235,198, 233,238,231,214,57,51,133,167,228,116,183,148,146,210,221,38,166,165,132,116,41, 78,161,80,196,25,27,27,199,154,153,153,197,244,238,221,219,107,195,134,13,55, 50,125,119,237,66,1,136,190,40,19,168,12,246,53,0,104,92,110,21,166,0,0,106,37, 73,146,105,175,94,189,90,245,235,215,239,151,224,224,224,70,252,49,43,88,176, 32,51,52,212,173,49,183,137,137,137,236,237,219,183,236,228,201,147,113,3,7,14, 252,118,247,238,221,107,181,124,145,63,4,32,154,133,122,0,0,104,28,78,60,0,144, 47,141,26,53,106,220,141,27,55,22,240,224,67,191,75,151,46,108,240,224,193,172, 102,205,154,204,202,202,138,233,233,233,70,239,211,212,212,84,22,18,18,194,14, 29,58,196,230,207,159,111,122,229,202,149,49,60,237,224,47,197,136,182,205,69, 8,64,52,11,245,0,0,208,60,186,42,40,74,0,0,121,201,136,17,35,90,91,90,90,70, 152,152,152,72,155,55,111,150,82,82,82,36,93,215,188,121,115,201,208,208,240, 109,187,118,237,236,68,251,47,151,149,224,233,77,163,70,141,68,255,18,124,6,87, 87,87,42,220,41,45,21,124,31,0,0,42,167,27,151,1,1,64,103,220,184,113,195,248, 234,213,171,179,35,34,34,44,22,44,88,192,134,15,31,174,51,45,30,31,147,156,156, 204,120,16,70,251,33,186,80,161,66,241,162,252,90,64,171,251,136,229,51,216,215, 0,160,113,186,93,42,3,64,190,243,219,111,191,181,241,243,243,107,220,162,69, 11,234,134,37,202,174,19,188,189,189,153,167,167,39,5,32,207,86,173,90,21,34, 202,15,0,0,160,78,8,64,0,32,95,225,149,237,225,241,241,241,250,95,126,249,37,51, 53,53,21,101,215,9,167,79,159,102,17,17,17,204,214,214,214,189,120,241,226,201, 162,252,0,0,0,234,132,0,4,0,242,141,153,51,103,150,11,8,8,104,93,182,108,89,214, 181,107,87,81,118,157,16,19,19,195,118,239,222,205,204,205,205,83,235,212,169, 115,80,148,31,0,0,64,221,16,128,0,64,190,113,231,206,157,161,225,225,225,86,61, 122,244,96,69,139,22,21,101,215,9,183,110,221,98,119,239,222,101,214,214,214, 183,182,109,219,230,38,202,15,0,0,160,110,8,64,0,32,95,152,55,111,158,177,135, 135,71,7,35,35,35,54,112,224,64,81,118,157,177,119,239,94,249,214,202,202,106,3, 45,76,40,200,14,0,0,160,118,8,64,0,32,95,184,121,243,166,67,112,112,112,195, 250,245,235,179,186,117,235,138,178,235,132,160,160,32,118,226,196,9,90,128,241, 205,144,33,67,206,137,242,3,0,0,104,2,2,16,0,200,243,36,73,82,4,4,4,12,79,74,74, 50,236,219,183,47,51,54,54,22,109,162,19,206,159,63,207,248,126,97,14,14,14, 247,38,77,154,228,47,202,15,0,0,160,9,8,64,0,32,207,91,176,96,65,17,127,127,255, 62,150,150,150,140,198,127,0,147,215,253,160,193,231,10,133,34,169,92,185,114, 127,137,242,3,0,0,104,10,2,16,0,200,211,36,73,98,174,174,174,61,222,188,121,83, 162,67,135,14,172,66,133,10,162,77,116,194,131,7,15,216,213,171,87,89,217,178, 101,95,180,104,209,226,162,40,63,0,0,128,166,32,0,1,128,188,78,241,234,213,171, 17,10,133,66,111,208,160,65,162,188,58,227,224,193,131,52,5,175,84,170,84,169, 29,99,198,140,137,17,229,7,0,0,208,20,4,32,0,144,167,141,26,53,170,154,143,143, 143,131,173,173,45,115,114,114,18,101,215,9,209,209,209,114,0,82,160,64,129,56, 27,27,155,221,162,252,0,0,0,154,132,0,4,0,242,180,219,183,111,119,137,138,138, 42,212,191,127,127,154,237,73,148,93,39,92,185,114,133,61,126,252,152,241,224, 227,218,254,253,251,125,69,249,1,0,0,52,9,1,8,0,228,89,59,118,236,176,124,251, 246,237,87,230,230,230,140,102,191,130,247,99,98,118,238,220,201,244,245,245,89, 195,134,13,143,43,20,138,100,209,54,0,0,0,154,132,0,4,0,242,172,109,219,182,213, 9,13,13,173,214,162,69,11,86,189,122,117,81,118,157,224,235,235,203,206,156, 57,195,44,44,44,124,235,215,175,191,71,148,31,0,0,64,211,16,128,0,64,158,245, 252,249,243,1,241,241,241,108,192,128,1,204,192,192,64,148,93,39,28,63,126,156, 189,125,251,150,85,174,92,249,226,196,137,19,95,139,242,3,0,0,104,26,2,16,0,200, 147,166,76,153,82,252,205,155,55,157,75,151,46,205,58,118,236,40,202,174,19,40, 24,219,179,103,15,13,62,151,26,54,108,120,72,148,31,0,0,32,55,32,0,1,128,60, 233,238,221,187,253,163,162,162,74,117,237,218,149,89,91,91,139,178,235,132,219, 183,111,179,59,119,238,48,30,148,61,250,253,247,223,175,136,242,3,0,0,228,6,4, 32,0,144,231,172,92,185,210,216,219,219,187,183,161,161,33,195,218,31,255,216, 191,127,191,188,2,186,141,141,205,54,35,35,163,104,81,126,0,0,128,220,128,0,4,0, 180,142,191,191,191,105,86,175,223,187,119,175,197,155,55,111,154,214,174,93, 155,213,175,95,63,171,172,185,38,57,89,179,147,79,133,132,132,176,163,71,143,50, 75,75,203,136,158,61,123,158,16,229,207,77,15,31,62,52,146,36,9,229,15,0,128, 142,66,1,0,0,90,199,221,221,189,205,215,95,127,61,110,193,130,5,153,46,236,113, 235,214,173,118,241,241,241,70,253,250,245,99,38,38,38,153,101,201,53,175,95, 191,102,255,251,223,255,216,190,125,251,228,233,112,105,70,42,63,63,63,246,251, 239,191,203,173,19,234,114,233,210,37,249,239,240,0,228,212,132,9,19,30,137,242, 231,38,125,125,253,178,191,254,250,235,98,254,57,237,69,121,243,139,216,216,88, 54,107,214,44,22,20,20,196,46,95,190,204,182,111,223,46,218,4,0,32,223,66,0,2, 0,90,231,229,203,151,87,220,220,220,198,46,91,182,204,181,91,183,110,35,188, 189,189,63,4,34,51,102,204,48,9,12,12,236,85,184,112,97,214,187,119,239,172,222, 38,87,92,187,118,141,174,240,203,171,178,151,43,87,142,186,67,49,254,121,229, 217,169,82,83,83,69,155,231,8,189,239,182,109,219,152,66,161,72,169,87,175,222, 65,126,43,218,36,87,149,44,89,210,251,209,163,71,150,251,247,239,191,222,190, 125,251,229,139,23,47,174,44,218,38,175,163,117,89,104,170,104,90,179,198,195, 195,131,93,189,122,85,180,9,0,64,190,133,0,4,0,180,206,184,113,227,34,107,213, 170,181,32,34,34,194,241,194,133,11,27,218,181,107,119,165,123,247,238,223,196, 197,197,89,132,133,133,125,29,21,21,85,158,63,199,108,109,109,69,111,149,45,49, 49,49,236,143,63,254,144,167,243,253,229,151,95,216,187,119,239,216,161,67,135, 104,161,67,249,117,90,91,131,90,48,220,221,221,217,252,249,243,229,215,201,95, 127,253,37,15,252,86,10,13,13,149,3,129,200,200,72,230,229,229,197,18,18,18,88, 98,98,162,92,249,164,150,26,10,12,232,241,134,13,27,216,136,17,35,216,130,5,11, 88,120,120,120,166,159,233,83,208,170,231,84,161,229,251,35,136,7,108,46,162, 252,185,141,7,143,82,143,30,61,22,154,154,154,74,252,251,157,176,124,249,242,27, 20,136,240,239,160,26,15,216,146,120,22,73,244,30,170,116,243,230,77,54,106, 212,40,54,108,216,48,118,246,236,89,249,57,250,142,231,205,155,39,31,19,115,230, 204,145,167,54,166,239,110,197,138,21,242,177,49,97,194,4,182,110,221,58,118, 253,250,117,54,126,252,120,246,253,247,223,203,173,95,252,216,100,171,87,175, 150,91,192,70,142,28,201,22,45,90,196,162,163,163,153,158,158,158,124,156,81,43, 24,141,93,50,50,50,146,255,206,147,39,79,216,244,233,211,229,86,179,243,231, 207,103,245,49,1,0,242,13,4,32,0,160,54,6,6,6,116,142,161,5,58,140,121,162,113, 29,5,120,178,224,201,82,148,120,176,113,185,108,217,178,158,252,150,249,248, 248,212,226,149,179,245,13,27,54,188,251,232,209,163,37,146,36,25,124,241,197, 23,153,253,201,79,70,43,135,83,69,243,239,191,255,102,99,199,142,165,191,197, 126,251,237,55,86,177,98,69,57,216,112,117,117,101,63,255,252,51,227,193,144, 252,28,205,50,69,193,202,225,195,135,217,174,93,187,88,153,50,101,62,188,87,129, 2,5,88,149,42,85,228,86,143,242,229,203,203,99,50,104,123,90,163,132,254,14,5, 34,75,150,44,97,23,47,94,148,43,187,20,176,80,69,246,115,199,139,28,60,120,80, 174,220,86,168,80,225,218,119,223,125,71,205,44,194,253,155,219,105,208,160,65, 193,85,171,86,61,68,251,196,223,223,223,242,210,165,75,19,150,46,93,234,202,247, 231,18,246,254,152,209,136,231,207,159,203,223,123,147,38,77,24,15,114,229,64, 226,217,179,103,242,119,78,221,165,166,76,153,34,183,96,77,157,58,149,209,177, 72,1,197,233,211,167,229,169,159,255,252,243,79,185,91,21,5,195,158,158,158, 108,213,170,85,242,84,200,63,253,244,19,115,113,113,97,212,69,144,90,196,232,56, 74,74,74,98,107,215,174,149,131,20,10,70,232,152,120,243,230,13,5,219,204,206, 206,142,209,108,110,51,103,206,100,231,206,157,19,125,100,85,163,223,166,240, 251,74,75,133,120,162,214,72,51,158,168,239,35,69,81,250,252,119,170,221,77,110, 0,160,117,52,118,146,7,128,252,141,87,196,106,159,57,115,166,175,175,175,175, 69,241,226,197,13,121,133,56,153,87,198,140,121,197,203,132,87,176,141,121,162, 91,211,148,148,20,19,158,140,233,74,176,68,181,242,143,216,179,103,79,10,175, 208,23,87,62,166,202,159,135,135,71,69,186,95,185,114,101,214,170,85,171,143, 109,250,73,232,74,55,85,40,215,175,95,207,234,213,171,199,170,85,171,198,30,60, 120,192,28,29,29,229,43,219,116,5,188,65,131,6,236,199,31,127,100,166,166,166, 108,241,226,197,172,79,159,62,242,122,27,91,183,110,101,37,74,148,248,240,94, 102,102,102,172,70,141,26,242,213,114,94,41,147,3,14,229,2,137,116,159,158,63, 112,224,128,124,181,155,174,128,55,107,214,140,241,128,65,110,97,161,224,38,39, 40,240,160,217,175,44,45,45,89,112,112,112,187,196,196,196,235,252,62,237,218, 84,46,253,45,221,145,248,119,144,156,182,219,165,12,183,25,239,171,29,15,58,44, 148,247,41,8,227,129,72,17,254,63,12,163,199,154,234,70,70,93,227,40,0,24,62, 124,184,252,152,31,187,114,96,120,255,254,125,57,200,44,86,172,24,77,107,204, 186,117,235,38,143,177,41,90,180,40,155,52,105,146,220,157,138,142,1,154,4,161, 71,143,30,114,171,215,201,147,39,229,224,130,182,161,64,134,142,1,234,42,56, 121,242,100,249,88,82,182,130,17,106,5,161,96,131,254,111,58,102,104,59,58,6, 246,238,221,203,218,183,111,159,197,39,86,185,158,60,213,206,42,3,125,102,254, 249,244,248,49,156,196,83,60,37,126,92,43,83,2,63,102,18,248,111,50,217,216,216, 216,144,7,109,113,13,27,54,12,236,213,171,215,238,111,190,249,198,63,171,247,5, 0,221,133,0,4,0,62,11,205,102,212,182,109,219,63,14,29,58,52,156,87,188,158, 181,105,211,230,162,131,131,195,83,94,249,122,201,43,36,113,60,0,73,228,129,72, 34,15,32,18,163,162,162,146,120,37,60,145,87,228,18,255,254,251,239,36,126,251, 209,65,17,11,22,44,40,178,123,247,238,139,238,238,238,197,232,113,193,130,5,229, 254,243,188,130,202,250,246,237,43,87,236,84,129,186,199,80,165,187,72,145,34, 242,99,170,128,82,96,64,104,150,45,186,250,77,21,84,10,62,8,181,120,80,75,71,88, 88,152,28,172,100,68,21,202,244,131,205,149,21,122,170,196,209,223,162,138,234, 173,91,183,228,43,239,244,28,181,132,208,251,229,20,181,176,208,152,147,38,77, 154,60,94,189,122,245,232,215,175,95,71,243,125,158,194,3,145,148,132,132,132, 228,180,219,84,190,255,83,120,176,146,226,230,230,22,207,239,75,177,177,177,18, 127,44,209,253,180,199,20,204,72,252,51,74,212,117,76,221,168,133,168,110,221, 186,27,142,29,59,86,149,30,83,160,102,107,107,27,85,170,84,169,163,151,47,95, 238,202,247,155,106,190,96,1,58,158,248,223,252,240,152,190,123,106,229,226,199, 174,124,188,17,250,108,244,93,209,126,161,227,160,80,161,66,242,243,20,68,210, 113,169,164,28,227,67,207,89,89,89,201,247,41,48,164,96,131,94,75,31,220,209, 251,209,223,166,46,120,202,241,65,116,108,81,48,162,97,135,121,154,158,85,6,254, 219,80,240,64,203,128,7,72,70,252,55,110,104,97,97,97,196,131,109,67,30,80,241, 93,96,100,200,3,18,67,126,220,88,60,123,246,172,252,203,151,47,107,241,244,245, 95,127,253,53,133,159,11,126,186,120,241,226,198,172,222,27,0,116,19,2,16,0, 200,177,169,83,167,26,242,74,201,242,74,149,42,13,235,212,169,211,128,133,11,23, 170,108,250,87,94,145,30,238,229,229,101,71,149,64,94,49,245,236,220,185,243,33, 23,23,151,233,188,194,102,76,1,200,231,162,105,107,169,18,72,129,7,85,42,233, 138,55,141,41,161,49,28,52,72,248,215,95,127,149,187,225,208,45,117,165,162,110, 83,188,66,197,150,46,93,42,183,122,80,87,43,106,21,161,113,32,116,245,90,132, 42,152,84,41,165,69,19,249,255,34,95,53,167,150,15,234,150,195,43,116,162,205, 51,69,239,73,221,192,168,117,133,127,166,21,53,107,214,204,51,35,155,215,175, 95,223,112,220,184,113,221,40,88,227,199,80,36,15,70,246,245,238,221,123,197, 204,153,51,95,241,151,59,137,182,87,21,170,240,83,235,23,5,142,212,202,70,99, 115,104,60,8,5,27,212,21,171,86,173,90,242,177,65,65,4,117,173,75,107,185,147, 183,165,219,140,45,70,244,152,186,89,81,43,90,163,70,141,228,174,125,20,212,82, 80,146,62,47,189,15,5,176,244,252,220,185,115,229,239,144,198,142,40,3,93,13, 162,104,51,42,171,12,20,108,211,108,110,217,197,255,79,163,177,99,199,78,229, 251,96,109,229,202,149,245,249,126,92,39,218,6,0,116,11,2,16,0,200,17,106,249, 224,65,199,252,114,229,202,13,227,21,168,238,245,234,213,187,40,218,38,187,78, 156,56,81,124,222,188,121,83,121,197,205,179,69,139,22,171,150,45,91,182,139,87, 10,29,238,220,185,243,83,235,214,173,85,114,149,152,191,167,124,5,155,250,240, 83,159,125,26,16,78,149,44,234,203,79,253,252,151,47,95,46,7,11,52,40,189,66, 133,10,242,56,17,170,36,82,23,42,154,66,149,186,217,208,56,0,218,134,2,10,37, 186,90,78,87,207,9,189,63,85,92,41,64,81,94,81,167,191,69,99,2,46,92,184,32,15, 64,238,217,179,167,220,117,43,39,40,128,225,251,138,130,143,119,195,134,13,187, 64,131,163,243,2,94,161,213,251,254,251,239,103,196,199,199,167,12,28,56,112, 83,191,126,253,150,247,234,213,203,157,186,31,113,212,167,77,51,253,175,56,254, 119,229,174,80,252,115,200,1,29,125,175,45,91,182,100,95,126,249,165,60,62,135, 90,193,40,0,153,49,99,134,28,172,210,247,168,236,70,69,247,233,251,37,233,191, 119,66,199,19,189,23,181,78,209,152,33,58,22,232,117,229,248,15,122,15,26,59,66, 221,188,250,247,239,47,183,148,208,152,19,58,238,52,76,229,251,154,255,111,137, 252,230,183,157,59,119,38,242,223,217,42,30,212,189,219,184,113,227,62,209,118, 0,160,67,148,87,112,178,74,0,0,25,241,74,186,189,163,163,227,219,49,99,198, 168,124,46,92,94,33,236,55,121,242,228,169,188,66,42,55,13,240,243,144,65,227, 198,141,143,208,221,77,155,54,73,170,240,250,245,107,233,205,155,55,31,30,191, 124,249,82,114,118,118,150,2,2,2,228,199,175,94,189,146,187,35,41,249,249,249, 73,33,33,33,82,112,112,240,191,222,131,82,122,180,13,175,96,203,247,223,190, 125,43,69,70,70,82,151,38,121,91,229,88,140,23,47,94,72,60,112,144,120,0,34,125, 14,94,89,165,19,180,212,189,123,119,141,143,92,254,28,252,255,174,186,100,201, 146,117,75,151,46,173,147,201,203,20,128,132,53,106,212,72,244,239,171,12,125, 63,215,175,95,151,110,221,186,37,189,31,34,243,30,15,70,165,147,39,79,202,223, 23,73,73,73,145,120,144,32,37,37,37,201,143,233,248,137,138,138,146,239,211, 247,78,199,2,29,55,60,24,151,124,124,124,164,139,23,47,254,107,91,58,118,104,91, 218,70,121,140,208,99,87,87,87,137,31,243,114,151,56,77,161,191,201,222,207,54, 182,44,147,239,64,101,120,112,254,27,223,31,30,92,206,251,25,2,64,254,35,33,0,1, 128,28,168,93,187,246,88,39,39,167,231,252,28,161,242,150,84,94,57,251,231,82, 50,247,243,207,63,219,89,91,91,71,217,216,216,124,8,16,116,93,98,98,162,212, 162,69,11,201,216,216,56,101,214,172,89,170,153,18,76,67,30,60,120,96,152,197, 203,26,15,64,84,137,2,89,7,7,7,121,92,141,54,211,84,0,178,123,247,110,187,250, 245,235,71,54,107,214,44,203,129,238,0,160,91,196,29,151,1,0,50,17,24,24,104,97, 105,105,233,162,80,40,62,111,14,217,76,88,89,89,125,24,5,205,235,74,116,197,124, 80,72,72,72,129,46,93,186,200,253,240,129,201,235,143,208,250,21,21,43,86,244, 159,58,117,234,113,81,126,109,82,163,70,141,36,81,158,188,138,186,93,81,55,42, 229,236,103,186,110,224,192,129,47,205,204,204,30,241,160,179,144,40,47,0,232, 14,4,32,0,144,35,22,22,22,198,213,170,85,123,42,202,247,185,30,61,122,100,230, 227,227,51,152,42,116,170,90,251,35,63,160,169,119,105,160,180,131,131,195,190, 130,5,11,70,139,242,131,102,208,32,114,26,167,132,0,228,61,186,64,81,169,82,37, 47,125,125,125,116,193,2,128,15,16,128,0,64,142,68,69,69,41,120,16,226,43,202, 247,185,254,250,235,175,70,222,222,222,229,105,224,121,227,198,141,69,217,117,2, 205,178,116,228,200,17,26,184,28,89,179,102,205,205,162,252,0,185,73,79,79,207, 155,159,47,52,62,189,23,0,104,47,4,32,0,144,35,137,137,137,198,10,133,66,237,11, 70,220,185,115,167,91,100,100,164,49,205,82,68,11,185,1,99,206,206,206,242,12, 88,213,170,85,187,251,227,143,63,122,137,242,3,228,166,148,148,148,132,164,164, 36,4,32,0,240,1,2,16,0,200,17,90,209,156,7,33,106,237,203,127,234,212,169,50, 175,95,191,254,130,166,40,165,233,82,225,253,218,31,59,118,236,144,167,127,109, 209,162,197,73,30,4,170,245,59,0,248,92,180,32,38,191,193,213,3,0,248,0,1,8,0, 228,8,175,8,27,165,85,44,212,102,211,166,77,78,129,129,129,214,109,219,182,101, 149,42,85,18,101,215,9,180,56,222,165,75,151,104,245,110,255,214,173,91,239,17, 229,7,200,109,180,222,11,191,49,18,229,3,0,221,129,0,4,0,114,132,7,32,134,234, 12,64,36,73,82,60,120,240,160,95,82,82,18,27,48,96,128,40,187,206,160,193,231, 209,209,209,52,147,212,133,246,237,219,7,136,242,3,228,182,180,243,196,191,166, 214,6,0,221,134,0,4,0,114,132,7,8,106,13,64,126,249,229,151,42,193,193,193,45, 108,109,109,153,147,147,147,40,187,78,136,140,140,148,87,98,167,46,105,109,218, 180,57,44,202,15,160,13,18,19,19,233,60,129,22,16,0,248,0,1,8,0,228,72,90,11,72, 138,40,95,78,221,189,123,119,88,68,68,68,161,158,61,123,178,34,69,138,136,178, 235,132,107,215,174,49,15,15,15,86,181,106,85,175,73,147,38,93,19,229,7,208,6, 60,0,65,23,44,0,248,23,4,32,0,144,35,212,2,146,214,183,91,229,120,69,187,224, 227,199,143,187,25,27,27,99,237,143,52,180,32,227,190,125,251,152,190,190,62, 171,92,185,242,22,133,66,241,86,180,13,128,54,72,72,72,72,101,8,64,0,32,29,4,32, 0,144,35,188,66,108,160,174,0,228,240,225,195,93,131,130,130,170,55,105,210, 132,57,58,58,138,178,235,4,63,63,63,118,250,244,105,90,9,62,186,127,255,254,39, 68,249,1,180,69,90,11,136,161,40,31,0,232,14,4,32,0,144,19,10,10,64,226,226, 226,84,30,128,60,121,242,196,192,197,197,165,43,173,242,61,104,208,32,172,40, 157,230,212,169,83,44,36,36,132,149,43,87,238,84,231,206,157,61,68,249,1,180,69, 90,87,77,252,144,1,224,3,4,32,0,144,35,234,10,64,86,175,94,93,204,219,219,187, 173,181,181,53,235,212,169,147,40,187,78,160,153,192,118,239,222,77,11,49,166, 52,105,210,228,176,66,161,144,68,219,0,104,139,196,196,68,234,130,133,0,4,0,62, 64,0,2,0,57,65,45,32,250,241,241,241,42,175,8,123,121,121,245,13,15,15,47,222, 185,115,103,90,235,66,148,93,39,184,185,185,177,155,55,111,210,224,243,224,113, 227,198,93,18,229,7,208,38,8,64,0,32,35,4,32,0,144,83,250,170,110,1,137,140,140, 52,240,245,245,29,70,3,173,49,248,252,31,52,248,156,87,226,104,60,204,177,178, 101,203,190,22,229,7,208,38,8,64,0,32,35,4,32,0,144,35,212,2,194,3,144,84,81, 190,79,49,114,228,200,58,60,0,169,86,189,122,117,214,188,121,115,81,118,157,16, 26,26,202,14,29,58,196,172,172,172,18,234,214,173,187,9,221,175,32,175,73,74, 74,66,0,2,0,255,130,0,4,0,114,66,238,130,21,27,27,171,210,0,228,209,163,71,117, 249,123,154,211,218,31,38,38,38,162,236,58,225,196,137,19,236,197,139,23,204, 222,222,222,109,226,196,137,15,69,249,1,180,77,90,0,130,250,6,0,124,128,19,2,0, 228,148,158,170,3,144,184,184,184,218,180,246,71,235,214,173,69,89,117,66,96,96, 32,155,55,111,30,43,84,168,16,107,213,170,213,10,133,66,17,47,218,6,64,219,36, 38,38,82,171,157,190,40,31,0,232,14,4,32,0,144,35,18,199,3,6,149,118,7,138,143, 143,47,162,167,167,199,204,205,205,69,89,243,61,47,47,47,54,116,232,80,185,245, 195,209,209,113,239,236,217,179,15,138,182,1,208,70,105,45,32,0,0,31,104,91,159, 76,10,136,20,233,110,51,75,44,147,199,185,69,74,75,233,239,103,150,82,211,221, 2,228,27,209,209,209,42,61,166,43,85,170,244,196,197,197,69,190,234,63,99,198, 12,102,107,107,203,12,13,117,103,253,50,30,208,201,1,199,133,11,23,216,186,117, 235,152,191,191,63,43,93,186,244,62,158,134,43,20,138,4,209,246,249,136,74,3,91, 200,146,218,247,53,2,16,0,200,40,87,2,144,35,71,142,20,90,181,106,85,191,107, 215,174,85,136,141,141,53,147,36,201,148,63,109,146,150,140,50,36,195,180,100, 144,46,233,167,37,186,159,91,173,56,116,66,77,73,75,201,233,110,41,37,241,148, 152,238,150,18,117,157,8,76,187,149,243,215,169,83,39,120,225,194,133,59,219, 181,107,23,243,223,183,7,208,126,169,169,170,173,87,52,107,214,108,79,112,112, 240,224,67,135,14,149,63,115,230,12,43,92,184,48,163,22,17,93,145,156,156,204, 34,34,34,228,64,196,202,202,42,185,85,171,86,187,251,247,239,63,230,127,255, 251,159,46,117,189,194,197,26,205,82,251,190,230,101,188,40,11,0,232,24,141,6, 32,252,36,100,200,11,210,182,211,166,77,251,221,203,203,203,158,78,74,37,75, 150,100,22,22,22,140,166,221,204,239,148,39,97,90,225,153,250,118,123,120,120, 176,95,126,249,165,207,221,187,119,123,212,173,91,87,151,42,24,0,153,154,51,103, 206,195,37,75,150,180,219,189,123,119,31,95,95,223,50,252,119,82,156,253,251,2, 132,126,38,73,239,35,73,19,173,164,230,6,6,6,5,120,224,16,204,178,247,183,168, 178,151,244,177,196,207,131,201,21,42,84,72,182,183,183,127,91,191,126,253,67, 252,252,112,241,242,229,203,89,188,93,190,132,0,68,179,176,175,1,64,243,168,82, 44,74,170,50,116,232,208,46,182,182,182,146,158,158,158,212,179,103,79,233,228, 201,147,82,64,64,128,68,3,212,82,83,83,117,38,69,69,69,73,87,175,94,149,106,212, 168,65,251,34,166,125,251,246,182,162,125,7,160,101,168,226,127,133,167,10,162, 140,185,224,99,221,55,85,154,248,121,75,209,181,107,215,117,60,80,240,228,172, 68,249,211,37,200,26,5,157,65,141,26,53,146,64,125,92,93,93,149,93,132,23,9, 190,15,85,232,197,211,118,81,38,0,208,29,26,235,219,176,96,193,2,199,203,151,47, 111,162,62,205,127,254,249,39,59,112,224,0,163,149,142,109,108,108,228,62,222, 10,133,66,103,82,129,2,5,168,171,137,188,208,26,15,72,76,249,62,169,41,218,127, 0,144,109,89,141,199,82,89,58,118,236,88,141,39,79,158,124,241,232,209,35,251, 173,91,183,14,18,229,79,151,32,107,180,143,112,85,94,115,176,175,1,64,227,52,18, 128,60,126,252,216,224,248,241,227,211,95,189,122,85,124,220,184,113,108,226, 196,137,58,209,229,74,228,245,107,121,65,227,56,99,99,227,23,162,188,0,160,61, 36,73,210,59,112,224,192,20,95,95,223,2,49,49,49,204,217,217,121,194,253,251, 247,139,138,182,131,108,67,165,88,115,176,175,1,64,227,52,18,128,236,217,179, 167,58,15,66,122,80,107,199,180,105,211,68,217,117,2,85,90,168,111,183,161,161, 97,92,106,106,170,175,40,63,0,104,143,163,71,143,214,184,115,231,78,63,26,52, 78,158,60,121,82,105,247,238,221,95,8,54,131,236,65,11,136,102,97,95,3,128,198, 105,36,0,185,116,233,82,151,240,240,240,2,125,250,244,145,187,92,1,99,55,111, 222,100,15,30,60,96,214,214,214,30,195,135,15,199,44,88,0,121,132,36,73,138,189, 123,247,78,244,245,245,53,83,62,23,25,25,201,92,92,92,38,4,4,4,20,206,106,91, 200,54,84,138,53,7,251,26,0,52,78,237,1,200,227,199,143,11,135,134,134,14,49,50, 50,98,67,134,12,17,101,215,25,187,119,239,102,41,41,41,172,102,205,154,39,166, 76,153,146,36,202,15,0,218,97,227,198,141,117,110,220,184,209,159,126,191,180, 66,185,185,185,185,100,106,106,74,179,218,85,90,178,100,201,48,209,246,32,68, 45,32,41,162,76,160,50,201,162,12,0,0,170,166,246,0,228,143,63,254,104,25,20, 20,84,165,65,131,6,172,118,237,218,162,236,58,129,166,224,61,121,242,36,179, 180,180,12,108,221,186,245,1,81,126,0,208,14,110,110,110,138,195,135,15,127,171, 80,40,140,191,250,234,171,131,213,170,85,155,111,96,96,112,108,244,232,209,191, 217,217,217,189,113,118,118,158,116,244,232,209,34,162,247,129,44,161,11,150, 102,97,95,3,128,198,169,125,29,16,15,15,143,94,145,145,145,138,126,253,250,233, 212,138,198,89,161,5,214,120,80,198,170,86,173,122,102,234,212,169,126,162,252, 0,160,53,28,91,181,106,101,242,197,23,95,116,31,60,120,240,25,30,136,244,228, 207,21,91,186,116,233,143,15,31,62,220,201,131,147,41,198,198,198,61,248,115, 155,69,111,4,31,133,22,16,205,66,11,8,0,104,156,90,3,144,197,139,23,91,47,88, 176,160,45,45,54,216,179,103,79,81,118,157,64,131,86,119,237,218,197,120,37,133, 213,173,91,119,223,147,39,79,68,155,0,128,150,48,53,53,125,50,117,234,212,254, 60,240,72,77,235,82,106,196,222,175,137,194,170,87,175,238,201,111,70,188,125, 251,246,195,216,16,200,17,4,32,154,133,125,13,0,26,167,214,46,88,247,238,221,27, 20,17,17,81,170,67,135,14,172,76,153,50,162,236,58,129,86,63,191,122,245,42, 237,15,239,9,19,38,220,17,229,7,0,237,81,181,106,213,4,10,62,178,202,83,164,72, 145,216,172,94,7,33,4,32,154,133,125,13,0,26,167,182,0,36,42,42,202,216,205,205, 173,87,106,106,170,188,224,30,188,71,11,48,38,38,38,210,236,87,155,27,53,106,20, 38,202,15,0,160,99,40,0,65,183,32,205,193,36,40,0,160,113,106,11,64,150,46,93, 218,44,48,48,176,137,163,163,35,107,210,164,137,40,187,78,160,133,7,247,239,223, 207,10,23,46,28,221,172,89,179,99,162,252,0,0,186,70,95,95,95,14,64,36,9,139, 198,171,147,114,255,42,20,10,4,123,0,160,113,106,9,64,104,158,252,43,87,174,208, 224,115,253,222,189,123,179,2,5,10,136,54,209,9,174,174,174,204,203,203,139,89, 89,89,157,95,176,96,193,3,81,126,0,0,93,211,185,115,103,201,196,196,36,37,60, 60,156,197,198,162,55,155,186,208,108,140,164,116,233,210,232,130,5,0,26,167, 150,0,228,231,159,127,182,124,250,244,105,231,130,5,11,50,90,124,16,222,95,109, 162,181,63,244,245,245,83,203,149,43,183,75,161,80,136,54,1,0,208,57,171,86,173, 74,178,181,181,141,241,241,241,97,206,206,206,162,236,144,3,84,30,237,217,179, 135,233,233,233,177,54,109,218,68,138,242,3,0,168,154,90,2,144,135,15,31,182, 246,247,247,47,215,178,101,75,86,173,90,53,81,118,157,240,252,249,115,118,225, 194,5,86,188,120,241,144,9,19,38,92,16,229,7,0,208,69,101,202,148,73,104,212, 168,209,17,154,182,125,198,140,25,242,185,19,84,107,245,234,213,236,216,177,99, 172,82,165,74,47,91,183,110,125,69,148,31,0,64,213,84,62,13,47,47,44,244,135,14, 29,58,134,223,213,163,193,231,184,210,255,30,157,236,169,75,129,147,147,211, 169,94,189,122,189,19,229,7,0,208,85,107,214,172,217,17,28,28,60,244,212,169,83, 13,187,119,239,206,38,79,158,204,120,69,153,198,207,137,54,133,143,160,9,97, 168,11,240,142,29,59,216,250,245,235,169,43,176,212,167,79,159,63,134,13,27,22, 40,218,22,0,64,213,84,30,128,108,223,190,189,60,15,66,234,148,42,85,138,209, 244,187,192,88,124,124,188,60,251,149,145,145,81,66,233,210,165,215,138,242,3,0, 232,50,126,174,140,56,125,250,244,0,125,125,253,45,206,206,206,78,99,198,140,97, 22,22,22,88,204,246,51,69,71,71,179,132,132,4,102,103,103,23,217,187,119,239, 197,243,230,205,91,49,127,254,124,209,102,0,0,42,167,242,0,228,216,177,99,29, 222,189,123,103,57,104,208,32,186,194,34,202,174,19,110,221,186,197,238,222,189, 203,42,84,168,224,54,121,242,100,15,186,2,5,0,249,215,196,137,19,75,62,127,254, 60,213,214,214,214,44,40,40,40,188,112,225,194,101,171,86,173,26,54,125,250, 244,0,209,182,100,209,162,69,150,17,17,17,118,125,251,246,117,175,93,187,118, 150,211,164,86,171,86,205,164,108,217,178,182,103,207,158,125,148,85,190,188, 166,83,167,78,47,37,73,106,63,97,194,132,238,252,252,233,228,230,230,102,18,25, 25,73,17,8,37,90,252,209,32,45,233,103,72,122,31,73,249,165,57,62,53,139,68,51, 90,165,100,72,244,28,29,67,201,165,75,151,78,174,85,171,86,0,63,174,246,15,31, 62,252,209,226,197,139,51,123,127,0,0,181,83,105,0,226,227,227,99,214,174,93, 187,175,232,42,213,128,1,3,68,217,117,6,13,246,163,21,208,235,212,169,115,174, 94,189,122,9,162,252,0,144,119,241,74,179,222,144,33,67,230,151,40,81,194,39, 36,36,164,85,201,146,37,23,233,235,235,47,52,51,51,219,203,95,206,214,229,102, 127,127,255,150,97,97,97,123,151,79,38,3,0,0,32,0,73,68,65,84,163,163,163,203, 241,135,193,89,229,125,252,248,113,233,212,212,212,77,252,110,163,172,242,229, 69,10,133,130,42,206,7,211,18,124,166,87,175,94,201,233,196,137,19,162,172,0,0, 106,165,210,0,228,135,31,126,104,24,26,26,90,167,65,131,6,140,87,180,69,217,117, 2,175,128,200,227,63,138,21,43,246,182,89,179,102,123,246,238,221,43,218,4,0, 242,168,169,83,167,26,180,104,209,162,152,185,185,121,131,82,165,74,121,134,135, 135,219,84,169,82,229,69,245,234,213,15,219,216,216,220,94,177,98,133,147,165, 165,165,201,158,61,123,244,56,51,30,156,156,88,187,118,109,252,246,237,219,203, 237,220,185,211,41,57,57,57,245,255,254,239,255,46,109,222,188,57,57,38,38,38, 37,42,42,170,0,223,102,84,173,90,181,206,242,243,135,223,214,173,91,135,190, 123,247,238,254,164,73,147,30,204,155,55,175,181,167,167,167,45,207,243,218,205, 205,45,145,254,254,165,75,151,140,246,239,223,223,137,7,48,69,29,28,28,206,46, 92,184,240,149,232,51,3,0,0,104,154,202,2,16,90,251,163,73,147,38,131,120,97, 168,215,175,95,63,102,108,108,44,218,68,39,156,57,115,134,5,4,4,80,235,135,203, 248,241,227,159,76,152,48,65,180,9,0,228,81,109,218,180,169,203,207,129,155,110, 223,190,93,209,192,192,96,90,88,88,88,50,15,66,190,222,183,111,95,159,122,245, 234,197,220,189,123,183,106,72,72,200,23,22,22,22,87,120,190,250,207,159,63,95, 126,249,242,229,85,243,231,207,63,199,131,143,119,10,133,162,216,180,105,211, 134,183,110,221,122,45,223,78,242,242,242,42,194,95,95,91,160,64,129,158,60,0, 241,191,126,253,250,242,160,160,160,153,47,94,188,168,201,223,107,77,177,98,197, 110,68,70,70,58,242,96,198,143,159,131,13,58,116,232,240,71,66,66,66,243,194, 133,11,135,156,60,121,114,84,203,150,45,7,185,184,184,120,139,62,55,0,0,128,38, 169,108,26,222,245,235,215,151,14,12,12,236,79,227,62,186,118,237,42,202,254,89, 226,226,226,228,46,77,52,171,71,102,104,144,29,229,161,215,105,190,115,74,41,41, 154,95,107,41,49,49,81,158,113,196,200,200,72,170,85,171,214,14,94,185,192,210, 190,0,249,88,231,206,157,111,250,251,251,47,25,62,124,184,17,191,95,60,38,38, 230,219,191,254,250,107,38,45,202,26,27,27,155,26,17,17,65,231,165,123,167,78, 157,234,50,114,228,200,115,134,134,134,45,151,46,93,218,57,32,32,64,239,210,165, 75,29,198,142,29,219,186,93,187,118,5,138,20,41,82,141,231,75,78,74,74,146,248, 182,137,241,241,241,116,2,83,240,247,139,229,193,69,17,55,55,183,105,229,202, 149,91,116,248,240,225,54,21,42,84,88,202,131,29,197,198,141,27,235,188,123,247, 238,43,30,148,204,115,116,116,156,89,180,104,209,2,252,220,243,139,232,51,3,0,0, 104,154,202,90,64,78,158,60,217,150,23,188,22,3,7,14,100,188,96,20,101,207,17, 10,36,54,111,222,204,246,239,223,207,230,206,157,203,182,108,217,194,102,207, 158,205,120,97,253,33,207,253,251,247,25,181,50,76,159,62,157,61,120,240,128,53, 106,212,136,153,153,153,201,125,94,105,27,77,162,191,127,237,218,53,154,58,242, 81,239,222,189,79,111,218,180,73,180,73,190,211,163,71,143,42,103,206,156,41, 199,131,49,61,186,66,203,159,50,74,75,198,233,146,9,79,166,116,203,131,52,163, 180,199,70,233,94,163,251,52,240,52,175,15,34,165,0,84,57,40,52,99,162,190,238, 212,141,38,145,239,39,186,77,72,75,241,148,248,126,137,229,199,113,44,175,92, 198,124,251,237,183,110,147,38,77,202,114,92,0,228,142,97,195,134,205,188,112, 225,66,15,254,155,151,94,188,120,161,168,83,167,206,247,60,192,120,76,99,25,104, 74,114,90,248,141,7,7,201,252,126,202,190,125,251,2,120,224,96,111,99,99,211, 245,249,243,231,222,252,57,154,158,251,29,255,254,27,142,30,61,186,23,207,107, 200,83,10,127,158,142,3,58,118,10,242,160,196,132,43,198,3,151,178,60,223,45, 250,155,197,139,23,191,195,243,116,226,1,140,5,15,86,140,249,223,29,195,207,197, 201,9,9,9,175,204,205,205,177,136,6,232,148,193,131,7,87,63,125,250,116,121,30, 172,155,243,223,128,57,123,95,182,80,82,150,55,70,105,229,140,50,81,185,100,200, 254,153,208,32,253,228,6,121,157,178,204,161,148,196,254,61,41,129,50,37,100,40, 115,40,197,241,125,20,199,203,156,24,43,43,171,152,137,19,39,222,255,238,187, 239,130,50,253,11,0,57,164,146,0,132,255,208,13,170,86,173,42,47,121,62,100,200, 16,181,173,253,65,45,10,188,208,102,212,197,171,116,233,210,236,246,237,219, 242,115,233,157,59,119,142,209,20,192,52,103,60,229,41,81,162,4,187,113,227,6, 45,142,248,159,247,50,50,50,98,234,68,83,239,82,75,76,131,6,13,142,116,237,218, 53,78,148,63,63,185,126,253,122,49,30,28,254,159,179,179,243,96,94,8,88,82,151, 60,94,217,18,109,6,31,65,193,55,181,236,189,124,249,146,241,10,173,31,47,12,22, 115,127,161,85,77,187,140,27,55,238,114,88,88,216,40,126,62,252,53,60,60,252,11, 30,40,78,174,88,177,98,224,201,147,39,63,84,102,232,187,36,252,220,16,195,239, 27,7,7,7,159,42,88,176,224,31,87,174,92,169,200,207,85,149,107,215,174,61,166, 75,151,46,23,66,66,66,82,248,182,252,107,79,136,240,244,244,52,190,121,243,102, 3,111,111,239,2,181,106,213,10,230,207,249,241,183,232,19,29,29,125,101,228, 200,145,93,121,160,98,201,183,243,121,240,224,193,27,254,25,214,125,245,213,87, 7,121,48,180,132,231,213,167,139,32,0,249,221,221,187,119,173,230,205,155,183, 224,204,153,51,3,222,190,125,91,144,202,28,30,128,139,54,131,143,80,150,57,254, 254,254,108,229,202,149,254,223,126,251,237,18,110,25,202,28,80,21,149,212,8, 231,207,159,95,155,23,182,109,105,213,243,230,205,155,139,178,231,24,181,98,60, 122,244,136,157,63,127,158,213,173,91,151,153,154,154,254,43,216,121,250,244,41, 59,116,232,144,252,163,113,119,119,151,243,58,58,58,202,115,199,43,231,143,167, 31,19,255,17,49,63,63,63,154,22,151,77,153,50,133,217,216,216,124,236,79,230, 24,63,1,178,35,71,142,80,235,71,92,135,14,29,78,187,184,184,136,54,201,55,248, 255,109,48,119,238,220,149,252,127,238,79,173,83,212,26,213,177,99,71,76,203, 252,25,148,139,136,109,223,190,157,102,85,43,187,107,215,174,21,201,201,201,116, 165,106,189,104,91,208,156,221,187,119,75,252,156,116,61,52,52,52,194,194,194, 226,76,147,38,77,174,242,130,92,159,63,247,154,191,28,205,19,181,114,188,73,203, 30,157,146,146,242,118,242,228,201,167,121,80,57,134,159,71,157,233,138,173, 165,165,229,159,81,81,81,15,249,54,161,252,119,243,118,245,234,213,23,110,221, 186,181,44,32,32,64,193,207,99,175,121,16,226,213,181,107,215,133,135,15,31,254, 253,235,175,191,110,203,207,117,15,248,177,240,100,218,180,105,62,252,249,45,7, 15,30,92,123,234,212,169,5,190,190,190,175,248,239,111,236,199,63,45,64,254, 192,203,126,163,31,126,248,97,237,233,211,167,251,208,98,149,191,254,250,43,117, 135,100,69,139,22,21,109,10,31,65,101,14,63,215,176,157,59,119,50,94,222,148, 225,229,206,159,252,57,42,115,86,139,182,5,200,14,149,4,32,206,206,206,61,163, 163,163,141,251,244,233,195,10,20,40,32,202,158,99,141,27,55,102,149,42,85,146, 199,152,88,91,91,255,103,92,7,117,253,106,218,180,169,188,216,18,5,30,43,86,172, 144,63,79,161,66,133,228,215,233,7,245,243,207,63,179,42,85,170,200,149,226,85, 171,86,209,204,93,114,183,46,234,26,161,74,174,174,174,114,64,84,163,70,141,183, 52,203,13,127,202,81,180,77,6,202,166,210,244,93,118,82,89,186,185,221,121,0, 150,18,23,23,71,39,132,127,55,3,229,178,13,27,54,52,190,120,241,98,159,98,197, 138,49,94,25,98,245,235,215,23,109,2,217,64,1,115,187,118,237,228,224,251,219, 111,191,165,64,111,26,15,166,15,243,32,250,13,3,173,192,131,130,27,47,95,190, 188,206,222,119,23,148,79,80,60,152,160,219,118,252,28,67,191,83,229,154,20,100, 133,145,145,209,154,150,45,91,70,241,115,83,59,254,187,233,206,243,190,152,58, 117,234,53,94,137,162,115,115,109,30,112,68,242,0,102,212,186,117,235,58,39,38, 38,6,241,115,217,83,126,14,139,187,112,225,66,34,207,255,240,221,187,119,117, 42,86,172,184,255,248,241,227,116,126,160,139,52,63,240,64,230,52,15,100,202, 125,247,221,119,135,27,53,106,20,157,201,199,4,200,87,102,205,154,213,226,220, 185,115,189,232,130,23,117,209,166,186,2,124,62,42,115,218,182,109,43,151,57,19, 39,78,164,243,219,119,11,22,44,56,56,99,198,140,80,209,182,0,34,159,29,128,240, 3,178,56,175,12,13,160,113,22,125,251,246,21,101,255,44,84,161,165,213,112, 203,150,45,43,183,126,40,187,50,40,153,152,152,80,127,104,121,204,7,5,30,212, 229,71,95,255,125,207,7,186,79,173,30,55,111,222,148,43,196,151,46,93,146,243, 208,227,55,111,222,200,219,169,210,238,221,187,229,86,23,170,116,240,10,201,31, 162,252,153,248,48,38,32,93,74,223,111,51,41,62,62,62,193,206,206,206,210,220, 220,188,92,88,88,88,82,131,6,13,220,121,112,182,97,196,136,17,190,31,125,87,13, 112,113,113,105,199,43,64,250,116,21,10,193,135,234,77,154,52,137,93,185,114, 133,2,144,74,203,151,47,183,101,255,92,81,215,52,41,45,65,26,254,91,255,207,162, 129,116,206,226,162,168,229,54,189,47,191,252,82,30,223,67,247,249,121,34,146, 223,124,88,161,148,159,87,41,160,160,231,148,107,97,28,101,25,124,243,205,55, 238,252,198,61,227,243,63,254,248,227,21,186,165,241,113,0,186,224,204,153,51, 78,49,49,49,122,127,254,249,39,130,15,53,24,63,126,188,124,81,117,223,190,125, 182,171,87,175,174,200,159,66,0,2,159,77,21,1,72,135,160,160,32,59,39,39,39,230, 224,224,32,202,254,89,168,5,131,18,181,124,100,12,62,50,230,201,12,141,199,72, 74,74,98,52,19,13,109,79,253,67,169,37,68,213,253,68,125,124,124,216,217,179, 103,169,203,209,203,63,254,248,163,117,155,54,109,124,69,219,228,128,130,166,62, 94,180,104,81,9,103,103,231,42,79,159,62,173,242,228,201,147,47,120,144,53,138, 127,23,195,249,115,167,68,111,160,46,81,81,81,10,26,127,211,165,75,23,81,86,200, 33,26,107,69,221,13,67,66,66,204,68,121,213,136,174,236,35,0,1,0,17,181,94,172, 8,15,15,55,41,89,178,36,235,214,173,155,40,43,228,16,149,57,180,142,89,104, 104,104,110,150,57,144,143,124,118,191,163,251,247,239,119,167,49,23,131,6,13, 82,121,55,38,66,211,237,82,228,253,238,221,187,255,188,63,141,255,248,88,32, 146,17,5,45,101,202,148,97,116,146,170,93,187,182,60,83,22,117,231,242,244,244, 84,249,154,37,52,246,131,159,16,153,165,165,229,65,53,5,31,132,254,241,212,62, 125,250,4,174,88,177,226,242,185,115,231,214,60,122,244,168,37,183,43,38,38,102, 79,173,90,181,114,243,76,172,207,255,119,244,191,85,163,242,229,203,203,183,60, 168,206,173,194,64,217,197,40,123,63,64,0,208,101,234,62,79,152,209,216,15,234, 37,1,234,161,156,221,148,151,57,170,189,98,11,58,235,179,34,134,31,127,252,177, 180,159,159,95,11,154,117,170,83,167,78,162,236,57,66,173,22,115,230,204,97,47, 94,188,144,187,52,209,216,15,234,126,69,193,8,205,112,165,236,98,165,68,227,61, 168,242,75,168,2,76,173,27,148,159,238,83,151,171,89,179,102,177,223,127,255, 157,245,239,223,159,45,91,182,140,245,234,213,75,165,179,51,81,48,70,51,117,153, 152,152,164,52,109,218,244,136,40,191,42,81,64,182,100,201,146,201,61,123,246, 220,194,247,203,190,69,139,22,213,20,109,163,38,242,14,85,215,108,104,240,175, 125,107,154,85,62,53,163,166,70,117,87,44,0,32,239,83,91,11,72,218,24,79,249,42, 34,202,28,245,209,146,50,7,242,19,229,66,125,89,165,143,225,21,221,159,120,69, 87,26,51,102,140,164,46,169,169,169,82,124,124,188,148,146,146,34,63,78,76,76, 252,215,125,122,61,189,228,228,100,137,22,239,34,116,75,121,41,81,94,37,90,97, 216,195,195,67,138,142,142,150,84,205,213,213,85,226,1,141,228,224,224,224,121, 251,246,109,139,143,238,60,53,226,31,67,207,222,222,254,72,251,246,237,119,72, 217,108,33,82,177,165,53,106,212,16,237,42,248,12,110,110,110,202,2,125,136,232, 203,80,19,10,50,169,155,95,105,81,198,124,174,63,79,27,69,153,0,116,28,181,200, 111,17,101,202,9,67,67,67,170,25,239,226,101,222,127,234,3,160,58,15,30,60,80, 150,57,195,179,254,70,0,178,39,199,45,32,79,158,60,49,121,248,240,97,47,106,61, 160,238,87,234,66,81,55,117,145,82,118,191,74,27,216,253,225,126,198,43,30,212, 34,162,108,209,160,91,202,75,73,57,13,47,161,166,90,94,65,86,249,216,15,66,131, 207,169,219,152,141,141,205,186,250,245,235,71,138,242,171,3,223,39,169,53,107, 214,92,231,227,227,83,127,240,224,193,170,107,222,201,62,245,46,176,2,233,229, 230,213,40,234,130,149,249,128,43,0,128,127,168,173,5,132,151,183,84,33,48,17, 229,3,149,193,190,6,149,200,113,0,178,101,203,150,214,33,33,33,181,104,122,54, 204,116,244,30,223,31,236,232,209,163,212,221,43,178,73,147,38,39,68,249,213, 169,92,185,114,247,205,204,204,162,156,157,157,115,99,140,0,2,16,205,201,141, 239,151,80,228,79,51,53,169,165,82,1,0,249,138,218,186,107,74,146,68,245,152, 220,188,16,163,107,84,59,104,22,116,86,142,2,16,254,131,103,183,110,221,250,34, 42,42,74,159,166,222,165,233,111,129,177,11,23,46,176,87,175,94,209,148,190, 199,103,205,154,229,35,202,175,78,51,102,204,136,228,1,200,211,55,111,222,168, 190,153,39,107,84,49,197,9,74,115,114,179,224,197,32,116,0,200,14,181,5,32,236, 125,61,38,55,207,131,186,6,23,24,65,37,114,212,61,103,225,194,133,86,79,158,60, 105,67,131,189,49,237,221,123,212,237,138,86,12,53,50,50,74,45,85,170,212,118, 133,66,161,174,147,109,182,20,46,92,56,90,79,79,239,145,161,161,161,166,3,16,42, 12,112,130,210,156,220,106,1,33,202,197,49,1,0,178,34,207,218,40,202,148,67,84, 230,228,230,121,80,215,160,124,7,149,200,81,11,136,171,171,107,199,192,192,192, 146,29,58,116,96,118,118,118,162,236,58,225,225,195,135,242,226,112,197,139,23, 127,241,251,239,191,95,21,229,215,132,212,212,84,163,132,132,4,77,95,25,146,175, 70,97,54,18,141,209,116,128,169,164,236,130,165,174,74,5,0,228,31,234,110,1,65, 0,162,57,232,225,0,42,241,201,1,200,185,115,231,76,121,240,49,150,42,152,3,7, 14,196,180,119,105,104,81,184,152,152,24,26,220,126,186,102,205,154,177,162, 252,26,66,35,239,53,221,63,142,142,41,156,160,52,39,55,11,94,140,1,1,128,236,80, 119,0,162,233,11,109,186,236,159,25,125,0,62,195,39,7,32,7,14,28,168,252,244, 233,211,218,85,170,84,97,173,90,181,18,101,215,9,180,178,250,225,195,135,105,44, 76,116,197,138,21,215,136,242,107,16,157,40,52,29,12,80,68,138,38,90,205,209, 244,247,155,30,90,64,0,32,59,212,217,5,139,202,28,84,138,53,39,71,93,247,1,50, 250,228,0,228,250,245,235,29,99,98,98,76,105,1,63,11,139,92,89,230,66,235,208, 74,237,143,30,61,98,182,182,182,247,150,47,95,254,72,148,95,131,114,163,5,4,1, 136,110,64,23,44,0,200,46,76,217,157,127,32,216,3,149,248,164,0,228,226,197,139, 5,34,34,34,6,209,172,87,253,250,245,19,101,215,9,52,35,216,158,61,123,228,251, 117,234,212,57,158,219,131,207,51,200,141,0,4,131,208,117,71,18,67,165,2,21,43, 0,177,84,134,223,73,126,129,22,16,80,137,79,58,144,86,173,90,213,42,44,44,172, 122,179,102,205,152,163,163,163,40,187,78,240,243,243,99,103,206,156,97,37,74, 148,8,238,208,161,195,161,29,59,118,136,54,209,36,10,4,114,35,0,201,173,129,209, 160,65,122,122,122,73,5,11,22,76,165,46,136,218,236,222,189,123,214,27,54,108, 232,243,232,209,163,42,158,158,158,6,252,28,102,152,154,154,74,231,62,67,133,66, 33,223,166,75,244,155,161,231,132,131,219,232,226,3,87,140,39,75,254,62,46,130, 236,159,75,217,135,62,53,147,148,146,46,81,171,84,10,255,108,116,155,204,191, 163,228,162,69,139,38,242,243,117,92,195,134,13,207,206,155,55,239,82,230,111, 15,160,86,152,178,59,255,248,164,122,163,174,24,57,114,100,189,227,199,143,87, 138,139,139,51,143,137,137,49,75,78,78,166,113,73,148,140,211,37,185,91,60,47, 47,232,86,89,246,24,164,37,253,116,183,185,65,89,150,36,167,75,244,56,137,151, 39,116,177,49,49,93,74,72,75,241,60,197,25,26,26,198,153,152,152,196,84,171,86, 45,98,243,230,205,23,29,28,28,162,51,253,11,25,100,251,64,226,31,64,81,167,78, 157,47,98,99,99,245,134,12,25,34,175,56,14,140,29,59,118,140,189,121,243,134, 241,194,253,20,223,47,62,67,135,14,21,109,162,73,244,253,106,122,140,0,29,24,5, 68,153,32,111,251,249,231,159,139,111,217,178,197,172,98,197,138,201,206,206, 206,162,236,185,130,159,179,76,198,142,29,219,237,203,47,191,156,239,229,229,85, 145,23,12,140,7,76,52,69,181,104,211,108,83,78,194,193,255,86,9,65,214,92,195, 207,217,242,26,69,79,158,60,153,204,207,81,147,182,111,223,190,142,127,110,92, 141,6,141,49,51,51,75,73,74,74,146,120,18,101,5,237,151,237,122,99,126,71,139, 96,46,94,188,184,236,161,67,135,230,28,60,120,176,247,219,183,111,205,168,135, 16,149,51,186,52,65,83,74,74,138,60,9,147,135,135,7,5,98,231,120,25,51,136,215, 133,195,68,219,101,251,64,90,179,102,77,229,208,208,208,110,54,54,54,172,99,199, 142,162,236,58,129,78,166,212,253,202,212,212,52,181,65,131,6,7,116,233,128,203, 2,237,4,68,167,249,156,183,183,119,237,162,69,139,86,248,245,215,95,19,91,180, 104,33,202,158,43,38,77,154,52,229,232,209,163,115,2,3,3,245,232,156,69,23,78, 106,214,172,201,248,231,166,214,27,209,230,249,66,106,106,42,11,9,9,145,103,233, 155,55,111,158,209,221,187,119,127,185,122,245,234,81,254,82,144,104,91,0,85, 225,245,134,4,43,43,171,106,252,247,88,176,68,137,18,81,162,252,160,213,80,190, 167,225,229,95,169,115,231,206,185,220,184,113,163,108,185,114,229,216,228,201, 147,153,147,147,19,43,95,190,60,51,54,214,244,181,223,220,19,29,29,205,30,60, 120,64,23,38,105,145,242,246,188,156,253,146,63,189,68,180,157,220,141,64,148, 72,251,246,237,199,211,248,134,49,99,198,72,240,30,63,232,36,3,3,3,137,159,92, 175,223,185,115,71,27,143,182,205,60,13,22,101,82,49,75,158,2,28,29,29,69,187, 15,62,131,155,155,27,253,48,41,109,18,124,31,106,193,79,48,211,29,28,28,14,138, 242,229,150,137,19,39,118,230,21,158,72,19,19,19,105,227,198,141,82,114,114,178, 104,151,230,123,205,155,55,151,120,161,24,211,182,109,219,170,162,253,7,160,74, 188,162,102,223,168,81,163,151,188,254,80,70,148,55,7,104,54,28,63,123,123,123, 137,7,220,162,159,1,228,16,175,96,42,203,156,109,130,239,67,39,240,58,159,69, 141,26,53,206,243,187,82,175,94,189,36,63,63,63,209,46,204,247,118,238,220,41, 119,19,230,251,229,153,104,255,145,108,93,6,116,119,119,55,244,244,244,236,67, 221,174,6,12,24,32,202,174,19,248,190,102,187,119,239,150,87,64,175,94,189,250, 209,122,245,234,37,136,182,201,5,113,12,253,110,65,197,102,207,158,93,48,33,33, 225,171,6,13,26,92,20,229,205,13,188,96,176,188,121,243,230,159,111,223,190,45, 248,219,111,191,177,175,191,254,90,231,187,140,210,121,138,154,201,13,12,12,18, 139,20,41,146,44,202,15,160,74,163,71,143,14,225,231,140,228,224,224,224,6,162, 188,89,225,229,46,186,25,228,62,124,7,28,47,91,134,122,123,123,183,109,216,176, 33,219,178,101,11,43,83,70,29,177,117,222,146,214,197,146,46,116,249,102,157, 243,189,108,5,32,235,215,175,111,28,30,30,222,180,78,157,58,52,214,65,148,93,39, 80,183,134,35,71,142,176,98,197,138,197,118,233,210,229,180,40,127,46,161,166, 110,4,32,160,50,188,2,80,200,223,223,127,127,161,66,133,20,99,199,142,221,35, 202,159,27,246,236,217,51,240,225,195,135,149,169,107,216,152,49,99,68,217,117, 2,47,40,25,223,39,140,127,111,175,166,79,159,46,236,155,11,160,74,214,214,214, 97,213,170,85,187,241,236,217,179,145,46,46,46,57,238,45,112,231,206,157,6,188, 226,247,205,230,205,155,177,6,0,228,154,75,151,46,21,242,240,240,24,75,93,92, 231,205,155,135,37,41,216,251,238,190,23,47,94,164,177,47,169,197,139,23,95,38, 202,79,178,21,128,220,188,121,179,111,108,108,172,97,223,190,125,105,188,131,40, 187,78,160,29,253,242,229,75,86,186,116,233,203,19,39,78,124,32,202,159,75,104, 69,118,12,54,5,149,72,76,76,44,48,121,242,228,61,183,110,221,170,105,110,110, 222,183,126,253,250,111,69,219,104,26,15,144,244,232,124,69,3,226,190,252,242, 75,90,28,84,180,137,78,56,125,250,52,139,140,140,100,101,203,150,189,93,175,94, 189,112,81,126,0,85,107,219,182,237,31,102,102,102,77,120,217,249,87,78,91,50, 146,146,146,30,94,189,122,117,212,156,57,115,46,15,29,58,116,16,127,31,250,129, 199,138,182,3,80,165,117,235,214,53,10,12,12,180,231,101,32,107,217,178,165,40, 187,78,8,14,14,102,103,207,158,165,139,92,193,101,202,148,185,35,202,79,178,21, 128,248,250,250,118,162,8,175,103,207,158,162,172,58,129,34,189,93,187,118,49, 35,35,35,90,124,112,187,22,207,40,19,195,16,128,228,119,41,162,12,159,227,254, 253,251,133,7,14,28,88,171,105,211,166,95,215,172,89,243,226,223,127,255,93,213, 212,212,180,221,165,75,151,30,138,182,205,13,135,14,29,170,239,227,227,211,148, 154,195,187,116,233,34,202,174,19,40,24,163,201,50,104,102,150,22,45,90,104,237, 184,29,200,223,190,254,250,235,123,41,41,41,61,79,158,60,57,112,242,228,201,235, 232,98,129,104,155,140,154,52,105,18,227,224,224,240,123,120,120,120,157,35,71, 142,236,172,85,171,150,75,223,190,125,191,82,164,205,0,131,137,96,64,221,232, 184,245,243,243,27,78,231,213,193,131,7,83,183,86,209,38,58,225,196,137,19,44, 52,52,148,85,168,80,193,101,237,218,181,33,162,252,36,91,123,238,245,235,215, 54,221,187,119,103,118,118,118,162,172,58,225,218,181,107,236,242,229,203,172, 100,201,146,190,19,38,76,56,119,240,160,214,150,233,20,128,160,11,86,254,214, 129,167,19,162,76,25,208,49,65,227,0,146,50,220,254,107,45,9,125,125,253,20,30, 124,216,152,152,152,56,36,37,37,197,241,0,228,204,232,209,163,215,181,106,213, 42,224,163,239,156,203,206,156,57,51,56,32,32,192,120,252,248,241,172,120,241, 226,162,236,58,225,246,237,219,114,170,94,189,250,227,153,51,103,186,46,90,180, 72,180,9,128,90,184,185,185,93,114,114,114,234,118,227,198,141,131,246,246,246, 53,248,185,100,71,213,170,85,31,241,32,226,73,155,54,109,2,69,219,19,126,252, 30,230,199,243,21,23,23,151,22,238,238,238,13,158,63,127,222,128,38,200,161,11, 131,52,214,9,21,66,80,167,229,203,151,87,120,245,234,85,15,107,107,107,92,228, 74,19,31,31,47,95,148,55,54,54,78,174,83,167,206,118,254,59,23,109,34,203,238, 47,213,136,250,83,235,202,212,149,89,161,110,12,52,213,24,13,182,225,59,122,13, 63,153,106,115,119,6,4,32,249,31,181,68,252,46,202,148,129,50,0,201,152,210,47, 104,151,66,115,247,243,2,61,113,242,228,201,241,195,135,15,143,244,244,244,148, 175,164,107,43,94,41,41,56,114,228,200,142,134,134,134,152,44,35,157,125,251, 246,201,87,134,203,148,41,179,217,220,220,92,187,87,141,132,124,207,217,217,249, 242,201,147,39,235,31,62,124,120,28,15,32,134,62,120,240,160,200,197,139,23,125, 245,245,245,223,166,164,164,208,66,160,202,148,233,130,160,20,108,240,227,184, 20,29,211,52,25,12,173,115,67,79,251,248,248,176,25,51,102,176,185,115,231,162, 235,37,168,205,133,11,23,58,250,251,251,155,242,50,145,186,224,139,178,235,4,10, 56,110,220,184,193,44,45,45,221,255,247,191,255,93,222,184,113,163,104,19,89, 118,3,16,69,98,98,162,40,79,190,231,229,229,37,159,224,174,92,185,194,236,237, 237,47,76,154,52,105,29,63,137,138,54,203,53,188,34,22,205,131,70,189,132,4,109, 156,160,11,84,132,90,35,156,69,153,114,34,42,42,74,78,116,162,205,11,246,239, 223,223,236,241,227,199,182,245,234,213,99,148,224,125,191,220,227,199,143,51, 43,43,171,152,97,195,134,157,229,21,63,209,38,0,106,215,165,75,23,111,126,51, 133,7,16,70,219,183,111,55,255,245,215,95,141,141,140,140,12,227,226,226,210, 175,6,157,233,212,117,118,118,118,198,54,54,54,75,255,254,251,239,15,93,50,40, 24,41,81,162,4,27,53,106,148,220,53,26,64,29,60,61,61,141,58,119,238,220,139, 102,85,28,52,104,144,40,187,206,160,94,64,20,35,84,174,92,249,16,47,123,179,29, 44,100,43,0,49,53,53,149,86,172,88,33,175,32,220,184,113,99,185,47,177,174,160, 157,234,235,235,43,119,185,162,105,119,95,189,122,197,74,149,42,229,204,79,128, 3,181,188,245,131,86,159,141,105,213,170,85,251,35,71,142,28,16,229,133,60,75, 183,231,151,77,67,253,114,123,246,236,57,154,7,219,250,253,250,245,195,21,208, 52,231,206,157,147,207,89,29,58,116,120,216,191,127,255,7,104,25,2,109,194,3,7, 170,172,100,187,194,66,86,174,92,217,114,252,248,241,141,104,90,233,210,165,75, 39,243,128,228,204,213,171,87,27,89,88,88,20,229,21,32,209,230,0,57,182,103, 207,158,6,97,97,97,45,29,28,28,104,60,146,40,187,78,224,251,131,29,61,122,148, 226,131,248,30,61,122,156,163,11,244,217,149,173,0,132,87,180,55,186,186,186, 142,28,59,118,44,93,80,215,169,174,88,212,196,75,39,58,194,119,112,84,211,166, 77,247,182,107,215,110,250,172,89,179,180,58,248,32,70,70,70,49,129,129,129, 117,68,249,0,242,186,195,135,15,87,112,115,115,107,73,23,73,122,245,234,37,202, 174,19,232,188,69,23,77,12,12,12,82,29,29,29,215,82,215,21,209,54,0,218,140,151, 199,134,3,7,14,252,37,42,42,202,160,91,183,110,199,58,118,236,248,39,63,174,111, 187,184,184,120,166,166,166,22,165,242,26,3,209,65,29,232,216,226,245,191,62, 209,209,209,6,116,33,199,204,204,76,180,137,78,160,139,243,212,59,200,222,222, 254,220,212,169,83,179,53,251,149,82,182,2,144,83,167,78,141,233,220,185,243, 214,107,215,174,89,242,31,190,121,114,114,50,237,121,186,196,72,115,242,210,156, 222,202,62,155,202,251,134,236,253,123,103,76,116,181,54,183,162,151,244,3,108, 211,167,164,180,148,152,46,37,164,37,90,200,47,174,96,193,130,177,230,230,230, 49,253,250,245,123,181,98,197,10,79,26,132,158,23,148,47,95,62,146,127,95,118, 43,87,174,180,25,63,126,124,182,6,248,101,23,63,224,244,42,86,172,136,25,182, 64,43,92,189,122,117,120,80,80,80,225,222,189,123,211,113,47,202,174,19,104, 221,15,190,95,168,203,74,32,15,202,142,45,94,188,88,180,9,128,86,115,115,115, 107,84,161,66,133,24,94,246,116,152,55,111,222,5,234,94,200,81,151,140,220,170, 87,128,142,216,183,111,95,153,128,128,128,190,52,35,44,149,51,240,207,140,176, 250,250,250,169,85,170,84,217,251,232,209,35,209,38,255,146,173,0,36,237,138, 194,117,81,190,252,74,217,23,158,186,161,229,37,171,86,173,122,49,118,236,216, 119,252,0,25,200,31,46,17,229,255,20,177,177,177,246,11,23,46,108,203,15,192,29, 63,252,240,195,27,81,126,0,117,161,11,34,109,218,180,233,67,51,224,160,95,238, 63,168,95,46,77,21,73,253,114,27,55,110,172,117,107,182,0,124,42,99,99,99,143, 223,126,251,173,95,90,215,45,37,52,121,128,218,29,59,118,172,99,112,112,112,233, 14,29,58,48,116,245,123,239,217,179,103,242,154,120,86,86,86,79,251,244,233, 115,250,83,199,68,227,170,65,62,86,191,126,253,168,234,213,171,255,145,146,146, 178,136,87,70,190,22,229,255,20,241,241,241,79,111,222,188,217,105,245,234,213, 174,253,251,247,31,119,237,218,181,66,105,47,169,117,93,10,128,140,254,248,227, 143,186,143,31,63,174,68,211,132,59,57,57,137,178,235,132,232,232,104,57,0,177, 176,176,72,180,183,183,223,138,238,87,144,31,56,56,56,68,100,8,62,0,52,194,211, 211,179,59,77,232,51,112,224,64,116,243,75,67,45,144,52,51,108,177,98,197,142, 12,25,50,228,147,135,37,32,0,201,231,54,111,222,188,245,221,187,119,63,253,245, 215,95,107,167,77,155,246,141,40,127,118,53,104,208,32,137,167,249,252,7,89,133, 31,132,43,71,140,24,113,157,255,48,199,79,159,62,221,146,33,8,1,13,114,117,117, 237,27,26,26,42,247,203,165,230,113,96,242,76,125,212,28,94,169,82,165,251,11, 22,44,240,20,229,7,0,128,204,241,122,141,157,175,175,111,83,234,222,219,177,99, 71,81,118,157,64,211,95,239,221,187,151,38,169,74,106,218,180,233,167,53,125, 164,65,0,162,3,158,62,125,186,48,49,49,241,135,115,231,206,45,172,93,187,246,9, 39,39,167,33,179,103,207,110,179,108,217,50,43,246,239,241,58,202,49,58,217,10, 239,191,255,254,251,171,181,106,213,58,66,87,5,158,60,121,82,237,216,177,99,43, 14,30,60,120,81,79,79,207,74,180,45,128,42,220,191,127,191,204,203,151,47,191, 224,39,65,214,167,79,31,81,118,157,64,131,37,119,238,220,73,253,114,89,243,230, 205,79,41,20,10,204,195,13,0,144,67,207,158,61,251,38,42,42,202,178,103,207,158, 180,214,133,40,187,78,184,126,253,58,149,191,204,214,214,214,99,194,132,9,159, 54,248,35,77,182,198,128,64,222,231,234,234,250,59,15,58,206,92,187,118,109, 180,187,187,123,143,119,239,222,41,2,2,2,252,120,229,36,149,87,88,148,19,10,80, 74,127,63,203,41,94,169,91,135,153,153,89,113,154,21,141,6,35,81,68,236,237, 237,45,207,205,78,247,35,34,34,88,161,66,202,158,89,0,170,183,109,219,182,54, 188,112,40,70,93,175,106,212,168,33,202,174,19,120,64,198,78,159,62,77,43,193, 135,242,0,100,219,210,165,75,69,155,0,0,64,38,60,60,60,204,122,244,232,209,137, 214,151,193,52,230,255,160,69,137,105,166,197,18,37,74,172,229,101,111,140,40, 127,102,16,128,232,144,153,51,103,210,170,217,19,232,126,72,72,8,53,157,25,234, 235,235,27,38,39,39,211,113,144,113,230,50,122,156,101,75,8,255,65,42,234,214, 173,59,159,71,194,85,232,49,5,34,150,150,150,177,225,225,225,70,38,38,38,6,5,10, 20,200,106,115,128,207,194,143,91,189,134,13,27,246,138,143,143,151,251,229,26, 24,224,116,70,142,28,57,194,248,111,144,181,111,223,254,74,159,62,125,94,136, 242,3,0,64,230,166,79,159,94,155,215,151,106,52,106,212,136,213,169,131,85,13, 72,64,64,128,188,246,71,177,98,197,94,183,107,215,238,44,13,68,207,9,116,193, 210,97,113,113,113,73,188,18,23,203,239,70,242,20,198,83,8,123,191,178,246,75, 158,188,120,122,158,85,186,112,225,66,114,96,96,96,107,154,125,200,218,218,58, 190,121,243,230,187,122,112,169,169,169,193,212,253,131,18,128,186,236,221,187, 215,222,223,223,191,117,169,82,165,88,167,78,157,68,217,117,2,5,99,251,246,237, 147,23,139,109,217,178,101,142,250,229,2,0,128,220,157,85,17,26,26,58,52,54,54, 86,175,111,223,190,116,209,85,180,137,78,56,123,246,44,123,253,250,53,171,82, 165,202,173,25,51,102,248,137,242,127,12,2,16,200,177,165,75,151,254,16,17,17, 97,222,172,89,179,221,195,135,15,111,225,226,226,50,120,211,166,77,127,243,151, 244,168,31,58,128,58,157,58,117,170,63,63,9,22,232,210,165,11,117,55,18,101,215, 9,119,238,220,145,83,165,74,149,252,39,78,156,152,179,203,82,0,0,192,230,206, 157,107,29,28,28,220,191,88,177,98,172,107,215,174,162,236,58,33,41,41,73,94, 224,214,196,196,36,181,102,205,154,219,69,249,179,130,0,4,114,196,221,221,189, 170,173,173,173,126,187,118,237,90,186,186,186,14,90,184,112,225,237,180,151, 140,179,220,16,64,5,120,37,219,234,225,195,135,189,169,219,213,224,193,131,69, 217,117,198,254,253,251,229,126,185,118,118,118,187,10,22,44,24,34,202,15,0,0, 153,187,117,235,86,215,192,192,64,75,106,97,47,83,166,140,40,187,78,160,129,231, 180,24,183,181,181,245,243,33,67,134,28,19,229,207,10,2,16,200,17,94,241,123, 181,120,241,226,145,60,18,190,33,202,11,240,169,66,66,66,76,179,122,253,244,233, 211,157,94,188,120,225,80,171,86,45,90,239,38,171,172,26,65,149,254,220,70,227, 186,210,250,229,198,245,236,217,243,168,40,63,0,128,174,226,21,105,3,73,146,62, 58,112,240,224,193,131,230,175,94,189,250,31,117,37,255,226,139,47,176,246,71, 154,3,7,14,80,247,125,86,173,90,53,90,224,54,78,148,63,43,24,181,9,57,226,224, 224,16,45,202,163,105,180,248,218,255,253,223,255,177,208,208,208,15,207,81,197, 112,236,216,177,242,115,212,45,140,250,113,166,119,254,252,121,246,252,249,115, 57,143,210,165,75,151,228,53,20,198,143,31,207,46,95,190,204,30,63,126,44,191, 190,102,205,26,121,234,57,26,108,79,39,35,190,15,216,87,95,125,197,138,20,41, 194,64,181,60,61,61,7,252,242,203,47,85,156,156,156,150,181,105,211,38,56,227, 235,127,255,253,119,103,90,0,169,127,255,254,52,153,66,102,111,241,217,126,255, 253,119,26,200,205,28,29,29,63,154,231,221,187,119,108,214,172,89,242,177,96, 101,101,37,31,23,77,154,52,97,219,183,111,103,19,38,76,160,149,155,59,89,67,238, 0,0,32,0,73,68,65,84,63,186,173,170,209,177,74,51,96,213,173,91,215,101,208, 160,65,183,208,50,4,144,187,104,6,58,90,55,34,42,42,138,102,162,100,223,126,251, 109,166,249,104,198,200,101,203,150,177,25,51,102,96,156,129,134,240,243,181, 213,226,197,139,191,255,223,255,254,183,115,245,234,213,119,51,190,206,207,167, 85,159,61,123,102,79,171,158,55,111,222,60,179,183,200,20,141,137,93,184,112, 161,188,74,184,114,134,80,122,15,170,67,228,245,41,124,169,188,163,197,7,121, 153,27,205,255,167,77,103,206,156,17,109,146,37,180,128,64,190,65,3,112,169,11, 10,143,204,229,65,201,116,226,167,68,131,148,169,114,70,193,67,70,30,30,30,242, 148,165,233,61,120,240,224,195,115,244,186,242,71,118,226,196,9,57,136,233,214, 173,27,107,221,186,53,187,123,247,174,188,246,196,155,55,111,254,243,190,240, 121,248,9,238,34,47,176,71,241,194,225,22,63,113,255,244,228,201,147,146,202, 215,248,119,92,130,127,47,173,104,138,231,94,189,122,101,245,54,159,133,190,247, 160,160,160,44,243,184,185,185,81,48,196,218,181,107,199,108,108,108,88,233,210, 165,229,227,225,216,177,99,114,95,89,77,161,66,110,219,182,109,52,241,131,68, 139,66,241,64,40,247,155,100,0,116,28,149,25,126,126,126,172,104,209,162,52,46, 235,163,249,104,218,122,42,187,52,121,206,208,117,252,92,29,242,244,233,211,216, 35,71,142,92,231,229,249,198,249,243,231,215,76,255,58,175,51,116,139,137,137, 49,161,25,22,205,205,205,63,246,54,255,65,1,8,125,151,212,101,171,123,247,238, 172,67,135,14,114,240,57,113,226,68,150,215,199,198,210,108,87,188,44,166,181, 63,174,45,95,190,220,75,148,95,4,45,32,144,111,208,213,103,170,148,14,25,50, 132,149,43,87,238,95,175,209,149,8,67,67,195,255,108,67,99,8,50,94,165,78,255, 28,109,147,254,62,175,220,177,222,189,123,203,143,233,10,51,85,60,183,110,221, 202,166,78,157,202,64,117,26,55,110,236,63,123,246,236,37,139,22,45,154,203,247, 239,92,30,60,142,226,129,200,166,95,126,249,101,235,159,127,254,57,52,44,44,172, 4,13,10,180,179,179,19,189,85,142,81,203,10,245,119,165,22,49,106,114,166,22, 49,186,146,165,68,87,131,182,108,217,34,183,188,81,43,26,229,167,22,55,154,126, 218,196,196,68,158,5,142,90,105,214,173,91,39,95,13,171,87,175,30,27,58,116,168, 90,90,108,168,80,160,213,207,171,84,169,242,150,31,159,103,120,225,32,218,4,0, 212,140,202,14,58,15,80,165,148,22,236,37,107,215,174,149,43,167,52,147,16,149, 41,147,39,79,150,243,209,57,131,202,30,106,13,161,60,84,121,173,90,181,170,224, 47,64,78,81,125,225,214,173,91,43,111,220,184,241,37,63,199,127,253,248,241, 227,254,78,78,78,251,26,52,104,176,108,204,152,49,239,120,217,62,204,204,204, 236,63,189,38,178,131,206,241,116,241,179,89,179,102,242,99,186,40,74,221,184, 232,187,165,224,132,122,77,208,5,76,106,61,191,122,245,170,188,166,6,5,39,84, 167,104,213,170,149,188,13,5,45,52,163,33,149,113,116,17,149,159,219,229,201,86, 168,155,45,161,58,13,213,117,54,108,216,192,110,222,188,73,93,111,217,136,17,35, 228,214,120,58,182,232,66,24,5,191,111,223,190,149,223,87,217,155,131,214,50, 105,211,166,205,71,63,251,199,208,69,46,250,156,252,239,74,117,235,214,61,238, 233,233,41,218,68,8,45,32,144,175,208,73,126,243,230,205,242,143,146,210,193, 131,7,229,231,85,213,127,51,253,21,42,122,79,10,64,232,199,159,139,168,189,190, 112,126,76,230,230,230,7,248,73,247,101,76,76,12,181,52,148,229,129,200,172,158, 61,123,254,205,131,145,159,168,64,31,52,104,16,83,39,250,27,167,78,157,98,180, 200,33,85,20,166,76,153,34,159,132,149,168,144,161,66,193,218,218,90,46,36,168, 197,132,174,16,41,215,35,161,188,63,252,240,3,243,247,247,151,11,31,10,100,230, 207,159,255,177,63,247,89,232,56,167,253,100,111,111,127,178,101,203,150,175,68, 249,1,64,51,168,162,72,173,234,59,118,236,144,31,83,112,65,221,121,169,130,74, 227,182,126,249,229,23,249,156,65,129,10,85,22,199,141,27,39,95,212,40,95,190, 124,214,111,156,123,242,77,153,195,131,141,56,94,97,223,70,193,95,80,80,80,129, 43,87,174,124,189,109,219,182,43,60,40,116,229,223,77,5,58,247,83,240,240,169, 40,152,160,139,82,148,110,223,190,45,127,223,20,76,82,64,179,114,229,74,182, 126,253,122,86,179,102,77,249,181,153,51,103,202,193,38,205,230,56,125,250,116, 121,22,195,135,15,31,202,129,41,173,59,66,159,141,90,79,220,221,221,229,11,90, 212,77,143,238,211,194,187,123,247,238,149,203,21,186,56,70,221,187,148,93,252, 92,92,92,216,175,191,254,42,151,79,84,39,162,94,27,116,124,81,119,98,186,88,74, 239,243,169,124,124,124,216,133,11,23,104,225,65,63,126,236,30,17,229,207,14, 180,128,64,190,66,149,70,26,191,65,115,84,83,5,176,100,201,146,114,55,169,172, 100,12,78,232,113,118,3,22,106,113,161,171,227,185,168,61,79,103,69,153,242,162, 239,190,251,46,153,7,33,31,154,11,168,130,205,131,61,185,43,22,117,103,160,194, 65,221,70,142,28,41,119,231,163,202,0,181,94,208,119,173,108,142,167,171,150, 84,136,208,149,32,91,91,91,185,162,145,126,237,27,111,111,111,249,170,19,245,7, 166,66,132,174,108,253,249,231,159,114,80,66,5,145,170,40,187,111,20,46,92,152, 213,170,85,107,51,63,118,255,137,146,0,32,215,209,185,65,121,97,130,126,251,147, 38,77,146,175,66,211,69,12,170,40,210,121,133,206,111,52,166,141,174,118,211, 115,90,140,46,159,231,155,50,231,240,225,195,198,244,253,16,170,51,4,7,7,23,58, 118,236,88,33,122,220,175,95,191,108,215,5,210,163,109,86,173,90,37,95,24,74,76, 76,148,91,39,104,76,33,29,3,244,157,127,255,253,247,114,121,64,193,0,149,47,20, 32,16,10,28,168,219,30,149,23,212,122,50,124,248,112,249,121,154,117,138,234, 54,244,249,202,150,45,43,151,41,212,210,78,199,10,5,41,20,184,82,208,147,190, 203,48,189,39,245,214,160,238,127,116,145,148,130,24,10,108,41,16,166,133,4,45, 44,44,50,251,232,31,69,45,47,212,234,207,131,154,211,131,6,13,10,16,229,207,14, 4,32,144,175,208,201,125,206,156,57,114,228,159,222,199,250,94,210,143,152, 126,84,233,209,99,101,55,25,81,159,205,123,247,238,101,217,183,87,3,206,241,52, 78,148,41,47,250,233,167,159,44,143,31,63,126,222,195,195,67,94,228,131,22,215, 163,239,151,174,26,82,179,184,186,7,244,81,161,68,5,135,18,21,30,233,91,64,136, 178,80,200,12,93,101,162,99,137,174,80,209,182,148,168,64,17,29,83,159,138,154, 240,233,10,107,253,250,245,221,249,62,187,243,243,207,63,139,54,1,128,92,66,173, 169,202,137,75,148,129,9,157,19,168,18,73,149,201,167,79,159,50,95,95,95,109, 110,1,185,192,211,104,81,166,60,34,149,87,210,103,28,57,114,68,30,255,65,223,71, 137,18,37,228,73,107,168,162,223,185,115,103,209,246,153,162,239,147,130,72,10, 50,40,24,81,118,227,166,96,132,238,43,203,21,186,80,74,51,57,42,81,80,64,229,6, 5,163,233,187,145,43,203,58,42,107,232,216,81,214,79,40,96,161,128,130,186,93, 209,182,20,184,16,250,63,40,240,80,110,67,101,167,242,239,43,7,198,127,10,26,95, 75,107,127,240,191,155,196,203,153,189,170,234,245,129,46,88,144,175,208,15, 159,126,100,31,123,141,80,63,125,74,244,152,154,36,189,188,188,228,86,19,66,21, 70,154,25,171,97,195,134,153,190,135,242,106,8,85,60,169,57,146,186,220,80,63, 204,92,68,29,139,35,242,99,226,39,225,78,222,222,222,21,41,232,176,183,183,247, 28,61,122,244,28,91,91,219,68,58,129,211,149,41,117,160,239,159,174,14,41,41, 143,153,156,4,13,84,144,209,204,88,212,47,119,241,226,197,172,103,207,158,242, 113,243,41,3,26,69,168,32,161,130,129,90,94,202,148,41,179,158,31,159,90,55,59, 29,0,252,91,102,231,21,186,154,77,221,135,91,180,104,65,23,95,180,98,106,239, 143,160,2,86,120,254,206,11,137,151,251,230,15,31,62,28,74,221,148,108,108,108, 34,155,55,111,190,178,87,175,94,174,180,239,63,119,129,91,229,184,158,204,102, 66,84,6,0,52,166,144,38,49,81,62,71,19,229,208,180,242,21,43,86,148,199,136, 144,176,176,48,57,208,160,64,149,234,31,148,143,142,27,250,140,212,202,66,229, 11,181,174,80,240,74,129,66,70,148,55,39,229,87,122,183,110,221,146,39,92,225, 129,208,181,111,191,253,246,154,40,127,118,161,5,4,242,13,250,113,210,149,129, 204,154,76,169,18,75,253,37,233,7,174,60,177,127,247,221,119,172,71,143,30,114, 159,91,234,163,79,125,52,105,208,22,245,249,164,233,117,73,250,1,233,116,21,97, 197,138,21,242,251,208,73,128,18,93,229,160,31,126,46,250,244,246,225,60,224, 208,161,67,86,139,22,45,154,86,180,104,81,207,166,77,155,254,197,239,239,30,59, 118,108,229,219,183,111,255,72,87,149,170,87,175,46,122,139,28,57,124,248,176, 220,109,138,102,148,82,14,36,39,116,76,209,227,140,199,22,189,158,126,146,2,101, 33,65,207,209,21,52,58,182,168,233,155,62,47,181,82,80,215,11,85,162,105,119, 105,90,68,30,236,188,227,129,240,121,190,223,68,155,0,128,134,40,7,161,167,63, 79,208,173,178,203,15,221,210,99,101,217,69,23,40,168,143,63,77,176,65,93,94, 148,19,158,104,153,124,81,230,80,165,124,228,200,145,227,222,190,125,91,180,117, 235,214,235,59,118,236,184,98,218,180,105,15,74,150,44,233,76,83,33,211,236,87, 57,69,101,133,242,59,206,236,53,101,57,66,45,226,212,205,247,235,175,191,150, 131,7,26,79,72,93,167,40,32,162,114,136,186,143,83,185,66,249,233,24,82,150,67, 132,30,211,24,84,234,214,75,23,66,169,94,67,207,209,5,84,202,163,156,116,39,253, 177,247,177,114,44,43,84,207,217,181,107,151,124,91,163,70,141,67,118,118,118, 170,155,170,77,25,29,101,149,0,62,129,37,79,1,142,142,142,146,166,241,31,160, 244,234,213,43,137,255,120,255,243,26,63,201,72,94,94,94,210,147,39,79,62,164, 240,240,240,15,175,211,107,103,206,156,145,220,221,221,165,164,164,164,15,207, 71,70,70,74,161,161,161,242,125,186,125,254,252,185,188,237,211,167,79,255,181, 189,166,185,185,185,209,15,147,210,38,193,247,145,39,241,239,162,207,248,241, 227,167,172,95,191,94,238,139,203,255,101,131,6,13,26,236,167,187,27,55,110,20, 237,158,28,123,247,238,157,20,24,24,40,223,15,14,14,150,98,99,99,229,251,137, 137,137,242,243,116,140,165,23,19,19,243,225,248,160,99,140,182,167,188,65,65, 65,18,63,97,203,207,243,192,67,226,65,130,196,131,5,73,213,150,47,95,46,31,7, 221,187,119,63,47,225,92,13,186,137,58,179,251,217,219,219,127,248,205,105,11, 58,135,196,197,197,253,235,60,65,231,17,101,25,69,175,209,185,130,7,30,82,64, 64,192,135,207,255,250,245,107,41,36,36,228,163,239,155,27,232,60,198,222,151, 57,219,5,223,71,158,224,231,231,103,189,104,209,162,197,163,71,143,254,112,5, 113,194,132,9,29,120,32,152,210,180,105,83,137,7,4,162,93,146,41,250,14,233,59, 166,239,54,179,215,232,251,78,95,71,161,50,227,220,185,115,210,149,43,87,62,252, 77,58,22,238,222,189,43,61,126,252,88,126,175,161,67,135,74,60,32,253,80,182, 40,81,93,229,234,213,171,210,245,235,215,229,191,71,101,12,255,191,228,186,9, 189,47,81,30,99,132,202,175,244,199,95,118,208,251,241,160,76,42,94,188,120,196, 218,181,107,63,125,68,126,86,36,4,32,160,90,185,22,128,232,146,252,30,128,240,2, 216,36,253,227,111,191,253,182,60,63,1,70,218,216,216,200,39,103,120,31,20,181, 104,209,66,50,54,54,78,153,57,115,166,122,167,4,3,208,94,90,27,128,228,39,249, 45,0,185,119,239,30,173,132,254,175,166,128,134,13,27,110,228,55,242,133,157, 220,68,1,69,163,70,141,164,149,43,87,74,223,127,255,189,212,187,119,239,92,187, 224,185,105,211,38,249,123,175,93,187,246,30,73,197,241,0,198,128,0,128,214,41, 86,172,216,135,206,172,116,210,123,241,226,197,192,208,208,208,130,52,40,144, 22,252,3,38,79,215,72,131,1,43,86,172,232,207,3,180,227,162,252,0,0,240,94,157, 58,117,146,21,10,197,135,26,245,222,189,123,203,250,251,251,119,163,113,123,52, 45,110,110,226,193,7,91,182,108,153,220,173,138,186,239,210,52,190,52,203,161, 166,81,151,64,90,251,195,196,196,68,170,92,185,242,142,79,233,186,149,29,24,3,2, 0,90,237,238,221,187,38,190,190,190,67,105,124,5,141,213,129,247,104,145,42, 234,43,236,224,224,176,159,23,78,81,162,252,0,0,144,185,227,199,143,247,14,9,9, 41,70,11,245,101,92,200,56,55,52,104,208,64,78,185,137,198,45,210,130,136,60, 40,123,52,127,254,252,203,52,254,85,149,208,2,2,0,90,109,205,154,53,245,125, 124,124,108,233,74,80,227,198,141,69,217,117,2,77,223,72,131,84,121,224,17,233, 232,232,184,89,148,31,0,0,50,183,97,195,6,131,123,247,238,117,163,214,118,92, 228,250,7,173,99,66,235,76,241,0,100,167,157,157,93,140,40,255,167,66,0,2,0,90, 237,238,221,187,221,162,162,162,76,104,86,18,229,252,231,186,206,217,217,153, 186,165,209,140,109,247,126,250,233,167,231,162,252,0,0,144,185,91,183,110,85, 241,241,241,105,64,211,226,106,98,129,219,188,128,151,185,114,0,98,110,110,30, 221,177,99,71,181,116,241,69,0,2,0,90,235,228,201,147,54,225,225,225,131,169, 255,107,175,94,189,68,217,117,2,93,165,163,105,17,169,75,90,139,22,45,78,42,20, 10,213,77,139,8,0,160,99,252,252,252,70,197,199,199,23,160,105,111,105,113,98, 120,127,145,139,22,197,172,82,165,138,251,130,5,11,158,138,242,231,4,2,16,0,208, 90,171,87,175,110,22,20,20,100,211,182,109,219,220,94,113,94,107,60,123,246,76, 94,4,179,116,233,210,175,218,180,105,179,71,148,31,0,0,50,119,233,210,165,2, 143,30,61,234,76,107,133,245,239,223,95,148,93,39,208,154,31,52,248,156,102,193, 178,177,177,89,173,167,167,167,150,139,92,8,64,0,64,43,241,115,159,226,233,211, 167,3,147,146,146,24,13,12,84,245,12,28,121,213,254,253,251,89,116,116,52,205, 142,114,161,125,251,246,175,68,249,1,242,3,94,73,252,207,180,169,0,159,107,206, 156,57,77,95,191,126,93,161,121,243,230,52,161,135,40,187,78,160,238,189,167,79, 159,102,37,75,150,12,108,216,176,225,121,81,254,156,66,0,2,0,90,105,198,140,25, 118,33,33,33,78,182,182,182,140,86,63,7,198,34,35,35,217,129,3,7,152,165,165,37, 107,211,166,205,97,81,126,128,252,130,7,31,14,203,150,45,91,177,97,195,6,213,46, 134,6,58,139,2,218,208,208,208,47,226,226,226,244,105,140,33,173,26,14,114,215, 103,22,30,30,78,221,175,174,254,252,243,207,175,69,249,115,10,1,8,0,104,37,55, 55,183,161,188,194,109,217,179,103,79,86,164,72,17,81,118,157,240,247,223,127, 51,119,119,119,42,24,188,39,79,158,236,42,202,15,144,95,240,160,251,209,253, 251,247,237,231,206,157,123,125,248,240,225,43,206,157,59,87,37,237,37,181,116, 15,129,252,111,206,156,57,21,222,188,121,211,187,116,233,210,172,83,167,78,162, 236,58,33,49,49,145,237,222,189,155,6,159,167,54,105,210,100,87,250,181,82,84, 13,1,8,0,104,157,203,151,47,155,63,126,252,184,187,177,177,49,166,69,76,135, 214,254,160,171,116,149,43,87,222,194,11,134,183,162,252,0,249,133,141,141,77, 82,231,206,157,231,241,187,5,119,238,220,57,126,226,196,137,127,15,27,54,108, 25,175,68,86,229,207,165,136,182,7,200,232,202,149,43,221,66,66,66,10,246,232, 209,131,89,91,91,139,178,235,132,219,183,111,203,139,220,242,253,225,62,101,202, 148,115,162,252,159,3,1,8,0,104,157,35,71,142,116,10,13,13,173,69,235,126,56,58, 58,138,178,235,132,151,47,95,178,83,167,78,81,69,44,166,127,255,254,39,68,249, 1,242,2,73,146,244,54,111,222,172,95,180,104,81,90,24,217,136,39,99,158,76, 120,50,205,152,46,94,188,120,179,118,237,218,39,104,38,184,39,79,158,20,217,179, 103,207,196,141,27,55,94,208,211,211,43,145,246,94,31,251,51,0,255,194,143,165, 130,193,193,193,163,13,13,13,25,117,191,130,247,191,31,106,253,160,65,232,188, 220,61,204,127,147,9,162,109,62,7,86,66,135,28,187,119,239,158,93,80,80,80,114, 151,46,93,94,138,242,2,100,215,195,135,15,245,135,12,25,210,149,86,249,30,52, 104,144,60,221,44,48,121,80,96,72,72,8,107,214,172,217,41,254,155,115,23,229,7, 208,86,94,94,94,133,182,110,221,218,245,250,245,235,173,91,182,108,89,154,7,215, 49,225,225,225,201,236,159,224,131,210,127,126,248,107,215,174,149,76,76,76, 138,42,31,83,119,17,95,95,95,185,127,38,45,152,22,17,17,33,143,143,2,16,217,181, 107,87,77,126,28,86,173,91,183,46,171,95,191,190,40,187,78,224,245,57,90,17,158, 186,95,133,214,172,89,115,203,145,35,71,68,155,124,22,148,236,144,99,97,97,97, 201,107,214,172,217,192,15,212,163,243,230,205,219,222,181,107,215,8,254,116, 170,104,59,128,172,252,249,231,159,69,252,252,252,218,23,47,94,28,253,114,211, 36,39,39,203,211,34,242,202,87,106,227,198,141,15,171,179,95,46,128,58,13,29, 58,212,110,212,168,81,7,222,188,121,83,210,192,192,224,116,197,138,21,47,241, 74,224,117,254,187,167,5,53,149,199,117,166,199,55,63,238,83,155,55,111,190, 204,217,217,89,30,255,65,221,17,139,21,43,22,29,26,26,106,100,106,106,106,100, 97,97,145,217,102,0,255,113,227,198,141,30,241,241,241,138,190,125,251,50,234, 234,11,76,158,222,157,151,189,140,215,233,174,205,158,61,219,95,148,255,115,161, 11,22,228,88,187,118,237,94,242,138,209,85,47,47,175,21,227,198,141,251,187,99, 199,142,227,70,140,24,81,152,33,8,129,207,240,234,213,171,62,225,225,225,37,58, 119,238,76,107,93,136,178,235,4,55,55,55,118,253,250,117,86,181,106,213,96,254, 91,187,40,202,15,160,141,120,160,97,119,239,222,189,179,69,139,22,141,169,83, 167,78,45,126,255,171,125,251,246,45,228,193,199,21,254,114,16,79,193,105,41,36, 179,116,240,224,193,162,188,188,233,146,146,146,66,231,134,119,173,91,183,94,61, 96,192,128,54,169,169,169,65,52,77,183,158,30,170,52,32,182,124,249,242,146, 175,95,191,238,71,11,220,210,36,39,240,126,237,143,189,123,247,202,193,88,253, 250,245,213,219,244,161,68,125,190,68,9,224,99,146,146,146,10,87,169,82,229,25, 191,43,241,3,87,42,85,170,148,55,47,4,226,120,4,45,129,250,240,10,41,253,48,41, 109,18,124,69,121,10,255,215,244,236,237,237,111,232,235,235,75,103,207,158,21, 237,6,157,49,109,218,52,249,251,30,54,108,216,106,9,107,33,64,30,196,131,135, 242,245,234,213,123,62,113,226,196,171,252,24,206,81,83,69,239,222,189,183,22, 47,94,60,162,109,219,182,127,45,92,184,80,57,11,22,117,215,242,227,231,13,137, 87,162,68,63,37,200,161,7,15,30,40,203,156,237,31,255,134,242,134,78,157,58, 125,99,96,96,32,245,239,223,95,244,111,235,12,15,15,15,169,64,129,2,82,249,242, 229,95,92,187,118,173,40,211,0,116,193,210,65,43,87,174,44,180,120,241,98,211, 176,176,48,179,228,228,228,130,9,9,9,102,252,248,51,99,239,79,228,233,111,41, 101,121,73,201,208,208,80,42,91,182,108,40,175,48,86,162,62,251,1,1,1,182,244, 60,191,149,163,233,62,125,250,160,15,63,100,27,175,96,212,122,249,242,101,181, 234,213,171,51,90,24,10,24,123,253,250,53,85,222,24,13,8,172,83,167,206,38,116, 191,130,188,232,212,169,83,83,227,227,227,35,121,165,175,39,63,134,35,69,249,51, 226,21,164,170,188,76,9,183,178,178,106,186,126,253,250,135,212,93,36,141,81,86, 219,1,164,183,121,243,102,189,217,179,103,119,163,43,254,131,7,15,22,101,215,25, 212,197,151,22,184,117,116,116,220,215,180,105,211,55,162,252,170,128,246,74,29, 114,238,220,57,171,110,221,186,205,223,186,117,171,7,47,0,78,243,131,108,29,63, 153,119,230,193,71,67,254,114,45,158,170,243,84,137,167,10,60,217,240,68,81,176, 149,40,37,37,37,25,102,252,91,212,68,78,7,51,192,167,184,119,239,94,141,216,216, 88,139,94,189,122,49,83,83,83,81,118,157,112,226,196,9,230,227,227,195,236,237, 237,221,38,77,154,244,64,148,31,64,219,240,50,162,224,195,135,15,59,150,42,85, 106,85,179,102,205,194,68,249,51,99,96,96,224,59,111,222,188,201,20,124,136,242, 2,124,12,63,14,11,6,5,5,213,162,5,110,91,182,108,41,202,174,19,194,194,194, 228,41,222,11,22,44,24,239,228,228,116,72,148,95,85,112,105,90,71,52,104,208, 160,212,119,223,125,119,210,144,179,180,180,156,214,191,127,255,11,252,113,44, 15,68,226,69,219,102,133,7,47,166,14,14,14,221,105,246,4,154,206,142,7,52,65, 161,161,161,69,202,150,45,107,60,98,196,8,209,230,0,255,162,167,167,215,128,250, 160,182,110,221,90,148,85,39,4,6,6,178,185,115,231,178,66,133,10,49,94,48,172, 248,220,223,43,64,110,216,180,105,83,41,30,132,24,243,178,39,199,227,151,120,0, 142,99,31,62,219,221,187,119,171,166,164,164,20,107,218,180,169,124,94,5,198,22, 47,94,76,51,211,177,70,141,26,157,230,65,254,157,249,243,231,139,54,81,9,180, 128,232,128,239,191,255,190,116,76,76,204,81,234,210,178,107,215,174,182,23,46, 92,216,55,109,218,180,183,170,168,204,116,239,222,125,252,203,151,47,171,151, 42,85,202,135,191,255,143,29,59,118,108,149,154,154,250,90,194,216,33,77,201, 87,59,58,57,57,217,154,6,146,22,40,80,64,148,53,223,243,246,246,102,95,126,249, 165,220,250,65,205,226,179,103,207,214,216,149,41,0,85,90,181,106,149,145,185, 185,185,255,143,63,254,248,201,93,175,64,235,228,233,50,39,34,34,130,38,202,49, 65,25,195,88,124,124,60,91,182,108,25,251,227,143,63,104,225,193,208,78,157,58, 205,227,245,66,141,45,234,169,117,45,32,70,70,70,122,188,2,171,144,222,15,180, 252,112,155,33,177,12,247,115,139,114,80,86,250,251,114,74,235,167,45,223,82,50, 53,53,149,34,35,35,53,254,195,165,64,160,125,251,246,75,74,150,44,105,184,114, 229,202,142,252,179,4,137,182,201,174,179,103,207,218,240,131,183,83,133,10,21, 126,154,60,121,242,134,111,190,249,38,148,63,93,144,33,176,213,164,68,81,134, 188,196,198,198,198,45,32,32,160,207,188,121,243,216,15,63,252,192,168,153,156, 90,214,116,1,253,86,169,64,120,241,226,5,59,127,254,60,91,179,102,13,205,8,70, 179,205,61,26,60,120,240,55,170,184,96,0,144,27,248,49,109,146,146,146,114,151, 7,210,111,69,121,65,235,105,172,130,170,14,29,59,118,244,242,246,246,14,63, 116,232,80,145,22,45,90,48,93,107,9,161,238,241,161,161,161,242,204,138,155,55, 111,102,103,206,156,97,229,202,149,75,226,193,199,216,153,51,103,222,21,109,175, 74,185,18,128,204,159,63,223,234,226,197,139,189,111,221,186,85,62,57,57,217, 44,33,33,193,148,7,29,242,226,67,137,137,137,52,160,44,125,50,76,75,6,233,146, 126,90,162,251,185,85,217,165,169,102,83,210,82,114,186,91,74,73,236,125,197,80, 121,155,152,148,148,68,183,84,129,136,55,48,48,136,163,84,187,118,237,224,17,35, 70,108,231,21,119,181,157,148,103,205,154,229,192,15,182,54,188,98,215,66,149, 193,7,177,178,178,178,24,61,122,244,168,30,61,122,120,241,255,65,249,116,174,28, 83,58,44,95,5,32,78,78,78,135,121,160,254,213,193,131,7,237,104,225,61,154,38, 145,230,250,215,21,252,60,193,222,189,123,39,7,34,69,138,20,137,111,221,186,245, 129,229,203,151,255,82,173,90,181,40,209,182,0,218,42,42,42,202,64,66,179,120, 126,145,167,3,16,94,255,244,189,125,251,246,129,27,55,110,140,28,48,96,128,130, 214,155,210,165,117,64,104,240,61,45,218,25,30,30,78,93,158,165,202,149,43,223, 107,210,164,201,247,171,87,175,190,66,23,189,52,73,163,149,69,126,254,49,24,55, 110,92,155,45,91,182,252,254,252,249,243,234,116,62,178,182,182,102,180,120,144, 174,84,50,232,127,166,217,162,168,111,247,157,59,119,254,191,189,251,0,139,234, 232,250,0,62,139,82,20,68,176,16,197,94,147,216,176,107,176,247,30,107,84,68, 141,41,150,136,70,99,137,198,36,230,213,79,19,123,137,37,182,228,53,182,196,94, 80,172,24,84,236,29,81,193,2,136,74,85,164,73,135,251,205,153,176,188,88,7,112, 247,178,176,255,223,243,204,179,203,238,185,187,203,150,123,231,220,105,244,5, 232,246,224,193,131,94,60,3,141,147,109,155,19,107,215,174,173,104,101,101,117, 211,205,205,205,151,230,73,215,165,134,13,27,250,200,98,64,239,18,101,1,121,201, 220,185,115,111,45,88,176,160,51,223,25,118,230,191,11,43,254,59,161,153,216,10, 165,23,243,244,162,61,57,65,215,181,39,39,50,159,164,40,144,233,82,183,95,250, 87,209,116,162,150,236,223,53,12,178,130,78,92,36,191,169,240,253,65,74,165,74, 149,82,106,212,168,17,209,168,81,163,93,211,167,79,63,202,147,143,183,60,28,128, 225,227,199,61,250,45,230,214,201,66,208,173,20,89,128,33,163,46,70,252,251,232, 210,173,91,55,119,174,92,88,88,24,237,191,181,179,127,82,121,249,56,163,61,17, 94,240,165,82,32,83,201,13,169,236,197,147,224,153,75,198,201,239,244,146,152, 94,196,73,112,126,156,137,179,180,180,124,206,19,143,160,117,235,214,237,227, 245,207,231,188,94,254,154,167,208,47,85,19,144,79,63,253,180,131,167,167,167, 27,117,49,232,209,163,7,27,62,124,56,171,87,175,30,173,100,106,84,83,181,62, 127,254,92,52,127,241,100,140,93,184,112,161,221,140,25,51,104,246,169,11,178, 237,114,130,255,208,44,121,101,38,128,255,232,242,244,78,3,222,40,95,37,32,100, 210,164,73,247,248,197,114,89,220,27,100,78,56,244,157,124,144,79,120,233,196, 75,70,19,96,22,188,113,181,103,58,59,69,99,63,168,184,186,186,190,124,55,64,94, 101,194,144,128,228,23,121,190,46,145,94,31,218,38,139,123,11,205,75,151,185, 229,141,199,146,183,161,227,12,213,67,169,171,47,79,62,100,225,122,163,90,173, 127,206,156,57,181,151,47,95,190,62,52,52,148,45,90,180,136,141,25,51,198,168, 146,142,204,138,20,41,194,168,239,225,160,65,131,216,180,105,211,76,206,159,63, 79,11,42,233,37,1,225,95,50,139,184,184,184,99,12,242,171,124,151,128,188,163, 204,59,226,108,237,148,115,136,90,52,148,244,75,0,120,61,74,62,114,187,178,6, 186,145,231,19,16,29,200,81,197,31,94,164,202,25,137,128,128,128,130,174,174, 174,147,31,61,122,100,247,213,87,95,177,241,227,199,27,109,242,145,217,147,39, 98,173,151,20,91,91,219,16,89,108,78,197,198,198,22,58,114,228,136,159,44,14, 242,44,12,76,206,93,168,84,1,200,233,187,5,4,39,0,212,147,44,11,0,200,10,125, 238,16,50,252,249,231,159,53,111,223,190,221,187,116,233,210,236,219,111,191, 149,133,27,5,106,254,250,231,159,127,40,17,139,45,89,178,164,222,22,23,75,75,75, 163,254,141,170,124,206,144,43,242,213,32,116,0,200,151,244,153,128,80,242,129, 150,96,245,228,233,65,232,96,56,244,181,67,120,193,177,99,199,186,63,123,246, 204,170,111,223,190,172,76,153,50,178,112,163,112,225,194,5,230,229,229,197,74, 149,42,117,173,121,243,230,250,92,246,158,38,187,86,251,44,45,154,37,213,131,22, 16,0,48,116,250,236,130,69,9,72,188,44,8,116,6,39,189,64,39,244,158,128,248, 250,250,218,132,133,133,57,211,92,254,131,7,15,150,133,27,141,45,91,182,136,249, 152,235,212,169,227,58,113,226,68,125,246,169,180,148,5,232,24,253,47,145,178, 32,208,25,36,32,0,96,232,244,185,110,23,37,32,122,153,69,18,94,11,9,8,232,132, 222,19,144,5,11,22,180,12,14,14,254,160,113,227,198,172,126,253,250,178,112,163, 64,83,240,186,185,185,49,91,91,219,160,118,237,218,237,144,197,191,35,181,151, 251,164,4,68,111,235,154,192,43,208,245,0,0,12,157,62,91,64,168,197,29,45,32, 234,65,2,2,58,161,247,4,196,203,203,171,79,116,116,180,166,127,255,254,70,179, 162,177,12,173,60,73,73,136,157,157,221,225,137,19,39,6,202,226,223,17,181,128, 232,107,199,255,58,104,1,81,23,90,64,0,192,208,233,115,12,8,141,73,64,2,162,30, 156,244,2,157,208,215,14,65,88,184,112,225,123,247,238,221,107,95,170,84,41,214, 171,87,47,89,184,81,72,73,73,17,221,175,204,204,204,104,33,191,173,178,120,29, 80,187,5,132,14,6,209,88,244,86,53,56,24,0,128,161,211,103,23,44,58,216,96,63, 168,30,188,215,160,19,122,77,64,46,93,186,228,20,21,21,85,166,115,231,206,172, 92,185,114,178,112,163,112,227,198,13,118,234,212,41,86,190,124,121,191,209, 163,71,95,146,197,235,128,153,44,64,199,168,63,110,172,44,8,116,6,205,225,0,96, 232,244,153,128,96,22,44,117,225,189,6,157,208,91,2,18,23,23,103,126,245,234, 213,222,52,208,122,224,192,129,178,112,163,177,99,199,14,150,148,148,196,222, 123,239,189,63,154,53,107,246,84,22,159,71,97,64,160,122,144,128,0,128,161,211, 103,2,66,45,32,9,104,117,87,13,186,187,129,78,232,109,53,192,197,139,23,55,11, 14,14,118,172,83,167,14,115,116,116,204,184,253,210,165,75,204,198,198,70,180, 4,180,109,219,150,89,88,88,208,52,189,236,233,211,167,98,117,240,138,21,43, 138,56,63,63,63,177,76,188,149,149,21,235,212,169,19,43,81,162,132,88,62,158, 166,175,165,82,181,106,85,214,174,93,59,102,110,110,46,30,211,206,206,142,90,21, 88,66,66,2,59,119,238,156,120,172,59,119,238,48,218,41,221,191,127,159,57,56, 56,136,24,26,252,253,240,225,67,214,170,85,43,113,27,185,123,247,46,243,244, 244,100,246,246,246,172,117,235,214,226,49,99,98,98,68,108,68,68,132,120,172, 154,53,107,190,238,223,204,22,90,120,112,219,182,109,244,255,199,242,247,196, 245,244,233,211,178,77,116,65,187,82,179,154,196,25,18,122,239,53,26,125,29,115, 140,91,166,131,45,22,133,2,0,67,167,239,3,129,24,11,135,99,142,254,100,58,230, 32,1,1,157,208,75,11,8,255,162,106,60,60,60,122,71,69,69,21,164,181,63,138,20, 41,146,113,223,252,249,243,217,144,33,67,216,254,253,251,89,124,124,60,155,56, 113,34,251,251,239,191,69,18,64,183,211,218,24,161,161,161,108,212,168,81,226, 146,146,137,47,190,248,66,196,110,221,186,149,77,158,60,153,86,247,102,191,253, 246,27,251,207,127,254,35,30,115,209,162,69,34,137,33,148,200,76,152,48,129,37, 39,39,139,248,1,3,6,176,141,27,55,138,133,255,166,76,153,194,214,175,95,47,18, 1,103,103,103,118,253,250,117,118,237,218,53,54,98,196,8,246,224,193,3,113,31, 61,62,61,215,180,105,211,216,225,195,135,89,100,100,36,251,242,203,47,217,197, 139,23,95,247,175,102,11,117,189,186,119,239,30,43,94,188,248,177,121,243,230, 121,201,226,117,36,137,169,127,150,60,37,58,58,154,61,123,246,76,22,7,57,68,147, 24,164,211,231,20,206,0,0,186,160,207,22,16,18,79,39,13,113,204,209,31,237,49, 199,194,194,2,61,28,64,39,244,210,2,242,227,143,63,218,248,250,250,118,163,214, 11,74,64,50,75,76,76,100,29,58,116,96,51,103,206,100,199,143,31,23,173,23,123, 247,238,21,45,29,113,113,113,108,213,170,85,34,225,120,244,232,17,235,214,173, 27,171,85,171,22,163,150,2,237,125,179,103,207,22,45,18,193,193,193,162,101, 228,235,175,191,102,5,10,20,200,156,157,103,92,167,231,162,150,11,26,244,77,137, 141,187,187,187,88,125,156,90,83,42,84,168,192,194,195,195,105,149,118,214,163, 71,15,145,240,80,242,210,181,107,87,118,249,242,101,81,40,73,249,236,179,207, 24,141,97,177,182,182,102,239,138,18,45,254,90,211,202,151,47,191,89,197,179, 52,137,76,229,62,155,212,170,69,159,31,189,223,159,124,242,137,44,28,114,128, 190,75,244,29,226,201,125,26,37,123,0,0,198,138,215,31,18,168,130,124,228,200, 17,230,228,228,36,11,135,28,160,19,186,116,204,41,86,172,88,92,166,19,96,0,57, 166,151,22,144,27,55,110,180,229,21,208,10,212,205,233,131,15,62,120,225,62,74, 22,26,52,104,32,174,83,23,169,176,176,48,209,218,224,226,226,194,2,3,3,69,107, 73,221,186,117,69,171,4,181,70,116,236,216,81,36,15,212,234,65,9,69,237,218, 181,197,182,212,157,138,98,41,17,49,49,49,201,104,118,165,150,15,45,186,157,186, 89,209,125,212,194,242,222,123,239,137,228,131,80,146,67,93,184,110,221,186,37, 42,202,99,198,140,97,63,253,244,147,88,169,157,102,168,154,55,111,158,104,165, 161,228,99,237,218,181,172,80,161,66,236,93,208,243,83,151,178,146,37,75,134, 242,255,213,93,22,175,67,148,124,168,218,2,210,188,121,243,83,252,115,78,229, 137,40,187,125,251,182,44,28,178,105,195,134,13,226,96,192,191,203,183,191,250, 234,171,7,178,120,0,128,252,172,125,251,246,231,204,205,205,83,233,24,238,237, 237,45,11,135,108,218,188,121,179,40,165,74,149,10,28,54,108,152,191,44,30,32, 43,116,222,2,194,147,138,2,67,135,14,29,165,40,138,9,157,137,160,36,224,101, 218,22,10,74,6,120,133,156,22,43,20,149,126,26,219,65,104,252,71,163,70,141,24, 175,92,137,157,9,181,68,212,168,81,67,196,80,194,97,107,107,43,154,3,169,85,132, 18,134,130,5,11,138,228,68,187,45,221,254,242,243,210,243,80,243,44,37,50,212, 218,178,110,221,58,86,185,114,101,250,65,177,46,93,186,136,150,14,122,12,87,87, 87,17,75,99,84,232,250,227,199,143,217,183,223,126,203,126,253,245,87,54,103, 206,28,17,67,175,35,187,45,24,212,202,67,207,223,186,117,235,131,253,250,245,83, 179,157,153,234,227,76,0,0,32,0,73,68,65,84,88,245,22,16,158,104,185,243,3,194, 65,15,15,143,238,31,127,252,177,232,102,71,201,30,125,110,144,51,52,254,41,32, 32,64,180,230,81,75,32,181,200,117,239,222,125,241,220,185,115,177,232,35,0,24, 181,221,187,119,31,230,251,195,35,135,14,29,234,210,179,103,79,209,13,155,122, 90,20,43,86,76,182,41,188,1,213,211,232,152,67,173,237,43,87,174,100,150,150, 150,180,156,194,175,63,255,252,51,154,63,64,39,116,158,128,240,44,185,226,221, 187,119,27,80,98,64,173,7,47,163,10,60,173,133,65,120,37,149,173,94,189,90,180, 54,84,169,82,133,253,254,251,239,98,92,7,141,215,160,22,137,241,227,199,139,25, 163,40,81,169,94,189,186,120,60,186,109,240,224,193,236,224,193,131,98,192,56, 181,106,80,178,66,9,5,37,23,39,79,158,20,219,16,186,212,94,167,24,154,10,152,90, 85,170,85,171,38,198,123,208,15,235,243,207,63,167,1,243,34,41,161,150,22,127, 127,127,241,60,75,151,46,101,103,207,158,21,171,183,211,227,82,75,14,117,43,26, 55,110,156,168,0,82,146,146,85,52,48,158,102,191,226,137,75,98,217,178,101,87, 201,226,117,140,222,0,85,7,42,243,228,44,245,226,197,139,163,166,76,153,178,224, 204,153,51,189,120,34,105,65,173,85,52,184,95,11,131,5,223,46,115,151,66,122, 159,232,111,250,93,208,119,137,127,247,130,123,247,238,189,148,255,118,126,255, 239,127,255,251,150,71,1,181,241,253,151,185,183,183,119,17,190,143,73,184,115, 231,142,73,241,226,197,205,75,149,42,165,153,57,115,102,152,108,91,178,113,227, 198,130,126,126,126,101,235,214,173,27,194,43,82,178,69,38,53,221,186,117,43,85, 161,66,133,112,94,65,192,88,32,48,90,124,31,153,196,143,223,95,240,171,43,79, 156,56,209,141,215,31,76,95,62,230,64,246,100,62,230,148,46,93,58,146,31,115, 150,173,88,177,98,17,141,191,5,208,5,157,39,32,251,246,237,235,24,25,25,105,75, 173,31,252,224,251,202,253,52,16,92,59,211,21,205,134,69,221,73,54,109,218,36, 186,95,45,89,178,132,53,105,210,68,220,71,73,1,117,89,162,46,91,212,250,64,219, 76,154,52,73,140,221,240,241,241,17,73,2,13,48,39,212,122,65,59,27,122,140,239, 191,255,94,252,104,168,5,132,90,78,168,117,132,20,46,92,88,36,41,212,117,133, 250,204,211,192,116,106,85,161,66,219,210,0,113,106,17,153,62,125,186,120,93,84, 177,163,24,26,11,66,73,10,255,241,137,237,232,204,51,157,141,206,14,26,192,78, 143,195,255,135,107,163,70,141,242,162,255,87,69,137,180,115,86,123,138,66,158, 240,61,230,23,78,157,58,117,106,236,238,238,94,61,38,38,198,132,23,250,48,204, 210,139,121,166,98,193,75,161,244,75,179,76,151,230,153,174,155,50,253,14,98,84, 3,45,210,72,201,32,37,133,84,185,76,124,169,208,109,241,153,174,39,177,255, 117,161,163,237,82,120,50,158,50,108,216,48,207,249,243,231,63,92,179,102,205, 171,207,0,185,42,36,36,100,8,223,63,180,120,248,240,97,48,255,221,61,50,51,51, 107,98,106,106,106,201,239,234,35,219,150,240,237,202,243,253,219,45,59,59,59, 58,123,227,33,9,215,240,36,231,47,254,219,118,230,215,31,75,98,1,242,181,58, 117,234,4,243,139,222,125,251,246,109,113,228,200,145,106,252,120,99,73,133,253, 123,108,161,162,61,222,152,189,84,232,184,100,154,126,89,32,253,82,123,61,175, 163,3,127,42,251,223,177,135,46,83,210,175,107,139,246,24,147,249,88,68,199,161, 120,94,255,122,110,111,111,255,156,31,115,206,254,252,243,207,119,168,37,4,64, 87,52,89,169,152,102,245,76,117,64,64,64,225,182,109,219,158,8,10,10,106,72, 179,82,53,107,214,76,182,73,158,66,227,85,104,92,8,255,49,190,182,107,217,155, 140,30,61,90,204,218,213,191,127,255,153,219,182,109,251,73,22,175,43,252,179, 45,200,147,169,153,169,169,169,243,98,99,99,35,101,241,0,144,109,253,121,233, 196,127,107,95,240,253,164,201,39,159,124,226,106,101,101,117,229,233,211,167, 157,202,151,47,255,125,187,118,237,202,89,90,90,106,120,98,114,204,214,214,182, 156,155,155,219,211,208,208,80,90,156,213,115,196,136,17,180,118,129,217,240, 225,195,155,222,190,125,187,240,236,217,179,189,249,126,179,224,149,43,87,252, 59,118,236,216,190,72,145,34,41,252,49,66,58,116,232,224,235,234,234,218,148, 63,70,50,143,189,124,224,192,129,138,59,119,238,172,93,177,98,69,255,21,43,86, 172,174,86,173,218,0,79,79,207,71,11,23,46,172,121,234,212,169,74,61,123,246, 188,73,253,180,179,186,223,6,80,65,111,246,111,18,62,68,22,8,0,198,65,167,45,32, 83,167,78,109,28,30,30,94,159,186,59,53,108,216,80,22,158,231,80,127,210,79,63, 253,52,91,201,7,37,45,233,227,74,158,181,104,209,226,111,90,7,68,45,91,183,110, 173,248,193,7,31,188,127,254,252,249,40,89,44,0,188,19,171,137,19,39,238,225,9, 70,99,158,24,84,247,243,243,179,229,137,199,64,254,123,47,109,111,111,207,243, 255,88,211,128,128,128,95,121,220,249,164,164,164,114,75,150,44,113,231,49,95, 247,235,215,111,5,223,71,52,183,176,176,72,230,251,207,196,94,189,122,141,166, 46,140,230,230,230,38,251,247,239,95,211,164,73,147,93,124,155,239,248,111,120, 158,183,183,119,232,170,85,171,102,46,94,188,216,181,64,129,2,225,60,145,41,102, 102,102,102,193,247,75,207,251,115,123,246,236,249,133,111,247,112,211,166,77, 21,3,3,3,255,195,183,91,255,214,87,12,0,0,144,75,178,94,147,150,160,181,63,30, 60,120,224,76,93,109,104,234,213,252,216,247,146,186,115,81,151,176,236,160, 177,42,52,118,164,92,185,114,39,198,140,25,227,35,139,215,165,237,219,183,219, 242,231,166,193,42,242,102,46,0,200,49,158,52,196,90,91,91,207,234,216,177,99, 145,241,227,199,87,229,137,193,198,229,203,151,127,23,30,30,158,22,17,17,161, 121,246,236,89,106,112,112,48,37,10,189,102,207,158,189,210,198,198,166,203,143, 63,254,88,159,39,21,221,249,254,242,243,99,199,142,53,171,87,175,30,157,168, 232,156,154,154,42,6,174,241,109,147,163,162,162,196,216,14,126,153,204,147,152, 52,119,119,247,241,252,207,128,67,135,14,181,172,81,163,198,143,60,201,177,104, 222,188,185,221,147,39,79,22,240,215,176,114,232,208,161,195,249,126,234,236, 241,227,199,93,178,210,186,13,0,0,144,27,116,150,128,252,254,251,239,101,248,1, 246,19,106,37,232,222,189,187,44,252,21,116,176,204,111,7,76,26,0,79,179,22,241, 202,136,226,224,224,64,107,127,168,250,15,242,10,76,143,18,37,74,168,58,0,29, 192,8,165,140,28,57,178,235,186,117,235,70,211,66,163,212,221,146,239,7,59,204, 155,55,175,58,191,47,129,90,76,105,226,141,154,53,107,166,126,241,197,23,79,109, 109,109,253,121,146,96,206,127,155,125,248,101,244,216,177,99,207,243,125,67, 196,202,149,43,235,63,127,254,252,175,2,5,10,80,127,117,218,87,36,242,235,98, 159,193,47,173,204,205,205,105,60,84,83,254,88,71,121,124,188,147,147,147,7,255, 59,232,226,197,139,54,161,161,161,69,120,130,50,132,63,198,122,158,140,84,228, 9,11,77,149,137,62,88,0,0,96,144,116,214,5,203,213,213,181,125,96,96,96,209, 129,3,7,102,12,50,207,14,26,28,78,83,235,210,244,121,249,5,77,229,75,131,219, 109,108,108,110,241,247,229,128,154,51,22,241,202,80,205,133,11,23,126,89,173, 90,181,49,180,226,59,0,232,141,201,215,95,127,237,31,22,22,230,80,185,114,229, 21,87,175,94,237,220,187,119,239,223,122,245,234,21,196,19,14,106,50,125,97, 134,42,158,100,68,241,164,164,112,72,72,200,37,126,249,229,222,189,123,235,69, 71,71,63,170,87,175,222,244,238,221,187,159,83,20,37,201,204,204,44,141,146, 146,199,143,31,167,241,191,109,123,244,232,97,159,152,152,232,103,106,106,122, 151,39,34,52,64,125,54,223,174,49,255,187,98,169,82,165,158,248,248,248,132,56, 58,58,254,189,108,217,178,133,195,135,15,119,178,183,183,111,197,242,65,203,39, 181,172,79,157,58,181,213,229,203,151,91,240,68,171,16,79,172,50,15,24,206,60, 104,184,64,166,162,73,191,52,121,169,228,151,132,44,237,13,37,245,53,37,69,91, 120,18,155,204,191,159,41,13,26,52,8,234,223,191,191,107,159,62,125,30,190,246, 209,1,0,84,160,147,4,132,31,24,11,242,138,174,88,242,156,102,158,202,201,224,71, 26,55,66,235,119,16,154,101,138,206,26,166,166,166,102,116,121,162,235,153,23, 28,212,198,209,153,69,90,151,227,101,111,154,230,149,22,42,228,7,237,87,110, 163,88,237,140,89,186,178,115,231,78,22,31,31,207,26,55,110,188,183,83,167,78, 241,178,120,93,185,117,235,86,237,159,127,254,249,64,225,194,133,189,120,37,197, 53,39,159,7,0,100,153,9,175,24,63,228,251,163,103,69,139,22,245,178,182,182, 174,53,110,220,184,63,168,149,162,99,199,142,84,9,164,89,101,168,18,168,221,7, 80,114,145,192,247,109,103,106,213,170,117,102,233,210,165,91,214,174,93,107, 193,221,181,180,180,92,78,179,214,241,152,164,178,101,203,158,191,116,233,210, 151,253,250,245,27,20,19,19,83,130,239,167,34,120,82,179,123,243,230,205,127, 241,219,188,14,30,60,24,254,236,217,179,251,65,65,65,79,120,197,114,153,175,175, 239,28,158,240,56,243,4,200,132,239,147,231,191,241,213,230,17,135,15,31,126, 111,192,128,1,43,255,249,231,159,143,195,195,195,11,82,183,94,154,205,16,114, 134,142,137,180,78,22,21,111,111,239,31,166,79,159,254,127,51,103,206,196,156, 170,0,144,43,116,82,227,230,59,177,122,17,17,17,237,63,252,240,67,214,178,101, 75,89,248,107,209,74,225,79,158,60,17,235,129,204,158,61,91,76,225,75,83,215, 210,212,184,117,234,212,161,133,134,68,130,64,43,157,82,12,63,40,137,117,67,248, 129,95,196,208,106,234,180,38,8,109,67,211,246,210,193,138,214,238,224,21,2,177, 234,57,141,195,88,184,112,161,88,88,144,226,105,61,17,90,77,157,166,230,165,113, 26,148,148,240,131,58,163,241,43,186,168,176,211,162,131,123,246,236,161,214, 143,4,94,9,57,120,226,196,9,217,38,239,140,31,96,204,187,117,235,86,123,226,196, 137,91,249,65,230,182,189,189,125,127,254,191,160,11,22,128,158,241,125,72,252, 181,107,215,186,187,187,187,199,242,36,98,27,37,31,233,119,185,240,162,208,223, 252,247,121,60,253,182,211,188,212,219,178,101,203,3,158,84,244,93,178,100,201, 16,190,191,72,41,83,166,204,150,106,213,170,197,123,122,122,214,225,73,69,208, 140,25,51,46,110,223,190,253,86,92,92,92,193,18,37,74,156,225,251,192,168,49,99, 198,132,243,248,14,124,127,219,135,239,191,182,30,61,122,52,196,205,205,45,54, 62,62,126,37,255,221,223,226,207,211,186,115,231,206,59,127,249,229,151,27,52, 141,120,94,197,247,211,214,46,46,46,91,248,255,214,182,116,233,210,226,152,64, 83,175,99,49,211,156,163,147,120,60,73,101,127,254,249,39,157,28,43,205,143, 157,43,120,18,146,200,143,223,127,200,182,5,0,208,57,237,216,139,183,21,153,102, 205,154,205,166,135,250,241,199,31,149,156,154,55,111,158,50,122,244,104,37,38, 38,70,169,80,161,130,50,117,234,84,197,203,203,75,169,89,179,166,210,181,107, 87,229,202,149,43,202,224,193,131,149,41,83,166,40,124,71,170,244,237,219,87, 113,117,117,85,194,194,194,148,46,93,186,40,252,160,172,60,127,254,92,225,9,144, 178,108,217,50,229,210,165,75,74,155,54,109,148,62,125,250,40,41,41,41,138,147, 147,147,50,103,206,28,229,225,195,135,226,49,70,140,24,161,220,188,121,147,198, 102,40,183,110,221,18,143,223,187,119,111,133,31,247,101,47,53,75,246,237,219, 71,149,14,133,39,79,143,42,85,170,84,143,191,63,181,114,88,106,191,161,212,209, 150,161,67,135,126,202,19,143,53,252,185,78,214,170,85,43,180,83,167,78,235,151, 47,95,110,205,0,64,223,104,26,222,223,101,65,144,61,252,88,240,153,149,149,149, 194,247,157,202,213,171,87,101,187,91,200,134,180,180,52,101,214,172,89,116,96, 87,106,215,174,125,143,39,185,37,100,159,135,14,208,52,188,121,55,35,6,0,157, 123,231,22,144,221,187,119,219,125,243,205,55,3,168,105,156,90,15,114,138,90,55, 168,21,130,239,31,69,75,198,240,225,195,69,75,5,45,20,200,43,212,140,102,136, 105,215,174,29,115,119,119,23,93,177,104,245,244,219,183,111,211,202,235,180, 248,151,88,124,144,86,50,167,46,91,46,46,46,162,21,131,214,223,160,110,80,52, 182,228,220,185,115,172,69,139,22,140,90,34,104,160,60,181,78,80,92,161,66,133, 196,2,136,60,137,17,171,159,151,42,85,74,246,82,165,232,127,160,193,231,244,255, 240,215,154,228,239,239,191,88,182,205,107,80,203,133,118,177,186,4,246,191,133, 233,50,47,78,71,221,56,226,15,29,58,148,106,97,97,113,131,63,223,233,81,163,70, 93,157,60,121,178,215,225,195,135,223,248,192,0,0,134,42,44,44,204,188,125,251, 246,3,168,75,46,237,231,235,214,173,43,219,4,178,129,142,141,223,125,247,29,243, 244,244,164,197,126,171,28,57,114,164,53,191,121,135,108,59,0,0,93,210,69,2,210, 145,39,0,85,168,235,21,37,11,239,138,42,239,148,204,100,94,107,67,59,165,175, 118,108,8,117,213,226,73,15,77,109,43,22,59,172,85,171,150,184,157,14,88,212, 229,74,219,133,74,73,111,189,73,76,76,20,133,186,69,209,120,15,74,58,190,253, 246,91,86,173,90,53,246,215,95,127,137,117,58,214,175,95,207,230,204,153,35,18, 7,74,124,222,5,245,177,165,4,160,120,241,226,129,115,231,206,109,199,19,40, 127,217,54,57,69,205,234,180,214,136,22,79,62,222,18,13,0,96,216,38,76,152,80, 240,222,189,123,214,149,42,85,98,29,59,118,148,133,67,14,208,241,114,208,160,65, 236,208,161,67,236,248,241,227,197,100,241,0,0,186,246,206,211,240,94,191,126, 253,227,132,132,4,49,248,60,187,107,100,188,137,242,82,183,47,237,223,116,73,45, 37,84,193,191,127,255,190,232,23,220,163,71,15,209,194,65,131,189,171,87,175, 46,174,83,75,72,100,100,36,219,177,99,135,72,90,168,85,195,222,222,158,6,131, 179,175,191,254,154,85,173,90,85,140,57,161,241,34,52,46,132,90,66,182,111,223, 46,18,23,127,127,127,49,94,132,238,203,169,125,251,246,137,100,199,214,214,118, 135,62,147,15,0,128,252,230,175,191,254,50,137,139,139,43,80,162,68,9,102,109, 141,158,164,250,66,9,30,225,199,83,221,28,184,1,0,178,225,157,18,144,105,211, 166,149,121,240,224,65,75,170,220,83,23,166,119,81,164,72,17,49,192,144,206,204, 80,23,44,237,140,84,116,16,178,180,180,20,215,173,172,172,196,1,137,6,151,83, 161,51,56,99,199,142,101,14,14,14,236,226,197,139,204,194,194,66,76,227,75,133, 186,112,81,107,7,181,166,208,118,51,103,206,100,179,102,205,98,3,6,12,16,93,173, 40,113,161,193,237,161,161,161,98,240,57,221,94,179,102,77,246,209,71,31,137, 110,94,148,220,228,4,181,180,208,148,194,230,230,230,169,142,142,142,123,101, 241,0,0,240,63,169,169,169,212,132,93,80,23,147,129,192,155,101,234,41,240,206, 61,33,0,0,178,77,121,135,65,232,189,123,247,158,70,11,101,141,28,57,242,149, 129,110,217,197,147,5,37,41,41,73,92,231,149,120,49,80,78,123,157,6,145,19,186, 164,191,181,183,251,248,248,40,81,81,81,226,111,158,72,40,79,159,62,85,246,238, 221,171,60,123,246,76,60,222,162,69,139,148,113,227,198,101,60,7,221,127,253, 250,117,49,208,93,139,158,211,219,219,91,20,237,243,208,245,197,139,23,43,57, 225,233,233,169,240,228,73,169,81,163,198,45,158,20,225,244,29,64,254,134,65, 232,186,87,148,151,107,77,155,54,149,237,110,225,29,208,177,138,253,187,86,204, 55,146,207,67,23,48,8,29,0,94,144,227,51,31,247,239,223,55,239,212,169,83,111, 106,169,160,150,136,119,149,121,13,142,204,235,122,100,190,78,93,188,180,221, 188,232,246,247,223,127,63,227,62,154,82,151,186,97,209,160,116,106,129,160,191, 121,130,194,120,18,146,17,67,131,207,169,100,70,3,197,169,229,35,51,122,142,158, 61,123,178,156,160,231,166,181,73,202,148,41,179,182,81,163,70,209,178,120,0,0, 120,129,104,1,145,5,129,206,224,189,6,0,213,229,120,199,179,118,237,218,118,161, 161,161,245,27,52,104,192,154,52,105,34,11,87,5,13,46,255,227,143,63,216,217, 179,103,197,216,15,90,27,164,100,201,146,178,205,94,65,221,187,114,130,186,115, 237,218,181,139,186,141,69,55,107,214,108,223,209,163,71,101,155,0,64,30,114, 247,238,93,243,170,85,171,166,106,52,154,23,86,55,215,82,20,133,133,135,135,91, 218,217,217,61,127,221,253,144,37,148,128,188,83,247,96,200,22,140,1,1,0,213, 229,104,39,79,7,217,11,23,46,12,140,137,137,49,233,219,183,111,198,44,85,134, 128,198,139,180,111,223,94,204,158,146,147,228,227,93,28,59,118,76,44,116,200, 159,119,255,79,63,253,228,39,139,7,128,188,37,34,34,162,210,204,153,51,87,44,91, 182,172,89,250,77,52,29,54,173,118,206,110,222,188,89,115,214,172,89,191,95,185, 114,165,255,155,31,1,178,128,18,16,84,138,213,131,247,26,0,84,151,163,22,144, 121,243,230,21,247,241,241,105,103,99,99,35,6,115,3,19,221,174,104,74,95,51,51, 179,180,50,101,202,108,164,69,8,101,219,0,64,222,210,164,73,19,159,230,205,155, 167,4,6,6,122,244,235,215,111,115,64,64,64,224,253,251,247,237,134,13,27,54,119, 224,192,129,35,76,77,77,163,235,212,169,131,185,176,223,13,18,16,117,225,189,6, 0,245,41,57,24,132,222,189,123,119,39,218,116,192,128,1,98,85,114,67,49,105, 210,36,133,87,12,100,97,122,113,237,218,53,197,210,210,82,225,201,199,253,203, 151,47,91,190,250,78,3,64,126,48,107,214,172,42,252,119,254,196,196,196,68,41, 90,180,168,248,221,23,42,84,72,41,92,184,176,50,113,226,68,23,217,246,32,69,43, 115,251,97,16,186,126,101,26,132,62,67,242,121,232,2,6,161,3,192,11,178,221,5, 235,232,209,163,133,130,130,130,92,104,10,191,129,3,7,190,176,96,160,90,248,190, 147,93,185,114,69,116,121,138,136,136,16,183,209,186,30,187,119,239,102,39,79, 158,20,139,243,37,37,37,49,15,15,15,182,127,255,254,140,24,125,162,177,31,180, 26,123,157,58,117,14,54,104,208,0,253,191,1,242,169,31,126,248,225,190,131,131, 195,31,52,89,69,84,84,148,248,221,211,4,24,252,183,239,51,125,250,244,77,178, 237,33,75,112,86,94,61,120,175,1,64,117,217,206,30,118,236,216,81,205,215,215, 183,62,45,250,215,182,109,91,89,184,206,81,114,49,99,198,12,81,104,161,65,154, 129,235,206,157,59,180,32,34,139,141,141,101,158,158,158,44,58,58,90,44,46,184, 108,217,50,17,227,228,228,36,86,79,215,23,170,132,80,242,99,97,97,17,91,165,74, 149,85,178,120,0,200,219,122,245,234,245,155,189,189,125,184,246,111,107,107, 107,165,85,171,86,203,138,22,45,26,245,182,237,32,75,48,8,93,93,120,175,1,64, 125,74,54,187,96,213,174,93,123,10,109,54,117,234,212,55,181,236,234,213,185, 115,231,148,198,141,27,43,33,33,33,162,251,215,196,137,19,149,81,163,70,137,251, 28,29,29,149,91,183,110,41,7,15,30,84,26,53,106,164,196,197,197,137,219,39,76, 152,160,156,63,127,254,109,15,251,78,246,239,223,175,208,122,40,53,106,212,56, 193,255,196,206,28,192,8,116,235,214,109,1,173,249,195,175,42,77,155,54,245,141, 140,140,180,145,109,3,89,66,179,135,60,70,23,44,253,202,212,5,107,142,228,243, 208,5,116,193,2,128,23,100,107,16,186,187,187,187,213,103,159,125,230,76,43,142, 211,202,225,185,225,230,205,155,52,205,37,117,131,16,3,191,169,123,149,118,182, 43,37,61,89,162,238,89,117,235,214,21,211,242,146,133,11,23,190,241,241,222,21, 61,231,223,127,255,45,46,235,215,175,239,170,209,104,210,100,219,0,64,222,55, 113,226,196,197,222,222,222,206,79,159,62,181,107,221,186,245,92,27,27,155,72, 217,54,144,37,154,244,2,234,192,73,51,0,80,93,182,18,144,21,43,86,180,230,7,219, 90,205,154,53,163,254,206,178,112,189,176,178,178,98,197,139,23,103,211,167,79, 23,11,6,250,249,249,137,68,68,155,124,208,109,52,59,23,173,201,161,181,105,211, 38,214,176,97,195,28,175,239,241,54,129,129,129,236,208,161,67,172,84,169,82, 161,93,186,116,217,69,207,5,0,134,227,242,229,203,69,38,76,152,208,250,198,141, 27,54,9,9,9,150,241,241,241,133,248,254,130,206,78,80,161,9,35,10,103,42,244, 55,205,43,46,173,148,181,109,219,54,205,194,194,194,140,206,38,207,159,63,255, 51,126,211,80,217,54,239,128,78,108,40,233,151,47,151,212,76,37,37,211,101,138, 137,137,73,74,137,18,37,146,248,254,58,190,105,211,166,135,103,205,154,245,207, 107,31,221,240,72,223,127,208,25,188,215,0,160,186,44,39,32,252,24,171,169,95, 191,254,192,184,184,56,205,224,193,131,115,101,240,57,105,221,186,53,91,190,124, 57,219,187,119,175,88,9,125,193,130,5,108,232,208,161,140,6,197,211,122,36,52, 22,131,214,38,89,191,126,61,91,183,110,157,184,125,229,202,149,108,207,158,61, 98,154,92,158,64,177,49,99,198,200,158,38,203,104,144,59,141,47,105,220,184, 177,219,160,65,131,252,157,157,157,101,155,0,128,10,248,62,203,98,200,144,33, 109,156,156,156,102,5,6,6,214,79,76,76,100,133,11,23,102,69,139,22,21,251,5,93, 80,254,215,69,181,185,174,30,83,151,232,245,209,216,56,154,176,195,215,215,119, 60,127,63,198,110,216,176,97,157,129,79,19,142,49,32,234,194,123,13,0,170,203, 114,2,178,122,245,234,234,97,97,97,31,219,219,219,179,206,157,59,203,194,245, 198,206,206,142,94,11,91,179,102,13,243,246,246,102,35,71,142,100,189,123,247, 22,247,77,153,50,133,157,62,125,154,149,43,87,142,173,90,181,138,109,220,184, 81,36,74,20,75,183,81,203,137,169,169,169,228,25,178,46,57,57,89,36,53,22,22, 22,105,60,1,217,97,224,7,117,0,163,50,106,212,168,175,220,221,221,231,4,7,7, 155,209,194,164,116,114,192,193,193,129,149,40,81,34,215,78,160,168,45,45,45, 141,133,132,132,136,19,51,115,230,204,49,191,124,249,242,79,158,158,158,251,249, 93,193,178,109,115,17,18,16,117,225,189,6,0,245,41,89,28,132,222,169,83,39,23, 154,247,158,87,248,21,248,215,133,11,23,20,158,208,40,60,41,59,119,254,252,121, 11,201,91,13,0,42,113,113,113,105,111,107,107,251,204,220,220,92,89,179,102, 141,146,146,146,34,251,57,231,123,205,155,55,87,248,251,241,188,125,251,246,186, 239,139,170,91,165,120,121,138,65,232,250,149,105,16,250,82,201,231,241,206,52, 26,13,6,161,3,192,11,178,116,230,227,214,173,91,166,222,222,222,125,233,172,33, 173,253,1,255,38,110,91,182,108,17,173,32,53,107,214,220,219,164,73,147,4,217, 54,0,160,127,167,78,157,42,204,203,28,154,149,234,151,95,126,97,195,135,15,23, 99,195,140,25,141,147,163,214,144,130,5,11,38,243,196,44,69,22,15,160,75,166, 166,166,89,170,107,0,128,241,200,210,78,97,229,202,149,77,159,61,123,214,188,94, 189,122,140,87,180,101,225,70,129,6,185,83,183,134,146,37,75,198,247,232,209, 227,160,44,30,0,212,177,110,221,186,174,247,238,221,107,208,162,69,11,246,213, 87,95,201,194,141,2,77,214,65,93,86,139,22,45,250,112,202,148,41,79,101,241,0, 186,132,4,4,0,94,150,165,157,194,185,115,231,6,196,197,197,153,246,239,223,63, 99,106,91,99,119,244,232,81,246,224,193,3,26,91,226,62,118,236,88,47,89,60,0, 232,159,162,40,38,94,94,94,67,248,254,138,125,254,249,231,52,62,75,182,137,81, 160,201,50,104,129,214,10,21,42,156,111,216,176,225,51,89,60,128,46,153,153,153, 81,93,35,85,22,7,0,198,35,75,9,8,175,104,119,178,182,182,102,61,123,246,148, 133,26,5,234,202,64,107,127,240,157,42,171,92,185,242,38,172,253,1,96,24,86,175, 94,93,237,209,163,71,173,203,150,45,203,186,118,237,42,11,55,10,148,140,109, 219,182,141,21,41,82,132,181,108,217,114,183,44,30,64,215,76,77,77,105,98,1,28, 39,1,32,67,150,18,144,240,240,112,123,154,254,182,74,149,42,178,80,163,112,246, 236,89,246,207,63,255,208,218,31,1,46,46,46,71,100,241,0,160,142,227,199,143,15, 230,251,43,107,58,89,162,93,160,212,216,93,184,112,129,93,188,120,145,85,172,88, 209,231,251,239,191,63,45,139,7,208,181,244,22,16,140,61,2,128,12,89,74,64,56, 179,150,45,91,26,205,212,149,111,19,19,19,35,86,97,167,193,231,245,235,215,95, 221,166,77,27,116,103,0,48,0,219,183,111,183,184,114,229,74,39,154,106,123,192, 128,1,178,112,163,193,223,23,113,89,174,92,185,255,90,91,91,99,181,118,80,93, 250,24,16,36,32,0,144,33,171,25,133,134,102,81,49,118,247,239,223,23,253,202,61, 60,60,148,170,85,171,30,27,55,110,220,26,217,54,0,160,142,157,59,119,214,9,12, 12,172,219,176,97,67,214,168,81,35,89,184,81,160,53,64,246,237,219,71,107,159, 60,31,50,100,200,33,89,60,128,62,160,5,4,0,94,150,165,133,8,105,224,249,178, 101,203,152,173,173,45,251,232,163,143,68,95,98,99,65,171,39,243,74,141,232,114, 181,121,243,102,113,189,105,211,166,143,157,156,156,70,183,105,211,38,66,182,61, 0,232,159,162,40,26,254,123,28,145,148,148,100,218,183,111,95,12,62,79,71,43, 160,63,122,244,136,117,236,216,241,230,192,129,3,111,240,253,150,108,19,0,157, 67,2,2,0,47,203,82,2,210,186,117,235,63,78,157,58,245,229,200,145,35,53,52,159, 190,49,117,197,162,245,62,180,173,63,54,54,54,177,142,142,142,219,157,157,157, 167,185,184,184,132,72,54,5,0,149,44,90,180,168,164,175,175,111,15,254,27,101, 125,250,244,145,133,27,133,212,212,84,177,86,81,193,130,5,211,234,212,169,179, 70,163,209,40,178,109,0,244,193,220,220,156,22,226,65,2,2,0,25,178,148,128,184, 185,185,141,236,210,165,203,159,167,79,159,46,22,27,27,107,201,15,108,133,249, 205,116,138,145,230,228,53,231,197,44,189,104,175,155,178,127,31,251,229,66,59, 161,220,202,94,82,211,75,202,75,37,57,189,36,101,42,137,233,37,158,138,149,149, 85,156,165,165,229,243,126,253,250,61,92,177,98,197,141,51,103,206,188,238,241, 1,32,23,208,73,130,33,67,134,12,8,15,15,183,163,228,163,82,165,74,178,77,140, 2,173,251,113,242,228,73,154,169,47,232,227,143,63,222,179,96,193,2,217,38,0, 122,97,102,102,70,199,254,100,89,28,0,24,143,44,37,32,233,103,206,140,118,246, 20,158,116,137,194,147,15,89,40,0,168,207,196,215,215,119,8,77,143,237,236,236, 44,139,53,26,187,118,237,98,207,159,63,103,239,191,255,254,238,22,45,90,160, 187,40,228,26,115,115,115,58,241,152,36,139,3,0,227,145,91,173,17,0,0,58,49,121, 242,228,218,247,239,223,175,65,45,31,173,90,181,146,133,27,5,58,97,178,115,231, 78,26,175,151,92,163,70,141,245,232,126,5,185,41,189,5,4,9,8,0,100,64,2,2,0, 121,154,167,167,231,199,17,17,17,150,52,245,110,209,162,69,101,225,70,225,212, 169,83,236,230,205,155,172,122,245,234,215,230,204,153,115,75,22,15,160,79,60,1, 161,222,22,72,64,0,32,3,18,16,0,200,179,60,60,60,74,242,228,227,51,154,169,175, 95,191,126,178,112,163,64,99,98,104,198,62,154,48,164,121,243,230,110,26,141, 38,65,182,13,128,62,89,88,88,80,2,146,40,139,3,0,227,129,4,4,0,242,172,21,43, 86,52,10,12,12,172,68,11,165,214,174,93,91,22,110,20,104,170,240,131,7,15,50, 59,59,187,240,22,45,90,252,41,139,7,208,183,244,89,176,144,128,0,64,6,36,32,0, 144,39,209,218,31,94,94,94,3,19,18,18,24,173,111,81,176,96,150,230,212,200,247, 246,236,217,195,34,34,34,40,33,59,217,175,95,63,127,89,60,128,190,241,4,132,102, 198,68,75,28,0,100,64,2,2,0,121,210,194,133,11,203,134,134,134,118,46,83,166,12, 235,220,185,179,44,220,40,80,50,182,109,219,54,177,88,108,203,150,45,119,203, 226,1,212,80,160,64,1,51,14,9,8,0,100,64,2,2,0,121,210,241,227,199,63,137,140, 140,44,217,173,91,55,246,222,123,239,201,194,141,194,229,203,151,217,197,139,23, 89,213,170,85,31,142,29,59,214,93,22,15,160,134,212,212,212,170,180,158,150,44, 14,0,140,7,18,16,0,200,115,220,220,220,10,251,250,250,246,53,53,53,101,131,6, 13,146,133,27,141,237,219,183,139,21,208,121,2,178,165,104,209,162,33,178,120, 0,125,83,20,197,244,238,221,187,85,210,210,210,98,101,177,0,96,60,144,128,0, 64,158,115,236,216,177,118,161,161,161,77,28,28,28,88,227,198,141,101,225,70, 33,44,44,140,237,221,187,151,149,44,89,50,161,87,175,94,251,100,241,185,233, 198,141,27,166,188,98,90,64,22,7,121,223,186,117,235,42,199,199,199,127,80,171, 86,173,40,89,44,0,24,15,36,32,0,144,231,120,122,122,118,140,141,141,45,64,107, 127,208,20,188,250,70,51,75,253,248,227,143,44,37,37,69,22,154,107,142,31,63, 206,2,2,2,88,217,178,101,61,6,13,26,116,94,22,159,155,204,204,204,170,44,94,188, 120,237,162,69,139,26,202,98,243,139,184,184,56,54,115,230,76,22,18,18,66,211, 71,139,169,146,141,193,174,93,187,190,228,23,129,187,119,239,190,43,139,5,0, 227,129,4,4,0,242,148,133,11,23,22,241,247,247,239,70,139,14,246,234,213,75,22, 174,19,148,228,124,240,193,7,76,163,209,200,66,115,69,90,90,26,219,184,113,35, 13,246,85,28,29,29,247,240,215,153,42,219,38,55,217,217,217,221,189,117,235,86, 241,37,75,150,156,116,114,114,250,239,246,237,219,235,202,182,201,235,104,93, 150,234,213,171,179,194,133,11,179,235,215,175,179,19,39,78,200,54,201,243,182, 108,217,50,233,201,147,39,19,235,212,169,51,179,100,201,146,207,101,241,0,96,60, 48,111,37,0,228,41,167,79,159,238,21,21,21,85,177,71,143,30,52,214,65,22,158, 129,102,136,250,227,143,63,24,205,154,245,207,63,255,48,94,41,98,53,107,214,164, 74,146,152,53,106,252,248,241,172,68,137,18,236,222,189,123,108,245,234,213, 226,76,53,117,239,250,226,139,47,196,246,218,214,143,93,187,118,49,26,123,114, 254,252,121,198,95,7,27,49,98,196,43,107,144,196,198,198,178,181,107,215,138,24, 122,142,175,191,254,154,29,61,122,84,60,198,192,129,3,153,159,159,31,115,117, 117,101,173,91,183,22,107,118,184,184,184,48,75,75,75,182,106,213,42,214,164,73, 19,214,160,65,131,87,94,255,219,248,250,250,178,147,39,79,178,247,223,127,63, 162,119,239,222,135,150,45,91,38,219,36,87,217,218,218,166,186,185,185,253,204, 95,115,167,173,91,183,14,187,120,241,98,191,254,253,251,111,239,210,165,203, 178,185,115,231,62,244,241,241,81,100,143,161,75,151,46,93,98,191,255,254,187, 248,142,56,59,59,179,246,237,219,139,207,150,62,15,74,22,106,213,170,197,190, 250,234,43,241,25,209,231,90,182,108,217,87,190,67,86,86,86,236,155,111,190,161, 69,247,216,95,127,253,197,138,21,43,38,62,243,106,213,170,177,145,35,71,82,171, 143,248,252,41,89,164,239,15,253,77,238,222,189,43,190,151,244,157,225,159,29, 107,219,182,173,228,213,26,62,69,81,10,241,247,235,155,149,43,87,206,136,140, 140,28,193,223,219,29,178,109,0,192,184,32,1,1,128,60,131,87,108,76,28,28,28,62, 77,77,77,213,100,119,240,121,98,98,34,251,229,151,95,196,148,189,221,187,119, 103,83,167,78,101,229,203,151,103,163,70,141,18,149,74,94,89,18,221,172,190,251, 238,59,214,180,105,83,209,186,66,127,83,165,179,121,243,230,140,42,245,180,222, 200,206,157,59,69,133,159,226,104,214,169,73,147,38,137,177,23,84,241,36,180,18, 249,207,63,255,44,98,198,140,25,35,42,177,243,231,207,103,125,250,244,17,3,230, 43,86,172,72,11,40,178,74,149,42,137,4,138,18,135,228,228,100,86,163,70,13,81, 145,205,201,138,238,244,154,168,2,203,43,187,103,120,34,21,195,111,42,42,219,38, 183,241,74,185,79,163,70,141,246,248,251,251,15,224,73,159,85,64,64,192,103,87, 174,92,233,199,19,196,253,60,1,81,109,124,8,37,156,148,92,208,247,128,18,81,250, 60,105,48,255,175,191,254,42,6,244,211,103,248,231,159,127,138,219,23,45,90, 196,120,130,196,58,118,236,200,62,254,248,99,241,29,42,87,174,156,72,48,214,173, 91,39,190,67,244,88,83,166,76,17,137,102,207,158,61,197,109,207,158,61,99,211, 166,77,19,215,41,169,53,49,49,17,235,214,60,125,250,148,141,30,61,90,124,55,40, 49,254,254,251,239,217,255,253,223,255,137,4,72,69,148,9,189,245,251,98,99,99, 163,169,87,175,94,193,202,149,43,155,218,217,217,153,89,91,91,155,242,132,203, 172,80,161,66,166,60,145,50,229,255,139,233,243,231,207,173,121,50,85,49,48,48, 176,118,179,102,205,90,243,100,174,8,79,194,134,243,219,214,191,237,177,1,192, 56,33,1,1,128,60,99,198,140,25,181,31,61,122,212,132,42,238,237,218,181,147, 133,191,130,87,164,216,184,113,227,196,25,109,90,47,131,18,13,58,235,28,29,29, 45,90,34,168,139,213,244,233,211,69,5,241,193,131,7,162,219,204,195,135,15,197, 223,116,214,154,208,245,79,63,253,148,245,237,219,87,180,84,208,25,243,152,152, 152,140,4,132,174,187,185,185,177,245,235,215,179,186,117,235,138,174,91,183, 110,221,98,245,235,215,23,45,29,52,110,133,90,57,168,242,74,221,113,150,46,93, 42,30,139,206,140,83,34,196,43,120,111,251,23,94,65,99,11,168,194,108,107,107, 203,120,5,190,14,127,189,135,100,219,24,2,122,95,195,194,194,138,80,194,70,168, 117,128,39,3,69,248,251,238,68,127,171,213,221,141,90,162,40,41,212,182,116,81, 43,24,181,126,241,247,146,237,222,189,91,124,30,148,168,82,194,65,99,129,138, 23,47,46,190,67,212,234,69,223,33,74,67,120,248,161,0,0,11,233,73,68,65,84,40, 40,129,224,21,112,118,224,192,1,241,253,160,199,160,36,164,66,133,10,162,37, 132,90,70,232,179,55,55,55,207,248,191,232,251,116,248,240,97,145,124,210,247, 136,182,163,46,90,212,122,162,114,2,210,155,151,183,54,185,81,107,16,79,148,77, 78,159,62,157,204,127,19,9,84,120,210,161,45,137,252,127,73,228,201,72,10,45, 56,24,20,20,20,199,191,223,27,120,2,182,101,232,208,161,143,222,246,184,0,96, 188,144,128,0,64,158,113,237,218,181,207,34,34,34,172,232,140,51,141,1,201,46, 26,203,161,221,142,42,131,116,198,155,80,165,144,18,128,248,248,120,209,253,42, 56,56,152,213,171,87,79,116,171,161,138,97,102,84,113,164,74,168,22,157,201, 214,86,162,9,85,214,232,177,180,107,147,148,46,93,90,84,72,73,163,70,141,68,197, 155,87,204,68,242,65,168,37,132,158,39,60,60,92,36,70,217,229,233,233,201,188, 188,188,40,193,185,230,228,228,212,115,242,228,201,209,178,109,12,68,26,79,34, 151,28,61,122,244,3,250,131,222,71,123,123,251,103,101,203,150,221,123,230,204, 153,222,252,61,205,254,7,156,3,244,89,83,151,42,45,234,2,69,107,169,80,66,169, 253,126,208,103,78,223,3,234,162,69,223,33,74,100,73,230,239,16,161,207,157,190, 11,214,214,214,25,159,57,37,32,244,191,81,107,74,230,164,138,174,83,162,67,173, 32,212,130,69,247,211,119,229,229,238,124,42,216,195,203,212,183,5,208,255,68, 175,143,151,52,254,103,106,122,73,203,116,249,66,151,57,74,192,169,0,0,188,9,6, 161,3,64,158,112,224,192,129,34,60,1,105,79,149,190,156,116,83,122,25,85,170, 180,137,3,93,82,107,135,143,143,15,115,119,119,23,3,186,127,248,225,7,81,217, 164,251,94,62,27,159,57,225,32,84,57,165,86,148,199,143,31,139,138,39,37,23,52, 174,128,108,216,176,129,253,244,211,79,34,185,161,110,56,116,157,206,124,159,58, 117,74,220,79,221,179,168,226,249,209,71,31,137,46,95,217,65,175,131,206,152, 211,107,231,149,228,121,60,249,8,228,55,71,230,133,178,111,223,190,82,252,253, 238,69,21,219,114,229,202,61,229,21,255,165,252,245,127,196,19,130,111,248,253, 170,77,55,70,73,31,181,118,80,242,64,173,24,212,77,46,50,50,82,116,217,163,241, 25,132,18,60,122,143,169,155,20,189,222,204,223,155,151,191,11,244,93,161,100, 242,230,205,155,226,239,115,231,206,209,212,200,34,201,164,231,208,162,235,239, 191,255,190,72,86,168,107,224,130,5,11,88,229,202,149,95,72,104,84,66,43,148,75, 63,175,244,66,201,237,243,244,109,146,216,191,9,136,170,227,117,0,32,127,64,11, 8,0,228,9,43,87,174,108,16,20,20,84,179,85,171,86,57,58,75,76,21,195,204,93, 96,104,16,48,85,42,9,93,210,89,106,234,138,67,93,110,168,31,63,37,17,212,61, 134,206,134,183,104,209,34,163,197,34,243,118,218,199,164,219,232,140,47,117, 217,217,186,117,171,24,47,64,99,5,168,75,142,183,183,183,24,19,178,112,225,66, 241,216,148,128,80,69,150,250,250,83,55,44,234,62,69,219,80,197,179,107,215,174, 98,224,114,135,14,29,94,255,79,188,132,186,137,237,223,191,159,206,200,7,127, 254,249,231,39,104,208,123,94,240,228,201,19,141,139,139,203,183,212,125,172, 125,251,246,75,249,255,189,124,252,248,241,247,142,28,57,66,119,151,226,69,157, 254,87,28,117,159,58,116,232,144,24,179,65,73,1,181,110,208,119,108,240,224,193, 98,252,71,195,134,13,69,50,249,237,183,223,138,150,47,106,13,121,211,119,72,59, 176,156,146,146,217,179,103,139,196,146,39,205,34,185,208,126,79,104,91,109,171, 25,141,37,161,214,15,234,150,71,93,232,168,117,140,198,158,168,76,181,247,26,0, 32,131,246,12,206,219,10,0,64,110,242,243,243,51,107,210,164,201,54,126,85,89, 183,110,157,146,19,169,169,169,202,163,71,143,20,158,84,136,191,195,194,194,148, 232,232,104,113,157,46,67,66,66,196,117,186,60,120,240,160,226,235,235,43,98, 121,5,82,121,250,244,169,242,248,241,99,133,87,80,197,118,49,49,49,34,150,238, 167,219,233,177,35,35,35,21,94,129,204,120,190,123,247,238,41,60,153,16,207,73, 2,2,2,50,182,163,120,127,127,127,133,39,84,98,123,173,224,224,96,241,248,89, 181,108,217,50,218,65,43,173,91,183,222,41,123,15,13,201,237,219,183,171,206, 156,57,115,254,216,177,99,63,124,205,221,148,128,60,109,218,180,169,236,223,215, 153,132,132,4,229,212,169,83,202,217,179,103,51,190,31,228,250,245,235,202,190, 125,251,196,103,73,222,246,29,162,207,150,190,59,116,63,79,90,148,187,119,239, 42,60,161,122,97,91,250,172,147,146,146,148,168,168,40,37,60,60,92,220,158,152, 152,168,120,120,120,40,60,129,205,248,126,168,193,211,211,83,124,119,120,89,250, 154,207,0,0,64,191,20,36,32,0,96,224,38,76,152,80,193,206,206,46,170,116,233, 210,25,21,122,99,71,149,224,86,173,90,41,5,11,22,76,254,242,203,47,59,203,222, 67,67,226,237,237,109,246,150,187,85,79,64,116,41,48,48,80,249,240,195,15,149, 184,184,56,89,104,174,66,2,2,0,185,9,99,64,0,192,160,241,186,18,181,128,12,12, 11,11,179,166,46,74,212,125,41,63,81,114,120,146,135,186,134,209,248,130,242, 229,203,223,155,49,99,134,187,44,222,144,212,170,85,43,73,22,147,87,209,24,32, 154,217,76,59,107,26,0,0,188,10,99,64,0,192,160,93,189,122,213,60,32,32,96,8, 245,155,167,117,56,242,155,156,78,55,187,99,199,14,26,40,173,84,168,80,225,79, 158,148,37,203,226,65,29,52,113,65,86,199,240,0,0,24,43,180,128,0,128,65,251, 237,183,223,26,251,249,249,85,166,217,138,28,29,29,101,225,70,225,201,147,39, 108,207,158,61,52,131,18,77,91,187,89,22,15,0,0,96,72,144,128,0,128,65,187,124, 249,114,247,152,152,152,66,52,75,17,157,93,6,198,60,60,60,168,91,26,173,95,113, 98,195,134,13,143,101,241,0,0,0,134,4,9,8,0,24,44,55,55,55,251,136,136,136,193, 52,53,42,173,88,14,255,142,25,217,188,121,179,152,246,213,209,209,209,77,163, 209,252,111,113,9,0,0,128,60,0,9,8,0,24,172,223,126,251,173,121,112,112,176,125, 187,118,237,88,181,106,213,100,225,70,225,206,157,59,98,177,196,226,197,139,223, 105,211,166,205,110,89,60,0,0,128,161,65,2,2,0,6,73,81,20,141,143,143,207,192, 164,164,36,177,72,92,78,7,107,231,55,52,248,60,38,38,134,85,175,94,221,205,217, 217,249,169,44,30,0,0,192,208,32,1,1,0,131,52,110,220,184,106,33,33,33,173,169, 229,163,77,155,54,178,112,163,16,25,25,41,86,78,183,177,177,73,251,232,163,143, 242,212,226,131,0,0,0,90,72,64,0,192,32,249,248,248,12,138,137,137,177,237,222, 189,59,43,86,172,152,44,220,40,156,63,127,158,121,121,121,177,114,229,202,121, 205,155,55,239,154,44,30,0,0,192,16,33,1,1,0,131,115,242,228,73,75,158,128,244, 52,55,55,103,131,6,13,146,133,27,141,109,219,182,49,19,19,19,102,111,111,191, 78,163,209,196,202,226,1,0,0,12,17,18,16,0,48,56,187,118,237,234,18,26,26,90, 183,105,211,166,204,193,193,65,22,110,20,2,3,3,105,86,48,90,105,251,169,179,179, 243,97,89,60,0,0,128,161,66,2,2,0,6,229,206,157,59,5,60,60,60,186,37,38,38,138, 214,15,90,1,29,24,59,120,240,32,11,9,9,161,217,175,118,14,29,58,244,158,44,30,0, 0,192,80,33,1,1,0,131,50,111,222,188,98,15,31,62,236,100,103,103,199,186,118, 237,42,11,55,10,201,201,201,236,239,191,255,166,100,44,169,65,131,6,123,101,241, 0,0,0,134,12,9,8,0,24,20,158,124,244,137,136,136,40,221,165,75,23,90,233,91, 22,110,20,174,95,191,206,206,156,57,67,107,161,60,154,52,105,210,73,89,60,0,0, 128,33,67,2,2,0,6,67,81,20,19,158,128,12,163,129,214,78,78,78,178,112,163,65, 131,207,105,61,148,202,149,43,255,237,224,224,128,193,231,0,0,144,167,33,1,1,0, 131,209,183,111,95,135,7,15,30,212,168,85,171,22,107,217,178,165,44,220,40,132, 135,135,211,160,124,90,251,227,121,149,42,85,54,200,226,1,0,0,12,29,18,16,0,48, 24,151,47,95,174,29,23,23,103,221,171,87,47,86,168,80,33,89,184,81,56,112,224, 0,187,127,255,62,171,88,177,162,231,210,165,75,253,100,241,0,0,0,134,14,9,8,0, 24,140,2,5,10,52,54,51,51,99,237,218,181,147,133,26,133,224,224,96,54,123,246, 108,86,164,72,17,214,164,73,147,101,26,141,38,89,182,13,0,0,128,161,67,2,2,0,6, 35,41,41,169,20,79,66,68,133,219,216,249,251,251,179,97,195,134,177,123,247, 238,177,218,181,107,111,93,181,106,213,81,217,54,0,0,0,121,1,38,216,7,0,131,97, 111,111,127,53,40,40,168,47,157,245,255,238,187,239,104,208,53,51,53,53,149,109, 150,111,196,199,199,179,128,128,0,118,244,232,81,198,19,14,177,248,96,171,86, 173,188,248,251,240,153,70,163,73,146,109,159,79,40,188,164,202,130,64,103,240, 94,3,128,234,144,128,0,128,193,224,149,237,61,209,209,209,159,239,216,177,163, 50,45,188,103,107,107,75,221,178,100,155,229,11,138,162,176,148,148,20,22,25, 25,201,226,226,226,168,21,40,214,209,209,113,235,130,5,11,254,211,168,81,163, 120,217,246,249,76,154,44,0,116,6,9,8,0,168,14,9,8,0,24,140,249,243,231,223,228, 165,203,170,85,171,58,63,120,240,192,234,209,163,71,133,249,205,133,210,139,57, 47,102,153,46,169,152,166,151,130,153,74,129,76,151,154,87,159,69,239,180,103, 240,169,164,164,23,186,158,156,126,157,46,19,211,47,147,210,175,39,104,139,185, 185,121,92,217,178,101,159,247,236,217,243,236,138,21,43,206,241,228,227,53,79, 145,175,81,242,145,34,11,2,157,193,123,13,0,170,67,2,2,0,6,101,242,228,201,119, 248,197,29,89,220,75,52,47,93,190,124,61,55,40,111,184,124,171,196,196,68,198, 19,47,198,147,15,89,104,126,133,46,88,234,66,2,2,0,170,67,2,2,0,249,65,182,42, 249,96,208,232,51,68,165,88,61,120,175,1,64,117,152,5,11,0,0,12,9,18,16,117,225, 189,6,0,213,33,1,1,0,0,67,130,46,88,234,66,2,2,0,170,67,2,2,0,0,134,132,6,161, 99,193,69,245,224,189,6,0,213,33,1,1,0,0,67,66,9,136,177,172,121,98,8,240,94,3, 128,234,144,128,0,0,128,33,161,46,88,56,43,175,30,36,32,0,160,58,36,32,0,0,96, 72,208,5,75,93,72,64,0,64,117,72,64,0,0,192,144,136,46,88,180,50,60,168,2,9,8, 0,168,14,9,8,0,0,24,18,74,64,18,101,65,160,51,9,178,0,0,0,93,67,2,2,0,0,134,4, 9,136,122,168,153,9,9,8,0,168,14,9,8,0,0,24,12,83,83,83,90,3,36,1,93,176,244, 43,253,253,85,52,26,13,18,16,0,80,29,18,16,0,0,48,24,201,201,201,226,172,124, 84,84,20,139,139,139,147,133,67,14,5,5,5,209,133,98,105,105,137,55,25,0,84,135, 4,4,0,0,12,10,175,20,39,250,249,249,177,147,39,79,202,66,33,135,182,109,219, 198,76,76,76,52,197,138,21,67,2,2,0,170,67,2,2,0,0,6,165,85,171,86,103,52,26,13, 155,58,117,42,163,68,4,116,107,245,234,213,108,239,222,189,172,76,153,50,119,70, 141,26,21,36,139,7,0,208,53,77,86,250,217,210,129,0,0,0,64,13,33,33,33,150,131, 7,15,62,114,236,216,49,199,154,53,107,178,111,190,249,134,181,105,211,134,21, 45,90,84,182,41,188,65,90,90,26,187,127,255,62,219,180,105,147,72,64,108,108, 108,20,103,103,231,81,75,151,46,93,35,219,22,0,64,215,144,128,0,0,128,193,57, 116,232,80,165,5,11,22,172,242,244,244,236,144,144,144,160,161,228,195,204,204, 76,28,143,232,184,133,227,146,92,230,227,59,93,143,137,137,97,137,137,137,212, 242,241,180,95,191,126,139,150,44,89,242,11,127,31,229,149,0,0,0,29,67,2,2,0,0, 6,137,142,79,221,187,119,239,112,234,212,169,170,209,209,209,182,252,38,235, 244,98,197,75,225,244,82,40,83,49,79,47,102,233,197,52,211,101,1,94,242,250,193, 140,166,40,78,97,255,174,20,159,148,94,232,122,98,122,161,25,173,226,211,75,92, 166,18,195,75,180,185,185,121,84,233,210,165,159,13,31,62,220,227,251,239,191, 71,223,54,0,200,53,72,64,0,0,0,0,0,64,53,24,132,14,0,0,0,0,0,170,65,2,2,0,0,0, 0,0,170,65,2,2,0,0,0,0,0,170,65,2,2,0,0,0,0,0,170,65,2,2,0,0,0,0,0,170,65,2,2, 0,0,0,0,0,170,249,127,83,186,124,199,82,158,209,51,0,0,0,0,73,69,78,68,174,66, 96,130}; fltk-1.4.3/fluid/code.cxx0000644000175000017500000010436615004135251015360 0ustar albrechtalbrecht// // Code output routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "code.h" #include "fluid.h" #include "Fl_Group_Type.h" #include "Fl_Window_Type.h" #include "Fl_Function_Type.h" #include "file.h" #include "undo.h" #include #include #include #include "fluid_filename.h" #include "../src/flstring.h" #include #include #include #include /// \defgroup cfile C Code File Operations /// \{ /** Return true if c can be in a C identifier. I needed this so it is not messed up by locale settings. \param[in] c a character, or the start of a utf-8 sequence \return 1 if c is alphanumeric or '_' */ int is_id(char c) { return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; } /** Write a string to a file, replacing all non-ASCII characters with octal codes. \param[in] out output file \param[in] text write this NUL terminated utf-8 string \return EOF if any of the file access calls failed, 0 if OK */ int write_escaped_strings(FILE *out, const char *text) { int ret = 0; const unsigned char *utf8_text = (const unsigned char *)text; for (const unsigned char *s = utf8_text; *s; ++s) { unsigned char c = *s; // escape control characters, delete, all utf-8, and the double quotes // note: we should have an option in the project settings to allow utf-8 // characters in the output text and not escape them if (c < 32 || c > 126 || c == '\"') { if (c == '\r') { ret = fputs("\\r", out); } else if (c == '\n') { ret = fputs("\\n", out); } else { ret = fprintf(out, "\\%03o", c); } } else { ret = putc((int)c, out); } } return ret; } /** Write a file that contains all label and tooltip strings for internationalization. The user is responsible to set the right file name extension. The file format is determined by `g_project.i18n_type`. \param[in] filename file path and name to a file that will hold the strings \return 1 if the file could not be opened for writing, or the result of `fclose`. */ int write_strings(const Fl_String &filename) { Fl_Type *p; Fl_Widget_Type *w; int i; FILE *fp = fl_fopen(filename.c_str(), "wb"); if (!fp) return 1; switch (g_project.i18n_type) { case FD_I18N_NONE : /* None, just put static text out */ fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n", FL_VERSION); for (p = Fl_Type::first; p; p = p->next) { if (p->is_widget()) { w = (Fl_Widget_Type *)p; if (w->label()) { write_escaped_strings(fp, w->label()); putc('\n', fp); } if (w->tooltip()) { write_escaped_strings(fp, w->tooltip()); putc('\n', fp); } } } break; case FD_I18N_GNU : /* GNU gettext, put a .po file out */ fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n", FL_VERSION); for (p = Fl_Type::first; p; p = p->next) { if (p->is_widget()) { w = (Fl_Widget_Type *)p; if (w->label()) { fputs("msgid \"", fp); write_escaped_strings(fp, w->label()); fputs("\"\n", fp); fputs("msgstr \"", fp); write_escaped_strings(fp, w->label()); fputs("\"\n", fp); } if (w->tooltip()) { fputs("msgid \"", fp); write_escaped_strings(fp, w->tooltip()); fputs("\"\n", fp); fputs("msgstr \"", fp); write_escaped_strings(fp, w->tooltip()); fputs("\"\n", fp); } } } break; case FD_I18N_POSIX : /* POSIX catgets, put a .msg file out */ fprintf(fp, "$ generated by Fast Light User Interface Designer (fluid) version %.4f\n", FL_VERSION); fprintf(fp, "$set %s\n", g_project.i18n_pos_set.c_str()); fputs("$quote \"\n", fp); for (i = 1, p = Fl_Type::first; p; p = p->next) { if (p->is_widget()) { w = (Fl_Widget_Type *)p; if (w->label()) { fprintf(fp, "%d \"", i ++); write_escaped_strings(fp, w->label()); fputs("\"\n", fp); } if (w->tooltip()) { fprintf(fp, "%d \"", i ++); write_escaped_strings(fp, w->tooltip()); fputs("\"\n", fp); } } } break; } return fclose(fp); } //////////////////////////////////////////////////////////////// // Generate unique but human-readable identifiers: /** A binary searchable tree storing identifiers for quick retrieval. */ struct Fd_Identifier_Tree { char* text; void* object; Fd_Identifier_Tree *left, *right; Fd_Identifier_Tree (const char* t, void* o) : text(fl_strdup(t)), object(o) {left = right = 0;} ~Fd_Identifier_Tree(); }; Fd_Identifier_Tree::~Fd_Identifier_Tree() { delete left; free((void *)text); delete right; } /** \brief Return a unique name for the given object. This function combines the name and label into an identifier. It then checks if that id was already taken by another object, and if so, appends a hexadecimal value which is incremented until the id is unique in this file. If a new id was created, it is stored in the id tree. \param[in] o create an ID for this object \param[in] type is the first word of the ID \param[in] name if name is set, it is appended to the ID \param[in] label else if label is set, it is appended, skipping non-keyword characters \return buffer to a unique identifier, managed by Fd_Code_Writer, so caller must NOT free() it */ const char* Fd_Code_Writer::unique_id(void* o, const char* type, const char* name, const char* label) { char buffer[128]; char* q = buffer; char* q_end = q + 128 - 8 - 1; // room for hex number and NUL while (*type) *q++ = *type++; *q++ = '_'; const char* n = name; if (!n || !*n) n = label; if (n && *n) { while (*n && !is_id(*n)) n++; while (is_id(*n) && (q < q_end)) *q++ = *n++; } *q = 0; // okay, search the tree and see if the name was already used: Fd_Identifier_Tree** p = &id_root; int which = 0; while (*p) { int i = strcmp(buffer, (*p)->text); if (!i) { if ((*p)->object == o) return (*p)->text; // already used, we need to pick a new name: sprintf(q,"%x",++which); p = &id_root; continue; } else if (i < 0) p = &((*p)->left); else p = &((*p)->right); } *p = new Fd_Identifier_Tree(buffer, o); return (*p)->text; } //////////////////////////////////////////////////////////////// // return current indentation: /** Return a C string that indents code to the given depth. Indentation can be changed by modifying the multiplicator (``*2`` to keep the FLTK indent style). Changing `spaces` to a list of tabs would generate tab indents instead. This function can also be used for fixed depth indents in the header file. Do *not* ever make this a user preference, or you will end up writing a fully featured code formatter. \param[in] set generate this indent depth \return pointer to a static string */ const char *Fd_Code_Writer::indent(int set) { static const char* spaces = " "; int i = set * 2; if (i>32) i = 32; if (i<0) i = 0; return spaces+32-i; } /** Return a C string that indents code to the current source file depth. \return pointer to a static string */ const char *Fd_Code_Writer::indent() { return indent(indentation); } /** Return a C string that indents code to the current source file depth plus an offset. \param[in] offset adds a temporary offset for this call only; this does not change the `indentation` variable; offset can be negative \return pointer to a static string */ const char *Fd_Code_Writer::indent_plus(int offset) { return indent(indentation+offset); } //////////////////////////////////////////////////////////////// // declarations/include files: // Each string generated by write_h_once is written only once to // the header file. This is done by keeping a binary tree of all // the calls so far and not printing it if it is in the tree. /** A binary searchable tree storing text for quick retrieval. */ struct Fd_Text_Tree { char *text; Fd_Text_Tree *left, *right; Fd_Text_Tree(const char *t) { text = fl_strdup(t); left = right = 0; } ~Fd_Text_Tree(); }; Fd_Text_Tree::~Fd_Text_Tree() { delete left; free((void *)text); delete right; } /** A binary searchable tree storing pointers for quick retrieval. */ struct Fd_Pointer_Tree { void *ptr; Fd_Pointer_Tree *left, *right; Fd_Pointer_Tree(void *p) { ptr = p; left = right = 0; } ~Fd_Pointer_Tree(); }; Fd_Pointer_Tree::~Fd_Pointer_Tree() { delete left; delete right; } /** Print a formatted line to the header file, unless the same line was produced before in this header file. \note Resulting line is cropped at 1023 bytes. \param[in] format printf-style formatting text, followed by a vararg list \return 1 if the text was written to the file, 0 if it was previously written. */ int Fd_Code_Writer::write_h_once(const char *format, ...) { va_list args; char buf[1024]; va_start(args, format); vsnprintf(buf, sizeof(buf), format, args); va_end(args); Fd_Text_Tree **p = &text_in_header; while (*p) { int i = strcmp(buf,(*p)->text); if (!i) return 0; else if (i < 0) p = &((*p)->left); else p = &((*p)->right); } fprintf(header_file,"%s\n",buf); *p = new Fd_Text_Tree(buf); return 1; } /** Print a formatted line to the source file, unless the same line was produced before in this code file. \note Resulting line is cropped at 1023 bytes. \param[in] format printf-style formatting text, followed by a vararg list \return 1 if the text was written to the file, 0 if it was previously written. */ int Fd_Code_Writer::write_c_once(const char *format, ...) { va_list args; char buf[1024]; va_start(args, format); vsnprintf(buf, sizeof(buf), format, args); va_end(args); Fd_Text_Tree **p = &text_in_header; while (*p) { int i = strcmp(buf,(*p)->text); if (!i) return 0; else if (i < 0) p = &((*p)->left); else p = &((*p)->right); } p = &text_in_code; while (*p) { int i = strcmp(buf,(*p)->text); if (!i) return 0; else if (i < 0) p = &((*p)->left); else p = &((*p)->right); } crc_printf("%s\n", buf); *p = new Fd_Text_Tree(buf); return 1; } /** Return true if this pointer was already included in the code file. If it was not, add it to the list and return false. \param[in] pp ay pointer \return true if found in the tree, false if added to the tree */ bool Fd_Code_Writer::c_contains(void *pp) { Fd_Pointer_Tree **p = &ptr_in_code; while (*p) { if ((*p)->ptr == pp) return true; else if ((*p)->ptr < pp) p = &((*p)->left); else p = &((*p)->right); } *p = new Fd_Pointer_Tree(pp); return false; } /** Write a C string to the code file, escaping non-ASCII characters. Text is broken into lines of 78 character. FLUID " before and after every line text. A list of control characters and ", ', and \\ are escaped by adding a \\ in front of them. Escape ?? by writing ?\\?. All other characters that are not between 32 and 126 inclusive will be escaped as octal characters. This function is utf8 agnostic. \param[in] s write this string \param[in] length write so many bytes in this string \see f.write_cstring(const char*) */ void Fd_Code_Writer::write_cstring(const char *s, int length) { const char *next_line = "\"\n\""; if (varused_test) { varused = 1; return; } // if we are rendering to the source code preview window, and the text is // longer than four lines, we only render a placeholder. if (write_codeview && ((s==NULL) || (length>300))) { if (length>=0) crc_printf("\" ... %d bytes of text... \"", length); else crc_puts("\" ... text... \""); return; } if (length==-1 || s==0L) { crc_puts("\n#error string not found\n"); crc_puts("\" ... undefined size text... \""); return; } const char *p = s; const char *e = s+length; int linelength = 1; crc_putc('\"'); for (; p < e;) { int c = *p++; switch (c) { case '\b': c = 'b'; goto QUOTED; case '\t': c = 't'; goto QUOTED; case '\n': c = 'n'; goto QUOTED; case '\f': c = 'f'; goto QUOTED; case '\r': c = 'r'; goto QUOTED; case '\"': case '\'': case '\\': QUOTED: if (linelength >= 77) { crc_puts(next_line); linelength = 0; } crc_putc('\\'); crc_putc(c); linelength += 2; break; case '?': // prevent trigraphs by writing ?? as ?\? if (p-2 >= s && *(p-2) == '?') goto QUOTED; // else fall through: default: if (c >= ' ' && c < 127) { // a legal ASCII character if (linelength >= 78) { crc_puts(next_line); linelength = 0; } crc_putc(c); linelength++; break; } // if the UTF-8 option is checked, write unicode characters verbatim if (g_project.utf8_in_src && (c&0x80)) { if ((c&0x40)) { // This is the first character in a utf-8 sequence (0b11......). // A line break would be ok here. Do not put linebreak in front of // following characters (0b10......) if (linelength >= 78) { crc_puts(next_line); linelength = 0; } } crc_putc(c); linelength++; break; } // otherwise we must print it as an octal constant: c &= 255; if (linelength >= 74) { crc_puts(next_line); linelength = 0; } crc_printf("\\%03o", c); linelength += 4; break; } } crc_putc('\"'); } /** Write a C string, escaping non-ASCII characters. \param[in] s write this string \see f.write_cstring(const char*, int) */ void Fd_Code_Writer::write_cstring(const char *s) { write_cstring(s, (int)strlen(s)); } /** Write an array of C binary data (does not add a null). The output is bracketed in { and }. The content is written as decimal bytes, i.e. `{ 1, 2, 200 }` \param[in] s a block of binary data, interpreted as unsigned bytes \param[in] length size of the block in bytes */ void Fd_Code_Writer::write_cdata(const char *s, int length) { if (varused_test) { varused = 1; return; } if (write_codeview) { if (length>=0) crc_printf("{ /* ... %d bytes of binary data... */ }", length); else crc_puts("{ /* ... binary data... */ }"); return; } if (length==-1) { crc_puts("\n#error data not found\n"); crc_puts("{ /* ... undefined size binary data... */ }"); return; } const unsigned char *w = (const unsigned char *)s; const unsigned char *e = w+length; int linelength = 1; crc_putc('{'); for (; w < e;) { unsigned char c = *w++; if (c>99) linelength += 4; else if (c>9) linelength += 3; else linelength += 2; if (linelength >= 77) {crc_puts("\n"); linelength = 0;} crc_printf("%d", c); if (wis_a(ID_Function) || t->is_a(ID_Decl) || t->is_a(ID_Data); // || t->is_a(ID_Class) // FLUID can't handle a class inside a class // || t->is_a(ID_Widget_Class) // || t->is_a(ID_DeclBlock) // Declaration blocks are generally not handled well } /** Return true, if this is a comment, and if it is followed by a class member. This must only be called if q is inside a widget class. Widget classes can have widgets and members (functions/methods, declarations, etc.) intermixed. \param[in] q should be a comment type \return true if this comment is followed by a class member \return false if it is followed by a widget or code \see is_class_member(Fl_Type *t) */ bool is_comment_before_class_member(Fl_Type *q) { if (q->is_a(ID_Comment) && q->next && q->next->level==q->level) { if (q->next->is_a(ID_Comment)) return is_comment_before_class_member(q->next); if (is_class_member(q->next)) return true; } return false; } /** Recursively write static code and declarations \param[in] p write this type and all its children \return pointer to the next sibling */ Fl_Type* Fd_Code_Writer::write_static(Fl_Type* p) { if (write_codeview) p->header_static_start = (int)ftell(header_file); if (write_codeview) p->code_static_start = (int)ftell(code_file); p->write_static(*this); if (write_codeview) p->code_static_end = (int)ftell(code_file); if (write_codeview) p->header_static_end = (int)ftell(header_file); Fl_Type* q; for (q = p->next; q && q->level > p->level;) { q = write_static(q); } p->write_static_after(*this); return q; } /** Recursively write code, putting children between the two parts of the parent code. \param[in] p write this type and all its children \return pointer to the next sibling */ Fl_Type* Fd_Code_Writer::write_code(Fl_Type* p) { // write all code that comes before the children code // (but don't write the last comment until the very end) if (!(p==Fl_Type::last && p->is_a(ID_Comment))) { if (write_codeview) p->code1_start = (int)ftell(code_file); if (write_codeview) p->header1_start = (int)ftell(header_file); p->write_code1(*this); if (write_codeview) p->code1_end = (int)ftell(code_file); if (write_codeview) p->header1_end = (int)ftell(header_file); } // recursively write the code of all children Fl_Type* q; if (p->is_widget() && p->is_class()) { // Handle widget classes specially for (q = p->next; q && q->level > p->level;) { // note: maybe declaration blocks should be handled like comments in the context if (!is_class_member(q) && !is_comment_before_class_member(q)) { q = write_code(q); } else { int level = q->level; do { q = q->next; } while (q && q->level > level); } } // write all code that come after the children if (write_codeview) p->code2_start = (int)ftell(code_file); if (write_codeview) p->header2_start = (int)ftell(header_file); p->write_code2(*this); if (write_codeview) p->code2_end = (int)ftell(code_file); if (write_codeview) p->header2_end = (int)ftell(header_file); for (q = p->next; q && q->level > p->level;) { if (is_class_member(q) || is_comment_before_class_member(q)) { q = write_code(q); } else { int level = q->level; do { q = q->next; } while (q && q->level > level); } } write_h("};\n"); current_widget_class = 0L; } else { for (q = p->next; q && q->level > p->level;) q = write_code(q); // write all code that come after the children if (write_codeview) p->code2_start = (int)ftell(code_file); if (write_codeview) p->header2_start = (int)ftell(header_file); p->write_code2(*this); if (write_codeview) p->code2_end = (int)ftell(code_file); if (write_codeview) p->header2_end = (int)ftell(header_file); } return q; } /** Write the source and header files for the current design. If the files already exist, they will be overwritten. \note There is no true error checking here. \param[in] s filename of source code file \param[in] t filename of the header file \return 0 if the operation failed, 1 if it was successful */ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { write_codeview = to_codeview; delete id_root; id_root = 0; indentation = 0; current_class = 0L; current_widget_class = 0L; if (!s) code_file = stdout; else { FILE *f = fl_fopen(s, "wb"); if (!f) return 0; code_file = f; } if (!t) header_file = stdout; else { FILE *f = fl_fopen(t, "wb"); if (!f) {fclose(code_file); return 0;} header_file = f; } // Remember the last code file location for MergeBack if (s && g_project.write_mergeback_data && !to_codeview) { Fl_String proj_filename = g_project.projectfile_path() + g_project.projectfile_name(); int i, n = proj_filename.size(); for (i=0; iis_a(ID_Comment)) { if (write_codeview) { first_type->code1_start = first_type->code2_start = (int)ftell(code_file); first_type->header1_start = first_type->header2_start = (int)ftell(header_file); } // it is ok to write non-recursive code here, because comments have no children or code2 blocks first_type->write_code1(*this); if (write_codeview) { first_type->code1_end = first_type->code2_end = (int)ftell(code_file); first_type->header1_end = first_type->header2_end = (int)ftell(header_file); } first_type = first_type->next; } const char *hdr = "\ // generated by Fast Light User Interface Designer (fluid) version %.4f\n\n"; fprintf(header_file, hdr, FL_VERSION); crc_printf(hdr, FL_VERSION); {char define_name[102]; const char* a = fl_filename_name(t); char* b = define_name; if (!isalpha(*a)) {*b++ = '_';} while (*a) {*b++ = isalnum(*a) ? *a : '_'; a++;} *b = 0; fprintf(header_file, "#ifndef %s\n", define_name); fprintf(header_file, "#define %s\n", define_name); } if (g_project.avoid_early_includes==0) { write_h_once("#include "); } if (t && g_project.include_H_from_C) { if (to_codeview) { write_c("#include \"CodeView.h\"\n"); } else if (g_project.header_file_name[0] == '.' && strchr(g_project.header_file_name.c_str(), '/') == NULL) { write_c("#include \"%s\"\n", fl_filename_name(t)); } else { write_c("#include \"%s\"\n", g_project.header_file_name.c_str()); } } Fl_String loc_include, loc_conditional; if (g_project.i18n_type==FD_I18N_GNU) { loc_include = g_project.i18n_gnu_include; loc_conditional = g_project.i18n_gnu_conditional; } else { loc_include = g_project.i18n_pos_include; loc_conditional = g_project.i18n_pos_conditional; } if (g_project.i18n_type && !loc_include.empty()) { int conditional = !loc_conditional.empty(); if (conditional) { write_c("#ifdef %s\n", loc_conditional.c_str()); indentation++; } if (loc_include[0] != '<' && loc_include[0] != '\"') write_c("#%sinclude \"%s\"\n", indent(), loc_include.c_str()); else write_c("#%sinclude %s\n", indent(), loc_include.c_str()); if (g_project.i18n_type == FD_I18N_POSIX) { if (!g_project.i18n_pos_file.empty()) { write_c("extern nl_catd %s;\n", g_project.i18n_pos_file.c_str()); } else { write_c("// Initialize I18N stuff now for menus...\n"); write_c("#%sinclude \n", indent()); write_c("static char *_locale = setlocale(LC_MESSAGES, \"\");\n"); write_c("static nl_catd _catalog = catopen(\"%s\", 0);\n", g_project.basename().c_str()); } } if (conditional) { write_c("#else\n"); if (g_project.i18n_type == FD_I18N_GNU) { if (!g_project.i18n_gnu_function.empty()) { write_c("#%sifndef %s\n", indent(), g_project.i18n_gnu_function.c_str()); write_c("#%sdefine %s(text) text\n", indent_plus(1), g_project.i18n_gnu_function.c_str()); write_c("#%sendif\n", indent()); } } if (g_project.i18n_type == FD_I18N_POSIX) { write_c("#%sifndef catgets\n", indent()); write_c("#%sdefine catgets(catalog, set, msgid, text) text\n", indent_plus(1)); write_c("#%sendif\n", indent()); } indentation--; write_c("#endif\n"); } if (g_project.i18n_type == FD_I18N_GNU && g_project.i18n_gnu_static_function[0]) { write_c("#ifndef %s\n", g_project.i18n_gnu_static_function.c_str()); write_c("#%sdefine %s(text) text\n", indent_plus(1), g_project.i18n_gnu_static_function.c_str()); write_c("#endif\n"); } } for (Fl_Type* p = first_type; p;) { // write all static data for this & all children first write_static(p); // then write the nested code: p = write_code(p); } if (!s) return 1; fprintf(header_file, "#endif\n"); Fl_Type* last_type = Fl_Type::last; if (last_type && (last_type != Fl_Type::first) && last_type->is_a(ID_Comment)) { if (write_codeview) { last_type->code1_start = last_type->code2_start = (int)ftell(code_file); last_type->header1_start = last_type->header2_start = (int)ftell(header_file); } last_type->write_code1(*this); if (write_codeview) { last_type->code1_end = last_type->code2_end = (int)ftell(code_file); last_type->header1_end = last_type->header2_end = (int)ftell(header_file); } } int x = 0, y = 0; if (code_file != stdout) x = fclose(code_file); code_file = 0; if (header_file != stdout) y = fclose(header_file); header_file = 0; return x >= 0 && y >= 0; } /** Write the public/private/protected keywords inside the class. This avoids repeating these words if the mode is already set. \param[in] state 0 for private, 1 for public, 2 for protected */ void Fd_Code_Writer::write_public(int state) { if (!current_class && !current_widget_class) return; if (current_class && current_class->write_public_state == state) return; if (current_widget_class && current_widget_class->write_public_state == state) return; if (current_class) current_class->write_public_state = state; if (current_widget_class) current_widget_class->write_public_state = state; switch (state) { case 0: write_h("private:\n"); break; case 1: write_h("public:\n"); break; case 2: write_h("protected:\n"); break; } } /** Create and initialize a new C++ source code writer. */ Fd_Code_Writer::Fd_Code_Writer() : code_file(NULL), header_file(NULL), id_root(NULL), text_in_header(NULL), text_in_code(NULL), ptr_in_code(NULL), block_crc_(0), block_line_start_(true), block_buffer_(NULL), block_buffer_size_(0), indentation(0), write_codeview(false), varused_test(0), varused(0) { block_crc_ = crc32(0, NULL, 0); } /** Release all resources. */ Fd_Code_Writer::~Fd_Code_Writer() { delete id_root; delete ptr_in_code; delete text_in_code; delete text_in_header; if (block_buffer_) ::free(block_buffer_); } /** Write a MergeBack tag as a separate line of C++ comment. The tag contains information about the type of tag that we are writing, a link back to the type using its unique id, and the CRC of all code written after the previous tag up to this point. \param[in] type FD_TAG_GENERIC, FD_TAG_CODE, FD_TAG_MENU_CALLBACK, or FD_TAG_WIDGET_CALLBACK \param[in] uid the unique id of the current type */ void Fd_Code_Writer::tag(int type, unsigned short uid) { if (g_project.write_mergeback_data) fprintf(code_file, "//~fl~%d~%04x~%08x~~\n", type, (int)uid, (unsigned int)block_crc_); block_crc_ = crc32(0, NULL, 0); } /** Static function to calculate the CRC32 of a block of C source code. Calculation of the CRC ignores leading whitespace in a line and all linefeed characters ('\\r'). \param[in] data a pointer to the data block \param[in] n the size of the data in bytes, or -1 to use strlen() \param[in] in_crc add to this CRC, 0 by default to start a new block \param[inout] inout_line_start optional pointer to flag that determines if we are the start of a line, used to find leading whitespace \return the new CRC */ unsigned long Fd_Code_Writer::block_crc(const void *data, int n, unsigned long in_crc, bool *inout_line_start) { if (!data) return 0; if (n==-1) n = (int)strlen((const char*)data); bool line_start = true; if (inout_line_start) line_start = *inout_line_start; const char *s = (const char*)data; for ( ; n>0; --n, ++s) { if (line_start) { // don't count leading spaces and tabs in a line while (n>0 && *s>0 && isspace(*s)) { s++; n--; } if (*s) line_start = false; } // don't count '\r' that may be introduced by Windows if (n>0 && *s=='\r') { s++; n--; } if (n>0 && *s=='\n') line_start = true; if (n>0) { in_crc = crc32(in_crc, (const Bytef*)s, 1); } } if (inout_line_start) *inout_line_start = line_start; return in_crc; } /** Add the following block of text to the CRC of this class. \param[in] data a pointer to the data block \param[in] n the size of the data in bytes, or -1 to use strlen() */ void Fd_Code_Writer::crc_add(const void *data, int n) { block_crc_ = block_crc(data, n, block_crc_, &block_line_start_); } /** Write formatted text to the code file. If MergeBack is enabled, the CRC calculation is continued. \param[in] format printf style formatting string \return see fprintf(FILE *, *const char*, ...) */ int Fd_Code_Writer::crc_printf(const char *format, ...) { va_list args; va_start(args, format); int ret = crc_vprintf(format, args); va_end(args); return ret; } /** Write formatted text to the code file. If MergeBack is enabled, the CRC calculation is continued. \param[in] format printf style formatting string \param[in] args list of arguments \return see fprintf(FILE *, *const char*, ...) */ int Fd_Code_Writer::crc_vprintf(const char *format, va_list args) { if (g_project.write_mergeback_data) { int n = vsnprintf(block_buffer_, block_buffer_size_, format, args); if (n > block_buffer_size_) { block_buffer_size_ = n + 128; if (block_buffer_) ::free(block_buffer_); block_buffer_ = (char*)::malloc(block_buffer_size_+1); n = vsnprintf(block_buffer_, block_buffer_size_, format, args); } crc_add(block_buffer_, n); return fputs(block_buffer_, code_file); } else { return vfprintf(code_file, format, args); } } /** Write some text to the code file. If MergeBack is enabled, the CRC calculation is continued. \param[in] text any text, no requirements to end in a newline or such \return see fputs(const char*, FILE*) */ int Fd_Code_Writer::crc_puts(const char *text) { if (g_project.write_mergeback_data) { crc_add(text); } return fputs(text, code_file); } /** Write a single ASCII character to the code file. If MergeBack is enabled, the CRC calculation is continued. \note to write UTF-8 characters, use Fd_Code_Writer::crc_puts(const char *text) \param[in] c any character between 0 and 127 inclusive \return see fputc(int, FILE*) */ int Fd_Code_Writer::crc_putc(int c) { if (g_project.write_mergeback_data) { uchar uc = (uchar)c; crc_add(&uc, 1); } return fputc(c, code_file); } /// \} fltk-1.4.3/fluid/pixmaps.h0000644000175000017500000000144515004135251015546 0ustar albrechtalbrecht// // Fluid Image management for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_PIXMAPS_H #define _FLUID_PIXMAPS_H class Fl_Pixmap; extern Fl_Pixmap *bind_pixmap; extern Fl_Pixmap *lock_pixmap; extern Fl_Pixmap *protected_pixmap; extern Fl_Pixmap *invisible_pixmap; extern Fl_Pixmap *compressed_pixmap; extern Fl_Pixmap *pixmap[]; void loadPixmaps(); #endif // _FLUID_PIXMAPS_H fltk-1.4.3/fluid/Fluid_Image.cxx0000644000175000017500000003262515004135251016611 0ustar albrechtalbrecht// // Pixmap (and other images) label support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fluid_Image.h" #include "fluid.h" #include "Fl_Group_Type.h" #include "Fl_Window_Type.h" #include "file.h" #include "code.h" #include #include #include #include "fluid_filename.h" #include #include // fl_fopen() #include #include #include #include "../src/flstring.h" #include #include #include #include void Fluid_Image::image(Fl_Widget *o) { if (o->window() != o) o->image(img); } void Fluid_Image::deimage(Fl_Widget *o) { if (o->window() != o) o->deimage(img); } /** Write the contents of the name() file as binary source code. \param fmt short name of file contents for error message \return 0 if the file could not be opened or read */ size_t Fluid_Image::write_static_binary(Fd_Code_Writer& f, const char* fmt) { size_t nData = 0; enter_project_dir(); FILE *in = fl_fopen(name(), "rb"); leave_project_dir(); if (!in) { write_file_error(f, fmt); return 0; } else { fseek(in, 0, SEEK_END); nData = ftell(in); fseek(in, 0, SEEK_SET); if (nData) { char *data = (char*)calloc(nData, 1); if (fread(data, nData, 1, in)==0) { /* ignore */ } f.write_cdata(data, (int)nData); free(data); } fclose(in); } return nData; } /** Write the contents of the name() file as textual source code. \param fmt short name of file contents for error message \return 0 if the file could not be opened or read */ size_t Fluid_Image::write_static_text(Fd_Code_Writer& f, const char* fmt) { size_t nData = 0; enter_project_dir(); FILE *in = fl_fopen(name(), "rb"); leave_project_dir(); if (!in) { write_file_error(f, fmt); return 0; } else { fseek(in, 0, SEEK_END); nData = ftell(in); fseek(in, 0, SEEK_SET); if (nData) { char *data = (char*)calloc(nData+1, 1); if (fread(data, nData, 1, in)==0) { /* ignore */ } f.write_cstring(data, (int)nData); free(data); } fclose(in); } return nData; } void Fluid_Image::write_static_rgb(Fd_Code_Writer& f, const char* idata_name) { // Write image data... f.write_c("\n"); f.write_c_once("#include \n"); f.write_c("static const unsigned char %s[] =\n", idata_name); const int extra_data = img->ld() ? (img->ld()-img->w()*img->d()) : 0; f.write_cdata(img->data()[0], (img->w() * img->d() + extra_data) * img->h()); f.write_c(";\n"); write_initializer(f, "Fl_RGB_Image", "%s, %d, %d, %d, %d", idata_name, img->w(), img->h(), img->d(), img->ld()); } /** Write the static image data into the soutrce file. If \p compressed is set, write the original image format, which requires linking the matching image reader at runtime, or if we want to store the raw uncompressed pixels, which makes images fast, needs no reader, but takes a lot of memory (current default for PNG) \param compressed write data in the original compressed file format */ void Fluid_Image::write_static(Fd_Code_Writer& f, int compressed) { if (!img) return; const char *idata_name = f.unique_id(this, "idata", fl_filename_name(name()), 0); function_name_ = f.unique_id(this, "image", fl_filename_name(name()), 0); if (is_animated_gif_) { // Write animated gif image data... f.write_c("\n"); f.write_c_once("#include \n"); f.write_c("static const unsigned char %s[] =\n", idata_name); size_t nData = write_static_binary(f, "AnimGIF"); f.write_c(";\n"); write_initializer(f, "Fl_Anim_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData); } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".gif")==0) { // Write gif image data... f.write_c("\n"); f.write_c_once("#include \n"); f.write_c("static const unsigned char %s[] =\n", idata_name); size_t nData = write_static_binary(f, "GIF"); f.write_c(";\n"); write_initializer(f, "Fl_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData); } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".bmp")==0) { // Write bmp image data... f.write_c("\n"); f.write_c_once("#include \n"); f.write_c("static const unsigned char %s[] =\n", idata_name); size_t nData = write_static_binary(f, "BMP"); f.write_c(";\n"); write_initializer(f, "Fl_BMP_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData); } else if (img->count() > 1) { // Write Pixmap data... f.write_c("\n"); f.write_c_once("#include \n"); f.write_c("static const char *%s[] = {\n", idata_name); f.write_cstring(img->data()[0], (int)strlen(img->data()[0])); int i; int ncolors, chars_per_color; sscanf(img->data()[0], "%*d%*d%d%d", &ncolors, &chars_per_color); if (ncolors < 0) { f.write_c(",\n"); f.write_cstring(img->data()[1], ncolors * -4); i = 2; } else { for (i = 1; i <= ncolors; i ++) { f.write_c(",\n"); f.write_cstring(img->data()[i], (int)strlen(img->data()[i])); } } for (; i < img->count(); i ++) { f.write_c(",\n"); f.write_cstring(img->data()[i], img->w() * chars_per_color); } f.write_c("\n};\n"); write_initializer(f, "Fl_Pixmap", "%s", idata_name); } else if (img->d() == 0) { // Write Bitmap data... f.write_c("\n"); f.write_c_once("#include \n"); f.write_c("static const unsigned char %s[] =\n", idata_name); f.write_cdata(img->data()[0], ((img->w() + 7) / 8) * img->h()); f.write_c(";\n"); write_initializer(f, "Fl_Bitmap", "%s, %d, %d, %d", idata_name, ((img->w() + 7) / 8) * img->h(), img->w(), img->h()); } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".jpg")==0) { // Write jpeg image data... f.write_c("\n"); f.write_c_once("#include \n"); f.write_c("static const unsigned char %s[] =\n", idata_name); size_t nData = write_static_binary(f, "JPEG"); f.write_c(";\n"); write_initializer(f, "Fl_JPEG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData); } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".png")==0) { // Write png image data... f.write_c("\n"); f.write_c_once("#include \n"); f.write_c("static const unsigned char %s[] =\n", idata_name); size_t nData = write_static_binary(f, "PNG"); f.write_c(";\n"); write_initializer(f, "Fl_PNG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData); } #ifdef FLTK_USE_SVG else if (fl_ascii_strcasecmp(fl_filename_ext(name()), ".svg")==0 || fl_ascii_strcasecmp(fl_filename_ext(name()), ".svgz")==0) { bool gzipped = (strcmp(fl_filename_ext(name()), ".svgz") == 0); // Write svg image data... if (compressed) { f.write_c("\n"); f.write_c_once("#include \n"); if (gzipped) { f.write_c("static const unsigned char %s[] =\n", idata_name); size_t nData = write_static_binary(f, "SVGZ"); f.write_c(";\n"); write_initializer(f, "Fl_SVG_Image", "\"%s\", %s, %ld", fl_filename_name(name()), idata_name, nData); } else { f.write_c("static const char %s[] =\n", idata_name); write_static_text(f, "SVG"); f.write_c(";\n"); write_initializer(f, "Fl_SVG_Image", "\"%s\", %s", fl_filename_name(name()), idata_name); } } else { // if FLUID runs from the command line, make sure that the image is not // only loaded but also rasterized, so we can write the RGB image data Fl_RGB_Image* rgb_image = NULL; Fl_SVG_Image* svg_image = NULL; if (img->d()>0) rgb_image = (Fl_RGB_Image*)img->image(); if (rgb_image) svg_image = rgb_image->as_svg_image(); if (svg_image) { svg_image->resize(svg_image->w(), svg_image->h()); write_static_rgb(f, idata_name); } else { write_file_error(f, "RGB_from_SVG"); } } } #endif // FLTK_USE_SVG else { write_static_rgb(f, idata_name); } } void Fluid_Image::write_file_error(Fd_Code_Writer& f, const char *fmt) { f.write_c("#warning Cannot read %s file \"%s\": %s\n", fmt, name(), strerror(errno)); enter_project_dir(); f.write_c("// Searching in path \"%s\"\n", fl_getcwd(0, FL_PATH_MAX)); leave_project_dir(); } void Fluid_Image::write_initializer(Fd_Code_Writer& f, const char *type_name, const char *format, ...) { /* Outputs code that returns (and initializes if needed) an Fl_Image as follows: static Fl_Image *'function_name_'() { static Fl_Image *image = NULL; if (!image) image = new 'type_name'('product of format and remaining args'); return image; } */ va_list ap; va_start(ap, format); f.write_c("static Fl_Image *%s() {\n", function_name_); if (is_animated_gif_) f.write_c("%sFl_GIF_Image::animate = true;\n", f.indent(1)); f.write_c("%sstatic Fl_Image *image = NULL;\n", f.indent(1)); f.write_c("%sif (!image)\n", f.indent(1)); f.write_c("%simage = new %s(", f.indent(2), type_name); f.vwrite_c(format, ap); f.write_c(");\n"); f.write_c("%sreturn image;\n", f.indent(1)); f.write_c("}\n"); va_end(ap); } void Fluid_Image::write_code(Fd_Code_Writer& f, int bind, const char *var, int inactive) { /* Outputs code that attaches an image to an Fl_Widget or Fl_Menu_Item. This code calls a function output before by Fluid_Image::write_initializer() */ if (img) { f.write_c("%s%s->%s%s( %s() );\n", f.indent(), var, bind ? "bind_" : "", inactive ? "deimage" : "image", function_name_); if (is_animated_gif_) f.write_c("%s((Fl_Anim_GIF_Image*)(%s()))->canvas(%s, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);\n", f.indent(), function_name_, var); } } void Fluid_Image::write_inline(Fd_Code_Writer& f, int inactive) { if (img) f.write_c("%s()", function_name_); } //////////////////////////////////////////////////////////////// static Fluid_Image** images = 0; // sorted list static int numimages = 0; static int tablesize = 0; Fluid_Image* Fluid_Image::find(const char *iname) { if (!iname || !*iname) return 0; // first search to see if it exists already: int a = 0; int b = numimages; while (a < b) { int c = (a+b)/2; int i = strcmp(iname,images[c]->name_); if (i < 0) b = c; else if (i > 0) a = c+1; else return images[c]; } // no, so now see if the file exists: enter_project_dir(); FILE *f = fl_fopen(iname,"rb"); if (!f) { if (batch_mode) fprintf(stderr, "Can't open image file:\n%s\n%s",iname,strerror(errno)); else fl_message("Can't open image file:\n%s\n%s",iname,strerror(errno)); leave_project_dir(); return 0; } fclose(f); Fluid_Image *ret = new Fluid_Image(iname); if (!ret->img || !ret->img->w() || !ret->img->h()) { delete ret; ret = 0; if (batch_mode) fprintf(stderr, "Can't read image file:\n%s\nunrecognized image format",iname); else fl_message("Can't read image file:\n%s\nunrecognized image format",iname); } leave_project_dir(); if (!ret) return 0; // make a new entry in the table: numimages++; if (numimages > tablesize) { tablesize = tablesize ? 2*tablesize : 16; if (images) images = (Fluid_Image**)realloc(images, tablesize*sizeof(Fluid_Image*)); else images = (Fluid_Image**)malloc(tablesize*sizeof(Fluid_Image*)); } for (b = numimages-1; b > a; b--) images[b] = images[b-1]; images[a] = ret; return ret; } Fluid_Image::Fluid_Image(const char *iname) : is_animated_gif_(false) { name_ = fl_strdup(iname); written = 0; refcount = 0; img = Fl_Shared_Image::get(iname); if (img && iname) { const char *ext = fl_filename_ext(iname); if (fl_ascii_strcasecmp(ext, ".gif")==0) { int fc = Fl_Anim_GIF_Image::frame_count(iname); if (fc > 0) is_animated_gif_ = true; } } function_name_ = NULL; } void Fluid_Image::increment() { ++refcount; } void Fluid_Image::decrement() { --refcount; if (refcount > 0) return; delete this; } Fluid_Image::~Fluid_Image() { int a; if (images) { for (a = 0; arelease(); free((void*)name_); } //////////////////////////////////////////////////////////////// const char *ui_find_image_name; Fluid_Image *ui_find_image(const char *oldname) { enter_project_dir(); fl_file_chooser_ok_label("Use Image"); const char *name = fl_file_chooser("Image?", "Image Files (*.{bm,bmp,gif,jpg,pbm,pgm,png,ppm,xbm,xpm,svg" #ifdef HAVE_LIBZ ",svgz" #endif "})", oldname,1); fl_file_chooser_ok_label(NULL); ui_find_image_name = name; Fluid_Image *ret = (name && *name) ? Fluid_Image::find(name) : 0; leave_project_dir(); return ret; } fltk-1.4.3/fluid/function_panel.fl0000644000175000017500000010023115004135251017234 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} snap { ver 1 current_suite FLTK current_preset 1 } comment {// // Code dialogs for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // } {in_source in_header } decl {\#include "fluid.h"} {private local } decl {\#include "custom_widgets.h"} {private global } decl {\#include "pixmaps.h"} {private local } decl {\#include "factory.h"} {private local } decl {\#include "Fl_Type.h"} {private local } decl {\#include "widget_browser.h"} {private local } decl {\#include "undo.h"} {private local } Function {use_tab_navigation(int, Fl_Text_Editor*)} { comment {Allow widget navigation on text fields with Tab.} private return_type int } { code {return 0;} {} } Function {make_function_panel()} {open } { Fl_Window function_panel { label {Function/Method Properties} xywh {540 418 343 232} type Double align 80 resizable modal visible } { Fl_Group {} {open xywh {10 10 270 20} } { Fl_Choice f_public_member_choice {open tooltip {Change member access attribute.} xywh {10 10 75 20} down_box BORDER_BOX labelsize 11 when 1 textsize 11 } { MenuItem {} { label private user_data 0 user_data_type long xywh {5 5 100 20} labelsize 11 } MenuItem {} { label public user_data 1 user_data_type long xywh {5 5 100 20} labelsize 11 } MenuItem {} { label protected user_data 2 user_data_type long xywh {5 5 100 20} labelsize 11 } } Fl_Choice f_public_choice {open tooltip {Change widget accessibility.} xywh {10 10 75 20} down_box BORDER_BOX labelsize 11 when 1 textsize 11 } { MenuItem {} { label static user_data 0 user_data_type long xywh {15 15 100 20} labelsize 11 } MenuItem {} { label global user_data 1 user_data_type long xywh {15 15 100 20} labelsize 11 } MenuItem {} { label local user_data 2 user_data_type long xywh {15 15 100 20} labelsize 11 } } Fl_Light_Button f_c_button { label {C declaration} tooltip {Declare with a C interface instead of C++.} xywh {95 10 120 20} labelsize 11 } Fl_Box {} { xywh {235 10 45 20} resizable } } Fl_Input f_name_input { label {Name(args): (blank for main())} tooltip {The name of the function or method.} xywh {10 50 320 20} labelfont 1 labelsize 11 align 5 when 0 textfont 4 textsize 11 } Fl_Input f_return_type_input { label {Return Type: (blank to return outermost widget)} tooltip {The return type of the function or method.} xywh {10 90 320 20} labelfont 1 labelsize 11 align 5 when 0 textfont 4 textsize 11 } Fl_Text_Editor f_comment_input { label {Comment:} tooltip {Function comment in Doxygen format} xywh {10 125 320 65} box DOWN_BOX labelfont 1 labelsize 11 align 5 textfont 4 textsize 11 resizable code0 {f_comment_input->buffer(new Fl_Text_Buffer());} code1 {f_comment_input->add_key_binding(FL_Tab, 0, use_tab_navigation);} } Fl_Group {} {open xywh {10 200 320 20} } { Fl_Return_Button f_panel_ok { label OK tooltip {Apply the changes.} xywh {220 200 50 20} labelsize 11 hotspot } Fl_Button f_panel_cancel { label Cancel tooltip {Cancel the changes.} xywh {280 200 50 20} labelsize 11 } Fl_Box {} { xywh {10 200 205 20} resizable } } } } Function {make_code_panel()} {open } { Fl_Window code_panel { label {Code Properties} callback {if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape) return; // ignore Escape code_panel->hide(); // otherwise hide..} xywh {539 567 540 180} type Double labelsize 11 hide resizable code0 {o->size_range(200, 150);} modal } { Fl_Text_Editor code_input { xywh {10 10 520 130} box DOWN_BOX labelsize 11 textfont 4 textsize 11 resizable code0 {o->when(FL_WHEN_ENTER_KEY_CHANGED|FL_WHEN_RELEASE);} code1 {\#include "CodeEditor.h"} class CodeEditor } Fl_Group {} {open xywh {10 150 520 20} labelsize 11 } { Fl_Return_Button code_panel_ok { label OK xywh {400 150 60 20} labelsize 11 hotspot } Fl_Button code_panel_cancel { label Cancel xywh {470 150 60 20} labelsize 11 } Fl_Box {} { xywh {10 150 380 20} labelsize 11 resizable } } } code {// Enable line numbers code_input->linenumber_width(60); code_input->linenumber_size(code_input->Fl_Text_Display::textsize());} {} } Function {make_codeblock_panel()} {open } { Fl_Window codeblock_panel { label {Code Block Properties} xywh {806 735 300 115} type Double labelsize 11 hide resizable code0 {o->size_range(o->w(), o->h(), Fl::w(), o->h());} modal } { Fl_Input code_before_input { label {Conditional code block} tooltip {\#ifdef or similar conditional code block.} xywh {10 15 280 20} labelsize 11 align 5 when 0 textfont 4 textsize 11 } Fl_Input code_after_input { label {"{...child code...}" is inserted here} tooltip {\#endif or similar conditional code block.} xywh {10 55 280 20} labelsize 11 align 5 when 0 textfont 4 textsize 11 resizable } Fl_Group {} {open xywh {10 85 280 20} } { Fl_Return_Button codeblock_panel_ok { label OK xywh {160 85 60 20} labelsize 11 hotspot } Fl_Button codeblock_panel_cancel { label Cancel xywh {230 85 60 20} shortcut 0xff1b labelsize 11 } Fl_Box {} { xywh {10 85 140 20} resizable } } } } Function {make_declblock_panel()} {open } { Fl_Window declblock_panel { label {Declaration Block Properties} open xywh {645 452 300 355} type Double labelsize 11 align 80 resizable code0 {o->size_range(o->w(), o->h(), Fl::w(), o->h());} modal size_range {300 355 0 0} visible } { Fl_Input declblock_before_input { label {Start Code:} tooltip {\#ifdef or similar conditional declaration block.} xywh {10 23 280 20} labelfont 1 labelsize 11 align 5 when 0 textfont 4 textsize 11 } Fl_Box {} { label {"\\n...child code...\\n" is inserted here} xywh {10 48 280 20} labelsize 11 } Fl_Input declblock_after_input { label {End Code:} tooltip {\#endif or similar declaration code block.} xywh {10 80 280 20} labelfont 1 labelsize 11 align 5 when 0 textfont 4 textsize 11 } Fl_Group {} {open xywh {10 105 280 120} } { Fl_Box {} { label {Enclose code generated by children in source file:} xywh {10 105 270 20} labelsize 11 align 20 } Fl_Check_Button declblock_code_source { label implementations xywh {20 125 260 20} down_box DOWN_BOX labelsize 11 } Fl_Check_Button declblock_static_source { label {static initializations and callbacks} xywh {20 145 260 20} down_box DOWN_BOX labelsize 11 } Fl_Box {} { label {Enclose code in header file:} xywh {10 165 270 20} labelsize 11 align 20 } Fl_Check_Button declblock_code_header { label {forward declarations} xywh {20 185 260 20} down_box DOWN_BOX labelsize 11 } Fl_Check_Button declblock_static_header { label {preprecessor and callback declarations} xywh {20 205 260 20} down_box DOWN_BOX labelsize 11 } Fl_Box {} { xywh {280 105 10 120} labelsize 11 hide resizable } } Fl_Text_Editor declblock_comment_input { label {Comment:} tooltip {Declaration comment in Doxygen format} xywh {10 242 280 65} box DOWN_BOX labelfont 1 labelsize 11 align 5 textfont 4 textsize 11 resizable code0 {declblock_comment_input->buffer(new Fl_Text_Buffer());} code1 {declblock_comment_input->add_key_binding(FL_Tab, 0, use_tab_navigation);} } Fl_Group {} { xywh {10 321 280 20} } { Fl_Return_Button declblock_panel_ok { label OK xywh {160 321 60 20} labelsize 11 hotspot } Fl_Button declblock_panel_cancel { label Cancel xywh {230 321 60 20} shortcut 0xff1b labelsize 11 } Fl_Box {} { xywh {10 321 140 20} resizable } } } } Function {make_decl_panel()} {open } { Fl_Window decl_panel { label {Declaration Properties} xywh {497 618 343 262} type Double align 80 resizable size_range {343 262 0 0} visible } { Fl_Group {} { xywh {10 10 270 20} } { Fl_Box {} { xywh {200 10 80 20} resizable } Fl_Choice decl_choice { xywh {10 10 185 20} down_box BORDER_BOX labelsize 11 textsize 11 } { MenuItem {} { label {in source file only} xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {in header file only} xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {"static" in source file} xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {in source and "extern" in header} xywh {0 0 100 20} labelsize 11 } } Fl_Choice decl_class_choice { xywh {10 10 75 20} down_box BORDER_BOX labelsize 11 textsize 11 } { MenuItem {} { label private xywh {10 10 100 20} labelsize 11 } MenuItem {} { label public xywh {10 10 100 20} labelsize 11 } MenuItem {} { label protected xywh {10 10 100 20} labelsize 11 } } } Fl_Tile {} {open xywh {10 40 320 180} resizable code2 {o->size_range(0, 320, 100);} code3 {o->size_range(1, 320, 60);} } { Fl_Group {} {open xywh {10 40 320 100} box FLAT_BOX resizable } { Fl_Text_Editor decl_input { label {This can be any declaration, like "int x;", an external symbol like "extern int foo();", a \#directive like "\#include ", a comment like "//foo" or "/*foo*/", or typedef like "typedef char byte;" or "using std::list;".} xywh {10 40 320 45} labelsize 11 align 134 resizable code0 {\#include "CodeEditor.h"} class CodeEditor } Fl_Box {} { xywh {20 139 300 1} box BORDER_FRAME color 43 } } Fl_Group {} {open xywh {10 140 320 80} box FLAT_BOX } { Fl_Text_Editor decl_comment_input { label {Comment:} tooltip {Declaration comment in Doxygen format} xywh {10 155 320 64} box DOWN_BOX labelfont 1 labelsize 11 align 5 textfont 4 textsize 11 resizable code0 {decl_comment_input->buffer(new Fl_Text_Buffer());} code1 {decl_comment_input->add_key_binding(FL_Tab, 0, use_tab_navigation);} } } } Fl_Group {} {open xywh {10 230 320 20} } { Fl_Return_Button decl_panel_ok { label OK xywh {200 230 60 20} labelsize 11 hotspot } Fl_Button decl_panel_cancel { label Cancel xywh {270 230 60 20} shortcut 0xff1b labelsize 11 } Fl_Box {} { xywh {10 230 185 20} resizable } } } } Function {make_data_panel()} {open } { Fl_Window data_panel { label {Inline Data Properties} xywh {567 382 343 264} type Double align 80 resizable size_range {343 237 0 0} visible } { Fl_Group {} {open xywh {10 10 320 48} } { Fl_Box {} { xywh {288 10 42 20} resizable } Fl_Choice data_choice {open xywh {10 10 185 20} down_box BORDER_BOX labelsize 11 textsize 11 } { MenuItem {} { label {in source file only} xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {in header file only} xywh {0 0 100 20} labelsize 11 hide } MenuItem {} { label {"static" in source file} xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {in source and "extern" in header} xywh {0 0 100 20} labelsize 11 } } Fl_Choice data_class_choice {open xywh {10 10 75 20} down_box BORDER_BOX labelsize 11 textsize 11 } { MenuItem {} { label private xywh {10 10 100 20} labelsize 11 } MenuItem {} { label public xywh {10 10 100 20} labelsize 11 } MenuItem {} { label protected xywh {10 10 100 20} labelsize 11 } } Fl_Choice data_mode {open tooltip {text mode generates a "const char*" and a trailing NUL, compressed mode uses zlib to generate a binary block} xywh {10 38 185 20} down_box BORDER_BOX labelsize 11 textsize 11 } { MenuItem {} { label {binary mode} user_data 0 user_data_type long xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {text mode} user_data 1 user_data_type long xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {compressed binary} user_data 2 user_data_type long xywh {0 0 100 20} labelsize 11 } } } Fl_Input data_input { label {Variable Name:} tooltip {Inline Data variables are declared "const unsigned char []" in binary mode and "const char*" in text mode.} xywh {10 78 320 20} labelfont 1 labelsize 11 align 133 when 0 textfont 4 textsize 11 } Fl_Input data_filename { label {Filename:} tooltip {Name and path of file that will be inlined.} xywh {10 116 280 20} labelfont 1 labelsize 11 align 133 when 0 textfont 4 textsize 11 } Fl_Button data_filebrowser { label {@fileopen} xywh {290 116 40 20} labelcolor 134 } Fl_Text_Editor data_comment_input { label {Comment:} tooltip {Declaration comment in Doxygen format} xywh {10 156 320 65} box DOWN_BOX labelfont 1 labelsize 11 align 5 textfont 4 textsize 11 resizable code0 {data_comment_input->buffer(new Fl_Text_Buffer());} code1 {data_comment_input->add_key_binding(FL_Tab, 0, use_tab_navigation);} } Fl_Group {} {open xywh {10 231 320 20} } { Fl_Return_Button data_panel_ok { label OK xywh {200 231 60 20} labelsize 11 hotspot } Fl_Button data_panel_cancel { label Cancel xywh {270 231 60 20} shortcut 0xff1b labelsize 11 } Fl_Box {} { xywh {10 231 185 20} resizable } } } } Function {make_class_panel()} {open } { Fl_Window class_panel { label {Class Properties} xywh {795 337 342 196} type Double labelsize 11 hide resizable modal size_range {343 188 0 0} } { Fl_Group {} {open xywh {10 10 280 20} hide } { Fl_Light_Button c_public_button { label public tooltip {Make the class publicly accessible.} xywh {10 10 60 20} labelsize 11 when 0 hide } Fl_Box {} { xywh {80 10 210 20} resizable } } Fl_Input c_name_input { label {Name:} tooltip {Name of class.} xywh {10 20 320 20} labelfont 1 labelsize 11 align 5 when 0 textfont 4 textsize 11 } Fl_Input c_subclass_input { label {Subclass of (text between : and \{)} tooltip {Name of subclass.} xywh {10 55 320 20} labelfont 1 labelsize 11 align 5 when 0 textfont 4 textsize 11 } Fl_Text_Editor c_comment_input { label {Comment:} tooltip {Class comment in Doxygen format} xywh {10 90 320 65} box DOWN_BOX labelfont 1 labelsize 11 align 5 textfont 4 textsize 11 resizable code0 {c_comment_input->buffer(new Fl_Text_Buffer());} code1 {c_comment_input->add_key_binding(FL_Tab, 0, use_tab_navigation);} } Fl_Group {} {open xywh {10 165 320 20} } { Fl_Return_Button c_panel_ok { label OK xywh {200 165 60 20} labelsize 11 hotspot } Fl_Button c_panel_cancel { label Cancel xywh {270 165 60 20} shortcut 0xff1b labelsize 11 } Fl_Box {} { xywh {10 165 185 20} resizable } } } } Function {make_comment_panel()} {open } { Fl_Window comment_panel { label {Comment Properties} xywh {519 374 550 280} type Double labelsize 11 hide resizable code0 {o->size_range(320, 180);} modal } { Fl_Text_Editor comment_input { xywh {110 10 430 230} box DOWN_BOX labelsize 11 textfont 4 textsize 11 textcolor 58 resizable code0 {o->when(FL_WHEN_ENTER_KEY_CHANGED|FL_WHEN_RELEASE);} code1 {o->buffer(new Fl_Text_Buffer());} } Fl_Group {} {open xywh {110 250 430 20} labelsize 11 } { Fl_Return_Button comment_panel_ok { label OK xywh {370 250 80 20} labelsize 11 hotspot } Fl_Button comment_panel_cancel { label Cancel xywh {460 250 80 20} shortcut 0xff1b labelsize 11 } Fl_Box {} { xywh {110 250 250 20} labelsize 11 resizable } } Fl_Group {} {open xywh {10 10 90 243} labelsize 11 } { Fl_Light_Button comment_in_source { label {In Source} tooltip {Put the comment into the source (.cxx) file.} xywh {10 10 90 20} labelsize 11 when 0 } Fl_Light_Button comment_in_header { label {In Header} tooltip {Put the comment into the header (.h) file.} xywh {10 40 90 20} labelsize 11 when 0 } Fl_Menu_Button comment_predefined { label Predefined open xywh {10 70 90 20} labelsize 11 textsize 11 } {} Fl_Button comment_load { label {Import...} xywh {10 100 90 20} labelsize 11 } Fl_Box {} { xywh {10 132 90 121} labelsize 11 resizable } } } } Function {type_make_cb(Fl_Widget*,void*d)} {open return_type void } { code {const char *type_name = (const char*)d; if (Fl_Type::current && Fl_Type::current->can_have_children()) add_new_widget_from_user(type_name, Strategy::AS_LAST_CHILD); else add_new_widget_from_user(type_name, Strategy::AFTER_CURRENT);} {selected } } Function {make_widgetbin()} {open } { Fl_Window widgetbin_panel { label {Widget Bin} callback {if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape) exit_cb((Fl_Widget*)o, v); else toggle_widgetbin_cb((Fl_Widget*)o, v);} open xywh {395 227 600 102} type Single align 80 non_modal visible } { Fl_Group {} { label Code open xywh {3 19 79 79} labelsize 12 } { Fl_Button {} { user_data {"Function"} callback type_make_cb tooltip Function xywh {5 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Function]);} } Fl_Button {} { user_data {"Class"} callback type_make_cb tooltip Class xywh {30 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Class]);} } Fl_Button {} { user_data {"comment"} callback type_make_cb tooltip Comment xywh {55 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Comment]);} } Fl_Button {} { user_data {"Code"} callback type_make_cb tooltip Code xywh {5 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Code]);} } Fl_Button {} { user_data {"CodeBlock"} callback type_make_cb tooltip {Code Block} xywh {30 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_CodeBlock]);} } Fl_Button {} { user_data {"widget_class"} callback type_make_cb tooltip {Widget Class} xywh {55 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Widget_Class]);} class Widget_Bin_Window_Button } Fl_Button {} { user_data {"decl"} callback type_make_cb tooltip Declaration xywh {5 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Decl]);} } Fl_Button {} { user_data {"declblock"} callback type_make_cb tooltip {Declaration Block} xywh {30 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_DeclBlock]);} } Fl_Button {} { user_data {"data"} callback type_make_cb tooltip {Inline Data} xywh {55 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Data]);} } } Fl_Group {} { label Groups open xywh {87 19 79 79} labelsize 12 } { Fl_Button {} { user_data {"Fl_Window"} callback type_make_cb tooltip Window xywh {89 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Window]);} class Widget_Bin_Window_Button } Fl_Button {} { user_data {"Fl_Group"} callback type_make_cb tooltip Group xywh {114 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Group]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Pack"} callback type_make_cb tooltip Pack xywh {139 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Pack]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Tabs"} callback type_make_cb tooltip Tabs xywh {89 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Tabs]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Scroll"} callback type_make_cb tooltip Scroll xywh {114 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Scroll]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Flex"} callback type_make_cb tooltip Flex xywh {139 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Flex]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Tile"} callback type_make_cb tooltip Tile xywh {89 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Tile]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Wizard"} callback type_make_cb tooltip Wizard xywh {114 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Wizard]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Grid"} callback type_make_cb tooltip Grid xywh {139 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Grid]);} class Widget_Bin_Button } } Fl_Group {} { label Buttons open xywh {171 19 54 79} labelsize 12 } { Fl_Button {} { user_data {"Fl_Button"} callback type_make_cb tooltip Button xywh {173 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Button]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Return_Button"} callback type_make_cb tooltip {Return Button} xywh {198 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Return_Button]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Light_Button"} callback type_make_cb tooltip {Light Button} xywh {173 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Light_Button]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Repeat_Button"} callback type_make_cb tooltip {Repeat Button} xywh {198 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Repeat_Button]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Check_Button"} callback type_make_cb tooltip {Check Button} xywh {173 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Check_Button]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Round_Button"} callback type_make_cb tooltip {Round Button} xywh {198 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Round_Button]);} class Widget_Bin_Button } } Fl_Group {} { label Valuators open xywh {230 19 104 79} labelsize 12 } { Fl_Button {} { user_data {"Fl_Slider"} callback type_make_cb tooltip Slider xywh {232 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Slider]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Scrollbar"} callback type_make_cb tooltip {Scroll Bar} xywh {257 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Scrollbar]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Value_Slider"} callback type_make_cb tooltip {Value Slider} xywh {282 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Value_Slider]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Value_Output"} callback type_make_cb tooltip {Value Output} xywh {307 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Value_Output]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Adjuster"} callback type_make_cb tooltip Adjuster xywh {232 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Adjuster]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Counter"} callback type_make_cb tooltip Counter xywh {257 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Counter]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Dial"} callback type_make_cb tooltip Dial xywh {282 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Dial]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Roller"} callback type_make_cb tooltip Roller xywh {232 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Roller]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Spinner"} callback type_make_cb tooltip Spinner xywh {257 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Spinner]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Value_Input"} callback type_make_cb tooltip {Value Input} xywh {282 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Value_Input]);} class Widget_Bin_Button } } Fl_Group {} { label Text open xywh {339 19 54 79} labelsize 12 } { Fl_Button {} { user_data {"Fl_Input"} callback type_make_cb tooltip Input xywh {341 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Input]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Output"} callback type_make_cb tooltip Output xywh {366 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Output]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Text_Editor"} callback type_make_cb tooltip {Text Edit} xywh {341 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Text_Editor]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Text_Display"} callback type_make_cb tooltip {Text Display} xywh {366 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Text_Display]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_File_Input"} callback type_make_cb tooltip {File Input} xywh {341 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_File_Input]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Terminal"} callback type_make_cb tooltip Terminal xywh {366 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Terminal]);} class Widget_Bin_Button } } Fl_Group {} { label Menus open xywh {398 19 79 79} labelsize 12 } { Fl_Button {} { user_data {"Fl_Input_Choice"} callback type_make_cb tooltip {Input Choice} xywh {400 22 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Input_Choice]);} class Widget_Bin_Button } Fl_Button {} { user_data {"menuitem"} callback type_make_cb tooltip {Menu Item} xywh {425 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Menu_Item]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Menu_Bar"} callback type_make_cb tooltip {Menu Bar} xywh {450 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Menu_Bar]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Menu_Button"} callback type_make_cb tooltip {Menu Button} xywh {400 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Menu_Button]);} class Widget_Bin_Button } Fl_Button {} { user_data {"checkmenuitem"} callback type_make_cb tooltip {Checkbox Menu Item} xywh {425 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Checkbox_Menu_Item]);} class Widget_Bin_Button } Fl_Button {} { user_data {"submenu"} callback type_make_cb tooltip {Sub Menu} xywh {450 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Submenu]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Choice"} callback type_make_cb tooltip Choice xywh {400 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Choice]);} class Widget_Bin_Button } Fl_Button {} { user_data {"radiomenuitem"} callback type_make_cb tooltip {Radio Menu Item} xywh {425 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Radio_Menu_Item]);} class Widget_Bin_Button } } Fl_Group {} { label Browsers open xywh {482 19 54 79} labelsize 12 } { Fl_Button {} { user_data {"Fl_Browser"} callback type_make_cb tooltip Browser xywh {484 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Browser]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Tree"} callback type_make_cb tooltip Tree xywh {509 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Tree]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Check_Browser"} callback type_make_cb tooltip {Check Browser} xywh {484 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Check_Browser]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Help_View"} callback type_make_cb tooltip {Help Browser} xywh {509 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Help_View]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_File_Browser"} callback type_make_cb tooltip {File Browser} xywh {484 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_File_Browser]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Table"} callback type_make_cb tooltip Table xywh {509 71 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Table]);} class Widget_Bin_Button } } Fl_Group {} { label Misc open xywh {540 19 55 79} labelsize 12 } { Fl_Button {} { user_data {"Fl_Box"} callback type_make_cb tooltip Box xywh {542 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Box]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Clock"} callback type_make_cb tooltip Clock xywh {567 21 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Clock]);} class Widget_Bin_Button } Fl_Button {} { user_data {"Fl_Progress"} callback type_make_cb tooltip Progress xywh {542 46 24 24} box THIN_UP_BOX code0 {o->image(pixmap[ID_Progress]);} class Widget_Bin_Button } } } } comment { //} {in_source in_header } fltk-1.4.3/fluid/fluid.h0000644000175000017500000001453715004135251015176 0ustar albrechtalbrecht// // FLUID main entry for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_FLUID_H #define _FLUID_FLUID_H #include "fluid_filename.h" #include #include #include "../src/Fl_String.H" #define BROWSERWIDTH 300 #define BROWSERHEIGHT 500 #define WINWIDTH 300 #define MENUHEIGHT 25 #define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT) // ---- types class Fl_Double_Window; class Fl_Window; class Fl_Menu_Bar; class Fl_Type; class Fl_Choice; class Fl_Button; class Fl_Check_Button; /** Indicate the storage location for tools like layout suites and shell macros. \see class Fd_Shell_Command, class Fd_Layout_Suite */ typedef enum { FD_STORE_INTERNAL, ///< stored inside FLUID app FD_STORE_USER, ///< suite is stored in the user wide FLUID settings FD_STORE_PROJECT, ///< suite is stored within the current .fl project file FD_STORE_FILE ///< store suite in external file } Fd_Tool_Store; // ---- global variables extern Fl_Preferences fluid_prefs; extern Fl_Menu_Item Main_Menu[]; extern Fl_Menu_Bar *main_menubar; extern Fl_Window *main_window; extern int show_guides; extern int show_restricted; extern int show_ghosted_outline; extern int show_comments; extern int G_use_external_editor; extern int G_debug; extern char G_external_editor_command[512]; // File history info... extern char absolute_history[10][FL_PATH_MAX]; extern char relative_history[10][FL_PATH_MAX]; extern void load_history(); extern void update_history(const char *); extern Fl_Menu_Item *save_item; extern Fl_Menu_Item *history_item; extern Fl_Menu_Item *widgetbin_item; extern Fl_Menu_Item *codeview_item; extern Fl_Menu_Item *overlay_item; extern Fl_Button *overlay_button; extern Fl_Menu_Item *guides_item; extern Fl_Menu_Item *restricted_item; extern Fl_Check_Button *guides_button; extern int modflag; extern int update_file; // fluid -u extern int compile_file; // fluid -c extern int compile_strings; // fluic -cs extern int batch_mode; extern int pasteoffset; extern Fl_String g_code_filename_arg; extern Fl_String g_header_filename_arg; extern Fl_String g_launch_path; extern Fl_String g_autodoc_path; // ---- project class declaration /** Enumeration of available internationalization types. */ typedef enum { FD_I18N_NONE = 0, ///< No i18n, all strings are litearals FD_I18N_GNU, ///< GNU gettext internationalization FD_I18N_POSIX ///< Posix catgets internationalization } Fd_I18n_Type; /** Data and settings for a FLUID project file. */ class Fluid_Project { public: Fluid_Project(); ~Fluid_Project(); void reset(); void update_settings_dialog(); Fl_String projectfile_path() const; Fl_String projectfile_name() const; Fl_String codefile_path() const; Fl_String codefile_name() const; Fl_String headerfile_path() const; Fl_String headerfile_name() const; Fl_String stringsfile_path() const; Fl_String stringsfile_name() const; Fl_String basename() const; /// One of the available internationalization types. Fd_I18n_Type i18n_type; /// Include file for GNU i18n, writes an #include statement into the source /// file. This is usually `` or `"gettext.h"` for GNU gettext. Fl_String i18n_gnu_include; // Optional name of a macro for conditional i18n compilation. Fl_String i18n_gnu_conditional; /// For the gettext/intl.h options, this is the function that translates text /// at runtime. This is usually "gettext" or "_". Fl_String i18n_gnu_function; /// For the gettext/intl.h options, this is the function that marks the translation /// of text at initialisation time. This is usually "gettext_noop" or "N_". Fl_String i18n_gnu_static_function; /// Include file for Posix i18n, write a #include statement into the source /// file. This is usually `` for Posix catgets. Fl_String i18n_pos_include; // Optional name of a macro for conditional i18n compilation. Fl_String i18n_pos_conditional; /// Name of the nl_catd database Fl_String i18n_pos_file; /// Message set ID for the catalog. Fl_String i18n_pos_set; /// If set, generate code to include the header file form the c++ file int include_H_from_C; /// If set, handle keyboard shortcut Ctrl on macOS using Cmd instead int use_FL_COMMAND; /// Clear if UTF-8 characters in statics texts are written as escape sequences int utf8_in_src; /// If set, will not be included from the header code before anything else int avoid_early_includes; /// If set, command line overrides header file name in .fl file. int header_file_set; /// If set, command line overrides source code file name in .fl file. int code_file_set; int write_mergeback_data; /// Hold the default extension for header files, or the entire filename if set via command line. Fl_String header_file_name; /// Hold the default extension for source code files, or the entire filename if set via command line. Fl_String code_file_name; }; extern Fluid_Project g_project; // ---- public functions extern bool new_project(bool user_must_confirm = true); extern void enter_project_dir(); extern void leave_project_dir(); extern void set_filename(const char *c); extern void set_modflag(int mf, int mfc=-1); extern const Fl_String &get_tmpdir(); // ---- public callback functions extern void save_cb(Fl_Widget *, void *v); extern void save_template_cb(Fl_Widget *, void *); extern void revert_cb(Fl_Widget *,void *); extern void exit_cb(Fl_Widget *,void *); extern int write_code_files(bool dont_show_completion_dialog=false); extern void write_strings_cb(Fl_Widget *, void *); extern void align_widget_cb(Fl_Widget *, long); extern void toggle_widgetbin_cb(Fl_Widget *, void *); extern char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W=0, int H=0); inline int fd_min(int a, int b) { return (a < b ? a : b); } inline int fd_max(int a, int b) { return (a > b ? a : b); } inline int fd_min(int a, int b, int c) { return fd_min(a, fd_min(b, c)); } #endif // _FLUID_FLUID_H fltk-1.4.3/fluid/Fl_Grid_Type.h0000644000175000017500000000622415004135251016374 0ustar albrechtalbrecht// // Fl_Grid type header file for the Fast Light Tool Kit (FLTK). // // Copyright 2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_FL_GRID_TYPE_H #define _FLUID_FL_GRID_TYPE_H #include "Fl_Group_Type.h" #include // ---- Fl_Grid_Type --------------------------------------------------- MARK: - extern const char grid_type_name[]; class Fl_Grid_Proxy : public Fl_Grid { protected: typedef struct { Fl_Widget *widget; Cell *cell; } Cell_Widget_Pair; Cell_Widget_Pair *transient_; int num_transient_; int cap_transient_; void transient_make_room_(int n); void transient_remove_(Fl_Widget *w); public: Fl_Grid_Proxy(int X,int Y,int W,int H); ~Fl_Grid_Proxy(); void resize(int,int,int,int) FL_OVERRIDE; void draw() FL_OVERRIDE; void draw_overlay(); void move_cell(Fl_Widget *child, int to_row, int to_col, int how = 0); Cell* any_cell(Fl_Widget *widget) const; Cell* transient_cell(Fl_Widget *widget) const; Cell* transient_widget(Fl_Widget *wi, int row, int col, int row_span, int col_span, Fl_Grid_Align align = FL_GRID_FILL); Cell* widget(Fl_Widget *wi, int row, int col, Fl_Grid_Align align = FL_GRID_FILL); Cell* widget(Fl_Widget *wi, int row, int col, int rowspan, int colspan, Fl_Grid_Align align = FL_GRID_FILL); }; class Fl_Grid_Type : public Fl_Group_Type { typedef Fl_Group_Type super; public: Fl_Grid_Type(); const char *type_name() FL_OVERRIDE {return grid_type_name;} const char *alt_type_name() FL_OVERRIDE {return "fltk::GridGroup";} Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Grid_Type(); } Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Grid; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Grid) ? true : super::is_a(inID); } void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; void write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate) FL_OVERRIDE; void read_parent_property(Fd_Project_Reader &f, Fl_Type *child, const char *property) FL_OVERRIDE; Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; void leave_live_mode() FL_OVERRIDE; void copy_properties() FL_OVERRIDE; void copy_properties_for_children() FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void remove_child(Fl_Type*) FL_OVERRIDE; void layout_widget() FL_OVERRIDE; void child_resized(Fl_Widget_Type *child); void insert_child_at(Fl_Widget *child, int x, int y); void insert_child_at_next_free_cell(Fl_Widget *child); void keyboard_move_child(Fl_Widget_Type*, int key); static class Fl_Grid *selected(); }; #endif // _FLUID_FL_GRID_TYPE_H fltk-1.4.3/fluid/templates/0000755000175000017500000000000015004135251015706 5ustar albrechtalbrechtfltk-1.4.3/fluid/templates/FLTK_License.fl0000644000175000017500000000114615004135251020435 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} comment {// // @INSTANCE@ for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // } {in_source in_header } fltk-1.4.3/fluid/templates/1of7GUIs.fl0000644000175000017500000000137315004135251017541 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0400 header_name {.h} code_name {.cxx} comment { 1 of 7GUIs 7GUIs was been created as a spin-off of the master’s thesis Comparison of Object-Oriented and Functional Programming for GUI Development by Eugen Kiss at the Human-Computer Interaction group of the Leibniz Universität Hannover in 2014. https://7guis.github.io/7guis/ } {selected in_source not_in_header } Function {} {open } { Fl_Window {} { label Counter open xywh {486 292 194 55} type Double resizable visible } { Fl_Output counter_widget { xywh {15 15 80 22} code0 {counter_widget->value(0);} } Fl_Button {} { label Count callback {int i = counter_widget->ivalue(); i++; counter_widget->value(i);} xywh {99 15 80 22} } } } fltk-1.4.3/fluid/print_panel.fl0000644000175000017500000002501415004135251016550 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} comment {// // FLUID print panel for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // } {in_source in_header } decl {\#include "fluid.h"} {private local } decl {\#include } {private local } decl {\#include "../src/flstring.h"} {private local } decl {\#include } {private local } decl {\#include } {private local } Function {make_print_panel()} {open } { Fl_Window print_panel { label Print selected xywh {465 222 465 235} type Double modal visible } { Fl_Group print_panel_controls {open xywh {10 10 447 216} } { Fl_Choice print_choice { label {Printer:} callback {print_update_status();} open xywh {113 10 181 25} down_box BORDER_BOX labelfont 1 when 1 } {} Fl_Button print_properties { label {Properties...} callback {print_properties_panel->show();} xywh {294 10 105 25} } Fl_Box print_status { label {printer/job status} xywh {111 41 288 17} align 84 } Fl_Group {} { label {Print Range} open xywh {10 86 227 105} box THIN_DOWN_BOX labelfont 1 align 5 } { Fl_Round_Button print_all { label All callback {print_from->deactivate(); print_to->deactivate();} xywh {20 96 38 25} type Radio down_box ROUND_DOWN_BOX value 1 } Fl_Round_Button print_pages { label Pages callback {print_from->activate(); print_to->activate();} xywh {20 126 64 25} type Radio down_box ROUND_DOWN_BOX } Fl_Round_Button print_selection { label Selection callback {print_from->deactivate(); print_to->deactivate();} xywh {20 156 82 25} type Radio down_box ROUND_DOWN_BOX } Fl_Input print_from { label {From:} xywh {136 126 28 25} type Int textfont 4 deactivate } Fl_Input print_to { label {To:} xywh {199 126 28 25} type Int textfont 4 deactivate } } Fl_Group {} { label Copies open xywh {247 86 210 105} box THIN_DOWN_BOX labelfont 1 align 5 } { Fl_Spinner print_copies { label {\# Copies:} callback {if (print_copies->value() == 1) { print_collate_button->deactivate(); print_collate_group[0]->deactivate(); print_collate_group[1]->deactivate(); } else { print_collate_button->activate(); print_collate_group[0]->activate(); print_collate_group[1]->activate(); }} xywh {321 96 45 25} when 1 } Fl_Check_Button print_collate_button { label Collate callback {int i = print_collate_button->value() != 0; print_collate_group[i]->show(); print_collate_group[1 - i]->hide();} xywh {376 96 64 25} down_box DOWN_BOX when 1 deactivate } Fl_Group {print_collate_group[0]} { xywh {257 131 191 50} deactivate } { Fl_Box {} { label 1 xywh {287 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate } Fl_Box {} { label 1 xywh {272 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate } Fl_Box {} { label 1 xywh {257 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate } Fl_Box {} { label 2 xywh {352 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate } Fl_Box {} { label 2 xywh {337 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate } Fl_Box {} { label 2 xywh {322 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate } Fl_Box {} { label 3 xywh {417 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate } Fl_Box {} { label 3 xywh {402 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate } Fl_Box {} { label 3 xywh {387 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate } } Fl_Group {print_collate_group[1]} { xywh {257 131 191 50} hide deactivate } { Fl_Box {} { label 3 xywh {287 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 } Fl_Box {} { label 2 xywh {272 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 } Fl_Box {} { label 1 xywh {257 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 } Fl_Box {} { label 3 xywh {352 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 } Fl_Box {} { label 2 xywh {337 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 } Fl_Box {} { label 1 xywh {322 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 } Fl_Box {} { label 3 xywh {417 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 } Fl_Box {} { label 2 xywh {402 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 } Fl_Box {} { label 1 xywh {387 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 } } } Fl_Return_Button {} { label Print callback print_cb xywh {309 201 70 25} } Fl_Button {} { label Cancel callback {print_panel->hide();} xywh {389 201 68 25} } } Fl_Progress print_progress { xywh {10 203 289 21} selection_color 4 hide } } Fl_Window print_properties_panel { label {Printer Properties} callback {print_properties_panel->hide(); print_update_status();} xywh {462 486 290 130} type Double modal visible } { Fl_Choice print_page_size { label {Page Size:} xywh {110 10 80 25} down_box BORDER_BOX labelfont 1 labelsize 12 } { MenuItem {} { label Letter xywh {0 0 35 25} } MenuItem {} { label A4 xywh {0 0 35 25} } } Fl_Group {} { label {Output Mode:} open xywh {110 45 170 40} labelfont 1 labelsize 12 align 4 } { Fl_Button {print_output_mode[0]} { image {pixmaps/print_color.xpm} compress_image 0 xywh {110 45 30 40} type Radio box BORDER_BOX down_box BORDER_BOX value 1 color 7 selection_color 0 } Fl_Button {print_output_mode[1]} { image {pixmaps/print_color.xpm} compress_image 0 xywh {150 50 40 30} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0 } Fl_Button {print_output_mode[2]} { image {pixmaps/print_gray.xpm} compress_image 0 xywh {200 45 30 40} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0 } Fl_Button {print_output_mode[3]} { image {pixmaps/print_gray.xpm} compress_image 0 xywh {240 50 40 30} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0 } } Fl_Return_Button {} { label Save callback {print_properties_panel->hide(); char name[1024]; int val; const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); snprintf(name, sizeof(name), "%s/page_size", printer); fluid_prefs.set(name, print_page_size->value()); snprintf(name, sizeof(name), "%s/output_mode", printer); for (val = 0; val < 4; val ++) { if (print_output_mode[val]->value()) break; } fluid_prefs.set(name, val);} xywh {123 95 79 25} } Fl_Button {} { label Cancel callback {print_properties_panel->hide(); print_update_status();} xywh {212 95 68 25} } Fl_Button {} { label Use callback {print_properties_panel->hide();} xywh {60 95 53 25} } } } decl {void print_cb(Fl_Return_Button *, void *);} {public local } Function {print_load()} {open return_type void } { code {FILE *lpstat; char line[1024], name[1024], *nptr, qname[2048], *qptr, defname[1024]; int i; if (print_choice->size() > 1) { for (i = 1; print_choice->text(i); i ++) { free(print_choice->menu()[i].user_data()); } } print_choice->clear(); print_choice->add("Print To File", 0, 0, 0, FL_MENU_DIVIDER); print_choice->value(0); defname[0] = '\\0'; if ((lpstat = popen("LC_MESSAGES=C LANG=C lpstat -p -d", "r")) != NULL) { while (fgets(line, sizeof(line), lpstat)) { if (!strncmp(line, "printer ", 8) && sscanf(line + 8, "%s", name) == 1) { for (nptr = name, qptr = qname; *nptr; *qptr++ = *nptr++) { if (*nptr == '/') *qptr++ = '\\\\'; } *qptr = '\\0'; print_choice->add(qname, 0, 0, (void *)fl_strdup(name), 0); } else if (!strncmp(line, "system default destination: ", 28)) { if (sscanf(line + 28, "%s", defname) != 1) defname[0] = '\\0'; } } pclose(lpstat); } if (defname[0]) { for (i = 1; print_choice->text(i); i ++) { if (!strcmp((char *)print_choice->menu()[i].user_data(), defname)) { print_choice->value(i); break; } } } else if (print_choice->size() > 2) print_choice->value(1); print_update_status();} {} } Function {print_update_status()} {open return_type void } { code {FILE *lpstat; char command[1024]; static char status[1024]; const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); if (print_choice->value()) { snprintf(command, sizeof(command), "lpstat -p '%s'", printer); if ((lpstat = popen(command, "r")) != NULL) { if (fgets(status, sizeof(status), lpstat)==0) { /* ignore */ } pclose(lpstat); } else strcpy(status, "printer status unavailable"); } else status[0] = '\\0'; print_status->label(status); char name[1024]; int val; snprintf(name, sizeof(name), "%s/page_size", printer); fluid_prefs.get(name, val, 0); print_page_size->value(val); snprintf(name, sizeof(name), "%s/output_mode", printer); fluid_prefs.get(name, val, 0); print_output_mode[val]->setonly();} {} } fltk-1.4.3/fluid/widget_browser.h0000644000175000017500000000445515004135251017117 0ustar albrechtalbrecht// // Widget Browser code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_WIDGET_BROWSER_H #define _FLUID_WIDGET_BROWSER_H #include class Fl_Type; class Widget_Browser; extern Widget_Browser *widget_browser; extern void redraw_browser(); extern Fl_Widget *make_widget_browser(int x,int y,int w,int h); extern void redraw_widget_browser(Fl_Type *caller); extern void select(Fl_Type *o, int v); extern void select_only(Fl_Type *o); extern void deselect(); extern void reveal_in_browser(Fl_Type *t); class Widget_Browser : public Fl_Browser_ { friend class Fl_Type; static void callback_stub(Fl_Widget *o, void *) { ((Widget_Browser *)o)->callback(); } Fl_Type* pushedtitle; int saved_h_scroll_; int saved_v_scroll_; // required routines for Fl_Browser_ subclass: void *item_first() const FL_OVERRIDE; void *item_next(void *) const FL_OVERRIDE; void *item_prev(void *) const FL_OVERRIDE; int item_selected(void *) const FL_OVERRIDE; void item_select(void *,int) FL_OVERRIDE; int item_width(void *) const FL_OVERRIDE; int item_height(void *) const FL_OVERRIDE; void item_draw(void *,int,int,int,int) const FL_OVERRIDE; int incr_height() const FL_OVERRIDE; public: Widget_Browser(int,int,int,int,const char * =NULL); int handle(int) FL_OVERRIDE; void callback(); void save_scroll_position(); void restore_scroll_position(); void rebuild(); void new_list() { Fl_Browser_::new_list(); } void display(Fl_Type *); void load_prefs(); void save_prefs(); static Fl_Color label_color; static Fl_Font label_font; static Fl_Color class_color; static Fl_Font class_font; static Fl_Color func_color; static Fl_Font func_font; static Fl_Color name_color; static Fl_Font name_font; static Fl_Color code_color; static Fl_Font code_font; static Fl_Color comment_color; static Fl_Font comment_font; }; #endif // _FLUID_WIDGET_BROWSER_H fltk-1.4.3/fluid/Fl_Group_Type.h0000644000175000017500000002234215004135251016602 0ustar albrechtalbrecht// // Group type header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_FL_GROUP_TYPE_H #define _FLUID_FL_GROUP_TYPE_H #include "Fl_Widget_Type.h" #include #include #include #include void group_cb(Fl_Widget *, void *); void ungroup_cb(Fl_Widget *, void *); // ---- Fl_Group_Type -------------------------------------------------- MARK: - /** Proxy group to use in place of Fl_Group in the interactive window. In an interactive environment, groups should not automatically resize their children. This proxy disables the layout of children by default. Children layout propagation may be enable temporarily by incrementing `allow_layout` before resizing and decrementing it again afterwards. */ class Fl_Group_Proxy : public Fl_Group { public: Fl_Group_Proxy(int X,int Y,int W,int H) : Fl_Group(X, Y, W, H) { Fl_Group::current(0); } void resize(int x, int y, int w, int h) FL_OVERRIDE; void draw() FL_OVERRIDE; }; class Fl_Group_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "Fl_Group";} const char *alt_type_name() FL_OVERRIDE {return "fltk::Group";} Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { Fl_Group_Proxy *g = new Fl_Group_Proxy(X,Y,W,H); Fl_Group::current(0); return g;} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Group_Type();} void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void remove_child(Fl_Type*) FL_OVERRIDE; int can_have_children() const FL_OVERRIDE {return 1;} ID id() const FL_OVERRIDE { return ID_Group; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Group) ? true : super::is_a(inID); } Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; void leave_live_mode() FL_OVERRIDE; void copy_properties() FL_OVERRIDE; }; // ---- Fl_Pack_Type --------------------------------------------------- MARK: - extern const char pack_type_name[]; extern Fl_Menu_Item pack_type_menu[]; class Fl_Pack_Type : public Fl_Group_Type { typedef Fl_Group_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE {return pack_type_menu;} public: const char *type_name() FL_OVERRIDE {return pack_type_name;} const char *alt_type_name() FL_OVERRIDE {return "fltk::PackedGroup";} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Pack_Type();} ID id() const FL_OVERRIDE { return ID_Pack; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Pack) ? true : super::is_a(inID); } Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; void copy_properties() FL_OVERRIDE; }; // ---- Fl_Flex_Type --------------------------------------------------- MARK: - extern const char flex_type_name[]; extern Fl_Menu_Item flex_type_menu[]; class Fl_Flex_Proxy : public Fl_Flex { public: Fl_Flex_Proxy(int X,int Y,int W,int H) : Fl_Flex(X, Y, W, H) { Fl_Group::current(0); } void resize(int x, int y, int w, int h) FL_OVERRIDE; void draw() FL_OVERRIDE; }; class Fl_Flex_Type : public Fl_Group_Type { typedef Fl_Group_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE {return flex_type_menu;} int fixedSizeTupleSize; /* number of pairs in array */ int *fixedSizeTuple; /* [ index, size, index2, size2, ... ] */ int suspend_auto_layout; public: Fl_Flex_Type() : fixedSizeTupleSize(0), fixedSizeTuple(NULL), suspend_auto_layout(0) { } const char *type_name() FL_OVERRIDE {return flex_type_name;} const char *alt_type_name() FL_OVERRIDE {return "fltk::FlexGroup";} Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Flex_Type(); } Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { Fl_Flex *g = new Fl_Flex_Proxy(X,Y,W,H); Fl_Group::current(0); return g;} ID id() const FL_OVERRIDE { return ID_Flex; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Flex) ? true : super::is_a(inID); } void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; void copy_properties() FL_OVERRIDE; void copy_properties_for_children() FL_OVERRIDE; void postprocess_read() FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; // void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; // void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void remove_child(Fl_Type*) FL_OVERRIDE; void layout_widget() FL_OVERRIDE; void change_subtype_to(int n); void insert_child_at(Fl_Widget *child, int x, int y); void keyboard_move_child(Fl_Widget_Type*, int key); static int parent_is_flex(Fl_Type*); static int size(Fl_Type*, char fixed_only=0); static int is_fixed(Fl_Type*); }; // ---- Fl_Table_Type -------------------------------------------------- MARK: - class Fl_Table_Type : public Fl_Group_Type { typedef Fl_Group_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE; const char *type_name() FL_OVERRIDE { return "Fl_Table"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::TableGroup"; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Table_Type(); } Fl_Widget *widget(int X, int Y, int W, int H) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Table; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Table) ? true : super::is_a(inID); } Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void remove_child(Fl_Type*) FL_OVERRIDE; }; // ---- Fl_Tabs_Type --------------------------------------------------- MARK: - extern const char tabs_type_name[]; class Fl_Tabs_Proxy : public Fl_Tabs { public: Fl_Tabs_Proxy(int X,int Y,int W,int H) : Fl_Tabs(X,Y,W,H) {} void resize(int,int,int,int) FL_OVERRIDE; void draw() FL_OVERRIDE; }; class Fl_Tabs_Type : public Fl_Group_Type { typedef Fl_Group_Type super; public: const char *type_name() FL_OVERRIDE {return tabs_type_name;} const char *alt_type_name() FL_OVERRIDE {return "fltk::TabGroup";} Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { Fl_Tabs_Proxy *g = new Fl_Tabs_Proxy(X,Y,W,H); Fl_Group::current(0); return g;} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Tabs_Type();} Fl_Type* click_test(int,int) FL_OVERRIDE; void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void remove_child(Fl_Type*) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Tabs; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Tabs) ? true : super::is_a(inID); } Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; }; // ---- Fl_Scroll_Type ------------------------------------------------- MARK: - extern const char scroll_type_name[]; extern Fl_Menu_Item scroll_type_menu[]; class Fl_Scroll_Type : public Fl_Group_Type { typedef Fl_Group_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE {return scroll_type_menu;} public: const char *type_name() FL_OVERRIDE {return scroll_type_name;} const char *alt_type_name() FL_OVERRIDE {return "fltk::ScrollGroup";} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Scroll_Type();} ID id() const FL_OVERRIDE { return ID_Scroll; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Scroll) ? true : super::is_a(inID); } Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; void copy_properties() FL_OVERRIDE; }; // ---- Fl_Tile_Type --------------------------------------------------- MARK: - extern const char tile_type_name[]; class Fl_Tile_Type : public Fl_Group_Type { typedef Fl_Group_Type super; public: const char *type_name() FL_OVERRIDE {return tile_type_name;} const char *alt_type_name() FL_OVERRIDE {return "fltk::TileGroup";} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Tile_Type();} ID id() const FL_OVERRIDE { return ID_Tile; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Tile) ? true : super::is_a(inID); } void copy_properties() FL_OVERRIDE; }; // ---- Fl_Wizard_Type ------------------------------------------------- MARK: - class Fl_Wizard_Proxy : public Fl_Wizard { public: Fl_Wizard_Proxy(int X,int Y,int W,int H) : Fl_Wizard(X,Y,W,H) {} void resize(int,int,int,int) FL_OVERRIDE; void draw() FL_OVERRIDE; }; extern const char wizard_type_name[]; class Fl_Wizard_Type : public Fl_Group_Type { typedef Fl_Group_Type super; public: const char *type_name() FL_OVERRIDE {return wizard_type_name;} const char *alt_type_name() FL_OVERRIDE {return "fltk::WizardGroup";} Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { Fl_Wizard_Proxy *g = new Fl_Wizard_Proxy(X,Y,W,H); Fl_Group::current(0); return g;} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Wizard_Type();} ID id() const FL_OVERRIDE { return ID_Wizard; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Wizard) ? true : super::is_a(inID); } }; #endif // _FLUID_FL_GROUP_TYPE_H fltk-1.4.3/fluid/pixmaps.cxx0000644000175000017500000002117515004135251016123 0ustar albrechtalbrecht// // Fluid Image management for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "pixmaps.h" #include "Fl_Type.h" #include #include "pixmaps/bind.xpm" #include "pixmaps/lock.xpm" #include "pixmaps/protected.xpm" #include "pixmaps/invisible.xpm" #include "pixmaps/compressed.xpm" #include "pixmaps/flWindow.xpm" #include "pixmaps/flButton.xpm" #include "pixmaps/flCheckButton.xpm" #include "pixmaps/flRoundButton.xpm" #include "pixmaps/flBox.xpm" #include "pixmaps/flGroup.xpm" #include "pixmaps/flFunction.xpm" #include "pixmaps/flCode.xpm" #include "pixmaps/flCodeBlock.xpm" #include "pixmaps/flComment.xpm" #include "pixmaps/flData.xpm" #include "pixmaps/flDeclaration.xpm" #include "pixmaps/flDeclarationBlock.xpm" #include "pixmaps/flClass.xpm" #include "pixmaps/flTabs.xpm" #include "pixmaps/flInput.xpm" #include "pixmaps/flChoice.xpm" #include "pixmaps/flMenuitem.xpm" #include "pixmaps/flMenubar.xpm" #include "pixmaps/flSubmenu.xpm" #include "pixmaps/flScroll.xpm" #include "pixmaps/flTile.xpm" #include "pixmaps/flWizard.xpm" #include "pixmaps/flPack.xpm" #include "pixmaps/flReturnButton.xpm" #include "pixmaps/flLightButton.xpm" #include "pixmaps/flRepeatButton.xpm" #include "pixmaps/flMenuButton.xpm" #include "pixmaps/flOutput.xpm" #include "pixmaps/flTextDisplay.xpm" #include "pixmaps/flTextEdit.xpm" #include "pixmaps/flFileInput.xpm" #include "pixmaps/flBrowser.xpm" #include "pixmaps/flCheckBrowser.xpm" #include "pixmaps/flFileBrowser.xpm" #include "pixmaps/flClock.xpm" #include "pixmaps/flHelp.xpm" #include "pixmaps/flProgress.xpm" #include "pixmaps/flSlider.xpm" #include "pixmaps/flScrollBar.xpm" #include "pixmaps/flValueSlider.xpm" #include "pixmaps/flAdjuster.xpm" #include "pixmaps/flCounter.xpm" #include "pixmaps/flDial.xpm" #include "pixmaps/flRoller.xpm" #include "pixmaps/flValueInput.xpm" #include "pixmaps/flValueOutput.xpm" #include "pixmaps/flSpinner.xpm" #include "pixmaps/flWidgetClass.xpm" #include "pixmaps/flTree.xpm" #include "pixmaps/flTable.xpm" #include "pixmaps/flSimpleTerminal.xpm" #include "pixmaps/flInputChoice.xpm" #include "pixmaps/flCheckMenuitem.xpm" #include "pixmaps/flRadioMenuitem.xpm" #include "pixmaps/flFlex.xpm" #include "pixmaps/flGrid.xpm" Fl_Pixmap *bind_pixmap; Fl_Pixmap *lock_pixmap; Fl_Pixmap *protected_pixmap; Fl_Pixmap *invisible_pixmap; Fl_Pixmap *compressed_pixmap; Fl_Pixmap *pixmap[ID_Max_] = { NULL }; /** Draw a zoom cross pointing in all four diagonal directions */ void fd_zoom(Fl_Color c) { const double al = 0.45, sl = 0.3; fl_color(c); fl_begin_line(); fl_vertex(-1.0, -al); fl_vertex(-1.0, -1.0); fl_vertex(-al, -1.0); fl_end_line(); fl_begin_line(); fl_vertex(-1.0, -1.0); fl_vertex(-sl, -sl); fl_end_line(); fl_begin_line(); fl_vertex(1.0, -al); fl_vertex(1.0, -1.0); fl_vertex(al, -1.0); fl_end_line(); fl_begin_line(); fl_vertex(1.0, -1.0); fl_vertex(sl, -sl); fl_end_line(); fl_begin_line(); fl_vertex(-1.0, al); fl_vertex(-1.0, 1.0); fl_vertex(-al, 1.0); fl_end_line(); fl_begin_line(); fl_vertex(-1.0, 1.0); fl_vertex(-sl, sl); fl_end_line(); fl_begin_line(); fl_vertex(1.0, al); fl_vertex(1.0, 1.0); fl_vertex(al, 1.0); fl_end_line(); fl_begin_line(); fl_vertex(1.0, 1.0); fl_vertex(sl, sl); fl_end_line(); } void loadPixmaps() { Fl_Pixmap *tmp; bind_pixmap = new Fl_Pixmap(bind_xpm); bind_pixmap->scale(16, 16); lock_pixmap = new Fl_Pixmap(lock_xpm); lock_pixmap->scale(16, 16); protected_pixmap = new Fl_Pixmap(protected_xpm); protected_pixmap->scale(16, 16); invisible_pixmap = new Fl_Pixmap(invisible_xpm); invisible_pixmap->scale(16, 16); compressed_pixmap = new Fl_Pixmap(compressed_xpm); compressed_pixmap->scale(16, 16); pixmap[ID_Window] = tmp = new Fl_Pixmap(flWindow_xpm); tmp->scale(16, 16); pixmap[ID_Button] = tmp = new Fl_Pixmap(flButton_xpm); tmp->scale(16, 16); pixmap[ID_Check_Button] = tmp = new Fl_Pixmap(flCheckButton_xpm); tmp->scale(16, 16); pixmap[ID_Round_Button] = tmp = new Fl_Pixmap(flRoundButton_xpm); tmp->scale(16, 16); pixmap[ID_Box] = tmp = new Fl_Pixmap(flBox_xpm); tmp->scale(16, 16); pixmap[ID_Group] = tmp = new Fl_Pixmap(flGroup_xpm); tmp->scale(16, 16); pixmap[ID_Function] = tmp = new Fl_Pixmap(flFunction_xpm); tmp->scale(16, 16); pixmap[ID_Code] = tmp = new Fl_Pixmap(flCode_xpm); tmp->scale(16, 16); pixmap[ID_CodeBlock] = tmp = new Fl_Pixmap(flCodeBlock_xpm); tmp->scale(16, 16); pixmap[ID_Decl] = tmp = new Fl_Pixmap(flDeclaration_xpm); tmp->scale(16, 16); pixmap[ID_DeclBlock] = tmp = new Fl_Pixmap(flDeclarationBlock_xpm); tmp->scale(16, 16); pixmap[ID_Class] = tmp = new Fl_Pixmap(flClass_xpm); tmp->scale(16, 16); pixmap[ID_Tabs] = tmp = new Fl_Pixmap(flTabs_xpm); tmp->scale(16, 16); pixmap[ID_Input] = tmp = new Fl_Pixmap(flInput_xpm); tmp->scale(16, 16); pixmap[ID_Choice] = tmp = new Fl_Pixmap(flChoice_xpm); tmp->scale(16, 16); pixmap[ID_Menu_Item] = tmp = new Fl_Pixmap(flMenuitem_xpm); tmp->scale(16, 16); pixmap[ID_Menu_Bar] = tmp = new Fl_Pixmap(flMenubar_xpm); tmp->scale(16, 16); pixmap[ID_Submenu] = tmp = new Fl_Pixmap(flSubmenu_xpm); tmp->scale(16, 16); pixmap[ID_Scroll] = tmp = new Fl_Pixmap(flScroll_xpm); tmp->scale(16, 16); pixmap[ID_Tile] = tmp = new Fl_Pixmap(flTile_xpm); tmp->scale(16, 16); pixmap[ID_Wizard] = tmp = new Fl_Pixmap(flWizard_xpm); tmp->scale(16, 16); pixmap[ID_Pack] = tmp = new Fl_Pixmap(flPack_xpm); tmp->scale(16, 16); pixmap[ID_Return_Button] = tmp = new Fl_Pixmap(flReturnButton_xpm); tmp->scale(16, 16); pixmap[ID_Light_Button] = tmp = new Fl_Pixmap(flLightButton_xpm); tmp->scale(16, 16); pixmap[ID_Repeat_Button] = tmp = new Fl_Pixmap(flRepeatButton_xpm); tmp->scale(16, 16); pixmap[ID_Menu_Button] = tmp = new Fl_Pixmap(flMenuButton_xpm); tmp->scale(16, 16); pixmap[ID_Output] = tmp = new Fl_Pixmap(flOutput_xpm); tmp->scale(16, 16); pixmap[ID_Text_Display] = tmp = new Fl_Pixmap(flTextDisplay_xpm); tmp->scale(16, 16); pixmap[ID_Text_Editor] = tmp = new Fl_Pixmap(flTextEdit_xpm); tmp->scale(16, 16); pixmap[ID_File_Input] = tmp = new Fl_Pixmap(flFileInput_xpm); tmp->scale(16, 16); pixmap[ID_Browser] = tmp = new Fl_Pixmap(flBrowser_xpm); tmp->scale(16, 16); pixmap[ID_Check_Browser] = tmp = new Fl_Pixmap(flCheckBrowser_xpm); tmp->scale(16, 16); pixmap[ID_File_Browser] = tmp = new Fl_Pixmap(flFileBrowser_xpm); tmp->scale(16, 16); pixmap[ID_Clock] = tmp = new Fl_Pixmap(flClock_xpm); tmp->scale(16, 16); pixmap[ID_Help_View] = tmp = new Fl_Pixmap(flHelp_xpm); tmp->scale(16, 16); pixmap[ID_Progress] = tmp = new Fl_Pixmap(flProgress_xpm); tmp->scale(16, 16); pixmap[ID_Slider] = tmp = new Fl_Pixmap(flSlider_xpm); tmp->scale(16, 16); pixmap[ID_Scrollbar] = tmp = new Fl_Pixmap(flScrollBar_xpm); tmp->scale(16, 16); pixmap[ID_Value_Slider] = tmp = new Fl_Pixmap(flValueSlider_xpm); tmp->scale(16, 16); pixmap[ID_Adjuster] = tmp = new Fl_Pixmap(flAdjuster_xpm); tmp->scale(16, 16); pixmap[ID_Counter] = tmp = new Fl_Pixmap(flCounter_xpm); tmp->scale(16, 16); pixmap[ID_Dial] = tmp = new Fl_Pixmap(flDial_xpm); tmp->scale(16, 16); pixmap[ID_Roller] = tmp = new Fl_Pixmap(flRoller_xpm); tmp->scale(16, 16); pixmap[ID_Value_Input] = tmp = new Fl_Pixmap(flValueInput_xpm); tmp->scale(16, 16); pixmap[ID_Value_Output] = tmp = new Fl_Pixmap(flValueOutput_xpm); tmp->scale(16, 16); pixmap[ID_Comment] = tmp = new Fl_Pixmap(flComment_xpm); tmp->scale(16, 16); pixmap[ID_Spinner] = tmp = new Fl_Pixmap(flSpinner_xpm); tmp->scale(16, 16); pixmap[ID_Widget_Class] = tmp = new Fl_Pixmap(flWidgetClass_xpm); tmp->scale(16, 16); pixmap[ID_Data] = tmp = new Fl_Pixmap(flData_xpm); tmp->scale(16, 16); pixmap[ID_Tree] = tmp = new Fl_Pixmap(flTree_xpm); tmp->scale(16, 16); pixmap[ID_Table] = tmp = new Fl_Pixmap(flTable_xpm); tmp->scale(16, 16); pixmap[ID_Terminal] = tmp = new Fl_Pixmap(flSimpleTerminal_xpm); tmp->scale(16, 16); pixmap[ID_Input_Choice] = tmp = new Fl_Pixmap(flInputChoice_xpm); tmp->scale(16, 16); pixmap[ID_Checkbox_Menu_Item] = tmp = new Fl_Pixmap(flCheckMenuitem_xpm); tmp->scale(16, 16); pixmap[ID_Radio_Menu_Item] = tmp = new Fl_Pixmap(flRadioMenuitem_xpm); tmp->scale(16, 16); pixmap[ID_Flex] = tmp = new Fl_Pixmap(flFlex_xpm); tmp->scale(16, 16); pixmap[ID_Grid] = tmp = new Fl_Pixmap(flGrid_xpm); tmp->scale(16, 16); fl_add_symbol("fd_zoom", fd_zoom, 1); } fltk-1.4.3/fluid/ExternalCodeEditor_WIN32.cxx0000644000175000017500000005440215004135251021047 0ustar albrechtalbrecht// // External code editor management class for Windows // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Note: This entire file Windows only. #include // Fl_Timeout_Handler.. #include // fl_alert() #include // fl_utf8fromwc() #include // fl_strdup() #include "ExternalCodeEditor_WIN32.h" #include "fluid.h" #include // snprintf() #include extern int G_debug; // defined in fluid.cxx // Static local data static int L_editors_open = 0; // keep track of #editors open static Fl_Timeout_Handler L_update_timer_cb = 0; // app's update timer callback static wchar_t *wbuf = NULL; static char *abuf = NULL; static wchar_t *utf8_to_wchar(const char *utf8, wchar_t *&wbuf, int lg = -1) { unsigned len = (lg >= 0) ? (unsigned)lg : (unsigned)strlen(utf8); unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 1; // Query length wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * wn); wn = fl_utf8toUtf16(utf8, len, (unsigned short *)wbuf, wn); // Convert string wbuf[wn] = 0; return wbuf; } static char *wchar_to_utf8(const wchar_t *wstr, char *&utf8) { unsigned len = (unsigned)wcslen(wstr); unsigned wn = fl_utf8fromwc(NULL, 0, wstr, len) + 1; // query length utf8 = (char *)realloc(utf8, wn); wn = fl_utf8fromwc(utf8, wn, wstr, len); // convert string utf8[wn] = 0; return utf8; } // [Static/Local] Get error message string for last failed WIN32 function. // Returns a string pointing to static memory. // static const char *get_ms_errmsg() { static char emsg[1024]; DWORD lastErr = GetLastError(); DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM; DWORD langid = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); LPWSTR mbuf = 0; DWORD msize = 0; // Get error message from Windows msize = FormatMessageW(flags, 0, lastErr, langid, (LPWSTR)&mbuf, 0, NULL); if ( msize == 0 ) { _snprintf(emsg, sizeof(emsg), "Error #%ld", (unsigned long)lastErr); } else { // Convert message to UTF-8 fl_utf8fromwc(emsg, sizeof(emsg), mbuf, msize); // Remove '\r's -- they screw up fl_alert() char *src = emsg, *dst = emsg; for ( ; 1; src++ ) { if ( *src == '\0' ) { *dst = '\0'; break; } if ( *src != '\r' ) { *dst++ = *src; } } LocalFree(mbuf); // Free the buffer allocated by the system } return emsg; } // [Static/Local] See if file exists static int is_file(const char *filename) { utf8_to_wchar(filename, wbuf); DWORD att = GetFileAttributesW(wbuf); if (att == INVALID_FILE_ATTRIBUTES) return 0; if ( (att & FILE_ATTRIBUTE_DIRECTORY) == 0 ) return 1; // not a dir == file return 0; } // [Static/Local] See if dir exists static int is_dir(const char *dirname) { utf8_to_wchar(dirname, wbuf); DWORD att = GetFileAttributesW(wbuf); if (att == INVALID_FILE_ATTRIBUTES) return 0; if (att & FILE_ATTRIBUTE_DIRECTORY) return 1; return 0; } // CTOR ExternalCodeEditor::ExternalCodeEditor() { memset(&pinfo_, 0, sizeof(pinfo_)); memset(&file_mtime_, 0, sizeof(file_mtime_)); memset(&file_size_, 0, sizeof(file_size_)); filename_ = 0; } // DTOR ExternalCodeEditor::~ExternalCodeEditor() { close_editor(); // close editor, delete tmp file set_filename(0); // free()s filename } // [Protected] Set the filename. Handles memory allocation/free // If set to NULL, frees memory. // void ExternalCodeEditor::set_filename(const char *val) { if ( filename_ ) free((void*)filename_); filename_ = val ? fl_strdup(val) : 0; } // [Public] Is editor running? int ExternalCodeEditor::is_editing() { return( (pinfo_.dwProcessId != 0) ? 1 : 0 ); } // [Static/Local] Terminate_app()'s callback to send WM_CLOSE to a single window. static BOOL CALLBACK terminate_app_enum(HWND hwnd, LPARAM lParam) { DWORD dwID; GetWindowThreadProcessId(hwnd, &dwID); if (dwID == (DWORD)lParam) { PostMessage(hwnd, WM_CLOSE, 0, 0); if ( G_debug ) printf("terminate_app_enum() sends WIN_CLOSE to hwnd=%p\n", (void*)hwnd); } return TRUE; } // [Static/Local] Handle sending WIN_CLOSE to /all/ windows matching specified pid. // Wait up to msecTimeout for process to close, and if it doesn't, use TerminateProcess(). // static int terminate_app(DWORD pid, DWORD msecTimeout) { HANDLE hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid); if ( !hProc ) return -1; // terminate_app_enum() posts WM_CLOSE to all windows matching pid EnumWindows((WNDENUMPROC)terminate_app_enum, (LPARAM) pid); // Wait on handle. If it closes, great. If it times out, use TerminateProcess() int ret = 0; if ( WaitForSingleObject(hProc, msecTimeout) != WAIT_OBJECT_0 ) { if ( G_debug ) { printf("WARNING: sent WIN_CLOSE, but timeout after %ld msecs.." "trying TerminateProcess\n", msecTimeout); } if ( TerminateProcess(hProc, 0) == 0 ) { if ( G_debug ) { printf("ERROR: TerminateProcess() for pid=%ld failed: %s\n", long(pid), get_ms_errmsg()); } ret = -1; } else { ret = 0; // TerminateProcess succeeded } } else { ret = 0; // WaitForSingleObject() confirmed WIN_CLOSE succeeded } CloseHandle(hProc); return ret; } // [Protected] Wait for editor to close void ExternalCodeEditor::close_editor() { if ( G_debug ) printf("close_editor() called: pid=%ld\n", long(pinfo_.dwProcessId)); // Wait until editor is closed + reaped while ( is_editing() ) { switch ( reap_editor() ) { case -2: // no editor running (unlikely to happen) return; case -1: // error fl_alert("Error reaping external editor\npid=%ld file=%s\nOS error message=%s", long(pinfo_.dwProcessId), filename(), get_ms_errmsg()); break; case 0: // process still running switch ( fl_choice("Please close external editor\npid=%ld file=%s", "Force Close", // button 0 "Closed", // button 1 0, // button 2 long(pinfo_.dwProcessId), filename() ) ) { case 0: // Force Close kill_editor(); continue; case 1: // Closed? try to reap continue; } break; case 1: // process reaped return; } } } // [Protected] Kill the running editor (if any) and cleanup // Kills the editor, reaps the process, and removes the tmp file. // The dtor calls this to ensure no editors remain running when fluid exits. // void ExternalCodeEditor::kill_editor() { if ( G_debug ) printf("kill_editor() called: pid=%ld\n", (long)pinfo_.dwProcessId); if ( !is_editing() ) return; switch ( terminate_app(pinfo_.dwProcessId, 500) ) { // kill editor, wait up to 1/2 sec to die case -1: { // error fl_alert("Can't seem to close editor of file: %s\n" "Please close editor and hit OK", filename()); break; } case 0: { // success -- process reaped DWORD pid = pinfo_.dwProcessId; // save pid reap_cleanup(); // clears pinfo_ if ( G_debug ) printf("*** kill_editor() REAP pid=%ld #open=%ld\n", long(pid), long(L_editors_open)); break; } } return; } // [Public] Handle if file changed since last check, and update records if so. // Load new data into 'code', which caller must free(). // If 'force' set, forces reload even if file size/time didn't change. // // Returns: // 0 -- file unchanged or not editing // 1 -- file changed, internal records updated, 'code' has new content // -1 -- error getting file info (get_ms_errmsg() has reason) // // OPTIONAL TODO: // Ignore changes made within the last 2 seconds, // to give editor time to fully write out the file. // int ExternalCodeEditor::handle_changes(const char **code, int force) { code[0] = 0; if ( !is_editing() ) return 0; // Sigh, have to open file to get file time/size :/ utf8_to_wchar(filename(), wbuf); HANDLE fh = CreateFileW(wbuf, // file to read GENERIC_READ, // reading only FILE_SHARE_READ, // sharing -- allow read share; just getting file size NULL, // security OPEN_EXISTING, // create flags -- must exist 0, // misc flags NULL); // templates if ( fh == INVALID_HANDLE_VALUE ) return -1; LARGE_INTEGER fsize; // Get file size if ( GetFileSizeEx(fh, &fsize) == 0 ) { DWORD err = GetLastError(); CloseHandle(fh); SetLastError(err); // return error from GetFileSizeEx(), not CloseHandle() return -1; } // Get file time FILETIME ftCreate, ftAccess, ftWrite; if ( GetFileTime(fh, &ftCreate, &ftAccess, &ftWrite) == 0 ) { DWORD err = GetLastError(); CloseHandle(fh); SetLastError(err); // return error from GetFileTime(), not CloseHandle() return -1; } // OK, now see if file changed; update records if so int changed = 0; if ( fsize.QuadPart != file_size_.QuadPart ) { changed = 1; file_size_ = fsize; } if ( CompareFileTime(&ftWrite, &file_mtime_) != 0 ) { changed = 1; file_mtime_ = ftWrite; } // Changes? Load file. Be sure to fallthru to CloseHandle() int ret = 0; if ( changed || force ) { DWORD buflen = (DWORD)fsize.QuadPart; char *buf = (char*)malloc((size_t)buflen + 1); DWORD count; if ( ReadFile(fh, buf, buflen, &count, 0) == 0 ) { fl_alert("ERROR: ReadFile() failed for %s: %s", filename(), get_ms_errmsg()); free((void*)buf); buf = 0; ret = -1; // fallthru to CloseHandle() } else if ( count != buflen ) { fl_alert("ERROR: ReadFile() failed for %s:\n" "expected %ld bytes, got %ld", filename(), long(buflen), long(count)); free((void*)buf); buf = 0; ret = -1; // fallthru to CloseHandle() } else { // Successfully read changed file buf[count] = '\0'; code[0] = buf; // return pointer to allocated buffer ret = 1; // fallthru to CloseHandle() } } CloseHandle(fh); return ret; } // [Public] Remove the tmp file (if it exists), and zero out filename/mtime/size // Returns: // -1 -- on error (dialog is posted as to why) // 0 -- no file to remove // 1 -- file was removed // int ExternalCodeEditor::remove_tmpfile() { const char *tmpfile = filename(); if ( G_debug ) printf("remove_tmpfile() '%s'\n", tmpfile ? tmpfile : "(empty)"); if ( !tmpfile ) return 0; // Filename set? remove (if exists) and zero filename/mtime/size if ( is_file(tmpfile) ) { if ( G_debug ) printf("Removing tmpfile '%s'\n", tmpfile); utf8_to_wchar(tmpfile, wbuf); if (DeleteFileW(wbuf) == 0) { fl_alert("WARNING: Can't DeleteFile() '%s': %s", tmpfile, get_ms_errmsg()); return -1; } } else { if ( G_debug ) printf("remove_tmpfile(): is_file(%s) failed\n", tmpfile); } set_filename(0); memset(&file_mtime_, 0, sizeof(file_mtime_)); memset(&file_size_, 0, sizeof(file_size_)); return 1; } // [Static/Public] Return tmpdir name for this fluid instance. // Returns pointer to static memory. // const char* ExternalCodeEditor::tmpdir_name() { wchar_t tempdirW[FL_PATH_MAX+1]; char tempdir[FL_PATH_MAX+1]; if (GetTempPathW(FL_PATH_MAX, tempdirW) == 0) { strcpy(tempdir, "c:\\windows\\temp"); // fallback } else { strcpy(tempdir, wchar_to_utf8(tempdirW, abuf)); } static char dirname[100]; _snprintf(dirname, sizeof(dirname), "%s.fluid-%ld", tempdir, (long)GetCurrentProcessId()); if ( G_debug ) printf("tmpdir_name(): '%s'\n", dirname); return dirname; } // [Static/Public] Clear the external editor's tempdir // Static so that the main program can call it on exit to clean up. // void ExternalCodeEditor::tmpdir_clear() { const char *tmpdir = tmpdir_name(); if ( is_dir(tmpdir) ) { if ( G_debug ) printf("Removing tmpdir '%s'\n", tmpdir); utf8_to_wchar(tmpdir, wbuf); if ( RemoveDirectoryW(wbuf) == 0 ) { fl_alert("WARNING: Can't RemoveDirectory() '%s': %s", tmpdir, get_ms_errmsg()); } } } // [Protected] Creates temp dir (if doesn't exist) and returns the dirname // as a static string. Returns NULL on error, dialog shows reason. // const char* ExternalCodeEditor::create_tmpdir() { const char *dirname = tmpdir_name(); if ( ! is_dir(dirname) ) { utf8_to_wchar(dirname, wbuf); if (CreateDirectoryW(wbuf, 0) == 0) { fl_alert("can't create directory '%s': %s", dirname, get_ms_errmsg()); return NULL; } } return dirname; } // [Protected] Returns temp filename in static buffer. // Returns NULL if can't, posts dialog explaining why. // const char* ExternalCodeEditor::tmp_filename() { static char path[512]; const char *tmpdir = create_tmpdir(); if ( !tmpdir ) return 0; const char *ext = g_project.code_file_name.c_str(); // e.g. ".cxx" _snprintf(path, sizeof(path), "%s\\%p%s", tmpdir, (void*)this, ext); path[sizeof(path)-1] = 0; return path; } // [Static/Local] Save string 'code' to 'filename', returning file's mtime/size // 'code' can be NULL -- writes an empty file if so. // Returns: // 0 on success // -1 on error (posts dialog with reason) // static int save_file(const char *filename, const char *code, FILETIME &file_mtime, // return these since in win32 it's.. LARGE_INTEGER &file_size) { // ..efficient to get while file open if ( code == 0 ) code = ""; // NULL? write an empty file memset(&file_mtime, 0, sizeof(file_mtime)); memset(&file_size, 0, sizeof(file_size)); utf8_to_wchar(filename, wbuf); HANDLE fh = CreateFileW(wbuf, // filename GENERIC_WRITE, // write only 0, // sharing -- no share during write NULL, // security CREATE_ALWAYS, // create flags -- recreate FILE_ATTRIBUTE_NORMAL, // misc flags NULL); // templates if ( fh == INVALID_HANDLE_VALUE ) { fl_alert("ERROR: couldn't create file '%s': %s", filename, get_ms_errmsg()); return(-1); } // Write the file, being careful to CloseHandle() even on errs DWORD clen = (DWORD)strlen(code); DWORD count = 0; int ret = 0; if ( WriteFile(fh, code, clen, &count, NULL) == 0 ) { fl_alert("ERROR: WriteFile() '%s': %s", filename, get_ms_errmsg()); ret = -1; // fallthru to CloseHandle() } else if ( count != clen ) { fl_alert("ERROR: WriteFile() '%s': wrote only %lu bytes, expected %lu", filename, (unsigned long)count, (unsigned long)clen); ret = -1; // fallthru to CloseHandle() } // Get mtime/size before closing { FILETIME ftCreate, ftAccess, ftWrite; if ( GetFileSizeEx(fh, &file_size) == 0 ) { fl_alert("ERROR: save_file(%s): GetFileSizeEx() failed: %s\n", filename, get_ms_errmsg()); } if ( GetFileTime(fh, &ftCreate, &ftAccess, &ftWrite) == 0 ) { fl_alert("ERROR: save_file(%s): GetFileTime() failed: %s\n", filename, get_ms_errmsg()); } file_mtime = ftWrite; } // Close, done CloseHandle(fh); return(ret); } // [Protected] Start editor // Returns: // > 0 on success, leaves editor child process running as 'pinfo_' // > -1 on error, posts dialog with reason (child exits) // int ExternalCodeEditor::start_editor(const char *editor_cmd, const char *filename) { if ( G_debug ) printf("start_editor() cmd='%s', filename='%s'\n", editor_cmd, filename); // Startup info STARTUPINFOW sinfo; memset(&sinfo, 0, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); sinfo.dwFlags = 0; sinfo.wShowWindow = 0; // Process info memset(&pinfo_, 0, sizeof(pinfo_)); // Command char cmd[1024]; _snprintf(cmd, sizeof(cmd), "%s %s", editor_cmd, filename); utf8_to_wchar(cmd, wbuf); // Start editor process if (CreateProcessW(NULL, // app name wbuf, // command to exec NULL, // secure attribs NULL, // thread secure attribs FALSE, // handle inheritance 0, // creation flags NULL, // environ block NULL, // current dir &sinfo, // startup info &pinfo_) == 0 ) { // process info fl_alert("CreateProcess() failed to start '%s': %s", cmd, get_ms_errmsg()); return(-1); } if ( L_editors_open++ == 0 ) // first editor? start timers { start_update_timer(); } if ( G_debug ) printf("--- EDITOR STARTED: pid_=%ld #open=%d\n", (long)pinfo_.dwProcessId, L_editors_open); return 0; } // [Protected] Cleanup after editor reaped: // > Remove tmpfile, zeroes mtime/size/filename // > Close process handles // > Zeroes out pinfo_ // > Decrease editor count // void ExternalCodeEditor::reap_cleanup() { remove_tmpfile(); // also zeroes mtime/size/filename CloseHandle(pinfo_.hProcess); // close process handle CloseHandle(pinfo_.hThread); // close thread handle memset(&pinfo_, 0, sizeof(pinfo_)); // clear pinfo_ if ( --L_editors_open <= 0 ) { stop_update_timer(); } } // [Public] Try to reap external editor process // If 'pid_reaped' not NULL, returns PID of reaped editor. // Returns: // -2 -- editor not open // -1 -- WaitForSingleObject() failed (get_ms_errmsg() has reason) // 0 -- process still running // 1 -- process finished + reaped ('pid_reaped' has pid), pinfo_ set to 0. // Handles removing tmpfile/zeroing file_mtime/file_size/filename // // If return value <=0, 'pid_reaped' is set to zero. // int ExternalCodeEditor::reap_editor(DWORD *pid_reaped) { if ( pid_reaped ) *pid_reaped = 0; if ( !is_editing() ) return -2; DWORD msecs_wait = 50; // .05 sec switch ( WaitForSingleObject(pinfo_.hProcess, msecs_wait) ) { case WAIT_TIMEOUT: { // process didn't reap, still running return 0; } case WAIT_OBJECT_0: { // reaped DWORD wpid = pinfo_.dwProcessId; // save pid reap_cleanup(); // clears pinfo_ if ( pid_reaped ) *pid_reaped = wpid; // return pid to caller if ( G_debug ) printf("*** EDITOR REAPED: pid=%ld #open=%d\n", long(wpid), L_editors_open); return 1; } case WAIT_FAILED: { // failed return -1; } } return -1; // any other return unexpected } // [Public] Open external editor using 'editor_cmd' to edit 'code'. // // 'code' contains multiline code to be edited as a temp file. // 'code' can be NULL -- edits an empty file if so. // // Returns: // 0 if succeeds // -1 if can't open editor (already open, etc), // errors were shown to user in a dialog // int ExternalCodeEditor::open_editor(const char *editor_cmd, const char *code) { // Make sure a temp filename exists if ( !filename() ) { set_filename(tmp_filename()); if ( !filename() ) return -1; } // See if tmpfile already exists or editor already open if ( is_file(filename()) ) { if ( is_editing() ) { // See if editor recently closed but not reaped; try to reap DWORD wpid; switch ( reap_editor(&wpid) ) { case -2: // no editor running (unlikely to happen) break; case -1: // wait failed fl_alert("ERROR: WaitForSingleObject() failed: %s\nfile='%s', pid=%ld", get_ms_errmsg(), filename(), long(pinfo_.dwProcessId)); return -1; case 0: // process still running fl_alert("Editor Already Open\n file='%s'\n pid=%ld", filename(), long(pinfo_.dwProcessId)); return 0; case 1: // process reaped, wpid is pid reaped if ( G_debug ) printf("*** REAPED EXTERNAL EDITOR: PID %ld\n", long(wpid)); break; // fall thru to open new editor instance } // Reinstate tmp filename (reap_editor() clears it) set_filename(tmp_filename()); } } // Save code to tmpfile, getting mtime/size if ( save_file(filename(), code, file_mtime_, file_size_) < 0 ) { return -1; // errors were shown in dialog } if ( start_editor(editor_cmd, filename()) < 0 ) { // open file in external editor if ( G_debug ) printf("Editor failed to start\n"); return -1; // errors were shown in dialog } // New editor opened -- start update timer (if not already) if ( L_update_timer_cb && !Fl::has_timeout(L_update_timer_cb) ) { if ( G_debug ) printf("--- Editor opened: STARTING UPDATE TIMER\n"); Fl::add_timeout(2.0, L_update_timer_cb); } return 0; } // [Public/Static] Start update timer void ExternalCodeEditor::start_update_timer() { if ( !L_update_timer_cb ) return; if ( G_debug ) printf("--- TIMER: STARTING UPDATES\n"); Fl::add_timeout(2.0, L_update_timer_cb); } // [Public/Static] Stop update timer void ExternalCodeEditor::stop_update_timer() { if ( !L_update_timer_cb ) return; if ( G_debug ) printf("--- TIMER: STOPPING UPDATES\n"); Fl::remove_timeout(L_update_timer_cb); } // [Public/Static] Set app's external editor update timer callback // This is the app's callback callback we start while editors are open, // and stop when all editors are closed. // void ExternalCodeEditor::set_update_timer_callback(Fl_Timeout_Handler cb) { L_update_timer_cb = cb; } // [Static/Public] See if any external editors are open. // App's timer cb can see if any editors need checking.. // int ExternalCodeEditor::editors_open() { return L_editors_open; } fltk-1.4.3/fluid/align_widget.h0000644000175000017500000000117215004135251016517 0ustar albrechtalbrecht// // FLUID main entry for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_ALIGN_WIDGET_H #define _FLUID_ALIGN_WIDGET_H class Fl_Widget; void align_widget_cb(Fl_Widget *, long); #endif // _FLUID_ALIGN_WIDGET_H fltk-1.4.3/fluid/fluid_filename.h0000644000175000017500000000367115004135251017033 0ustar albrechtalbrecht/* * Filename header file for the Fast Light Tool Kit (FLTK). * * Copyright 1998-2023 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /** \file fluid/fluid_filename.h \brief File names and URI utility functions for FLUID only. This file declares all fl_filename* functions using Fl_String and also includes the main header file . \note This file contains some filename functions using Fl_String which which are used in FLTK 1.4.x but will be removed in the next minor or major release after 1.4.x (i.e. 1.5 or maybe 4.0). \note This entire file should become obsolete in 1.5 or higher, whatever the next release after 1.4.x will be. We'll use std::string instead! */ #ifndef FLUID_FILENAME_H # define FLUID_FILENAME_H #include #include #include # if defined(__cplusplus) class Fl_String; Fl_String fl_filename_shortened(const Fl_String &filename, int maxchars); Fl_String fl_filename_name(const Fl_String &filename); Fl_String fl_filename_path(const Fl_String &filename); Fl_String fl_filename_ext(const Fl_String &filename); Fl_String fl_filename_setext(const Fl_String &filename, const Fl_String &new_extension); Fl_String fl_filename_expand(const Fl_String &from); Fl_String fl_filename_absolute(const Fl_String &from); Fl_String fl_filename_absolute(const Fl_String &from, const Fl_String &base); Fl_String fl_filename_relative(const Fl_String &from); Fl_String fl_filename_relative(const Fl_String &from, const Fl_String &base); Fl_String fl_getcwd(); # endif /** @} */ #endif /* FLUID_FILENAME_H */ fltk-1.4.3/fluid/Fl_Type.h0000644000175000017500000003001215004135251015417 0ustar albrechtalbrecht// // Widget type header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_FL_TYPE_H #define _FLUID_FL_TYPE_H #include #include #include "code.h" class Fl_Type; class Fl_Group_Type; class Fl_Window_Type; class Fd_Project_Reader; class Fd_Project_Writer; /** Declare where a new type is placed and how to create it. Placement can be as the first or last child of the anchor, or right after the anchor. In most cases, the anchor is the last selected type node. If the source is FROM_USER, widgets may be created with default titles and labels. Type created FROM_FILE will start with no label, so the label is set correctly later. \see Fl_Type *Fl_..._Type::make(Strategy strategy) calls `add()` Add single Type: Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy, bool and_open) Fl_Type *add_new_widget_from_user(const char *inName, Strategy strategy, bool and_open) Fl_Type *add_new_widget_from_file(const char *inName, Strategy strategy) Add a hierarchy of Types void Fl_Type::add(Fl_Type *p, Strategy strategy) int read_file(const char *filename, int merge, Strategy strategy) Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options) int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy strategy) */ typedef struct Strategy { enum Flags { AS_FIRST_CHILD = 0x0000, AS_LAST_CHILD = 0x0001, AFTER_CURRENT = 0x0002, PLACEMENT_MASK = 0x000f, FROM_USER = 0x0000, FROM_FILE = 0x0010, SOURCE_MASK = 0x00f0, FROM_FILE_AS_FIRST_CHILD = 0x0010, FROM_FILE_AS_LAST_CHILD = 0x0011, FROM_FILE_AFTER_CURRENT = 0x0012, }; Flags flags; Strategy(Flags f) { flags = f; } void placement(Flags f) { flags = (Flags)((flags & ~PLACEMENT_MASK) | (f & PLACEMENT_MASK)); } Flags placement() { return (Flags)(flags & PLACEMENT_MASK); } void source(Flags f) { flags = (Flags)((flags & ~SOURCE_MASK) | (f & SOURCE_MASK)); } Flags source() { return (Flags)(flags & SOURCE_MASK); } } Strategy; enum ID { // administrative ID_Base_, ID_Widget_, ID_Menu_Manager_, ID_Menu_, ID_Browser_, ID_Valuator_, // non-widget ID_Function, ID_Code, ID_CodeBlock, ID_Decl, ID_DeclBlock, ID_Class, ID_Widget_Class, ID_Comment, ID_Data, // groups ID_Window, ID_Group, ID_Pack, ID_Flex, ID_Tabs, ID_Scroll, ID_Tile, ID_Wizard, ID_Grid, // buttons ID_Button, ID_Return_Button, ID_Light_Button, ID_Check_Button, ID_Repeat_Button, ID_Round_Button, // valuators ID_Slider, ID_Scrollbar, ID_Value_Slider, ID_Adjuster, ID_Counter, ID_Spinner, ID_Dial, ID_Roller, ID_Value_Input, ID_Value_Output, // text ID_Input, ID_Output, ID_Text_Editor, ID_Text_Display, ID_File_Input, ID_Terminal, // menus ID_Menu_Bar, ID_Menu_Button, ID_Choice, ID_Input_Choice, ID_Submenu, ID_Menu_Item, ID_Checkbox_Menu_Item, ID_Radio_Menu_Item, // browsers ID_Browser, ID_Check_Browser, ID_File_Browser, ID_Tree, ID_Help_View, ID_Table, // misc ID_Box, ID_Clock, ID_Progress, ID_Max_ }; void update_visibility_flag(Fl_Type *p); void delete_all(int selected_only=0); int storestring(const char *n, const char * & p, int nostrip=0); void select_all_cb(Fl_Widget *,void *); void select_none_cb(Fl_Widget *,void *); void earlier_cb(Fl_Widget*,void*); void later_cb(Fl_Widget*,void*); #ifndef NDEBUG void print_project_tree(); bool validate_project_tree(); bool validate_independent_branch(class Fl_Type *root); bool validate_branch(class Fl_Type *root); #endif /** \brief This is the base class for all elements in the project tree. All widgets and other types in the project are derived from Fl_Types. They are organized in a doubly linked list. Every Type also has depth information to create a pseudo tree structure. To make walking up the tree faster, Type also holds a pointer to the `parent` Type. Types can be identified using the builtin ID system that works like RTTI. The method `id()` returns the exact type, and the method `is_a(ID)` returns true if this is the exact type or derived from the type, and a dynamic cast will work reliably. \todo it would be nice if we can handle multiple independent trees. To do that we must remove static members like `first` and `last`. \todo add virtual methods to handle events, draw widgets, and draw overlays. It may also make sense to have a virtual method that returns a boolean if a specific type can be added as a child. \todo it may make sense to have a readable iterator class instead of relying on pointer manipulation. Or use std in future releases. */ class Fl_Type { /** Copy the label text to Widgets and Windows, does nothing in Type. */ virtual void setlabel(const char *) { } // virtual part of label(char*) protected: Fl_Type(); /** Name of a widget, or code some non-widget Types. */ const char *name_; /** Label text of a widget. */ const char *label_; /** If it is just a word, it's the name of the callback function. Otherwise it is the full callback C++ code. Can be NULL. */ const char *callback_; /** Widget user data field as C++ text. */ const char *user_data_; /** Widget user data type as C++ text, usually `void*` or `long`. */ const char *user_data_type_; /** Optional comment for every node in the graph. Visible in browser and panels, and will also be copied to the source code. */ const char *comment_; /** a unique ID within the project */ unsigned short uid_; public: // things that should not be public: /** Quick link to the parent Type instead of walking up the linked list. */ Fl_Type *parent; /** This type is rendered "selected" in the tree browser. */ char new_selected; // browser highlight /** Backup storage for selection if an error occurred during some operation (see `haderror`). It seems that this is often confused with new_selected which seems to hold the true and visible selection state. */ char selected; // copied here by selection_changed() char folded_; // if set, children are not shown in browser char visible; // true if all parents are open int level; // number of parents over this static Fl_Type *first, *last; Fl_Type *next, *prev; Fl_Type *prev_sibling(); Fl_Type *next_sibling(); Fl_Type *first_child(); Fl_Type *factory; const char *callback_name(Fd_Code_Writer& f); // text positions of this type in code, header, and project file (see codeview) int code_static_start, code_static_end; int code1_start, code1_end; int code2_start, code2_end; int header1_start, header1_end; int header2_start, header2_end; int header_static_start, header_static_end; int proj1_start, proj1_end; int proj2_start, proj2_end; protected: int user_defined(const char* cbname) const; public: virtual ~Fl_Type(); virtual Fl_Type *make(Strategy strategy) = 0; Fl_Window_Type *window(); Fl_Group_Type *group(); void add(Fl_Type *parent, Strategy strategy); void insert(Fl_Type *n); // insert into list before n Fl_Type* remove(); // remove from list void move_before(Fl_Type*); // move before a sibling virtual const char *title(); // string for browser virtual const char *type_name() = 0; // type for code output virtual const char *alt_type_name() { return type_name(); } // alternate type for FLTK2 code output const char *name() const {return name_;} void name(const char *); const char *label() const {return label_;} void label(const char *); const char *callback() const {return callback_;} void callback(const char *); const char *user_data() const {return user_data_;} void user_data(const char *); const char *user_data_type() const {return user_data_type_;} void user_data_type(const char *); const char *comment() { return comment_; } void comment(const char *); virtual Fl_Type* click_test(int,int) { return NULL; } virtual void add_child(Fl_Type*, Fl_Type* beforethis) { } virtual void move_child(Fl_Type*, Fl_Type* beforethis) { } virtual void remove_child(Fl_Type*) { } /** Give widgets a chance to arrange their children after all children were added. If adding individual children, this is called immediately, but if children are read via a project file, we wait until all children are read and then lay out the group. */ virtual void layout_widget() { } static Fl_Type *current; // most recently picked object static Fl_Type *current_dnd; virtual void open(); // what happens when you double-click // read and write data to a saved file: virtual void write(Fd_Project_Writer &f); virtual void write_properties(Fd_Project_Writer &f); virtual void read_property(Fd_Project_Reader &f, const char *); virtual void write_parent_properties(Fd_Project_Writer &f, Fl_Type *child, bool encapsulate); virtual void read_parent_property(Fd_Project_Reader &f, Fl_Type *child, const char *property); virtual int read_fdesign(const char*, const char*); virtual void postprocess_read() { } // write code, these are called in order: virtual void write_static(Fd_Code_Writer& f); // write static stuff to .c file virtual void write_static_after(Fd_Code_Writer& f); // write static stuff after children virtual void write_code1(Fd_Code_Writer& f); // code and .h before children virtual void write_code2(Fd_Code_Writer& f); // code and .h after children void write_comment_h(Fd_Code_Writer& f, const char *ind=""); // write the commentary text into the header file void write_comment_c(Fd_Code_Writer& f, const char *ind=""); // write the commentary text into the source file void write_comment_inline_c(Fd_Code_Writer& f, const char *ind=0L); // write the commentary text // live mode virtual Fl_Widget *enter_live_mode(int top=0); // build widgets needed for live mode virtual void leave_live_mode(); // free allocated resources virtual void copy_properties(); // copy properties from this type into a potential live object virtual void copy_properties_for_children() { } // copy remaining properties after children were added // get message number for I18N int msgnum(); /** Return 1 if the Type can have children. */ virtual int can_have_children() const {return 0;} /** Return 1 if the type is a widget or menu item. */ virtual int is_widget() const {return 0;} /** Return 1 if the type is a widget but not a menu item. */ virtual int is_true_widget() const {return 0;} /** Return 1 if a type behaves like a button (Fl_Button and Fl_Menu_Item and derived, but not Fl_Submenu_Type. */ virtual int is_button() const {return 0;} /** Return 1 if this is a Fl_Widget_Class_Type, Fl_CodeBlock_Type, or Fl_Function_Type */ virtual int is_code_block() const {return 0;} /** Return 1 if this is a Fl_Widget_Class_Type, Fl_Class_Type, or Fl_DeclBlock_Type */ virtual int is_decl_block() const {return 0;} /** Return 1 if this is a Fl_Class_Type or Fl_Widget_Class_Type. */ virtual int is_class() const {return 0;} /** Return 1 if the type browser shall draw a padlock over the icon. */ virtual int is_public() const {return 1;} /** Return the type ID for this Type. */ virtual ID id() const { return ID_Base_; } /** Check if this Type is of the give type ID or derived from that type ID. */ virtual bool is_a(ID inID) const { return (inID==ID_Base_); } const char* class_name(const int need_nest) const; bool is_in_class() const; int has_function(const char*, const char*) const; unsigned short set_uid(unsigned short suggested_uid=0); unsigned short get_uid() { return uid_; } static Fl_Type *find_by_uid(unsigned short uid); static Fl_Type *find_in_text(int text_type, int crsr); /// If this is greater zero, widgets will be allowed to lay out their children. static int allow_layout; }; #endif // _FLUID_FL_TYPE_H fltk-1.4.3/fluid/widget_browser.cxx0000644000175000017500000005053615004135251017473 0ustar albrechtalbrecht// // Widget Browser code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "widget_browser.h" #include "fluid.h" #include "Fl_Widget_Type.h" #include "pixmaps.h" #include #include #include /** \class Widget_Browser A widget that displays the nodes in the widget tree. The Widget Browser is derived from the FLTK basic browser, extending tree browsing functionality by using the \c depth component of the double linked list of \c Fl_Type items. \see Fl_Type */ // ---- global variables /// Global access to the widget browser. Widget_Browser *widget_browser = NULL; // ---- static variables Fl_Color Widget_Browser::label_color = 72; Fl_Font Widget_Browser::label_font = FL_HELVETICA; Fl_Color Widget_Browser::class_color = FL_FOREGROUND_COLOR; Fl_Font Widget_Browser::class_font = FL_HELVETICA_BOLD; Fl_Color Widget_Browser::func_color = FL_FOREGROUND_COLOR; Fl_Font Widget_Browser::func_font = FL_HELVETICA; Fl_Color Widget_Browser::name_color = FL_FOREGROUND_COLOR; Fl_Font Widget_Browser::name_font = FL_HELVETICA; Fl_Color Widget_Browser::code_color = FL_FOREGROUND_COLOR; Fl_Font Widget_Browser::code_font = FL_HELVETICA; Fl_Color Widget_Browser::comment_color = FL_DARK_GREEN; Fl_Font Widget_Browser::comment_font = FL_HELVETICA; // ---- global functions /** Shortcut to have the widget browser graphics refreshed soon. */ void redraw_browser() { widget_browser->redraw(); } /** Shortcut to create the widget browser. */ Fl_Widget *make_widget_browser(int x,int y,int w,int h) { return (widget_browser = new Widget_Browser(x,y,w,h)); } /** Make sure that the caller is visible in the widget browser. \param[in] caller scroll the browser in y so that caller is visible (may be NULL) */ void redraw_widget_browser(Fl_Type *caller) { if (caller) widget_browser->display(caller); widget_browser->redraw(); } /** Select or deselect a node in the widget browser. \param[in] o (de)select this node \param[in] v the new selection state (1=select, 0=de-select) */ void select(Fl_Type *o, int v) { widget_browser->select(o,v,1); } /** Select a single node in the widget browser, deselect all others. \param[in] o select this node */ void select_only(Fl_Type *o) { widget_browser->select_only(o,1); } /** Deselect all nodes in the widget browser. */ void deselect() { widget_browser->deselect(); } /** Show the selected item in the browser window. Make sure that the given item is visible in the browser by opening all parent groups and moving the item into the visible space. \param[in] t show this item */ void reveal_in_browser(Fl_Type *t) { Fl_Type *p = t->parent; if (p) { for (;;) { if (p->folded_) p->folded_ = 0; if (!p->parent) break; p = p->parent; } update_visibility_flag(p); } widget_browser->display(t); widget_browser->redraw(); } // ---- local functions /** Copy the given string str to buffer p with no more than maxl characters. Add "..." if string was truncated. Quote characters are NOT counted. \param[out] p return the resulting string in this buffer, terminated with a NUL byte \param[in] str copy this string; utf8 aware \param[in] maxl maximum number of letters to copy until we print the ellipsis (...) \param[in] quote if set, the resulting string is embedded in double quotes \param[in] trunc_lf if set, truncates at first newline \returns pointer to end of string (before terminating null byte). \note the buffer p must be large enough to hold (4 * (maxl+1) + 1) bytes or (4 * (maxl+1) + 3) bytes if quoted, e.g. "123..." because each UTF-8 character can consist of 4 bytes, "..." adds 3 bytes, quotes '""' add two bytes, and the terminating null byte adds another byte. This supports Unicode code points up to U+10FFFF (standard as of 10/2016). Sanity checks for illegal UTF-8 sequences are included. */ static char *copy_trunc(char *p, const char *str, int maxl, int quote, int trunc_lf) { int size = 0; // truncated string size in characters int bs; // size of UTF-8 character in bytes if (!p) return NULL; // bad buffer if (!str) { // no input string if (quote) { *p++='"'; *p++='"'; } *p = 0; return p; } const char *end = str + strlen(str); // end of input string if (quote) *p++ = '"'; // opening quote while (size < maxl) { // maximum characters if (*str == '\n') { if (trunc_lf) { // handle trunc at \n if (quote) *p++ = '"'; // closing quote *p = 0; return p; } *p++ = '\\'; *p++ = 'n'; str++; size+=2; continue; } if (!(*str & (-32))) break; // end of string (0 or control char) bs = fl_utf8len(*str); // size of next character if (bs <= 0) break; // some error - leave if (str + bs > end) break; // UTF-8 sequence beyond end of string while (bs--) *p++ = *str++; // copy that character into the buffer size++; // count copied characters } if (*str && *str!='\n') { // string was truncated strcpy(p,"..."); p += 3; } if (quote) *p++ = '"'; // closing quote *p = 0; // terminating null byte return p; } // ---- Widget_Browser implementation /** Create a new instance of the Widget_Browser widget. Fluid currently generates only one instance of this browser. If we want to use multiple browser at some point, we need to refactor a few global variables, i.e. Fl_Type::first and Fl_Type::last . \param[in] X, Y, W, H position and size of widget \param[in] l optional label \todo It would be nice to be able to grab one or more nodes and move them within the hierarchy. */ Widget_Browser::Widget_Browser(int X,int Y,int W,int H,const char*l) : Fl_Browser_(X,Y,W,H,l), pushedtitle(NULL), saved_h_scroll_(0), saved_v_scroll_(0) { type(FL_MULTI_BROWSER); Fl_Widget::callback(callback_stub); when(FL_WHEN_RELEASE); } /** Override the method to find the first item in the list of elements. \return the first item */ void *Widget_Browser::item_first() const { return Fl_Type::first; } /** Override the method to find the next item in the list of elements. \param l this item \return the next item, irregardless of tree depth, or NULL at the end */ void *Widget_Browser::item_next(void *l) const { return ((Fl_Type*)l)->next; } /** Override the method to find the previous item in the list of elements. \param l this item \return the previous item, irregardless of tree depth, or NULL at the start */ void *Widget_Browser::item_prev(void *l) const { return ((Fl_Type*)l)->prev; } /** Override the method to check if an item was selected. \param l this item \return 1 if selected, 0 if not \todo what is the difference between selected and new_selected, and why do we do this? */ int Widget_Browser::item_selected(void *l) const { return ((Fl_Type*)l)->new_selected; } /** Override the method to mark an item selected. \param l this item \param[in] v 1 if selecting, 0 if not */ void Widget_Browser::item_select(void *l,int v) { ((Fl_Type*)l)->new_selected = v; } /** Override the method to return the height of an item representation in Flixels. \param l this item \return height in FLTK units (used to be pixels before high res screens) */ int Widget_Browser::item_height(void *l) const { Fl_Type *t = (Fl_Type*)l; if (t->visible) { if (show_comments && t->comment()) return textsize()*2+4; else return textsize()+5; } return 0; } /** Override the method to return the estimated height of all items. \return height in FLTK units */ int Widget_Browser::incr_height() const { return textsize() + 5 + linespacing(); } /** Draw an item in the widget browser. A browser line starts with a variable size space. This space directly relates to the level of the type entry. If this type has the ability to store children, a triangle follows, pointing right (closed) or pointing down (open, children shown). Next follows an icon that is specific to the type. This makes it easy to spot certain types. Now follows some text. For classes and widgets, this is the type itself, followed by the name of the object. Other objects show their content as text, possibly abbreviated with an ellipsis. \param v v is a pointer to the actual widget type and can be cast safely to Fl_Type \param X,Y these give the position in window coordinates of the top left corner of this line */ void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const { // cast to a more general type Fl_Type *l = (Fl_Type *)v; char buf[500]; // edit buffer: large enough to hold 80 UTF-8 chars + nul // calculate the horizontal start position of this item // 3 is the edge of the browser // 13 is the width of the arrow that indicates children for the item // 18 is the width of the icon // 12 is the indent per level X += 3 + 13 + 18 + l->level * 12; // calculate the horizontal start position and width of the separator line int x1 = X; int w1 = w() - x1; // items can contain a comment. If they do, the comment gets a second text // line inside this browser line int comment_incr = 0; if (show_comments && l->comment()) { // -- comment copy_trunc(buf, l->comment(), 80, 0, 1); comment_incr = textsize()-1; if (l->new_selected) fl_color(fl_contrast(comment_color, FL_SELECTION_COLOR)); else fl_color(comment_color); fl_font(comment_font, textsize()-2); fl_draw(buf, X, Y+12); Y += comment_incr/2; comment_incr -= comment_incr/2; } if (l->new_selected) fl_color(fl_contrast(FL_FOREGROUND_COLOR,FL_SELECTION_COLOR)); else fl_color(FL_FOREGROUND_COLOR); // Width=10: Draw the triangle that indicates possible children if (l->can_have_children()) { X = X - 18 - 13; if (!l->next || l->next->level <= l->level) { if (l->folded_==(l==pushedtitle)) { // an outlined triangle to the right indicates closed item, no children fl_loop(X,Y+7,X+5,Y+12,X+10,Y+7); } else { // an outlined triangle to the bottom indicates open item, no children fl_loop(X+2,Y+2,X+7,Y+7,X+2,Y+12); } } else { if (l->folded_==(l==pushedtitle)) { // a filled triangle to the right indicates closed item, with children fl_polygon(X,Y+7,X+5,Y+12,X+10,Y+7); } else { // a filled triangle to the bottom indicates open item, with children fl_polygon(X+2,Y+2,X+7,Y+7,X+2,Y+12); } } X = X + 13 + 18; } // Width=18: Draw the icon associated with the type. Fl_Pixmap *pm = pixmap[l->id()]; if (pm) pm->draw(X-18, Y); // Add tags on top of the icon for locked and protected types. switch (l->is_public()) { case 0: lock_pixmap->draw(X - 17, Y); break; case 2: protected_pixmap->draw(X - 17, Y); break; } if ( l->is_widget() && !l->is_a(ID_Window) && ((Fl_Widget_Type*)l)->o && !((Fl_Widget_Type*)l)->o->visible() && (!l->parent || ( !l->parent->is_a(ID_Tabs) && !l->parent->is_a(ID_Wizard) ) ) ) { invisible_pixmap->draw(X - 17, Y); } // Indent=12 per level: Now write the text that comes after the graphics representation Y += comment_incr; if (l->is_widget() || l->is_class()) { const char* c = subclassname(l); if (!strncmp(c,"Fl_",3)) c += 3; // -- class fl_font(class_font, textsize()); if (l->new_selected) fl_color(fl_contrast(class_color, FL_SELECTION_COLOR)); else fl_color(class_color); fl_draw(c, X, Y+13); X += int(fl_width(c)+fl_width('n')); c = l->name(); if (c) { // -- name fl_font(name_font, textsize()); if (l->new_selected) fl_color(fl_contrast(name_color, FL_SELECTION_COLOR)); else fl_color(name_color); fl_draw(c, X, Y+13); } else if ((c = l->label())) { // -- label fl_font(label_font, textsize()); if (l->new_selected) fl_color(fl_contrast(label_color, FL_SELECTION_COLOR)); else fl_color(label_color); copy_trunc(buf, c, 32, 1, 0); // quoted string fl_draw(buf, X, Y+13); } } else { if (l->is_code_block() && (l->level==0 || l->parent->is_class())) { // -- function names fl_font(func_font, textsize()); if (l->new_selected) fl_color(fl_contrast(func_color, FL_SELECTION_COLOR)); else fl_color(func_color); copy_trunc(buf, l->title(), 55, 0, 0); } else { if (l->is_a(ID_Comment)) { // -- comment (in main line, not above entry) fl_font(comment_font, textsize()); if (l->new_selected) fl_color(fl_contrast(comment_color, FL_SELECTION_COLOR)); else fl_color(comment_color); copy_trunc(buf, l->title(), 55, 0, 0); } else { // -- code fl_font(code_font, textsize()); if (l->new_selected) fl_color(fl_contrast(code_color, FL_SELECTION_COLOR)); else fl_color(code_color); copy_trunc(buf, l->title(), 55, 0, 1); } } fl_draw(buf, X, Y+13); } // draw a thin line below the item if this item is not selected // (if it is selected this additional line would look bad) if (!l->new_selected) { fl_color(fl_lighter(FL_GRAY)); fl_line(x1,Y+16,x1+w1,Y+16); } } /** Override the method to return the width of an item representation in Flixels. \param v this item \return width in FLTK units */ int Widget_Browser::item_width(void *v) const { char buf[500]; // edit buffer: large enough to hold 80 UTF-8 chars + nul Fl_Type *l = (Fl_Type *)v; if (!l->visible) return 0; int W = 3 + 13 + 18 + l->level * 12; if (l->is_widget() || l->is_class()) { const char* c = l->type_name(); if (!strncmp(c,"Fl_",3)) c += 3; fl_font(textfont(), textsize()); W += int(fl_width(c) + fl_width('n')); c = l->name(); if (c) { fl_font(textfont()|FL_BOLD, textsize()); W += int(fl_width(c)); } else if (l->label()) { copy_trunc(buf, l->label(), 32, 1, 0); // quoted string W += int(fl_width(buf)); } } else { copy_trunc(buf, l->title(), 55, 0, 0); fl_font(textfont() | (l->is_code_block() && (l->level==0 || l->parent->is_class())?0:FL_BOLD), textsize()); W += int(fl_width(buf)); } return W; } /** Callback to tell the Fluid UI when the list of selected items changed. */ void Widget_Browser::callback() { selection_changed((Fl_Type*)selection()); } /** Override the event handling for this browser. The vertical mouse position corresponds to an entry in the type tree. The horizontal position has the following hot zones: - 0-3 is the widget frame and ignored - the next hot zone starts 12*indent pixels further to the right - the next 13 pixels refer to the arrow that indicates children for the item - 18 pixels follow for the icon - the remaining part is filled with text \param[in] e the incoming event type \return 0 if the event is not supported, and 1 if the event was "used up" */ int Widget_Browser::handle(int e) { static Fl_Type *title; Fl_Type *l; int X,Y,W,H; bbox(X,Y,W,H); switch (e) { case FL_PUSH: if (!Fl::event_inside(X,Y,W,H)) break; l = (Fl_Type*)find_item(Fl::event_y()); if (l) { X += 3 + 12*l->level - hposition(); if (l->can_have_children() && Fl::event_x()>X && Fl::event_x()level - hposition(); if (l->can_have_children() && Fl::event_x()>X && Fl::event_x()new_selected && (Fl::event_clicks() || Fl::event_state(FL_CTRL))) l->open(); break; } l = pushedtitle; title = pushedtitle = 0; if (l) { if (!l->folded_) { l->folded_ = 1; for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next) k->visible = 0; } else { l->folded_ = 0; for (Fl_Type*k=l->next; k&&k->level>l->level;) { k->visible = 1; if (k->can_have_children() && k->folded_) { Fl_Type *j; for (j = k->next; j && j->level>k->level; j = j->next) {/*empty*/} k = j; } else k = k->next; } } redraw(); } return 1; } return Fl_Browser_::handle(e); } /** Save the current scrollbar position during rebuild. */ void Widget_Browser::save_scroll_position() { saved_h_scroll_ = hposition(); saved_v_scroll_ = vposition(); } /** Restore the previous scrollbar position after rebuild. */ void Widget_Browser::restore_scroll_position() { hposition(saved_h_scroll_); vposition(saved_v_scroll_); } /** Rebuild the browser layout to reflect multiple changes. This clears internal caches, recalculates the scroll bar sizes, and sends a redraw() request to the widget. */ void Widget_Browser::rebuild() { save_scroll_position(); new_list(); damage(FL_DAMAGE_SCROLL); redraw(); restore_scroll_position(); } /** Rebuild the browser layout and make sure that the given item is visible. \param[in] inNode pointer to a widget node derived from Fl_Type. */ void Widget_Browser::display(Fl_Type *inNode) { if (!inNode) { // Alternative: find the first (last?) visible selected item. return; } // remeber our current scroll position int currentV = vposition(), newV = currentV; int nodeV = 0; // find the inNode in the tree and check, if it is already visible Fl_Type *p=Fl_Type::first; for ( ; p && p!=inNode; p=p->next) { if (p->visible) nodeV += item_height(p) + linespacing(); } if (p) { int xx, yy, ww, hh; bbox(xx, yy, ww, hh); int frame_top = xx-x(); int frame_bottom = frame_top + hh; int node_height = item_height(inNode) + linespacing(); int margin_height = 2 * (item_quick_height(inNode) + linespacing()); if (margin_height>hh/2) margin_height = hh/2; // is the inNode above the current scroll position? if (nodeVcurrentV+frame_bottom-margin_height-node_height) newV = nodeV - frame_bottom + margin_height + node_height; if (newV<0) newV = 0; } if (newV!=currentV) vposition(newV); } void Widget_Browser::load_prefs() { int c; Fl_Preferences p(fluid_prefs, "widget_browser"); p.get("label_color", c, 72); label_color = c; p.get("label_font", c, FL_HELVETICA); label_font = c; p.get("class_color", c, FL_FOREGROUND_COLOR); class_color = c; p.get("class_font", c, FL_HELVETICA_BOLD); class_font = c; p.get("func_color", c, FL_FOREGROUND_COLOR); func_color = c; p.get("func_font", c, FL_HELVETICA); func_font = c; p.get("name_color", c, FL_FOREGROUND_COLOR); name_color = c; p.get("name_font", c, FL_HELVETICA); name_font = c; p.get("code_color", c, FL_FOREGROUND_COLOR); code_color = c; p.get("code_font", c, FL_HELVETICA); code_font = c; p.get("comment_color",c, FL_DARK_GREEN); comment_color = c; p.get("comment_font", c, FL_HELVETICA); comment_font = c; } void Widget_Browser::save_prefs() { Fl_Preferences p(fluid_prefs, "widget_browser"); p.set("label_color", (int)label_color); p.set("label_font", (int)label_font); p.set("class_color", (int)class_color); p.set("class_font", (int)class_font); p.set("func_color", (int)func_color); p.set("func_font", (int)func_font); p.set("name_color", (int)name_color); p.set("name_font", (int)name_font); p.set("code_color", (int)code_color); p.set("code_font", (int)code_font); p.set("comment_color", (int)comment_color); p.set("comment_font", (int)comment_font); } fltk-1.4.3/fluid/file.h0000644000175000017500000000521515004135251015003 0ustar albrechtalbrecht// // Fluid file routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_FILE_H #define _FLUID_FILE_H #include "Fl_Type.h" #include class Fl_Type; extern int fdesign_flip; int read_file(const char *, int merge, Strategy strategy=Strategy::FROM_FILE_AS_LAST_CHILD); int write_file(const char *, int selected_only = 0, bool to_codeview = false); class Fd_Project_Reader { protected: /// Project input file FILE *fin; /// Number of most recently read line int lineno; /// Pointer to the file path and name (not copied!) const char *fname; /// Expanding buffer to store the most recently read word char *buffer; /// Exact size of the expanding buffer in bytes int buflen; void expand_buffer(int length); int nextchar() { for (;;) { int ret = fgetc(fin); if (ret!='\r') return ret; } } public: /// Holds the file version number after reading the "version" tag double read_version; public: Fd_Project_Reader(); ~Fd_Project_Reader(); int open_read(const char *s); int close_read(); const char *filename_name(); int read_quoted(); Fl_Type *read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options=0); int read_project(const char *, int merge, Strategy strategy=Strategy::FROM_FILE_AS_LAST_CHILD); void read_error(const char *format, ...); const char *read_word(int wantbrace = 0); int read_int(); int read_fdesign_line(const char*& name, const char*& value); void read_fdesign(); }; class Fd_Project_Writer { protected: // Project output file, always opened in "wb" mode FILE *fout; /// If set, one space is written before text unless the format starts with a newline character int needspace; /// Set if this file will be used in the codeview dialog bool write_codeview_; public: Fd_Project_Writer(); ~Fd_Project_Writer(); int open_write(const char *s); int close_write(); int write_project(const char *filename, int selected_only, bool codeview); void write_word(const char *); void write_string(const char *,...) __fl_attr((__format__ (__printf__, 2, 3))); void write_indent(int n); void write_open(); void write_close(int n); FILE *file() const { return fout; } bool write_codeview() const { return write_codeview_; } }; #endif // _FLUID_FILE_H fltk-1.4.3/fluid/fluid-shared.plist0000644000175000017500000000275015004135251017340 0ustar albrechtalbrecht CFBundleInfoDictionaryVersion 6.0 CFBundleExecutable fluid-shared CFBundleIdentifier org.fltk.fluid CFBundleVersion 1.5.0 CFBundleDevelopmentRegion English NSHumanReadableCopyright Copyright 1998-2025 by Bill Spitzak and others CFAppleHelpAnchor help CFBundleName Fluid CFBundlePackageType APPL CFBundleSignature FLID CFBundleIconFile fluid.icns CFBundleShortVersionString 1.5.0 CFBundleGetInfoString 1.5.0, Copyright 1998-2025 by Bill Spitzak and others CFBundleDocumentTypes CFBundleTypeExtensions fl CFBundleTypeIconFile fluid.icns CFBundleTypeName FLUID Designer File CFBundleTypeOSTypes Flid CFBundleTypeRole Editor NSHighResolutionCapable fltk-1.4.3/fluid/Fl_Group_Type.cxx0000644000175000017500000006065215004135251017163 0ustar albrechtalbrecht// // Fl_Group object code for the Fast Light Tool Kit (FLTK). // // Object describing an Fl_Group and links to Fl_Window_Type.C and // the Fl_Tabs widget, with special stuff to select tab items and // insure that only one is visible. // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Group_Type.h" #include "fluid.h" #include "file.h" #include "code.h" #include "widget_browser.h" #include "undo.h" #include "Fd_Snap_Action.h" #include #include #include #include #include #include #include "../src/flstring.h" #include #include // ---- Fl_Group_Type -------------------------------------------------- MARK: - Fl_Group_Type Fl_Group_type; // the "factory" /** Override group's resize behavior to do nothing to children by default. \param[in] X, Y, W, H new size */ void Fl_Group_Proxy::resize(int X, int Y, int W, int H) { if (Fl_Type::allow_layout > 0) { Fl_Group::resize(X, Y, W, H); } else { Fl_Widget::resize(X, Y, W, H); } redraw(); } /** Override draw() to make groups with no box or flat box background visible. */ void Fl_Group_Proxy::draw() { if (show_ghosted_outline && (box() == FL_NO_BOX)) { fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f))); } Fl_Group::draw(); } /** \brief Enlarge the group size, so all children fit within. */ void fix_group_size(Fl_Type *tt) { if (!tt || !tt->is_a(ID_Group)) return; Fl_Group_Type* t = (Fl_Group_Type*)tt; int X = t->o->x(); int Y = t->o->y(); int R = X+t->o->w(); int B = Y+t->o->h(); for (Fl_Type *nn = t->next; nn && nn->level > t->level; nn = nn->next) { if (nn->is_true_widget()) { Fl_Widget_Type* n = (Fl_Widget_Type*)nn; int x = n->o->x(); if (x < X) X = x; int y = n->o->y(); if (y < Y) Y = y; int r = x+n->o->w();if (r > R) R = r; int b = y+n->o->h();if (b > B) B = b; } } t->o->resize(X,Y,R-X,B-Y); } extern void group_selected_menuitems(); void group_cb(Fl_Widget *, void *) { if (!Fl_Type::current) { fl_message("No widgets selected."); return; } if (!Fl_Type::current->is_widget()) { fl_message("Only widgets and menu items can be grouped."); return; } if (Fl_Type::current->is_a(ID_Menu_Item)) { group_selected_menuitems(); return; } // The group will be created in the parent group of the current widget Fl_Type *qq = Fl_Type::current->parent; Fl_Widget_Type *q = static_cast(Fl_Type::current); while (qq && !qq->is_a(ID_Group)) { qq = qq->parent; } if (!qq) { fl_message("Can't create a new group here."); return; } undo_checkpoint(); undo_suspend(); Fl_Type::current = qq; Fl_Group_Type *n = (Fl_Group_Type*)(Fl_Group_type.make(Strategy::AS_LAST_CHILD)); n->move_before(q); n->o->resize(q->o->x(),q->o->y(),q->o->w(),q->o->h()); for (Fl_Type *t = qq->next; t && (t->level > qq->level);) { if (t->level != n->level || t == n || !t->selected) { t = t->next; continue; } Fl_Type *nxt = t->remove(); t->add(n, Strategy::AS_LAST_CHILD); t = nxt; } fix_group_size(n); Fl_Type::current = q; n->layout_widget(); widget_browser->rebuild(); undo_resume(); set_modflag(1); } extern void ungroup_selected_menuitems(); void ungroup_cb(Fl_Widget *, void *) { if (!Fl_Type::current) { fl_message("No widgets selected."); return; } if (!Fl_Type::current->is_widget()) { fl_message("Only widgets and menu items can be ungrouped."); return; } if (Fl_Type::current->is_a(ID_Menu_Item)) { ungroup_selected_menuitems(); return; } Fl_Widget_Type *q = static_cast(Fl_Type::current); int q_level = q->level; Fl_Type *qq = Fl_Type::current->parent; while (qq && !qq->is_true_widget()) qq = qq->parent; if (!qq || !qq->is_a(ID_Group)) { fl_message("Only menu widgets inside a group can be ungrouped."); return; } undo_checkpoint(); undo_suspend(); Fl_Type::current = qq; for (Fl_Type *t = qq->next; t && (t->level > qq->level);) { if (t->level != q_level || !t->selected) { t = t->next; continue; } Fl_Type *nxt = t->remove(); t->insert(qq); t = nxt; } if (!qq->next || (qq->next->level <= qq->level)) { qq->remove(); delete qq; // qq has no children that need to be delete } Fl_Type::current = q; widget_browser->rebuild(); undo_resume(); set_modflag(1); } void Fl_Group_Type::ideal_size(int &w, int &h) { if (parent && parent->is_true_widget()) { Fl_Widget *p = ((Fl_Widget_Type*)parent)->o; w = p->w() / 2; h = p->h() / 2; } else { w = 140; h = 140; } Fd_Snap_Action::better_size(w, h); } void Fl_Group_Type::write_code1(Fd_Code_Writer& f) { Fl_Widget_Type::write_code1(f); } void Fl_Group_Type::write_code2(Fd_Code_Writer& f) { const char *var = name() ? name() : "o"; write_extra_code(f); f.write_c("%s%s->end();\n", f.indent(), var); if (resizable()) { f.write_c("%sFl_Group::current()->resizable(%s);\n", f.indent(), var); } write_block_close(f); } // This is called when o is created. If it is in the tab group make // sure it is visible: void Fl_Group_Type::add_child(Fl_Type* cc, Fl_Type* before) { Fl_Widget_Type* c = (Fl_Widget_Type*)cc; Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; ((Fl_Group*)o)->insert(*(c->o), b); o->redraw(); } // This is called when o is deleted. If it is in the tab group make // sure it is not visible: void Fl_Group_Type::remove_child(Fl_Type* cc) { Fl_Widget_Type* c = (Fl_Widget_Type*)cc; ((Fl_Group*)o)->remove(c->o); o->redraw(); } // move, don't change selected value: void Fl_Group_Type::move_child(Fl_Type* cc, Fl_Type* before) { Fl_Widget_Type* c = (Fl_Widget_Type*)cc; Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; ((Fl_Group*)o)->insert(*(c->o), b); o->redraw(); } // live mode support Fl_Widget* Fl_Group_Type::enter_live_mode(int) { Fl_Group *grp = new Fl_Group(o->x(), o->y(), o->w(), o->h()); return propagate_live_mode(grp); } void Fl_Group_Type::leave_live_mode() { } /** copy all properties from the edit widget to the live widget */ void Fl_Group_Type::copy_properties() { Fl_Widget_Type::copy_properties(); } // ---- Fl_Pack_Type --------------------------------------------------- MARK: - Fl_Pack_Type Fl_Pack_type; // the "factory" const char pack_type_name[] = "Fl_Pack"; Fl_Menu_Item pack_type_menu[] = { {"HORIZONTAL", 0, 0, (void*)Fl_Pack::HORIZONTAL}, {"VERTICAL", 0, 0, (void*)Fl_Pack::VERTICAL}, {0} }; Fl_Widget *Fl_Pack_Type::enter_live_mode(int) { Fl_Group *grp = new Fl_Pack(o->x(), o->y(), o->w(), o->h()); return propagate_live_mode(grp); } void Fl_Pack_Type::copy_properties() { Fl_Group_Type::copy_properties(); Fl_Pack *d = (Fl_Pack*)live_widget, *s =(Fl_Pack*)o; d->spacing(s->spacing()); } // ---- Fl_Flex_Type --------------------------------------------------- MARK: - const char flex_type_name[] = "Fl_Flex"; Fl_Menu_Item flex_type_menu[] = { {"HORIZONTAL", 0, 0, (void*)Fl_Flex::HORIZONTAL}, {"VERTICAL", 0, 0, (void*)Fl_Flex::VERTICAL}, {0}}; Fl_Flex_Type Fl_Flex_type; // the "factory" /** Override flex's resize behavior to do nothing to children by default. \param[in] X, Y, W, H new size */ void Fl_Flex_Proxy::resize(int X, int Y, int W, int H) { if (Fl_Type::allow_layout > 0) { Fl_Flex::resize(X, Y, W, H); } else { Fl_Widget::resize(X, Y, W, H); } redraw(); } /** Override draw() to make groups with no box or flat box background visible. */ void Fl_Flex_Proxy::draw() { if (show_ghosted_outline && (box() == FL_NO_BOX)) { fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f))); } Fl_Flex::draw(); } Fl_Widget *Fl_Flex_Type::enter_live_mode(int) { Fl_Flex *grp = new Fl_Flex(o->x(), o->y(), o->w(), o->h()); propagate_live_mode(grp); Fl_Flex *d = grp, *s =(Fl_Flex*)o; int nc = s->children(), nd = d->children(); if (nc>nd) nc = nd; for (int i=0; ifixed(s->child(i))) { Fl_Widget *dc = d->child(i); d->fixed(d->child(i), s->horizontal() ? dc->w() : dc->h()); } } return grp; } void Fl_Flex_Type::copy_properties() { Fl_Group_Type::copy_properties(); Fl_Flex *d = (Fl_Flex*)live_widget, *s =(Fl_Flex*)o; int lm, tm, rm, bm; s->margin(&lm, &tm, &rm, &bm); d->margin(lm, tm, rm, bm); d->gap( s->gap() ); } void Fl_Flex_Type::copy_properties_for_children() { Fl_Flex *d = (Fl_Flex*)live_widget, *s =(Fl_Flex*)o; for (int i=0; ichildren(); i++) { if (s->fixed(s->child(i)) && ichildren()) { if (s->horizontal()) { d->fixed(d->child(i), d->child(i)->w()); } else { d->fixed(d->child(i), d->child(i)->h()); } } } d->layout(); } void Fl_Flex_Type::write_properties(Fd_Project_Writer &f) { Fl_Group_Type::write_properties(f); Fl_Flex* flex = (Fl_Flex*)o; int lm, tm, rm, bm; flex->margin(&lm, &tm, &rm, &bm); if (lm!=0 || tm!=0 || rm!=0 || bm!=0) f.write_string("margin {%d %d %d %d}", lm, tm, rm, bm); if (flex->gap()) f.write_string("gap %d", flex->gap()); int nSet = 0; for (int i=0; ichildren(); i++) if (flex->fixed(flex->child(i))) nSet++; if (nSet) { f.write_string("fixed_size_tuples {%d", nSet); for (int i=0; ichildren(); i++) { Fl_Widget *ci = flex->child(i); if (flex->fixed(ci)) f.write_string(" %d %d", i, flex->horizontal() ? ci->w() : ci->h()); } f.write_string("}"); } } void Fl_Flex_Type::read_property(Fd_Project_Reader &f, const char *c) { Fl_Flex* flex = (Fl_Flex*)o; suspend_auto_layout = 1; if (!strcmp(c,"margin")) { int lm, tm, rm, bm; if (sscanf(f.read_word(),"%d %d %d %d",&lm,&tm,&rm,&bm) == 4) flex->margin(lm, tm, rm, bm); } else if (!strcmp(c,"gap")) { int g; if (sscanf(f.read_word(),"%d",&g)) flex->gap(g); } else if (!strcmp(c,"fixed_size_tuples")) { f.read_word(1); // must be '{' const char *nStr = f.read_word(1); // number of indices in table fixedSizeTupleSize = atoi(nStr); fixedSizeTuple = new int[fixedSizeTupleSize*2]; for (int i=0; i0) { for (int i=0; i=0 && ixchildren()) { Fl_Widget *ci = flex->child(ix); flex->fixed(ci, size); } } fixedSizeTupleSize = 0; delete[] fixedSizeTuple; fixedSizeTuple = NULL; } suspend_auto_layout = 0; } void Fl_Flex_Type::write_code2(Fd_Code_Writer& f) { const char *var = name() ? name() : "o"; Fl_Flex* flex = (Fl_Flex*)o; int lm, tm, rm, bm; flex->margin(&lm, &tm, &rm, &bm); if (lm!=0 || tm!=0 || rm!=0 || bm!=0) f.write_c("%s%s->margin(%d, %d, %d, %d);\n", f.indent(), var, lm, tm, rm, bm); if (flex->gap()) f.write_c("%s%s->gap(%d);\n", f.indent(), var, flex->gap()); for (int i=0; ichildren(); ++i) { Fl_Widget *ci = flex->child(i); if (flex->fixed(ci)) f.write_c("%s%s->fixed(%s->child(%d), %d);\n", f.indent(), var, var, i, flex->horizontal() ? ci->w() : ci->h()); } Fl_Group_Type::write_code2(f); } //void Fl_Flex_Type::add_child(Fl_Type* a, Fl_Type* b) { // Fl_Group_Type::add_child(a, b); // if (!suspend_auto_layout) // ((Fl_Flex*)o)->layout(); //} // //void Fl_Flex_Type::move_child(Fl_Type* a, Fl_Type* b) { // Fl_Group_Type::move_child(a, b); // if (!suspend_auto_layout) // ((Fl_Flex*)o)->layout(); //} void Fl_Flex_Type::remove_child(Fl_Type* a) { if (a->is_widget()) ((Fl_Flex*)o)->fixed(((Fl_Widget_Type*)a)->o, 0); Fl_Group_Type::remove_child(a); // ((Fl_Flex*)o)->layout(); layout_widget(); } void Fl_Flex_Type::layout_widget() { allow_layout++; ((Fl_Flex*)o)->layout(); allow_layout--; } // Change from HORIZONTAL to VERTICAL or back. // Children in a horizontal Flex have already the full vertical height. If we // just change to vertical, the accumulated hight of all children is too big. // We need to relayout existing children. void Fl_Flex_Type::change_subtype_to(int n) { Fl_Flex* f = (Fl_Flex*)o; if (f->type()==n) return; int nc = f->children(); if (nc > 0) { int dw = Fl::box_dw(f->box()); int dh = Fl::box_dh(f->box()); int lm, tm, rm, bm; f->margin(&lm, &tm, &rm, &bm); int gap = f->gap(); int fw = f->w()-dw-lm-rm-(nc*gap); if (fw<=nc) fw = nc; // avoid division by zero int fh = f->h()-dh-tm-bm-(nc*gap); if (fh<=nc) fh = nc; // avoid division by zero if (f->type()==Fl_Flex::HORIZONTAL && n==Fl_Flex::VERTICAL) { float scl = (float)fh/(float)fw; for (int i=0; ichild(i); c->size(f->w(), (int)(c->w()*scl)); } } else if (f->type()==Fl_Flex::VERTICAL && n==Fl_Flex::HORIZONTAL) { float scl = (float)fw/(float)fh; for (int i=0; ichild(i); c->size((int)(c->h()*scl), f->h()); } } } f->type(n); f->layout(); } int Fl_Flex_Type::parent_is_flex(Fl_Type *t) { return (t->is_widget() && t->parent && t->parent->is_a(ID_Flex)); } /** Insert a widget in the child list so that it moves as close as possible the position. \param[in] child any widget in the tree but this, may already be a child of this and will be relocated if so \param[in] x, y pixel coordinates relative to the top left of the window */ void Fl_Flex_Type::insert_child_at(Fl_Widget *child, int x, int y) { Fl_Flex *flex = (Fl_Flex*)o; // find the insertion point closest to x, y int d = flex->w() + flex->h(), di = -1; if (flex->horizontal()) { int i, dx; for (i=0; ichildren(); i++) { dx = x - flex->child(i)->x(); if (dx < 0) dx = -dx; if (dx < d) { d = dx; di = i; } } dx = x - (flex->x()+flex->w()); if (dx < 0) dx = -dx; if (dx < d) { d = dx; di = i; } } else { int i, dy; for (i=0; ichildren(); i++) { dy = y - flex->child(i)->y(); if (dy < 0) dy = -dy; if (dy < d) { d = dy; di = i; } } dy = y - (flex->y()+flex->h()); if (dy < 0) dy = -dy; if (dy < d) { d = dy; di = i; } } if (di > -1) { flex->insert(*child, di); } } /** Move children around using the keyboard. \param[in] child pointer to the child type \param[in] key code of the last keypress when handling a FL_KEYBOARD event. */ void Fl_Flex_Type::keyboard_move_child(Fl_Widget_Type *child, int key) { Fl_Flex *flex = ((Fl_Flex*)o); int ix = flex->find(child->o); if (ix == flex->children()) return; if (flex->horizontal()) { if (key==FL_Right) { flex->insert(*child->o, ix+2); } else if (key==FL_Left) { if (ix > 0) flex->insert(*child->o, ix-1); } } else { if (key==FL_Down) { flex->insert(*child->o, ix+2); } else if (key==FL_Up) { if (ix > 0) flex->insert(*child->o, ix-1); } } } int Fl_Flex_Type::size(Fl_Type *t, char fixed_only) { if (!t->is_widget()) return 0; if (!t->parent) return 0; if (!t->parent->is_a(ID_Flex)) return 0; Fl_Flex_Type* ft = (Fl_Flex_Type*)t->parent; Fl_Flex* f = (Fl_Flex*)ft->o; Fl_Widget *w = ((Fl_Widget_Type*)t)->o; if (fixed_only && !f->fixed(w)) return 0; return f->horizontal() ? w->w() : w->h(); } int Fl_Flex_Type::is_fixed(Fl_Type *t) { if (!t->is_widget()) return 0; if (!t->parent) return 0; if (!t->parent->is_a(ID_Flex)) return 0; Fl_Flex_Type* ft = (Fl_Flex_Type*)t->parent; Fl_Flex* f = (Fl_Flex*)ft->o; Fl_Widget *w = ((Fl_Widget_Type*)t)->o; return f->fixed(w); } // ---- Fl_Table_Type -------------------------------------------------- MARK: - Fl_Table_Type Fl_Table_type; // the "factory" static const int MAX_ROWS = 14; static const int MAX_COLS = 7; // this is a minimal table widget used as an example when adding tables in Fluid class Fluid_Table : public Fl_Table { int data[MAX_ROWS][MAX_COLS]; // data array for cells // Draw the row/col headings // Make this a dark thin upbox with the text inside. // void DrawHeader(const char *s, int X, int Y, int W, int H) { fl_push_clip(X,Y,W,H); fl_draw_box(FL_THIN_UP_BOX, X,Y,W,H, row_header_color()); fl_color(FL_BLACK); fl_draw(s, X,Y,W,H, FL_ALIGN_CENTER); fl_pop_clip(); } // Draw the cell data // Dark gray text on white background with subtle border // void DrawData(const char *s, int X, int Y, int W, int H) { fl_push_clip(X,Y,W,H); // Draw cell bg fl_color(FL_WHITE); fl_rectf(X,Y,W,H); // Draw cell data fl_color(FL_GRAY0); fl_draw(s, X,Y,W,H, FL_ALIGN_CENTER); // Draw box border fl_color(color()); fl_rect(X,Y,W,H); fl_pop_clip(); } // Handle drawing table's cells // Fl_Table calls this function to draw each visible cell in the table. // It's up to us to use FLTK's drawing functions to draw the cells the way we want. // void draw_cell(TableContext context, int ROW=0, int COL=0, int X=0, int Y=0, int W=0, int H=0) FL_OVERRIDE { static char s[40]; switch ( context ) { case CONTEXT_STARTPAGE: // before page is drawn.. fl_font(FL_HELVETICA, 16); // set the font for our drawing operations return; case CONTEXT_COL_HEADER: // Draw column headers sprintf(s,"%c",'A'+COL); // "A", "B", "C", etc. DrawHeader(s,X,Y,W,H); return; case CONTEXT_ROW_HEADER: // Draw row headers sprintf(s,"%03d:",ROW); // "001:", "002:", etc DrawHeader(s,X,Y,W,H); return; case CONTEXT_CELL: // Draw data in cells sprintf(s,"%d",data[ROW][COL]); DrawData(s,X,Y,W,H); return; default: return; } } public: Fluid_Table(int x, int y, int w, int h, const char *l=0L) : Fl_Table(x, y, w, h, l) { end(); for ( int r=0; ro : 0; if (((Fl_Table*)o)->children()==1) { // the FLuid_Table has one extra child fl_message("Inserting child widgets into an Fl_Table is not recommended.\n" "Please refer to the documentation on Fl_Table."); } ((Fl_Table*)o)->insert(*(c->o), b); o->redraw(); } void Fl_Table_Type::remove_child(Fl_Type* cc) { Fl_Widget_Type* c = (Fl_Widget_Type*)cc; ((Fl_Table*)o)->remove(*(c->o)); o->redraw(); } void Fl_Table_Type::move_child(Fl_Type* cc, Fl_Type* before) { Fl_Widget_Type* c = (Fl_Widget_Type*)cc; Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; ((Fl_Table*)o)->insert(*(c->o), b); o->redraw(); } Fl_Widget *Fl_Table_Type::enter_live_mode(int) { Fl_Group *grp = new Fluid_Table(o->x(), o->y(), o->w(), o->h()); live_widget = grp; copy_properties(); grp->end(); return live_widget; } void Fl_Table_Type::ideal_size(int &w, int &h) { w = 160; h = 120; Fd_Snap_Action::better_size(w, h); } // ---- Fl_Tabs_Type --------------------------------------------------- MARK: - Fl_Tabs_Type Fl_Tabs_type; // the "factory" const char tabs_type_name[] = "Fl_Tabs"; // Override group's resize behavior to do nothing to children: void Fl_Tabs_Proxy::resize(int X, int Y, int W, int H) { if (Fl_Type::allow_layout > 0) { Fl_Tabs::resize(X, Y, W, H); } else { Fl_Widget::resize(X, Y, W, H); } redraw(); } /** Override draw() to make groups with no box or flat box background visible. */ void Fl_Tabs_Proxy::draw() { if (show_ghosted_outline && (box() == FL_NO_BOX)) { fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f))); } Fl_Tabs::draw(); } // This is called when user clicks on a widget in the window. See // if it is a tab title, and adjust visibility and return new selection: // If none, return o unchanged: Fl_Type* Fl_Tabs_Type::click_test(int x, int y) { Fl_Tabs *t = (Fl_Tabs*)o; Fl_Widget *a = t->which(x,y); if (!a) return 0; // didn't click on tab // changing the visible tab has an impact on the generated // source code, so mark this project as changed. int changed = (a!=t->value()); // okay, run the tabs ui until they let go of mouse: t->handle(FL_PUSH); Fl::pushed(t); while (Fl::pushed()==t) Fl::wait(); if (changed) set_modflag(1); return (Fl_Type*)(t->value()->user_data()); } void Fl_Tabs_Type::add_child(Fl_Type* c, Fl_Type* before) { Fl_Group_Type::add_child(c, before); } void Fl_Tabs_Type::remove_child(Fl_Type* cc) { Fl_Widget_Type* c = (Fl_Widget_Type*)cc; Fl_Tabs *t = (Fl_Tabs*)o; if (t->value() == c->o) t->value(0); Fl_Group_Type::remove_child(c); } Fl_Widget *Fl_Tabs_Type::enter_live_mode(int) { Fl_Tabs *original = static_cast(o); Fl_Tabs *clone = new Fl_Tabs(o->x(), o->y(), o->w(), o->h()); propagate_live_mode(clone); int tab_index = original->find(original->value()); if ((tab_index>=0) && (tab_indexchildren())) clone->value(clone->child(tab_index)); return clone; } // ---- Fl_Scroll_Type ------------------------------------------------- MARK: - Fl_Scroll_Type Fl_Scroll_type; // the "factory" const char scroll_type_name[] = "Fl_Scroll"; Fl_Menu_Item scroll_type_menu[] = { {"BOTH", 0, 0, 0/*(void*)Fl_Scroll::BOTH*/}, {"HORIZONTAL", 0, 0, (void*)Fl_Scroll::HORIZONTAL}, {"VERTICAL", 0, 0, (void*)Fl_Scroll::VERTICAL}, {"HORIZONTAL_ALWAYS", 0, 0, (void*)Fl_Scroll::HORIZONTAL_ALWAYS}, {"VERTICAL_ALWAYS", 0, 0, (void*)Fl_Scroll::VERTICAL_ALWAYS}, {"BOTH_ALWAYS", 0, 0, (void*)Fl_Scroll::BOTH_ALWAYS}, {0}}; Fl_Widget *Fl_Scroll_Type::enter_live_mode(int) { Fl_Group *grp = new Fl_Scroll(o->x(), o->y(), o->w(), o->h()); grp->show(); return propagate_live_mode(grp); } void Fl_Scroll_Type::copy_properties() { Fl_Group_Type::copy_properties(); Fl_Scroll *s = (Fl_Scroll*)o, *d = (Fl_Scroll*)live_widget; d->scroll_to(s->xposition(), s->yposition()); d->type(s->type()); d->scrollbar.align(s->scrollbar.align()); d->hscrollbar.align(s->hscrollbar.align()); } // ---- Fl_Tile_Type --------------------------------------------------- MARK: - Fl_Tile_Type Fl_Tile_type; // the "factory" const char tile_type_name[] = "Fl_Tile"; void Fl_Tile_Type::copy_properties() { Fl_Group_Type::copy_properties(); // no additional properties } // ---- Fl_Wizard_Type ------------------------------------------------ MARK: - Fl_Wizard_Type Fl_Wizard_type; // the "factory" const char wizard_type_name[] = "Fl_Wizard"; // Override group's resize behavior to do nothing to children: void Fl_Wizard_Proxy::resize(int X, int Y, int W, int H) { if (Fl_Type::allow_layout > 0) { Fl_Wizard::resize(X, Y, W, H); } else { Fl_Widget::resize(X, Y, W, H); } redraw(); } /** Override draw() to make groups with no box or flat box background visible. */ void Fl_Wizard_Proxy::draw() { if (show_ghosted_outline && (box() == FL_NO_BOX)) { fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f))); } Fl_Wizard::draw(); } fltk-1.4.3/fluid/Fl_Menu_Type.cxx0000644000175000017500000007327415004135251016777 0ustar albrechtalbrecht// // Menu item code for the Fast Light Tool Kit (FLTK). // // Menu items are kludged by making a phony Fl_Box widget so the normal // widget panel can be used to control them. // // This file also contains code to make Fl_Menu_Button, Fl_Menu_Bar, // etc widgets. // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Menu_Type.h" #include "fluid.h" #include "Fl_Window_Type.h" #include "file.h" #include "code.h" #include "Fluid_Image.h" #include "custom_widgets.h" #include "mergeback.h" #include "undo.h" #include "widget_browser.h" #include #include #include #include #include #include #include #include #include #include #include #include "../src/flstring.h" #include #include Fl_Menu_Item menu_item_type_menu[] = { {"Normal",0,0,(void*)0}, {"Toggle",0,0,(void*)FL_MENU_BOX}, {"Radio",0,0,(void*)FL_MENU_RADIO}, {0}}; static void delete_dependents(Fl_Menu_Item *m) { if (!m) return; int level = 0; for (;;m++) { if (m->label()==NULL) { if (level==0) { break; } else { level--; } } if (m->flags&FL_SUBMENU) level++; if (m->labeltype()==FL_MULTI_LABEL) delete (Fl_Multi_Label*)m->label(); } } static void delete_menu(Fl_Menu_Item *m) { if (!m) return; delete_dependents(m); delete[] m; } void Fl_Input_Choice_Type::build_menu() { Fl_Input_Choice* w = (Fl_Input_Choice*)o; // count how many Fl_Menu_Item structures needed: int n = 0; Fl_Type* q; for (q = next; q && q->level > level; q = q->next) { if (q->can_have_children()) n++; // space for null at end of submenu n++; } if (!n) { if (menusize) delete_menu((Fl_Menu_Item*)(w->menu())); w->menu(0); menusize = 0; } else { n++; // space for null at end of menu if (menusizemenu())); menusize = n+10; w->menu(new Fl_Menu_Item[menusize]); } else { if (menusize) delete_dependents((Fl_Menu_Item*)(w->menu())); } // Menus are already built during the .fl file reading process, so if the // end of a menu list is not read yet, the end markers (label==NULL) will // not be set, and deleting dependents will randomly free memory. // Clearing the array should avoid that. memset( (void*)w->menu(), 0, menusize * sizeof(Fl_Menu_Item) ); // fill them all in: Fl_Menu_Item* m = (Fl_Menu_Item*)(w->menu()); int lvl = level+1; for (q = next; q && q->level > level; q = q->next) { Fl_Menu_Item_Type* i = (Fl_Menu_Item_Type*)q; if (i->o->image()) { if (i->o->label() && i->o->label()[0]) { Fl_Multi_Label *ml = new Fl_Multi_Label; ml->labela = (char*)i->o->image(); ml->labelb = i->o->label(); ml->typea = FL_IMAGE_LABEL; ml->typeb = FL_NORMAL_LABEL; ml->label(m); } else { i->o->image()->label(m); } } else { m->label(i->o->label() ? i->o->label() : "(nolabel)"); m->labeltype(i->o->labeltype()); } m->shortcut(((Fl_Button*)(i->o))->shortcut()); m->callback(0,(void*)i); m->flags = i->flags(); m->labelfont(i->o->labelfont()); m->labelsize(i->o->labelsize()); m->labelcolor(i->o->labelcolor()); if (q->can_have_children()) {lvl++; m->flags |= FL_SUBMENU;} m++; int l1 = (q->next && q->next->is_a(ID_Menu_Item)) ? q->next->level : level; while (lvl > l1) {m->label(0); m++; lvl--;} lvl = l1; } } o->redraw(); } /** Create and add a new Menu Item node. \param[in] strategy add after current or as last child \return new Menu Item node */ Fl_Type *Fl_Menu_Item_Type::make(Strategy strategy) { return Fl_Menu_Item_Type::make(0, strategy); } /** Create an add a specific Menu Item node. \param[in] flags set to 0, FL_MENU_RADIO, FL_MENU_TOGGLE, or FL_SUBMENU \param[in] strategy add after current or as last child \return new Menu Item node */ Fl_Type* Fl_Menu_Item_Type::make(int flags, Strategy strategy) { // Find a good insert position based on the current marked node Fl_Type *anchor = Fl_Type::current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !(p->is_a(ID_Menu_Manager_) || p->is_a(ID_Submenu))) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } if (!p) { fl_message("Please select a menu widget or a menu item"); return 0; } if (!o) { o = new Fl_Button(0,0,100,20); // create template widget } Fl_Menu_Item_Type* t = NULL; if (flags==FL_SUBMENU) { t = new Fl_Submenu_Type(); } else { t = new Fl_Menu_Item_Type(); } t->o = new Fl_Button(0,0,100,20); t->o->type(flags); t->factory = this; t->add(anchor, strategy); if (strategy.source() == Strategy::FROM_USER) { if (flags==FL_SUBMENU) { t->label("submenu"); } else { t->label("item"); } } return t; } void group_selected_menuitems() { // The group will be created in the parent group of the current menuitem if (!Fl_Type::current->is_a(ID_Menu_Item)) { return; } Fl_Menu_Item_Type *q = static_cast(Fl_Type::current); Fl_Type *qq = Fl_Type::current->parent; if (!qq || !(qq->is_a(ID_Menu_Manager_) || qq->is_a(ID_Submenu))) { fl_message("Can't create a new submenu here."); return; } undo_checkpoint(); undo_suspend(); Fl_Widget_Type *n = (Fl_Widget_Type*)(q->make(FL_SUBMENU, Strategy::AFTER_CURRENT)); for (Fl_Type *t = qq->next; t && (t->level > qq->level);) { if (t->level != n->level || t == n || !t->selected) { t = t->next; continue; } Fl_Type *nxt = t->remove(); t->add(n, Strategy::AS_LAST_CHILD); t = nxt; } widget_browser->rebuild(); undo_resume(); set_modflag(1); } void ungroup_selected_menuitems() { // Find the submenu Fl_Type *qq = Fl_Type::current->parent; Fl_Widget_Type *q = static_cast(Fl_Type::current); int q_level = q->level; if (!qq || !qq->is_a(ID_Submenu)) { fl_message("Only menu items inside a submenu can be ungrouped."); return; } undo_checkpoint(); undo_suspend(); Fl_Type::current = qq; for (Fl_Type *t = qq->next; t && (t->level > qq->level);) { if (t->level != q_level || !t->selected) { t = t->next; continue; } Fl_Type *nxt = t->remove(); t->insert(qq); t = nxt; } if (!qq->next || (qq->next->level <= qq->level)) { qq->remove(); delete qq; // qq has no children that need to be delete } Fl_Type::current = q; widget_browser->rebuild(); undo_resume(); set_modflag(1); } /** Create and add a new Checkbox Menu Item node. \param[in] strategy add after current or as last child \return new node */ Fl_Type *Fl_Checkbox_Menu_Item_Type::make(Strategy strategy) { return Fl_Menu_Item_Type::make(FL_MENU_TOGGLE, strategy); } /** Create and add a new Radio ButtonMenu Item node. \param[in] strategy add after current or as last child \return new node */ Fl_Type *Fl_Radio_Menu_Item_Type::make(Strategy strategy) { return Fl_Menu_Item_Type::make(FL_MENU_RADIO, strategy); } /** Create and add a new Submenu Item node. \param[in] strategy add after current or as last child \return new node */ Fl_Type *Fl_Submenu_Type::make(Strategy strategy) { return Fl_Menu_Item_Type::make(FL_SUBMENU, strategy); } Fl_Menu_Item_Type Fl_Menu_Item_type; Fl_Checkbox_Menu_Item_Type Fl_Checkbox_Menu_Item_type; Fl_Radio_Menu_Item_Type Fl_Radio_Menu_Item_type; Fl_Submenu_Type Fl_Submenu_type; //////////////////////////////////////////////////////////////// // Writing the C code: // test functions in Fl_Widget_Type.C: int is_name(const char *c); const char *array_name(Fl_Widget_Type *o); int isdeclare(const char *c); // Search backwards to find the parent menu button and return it's name. // Also put in i the index into the button's menu item array belonging // to this menu item. const char* Fl_Menu_Item_Type::menu_name(Fd_Code_Writer& f, int& i) { i = 0; Fl_Type* t = prev; while (t && t->is_a(ID_Menu_Item)) { // be sure to count the {0} that ends a submenu: if (t->level > t->next->level) i += (t->level - t->next->level); // detect empty submenu: else if (t->level == t->next->level && t->can_have_children()) i++; t = t->prev; i++; } if (!t) return "\n#error Fl_Menu_Item_Type::menu_name, invalid f\n"; return f.unique_id(t, "menu", t->name(), t->label()); } void Fl_Menu_Item_Type::write_static(Fd_Code_Writer& f) { if (image && label() && label()[0]) { f.write_h_once("#include "); f.write_h_once("#include "); } if (callback() && is_name(callback()) && !user_defined(callback())) f.write_h_once("extern void %s(Fl_Menu_*, %s);", callback(), user_data_type() ? user_data_type() : "void*"); for (int n=0; n < NUM_EXTRA_CODE; n++) { if (extra_code(n) && isdeclare(extra_code(n))) f.write_h_once("%s", extra_code(n)); } if (callback() && !is_name(callback())) { // see if 'o' or 'v' used, to prevent unused argument warnings: int use_o = 0; int use_v = 0; const char *d; for (d = callback(); *d;) { if (*d == 'o' && !is_id(d[1])) use_o = 1; if (*d == 'v' && !is_id(d[1])) use_v = 1; do d++; while (is_id(*d)); while (*d && !is_id(*d)) d++; } const char* cn = callback_name(f); const char* k = class_name(1); if (k) { f.write_c("\nvoid %s::%s_i(Fl_Menu_*", k, cn); } else { f.write_c("\nstatic void %s(Fl_Menu_*", cn); } if (use_o) f.write_c(" o"); const char* ut = user_data_type() ? user_data_type() : "void*"; f.write_c(", %s", ut); if (use_v) f.write_c(" v"); f.write_c(") {\n"); // Matt: disabled f.tag(FD_TAG_GENERIC, 0); f.write_c_indented(callback(), 1, 0); if (*(d-1) != ';' && *(d-1) != '}') { const char *p = strrchr(callback(), '\n'); if (p) p ++; else p = callback(); // Only add trailing semicolon if the last line is not a preprocessor // statement... if (*p != '#' && *p) f.write_c(";"); } f.write_c("\n"); // Matt: disabled f.tag(FD_TAG_MENU_CALLBACK, get_uid()); f.write_c("}\n"); // If the menu item is part of a Class or Widget Class, FLUID generates // a dummy static callback which retrieves a pointer to the class and then // calls the original callback from within the class context. // k is the name of the enclosing class (or classes) if (k) { // Implement the callback as a static member function f.write_c("void %s::%s(Fl_Menu_* o, %s v) {\n", k, cn, ut); // Find the Fl_Menu_ container for this menu item Fl_Type* t = parent; while (t->is_a(ID_Menu_Item)) t = t->parent; if (t) { Fl_Widget_Type *tw = (t->is_widget()) ? static_cast(t) : NULL; Fl_Type *q = NULL; // Generate code to call the callback if (tw->is_a(ID_Menu_Bar) && ((Fl_Menu_Bar_Type*)tw)->is_sys_menu_bar()) { // Fl_Sys_Menu_Bar removes itself from any parent on macOS, so we // wrapped it in a class and remeber the parent class in a new // class memeber variable. Fl_Menu_Bar_Type *tmb = (Fl_Menu_Bar_Type*)tw; f.write_c("%s%s* sys_menu_bar = ((%s*)o);\n", f.indent(1), tmb->sys_menubar_proxy_name(), tmb->sys_menubar_proxy_name()); f.write_c("%s%s* parent_class = ((%s*)sys_menu_bar->_parent_class);\n", f.indent(1), k, k); f.write_c("%sparent_class->%s_i(o,v);\n}\n", f.indent(1), cn); } else { f.write_c("%s((%s*)(o", f.indent(1), k); // The class pointer is in the user_data field of the top widget if (t && t->is_a(ID_Input_Choice)) { // Go up one more level for Fl_Input_Choice, as these are groups themselves f.write_c("->parent()"); } // Now generate code to find the topmost widget in this class for (t = t->parent; t && t->is_widget() && !is_class(); q = t, t = t->parent) f.write_c("->parent()"); // user_data is cast into a pointer to the if (!q || !q->is_a(ID_Widget_Class)) f.write_c("->user_data()"); f.write_c("))->%s_i(o,v);\n}\n", cn); } } else { f.write_c("#error Enclosing Fl_Menu_* not found\n"); } } } if (image) { if (!f.c_contains(image)) image->write_static(f, compress_image_); } if (next && next->is_a(ID_Menu_Item)) return; // okay, when we hit last item in the menu we have to write the // entire array out: const char* k = class_name(1); if (k) { int i; f.write_c("\nFl_Menu_Item %s::%s[] = {\n", k, menu_name(f, i)); } else { int i; f.write_c("\nFl_Menu_Item %s[] = {\n", menu_name(f, i)); } Fl_Type* t = prev; while (t && t->is_a(ID_Menu_Item)) t = t->prev; for (Fl_Type* q = t->next; q && q->is_a(ID_Menu_Item); q = q->next) { ((Fl_Menu_Item_Type*)q)->write_item(f); int thislevel = q->level; if (q->can_have_children()) thislevel++; int nextlevel = (q->next && q->next->is_a(ID_Menu_Item)) ? q->next->level : t->level+1; while (thislevel > nextlevel) {f.write_c(" {0,0,0,0,0,0,0,0,0},\n"); thislevel--;} } f.write_c(" {0,0,0,0,0,0,0,0,0}\n};\n"); if (k) { // Write menu item variables... t = prev; while (t && t->is_a(ID_Menu_Item)) t = t->prev; for (Fl_Type* q = t->next; q && q->is_a(ID_Menu_Item); q = q->next) { Fl_Menu_Item_Type *m = (Fl_Menu_Item_Type*)q; const char *c = array_name(m); if (c) { if (c==m->name()) { // assign a menu item address directly to a variable int i; const char* n = ((Fl_Menu_Item_Type *)q)->menu_name(f, i); f.write_c("Fl_Menu_Item* %s::%s = %s::%s + %d;\n", k, c, k, n, i); } else { // if the name is an array, only define the array. // The actual assignment is in write_code1(Fd_Code_Writer& f) f.write_c("Fl_Menu_Item* %s::%s;\n", k, c); } } } } } int Fl_Menu_Item_Type::flags() { int i = o->type(); if (((Fl_Button*)o)->value()) i |= FL_MENU_VALUE; if (!o->active()) i |= FL_MENU_INACTIVE; if (!o->visible()) i |= FL_MENU_INVISIBLE; if (can_have_children()) { if (user_data() == NULL) i |= FL_SUBMENU; else i |= FL_SUBMENU_POINTER; } if (hotspot()) i |= FL_MENU_DIVIDER; return i; } void Fl_Menu_Item_Type::write_item(Fd_Code_Writer& f) { static const char * const labeltypes[] = { "FL_NORMAL_LABEL", "FL_NO_LABEL", "FL_SHADOW_LABEL", "FL_ENGRAVED_LABEL", "FL_EMBOSSED_LABEL", "FL_MULTI_LABEL", "FL_ICON_LABEL", "FL_IMAGE_LABEL" }; write_comment_inline_c(f, " "); f.write_c(" {"); if (label() && label()[0]) switch (g_project.i18n_type) { case FD_I18N_GNU: // we will call i18n when the menu is instantiated for the first time f.write_c("%s(", g_project.i18n_gnu_static_function.c_str()); f.write_cstring(label()); f.write_c(")"); break; case FD_I18N_POSIX: // fall through: strings can't be translated before a catalog is chosen default: f.write_cstring(label()); } else f.write_c("\"\""); if (((Fl_Button*)o)->shortcut()) { int s = ((Fl_Button*)o)->shortcut(); f.write_c(", "); if (g_project.use_FL_COMMAND) { if (s & FL_CTRL) { f.write_c("FL_CONTROL|"); s &= ~FL_CTRL; } if (s & FL_META) { f.write_c("FL_COMMAND|"); s &= ~FL_META; } } else { if (s & FL_CTRL) { f.write_c("FL_CTRL|"); s &= ~FL_CTRL; } if (s & FL_META) { f.write_c("FL_META|"); s &= ~FL_META; } } if (s & FL_SHIFT) { f.write_c("FL_SHIFT|"); s &= ~FL_SHIFT; } if (s & FL_ALT) { f.write_c("FL_ALT|"); s &= ~FL_ALT; } if ((s < 127) && isprint(s)) f.write_c("'%c', ", s); else f.write_c("0x%x, ", s); } else { f.write_c(", 0, "); } if (callback()) { const char* k = is_name(callback()) ? 0 : class_name(1); if (k) { f.write_c(" (Fl_Callback*)%s::%s,", k, callback_name(f)); } else { f.write_c(" (Fl_Callback*)%s,", callback_name(f)); } } else f.write_c(" 0,"); if (user_data()) f.write_c(" (void*)(%s),", user_data()); else f.write_c(" 0,"); f.write_c(" %d, (uchar)%s, %d, %d, %d", flags(), labeltypes[o->labeltype()], o->labelfont(), o->labelsize(), o->labelcolor()); f.write_c("},\n"); } void start_menu_initialiser(Fd_Code_Writer& f, int &initialized, const char *name, int index) { if (!initialized) { initialized = 1; f.write_c("%s{ Fl_Menu_Item* o = &%s[%d];\n", f.indent(), name, index); f.indentation++; } } void Fl_Menu_Item_Type::write_code1(Fd_Code_Writer& f) { int i; const char* mname = menu_name(f, i); if (!prev->is_a(ID_Menu_Item)) { // for first menu item, declare the array if (class_name(1)) { f.write_h("%sstatic Fl_Menu_Item %s[];\n", f.indent(1), mname); } else { f.write_h("extern Fl_Menu_Item %s[];\n", mname); } } const char *c = array_name(this); if (c) { if (class_name(1)) { f.write_public(public_); f.write_h("%sstatic Fl_Menu_Item *%s;\n", f.indent(1), c); } else { if (c==name()) f.write_h("#define %s (%s+%d)\n", c, mname, i); else f.write_h("extern Fl_Menu_Item *%s;\n", c); } } if (callback()) { if (!is_name(callback()) && class_name(1)) { const char* cn = callback_name(f); const char* ut = user_data_type() ? user_data_type() : "void*"; f.write_public(0); f.write_h("%sinline void %s_i(Fl_Menu_*, %s);\n", f.indent(1), cn, ut); f.write_h("%sstatic void %s(Fl_Menu_*, %s);\n", f.indent(1), cn, ut); } } int menuItemInitialized = 0; // if the name is an array variable, assign the value here if (name() && strchr(name(), '[')) { f.write_c("%s%s = &%s[%d];\n", f.indent_plus(1), name(), mname, i); } if (image) { start_menu_initialiser(f, menuItemInitialized, mname, i); if (label() && label()[0]) { f.write_c("%sFl_Multi_Label *ml = new Fl_Multi_Label;\n", f.indent()); f.write_c("%sml->labela = (char*)", f.indent()); image->write_inline(f); f.write_c(";\n"); if (g_project.i18n_type==FD_I18N_NONE) { f.write_c("%sml->labelb = o->label();\n", f.indent()); } else if (g_project.i18n_type==FD_I18N_GNU) { f.write_c("%sml->labelb = %s(o->label());\n", f.indent(), g_project.i18n_gnu_function.c_str()); } else if (g_project.i18n_type==FD_I18N_POSIX) { f.write_c("%sml->labelb = catgets(%s,%s,i+%d,o->label());\n", f.indent(), g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), g_project.i18n_pos_set.c_str(), msgnum()); } f.write_c("%sml->typea = FL_IMAGE_LABEL;\n", f.indent()); f.write_c("%sml->typeb = FL_NORMAL_LABEL;\n", f.indent()); f.write_c("%sml->label(o);\n", f.indent()); } else { image->write_code(f, 0, "o"); } } if (g_project.i18n_type && label() && label()[0]) { Fl_Labeltype t = o->labeltype(); if (image) { // label was already copied a few lines up } else if ( t==FL_NORMAL_LABEL || t==FL_SHADOW_LABEL || t==FL_ENGRAVED_LABEL || t==FL_EMBOSSED_LABEL) { start_menu_initialiser(f, menuItemInitialized, mname, i); if (g_project.i18n_type==FD_I18N_GNU) { f.write_c("%so->label(%s(o->label()));\n", f.indent(), g_project.i18n_gnu_function.c_str()); } else if (g_project.i18n_type==FD_I18N_POSIX) { f.write_c("%so->label(catgets(%s,%s,i+%d,o->label()));\n", f.indent(), g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), g_project.i18n_pos_set.c_str(), msgnum()); } } } for (int n=0; n < NUM_EXTRA_CODE; n++) { if (extra_code(n) && !isdeclare(extra_code(n))) { start_menu_initialiser(f, menuItemInitialized, mname, i); f.write_c("%s%s\n", f.indent(), extra_code(n)); } } if (menuItemInitialized) { f.indentation--; f.write_c("%s}\n",f.indent()); } } void Fl_Menu_Item_Type::write_code2(Fd_Code_Writer&) {} //////////////////////////////////////////////////////////////// // This is the base class for widgets that contain a menu (ie // subclasses of Fl_Menu_. // This is a parent widget and menu items can be added as // children. An actual array of Fl_Menu_Items is kept parallel // with the child objects and updated as they change. void Fl_Menu_Base_Type::build_menu() { Fl_Menu_* w = (Fl_Menu_*)o; // count how many Fl_Menu_Item structures needed: int n = 0; Fl_Type* q; for (q = next; q && q->level > level; q = q->next) { if (q->can_have_children()) n++; // space for null at end of submenu n++; } if (!n) { if (menusize) delete_menu((Fl_Menu_Item*)(w->menu())); w->menu(0); menusize = 0; } else { n++; // space for null at end of menu if (menusizemenu())); menusize = n+10; w->menu(new Fl_Menu_Item[menusize]); } else { if (menusize) delete_dependents((Fl_Menu_Item*)(w->menu())); } // Menus are already built during the .fl file reading process, so if the // end of a menu list is not read yet, the end markers (label==NULL) will // not be set, and deleting dependents will randomly free memory. // Clearing the array should avoid that. memset( (void*)w->menu(), 0, menusize * sizeof(Fl_Menu_Item) ); // fill them all in: Fl_Menu_Item* m = (Fl_Menu_Item*)(w->menu()); int lvl = level+1; for (q = next; q && q->level > level; q = q->next) { Fl_Menu_Item_Type* i = (Fl_Menu_Item_Type*)q; if (i->o->image()) { if (i->o->label() && i->o->label()[0]) { Fl_Multi_Label *ml = new Fl_Multi_Label; ml->labela = (char*)i->o->image(); ml->labelb = i->o->label(); ml->typea = FL_IMAGE_LABEL; ml->typeb = FL_NORMAL_LABEL; ml->label(m); } else { i->o->image()->label(m); } } else { m->label(i->o->label() ? i->o->label() : "(nolabel)"); m->labeltype(i->o->labeltype()); } m->shortcut(((Fl_Button*)(i->o))->shortcut()); m->callback(0,(void*)i); m->flags = i->flags() | i->o->type(); m->labelfont(i->o->labelfont()); m->labelsize(i->o->labelsize()); m->labelcolor(i->o->labelcolor()); if (q->can_have_children()) {lvl++; m->flags |= FL_SUBMENU;} m++; int l1 = (q->next && q->next->is_a(ID_Menu_Item)) ? q->next->level : level; while (lvl > l1) {m->label(0); m++; lvl--;} lvl = l1; } } o->redraw(); } Fl_Type* Fl_Menu_Base_Type::click_test(int, int) { if (selected) return 0; // let user move the widget Fl_Menu_* w = (Fl_Menu_*)o; if (!menusize) return 0; const Fl_Menu_Item* save = w->mvalue(); w->value((Fl_Menu_Item*)0); Fl::pushed(w); w->handle(FL_PUSH); Fl::focus(NULL); const Fl_Menu_Item* m = w->mvalue(); if (m) { // restore the settings of toggles & radio items: if (m->flags & (FL_MENU_RADIO | FL_MENU_TOGGLE)) build_menu(); return (Fl_Type*)(m->user_data()); } w->value(save); return this; } void Fl_Menu_Manager_Type::write_code2(Fd_Code_Writer& f) { if (next && next->is_a(ID_Menu_Item)) { f.write_c("%s%s->menu(%s);\n", f.indent(), name() ? name() : "o", f.unique_id(this, "menu", name(), label())); } Fl_Widget_Type::write_code2(f); } void Fl_Menu_Base_Type::copy_properties() { Fl_Widget_Type::copy_properties(); Fl_Menu_ *s = (Fl_Menu_*)o, *d = (Fl_Menu_*)live_widget; d->menu(s->menu()); d->down_box(s->down_box()); d->textcolor(s->textcolor()); d->textfont(s->textfont()); d->textsize(s->textsize()); } //////////////////////////////////////////////////////////////// Fl_Menu_Item button_type_menu[] = { {"normal",0,0,(void*)0}, {"popup1",0,0,(void*)Fl_Menu_Button::POPUP1}, {"popup2",0,0,(void*)Fl_Menu_Button::POPUP2}, {"popup3",0,0,(void*)Fl_Menu_Button::POPUP3}, {"popup12",0,0,(void*)Fl_Menu_Button::POPUP12}, {"popup23",0,0,(void*)Fl_Menu_Button::POPUP23}, {"popup13",0,0,(void*)Fl_Menu_Button::POPUP13}, {"popup123",0,0,(void*)Fl_Menu_Button::POPUP123}, {0}}; Fl_Menu_Button_Type Fl_Menu_Button_type; //////////////////////////////////////////////////////////////// Fl_Menu_Item dummymenu[] = {{"CHOICE"},{0}}; Fl_Choice_Type Fl_Choice_type; Fl_Input_Choice_Type Fl_Input_Choice_type; void Fl_Input_Choice_Type::copy_properties() { Fl_Widget_Type::copy_properties(); Fl_Input_Choice *s = (Fl_Input_Choice*)o, *d = (Fl_Input_Choice*)live_widget; d->menu(s->menu()); d->down_box(s->down_box()); d->textcolor(s->textcolor()); d->textfont(s->textfont()); d->textsize(s->textsize()); } Fl_Type* Fl_Input_Choice_Type::click_test(int, int) { if (selected) return 0; // let user move the widget Fl_Menu_* w = ((Fl_Input_Choice*)o)->menubutton(); if (!menusize) return 0; const Fl_Menu_Item* save = w->mvalue(); w->value((Fl_Menu_Item*)0); Fl::pushed(w); w->handle(FL_PUSH); Fl::focus(NULL); const Fl_Menu_Item* m = w->mvalue(); if (m) { // restore the settings of toggles & radio items: if (m->flags & (FL_MENU_RADIO | FL_MENU_TOGGLE)) build_menu(); return (Fl_Type*)(m->user_data()); } w->value(save); return this; } //////////////////////////////////////////////////////////////// Fl_Menu_Bar_Type Fl_Menu_Bar_type; Fl_Menu_Item menu_bar_type_menu[] = { {"Fl_Menu_Bar",0,0,(void*)0}, {"Fl_Sys_Menu_Bar",0,0,(void*)1}, {0}}; Fl_Menu_Bar_Type::Fl_Menu_Bar_Type() : _proxy_name(NULL) { } Fl_Menu_Bar_Type::~Fl_Menu_Bar_Type() { if (_proxy_name) ::free(_proxy_name); } /** \brief Return true if this is an Fl_Sys_Menu_Bar. This test fails if subclass() is the name of a class that the user may have derived from Fl_Sys_Menu_Bar. */ bool Fl_Menu_Bar_Type::is_sys_menu_bar() { if (o->type()==1) return true; return ( subclass() && (strcmp(subclass(), "Fl_Sys_Menu_Bar")==0) ); } const char *Fl_Menu_Bar_Type::sys_menubar_name() { if (subclass()) return subclass(); else return "Fl_Sys_Menu_Bar"; } const char *Fl_Menu_Bar_Type::sys_menubar_proxy_name() { if (!_proxy_name) _proxy_name = (char*)::malloc(128); ::snprintf(_proxy_name, 63, "%s_Proxy", sys_menubar_name()); return _proxy_name; } void Fl_Menu_Bar_Type::write_static(Fd_Code_Writer& f) { super::write_static(f); if (is_sys_menu_bar()) { f.write_h_once("#include "); if (is_in_class()) { // Make room for a pointer to the enclosing class. f.write_c_once( // must be less than 1024 bytes! "\nclass %s: public %s {\n" "public:\n" " %s(int x, int y, int w, int h, const char *l=NULL)\n" " : %s(x, y, w, h, l) { }\n" " void *_parent_class;\n" "};\n", sys_menubar_proxy_name(), sys_menubar_name(), sys_menubar_proxy_name(), sys_menubar_name() ); } } } void Fl_Menu_Bar_Type::write_code1(Fd_Code_Writer& f) { super::write_code1(f); if (is_sys_menu_bar() && is_in_class()) { f.write_c("%s((%s*)%s)->_parent_class = (void*)this;\n", f.indent(), sys_menubar_proxy_name(), name() ? name() : "o"); } } //void Fl_Menu_Bar_Type::write_code2(Fd_Code_Writer& f) { // super::write_code2(f); //} //////////////////////////////////////////////////////////////// // Shortcut entry item in panel: void shortcut_in_cb(Fl_Shortcut_Button* i, void* v) { if (v == LOAD) { if (current_widget->is_button()) i->value( ((Fl_Button*)(current_widget->o))->shortcut() ); else if (current_widget->is_a(ID_Input)) i->value( ((Fl_Input_*)(current_widget->o))->shortcut() ); else if (current_widget->is_a(ID_Value_Input)) i->value( ((Fl_Value_Input*)(current_widget->o))->shortcut() ); else if (current_widget->is_a(ID_Text_Display)) i->value( ((Fl_Text_Display*)(current_widget->o))->shortcut() ); else { i->hide(); i->parent()->hide(); return; } //i->default_value( i->value() ); // enable the "undo" capability of the shortcut button i->show(); i->parent()->show(); i->redraw(); } else { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_button()) { Fl_Button* b = (Fl_Button*)(((Fl_Widget_Type*)o)->o); if (b->shortcut() != (int)i->value()) mod = 1; b->shortcut(i->value()); if (o->is_a(ID_Menu_Item)) ((Fl_Widget_Type*)o)->redraw(); } else if (o->selected && o->is_a(ID_Input)) { Fl_Input_* b = (Fl_Input_*)(((Fl_Widget_Type*)o)->o); if (b->shortcut() != (int)i->value()) mod = 1; b->shortcut(i->value()); } else if (o->selected && o->is_a(ID_Value_Input)) { Fl_Value_Input* b = (Fl_Value_Input*)(((Fl_Widget_Type*)o)->o); if (b->shortcut() != (int)i->value()) mod = 1; b->shortcut(i->value()); } else if (o->selected && o->is_a(ID_Text_Display)) { Fl_Text_Display* b = (Fl_Text_Display*)(((Fl_Widget_Type*)o)->o); if (b->shortcut() != (int)i->value()) mod = 1; b->shortcut(i->value()); } if (mod) set_modflag(1); } } fltk-1.4.3/fluid/shell_command.h0000644000175000017500000001014015004135251016662 0ustar albrechtalbrecht// // FLUID main entry for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_SHELL_COMMAND_H #define _FLUID_SHELL_COMMAND_H #include "fluid.h" #include "../src/Fl_String.H" #include #include #include #if defined(_WIN32) && !defined(__CYGWIN__) # include # include # include # include # include # include #else # include #endif struct Fl_Menu_Item; class Fl_Widget; class Fl_Preferences; char preferences_get(Fl_Preferences &prefs, const char *key, Fl_String &value, const Fl_String &defaultValue); char preferences_set(Fl_Preferences &prefs, const char *key, const Fl_String &value); void show_terminal_window(); void run_shell_command(const Fl_String &cmd, int flags); bool shell_command_running(void); class Fl_Process { public: Fl_Process(); ~Fl_Process(); FILE *popen(const char *cmd, const char *mode="r"); int close(); FILE * desc() const; char * get_line(char * line, size_t s) const; int get_fileno() const; #if defined(_WIN32) && !defined(__CYGWIN__) protected: HANDLE pin[2], pout[2], perr[2]; char ptmode; PROCESS_INFORMATION pi; STARTUPINFO si; static bool createPipe(HANDLE * h, BOOL bInheritHnd=TRUE); private: FILE * freeHandles(); static void clean_close(HANDLE& h); #endif protected: FILE * _fpt; }; class Fd_Shell_Command { public: enum { ALWAYS, NEVER, MAC_ONLY, UX_ONLY, WIN_ONLY, MAC_AND_UX_ONLY, USER_ONLY, HOST_ONLY, ENV_ONLY }; // conditions enum { SAVE_PROJECT = 1, SAVE_SOURCECODE = 2, SAVE_STRINGS = 4, SAVE_ALL = 7, DONT_SHOW_TERMINAL = 8, CLEAR_TERMINAL = 16, CLEAR_HISTORY = 32 }; // flags Fd_Shell_Command(); Fd_Shell_Command(const Fd_Shell_Command *rhs); Fd_Shell_Command(const Fl_String &in_name); Fd_Shell_Command(const Fl_String &in_name, const Fl_String &in_label, Fl_Shortcut in_shortcut, Fd_Tool_Store in_storage, int in_condition, const Fl_String &in_condition_data, const Fl_String &in_command, int in_flags); Fl_String name; Fl_String label; Fl_Shortcut shortcut; Fd_Tool_Store storage; int condition; // always, hide, windows only, linux only, mac only, user, machine Fl_String condition_data; // user name, machine name Fl_String command; int flags; // save_project, save_code, save_string, ... Fl_Menu_Item *shell_menu_item_; void run(); void read(Fl_Preferences &prefs); void write(Fl_Preferences &prefs, bool save_location = false); void read(class Fd_Project_Reader*); void write(class Fd_Project_Writer*); void update_shell_menu(); bool is_active(); }; class Fd_Shell_Command_List { public: Fd_Shell_Command **list; int list_size; int list_capacity; Fl_Menu_Item *shell_menu_; public: Fd_Shell_Command_List(); ~Fd_Shell_Command_List(); Fd_Shell_Command *at(int index) const; void add(Fd_Shell_Command *cmd); void insert(int index, Fd_Shell_Command *cmd); void remove(int index); void clear(); void clear(Fd_Tool_Store store); // void move_up(); // void move_down(); // int load(const Fl_String &filename); // int save(const Fl_String &filename); void read(Fl_Preferences &prefs, Fd_Tool_Store storage); void write(Fl_Preferences &prefs, Fd_Tool_Store storage); void read(class Fd_Project_Reader*); void write(class Fd_Project_Writer*); void rebuild_shell_menu(); void update_settings_dialog(); static Fl_Menu_Item default_menu[]; static void menu_marker(Fl_Widget*, void*); static void export_selected(); static void import_from_file(); }; extern Fd_Shell_Command_List *g_shell_config; #endif // _FLUID_SHELL_COMMAND_H fltk-1.4.3/fluid/mergeback.h0000644000175000017500000000462615004135251016011 0ustar albrechtalbrecht// // MergeBack routines for the Fast Light Tool Kit (FLTK). // // Copyright 2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Matt: disabled #if 0 #ifndef _FLUID_MERGEBACK_H #define _FLUID_MERGEBACK_H #include #include "../src/Fl_String.H" #include const int FD_TAG_GENERIC = 0; const int FD_TAG_CODE = 1; const int FD_TAG_MENU_CALLBACK = 2; const int FD_TAG_WIDGET_CALLBACK = 3; const int FD_TAG_LAST = 3; const int FD_MERGEBACK_ANALYSE = 0; const int FD_MERGEBACK_INTERACTIVE = 1; const int FD_MERGEBACK_APPLY = 2; const int FD_MERGEBACK_APPLY_IF_SAFE = 3; /** Class that implements the MergeBack functionality. \see merge_back(const Fl_String &s, int task) */ class Fd_Mergeback { protected: /// Pointer to the C++ code file. FILE *code; /// Current line number in the C++ code file. int line_no; /// Set if there was an error reading a tag. int tag_error; /// Number of code blocks that were different than the CRC in their tag. int num_changed_code; /// Number of generic structure blocks that were different than the CRC in their tag. int num_changed_structure; /// Number of code block that were modified, but a type node by that uid was not found. int num_uid_not_found; /// Number of modified code block where the corresponding project block also changed. int num_possible_override; void unindent(char *s); Fl_String read_and_unindent_block(long start, long end); void analyse_callback(unsigned long code_crc, unsigned long tag_crc, int uid); void analyse_code(unsigned long code_crc, unsigned long tag_crc, int uid); int apply_callback(long block_end, long block_start, unsigned long code_crc, int uid); int apply_code(long block_end, long block_start, unsigned long code_crc, int uid); public: Fd_Mergeback(); ~Fd_Mergeback(); int merge_back(const Fl_String &s, const Fl_String &p, int task); int ask_user_to_merge(const Fl_String &s, const Fl_String &p); int analyse(); int apply(); }; extern int merge_back(const Fl_String &s, const Fl_String &p, int task); #endif // _FLUID_MERGEBACK_H #endif fltk-1.4.3/fluid/README_fl.txt0000644000175000017500000004630115004135251016073 0ustar albrechtalbrecht FLUID .fl file format version 1.4 ================================= This text explains the history of the FLUID .fl format and faithfully describes all elements of the format and its caveats. History ------- FLUID, the Fast Light User Interface Designer was started in the 1990's loosely based on 'fdesign', a GUI designer that came with the 'Forms Library', later 'XForms Library'. FLUID's .fl file format was originally compatible with the fdesign '.fd' format, but evolved somewhat ad hoc to become what it is today. Basics ====== FLUID is a visual editor, storing the user interface description in .fl files with the ability to create ready-to-compile C++ code. FLUID can also be used as a command line tool to translate .fl files directly into source code. It can be integrated into build scripts and most IDEs as an external tool. .fl files describe a hierarchical graphical user interface for the 'FLTK' library as a tree structure. Elements in the tree can be FLTK Widgets as well as functional components like classes, C++ functions, variables, etc. . FLUID calls all elements in the hierarchy 'Type'. Line Endings ------------ Although FLUID writes all line endings as '\n', readers should tolerate '\r\n' Windows line endings as well. Except for the Header, the FLUID reader does not differentiate between a line ending and a space character outside of a 'word'. Unicode ------- FLUID does not handle UTF-8 characters in any special manner (unescaped), but stores and reads them verbatim, making UTF-8 character sequences perfectly legal in .fl files. FLUID can translate UTF-8 into escape sequences when writing source code files. File Structure -------------- .fl files start with a 'Header', followed by a list of 'Options', followed by a hierarchy of 'Type' entries, the 'Tree'. All elements besides the Header are composed of 'Words', 'Strings', and 'Groups'. Words ----- Words can be any sequence of ASCII and UTF-8 characters. Words are always case-sensitive. Simple Words that are composed of 'a'-'z', 'A'-'Z', '0'-'9', and '_' only are written verbatim, followed by a space or newline. All other character sequences are bracketed between ‘{‘ and ‘}’ without padding spaces. For example, an empty word with no characters is written as '{}', and ".hello" is written as '{.hello}'. The special characters ‘\’ and ‘#’ are escaped by prepending the ‘\’ character, so "#define" is written as '{\#define}`. The characters ‘{‘ and ‘}’ are also escaped with a '\' unless every opening ‘{‘ in the Word is matched with a closing ‘}’. Note: line endings and the following indents are copied verbatim and become significant within a Word. Strings ------- Strings are generated with 'printf' statements in the hope that the generated text can be read back as one Word, set against a corresponding 'scanf' to retrieve the original values. Note: As there are no defined start and end markers to a String, a reader must know when these Strings appear and be prepared to read them correctly, even if the String itself is not useful to the reader. Note: All Strings that are generated by the current FLUID source code can be read back as a single Word. Groups ------ To create a hierarchy, Types can be grouped within Types. A Group starts with a lone '{' and ends with a lone '}'. Note: To know whether a '{' character starts a Word or a Group, the reader must know its position within the Type sequence (see 'Types' below). Elements ======== Header ------ The Header for any .fl file is # data file for the Fltk User Interface Designer (fluid) followed by a newline, followed by version where 'v' is the version number as in FL_VERSION (major*1.0 + minor * 0.01 + patch * 0.0001). So for FLTK 1.3.4, 'v' would be 1.0304 Note: the version number corresponds not so much to the version of FLUID, but to the version of the underlying FLTK library. So unless the version of FLTK is finalised, the file format in the GitHub master branch can still change unexpectedly. Note: if the version number is above the internal version number, FLUID will report an error and continue reading, hoping for the best. There are no other uses inside the FLUID reader except for features for the discontinued fltk2 which is beyond the scope of this document. Note: fdesign files (.fd) start with the text "Magic:". FLUID can read these files, but Forms/XForms files are beyond the scope of this document. Options ------- Options are usually comprised of a Word, two Words, or a Word and a String. If an Option is missing, a default value is assumed. "Magic:" : used by fdesign, not written by FLUID "define_in_struct" : no longer used "do_not_include_H_from_C" : don’t generate #include “myDesign.h” "use_FL_COMMAND" : use macOS CMD key instead of Ctrl "utf8_in_src" : allow UTF-8 when writing source code, otherwise escape UTF-8 sequences in source code "avoid_early_includes" : generate the '#include ' statement late "i18n_type" : integer 0=default=none, 1=gettext, 2=catgets --- the following list is valid until June 2023 "i18n_function" : function name, e.g. “gettext” "i18n_static_function" : function name, e.g. “gettext_noop” "i18n_file" : file name "i18n_set" : string --- the following list is valid from June 2023 "i18n_gnu_function" : function name, e.g. “gettext” "i18n_gnu_static_function" : function name, e.g. “gettext_noop” "i18n_pos_file" : file name "i18n_pos_set" : string --- end of June 2023 changes "i18n_include" : file name, e.g. “” "i18n_conditional" : string "header_name" : can be the full filename or just the extension, e.g. “.h” in which case FLUID will use the same filename as the .fl file. "code_name" : can be the full filename or just the extension, e.g. “.cxx”. "snap" : starting in V1.4 from May 2023, the 'snap' keyword can be used to store the selected layout and preset and include more suites of presets. The following block can be skipped by reading it as a single word. The format looks like this: snap { optional snap Word since 5.2023 ver 1 version of following data current_suite {My Test} opt. name of suite selected at save time current_preset 1 opt. preset selected within suite suite { optional suite store within project name {MyLayout v0.3} name of the layout preset { 1 3x preset, preset version (24 integers) values representing the layout preset } ... (two more presets) } ... (opt. more suites) } "gridx" : ignored "gridy" : ignored "shell_commands" : starting in V1.4 from Sep 2023, the 'shell_commands' keyword can be used to store user configurable shell commands in a project file. The following block can be skipped by reading it as a single word. shell_commands { command { name label shortcut (optional if not 0) condition (optional if not 0, see Fd_Shell_Command enum) condition_data (optional if not "") command (optional, but usually there) flags (optional if not 0, see Fd_Shell_Command 2nd enum) } (repeat as needed) } Note: There is no keyword that marks the end of the Options section. The Option list ends when a Word is not in the Options list and it is in the list of known Types. If the Word is neither an Option nor a vaild Type, FLUID will give an error message and try to continue to read the file. Using new Option keywords makes .fl files incompatible to earlier versions of FLUID. Due to the forgiving interpreter, files may still be read correctly despite error messages. If a Word is in the list of known Types, the Type is read, including optional children. No more Options are allowed beyond this point. Tree ==== If a keyword is read that is not in the Option list, we start reading Types. Types represent all possible entries in the hierarchy including C functions, class definitions, and of course all Widgets. A Type is any of the supported Widgets classes, or one of the following (case sensitive): Function, code, codeblock, decl, data, declblock, comment, class, widget_class Every Type keyword is followed by a Word, which is usually interpreted as the C++ name of the Type, followed by an opening `{`, a list of properties, and a closing ‘}’. If the Type has children, they are stored in a Group between another opening ‘{‘, followed by a list of Types, followed by a closing ‘}’. Fl_Group MyGroup { Type name start_of_options label Surprise ... Option parameter } { end_of_options start_of_children Fl_Button {} { Type name start_of_options label {Don't panic...!} Option parameter hide Option } end_of_options } end_of_children The file ends when there are no more Types. Note: the "class" Type may have an additional Word following immediately after the keyword. It contains the prefix for the class. A class definition may be written as: class FL_EXPORT MyClass { ...properties... } { ...children... } or without a prefix as class MyOtherClass { ...properties... } { ...children... } According to the source code, we know if the word after class is a prefix if the next word is not a lone '{'. We apologize for the inconvenience. Types ----- Type names are based on FLTK class names. Types derive properties from super Types loosely similar to FLTK. Note: the hierarchical dependency is implemented twice and somewhat conflicting in FLUID via the Fl_..._Type hierarchy, and by using '::is_some_type()' virtual functions, which does not always match the Type hierarchy. The list of known Types and their inheritance is: Fl_Type (note: can't be written) +-- Function +-- code +-- codeblock +-- decl +-- data +-- declblock +-- comment +-- class +-- Fl_Widget (note: can't be written) | +-- Fl_Window | | +-- widget_class | +-- Fl_Group | | +-- Fl_Pack | | +-- Fl_Flex | | +-- Fl_Table | | +-- Fl_Tabs | | +-- Fl_Scroll | | +-- Fl_Terminal | | +-- Fl_Tile | | +-- Fl_Wizard | | +-- Fl_Grid | +-- Fl_Menu_Type (note: can't be written) | | +-- Fl_Menu_Button | | +-- Fl_Choice | | +-- Fl_Input_Choice | | +-- Fl_Menu_Bar | | +-- Fl_ | +-- Fl_Box | +-- Fl_Button | | +-- Fl_Return_Button | | +-- Fl_Light_Button | | +-- Fl_Check_Button | | +-- Fl_Round_Button | +-- Fl_Repeat_Button | +-- Fl_Browser | +-- Fl_Check_Browser | +-- Fl_Tree | +-- Fl_File_Browser | +-- Fl_Counter | +-- Fl_Spinner | +-- Fl_Input | | +-- Fl_Output | +-- Fl_File_Input | +-- Fl_Text_Display | +-- Fl_Text_Editor | +-- Fl_Clock | +-- Fl_Help_View | +-- Fl_Progress | +-- Fl_Adjuster | +-- Fl_Dial | +-- Fl_Roller | +-- Fl_Slider | | +-- Fl_Scrollbar | | +-- Fl_Value_Slider | +-- Fl_Value_Input | +-- Fl_Value_Output . Properties ---------- Properties have zero or one Words as their arguments. The number of arguments are defined per property per Type. The content of the argument Word is defined by the implementation of the property and can contain mutiple values, as described above in Strings. Properties are inherited from super Types. They can be limited to certain Types by calls to 'MyType->is_some_type()'. All properties are optional, some are mutually exclusive. Note: It is possible that the same property by name has different arguments when used in a different Type. Every node can have properties that it holds for its parent. Parent properties are stored as "parent_properties { ...list... }". If a node encounters this property tag, it must ask its parent to interpret the contents of that list. See Fl_Grid for an example. Type Fl_Type "uid" <4-digit-hex> : since Oct 2023, optional, a unique id for this node within the project file “label” : text “user_data” : a value or an expression “user_data_type” : usually “void*” or “long” “callback” : a function name or a function body “comment” : one or many lines of text “open” : Group content visible in the FLUID tree browser “selected” : Type was selected in tree view Type "Function" : function signature none or "private" or "protected" : for methods in classes, or to mark functions static in a file, default is public “C” : if set, function is extern “C” “return_type” : C or C++ type descriptor, can start with “virtual” and/or “static” to further define the function. ... : inherits more from Fl_Type Type codeblock : C++ code, for example "if (test())" "after" : C++ code or comment following the closing '}' ... : inherits more from Fl_Type Type "decl" : C++ code to declare a variable or class member none or "public" or "private" or "protected" : for declarations within classes defaults to "private" none or "local" or "global": for declaration in the code body defaults to "global" ... : inherits more from Fl_Type Type "data" : C++ variable name "filename" : name or path as entered by user, forward slashes "textmode" : defaults to binary mode "compressed" : defaults to not compressed ... : inherits more from decl Type "declblock" : C++ code none or "public" or "protected" : defaults to private (obsolete) "map" : integer value, default is 2 (CODE_IN_SOURCE), see Fl_DeclBlock_Type::write_map_ "after" : C++ code or comment following the block ... : inherits more from Fl_Type Type "comment" : comment text "in_source" or "not_in_source": default to in_source "in_header" or "not_in_header": default to in_header ... : inherits more from Fl_Type Type "class" : prefix, class name none or "private" or "protected" : defaults to public ":" : name of super class ... : inherits more from Fl_Type Type "Fl_Widget" : C++ variable name none or "private" or "protected" : default is public "xywh" : "{%d %d %d %d}" x, y, w, h "tooltip" : tooltip text "scale_image : "{%d %d}" width, height, default is 0, 0 "image" : image name "compress_image" : integer (1.4 and up, only if `image` is set) "bind_image" : integer (1.4 and up) "scale_deimage : "{%d %d}" width, height, default is 0, 0 "deimage" : deactivated image name "compress_deimage" : integer (1.4 and up, only if `deimage` is set) "bind_deimage" : integer (1.4 and up) "type" : integer "box" : text or integer (see FLTK boxtypes) "down_box" : (is_button() or Fl_Input_choice" or is_menu_button()) text or integer (see FLTK boxtypes) "value" : (is_button()) integer "value" : (is_valuator(), is_spinner()) double "color" : If Word starts with "0x", the rest of the field is a hex number. If two integers follow, this is color and selection_color (deprecated). If one integer follows, it's the color index. "selection_color" : integer color index "labeltype" : If the Word is "image", TBD. Or one of "NORMAL_LABEL", "SHADOW_LABEL", "ENGRAVED_LABEL", "EMBOSSED_LABEL", or "NO_LABEL" "labelfont" : integer, font index "labelsize" : integer "labelcolor" : integer, color index "align" : integer, see Fl_Align "h_label_margin" : integer, horizontal label margin "v_label_margin" : integer, vertical label margin "image_spacing" : integer, see Fl_Widget::label_image_spacing() "when" : integer, see Fl_When "minimum" : (is_valuator(), is_spinner()) double "maximum" : (is_valuator(), is_spinner()) double "step" : (is_valuator(), is_spinner()) double "slider_size" : (is_valuator()==2) double "size" : (is_valuator()==2) double "textfont" : integer, font index "textsize" : integer "textcolor" : integer, color index "hide" : default visible "deactivate" : default active "resizable" : default fixed "hotspot" : make a Widget a hotspot "divider" : add a divider under a menu item "class" : superclass "shortcut" : integer "code0" or "code1" or "code2" or "code3" : C++ extra code lines "extra_code" : C++ extra code lines ... : inherits more from Fl_Type Type "Fl_Button" : C++ variable name "compact" : integer, set the flag for compact buttons, defaults to 0 Type "Fl_Flex" : C++ variable name "margins" : this Word is written with printf as "{%d %d %d %d}", left, top, right, bottom "gap" : integer "fixed_size_tuples" : this Word is written with printf "{%d", where %d encodes the number of tuples to follow, and zero or more " %d %d" containing the index and size of that child, followed by a '}'. ... : inherits more from Fl_Group Type "Fl_Window" : C++ variable name none or "modal", or "non_modal": defaults to not modal (which is different to non_modal!) "visible" : show window when opening file in FLUID "noborder" : borderless window "xclass" : see FLTK "size_range" : this Word is written with printf as "{%d %d %d %d}", min_w, min_h, max_w, max_h "xywh" : this Word is written with printf as "{%d %d %d %d}", x, y, w, h. This as actually read in the Fl_Widget Type, but here it ensures that the window is not created as a subwindow. ... : inherits more from Fl_Widget (not Fl_Group) Type "Fl_Grid" : C++ variable name "dimensions" : {int rows, int cols} "margin" : {int left, int top, int right, int bottom} "gap" : {int row gap, int col gap} "rowheights" : {int h, ...*rows} "rowweights" : {int h, ...*rows} "rowgaps" : {int h, ...*rows} "colwidths" : {int h, ...*cols} "colweights" : {int h, ...*cols} "colgaps" : {int h, ...*cols} Fl_Grid can also produce parent properties in their children "location" : {int row, int col} "colspan" " "rowspan" "align" : see Fl_Grid_Align enum "min_size" : {int width, int height} Please report errors and omissions to the fltk.coredev or fltk.general Google group. Thank you. - Matthias fltk-1.4.3/fluid/settings_panel.cxx0000644000175000017500000053713415004135251017470 0ustar albrechtalbrecht// // Setting and shell dialogs for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #include "settings_panel.h" #include "undo.h" #include #include #include #include #include "../src/flstring.h" void scheme_cb(Fl_Scheme_Choice *, void *); int w_settings_shell_list_selected; static void cb_Comments(Fl_Choice* o, void* v) { Fl_Font *font = (Fl_Font*)o->user_data(); if (v == LOAD) { o->value(*font); } else { *font = (int)o->value(); widget_browser->redraw(); widget_browser->save_prefs(); } } static void cb_Color_Chip(Fl_Button* o, void* v) { Fl_Color *color = (Fl_Color*)o->user_data(); if (v == LOAD) { o->color(*color); o->redraw(); } else { Fl_Color d = fl_show_colormap(*color); *color = d; o->color(d); widget_browser->redraw(); widget_browser->save_prefs(); } } static void cb_Color_Choice(Fl_Menu_Button* o, void* v) { if (v != LOAD) { Fl_Color *color = (Fl_Color*)o->user_data(); Fl_Color d = (Fl_Color)(o->mvalue()->argument()); *color = d; o->parent()->do_callback(o->parent(), LOAD); widget_browser->redraw(); widget_browser->save_prefs(); } } Fl_Double_Window *script_panel=(Fl_Double_Window *)0; static void cb_script_panel(Fl_Double_Window*, void*) { if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape) return; // ignore Escape script_panel->hide(); // otherwise hide..; } Fl_Text_Editor *script_input=(Fl_Text_Editor *)0; Fl_Return_Button *script_panel_ok=(Fl_Return_Button *)0; Fl_Button *script_panel_cancel=(Fl_Button *)0; Fl_Double_Window* make_script_panel() { { Fl_Double_Window* o = script_panel = new Fl_Double_Window(540, 180, "Shell Script Editor"); script_panel->labelsize(11); script_panel->callback((Fl_Callback*)cb_script_panel); { script_input = new Fl_Text_Editor(10, 10, 520, 130); script_input->box(FL_DOWN_BOX); script_input->labelsize(11); script_input->textfont(4); script_input->textsize(11); script_input->when(FL_WHEN_RELEASE | FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY); Fl_Group::current()->resizable(script_input); script_input->buffer(new Fl_Text_Buffer); } // Fl_Text_Editor* script_input { Fl_Group* o = new Fl_Group(10, 150, 520, 20); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); { script_panel_ok = new Fl_Return_Button(400, 150, 60, 20, "OK"); script_panel_ok->labelsize(11); script_panel_ok->window()->hotspot(script_panel_ok); } // Fl_Return_Button* script_panel_ok { script_panel_cancel = new Fl_Button(470, 150, 60, 20, "Cancel"); script_panel_cancel->labelsize(11); } // Fl_Button* script_panel_cancel { Fl_Box* o = new Fl_Box(10, 150, 380, 20); o->labelsize(11); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o script_panel->set_modal(); o->size_range(200, 150); script_panel->end(); } // Fl_Double_Window* script_panel // Enable line numbers script_input->linenumber_width(60); script_input->linenumber_size(script_input->Fl_Text_Display::textsize()); return script_panel; } Fl_Double_Window *settings_window=(Fl_Double_Window *)0; Fl_Tabs *w_settings_tabs=(Fl_Tabs *)0; static void cb_w_settings_tabs(Fl_Tabs* o, void* v) { propagate_load(o, v); } Fl_Group *w_settings_general_tab=(Fl_Group *)0; #include static const unsigned char idata_general_64[] = {137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,96,0,0,0,64,8,4,0,0,0, 79,61,186,133,0,0,8,57,73,68,65,84,104,222,205,154,107,112,85,213,21,199,127, 151,60,185,36,18,66,204,131,120,155,82,136,163,131,4,41,180,130,36,2,117,8,15, 173,58,109,103,168,97,42,67,135,78,167,84,16,59,118,192,41,29,201,244,3,14,182, 14,62,74,77,149,42,12,226,180,160,130,19,32,136,144,34,193,240,104,136,52,193, 18,196,16,200,131,128,121,191,47,185,247,158,126,72,206,221,251,60,238,189,39, 112,46,115,247,249,178,207,217,123,159,179,214,218,107,173,255,90,107,31,176, 187,37,81,72,13,237,184,25,196,135,130,130,143,65,220,180,83,67,33,73,68,120, 203,162,114,152,108,179,203,199,89,178,34,155,129,210,128,196,171,87,73,36,147, 63,11,119,72,6,220,60,108,231,39,71,217,204,64,108,200,57,177,204,180,243,147, 209,182,50,112,175,191,167,188,231,72,197,65,52,224,65,225,58,43,20,28,195,99, 223,139,92,6,114,212,206,115,142,185,196,73,3,110,86,59,222,80,111,210,34,87, 133,198,169,157,4,162,52,3,81,36,138,155,187,35,149,129,120,225,229,83,116,12, 140,98,172,184,153,100,231,190,223,202,171,82,153,137,135,47,185,161,123,158,41, 196,156,233,87,120,149,1,9,193,146,201,160,94,183,54,141,217,140,226,20,141,225, 118,148,73,108,167,29,47,30,218,216,71,174,127,7,147,216,196,13,225,44,15,40,77, 186,107,135,236,74,27,217,64,130,95,132,115,41,166,29,47,94,58,217,65,114,56, 201,143,231,51,157,79,175,100,5,78,150,114,69,198,95,151,114,204,192,64,137,30, 147,107,200,39,129,149,124,201,77,205,200,49,156,225,99,96,155,73,152,224,165, 89,71,130,50,77,57,99,96,224,164,114,191,126,229,0,205,120,77,194,141,183,71, 66,82,212,8,230,174,96,131,201,124,135,222,229,36,243,56,15,51,90,55,109,144, 38,174,208,175,181,191,4,157,169,12,189,47,135,58,254,107,149,40,135,101,242, 93,156,9,237,193,103,243,20,51,112,201,78,83,69,54,186,168,231,52,123,249,79, 232,111,53,49,203,96,230,183,189,3,219,69,8,176,148,181,164,114,141,30,205,132, 251,89,199,175,153,77,154,6,194,132,164,226,73,101,42,115,152,200,101,58,52,99, 233,20,176,26,39,85,234,131,68,82,248,216,222,29,152,79,137,26,231,76,103,51,83, 232,161,150,227,236,163,122,120,66,1,203,185,143,24,11,175,114,83,205,54,246, 162,190,237,113,114,153,72,2,213,172,163,82,76,202,231,115,59,25,40,103,150,218, 45,98,201,240,198,221,164,145,51,236,231,48,235,249,57,169,35,48,167,38,118, 178,133,37,60,198,116,38,12,75,198,203,62,158,21,83,62,99,129,125,12,44,96,191, 42,220,103,88,39,34,6,192,199,13,174,49,137,187,70,232,208,218,185,194,4,82,52, 161,64,43,47,243,190,176,250,133,148,218,101,3,69,100,15,117,156,252,129,201,6, 39,148,97,170,245,193,219,104,210,25,163,147,159,19,39,187,5,101,99,196,205, 237,197,66,89,252,80,237,254,130,41,97,5,250,105,252,74,222,119,11,233,167,149, 88,104,145,240,138,249,254,8,32,120,243,209,78,61,77,12,224,32,142,76,92,36,89, 146,85,34,243,4,142,221,197,34,138,236,96,32,93,221,105,39,221,220,12,153,116, 41,92,163,140,35,156,160,205,15,109,121,60,202,28,241,162,32,30,106,64,214,206, 84,123,108,96,10,75,134,190,60,72,5,9,184,12,40,43,55,15,167,120,149,55,184,40, 161,110,63,53,28,164,137,52,210,131,238,67,43,31,179,70,150,196,238,208,168,103, 133,129,22,86,16,63,212,237,226,48,94,238,97,92,0,89,122,56,194,70,78,153,142, 93,228,44,46,178,2,176,160,112,137,191,179,89,235,168,126,79,167,29,12,116,16, 71,158,248,110,5,117,164,144,97,170,125,229,108,224,155,128,47,106,227,60,57, 100,154,170,78,25,175,242,145,252,200,203,75,28,180,203,141,30,167,139,92,161, 252,117,156,32,1,151,33,238,109,226,117,173,244,251,248,150,30,162,5,64,183,209, 203,15,12,142,160,133,15,249,147,31,211,1,232,225,69,94,67,177,211,195,61,194, 37,109,224,251,182,46,96,110,80,182,200,227,189,252,153,73,196,19,79,54,175, 211,47,70,182,42,13,186,149,127,211,135,212,53,214,107,71,214,115,226,207,153, 195,30,124,226,193,120,3,182,150,202,178,95,198,11,124,195,0,3,124,205,26,126, 41,220,203,33,218,13,121,146,198,3,239,33,143,47,194,145,212,95,103,169,216, 214,100,57,77,7,160,158,195,50,118,239,213,12,126,192,187,66,31,175,27,146,105, 167,176,229,215,88,106,200,182,109,171,74,248,168,81,187,19,12,154,220,68,159, 144,255,91,134,181,91,212,225,54,90,117,67,99,229,90,87,141,188,203,246,151,85, 226,84,255,25,101,88,234,22,221,78,174,26,86,54,8,151,216,106,32,34,74,128,215, 8,195,42,123,11,91,193,223,235,184,83,31,10,142,245,138,234,166,125,134,205, 145,138,47,247,24,86,126,71,24,77,138,65,51,189,194,6,220,225,101,224,1,85,142, 181,116,7,54,197,209,172,54,172,124,94,141,64,146,13,254,171,131,90,177,75,83, 71,70,211,72,38,167,113,128,85,194,78,187,12,89,127,190,184,89,201,211,154,193, 229,44,23,128,146,22,216,252,225,55,124,66,70,56,24,152,207,41,22,203,243,91,13, 69,187,31,201,174,253,31,188,233,7,178,34,138,132,134,45,212,100,116,67,193, 158,134,162,199,40,231,81,187,109,229,69,250,100,172,76,87,54,43,213,134,226,85, 133,242,99,45,162,246,210,72,147,118,229,83,74,165,97,93,149,242,178,146,174,93, 217,199,70,107,194,181,22,11,253,145,66,57,13,152,207,75,44,48,169,253,36,146, 202,89,127,22,0,196,144,72,162,92,170,200,102,189,116,10,34,82,201,251,152,70, 27,151,229,149,143,16,195,81,123,24,152,200,123,114,220,182,138,231,200,9,144, 9,165,227,226,188,204,130,166,101,179,145,135,76,5,27,141,139,7,137,149,195, 127,7,223,103,31,223,218,193,64,1,63,81,125,79,58,27,89,70,70,64,151,62,138,44, 166,209,195,69,147,177,39,89,207,67,1,83,64,7,227,200,97,50,135,196,163,88,234, 57,97,71,74,121,183,74,111,50,175,144,23,34,165,140,102,6,46,22,115,80,151,82, 46,100,54,169,33,176,108,28,63,229,119,101,228,74,229,4,91,146,250,102,134,15, 232,218,24,109,225,24,210,65,26,79,144,199,117,90,105,193,65,10,227,73,179,152, 212,199,176,39,247,103,226,182,214,30,6,74,232,86,235,86,37,76,53,49,94,51,85, 26,111,128,43,43,173,151,99,114,72,126,192,30,28,184,34,52,113,23,95,133,181, 46,84,205,54,57,15,252,202,30,6,224,21,6,85,161,236,209,1,152,66,43,103,13,168, 28,186,245,80,73,139,46,158,234,100,191,192,100,15,127,181,15,7,234,88,132,107, 168,91,197,84,178,135,249,246,208,72,41,239,178,137,104,38,90,44,121,169,185, 209,78,94,224,42,110,156,36,12,191,205,199,81,10,229,250,192,122,251,24,128,75, 20,168,246,210,192,116,82,233,231,2,197,108,229,45,254,199,32,95,208,69,186, 174,84,27,184,114,116,158,34,182,50,200,5,14,82,69,55,177,36,18,195,5,254,66, 131,40,237,254,150,175,173,16,102,61,70,223,141,223,61,60,205,60,170,217,171,59, 68,121,128,101,204,39,51,168,76,124,92,163,148,247,57,167,11,3,159,224,65,142, 179,67,60,250,132,39,173,145,101,243,17,211,92,22,51,131,239,50,198,100,172,143, 58,42,248,148,35,86,74,105,115,76,177,240,54,219,114,6,67,254,76,163,160,184, 148,103,149,42,67,192,118,94,121,94,113,41,86,214,227,97,101,120,242,129,237, 108,55,41,53,41,180,227,209,86,39,254,77,175,137,252,143,234,207,237,60,180,155, 150,174,118,241,78,184,50,178,53,148,233,72,56,199,90,238,165,128,58,249,113, 173,137,91,237,215,135,120,87,121,134,201,172,162,82,203,62,39,229,115,38,251, 91,10,219,232,196,135,143,46,138,89,228,143,44,82,40,164,89,168,65,177,65,133, 62,148,149,164,133,77,254,210,121,52,249,124,68,7,62,124,244,240,175,145,100, 99,183,90,41,112,145,11,148,209,168,195,161,108,42,212,56,99,167,156,157,1,112, 64,40,118,47,51,185,96,72,168,231,18,67,25,151,71,86,21,186,181,191,85,234,249, 192,244,249,101,90,85,6,26,241,233,180,179,95,6,225,6,195,218,70,118,221,153, 178,74,112,132,234,21,65,129,86,144,94,57,51,105,212,157,144,223,209,186,80,240, 230,167,178,75,103,153,62,249,232,168,206,206,79,218,251,207,220,57,230,13,117, 78,83,204,120,198,18,7,12,208,73,7,21,98,86,119,228,50,224,79,64,78,115,122,56, 93,71,174,249,12,181,139,145,203,64,57,110,109,113,182,207,56,103,144,114,34, 184,29,10,25,40,124,74,68,183,76,202,131,254,252,125,210,238,159,191,163,108, 102,160,155,127,210,133,147,49,68,161,224,192,1,40,120,241,208,73,37,239,176, 150,102,123,63,248,127,27,97,180,206,27,14,172,151,0,0,0,0,73,69,78,68,174,66, 96,130}; static Fl_Image *image_general_64() { static Fl_Image *image = NULL; if (!image) image = new Fl_PNG_Image("general_64.png", idata_general_64, 2162); return image; } static void cb_(Fl_Group* o, void* v) { propagate_load(o, v); } Fl_Scheme_Choice *scheme_choice=(Fl_Scheme_Choice *)0; Fl_Check_Button *tooltips_button=(Fl_Check_Button *)0; static void cb_tooltips_button(Fl_Check_Button*, void*) { Fl_Tooltip::enable(tooltips_button->value()); fluid_prefs.set("show_tooltips", tooltips_button->value()); } Fl_Check_Button *completion_button=(Fl_Check_Button *)0; static void cb_completion_button(Fl_Check_Button*, void*) { fluid_prefs.set("show_completion_dialogs", completion_button->value()); } Fl_Check_Button *openlast_button=(Fl_Check_Button *)0; static void cb_openlast_button(Fl_Check_Button*, void*) { fluid_prefs.set("open_previous_file", openlast_button->value()); } Fl_Check_Button *prevpos_button=(Fl_Check_Button *)0; static void cb_prevpos_button(Fl_Check_Button*, void*) { fluid_prefs.set("prev_window_pos", prevpos_button->value()); } Fl_Check_Button *show_comments_button=(Fl_Check_Button *)0; static void cb_show_comments_button(Fl_Check_Button*, void*) { show_comments = show_comments_button->value(); fluid_prefs.set("show_comments", show_comments); redraw_browser(); } static void cb_1(Fl_Group* o, void* v) { propagate_load(o, v); } Fl_Spinner *recent_spinner=(Fl_Spinner *)0; static void cb_recent_spinner(Fl_Spinner*, void*) { fluid_prefs.set("recent_files", recent_spinner->value()); load_history(); } Fl_Check_Button *use_external_editor_button=(Fl_Check_Button *)0; static void cb_use_external_editor_button(Fl_Check_Button*, void*) { G_use_external_editor = use_external_editor_button->value(); fluid_prefs.set("use_external_editor", G_use_external_editor); redraw_browser(); } Fl_Input *editor_command_input=(Fl_Input *)0; static void cb_editor_command_input(Fl_Input*, void*) { strncpy(G_external_editor_command, editor_command_input->value(), sizeof(G_external_editor_command)-1); G_external_editor_command[sizeof(G_external_editor_command)-1] = 0; fluid_prefs.set("external_editor_command", G_external_editor_command); redraw_browser(); } Fl_Check_Button *guides_button=(Fl_Check_Button *)0; Fl_Check_Button *restricted_button=(Fl_Check_Button *)0; Fl_Check_Button *ghosted_outline_button=(Fl_Check_Button *)0; Fl_Group *w_settings_project_tab=(Fl_Group *)0; static void cb_w_settings_project_tab(Fl_Group* o, void* v) { propagate_load(o, v); } static const unsigned char idata_document_64[] = {137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,96,0,0,0,64,8,4,0,0,0, 79,61,186,133,0,0,3,102,73,68,65,84,104,222,237,154,223,75,83,81,28,192,63,155, 115,58,171,153,191,42,140,2,75,115,41,69,20,73,61,244,3,67,176,68,122,168,8,234, 65,123,90,32,81,68,65,47,65,100,208,15,95,194,8,130,94,140,30,250,3,210,94,6, 65,15,162,15,21,250,160,145,62,68,141,182,39,205,205,156,211,181,173,135,221, 93,231,118,167,251,113,239,238,153,236,156,135,125,57,231,220,123,191,159,123, 239,247,215,221,129,244,90,39,223,9,16,206,178,7,113,97,71,135,102,199,151,181, 242,209,30,224,113,174,213,111,194,163,154,250,145,231,240,44,183,0,3,170,170, 31,65,232,203,86,41,83,26,107,143,70,133,50,74,51,184,148,31,95,252,144,145, 219,192,221,220,0,24,87,180,190,65,27,134,52,47,20,198,193,83,165,179,102,137, 144,14,128,49,42,214,178,63,3,128,9,89,238,98,150,247,42,33,152,244,112,102,167, 57,72,136,33,85,16,140,122,0,24,57,68,47,29,171,95,164,190,60,2,0,131,106,8,58, 1,168,135,160,27,128,90,8,58,2,168,131,160,43,64,18,132,222,60,2,136,32,60, 162,51,86,163,59,156,20,28,96,17,111,76,159,103,15,55,87,242,20,40,165,91,192, 64,102,160,88,150,223,50,26,119,23,131,120,98,7,14,11,25,137,183,203,210,48, 195,107,47,45,199,196,63,225,94,33,27,87,52,137,234,57,107,21,116,113,74,245, 179,230,52,153,107,230,33,67,56,112,179,156,90,189,32,26,128,145,6,174,115,137, 5,130,169,214,11,226,165,211,165,236,92,183,94,200,171,64,150,71,70,92,0,208, 206,6,194,120,249,131,159,176,194,156,25,43,149,20,137,12,224,103,132,65,62,51, 163,56,187,9,27,103,105,163,74,84,128,101,6,121,192,108,210,249,89,156,56,232, 193,78,181,152,54,48,65,223,26,234,71,219,75,62,42,248,126,1,0,130,124,193,153, 210,202,15,41,96,234,240,10,45,241,83,150,79,176,149,80,220,221,9,48,142,27,128, 105,188,212,136,7,16,98,94,206,128,175,81,159,224,135,22,232,151,0,60,138,249, 143,80,201,156,133,50,133,81,237,28,104,33,18,111,160,72,28,27,147,87,215,193, 225,184,185,176,52,46,12,128,129,18,73,242,240,137,169,4,128,69,126,201,241,218, 193,164,12,80,66,29,123,177,232,15,96,166,86,150,95,173,185,210,23,87,174,236, 226,42,151,99,10,125,157,108,160,152,230,12,143,116,242,132,55,171,63,166,232, 99,196,45,220,202,248,216,231,140,233,15,96,165,155,251,236,200,240,232,49,2, 250,123,161,109,116,211,138,147,57,217,68,127,243,66,250,194,112,128,14,44,9, 166,237,102,0,63,0,46,150,98,190,216,233,230,70,45,52,210,24,227,36,39,121,45,1, 236,166,157,205,9,0,211,188,147,0,150,196,138,3,134,184,223,168,172,166,223,47, 164,18,27,60,149,72,44,120,22,20,94,180,69,209,1,204,148,75,245,215,56,253,20, 39,148,57,115,114,0,179,102,157,110,107,2,96,165,129,31,0,184,165,114,38,89, 171,195,44,162,13,84,210,158,210,186,58,90,178,126,2,154,0,20,209,70,79,10,152, 247,216,39,170,17,87,97,167,158,65,166,20,140,56,50,127,140,243,28,201,50,10, 107,234,133,170,185,64,43,94,197,82,222,128,133,10,182,168,18,224,52,116,163,38, 106,52,249,144,82,136,196,5,0,157,82,137,208,74,64,117,241,77,245,12,51,140,75, 241,90,169,102,192,169,180,9,154,34,66,102,219,46,215,107,49,127,179,142,114,92, 11,47,52,18,5,240,101,244,143,110,90,87,210,164,217,152,83,125,239,174,82,159, 193,166,213,157,233,226,175,230,234,123,185,168,229,195,61,199,184,10,219,239, 147,239,104,255,202,153,244,20,250,15,100,60,232,29,230,9,101,148,0,0,0,0,73,69, 78,68,174,66,96,130}; static Fl_Image *image_document_64() { static Fl_Image *image = NULL; if (!image) image = new Fl_PNG_Image("document_64.png", idata_document_64, 927); return image; } Fl_Input *header_file_input=(Fl_Input *)0; static void cb_header_file_input(Fl_Input* o, void* v) { if (v == LOAD) { o->value(g_project.header_file_name.c_str()); } else { if (strcmp(g_project.header_file_name.c_str(), o->value())) { g_project.header_file_name = o->value(); set_modflag(1); } } } Fl_Input *code_file_input=(Fl_Input *)0; static void cb_code_file_input(Fl_Input* o, void* v) { if (v == LOAD) { o->value(g_project.code_file_name.c_str()); } else { if (strcmp(g_project.code_file_name.c_str(), o->value())) { g_project.code_file_name = o->value(); set_modflag(1); } } } Fl_Check_Button *include_H_from_C_button=(Fl_Check_Button *)0; static void cb_include_H_from_C_button(Fl_Check_Button* o, void* v) { if (v == LOAD) { o->value(g_project.include_H_from_C); } else { if (g_project.include_H_from_C != o->value()) { set_modflag(1); g_project.include_H_from_C = o->value(); } } } Fl_Check_Button *use_FL_COMMAND_button=(Fl_Check_Button *)0; static void cb_use_FL_COMMAND_button(Fl_Check_Button* o, void* v) { if (v == LOAD) { o->value(g_project.use_FL_COMMAND); } else { if (g_project.use_FL_COMMAND != o->value()) { set_modflag(1); g_project.use_FL_COMMAND = o->value(); } } } Fl_Check_Button *utf8_in_src_button=(Fl_Check_Button *)0; static void cb_utf8_in_src_button(Fl_Check_Button* o, void* v) { if (v == LOAD) { o->value(g_project.utf8_in_src); } else { if (g_project.utf8_in_src != o->value()) { set_modflag(1); g_project.utf8_in_src = o->value(); } } } Fl_Check_Button *avoid_early_includes_button=(Fl_Check_Button *)0; static void cb_avoid_early_includes_button(Fl_Check_Button* o, void* v) { if (v == LOAD) { o->value(g_project.avoid_early_includes); } else { if (g_project.avoid_early_includes != o->value()) { set_modflag(1); g_project.avoid_early_includes = o->value(); } } } Fl_Check_Button *w_proj_mergeback=(Fl_Check_Button *)0; static void cb_w_proj_mergeback(Fl_Check_Button* o, void* v) { if (v == LOAD) { o->value(g_project.write_mergeback_data); } else { if (g_project.write_mergeback_data != o->value()) { set_modflag(1); g_project.write_mergeback_data = o->value(); } } } Fl_Group *w_settings_layout_tab=(Fl_Group *)0; static void cb_w_settings_layout_tab(Fl_Group* o, void* v) { propagate_load(o, v); } static const unsigned char idata_layout_64[] = {137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,96,0,0,0,64,8,4,0,0,0, 79,61,186,133,0,0,1,168,73,68,65,84,104,222,237,154,49,75,3,49,20,199,127,119, 84,168,109,23,197,201,209,69,116,16,197,130,159,160,123,151,226,226,42,14,98, 29,244,35,184,56,59,250,77,244,27,88,113,171,90,144,66,41,116,180,72,75,45,120, 92,92,122,109,167,144,75,155,35,202,123,89,18,146,123,252,127,112,239,46,47, 121,144,206,78,232,16,161,28,181,136,14,53,28,218,21,99,103,226,147,246,205,185, 43,249,135,12,157,203,87,40,6,28,152,139,10,83,0,92,83,36,11,43,113,106,190,56, 151,194,241,94,210,41,144,215,46,28,51,154,246,215,141,221,207,61,85,118,1,16, 178,154,116,47,168,16,104,22,126,112,57,17,83,161,78,17,101,224,94,241,200,109, 50,216,32,36,94,62,192,84,243,38,59,26,0,136,201,79,0,214,216,166,100,228,94, 209,156,13,2,115,128,144,63,110,2,32,0,2,32,0,2,176,144,229,220,186,143,24,26, 174,84,140,125,4,104,112,195,138,209,86,2,218,62,2,116,233,74,12,72,16,47,102, 86,249,128,63,0,150,249,128,63,0,150,249,128,4,177,0,8,128,0,8,128,0,8,128,0,8, 128,0,8,128,0,8,128,0,184,55,171,156,184,199,155,246,146,175,109,121,76,152,25, 192,29,247,218,121,187,3,146,12,1,70,25,10,148,32,254,151,65,92,102,75,51,27, 208,231,193,111,128,26,85,205,87,40,224,157,103,62,125,6,200,83,210,150,26,20, 36,6,4,64,0,4,64,0,4,192,187,31,89,60,187,171,51,207,7,250,180,140,47,249,122, 243,131,216,84,86,144,2,182,201,110,242,167,117,92,118,249,196,145,139,173,196, 75,2,144,38,31,176,218,19,53,220,188,110,251,12,50,41,61,254,154,149,216,46, 219,234,153,20,127,159,185,12,250,99,90,14,203,239,127,120,165,154,78,208,47, 215,15,118,242,56,45,94,1,0,0,0,0,73,69,78,68,174,66,96,130}; static Fl_Image *image_layout_64() { static Fl_Image *image = NULL; if (!image) image = new Fl_PNG_Image("layout_64.png", idata_layout_64, 481); return image; } Fl_Choice *layout_choice=(Fl_Choice *)0; static void cb_layout_choice(Fl_Choice* o, void* v) { if (v == LOAD) { o->value(g_layout_list.current_suite()); } else { int index = o->value(); g_layout_list.current_suite(index); g_layout_list.update_dialogs(); } } Fl_Menu_Item menu_layout_choice[] = { {"FLTK", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {"Grid", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0} }; static void cb_2(Fl_Button*, void* v) { // Clone the current layout suite if (v == LOAD) return; Fl_String old_name = "Copy of "; old_name.append(g_layout_list[g_layout_list.current_suite()].name_); const char *new_name = fl_input("Enter a name for the new layout:", old_name.c_str()); if (new_name == NULL) return; g_layout_list.add(new_name); g_layout_list.update_dialogs(); } Fl_Menu_Button *w_layout_menu=(Fl_Menu_Button *)0; static void cb_w_layout_menu(Fl_Menu_Button*, void* v) { if (v == LOAD) { Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()]; if (suite.storage_ == FD_STORE_INTERNAL) { w_layout_menu_rename->deactivate(); for (int i=1; i<4; i++) w_layout_menu_storage[i]->deactivate(); w_layout_menu_delete->deactivate(); } else { w_layout_menu_rename->activate(); for (int i=1; i<4; i++) w_layout_menu_storage[i]->activate(); w_layout_menu_delete->activate(); } w_layout_menu_storage[suite.storage_]->setonly(); } } static void cb_w_layout_menu_rename(Fl_Menu_*, void*) { // Rename the current layout suite Fl_String old_name = g_layout_list[g_layout_list.current_suite()].name_; const char *new_name = fl_input("Enter a new name for the layout:", old_name.c_str()); if (new_name == NULL) return; g_layout_list.rename(new_name); g_layout_list.update_dialogs(); } static void cb_w_layout_menu_storage(Fl_Menu_*, void*) { Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()]; suite.storage(FD_STORE_INTERNAL); g_layout_list.update_dialogs(); } static void cb_w_layout_menu_storage1(Fl_Menu_*, void*) { Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()]; suite.storage(FD_STORE_USER); g_layout_list.update_dialogs(); } static void cb_w_layout_menu_storage2(Fl_Menu_*, void*) { Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()]; suite.storage(FD_STORE_PROJECT); g_layout_list.update_dialogs(); } static void cb_w_layout_menu_storage3(Fl_Menu_*, void*) { Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()]; suite.storage(FD_STORE_FILE); g_layout_list.update_dialogs(); } static void cb_w_layout_menu_load(Fl_Menu_*, void*) { // Give the user a file chooser and load that file Fl_Native_File_Chooser fnfc; fnfc.title("Load Layout Settings:"); fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE); fnfc.options(Fl_Native_File_Chooser::USE_FILTER_EXT); fnfc.filter("FLUID Layouts\t*.fll\n"); if (fnfc.show() != 0) return; const char *new_filename = fnfc.filename(); if (!new_filename) return; g_layout_list.load(new_filename); //g_layout_list.current_suite(n); g_layout_list.update_dialogs(); } static void cb_w_layout_menu_save(Fl_Menu_*, void*) { // Give the user a file chooser with a suggested name Fl_Native_File_Chooser fnfc; fnfc.title("Save Layout Settings:"); fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | Fl_Native_File_Chooser::USE_FILTER_EXT); fnfc.filter("FLUID Layouts\t*.fll\n"); Fl_String filename = g_layout_list.filename_; fnfc.directory(fl_filename_path(filename).c_str()); fnfc.preset_file(fl_filename_name(filename).c_str()); if (fnfc.show() != 0) return; const char *new_filename = fnfc.filename(); if (!new_filename) return; g_layout_list.filename_ = new_filename; g_layout_list.save(new_filename); } static void cb_w_layout_menu_delete(Fl_Menu_*, void*) { // remove the current suite g_layout_list.remove(g_layout_list.current_suite()); g_layout_list.update_dialogs(); } Fl_Menu_Item menu_w_layout_menu[] = { {"Rename...", 0, (Fl_Callback*)cb_w_layout_menu_rename, 0, 128, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {"@fd_beaker FLUID Built-In", 0, (Fl_Callback*)cb_w_layout_menu_storage, 0, 9, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {"@fd_user User Preference", 0, (Fl_Callback*)cb_w_layout_menu_storage1, 0, 8, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {"@fd_project Store in .fl Project File", 0, (Fl_Callback*)cb_w_layout_menu_storage2, 0, 8, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {"@fd_file Store in External File", 0, (Fl_Callback*)cb_w_layout_menu_storage3, 0, 136, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {"Load...", 0, (Fl_Callback*)cb_w_layout_menu_load, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {"Save...", 0, (Fl_Callback*)cb_w_layout_menu_save, 0, 128, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {"Delete", 0, (Fl_Callback*)cb_w_layout_menu_delete, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Button *preset_choice[3]={(Fl_Button *)0}; static void cb_Left(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->left_window_margin); } else { layout->left_window_margin = (int)o->value(); } } static void cb_Top(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->top_window_margin); } else { layout->top_window_margin = (int)o->value(); } } static void cb_Right(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->right_window_margin); } else { layout->right_window_margin = (int)o->value(); } } static void cb_Bottom(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->bottom_window_margin); } else { layout->bottom_window_margin = (int)o->value(); } } static void cb_Horizontal(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->window_grid_x); } else { layout->window_grid_x = (int)o->value(); } } static void cb_Vertical(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->window_grid_y); } else { layout->window_grid_y = (int)o->value(); } } static void cb_Left1(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->left_group_margin); } else { layout->left_group_margin = (int)o->value(); } } static void cb_Top1(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->top_group_margin); } else { layout->top_group_margin = (int)o->value(); } } static void cb_Right1(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->right_group_margin); } else { layout->right_group_margin = (int)o->value(); } } static void cb_Bottom1(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->bottom_group_margin); } else { layout->bottom_group_margin = (int)o->value(); } } static void cb_Horizontal1(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->group_grid_x); } else { layout->group_grid_x = (int)o->value(); } } static void cb_Vertical1(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->group_grid_y); } else { layout->group_grid_y = (int)o->value(); } } static void cb_Top2(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->top_tabs_margin); } else { layout->top_tabs_margin = (int)o->value(); } } static void cb_Bottom2(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->bottom_tabs_margin); } else { layout->bottom_tabs_margin = (int)o->value(); } } static void cb_Minimum(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->widget_min_w); } else { layout->widget_min_w = (int)o->value(); } } static void cb_Increment(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->widget_inc_w); } else { layout->widget_inc_w = (int)o->value(); } } static void cb_Gap(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->widget_gap_x); } else { layout->widget_gap_x = (int)o->value(); } } static void cb_3(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->widget_min_h); } else { layout->widget_min_h = (int)o->value(); } } static void cb_4(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->widget_inc_h); } else { layout->widget_inc_h = (int)o->value(); } } static void cb_5(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value((double)layout->widget_gap_y); } else { layout->widget_gap_y = (int)o->value(); } } static void cb_6(Fl_Choice* o, void* v) { if (v == LOAD) { o->value(layout->labelfont+1); } else { layout->labelfont = (int)o->value()-1; } } static void cb_7(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value(layout->labelsize); } else { layout->labelsize = (int)o->value(); } } static void cb_8(Fl_Choice* o, void* v) { if (v == LOAD) { o->value(layout->textfont+1); } else { layout->textfont = (int)o->value()-1; } } static void cb_9(Fl_Value_Input* o, void* v) { if (v == LOAD) { o->value(layout->textsize); } else { layout->textsize = (int)o->value(); } } Fl_Group *w_settings_shell_tab=(Fl_Group *)0; static const unsigned char idata_shell_64[] = {137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,96,0,0,0,64,8,4,0,0,0, 79,61,186,133,0,0,2,233,73,68,65,84,104,222,237,154,207,107,19,65,20,199,63, 155,196,70,235,161,154,149,104,165,148,170,104,127,252,3,30,5,43,69,130,55,15, 222,234,77,65,240,34,182,1,127,28,2,189,181,9,120,16,244,82,240,32,210,179,162, 69,241,170,30,196,91,107,171,208,218,94,26,161,77,218,131,182,49,38,245,80,77, 118,67,205,254,152,113,102,87,242,114,217,101,194,240,253,236,188,247,102,230, 205,128,179,181,145,97,141,10,219,10,127,21,86,201,208,134,4,139,49,165,88,124, 29,98,146,152,56,64,70,147,252,29,132,180,147,60,195,17,96,141,4,250,236,43,71, 68,1,42,68,118,30,246,18,87,164,122,163,254,88,37,42,10,176,253,71,126,134,30, 170,10,228,71,248,98,245,28,195,41,68,93,90,156,110,78,40,26,129,170,39,220,144, 91,11,64,183,185,142,129,18,203,68,20,5,241,178,135,127,187,206,66,245,52,106, 73,114,116,252,19,132,18,91,174,21,122,0,208,100,70,43,136,255,147,32,134,33, 14,42,241,39,131,34,47,229,3,36,184,78,159,34,128,57,222,83,144,63,2,237,236, 87,228,22,237,173,153,184,5,16,200,44,100,223,114,124,96,157,227,12,176,39,140, 0,155,60,102,12,56,198,109,206,201,41,29,168,117,161,60,83,0,44,114,135,87, 252,8,31,128,81,27,184,60,119,53,35,248,2,56,204,69,203,104,232,69,240,5,176, 143,75,140,4,4,193,103,26,53,25,14,8,130,239,121,32,40,8,2,19,89,48,16,132,102, 226,32,32,8,46,37,244,35,8,175,133,116,35,72,88,204,153,12,115,211,134,240,154, 114,184,86,163,38,151,109,163,48,198,76,216,150,211,118,71,90,100,154,205,176, 237,7,76,134,45,69,241,55,172,135,111,67,99,114,186,182,155,45,11,22,33,11,58,0, 62,241,136,239,181,26,134,170,141,78,76,158,252,44,79,107,111,131,202,14,214, 36,1,204,147,179,200,79,49,40,239,203,168,0,152,39,203,179,218,219,16,55,232, 14,250,166,222,106,115,228,108,242,71,233,119,81,244,14,12,192,28,19,60,183, 200,79,211,167,80,190,112,22,250,104,147,127,94,154,252,132,154,17,152,37,103, 147,63,74,175,210,175,47,8,48,203,4,211,154,229,11,0,204,144,109,42,191,76,201, 67,111,113,223,19,95,204,175,252,113,203,33,68,138,17,78,217,228,127,230,5,75, 84,92,246,22,165,135,148,207,123,0,190,0,10,76,54,200,239,109,104,127,192,19, 143,125,46,113,203,215,236,237,43,11,21,121,215,68,190,189,221,173,189,165,168, 46,141,182,211,245,251,233,194,46,242,173,237,238,173,203,211,185,140,160,11, 37,185,194,79,22,57,203,85,78,254,181,125,222,67,143,253,92,35,169,14,32,202, 25,6,248,198,33,14,52,105,223,112,125,36,104,208,65,210,233,102,147,220,44,20, 163,211,177,189,51,108,59,50,61,214,2,208,109,174,99,160,192,130,178,251,66,11, 214,235,54,142,9,192,201,42,205,71,41,33,161,178,208,216,199,86,173,56,32,227, 218,229,42,166,70,15,89,225,168,104,12,220,87,226,55,187,91,149,123,50,162,100, 82,219,229,239,135,114,138,14,109,164,201,83,85,44,126,133,81,55,103,232,191,0, 145,21,211,195,226,88,204,195,0,0,0,0,73,69,78,68,174,66,96,130}; static Fl_Image *image_shell_64() { static Fl_Image *image = NULL; if (!image) image = new Fl_PNG_Image("shell_64.png", idata_shell_64, 802); return image; } Fl_Browser *w_settings_shell_list=(Fl_Browser *)0; static void cb_w_settings_shell_list(Fl_Browser* o, void* v) { if (v == LOAD) { // load from g_shell_config if (g_shell_config) { o->clear(); w_settings_shell_list_selected = 0; for (int i=0; ilist_size; i++) { Fd_Shell_Command *cmd = g_shell_config->list[i]; o->add(cmd->name.c_str()); if (cmd->storage == FD_STORE_USER) o->icon(i+1, w_settings_shell_fd_user->image()); else if (cmd->storage == FD_STORE_PROJECT) o->icon(i+1, w_settings_shell_fd_project->image()); } } } else { // int prev_selected = w_settings_shell_list_selected; w_settings_shell_list_selected = 0; int selected = w_settings_shell_list->value(); if (selected) { if (w_settings_shell_list->selected(selected)) w_settings_shell_list_selected = selected; } w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); } } Fl_Group *w_settings_shell_toolbox=(Fl_Group *)0; static void cb_w_settings_shell_toolbox(Fl_Group* o, void* v) { if (v==LOAD) { propagate_load(o, v); } } static void cb_a(Fl_Button*, void* v) { if (v != LOAD) { int selected = w_settings_shell_list_selected; Fd_Shell_Command *cmd = new Fd_Shell_Command("new shell command"); g_shell_config->insert(selected, cmd); w_settings_shell_list->insert(selected+1, cmd->name.c_str()); w_settings_shell_list->deselect(); w_settings_shell_list->value(selected+1); if (cmd->storage == FD_STORE_USER) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); } else if (cmd->storage == FD_STORE_PROJECT) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); set_modflag(1); } w_settings_shell_list->do_callback(); w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); g_shell_config->rebuild_shell_menu(); } } Fl_Button *w_settings_shell_dup=(Fl_Button *)0; static void cb_w_settings_shell_dup(Fl_Button* o, void* v) { int selected = w_settings_shell_list_selected; if (v==LOAD) { if (selected) { o->activate(); } else { o->deactivate(); } } else { if (!selected) return; Fd_Shell_Command *cmd = new Fd_Shell_Command(g_shell_config->list[selected-1]); g_shell_config->insert(selected, cmd); w_settings_shell_list->insert(selected+1, cmd->name.c_str()); w_settings_shell_list->deselect(); w_settings_shell_list->value(selected+1); if (cmd->storage == FD_STORE_USER) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); } else if (cmd->storage == FD_STORE_PROJECT) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); set_modflag(1); } w_settings_shell_list->do_callback(); w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); g_shell_config->rebuild_shell_menu(); } } Fl_Button *w_settings_shell_remove=(Fl_Button *)0; static void cb_w_settings_shell_remove(Fl_Button* o, void* v) { int selected = w_settings_shell_list_selected; if (v==LOAD) { if (selected) { o->activate(); } else { o->deactivate(); } } else { if (!selected) return; int ret = fl_choice("Delete the shell command\n\"%s\"?\n\nThis can not be undone.", "Delete", "Cancel", NULL, g_shell_config->list[selected-1]->name.c_str()); if (ret==1) return; if (g_shell_config->at(selected-1)->storage == FD_STORE_PROJECT) set_modflag(1); g_shell_config->remove(selected-1); w_settings_shell_list->remove(selected); if (selected <= w_settings_shell_list->size()) w_settings_shell_list->value(selected); else w_settings_shell_list->value(0); w_settings_shell_list->do_callback(); w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); g_shell_config->rebuild_shell_menu(); } } Fl_Menu_Button *w_settings_shell_menu=(Fl_Menu_Button *)0; static void cb_Import(Fl_Menu_*, void* v) { if (v != LOAD) Fd_Shell_Command_List::import_from_file(); } static void cb_Export(Fl_Menu_*, void* v) { if (v != LOAD) Fd_Shell_Command_List::export_selected(); } Fl_Menu_Item menu_w_settings_shell_menu[] = { {"Import...", 0, (Fl_Callback*)cb_Import, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"Export selected...", 0, (Fl_Callback*)cb_Export, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"Example Scripts:", 0, 0, 0, 17, (uchar)FL_NORMAL_LABEL, 1, 10, 0}, {"Compile with fltk-config", 0, 0, 0, 16, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"Build and run", 0, 0, 0, 16, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"Build with Xcode on macOS", 0, 0, 0, 16, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"Build with CMake", 0, 0, 0, 16, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; static void cb_T(Fl_Button*, void* v) { if (v!=LOAD) show_terminal_window(); } Fl_Button *w_settings_shell_play=(Fl_Button *)0; static void cb_w_settings_shell_play(Fl_Button* o, void* v) { int selected = w_settings_shell_list_selected; if (v==LOAD) { if (selected) { o->activate(); } else { o->deactivate(); } } else { if (!selected) return; Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->run(); } } Fl_Group *w_settings_shell_cmd=(Fl_Group *)0; static void cb_w_settings_shell_cmd(Fl_Group* o, void* v) { if (v==LOAD) { int selected = w_settings_shell_list_selected; if (selected) { o->activate(); } else { o->deactivate(); } propagate_load(o, v); } } static void cb_Name(Fl_Input* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->name.c_str()); } else { o->value(""); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->name = o->value(); w_settings_shell_list->text(selected, o->value()); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } static void cb_Menu(Fl_Input* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->label.c_str()); } else { o->value(""); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->label = o->value(); cmd->update_shell_menu(); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } static void cb_b(Fl_Group* o, void* v) { propagate_load(o, v); } static void cb_Shortcut(Fl_Shortcut_Button* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->shortcut); //o->default_value(o->value()); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->shortcut = o->value(); cmd->update_shell_menu(); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } static void cb_Store(Fl_Choice* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { Fd_Tool_Store ts = g_shell_config->list[selected-1]->storage; o->value(o->find_item_with_argument((long)ts)); } else { o->value(o->find_item_with_argument((long)FD_STORE_USER)); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; Fd_Tool_Store ts = (Fd_Tool_Store)(o->mvalue()->argument()); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); cmd->storage = ts; //w_settings_shell_list->text(selected, cmd->name.c_str()); if (cmd->storage == FD_STORE_USER) w_settings_shell_list->icon(selected, w_settings_shell_fd_user->image()); else if (cmd->storage == FD_STORE_PROJECT) w_settings_shell_list->icon(selected, w_settings_shell_fd_project->image()); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } Fl_Menu_Item menu_Store[] = { {"@fd_user User Setting", 0, 0, (void*)(FD_STORE_USER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"@fd_project Project File", 0, 0, (void*)(FD_STORE_PROJECT), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; static void cb_Condition(Fl_Choice* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { int cond = g_shell_config->list[selected-1]->condition; o->value(o->find_item_with_argument(cond)); } else { o->value(o->find_item_with_argument(0)); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int cond = (int)(o->mvalue()->argument()); cmd->condition = cond; g_shell_config->rebuild_shell_menu(); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } Fl_Menu_Item menu_Condition[] = { {"all platforms", 0, 0, (void*)(Fd_Shell_Command::ALWAYS), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"Windows only", 0, 0, (void*)(Fd_Shell_Command::WIN_ONLY), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"Linux only", 0, 0, (void*)(Fd_Shell_Command::UX_ONLY), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"macOS only", 0, 0, (void*)(Fd_Shell_Command::MAC_ONLY), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"Linux and macOS", 0, 0, (void*)(Fd_Shell_Command::MAC_AND_UX_ONLY), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"don\'t use", 0, 0, (void*)(Fd_Shell_Command::NEVER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; static void cb_Label(Fl_Input* o, void* v) { if (v == LOAD) { // o->value(g_shell_command.c_str()); } else { // g_shell_command = o->value(); } } Fl_Text_Editor *w_settings_shell_command=(Fl_Text_Editor *)0; static void cb_w_settings_shell_command(Fl_Text_Editor* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->buffer()->text(g_shell_config->list[selected-1]->command.c_str()); } else { o->buffer()->text(""); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->command = o->buffer()->text(); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } Fl_Menu_Button *w_settings_shell_text_macros=(Fl_Menu_Button *)0; static void cb_w_settings_shell_text_macros(Fl_Menu_Button* o, void*) { const Fl_Menu_Item *mi = o->mvalue(); if (mi) { char buffer[256]; fl_strlcpy(buffer, mi->label(), 255); int n = (int)strlen(buffer)-1; if (buffer[n]=='@') buffer[n] = 0; char *word = buffer; if (word[0]=='@') word++; if (w_settings_shell_command->buffer()->selected()) { int start = 0, end = 0; w_settings_shell_command->buffer()->selection_position(&start, &end); w_settings_shell_command->buffer()->replace(start, end, word); } else { int pos = w_settings_shell_command->insert_position(); w_settings_shell_command->buffer()->insert(pos, word); } w_settings_shell_command->do_callback(w_settings_shell_command, (void*)NULL); } } Fl_Menu_Item menu_w_settings_shell_text_macros[] = { {"@@BASENAME@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {"@@PROJECTFILE_PATH@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {"@@PROJECTFILE_NAME@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {"@@CODEFILE_PATH@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {"@@CODEFILE_NAME@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {"@@HEADERFILE_PATH@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {"@@HEADERFILE_NAME@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {"@@TEXTFILE_PATH@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {"@@TEXTFILE_NAME@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, // Not yet implemented {"@@FLTK_CONFIG@@", 0, 0, 0, 16, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {"@@TMPDIR@@", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {0,0,0,0,0,0,0,0,0} }; static void cb_1fd_zoom(Fl_Button*, void*) { if (!script_panel) make_script_panel(); script_input->buffer()->text(w_settings_shell_command->buffer()->text()); script_panel->show(); for (;;) { Fl_Widget* w = Fl::readqueue(); if (w == script_panel_cancel) goto BREAK2; else if (w == script_panel_ok) break; else if (!w) Fl::wait(); } w_settings_shell_command->buffer()->text(script_input->buffer()->text()); w_settings_shell_command->do_callback(); BREAK2: script_panel->hide(); } static void cb_save(Fl_Check_Button* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_PROJECT); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (v) { cmd->flags |= Fd_Shell_Command::SAVE_PROJECT; } else { cmd->flags &= ~Fd_Shell_Command::SAVE_PROJECT; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } static void cb_save1(Fl_Check_Button* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_SOURCECODE); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (v) { cmd->flags |= Fd_Shell_Command::SAVE_SOURCECODE; } else { cmd->flags &= ~Fd_Shell_Command::SAVE_SOURCECODE; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } static void cb_save2(Fl_Check_Button* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_STRINGS); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (v) { cmd->flags |= Fd_Shell_Command::SAVE_STRINGS; } else { cmd->flags &= ~Fd_Shell_Command::SAVE_STRINGS; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } static void cb_show(Fl_Check_Button* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(!(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::DONT_SHOW_TERMINAL)); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (!v) { cmd->flags |= Fd_Shell_Command::DONT_SHOW_TERMINAL; } else { cmd->flags &= ~Fd_Shell_Command::DONT_SHOW_TERMINAL; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } static void cb_clear(Fl_Check_Button* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::CLEAR_TERMINAL); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (v) { cmd->flags |= Fd_Shell_Command::CLEAR_TERMINAL; } else { cmd->flags &= ~Fd_Shell_Command::CLEAR_TERMINAL; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } static void cb_clear1(Fl_Check_Button* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::CLEAR_HISTORY); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (v) { cmd->flags |= Fd_Shell_Command::CLEAR_HISTORY; } else { cmd->flags &= ~Fd_Shell_Command::CLEAR_HISTORY; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } } } Fl_Box *w_settings_shell_fd_project=(Fl_Box *)0; static const unsigned char idata_fd_project[] = {137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0, 115,122,122,244,0,0,1,110,105,67,67,80,105,99,99,0,0,40,145,117,145,187,75,195, 80,20,198,127,173,239,23,14,58,136,116,200,80,197,65,65,20,196,81,235,208,165, 72,169,21,172,186,180,49,109,133,164,13,73,139,136,171,224,226,80,112,16,93, 124,13,254,7,186,10,174,10,130,160,8,34,110,238,190,22,145,120,174,45,180,136, 189,225,230,252,248,238,253,14,39,95,192,31,49,117,203,109,156,2,43,87,112,98, 225,144,182,144,88,212,90,94,104,163,153,46,2,244,39,117,215,158,142,70,35,212, 93,159,119,248,84,189,29,81,189,234,223,251,119,117,172,24,174,14,190,86,225,9, 221,118,10,194,50,13,145,181,130,173,120,91,184,87,207,38,87,132,15,133,135,29, 25,80,248,74,233,169,50,63,43,206,148,249,93,177,19,143,205,128,95,245,212,50, 53,156,170,97,61,235,88,194,67,194,65,203,44,234,149,121,212,151,116,26,185, 249,57,169,253,178,3,184,196,8,19,66,35,69,145,85,76,10,140,72,205,73,102,255, 251,70,127,125,179,228,197,163,203,219,102,29,71,28,25,178,226,29,22,181,40,93, 13,169,105,209,13,121,76,214,85,238,127,243,116,211,227,99,229,238,157,33,104, 122,242,188,183,1,104,217,129,239,146,231,125,29,121,222,247,49,52,60,194,69, 174,234,207,75,78,147,31,162,151,170,90,240,0,186,55,225,236,178,170,165,118, 225,124,11,250,30,236,164,147,252,149,26,100,251,211,105,120,61,133,174,4,244, 220,64,251,82,57,171,202,57,39,247,16,223,144,95,116,13,123,251,48,40,247,187, 151,127,0,229,44,103,253,189,250,32,75,0,0,0,9,112,72,89,115,0,0,22,37,0,0,22, 37,1,73,82,36,240,0,0,1,13,116,69,88,116,82,97,119,32,112,114,111,102,105,108, 101,32,116,121,112,101,32,101,120,105,102,0,10,101,120,105,102,10,32,32,32,32, 32,49,49,52,10,52,53,55,56,54,57,54,54,48,48,48,48,52,57,52,57,50,97,48,48,48, 56,48,48,48,48,48,48,48,52,48,48,49,97,48,49,48,53,48,48,48,49,48,48,48,48,48, 48,51,101,48,48,48,48,48,48,49,98,48,49,48,53,48,48,48,49,48,48,48,48,48,48,10, 52,54,48,48,48,48,48,48,50,56,48,49,48,51,48,48,48,49,48,48,48,48,48,48,48,50, 48,48,48,48,48,48,54,57,56,55,48,52,48,48,48,49,48,48,48,48,48,48,52,101,48,48, 48,48,48,48,48,48,48,48,48,48,48,48,57,48,48,48,48,48,48,48,10,48,49,48,48,48, 48,48,48,57,48,48,48,48,48,48,48,48,49,48,48,48,48,48,48,48,50,48,48,48,50,97, 48,48,52,48,48,48,49,48,48,48,48,48,48,53,50,48,48,48,48,48,48,48,51,97,48,48, 52,48,48,48,49,48,48,48,48,48,48,56,48,48,48,10,48,48,48,48,48,48,48,48,48,48, 48,48,10,190,225,144,105,0,0,0,90,116,69,88,116,82,97,119,32,112,114,111,102, 105,108,101,32,116,121,112,101,32,105,112,116,99,0,10,105,112,116,99,10,32,32, 32,32,32,32,50,54,10,53,48,54,56,54,102,55,52,54,102,55,51,54,56,54,102,55,48, 50,48,51,51,50,101,51,48,48,48,51,56,52,50,52,57,52,100,48,52,48,52,48,48,48, 48,48,48,48,48,48,48,48,48,10,199,209,105,220,0,0,20,96,116,69,88,116,82,97, 119,32,112,114,111,102,105,108,101,32,116,121,112,101,32,120,109,112,0,10,120, 109,112,10,32,32,32,32,50,53,53,53,10,51,99,51,102,55,56,55,48,54,49,54,51,54, 98,54,53,55,52,50,48,54,50,54,53,54,55,54,57,54,101,51,100,50,50,101,102,98,98, 98,102,50,50,50,48,54,57,54,52,51,100,50,50,53,55,51,53,52,100,51,48,52,100,55, 48,52,51,54,53,54,56,54,57,10,52,56,55,97,55,50,54,53,53,51,55,97,52,101,53,52, 54,51,55,97,54,98,54,51,51,57,54,52,50,50,51,102,51,101,48,97,51,99,55,56,51, 97,55,56,54,100,55,48,54,100,54,53,55,52,54,49,50,48,55,56,54,100,54,99,54,101, 55,51,51,97,55,56,10,51,100,50,50,54,49,54,52,54,102,54,50,54,53,51,97,54,101, 55,51,51,97,54,100,54,53,55,52,54,49,50,102,50,50,50,48,55,56,51,97,55,56,54, 100,55,48,55,52,54,98,51,100,50,50,53,56,52,100,53,48,50,48,52,51,54,102,55,50, 54,53,50,48,10,51,52,50,101,51,52,50,101,51,48,50,100,52,53,55,56,54,57,55,54, 51,50,50,50,51,101,48,97,50,48,51,99,55,50,54,52,54,54,51,97,53,50,52,52,52,54, 50,48,55,56,54,100,54,99,54,101,55,51,51,97,55,50,54,52,54,54,51,100,50,50,54, 56,10,55,52,55,52,55,48,51,97,50,102,50,102,55,55,55,55,55,55,50,101,55,55,51, 51,50,101,54,102,55,50,54,55,50,102,51,49,51,57,51,57,51,57,50,102,51,48,51,50, 50,102,51,50,51,50,50,100,55,50,54,52,54,54,50,100,55,51,55,57,54,101,55,52,10, 54,49,55,56,50,100,54,101,55,51,50,51,50,50,51,101,48,97,50,48,50,48,51,99,55, 50,54,52,54,54,51,97,52,52,54,53,55,51,54,51,55,50,54,57,55,48,55,52,54,57,54, 102,54,101,50,48,55,50,54,52,54,54,51,97,54,49,54,50,54,102,55,53,10,55,52,51, 100,50,50,50,50,48,97,50,48,50,48,50,48,50,48,55,56,54,100,54,99,54,101,55,51, 51,97,54,53,55,56,54,57,54,54,51,100,50,50,54,56,55,52,55,52,55,48,51,97,50, 102,50,102,54,101,55,51,50,101,54,49,54,52,54,102,54,50,54,53,10,50,101,54,51, 54,102,54,100,50,102,54,53,55,56,54,57,54,54,50,102,51,49,50,101,51,48,50,102, 50,50,48,97,50,48,50,48,50,48,50,48,55,56,54,100,54,99,54,101,55,51,51,97,55, 52,54,57,54,54,54,54,51,100,50,50,54,56,55,52,55,52,55,48,10,51,97,50,102,50, 102,54,101,55,51,50,101,54,49,54,52,54,102,54,50,54,53,50,101,54,51,54,102,54, 100,50,102,55,52,54,57,54,54,54,54,50,102,51,49,50,101,51,48,50,102,50,50,48,97, 50,48,50,48,50,48,54,53,55,56,54,57,54,54,51,97,53,48,10,54,57,55,56,54,53,54, 99,53,56,52,52,54,57,54,100,54,53,54,101,55,51,54,57,54,102,54,101,51,100,50, 50,51,56,51,50,50,50,48,97,50,48,50,48,50,48,54,53,55,56,54,57,54,54,51,97,53, 48,54,57,55,56,54,53,54,99,53,57,52,52,54,57,10,54,100,54,53,54,101,55,51,54, 57,54,102,54,101,51,100,50,50,51,49,51,50,51,56,50,50,48,97,50,48,50,48,50,48, 55,52,54,57,54,54,54,54,51,97,53,50,54,53,55,51,54,102,54,99,55,53,55,52,54,57, 54,102,54,101,53,53,54,101,54,57,55,52,10,51,100,50,50,51,50,50,50,48,97,50,48, 50,48,50,48,55,52,54,57,54,54,54,54,51,97,53,57,53,50,54,53,55,51,54,102,54,99, 55,53,55,52,54,57,54,102,54,101,51,100,50,50,51,49,51,52,51,52,50,48,50,102,50, 48,51,49,50,50,48,97,50,48,10,50,48,50,48,55,52,54,57,54,54,54,54,51,97,53,56, 53,50,54,53,55,51,54,102,54,99,55,53,55,52,54,57,54,102,54,101,51,100,50,50,51, 49,51,52,51,52,50,48,50,102,50,48,51,49,50,50,50,102,51,101,48,97,50,48,51,99, 50,102,55,50,54,52,10,54,54,51,97,53,50,52,52,52,54,51,101,48,97,51,99,50,102, 55,56,51,97,55,56,54,100,55,48,54,100,54,53,55,52,54,49,51,101,48,97,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,10,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,48, 97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,10,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,10,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48, 97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,48,97,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,10,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,51,99,51,102,55,56,55,48,54,49, 54,51,54,98,54,53,55,52,50,48,54,53,54,101,54,52,51,100,50,50,55,55,50,50,51, 102,51,101,10,87,123,188,247,0,0,3,115,73,68,65,84,88,71,189,151,75,75,91,65,20, 199,79,110,222,169,52,180,203,22,186,239,210,47,80,236,206,126,5,177,17,151,46, 68,23,82,220,138,90,84,116,163,184,80,81,132,98,93,234,42,203,210,79,209,149, 32,213,68,164,165,165,129,230,97,94,246,252,166,157,246,246,102,154,132,230, 226,31,134,59,247,204,153,243,158,123,207,68,206,206,206,164,86,171,73,52,26, 149,68,34,17,175,84,42,215,123,123,123,15,119,118,118,164,23,26,141,134,164,211, 105,243,28,29,29,149,229,229,229,183,177,88,236,101,171,213,106,235,83,154,205, 166,120,158,39,145,72,196,12,23,188,106,181,42,201,100,82,110,111,111,69,149,55, 246,247,247,139,187,187,187,102,209,110,252,215,200,100,50,162,202,12,111,62, 159,151,211,211,211,49,85,252,70,135,231,212,230,64,44,149,74,201,205,205,141, 196,227,113,97,174,222,84,48,102,102,102,70,230,230,230,186,110,110,183,219,178, 177,177,33,219,219,219,198,129,133,133,5,188,30,27,31,31,71,78,78,89,90,93,5,40, 60,60,32,92,8,168,215,235,120,86,96,129,148,244,138,0,70,219,208,142,140,140, 144,66,89,89,89,145,163,163,163,49,221,255,90,195,31,65,62,60,200,7,240,48,39, 53,198,0,187,96,94,126,230,43,195,28,239,122,129,189,150,111,120,120,88,22,23, 23,13,109,105,105,73,142,143,143,95,169,242,247,42,51,107,249,144,79,202,49, 136,186,1,198,0,191,17,186,88,177,194,123,1,239,134,134,134,76,228,152,79,78,78, 202,250,250,186,137,232,218,218,154,156,156,156,60,211,72,92,43,235,115,60,247, 43,166,238,128,137,67,192,136,102,183,170,245,3,30,45,92,227,25,74,121,78,76, 76,152,72,112,2,168,137,195,195,195,148,210,223,169,226,23,208,40,92,210,203, 201,3,158,205,15,33,98,232,60,101,22,188,222,133,108,235,135,90,64,40,239,200, 154,154,154,50,17,96,190,185,185,73,77,80,224,121,93,127,130,62,12,97,15,48,6, 88,101,254,72,244,19,1,194,138,48,242,74,26,108,152,145,145,203,229,76,65,226, 212,234,234,170,28,28,28,96,228,71,235,168,69,44,24,110,221,156,237,39,255,22, 40,197,155,173,173,45,115,36,153,147,22,66,205,241,198,57,140,164,54,74,165,82, 99,122,122,250,47,71,141,235,129,40,164,131,133,249,47,16,242,96,85,227,29,133, 201,187,149,107,63,116,58,10,24,131,209,22,158,221,4,51,2,117,67,201,127,110, 187,1,190,249,249,121,185,188,188,148,98,177,40,87,87,87,102,126,126,126,110, 230,133,66,65,46,46,46,100,118,118,214,242,127,192,32,127,10,92,149,246,217,65, 11,11,159,130,4,151,1,53,7,45,44,60,8,18,92,6,60,114,208,194,66,35,72,112,25, 80,113,208,194,66,50,72,112,25,240,205,65,11,11,55,65,194,93,167,160,175,8,68, 29,180,176,224,142,0,103,211,254,163,245,140,86,59,247,253,31,252,95,216,95, 243,108,144,199,21,129,14,166,16,113,63,72,112,25,80,119,208,194,194,215,32,193, 101,64,104,41,112,160,28,36,220,117,10,238,5,9,119,157,130,14,125,46,3,254,252, 43,195,71,51,72,112,25,240,197,65,11,11,29,245,229,217,179,106,155,10,237,104, 154,253,180,228,253,2,153,246,142,161,207,36,223,26,123,155,2,30,139,86,33,237, 148,246,118,41,255,197,97,16,160,148,238,135,214,140,161,198,52,81,110,47,39, 224,119,71,196,176,157,45,253,28,173,211,160,176,109,25,45,25,50,213,193,199, 190,27,152,225,137,209,159,99,17,30,151,203,101,218,236,44,52,154,76,90,234,65, 128,34,228,250,90,246,136,255,29,196,176,206,118,175,58,79,232,226,83,24,236, 213,122,16,176,223,94,207,73,175,70,249,59,81,177,117,128,158,31,49,127,246,30, 207,181,170,20,0,0,0,0,73,69,78,68,174,66,96,130}; static Fl_Image *image_fd_project() { static Fl_Image *image = NULL; if (!image) image = new Fl_PNG_Image("fd_project.png", idata_fd_project, 6950); return image; } Fl_Box *w_settings_shell_fd_user=(Fl_Box *)0; static const unsigned char idata_fd_user[] = {137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0, 115,122,122,244,0,0,1,110,105,67,67,80,105,99,99,0,0,40,145,117,145,187,75,195, 80,20,198,127,173,239,23,14,58,136,116,200,80,197,65,65,20,196,81,235,208,165, 72,169,21,172,186,180,49,109,133,164,13,73,139,136,171,224,226,80,112,16,93, 124,13,254,7,186,10,174,10,130,160,8,34,110,238,190,22,145,120,174,45,180,136, 189,225,230,252,248,238,253,14,39,95,192,31,49,117,203,109,156,2,43,87,112,98, 225,144,182,144,88,212,90,94,104,163,153,46,2,244,39,117,215,158,142,70,35,212, 93,159,119,248,84,189,29,81,189,234,223,251,119,117,172,24,174,14,190,86,225,9, 221,118,10,194,50,13,145,181,130,173,120,91,184,87,207,38,87,132,15,133,135,29, 25,80,248,74,233,169,50,63,43,206,148,249,93,177,19,143,205,128,95,245,212,50, 53,156,170,97,61,235,88,194,67,194,65,203,44,234,149,121,212,151,116,26,185, 249,57,169,253,178,3,184,196,8,19,66,35,69,145,85,76,10,140,72,205,73,102,255, 251,70,127,125,179,228,197,163,203,219,102,29,71,28,25,178,226,29,22,181,40,93, 13,169,105,209,13,121,76,214,85,238,127,243,116,211,227,99,229,238,157,33,104, 122,242,188,183,1,104,217,129,239,146,231,125,29,121,222,247,49,52,60,194,69, 174,234,207,75,78,147,31,162,151,170,90,240,0,186,55,225,236,178,170,165,118, 225,124,11,250,30,236,164,147,252,149,26,100,251,211,105,120,61,133,174,4,244, 220,64,251,82,57,171,202,57,39,247,16,223,144,95,116,13,123,251,48,40,247,187, 151,127,0,229,44,103,253,189,250,32,75,0,0,0,9,112,72,89,115,0,0,22,37,0,0,22, 37,1,73,82,36,240,0,0,1,13,116,69,88,116,82,97,119,32,112,114,111,102,105,108, 101,32,116,121,112,101,32,101,120,105,102,0,10,101,120,105,102,10,32,32,32,32, 32,49,49,52,10,52,53,55,56,54,57,54,54,48,48,48,48,52,57,52,57,50,97,48,48,48, 56,48,48,48,48,48,48,48,52,48,48,49,97,48,49,48,53,48,48,48,49,48,48,48,48,48, 48,51,101,48,48,48,48,48,48,49,98,48,49,48,53,48,48,48,49,48,48,48,48,48,48,10, 52,54,48,48,48,48,48,48,50,56,48,49,48,51,48,48,48,49,48,48,48,48,48,48,48,50, 48,48,48,48,48,48,54,57,56,55,48,52,48,48,48,49,48,48,48,48,48,48,52,101,48,48, 48,48,48,48,48,48,48,48,48,48,48,48,57,48,48,48,48,48,48,48,10,48,49,48,48,48, 48,48,48,57,48,48,48,48,48,48,48,48,49,48,48,48,48,48,48,48,50,48,48,48,50,97, 48,48,52,48,48,48,49,48,48,48,48,48,48,53,50,48,48,48,48,48,48,48,51,97,48,48, 52,48,48,48,49,48,48,48,48,48,48,56,48,48,48,10,48,48,48,48,48,48,48,48,48,48, 48,48,10,190,225,144,105,0,0,0,90,116,69,88,116,82,97,119,32,112,114,111,102, 105,108,101,32,116,121,112,101,32,105,112,116,99,0,10,105,112,116,99,10,32,32, 32,32,32,32,50,54,10,53,48,54,56,54,102,55,52,54,102,55,51,54,56,54,102,55,48, 50,48,51,51,50,101,51,48,48,48,51,56,52,50,52,57,52,100,48,52,48,52,48,48,48, 48,48,48,48,48,48,48,48,48,10,199,209,105,220,0,0,20,96,116,69,88,116,82,97, 119,32,112,114,111,102,105,108,101,32,116,121,112,101,32,120,109,112,0,10,120, 109,112,10,32,32,32,32,50,53,53,53,10,51,99,51,102,55,56,55,48,54,49,54,51,54, 98,54,53,55,52,50,48,54,50,54,53,54,55,54,57,54,101,51,100,50,50,101,102,98,98, 98,102,50,50,50,48,54,57,54,52,51,100,50,50,53,55,51,53,52,100,51,48,52,100,55, 48,52,51,54,53,54,56,54,57,10,52,56,55,97,55,50,54,53,53,51,55,97,52,101,53,52, 54,51,55,97,54,98,54,51,51,57,54,52,50,50,51,102,51,101,48,97,51,99,55,56,51, 97,55,56,54,100,55,48,54,100,54,53,55,52,54,49,50,48,55,56,54,100,54,99,54,101, 55,51,51,97,55,56,10,51,100,50,50,54,49,54,52,54,102,54,50,54,53,51,97,54,101, 55,51,51,97,54,100,54,53,55,52,54,49,50,102,50,50,50,48,55,56,51,97,55,56,54, 100,55,48,55,52,54,98,51,100,50,50,53,56,52,100,53,48,50,48,52,51,54,102,55,50, 54,53,50,48,10,51,52,50,101,51,52,50,101,51,48,50,100,52,53,55,56,54,57,55,54, 51,50,50,50,51,101,48,97,50,48,51,99,55,50,54,52,54,54,51,97,53,50,52,52,52,54, 50,48,55,56,54,100,54,99,54,101,55,51,51,97,55,50,54,52,54,54,51,100,50,50,54, 56,10,55,52,55,52,55,48,51,97,50,102,50,102,55,55,55,55,55,55,50,101,55,55,51, 51,50,101,54,102,55,50,54,55,50,102,51,49,51,57,51,57,51,57,50,102,51,48,51,50, 50,102,51,50,51,50,50,100,55,50,54,52,54,54,50,100,55,51,55,57,54,101,55,52,10, 54,49,55,56,50,100,54,101,55,51,50,51,50,50,51,101,48,97,50,48,50,48,51,99,55, 50,54,52,54,54,51,97,52,52,54,53,55,51,54,51,55,50,54,57,55,48,55,52,54,57,54, 102,54,101,50,48,55,50,54,52,54,54,51,97,54,49,54,50,54,102,55,53,10,55,52,51, 100,50,50,50,50,48,97,50,48,50,48,50,48,50,48,55,56,54,100,54,99,54,101,55,51, 51,97,54,53,55,56,54,57,54,54,51,100,50,50,54,56,55,52,55,52,55,48,51,97,50, 102,50,102,54,101,55,51,50,101,54,49,54,52,54,102,54,50,54,53,10,50,101,54,51, 54,102,54,100,50,102,54,53,55,56,54,57,54,54,50,102,51,49,50,101,51,48,50,102, 50,50,48,97,50,48,50,48,50,48,50,48,55,56,54,100,54,99,54,101,55,51,51,97,55, 52,54,57,54,54,54,54,51,100,50,50,54,56,55,52,55,52,55,48,10,51,97,50,102,50, 102,54,101,55,51,50,101,54,49,54,52,54,102,54,50,54,53,50,101,54,51,54,102,54, 100,50,102,55,52,54,57,54,54,54,54,50,102,51,49,50,101,51,48,50,102,50,50,48,97, 50,48,50,48,50,48,54,53,55,56,54,57,54,54,51,97,53,48,10,54,57,55,56,54,53,54, 99,53,56,52,52,54,57,54,100,54,53,54,101,55,51,54,57,54,102,54,101,51,100,50, 50,51,56,51,50,50,50,48,97,50,48,50,48,50,48,54,53,55,56,54,57,54,54,51,97,53, 48,54,57,55,56,54,53,54,99,53,57,52,52,54,57,10,54,100,54,53,54,101,55,51,54, 57,54,102,54,101,51,100,50,50,51,49,51,50,51,56,50,50,48,97,50,48,50,48,50,48, 55,52,54,57,54,54,54,54,51,97,53,50,54,53,55,51,54,102,54,99,55,53,55,52,54,57, 54,102,54,101,53,53,54,101,54,57,55,52,10,51,100,50,50,51,50,50,50,48,97,50,48, 50,48,50,48,55,52,54,57,54,54,54,54,51,97,53,57,53,50,54,53,55,51,54,102,54,99, 55,53,55,52,54,57,54,102,54,101,51,100,50,50,51,49,51,52,51,52,50,48,50,102,50, 48,51,49,50,50,48,97,50,48,10,50,48,50,48,55,52,54,57,54,54,54,54,51,97,53,56, 53,50,54,53,55,51,54,102,54,99,55,53,55,52,54,57,54,102,54,101,51,100,50,50,51, 49,51,52,51,52,50,48,50,102,50,48,51,49,50,50,50,102,51,101,48,97,50,48,51,99, 50,102,55,50,54,52,10,54,54,51,97,53,50,52,52,52,54,51,101,48,97,51,99,50,102, 55,56,51,97,55,56,54,100,55,48,54,100,54,53,55,52,54,49,51,101,48,97,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,10,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,48, 97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,10,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,10,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48, 97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,48,97,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,10,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,48,97,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50, 48,50,48,50,48,50,48,50,48,10,50,48,50,48,50,48,50,48,50,48,50,48,50,48,50,48, 50,48,50,48,50,48,50,48,50,48,50,48,50,48,48,97,51,99,51,102,55,56,55,48,54,49, 54,51,54,98,54,53,55,52,50,48,54,53,54,101,54,52,51,100,50,50,55,55,50,50,51, 102,51,101,10,87,123,188,247,0,0,9,241,73,68,65,84,88,71,109,87,105,144,85,197, 21,254,186,239,242,222,155,25,102,88,12,14,46,227,16,96,12,26,80,118,103,16, 113,3,5,89,203,10,70,75,42,106,170,48,196,16,141,154,20,18,177,8,41,21,149,82, 81,244,71,48,166,42,75,37,96,22,29,5,9,155,131,37,139,16,65,113,153,25,71,8,66, 153,165,148,137,226,204,91,238,210,55,223,233,251,30,49,58,77,53,115,223,237, 190,167,207,249,206,57,223,57,173,218,59,223,128,163,92,104,147,32,138,12,84, 162,225,58,62,100,36,137,66,38,147,65,177,88,4,31,225,186,46,130,56,134,210,9, 188,140,139,158,82,30,78,198,65,20,26,238,5,60,237,91,57,242,157,231,184,8,75,1, 148,82,118,130,223,12,168,27,152,62,127,97,104,3,23,9,52,226,242,76,228,173,50, 118,81,169,4,249,124,15,5,198,86,160,85,138,135,185,78,22,189,61,37,104,30,104, 98,5,87,103,184,158,227,51,191,113,249,206,24,132,97,152,202,41,79,101,13,74, 240,229,225,26,83,131,68,203,193,49,12,2,24,45,31,184,246,35,199,113,64,120,104, 177,139,222,82,137,104,228,16,169,88,187,137,250,238,137,79,62,251,246,238,93, 187,250,83,232,137,113,227,199,71,77,77,77,71,78,22,78,222,149,209,94,41,227, 249,68,165,68,153,148,65,52,42,255,250,26,174,67,200,211,161,211,153,104,139, 136,60,151,104,133,235,106,68,38,132,118,29,132,145,25,250,139,103,158,217,186, 105,227,214,97,199,143,253,131,240,41,56,70,67,211,13,67,134,12,198,236,249,215, 220,178,112,225,245,187,170,171,252,233,132,58,53,216,162,233,244,121,184,12, 213,217,222,97,31,100,183,5,138,10,40,229,88,248,5,21,223,23,69,138,242,46,179, 252,222,159,183,183,190,176,121,104,130,44,178,153,254,152,56,102,10,98,198,196, 161,183,246,163,55,255,31,120,185,24,87,207,188,20,15,220,191,242,128,49,193, 196,40,14,98,71,149,229,81,137,218,218,218,20,213,47,12,87,39,97,89,1,5,35,112, 241,3,109,53,151,169,24,3,69,56,158,118,215,172,121,114,127,235,11,155,134,122, 110,45,150,46,125,16,45,205,151,211,184,156,85,160,95,181,135,109,59,94,194,170, 71,238,69,235,11,127,197,160,1,3,198,222,241,163,239,63,79,9,179,147,10,242, 125,123,128,56,19,70,9,26,9,52,135,24,136,66,137,138,184,196,103,122,194,247, 125,245,234,206,221,109,191,122,246,119,163,20,170,112,255,202,53,184,184,249, 106,6,99,21,181,118,224,185,89,20,243,6,151,77,189,6,203,151,61,4,159,10,62,251, 203,223,98,223,190,191,141,75,143,48,167,142,234,35,6,233,70,30,46,43,137,157, 113,249,131,116,138,117,68,166,186,189,189,115,50,19,18,115,103,45,192,248,177, 23,35,10,178,60,184,14,90,101,9,105,22,97,192,248,40,41,76,110,158,134,185,179, 175,227,59,31,7,14,188,233,126,249,176,190,178,160,18,129,68,168,156,50,246,111, 100,115,93,16,160,207,146,55,15,190,131,160,148,96,204,133,205,40,246,42,248,78, 53,24,151,20,232,160,144,15,80,83,221,143,252,193,12,9,52,206,251,198,88,196, 92,123,243,224,161,56,149,92,65,160,239,161,157,47,40,165,202,81,43,239,44,26, 212,56,8,130,248,224,129,3,240,189,44,134,15,111,66,198,175,161,229,220,39,123, 153,1,53,53,57,20,11,198,198,144,239,229,48,98,68,19,60,47,131,183,223,126,183, 88,62,162,143,99,255,55,180,48,147,107,35,228,203,27,211,223,76,195,184,177, 177,129,86,149,112,244,232,17,166,98,17,145,216,38,228,198,45,226,127,215,35, 123,122,224,90,47,142,29,63,76,18,42,161,190,190,254,36,18,221,135,220,175,156, 162,203,169,167,210,116,41,127,36,40,72,124,184,218,137,167,78,157,130,108,149, 135,182,157,91,200,7,12,80,29,17,58,11,144,245,171,226,239,48,250,156,73,219, 131,215,118,109,227,122,140,25,51,102,100,42,178,83,37,250,118,133,85,47,34,158, 9,179,65,38,148,87,230,1,199,42,101,146,200,204,152,57,237,125,147,228,177, 243,181,205,120,175,99,31,81,233,229,222,34,21,76,200,142,204,29,174,105,175, 136,119,59,247,98,123,91,171,85,104,250,244,43,125,77,6,53,166,98,28,229,39,95, 85,66,71,41,251,83,63,42,65,14,168,40,18,89,10,117,108,38,12,31,209,120,83,115, 203,120,148,130,147,184,231,222,219,177,105,243,6,120,126,36,52,129,124,177,100, 41,124,71,219,75,88,198,181,56,233,193,228,201,147,208,216,216,56,75,228,168, 50,11,138,187,84,31,222,176,172,35,100,33,22,11,92,177,74,103,197,119,36,33,81, 111,207,83,79,175,217,187,224,186,121,40,20,63,197,99,143,63,136,205,91,90,89, 17,149,240,4,182,110,219,132,135,30,89,137,124,161,27,243,230,207,196,186,103, 158,218,67,22,125,79,170,171,84,80,97,191,40,138,208,91,232,65,108,34,235,182, 34,43,101,41,40,165,65,104,161,150,169,211,103,85,174,15,162,152,148,226,32,40, 18,137,112,206,178,101,75,183,141,190,224,124,107,49,139,55,74,20,98,40,208, 247,61,6,102,128,81,163,206,199,138,21,247,173,47,20,10,45,130,105,38,227,217, 170,88,98,33,75,203,112,130,79,79,118,227,147,238,19,164,238,188,157,172,39,14, 9,141,126,42,79,139,136,69,37,101,66,177,192,243,60,233,11,62,102,74,62,76,82, 162,50,9,38,76,152,96,149,148,67,46,188,112,12,171,90,6,29,29,93,193,231,159,23, 158,20,223,107,126,28,70,37,155,214,242,189,252,22,20,4,101,73,83,249,93,118, 129,197,223,22,159,116,166,164,45,127,197,255,217,108,214,30,24,4,17,118,239, 126,61,137,194,4,35,207,29,133,65,3,79,39,180,202,90,87,83,93,135,97,67,207,101, 63,224,153,3,111,28,202,184,174,239,136,229,41,145,41,203,41,34,75,179,204,139, 65,50,108,191,192,227,221,83,197,226,212,72,35,213,214,114,250,174,187,187,155, 188,190,79,255,229,207,47,206,223,183,247,157,135,227,64,161,101,210,101,164,94, 32,173,90,160,146,53,152,48,126,10,142,28,237,204,254,224,182,59,159,187,100, 202,164,127,206,155,63,235,195,150,150,139,158,173,170,170,122,217,36,113,94,24, 95,14,15,67,246,29,236,92,114,185,156,85,66,181,119,118,88,6,252,127,69,82,37, 94,106,221,56,106,245,234,71,175,232,62,209,51,203,113,170,91,76,224,231,38,76, 184,20,75,190,119,23,206,58,123,56,203,116,10,181,75,234,62,246,81,39,158,88, 187,10,239,180,239,71,18,247,218,56,169,98,149,252,241,79,238,196,220,185,179, 47,247,60,231,21,81,34,117,133,177,127,5,25,213,222,222,14,169,136,142,231,218, 128,50,73,32,10,12,88,187,246,233,59,215,173,251,245,45,42,169,61,99,120,227,88, 76,155,190,0,83,155,175,68,255,65,131,105,56,59,7,82,95,28,146,176,24,55,137, 229,112,33,167,8,255,254,248,24,118,182,109,196,43,109,47,163,189,243,32,15,138, 177,232,214,155,112,251,29,183,77,85,137,121,53,45,72,58,45,76,68,80,189,253, 214,33,194,209,207,194,33,41,215,211,243,233,232,229,203,151,255,126,203,150,29, 231,185,172,120,75,22,255,20,211,167,221,72,70,172,163,94,14,164,159,8,36,152,0, 219,204,74,200,136,44,9,48,41,227,174,71,106,87,228,6,213,139,23,95,124,14,79, 174,125,136,27,3,92,50,181,217,172,121,124,245,24,173,205,33,203,158,182,81,165, 225,75,126,184,132,86,211,227,180,202,209,222,153,119,223,125,207,235,219,183, 239,110,168,171,61,3,43,239,123,156,254,190,10,85,85,167,161,80,136,88,130,93, 27,88,68,144,169,71,146,226,193,177,73,27,78,66,12,135,235,113,28,165,5,149, 194,217,39,226,155,163,70,99,207,174,93,248,224,112,151,58,124,164,107,241,244, 171,166,29,103,237,56,40,116,45,25,161,125,95,160,15,108,239,199,96,187,97,103, 219,158,129,190,219,31,171,87,173,195,216,11,46,99,233,29,192,146,27,157,138, 222,82,41,141,232,56,182,201,99,93,32,214,136,95,77,148,240,119,134,41,153,35, 186,213,136,131,12,198,140,190,24,143,174,94,135,154,220,215,176,99,251,107,120, 125,239,254,7,136,182,170,196,154,14,216,239,101,115,210,5,71,151,175,88,249, 179,165,33,133,44,188,97,49,154,190,62,142,66,171,73,48,20,200,86,91,14,9,73,54, 174,207,190,136,133,73,44,141,227,52,88,45,205,10,141,11,125,115,198,180,44,138, 121,71,64,127,148,242,62,70,142,156,136,57,115,174,167,66,46,86,63,242,196,32, 130,214,84,9,119,45,36,81,40,244,158,182,97,195,134,223,124,208,245,193,192,179, 207,26,134,111,93,187,144,13,8,157,29,123,105,59,109,42,221,140,177,129,26,210, 223,18,197,158,167,109,129,137,152,86,202,94,92,202,118,73,185,230,118,135,37, 211,247,170,17,20,20,22,222,120,11,59,231,6,116,117,29,118,159,127,190,117,69, 84,142,35,29,209,145,142,155,61,255,15,235,255,116,70,93,221,233,184,249,59, 139,104,5,153,138,157,175,133,88,167,80,11,2,162,172,237,106,89,5,227,40,96,239, 79,74,54,129,205,0,197,12,136,19,42,39,237,16,247,243,106,192,192,78,121,223, 146,26,207,91,116,235,98,42,31,99,195,31,215,79,114,41,75,134,155,48,178,185, 195,59,114,248,56,130,162,143,230,139,166,216,194,164,43,209,29,167,85,76,243, 191,48,76,155,28,199,241,108,76,164,205,108,74,90,70,114,154,123,36,150,4,21, 113,179,40,171,29,9,204,34,41,187,26,227,199,93,100,255,190,223,113,204,72,44, 249,76,101,22,35,15,135,187,62,26,98,34,31,67,234,207,177,27,148,244,134,210, 116,136,134,101,4,36,215,229,224,180,175,55,246,112,197,158,80,131,190,86,25,72, 95,85,25,210,97,185,90,89,235,131,82,104,175,114,48,164,97,93,139,51,235,155, 104,168,151,251,232,248,103,20,202,119,212,86,31,61,122,108,149,4,80,67,67,131, 189,136,228,195,30,114,127,129,26,74,235,205,128,67,234,83,200,83,249,222,152, 118,58,94,249,89,242,46,172,108,42,95,195,180,101,87,47,35,233,202,106,232,196, 168,98,176,15,30,124,26,254,254,161,170,233,234,234,194,208,198,122,81,52,202, 53,156,51,196,44,186,245,230,127,13,169,111,200,38,186,23,253,6,120,82,231,221, 176,196,226,159,208,145,112,107,172,97,9,97,81,9,159,217,14,33,166,242,18,73, 230,4,103,29,223,243,217,94,114,184,238,68,118,63,97,36,82,174,152,47,212,204, 238,14,243,174,189,2,19,155,135,117,203,225,246,210,218,222,241,22,3,134,23,84, 238,147,74,103,27,19,11,113,26,120,114,249,176,150,90,139,203,237,112,5,133,83, 163,124,159,80,105,166,84,154,25,123,221,51,105,57,150,247,65,216,203,236,81, 116,89,108,93,41,107,255,5,119,155,194,247,64,241,254,70,0,0,0,0,73,69,78,68, 174,66,96,130}; static Fl_Image *image_fd_user() { static Fl_Image *image = NULL; if (!image) image = new Fl_PNG_Image("fd_user.png", idata_fd_user, 8612); return image; } Fl_Group *w_settings_i18n_tab=(Fl_Group *)0; static void cb_w_settings_i18n_tab(Fl_Group* o, void* v) { propagate_load(o, v); } static const unsigned char idata_language_64[] = {137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,96,0,0,0,64,8,4,0,0,0, 79,61,186,133,0,0,5,113,73,68,65,84,104,222,237,154,107,76,28,85,20,199,127, 188,10,44,182,184,116,75,75,65,1,129,146,20,140,15,106,91,170,166,129,182,40,98, 53,104,98,66,240,145,26,67,140,38,245,21,245,139,177,54,126,48,126,48,209,38, 162,198,132,24,141,181,173,209,86,98,130,129,32,98,1,91,196,214,90,181,136,20, 90,160,32,10,8,88,96,11,44,227,7,102,239,206,46,236,206,238,236,206,204,154, 120,246,195,158,123,103,231,222,243,223,123,207,255,156,251,0,117,89,193,43,140, 226,64,210,244,89,96,154,47,72,197,52,137,230,144,102,227,93,159,78,178,204,2, 176,63,4,230,75,72,52,154,5,96,52,36,230,75,204,82,164,207,4,81,147,171,157,74, 28,177,26,58,152,112,42,49,220,74,147,25,0,34,157,230,239,39,131,133,128,26, 143,96,154,26,90,156,197,181,230,140,128,44,177,92,171,193,15,167,72,116,21,162, 244,0,16,25,124,19,14,102,152,51,145,36,131,148,113,154,57,199,90,138,200,88, 182,249,213,174,194,80,24,2,88,160,153,87,1,24,96,175,114,186,136,137,183,133, 134,69,203,71,248,52,140,0,56,24,225,31,192,206,247,114,77,43,219,73,101,129,56, 214,16,167,248,229,205,188,193,69,86,83,85,78,167,30,0,34,84,127,33,45,126,37, 242,46,57,194,252,54,62,164,199,157,38,101,154,181,114,15,229,172,92,210,204, 166,136,48,242,129,17,14,114,122,73,173,29,59,48,193,1,242,40,48,204,137,53,177, 208,140,138,63,254,105,32,11,105,2,96,101,147,74,204,8,115,26,77,228,65,210,232, 195,225,230,42,221,116,201,250,42,225,43,179,174,216,189,53,160,46,254,162,159, 89,29,89,40,131,74,143,246,175,80,35,0,196,3,115,116,241,19,3,92,118,254,224, 120,64,29,204,49,204,219,188,201,188,110,113,32,134,24,15,0,3,178,102,195,194, 28,245,188,47,106,52,244,20,77,6,175,147,207,99,106,16,52,166,18,14,134,185, 160,160,80,152,18,230,166,96,225,20,175,185,155,175,205,63,31,226,57,93,156,216, 65,27,47,241,56,111,113,65,212,13,10,61,23,7,141,216,67,67,49,207,232,26,7,106, 73,39,149,24,64,226,146,120,154,206,44,103,68,41,73,67,251,118,166,157,234,26, 93,0,184,226,192,143,236,38,9,152,22,14,12,89,56,24,145,245,93,236,37,193,25, 204,253,254,219,187,121,202,9,33,82,23,0,241,88,229,25,126,142,113,146,128,63, 104,149,159,165,145,162,224,39,43,185,92,165,33,69,140,115,141,129,30,62,144, 200,13,98,50,245,2,18,231,196,152,220,66,82,128,255,184,9,145,56,86,177,54,107, 101,146,9,78,186,146,182,128,167,140,9,0,34,200,37,69,214,107,233,228,23,234,68, 128,203,53,120,69,166,49,14,92,195,46,161,31,84,172,84,118,178,238,191,1,32,158, 109,66,111,17,251,14,113,108,115,91,204,132,49,0,216,200,158,37,117,21,100,27, 190,168,215,12,192,66,9,121,30,9,222,78,44,126,190,61,65,19,71,57,19,130,221, 140,32,182,85,50,20,126,0,144,185,204,66,210,91,32,252,152,74,158,164,74,193,94, 134,3,152,166,221,163,251,38,222,161,141,73,63,222,237,162,26,128,126,142,50, 110,206,174,68,47,95,114,204,45,27,5,168,163,137,18,74,177,120,164,218,158,169, 254,9,198,100,253,19,42,84,86,119,186,0,24,231,35,106,189,164,97,181,116,113, 151,79,46,186,36,162,6,64,51,121,196,27,61,133,198,57,165,40,149,242,60,215,43, 202,157,124,231,35,153,150,232,160,93,81,254,156,126,227,71,32,158,20,57,153, 139,99,15,101,216,40,160,142,195,178,217,54,114,124,24,53,202,215,30,147,177, 157,172,32,246,125,53,1,176,81,201,60,253,108,225,110,242,137,7,178,121,148,219, 105,230,56,243,84,144,69,131,215,119,207,114,108,137,231,20,179,222,88,0,81,20, 146,195,12,86,86,137,173,189,4,110,100,3,247,1,201,244,123,77,134,167,150,89, 219,55,113,214,104,0,16,181,236,105,133,69,14,100,222,179,209,223,57,34,107,235, 72,17,187,123,245,108,198,106,124,32,11,92,230,56,41,8,244,14,158,37,83,144, 233,121,51,34,113,224,162,36,208,29,108,165,76,65,166,51,225,15,64,73,160,59, 200,35,129,219,66,64,166,126,251,192,21,250,136,244,114,200,23,193,74,108,170, 84,168,36,208,116,70,152,4,242,249,57,72,50,85,7,176,176,56,74,118,246,249,216, 180,189,142,71,40,84,49,64,73,160,135,100,221,30,52,153,170,3,24,195,230,76,19, 188,199,215,211,68,147,227,243,28,213,157,64,167,151,16,173,86,50,85,247,129, 106,255,14,135,135,84,220,176,91,16,168,55,169,15,58,51,245,54,70,31,248,117,91, 98,150,59,21,160,229,218,7,164,46,105,80,26,148,46,74,251,252,184,142,80,43,13, 74,131,210,160,212,40,37,185,106,131,158,66,243,84,209,206,211,164,249,204,145, 47,115,128,175,252,35,208,18,172,110,118,245,208,17,68,102,234,15,11,205,82,77, 13,169,62,246,41,37,250,124,157,58,41,9,180,136,151,73,118,123,122,130,135,5, 153,238,102,131,78,52,106,231,188,246,112,57,198,55,66,47,35,221,131,173,110, 226,126,62,147,201,180,131,236,0,67,147,33,129,108,92,100,61,57,108,94,66,182, 73,138,123,56,191,6,188,45,111,8,0,11,105,178,86,46,52,101,24,44,160,80,214, 215,251,116,180,16,102,163,129,73,50,85,204,211,75,49,247,46,187,216,76,227,9, 160,151,98,74,195,19,64,20,219,217,200,20,54,215,237,169,128,158,155,14,0,162, 197,102,176,182,231,97,146,78,235,33,255,3,48,91,244,241,1,113,7,225,111,126, 211,112,200,215,19,64,52,208,7,128,72,43,26,248,65,195,235,138,99,214,5,115,0, 180,48,231,36,244,177,224,90,26,54,107,106,126,27,146,219,190,14,94,52,11,64,38, 157,33,48,255,61,163,226,212,114,146,206,17,166,130,48,126,136,23,88,161,222, 205,191,56,75,123,84,202,251,159,166,0,0,0,0,73,69,78,68,174,66,96,130}; static Fl_Image *image_language_64() { static Fl_Image *image = NULL; if (!image) image = new Fl_PNG_Image("language_64.png", idata_language_64, 1450); return image; } Fl_Choice *i18n_type_chooser=(Fl_Choice *)0; Fl_Menu_Item menu_i18n_type_chooser[] = { {"None", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"GNU gettext", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"POSIX catgets", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Group *i18n_gnu_group=(Fl_Group *)0; static void cb_i18n_gnu_group(Fl_Group* o, void* v) { propagate_load(o, v); } Fl_Input *i18n_gnu_include_input=(Fl_Input *)0; static void cb_i18n_gnu_include_input(Fl_Input* o, void* v) { if (v == LOAD) { o->value(g_project.i18n_gnu_include.c_str()); } else { undo_checkpoint(); g_project.i18n_gnu_include = o->value(); set_modflag(1); } } Fl_Input *i18n_gnu_conditional_input=(Fl_Input *)0; static void cb_i18n_gnu_conditional_input(Fl_Input* o, void* v) { if (v == LOAD) { o->value(g_project.i18n_gnu_conditional.c_str()); } else { undo_checkpoint(); g_project.i18n_gnu_conditional = o->value(); set_modflag(1); } } Fl_Input *i18n_gnu_function_input=(Fl_Input *)0; static void cb_i18n_gnu_function_input(Fl_Input* o, void* v) { if (v == LOAD) { o->value(g_project.i18n_gnu_function.c_str()); } else { undo_checkpoint(); g_project.i18n_gnu_function = o->value(); set_modflag(1); } } Fl_Input *i18n_gnu_static_function_input=(Fl_Input *)0; static void cb_i18n_gnu_static_function_input(Fl_Input* o, void* v) { if (v == LOAD) { o->value(g_project.i18n_gnu_static_function.c_str()); } else { undo_checkpoint(); g_project.i18n_gnu_static_function = o->value(); set_modflag(1); } } Fl_Group *i18n_posix_group=(Fl_Group *)0; static void cb_i18n_posix_group(Fl_Group* o, void* v) { propagate_load(o, v); } Fl_Input *i18n_pos_include_input=(Fl_Input *)0; static void cb_i18n_pos_include_input(Fl_Input* o, void* v) { if (v == LOAD) { o->value(g_project.i18n_pos_include.c_str()); } else { undo_checkpoint(); g_project.i18n_pos_include = o->value(); set_modflag(1); } } Fl_Input *i18n_pos_conditional_input=(Fl_Input *)0; static void cb_i18n_pos_conditional_input(Fl_Input* o, void* v) { if (v == LOAD) { o->value(g_project.i18n_pos_conditional.c_str()); } else { undo_checkpoint(); g_project.i18n_pos_conditional = o->value(); set_modflag(1); } } Fl_Input *i18n_pos_file_input=(Fl_Input *)0; static void cb_i18n_pos_file_input(Fl_Input* o, void* v) { if (v == LOAD) { o->value(g_project.i18n_pos_file.c_str()); } else { undo_checkpoint(); g_project.i18n_pos_file = o->value(); set_modflag(1); } } static void cb_c(Fl_Group* o, void* v) { propagate_load(o, v); } Fl_Int_Input *i18n_pos_set_input=(Fl_Int_Input *)0; static void cb_i18n_pos_set_input(Fl_Int_Input* o, void* v) { if (v == LOAD) { o->value(g_project.i18n_pos_set.c_str()); } else { undo_checkpoint(); g_project.i18n_pos_set = o->value(); set_modflag(1); } } Fl_Group *w_settings_user_tab=(Fl_Group *)0; static void cb_w_settings_user_tab(Fl_Group* o, void* v) { propagate_load(o, v); } static const unsigned char idata_user_circle_64[] = {137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,96,0,0,0,64,8,6,0,0,0, 229,52,114,14,0,0,1,110,105,67,67,80,105,99,99,0,0,40,145,117,145,187,75,195,80, 20,198,127,182,74,69,171,14,138,136,56,68,80,113,168,32,10,226,168,117,232,82, 164,212,10,190,150,38,77,91,161,143,144,180,72,113,21,92,28,10,14,162,139,175, 193,255,64,87,193,85,65,16,20,65,196,205,221,215,34,18,207,53,66,69,244,134,155, 243,227,187,247,59,156,124,1,95,52,103,228,157,250,9,200,23,74,118,60,18,214, 230,230,23,180,192,35,65,90,233,100,132,222,164,225,88,147,177,88,148,127,215, 219,53,117,170,94,13,169,94,255,223,251,115,53,167,76,199,128,186,70,225,49,195, 178,75,194,50,13,209,149,146,165,120,67,184,195,200,38,83,194,123,194,33,91,6, 20,62,87,186,238,241,131,226,140,199,47,138,237,68,124,10,124,170,167,150,249, 193,250,15,54,178,118,94,120,80,184,47,159,43,27,223,243,168,47,9,154,133,217, 25,169,221,178,123,112,136,19,33,140,134,78,153,101,114,148,24,146,90,144,204, 254,246,13,127,249,166,41,138,199,144,183,69,5,91,28,25,178,226,13,137,90,150, 174,166,212,180,232,166,60,57,42,42,247,223,121,58,233,209,17,175,123,48,12,13, 247,174,251,220,15,129,77,248,168,186,238,251,190,235,126,28,128,255,14,78,11, 53,127,81,114,26,127,21,189,90,211,250,118,161,109,13,142,207,106,154,190,5,39, 235,208,117,107,37,237,228,151,228,151,237,75,167,225,233,8,90,230,161,253,18, 154,22,189,172,190,207,57,188,129,196,170,252,162,11,216,222,129,1,185,223,182, 244,9,79,172,104,46,25,119,193,26,0,0,0,9,112,72,89,115,0,0,59,14,0,0,59,14,1, 204,182,161,131,0,0,13,125,73,68,65,84,120,94,213,156,9,236,86,197,17,192,7,4, 20,177,10,8,2,162,96,16,209,130,40,136,82,4,27,174,214,139,195,8,8,166,73,1,5, 194,77,75,64,1,141,28,81,74,72,56,203,101,61,138,130,137,82,3,104,64,52,16,16, 218,130,28,22,149,163,9,1,4,148,163,30,92,162,92,94,157,223,203,247,253,243,142, 125,223,187,246,195,63,147,108,248,243,190,221,217,153,157,221,217,217,217,153, 45,35,25,225,231,159,127,206,136,193,220,188,76,153,50,21,244,151,22,90,218, 106,249,173,150,134,90,106,197,236,236,136,214,251,175,150,127,105,89,163,101, 147,210,121,62,102,219,68,213,148,206,68,245,173,87,70,0,182,138,18,87,86,203, 239,181,44,208,114,74,11,210,181,81,192,5,206,223,209,135,45,122,139,53,249,18, 9,201,6,51,218,225,229,90,254,164,229,128,165,1,47,36,52,250,24,166,165,162, 37,218,19,141,151,245,202,89,152,80,98,202,107,25,169,229,139,11,48,240,126, 161,252,79,251,28,14,13,25,121,200,52,166,153,21,88,218,101,168,186,179,141,82, 62,71,11,186,61,18,174,184,226,10,169,87,175,158,220,120,227,141,114,237,181, 215,202,149,87,94,41,149,42,85,114,218,125,247,221,119,242,205,55,223,200,161, 67,135,228,211,79,63,117,202,183,223,126,27,137,51,87,97,167,254,59,72,249,248, 103,220,6,238,122,89,247,128,11,46,0,37,248,50,101,96,154,150,1,90,66,251,47,91, 182,172,180,108,217,82,218,181,107,39,119,223,125,183,52,108,216,80,248,22,7, 126,250,233,39,217,185,115,167,108,216,176,65,214,172,89,35,27,55,110,20,190,21, 0,86,7,147,97,164,10,226,92,156,62,242,117,46,42,1,40,177,13,148,240,69,90, 154,132,49,89,163,70,13,233,213,171,151,116,235,214,77,106,213,138,107,244,20, 30,178,195,135,15,203,226,197,139,229,213,87,95,149,47,190,64,219,133,194,86, 253,165,135,10,97,79,92,33,92,52,2,80,66,239,81,166,150,105,169,108,98,174,118, 237,218,50,100,200,16,233,222,189,187,84,168,128,5,106,31,206,159,63,47,139,22, 45,146,89,179,102,201,145,35,88,170,70,56,166,95,59,169,16,54,196,161,224,162, 16,128,18,217,81,153,249,135,150,138,126,166,202,149,43,39,61,123,246,148,39, 158,120,66,208,243,23,2,206,156,57,35,243,230,205,147,217,179,103,203,247,223, 127,111,234,18,53,244,7,21,194,146,40,122,74,189,0,148,192,206,202,196,98,45, 229,252,204,176,169,206,157,59,87,26,53,106,20,197,103,81,126,223,190,125,187, 12,26,52,72,246,239,223,111,194,143,100,186,168,16,150,23,234,60,171,0,226,237, 106,41,217,87,226,56,193,190,97,26,252,78,157,58,201,59,239,188,243,139,13,62, 44,53,110,220,88,222,125,247,93,233,208,161,131,137,67,76,228,69,202,67,203, 148,236,199,106,86,52,43,40,183,225,110,82,42,2,58,191,95,191,126,242,204,51, 207,72,218,217,115,236,216,49,217,189,123,119,137,30,103,179,110,208,160,129,84, 169,82,37,22,211,254,74,88,72,207,62,251,172,188,244,210,75,166,246,236,9,205, 117,37,236,53,253,152,150,135,60,174,162,8,32,103,106,126,160,157,4,172,29,116, 253,176,97,28,68,147,1,231,141,101,203,150,201,194,133,11,101,203,150,45,242, 227,143,63,122,16,92,114,201,37,114,215,93,119,57,251,73,199,142,29,83,9,119, 230,204,153,50,101,202,20,19,97,255,209,143,173,76,38,106,105,21,192,92,37,120, 160,159,19,102,254,216,177,99,147,141,188,214,70,71,15,30,60,88,182,109,219,22, 171,109,211,166,77,157,13,182,78,157,58,177,234,187,43,77,152,48,33,108,37,204, 86,1,12,245,35,44,117,2,200,157,112,241,64,122,86,23,58,127,206,156,57,137,103, 38,179,189,79,159,62,114,252,248,241,68,131,89,181,106,85,121,249,229,151,229, 206,59,239,76,212,14,117,196,198,204,254,228,3,14,107,109,252,39,230,82,37,0,37, 6,75,135,195,76,99,55,241,55,220,112,131,179,217,37,53,51,63,255,252,115,71, 157,160,243,211,64,229,202,149,29,181,69,255,73,0,215,6,27,243,222,189,1,181, 143,219,162,169,10,161,196,118,45,109,2,24,161,4,122,148,40,118,254,242,229,203, 19,91,59,232,124,86,205,39,159,124,18,24,59,4,217,166,77,27,103,227,5,118,237, 218,37,235,214,173,51,250,127,238,184,227,14,121,235,173,183,18,175,60,76,212, 206,157,59,203,15,63,252,224,239,127,184,210,54,35,255,49,171,0,2,182,121,146, 153,226,174,171,132,224,82,126,210,223,190,127,255,254,137,7,31,28,8,205,52,248, 247,221,119,159,140,26,53,202,113,198,185,225,228,201,147,50,121,242,100,89,185, 114,165,231,251,214,173,91,29,117,194,74,74,2,152,168,143,63,254,184,188,240, 194,11,254,102,163,149,215,191,169,16,206,36,193,23,86,215,230,57,160,175,118, 114,141,187,35,220,11,105,44,30,112,224,183,241,3,131,255,220,115,207,5,6,159, 122,87,93,117,149,76,156,56,81,238,189,247,222,64,187,5,11,184,139,73,14,195, 135,15,151,154,53,107,250,27,214,208,15,125,146,99,51,183,176,34,0,157,17,224, 65,253,120,0,223,206,229,151,179,48,146,1,58,255,195,15,63,244,52,66,237,48, 243,11,45,121,126,163,78,222,77,157,71,192,70,126,226,196,137,100,68,104,109, 250,28,58,52,96,248,128,103,100,142,231,196,56,253,13,172,8,64,145,182,215,226, 177,249,170,87,175,46,143,60,242,72,42,2,209,233,126,59,31,157,239,87,59,38,228, 172,4,234,186,1,61,14,206,52,208,163,71,15,193,67,235,131,186,250,127,111,39, 105,144,107,27,91,2,248,163,191,127,244,231,165,151,94,154,138,44,147,203,56, 191,225,198,65,120,211,77,55,5,170,69,184,161,67,209,194,3,135,59,3,4,120,142, 67,155,245,21,160,75,145,81,126,216,141,152,139,147,174,93,187,166,161,199,105, 99,82,51,17,23,42,158,190,210,222,210,133,17,220,165,75,23,19,77,93,149,78,252, 69,153,192,198,10,248,141,82,224,241,35,115,147,149,229,50,229,154,107,60,123, 185,195,224,158,61,177,239,72,28,63,145,31,12,106,36,246,192,93,119,221,117,210, 188,121,115,127,253,95,233,135,192,199,216,72,115,21,109,8,160,157,191,83,174, 17,179,192,45,183,220,34,248,118,220,176,118,237,90,193,212,140,2,54,91,206,4, 110,224,44,114,243,205,55,71,53,45,248,123,8,79,217,24,213,30,109,8,0,151,179,7, 184,195,205,2,120,53,113,172,185,129,75,118,236,252,66,234,133,223,38,77,154, 228,92,210,187,129,217,203,169,56,11,220,115,15,23,122,1,8,240,158,180,15,27,2, 248,181,187,83,76,55,46,208,179,130,105,227,227,144,245,244,211,79,27,87,2,51, 127,244,232,209,178,122,245,234,64,215,33,155,104,34,18,185,52,242,155,183,138, 32,51,163,153,221,209,74,132,39,54,241,246,219,111,119,78,177,89,129,217,252, 208,67,15,201,71,31,125,20,64,197,64,180,110,221,186,68,173,228,93,17,254,153, 79,67,156,113,75,150,44,73,236,138,48,209,255,224,131,15,10,46,10,23,192,123, 166,73,108,205,21,145,39,138,184,29,27,128,37,196,117,37,46,132,163,71,143,122, 80,50,208,43,86,172,112,74,33,64,149,225,227,207,234,175,201,247,193,21,170,79, 0,153,39,112,38,233,153,152,39,104,202,22,96,125,224,82,198,181,156,20,104, 243,202,43,175,164,186,19,8,235,11,122,108,131,117,1,36,117,57,71,49,212,172,89, 51,199,165,140,87,51,46,160,118,112,192,37,105,19,7,183,97,15,136,211,172,96, 29,235,2,40,6,145,220,108,225,82,38,148,4,11,11,179,210,15,124,227,252,241,252, 243,207,59,58,191,24,179,213,246,228,130,7,235,123,64,230,41,17,130,0,61,206, 126,64,225,118,140,195,22,17,111,124,207,95,202,103,53,53,139,69,123,33,188,214, 5,96,178,68,108,51,198,230,106,56,153,218,238,38,128,47,65,192,111,108,90,172, 171,160,98,16,25,155,155,34,87,44,6,111,214,87,0,33,226,197,132,211,167,79,59, 234,135,59,131,252,69,61,43,2,171,7,47,104,154,251,135,184,244,22,131,55,235,2, 48,92,100,199,229,47,180,30,97,41,47,190,248,162,188,255,254,251,114,240,224, 193,80,119,4,251,193,245,215,95,47,109,219,182,21,66,96,234,214,197,109,111,15, 200,59,240,65,230,4,185,204,7,9,37,232,176,150,146,56,114,44,5,98,243,227,198, 242,23,26,30,240,112,195,69,60,80,82,23,51,194,224,84,142,255,200,134,107,132, 11,34,220,17,190,61,142,229,158,233,112,96,99,15,32,27,177,4,208,147,12,92,22, 56,123,246,172,60,245,212,83,242,192,3,15,56,23,243,73,7,159,190,105,243,241, 199,31,203,253,247,223,47,99,198,140,145,115,231,18,229,93,4,200,223,177,99,71, 192,201,167,149,60,188,167,225,217,134,0,72,5,245,192,7,31,16,149,152,14,208, 235,248,92,8,65,76,51,240,1,29,161,130,120,237,181,215,132,11,253,175,191,254, 58,29,81,218,106,253,250,245,166,182,169,210,154,220,136,108,168,32,92,178,30, 66,90,181,106,37,111,188,65,80,116,50,192,174,103,214,23,10,196,226,98,133,208, 67,14,90,220,255,2,220,19,16,196,133,227,238,203,47,191,12,237,180,90,181,106, 78,128,152,33,210,33,146,80,50,118,54,109,34,214,216,3,173,244,127,177,18,57, 194,58,176,33,0,210,89,240,150,149,220,138,161,255,89,5,73,252,66,232,214,246, 237,219,59,137,118,126,0,31,225,38,143,62,250,168,220,122,235,173,5,7,11,103,25, 194,199,117,109,90,65,108,210,171,86,173,50,185,150,67,241,178,241,115,202,246, 225,227,118,168,186,22,99,134,71,164,68,115,21,50,171,32,37,138,12,116,79,38,9, 247,183,228,100,37,129,199,30,123,204,56,248,184,33,8,27,39,30,40,106,240,233, 143,128,42,226,131,176,154,76,193,185,172,20,98,77,147,0,174,13,131,48,23,187, 67,20,147,224,115,215,205,44,128,28,178,133,126,2,230,207,159,47,108,166,113, 96,233,210,165,206,138,241,3,170,6,143,230,109,183,221,22,7,141,167,78,147,38, 77,4,26,76,109,209,231,111,191,253,118,44,156,108,222,33,129,93,1,158,99,33, 244,85,178,37,0,162,161,63,115,227,254,234,171,175,228,205,55,223,140,164,233, 212,169,83,142,149,226,7,14,85,248,242,227,196,2,133,117,194,30,65,66,30,126, 124,63,96,222,198,57,217,190,254,250,235,166,204,202,253,138,47,243,6,12,77,86, 4,160,75,145,36,220,169,126,38,97,62,202,55,132,247,210,95,135,211,236,212, 169,83,173,156,106,241,206,78,159,62,61,128,139,62,233,187,16,32,32,242,12,12, 48,37,199,115,228,4,139,170,96,69,0,185,78,136,98,245,228,126,146,10,58,99,70, 73,32,113,128,22,150,55,23,46,126,32,62,63,201,6,30,197,36,49,170,3,6,144,23, 238,5,246,137,66,106,114,218,180,105,166,217,207,19,7,127,143,234,51,238,239, 214,4,160,51,2,133,31,200,239,97,3,245,93,227,149,208,134,107,193,63,251,25,44, 194,1,109,3,56,253,66,197,175,68,184,139,9,56,125,179,135,24,224,47,182,34,163, 173,169,32,23,145,127,213,191,61,121,68,196,101,50,163,209,245,126,48,221,213, 226,195,241,199,4,217,16,6,201,223,36,6,198,161,129,119,39,6,14,28,104,202,13, 216,161,237,11,235,173,132,196,90,91,1,244,171,51,131,108,6,194,137,61,78,42, 156,105,36,231,249,195,11,113,154,229,55,72,108,125,254,38,41,34,73,24,98,92, 126,241,229,112,135,128,153,90,191,126,125,105,209,162,133,211,31,52,184,129, 190,71,140,24,33,159,125,230,177,41,28,246,180,12,180,97,122,186,251,203,124,16, 51,29,118,116,102,207,210,78,134,248,7,167,111,223,190,50,110,220,56,207,103, 102,27,106,136,213,192,204,47,198,224,187,59,164,143,124,228,53,127,95,125,245, 213,158,168,9,146,8,67,84,207,76,229,245,207,113,86,80,220,73,81,12,21,148,239, 155,55,128,200,21,243,0,251,1,166,101,30,80,79,60,27,192,236,71,0,89,6,159,246, 224,193,130,66,221,132,169,49,119,216,59,127,187,247,32,172,165,144,193,223,162, 52,7,178,127,146,12,116,88,221,162,172,0,58,211,1,169,175,255,224,60,9,196,148, 176,18,208,199,188,211,144,38,113,194,179,132,115,43,199,180,159,32,224,40,135, 30,2,195,84,29,63,126,124,216,224,227,102,33,81,59,112,25,144,227,51,147,28, 138,38,128,28,113,164,249,175,210,18,72,147,193,227,137,173,143,25,232,79,198, 200,196,81,130,198,172,24,226,255,209,249,239,189,247,158,169,229,105,253,216, 94,7,127,99,232,12,206,248,104,95,81,5,144,19,2,217,113,248,138,2,177,244,164, 143,114,24,194,103,195,83,50,134,140,196,4,195,25,191,42,171,165,98,197,138,114, 224,192,1,33,137,208,176,225,130,12,39,219,195,58,248,129,132,97,255,10,140,223, 115,176,102,209,5,224,18,2,15,53,5,86,130,251,185,26,234,70,157,156,211,50,203, 108,47,95,190,188,51,240,172,56,4,95,224,185,26,102,126,247,168,193,47,245,42, 200,55,83,80,71,60,216,100,140,51,196,71,79,66,28,15,54,1,172,6,27,234,137,217, 78,188,16,27,51,248,112,85,51,240,5,82,150,208,249,29,11,169,157,139,110,5,228, 9,214,193,32,114,151,149,208,44,108,38,147,29,211,187,119,111,33,45,136,83,49, 179,21,75,41,169,48,24,120,86,23,27,44,142,65,92,202,120,86,249,187,0,96,237, 240,100,217,190,184,43,45,107,224,239,5,81,65,190,25,67,78,25,46,139,193,90,10, 62,218,199,193,137,204,20,110,216,184,16,71,24,249,187,93,172,27,204,86,10,127, 163,98,242,129,0,12,60,41,77,60,218,71,190,192,230,205,155,163,172,33,14,89,156, 226,159,204,221,111,196,29,255,204,145,215,23,92,0,174,213,192,85,38,175,170,20, 190,226,202,53,96,38,115,114,165,224,211,193,213,236,126,182,146,107,73,110,211, 246,237,219,231,60,91,153,96,47,193,117,50,88,7,254,223,177,71,221,85,49,235,10, 72,211,167,167,13,179,47,109,81,68,88,70,188,152,139,23,213,198,19,197,73,112, 16,78,195,195,69,229,210,210,31,117,198,200,60,184,113,16,100,33,62,223,86,251, 225,49,63,92,23,232,222,36,131,152,166,46,125,160,254,46,179,68,123,156,97,42, 94,29,27,76,184,4,129,115,16,239,24,126,96,46,189,211,12,176,169,13,239,20,224, 195,7,119,169,122,188,251,23,219,3,162,166,68,46,9,154,60,92,82,65,243,207,215, 215,142,106,151,251,157,208,10,130,166,184,54,228,186,116,115,206,83,27,179,121, 252,106,89,247,128,255,3,60,207,245,248,165,38,113,147,0,0,0,0,73,69,78,68,174, 66,96,130}; static Fl_Image *image_user_circle_64() { static Fl_Image *image = NULL; if (!image) image = new Fl_PNG_Image("user_circle_64.png", idata_user_circle_64, 3909); return image; } Fl_Choice *w_settings_user_commenttext=(Fl_Choice *)0; static void cb_Close(Fl_Button*, void*) { if (g_shell_config) g_shell_config->write(fluid_prefs, FD_STORE_USER); g_layout_list.write(fluid_prefs, FD_STORE_USER); settings_window->hide(); } Fl_Double_Window* make_settings_window() { { settings_window = new Fl_Double_Window(340, 580, "FLUID Settings"); settings_window->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); { w_settings_tabs = new Fl_Tabs(10, 10, 320, 530); w_settings_tabs->selection_color((Fl_Color)12); w_settings_tabs->labelsize(11); w_settings_tabs->labelcolor(FL_WHITE); w_settings_tabs->callback((Fl_Callback*)cb_w_settings_tabs); { w_settings_general_tab = new Fl_Group(10, 60, 320, 480, "General"); w_settings_general_tab->image( image_general_64() ); w_settings_general_tab->image()->scale(36, 24, 0, 1); w_settings_general_tab->labelsize(11); { Fl_Group* o = new Fl_Group(120, 78, 130, 25); o->callback((Fl_Callback*)cb_); { scheme_choice = new Fl_Scheme_Choice(120, 78, 120, 25, "Scheme: "); scheme_choice->box(FL_UP_BOX); scheme_choice->down_box(FL_BORDER_BOX); scheme_choice->color(FL_BACKGROUND_COLOR); scheme_choice->selection_color(FL_SELECTION_COLOR); scheme_choice->labeltype(FL_NORMAL_LABEL); scheme_choice->labelfont(1); scheme_choice->labelsize(11); scheme_choice->labelcolor(FL_FOREGROUND_COLOR); scheme_choice->callback((Fl_Callback*)scheme_cb); scheme_choice->align(Fl_Align(FL_ALIGN_LEFT)); scheme_choice->when(FL_WHEN_RELEASE); init_scheme(); } // Fl_Scheme_Choice* scheme_choice { Fl_Box* o = new Fl_Box(240, 78, 10, 25); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(120, 115, 0, 20, "Options: "); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT)); } // Fl_Box* o { tooltips_button = new Fl_Check_Button(120, 115, 200, 20, "Show Tooltips"); tooltips_button->down_box(FL_DOWN_BOX); tooltips_button->labelsize(11); tooltips_button->callback((Fl_Callback*)cb_tooltips_button); int b; fluid_prefs.get("show_tooltips", b, 1); tooltips_button->value(b); Fl_Tooltip::enable(b); } // Fl_Check_Button* tooltips_button { completion_button = new Fl_Check_Button(120, 135, 200, 20, "Show Completion Dialogs"); completion_button->down_box(FL_DOWN_BOX); completion_button->labelsize(11); completion_button->callback((Fl_Callback*)cb_completion_button); int b; fluid_prefs.get("show_completion_dialogs", b, 1); completion_button->value(b); } // Fl_Check_Button* completion_button { openlast_button = new Fl_Check_Button(120, 155, 200, 20, "Open Previous File on Startup"); openlast_button->down_box(FL_DOWN_BOX); openlast_button->labelsize(11); openlast_button->callback((Fl_Callback*)cb_openlast_button); int b; fluid_prefs.get("open_previous_file", b, 0); openlast_button->value(b); } // Fl_Check_Button* openlast_button { prevpos_button = new Fl_Check_Button(120, 175, 200, 20, "Remember Window Positions"); prevpos_button->down_box(FL_DOWN_BOX); prevpos_button->labelsize(11); prevpos_button->callback((Fl_Callback*)cb_prevpos_button); int b; fluid_prefs.get("prev_window_pos", b, 1); prevpos_button->value(b); } // Fl_Check_Button* prevpos_button { show_comments_button = new Fl_Check_Button(120, 195, 200, 20, "Show Comments in Browser"); show_comments_button->down_box(FL_DOWN_BOX); show_comments_button->labelsize(11); show_comments_button->callback((Fl_Callback*)cb_show_comments_button); fluid_prefs.get("show_comments", show_comments, 1); show_comments_button->value(show_comments); } // Fl_Check_Button* show_comments_button { Fl_Group* o = new Fl_Group(120, 225, 50, 20); o->callback((Fl_Callback*)cb_1); { recent_spinner = new Fl_Spinner(120, 225, 40, 20, "# Recent Files:"); recent_spinner->labelfont(1); recent_spinner->labelsize(11); recent_spinner->maximum(10); recent_spinner->textsize(11); recent_spinner->callback((Fl_Callback*)cb_recent_spinner); recent_spinner->when(FL_WHEN_CHANGED); int c; fluid_prefs.get("recent_files", c, 5); recent_spinner->maximum(10); recent_spinner->value(c); } // Fl_Spinner* recent_spinner { Fl_Box* o = new Fl_Box(160, 225, 10, 20); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { use_external_editor_button = new Fl_Check_Button(120, 275, 200, 20, "Use for Code Nodes"); use_external_editor_button->down_box(FL_DOWN_BOX); use_external_editor_button->labelsize(11); use_external_editor_button->callback((Fl_Callback*)cb_use_external_editor_button); fluid_prefs.get("use_external_editor", G_use_external_editor, 0); use_external_editor_button->value(G_use_external_editor); } // Fl_Check_Button* use_external_editor_button { editor_command_input = new Fl_Input(120, 255, 200, 20, "External Editor:"); editor_command_input->tooltip("The editor command to open your external text editor.\nInclude any necessary " "flags to ensure your editor does not background itself.\nExamples:\n gvim -" "f\n gedit\n emacs"); editor_command_input->labelfont(1); editor_command_input->labelsize(11); editor_command_input->textfont(4); editor_command_input->textsize(11); editor_command_input->callback((Fl_Callback*)cb_editor_command_input); editor_command_input->when(FL_WHEN_CHANGED); fluid_prefs.get("external_editor_command", G_external_editor_command, "", sizeof(G_external_editor_command)-1); editor_command_input->value(G_external_editor_command); } // Fl_Input* editor_command_input { Fl_Box* o = new Fl_Box(120, 300, 0, 20, "Overlays: "); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT)); } // Fl_Box* o { Fl_Check_Button* o = guides_button = new Fl_Check_Button(120, 300, 200, 20, "Show Positioning Guides"); guides_button->tooltip("show guides that help to position and resize widgets and enable snapping"); guides_button->down_box(FL_DOWN_BOX); guides_button->labelsize(11); guides_button->callback((Fl_Callback*)toggle_guides_cb); o->value(show_guides); } // Fl_Check_Button* guides_button { Fl_Check_Button* o = restricted_button = new Fl_Check_Button(120, 320, 200, 20, "Show Restricted Areas"); restricted_button->tooltip("show overlapping and out of bounds areas, show unfilled areas in Fl_Pack grou" "ps"); restricted_button->down_box(FL_DOWN_BOX); restricted_button->labelsize(11); restricted_button->callback((Fl_Callback*)toggle_restricted_cb); o->value(show_restricted); } // Fl_Check_Button* restricted_button { Fl_Check_Button* o = ghosted_outline_button = new Fl_Check_Button(120, 340, 200, 20, "Show Ghosted Group Outlines"); ghosted_outline_button->tooltip("groups with no box type or flat boxtypes without contrast will be rendered wi" "th a dim outline in the editing window only"); ghosted_outline_button->down_box(FL_DOWN_BOX); ghosted_outline_button->labelsize(11); ghosted_outline_button->callback((Fl_Callback*)toggle_ghosted_outline_cb); o->value(show_ghosted_outline); } // Fl_Check_Button* ghosted_outline_button { Fl_Box* o = new Fl_Box(120, 530, 200, 10); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o w_settings_general_tab->end(); Fl_Group::current()->resizable(w_settings_general_tab); } // Fl_Group* w_settings_general_tab { w_settings_project_tab = new Fl_Group(10, 60, 320, 480, "Project"); w_settings_project_tab->image( image_document_64() ); w_settings_project_tab->image()->scale(36, 24, 0, 1); w_settings_project_tab->labelsize(11); w_settings_project_tab->callback((Fl_Callback*)cb_w_settings_project_tab); w_settings_project_tab->hide(); { Fl_Group* o = new Fl_Group(100, 78, 220, 30); { Fl_Box* o = new Fl_Box(100, 78, 210, 30, "Use \"name.ext\" to set a file name\nor just \".ext\" to set extension."); o->labelsize(11); o->align(Fl_Align(132|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(310, 78, 10, 30); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { header_file_input = new Fl_Input(100, 112, 220, 20, "Header File:"); header_file_input->tooltip("The name of the generated header file."); header_file_input->box(FL_THIN_DOWN_BOX); header_file_input->labelfont(1); header_file_input->labelsize(11); header_file_input->textfont(4); header_file_input->textsize(11); header_file_input->callback((Fl_Callback*)cb_header_file_input, (void*)(1)); header_file_input->when(FL_WHEN_CHANGED); } // Fl_Input* header_file_input { code_file_input = new Fl_Input(100, 137, 220, 20, "Code File:"); code_file_input->tooltip("The name of the generated code file."); code_file_input->box(FL_THIN_DOWN_BOX); code_file_input->labelfont(1); code_file_input->labelsize(11); code_file_input->textfont(4); code_file_input->textsize(11); code_file_input->callback((Fl_Callback*)cb_code_file_input, (void*)(1)); code_file_input->when(FL_WHEN_CHANGED); } // Fl_Input* code_file_input { include_H_from_C_button = new Fl_Check_Button(100, 162, 220, 20, "Include Header from Code"); include_H_from_C_button->tooltip("Include the header file from the code file."); include_H_from_C_button->down_box(FL_DOWN_BOX); include_H_from_C_button->labelsize(11); include_H_from_C_button->callback((Fl_Callback*)cb_include_H_from_C_button); } // Fl_Check_Button* include_H_from_C_button { Fl_Box* o = new Fl_Box(100, 205, 0, 20, "Options: "); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT)); } // Fl_Box* o { use_FL_COMMAND_button = new Fl_Check_Button(100, 205, 220, 20, "Menu shortcuts use FL_COMMAND"); use_FL_COMMAND_button->tooltip("Replace FL_CTRL and FL_META with FL_COMMAND when generating menu shortcuts"); use_FL_COMMAND_button->down_box(FL_DOWN_BOX); use_FL_COMMAND_button->labelsize(11); use_FL_COMMAND_button->callback((Fl_Callback*)cb_use_FL_COMMAND_button); } // Fl_Check_Button* use_FL_COMMAND_button { utf8_in_src_button = new Fl_Check_Button(100, 230, 220, 20, "allow Unicode UTF-8 in source code"); utf8_in_src_button->tooltip("For older compilers, characters outside of the printable ASCII range are esca" "ped using octal notation `\\0123`. If this option is checked, Fluid will write" " UTF-8 characters unchanged."); utf8_in_src_button->down_box(FL_DOWN_BOX); utf8_in_src_button->labelsize(11); utf8_in_src_button->callback((Fl_Callback*)cb_utf8_in_src_button); } // Fl_Check_Button* utf8_in_src_button { avoid_early_includes_button = new Fl_Check_Button(100, 255, 220, 20, "avoid early include of Fl.H"); avoid_early_includes_button->tooltip("Do not emit #include until it is needed by another include file."); avoid_early_includes_button->down_box(FL_DOWN_BOX); avoid_early_includes_button->labelsize(11); avoid_early_includes_button->callback((Fl_Callback*)cb_avoid_early_includes_button); } // Fl_Check_Button* avoid_early_includes_button { Fl_Box* o = new Fl_Box(100, 283, 0, 20, "Experimental: "); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT)); o->hide(); } // Fl_Box* o { // // Matt: disabled w_proj_mergeback = new Fl_Check_Button(100, 283, 220, 20, "generate MergeBack data"); w_proj_mergeback->tooltip("MergeBack is a feature under construction that allows changes in code files t" "o be merged back into the project file. Checking this option will generate add" "itional data in code and project files."); w_proj_mergeback->down_box(FL_DOWN_BOX); w_proj_mergeback->labelsize(11); w_proj_mergeback->callback((Fl_Callback*)cb_w_proj_mergeback); w_proj_mergeback->hide(); } // Fl_Check_Button* w_proj_mergeback { Fl_Box* o = new Fl_Box(100, 530, 220, 10); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o w_settings_project_tab->end(); } // Fl_Group* w_settings_project_tab { w_settings_layout_tab = new Fl_Group(10, 60, 320, 480, "Layout"); w_settings_layout_tab->image( image_layout_64() ); w_settings_layout_tab->image()->scale(36, 24, 0, 1); w_settings_layout_tab->labelsize(11); w_settings_layout_tab->callback((Fl_Callback*)cb_w_settings_layout_tab); w_settings_layout_tab->hide(); { Fl_Box* o = new Fl_Box(25, 78, 60, 24, "Layout:"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { layout_choice = new Fl_Choice(85, 78, 187, 24); layout_choice->down_box(FL_BORDER_BOX); layout_choice->callback((Fl_Callback*)cb_layout_choice); layout_choice->menu(menu_layout_choice); } // Fl_Choice* layout_choice { Fl_Button* o = new Fl_Button(272, 78, 24, 24, "+"); o->callback((Fl_Callback*)cb_2); } // Fl_Button* o { w_layout_menu = new Fl_Menu_Button(296, 78, 24, 24); w_layout_menu->callback((Fl_Callback*)cb_w_layout_menu); w_layout_menu_storage[0] = &menu_w_layout_menu[1]; w_layout_menu_storage[1] = &menu_w_layout_menu[2]; w_layout_menu_storage[2] = &menu_w_layout_menu[3]; w_layout_menu_storage[3] = &menu_w_layout_menu[4]; w_layout_menu->menu(menu_w_layout_menu); } // Fl_Menu_Button* w_layout_menu { Fl_Box* o = new Fl_Box(25, 107, 60, 20, "Preset:"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Group* o = new Fl_Group(85, 107, 235, 20); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); { preset_choice[0] = new Fl_Button(85, 107, 78, 20, "Application"); preset_choice[0]->type(102); preset_choice[0]->value(1); preset_choice[0]->compact(1); preset_choice[0]->selection_color(FL_DARK2); preset_choice[0]->labelsize(11); preset_choice[0]->callback((Fl_Callback*)edit_layout_preset_cb, (void*)(0)); } // Fl_Button* preset_choice[0] { preset_choice[1] = new Fl_Button(163, 107, 79, 20, "Dialog"); preset_choice[1]->type(102); preset_choice[1]->compact(1); preset_choice[1]->selection_color(FL_DARK2); preset_choice[1]->labelsize(11); preset_choice[1]->callback((Fl_Callback*)edit_layout_preset_cb, (void*)(1)); } // Fl_Button* preset_choice[1] { preset_choice[2] = new Fl_Button(242, 107, 78, 20, "Toolbox"); preset_choice[2]->type(102); preset_choice[2]->compact(1); preset_choice[2]->selection_color(FL_DARK2); preset_choice[2]->labelsize(11); preset_choice[2]->callback((Fl_Callback*)edit_layout_preset_cb, (void*)(2)); } // Fl_Button* preset_choice[2] o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(85, 132, 235, 20, "---- Window ----"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(25, 167, 60, 20, "Margins:"); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Value_Input* o = new Fl_Value_Input(85, 167, 55, 20, "Left:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Left); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(145, 167, 55, 20, "Top:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Top); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(205, 167, 55, 20, "Right:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Right); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(265, 167, 55, 20, "Bottom:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Bottom); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(32, 201, 53, 20, "Grid:"); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Value_Input* o = new Fl_Value_Input(85, 201, 55, 20, "Horizontal:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Horizontal); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(145, 201, 55, 20, "Vertical:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Vertical); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(85, 226, 235, 20, "---- Group ----"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(25, 261, 60, 20, "Margins:"); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Value_Input* o = new Fl_Value_Input(85, 261, 55, 20, "Left:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Left1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(145, 261, 55, 20, "Top:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Top1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(205, 261, 55, 20, "Right:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Right1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(265, 261, 55, 20, "Bottom:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Bottom1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(32, 295, 53, 20, "Grid:"); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Value_Input* o = new Fl_Value_Input(85, 295, 55, 20, "Horizontal:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Horizontal1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(145, 295, 55, 20, "Vertical:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Vertical1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(85, 320, 235, 20, "---- Tabs ----"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(25, 355, 60, 20, "Margins:"); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Value_Input* o = new Fl_Value_Input(85, 355, 55, 20, "Top:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Top2); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(145, 355, 55, 20, "Bottom:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Bottom2); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(85, 380, 235, 20, "---- Widget ----"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(25, 415, 60, 20, "Horizontal:"); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Value_Input* o = new Fl_Value_Input(85, 414, 55, 20, "Minimum:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Minimum); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(145, 414, 55, 20, "Increment:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Increment); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(205, 414, 55, 20, "Gap:"); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Gap); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(32, 440, 53, 20, "Vertical:"); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Value_Input* o = new Fl_Value_Input(85, 440, 55, 20); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_3); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(145, 440, 55, 20); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_4); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(205, 440, 55, 20); o->labelsize(11); o->maximum(32767); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_5); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Group* o = new Fl_Group(85, 465, 201, 20, "Label Font:"); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Choice* o = new Fl_Choice(85, 465, 150, 20); o->tooltip("The style of the label text."); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)cb_6); Fl_Group::current()->resizable(o); o->menu(fontmenu_w_default); } // Fl_Choice* o { Fl_Value_Input* o = new Fl_Value_Input(235, 465, 50, 20); o->tooltip("The size of the label text."); o->labelsize(11); o->minimum(1); o->maximum(1000); o->step(1); o->value(14); o->textsize(11); o->callback((Fl_Callback*)cb_7); } // Fl_Value_Input* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(85, 490, 200, 20, "Text Font:"); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Choice* o = new Fl_Choice(85, 490, 150, 20); o->tooltip("The value text style."); o->box(FL_DOWN_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)cb_8); o->menu(fontmenu_w_default); } // Fl_Choice* o { Fl_Value_Input* o = new Fl_Value_Input(235, 490, 50, 20); o->tooltip("The value text size."); o->labelsize(11); o->maximum(1000); o->step(1); o->value(14); o->textsize(11); o->callback((Fl_Callback*)cb_9); } // Fl_Value_Input* o o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(325, 535, 5, 5); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o w_settings_layout_tab->end(); } // Fl_Group* w_settings_layout_tab { w_settings_shell_tab = new Fl_Group(10, 60, 320, 480, "Shell"); w_settings_shell_tab->image( image_shell_64() ); w_settings_shell_tab->image()->scale(36, 24, 0, 1); w_settings_shell_tab->labelsize(11); w_settings_shell_tab->callback((Fl_Callback*)propagate_load); w_settings_shell_tab->hide(); { Fl_Group* o = new Fl_Group(10, 90, 320, 132); o->callback((Fl_Callback*)propagate_load); { w_settings_shell_list = new Fl_Browser(100, 90, 220, 110, "Shell\ncommand\nlist:"); w_settings_shell_list->type(3); w_settings_shell_list->labelfont(1); w_settings_shell_list->labelsize(11); w_settings_shell_list->textsize(13); w_settings_shell_list->callback((Fl_Callback*)cb_w_settings_shell_list); w_settings_shell_list->align(Fl_Align(FL_ALIGN_LEFT)); Fl_Group::current()->resizable(w_settings_shell_list); } // Fl_Browser* w_settings_shell_list { w_settings_shell_toolbox = new Fl_Group(100, 200, 220, 22); w_settings_shell_toolbox->callback((Fl_Callback*)cb_w_settings_shell_toolbox); { Fl_Button* o = new Fl_Button(100, 200, 24, 22, "+"); o->tooltip("insert a new shell command into the list after the selected command"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)cb_a); } // Fl_Button* o { w_settings_shell_dup = new Fl_Button(124, 200, 24, 22, "++"); w_settings_shell_dup->tooltip("duplicate the selected shell command and insert it into the list"); w_settings_shell_dup->labelfont(1); w_settings_shell_dup->labelsize(11); w_settings_shell_dup->callback((Fl_Callback*)cb_w_settings_shell_dup); w_settings_shell_dup->deactivate(); } // Fl_Button* w_settings_shell_dup { w_settings_shell_remove = new Fl_Button(148, 200, 24, 22, "DEL"); w_settings_shell_remove->tooltip("remove the selected shell command - this can not be undone"); w_settings_shell_remove->labelsize(10); w_settings_shell_remove->callback((Fl_Callback*)cb_w_settings_shell_remove); w_settings_shell_remove->deactivate(); } // Fl_Button* w_settings_shell_remove { w_settings_shell_menu = new Fl_Menu_Button(172, 200, 24, 22); w_settings_shell_menu->labelsize(11); w_settings_shell_menu->textsize(11); w_settings_shell_menu->menu(menu_w_settings_shell_menu); } // Fl_Menu_Button* w_settings_shell_menu { Fl_Box* o = new Fl_Box(253, 200, 13, 22); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o { Fl_Button* o = new Fl_Button(246, 200, 24, 22, "T"); o->tooltip("show terminal window"); o->labelfont(5); o->labelsize(11); o->callback((Fl_Callback*)cb_T); } // Fl_Button* o { w_settings_shell_play = new Fl_Button(270, 200, 50, 22, "Run"); w_settings_shell_play->tooltip("run the selected shell command"); w_settings_shell_play->labelsize(11); w_settings_shell_play->callback((Fl_Callback*)cb_w_settings_shell_play); w_settings_shell_play->deactivate(); } // Fl_Button* w_settings_shell_play w_settings_shell_toolbox->end(); } // Fl_Group* w_settings_shell_toolbox o->end(); } // Fl_Group* o { w_settings_shell_cmd = new Fl_Group(10, 235, 320, 291); w_settings_shell_cmd->callback((Fl_Callback*)cb_w_settings_shell_cmd); { Fl_Input* o = new Fl_Input(100, 246, 220, 20, "Name:"); o->tooltip("file the shell command under this name in the shell command list"); o->labelfont(1); o->labelsize(11); o->textfont(4); o->textsize(11); o->callback((Fl_Callback*)cb_Name); o->when(FL_WHEN_RELEASE | FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY); } // Fl_Input* o { Fl_Input* o = new Fl_Input(100, 272, 220, 20, "Menu Label:"); o->tooltip("label text for the Shell menu in the main menu bar"); o->labelfont(1); o->labelsize(11); o->textfont(4); o->textsize(11); o->callback((Fl_Callback*)cb_Menu); } // Fl_Input* o { Fl_Group* o = new Fl_Group(100, 297, 140, 71); o->callback((Fl_Callback*)cb_b); { Fl_Shortcut_Button* o = new Fl_Shortcut_Button(100, 297, 130, 20, "Shortcut"); o->tooltip("an optional keyboard shortcut to run this shell command"); o->box(FL_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(11); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)cb_Shortcut); o->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)); o->when(FL_WHEN_RELEASE); } // Fl_Shortcut_Button* o { Fl_Choice* o = new Fl_Choice(100, 322, 130, 20, "Store:"); o->tooltip("store this shell command as a user setting or save it with the .fl project fi" "le"); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)cb_Store); o->menu(menu_Store); } // Fl_Choice* o { Fl_Choice* o = new Fl_Choice(100, 348, 130, 20, "Condition:"); o->tooltip("add this command to the main menu bar only if this condition is true"); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)cb_Condition); o->menu(menu_Condition); } // Fl_Choice* o { Fl_Box* o = new Fl_Box(230, 297, 10, 71); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { Fl_Input* o = new Fl_Input(230, 348, 90, 20, "Label:"); o->labelfont(1); o->labelsize(11); o->textfont(4); o->textsize(11); o->callback((Fl_Callback*)cb_Label); o->hide(); } // Fl_Input* o { Fl_Group* o = new Fl_Group(100, 373, 220, 80); o->callback((Fl_Callback*)propagate_load); { Fl_Text_Editor* o = w_settings_shell_command = new Fl_Text_Editor(100, 373, 196, 80, "Shell script:"); w_settings_shell_command->labelfont(1); w_settings_shell_command->labelsize(11); w_settings_shell_command->textfont(4); w_settings_shell_command->textsize(12); w_settings_shell_command->callback((Fl_Callback*)cb_w_settings_shell_command); w_settings_shell_command->align(Fl_Align(FL_ALIGN_LEFT)); Fl_Group::current()->resizable(w_settings_shell_command); o->buffer(new Fl_Text_Buffer); } // Fl_Text_Editor* w_settings_shell_command { Fl_Group* o = new Fl_Group(296, 373, 24, 80); { w_settings_shell_text_macros = new Fl_Menu_Button(296, 373, 24, 22); w_settings_shell_text_macros->tooltip("a list of text replacements available for the shell script"); w_settings_shell_text_macros->labelsize(11); w_settings_shell_text_macros->textsize(11); w_settings_shell_text_macros->callback((Fl_Callback*)cb_w_settings_shell_text_macros); w_settings_shell_text_macros->menu(menu_w_settings_shell_text_macros); } // Fl_Menu_Button* w_settings_shell_text_macros { Fl_Button* o = new Fl_Button(296, 395, 24, 22, "@+1fd_zoom"); o->tooltip("open the big code editor"); o->labelsize(11); o->callback((Fl_Callback*)cb_1fd_zoom); } // Fl_Button* o { Fl_Box* o = new Fl_Box(296, 417, 24, 10); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o o->end(); Fl_Group::current()->resizable(o); } // Fl_Group* o { Fl_Check_Button* o = new Fl_Check_Button(100, 458, 110, 20, "save .fl project file"); o->tooltip("save the project to the .fl file before running the command"); o->down_box(FL_DOWN_BOX); o->labelsize(11); o->callback((Fl_Callback*)cb_save); } // Fl_Check_Button* o { Fl_Check_Button* o = new Fl_Check_Button(100, 478, 110, 19, "save source code"); o->tooltip("generate the source code and header file before running the command"); o->down_box(FL_DOWN_BOX); o->labelsize(11); o->callback((Fl_Callback*)cb_save1); } // Fl_Check_Button* o { Fl_Check_Button* o = new Fl_Check_Button(100, 498, 110, 20, "save i18n strings"); o->tooltip("save the internationalisation strings before running the command"); o->down_box(FL_DOWN_BOX); o->labelsize(11); o->callback((Fl_Callback*)cb_save2); } // Fl_Check_Button* o { Fl_Check_Button* o = new Fl_Check_Button(214, 458, 106, 20, "show terminal"); o->tooltip("show the terminal window when launching this script"); o->down_box(FL_DOWN_BOX); o->labelsize(11); o->callback((Fl_Callback*)cb_show); } // Fl_Check_Button* o { Fl_Check_Button* o = new Fl_Check_Button(214, 478, 106, 19, "clear terminal"); o->tooltip("clear the teminal window before running this script"); o->down_box(FL_DOWN_BOX); o->labelsize(11); o->callback((Fl_Callback*)cb_clear); } // Fl_Check_Button* o { Fl_Check_Button* o = new Fl_Check_Button(214, 498, 106, 19, "clear term history"); o->tooltip("clear the teminal history in the terminal window"); o->down_box(FL_DOWN_BOX); o->labelsize(11); o->callback((Fl_Callback*)cb_clear1); } // Fl_Check_Button* o w_settings_shell_cmd->end(); Fl_Group::current()->resizable(w_settings_shell_cmd); } // Fl_Group* w_settings_shell_cmd { Fl_Box* o = w_settings_shell_fd_project = new Fl_Box(20, 70, 16, 15); w_settings_shell_fd_project->bind_image( image_fd_project() ); w_settings_shell_fd_project->labelsize(11); w_settings_shell_fd_project->hide(); w_settings_shell_fd_project->deactivate(); o->image()->scale(16, 16); } // Fl_Box* w_settings_shell_fd_project { Fl_Box* o = w_settings_shell_fd_user = new Fl_Box(20, 70, 16, 15); w_settings_shell_fd_user->bind_image( image_fd_user() ); w_settings_shell_fd_user->labelsize(11); w_settings_shell_fd_user->hide(); w_settings_shell_fd_user->deactivate(); o->image()->scale(16, 16); } // Fl_Box* w_settings_shell_fd_user w_settings_shell_tab->end(); } // Fl_Group* w_settings_shell_tab { w_settings_i18n_tab = new Fl_Group(10, 60, 320, 480, "Locale"); w_settings_i18n_tab->image( image_language_64() ); w_settings_i18n_tab->image()->scale(36, 24, 0, 1); w_settings_i18n_tab->labelsize(11); w_settings_i18n_tab->callback((Fl_Callback*)cb_w_settings_i18n_tab); w_settings_i18n_tab->hide(); { Fl_Group* o = new Fl_Group(100, 78, 170, 20); o->callback((Fl_Callback*)propagate_load); { i18n_type_chooser = new Fl_Choice(100, 78, 160, 20, "i18n Library:"); i18n_type_chooser->tooltip("Type of internationalization to use."); i18n_type_chooser->box(FL_THIN_UP_BOX); i18n_type_chooser->down_box(FL_BORDER_BOX); i18n_type_chooser->labelsize(11); i18n_type_chooser->textsize(11); i18n_type_chooser->callback((Fl_Callback*)i18n_type_cb); i18n_type_chooser->menu(menu_i18n_type_chooser); } // Fl_Choice* i18n_type_chooser { Fl_Box* o = new Fl_Box(260, 78, 10, 20); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { i18n_gnu_group = new Fl_Group(100, 103, 220, 95); i18n_gnu_group->callback((Fl_Callback*)cb_i18n_gnu_group); { i18n_gnu_include_input = new Fl_Input(100, 103, 220, 20, "#include:"); i18n_gnu_include_input->tooltip("The include file for internationalization."); i18n_gnu_include_input->box(FL_THIN_DOWN_BOX); i18n_gnu_include_input->labelsize(11); i18n_gnu_include_input->textfont(4); i18n_gnu_include_input->textsize(11); i18n_gnu_include_input->callback((Fl_Callback*)cb_i18n_gnu_include_input); } // Fl_Input* i18n_gnu_include_input { i18n_gnu_conditional_input = new Fl_Input(100, 128, 220, 20, "Conditional:"); i18n_gnu_conditional_input->tooltip("only include the header file if this preprocessor macro is defined, for examp" "le FLTK_GETTEXT_FOUND"); i18n_gnu_conditional_input->box(FL_THIN_DOWN_BOX); i18n_gnu_conditional_input->labelsize(11); i18n_gnu_conditional_input->textfont(4); i18n_gnu_conditional_input->textsize(11); i18n_gnu_conditional_input->callback((Fl_Callback*)cb_i18n_gnu_conditional_input); } // Fl_Input* i18n_gnu_conditional_input { i18n_gnu_function_input = new Fl_Input(100, 153, 220, 20, "Function:"); i18n_gnu_function_input->tooltip("The function to call to translate labels and tooltips, usually \"gettext\" or" " \"_\""); i18n_gnu_function_input->box(FL_THIN_DOWN_BOX); i18n_gnu_function_input->labelsize(11); i18n_gnu_function_input->textfont(4); i18n_gnu_function_input->textsize(11); i18n_gnu_function_input->callback((Fl_Callback*)cb_i18n_gnu_function_input); } // Fl_Input* i18n_gnu_function_input { i18n_gnu_static_function_input = new Fl_Input(100, 178, 220, 20, "Static Function:"); i18n_gnu_static_function_input->tooltip("function to call to translate static text, The function to call to internatio" "nalize labels and tooltips, usually \"gettext_noop\" or \"N_\""); i18n_gnu_static_function_input->box(FL_THIN_DOWN_BOX); i18n_gnu_static_function_input->labelsize(11); i18n_gnu_static_function_input->textfont(4); i18n_gnu_static_function_input->textsize(11); i18n_gnu_static_function_input->callback((Fl_Callback*)cb_i18n_gnu_static_function_input); } // Fl_Input* i18n_gnu_static_function_input i18n_gnu_group->end(); } // Fl_Group* i18n_gnu_group { i18n_posix_group = new Fl_Group(100, 103, 220, 95); i18n_posix_group->callback((Fl_Callback*)cb_i18n_posix_group); i18n_posix_group->hide(); { i18n_pos_include_input = new Fl_Input(100, 103, 220, 20, "#include:"); i18n_pos_include_input->tooltip("The include file for internationalization."); i18n_pos_include_input->box(FL_THIN_DOWN_BOX); i18n_pos_include_input->labelsize(11); i18n_pos_include_input->textfont(4); i18n_pos_include_input->textsize(11); i18n_pos_include_input->callback((Fl_Callback*)cb_i18n_pos_include_input); } // Fl_Input* i18n_pos_include_input { i18n_pos_conditional_input = new Fl_Input(100, 128, 220, 20, "Conditional:"); i18n_pos_conditional_input->tooltip("only include the header file if this preprocessor macro is defined, for examp" "le FLTK_GETTEXT_FOUND"); i18n_pos_conditional_input->box(FL_THIN_DOWN_BOX); i18n_pos_conditional_input->labelsize(11); i18n_pos_conditional_input->textfont(4); i18n_pos_conditional_input->textsize(11); i18n_pos_conditional_input->callback((Fl_Callback*)cb_i18n_pos_conditional_input); } // Fl_Input* i18n_pos_conditional_input { i18n_pos_file_input = new Fl_Input(100, 153, 220, 20, "Catalog:"); i18n_pos_file_input->tooltip("The name of the message catalog."); i18n_pos_file_input->box(FL_THIN_DOWN_BOX); i18n_pos_file_input->labelsize(11); i18n_pos_file_input->textfont(4); i18n_pos_file_input->textsize(11); i18n_pos_file_input->callback((Fl_Callback*)cb_i18n_pos_file_input); } // Fl_Input* i18n_pos_file_input { Fl_Group* o = new Fl_Group(100, 178, 90, 20); o->callback((Fl_Callback*)cb_c); { i18n_pos_set_input = new Fl_Int_Input(100, 178, 80, 20, "Set:"); i18n_pos_set_input->tooltip("The message set number."); i18n_pos_set_input->type(2); i18n_pos_set_input->box(FL_THIN_DOWN_BOX); i18n_pos_set_input->labelsize(11); i18n_pos_set_input->textfont(4); i18n_pos_set_input->textsize(11); i18n_pos_set_input->callback((Fl_Callback*)cb_i18n_pos_set_input); } // Fl_Int_Input* i18n_pos_set_input { Fl_Box* o = new Fl_Box(180, 178, 10, 20); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o i18n_posix_group->end(); } // Fl_Group* i18n_posix_group { Fl_Box* o = new Fl_Box(100, 530, 220, 10); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o w_settings_i18n_tab->end(); } // Fl_Group* w_settings_i18n_tab { w_settings_user_tab = new Fl_Group(10, 60, 320, 480, "User"); w_settings_user_tab->image( image_user_circle_64() ); w_settings_user_tab->image()->scale(36, 24, 0, 1); w_settings_user_tab->labelsize(11); w_settings_user_tab->callback((Fl_Callback*)cb_w_settings_user_tab); w_settings_user_tab->hide(); { Fl_Box* o = new Fl_Box(100, 84, 220, 20, "---- Widget Browser ----"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Group* o = new Fl_Group(100, 112, 220, 20); o->callback((Fl_Callback*)propagate_load); { Fl_Choice* o = new Fl_Choice(100, 112, 151, 20, "Label:"); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)cb_Comments, (void*)(&Widget_Browser::label_font)); Fl_Group::current()->resizable(o); o->menu(fontmenu); } // Fl_Choice* o { Fl_Button* o = new Fl_Button(251, 112, 51, 20); o->labelsize(11); o->callback((Fl_Callback*)cb_Color_Chip, (void*)(&Widget_Browser::label_color)); } // Fl_Button* o { Fl_Menu_Button* o = new Fl_Menu_Button(302, 112, 18, 20); o->callback((Fl_Callback*)cb_Color_Choice, (void*)(&Widget_Browser::label_color)); o->menu(colormenu); } // Fl_Menu_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(100, 137, 220, 20); o->callback((Fl_Callback*)propagate_load); { Fl_Choice* o = new Fl_Choice(100, 137, 151, 20, "Class:"); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)cb_Comments, (void*)(&Widget_Browser::class_font)); Fl_Group::current()->resizable(o); o->menu(fontmenu); } // Fl_Choice* o { Fl_Button* o = new Fl_Button(251, 137, 51, 20); o->labelsize(11); o->callback((Fl_Callback*)cb_Color_Chip, (void*)(&Widget_Browser::class_color)); } // Fl_Button* o { Fl_Menu_Button* o = new Fl_Menu_Button(302, 137, 18, 20); o->callback((Fl_Callback*)cb_Color_Choice, (void*)(&Widget_Browser::class_color)); o->menu(colormenu); } // Fl_Menu_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(100, 162, 220, 20); o->callback((Fl_Callback*)propagate_load); { Fl_Choice* o = new Fl_Choice(100, 162, 151, 20, "Function:"); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)cb_Comments, (void*)(&Widget_Browser::func_font)); Fl_Group::current()->resizable(o); o->menu(fontmenu); } // Fl_Choice* o { Fl_Button* o = new Fl_Button(251, 162, 51, 20); o->labelsize(11); o->callback((Fl_Callback*)cb_Color_Chip, (void*)(&Widget_Browser::func_color)); } // Fl_Button* o { Fl_Menu_Button* o = new Fl_Menu_Button(302, 162, 18, 20); o->callback((Fl_Callback*)cb_Color_Choice, (void*)(&Widget_Browser::func_color)); o->menu(colormenu); } // Fl_Menu_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(100, 187, 220, 20); o->callback((Fl_Callback*)propagate_load); { Fl_Choice* o = new Fl_Choice(100, 187, 151, 20, "Name:"); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)cb_Comments, (void*)(&Widget_Browser::name_font)); Fl_Group::current()->resizable(o); o->menu(fontmenu); } // Fl_Choice* o { Fl_Button* o = new Fl_Button(251, 187, 51, 20); o->labelsize(11); o->callback((Fl_Callback*)cb_Color_Chip, (void*)(&Widget_Browser::name_color)); } // Fl_Button* o { Fl_Menu_Button* o = new Fl_Menu_Button(302, 187, 18, 20); o->callback((Fl_Callback*)cb_Color_Choice, (void*)(&Widget_Browser::name_color)); o->menu(colormenu); } // Fl_Menu_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(100, 212, 220, 20); o->callback((Fl_Callback*)propagate_load); { Fl_Choice* o = new Fl_Choice(100, 212, 151, 20, "Code:"); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)cb_Comments, (void*)(&Widget_Browser::code_font)); Fl_Group::current()->resizable(o); o->menu(fontmenu); } // Fl_Choice* o { Fl_Button* o = new Fl_Button(251, 212, 51, 20); o->labelsize(11); o->callback((Fl_Callback*)cb_Color_Chip, (void*)(&Widget_Browser::code_color)); } // Fl_Button* o { Fl_Menu_Button* o = new Fl_Menu_Button(302, 212, 18, 20); o->callback((Fl_Callback*)cb_Color_Choice, (void*)(&Widget_Browser::code_color)); o->menu(colormenu); } // Fl_Menu_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(100, 237, 220, 20); o->callback((Fl_Callback*)propagate_load); { Fl_Choice* o = w_settings_user_commenttext = new Fl_Choice(100, 237, 151, 20, "Comments:"); w_settings_user_commenttext->box(FL_THIN_UP_BOX); w_settings_user_commenttext->down_box(FL_BORDER_BOX); w_settings_user_commenttext->labelfont(1); w_settings_user_commenttext->labelsize(11); w_settings_user_commenttext->textsize(11); w_settings_user_commenttext->callback((Fl_Callback*)cb_Comments, (void*)(&Widget_Browser::comment_font)); Fl_Group::current()->resizable(w_settings_user_commenttext); o->menu(fontmenu); } // Fl_Choice* w_settings_user_commenttext { Fl_Button* o = new Fl_Button(251, 237, 51, 20); o->labelsize(11); o->callback((Fl_Callback*)cb_Color_Chip, (void*)(&Widget_Browser::comment_color)); } // Fl_Button* o { Fl_Menu_Button* o = new Fl_Menu_Button(302, 237, 18, 20); o->callback((Fl_Callback*)cb_Color_Choice, (void*)(&Widget_Browser::comment_color)); o->menu(colormenu); } // Fl_Menu_Button* o o->end(); } // Fl_Group* o w_settings_user_tab->end(); } // Fl_Group* w_settings_user_tab w_settings_tabs->end(); Fl_Group::current()->resizable(w_settings_tabs); } // Fl_Tabs* w_settings_tabs { Fl_Group* o = new Fl_Group(10, 550, 320, 20); { Fl_Button* o = new Fl_Button(230, 550, 100, 20, "Close"); o->tooltip("Close this dialog."); o->labelsize(11); o->callback((Fl_Callback*)cb_Close); } // Fl_Button* o { Fl_Box* o = new Fl_Box(220, 550, 10, 20); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o settings_window->size_range(340, 580); settings_window->end(); } // Fl_Double_Window* settings_window w_settings_tabs->do_callback(w_settings_tabs, LOAD); return settings_window; } Fl_Double_Window *shell_run_window=(Fl_Double_Window *)0; Fl_Terminal *shell_run_terminal=(Fl_Terminal *)0; static void cb_Clear(Fl_Button*, void*) { // clear screen, clear scrollback, home cursor shell_run_terminal->append("\033[2J\033[3J\033[H"); } Fl_Return_Button *shell_run_button=(Fl_Return_Button *)0; static void cb_shell_run_button(Fl_Return_Button*, void*) { Fl_Preferences pos(fluid_prefs, "shell_run_Window_pos"); pos.set("x", shell_run_window->x()); pos.set("y", shell_run_window->y()); pos.set("w", shell_run_window->w()); pos.set("h", shell_run_window->h()); shell_run_window->hide(); } Fl_Double_Window* make_shell_window() { { shell_run_window = new Fl_Double_Window(555, 430, "Shell Command Output"); shell_run_window->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); { shell_run_terminal = new Fl_Terminal(10, 10, 535, 375); Fl_Group::current()->resizable(shell_run_terminal); shell_run_terminal->ansi(1); shell_run_terminal->history_lines(1000); } // Fl_Terminal* shell_run_terminal { Fl_Group* o = new Fl_Group(10, 395, 535, 25); { Fl_Button* o = new Fl_Button(10, 395, 94, 25, "Clear"); o->callback((Fl_Callback*)cb_Clear); } // Fl_Button* o { Fl_Box* o = new Fl_Box(104, 395, 341, 25); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o { shell_run_button = new Fl_Return_Button(445, 395, 100, 25, "Close"); shell_run_button->callback((Fl_Callback*)cb_shell_run_button); } // Fl_Return_Button* shell_run_button o->end(); } // Fl_Group* o shell_run_window->end(); } // Fl_Double_Window* shell_run_window return shell_run_window; } Fl_Menu_Item *w_layout_menu_storage[4]; fltk-1.4.3/fluid/Fl_Button_Type.h0000644000175000017500000000277715004135251016773 0ustar albrechtalbrecht// // Button type header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FL_BUTTON_TYPE_H #define _FL_BUTTON_TYPE_H #include "Fl_Widget_Type.h" /** \brief A handler for the simple push button and a base class for all other buttons. */ class Fl_Button_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE; public: void ideal_size(int &w, int &h) FL_OVERRIDE; const char *type_name() FL_OVERRIDE { return "Fl_Button"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Button"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE; Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Button_Type(); } int is_button() const FL_OVERRIDE { return 1; } ID id() const FL_OVERRIDE { return ID_Button; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Button) ? true : super::is_a(inID); } void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; void copy_properties() FL_OVERRIDE; }; extern Fl_Button_Type Fl_Button_type; #endif // _FL_BUTTON_TYPE_H fltk-1.4.3/fluid/fluid.desktop0000644000175000017500000000027615004135251016413 0ustar albrechtalbrecht[Desktop Entry] Name=FLUID Comment=FLTK GUI Designer TryExec=fluid Exec=fluid %F Icon=fluid Terminal=false Type=Application MimeType=application/x-fluid; Categories=Development;GUIDesigner; fltk-1.4.3/fluid/Makefile0000644000175000017500000001200715004135251015350 0ustar albrechtalbrecht# # FLUID Makefile for the Fast Light Tool Kit (FLTK). # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # include ../makeinclude CPPFILES = \ CodeEditor.cxx \ StyleParse.cxx \ Fd_Snap_Action.cxx \ Fl_Button_Type.cxx \ Fl_Function_Type.cxx \ Fl_Grid_Type.cxx \ Fl_Group_Type.cxx \ Fl_Menu_Type.cxx \ Fl_Type.cxx \ Fl_Widget_Type.cxx \ Fl_Window_Type.cxx \ Fluid_Image.cxx \ about_panel.cxx \ align_widget.cxx \ settings_panel.cxx \ autodoc.cxx \ code.cxx \ custom_widgets.cxx \ factory.cxx \ file.cxx \ fluid.cxx \ fluid_filename.cxx \ function_panel.cxx \ mergeback.cxx \ pixmaps.cxx \ shell_command.cxx \ codeview_panel.cxx \ template_panel.cxx \ undo.cxx \ widget_browser.cxx \ widget_panel.cxx # ExternalCodeEditor: platform specific files CPPFILES_WIN = ExternalCodeEditor_WIN32.cxx CPPFILES_OSX = ExternalCodeEditor_UNIX.cxx CPPFILES_X11 = ExternalCodeEditor_UNIX.cxx CPPFILES_XFT = ExternalCodeEditor_UNIX.cxx CPPFILES_CAIRO = ExternalCodeEditor_UNIX.cxx CPPFILES_WAYLAND = ExternalCodeEditor_UNIX.cxx CPPFILES_WAYLANDX11 = ExternalCodeEditor_UNIX.cxx CPPFILES += $(CPPFILES_$(BUILD)) ################################################################ OBJECTS = $(CPPFILES:.cxx=.o) all: $(FLUID) fluid$(EXEEXT) fluid$(EXEEXT): $(OBJECTS) $(LIBNAME) $(IMGLIBNAME) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) -o $@ $(OBJECTS) $(LINKFLTKIMG) $(LDFLAGS) $(LDLIBS) $(OSX_ONLY) $(RM) -r -f fluid.app $(OSX_ONLY) mkdir -p fluid.app/Contents/MacOS fluid.app/Contents/Resources $(OSX_ONLY) $(INSTALL_BIN) fluid fluid.app/Contents/MacOS $(OSX_ONLY) $(INSTALL) icons/fluid.icns fluid.app/Contents/Resources $(OSX_ONLY) $(INSTALL) fluid.plist fluid.app/Contents/Info.plist fluid-shared$(EXEEXT): $(OBJECTS) ../src/$(DSONAME) ../src/$(IMGDSONAME) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) -o $@ $(OBJECTS) $(LINKSHARED) $(LDFLAGS) $(LDLIBS) clean: -$(RM) *.o core.* *~ *.bck *.bak -$(RM) core fluid$(EXEEXT) fluid-shared$(EXEEXT) $(OSX_ONLY) -$(RMDIR) fluid.app depend: $(CPPFILES) makedepend -Y -I.. -f makedepend -w 20 $(CPPFILES) echo "# DO NOT DELETE THIS LINE -- make depend depends on it." > makedepend.tmp echo "" >> makedepend.tmp grep '^[a-zA-Z]' makedepend | ( LC_ALL=C sort -u -f >> makedepend.tmp; ) mv makedepend.tmp makedepend # Automatically generated dependencies... include makedepend install: all echo "Installing FLUID in $(DESTDIR)$(bindir)..." -$(INSTALL_DIR) "$(DESTDIR)$(bindir)" $(INSTALL_BIN) $(FLUID) "$(DESTDIR)$(bindir)/fluid$(EXEEXT)" install-linux: -$(INSTALL_DIR) "$(DESTDIR)$(datadir)/applications" $(INSTALL_DATA) fluid.desktop "$(DESTDIR)$(datadir)/applications" for size in 16 32 48 64 128; do \ if test ! -d "$(DESTDIR)$(datadir)/icons/hicolor/$${size}x$${size}/apps"; then \ $(INSTALL_DIR) "$(DESTDIR)$(datadir)/icons/hicolor/$${size}x$${size}/apps"; \ fi; \ $(INSTALL_DATA) icons/fluid-$$size.png "$(DESTDIR)$(datadir)/icons/hicolor/$${size}x$${size}/apps/fluid.png"; \ done -$(INSTALL_DIR) "$(DESTDIR)$(datadir)/mimelnk/application" $(INSTALL_DATA) x-fluid.desktop "$(DESTDIR)$(datadir)/mimelnk/application" install-osx: echo Installing Fluid in $(DESTDIR)/Applications... -$(INSTALL_DIR) "$(DESTDIR)/Applications/fluid.app" -$(INSTALL_DIR) "$(DESTDIR)/Applications/fluid.app/Contents" $(INSTALL_DATA) fluid.app/Contents/Info.plist "$(DESTDIR)/Applications/fluid.app/Contents/Info.plist" -$(INSTALL_DIR) "$(DESTDIR)/Applications/fluid.app/Contents/MacOS" $(RM) "$(DESTDIR)/Applications/fluid.app/Contents/MacOS/fluid" $(LN) "$(bindir)/fluid" "$(DESTDIR)/Applications/fluid.app/Contents/MacOS/fluid" -$(INSTALL_DIR) "$(DESTDIR)/Applications/fluid.app/Contents/Resources" $(INSTALL_DATA) fluid.app/Contents/Resources/fluid.icns "$(DESTDIR)/Applications/fluid.app/Contents/Resources" uninstall: $(RM) "$(DESTDIR)$(bindir)/fluid$(EXEEXT)" uninstall-linux: $(RM) "$(DESTDIR)$(datadir)/applications/fluid.desktop" $(RM) "$(DESTDIR)$(datadir)/icons/hicolor"/*/fluid.png $(RM) "$(DESTDIR)$(datadir)/mimelnk/application/x-fluid.desktop" uninstall-osx: $(RM) -r "$(DESTDIR)/Applications/fluid.app" # Note: The rebuild target can only be used if you have the original .fl # files. This is normally only used by FLTK maintainers... # It *must* be executed *after* fluid has been built and # fluid must be rebuilt if any {.fl|.cxx|.h} files were changed. rebuild: fluid$(EXEEXT) echo 'Rebuilding fluid (.fl) and .cxx/.h files from .fl files ...' ./fluid$(EXEEXT) -u -c about_panel.fl ./fluid$(EXEEXT) -u -c settings_panel.fl ./fluid$(EXEEXT) -u -c function_panel.fl ./fluid$(EXEEXT) -u -c print_panel.fl ./fluid$(EXEEXT) -u -c codeview_panel.fl ./fluid$(EXEEXT) -u -c template_panel.fl ./fluid$(EXEEXT) -u -c widget_panel.fl fltk-1.4.3/fluid/Fl_Menu_Type.h0000644000175000017500000002475415004135251016423 0ustar albrechtalbrecht// // Menu type header file for the Fast Light Tool Kit (FLTK). // // Type for creating all subclasses of Fl_Widget // This should have the widget pointer in it, but it is still in the // Fl_Type base class. // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_FL_MENU_TYPE_H #define _FLUID_FL_MENU_TYPE_H #include "Fl_Button_Type.h" #include "Fd_Snap_Action.h" #include #include #include #include #include #include extern Fl_Menu_Item dummymenu[]; extern Fl_Menu_Item button_type_menu[]; extern Fl_Menu_Item menu_item_type_menu[]; extern Fl_Menu_Item menu_bar_type_menu[]; /** \brief Manage all types on menu items. Deriving Fl_Menu_Item_Type from Fl_Button_Type is intentional. For the purpose of editing, a Menu Item is implemented with `o` pointing to an Fl_Button for holding all properties. */ class Fl_Menu_Item_Type : public Fl_Button_Type { typedef Fl_Button_Type super; public: Fl_Menu_Item* subtypes() FL_OVERRIDE {return menu_item_type_menu;} const char* type_name() FL_OVERRIDE {return "MenuItem";} const char* alt_type_name() FL_OVERRIDE {return "fltk::Item";} Fl_Type* make(Strategy strategy) FL_OVERRIDE; Fl_Type* make(int flags, Strategy strategy); int is_button() const FL_OVERRIDE {return 1;} // this gets shortcut to work Fl_Widget* widget(int,int,int,int) FL_OVERRIDE {return 0;} Fl_Widget_Type* _make() FL_OVERRIDE {return 0;} virtual const char* menu_name(Fd_Code_Writer& f, int& i); int flags(); void write_static(Fd_Code_Writer& f) FL_OVERRIDE; void write_item(Fd_Code_Writer& f); void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; int is_true_widget() const FL_OVERRIDE { return 0; } ID id() const FL_OVERRIDE { return ID_Menu_Item; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Item) ? true : super::is_a(inID); } }; /** \brief Manage Radio style Menu Items. */ class Fl_Radio_Menu_Item_Type : public Fl_Menu_Item_Type { typedef Fl_Menu_Item_Type super; public: const char* type_name() FL_OVERRIDE {return "RadioMenuItem";} Fl_Type* make(Strategy strategy) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Radio_Menu_Item; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Radio_Menu_Item) ? true : super::is_a(inID); } }; /** \brief Manage Checkbox style Menu Items. */ class Fl_Checkbox_Menu_Item_Type : public Fl_Menu_Item_Type { typedef Fl_Menu_Item_Type super; public: const char* type_name() FL_OVERRIDE {return "CheckMenuItem";} Fl_Type* make(Strategy strategy) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Checkbox_Menu_Item; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Checkbox_Menu_Item) ? true : super::is_a(inID); } }; /** \brief Manage Submenu style Menu Items. Submenu Items are simply buttons just like all other menu items, but they can also hold a pointer to a list of submenus, or have a flag set that allows submenus to follow in the current array. As buttons, they can be clicked by the user, and they will call their callback, if one is set. */ class Fl_Submenu_Type : public Fl_Menu_Item_Type { typedef Fl_Menu_Item_Type super; public: Fl_Menu_Item* subtypes() FL_OVERRIDE {return 0;} const char* type_name() FL_OVERRIDE {return "Submenu";} const char* alt_type_name() FL_OVERRIDE {return "fltk::ItemGroup";} int can_have_children() const FL_OVERRIDE {return 1;} int is_button() const FL_OVERRIDE {return 0;} // disable shortcut Fl_Type* make(Strategy strategy) FL_OVERRIDE; // changes to submenu must propagate up so build_menu is called // on the parent Fl_Menu_Type: void add_child(Fl_Type*a, Fl_Type*b) FL_OVERRIDE {parent->add_child(a,b);} void move_child(Fl_Type*a, Fl_Type*b) FL_OVERRIDE {parent->move_child(a,b);} void remove_child(Fl_Type*a) FL_OVERRIDE {parent->remove_child(a);} ID id() const FL_OVERRIDE { return ID_Submenu; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Submenu) ? true : super::is_a(inID); } }; // ----------------------------------------------------------------------------- /** \brief Base class for all widgets that can have a pulldown menu attached. Widgets with this type can be derived from Fl_Menu_ or from Fl_Group (Fl_Input_Choice). */ class Fl_Menu_Manager_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->textsize_not_null() + 8; w = layout->textsize_not_null() * 6 + 8; Fd_Snap_Action::better_size(w, h); } int can_have_children() const FL_OVERRIDE {return 1;} int menusize; virtual void build_menu() = 0; Fl_Menu_Manager_Type() : Fl_Widget_Type() {menusize = 0;} void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE { build_menu(); } void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE { build_menu(); } void remove_child(Fl_Type*) FL_OVERRIDE { build_menu();} Fl_Type* click_test(int x, int y) FL_OVERRIDE = 0; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; void copy_properties() FL_OVERRIDE = 0; ID id() const FL_OVERRIDE { return ID_Menu_Manager_; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Manager_) ? true : super::is_a(inID); } }; /** \brief Manage the composite widget Input Choice. \note Input Choice is a composite window, so `o` will be pointing to a widget derived from Fl_Group. All menu related methods from Fl_Menu_Trait_Type must be virtual and must be reimplemented here (click_test, build_menu, textstuff). */ class Fl_Input_Choice_Type : public Fl_Menu_Manager_Type { typedef Fl_Menu_Manager_Type super; int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Input_Choice *myo = (Fl_Input_Choice*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); switch (w) { case 4: case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); break; case 2: myo->textsize(s); break; case 3: myo->textcolor(c); break; } return 1; } public: ~Fl_Input_Choice_Type() { if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Input_Choice*)o)->menu()); } const char *type_name() FL_OVERRIDE {return "Fl_Input_Choice";} const char *alt_type_name() FL_OVERRIDE {return "fltk::ComboBox";} Fl_Type* click_test(int,int) FL_OVERRIDE; Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { Fl_Input_Choice *myo = new Fl_Input_Choice(X,Y,W,H,"input choice:"); myo->menu(dummymenu); myo->value("input"); return myo; } Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Input_Choice_Type();} void build_menu() FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Input_Choice; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Input_Choice) ? true : super::is_a(inID); } void copy_properties() FL_OVERRIDE; }; /** \brief Base class to handle widgets that are derived from Fl_Menu_. */ class Fl_Menu_Base_Type : public Fl_Menu_Manager_Type { typedef Fl_Menu_Manager_Type super; int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Menu_ *myo = (Fl_Menu_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); break; case 2: myo->textsize(s); break; case 3: myo->textcolor(c); break; } return 1; } public: int can_have_children() const FL_OVERRIDE {return 1;} void build_menu() FL_OVERRIDE; ~Fl_Menu_Base_Type() { if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Menu_*)o)->menu()); } Fl_Type* click_test(int x, int y) FL_OVERRIDE; void copy_properties() FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Menu_; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_) ? true : super::is_a(inID); } }; extern Fl_Menu_Item button_type_menu[]; /** \brief Make Menu Button widgets. */ class Fl_Menu_Button_Type : public Fl_Menu_Base_Type { typedef Fl_Menu_Base_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE {return button_type_menu;} public: const char *type_name() FL_OVERRIDE {return "Fl_Menu_Button";} const char *alt_type_name() FL_OVERRIDE {return "fltk::MenuButton";} Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { return new Fl_Menu_Button(X,Y,W,H,"menu");} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Menu_Button_Type();} ID id() const FL_OVERRIDE { return ID_Menu_Button; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Button) ? true : super::is_a(inID); } }; /** \brief Manage Choice type menu widgets. */ class Fl_Choice_Type : public Fl_Menu_Base_Type { typedef Fl_Menu_Base_Type super; public: const char *type_name() FL_OVERRIDE {return "Fl_Choice";} const char *alt_type_name() FL_OVERRIDE {return "fltk::Choice";} Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { Fl_Choice *myo = new Fl_Choice(X,Y,W,H,"choice:"); myo->menu(dummymenu); return myo; } Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Choice_Type();} ID id() const FL_OVERRIDE { return ID_Choice; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Choice) ? true : super::is_a(inID); } }; /** \brief Manage Menubar widgets. */ class Fl_Menu_Bar_Type : public Fl_Menu_Base_Type { typedef Fl_Menu_Base_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE {return menu_bar_type_menu;} public: Fl_Menu_Bar_Type(); ~Fl_Menu_Bar_Type() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "Fl_Menu_Bar";} const char *alt_type_name() FL_OVERRIDE {return "fltk::MenuBar";} Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE {return new Fl_Menu_Bar(X,Y,W,H);} Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Menu_Bar_Type();} void write_static(Fd_Code_Writer& f) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; // void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Menu_Bar; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Bar) ? true : super::is_a(inID); } bool is_sys_menu_bar(); const char *sys_menubar_name(); const char *sys_menubar_proxy_name(); protected: char *_proxy_name; }; #endif // _FLUID_FL_MENU_TYPE_H fltk-1.4.3/fluid/custom_widgets.cxx0000644000175000017500000002137315004135251017502 0ustar albrechtalbrecht// // Widget type code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "custom_widgets.h" #include "fluid.h" #include "Fl_Window_Type.h" #include "factory.h" #include "widget_panel.h" #include "widget_browser.h" #include #include #include #include #include #include #include "../src/flstring.h" /** \class Widget_Bin_Button The Widget_Bin_Button button is a button that can be used in the widget bin to allow the user to drag and drop widgets into a window or group. This feature makes it easy for the user to position a widget at a specific location within the window or group. */ /** Convert mouse dragging into a drag and drop event. */ int Widget_Bin_Button::handle(int inEvent) { int ret = 0; switch (inEvent) { case FL_PUSH: Fl_Button::handle(inEvent); return 1; // make sure that we get drag events case FL_DRAG: ret = Fl_Button::handle(inEvent); if (!user_data()) return ret; if (!Fl::event_is_click()) { // make it a dnd event // fake a drag outside of the widget Fl::e_x = x()-1; Fl_Button::handle(inEvent); // fake a button release Fl_Button::handle(FL_RELEASE); // make it into a dnd event const char *type_name = (const char*)user_data(); Fl_Type::current_dnd = Fl_Type::current; Fl::copy(type_name, (int)strlen(type_name)+1, 0); Fl::dnd(); return 1; } return ret; } return Fl_Button::handle(inEvent); } /** \class Widget_Bin_Window_Button The Widget_Bin_Window_Button button is used in the widget bin to create new windows by dragging and dropping. When the button is dragged and dropped onto the desktop, a new window will be created at the drop location. */ /** Convert mouse dragging into a drag and drop event. */ int Widget_Bin_Window_Button::handle(int inEvent) { static Fl_Window *drag_win = NULL; int ret = 0; switch (inEvent) { case FL_PUSH: Fl_Button::handle(inEvent); return 1; // make sure that we get drag events case FL_DRAG: ret = Fl_Button::handle(inEvent); if (!user_data()) return ret; if (!Fl::event_is_click()) { if (!drag_win) { drag_win = new Fl_Window(0, 0, 480, 320); drag_win->border(0); drag_win->set_non_modal(); } if (drag_win) { drag_win->position(Fl::event_x_root()+1, Fl::event_y_root()+1); drag_win->show(); } // Does not work outside window: fl_cursor(FL_CURSOR_HAND); } return ret; case FL_RELEASE: if (drag_win) { Fl::delete_widget(drag_win); drag_win = NULL; // create a new window here Fl_Type *prototype = typename_to_prototype((char*)user_data()); if (prototype) { Fl_Type *new_type = add_new_widget_from_user(prototype, Strategy::AFTER_CURRENT); if (new_type && new_type->is_a(ID_Window)) { Fl_Window_Type *new_window = (Fl_Window_Type*)new_type; Fl_Window *w = (Fl_Window *)new_window->o; w->position(Fl::event_x_root(), Fl::event_y_root()); } } widget_browser->display(Fl_Type::current); widget_browser->rebuild(); } return Fl_Button::handle(inEvent); } return Fl_Button::handle(inEvent); } /** \class Fluid_Coord_Input The Fluid_Coord_Input widget is an input field for entering widget coordinates and sizes. It includes basic math capabilities and allows the use of variables in formulas. This widget is useful for specifying precise positions and dimensions for widgets in a graphical user interface. */ /** Create an input field. */ Fluid_Coord_Input::Fluid_Coord_Input(int x, int y, int w, int h, const char *l) : Fl_Input(x, y, w, h, l), user_callback_(0L), vars_(0L), vars_user_data_(0L) { Fl_Input::callback((Fl_Callback*)callback_handler_cb); text("0"); } void Fluid_Coord_Input::callback_handler_cb(Fluid_Coord_Input *This, void *v) { This->callback_handler(v); } void Fluid_Coord_Input::callback_handler(void *v) { if (user_callback_) (*user_callback_)(this, v); // do *not* update the value to show the evaluated formula here, because the // values of the variables have already updated after the user callback. } /** \brief Get the value of a variable. Collects all consecutive ASCII letters into a variable name, scans the Variable list for that name, and then calls the corresponding callback from the Variable array. \param s points to the first character of the variable name, must point after the last character of the variable name when returning. \return the integer value that was found or calculated */ int Fluid_Coord_Input::eval_var(uchar *&s) const { if (!vars_) return 0; // find the end of the variable name uchar *v = s; while (isalpha(*s)) s++; int n = (int)(s-v); // find the variable in the list for (Fluid_Coord_Input_Vars *vars = vars_; vars->name_; vars++) { if (strncmp((char*)v, vars->name_, n)==0 && vars->name_[n]==0) return vars->callback_(this, vars_user_data_); } return 0; } /** Evaluate a formula into an integer, recursive part. \param s remaining text in this formula, must return a pointer to the next character that will be interpreted. \param prio priority of current operation \return the value so far */ int Fluid_Coord_Input::eval(uchar *&s, int prio) const { int v = 0, sgn = 1; uchar c = *s++; // check for end of text if (c==0) { s--; return sgn*v; } // check for unary operator if (c=='-') { sgn = -1; c = *s++; } else if (c=='+') { sgn = 1; c = *s++; } // read value, variable, or bracketed term if (c==0) { s--; return sgn*v; } else if (c>='0' && c<='9') { // numeric value while (c>='0' && c<='9') { v = v*10 + (c-'0'); c = *s++; } } else if (isalpha(c)) { v = eval_var(--s); c = *s++; } else if (c=='(') { // opening bracket v = eval(s, 5); } else { return sgn*v; // syntax error } if (sgn==-1) v = -v; // Now evaluate all following binary operators for (;;) { if (c==0) { s--; return v; } else if (c=='+' || c=='-') { if (prio<=4) { s--; return v; } if (c=='+') { v += eval(s, 4); } else if (c=='-') { v -= eval(s, 4); } } else if (c=='*' || c=='/') { if (prio<=3) { s--; return v; } if (c=='*') { v *= eval(s, 3); } else if (c=='/') { int x = eval(s, 3); if (x!=0) // if x is zero, don't divide v /= x; } } else if (c==')') { return v; } else { return v; // syntax error } c = *s++; } return v; } /** Evaluate a formula into an integer. The Fluid_Coord_Input widget includes a formula interpreter that allows you to evaluate a string containing a mathematical formula and obtain the result as an integer. The interpreter supports unary plus and minus, basic integer math operations (such as addition, subtraction, multiplication, and division), and brackets. It also allows you to define a list of variables by name and use them in the formula. The interpreter does not perform error checking, so it is assumed that the formula is entered correctly. \param s formula as a C string \return the calculated value */ int Fluid_Coord_Input::eval(const char *s) const { // duplicate the text, so we can modify it uchar *buf = (uchar*)fl_strdup(s); uchar *src = buf, *dst = buf; // remove all whitespace to make the parser easier for (;;) { uchar c = *src++; if (c==' ' || c=='\t') continue; *dst++ = c; if (c==0) break; } src = buf; // now jump into the recursion int ret = eval(src, 5); ::free(buf); return ret; } /** Evaluate the formula and return the result. */ int Fluid_Coord_Input::value() const { return eval(text()); } /** Set the field to an integer value, replacing previous texts. */ void Fluid_Coord_Input::value(int v) { char buf[32]; fl_snprintf(buf, sizeof(buf), "%d", v); text(buf); } /** Allow vertical mouse dragging and mouse wheel to interactively change the value. */ int Fluid_Coord_Input::handle(int event) { switch (event) { case FL_MOUSEWHEEL: if (Fl::event_dy()) { value( value() - Fl::event_dy() ); set_changed(); do_callback(FL_REASON_CHANGED); } return 1; } return Fl_Input::handle(event); } fltk-1.4.3/fluid/pixmaps/0000755000175000017500000000000015004135251015371 5ustar albrechtalbrechtfltk-1.4.3/fluid/pixmaps/flTile.xpm0000644000175000017500000000254015004135251017337 0ustar albrechtalbrecht/* XPM */ static const char * const flTile_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "a c #eeeeee", "b c #2020ff", "c c none", "d c #dddddd", "e c #8080ff", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffdddddddddddaaffdddddddddddffcc", "ffdddddddddddaaffdddddddddddffcc", "ffdddddddddddaaffdddddddddddffcc", "ffdddddddddddaaffdddddddddddffcc", "ffdddddddffddaaffddffdddddddffcc", "ffddddddfffddddddddfffddddddffcc", "ffdddddffffddddddddffffdddddffcc", "ffddddfffffddddddddfffffddddffcc", "ffdddffffffddddddddffffffdddffcc", "ffddffffffffffffffffffffffddffcc", "ffddffffffffffffffffffffffddffcc", "ffdddffffffddddddddffffffdddffcc", "ffddddfffffddddddddfffffddddffcc", "ffdddddffffddddddddffffdddddffcc", "ffddddddfffddddddddfffddddddffcc", "ffdddddddffddaaffddffdddddddffcc", "ffdddddddddddaaffdddddddddddffcc", "ffdddddddddddaaffdddddddddddffcc", "ffdddddddddddaaffdddddddddddffcc", "ffdddddddddddaaffdddddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flFileInput.xpm0000644000175000017500000000254515004135251020346 0ustar albrechtalbrecht/* XPM */ static const char * const flFileInput_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "f c #606060", ". c #000000", "c c none", "d c #ffffff", "e c #8080ff", "a c #d0d0d0", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "c..............................c", ".ffffffffffffffffffffffffffffff.", ".fdddddddffddddddddddddffddddda.", ".fdddddddffddddddddddddffddddda.", ".ffffffffffffffffffffffffffffff.", "................................", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fddddddd..ddddddddddddddddddda.", ".fddddd......ddddddddddddddddda.", ".fdddd...dd...dddddddddddddddda.", ".fdddd..dddddddddddddddddddddda.", ".fdddd..dddddddd....dddddddddda.", ".fdddd..dddddddd....dddddddddda.", ".fdddd..dddddddddddddddddddddda.", ".fdddd..dddddddddddddddddddddda.", ".fdddd..dddddddd....dddddddddda.", ".fdddd...dd...dd....dddddddddda.", ".fddddd......ddddddddddddddddda.", ".fddddddd..ddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.", "c..............................c", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flCheckMenuitem.xpm0000644000175000017500000000262615004135251021170 0ustar albrechtalbrecht/* XPM */ static const char * const flCheckMenuitem_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 9 1", /* colors */ "a c #808080", "b c #dd0000", "c c none", "d c #aaaaaa", "e c #bbbbbb", "f c #d0d0d0", "g c #000000", "' c #000000", "o c #ffffff", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ccccccdddddddccccccccccccccccccc", "ccccdddddddddddccccccccccccccccc", "cgfdddddddddddddccccccccccdagccc", "cgfdddddddddddddddccccccdddagccc", "cgfddddddddddddddddddddddddagccc", "cgfddddddddddddddddddddddddagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfee''''''''''eeeeeeeeeeeeagccc", "cgfee''''''''''eeeeeeeeeeeeagccc", "cgfee''oooooo''eeeeeeeeeeeeagccc", "cgfee''oooooo''eeeeeeeeeeeeagccc", "cgfee''oooooo''eeeeeeeeeeeeagccc", "cgfee''oooooo''eeeeeeeeeeeeagccc", "cgfee''oooooo''eeeeeeeeeeeeagccc", "cgfee''oooooo''eeeeeeeeeeeeagccc", "cgfee''''''''''eeeeeeeeeeeeagccc", "cgfee''''''''''eeeeeeeeeeeeagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfddddddddddddddddddddddddagccc", "cgfddddddddddddddddddddddddagccc", "cgfdddccccccdddddddddddddddagccc", "cgfdccccccccccdddddddddddddagccc", "ccccccccccccccccddddddddddcccccc", "ccccccccccccccccccddddddcccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flWidgetClass.xpm0000644000175000017500000000260515004135251020655 0ustar albrechtalbrecht/* XPM */ static const char * const flWidgetClass_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 8 1", /* colors */ "a c #606060", "b c #2020ff", "c c none", "d c #bbbbbb", "e c #8080ff", "f c #dddddd", "g c #c0e0c0", "h c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffff", "feeeeebbbbbbbbbbbbbbeeeeebeeeeea", "feeeeebbbbbbbbbbbbbbeeeeebeeeeea", "feeeeebbbbbbbbbbbbbbeeeeebeeeeea", "feeeeebbbbbbbbbbbbbbeeeeebeeeeea", "feeeeebbbbbbbbbbbbbbeeeeebeeeeea", "fdddddddhhhhhhhhhhhhhhhhhhhhddda", "fddddddhhhhhhhhhhhhhhhhhhhhdddda", "fdddddhhgggggggggggggggghhddddda", "fddddhhgggggggggggggggghhdddddda", "fddddhhgggggggggggggggghhdddddda", "fdddhhgggggggggggggggghhddddddda", "fdddhhgggggggggggggggghhddddddda", "fdddhhgggggggggggggggghhddddddda", "fdddhhgggggggggggggggghhddddddda", "fdddhhgggggggggggggggghhddddddda", "fdddhhgggggggggggggggghhddddddda", "fddddhhgggggggggggggggghhdddddda", "fddddhhgggggggggggggggghhdddddda", "fdddddhhgggggggggggggggghhddddda", "fddddddhhhhhhhhhhhhhhhhhhhhdddda", "fdddddddhhhhhhhhhhhhhhhhhhhhddda", "fdddddddddddddddddddddddddddddda", "faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flHelp.xpm0000644000175000017500000000246515004135251017340 0ustar albrechtalbrecht/* XPM */ static const char * const flHelp_xpm[] = { "32 32 6 1", /* colors */ "a c #606060", "b c #888888", "c c none", "d c #ffffff", "e c #bbbbbb", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddffddddffddddddddddaaeeffcc", "ffddddffddddffddddddddddaaeeffcc", "ffdddffddddddffdddddddddaaeeffcc", "ffdddffddddddffdddddddddaabbffcc", "ffddffddddddddffddddddddaabbffcc", "ffddffddddddddffddddddddaabbffcc", "ffdddffddddddffdddddddddaabbffcc", "ffdddffddddddffdddddddddaabbffcc", "ffddddffddddffddddddddddaabbffcc", "ffddddffddddffddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flSubmenu.xpm0000644000175000017500000000265415004135251020066 0ustar albrechtalbrecht/* XPM */ static const char * const flSubmenu_xpm[] = { /* width height ncolors chars_per_pixel */ /* width height ncolors chars_per_pixel */ "32 32 8 1", /* colors */ "a c #808080", "b c #2020ff", "c c none", "d c #aaaaaa", "e c #bbbbbb", "f c #d0d0d0", "g c #000000", "' c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ccccccdddddddccccccccccccccccccc", "ccccdddddddddddccccccccccccccccc", "cgfdddddddddddddccccccccccdagccc", "cgfdddddddddddddddccccccdddagccc", "cgfddddddddddddddddddddddddagccc", "cgfddddddddddddddddddddddddagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfeee'''eeee'eeeeeeeeeeeeeagccc", "cgfee'''''eee''eeeeeeeeeeeeagccc", "cgfe'''e'''ee'''eeeeeeeeeeeagccc", "cgfe''eee''ee''''eeeeeeeeeeagccc", "cgfe'''''''ee'''''eeeeeeeeeagccc", "cgfe'''''''ee''''eeeeeeeeeeagccc", "cgfe''eee''ee'''eggggggggggggggg", "cgfe''eee''ee''egfffffffffffffff", "cgfe''eee''ee'eegfeeeeeeeeeeeeee", "cgfe''eee''eeeeegfeeeeeeeeeeeeee", "cgfeeeeeeeeeeeeegfeeeeeeeeeeeeee", "cgfeeeeeeeeeeeeegfeeeeeeeeeeeeee", "cgfdddddddddddddgfeeeeeeeeeeeeee", "cgfdddddddddddddgfeeeeeeeeeeeeee", "cgfdddccccccddddgfeeeeeeeeeeeeee", "cgfdccccccccccddgfeeeeeeeeeeeeee", "ccccccccccccccccgfeeeeeeeeeeeeee", "ccccccccccccccccgfeeeeeeeeeeeeee", "ccccccccccccccccgfeeeeeeeeeeeeee", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flValueOutput.xpm0000644000175000017500000000254715004135251020746 0ustar albrechtalbrecht/* XPM */ static const char * const flValueOutput_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "f c #606060", ". c #000000", "c c none", "d c #cccccc", "e c #8080ff", "a c #888888", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "c..............................c", ".ffffffffffffffffffffffffffffff.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fddddd....ddddddddddddddddddda.", ".fdddd......dddddddddddddddddda.", ".fddd..ddd...ddddddddddddddddda.", ".fdd..ddd..d..dddddddddddddddda.", ".fdd..ddd..d..dddddddddddddddda.", ".fdd..dd..dd..dddddddddddddddda.", ".fdd..dd..dd..dddddddddddddddda.", ".fdd..d..ddd..dddddddddddddddda.", ".fdd..d..ddd..dddddddddddddddda.", ".fddd...ddd..ddddddddddddddddda.", ".fdddd......dddddddddddddddddda.", ".fddddd....ddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.", "c..............................c", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flMenuButton.xpm0000644000175000017500000000256515004135251020551 0ustar albrechtalbrecht/* XPM */ static const char * const flMenuButton_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "a c #808080", "b c #2020ff", "c c none", "d c #a0a0a0", "e c #8080ff", "f c #d0d0d0", "g c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccggggggggggggggggggggggggggccc", "ccgffffffffffffffffffffffffffgcc", "cgffddddddddddddddddddddddddfagc", "cgfddddddddddddddddddddddddddagc", "cgfdddddddddddddddgggggggggddagc", "cgfdddddddddddddddgggggggggddagc", "cgfddddddddddddddddgggggggdddagc", "cgfddddddddddddddddgggggggdddagc", "cgfdddddddddddddddddgggggddddagc", "cgfdddddddddddddddddgggggddddagc", "cgfddddddddddddddddddgggdddddagc", "cgfddddddddddddddddddgggdddddagc", "cgfdddddddddddddddddddgddddddagc", "cgffddddddddddddddddddddddddaagc", "ccgaaaaaaaaaaaaaaaaaaaaaaaaaagcc", "cccggggggggggggggggggggggggggccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flInput.xpm0000644000175000017500000000254115004135251017542 0ustar albrechtalbrecht/* XPM */ static const char * const flInput_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "f c #606060", ". c #000000", "c c none", "d c #ffffff", "e c #8080ff", "a c #d0d0d0", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "c..............................c", ".ffffffffffffffffffffffffffffff.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fddddd....ddddd....dddddddddda.", ".fdddd......dddd....dddddddddda.", ".fdddd..dd..dddd....dddddddddda.", ".fddd..dddd..ddd....dddddddddda.", ".fddd..dddd..ddd....dddddddddda.", ".fdd..dddddd..dd....dddddddddda.", ".fdd..........dd....dddddddddda.", ".fdd..........dd....dddddddddda.", ".fdd..dddddd..dd....dddddddddda.", ".fdd..dddddd..dd....dddddddddda.", ".fdd..dddddd..dd....dddddddddda.", ".fdd..dddddd..dd....dddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.", "c..............................c", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flFlex.xpm0000644000175000017500000000254015004135251017340 0ustar albrechtalbrecht/* XPM */ static const char * const flFlex_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "a c #606060", "b c #2020ff", "c c none", "d c #999999", "e c #8080ff", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flCounter.xpm0000644000175000017500000000256215004135251020065 0ustar albrechtalbrecht/* XPM */ static const char * const flCounter_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "f c #606060", ". c #ffffff", "c c none", "d c #bbbbbb", "e c #8080ff", "a c #dddddd", "x c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "xffffffffffffffffffffffffffffffx", "xfddddddaa............ffddddddax", "xfddddddaa............ffddddddax", "xfdddxddaa.....xx.....ffddxdddax", "xfddxxddaa....xxx.....ffddxxddax", "xfdxxxddaa...xxxx.....ffddxxxdax", "xfxxxxddaa...xxxx.....ffddxxxxax", "xfxxxxddaa.....xx.....ffddxxxxax", "xfdxxxddaa.....xx.....ffddxxxdax", "xfddxxddaa...xxxxxx...ffddxxddax", "xfdddxddaa...xxxxxx...ffddxdddax", "xfddddddaa............ffddddddax", "xfddddddaa............ffddddddax", "xfaaaaaaaaaaaaaaaaaaaaaaaaaaaaax", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/compressed.xpm0000644000175000017500000000253115004135251020264 0ustar albrechtalbrecht/* cPM */ static const char * const compressed_xpm[] = { /* width height ncolors chars_per_picel */ "32 32 6 1", /* colors */ "- c #000", "= c #444", "c c none", "d c #cccccc", ". c #888", ", c #888", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ccccccc==================ccccccc", "cccccccc================cccccccc", "ccccccccc==============ccccccccc", "cccccccccc============cccccccccc", "ccccccccccc==========ccccccccccc", "cccccccccccc========cccccccccccc", "ccccccccccccc======ccccccccccccc", "cccccccccccccc====cccccccccccccc", "cc==.cccccccccc==ccccccccccc==cc", "cc.====..cccccccccccccc..====.cc", "cccc.======================.cccc", "cccccccc..============..cccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccc..============..cccccccc", "cccc.======================.cccc", "cc.====..cccccccccccccc..====.cc", "cc==.cccccccccc==ccccccccccc==cc", "cccccccccccccc====cccccccccccccc", "ccccccccccccc======ccccccccccccc", "cccccccccccc========cccccccccccc", "ccccccccccc==========ccccccccccc", "cccccccccc============cccccccccc", "ccccccccc==============ccccccccc", "cccccccc================cccccccc", "ccccccc==================ccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", }; fltk-1.4.3/fluid/pixmaps/flBox.xpm0000644000175000017500000000253715004135251017200 0ustar albrechtalbrecht/* XPM */ static const char * const flBox_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "a c #606060", "b c #2020ff", "c c none", "d c #cccccc", "e c #8080ff", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flCode.xpm0000644000175000017500000000250315004135251017313 0ustar albrechtalbrecht/* XPM */ static const char * const flCode_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 4 1", /* colors */ ". c none", "a c #000000", "b c #c0e0c0", "c c #000000", /* pixels */ "................................", "................................", "................................", "................................", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aacccccccccccccccccccccccccccccc", "aacccccccccccccccccccccccccccccc", "................................", "................................", "................................", "................................", }; fltk-1.4.3/fluid/pixmaps/flRoundButton.xpm0000644000175000017500000000256615004135251020735 0ustar albrechtalbrecht/* XPM */ static const char * const flRoundButton_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "a c #606060", "b c #2020ff", ". c none", "d c #ffffff", "e c #8080ff", "f c #d0d0d0", "# c #000000", /* pixels */ "................................", "................................", "................................", "................................", ".............aaaaa..............", "...........aaaaaaaaa............", ".........aaadddddddaaa..........", "........aaadddddddddaaa.........", ".......aadddddddddddddff........", "......aadddddddddddddddff.......", "......aaddddd#####dddddff.......", ".....aaddddd#######dddddff......", ".....aadddd#########ddddff......", "....aadddd###########ddddff.....", "....aadddd###########ddddff.....", "....aadddd###########ddddff.....", "....aadddd###########ddddff.....", "....aadddd###########ddddff.....", ".....aadddd#########ddddff......", ".....aaddddd#######dddddff......", "......aaddddd#####dddddff.......", "......aadddddddddddddddff.......", ".......aadddddddddddddff........", "........fffdddddddddfff.........", ".........fffdddddddfff..........", "...........fffffffff............", ".............fffff..............", "................................", "................................", "................................", "................................", "................................" }; fltk-1.4.3/fluid/pixmaps/flTextEdit.xpm0000644000175000017500000000254415004135251020200 0ustar albrechtalbrecht/* XPM */ static const char * const flTextEdit_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "f c #606060", ". c #000000", "c c none", "d c #ffffff", "e c #8080ff", "a c #d0d0d0", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "c..............................c", ".ffffffffffffffffffffffffffffff.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fddddd....ddddd....dddddddddda.", ".fdddd......dddd....dddddddddda.", ".fdddd..dd..dddd....dddddddddda.", ".fddd..dddd..ddd....dddddddddda.", ".fddd..dddd..ddd....dddddddddda.", ".fdd..dddddd..dd....dddddddddda.", ".fdd..........dd....dddddddddda.", ".fdd..........dd....dddddddddda.", ".fdd..dddddd..dd....dddddddddda.", ".fdd..dddddd..dd....dddddddddda.", ".fdd..dddddd..dd....dddddddddda.", ".fdd..dddddd..dd....dddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.", "c..............................c", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flComment.xpm0000644000175000017500000000250615004135251020046 0ustar albrechtalbrecht/* XPM */ static const char * const flComment_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 4 1", /* colors */ ". c none", "a c #000000", "b c #c0e0c0", "c c #000000", /* pixels */ "................................", "................................", "................................", "................................", "..aaaaaaaaaaaaaaaaaaaaaaaaaaaa..", "..aaaaaaaaaaaaaaaaaaaaaaaaaaaa..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aabbbbbbbbbcccbbbbbcccbbbbcc..", "..aabbbbbbbbbcccbbbbbcccbbbbcc..", "..aabbbbbbbbcccbbbbbcccbbbbbcc..", "..aabbbbbbbbcccbbbbbcccbbbbbcc..", "..aabbbbbbbcccbbbbbcccbbbbbbcc..", "..aabbbbbbbcccbbbbbcccbbbbbbcc..", "..aabbbbbbcccbbbbbcccbbbbbbbcc..", "..aabbbbbbcccbbbbbcccbbbbbbbcc..", "..aabbbbbcccbbbbbcccbbbbbbbbcc..", "..aabbbbbcccbbbbbcccbbbbbbbbcc..", "..aabbbbcccbbbbbcccbbbbbbbbbcc..", "..aabbbbcccbbbbbcccbbbbbbbbbcc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aacccccccccccccccccccccccccc..", "..aacccccccccccccccccccccccccc..", "................................", "................................", "................................", "................................", }; fltk-1.4.3/fluid/pixmaps/flSimpleTerminal.xpm0000644000175000017500000000255215004135251021372 0ustar albrechtalbrecht/* XPM */ static const char * const flSimpleTerminal_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "f c #606060", ". c #000000", "c c none", "d c #ffffff", "e c #8080ff", "a c #d0d0d0", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "c..............................c", ".ffffffffffffffffffffffffffffff.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdd...ddddddddddddddddddddddda.", ".fddd...dddddddddddddddddddddda.", ".fdddd...ddddddddddddddddddddda.", ".fddddd...dddddddddddddddddddda.", ".fdddddd...ddddddddddddddddddda.", ".fddddddd...dddddddddddddddddda.", ".fddddddd...dddddddddddddddddda.", ".fdddddd...ddddddddddddddddddda.", ".fddddd...dddddddddddddddddddda.", ".fdddd...ddddddddddddddddddddda.", ".fddd...dddddd........dddddddda.", ".fdd...ddddddd........dddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.", "c..............................c", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flAdjuster.xpm0000644000175000017500000000256315004135251020230 0ustar albrechtalbrecht/* XPM */ static const char * const flAdjuster_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "a c #606060", ". c #ffff00", "c c none", "d c #bbbbbb", "e c #8080ff", "f c #dddddd", "x c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "xffffffffffffffffffffffffffffffx", "xfdddddddaxxfddddddaxxfdddddddax", "xfdddddddaxxfddddddaxxfdddddddax", "xfdddddddaxxfddddddaxxfdddddddax", "xfdddddddaxxfddddddaxxfdddddddax", "xfdddddddaxxfddddddaxxfdddddddax", "xfdddddddaxxfddddddaxxfdddddddax", "xfdddddddaxxfddddddaxxfdddddddax", "xfdddddddaxxfddddddaxxfdddddddax", "xfdddddddaxxfddddddaxxfdddddddax", "xfdddddddaxxfddddddaxxfdddddddax", "xfdddddddaxxfddddddaxxfdddddddax", "xfdddddddaxxfddddddaxxfdddddddax", "xfaaaaaaaaaaaaaaaaaaaaaaaaaaaaax", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flOutput.xpm0000644000175000017500000000254215004135251017744 0ustar albrechtalbrecht/* XPM */ static const char * const flOutput_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "f c #606060", ". c #000000", "c c none", "d c #cccccc", "e c #8080ff", "a c #888888", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "c..............................c", ".ffffffffffffffffffffffffffffff.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fddddd....ddddddddddddddddddda.", ".fdddd......dddddddddddddddddda.", ".fdddd..dd..dddddddddddddddddda.", ".fddd..dddd..ddddddddddddddddda.", ".fddd..dddd..ddddddddddddddddda.", ".fdd..dddddd..dddddddddddddddda.", ".fdd..........dddddddddddddddda.", ".fdd..........dddddddddddddddda.", ".fdd..dddddd..dddddddddddddddda.", ".fdd..dddddd..dddddddddddddddda.", ".fdd..dddddd..dddddddddddddddda.", ".fdd..dddddd..dddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.", "c..............................c", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flClock.xpm0000644000175000017500000000263315004135251017500 0ustar albrechtalbrecht/* XPM */ static const char * const flClock_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 5 1", /* colors */ ". c none", "a c #000000", "b c #bbbbbb", "c c #000000", "' c #202080", /* pixels */ "................................", "................................", "................................", "............aaaaaaaa............", ".........aaaaaaaaaaaaaa.........", ".......aaaaaabbbbbbcccccc.......", "......aaabbbbbbbbbbbbbbccc......", ".....aaabbbbbbbbbbbbbbbbccc.....", "....aaabbbbbbbbbbbbbbbbabccc....", "....aabbbbbbbbbbbbbbbbaaabcc....", "...aaabbbbbbbbbbbbbbbaaabbccc...", "...aabbbbbbbbbbbbbbbaaabbbbcc...", "...aabbbbbbbabbbbbbaaabbbbbcc...", "..aaabbbbbbaaabbbbaaabbbbbbccc..", "..aabbbbbbbbaaabbaaabbbbbbbbcc..", "..aabbbbbbbbbaaaaaabbbbbbbbbcc..", "..aabbbbbbbbbbaaaabbbbbbbbbbcc..", "..aabbbbbbbbbbaaaabbbbbbbbbbcc..", "..aabbbbbbbbbbbaabbbbbbbbbbbcc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aaabbbbbbbbbbbbbbbbbbbbbbccc..", "...aabbbbbbbbbbbbbbbbbbbbbbcc...", "...aabbbbbbbbbbbbbbbbbbbbbbcc...", "...aaabbbbbbbbbbbbbbbbbbbbccc...", "....aabbbbbbbbbbbbbbbbbbbbcc....", "....aaabbbbbbbbbbbbbbbbbbccc....", ".....aaabbbbbbbbbbbbbbbbccc.....", "......cccbbbbbbbbbbbbbcccc......", ".......cccccbbbbbbbbccccc.......", ".........cccccccccccccc.........", "............cccccccc............", "................................", "................................", "................................", }; fltk-1.4.3/fluid/pixmaps/flPack.xpm0000644000175000017500000000254015004135251017320 0ustar albrechtalbrecht/* XPM */ static const char * const flPack_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "a c #606060", "b c #2020ff", "c c none", "d c #dddddd", "e c #8080ff", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flWindow.xpm0000644000175000017500000000254215004135251017713 0ustar albrechtalbrecht/* XPM */ static const char * const flWindow_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "a c #606060", "b c #2020ff", "c c none", "d c #bbbbbb", "e c #8080ff", "f c #dddddd", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffff", "feeeeebbbbbbbbbbbbbbeeeeebeeeeea", "feeeeebbbbbbbbbbbbbbeeeeebeeeeea", "feeeeebbbbbbbbbbbbbbeeeeebeeeeea", "feeeeebbbbbbbbbbbbbbeeeeebeeeeea", "feeeeebbbbbbbbbbbbbbeeeeebeeeeea", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "fdddddddddddddddddddddddddddddda", "faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flFileBrowser.xpm0000644000175000017500000000251315004135251020665 0ustar albrechtalbrecht/* XPM */ static const char * const flFileBrowser_xpm[] = { "32 32 7 1", /* colors */ "a c #606060", "b c #888888", "c c none", "d c #ffffff", "e c #bbbbbb", "f c #000000", ". c #ffff00", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddfffffdddddddddddddaabbffcc", "ffdddfffffffddddddddddddaabbffcc", "ffddfff....fffffffffffddaabbffcc", "ffddff......ffffffffffddaabbffcc", "ffddff..............ffddaabbffcc", "ffddff..............ffddaabbffcc", "ffddff..............ffddaabbffcc", "ffddff..............ffddaabbffcc", "ffddff..............ffddaabbffcc", "ffddff..............ffddaabbffcc", "ffddff..............ffddaabbffcc", "ffddff..............ffddaabbffcc", "ffddff..............ffddaabbffcc", "ffddff..............ffddaabbffcc", "ffddffffffffffffffffffddaaeeffcc", "ffddffffffffffffffffffddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flTabs.xpm0000644000175000017500000000255715004135251017343 0ustar albrechtalbrecht/* XPM */ static const char * const flTabs_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "a c #a0a0a0", "b c #2020ff", "c c none", "d c #dddddd", "e c #8080ff", "f c #000000", ". c #eeeeee", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ccffffffffffccffffffffcccccccccc", "cffffffffffffcfffffffffccccccccc", "ff..........ffaaaaaaaaffcccccccc", "ff..........ffaaaaaaaaffcccccccc", "ff..........ffaaaaaaaaffcccccccc", "ff..........ffaaaaaaaaffcccccccc", "ff..........ffffffffffffffffffcc", "ff..........ffffffffffffffffffcc", "ff..........................ffcc", "ff..........................ffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flMenubar.xpm0000644000175000017500000000260115004135251020031 0ustar albrechtalbrecht/* XPM */ static const char * const flMenubar_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 8 1", /* colors */ "a c #808080", "b c #2020ff", "c c none", "d c #aaaaaa", "e c #8080ff", "f c #d0d0d0", "g c #000000", "' c #bbbbbb", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "gggggggggggggggggggggggggggggggg", "ffffffffffffffffffffffffffffffff", "dddddddddddddddddddddddddddddddd", "dddddddddddddddddddddddddddddddd", "ddddddddgggggggggggggggggggggddd", "dddddddgffffffffffffffffffffagdd", "dddddddgf'''''''''''''''''''agdd", "dddddddgf'''''''''''''''''''agdd", "dddddddgf'''''''''''''''''''agdd", "dddddddgf'''''''''''''''''''agdd", "dddddddgf'''''''''''''''''''agdd", "dddddddgf'''''''''''''''''''agdd", "dddddddgf'''''''''''''''''''agdd", "dddddddgf'''''''''''''''''''agdd", "aaaaaaagf'''''''''''''''''''agaa", "ggggggggf'''''''''''''''''''aggg", "cccccccgf'''''''''''''''''''agcc", "cccccccgf'''''''''''''''''''agcc", "cccccccgf'''''''''''''''''''agcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flWizard.xpm0000644000175000017500000000254215004135251017704 0ustar albrechtalbrecht/* XPM */ static const char * const flWizard_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "a c #606060", "b c #bbbbbb", "c c none", "d c #dddddd", "e c #8080ff", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffbbbbbbbbbbbbffbbbbbbbbbbbbffcc", "ffbbbbbbbffbbbffbbbffbbbbbbbffcc", "ffbbbbbffffbbbffbbbffffbbbbbffcc", "ffbbbffffffbbbffbbbffffffbbbffcc", "ffbbbbbffffbbbffbbbffffbbbbbffcc", "ffbbbbbbbffbbbffbbbffbbbbbbbffcc", "ffbbbbbbbbbbbbffbbbbbbbbbbbbffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flBrowser.xpm0000644000175000017500000000254315004135251020070 0ustar albrechtalbrecht/* XPM */ static const char * const flBrowser_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "a c #606060", "b c #888888", "c c none", "d c #ffffff", "e c #bbbbbb", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flValueSlider.xpm0000644000175000017500000000256615004135251020671 0ustar albrechtalbrecht/* XPM */ static const char * const flValueSlider_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "f c #606060", ". c #ffff00", "c c none", "d c #bbbbbb", "e c #8080ff", "a c #dddddd", "x c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "xffffffffffffffffffffffffffffffx", "xfdddddddddddaaaaaaaaaadddddddax", "xfddddddddddaaaaaaaaaaffddddddax", "xfddddxxddddaaddddddddffddddddax", "xfdddxxxddddaaddddddddffddddddax", "xfddxxxxddddaaddddddddffddddddax", "xfddxxxxddddaaddddddddffddddddax", "xfddddxxddddaaddddddddffddddddax", "xfddddxxddddaaddddddddffddddddax", "xfddxxxxxxddaaddddddddffddddddax", "xfddxxxxxxddaaddddddddffddddddax", "xfddddddddddafffffffffffddddddax", "xfdddddddddddffffffffffdddddddax", "xfaaaaaaaaaaaaaaaaaaaaaaaaaaaaax", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flDeclaration.xpm0000644000175000017500000000251215004135251020666 0ustar albrechtalbrecht/* XPM */ static const char * const flDeclaration_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 4 1", /* colors */ ". c none", "a c #000000", "b c #c0e0c0", "c c #000000", /* pixels */ "................................", "................................", "................................", "................................", ".......aaaaaaaaaaaaaaaaaaaaaaaaa", ".......aaaaaaaaaaaaaaaaaaaaaaaaa", ".......aabbbbbbbbbbbbbbbbbbbbbcc", "......aabbbbbbbbbbbbbbbbbbbbbcc.", "......aabbbbbbbbbbbbbbbbbbbbbcc.", "......aabbbbbbbbbbbbbbbbbbbbbcc.", ".....aabbbbbbbbbbbbbbbbbbbbbcc..", ".....aabbbbbbbbbbbbbbbbbbbbbcc..", ".....aabbbbbbbbbbbbbbbbbbbbbcc..", "....aabbbbbbbbbbbbbbbbbbbbbcc...", "....aabbbbbbbbbbbbbbbbbbbbbcc...", "....aabbbbbbbbbbbbbbbbbbbbbcc...", "...aabbbbbbbbbbbbbbbbbbbbbcc....", "...aabbbbbbbbbbbbbbbbbbbbbcc....", "...aabbbbbbbbbbbbbbbbbbbbbcc....", "..aabbbbbbbbbbbbbbbbbbbbbcc.....", "..aabbbbbbbbbbbbbbbbbbbbbcc.....", "..aabbbbbbbbbbbbbbbbbbbbbcc.....", ".aabbbbbbbbbbbbbbbbbbbbbcc......", ".aabbbbbbbbbbbbbbbbbbbbbcc......", ".aabbbbbbbbbbbbbbbbbbbbccc......", "aabbbbbbbbbbbbbbbbbbbbbcc.......", "aaccccccccccccccccccccccc.......", "aaccccccccccccccccccccccc.......", "................................", "................................", "................................", "................................", }; fltk-1.4.3/fluid/pixmaps/flScrollBar.xpm0000644000175000017500000000256415004135251020333 0ustar albrechtalbrecht/* XPM */ static const char * const flScrollBar_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "f c #606060", ". c #ffff00", "c c none", "d c #bbbbbb", "e c #8080ff", "a c #dddddd", "x c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "xffffffffffffffffffffffffffffffx", "xfdddddddddaaaaaaaaaadddddddddax", "xfddddddddaaaaaaaaaaffddddddddax", "xfdddxddddaaddddddddffddddxdddax", "xfddxxddddaaddddddddffddddxxddax", "xfdxxxddddaaddddddddffddddxxxdax", "xfxxxxddddaaddddddddffddddxxxxax", "xfxxxxddddaaddddddddffddddxxxxax", "xfdxxxddddaaddddddddffddddxxxdax", "xfddxxddddaaddddddddffddddxxddax", "xfdddxddddaaddddddddffddddxdddax", "xfddddddddafffffffffffddddddddax", "xfdddddddddffffffffffdddddddddax", "xfaaaaaaaaaaaaaaaaaaaaaaaaaaaaax", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flFunction.xpm0000644000175000017500000000250715004135251020232 0ustar albrechtalbrecht/* XPM */ static const char * const flFunction_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 4 1", /* colors */ ". c none", "a c #000000", "b c #c0e0c0", "c c #000000", /* pixels */ "................................", "................................", "................................", "................................", "..........aaaaaaaaaaaa..........", ".......aaaaaaaaaaaaaaaaaa.......", ".....aaaaaabbbbbbbbbbcccccc.....", "....aaabbbbbbbbbbbbbbbbbbccc....", "...aaabbbbbbbbbbbbbbbbbbbbccc...", "..aaabbbbbbbbbbbbbbbbbbbbbbccc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", ".aaabbbbbbbbbbbbbbbbbbbbbbbbccc.", ".aabbbbbbbbbbbbbbbbbbbbbbbbbbcc.", ".aabbbbbbbbbbbbbbbbbbbbbbbbbbcc.", "aaabbbbbbbbbbbbbbbbbbbbbbbbbbccc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aabbbbbbbbbbbbbbbbbbbbbbbbbbbbcc", "aaabbbbbbbbbbbbbbbbbbbbbbbbbbccc", ".aabbbbbbbbbbbbbbbbbbbbbbbbbbcc.", ".aabbbbbbbbbbbbbbbbbbbbbbbbbbcc.", ".aaabbbbbbbbbbbbbbbbbbbbbbbbccc.", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aaabbbbbbbbbbbbbbbbbbbbbbccc..", "...aaabbbbbbbbbbbbbbbbbbbbccc...", "....cccbbbbbbbbbbbbbbbbbcccc....", ".....cccccbbbbbbbbbbbbccccc.....", ".......cccccccccccccccccc.......", "..........cccccccccccc..........", "................................", "................................", "................................", "................................", }; fltk-1.4.3/fluid/pixmaps/flProgress.xpm0000644000175000017500000000256315004135251020253 0ustar albrechtalbrecht/* XPM */ static const char * const flProgress_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "f c #606060", ". c #ffff00", "c c none", "d c #bbbbbb", "e c #8080ff", "a c #d0d0d0", "x c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "xffffffffffffffffffffffffffffffx", "xf..................ddddddddddax", "xf..................ddddddddddax", "xf..................ddddddddddax", "xf..................ddddddddddax", "xf..................ddddddddddax", "xf..................ddddddddddax", "xf..................ddddddddddax", "xf..................ddddddddddax", "xf..................ddddddddddax", "xf..................ddddddddddax", "xf..................ddddddddddax", "xf..................ddddddddddax", "xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flClass.xpm0000644000175000017500000000253415004135251017512 0ustar albrechtalbrecht/* XPM */ static const char * const flClass_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 4 1", /* colors */ ". c none", "a c #000000", "b c #c0e0c0", "c c #000000", /* pixels */ "................................", "................................", "................................", "................................", ".....aaaaaaaaaaaaaaaaaaaaaaaaaaaa", "....aaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "...aaabbbbbbbbbbbbbbbbbbbbbbaaa..", "..aaabbbbbbbbbbbbbbbbbbbbbbaaa...", "..aabbbbbbbbbbbbbbbbbbbbbbbaa....", ".aaabbbbbbbbbbbbbbbbbbbbbbaaa....", ".aabbbbbbbbbbbbbbbbbbbbbbbaa.....", ".aabbbbbbbbbbbbbbbbbbbbbbbaa.....", "aaabbbbbbbbbbbbbbbbbbbbbbaaa.....", "aabbbbbbbbbbbbbbbbbbbbbbbaa......", "aabbbbbbbbbbbbbbbbbbbbbbbaa......", "aabbbbbbbbbbbbbbbbbbbbbbbaa......", "aabbbbbbbbbbbbbbbbbbbbbbbaa......", "aabbbbbbbbbbbbbbbbbbbbbbbaa......", "aabbbbbbbbbbbbbbbbbbbbbbbaa......", "aaabbbbbbbbbbbbbbbbbbbbbbaaa.....", ".aabbbbbbbbbbbbbbbbbbbbbbbaa.....", ".aabbbbbbbbbbbbbbbbbbbbbbbaa.....", ".aaabbbbbbbbbbbbbbbbbbbbbbaaa....", "..aabbbbbbbbbbbbbbbbbbbbbbbaa....", "..aaabbbbbbbbbbbbbbbbbbbbbbaaa...", "...aaabbbbbbbbbbbbbbbbbbbbbbaaa..", "....ccccccccccccccccccccccccccccc", ".....cccccccccccccccccccccccccccc", "................................", "................................", "................................", "................................", }; fltk-1.4.3/fluid/pixmaps/flGrid.xpm0000644000175000017500000000254015004135251017327 0ustar albrechtalbrecht/* XPM */ static const char * const flGrid_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "a c #606060", "b c #2020ff", "c c none", "d c #dddddd", "e c #8080ff", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffddddddddfddddddddfddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flData.xpm0000644000175000017500000000254215004135251017315 0ustar albrechtalbrecht/* XPM */ static const char * const flData_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ ". c none", "a c #000000", "b c #c0e0c0", "c c #000000", " c #000000", "- c #607006", /* pixels */ "................................", "................................", "................................", "................................", ".......aaaaaaaaaaaaaaaaaaaaaaaaa", ".......aaaaaaaaaaaaaaaaaaaaaaaaa", ".......aabbbbbbbbbbbbbbbbbbbbbcc", "......aabbbbbbbbbbbbbbbbbbbbbcc.", "......aabbb bbb- -bbb bbbbcc.", "......aabb bb- -b bbbbcc.", ".....aabbbb bb bb bb bbbcc..", ".....aabbbb bb bb bb bbbcc..", ".....aabbbb bb- -bb bbbcc..", "....aabbbbb bbb- -bbb bbcc...", "....aabbbbbbbbbbbbbbbbbbbbbcc...", "....aabbbbbbbbbbbbbbbbbbbbbcc...", "...aabbbbbbbbbbbbbbbbbbbbbcc....", "...aabbbbbbbbbbbbbbbbbbbbbcc....", "...aabb bb bbb- -bbbbbbcc....", "..aabb b bb- -bbbbcc.....", "..aabbb bb bb bb bbbbcc.....", "..aabbb bb bb bb bbbbcc.....", ".aabbbb bb bb- -bbbcc......", ".aabbbb bb bbb- -bbbbcc......", ".aabbbbbbbbbbbbbbbbbbbbbcc......", "aabbbbbbbbbbbbbbbbbbbbbbcc.......", "aaccccccccccccccccccccccc.......", "aaccccccccccccccccccccccc.......", "................................", "................................", "................................", "................................", }; fltk-1.4.3/fluid/pixmaps/flTree.xpm0000644000175000017500000000254015004135251017341 0ustar albrechtalbrecht/* XPM */ static const char * const flTree_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "a c #606060", "b c #888888", "c c none", "d c #ffffff", "e c #bbbbbb", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddffddddddddddddddddaaeeffcc", "ffddddffddddddddddddddddaabbffcc", "ffddddffffffffddddddddddaabbffcc", "ffddddffffffffddddddddddaabbffcc", "ffddddffddddffddddddddddaabbffcc", "ffddddffddddffddddddddddaabbffcc", "ffddddffddddffffffffddddaabbffcc", "ffddddffddddffffffffddddaabbffcc", "ffddddffddddffddddddddddaabbffcc", "ffddddffddddffddddddddddaabbffcc", "ffddddffddddffddddddddddaabbffcc", "ffddddffddddffffffffddddaaeeffcc", "ffddddffddddffffffffddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flButton.xpm0000644000175000017500000000256115004135251017720 0ustar albrechtalbrecht/* XPM */ static const char * const flButton_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "a c #808080", "b c #2020ff", "c c none", "d c #a0a0a0", "e c #8080ff", "f c #d0d0d0", "g c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccggggggggggggggggggggggggggccc", "ccgffffffffffffffffffffffffffgcc", "cgffddddddddddddddddddddddddfagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgffddddddddddddddddddddddddaagc", "ccgaaaaaaaaaaaaaaaaaaaaaaaaaagcc", "cccggggggggggggggggggggggggggccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/invisible.xpm0000644000175000017500000000254315004135251020107 0ustar albrechtalbrecht/* XPM */ static const char * const invisible_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "` c #000000", "a c #80c080", "b c #c0ffc0", "c c none", "M c #e0e0e0", "e c #408040", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ccccMMMMMMcccccccccccccccccccccc", "ccccMMMMMMcccccccccccccccccccccc", "ccccMM``MMcccccccccccccccccccccc", "ccccMM``MMcccccccccccccccccccccc", "MMMMMMMMMMcccccccccccccccccccccc", "MMMMMMMMMMcccccccccccccccccccccc", "MM``````MMcccccccccccccccccccccc", "MM``````MMcccccccccccccccccccccc", "MMMMMM``MMcccccccccccccccccccccc", "MMMMMM``MMcccccccccccccccccccccc", "ccccMM``MMcccccccccccccccccccccc", "ccccMM``MMcccccccccccccccccccccc", "MMMMMM``MMMMMMcccccccccccccccccc", "MMMMMM``MMMMMMcccccccccccccccccc", "MM``````````MMcccccccccccccccccc", "MM``````````MMcccccccccccccccccc", "MMMMMMMMMMMMMMcccccccccccccccccc", "MMMMMMMMMMMMMMcccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flInputChoice.xpm0000644000175000017500000000260515004135251020656 0ustar albrechtalbrecht/* XPM */ static const char * const flInputChoice_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 8 1", /* colors */ "a c #808080", "b c #2020ff", "c c none", "d c #a0a0a0", "e c #8080ff", "f c #d0d0d0", "g c #000000", "' c #ffffff", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccggggggggggggggggggggggggggccc", "ccgaaaaaaaaaaaagfffffffffffffgcc", "cgaa'''''''''''gddddddgdddddfagc", "cga''''''''''''gdddddgggdddddagc", "cga''''''''''''gddddgggggddddagc", "cga''''''''''''gdddgggggggdddagc", "cga''''''''''''gddgggggggggddagc", "cga''''''''''''gdddddddddddddagc", "cga''''''''''''gdddddddddddddagc", "cga''''''''''''gddgggggggggddagc", "cga''''''''''''gdddgggggggdddagc", "cga''''''''''''gddddgggggddddagc", "cga''''''''''''gdddddgggdddddagc", "cgaa'''''''''''gddddddgdddddaagc", "ccgffffffffffffgaaaaaaaaaaaaagcc", "cccggggggggggggggggggggggggggccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/print_gray.xpm0000644000175000017500000000173615004135251020304 0ustar albrechtalbrecht/* XPM */ static char * const print_gray_xpm[] = { "24 24 17 1", " c None", ". c #E3E3E3", "+ c #D2D2D2", "@ c #969696", "# c #C2C2C2", "$ c #4C4C4C", "% c #B2B2B2", "& c #000000", "* c #696969", "= c #ACACAC", "- c #626262", "; c #767676", "> c #3C3C3C", ", c #161616", "' c #1C1C1C", ") c #929292", "! c #585858", " ...... ", " .......... ", " ............ ", " .............. ", " .............. ", " ................ ", " ................ ", " ................ ", " +@@@@@@+#$$$$$$# ", " %@@@@@@@&&$$$$$$$* ", " %%@@@@@@&&&&$$$$$$** ", " %%%=@@@@&&&&&&$$$$-*** ", " %%%%@@@;&&&&&&>$$$**** ", "%%%%%%@@&&&&&&&&$$******", "%%%%%%%@&&&&&&&&$*******", "%%%%%%%%,&&&&&&,********", "%%%%%%%%''''''''********", "%%%%%%%%''''''''********", "%%%%%%%%''''''''********", " %%%%%%%)''''''!******* ", " %%%%%%%%''''''******** ", " %%%%%%%%''''******** ", " %%%%%%%%''******** ", " %%%%%% ****** "}; fltk-1.4.3/fluid/pixmaps/flTable.xpm0000644000175000017500000000256115004135251017474 0ustar albrechtalbrecht/* XPM */ static const char * const flTable_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "a c #606060", "b c #888888", "c c none", "d c #ffffff", "e c #bbbbbb", "f c #000000", "x c #9999999", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddxxddddddddddaaeeffcc", "ffddddddddddxxddddddddddaaeeffcc", "ffddddddddddxxddddddddddaaeeffcc", "ffddddddddddxxddddddddddaaeeffcc", "ffddddddddddxxddddddddddaabbffcc", "ffxxxxxxxxxxxxxxxxxxxxxxaabbffcc", "ffxxxxxxxxxxxxxxxxxxxxxxaabbffcc", "ffddddddddddxxddddddddddaabbffcc", "ffddddddddddxxddddddddddaabbffcc", "ffddddddddddxxddddddddddaabbffcc", "ffddddddddddxxddddddddddaabbffcc", "ffddddddddddxxddddddddddaabbffcc", "ffddddddddddxxddddddddddaabbffcc", "ffxxxxxxxxxxxxxxxxxxxxxxaabbffcc", "ffxxxxxxxxxxxxxxxxxxxxxxaabbffcc", "ffddddddddddxxddddddddddaaeeffcc", "ffddddddddddxxddddddddddaaeeffcc", "ffddddddddddxxddddddddddaaeeffcc", "ffddddddddddxxddddddddddaaeeffcc", "ffddddddddddxxddddddddddaaeeffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flDeclarationBlock.xpm0000644000175000017500000000251715004135251021646 0ustar albrechtalbrecht/* XPM */ static const char * const flDeclarationBlock_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 4 1", /* colors */ ". c none", "a c #000000", "b c #c0e0c0", "c c #000000", /* pixels */ "...............aa...............", "..............aaaa..............", ".............aaaccc.............", "............aaabbccc............", "...........aaabbbbccc...........", "..........aaabbbbbbccc..........", ".........aaabbbbbbbbccc.........", "........aaabbbbbbbbbbccc........", ".......aaabbbbbbbbbbbbccc.......", "......aaabbbbbbbbbbbbbbccc......", ".....aaabbbbccbbbbccbbbbccc.....", "....aaabbbbbccbbbbccbbbbbccc....", "...aaabbbbccccccccccccbbbbccc...", "..aaabbbbbccccccccccccbbbbbccc..", ".aaabbbbbbbbccbbbbccbbbbbbbbccc.", "aaabbbbbbbbbccbbbbccbbbbbbbbbccc", "aabbbbbbbbbbccbbbbccbbbbbbbbbccc", ".aaabbbbbbbbccbbbbccbbbbbbbbccc.", "..aaabbbbbccccccccccccbbbbbccc..", "...aaabbbbccccccccccccbbbbccc...", "....aaabbbbbccbbbbccbbbbbccc....", ".....aaabbbbccbbbbccbbbbccc.....", "......aaabbbbbbbbbbbbbbccc......", ".......aaabbbbbbbbbbbbccc.......", "........aaabbbbbbbbbbccc........", ".........aaabbbbbbbbccc.........", "..........aaabbbbbbccc..........", "...........aaabbbbccc...........", "............aaabbccc............", ".............aaaccc.............", "..............aacc..............", "...............ac...............", }; fltk-1.4.3/fluid/pixmaps/flReturnButton.xpm0000644000175000017500000000256715004135251021126 0ustar albrechtalbrecht/* XPM */ static const char * const flReturnButton_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "a c #808080", "b c #2020ff", "c c none", "d c #a0a0a0", "e c #cccccc", "f c #d0d0d0", "g c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccggggggggggggggggggggggggggccc", "ccgffffffffffffffffffffffffffgcc", "cgffddddddddddddddddddddddddfagc", "cgfdddddddddddddddddddgggggddagc", "cgfdddddddddddggddddddgeeegddagc", "cgfddddddddddgegddddddgeeegddagc", "cgfdddddddddgeeggggggggeeegddagc", "cgfddddddddgeeeeeeeeeeeeeegddagc", "cgfdddddddgeeeeeeeeeeeeeeegddagc", "cgfddddddddgeeeeeeeeeeeeeegddagc", "cgfdddddddddgeeggggggggggggddagc", "cgfddddddddddgegdddddddddddddagc", "cgfdddddddddddggdddddddddddddagc", "cgffddddddddddddddddddddddddaagc", "ccgaaaaaaaaaaaaaaaaaaaaaaaaaagcc", "cccggggggggggggggggggggggggggccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flSlider.xpm0000644000175000017500000000256115004135251017667 0ustar albrechtalbrecht/* XPM */ static const char * const flSlider_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "f c #606060", ". c #ffff00", "c c none", "d c #bbbbbb", "e c #8080ff", "a c #dddddd", "x c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "xffffffffffffffffffffffffffffffx", "xfdaaaaaaaaaaaadddddddddddddddax", "xfaaaaaaaaaaaaffddddddddddddddax", "xfaaddddddddddffddddddddddddddax", "xfaaddddddddddffddddddddddddddax", "xfaaddddddddddffddddddddddddddax", "xfaaddddddddddffddddddddddddddax", "xfaaddddddddddffddddddddddddddax", "xfaaddddddddddffddddddddddddddax", "xfaaddddddddddffddddddddddddddax", "xfaaddddddddddffddddddddddddddax", "xfafffffffffffffddddddddddddddax", "xfdffffffffffffdddddddddddddddax", "xfaaaaaaaaaaaaaaaaaaaaaaaaaaaaax", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/lock.xpm0000644000175000017500000000253615004135251017055 0ustar albrechtalbrecht/* XPM */ static const char * const lock_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "` c #000000", "a c #c08080", "b c #FFc0c0", "c c none", "d c #FFc0c0", "e c #804040", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccc`````````ccccc", "ccccccccccccccccc``dddddaa``cccc", "cccccccccccccccc``daaaaaaae``ccc", "cccccccccccccccc`dae`````dae`ccc", "cccccccccccccccc`de``ccc``de`ccc", "cccccccccccccccc`de`ccccc`de`ccc", "cccccccccccccccc`de`ccccc`de`ccc", "cccccccccccccccc`de`ccccc`de`ccc", "cccccccccccccc`````````````````c", "ccccccccccccc``dddddddddddddee``", "ccccccccccccc`ddaaaaaaaaaaaaaee`", "ccccccccccccc`daaaaaaaaaaaaaaae`", "ccccccccccccc`daaaaaa```aaaaaae`", "ccccccccccccc`daaaaa`````aaaaae`", "ccccccccccccc`daaaaa`````aaaaae`", "ccccccccccccc`daaaaaa```aaaaaae`", "ccccccccccccc`daaaaa`````aaaaae`", "ccccccccccccc`daaaaa`````aaaaae`", "ccccccccccccc`daaaae`````eaaaae`", "ccccccccccccc`ddaaae`````eaaaee`", "ccccccccccccc``ddaaaaaaaaaaaee``", "cccccccccccccc`````````````````c", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/fd_project.png0000644000175000017500000001544615004135251020230 0ustar albrechtalbrechtPNG  IHDR szzniCCPicc(uKP:tPAAQХH1m IPp]|  "nx-'_1um+WpbᐶXZ^h.'uמF#]wTQwuV v 2 x[W&WPJ2?+Δ]̀_25a=XCA,yԗt9B#EUL HIfF}ţfG(] i yLUtc!hzhف}y141UF@,J͍qaT0fffFnn۲!ƁGNNYZ](<< \xV`FЎBYYY1ZA><0'5`^~+zoxxX miiI_*3kO1X{LONNښ a0XeHŠ0JlLA`GE,nݜ'(ś-s$B96JRczz/G(/`Uɻk?t: 3uCnyb(WWWf~~~nBA...dvv  \A 5-,<\ c #C80000", ", c #0000C8", "' c #0000FF", ") c #00C8FF", "! c #C800FF", " ...... ", " .......... ", " ............ ", " .............. ", " .............. ", " ................ ", " ................ ", " ................ ", " +@@@@@@+#$$$$$$# ", " %@@@@@@@&&$$$$$$$* ", " %%@@@@@@&&&&$$$$$$** ", " %%%=@@@@&&&&&&$$$$-*** ", " %%%%@@@;&&&&&&>$$$**** ", "%%%%%%@@&&&&&&&&$$******", "%%%%%%%@&&&&&&&&$*******", "%%%%%%%%,&&&&&&,********", "%%%%%%%%''''''''********", "%%%%%%%%''''''''********", "%%%%%%%%''''''''********", " %%%%%%%)''''''!******* ", " %%%%%%%%''''''******** ", " %%%%%%%%''''******** ", " %%%%%%%%''******** ", " %%%%%% ****** "}; fltk-1.4.3/fluid/pixmaps/flLightButton.xpm0000644000175000017500000000256615004135251020715 0ustar albrechtalbrecht/* XPM */ static const char * const flLightButton_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "a c #808080", "b c #ffff00", "c c none", "d c #a0a0a0", "e c #8080ff", "f c #d0d0d0", "g c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccggggggggggggggggggggggggggccc", "ccgffffffffffffffffffffffffffgcc", "cgffddddddddddddddddddddddddfagc", "cgfddaaaaaaddddddddddddddddddagc", "cgfddabbbbfddddddddddddddddddagc", "cgfddabbbbfddddddddddddddddddagc", "cgfddabbbbfddddddddddddddddddagc", "cgfddabbbbfddddddddddddddddddagc", "cgfddabbbbfddddddddddddddddddagc", "cgfddabbbbfddddddddddddddddddagc", "cgfddabbbbfddddddddddddddddddagc", "cgfddabbbbfddddddddddddddddddagc", "cgfddffffffddddddddddddddddddagc", "cgffddddddddddddddddddddddddaagc", "ccgaaaaaaaaaaaaaaaaaaaaaaaaaagcc", "cccggggggggggggggggggggggggggccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flChoice.xpm0000644000175000017500000000256115004135251017637 0ustar albrechtalbrecht/* XPM */ static const char * const flChoice_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "a c #808080", "b c #2020ff", "c c none", "d c #a0a0a0", "e c #8080ff", "f c #d0d0d0", "g c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccggggggggggggggggggggggggggccc", "ccgffffffffffffgfffffffffffffgcc", "cgffdddddddddddgddddddgdddddfagc", "cgfddddddddddddgdddddgggdddddagc", "cgfddddddddddddgddddgggggddddagc", "cgfddddddddddddgdddgggggggdddagc", "cgfddddddddddddgddgggggggggddagc", "cgfddddddddddddgdddddddddddddagc", "cgfddddddddddddgdddddddddddddagc", "cgfddddddddddddgddgggggggggddagc", "cgfddddddddddddgdddgggggggdddagc", "cgfddddddddddddgddddgggggddddagc", "cgfddddddddddddgdddddgggdddddagc", "cgffdddddddddddgddddddgdddddaagc", "ccgaaaaaaaaaaaagaaaaaaaaaaaaagcc", "cccggggggggggggggggggggggggggccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flValueInput.xpm0000644000175000017500000000254615004135251020544 0ustar albrechtalbrecht/* XPM */ static const char * const flValueInput_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "f c #606060", ". c #000000", "c c none", "d c #ffffff", "e c #8080ff", "a c #d0d0d0", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "c..............................c", ".ffffffffffffffffffffffffffffff.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fddddd....ddddd....dddddddddda.", ".fdddd......dddd....dddddddddda.", ".fddd..ddd...ddd....dddddddddda.", ".fdd..ddd..d..dd....dddddddddda.", ".fdd..ddd..d..dd....dddddddddda.", ".fdd..dd..dd..dd....dddddddddda.", ".fdd..dd..dd..dd....dddddddddda.", ".fdd..d..ddd..dd....dddddddddda.", ".fdd..d..ddd..dd....dddddddddda.", ".fddd...ddd..ddd....dddddddddda.", ".fdddd......dddd....dddddddddda.", ".fddddd....ddddd....dddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.", "c..............................c", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flRoller.xpm0000644000175000017500000000267515004135251017712 0ustar albrechtalbrecht/* XPM */ static const char * const flRoller_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 12 1", /* colors */ "a c #606060", ". c #ffff00", "c c none", "d c #bbbbbb", "e c #8080ff", "f c #dddddd", "x c #000000", "1 c #555555", "2 c #777777", "3 c #aaaaaa", "4 c #cccccc", "5 c #eeeeee", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "x12334445555544444433333222211ax", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/fd_user.png0000644000175000017500000002064415004135251017534 0ustar albrechtalbrechtPNG  IHDR szzniCCPicc(uKP:tPAAQХH1m IPp]|  "nx-'_1um+WpbᐶXZ^h.'uמF#]wTQwuV v 2 x[W&WPJ2?+Δ]̀_25a=XCA,yԗt9B#EUL HIfF}ţfG(] i yLUtc!hzhف}y14d$B&AX.8 RNA<[9KRv >ah 4L2vQ|VUN=%hhbWg3qa)Oe JSD1 -#q@xhRhXO>]SqGMMMGNNޕ^)DDA4*Cӡәhb߾K0#F.+qtuDs2sg-# <Ze ia()Ln;~D2ods]ϒ7`̅(*N5蠐PSݏ 4X\{8\A/(Q+,8,oBƯ'{559 Ɛ0bDc70k#LøVpb&-#{zZ/?L*$݇ܯ˩t)$(H|ډNl[ P: 0Iۃvmz3fd*S%vU/" A&W*e̘9}xcQ"LȎiw;b{[Uh+}M5b'_UBG)S?*A(Y ul& xSsx۱ix~$4|d)|GKXƵ8ɓ8K2 Tް#d! \Jgw$!QoSOٻy(?c?[ZYnۄY|ĺgC}OTPa([Al""+e)(AhgU (pβeK|k17Jb(=fQNJ/ -i&٪Xb!KpOOv' ~*OE%eB< >fJ>LR2 &L`C.p Z]k~F%eIS]vt-lv~=#AO'ZWS]aCe?oʸ)))"K̋A2lSH#rO/߷@ee^ Z50~ ;dʤΛ?Öz$q^_C\rUBwvXER%^j8jG>3q[L&LKw:{8t K>Q'X G8bOܹ/<Q"uڀ2I X;׭-*=cxXLSDAi8;R_7p!vm+m/ ֛pMUy5-H:-LDP!!)˗~˖繬xKӧHF^$JȈ, 0)GjWՋ_|O}\2٬y|!˞QK~Vޙw}۷n=+{ UUPX]XDGINB q'⛣FcϮ]p:|kg8(t-}_l`ag۞W .cR)8c] ֈ_Mw)#Ո ƌ^װckx}ĚesGX!,a1>BI0V[ I6ϾI,4X- }sƴ,yG@>F9sB.V? T w-$Q(aÆ|o] {i;m*݌ŞmV^\vIv%x ;tuvuET#ё=tF];hXP jY(`OJ6 *'jNyߒ[tb*cOr)K0;r8拦¤+UL0LlLlJZFr{$q( ")]dqH,Le#>b"Cϱte$യ7pŞPVH_UaZYRhr0a]3hgwV=zlPCCrJ̀CSSޘv:^Y.l*_ôeW/#jĨb|zQ453, o&xRݰБpka aQ !Ig^rDv?a$R/uTJg qxrZpS|PiT{3i9AQtYl])kw@FIENDB`fltk-1.4.3/fluid/pixmaps/flDial.xpm0000644000175000017500000000263215004135251017315 0ustar albrechtalbrecht/* XPM */ static const char * const flDial_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 5 1", /* colors */ ". c none", "a c #000000", "b c #bbbbbb", "c c #000000", "' c #202080", /* pixels */ "................................", "................................", "................................", "............aaaaaaaa............", ".........aaaaaaaaaaaaaa.........", ".......aaaaaabbbbbbcccccc.......", "......aaabbbbbbbbbbbbbbccc......", ".....aaabbbbbbbbbbbbbbbbccc.....", "....aaabbbbbbbbbbbbbbbbbbccc....", "....aabbbaaaabbbbbbbbbbbbbcc....", "...aaabbaaaaaabbbbbbbbbbbbccc...", "...aabbaaabbaaabbbbbbbbbbbbcc...", "...aabbaabbbbaabbbbbbbbbbbbcc...", "..aaabbaabbbbaabbbbbbbbbbbbccc..", "..aabbbaaabbaaabbbbbbbbbbbbbcc..", "..aabbbbaaaaaabbbbbbbbbbbbbbcc..", "..aabbbbbaaaabbbbbbbbbbbbbbbcc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aabbbbbbbbbbbbbbbbbbbbbbbbcc..", "..aaabbbbbbbbbbbbbbbbbbbbbbccc..", "...aabbbbbbbbbbbbbbbbbbbbbbcc...", "...aabbbbbbbbbbbbbbbbbbbbbbcc...", "...aaabbbbbbbbbbbbbbbbbbbbccc...", "....aabbbbbbbbbbbbbbbbbbbbcc....", "....aaabbbbbbbbbbbbbbbbbbccc....", ".....aaabbbbbbbbbbbbbbbbccc.....", "......cccbbbbbbbbbbbbbcccc......", ".......cccccbbbbbbbbccccc.......", ".........cccccccccccccc.........", "............cccccccc............", "................................", "................................", "................................", }; fltk-1.4.3/fluid/pixmaps/flGroup.xpm0000644000175000017500000000254115004135251017537 0ustar albrechtalbrecht/* XPM */ static const char * const flGroup_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "a c #606060", "b c #2020ff", "c c none", "d c #dddddd", "e c #8080ff", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffddddddddddddddddddddddddddffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flSpinner.xpm0000644000175000017500000000256015004135251020062 0ustar albrechtalbrecht/* XPM */ static const char * const flSpinner_xpm[]={ /* width height ncolors chars_per_pixel */ "32 32 7 1", /* colors */ "f c #606060", ". c #ffffff", "c c none", "d c #bbbbbb", "e c #8080ff", "a c #dddddd", "x c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "xffffffffffffffffffffffffffffffx", "xf....................ffddddddax", "xf....................ffddxxddax", "xf.............xx.....ffdxxxxdax", "xf............xxx.....ffxxxxxxax", "xf...........xxxx.....ffxxxxxxax", "xf...........xxxx.....ffddddddax", "xf.............xx.....ffddddddax", "xf.............xx.....ffxxxxxxax", "xf...........xxxxxx...ffxxxxxxax", "xf...........xxxxxx...ffdxxxxdax", "xf....................ffddxxddax", "xf....................ffddddddax", "xfaaaaaaaaaaaaaaaaaaaaaaaaaaaaax", "cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flRadioMenuitem.xpm0000644000175000017500000000262615004135251021211 0ustar albrechtalbrecht/* XPM */ static const char * const flRadioMenuitem_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 9 1", /* colors */ "a c #808080", "b c #dd0000", "c c none", "d c #aaaaaa", "e c #bbbbbb", "f c #d0d0d0", "g c #000000", "' c #000000", "o c #ffff00", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ccccccdddddddccccccccccccccccccc", "ccccdddddddddddccccccccccccccccc", "cgfdddddddddddddccccccccccdagccc", "cgfdddddddddddddddccccccdddagccc", "cgfddddddddddddddddddddddddagccc", "cgfddddddddddddddddddddddddagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfeeeee''''eeeeeeeeeeeeeeeagccc", "cgfeee''''''''eeeeeeeeeeeeeagccc", "cgfee'''oooo'''eeeeeeeeeeeeagccc", "cgfee''oooooo''eeeeeeeeeeeeagccc", "cgfe'''oooooo'''eeeeeeeeeeeagccc", "cgfe''oooooooo''eeeeeeeeeeeagccc", "cgfe''oooooooo''eeeeeeeeeeeagccc", "cgfe'''oooooo'''eeeeeeeeeeeagccc", "cgfee''oooooo''eeeeeeeeeeeeagccc", "cgfee'''oooo'''eeeeeeeeeeeeagccc", "cgfeee''''''''eeeeeeeeeeeeeagccc", "cgfeeeee''''eeeeeeeeeeeeeeeagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfddddddddddddddddddddddddagccc", "cgfddddddddddddddddddddddddagccc", "cgfdddccccccdddddddddddddddagccc", "cgfdccccccccccdddddddddddddagccc", "ccccccccccccccccddddddddddcccccc", "ccccccccccccccccccddddddcccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/bind.xpm0000644000175000017500000000252215004135251017034 0ustar albrechtalbrecht/* cPM */ static const char * const bind_xpm[] = { /* width height ncolors chars_per_picel */ "32 32 6 1", /* colors */ "- c #000", "= c #444", "c c none", "d c #cccccc", ". c #666", ", c #888", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccc,,,,,,,,,,,,,,cccccc", "cccccccccc,,................cccc", "ccccccccc,...................ccc", "ccccccccc======..............ccc", "cccccccc------cccccccccc......cc", "cccccccc-----cccccccccccc.....cc", "cccccc,,,,,,,,,,,,,,cccccc....cc", "cccc,,................cccc,...cc", "ccc,...................ccc,...cc", "ccc,..............=====ccc,...cc", "cc,.....-----cccccc-----c,....cc", "cc,....c-----cccccc-----,.....cc", "cc,...ccc=====,,,,,,,,,,.....ccc", "cc,...ccc....................ccc", "cc,...cccc..................cccc", "cc,...cccccc..............cccccc", "cc,....cccccccccccc-----cccccccc", "cc,.....cccccccccc------cccccccc", "ccc.....,,,,,,,,=======ccccccccc", "ccc....................ccccccccc", "cccc..................cccccccccc", "cccccc..............cccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flRepeatButton.xpm0000644000175000017500000000260615004135251021061 0ustar albrechtalbrecht/* XPM */ static const char * const flRepeatButton_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 8 1", /* colors */ "' c #000000", "a c #808080", "b c #2020ff", "c c none", "d c #a0a0a0", "e c #8080ff", "f c #d0d0d0", "g c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccggggggggggggggggggggggggggccc", "ccgffffffffffffffffffffffffffgcc", "cgffddddddddddddddddddddddddfagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfddddddddddddddddddddddddddagc", "cgfdddddddddd''dddd''dddd''ddagc", "cgfddddddddd''''dd''''dd''''dagc", "cgfddddddddd''''dd''''dd''''dagc", "cgfdddddddddd''dddd''dddd''ddagc", "cgfddddddddddddddddddddddddddagc", "cgffddddddddddddddddddddddddaagc", "ccgaaaaaaaaaaaaaaaaaaaaaaaaaagcc", "cccggggggggggggggggggggggggggccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flCheckBrowser.xpm0000644000175000017500000000247515004135251021032 0ustar albrechtalbrecht/* XPM */ static const char * const flCheckBrowser_xpm[] = { "32 32 6 1", /* colors */ "a c #606060", "b c #888888", "c c none", "d c #ffffff", "e c #bbbbbb", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddddddddddddddddddddddaaeeffcc", "ffddffffffddddddddddddddaabbffcc", "ffddffffffddddddddddddddaabbffcc", "ffddffddffddddddddddddddaabbffcc", "ffddffddffddddddddddddddaabbffcc", "ffddffffffddddddddddddddaabbffcc", "ffddffffffddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddffffffddddddddddddddaabbffcc", "ffddffffffddddddddddddddaabbffcc", "ffddffddffddddddddddddddaabbffcc", "ffddffddffddddddddddddddaabbffcc", "ffddffffffddddddddddddddaabbffcc", "ffddffffffddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffddddddddddddddddddddddaabbffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffeebbbbbbbbbbeeeeeeeeeeaaeeffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flCodeBlock.xpm0000644000175000017500000000251015004135251020264 0ustar albrechtalbrecht/* XPM */ static const char * const flCodeBlock_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 4 1", /* colors */ ". c none", "a c #000000", "b c #c0e0c0", "c c #000000", /* pixels */ "...............aa...............", "..............aaaa..............", ".............aaaccc.............", "............aaabbccc............", "...........aaabbbbccc...........", "..........aaabbbbbbccc..........", ".........aaabbbbbbbbccc.........", "........aaabbbbbbbbbbccc........", ".......aaabbbbbbbbbbbbccc.......", "......aaabbbbbbbbbbbbbbccc......", ".....aaabbbbbbbbbbbbbbbbccc.....", "....aaabbbbbbbbbbbbbbbbbbccc....", "...aaabbbbbbbbbbbbbbbbbbbbccc...", "..aaabbbbbbbbbbbbbbbbbbbbbbccc..", ".aaabbbbbbbbbbbbbbbbbbbbbbbbccc.", "aaabbbbbbbbbbbbbbbbbbbbbbbbbbccc", "aaabbbbbbbbbbbbbbbbbbbbbbbbbbccc", ".aaabbbbbbbbbbbbbbbbbbbbbbbbccc.", "..aaabbbbbbbbbbbbbbbbbbbbbbccc..", "...aaabbbbbbbbbbbbbbbbbbbbccc...", "....aaabbbbbbbbbbbbbbbbbbccc....", ".....aaabbbbbbbbbbbbbbbbccc.....", "......aaabbbbbbbbbbbbbbccc......", ".......aaabbbbbbbbbbbbccc.......", "........aaabbbbbbbbbbccc........", ".........aaabbbbbbbbccc.........", "..........aaabbbbbbccc..........", "...........aaabbbbccc...........", "............aaabbccc............", ".............aaaccc.............", "..............aacc..............", "...............ac...............", }; fltk-1.4.3/fluid/pixmaps/flTextDisplay.xpm0000644000175000017500000000254715004135251020723 0ustar albrechtalbrecht/* XPM */ static const char * const flTextDisplay_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "f c #606060", ". c #000000", "c c none", "d c #cccccc", "e c #8080ff", "a c #888888", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "c..............................c", ".ffffffffffffffffffffffffffffff.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fddddd....ddddddddddddddddddda.", ".fdddd......dddddddddddddddddda.", ".fdddd..dd..dddddddddddddddddda.", ".fddd..dddd..ddddddddddddddddda.", ".fddd..dddd..ddddddddddddddddda.", ".fdd..dddddd..dddddddddddddddda.", ".fdd..........dddddddddddddddda.", ".fdd..........dddddddddddddddda.", ".fdd..dddddd..dddddddddddddddda.", ".fdd..dddddd..dddddddddddddddda.", ".fdd..dddddd..dddddddddddddddda.", ".fdd..dddddd..dddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".fdddddddddddddddddddddddddddda.", ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.", "c..............................c", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flMenuitem.xpm0000644000175000017500000000260215004135251020224 0ustar albrechtalbrecht/* XPM */ static const char * const flMenuitem_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 8 1", /* colors */ "a c #808080", "b c #2020ff", "c c none", "d c #aaaaaa", "e c #bbbbbb", "f c #d0d0d0", "g c #000000", "' c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ccccccdddddddccccccccccccccccccc", "ccccdddddddddddccccccccccccccccc", "cgfdddddddddddddccccccccccdagccc", "cgfdddddddddddddddccccccdddagccc", "cgfddddddddddddddddddddddddagccc", "cgfddddddddddddddddddddddddagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfeee'''eeee''eeeeeeeeeeeeagccc", "cgfee'''''eee''eeeeeeeeeeeeagccc", "cgfe'''e'''ee''eeeeeeeeeeeeagccc", "cgfe''eee''ee'''''eeee''''eagccc", "cgfe'''''''ee''''''ee'''''eagccc", "cgfe'''''''ee''ee''ee''eeeeagccc", "cgfe''eee''ee''ee''ee''eeeeagccc", "cgfe''eee''ee''ee''ee''eeeeagccc", "cgfe''eee''ee''''''ee'''''eagccc", "cgfe''eee''ee'''''eeee''''eagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfeeeeeeeeeeeeeeeeeeeeeeeeagccc", "cgfddddddddddddddddddddddddagccc", "cgfddddddddddddddddddddddddagccc", "cgfdddccccccdddddddddddddddagccc", "cgfdccccccccccdddddddddddddagccc", "ccccccccccccccccddddddddddcccccc", "ccccccccccccccccccddddddcccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/protected.xpm0000644000175000017500000000254315004135251020114 0ustar albrechtalbrecht/* XPM */ static const char * const protected_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "` c #000000", "a c #80c080", "b c #c0ffc0", "c c none", "d c #c0ffc0", "e c #408040", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccc`````````ccccc", "ccccccccccccccccc``dddddaa``cccc", "cccccccccccccccc``daaaaaaae``ccc", "cccccccccccccccc`dae`````dae`ccc", "cccccccccccccccc`de``ccc``de`ccc", "cccccccccccccccc`de`ccccc`de`ccc", "cccccccccccccccc`de`ccccc`de`ccc", "cccccccccccccccc`de`ccccc`de`ccc", "cccccccccccccc`````````````````c", "ccccccccccccc``dddddddddddddee``", "ccccccccccccc`ddaaaaaaaaaaaaaee`", "ccccccccccccc`daaaaaaaaaaaaaaae`", "ccccccccccccc`daaaaaa```aaaaaae`", "ccccccccccccc`daaaaa`````aaaaae`", "ccccccccccccc`daaaaa`````aaaaae`", "ccccccccccccc`daaaaaa```aaaaaae`", "ccccccccccccc`daaaaa`````aaaaae`", "ccccccccccccc`daaaaa`````aaaaae`", "ccccccccccccc`daaaae`````eaaaae`", "ccccccccccccc`ddaaae`````eaaaee`", "ccccccccccccc``ddaaaaaaaaaaaee``", "cccccccccccccc`````````````````c", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flScroll.xpm0000644000175000017500000000254215004135251017702 0ustar albrechtalbrecht/* XPM */ static const char * const flScroll_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 6 1", /* colors */ "a c #606060", "b c #999999", "c c none", "d c #dddddd", "e c #bbbbbb", "f c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "ffddddddddddddddddddddaaeeeeffcc", "ffddddddddddddddddddddaaeeeeffcc", "ffddddddddddddddddddddaaeeeeffcc", "ffddddddddddddddddddddaaeeeeffcc", "ffddddddddddddddddddddaabbbbffcc", "ffddddddddddddddddddddaabbbbffcc", "ffddddddddddddddddddddaabbbbffcc", "ffddddddddddddddddddddaabbbbffcc", "ffddddddddddddddddddddaabbbbffcc", "ffddddddddddddddddddddaabbbbffcc", "ffddddddddddddddddddddaaeeeeffcc", "ffddddddddddddddddddddaaeeeeffcc", "ffddddddddddddddddddddaaeeeeffcc", "ffddddddddddddddddddddaaeeeeffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffaaaaaaaaaaaaaaaaaaaaaaaaaaffcc", "ffeebbbbbbbbbbeeeeeeeeaaeeeeffcc", "ffeebbbbbbbbbbeeeeeeeeaaeeeeffcc", "ffeebbbbbbbbbbeeeeeeeeaaeeeeffcc", "ffeebbbbbbbbbbeeeeeeeeaaeeeeffcc", "ffffffffffffffffffffffffffffffcc", "ffffffffffffffffffffffffffffffcc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/pixmaps/flCheckButton.xpm0000644000175000017500000000260515004135251020655 0ustar albrechtalbrecht/* XPM */ static const char * const flCheckButton_xpm[] = { /* width height ncolors chars_per_pixel */ "32 32 8 1", /* colors */ "m c #111111", "a c #777777", "b c #2020ff", "c c none", "d c #ffffff", "f c #aaaaaa", "g c #222222", "' c #000000", /* pixels */ "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "ccccccccmmmmmmmmmmmmmmmmcccccccc", "cccccccmaaaaaaaaaaaaaaaagccccccc", "ccccccmaadddddddddddddddfgcccccc", "ccccccmaddddddddddddddddfgcccccc", "ccccccmadddddddddddd'''dfgcccccc", "ccccccmadddddddddddd'''dfgcccccc", "ccccccmaddddddddddd'''ddfgcccccc", "ccccccmaddddddddddd'''ddfgcccccc", "ccccccmadddddddddd'''dddfgcccccc", "ccccccmadddddddddd'''dddfgcccccc", "ccccccmad'''ddddd'''ddddfgcccccc", "ccccccmadd'''dddd'''ddddfgcccccc", "ccccccmaddd'''dd'''dddddfgcccccc", "ccccccmadddd'''d'''dddddfgcccccc", "ccccccmaddddd'''''ddddddfgcccccc", "ccccccmadddddd''''ddddddfgcccccc", "ccccccmaddddddd''dddddddfgcccccc", "ccccccmadddddddddddddddffgcccccc", "cccccccmafffffffffffffffgccccccc", "ccccccccmgggggggggggggggcccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc", "cccccccccccccccccccccccccccccccc" }; fltk-1.4.3/fluid/autodoc.h0000644000175000017500000000325715004135251015526 0ustar albrechtalbrecht// // Widget snapshot header-only file for the Fast Light Tool Kit (FLTK). // // Copyright 2023-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file autodoc.h \brief tools to take snapshots of UI elements for documentation purposes */ #ifndef fl_screenshot_H #define fl_screenshot_H #include "../src/Fl_String.H" #include #include #include /** Class to initialize a Rect by providing the margin around a rect. */ class Fl_Margin : public Fl_Rect { public: Fl_Margin(int dx, int dy, int dr, int db); }; int fl_snapshot(const char *filename, Fl_Widget **w, const Fl_Rect &frame = Fl_Margin(4, 4, 4, 4), const Fl_Rect &blend = Fl_Margin(4, 4, 4, 4), double scale=1.0); int fl_snapshot(const char *filename, Fl_Widget *w1, Fl_Widget *w2, const Fl_Rect &frame = Fl_Margin(4, 4, 4, 4), const Fl_Rect &blend = Fl_Margin(4, 4, 4, 4), double scale=1.0); int fl_snapshot(const char *filename, Fl_Widget *w, const Fl_Rect &frame = Fl_Margin(4, 4, 4, 4), const Fl_Rect &blend = Fl_Margin(4, 4, 4, 4), double scale=1.0); extern const int FL_SNAP_TO_WINDOW; extern Fl_Widget *FL_SNAP_AREA_CLEAR; extern void run_autodoc(const Fl_String &target_dir); #endif fltk-1.4.3/fluid/about_panel.fl0000644000175000017500000000443315004135251016530 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} comment {// // About dialog for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // } {in_source in_header } decl {\#include } {public global } decl {void show_help(const char *name);} {public local } Function {make_about_panel()} {open } { code {static char cbuf[200] = ""; if (!cbuf[0]) { time_t t = time(0); struct tm *lt = localtime(&t); sprintf(cbuf, "Copyright © 1998 - %d\\nby Bill Spitzak and others", lt->tm_year+1900); }} {} Fl_Window about_panel { label {About FLUID} open xywh {449 217 345 180} type Double color 50 selection_color 47 hotspot code0 {\#include "../src/flstring.h"} non_modal visible } { Fl_Box {} { image {icons/fluid.animated.gif} compress_image 1 xywh {10 10 115 120} code0 {((Fl_Anim_GIF_Image*)(o->image()))->speed(0.5f);} } Fl_Box {} { label {FLTK User Interface Designer Version x.x.x} xywh {135 10 205 75} color 12 selection_color 47 labelfont 1 labelsize 18 align 21 code0 {char about[80]; // uses less than 60} code1 {snprintf(about,sizeof(about),"FLTK User\\nInterface Designer\\nVersion %d.%d.%d",FL_MAJOR_VERSION,FL_MINOR_VERSION,FL_PATCH_VERSION);} code2 {o->copy_label(about);} } Fl_Box {} { label {(Copyright)} comment {Label edited dynamically:} xywh {135 90 200 45} align 148 code0 {o->label(cbuf);} } Fl_Button {} { label {View License...} callback {show_help("license.html");} xywh {115 145 123 25} labelcolor 136 } Fl_Return_Button {} { label Close callback {((Fl_Window*)(o->parent()))->hide();} xywh {250 145 83 25} } } } data fluid_flow_chart_800_png { comment {Embedded image for internal fluid.html web page.} selected public local filename {documentation/src/fluid_flow_chart_800.png} } fltk-1.4.3/fluid/autodoc.cxx0000644000175000017500000005602415004135251016101 0ustar albrechtalbrecht// // Self-generate snapshots of user interface for FLUID documentation. // // Copyright 2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef NDEBUG #include "autodoc.h" #include "fluid.h" #include "factory.h" #include "widget_browser.h" #include "widget_panel.h" #include "Fl_Widget_Type.h" #include "Fl_Window_Type.h" #include "function_panel.h" #include "settings_panel.h" #include "codeview_panel.h" #include #include #include #include #include extern Fl_Double_Window *settings_window; /** \file autodoc.cxx \todo Implement a function to snapshot a window including decoration - see: void Fl_Widget_Surface::draw_decorated_window(Fl_Window *win, int win_offset_x, int win_offset_y) - see: void Fl_Widget_Surface::origin(int x, int y) - see: void Fl_Widget_Surface::draw(Fl_Widget* widget, int delta_x, int delta_y) - see: void Fl_Widget_Surface::print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x, int delta_y) \todo Implement a version that snaps multiple windows in a desktop style situation. \todo a version that takes snapshots of a range of menu items \todo implement FL_SNAP_TO_GROUP, possibly with a number on how many groups up in the hierarchy */ /** \addtogroup fl_drawings @{ */ const int FL_SNAP_TO_WINDOW = 0x01000000; static Fl_Box snap_clear_(0, 0, 0, 0); Fl_Widget *FL_SNAP_AREA_CLEAR = &snap_clear_; static inline int fl_min(int a, int b) { return a < b ? a : b; } static inline uchar fl_min(uchar a, uchar b) { return a < b ? a : b; } static inline int fl_max(int a, int b) { return a > b ? a : b; } /** Create a rect by providing a margin around a zero size rectangle. \param[in] dx, dy positive integers, move margin up and left \param[in] dr, db move margin to the right and down */ Fl_Margin::Fl_Margin(int dx, int dy, int dr, int db) : Fl_Rect(-dx, -dy, dx+dr, dy+db) { } /** Convert an RGB image into an RGBA image. \param[inout] image pointer to an RGB image, deletes the RGB image, returns the RGBA image \return 0 if the image is now in RGBA format, or -1 if it can't be converted */ static int convert_RGB_to_RGBA(Fl_RGB_Image *&img) { if (img->d() == 4) return 0; if (img->d() != 3) return -1; // Copy pixel data from RGB to RGBA raw data int img_w = img->w(); int img_h = img->h(); uchar *data = new uchar[img_w * img_h * 4], *dst = data; int ld = img->ld(); if (ld == 0) ld = img_w * 3; int i, j; for (i=0; idata()[0] + i * ld; for (j=0; jalloc_array = 1; return 0; } /** Blend the left side lines of the alpha channel of an RBGA image to full transparency. \param[in] img must be an RGBA image \param[in] dx number of lines to blend */ void blend_alpha_left(const Fl_RGB_Image *img, int dx) { if (img->d() != 4) return; if (dx > img->w()) return; if (dx > 0) { int max_x = dx, max_y = img->h(); int ld = img->ld(); if (ld == 0) ld = img->w() * img->d(); float a = 255.0f/static_cast(max_x); for (int i = 0; i < max_x; i++) { uchar *rgba = (uchar*)img->data()[0] + i * img->d(); uchar alpha = static_cast(i * a); for (int j = 0; j < max_y; j++) { rgba[3] = fl_min(alpha, rgba[3]); rgba += ld; } } } } /** Blend the top lines of the alpha channel of an RBGA image to full transparency. \param[in] img must be an RGBA image \param[in] dy number of lines to blend */ void blend_alpha_top(const Fl_RGB_Image *img, int dy) { if (img->d() != 4) return; if (dy > img->h()) return; if (dy > 0) { int max_x = img->w(), max_y = dy; int ld = img->ld(); if (ld == 0) ld = img->w() * img->d(); float a = 255.0f/static_cast(max_y); for (int i = 0; i < max_y; i++) { uchar *rgba = (uchar*)img->data()[0] + i * ld; uchar alpha = static_cast(i * a); for (int j = 0; j < max_x; j++) { rgba[3] = fl_min(alpha, rgba[3]); rgba += 4; } } } } /** Blend the right side lines of the alpha channel of an RBGA image to full transparency. \param[in] img must be an RGBA image \param[in] dx number of lines to blend */ void blend_alpha_right(const Fl_RGB_Image *img, int dx) { if (img->d() != 4) return; if (dx > img->w()) return; if (dx > 0) { int max_x = dx, max_y = img->h(); int ld = img->ld(); if (ld == 0) ld = img->w() * img->d(); float a = 255.0f/static_cast(max_x); for (int i = 0; i < max_x; i++) { uchar *rgba = (uchar*)img->data()[0] + (img->w()-i-1) * img->d(); uchar alpha = static_cast(i * a); for (int j = 0; j < max_y; j++) { rgba[3] = fl_min(alpha, rgba[3]); rgba += ld; } } } } /** Blend the bottom lines of the alpha channel of an RBGA image to full transparency. \param[in] img must be an RGBA image \param[in] dy number of lines to blend */ void blend_alpha_bottom(const Fl_RGB_Image *img, int dy) { if (img->d() != 4) return; if (dy > img->h()) return; if (dy > 0) { int max_x = img->w(), max_y = dy; int ld = img->ld(); if (ld == 0) ld = img->w() * img->d(); float a = 255.0f/static_cast(max_y); for (int i = 0; i < max_y; i++) { uchar *rgba = (uchar*)img->data()[0] + (img->h()-i-1) * ld; uchar alpha = static_cast(i * a); for (int j = 0; j < max_x; j++) { rgba[3] = fl_min(alpha, rgba[3]); rgba += 4; } } } } /** Take a snapshot of a number of widgets and save it as a png image. Draw a rectangular snapshot that fits around all widgets inside a window. All widgets must be inside the same window. It's up to the caller to ensure that widgets are visible. This includes children of `Fl_Tabs`. Outside labels of widgets are not taken into account, but a `frame` can be provided to grow the snapshot rectangle. Setting individual parameters of the frame to `FL_SNAP_TO_WINDOW` will extend the snapshot to the borders of the top level window. Another `blend` frame can be added around the image that fades to full transparency on selected sides. Use `Fl_Margin` to create `frame` and `blend` using positive integers to grow the rectangle to the left, top, right, and bottom. The image can be scaled after all processing. Note that snapshot is always created in FLTK resolution, even if the screen uses a higher resolution. \param[in] filename the snapshot will be written to this file in png format \param[in] w draw a bounding box around all widgets in the NULL terminated list \param[in] frame add a margin around the bounding box \param[in] blend add another margin around the bounding box that fades to full transparency \param[in] scale scale everything by this factor before saving it \return the result of fl_write_png or -3 if another error occurred */ int fl_snapshot(const char *filename, Fl_Widget **w, const Fl_Rect &frame, const Fl_Rect &blend, double scale) { int i, min_x = 0, min_y = 0, max_x = 0, max_y = 0, bb_w, bb_h, img_w, img_h; // Get the bounding box for all widgets and make sure that all widgets are shown for (i=0; w[i]; i++) { int x, y; Fl_Widget *ww = w[i]; if (ww == FL_SNAP_AREA_CLEAR) { min_x = max_x = 0; min_y = max_y = 0; } else { ww->top_window_offset(x, y); if (i==0) { min_x = x; max_x = x + ww->w(); min_y = y; max_y = y + ww->h(); } else { min_x = fl_min(min_x, x); max_x = fl_max(max_x, x + ww->w()); min_y = fl_min(min_y, y); max_y = fl_max(max_y, y + ww->h()); } } // this does not help us with Fl_Tab groups while (ww) { ww->show(); ww = ww->parent(); } } // Check for special values in frame and adjust bounding box Fl_Rect c_frame = frame; if (frame.x() == -FL_SNAP_TO_WINDOW) c_frame.x(-min_x); if (frame.y() == -FL_SNAP_TO_WINDOW) c_frame.y(-min_y); if (frame.r() == FL_SNAP_TO_WINDOW) c_frame.r(w[0]->top_window()->w()-max_x); if (frame.b() == FL_SNAP_TO_WINDOW) c_frame.b(w[0]->top_window()->h()-max_y); min_x += c_frame.x(); max_x += c_frame.r(); min_y += c_frame.y(); max_y += c_frame.b(); bb_w = max_x - min_x; bb_h = max_y - min_y; img_w = bb_w + blend.w(); img_h = bb_h + blend.h(); // Generate the Image Surface Fl_Image_Surface *srfc = new Fl_Image_Surface(img_w, img_h); Fl_Image_Surface::push_current(srfc); // Draw the background fl_rectf(0, 0, img_w, img_h, 0x1395bf00); // Draw the top level window srfc->draw(w[0]->top_window(), -blend.x()-min_x, -blend.y()-min_y); Fl_Image_Surface::pop_current(); Fl_RGB_Image *img = srfc->image(); // Do we want an alpha blended extension of the frame? if ((blend.x()<0 || blend.y()<0 || blend.r()>0 || blend.b()>0)) { if (convert_RGB_to_RGBA(img) == -1) { delete img; delete srfc; return -3; } if (blend.x() < 0) blend_alpha_left(img, -blend.x()); if (blend.y() < 0) blend_alpha_top(img, -blend.y()); if (blend.r() > 0) blend_alpha_right(img, blend.r()); if (blend.b() > 0) blend_alpha_bottom(img, blend.b()); } // If scale is set, scale the image if (scale != 1.0) { Fl_Image::scaling_algorithm(FL_RGB_SCALING_BILINEAR); int scaled_img_w = static_cast(img->w()*scale); int scaled_img_h = static_cast(img->h()*scale); Fl_RGB_Image *scaled_img = static_cast(img->copy(scaled_img_w, scaled_img_h)); delete img; img = scaled_img; } // Write the image to disk int ret = fl_write_png(filename, img); // Clean up delete img; delete srfc; return ret; } /** Take a snapshot of the size of the bounding box around two widgets and save it as a png image. \param[in] filename the snapshot will be written to this file in png format \param[in] w1, w2 top left and bottom right widget \param[in] frame add a margin around the bounding box \param[in] blend add another margin around the bounding box that fades to full transparency \param[in] scale scale everything by this factor before saving it \return the result of fl_write_png or -3 if another error occurred \see fl_snapshot(const char*, Fl_Widget**, const Fl_Rect&, const Fl_Rect&, double) */ int fl_snapshot(const char *filename, Fl_Widget *w1, Fl_Widget *w2, const Fl_Rect &frame, const Fl_Rect &blend, double scale) { Fl_Widget *ww[3] = { w1, w2, NULL }; return fl_snapshot(filename, ww, frame, blend, scale); } /** Take a snapshot of a widget inside its window and save it as a png image. \param[in] filename the snapshot will be written to this file in png format \param[in] w snap this window, can also be a groups \param[in] frame add a margin around the bounding box \param[in] blend add another margin around the bounding box that fades to full transparency \param[in] scale scale everything by this factor before saving it \return the result of fl_write_png or -3 if another error occurred \see fl_snapshot(const char*, Fl_Widget**, const Fl_Rect&, const Fl_Rect&, double) */ int fl_snapshot(const char *filename, Fl_Widget *w, const Fl_Rect &frame, const Fl_Rect &blend, double scale) { Fl_Widget *ww[2] = { w, NULL }; return fl_snapshot(filename, ww, frame, blend, scale); } /** @} */ void run_autodoc(const Fl_String &target_dir) { // A list of all the margins we will use later Fl_Margin win_margin(0, 0, 0, 0); Fl_Margin win_blend(10, 10, 10, 10); Fl_Margin tab_margin(FL_SNAP_TO_WINDOW, 32, FL_SNAP_TO_WINDOW, 4); Fl_Margin xtab_margin(FL_SNAP_TO_WINDOW, 50, FL_SNAP_TO_WINDOW, 4); Fl_Margin row_margin(FL_SNAP_TO_WINDOW, 4, FL_SNAP_TO_WINDOW, 4); Fl_Margin xrow_margin(FL_SNAP_TO_WINDOW, 14, FL_SNAP_TO_WINDOW, 4); Fl_Margin row_blend(0, 10, 0, 10); // Fl::scheme("gtk+"); // Create a silly project that contains all widgets that we want to document new_project(false); /*Fl_Type *t_func = */ add_new_widget_from_user("Function", Strategy::AS_LAST_CHILD, false); Fl_Window_Type *t_win = (Fl_Window_Type*)add_new_widget_from_user("Fl_Window", Strategy::AS_LAST_CHILD, false); t_win->label("My Main Window"); Fl_Widget_Type *t_grp = (Fl_Widget_Type*)add_new_widget_from_user("Fl_Group", Strategy::AS_LAST_CHILD, false); t_grp->public_ = 0; Fl_Widget_Type *t_btn = (Fl_Widget_Type*)add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false); t_btn->comment("Don't press this button!"); t_btn->name("emergency_btn"); ((Fl_Button*)t_btn->o)->shortcut(FL_COMMAND|'g'); Fl_Type *t_sldr = add_new_widget_from_user("Fl_Slider", Strategy::AS_LAST_CHILD, false); Fl_Type *t_inp = add_new_widget_from_user("Fl_Input", Strategy::AS_LAST_CHILD, false); Fl_Type *t_flx = add_new_widget_from_user("Fl_Flex", Strategy::AS_LAST_CHILD, false); Fl_Type *t_flxc = add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false); select_only(t_grp); Fl_Type *t_grd = add_new_widget_from_user("Fl_Grid", Strategy::AS_LAST_CHILD, false); Fl_Type *t_grdc = add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false); widget_browser->rebuild(); g_project.update_settings_dialog(); // TODO: FLUID overview // TODO: explain FLUID command line usage // TODO: take a snapshot of FLUID in a desktop situation // (main, toolbar, document, widget editor, code view) // ---- main window // explain titlebar // explain menubar? // explain widget browser // explain widget browser entry main_window->size(350, 320); fl_snapshot((target_dir + "main_window.png").c_str(), main_window, win_margin, win_blend); fl_snapshot((target_dir + "main_menubar.png").c_str(), main_menubar, row_margin, row_blend); fl_snapshot((target_dir + "main_browser.png").c_str(), widget_browser, FL_SNAP_AREA_CLEAR, Fl_Rect(0, 30, FL_SNAP_TO_WINDOW, 100), row_blend, 2.0); // TODO: document view // explain dnd // explain selection, multiple selection, keyboard shortcuts // explain mouse functionality and alignment // explain live resize // arrow: move by 1 // shift: resize by one // Meta: move by Widget Gap // Shift Meta: resize by Widget Increment // ---- widget bin // show grouping // explain non-widget types and where they will be located // explain widgets types an their dnd option // explain menu arrays // list exceptions (subwindow, scroll) Fl::wait(0.2); Fl::flush(); fl_snapshot((target_dir + "widgetbin_panel.png").c_str(), widgetbin_panel, win_margin, win_blend); // ---- code view // explain functionality // explain live update and choices // show various tabs // explain find and locate if (!codeview_panel) make_codeview(); codeview_panel->show(); Fl::wait(0.2); Fl::flush(); update_codeview_cb(NULL, NULL); // must be visible on screen for this to work cv_tab->value(cv_source_tab); codeview_panel->redraw(); Fl::flush(); fl_snapshot((target_dir + "codeview_panel.png").c_str(), codeview_panel, win_margin, win_blend); fl_snapshot((target_dir + "cv_find_row.png").c_str(), cv_find_row, row_margin, row_blend); fl_snapshot((target_dir + "cv_settings_row.png").c_str(), cv_settings_row, row_margin, row_blend); // ---- settings dialog // show and explain all tabs fl_snapshot((target_dir + "w_settings.png").c_str(), settings_window, win_margin, win_blend); fl_snapshot((target_dir + "w_settings_general_tab.png").c_str(), w_settings_general_tab, xtab_margin, row_blend); w_settings_tabs->value(w_settings_project_tab); fl_snapshot((target_dir + "w_settings_project_tab.png").c_str(), w_settings_project_tab, xtab_margin, row_blend); w_settings_tabs->value(w_settings_layout_tab); fl_snapshot((target_dir + "w_settings_layout_tab.png").c_str(), w_settings_layout_tab, xtab_margin, row_blend); w_settings_tabs->value(w_settings_shell_tab); w_settings_shell_list->value(1); w_settings_shell_list->do_callback(); fl_snapshot((target_dir + "w_settings_shell_tab.png").c_str(), w_settings_shell_tab, xtab_margin, row_blend); w_settings_tabs->value(w_settings_i18n_tab); i18n_type_chooser->value(1); i18n_type_chooser->do_callback(); fl_snapshot((target_dir + "w_settings_i18n_gnu.png").c_str(), i18n_type_chooser, i18n_gnu_static_function_input, row_margin, row_blend); i18n_type_chooser->value(2); i18n_type_chooser->do_callback(); fl_snapshot((target_dir + "w_settings_i18n_psx.png").c_str(), i18n_type_chooser, i18n_pos_set_input, row_margin, row_blend); w_settings_tabs->value(w_settings_user_tab); fl_snapshot((target_dir + "w_settings_user_tab.png").c_str(), w_settings_user_tab, xtab_margin, row_blend); // ---- dialog types // list and show all non-widget types and their respective dialog boxes // -- ID_Function Fl_Window *adoc_function_panel = make_function_panel(); f_name_input->value("count_trees(const char *forest_name)"); f_return_type_input->value("unsigned int"); fl_snapshot((target_dir + "function_panel.png").c_str(), adoc_function_panel, win_margin, win_blend); adoc_function_panel->hide(); // -- ID_Code Fl_Window *adoc_code_panel = make_code_panel(); code_input->buffer()->text("// increment user count\nif (new_user) {\n user_count++;\n}\n"); fl_snapshot((target_dir + "code_panel.png").c_str(), adoc_code_panel, win_margin, win_blend); adoc_code_panel->hide(); // -- ID_CodeBlock Fl_Window *adoc_codeblock_panel = make_codeblock_panel(); code_before_input->value("if (test())"); code_after_input->value("// test widgets added..."); fl_snapshot((target_dir + "codeblock_panel.png").c_str(), adoc_codeblock_panel, win_margin, win_blend); adoc_codeblock_panel->hide(); // -- ID_Decl Fl_Window *adoc_decl_panel = make_decl_panel(); decl_class_choice->hide(); decl_input->buffer()->text("const char *damage = \"'tis but a scratch\";"); fl_snapshot((target_dir + "decl_panel.png").c_str(), adoc_decl_panel, win_margin, win_blend); adoc_decl_panel->hide(); // -- ID_DeclBlock Fl_Window *adoc_declblock_panel = make_declblock_panel(); declblock_before_input->value("#ifdef NDEBUG"); declblock_after_input->value("#endif // NDEBUG"); fl_snapshot((target_dir + "declblock_panel.png").c_str(), adoc_declblock_panel, win_margin, win_blend); adoc_declblock_panel->hide(); // -- ID_Class Fl_Window *adoc_class_panel = make_class_panel(); decl_class_choice->hide(); c_name_input->value("Zoo_Giraffe"); c_subclass_input->value("Zoo_Animal"); fl_snapshot((target_dir + "class_panel.png").c_str(), adoc_class_panel, win_margin, win_blend); adoc_class_panel->hide(); // -- ID_Widget_Class is handled like Fl_Window_Type // -- ID_Comment Fl_Window *adoc_comment_panel = make_comment_panel(); comment_input->buffer()->text("Make sure that the giraffe gets enough hay,\nbut the monkey can't reach it."); fl_snapshot((target_dir + "comment_panel.png").c_str(), adoc_comment_panel, win_margin, win_blend); adoc_comment_panel->hide(); // -- ID_Data Fl_Window *adoc_data_panel = make_data_panel(); data_class_choice->hide(); data_input->value("emulated_ROM"); data_filename->value("./ROM.bin"); fl_snapshot((target_dir + "data_panel.png").c_str(), adoc_data_panel, win_margin, win_blend); adoc_data_panel->hide(); // ---- widget dialog t_win->open(); // open the window t_win->open(); // open the panel select_only(t_win); // -- snapshot of the widget properties panel fl_snapshot((target_dir + "widget_panel.png").c_str(), the_panel, win_margin, win_blend); fl_snapshot((target_dir + "wLiveMode.png").c_str(), wLiveMode, row_margin, row_blend); // -- snapshot of the GUI tab widget_tabs->value(wp_gui_tab); fl_snapshot((target_dir + "wp_gui_tab.png").c_str(), wp_gui_tab, tab_margin, row_blend); fl_snapshot((target_dir + "wp_gui_label.png").c_str(), wp_gui_label, row_margin, row_blend); select_only(t_btn); fl_snapshot((target_dir + "wp_gui_image.png").c_str(), widget_image_input, widget_deimage_input, row_margin, row_blend); fl_snapshot((target_dir + "wp_gui_alignment.png").c_str(), wp_gui_alignment, row_margin, row_blend); fl_snapshot((target_dir + "wp_gui_size.png").c_str(), widget_x_input, xrow_margin, row_blend); select_only(t_sldr); fl_snapshot((target_dir + "wp_gui_values.png").c_str(), wp_gui_values, xrow_margin, row_blend); select_only(t_flxc); fl_snapshot((target_dir + "wp_gui_flexp.png").c_str(), wp_gui_flexp, xrow_margin, row_blend); select_only(t_flx); fl_snapshot((target_dir + "wp_gui_margins.png").c_str(), wp_gui_margins, xrow_margin, row_blend); select_only(t_win); fl_snapshot((target_dir + "wp_gui_sizerange.png").c_str(), wp_gui_sizerange, xrow_margin, row_blend); select_only(t_btn); fl_snapshot((target_dir + "wp_gui_shortcut.png").c_str(), wp_gui_shortcut, row_margin, row_blend); select_only(t_win); fl_snapshot((target_dir + "wp_gui_xclass.png").c_str(), wp_gui_xclass, row_margin, row_blend); select_only(t_btn); fl_snapshot((target_dir + "wp_gui_attributes.png").c_str(), wp_gui_attributes, row_margin, row_blend); fl_snapshot((target_dir + "wp_gui_tooltip.png").c_str(), wp_gui_tooltip, row_margin, row_blend); // -- snapshot of the style tab widget_tabs->value(wp_style_tab); select_only(t_inp); fl_snapshot((target_dir + "wp_style_tab.png").c_str(), wp_style_tab, tab_margin, row_blend); fl_snapshot((target_dir + "wp_style_label.png").c_str(), wp_style_label, row_margin, row_blend); select_only(t_btn); fl_snapshot((target_dir + "wp_style_box.png").c_str(), wp_style_box, wp_style_downbox, row_margin, row_blend); select_only(t_inp); fl_snapshot((target_dir + "wp_style_text.png").c_str(), wp_style_text, row_margin, row_blend); // -- snapshot of the C++ tab widget_tabs->value(wp_cpp_tab); select_only(t_btn); fl_snapshot((target_dir + "wp_cpp_tab.png").c_str(), wp_cpp_tab, tab_margin, row_blend); fl_snapshot((target_dir + "wp_cpp_class.png").c_str(), wp_cpp_class, row_margin, row_blend); fl_snapshot((target_dir + "wp_cpp_name.png").c_str(), wp_cpp_name, row_margin, row_blend); fl_snapshot((target_dir + "v_input.png").c_str(), v_input[0], v_input[3], row_margin, row_blend); fl_snapshot((target_dir + "wComment.png").c_str(), wComment, row_margin, row_blend); fl_snapshot((target_dir + "wp_cpp_callback.png").c_str(), wCallback, w_when_box, row_margin, row_blend); // -- snapshot of the Grid tab select_only(t_grd); widget_tabs->value(widget_tab_grid); fl_snapshot((target_dir + "wp_grid_tab.png").c_str(), widget_tab_grid, tab_margin, row_blend); // -- snapshot of the Grid Child tab select_only(t_grdc); widget_tabs->value(widget_tab_grid_child); fl_snapshot((target_dir + "wp_gridc_tab.png").c_str(), widget_tab_grid_child, tab_margin, row_blend); } #endif // NDEBUG fltk-1.4.3/fluid/undo.h0000644000175000017500000000255315004135251015033 0ustar albrechtalbrecht// // FLUID undo definitions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef undo_h #define undo_h class Fl_Widget; #define kUndoWindowResize 1 extern int undo_current; // Current undo level in buffer extern int undo_last; // Last undo level in buffer extern int undo_save; // Last undo level that was saved extern int undo_once_type; // Suspend further undos of the same type void redo_cb(Fl_Widget *, void *); // Redo menu callback void undo_cb(Fl_Widget *, void *); // Undo menu callback void undo_checkpoint(); // Save current file to undo buffer int undo_checkpoint_once(int type); // Save undo buffer once until a different checkpoint type is called void undo_clear(); // Clear undo buffer void undo_resume(); // Resume undo checkpoints void undo_suspend(); // Suspend undo checkpoints #endif // !undo_h fltk-1.4.3/fluid/print_panel.h0000644000175000017500000000340715004135251016400 0ustar albrechtalbrecht// // FLUID print panel for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #ifndef print_panel_h #define print_panel_h #include #include extern Fl_Double_Window *print_panel; #include extern Fl_Group *print_panel_controls; #include extern Fl_Choice *print_choice; #include extern Fl_Button *print_properties; #include extern Fl_Box *print_status; #include extern Fl_Round_Button *print_all; extern Fl_Round_Button *print_pages; extern Fl_Round_Button *print_selection; #include extern Fl_Int_Input *print_from; extern Fl_Int_Input *print_to; #include extern Fl_Spinner *print_copies; #include extern Fl_Check_Button *print_collate_button; extern Fl_Group *print_collate_group[2]; #include extern void print_cb(Fl_Return_Button*, void*); #include extern Fl_Progress *print_progress; extern Fl_Double_Window *print_properties_panel; extern Fl_Choice *print_page_size; extern Fl_Button *print_output_mode[4]; Fl_Double_Window* make_print_panel(); extern Fl_Menu_Item menu_print_page_size[]; extern void print_cb(Fl_Return_Button *, void *); void print_load(); void print_update_status(); #endif fltk-1.4.3/fluid/codeview_panel.cxx0000644000175000017500000004733215004135251017431 0ustar albrechtalbrecht// // Code dialogs for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #include "codeview_panel.h" #include "fluid.h" #include "file.h" #include "../src/flstring.h" #include #include static char *cv_source_filename = NULL; static char *cv_header_filename = NULL; static char *cv_design_filename = NULL; int cv_code_choice; extern void select_only(Fl_Type *o); extern void reveal_in_browser(Fl_Type *t); /** Update the header and source code highlighting depending on the currently selected object The Code View system offers an immediate preview of the code files that will be generated by FLUID. It also marks the code generated for the last selected item in the header and the source file. */ void update_codeview_position() { if (!codeview_panel || !codeview_panel->visible()) return; if (cv_autoposition->value()==0) return; if (codeview_panel && codeview_panel->visible() && Fl_Type::current) { int pos0 = 0, pos1 = 0; if (cv_source->visible_r()) { switch (cv_code_choice) { case 0: // prolog: not yet (include statements) pos0 = Fl_Type::current->code1_start; pos1 = Fl_Type::current->code2_end; break; case 1: // static: callbacks, menu declarations pos0 = Fl_Type::current->code_static_start; pos1 = Fl_Type::current->code_static_end; break; case 2: // code: entire implementation block including children pos0 = Fl_Type::current->code1_start; pos1 = Fl_Type::current->code2_end; break; case 3: // code1: all implementation code before the children pos0 = Fl_Type::current->code1_start; pos1 = Fl_Type::current->code1_end; break; case 4: // code1: all implementation code before the children pos0 = Fl_Type::current->code2_start; pos1 = Fl_Type::current->code2_end; break; } if (pos0>=0) { if (pos1buffer()->line_end(pos0); cv_source->buffer()->highlight(pos0, pos1); int line = cv_source->buffer()->count_lines(0, pos0); cv_source->scroll(line, 0); } } if (cv_header->visible_r()) { switch (cv_code_choice) { case 0: // prolog: not yet (include statements) case 1: // static: callbacks, menu declarations pos0 = Fl_Type::current->header_static_start; pos1 = Fl_Type::current->header_static_end; break; case 2: // code: entire implementation block including children pos0 = Fl_Type::current->header1_start; pos1 = Fl_Type::current->header2_end; break; case 3: // code1: all implementation code before the children pos0 = Fl_Type::current->header1_start; pos1 = Fl_Type::current->header1_end; break; case 4: // code1: all implementation code before the children pos0 = Fl_Type::current->header2_start; pos1 = Fl_Type::current->header2_end; break; } if (pos0>=0) { if (pos1buffer()->line_end(pos0); cv_header->buffer()->highlight(pos0, pos1); int line = cv_header->buffer()->count_lines(0, pos0); cv_header->scroll(line, 0); } } if (cv_project->visible_r()) { switch (cv_code_choice) { case 0: // prolog: not yet (include statements) case 1: // static: callbacks, menu declarations case 2: // code: entire implementation block including children pos0 = Fl_Type::current->proj1_start; pos1 = Fl_Type::current->proj2_end; break; case 3: // code1: all implementation code before the children pos0 = Fl_Type::current->proj1_start; pos1 = Fl_Type::current->proj1_end; break; case 4: // code1: all implementation code before the children pos0 = Fl_Type::current->proj2_start; pos1 = Fl_Type::current->proj2_end; break; } if (pos0>=0) { if (pos1buffer()->line_end(pos0); cv_project->buffer()->highlight(pos0, pos1); int line = cv_project->buffer()->count_lines(0, pos0); cv_project->scroll(line, 0); } } } } /** Callback to update the codeview position. */ void update_codeview_position_cb(class Fl_Tabs*, void*) { // make sure that the selected tab shows the current view update_codeview_cb(0,0); // highlight the selected widget in the selected tab update_codeview_position(); } /** Generate a header, source, strings, or design file in a temporary directory and load those into the Code Viewer widgets. */ void update_codeview_cb(class Fl_Button*, void*) { if (!codeview_panel || !codeview_panel->visible()) return; if (!cv_source_filename) { cv_source_filename = (char*)malloc(FL_PATH_MAX); fl_strlcpy(cv_source_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_source_filename, "codeview_tmp.cxx", FL_PATH_MAX); } if (!cv_header_filename) { cv_header_filename = (char*)malloc(FL_PATH_MAX); fl_strlcpy(cv_header_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_header_filename, "codeview_tmp.h", FL_PATH_MAX); } if (!cv_design_filename) { cv_design_filename = (char*)malloc(FL_PATH_MAX); fl_strlcpy(cv_design_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_design_filename, "codeview_tmp.fl", FL_PATH_MAX); } if (cv_project->visible_r()) { write_file(cv_design_filename, false, true); int top = cv_project->top_line(); cv_project->buffer()->loadfile(cv_design_filename); cv_project->scroll(top, 0); } else if (cv_strings->visible_r()) { static const char *exts[] = { ".txt", ".po", ".msg" }; char fn[FL_PATH_MAX+1]; fl_strlcpy(fn, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(fn, "strings", FL_PATH_MAX); fl_filename_setext(fn, FL_PATH_MAX, exts[g_project.i18n_type]); write_strings(fn); int top = cv_strings->top_line(); cv_strings->buffer()->loadfile(fn); cv_strings->scroll(top, 0); } else if (cv_source->visible_r() || cv_header->visible_r()) { Fl_String code_file_name_bak = g_project.code_file_name; g_project.code_file_name = cv_source_filename; Fl_String header_file_name_bak = g_project.header_file_name; g_project.header_file_name = cv_header_filename; // generate the code and load the files Fd_Code_Writer f; // generate files if (f.write_code(cv_source_filename, cv_header_filename, true)) { // load file into source editor int pos = cv_source->top_line(); cv_source->buffer()->loadfile(cv_source_filename); cv_source->scroll(pos, 0); // load file into header editor pos = cv_header->top_line(); cv_header->buffer()->loadfile(cv_header_filename); cv_header->scroll(pos, 0); // update the source code highlighting update_codeview_position(); } g_project.code_file_name = code_file_name_bak; g_project.header_file_name = header_file_name_bak; } } /** This is called by the timer itself */ void update_codeview_timer(void*) { update_codeview_cb(0,0); } void codeview_defer_update() { // we will only update earliest 0.5 seconds after the last change, and only // if no other change was made, so dragging a widget will not generate any // CPU load Fl::remove_timeout(update_codeview_timer, 0); Fl::add_timeout(0.5, update_codeview_timer, 0); } /** Show or hide the source code preview. The state is stored in the app preferences. */ void codeview_toggle_visibility() { if (!codeview_panel) { make_codeview(); codeview_panel->callback((Fl_Callback*)toggle_codeview_cb); Fl_Preferences svp(fluid_prefs, "codeview"); int autorefresh; svp.get("autorefresh", autorefresh, 1); cv_autorefresh->value(autorefresh); int autoposition; svp.get("autoposition", autoposition, 1); cv_autoposition->value(autoposition); int tab; svp.get("tab", tab, 0); if (tab>=0 && tabchildren()) cv_tab->value(cv_tab->child(tab)); svp.get("code_choice", cv_code_choice, 2); cv_code_choice_w->value(cv_code_choice_w->find_item_with_argument(cv_code_choice)); if (!position_window(codeview_panel,"codeview_pos", 0, 320, 120, 550, 500)) return; } if (codeview_panel->visible()) { codeview_panel->hide(); codeview_item->label("Show Code View"); } else { codeview_panel->show(); codeview_item->label("Hide Code View"); update_codeview_cb(0,0); } } Fl_Double_Window *codeview_panel=(Fl_Double_Window *)0; Fl_Tabs *cv_tab=(Fl_Tabs *)0; Fl_Group *cv_source_tab=(Fl_Group *)0; CodeViewer *cv_source=(CodeViewer *)0; CodeViewer *cv_header=(CodeViewer *)0; TextViewer *cv_strings=(TextViewer *)0; TextViewer *cv_project=(TextViewer *)0; Fl_Group *cv_find_row=(Fl_Group *)0; Fl_Button *cv_find_text_case=(Fl_Button *)0; Fl_Input *cv_find_text=(Fl_Input *)0; static void cb_cv_find_text(Fl_Input* o, void*) { Fl_Text_Display *e = NULL; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { e = cv_header; } else if (cv_project->visible_r()) { e = cv_project; } if (e) { Fl_Text_Buffer *b = e->buffer(); int pos = e->insert_position(); int found = b->search_forward(pos, o->value(), &pos, cv_find_text_case->value()); if (found) { b->select(pos, pos + (int)strlen(o->value())); e->insert_position(pos); e->show_insert_position(); } } } static void cb_(Fl_Button*, void*) { Fl_Text_Display *e = NULL; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { e = cv_header; } else if (cv_project->visible_r()) { e = cv_project; } if (e) { const char *needle = cv_find_text->value(); Fl_Text_Buffer *b = e->buffer(); int pos = e->insert_position()-1; if (pos < 0) pos = b->length()-1; int found = b->search_backward(pos, needle, &pos, cv_find_text_case->value()); if (!found) found = b->search_backward(b->length()-1, needle, &pos, cv_find_text_case->value()); if (found) { b->select(pos, pos + (int)strlen(needle)); e->insert_position(pos); e->show_insert_position(); } } } static void cb_1(Fl_Button*, void*) { Fl_Text_Display *e = NULL; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { e = cv_header; } else if (cv_project->visible_r()) { e = cv_project; } if (e) { const char *needle = cv_find_text->value(); Fl_Text_Buffer *b = e->buffer(); int pos = e->insert_position() + 1; if (pos+1 >= b->length()) pos = 0; int found = b->search_forward(pos, needle, &pos, cv_find_text_case->value()); if (!found && (pos > 0)) found = b->search_forward(0, needle, &pos, cv_find_text_case->value()); if (found) { b->select(pos, pos + (int)strlen(needle)); e->insert_position(pos); e->show_insert_position(); } } } static void cb_Reveal(Fl_Button*, void*) { if (codeview_panel && codeview_panel->visible()) { Fl_Type *node = NULL; if (cv_source->visible_r()) node = Fl_Type::find_in_text(0, cv_source->insert_position()); else if (cv_header->visible_r()) node = Fl_Type::find_in_text(1, cv_header->insert_position()); else if (cv_project->visible_r()) node = Fl_Type::find_in_text(2, cv_project->insert_position()); if (node) { select_only(node); reveal_in_browser(node); if (Fl::event_clicks()==1) // double click node->open(); } } } Fl_Group *cv_settings_row=(Fl_Group *)0; Fl_Light_Button *cv_autorefresh=(Fl_Light_Button *)0; Fl_Light_Button *cv_autoposition=(Fl_Light_Button *)0; Fl_Choice *cv_code_choice_w=(Fl_Choice *)0; static void cb_cv_code_choice_w(Fl_Choice* o, void*) { cv_code_choice = (int)o->mvalue()->argument(); update_codeview_position(); } Fl_Menu_Item menu_cv_code_choice_w[] = { {"prolog", 0, 0, (void*)(0), 16, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"static", 0, 0, (void*)(1), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"code", 0, 0, (void*)(2), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"code 1", 0, 0, (void*)(3), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"code 2", 0, 0, (void*)(4), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Double_Window* make_codeview() { { codeview_panel = new Fl_Double_Window(520, 515, "Code View"); codeview_panel->callback((Fl_Callback*)toggle_codeview_cb); codeview_panel->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); { cv_tab = new Fl_Tabs(10, 10, 500, 440); cv_tab->selection_color((Fl_Color)4); cv_tab->labelcolor(FL_BACKGROUND2_COLOR); cv_tab->callback((Fl_Callback*)update_codeview_position_cb); { cv_source_tab = new Fl_Group(10, 35, 500, 415, "Source"); cv_source_tab->labelsize(13); { CodeViewer* o = cv_source = new CodeViewer(10, 40, 500, 410); cv_source->box(FL_DOWN_FRAME); cv_source->color(FL_BACKGROUND2_COLOR); cv_source->selection_color(FL_SELECTION_COLOR); cv_source->labeltype(FL_NORMAL_LABEL); cv_source->labelfont(0); cv_source->labelsize(14); cv_source->labelcolor(FL_FOREGROUND_COLOR); cv_source->textfont(4); cv_source->textsize(11); cv_source->align(Fl_Align(FL_ALIGN_TOP)); cv_source->when(FL_WHEN_RELEASE); Fl_Group::current()->resizable(cv_source); o->linenumber_width(60); o->linenumber_size(o->Fl_Text_Display::textsize()); } // CodeViewer* cv_source cv_source_tab->end(); Fl_Group::current()->resizable(cv_source_tab); } // Fl_Group* cv_source_tab { Fl_Group* o = new Fl_Group(10, 35, 500, 415, "Header"); o->labelsize(13); o->hide(); { CodeViewer* o = cv_header = new CodeViewer(10, 40, 500, 410); cv_header->box(FL_DOWN_FRAME); cv_header->color(FL_BACKGROUND2_COLOR); cv_header->selection_color(FL_SELECTION_COLOR); cv_header->labeltype(FL_NORMAL_LABEL); cv_header->labelfont(0); cv_header->labelsize(14); cv_header->labelcolor(FL_FOREGROUND_COLOR); cv_header->textfont(4); cv_header->textsize(11); cv_header->align(Fl_Align(FL_ALIGN_TOP)); cv_header->when(FL_WHEN_RELEASE); Fl_Group::current()->resizable(cv_header); o->linenumber_width(60); o->linenumber_size(o->Fl_Text_Display::textsize()); } // CodeViewer* cv_header o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(10, 35, 500, 415, "Strings"); o->labelsize(13); o->hide(); { TextViewer* o = cv_strings = new TextViewer(10, 40, 500, 410); cv_strings->box(FL_DOWN_FRAME); cv_strings->color(FL_BACKGROUND2_COLOR); cv_strings->selection_color(FL_SELECTION_COLOR); cv_strings->labeltype(FL_NORMAL_LABEL); cv_strings->labelfont(0); cv_strings->labelsize(14); cv_strings->labelcolor(FL_FOREGROUND_COLOR); cv_strings->textfont(4); cv_strings->textsize(11); cv_strings->align(Fl_Align(FL_ALIGN_TOP)); cv_strings->when(FL_WHEN_RELEASE); Fl_Group::current()->resizable(cv_strings); o->linenumber_width(60); o->linenumber_size(o->Fl_Text_Display::textsize()); } // TextViewer* cv_strings o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(10, 35, 500, 415, "Project"); o->labelsize(13); o->hide(); { TextViewer* o = cv_project = new TextViewer(10, 40, 500, 410); cv_project->box(FL_DOWN_FRAME); cv_project->color(FL_BACKGROUND2_COLOR); cv_project->selection_color(FL_SELECTION_COLOR); cv_project->labeltype(FL_NORMAL_LABEL); cv_project->labelfont(0); cv_project->labelsize(14); cv_project->labelcolor(FL_FOREGROUND_COLOR); cv_project->textfont(4); cv_project->textsize(11); cv_project->align(Fl_Align(FL_ALIGN_TOP)); cv_project->when(FL_WHEN_RELEASE); Fl_Group::current()->resizable(cv_project); o->linenumber_width(60); o->linenumber_size(o->Fl_Text_Display::textsize()); } // TextViewer* cv_project o->end(); } // Fl_Group* o cv_tab->end(); Fl_Group::current()->resizable(cv_tab); } // Fl_Tabs* cv_tab { cv_find_row = new Fl_Group(10, 460, 500, 20); { cv_find_text_case = new Fl_Button(244, 460, 25, 20, "aA"); cv_find_text_case->type(1); cv_find_text_case->labelsize(11); } // Fl_Button* cv_find_text_case { cv_find_text = new Fl_Input(40, 460, 200, 20, "Find:"); cv_find_text->labelsize(11); cv_find_text->textsize(11); cv_find_text->callback((Fl_Callback*)cb_cv_find_text); cv_find_text->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY_CHANGED); } // Fl_Input* cv_find_text { Fl_Button* o = new Fl_Button(273, 460, 25, 20, "<<"); o->labelsize(11); o->callback((Fl_Callback*)cb_); } // Fl_Button* o { Fl_Button* o = new Fl_Button(298, 460, 25, 20, ">>"); o->labelsize(11); o->callback((Fl_Callback*)cb_1); } // Fl_Button* o { Fl_Button* o = new Fl_Button(327, 460, 61, 20, "Reveal"); o->labelsize(11); o->callback((Fl_Callback*)cb_Reveal); } // Fl_Button* o { Fl_Box* o = new Fl_Box(490, 460, 20, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o cv_find_row->end(); } // Fl_Group* cv_find_row { cv_settings_row = new Fl_Group(10, 485, 500, 20); { Fl_Button* o = new Fl_Button(10, 485, 61, 20, "Refresh"); o->labelsize(11); o->callback((Fl_Callback*)update_codeview_cb); } // Fl_Button* o { Fl_Light_Button* o = cv_autorefresh = new Fl_Light_Button(77, 485, 91, 20, "Auto-Refresh"); cv_autorefresh->labelsize(11); o->callback((Fl_Callback*)update_codeview_cb); } // Fl_Light_Button* cv_autorefresh { cv_autoposition = new Fl_Light_Button(172, 485, 89, 20, "Auto-Position"); cv_autoposition->labelsize(11); } // Fl_Light_Button* cv_autoposition { cv_code_choice_w = new Fl_Choice(265, 485, 70, 20); cv_code_choice_w->down_box(FL_BORDER_BOX); cv_code_choice_w->labelsize(11); cv_code_choice_w->textsize(11); cv_code_choice_w->callback((Fl_Callback*)cb_cv_code_choice_w); cv_code_choice_w->menu(menu_cv_code_choice_w); } // Fl_Choice* cv_code_choice_w { Fl_Box* o = new Fl_Box(375, 485, 80, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o { Fl_Button* o = new Fl_Button(460, 485, 50, 20, "Close"); o->labelsize(11); o->callback((Fl_Callback*)toggle_codeview_b_cb); } // Fl_Button* o cv_settings_row->end(); } // Fl_Group* cv_settings_row codeview_panel->size_range(384, 120); codeview_panel->end(); } // Fl_Double_Window* codeview_panel return codeview_panel; } // fltk-1.4.3/fluid/Fl_Window_Type.h0000644000175000017500000001217415004135251016757 0ustar albrechtalbrecht// // Window type header file for the Fast Light Tool Kit (FLTK). // // Type for creating all subclasses of Fl_Widget // This should have the widget pointer in it, but it is still in the // Fl_Type base class. // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_FL_WINDOW_TYPE_H #define _FLUID_FL_WINDOW_TYPE_H #include "Fl_Group_Type.h" class Fl_Widget_Class_Type; extern Fl_Menu_Item window_type_menu[]; extern Fl_Widget_Class_Type *current_widget_class; void toggle_overlays(Fl_Widget *,void *); void toggle_guides(Fl_Widget *,void *); void toggle_restricted(Fl_Widget *,void *); void show_project_cb(Fl_Widget *, void *); void show_grid_cb(Fl_Widget *, void *); void show_settings_cb(Fl_Widget *, void *); enum { FD_LEFT = 1, // user drags the left side of the selection box FD_RIGHT = 2, FD_BOTTOM = 4, FD_TOP = 8, FD_DRAG = 16, // user drags the entire selection FD_BOX = 32 // user creates a new selection box }; class Fl_Window_Type : public Fl_Group_Type { typedef Fl_Group_Type super; protected: Fl_Menu_Item* subtypes() FL_OVERRIDE {return window_type_menu;} friend class Overlay_Window; int mx,my; // mouse position during dragging int x1,y1; // initial position of selection box int bx,by,br,bt; // bounding box of selection before snapping int sx,sy,sr,st; // bounding box of selection after snapping to guides int dx,dy; int drag; // which parts of bbox are being moved int numselected; // number of children selected void draw_out_of_bounds(Fl_Widget_Type *group, int x, int y, int w, int h); void draw_out_of_bounds(); void draw_overlaps(); void draw_overlay(); void newdx(); void newposition(Fl_Widget_Type *,int &x,int &y,int &w,int &h); int handle(int); void setlabel(const char *) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; Fl_Widget_Type *_make() FL_OVERRIDE {return 0;} // we don't call this Fl_Widget *widget(int,int,int,int) FL_OVERRIDE {return 0;} int recalc; // set by fix_overlay() void moveallchildren(int key=0); ID id() const FL_OVERRIDE { return ID_Window; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Window) ? true : super::is_a(inID); } void open_(); public: Fl_Window_Type() : mx(0), my(0), x1(0), y1(0), bx(0), by(0), br(0), bt(0), sx(0), sy(0), sr(0), st(0), dx(0), dy(0), drag(0), numselected(0), recalc(0), modal(0), non_modal(0), xclass(NULL), sr_min_w(0), sr_min_h(0), sr_max_w(0), sr_max_h(0) { } uchar modal, non_modal; const char *xclass; // junk string, used for shortcut Fl_Type *make(Strategy strategy) FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "Fl_Window";} const char *alt_type_name() FL_OVERRIDE {return "fltk::Window";} void open() FL_OVERRIDE; void ideal_size(int &w, int &h) FL_OVERRIDE; void fix_overlay(); // Update the bounding box, etc uchar *read_image(int &ww, int &hh); // Read an image of the window void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; int read_fdesign(const char*, const char*) FL_OVERRIDE; void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; void remove_child(Fl_Type*) FL_OVERRIDE; int can_have_children() const FL_OVERRIDE {return 1;} Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; void leave_live_mode() FL_OVERRIDE; void copy_properties() FL_OVERRIDE; int sr_min_w, sr_min_h, sr_max_w, sr_max_h; static int popupx, popupy; }; class Fl_Widget_Class_Type : private Fl_Window_Type { typedef Fl_Window_Type super; protected: Fl_Menu_Item* subtypes() FL_OVERRIDE {return 0;} public: Fl_Widget_Class_Type() { write_public_state = 0; wc_relative = 0; } // state variables for output: char write_public_state; // true when public: has been printed char wc_relative; // if 1, reposition all children, if 2, reposition and resize void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; Fl_Type *make(Strategy strategy) FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "widget_class";} ID id() const FL_OVERRIDE { return ID_Widget_Class; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Widget_Class) ? true : super::is_a(inID); } int can_have_children() const FL_OVERRIDE {return 1;} int is_code_block() const FL_OVERRIDE {return 1;} int is_decl_block() const FL_OVERRIDE {return 1;} int is_class() const FL_OVERRIDE {return 1;} }; #endif // _FLUID_FL_WINDOW_TYPE_H fltk-1.4.3/fluid/print_panel.cxx0000644000175000017500000004757615004135251016772 0ustar albrechtalbrecht// // FLUID print panel for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #include "print_panel.h" #include "fluid.h" #include #include "../src/flstring.h" #include #include Fl_Double_Window *print_panel=(Fl_Double_Window *)0; Fl_Group *print_panel_controls=(Fl_Group *)0; Fl_Choice *print_choice=(Fl_Choice *)0; static void cb_print_choice(Fl_Choice*, void*) { print_update_status(); } Fl_Button *print_properties=(Fl_Button *)0; static void cb_print_properties(Fl_Button*, void*) { print_properties_panel->show(); } Fl_Box *print_status=(Fl_Box *)0; Fl_Round_Button *print_all=(Fl_Round_Button *)0; static void cb_print_all(Fl_Round_Button*, void*) { print_from->deactivate(); print_to->deactivate(); } Fl_Round_Button *print_pages=(Fl_Round_Button *)0; static void cb_print_pages(Fl_Round_Button*, void*) { print_from->activate(); print_to->activate(); } Fl_Round_Button *print_selection=(Fl_Round_Button *)0; static void cb_print_selection(Fl_Round_Button*, void*) { print_from->deactivate(); print_to->deactivate(); } Fl_Int_Input *print_from=(Fl_Int_Input *)0; Fl_Int_Input *print_to=(Fl_Int_Input *)0; Fl_Spinner *print_copies=(Fl_Spinner *)0; static void cb_print_copies(Fl_Spinner*, void*) { if (print_copies->value() == 1) { print_collate_button->deactivate(); print_collate_group[0]->deactivate(); print_collate_group[1]->deactivate(); } else { print_collate_button->activate(); print_collate_group[0]->activate(); print_collate_group[1]->activate(); } } Fl_Check_Button *print_collate_button=(Fl_Check_Button *)0; static void cb_print_collate_button(Fl_Check_Button*, void*) { int i = print_collate_button->value() != 0; print_collate_group[i]->show(); print_collate_group[1 - i]->hide(); } Fl_Group *print_collate_group[2]={(Fl_Group *)0}; static void cb_Cancel(Fl_Button*, void*) { print_panel->hide(); } Fl_Progress *print_progress=(Fl_Progress *)0; Fl_Double_Window *print_properties_panel=(Fl_Double_Window *)0; static void cb_print_properties_panel(Fl_Double_Window*, void*) { print_properties_panel->hide(); print_update_status(); } Fl_Choice *print_page_size=(Fl_Choice *)0; Fl_Menu_Item menu_print_page_size[] = { {"Letter", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {"A4", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0} }; #include static const char *idata_print_color[] = { "24 24 17 1", " \tc None", ".\tc #FFFF00", "+\tc #C8FF00", "@\tc #00FF00", "#\tc #FFC800", "$\tc #FF0000", "%\tc #00FFFF", "&\tc #000000", "*\tc #FF00FF", "=\tc #00FFC8", "-\tc #FF00C8", ";\tc #00C800", ">\tc #C80000", ",\tc #0000C8", "\'\tc #0000FF", ")\tc #00C8FF", "!\tc #C800FF", " ...... ", " .......... ", " ............ ", " .............. ", " .............. ", " ................ ", " ................ ", " ................ ", " +@@@@@@+#$$$$$$# ", " %@@@@@@@&&$$$$$$$* ", " %%@@@@@@&&&&$$$$$$** ", " %%%=@@@@&&&&&&$$$$-*** ", " %%%%@@@;&&&&&&>$$$**** ", "%%%%%%@@&&&&&&&&$$******", "%%%%%%%@&&&&&&&&$*******", "%%%%%%%%,&&&&&&,********", "%%%%%%%%\'\'\'\'\'\'\'\'********", "%%%%%%%%\'\'\'\'\'\'\'\'********", "%%%%%%%%\'\'\'\'\'\'\'\'********", " %%%%%%%)\'\'\'\'\'\'!******* ", " %%%%%%%%\'\'\'\'\'\'******** ", " %%%%%%%%\'\'\'\'******** ", " %%%%%%%%\'\'******** ", " %%%%%% ****** " }; static Fl_Image *image_print_color() { static Fl_Image *image = NULL; if (!image) image = new Fl_Pixmap(idata_print_color); return image; } static const char *idata_print_gray[] = { "24 24 17 1", " \tc None", ".\tc #E3E3E3", "+\tc #D2D2D2", "@\tc #969696", "#\tc #C2C2C2", "$\tc #4C4C4C", "%\tc #B2B2B2", "&\tc #000000", "*\tc #696969", "=\tc #ACACAC", "-\tc #626262", ";\tc #767676", ">\tc #3C3C3C", ",\tc #161616", "\'\tc #1C1C1C", ")\tc #929292", "!\tc #585858", " ...... ", " .......... ", " ............ ", " .............. ", " .............. ", " ................ ", " ................ ", " ................ ", " +@@@@@@+#$$$$$$# ", " %@@@@@@@&&$$$$$$$* ", " %%@@@@@@&&&&$$$$$$** ", " %%%=@@@@&&&&&&$$$$-*** ", " %%%%@@@;&&&&&&>$$$**** ", "%%%%%%@@&&&&&&&&$$******", "%%%%%%%@&&&&&&&&$*******", "%%%%%%%%,&&&&&&,********", "%%%%%%%%\'\'\'\'\'\'\'\'********", "%%%%%%%%\'\'\'\'\'\'\'\'********", "%%%%%%%%\'\'\'\'\'\'\'\'********", " %%%%%%%)\'\'\'\'\'\'!******* ", " %%%%%%%%\'\'\'\'\'\'******** ", " %%%%%%%%\'\'\'\'******** ", " %%%%%%%%\'\'******** ", " %%%%%% ****** " }; static Fl_Image *image_print_gray() { static Fl_Image *image = NULL; if (!image) image = new Fl_Pixmap(idata_print_gray); return image; } Fl_Button *print_output_mode[4]={(Fl_Button *)0}; static void cb_Save(Fl_Return_Button*, void*) { print_properties_panel->hide(); char name[1024]; int val; const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); snprintf(name, sizeof(name), "%s/page_size", printer); fluid_prefs.set(name, print_page_size->value()); snprintf(name, sizeof(name), "%s/output_mode", printer); for (val = 0; val < 4; val ++) { if (print_output_mode[val]->value()) break; } fluid_prefs.set(name, val); } static void cb_Cancel1(Fl_Button*, void*) { print_properties_panel->hide(); print_update_status(); } static void cb_Use(Fl_Button*, void*) { print_properties_panel->hide(); } Fl_Double_Window* make_print_panel() { { print_panel = new Fl_Double_Window(465, 235, "Print"); { print_panel_controls = new Fl_Group(10, 10, 447, 216); { print_choice = new Fl_Choice(113, 10, 181, 25, "Printer:"); print_choice->down_box(FL_BORDER_BOX); print_choice->labelfont(1); print_choice->callback((Fl_Callback*)cb_print_choice); print_choice->when(FL_WHEN_CHANGED); } // Fl_Choice* print_choice { print_properties = new Fl_Button(294, 10, 105, 25, "Properties..."); print_properties->callback((Fl_Callback*)cb_print_properties); } // Fl_Button* print_properties { print_status = new Fl_Box(111, 41, 288, 17, "printer/job status"); print_status->align(Fl_Align(68|FL_ALIGN_INSIDE)); } // Fl_Box* print_status { Fl_Group* o = new Fl_Group(10, 86, 227, 105, "Print Range"); o->box(FL_THIN_DOWN_BOX); o->labelfont(1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); { print_all = new Fl_Round_Button(20, 96, 38, 25, "All"); print_all->type(102); print_all->down_box(FL_ROUND_DOWN_BOX); print_all->value(1); print_all->callback((Fl_Callback*)cb_print_all); } // Fl_Round_Button* print_all { print_pages = new Fl_Round_Button(20, 126, 64, 25, "Pages"); print_pages->type(102); print_pages->down_box(FL_ROUND_DOWN_BOX); print_pages->callback((Fl_Callback*)cb_print_pages); } // Fl_Round_Button* print_pages { print_selection = new Fl_Round_Button(20, 156, 82, 25, "Selection"); print_selection->type(102); print_selection->down_box(FL_ROUND_DOWN_BOX); print_selection->callback((Fl_Callback*)cb_print_selection); } // Fl_Round_Button* print_selection { print_from = new Fl_Int_Input(136, 126, 28, 25, "From:"); print_from->type(2); print_from->textfont(4); print_from->deactivate(); } // Fl_Int_Input* print_from { print_to = new Fl_Int_Input(199, 126, 28, 25, "To:"); print_to->type(2); print_to->textfont(4); print_to->deactivate(); } // Fl_Int_Input* print_to o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(247, 86, 210, 105, "Copies"); o->box(FL_THIN_DOWN_BOX); o->labelfont(1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); { print_copies = new Fl_Spinner(321, 96, 45, 25, "# Copies:"); print_copies->callback((Fl_Callback*)cb_print_copies); print_copies->when(FL_WHEN_CHANGED); } // Fl_Spinner* print_copies { print_collate_button = new Fl_Check_Button(376, 96, 64, 25, "Collate"); print_collate_button->down_box(FL_DOWN_BOX); print_collate_button->callback((Fl_Callback*)cb_print_collate_button); print_collate_button->when(FL_WHEN_CHANGED); print_collate_button->deactivate(); } // Fl_Check_Button* print_collate_button { print_collate_group[0] = new Fl_Group(257, 131, 191, 50); print_collate_group[0]->deactivate(); { Fl_Box* o = new Fl_Box(287, 141, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(272, 136, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(257, 131, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(352, 141, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(337, 136, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(322, 131, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(417, 141, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(402, 136, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(387, 131, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o print_collate_group[0]->end(); } // Fl_Group* print_collate_group[0] { print_collate_group[1] = new Fl_Group(257, 131, 191, 50); print_collate_group[1]->hide(); print_collate_group[1]->deactivate(); { Fl_Box* o = new Fl_Box(287, 141, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(272, 136, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(257, 131, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(352, 141, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(337, 136, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(322, 131, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(417, 141, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(402, 136, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(387, 131, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o print_collate_group[1]->end(); } // Fl_Group* print_collate_group[1] o->end(); } // Fl_Group* o { Fl_Return_Button* o = new Fl_Return_Button(309, 201, 70, 25, "Print"); o->callback((Fl_Callback*)print_cb); } // Fl_Return_Button* o { Fl_Button* o = new Fl_Button(389, 201, 68, 25, "Cancel"); o->callback((Fl_Callback*)cb_Cancel); } // Fl_Button* o print_panel_controls->end(); } // Fl_Group* print_panel_controls { print_progress = new Fl_Progress(10, 203, 289, 21); print_progress->selection_color((Fl_Color)4); print_progress->hide(); } // Fl_Progress* print_progress print_panel->set_modal(); print_panel->end(); } // Fl_Double_Window* print_panel { print_properties_panel = new Fl_Double_Window(290, 130, "Printer Properties"); print_properties_panel->callback((Fl_Callback*)cb_print_properties_panel); { print_page_size = new Fl_Choice(110, 10, 80, 25, "Page Size:"); print_page_size->down_box(FL_BORDER_BOX); print_page_size->labelfont(1); print_page_size->labelsize(12); print_page_size->menu(menu_print_page_size); } // Fl_Choice* print_page_size { Fl_Group* o = new Fl_Group(110, 45, 170, 40, "Output Mode:"); o->labelfont(1); o->labelsize(12); o->align(Fl_Align(FL_ALIGN_LEFT)); { print_output_mode[0] = new Fl_Button(110, 45, 30, 40); print_output_mode[0]->type(102); print_output_mode[0]->box(FL_BORDER_BOX); print_output_mode[0]->down_box(FL_BORDER_BOX); print_output_mode[0]->value(1); print_output_mode[0]->color(FL_BACKGROUND2_COLOR); print_output_mode[0]->selection_color(FL_FOREGROUND_COLOR); print_output_mode[0]->image( image_print_color() ); } // Fl_Button* print_output_mode[0] { print_output_mode[1] = new Fl_Button(150, 50, 40, 30); print_output_mode[1]->type(102); print_output_mode[1]->box(FL_BORDER_BOX); print_output_mode[1]->down_box(FL_BORDER_BOX); print_output_mode[1]->color(FL_BACKGROUND2_COLOR); print_output_mode[1]->selection_color(FL_FOREGROUND_COLOR); print_output_mode[1]->image( image_print_color() ); } // Fl_Button* print_output_mode[1] { print_output_mode[2] = new Fl_Button(200, 45, 30, 40); print_output_mode[2]->type(102); print_output_mode[2]->box(FL_BORDER_BOX); print_output_mode[2]->down_box(FL_BORDER_BOX); print_output_mode[2]->color(FL_BACKGROUND2_COLOR); print_output_mode[2]->selection_color(FL_FOREGROUND_COLOR); print_output_mode[2]->image( image_print_gray() ); } // Fl_Button* print_output_mode[2] { print_output_mode[3] = new Fl_Button(240, 50, 40, 30); print_output_mode[3]->type(102); print_output_mode[3]->box(FL_BORDER_BOX); print_output_mode[3]->down_box(FL_BORDER_BOX); print_output_mode[3]->color(FL_BACKGROUND2_COLOR); print_output_mode[3]->selection_color(FL_FOREGROUND_COLOR); print_output_mode[3]->image( image_print_gray() ); } // Fl_Button* print_output_mode[3] o->end(); } // Fl_Group* o { Fl_Return_Button* o = new Fl_Return_Button(123, 95, 79, 25, "Save"); o->callback((Fl_Callback*)cb_Save); } // Fl_Return_Button* o { Fl_Button* o = new Fl_Button(212, 95, 68, 25, "Cancel"); o->callback((Fl_Callback*)cb_Cancel1); } // Fl_Button* o { Fl_Button* o = new Fl_Button(60, 95, 53, 25, "Use"); o->callback((Fl_Callback*)cb_Use); } // Fl_Button* o print_properties_panel->set_modal(); print_properties_panel->end(); } // Fl_Double_Window* print_properties_panel return print_properties_panel; } void print_cb(Fl_Return_Button *, void *); void print_load() { FILE *lpstat; char line[1024], name[1024], *nptr, qname[2048], *qptr, defname[1024]; int i; if (print_choice->size() > 1) { for (i = 1; print_choice->text(i); i ++) { free(print_choice->menu()[i].user_data()); } } print_choice->clear(); print_choice->add("Print To File", 0, 0, 0, FL_MENU_DIVIDER); print_choice->value(0); defname[0] = '\0'; if ((lpstat = popen("LC_MESSAGES=C LANG=C lpstat -p -d", "r")) != NULL) { while (fgets(line, sizeof(line), lpstat)) { if (!strncmp(line, "printer ", 8) && sscanf(line + 8, "%s", name) == 1) { for (nptr = name, qptr = qname; *nptr; *qptr++ = *nptr++) { if (*nptr == '/') *qptr++ = '\\'; } *qptr = '\0'; print_choice->add(qname, 0, 0, (void *)fl_strdup(name), 0); } else if (!strncmp(line, "system default destination: ", 28)) { if (sscanf(line + 28, "%s", defname) != 1) defname[0] = '\0'; } } pclose(lpstat); } if (defname[0]) { for (i = 1; print_choice->text(i); i ++) { if (!strcmp((char *)print_choice->menu()[i].user_data(), defname)) { print_choice->value(i); break; } } } else if (print_choice->size() > 2) print_choice->value(1); print_update_status(); } void print_update_status() { FILE *lpstat; char command[1024]; static char status[1024]; const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); if (print_choice->value()) { snprintf(command, sizeof(command), "lpstat -p '%s'", printer); if ((lpstat = popen(command, "r")) != NULL) { if (fgets(status, sizeof(status), lpstat)==0) { /* ignore */ } pclose(lpstat); } else strcpy(status, "printer status unavailable"); } else status[0] = '\0'; print_status->label(status); char name[1024]; int val; snprintf(name, sizeof(name), "%s/page_size", printer); fluid_prefs.get(name, val, 0); print_page_size->value(val); snprintf(name, sizeof(name), "%s/output_mode", printer); fluid_prefs.get(name, val, 0); print_output_mode[val]->setonly(); } fltk-1.4.3/fluid/Fl_Button_Type.cxx0000644000175000017500000001567115004135251017343 0ustar albrechtalbrecht// // Button type factory code for the Fast Light Tool Kit (FLTK). // // Type classes for most of the fltk widgets. Most of the work // is done by code in Fl_Widget_Type.C. Also a factory instance // of each of these type classes. // // This file also contains the "new" menu, which has a pointer // to a factory instance for every class (both the ones defined // here and ones in other files) // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Button_Type.h" #include "Fd_Snap_Action.h" #include "file.h" #include #include #include #include #include #include #include #include // ---- Button Types --------------------------------------------------- MARK: - // ---- Button ---- static Fl_Menu_Item buttontype_menu[] = { {"Normal", 0, 0, (void*)0}, {"Toggle", 0, 0, (void*)FL_TOGGLE_BUTTON}, {"Radio", 0, 0, (void*)FL_RADIO_BUTTON}, {0} }; Fl_Menu_Item *Fl_Button_Type::subtypes() { return buttontype_menu; } void Fl_Button_Type::ideal_size(int &w, int &h) { h = layout->labelsize + 8; w = layout->labelsize * 4 + 8; Fd_Snap_Action::better_size(w, h); } Fl_Widget *Fl_Button_Type::widget(int x, int y, int w, int h) { return new Fl_Button(x, y, w, h, "Button"); } void Fl_Button_Type::write_properties(Fd_Project_Writer &f) { Fl_Widget_Type::write_properties(f); Fl_Button *btn = (Fl_Button*)o; if (btn->compact()) { f.write_string("compact"); f.write_string("%d", btn->compact()); } } void Fl_Button_Type::read_property(Fd_Project_Reader &f, const char *c) { Fl_Button *btn = (Fl_Button*)o; if (!strcmp(c, "compact")) { btn->compact((uchar)atol(f.read_word())); } else { Fl_Widget_Type::read_property(f, c); } } void Fl_Button_Type::copy_properties() { Fl_Widget_Type::copy_properties(); Fl_Button *s = (Fl_Button*)o, *d = (Fl_Button*)live_widget; d->compact(s->compact()); } Fl_Button_Type Fl_Button_type; // ---- Return Button ---- /** \brief The Return Button is simply a Button with the return key as a hotkey. */ class Fl_Return_Button_Type : public Fl_Button_Type { typedef Fl_Button_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->labelsize + 8; w = layout->labelsize * 4 + 8 + h; // make room for the symbol Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Return_Button"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::ReturnButton"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Return_Button(x, y, w, h, "Button"); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Return_Button_Type(); } ID id() const FL_OVERRIDE { return ID_Return_Button; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Return_Button) ? true : super::is_a(inID); } }; Fl_Return_Button_Type Fl_Return_Button_type; // ---- Repeat Button ---- /** \brief Handler for Fl_Repeat_Button. \note Even though Fl_Repeat_Button is somewhat limited compared to Fl_Button, and some settings may not make much sense, it is still derived from it, so the wrapper should be as well. */ class Fl_Repeat_Button_Type : public Fl_Button_Type { typedef Fl_Button_Type super; public: const char *type_name() FL_OVERRIDE { return "Fl_Repeat_Button"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::RepeatButton"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Repeat_Button(x, y, w, h, "Button"); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Repeat_Button_Type(); } ID id() const FL_OVERRIDE { return ID_Repeat_Button; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Repeat_Button) ? true : super::is_a(inID); } }; Fl_Repeat_Button_Type Fl_Repeat_Button_type; // ---- Light Button ---- /** \brief A handler for a toggle button with an indicator light. */ class Fl_Light_Button_Type : public Fl_Button_Type { typedef Fl_Button_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->labelsize + 8; w = layout->labelsize * 4 + 8 + layout->labelsize; // make room for the light Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Light_Button"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::LightButton"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Light_Button(x, y, w, h, "Button"); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Light_Button_Type(); } ID id() const FL_OVERRIDE { return ID_Light_Button; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Light_Button) ? true : super::is_a(inID); } }; Fl_Light_Button_Type Fl_Light_Button_type; // ---- Check Button ---- /** \brief Manage buttons with a check mark on its left. */ class Fl_Check_Button_Type : public Fl_Button_Type { typedef Fl_Button_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->labelsize + 8; w = layout->labelsize * 4 + 8 + layout->labelsize; // make room for the symbol Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Check_Button"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::CheckButton"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Check_Button(x, y, w, h, "Button"); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Check_Button_Type(); } ID id() const FL_OVERRIDE { return ID_Check_Button; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Check_Button) ? true : super::is_a(inID); } }; Fl_Check_Button_Type Fl_Check_Button_type; // ---- Round Button ---- /** \brief Manage buttons with a round indicator on its left. */ class Fl_Round_Button_Type : public Fl_Button_Type { typedef Fl_Button_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->labelsize + 8; w = layout->labelsize * 4 + 8 + layout->labelsize; // make room for the symbol Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Round_Button"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::RadioButton"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Round_Button(x, y, w, h, "Button"); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Round_Button_Type(); } ID id() const FL_OVERRIDE { return ID_Round_Button; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Round_Button) ? true : super::is_a(inID); } }; Fl_Round_Button_Type Fl_Round_Button_type; fltk-1.4.3/fluid/CodeEditor.h0000644000175000017500000000554615004135251016114 0ustar albrechtalbrecht// // Code editor widget for the Fast Light Tool Kit (FLTK). // Syntax highlighting rewritten by erco@seriss.com 09/15/20. // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef CodeEditor_h #define CodeEditor_h // // Include necessary headers... // #include "StyleParse.h" #include #include #include #include #include #include #include // ---- CodeEditor declaration /** A widget derived from Fl_Text_Editor that implements C++ code highlighting. CodeEditor is used in Fluid whenever the user can edit C++ source code or header text. */ class CodeEditor : public Fl_Text_Editor { friend class StyleParse; static Fl_Text_Display::Style_Table_Entry styletable[]; static void style_parse(const char *tbuff, char *sbuff, int len, char style); static void style_unfinished_cb(int, void*); static void style_update(int pos, int nInserted, int nDeleted, int /*nRestyled*/, const char * /*deletedText*/, void *cbArg); static int auto_indent(int, CodeEditor* e); public: CodeEditor(int X, int Y, int W, int H, const char *L=0); ~CodeEditor(); void textsize(Fl_Fontsize s); /// access to protected member get_absolute_top_line_number() int top_line() { return get_absolute_top_line_number(); } /// access to protected member mTopLineNum int scroll_row() { return mTopLineNum; } /// access to protected member mHorizOffset int scroll_col() { return mHorizOffset; } }; // ---- CodeViewer declaration /** A widget derived from CodeEditor with highlighting for code blocks. This widget is used by the codeview system to show the design's source and header code. The secondary highlighting show the text part that corresponds to the selected widget(s). */ class CodeViewer : public CodeEditor { public: CodeViewer(int X, int Y, int W, int H, const char *L=0); protected: void draw() FL_OVERRIDE; /// Limit event handling to viewing, not editing int handle(int ev) FL_OVERRIDE { return Fl_Text_Display::handle(ev); } }; // ---- Project File Text Viewer declaration /** A text viewer with an additional highlighting color scheme. */ class TextViewer : public Fl_Text_Display { public: TextViewer(int X, int Y, int W, int H, const char *L=0); ~TextViewer(); void draw() FL_OVERRIDE; /// access to protected member get_absolute_top_line_number() int top_line() { return get_absolute_top_line_number(); } }; #endif // !CodeEditor_h fltk-1.4.3/fluid/function_panel.cxx0000644000175000017500000017417715004135251017461 0ustar albrechtalbrecht// // Code dialogs for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #include "function_panel.h" #include "fluid.h" #include "custom_widgets.h" #include "pixmaps.h" #include "factory.h" #include "Fl_Type.h" #include "widget_browser.h" #include "undo.h" /** Allow widget navigation on text fields with Tab. */ static int use_tab_navigation(int, Fl_Text_Editor*) { return 0; } Fl_Double_Window *function_panel=(Fl_Double_Window *)0; Fl_Choice *f_public_member_choice=(Fl_Choice *)0; Fl_Menu_Item menu_f_public_member_choice[] = { {"private", 0, 0, (void*)(0), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"public", 0, 0, (void*)(1), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"protected", 0, 0, (void*)(2), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Choice *f_public_choice=(Fl_Choice *)0; Fl_Menu_Item menu_f_public_choice[] = { {"static", 0, 0, (void*)(0), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"global", 0, 0, (void*)(1), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"local", 0, 0, (void*)(2), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Light_Button *f_c_button=(Fl_Light_Button *)0; Fl_Input *f_name_input=(Fl_Input *)0; Fl_Input *f_return_type_input=(Fl_Input *)0; Fl_Text_Editor *f_comment_input=(Fl_Text_Editor *)0; Fl_Return_Button *f_panel_ok=(Fl_Return_Button *)0; Fl_Button *f_panel_cancel=(Fl_Button *)0; Fl_Double_Window* make_function_panel() { { function_panel = new Fl_Double_Window(343, 232, "Function/Method Properties"); function_panel->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); { Fl_Group* o = new Fl_Group(10, 10, 270, 20); { f_public_member_choice = new Fl_Choice(10, 10, 75, 20); f_public_member_choice->tooltip("Change member access attribute."); f_public_member_choice->down_box(FL_BORDER_BOX); f_public_member_choice->labelsize(11); f_public_member_choice->textsize(11); f_public_member_choice->when(FL_WHEN_CHANGED); f_public_member_choice->menu(menu_f_public_member_choice); } // Fl_Choice* f_public_member_choice { f_public_choice = new Fl_Choice(10, 10, 75, 20); f_public_choice->tooltip("Change widget accessibility."); f_public_choice->down_box(FL_BORDER_BOX); f_public_choice->labelsize(11); f_public_choice->textsize(11); f_public_choice->when(FL_WHEN_CHANGED); f_public_choice->menu(menu_f_public_choice); } // Fl_Choice* f_public_choice { f_c_button = new Fl_Light_Button(95, 10, 120, 20, "C declaration"); f_c_button->tooltip("Declare with a C interface instead of C++."); f_c_button->labelsize(11); } // Fl_Light_Button* f_c_button { Fl_Box* o = new Fl_Box(235, 10, 45, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { f_name_input = new Fl_Input(10, 50, 320, 20, "Name(args): (blank for main())"); f_name_input->tooltip("The name of the function or method."); f_name_input->labelfont(1); f_name_input->labelsize(11); f_name_input->textfont(4); f_name_input->textsize(11); f_name_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); f_name_input->when(FL_WHEN_NEVER); } // Fl_Input* f_name_input { f_return_type_input = new Fl_Input(10, 90, 320, 20, "Return Type: (blank to return outermost widget)"); f_return_type_input->tooltip("The return type of the function or method."); f_return_type_input->labelfont(1); f_return_type_input->labelsize(11); f_return_type_input->textfont(4); f_return_type_input->textsize(11); f_return_type_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); f_return_type_input->when(FL_WHEN_NEVER); } // Fl_Input* f_return_type_input { f_comment_input = new Fl_Text_Editor(10, 125, 320, 65, "Comment:"); f_comment_input->tooltip("Function comment in Doxygen format"); f_comment_input->box(FL_DOWN_BOX); f_comment_input->labelfont(1); f_comment_input->labelsize(11); f_comment_input->textfont(4); f_comment_input->textsize(11); f_comment_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); Fl_Group::current()->resizable(f_comment_input); f_comment_input->buffer(new Fl_Text_Buffer()); f_comment_input->add_key_binding(FL_Tab, 0, use_tab_navigation); } // Fl_Text_Editor* f_comment_input { Fl_Group* o = new Fl_Group(10, 200, 320, 20); { f_panel_ok = new Fl_Return_Button(220, 200, 50, 20, "OK"); f_panel_ok->tooltip("Apply the changes."); f_panel_ok->labelsize(11); f_panel_ok->window()->hotspot(f_panel_ok); } // Fl_Return_Button* f_panel_ok { f_panel_cancel = new Fl_Button(280, 200, 50, 20, "Cancel"); f_panel_cancel->tooltip("Cancel the changes."); f_panel_cancel->labelsize(11); } // Fl_Button* f_panel_cancel { Fl_Box* o = new Fl_Box(10, 200, 205, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o function_panel->set_modal(); function_panel->end(); } // Fl_Double_Window* function_panel return function_panel; } Fl_Double_Window *code_panel=(Fl_Double_Window *)0; static void cb_code_panel(Fl_Double_Window*, void*) { if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape) return; // ignore Escape code_panel->hide(); // otherwise hide..; } CodeEditor *code_input=(CodeEditor *)0; Fl_Return_Button *code_panel_ok=(Fl_Return_Button *)0; Fl_Button *code_panel_cancel=(Fl_Button *)0; Fl_Double_Window* make_code_panel() { { Fl_Double_Window* o = code_panel = new Fl_Double_Window(540, 180, "Code Properties"); code_panel->labelsize(11); code_panel->callback((Fl_Callback*)cb_code_panel); { CodeEditor* o = code_input = new CodeEditor(10, 10, 520, 130); code_input->box(FL_DOWN_BOX); code_input->color(FL_BACKGROUND2_COLOR); code_input->selection_color(FL_SELECTION_COLOR); code_input->labeltype(FL_NORMAL_LABEL); code_input->labelfont(0); code_input->labelsize(11); code_input->labelcolor(FL_FOREGROUND_COLOR); code_input->textfont(4); code_input->textsize(11); code_input->align(Fl_Align(FL_ALIGN_TOP)); code_input->when(FL_WHEN_RELEASE); Fl_Group::current()->resizable(code_input); o->when(FL_WHEN_ENTER_KEY_CHANGED|FL_WHEN_RELEASE); } // CodeEditor* code_input { Fl_Group* o = new Fl_Group(10, 150, 520, 20); o->labelsize(11); { code_panel_ok = new Fl_Return_Button(400, 150, 60, 20, "OK"); code_panel_ok->labelsize(11); code_panel_ok->window()->hotspot(code_panel_ok); } // Fl_Return_Button* code_panel_ok { code_panel_cancel = new Fl_Button(470, 150, 60, 20, "Cancel"); code_panel_cancel->labelsize(11); } // Fl_Button* code_panel_cancel { Fl_Box* o = new Fl_Box(10, 150, 380, 20); o->labelsize(11); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o code_panel->set_modal(); o->size_range(200, 150); code_panel->end(); } // Fl_Double_Window* code_panel // Enable line numbers code_input->linenumber_width(60); code_input->linenumber_size(code_input->Fl_Text_Display::textsize()); return code_panel; } Fl_Double_Window *codeblock_panel=(Fl_Double_Window *)0; Fl_Input *code_before_input=(Fl_Input *)0; Fl_Input *code_after_input=(Fl_Input *)0; Fl_Return_Button *codeblock_panel_ok=(Fl_Return_Button *)0; Fl_Button *codeblock_panel_cancel=(Fl_Button *)0; Fl_Double_Window* make_codeblock_panel() { { Fl_Double_Window* o = codeblock_panel = new Fl_Double_Window(300, 115, "Code Block Properties"); codeblock_panel->labelsize(11); { code_before_input = new Fl_Input(10, 15, 280, 20, "Conditional code block"); code_before_input->tooltip("#ifdef or similar conditional code block."); code_before_input->labelsize(11); code_before_input->textfont(4); code_before_input->textsize(11); code_before_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); code_before_input->when(FL_WHEN_NEVER); } // Fl_Input* code_before_input { code_after_input = new Fl_Input(10, 55, 280, 20, "\"{...child code...}\" is inserted here"); code_after_input->tooltip("#endif or similar conditional code block."); code_after_input->labelsize(11); code_after_input->textfont(4); code_after_input->textsize(11); code_after_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); code_after_input->when(FL_WHEN_NEVER); Fl_Group::current()->resizable(code_after_input); } // Fl_Input* code_after_input { Fl_Group* o = new Fl_Group(10, 85, 280, 20); { codeblock_panel_ok = new Fl_Return_Button(160, 85, 60, 20, "OK"); codeblock_panel_ok->labelsize(11); codeblock_panel_ok->window()->hotspot(codeblock_panel_ok); } // Fl_Return_Button* codeblock_panel_ok { codeblock_panel_cancel = new Fl_Button(230, 85, 60, 20, "Cancel"); codeblock_panel_cancel->shortcut(0xff1b); codeblock_panel_cancel->labelsize(11); } // Fl_Button* codeblock_panel_cancel { Fl_Box* o = new Fl_Box(10, 85, 140, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o codeblock_panel->set_modal(); o->size_range(o->w(), o->h(), Fl::w(), o->h()); codeblock_panel->end(); } // Fl_Double_Window* codeblock_panel return codeblock_panel; } Fl_Double_Window *declblock_panel=(Fl_Double_Window *)0; Fl_Input *declblock_before_input=(Fl_Input *)0; Fl_Input *declblock_after_input=(Fl_Input *)0; Fl_Check_Button *declblock_code_source=(Fl_Check_Button *)0; Fl_Check_Button *declblock_static_source=(Fl_Check_Button *)0; Fl_Check_Button *declblock_code_header=(Fl_Check_Button *)0; Fl_Check_Button *declblock_static_header=(Fl_Check_Button *)0; Fl_Text_Editor *declblock_comment_input=(Fl_Text_Editor *)0; Fl_Return_Button *declblock_panel_ok=(Fl_Return_Button *)0; Fl_Button *declblock_panel_cancel=(Fl_Button *)0; Fl_Double_Window* make_declblock_panel() { { Fl_Double_Window* o = declblock_panel = new Fl_Double_Window(300, 355, "Declaration Block Properties"); declblock_panel->labelsize(11); declblock_panel->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); { declblock_before_input = new Fl_Input(10, 23, 280, 20, "Start Code:"); declblock_before_input->tooltip("#ifdef or similar conditional declaration block."); declblock_before_input->labelfont(1); declblock_before_input->labelsize(11); declblock_before_input->textfont(4); declblock_before_input->textsize(11); declblock_before_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); declblock_before_input->when(FL_WHEN_NEVER); } // Fl_Input* declblock_before_input { Fl_Box* o = new Fl_Box(10, 48, 280, 20, "\"\\n...child code...\\n\" is inserted here"); o->labelsize(11); } // Fl_Box* o { declblock_after_input = new Fl_Input(10, 80, 280, 20, "End Code:"); declblock_after_input->tooltip("#endif or similar declaration code block."); declblock_after_input->labelfont(1); declblock_after_input->labelsize(11); declblock_after_input->textfont(4); declblock_after_input->textsize(11); declblock_after_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); declblock_after_input->when(FL_WHEN_NEVER); } // Fl_Input* declblock_after_input { Fl_Group* o = new Fl_Group(10, 105, 280, 120); { Fl_Box* o = new Fl_Box(10, 105, 270, 20, "Enclose code generated by children in source file:"); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); } // Fl_Box* o { declblock_code_source = new Fl_Check_Button(20, 125, 260, 20, "implementations"); declblock_code_source->down_box(FL_DOWN_BOX); declblock_code_source->labelsize(11); } // Fl_Check_Button* declblock_code_source { declblock_static_source = new Fl_Check_Button(20, 145, 260, 20, "static initializations and callbacks"); declblock_static_source->down_box(FL_DOWN_BOX); declblock_static_source->labelsize(11); } // Fl_Check_Button* declblock_static_source { Fl_Box* o = new Fl_Box(10, 165, 270, 20, "Enclose code in header file:"); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); } // Fl_Box* o { declblock_code_header = new Fl_Check_Button(20, 185, 260, 20, "forward declarations"); declblock_code_header->down_box(FL_DOWN_BOX); declblock_code_header->labelsize(11); } // Fl_Check_Button* declblock_code_header { declblock_static_header = new Fl_Check_Button(20, 205, 260, 20, "preprecessor and callback declarations"); declblock_static_header->down_box(FL_DOWN_BOX); declblock_static_header->labelsize(11); } // Fl_Check_Button* declblock_static_header { Fl_Box* o = new Fl_Box(280, 105, 10, 120); o->labelsize(11); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { declblock_comment_input = new Fl_Text_Editor(10, 242, 280, 65, "Comment:"); declblock_comment_input->tooltip("Declaration comment in Doxygen format"); declblock_comment_input->box(FL_DOWN_BOX); declblock_comment_input->labelfont(1); declblock_comment_input->labelsize(11); declblock_comment_input->textfont(4); declblock_comment_input->textsize(11); declblock_comment_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); Fl_Group::current()->resizable(declblock_comment_input); declblock_comment_input->buffer(new Fl_Text_Buffer()); declblock_comment_input->add_key_binding(FL_Tab, 0, use_tab_navigation); } // Fl_Text_Editor* declblock_comment_input { Fl_Group* o = new Fl_Group(10, 321, 280, 20); { declblock_panel_ok = new Fl_Return_Button(160, 321, 60, 20, "OK"); declblock_panel_ok->labelsize(11); declblock_panel_ok->window()->hotspot(declblock_panel_ok); } // Fl_Return_Button* declblock_panel_ok { declblock_panel_cancel = new Fl_Button(230, 321, 60, 20, "Cancel"); declblock_panel_cancel->shortcut(0xff1b); declblock_panel_cancel->labelsize(11); } // Fl_Button* declblock_panel_cancel { Fl_Box* o = new Fl_Box(10, 321, 140, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o declblock_panel->set_modal(); declblock_panel->size_range(300, 355); o->size_range(o->w(), o->h(), Fl::w(), o->h()); declblock_panel->end(); } // Fl_Double_Window* declblock_panel return declblock_panel; } Fl_Double_Window *decl_panel=(Fl_Double_Window *)0; Fl_Choice *decl_choice=(Fl_Choice *)0; Fl_Menu_Item menu_decl_choice[] = { {"in source file only", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"in header file only", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"\"static\" in source file", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"in source and \"extern\" in header", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Choice *decl_class_choice=(Fl_Choice *)0; Fl_Menu_Item menu_decl_class_choice[] = { {"private", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"public", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"protected", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; CodeEditor *decl_input=(CodeEditor *)0; Fl_Text_Editor *decl_comment_input=(Fl_Text_Editor *)0; Fl_Return_Button *decl_panel_ok=(Fl_Return_Button *)0; Fl_Button *decl_panel_cancel=(Fl_Button *)0; Fl_Double_Window* make_decl_panel() { { decl_panel = new Fl_Double_Window(343, 262, "Declaration Properties"); decl_panel->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); { Fl_Group* o = new Fl_Group(10, 10, 270, 20); { Fl_Box* o = new Fl_Box(200, 10, 80, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o { decl_choice = new Fl_Choice(10, 10, 185, 20); decl_choice->down_box(FL_BORDER_BOX); decl_choice->labelsize(11); decl_choice->textsize(11); decl_choice->menu(menu_decl_choice); } // Fl_Choice* decl_choice { decl_class_choice = new Fl_Choice(10, 10, 75, 20); decl_class_choice->down_box(FL_BORDER_BOX); decl_class_choice->labelsize(11); decl_class_choice->textsize(11); decl_class_choice->menu(menu_decl_class_choice); } // Fl_Choice* decl_class_choice o->end(); } // Fl_Group* o { Fl_Tile* o = new Fl_Tile(10, 40, 320, 180); { Fl_Group* o = new Fl_Group(10, 40, 320, 100); o->box(FL_FLAT_BOX); { decl_input = new CodeEditor(10, 40, 320, 45, "This can be any declaration, like \"int x;\", an external symbol like \"exter" "n int foo();\", a #directive like \"#include \", a comment like \"//foo" "\" or \"/*foo*/\", or typedef like \"typedef char byte;\" or \"using std::list" ";\"."); decl_input->box(FL_DOWN_FRAME); decl_input->color(FL_BACKGROUND2_COLOR); decl_input->selection_color(FL_SELECTION_COLOR); decl_input->labeltype(FL_NORMAL_LABEL); decl_input->labelfont(0); decl_input->labelsize(11); decl_input->labelcolor(FL_FOREGROUND_COLOR); decl_input->align(Fl_Align(134)); decl_input->when(FL_WHEN_RELEASE); Fl_Group::current()->resizable(decl_input); } // CodeEditor* decl_input { Fl_Box* o = new Fl_Box(20, 139, 300, 1); o->box(FL_BORDER_FRAME); o->color((Fl_Color)43); } // Fl_Box* o o->end(); Fl_Group::current()->resizable(o); } // Fl_Group* o { Fl_Group* o = new Fl_Group(10, 140, 320, 80); o->box(FL_FLAT_BOX); { decl_comment_input = new Fl_Text_Editor(10, 155, 320, 64, "Comment:"); decl_comment_input->tooltip("Declaration comment in Doxygen format"); decl_comment_input->box(FL_DOWN_BOX); decl_comment_input->labelfont(1); decl_comment_input->labelsize(11); decl_comment_input->textfont(4); decl_comment_input->textsize(11); decl_comment_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); Fl_Group::current()->resizable(decl_comment_input); decl_comment_input->buffer(new Fl_Text_Buffer()); decl_comment_input->add_key_binding(FL_Tab, 0, use_tab_navigation); } // Fl_Text_Editor* decl_comment_input o->end(); } // Fl_Group* o o->size_range(0, 320, 100); o->size_range(1, 320, 60); o->end(); Fl_Group::current()->resizable(o); } // Fl_Tile* o { Fl_Group* o = new Fl_Group(10, 230, 320, 20); { decl_panel_ok = new Fl_Return_Button(200, 230, 60, 20, "OK"); decl_panel_ok->labelsize(11); decl_panel_ok->window()->hotspot(decl_panel_ok); } // Fl_Return_Button* decl_panel_ok { decl_panel_cancel = new Fl_Button(270, 230, 60, 20, "Cancel"); decl_panel_cancel->shortcut(0xff1b); decl_panel_cancel->labelsize(11); } // Fl_Button* decl_panel_cancel { Fl_Box* o = new Fl_Box(10, 230, 185, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o decl_panel->size_range(343, 262); decl_panel->end(); } // Fl_Double_Window* decl_panel return decl_panel; } Fl_Double_Window *data_panel=(Fl_Double_Window *)0; Fl_Choice *data_choice=(Fl_Choice *)0; Fl_Menu_Item menu_data_choice[] = { {"in source file only", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"in header file only", 0, 0, 0, 16, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"\"static\" in source file", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"in source and \"extern\" in header", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Choice *data_class_choice=(Fl_Choice *)0; Fl_Menu_Item menu_data_class_choice[] = { {"private", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"public", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"protected", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Choice *data_mode=(Fl_Choice *)0; Fl_Menu_Item menu_data_mode[] = { {"binary mode", 0, 0, (void*)(0), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"text mode", 0, 0, (void*)(1), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"compressed binary", 0, 0, (void*)(2), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Input *data_input=(Fl_Input *)0; Fl_Input *data_filename=(Fl_Input *)0; Fl_Button *data_filebrowser=(Fl_Button *)0; Fl_Text_Editor *data_comment_input=(Fl_Text_Editor *)0; Fl_Return_Button *data_panel_ok=(Fl_Return_Button *)0; Fl_Button *data_panel_cancel=(Fl_Button *)0; Fl_Double_Window* make_data_panel() { { data_panel = new Fl_Double_Window(343, 264, "Inline Data Properties"); data_panel->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); { Fl_Group* o = new Fl_Group(10, 10, 320, 48); { Fl_Box* o = new Fl_Box(288, 10, 42, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o { data_choice = new Fl_Choice(10, 10, 185, 20); data_choice->down_box(FL_BORDER_BOX); data_choice->labelsize(11); data_choice->textsize(11); data_choice->menu(menu_data_choice); } // Fl_Choice* data_choice { data_class_choice = new Fl_Choice(10, 10, 75, 20); data_class_choice->down_box(FL_BORDER_BOX); data_class_choice->labelsize(11); data_class_choice->textsize(11); data_class_choice->menu(menu_data_class_choice); } // Fl_Choice* data_class_choice { data_mode = new Fl_Choice(10, 38, 185, 20); data_mode->tooltip("text mode generates a \"const char*\" and a trailing NUL, compressed mode use" "s zlib to generate a binary block"); data_mode->down_box(FL_BORDER_BOX); data_mode->labelsize(11); data_mode->textsize(11); data_mode->menu(menu_data_mode); } // Fl_Choice* data_mode o->end(); } // Fl_Group* o { data_input = new Fl_Input(10, 78, 320, 20, "Variable Name:"); data_input->tooltip("Inline Data variables are declared \"const unsigned char []\" in binary mode " "and \"const char*\" in text mode."); data_input->labelfont(1); data_input->labelsize(11); data_input->textfont(4); data_input->textsize(11); data_input->align(Fl_Align(133)); data_input->when(FL_WHEN_NEVER); } // Fl_Input* data_input { data_filename = new Fl_Input(10, 116, 280, 20, "Filename:"); data_filename->tooltip("Name and path of file that will be inlined."); data_filename->labelfont(1); data_filename->labelsize(11); data_filename->textfont(4); data_filename->textsize(11); data_filename->align(Fl_Align(133)); data_filename->when(FL_WHEN_NEVER); } // Fl_Input* data_filename { data_filebrowser = new Fl_Button(290, 116, 40, 20, "@fileopen"); data_filebrowser->labelcolor((Fl_Color)134); } // Fl_Button* data_filebrowser { data_comment_input = new Fl_Text_Editor(10, 156, 320, 65, "Comment:"); data_comment_input->tooltip("Declaration comment in Doxygen format"); data_comment_input->box(FL_DOWN_BOX); data_comment_input->labelfont(1); data_comment_input->labelsize(11); data_comment_input->textfont(4); data_comment_input->textsize(11); data_comment_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); Fl_Group::current()->resizable(data_comment_input); data_comment_input->buffer(new Fl_Text_Buffer()); data_comment_input->add_key_binding(FL_Tab, 0, use_tab_navigation); } // Fl_Text_Editor* data_comment_input { Fl_Group* o = new Fl_Group(10, 231, 320, 20); { data_panel_ok = new Fl_Return_Button(200, 231, 60, 20, "OK"); data_panel_ok->labelsize(11); data_panel_ok->window()->hotspot(data_panel_ok); } // Fl_Return_Button* data_panel_ok { data_panel_cancel = new Fl_Button(270, 231, 60, 20, "Cancel"); data_panel_cancel->shortcut(0xff1b); data_panel_cancel->labelsize(11); } // Fl_Button* data_panel_cancel { Fl_Box* o = new Fl_Box(10, 231, 185, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o data_panel->size_range(343, 237); data_panel->end(); } // Fl_Double_Window* data_panel return data_panel; } Fl_Double_Window *class_panel=(Fl_Double_Window *)0; Fl_Light_Button *c_public_button=(Fl_Light_Button *)0; Fl_Input *c_name_input=(Fl_Input *)0; Fl_Input *c_subclass_input=(Fl_Input *)0; Fl_Text_Editor *c_comment_input=(Fl_Text_Editor *)0; Fl_Return_Button *c_panel_ok=(Fl_Return_Button *)0; Fl_Button *c_panel_cancel=(Fl_Button *)0; Fl_Double_Window* make_class_panel() { { class_panel = new Fl_Double_Window(342, 196, "Class Properties"); class_panel->labelsize(11); { Fl_Group* o = new Fl_Group(10, 10, 280, 20); o->hide(); { c_public_button = new Fl_Light_Button(10, 10, 60, 20, "public"); c_public_button->tooltip("Make the class publicly accessible."); c_public_button->labelsize(11); c_public_button->when(FL_WHEN_NEVER); c_public_button->hide(); } // Fl_Light_Button* c_public_button { Fl_Box* o = new Fl_Box(80, 10, 210, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { c_name_input = new Fl_Input(10, 20, 320, 20, "Name:"); c_name_input->tooltip("Name of class."); c_name_input->labelfont(1); c_name_input->labelsize(11); c_name_input->textfont(4); c_name_input->textsize(11); c_name_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); c_name_input->when(FL_WHEN_NEVER); } // Fl_Input* c_name_input { c_subclass_input = new Fl_Input(10, 55, 320, 20, "Subclass of (text between : and {)"); c_subclass_input->tooltip("Name of subclass."); c_subclass_input->labelfont(1); c_subclass_input->labelsize(11); c_subclass_input->textfont(4); c_subclass_input->textsize(11); c_subclass_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); c_subclass_input->when(FL_WHEN_NEVER); } // Fl_Input* c_subclass_input { c_comment_input = new Fl_Text_Editor(10, 90, 320, 65, "Comment:"); c_comment_input->tooltip("Class comment in Doxygen format"); c_comment_input->box(FL_DOWN_BOX); c_comment_input->labelfont(1); c_comment_input->labelsize(11); c_comment_input->textfont(4); c_comment_input->textsize(11); c_comment_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); Fl_Group::current()->resizable(c_comment_input); c_comment_input->buffer(new Fl_Text_Buffer()); c_comment_input->add_key_binding(FL_Tab, 0, use_tab_navigation); } // Fl_Text_Editor* c_comment_input { Fl_Group* o = new Fl_Group(10, 165, 320, 20); { c_panel_ok = new Fl_Return_Button(200, 165, 60, 20, "OK"); c_panel_ok->labelsize(11); c_panel_ok->window()->hotspot(c_panel_ok); } // Fl_Return_Button* c_panel_ok { c_panel_cancel = new Fl_Button(270, 165, 60, 20, "Cancel"); c_panel_cancel->shortcut(0xff1b); c_panel_cancel->labelsize(11); } // Fl_Button* c_panel_cancel { Fl_Box* o = new Fl_Box(10, 165, 185, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o class_panel->set_modal(); class_panel->size_range(343, 188); class_panel->end(); } // Fl_Double_Window* class_panel return class_panel; } Fl_Double_Window *comment_panel=(Fl_Double_Window *)0; Fl_Text_Editor *comment_input=(Fl_Text_Editor *)0; Fl_Return_Button *comment_panel_ok=(Fl_Return_Button *)0; Fl_Button *comment_panel_cancel=(Fl_Button *)0; Fl_Light_Button *comment_in_source=(Fl_Light_Button *)0; Fl_Light_Button *comment_in_header=(Fl_Light_Button *)0; Fl_Menu_Button *comment_predefined=(Fl_Menu_Button *)0; Fl_Button *comment_load=(Fl_Button *)0; Fl_Double_Window* make_comment_panel() { { Fl_Double_Window* o = comment_panel = new Fl_Double_Window(550, 280, "Comment Properties"); comment_panel->labelsize(11); { Fl_Text_Editor* o = comment_input = new Fl_Text_Editor(110, 10, 430, 230); comment_input->box(FL_DOWN_BOX); comment_input->labelsize(11); comment_input->textfont(4); comment_input->textsize(11); comment_input->textcolor((Fl_Color)58); Fl_Group::current()->resizable(comment_input); o->when(FL_WHEN_ENTER_KEY_CHANGED|FL_WHEN_RELEASE); o->buffer(new Fl_Text_Buffer()); } // Fl_Text_Editor* comment_input { Fl_Group* o = new Fl_Group(110, 250, 430, 20); o->labelsize(11); { comment_panel_ok = new Fl_Return_Button(370, 250, 80, 20, "OK"); comment_panel_ok->labelsize(11); comment_panel_ok->window()->hotspot(comment_panel_ok); } // Fl_Return_Button* comment_panel_ok { comment_panel_cancel = new Fl_Button(460, 250, 80, 20, "Cancel"); comment_panel_cancel->shortcut(0xff1b); comment_panel_cancel->labelsize(11); } // Fl_Button* comment_panel_cancel { Fl_Box* o = new Fl_Box(110, 250, 250, 20); o->labelsize(11); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(10, 10, 90, 243); o->labelsize(11); { comment_in_source = new Fl_Light_Button(10, 10, 90, 20, "In Source"); comment_in_source->tooltip("Put the comment into the source (.cxx) file."); comment_in_source->labelsize(11); comment_in_source->when(FL_WHEN_NEVER); } // Fl_Light_Button* comment_in_source { comment_in_header = new Fl_Light_Button(10, 40, 90, 20, "In Header"); comment_in_header->tooltip("Put the comment into the header (.h) file."); comment_in_header->labelsize(11); comment_in_header->when(FL_WHEN_NEVER); } // Fl_Light_Button* comment_in_header { comment_predefined = new Fl_Menu_Button(10, 70, 90, 20, "Predefined"); comment_predefined->labelsize(11); comment_predefined->textsize(11); } // Fl_Menu_Button* comment_predefined { comment_load = new Fl_Button(10, 100, 90, 20, "Import..."); comment_load->labelsize(11); } // Fl_Button* comment_load { Fl_Box* o = new Fl_Box(10, 132, 90, 121); o->labelsize(11); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o comment_panel->set_modal(); o->size_range(320, 180); comment_panel->end(); } // Fl_Double_Window* comment_panel return comment_panel; } void type_make_cb(Fl_Widget*,void*d) { const char *type_name = (const char*)d; if (Fl_Type::current && Fl_Type::current->can_have_children()) add_new_widget_from_user(type_name, Strategy::AS_LAST_CHILD); else add_new_widget_from_user(type_name, Strategy::AFTER_CURRENT); } Fl_Window *widgetbin_panel=(Fl_Window *)0; static void cb_widgetbin_panel(Fl_Window* o, void* v) { if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape) exit_cb((Fl_Widget*)o, v); else toggle_widgetbin_cb((Fl_Widget*)o, v); } Fl_Window* make_widgetbin() { { widgetbin_panel = new Fl_Window(600, 102, "Widget Bin"); widgetbin_panel->callback((Fl_Callback*)cb_widgetbin_panel); widgetbin_panel->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); { Fl_Group* o = new Fl_Group(3, 19, 79, 79, "Code"); o->labelsize(12); { Fl_Button* o = new Fl_Button(5, 21, 24, 24); o->tooltip("Function"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("Function")); o->image(pixmap[ID_Function]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(30, 21, 24, 24); o->tooltip("Class"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("Class")); o->image(pixmap[ID_Class]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(55, 21, 24, 24); o->tooltip("Comment"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("comment")); o->image(pixmap[ID_Comment]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(5, 46, 24, 24); o->tooltip("Code"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("Code")); o->image(pixmap[ID_Code]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(30, 46, 24, 24); o->tooltip("Code Block"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("CodeBlock")); o->image(pixmap[ID_CodeBlock]); } // Fl_Button* o { Widget_Bin_Window_Button* o = new Widget_Bin_Window_Button(55, 46, 24, 24); o->tooltip("Widget Class"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("widget_class")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Widget_Class]); } // Widget_Bin_Window_Button* o { Fl_Button* o = new Fl_Button(5, 71, 24, 24); o->tooltip("Declaration"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("decl")); o->image(pixmap[ID_Decl]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(30, 71, 24, 24); o->tooltip("Declaration Block"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("declblock")); o->image(pixmap[ID_DeclBlock]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(55, 71, 24, 24); o->tooltip("Inline Data"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("data")); o->image(pixmap[ID_Data]); } // Fl_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(87, 19, 79, 79, "Groups"); o->labelsize(12); { Widget_Bin_Window_Button* o = new Widget_Bin_Window_Button(89, 21, 24, 24); o->tooltip("Window"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Window")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Window]); } // Widget_Bin_Window_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(114, 21, 24, 24); o->tooltip("Group"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Group")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Group]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(139, 21, 24, 24); o->tooltip("Pack"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Pack")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Pack]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(89, 46, 24, 24); o->tooltip("Tabs"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Tabs")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Tabs]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(114, 46, 24, 24); o->tooltip("Scroll"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Scroll")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Scroll]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(139, 46, 24, 24); o->tooltip("Flex"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Flex")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Flex]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(89, 71, 24, 24); o->tooltip("Tile"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Tile")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Tile]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(114, 71, 24, 24); o->tooltip("Wizard"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Wizard")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Wizard]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(139, 71, 24, 24); o->tooltip("Grid"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Grid")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Grid]); } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(171, 19, 54, 79, "Buttons"); o->labelsize(12); { Widget_Bin_Button* o = new Widget_Bin_Button(173, 21, 24, 24); o->tooltip("Button"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Button]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(198, 21, 24, 24); o->tooltip("Return Button"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Return_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Return_Button]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(173, 46, 24, 24); o->tooltip("Light Button"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Light_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Light_Button]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(198, 46, 24, 24); o->tooltip("Repeat Button"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Repeat_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Repeat_Button]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(173, 71, 24, 24); o->tooltip("Check Button"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Check_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Check_Button]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(198, 71, 24, 24); o->tooltip("Round Button"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Round_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Round_Button]); } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(230, 19, 104, 79, "Valuators"); o->labelsize(12); { Widget_Bin_Button* o = new Widget_Bin_Button(232, 21, 24, 24); o->tooltip("Slider"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Slider")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Slider]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(257, 21, 24, 24); o->tooltip("Scroll Bar"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Scrollbar")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Scrollbar]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(282, 21, 24, 24); o->tooltip("Value Slider"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Slider")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Value_Slider]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(307, 21, 24, 24); o->tooltip("Value Output"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Output")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Value_Output]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(232, 46, 24, 24); o->tooltip("Adjuster"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Adjuster")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Adjuster]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(257, 46, 24, 24); o->tooltip("Counter"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Counter")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Counter]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(282, 46, 24, 24); o->tooltip("Dial"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Dial")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Dial]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(232, 71, 24, 24); o->tooltip("Roller"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Roller")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Roller]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(257, 71, 24, 24); o->tooltip("Spinner"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Spinner")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Spinner]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(282, 71, 24, 24); o->tooltip("Value Input"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Input")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Value_Input]); } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(339, 19, 54, 79, "Text"); o->labelsize(12); { Widget_Bin_Button* o = new Widget_Bin_Button(341, 21, 24, 24); o->tooltip("Input"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Input")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Input]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(366, 21, 24, 24); o->tooltip("Output"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Output")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Output]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(341, 46, 24, 24); o->tooltip("Text Edit"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Text_Editor")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Text_Editor]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(366, 46, 24, 24); o->tooltip("Text Display"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Text_Display")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Text_Display]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(341, 71, 24, 24); o->tooltip("File Input"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_File_Input")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_File_Input]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(366, 71, 24, 24); o->tooltip("Terminal"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Terminal")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Terminal]); } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(398, 19, 79, 79, "Menus"); o->labelsize(12); { Widget_Bin_Button* o = new Widget_Bin_Button(400, 22, 24, 24); o->tooltip("Input Choice"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Input_Choice")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Input_Choice]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(425, 21, 24, 24); o->tooltip("Menu Item"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("menuitem")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Menu_Item]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(450, 21, 24, 24); o->tooltip("Menu Bar"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Menu_Bar")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Menu_Bar]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(400, 46, 24, 24); o->tooltip("Menu Button"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Menu_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Menu_Button]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(425, 46, 24, 24); o->tooltip("Checkbox Menu Item"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("checkmenuitem")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Checkbox_Menu_Item]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(450, 46, 24, 24); o->tooltip("Sub Menu"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("submenu")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Submenu]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(400, 71, 24, 24); o->tooltip("Choice"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Choice")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Choice]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(425, 71, 24, 24); o->tooltip("Radio Menu Item"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("radiomenuitem")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Radio_Menu_Item]); } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(482, 19, 54, 79, "Browsers"); o->labelsize(12); { Widget_Bin_Button* o = new Widget_Bin_Button(484, 21, 24, 24); o->tooltip("Browser"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Browser")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Browser]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(509, 21, 24, 24); o->tooltip("Tree"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Tree")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Tree]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(484, 46, 24, 24); o->tooltip("Check Browser"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Check_Browser")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Check_Browser]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(509, 46, 24, 24); o->tooltip("Help Browser"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Help_View")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Help_View]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(484, 71, 24, 24); o->tooltip("File Browser"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_File_Browser")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_File_Browser]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(509, 71, 24, 24); o->tooltip("Table"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Table")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Table]); } // Widget_Bin_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(540, 19, 55, 79, "Misc"); o->labelsize(12); { Widget_Bin_Button* o = new Widget_Bin_Button(542, 21, 24, 24); o->tooltip("Box"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Box")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Box]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(567, 21, 24, 24); o->tooltip("Clock"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Clock")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Clock]); } // Widget_Bin_Button* o { Widget_Bin_Button* o = new Widget_Bin_Button(542, 46, 24, 24); o->tooltip("Progress"); o->box(FL_THIN_UP_BOX); o->color(FL_BACKGROUND_COLOR); o->selection_color(FL_BACKGROUND_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Progress")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); o->image(pixmap[ID_Progress]); } // Widget_Bin_Button* o o->end(); } // Fl_Group* o widgetbin_panel->set_non_modal(); widgetbin_panel->end(); } // Fl_Window* widgetbin_panel return widgetbin_panel; } // fltk-1.4.3/fluid/documentation/0000755000175000017500000000000015004135251016561 5ustar albrechtalbrechtfltk-1.4.3/fluid/documentation/copyright.dox.in0000644000175000017500000000007315004135251021712 0ustar albrechtalbrechtCopyright © 1998 - @YEAR@ by Bill Spitzak and others. fltk-1.4.3/fluid/documentation/Doxyfile.in0000644000175000017500000032553215004135251020706 0ustar albrechtalbrecht# Doxyfile 1.8.14 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See # https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "FLUID for FLTK @FLTK_VERSION@" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = NO # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines (in the resulting output). You can put ^^ in the value part of an # alias to insert a newline as if a physical newline was in the original file. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. # Minimum value: 0, maximum value: 99, default value: 0. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 0 # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = YES # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = @FL_HTML_INDEX@ # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = NO # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src/index.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_introduction.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_commandline.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_interactive.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_main_window.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_widgetbin_panel.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_edit_window.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_functional_nodes.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_widget_panel.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_setting_dialog.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_codeview_panel.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_tutorial.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/page_appendices.dox # @FLTK_SOURCE_DIR@/fluid # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: https://www.gnu.org/software/libiconv/) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. FILE_PATTERNS = *.H \ *.h \ *.c \ *.cxx \ *.dox # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # @FLTK_SOURCE_DIR@/src/drivers/ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # */src/*_win32.cxx \ # */src/*_mac.cxx \ # */src/*_x.cxx \ # */src/xdg* \ # */src/text-input* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # @CMAKE_CURRENT_SOURCE_DIR@/../test \ # @CMAKE_CURRENT_SOURCE_DIR@/../examples \ # @CMAKE_CURRENT_BINARY_DIR@ \ # @CMAKE_CURRENT_SOURCE_DIR@ # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = *.cxx \ *.h \ *.H \ *.fl # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/src \ @CMAKE_CURRENT_BINARY_DIR@/src # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = # fl_ \ # FL_ \ # Fl_ #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = @GENERATE_FLUID_HTML@ # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE tag can be used to specify if the generated HTML output # should be rendered with a dark or light theme. # Possible values are: LIGHT always generate light mode output, DARK always # generate dark mode output, AUTO_LIGHT automatically set the mode according to # the user preference, use light mode if no preference is set (the default), # AUTO_DARK automatically set the mode according to the user preference, use # dark mode if no preference is set and TOGGLE allow to user to switch between # light and dark mode via a button. # The default value is: AUTO_LIGHT. # This tag requires that the tag GENERATE_HTML is set to YES. # Note: since doxygen 1.9.5 HTML_COLORSTYLE = TOGGLE # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via Javascript. If disabled, the navigation index will # consists of multiple levels of tabs that are statically embedded in every HTML # page. Disable this option to support browsers that do not have Javascript, # like the Qt help browser. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_MENUS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: https://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = YES # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # https://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from https://www.mathjax.org before deployment. # The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/ # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /

UsJ'B!䯕gE7I(JW;"(Ģu's9ǁaJ#LLeEF|-.MX 0vZSNL\0 #[[[KMJ0 0> elnnZimmm=tRa oll|Rkjnn˗hQ[W0r(#+j5-j/^xʼnkfMd 0Mz׭~& hoo_JʠZPk)wA,)!h+ou[{Y^:ʴwjuݼ_?xuW^}>+0KxH"aW,[y+o \image latex w_settings.png "Settings Dialog" width=7cm The *Settings* dialog combines application preferences and project settings in a compact set of six tabs. The *General* tab contains a collection of application wide settings. They are stored as user preferences. The *Project* tab holds settings for the current project. They are saved with the `.fl` file. The *Layout* tab manages databases of preferred widget alignment. These preferences can be saved per user, or as part of the project, or exported for use in other projects. The *Shell* tab manages a database of quick access shell commands and scripts. Shell commands can be saved as a user preference and also as part of the `.fl` project file. The *Locale* tab sets the method of internationalizing texts in the project, commonly used for labels and tooltips. The *User* tab manages customization of fonts and colors in the widget browser. These settings are stored as user preferences.

\section setting_general Application Settings \image latex w_settings_general_tab.png "General Settings Tab" width=7cm __Scheme__: Select one of the graphics schemes built into FLTK. It's helpful to verify the look of various schemes for an application design. __Options__: Various options to make life as a developer more convenient. __Recent Files__: FLUID keeps track of recently opened files. __External Editor__: Users that don't like the built-in FLUID code editor can enter a shell command here that opens the content of Code nodes in an external editor. FLUID does its best to pick up on changed content or when the editor is closed. __Overlays__: The *Position Guides* are little red arrows that indicate if snap points are found. See the *Layout* tab for details. *Restricted Areas* are areas where widgets from within the same group overlap. They are visible in the project window as a diagonally hashed pattern. *Ghosted Group Outlines* show faint frames around groups that would otherwise be invisible in the project window.
\section setting_project Project Settings \image latex w_settings_project_tab.png "Project Settings Tab" width=7cm __Header File__, __Code File__: These fields are used to build the file path and name of the generated header and source file. If one field is empty the value defaults to `.h` and `.cxx` respectively. If a name starts with a `.`, FLUID assumes that the rest of the text is a file extension. The code file name is then generated by replacing the extension of the `.fl` project file name. \todo Document the exact way the source and header file paths are calculated for interactive FLUID, and for FLUID launched from the command line. __Include Header from Code__: If checked, the statement to include the header file is automatically generated in one of the first lines of the source file. __Menu shortcuts use FL_COMMAND__: Setting this option will replace FL_CTRL and FL_META as a modifier for shortcuts with the platform aware modifiers FL_COMMAND and FL_CONTROL, making shortcuts more portable between macOS and Windows/Linux. __allow Unicode__: If unchecked, Unicode characters in strings are escaped. If checked, the Unicode character is stored in the source code in UTF-8 encoding. __avoid early include__: FLUID by default includes `` early in the header file. If this option is checked, users can include other files before including the FL header. The user must then include `` later using a Declaration node.
\section setting_layout Layout Preferences \image latex w_settings_layout_tab.png "Layout Settings Tab" width=7cm Layouts are a collection of hints that help when interactively positioning and resizing widgets in the project window. Layouts come in a set of three for the application window, for dialog boxes, and for toolboxes. __Layout__: The layout pulldown menu lets users choose from a list of existing layouts. The plus button creates a new set of layouts based on the currently selected layout. The pulldown menu has items to rename, load, and save layouts. It can also change the location where the layout is stored. The FLUID beaker is for layouts that are predefined in FLUID, the portrait icon stores as user preference, the document icon stores the layout in the `.fl` file, and the disk icon lets users store layout in external files. __Window Margin and Grid__: Snap widget position to that margin in relation to the window. The grid snaps widgets to fixed intervals. __Group Margin and Grid__: Snap widget position to that margin in relation to the group. The grid snaps widgets to fixed intervals relative to the top left of the group. __Tabs Margin__: Snap the tab inside `Fl_Tabs` to the tab border and the offset given in Margins. __Widget Minimum, Increment, and Gap__: _Minimum_ sets the minimal width of a widget. _Increment_ is the size multiplier added to the _Minimum_ value. _Gap_ is the preferred distance to other widgets in the same group. __Label Font__, __Text Font__: The preferred label and text font and size for new widgets.
\section setting_shell Shell Commands \image latex w_settings_shell_tab.png "Shell Settings Tab" width=7cm __Shell Command List__: A list of all currently available shell commands. The portrait symbol in front of the name indicates that the script is stored in the user preferences. The document symbol saves them within the `.fl` project file. `[+]` adds a fresh new script to the list, `[++]` duplicates the currently selected script. `[DEL]` deletes it, and `[v]` offers import and export functionality. The `[T]` button shows the terminal window, and finally the `[Run]` button runs the selected shell script. Selecting a shell script will fill in the bottom half of the dialog. __Name__: This is the name of the script as it appears in the Shell Command List. __Menu Label__: Shell scripts that match the *Condition* flag are also available for quick access in the *Shell* menu in the main window and via shortcut key combinations. This is the text that is used for the menu entry. __Shortcut__: Assign a keyboard shortcut to this shell script for even faster access. FLUID does not check if a shortcut is already used elsewhere. Try to avoid collisions, especially when the script is part of a project file. __Store__: Choose where to store the settings of this shell script, either in the user preferences or as part of the `.fl` project file. __Condition__: Shell scripts can be quite different for different platforms hosting FLUID. This choice limits scripts to specific platforms. Multiple scripts can have the same shortcut if they have different conditions. __Shell Script__: This is a text field for the shell script. The `[v]` pulldown menu has a list of variables that are replaced with the corresponding value before running the script. The zoom button gives access to a much larger shell script editor. The options below are a list of actions that can be executed before running the script.
\section setting_i18n Internationalization The *Locale* tab can be used to configure optional internationalization. FLUID supports GNU `gettext` and POSIX `catgets`. FLUID supports internationalization (I18N for short) of label strings and tooltips used by widgets. The GNU gettext option also supports deferred translation of statically initialized menu item labels. The setting panel (`Alt+p`) provides access to the I18N options. \image html w_settings_i18n_gnu.png \image latex w_settings_i18n_gnu.png "I18N With GNU gettext" width=7cm FLUID supports three methods of I18N: none, GNU gettext, and POSIX catgets. The "none" method is the default and just passes the label strings as-is to the widget constructors. The "GNU gettext" method uses GNU gettext (or a similar text-based I18N library) to retrieve a localized string before calling the widget constructor. The GNU gettext option adds some preprocessor code to the source file: ``` #include #ifndef gettext_noop # define gettext_noop(text) text #endif ``` and the gettext call around strings in the source code: ``` new Fl_Button(50, 50, 54, 40, "Button"); // -> new Fl_Button(50, 50, 54, 40, gettext("Button")); ``` FLUID's code support for GNU gettext is limited to calling a function or macro to retrieve the localized label; you still need to call \p setlocale() and \p textdomain() or \p bindtextdomain() to select the appropriate language and message file. __Include__: controls the header file to include for I18N; by default this is \b , the standard I18N file for GNU gettext. __Conditional__: If this field contains a macro name, i18n will only be compiled into the product if this macro is defined. The build system should define the macro only if all required headers and libraries are available. If the macro is not defined, no headers are included and `gettext` passes text through untranslated. __Function__: controls the function (or macro) that will retrieve the localized message; by default the \p gettext function will be called. __Static Function__: names a macro that will mark static text fields for extraction with the `xgettext` tool. The default macro name is \p gettext_noop and will be defined as `#define gettext_noop(text) text` right after the `#include` statement. FLUID will call `gettext` on static texts later, after the textdomain was set by the user. \see [GNU gettext special cases](https://www.gnu.org/software/gettext/manual/html_node/Special-cases.html) \image html w_settings_i18n_psx.png \image latex w_settings_i18n_psx.png "I18N With POSIX catgets" width=7cm The "POSIX catgets" method uses the POSIX catgets function to retrieve a numbered message from a message catalog before calling the widget constructor. FLUID's code support for POSIX catgets allows you to use a global message file for all interfaces or a file specific to each .fl file; you still need to call \p setlocale() to select the appropriate language. This option adds some preprocessor code to the source file: ``` #include // Initialize I18N stuff now for menus... #include static char *_locale = setlocale(LC_MESSAGES, ""); static nl_catd _catalog = catopen("", 0); ``` and the catgets call around strings in the source code: ``` new Fl_Button(50, 50, 54, 40, "Button"); // -> new Fl_Button(50, 50, 54, 40, catgets(_catalog,1,6,"Button")); ``` __Include__: controls the header file to include for I18N; by default this is \b , the standard I18N file for POSIX catgets. __Conditional__: include the header file only if this preprocessor macro is defined. __Catalog__: controls the name of the catalog file variable to use when retrieving localized messages; by default the file field is empty which forces a local (static) catalog file to be used for all of the windows defined in your .fl file. __Set__: controls the set number in the catalog file. The default set is 1 and rarely needs to be changed. \section setting_user User Interface Preferences \image latex w_settings_user_tab.png "User Settings Tab" width=7cm This tab lets users change the font and color of text in the widget browser. The settings are stored in the user preferences. All changes are directly visible in the widget browser.
*/ fltk-1.4.3/fluid/documentation/src/flData.png0000644000175000017500000000032415004135251021250 0ustar albrechtalbrechtPNG  IHDR g PLTE`pGpL3.utRNS@*sIDATӍϽ kX(`!&Ё܈L`r6%P/\4Ԫ9KbAt dGHt'9)j\4WK]y0~$EIENDB`fltk-1.4.3/fluid/documentation/src/flCodeBlock.png0000644000175000017500000000032215004135251022222 0ustar albrechtalbrechtPNG  IHDR g PLTEGpL1tRNS AuIDATE 4Y)!EP"AO:~kYQ6!Ԁq%d2s *@PJ%$><-T1DUxZBXnXIENDB`fltk-1.4.3/fluid/documentation/src/flClass.png0000644000175000017500000000026015004135251021443 0ustar albrechtalbrechtPNG  IHDR g PLTEGpL1tRNS ASIDATcX   J3` & :aX Dbh0V!`*n'p&-;0SGx,c+]޵IENDB`fltk-1.4.3/fluid/documentation/src/page_tutorial.dox0000644000175000017500000004434015004135251022730 0ustar albrechtalbrecht/** \page page_tutorial Tutorials \tableofcontents \section fluid_hello_world_tutorial Hello, World! The first FLUID tutorial explains the FLUID basics. It creates a single `main()` function that opens an application window with a static text box inside. After launching FLUID we want to make sure that two very useful tool windows are open. The "Widget Bin" gives quick access to all available widgets and functional types. It can be opened via the main menu: __Edit > Show Widget Bin__, or using the shortcut __Alt-B__. The second very helpful tool box is the "Code View". The Code View gives a preview of the code as it will be generated by FLUID. All changes in the layout or in attributes are reflected immediately in the Code View. Choose __Edit > Show Code View__ or press __Alt-C__ to get this toolbox. Make sure that _Auto-Refresh_ and _Auto-Position_ are active in the Code View. Let's start Hello World from scratch. If there is already a previous project loaded, select __File > New__ or __Ctrl-N__. Before we can create a window, we need a "C" function that can be called when we run the program. Select __New > Code > Function/Method...__ or click on the \image{inline} html flFunction.png "Function/Method" \image{inline} latex flFunction.png image in the widget bin. A function is added as a first line to the widget tree in the main window, and a "Function/Method Properties" dialog box will pop up. For our Hello World program, delete all text in the top "Name(args)" text field. If this field is left empty, FLUID will generate a `main(argc, argv)` function for us. \image html fluid4.png "Function/Method Properties Dialog" \image latex fluid4.png "Function/Method Properties Dialog" width=7cm Click OK to apply the changes you made in the Function Properties dialog. You can get this dialog back at any time by selecting the function in the main window and pressing __F1__, or by double-clicking it. Note that the function will not show up in the Code View yet. FLUID will not generate code for functions that don't have any content, and only create a forward declaration in the header file, assuming that the function will be implemented inside another module. Keep the `main` function selected and add an `Fl_Window` to the function by selecting __New > Group > Window...__, by clicking the \image{inline} html flWindow.png "Group/Window" \image{inline} latex flWindow.png image in the Widget Bin, or by dragging the Group/Window image from the Widget Bin onto the desktop. A new application window will open up on the desktop. The thin red outline around the window indicates that it is selected. Dragging the red line will resize the window. Take a look at the Code View: the main function is now generated, including code to instantiate our `Fl_Window`. To edit all the attributes of our window, make sure it is selected and press __F1__, or double-click the entry in the main FLUID window, or double-click the window itself. The "Widget Properties" dialog box will pop up. Enter some text in the "Label:" text box and see how the label is updated immediately in the window itself, in the widget list, and in the Code View. Adding a static text to our window is just as easy. Put an `Fl_Box` into our window by selecting __New > Other > Box__, or by clicking on the \image{inline} html flBox.png "Other/Box" \image{inline} latex flBox.png image in the Widget Bin, or by dragging the Other/Box image from the Widget Bin into our newly created window. Most importantly, enter the text "Hello, World!" in the "Label:" field of the Box Widget Properties panel to achieve the goal of this tutorial. Now is also a great time to experiment with label styles, label fonts, sizes, colors, etc. . Finally, we should save our project as an `.fl` project file somewhere. Once the project is saved, select __File > Write Code__ or press __Shift-Ctrl-C__ to write our source code and header file to the same directory. Compile the program using a Makefile, CMake file, or fltk-config as described in the FLTK manual and the `README.txt` files in the FLTK source tree. \section fluid_1of7guis_tutorial 7GUIs, Task 1 In the first "Hello World" tutorial, we built an entire application in FLUID. It's a boring application though that does nothing except quitting when the close button in the window border is clicked. \image html 1of7GUIs.png "Task 1 of 7GUIs" \image latex 1of7GUIs.png "Task 1 of 7GUIs" width=5cm The second tutorial will introduce callbacks by implementing task 1, "Counter", of 7GUIs. 7GUIs has been created as a spin-off of my master’s thesis Comparison of Object-Oriented and Functional Programming for GUI Development at the Human-Computer Interaction group of the Leibniz Universität Hannover in 2014. 7GUIs defines seven tasks that represent typical challenges in GUI programming. https://eugenkiss.github.io/7guis/ . Task 1 requires "Understanding the basic ideas of a language/toolkit. The task is to build a frame containing a label or read-only textfield T and a button B. Initially, the value in T is “0” and each click of B increases the value in T by one." Our knowledge from tutorial 1 is enough to generate the `main()` function, and add an `Fl_Window`, an `Fl_Output`, and an `Fl_Button`. To make life easy, FLUID comes with a built-in template for this tutorial. Just select __File > New from Template...__ and double-click "1of7GUIs" in the Template Panel. We will need to reference the output widget in our callback, so let's assign a pointer to the widget to a global variable and give that variable a name. Open the Widget Properties dialog by double-clicking the output widget. Change to the "C++" tab, and enter "`counter_widget`" in the "Name:" field. The "Count" button is the active element in our application. To tell the app what to do when the user clicks the button, we create a callback function for that button. Open the widget properties dialog for the button. In the "C++" tab, we find the input field "Callback:". The callback is called exactly once every time the user clicks the button. Our strategy here is to read the current value from the `counter_widget`, increment it by 1, and write it back to `counter_widget`. The FLTK documentation tells us that we can use `Fl_Output::ivalue()` to get text in `Fl_Output` as an integer, and we can write it back by calling `Fl_Output::value(int)`. When the value is changed, FLTK will automatically redraw the output widget for us. So here is the callback code: ``` int i = counter_widget->ivalue(); i++; counter_widget->value(i); ``` That's it. This is a complete interactive desktop application. Compile, link, run, and test it to see how it works. \section fluid_cubeview_tutorial Cube View This tutorial will show you how to generate a complete user interface class with FLUID that is used for the CubeView program provided with FLTK. \image html cubeview.png "CubeView demo" \image latex cubeview.png "CubeView demo" width=7cm The window is of class CubeViewUI, and is completely generated by FLUID, including class member functions. The central display of the cube is a separate subclass of Fl_Gl_Window called CubeView. CubeViewUI manages CubeView using callbacks from the various sliders and rollers to manipulate the viewing angle and zoom of CubeView. At the completion of this tutorial you will (hopefully) understand how to: -# Use FLUID to create a complete user interface class, including constructor and any member functions necessary. -# Use FLUID to set callback member functions of custom widget classes. -# Subclass an Fl_Gl_Window to suit your purposes. \subsection fluid_cubeview The CubeView Class The CubeView class is a subclass of Fl_Gl_Window. It has methods for setting the zoom, the \e x and \e y pan, and the rotation angle about the \e x and \e y axes. You can safely skip this section as long as you realize that CubeView is a sublass of Fl_Gl_Window and will respond to calls from CubeViewUI, generated by FLUID. \par The CubeView Class Definition Here is the CubeView class definition, as given by its header file "test/CubeView.h":
\code #include #include #include class CubeView : public Fl_Gl_Window { public: CubeView(int x, int y, int w, int h, const char *l = 0); // This value determines the scaling factor used to draw the cube. double size; /* Set the rotation about the vertical (y) axis. * * This function is called by the horizontal roller in * CubeViewUI and the initialize button in CubeViewUI. */ void v_angle(double angle) { vAng = angle; } // Return the rotation about the vertical (y) axis. double v_angle() const { return vAng; } /* Set the rotation about the horizontal (x) axis. * * This function is called by the vertical roller in * CubeViewUI and the initialize button in CubeViewUI. */ void h_angle(double angle) { hAng = angle; } // The rotation about the horizontal (x) axis. double h_angle() const { return hAng; } /* Sets the x shift of the cube view camera. * * This function is called by the slider in CubeViewUI * and the initialize button in CubeViewUI. */ void panx(double x) { xshift = x; } /* Sets the y shift of the cube view camera. * * This function is called by the slider in CubeViewUI * and the initialize button in CubeViewUI. */ void pany(double y) { yshift = y; } /* The widget class draw() override. * * The draw() function initializes Gl for another round of * drawing, then calls specialized functions for drawing each * of the entities displayed in the cube view. */ void draw(); private: /* Draw the cube boundaries. * * Draw the faces of the cube using the boxv[] vertices, * using GL_LINE_LOOP for the faces. */ void drawCube(); double vAng, hAng; double xshift, yshift; float boxv0[3]; float boxv1[3]; float boxv2[3]; float boxv3[3]; float boxv4[3]; float boxv5[3]; float boxv6[3]; float boxv7[3]; }; \endcode \par The CubeView Class Implementation Here is the CubeView implementation. It is very similar to the "CubeView" demo included with FLTK.
\code #include "CubeView.h" #include CubeView::CubeView(int x, int y, int w, int h, const char *l) : Fl_Gl_Window(x, y, w, h, l) { Fl::use_high_res_GL(1); vAng = 0.0; hAng = 0.0; size = 10.0; xshift = 0.0; yshift = 0.0; /* The cube definition. These are the vertices of a unit cube * centered on the origin.*/ boxv0[0] = -0.5; boxv0[1] = -0.5; boxv0[2] = -0.5; boxv1[0] = 0.5; boxv1[1] = -0.5; boxv1[2] = -0.5; boxv2[0] = 0.5; boxv2[1] = 0.5; boxv2[2] = -0.5; boxv3[0] = -0.5; boxv3[1] = 0.5; boxv3[2] = -0.5; boxv4[0] = -0.5; boxv4[1] = -0.5; boxv4[2] = 0.5; boxv5[0] = 0.5; boxv5[1] = -0.5; boxv5[2] = 0.5; boxv6[0] = 0.5; boxv6[1] = 0.5; boxv6[2] = 0.5; boxv7[0] = -0.5; boxv7[1] = 0.5; boxv7[2] = 0.5; } void CubeView::drawCube() { /* Draw a colored cube */ #define ALPHA 0.5 glShadeModel(GL_FLAT); glBegin(GL_QUADS); glColor4f(0.0, 0.0, 1.0, ALPHA); glVertex3fv(boxv0); glVertex3fv(boxv1); glVertex3fv(boxv2); glVertex3fv(boxv3); glColor4f(1.0, 1.0, 0.0, ALPHA); glVertex3fv(boxv0); glVertex3fv(boxv4); glVertex3fv(boxv5); glVertex3fv(boxv1); glColor4f(0.0, 1.0, 1.0, ALPHA); glVertex3fv(boxv2); glVertex3fv(boxv6); glVertex3fv(boxv7); glVertex3fv(boxv3); glColor4f(1.0, 0.0, 0.0, ALPHA); glVertex3fv(boxv4); glVertex3fv(boxv5); glVertex3fv(boxv6); glVertex3fv(boxv7); glColor4f(1.0, 0.0, 1.0, ALPHA); glVertex3fv(boxv0); glVertex3fv(boxv3); glVertex3fv(boxv7); glVertex3fv(boxv4); glColor4f(0.0, 1.0, 0.0, ALPHA); glVertex3fv(boxv1); glVertex3fv(boxv5); glVertex3fv(boxv6); glVertex3fv(boxv2); glEnd(); glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINES); glVertex3fv(boxv0); glVertex3fv(boxv1); glVertex3fv(boxv1); glVertex3fv(boxv2); glVertex3fv(boxv2); glVertex3fv(boxv3); glVertex3fv(boxv3); glVertex3fv(boxv0); glVertex3fv(boxv4); glVertex3fv(boxv5); glVertex3fv(boxv5); glVertex3fv(boxv6); glVertex3fv(boxv6); glVertex3fv(boxv7); glVertex3fv(boxv7); glVertex3fv(boxv4); glVertex3fv(boxv0); glVertex3fv(boxv4); glVertex3fv(boxv1); glVertex3fv(boxv5); glVertex3fv(boxv2); glVertex3fv(boxv6); glVertex3fv(boxv3); glVertex3fv(boxv7); glEnd(); } // drawCube void CubeView::draw() { if (!valid()) { glLoadIdentity(); glViewport(0, 0, pixel_w(), pixel_h()); glOrtho(-10, 10, -10, 10, -20050, 10000); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef((GLfloat)xshift, (GLfloat)yshift, 0); glRotatef((GLfloat)hAng, 0, 1, 0); glRotatef((GLfloat)vAng, 1, 0, 0); glScalef(float(size), float(size), float(size)); drawCube(); glPopMatrix(); } \endcode \subsection fluid_cubeview_ui The CubeViewUI Class We will completely construct a window to display and control the CubeView defined in the previous section using FLUID. \par Defining the CubeViewUI Class Once you have started FLUID, the first step in defining a class is to create a new class within FLUID using the New->Code->Class menu item. Name the class "CubeViewUI" and leave the subclass blank. We do not need any inheritance for this window. You should see the new class declaration in the FLUID browser window. \image html fluid1.png "FLUID file for CubeView" \image latex fluid1.png "FLUID file for CubeView" width=7cm \par Adding the Class Constructor Click on the CubeViewUI class in the FLUID window and add a new method by selecting New->Code->Function/Method. The name of the function will also be CubeViewUI. FLUID will understand that this will be the constructor for the class and will generate the appropriate code. Make sure you declare the constructor public. Then add a window to the CubeViewUI class. Highlight the name of the constructor in the FLUID browser window and click on New->Group->Window. In a similar manner add the following to the CubeViewUI constructor: \li A horizontal roller named \p hrot \li A vertical roller named \p vrot \li A horizontal slider named \p xpan \li A vertical slider named \p ypan \li A horizontal value slider named \p zoom None of these additions need be public. And they shouldn't be unless you plan to expose them as part of the interface for CubeViewUI. When you are finished you should have something like this: \image html fluid2.png "FLUID window containing CubeView demo" \image latex fluid2.png "FLUID window containing CubeView demo" width=7cm We will talk about the \p show() method that is highlighted shortly. \par Adding the CubeView Widget What we have is nice, but does little to show our cube. We have already defined the CubeView class and we would like to show it within the CubeViewUI. The CubeView class inherits the Fl_Gl_Window class, which is created in the same way as an Fl_Box widget. Use New->Other->Box to add a square box to the main window. This will be no ordinary box, however. The Box properties window will appear. The key to letting CubeViewUI display CubeView is to enter CubeView in the Class: text entry box. This tells FLUID that it is not an Fl_Box, but a similar widget with the same constructor. In the Extra Code: field enter \#include "CubeView.h" This \p \#include is important, as we have just included CubeView as a member of CubeViewUI, so any public CubeView methods are now available to CubeViewUI. \image html fluid3-cxx.png "CubeView methods" \image latex fluid3-cxx.png "CubeView methods" width=7cm \par Defining the Callbacks Each of the widgets we defined before adding CubeView can have callbacks that call CubeView methods. You can call an external function or put a short amount of code in the Callback field of the widget panel. For example, the callback for the \p ypan slider is: \code cube->pany(((Fl_Slider *)o)->value()); cube->redraw(); \endcode We call cube->redraw() after changing the value to update the CubeView window. CubeView could easily be modified to do this, but it is nice to keep this exposed. In the case where you may want to do more than one view change only redrawing once saves a lot of time. There is no reason to wait until after you have added CubeView to enter these callbacks. FLUID assumes you are smart enough not to refer to members or functions that don't exist. \par Adding a Class Method You can add class methods within FLUID that have nothing to do with the GUI. As an example add a show function so that CubeViewUI can actually appear on the screen. Make sure the top level CubeViewUI is selected and select New->Code->Function/Method. Just use the name \p show(). We don't need a return value here, and since we will not be adding any widgets to this method FLUID will assign it a return type of \p void. \image html fluid4.png "CubeView constructor" \image latex fluid4.png "CubeView constructor" width=7cm Once the new method has been added, highlight its name and select New->Code->Code. Enter the method's code in the code window. \subsection fluid_addconst Adding Constructor Initialization Code If you need to add code to initialize a class, for example setting initial values of the horizontal and vertical angles in the CubeView, you can simply highlight the constructor and select New->Code->Code. Add any required code. \subsection fluid_gencode Generating the Code Now that we have completely defined the CubeViewUI, we have to generate the code. There is one last trick to ensure this all works. Open the preferences dialog from Edit->Preferences. At the bottom of the preferences dialog box is the key: "Include Header from Code". Select that option and set your desired file extensions and you are in business. You can include the CubeViewUI.h (or whatever extension you prefer) as you would any other C++ class. */ fltk-1.4.3/fluid/documentation/src/fluid_flow_chart.png0000644000175000017500000024243215004135251023400 0ustar albrechtalbrechtPNG  IHDR̮miCCPicc(uKPO|P *DA.E*Xuib iWAp]|  "n)\#T'_ [;$&c|rAkxz"tCp8U!UoT*e5 ( pHYs  ~tEXtRaw profile type exif exif 62 45786966000049492a0008000000010069870400010000001a00000000000000020002a0 040001000000f606000003a00400010000009602000000000000 Xl<ZtEXtRaw profile type iptc iptc 26 50686f746f73686f7020332e30003842494d0404000000000000 iUtEXtRaw profile type xmp xmp 2423 3c3f787061636b657420626567696e3d22efbbbf222069643d2257354d304d7043656869 487a7265537a4e54637a6b633964223f3e0a3c783a786d706d65746120786d6c6e733a78 3d2261646f62653a6e733a6d6574612f2220783a786d70746b3d22584d5020436f726520 342e342e302d4578697632223e0a203c7264663a52444620786d6c6e733a7264663d2268 7474703a2f2f7777772e77332e6f72672f313939392f30322f32322d7264662d73796e74 61782d6e7323223e0a20203c7264663a4465736372697074696f6e207264663a61626f75 743d22220a20202020786d6c6e733a657869663d22687474703a2f2f6e732e61646f6265 2e636f6d2f657869662f312e302f220a202020657869663a506978656c5844696d656e73 696f6e3d2231373832220a202020657869663a506978656c5944696d656e73696f6e3d22 363632222f3e0a203c2f7264663a5244463e0a3c2f783a786d706d6574613e0a20202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020202020202020202020202020202020202020200a2020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020202020202020200a202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020200a20202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020200a2020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020202020202020202020202020202020202020202020200a202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020200a20202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020202020202020202020202020200a2020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020200a202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020200a20202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020202020202020202020202020202020202020202020202020202020200a2020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020202020202020202020202020202020200a202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020200a20202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020202020202020200a2020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020200a202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020200a20 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020202020202020202020202020202020202020202020200a2020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020202020202020202020200a202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020200a20202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020200a2020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020202020202020202020202020202020202020202020202020200a 2020202020202020202020202020202020202020202020202020200a3c3f787061636b65 7420656e643d2277223f3e ѐ IDATx xT3!@n,& ";Y@oTjKk]PQ\B&R(hY4"n* DddI2{LcGg'^ܩxIUjwǥT֚?<uI!ssvN.uAbk8 (ZR:/_+q9Wޫ;z"}o 봷]1zZ&gsڨ8{[|)2F$,:I9"ST"Ywꋯ[=֎q}b)5I"3A$"y-JS{}kT:tvIbqɎ`=H c|LD.=̦W|<k8_ 8 $1ͽ#E_"Ͼ<{YUX5iPՌ&dʎ;J9 :u[nJ r7im=@شi;#eÆ ~I!ҕ'{꥞znݺQ$af޼ycǪ5LC408PLũ,5zhA$aOzGoTÇWݺuS?OU5(0D"g靪^u/oܹ$b=@X{#E$7uTզMqޜ<73V TFFFɾK -ڧOϜ9SM81p@4Ľe<;=s!q \=%n6_CzǫfZǶSO=۰azgSb{թS'ώ;|&L(1$!l"/ocǎj۶m.@bV\YߙvڥڶmK f޽[ko݊+ 40,YR\J$+^$a)'''\>|8XF{,Cp:D/{sN^H^zi}bInby zq=@Xi}gݠO:%J@,+**R :ּWqq; @aox5jP"q.k[s Kd#A{1 ,8.+xq>8$P* ,8f=z@ WB8W` W$+H s{pU"8W#{pE/$s{pE/$s{pE/$s{pE/$s{pE\ \8W` W$+HU"EpG$@bQ ~Db$*"8W#{@ xh;b76H+=D5{(IcnGƙ@U!f&IzcX{7 \$k%tX(-H =D@I=Y'3iC'KT z!+0SvUVrrrjlݺ5~׮]YXXXԴvjGkz粮=;tc>w~w7:uσR'ce G'ӱc.u ֭[جY֭[!C0.\2jٓ^zW.-P=k׮Ͼo4ufM2,w~H ̛7oҴiӦR` ɓ'z9x"=AbM'M_tM_|ѷ]o B?~Grj Z<su~ԧT=D{zF֯_p{޽ՠAe]:tZh֭jԨAA#G={>@-]Tnvi@WVޡĪ=\$#H "ۧٲeK&NnV<;e$#ԡC|y䑻'(Ūa֬ysu~ԦT_EH4e裏C䨙3gz@[GzR~׭[׋Tx{\o 9w\ L~}բ{XWckL1?R'T%{Xe+:tPg.y$cPxN5o]>$U8ւ u=魷[OzQhO .܇D1ca=TuWShi-_ܷ,سgw.. Ikׯ*sƍե^JA!d8SVꫯ\͛7K!YZ"*O;? `6`.^x~С$r-Ř$~)3KzP8YYY\'\HL۷4JPe޼yƌ3]_6nX8pAL=ڗ<]Cqq~PGz ^f2Q(8%33L2tT6{/;.@L8=+Φ鄲-={Kz?Ue]zAO):׽{w wFbaI'Q̤]ff> )3tbOKMMͦů VZ~=߯4iB dV^ q"ΪWP_z |lLMM-ԣg+4PP]H ,$$ ucǎ-cHN g&+ΦQ2pAbaGv3zM:~ogN"!%I=39 J.H 脝gffN7xiiiBGM8SV4h82U*s/|8?b=V iii$rqFRh@X$~ۂ JǙN*[q6#z Hr/++kk׮wޥ>aP8[YG@Xr(pQQYYYǒ,R+j@y뭷_y~=dĖ-['ײ$pq8S8s9 :=sP18vn_R/%%EJÙ0,-$VN8Q"ᒞN ?Ոi @*k(==ѣ6mڨk\K 2(@8#*Un{fϹB'q pO Hn|M:BR!3%qcJ֥2 ' @X$^eׯܹ3PǙX*qv2 ' 1'Fffrzz:lsG@s^?rH_:uꨃ 3eřrę8 O. +_C9Ƭ@Xp)#قP +8D z߿_5k#ի{ q%q֢E ^_VM)zq~c Sns̙$siʤ$z)+魧CFe 1'$UntXS0Y|qřSpF=T K*''M|eرc) ,ƄggcƌpF=T K*33s~ȑM6:Gs=mf8 @Љєn"vYYY~q4nܸl~;{6r˖-UJJJI4L9믿A/0D {e%K$IvBB)XP3T>Iw${e%KvcxFmԣgJǙf4"jb09/5.Iw${8ci7l+_Lael'}9=Z02 IK.DG=Px 4P=THnnU7VWnĒ֣wF \ٳ^'rrr_;G]H|eee,|\޶m$pbۗ_~}]n2bvtQ p  Y=C3Z|o{||JMM?Ddd&Mon뮻TϞ=턟h"u嗫QY:΄YZZ 'Eb~zd~1=G^Խψ#z)77HB:t9眣:EvO R\e. "?:|jժ$=TړO yxUWM6O s~;uH:v=oҤvکΝ;ƍ<6ęԓ84hPQ- B|Æ +1D'bKӦManP>@+Pd6\{̙3\' 4]zI!C<|{֋ĒܟW_US/Fio?uꔚ:u*,,{M8kH>a„ _*{VyyyѣK/-[fA)!Ν;WܹS]}ժ[n>z(`g,i&~~X}DnX@BIW_fV}H{I>aK7rLo\ڷonF_}tR97oVGQ]t}J=,O?~\￷_]5k~aÆu몂.ٰa*..V=z롶m^S3fPuԱ'=/^VX}lذ{xw}:vF]21دݯ_7gbbbbbbbbIL#=׿PrslٲI{%|^AO˖-wu9ѣG7gwٺuaÆs^{5G}9r䈽]'{9kKI2P{xg'۵kg g}j\۷oG$Ųe=b2DꫯC9'FL:^נAς <~]y,I@NժU>z-1cHv{=_͛&O{-{tBQ+I5kxo.^9yy%dؓ6OzX$geԣhn=|/OtzT SF<Ă h/ /3EzǏ?Ojj, ҃E'nv~qY"Kønܹ4ib?o۶m~cO/B{O>YH$88{qF&+,XrO'b1fbJ Rf&4g uݲpB69eGN{^׮]mu|駾ג{ԤK.{t풜$'++WV$Q> &Į°ǞDS'P }L?6 Wwީ&۳gO}}wǏo`=/ڭ5%FƼc5%VԟGN8׷d8x-[J&yrO)]&M|ZnmO3ϨFٳgZjٯWvmӟT=Sz|׬YSeff*o\իW>HhB~%QvԀkf/8lGe_رcePWx㍘,g}cQF'yauetgz,Yb^ko{ ]5\>urN~2dzGK222zά7;<}Yz?ͬnϑhI]t2BtĚ1k1?bYG4hPhDž:oHRRajD!Pd͛)O" e4JD?؞_tE;wV%'I:9-Ru2׉0gbwzK_QK2 =77מjʗ\RgI g~U $svWNY*ZܹӞ4(k^r%vb/??߯~ts sI95I I>ҩSgRR=o~~$)錋͛sID"\wjZz@رc__/_sϵӬu3@HT7衇R.\['}Qݺuyڵm޼ HHH8~s.?靟˘-yΆ@ b&tK IDAT /,w~OY'st_@?!!d(U2|p9r~'ۿ/}ɚR?x򗿸BqСCj̘1=̡߬Y5,эzuw EUֽI{޽[bbȑ2.MM6Mծ][{Hj֬Y~Czݻԩeޓ{9{P4fOz~3oK:v옺kx9P5jh 5N#I}V}a'#?ًO4?~jݺ}=~ۤWH$CJ=I9IsQ{r [Ѻ<>R0¦~Zz`uqII%ԅR6v]'?~2?|p5jx2-]{1tZ`'>>L2s{:,{Jܹs}rJי4iN:;w l3/hҤ>>^?k,ߺ^x^7l0}7o[/rԩS=>gyڎ.kwqꜰ/rc#o!Ids@7輌Voٳ=CW_mUg…~^zsmVr-{ĶUV{n1j֬y枴4σ>{2I]gӧۯu5֭[{=:)111h$O?31qU7sڟK$KD!01111111Ud6Z㜜M"d}7۟Co-[f'}g}vnl8, [ė ~!{/Nɶ &%Daa}{ƍߡC_cvQQQeִiS{i7Ğw&d$7$uVK.%Kxs=1ϗbJBzR_UyĞ2]Y9)el 2iƳaÆu$dKIɶᄏ6IɶF^\\'77Wg~vu('~Yk:k׮T͉=|M_)kAT6U+O{#v )v9^2d ֪AvݧOcooEFFz|i %O>Q[nU͛7'˕9 yK+ҞW+ߐ|{=SW^ye7lz-g1N[xwygU_ :t2Wsۨo,駟>Ȯot7Z^2^˪{ñ z%xk'μ$*ȔW_ԲeKuW< ?;;{_~[nԨJOO'08Sz@#iʈ%}-%N[om۶u$*֓Ʃ}b,$9BRSS WęFѦM;up܏1+;(HT͛7'K.Y'ȢE|87~x~Q*((P/K१P 3aK/~,Tflg d򤤤X/4uMuޝ@@H͝;ׯG4oN{@2A'~́PĖ;ud_C#@#Pvek׮], _oAhxCIwtp8PejϞ=θ ֐d{͛7u͚5Sss̭H[zz:APǙkls?P3p} o߾$*w}g7B5jDV}埳$\L2 'p]؊3 RZ%kǏ'PB ֑|Qcv}ڵS#FtlՏ%'qfwIJ y$*uy4ثz8] gř=?o k(zGbE}bo֭YN褌 ONYoř gk=xE}b/++I\Pbzbňa8D =/zTZ(|dxDI=J3c*555Ϛg5T-:{/{S ǒ`[/}$^p-Z[8KOOh jc@{ns9==]ժz/8SW#cEb_G]b/l`u8S8[8b==fֻ袋W\GHɽL_|ӧ zx|(>WC!S 3Ly{! fk({ |Qcol޼/" gaqq>u2 3 b=)J=2330x]wjժG3믿^l"%1{^|y;uT,uPYa8Y.Cp@LPu$Nsݳ;r֭{!ӈ3uaOSuڽbJݧ഑|hivG+[D *[/55Ufk(9Eb=zر+VӉ=z!T8Sl-%1{^$*_wRfϺ@;}.s3ařr~$&R25TEb=s2pD]#Y\VVrjjj5˥d &E5@e*]b4|齷dɒ}o]BB8>S{Y˵jՒa8k*3A=s"߼$Xᔤ^b"mlm˾ǒ{8ZqPDbE`[#J%+|p8l-%Pc@:)oT2eff6Ԁ&eř gP2" |rIj@gĊ3 P2E={Ud񜜜G6n[d{a)3pT_C=.I;}~Ĉm۶vz!Tto=S#G8Hb=q&X9.I=3P,ϚR2=q.׉?S<[nѢ5jT31}tLxz=@#Pu"'׬Y7 3'BaժU~˩2[C=|HTZƿFK,['=H!6mڤ.]kYK" THT+1u[&PxﯮJ{Ny(z|wy!o߾Kuڵ ^U(/3~~_|<@5˥(Ğ(E*z@" pr '?cƌQ .{GL" s0 V5m۶\뢷~(MpNNտo_ɾ R>h'k1|s{ݨ\u:JqӧGPFFڰaA"rssmݦzi'L^xrA/=\4g&I@I@N<W\w_ibiiiꫯV_|Su ۉ&rQ_۸qZrZ~}{ꥲ]?Onz+Y5ea.ΏQy#z HPPPPժUrrrnZo׮]H,,,L+%њV9%z_w':k9氾8ʘ:O8c/X_NZO֭[dfNoTn݊ ׯ'Hoz=}6Qd>aå0I{ٳg饗RV^]hB9tU\Q-~{~a3qmӖL7jԨdJꚣDR燹XhuP$l͛?mڴP(HɓC=ė -Zϟ͛7Ӹ^5ql~o1oܸqE.Q!??E{1"{zo&ϋ/cC9ˆ_#P,{,~m Q׬Y7ިO|5 k״[F9n/;X6̜4&\B,R? O^]>e˲ Y~*11dӦMOkdΝOtNiƭHx֚5|s;h埗{{5J_>޽{A.LuAhBխ[WըA{*..VGQ{Q|Ztr?X, j0%-Bqo)aÆql2 1Pa.13ۧٲeK&NnV@u$1b:to#<{/->^|yUW]$yC {K(Yc3fsu~4Kb+T_<--GmѣQ3g%!vsn\ի۾nݺ ژCO;iO}: Fp?sЖ\;Xb{7ޘi;()\b*z=ߺkV͝;瑌Ay!>>ޞ"4\FUWֵC6^4@b*"s\С={v#nuT܇+@$(mM*Y3Oz9WsNR ~u`Io]OzO .X܇+@$`ͪ֯S8#{#<)rjj꫉4_K,s'=@Y]뭧s= oCT%3vکWw뮻8u֩M6;2Аf@l{ɔŋO1_uUK/#-Z{?{%!@Ytodk{!DEmbϔeϥaD<ȑGřnT۷4J{0hƌI~h_Λ7o1cRlܸ:pG35zh_glB`'ZX"wСIeĔ_RpyC aHND+sYyb#?/S*zX"SZZGg~ l:̆g#.:lz?ckѪ"8WN޽{ŋ!=TB}~mo4sY8b,bW}o=_׾7|z\JQdC$~rS.LуR)'tݻKeig…S#Fpw""DYfyfϞ&O~Jsuau{:wΝ*>U\E9;x)dqDP EPrvS/ǏH"deę gfOQP^zIծ]^O?֭A%};@CswmW3V\\'|4|O>/(-+xaŬGcO"-''gXucǎH"d1&83f4~E',]l߾={{χ~̗_~?ѣUrrݻwk "=k{@q>7..5]d t`y7,J1==33s~ȑM6|1q6*͙3/$ڶmQV@Xre_^:tk˗7k>}\W,+=X"痖8tZσC  z єnOF%,87n\s?V5ʕ+U֭UNF̊+Թ+ϛoټy$TΝyԄ 6jԨٳ_VTT.MM6-q7fZP7mtKJJoiK{ϯԅ^1??#]tQ]w߶˓ <8UZy^zU[lI!+~6N:S;!"5f[1=9o-lRݟ af)g]7e@z'=ǏY=r<ݹ^y3Ϩ:K{.]jkݺu{̓{y D D,MbS\QXu)нP>4| 5cJ8w?)IM<^:uH[dj֬Yu뭷 y'Np۵k'S3g|NrwZjСCO?4O$nƤB_b<Kgٲeo$aoYz+#IIDFXKbW$v9uc}񒖖"r(5Δ3͊i N|4 9tPױc;a69jԨn6{{J&|g׻v\fMu%r}{zɓ'{'sس| _=zS̋+B]|Q{`GViSa:b i8ҥKUʃk _C%ֲEݻ 85x')))#^PsQm۶M >oJg]2֯_/<5f̘ns[hQ{tѪQF%ȑ#`nD \P~a=LG4 ߻w"]sss{̲>g>(Ǐ?ibMT~ %`G,;َTX,IŠ(ł(DE@鞀Ygfv~&ݝ};<ϳfZNkNF_ԱzioU2FJzD%gϊ9M ce?N >AP+}m۶O>DIw2?/_Nw^ ZOjʾFҭZjN6m39AZ}Z6qZ~2ҳcǎ3N8ᄡlu]yy竬,|&6nܨ7ͭEX@|d@| =1{<|rbS>|xB"E];=z{2tt1.L/]'B.HŞ}"OQFd Z e.뙕Bn|;#X'llė2Ո/e_N-S=uJ|;A<նo^6G|!{2vhKJ7pJ=ܵ2uT]']]~Bt:yŊU@s+hЦM$=COT]w]^W o}s=j޼yr1P-Ǐ>C]ޔ%^徟,7{gzFXDžB$ k^o3%@o]vM޽{)=@寿Z1ڷobᎿlv١C2߲et}#8o{v&M6|֭>g[벲2u\_|AO8ᄕ2뭷dU=Ν_y78j+LK$2K+(((.]KŒ9J-ZT5+*~o!oN}[;,}JROYs9E 3fxu6? P$ ,y82_~e\ljJkqWXQ"c/gdd8 w65k֬ļiliy^y2߀N]t(KB^}Ukݺut!/XOm߾]w}MVV$Aƭ^.M :_^|_WϪ-[52$D2 ꉩ8,((41iH'uizO%Ke0a2H]y!Vqqw ^xA']}/ZrOSP߫BkL-c߃ JUhݕOTe]UW];|K.{!aSO=}3<םs9,7nWϮ];XxAgy|l:I(ǘ':֚_+>H߄:gWyݞkժ1"ΓN(o5kVjns{ڵkW9^{~g}֛?GgͲ駟3_wŊryCL4oVkyԻ7,mذ9+,\P/1g{#N(5>uɳa#?4mڴ&MNU^S?X"}g%۷oOK7ʲ^O?4T^/wN_pa=h0s>^̜93}dbbbbZOLҕbRߋ;uVru>3ri-\gNs=W4idvkn 'vv}Gzzvo~$}}u2^{qbiDaW#7PkPnD 35 1%SwZb?͜9g]&N|ҥjjРA*##gmmibcZz볝til(SEEES-[6*׿TVԪUtW]tw%x>"y9*uQG8Hj <Ǿ;H rjFEB->ܾ)<۪>TGe|Sf&/ X5bC~~862nF׮]}Gӡb']lJ-5mcU泄T]S)Rtyy[`AM:U2evm'r`9֖,YRۺΚ@2c^0_xq*{iNL nĪS߶WSD OX b+N$'VT MNUᤃkYرݺuϾ}=#'߳g\Ə&NyդI?sK/ra?xL>ʕ+}Ι~zҥ<XJ }X 0ҟh/}ė@| TWwͳ1.K^UuwTV* Eiiiz͛'|r{Æ SM6=hpJCfjرj̘1~WrUj9쳥5^㏫e"6Θ1CUTT.(KVXXL**H=te]4ڌ㰮5Ycbp`?c ,3_ėS ,;vQN999 ؟zJ>e.f:s;1+kb?eգG-UԠATF… + ۷~^{>F>'{j۶m믿9묳Ԝ9s{RLzP^vagL` IDAT,3_+bbO ,EnB*2[cVY?".t³no]ۊSN9EZ--Z'S.]Xl~[wdRY)M\NkӦM3<߿ RԵk׬D8CYCMRC|I%,%˳`rnn?~w9*BnS)'+VЭ wޭ+[{/k=?ОX67xGP2dtbxUq֚xkW!U`$*#'5P|$@1~5fMw(?_a|eK jbϬ/t_OI ']"YbXl2չsg|F=yfպuk5 :uJ42M1+a]eO*>CGTRUg1{\&|"%Ԫ0OԳn} TN0[LNJ=yk1m%s"R1@%҇1F|@P/+LRbP`+ G>2Y1߰a&^#10 @ė@8V&&*֯_]nڴہL9,Rƿ={nZZJ5&ET] ]$@Şf8 X61Q)ss|Ç ̧3xp֫W/=_hA@8__+[vmo] /n$5k֨7|ӧ/''g7*vi:}TRC' x9c=Mӄ -+O>_*[n|3pK/m*N?tugZrى'X,R^^N ! p7MW?/ٴCDnmG׮]jM$E= 8^~# –hcb`S{%%%yeT[LT,˾R{A-M65VI= 8\f8 8TMV.:T5oޜon3o%/Ҡ~OC=T믿2,/g$@$f8 8ė`Sc{Jemag'M נuYw&b g{ITXX^AAAѮ]۷W>BfVY[ؙK3s2jaŞRI (HGT/RJp= ljb/???ӺzW.3|fZh XnuF@5T|򼒒]!cVH7֮}GdϔC>`o!BR@Ph猊=%Z-_MxqRbVOtIm%(z!咿F=Fg{Hb@P=Q*[-&سÇϪ %1# –h{p= l^YF/, 6V}Tx vZ䳜,k>CȚP-7I+((g]QنT*)Qq6R0@50@HNnV_^+>z؞&Sq6Z@b/ۍ>ܘ-5x &{EֱN=TճgOJֳԩիW.)SmH՘$P ؋!p5xƤȦ2 bHN GonRfߍd5}z#u0NߵSZSv+q@z&GDVƏQg_|jݺ59n3K.Dp{JJݿիW8vSO5kz-[VVVou7mTw׮]u8Pخ)o7ڕscu#5PkNqm^iun>#]UVۨQ͛7{90`O>};R*q|onZ~J=B?62T#~ldďFjďPcT9R,\B:VUʹYaj[7gϜWT1i[aY6UXw]a|wN#~iď;q?0)ѨQ޷o:#<۶m{Wtf>;;j!C'9Q4ұaZc\Y6N6lؠQcZצM*+( |S׶m[%z?zH% h 4Rٸqc[YftE3f(=䓗_q+(#$PwN +++[o%@T^=ie**~ўFc?z1+HǏQ銳 Ӻ,c빙X@e>Y>|85" B3WTo׮R$*?/'>C0߻Ozr-*P=н7nTjР׍{(#~?{:n}(VX7w\uf#-F>Sl)i_dp ؋~3tPG9>~g]Zj6lir2fӎ;d< l2otحުrrrݺuz-Zh+6lؐղeˢxw~' ?"Ո0Dž^+ӺN5˽{VzAg>}|KjL駟2OΝ2iӦs9砠LkU˗/W ,PǏW{Сjܸ7(3Eߒ4iuRUӦM}mc}۪^ 6m?8Xwz$fďFؽ GH~8a!u>TLjL$;)̝q؋.l%gխ[7h"5e]B%w3v D_H,W0G#'~{Rz{:qv>9sի'pf:fW'xR$2{_z꥗^"qW0ݟ={/lK@Ir>u*F=F=S+RTvЧNKMM%|6}tr3$ tF`0O]tNqYɓ}2duNsz !?ԩOս{wbOzCyJ=@0*"G#GW*vf˖-u(.̇F>@ʸnI>~iNNΣuznnnu}0m4q~hѢZ9w駟Wlj*!2 @;'N۷O]|SOTq_qq]zH5jԈAh,ENZkDZUT3ˆjƏZ;''q;:|\WA@}??QM.'Эt~9d)LS!BIfϞ|gbjϗSL^VVFb? Gcس[xq'|ⳳf7p1)k>t1 [sWo6յk H}S1c~OAL}g> O@ԩh AzE{GT:u 3gNQ8Ϸ+=F>QgNH{AQPP%矯:(8b3\ n8#cIؓJ="S8S(DoۺhٲeK @} 1>ďP>Y}ֹ?Zg:.fk= %pgŤJb@Rs*lؓ K{֭ɻv^zE7e,gmn;?ЅW<."%AnhƌKlܸQW <3{"D#LF8!R+{f!I֭[-[TC=h;:&O|&*Y)1 iU「rM7yVZ[͞=;>f̘1eÆ #P7|3 W{#)gᇫcǎg| s e.%AzK駟q:K#Fxg͚ 7(?"ďwbY4k5[뙏'0ot9\>LJqc|_VymK;ʝ.wzouE?cI}[x֭721_q_~E]ve2^ߞb*QFy~i4HW 1D0yFާ!#"Ϝ F`ܹgXeJRO >r߾}\ 8F"<wqB/;;Ν;b =.)((m^3 pSaaOk i48%AzK=&MRLJ:Yb7}ܼyS\"c9LY_#bҗ-[6%??kVZe>RwM7q<%`rO7ďǔHjس~M6u7ɇ~E>,z`+|*I3]8p@ժUԈBJ. bM]PکS>Ƥ>eee-:dҥC֬YSoӦM۶m{T_xNCc2 ,Spv @È}*Q]!ďW4/S AP4!iXfe|,R/իz޽{ݕM;w#[X0pծ] F1T&パMjԨQ>]qVwQ ["~D'D]mzsQG-BY0Z`.ŋUՌ3H߿}$=PJ믤1FAٔ={x=Xu90pY_nf2s1jI!?ָ5Z-)///5+="GDJcn4Պ^z}, >ckbo3Е{VrԄTu`=͚5! 6dh3ʍӧOO FS } >\Y )㏵,S$ CYNcQwԈ3frZ'~>Z:?ճgOU>Tl߾]E+WT3gΔ1t9Ք)S:hzf͚ҢE2T_vtիW%5W_M))).K9rĈMe/,k^1˕5 Nʘeq$[^^SO=]ΥUٳ了}(;1n !~`&\cu 'NnVϨLֻ/_Xn+ճ>Ata|:#AQۺܯ_?ձcG?.k7*V |6|Ǽ|}iBo̘1eeK pQg]&~sj?RRX@BKOOW/Rs=bӹsgb>XD[{ zHz]l_ZQەzBZ>]nV;yƪhɊ?GkEEޔ_~K.CHپ}iӦ/_Sl4)'x6c! @Ia니|?FN^8wh9s4OSWZhƍ;wL=p@Yc2TanR+ߢQA<նo^6R{l*;m;,ئ 94 ;5k};O>ݺuygh׮vؐS1,X׳gxG1酅iծ]>9:SN )ԬY222ryF>ӺL31H[ {&OZ5eʔ;pGkc|TO?TҦMxϞ=I•-7Y@|>_SOngeOk  kUs/#!~,m$^h|X{=.#<zDmݦOT?7od?Idm=ܡC>Zedddy䑞ٳgٻԬ>`_~7/I?E/˕lunahfc#"Oe&ZcT"?[N;nMWuҾcƌѕ6lP j^aaaoko#$a 3o]|Vb݆r 3qď*Gmj@]m#V'O81eS5ڵk*b1OjoĈs-]toϞ=}}~nK-|$Y[Vlu+. \OH ?Nnc[i 1K)]vU|ݻ[xe=?ygϦjXAA~Ү];u0pUaa|&$I> ۞=FXDH?>cJ 0o˽nɳyfAicOZ9һ֛ {ΝKDAFYggg8p=ݖ|fJH YG̴'~D$).e̠wqgĉzڵkkF 6lBϞ=s}T^^^Աc̪Е}V}CFmY IDAT7|SrI'OW_O>ākkS,l:h0:>>v|_‘?8GDqrkjh`*瞔%Kx{SO<ի׸֭[{.2<9sfqڰaڵkWL,V{>ق/_-so߾e2 znUFb@0q2'~Bskr_uS;N;-W^Q˖-kUV3fɐiliw e9stG pqc/0>|f>sF̘:@|r=#/P?eee/^hҥ~m1uӦMmۖZQQ$՘d2oj׳-7|­hIEW)p[oUrxp?"Bg2~b=UWz+!a}n'~Du?*$ >^ =ܳp)K.Y:>+5L}|F7@1yď ǘSP )X+WzY8P3ؘg9=Dk=p_AAAouȐ!m۶2T:蹬gI% ~qď ǘSP )r2[EjڴiΩ0@8),,.˹wذa$ \a!K \OUďű"=IìܓzWVfr~b>D^~~_~ŻܲeKupoȜ.;26C>Gr}#")@KIa۷/wIT+NpUzAAAo0j2]̞όKW@0LGDJcL.PHp'dc[xF)UZreIz[]t!qf>SF>Yt;wCj %PR3|?N0ǘ_O,Cީh| QPPz.ٳgReEn|g\y#F~\"Əh5ǹшw]g>˕cLU E S~ڿ?=oՖ-[G?xΩ}ŋ\# d~SZRGuwݻղek|ɪaÆ=sFs5;;;aW{Agn\v>*33SkN9բE ݦMw};0 q/33SK|/|*ԩvر>rJ,YĻ/Y#S֭=\p/༑7|S:h ٳKtmcNO^w):uxmۖ0DFyHqUĬYif^'|gyF頻׭2#yl}8jz"t_6mtZ.^ػnz݅^k9jϞ=~O\&˄*"?dfdս{w\#Ǎ'uyXx-c ljڴOYo{~O;tZW;9=Pﺊ b ?7|S͜9S=C# )uqQG<###E˧MVf?8Jc}1bjܸqB\ꝍS;v֭[x.>]Гmۦx2UwYf_i3V6I74뱗ȭ3ZJlX:,u7O>g癊Մ Ν;wuK/?쳠K3zhM[fMByW-%'ߜ.N/\Pf̘nSݻդIE]z--m휺:W\}%Kx/F1b޶K.d'd<(@䘒9ӍqgKcQFM:9A'55c?!3,;mrC Aokƥf9nٿkժ/ė ? "y?>e@*M69^[2O-lһy 7]_V-Oڵgugݺu9#L2E/}j_ݻw}ݺu\ȵ5+\+ڟ:uy}9O-f1[,YJ2/qmkm7w;yf=wi b Ls9оH ?^}:vFq6l->gk$~}d$fҊZscéPRp.LƏ]:t #P+Bo*"۵kRВndl+ ǷnON‰ٽӹ#H0{y?" ]_\R#i۶NKyp.I`uQG>H5jHҥ߯G}TwbߑunT|&Х$'1\Ȗ6l_;>NórT`)[ Sr@`2^<Ǐ}TzYՔuR&q̅yG|OUǎ}Iwmt l0&tk!C䚔t)ʹR2Ӿ?Pϥ 38C/7ʍ+TV{CGݥ{t޽ N7}}y_} 6ZcXb6p˖-z7 e޸qcjZ`V@ѲeK۷;A}3HBcP & .2I3f dS={ZU{C=rRJ8̙3r^5c- AZGiӼysg> "Rϔ9k.]WIԓ2J>wE|aď'6Ruw;>.Y+;vmJ=g;CZyE`/}Z1](_7ǰPmͻ3㍵lÇK8:0I2wAjZ.8դl!jqRp<+TKk8{ d+ S^^0`R'qY(7 ?N;-`zN>Lw5M泭г3?n36ď1=@#O) H+߻*f7t'}㠼AMg5jT]8;DeoZn(=:G{s}!ɬ(LZ}e;PHԱsհ?~~녥@k=Yǝw e{5\nucc%]n8#}<*Ei?Iuu5J???+<1{{j?n~Y|KeTqFիW;z}dPi)ݤK/]rjPn}6k+17%*RiKnʕj…z_A/ԅq 'epa@de|@D= zoq{D_+pZٟrn@BT(/}d]ʑ ŏN-]͝;W}Q=Uii4i~9Yx_ۓehr󻴰@핋K.vv%KtTu8䚜ܪ s;tNx9jˎbcKWXo1VEF׿zc8HZ8pV}zܑd!w[Z즛n*6>wI9&)'''aӟQ*4*XNW ɘJ#cT1BtIz"?Vޠ3>3XwP{48WO=)fѢEl(7@1DzH+_׸qt.Mos33O͘1C-[L'ҪNnV3Enր[lQ={T]v~\CK5k1T*2cǎAYfUn~ eTfn8sα+F[IkI ]N* /2B̨QT6m~7$slЊͻ+ ̖rl1,&馂7DgڴiSNAt]Z~2X7mHe9a r:}Z9=&7LIkS.BCǏNמ/\5o\ϥL&ym۶7bvׯo(}rSt)7oY4%cJaU1ؑG+ =]wݥ5 &[oUW>JEw߭[,05 t3kst$?#M 8IY wz=^@ƥۂnݺP־&sC!'0;vO@t ˳`rnnw,dnK=-{;,?3= RnXp}#F>S}YR"@u_/ (WD9 )~t``nEE% C"=f۾aC9D/?zk@|LYp駟x{RYh}n:rlŏT@uUUmSpU30R@ÓRձ`#y]tg]b ݍn2*`r:vyͪ]K%KUyyN8G+ V_FF(Pjc!Dc?V'sH(tj;Ls BEѣ~g 'cn<W8NNLWs.fPuq$ 3( N`uG!Y*'պ8й˾΁ s}|fe9RH>nT2I1sGUϯ깡ĉͦ p-tnzWu^ݺuՐ!C|la8}`w'~J={3vTUUvyzD2s`f@ k4kzW$ZN#$ IDATRr nz48%~t<"l+ꭷC+_YdJbպu*>(rkHq.]'ᓜ@eeeeM6U[nMcq9c*)#)[>kk eė@Cَ .P:TᙤBSOd.|?c> aq9e2QI>(W7-%g% ?9~ E0CXK}jڵWկ_Lϼij3pG;*LJX$1#k׮ϠlH LgG}4G}H@#v|_&0GD)9ŏ1J&ssiFPH3egFP6cpӈO>S|z=_Y!k̼ogec?f 0~,|FW$Jv|PzLR%%%yg}8)ycÆ y$go߾|g% _e;>/;$ ϜǔxgkY/Leee頌Up9,WRď*3H;|lxFf ***Taa#FAO>O1r=Η|6!?WZ4ڵ˻ܾ}{uyHp zngGu ۈg̣R`~x\@X]|gZI$ލk(!eFf>Ƞ2/0?cܣba˗/ϓrrrH$gʞϲ\<?"ďq bVPP0κܯ_?uI'0p;)|6#ϔC>n8{6{nTk=Ϭw̘J@ ~DT?'W x֬Y]nԨ70 C7|SYYÆ %Z#ď*ǬD@zQBe.%S2JH ~?"ďM?>'LΟl$auG?իW/Y~jժF>C%P2A?"ď| Z lEN:u18*xRPu:)U#~D4ROPwLz=G$|VBjZ:u |Μ9 >pDh?&*s@ -]13׌|rXСУ>Zeddl >s[ͼ'~h=󢠠`u}ffjݺ5 j^zn%&56Wرc䟍7 {+mc@ ~D$?&T7=l߾}gITKw^5}tdziL @M;1»h?u=Ts9i2ܹsIUďYm%~b!zݖp[I`f *(?;-ii7rHߧٳg .: ?"DS 8 's|(AbŊO9TjӡCtiggW@"#~Drgcrgڽf>3[8<''G.2@ Zh!_|EԵkߴiS꯿ZoϞ= ߘzv 1beo6VsU [p|fR iA'-- gΜ{ׯO`g!&&?e˖MkUV<je[vc`'6QS1+Ӄ8$ڵk)Kwܹɓu^֭ե^~[o/[lSvڕriԨQ!W s@!~D4:?cbd6rHԩSU-ԴinxߝF:O\/ q|,3ybڼyj޼OSg}6lٲE5kLo0}&w8qnݺꫯzzkzᶄ39nyyyQǎ3=_3N5k,@|( ~ F#-$-9я;fƍj ;wX6V|\WPPPd]NKK#(w[JLOO|6J=֭[[w7u֥L2%ŬԳg%5|Lח wyؘQpQď ]'ߡCF?{l ttimk {F tL~~rg%T_T cUz衇R7oT6zO?eėkϚ5+ň7zɋB2@3;v`7t|]$Eq>#^ZuQ$\xbս{weg|ևXIK=ڵzT6m.q#_y}IMN=I ȑ#q|d%B . (녜|6X~ޖzխsÊ+z妴Г.7iG0 #Oz=̝x?f̘m+]t@zMuϬe#RR`OJ'M:u+zTYz!\-]n80+DBhqS $@@*a\|W=6lX1LNL[lcUZ5y PFWR)'\G.\̟x≰J*| Oaпs[/" ,rl:M7)lo'ȑ#m뤥LLL?r `rJk>K@(+!P˓" JzzAzŋK,נ3e?>51!_~qYn]c"};l[@k=@ׯ/&S֭0Ⱥ A=#$ǐk'h]x'-֬YZj̙jԨşΩg}6Gk= 5ꑞ={' IVgϞεqS,+u~3fҥK4pھ}n׸qB//<\Uq.r-/8*.3[]lPϟHkӧ{%7|BȳdAUJ+rl#1˅|իW.y>ݺuS/" ݻu:ut, pPĥxqy 5k$?)SrReWreOzzynJ:tL{yf5|p])ʙUfԌ3K_>{F-D%ǐ6'|>̓s+#讻rϞ=[V*c:1bѣGۺu,27?8?+amkժma 4HGhBլYSEFF"E]dP_~EmٲE[N-ZH}^m߾9s^:w|*UTRff%KPr=?' ?bQ4T?S&555rʕ鑻v8x`ĩS"/ƶs*RTywN)"#hc״c?f8OXg9iOiF (RJ?q7fDΝ{oذ!y+fAs(P|7ovGGG)0) *^|׽LKK+hѢȵkFl߾=R,?ytU.݌KWLt[XXtOiseϟ,7e3F9qbŊgԩsI&Y[>ӵk׬ZjmvpьߗόIoZ!q[gG-r%P (6UL2Q0F1è?0FQ a.Uׯ/AwZj4h$QtieJ7AyK_2={d95oLYߡCx{wnn=={D|ڵg-\:-D=p{HMMM8qwܡz2o}!/,)rr9e)CEʲ*U$ Z Ib1e 6TӦMNѶr+@:&~M' @.gBSYv!KIII^|m+"##)Ŵ[zmq_^kL+QP-GL`֭HqqqOS+ ]nmt=/BD0+Y|l=Z!yCB"lٲT Ѝ5*ϗ  䡜uٖ ;L{*D{}8|>}T˖-6/-B+Ud[fm@KIȃ#dY ;{@# 8D`rk׮|bԥK ΖmJ=. K> ֏T #<˜y7Rr˫ѣGCϔx OgŃxh [!{3f̈8PO3EʒQc |\\gl +kWM >rw,$,޽;9ԑ6r6WKo-vR}G3ȓ3dYأ${M3b%80xfK|)o˒luܼŁ{@pG%;$Ao<hz˗w/^ضogΜɑ?<5ǙG^ov9 B)c6T*UTڵ/)P\+W.$ҕN9F^H$_6~ ~ٌ@DryrS\\\- [թSG/_dׯPO?n}O?fkV|[m IDATϫ˗hb f͚*T^~e5{lGQ{V;wT׭N>mۦ{1uI5|prwiyk<&ocIK.U׿TUBB~}qaumd*-N:[թS'u 5p@J+O>D]jѣ믿V#G[jj--[[I>I1:_H1c-?r+APB> ͵k׆ZV^I ok?K9Y'_9y_ W!K.MPwq-8p;@̖iʕsoݺնٳ&MzܹS`6lˤYN9Ousg٘1cnݺϝ;9#F믿|k'iذaד#G7o>y5o߮[z35׮]}q~myNclٲ6kP 79R{}_>w+=A"]ɤhG"H$~wиfFK߁$dObO"))iu>&&FUZ5v=Z5lж۴i~ENҪK.z^Ƌrə3+{{'Xzo'MͼźzqFuW78KG89vs\f@JԪUKw1`Bɼo8q9vC=[2v{wt*Z A ;vHP`N?%K?{fۅ,;wm5%Şh>_ƿi'ĨQ.Gy |J>gҷo!-?G 6ќ*o5bĈP) /޼ȅ@/Se9O)/ _.+ƺbBue &y}if\der$]w:T-_\n=e/B' Y@@) &I3t!-vܙ#. |IZ噞z)2Ǻqƶ_VX.\RSSs(kVRBtx衇^2Diyj~1] tR :p7b\;K7K\ꗱxnٲ%A |իZ*Ƕ^WbEsz_lٲz~ɳǏT6w,7y9~g}<˧Lw9s|c5k_vZ?^ˑgzW_k9^e7%⠜FJ*Ao]vt"E<w 2$֭$R3XއD"HoQL~Pue2}$= ǙIѥK\t$ZEGGuRWzTW]uzWq֭ijXz7tK7ȑ#J*B }fΜ=V\׫WOըQó|lvi%wzYȵ3UZU'y#8tf>s,O?Oo>oÆ 1 Rϼ;̟G޸\.|v9 n8Eȶ3 7tԩ>=Φ5[z+g!I,eZvڵst݂^hтz@(+kWXh4e,KK]?H2.plwsH4aP5jl':t4}YI5YWD [K *)))9^/--M_|Q/[n;viU8ydۺnM/-_bXb;Y'#xx 5k{z-\Г7n,|_=CyI |.9rNϿw j,gC<߷>&YnMޖH|ieRHv_9/ z=ߋD"H;HD~I"H!q];ۺ,UԩS[rm֯_tM~}wz~xz-[@7$`ڤItL29gӧOsT~u Ml}YYY}{w=?zmڴq6ݶm[wѢE-[tWVM?e=Zjٗ/u릗-[?!AOY'4tP~G<7{H|-3$?u$d58kKA3ʙbC(g^×Il׮+_$R&gK٧M2J¬_G"H$~~LK$H\Cp/rk'ANʜ?D͛7wg9#cIdɒ9~$p%-$eȜIZeffzm:OR߾}xyj1\[kKpTq.Ib}~XߡCrl`3yk`o„ 棜zEj(_9|G7nܘ uRHFM(H$?C󩧞rm>=浟fs5ܰ&7}W wN)#$`/_B~I@D"."e_ʕ+v<55Uu^Wg9j֭믿c]s5SN!cs?kU-[cz={۷Ocؕ+W.}T~ !N8W,_jذa~W7|ڶmky?[njС_~~VW)G9`_/;|CR>y慭Zm9n|3V3[xcIōTRgOeYiedtid쩹lcZ<ӓcӣ?2ө,;=Ͳeg3YM7tN4 ^1Y-Zsu~t7o^Ho?LSnS&Mk|~MƼvx2.vc@`@cQ4F2Ҩ_FcUܒk㒖TԚ"_ڬ̞F8}M;,Y L3',˳鴗2̩Q0FQ0'q>8ၸӉ&M]JjܸNyUZ5.}kժ(Q?2[ddرcꪫT.]t˱^LHpQڵgu)|)/,dzD%K<yr׽{w$y{`w߽%7=d~ƍoOgϞmﯢmUޘ7]5Wnp#$y_Dn@ XslC>8D`СYig󵝁=o,HLQl#L eѢEdڣGu2]`޽:so9H>_$|+g>Kȕm?|].W_%HV S*iȑj|m3J\.e(gBs_b%/*UR @sҖ,Yojܸ|ѢEzj>g׫^zIoO>Ľfu.-W\iӦ]jUKo\7dȐ[ua}իW'\5SE1bvcMGz>&&F5m}mkf͚;"k׮pM6EKٳ-06ȇ7FޱcͷrKBR6So@pV7Bk(g!= ܹs \w>}JzH$D*d^X%KK*)RDK$e`ƑeSN'ϝ|ض//;<<\ח5ٛq|ҤI2d^6c ¸^ywocnf=z*^3g:rH.-uF:u*ڹkzM!Si…z!UT)5uTuѰ}?#g/ ncU۶mefddڵk>(-TNԹss?Q@gJ**666vTqz^Ylw$͛)WP+˞={effaÆn6O8{Ça]v?f;n>kԊ+Zh]X1u 7<O^>Iko[ݺu'L֦Mot1S:޲nO>vTq)?$,gZlΗ6mڐ 믿^U\3ߺuk%A0'g=ޫ[YG"}]v/ծ]0`@_oK}Q銳7n6=={vKJ Єʎn߾=AD?{r&=ٖ4hBWXpuת({g,ܪUuRi&OyxluϬa)SF?8sLUY?-5kTW_}:k5iDZxm_Wݹ~ǎѲMFT"Er_Mںuk}I nk/z~(E@S-0r1СCբEBNj\:۷o/]Ocϭ͘1cL ~ot,Y]res믿J(!b׿d}-yoA6ҥ7uW{${ݧ<^4u_cǎ6 z=_cm \6Oܗk*iӦ*""{"B˽~]_.HIIIPRp~c2#?Z~Z~޿oh"xbiզƏ/2VwôܮیoncOiylRcIZ+KkOZdɒ^Z{wm۶ԬY3ݘD\Ry,kaLZ 3[]`>+Y@p8x 2g 4gѥK7|#r6c\^^ܿܞ|@LLwi-ge`~vβVZYf3nݺufoٲݱcGծ];uVwΝ\w:on]w$СCM6k}q6k֬N))); v^ddnwW7ųL4h`1~˗/| ]O>Dc+m.\9sn0?|мyZq=_Ο?_XWxnpK*ejMŲ_tҬ7suLX9g/0=ϲ,?HgLtƜ)RL ߁Ymڴ9ӻw=zH2/@Jubb8m[bގɹB&8lyr a W&xp{}RX ,Y~{쑠>pݻ/z~۶mivR#GwCbcck\9===u֬YݻE5 7LE oSSS'ZF }{K/yEn{rcLLsO> c$I&}^'?z!?x =?W=iҤZ֭[< )=H/5jw-Z-~v1z#8PsժUBkpy@st%O* 'S _%l[6hР yw?zO4?\UP!EVp5jHm{u_n|=Oԯ_5k6DM6MIʕ1nj|毆 5kV縸9s(IVCUm۶]|wygԌ3$ѬY33L4o>|x?Oʕ+^{-}ذaގ !̙3F5*y)߀? β+-Znr {ǨػW\陟0a;vlܝZ^tR}7ި/^:޸qDJ$**JoouP'ovܩy_~IUXQ|tAo-"-X@צMէO}t$g5䏒/BmذAլYSطz~ HeZ裏tUlYմiSum $Y=S^+IJMM-VZI9 ꫃nLE/܍`?,]!ݻM6u2+JtқsEw3g&NV@^{7Qc5jPE2qn|2^?IKin2_\y f5V^ hM?0?]L/|gĉA vwxx{ҥ~8:I/b;w~M%l5jTt6{/qC?^ryvaϻ݋/mرc&r㘿>7D_d<O}ȑD"9ї|)Jl_)?0teڵk7)R$uԽvޝ.]vyA iA D"H$Rh%r\sMSnc7:id ^ѳgJ׎1bn'c |zn)R*0Z.˩y-=1o%SZj׮˺y+9'd˥ۈCe]Gu/^\ꫯY'cIyeZHUzu=om'eddvک;3ǾI˿bŊ욭ƌ"##2]C ?zOHKBY&Μ9V=䓺şHɘ,T8p_5i'9%KTgz1>Q߯Z5zhi9a֬YaZk7|3ʺL'C Z˙}~W@8wygMcF hԩ+=z sBAqumڴUB`Bɼv$Էo_=ߢE իW/=mԨ-˒m'A53xݻwۖsLO=Y|6+ QQQÇC+V~iiij/Iƍ9ӧ+g9kժUAnAjժUŬ70r-:'s\ ~\#.iEvt 6l c{5իgqȑW_ē:%P`Νu}9|؀'Nq΂"cZ,1;gR(ؾ}{q)Pµ,BY[lwŋ'8n Z]:Z%b&6ť#! c,"ΚGAz~ܹ5̙c{/SӦM~u֯_2>wUWu몳gڎbŊ7Џ??Wf93,6Կ#öVH5jSo=p-P`sm's˯{٭l}7JPOJ {Z95mۜ:uJw)SkV+Wg?3[f1b|"cǎӥKq~7!AIyjժ@FR#Gv%?g` rۂE%S/\@8O8!ٖU{g7qy9^:֡C7ߨ%K|ݻIwzN髯|O?Ik_?L;Y.u]M oA< żf03ʙrA 'k2^^lk<9 U,8WxS5:߭[7ոqc>l۵knm_Cvک;?Om'O=AUti5~xUlYvgVZf֯__w}o߾AF9S^xJgr]',Xmi@(1j׮޳gg~ԩ{PDž;~bcc{ァJ*S-Zȶ纍3al=-~1a3<`;?f/c&Xz)dկ_?[رCOoVZ*99Y3JZ[ŋ.(+W頞䵎=L/@b0}rf擴b4A=뗇~8Bݭ3{IIIn8 IɜegϞ?g_~YZUJum˗[OݺuUTT5KSWW/^.@i'J0`^'t)GҍLf9gK^b{s;ig$C+F+C~g$)~o'; >5*eh^0\QȻ/Hc%"E~UZ 6,m+UyY&csyb po_ݚ&>,Xg֋vnO?C+$sr'qp]w.' ڷoz|8ɓƵiIc#41-kS9H9}6o;?s L8,9YóF~^ϔ.]LJ4h e˖gzչsgXVWZ#^y':tH^Ziƶ^ 8P͟?_=,BTZIםe˖믿bbbl=@SG9Kq!\˦M{Ťz}?_8z}AcZ W8qBd]w}2uA+$sE M\.W=5j;wҥСΧ7xC;wٳ|N>[y>"ETѢE,{u^?ݻՔ)S}z-]T=Z=#ԓ?c,ֺ |$GGG zfpl֠3Wuj׫ب'xM [rbdjViۛoڵkT޽UҥW_}{_VjRf+VL?gjuujkV~>Zrj۶_kTu)u+KoIII?by'?-|Z=SXk/[]1󲭹?*c=Ed+g֭[qe6lP_=w}uJ֔zO_s=*+Eݫ[e˖5y³\ZOE Qd3e u07nдiS :X_z]߾}{ս{wժU+=qժU Tq>]ϟ׽?ٳGt浥Y.^X0=SYe% lq~ugC B;-L:uRiii UffW;IعsլYӶN>^mڴIU\Yʗ/4e3奜q@0(ѣ[n |P >\EGG5hݖd[b[u^xa>ڛ)F>w`??#[իW-ϛ&O򗿐rZnQbBC݋/-馛믿).y])en?80Aa%"./;?kPD|+g2)/匠!b̘19z]ʼС-{N*J+C}w\$]rm}b~/mNP&<{!ksΑ)P5"(_/ 8'3f̰-3[1Ç=,WF9@'Ǐ7jHM>=vޭr{)W’ow<9Jt\QQQk׮8򕵵h)g߬Y/_סz/22R?6/T˱j*|ƍu܆%+vZ\|||?T̙c{Θ1cT.]h@k pr9Yv7K(t-_{jZi_bEmޘZ>իu|mnݺ_|@k˕Yv5ר[nA34=MߠyС×25+Ǐ.D5>|IpϪYfjƌ!.+:l\,o=ErFn@+N.,?ܿZj}yyOp/էOբE UfM)Beĉ2>ڲeZnZh/ur۫3gի Dlܸ1YfA5jD lذA5oܶ[j1 uHv~(_R jLWy>eGyjվq[K|ubm6k9`ԻԔ)Sd;:qk[z\K"HY1cmY= 7e U1w>c=vQ /v3q !HP[hҤ;vlJ~br >>v\RIILL-4hP1LP4{{ k'sυ͜93EgYt颦Mq03g]ϟ,9s$۷To IDAT3_Lzk pfϞeHY\\py̍ /*☘XJKK+hѢȵkFl߾='O0*Ʀ%dNTԚ"&2{Z2{5-B,YtLFY9QbŌ:ud4iD֭3vzVZhm.+:/AP\!IIIzj+V,V7 0@k$ԨQcuU iWfM(gKrY& <#P#n2w1g-| ! oJe I7zr6[~YB=%ei(gd9o9*+,:(_ʊ+6lY&$G)e˖7zʘ0ʙ,N(tW@ȣPlpy睪jժdtimw]wI9Ks#{dffiӦf@&cTbb-h7xrF`~%)))9##C?SjR}%cdl=)gfr1duW\.Wu>..L(ghH3i~{olٲ%aɒ%ed 򻜩ŋۖ 4h)9:XbZG`W7.ku]NT&M0+igչsg)gr-`Ξb =8_&&&ڶdy_wX{@ٓ@KUUUyi )WlĈj Z_>^xWX Phq['\2} Vv^6;nܸ(d[hg'tl=("T= Q vUUUyQlr[cv=ʥA/kb/=}<^?蠃V'&('@ ^~1>`^\uѺrɒ%Q7jԨYJ&>HSO=wy'L{Uh+@9@ *++GvaQ>}TM*΢",7 lظeB6B{0a€~ '~ʁ-.\ 0=bxg9sDkָUPs+ e٢ba.м-ZV$ҁe˖Es΍/^w1>Rae,rK>jԨŎ(7{4bߦ>}W^y%o6+>Rl<5|syze|s1Ϙ1#SJPa߭/oH?O~6 0?sޱ|}ѢE>Mm5ƕW^g}x!r @3+mǏN_ jJ꼋]Eʆ\ȬOAsjz^: S{XAl;{cr~{.ѐ!Czmv|I Z^@[g!Q p|]՘ly_?'Q/UrF3gΌ:?BuC/Xo o~3r-u75LSz83fʶ#3f/^أG^1]p|J5Y$Yd+'6I6s =?3|#ڵk[oqtAvjnE%Ff ~Gj_2d֓@^kZ462XwM?Sx|MKݻw{W g ڲk5WX' Lu7z9#+[4M_ BިQr!/L9}jSt++tSVԐ"ؘUjzbR1٩Sx, A?5e8TSŎy3 l hI-}oK/4O֮]{є)SΝ;GCKFv[O}Qnݪe8qbkE_|Eq2hРxǎ;UW]}я~h͚5+ߐa͟??y㬕s=7j׮] ǽQlܹQN;r!/~jc=+oڶmyћoYxbLJ;#w|L,/H0|x8O*pWբJbB>}z!C~X2?Dgώ+EZa _tEs=?W۷o\pA6ǐ SO=^}_ww衇fx喱Zu%y裏f>]zFwyP9EQEQEi[ŖsMJfW_ʹ:į=q)Aʱa7Yti}Ǚ|3vmYxqs?~n۵^oLa=%nݺL>^̎;{6ms_fvuxyo߾#8"^O߿?8p`||K{g]=V[[UoX_zs9T 2$2±ϧҗkf>3Ϭ6#ilfC? S}_ύnm^ d,L!5of=:b c((JEQEQ+ɅwqV[ůݶm̠A2O0 ̅ c[ 0K.$\oF^PO̚5+{o}+߳g8H{cdLL{ B/e˖e.;#˦d %k%˜|J=$/_rEQEQR.*AQEQEiҩS&Lȴbv^r /\+$袋rA:*~wV{x_H]B[rùrI'Rꓱd>'f͚}!X\Og^p./Z(Ӯ]x۸q㪽Fr|x?9ΪGzWjۺ 312ڷo0:3}ÇCp+SBPB={ iO|I`/?A/AN&셱: xcE eKl-]elfˠ\l-_~9~/[NYl9ڵ-__{7t6hx!z1TQEQEQEQ)&L/Cr7_~B7l)fmKƂ0p1a aÆY5 cZ8spƌB:w}=XU,c/li{a k7d憟 ˢ82Jg`1((JeନWVVK1bD{T۶[w߽ھ7<^]6^&ݿ1 . Fz/GwqG{޽{ԦMjwixnݺZ>ƲeˢիWַ7vj۶bhܸq͘1#o>Gvj=>߂v=nAg,!nRZ'K,ѤIrG}tϻGӦMǧºMI'cnV6ld,,zY;^1=Wlx ̙3.]?Fݲ [_.˖O ӇaM۶mWo6k:u괦[nksսzZjF`f\X}L2%- l o}B֬YUUUE7|s?)o_0At#,RWJ u]۷o4|8(\qs*+>o=vo7΢ҁpn_+%"d Mc9&z˪~B}WOǥq߻uVq{gtj2=~a-| Ǔx]v){/yIAHϏEzKmP/[%YͮrtX&_CׁQ/5ugEyhmN9#3`qJC^+K= iy OMl}ݹ믿>5jTWNBbɹwgDm۶ZI^9\Q./T,WC .(:ꨣկ~]s5E$Gyd4o޼k >nsLÇOJu]74zhI@)G}4.ńv'L?a<8XSҐ*9=Cc^|żI`oc+D+ܞޟ^^Na(zϾYf=_}.8u‹Ŧ S%%~z=߯駟v[ߣ]r|??y0@mgQvVR>w-!Co|!CЩg75_ Ni% ]}/~yA^2mC_x/ :0`@X]7[Xc Y+vɔ|A4gΜriEwxKoMyMC`fLÙApRZE.>{wCpky͜9Z[c.jdI  .ؐٓd$-Ow=/0e~hȐ!q3όV^{{.=ˏ6=I>?G3[N6ms z3f̘><ǿ ^w]xfL,w~u׷3D96]tL>}RC~6nM٬Y2;c|3?O3+Wk(SNt9SXg]v̞='PSoFXpL=!V %СC'c9ss۷oƴrRsEQEQʠT| 4?b cCPjH0ئ $| =Ϡ^_`A~m[xݻ_NEBhEYϦ\{?6f[O{+h Mk;ctX&mJ5W,XPl[mm^Z c[Epϱ^kXvIٳ"GҟGCi_nZqa&9&9d\ϹjOT…֪#FrW{ηϦ(^NO }?*++^+&7y>¶Zs  j^?WB\jSl}~| =w=w]xvm^)^ob?[WࢾcȩDžut=D˖-˭v6jԨ՝-=k\ֶ>;k my !@ bǏ?,}QO/ً$*Ӑ;Syd5ǽj 5 pvVS1Կ~7䘦v-~?|ι[=@k!@Zt/ȑ#K<7pL ^3U]SVa}Օ\϶{ۗmgc!(tR_5[6{+cOr%@^۷ot!y(ܺ+[H;'={}t9ߛv j1[Za`/& qIDAT6u@1c8p`^޻uYѨU̬Y#8"o˗WtEmbq])e@Rk4ɶN;MPF$SI Ph֭ƍ?N.~ -o38CP&oov3A=ʍ=moY?Z&4ֲeˢv!o?>6_o'cjQA Ə?)ާOtV4T[/3A=ʑVYY9,>r$@n7p='3mÇW14'x"Z`Aa;f(G{4JeeI'*&UUUig4y`}Ygɔhvv6bĈdB`jժqLO2hI81ݦַL`?~|#⥌=Rłml* @}M:uq7:]vъ+۫<@]۶m+WVhg姢"VB^ o{[3}a}ȑz4H}3pjg%{|u)LJ~84hʡQ"!$ vvzeH?!c FE׻wh*FK.Jp LP$@q K1bDlPav|I`:3o޼z & 1gΜhܹl/ PI.[?hwV14t^NK%zz椱DZMV3=ju׎YbEn}N9q~(l7]w]T+{G^z頌,=#nB{zGvPw}7:uj޶CV !ϟM6-~l;</ P3g^۷o4`j !4$8p`Կ Fg>82dJa3<x*/8|yMvFN`-Ztp堃/Bc$AUVE^xa-~xtI'>y{v-$"Gc~襗^>f̘j O:Kk_Z޾>ΟSO=5]tQj O:nwczߓO>Y8gy&:'} D"~C8p`t뭷N~+ vrz?P7SqPb:H裏n5skdɒ^իWj=nҶ2]گd-/״l[$>)Xc`}uj'e]eRdۯرvmM^Vo͠AVwmU] Ҳmk^] O`zIn, P$]^{PkH  Sq 5M)HC}D:'@C=o+GjKԟJ+@+ @Z @_+{ P7 RTV=h(UkT+|E`R*}P+@_ E`R%X ){* WHTS=J,$WHTB}=J,$WHTB}=J`+P+@_ E`RFW(U@_ E`R% R(Imڴ V|Վd2*S .=JRǎoVLyaYQQ(;I_$瞫>lLyztvj ߽{j<P:5Ŕ)SLIJBO@${챫Ӂ[o5Ztq_H>({>z^{[IGV1$@:5W@y$A?rzmtM*y~ySҦ 'WC0v駟w7F?OUe#??oۡ=Sj|$~4n??'i~謳ΊxZZ{ m0 7 [d%Y{wuWNmےgC㎋8hv8Z?sO.łlhz衭NaΜ9,Y>h_j_QQExTi[d.?u-/״l[u`嚂թuEIY,۴icǎkwᄎ_~k=G}* %)2d5V*'{ @+ { @+ { @+ -h.IENDB`fltk-1.4.3/fluid/documentation/src/flBox.png0000644000175000017500000000070515004135251021132 0ustar albrechtalbrechtPNG  IHDR s cHRMz&u0`:pQ<bKGD̿tIME 5ݭ/orNTϢw%tEXtdate:create2024-04-11T13:53:29+00:00z%tEXtdate:modify2024-04-11T13:53:29+00:00)(tEXtdate:timestamp2024-04-11T13:53:29+00:00ZeXIfMM*JR(HHR46IDATHc` )D XΐJSQF 5`Ԁcʣ1IENDB`fltk-1.4.3/fluid/documentation/src/index.dox0000644000175000017500000000504315004135251021175 0ustar albrechtalbrecht /** \cond FL_HTML_INDEX \mainpage FLUID User Manual
\image html fluid-128.png \image latex fluid-128.png "" width=3cm
FLUID 1.4.3 User Manual By F. Costantini, M. Melcher, A. Schlosser, B. Spitzak and M. Sweet. Copyright © 1998 - 2025 by Bill Spitzak and others.
This software and manual are provided under the terms of the GNU Library General Public License. Permission is granted to reproduce this manual or any portion for any purpose, provided this copyright and permission notice are preserved.
\subpage page_introduction - \ref introduction_workflow \subpage page_commandline - \ref commandline_options - \ref commandline_passive - \ref commandline_windows \subpage page_interactive \subpage page_main_window - \ref main_titlebar - \ref main_menubar - \ref main_widget_browser - \ref main_menu_items \subpage page_widgetbin_panel \subpage page_edit_window - \ref edit_selection - \ref edit_layout - \ref edit_snap - \ref edit_resize \subpage page_widget_panel - \ref widget_panel_gui - \ref widget_panel_style - \ref widget_panel_cpp - \ref widget_panel_grid - \ref widget_panel_gridc \subpage page_functional_nodes - \ref functional_function - \ref functional_code - \ref functional_codeblock - \ref functional_decl - \ref functional_declblock - \ref functional_class - \ref functional_widgetclass - \ref functional_comment - \ref functional_data \subpage page_codeview_panel - \ref codeview_find - \ref codeview_settings \subpage page_setting_dialog - \ref setting_general - \ref setting_project - \ref setting_layout - \ref setting_shell - \ref setting_i18n - \ref setting_user \subpage page_tutorial - \ref fluid_hello_world_tutorial - \ref fluid_1of7guis_tutorial - \ref fluid_cubeview_tutorial - \ref fluid_cubeview_ui - \ref fluid_addconst - \ref fluid_gencode \subpage page_appendices - \ref appendix_keyboard_shortcuts - \ref appendix_fileformat - \ref appendix_licenses
\endcond */ fltk-1.4.3/fluid/documentation/src/fluid3-cxx.png0000644000175000017500000012700215004135251022046 0ustar albrechtalbrechtPNG  IHDRX iCCPiccHTS" %&H %@A:IPb kAEˊ((bC,^YDu`C]vysΜgϙ @g d T SGؤ *Ѐva ڿˇ [C 8Kc$fb| >L&!1S5qp' 3?XL)4S`yh~KE)3xefaK,FP~N_-g2@䑽 O%KfFh sLib}!(Y45l%aNea/aEڌ, +(Q,eed9;Xh?UWKIQJ )ebiX3_ _Vܻ`;3+NٛH?)|dxqFҟ\p7L2B !2@r@H@ bxY\`s[&fB lG{G';;r$ޱ"º2[Q y|ppĘ/Djr&zlyΈo:L0KGp0xBHLyA:ev>8GNYW܁G BBA 3qD8⏄"H< R$Y@b ىT"Y2҆<@:^-š4Dr4 s<4]=^EK8 gqp<\. q% \5ׂ} <oB\bj|~ ߉' z;O# %=ZB7Hd- b<1XCl"$IdC$$tttMDV!\BO>MI!P)fwJEDɥ4RS)T ՓEM.Rw****n*T$*KUJU\RTLӤYxl^ZN7 z% *CN*R]ZZzSEL6K-ODuWusu@}zq{ 0L5.k<$ikk45wib& CX͸fL>3YbB;_t:::uuuuݮ{Axx㏌YE-ۥwM_@?P_E+AF C/CF3/Zl.;]>33 26ij4`lamܸ ՄclѤ٤tB*Ӈf3Yf+͟[h[-,,-ޖs-+,o[8VV۬nX֩mP6 n*&ܳrmsll;Xvv^O40qĖ3w?rtvXQXxۉĩ$II'wf8Oq^ERj \r#-q;]~O[t'[LO=SӳËWgO׊=}k+s-5 Z5T:.l " `ECh!!e!OCC塍S)S6Lij6U:> a[ ?18-|Zg #Z"#G~Z(2:;9F-fFLeX؎qKH 1 {O4{wgZ̜?,YNV-}4? LP!O'mM򄛅/E>^Xܓ\<3eCJowjI+ OR&y#czX،Lrfbq4]z~sd6Y\C{Y &6]˶!3+<ӼyGk̗οk*'/  .[عhbdq%&Kt/ \ouY_//^~E|]?PUZ /c?J~l]j˪+EE%E_W W_ҟ$i]v::麻+(+0eCF7tdRɎٛ;JCKnYkYjٝrz[WmMv;w;wUW"lw_8TS^ގ}WVVۿ ʮ=0~mwְjC/'{$HQcfǶ2j 됺ܺǛ=kO؝{d)SkOSO~':W/~_wB|F+[]}a^@{\RZa=G)Y|ˈY=/+E:2-Q8=R_a==E('rJimmEޔ˗1e Fiщ"aq… G/_B7N%$N%$*$k](2d7V V4%B[5|/t'Lj bt \6yk% Z'iX/d Mz0_Kg.#-)݀!#]r QMx߳&ULIxby嗤UZkQ#lfҥ#/Λ7oYguT퀈 &8r\(UnX X +wգZW\]g◕z Uq#=%~VZl-7BRB\h\L5,G4IVFDԜH6R:ry鐮;v8 b"{'JqLWYIWޖf͒G3aFw\qeQLu+!dDen* VIUbHחwJ=cNf-a6 QA*5r2lEA*Sd@N8l)-$e;~F& vib&9ȊLLPS6DDud),X_ͺ+Q(U{oF,ܴ2J:Di50:!94Qߞi5XCL.*ԅ.C+- _OQ5ZvVW獊F:"k)5wd]mߞOAU9* >'M,˗/V32R: i)jff;s jw;FYRHYx+]]3@B҉+jJVGQH(/͑Ud^ةl)H*Α #I;-I}Z;HLbztm,(3[IJ9, rԭv~j>Du3%D9vѼoN#h: )7Qv: z 4~-$諤 ;~/$E:;\9 AV*/y3l_I!Wx +jxTBP(C!9Ƌ!IpE&4 ?ż/?ʍu0bIXY"-v&mQP39cL6}2I}|Po̍:7n\+]iT1($}cD#ǭ)+OfLǧ ,ޘ;W뼥|Tƌ#'N bbNGg!,M R^ԁ-[&]s\ĥ˺ו*pʕg)פsXϫ\tQFɺ7"Hl^™D(D`d" Nf=?Kz+p ]3f {>I ŏ+z>{HDVvh@HBF /ƌ]t+Vʳ>+O8:7&ԉ5ͬR.'d-ʛ762լI2y瞓-2f +JyZ|LF^/CgNDOkXcluy'֮JM[T/q:tҏ5ڢ<翩Vo.VB\kvD2br:e)GG W", d3uz70}7PO@쒌Ȋ+_'v,^^暂!Gh\ѝ i&u9Jɨ8Vyvua'Mm@$)o^yDOHzsʛ +t+/AYyFt,đړ'OVP|_]M/rd<J}#GV[mIܳɫs^wYFސx keBN|rlq MnٳeO{7R%nDiJiaх!fzY| d]œDEGZ&LgI|t 4948]WyIgrgo*.="En;ƐDø2,21 u.N;i3gKˑBV? %L>Ԥmm/#ȷ[6lg|2lh}!m6Fd}-H蕈)3!=C8HjFm,„FhveD }AF#2=ak=hp_sݗ^zI{)뭿ZS)J @\&$|Kr|E+*@/4706B! }Ƹ-::ME-[iG^Vn!_#|I ]3NڦNlM&ΦˣcQn"LK:=*_{}La7a:1AVʸq ^+//}Pl/t}Kj @T.3fjxWswW̚^٩Qn#zQˣ+|͉Җ ׊,.X(<üXpAjeD~G^ VϚQq:'W^x;65}=J3k >TEdHߋ-Uz+5th#9;<ꮛ2eJ qKaL6ڦ.Akn r-+^ʛ¹jyQCGKF 0:2W,u[b*huªu;D*OڟVM"yooY#7)#iT`\fbVp=13q2P6ʀ` Tɠ4mjy>i9s4JntrMnV2)7@w&V*B)dvnbȈdSZC#Zx;$F -EPf͚s}X4EHiM6kq߄cD1`tƝ^|AޘCǸϗg2fK]zLH_erߜ9pVIliu~; oGuq p8GAǐ(4,"-W04 ÅdDPp=Bbr4p8}nUwr,i˴tvs8-UNFR9G-0/]VIXe>0/+sfl'B|[Hk]6'

,N)[ZZ|p yrZk@oZ$esןa~;'uTU#3{w]u>1XբC3Ɋ;u I$]l2I9JH9io-…p8訉2 :::jK ZAv;dQF|! o}'"Ȭt泲dif#ra\V|,ThI(XK( $M q;)FZb<6uʕ+iŊERYkkb[V.k+2SVY_F P0w\VP +bRR3Ѳ &,itJ[k{d=&c&BF ,J^{MI}F`$bdecf 6oCϟ?_?^{minn2T HuMF3b!B!a8nȂte-֐+%"!%k<=rmi/)dDXBǚ  aш\^#J 5 c8꟥& L9#3ΐ/~rq̙3e̘13g?Y%@%Kȩ*S";SW^Qz 9ȏ/}K\'5 x[o-3,z5Ys2CK,t,\,]R˶۬!|7%S#=o\$c哧)k=cInD,_X:j9˲%%ה/N5wp hqU򵴴c=&G/]vE/QzLF XLDЙ;\gH#MR7plo[ɄzzsɓO>)CFJ|b95ꫯ]|`ZVzzd;%遈[eZdGÏ&]Ld}y2j d>N^|%ц&"m+엗Fזe+ɓ"MeaQz>2zT'~lrvNdze~RfHpeȱѥ-]J1ta^l=DB@CH7|l*8Jp 0n2pW+1&Wݍ7(n q}6>Xw(AROI n…ˢE kk;Oݎ/Rqkؑ4@^{d-!/,-J(Ӷ\/:.+[;StEiשJ.+:h;YYIxXc5icÂ˲ZGKCF IDATRc;6Oqȑ#eҥ݈$HPud, Ro~#{챇tIrii]&N :#l "xGu֍`oqƩ{k 0ERx(|$WGsɲ"M[_.^*m[^@d޼S+Âs͕wgYmƠ$ȇ}FV8f0"pu쒨;PS=dbzx;ߩ@袋t\SR a߲e4`ZDZd@m|@y_dB,|-PbVXc -ǒ'?lJzB ɎqkjK2r߽曎8D6,/r;ɢ7DRqRtdV9jLb=2vud'ˋ/-ٳL5ǎBgSLF+p8j[E |Ѐ_:CP/ӟT3>Zuw-o/ǏWRQv\9pYnOkٸ :묣d2{l%5\Sw+9ATKq'HvI]xDVǤTHً5ƮvˣrݯȶO_|ώNztL}uBeނib>HkJip{k;[l@4),QX.Z#^z zB/b>} tYg0 .PB"{"TF !bP.Ї>$lӕW^C "awkA pz"B|ֱ#HgUԩS+ct}&2kUW<"LqŲV"iFEr2f$7ΎdX!+l1saQ!&^d=PccƌҡlBVRHe'Ȃ t ,7P 'r@3¤8ࡵUG4WCtAjL~w#-OvXBXF\PdG}T=\#D Xk|LH-U3و[4y̛",om֛RG _Z%OQޖ朖/x!Yݲ"ϸ빕-BD>Bs !1+:4I[Ry}=##[\p > sYuTХqJC:ŶO>:۔#=Iz9Z8/-/CF)_h)f|QRɆǍW҂رc5W\){Nd=]%GFdr&M&FY|]~Sq}|Ff߮$fwD$Ѥ V9߉3*+xJ[YdjSHRBQ?UO)*!<:範,nD2WlCU )[h3qۡgElLthtP>qΈ VŎHkhLr}*3oID +^nϽ?&z뭊UI].vޮDUA<,;oGƘH )MdV8?r{)̢F~@9(cUy~J[#[PF)F *9/HxwNit/t eu˝p]a)Ftx#Ve2)Y< 2mm+[[DW**.]:y#ZpQ& Nˆ҈rUd*\/Ε $~hxZw.V+\"tnJ\h(lw\`uFR~#$0P+xJQ $73şy5=R1` m&TbJN]eV7 kZ0n{?}a_07-Z[7NHSJ`6/Ι3G. 6@v۲$Ö;Swy}l FHF/<䓪2hMbb-M_/~ѭ&1n¾b˂ V)}M _^{|!zPA"ЭG)O?[ϟ?_>X~(YLcikk?:?\r .]Zx-馛CMwKoeb=ٳ>V7\1s̙3D K/tߤV9%+lcғ/^gQ;Lzަ /VBczb}I'[Vk3|{ߓڱf̘Aj~t# ^EYeΑ/|OCyO=Tկ~%ԧ#TR;嗿q9V[m5J׾5%Y>x /yo>9,\P_ve 5曫yYg)!a!3#(}x]o֌걿Y׉ˏ~#-+T:;O<[1|`BluQ7oYtqm?~2E3yi[b+hYDGgʻBFM>]/aT TK4FP=q#4}{.1n믿^,~ԟ' aE`M0΃N8A6dM?ϢJ]GpY3 DBpmiկ*ro|Cz)u  ʄepB dI Jr6z-:d֬YJP]t~?c>h 2|Z2pl6^=ڮŶf"qQqQ.yĚaq~v~ :zRnP%#P(6m 22Sp>O;f/Nߐ+ ퟎDG qmZL$HؽK-0ӡ 9Gs4 XASLQ R1!ǩڣ_ hP y&1ҡq2Ž3vC%Ċ`P>v0w gs!!u.r6׺kE8xoFz欟A:ALQw siw<ΑvM5F{ /P&ZXx\-d[%$W[ @Q?|ARJ93o(:HV/" «qa?U zC nM8j 7ܠVn>?Td\ MU0> AxNSn;cL ?K;s9vaz arG+ރc.J ZkyڹM!8}<_HbF_dȸcUhcL0e5X- =X8Пglmavv饗lc|XE!}W]z3n[_uB9oK-.{GbQnXhpy|AG##ңL '\05FDDⱚc&(:(cD pf9c3JY}#$`V$`aiB7d^k9C lQB4aRK!$wtzrJ;F!ӀPU{@Ւ ri=i,vcڱY +{vB.tnP6<} +^F5! xY[o]c0ø+'0`ajƞ`a[ZV~z̺T:ljK'/i^&lA4yўQk~k|2M­iȥPMc3~qɶoV=@\xZ3:z8е\ג4檛2eˈaޖwhz\v/g{bAGEZ1X`e1ێgOٰF{?7iU ֶrft>x,R \#,.=OaT !]N'\e"-H)T#%S8, T 4v4&7ZE)nQ].M%x~buO^)ه,]- `=} fȗR96eݫT?rh*`j&l =?R-O)5XͿZ ȡ!mXʑUZy6Yf;nCؤo"R,?.{B|_5\Tm>zc/lLFkA9ydKk X%Y &!PA/ZL40AY,󅮅 i</,{1]HR2$X =!)r*VoDƥU luyTZ~SlNVJ3 QC[Ν׃>(q%Ag?|+%ВXvamF:餓yN;4رz}6HImO%_zfdp.&P g^5 ȌyI|b)u0k`♹7 >{цCc'>!wZ\T]&ʢ@"7{>3Z{8}O<g 9#~[YC\{PN6M~򓟬BRLEaJʾ+쳏~T4Վh(̼o" eo4+9}rG˵}E y( \g7Voǰ<@m$y-"Fq:'F { Uu8Vg1tQGk-^ IDATxAbb\C&+mgȇ'fԨQERc=txJ.n}c\5B3`0܈ mFFXiRTՅ ؘh8x;lا|x9+ϧEEҐ ME-5hFѡmaM:UfΜ4,s7ias=yv7wlN?я}W]j76 DZV~ -d1Qrq$dYW}~VF6f6u= sGqκ4 ҢT xIl .ƅ3_Ɨ ) TZpTFZF~Ht2=O_d!$3 +>qzQ:Ig>k~R nu$F 1 0-Ch ,cV4%o4 Ϙ rz40;9B()'qhdX7dqa(  , CB zۀ{z"+PWUVi$DBPL#jP?`F*BiX4h0ܫi? h$ QH7²qql\u"Ô/E^|9;5 )J"3یBkHXE P[y)] W 1o(e!.N{)Y=^ ^JChPJŖ;W[UG xN~wy U^ԚX=2r*5c2І,JƟɲ8y=pB*F@y(ӝ`B 3~З!Z#U,̕oӮJsJɘrP+jo$$ug󗓅q{VLIa72TRp c k%30J.6'DV!|h!5rl,뮻a[D2kH`_J ,:pיJYTCo'o)ҫt~4kqB`jQ5x~´Ik@ SHF28! 0TQԛ> =H+za:zzO/D#Q'Du64< V4Z=BjH4%丁B=dX =?T޷a)4@uWM_9AΟNS|7==_~LcaFKzNHWzR>y{qLVZ jei}=[?720( tĽ[N>d&|Ry{߫yႋaچO[u/Y,|ƣ\,ykIoϴTDcjVaSN9E6hCW;]ì'&0<! /r 9s^ٴyv@zsOl~cg=Эce@v8?"NLw/b=v[9cekhҲU=ePgI=G-ǟp~T6g2i/2wM9{キXGp(); oQ]cXFJ4Y&EVI'C#6 (#AziGEkGCE37X(r{챪O<zwuv`{4HpN2vfZ. (1 h$XuD#?ՀfoS |qYAfC~E,p7Z^!qqkȀgs_՝lμ.(R`6SN-ZČ g?+$ ܡZ i \ԋ`97Ni;1W8묳䠃{N|A%QH\j>m2Q@=Qx=ZiC5іQx<3c*KX҆KݯiNP%ͮVnG\sMB!{=G߲+Ʉ ΄t@{ ⳟ~:/.|hgVLXB>B0F!ƕOve00=RE & ]SDx/r4!'ZkUȘcĀmX}"Ѝ[c<'wk Bn mu!}s-BlDрlgȍ;7d}gR}gK"<{xFА:VV֌Y${똵2iaa)qJ = UXE혮w떐c8-4c)F["9yd:>^hvHkP#XÐ4nyM t8duc} [ܸ.eP ,`zќyG( w~<#J\\IC & w}뮪C<凖0uQa3xkV- oo@X7"ɏ[{ œk\e4IzGj0¾KTADtcȊ]= &#.7,"pyc7/epꩧ?]-GC=wܱ%/Pe+Uxi+Z{egkH,30z0E-)nk!yc( \AhFd I^%z_ 3AEpm;BFe,;n  5٦PdrfqOEXvizBEx:-XmTEP>u n6Il*4X 騏.9SO]w=ڳx;CyZ~" &#@9-xE1fbu"ڑ9NZGE@׿;CzyXFoJ tΔx .ԅzR4x2'EAfVO$˳66MCل|jLrޞ5τA ρ6EЄ-Zwep ޳YNH#O96hQg}MH‚6w%FD]LA2Β7O\HC sx5ySi!Y+* pJ χ* BEs7KYX-҆H?4JLwp  s(Y?E^ڪ# Rix'ji|ءJi|"tǎy{ "p*i 1rZD$]6""k)?BN &HHWɲIyP!UJN~I :]6%-k%(攇=$Gqqd("p `E @f1B4*SOE!4*傕V0 ȾX0ɋh1z T0!=߲(&$ *rHUn>Cx~_*'pE%uT3NJ5Ms9]9VlBfl0{1~ĚLfw Vk9*F*|y5 }C11PBq`z0e\Y} Z[[uszu8d)٥W5FJ:Evet[p8Bn]*W_}nǖ:UJ@!՛sٶ| 6Зɋd>u8Z6瞲*5j?G9a0w84F#Zy49sȃ>(sp8 –Y!O Ջ\ROQ;xƸx 9d„ ǐ2믿^8-8zO|~sFXl7a=ʟr0BbF5 x Hq<{&7E8Ⱦ[v5;}YŠцd=<07j%F@l4I8pEُFYp8!9ۨ .jKX p86 p8Yv8G_V~Qap8FyH_p8](![ְHl0i(U>"[Kc(dWkkkvq`̎m'veԊ p8Ȭ&Yr\}2}tinn;.R/m'MUW]cxs8C )by/cԾG\7"!|̙3Gx>Pm1.zޑix~_+crE+k;6xcG!'Np8-i(ֿT^بh h˗/1zhcHB$!! hw<\=G 3 UofGaA V}e* ]D/p8 J/WG4Ej@p8AF#%t8/aCNHpBr8GV1(.;p xطp8':G̃ Fp X2h=!5p ePFp 9 dYj#ȱȑ#uKXX;z뭺H.7":Q-p *PCF\s4dH"ؘɓ7ZJfEy~_ WB-= >}L4hT^A@l &Li <範F`%%U JHcKصp8 ! ̰Y\#}حLG2Czߑ!<o" Aj![IGZ^h-i*{{J P69rpIL,Έ.ϛW_}U~cy5rZ zDއYFs̑zHw)9q~ޮ_~Uon61̜J~9ȼVu IDATUK}`}Q9eԩz<kiqB~z{J?N( 4|/կ䠃R4ck]|]ˡf L2k/}>Q&'Z{a`)cc" .hDAb9!9c@p8A'FO}1\p81(A pB%dLs8!Zep8Cr8Ǡd p8!AH0'655 R=p %ԺАpAB˛o#1˰FxVg,.;[o}{ˮ*]v,]T-pFt: P*}iesԉgֽAlD}Ac1(%$a7O|vɵ^+'||{ߓg%fw* =֦aHڪץL6\˧]kߤ|:xO%[IQMYMsGx=ZVXQ Cy*>}l喲&V[m%mkDI'Эs9+̟?_=X;w~,[lL6M~/Kyꩧ㏗#GʢEN;Sl/}g>#lzX]Xq;Õ̙3EN{رr7*K+jΜ9K_r!rm!j'OJcQ2e^^P K m4w^qܫ-LJAg!Yc1 \bXI O?tԂ Ұ`al#?c;aY*\õgI qc}u!ym0p8|?$1\Qp1(.;p 8!9cP i!9X1(ѫ*4NH 3U{"c a VNHp'%1Ԑ^TQbR7ϔBUc(vF5\'#زvyg[u۵ZZ6tf&\sōPUɓ~Ŕ7)z4VԒ?Y2vζ^]v 6c'܃>x Q?{~v2jmGZpu*-$dYh3rsB啳JT9S;L=!i$ n(^#<"~L:U7b:`1#]wL0A?~ s +Vep8CƍSOA8! xq<hc p8g9! {'E1̷fŜ# **`@OϜ0c" "bNw @̘#~m{fzfw~fzBW8WH1= qjεq'588U+*V9L\qj'Єqq!98U+*X-q&: ]v8NU.;qjp8T_8 :p}8N+!98UCrq WH^AֽqZ2q.;q*I 8NU !9Ӓ:F.;q:$q*uH8NU !9R!985qff88Ob )i6i~v2휭xS(62eJ uH85PB(9|Wag ڵ3E0y\XjǦnk۶m;/b# 18NKf!z(lk׮aUW ]vYr ߭aqaN8>pp'[őK O<0h T<ȬqZ5Is={ +*tAN ^x?JF>C _{ώ믿(( eL % q |x8S|vm }S<4vЫW*c9 ĕܹsc=,-_FF~i={g/&Ne;q kF!0?h3\` ॗ^XUI+)9馛w6lp6H KSFXLݻwkVksai=#W_+":bBE<8N Y|onJ#]w Hn喰RKOr E= 34P(>Һ[K/mǰ [o,M6ƴذ%OpqGM)$BO>6Fѣ%\0\s&-l֡cǎ6EXP?Snǭ?nV1ibVЭ[ЩS'?cNXF~z3fL+7Eۏ|0rH^{5s#2VI foqZ(YkeGfqw,̬c߬Ɩ[ni3p\f=dP hjp7ٳgXoLn6Č.77 mv2$tk߾QSLMq-~ gqZ2O3a„?f1~B.'MFȣfi&ZOC%ی|k8&<0IݸI x|j:8偻O<.iXb?qx!}L<&K82;f?Kq ֦nj YK@޳U n1"> mڍA6މ(8pqLqƼΛ;RZ;t]qbXe78UA)$Yg"1}j+hAR3c8NzpX2i3;NSr5G >8N$GͼVU+n2>0Uʹ,468NKyX3q+$q*pT8+8Mr8Tnv8T*L)qֈ+$qqǩ |R8SBl=8N %qq!98U+*8Skd}͎q]v8N qǩ \!UqRuqVCrq_8T*q翸Brq**L̎8-PaU8NKBRH]vF^;qjce2_Tv?8SR{)%wmN`i6.9T _}MR2eJ~+ЫW0s8SuPFW]uUX~ 3~wp|Pb*hay絇pu;'hkY]v§1<ˬ&8Nj۶y}ʕc* |Ӝxi$e_()JR)xKsP:XgrHO%WHU=| Ѓ=~/TYJO:H1)Fc;4* ~ RHVR}eySqn[E'-LuZ'q*wT!h>(<쳹cPL qO7|6&_eԾ}{(uC};*zqx6lc)c-U P-3>DZN>s7wJaşi)4<~ˍ9k|zٌrpTxxRǍw:ud 5|Q u'^޽_6x{H;/RZF| =hr + SU>"sȐ!#4bꫯo H' SEc\(W^yf ma饗-\8'|b GKT{ƂfqFpIkNаYI9 /XM6l6ue +Ç?mCPdY:%ۑUȽXd]AcdeՕ2_Z{Hw9COG3X-T.* 'W(]K[mUk±F ~+xHK zpo&wmsmOIk=q#8~so_|aʇNK.٠He%6ϧ2;St]SMH2=qD+XnQ&2߶rnB)b+MGcD(o9#,2ᤓN ~){/p vڍbqyqګJh{N9Hs[kFL1aYf {w3fLx7fmfsOXxX^/=>ikHEӯ_?KoM75 %*6nūڬ&Ʀt1qZthxS^ua\mB s9'ֆ7zɇI&K.x/&Lh I Ptпkg5PY0@94jR UtXIW^yezM1 $oF qR>hb65Qy @&`5-RV9+kF[qEJ $!9 $VϚki/ ]tcOmǎsC/b>O r:[z|Ah׮]ܹsyŠBQժ"O{A>"Ӏ>23v魾D>mXe''`* 7?묳C6.]w5;#^{Y+@ޘ 0K^3JV aqwwҪjy0H|g}'9V4HMih))ǩ4&€n):a̹lhh_׷Qk:gw%ڲrKCJ K9 X~s\TchUv+(0aǏ7Ow}8Z1,momBKS:k1%N;R;JcxCEGqz衖G}pkvoOjp!IJ` I`=ea\\Wۍ$X)qX2nYMJg?$, . `&a,o߾a3SL6gKqarRqdn:_D,LJ&$}`nL0Epg}E)A~P];)Ċ-MXwu2?M %D{#ːrq / -y[neXb%rg9L3a„? m7/!n(PڦM @-Aa|I~0ɛf9LӵA7eo*8Jkk%WnBM&M%1SKymruȑ#Æn[_CSG]o*LkklM8Mgb|ב#Cy#!lKԐ(_Pw}>)yI ʘ^J*ƣs, MXW/&Y V9'Z(r]U`UP ]Wbz(V!*ۓӊӗiȁy晧! 'qt`\i۩&b&I!gW7Y=:.e+"NjvǕt<.p}׊ʪs%ZiNT_ յiy¥$oPۍǯ1s,W5k UfR1@JFX:v|a0U[SevWpjISLN XWoU) X;mq,!T( CXKUBšLii i^ \!U ^Ay|/\I,+,x1rw,hn 6ȍI У`ДY2"3t ?ejT {b-uwkL-rpTa@rߩ8MVN))9MkPܶ҄+flE*!·'|]ݓԧۏuJBR a8E1EU45ڸcKNH!0_%IoZKR{<ϧjyzd9J8ҌgjzYZ(%D5Q_a\&\wY=B0 Zrj,R% y ?裶sJr-Z6i:uk/lŭc:;80i`؍P('d l IDATCKw^3õP\%Me2?I^lm1eY=\G^ ޜl&߰[/6wݻwlOn>M~,=WHD'UPi.hѴ  m4;c$-눝Qs% uuuaeE eYv-'d_N;͔9J ;0Va;3퍵ƻ6rgpgj6l 9;2mQx6dĉbK)k WHʂnTVI|Q"m_}v3|Gʕ%N쒒n2ˆĝ+_ضR$Aώ ^1c5cd^]EҸ{ [yo#w>zh[[mWɓf|Lӳe=&7;F!qOq\F:mO uoWI'wB@9M鎷h'%KzR.;)כɹ,Sy϶J$@VU(%{&L@(+atrS: cq I uEUN‹Oi$):Ɲ K@U"q9IK, "3~į G!J9b)cf!hqi+&bXRBZ8u, V\zV2МD*e "MG ի"ˊ_PO _6_"S^%v7ͽ>@5 րV<6!up1wĈ#GliuOx}&'~$K9 |0ۏ8\Uiif=|U<^Kn07å5qEgyƄ<_fhŵq<)^-? T+nr @ ႕oK.8qgNav 7Ţ3`{O>Kʹmwfwq6U2Cf'1؍owT:<Q*.7YYNxU&)ֹuhuuuTpWI8p)~í3OǏn6; &뮻rBbСz*,ǰPP&1T.ǀ,i3D>a 8s[\}AM,AۆUyY>i$`+Y|Z Ɏu0tuE{Wp]1޹s\)eRP=m/}Y+S cZB*,;f`C`I!559JCZ9M8-NԫI7 ۙ@P~IF\\X:uU+M}1c)K[l}p;0EBFlXMZQֳgϜ-( AIk%m-d&3PL?1>Bd}{d vv"b.G@).̪4s8grZ+$"ϔA a\( >po Y@;vZTou%iB%.dfqW^6Օpw,6oncVXW+d:,XĪw&3w-!RNgQ)<`=te1w":ezc]vEXB<<Ʋ`,w2 7 (&K Fmicl"baM1eR&&HpMB WfHN dpDz>2S3sjEU+$YD8{X;JCae>U\xX3J-8L%@I/X]kr* ip݂1DAiXtę=)q-`ǩFTW[B7c19-]/}Ƥ`\Gہqpph%V$XZϠ$H4BVK|Rb h 6ӅީRxdwLYJxd h3N,_^ǦZP=su|\ɩvZB.L$`RcF4j4XT{\Alh^|,dXHSiǤ5 Ě8xwk=C&4Hj.3f).EcKڕӜdkջҠP4 1aR`X:FL1\הbzWWWuf1"JS"u>YPFL TEWH ,PV =jr3ņ`f\ R{ՉA)ؙ= 鰨.cX2Zx:)Y!JBpz=`Fi:-:/"#ɶh쓉8,N^ߜjdХ*Z/4I)',uG,-[f|RR7?n;N՝m#BRb i:2g}h-3~tu|IjgA*⊩-:NC랤;BD II(, =~ǯl|`HT7^2:ǝQ)U/[}fXfͰ?W6>$QҞ믿_^Ki&LVvz[e=1q ڞbOqRNY %88Ivώ8Nr8T#qu8S5dV4D0q{35qWʿgٙI/wA˷v%|9^l Xc4._z\+i3+$eS]Ё ˶i(ް¹?_%_,4%.J_H#B"#$;;6lX R[l{«<}p]w3F13Y w߅7~uai,.)W"Bb> za]v .`IZP87|=^%3*{s- ; ř*+|/g^v$@ÿ馛¦nXb `UJժ L֗^z)m0?f__ןM{RWWgȢI"4HeJ |BSo)mME̮fqjwI_cm/+?>O6|pRV|B߾}sJ)Vq8?G*P>wg'x>ע36㠃2ʄR1>hxq# 3 } 'pBX~ÝwiaԉгZI+M0;稐~q9#K#-8w'4a9ݹskݻ,+lXnLaȼ;|[UI0/;v#yu׵!e:ʔ.[^z/ 7Ījʓks=ᢋ. LZYgwyV[͖Cp KQJ2'ettw)%OZ1)Rx AfKsK-Tկ0iJ++J#pc]s5&( fnvp"B4xȄAq!< hCˁOeW^ rH8sȑ#M`Jy{\}^Ծk9,"*@^yB?|S(P!ܡ Pf4OJ^xoصPXT2E#z뭷,O(.K#xM,p#]zu2EyP>qQrr,ѣG5KńPZ[(|C S+uԥ؁:g6 v@Az)k:3:y7/vK'uzrA#X}<X.A(9\ 7BRfȬ2< DP}'A аJBBW6ۄSN9%&45<\!vڙ-c"-bR )ܵkW'AI{3h7Ǻ$*!קLKN~9NQ2dE@%Oy: T~-jq<\r\Y뮦) zzgF Bʓ|bqxM~EщXdEm, 8Ղ`g:^hs~ MBahXEtO:$$ 9NNq౑! .e1vO-fQHR X'MK yE"A3~C!Nli!xH<\, aQb+ #(0D>J폀rK7A?փg .<'v5Jҧʌ* J-sCyPNTV\`sQ~QAq30%ZqQV<٪g"q,.R|W_0)si>?cD4@a.CPr6a5r)#Feoi{]l Ƌ^JYK8cLrSw-7eQZ)6!Yia㞿>W7Ղu#gP/yrr}+|3JCqx㍭l7+2iar(ݳb-Cso%}.rSi}LlK.kƖ`K=4X/>PG!t9Nz (ΑT^P`C`0XQ<#W&4]Zy _0:,>5嚲DSnznJȺRy+m(mͲQKo3!t@ttrV#a1^)(W !hMd.;hKbyט%tjI<16AT+'ʺm)N |HKQS%."/R 3fEͤ534F$As\HP%puo(0!KY)G %&^#ŭ/>nMzfZ%kݺu)6i/.g,OqO2r<\LDA(ozuuu75|Ha)q,mĥ P4dN).0ΩMDzQ8]9ӽ lRgUNyib3 eD·om#=sz y}-+8N BTq8u\C&xZyֵy{H8E]\mʗ DiҮ+FZxǕGB RkWJ|.ٮKOe$M)>l)P`6nҒ⦥]zsiaJ-㤥+Үg)(|eJy)OYp5_ش+X~=V|>=7O,ё;܁t1/I0siy(EvAE&__|uf"՘]m#*$d!E(IDATSŏI_ s\ 2xL4JXRǪb_ `X`=Ui SKi/k{fܸqh Mz PY&1-->Y7LPXHC2Q"Iʍ]=/Ǚ+iXy0R7H`vBfPv(RQkӆ˿)$L[ Z\#4F6\<)+#+Bn:\|"Y 7NF^ei2r*˿)uSYfM7v8㔃z6zaZu58Xd!iz]uv}7z%84~ !tP.: 3p:D89qqK?4=^]ئۏb1B@ |qi b]"o;O7to렭4 3ɓUo%mξbl;(WLG-Z,PPuB竩d~uno{qm2zC֟{ߔs]%XoB_cνvիVB9e5WҎbi,O#^d>q{E sH˛vfJ_ ⭎C^xY%܋v]wÇdY8Ctr-W2/iK#??Ui+_8A|ƯڵP rMCIENDB`fltk-1.4.3/fluid/documentation/src/fluid-128.png0000644000175000017500000002370315004135251021476 0ustar albrechtalbrechtPNG  IHDR9Q]bKGD3 pHYs  tIME 3=[tEXtComment̖ IDATxwxTEw[v7M#zGH^ XyWQ{ "A@j ;sn I <ݻsΜ99gf΁rEQ@tET͛I]!,i >,i /+pۦ \R \~].ө *J4nhD"d*~ߛB${(J Z\'6b@W>ue>`J+$ !9fdu$A~A 1qoL*Cx o]AT$9Pdj 5.V6_@VNgT"N%K<%A!pPyt:P\VЦMZK.9 "8R[PJ = T4QdD Yffe@Yd!&-þ$ AYf/Or! Dwܷsd!Z$J`f(Q⛇bODZ2#)=#L$%EMy a mS((]rBA6BgYYD̩93UQsJgJR heXPR[p@y十= F2C)S-{[Q:thQhU]0K70|>)i+_bE`o a"꠾ 6&tJ(|^s;0)?A8O~S\þrdj} HzlyV[~`$!00ZlF],ƣGc҆C:m&\E3Xmȍy1j/|42QԽ$ׯ?ר}V^Ɋ&(;OZ޻kbFK0t,Xld9hWi(\ѕޖB y(f @YY7`rmA뚐5 UDX1CjEi%jZUJԈP@?(Wk׮nbtU]n먈lٰ2/YY1)t,n4/LK+|o-V,2_6_ژ60Q7DMz$ p:~f~72}_.&)|6GGGKK(t`tMR^7&96n _ngx4CU0oU< k{f}6 FJC?&\^s{Rq!3 Rp4C`ν EJSmy䝡xͧ~-:8UGȿ?LZz1!yh^\«3<+m|Tn = }9.[`gݹ ugl<Ԉg{=;tWA[=-hwOUcOG CrU+* N ;AoWk'vB5#&I(w OIVf cȃZ*:&&+R^R\.ZucINN|'g @#Ʉl0.!Wy,T Pn^ZCmB3]"11C+䕕_y)*; (:~gegᏀA. 9 z2aC@EP@-f͚&)hÏ75SiR{*3Ln  +xe*)333Ei`РAMv',D!+Eֻ\ӃO+\mjIr_Ç]Q=@[o)i4pk6++ !r&lQVpBDL٣qƾla= ]nko6z8OI SaXXf :tXo[%f#Y:Dlݺ56l(uJcepb n=F3twUki>.=\?9t@ w: ?֍Fr!!]mgͲB@Zᕘ;'NB Y*cH`\3IJyr~X'R9O< gj٥`"_: ǟiqxݑ/tme\Ab_4T `"x\=~zMz"k>kΕ|&ž.<laYd愱s9 Wvڗ \YW.n'aze* 5cuc1"i 5yவpYl?N9sN4ߕu!:( z<@#M鸲OӹԄl<>/FuI鐛Njo@Ъ^ gm&?L+̓&9U҇IBȺ <ѫ3_^:rQotLAL%vX wxۼMñs'6mhuE `/ .E@>N 0~3K;w;y}n2^NUP F~Zs)7`ͅ䌳ŕ#uNQυ64UAb% V B@  CBʫ P&Rܶm*MG,0 !7J0>|pTX*TL}H*RTZ$yiYehd^pJ:[΋ބݧwxLOgA'Uᒨ͕=F.`E(k,+.#O8!?^Wؒ`\fƐ({ȀJT2.?pڵ>;(iq`0*gX.+NQQҐ?dff"`\eիepE޽/zRv=Ç3dLx:vF_?r>#@oߞkY٫i7M1>< m#9?ygJ .t #@Hs] V^Mba:hCҼysٜG;IVc|[''BPID@vVvJ/C&u.f%}Th䄨]:78`Mi(4psg+m-ܣwpF CK?z'3oWAQ483S{+ 8PB.O{鼖".y; ߱_^<hy%msoe(ȡq !3K* ^!/K>fͦFw k%wOAr8/~?ρG#XS62 P=bj?~TXi8'[qN$8]%0C_9I2'%dcPBFG~d癟#+Ov`\.CC@/1-8 o_iI3l5QfC tlM!,ҝp'=rjZt_:9RDx$~EA@ՕS&z#b؉?f|鋞`e)D 1*y֑+y=5L"wEbaZ2oFCx]Nmh X)Y u |^R,:L?o!ӗ7tAktzFuxW  k _!dU_ y&r`5Rfvl.v=А@-sR֌9,1U0 _y0 !^: W `O4&j2 ބ;ظ(f\$Kֵ<粀ʽm_a[߂lbeXfy-y" @ˠ&)caH$i=0Z1* s,#5|V d<|.5yc\<"EL(LۋCw.*6fKzL$^]'um&='QTtL#g;'yj|quĂ!ߨ=!ۯEz] iդ$VCI W~i.<} XbFh0pѳ*iܯF:Ǹ;P0O Fg~t,e  ]^))ڪ_'I)sȃ:*a:nh%`jRλw,C#xɬg`K]"4rvsc%2Ȃ+DCC; y. iK =QF>!!5`Άt1""接=/_d@LVooD?h&F^鎟Ix]k6T*% /{>-ZЮ];FR||8͛IOO'--?~*<-LHN'HIUBw.F.[.AkÇ9"s FwD{ςf~_&#ecǎ:]gh]v/$SEL'g?)OG XM a Hazl|?쑻:KTt@$Cn[a=Í ;ɪ)܂F +[AB܂f3XF*H$@%PEUJ `~5 !>›%- d2y!JC/(Y!OJ8`Sn/ 26-h2֭[$w?HB'23wVMl"aBwyگ]0+r!mp"c;WMfE?22^UETn/t{O' `yiߕFa "$[hQ ֭[cFUC+ZеkW+HMM )_t(֮]+*<(Zl~&HT*8;ƌJD9OM`F+ k-UmS-PMt<gC:-%.w^ڶm˩SJZ U#NtҥKC:>IA%!d=Y2"Xd  d hdݺuO|gW{>u0]vE"@*( }޴X,ر/_0/l?!V o>`ޅT0_/,s-+_+?[|/4!n-YF@JB}!$ 4H\(ꫯ;ZŮ>s<m,޽e@Ft0hs;v_=/Ŕ~rmcn6݋F'|۩A |wu:oVȃ@f0B+Ӑ ?osX45[/H ` ózͮjعs'ѡاCm<TvO])׌<L,bI| . d- #vA={67\ Pya1xKMt֯_Oǎ5H+;o]P[ 8FfSfɭl]Qس4np%< Vԫq᎟!} QABykˀ@rI3Y[9\hcsgmWxIPԶ7.6}z+gX -􊛾FW!|^8 4>Z7qT#m´GQ=*ĘԏOiYs;֓T guXQԋ.wM屮38} Rj{_h..yGq:ԍ9(4MZ#F]SB]5~ڟoP_4wW0A{s=?:K/p'M78H,&4aL?`#ٽ,y:O&3m _%Cq|z.`YnabZs.8pj='C ErSgl[RƐ= Û:8o$ݚn +] 6Ϡ7yV=r4VE  6BـF.M3B hUsL ҈/ApyoQ?Qӹ Xpb9|u5[--> SD&|4^&sAh]yA2È=FmOjQ^?#3 ̓cR;wǑ}=f,ͣsnz2;XQɲq49Wh=nXMU'gҏrpO'Ef瓭#~ 0wv&-1rz10`zQ{hq;iYs5w ):?+V8AZ"ҫC<Îcмv J>?\ fu/K\3FN X?K6u ~nIsDnq? z쾪 ǐn{7XUT4 #;r[K5X@>ހKݯ('SrԴ;FON27yYbSvs]~;nԔ~(\ jJH^ w]>S楯{h DMk/ۨӃK!ɾe# VY{';<uaZe6-;s,]9ݏ z儇YRT lL'f %#db\3E,Hn[\` Ηż~`fuFk4J.wå0EHKсp3,Er6l"/ fPttOZ5-LuJVŷ^O̎y~K* fl>H"tl_;Oӟ[H fs$Ǡx}ixgiIph/r2szW)  S)Bҹrn<~qq_YH:=3al4fc33SrՏjm8M>fc]п2.~ P2){aQinQ;5Ty%X N!2ߪ9F~exx2[y!OR@nN7.'3vwxݓb:r4 צJb\iԣo~݅Ù5d_4 gWw17z}˥|=iJlh9ϏA2߻#=&f}mI7d$.)ih[.EBkYqG_n_k:$+[j|ՁVSܷEJfv7>yE:KmZޖ7gHGi%RvYmjJd64$Ee)WBUO{:ǒ?0/,wϙ&uWQkOO48}D+^F35_{'+ x>L՜GqKLN\RLEǦUi N 7h .-dC*z94)N.f =0~`ԆjLʊCf{CK{H;͚]M:r ,%)+Ν`dBc5vl\j`1ښl=Ʃ31X~֭{F咄9ڿjȂv;Nό撥XLYξQCl5ibX j0NsuzSoe? 2ADGO`0nJj&\ꥮ nEzҙrSczL/2{qP#MG~cD [-/`X=כrJih(\(Ȓ^G~]-St.E.vG5Z{ө}|w)~]N׊妼?1ҟ=nW}zLnOެ]StArfٔHY$x֐5{ݳ2u u/jd9S:}fWB+n7oe$Jr.vnl.,# "#gΪA6CEf( 4)SҲŕ+;;h 2VɮR/ȃtj:?KAA^n1U* /ԅ3h>Yֶyϳ⦓ vTAòq ڑEyВ{;VULP% h ri|JMx2|UL-uHIENDB`fltk-1.4.3/fluid/documentation/src/page_widgetbin_panel.dox0000644000175000017500000000231315004135251024212 0ustar albrechtalbrecht/** \page page_widgetbin_panel Widget Bin Panel \tableofcontents # The Widget Bin Panel # \image html widgetbin_panel.png "Widget Bin" \image latex widgetbin_panel.png "Widget Bin" width=9cm The Widget Bin can be activated via the main menu: *Edit* > *Show Widget Bin* . FLUID will remember its state and dimensions. The Widget Bin is a great way to quickly create a GUI project. Clicking an icon in the bin will create the corresponding code or widget node inside or right after the selected widget. If the parent widget is not supported for this widget type, FLUID tries to find a better position. If that fails, a dialog box will pop up, explaining what type of parent node is required. The Window and Widget Class icons can be dragged onto the desktop, creating a new window or widget at the drop position. \image html widgetbin_action.png \image latex widgetbin_action.png All other widget types can be dragged from the bin into a window, or a group inside a window. When dropped, they will be positioned close to the drop point and inserted into the widget tree as the last child of the chosen group. The order of widgets within their group can be changed with the `F2` and `F3` keys. */ fltk-1.4.3/fluid/documentation/src/page_introduction.dox0000644000175000017500000000625415004135251023610 0ustar albrechtalbrecht/** \page page_introduction Introduction \tableofcontents \image latex fluid-128.png "FLUID" width=3cm FLUID, short for Fast Light User Interface Designer, is a graphical editor capable of generating C++ source code and header files ready for compilation. These files ultimately create an FLTK based graphical user interface for an application. The FLTK programming manual is available at https://www.fltk.org/documentation.php . This manual provides instructions on launching FLUID as a command line tool and integrating `.fl` project files into the application build process. FLTK utilizes _CMake_, but other build systems and IDEs capable of running external tools can also build applications based on FLUID. The majority of the manual focuses on using FLUID as an interactive GUI design tool. It covers an overview of windows, menu items, and dialog boxes, detailing how to create visually appealing and consistent user experiences through drag and drop functionality, a "what you see is what you get" editor, and alignment tools. The \ref page_setting_dialog will detail the process of initiating a new project, creating an alignment template, and incorporating internationalization. Several tutorials will explain how to generate small apps in FLUID alone, and how to create more complex user interfaces, followed by some advanced subjects like creating integrated reusable widget classes. The appendices contain additional technical information for reference. \section introduction_workflow Workflow FLUID stores user interface designs within `.fl` project files. These files are transformed into a binary application through a multi-step process. Initially, FLUID converts `.fl` files into C++ source and header files. Subsequently, these files are compiled into object files, which are then linked with other object files to form an executable binary. FLUID-generated header files give access to UI elements from other C++ modules within the project. FLUID can also generate forward declarations to variables and callback functions that are defined and implemented in other C++ modules. \image html fluid_flow_chart_800.png "FLUID Workflow" \image latex fluid_flow_chart.png "FLUID Workflow" Small applications can be fully designed and developed with FLUID alone. Users have the option to include shell scripts in FLUID projects, enabling them to directly call compilers and linkers to produce the binaries. For medium-sized projects, a build system such as _CMake_ or an IDE with integrated build setup is recommended. FLUID in interactive mode can pre-generate C++ code files for direct compilation by the IDE. In larger projects, FLUID projects frequently reference external resources such as graphics, binary data, and internationalized text. In such scenarios, it is very useful to distribute the `.fl` project files instead of prebuilt source files. FLUID in command-line mode can then be called as an external tool, dynamically generating C++ source code from all external resources at build time. */ fltk-1.4.3/fluid/documentation/src/fluid2.png0000644000175000017500000030554415004135251021256 0ustar albrechtalbrechtPNG  IHDR5c iCCPiccHTS" %&H %@A:IPb kAEˊ((bC,^YDu`C]vysΜgϙ @g d T SGؤ *Ѐva ڿˇ [C 8Kc$fb| >L&!1S5qp' 3?XL)4S`yh~KE)3xefaK,FP~N_-g2@䑽 O%KfFh sLib}!(Y45l%aNea/aEڌ, +(Q,eed9;Xh?UWKIQJ )ebiX3_ _Vܻ`;3+NٛH?)|dxqFҟ\p7L2B !2@r@H@ bxY\`s[&fB lG{G';;r$ޱ"º2[Q y|ppĘ/Djr&zlyΈo:L0KGp0xBHLyA:ev>8GNYW܁G BBA 3qD8⏄"H< R$Y@b ىT"Y2҆<@:^-š4Dr4 s<4]=^EK8 gqp<\. q% \5ׂ} <oB\bj|~ ߉' z;O# %=ZB7Hd- b<1XCl"$IdC$$tttMDV!\BO>MI!P)fwJEDɥ4RS)T ՓEM.Rw****n*T$*KUJU\RTLӤYxl^ZN7 z% *CN*R]ZZzSEL6K-ODuWusu@}zq{ 0L5.k<$ikk45wib& CX͸fL>3YbB;_t:::uuuuݮ{Axx㏌YE-ۥwM_@?P_E+AF C/CF3/Zl.;]>33 26ij4`lamܸ ՄclѤ٤tB*Ӈf3Yf+͟[h[-,,-ޖs-+,o[8VV۬nX֩mP6 n*&ܳrmsll;Xvv^O40qĖ3w?rtvXQXxۉĩ$II'wf8Oq^ERj \r#-q;]~O[t'[LO=SӳËWgO׊=}k+s-5 Z5T:.l " `ECh!!e!OCC塍S)S6Lij6U:> a[ ?18-|Zg #Z"#G~Z(2:;9F-fFLeX؎qKH 1 {O4{wgZ̜?,YNV-}4? LP!O'mM򄛅/E>^Xܓ\<3eCJowjI+ OR&y#czX،Lrfbq4]z~sd6Y\C{Y &6]˶!3+<ӼyGk̗οk*'/  .[عhbdq%&Kt/ \ouY_//^~E|]?PUZ /c?J~l]j˪+EE%E_W W_ҟ$i]v::麻+(+0eCF7tdRɎٛ;JCKnYkYjٝrz[WmMv;w;wUW"lw_8TS^ގ}WVVۿ ʮ=0~mwְjC/'{$HQcfǶ2j 됺ܺǛ=kO؝{d)SkOSO)ioܲXXHTHP,Ә( h.71bwoXٰv~zƷ.sO;}|Ά?g 92t?aXo{ hox酅 f?eIrʦyx=<n{2eʔK֬^#Ǎmo>޶z R:FYefYJS=Ƈ bboC,ԡVKă=3'"DCI l)4j "Vew!gDjkC| g.h!Ԋy V*Cg=<6$ػ0vXYbʼnu֬w}[)v%(0(٢:g.Uʇ-:Z[º>U}E6ҵVb%~Y?{aݶ'}J8.N͌1/zܸqBxZCC.-̒,aمOJ@Lcd%mބJSS> ᱱމFfT[odk u0^d^f)Bͻ[t^)1oW[.ћ̥sPRWc#wNj 9)ie($s ,Zcz)}6Uu?tZusWϐ֯Cd0:eerM~GZ+rsfC>/ #GGM^d`1`ms-pIq}@%V&ӹ˗/zxl]@&oM';̥dRͼ\DVޙD'pD\%ZSz^Wz ʘ˛@]xj$ k &q8+n]cBT!Or^N, JDH;eҤIbSX~9ɻNQ><{!K!&sM&M?^  #I}cڿЙZu]Krn,L-UMJ =A{K'qc줫Qס c_L~1yֱ.Lnû֦v֭K!ϨQdԩ)IXzlhѢ.=ᦛn* 5RKL֔Z9_~eyW1cOZ2mo:><Ӳ;uXxg;ƫVHʕ+*W}~XV^-pA=t-# 57׍T0+ F1vҚŲvڸ"bK½gHo]D"ˋe͚5e/M)zM/-WVJj"|//~Y֮]+D`mNO}cC^ Rme׬]`옱2ejI1 *QX=3.;"ӷ0!F P$!˖-S!r>.l2%|@ΖIѹLz d&!)Ɇēϸq4#/Gau4&O)X)5ɮo!"O=,YDs֬YjE;wβ[hk4.[͢gKf\hԷЅ1y#u 5vq3Wbrp2 ?y0a;V7T6.m}ɝ@k K5/7~7! ;zJ?ܯD.xϐIgW}9ioiiQNYz"wMd+kIw9[>HSO=%[ou90"O2}]w>fٝ1A kcFgJ 4I_|ɟ}]`…Ofmğϔҳ-,=Kk} EGzx sXg Q'F'Ŕ2Y h:=8M2y'ۼOF%͐b2r#e\(FB)1U>"RlVzOE"y.JiT|uwD,J/RfV>E`"R<,VRkkl-F$O P!K1jf&Md d4"(G"!9nqjm 9s"!iT͕l0Hj%zhe 㙄\lFIWK,Q";ܞ矓ϗf*vI-w (,=F}X-< x6-w-$;!p T|@[d}.H ibXR&?&ɨONZ6Tn\3`60{+,];Ǐ׾`$KiDpf)}f ӷf̘$d'AL;֜(7=31Ҡn$M_^&.(-V>4^Ύ gj/NG,be}eTb~SeQ5:h;F"Լ|?ܳIăP2w\ND !iy,?eBrT(=^t );A, 'DLH=v8k !xJD4D>yd?.kٲv효+9DH2("2!t>8W$Br3PVs1yc$ޔv-(f&Oq:M^׮Y+MM:]:9 7ܕ#e++u`Hޣ#Eݔi!bZ|MM BYv;啕hz/(/(*[ Q{@=F ateIhvx9$[O<,0oZѲD,hfM]`5[e&;\Yzl,,{Zz 0Ztg-ް/AB!o2{d#>>Ȗ[n$S5FCޱ@&mFz  ջ[G"yB$( ld?<w̙J0[d܁p xzHAe5 q!Xy.1\`n3S>JlҩP}qMX/S8 yrM?5sV4)!zcD,΁$IERYjyxġs2 I&JltJڵ+e96CwiGU6=2iQ(=SP_}9.Q <`GYwU Z6vf])rrMrH$Sa:=0 #P3.A5Kuc˦=0CSzFK/[>!m7=TJc 24#Ox\5lF͠Da_ t#=%6y@m#ۈao%=8G&Og<1bPfli{1S0K@ʕEP]&J ]U'u5XHuHU+e*o%FUD\AgTT 0j2C/pu{2= 5e ,D2cp otQvf{)ic~C]Sz.EB man p]^ KOO\=*E_qK)ӿW҄OD%. XRKI>G$$9}-dvP8i@p`s1N?q|'FB2*E6'BOI`GyR9VdTIQ<'R:}&;,&KХZi6`S6#!3:r)VaA,u]u*t*"VL4/&B҄\cXAw0rdd .,oߧ=F*JJ`HfXKmЪ c򄛆Fbd@^_z%-ԄRnVZ%N҅ I&)WbeV-M >=Y-ҋ/)_,c!΂V)ґ]Α $$qj6rVlSb)+9wct ̒ST"H,9p:B>FlgYDqF[t:9AfAF..13ԣ0ǎY ;lQ" AL;B)(j있1bȱ γ0bCV!RKz.RJ3fl !iGS`  y_xk@&"|>Gg]Й'TbᗍA2I^0at5>M;Sݮ_t6Y c +haY@0ݥ=CGv󩯸XyWOGiOd fCXi_0m_a)rPw߭qqzME_֬Eh^1W(\f_ ەm:c:1 9,h1eUR|!]cΨpjgPJbYBQizY bKz|ܽ5\􃤱ж٪@|Յ$R .\\  V[k/PA M'&.PX/DUֈE/-R w]$ qs{X B/|@:̄mokʔa}T^vXeMoڏg#I~ I&իW, Q\X BZ+O=v#_^/|t-* %g mP6>ȣ|{pOѝG.]]XCw)BJqY8qE奾qGaa:b`"YҲnvЧKXv -IDt*%9f#6}-Q:@Wrj%^ f aRo.#qGs 8BB^?\#r-7ss!>m݉+ٛNg3D#ݺ@z)y"R%gD[źHYL< V|1w5V>񈹳яNO+"MяW7&3gJ\u!+Щ+v۴*QVp(zӧo!ԳA;jw/-zI 2B9!^+V,IuEwLj>s=uBw>NTdTc$%vʽ{ʜl7N[ӿCsbgqcӖok  цBhqm :) f7 괘Xj x~TI?uGxvq-pz/;>Io<`rtb&^/;qA_` g prJ\ p1uWfmӖZ@c ~^G3&IyVݵIRw ˗ztd)eA9%uUER6#9LbzlCn{%B0m['Ĥ:?5I=W f$:WݣRzgخȄUk߈ L 0ҝUc kpd' g=iM}6 Uv|+2U>tg|[Sp.bԩU3ϵEYzjv2e8Y-%Ykb=)Z@ʨljP!7I|ם;qMWB]A 4l&$1- IDATT9FaP [n5甼IWbӋbkDvE[kl򶉏m@K.gR]HZVGqs)[~^f#CY{{= }]emq!&d}yslb1`VB#ˆna*=|Ya10r^ˆɞWB%X?uuȖk=< d;4edHC{mVQU\U"[L3=CmvJ.lHԞܮp*lOI2m$L\Œ%m2b j n:sUV,gIs[ N-TliA5ihkLs0ɵiI v<,#&ŔC͝+rPMd)mZ%"_c?HG>Z1EIwi,0있DE!J?3Ԗ^k"6:,W"yapнfaݺr ʎ3epdQJ7K$jdRn@JUaq$By,*=y)yoP9elA.g-z[ n=d„bk) _"yHY*]+F7#ҚvɆ+]R՛Wi}7RЛ׊jqTUCweHTZџ\-f3icX9ݖҬPVcc(Nl0 <<<)NK^_y [Aw[,Ȣ^id{xxxxx ̌$>ہ~zxx \Kv3’Q/$VnV$ ~麓N (^xƻ$Ƕc@#uO޵lg 0<ʞ[;I+Ѣ6,:)D/moZ8Ī(/rR/ZHJch ;0E',rG+Hٮ#8 =JqxG\+JG^d|}^":]υrawk_bʿ||߅01: %/H]G{Nul ;=+B)YU 吝ØxkdNw;=mF=S_Zn4Arr7¶䚿0ւlye('p}|Zwu׊yne߼@罯Z8qB#+Zy0}0 ]I< й[m˗!;& ͫeфeͷBk=`WS *dž/zꩾA>H+d᫋n?YN?e뭷/1B'ߟvcg__^S$ rӍMo!w[ZZZ$X.9(||˿] A *J*w=;rTdd6_~Oߏu -w.FBlݽ]A Mک,umo{lvn:ܯP!k5#3knn|l 7"o-[n*WB!bίTF i;O>)7tSzhgW l׿^ P`޼yr7eCO>׃x`{QqCn.j(ZXA}h*JEae ݽv0)++ H7Zj]o~E6TY כlExjɫe-sl畎lc |%"ư@Iڤ[-U3_:ţ:/3<wѓL~w)7Dc9Ft7xzj._}k%Eu d]NW.˳7_y^'[mU?y ho.F.&pUW0۱ ڵ2+g?pWiOr/Tᆁ3Kț]5Qou tZeJmwz wή};ztIm=~uHiNb"!Anu8 `cGG_C9D&OSgmtx va2eʔsuJ_>KXd:5F?9Q@ F  u&YzzAVDhU~dg{GI'@7-NC. JiŴJ`C8FJңHo0Ȅ)yn3an\f({<а2a+}2ڬ%6z 2РԗNǭ/O`n}wMT\IzYawXM c[~ 7nt{ _``2[ nU W_}57MMM%c[Fw+*ޑjL?>2:ф. 䣲,\@ny;-[l֎Sug뮿N9D6}S ~ƣ0Íkt+ZeV%l2y˦ѸqtMe6}t sɖ[n)̓P濶dYxq@;j Ďz)y*b``%?ҥKeѢE2cƌ^̙#lZNJvC+3Žhm)OXٌliD^ }aڴib^b3Ô-[ĉZȣ?uJ\b j:ujN4It ?v_³%"}mHp!˩<2x̜9Sҹd]w=Άu㻲T"\C`d f!Ϥkrz-!)TH?yEk iɺ5y'>%}KR?V9_oIN})R_Ww.EqOeG;N=X^f%({A" ozӛ/#o @:Uro|~驵ݝ^}W$}T$![ַTTr ȋ:x~{LxwΨ劣ug pa' Qc[xlg{1Ypapu]jLg?3FD+~QOaj/u [me|kdr9fף䶿?'R5k:.W>Vכ2&w1}=>uW&0^wu2nܸԊl͔@Wr[ɝ/p"u6 nysp }wS?Jv$tH?A[̪2~2"DmQͧ5DYZ{W>O)5kV:@z߭EYm3k;[Zޖ]}ʘ1cR̥s=1񦮁 bYP>ȅ_W Sr CN,,DAG'Qez8ih!($>ۢ|ɭ0 xtauT~{%ާn&)G7V,+Ԧ@{ *Y6lƒ`fFkT0DЬXu4:JJ0KJ Rb5H=,_\О{~vyg}f)^ߪUPW;P<(Hڞ|=C k I7{lMzgBᶶj8,״~ms`0aCp;쳏upaσ{8ôgl))zk 3&ݣ>d;vl.9 Ҕ`jP~2}ݵYtC>w ,Z-[omLpېL䳟gucE]$Ӹ D}Zug +x4Y-! SNwJ j=b>ZۀngDS&#^FP xjBk_Z 7c%N;QNHy睧 ,fy;w=O|Bau}WB_ze q뭷j:@M=&}s??(9f2%\.b%D);,M?яk_k@qsxsPMQn[F_l_?#Z<PD; ϣ;`H3n+DK/Vw v}wixdQ '\x7PXα<P뮻Jm2,QmgfB |1 &yVd(c%9 V1P5ώ H!E]8:0?W˷XTGo{\ CP,XP36E (_sp9zDP! O,$dW2jeoƃ2K.jhcqXQ|- a}k_Ȣͫ@Ȱ Bp /(EGWV\|p EDby( r YE AD {Gj^?c@cqzU ^}_>uM <8|G.4\_h gD\ƠA3rLӏ@vXh; % Uo;i0PΖ0`m5, j=F@ثY{Wk?ҶH9d0'?X»цp( X  ;j3+觜^-K5X?/=3ב#^w \fc,ւZw%`=Z6)l;Ȭd6cۭNo)?GN|¢#==z$XVX'Rp 6bY3K8,e].Z[, ױ8̧2}`i !-HB1_RIy97k#s=Wq #{(/i ,AV.}Eٴ0X(m 2! rx6w1mr3o{oT2A;혖 cǞA mcDueA(3 τEqi7i} cl& jpuĻ;(*)7Xy6 w#X"4H+s z\,5?M2Zxʠn;L)3b<wQV{pA@ߵw}p ڋK-dqz툇m['@1诛Kna# rrLRDQF&Y [;NuP1_z@Я\M [xfmx%q;7 0 wi6```>+#zrK5ς`(Qt]N^-@PCMrLD1`T"}wcヹN Q3ٶ Ga!u¶`]#t!XҰ8 cI,Xqs@Q$TJt涀 >\I~X>m" SLb]J!O8SfV^{)g?D{ .TQk+,V]\cu A4Egmd{0F*KF Ngf@>f :XjV;,Ȗ^6v/]X_ etAR5iƸ`Vܿj;0KDc̐1c:7@\4ø1(卙C2 ̟(i&;co}1@0x|߯Ǹ0KÂNֹ|ո˘ѧ'铁a@^Q_> ٝ$SK: Ҿ&[ckx}!у[^ EzTFd۵s޲VO;F#l@΢ -n_Rj,/,A`ɄHAږzV[D.[& G(/~аC}CREGIf pA⊃ hӾN}!78@=i+jc yC 3@zBd(BL3X /XqSW1PʈQGt[ vA9IE,ⴶN81,{~'~`N ֿؽo9ed `uL_b*0Xe3}[ՕήN63T?WVk;+}  ]>H8d@҇ y 67b\Bv3!3ۿz nx7t^+Q]m>m<`L=5JXWDGrGM`S# iXpznO~ƢJ`ceee+`lЀ"ƍ "kr>pCeaDrʮ(9۷2  (-oytgF}s-؀Ţ.PTX 7 ZZZt@2b~(i! j:`@- <5N1u֗gyl05NX Xȇ+6P0BK{ n1xѯpc5/mdbAsԿ(# RByNr|m5*侐7KGDH .OA+wPO߱Y+&L>۹kWt&~/aEh Yp)k6|]`YzmrϑNxIλ*hԎb$e2{lX}wzADxB,X0~t T&YYMs eL<JV\OH+[~jf'ʀ IDAT x0K#(7wނ2 s2qkX{)+ `eȌqn  Flɷvg;T,mJ5?x3"v<7\{{DeBO~J~={/AM촛jSFڍo̍#Y2ڻHl!S޲M'턕ض@jm Jٟs/nqam8gcDwJ ҳ>JiCٯUfӮTl؞xv @7_ V?L@ʠ:)/)6no+D2Vyk-&NTzc#k\Q;SyDjٮV- (akKd`h9oÑKI[T`pIrlSЬ VŋCw? g'}O瞑 §KR 㶏 <\e[0ͳ F9Y힑+7% DWX"Mעh}-աY9f0mmmpmv0۞6-Cwޗ>ޕ^ܽfz 1bؗb4C}7-ܪ>AE I;PgҶڲ%?<nB_XAf'#i}&{fOg-+ }G]v!<+4D>3oflc?8`yQF|πg71fpe5" 膳TmdDDfʲTem$SKzBЙl Q;SP:uo-۶b5]KEDV ùlP,2_ZZj)OmU `>{5o$wf%F-s4(ߙ{"mdG%DoP͸ ݔ%ۇ#] D|w=`mR/6v)T䞄@{_K~Z?~0ݫnOkmj0}ɿVj0-oue_֢m)nd i=7~d@#8@,f?Pc[5:-c07wh.ٶveGHr%Y;ذ]k*ߣ0RǾz׻(FB}m᠒2{K9{eFki(.P᱾1{_`PSc|9Wl-X=-7VV)>yxltl[ __uqH>.lٲDiv !<-L_HoaF|a_p*>[kok0Ha7ę8wHJK &ip/.Ѷk/KMmH#g rr#ca:ykt&&p@KzK\a%5_#3fl#·/b'ln䗿ejyTJj ٴתzS&DCgɎ[c~X峿ҭ=<(#5;,vCه؎4P ~rH٢JEo(E|wCM?8\PWjN˯\K!.Y @衣§^r5u!Vi &>q(ٴ?K$+Wڃ_ٻ\FPm^7 >SO`.ǽ])Whmm8 _:XJ ere^cD/f룷&kk 3>#}O:餔_/PV+oUM=9)9?)V!J@$xUD AA\9i 믕oQa{U,D@0eRmoVK_8bX )qʰJ0W\q\tE=~3mXx)IvMfϞS)})-TINru:# pp 1M|CK.Dk/ ꫕ԗĐԭoŭO9 O}JZSrgtdyYg'|ruq U go{#mwnժU`Vr ̀i'2T(#.޻/|BGkI.B1HraDjZ(ANVxEߏ ,Ip&P0"d2B=tɢƋǿlj{ -_,x~ 9S5?>K?3a,|N]ʡq$>{-3gΔ;S{1%ʕ+76uT?(tP2\ʭ'7? ḎEݽm +4 _I7nX `ϒy&2s8 %ۮ5]-<Vh [Bm375;sbbVz;r=(`֬Yܜ.t͛'s_K.4pb=Դ;.VjdcWsv IG-eZfH+w}"OhS0|]w`53͝;WÒnJR<߮ğ:3gzjk֬7<e}4q=y衇dwN;S,ka$m|_ۑNc7S`Pm]k6ʞf*= !Q.֙bd=c9҈e?e s94f'֡$8d^%$>H-9 .i~Q;S<@u0bqQcх^uU^rʻnGnmg:d|Pme&o\5Ms9GnF%ۄ uil;P."9Ȏwڱi< 6B'Ovou s[~+y'^]|/\㎓m\{4̣>[CuTkpaj,,Ά5súdc\ { N왆{=<<<1 6\j+N!XE?sp/'PNf, JTa4}~;m[~׿.wq|+_Q/d?I!q ԋ/V}mg?Y:ƝG,m|?轏|#j 50M DzEݔR!y!n~DgW^yo}S+"_WK/_z 4Xhcn%, 7 =~IXqMշ{ŊZO_~Y1m֗%vnZn]bݓU7ɂޑ'ky^7smׂ`5mfEm^X$ Ԯvh=V-q!XY'ᄏd~{,#Z\ OٮbDd].k3t;/6Rnlk:xl3N; 2id1#;whl uQjY%gvpAֲmSfܰs>?31 %R{ѦeO9aW}ݧr}±FcC2q]&`mV# d~3媟\%֬@.0ҬFjLʁ{L8Qu5P 6e& ./cFe+5\ރܚ $zvzv8?|W+k},~e\9wq`ö_P7Ft`3V>@X!cRM ׿U0xo[zǀt=\"5nޞxHwJpeec XM#C}f#_We+kY:ŒF9g(c'}Kn=vp=za\ڐ{sjK $7K.S-E}3f̐zՖ4Bq7ɶpq[X%x%K_H.~m $SO?"I\Q(2 /~Q߸AMoztMzaF>ԧw,ܐi7N8Aύ{ʗev\s~{ZZZg M׿ZP +^ŷsPi0=;nQqU`nZLmreE_H:_-HNu*neipcD[AN@w]@O:Efր]E/[dE@[S4a\K|C!ǐ`,p?uV# eUf}`=d^{_ O8eK5ͶgP>3eiHm o-a(cnjK>ϯyDcp#p0ƒU w12%Xd٪?#dv.` {j6S <NX}G?ҁ`@ ,'u"e ͇]l'1}{uO?]7wScUZfkDi,a~P`fl7@sL@O(pL x: /ry[Ɏ)7%],#F3%Y2M_dk ŒGO8癈e(&aߚuk2%MDA^w]}C+惉{=!jā||:%kSF,|i>|Ep Z^ưd5:( lwᕑ,'onoy./ w2i9zgA$?LiP>!4qmLjs=JXtIh `3+ԭ+_*Yiyc;c[{b3aӏY+M $}h ^vβ7G9L^^wu:S^J||W˶ywș oJ@@W )QUeP#XMb}Ms"Lsup^%a]\ri$bıem=wA!lAzS[Kr Fa>.\l)?#nY=Kp{(}M V]( G֟P%톷׎Yl(=<<<<;L'u!۽E(a nfP0>-YC-S,X\ ۬P {ȝ\TIעaDR~,pʒCBT|>Yj~K;$(knt=Z ǯ֧]w$CWl|EļD]ro !cƌͣ5 0BFd-F*Y]ɲM =jlg-]rBXHZذadfEY*ی3E:J5Cjnz#(sMIz-' #eX%S-}ʦ]dJ}P:]Op2V-itҳWD=/:C'ۆ0噯>2avdZa{gmo}^wxͲ붻cξlgdDLj_s_-/?3ڪ[dA~ܻ첋=rɣ@IO>)#%M—/]k}ݧ{oѢE>CJjdv]NˎG|M7zxxxxxSn,X⿄d^~r#w˹:W?Һ*Jø:ISQ٥Erqrygk/ӧ~Tڮnw!sۇX\Kl _o/"z%qtlBI)[v Ze"͠c=~Xo6$Ws='oj~I.4 d+W>8۱f xxxxx| 7^[Sejdr0/|4r޼yy{-:i[Fry!+׮ƺfg>!3wO7jѮɊ+SNO%˻_cqKۮٴϸFbe}=I/&~_38CVćt싉|5K/O>Al+WQ6f5X["vK_|[ϲ+R?'= X_pɷ,w; {3Oe{xxxxx "Lڲ**IρWuc{W>v98AJ]>&!z0 c+{oYCqB!z׻Γ/JZ~%J#׿… /0A[*׿-7bK<\.~_ʵ^SG}O蹑w5o2K#7&amM7ݤf;ܔ\S(3egPAZ] ,9s}9c{GuG?{6IF4_Uw>1T0k*(]vYwCk~; w=>'SN?;5 nw '׿@Ñαa0xfjpmip|=$ Dz3i;;TDooX)ɓ'/~p/c^t7ݮK0ئe0tֶmS IDAT6R-Ĕ+%¬,t<ԅ?^;0y[ޢZY@~_ȡx̘1J{'n܃@6}^{){ 7 i?iW&H.)_Z䍬X}u]'41=߲V,^0V]$Kއ3r2{xxxxe`ʼnOҋW3?r7H ֓*wi7t$_'E(LCQBLU]ʆ2r]@ X.z!%m__XtU[n=$3xG?(X~gc\YHnPR ~i] Đ^HcĢk= 6Í;|Ki0[@H=<<<<{zm6$rwJnq[OVV,ӽSuQ Ͳc'$JH~j?{̝77*={쪟F:F%"΅-6Օ)pYr63ŏX O?t%3g㫯:My5|ɱO4IL;Mnv 1+_|Q-Ƭ\|[/_^vpqቶpB%˶{u-{xxxxx %RckzOVk-;p#d=̳d]gW>U7˺mRX]_oۊvu}v).^6ZԸ|b?v?|%XvK2]=,qq̀3,X sΕ܀5tIO}J*xV{L]CCl$iAwC=B`;s9r볳!qcfȵ>/Ryw@% ѝe驪Ȁ~Y K yAʔ\r:_|bO/ZVZqѩ.ǼX%@Z%ίI/ˌmf(4C X | K8fB~@ 3D6%Ƣ6>ޅ΂>.gyZ`RNYI9;^vtC4/=8v񵶴 ԥkIǪ/%|֬YmX I9?nca^bw=µRWX;Hp.b{{xxxxx \=l&qZ$(bKW++h_íAu=!nè4IKˮC/^&$:ݔ)j+TsB3.,YD}5um6 c~ӦMS LȾ"Ie  Wg7kKg"Mh,F!/]TwMqcPZ=w}|cر}b2.V{twjq@׾Vmdp/P%,_j7n7|X+!V AKJQɲX5*}E;mTTI7n/J"4lYeXy&ŷ/@5K/VdS.ٶFgi { gD{im;d(p,efAw@ }¸z"*[xiv$c1dZHv>(9DV/bB:8R+׬ի^TiW|(JS._4U.16Xү߽"]swWJp燕 wc477 E{wk/{}/{%5]6# IlT ALG+J^ ՝zuJ =q]n|Ϳ/ĸۢuZTw7Mq%m$e*ƬMvư to`ǡz%a?٪G\5zR 5U]_WW #BuMvZPw|1,Z[[= O|mGOXIx,^VqjiiѲԀp$!K݁4R 6%{TwG=<<<<<po dz?)'Gth9藗#*Ɋŷʸg,쨮>~w8&@C@p/ÇŭHnݝ?̓Mfws~{3sΝy3s̹>4R㰗SLĪՒÙ3k7hd0vv[J!|AZ`lI@O?G\1XzD5ǂ~PCɳap>j|*Ȁ R:uxV盗y+Foִb1%8]vFKK.UôȂt~lR'֜{ҚsN|4doOv|Zv3c`_~)>Q7_W\FA,%+crCky?$4:VpzvyO 7}:3T>1&@F9zo)G4T:!厷:*FcaJo2>8 6 =#ֹn3>h _~9fyZ 3P+߇6ϛ>G6_~E!(tr%GҔIccy7OG9,e ZŶ*PV[E"l6Yl mJÚ?#ͅӤ7x? 4JSLiL=~_:T7%E|վR;3mfV)j1p@s@aadtIDÜ9*4hPZyK޳}YZdE Q2amF-iknlÈX]޴z뙐|WlDuY']i׷c`9H_uiMʈ%> ]pMKz㏧$%d+3pMlc%16ۤeoe_uU7\ۈ',x76/Y;TpFn&WXa>:kY^~)߾k>8z{M7:ȶ+^KkkٓO>iцHFǎo}޽{6( Nc=0~{l? #Fh\k΂gqFcMp>9oX s}m?wܑ9x;l,?# oCfȏ#ǻ{A!O?rI/8mv&qg[ZorQzK+:|ݐՎ 7`W^iqGa\7r3S QlK@Qa)DP"VW_}j&1kZ[:lZ߱zCzv?N='}4hsoJY;N#{^28c(#9 qM#Yfkph]}&X9yGu< 64ԐfmJ.*5hhq`EEd7h[i0a\p:p8< wc P.l onb.B.Ih˴S)Yr}Ηߦ2-0kDiOwFҨqd{KDBFTI7RuSɗH(qLS^EAoT8 <ж;d%j>|WXӼ:{ |ق1I>O?YP)ω'heu! BV~kPGrF+ %.!cIvAAYv}XipNN>d;nYit f8[N0k!- tIKi*9n-\&S)bKׅk E^BNjy37r5jƂ `\v@'сy>\'yS}SU??30.izm[OK.rHɊ%G .Q᭦0OFrEz)a7HdHdzcyq~J\I?>by?_0.R6q~9gXiךD5o t7љgi˸T&,強73@ |{GK  hOݴVX,#XIJ#ϩYtO3EM:id]cٔ6zC"L\zGʂ8=h*"W8ËU鬇( .i:I644X+q=P`"OQ05\cyD?s5@9ӦNjkNLO6ǵsG<"N_]nBDZk7|Gvu㎂^4=mԐAtmղ 2S 4 Ȥ,Ծ4qY_L~74],_K b4YtקƦ w-la!5V@K\epC=cv+u*xuD"x&X+q@x^VR g-G  %RH"Q:1+)񌠄M6$O*jI‘H('hX4kՄ,yiFԵ@޸Qp̸B盎l7V>$c"?\5mC\r؆#Y)j4)I΄3А/kC~4.?x:; %9fF;|)' kKo ?|# sNF Ž:VAPT75'ˁU.*4'fQAiSM oJ 'K4 Ǯ.wߝ'F6ןUVG`:7hȨwTt\b)bD|!() =&jl?uʝKhgR^#)4t|[ pQOӃތڿ|%4ن)w9Xr%jwn.0yyC[" 5F /&< i' t`In2ϴYI~(.ٱ֬~jSjo?n"nuab2UIQ%W,@U:ͫb: %X^ZE^],h$!e\%Gl%$m|D-y[2̋j̩s&7HH-IJyӹtN<h\{}!$V4 J#ͳ/Ή#K @~my"[ >Ax+cPyJgudQn7dW){߯g_/@ΖEW]1;S~>/re{6yޕ(*C~~;ߨ(]-ܔ~s -&ߗ} ;_lC(K6.$GJYԭ1uks. u-Bk:bws9?|tP\s CuG^C>j+6Hg |ǿBWt/ƒ ho}Tdr+5,/gg)sABۣ:H v!6ҞDs5lWwySi/k! p`Y%O'{[AؠKg]SfE$&_oֆ%?[mKO`qo|қoVZi%K'm$?=쳥`? ͽ2ˤiUD h䂸H WZV kA}:'>3ʀ4`J[/bw]a]K;`3O>|E0a D[oe.g{ׯ_km}\,W\atđGؾI'duQiO[mP]\Hjx"w+AA{'}%QkO?kEhvtIJ f9VC,̒~ߦUW]5M1&zjݿrguVZgu+8xwþiiy,ـhݻwqm_mtr,>M]z0r3 A:϶*I*F}`ꪫlX#'1Qi1PQ9p]v?:TKm5ǽ{i饗.'n%~rD> 2$N&~gNozm>vι~yA7Vl՛niZHy:WaAD0 p/駟ڴ 7ӗ`^hN$U&'yAgDE˔G!QyA0!ь*C>µ[+"|9>2H>.JmWϛo>IqT*s]$qQˈn&`{,|2#qiֲuQ]?VzZ}"/= O.B瞻d1\$cQf+FRȪ~8㌴[XǕVZ9*wyonSNN{aЫW_z+ z"x*Vrz AA5t&4jAA{)j_a.袭WD25$"ڄ+j}s̑8tA3,͕+5QO|&|;;8[.c=־Νmәrv+Ys94pM7va ~-gQ˼QAI۹k"&|ML٦T߶GV/k7 *S͸xO9:9ؔ_m'U_5l, zҰlV A!|#|2dY1Z\bcJ W}I|aw5\э+S.EO@/"8 q:/yA1Ӊ_Up?]:$**R_1VSϏO|NEbۃ&^4_nRcV'o!o@/FvQ,o~߇ּ񒀯fX :6zև.2e_j].0Ɔ2W~Ʌ|nex4\Bj}磜&/;{U.:8V|-4U6H:yWr :!+{r" 2Ok)Y JŵO+gGm|AV[meхw9؎A\sMZ{-')x 'v r:Y+R"A*Z^1Av=共D/r:?EYك߿dGyd4amx&5\Fe{6ꏡb㎳&xVK5X|2`W* ??-&wcɨXʛJZ:e#Ih]c_TH;ۈ|]&/ΙG744X{RAX м2dHrF\sDK/d#ʭD<ދ s:iۼ%^6#V"r)- %pkM*5Pt.WCHk#!γ>Td"=%+X 4PIWZg1JW)#6F|wݻZO?5T,{gwߥwySC?$uE$LĖU3Ϸ5vz/ZAwuGRieU^QPw '6m2\seXIwLt_Dfg[?|m|AaРA6%>|MIW^a\x&Ϸx\rɴ|K'\Pf^,i4EZbB2E6~}9'\i_Ϋh ~-O&,:^ÎiK+As7 qoIv"ףe.MO?tz:š]{fu׵egyf:l٩j'xb:C_N9R9%i2/]sERVD6y>vm𣇎xy~_X*~^J =.A].#}[+yjV 8Є6 @ż {ywyMx/kiI~B„a-0`P/}O~z7R>},='A:X`sϙkgQ$5?[Tg}֢(Pn(x衇㯽zIhsXay汈 4x,K{R`װEy7Z\ c}AWgq{5W+E*UO-g=ޱ!A'#P[oV ?|zb%K6_ҷoW_Dh" ~tih<3l :dji_D8oV:CW\iVv(q T܈U,,n%""W\rcuj8VD5a9NJ/:`Ij{rؠVv˥^j\r}bѧ| iOyz);Gy:thIhCgN;Z<\(jVKr-F9ܷs=D#9XnoCAUm_!30C|]e7:j[+*X'y|GtNK_^rwCeWn%PwrF1A"~殂G"|!bf -.yz^#m6֠@ЙR- !>_w(:ž{8r#;&O~)o-[+/N4lW4riɛ\H ^lN7l3lDOЖ-b('e]fe̯_͓;:,K!}!u uD,i`rn.fS]Y*? o2:f< ㇯5wk* A*3vu8;o^wu_~ :bTf'~+!1MZDAVraL:Lqb}^mDF(DgrUFAKhq1@`pW|(+tRħ\VhEXzLVn-:]NhaEHwEZ`an+ጯ8.1s'@İ"hp y"=s<.2Xx㍶2UBa٧Yp[Ơ zGڀ5T8f ]Uu]U4ytAD? Gҩ}qr,D\:Ln6OTw߽j<׾袋Jn*,Zj)f#^ռ*WÅ<Bmi-x7sv6:,8餓D"!8霆G2v tH?7,4Y=[oWqtuMtj ZQ%6H zbELnL"S|;jE$ 74jI@uy|-DC=L"fyKr>}&V^W|rV@_v,¸f(p~cïth#Ĥ>II5 ȃcRqp |G|㚢z2 6y@;_ǺMC q<8BQ%U`E@r(yt6Ƶ߇jjE( v^Y-~#1.::r#>uU u/YvXYo '?ɤvFtIH)xVWY#+l!6*o,7,vm7N"{ Po h&F)YT(wMU$/m[k*&][2~c}]6_SAAˉI`]k>y]nQ+I m\"150Rn]&іx!6-]."9 e}[#p|A1;ۏo| \`o~x-[Ę &,TL8b{\R翶I'k,Uz-9Njj"!gl+<[r?'ۿ ҺZdke[]2|Ց-L9X~AG)؂.hjėF7]bR$ \tv">y|0r*ipӪFcڸ &CBl"|.Z^XQm@~1wreҖ4Vt?ζlA.*y=|-yA=!ۙ/URF}_ojgstr!]R:O|kKVARiA ~w1QT K"(rt&V;֠_ O|$\jQTru-n$qA=;[*s?&Rf[ #f3 qZΐ302r%ի!p&L Sh mwzlC*g.Q%[˄i*7xÆCg$IP SH?ۇeuxw / yW9qdca !K |~{P3/ZC^ŏVGv秥^چ~*5 ^4FAFWQy+噓cnAЕYܞH@Zk>_xP3 B81*/2}6(#G2"'+V[mUG`i 2ذ `yA4@aʢd%[ECWTދtjhRntGuֽ'ѕ5?C%X}S-IFAAPj+HMȉTh6lXHnE4|/ 1% fyTAЫ!~6,9C#3O?,%X"M>xQL}%4T/NJb{t!n61ƺ曧^{-O:˶)R]\Ѻ|"0QF 8kmCseּ}.>Gu]lwC'﫮*qK/5@馛N;dVl͕~뮿^#MgvT IDATJ`XzjYΈ,o:`DR l~k; m@#W[m5k0QTpmYhJ6l;] UoUj@:\HjBG{AFR |9iNcyFb)JKF&晴[ٖޗ[nai.3O  _W#,M;M> ;sM\X3hbONj߷2|@y>C"whE9,V_嶩d)W  !kaTb-,yf|䓊~Ȑ!oI&-Bi9n[n1k/Y $Ȳ8oI'K 2߾Lً+B)3p.b ]-D?-U^/}f :?լĹ׃B[*]5fu|;,jWAmw1ԦY/L)D.ާOv^xap K(C|޽a9昴뮻ڹP%/d\sM:Sw[`=LBN0uNsbB6km-Eo#Xc(6Ҳnk3 D."Ԅˣ$;hQJHON>7~߿ol<!zhiˬ :K, ~AS_ )~KAdJ:LV\Xhx1RKY n\L86^{L8%<E"] 6㍋)Byj@  (BuSvdY㯾䷭#HN ,pXװ")\uP$t)QM@ضur{#᮲H(1{`u,GTk=ɗBpwm_{ץ>]P>E:ruR J. U+.&Kޣ"ָvNl<('mW˶ȷSz!o(we >w9]nBjJ}UZ_E{(w߃ D$LQi2^ H}͏h{]N\y1D. h/|}b{<-A0Rd߾(RI@^ lyܮ"Ap< hrwtEۅ an#7m0WyGUP޷SbEHBdT?zW}ۈ2 onLcscL 2<BlQu]["(O%E[=>:,ec,'4s[ABl t]*EK˂_ xKGb,i}YzMP744gӬo7|>SoH # 1jAYű%blȗAA0>]+ . s=& 3p~YPfxۮ/۷?O? 6?xZwu-6"BGQ#Goq#EY[ᕇ_hPQ>>MiI5>Mr]Jo -uVZZA!kaX6l mgG?bgISO=uIIGwyĸA<#oᆴJ+ȀҪj}٧M⋧z$`s|f+ /x->[[6LO#[׭|~Y5v[sYm_~|hAtLj}bFխT2 gȎLX}ѴFFqf1VkUVY%z&!%Kvs6L|ゲ l7.L~ |qMx`k p,(75gO>Ą8˱bo :Gٺ]ji~rKJAs*[>ؿ[laYg:k^}&б^cƕ䮻Jrt .he?X͕&7)y(M9{go.kO?cI2SFp !^EAAbZ'1g\TT\D"W߸|%*vNMG78]|dv0+/%_~޽K)Xn:f!]w4 m=bw]ɟ: |tP|IƳ:TN;a ^zdN ~@AAa.e8O=_~"i2 *)v-ҠXq-aJ]<~Eb3[`-:Hbywy;"ܫr5#b:zh@9/mG#˲ϳ :n'r!%lBJ|HBKw~ dh#`ͿL6>}$^'u4OX5ߟy# (zKUK~A7خUlMВ/JS4~H,TXWXatAtIǟ|l~X>?R>@Ln:"Lj&\J^o̲5yvKYQ #SJjE^~WN:CK ~nYd /;.,@< *ߠSM"\5[ZAA-Hخo5b).|ye[f&[@"Py#~QB< 8 '8bO&oVڂx}^p}oo4o&<\6*yf٦s&ވu zJ,O\Tj%~LDNXj G5nηע_^Nk9)zR_Z[|Җs͏-yAoBl3VI6"0OXlitG8~ L}e1_iƺP%#d`a޽0XY:`!֦Jܵ_9b_w{>}.U$ܫyG[Ҙ4rEAA!m~Ʀnݬ3!"긨 t۶\Jز|F*꘨8#[3m^N;_A >h,3wp\V~^eihe(Y86ެ]\X-_X4Ǹ BvFd0yQ-͕*"-a^.D|EyC.ni4"<>hXYe·_>&mDlO}$!LOĺAEvF=nf4>_>_ fµŊ^i%曳*_ދ"RqQΠ_/,ڹSVq񂛷3 }oLx-U/jal ,nO|b{5YVZf=&11YʞIJ|"F˶omHtYnl{A|+*ܟ5aA(Gi]V ZC[,]{6w}iO7|Sv4DYjf]+J δKAټ T|]~9+O-#xLZVzd |Fכ?'n ]Jl¬ܔ. Rm;Ml'+>t-eQoVh \XE__W- ߾^XІiH\x3[ni0}Qy*7_'N9+O-#hhz&|I;S&$+M*sAtz7RQ|kE*J4>-y`zga#-.u -PKm^{ͬXq@ f5ꩧL U{=*}>+n8`*7|瞳27}i(A}zQ%Я{mݖ\stE{ ~M6٤dcW^y% vK.do~cgӧ~ҜnwϡMOx ǃ{㡌Аù_=3BHhS7~}:-'f(E5>utu[tq-v5UAAǧӋmŒcYeQ}cv_"=Q,P_n}7R{\NwqGZklВG!۱.;ؾ+'ll7k9眓bV8{K4eYn&vofvN9i8cӣ>Z~gVqɩb "~Cji.LC9ۧvZ_2:\_otFn՘y!嗿$J@#9GQj &lTtz7 j>TW_=<7Ӷl\7n^SB2p٦a}MaeLR6(}W믿6q߿: +kmXys5`⸲`kVv-}N8!-"oS5eY|h.b$"ޱc׿eg=K-.r;߼㏷y,p'hy^uURW_}Մ[lam,p衇ZԀ:EBXHDy}z-hs_A9hd"yäy?,AAuRW:*Q*=3M?fiŝK6W_}uׯ_Jf9K,E#-ɍ7XJy]v·KeK[c5; ?{;zmDŽžkuYz:7<&441Zv*,Jk .4gyLTӁtYgMgu5Dۏ=Xz+:K/2%8h.-X7pôQDQ,;;JX;EV^$[+3! ZQ-:l馛ҌHEh3ηS $N^zD0XܸGy{eī6 }Hv Gȉ*Rh&kľʚW^6\P^z" A č]yWKip1_9)-<&yAl7.ZWW{&uv} 1'OA]^l{Re9w uЪT Kt3!h^ % P#x##V^Qw ,t`[E?>̳%w>IRߛy/o%lS*O>6O/l~7?O:Sg*?TNs9_/ T9Yy3 > /\rv}w /Ft^V8*"xb7 +:IV%Tisu-Xe,4$/#/O:A}y癰ķYyAw}vuk$`QV,:BŠ[o1_e/bL7{΄|##GYDLM34K4o|3|A$=DQ*Xps[oeZJ"՘BLrPB(,z\Ih^ŋf=>M]֙|VPcK\7AA[b[,@Tu J*_"u`հ*c5B˪w(k@"*a/rj5fP@΂n#qe< GFDpM7(F.NY и3(gN#Eca?ϴ \Lzѻ$l~ה+5cD_r%}eYjg47#8"m֥r2V/s{[%uOFm; 5]NlV'u(. Zt~>MJ\bY#済 Tp,w0x'Jk,*⍐FX.Wo"׌rR塼X뭷^iʁu]vmgn.⾣a߾}m;5t".̱Z~*2P뮳O? q1_9õD0f3xA^§iJ-I c}AWgq{.'sY/`S5MsXWJI[hZNZ: /OFud,>%z _=w#}C5JI:\s1&&_۾O@_AAS\M{H^~ӱ! e*dҶu{5jw/oʕ78^T m>Ķkb7<  hBl%ZLۋRB-1:d碜|.] , j߅܉r|cAt>:3+J oa%)s0 IDATȺ]i;AAEuΘ9SRKY劬y\(&ƻEeͲh#DZU3 ~]Te{\Q.NBh AgZ0w׸]}9E<~rAbF|L̯gG&%^om¡QX>4YO?QO I(=1$s|p&>T֊B.YwVFn!,:к4_CnIup%-rx~%*ݗ" ]#{K34c+3xː!CFۖj ,J@+_~?aGфc?= 4Cd*|@GxEn)^bm7kjE#. fS|8Cöyh44]OAA'Bl窹6lX{wJW3Ϥڄ%kށ"7pCӧE0`r*sh#o gmV"8G":!BZi|RMţ6JUQ듋] 5_(Ezް# mKx"eo* `Fuijs c'2nh%v^T~:FX\uUih QOwy'-6pY=3RK٨lZ ă C3J|G^/BifH^@W^i.5H_c_z-k,ր +bvѼDwLi%sm5At.Z,LK&UAmT{+D`b;Cs4S{A8 K n"g?}FXυ^򗿘k \rI:KXŶp[O<1mViUV1'-2&R>u]6hc3Oy +n;y}ө&>Qag9reXT=/GK~SV߃]MsÅҶQQAOko|1{*hJxRTP܍m[ltM7>du]Ӄ>8ڃ` ~M5ms}/)bgay a0 yO9ߤk֖BFhxim7d[Oc7H_o&-lۗ}5tʸ(fz";#~EL껕*h{\]6I4תm+7^i^,̒jZ[mÆ|Ï#=*6!/\G<^|E{+&N/ lO mM\ʱMY"ہ CO|RO8=I-Y3o[1mVu FR ܟu-4AKn#L@4 t?0F|2ˬiom7\3BoZ?v޽:,"dYNC(\sMIqEY>+ rsp7S9ƃ}9yIp=Ѷ#i2蚌fMX+Uȹыn}‡~4ɤ=J+V^i䣏>I7xSojdKkVِܥ,];<㰆%CB!믟:3аҵO{a]n,clk]9j \uUiez+7{?uA~'򼔇/N;Y EjuZke}-fgźcخQ*X%x7O>$8vim7JzϜnLݚ&nidϩ15{uWߚ]4 |o6vKM?L?+~e`CT&_خ=Dn;G;OS>ܘܜ=PӧO:͝7wm7>sM/Aeb2!{Z@YXxmk;lixP\\`& H|_84,w7J@[*`Dm('>ݯ]}P9?cim97 ruk|`|uhHMď?xG$" ߏ=׿<zkLoN(\6A)+o(?ҜuYa4I9XЦ'?fŧa'WTBmߦK;8m=8*}ԽGDe\R Pݱ5*SD(:, r1D_˳W6> J:E8g#Eȥfm.R9dw02b1[Ͱ=u)0"ވf\xsI##rQ{,raꫯn!v9²t#a.'5 ,3ϒzNK/q<<ن-|D7*,XyeE0SsAЇMYguoiO\ףR䅆N{r/:}66O#OIw}'^MO4j^{.4lt\W;%iGˎk/: {N2CWX+)"YhlPD*C$B(\Q>t:rL=z%cI&UY͹~o-BugK AËzo?u/>/ɛ|'N|URɦH׼Y!>Fhhn 7 ƺKvVQq;tK9FU#r幇`<#G lGWD G%kJ+;r - *xFy#oYqRΛ]"`h%>#+ipH8C9ck9"7ΣmC.?C4F7=n6,S#gY3|\!܌k*z]) P7_W޲P!O~G#8<xi>L#>ˆk.JiOf!-5"FY[)wŋR]Dᡇjg\'#1c;\+O\*Ѷ @bД/Pƥb ֘ ^JcA+*`kS)V]3^۶h"Ur*>z4$C MXl"y$-i{}F YRO26ɜ#IGGOitj^wy|&"PB(jߎ1vpYс2I ݼ!H$[~aKX?KǍ04#C9@D4$nƖ+Bc[ ystV#*"?qyQ"鴏6n+P:2!IK>f`E.?A v;^յT2[*Ɔr3g\+ȭ~y-~Snc[h,}IW]sY&G{??4o#[8͉c$LTJYDŽk+ӳ]Z;$x{UXc=Dʬ 5<LWAX^x& G\pc.ˌg?tXLtDsƗ`Fr-f]׸te}3MX:]8@H#&"V[ζ$ 'yge8tWDraŝA8ru^}d7-脉ʍ%s+K4X%rU D.r`ͅl%S֚G9JelΆy6`¦H@*2U:.Ǎ]¦U~D@ho7X0t#/ ؞G+x*x:=ylҜը&=B qu6 MJ);=|{z=8 H2 zT4)BErpU<ؖ뇼Di;ʧ{2X@"k39*,II * fP9*gwg(J0+DQ sf8zlm33;-MOwW~J$t^qOszb#Qo]ԅea%~VLug8mW[I1a:mo7ۋ0?[#OtR)3OqUA~뭷}c"S~M/} %YU;'; $vyA2uuf=ֽ^?cNO6ݨy?,pA(~Ƨv=NgC&mIyswE;Zi-񺮸l%:Y~xns"5>3.UI%45ӾZQ $$BMp~z8Ύ֛hM>ggx\mAiCW$'fU,}׺=zi[:8(Orsd{`ۺkۄڃ=0 ` NA*) v"QƗ… %d;kͣ]?2c 6lrXI=g_q2_z-{- 6 !|U,RtsY=gPzL؋AɨO:">ֻ\hZhUri JUN;r$j?$tGr[|vjD`Gڤ9Xs"?'3$|Ho [Lr桄^/8nF|0-./ՎgE8+rK/+]/O;\T#a,\=? hhԽT8]RD#|&]\>Ϝ&d&ִٰ !^?(힖vG oⅉ߉iM;d$al roC#ɀQsz+|N /~NTtnOHM[6]wA*LCPP3Hj996x^/Ֆ".-M?/vvZ82{s* ?X>UJ#fiWZ8$ 3/Gj}llk_ED벵TTV.8+uѥOp6rxOseh/7k,8,.gsr oRN+$nٲs\gϞn?iVE[mM)}OˊxFps;2B 57#X6g3u3TM&+X1 \ED5tD7Q\V)h|?=/_I{Lte ɦ= >|tb^{5)y矇Q*q3O>d@H7R$e&يXn?4_ۭ|(RLyU0o:8888$ PPA^ٰM('HwYtz[nEH6}B/ MԎ8Pіgo&d 0_v"QD4jSMm4;mu%1⡇oW_}U6I9;4gђSktvK}&t;ϓ{4\sф_ӌ_l~~Q{3yNc3e@OLiy{2ml6$׼NtOjի =z8ҽ J,K(ಸoxqjWI:Ԡl'WI 7 !;vճzhNEjf&L:ϓ\$ 6 vK۰}YȯH֋Hip,pf$ 2A2[nBIj%I2iMtmIY&1%0EhAMbKVN9u4 IDAT uԌs+axaxC/ӌ}fiKؓ i˭ !'|"($*8½"Vg6~g})q},pd;DVjcPdSLhXFWoy;Hu%CwedNj$,Y"{%&L0~ekAF&$C_O$z{%?*=o֬hm'h64mH; +~s %& G.Cژq^]QCD0J04 t3ছnO<3<BVi2vXN)$Ԯ1{n]r)bXq>ǂs-7[}hNSw}Xx1qB@7ɉZLd: dd֞'~A0kwpppbO{#;dABDSL"6τn߾~EbߧO\xᅢ!JHIHIi;YWY 5tx .\5.'4~;-5MTv ۻwo@\yBu)`p(/8ET,SHȳ_ Gw3l2{zvZ. '=ĒtOu:u.kjJBHeƫY&*W즃#Ij96Z^O $/iٓAgt 6'NjRCSN|^]1+`njb/#ۚmq,vqőmp%J2uH8rV$C{gMJD!pqZ9sa8.VSR8ymCD61FCڵKtN4fYLeԶSa@MvLW;Ucĉ| sp{Ia&I6=Pm $6&WK\0`^3l6Ʊ4B6H{_|z4swɓѥKh;dFIȴipG/fxq _Xwy7x#ZYaRӥ}-Ͻ[?~y?>66$״${bdKzS"h_9988888ánIt]q.,V8vv zBǎ+✜L> ,շ6I~7Or=.^ zFDGm2A3AMh9IJlsQsuK.~ 'DG__:J4!8Mp9 JԀ+aw^ kîE"о/~~m hގoi; OT~_6ތdŻ:{f?'.+نSb/e)v־}{K%YFN_jժXdףGіS{LK

W2o8#2].Nsm ~'T^r,NCoCgm̘1]L:~9O3BuIիV GΝ!i.$̓Ҽysɇec};t &!5>fΜ)&,'n&IBJ>}IM!%lLL2Eg$ G;tU ێ㰍Tq3`XgO{R M[888888$G=:|Xy"Ji@M- ZRb„ b`S`آE YXZdI${$?< \r% d;L/8Nu]'d^3 ⮻¹瞋IH ?5簡$7t?PIXW?ӦC= s'SN9ELD$$ҥK%m֋dO>F\W7 /ƍCvv6fϞVZHu?,edqpgKs;L)88Z%6!kkw29;@!;pppppwj=_EW^8cp1G製H.\%;:p :6z%4hRJ5s2ðk׮ k ?Oj{m۶\cZjm[n"+믿9^]}J/"sΉjI.LR,מ}YًW&*$(T\$ իH5kv5 =7l ߢgϞr'fSM0mցx']U#}aס,C&Kv e.LAijU%x+&>O&#w܁C=ݺuN#OEK6@e?ceO!=-D~S̍5:+RjόD M=hB%4֕O3I7ߔkJ](| igZ4 $iӦbMP862dj֬Y"փZsN@-6M`vԔlN0m4Q9}'#<"^x/ɢ6Jiv5Ɂ@dH֪,đ@́pNV$IkL는 ƣ3yu! 6b9Hzu@$AVԥ1-h:!I+H񦉌5籶3<CEF8IMjyyjXg&.lgW ,;ˡvYJȯϦٞz鯞KQF`ƾžȲOYM.3=*ѵ'#D1W_q(S3e ,'s"svkJCO;(9VulQRM[wkOU*HhJ&lRG(P3 U0I*s%&фMuuMX8DHs$]7״)Hy-*4"Mu_>&)7Zvm/mW;ۄ 3lr{O?o] r z]*mc<xw5(횹'mԔ(* Խ 5VeeXbIXG~v~zM״܎3Ҿy_mx}C'þ KDivq<5j,(>;oVrՔɿ,E,>#dz'/bk=~AKakɶM)ɶ~~H^5H1DVhdeIᯁIl cqf  ;!Xzbo勇8bO^mBILS%upk\=ς^[fRK'p\a'/3v\v+)3' T<18qu?y'98888$GQVp`N4&e\VmPXXqIǞ[w)CIs7nĂ -D&!N&j WBN\V-Y0lRPl#z-[5:R lv!Y=jI">8UF2{W ٳ'?pԯ_/S_F~>z+C>UH6$'B>}0c !:uhW_uֲd4AN?YfҥK M޴i0w\!۷0D޽e9scǎR6mEtU~3|L>]ƍsrKW. 4N*֭KMYDk¨")NK˖-%/?K4m2#=zDcfyB= 75JҒ vv[~ Ma_6bGdQ!a`O{/ۼɩv#t'$a;vΦMFoj G}T>qc=F55jfW^yE~+F/p$ăG:,1&8DP,^+6$ ڎSM2S4Qi: FqE2N[mX6fkZ4ٲf }&Wqu O$?JB%G΅yHĉu^ۆz.BDa/sBNS}%,5jX~,r6v~n, *drppppطUQ&^xG N=ANh&vQbkC|jU')`8jI]EHmJisxv^f@^~U?fy5nХ}}\vzW](o7 IDATbGvO5a|&Ds`^jyRpQpHֹLW>Cipd/p ȞþX&~_QTHɯ-7:,&\0iƎ̳37#w=8!V;ޱ}޿[eG;~s'?Jc ǕCITՉ'J6'#ڟbicgx _8e Nw?'\Ɇr*R)5;l"%CiuiXOd&¾K#$!m=(=nWZ% ϳj\*\ <yzL4yvybŃևa˨tפI5=_jݨQf}_|O>~mXac]4n;zDPe#Ϛ}a/1'ۃI<=ɾw.َ=>#~!:55{%˄3W) \Kď.HbR'=,O˱v}MSlDMO}~'gAݺu*:t(z17Gw-9kĺ/<30OQs@8&\^;#}݇供 zW?o9{[y!C7ߌqjd j`?N< 6L$~\KBImBd˒>(t^oR $ ݆y睸袋Я_?4n||jt8{/_0X칟z)*@Nr y'?+&̋mc/'\N8?^y4l +w}L1bZTX ~hߩVo@s @$l{sϕ2>rG'O2_ a~Ros 9I{2>pI8B7=0ڒL.t66 /,4Pranhuj,C %A#!#{Gld3gfp;l,I+M$9#+E`5>>!'A. v tM^{5 8}kni/\P~Mᅬŋ9Y /0xXN>-9NeРAꪫLFl{Pw90Ok" @ЌfÆ RbBX7~uP:k`+laWuol'kM0͛(5/Δ!.1i4#8u։攚mn$DL^jSiAijA;M l2<%8h3I< 83]>F>j[j%RPKNfBjPG ňt"? ?.+\"jR&b888888a.7m~P *'BN[MvlW7Lv@8' ٫:x(|1R2DP&>g^^8"J nw}O ;VۮlB5 I3 >)$yǹ4ob+g|8J}3mN;-*Ӥ=9G鈾CIzr̛JI݋F$QX"[Ά"[0B‚JP%6N\aػ"iBȽȠܸIc9*GCR=2 kwͼ8={BPb^E& 'w GeX!a/e!r.iP1YlhͽHϐz(-P{(2G5aF^=lGmG@4y;pzJ"}e SLS%ZzFpf/̜,}kH2oI(ރPd{H)9%`kfTɴ$$[{(q_W^,l|ɼw'8nPO' Rc?exFTB94#=Zhpo@%Aq" 4 ʜMز%bm xBFQpqFqЖvQl͗W[z!Hٴuo.>%uv~˦X%KM;A 5f{F[ǰwλ $$?$;E(紕Ä^^B(}G!)>y5C"E4V;SˍpHvܟCu$ ߱*mH!ն`%f,ؔ&gLǪ֫6 R0U.ʞ :kg."`Wb^~u!'ͯ42HY@XaOC%adV i1|O! %'"eFHNo'x_ TŭMX 6HG(\LV r3=  -իVE0hvjE&4N,Rrw`1-dI U"?^ g`hrV )4 KeEnOE )xmGãa.i;Ila &J~TDgU%rsV'&ﺽyaBd(b2oDLIRPH3<ߠU'[T/./5wppppp( ǟM),{3>'&&yP/E#)Ȋ~ y]ah iCL7^\takdD aP Z6$sR#|`;FF]ma1(D䞫iFPZן&al"kre-3A!!,Y+kVa/xZ0 e),%>˶^v=H`W\~xuɈRXG&F֫s3gסQNؼ)4~=(IJeиq]^QHP0HSll_{^Tj ͵ hР=֘&PDE/[DY??Hȫn"%[;UD!_ҽ~(*Bh\Uv FR:u*S=-Dl+#g[%yQ,' <7E?dO45Ja!,^ZCƕ Zރk`뢰0R4`ɢeXt ͞}u eui8hLHҭ8,3wǘA3O=2ʕC~.%W%/ A:r+QwpTk-l݌U+b c^2{:t8?%AJjdΗP&sZF -^dҩcE(vyݬG()TuQx6c/ Dn};(=Aq,̃x- ߙalY 9AO|i"x^J"Whip&kI3B#̝6z87i/$ޗBӐnX^ٺȴ_uFJ2H k^v}[MҹM G! paУޥ#6+:ϔy*W*UᘣbۖvhӶ>F=~e*д0Y˃FJC;<,^R(ZڵR"rbд)WF!r l\T'tj֬5bڥXty^ec-H-JWח?~I@b_ȸu.h{/<.<(D;lh6َVxwO4wFEm7`E.eIB)W?#pD$q!e!"++ի{pIuk,<"ZE% -@n!0`ЙiUEV\9CrrYQUH@8"jfa/"ejj5*cݺ|C: ݜg?L4^9>ȄhsL6V- W7s\'^eggys4=倶sc8 H,t֐'ѩhxo4fBJX1b,5ULTU V0_11 -wBvԽbF>aظ~>6yԨYnޯɨ"N 2z"iS$g3o4Fju~c>-i,Rz#1;YFP*MEbsѥ'fxiϬ98NX;vڴ KfPFcY[  . sH:'hMZ&~Yȧ IDAT!y9W ]4شH)@d% Ň}laخ#ⱈy$N;&,e|`mF 6_"xeDþͶw(AI8dd"/o!/#_$;:Q“tAJjEԪ Őe!'tKhb {l߄n0m*1_F jj<4tY27(_S&[n~ޤU?w)*W)_7D}5n8Hsz(0;?xzж]cC_Bc8cAdڔٸᒋB6d/m!U99 qᝐU [s__FMq簫 063Co2k⧙3S¢TҪi!\u*a˦mxԓQV ZE].Sh]{"NwxҰbBO>6y*2R2 qE}}Ѯm}Sa/a5R{9=zCffy#>]wkaÍ5-4GQAyn~_ ᗟMcqˉ_;Ƣf͆FX\wijZW,AU ^Fފvj֣vCѰa=;Ф}5UۈUF'a5x㸣coƜu8Ѯmh*f#xPsqfGde#^cD~XN yHXDo#zKyCO4E_+]܂1HˠW.3)|>`!ix+qmXj ڷC1upb=Sꙶ6oN;5ntt'툪g <Aehױ:ud0>5kTut݀@ b?p߽gƛzap\Dz3kפuV}7N]O6uF|ǔUt<2~2w 8>Z>ǐɨS/'D+UT\iVc<̘9v$cO|Î8´kG0x 8%-/_;TCn}lI.LOlf[MJ1kVX:5 >248֐w ^ w@ߓQΧG#:&)~wTý7[](Yp$ꍄmJm΍Iʢօr%==/-0*&q J ?ozS?=!=! aicn\CJ,G08k"c%I;lo2SEcmh۶!x0ǟн{54m>m[iҤ/s* >#+DoC'}8ǓOp}ዏ'Y FFD󈖠 BU0y9WիG:rףPeiyЩ]k:l5~xW:eԳk1ɆUEظ )hܤ%Mᰃ7!`c;b%8Q)8Ԟ`t>㐮-7<'m\P@s8ިVнK{\tCbJ߳r&[&xG~=z}uj^n]O4Bp#_^1mY7\3Yv>f&f7h1TƋ/}ux1֭ M]``(N}myA,ZDBz.8$Z5 l עk[q}[0n?L[f8jѫ5fȡ,CwAL6{k?}/+v_ЬyN֤?\S;%#42`UMKXgw9ϯבɐ{W|hG5;i¡!Ӌjέms͍}1vX?>7N6=~t4Q!-ckBl6;v9tlS?nwLK wN/LfHl秠'!|ُؐv̚ y1/gڮA:V=fŔɛЩc,[YdG8anFz&~kFLb 9X7^~P|s;5ط ݐKᇷƪjzW>x: B&ygFJ8-q9U G'?-^eK6^32<507 ز׫.>Q x$^0H?„/?Imvژ|lt|x+̛ jQn][hy5|k~7i.^@}geahټ f)sA{އWDza&ۥ0]d4gG-o]QhT+Nb[r!Rd~hKnFM{3Rذ5{B!kScԨ1x䱻Sf2aref"SZ-_M[1?W 9AۀzIԥ!~yf^2ϵْo%s f }-}>b[c^Z:JjϋNq%taoEr%hCê-7L~'իK~߳ ߪU^%l(98SK Oy?bY!!&##_]GC#SQ B![6RMdfexS7$jE(4lM3EC60i]rHn޶>|46rvvyz.2m1yD)G *V6J^"Zwr,]GC eBŅXr!аiB!G@ lIK/6* ! 2ai|ԭymP| HŶ" pABԮ[PT@PU+ &Qlq07{1r2!Yě|˗Wwï Q͐@H*=>u"3L>|ddv]PbsrΘI,^kW)$ y?*Sgd݄;ay8Kf3PT|0Q_&PƗSRvd"^X$IK| dP"l>z6oތKPP@ \Z*UDm}gSz.]+UF?3Mq{dÞ`xXߞ[j/#Q u-xBbGs&,ZFa>l3Yxc{H X\L2d1o&~55j63YW[p!˯~@\)Mڡ0?M/"!Ca ayֽ6V/āꡢcyԀ~g!=Ua`#̙^ ksn=Ngx&AC҄l8zB D^Ko/hC[ēbEHƁq(ϋbZq-jklк/@bܸq9bEa*Ks]+oû0~6!kQ*kF )} yQT6`֌,>՞Z!ɳ[K.,D{_zn9?̜΋ Yf@ܧ ,FPJaâ4ǐ 5 eq~)X2} ў5c V<ѴYy˛ұӘ~,'_ `֏4uUA%ŧS0ov+۶rpBضYG? vr_lۀ$GqPeMZUGیʾP5w~m̚5 ܹsMϟ?3f ЫW/YuK{ҤIBi2MItǎeI;Ï3~xtK?R tsҽ=cpJ~-Ti>xxCT ˗xh+&:((ǁDō B{2 #ʕ0q+#B{m8{-t94mP]5v-rކĽnVL(1xHC2?ƛVÕ^} dL'rpm _{1(3N6fnѼICxn2"o#96?_e)D %5ߖ"xo0Րj5涄<իVĹy+pE%^{w.N$t[xבyԁ4Dд٧_MGGIw3νT)n'M{\w\NL/^Zo^Ǝ[> \Մiݷ)D"r /# ٍC>}'_MQT[|FWDC%egi^B…B"褢0/_*WshR YZz";kZx8+3]ЦU[P>_O=1 jW4wYMc[ueX|iFX}]̿PCi>Kј{m+ `'\]|XwY*6,DjBX+H5j޽{O>A2Pm7$Q2MܰaC3fz~k[{=6\bcOh%zT O#D ˀ|p sRQzCǢJظ t4`(i^x3-_^_nB,_$f R@. 21cbuZc*S m[T/scحq p ')Ȇ =wjsR"=i]ҰeU]K:Iox}4CƏ9 |!zer-RSŜy+P$cUQۊDY["ZΜzra:a/qpl? Hk@fH&G| ǟXlÿ2;"g3CqMw#?C3uOVZ3ơN* <9*0z >stWtRy@*UiX#bPg0+v8vRG}2 =1r 9]5ˆW\s[pXxeb&-VؓP<9 @X3r6WDꙘx8̮P hT6m{ ɣMJ7c 97 3 -_l0S+`ڌ>m1?~swl0n3zl٩3~"\89>? ƋG0ұ#ADz lDn!rl\U+W0G4Jacb-]"hD[0Դ0`vv6|J'v&${Uްay_.텯e0TIE#$[5ZYvY9XxJdUĦ غ<$df:i 1~ѲU))0mj#33dd%,[ Wo q'677Qo16Ԫ?V-\Cұju~2y,ԬY'1e%q}p qE`3vM _G&YF(燐6;Ml>:v02?Πhڴ*T95Jې"*ZNI5qWW5Ft?[[Ǟ *giJX̚=[ÜٿUFf%6⻉ PFu^3~y,~WaǢҞYLlf{ma=[N"#EzfUjQِLfc**ݻU yMR^ǴwrT?[^O/RIAHS ( " J(ETпJS"TA @HH}mwg;{3{yo|yٝ{ܶs̙;ƎGYӴ;:wm'ZO+^oM,.٪sqr+\;Ϣ[˖ҽw=A'q rmnR_u/J{:!6ZN'[|FPOW`i]M3h U;M@ܹMR0l_dSZTN8%'MSrDGI'~M(7(SKi봈n]D4]qL=[ǎK---& 0<乗k?p^ƵkdR,q+%Ə:?xc*~.(TUA mo!!vVk$rx8(: a<$·A4-F6qo+u1qD'_|'(Z^!iV^CkA 4i6'z!x!vs9b4>ry )w wz̢Ui3h*FQ*Zx>Xݓ4jL#ZrᯑR IWI3F>^Zcpu4stӇAc9p qoosm>e J%2N$pktIu<}ohT(ZہWǣVQ߶R< F'>oytiDT5Pk[#ZrhfztT9l"ydr,RRn D4 feOXhڴx1o;MF0sit9;?\oMӦOח;Z\M#[i+Lt͘-+B_ѦLPPCr-) Q(*<\ 245GǞ<ƍ&:OPGZ'1ǝT>r&E$k[,=9>tĶaFyjYlZCybPᮂ@}& wQ8ܱJe_[,pD(“5 zͭ;0(&֮KЄq+K#Թ6GZ)Ţ 꽁Ezג5:MJG w2 lpa(cCHE8 IDAT^O@c+}+sm=izʵd7^7v &Jx;'q?N?aQ>ڍ] ;DZ>:"ޟPH3ƆSjX$%Scv>}W#MXBa-DJ3 Fa}Fu>]o>;8|GQ]ϫ˂4CW08Le7 [~9E[R[Hay* (Ӕ( ®ê$(SwNOtLliD8Q J7IQ|&~d>}O{ۨ16@e7"aNoܜ)Ra3s/Pi[|˼)wq~@It_z93EX}iYQe0 2zY+mW_I ,qio ODR' ,YBc)؉}+ 2] &% xB}dI1Is;xw>p^/sQZK*O~n;2fx0 s" ˫d$;*{0Sb.EJJ9FN}|a^|HgʓUiq*H~{%eDzMڷ }1T)h(>orp$ ӕ,M/Җ*\[D;ο]0 ظZHKp;KYX3JE9z -&`:>T2M]a+& AoJa'J@hOr+CU%^az:_~XS)dއ6o1Yי>o:YIW?JA'w\CMtHQ.N=a廅Gߔe(ڏZt$5 w`T^+T nas)70lx<X>~iŪt"S$D5$U.7l^|ډHye Lz@wGWgj)>ZCr u=ufϷ9?ut?FuT8+AOc+C%e~u{cӎ+'X\t;e8w}c}{'mɗ.6 0DƩ,v.R&P6 L/q@ QWh ?mYV>Cs[:h7mjO?.Kм-Oַ /?<~Cb+s6xs\9)/ʧO?MV&g};<׿s v8-ԩ|JYh'.~t&`E׿NG|'~?r~}~٤ ҍX2˯_o]3.nF7xu+W_E7.bRzE翯la .2vOMʒtG V-ryT#p'`,y7Xpfv~ؤI蠃1c6;@<1-ǏǛ?>}|sqƅ.${w-!|^r%|oy+!X׬Yiov4uT?\.:|ؕ-؂ӧs;WU;#d+u }p?҆ ?CpB2e ?@|Ȣ}]wzB;۝wI"u4^uhvډ]~^z%kyCqѷЯ?{ ಂp (G:hW]3vĉ\W8##&3Ήo{xr󣯢P?H`&KœtItsAQ~wRu-$E 2IN=daQqv/Nv>(]' YUW]E>?Os}k_cis^{т /aQr->93>OOS}ݺu,>^'x" &q)(s='#H]@C|;mXGŗ&|K/n6$I@Yp7C@Km %&v@:SM ŕBHJ-Zt~ɧaa &u kk'[tf.$# u! j >p4+,pO%U}X>a'Xz5'@lUX!fpλ~'*+  A ^ѣz  !quD)}@ç8<1.;,ðxB0#! 8@^"+ /3чvU;?fX(kǝXQ87EuHɶ< xtԙvmI /CBCbn'QU[xp%f?ĨCdY 7 XQ p.<_<&7p36&-h_?Gut~\h'LJėҺ_$ -w_(aQf Լ tO9^:жnn!S_`OC  ~ F{x[|ŠX 7!#r\D,Y`Y}hkY}ٜ_Yn:P ( 1H/4.XaqK A[]tŠ A ˴XE}/[ćHDaKX K?&; 'e 'RbhGX!f~y?&Jpс'RcL0 Ţ 0V`:Ĥ Ͽ<)|K8 mfϞ+ U'碼pcKvWz ,x@K+c3 B[&S[ \ayPy>3yD+7,xロ~"R~BD,2P^mXp!xa}1X!P19; ʄ0pApnя"|}w຃RP0І*LT(Fy}ܙ"~H!>ˀ c5{V> yH`E=ھUZs)va nA&f%6 07t@i^ _j#n%9 KmW*lhZ`qy28;꩑pb鋵S/X>@D9"+`(oIa #?q" DX!zV Z *)yG X'MAZ"P?[7{>XZf Xł,eu CH;( Ĥ@uc-,pi2"=wBb0ë_~9o×;l |?|+`FyRQ _tU>հCAG< LbC}҇PWx6uvuוs%\=0q@yڊ !{}ө46d n@?я]E^~p? PXpK*y~TCP"8?-/vANt 65=>Ĭ_Fv xgu=ɋD t <@{!6,X66m^13aKV(&MpÔ^pa~rd6Wߐ _ V ;puU< m.r Oc臘h)_Ӳ/΢]-ꉈD-aFSkmI;Y+/%C%JZ R9'iJ5%_1B D*2 #D \` /BSDqIO^p:=%{IGG8ٯ ˶CyA3X'bOx@D}b[E*D8\2^l!}<KK.3=Lab"yħa|]LpB1с &w5KnW/e[JEmLRPzBSH!Lm`Q\/a8R0¸UӖmd$7 + 692HȕBa͋NHS|a [%<]+~ isr'J gaX@%"]B܅p''5O$ eY+ԙ엻1EHw>| .H]k,eEcEEtOh5y;"mzZo0 0 j|A`xi?'^ko 5z4n:zs՛ya-0#0r\}Oht8>?M["h +)՝q&WTOÏ# lcVByK!{FC˹$/ɏ>O\{4Q,H_~2m#. &"hu¯?qC|m=9R~< Ugfm0\/kɲ;pGm6d$y  OhÃm}:\R v1Ł%.??`H_B[,"XE$l03^d_l81oOVlJ_/U^laԼS[J UC ;^RCOy/iڨT_&oG[SJl}'AD47,݂$jiaO) 06[vxmagb0NVn'a18U7n$a O|A'KE\0M1e0!:_"pڂxa1Xh#m0jZ %%Loaa 6& èrRn0 0ۆa )"[ƹ(a֮wh˄5 t|\I8sPY.ƆaĶa5I?v19I #m_hQxiabb0+g_fM aa & 2|뻁ą>ۥVJ_-_ۆaF!fDcm0j5$U$z x5t] 0቉m0j-}v)k߷V3f50 4d1mƐQ\ġTRTa@cb0!E?(b\s}~zq|am0j-= puh7 0lQs lw#/(E,a`$ۆa8f6 0ealT*.˵o7t,a b1˶aCX#q>eIDAT6 066 f^S[_:Vbam0jb"e;naa && RJ iEķZ$XˉZ& aũ{2a 0ﺒp E|a`c#a5I?v1- djaa LlQT#}_m_H.\haƠcb0!CЂ6zh? H֭[W`ݮFaMSeb0!F-akkalZ8do4 f]B"";7f̘ ,aH r RnH1+O:\G 0AĶaC~QE$ljq}lT*Et |9_Kz0 ~0mF͠Er$N[ux6 0{@0#N` <0l%0 ldb0kI)W0 8e1bv}X}x_e1 TY ruZV ׾w_aallĶa5 N=.Vbam0jb"eoam0RBwqq}7IIl`QZܡ-0 cЉF"qr0 ,LlQckѬ>߶a16 &Fqﮮ4 0ĶaCo}ƹĹ-ZT o0C 1Ķa5*Rzk׮L&c"0 cR6 fN߲>qZ?^Ok 06umb0![*釋qGMt9ke$ik0bZJbjalLÍ@|X\IxڴidɒtʉZ@,===ޕW;X|2>655s=G|ͯ%LlQ38>_DDެڒW ytPCCC]0 cc!?O7tz|,j8XȵĶa5o|[.^ ) >}:͝;n|YO c8`,3f̠!S.aF-vܶ/M\2e q%W1W*BJoؘITCŇumq$& R f Tj_%Sp@6eWyPrL& ӎ;kR #Ll1÷؈xI?Nw FRZLj &zG_v3j=6 fE 0aﲭ$EtѷqK+/h"1q@_nllt& ènY}H[\hbwʚơX&d>mNT+ab0!ϵoqNO cv_ŋ;=؃| @mgS곱:)P@xlθZ547Pg 0mFMRʢ] EIi _!HDP"w,X@{,j6Зt؋iV{;]p4}6w4tQ86aOMۆa b)f.V[7Fj_9l4n8ZtiAzD[a@9Gx^%-gѲ׺~ny;:z9} nhegg'e2=Ϧ1Y01ۆa IIu&io㦃\@K,_rS8N%.͛7dp w2I颞\7]N9NU< dAƇƤe-o~Aab0^e챭?ӟtF"klwy4r*;w%vI#GҚݔpO$_.9B}Q:iΜ9Mp>26 c(7XmߚY16 $cƌ &7O#J|=ѕs~' )ہ5f/I3gra2ߩfc#Q6 cHѢ9n;d0BU;n7p:s'`b^+K+8HݑPӵA:Mgq:>Fz>N;~0mFMgBr͛iv+ԨlCl7b{p(D]NReИ]wٕ_6ۄv} Ķa5f "l4I$z_)nw1P[SIo>@M4^,xdšCцZg&bm0)%dҦ!Ib-zFFO=3ܐn+*'; @:G&Czk~?Qz?7I(Hfݎ%9 qxdnrw=!!DZ]ۆa )z(6X>o"\ǑƦM:>m iE^L T`1wkLh>db0ao mynGz5BqM2u낁c~ڃ!Ķa5/fuE^xq!Kcx"}?-Bmmm|lcr-VZM+Hw͚5,B{{;X2ۆa<)-Niȑ^+G>BӧOgQwgu:}NH}T}Wx70O|OCäDX_(@$&]w|4yd{@N0mƐ!B8N< l-j1_7M4zj;*3,w>,wpү |̙`#"'aWp_+W5ouHO ZI}!Tʑ[_?#WēExE{kk+}"r\‹c"OXDVGˋO#}Iڴ7};%_6)f1\(9@3ȉEq>IҾd =N& 2Y-7XK~h$ׇDH8"C0"d_5\.>_]?9~c)2 _Ҏ& èYH.5a帎[n3ҔVw66 fƺSΒT.a 4,K0yQ@wNe1z~oH1Y} ?`oQ 2m^(V 8gXjW3a{1^,~5!._6}3}*v3 {f6 cb Zn,*2ЗK˨j/ʇfŐA/߫J_drT_J?\[#/iCU^v\`0B)`mz}bB=::1<~#o%w=E˹!]y_8_%^חV_tu#oҔIG6z5zu@V?~r9&}P[.Fm!^߿\`0 ^iQ6>y)c[@kkkW@ƧC͚5y!%~[m^[oMz"pm:~ok?.Qjs>W^yeK,ZK]bb7JD+& Z@bߵ5`-zP4 XJ(::zhA8a)!)^tiuUSJTV[3P OG9ʝ 7|ssh?L2ЖF*wwpa>>?Lm9f̘WLlQ3Az&.AjܸqۻC&Ux ]s5tAb@WJ8UN Kg ) w2M>S_O: h}徎k!)S|/بcwsg_ϣg}zzz0h 5@{q_oyY'gr\8x7o͘1îa5fҥ=#Gmb0!ؖ6^gfፁJ`Uĵ#,J#`1H?)~q.H;'|3&O|1聢T[zN-[n;{668gq%eC_\{06ρD0&+Wrر?jii LlQ3hpʧ<@+vhoo__6iҤ?744LYd)ƍ{7[N`V|.R/>4z~AjcSGބRM5CSi|w 4r񄁺~j82wo>0jԨώ3Ml1d Aa"l_\\XE:'/3gR/ze?USLe yǿDJ%Iwiĉ>A\Sl,J L%+;WwX\xN[u^MR:^\\R_S峯'* (vnW/Jίqm^0~; y R2 DVn`^I$ni4? نnjj]t:Yfc˗/_4u X k ]||WBBr5//$DKzOCJڨ#|Zc~4I,eae l7k" !atZKJ\p`di+]Ǖ :m'uH} _ ('<8Fzk+7;K[0@F!$e6e_gm`9'C'xVROL]Q"Njߣ/cȗ;@}=tuϯ<2+7!u6?"u;I]חԥ.߮J^)k=ɓ'e7ƉU}qo-rqD..:/E> T֏?=sG,uky . fڅǕRBIw?x*Oʀ/`pXj_gGp(F>{#G̋/}Kt'O:΋_Sǽ:kiiI=C wygi`;W=q78 |/^.NKVXA^x!}6یӟ=ܼD.R#Y|_>rX]ss}-ܒ]_2}c9sp=޾/ҩJftvѢE&X_O9N9~72w}|v}w/be]8s·'z'<2G?wޙvus]~!P{>O.&aqәgI&LsQh{zXn{VI`6G?8A@wiU-3gWy\(7!ӕW^eų9Oa='||'3,8#?mM\}$\ \FHyƏOA^؃@EIE_=^R[n˃؏zQGEh^{SOPN1 2W\qEA6E~.cM>:% ܨoB˗{[NCyQn_?>駟6u좋.8wYgi%A' 7@s=#4|rף|wuwi'nK r |1 eB{ފߧGu TdŷqiAM.v>.8]O0a;v,_EGPn}n(ptϸ}+'ɗ·_^/ O0.Pf ~'?C(B@(sfξ]ӧ :pb&QQ78"/+*C!mt!lRD 7H'zN|&ٳSNH48vmSn@ϹKL6 )@<'*/9eʔ'^r.pl +C K~7cƌ-؂}'G L ;0P`rB,D&NH.~Z؏6j9ACH v]r%O%=8b`3g~p1~:CX`|zOCeFyП orxCۢ6eˏmvBYx C 5>,m~e=!(;iHm|c} ewqG=&t(&ml]pOL&!1S5qp' 3?XL)4S`yh~KE)3xefaK,FP~N_-g2@䑽 O%KfFh sLib}!(Y45l%aNea/aEڌ, +(Q,eed9;Xh?UWKIQJ )ebiX3_ _Vܻ`;3+NٛH?)|dxqFҟ\p7L2B !2@r@H@ bxY\`s[&fB lG{G';;r$ޱ"º2[Q y|ppĘ/Djr&zlyΈo:L0KGp0xBHLyA:ev>8GNYW܁G BBA 3qD8⏄"H< R$Y@b ىT"Y2҆<@:^-š4Dr4 s<4]=^EK8 gqp<\. q% \5ׂ} <oB\bj|~ ߉' z;O# %=ZB7Hd- b<1XCl"$IdC$$tttMDV!\BO>MI!P)fwJEDɥ4RS)T ՓEM.Rw****n*T$*KUJU\RTLӤYxl^ZN7 z% *CN*R]ZZzSEL6K-ODuWusu@}zq{ 0L5.k<$ikk45wib& CX͸fL>3YbB;_t:::uuuuݮ{Axx㏌YE-ۥwM_@?P_E+AF C/CF3/Zl.;]>33 26ij4`lamܸ ՄclѤ٤tB*Ӈf3Yf+͟[h[-,,-ޖs-+,o[8VV۬nX֩mP6 n*&ܳrmsll;Xvv^O40qĖ3w?rtvXQXxۉĩ$II'wf8Oq^ERj \r#-q;]~O[t'[LO=SӳËWgO׊=}k+s-5 Z5T:.l " `ECh!!e!OCC塍S)S6Lij6U:> a[ ?18-|Zg #Z"#G~Z(2:;9F-fFLeX؎qKH 1 {O4{wgZ̜?,YNV-}4? LP!O'mM򄛅/E>^Xܓ\<3eCJowjI+ OR&y#czX،Lrfbq4]z~sd6Y\C{Y &6]˶!3+<ӼyGk̗οk*'/  .[عhbdq%&Kt/ \ouY_//^~E|]?PUZ /c?J~l]j˪+EE%E_W W_ҟ$i]v::麻+(+0eCF7tdRɎٛ;JCKnYkYjٝrz[WmMv;w;wUW"lw_8TS^ގ}WVVۿ ʮ=0~mwְjC/'{$HQcfǶ2j 됺ܺǛ=kO؝{d)SkOSO6ԧ>ۯXy6aC^HHBMο:wߓ{L2A+s=^k}qyqKV +Qii E"  8\\9!INۑ?u4{6}?}r޺iTLplұ=Rr)G @pĥd2ED\kh(NuRUVT**+.b\-`#ʔ㍳`OP(1{ٲeM:ʊFh]ӠNli Hlt*ad2(":ptd1өt'$i~;,0;֎SL_L]ا.N`D@%armm7E_1F14y()žBd)k֬ }3f.OlJ Z Ɠ2M:۱+n!wIvN\uA62h @,βbTL_LZL AH/)ܩ,$,PDv>l-[3>~\9)oֽ\̝{Ι3ljǓâU284YHE*+\d)ವ0FQخ҅ *BX+CΜ86 .HE*Rr$a3% M|]p,.BT(<4mtGk}FK.{!S.{ɒ.Rthԩ]m?j:UVTR*X]o9棦~#; ;8?kI{gg.ɺ\V:Pξ!YGhF#&^@ ~/h䲚+pI GOFNV^U] щxuC!@._h)rn92 C̤|p(>EϏ+ha1\ KؖP~*C{>!ݦ&~\~߅;/dI$~&+Xt?ߏF҆]]]b2E6s~37=17/m y3d&q1)R4ص|HdChx7Jk]O%;ѠMW3ȓ`#)(kQKR_lզ$D9!jA780oBr0aP^$͏ P?gWϯl**C+28 c?nA#ɓ)ɤw1#efڲu+-\NFD 0mȩ0QwOЅMC}}==SKwՑC\4i$d3 &KI y*&j JeO!$"c,~[&_G#HZ@)tаh۶m20Y! `+@mӦMHRA`\0B:7s~3gr~}hD}mTU CA$ԹAgPڛyD777K ƅf:;:΃mg47hI/Cgh\X׬YVM{ka)]a0Y&S0wL "aSuRNyZF]¦P>&ҧ~͛@ZgYNԴeaZZiGرAxvH\8e&db عz]YUE'Njƣ7]-[.µ hPsKfnZ ZE[Bcɀfv[k?k\j.-@fDe*Pհ)".~4{l3}0? H ,tKpMH&ov/?+@: h3QVjC;,~\! ׋Xǃi̙'h+V >U|\1UQ>``b&N8^5]O;_ɚ矗A jΜ94'"®hho{ɒ%4qD5<Bk`cx411=5c^zDo…?~Jb5k)CfN<f#9yJ]p]7V;'LLݤ7HYkh׍\h˗/7t=v_pk|e]i6 @3kF@;j׹NJS9Y\+7oyvabEaih"82C}k.`22 01+??oF)P0V~1Ma`~ y &ϴY9f!! "^0Y.YZ$ǴdЛɯZH/ vmCwO bhM AoO/۷O +p(IbP;L G<*n >_ FL3qkYkVCњsW>&+oԩt[hL&\ 3f̐CC.+/?\ ÝW4k,n p"+5cYi#[r}/dQČ)o $4n 3+m6f(w\ec',{*0rMRx PhOz C}B9M>l(|wReNW!Zٖ@T?9&Վ_ mmu풅J-4,@:V P y`YScm,vik6xu^ll\8V75=ȓAIuQJiˈX\*2E$un xiN 2Ž>h+B "<< hk5|\d\7_7hc'%j-A޶!=o DF,{l5h 2 RPU]cw4m ?,3ozdMD1'A,\-YTA;  bQ<y2χ9LZ 7LJoZ"FasϞ="3Y Asݱn `ް#dɍSOw-dQ6 |LOq }ߴBKw04i{O &"L0: ՏI5v-eVHcC3m|Ts2V!5}1a cLJD .8Cqap hpxpyLŋr~HK ߕq B׋\*r[6m6YEx>} E[4 p3<VGyDI?6se}wX@64A]qOYB̌7pXxo KbyF]! TChǍ}SO 0}žWhwPGK|7lsŋ|6mUy}몀k>_ MUcѪ\& u$̳Ml}ԋK.\M; m%r&7Sm?PښHp O8ؤ GE;5IB21CN5&9% XF*K+fob&N( *ڔx^7)X͞=Λl`2B|t7 ։V;1B|uqɒrom EE ?.v/b%Xli=ʠb {l`ao3>_Ys2E;4tZ@XL&_DICqba'aRD5LiYaƒϴ#,q__6/ilh[_XeœBinn T!hf1jxڪQ~ZE~~,|늽%٠m@8sч%?ddfr~ު4ANp1As}4;AݬT˃C⎉z N6ҧ]ф x#Жp0<ޢy8!%ӠDcҲC&P\ 9f깮7һPEX%}lk-TVZ.乔d3yp.>k0avqհ#V<☺iIn,.E OTh%'xWV6)dT" &lI20C,1 \2NU[HMbm&r!dgC+Ä=߿~riwJeu課cnztҋ;T#?<3!* O!Qs NFIm<6BZWJ|=jLu3f?9>Yy[FGp`vMM ^.P4(HWopK TӒaksU 㟢1h~-Mx~NH0Ա[@O+dp 9Zyf],ߣ{y۷sݳaLHIh3\\V&3CW'Q@UP\m`|9 *L&F(9'k(엟#Ώt O_|m͋Bxp?o;/Hw#,x/O~y秂}31R:H 8ZފtplKcI2 c:tV?2yHZ-65[r\]?E*?\FE*R^Vdz2˼G#m֬ⓝE t$&>[N6J\/Ë\8_9;:Ifۀh_NQ'nTdHE*RIBy ;orMBW..\)׿ yPHE*R^D}[o'ȣPC]Ȏ*p⦝{ax;X؋A.|8*~ጄ+c8 KJcQ>J?*F#) hdheFXWē8wIGy$#rp_~'>"GؾHnBɇ`o0`# r 嫔=εҧa6 -.'WEx>4ܦ>L\4Ry G'sp{!<_DgQ0}4kO#"M>'Ey W=J-!CdP;Lkzr_tI;u2)὚#H^-߱odcA09b  U%m`<~@ ʃ!/m}W׹`H[ܑȗʢr\2}K~00njp܇@8Y^v&^ӌa !k@ʍ%a 8|YMnf ›MqN([:T%Y4ar8-y(k 47+]7Yg1_*??tꩧJ;ww]i5'iu!h߼׽ul;;,W[A·-H6,t.mM0 #(Zr9ZUBF~ȫE]D'x"G?WAyaPR>8zi}YQ6Ag}//@w_5fːxĘx'\:z)P] )ڿ|TT,%w$p)oYD [cp!Uͣ {6ۼԯ@7WϣKK.M?a S-`HyQ?Нw)vQ|֍WM9xmS`'hH[ <==G5SqO])jUZ.yor^kN ?ҧ>)Msz;!Tv+ȻyxeT}Q,|pŬZJŻeck:mOav>-B<x-:A./0F!w0o?pqU20@sd-QWD[u5k;xoLh'A ޵-| ,Pl0 x2%tk_Z1z) D)i#I B,Σ{ğo~SMyp]xxVC~V 8N'46m$+@! IDAT<4phH-Hy{+_0.n~K_ Ѕ^(p뭷iF?dr ~Y-)~/~!aӟF?#?| L,|;o[3<?3n1?&d }?/rhU(ٓn! Jh𬖃Nn4sL)ӿpe?AePH@EM_2#lbVssΑTak|@UѾo/~"l7I: diG/D*tԴT를zH ob`(ap!-4/| 2o[%PO~?Cb@1:h~f㏗&Qφ&῅k~Ñ F00Ap 2q~'|)hۯ}k'p>-[HM7$2@P5yă]g8-jc%`doz୯G8m9-߄u0Bߝqi1 SN܏c͢hիW(,w1Y/ztu$ѦWɑ/9} ^"'WY @jC m VE!Թ: S_xX666yS&x z!s=Z(f',uҺ뮻\Ljs v >HZX&C aNN:I_B]u(.%*?E}{a5€fO|b5\5#:C&rȘjXLRWXM$֏8 "/ݹgYL010vfz|4bi9(;H8hT\TP 9|sЬ0HG>"5=7 P {a|E?E];TGuAlT5 `H|0 @͛') mMHehZ9VAwh1q( x3&;(G " 1v7n(ŮwϚD]8~{ |#WYL AZt0Owf2P@/sdn 3; vm[TEగ/ ꋅ^~GV!r_| =pc1a) ~I6V<`1t7&ݱ Jp} UӺ4 r`b?*>Ae~59a0;j[k#pIO]肦 m>n`AA,.7':s6&ؿ$PZֆ/׹Ҁ)‡@4H0,] +84 N`$Qpb պ§@H5|{vBʕ+eCῆ@+VA 7h'|(ۛƂh;%v!6hiD1@ =:&鄏|ccBE|F|p,7tG? /e€[u,ZN0|+ e;Ȝ@ 2uR \m,`c>Q mA W€8Ӥ0QWz-I{ #c,R*upTVV0/3d~dLHHC\&7X \ӟa+!B_@F?ptq%x7 W^xQVZ SLh"gR4> jjAGW\OPtx.dOj_a~q;ѿ|Jg0;w"-C0[]֍q]5f@ӁF~ђo; `>+sa%,Ж[~P2EYʣjXKMW-7%%6;GabR^]ShHAXw}J~K_3'X!q狈<6@ŁUU JvC0] 2̪kց>**۸F -&@\p!lM "qwZՊ+n"$rmָ ;\Isɞ9Ñj9h3kX:a ji"`FV t #uj)ollz@)7<^}}'8`sҒn~l @;4I"eCw"M 7 ,)1gxBMI)6ۡC?0aBbk?_D ,Ev@FU3A&|S.cvL]uP$3 E``w:ɘEY?J7aB3*B%}Nwp]l_ӽFc W˴i؞&(75DJJq5Qhevd' $ 3H## :yI/[l{$ bڢ;pHW^~hPH t(ddq3c,Moӟ@ӦO5 LMnl| ,3E﹛'cB1m|}8< L|#yOk W_\X^|In;#^?ΛS3LBwu7py :`bD.\*>K9dܻu77\ c^Ȥ2s|G^cNي.Awqf56 țyVK1y2X oޙZ:_;$a7G*_ȗmOF1b2Tbfߏ4`uy:aтeALd"{ٵj> i;A"&ѐ)$L' V!wo?30s:LzJ){1S&LД"0E!_\]o4lUNҢZzF?2+pM0R('dNHPi>y甑5Y4FAjBwGZ|%M4%u"De QCNX("6o`eɍHRYIٽ_CL*Lgɘe'899dRof\|`@X;iRȚ A)_Q&p}$LnRӎ\:ulsulݺE||bۃJf0H†Ѯ,fȿri繚O.2\Lfx>.e3].i+g@`s ApCYV}oR̳f6n JiG-fd }oGEeE]oAtpO 9 @-™Áp En[S_++f1+^e@?;=c߰#YqG"7mӘi~[44 k3n@ԝ7\뗝\ǚN7|HW:cƿۈSa&>Lڻ{Z@f.iXmG'u U*pn~N罇~œ, Az23 7XYR6hpGߝm#@\tW:M$Kiٴu&*u&Dx0%yf\GX_qui$`N߅T\(V/ȞaCNHl vr+OoI& sJˢ,ץtv}/-ѕwCtvhz9BvA/o0}>׫@}s24\rUi\?|e_ }.si7DfDij!z)S8ˤh anh/fZزo^)7iHLji_{[#Ny4H x6(,#,.E\h|3QgcE~a>S49.Iز0SBx0Hm-~R-0. `MRivmE*8RRJPJ@1V9?zx I %L配* )M\A{Q Y"u~G#TW;QڹAl9-Z <#OӃNkozVU ë7tw5ڹ'&sm,[m ۴[@^pF1QVtCm?ptH%Lr#N {>Ȏf];Yh(G[K3}T5-[8%pTaQTy7B"SQ^:wql') 6qkRMtŇϦ7{ UwW'}˷ҽR`|M^t0TɊ02OIͯ[{q+hҔ:W`i4M*<"I!Z,8B\{!}gP;+H;nEG\ASY e@|~7.LJ˗NV`~+_{.sE 0XǦn-~D%D5Et Gm:JZk͓M ΦXxrN8qy440N^w,r6q*`7V?xɲ 'Nr_8]qiToqŕ+?Fot}/#m'-,y;\eNZ~=jIg9fo^q=]s裟8J\7nXN:f6`z-“fH[8]i\-ѽcWsvⲅG\AB~w:YDtDRᣡbѿ{zDa"'._;u[N'@_H=+ II'5pX֌#3S#`D2ż NSio UTU{?lI[[%`p5UMǝH e-'Fwޱ!0tO#-*zTzJWF7ZTk^M .)o3zӍ?||MIw+ɓK=N7"3CWVFM[J_;K IDAT :H{f_@$C42`-_I ]VX`Pg($vwNQ¹٩dE?%ݔLcaqNPԥG|i#hn8)Z_p* o"a8D.wAW*]K͟[C3y×g×N;KCh VtO~x?wOӽDE;`-x5=Bnj3mkiA}UW~ s@Z )O[ Ƣ{ɠܳ%n' 2qD[dv)`Bk|4fߨq>N{!օyil%(Y6Μ@\q~^d$k#x%[_w`KT^}T?ӜlwM2͚WFx˸k>ti4mFeoh(x\em650QJY`B"i1;2m`S.1 E*+%e){M=8>:+w;_ْCx}WG"ZW2ăDC@/qڽ+E3g.w_A+B7 z۾W]b{=4o Sy(E\A;Hj%C% QZR]Oo Nw;U7 6e{vM+uwIg6 |>shh@(ΙOO?מN˗Tai]~t+hʡVt[h3kG9N\>Li4DoaTZ =&Z}D#͜SI?߽h q“(y \%;U?|"_qQ1+=}\zjCou}zl8Gא٘bwa'Z%7Op'PUU)T1h_O;i9TY]!V<\۩*̧~F]F LGL>:'Uu70Hx5m=-t䪙7hN_]Gry#{,NG[]3Us+|Õ=Ȁ?bcakj2i`(I؅ׇDz׍?\=N8ez:z%? l55m'\G };nNvӥ?1:9tUb ӹȠP]}<6Q.>u9-n A!r22{TLJN(;` @_dn \`?8^bBH^U[}b3܇Y'OSA ʣ_>lsXPtt)L#oՄ0\iG{cS*zgiw.*)O*kAr,j[EvѣlѼ#-_7-X4,O]Ct] ej_{3[2MEwܹQ%YX9ޭSB挀h55%ՅlE&ӌ(ҟo|/544Rk%ӖPg F5F@Y;vUU뱷c/||.;h¤:jmƓf-ȹT=)fz"ǚo'0st5JҴm[m}NN4cz͚~Z6E&6Z}d@n?Rw+hU48>Rwxd~h s!/M4pa=AYql- 8hwPx*G5*ּ$O_N-{`fm3F cbѸ*Jx˥!=! A6D{vw8ZF&]fEY]=ny L0d[0vIUP'RTYvj@<paIAm(bbCZ^1(i1KӴZZs[4rCrraƟG8s"le+h0OlIZhPfۀS Z}emxi$P1}1}>b}M^ \#>*hW8AW :W0\z:SI2ּ~'˘ucPv02&قc}16vSbJNRJp~;pay첌G.iŢ8I 1P0ЄIs l>c%J)3YkIptj1_g4) W8$&~22L8ܖF]*h?-r,)~H5`->\De2Z7 ZusB)Nf#az J(+Ң̃wmʠs-8'EMNvqC,qpΏHJ; e2"F7@m; ٢p&4byj8 d-8 Qe0㎌4mui}G2EBר@`m0߯\#H SYwOֺ [L|Ǻl$GԠy\ Yת!+K ?jwo9wT*{y t~ ={D+?M&! @E*0IMCWR2kR-yíEUNm-Ug|F ¢(e\;ƼARH"춶>ڲul;TZH$"ZI8͵,eX? $Z:MzE@eќcVZt^hК?YH2Nm`FIIxjw@̊WbBЩ=q2|  A*/!r *(4:BƒR,r}9R. rn"'WdE/Xs_5!ZQQ+=8[CuWSVѮH|å:cLr;:ݖ3>Kf ! Lx@35Ɲ`L21MZdoWY%vtwAx=i~\(x/zzi?cKG[UzqvD=K@EɬfzN[_WeugI̭L1;~h(, deYxOJ=1dWwb&_\/Oc!\!fk $ۦ$'s}Vs@!j3"L&S\HGExi򑩘ЧpV;Ѩye*rL>y {HJ`a7GC+T}ׂ2ӻpȴk+swq j^뷵4ʆq3ZA=5$ ە>$T|2!DOE(L3e|4ІTUU%?KFj;)߫_N/N<X1z1l3 #;"x,@"*h8nkk U R*1y OeD׊v~2\ H űR'A[sXq)pK==O R @i iߒPMh۶m`6mLvV6v, ӆ=[Au{LlQGGJrx9Suu@:ʔVs2\=L?yW^)p/_Ka_'1a;fBvc=FsΥK6RP_-ZU(-ᐉ! ?}>HPN.+gLuˀ}6+yp@ƿ}a H˼f2cɀ./G~04CC&HYVߎ۩,g:"1CCCi&᯼^^$}C< uwuyd p]hW)kƛt}-CJJ$jȼ”ֈ)S)Kh(Fmr.- aXhERv#ߐ<5g`ÎȌ#,.0f12 !qH"zz駞ҲRZrWUU̙3i~nPOToG&!!O:`-K"h$" Ő!Ncc*\a,cm߾9D%?'3 !.)DzPJ˖-~ڵkE+UQhǏQ߲eLL+^d2`h6nm -xႅ^linpWEzPD`M5+)y1s 7sҘdXU[!s3lr<ߜ2q4?g\MB/CHu?\_W! uW0Z=@BLw8doUGH'dG,pH45q74Δɭe[Z[DqÐ'gڷoYiy4m4ѲXY>}@;:;%]8,/ivvvȂ9F1` lh+hƗBg~Ά0Vq@e:7|\Qx ]dŊj3kuH/Gڷr35\мp?ex&WhC|\I,3Cfs /RLh/C=c IDAT:!#480(XAHKn0~oMҘШ'vܼWL`;ŋ$ 5l7>Wҥt@ ) gФI(}?3Q*8$ PGn ]ϒVlK| "!oȗ찵mҭH -•wN4Z1A pL2e5"hFj=f•!݂cMG#ۡҞ6ڢb4Mxa~Q`R mf/)(|Dhr>{ @Ġ 꼓MuϯSN'M׾.ڽkhT+X)an+ 6ᏄT/mI%w)~Uh>v!D0;D])1pa74P, Eͻe -D ~%Rnk*9`ܖXG:빽dVZ%mM}T]SC3.wG{isf|9r$kb.wb(T{sg&=n`4:)\wU~k5Z#2=(*;@u l-؊'[r i\R0a`&49i9r>5da/>ϕy{ r/$> ڍkg*~c4hP53# ѣò^uh Z|ixcV&L7)vZ^{y [AiTTսC/3 Dž[Ou /ـzW>5?n>ޞ"ZuUy+8}4]vL ܀Uu|HmyGONc(V0j~5WDho>yk"yK2'XUGI!iqN̯|ɵ ˴VIefLWVcIYZʻ3F%,ٯaZ;&z$xsRˉ,Hakhʧrs3KkKSCt[l^~Mf`w랫eH >ra\oU;vl 'xҊտ`n5*PBk]Y(d r48ڰ8uc{~$sMSxpR+ck{,-'v~E:=JOCWZUeMu4fK,we-_1Dmݿ"P+iGUE%YѾg%*j?W,SD'.ڙ?q b= 㗪Vȿ8Cx&bbt"xwٔbQzjY:1gF}B}iӦ,JcOJ`o1%3}= WloUs\;tVѡf⭞tWj{RN>0)f-T"]HW|*Qx5<+H 5iq z]3io.2R B׭f YOm)\>mK%ezND?Mv~QW.†>F)\e*ԋb-MNh9=hH!qYFk^mqTښ!EXqfZ:4+&frqQV8N%n:Lr1n;@fqe 32 |asǩHRO.5~m[Wg?n~-NaAv qBXcO>|x2e-Bp%˫x]_|XUN+6B5lK-8-W-ʑ#G~ ?׿6# ~m?=餓->o~?ٖ9f1cƄw_y&{WN8 .dW\lo۰?8 &g m]XyM7;p]w\؝83'Z\e)J+=P}뭷(gϞk ,@;vLYp3\klo bq+;}y5@.]̪%myذa38s.ɲ ,E~5;pgvqaM6m1?+J ZW>^.3<jq9Ԗ;6|Я_?ɿ馛ZX ݻw7 /`/37k8/Ijqs K. /l+aOu>m&k޽mX@,Aõ"L>}/v6 oVXs5-ܿoruugNjԨQ;wn,o L/ h g+ĉ6 ǒ+cǎ&q!߆?P6c8)\&qč&O*1k@cV7V¬mɗ |Ā8-ER0 ѣ, $,O>$d<K'~+qgv +ZtE /2ѦK,Vz_y*q*Z̸=y9 \dERX*U 2ꫯZzJsY'մKiS;`/6mFfhnH=Θ>#T Us:Fy$}Tڱ?V5!' $YwgC>W>A5ͽ ɷȀm4! gK]vR 3bAli+^qb|i:8N'6ҒI\c$RaKo`1o{ai[FXeUl;k??/7\tE8_|Ef3v}Wrs8Ӷ(thIJ7C 7|sq7VSO=eVݎ;v.SO5g0bԂO>?6xp=zثV!W|Mhp mv.,WDSƫrLp[^XuQGxLx)Xo=0ի#_m|A%Xm:*pmr;qƙBkd+߾cF3 bAv6N{ھ . fҴXa`V8?:+C9@@Ui"oF⋭2w_{Q`|oM8:q%5nb#$ڵUrG'0"""uX".w}&Ʋ_bl¾k 'mք|[VF)E,U^{ K-5 ?裏6>7p'}F섋_{1Eg=tB)Չ+(S bb=l}?drnF<# (~ /0x2) ` \u+oX 0 q).- LC"8m&Y'.AU$c_~yL#HS 6j\|OY,r_}T'+EqTbi=Xv4VxWi)7>$;WcP<(n_tiX~Z!;3]~ K0MK?H-)'߶P'+muT.>5YƯ&'PYO\d^K:Ne$X ;+L)+tMs S*Nsu -i \3;V[2-MYtqJ&9BqQ|;>& 1m9%i%ۓ4bcNM-ַpX?S`j6e}8ʅp|g!Cj63+98 DJ=z #kNI3]kdʉ <&<"5a„0|ZI13,71n6eNڤcSփs3ƃ7.Kl' 3Qox K̓,ZM48X_ʚ<*V+&-Œ0Ĺ[m>aa5 dֶƄqZ ƬpQcLfj,`h&}W G qXniޑr3OwqJ!r揸hmm҄Gv}w3*FlkwQ&% b;ۃDV+HeY}E\u{9[!X3pfM75˗58DOČy3:#."m=Pȇ%qAyp9~2sRVeP+K;NKH+o*_2kO|[Tf+R0qi!˅UDӛaDDt 8qw7 7"@7n#rXfl^nkQp!thXBveUJ |0#7.?줋!|#~ (`ba37bJ ABd>rS,嬬@zy`p,7'IX >.ys;qȇsh#`B89GzتV ]:PY)Oě:@2`sYrsKxvǙ\+ڡMC3%k!rq)ZXI $%+qb+)&"?,>c=rs",Bs 7 V= ėz8qc_ JSfɗ &.? ~ qд'-=tH۷o8ذJYQU^?&p GX:/lfq)e-WKDC8\HօΓD(O0Hv9NK"~M4BOXENӜhE(Ys Nski hsBDXIqSe;#zÒßuDO7>p$)a-#X Ƈ4H_|Ek'MgR|4ԭx0ycQW.Ǐ zzg;VyKkMx,~Ⱥ;sEhh\XH 0ŧ>c!;sZ>jΓ9lG; b4$D,VfnH,OƏI BF4qtbBn3 fFIMyP6|XH;uAxT@Mk(eG x]71U:Vhr|4)2ď+QCDy&=zB@®.zY\ +#F<:8?4R&&24iRx8o ak8g59~N;4{xq0hp^ڐʍu֔ȎT I'Uq#*_&*.l kN>P#54@pQ&ܜ&ǺNI4c1N)7M8YJ- ’?BЩFou*- 5"]* S+qFrIbDMGCtb%`P$.KQ7N..IDAT_7|q %ZfҕoS< BuLzpE*җKd}u1VP.ul;;Gد'=>*_q#P8N:5yO监XtJ2{Uqƃ<9\d|yco.b7ەN,r8d2%EXmf-M:Tg8d0':uxjBbYٔE)&>ʑ)砱YӀ8|E\aȃdf0:FZH%r0KsܜW9ĂB,|K4qGj)R+tD#rWFm4?I=,- ]?_%5|qsKmx㧚3g<'~nYF'Eq:iEU:.8-@\0i9urui\\qZWq ű8M!:8([8͇rǙY\6Mxq֊M_;-i[gRg)78Nk&8-9%am)Qpd;֏b!?8SH@nd =\T IBcJp7;TBCX?YiH=+Y%Y5qAqr¬^NRY1q\7Bfq-6Z MF8h\fq5}35q 8W ,n}YgB!l[l[,zɸܞ,ro p@8묳 aw~anڇ/&}!2q\qW8]=}W^ye6lXALƟ8Nsn}hE"|yyV2˄_ܬK/4 zXtEC>}ѣ '&Nvi_s9SO0K-T;l[ov}ЩS0iҤ.>,6>{n8'|zxpEƌV]u{N:)t=kau Guqdi.RYqƅ*7|a&~ؠA=pךxwф4}0~x[n%aa3/?nйsg2 . _~yog~ik@NjE_ve&ȷv[Xp +`Cf.4F >}]P;}%ۣG 03zvmü.KGnw9| s6 ??pzMdt{8>0^z5X,V[͎9ri.Rt4xkv#XrH1bD^y j)~wڵ>~+ 6`qb}*X.8NKz>WD O5|pUWG}D_~έz*}A1e^'H|bbb-v/\2Uovx饗l;eG8Nz+aVYepWK‰'hnnݺ#G:?pZ'TlyMtd=tlĵ@XaioɶfVïd F'y?<|Ͳ8NcVujԨQRY*o1Ayqq:h#X4G(մ8SUYX}%wiُ CKf;,t2i6dWDN 5_b%+ҌǮ0}r BA2m+kWVqdWq<5qRwu)Mfq)8N 88Wq 8S8'fq8U2+:㔦I8sui|>Wqǹ:}.8,8Ny2k8N[sui2[8Ny\\qZWqǹ:-WVqdWq<5qY\q4MWq4>8N :>qsuau)OfquqʓY\q*>8N ruqʓI\buIG&q:pieV4Ε0y=1cFЎ84.E}O+*?%6qֈ I駟Sf@*qE;tVZip}>?9Z$SN 7xcXa\sMf[J\ի q* /o{9aT*PEY$,&.T2gر_$0}ts8ҁ_״np8mq4qIG7qt:.w=zm65ǩttJ_Pcu]v&W]O;?8Wip3! cXJc ;ǗN q~&m P/D@W)"Ҿ}z(t9ML6dPSScTY^>p.]TT*o\^㔁 ;nzmBV G}nְfE],Vq>p=#,w+|b-V^bFU˓8^qzD_~ ɊY2?oOޠ,$ŏ}žyƎ;*kw٣҈N>$-Uo_}Uw*irqYw,o W2n2"oOMX~J#^̈"(ױE:?5tc:H+uإU8͇xHp ifG0SV quRy"b b]' .,gM*MOY;HCy_I[*w :N2 ԓ>~xޣG-rA@K/:]裏6J;uZk-+8&ow}0Wi+bpsCc{a5״>Û:0|0n8kIFӘf<|zfզ@ʟ㏷~OZYouJ7\q޳{As 'XQOQ ta6$+ǃ{M7dbmoi|>Wi4٘1cBMMMBT 2m|yfr;I]@8ҹ )N:$"¾[>_UMOsA|5. ֧΃鬳2D\|A#O[oYXsNXhL|A\TRW*$q&Nzi"ɋovYz/|q [YdžuyGX6v||~G ׉:Y7(3X{ n_xᅰꪫFg!/2)hifiVZ)\s5G"ƘKl饗_|q{M`4[>3Ze^ ")m|8DŽ:thX{oN',Npڵko`j/>#Gm>}¶nb oM]"PBsba^zZMq*>ֳT f* ,PVRuÒ}t!b4 hc=VzF0^?˽{Xۨ7r?k8ʓI_.nАr}*/FtY<KƘLu)\\t# *'~JUSM=>~KYw4KOBQ,ŏgۣ\ڜh,rK4K㔀RӱBX"T^ m11i 4Ҏ'S)HKZJHY+L6MRWǦzIf皥R-AXx&ekN\y% ޯ֙VJ#=TB@h殗reO ,˗묳NaB4zY5zZ|BYfq=NJC`0T+-`"Mn5554k՘1cjy!V)3Ht4]T":wJ[88<\'-a;Nk&e%UXE_SVU4[3YKaӊMkDg|H+8-EQⰈr~T?8@:t8('Sy=,6qqt]WSƜ.8 ]FrEu΄Y7tj&8h,qR7|9_W׉N:5'?a֪K8N.afuV3h\ઉ'͙3<,ؒm+"[jEqnŏI0ږ"xlf1}ɡ&i(u}ږeJ27=~2\F|x[]׺׽f;cUǎ?ڵڝ;w~_x: IENDB`fltk-1.4.3/fluid/documentation/src/flFunction.png0000644000175000017500000000031015004135251022157 0ustar albrechtalbrechtPNG  IHDR g PLTEGpL1tRNS AkIDATӅ Я{p }&)M 6]D+1#ʞ'kAIhhtUDUx})2,}h#l`*}h @IENDB`fltk-1.4.3/fluid/documentation/src/page_appendices.dox0000644000175000017500000000635415004135251023203 0ustar albrechtalbrecht/** \page page_appendices Appendices \tableofcontents \section appendix_keyboard_shortcuts Keyboard Shortcuts On Apple computers, use the Apple Command key instead of Ctrl. | Key Combo | Function | | :-------: | :------- | | `F1` | open widget dialog | | `F2` | move widget earlier in tree | | `F3` | move widget later in tree | | `F7` | move widgets into group | | `F8` | ungroup widgets | | `Delete` | delete selected widgets | | `Ctrl-1..9` | load project from history | | `Ctrl-A` | select all | | `Shift-Ctrl-A` | select none | | `Alt-B` | show or hide Widget Bin | | `Ctrl-C` | copy widgets | | `Alt-C` | show or hide Code View window | | `Shift-Ctrl-C` | generate C++ code files | | `Ctrl-G` | grid setting dialog | | `Ctrl-I` | merge project file into current project | | `Ctrl-N` | start a new project, close the current project | | `Shift-Ctrl-N` | new project from template | | `Ctrl-O` | open project file | | `Shift-Ctrl-O` | toggle overlays | | `Ctrl-P` | print all visible project windows | | `Alt-P` | open FLUID settings dialog | | `Ctrl-Q` | quit FLUID | | `Ctrl-S` | save project | | `Shift-Ctrl-S` | save project with new name | | `Ctrl-U` | duplicate selected widgets | | `Ctrl-V` | paste last copied widgets | | `Shift-Ctrl-W` | write i18n translation file | | `Ctrl-X` | cut selected widgets | | `Alt-X` | show shell command settings | | `Ctrl-Z` | undo | | `Shift-Ctrl-Z` | redo | | Action | Function in Layout Editor | | :----: | :------------------------ | | `left mouse button (LMB)` | select one widget | | `LMB-drag` | select multiple widgets with selection box | | `Shift-LMB` | extend widget selection | | `Shift-LMB-Drag` | toggle selection in selection box | | `Shift-LMB-Drag` | resize window proportionally | | `Tab` | select next widget | | `Shift-Tab` | select previous widget | | `Arrow` | move selected widgets by one unit | | `Shift-Arrow` | resize by one unit | | `Ctrl-Arrow` | move by grid units | | `Shift-Ctrl-Arrow` | resize by grid units | \section appendix_fileformat .fl File Format FLUID edits and saves its state in `.fl` project files. These files are text, and you can (with care) edit them in a text editor, perhaps to get some special effects. The `.fl` file format is described in detail in the file `fluid/README_fl.txt` which is part of the FLTK source code repository. \section appendix_licenses External Licenses FLUID uses graphical images based on the Zendesk Garden Stroke icon set: [https://github.com/zendeskgarden](https://github.com/zendeskgarden) Garden Stroke is licensed under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html). FLUID includes templates based on 7GUIs: [7GUIs](https://7guis.github.io/7guis/) was created as a spin-off of the master’s thesis Comparison of Object-Oriented and Functional Programming for GUI Development by Eugen Kiss at the Human-Computer Interaction group of the Leibniz Universität Hannover in 2014. With kind permission by Prof. Dr. Michael Rohs. */ fltk-1.4.3/fluid/documentation/src/fluid_flow_chart_800.png0000644000175000017500000012112715004135251023764 0ustar albrechtalbrechtPNG  IHDR )kFniCCPicc(uKPO⠃C|8j\HUĴWAp]|  "n)\Sh'_ [; $'\j^kx!B=mDH=65yGHۘ?Wdt 5  4$V=[pK/  92g~W$!zj*֫9ypw*yԗ4ipI2A "XxĤ$}?IVcf GYr(]MMy,Tt3CA8=[4@i|t 5pQW$ѷ+ZneEw|:촓jd3x=@BU{Y_t {+[B^h([' pHYs  d_tEXtRaw profile type exif exif 62 45786966000049492a0008000000010069870400010000001a00000000000000020002a0 040001000000f606000003a00400010000009602000000000000 Xl<ZtEXtRaw profile type iptc iptc 26 50686f746f73686f7020332e30003842494d0404000000000000 iUtEXtRaw profile type xmp xmp 2423 3c3f787061636b657420626567696e3d22efbbbf222069643d2257354d304d7043656869 487a7265537a4e54637a6b633964223f3e0a3c783a786d706d65746120786d6c6e733a78 3d2261646f62653a6e733a6d6574612f2220783a786d70746b3d22584d5020436f726520 342e342e302d4578697632223e0a203c7264663a52444620786d6c6e733a7264663d2268 7474703a2f2f7777772e77332e6f72672f313939392f30322f32322d7264662d73796e74 61782d6e7323223e0a20203c7264663a4465736372697074696f6e207264663a61626f75 743d22220a20202020786d6c6e733a657869663d22687474703a2f2f6e732e61646f6265 2e636f6d2f657869662f312e302f220a202020657869663a506978656c5844696d656e73 696f6e3d2231373832220a202020657869663a506978656c5944696d656e73696f6e3d22 363632222f3e0a203c2f7264663a5244463e0a3c2f783a786d706d6574613e0a20202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020202020202020202020202020202020202020200a2020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020202020202020200a202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020200a20202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020200a2020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020202020202020202020202020202020202020202020200a202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020200a20202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020202020202020202020202020200a2020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020200a202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020200a20202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020202020202020202020202020202020202020202020202020202020200a2020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020202020202020202020202020202020200a202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020200a20202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020202020202020200a2020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020200a202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020200a20 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020202020202020202020202020202020202020202020200a2020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020202020202020202020200a202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020200a20202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 2020202020200a2020202020202020202020202020202020202020202020202020202020 202020202020202020202020202020202020202020202020202020202020202020202020 20202020202020202020202020202020202020202020202020202020202020202020200a 2020202020202020202020202020202020202020202020202020200a3c3f787061636b65 7420656e643d2277223f3e ѐ IDATx^X9zQQQ`kl11=i5Xc{EPR+gA8y6{{{;4$I @DTh  1@@c DBeP>}quu+̟*ēOx2OKfiɔ't(֐/zaSOi)!6>-vv?H==w  2eʭQFf>WvfUd+РӧO\r׮];Sf`kf *Yjj*}ѷoz^+ ;U<<<~mϟo[T)?;2KKKѦ)))ӧl֭l߾}vܹ#mTQД>dgg'K:<~7*%[[[իW}BNl! ! K___:x`3!:uRxWC}| )fi\B֮];QV9x`"4뉩+X(;PrF4h}~c+mLY@k҅1c 5Q&O HhmB咑((!m"d =8 M\2eA h&Ds@6A f4h }  u}  ¾Cfa_͛7ƎV?4HMM>h-`v$}93t&t)NPǚkÆ 72}wB( 5h\nj%Ii^ZF1+X 34ԭ1۷ɓqvk|? zhN</5j܍7CK.lf͚ʊFT:ϟozʕ1 "\rh $Ib=޼ySCB MtƒիWYٲe_h(? Nի BoРA:4TTcƌ 5-srre rR@8ݢ۷ow*ԿI]'\r=~}E4 Y;v|WfcbvYÆ +d6m۶ ֢E VzuQvΜ9,,,|ׯG@@l@]'?~}U\ĉ_hȓLR͛7K.:v(ʮ(۳g >6lxH 7 <ݻJuڕY[[۷o;w0=߯ \ۻ!ؿ6##hQ~܀iV߻wś7o֮]կ_?&9YOG2KKˈ={M>4$ BZݽ_=n.q֭vFc&&&e5_fؾ}piF*???˭r%Ԅ &}}b9EyX6k,._̶o. BZ˗W.[̵[n#?"3f0 Upaֻw&W\v˫+WC1y٩RSSEmۘBHWA~+$W,YѣG޾}/,&uYhhZÃ]zU @θq"kժ ""… ڵkw{Y}U?lmmEo-111?_ػwءChCuZ[Z0_%V HXbb\ ؈#؂ XxxxSЪT#l.R=J|ؒxItM6j(6l0vY9͛'s̑6nŊ1an:vu6~x˭_dW[F-ZĢ|Q+]222Γ'OVg1  6t:yqxRxqlٲ╳ 6ѣ%$|OF+SEfcǎ~7VbE9puue?32EÇٮ]X2e>WX*UVc2h{Z"K,a/^+PEsNjʟGE_re֪UmIJ7U(ׯ_իǪUze%J^fffFr^)t?p|7k֌Ana&'(ٯ,--Yppp>T.-ݑwۥ :,)H? ǚFF](>|r`x}9,VMk̺u&)Z(4iܝGrɓ'@*8ydXRj`o:fh;:ڷo'V<*}f1S<%~\+S?fo2ؐmq 6 իo?݅> fԶm?:4Wi梃S^z+$q<IH" x%xPKGXXdD͕zߢ[+И&M<^zׯ_G}TSxK,H3JuLݨnݺ;VSfkkUT/_j`:{jǮ|l]~PBDqCYYY)0`^Kߦ.xAtlQ0ayUP@ˀHF7nhaaaămCP]`dC~X<{˗/k_5 ~xƬtȱSJJ* ԩӀ lW^eG@^1ܹ!fLikHU*7)14H_-unSBŖ.]*zPW+jq tZ*T)E"_5+t3EIu5k3#ׯ_pܸq(XP$F{̙3_;WSFcsh<VZAAuKkی-FYQ+ZF}RP>/ܹsƎ(] h3* llnOcN`mʕ~\'t jAr ջ(&N8Q|޼ySyͳE-[W ܹS֭Ur|S}N,O/_. 4(B 8$R*B8چ %ZNW ?U\)@Q^QEc.\ @ٳu+'(wÆ @^gǧ 8pS~˝qԧM38wPs}-[d_~<>Z(1cFE%wBNј!:uz;Bݼ/И:4Lo淝;w&*Խ۸q>vCWpJJ1cƨ|.\^!7y䩼B*7 AƍM6Ik͛7|Rrvvǯ^#)I!!!RppރRz `߾}+EFFR&y[X/^HoLXYY}Jt|PHHH.]+V:uqQ~mRF$Q]Q7*gn/񠳐(/ #ժU{*=zd3*tZ#?wiþ Ff r=@QR%/}}}t@DEE)x+FiyƍEuͲtYf͢IOOϛ/4>h/ # B Fܹs[dd1RD c XժU?z䦔$ Zќ!jԩ2_(R;v쐧mѢI;\ &U,fӦMNm۶e*Ue 8ޥKhn֭[m 1݁r @$IR\BV 6HHHHe@  #Bl]7i҄9::???viZ >'DEZ (  @T@9A- *{yy /޹sgZB]'7oq]&@ # Sn4F14Wh<̱e˾&@ # #TQO1r:<VzuּysQv:Ĭ֭ ݯ IJJBrBѣGu{&&&:ĉŋmĉEMZ|䔞ڴG֭EYuB`` 7o+Tkժ B/@$&&R( #v/EY=///6tPqٳFi- h[L n3K,ǹEJKgR*=+UE?c fkk ug2Dž غu똿?+]>+J[Ȓ5(W#GZjUk׮U5$ɔ?m2$ôd.%[8tBMIKn)%uLשS'x…;۵k߷~W4klOppC?s +\0]"""@*UV?.uRe(  $d ҶӦM˞NJ%Kd'aZv{xx_~ݻw{ԭ[W*3g%K۽{w__2wR~&I#Ix̲σ*TH[~CpY]D@R,J2t.ԳgOɓR@@DRSSu&EEEIW^jԨA"}}e c7UyKѵku';pmll> BgRHL>)mYRY:vX'O|#[O kpU^s@4<~_zU|ܸqlĉ:JkyA8cc=$I;p__111ylCXs@4ٳ:BzPkǴiDuUZoa\jj(?hGָsN?4N\\\&j[6T54NǏ 122bC ewf)))f͚'L$aƍunܸџ~BdjjJUZd0 D- )L2ɢ ?hTAvڢ:=y$ lݺQ~nnnÇP(꫃ժUo``plѿٽqvvt", fa_Ʃ}^~ԊYxPƪVzfԩ~5[je_tɃ)=sEoB hZŋ[/X--6سgOQv@Vwx%խ[wߓ'OD055}2uSHج^! } $**ͭWjjG 0&&&W5j&c(A $(qj @.],00#kҤ(N .ݬYcF___@$ ƫr* {qj @h+Ws޽{ 6 ˋYYY_`Q~]ӹsg$%<<Ƣ7lt|i 2Z|_m?S˕+KP69VJa΢Tٳ6mDZ/ײeKVZ5QvsvVx &\EeʔIhԨ}ƌTkرcRJ/[n}E@T> //,:գKө^zUk֬<ԩS w&OxEω6 a ;+ԧO? (@Tl߾<B*UX||<,(((peV6}ѶdѢEv}u]vӤVVͤlٲgϞ}USN/%Ij?a„fI%Z -gHzI9>5D3ZdHCɥKNUV?>ŋ3{Sic֮]*ՀDu ԩs^z wJސ!C(Q'$$Uɒ%/433_faaa{O& IDATY}qMnE *|W^ĉj~hZAWEu?+Yf{+ShѢyRJyTRE^bɞ={83Xvmܹ)999.m޼99&&&%**fTZ֭[{I̛7--K߉0E.\3hZI&xaׯ_?fll,D'9sPL0A Qmڴρn߾]`ZXXX2B޷o_zܽ{jHHWxϟ?_~U?ǃw شiӆnz-N*__[@<~򠠠/^kMbnDFF:`Ə :tGBBB… 7&lח O>v*Y.M4GfhisJ))_k)11QqHU^ҾXΝo/>|_<&&ۿk&-A{N2rs-.]9 @ҥKƎۺ]v)RKNJJtSE77iʕ[t6*TXʃƍ{+sttYh3hZ@N<ٖd`e $6oΝ˶lfϞxa!2L>=x5jԈ}^iM5:Q޽OoڴIIӣG*gΜ)ǃ1=B˟2JK Ot˃4F^44"T9(4cԍ&'MHK~q,\|n&Mr\aÆͼpB^xSdA- fūts;w4g<)Qq-222bDSRKL t5N??~z1`^XR<^mA7| / sUM7rXX(~>5<< (NXbɓ'?Tf$*XW\Uk׮=K.BBBRkO4yfooj }eȑ]ybɷy}Wy0է ݻw̙͛3޾}[6P9lʕ~nPϟ_mi͛b-\{ԩo?-@~~aӧb+udEm Ae?װ;w2^ޔΟ9*sV = ( ʞc7f*UǘX[[g\ujڴ+V?OB?*UȕUV]r.Jr@TF4 QMʦ]vRYyG'7 64xbbŊ1^bm@svo@o /_wOP*sڶm+9'Nw ,88cƌPѶ"8 q}e,Tp˖-+~(2(PhyG_}O7oޔ+ė.]7o۩ݻVt 0& ]Jo3)>>>ܼ\XXXR ypaĈ}W pqqi+@t M4]rJ˗/e\Q4)-A[Ϣt⢨6/RCy"|XW)kae|7=?q̙3N111z'5?~|Qu߾}WȟBMH ;''' Y|d >2 HJJb4 mOC%DD}||ٳg?u6m|E䀂>^hQ gg*O>ɓ/x5sDo.QQQ ӥKQV!kE CBBDyՈ#^7)Y$֭(+9Yhhhn9|vw1 Ry7&BRݻ?X -eʔat]}XsO%ꡜݔ9b :"_ uSN9Bsa/^4~EpbD=KLSYfߟ-[K3Q0F3u4m(*Q@dɒ={˾Em&Ulh}kU>5FuW, S[ HO*"ђ2B}YݟxEW3f.R||"?NLL}z=d"tKy)Q^%ZaCTUym<5CHwHl!R5j* nnn}P 2_iQ|?OEtoe CCCe:.(ꂕ+T!0qe˖!!!hz6tѣ+I&'Dթ\r̢scɍPO35RںkJDܼkT;htVgn"**Jޥo .W^єg͚#ʯN3f̈7oި'kT1 Jsr t }=&7σA%r=g…VO' UTaZe Çi,LtŊ׈k(4 PD&ZZ@ ;T5'G]2cbbLi? \YBJ=b/_H_rn@,.Lٝ ŋ"""ѬWe 4#؞={u9ۃ3ȍuGC+TI~PO:VZ*,,zf͘(NcgΜa%JСá;v6$ r#ɭѠAzzzI L.޽{6lѣ*fJ>CB!ߦK焃W'K>.Kه>5.QT lt̿E&u\Æ Λ7RoV;z9rdǏW31KNNqI%[CmIjzD o矋oٲŬbŊ΢칂LƎ/U L4EhlSNV A\EO0)m|jO0喉'vHiƍRrrh{͛7xӶm۪JfߨQPF7h6?{{{ܢ`*˜mC':E5R^$???.v)whl]tww7Cݮ  ʮfwW@^z%q nAfϞ]0!! \ `yo߾-oZ绌y ),JGY.>|/[z{{mذ!۲e +SFuޒŒ.tfl ׯo޴N:4A]'P#GbŊv(.n 2PBcǎ#ʟ3Çkؘ1cDu/('oO. JaժUٳ...9-pΝ͛K.K]\͛%)/^/ŋ_&Oܼyolla߾}i(NKVt'N| ʟKhEv 6HLL,0y=nݪinn޷~oEh|EKZTN8}4de˖]^pQ~Uk۶fffMxWN[2^zuԜ9s.:tNJPu5 e kٲ(NfgϞ\eʔ#OvgϞ:"]v1###Z|p(w) XiӦ_׬Y]ԴݥK Ӕût"ʮ(2hf-Zh߾{)))=O<9pbh4i{xxx#GUK߾}R`@NSV&:ĉ,44UPeڵ!$[{6ݻwgvvv:ڵkˬdɒ&L8w֖ VցL1A2k- }}|ؘ8$%%ѣ׵j*Μ938 xx:r^3g.ZH Z]rrrvƍ5dGժU I6mE~ ?ހ&ȡ 4 BP˗WxUkkk\J/_766NSv;m"/ՈSԕYn 4 ;z ?jsw D.ʔ2ɘ/hBs=qÇk+^))8rȎ,#}W˔)\W|ɓ'>|x >xŋ}ߦBʔ邠l4 sCO3fs%ͅ :2 8nܸ,--]޸qhYvEbb(O%\/L4i?65"̓Fm TZ#Er"**JNt Ƕc}Ǐ3++aÆ?&jץKo~3F۷o7_ үuvvv666K]2()Q5j5@<==:w܋fU4h(Π^@#T\/{,d+155VX! ܸqc/+wiw_zJ*OViժU#Gt!LN;ԩS5RSNܹk׮Yyrr2yHsҜ>{gLt6lӧ.%%Z/`1{b O/_>_v+W?~|e?*V@+\zuxPPP޽{q/ʮh_J ʎ-^X VssskTB^t7o^QܪWطo_4#,3όUT#&$uQJ%Vz1vw. .l?Q~u "mڴC3_?_.MIr7nuk|*ccc~_Z-%4y;vcppp:0t{ٳgxVVVOsSDA>V~իWFOo޼iծwڵBi/u] ㏺?Dӄ;99h9HߊW888Dd>4ӳ;M3p@tKC-43lbŎ 2䓇% 6o޼ݻw?_kM(v5h Y+Gq0O>ݒ! ruu*˥q`L}^R ,zoS۱cGQv@_ݻ&Jjڴ5}A>}011s-] ''!gnl2+:1: j:BWM+dҥKE@&<<}^@O^חj4jԈթU H@@Gb^k, D taqqqIFS{KxzUpBr```k}:yzpݻ߿uRXNDucmٲeܝU:466Vo߾tUN8{,{5Rʭ3f ȱKaެYÇo2xӦM:::u?? ҥ u7e wܑSJ'NRΝkܿXbk׮:!))I^$f͚Erݽ~vZZp@x%ÇEu~vvv ,"uV@Kja/S(N!C ^{x<! BBBLzӝ^xPV-Z&AF(?iI>:p^u%/GP}VZ5Z6N?+ 9-ʣiQpرs-qwys9ҥK5Ə._?~,fy9lO'#W_}Ŋ)@<==/Ui&8wgZ4Bfo~w?ݻwl֬Y`ee%M4a۷og&L;YC IDAT?ѱJ3`խ[eРA2h:Z7"**fd~mhe˖3f`ŋsw3ϧU={fO7o<]pJrPzC)|yMgΜm%@Ap AtDrFCF=xsGv 9֭kݺ5{ě7oy "/G?qɓw\/h^ze6,󸹹Q0ڵklllXҥرcr_YMBn۶m4DB@(dt~~~hѢ4.hz*4yu\#G\L:3t1?6A}e{Cr9qDlW,?-_K_- og2+W_ѕCClCc2^Nm>ܱ޽{ˏ 3U?&tYfc(Jݸ軥zMLj=z'Thժ -4!qtV-: u6ln޼I]oو#x:Bo߾Wٛ2iӦG?E.Ju=)D- I~U3*zO @ǟp~LIeLL 4Ȭ={̓@4hS'Nb!UL"BZ.$ń)#?  dϟ?Y8dooe˖D@3H;vSpAyJ~A UǍ'_(_|o{MÃ8^aF_PPP+W|m۶+<(tM:S(Rn߾-LR@rJ~zVfM3g&8}tyÇʁ);BZO ZM»{8Fݻ]\\\د*OT'^t|QwbXJ|||؅ hA?~@BFAsTSdɒr7d Nqvjq㹨=OgE.! ̓=+ugAF)w^wlTЕ [[[~oooBlrPB(o.\ժUk3?v ѹAya~&MBE (yo4vsZ.23:vX!zܯ_lңmVZ%_JLL['hL!ry@/  z2|pyu6ʖ-+)N )RГ0'֠t l)-,,2E-/σӃ  }Μ9r^ҏ~Tce7Q{eٷW4N)/駟,?~C^ףRQD[@P ]ecPѶ@S k>?6\BʉK IɧO2___mnhQ<"Wg9rDAG%Ik߹sgH 2(Qv`+PJ39*QP@黑+:*kQO(`]Ѷ?(PnCe+ _Kk˙.X~d{P?}J$VBFaÆjU<9P?\D#c'N)谷=z[[D:ӕ)u)) TX/wŬgϞq)E Z^ʔ)Z7;[fM݇[hA_bjVx >Jݔlll"7oW^?w[帞fBT4&1Q>Gд+VLj09Р@B PJBF7'Wznݒ'\еo(v qҕ̚LK%<wGr[O}4iuItaŊI]~.<СCV-VhQϦM;vl۷oHWW.z9|mfR$'tL~e!A4:>/RP UiwiZDyD(?OЭceE(?MA]^h|QP|ȑ޾}[u;vbڴiJ,LS!W9Ee;5e9B-믿OH]( rSBRCTKB^CTʣt'r,+Tٵk|[FCvvvMe>%O+x?H^^^ғ'O>kgΜݥGFFJ}}ӧO&'㧬_^e 짻7n{(bcctcAAA?aCAăIՖ/_.ݻw?/\ :i :M:޽+=~X~CJ< P(Q]իGe /Qcʯ_vL*^xڵk?}D~V$ Z$oeʔsh#Gt E~8::넗/_SNQE,'DI6oެ_hQZو'cLx2͘.^xv'h&'Oٳgč7^+^3 ujA= m>VBw]PPPr.]^dÇ ҕV4h<,0yP`HHk֬)sV^^^n[lY1~k׮LLL*Sw___&-!ٵkWM~V[._(N9Z_֬Ysˑ#GD|caaak֬ԣ޵kth;E/^r$''"Wjƍ_.: :nԨQ޼yStŊ/Ju5u7?S7oYA+jdjjjdaafqƍ}2 Lޝ͞=_s Xv^U//ƍcǎFQ!ի>%:wLk]777vuVj`[(xaw޽ESN-~}-rOi)$t钒Bw[^=`6A4M4 |_G $'~폽{XD}D c WR+W*U7/x- )0)m|Ey oKgϞ1m46lj k!@ă{>qīQSE޽/^<>}?d`zeի3Z {5U S&tԩSS#y'?#E3L j~]$QVyfٳgw+eŗutt״i7Jr9nݺߺu/Nl?wGCr-T ݻwkڴ|^/^L3ӱFA6Q tLLQҲk׮.\7mڴt}˗/*Uʇ;vlZ!MW;:99ٚ(P@5f_~Agؕ)UZj?]@2'""&1AX||<[l?hN:B-u- FFFzp! srPVrJ-R255"##5å@}KJ,irʎɮgS ~99,!!C4,}2LK~ZU٥fSRr[JI}PyDT700Tv#Flwg͚6bB=z=zxAtS:,_ NNNyh=&<޽{'"Eoݺ˗RZ(Ѷ***@Bx~^}7n0`֛ҥu@h=-N]ʕ+kҤWB4IE~17n\-[t>fxT2٢o;w>RD^ذkkTD)Fc$O{%5^PTQJUI͙Xp̳˖{i^<mk׮heeu͗Iץ b@eyܹso-X3v +; =9A׵''2(R_Wt5 N\$AJJRjԨѨQ]ӧO?ʓ<=-BЭY!.Fҭ[7w\XXRy8=^R S œK^Ip~|u^/UO?u1ѣ>|8WdjTS>\4d]p݌3h r,ye&N(_% dҤIrYdN8|OxKF`qg:;Ec?|7@^ey.^&{ Kǒ C/O>dzZΜ9/_>44-Z3ƨ̊)¨AشiLΟ?O *%_2c |;lsZ4Kx=J>rQ^=zdW_mٓ'b[[YlN:r䈟,, L]T'ԓ, }25o߾ݻtoj(-YKKK|ΐ+ tȗP`A`8CxcǺ?{̪o߾L2ppJ*uy\&V,-%Ճ0tE H,t'@'ڄ9\-[ԩ:qD}/ $ `n% zE^   qƬ~p@S𺹹1[[۠vſ#Do+ >[@- A:˫OttF RjU֮];fnn.ΎZXBB;wx;w0)ݿ988C֪U+q{.du1cbbDlDDx5kZxp۶mӲMtARz5}s[-C cd: K j<<=״iÇYdd$/ŋ_f uw+^yyu$<%::={L9DO' q1=@'?v J@2KLLd:t`3gdǏ{-qqqlժU"x֭U}g-e믿f Ȝg\碖 MX}ZS*Tiv֣GPҵkWveQ(Iaf-Zʗ/Yų4L>ԪEߟ|,rK}%{Ɗ|$ t)VX\`97n >x>J4h S0EkIݺuEFtQ$A EڵŶԝb)111hv-Y}{PC]nݺ%*cƌa?Xf7ohcڵPB]S%K]C|ҼySsN(},iÆ `˷x}S- lڼy(J 6l, +t“C( $e Jx+~AhGF\ DԨQCPakk+U D-P,%2ڲn:VreA.]z WWWKcTǏٷ~~W6gC#-CߺuSL IDATXhAfG}n34) @QK u}ܹs#ݻw#ҳgO zZ+VL)C+Wd¯?3?@'t,ݻwPb@/ @d>.]:sXb' iK4\;͆EI6m$_-Y5iDGIuY.[@L4II 0'zA;z^hZNu.\X$)utjUBqj>}x]T BI 3NkFWEsV{B=N:uj^=&&Ƅ0ҋybKKL普2bT-H %TL|m'uRx22l0?\fͫ*$$d?xa0=233kbjjj#ۖ-;;;:{! $/vKb:u}mqȑjxcI{l=ޘTd~Y R{=*߱.SүkXDǡx^znoosw%@W4YfLu@@@m۞ jHR5kLIBUh\1kٛ=Zտ۶mI+-ȓbcc#emyk_'|jeeuӧʗ/}vYZZjxbrֶPZsĈvÛ޾}ٳ~+W;vؾH")1B:tڔ?F2|;w]bE+VVOOG .yԩJ={IPAoo>DA- SNm^;5lPPO?4[%-JhoZD-[n(Y,' FcT@{/mooXӀ_yrK,q1_oG4H^z.&_ӤI]|oxwUf.^ص@<)ffffKs{opӦM÷[W K^?X`tյ}```сf 2NSyMKmlln倚3Pͅ ~YZ1;_PrW^ܻwzj2}a*dDpHH%~޽{EGG?WݻS%,Ǐm{agjjz'"4@}6߮1bR8::lٲÇwoA'O:˗[DO2}T XfG7BweftyљEZeo*WnXYsN7nSNx]uV@…x%5'd ?gE5nܸ?cǎT YePrmgjժufҥ[֮]kݵ\N񘤲e˞tҗS"xR{ۼ<ٳAAAOxr8Ȅ~o+矏 R^rNooO3gĜ+tR;z?CֲeKYkJO<̞=[LKSԸuԡD@+R ?(uC_j&mC9XpXXi=ZMq:+Ӣ{֏^ 9x &`̻uV{ĉ[A涽} }Hk׺$b%wy<Ӽ۲eT]dH)S̖jժ{zzIEЌ3.n߾V\\\%J1cƄ|ۇ￶=z4-6>>~%Ӻs;4x^...[ֶt@Sc1Ӝx}()))2gÇ1Fܼyf(n߻woe/5KG'O*UT?rXjіC~5N֪U+SN/_n@heA=X𙕕իWe[Ȇ4e֬Yt`Wj׮}'%d4y7#{ݻw}7iZrZ7EKEK-+Ԍfi׮sww]h۷oX|V2.[...ߠnP4ܹsEZ"h `&LP޽{֕*Ub;vCrРAСCd^~㄄1毿2+PD fmB SiӦyAKSwQH1P,Tt׭S38cǎeŋBLKpQkv3gdfb ](qb9^fMGn^Д橎{e?Ԅ]Pe)=!MyA{F e9nœ%))I\x1PN{(QQQoH(O>Uݫ<{L<ޢEqe<u1][ŋ+9IQ-@AWkM6nбV7C0^37ԩSojwy zdN]ݼ?>RaѠtjyxCϩdFũ#3z={禵Iʔ)QFѲxxhxdzvv4h4i" W .?ٳgZdɒ^AݻrsڵE7klѣGe@r]Uj4V7R[=%S`h'O . 1۷o,UƋo^̞];vL,tȟwO?'%""̙3W,[YM46vn޼Ys֬Y_rTՃTyigcc#sݮhJ_332elEe@ҤI͛zos@@@ 6w#LMMԩ u)9޽{w'tbUrC1i$W dazq5R˗/[N@~0k֬*wD)Z*TH)\2qD E+sa~e>Cy ѣ\h `Z]rEtyѺwf'O%%%1}{:u6h~ᾃ4YETT3}M!KpV^=x@uvQ׷>-׶m[YQr1c QhAΝ; "e,::Z,.l2$VOPcaa[JUxz}okkkUVˊ- K0]]x@}J6`ծ]{ m6u7չsƍ+!!!ĉQF[n)T5jʼn'L?mN߯z(5j8tmï*M6mYBkݺ\H6%I3P]+VZ͚5βpbŋgӧO DD|m4;ɡi&ְa6СCTR]tEE&Lƍ6 NP # g*7+.m6Œ&ϟ?3~P6Nl(/L%%eIJ%:iӦg͚kH,' _8se9iݺ5[|9ۻwX }lСz$4&Y~=[n}ʕlϞ=b\@1cȞ&h;/iܸ۠Ae >bȐ!mfOLLd fE]PES8w<?nذaO1 { rzaaa۳Ν;Ύ^ [f f#Gd{M2>}+WZmܸQ$JKQˉ.99Y$5i<au2jԨ¤tr(Q"N---3s1|O]msu)YީS'Wׅ (<);wy [ *qqqiokk\Yf"9{͛7W}[xyAiR4  t֭[}!&n[l 5kۤI6N*_~aÇcÌ֐ &,EKYkNaʕM={ּ^zWeFS%K,ԱnݺkТE W_MA]V-pʔ)Oe^¹sř?cj[cwQ[>vX/Y<蟢(&^^^C}4>KQ2h *oذ3Y<.Q]#U#K hwf={@k*\&`V^]ѣG˖-˺v* 7 m۶)Rlr,@LMMib' Cp{J*PpY?...GdǏ+k:Y]]p]xUX?-е= YJ@8-[ԕo#Va_ݦMtg0۷orJ'j{pqY\Z[[cvP]$ !fQ1v=<^ie˘-裏D_bcA'JryfqiӦFi&B=蟢({dڷo_ >OG+?zuolC/RҺu?N:ȑ#541uŢ>?666۝H6,Zoe}TVQԩF(mܜAҥ˟O.klt5,hB;^RKK%9$e*%U~=\bō3gμ I!C RJMqI/?޳`&zaffFdY,% gΌvt“Y(wM,5vbϟ?g-Z(sss:$[:1y߯A-Z:asN\F~) d@y4nѢEeFԩS͛z̙sKO<H@ ȳ<<0yn&A >YXXP(+V4 D ֮][nh2;;-Z)зY@$ '^^^oQ`"""(!;ٯ_?Y<fDKd@y… ˆv.S ܹ,(P2m6Xl˖-wP@3 d@y?,٭[7{˗ŋYժU;]Ԫ,s 555e ۷yhѢ!x}SݻUbe`<@sرvMXƍeF!,,ݻ,Y2W^dƍbZ@yߺu*PV(Y,$ xzzv-@kF3K,%%Ek?Xٲe= t^̪,^xEb󋸸86sLBG]w+ FK|LBsEZZ۸q# Uי*&7ݽuV%Ktrrʶh]ի… ׯ'N6l2ɓ'ԩ3dɒe`<0o%)OUG4Af?͚?0^)b5k֤J5jD޽{lL5u/֏]v1{ry_1b+kƲk׊z=zT<suue[kv0KKKj*֤I֠AW^'O?wއ-[&$Wڦ_s[xboҥ˲s>QdK.]b8;;ۋϖ>Jjժž+ZlWCVVVoE_Ŋ+&>jժ#GR)YM޽+k۶>EQ 뛕+WΈm MMMdwybb"_ĔݻwgSNe˗gFJ^Yݬ;ִiSѺBSy*Ν;Eh֩I&T$?,bƌ#*g}+VH (J*dVF QɊ+gx"o**&JOFIU@@gW\<Qm|%\Qc*WH0֭['CXSLfϞ=mϞ=cӦM)511<}=Z|7(1HE bccW^ʕ+ٙY[[ˬPB<2ϭy2U100vfZdO†ֿ8! Txҡ-IH -8ǿxeС`@qڵ"""3.ˡݎ*tƛPx*88իWOtafTqJV U豴k.]ZTHIFDśWDA%'<<\$Fɼ(sѲm DO"=zG{{ge˖{̙=YS*-EkPB~gNE!JdIϝ 9% QkJ椊SC ԂEw|*ԷD4gjzItB9J @p"<iOtSzU]RkswwQ٤^>9 T9VǏ'%4lذO"n8t|:uJOݳG._AΘky<7G慲o߾REr=oM7FIvP@M.22Rt٣EPųk׮br^O߿'h{^˷}}K|9BwEWu:tAInwlbGÆ E2ߊ/j ywH;ٳgĒ'"~Oh[m%G]uƞL @n3kҤ6~UYnʣGT”hq.CBBudggǺv* 7 d,A{e |􉈈(ݥKZ[n_Μ9Ck<4iIY<!CCQ NNNpAi=ʕ+!ѷo_ԨUkٲ,(Ӡ|Zy*U6 0/_gݫW/VP!YQ8p>XҥKd  4633cڵ`6{lVH֤Ie&Y C#))OBDaÆ{ڵko]jQ6y&aoo5((/h5355modzvQ`VFImO(ʂ@g^ꐀ=џر2-gkkKݲd (q ӨQxL,t  ˪U:?xѣGͅҋ9/f.JLWEg𩤤~./ү'hy\ٲe+5OQ" { CewYK4/]|=7(o|D/ƓYh~.XBCA*`3DX=x@u u!C.XBCcE!CB yb^ꐀ!.X8+$ :$ `HK]H@@uH@.X2<  J@eA3 ]C z   SSSZ$]+U4 P0|TTCхbii7T ''OB!mLLL4ŊCCUVg4 :u*Dtkl޽L2wF$5MVҁ@ !!!>r1ǚ5koiӆ-ZT)AZZ>۴iH@lllggQK.]#@א9tP 쐐L踅\;]a_~,Y COݻwpԩѶ&bKR(S1O/f4e^(Na^zbzK\KyTҥ >G65H@@5AAAAAS|R3IENDB`fltk-1.4.3/fluid/documentation/src/flCode.png0000644000175000017500000000017015004135251021250 0ustar albrechtalbrechtPNG  IHDR g PLTEGpL1tRNS AIDATcX x5 w=XFIENDB`fltk-1.4.3/fluid/documentation/src/page_codeview_panel.dox0000644000175000017500000000552315004135251024051 0ustar albrechtalbrecht/** \page page_codeview_panel Code View Panel \tableofcontents # The Code View Panel # \image html codeview_panel.png "Code View Panel" \image latex codeview_panel.png "Code View Panel" width=9cm The Code View panel shows all code files that can be generated by FLUID. The Code View window can be activated via the main menu: *Edit* > *Show Source Code* . FLUID will remember the state and dimensions of the Code View panel. If the Auto-Refresh option is selected, the code views will be updated automatically while editing the project. Code View has four tabs. The first tab shows the source code. Inlined data is omitted in the code view for brevity. The second tab shows the content of the header file. The size of inline data is not calculated and shown as `-1`. The third tab shows the list of labels and tooltips as they would be written to a translation file, using the selected project internationalization method. The fourth tab previews the contents of the `.fl` project file. \section codeview_find Code View Find \image html cv_find_row.png \image latex cv_find_row.png "Find in Code" width=9cm This group of buttons makes it easy to find any text in the Source, Header, or Project file. Press *Reveal* to select the widget that generated the indicated line of code. __Find__: enter any text you may want to find in the current tab __aA__: press this button to activate case sensitive search __<<__, __>>__: find the previous or next occurrence __Reveal__: clicking this button reveals the widget that generated the selected code in the widget browser \section codeview_settings Code View Settings \image html cv_settings_row.png \image latex cv_settings_row.png "Code View Settings" width=9cm __Refresh__: preview the code in the selected tab as it would be generated for the project in its current state __Auto-Refresh__: Automatically refresh the code view when the project changes. The Auto Refresh is designed to use relatively little resources, even when continuously updating the selected code tab. The Code View window can usually stay open and auto refresh during the entire design process, even for relatively complex GUIs. __Auto-Position__: highlight and reposition to the source code generated by the currently selected widget whenever the selection changes __code...__: choose the type of code that is highlighted. In source files, *static* code is generated by Menu Items, *code* refers to widget creation code, *code1* is the part before possible children, *code2* is code generated after children. In header files, *static* highlights `#include` statements generated by a widget, *code* refers to the widget declaration. */ fltk-1.4.3/fluid/documentation/src/edit_snap_grid.png0000644000175000017500000004315115004135251023035 0ustar albrechtalbrechtPNG  IHDR~ItZ @iCCPICC ProfileHWXS[@hB *vdQl誈b;bþXPPł]y+ߛ;Μ;sNrD\T.9N(0 s"ftte{yw Th\hy<WqERljHaZb 8S8]lcY3Pyz!7jC( !˛̃8 bkh#XHA'oÚN0EV\3J|Xª%Vp)VO&<=(%K G ,3#!fC W:MPX8fX/>Cb*̯INS:VcEYIS 6/$FB C~N\fLQ+rF,oq,_ 3 bH>P*s̄!~Ac=|aBB烨 V>r)?7DʛB_')3D8lNX<|,@k: {A&{34"I#8Pz_Ydz e#rS@8ȅ(᰷D2xʅ*aB&BH<Ն,A@b(1h㾸7: sh O G.IbOQ]P?Xs[BM7<P= 0q? ,EҬ ~x ;#% j6"ǚ>opY?d-Av ;5bm1)^]Odk[,#'+dccy_ XEł̬:~t0 "}}7?9188x;vp7}ӡ &D\(pjp#`|; (D}\b0@)(jl[N (8΂K  ^~|FP#0_$@bd$ DGʑzd RGSP K%UEDeI*oT%՟B-.POSP?TT٪<9WU_,ԘjՊ*]VS'[9+՛;4hNQy5vi\$iZji4K4j|Lhf4KOF;C"jYiʵhkkkjj'jOӮ>ݥXuruйiE#F\^w._Lw Ozt z zq}[=;l䁑w P[X[  C E Oe2:nkL352>aMgsk~PvϦV Ŧ{MQffZ͍ǚ45cA`XdY8g2ree۪Ȫ5zuu &f[6˶jn'`10spTN{{}}CbG^>on:i:9;5;vu:W:_wqityjwzˍ6m[Www{{GGG'CX8I y󣗻WswymcS._of.??_#3vgLf6s7ec8p{kd X>Aipfpmp[Ȍ塝lC6]>Qm8y,:6lʱ"-" Q 2~U#1ĘʘN3c&{4nu$%Q-15&}R`Ҋqw)Y?YܘBJILٞ20>hݩn7'XM6DMRęt0+ 'SHgWsY5<*^/߇,'cEFOO,>K^*;4{S9I{򚄚ad&wD)^SVO# |ZaoaeᇩSNӘ&6vϊ~hi2ṡFfnc6dNܐ;QرxEIK K<%RRqi  ,Z[bcyEuuK2/u_qqp~wXQʱ+WWzz PHtX۸|ݲu_gQPʠjQ W7od|ӧ͂ͷlJZm~cV]{;;vleki-Z+ݝʞ=uu[-I=ߟ-Y:L;\VOojjLnh kjin>|Ȏ&G+i[zr'E'Nez2qƴ ?slN9ׅ /շ=.7^1U^;{}ҍ7nLŻs;;w>ߝ{pco{ױ=œ'_KRV<3~Vs7ϻ_^|+SϪ/W[WW{ۖ}~_AΏ>%}zyҗ_m6 vo0opPsdhFw@Mg 3 gDYqNm/ @4xO ס\)-Dx5=/"?s-| eXIfMM*JR(iZHH02210100~έ pHYs  xiTXtXML:com.adobe.xmp 72 2 72 1 300 1 0 0221 1 2 3 0 0100 252 4IDATxWՕ_2#M@" (vT51j4k&1i&nOO1jlQ](QTHD 0^ywfewn={={O?^=FOn|oۅq a/==\ a@@/B);˅x ra/==\ a@ıK5 scQ:Bֲ,w:thMM nP3f ($Ig{I.Dd0` T/Ϛ6o|Ҥg\tE'4_aՊYƦ~ٲ-G_\%ys,zeaZmyiXbԩV!]wu-(aX^Y$JcQ4z͇\xߜ|O {e+ϸ`z~ŏ{92v!ܜIKWhKgE3g#Kej.$ d2EFR);"=)ULp;'Hd:) eY(fRƟ82UC?Gsta1ik?R;{=f~-ŗ^T:SOBg*.We/.]aO|bر^}E {xs\2yFS{/˙+E/ڰeCE?s|]|%o#?[+j*MyKlU@դH̺u.ɓ'ϟ?^;3^|E .]*z(KuٝB/ҩ4C!ÿ.{k)E~!e\o%~vu1z>~?/}f/ \J%(t oΘ1GK.7oI2%KtB1Ԋx[bŒYGv旿'@7tߺq؄~r>βlTe+1fsѶ4qw×ઘva< ~8 ֯_D5jaAJP!l;'H5#1qLǟ<|0 0Ň[n?>v}9s}gu)8e`΀Ԗ.֭[Z$>T$hllqVngiCwBW"_VXb/#Sc&'™Lp#26n(+2/_5fUXRPp6"Y@UWW~`Lo2dyӦ >~|?O)G:1#)կTTTN9tX_nQ$wo妛V߽ŠXΘ~c_q6 hjyCG/ݴq)vWvM_jO1<0`؅:%˖;Y/5Y[,tJ^Rbec`$daCG-4<Ғ公[7oBYS]e;t6D^P(fM`)WT(ԔUWWU2͛6YS])QE/pYҍM[78SSUԌR&z=tx]#G ϑ 11¯۞1vVƳcۈ ڦИ+KY }2P]I"b`l<\&?L۵ (2 2t )T*mJy1 Sh3X${&, @zVU</']SQZ=¨Q q2qGSex6.z&LU%S р Huuu $wImXp(] =ܐ#=6u.< ۩)ƉH_o=sp{+sg~d܈8}* „ Xxg/L^3o#O47=xŶ7YIJi)BݸyϽ+3\`uC%5HS ymڜJ+q_HEA;xq^}kV\zH{yC%=sWkT64R)E4KYIvsɓ^/x8~+k`.l? 3THO8W]9fDZ ĂOE|ܺ5-}җ4̻%l` lfzq 8`dz:bAk/݃/уm+ÊN8ɤuW;G=NǣMxH,#4KSe;y'U {H0dmjx'\rB̐q0b-Ŵ`Zdf2W!ɲ7,ҾY@5Y!GCTrƜa;^YYVuM U>wkaK?ɾ"nfװ=nYe~pLأJ$u٢c7>q hjZ źS^Ed#6HC 2 cϰuΣ ټ!Y-=.cE-j5"KgG#N2 *B3k \,bILz6*(\#belB[01ߕb7RlZ9vF!#Ǩ[dʤJ~ Ќ>0z;Gs1WJj2ZLWvCY@e ?* XWx%`J`wf B疀şC|AL '"!.0R2E +&^A-3Fdhy"݌WĖ9kۗ9j̈)jqҏd(1 )iKrg#G-"> J  H-8;gNBa(_)!Iʿ0/XaByǾcǺ'р71]G+,M!ŜDP퉌|1[|?+wHPmڀL)c{h1$`r|baX&OKhb"DMFbL2 '( ""DؽHQS(~džn 2eH&%Eu͖{^I4 {vG!+iG$[;jYa1*X\We$Ҋ"2K s@NH*A* Cd8L\$fՁrcep Uo4)Qv&spX(nV'M^X=. b<@l|n{A=m[ ,[0H4 EJj %íE8J![dCc7/jf6j; TQaE؊5Y,rdb?,`› ?5aHti{arpDk]vF0 A6)sp ra4$kvHI M(_0|.9>2 @za?Q&SbhDz)"iNKARQY?,wV i܎ڬZ#2w@Q&0r9nDk@d=Y,V64i x — X xj~٬{lLoX '<gF3ŏ?~Z&I)OddTQ&3,u-?25FlQwwtT_ #4 0<"Bc|_1@DWf]>s&S& %/Ny-˜%>xkAk%X.wܳ PlkS& X~9 nk]>cU"+jXؚ̓Ѫ翾zmm:O$hd оҢnvق? XU+[ i#.l]yOP#aޠ(T2ƏuSM*"ve W`̑ǝPV۸[cY.HF%E##&w\WX9` /ְ`{Z*>-5HLw0s!'m4WZ~`3DzԶ/ۑ9Awo[?ɾhp~In|w7f\[+>u—qmJ H@p+Yo!{V}YycZ0 5hQǾ}W!@5Vo ~jVqH?ZMBg˰报TEeϫgs`w|.rAad *͸IkC4*iM? 28U*TvyTP^&8<٤UfeP&D6|V,q,Gs9ž)qL($ +hęd&K FqZXʕaA9)e򘚩)sC0Bۊ%JFL 9ZGR)9kRJGW4ywuװvN);M%m69ii,r (Gbs)0@U %_D2"Z#K ǎx@],|(2VsQٵ*gSVuVתRY^gSN Kߴ^N形#TO3bcoRAkL1LRL[M;zλ}J܉8aSc٢oܦ}rlݬ51p_(OxFd ˑs(Vf 8Ǩ" $l-\ PƠAc/5MW/_4:n+L$gwqC6bDS DCҲPҙ 'ij~ ,,w Z۵Ճ,\mwL\~Ya]dL=?q\=͞ ;p?Ȃ0oJ>aFhIȲ0n B8$p2 |ٲ/SzKEHML"ɟ")qCDķ/|݅lEˑ%'$D)mmG;vx_5:+ZxVֆZ}#:O \ʧ-dC9yƮa#/{Lɂ;O̎FU'~ 9ߪHY,xDs{]Ӷo΅L-?=8s6yG _xҤkr檫ַ5}tNbG_+򗿼a0W\yn'qvw-׿'?I+=;:҃FǘO `K a)( XB8Go]5>Ӧd*=lDT3!~W>⑧S\YLjٿ_تg8l֗/d"_qkp!?Ϣp1k9_[ooL#ֆk=0+ll?ā*FeʴV\9c95kGM5֯zw58[j5k0oZ;{* 2}> qo/ro}o_~YfWnU7,A_,^Oe:U*ڱlK8nGBg(E5) PL)PHRL% -(cJ/B51K;99HON )Է+6&>ar8_1q8F7"&ZkK= eڐ 6م_}c|aWXc |LR @BoLcģ2h 2xr!aDzvwk3de@>/rwuz!(p?Lzk 8PھVM -5%a\:)(v"X6 F0Ӱ:':Brׅ q'}ԆF >6׸5{kN:|'/@z;vz@MP9XVn?I'>̀y>2lĈ|8tp92"9lٲ!C {Y;xsjja  p_`TvwFL80`@M2],`EcW*vcYBߦ|S?A <ð !3O?slٸq*TX,u~S|óysUU1)~A[?q}_uوYjݺuXjG  #w©|N%m,UxrqH#drȅ`7\ E .Ҥ yd.=x!!&?EhJ (Be8Wy+$fwVadK&Farqj4Pz 瑥@%*mob?VFϏ*bqM4s9|ad+iBy'q9"w0Ppm%J"?`O%r܎=KKD&*o),j]JhCG%F>~rŊॅ8LxPfLJhg: aDJrLciVm lb %s_<BP(B+r=!09QuDgP:6P0 3yw *'A3\ բH`Ҥ"!"x)6`D%TpԎ $_v=y5T@&[tLz'9"4i[m'!DUI8i# Gk "G ;8Ot*W*6c wL:JV-xg>-acCvYE8-uI GHnGI$##P!ʥ,*/4:Tqz*BhbaZ]c{0[Q|b9'Z*]Ooh1{|'=x2bK`M3h-jHg̞qe 0 E5-L+^c;HC2Ýd m!%J ;a&B5d U s'`6gZ)J}S~KCjnohb`޾)şT+s|c|g䴳8JN{Q=ms\0vɰXҧAo+/%*DmJXMb{Dzt&$:--3JhBQI%$m-%r;rI {UkM8DW_Qe_S>37sN#8aDL !-wyӶR[)յ\REG*=TblЧB|( m2=p YmbX@6 N!ȄФJ+DzZ,6b:,k$uB^1":XTz׭/ij%s"A$RABq@nCAHQXRȦ 7Fh Y2 V d(K|~PWJ,>bR9}|ւ=N:t~"e.cRDɗ+Լvɧ`DԶ'M'!D|I5w:m丗l':dbJhR,6v#b?ޓ°Ì G۵Pa:H;u8'3L 0>qFV!ڵ*I7/0Ġ->8ZIl&&af>>:L ʂX&%F M[ Ѓ袈JqZ FZä/"mu $5` '5&pV7QZAhKɤXfLb"`[Qc.S 6\-MTŋm"{cƒBH­uR,c'N$"EFHERkpC`Beh,F 8~hcvbfIZQ%Is@h+R A|ޮ@&՞o}oP+#E@g[7WƇUit/ r-vB0Cr:Teǖr[">v;aT6ǴI6741 a/l/!dF|zv;no_oHa//~ ݻ1nPn} ,ÝĿO]M zkC=⷇k_]W T\TמJLW P[(; +N[SC *4J!!Es t \m^iq)moJ/~i;b^vH_f7Cv t3޾?^^@wc.l ;}L;Kݙ+\ w=^ >Da|%\0زB܉Q*FuG!o|ʈD*^dUJ+b7p!}k)A|YQ%M>yz$Ft08USurp^R*NCgu7~Ocp% r+Hi/矟?<#Ux֬Y'N|gxoR+\B&حkSQR &A# ǿ[o\x9O7oVqe3Oz,_ cE~s6C%FD(12=[ly9R#<~HD+0ts璽~W TDdi)+dޓ0X\TJXMo#F$W/rX/yo_^-=\6P>kv6^~e0&;?sPTt1B,ȡF"  iK__ xFvUcG#$~O4 >#Rv~8~Mn$%̗5AZu~g.bᑾ\Luؑ_]d)Y{>旾%RR/wʤ(HEu3}]ܐMcCwKV`B:zGя~[=8r(s!\7p-BJK2NJӡdLxWs'DH퐂6S26fSi%j4Z5VnbZ0Dnƌj&-4"L_NS2$; F B "G~: 州 %#m $& PBsRisu)ڔt4U@IENDB`fltk-1.4.3/fluid/documentation/src/page_commandline.dox0000644000175000017500000001015415004135251023347 0ustar albrechtalbrecht/** \page page_commandline Command Line \tableofcontents FLUID can be used in interactive and in command line mode. If launched with `-c`, followed by a project filename, FLUID will convert the project file into C++ source files without ever opening a window (or opening an X11 server connection under Linux/X11). This makes FLUID a great command line tool for build processes with complex project files that reference external resources. For example, an image referenced by a `.fl` file can be modified and recompiled into the application binary without the need to reload it in an interactive FLUID session. \section commandline_options Command Line Options To launch FLUID in interactive mode from the command line, you can give it an optional name of a project file. If no name is given, it will launch with an empty project, or with the last open project, if so selected in the application setting dialog. The ampersand `&` is optional on Linux machines and lets FLUID run in its own new process, giving the shell back to the caller. ``` fluid filename.fl & ``` If the file does not exist you will get an error pop-up, but if you dismiss it you will be editing a blank file of that name. FLUID understands all of the standard FLTK switches before the filename: ``` -display host:n.n -geometry WxH+X+Y -title windowtitle -name classname -iconic -fg color -bg color -bg2 color -scheme schemename ``` \section commandline_passive Compile Tool Options FLUID can also be called as a command-line only tool to create the `.cxx` and `.h` file from a `.fl` file directly. To do this type: ``` fluid -c filename.fl ``` This is the same as the menu __File > Write Code...__ . It will read the `filename.fl` file and write `filename.cxx` and `filename.h`. Any leading directory on `filename.fl` will be stripped, so they are always written to the current directory. If there are any errors reading or writing the files, FLUID will print the error and exit with a non-zero code. You can use the following lines in a Makefile to automate the creation of the source and header files: ``` my_panels.h my_panels.cxx: my_panels.fl fluid -c my_panels.fl ``` Most versions of "make" support rules that cause `.fl` files to be compiled: ``` .SUFFIXES: .fl .cxx .h .fl.h .fl.cxx: fluid -c $< ``` Check `README.CMake.txt` for examples on how to integrate FLUID into the `CMake` build process. If you use \code fluid -cs filename.fl \endcode FLUID will also write the "strings" for internationalization into the file 'filename.txt', 'filename.po', or 'filename.msg', depending on the chosen type of i18n (menu: 'File/Write Strings...'). Finally there is another option which is useful for program developers who have many `.fl` files and want to upgrade them to the current FLUID version. FLUID will read the `filename.fl` file, save it, and exit immediately. This writes the file with current syntax and options and the current FLTK version in the header of the file. Use ``` fluid -u filename.fl ``` to 'upgrade' `filename.fl` . You may combine this with `-c` or `-cs`. \note All these commands overwrite existing files w/o warning. You should particularly take care when running `fluid -u` since this overwrites the original `.fl` project file. \section commandline_windows Windows Specifics FLTK uses Linux-style forward slashes to separate path segments in file names. When running on Windows, FLUID will understand Microsoft drive names and backward slashes as path separators and convert them internally into forward slashes. Under Windows, binaries can only be defined either as command line tools, or as interactive apps. FLTK generates two almost identical binaries under Windows. `fluid.exe` is meant to be used in interactive mode, and `fluid-cmd.exe` is generated for the command line. Both tools do exactly the same thing, except `fluid-cmd.exe` can use stdio to output error messages. */ fltk-1.4.3/fluid/documentation/src/cubeview.png0000644000175000017500000001060215004135251021666 0ustar albrechtalbrechtPNG  IHDRm PLTE]1yJ1u)uab洶1yJA qab{je޽bZ9} mLsjmj޽ vpAgOIDATx݋cVl+])ݺ 6kxn$mtXs98쩪|ײ; 6\=\hVYŢ\ޜ+.dF?#w3)sk}~zLזkx4쁻ヶKnL&R<ϿϮ]~֜=U٪b[^r럺;wݭwr +u76{Ph3iF~)lNrٿ}۪.f\l͑{?g}wz;-_??ɭe(_ e}v].ogYY67/'!0]^;ïヶKnuvv=,>.ϊ?}*{ϲfl=y%Wr]w~߿t$+έ|o?t-.y|=W%ρgU|ɯ?p~-_>z4tn#wt\s=}㾑>(MnJabm^~d7&ۅQaJnuRٻ,7‚%?>hdVfrm坬Hp>0x5-5}_i,~џQ:FTķ?/"V'Euj{rzYɪUF17֎w 63X;5VjXV+Vy:Zw`kVO*09Jl!XcnySRVjwXJ_)16zdjovș۱*j2/V03IXJKs=ʯ^U9;L0go2llkhW `+kǻfLV˶:V.ӟJxVv+; ~ޘq8JE1XVv+;N`e'X Vv+;N`e'X Vv+;N`e'X Vv+;N`e'X Vv+;N`e'X Vv+;N`e'X Vv+;N`e'Z9uU#տuVT+raD.,5Ȭ2*UV4YTjRdUPJVIE5"JUEF*%V5tXyTjRaSJ8䭶`H%nMF*iKTV$*^#ѫTV{(z坡~**Iķ߫6VmTU+UlV*^׉ݫvVT"U\TX{Յ**V'*Acp^uhՍJWB;RųH%ګ:zRŲr]±zYEUgXXݥDzՇ*UiU ^TU?V${W=zRcʳѫTXĬ5USʷ*^TO1/PZ U}W8QIYmW̽Fň5JWƫTlVC߫T\VF߫TLVézuZWTVTϳbhJ<@+NaXTZKmVTC©z:WTBzY77U+ *kNj@ӊjAϊjtrQXuEFy^uNJ#NJL*W^{*Uw,B^-.*UW+J^y@Hъ*W3[uŠI͊*WwXEEL5^E`EMҫ7u{݊*WxSZSy~Ն͊+,^#+V,T!"+}V.9N(0 s"ftte{yw Th\hy<WqERljHaZb 8S8]lcY3Pyz!7jC( !˛̃8 bkh#XHA'oÚN0EV\3J|Xª%Vp)VO&<=(%K G ,3#!fC W:MPX8fX/>Cb*̯INS:VcEYIS 6/$FB C~N\fLQ+rF,oq,_ 3 bH>P*s̄!~Ac=|aBB烨 V>r)?7DʛB_')3D8lNX<|,@k: {A&{34"I#8Pz_Ydz e#rS@8ȅ(᰷D2xʅ*aB&BH<Ն,A@b(1h㾸7: sh O G.IbOQ]P?Xs[BM7<P= 0q? ,EҬ ~x ;#% j6"ǚ>opY?d-Av ;5bm1)^]Odk[,#'+dccy_ XEł̬:~t0 "}}7?9188x;vp7}ӡ &D\(pjp#`|; (D}\b0@)(jl[N (8΂K  ^~|FP#0_$@bd$ DGʑzd RGSP K%UEDeI*oT%՟B-.POSP?TT٪<9WU_,ԘjՊ*]VS'[9+՛;4hNQy5vi\$iZji4K4j|Lhf4KOF;C"jYiʵhkkkjj'jOӮ>ݥXuruйiE#F\^w._Lw Ozt z zq}[=;l䁑w P[X[  C E Oe2:nkL352>aMgsk~PvϦV Ŧ{MQffZ͍ǚ45cA`XdY8g2ree۪Ȫ5zuu &f[6˶jn'`10spTN{{}}CbG^>on:i:9;5;vu:W:_wqityjwzˍ6m[Www{{GGG'CX8I y󣗻WswymcS._of.??_#3vgLf6s7ec8p{kd X>Aipfpmp[Ȍ塝lC6]>Qm8y,:6lʱ"-" Q 2~U#1ĘʘN3c&{4nu$%Q-15&}R`Ҋqw)Y?YܘBJILٞ20>hݩn7'XM6DMRęt0+ 'SHgWsY5<*^/߇,'cEFOO,>K^*;4{S9I{򚄚ad&wD)^SVO# |ZaoaeᇩSNӘ&6vϊ~hi2ṡFfnc6dNܐ;QرxEIK K<%RRqi  ,Z[bcyEuuK2/u_qqp~wXQʱ+WWzz PHtX۸|ݲu_gQPʠjQ W7od|ӧ͂ͷlJZm~cV]{;;vleki-Z+ݝʞ=uu[-I=ߟ-Y:L;\VOojjLnh kjin>|Ȏ&G+i[zr'E'Nez2qƴ ?slN9ׅ /շ=.7^1U^;{}ҍ7nLŻs;;w>ߝ{pco{ױ=œ'_KRV<3~Vs7ϻ_^|+SϪ/W[WW{ۖ}~_AΏ>%}zyҗ_m6 vo0opPsdhFw@Mg 3 gDYqNm/ @4xO ס\)-Dx5=/"?s-| eXIfMM*JR(iZHH02210100| pHYs  xiTXtXML:com.adobe.xmp 72 2 72 1 370 1 0 0221 1 2 3 0 0100 332 :@IDATx Eq8gv]cAdDAWH E@  E T4/@#(DE+3cȪ488ll᯲h:2%`:)4JV\#()kW%)$WIR&u p\L\FD rn$SxWn[K`a{ؒ%K6x^33["n\WV)y$fUzeAYCʤR tMW^y%4Twz5웞'm֫V`믿?__oZr/~s=}#HA"8{XUVY%Wʻ{rVpBD*_JFMogjJvȦԈo(JeLYxS"uLwfU1&LVDj|Hxm=$X}Om[l[>gC7pCNMUAog1秶2u]|3of@y-`'|^U]da^L # ~'DI\aa8) Y\t w+© jHmue͐) ("TDDEՂgsfSa7Zy'`lxGa賟,>YC*1m} _~+I]SC2'sqN<Ľ[ԔE@ e6O'b D?Wo⃃Id01͌HDL<+E% ViŪ+5CC-́ުn$e˖ ܉$P eO| re yU 5.rFҥK?!Dtg lk]vY|9O?i7r-v} "W\qD~ 9MPiyJ$|5Ϫ!UU$yB#+0svEұWAYp$=яΥhW5y_}{/}K>/~_:C=dD袋/} N _ן砆§?i0lg򗿌|q;3w8 AE'U9`R}3V9+3˅q0Ci"xJӀtC؂ A$1} <{w/zы4O?SjWG?#dG_Dc=փAS}go{۔B }be.k=TW2Ϛۄ̃vFnVWS%iδ?O4ڂMFIS@D Ox:/πc} :">P;0boDWW,EKUg}ꩧ}Ӟ 7^G?2!jwDpfY"_xSa2V+A2H۶t Na$kN˵p!$l(#!TWCARFS0*cG*&h^A&\.G9u{ݮ/~ \(J6w7rE8>DFh _C% jEUm+܍6̐8-ZDɐ&h.og 4'HJ4p9 9iRR`&ԓd JdQn, Kb$=0ɮWR6*T&,?d2UUTdUI28m9MVeSRy M.RȂSa*n>I gR+^ 5 rַJM_Ri+MGұ[M*׈u1R.F_7]z vi*#; bm6t9xmdY4هESRm9@6I5I ) Hk=ĭ ˯Tԧ>_ !}ŋXC30 1ȡ.NFL'pbG8 6't=YRbZ8C9!Iqoy[LO.L[H/0o2%f]tY%ya5M p6<FN֣U*H3OY,9"gYF(8xU/[yPV"*\VVtrvЉŚ+IJ.zJ# R*OIt4TD+>AǞW1 "H>sdNtp GerhYE3gF NzOuBO!#d UXl{Yeض⁸:qV#mm~qAtUv@vWys!(5=m DIJtxfe˖نg ;`>G&SS vY"cDžr.u ֣Fs}.:"ԬZ>hm8ӈ)f=TY5-o}z*9Aᥞo";3cndQGem(˘VB@ %?2lxJ6VgCE-5{ěl^[r4ŋ2DS#MD;% \\ C6?._qo E7>VEo NGcaG\ g|{sb%cs S;3#R:r ͱ|+^ 4' b .dN I-æ/SB}_lF>129]ÅDŨ-ꥷ}ݡe0Ha"n~3i^{X>5#BJ!fE]:g+X6/" 5'zPA.PUf>$WI7D(xLjDAؐ8L:I]9'В%Klgmr N!kMDDRr D$d*8s;MS CU Tt3#beոs2f^AD}{FiDdxM$N餼`?bZlۃP 6 koi")+p CAۖc4N]JxǧiWѴ9fCگ}k$=H6Tv_n AĤf hlLā0irz/ZvT,9$koOO[AC^7ƞ,JG 23$iΌS6U@8Zf5A!'Uӂ9+mUӭ))/USNpƓI! ?iy+i7;@Mo8ft1#b4f S_ b+K^?{$oYFu|S26-bUe5H&tkڃ7L I*,R|?H5Т6MZLq܃Ү8P&"Ƥ^10U+>m2 PZіr}zMru.Z 2&(uj9AkS_K5AtC"IU7hX$EveJރ &MQyMS*C3v" BpxD ֊y睷{J YFB?W9+M+ PڄfMjT"R),}I(:Kn HrMηTX HZyMx=`B%uJ6G6[9pBT-!k U똦 "xu 'ZTIçEI !P$$Yʼn+].!VvRe  B2_UDQ/ܪ+PEDѭc۵UUa1'*lt),'=NS IDS[E2Rܦ" 4+ΉjJĕYkS9t'^+MťV6Aߪ&vE3@uED)AW8KcB!$)N)Yb= 򮳑rN}1OJihN<?٨eF?ڵ |B13E` ^Iߕ[ c""vK#HBK\ +D*f^ɛD\!A>q !`"8UDܭ٠ xƀ7My@9;m—:: !g e6l326ke}C7>Z&G&ZR7aGXm1'+֍a;t֛@8K}2pZM˒ńOR(st|(",6Ysû4q 9Z?b@Ȑ$YB:M ZT U]F#㌡^q2SjLDjDtLX *Y'"*ÂvLMt] }]=}6tvuTB}*ML%N%V#^Z#zޞ}q(:ё`uִ. $HOT4Ui L0{d8|p.T T<+ sk|pK{FFff^ 2^@=Ԫ)smJ=` [Ȅ!Luu[0 oΜԢH?J #yln @E=[!~`鼿w|t+;G::IۻԃX^>x}i Tꉬ=D:j:CΤsk] Q`'=67olj" Tee%dp;,Z6 S.!۳u-S5q{m[M0u婞4*T!'ѯ`4Fj\]ptG98Pͷ;.4SBRgse2q\لR7g/@S4Lp n=6:=>ڱ|g=qӲyË+ZO_<&ʯ8>P3Toi}kvhC*6X94ٵrlsv j]=i+ rjپEL\H.)4-:{UM9 eTESiV6c11sAW\(lݗEmE?42Xe+!q VwV SΉE G+df}Hw1^w T+גbwU`: Ԉwk xK{RxY` Fv7ŰdÍV[0T >601\W*4X diV  \b_ۊ{m{4&+$J&B sWR觕0ęNvCR1(&ɁqYWOX^3L3_4LQk|0 a^ ?X)Ύn::2/oaU&Y _&OԪ,VMR$;9652=:=>5AVQR#:n[#GNÚb, U@!rcXߔ BGJ>2vfi UYHW:z6M:wv-~A͛ V I[yߊX9[hW_KsctΓ]r1x,e){wT3˜R]0]HF\ ޞ$fnvm~]W+z-X '[V1fWxeaR`b¦F@8r1f2O΅YL"o^! 'Z&J,|@1+KäR=h#vuc|Mz~ѹ=ÅY !UIJ5o3z$g+Q< VO>nlgĘ{J`DŽ7e6/>^{ikFƵq憇Vr_g>j|N~^+Q^HI%pJ$ )!%mNB1y+XJ;Í\-pP_2=O&Z=[A+>W)<,t{3,03 T]a1oҥKYLZe[oN[=Q\qŕ>z=dFsq=e?ѥj D~3Q>b(B(ML[o\ds<[=45\aacONlm:/BN6燭: ]ݽ1\)6b_%=}&:@SPky0ׯ}R*M{Q{qy Mvۯu饗XMbiXx HInZ_6<=[n};WM1+d|WP.\ķ}So 阚|3+>] i_ׄD/俉`-K?1K v4>ޑ%i0͸ W]TI-m)ת1JP{ߘuۨA` :5Ub":>E^D tS;c/«nCq@y]%`i)1b1t*zp *j4]䥾\br@_OMVBJM[ѿ./kf+=nQ3֛0t=f1u~ء0;՜ C~;uo$;wt޹ %m{5a37y}\͟׏?̤EX/UcD ßh/%)RJZWBTM'U-9.۵ P"d{z{bA#(QN,4xLʪI!#F$~QGmߞq../1QnD8p ]w1Ǽ˕^& js $(ʓVPӆqapG]H%Iw9\/K(phjPYTAn}pKmcToǪ:1h Pwhefg&!˸w:䵯;k^Vv B- p,rpxd?o}W_?#wetŋ7bm[x%h.~9cݰ忽C#XFu6#ʬOe0*.D46T@isiei?F}ZlEOԞ(F{) z[紉rX4ӎ[cȰkwO-p׿+W>OyS~rO? /\p֋CV zwmWY s1f;}9Hm)"}`c$zdqs1ÐP8a%na%+9\#vU%dä#T( fI,.۳`c~|&eۇ?$/&z@c[x!vv:`f=qcճ6` x Vqߠ,ҥTIvN-j+L[އ- KC(1 -և=[zbVe ,*('эIH i$=}4,)EK";]q= X1#21ia o 9Lx¢Us6D6foMaۍ_xHXbH C\L2{qD7M~\TxDŸwjV\"l`>ہI"Jʦ^/M)ZMNlpcqϴCd/qk]cFsS_jߪ"6k W-.Z'đ8Of.pICK[iBi,ƌj4̘.۞Sǖ收"kAtZ1'p%M Nm:$؆HN͉cr72/ ,t6]|*'|-m2ה K˿%.>)يV2>4՛ċkc#n_qѢmMM"r~H@o*yqkQ]r|c}NY6'ZQOb2#EuU,sq~}f [ӊڳ1d3Q7m~]eE6rFtI7SeCX-\Fq! ,̇:\!W[Pyw$=1P+Qnzڞv*mx;ݤgf;KA*B%$7?k'[\_bk*):n+zVrNcX]է{*`*7#q)l$B~OscI57KIGT\\zɤcЊZ^_?A[{ rZĝЯNCAOү4e ۦ5Õ:]ݲ\WI7WIiո=)H%ct8vB//3iV3W 4b0Sh+ŀ<$ U!.lT? / ttR, LF~:&o0谵$]>a7{X+ftf9NϩT$]ÜQ)ڲpmq rN!-9?JiaĊ oVT693{k0@bCnm BTX,>e˖]yk}_%V_Y-bvl&]X0Pe ədӽ}qpP*hYQUKх4* ⺪4Xp>!Q"83FtmJ1l^(VH{yrDK8 ]*6N;CN S<ҒQjqІ=<\V HUO Xp5uMcJLD OŸ6$%3P> !o۶BO L~8vEʓZmpXnDasG49AXʤ%1$@ndwfnR@d@k5_YޅRnH49B]3.m[E^@E T4~[``Ĝph~dɒ>͎ LߋnmđM vaUzŷ@X s9蠃,aߥw̼8!9^ Yב@:i ~%X^ Z?IdTlП\L[дc(U?S8:J:Cp*놶SPx,}dG=p0 +g^xS\ W UğOϥɲKӚPimUfA!B&4 -m*!B߹p-ԸK0d2l9_U<p3c +cdSk~\w!||-N]0o q90Hٽ$ޥ˚' ʪLiEg,m%nTF_BDL)\;engm[x#_&Ul0^@7e'1^{[i ԕ&D'ǁ2Bf7nqmSNHFl9^eo|7rWE]d zS"?mda.viWv_8O ԕr f"CCwReV. &2brJgP`*܆~A' ,7x $S.s%cwݾkʤsQ+y ͓N:Qϼt)#Ї>|D+=ksi̵#Rc>C:bgDD[ B2WZkVCBΌP].〖 ]R 7J[/zm@ӳ8$}hR$Mc۰ѱ͏ !nFЍ]8&µ(h:* J\DM;v96+mH۶kD`z0ۖ!I ۤ-Qez \4a,h$|qgHJM|R)*&M5i/}+Lr2PsrKQ98>w4TJ1Z+QLtzK/~K{7~Zȏ=;T:3%HH0[1dgF)sΛ=%'döX\[Qb9^ 0A@ Js7Epbq M+X0e=x[Ҟ@9l5JDmۇ=LKg.f㘖 E1;-j%/]T8ˤQpEqaReKHݳl"nsh?KQ,攬uTc1!~c*ܠ%yv2jjgbsfN=TcŶlY7?68l*\^!-bﭼX/%ƶ [\W½"VU RU=f]3KLq"E 'NUn!09]^AD}6G@Ē#-og2 ճTo@C`ĉH'0&Mh&D\̴ϖR_vŴX\X`_6?`KL4ffmbDVz"H&u=+b+4 Iva;6YT]#!F7bb`XF#YDP5Yf;ߤNb+x=ŵ+ՖN,8/ ^l,y?h>h12w\,[ g:lsc9j%K,@WyzZ=%߱z,L̋,EJ H)4~t)']ť kձU㞕 r ck{艬lUfidVfي1{ Uʜ1Rc#;-(K쭍q@x!w^ @ti$k_O32>'$MG @% E΋K^ysVvC}۳bpee.v* 5\# ɅvVLDO_ m,-Z=w*YE5V CSM5(%|FɘS2=Z(C[-z$G&NQllIg+ᩒous(ZD{7pU?yѷz,Ϊ %ͳvl8` 2]@dk-rpENaaij]M- AVBj>" 4 ՇFǬ [-uRxQUoU+fwsRx4:0?>XEXDK*6P8`0bŠoM]I"x{ Z՚"؄/ 9"I=[SÒۢuX}͵m׾[O}l/"!hCkXN3~) J8@B\e˖b@VHҀLm>xȞ+Q8̇1d'p c@FٹE@M ER8)eI[}'NªC +?W"⚒Lg+jԕ9‘,(ɉW_{^VS9eƐa켝a{ol~ U `O1y_I1 zIDAT (@P864mC]RUb'?sꕯ|BY ߤPNK"~ig&l<44xqǾo?0yꩧvFG kƿs?n~(;/{rmokn_"={Nc`S{/{~񋫏>Wz;{U[=7Q\NoB|=!E|3|{rC8fw_F2"1>]#MA$y _RSɌKj{#lFR,7UOﻇ R Q6xδEi+^l6 bk&!:vx6\ǃ{bF BH2PA^Pt`ze-!r-)KCP^uiʨ\/7| BPz K;5a!Z㰡brfj״@Hƒب@SJ 1Nx:y漞Q7O^}OBs#+)@ 76Er+"Ӭ݆z?wan JnjFf]!.W$WqP똠=/ޚUxqvfG *"H ,kaOr$S-,"r!(r-[fc-Fd7@<4dk7k^cU_7w_xc\-mPE>cy\u!g,YB.g~ư<qJ/B\!i֍R:WhO-eԜ\gmtJv|?/_~;fZϼ6GvfN=>SӐ"]DWpSC{VnmglЪD흝7t'nםH*oy;Sdy`h=qoۭXQs!a,ɻ5 `۶$zx6WjJO4[\+eg}M6cÌ?5(FhӺư߻|`kkc1O| 5tGQ lA{~%* v6OxԽ|c`i@9(B5jʻb! /Ï+kH~=DxJ{Y\ڨ3‘$iN{~E1x$YNn}Rh/feQ*^1WB9s3Ϥ̗t'QarۘvwYhV{:sr4K&ݢY" I0TAΖ,1V#d6YZ2ҖbJ̠W˲É0)!4aE*RꙆV  3Ϥgw!iKNb;F)Vp "1H-==`QB; ITP?絥ӍY."'3\5ܸ5y{ME&ѧn?iSOKYԛJAy-1+;HJ=F 젨/:-(_[ CW+}F*.  Gl"2HK[_I,C Hl>\%h3KhU*|qzTq lZs`ES:PgTxdt~%QjR> dg)V$"ш-1JCv?Rg$+g`n熟O6bŇgSwHBq+T/3ЇүTfv3a}:(Awi=ŀgoi+ aۇVA\B\% cmeQQ|PV,r,E4=lǶbIJ~P=Eb17|yyVI[{LyȝׁVRtN%KAs1]SHN8>3rz2J`(IQ$9.`53ΙǾL;ߴ*z7!#O%Ιk)}׼ 6̕f'._!tl O\ޤR񃇊>s -mEUD[ĞEl;2N4!Bf!/qӞ(`"9uj傓'!$~&\NnN5IMC`+.hBSHI".4:8 G{I5SYTUAh+HZFq\@WˈѴѤ5,5'2y\ i7Ȯ3BdQ%wJ@ĖzG"qN-m|]Qޑp8tW'`2[o }G7]KM3/?|Kqߚ19' QN}|[4'GqYg|SNTq;0_/| &,}dw;E?>z8>NKvhV+Car^{EGuTg:y}G?_='Ԭ?-)xdd]udh4*ȪqB>D !̤La2LW=[bo .MF+aĭFtAФwJDHP==9eqKx(D/ 5,wΗ-[~!8<5:nu6ͯ\VYo1SkE\H AslDe/վ8_;I߆045aOT"B<%1&#}hٜ>f ̘YOT~=`%#z:'}Nb B';fX{챇) /ɨ iap}9 9\K3d$ZN{g"@z|\ʊO|"SY[ 90UD2Pg m!ɠhbNG1[FS`c x~\}BRJ>hG!4`+IʫM4$NA &)0 !HiQFӸeLY%MFh8 q`IZWVsQIdjB\敶(^.ڢNEy^);THVus(}% 4WlHJI ^|7F)wIENDB`fltk-1.4.3/fluid/documentation/src/main_titlebar.png0000644000175000017500000003515015004135251022674 0ustar albrechtalbrechtPNG  IHDR]*؈z iCCPiccHTS" %&H %@A:IPb kAEˊ((bC,^YDu`C]vysΜgϙ @g d T SGؤ *Ѐva ڿˇ [C 8Kc$fb| >L&!1S5qp' 3?XL)4S`yh~KE)3xefaK,FP~N_-g2@䑽 O%KfFh sLib}!(Y45l%aNea/aEڌ, +(Q,eed9;Xh?UWKIQJ )ebiX3_ _Vܻ`;3+NٛH?)|dxqFҟ\p7L2B !2@r@H@ bxY\`s[&fB lG{G';;r$ޱ"º2[Q y|ppĘ/Djr&zlyΈo:L0KGp0xBHLyA:ev>8GNYW܁G BBA 3qD8⏄"H< R$Y@b ىT"Y2҆<@:^-š4Dr4 s<4]=^EK8 gqp<\. q% \5ׂ} <oB\bj|~ ߉' z;O# %=ZB7Hd- b<1XCl"$IdC$$tttMDV!\BO>MI!P)fwJEDɥ4RS)T ՓEM.Rw****n*T$*KUJU\RTLӤYxl^ZN7 z% *CN*R]ZZzSEL6K-ODuWusu@}zq{ 0L5.k<$ikk45wib& CX͸fL>3YbB;_t:::uuuuݮ{Axx㏌YE-ۥwM_@?P_E+AF C/CF3/Zl.;]>33 26ij4`lamܸ ՄclѤ٤tB*Ӈf3Yf+͟[h[-,,-ޖs-+,o[8VV۬nX֩mP6 n*&ܳrmsll;Xvv^O40qĖ3w?rtvXQXxۉĩ$II'wf8Oq^ERj \r#-q;]~O[t'[LO=SӳËWgO׊=}k+s-5 Z5T:.l " `ECh!!e!OCC塍S)S6Lij6U:> a[ ?18-|Zg #Z"#G~Z(2:;9F-fFLeX؎qKH 1 {O4{wgZ̜?,YNV-}4? LP!O'mM򄛅/E>^Xܓ\<3eCJowjI+ OR&y#czX،Lrfbq4]z~sd6Y\C{Y &6]˶!3+<ӼyGk̗οk*'/  .[عhbdq%&Kt/ \ouY_//^~E|]?PUZ /c?J~l]j˪+EE%E_W W_ҟ$i]v::麻+(+0eCF7tdRɎٛ;JCKnYkYjٝrz[WmMv;w;wUW"lw_8TS^ގ}WVVۿ ʮ=0~mwְjC/'{$HQcfǶ2j 됺ܺǛ=kO؝{d)SkOSOw˦t388v3V!<"\r#Zˑ'xaE:%(@Zܓ~=Ww#*'0;֧Km?Sf6uI"ď=wj?ͨwoo^j1"ڊǺҩtm^3Yeg\Zâ .]:}ŊӦM3fm&9{9|pc!8Sr͋LM8F:0xazWd-=l0𤬰)o9&+7UݬRjJMWH*t=V&w*5u.Qz&;kQ'T>suRu@F$Yf,)U a]g2W#e'y9Νkp`:`M7NNcӬ4}Jp4 ;.[ungf6KA#]Q(Hg0B{'mV[$F7ZhY|a'ke]$Z5۸lZ +6p5K Е&?pV=lers)$3w6S4LɆZ1N6lXJUD*ƒ>iIK'UPbf=5+"l? Vc =! S~j}5RikߢD`:|֟Tk>WpҪs2yIˎ,2nO-r6lFRwZV˕(cʗ+`D¨-_MmlJQG" 'QadrĺcmZjLԐ\'êF =N,ov 7ؒ{8;9w6Ye_XcAS jےE7EJO\Oom6oͦmn5i#)f^quM@FnC5ٖ._ ;kLe]mM @\żZ,zCFqhJgV]pT]zw8i#PX[` xO9;b-ȟP[vN闌=y@.]jmM6c=E0.~۟gG>K~(>v衇:%\bm͚5G:/Kn3"eξpB_;$]iET#Bw%I'\Cx5JA@ү}n6o`\iWYϢ:͙ۚm &_|ٖbmpF!뫬4[rBS]bK:|Z[&WyzXFRFokve{{v]"mb3*ӭ5k[9YĿp^ח%'/=i~'Wode+D7 |vMJs-0-[f첋=Ě N1D.NH]w2UP1w$E[oe~ap{P?}kkiu|ELɺΐ~p:[ x\v-Ypmڛ-Ngpp c$j[[zf 9lnΆWf3nXs  4yiVqeUVYe$Hڽ^Yշ]n/*srx  %Ɣ~{o6d/ʮ2uZח |BtK}u;'l^{~eh;]!22;Ꝛo+l/}wx^*wG'd}18"o{wqKwyg`ozӛl:~__&8[SOu!bo{P8IG8#=sZ3#o--%0<1¤aJc#,zЃZeP7G? T]jM怸򁰏?xpG(Q,(7xK^:#=.@Ab@SN_0y<(kh#y t7ԪW&8mR\a} Vl z%YiI/__1ʪ JzXff6 !Mbm6a5Ej@zuG\!4rWZiվ,ju%1>w .J .&yuϋɴrr-?Y"Y==.F RgUgP'Ui{kHo >1{+^Lv{>ast>l~^xguyYg9e3 7IӟӁ0PH0+V9s80! @r#}s>g?s9F>Q g&]x+0po@?5 Pe=2]RH<h_rף(yʑtr-n"Q ?O j+M1bYDB^#ڇdÉnrL2~1nmadd8RgHXX23^fA\Q%Xdb9.ٝ4S3ye;9R|hUW|OjfŲr=.ݼ `s+>KN< t@wy8SJ 3]sAI#3"z&HH@!&`)0~{>P7lrːҹ.b~@6(;{:qs'O q@SVl4 LƮnrD27]so-K|`=wrnJXzԨJ͝1f50kt{^ĬΙǴ)N98+9E  }l ;=CS;+M5fO&g#>M+Py<P4,OzL -vhh0s׿Up[Wʽ*?™g,(6`t x4e ZqR~.TzB4yp3G!nr90dn0;!cfK}5ߪ 7%^*>oUgJ>vANu,`Cw2o93mfmP-aFhj=m`f6&=|FfzIxͦ iۇ!p1̣0?T3 Ta{ihb[d2V6ص,F/ @$Labh6-aVˤ6׼5>{;q@S &aJi17/D.@ L-a ˝9 i ƞ ).i1I0_w=tFyҋ-oy o0)2&-\|V]ɕy!M#bwCƝ֘jm 9 >FL0=Ga?e Fh#b;0 ?YrΤc"c%w?Uw&h_ |;W) VX^׻@&L^/v^]جY% `SN\1En-USe:\rY>+y#A(f#1ڥ|V^{I@qm>b ٜw=8A['f:}bM*1+?-570[o?[mY5+m!޽u럷mff#CWrzɚjņ!dy:c)}dRo a+9ݪ Us,/V`XytwY^Y+9ņrɯƃS+[] &@]ajG43 abuV<ڇxuh82gŽ?`GZ;~@I6Շ*}\k 2 JxM2&{0)'(GFe&Ĩ[t0IY"av}o%>▲ßlQ@YG;Nlfc:0L:RjK{.^[1~{؜=6G#lkłVT/XnVC*Ջ;wf͑Ƥ\׶x6{]3%@Vm|s?~rlv.b[z[t7Ysn;nfm& ¨4xf]Vya2AP'A*H kuwb/ Z',;&qg壂DY2p**}p%]d@'j vڸw-S+o,^c]-KTyˆQ‹f $_@F6ՇSDm7{k}֨xXuީh(C [Zp{ 3B5 fo/Śf7.kga} f'ۗ6u~_zfn~B$ϭ&x Zb{YŪY7)zau;n6Ry]jmjJUQcNoudu0 pM,` (fOS!Ef\YIDATQ^PxoKl{Sq0h`1UބUq6UX}z}o08 &70zD IJ¯Si@WHa> 7/z{/r:F<=-;-,ec5j֗nCՏ~L$F7mg[tY 6O#j"D /U|A8 "Dvt(Nu\(:vdIb-f;|{<()UqW~VM+LOAx9dCi6f5GerQ| Gq $N`pU ȧLnWe. 3z)vft)ٰ:]21wgnV:%b" :{T{ I, 3pn=+f%=bV}>6ɔ7vAwo@fnvcZhp*aY,w"?-' ;_ʼ`&V^YÌPs9!:zdbm8*3>l/24ױXdT TcqH;<,nT~#94Ge42lσcI,XK.%M8Ɇ(4:iLƑlh`(׉VGO!~~:vmL#+Xe4N|-S*5/SVcg>2}QpUpQsuG7 uN'iw3ѻu.q@LIj2KFiMAW0jG6Q4{[cunAS:ɺSumƓm9uW'/7t&Dտ֪״dJdJdrƗ0l'|tk+y7LɖN'딶NLJ_[7__Ԯ;ſmf<\D~ZOk|7lw `,L,*SOƕSx:`=:N:餜DʻScVNɔt+)_DZ2&Kմ킻u2m:;3JX֦rRLN2Q(NOnxuI&RcyũGgBi,.}t1*%~T BKi3ݵǍWTnKT?S2rVV{]į>{KwGg*ÉDSۉZlyMnMoA}"x梽p+ؗxaiʔ>6y@.U/j'‚nX((5ة؆ة^w@NkoӰ:ሑP:C SAas^tE~ .'a~~:"^L%)'BHfQ\RhSt* ҢxL(*=SY6% LH|$D'68r0qGT2Gi7E>%9HFN$ ;*tKq3!rG&Mp2R=.ʔrΚF9*#"jSbܺ{YFƄ(`W9U0JU>ƙYhOщq8⟿FMMCwbsޑ.wz^ Cgqt/SS$#ŭӐ{E9 IKL'&9u:C"uXz41Nbr0d;uDؒmGio>27"0`gq׏ڡDQsiGG;5R"mjbDQCm\s)q)hHSRPjOÔ;ryL!PsԾ5@ Ѣf?SCX"Cy<'-NaU{R:Z!hyΟ&$SS#0Tg[qw B8 .v^ս ,fv.B=([|z zpnaRb05a2Z` qvCgMB"i0]L: 'FGҴ#L/[qc⋽.H#G1bX}N7WA,ūH)p2}4bF$,2)h|p6g2MIgYETq@aS4"4NNŦ8ia:ɡ,NzQGPNPZDGd7b40X2:G'Ҙw)Iԡ$\@Ҹ9rDxo@tsf ha;Nlf׽W8Ȧ+0hg4Qd 2sx%Xi6PGd[3lPpVL  Sʂ{+_i^x/P|# `Ee(Ӄi:?Aw9C<͜IRw(=q~$uE8]!i%@ Qyw+>kTo!J ~@ᆲE~UW];S[JA 4Ѿ# 6yI'Βp pZ8ĈFE)at9ɕ%4[GIYahHBKږ߀T Ct~:7 ;#&-39}s1~$8 "'?~`0& {bh bё^0l:'bC/ACİ3l5`3ļz5GxN%B'oL;0? F( v|i eHOUbp)w ^;_=~nZ ܀{>8Fw>hgbSexGLKf2N F{vLqD;_Vi~>`LjGӏ/m#Ek^'BG&;SZ:`IC740R0Z\X^ IJsw䋸# AH0J:K7 !.@)ưv*]N8W{ߌ.!#>`4U'#+ SYv&0EHGu+(K/Dq]wuME̟?륌PNLɔLɔ'aaEaB IENDB`fltk-1.4.3/fluid/documentation/src/widgetbin_action.png0000644000175000017500000070530015004135251023374 0ustar albrechtalbrechtPNG  IHDRK6 iCCPiccHTS" %&H %@A:IPb kAEˊ((bC,^YDu`C]vysΜgϙ @g d T SGؤ *Ѐva ڿˇ [C 8Kc$fb| >L&!1S5qp' 3?XL)4S`yh~KE)3xefaK,FP~N_-g2@䑽 O%KfFh sLib}!(Y45l%aNea/aEڌ, +(Q,eed9;Xh?UWKIQJ )ebiX3_ _Vܻ`;3+NٛH?)|dxqFҟ\p7L2B !2@r@H@ bxY\`s[&fB lG{G';;r$ޱ"º2[Q y|ppĘ/Djr&zlyΈo:L0KGp0xBHLyA:ev>8GNYW܁G BBA 3qD8⏄"H< R$Y@b ىT"Y2҆<@:^-š4Dr4 s<4]=^EK8 gqp<\. q% \5ׂ} <oB\bj|~ ߉' z;O# %=ZB7Hd- b<1XCl"$IdC$$tttMDV!\BO>MI!P)fwJEDɥ4RS)T ՓEM.Rw****n*T$*KUJU\RTLӤYxl^ZN7 z% *CN*R]ZZzSEL6K-ODuWusu@}zq{ 0L5.k<$ikk45wib& CX͸fL>3YbB;_t:::uuuuݮ{Axx㏌YE-ۥwM_@?P_E+AF C/CF3/Zl.;]>33 26ij4`lamܸ ՄclѤ٤tB*Ӈf3Yf+͟[h[-,,-ޖs-+,o[8VV۬nX֩mP6 n*&ܳrmsll;Xvv^O40qĖ3w?rtvXQXxۉĩ$II'wf8Oq^ERj \r#-q;]~O[t'[LO=SӳËWgO׊=}k+s-5 Z5T:.l " `ECh!!e!OCC塍S)S6Lij6U:> a[ ?18-|Zg #Z"#G~Z(2:;9F-fFLeX؎qKH 1 {O4{wgZ̜?,YNV-}4? LP!O'mM򄛅/E>^Xܓ\<3eCJowjI+ OR&y#czX،Lrfbq4]z~sd6Y\C{Y &6]˶!3+<ӼyGk̗οk*'/  .[عhbdq%&Kt/ \ouY_//^~E|]?PUZ /c?J~l]j˪+EE%E_W W_ҟ$i]v::麻+(+0eCF7tdRɎٛ;JCKnYkYjٝrz[WmMv;w;wUW"lw_8TS^ގ}WVVۿ ʮ=0~mwְjC/'{$HQcfǶ2j 됺ܺǛ=kO؝{d)SkOSO_bh= hz15&303c/2mɌDiv52\znOPZXZJbXV̙UjV\uч@oµХ{\Z h֬>*Yw`B3Ҧz_=}yX=$zv"H#'c"?inie.n5?{Sqz_crJVn,[n(?rن{ȢEZ m˗,>^Bͤf7m߻mmyVG~V Ʉ'׃2TpjQIj4 iҐØc9iBVO_#z4Zc)Khژmoֻ%PhñuYRsZX\jndg147:z[(KZf%AF-*=%g5$)5u\=RP 6 }u``݁V^z~ Wgs9i0бtm-Vkg 8 T JUа]'s'v B_<0gw'-^3t@Ħ]8䄈MnVh{IXf+%,aFx(Nݵ殠0 ;wZeG}lsd458oϨO\Ґz/OiS'\Fh[|~rG:/9ӅUɍzL|#s+ӝ7aɚ,Lo5d?0itBZd`Ǡdq&1P?$}`]&!*"T+cz7}<׃ndXigƅϏƴ\iΏƅs4g\08~$sSsLJyWs۪gd~q\9?gjǍ|X>y#Nsl珎Nz8N_;ڛK"0`wQfWH_K'o4?c^s]I$5KZ [huvM[N4\|TX0]ԨWRxm#OBl ޡZD]" k**Pwep]=p]m$\RZ$_ֺXh̦4 ,5)8o^ޘq.`&)zrA߳|X8?v9y.E\ )^ق t%+gMglNz5Y'j wU[.[4.DxU$"C*u5 ua;,p $ddDD(Dt%*E0:< Ɣk4F"Zh Q^IܥG\P!" x+?߷s<ڊ"%!Kηokdk)Z^QҸz|"h^Q?s1E)yDkcXZ} q̃ v:*:tO(7ՠ@{ cN6IO^iI֓[8(O>^CƃYEY$[-CFVu荛9<İ) |oy^k(N#'=T[_ߏøo>vEiOX1F-%hOCHgpɣ*PDA 1"~RB3BTӃ40Im6/E*ܥvi;s۶mQ;wAq!w@B靲b*,^yyĤyw,O=cbdߨYtϱ&Ӝ{$eZ7lal(w x۸q8+v9 FUjj)03t/IqkbO98o;lڴ)yY|q.;Ӛvy5'{ɟ~JU5j4d1:v@`Q?a13yXgȳ`bď{D6 wimˊ?5oXVe ^pMNpkcG ' jٱ٢SOA;JTqʌD5WyPۖ57֍Yud{,Qcn ޸ Sw6mkXx#_7sα/N?sd|(KCިYPZbŌ C"U1Rwf5 Ȑmk-]4*NBH("m$J(mݶ=*Rm=MhgomU$hϑ@x r'9+D%c-00k"cpw Xl_& [L ҸrPn[*C2'R o|]w ``aS*uFKss9D߉d룂5(gC#q1&huW$Ͳ0^<#A^oTshL tr!2>9d[ܡP1yٲeI\7a΅).>+q,%IRXfUN<77lXq﨣B,8=tbb %0n-5Zn)VLq(tb.ŢuIVUdwi~[}mdNnFټn*p5v _lC-e1 e aASAv6&Xw}F4Jmkle'ug+4^J)EA<׻{x}`6߻9䐸1o.o:/Ur걏=w{󞰶rve3 ◾d~Q{8 w}yԕq6+"z˹oMQpb!1TN<׿ȾկڻhH'F)kO~r3\wqW^~4Vqi/tfG~O*](L r9iht¸^DpAL,Ԓ8C_{442tgs?Ǹv͚5v衇F2yQ~O,>(S|nq!h eEs*^( dOv+ɏk/ G6ɋ#mXq@F.̯kwO qbóysEi-۷k;}wۤq_v>yF9Tb,!癌%}`l( G67#;$V\dl[*r]PXn+ Dwu{8wNjbP]os^k6oQAD` `*(Qawmo9=ۃ4HX%;%}=ݶ;o7 $Gm5!@UFPJvڝwא S _]wݕ*L}Mz:Ё |13bw R?NCb4uw0;;w {_;xZD^Sxq=, #yqM[ȯY^fa4>`Ox"wkxx=Q#<^G##r0P^}gg㽊)+AJq;FH% uXjVo_Hbqi(ݾ>cO,DX~E޲q:Jiu$L;s<q ײеMjd Ū&m[cەz2Wp tEk+/$GEpVA8Wiw*Ab[! "sncx(^O \}vFByUĝtuJ[|cچ{F|/ ^)%}\Qb!qBO^ 7^xiS#CvwŌmVP`z|-2G;##Q8^fiӪ+#bl8"t'F(7~~#ޜ|ɶ=(h7xc:;c7c m8ƭ#m}5O~|$1yL|G>e_/z鍯<9O|" gç?w;9郆);Uu/dp"Z: kjjU!IfXR_֒PzL׆I5M$:жonA.2sk:}{{Vj8j>?I1(AXw"  1`uV ăq_7 QCSMy9Iy$'"&UĻ4u4ׅw+f! k׌%̛>$n㦘.Sd .(6<#фg,[~`"(D(Bʽݛx6B/y׊#*-(\G̝֮ʤѻޠX.}]w9J+-\8{+%!堃 ϙ!P-*C]7$)*w|M9_qDR5(Q בu1? h"[q6\Y|CՑzpP+ "r)囿{X~D1Mg (q;{}nVYϓ깺ÿF!ЃZ%Q`!RPFыs˽0gkEyyeVZp=c<|':x 6Cux);rbG|]46l<ҝ<ٕ$Yۺu[oJ(̵=ʂBʖpֆo5Cމ/J@rCh ӇXgqM3t%m* HVeΧ |IkM}OPhiUΗֳ|YlaQB0~dX{ ^`/~㵿/YzV|w)6xQȃ8ʎyH=zB,Q 76`J֥*sw(-~FsUT.JRopݽ` #Rꅆ 7ހC$J(C>Vc%fwͶVSx\j1m?Khq`Ů9a7=rKU,f!F\`CK?I8x5}@ TPuы'1CPT;|+XuJ;le6RXלYVK`?)Q1y?"}hP5KG??{l˶~h`5shAhHNx6}2X2Tw3w~V B2O9/~JA@y)N%;#M N~gnUw# KoQ\i (AWAA7̃ 후'o`BR<#'}q=W\?<oEەEQxm+@oEYB$ F`Kyvw=LDQjw<(5\(mߺ3F!fÔFj0c$1}퐓Np͟qcޥZ!z{*VÍnwmj;T޾򕄪X*ĝ+ټGۆU쀹bBC@KA)my;̺z)CakQJb]x֠ cD,|@: [&rlj}8Q[J&Y"OpK.Zma= ·Odw]Yn۱#Wv씓O m8Ѿch)#o|#o$'{ /Юꪸד fǥ!pe{4XRBjKHPMqVTXB9m@A܈(݇ Z^2GA1"<,p ]P^bdwnn=+SNJQ@Ԩ$T=ozmܼvD~fTbmù Eg6{q~rj ؿ>cX kG]h2hm x6;Ё+g?ّ'x2*JquGާ>ӷm{k^gxm۾=27_)A w&;)΍[~˗ 1_H?tϲ(}czXt&}swo %\PrQR=xt>c['ku:Ё݃%\`)J`1I@e)M^ LyI' +Im<χ.%t|lh R"񑥘*([Q'ˑ7Y׼mK^! s{Ǒ,YRDOzeH*/kfA8|1Fk=|{Ӈ*c0&Ei\L+)cwhql }c\A}߷\-ٰ%EQ%(#]Th~[m ׏ 8%(J9ގ;fcQ]!|[wm{ywTg~y- X⦴Di"GX(欽X>YdX$ewCf=n-uv?aPKkcrz`6{$l=Q\J}o.YVŎBGs tg"ñR |avꇢr Ct`&>%Y!Vv@|`a#أ@dKцm(Zёs߷O? νIQb$%#[XB} >}z-HxS "q@J aHX(?9W$k{wxc_+bu5j.i==~Wb/]fGl;ફ[onyM̷S?|٬E dkEbϤ (9GFu/<֎ywu}JkT¹ƺfe؂Ï3Z A$ϱ%]-B$jA{ /EK^t`2 D^/ʥ DC\ S,Z|϶eKu l{|7<F3SY"o\% Щs2+;3F3|u0ؐw,iAJ0zy0$轇FxIJ[ " o]' ' 7*"U(4x[ .+Rx}4޲ns&sv_2ۘO}ԷVA^,΋1?x XvNp;xA<4b?9|{[lR HʢQFV{GfIռ\G4&|/"6nbހ/c7S.nPfꉇu}A˘MŠ,b\5 W*XpU%UԵft`,PĂd}#_HU~:oAXa(RMk׍ׅ^ GB(R|we+ߵ⃢j78{yOW&cQ:Ё!wE5~KYUHX :Ё}뷝꾱zΞjpވ۷م\`ozgVPr1(zMjcɇ\Zw Yc\$|'F(NQHEoSm.zr.X9C+0{ao uo Bﺓ_6n|vGQ@fT|G;G h'$e߁<С>c,/x|sHJfyʇr1w%oyŦ"aqXo$7E(&#o͜xGOKa|9K=QI_|4ܯZQFt'7ͱuk?W6.YʧrD=@ڭ( D^hj7U,nC:/T~L$i"e1-]˱Xƍ`I=4qzW|-K= x=%O(.ѣTHB Hax1?)q)W4ӷiNRC9S>XRWS:Ё(h$Q.$hNZ v'>lOz3Y%VBxS9KjzTm"ܴ;֊LvXn:@ 5Z7]b/zqjAYrA`c$-o4H%(xҜ%*ZZ=aH*P^4NUw빠.qȒw`@/u 던Z/ӈanjkVݫn&_fiݳV(irdzԁP>?ncAVהV9x@ko=RZ)K>\vS!>ʆ얛n T8W*ZQzyՓ" >k)zsIY\ObeRg %x| 44Xxbe֕TxFz&h!{:ԁW.^pBT 5Qn_jsj_}| v×?oK-[툇~Z(Yw^orI-owz13ܐ 'NL@XoA5~hmW* VqZ_1o'5ߔ8V0Le֗֍>oG?nќݡ?+o"y6Q|.nMޓO~O=:j<=>eWYjA9X_OS |^B17r9vfXڻ|Uָb!?z~ ϚmzLQ_\+XgJTI$)L5L%W^ajRt=x t牿jC^ə-/σ_Qɑ^^hyI焧YJ移l>$Y<+2_oY|hE[U۳!L S /+vVc3´cp_+ˀAh.j'/Pj^xU4?T8&\t_Omlt(Ni ]^`R81c"b(&R5%xs-G;# OxBsf d {p!z!ϡP"5?uJݗA~EG%4鼧_B׸A&;=M>dmv3C(sʶH Ƣ 5y 0PdwO.0(użzbF5 ~ob+8=(09뷡ً2;iϵ lʥ45j#пbR~ͰՀ7l(Ka4鵓O g=jNPxZO#˥/Ur/(g3NIwGƚ }Zj6vt2dKn%KE7B\>(IxD8yBʓPOyG}X6+س'%&J(͞$r ǂg-y\g ^gY+;vh Y›vsh``9ٹaV[ QVqo~ 1c*:Tf 3bVdEZh$M?)핦ࡕ"v8i3tzQB/|R8hʀ0޸cR[bDk뽂.?>G(}oOEWNjٛ5Jd(yvo~og+t7>dC*}C.ӎV-[UV[ =#ZTJWxYZKYD^V[Eg4~d-R{YJvyƟh{+u?>4h<}="Z Z'ZGhLv LDiTuX~ 'XySx5$ExV^f}Z !fjyi8c~:TbWv ǜjH(%ao<U,YE_vwXu+CA)[o)JV,Wu֜'eGڎpnV -Gɉ["ۢI`7]EoK|YS:V8<_D[mk"9˹Y}CVc9<ҷNk /}K߻vZ{ЃZi7]we7o-[m֭vwF+WAa1K^VDu?v>ڶ}ضu6m"-zmʼn y"!'i 6wۂ)n؎ٳg Ojh&މR1ppc6 Vc3kyihBKYQȓ 7? 4',o}qGyf͚o({zWDyj֬YBwM7E%XhMvVx7B݊`y#Ƌb̘-^8-;OړEZJxʸx |耄6͹:c IDATOuoƐb7Rt; oylxa_2Pڬ55ffU:&AQÏᄁel]⽻.V 緶:={p_XX&'zRZB37m6bj*ט Ϭ.+TmsٶnF[4w"gTZxGG5no8xόgZy{%Y ߳A+3khgS&bX R;DxmgV3grsv̲Ϝȸ/ȠUڥE;y{^,A?Ϸov)# \~ /"ýK}< ;C{.G }{я~Mo/}Kv_|;v95^}>&:L}sԧ>аDCfگo +ctW4ʶMbо x|ߵ׾E9˓Pyˇ,B?~.^8袋 ox]uUy Uwy|3 _BP@x<\p/>ggm ?k3=OС?J ޕpk޼ As8Yfڪeg?}_c'=)rfq?GՂ(óky6d`Wt;)ַ۠~pK>hs (\+}{~# =S#?"X ֻꫯ*bdL?]8VY`_?ϼKؽo%rƧ>H_+A'?I>S]oXWw cPdj-nMR#\;LQwU,ʎ69|ԈR!(oo^jw lUvq'βlS`UV|ۤ9%|AX0٭ d8W>ܲp80cz ^`~#]󹌞ꙢQALx,xA on9__푏|=O}c:ݷ[98,<䧝vZ74I3<-G11\߳ ۯϬ▍ Bї &_5KZ!FEN30 \|%" &8N߁44u{]M!G8%￈sS4[҇q >S89U(H*>N8w>/y,iw]Ojyc|]ڣyZ8w.bXƉ}'(oo#<7<}[3vB Xh]8SJ3'v14%>t^pBPRtIu)1?VnzP/`ɒ%Qtǵ k rg7qAtU%&{_ٶm{+-m= SR+Y~k`+Yy=#]첮FPuw|93얍k8{mi>LϵbsMf$Qlt\_3/ˣtG CqQk.ɣc_Gh'߬ΞP9>V,1V`{i}{_3n_ vH!K.Z:~xeA(s=1XmRKS5L2-m3v)݄ҷ=a(#?#s2<`P8\` rA_]uHL+ߟ'F⎀=.⭄5 +7ōQ+v/뮻.2eh>Vݻ̓km }2?Kk_ ^a_,Z{ Z[xDPr?w7Ʊ7%kO9T`] 4~~?2p5?83⺇uYq7 oh cXJ耶CX '44Ox' s('b7ev1Xo"O<1 ~3xTDh/f+ j qf͙m7^pgY@3Ol7[ˇϒpm֊6;VjA(mh+mQno֔wg=6 =''&+ 1q>pJS'8Dm + (D1˒w4#Op|ٲeq{F7暈^؝i]?),4GNј) ^NC?GYAsƃq"r>5ܫa1piC1(h: YȉeR;C۠q M}g&?@N8(0_cnY93V=f'ZՅ``/Ȁ@_W)T̍l>+_ך TY hVL-R&FV9~/% oh2@igiӏ)c<BVA?x2 ބ!ڭa:{ɻ"tsZ&}r{!'s7څ05#܋wՉ9я~4)=7Z$x1%{#"JG{wyʼB veE<(Fƻ=iX!! JbhIj:σX  !*p"63Bq^_ƞ% Ӷ;Ns '}P0v1ӌk_=c'z<{Xdg~ck5F ~C_xO;/2D?'4`AG0W5BIˬ>Q `2h?4 ୢ Pr:gm2~k;~0np//ds& 3<8|gO23@h S 4ET fId@i#coox k~y{St.ypS {d S~ sRysw/~u= fkYo>fg֗+kC6?oUzl(h7}t.Jrw*wnmǕ=- Y׎m_+[VLk5= +cƿI7>JR(:[(΂cx30p1\fs1Bʹ _28HD&8# pG>U_\@ o\9x,A!3=Um8cn&%|oh2\$ʳaOEh-80 q=kٖuǽ< #:ɀw}'K[DOl2 i,0)˻ !d|BGD sddO0Z>#20k!>&ernwkYoHJ__E  SJD__e~ƽpqW{QP` x4jぬ%m"c B3(K < ~N^X ;90x kiBlwe}/X빏s^q |z ?A!TᑪݲíkpFk Xwͬoa;^mbtPymcKVm ;(@ ]1w*uSP^RzY֊@O [Qy??Fe|du b.ۯ$"<>}|{,BEcOU(%79xȚy #; X0Y2xqQy?˿Hӹچ! !J4D}dF(sYG/r'1c?x .O-ʳ,}W9?BXè{{,pS Ƀ?vY?{]uն#ђeKmXe6?Ђ%K؝+Wo~}i ƒnr+,,>d  j ´_ ammqm8(V;JS)iJI Mַ$Ч1'^oXsM#s,\1?;Cc>5.W)V>*) Gc7v"8˪-,FGm/TISRFpD#(J{J-r"-Aۇ ,!{6!Hh/kC'ֺcFȏWo JOk=6giWءx 1J 3c%\x` .PXa$Xoź x KRh`N>Z8XO07OIJg! 37% zƝJ;"DbL`<H ɣEaj'_oc|DeԽZ:Ai6*|3 >,1 .ry!V0#9d"4Nrw"co }᭜ Qkm vزPy[WO ݁&eeZ†nږ/8~V;6R;Vf.oG??އy\ޱ!$UlEd?Nr <7'  EA6Px(:%~ԒKQ 61+|TW c牭KCː_8#Ms= 'FAh @hr#Hȓ QNcfaE+|ԺW>~a(Ϗ.9KDPN_D;/D<@k>dBpkQ  8{9G좄B1#%FBxЎf3frk4 6"1B"Lp/,,@<50N=u#B.MU 3yQ >ib%C0qmq+KX͟bX5 < X~ܴJ/:7i\4&Z5Dy3Me]Xp /@R&'3Y"?783|Ѻy|rN0r@0&IVl,g<{*{T,ZXgp5%u@!( ^%KohJ\ 3%4eڂu󰾢zf(/tAANH>!k5I ecTe4qϠXy7pH,|U VV}AQ| ڃvcIFXp ~BE 3A yKo_wf,vzk5~} vmwsg% +h1r֮Yo`;ϴYvԃ2R(Z%|o*+o[7-?mb6[fUX t;ZMq%$_Iy(?hn> @@?qc8W@~8F"Ed %C=J ', E7HvcLQƃLX;08!sn{U oB$Rٖ%R[߬Kq@` 1d[ HG4}C2ȼD Bd~</ T!- Ī: BĀ2P $R`q]Jb /~;v@| }EG!“!i[I؝LQ*+yGo,^Pdz5 IDATcCᒄuAXXĞ# [@P+,uYZP"=h4=C&p %Bmau2S2>*(s0-7U^\7b##"aŁFqBMGg:!`C1?{1k @y1^0wBzPq܋J/V+ Rq/Bʫ253^8p((ɸ>wAվLxx1e̙# ~0̚n 䞩6U M ^pK{Upkd <k9Gd0Ȃxʚ(n1r!p8jL\tE>BC8 /g)<9F&C.yGd Fp[3#¬ 潬ia'OPY IŲ@gk+El (#"!u6[f sAVhm0y-mD`Ph;PvYLE "3>>w1 (<071Mڎ!g|4PxDSNyX^#!xKk;;ht '`@v´X,;3r=S6TEuw=D!)$$ceP¸GuwJJ{|X#<BزiVYaA5@dN=1=L]C7owg~,(xڏ ҇E0!1 :ºoks?P,82*HxTvw1L]|%'x~|]},6tk b ׃:WVkh% ! SH_lWZ&VǐFs7|#WO~ r1at?ed#)hnvFf ׺Rf#<`4_\y_(\h)& GOg<z[yva5rRB^'o*zalG2"\OowQ!V@SK6odtKx/ S/ƽ$pm#~ᑸ{au8FNe+(8;ZU_ڢշm/ JLzm[ûs-f5W m  Z:d=y+%"s0<6U/- O|mc lX-2W>Y˅z>,\sڜ4&QzCɻۡ Ɇ\,:XwSA+Eg(tTpY?<7$_ThZcYx'֙WWKu󡁢u )L” yERDhh8cqhN_wUǸ}>Bkg|%I֞k>E{E]|oP"L0rR^  (L 楝vqؙفY͚5;Q|V iTb !k D} rMD}|_݇^ @h "̼K.S#S+De_m>V+Sd- %EAbZHX;}Գ$ dRCtT~ׇ7?j| ? 2wִX>sY_]̲I(Hx5G>"6~#VxiY}۲.vJSV!wmu뭔7F+SC;IS!@{$ d+ Qe|.\#1 o)KC"@PfKW쓲KI=U8,tSE:M.Udn]q;JHuVzPD(抑d7Ac㩖c8gbXOFU\2>Mu=fn3ʘ֫VCYܯq@kUy lEeWc`,p1(R[> GmY;BXT"_Et8>W㟻x2YZ=Mmކ5'?[12z`KO9Ͷrm5z/?V+#;6p4ZڃR pMapl;gٶF+a|F ոjA FUk1ިFzbQCL-KB]W#-`H7M4'՝7膊UFF}WͿ/TLyNYc'yhA<]yZ @tH1{yķ]"XU;tR< G<*ٱlD8y>4 MW!рS 5$e+ݣHp:g>?ސc'ˣ>xy|+ap,%/HK )y(nJ;e6rӽcAn{孶cjAȳjWڲJ{xs@UTAnۄD1u1c|">sFEn mIENTQEQ7w׹~Ʃ{k8foL堇$;v#H2%^K%{KYj\/ˡ?]*JW2Ywgzhy)VCJ;k7m40 keKt|MbSh[7[țyaK^hg mcs}I?pOQӪf=ϴ&? +.ߓ =ǝgiLui1^V 8StϣR6#[0WLy Լ쳟2ٳVBIԉIeXR8%mKX9$ ˅tSeK:,$F`Z/vpu3sZy.,#HpX&q"{~*`E+ p!v&ie,!1bE:DeT1XGg4?)"Ym;1\V"CöUd}gp > {&a>ڝ[=M⺳S7:lҥT ( J*(z\9!SKPA~53!`r=cZ!S9kd'$P%U0Ct@̌[_I[U`Bڑ IƉI$(L6~Wh @bLÃ& *Th:PMBLouvChb2ӭ{x~ tQKgbvϙf)@ 2p5|V->nE!OWxi8c&3Z=Wlπ@d31Oj4u;(T{9z\] Y%GA;^A +kN)!yd'As!vs׬qO~ler"؎K@Tޔf[F6]+=rw%+;Av5}q@ Mb^DmOx #}D@ՔFyUPcIhVҁwO,ޟBg2Ϳ {nm[mҎ|̀l`4Q&>7|86U~@2L4q\fk{o~3fNjJdT2 r\ hAjECrXo|2=ܹfHv-eV\$CxTج|g ( g)i/ה݀O7L.#rUWz=0ޝi>_il.$GJEGᎆٮ4}^% 8fR(3!&tȉe&x%ehSs~sRxaJ5?o3k {U3Vӱbq}."Oqqq t踥U4w b3‘&LjyLPt_eĞ}#CAHSLWlKfmkޔϞgc@6۶T2>t5sސv ˺%|HvQrKdn?4vWȝ#2?(hi)G>,iT{ܞs}Dj*7{r";dˍ7Hh]0]L o+UgrĤZ>ҚDZCC2X3Z)\31 5h8MJ3_/Hjy?OrID9[~.gv[K?u}4~IX3o*l$ elclyUobS0oҭtۗ߹-͵?"5rK5K9II(E]j)^ 5puxx]W |HhՔ)lBɀf>6E6:6Ӥ ڗ|YiLJȐSe: (Õm ݃-ᳩL vX?qTk !`]_a :Tf&%?Jo[ܿ8 EXQCkD%͑WUn\c O)=[DLiǼTU_thC6]ͯAQCng:{`HϷk k$qσIx3C3xLl2 B_y.tcm1&x_E7$= (-zf{>M1dt> XhUa2qMRhKT dne݉ `AjA&*/?P{ֿʞ7;)Ky6)5d mimCV .]7_#7z$O(i f*u1ɼδ> 2f.„nY`k*\7oVlHB;g^P3]gl&Bt֏cٞ7Dn|GQ0>T,< ڙ4ʚ*Ym}`‚ݡxkR")q v*\T@ ulGK\d0vvpQ`Λ'aD No٪h%Eݞ?SăB!L9kMAU(y3=K UA`FRLMG`p_ A%b7ϵƈ9LNo)1q*Ҍt:S:<0,,,Cj\<3StF|@}+,CkWiJ]f ~{7 t}7 &@IHӎ#Lbㅚ؃%9ZRWQnC$ wH-`\[I\˔=?20E& `QaizlV{)ij^5SɟzD=DiQmx6;̗a AJ|.f*xS+ t6XXG_$i.F/D]jUjYvLvC؋ȿH|t3ŒѬbY,UnGژ,vh;Ɏ=<1.vSFk-;4llk|&QGbB`[T^tpRm55?)?_>-:@Fj« AaW+o&Lls=>9wtg~x֍鶞BYjga|dȹխ`/ "L@_ҷyn{Z` .L>碝mF[ W LϞw¼b/k7j< Z!ZRBCv B oM1?\XCqr ad@,(UGdY f|̛Y&vp2xXj̹8y gRޟH(6m<ð?z;:]l)ցjblT>zplX Ĕz袂=a0qLQmn+R)$2C1B;bh=81")FDA GKYI;/ׁB.!9i$iL^돉3za{q=4;yəzi*H@B=`T'k>SK6 -ʱЂg Ϟlm ƋZ1#/UEr HVs3 KÒ4eu7H'KW*w+u 9 BYQvݿC/^&RK{f"uvn=Ea?Ϫ[+.!W*MGiAj㣺kSu{;@y${z$.G4 ha3e_Xsa9ˤGa2{{g2CpF|k:og-{C ̥X.Fhؽ?i5˗|yi#ڡXxk,HSf+E4 NYBv-o%y޼.nmsWyf5=JJL%J*-S{xXt ;\k,d IDATn37_74̵@_Pʯ Xyv-O^n :9[a~ۆE;`rM Lu&l \Aԃ.(8kW4aR08h`'IA{MWMI蠕o1eN\I\c5QK5Cr}ZجKtV) Ȃ~~Z^HmF k 4PFC^[J73Tmm7̊߸&Y?ןMHOۨVg(M*c{dr/~wC2-Z8ä$|ISuQΛ[wltD euhL116 ^1y!IGIOGԄ͐j`|y\f iX,mT>@tsε`F8АqAXd,k(*ղFZRJQ}>tl0G+k^)m) 1óAj`}dld:SRTMȃd湱炶>'lu {P}gOd_k\nnȿY O9os5Z[掿["JV`%y{Ha\ia8[k FSz Hܳ$EITxρE5S46VBJr tAY5CLU(Hmu6"K=_hpɴɘA)G.=Pnw$N:A-}}#ƘjJL9BGMOݻs4*Y`>'/ EL^a.74y>k|ce˴b8 Į!qI|9 zucth;32ѕ/ߤ qC)~QIupb>Z$_Ӱ2% "Y8_,ALY,[:Dž E'\=c+Y ?߮I7z,¶(nR/{q5C.#~e+ @glb\Jq,H_#5~@C$(}ypR(8c316!U}c7#p :ghvw/I%A Ojd$@ /0gmToӻ\&hI,禱uVoAgA 3{qY $b:fstk^75&/E_%l򚥙4M(n[)a)jr7v#e-U~ɂ3͟a'/eEY٬uQ0otLNіCkp( x]J;XmRDL4k йhh9ᗼBϥ4GHEwGNHЍ-p(AN?ӂjR0 dmy6xx? +;z|2&+VK+fl:~u|yѧTCY`nkV%\s~+&A,l-L!(6)"*d*Bq]2vLƂ F)12ad4)("n"<qnbj&L:֓u1uߪH0Np3ʾbVYxn5o_AWU7^JvOWAtur“Δ=mWk&!yUk9q(Kkz`C(R`P Lzg Dz-cFa<|4:DyaȓNn5VuCCME?Q@{%g7gA%ǔ\xMv!~xzJJ>-*=aarߨ9DѨV>mNcXCLaÆn Js.f1*Lł#1a=^[nшQbLuǂ;8ٽ{l߾]+3Il^g;g~ؒ_Vbn *JyM7CYmSy 5r[> ,Gл[ߖJTs?iF~ qZު\e=' 13%jGs||K.Eߧ LJABHim&)}v)$U8T8Z\uu"W|srWKVbt wt];eLFm*{&׿=%?tU8!"↼ϔJ.wqtRV'e~<-ή!0o~YSok&L]pS$>E'Bg2_!ʮ&D@Ͳ!_1Lo\|#`mWȠ@ ı0'#m[LYժY\8DZ卌;IybE֮?Rv(a,5m{eUqJfO\;O6!}m.DG7h]T˼?$ٯB08/}ֱpQ9t!rƙgj[ig>~ߖn!ۋd[5O.O~3m\^8OEkCsQ[=A7e[yRwygP&PްoyA0@Y"3Υu^g.K!;58&o!|1'P{NzfYxɫ_j>V7AʈD)/Fcd$OXmǦ@8=qSB(Y@cMl-V+z=ȟ'rmMy븉)qD>#4,i6ɷjk ӟ &u]bŊ@?K7/N@Jׂ AǺ`(pu+MيL;BZ ̧>)9S^g;To@=uȍxLS.b%_s_bI.b`G, r zL[*ĈLըJQ1@'eƍ2>:&,bNM@Q{q?ښYǽ^nXX꛷Jo3ZԐVsl '`n#T|lSd۩zow5y]-,JȩXˆ ^Z;Yx1̳ݼdp ql$S @@;<r3KA]gy3R"D 'u5Go~3T< x1cN 嬧>MNQY } kA:~ ‘$;.7JU'%#i[#Rz< Iύ}ʒ"m׎nAZ#,}m-::x`,^Jqiמ?{OYDxԁѴB]Y[ coɰ1,Ѵ H1˗e¼ٙ]7,<9* X?MV߂nbZk'o5Z)yYLQ=ܣuWB#bMf Bpe5G򠓼(98ض=gl'0 W_ +4!Bi(/>":>2C^|yR [E*}`2oxO$jˎ];$.!$ j׿FN{?O{OgޟA|Mڗ=|$hXF_ߒvdmT2e1ı>̃ar93G&m%Z8#`z 7lA^K~@FTטìx=+'/{TkăVg4k -E5OЂM'܃\+-:_Z>ϻ=9߹zOʷ?#pu{TSHe[oA0cj!SфH[p6U&C AUY:r=rءtG(8tD> >L w}C֭[ek.)s_c,\G[EV;ڷc|qرCke04׻/B%> s6_0j.ZJ%w:Z(ᢹA]2 h@s7{ C2zM98f22˨ZgK\|1|OPFvpNbnYpMGJU:`֖>/jH@!;LV/Z&:&ek!KMsz[J^5Ρy2تK}Rj4ebf֛6J @en:Aw;&9*V_ K` %m@_#qOX;[-&.Ϥٵ4j >5Z^7=[}T>Ѓ'^DZ& c&O4 Uwd ,bAh7/WE{y20a$amIœxgd0.uV?5VQqrb\CC=4sd> ($AD f0ĢD Aof4m-LܐxXM63q' 6%7%'n҃ mZrj=j<蠃M'? 嗿~i |֯_?eu;<+wDku2vMH`j,ӴgN0^+ Q)Wk;'#6&~Қq^JL7\s5Ubdv́vՏⵯ>@k'(bKge:k'6B:][s  la o~wq>?l *x yKH{O?,@@Ε =@>#a'̖pCj5O{9a|3i.KN0W%Cpƒ9)OyJIPS3A}DQqOEz*rຍr䀃6Kq5nj/Y\Uz .dTmVG xq{#sxVڡz_9AIIqb9ɦJ*4߮9=0- M!\۾r?RZTڵ1)UP*EQq ϦX_Li+@k?O%' P̹g ǚ| :6=k 7dq P/ _BoX/u3 3{|5_!Q8j[,e ;g&S fMbP yyӟoy'0F_+SPY XtG*>TMi׿uywPMla*8}I/}3,h׾UyypVb}s*[xڟ)T- IDAT=xsϑK/T9e67/5%/9W 3>嵯}|ՁF/ -ɺu\ Tɹ+gqE Ch /\_<s VȻeMB_f~ yQ!;IZ:%V^O[4 ?sSˢ=IO-I2 !1^kuK=q@@s0_P{CZU]+F#e>-S;|T,vi>)8r> Ox@pʴACp^YzLIc6/ I\LGc85mwAwR(v'-CTjG~_hW5>ēO>ސz/X,C2qr&ĐT }0$1,K=nD%w;]z̕2䑔mn7<Omb:[ fX9B>=ܨL6jj1ÙgEQ\c4ַf)[@f~h&:e#MeC`/hd&X'͖d!`;uJQ{0H,=L; 08+oM>laTY^ '`q>lp9~7cP1h%(8?@pȱ=/*sQ܏U(aapo8\vkeD]V6ov:Yr`TvK1Eݼk(h4mݿMWW0s3x{9_oQ֜P۾Rt+N "RDL2W͵q%[+{#&_&E#DhSܯ:4Pۚ|@\/yckQGK8>"5m }?jP2LB` 9$<#ж`Xq >V}=5N,nIӃp9n!#=ݕR|[}Ow8>7X[׬jhd03|#|(`(fV[ҍ BGEE&X~|$Ed[>]VSd}mtD>d>}+jhg̤]~!rǀ@pP?5e2TI/3Hߡ^5QkC;nCV^%z33,?q}7QGf/}K*M9昣/xM/_MrQG~9Wi'T%A`1B s9D;ZaC`LmAD18|\p?N Pg7rGT` 8`q袯hǵT7>򑏔8"`Mm~` z~*P䢥$ ??=wi_7ۃ-r}oNB'GSP;/Y:L?O-p?Lڞ=%}k`"ge6vX){,_̤͌u׾r&UP4)s$fUz3$8ĢT%lc`|5fH u#HMdG}VcH4L f6 TWF\Stp<?~i8sEH{Sm&M}8Fޮv3Ѡ:1#cWQ.7#{Fv/|J9\'p{ (i%mhΤƮR&Րx4Z\)0H1htQLaiSTS>;v'`hi}.,i3v@<]_?O#}c 5h4k;4lo8tM^KOtبpKQc4nڪ96;b jPM۵=%Tj6[S5M'3v8 D-\do2&1gJc֡k>~~kcr`Ѐ0`VS o$NݞaCCһH}e+dlvinYumR;`t:sx,d ) V\.yk^qv^j(g@5vi}ȞgܬҔۆ V8ĵ4yL`ZgY?1Ksy3ֲgZVhƌ<*; M,Ζ`sh 0,{0O?]C#|3ԜmaHuR[XMiӼ-| `bǰ6![hZTXsJYˢ 庫q? TAYZ =I0uNR$W~CLpn W(FېN8{^ǘHTbԻQA_`cgh˼i^BiCPzD)ڥpN4^zY'ϒ'INT୭ HOW&.BWR9z~ 0޴W4kv^kӑz4eSJ% 0/QQSԌuN<۰q| $q9!,~S$9׵}M%0 0xkԠUM[[XKC Qm >Y<&``VDO&Q={jit>A5FqւDma|P.)Wxbm |9%KP~ -:u=4g?l=XŞ8y<_|YW,v*$@߁AiM|= P(+t X%8$|&m/ y_Mat\z׻ ެsyNl񂆉'L,%G=QJ$I#x@&!49Ϫ;gYXl(r1rrujp50s80Z8,*`Hy ~ޗ*C( %#' e[ Ԕ'onP_ׅ{ݫ]Z[ٿys/͖a~Z`VJ(_/s?@|_CFJ =N.DóZ}ٱgFgTIFH^v4=(xVjWC 64vHFLXqt-//A;EK.Ѫ٠ EJ@@ @OTtT z?X7f}iA6AAY(5WgY 0qa$Gi$jH6cσ#h1hOރ6IFnځ¹7.Aydэ_} qoT!ic^Vj IL asUM:>'3|$~𥵂:QGeFVCBZ:`Yf9 m}3IX~0 5I>#hLfspGPbկv.@X3sp龭R{aeFE ")ʒo wvkvu<X(cXGZ΂,O¢v%Ud rGw iWй7+JАOKv1V29wR,7Uvc&njyJU%:@NQ-ZƤtI !7ݴI>Ow}&ox*:w7 gL -?.f3qÚF_X Auo /c:31^C!Z\*ls-PbZTf c*{{sP?[xq *JLy"7<DDhPe Ј]/^(|;Ŋ};caşn?^ \€LjÁ̵^'_KCfJQvܥmB?j//r)'kUhЃLPh'73 < &*F+m{:B k`^Î@ik )'?IE0!?Oi8POڅ>mհ*SA޾,w^cv&2S314ksie(ɶצI;9:%y˔fHOB;$R2mR";4Q~ f2ʜ$Э5ȿV}w >c}%cyCrOrxфܸ`/8)K`K>DQg>+}YTᰆ_ I7%1p V|Jv!}Tv0=ʌZ\;`o4R}.ޮB`^K0970006UjqZv0V\S 16 z Q0`NxoMCߚ| A{ѿjVGh#%{vh<[1k*VZ75[NT+c h- @ ,lz Kdr)p+ݷ~8!u%VYO 9d 5Ygڳ w+4;|ƶ`b P0V4\ A&_ݖK=n9R)m@rl5)BCe?9!m%r7 k268{K a/j?5BQI 舚X& dˑg-{6 W9]RX;-J uB;ѐ߽{CdpJLK'5k Tn45)U5}  [W׫{n޶jS5_ThU4nq~Uzm;R5~NC|SɎd j8Gt=|MA,ۯ&o^H.4=}Q##23>g#ے?o1Ž;[kQH³:K4ԣA-T<, $2&a:9@ĐtZJ@B/րO_|qPԶ؈А!` @"|TB >d!"Mȅ5װt3wOndʫ;|~^\TQCE}b^Mu<: D6@)6.V ZK0fm{c&tDZ_I|t'NR5V.0^p ϕ>v|⢏˱9V=2N ?o~yϻ#/z/~$=6+ՂC|\/^\8"m4U')Ow} BC3;@@ThJ"z^"":h ώ.:39Sp1dj4pXp`阯Q)c_q5Sß R\HUA $j> !:VM(} HE<7ڊ )z3K5tWGM[n{~!HUTPLkuI2yARo2cX'=vl!gcG -!Sg}.}ބ_ObUA!=/rnc6JȮ[oEw*U`+͉InCxqcgi0] C JTSЎMbΑEnKeYt26KV-r{oP8_,;d耥ٞ`,5*hKHjiuc~G˷7{mLA̱ JYrG+`7P/Sy_еL6^:׆(Aw7^/'+_:~]{lvr#<zh}xT4Ä 55Cι )0Ruox}7][\5PaDe%A± `[){:w4Ze 8v }ŤgnlLt% 5'61 Kv!1&}ΗM(_l[0_fM=}ӟ$7\}[:Jj2 &h YzwcTm?'/͗uJYwk``P`h?Hp3 𶷽m/5ժ/D %K$1ԉCqY/O% p8@FXR9wI #DP~ğG C-oyvVW\=wK0/7Dݞ3u!(O IDATJ: ՟N{)w_4%AQ~BT(Hʪ؛i]k:QY;nrRS*Ж8Q=nUDSw/dӍKC_:сHJqى7h[}/^*UtR=7O"ڮ!"E}Z.F#2iڽo{)U j#5DbAMJTS SIjn'𸞀!Ajy7 - ~b^:yIbf U ozjى(XBܦ; ̍x jG/x zuodS8ޏ RWO 9-($,ZuzJ vxZ C Owڀ_nG뇮]+Gz:T-{Yc hR듞 'iJьhf#pϑ!93̑g},g0=sMFbA?ScZVpwX?~0s-#JiZ'~klBnuA%l;%ݖw`f6[ Z`^B(G%[jڛbs.lFylt|TkdsU$?fR0H0KwC ˲u'?}Ę??a:9%>O@3X`DS1G_gZ ?\6 |`Ik<bh`C|5mRz?/GO_ tWf JȇHt8^x@7O BaJq9?Ɍ[z_MTb6x9wȷc0CFOK@le2y\ G?di.8@ 9Hb1d&$}6DY&| Ikmؾn6: j&2XjRR mZa[Tze`z}nO`&\Zѭ`]9/ Pq<,F<;U!j.Pӈp 6}Y퓡r_IoWw7Y}1rׯ~ ;6 P8ޤy-6!nKgr,qئ*VMgMGP4OȢm4!I:pŊmkկ :MR H"a E>! \$ņptdZ)&~A* P.Nkbar|O?4q:DO Sqn"AI6[2$y]~AI.;d5\x:9*)2i&:-| Flk$$}1AeGdƳOe,6!D$)ε3,u&Á `A;ĿԣȐpR $9=qt!FgkJ>QJAm4D\_`ԃV;=Ty@÷ҫ!  XS͖Єd:g?vn%v_[ %f)hu꾯t|4oKXM E\u`` Lq/A0 mfDil!_U[ݲWJ[d`bDƤ&39rЌ/GImunixsnLҀT2M>5ǖIOsqH jr/~,훮{v*Xl= wRi3 8H㽣ڰk##@>ַPlϵ< Uy27V+1gYD͙b Χ`_h~g&hĺm5a=EPҖx)k7E=i]/Wd|LڍQUwk}eYˎrTp  J(O&"3sBك75F'8ZM[b*a}8:Ͽv/\N/{[n'Bm0~۽B^ jٟ)g&<>䐮ySvjhkjluS怜iA- n'@ B/lCi*'gxk'a6ESWgc7hqi?+ YCtٯ ڔX5 uȑTnb5xtDSKdM h볉7MY?pp%93g?d dN^&Viz ED)&_2 ,1DUwBEyk` Rj%?qӁH,B7@iSff]W)S$> 4-H5Bkˉ<ġĞE,$zPH 0BsDKݣa!D;JE:D^S;  + |XM p"'^Xd搐kRQP4'n1:  ,{^1e` 8aZj@$J3hX)X&8nN[6h„=4D31Q(Ƹ273g: "(h^a$xP0Xi#^ۑFɋsTp{drTQ$n%Yn*[n|OS2[PKAQ&{|?4҆=~f_Hϰ_C;4OMjg/Ͼo,C}bKF)5&Mlئ4MPio_*Sn5GK("SuR&M%dw,L55R;:R53Vg9֞Kdr.pJP{O2֔2߽g9L-E L"BDM1 $ॸ`XSzuL3#-/J_Fz%.[cDi$lJhJJd@[EC8L16`i>uJ;݄] χ1%JfKi؟ఉt b"i H`bpɵL;P!N''c4a =(v+1hF8S`̓PWMCO 1.T yqԱX0n^@ZlrѐbaLǍaϨFK'aTq)6*SZQ<4߿M+k2{vX!Ai#D[ JVAm@n*]7]U@= _&jvA_{MCh+Te,u1-}}2(X/L1R(  -h%/g06o %g \WJ Y;wd̗h VJ87.oV6n2l0*t' X\v΅!ysDܞNJl Jl g-_?i`f+3=\' m\!fGinzƯ$5Y\j۶H1Qbٹ-rE;ehϐ`fY}b֨ ;;.q?Bp{B,Z(G Z# J,pe5WKy="͚F qz}?_AY@$h;Lvw&4ಅ%04:ڄ_?eݘBKDS!.G"D_>Ф ApA@sI468"dM@i5U3H; ͈nCѶf.kh|p<E=p4{ӱ0RcTt{\ 5/VB/ |6[ݙȗW9k K5=3`C?AvPo24wySخ"̲t,YȬB&aj' ej?8"y75Y;!jI>4x?Q;hXg6X&ԚkPY .&h"ΨdϞi%`Vy"C`FHB2^X?;! '؉ "1KV*Pf;B3(14>H~00%k{R_!ML@(p}íRғ8h!f iЧXe^"H^[?G#-U`#p%Lo[ŒEپcXA?c;쪪mzˤR 4Q)~b+ *(@@I~JK'$H!!m&3i}~sf{=]^;44W1 ƒCRdjL:&aB"{H>}SqAєrY$1HRVKlD8e@imkdCb 'P&O7,%ZP.0؟ֻ_?WJ5gg?0燆LMCX=48b%B6'iA_!*{)]wv5ޠpm AkA9F~Ȣߜ#N}߲\FN(;?v Bh!{o9$Ңd2#tZA&aLd ^6j+!̬hK3J14ԇh9"a`YDqhRrRh1WjU= f,]PB:a4;`Г^PPh-pk_ӫWՕؼG|Qˤ(hZ8aQͦ&ri k4gM'%XG<LR Tu!ǠjFrUSPasy}l,)r%|&Y8^L RHӖ$y@۲Lppr} xȁBĎEfDf}f3^R-+cR\$2.:ηs\ӚkمD0{ls?Hs4{5~e ~m](ߡ-YAjQnQ )be-(" ހg& 43nëEcpw[϶F?G~GSo$30Yh[c)_?2Y+hl>ouzߺ=(FBK c[Wp-S-5=@my`W#7;<8lpz팳vgZ.(=DEj|2́-٫p Ps82}iv]a5E'9Z5OAŠawNN503^Zٷi(QWT2ȶPVf6ϸ!z衇w/ŋՀjH5V5Žo J![*+dr^}[-չ)d ;zW7["* &@4TbQ:wjo b!Ah&ZAwt!= ]8y?Uʣ-=MѸn9+b!& փVF vdBQT5 :fSurQQw|666S/(}oImÔ7`q3'6r,I ޾~"ҩܕJ>TDPeZ n+: I%vt"*uFyp3LsV G1&׳s6#[E emEMbt嗯DwYqX;0W]/K}Nthi8a:Mo9q"-{<m xȾS9Y)3V5t{}NXI떼4Ѩ㧞| Guq.zH]I_N??cbL6z5ETj5^K })u}>uΒ9Z\غhT+/ꋪPvګU(f*+Rd1{esFG3(ўe ZD.Ȅ5%ٍ G-OaX(Fs:l~1_|FZ`C\5b";y:ZvD"FZm@B.O# \g`=K)pg;!4"׀=9;!5VQ}naP9eTurwؚFk ⻦zcQhnť#{1'o4Q(#h@z<g-@{!$|8|K/$?|{^WY=[K^ikcet~u}&r5^,;z꼬Po*G7aSGh瘗lkGy L?d'"8` ҾJ' S# L jO1.\[QG7QԋoE&+!lZ8#ym)+#, d'"~(F H7&|2m1socMR5i@P7)!,.\LuMY#zvVO>!%̙Lk#Q8 ݺ>.11$v"R˃a>l(MZ{Jm> ,͒/tny RbW؄w-1ii~Y=퇸kl- 2ƚ#gY^g3*?PcGcdt~<3?9shDGĞYnQFPIf Mȥ1,rgdlZ=~Ȍ_뿼i$R(6?1VE9 k[{Ag/8LN=^r<$OLAٓx vH/X Qy% XC@&{𤉘"k~JW'1?aq8c*3Sqz锑, 89k*[ ՛HrA>SV,Պ#DBy5e "/+u@L~гI#'yzYG3x̃{+X?nQg{4_zS ql;ee"k4O>[osͰ %`;B^awDӹƽA,m''mQ錌ओA◞3ؐ<{yQRқkW#J(.'3mSP朡ˎӌ\sQd懟}9cƌZ1kh)?ۮǿ )Zj^g̙"^Қ&OYrRO=.ӧgVwnws/5N;m@C]~ gi 4]-7:YQY}C1W^9ֽDPnZs;j`i e޽>cedrd㷊q2-Q9nri%/&Ţ}Y1;sT*"7y'M-899к5ӝה5o 2od #UP!t͊?3#P5OV,Ml`(OKKԬ{ =HUTǨˎA JEy26c{^;̮0z{*Msǚx>Ь4B0r+]EA;Ş$f8 Fi9Z@;ZfaE攬T>L蜁W_sA1)24>1#q|bhkslMk0dQJmK$AJ?/d%eLhoś<9]K4R0䅣z?+w (wPpeb" E%(]$wVKŀ(€oHb¼y Uo`!ѭ$2oQd7`_5AB,bpUX4.{8Z) لlܨ:AqMI]wCFD1Cf]RD^d?r=kQ'&VyfDdL"+W|<@)UG)A'? Ú-};ڮlDB#+&Chrkǎ , 2|{m]oG`X졼dZBXl[,mKvcR~n#l?Ut\B[bz.nO|ڹIsJm ?I3e[TD?$=yN:$m /hX 7 _~'?I|͘;w.SN9/jZ}tC.ֈcBh#jH.C5P[!ǀ'O>*/es_?E}}=`ff%ipR)H=gs ꟼP橤y \ٰQUs^p* *{cX+1㸶 jTE pQ!\˟1QT{+Ly?|83*;/~r3v5`Ҙ8Vm˜Xu{\i f[;+~rصΌeÝR{깽nnu^)h`ْd ɦR\3 4F<qYm\GFA,c{,!LmR7.Gsz8-E DZ01܀1ª16YޚF#isA+g1,Oܖ si&#.rhhdXǺ{ `٧ʉ)XB "ֈ9 ӧ#$^hW:Gf{fbAm͕]13o'f5爇=s%U7[d{ ۧdf +GOGF=~nWv PWB01q"ǣMwbȃ84`k ܵXNM-9m,䂙|yEGXd A@8 u$҆Xtظn-}ߗ_ h:xAd/GP~ͱ Y.7_*F:9o'lwk ?.E{d$r8V<ќy"T$6YW~@Xͭ7ozn=֔BcS=עJJ|Il?q)Ƒmdh%-ey^C}/@0MM=؈HQϠTI3>wbO):T*ų=L"V(?Gd}Fîf},Eb ~|;:Ufe̞id ]E)2~78]>0eddsߤl"й#~5혙J#˕DƢ貾&R6{taf8#cW V=r "ldȣR1g`:_T15EbN_όPUK#!uw=ؽV̓D*dn 5u^#O뽠;*ϑ}+\DyA8 f{G2N1̇+Yty{  P:`-3 }Vk#M`8ҬSFg?ʹVlcaq{]HK?BZVsbq<)^`Z1CljltDgf̵$)r $sL<ϊU]Ao&!}6(h=U)W{36lЁhG%sfD=T ye'O lԆFO]0XKOe)ģ] +4 ȓ]ܪР`֓{[UQ#hel<֢.cW8݊c6k[Fw~{<ѫ/_okz(][1|&MwGjֈ:AV 7]]]]xꩧt| ~w';|f̘.>=ӦM%!$|8Uqd&>3v'а`/7cҗŁo*1p0{f(Ǵ8 Huu"Cܸ$5-UE VL Fc}ո±,pZUA-ߋc#["ÒEcsU: ^ UZ\[W^u^缯|fRqε}q& ޘѲ̎Kdf 43d<{kQ>S^\wB G<3%*X+?Y!v{챇P1"ޒ5Jw|8cH}{{ezV^,B9昷q6'y睷|K.?qkS}6؉1gs,o9^J|+=c&:E|zrCͰ;GRW}}~oًqG>~3%cX-?w݃`Kfp~vɕhlhw)h͂Q\ -y_]Yb`D҄_r6yy+:q2!1b.bg?wI3.m8[Ա".:~r+~ÛqVgK/^pї%W_>Xsс8ɽpݷ-.+P6 !>}C7㣟8?BKc3Dï,U_9S;c?Dc)K.~F^y_z1y{brjp~ S&o~MIl. udq"X 22'|Y ڡ[ gqvakw,2B>eL(,[;v]='3w$Ś᧟~b:i *+մ輢{WׇN]Fch|)2P沨d*w!\MhC9!&zyYf& lyYъr]7+k7,9[˞n=Š矕*8Du,'k}E' ȺoY(,䎻܊Q'佰,wNz)L+z8)h}i:qP&DH}ZȻRx!(4~DSQdy[8gyMhiNb`dMp@-D9%]tMdfoKsuO_o0*흈 mtCds;kDG弡Xޠf?b(|}(o+! FU09JcQu'&eЂBРx٧L\|Ih L5$1y` QX3`t5b}*5Xn1Ya<G>e4bݬa%:~!/5wv[ss!aTReo-?_C~;\xqݽ/3m0f("z#="JX's3jp"\t&A qhp9/]h*}G|2fμW|BZoW\Q\tŘ}"@]?zxװp}aCV][sO")v[)mOձ7%.@RP!v,NVgUΒ,m%]J1dMC!+znT]d{D]>rg/}*jHDLй1&RD'C7'JSY4Ή>ђvF&L֪ !(p`X[֞&U׿!H8G6ئ Jߋ&rӱdil}5a*~xz1A*0jX1bL֓QC{t5t{fGpXyjac YM,[ߟ8"Zښqw.~dOe&)PhikZͲ@O d-%ڰާC ivAKLXdkիMv(k]#VS1wϾPCfawmV{2F~۟)?u+ssE]dia?kAma?_Q/\Cv$40Ϲksȶn=O|;jV?wc8?11y䑚ru]k,w!{薂{db4_%:RlHh::D&X#8^r%JF:*:vd 2D c jaԊk,gLr>]'ti8j#H e(Cߛ1g6~qO~bߠF"9ec[0s=wcuW_(AGw[A8G1U?7EmOy?TvLo`e|qYo%} F*Aكj1  IZ1.R:6;o" G4 5+{y|+gyg.|U@U#%:]QG ˥J֢oz^Aaf<&yIP.#$T+GKᓧd_}ӧt^a4:>Qd~DeEXY1qY1>b~ U4 4PҬfK<]&%2g>v:PTI1P_GH_`=(x,j*^DZEu5}q"  aL랁!״ȀI3&a 8A0nZIs\&h1L9F2;0_cJقTS֑dx~"aPæ* P^2k@IubTFdoEdd&7W7FPW:5a5L;CŜ3nj]gsZJkV9d$6v5o>Wgdk]::?:D~!AVZ"*d,UYp(gVF8ů׸fel::z wf8;۰%FB OEyă,KgPD kb:y1gr7uHT^ck+'[$.2HG+Kaqݻdy2/SϿVs"vȄa"h16a( k7OM2IFߋ;G4F#eŨ쓉̗b8Ht~Ik\%t.ayzQ dB1_dX y:2}c+] BӼ(H"S(ҢּQ1P/*G-D*ej2 # N?CsqUy'NeV4xlĆz~InE-IkKJӌ{$^^ ; *9&1"12Ue62mkkD8H6Q nFɣ-t55aa^L<*LE% J}eTx^!]HMɮ'2TRo'*Ӄ(P4 Qedt6O~I[5#\fxLv~3؇&ӷfA հX~-zcr!ưЀ/1Y ǡX #(QeuO3wa5q" ϔ˰PZavN fN,2scN_WcYC],k0A8 r];L֮uGWjܴz&^YȟgʜK/\wʶ ^M8CpDbH&2-i}HeZBT'waQjy%Ny(Yk~z .`rZifzU!_tnK#<ܖb^C"-aL,ls=?As*XBTd7:]mDNɶԈY'zȊ0x9)HbTr8 cI$&LVDKQQ>#1yfYr'c_cTݸJ!|b4%ff<c4u`C_) 8eѩay6A2Ga.C*#12EXt')$^["B)%it3b{T2Ȭ{]ٔD~M(ھ^|Cog*fTEM8eɡMڛ*ɀ",g z}겟 w1}fpHn:=7o\pf VO˥%,(QP&Z',PR_r}Duw_-->P#kϟ$>PYTQ!J3Bfѩ#/wDp%~4(ţ^J'A}p))rޛהYbBZׂN,za /; L$YXݥ׭D(2?1 H`*#8'c}9;n|i4tu 5r {1G[{1uxJ xNQPhF#UH_ku'e)x_qvb6 Mw}Tw>ookTqA2#r{ 2s`LP 6X:g>}5ѹJ<_?cF&e`C҆Cv>>=T^UwԽPoUxk]D~-B kPcC3X_;W]o8tH  W *RF2'K;ܳ4/!,W}|g+o_<+Ph}ՖJlo@d#W8w5!7ċ,w(lHӸҌ{>q!cFo\MʹD.-e LԞҕC0;]M>1fU:A eIJd4M=ՂkO=BridȺfW_R.\ q@5T7P5XCǦer|ncPBo0+D O^u 5d\5+:$𳲙(TIJokGgb%F6u!HC dD&"= d^bl,[L6Dt#3[sPܷE+4b9<E&bc%":K_s)ykP=ۢEO}SF͔)S4lp~kQv/٪= IDATu~z5.!C\:"8)E#FĚY*yn/4aWH-kʢb{1R$d1"z q<<8GPlLhAd?%Mlo3&M\TyJ kʽwdD^ەvOCH^K^D/$=,{$aS'B?7ub; g粣i:uݓI)#!2ᔂy}_Q8*:t֧feܑ,&ϝ):g2P ##NU '7=\#{4ь)yxS7`X0XFA ,dGks,WӈdP&Uu֤+[b:D5؁ _#²$&ODŽ{ђ`ѯ?b5 s/9q.z0k}R^tO9\_3aP\ k܋{f̦fpK_"Ǯ|eme"K?-gB,FH. -#[kþMON-ڭwܑg{Ԥxg:#m|^ +E{<cӟ~H^z<կ"rTWg76a.{ӹu~_~k7݌} R^4Jh >[^[qwͱM ecsVtT{b"d+]/r.Q5WTr6DH91ph(d 90ta|圯ѬPx ,bW`1ve,[~u[{-AD$QJ7^[-{ǟ'{ˉDl6e-e62y!-=dF0JTzd ,d|h1+"-`Y 3KGq ͣr͊q|rFý±U<'?Yn(Iɺ*AuT^{E 2F*̸L(DUFdQ8zs{1U[bɷY?q}mUhW3@WʗFҊD8m%|Ȫ1:JK-AN{w5ktю*L[v:1:V9Dҁ⹩[%kt\=bOgQ^gm\$u?:~xn+02mhhYEk%AK3}'Zp=B^o~rJ13^>z f#0V< +yLjў}fn+^$90'.s vv٫]& 0kb3{LKF>S7 %2g mN-Bn{A״ȼ̝: DJ\tROhFgtF6)MEGľsjvQb42]puWB ~'.joq'a?޾^t͛Y\C t\M(-8#3Z!gTԌp8ww\(L:9qSȉLv8>X;O놘:kaw".j ;/;j̙O| MiK.I,{"}ixgQm(!µb]q`' Lm'[8ÄfŤ{- *5M+W*7{v6g ("Չ>q1u$t )3ϖ4}8Ng:B'Ÿ}੟8?]ZQz9Yqj[2&WeM^9cuH4EAg{Dz^0r.*8O UN2wuW+6)EGa!g˒관 5qnUd{֗I `FY.{HtΔԹ`:HCxD\ D5ua)҂3>& 1iD 94Z29"Q??Gk[يD 6}̌ui3"Y =[^Wc$0'a LwEU,[+'TɄź0ՔĪ! {|F䩊. !-8aXnPR({1&R͊;7Ra 4XS$e %RdE%jɊ܁b8J|5F!DyB7͍GJ&g*|ɧ`ŊX0o'Yӱ뢃5yblˆ54%V[0t1҂3tJrT`0Ȑ|IzeP0A`G)%7_XqV[N+;G6Ɠz"M9+.Wk댢/SVYfP` /3Xozk\pjR1̿aQ z;e0F/u]SO=Uo6?ea7߬e&l)2alֳ)_ccBҊMp^ u lg5ZAux~Kst$ݘ]cԋ'3&Xƙ|sPA@`$ $">5K위xN;wcư8wâch~Go_iʂBw{Ib(ɸ귿sajn:>.jkba|~js".ǚSk@xmG Nqn# IX y)@߱I_Yͣ;gytG}dPO_:GOsHk`R j3ϟ :\)DU QjH!„5{U %] 'Jf|da=QI1(NL2I9ᡕ5 * MdQzYV`7Rhb-_q4f̢HapU׷ gNhv%eu54Q6^Y^$ "j5O L ^#n-Atg6#ΖQz ÓlWXKUa(,et3)KS6濈8c@ȃR ,BIoQr(1kd%]v*F1:22+0mt-N{RcqvXa/"߳(?s-.Ha cLfqަMCaO\yكR&u$/ L<¨|6Ț*Ol?@!h|5"Ggtv o_?&ܜf#g>sB"ޗ=_?GgoX˃: Bω&v/fPq\d^`'=?e9KAYU8RDSmAF{Ao1 =a/993*Yg؀g-Y)JAMZH`+uwWjԂ5':a$0 vv] FF̖EEQc6L9tVqJ mmȋBAb /s3BC \o/VsӉ'`͟|c Ri/EfbI2ּ2 0Aٸ^Lޔ xa&%-Y2!El'0m+[Yrr"AҿMcMP50E2p^gpt<Ѡ(K^ƝN  H#YZPמ9\CS2{r3\})f.kt fʪIt:Rq, `d+X0 EA.VH*^gtQv?qz9̨̩` *BLãI*XKuBŲB9,ЍEoP)َLC'LD 9y+jmy2n3^8Tͨ2]➑s78gѬd,p!$k.]Hkd6eD0"Uut/;_-hWMv9g3rQT0;p^3|(v1b(qU7iy~9E@8u>&&Ea/M"(e빐͡!ր|zV ɒ:xF;F{i4;f"z^~4(f&`U{Νkdg@M4Ѩ&OL41 51!`h'1Y!@34@w\us׽NWy9T Gԏ$32 Z 1qy#5'R:̀9~Y!w@Ewuwr5h7!>QJߠN@Zn6q5Ll(1^{5O;6LgPN N<7Zkmg՛|QuaˊYq}H }fIձ!D!tl!$t,rlú%} 3g&5E (?6z,ǂhGXptժUa'+jf$ {Mqze2nj8uN40I7]D]CC0e.q[Ump2k@i׿=\ /D]9r2ȇ~; rAf猘hpSKè-r3ҡ߉k(`Y,8"\zl9Wu\ʂrK"H \wm<{XyZ.ZM1Il֝z&ﻬ~qtdVa*2%稧dq=X4$m;Kos_|_?\޲>(ql l߲qA$mjui_fCYaYK;42,vaŮ✵g4i>{ee߾bw6}c6O;h}{]A%ե;E2lldktLYA~#dɺcx'LuEpX`0"9th :K0"dp7B(h^iS}`} ( #¨ an1m&<›¦̼0+B D6b͛7k92#ƞAP2:H,(e faD8W:<gf ox#ɒ`!400nw>dBXʄ-Y(\ X$Î][H߷9cF`F3.p s]nQe]v]QyuNҰIxJIQJôᘪn#lJ-W"׏IqHMGW_BaQ[.}'߼M髑S#U#QFurOSw:'t3CՂMjl{Ln/%pdQֈbS#D@4u/F)5YPa*!>[LqQ#q҃j)u;Gi1O2?cȋ@ޱw4Riiٺx*OO YK F8omg(h]ATPB:({NkCڏSן۬ HY g^ZѦ{8|M Lʽ/z }lxr뉬99#k#^ȘQbT_uO>fl/PעuK^C6lJqnUٵC69{y51.'u|k_Q?!j!rk6-kr8Vw~ -~db=wރ>16F1,*R.#,8oç'ư$fc !w 734eaY0s 9!!zh02dG6ꜹ IDAT"28OcyOK:gOJ$u`։\u=!ʴ!jӮDzpV+L`Ԟ?`)4r@ep'#eTX"s8s)<3"$XA-Y Gx8A-5 ܮe>hZDpn֭1C"at.+8,@,Y`Bn.ٕ7xՠlu/-M}r,fǦ՝/{k^d!,0KQ\__W^OE4鍰iW`eWh=s~ bb]X0b114y\l/`ҥ[,*}[`f._G-\Vmb^E¬v6hg-HWw",޵v=殇1TL8}-Fe&`Ds{h.v_ /(S6a@B Rajh39e nG Q<)+TfȐAbN.F?M a$qb&P<_<&Cl qȗ]vO ߧbVuTeLC" ~Ǥ"v( 8c! 6:.fa+P& >:H}k51njB# :a})h !&0l99!jXe p3-.F`[ f6E#fWNbFfT9ӹh$њZ4o g.To!uBR9Užgh;!95y\!vQ?:SވgТo( cgm &og>7 mdPlaz}> gHr.Jk'Jjm ckaQ4/b\bRxeCVKY2]PcqDĵES/F{Mv)I#2[C>GGX2‘9_K[QB>k֫R7:ȩ8BE\̆s=ľρ8juТ{mk $sW=7n|WiR ~ NC!\h>n4sN#-V+%2<~տmK"cM\K/^DYYyռ`RJQH&pcm1H "6<Jr>9fIki4&g9_3F s7_9m/Ɍo sꛫ#nC駭iC})h+7݌g1S9VDM"{̎+YgEHUMG9 꺯]%f[ڔ^ {HUז{0C%p֯Gλ q]w`%){l9gbb.\Sd5[>x=VaXP<Ɇ<B!fxs:ڷGkXS?b Yq_?_,_-ڬӥ~T1! Jl|DrV` B\ƌڐ0Hl66c-0>'J oL3FfF63N,e cE3jD˜C1+D3X&XWx.:XVDlC)B,v" Dqf!)#FK}Ǿ"b0;~M}<8U$JY):>vSkREĐ,.kMcD{^xXk]ꑬ kW0#-:8Ӥ'X}i3(ϔSMV/N bS0b%Zbti^FL۵4l3"l&}yF u5uߏZ% lކ!o-6j.B 29a.kBh"2 AԜ7Җ[ƙN&Pabi?0TFָE:/LGcn UP߻w|Hj5L7Lu3\κqG4*)cemBxY#ڦEV Q?|)w_9!P#WHhqIPNٹtPl0=j;ZvzKmi`VjxEWC ܧuz2Dt,T%wc*zIGfDͩ*ޕ`V5|B yZnߊP܆۶a㟌ug5cΗ21'vJ$=p?B唐:\?hγdt0Hzhߨ/3zz[07)u)HV-VV5> fq{ErTdCH-Nr UYE&P C>8~`ScXǻ όMߺY3$q#0 d V;<(M>pQvv!zVxqm,t<(7?Clt a`g96cA.nL= skNjZf FMxHO@eGfa87D@I !|tBim\9<!f7i=:E*C6hǑodYŬb zἳJ+3̎P҅<(QrR*b:%OI)גs}c;Ri4k伬+37.rg'>J.4.Q?I ԍ8I|C62+z@3Tl1X=ι\G{*k T^*9^PXx: ;-}b-S;q5*R$|=Jjfs4-,K;G"=>+WpRo2_ǵV3@$9 ,LTA5%l'zU):^18*:wز,u!!y:|yo]W"U lWfq.vYEpŏwqE>J0OFRnOACݬKb]s^_X1¾~G8Tt+uyu1cQ͑q^KQYH5E3ĨzG-nZŊ_j9 [13+SF24K_&Q W,]s/1xHG1I#.PCiF#b+Lw( c%_cujw|3F<h doQ^<>q#9-0 !DF̒ &ljW30Bm9Q'1w TY /Dhd3\p,x봉wh'r}̌˟C5fZ|?೟ٟ tgSu^}jU2==X}P70>;3167wc`Z Td-NܕgЉSРz F=0zZݱ%;3Q4:¬Qӱւbp7>.O(Է;+M;$[KP?cHKeqĮ/z EOh;;_)7p@ninя9?bOtGFmNDr*~UmL==8Cvbo~NHTbx7׬)?Oja$m E%:Gܬ">ΑQ$:oy$ cmӼ=(^8,0{aJ#T4YePI(/ehX涌s:v'joC\i:@L\Riih5uIچ{!uik3e&ˊF(-G|`a 0yv=j`EH%1f B;xS^}՚=Qx sXEj^ޓfP,7xΦb t iyfdlARҼ-26vD Nc߷8u`WM6x &Ϡ͌ =h cKPT]tIdu-S/RrruQ[!uIޑбjU8w~v4;o71ju _ Ӗs 0٧Mqd ݞе8͉(p| el-u<2>_fŞ'2~i)r6Zb0K:sh!u|r4JuIQ*eT% |v;=D~XF͠PwL!qddX I]8t`e(tw/zDjPLk1[~fieߢB>_k`3׼YveLe;^TWc`Dc h޷+3{sY9hV÷ N𚚚lT h-݊-w݋ _R,UNz1N~_0ǧ;}=x7>ヮMo v4:X9XV̛có f%ةd0̊>lhJh޸HJm8X6kOLN ϖ(w].Gd= l]Mm"Y70%o),tVZfp{8l8]fcV^ 6(M7ݤ1a}>w֭[ O,|_:U2w'2agFc1(k8xLB"":fbڜQ4:uYG>S9Ν;ŝ&)YD" N t1g: /Ec(7ݬó;QN-DsĬ23o{y'NF#q@o#Ybԟ)^kj1K5n(S. * T446oueT 0 Q90I{Xs^ Z~^c/159xaBe/&VխP%m% =|J*ψpN^ R5S51Xmm{WD)dXf);zO){ bm߱6&g2Iv] ] /Z}{t|[h{ Vd,RbD,9D]:ÎT鶁`2DeR>+CJl*AbybPV#S, fz+tZXL˄3oߣCdp ?z)~֠<'7ѩ"ՠskua&?d hpkm2\B,<ào&[,d'8'Ł\qMGǝ.D} EsjpnZyؤZ7hcьEc1jQZdlV_4ڮ,Eu?* Db}W.}FZm5@/.Q' D:zT¡eHEbs9ZS}IXY" 'e -= :֌n &N̢8L#64jFogD(ChF aejfR%S'z]GEVEiSEux1$'Gm6Ɂ(5j(把ҬB sA잪aP :wY ^4+l-!ʓ)&1^g|t(+ 猼֜D:J.L ׫#v}" qR>akώ#r JKr#J ۊYGsn1(+YvHMZ~FSO(86e~fkq`@[G7?0Ȟ+IK?c @B\ ܿs"GHZ!L{E6ZfvIcΥY?'RYcsUqc׽}X<+qTҌjs:yY6Oipr*w70sd |uO|f8gݥdB D1TPw0b0w?.qL|B:0 2/xXe+1ӧq%U88}Q:,`lc#KW w9굨؎ _bH! qKP,1)k wam Ո10V #bLڽ=;יC_K5CG$σmU^%>8k.|<0~ |НpڵX0n5C#ipW;d$1yCE'?#Iv\/ ^ C~rj;Wp ݕ(myNkR;H2XF}q"%1E!ƽ݂=wݎ0()T(;56G\5:L씬gYeq&`WNS"+p<Ҡ%H%\fUIt:z>u0u:9/LVPnRpMC:Yei,;d&C0d+s@{ fZB` (gٱBk*4:flݣE.k0kG ޓg>{p,89#22!~@3ZH3Íuzv߅IXK&avQ=҃o}ۃ:D;nx--_3ֿc5Kh/XRv^ ~?=4mEjN-B>_*"q7I,2'̈u`O!HZ;fIW]FC7"F)Y,!]ǽ藐`\Ģk4z׾ d40h_ՐW |Sy[#j:b9=oDfɯU/{4KQ,qD^gQ^&>X}vKt.'H %(w(TdK%q`Z5`n= ~HEc^~ V7݃8M_x-uThϳic>rw!W@8OCԋhaf->/.sH|͒&QSײ"%f,pg)50Pnd!;ft";4BFBvSfҊxP2Bhp83K'DB8}ܳ~&tY 4H} 'e/{YoqtNх},8xjd 3PWbd>9K=ɝ30  ݻw{*t.iy# A~zzӕk,' ߰IfX>;םT]_[ #T(qӘޱ;P΢h(bgI7aīWt S~-&x±׸Pƃ&˽Z<{t:GN+5؇+P^8ˀ䋮%'28ڵk[f/CRc_AV=EFƹa*X׾Yz_Cn!D\^>ZӇcx(+ 9C~n+d8Al<.3Y:%AҿtUZm*N9#Ʀ`q$IaFJB@C SV(zxbp/ٌz0և୷cZ/ _2J2Vۨc lٻExK_jgƨ;Dl]Bm4qQBuYWFs,1fsФFNܑK.Qzb#>4$OZH>Oۏ6l`юʘ `Wǵ4~ ׾y31<85p=_0OhR{MY4o>E z!/sG7XgQ,*Ѳe+0(N;DBS"&g'1c㇟  j%$ 0Nϡ&+^(%xhV6#7v #)WtۦDupG7_ Iu=UxKɀFϒtD8B%DoT+8̦r>eՑ0O(Ao]MFY5 _ySbαIhۣ2|P' >ݞ%1~?d:{!^q7)Ν'6lGL,syF?ؽ_>Ƚ//ʁhA ދ˾>n&EK h~ecNF]{5ZM|&MX#qF^Lp9qfU@e'dXcY0 W*.*6:/5Bv 2|_ߍw?Oq9h'T)dS[]uU>l[se'?o^#8OB!!>կ~5p?.:\hNg'#v!듘u$_**l1 `x ٲ Ys:J3;8@kęՋt"g`,pRsR{5t~|Rvő'=Fb}9GMY}#fUNNHȄd6?k?  G^Ց!rA]izjX3W`{<_t r߉_W{{0G^COD{^ L+ڊA]ީ,_stDUl рbM{bkadJ9_9]:7+A[ >ďstZLə2XK){0WUZ|J' _>::g`=O*s tM?3<o{:c}C?G V]D_W7<OxsFN ]XaxNV8'͐ FK4TdGe{{͎vZyWBZJ5áBЍ?{ϵ(s~5 :E!rZ-sEI t 룡0=3ʡ}8kt;%*jZ# !(SF*al:,E#&DY1&1"GcU \愮ߞRf Wkm1,Aάu\4I]SR\pY.2U0%fR4#׈wFňA.:F&=E['A<9e ZF&;eALw:eu剎֗:W9 x13<h~f~&.3iΒ->}24i( 0uBA dX9BX{61B(#k Gx(eIBI?[>5+(H!n4eϷRgTQu$k?;12WMw_"Zd.`vSv^~$=0z=!CvM:D O%oFZ# wFs pw7!쯍4x~&.3fh3xZqNT7/sv/tj(lMK]mIw D|pP=l%fWMXT|;>=ݲ F1mZ"Шbw˃sLzatȠ>ǻ~Q]{*Bt\EhBqB|x'aœ?L68^ا>=vmٌ8~]ȬC!z֗sb txl&z>~ר[c$2h-Ekx+_ٍ꙲f*3\x;H= ;9)GSD^_s L'<6c 3j(끒 *^4+T߉x/>=J lx^LNL=~P%N˳MiJ#"#rNf)Ű\R^4&^שZkoH Fk^"a!9}}ϿB3'|21<-ז8_Isi*745HGDZ`){ixP3ai.V'hkZ yYDХ):a$ek%-pe7|-/B4 8kսЎmWθ;:yLU(-;''5:DzOe6N=Ac |#QO5 ٺ0e4x:H^6Öt?<<}%fPSYXWn|}֭Nj}֯_:߲{2t7۽ `""^{:TY2s*8  $GF0 (lAzAla$@M~8u"ϫ߇%kNνQpQLGMa˲<)I[׉u _ EΉwf_z{D ^;3Gȵ9c(Z56*Lc|38'kK#l]+4~l`s#(K폒1Gi{U.M=m9HuNuŁ!yʭ9~oGnnonۿXTF?mgR/Oø蟥Kᵯ{300W/| CCep:{׻qŏ?]G|,b5V+v`. P0lE C\XHjǴ$ 5k+޵L[HxaE}:GW)8Zv<<9Evmtlv_B<㱊'Bٙ;gBGyD2CG}!x^9VET5#LT)k w݁O|oX 3jtt\HO }6TzDش]FiN9؞DGq \y[z-׼{ރmkLY0(&'LPlNc3 azfJ~mb1.FuC!i(Z,  NsU\5b1Cb ƌ`fɨ|Z׾ZͲ[=WU|ы^C0π[|:Mڳ#D^$ATvD8m" c곰gX@ž@v& g7@4:Bt(m"x<"?Lvn/ߤj(41J\FaV/m S^˞lT7#{G6aⳟ*~kus\u؜h*eD{9:12SrNՂAyX mNkQ>?7t쑲K6aщIDX|EdRɣO݀eOڈ´BuK}z-[i-,>!!l DB҈l l. nssfe)X>nBBgas:]:9^: g)eyd[1-5;Bn:7oK_:n$8a' k܎s?W G g4=U1c|7Ѫ㪷.fj3'ޜÕo} 7-r\u #&')w߅{7݃ >7տ|Š1g6ލ3c:xtr@hfI8y *go"$rS)4QP뫔0 ,8vTzt(Lfo: a]1}*C5BN(Ih4gQ;|cEDME. a|r' !J(^4 (['M/yrۼyR˖-駟[$*c \y:wc kb3{ Xt,')/}J/@R38e)(C6LdžkE .x]Ge06o'wt>I?O+ "-Xl5bY9LѶc<XKKz|>S+_QMuv Y ]h{Ņ>cH>Naޭw:c_L/Y_.)8ZO|oQT^Z2XE0bsZL^n|k9<q`>xW(^F=0S;X?qD={98JdT!Z|C az~ͮC̦e?#Z][/fk'QS&zJ58؉kis!:TnMS#>$lA%Js u>*r'?I3BmJuɸ'UbKa>mXW-8/)kPEUtρ*ݸˌaB#ϾlCeyQ~1hg0[Q}Wck.N!yHix>۴wNn!QCJuχgTea'{>Oſfs&짻|`d>qمߍlPeAݨMOa,d5ozi 2IYN%yHeB|K+G]܅'> W6d|R#_Oܾјkl"ك2Efjeq;xnT} Wj;ZDĉz_+ M( JWyXR_9ݿy#.~(Q+٨?O|Ehg. 1;&\$ܬ2k"JXr v$%d9vJOX_\ʠ^?a\plJoބ[nW]u6> It|cÃ}4 )$8)̌cCcGa=^ɴ DeF-[aLj! ֝т[Cv[tB覞G2RЈ\g܋Zu%fBz>Qj8gВg!-v+ޞё$1k \wu~#QiŊa ll>&qyssib,4ѡ=#DIz !fAX: я߂#f%1_cFw#Ų_^4/  З }{Q۰zZD2eK>guS63cu:_reĸ3@;-o8{,H/.)aO.Ne{.uo֘׬w~sʜYz@;5i[_cHYtׯ5\,+]#8~ش{!Б l'*~xEU/_B8Dww\_s5:{h/_1W -٩_?pt2Hf=y@uFf {>Oqm.9o8=BF]:M-t:IkwhϹ%~w4wE' >}Nns<'|1=C 88>fC/X:Pq:afish~Ȟ`6Fh$6eM({\rPZ6ut`}8bݏnpTj(ZS.UT^n|fPÛq%&kߏ}+N2K7mWo>?u<4Qcj q3Cbب}9wS)~qφ{1Zqy|EB6_-1d/]B%bu"58'kJrE^G>!҇)Ɲ~=Fiڶc'>яbpx}֘,Zoאk˿4Óx2-k٦%/CspXDJi:(w3ew]3\`N: عs'\OF}Y&sDfvp5g3G[QGC:3uu3Gi% .Yoܽ~.zdh˦y ,$:InK_RWyb,WVXc9M~ v<7q$ޜPZ,{!{ycv 1e+1|/Ӯ C"? r/ވ'^DijS(cC";:;hqz]LԶM 9[Q^kG4 4e5T aQBL0 F q[Q[)}DrGCj%6Ǧ16#fG~tT" 2Pmg`4͌Gtv&9vC~Xb[]}iwREu%b'9ew9'sI>pH?-GHk?ũ갴e#n;xr'nGyͽ- (7#1zZˎum+{u*6(њ{Audx\+vq/ݘQۦbOoNo읨Jط@vH#QEzFw)D8(uy=؟*3k0Eo'&{ 8 rجyn 4-YןUבȇA(h> ;]jZfQ/;>Jef,f[hUyWZNv7](Jz' õ?BT 郳c1TDreW%mqvNEE_P,B0M<[*|RҨs,/mAXFf[:%OA̴&{0 G06ںK>eZWkHFa'φ^bQ#Ғ[IS9}f<2¢4CԪ5YУ⤶(ʎXobWyO}0֔$~:46vGFㅯTڃ7y ubboCB]J5}*;3@#839uT^Q0"Bw`q]0`hկc;^aWIઝ.S;rJIxBfF uM'S3 C:66Xbf 1QAge>XS*a<I=Oԁ%,^Gn]3Ϋ5ښmBEAC^FmXŹv7Si"1gt'He-}5*=@x)xv_pyb׍W8 zEC#r|*s^v:\yUiKGO9X~ 2RlIϟo=TC Džu׽Qܮ IDATbxKVLxx5/X'PN3%i1֨ \K]6aӌcG\-=fzPl39G}u!mfElbtkMF7AwDP?Pk R!llBTzW++.dT0ؘ,"i{i896o{WI:rc491&|q6_iqȦos"]=شy2_jx^8z0x H,Z:KȉQ(WL- Z8gc^P,3C4fg'f*֬'N=%k}7DJQ;6/P:1^s u%"X s~*XHqKM2˒9Y/uezݍzlV2DB^xn54|APQf lL͈ #vh,M(C{pOVN^V5ڔ_ͳ._L3x )yb-B$m5Ҽj>4fNTw1 8=5=>ߟeWiGOuJ(we&A_ki:S†'pE)˕sflMr\*y\o Ajfbu,ym *k8pIA7f_â!k"$VcdVi'3͌PL#QY?oW\~2ጐ1=k(߹7aӴfj-F9~n Ɗ9mWe!v6z+GUAƮ4b:|S"F#5^COt)ȏA8YϘ#-p*mwtD(֬ @;kHpO2DRF7G s#u-$?'حv.Gyb W=WS.YօukV3% yKԪGk.>ljc{c ܡC4.gIWܬY}$ %XugKX#D3Ṉҹ'k.f=۔UuSos͙uvɺ7eC[S3DB,jpv$M7")cfD1"$l@˼=n`8zh2N"P[ނсPjqӑOpS2CZCCXxTFCBgBx 86]i&qH8Unc+ ["8v\p@|fO]׫pMR5FI#qԁ iaȡBغӰoE4ܙxUa5d>XV* sB!kk .xj "YmX"f<`͈cSW7n=lS:Wh@0WH=` ӛH&h3۱z`!㔠j 7 ~G xދRO){k[Mi$ѨMG -FO]o~[Ћcdžۍ5k>Y}kot/~U8Q^,hOlqttGO_@";zvyZ߬oӃFe7( >+믾Fk LK?Ї7xݴCHݑDJy!YQ(N~x{%g41u+u;h6 K2vA(Fb)H8ў789T"ѯ&=Mi r֜|fR(7«DNg:@ąI>(j|_9眃[k/`ݺuKۭ z >?hj.~FPlDZEP&}:LYoXkX)̹3< n%Xz:.Bu|8/a27$Ix |^l]VsKm&p¥_y mhN/M$n#Hdo/ B~~7vd)!]B .;:љ#֡}ܠ/ PBiO7`ڹe"(!뀠%,ijshcf>+yEYgTu|D74K$lmEfCsX4ø\mua7 }%y- `[6}R..TVϐh/sm &Q+vȈY]]*ջjؘmS47BUVUMRbuox2m>lٙ[G8w` 隟f8٥8ɖ}҈Qc9g}E\%Q1]XiHxjQ׵S1J1C5ZWt7 ׼RA,BD4/Zh֧bڌ6-ȵkĔװItWWw n㓸qn^M7ݤ&+ 7|b$>{iM7ިQnm-mѣkqQlؾ~kpPkz8 !|Cx" ]s:N&z<\o>B#Ӆ V$@2ݦ#\/6va{=d Lbxk_bR^7͏?/Mo_*[u3ˈ:zPMȟg ShsNFp/."π ./pɪ1pexl><䓪:;vһ THXQ61+H͘2Jǁw !sl f*<6ڗUa/8&AdkcڵQ5kx,1==2ͽ x?$, PLg:s i>7r0*%ptUU;0=ơL6D<Y"^Ө;|iijDk-Vb(8:]R/G ɶqt&lmg5Lg>kDvX?K0AiY];6OS4詳\?|S i Ͽ + JD#Nw$lZ̀?ώ6j[{Gѫ<3d}:q~CO<2$|̾,ٳ -,UPKv(d5lP`lS6iyMEƭf43.ޥa\>?sҝx4NmH-~acQ咐ШljHz6(P 8 sA4uFi s^{+pݵoUP'5L"`T uaۏ}x+▿Sesni:7rO`OnMTh`x$hl ACzY:'4F#rQUXz\ޕY^{AchsWpA~ ^G7J F2}5587nkW~/|V,=סs<E Gu _2ܔl>I찦څ1847EX8lxZb#N`rY 87ɵyh,9'ٲ>y3~94yri洇0o Es Ҋ" &TP,|!ή{ːN1UəP;Edm$¶F"q_@.7ϳҐ3ͮf{q<9g6W7x3>yǧn{nz> ߌ( -ƍՒQ GcZW e:6zX*~ӃpUW #kmY9gsH=x뗿BwY|0ԙ^($/>4z,0lVeak^e昤\Sw\Oi3.>rÛQԑ@KK^2\KfRT'$eJ2A?Fb#S@q,dWBQlÈ/],`3կ|+M`MԴkLx ilps_D9`}{kYs">3Vc]S㈌"T.*X222eyQK=ɎWiZVlkd+Q=: -[Ѧ CE:F8Ad[?DGkxMW^yrl:_B@\VޠkǮ.}:7b28s o CEZCx ǢӔ@Fd]v`'򈗧)٬ay E睋mwP@X#%(tCDO ꊦ:5$QkI)SGnj%I=4D22Q=M05 #>|7$g]6GSOn9():8>C Ġ{q!=}taڍ=]]|g/}×aD݆'.څ}Ԅ 1%1n.$19eLT KP0" 6&R*«UFuKb*;:Y)ɽ܆ OV񖷾/|a 7'>Ul1|XM+Ã;08q%KtjݺUsav>$"Ơ:!{@yZAWǀϔ?}w{X vImbki&U u2,c[ `.9o*Ci淢RB~rӬUt!x&<0/A[w/B&Ye6;a5Jȵ%#4+Ρ Rr19e8 9POFɓ|d vD Bx=y(Tf*_;rʦZhTV "L#q ῃ~=AӓENحX^2!=*/vG{4A^1 bȋ+VѢGķ=PvqHʵSFl$IJHb@.kcj3jvYW*L>V9H U j_- xAȖ +ydkp6=jq{@AʲTɶR,֎I.Aw))KE2k6$XӰ G5 ׳Us(IrC"ljе,L>2ЙfGX ]ɼbSp\/%!k6A(}f |]-N`L}y~S*?IxXw7w[c 65}[0Z19^+"R!u,2Q!>A32LG.ŮꎦItO:![uYFZԄRVB_^(lZFH`Ja RDD] m0Ce}#AXل9'g(fhu8=S 8! cC;Ok!&2Q7]&F2;a2G{:FEʛIhTH3u 8zukQY=ѰO%KLcǔ`]DaleT(hɉt^7#yfX@ [Kb2Q+']|~nsWYx -/Wk^QMXwEz'b =?)^?_t56ɏgg-3p!(lل+ L6;adR˅08{2)c=12ؔBvj& ,d7-kדr?D"^YčvnQ/؍ 9gw곸;qmgt}KV| /Z$oa @>/zx^GWI?;n >S~ IDAT{lJR|p5gabQPc\eZ *3e hoq{?6?Eַ.`-!d`ϳUS|զɓiJlފC h0!$#Aq OYi&:k,سy!S[2J7ⓟ Hil%BfORf#) KR40:.za|Pb=퍍S|:I\/t'~K Xx-9SB6WZA%ڱL9=# ִ݂8W箕ۿ Iд0VYޖL yaV1Ӗd $T 5 Vi1e hW]jأlB}xG05tDߗX_"TJJ*һ/sao/Ƈ%6)pg5ffTmѱqACdNjkJ٬ʼnqF۽ NiJk]ҩ\KX֩UG$GegAv8c{vcbCUDg!ݏ:m#R-- QR3@^8.F`JCSJVS(C<4H2{CzyZNÛ!< oף!,sw`˄̻qT*Dɝ;0*,@e쨦oGEٿB!o27DVar!!0E*uGL[?sݝ(9V\7%}ekA%lD2DT^Xcr AArib 4,F7>1믕gR15x\TvmƙcT6hh.fgAGgN}f}y%vɄ5$4,ωí3B&f6imbxJsƈ?fYn1|jV)BelMAӟ~Fp;-wUTC?җޡ-W?>_ =/ # os;pڊ~]z/vٚBex QYJ hJN~CeK տѰsB{Tq1mx9|䍸~z09OW\q%^җk3xz}3_ >w@OpUu/1oA>gw3KxFW ld~T%5L *:CB3$r3z3ߘhd-U%!]6Ms 8'yVHo2Yܭ޵್4]C6dƜ[/jȺj  yn?9M{-nF=EcImU \{J(xO|~&;C90B=G7OTf4@Fd"DDW#Z#mjV.)&O- >>NITaY ]ӧ%XluϏQsڢGPE`K~_VL] z+$rQ"eڼ0(>|6syl<7}sh>OFS>_9QMp3kL;TЏvv".৽]I-8HLCmWp-iuzw@ |s[y9:wZꞎ7{|w}dP{5V(aT ƨIMcEHp_u:)M9oH!esLђnohBׅFUl :Q1`goH8ofu 2٤u$a:-d~չ\ %]vo7FW@<.Lep-[ 9m{zF$F"$g Gйp><:ZJF=; G8R(!GEkF@ɒ{Zk6 )ⶤsJ~2m_4"D 32c۶`tNUtsS*8CF9EAyOJsl^$O;CU~+5%v)dL+Q"w6TL:2'[%љAR>24 [av#J"ሌDO7:ۻQ{cD {bY^}~w֞yy_Q~O];f4/.Ӄ/ElAN]2 [!EoY[mYMYu9$5yX Re:M)hC)VK[MFdd4wd޺]]ɸ [Y%W7-fTNGH1Mډ!L3;Οgw_npbmf1q^EqV`1c6*Ci6>_M iaw:vرmPvTߎs]?^/:62?5iIr;un;)o֯fx Js!%FsN Qۃp:Jis`Vy%K,_iDn~Sl V)|!ogUl]]PrɪrRL&ij)>f7>`+b_r#lٌvFLk]'B\6 /مeCղ4E5KDZMBb&tW65dÞYnMIPٽ#!|j`ԢhVUn9J4YMao!aNST{qUAqwj|FASV>O>B{RZAZ@ H>33Fw蝬 FA "cD0S75xH{Tz#bWc 9WԷRjǩcjh6幂KS9fc†IJ$5tQ<_R = nތ^y֘@"Iɜ4z;PzZ!2G}\@W[HL_&tiwaӁ4֌bԸgZC#^mIc>{-HWA&0:>CX|z~tetΌ;XDm詧 A/DǪ3֞1^e<<\֤"vɤvwagO"$@j`>0m QGk(vzl8Z)MCby dJSbbwnGvy%y˸.׵/du^Bݻ1!?Kjdq^1– =/k@1qw0e+RDriU%dg䫶m;>"m=B"!-J#\("9ܪQ?6FsT[*V[GtjcG3Z:UaSoN:imttI[Hݲv-El\@aR"y/; 3G^!մl3pڛp@iLJ;+6*2y+ "TM~欶Qϱ^N"A6{T yV5*K̔UirȼSZxz~߶mK uJֿ}Ÿ"Y0j/,:ksA6zh&U.[ךVac$fF]959t 9YStwuwj.Jp2ca*Ui=MO&H %qtXض_E~(c9ه?!oM BXm?uׯU_JzA ĩ456 7y.ߛ4@OBR`$kDkt(c߱}֣*>2c*(52 zC}?)!yzwZ͎_]w4-?o}a2"x*y( ϶ [/?޽ӑ >NĀۦ'_Of囍f^ ؠG3 }ZJly=UA JgR _URC{0ģ"^[OkEyل7diW`=hgۻ%d&k"FgdBe[鍏wuˮBo )ڟs>r6P'P9/}چU[̢hx`,d'Lg"KtR^n nC2i _ gT9r9ClZY)8o9^I@b~KHfK-c5c%4O6$UD#dwÙ'HDZMfmž_8/(?zYFz`1rٍ1k7"\^8]p"aD':FhuÅxh|nhχz=]z+)zݻu\5w#%R zIF q"dMSOE!FżD`jL92ul5㤿u)DVS*>%ݭiS9Y: 2#V̨UD~YNٰQ$P35sbC ]3(heADД,6&Pч%eyP-$-)v֥ WQ4,kC\*7BCBf,\nGD(;RMQs3b%{Pޘ\0|%YjbugcekFU1t,W4ի=գG Д Y}!N[#p1q`CB\P٠aGA!~9%!':l$L}XP6mI}Q 7#/D~C{a٨I"'#47{0f?WF&&Fl)v,s.k9Py]i?3Hb_ \. 4;DךL Jw#൵ c̕wϟw6 cWeﯘN 51aeky#qp?RlItX^<#Hw!m=\}QZ'T4f9MW3í<ꛝ;~}d ׮gT}ǵSY0zڃU8Q"Y&2.GgPi`:'|@*iĚZ*Ij~%ټ# :Qk `$пr%*Xjni jl,$4'kiBzYH,"sفFܠAA;6:r#6vLz;KQbq8Wn% IDAT&mBZH!^50TujeitǑyEP|ADpHYڼm(ۑׄ4e22BAEƮ15i\bbFj~a\qlM} ȒxqڷiZ(#XA'vT7S+QA|udƺzkQye E4f HDR `e$6R ^f{ZrZDQVsO敞.F:KfǭKUD2M TGt"՘kڃDI zU$B sEpæ LrY<RRD/w_Xy<%0 >LEO.սs?~6ַ]׬iKc j6n~:%H^p|nB?Q1?(%bI Œ**!۰hQɽ~ai,Zu~ v5W//{*{Iމ|^_;ۈȇ?x/׽G&TR_ʝ+4E)Dz8>4ێ/=%PxP36~¦dtc+mbdϯT7{/$Liw0 ]6}*O[Url\N6\uUHf2`IX"Cke8<4'6m7^L*z!仺E9 ?&#-fAr& eQ{Bp\q:x1y9:dǰ ԋ% c8g Rw%(Pg 6h]\"Kp|ޗ_~yl#i`1͛TbC;1D;xXp]hSH|k 1ri&;?;xm pzق xL,JܹSIlq'&KP@5 b̯%'R-E۝"Ç0OHjNLO`ށ\'7mAJ~׊3 (.6L1yPLbڴsճv'E$p![fiJzHXLYSUBZ5ry)ieߍ F|\ɞ9baD\B3呩J? I"!vuݽYSYu&:MSBnRJْ"r$-(ۆvkJ9ȷUm݂hy]HΟ|" 3|4hڱ, fY-D 68?OZC%,$rBQ낼E;ɸq/U<}ا DU'*חېgAE{8BB,)rXP!ƏoK;OZPb8"del+Sah>f6O Йg#MGFmՔhkɜo; 1%քT1L N dŮNf:ݳ+ņ޿ʜvUA)_qy7:z2 FAkp1^?2~8b e0$=lpYL0l V EtU{t#^qaLR=?Bt'')YI4ERsOQB#{RU*[q_||];O.kzo|3o»\ (>pw7կ}RAP3D 1%>4;n4 v 6̐M#j8<Ңǖx6D^>ڱgW6T\6H7ƮϽZzZaH|X栠V͆t2oyP4sڿE E!<ҺFkb C414F*c]F6s@!#QO xteGzE`./a9ڽ&ٰ-ǼUڵHL[;b]mnEǺXi\\.)-1O3S`ۣ%/{5 a o!u_y &EFӕMxّAFFMaYF2ާ-YEb?b mbޣ \lr!kĪ,1CZ~N$M"/yHVĀ݊nd!eMITI!h 3Xzy/^%@+ 5C>t-rPh'? zb;9i^xa<*{':N}jh!ė_y϶*h-S,رx[@xofH{ih[bYFQ}Ʀ{L,5yG[0lvuJ5iBK'k ~#y.QBJ4|nFdYGFOwy").DmǴ$'"U?6ۺ\@\hj^? 9ۈ}\6xT!5& Tm`'z!ۭ i+tewG'>)U8 Ua#HgH;<<4mI]HtOAl #Jj'a|TDc䈐nۆe  L[&ֈfǂhz ׵{+]G_y1(G2hH&cW@^޲bB$ݮټZ+OA!x!=pPPHL*k]Ih_ tU~;Fw[UEN֩kFiܓ;S%G7vL#C!UH(u"cVdҕhu_v!2)<򣻰%uqt!6l z9.Ynb:t13mBgY*W63ivG$@6<ZfdGv=LCsS5q){{Ѿ=]ǸaB@coɧ6K^\wJ6*B(?%8ՓRfNfLAř,nL ǂYwa?A`n 0bEQzCMM&!!/>؃(称Pe (jbMWF&S*̋4-FZPg\K.qiQ@ޟ̤QZ9]B܈*WDqjA#ZP//gQR'銌,GO"VbC`M24# 0JmLJjLN1ۚN=3 \؞"_*BTDV@MEe!"$1ѩm: |۔5lhJx4*h%WǽG;~xwZG41g@!5dJf9#Tcy,7".7cIS7\!Q* "# 2cɵ5UahLqK_{5_Z`<]޸3? J!m(xo5}3;i1FdfQ-h-92d!sSZϑ^4yQZtYF8j2vG6mIlB܅K"#Dʜ[IUvs-TP{ {~ՉQ:LG|^lS8E9ކ6 n Sط[)>:1dvը6ܞ̡p(݈\Zק=`޽hKfPg-MƔ8S=3)6fuNzIY .l:1Q;2PS޼ w'!Ay ж |P]Om@WQls D,~S|دPvz*C o|YyLRn`iDUr5^c_lX;B֘9ݝpĮ4_G'O7'6G4Bb[ge֞ELip+0Վ՝=)d]+})~)z0B:Ws66١Kn=8\@ *02sӬme<`^c˭f%(Þ)l8m]m]D?o)Ȣc*~d"Džx,ٻ]$! > lfvSz|U|{O"#cJ!I+A_O'z=w']]k#r.*׻B?N[c~MHQj|NJY#l:lwt &f Mwkt5#CAT$$xF'd3Ds"XfNHSdI森v;Z-2dj \@ޱ΂%x-ׯRaMVPO6hTS{qF4LQvHxRh%ޅB)W͏aA󑍉MXk/Bq?鶮JG (Fo3F7S,IR@JG4_=2s0!!yVz $IJd#v`\ǼE5?Z(jb{ nuTQ']DCfV\ ;(v`w*Cs w!7|n_ڱ)=4-K=Aكh؇G|SFxWR?;^u:/L u]!3Tf:\8O MlsMHUe<ǟFHƘDgc8]ѾV~(X$v0}8{)ܬ  ˗"7U?6"-^|UWU? @x+RKRHEE =Iz=($FAI`hWJ H f8`Li[+}5sfvUw !tdWk=~{eBTGM #<1Jq`3UREAi4V7ϻa F}3`.g9|TC-Xu2KHiaQV֘ \x g>ACh/MΤ4nھ|{j ܋%.)TpKDnd4D]S%ř'ƞ,ݫc(g pDL)vNkWdtD0IdIfS]ƭ. *D&*H.0q#԰EmǡuET`R:`TZk3~o +#S?sHg!-؇ +"_[DL>]VG*9FX3 D^pmQcN~}t nNpN2T>(ڍ #"8$f[G&;{2A&c@VPFDEړq[kbV@A%y&V>c$0s#]UwTY4{9|'q~.s++6F4^~2/H?C7_zP_ǫ~AϳyLs)OUs F@+_ks}}E-o8&cZ9!bȼe2gdo^ﵱejS8ӈff0ȣ5,#^ySɱ2v77T0%P?aTn(T}\[>=,A/AkctVPPyG}"{k~z/^6s죺rQ:8=ey ̅Ғ?r. v^5WYy<:̥ici@_֠7z2OU-\IBSИ/O\/6 }pL ڱ\ߓk@Gs/zј•.K۟:ȺR],$ #'N湗Q~h[O_̻PRKbS+G . j==:O:{SWe.*kNxŏT_Ϡ0=nKSkbag}ӏ._"ۑ=w'#ER:2+ X_&]CyS+ije%I0cg̃!o$XN.o^'_҉^fI׍ȲH 4}}ULK;Wڿ<+_;"@1 2u7vGC۽_is.Qx {)HTkgh3i5{m]Ks{(t4Δm{w2r[1:xۯ=? 7kq'8R1$JcL1ET²E,?Pۼ-h, P*K:Ӳ})[ +bCNaBl Gƺrm-]-uH+{0 (HJACՒhC1/@̘ D}PVސͷ+C6P/YN!;=yf | '<)Oƻc}{;ݓ4RIHsaf;-/2. nSIҁkmKku/olbYCJ;/йhҌ͘wc1;8}6/D>DOև on*@;ACm+=yHFmyX|f+o܏DD!y'Psv YswС˿jBέ$kr#kXNxCKJ ӗM|@v^o-`4&[řO,JEd 8a&cOz" v/X|[' ăk*,!-PgZU <)ڛ'cEHv -j<%֜kXx+sknBQy/b|Q`y\8ʚ"TDT]Ȋdo[W҈,ˑ ]V;2c)TQjǠ5ƬklnpVR;Ow{-y5O/4SbUv 鷲g\{?~mb?['E_E7M-K{I?~7k*khd'-NY :Ou7o xŎT"`bGѫוmr^²U) vQK h?&࿠p++rЩm/g\EAUbwa."'5NqqYMUI6YSYxjA{|3(TbvzԜ]B%sRϤ2yzБsz{u;.LOaDҖt;,dJ_2ӈd#H jC*`q }q*5쭭a3r zN'm4jb:,\a$!8 F=Rm/X{%yL0YǞ|[{ln<|$3>9S.฻`ߓ,|E6mvk7XsQ~ѕxW~C28OPAc}֗#Bɹ*'=i?W.ʩy֠ds3Ze^Krܻ483H>snyCgBzu|gb 0=Ӹ g/_G>YَI2~xߵ1 倵QNu uF3e`~%D~4-QTU%'=#L rPpINL-X>ip tPb"zHdSyƔ+޸ymT ;z|j6^y^w7%2V%)jvpu$h@@ס:mhqf r~Xdud Y&dB p SM, }t~m٤'@4X:uMjp6O¤kk"Ĕ3*܊H>ZMi14H4)bj h]3ԩ˯CB$?ЂV*MX>-eZ9Bfa691t& Aud2Îz-{tcpn^ ]y2{T$Ѣ04D]*}HkIP.O9u\]0WHXÁ{ɏ/ƅp~Vi%vUʋe|A9dXEၓ@uZYm*`H;m.|Q bUӃc#*TQ!$V~Qto-+Fʬ|w>+d%!bUYO6mq}J1OrLq na'-'&(|<2&`NFRGVv*s^ъ p#A R\*MM֏d 0{(0y|aABckd>!pB-Laڵ˴9|3^_C_ɫ2f&Pinv\)] TT~"הQCw@3U0bZCܒҠ+O?yEY=T@c!mԾt^]EQrPǻ!e!-m(>='H0[ p(R5{NY\$C`]䩋7r[J_wr|R4ػ}袏,cĢjOoޕ,<%Z9g?`qw_*_]h) FA΅pczX~zN`*5ȁʃxtHDEM4*;fILb2&2 #46kjM^ {d~bCS)mA"H:/rM0`fw[.j{IS}Ɯ]̡bg{[3YiOc(G">rz"tEvm _}Ks1!u|O >annyY?._Ep/y}Vcmok^~(޷ [aG@Vrv!ĆH79999_WcK_|WǑ55paNw_7Me/~.]\7tLo4c3{Z O]ݗ>OjW~s uCt|ܐۿ[g266peOg~:Z{{G'?gϿX4y {o*!vҧivJ|(.x쩧Gw]`2^o~4/K'Zx/[%Sp!Ƭ(:.aei孛dH(2W}Ӹٖx$SS"TV@Ja=m3ϺSܯԧKWe0;Qafg0M! bA4M+Bі$1W+Ŀ| =ID.Ix03B #( !CW7rT-,39/]|I cL}!\]Zen(Uk=FQoL%WE!Ak,-h@vCÐh3 wIŷkT:>}# ʬׯ,GccMTVlDDڋd|ndž|@`ԥZkTai$aGBLlzk4@ nbloBKԉ86%K֖qD O`xrMcQV98YW^zoSliLÏƺa=}lCLE@k}זoaP6$bvƫX=Jlz*qww`=0Js #;-ؾ5tXuA;\-L0(1"2\#]^>\6]׷mYrZ%,%`údzY4h3%]s|4m^s q߬ˎ9=6M }y Ҟ05}NeI߼wj{|+ ]2;S"hhZ\䶺N1Zba,^0%*/Jyʐ]<ʜ6(~7^~ q0Ϲ TsUuU5bT8JSf`/sIhT x}RM g7 IJc[)5T0:wl uX=bNWeo1ML"9lmVgtwk;'оz NUU+JKr^Z,FoӧOᴀ#gǛ<vvv0ը^Ó'Q޸Rij^ RgVz ov"[],YUWZZWպ}Ms JGl@7JNR#+(InxpETh~8~+`l܇',#g(=iixCV(,uDZ\\܂9Ԙƫʳ@*7| ,XQZ筍Ms: :N?_*VWW\ qzzZHF1ohV< Ҝ 4q5j^pUS"dE8QwWU34 g(p=)?9%9K`~(³lʺ*sD&[H<!]x5V!% 0/CR&$/~`R7)iUIN1kEQ'GGin PunI]٣iNTQF@EC"א= 1z e/,B>ɘm17>,duȜnk8c}r|;żɨ=qUiY)CW @eBJfbA=-n̈'`SˍO|'cA]FJ&-X+\<Ǒe鏽v_c,禙D Y[`"nO}?]TJ55}2PLk-DH ZXHKo2m4ϸ.&%]MХ.1tsHܓWj}i⛼t/Hq>ilz6tӕ>N7^ GK3, cu잍 %΋a[=(L%Zɘ<:D `2Rf#Wy#]*;[_+J<$&R{V.)AZY_PEZSƌ$e2z2l<-DZ K%`qWq z&ȱ]~0 r>z~eXOiInL#X9ӓ=2v"Xd|tN; h^5^\#,m2ݾW;}g_KQ??ykgLپ=MiYr &l~3wp /7 ml^1ˍ_.m瘾;xNɗjw7us);@|ΚɁq;j( +ë&= bƲb'fg rVP5cU\bSՖk7/2V2H_:#ǵ_:pKu(:hafLw*_z_ʗU!@4dOB 4Q$ #˨lM&z&W_>Vҡ Elcok?#BF֮]~t"Zmȷ7o!!Q'ˆјm@PNcp^ڍ|>??Ơ7Tz;0Bu%z,$tko[W`AΏ?q?x+Ow} x⑳:6hE˳$QZtN{P;mu]mbҳh{zmTw71ߗ1p{o/1q0":q¶NFc9Ь9}2s='UhmWQ]`ZCL,ṠTȢ; Y@KxfPN/_-=,.,x)y~o& ,Vn@}ED"/8H5 ϣƵ*5Mg7t:>(9W'!>Q["s ZRB"dt}uQc<O< >QLMMNU>5cʕ ~s/oM+o[uJ.Gԝ$+:V)էmfcqҝtHϓu*om:ZS%d0ʒ a0? Z=dU(J[Oe^x;p\}?AU=uN3nc,#93ut8oQŸfMs<`tn_"y~N1o;[4v14ka2ٽ^;"TY+z;>{a8cES7LmhFjkᥣYeIP=fXYB@ LwMY_Wa?DO֫36(IM7SʾEܵӌƳDF=N/ߦq~7բTGߐ"eXҿj3?A%&`qZa2Zt}I.~NJ~1`&kyƏ$w`- O:L<'+AO^x4cӌ=΂V_GL= Fu&.Hlkq$hBA뗑\z ;{խBRO =2jdES|D}[Xvtk(ԧ.)@~KԲj_<j:~ҏkWݿg6oH:Xoa 7X6R fS[j[Դ51ZAg2I}n".>RQADW?J-{Z7 ؙ_A#rAl5M"QgD.z@xZiq$倢VzNK/ۨP) 150āʢ^cfk  7PQ򌥶[C"lN-f@ۺKR]vd0VNSk5R#̺3V%l}+;p> %Z˜(k7]de‚JR@FBJ(h0kв6P < 4NJ-K-Y˒ * 9#`iTM_&µ1,lYH/5J!19>4 Rӥ*K)P-ֶM_:7oy/NwcSޗʴ+YZSgmN$ϰusAyF|^8+6½:@I'm_G󯿎+ W^AkA4vzˏpxjƧϫ1Z.vSɍ킥˻K9X,w&MZFV% i̒6~|]OZ Y|^4Y;;t):(B{2/\# cqz0FCFHs[]PNE*a{wlxr*)lp?Q. \ă@ Zu˓6'ӐX ]1k`#bI$BGϜE46msÇJ"2nK-llbcGQ]:#lĘӺ ƺϹ߱=# ^3ӆ&n;5 Sf$¬FG03,!B6@%?=C3]j~!伺"+/]/I_F(CZ)ph1J\gl,`1 zcqqIڹqҾ)"rA(@ey-VMLmɿtZKZh..z5`6s>oQ֙˵]CbG <vH"/.0nyiLedZcl&1;Ӹớ^SsG݀cs)j@ke]`Zǎ]G ʅ"* h΢QѼ~ ֕kH{M| ]^GQ?u rdvّi/%YR/2mM+qUnzd –l) 23 x諶Ok?wnzwꄢD83 2Iu;5 )P8ƅ7/~y,zdϢEZ*k<3 L0N2X[ KEt&LS'peZl^s9:ГT Rj%@A.LR~sHz]MnX[G(<`~  ŢJ,H~G dQf #% {=вDhZBTl.n^"`rT,aKœ6P׀z%Y Shw6&|WjM9%૦qrL^K8,IX[9E/oͳ⽗Kb|Xe%oOI13h-X*%,iT<οxH4)4s\9M%{˹xI[v< zLY\Y ,H[%S{M>4TZ~[IfqO-H*RI<+;'%ỦZX&uFvuv5=۶eAAx.Ɵ#oA.c!Sˎ>Q*f,wv˺"Ә~$Rǩ"xd].{ϯEuqrE/0]bhؽyb-b?ɍOo'3!͢sNb#Y_ƚoIޞyZVu~}IL%p.̢fXp܋u^rU'& 9?Ɍ70Gl$ZuTO&ϼAj3b*kCG~_ /5 qԷX @Сe^:;븺̉SR*B)[IQ;TA GBn)aj tRE&*tw&aZ!]IƲA(aI@9BTb Z{M 3f<}#MDCsc#`_`#/8XKh5bRWG+4@݀0ZB+`i@E]ӷw_C uHI_M }M.io,>{S# tbcMVxi08D=-Dl,Tow3e솧s)LX|u#={]2hxwl}zL\y3 8@b޽;Y,jD8} \3 gN'HSB侵x뛉I҉fµGE7\e2vN4/Wg frp~cef::4虩Or!s#"FLg3_$ʞ(Sm_2J4^"ZzlGpeS˺^*u{eԽ3ܥ=iF|,{_':eW-<0My8aCbzy~ ( ɢ-,徥r݌gnay/6o-FA%_qpژ.a1#giJ,1lĀh| VlwoO̬  d _xL37o0amX`\T{t-r>[ե4)TIz$0ފco#"(l_n@ћ_LA{ `إ"5OhyRJ|ds77ZCK&-[x*P=~R T*:?t_꜐iR+Bmk* uQkS"¿́%?;`{:`4NXP@*unh<$` r*A5Pݺ^Or }QvK+fGVGbzo$7ZM< ;Ҿyi:~uPc c&o6,gq9]>7<݉D^;? LBUi%];m&)-@2v?WnbgbD3V:YGdRų  g 4'8+>[ if  cO3h3k=bđ9fqSOV,W㬃i=:Wt xpe~VSt9.=gA4grVQ~viܸոQc] 4X:٨Ujdc sqcwnHڵP#av yidXf?R,i>L$r)fɑfFʁ3^:Y}ͥLF&3[GwqXBFsY4uV&Ɠ򰢺{Uux&zh׮DL{9띒:XK^fYRiYHS2Y_{puOY$k cT/X):S6jASO>kMGeܨh/`X" =i:Jn~I;N˻ o[}|Ƀ;;Dƿu&7ry'p0Y~}vKW0v\'5βsi00;I`P2u1yclNH6oagܲʪ;`} 667R"itTݷ<$4l32P"o*7{yt]BrT|}cA~=I7@-M4Ǡ\ulOjFyUB ٭Xͥxҩ9ki{"vd̃Lu7(7q5CzrÙiytPAJp&-)te]rrDwcUJ]ٴb%,ulWPIDk8 ֑5jQ6z"[J],̢ب!b>-YlcͿ1L˸_7ʇ[@h2 /yhr~muPB9yεF9˖C2|ky5I w]6ձGp[F3w?tadt2L@P+dVg SPoBZRO&}d1_{Ӽl:zt$I'HHayq, N΄1׶j9<9tD+SNQXbYh LKJFn-[ʞhJ*۸9 D-Zn}UVX Z3`6g V(zrٓuF!^ OCA*?Ww*yإJWstz$J oΞU|u3s(ݺ" 2\3p!P77X5 H{Cᛦ.[5^ŏ*tDp;0m"v:ed ݐ j(@f]Fn$W4<1vFcn \, oov[hC ɺTA\,`^EI!VL`q$}6.$17G.ဎ#PVE VU9 8I6H,NYF_JŲΙr 7yFWj)[ƽ\3TV1VR@rXa(oǭnRsNO`5vtk@5* 2N]_uw@ȸ+@A]a,&[ &* tpU*;xjp:kV05{=[B@I&H]H&)J&hdF':] CГgbmaaH>ʆ7"6z;!wa壭6͆A3tŀu,/E' QZ2%{?b 7\uh +W֦ (Q y_HyL t#~cZCC!Ɣ=w.wr%!&qV|qykͥ<_\w_GW2ƾW&)g%FI!D}6wZdߣkvj/e88rX˾^~hs'-8܆A;ϝǤ&JB")gKw A\| [-"VDHˆ0`rْq+َ36nuqh6}nLDރ!Z-TQkT:XDPo6qC*KUX_ǰ?ԍ9傲2L(HKo'. Q3lȉH(J~//˜P>lW]d@JHj^;2O5VVћ_B[pH6P- ]_|knn_*z8zCx &X J{>7-Ŕ/6aV^aº nssSNMM'?l3/3S\)[2rz]s&u%Vd-SYd1faPd( 5|~aiKLP\rߛ?!~?AV2u.t7ߜX;KVF,v'ojvkΒu/ b@gfq/gP&;G@4ga(dj# 2ckYfwab< `.d%EöS]S d\̃/]ŶF=`Rc,#5ybuҸN:A#%pTm_E*at}KK %IT:,]*ai~yp̓ʝkR0Q$jWl9*M-6 ȥ8cvdhԹa,wUM!:3e<7j5ŀbUY}.7wT,J,JRX[͖&T+j b._#W1s̃պE@ C~ҜK wۨgEWh&@;ɳ-[Dߩ?*a{blͧB&CGB\ܘhQ xI*)#½6.êީ.x8:J.+P 8$g+$c,+U%۰h΁W`|~jY":{l[0==Q?8%z[nիr~+++X]]UPrJ&S! ى֛B`se1:R]RSa:#dn>o^/} xWUMl ^i}+CI-GEylG42Y@Ma$pmXgrFlw&fԗf.6Jې6{{RVvkWQ5PzaŪzsX=|Fs.FGMlQA" .3gQUh,`%bۊmìضW@w9 @*+\i6)rm7`2Aז̺vl9+%H]\Ĺ\WY7GҞAFa& {^1OujqBuQTb:,.wrq?ikL{ZwKPM^g H9j\q}yH01^́9F'b 8y?ɱ (015L(+JU2>tcq[.F!Ծu k= O$ }wrWo Q-N#-3(.iJM5+0xJsl&qUa&]h)_D:3a`T}w|'xN Je3A 5tSi6M4 \ib"+(17)m'cm.|G2؛PbMjz0^*0b[v~+q9=-HHDEI[*)כ5qk.ӎׯwG.M8s x~?V >5]F\RDcGڲD-hȉӨCD_B{k]<՗_Pڱu2>~s9ؙ7Eƒ;ئ7& p 0ޘ߸_*#@ȡ˳!biT ո"+/azv'Q\>.k[AT0Jk]O節@l%ڛPC31T ?z&ĶmG`&su1kP2I"7Q(,7]2S%9kFvc=$GaK8uFrFcaHvpboFd?/3G^<ȲyhY:,dnyP&Nnt B~^@/fiҲdmZJDbP7 ϸH8VV=Qe "n"_Q n@֯! $CƧا4BژtE2$-H02  vv?__ :,krr8-u`rr/>o:_d_^nA~LxWФAA`q Hm9.+U$4bm]m2Nc}忪"El(ͳjRQvn)fSS ݓD+WO.6d[Y-|ljd=eMJi 5P@%9UpgpxF@ 71v=j)&6JLY W)PM4Es߷WG7rƌ Wװ2Z!( d~֍5o"t JH( m,ϣ"QI!ghKiE3K@тOuA#&}^箔їk3m0(f GMBkX#5pN~`V$j5=3uQ<%cǎU `iqaG.\ zjv9C\9֮Qbuvig߮\>k2_s){J>"Y<+᝷a1 sD^,O:c%3dcs]I>+baQDy9^Ϭ#Յ0%sl#jwT&Ll\JcZ@{e+FMPcR[[(~N ((~PeuQV|oI}Xaɕt>v.uV$'lw|<={y^w< FBG=u.{|Lu\ǡ,Ii JMn`s ^5#%ucdLnE*tka" MREݸe'T+\`' 1"^^7^ FP1o\~W+U0UC ͆Nu406LDQ&P?Ex("gI#O>^/y!Z > -]h'7ZE߂jQ3,2aEekӃ>=\c՗ѣ->qTwqPHm/7VBn_}VQ,=KҗQbѫh.QuXx/1 >öM-dq )-\&B!ϰ; W4q+Z\ FT֓ҸQ̣Rx,l|INM%&(s؈$*MZWG:7$;m"_L7PŐ%pct)y~zJcr=4*x$Jaq kG貄qCTP9&&Hcz&7̸@.cq$8* s!gO̾yCzPKyݓatc(MG+7`]M{Ib M5 CZLJ> ܷ{W_G qTw4ҷd=y(HвtXaɕ;Yގ5砘IW,]˝-Kq3--\ rѽo7&x)D0][efЬ& -mjCz7zhPG^MAiZ}by\1U0,- fI\W^ڲV*SD c*u"K*\ e #sr%˥C:ttfiM]oWP󁀺Rz!Wha"S:2և:r⴩^l$ӢA`JG&)_]"W0|KWVc~("ǤkblagVߛ=$ -}=EP1!U ȮHKLlAyqis)wͲ8 ̐qx"*ĸ|Z9k#??wM7,lK`\6[| (K2 5-%1-ɤl[dČ_/?,w.^, .D)cu82d94!pɚi ORjBk12_W䫖o29є{&$TAOWN7,ׁm78~}YX*\k߼tu&.@<ҪDL1Ʃ.l\TE.a9,[AYAGw"|[4yb[tu9pĢ.JŪ,/1F,?qP +DUX[1؜*_RᙚlDlJW|{U˂e( .OMP£.لܐ( (J,%P7Ãk]3TK= E(H}vqZtQvۙCrd"YNkF[%Gq;Hf7rnWRFE(WH]7ֹ˨ 0붤_E3JFM YUiύob'هʀgP1El\9Zg@"ّ۔`׏+G:Hw,t2 g h9YX Dx.%{˲,;l]} l类!GCp!" QD 蓠  A$"5C4vO2Y& oV{sQQY]q2kϽ眽^{s||"̏wjvH"R4`egA}||!;b6XL_uP `EԻBc.#d 'ĿG=zW}SrJFm#=aF9Td58\[`ǃ&Q<8]~Hmt3"B>!ш 'ekeN!B*K9iD#cOG)/hz&wL}<#8N-(]j{}a21JSј\22|$FGNԱcJ4t^9'ʒP%F 3(Hg)OV`Qi?jĀ,0X^^?#K_VsFrX`ƢNb07)*T bhO`hlD:&֗V0BN8 @#jc phbAs Mt1|p?Y:Ն:Vb1[^.bsN-{c׳-JeDr*TDPdς#IGǔҰe\H/1LZOaJpr08tjZ*!2r/Ok 5v%Fș?2Jx+ivdIgWgw;x$[6NC, X9QPcFhR2OI;i')qAhEt(:?ѫlA2R@ګЉ>b2_`c^7ԹZ׈Hh˜  ;/T38~}]L/\+( T7*YZEQniqh$jL !*}Mˮ7Bh]*5vӽ‡4zvw6۲9j HFQT 륚CD&@3 B=L*P̑g7 FYEblcUw[J~u @7 IDAT#(wUUP!uX-]T1-"&)%*&=(oHujFr t9~ 6vO@?c3b}ܟ)FHO\(s4>*yX]^C`i]<+Wùt ƛz*?swPwQtP%݆ҕE1ξ Ho}`z\@y"Z(1TrNN1e6PEnc#nXQ#!RC,Ȼ{b<ʼD'0sc)sdfqS%&U]'V 8mjA8=DkkP@XsfAPޝFoDͩl꼢C)McoTU4Q11L cNqX*H*H F &w/ϗ'}Jv%@-]1݂~e*HdU\'y$*uchΔY[ I#L&1 :[ нs|YgdkC?18dO7|sxNP~L\!:P9MGs_C /i4f&TA,]FOx[@iez[О}*%;md'N!_EVbq[V\KWכ؉"u?ihu .tZ2>C$nӲ޽k Sk`1ЩBjf0gu'5Jr,F`+Jni͞gT.Z\4N'LAs csa ^סi5m8\ U)3ujcq;X[Co.61̜׼:?@ynE֒^@+2Xc4("MٮPDe)q0،}+hUY 6>ogzt)}XsWPᔊHSlZ+,"ܾ}*MD7v;\]W;rsA P 欄ݎ$QQ;, d6arʣ?0Bb~i)&j\ŶlsbYn xdMғ=alx߾,~1^A/VcEX:_zٛ ƕWN!N$)MN(0O#W08Fu29.[A@·⚟kJ[aӜ1~ҵed"b|҃/}ũMz^EeD|Q5^xl\SEJãG),L%D#zP. 'fw4hT>fsϢ] > *,%)m/`\{ߍR_s<-K6 ˍIOR_Ъ O}%҄XD'hnq<_0~7 <[;x7~I!X7uͩ)yVrΔ=煭_sCƛ`$] :[,{w"&zu@Ɲ P1XZB#2眺xyS<|wE-@^{ ӳH(yϑt * ﶑ @<-\rvAogye9[k_6pw$Y`dU%C![vo 0ҕ{:mlom,Huy/wɘqb[W9᭛ 4y񲖶h/=BxcconTp-8_~Iɔm浏~EezY RMr|‚vMSώ8[a3cnf[,-*vnނד.f2:FfLurW)~p-Ms&1[j{X}Gw2N*}oR`bI~ :ײ[swNI;=- t\0vTD n}X; $=F' D)F* k=^e@/ QtuY.%kLiNu\+ "`ˢc0}Q}Y&e(}T18jTEO/>'E"İb_RUnr]$\^Gll'!;eSM3 ytNKuY7O]~sda.k/E(4ERDG"luy.wtV?H ;.>^S(D1P11o? D  +X};<R1NyƎGc'Xtm!b&W&ؖQ˂-@L&SӇ_q567.f 9Pʷ'!8)zhsJi@忏nGh= Uɏvdm;?yyX#NR2fXDx.![ 4?PFuM/`…}'O@YI"wtMwmiq&z}U=i'@BOQc e:FirgӨ0MqGsnr-&[z hQ&ZzaB&n߄/B+){h*'8׵& p Z^bigN?&TGp}KeysFVesse lLF<ãDe|SFPZAH᧫̬iPX5#Or.Ӏۑ9_DZE`qr b ֺL9mrFa@:~5.ypiXS'&jS,>Cыy|9y.f᠋MbܻzU48jA,4.8J 0X? NuZ(RKetlLTqX|G<4?ac:<tmHhT6?F1׺ 9Aahr`O_TqVD2 ?=?>NIcb܅;(Q~F6_}Y]T( rʛ"ݞQjTifFG-VkO3t$ sy'vj=(}> mk?Ƕ啪`mfs(acVR,6 ΌOh.œl9/>199%L7jHvvQ@G@oҳ5*ua0闦8fIb|LW̗i`2Jhe>nJ}Ҹw^tJfo0F ye 6 L&f?y/OO)~.V7;x/̊q^`TĴpj o;y\_ <ͪ%4%`cT `tVyy#q8G£wF| 2?tm {umydr쌊e6Zwo`mxTb ":<9<2K+7aހ/ Ĩ2)s̵w<ڛ\xhȜT\gtJ6 "s3nP% 6>ܯݛ[ZWi晋_y K/!t22N[~ݽ#Y30h@EgPݐc~} Ի~k0ۀ/kSyϓ5hwt=>KϢ|z QKFs\y.-w5S^hjji-(駲,:px . ھ=VqͬQ>u]G[j͟u=f7NH SgvFQ~sAE;'h~:^Y$ gјUWV#7}H%Tb nmgrSsǧKH@b!GykAx<?rU354 iVMցRږ\oE761-FĒR*XA~p/SDXqW̺9J!)`x(Si=D]SPUF^iwT0 NQq}M%Z,zzW_E:7hPn^BHp!4&^y琉ATjb4yb d|?j?Z(8G/NJFǒ*byř ;{&'nR. xA+ϟß;ksg%@eƸQϾg6W6Ħ '& Hlnncpy"&Yc}X g(˲ka-\;hnczv݁<s0b-ʀ;A1f?|6:Pt7t3at v~q#B_tÀ~t{SܼK|G ]lSL_x\Y<^RZWߺv$.Nhx'j/@O[?)r"~r3&zVN4QjOiL@䴪U]|Q ;Y-EXk*"Y삢r2S݋&ގ/t 1X򆶠WleyJiW5O0Q9VNI4hS0+bb&Dpejt)]*3Fl* dO fo"^_CE9$V? !ҘD_ە OOW33R2hJ?n!ބKSDXWmEbDP:dY}@k* -W: 8?~w=aQ〩a?k7=ła #+GB518xu =r+3Mk5$%K( HbrV/I 0Fq?Jil幮{v:JMW[d-Z^XJqwSkb5̜} FXۃ ^ڨ5WClj<_N9/` xy56,\l+km1[;&Ab|{#FVN頻Z(3(4pI\jay3Tar*EPb,&4e|Eg0$Frl̴$~SXzG̣)g_yK%#9ܻF+M2c#y0"ڝT,E=@ZYw}9\bdZ,[rA gQ('*&V ]Cb }HsjM3_ kN`\BN|?h!]Br4ν]PO@hI`TJ*eZQHZrVCR)ԋH3HfgD J5TeKʂ;96+ O T/=:ĜĶyk"Re[^T1[[?\l/TiA 3aTZ${F *rŞW_nd|RCKKUR) 35DMe,Udrp(]( hC?4u uL!kJs"ì5ۑv*Q)$ч}|ѠwKJ mu1vGܿL^攅cg%_]fkuiS2~q]SO?[o-5$w.ȥ&Y>ZT1h+o`rcch}$\֝X~ xtcʆ+%U)kR/Ų̌ Xoh2ҽiSUD]]1&b`R5:## .Ϟ2mcrobۃ. Җrv?v\G;ԉ@42b.AY,FY7Aū0]P)z9%1)@h`]\{p_b`]AVIEujLfeH*=9&ы5Bܜ4l g̅doS8Q(װt&4:ۈH\|8oOEm{N" 95ȣ:#D݁=Fg1o}6k(cY85k=SrϽ_s2~QqsWҭ66,'+UPG%,Aпeue^,-4^D kkN[ޏ1hm㎀^} xsJEt5tp 9 |ӋhGE˕yXh%7M˜ƆuջwBXxUg3撿؈F6zrG;(߸ZE%C>B!I/^Kh 8fV9*mR]?FWT@/QCK60P:@z~V<@I݇OA6|_q r7Bٹxo,㲀sFYeI8e>,߼ܓW9)>3zNIiEyk_:qy:8:3c?V׉&ўp^EHtBs'fEu(;zR\hJғ~}4\{LnU1e.Tվt1չkQZ#K 18udu870JmdQ Ac:} vd_.v׫yiΒRS $2%a|fX|L^3ԯ:VDJ"XKe$kJWi>;چzOO5᝛Ǡ>&QҿiI`.@ b$"im𞼯q(@J̥J{"?a)IWÿ#`Uy3@`楈aE\۞%gGf0$MmԼ|;F]sNh5BP*[gq2?6RH2~7^ O4_PegJK_1W~vouhl3s5L>ʫŚ?,jlx򯏶`͟;pXڟM$<<&1]&URQCy){A[p!z M7} nC, :z&?ISͥ#n摲'8y _t sYG**r>V&_GK@S9ud /-潇囗~k݃r;&6P!fT&EW^HV}ϰ6"A;I$7>#Gi44'Fy_%$)1=_CWћA_uE0!эvɟKȸZ^B2vdM)TKF#P T[fqm^Q_9)%P饞UuT{M vNIh؇}~XnFw[xVO3Jۣ anT@w0ٚI*ϱ7 7oxsg1{{&73Z;.c D3B/ʪ,²Ў1fR9aǽ~)4yUzԃ1}b#iȵl&өSp8Q nYhN)XgN%=c6d>BjSs>bd#q=G7QC5J\E H ' P&}|y3c]^?w/?>ο&f}Al#US"KP'qy?f`3ny0Z+}{pbJ cH{",c9_DjZUOs>bgH6Q?3"Ic* L ~EawP9-(aRj9D㓈eu2eb,`laW^E4 ԣ"ʉobvn:GwKgP3̝EqlK7n3-aW࿛|'ϢX7 ;֭Kw2N3NYr'_UrvX騼>"u菂x5e;; 6ɯ3kNI ,#2$*"ӽQuwǭshܳc @IHSN%?$A {W~3(?tFF05#&Ks=ң@55aČ\7M<:vZU0 ՐϢm;}TYSe F|OuD {ΙDdO}_S0".@ FaױyCd~ Ŵ/oO=,xut½Uv;7/hkU vet+kHW=cPiSakK\1- ;>2+OQk.c~pwYEzL}sgbaF8>.OM5ı6&@HbtK\^F> `7خYFfej/E}񒜻A!s+]m &"-nQ鲩p\xZ c. 쌍˽NS8% )9 R]ly :)%}g+ #PC-:*5P|MY H9kBpdv `DGJ0K2)O@(Oͣ8qsϦy9@3:ߌ_yRYPL{ؕyxjC<}dFF4T*ӄQTWV/^<\P>}"pc*6hkkn7P?`.}<3%|ocQ7j5N(*SCBJrsSs gH X:i' Q %v_4W :hu1R!y.ɌQzveQGe@I#ގ`Oa.Li? j?o1P45*FuZom PgYJ-$(תNc FMLM'# xƍ@~C>j^.9nF,q-xjX%D @8BAâkުJ0g8?~7D<=/#]24yE|AC>;oT1+r26~&.^οQXOzcg!!DPm[ǁL50i+UL- XOd&eW)."sP:]Ud=TBa,&t5Y Ԩ8b;#$mB ܒe37:x*`xl:2CȈ?}  *º-`/)S(݌Ĥ:H#S4W4QH8ܹCZ'P8]NOu0Jy+qW[LbTVM*%LR0ds>˞KjզiNk.5vuM&?3|NZC/(.@, - 8geRV>zwr.w Σ}vDm{ʾmll:R@cv᏶&NgY:5P"bA5=%oX mvk_: :=)1:~I;i'k_p:,$Ж~nw}i ߔJ(i7\m)Fofh84L!7.Ǚ"mrT۪yaGuDjO>)';L5^ɱz'*n"KiJmbMi(ǚ *ShLϩžǥ5V@ 2(;1y|3amDS HtL1T.˫l_-9 V̪eH[uߞZMx}֎(S<)!^aɻ:Ēo7W}x.&P/YA<{c=twb8x/ Aî/3T̪9Vݾ,=RgJd|*J:Pbc4bP#T@6},N!+;ϜD-Om&7QYTV3yƁYudX*4I҈ r|SO0NL":,s^£S:m":1b2h9l8U`e9y ,N sccE,6k 31`OeU1 ݳ/75b&c1*  kͬpܲqMpY\@"ͼ(},T(}"aU:/WG)J9 |0ӧҧ\JTd pN νOq_>U<1?_˸PcyLn3XY^Eqr݉3Π|0g

m T d;i@^^4SbE-F$0҄x%CR)!El(x4˼i+Rk# b-RA~jfKQ:1`gjgƧp[(nCAI@1k%v/Sd϶Y8Bfm9D Ѱ=Jy- qݑY:t*T[䳍]G×5dEvEO] E߱**QE$kOxNF)6$򐲝a'yzR9!3̀$\:y-.Qt~GS97]\~RSU35j {0 b35RiyL֮p9 ?F|Ǡ (~B& IDATmli!aނվLEM"w( x"펂?2} >~:m?uo1NBǞ}w[=N=~45 X*VJGs^Ma-?Qyg.{Dq|ű 1a'?_9}gǫ<?3Qj$w{j ,WF_õM̾&>)N vvFs}[A_އųX^#o{ b# w3]jiX_frsg =aK%7&9셄Ϯ9FpL/L aHK~&2AGA-%n6$9-,@U̺X){^(Йjs%&oX{4+U-R0|:itma#)v5r P3`%HhFCpH4FF ҟշs?G: rސu|!r'SXBfM=Y@sA-πE?xN&'PV9$0ɘJ($XI=tzA3/PKԩ;ab9nČ.*Y Լ @߳O"K'u;?t=o;J c#W-ˌwslv:wc3Wr[ݜ6dQ|_˗ 8g).gh|1rX%1/*zI,4UXPE -X)]ww^&Bè ~sugȟ#@D5Ƌre=H;Ap4֒0Be/zT|֓ƻQes<^ ˱`WwQb9 ĸj/t[#J]#xwS X l Nt;X%\?2~Ϙ Bcr"S潿i  kY68Fȑ<(Ɂ3V?OjVJ[̄UߵtUKc_ni"‹bFN T=Di~`#x̝]*p/~ŏ](WD՚\WE LI֮E&63MD=N6rX2Y9i'WF{ҶsбF:G?W^$nTEoP5 6x$F=Qb" R6ا1hI\(C"+Ky}P:c'Eyo˸0rh`֒Je1(=vć 9&1tA~q1+{O#*]`zr bmloV_.yfN?RNCP{mQ#(>9T㼰("FbR!-ojnF ȳ*6Zy%12 IA5%^.kHR#LȯcEB#htsEn>}:f>x_\=g{l#Mhes7+cj(=d4c@b)E Ԝ|^ x2y4Jc@af2{}}N*9HPFʞN2_s|QhX*Zu^y _|[Υ&d3Br6Y>qi!E}0LD XR(;*fy(1*\;q=T=4 *SF.~:Sh s~iNm\P(>q 1/`IA׾nZyۦ|DNI;i?e)A須yu'W7͍,xb <͡ڷgZtLr1i,$VI4Lb ADfGb4Dz;fd}!75,E?@[i1}FGq6c2W4 TS2L&8g~&Z;IN:G拽#o=;`+;hwP`Ԟ%gX{s2֥gW`e}H;0ʓ/?l00jJB3C@%SH=t;(ʻ_jr-9ή>b8@2P%L͏Q8%Fd+_|>===M PddֱNR"0Q!zi|XK 4`>h`q*(?QlS!r|HaӃJd1Q-[02OggwUFeE8 *zE:;ݻ&>w09%D4$']_kw.TBËt,PvN4OP:h@m WT}5Aو]"By\uy72;3W =`+f](5)i/Qisұh9AZÍ'P0b;8J ޼O%Ҕ<⧆H7+{&CL<~ې{6+}iT0,豹8f7CU50O29s9W)!(hQS "MČ>ɺv :D PSn0VkwpӏI4rPA<3hbIdʿ-W+(Eu.0:g؃:#k?=|>8K'{IPGy;~tPsH;u(t}ESL6\Dh\Hi{ak?޵kEb G"bݺw;^DRAogQR,}l|T#MCԓ(4j8= BD( O%Ke|vh칦kn E`afcrϏ˿E*s=6@z[%y,chb4d&ɞWs}eIm晰vX"zeyqKtKa:b Y*1ÎZ+w#$wo+(b ]Ϳ+7ZX_ Ey=2~FQHk(8WFk .uş.`01OydF#Fw4`4MW=Nܑ( FhQЊ22^iO'+̞̎Y.ddvyTAB -¾ ^WAw>(Dgn 2*2Q}lΆ b TsJZCJm2Ͽz2YhU:8G嚂bAstLX=7;Xc='_va0c845.?jؗi WPKL4mo"ZdgW*b 29!%kL#L9^|_gϞ 6e :XkU|x[CRG}lL +(L^Q~Wb9kJw[v/1OC2,GaNy;&p?iΌ\ 5vQ xrғcd%2)jm Fe9&Ws?OFd^ 7L aHm&la2Fu }cL2*F^j+ ;ipnɃq GWqzv~?UGbM>wEYX'4Ovdyؗ{[k_Ž{grHfFB??1%Zt%*)zH9 !g齁ƾj>ܛ^*@hF{޼y9rְሣۖDT$Ařع%QXMejtUJY aBYVJ (}4Lʀ۝&8F̊MȠV铦FJi'Wcd@ нĄ.p.Ǵ5z \k|u' _~+Y=niNn wYwOo`6QBb,"ZlJ0-J"yul9,UVYe>qC>>xfpA㿏Ǻ>1%A./:Bcc MԶ0 œtj#:G&>|u&߆FpS`K ,M+vkV}#o`qR׫ +3=Xis +͖g %j~ﵯēOts TWLj4t3k"ipDM?h!f20[ȺJ]s2 [K![3o"[ڝ t{KCuIubύ}Mocߠmcݿ{?Ÿ^&2B3DAc5L0:T$uCHzU1]JhS:7ַ;hW[:H:8nfUBQ wVyؼF Zۉ"BehU | X#1,INO~O@F9|_B۸ֻ~ ?\~u V=a:H:gm.E!ׁ#Xa2lt0;1F?xh017hP?q ב>9VrųD_J+aqon.dp +MxbC&?13=$G uߓ/bnjpW1I}~Ȳ.ڦJDk8dz4ŤW;g~*ZS_rU~K>~o㕯\t̳=~L B"e%⥅,)U@ոerϕ_4:c*:UCa_Jlc {GNB)ZI?G+/tZ&F-?D'YBiT@Gȥ"ظ [~$9OɅ/-xV.֫f չ&׻5hcЛEџGTo#ϭ9sYҐr&B) mghZIA50L3*Z;zBU*v/ #4bC ì2~6Y{aDl”]^;\$X줦Mh%dW{ud yE'M!M\@e)' 2`x"l#‘IɤVȻ4G fNGRUl\awzSȢ&νmrNAǨ/KG7BD>$djB甯qwVh7 H-:_bEׯa+Lo/ Cؽ^u;^yy k.Z3ܧZ@ܕ~ gN]~DpGp [Eۆ$`Ӿ4tE1&rSIJE r7{Ev`_FcowXkMeеɉ G1[qF$0 C'`@I9ޣ*B~at w~w@2^9`\4z2d`<զHI@f bܷX{[c^xw%?,3 \'6 _k^­Gѽ t:n^"l8JZSi㘊͕"SaO Ő!T!GxI0a`KǁyUYeӻyPti$jvhʍl{>pn$1D2W~gK}翂<9>MLtKX^j s~XAR{;#nݒ>o"k`[պq vn~_i㜏?, B!pZ})lN5$q)SK(>mWnbR{֥Ie?Rj90p_k nj>3 لg_uA+\A!"TwRMҔ^F}3{]% %BEp9"bvE4`hYKjPuPgi3qBCi=eGIz%iBxCͺEJ\st:t4h=894D_ʣ'oe2B2HuO\~}FOuac1%Nn?z,|t'9;Lrc{!&;`ͮ,j2-cdhך]$#ܢ~X/.޾qs_6<..6xz 93;B'̡)6n\QXi!&j GМ_@F`2_R];,ͨwR"34 CQ2k海3W`*v7)nw:CGN)q):{Enr?J~PZ}KhdG]8Xo oNbo# n`-;S60T&\JAEUZk,]@^s<+<@D8Sh]7ab/^11 Dg`uc$Ӎ`޾OĽq{Sv/הu=`Ұ@"v9;ESս>j{|+dv0 KU~J˟r6TIJ8 r/@Bj{8&Yd[Bԑ SN6{yk[oD?crrp˜mcWk`3h11;&$FS QR4w^ ga&"ĩ8~*t-b%Mngb2oIYV{(]Τ OM(%SB`4~aᅗ벏[kx1`sGLf)6n@FFrd}<$r=CD5~!XzqaGe!VӾ5m"Lrx>e9ChmYJ|]Ӭ`:O(ZP9h>+TYe=0;laRƏIN iAFIuD91+PR)jYΜ3eMIaM͡;GJ10rmX=;0O{F%K1* %YhRQ8L]F0 MF@#D4a?CݣTVHjo>c0Xjho# Px>>`'=JT /*:7U6%-;x9k3GNIӝ$tҜP0SlgodKL?vtnOA: & ƚRQ}*w?c~~ֱ%LLs>˗0;37h{?`|z.k|e?&;B0Ɖ&ff7CҤryMl'7T b0g* EnKTޒ:GQu}J28qTQqs6vB|sO`%]4_©_eݸ xFq"νCk>z}4tlnVrZ*]gȤ%ԧ47!];q@@T{(>xrԧ2y"6&N䈘5Id,WóӋpRZ( rsk-uEՃK*TYe}"vߣ1o4 o?aR=LS 3ēEٹhrȁ}rYu}Ĉ`ow'`ss%x[99 E"th(J^"f3pK,фEur8X%'We-T]O ,%Dڪ66k~xx},NsϡsuNEދH7KL?BjkNukETNQULO0\{w5} Cy(]d9-7c6< W)/9ᇌ~ xeYjJNΠXFQ1j~ !/NbJsEnBRx덷@E~l_wY,[K跛XD]t߼,:Q;=3g09;^"^1}s2~z6Y4ȈZ&QҒ%Pޣa:p5Y?`bLffM~(`2Dj1i'鏰ys8} 'gCex\ӔHYPܗIYY kr1}sNϾt,͵`o-\WǗ)\(zJq\f!B/ioAiq,LsͲQ4` ,UVYe6~AlzEw?nT)o&=׃]MO6M`=9%U kW8Jp7KekD_2eoK1DNet j rz]RbAOgr3oœljKK M{3[ZwA^{ȫN_18JƫPS­-hxzQyKǶ?Z)&0;d-Gj$1ŽKd0>y"JiEr(6я|77754 &ct5Q)eNͷh'7aB`ABVa_܋x>?/n#<կ1SRQoi"j>iu\ uY\Ʒe4}PsZV9#ೌ{K2R"NaE4*Aqgs߽~ >J'*$MgFY ˺KcTJ`M$N ä ˓Hr 8]$`UFS Iᯬ6+',U@5s J˥2 +gʘđ$fE?5P2ܳ/ r|Yѷs5OJi{>y43` 'F#y)N"B*.0$l.vښYԏ?w\(U &|t`7|z$Heǔ$ ˨rI(LȆqׄ(?KfAiX) :GJB8Zwe3wN3 b ȡZgx¬Ց)DyC2'mXڡqJ19Y dOے,ƽ"$s%K.;@s!DMD%E$q]XЏS\ :8q8 rF\WKMN<{xM\%A[RJ}/$ 9f8#.rŔ >-?Gr4k E3BFammNfsrܵ7ɹvP$0{$ηQ&b >{~Vkx-K97m1CO K/~c' T$̥#ј~sG јPo EE﶑J{X\"3WɊ 鲊κ%UBfJlzOhWU_a EYŘ1r\I<㪅}5b\Ȏ\ZH-pJmlQh)^KFL.98EcAw:N`{y?UiGC-7VQzN8YËUoqƥgA~LYyiJmRԹf#``Lbi\t9IǰZk ]pcjz#p]6&Qs4K?ї&z1L㩉bɗszֹqPG5;%'Zst݋c.4LzuAj!}*l7{j{w|Ҡu{sT4㢱<=6t h ?RU~" GR @k~a`aue }ϩyu.^bYν!Ijn[S(hTr.V+jAtŞL&9.1IN$m1Ff><9lnSUHPτ)';@k;Ri)r,Ivy=\Dh +@gQP:嘤* OiBߙ !{ݱ$8q:;NN6W[HXSO8h(But:9\Big>">O ҋpkノv@~7qoz=ii@FskZ"v7Xg^U\HLybCc+&3uK̸?,mRE=ƊA>KbF nq}Gt,KO.LM,m>COh~>]S5LκQ,yDgLtg:;et$혙@R=&FMH/1=̳RіwR}|CL!`y>0#0VP-|ZM?̞:S/{>D;Nsbj1a bE3Il_L[OwSuiuĭiX/5],uyR5*x goM}?&q3ez1M 9,zeJu"IJ*ZIC55*-O%:vz?h:w=Xe>_iE>B8)ʵχX9v =l~+.N(|=3``O=>Mikl F)j9jBHx8'd@PDj!BŒi'ua#br!3oKW*3Cf~g>6$K6GW17nce $CHTquqgf&|T'j~hVg{TD|{,VbzQNeZ(ȮM?@)?9Y"3 ;69'zi8[(>._ O9{Yg2,הh%"i;c# QBtk?isװə~~6?^y˿BV+N ~QgC!T+[]o!] N9#ZT9河ߣ D"\}J8"sXzC~{=LL)3fߕ,kиyxSh>/R#ws}u~ODzK-\vS>y5]QKzSO_୷:xk *[ tK0w fcŻWY.D0}H<GSPvzt_=gS&n߼tCG0$04wit6'[<_5-#B<'r02%6gs.mgC>Ґc'{t>/t}|T~>ZdUVYekm{U5xhR9>>~M>1Ji 5pݶb"@׏ &ae!~@r:XA^.B8$ Ws9hDk&gf<3 XϬSkb0aN#W9 TLJ$-C3)'I%-hMj&C`*i/AM5XkőHGl D.l9jcM ~P~9Td{fk8l#&9]:*N +9Anw<.1X zOUOB!SkO..buiסs^~\<hQ&K;xsY$a+WѬodO.~`.*U\_`o ~Y\kw~<ƍ[p |߀;;)Bt^}V/BR;[t^ low0˸p".Ѩ.xy@*no\pڣ,Wk/}#SSXnoK}g{hеK&.sH6.RX,[`o M~ s!G;Fi~N :&nqA빳ئvًGp &hjf;a,7 DX4qTDin܉i?U:7we~> ?sΜq/Ҙѣ6r$/ýy!ɏpxyr ?˯'^~S6&H{-ذМhm`\Y3F$zڏ]U.jP{k8*]-1A!P:NHRG=YgpKElo-l{1G&Bxm疐MLuZm^7';mU$}ډ 18@گ_~ys|asA?d3FWև=eeUV٣l#d|{!{otuw4-mTwGt6blάLک'&] :j9q S\Z$zEkc 0)'}Y 6ײb[3O SHȩr}N#`'CU؋|$x<1;^D\΄Ep$fsi,9,PTj;|<=JeR L]&qEs2Ep(ה&ZM4tlmnuqׁ;?/_Mr`o%ډ5qfݳ U=Va PH褹~`f IDATC@}ڷ 9S&Ic&vJ })k2c[.\e$ WZArVW"\8+1C41wnow^7~G9z+/wxY|Xs=\w+lϿ^y??846}?C>- `\s?昘4jw0'i,9g.26fD;C!B+v]S3=:N Lz:p?<,j@A ,C4w "\ 3IN0@1/HYtⵦ5ju!arKs'\Ռ`KwkwN/uxk>dG;^5*>)/d~?@*xh&tVS91< 8;BZX#ÝChPA4j $ =IP&:).ǒ @M '"jO#% lrx8 r풳JH)q7pn rڴ Sڴ'C-g~v-_,bUo34䘴%'yZjprf91׭K qJ,G4?Z!#.Ym.0 ͵~7#6o:;06:şTa.t_y|ѿ/ &.?#07 ТbaI!sV+4fl -rf=VF jׄN&H@Oe A}#V Hlzg29Fs/!CHcgA/ 93pX[LA},N_5F Wڝ8ZTrcfY}ϊmF"L?eUd~+tofնY*SIglB)\K naʫ1{ۚ;ķnw%kÕEP42j uLȦJl~ۋ'doп)M(:ZaCU̝lg0Gh~?QӺSvRC@֣IR,/"f:hжU'Y UHAm]@9Z Ԑ-lzA"h9BE)ioOh" Po"z軆:_9+4ZfhN/|f t]뛈 teA 9EP2t[;6ae冤fL`*d%3jzo I2NH̳JabG +:זAm;fL#xK *`<Blflc_ 1$ ytA%̈́Ssyqb9G0a;oss BI,8z3M&@IǦ^B{fsh t=,St%yJm790_5!am=G7sf r BdjKbj{/DŨ~{E%?E< ̕Tِ)ORr|GGi+'Uk|ܧLyAexIm}U.u#   OxRMOa㽋\8&ה~*l#݆ fxe$s\,Q6rzjBNҺ[C5Iί"Gȣk`j_h+J]>G\4hR9x6zq{c©mFK!uYY௿vB]n zU_ErGLP'?w'TDp씀hn"@w/N5&`@D83z=7y!G5WY؃M{nMG.kH sp٣'u<حI FoK"q#!JB48=p{h*ݡ1#Rk"WՋ%W& =zñ:!Yt>-k |b  1 ߡ+w6Ks5qT.=3&ML}4֩/߸ ]ka@ z*zOulN?,חqOgiE4'uJi{„CK'=HmYrVTLQ3E1H&vtGkJ:!a;?x,t%)[ahTI3ߍEvѧ*UYeݍ5Dg{nUH'I : qn}lg99&Pqx&Ԙ&@EvIނϚ.VN9tOXV yE؄R`_N.ZVb.A kNѾ 8tn$m af1;5bS-GwGJS\Kۘ3"|UR=j;YB`r\["A^ >0J}j,y1&xJ;cבe Ns$kS D#PB"03ަC1ҩ tgxߦm/c4Fƈ7nx#pK]Smz@ ]:.\=iIE`0XkcG=GcVg_~:._BXhLHS:ODMj0 i3 K'Z,H UCY1s p#F3S- xQThsmy6Bv GJ/7.6z/N-,C;tqĔcZSe;.m$sxiJR u, XJv,]_IJ =y\@ S(G%#+#u%D:zG,F3333]jTNj^yG_.UVYeUxؽYVr9.ptȮ5X8 Yx bW&rvlC9^,N %~*$SO<'efc!!$_ 4Y>iwX %:M<`E`I|9IߨqZ3v@Nʋ.(W󣁬v3CUkDcqh/.WKfjjys!@EYA0KbIbZ*S,>j3W]| ɓ$4n kZ` +;qo3hMP"=l{WqgP/aKt4g`=m]ۃSsI @AŒ |©1r=Yʑp¯im̴X]]H[j!- kY j˷X<ʘ=.v L)#eRbrXTҚ?l(RANGI#+zѿi|$-j7ãw -0p -rf)3S6!Bo)2'gGӪW$vFV >迚) m,U.4A $ɻKٿD]B^E vʚ){+\r=S9lm:O\Rsc1e 5l~ǩi,rp,.| SQޙ/"ZODS]$H;[B>NaM cZ?g[= VXwmK:,Ur3Rj6 E[tSRG`,d#&xl͗Hdsp]SMS:RisIr Va3+,fp2/"|C:/r1XyHw!8°|8TӃ\h:rB$9m2v2u4 c)x?I]d`J ,=qeUVVV&sCѱN΂"A|8"a)3iRVErigL^?!?% $}g8SDZe:2Aw- 8L(3[) MOLi2Z$Bs,9S}G[G &<3*N"mP;GM?sK/4xO%w $-%s_RἡJEg\4]"KUVYe4G=^qerQRЄ^k\:3Boqh~ɫܧ:2= YKɯJ)F&Y +륃(Q{eȪw?c HPvstT86y,RۑIaPN z[K7GzwOT/b5DT1ssHex"*I%&sfLSU.iVO+ {"˔~ˑm$mKL C"E qKJ^@x` aib a"7C{xfq  Guf3}%Q:>6L_ Fu +:#)6+&0lӐ)+7ؕSƗ SJr(RV#9y/ shB2eYbM^jR(kO{RN$iO N=/T((oc&15EI=^*챱{(wTu1XyI=-+M`7NR'bx  |}J񩓰ΞAj |N)0N&Ec8ᱱcjt:hzklUޘxE-,lxGpupQhZuKV\YeO(T0tԽ$~(F!=xD$mis;̅zO3Y Q{G2$Ra.'X:+fqŐaU*nϯ5;L~\OĠ(WnHl8b JX>R&чvy|39 兊dsCʻȑ"ގ50Zup}qZQ)3E<+ иf3q0Wξ$-^XbHtTyJW!i/!FFQ-k}! ~2r6F1>eZsK FN=NNꪩ'};Wcg}ODMhBw؃j*qЃ(FGA~^ c"n;v)i*2Z՛HoͅEUBr-e:Ϣ^t$\VoΓCPG #,Dh,^J ɋ]]0cq^v K>P.zh .K9:Egy}TIQQؤ:It&eɆҘ֪=j0Mv>͡:Qxmr-i |Sog!َ:.GFsh;X5vkcئv1)߈i0Q#X*~!LtNJ|R@Y6~[ב0qaX0F?:Y(g5@<1dQfdBAs[kj*ٞ1흩R;2S ti~ .o 0Y梄@vx~ X:5 &`u++"hцv ]-z^CZr/߆oRH-dXK QP9\er9qȂ%u6|11ٵqFGrstoik_kOZ$o뽶)f{56HSQ we0<;-|t;*2J"28Quc\'&ăa)CR&ܒ\j+"!GBhUReUVYe0a;q\,:–H|h!'mPSiBuDsO ?rc(Zm4Z\♬8/9&5M)mWH F=yH 'm6nzpRmMN ffA 갅A u=j_xAE;-t}+h\ svJaӘ OEQ"Nq}I!?%" IDAT_i@FJMiP1/H12-,9rb~y*II)K,ZSjJY~KtY3mHb*>f[[YŠSDžIb̧-addD$_#N0)UV٣o ~ÐKߏ]rfZUbbjs Xks/JFVFn޺!X:v ~)m/M#ߙdžAHUBeUZ5~}2&dZv7hBs˚Bkf ,ML" ;Lz>kS0Nj5&0 5z_VlG> Tد(bR*rխ4Ma GMҬvRq,֢( y~k KB7JNF7ʔZE蔊 >䏼 u84`az yķ.È aqJMlм-Lx&Y"Q(*cD~d#Hgl=`& u n3#u\Ƹ~:1SvuU(Oc !M! t2I9l9{ clx}XV*;W:~9^= cGx2PRCҕdϷ€nm X)ص&RBB9+an j]f%`s]$~2y)BGz/cv+zrIa똿6t,9%w7o5Icr) ҸW <_h?bS$W^ye7͸<ёǷ~Oro#B.u{[X9NMR'p*~3R4k.Νk4k>~$)C3oDz 8 CJ,Ew+*{ bSLC'HЗAB} ^51!U$`UqTq-8OiZqG^)7<Nwo~/_@6b-E=zs؜9~;!mr)KL ƏW?sc1y0 W)c=5y8t'7o-#'nffpA#I榚!I!"sL*4}ݒ(děDxxzA*&Z+ _ ͌?oxSX62I3%a!(E&H!ZTPGx"4!`k(PR+ƒ}tf%ӓAkh9&2ȷ%sF f]weEhL7I]kRMzxo~S^ܕU`%|eصm-cfbFʬ<@b$&d%.w)TTIg ߁t~**;؞DC,ox.qD+׎ QCʫ׹-B`,%ue0JXPl{jQpF֜!1{6uQ+&9%j95%MblapGcKFE+Q1h(xx橧К]9q4AsӠ9HӰ jWd4 `ڎ,:K-VRf cRQ,U@^ڶ](UVYe} aem2~8BS!LM lGHn8rNjЬ+yHU0QFxi{U+6σ~ms.C{T9qw뗱$j&w&P-JþjG8AXn3ww1:VaemM'>Q߱qL)c@Ѽ%$&qw! &)iFRQ_as*$6~qUVYe=򕑥BBGvҴt5"+b׹,}<i`Œ+sI^6jt]XL>f)̈R} -_iQ7H^uÔkL&QmK_{i"l5ε73Tz:u&ͧƻ:#\7ί7t<&7S3_ؔej, )tT&|g/ZKSt>Vdiq.&=أIw^}(JqMeNh7-gSrUT |僗˄󓎃uH hqf+r"e&^};%x2`/[1Bʉdޅ:#W^>~b~2hMLX1+}F,9I9Fe" EĊS w^&u=Rq {1uE|_zuv#Vdf)"Q7ڊ$ʔد\$ E*_' N6 վa퓗TВZJ"1ppXk#%XqݻwDS(<\rפ }!JNYtwZ,j4hfyDqJOmQKe25UN*IOvnݣ^K-{EX1ԳNv.mժ?)ȵ/_ ,$><6NVL-{IL5V^ \ D=˦ bV_ۄ˧ò%.|x!4gp|<(.x>w/taSji1"Hǩ%53=k"v2e/k.QF]jn46%Sarɹ2K n6^+)˚Ppj]%D]}5F$a,5U0[ahE6*i" ߃L#A$4D^Ʊk]DPU%*M)aKPEiw׊Ey><-x+<̕KdR.@v!E-ξghX )᪉\ދHI,qݜLEd=/U}Zֈ">JM<Ngi`bꜿ$.<~5{:|zԽs6fjהZ^}etOg.^Ɲ<+t66;u].[=cFI;@ũD,9[LDG׸?'imaKħKl^{?Ig{s6r5vL7c;ߊJy}/Kϐ҅~A_^`̊]H[l ~vݦ[tz`o`/],i'h3~Ί C=$ݳbk[;E饫6iH˗887O N&Qtr(4;L0.#蜆;ߺIWmc (ۦes%zN7?) oOnMc+h6:[1J\06ku%S"1T<!=tNQ6_z|͊:C+ݢQ4o2\XQv?$F0 ,PYdK#j*h vcO;Mg?]s+uNa :7+Ia[/'2 k-ա)qpxX07M /O+n 7<kqTi..kESiuO`/HS;{޽k_(hPK°rhk#,M%$g-W5F=E0J.N=ne.zy=Q#nw,t` 5+u kOFV׋pT(j[st랦m:kEJ:ܥS*7EpL)oqb RR+wH7$DHź2Q&a`=^b4P2V.mlm)w6Vt=oN=@_A7[Ԗd(HŸ<3͒Twh jeuRZq3(:wыRs v'J'b1T 8UIɍbޞFr*$c^1TLq̮{=xDyz"h1Ov~N]R&s* zNJ6د3N:˸'`@=Bh\E)rqqLEQEٻJڹ29W_|wR2:;O8`r.R>?\ns"{F`@T.qLٍmuvMSoR~ VҴEe,(Lp8`6ն 0Ex`J8f Z.Sӥo¤M&N]v<]f`K$4ƌ|reƑS\Vhθg =wQZbGZ7T +QV(Eqb8)G{LX'ߓeGah[r u_;b%JMB7_|.otiMiPբb-8=n%iVX,N((m'ӆRs-V IDATIR]fS-+Al휹DN{z=jsl"w̤ƓqEvq J88}Z7h '?XMKT]h4uE:Z /?c(pͥPqCУ#-ڵgB'PR߈b%nuC{N^> qi]o[T 3ɜuɭhbVDco㔜9Oաcm+mX9 &fRQUMu8,LK^KJ8K]^3ԙV6<.)+Tlߣhϊ = 5ID7Q OTXSYD{M8 ݳ:vwi.]&sQB*8+k+N!u8x?_www';TI (fp {&SϷkE%%l, 9EM+.Qۣhi3p@]? 2Yqzӊ"+lU"Js#I!\" ]dvЮ۵b]~ZgJ*M.@\=x!W Q HBW}F}Y,4͚4kٴs2,@MAj: R;w<ps/ܲPޡ"iYac8eА$&ɶX"Xck^'rWD6j-M흢[yz "+:ݞX8EʙJO~egh ^wkLLvsؒI狈y:yA.I'J,$Y$s^d(縧4GIDE⳥>jMSQ6u~;?iO,JaYYDFq 2NU4-N6i K0_eGہw^/ר8 N(n` ڱLݥ͋Wi9jIN$qElVQUݽ^So$:T-'^(У7\^>Ur'"̻)-Hu 4inuW=Y=`C*;quSue3ƣԊEd.^^坿{|"3}riI ܲ,B z<4=j)8`J,2"i-fT4jr_eSl[4b!J̻A:G$3J4u ,K0,Ga=q$FRKE'њ8!e_HnSRҷnQ]ʞgw4OMe۳oXneItزbNwӶ)u$([g 87> OI6<=TN_j 4iYix:ǝ>Q? A1]x4bJ(mI;(JC8ӝK K8U#2Xu׊;mD˔vRdS;IJtۣ @,/*'te}(mwFB0qZK{;f({{pwwn߾- oLx:B %`ƉJJĤv EN9[imlҙy}8]B dˢng)?ӗ:=Y($5Je;1"#񣝥iSeVTrgv^+lȘdY)#hggg(fI>܃E^EO`0Jp9L೼iJB tLYG3gZTJx4Mm_}t)?sⳗ(=uRv2qLy$k]̔9Y"jf#)g$<<7ę#孖nGge#`֚iVrY?~X^zɯk8(PT؅9u{]L:=LFiL)+moP)=t +Z-+R+iRqKXLuqd( m''̾c;os;Rîw[[[tQXyiP &*dQ`O #֤D,;FrBxeb"ÏN'_Oѝ/)M4P=>OKg(*J[w8RJ;@Sijܿ~*v@F0⩨]baF6ӕ)E>( L[X @ VEN,X@-Nb%C5J߉+L&6J`hdk>-W1х/h.ݹY{tePolgN@aERQ[2u͛xL7f Э]2-DF#/(xE@hW^Kd?ZU-K1,)_i @ֻCeR?R;lh%1nayȲz Cw"xԕ画e o4 FKA~MeN449 v+%m#8-}|&}'~iH; 0]m4"I)$XQ~1%jbo:&L϶/G 5?/m8SmaY}@rwAt_ݿK5 h [Kv٦ݦ.zMC^W,J$nѣ $(ĪhJ76ou۱JڮW5({9:բmJ[QG$t׊ʭ >KC+]vWEYqNʸOqIoNKWO~0%ChB(L2%KRji)+hXĤ! HsFb7<+6] Oe\1,S^Tz.V5&`` [LlԿ{WbEC>N2u^oʮ;9m%qL邔 Kv?Lr6$]|2'`@,ü;X$I[-|h`H"#s;|U%r)LYϾnt #vcBaL {/x9=6eaٖy;;NS*=++b {JӝޥKtS269=\>CThM?o,"4OL9 @(Eʊ Xdp淘BM2*Y!8E}Eذ0z'P:Ey^ܔ~o"XLRZ*$j0{%JIj: Ȯϳz`N JNIk΂E2e|_׶fs .̡ڹU ̣jYWAЉC8p鲝&*ShGF.Mz%7Y>9K=L{F?Oә3gD,<[X\>5,/H<O*-f,Β4nhdw}YE h4u80;XlE eI@O3.+\d$߇ 0+z%f-K?n{x$o ~-T<|`[y;)ׯ_S:f( w}KT}PGJbu㐸R^B)w U*XL$of3?b X19 qWCr[s}!va+E__/~Ϣ>pF}CLx] ˚JIrb3lz?8ݹs Δ_\6(i\LdS Y|HLU%Ң$-6~4|鄣=JU`$'WV0+*$-$x&ah7BqJ666hggg厅"1lq"jkkK86_b8/o΢.y֭[=O,}Yp"ťcV Lׄ.~)=,.ctw=RȿYgMKHXp ,[|up.vr&į %&ْE )c2Iagg"j8~2|vJ}cBGGc>]!=Sbq:{~o|i+Ak#J؅0e%J`d|)y wFՔ$q}O-&t0p[1,M[&kv aNA;uϹIN[5(\W(<~8xK"q;VRpZq==b Lavcw:KLM$.]4WׇzHREq__3V$kߧGST%\/2S2#Naޥ-UQG)8 hCTp!43j_gִ Yf®uC$Q!BZCon\;CڦZgjx">3 .ֳΊF1xbʼn Xlq>/_׍b'Y}e(%)juOQa=/ (b!vVzwo_O#mrT1AҦV%&\D_g$8q r5! ~}L"=q 4GX{iV]->m*,'CTti4= }תRK&P2 mcq^wZFM+W:ѼNc,p6E\۝󕳝o+eR 9Fc[Bݾm??MgX*2I5n$vݕ;8XW@,1]lOܶG{V8 1get\ZK2' k騈#%,8ƊS' $u RN,weX9[sv%ݸϯR9 0͖X~]gw (9~eXw= 8Q{eG`;%mt%:dM[t'm[S#* oݥ(c VIqI ▸9뼣>ӝvqQ2IP2fھy޶5It'N'I,*mEU HIb[Ӛ}Igv:A LFVD$+tMb!˩o'~i'imr'Ⴔ.;BAn7\6 &"W9I('V"ӄ[tE+^ IDAT;Ćg{vWh;bCVfE.i%sw',:T,KgZq޶, ސ6+?!ZDef8QqJV==dFo;E_[e}{k$+y1'*ikl?Kg{VT!g]v=:E}{,>Z ֺ*2gh8 \~O=%x~FQnm*}f9q.>EΐÍ˕q=4C/[eQ O2J$UT08w=ɼbɜ&mŒ&M9.+l~8EcIÕ9e:1n4)*̆reY^6SsRnS&4pU&q!1Kˉjp3c &\FSfc㜦?pnvYNqGPu9[b:fApKCwP GKU1%CNq!Pr>&b78nәnzݾ ef%!Oo&q?Z \l8{oa~1TelQ <9HlDV d҈2P&v9> ӆQό;m9|%}3pԄ ޳޿,`qXj)4LTi3sfXCToL%?_[Ϣ\2إnD (]n_uI-#,\ Y X4~~uE FFQ]~r4p($GSlܧ 'tő< +/5֋exWB壯cN嶗#K~;Xz4bF)I:~?UvψiL!KrNA!*9$+%Ac$ۙ@X8u?Me+U*5íǨyؖsiww޽+LRuǛ&G' pL`W4QnGT (em'2f!Lt>m0.Ak/Տ=$3*;*nw>i,@XYlaY @bYQβdʪBFĒsQ+SA}\;'8غ`$q ل1e]$~N(rHt+gSԏ#x8(0XOPthkk+únxZB )_;\2BC8AQj SZ F#t] b4e\D"Y$6Li2&c5JRiW~נ Շ]|/yALDR\7<h*>+EhL Gz VJ:>7;C3N@jӈ%>u4Y~Ȇh'`Y0 [O?NUyKpοg>)*-,>\db GlIu0wJW \8F)H7>4Tn?~5>XNg&TC{ϳ U{o%I`/XJac*[T׫cV+Ud'~#XAC>iW+w@(UUgꤹvh &KdqBG}D IgdYŝ%@S9e|h,'3c, ߃~~y h*u2p 3. ,K> u g8IQZ!qK`O]seVQy֕Z&k-p]7b+Lk1ڔTd6r+J<0dM[uMeEi`o~J}slL 9ȯӸx_]Q$W[D:ʼn+)=#®Ao!M* A/ND¾fEaI  ˆ]pKɫIB!G}X=ޅFpՈTNqXQ∽H\LO mK 8(-3 A9rY$ynrnzW*#YRe\8X8<1T:"3<8yw G)I*XJNP9?χ"ɿ.Rh*+5gJc%v#-#vœu4TI2_'6^S^`V垷NUYϦuJNJh:a%ZRJ U Qm$N঱L?qݦ2w_I8: $J&mGS1]b TB Mfd!7ee|QT h >@M`]Mŷ=,zSOx @CA4&Ib8qC5h*6ҳ̠A3gg;;~0!  K@S(Ì[L̇hN%@SɏB`]4%4oҽΗd̓W&4uUԤU=zN.p>;MZc1fr ҬFtyrF- )YiEiZXk39\ڈ ӎQM jr,NGAUSB@,B1|0Yxˑ6@7Z^IѶ,H8~2KACFulivbAJKQT*y[Ţ*%#K$Jp@PXk2FHrh",'U"4Td͐;o%8`]4YNh u:EXszYUfút:Bu4jn蛁5ݯY&+^~e P(-h!#eZP> `A~w /„XB'dӛ%;`4EX4ì!'0^s'h:800dTm5Fi;L]pGҢUv0Xպ筯S~ֳn@:}vNXc)TQB)Z4i{jmQD}V n(3i_H$(m ?V]mtAIevU>ETBJEN|(#h*MJH*EMy8ŪK~vBYQaE/YXqe)r+4~oq5-w$"Iy!` M*Tc-ׯE_LfnM*5SF*40Q VL^]EAq2:)I QlU19k8(1GuݾEvo.\=oE{;7KQ I`r*T uzڊ~Wsеk/җ.ڈ(s/coөꦧ×ȭ+$HҘx.! u~clxF<$x4 <@SPbY2C}wEBN=y5z쉫?͛럠}WWkӟs?62-qb۷Rj#Բm8 <R''i{gw/=|QzWV΍XQm,B@K{;D0qaZή|||_A ͦ(D "NR7>E7G} 5K}#t죤ZԥoF/ی\߀N%K]DYeoj%4~tN%j-{gڝw LSw5Cq{c~ÓH" j%q\Q'bdԲm7ݜ,JN8:D=3vw)mT{{VHi2V"1zIo)߳i0<$)D+imSBw%$U3E/ k\|g4 q3fbmwoo D$ Q,5,1HVP Zn_XDZ,}8^JS>!#b <kIԧ͛baۻ/Iv[ ~#t֭~gcE(sO} Y7'<,KuQ;0oEi$j*a YE;h4ujs99DiY#aڃ?_ޅLõb |n tcZ=N 0nvQO Ru;o` ކi$tޯ9H[7<@cX ꩦ3A,8J ` R|$/~0 (ʲE;L+`V~3nQc쿎NX_iZW_};V9,L ` 1&-8l"t0WXk2F!\D,h*%>K# BV9z%E+R}*J[=Wj.`a W-mVɡ} 8A-J 20/F[-J;o aXsB,M]5p2 T+d!~=@P0yxb qnt3-l>~%@V;x1͠U?̚sjB4e ,@g)Mu٬UBLaVpr[GK(U)umvQ]3T*;pg,ª[LFp8v%/&o ( 1K0EiYںR]X4;XÁBRb `A=Aw\tC'pԉ`YT4w=s~ʰ-iz%@cXPLl 9pbh^JY˪!` }u6$h'`1 XQoLݬˬއ -:6DZmk#;QQG7"kg27Ɇ]_q^]@x` %`uPqM+( ʲkE (XT}3:8LXVv@:QĢissΝ;6;ߋd7bhR MKju)| b ,&XŎSŧOJ/c<0)ދ-LZkm߿ׅU|quiS&՜@|X^,U]x)[B oV@o.$nkY;/f1m'5YEs+}n*J[]߈(ķ˾mIӶ ,KR#/u]f=KF3!8|8p>|?XG p<,NST4!H4کa]4E_My /i %pP NQmW9`;欺8#4߮<\_g%(@869A4'ymuK 8,NΆw'&, `-p3e!A $0KPz$V١@<`OHUiJYjQF_0%@8*Nt˶Kpآi? QKA|B(p%@  vx2Dl↺ pR0A,֒7}L0DTtX"Ap7 \"B=2 FgEFq~& -Rc/g^=y߆0xHU]M>>/3X UeȱFCLάgT8s`EXK闃yFi >8M*xs Y dz_g4IJB GV{0N[wBcW~PA&$RU |8pX53jT}bf 0t),GU, ~D^,wU:y}潪e nmV]Vz>>OQ P8^)~V"V-K~Y3Ē PSm3ur}?,Q׫zxx{^/2͸%ׁ4/"nIi9?呦$Mh[RjDb\ fLsQ,iۆ˫8k8 2amiT8Tȵk̙3Oyt>jWfݴ |iZƍzu>~MO?.?u^Ѹ_ȏٍHTG/w1eP99`( ]r(yW/9}??g|ݷދ$ǧC&⎧}zg;oݼE\hGm!,{qp$;Hjᴋwqدϸy4b6Eʝ;w!ܳ?Vn랖ծOӡ]vmmm{`ݞMՆg~a[BO:jߦST)LƂ^1^en5q9.nӛҞeCߚ5 1OX^;yr\]iu>ݯ>4h$$!!Z@I8U Ն 8Eņ8Ud+*&,$-9UKbHI H[;Zތ@pT}so{{ 5 0%r8.Z>R<nASyCu.u*[BDSCrk@6]$L)НkY4hQaxY]d/&MAWY@ !@)Ghu0%Vl0(B"pͱcHp !N<1f}')fTRRU 0qTHE ҐL˙LrJGhD i T-G|n2"C@KiI~L? 38"|L}כ}4i:s)ltJ4\I5<ͱs---{)UNrIJL6?>-9&qAO&&2Bhq};\JK]UMU( %yvK]i&MT4މH`"41177d_Q>$Qf>~:t:::*_QkW^yO+R0('a#C ndle!lXƀEQSh;nILr %"Q R)& MF.7(3EI&Mg ktDy"Qt pvْOR6ҧBIꓗ 7tuy4%`űB A$jWZôR@hݰr4id(90۷|&FU͚S_3d F<_AK%y\ڏ%t;es@FT@k}TPY* çOgP>Le:razp8I &i6gvI[耘L b0U`Yejog@uy]>|5 RX\i%t:aBGefywYnuv&R039TBu$A);UFIUaʢ\.y -Ob UH݀_/jjjzeͣ—$3H:P^ʵ,WZ;A+2DņDžK45 (8+SG*ey,1Xj j\/cѱ+IN!רXyQА&x\p {ظL 74it&gOIQoh^d2yEccc ,T @Y` #q?ZT{c< }PW2ؐJXLPhWy5=A N˫A&Mӧ DA 9I087z%09Q4۵FJ](gHt cccK |̫_4.D<2vS'L뉾 Fjf݇ho2[8 i>p;Y[KjA`JkەQ"ڜR:e%%Re:aD%F|"T>XD:yOW-[dDAm81 4itF[O ,Ёl6 ---ĹUZ׳_P?_iia}( dbθq[,f=:v.ȡ*X3bEMTo֥߯k>ȷY1Be&Mӧj`)rޏ4z؃G7G+ $]__3Lf P!U T ģ_Ɛ M@m%B)GEHP4< g2&a2\oKLN X*cR3j`d= >/#4@2Y9-/`ȿi% TN0lWO_fV+%0[HבaKx`bTL9:27xc%4IX3K.پ`&i9+iҤIgaj9頹6&)}y8ƃLJeGiMԠ~YeZBh"Zϸ3ǎ7/AF?ʤziq"@ l Um"L1*bTz ċD^@G‹Z\|P (WwQm3WˉqCCݳ4]_* E /suN&mR`#M ;lz;.Xݸcʠ(xQ|Ż<, CڧE.) @SbKHs&]Pa]VϑD _qx?-4iLA)ZaddGԋB ς2(ԲvX.Z%Xr5XX EYx  u\ yp8|Zx8˫?~8qaG=̛Ps7> ZgÇaݺKካEj x<-CB Z羰|.JΫsZ`: DU7 UHqE/=98hqD~f==*RUm~ߣRDaTm աgrZA 2YWƨV >j+`ǎvZn ׯݻwѣGaʕsNqffdҥe}4oXBE `M+2\H<::&.{aNG#HCiEBE&liJWpÆF-a^F@.:{li<$&pPl} 1l cZ[n R& ƾT T0pJDZg?d4}ܻ.Xu v`o $RF:02dVHՕ*6Pl' ;UC,<ԪY.Y._vp65jնWyUDjTlLD2[l̛7Oh<(iV^-Dv%RP?9HD#f-. N*U p"Ŀ=m*;AoOϟ[oVxpro{Cdo|xA 6N 7n\xj8ؽ~  dn ~$I_/22M7λnv'|zCa˰-Or NRvMs\Gu.%@E5 x砹etp]'x<L 6L≴0C˖l۱.]1+!~-Yxl st¾Cb|/[*Ƽ !oXڮ#[ey1 D>0Ұt?.-?VTR55îx냚nbNk-"#3 բOJfCU5Clt.߱8C/7(ijV캢ѩ&08Z Oզiا)DИbL2Å:#V4Eϟ/رcBD>Ke.['}>'?.(aͅ_nwB ˕ph㢋/K|1j$)"QQFK;ww`K ]{- 4 W~2Ϛ[aph~GTRG9 瞃}]A;awa+o.0b 0/ 0!Z$Ld J|nEIM 0e&q̎>$بy Z&%ԨoEs6W ?3梋!Lcd> [߅C}7ބ8 Ĭ߇Qe-{[𾈴uX$GW *7M4}Tm#2,_~:(>PBް]ӡХ"5(;s+© o#$68Ƒ};[yT <1]]{ylyXE겐F=q ǀM27 Q4z.YqQKK3>ٴdBViR>e蝅e ()>,á#}blγDM6opl`H){7 !R-;Q+.q˫y3T(D|rIENDB`fltk-1.4.3/fluid/documentation/src/edit_window.png0000644000175000017500000021452015004135251022376 0ustar albrechtalbrechtPNG  IHDRB؍k# iCCPiccHTS" %&H %@A:IPb kAEˊ((bC,^YDu`C]vysΜgϙ @g d T SGؤ *Ѐva ڿˇ [C 8Kc$fb| >L&!1S5qp' 3?XL)4S`yh~KE)3xefaK,FP~N_-g2@䑽 O%KfFh sLib}!(Y45l%aNea/aEڌ, +(Q,eed9;Xh?UWKIQJ )ebiX3_ _Vܻ`;3+NٛH?)|dxqFҟ\p7L2B !2@r@H@ bxY\`s[&fB lG{G';;r$ޱ"º2[Q y|ppĘ/Djr&zlyΈo:L0KGp0xBHLyA:ev>8GNYW܁G BBA 3qD8⏄"H< R$Y@b ىT"Y2҆<@:^-š4Dr4 s<4]=^EK8 gqp<\. q% \5ׂ} <oB\bj|~ ߉' z;O# %=ZB7Hd- b<1XCl"$IdC$$tttMDV!\BO>MI!P)fwJEDɥ4RS)T ՓEM.Rw****n*T$*KUJU\RTLӤYxl^ZN7 z% *CN*R]ZZzSEL6K-ODuWusu@}zq{ 0L5.k<$ikk45wib& CX͸fL>3YbB;_t:::uuuuݮ{Axx㏌YE-ۥwM_@?P_E+AF C/CF3/Zl.;]>33 26ij4`lamܸ ՄclѤ٤tB*Ӈf3Yf+͟[h[-,,-ޖs-+,o[8VV۬nX֩mP6 n*&ܳrmsll;Xvv^O40qĖ3w?rtvXQXxۉĩ$II'wf8Oq^ERj \r#-q;]~O[t'[LO=SӳËWgO׊=}k+s-5 Z5T:.l " `ECh!!e!OCC塍S)S6Lij6U:> a[ ?18-|Zg #Z"#G~Z(2:;9F-fFLeX؎qKH 1 {O4{wgZ̜?,YNV-}4? LP!O'mM򄛅/E>^Xܓ\<3eCJowjI+ OR&y#czX،Lrfbq4]z~sd6Y\C{Y &6]˶!3+<ӼyGk̗οk*'/  .[عhbdq%&Kt/ \ouY_//^~E|]?PUZ /c?J~l]j˪+EE%E_W W_ҟ$i]v::麻+(+0eCF7tdRɎٛ;JCKnYkYjٝrz[WmMv;w;wUW"lw_8TS^ގ}WVVۿ ʮ=0~mwְjC/'{$HQcfǶ2j 됺ܺǛ=kO؝{d)SkOSO[F/G)D~z\(n*5{Yj# rh|W.BQ"H~y0_FQQG?Gu:>tE?LsMz\V+MOO/̤v}S ^|ߑ_6 .K.S֕ө=Nӳi@JlV$r@kf52 vwwJk(Z8aH L$I9W+Q99q7s9N? (0eKwWyM5մ; Z EϧNnھ}{ K?||o{J0?]tEϻdcvȡ W*j`?_)Kn%%~j?H~5IR.gB*kJ)0 us[hS#`l(e@b[aM5 dKIyY [ ]po.,^WFR\wmlߺ@N @5u4]$_D:MIQHz oNKBZWJĈ@"RaqS)aJ3ze"K LU^)|_Y]+JuHzC^#,^W0ظ⭍.~\ڥvLT% =I-d%EheVA *g Ym1 U TPvszc)Mk{(DKNrji_$@PB_dCns1׸5Ub:3f6yV斡+RWc` <TOܚYBkU3@!}Sw9сhnak竦jIUXPA_@u֛4/·|URk:lX>:xZSi>FU+oD{ySAT9vmJQ:i1Sv3f+Q|;|- Zٜ.OʭBb͠\ Yke_O-웽"N!yvԉR-.,,ɫw|6ƅ!gu$m~7}(ϧ$׸e4 'DU0|3f|ɺu]GmKѾW_6a̔(ӳ3in` iv.ӈii~PH!hvj:Odۭ tY-*E7I|u.+ٞ;TkȫDž{Q&kKف 5[C l KBo MMev{9N Pܸ |r sC @:OXf?77Sq͗OITk?t59 cY)I>YG֙jڳڳgS̗v9K}vqѿ.W0@\?UQӳ -t |,:LEX5Eg*2?HvGR]kCcv,ɂ n2~n"߅v\D:̕dۚ uL1kLLjv[XTF'=;?=@4:? =g܏ a`ivرH 3 YN2Lϧ@;y_)2?6J5$OInjujeV E"t׿9[{3WrMnz[WOy ?ӕvGePM"eH[dG{tC6uZ³"M9~s0\ʑzG$77zϿ.ۚ_ WN]7tPдS0l'}VݿocH6m">+?M{nl޼y(42wWU~NGC9$]jWSbPRU}_ON;<'q*fTʩg^SQp*nZJ]|$|} ״P~uCrh KfCb+#Stޗ.>tȕH-֏r`/ݞ|pJ׹^gֱS:) =f~ irj.-\tη=5v]n/lݺm>m gJTnoeg\ȶ?rON;1ƃ( j^n|MotݙyrsSǽtG>#HO'}S=y|f8;!P(ISOMwwrG=QN 74q#`WUڶm[Nk_Zzq{\:CpT)@hv'+)񑗀oVWy_ɺZ^g5D;7IͩrF*hapmۚtMR:".Lݟ,} R9R5F)i JBvN:{_L3s5\H\sJ_g/)E\=PN 3C]iG0:}L?iΦ3 uִqӆ0I<}Iq=#?(D0};4~Ss?gk3T^W %8~9> ALַҏ~!0 G|(a~w.!_:CK.$x~7({r!9!i-DޔUqt< 5o(g~̺"M0:ѫ }%m?{jW.K l>-B-3-F.A.*l:8A79ilM[z }n;Vn>WHtM.38P~3>'_! vy>Ut56\ycsOOq ڋ /|!厬 x}Yj h|F7J'xbf U;Ht,wMsڨ܄}K^򔧤׽u7azߟr)OO-oyկ~uV7AK/4s17q \=aK/{ҋ_t<} vaN>D(=Hykwt?/I;/=qor˃ 38#}.'?y71 yϷ-CTi'5{]tQ>sd.K|pӝСiA6C::y)50׽Anw[)ȝtIN}(|&{_ӟt0Bܸqc,5J> :җ4=AvG~Y '>A PD#7 ٜw#yAl&~Ozғr|e?_jˬi$IsPm+7/j5uƗ4ۚ,k % ϝB_؄a a5ԍ8t6-$.I|%tZ!@X`.-ef&!ˆ 4iGIfͱZ.du9<)}a\ofr!K ugfx+^UY$HӟA 6mڔ8蠃x L`wDD?8R>$Cd ʏdg?;N׺ֵ26:qz>y'Ļ$@;7!quQY|}ϋO~YZ&l׿3vƤE8z)F=YSg8d6hg KINܩh6qgq)0<ⳐmylΎ}fSb;tq0f +P,<} vɶMql_g0us:" SYT*$T"|!;;:i{AP;^j-n;8Lwe'?Iomٲ%*+\x`җ@o%7$6fÆ Y5ggq { P\Nz-0uA# z=yOV,`MBw!j"tfDG/I~tzq:lHbi%{lMwr9R{*m< {;ԸHS;)ebT+< ɬJLyJ*ojÁin4y[:2R\!tEǩ"ݬdͪ|/0}@:xt.F]b:as4ݝNhO3ƩJbHfRΛ,MI}+ ,-,$6dh΄<> ; uϪ8ed ]*W'3+\HIQyPx$=֍$ZV(^JW$x/TfzcB}!>qp'–wݳM b+E=9š|Ԝ_(gw( j0_6"`?*/ttmzې%A`q?eu4KW: i9/K3E[lfW*t$T -TmSE fdd~Mwht6Y\$8TW4{4F"<RJSuIΏ mY+[i_7R)xR^TGmKt!>MozSzޗu/$j'y Xp[8H3y8|?8Aԧ>'KG:'pBVy?3#4x/@l"]gQs]p͙Z`&-Z0~ўӷYp 9^RHh"[{ߤ_\|i-4ͪh+B5S+ttoZ~}!5g[M[d݅H;{ WynE97B\(nN7JUoxtݍeAf R(BlO\nP s_w3+ԅѸ=Yl(J^RW3TI Q_>ҡ %`b`Udb䵯}m4L@>C\ w?A 7PD'M<]H$W`~s!1Y4%S$Y {YzF{b _fZӞIqʼm|?n#.F5,t8.*ϻ󜴢625ug=:i#v.xK(݁i<& ŅqY?HLwA~X-nҕZ O!-k2Y?0"7K5o11~^gN ;{x\"v e|媕 շ~tatO{w%;.xҍyX (L3i a UQC'2Ʃ$8RbO|? 4(٨rOkA'Eɒe=lSUߝ@CJ6=reH|-T@4u5k#5Rm'ܳwp֭Bm/ȂzI3M[\5Z)uk'h1Pag{K`ܪugvױZArY7E N4}k0LVT;MddZfQ"^s1Z?hSc%F)5L<4䤘@)-_ ңW_I;<66/RQW k) }d~{QڸaC^/+FJT3W)" =%@u;Fcn<؝K[^ {A 5 .2 vH,EYp"I8͡`0N⫁+2BW0IM6D=mLSeE 5k݇˸F8W:m߸Bʮ aGiɠqy"gi]t=r\iRȿzNү㏏˭[yaRX>{n Xw+aƽHm| nZސNU]U8->b IDAT yEqVK,_\e%TH\KcGkM3%#ys뀧&~ ;ܲ) rSWЉ*wI"NAvM?cI,Guŗ".yT-k%Ҋ_$#=L3NBk}:G^j %ϬXdhSE`"OL? d ƽ$Ƹ^M{.EfvcNv]kG-'K/c'l8e ڥp!L7b͒pL"Uoa lA7[ȳۛ{Nn]#CGrdvq%)q Rl3*PX9{ly =Q6N(1~Ѹw~eq8.wK>"@9?<4,hX)t+u;dpNLKGb'3R8,>u|%C̙!,qp'$1FSَTm(i1D[g}0}DÁx"hE8{9d= +*'o;gO0Orƿ˿??gddz-!> 88&j;l %rϳl2&5$v,К֏dF>cǗ8]~zS1܄F[` I/NMz],9$ oMys!T,aL8c %%?:8B=i9/ʏ ,&5uneg;3 Q>q9hӿ8Ao{>׼5^W 9:RqO=D _BΗ=!-2E L /a9b3jQa<׽n> x0,y|сQ[ Xu x:무e˖lA9a7[:3_ /y ψOp~1'ʼn;!q"_L3&ؑBs22ih5ry:S!Z:rSxwF# WTTm?}-7 ч?h}ӿfFַ吡}{C¨#@Ĩ9zԣ*~6}_a$ s2S/p$RRkWap D0^tL> PB0z80( pRݹF5㐆R)$Hp֑O Q:i})mr:36zֳĖoկ~l"26mڔ8&Bx>|Հ*G2k>Q+!=q3R"@G.T9?/OzЃrz<(9'ԃSvު`3@]B 4]1^0 3`~QcdS 2MO~oUhߤ=&MXV̭,t O:ڍbׁV;<:D"[7g) aŒ\{;Iw.<y"Ÿ-<  2|j c+97zDԴ~T_?.^Hj)b7xs2#D0ZzYAp}a,QS`vԇ0j#h$sLl[ a&mfX&_Lu pb#w ҂>d5g ʂ5v\'nv.3ws)zhKք1i3fgibj7RnaJx.5ۃMVgKv"O ׽.*X.Ȏo5Gu! R߫^!ٙ=ox׉w]PMyP9.=A0)qLHGq8FLJ?4cXǐҎ[%&xD d2Du\h# (DI/2s3zJ=-睘c0$>$AP9 m'>\N8!ȔI_H5h\fHo?mݶ5M`XH/4/iw;ADl(s!-Z0g8v)C' 2>>%Ev@Ge#tZq 5.}=uwl/vu6\.!5NT@|}Yoxӎ (sQ.!]03&y8<GxLBLQE+qm0Əbڛ7oοd,7uf47SPugo‰1rG\Qb(O"E>LK`&b}/ kXХK $J.=J`'H4Dsz9$Э=>)xHjLїSJDXf270Ŋ3y9e.Q^ a>;"P|Q B5}ӑz(*5dq`{.T7.%9j_mS%P/)|%_J0")%=/F鲦d[Rr45:f- Y(ÛzQq 6R*QJS2j$A)d8sQU8`hsd?ǍW?ëE0i _>~G'DP|#E(#N^F cȰWRMT&;i\Kgoo[Gl`6]6nzDMj1luG|vޜu .9lT)1ƗYs.R"i|IQ@F [Ta'~M؎ڌo@z<OL1 aT[j{Wy/o,md|*E0h'-FމyK3bXˣ0 j*:Ӳ׀Bdͬߖgُɹ%$A~8*<G mARGnN`*L#(zxF';:xmo<na:OGR_ DQV~t' cIүwvͰ Q-4T(6k\c".J{¨8 P4UIi8/Gw4.._F^/9ShÍ~Y2kQK@{*@S)1:[im$4~v?5f92^x'I}`iԴ1 #,,"g;Jokڻj[ %nMW,6NȂ4;TGfS)#ߋ}&ܚ&'t%:i<}Oay~^e ȗ2{"eh%6 cWӋ'/Eڳ<\d`&3R`4&b8QI@n5ٴ\K#Tmx5_mն=!N!,Z;_b#8R*Vo *Ė/cMdη`tppjW)ܼCGQԝX6޶mV̅3~S:֚+L\~]fN0\JVOײ5ΛR|5w >4՞>ʅ$@2!b!+ 8n|C~cy6n@:J.a)GG~ե~čı7 ;d::uMkj}d Xڈ6Hd#UpXڝ%phO``|dҖ\2*8Oq{M{. xM6 Zrq^k< :ˎddY}6y %A>c..SbO7pqpl'/ s\ ǧy\ZJ~WWax?f)IJ8a+[s2GxVhV!_lV̎=ҍ=.8Uj5Uk@lU SV3 5bs/[%* (ל)Fc͛7HTr#;[0:96FFb8 0t Ϫ oI~,E|9\E]Q5͎7[C51/"Sh{O_t|5  Uɑ0HoN'?|,[ yViq^*g[x& ޜNʇB>1TkZ9-'QE`tM6eM7i>D#7O=ԼɑcGtLjR]9뚁6<Ym̜ɹ(9Dp-IMk=LJmv^,Le 6V8R|aNH0/Caw <.LjNwlْOD}+^ӟtBQc!Gogl/~17)=Q粐/%y)]BnUh3GPv@eF4:?x@3 -qZ kgAA^)`3d%-aOEW;Դ~TlI@hR5nabtvqd5j(㩶5#)̅OOxD>|)4s'#3j-ُ~VF0,0 E# V>r2w|d)90ii0oWd#ѣ D;Hq26DgT m7e" ~ HAw}l rjEmg`չ7G3hyΏ+~ \JMw\vs6'o&=`h1F <֖08%?z̨֏@1n˞`8lveHjLñ'm+2Eĺu6 ߯#vgW]?Y2 L_2o - 7RBlgE{uƏrg2*bd/̹([8v7if#L{Gt\]/gC6M.4[izjz;v4܋0_iQ{ v-[dla:e/O~3h2mħˋ.}lx&yv))j5-O 5s-q)͌h`&,p}Q'׼fTjtqZw@JcJnj/&R eff`f&CJC8: 3Ї21HXR)`lj4aI߄wbE@Q8)ɸh]!OgG3'?9!>ٹA2>7(ߘo#G>'SpCl]\M]Hv|c_ٝ.0i[4XI .=}?A,ɶ 5zWMձ{f"7&PT=R N$}hOl= 싶6;%3(fȓI#+&9 @ rYCUnNHдQacx+;`[W?m=3+ECdXuC<|;Yj HK`ǚr]~G(+t3RqIHVkY:QG; %!P"pQH;xd"ƅI=ǸӰ~6mNߊw ea}NYsĵF-ybzv|GRZOB!vGb,1j=!1Ȍ ^J`vr,zf;>pc$Szu.#E`$MC$VE«2XhO 0J IvyMs~a>c^7AFXR4TҋC 20jwTixUhQ+6r&!D$q/2^:ҍ 3gT(vsqpQz0^RBGiڇWeWB|Ṉ.!;W1$H'%[ob'k~2|,r9;=@p 4O˹7_=ꀾb" uD]h֡oNmVn`B; %5kR#*켌jy1 +mF c%9[y@+f$I+{ʱ 6NҨz׻{Ԭ;ym1C.$Xj;֞FQ[($IC`sZ6<|>f9Be_GT,JvxYNјe+6UؙcUj)&j|o5]<#喯 9HC%H\a>=T R-j:FiR'>V/O&IZiDjR=n*GwWkW@ͪTXĎӀ/#2.3w] [$aD% vfV$qi&/\-Gg&@gp9*C"!xy`S~ ˠ*$9jI}rc`эn5쫨QWqowe)) ?\)pG=1m6h$wCQҕbqGXfmuTJ)t*ց $ f9xƾgyf2]؍}+<@&tO! ڍ^bFuf&xͤk߳ {9Gy A$"T~8C+5==zl:\ռ,e˖,mIMC69,<#- V:h't؄%R D9,kY =̀ԥOTyb3]E2JZJ\tJ$-֩2ӆ `:ؤ]Is\+$ ݲq#a]md~Qz@Q~0VMIFa$T86%+rQ_끱qf0ж.Zg=Yy:%/ u'hڛtj|ahxFz;ޑ5 4AAa# vFǖ<{MZG{YnavD+(;EzPێY(:sד4`vUg#yxb<LkSN'ZqQZAZ>鐆 $ۙh:J YetG70O{ӲĀ`&0]p2{ %zh\teE ˁ"JvQYf%-ʦYUi||Td[xP,mh=F g2Ta:(盰S5җ4}dܱ)2 !Y2`!$XI!z]Qۘ(;SoTYN2M$=d|Kc_N @26C`Z})sWQ].A~nW).Hp٦MJL"mJ>krd,nMtv POȏve˩ꭴqZCK t ~7Z }7/j`j5K[&Moj^ E` 24#0aGǩU&:E7AQ05Lo,: LDņgԂܤrXJLDL0?3I$Vx1`"=$rƲPg0F}UJ˾)'c8+DT', .Kgc2ߔ |h;y7<{53AHH ʘ$l8؁1 9F_Zx\q@9 N\,&|4{ދVD)Od)hwK^ 7 .B2gg72#G%D1c9bXn%:ă n<$YA#%G[@|4v|F{ֱ06O!P#Cu?/ֽ۸5u*vR%U:R-`N 8?Rm D ĥ`E ou ꃁC;1@d +B3r4.8؝X5&m(#?bqy =ˎHKV +8+Yvf%>D`>o4Vu07(,WӶ>bHM̸`cEɂq`~ޏhN1(OXAԅ1XgM mJY#he =)Q1owG:t%my6vc^~;9b֑<eIOϵ+T;lP=98A?Z~c򲮩e8j0#9eU {  jN*j9NϨڙ"HJr7z4~§. +f &uQ=TK2v7&$ Ҟv`ہMO-Ͱ)&>#Wy$~Ҹ6qG?V #yBBR(IPM*lOJU^ܘux5ҊľUNW^Qӑqk 3[=3V&62(`9F]s`0n2(?D"]hQ]VJSu ;3PگиzG_*$W6pJH.Ge KuG@GyIx&BQw u_8F$Dj&3,Pǰ+_qsfK4U{ʰJFoWT)b: GwRZ xǁ6 hU:5O-HnP;I$-[4ɬnqy.GqT:*  $аhxֲRAnB#㭥dh_IkI[2 .ܴiS Q{QJ\OdLMJZk!b`a c<v8#!$VR5Zm52v5Ol8R0BP{DVҾҺ"b8Z!LRl.|3@ÙD8WqbJBW I* U D BYU2Kv7MZIíl8*Lb#Ņa8Z5NY8WYG%ŌĽhಳar6Q͗OݗƩ/K)-٣-EXVOUT߰-n\g䝫4=j+ /KU>t𳏌IV UACxӕdcZ_r@0_D&QjrH7 2YZ*IW5vI;Ra@fx='$J$7i+Ҥ 7iq4_VJFuq>J|ז;mǭ٤SipFI76^.ZjDHF*ņZmxzw"󤾣mW?y*!Tp^KQV>,|glK0@0?EO)UL-Q͠Q2y[)m|=)ٞK8u?I\i%a$wDX%weej +ڸ6tdQ!1 VӞO5g5k`>qш+e0w0o|ߤ  v)7qAen1ds0N˯eG7cE%GxUAO *{| VQ rY 01FGW"asT*e3l{?%6ʃɈ gy{^^΁\)lN/K ǝ7I&qhigZ7 t` 0}awau");a%GBQ 2abޣ=V3HΪQ(q,ڒPU$$>3@)|2 ]= "i9^p_ЦL?;mٲ%f#'ޡn"]}a ckyhkZ5D \0]?UA1&%G£06#3&΂ ff* dTiT0'qB;|Z'AE|WHpĦMҧ>#zU~iJ\%>A𙳿^hLr)(Zb1ŒisQٔt<7F\]Ev]vo P{ $qxLe-BM "Cd4ҧ7oޜɏbW&M Pu(\ˬ&%]:=GtZ|j+d*aA$^n # `!M&$P-D-%O$ɸtR|Apr^TI:N_tĕ՚VFm捛fl]a73 tq}CGQeQhxM0`GFZT UPP#$kqD]D A$ /?T28SNɃaT5~G'jV]Ұz9Hh,kH\8 v[jx 7Z G/Rxh@ 8)0@G£wTm9st1%oz_ Q"E)jX ;Ȝ8n悔vaR(GTy]<Q$i IDAT9W4 Ft־7P+AhLQiJL5`*~#)6.`y7/@ C0* T0b $} ڸ_艏ʀ25|MOk|x M;yM`"y >mê9㪴)͹F4cCT U+rY{XУy2T{"  0,6;^@_+ }BpK#0QG5pfEpF87Nc622ױeGxxރ?}i% |cx(: 0R-Q-棦!0]ЂH򤠬Z%x?,()05gڠoOEHpXBW/MQ^Fd>6hć䇺X %Uy<cv}}TS\;%c.j eT3JMi'؃L!nA3$CM5"q<6 "n>lSgyʄtx̟ #bò6 [N8@;})I-B_́5j0~dc} PVKk[SM6LlRɨYt&&((ri\yF(z`bpmu3W\>6o:R y{KTuSu9N(m:&gTlYIҾfPg &闉 &8:MW)U;>R^ ;#acx!U2L^̿:'7Q7)Ŷ|sL[_K]4FZ.V{ 27R]IYX})#1{1+;Q/" ;6DģS# ˵8} Y '`nפN՜ƾr?v׾D1D3 Pl1E}0&'EpҸ<5eX 4ߌA08 hپCWjOϴmlkf2$gPUGswqy .6`pW +D6uEy/C²:[Cڀp6ݭG6dx3籹%Q;32)u{+u\ u90:D&xyM*U.U o(k[&.sY뼳<j-KJQ30 GipeNB0XġNly+`QQ'#@q wϣ*l+(OdT|GfU#N< A:Yt"¹+3!=5:)DT&t_NyuU]YF= ,fTQ2TK9̋)ɳg>Yw\і`*+ L.vG9ߵQV}[kڳ(E, pc_b9(s'[I?#8vG&=6ϽT hRx_cDmte-M,;KeRW拗RaTEt0##tZ35'OL|Ta:?#8Gs1Yu#|_ Nҁ]ߕ#n3ĢD+f[޺_uaIHGfs!<Ho{mo}mB$_[I7mAz| }3hTɛ2pn2fTӞCVfƹ~֎Ej gTPRK"UnJ3 L-¡)ir|HH8UU TP&_T7(2[UF=#>$YJ@E7pE\^gnX[2⤀i%qCGe[ ڍqg27*Z>kM'_ھ7Dz <JYhEڶON-DISҰ{.#Q\#/X6~ץC!M)N'~i ľr*"Τ;";L1+Hֳ7;VFyW\Dd iA" )|V%BIUg;@9 0%ͪ(vI{9pW@عT ^J|:AM8Q^G ʆ^di4k ''[X'g4a5Isks K}v1w;Z}_C/ TbV:\H%LOFUYP|]DP6,N-8aI$$*_RʊM '8G0?>n{J\L:<#{17eMh޽Zeu߻>߿xC/0Hr1-x D44JK#mǣ -\E zB#4^(1j D!0tSU?Ϯoը笽ڵ벫jzgޞ91ƜsL3wgI`Ij2;>)$,@TK^&)f.l?R$u>N{ouQ;[æs2{YFs6#oh:iR=[ffAO]y%,gO*$)NSY\ա!-Mu|z.ҘO3.SW7_K46x 3,|/Vmky} ܄M~o#OljYh֑j˖tܵk'+nܺyd 4ʎw5zLiGS->#_Ѷw:N$[k-oUiVֺfũ`?FLve9UHJ*mj X9Kk-Yѽ:T2vɚ]@`j훤3oT lQkaS(.)4jO=4۠zR_~uÏÛ@iC!ڍeq0:cc:,:Pт#Ukbf 4C-c q#L}'Ah>u*Tkoy$=q& * (Gj ق_|Nv r~<~kmWɧ`um@Gv;xVjS~FozӛӾ_11|xʃ3MΊD@FyG-u( =+ ?@ך0iaߩ~/ˢol c"m ת|ѳ֚!+]Ci1U xA4S%3&5~K;錵Oj*rQkפ{V{j"i ym㎯986s;F\-Dz'gѺ|zۻmÓ_;ANԺ_4odf&~k*ݦvŹg:Ev†xwk*~5H$E!R+O6+3h5|rv4zJfg'|h[GCu-M}=&8MI"S=Tu_7sɔ' {dXO3i_I yڥAXD.<+=]$7N ё7%sȺKK2d(n0RYLIs2P;sYojT.gu,owߒrś6$|ne>n=f6W~aj$)J+[NgI1)iT7Ԗ\}.Qŗ~ܜ|:j<gv SuK{ݱ {818ʄ)؄u??t j߸ l~tޛNxޤGϟpzn pmo6~xMMHtp{C$P#r"LH.QfaK1̒ sh5aQN#nEL}StI2S;te&G1;3i)1BSp)8G=̞ t& x@# 5isi i >am#ͳDUהX' >TsCz~DȮY |/yO_{a"reC 5:S Ims0[;)sҧ"^`fS|x$[xZlC?u eE:1]e&郣]Ug=l=ސLl18D̑ O⼕&lՓ>dm ,瀁LXYR S/[Uxʲz<|7HOJK:hqZW 7y6B, 1˿ {<cye'r۔:i}'|xJ۸Ts> SQdPFnSxUh$Ƭq ܟ_w:Ն7jKIx^Z@˾cˤ[eFLס;2R:_?QkT#IƳ$G#K/CY+iP5}IHZRC~zDJ 6?Ëj<((>͔f''ohp"=wsϴNл<pG޺-tFN+|q#Fvq 6W6"@ q#tِ1oq`E:` /^4w?ywOSYIjBT N,QخTߨ3\յgNЀITjm -]cxmK:s?OcyZw@O|^<EM(=?tz%8<S#B E22ـ0$bY8Ħ==ˮqETe(a~*ZfǸ!-pD'm#e2DitIi8{<8Q ݠ~3C4**0SFy6Ŗk$#`kD0ċ$L`,;V́J[m Gf[Ĝ@meä5 _ ,NjJl 'f+<#:7NoG~<(J6a(Tt&v3SAG%&Q+/vO#4Z@"5m&ZTz*:uJd{&PsUmT֮Ѽ}қOZ>'֦:f],IĈI(lx63ZXY IDATXDD2^X9MzTZxvfxh]u6+F;hlNL~4n_,҉Q{>\}'xM2_0D3FqK:\eDλ$ FzsB%(Z@52Vgj:YsT=wECTI=1R}W|Wv6!ZE4R%~@L-ښdw{I?i9$PW5^佲̶#Iy{A$g }~(imyW2YԾv\}JkkmaTngSz-Lϼui*&V6 z45Cum!)\d#Qj*4?K3bB!9@m؛4kˎW]|ONkAT潫NgIY/|[KɴT1k6yT,*T@8k,Ϣ;I-lqRuvCmyk`BjgZ$[$R 隿Y6@w˂ G4U;rΓGOUb:V7OiGav,*Ǽ? ? sԛ@]&!4 (a7uCfSgʓY@s\:pG{-D~yWM ƀmgy߷>`Uh]y-&ZT㢝&YE(dvQRc5UN cN1pJ& H̻ttP8Tfky= TݘČdpI} Y9XNI=Su`4w kP,Γγ^uշ6 jm4"(lݵnEw.A3O] REmk{tbe_3cMp|ZvYlv̎_t]'+l Izw ׫zlzKqz2>y:I!p' dRkp 0qS\ii. ޹I*23NYd]OIaݰ=kT+r! =$Li4"vg0;U8'b2I-}Yg<_KISF\[ٴ+{N.<]$ZʮF[cxEfj1,uzѫAtO4;ڬF:E4MA&4cs,^|]WO3F 껺nvKjk?ׅ`m0A(Is`;-z{6漏 Xeg绢YhޛqHn"bЦ(ݷa ' $#,\R`yw^iMFdS&@Uv.k&TQ|4;Z3,Dw 劭v].Idtk V:+> R^cgc]Y>1?gX'].Q;ۢ}fB_1eF Q.-VSڋ|DŽIk>1uL6{U bj1#|Sݛ҈x)YIWvAReS/Qu6jPlͶf5j{qc WfJL͠Nxw=~Z<:"^3vqFujv @q2ݤkTliTaqmZ֑,dq39] Sd@}'8k,[r^zy] 8a礊tN -k[GY' ^28 \{<=k@(ȷrH 6EiL,KEB)VN(7;a@Z< U޺Qcn;s(jMV|Ӌ봩:2mhO9[%~(yv8FMϠf 5/i8iNw25W6#ԉeمÔr#\$-TTNI1/5C10/t{/rTݥѹhJ'C?PZ9N@?wPo'<ڦv-xAZ!96>q/9SbK Ny}ڻuK9u RE'>OwGg{ֻN`ipO p҃O'L];M_;TxLutYB6w=-52T^̃ O)Q碽$?-EIuspCqit|}h0=O*s|^+ lR/zJĐYQ0&n䯜VtjwQhG:}4;k^;i\sPXK3tX&OO^c^9 qFxWH~kKTmaH t< _ >ߛdgLGxHx9X[ΥT+?}I>=tQ`_3YיmayC3۵JzgkbjN743~pQeCvg`2LƲoՖ-g^CZo!'u7I+̈́.Scp&50TxC*Zi 9E:8Ŭ/rvr+wlPf]Y&`1pg94Q`?L x}Hj<-ŭ?svԾN9~ҙ 8'uTTm?#KM v:guǏI"e ;RN}oǐ48EYD_u:oz 0I+u~7J-yl#9K|31#_U_Y깳1|+' w-E?ӮsnC0B<6As00ꗉRlJwBZg>MtAs K[;7m$qEOxQ?gBfPdTkJ PӮ8Q?}q/҅xޖ/ s6 Cc״+[W6e0i,NCpo yRϺL:Ĉ=51f$<F&V`6,Fb'~'.@ĩ38[P1idr!,5sjP+Uk2tQq8ٰ yTMz2xjY|6EuoE CՋk8IznLrlֺ$_ӬYgr ̫;{P%N^-5z贁ӈOv?:4.1;58疭Z^ɥ.;L&21;M"f*NR@R<[i,HݶfA: uQ\~`M:|RQvV$3n Vd B:$1i0Ӝoi`A3j=A?l#/},O3´~[?y$hm>" . RS6/]Iy{QT SR3Ǵ"}@miĝ=b( ~XN-"9Lȁ7/LK PFS"ef-}R ' >Jqթ"}|RTJftB#00 `{˾6pk4~Jw}ƷrΕ ¤(ka73p&/_v\~> }xSsMRm5<׸C6$1&:0d2`cg&UVugy?Mtk LY䔽HX}MnM-IIG~mM;>upo wZI?󿰌B*ߜ95٩:B`:ۗ0MfLg])~mM͵eM3Y0}ꮺ=}m*huh@ㅮ=F:53iG17vsU}~'a;lBAv=ݥ# xcᤂN[9=z0S ,ZpjQ|֝gJg1& ZwI|"d1*Me|@0l_RvrTW]& `Q?⭥M@6ͼ*4//j Th'O2w=MH{:+7\*^7ŘzJMs$lpj]F;a ]4fd(C1d9g v޻R}$ֳJS= }W`u0ɳp}OiFk~,~.oNޝ{;o:xoX*TᏓ0\ܨlb5M#x`8j~]1)la WRb7ռҭ[ٟuR-Ej}f7Y|^s~X7k-D]ϼ'~Fڿ0pcZ {~ ԋלdHQS#| X>1p4>m)jNy7)ٮAo4E;:dK2uɊ@0 Mp@ )'ܛ?Zh'.:8yRYnnM<ފ69Mą hԾ[`|g2da{>q2&$&Xc 3i~`uT&=Wɒ:>|нuz:n75uךfZG+Y盳ڵ'ꘝv':L51߻Zmf )]M*JkV|{ ֝aCG(:)aӺE]6;Wj+4t Ѻ}m6U.3M ^xgZMgM5dS]?4rZ۵k'R@8WbM~K)֤J8E~ߘz|6{-EYI*}}>+49HTS |{z:ΪM:ktLjjjR;kɭAem4<3t6ŋ U=Oj{ZgvM@X: |Vcao&#^w!My9">he]Wl(U^D֞^^;Mވ$KIHE@8m/Qbr39s 0ia뉎5}g~UINixIҳWi< &qs'I GߝU<=] zmqd#ψrp.Dn99"M6ʯYaH\eޓZ{9൦v*GGzەŇ3~OS{I~qMķ!$擐9fgރsds%_a5|"/qpkh鐦ʦ硛gae<ǡMp (Q`n)w]yƜWgMIՁ:\\`];4l.AIےDKvfڒ :~n H펩A.Qq ^ 1_kpn0OQx;Y o/*;L3Q0%L  \;S^mmpO" 0}ʧ|rȓ#< ;1Pe$WGy wtBLJ=~)8̖F6羁1عf>7>.Ԯ:l͜8쐤ݴr$7`L(W==Z$d2Vg is`y8v sߎyt_\.!!]G]w-ĥ7:st}! ;dZҀC|>?yC&0;:]Mg 3IC&GH$IST i^T{&~$&Lz)NTf(\qr6q\'9D[@W^fs hXلڬ!$Z5q0wI:It/IV `bTvØD0o%ng'5IAM-F;IΤz]eqG_|q00Oj'Yc"uV]VS,Nc3$L'd/&J餾jq?̀x _מ,#g?M 0sx IDATE6\x=oDL#ꦅ(wM9"џbؚ͐_jlYؤ*Z/'uTɞd&$@iJ[ T5)ULà6'_v \F0K۳[ŝﻧGGk xi;,DCP';6 ֭ulFsB*MtQ}e|%}i1Kd1p;~ҩw7˦ I%M2Am򪳶.Ll} !ꑩ% ʯjս]?w(;7*Mߩ{ |tm6.V:K`19::Ma2gFnK: a$$,'sD-d Ctqw.R3Q"K۾ۖI"z׻`eٺA@oDŽj9ɓFX027߸:,~oS7??ڃĤz4ye ?%6 fﵵ6`3[/r4wԏ/W',xlti*3wlT#N8W6h"q}-F4&U##7$'|',v)P;_SdIUoJHpy{&w')~0qn2_Sf۷~.zffLDʓLIhk1@ 8)uOvooZ&hk۵ŗ/s˕$ xLrOĚv3#ѧ~. mw;sis&Z VecOriPT6 }֍[UUn~חD$_ L*o^E ұ0Y;X?Y9Kj8PqLMcOiI˦Ht^΀nK6߸N%MA'ZP3Ik>*xȻZJ/EMoC-FI)2P 3{,[k$i߻ ’9I i.1HY4/Jk8ſ62ޝM(*P6A~>Ȼ^8NjiʆّY7S3zE+EI%E hAD=/ bkk0g[: z6HsFw[9cQ}ri&Qj?>֘b_O.a 0W>,&].ݺޕ}IE57'?v 0uiYրV)쌅iVTES Jsvd1~.߃yfͶ חܷ#Iev$&3؊g*L:sw?Vg~geJJ1st3Mpץ3Om`vǼ0̴iN)tJ¦r-G2KK/- -2@6L;l&7LU`/"IӬ0P6 P-1ab/3׎IHŜߕ&x%7l}fcs^mt^}̲S?fMpi\GCj3XsSRL{m6Zt4P3Bۨ4'XţkV7掋]< 9yv_T*]==8:2p?Ѩ4bF 6F%==|`5UL-@"綦mq h8+GM^,Bm R-aa ,F:<0NF=<^&\6 S=yX:$YYg$zmOsz^s9Ճ#{ڝjcsUxpsM$L4R/M 3W_]&az h`'9&%fT?/ ΃x[ߺ'c?cphR02ٔE.wLHN:=lAOםkN8@oJ8g&P`9I~}yFg*AS$\Nz=Wf/.4nJ{#d{.5r5RtZnGsr5"lA۳F(`abM#m cyFe ġ%XHdgDF(5l[, 6IR}<0u8&l /uҩl'h<Mg~g `N\tմC؇gM^\ki;ӎyge0 YzvG{9 ́ka>ӖsRx׌gy7sS~t~}2- o8]O<J|F ZCnDoD]Z26AZޜ_}pZo->ɒ  `[18j'0 =lWFfڥ soͿhlylp1Nن9NpD4m@DzMAHTC3VP~gi}A޻ӮSxo~^E WG0g4ԌnLF,F {s_+ c{N -Sv*mB1v<ԉbfMH"^&DPvAۡ;' a$0f:J\K~koR[h l?HN\k]fkpLC؛֒W@X]˒ H>cf`7 Ȗ KMv)A AqM 4ҞmX# ϟK'> /K j@hïc 83Fw / E/77߼hF%:5jKK5`{ʃ9LL(oy,pٴ+iǢz]R1M f|??:lkhJ~k){?>5K!;^R0}$M:z_^~(#|Istsϟn;vK6T\ V??{zA\aZRl*#(  ŶgT){ο/nQTL_tj|).t6ev$i{@h&"l=If_Ҫ]|a鴋]$^ 㯳xL<J_+RW,LEV]Xb֑$r Yq{WLE1a0N^&7jū\ #wm>}##\Fپb)C>\"$\2Uĕ4ݐJGL?;3c|W~2th2A5!`-i $HqIS~[h_}̓Ȫ3OI %L'>?l*vƉ܉prÅ%X||gQBb^İ0S6i=k1Œ_3uku? 4f'< VUGny,b>l,µ_4OOYҧnc? Pgi`W#afY;U:kimjY`ikkBT7%AgΙ%ܸuw>Iq>զ@$0ë~Z`Lu!*j<%r? tI#<(L>KcƟ[1we.S8PkcM%|fAvWJI!uYVoX1$$틀4Th}/:yp' O*ۛi;m]aOON5@g"鴋HMp:KJJZH]p>nbiJ 7[ZYqʳ0SeJ:@Z,KYԟ<9ICdVE4Rz#+ ׿v]$O,.[&HɄnn[CϥW[\{z( ` ז( ,n@8Nv ^Mi'M6aV|y&ɲURIOf⚸~綾^g":˱,N4+T'[m$='jo`*hI26X-©=gMiOf'SOєH;*H}-]Q'.'ਃpOC5sxe2'L2E"8 7;S@K3m;U>4'@+SylIy@ѭ7^g`==E|d,$~4>Or7:<)n dKI`Ͳh[X$U5[JgQB PZR瀪<mJ DiXLK IjM@3ʽHN۶`\ϬpZ5#).I'YLSJ#g4AS=~De{˾Vޕ' MTR[j<'xǶۣIT;N;Uw%yO F)%?Σ8:zdb+x>h|m R K"x6 `Iľp{F3A47*le(&%3@Nj斩==`_ ԟ:es+x499$,cd/&t♅AewƋѶqM瀻~=B_@i(P7[V@4+{ޠT,ZWTׯ__~[Ut18oA߼gOI{a>Y,cdC=M`3[[? q翧{Z󅃩^}Vvu5`$, ,I`>|2;G]IX/q[R|}2k_ dw/swξQDv3S*sfo<%I]ݤ~Ҍ;m@t[\3J$mx;8t;p gDջ4&[#uع/V1{r4ycw0hcJ V X `sISRx%Y&uO~5Yy,PI] Sg.*v77LM}g}4ڡva/“}]3W^ye v&9R)kGӗ|ɗ,g2ַ.X0 znD?!t-“@*;f7/ce#HpL9[ٔG4wG[=(CSZw=4 L5M6 e>c?!Y3o'e;|T\g',dW>1gFkVᑺeA$},gKv PImLZ3+ IM<6_$/mJ3pz 4-$r#&Hk}g$Vi{x HdtZVceEvQ:ۦ=)~m6zh@tF^nj9ق |gSh6pִ{= Գ| ֕7{Oge;d񵃵/E2oTڞ/x r ФC'R7-P&M-"ER?&Hׯ__Rpcf[EbZ Hy]lZ[;7tl@-+-9pNj¦X?z<4 Oik# Հ(3C5l  _b#bqcқL2վɘ MRO=l:369bCi@@ eA$1Ge#QਮV'h!q+je[IQx&12/SšZaNeg(0$ O8iO].>uO~CGgIfvFgIich;)TA^=íy 0 e*|у]*So/κ޳? cf}PfaJی>P\@H=/$,;[$>)$ Q)_>2nz߾IZ깅6,7y +\PL67 wP~ն0߳v.Ѷ2G-ڏ$H/gO.iSlr$Bau2@1kjBOTJ3EcpQ!~.*My0j/-:77Rree&ޕ-oy":7wYfcw -qMUBs0opllWOJlQw}==|zڡC G c4[ DN4O\kkX&نI 5|`0MNX/ y & lY@lrCYIz׻Z2`7U@Ҋ$D@¡ɘD[5yT'~($PǖLs[!F%jc91W >ߘ&WiwTXz2IHjIBjAq_#?Rt 9˚~s>Sh c%I֭*wqiLh(Jnfn9Dc2gj|F=iJsSGq HRgFv)TT/ ey|I`6 16a2t;ʒ*gisШ'Ug i(tm/բ4(@0҂̰-{BsYi/ɟS8eI#m?'w? D±_Zc"fҜ-oMkgsjJ&G_r$eLLO;><(hΣ92٣:I|&ٰxK0 yN^dUWe 7]eY@jh@|8gYtpReQ.RӣJ^pedTY QoX:jk$N\cZjFƭ3L1m[ +518Y_NP[e]77վIǏ}'8~/P-~;T@W_}um ƮTnҰ'~ w>Pmd~i.k`k,SP1ux*okb*uهPQd֪P)/ҋ/x;W g'AmϫCA:}i|ofRYu*`3Ҫ]=VG[O^qb5Lp53j+:mJo>/]v,|i:dU^WY@q /|IŞ4swF/P\l<\c[li#rn yKc2Ā7SvZXŹVwrWGpݨ^Yel{c-NJRB^_˒̮6i؜6.PA_XRevQ hFl3Hrtav?_NPn@7-|pfZf}44 th4x~DS S#^| {Z1@K#Dcs HvisVΤ ͼ|JC3La,[NI\#2z$N;s\0%IwNR61ȓH+CA9F0Xp<~qPXvu|^:2$yKRxrtV^ij]{Jc+ \i\O'a0qm6|ݨ٪TiK\ӚɓēFR4.X}otV'c󺽨T'Ӓ6'jxv\~})KΦ)/Lk<ƣuLFaUfJg =;pLْHG:fMޭ<`XC}eU+ Xx /$B*\ڷi`<׮uK&iN tKFS?i@."4wnTj UkN_oJ\ΟFlj1y#E;Cpd%9=Z3%U-1_ov7˴8cHo?B1t*si)g hգ>mϲ_Ϗ]#-Y 7 z0Nٻ=3 0H ,2. δ geH[(9G /,L3j܁Q#d3]t@ -(~QFuire36o3[}$:o%ң?yyQ: O*&ۂ^*a=;ϔjxnNDU)L +|~}i0J*ZZBt 'Ibo2qa%/{0 |$IWnנsQzXOڗbb5ɭsaW Ĝ cMqf=:@rd3="](U}ᚐ`#p}ػL@(B%}Y ZHJߦ{bj[*/:nak>9KD3nP:ԪU'I·X_\ԐCBΆmpzVҙ|Μ߄ r*R̷?j5\pVwwG#-.kIffI#&~5_S/Zڊt'\ksRY,|1fq]]K͑-)IwѤݻ9k$*)LllTFR"ENυWfcجr6LzhOkP ]5AMU~ Q ʖPsE:xڳ}MQ' z6%)n]/%O"uG4OAϵ3> 5d2(RO=dI N _ȣV y@s^mlAq56?{O??6FT{A^&5&`X"gxg:S:g]MF4DŽG*p*Ql="? 1tjQ^vq:%pCSҗׯQy+H_<֨7 d|h$5(j (:,q!q9U;!ldЖ6Ǭ&NL)G:Q?0ȊkM+r5qV=O Ӧr{Ǟ2[M, cVfgGw ߿D8'/H-c%$0 HIJkqwO9TF&IOfM) uԐ@_8 糎=T3WTpߴ1O2Ũg=k@ N4۾LG)mCO|0[hI:Qa}.HtFlseS`\:w=ݥ#Tޭ>7ZR]t:f 32jQ[;էg`gT]1jWDZ#ܔ'_ۧw% $ހN{;ÓD6]ԉw_Xbp͏MXTO—Vŭ= |<\%jPZ]=Oޯ{V9{~O 脱}F?lCgN6^[άaC`E٥ LYRW`1BܤfK@,bPIŽ"NT0G@eY>ʓLx#@ɬ4yeR^jFj34w<OwDu/5et~~qzhֱ88(m؏۝ޒ/y=GF]hS@'3SJhFS24~(g^î~v~^?ri@ 8nNS; OmwX~6K il5tѮu<̇]w5]Z| QۙgG?|u}t^G= R 27Ӟ<%ai RX*yCg YwmRef&`>-QґҨzF|n== ZE]j$ioL%%]t6Iғ6uċO+9KR_(O --&f=O*0z+PF,Aw'UOu=-.8[`'g02=fӳAXt= Mrm6mmnTh[m_sH6qK܇AGox 7~Ͻay9\?==HJ͝@2ksJ$~:~o6 lW=~\hc[DۅlfZ] IDATO Yۜhge`HvuvmRe[ȶ`[kh5];Q;x<utَ5iZ-mϷUyKsMG1Fnl=>][h= XR1.>/V@kNwq|FWw=+&A 4h$,5JG EBupx ׉z~q[a==rh/b>ML_ Y3Uh֍H'UM#EhɌ4tbIj?=G7Y4Sĝ[삒9nNTf 6yoDӱA<6 SsPZh[Dϣ}?0Exh%"tُ_N' vpbwg ~p $:==_wỳ駄I;.v^N=}8o?;#^piٔUK``S$==D80|orMw::>8dVSup$xx_ U:mhk9K'ݏOQ}=Ӟ΢~jnG'ZJX #PeYYetz#E 95O>.}Ӟ ̓7n1ORiO{Env=q6=iO{zZP컪POUE,t6wUjC䟥-^ v"kTblGA0{϶[lguv/KNa׃LMepɻ3:Z6Xy?3Xwʱ m/?rrPmWϝ@v _bF^~$8{0S=SL\5^e=w҃?x4h=Xu=L@8<j$}l[nʰ˙"zמ!mK/ :IA^{Ĩ17IO3&?|?_= :l*\8݄'00N=,ϙ6qM B-)t{@0@XZ?3?s~p]v& 鎌{|ߚ^o;1,cmU]|Ͽo~"y#'-/*} (N][Xqi F~K7a7u`vg[Y2 {VY8iwuMoz>;`=UYT/q:<;huxTd'|:Elg+l7שM gJ ϻwm_=F=ԡp;guww^]mn=|t ``xhv#l?s?w>;iJ9L0hX^M: 8 k:J%-::w-NitHa*no=e_+~gv6 'r*:'ei-{w rf `>k]s;[NF>kOWl:_w??qK~/3 myRMZgHt6[;AlVE^uҤę&q_~{M~~h>,ٟ~i`;6ж hS|o/gOO g_]KЙmGIGrs7nj|x oa֙t_'RWP+~.;ΧY=QҕS>*|V\QRHKZ^-ID=OKr+df+3pVu #}.1**""ʦ`ʢ2O Ǣ@ b>P^՗U_KUW?7?9y29wegU㞼22ʑq?=eL?6rn DZk6:ݪrP8(K )W_>򑏤/o{c|˥388L5=r^mԆA56imVTIx9yzPt:'NKcqW2zKֈmUjwGy$yڍ78ߏV[;#o-h\G>J{o׿fa7ϝA0CZ;%f/oO=P&d;"n!` Fub $Q3H4<5.% nآEdž1 }ݗ9t'k!/-]4uYkIon*~~@&w=]J?sC?ӹ۾/ȏP ~_zi=L_}\x{ҩַg}2`ƻn- ԅ υ N H́\ַm鮻ƀ./8N-oqsI{l&u 6<3yg?s}{iN˗/O}Ѷ8(Rکoc:3gofp@RM:f /xo &/3`K >A>D~K"=f/k!j[:r9 HOSΆv8&29,Σ/QBz$L :묓[ouyERf1Nqɝo~s&JM׽uټ&=.P$&_M]d"(Zש v3g v( U/zgۅ:fUˆowE_b<1J&2 1;KHs2FӇ/p%ӟ $; 0&'ZyAjDpB#[f,ǣ:*9'"$7F(۩yH K݉ q)# ?F.h\hѢLuo:Ѝl ʙr&5jDmxYg;J/veDwtk4j48(~ 87;lٲlɄ36Zңua'fN;*j097>H禛nʾHʋf[~LPzA'Z~:42/n>BIOx8 8=9d">Ũ)q5!I$oyrMozS{]{[*S"!v-QhN VhN4٩~P[cg5L'.!曕۹7w'OәME%_ғ(hȉyʤ&-KӡELjِPnΘ1Mpf j#CL4Fh8bt3 MvA;/?L@`N-Y$}_N4L2GlGp:#w:+dD !?#mY:s@4! . V7"ǜ>#Čf&(y.4vr "~?Xbw`pE 5he\Gd Hdҗ-Ș| |䈖Aƚ/zыP@+#LuLhVՌ^ׄw0N 2ChWypLMYm9Tƛߴp6}EϑR C?h|Gcѧu6:HN&CG&1htPmIL!DVüC$?: yɉkdrzʁFyWO /N+f_ !B.bNg9=Y3n0X@^h$@yC׫I1 :(~N`,x~劻Ƞ{$5kјbpJX|PcH9SoEKL?ld4.WBǦߌ&LhfIqE m4j 퇙V4#&.02JYZ䉿HSO!oLfX>ءYHLvL}Ntۙ09 󒗳ےSƕ1js<,h/s̆jq_CYG5@O'mQ` D ;V"ȲNyoZM'*nj4J8RS#i4D8ٸoKu^cǏ 4/'~=|`:&DQc0ؑj?iY5B")K͓<~W$|X"r(dGBRy6?m*^_@-(x|*!,U?2v.\yYGʂOBpA%~F'ae "\~)D$Df$"F"7Mr,/GRUtZ'yq>j 1H =%5rgTdASGJzZ'r)֣.ǜ|Ew,DQNGB K|h]zLb 0md*Q$Zƿe5>eMpW~qPP1M$I;Ոnx^zw-wMegFHyN'*˗xyq`j}u W: ;dVbz;K *9zN(obCS_찤省_"zv.;P4ϽI^$pagvBg ʢz ]}~/ yI㲸~zɠW{Ū"ߕ@4wťAmdΌI\ݜ50ڠ1dSi"^E܈j'A$bhޓ0jc!ym$:eΧr к4m&э: Ћø/r d84rsϕa$߰i/=Ɠ7[XUɤWǙk]5l6K,i}GsuӀk 6lu}|Ct<e`agm .τ"֒^JSKL$oSfJ `2P^t68^<|؄;Nޠ-8}h"s.x!9^m1AU:-q|0˖y5^f1kyqsbjS4KG\`, SGz۫B{irD浛ȘwNʛyZث\wC+_-ohi)&CFuEr4jnTؠNvX;kL#^(ʹh *-rnHdp˩u6jw3ɗ阽lCnaW754InXQb gox0ۈpqkd鋞2Vjn .gG ^45CIjqjzN-%jhy-O* H^LSyE5E㦬s_߭,qXuw3AL,S,$mqLkthZӈ<|tlBRH|"6i3=P~/|a~U(39Q]d%G{Ʉ?Id=y/絒v"1MCӍ8A ##@1l+Uk_Jz~ M7`kFsAi\W? NBG8묳_<͜tIi=h :jv<:KM}j,;ӡ? <VZ"2-t~:3'2;򻨑٧>馛O~oÇxu>ԭ>:5ǹ}(1Ic넉є8[,w뮻.{9^nwnv~ө4[paf3hz☚_ZD22?? V?яg6||ˌ?ub@8sOz;ޑvmt1dMrb ـl.]MZbЉ08v-;pm1~ӟH^sir~5wqi=%s1~_SPt"da<2j<ԈkD~mY;s|oe5 otGcTWsm9G#%f7xmjmwKmQRr6XbO~?lFө& *4>i->|UWv!yg 8O|nȉ'Lp]veLsyltZAp"h&j,f[ׇOȿ_k_ZU@",oUCXf KF+mhGI_ 0hE1|KM&5u]<)Iߘw&c[9Y ~'x"]Ll1qd X>`@%19:5 @h jVbyhU5T'Q>ub}F+]1M1a*tL[o ɉq%d3 ގ;Lx4vJ}JHl,ykyod%!WԯaHlj]v%kvX9/7Ո9{!Fg򟔘9XQC pξ#:_ 'Sl#>v!LbueDI]lY6M{Ї>sO"}L^do>0Ϗlvi20u_-u[cմ)>J}Ɠ_/AF_g#}yv+D|+Ow^6f+2_IDagg!]LmHpM6ɝ88{7Ǽ1Iu6xlvK#t>ֱ^u^eltP%=uVdɒv0r .Ȯ.(םgDO~ WN}t)hu`O~#jҥ^?MobF6PLM3=ҥKs~|pXo94O&K|Sߐfx$۱(`N~2P,ul%/yI&=@ٸSOMk@ip<2vp'׵({uQY|yMdrA?ȣ>َoc)vN1qFOޘPtf]!g" :eL9Yf̟AܓNr94AIcp<9?qlf?~^Ybv 7kԻK\&&2c?IJl@ڝ,q-1uߕ{sN9ilj(? o Yk IJjbIQVKLJv欯/yN{<\vR.?CWT:vlKlמ̕SE PX~A?}(/C㜯uP|2[)[?׌i,mƳũτ z-66 ?nF&񨅢Y)F@6d:ib;DFޛvtM͉~VN:ߍ;iE2tM6 )2&%"i- m}X?K?ezb;(riz2C*t.%fԧDh߻[Cy| ŭ<ǧ!/^k[TdQ03Òd˯F <>u1>3?sPeϵPv1Ʋ*o2jb*a9ωʳ62)kF8<7c242 9$D mF%z!6"hɃ݂ņ5n(ާ[z5s<H~dwK}`$dIa% ?K{z~/L/0]Yͣ(ND_LN7E|W#Q;gָR CokJ*%f-IOF4Vv|Ohiٱ];uCMxHaָrM7{ R:0SeIE[%9D233A; ?| EbG4iח<DX-h8=qP-u^\sj&|Y~Iv0e2H'> OЯ22S~M`F`͓-mkw=ai;Q~ s=X'i 2gTcx>wpo|?}dkOL׍CTX5Y-L+ω=d It5xn~7]z\4|7,%Lv\O20QQCE6**.yoNAg=ZM蓮6nD<c8V_h4>O5;2G4Dʥo5MZy%f/4׊ b DcEB򛿸%kUrT#T;W%㨕gF+9¥p*%J-:ڂ}88:b?S;i=XD-sXzL  v`J*DsZmX==hEMg:&qO*QXzuͅ ?z:Pk;wUJůD ^곟FN=hi\1DT aK#,%J#0A«`ZU .ѝO+Fqxk{DN%%(QBl35\sӕ.<==4M[g7rEc[Ԋ5nn:<{߱=ol_m5POqdſ@jZ;(w:zr Nrƕp%V`11H9ui~F%Ш@p5CA%1}1M;SܠG`F_>9yΙkF~eg7wSm\e-C#û>nSOꭥBFSF4Hg<4"7б 7v#^WqFY=0γ"UF|4\owW3E"}/V6 $gw6W 8lpc nm>RoEt3a%UN8s{e!h[+7Z5 mȲ?far_IENDB`fltk-1.4.3/fluid/documentation/src/page_main_window.dox0000644000175000017500000004127115004135251023400 0ustar albrechtalbrecht/** \page page_main_window Main Application Window \tableofcontents \image html main_window.png "Main Application Window" \image latex main_window.png "Main Application Window" width=5cm A FLUID project is a hierarchy of nodes. Each node holds information to generate C++ source code which in turn generates the user interface that is created in the layout editor windows. Projects usually define one or more functions. These functions can generate one or more FLTK windows and all the widgets that go inside those windows. The FLUID Main Window is split into three parts. The title bar shows the status of the source and project files. The menu bar provides a wealth of menu items for all major actions in FLUID. The biggest part of the app window is the widget browser, a tree structure that lists every code node and widget in the project. \section main_titlebar Title Bar \image html main_titlebar.png \image latex main_titlebar.png "Title Bar" width=5cm The title bar shows the status of the project file, _function_panel.fl_ in this case, followed by an asterisk if the project was changed after it was saved. If the asterisk shows, FLUID will ask the user to save changes before closing the project, loading another project, or starting a new one. Pressing `Ctrl-S` will save the project and make the asterisk disappear. The _.cxx_ in the title bar reflects the status of header and source files in relation to the project. A trailing asterisk indicates that the project and code files differ. Pressing `Ctrl-Shift-C` to write the code files will make this asterisk go away. \note FLUID currently supports only one open project at a time. \section main_menubar Application Menu Bar \image html main_menubar.png \image latex main_menubar.png "Main Menu" width=5cm The menu bar is the true control center of FLUID. All actions start here. The *File* menu offers the common file operation for FLUID projects. Projects can be loaded, merged, and saved. *Print* will print a snapshot of all open project windows. The *New From Template* item opens a dialog that provides access to a small number of sample projects. More projects can be added using *Save as Template*. Use *Write Code* to write the header and source code files, and *Write Strings* to write the translation file if one of the internationalization options is active. The *Edit* menu is mainly used to manipulate widgets within the widget tree. The bottom entries toggle various dialogs and pop up the settings panel. The *New* menu holds a list of all widgets that can be used in FLUID. They are grouped by functionality, very similarly to the widget bin. New widgets are added inside or right after the selected widget. If the parent widget is not compatible, FLUID tries to find another location for the widget. If that also fails, FLUID will pop up a dialog, describing the required parent type. The *Layout* menu is used to adjust the position and size of widgets in relation to each other. The *Shell* menu gives quick access to user definable shell scripts. Note that scripts can be stored inside `.fl` project files. \see \ref main_menu_items \section main_widget_browser Widget Tree View \image html main_browser.png \image latex main_browser.png "Widget Browser" width=5cm Widgets are stored in a hierarchy. You can open and close a level by clicking the "triangle" at the left of a widget. The leftmost widgets are the \e parents, and all the widgets listed below them are their \e children. Parents don't have to have any children. The top level of the hierarchy is composed of \e functions and \e classes. Each of these will produce a single C++ public function or class in the output .cxx file. Calling the function or instantiating the class will create all of the child widgets. The second level of the hierarchy contains the \e windows. Each of these produces an instance of class Fl_Window. Below that are either \e widgets (subclasses of Fl_Widget) or \e groups of widgets (including other groups). Plain groups are for layout, navigation, and resize purposes. Tab groups provide the well-known file-card tab interface. Widgets are shown in the browser by either their \e name (such as "Button emergency_btn" in the example), or by their \e type and \e label (such as "Double_Window "My Main Window""). You \e select widgets by clicking on their names, which highlights them (you can also select widgets from any displayed window). You can select many widgets by dragging the mouse across them, or by using Shift+Click to toggle them on and off. To select no widgets, click in the blank area under the last widget. Note that hidden children may be selected even when there is no visual indication of this. You \e open widgets by double-clicking on them, or (to open several widgets you have picked) by typing the F1 key. A control panel will appear so you can change the widget(s). Nodes are moved within their group using `F2` and `F3`. They can be grouped and ungrouped with `F7` and `F8`, and relocated by selecting them and using cut, copy, and paste. Every line in the browser has the same basic format. The level of indentation reflects the depth of a node within the tree. The triangle appears only in front of nodes that can have children. If it is white, the group has no children. If it is black, there is at least one child. If the triangle points to the right, the children are hidden in the tree view. Click the triangle to reveal all children. The icon to the right is a small representation of the base type of the node. Widgets are gray, windows have a blue title bar, and functional nodes are green. If the widget is static or private, a padlock icon will appear in the bottom right corner of the type icon. The content of text fields depends on the node type. If a comment is set, it appears in green over the text. Widgets combine their type (bold black) and label text (red), or their C++ name in black (not bold). All colors and font styles can be customized in the User tab of the Settings panel. \section main_menu_items The Main Menu The "New" menu of the main menu bar is duplicated as a pop-up menu on any layout editor window. The shortcuts for all the menu items work in any window. The menu items are: __File > New (Ctrl+n)__: Close the current project and start a new, empty project. __File > Open... (Ctrl+o)__: Discard the current editing session and read in a different `.fl` project file. You are asked for confirmation if you have changed the current file. FLUID can also read `.fd` files produced by the Forms and XForms "fdesign" programs. It is best to _File > Merge_ them instead of opening them. FLUID does not understand everything in a `.fd` file, and will print a warning message on the controlling terminal for all data it does not understand. You will probably need to edit the resulting setup to fix these errors. Be careful not to save the file without changing the name, as FLUID will write over the `.fd` file with its own format, which fdesign cannot read! __File > Insert... (Ctrl+i)__: Insert the contents of another `.fl` file without changing the name of the current `.fl` file. All the functions (even if they have the same names as the current ones) are added, and you will have to use cut/paste to put the widgets where you want. __File > Save (Ctrl+s)__: Write the current data to the `.fl` file. If the file is unnamed then FLUID will ask for a filename. __File > Save As... (Ctrl+Shift+S)__: Ask for a new filename and save the file. __File > Save A Copy...__: Save a copy of the `.fl` data to a different file. __File > Revert...__: Revert the `.fl` data to the previously saved state. __File > New From Template...__: Create a new user interface design from a previously saved template. This can be useful for including a predefined enterprise copyright message for projects, or for managing boilerplate code for repeating project code. __File > Save As Template...__: Save the current project as a starting point for future projects. __File > Print... (Ctrl-P)__: Generate a printout containing all currently open windows within your project. __File > Write Code (Ctrl+Shift+C)__: Write the GUI layout as a `.cxx` and `.h` file. These are exactly the same as the files you get when you run FLUID with the `-c` switch. The output file names are the same as the `.fl` file, with the leading directory and trailing ".fl" stripped, and ".h" or ".cxx" appended. __File > Write Strings (Ctrl+Shift+W)__: Write a message file for all of the text labels and tooltips defined in the current file. The output file name is the same as the `.fl` file, with the leading directory and trailing ".fl" stripped, and ".txt", ".po", or ".msg" appended depending on the \ref setting_i18n "Internationalization Mode". __File > Quit (Ctrl+q)__: Exit FLUID. You are asked for confirmation if you have changed the current file. __Edit > Undo (Ctrl+z)__ and __Redo (Shift+Ctrl+z)__: FLUID saves the project state for undo and redo operations after every major change. __Edit > Cut (Ctrl+x)__: Delete the selected widgets and all of their children. These are saved to a "clipboard" file and can be pasted back into any FLUID window. __Edit > Copy (Ctrl+c)__: Copy the selected widgets and all of their children to the "clipboard" file. __Edit > Paste (Ctrl+v)__: Paste the widgets from the clipboard file. If the widget is a window, it is added to whatever function is selected, or contained in the current selection. If the widget is a normal widget, it is added to whatever window or group is selected. If none is, it is added to the window or group that is the parent of the current selection. To avoid confusion, it is best to select exactly one widget before doing a paste. Cut/paste is the only way to change the parent of a widget. __Edit > Duplicate (Ctrl-u)__: Duplicate all currently selected widgets and insert the duplicates after the last selected widget. __Edit > Delete__: Delete all selected widgets. __Edit > Select All (Ctrl+a)__: Select all widgets in the same group as the current selection. If they are all selected already then this selects all widgets in that group's parent. Repeatedly typing `Ctrl+a` will select larger and larger groups of widgets until everything is selected. __Edit > Properties... (F1 or double click)__: Display the current widget in the widgets panel. If the widget is a window and it is not visible then the window is shown instead. __Edit > Sort__: Sort the selected widgets into left to right, top to bottom order. You need to do this to make navigation keys in FLTK work correctly. You may then fine-tune the sorting with "Earlier" and "Later". This does not affect the positions of windows or functions. __Edit > Earlier (F2)__: Move all of the selected widgets one earlier in order among the children of their parent (if possible). This will affect navigation order, and if the widgets overlap it will affect how they draw, as the later widget is drawn on top of the earlier one. You can also use this to reorder functions, classes, and windows within functions. __Edit > Later (F3)__: Move all of the selected widgets one later in order among the children of their parent (if possible). __Edit > Group (F7)__: Create a new Fl_Group and make all the currently selected widgets children of that group. __Edit > Ungroup (F8)__: Move the selected children of a group out of the group and up one level in the hierarchy. If all children of a group are selected and moved, the remaining empty group is deleted. __Edit > Show or Hide Overlays (Ctrl+Shift+O)__: Toggle the display of the red overlays off, without changing the selection. This makes it easier to see box borders and how the layout looks. The overlays will be forced back on if you change the selection. __Edit > Show or Hide Guides (Ctrl+Shift+G)__: Guides can be used to arrange a widget layout easily and consistently. They indicate preferred widget positions and sizes with user definable margins, grids, and gap sizes. See the "Layout" tab in the "Settings" dialog, \ref setting_layout. This menu item enables and disables guides and the snapping action when dragging widgets and their borders. __Edit > Show or Hide Restricted (Ctrl+Shift+R)__: The behavior of overlapping widgets in FLTK is undefined. By activating this button, a hatch pattern is shown, highlighting areas where restricted or undefined behavior may occur. __Edit > Show or Hide Widget Bin (Alt+B)__: The widget bin provides quick access to all widget types supported by FLUID. Layouts can be created by clicking on elements in the widget bin, or by dragging them from the bin to their position within the layout. This button shows or hides the widget bin. __Edit > Show or Hide Code View (Alt+C)__: Shows or hide the source code preview window. Any changes to the layout or code in the layout editor can be previewed and verified immediately in the Code View window. __Edit > Settings... (Alt+p)__: Open the application and project settings dialog: \ref page_setting_dialog __New > Code > Function__: Create a new C function. You will be asked for a name for the function. This name should be a legal C++ function template, without the return type. You can pass arguments which can be referred to by code you type into the individual widgets. If the function contains any unnamed windows, it will be declared as returning an Fl_Window pointer. The unnamed window will be returned from it (more than one unnamed window is useless). If the function contains only named windows, it will be declared as returning nothing (\c void ). It is possible to make the .cxx output be a self-contained program that can be compiled and executed. This is done by deleting the function name so \p main(argc,argv) is used. The function will call \p show() on all the windows it creates and then call \p Fl::run(). This can also be used to test resize behavior or other parts of the user interface. You can change the function name by double-clicking on the function. \see \ref functional_function __New > Group > Window__: Create a new Fl_Window widget. The window is added to the currently selected function, or to the function containing the currently selected item. The window will appear, sized to 480x320. You can resize it to whatever size you require. The widget panel will also appear and is described later in this chapter. __New > ...__: All other items on the New menu are subclasses of `Fl_Widget`. Creating them will add them to the currently selected group or window, or the group or window containing the currently selected widget. The initial dimensions and position are chosen by copying the current widget, if possible. When you create the widget you will get the widget's control panel, which is described later in this chapter. __Layout > Align > ...__: Align all selected widgets to the first widget in the selection. __Layout > Space Evenly > ...__: Space all selected widgets evenly inside the selected space. Widgets will be sorted from first to last. __Layout > Make Same Size > ...__: Make all selected widgets the same size as the first selected widget. __Layout > Center in Group > ...__: Center all selected widgets relative to their parent widget __Layout > Synchronized Resize__: If unchecked, groups and windows can be resized without resizing their children. If set, the layout of the children is changed according to their `resize()` settings. Try __Live Resize__ to verify the effects before permanently modifying the layout. __Layout > Grid and Size Settings... (Ctrl+g)__: Display the grid settings panel. See \ref setting_layout . This panel controls dimensions that all widgets snap to when you move and resize them, and for the "snap" which is how far a widget has to be dragged from its original position to actually change. Layout preferences are defined using margins to parent groups and windows, gaps between widget, and/or by overlaying a grid over a group or window. A layout comes as a suite of three presets, one for the main application window, one for dialog boxes, and one for toolboxes. FLUID comes with two included layout suites. `FLTK` was used to design FLUID and other included apps, and `Grid` is a more rigid grid layout. Users can add more suites, import and export them, and include them into their `.fl` project files. __Shell > Customize... (Alt+x)__: Displays the shell command settings panel. Shell commands are commonly used to run a 'make' script to compile the FLUID output. See \ref setting_shell . __Help > About FLUID__: Pops up a panel showing the version of FLUID. */ fltk-1.4.3/fluid/documentation/src/edit_select_group.png0000644000175000017500000022114715004135251023565 0ustar albrechtalbrechtPNG  IHDRBL&!1S5qp' 3?XL)4S`yh~KE)3xefaK,FP~N_-g2@䑽 O%KfFh sLib}!(Y45l%aNea/aEڌ, +(Q,eed9;Xh?UWKIQJ )ebiX3_ _Vܻ`;3+NٛH?)|dxqFҟ\p7L2B !2@r@H@ bxY\`s[&fB lG{G';;r$ޱ"º2[Q y|ppĘ/Djr&zlyΈo:L0KGp0xBHLyA:ev>8GNYW܁G BBA 3qD8⏄"H< R$Y@b ىT"Y2҆<@:^-š4Dr4 s<4]=^EK8 gqp<\. q% \5ׂ} <oB\bj|~ ߉' z;O# %=ZB7Hd- b<1XCl"$IdC$$tttMDV!\BO>MI!P)fwJEDɥ4RS)T ՓEM.Rw****n*T$*KUJU\RTLӤYxl^ZN7 z% *CN*R]ZZzSEL6K-ODuWusu@}zq{ 0L5.k<$ikk45wib& CX͸fL>3YbB;_t:::uuuuݮ{Axx㏌YE-ۥwM_@?P_E+AF C/CF3/Zl.;]>33 26ij4`lamܸ ՄclѤ٤tB*Ӈf3Yf+͟[h[-,,-ޖs-+,o[8VV۬nX֩mP6 n*&ܳrmsll;Xvv^O40qĖ3w?rtvXQXxۉĩ$II'wf8Oq^ERj \r#-q;]~O[t'[LO=SӳËWgO׊=}k+s-5 Z5T:.l " `ECh!!e!OCC塍S)S6Lij6U:> a[ ?18-|Zg #Z"#G~Z(2:;9F-fFLeX؎qKH 1 {O4{wgZ̜?,YNV-}4? LP!O'mM򄛅/E>^Xܓ\<3eCJowjI+ OR&y#czX،Lrfbq4]z~sd6Y\C{Y &6]˶!3+<ӼyGk̗οk*'/  .[عhbdq%&Kt/ \ouY_//^~E|]?PUZ /c?J~l]j˪+EE%E_W W_ҟ$i]v::麻+(+0eCF7tdRɎٛ;JCKnYkYjٝrz[WmMv;w;wUW"lw_8TS^ގ}WVVۿ ʮ=0~mwְjC/'{$HQcfǶ2j 됺ܺǛ=kO؝{d)SkOSOqLj>[b688h^s͂w3D̪ Ț͖ Zsl)Vboo%[߂mCe֟@@L]c}, ؍]gk.|M⶿hɾb=6<[sK ۓltlD[wҿ^lnu_hw`;x=mEmτ}6,\xw`{Gh/oիࡎLLDf h">sc :-Zi ,#0T^|S8 }cT&-s>ź0MY SzSO~ A2A| s'=ڹ:hĀItRc6hj_h%Hbߺ#pjO2[{E)Č <[)/N'uؕ]d$xRޭm=nwGJb4@Njw}r®¾%7\l Rìc6>2nw^v;ؾ,5'Z>3>Ng>Ӿ>{sӖ~K^bЇ3ϴeޱ!_;=aGOl՞֋`MBԆeVŎl|\jKH&3h(U*âr.gcVOyM$NWMF6 w.G^F@RLjTfbE{,0sϒ8HO[E{wZI;?}tjЧ>2i/RW?Oy'HL=yO{nO~=}/]ﲻ.}=a{^v׻wxxHKk_kwlwWaWX@nGmsK2va?RKlrHHE\  3o}[vi7 g} "r}=}{*)ׂ \['|L@i7i wsI3gG~|KH֧zK? (@'?.6TLI$82T\k[iDZn$DbkoE+l-bi <a[ܐԚBN|=oC2d?sӍcIO fog'Pɳ|`bJEDcl 4鯦KXL In-nJ) ֙fI s3 H:׭_q {|':&@xڛf.̾@['uL$QF% $)P5&wKz:nt "ʕ+{ɒ%n[(( :7ސN@;OPAQU }ICl;mHZ8SbO렫-/c%ImN"+׹$DӆTfZgT1+j)j&v;vB DRHY3ZJ {mptI DE*"=8 R!E9>ŋ@DxIo}[]CD->e!*Þ(K_r@Bd" ̾KHz7T[쑔ɑw 68QGHG]>R׼Rk^cxOVQNMHM|kSn`e (\EM7xYcCCG$ƚIrRVRM xЀlm{Vo,dڀ ,J`'K ר%o2hڂv8JhiO|nC@ S;=O|\+`F(8:*?f$?SeB]4?ߗ#E}`G9Tev~ jV(] , gՕu&riRsZщ ne :!)΀/iB $k ^n[ϚĊ/i뤞$ơ[a ݖ~Xu 09Xk%5R>go#kGl`PaE+ ~Ws\"D-cQY``Y.58 }$lko5 )*!ǟg= 'oVaD* #L<~]mHZG}c9W_vPDiek/syғ6Oo&hHD"d&3Ϩ}[1PO~3R!OZzԣ%SIL ev'u!ѵ4v ~n[dP@Z)UI'>l;]2ԲO8ø߆d͍I›M_vk6D6&ٷqV]q7[y퉨U}/Wؗ9˒Йp0,b=_ldOup\Cv'*%YK~Ӹsf-EbVG;#dXH]M! E%|$) $DgģZVD8QW7#mB~h"ਝ'ޏy˴ 0;?<2p;d jbW1?\dW]x5op^}Ѱs=m=1[GX_=S`. 8$6b6zB[抄 `Edնbߤbad#C^O8`.ryZݗaJ' 9 @E}l\ic#R\gzQI\q[VJhC3ǺAJ@=B(}*P+fcOVUz ]Zg)jE p#Χ#*6Kj#keh6F, &xX+v^\12͋Z4n 9[4Ԓu#Zgndu2>kUEݭH7|I|YfY@;07S7[\RE;LĥD6aj)y&89vsꄹ"%z%V[yZ\z[T>WcCOO*ۈӋߋ?%6lؘb;᳉|*m@䂔cTan9eֶݵ3'a %j"9"r*75?y.9zÞrUBX.#v+Zlm[dzԣ]@M$~CN _FS-U [WBmv rۓ+Y UҪ9f|Km,|83?8, @0ٚ>)ƈ3D6paŲe|en6b@+dp EhY~V&X$VȆY!if g۟ř߼|dM@K2U"d&kڒfzԣ]!ގL;?]7ZKXn W)?jVswY:mxՊ CUvLa~ɎJV5֊r.{hfvR8>ՙAp#N/L3&)bA+H~oNϵ=~yWR=?$d7%u Idͺ&Iv%Ȫok/nƑk*⍦^ko!߁BaNWf#?qdXF^ٜ O6&[ӪŕkeZVoM7˲,4"őf&ڕoEYrRGdAcQU%f޾L`p<~([B|jYA;v>F`3w;T! IDATbgIO}ĸ-HefdO9Z܃s9h=:tL@a Ιmݨ'3UR{11WKqw Vl+5 oU0*olz>vd!oˍ&^xC,㺾'wĝ'x |=ںDյ*2CvԉXK؟@Ɏ,0p,6ϠeH#dr$jbPjTƷrMCxfiOL9 [D=f1}y,  p,Um8c$gЮ.}A{O7Ii?t#Iin䯘(G|rŭx=9Ɣ/^Lщhޅ}/IOj-Gn6\eϚFfzF%][_İ'- X&?puaXnî|Cj>\*a;R ?ADAފr>6jܣKu9Ք ـO7X+gphA; cedm6GwȐULRެGa!bS@(;*gZ4m]v ϗ\lIj_~a#ߩv?G8`Um-&ԖC]R]YEh,oFO9eR>`%M{7|Z {}) Q\j]f>{5~6~%K|b_j2 ~IVryȈ;\̓9 x=nK/Ǩycɰ/ɮ#xY֧{{_xUm=8M7d]wm~jzޗpE^wpp, DhtLE0a"Op`!Sj۴P*tj|9rtNˋ%#A^/=۹.`PD |u:v-'?9{ޟiG>vO8 oG'}01kLկ|ϚŶ!;"?ě"8슟̧Q9h&m}Mng^2y !FąnIB!"nh~ګ^&63ΰG[876u_nGRݓTqg&_3RtXO?s'gXe@g=Y.v*v aPF`(Kzƍ]g>/ٻ}\~sc~ۢ4~j%BOh|Eָg&'#k&!u>!U6&thdaJ9lnƎ @t}6q]0?dDiv3UPDXbl}'3?K_~z=!e?m.~ͧ&䬽tF<$% xvG>LX+sO8e^uݣCeiށP 7[.Y/8>/'>I;GQWqcwÜ.2?{wtFի}c?- 1+=<ynrUslB{Q+r_.̏-9ã8rS搼 bT`$>rߐ۴-Qso~Ї>wv"\pIq@|dp8'?N#oxiqn-i &L:KC?KF}K]}u[@ η{緿կ~.{OjǷ h= я~RwϢZ|!=w#$_fk׮@?B Gj #R;b:ljO@8u89R-Bs,'?rvpgy(a 8؊cHLG@\'lXG=QH̹87(&1ߜ#m߽%5ۗ@t@ /C-`='к m}4y_' {gCB{YW~yQ%>9(/?z;ӞLŗ,]fg'\F˝GQ&&/hT,l_ 7rSB&f?xQGI2dP>˱؋bt~3LFN}ߴ {sc/{GyH77~ӟ{R>)N@k_2:8ؑ@_k^Cr* B뮽N{+8Tb0$o}[.}i6l~suisα[o+?,v쳏K"Ϡr# uC#MfZ#)"i"xrOk,+l><Ӊy^?eSB LZ 04Q}xx~wN?ōxկ}z}̣mu]M߲eK_R[bo#|+˽ZOؕ| s a?:qas,ÖJW2 +#+XGȖz.^zKqOxl{? @+VpHN.*,})]B eU.R!6j򑟖p{rUVx#qmo{ )&c{{ I.=Y0Ѩ>_RM~`w-XOcm_k7&ٸ8pw,GԤ2;-]G}VFZFl`<{d 6@P&n:?I:g?i[QU;}wېĞlfC=ںlj\t|9{o4hl<͞ѥ-du#o!1yvK)?Tb3 BH@$MK{֭k!Jo%Dl.7& k_ْ%K<<p13AeAr&*B=>jS=zӨ4=>o@%T{7U;wx/x O=> Q]^W[*T FlD3l8@M[rH0MD K8Q(!nhbVok?)b]&ib'ag5B s$Mo4|p|g#x#I'Ԗ= |ܘTapDBzL3,w]WuH,!a YЇz>O~r)^ _"EJY$=yO[rmE?{nƚ+1l$zְحvukl;kevFe"|-\g}p[ ېyAd'aD%.e9#Ϸ^o,@`]pQ[2@u~#Zm&ݞwwbx=(_΄MNQg l}Wڭ;~LC=4}|EeKqYyr&X%[|00y_`r4q>EX6M~HG$a֘ZP-&."Qx\̬c9D#|;y3y'C#.7|Ǘ[sU ~z>:a{G-]n֏¿]g ڜijmfELj ]VhG2[^&KMAeK5jC.O239Â+m cL]N/IWk`&p-˙Y)qACS \ۻSR!,r,WM-JQ'?i0k頥UQVdjW_k#ƊFuv[lOmꟜ{ƭL8 Or fTm)o_jET.}xQh]=.h6NeTWk2`%nNc Tc4IwXښ % 'S!)iM sT)XYz1#,8Yp,Js3:h 'G ;ÝVզ&M,^K뮷+^r7;3tj'=6sθ [dW+p LD{Pyy3A@:v;+9NG1-Io>ŗI$.Dm̊$62bKF6!z}RU魻ɮuQ0xo*SN7F#2e$uQr%wz.QT6ƴ[uKg>!0WSk@`DVXWi؝6jc8+эqdl|mR P U睜AV*d) 4S|iȞsy=/!8 DՉz0`_&i3QoH"D`5{$}6Wc.daMgxbZ+0 v Sdd&]DOD@d-k$tmmɑ˯h 7Hud'&25M&7v뺍Vw~3QXJEqUG 27΅ ;`.[ud߀O~lM~R꿺"mUol2Sp~Kf_r)M4Q*Klʶ#E$[)lD]k47ڇ7Cp-Gﻯ|n 1?d7/N F g{ Tf2~h2[ĩM\cAڜ턐l bw=1sIbbҤJ;Tl킅lߵ5W_ZDoS4|!,&L#Lh E-qD#O(.NârډẒG[N/c?F2(mpzrI#(N/,x᠝;|2z_%nG{)OApD\<`k6xGY>uNf:,m슔YPUqI%7Fko0AfI3h9/Z;J2x=ZXy@bmV@ D%0"I;YܣI6_4X&WZa,Ͳ_ʗQ'r7Bjbd HH?1>!9#|؄4٦nSРن+}y,WU.JrH*Jj5*y#eM_bh iS&@ĬfkP4M! LQWxi oc#& B NʔD.|oR3nڗ bej[h$NnzV-\'Ҍ4oѮ.fs+(p<>$+أڦr>"XPIY֖ǹD)Q"$AF5K҉&o j$T)T v76,%i1dAK9~FslyndnGl%ImVs0Ld b @=hWj!!Qn\lKo>[Z>UxJH!H hų#@:w@R߬GmѬqNQhJj:3 #?7hf (?::% j4+s7L0ٍzBlj'I!tXTq`~+q誳#]V'GEȇ *' _`wliY+ mV-ߝ)Әl]+}c66:f}u+kWHL Y)|-Iث ܦOT25Yr۟'?jk! t0$ Z’2) %Mh~S'~]kEy"i~iĐȨ?e 71_hLZՊoNcPRK xX?\{L%aزŊȇ9DUǂÞ z9/]b_g{~P\q}dvƏ9X?ş; &BZAT֙}-V@.O(M囃p A4ocs' ('|Y~M*m*mhQ٤1[* }:q6n攊q[ʢ,4Z8&7f/x mtϾGu8bl18OոAg9N~ސ(#*4fp {߸ng,s\#D c];^( lކQ983//r7s>ve9;Tژf*X)~Iu?r|~wiW+ސSp֋' y9q1=5iBzz"sԽCyl)I* q~?k_-]hϑENcpVrQ IDAT~y;tt}c_җ_ Sz/`tΦ1g<>CڑȐ`>s)w<8bS_Ϟ 5&!<ϐ O9Ct87R];Pgu=;iFw}׏DG]9G;P'zb$-@8S3h/*84?ӟtEIx>יG-F[fr7HsGy~á0?A?Cnp8 %g ~~BF}; 8 F0Ti>`߀,|{Zٜ;g\2CBvKٸHLlY5_Wv8 ɝpG%9m@7ANcw8S>YL;[C)vra# KƱQg<5xK__щMG@1ڢz2F+Wsaap*V2qFr FI@;[#f9l~im t0TGXnϠMHi[iK/zы<}/&a1&dWOYn)ɀ,3zvYg4'G*ʞp ~T>z\q hM,u` t $$Qo`dGRSVIj]ʋky%:֨MO? :jW>X5cmvhh0yғ f "IU܈Jb<ټ|P*PUofuDQ;`Ӂ[ )3&ad]P*P0A$1ù8@\='? FFw4UH{Z ˭Ntd?я<]vm-Gۇ-'UHt#*?P;a:&?ft85v7D+` $:KlĩNi+l(S6RDB?s\P=t^ .| Y9%A|N3BCcEVhg%bxsSJfCc:ܚu 7z+Mj0!5U,_o} X#W/ ofo =I e!pŬ!3,@Zl"@eVEM #Ւ&3|i@Qe&JۨeI:&uN@#OCR;t=#TydGd;ڛ,'F% 6bj*3F^`҅eXL|_w:E ݲ-=KˆFNDK'w}mOGd\I`ԜA%5Afi%-b-"܃a<)ɓ`Rfü<oMli&/IJrK!]@gSiш̒8]S~ZC7G:\Z۔rān:#{'*C!%TN^kwV0FG†+-&5!u@`<kW3@ G- 4AQQw" FƷ7Nv+xT`"^PȮduJ"LX!x&÷)ޭ &m h<N21\ܗQNRFB>Hw˨FbC䩁NRbs20龜|O*os!m kP %pJ8(= Zm*S Tf(tm F:YDq QS$AUH/vۖG4v`pK\1@J1ʬĄQĎ#5AK%gNآNw{,O~Җv/o[0JX_t ~vvPIG t ^ +S\c΀bl:xJeGcpݺu|ih$LwTF꣊=42Up1 Iɾ~aeIgRa*@̭  G謌K]]RͲLijˣ>Hu H[[I]0mMzț,LԉmAB"^<؝P8ZI@ JF6X ^'i9JG6J#Cz. Smk(MoDj!҂T}IH p]"FH3!|dE(fޅ9N_:S͇=0."3U1X;Imfo߅%M̱M~,@U^yeIF@sM (u4H` =͞*fա% '[CfIoToOtߝ#zT(x*ڣ?+- !=V!n)/=xOQ(fN}4\{7`A_{ '",<ďt.uK)vFH ˕ Pjs5׸ N[qؗKIdPN|~R["ߨfx+m"(erHga41SKqń ;2c5RqFc=+u()yI8`mqăkx* ݸK$ *>Vj\7ڙ\vJS7uCE)=)mA!vE7Vj6$ C^Z|qlhP)Uᐘ]'XdbEe#m5?V4[`%Jbsu5q1u>ki ;_Se}Ou*i6UWKܻ᚝Cn`4vg<ccK=3'J@2qX:pz.̞'.TWYgJԾN:&Olő^569TXg>ψg?۽ਕ:PwyVvl4xyK_d$2$gl0eI\` NgIxH*BL/铟吴*ogi`7zמ`u@ޛ04аu/x^^t#] J5Ah6e SV@|蹼@i|wT[AQD;P{aE!M@T=ypHj; Wx#!;*N53<đ&.YGǷQ&)1׀3>PqSYf:vYÇfKe6I`ըHGSO^T4lx놹JFPɗq6&|_x@[`wB::SO!x-Iƒ>uu\P`i|\3>y'\pti88`YgP2;ɩ8 xQI)_k"0؈4K“˨F<lj6}A\I(ĈVNrq[A=Ͷ0$WvI'dO[c_f/k^{$ '= ,wqi|yF\O}S^O8nel Mo+ O}CjSGiq:"IP ZcQ9Y~ NsX A :HiM&>&xG ;J5*5Xxԙ\c[Ďv3*$N"@e0#>oU:)fʣlZlw|N!feK~h`QT`^έixIRՉA ͊v*/:O|lC$fqEGB{eӋG#lڹ!RIGkKuU H>6TJmʝ\5Bg(M4pR3\UʥR[wZP]pcлgq65ݵ:2?& HOHJ$C:/ձ4lHΤM QWTbB@R4D-l&*ͥƏTNFR@sWԓk)myk|׵SCd:-d07=O3Qe/20!#1 w8ih O`sb3 'ɁtVZ6Bcc}mQ Q&v2`S#UxUMjR3Qf!6e1k |CuJA~x5",.f,:Gg2’VpT0ڝ#ūVkʯ*#5$NOdcM+27Ax t\-Fӱ;\D5Р8F׏(Ӟ6ԗyN5H;j$ƖT2FFqߪ, ר0ʕ+d@Θ^C$(fu CfGZLI'#2?cfyi$l88F@a4GZ!55& !PoF:扁=tRptb XiBZcieRz.1KS[bg#7y1λ[ZIXq$¤Yp?s|uQZRyK8a2 s5vZӆؤ(ZR  ?1͗#M#ebCVKT9͡-Õw)>d gx'.`_RGaq#hG~&*0o*>ŒGikQ HH iN&0Xߨ"G"GQ")tDUܵ\L~t wA]tp{Ѓ?Էf;](z.1I0 \w1L<;P[Jmi&I԰Zz%A09C{3f3!f` OI"]$kH1"]҆e0Æ@0b)fcDWhR3PכK[#~kuu,ۈЍĜ~`cCKS bGRacHRR%˓"o , X*.vrT16(iL;_+MӳلْG;&[ر)-h4XH݃f[vgJ@ʦ\rēlpaF(uؑ[#Л?ip5#򕁰uтXt$ QB}nEjWm;NaS#1ʪt4/ln:k&IT8@җ,ftE$F`HnCPlSU=tl@e4ŗD,[nmkTqByƕ)qy./ mMےTOR۷XdTF;:~pщ ;:$LLǑz%($O\ܭ)@ҤJ?FFa#wWq$nm;gƇTv)kmK`qC/mĜZέhsM64Gс[bjMi&{nFku^ Ww.qK'f[F2Dgnw_G;iV\F:j,CH >]MW IDATNӉvt2bpGR\GYFG*:e6<-Q}ZT!iTw@r{\р/ö?YᶪHOxi-r6y,Ra͆vTn5h<4|u:q~ӹpjժY* Xti!DMD6YGW=)l[mۃt!һζڜ)ӉvtAl8` 9Νw OϵXPvp1-М+OXbGw ۚ%y ! 2Q${jE̝Rk䒡:d1m\LY]bXhV:1h]buʦhlq>@^D8Mmpl$X xR3ƝN#RNɵNӸ)< ,\ɑvqKOqwf(|*`+(osuޣGGhd f)Z5?YL0l;<;KEfsiV8#gzdң-m]QvЉ4W*S F8ʕHYy(R%J$NßGJO;6'!E\iDW%~59S!s\U$3\yq=tx'>Or-l'⵸wAr7n+$5f  ^CeO`l?{8|;|-MF ]Fp.YgO>l@F5銐^.5ŁUGt5FhCSk?lSk&@E#$2 /qE sP5Kd91\."\r1Tأ32:IҀ$%ij{G1xFU;@4J9*4=xeϓD߿x[L@OX규sl =N~xOosα#z0 a@5f[ ؏z=\] a2UF`fe[p-@8PHzi&Zc$5p |{'t*G0-O, 5]I̛pI 򆤕hot7lwhSm H%LB#shBnH}zqPCR49f :k8L暗Ķ}TalF)cKۢ> e+SYG$!*)Z~s j4k'L4Q'aB"9lغG3SQ"LPd'P`UV7/@wcNg" Is&r։!1j||ه~8gqAf`XΙY;Ɖu053K^wu7fÈ=lk}fJd]Ѽ.ڕf(=g!v?k&vIxN|p-p@JfuEZKky%`qDK-&Z}]o2OV!rJHtQW aSa4c&LhD0}y9s`^A=ˈT) Q$:TͩN4XH{M\ī㋗l@Hp7oxl}Nm@d@8fexpq&H…V4`Ƽ]w WEm\ ;'Ǘv}hf4i+rF;]T[wNp>Y4>R"@.ف`?~2"Ub즬03#Fz!nx7:pgW5oDs> "OZ 0r@1ϠmpI$,~(Na7Ԓ^G{*"{,&O|Λ"i1:! `\;6}z̵G)04,);\H^-JJg=ݟnzv}>Rlb06LgH, TDuIPy8h3β %.n|r!I8M jPkQbr/[J/c$%>>ZʣoOhwj<%B5l\RCTOPCİxa;S9zO?Ucc(PX㾘 HPO<$~'wڎ@<:R4 ~tpѴ=GCm-Ii=)AڣͣFN5oQP."?ۊ;)1G> Tc$?yvG{2aSO=f 6N3{7}{4?]N]r]LrdJx>+d_B$2#Ե b҄ MNBu[Sb|F:~T=;Bb1կ{Z f=]ZT%11Z. ϹAA-%ȔkFL f}'_Rj_@ h;t>,MiZFTˠ&~X XJ3M+$UR>qV9S]TˢF29 PBP1Ҁ ZHڀ1u"$)fӈ"l 8nIH1⣨,4. eTiGDFKI%r "c$c"B"/V *|D*DQ"sЪ)$d:ƺ}w^kZ=y991s@0N'0E* /xo{jpk͛7w5v6KjU0}/I0PnӖ6'DmRgOkR '? ItI' 4yDse8<$53ϴDma?=yT)%%,=8JŞKGq'0 -*t0NA}jq N5^nz0q P}&lFb\ƵUl- ZKzT)?cک^#g+( < >&E<=Jr|4m=9w}}4m(<=InN -D>~V{rv$Ŭ1FvIQq  k@<-MiM)S'@<ą?֔LJ3UKʩ>։_ݛ+٘G@*Bc~YBJi_j$D=q.Q{$TbZ35hQn9>_gr5؀͞~z e׈=lCO - H^`;Lݸq@KP,^=%In~vAoo\ۙ2߶Y.8W )м3-׮s=׬YyLit~`}RS| Wi[\+9 ]._AZ<Uܼys:8&$"'ĒDN 1b~g~rP8>eRxَ'h#dt~(&%Q'Ǒ`J/hQ{c@N>{^5xkz?s;ɵHIPRn`_H7%&b.Э_I1K*lPŌ5Z @a wHDjFd4T5R[x+ tӗ|ɗ,!ULq ߽~K9y X׾vMq E~߼#_ iГ~x\%IDj;wJ2ls!d=>h0w= P =E딠ϙzN"\Һ:*:-ǚ\=آ4gdf mU_1?=,BzRt_gȓQ'?ޤP4%&@,%fDMGeN TiÉ hooZ *q nѝ2A1O 1q$ժkvnW6Ah QhV,Y20x:yP;]Igmj$oIN\mgIdY*dgWN0)tN}ot߁LwHOX>Ϙ<-x6&㗿;m߶gsRSjqb2H$T=IvR:g_moǥg')k=6'pA6ChjҮ]vpaRt]kq~s)O9X'Frlͨ=+k6ٖA=tH-m%I,F1 查'd;j%h/Zַuya d4nT~gC+G?%{_zxKT%5;>6:NEQ=(8'd()֭ˀ4sep曨Y謁50LRoSFnfn O6 74k:罯ߵ G^QPё $/hxZS 0y"S3䵠}IKt%mkKzwmL^^ջ6x[ 7S]kՔ:N|m{mzϗ{to \q] xǯRg{wM(pL}S|iNv1QuTS V wvְ#Z<彀mϐ=?s/8m{IG5>Ninܸ˶}%*)u `^ohM n4r~~NM$8Gj8ڞ~NȧOVET[ "m9 86y߾moro|w~w.vdEᱠL~o-K, Ef&f0Z؋%=|(6 K60WktSSC 䗄8ڴF귭y-17!k"pYv+ [kҐMA;j~zfN6h9P}*O"7o,.R@J]t- ݢɧ~.6Bj\,uQm}IS=v^;YfUGr^{CMW/7gmn\dJYm0:]kQԄ.\Y MyK:=Eg9_ؓB ~X4h: z܋(05xi yMbi06A&fNyүk$CI3o'N~.KWHڲ W93a][I鼞<7=0'0=;KyCpf,>[7 <1y\sS'k0lRd̾]* nѵi~q[{qrqfGw f 7C,Г5b | 6: uG RЮZgJgZI.{=A<4'vW .0vq`|֯Kȿ9EAV\iz0`m@mП~cq/(ZOSt*=Ɍo({,zqdJZɍ#U%KtTU9stbs:Ok@I嫷cj$ҁpu{}s=oYhӤʃDu IM$_`X4 ®6N@h" kVh^>hzh@8!30}ƍ]GG} :Ȧy !6fJuKeCDuq[3[).8@1U~7pd DKMvX [0H_jY7%%|'{ _f+cJGǙy? GP,J( q.vȾpЀYr1(`x+v-T4\5 1^pzEKsIq2:H IDAT<3f1gS!0\+j  k tjy՗O^SZmź .TIx&/$m뾘Zd@s{,;iĻlƉvHҞ}P?;aC %`\Z9ZN.[yfgP@zBYP>,\K$XXP!m"![Z?'T׮N6/^$«DkXiڑToYcO-'u:[>O3d/L7(f?+vdš='m~?h E^7fiQ+ZŐ}Jk䘅؊:'M| EƜ@'EroҞ$}0Ğ;[E6AT-fy,oY/%_u_H(R>+"~ח# 8e~$EK /ۥY$7nX>w*BLab&۽*I.AMOdJ4.M }ZAmF"(8FW4AԿ9qiqWCߤl#K5m%0Sr:6{vmCDƬ??lRXuSd@|eɠkfe;;`S$jN ݿx %?E] Jf%!kgiHV5ؕI*"p_/i WrĀfnbuThcmg7-?`7 zrhf ՁWE>fw^_L{J5^l9_u_\YyfHH#*?%H X`(2iyhz^[0)mV:GsܭHm:b W&B /h508|Y&I"As" ;eZ k2?.<(> PjA.Cef }O/RɿU~ޙkETxbG&?,揄IԿHƋqR; 풽Q{8qt`sȚ4hn@a2bo/09 $lFG',K-y"u>VNޔZՉ*$=fLZNNYŘ]fIJKLI>[tUxLH. eLDV# Hvz=`#uhj a?" ;|3>C af9utʯ~Äz5~{ NiVAǮ7 &Mڪr kl mG&-ClO}{A[UwU%ę 'R:3{ǹ$ebҧ\`c4f")Ϙ4&R_"i/"Ӕ֤,iTڒi:%"JW>LI|d5˧a7st#t?p T~$)m*6T0tA4S~^$lN I=6xhiiF3jaiu&C`nUAiIM6q?-cK UC! q$}w"\e㏋M@;Lh:&&gX? h>ϲ2hXalGZbbLmͰ Qɩ.}./.Zw\=xJ|P*DyGAz9Dž@lI[s m@H_4FMhyր\kI{~O-buĜ4ZO/}[k aҚQKz)xnZZA qsy_}\?oFz:LeeėշE t.6| \z6'l[ϗ;GcKzI?/j_󼹖ݽ椇)Q@;~Ru9oc]z\K߻N!QM@'Uv} ~}626%i6ݟ>E5la9b:LT3iEhջA'Y$¯N9^^;>wX< f}hlwQ =DRf?:yTf%xK;A~ɛO)ͬKZ7ySZ]GkL4|ڹߓK;OޞffKH{&tX 23} Q)~VqrES [g#V*sn`VdU}jĔ}ǎf$X4?M.AK:&]Ԯ }Oi}'x? ?WI﹓M*?pYpһ>N.)#).Issf̿i öL+|H1Ѻ#'\2̞93`$MKӠ`16+|k)5g=S*poJk]Zx3Q>^O5/LiZ)M++;\[Gv3SkZH]ɿGI+]INJ'}f>@f7¼5ZfwDVGb)1iG??gC d)_ IqiF+apv \w BHjRȢg=y<_sع%s0fHkCNb+mNԄ( SMB}䕗$W?7:U@X50jK1yNM=Gzuڻ? >4_7Asqe @f?2T^&zgTL%+i4-(o$fTftI U=UKY('_  ``#0O~"_ \joԄ-ⴾv>pp43 T_,fT=:-F>- ˷}۷-jnRaҥ˧޽2XBWgG/u$E#F:W@LQ'rp}JST{ƍ%v(mÒ<NS\q eaμa67o\0R4 BWT4Z6'EJ ;g T$g됰@3󷶗<}CR|PVS253Է$+2Nw%5 U]J +֦C<\g<%i-DT _& 련Ygu4F ` *oxadя~t)Gv☃f#Tlw-9#b6`)gҫ_qQH'&1tU PX| Sk6QR9vB3I]I<(e=u5NIrb6hHr <@]>T oE$kg൶M5T]ߺk_%24Чƀ43Tll}@g; ls=)t5&ƬkUvӽyNALpT0&0q3i$'=IcAE`f} ooXOZ8=.)-:->u!!I,uHe'?,\G H]]͇݉Ix(4Ah`<X'5)7KjNq 򲗽ligwL6: @6[߉GțAl 0 M:E!B:yp~;߹HxلJ:&`'%u.=;9f/k~9.Շ51C]-!J;&EP P ӎQ/L$ |)ggOaL3/·tL|@s? 1(i1;]kKER쥤qPnFI1t Dz")[RU׷bVڛfR_TιR탎xƿIxք\SL~+> ~;'3I MiMJepAa6L*M*q̈̾˵:CL#p:{^+VI9KM6@z(?s? 4yyOҀ{;i~_ ? !c %)&PxJpQ Ɏ@}[ߺD&'>987 wM>|5|;)?\irәɝׄ(lL2x`♧N[ד26^:`xP`d:0j΋y[UCI>]43J/KĈ[eP>=7AatB@ X bQ}$d t)nV?G|u8S DdSLdfN-AOl7|$${b|Ċ?illb yiSsBFKWjB=lAsFB1#+p2a7KegL ):K%Xa+nzHR}YWΩ,I3P;![=~s$hU_U"C!/e:mo{۲r& oƊ߃5|/ݜg?"7`gьthZ=.#TjRPZ?\<h|ٛLî9`ca81)nEX` TY){7|4zxi: @%c Ѻ0`G`@ Z؀X-LNh@PMKdkk q `y *-Zߎt@VSI%LhݙO#}}w`!TQ=9E'uYt^؄M0|U : š;?PGt0LlbhW휲b1P0B0K=|ܶŦ̯֤i2?ˉWa4Ǖ&_,ckWպC= ࿷+|W}n 0~;ݾ _ɟ1W 3C/܍"P[0 =Mfn`vݓƀ/ੜtf`ժ_`N׬JuUԙ@;'`:65Z G3cՠ;S;ozJDk[ݫˤC??s;}/_?v>_^ } ;Kepe/HSʻ 3#};u4fQ#G\}PHrTvTo^-"i+;7s&U갺w>Ɯg5}y5O) $x0h7"qԸF_`N(>+1k͎1Cc4 Væ ~CǶ{V\;?)1agVmVƘ*Y7$E='f@GH 3>#ܩh G _IsZ}= D*{w~*B*?Onn$@zI/Wy^=~o6@^ݪkx=&<4.Ya 4s\ YG1̯Ncdv^]f~;@E9ݳ-bʝL~yu f4')}æ;n>7p3m$]H4uƟѴMAKWǵz9yߵIM>K_S=;^QY9^Gpkܹmrhvd OyƂ g7F'y]i}hɻH߶qf[҃,"ҹ$®pf>Nu8Ni'λ t?mҶF}qp$޸o t&@R1~VtV V% M8:lVNÓ^`hes^xLX^e!G_D:7a%E:ͳhѺ Cp[mtlchL~ټ-MS͝O= t(M7kA2hպ6>jMƮ6ojxg4vh=Q>7ߩ/ߛ|g5nw[.Ѡu[i͓mAێ('72X$ IDATNG. v4( :-M ]uX[@`n<'wq"74k'=ҶUF{2.b1Дb :=?I@ZT׀slU U{a=ΪG;m [BԄRԞg{8DS꿤Nj[a9O&$orJ@ }tcϳ|g3TIsXԼdU$^)ZjOE&iR~Nxa32\k"Ǐ.9HB0'MR]H"D9qS RQMҹ/.rMQOS}r\"eI-Mut-f e i%H_4,֏K^]zlǂcvDᵒ0Ң :sK %)$ED~V} 25 @W 8DMJݦ^}P|~>Z,m}-J"W]Kz|BaWYQtO o)& &ЩxO=k,*PSU'1~~nƍKli3J>D6{ Zc jEp;W@&%_G{<澋rI[ p<~["RwtSO`"a'a13T|" |I>pMuvL"j?g} %V6 /8/P?s9>@k^?_B|R=,ǁ(_2و%))Mf{Z!<} pI-@}(61@GxJZHr>N F7o\BEQEvփ< ` @7i/!O@B)v?=xNxf[l4b . Ї>b' |I$]RgE9=i}O0@۹sO>-`(5߷cf fڨ5YM ceKNOlyZ@L#_:G{d_>6mvYI*wTI.$= $H})[ԈcTT@"5w߽ J#?#Dr $Zq`T|ΩU\(y1YkB`Nk&nj1s;}[\9>?y9`,__ RexҠo%1SՍj))K~IʚvƇIڝebR;'H/;,pVe\k"W^R8@(G[ߦ]vZ }9nk2Iӟq{1pakJ0;5 gsd#6}g*yߗ}ٗ-.wPN"ERéq'mp"merBMڥ {F垤?7' LK͍o#τ< ܯ3]Lx,9i* e`t{IgC"6͋LI<lzG?0 So%0KpPg=o2g**Lr& $K9)Vuƍ?r# o_•ܹ 0PQZ`5qqJg2TvZvxf"ah0;o\"{#g+SsVُ 4 }atW;x;'&lP&Cooi-Vpm9'ZYuN}HMծO 5æ*R h0Z j'H&ҧmFI)D[l <[ş%R%mp`s'ˣBS;+_&VZ#PӄQ_~mŬ)mH&Y<+[.MA|>>@6ɇ*DžM:lvN[i?-=W݋PQg/P_+˖D`o\u8_W, G7_eI]Gc@2??,!>ҞrξBNV'q*T[u?InsaNqߤ2A$ms;4luM| 8DZd[e dVh}~@L^l@?/7sDc׽uҪ=Vl ݇}CJ2b7ncsM@l:?"QMw:մ :0~4`xf^ DIg*k 45y<"r)@ŵxFmфn>}{|--K{gYS Yұ>.G'z@mȣ#@gEmmy^SׯU}W/`mo^IRҧv-`o 9-d ."Sz3'`^æ(A7oʯeeΡooy;߹;)`/Ζ Sm8(:h[ʿ-k [e~*zvE\ܹ{血<6H: X| *OvA WDvCC5,rE f}[D6]Ѵ8y=Ol4%}.Z3Ѥᴔ ZlWT_OX,DHIϑY TU 9toMyVlH.1E]D7nX^@۳`ZI]}?Fyέ{gƗGz{s&,5?_snk}᭣ gn`Kb6ﶍ.sZblyx\!JwI뙀bi4n;eK4&X]+oJd;{=.4mqI2<}mwܪv|MxvKL{ j5s=;]>P_{u·3vXbF*s4y"M/|i ϫ?PKAK=(ZϮ>΁ѻxA{u]g9Pev0>JKHK}Lm{W_*NOIYPrN[Ƈauٖ|Z6!]҃ ,`+;L0'SL [N3}/;rr,ԩBEUO(q0&d oz~=y/%U[.a{vqW&/<\ʿv yL \xCXl\7>acp䣴M>G?}Fkiy.Lm1=iVT>?z!P*ݧ6(W):,P {1NHtLsP޳E/dSLSŔfIaM`w.O,~#9 _&VxsNzyh#0ntSM 8Ag߁m}w…OnܸqsD ]zM:/\xX4ؖ6iil̐|SZ4%o?K$Dm=$H:ggh 3_4L:]$xV&~3"O6c>qD've.t:0iIt8Is]9% Mp |yhfW\@dz$Ż4 y[*ș~Mj{V׷i DU]#^tp6p NS`:Lr7Eȿ8mfEiF7ч1`&칓JS_'l!Lu`#h3YD{է^-`x_SOq&)⻿bJ Zk\M S(f8&_TmǖgF[aקME |_J$1`Q$A`XgڪKG.:]}D*vAW_]L7.¹#pK#|t ;iS} V{Kڣ~+{Ğԓ$S*h@$}>] ֓<%09:$A(ي'2G"hxCТBvx;;c&ܙO6%J^ḽRT 6QV:o@%O? c2 N !́1 'p;Jl- dB'IEݜE_E$.=\Hmp}~@rPŒlęW3bؖ6aJOOaBWhW@w}c6 k鲁_x:yt(oF Ѻ65f3[Njc[o-u}DJsQ*oQ$?&:\[L` Cz^&o3:7U.Kmyܘ( лRKvl /] ؊lcޓ9}- >ϒ&gx~^IFQ<4: kM$\=g ;qQ %ըaέuɟɃF'%`!|@]<(ئj;d&%b̋1q$YQhm??T?xA嚂s_| &go>"ݏT:ʟCˋ༑ M:;L"h PMt6m{fmwN~շ$tK{[NٵyQi>%^t s6e.mw'ğXVr-3f6#'YF f Cu>5[[ 㻨|߭;Sv}׻޵`D,@s9l+>D >3a/g}0{tӯL+X鐟+@Lw̟3ofyK̆_i|vHr2YEmihw][crAPfK-EI7x*SjBQ3%y"y;;Ÿ1Ye~`Z2>?qP$=YZXZу|p8Pc㊶8 _w qέ;/,@e?x۾VNԮTN@4{M+}Ϸ=m"_勪Ӧv|IMϔ r\nߐM`x?(-qR&AHbFϓfؤd~B`x%P|o|T"Н;Uޛg)mtच%{6+w/qhNj|ߛ5ui&ˎ9f^Ҧ*Ì1Ք\7% 6l&@?2ROi mn,VN-|YDav:q pM~Q4y`'_CS+1F2(qT;]+w`~yvqSNcUR R75;vxӤ)䓋BdԜeoڊtgA1k~d=[\k<@xϫϒA`{tre?v]seߦpO1AM6wJĒfЃ@1.xc?]^I#եz_8oZֶ@$@fA@w}oߨ(qDM'e9q?-/i͵" kA(g󮩷ŕ8'x}6F8L =4e ad IDATA`V <]ܻ0ׁҵ-c"u-CQRWgם@~ u]|6z:R|nzD1A5Hxωm{'"4ϲzf={7}N^;]Ң (`V?{#a:ލ%2-RK_YڢSz4$N=>h1ڢ>(jQ %;f@kfKI ߹ru:d74EMbQ sRe՟S6S*dMN|'pE}&hLD78ѹa3\{E ysLi6hlcKzivmV/}Kw^[EMq9[/K?я~kE4m6Ц߀'|p64 bls!f6…s)WY0܀N1]'\cX9(c\bj>r=༤Kj}HZv5Gb4G=v@|k_{P O~?oƿShoHK k܀0k{ns-?.wn=gT05)#UH5_K:Id}ΕpJY-j=@*{umpZk/5J3x6E7}bǡmm/2-iM]7FF0S\_^\5ya4"P*񴭤8TI![b@@Y1Q~r:S&Vg͸OS}#\;wW+-$^Sca;H s(p{yImՔg"A=wnMnxT工 XcfQ3猍(.+H:4uqlݛ&oxfMg9t:7 Ds]&OF[9EǠ6t|9"&r1;Cs@v?{6AU+$"^k#pO2fn{6ߩkJ :kVm4>wI}&\3߼Y<rJD=Wh,a 7,MA}>@BS$4״FIg_,m? emZ NE4O5r0~%-*:8L }kɝ\$Fp0ur 9~w|{J!{ ?S?u9Ջ4=/R6+=Rh'J}0JttĴG8i sm3C-2\-.iMD_ڦj{>3OU'td[k9׆sc?cj;&?? &K8rܕyPaI@pv /qyѽRVV6~}*%KK6I1i0 Ip)?;\cN:8k VA4͛P{R ,Y씳$‹<ΊN;FK[^ogob_JMd3;y?6yo7i:_tn@f:{8iBeF5\cBs(,Xz,F6>5IkI ߽H|?oQh%u;oJxfVWé?Lx34LB?i& Q@7iӽ5t/i;]ђԶݛ3VwM|g4ctho\f}L/_'W:̞tyt'5V4~],__!d9( 9 ԪWj竿yIJidyZAF+pn"Ϙg;77RTZ!|w}J+/͟Ν]܏|# 9NIJ;\}0?BCykLLa_|~XxZAlɳ Ŝs*`F1^.?ig`dr#[4*|?YuPlPe3?-̖aP__&Q!P%Oůʣao_j"vHxz{g1X}|R\ꩧ#}{omt/v >Asu qc\~;_؞?4wnqN-mGA WֹVQJXz.b v5u>ky. ig@Ǝ Hlb"x$0Gu:?'!1?! 1i^ۖH&cX 恷mK=n:lGzM:wdZhkLif{ҙg!Bφ_e3HV~5n9 A2kro$PJ5/vIQk2.}ΟrGw;߾3x[.|+; Lz`jW0)ݙIx-Y\E=IKP!OpN KC "Z$THভH?IlIM:L2: #\@j޴Ha>0P3hru6#۝g΃v_}O{~v`O:="Hd$7o.*$ot@( ([6cH/tVcKzr?N 3#T?إ/QгU|S[siC@yG׳=UN VuD փW]ṿ QhZ`R`K5He}|%T66N(B ^t~/ *w*06)tݷ0@}-md%t)jQQz &"ǻ-/W8>I%Uf?" ,Jt 畆2m&O <,&p ЎKx֡Y3Iޱ 1V Izgs=%͓%S d$ C=1ԨdS-I-Y˦[?I\kr?e# Eյ,6O 'ٗT)ަ,:&U꥾_eESk'&?pGZbi}X.ǵ:@Rۗ]m:7iv jϼ7+|45$0awR)w<2Λ zesxeґLR6A3cI Vq_W/`g~g.cCG6,N9oooZ@P@TgU=u"B߸H]tZZm56O[al*'Q<{Rad|wԫy'/y&m_.ήOv%kg_{!՗W[{Af&[ zҗSeϻ|=(isJuNYBs;'_;+wOv>_^/mW?whߑx~_X_j+@4Ŀ~qIz d_m9r{H~:R@Wz!G{&{>Le/^V$\]IqƒP/UeҤ{V4嫣&O@ 8Dh' Wm7_Mc8<}EܶWqUt8LfD'R@3ȃ`fNiԽkWF;Rg41V^6%Ps2/J4)z$ =ٳ-VdnU!WdIJ NO{S=&s-ʽUŶDǡM2R{qYc6{'ϓ;Uf.w8m|xXH;ݝ}`e5{Rg'p$~3FDR\ Ԅ㹤@4~}L`r&U) f^S BfɇIW7GsmdA)O[gN(\c\cΪ95;s^#X1d)6'\:̈́;_suYq& ɳ!@ j& }D44饽z456)1{flk ^</D3Oi/ g=? O!%s4y\p` V=6(꘠>ϛH: aY) @~XAhpы]=hLINSz挩Un#ii>hM5&> hO ~NuWIVu>/L}TCm?Epl $F=Q?FbbL3, DM*fW2"ft }G>E*$AMc+J;PULoC ']A>NI56mq$l(w@zf2lբ$d"ԤH?q @t{i)>٬ )Rod Au16 }˜̆'OS~fk&lFZŒS HxlV B+)?> F ڶ 'կ;}2mGJ#qynM׼5> jL'SD~gQ>̗}ٗ-}  AW)I##S =CVg@i P&UfԀ_T<$޻|^LJ+ iG'*ɐkj,15 4dܛ@MN6 $V7/*GujL8>Rზ'=0 &pEzw=uP+}oŶ'\e҂{B=! `>3QDJJt4bcf9ت . JlZ^M6#R,85@أT'ANX`^;W?&ABJz$yeOu/,p+"ejQQiښ'gHD WGi'x=m2mFTIfskdrM$W:2f*&ft޿=\MƂu|Q>ԆIѥgLճ$!;Mc³M|SpO6HEt*~:XJ^9` zCj %#{ =;Ҝ: ʎ$A}-C4x0M$ P*-vu*#~6(o2T좙Kf_?t2s}} CSFORI(?;qtp3U+]*I4yO֪0JI$p%svmUBe:ґIpKv_8v{0vPmR(*\@lCH}wwr1H$Fݼys NO30MQ K]NRIs# ;W\={ig.3kqJyhklV-moM@)\;Wuwyʬ&K]2%tD~:φ^v_h{cj^@t]9U+ʖN?B.Fz5XතJI)?T,&f󿼼KtԱ, IDATBYHD0#qç#1?Kz`76]ac XMLO3;|"ɍi%Y=쳋9D\KOL<~d"w  }JPaRգHIt. fLqo`9y'BnHS %̍{s1HAoV1nQn dָ2sI}jwhEi% TޥiŕT> TʕF>ufL&@*/f2n ۹W:8~T$96Q`M-~Mb]7-4;~}+_y@\6P"6UI>9ڻf]z8P;ÃYy,F8#ؕqs5FNt1l*_D_.ֆq#`~So')UZW`lZ^ tcyx2gz5.E`MOkӃ{7ܑ7W~4yj5E)-hy}f`5fb耦5 gԞL_G 埔U'ʮ2էj=)_ױ;%Ms-~B˝>;?<[,J!1(%ߥM0\q}P9x+'VNGeC\_O<ԋK(^jGI?C}ssS<@,v2΃$,l-qIWv;wo|Xi텉t}P7%t^gRٻ]̇Yu@ͱd9A-FmկQ;BIf]V}L0O*= w=_y-׽r'MھWZꂧܽ|_c;˿ŕW =rkvtvo1!|Sk_:h|6Nfv|֚&p:.?l|{̀&|{%5,cx6tߏ%'e+_WuݦU}m[bavnKv`v;W_=7vҝ{[>-k^yW-sn۹sOon{?;Lnk\ݷsٷ;0<+珢k-Q]x?{;@\nZ"K~vWM`],y,%{iR/ ,)h{&=gkPߔ(K  *}Y6&Rk./!^vΝ)3WCo{mi.?Ww7{ܦN4G*vW&Yd?xie>j͚& Ft{~Ɯ4( &"]ڟ վ}t]^GIbbc.!ٗvn&>=AvICkäYRf4E5VqLIXS.W2[ae WvT$6sl:gΘmn.rDJ BJHEՋ(҅KTJDEEQBJa9罞~;<93sΙy{ZYw`K׻&Y*@l=C>[Ǥ!2?wF[-66hC/Y ? V4ܑ9+N{lW'5̖%@s Lj;~E4ec֝>O㜓zjb2$fl'uct^䏂EaD8D3!EN^8QMc.B w'gSoigIϜ,dzESӳS۵#KDoH?03 6vzfGtM[[ɧҴ?뙴S3/F-أG>\?'=U>4sj>^O1[PḄ͙!ϭ:8bdͯKѳ/=ҤL˿v$a6&D{d%r y'ZB0<~; 0U'5p+&XV@=<_zߦ3M<.-6iI4w9YHzKlRʋiB nG*C yU@q}ǘ7P0HmL3;)3uQ{X^sv=:S&8tެܝ]~.4ur~4e'NIOB25=?P_V5糞}._Ͼ! p0!Waβ/ID*#@!5fH)ǟf׎?E_QJ/;- Ρ_vH;W詓a M ީ%̙^4Ӳ5+ZY/[2&}sVY3~zH묻PFVDXc|LͱF#̬}활fE5GfIp=,Q]D-ү0=u8x$k0cx{gN]>yWU_f6yRoKRكf7/CDXl_嫰hW]/Dza+sޘוdרZ_v<9ijZaʣzo+f`zg~h ZqD8UvHgwr})+ j#SH3_"=X|ɵҟϩYKn}ya 6֝|ʖ_uU4K[".)$Gi!kZ㵎9uoڒfVU_">g]m cylwА6 F_Mw ԻTgͮūi=fAn??78;4ΩH_umN4v/]njB:qN9"0ӌff?,V+fI2ebȷxnR>Yp"SP7{aH}ڀ8pRNg–Us[c  s4dg Mρvpu*/ ,l1ZvKϚl>`}lwUO f!.hA1<7#An| a_~r os1i6`9'kǾs6b$z¯uPFsz 7ΝMpN]kZrL4tfpS4g`&Eug2(Xe}*‹ߊ%¸3e{_`c?B59rWr<:iHRvp{g uy/WW5R?O44ڍ^ {00m:~~h}-ŷ{3)::с}8PbzǷ*iyaʐ޹߸V=P SabjQ0^xmP R3:_rU4BS&,E.7iO׈V0JsfSH*\mmE=yBfLKUcic#6+T(Q c V V9b~-VxF:+U۵Â40Lri\a7A^NTX`?6?H/\3= NɁ'Lh+My'aL9!7/~g}Ϗt,tWk RB}:``p;|Hw֬Y9/W\k>ugyEMx HQkܳ/E-#aC?jmIzի9XP{ޤM ctҸH8+Бz }_A$HΎpSH1=}Z@>$Dz(]z}oz+_! Cr` +S~7^$S6O6 Ԭ G cٖ駟NӦMh9"{H| [ƪWVxղ,Ch/9I͏%f yy$d Y}90X8(TO<5elqsIsL:2цG4%B؅`Ԭ8ҹ09|ɴ6:~;m,^'L4U'I@RfGAiG6/}SӲ.4O-s(?w5yKThf/}Keyz]2@Z~Ӌ_+ fuIYL[R{s~QmH;1j`#ǎxMB`jZ dex6NfӧD@m^~{hX]qW\hH2Hk֑漚;o|ivH'|ro~hyR<3}3iLM<,7#õ/193/$r?)iS] b&# ,B 'DsOt#Nz4 S(:ԒKr6ycVJr%;M\KzQB<  *Fu1, bĨ)k.@q}C Ф$UAœ\k ´W8-I{ʉFxuץC=4}_L|;sA%>S'-"r^8B FIu5-;o=C @H`³Z&4ut]w0Yēg)n N*H/sܘ1%yE~VH}R۽7IWk#d7gM8vXv=> b琨  7ˌ *Bw8ww]oLR> 9o~sַý+]uU9>#G>?9wy_zCiv3/{^,H\wn!/nM7ݔ b>+֕~7L@kc>?W^yeҗwdr!-;N.&0agQ>;}t!ZdO7|s\>Č7uM3H1HoEhrzåp9o~s} G{arjq ,D$D|t::+G'?}?;{4N?tg]v% &Тޙ]vٜ2,MIʧiLziI -2~x>AԛniGfAҧaS~A܄L!&$:) fH a[l}7^ctfK>{^I?Ȑ{ ړu.y0P̄mWC7h?'S( @-P_XAeSD^zGq}:Z~ D#6(uY9,:=o(3!f` E6ʬOӜZDA8_FY"i8x>4Zj5:3GLP P^頃~A{4ZC[vr:d46e:)Z#kj8j8B9 4&5:"3q '3<3IG׾yHNIL_W$| oȔg2P|wrJ!bf49\(3)cmBi]4BXU%@`?&o@yԂM&hlַfsn U$='h_(XTf8ѿ8pkˆ!*j7L}K^.s qHvZΙ qb3,f>qi˓' 7L,.gBOreo9o֜_Mdf&˂W3W"~-t'S$D"$4 5_x`xӉ'ԧZv$h"/пpzꩍgnցd,ahRWmqa㺝->:^",@KW518MYV¨NGX1o?Ofml~w#-KtO|"OB`C$X"ߒ pvJrH %dv뭷dM}&ko)F+',>g5}9k['< ';7% &=%(- ~F&BI'5O~H4 *xl# 텐٘=b4M8~"a~ yCj<`ӏFGKBۑIH(Lx0 4:C&5?s,'c8 LX#Ϩi |}AnjxY{v,0G^D'Q6C ն\@|v/p-s}//xgխgF7mX Q.> r cQ#*Hqד[AWXŒC4кpCES #􀎈.' ZG>e"$hIN8@? +@x&}W8i}Yj<0y.gLBDvJu 9f4rB;:P,C4㹛Sد(BeOPt"(@%QIDAT4Q׿>>fl׼f%=iu h S+([|G!CCfX5~>0|j{ Z1>b,4[,>[>,1<(9LL{~ii\VI&B(NMK 4̈́kt~dZI׵ji-4+MLUuckEʉGҌ3׭f.#@Q&:oƭ 烸 ŜlWֲhwfMц4]S`tc4$K $*ʍ?'MYƨ JShRf&,3XND(YG؎p9ne~Agp 95.YZ]ZV@6|&yH (Vy.,Qk 4@-lSiZBNF6;p' i 3?ӋZN|HƓAiJ(+iG!q FM{~ap/NhPIH='Mw" MFUH+iMB;vYGVkRÐ@It\w\ IXvs^ɋY= 瀠&M_ɾj"ɵ |8zC v8 әVʙ8N㊤aZrI2A1v4$NL2HҤ-ƴf9GXw`8>Ѥ[!~[4 ;Tnm}[ H$;w$"52tyX=oٽҏX~a"/0>se*~Dh>WV7PEYGjw,nYE!~6E=~(i\BEw5+"P"$+"\"*,(n+"\İ /*u8!/oQCE&kuDf'8:!⒏bQ?\+"5#ݴAET8E\>;y_M3GnNjiVYAݸP]ԏ5h}r]cw>r7_V2P:3!~+HXt7i:[IvIaǢ9GZcؑl77?ƞ|\ v"!vJepJN~9wBYEc7ovfcZ`> ox$xNq!v+ ,>m_.#1L;},LYXM>=V64+" Y<[Mw褣!v:LFPX"'527SP vl#l K[~˾W0!GҳL}yYqj{o\sI+Sm5A^|Źs3;4k %Ќ |Ab5LX$Hp]wݕ7{̾_ͯ3|슏4„$CW׉D mc5Aߴw~(]w]keEW18FlqUWF3~`o2"SPL_!j kVP/On R~$92q͑Ov/+'`V$35' xG d 3WD8PTvb:f[Ǐrw: _ 5(;x~kCY4'T;*eD0(N8HHQ3m;sOh8X|d¤8TD8N;x cgÖ1VP;"l3ͰlB'~4L"?#MW9HC'c}HA"/pbIED:ttR~owm$ m cHP³pZ]o¸4"Nkgۡ[ 0KY": c:%}ԁ;)jᤄn'&O9V0 ΗD ڕt.LQ/AMAԬu wI cH { f)Y g̞YO>>E]Ќ뤅B&']RMc j[nFlSH:y~ xBhYN;Aw:<̴V[vguVD {ᇧ~4 {'{  n߾|erSiTHt4ˇt饗UVY%+QG^z68|d5: a\9?hB"qN;Zኈdyqotiumjv}kI[ouCx0{4mڴ 9͌ߟVZikg„$n-=9uY'φ(.<Ľ(#0]r%i6H4 /0/ e]=f}KN;cmґGI.e0޲jTD8 5H.tn!mym-~9,~,X|| 7L{lN{/頃ʝq>*޾L9昜9眓N;뮻f|`Ÿ{NH{gub³fϲD2 &.5nίFZ+hS:@G='Y82 _'b26d|xI'#Z ؿ5c.zF":Kl}m}]ߖa5ĀIkhɫFX>RaBe'GH~_7n-ӭޚ7eW0;eC ?ȍ H?曳9M~?lE(ȋ iE[2YL'x"ko}nGfc\ę=뤭_0P01:d$lF=P60 82LgqF͜93xD^rqyeXT0}Ɏ=!0עq_+iŠ*|;Ntϲ9&zda‰Y}f9?òƷk4~!>&L#VG7/C#ַuG8NѮ Q#ꤳ 0ş@1LDSCXVǤ YJ̏rH4\pA:l0ޝw9 y+,&YX̽M74]q١ì y A֮s8pi$AY!m S4!SN9%H} ;fiO<17mF۹>6RHA `VB 8FQ˳,r>2i4Y\#]:"+3tB֖i"S4BA`E8oQM3ķ|gtgb_eV@w'mE_(qpd&%mNЬQS7m-\+jHs\cg\RQ ŸShڼݕ4јοJ#hJwք褣Ĵ\fe释E'= #;=d ȃk+rô浻;i75h5|k=}SFS[P&#\NJ9A蝼2nI- ̏`&- ф΃z4dVJGrY1.M^$M1 8qA6?đpK>HcZq=c{E|q9dkzkvZ5#f$pLizF)y; \ "q(PIaRFN$1mMO^\h{܈DJ>^ a S?h%N[snZkBQ,GYa?(?u"jfyN*b:( V _B{4f$7=5VjJ$s2oWT;hDZ3VQiJjK̶.V[[q. dlgb#)+",Nx9WVa&h1v :/b=Gy5DM38*G뒖rTCQkTU cb ^k!>|xBnz3fu ڑFHƲHdcx#FZVud\ɚꘁ&ZAլ*m؎,`6"@cY=>;묺 b-jÐ!."o_[ <,w3Nkd$n$0pT%:5[ڷ~YG񉒆k9W#$sAYei, 9{-1gio\V[V c:Hg:KYwQa&=i;a]2Vm{|׃˦^L裑 GqՉ]6kZDOJjzeƕ\&9Kk*n.QԵ{Bn]^V -$ vnP0+3( !uWt z|.w9tH=iݢ83W/첍wD2S^y'uQ6**xjn=Oͨ5A.9N(0 s"ftte{yw Th\hy<WqERljHaZb 8S8]lcY3Pyz!7jC( !˛̃8 bkh#XHA'oÚN0EV\3J|Xª%Vp)VO&<=(%K G ,3#!fC W:MPX8fX/>Cb*̯INS:VcEYIS 6/$FB C~N\fLQ+rF,oq,_ 3 bH>P*s̄!~Ac=|aBB烨 V>r)?7DʛB_')3D8lNX<|,@k: {A&{34"I#8Pz_Ydz e#rS@8ȅ(᰷D2xʅ*aB&BH<Ն,A@b(1h㾸7: sh O G.IbOQ]P?Xs[BM7<P= 0q? ,EҬ ~x ;#% j6"ǚ>opY?d-Av ;5bm1)^]Odk[,#'+dccy_ XEł̬:~t0 "}}7?9188x;vp7}ӡ &D\(pjp#`|; (D}\b0@)(jl[N (8΂K  ^~|FP#0_$@bd$ DGʑzd RGSP K%UEDeI*oT%՟B-.POSP?TT٪<9WU_,ԘjՊ*]VS'[9+՛;4hNQy5vi\$iZji4K4j|Lhf4KOF;C"jYiʵhkkkjj'jOӮ>ݥXuruйiE#F\^w._Lw Ozt z zq}[=;l䁑w P[X[  C E Oe2:nkL352>aMgsk~PvϦV Ŧ{MQffZ͍ǚ45cA`XdY8g2ree۪Ȫ5zuu &f[6˶jn'`10spTN{{}}CbG^>on:i:9;5;vu:W:_wqityjwzˍ6m[Www{{GGG'CX8I y󣗻WswymcS._of.??_#3vgLf6s7ec8p{kd X>Aipfpmp[Ȍ塝lC6]>Qm8y,:6lʱ"-" Q 2~U#1ĘʘN3c&{4nu$%Q-15&}R`Ҋqw)Y?YܘBJILٞ20>hݩn7'XM6DMRęt0+ 'SHgWsY5<*^/߇,'cEFOO,>K^*;4{S9I{򚄚ad&wD)^SVO# |ZaoaeᇩSNӘ&6vϊ~hi2ṡFfnc6dNܐ;QرxEIK K<%RRqi  ,Z[bcyEuuK2/u_qqp~wXQʱ+WWzz PHtX۸|ݲu_gQPʠjQ W7od|ӧ͂ͷlJZm~cV]{;;vleki-Z+ݝʞ=uu[-I=ߟ-Y:L;\VOojjLnh kjin>|Ȏ&G+i[zr'E'Nez2qƴ ?slN9ׅ /շ=.7^1U^;{}ҍ7nLŻs;;w>ߝ{pco{ױ=œ'_KRV<3~Vs7ϻ_^|+SϪ/W[WW{ۖ}~_AΏ>%}zyҗ_m6 vo0opPsdhFw@Mg 3 gDYqNm/ @4xO ס\)-Dx5=/"?s-| eXIfMM*JR(iZHH02210100 3M pHYs  ziTXtXML:com.adobe.xmp 72 2 72 1 2842 1 0 0221 1 2 3 0 0100 1490 0@IDATxyU;=5Zխْm<Ƀf0y! %dY++$++k%$mdeI%ۚpι߮}Nsn۲dnծwڵj}g_n޼鹱++++3ӳ++kckkc+3N{|g#Hr+$8[tͪB*NӫXe2aͬnHV+SSSJlЍ$8 'IBHERk)a<ǻM 92+Cf ]U.4Y#jb0 !xK4*[P4FEg-r&afU&[ iYBB$fgf;<աYoյɩU ip)2/ѝ"$+VO1R5dZdJΙd];@v$0D7щbπɔ-=0C ҵ҃"Kgi[ssslfb|ܞ!|PPB82Da0 RpkUOzn2 s$vzF"8єHlٲ3Sf&RJABQQ(R@4&`Mj=ỹ9bٳgr|8dR0%IyJk$-YBGR]a ĩTVVVMkSZzqglzrJwV&wk+ iLkq>>8 x9ssb1ybrq53;7ݚ.]Y[)D{vkfWړ涘κ IRW2{j-KK33ssn'c +1_"ZT|{z[bCWR*F1DI ݂ 1F.NOTuǪ`U㘹 8 &ݬH@8YZ8Yfd|L| ֫ggLd_ 6Jg5ӨEpɱW')W!Cy+'sRQɋdT2hf#E/(fLݬT35_f)`_9!E'Jy]=7ZEn& .BjǟJG|Bu3gBњRfzP$ C/%˪BV偶Ogl*|1[IlF*!`M'fE@%dV/VA#9 })ڲI($ }JXKְɼ<&Y5+ $Vu4%dD  $|9f0m۶y+)Uǿ4J~nѧ$S*H4Ui 3)7J}dXlJ3* plK2UΕm'OHrgzl zn1dOuT=\4"+IU-+{!թIROY.Kw+0=2^YQㄷ ~Qwrn~ǥ͛@1f-ccv|t!d8ke)%[U_9!CBO-,.njr|vzvNUH2?7 9DM K˅l"J_0: 0X$U"^BY!/轚K@O8},ǀ>ЎYJ (#J)Rf$xW J s4@})^8{W^Bd4:^Vz%ǓckH74sPɊM Ѱ=gGu]w3;K70=묔qZȓ-@SD~mۺ}֭ /`?'}fg P!Uq5* dz[^2tQɬݖ+%sb"$ϨE)Sih$]eW݈Ε'ZԴ2{!*Yl'CTRho0 nɪ${C]tIPPLa"]!DXjGOبt{lfyZ$1٭ύlZ95SZ,[M,DU奥);akFy|oL>jʟYLfAkpJ/I  ͘ XzwC=e&'H..t Wzo&UN!H4>J bZ6IgޯGUZ`'- KHHd3SiڊFl&uVZ08‰J(gMfxO>8TXV:m38Eάf7mNB}ZV`t׭rdGeUx19ц*quΑUqjT[j%$nR :#,W8 (ئ9qh&  r%t+ 9d*eKx]K}xџf~Ѩ'c#K/¤$]Ձ YC!M = { l2KϺj6 1 #T&ZT`);oJUҨڈrٍJX[^'gP4 FWH Mu֬@A6;:h AYnŒ_y|^n Ym[mj HVDx%#Y%#/:Mo` +U P\T IF<-}nCNx#ՔEIЖx2T!)A 20L{x}fA:܂`E$A'PB daͬ҂Ѽ=2cg+3Nxxgv=nZH->=XZ8_ѧh#R<0DYK$85הQ^45}BϞ9x/x;vl޼jü`( CQ9K 2$yH=@iUH0 = ̾UuH93˳]{Y1 4qO'Q>Ss*P2,je<~ئ[6|rl]:P`HUg-V$M kސ}J!uQLH9PbK2&"R!IRbP Ͼa EV:5 ؝&T!:.u#݂eR9 8XB$ R.20*gK6x:t matWT)C#^j#XC_RC,++7ya4xRh ^031M6mw]02{46Ȳ4= I-~/x#u"RQ0 1W]Z );o$& fvZR"m[_*$`338K1ɯ1Tdn"jaבgŨ1Ф-7Cfl~n @gl|iula}Ʀh[^rG69oT ](v|vy^2+i9+Ϭ.]uz~*mGً1"*ŰQ` bZN A_V2x+0vcrc_{G޵>ۅJ6nFu쐁H R(3sF"gnQƀsciIi Yi^'a$J`nȢdDo)ڮh8 d\Vߏ CY B6ZOlnM-.w|/cXUtbFM@WR~ XV9)8}šȕ9{jK*]xT*nzY5d)ĉ"dqQrh%'>,\9B8>M0n]3zaT)v5pʘ^N EaT$&#ɳHr#QqI?B%@APzneRUX?}cǍXLCCE ʒݙaB}yWeJ)&}tr nRKM]E74U5|JR4?!$ԢGqSF4DYPnݲuMsS入ӲBUfrJRDBFƫ$rIAU|*IDS700Z2nj?YbIBQ ̭r6 V8&01k)5 Sį|2R!LM}1Xpu"lu5>6s٩nf7Ӥ]\9"2SiPVO2ffl_ƭ1w[h9} !1jΆCFr#-'6s5vɫu+/rZ<{ ޯL)e}2I@W8ŽI0d3V"Oa6JzdVebꐕo44_nE(L{yfje/yMs?ݴe{nZəg˔ȂJzE ¶gťr`K(%( zfoř8= F3y '&.$/7n}C0a[)Cu2ӘΞ9}sb1w,+e #QY2 t+R*CH ؓ3$M"m T kpFa&SUզZh":WFDf+lf}mG0\,gjr|Kwn3?7N KI1jє1Y])Wj!ú,~]Gz̺at~0iqˌ2/3K(nmlJ&SX/FP$$˭f2*~pǮ]n&ƣpCFz韸D4ѱOaͮиHyx(YszJ v.ԯ*ۘIVg$riR7qysR0-[\&௽WT&m# 0<@ S3Y ZX5۾k32V0&O.N|$pZMLqo;& wWnȻ2Z37\щ4xĉyR]xFr$S3xwuM7^ ٹr}vfLʈmԩYU=+-E ,_ 4QPV==o6b29QSrtc99ge'ɔ:LH QDyS e:2H D0L䣾45 [ .#7E!+E7d~'8 Hfa E|9QE!]*Z-]KUiUi U(L: w[nҶƘ3(5\U˅r]kθ'a&r)3rk `M߉lD#ʳ_jxn,,A:=Roj&MhD?Ic!XNǏ(B)&?!>=T^V[ҊPjmz $/"}v~*,"+[QF7 ¥K˨ɦ _r8I^==]IW$nZa>]jEK3QZJhЭp2jT,lWϜz?-iWva~a9v!?] [+QZ.IOTxʅ\z봗3o9f~ SnQAe'} %YoDj"RDW^ӻ\)êvIfY_EQ )2&HNSL6#1rDs<'Q3B[BTRk^5xlg-5'垣K8*e7Xm-o+-v֜܉׽4 m6_l[v휙HH'YU~ [x3D*#I>d ,oڴŋr_#ywx=y%hIY LQ)+_]DAgd4653Z^+kR>_S3ӱa;˄_PLۈ9u58-V1FV]WJ#K%B^Y)r=z]lXr3EVVtɓ';19{1Y:z48:޽]w>oG?t -pe޽޾}'x<*S?pi\~FyTe9xz]z\.ʆy`nI_9s"̆;tٯ8H+'-w1#Gڵ+8L%n$B!Aڶ^.؝Իj[7\Q\@ `EBi([ ~Moog4zzODЯCZ]f˪8v8#(UNEy+$,/. h$%/8`4ưU17Vg~,_gxS񠋒ƕ,FeWK!AD+qbh@+Z Rᥛ,1f[7tçt G[Y _~zVJEu[8Z!T|` Dӛ38 >>%GΪ8.@VTt +*S'OKx8`:tn{=J/;v7ozGyE!@' /|/|gcGx/q8ӳ3<Lm-/pڼuy̜ϵΐ3uQ _ot(_ʗc=/~G?rX[oETB`P(c`z5v#NA.y?<,n-+J-kʛؾ\˿x9 ir+K H0_8D-;sr%R,‹2 ITP<3R68JMO:CZeMޝ eP-Ȳ4xIyլ$Mϊz8*nD_O hX.uRoT^FZFgI ^B^ 5ZD`RՋ$؂kFs^ bv=޺ysd<5٥ųؔlyxZp2$pOgJoč0mټŽ*gCkfPhħ=b!xh;Lbb&adRCք_S|.7AYJY"r[zʙJ8[RP$>_lR BpRΙ{UtCe [r2fS7}ɩe Z>Va&o#AdYH}mܮ;ybzv3GsJ ZAg9"jͯ,!-EĘe3df)#HBd|c]Ҁw `ʗb7]m5Ax:eJrodۋ_ό= 7߸=~;Kݺm3q^ze lپ_im޶!]~ثz`72mQ%#؇8MjC xCXGEs?1Y\\V'ϜUǏsg?EE8v-=e7;PWЫlB7AP uŎoC rX T5r/ܽp F2I >qN丟[^G޾emܪ.>m֍T{JiT4%q]`Mp>8f`cf2~v/{q4zʠoRz.oV'!s0@MV׉. ~lO6`00lL9O̾61Et@bLa#WqNR8$DT56!T 琿W>!X.>_/hHo͒C[~烓TN͉DLbcs31B3G5B}+:h㐹T'~OĔd̔)=ɩFzFHr ؘ^J~g Vg+.pgRc؁CW:z+-z?ӀӳSΜ\n/ML\cÇLW_uU9Y9sÇ暓c gNdOhd[4R !vz#"O泰 tŝRpcS,KYU/ld4_Jfe>R n)fu12wеxE=E!u˖h>\ށ97\ S173{7*_02ݬ]m; ?p@rzsUjϵ}sJlץM/БxB'laQ/ !ku58 JtN oFɔV*(IMLKEbюVf#ec|EBʤkN 靅$RhUT﵄rM>HrGD2.s0yw/Elw{ZsZ ,EDn  Oɳ٥ O1Rv%61+g&= ? dVΟy!@۵* 0./alэ\^Zbq9,Aw)s6LFtF댞;w*acX3܂kw(7tKz=vj8Rl2I.F,)Q~ӟ6908j7 :3dz+= LuKӀfj@-尥Dllg/{ =h3)f=ChȘ2dDzvMhTYt]*a2\q ]Nk4"O,ʛ&c嚫IY_'>g;<]N) i[`dEY%p HND!Xf!KCwsꑖ٬@O!5l$ soȶWt)k 7|&G_-K]Wj=SV>"KBN"s%0$Fy8[\)pp˰Noh]Wue7oVsFo(6*yeU)h#YWe(n2T[9gΜ9rҴB'JtWזnaz2H\ɊBZeAEn) ysyrXBDpfn{W;kW\|?~뮻.w7YHxAj趻]/nkvum/t 7:'7tvn˯cb!LQuTFM]>4=)g&Q_&] xlzT!@F37^q(k*1؏c<+?؏/9keJu٥^@``8Lx5PhUDFqn$#뒒JU BI390jxjO,i̩:$$8;CN.`9+83x2re`)jgU;ԛY5 m{es^rjWF(t)BR,bӀZw2m/-,;vRWt3ϲ =ܱK汱yku=KbW9yyhT V㯓8t%Yuա7I t rէՉt~T Z>a GNJQl:[1NS3qG?OodG'W$^x,CS>ᳮrQ٦.A$ t}e&̐#>L> {ix 9Qr0A*+d`R6¬H}֢E=Ծd.ͩ S/8)Wц aFrbtS GpU|Ru< i5n jzn;jή"\k,MGvrˋ:#tHdnz3 *o*xT^u{ᙁ+% l\-fb_Dxf5{>1 yK>)[YʴW' AVGNʈlz}Õdo՚dQr~U@a& h_2BY<;~BgVقYZ^DIAYѮ0>Ц=A~4H<#1nBϟՓ0R¦0ÐaO?J0E<χ*)I"455xD>vCNf\6 )˓b\mot{fesv C H]U!/F h)F#Wq}>6xڂjA0 _oi^p:wȵcmb~!l9o,V $竨EYuKiNҦ{G%_y|$$r:wYUa?w_^r<ҽJ4o{C\I$xhL@qA\H2~Iќ$" ,Ȃ/kˌ`Yhe͔듒T~EPCWbǷ~뷖D,h6T0p.9sIHI yF||m+0,jŇ#.$s6L&CY#M|8 Oz2-i5scCՍ%eMLxqdG+T;H!Y=%=TIB5v>G&&xGx]~-1nKZ[I 2o̾HtmFEoO}SDfYBpӀ$1cr0˗]d>|p>|H;v1pqH ,ѓ3VofICkd#q0s]&T[dM0)\`4֋A͐֨+K)(*&#pc=#zXXXѸE6i$C=7lҕ?U0 j8&&ZtB*>Mg2^e(tXĬJGD$ t\ OZd CЊ!qE2P;+ӻ"4I/3,.) ⸥%!7~2> hT)伻)kE]F^]W$ 8[P4$&s޽TĀ0DQC+> "3=7+68铧Ϝ==33DžS1&:~&/R|-2vJs(,.K]}]Fw_t(=%L--Kʪ@pkxxEd%mb_ _? :X:K&>\.V1"k]OoCҸ=^7/~4-[$Cd7#!8 &ZhʪWH%^*2,rWaXDBBQm!@1b6$BEK̭@8 iGn"< LdKgи@<0H \٢`bffe$*bEApLЀPqlHJ~2.y1\.q NkR$?gJ+Y[i `sKV6r@\86#)B0rXpӎ)3v{&TF0Zk3z-T>ǎ;tC\8m~8X젌:~ҭr,b;_"9%*hd(a׀" \A8θA=tܴϞp-&~A x_E/zс?N .g(#7&ljC"Fy?48W ox~ߋN8t^2s34,Iַ~|Xv"A)I)>"G>uV#΢Qzʮ8x|ץA*-K$j<ȏi̤EWԹc~ȐT"n8"o{~$f( =y[hfo'6B|6r8*@Y%y qO)8TO͐b4!O%D{RF𩗲8kI4H& I*&s\VY ItϤJ].<4\F5n$Flna6vng0WjʟQL]4£$ijb&~~bbz̶},5Ćңj4=I%O:i f53 s) 9[RH^O*g1DȕYɊoi"Tpdv'gCiʚX;2$r|e4~8IϞ!IAMk6˿gX6 o'f6iVL,o6gTk7Ԍ>/41.fR</ŋN,.?As? ^/wn L]` %dfj wS<쉩 -j-rIbDvJr+B cf57 b9Is1J`7ⓥ ?sOCȞu|9_IWUy9!*`^=M1ⅅ{u:S;UZ<'0ymڱwpNG?QހCJCA ?'~~joIŻ) [;w\WP H )1e_*Y;׾//y`'bmz;P-Bq|%뮳RḆTAuh"ā&l!`Txl׊G?c?ƿ!?nx; ձVB3XBII&D\R x$NA L"\m =+ 5, kefPMDN|m2ԂѾ$Sg$F><_iF"]`}Uq>w59W(ܿ ..WOMʹモ3k+K;Os ]/ɐQ+cYj8ĵohT 2dH7&f|h/ga/Iύ×k(]W}085S~*|fzjnueܡ5:n 9`JKHmRIN*ɄWp*0ύ EE еZJ :XeM{mctncvKÚUMfpxi\ $\ؒ̄~W~տ<_J9:܍RQ_QV+?vT9#*.()'X'5L撪ϧ-GLkECB:U5C=ğK&f)'fKUY"HEūɸƾ_q+oLON؃g"~o|~U>r`u]cEakD.?J&Of,IrpUQN@Oe!ŬoZ T+ٷL^D3w87s;<TNl-L$Z pw9粧3p(" 0<3HS?Svq f{{ Ń&Q2d=B_b wV(__T)#0!♅rI39|JUR)g7~~Hu!ޒOT qn!EMA{^*!yQ 8mMRjOwAČr?۞:c'zx!xzve,~cnj~ewݳg_7ⲻ/7pzrJU6ڤ4("*B֫j 8X  7+vdk|O|"H6-Cxhe/k`26c?+ڈc/{Jc]b;/0>+?\.Ϋ;C N :";4" DX9W H1y8.8p)HG'4< e< U0@Ӂ#" o 9O" hDKDPOZ,&r=hN*3qpQ3% #={R h C?C !OTL9 "̈xaa&Pe[BYP)pם`ϘO|ӟ߶RߞsQ w$\q2Y+U^fjɯfv^'~驸s=59e&GXL~g2VuıՕ)=۷_RNbG( D.e|v>sOrrJ -//Izxiy g:`P{"yz1n;9+فy_ҁcv[m]Z\1<1U,rrSʃFH)όsv^Amx1:&:,ߛ3`?2xreu=ifj]>9۝{sɐn%Smty[nŽ4sB^PqD4)h,y"+l%?Z=p$^d◂2ϧ;tT+Idrt.@ΪRaRnDIX%9-M )rN39V.0l|$[drhɿ<>)ZM Ocגəٝ'N-No1MLn^LӎOtLApVk:M單WaMid^) <{|X.ȵ:OW`br6745 l$"8x9*,kd,.+bIrͦ2Y&%¢6OtpJ`;k.z{?&c~VڼiZ^n/i绲/YpV`Ԭo׾ٲmk_~jr|ʄYԇ'9jn w_kuaZoYno;+8O򮖖!6VZs޿S"-&Cilk-,̅#K\c/gFtFY2ܛA1 mM^<;;5Y 2pu35Ш*qcpu7x4hZ=eb/k]s jO^oI+=9/o[D SKK,gҶK -cMӥS_ X|ϰ!-QOpCgʞJ|7d9GI|\B1Vb7D c*K'r)ڈxGDDRd+9(g)Onj 'd͢F7.$L9〘 !I$W Y$5]8@M$5@S&ZR"$!Ȟ&9GIIPe$ AWYxm&)y>C$!>Y'Y ".KHÄ[MnD_ԻWu [dP6uQW a4ϻZ[h6P㜋oqI4*mëB6GT'[m[{NLWZ3s =PanIe8g k1`Ĩj[asvi"vi)*KL<@!UtZ.ixzd.j7P&81qyab,Et%=7lX$ao o?q#G>xWfWA=n1MRg36Ű'ꉶ 050Ȕ Ǎ$\ dcͶm5My b|!UNxG+ 1nfwK}BWv|K)+}nj&4yW֔os3ˋKD\zOLZe$ gHUӸ_bTӆBnbSZ-oƨ9/f#Wc܉nEJ3r *h1T_(׏OCͿIٙrۧhKp$=B ![e)WDRr^f-}C츻ꖅWb]ye^ .!jlы7+?v{{8( rӳ'^ԙ8d>ݛ7oͪyf7dw ;fZ˭ٙJa4NZ7bDsϗ|Wَ8)ꖗ[02yb87[Qi>C k'~ t7"FW[-L(Tܻwnyn9H,< PM˂Njh ɰMb)Yl"RY/ʌΠ{=p߫2Kf YۑڴuI. t%֯S~ۖIi'h˓k3ӱ&Ggx{}GPʼnJY[ 8zfkTS gnfy7}n߮nM3+0zBMatZwReoIW/Nbt!~b"֠ㆋT[kKǑ5(Y 8Scg&V(sß^2-評33r!ZyMl=oApc\$ѐ1RR{ka"a!K%8JxUo7~9w}/z̚]{>fm-7qK|R{Z`TZ|AnBO|:L甌ʇj|a,L*KP.H"0,"K`ThM/Lf\W<՚mB&0_E1C 4+DET'RHy6rS8Qr-(U W*/Lɔ:ܨ ￟U_ QA>VC[*&HWxd#*TZ^4/q&t)y߾}pz`Z^@ݿ` khy'wk-?zQpzi5`7wF8+0}nga;L{rӑSYKvul3soW,+Liڻ3w"2EqYHy6ҌZd#BۼI<15%cuwe6,~'Reu1?oW;>FΝb,26mb)[믿Qq? qM#Ԏع׾VVs#,!Dz|5`XvW~ѣOh 6cĉ ʤ|`B:肨4S Y:IxM.a{q#dm ̔Gm烝8X9hvS)d.iVGc}ct8ZX[X$c +N.tκ67>;K[+ U3sFcPA&GӼ'_\Zr+o|'c#߫OO>*xcSӜ!=g%VN1.ٶޯsק>~e;8zѽ19K{ ?c?7Ç?ocYcc|K/MvjW F`7Sz/4ox!7}y?}e?䛷nڱ flmrְeɟo'C?dK;wkQS[e|>so_rJR5Hg#G`4rî+|g}cyZboV{sdd&-hF;w\+w\ßȎv=oqecxk;wr,w}G[ώ-M{>pxkmM`imb]G>Ay|Xoc cg>pi'9x@>x8p}I?AǾ^[| ^=s!h{#cK#KGܱC?rtDZGWalv'QĶ6zߣ--'Zǖ>{u/?SjtsC'N\2W=:x궗޶<;:zsͭZ;rѳGPkmɦU{4Փ9>gUYjwⱓc'Y[.rבN>bobH3ZO,rئ婥Եrv܇&ŷf Kk,C|۶o{;wڪ{i;o~ӛ>?{ƛ&T*>\1p,ʆjBz큇}ZO^~wJ of?|Ǟ[?~Cۢ3繷I݂1B] S]NahC`h 37P6'q>7r޽VNpĦ:q*%GSw$'a+B5E,=w%%XR|OBsg\fH$yͤu&* իX?XUw) H!YZJnvk܏Eˢkaxu[R$yy䠸`P` N&d#FUIl *uww`lZȽjR`W1oo˜cGǯ/|?ljd!Cх#adv/5^{5 X.YH߾ل޷,]7VaQP^oYK޸~Nb 3ld|p]/ipp&]\ʅwYO#;yo[(LR'&|yV u-O;| e˖q)qD`*t ɕ\eZ"G-Be5_rll1wK/>gj#AV~~]˻lcg;]w`מ78mr3֍6W/_}MO.Y74T7oN4L=]|ngS#_<{v~cǪ:|cF{y-l۵uъ?^ߵXԳxgžێn߼W\?~ˮ-#+z~Z}q#>r_}z_֗7Sw.ڷr:пmG=|k|G8wx}s{G9YG;?YjYWXɩ>0e$6C@Pe.rhiYj*s R0,n֎ʚc2U3~?od&bL)Jp⊅?,PgpY>)fʛޓuU5B:-$ƇO ".D@0:v B 'Rxt< ܥ-^q%tYzIRǔdRǀL7d4 OgxjbS0z)UӰ2O:['퍍K_ݰ~Uw_7::05l&854Ftn.<7my;0 ,~G嗿16p!;{Xt 󈈎=Oq]vmX H$CTvˊ+:ten߱}mO?飔e sı]/^4nj]] L~{׭[m۶t7E]lg[f-Q?=Q.];=W€2afͩR8o`=pT[L^1|-:Y`ԁ[Iqh _ׄ|W~ӏ<W\AMXTUu;b/o߳}ˉN\~w\wO?pcSwu9u+ʮ Ϋnjź{_ggez[OZ|E:;nmUML/?ǟ{ܫu[ԧ=֮YlɁ |7[֮ԧ~e۾m/鮻/M7L=w;7{^hݾw?|/ZOlSrs{mol+Zw9wێ眽q=Nް7Ovt~b٩ky{m<ӗ\t[~n[zW'y噡_~cttK=޻ҋ{Ŋ>XWLf{wι_,u-xoeK]ڷkl8?,*mlv1ՙ+crp5iW>ׯ]{>38dWa0JmulbS!QSYC+l/V7~-Sx HCC.<(}$W{{zVb7֦Yff foQ09ɃH,uQ/,6eU| i.3m8dX$6<̛N! xtU*Yg8_]+$j:gxx#U=^6T){!vv\|`aɥu1 Rr?R\{5,wv+ c͚˖-E4LP0z9tQVzp'%0 wZbkEK|մ) A BvZp!+??@JP*U$c+Ř)YTNiqbT7?1Qq@mʼn܆7E691ygpYKFe[Nv^}7osxqx5I.VGiJK.pڹs׮.*w6uT_MMojloloSyҵIU^1w\\״`ƪѱܒuŗtyɆב5TT_ڵ.%qm?rnSU.^tǁ,nk\ھcw.X`eKUKgFwZ ]m d9V^ox9 b 8 J8CSvmum'絛KuD1 sZmspƢ9 I`lxmnGK\>1:|rmNVcMq}b@L(Z8&ʻ$zJdqD\?6ozˍ8,.zg62Ĵ mq wVO w$$rܯEp΀1֞X8RH,l#jӘWANEO$/rz5 +] E$뫨$?"%a=2iPD,Az"ϙ+Rz %&d.#B"JEM "l>BF`~) z&PVnBzCJ+ʹJ8H N4_J\! 6D2=¨T `:)P D$*(BnI~uZnԅ M.t=W5I2zKva3'1ZaoA(喽df'Omi{ [Nn{m=5UO>Gߛۺ=lX=w䑟xqnѷhle닯x`y;9<7ձ+n<ٰww]7sy+n߸jKOtx[Ʃ&~kmX\~?oCW\y_j_;1027C;c[}P/Sv#ŇxYb:yԖ緞{yY1o}u)zur^}g}3۟ijikl[b_%9>ѡ09(wvmƄ:8o˭<dk50w|tG|ӺkBB;{u , ͍-`=&8l`-nMwY-+iRКN`L %m3y,(g Ht KZJ:f` /0Y)LN603KMX 3y@B)=` ѦAN @JedkzYt!V8mm) nt-Kښ(<#gORDظX͐-~Rخ<ގ9CY"vwت8krDl-2:>>46tt~w 5/XԼFXWKעLJ昗nw^߳cm4ݳp?64Fk66 6V7_f]vugJ֡3젍w6v[8>09@sbs|CM#1.}honO'e{jn8&oRZ;-v,~Wt{i9KXi2oAۂɎƎ ~l^9sL꫇dx]Whd4oaE*a"n`zީjhjSHS5|ig|4-muȦځ0=XZ]#c4YfD1Ul(^PCt5/D\d[AhmG|}I{my霾dN-%/Yy[Ь YyM?QA%T"R)R)f&ѿs7r8)TOEq U kazD\2IfTRJbN#*zd31 l2xs 3B>10}cGK|F%LL^`V7qԆ͢ÐFI.^=]B %0US;f<4hrD-+M4kYM΋G?vv=)%K"sTv7ז]aSUGAe}fn^ue?"h)F'nbq F ̜U;pTPi58"›\{s0v0SQ_yu2b}Ƹkb"VT}Sv@UOtUkyRkM321bdgno;7kg04խڳI"r`;.|IR.8jZIt;O:8<2<`涖ֶޅ9lj >&•I^^l3X9]!~T$d: 6/DG/ZDgfy"A  "+ )"e*[Qlex W,`fSxSN܊KQ)B!PKIZm ?&9"|dJ8BU6Jy\be`FA)'*x?ٖG\٬>Cr@:O'&ۋl 0d“ɀ!LR{J"+wդP“|c(/8PjFnާ?iTbAȫ h1Q\O?< ES$ߩ՗FG{s tjbgâ /}q쉑>}Ŋ=؋7msssf?#mgw_[E5 ?~tE#^GRX Aec[rV?PUxXU'muM>pi[إ}8M"i%$3L='&=6#W,r% lbJRO^OÀDcLX*&HWC~Q0 Ek``0$L@t34ۑŬI6%Pq8 0Nqǡ rk*X aD} SAN)")`0`#|yb|ƒHnIOO,<3JxEHה;v01 xq#<,]IÄ:<8="p2rJΦ , F%ť *$<"OS\ӎ9wŇi0pBF 昼'w%&%jPUdrP %=ܵ{/-E1 RC>vY .zis2w|+M"R+zfNcI.5)~ƽ!xf@K(3leuoœ L(Ҡ:?+hCD4ɈX`!s#VRgdX%dA?C WO` @o5.;{-=xD7#&,񭂂.wHht WwzUwF{kSϿrՊpLW׭֬ߺoEx1 ួ|}q 3HŚ-mQn iS)b^V_NuIooox?C}tܵ78kuu{vx>{nʨ{JwyCrG5L\aNy'oւ8b&7'ZZ *唤b`nUa{, 76m>_@~=q91 A[5ZUH@D7!5l֠4UiS6hvnٳkHްq=sɅ؅-cCƂol+ #O}PǪx3fϽe_?ᾣaK6t ,Mk!"('3bp=GL01)j>AĕD~HR\Y,觶H BEdy&vd\p!5+NX|ZU'Ouŋzbm?$,Pb 9/CU^v]by%D|ጬ LF~vΛ?(RXxgr8VQ)3Tgb%e?T&Rtijg-o7f-~Uϟw*ws˫^{Ʌ l/P1EZa)a`j1 Ҏ>^!.N9a:NF [}k[^K{߯Y֮;e%{o5K,>rM/lxmఅ5}vj;d/O񺻔B?=F4;ysw瓟%kJ_W-jMtηl沀Wn dkYjH9R{ǎ?CN葇$^ڼ9_ yd!Hm}37뮽/8w60Kɫr|h^gs82<567]r%?X_G⋨_z%4;28rQ;~bw}:oBesad_/!B(,ϲ+Ia!ߦxљ_(5sڿ[ zw}[lq;| SC=RS~8:8L1]V{dtǛ]ஓ}Wݗ_+{\džyƝ'wCSm}U{NS')Mvh{Q}_Wpy;>ul_ܹhۑZn8whjP7X|e[ctou-j_t~UKW<%NnjZ`y@9[aX^/˿*{g< 17gt̏gtMgyI%1f?7)FeD𳐚ɗRSRT7dSa2?#U ˯3`3(&.f +rd͝?׌d]=5RI/ƌf ¨q x:BNWH/zǞ kjH.8uwۛ;xi:5ݳjhdjasg?M _^}u˪U=g:r?g??`Q=ÌGy?ZQ{hٲrz'?kljg*8/:>o~pjdg?]\1~gH[=/}IkNd&۰aSAg?S5<_SO=#};wXz@ks?@׿U^VEBQřSB+q35ԱL. K"{:{v)w̳7?Ownsl7v۷g^: ӫnú :Fw-QqJS475i]q;׭^;sm7iKc ~ ꒝-#Õ"EŚɛ=\+81>}bCWcH٤ Uv}o.bϹU{*B *ƤCڭڵk=ܣ*{~*Sx2@.̄c4,+wi0cfq\xTAPГ(H[Y?t Kҥ_:`q|JTTf?e%ҩ =k֬QPq_CwfI=2u&g'}tK7UkaN#!DnAh-dtْfU44;U#Fn E5jX]H.x+JYctw&d7U:z#GG|FG۴ͯ`ɂwo۳mp|襭;r$T v =;cӃ>+aO䋯͏=;2=:Y7525Ms}FнOںc['/6֞?o۾L`ܖ.>؉?uhW|vhhݱgΠ}{|G_ݱeϽT^zh׿m{oC?}LEdž3W٦(8Zv6"^ 33q- IeF0cE4ky:ӿf o"QX$i7 :P2Dr'+6=%T:*3nd6gR,($F-XzܦSVu.#0r6>;v}>9Λ_s֔'ʑf7gP>g9(}ECь&-*+*O"0>MtY5\ h"ZI͂mІ7ʢY=f/~!2ht~0I] f)&(6/| @NW^y7 8908y&EM ZATSVm{ɒ^@mx 5[a0 #on}[ҵ7˫ wKw-wUCmnhK=+{V,qZv}M?|@hzdž&+V,>~``Ąe~Z {]-.| 02pk'+*;)dij5s MaC$*K-)WjT[]ψ$'\!7Zܯv횱ͮdVa嬙$[:gA7Y-Ylt0HDfv8}2aВ.%!J`3yp `D@*ͣg2`[J爓"(HDY =Wf: .[alV>ftfMOva"ێՈa+T5']kP$[/@/W8=$r=#Ԗ+F!$DVP}q. U_•"P}NIA'j&5Ս>V^[\wc`:Ucyn8m|bkF?x$P,@>C8իW#[DD& 5JE0[n={bx]ϮqN<{] ]nY1=<}C >tqe=n}W^zWwut4wߜs]džki^ܞsM WDZ5x^ysҲAnZbŖ_4gmYtsK/ 8MM-/>oǕuҳ;w!ƊϜb`u>]OPtc?(@SI|RdOt JwЄZ}DnR_e0JRQjYr؈ZX)9f:Q S("''@gTEX]Zܸ_ua ha6$?DHċ[0JwS"FdmCGa^;ν<㢈2?M-CagB}{?ZcmXE<6.A^s:[:bΪ.Z2o L1ޤ(+#5a_H4ڈ+=Ů aHz>P9zȈE .! W8%$uBĸHUB} -aժUM\]C0BD0" M p=͝TRb/Kā &Nɟ0HYdeY&l0LbB)Yc[)"K-2]D%%Öb7HRT` :`𙰄 '΍kCX$? $3p˙mŎ$n])[^Ze:`uԝw'%)d {ss=~E]о\}ֆɡɻ|˯&@΅[_y³/ljh|y?{.+^y}8|Y2O3>SHǛ#ȼ ŬtNpv,{P%zF(SB)}]QHyөLpb*2OU~d7RTo1vd暫iR,t]xyഁ(?BNe'_pLlD:qjeM˘f%YW^b86ntRYKz}8rYL?XXڲid.Ν;i؜T UF<=бcO|BR R̯T6}Jj(i:(.׾ wqtϸ8p+<̾3,1r)L+Y?:" '*{JgB.6D<9>%*L|fj*%FHk#$䦠$Eu6O)FSRyROaCB$`JxO0(؁%,aHlrWv@&RT$eh,t% I1$gZT0ԎqUq)`@&ĬT0H}HƳ7Ak?z hlr`Bx?ABjj,Ïd,68ݓCԊ@ a`NKGS>_%KBz)>15~?j+n ҉EV`*br5ר~QdtYH nG9Kv\0P:UČ5<(kiLPJ hϦ  %U)kNTQODŽ{^%f ~)npR(B %r9<`gdB`!Vd< <}O:tʬSA:sK 0-uLgP>#Z!0C9~ Jr4]V@QIFcmc8iMSzLe<$ױ5kѻzɧy}|$}H;z+M,}L!,U[9M\80uk|1Zr3Qee  u%䘾O5̝)Yh)=ך4ZEYP0saZ_"!3jP"TLe-³`D2 Yn`]`0#$` ,9 RT_zJ@ $YJJHC>fDE6͗ dbxug(^82|x+ h;qYW#u8<}B;~+j&8>2 ($A iEMF0J&QqZe9d$xd)?sID*`}R[ ]J,jJXYl&Y zJO ؀XEl۶ <=#!㼿i-`r,|@lLEJ ,x*aK9ťi@O~fK\3j^ ^B]d`FcqCTrUg(pb XJ8l5o bp5.=<[[Z:: ؗL֙̐بwgA YY}\}bHXReNzSN3)` [!|tw0BLC&0Zl5*eEiA]Niִr d #iʺuN˲qtgQČq!4kډ:вip%#'ʔLbGDfB)=?u?*e@WGKr>ȏ*sYfOdڂ:ifC2LLN)<g㳹RӔfJioW+> /-c*Fܒ%=u_@<:1vL!Ɨ#Av.X.4TXg!]dUZ$*JMUP TW7LB +!+?xIV`Q\HLH)oZdˠ'dugDO[tm"%SQ3>'q/E, fmTW.)UMgyu>gCYiAf.~y>%f`خTv*9ket (:9%,e4)YRpor}cGp!,`/$?3inf1'1- "Hj!t3"W0TY3 !όH ))=tfB CH*E@fROĀjY a>4(%I?ΔL%3  Ht:p#`PO2. .7&glX繞joXq*^6 h " ō;1=hmݾzuC['.jǒQotX0dۓdz)d(S{LH;w̩:>O /I"s$I¨f{zOjK# ӣnbuw.t|v߾}|ȢsRBȔcFFGQ7!lhk‹n&ȝgT!1:9:9ŏe]VR8@IDAT#zN,iǓɒS:QӉDxA o9)pSx "l2{a5E ?#RvGFmnjcpfɕK/ffS$J<d P%cY "(HԹpuID<6!ɉ`sq쬟Loz™)D<pB􎊫T =UӠI `\)F# B&@deC0KH'Ƃ)9(FQH^dOt+LfMP?C0-,Gj3೾z8B~Svc{[kO0M $'8H CCK".'`o*yܷ&M dqޑc|j"b?pOpɱ}AlqZ^Әc$PsQj !mVspI5!0*.L8!-G[,c6Y K^/+s.64n0/ԖMx a]AKhtJc|SzH 㲕4FtMUh A`a_5@]eXHAPQ5(fKxvgB_jr+ M#22¼, d.qt"\]> T\'em֤N10=PlD-êtlbΠe҃a([WA4jRHCy 1>!Fd.gdI؄F?!"/7E _ :n(ӕPP ?؋նkzו{v^t"Y±!m|*`z; '33L(6u %F><OOzjxrkErR$&~%`Fl(-o沆v޻+_ם}Ƿݢ>:Y;U;m;.KbCS@[gC' .?Ȕ'[N 7xY66]qKHNŦlHXCKqp8[![|aJj*!GŎx --wQS4\IWboׇ, @Nr"3` 䚆cIbȅSDHZ+r) R&ȬEZsu7y)"!)(ۆ♹ 38n;Ƶu*$' Mڞc@ ]1o rE$O#E"=hU*~HAO`r~ў"QJ@*t\H+;Ȋg `T2"QLHZ\Iw>__L&vXdʅ?N Ŝp~Z`rBZ }.&wȳ)tS[c}Yarj]>W_URX̵ci ̄14X1Yΐ_"Ŧ C]t>3v _ozCJC*:jA{3*)ǤTg.Se"mg|B0xf`f6=eu50|z6bʨyZ]pm-LGXL/(AoriN]8C& 4glbRCBN{w1Tx{Cb)i]BaZCC>fmRbF?E1D.r/|%'Z竬NEP3d4$Xx*;SFR [Œ|eW%1*YTCݝy>]'qH7HLK;-Rv=WIRUb+OO$DJ(xM$qc `{zfc%vt7. ^VJ@ӽF*+{b>t=S4m|Vv.h9v3?k:ґT䎣۝̫/ ;YpgyƉ 4#nv`Kvvvt苻O9߿k׮rFQm\|qzǶ#Xw Lm۶噴j*ZDs)+hTh12$8lu !XR;WCLzúr?rw,j}Wy{?u#$[7{{{7z֮3%;vlQ:kS7'4Rַto5.;+*`Li8{e| Gj)uhqywLܬʢe/_g іQbT'[@rɴz#"H8-HLt&F񜨳A-c(7xhّR̯$f43Y$PBAXLȕ0w$nPYWb e傔<}8HϤ0388?ۍ2<10!t-gv13:OkEJ[`R'?%@^`>bǜÇ?x8r!LuaV3$+ dȕSذȳ /}K~LXEFGO^+$1.hvhɌak(c?fYkSEEMEmswʜAK\Fg +X1$3Ect$˘|-e1[ Wļd]QǺdʰfɶ5BSKʭ3:BT '0,:cD:Ij5B>B Qoe #<"g-zo(*c: *;GA32pɾqWU7i:]HxO?!ܙCZYG5Bf/~O<PS8]w??fHCP <_W/3P\tKW93Us UE4yGU7W-h_hhl~.TlUqduC5{Wu5'zO|{}g{v;/c߾SO$1޵vbA5s%sk쩣Z]! @Ĥ jkAݛD1[%US<(T<>>ʏ* ,?逓GK"di {/J LL~zzz)%_AJTT0䕂xޕK{wѡodi]nn4"lk]n #ΗXWD'ȆEgѷ##5T%8?[T-]СœiKuHTf0wmM  ;KD+Qa%/@Z qhE b-)nda#(Bh9T~(d2uxX5{"쭰Azk1mB,3+a3XC|MoL ~ʰPN!!Sb~tOk+ja H5DKM*T'cUc0#*f9$ Gˊ+&ۚ&~2 G 0w!/ qd$9`.>9l  G$*PxnhI@G0% ?V|cٸmSES8?"M;d)$H -d`YHCp#&|Wv}Sww-׺JR񫯾+M- !}wl gu7`@$)o*q1QhؓYL"bҰdwhz0O31,9i#n*ĝ^\Y;::h>94Wr~x/|v'O%3%?z|p]׊8A; D"'=))l8B3C< 73%70wȨ{zYY`X* I7K2[L@3NE A\gL!yb:䭼p2g_W{/D9<uXŅRe^)NAg>(vO8H|)1^a~0A \DL^.%cP;F-"0DzҟU)~H4¶ţ6@NLRYT uOVB(_|[O,^ϙe[\cLM<ҳn7hbAESϾ l 8-ӚXOז8G Y8|G JZC(t脍Nx*;{ݯt^Y2Vh>鑩1^#jViu: &xei_\JӓO=fܻH)DXA+ dYjK}ѻᄃ<^&#b %У,1XHjhj=nHSOsk濘-. & j}/;~ÂrX#+@' \щ?s?-aNLOTZuaьLӐI&'Fq6{ѪU +'g]sȞ}om;oiƵ]k>αǘ m ]^;44S4.jK 'NOv-?Z؋7oܽ_ODUm%Μ:ÕsutGr;KL;U$۫ofH\kyge?<̃r/NQF_V̺\?quu+Z'+LNΞ ^Q6\?n0xOk S[2إ 'Myf%ɥ̧K|9~~"=7[V>U!"SSFviw&i5STSYݾp%@QmRc.-^`cdfl".0[^9UY358Eqc)3IG8IQ&BL O&2ȬQ/AVSy`H)\-l,ό(nl(?q?SjIՏ:_i~rB 'R`SASdRϤT@"bhppŲ}g?8zLƬGzk[kШlҖؤ䩓Ljٺ١oUW]]/=59vU7Kޠg^QU]+\o?ĭkVэ6-Yx˺ tÍ멧l\vmMm͞{,LSɭuקy={zCL{pȅOb_yW7ڴn?{ m6 .N/8;ַ͸~ᕛFݿw1Cס|۶m/~׬YhA8r Ys ? 0bʎ,K2 q]wPt&~(TtxD n!bH'k*t;cKeB\[:_mӦA3 䏦A9˭$R^e^ʅ~)>rEp:l"~ LX:X^Hc |½EZ4mQ䢾^Q0gJfꆇ|jZ69W0x?#s~fzԴqxٗ^ij<=F'Smw# RV,Yްwߺz5#3gΞzuz{[DZsGϬohju6;{ZTW\wlko,w xLUv ˿w-=z?itz۝9v{{߽Sy}m:p@?;=kvgCgV7 MllW.mC\yuCe=šaxݰ~#n66?wwڪ<%KwX~mieý՚쬫8"k&ŚZs=Ƒ .X]׶Oo ־p}ʪj^ֱ뵧}Ҵqe`lB7ӱLXsq[MiCk˵|b5%4Ku 9b}C{j37ٱfv;^eႺ:v[yQGkXxL/lhw|}{?.v>TWWbTmK5u5͛6WUڄҹwWlbhE>߽gή]<]0m~G!9I"MkbƋWP@(EqXSO"i"eK-jhҔ!fxɘ+\ wѱU݈ OQci@=ǫlGpH4__姕>Y'r4E [e(NHb();/zy¸RJ 0SY9"  " O5h[EȓIQ{g,V8%?;IJINXg'F&. 0"b_J7òkUףysɪ[a0Mw|h|Y˲|;5Ub_^ѕsz$n?<79惟vd1h#xB10"SP> xi]x({47_PoDOURٞS RiJG-T$z\oazSs-ya/~mm+y`4V}mC) 3t#ԗ&Q|?m*cEjdlcY{OPgvմ.lvmr+r!O(d>;zzޟ,)=wkVwQYV56;m.ىqiSΫ 17;s {zY߉^/WWw,6!ٴav.9]47wat\wu0nҾ&nnAgO=pŠ/[PP3V^xyC}e/MrYőz֮\n߹}bltSc5ͬX7gnx~aV~Y:=G?ʺ*}ukM +:ח-YP3p(M)\r[XGΞ-8vyϋ/ڶ}edu9砬To9vx[?qc~N~v"Z,Ys|wK6[\jk7Ut졽-i+8{~O??>t#zYqCEec|XKC3VvzUquڂ6w>qM'Νؿwߺd9/yaVm}v Wl#T\U3u|klj^_'~x╍%_gz޻cm5O]4+EYOt⃇z~XQo։{{9~5}3MMkf9KC= _MqMei/qiō5*H Y13WdԄĈQl*UuJREfK-ŞN1YN}>ٍNF5i| EjD9|DOVȖ'D7++_r^ɄQS[T~g^^ux` h#X:caK[sギձDg8{& ᒼW!5":E"&26R4>Os<L*+"M}e.J{:R>zGǝBoGf@PzMdʘ;̡)d0Z)QfY(H2 yUe`!E$WVC\(<"~*%%8tE|}fLARx&]N0,\-lp`I6sJ `Dr:Pc)f/FGKX2:UW"\BuH6xe'WiHcgUVZ8:Ԏa)(1Ԯ[pvfja[*r->tJUTV`^a]2vծIO.9ЬY 8f\[_aOD]-:C>ozĖ6V6(0yb=Vu-錮;STR]eMikck!lb>Fj[ֺVmmnz>{\EswAus\wM6WLWlZU=54;?{l[b'oaǍ7,-w={ŪUkl}Jp|:Q?c4Vښviem˗xV.Zҽ|RpEQŪ]y&+ݿZ0浝k9rÊM7th*n8>5qon„G1e-*h_Y^ZYR^\nYiw;}"vVg5+[ܬGUվ!.~޾ަښ djFwoT՜[)*ݴ#҅KZkXaIb3 mP&M=Zu{s[ylj69;nމ#EU3;o# %KZ>s\cU#cy;@QOwͺْ7otۜR^_UO]aScT)~8iѝRouoLںݐk1/ks6743g-9=\ՂM!V$}dc-=F<W0N`0  ,\JB^>=Г7 KJϑyB.._zD6I:5t]P9e*`3,{P_$=BᩊOgq&;Gg-Vhhh$])@bgx,>*z6͟n Cyn]cͪ.TU8gzҹ{T\:19]W߈oAUQPү~PEZPxgH\N2>tttxEQy*[5WBNxrɘ!x:MGg5 F+ $Et]e{A@J\^RB$.E.o)9'H\.<ʵJa!8"  {Ca=|*f (|9^ xAVeOЏׁL T!l^e FY#de3"RrY9x."cٕE.U=(]d`[sE EMM.e,BZ l5^I䕗W3ǫrI$q{XH_^zuWT&A䠃m R"̌B WV B$bDtWSOvTY^*ams) X5յv= '%Q_UT[O)7I#yEb:sQI!q9\ߩbO=nOeK-[FW5W5eyAyKؼu uvvNKh^RY˲⦅j,mY 46_T,_r9 US 6ùLR |c&^edkE[SՂ.a286.[HLG ⲭ%lm*3=;ތ#;}[HQ֪TܸĞ6wnyu]➂|3Qڱ(-^R⢚Ҳe\bo[ E_IҦe1c4.ݲ6]\KI VR]T~ŪYX_%d3}]ZSTsm׵ZVBxx'aVT;F{Zq.ղc|USJP{-*].πLjU]˴Ł\ҰdG|@12xPc0/o]Xߒ ٺeKZC/{5'H4l5Hah+lYxH a`EGBIaN-T7^si|016xђ{pNZ\}Ȍ1s"@rJfam@tO 0Ȳ̑5TDq\K,{*gQ U-\ĈԸHaBr,-;CrpP}HMbMy{YC#U]\t6O dR3>=V:!#,bf vh(:EFbnD9? {Y;- 4<Ir5E6#@\-W{Z ,@#R'2"IY*!` !S lB6l2JADqF˞3K?U-[W: 4+ha?ωeO22 r(6Blktgݡ<9P)ZP\(dHE). .Z~\_ْAq2 XCR p"/sXqlpphp(;Αաi)nd8BN9HD"33U5H)2jhC^K0:~:Ǥޒ>5tr"sd+o'4/MBmbDCL,*R{I2'6څfL+#EG۬$SiMW[xNRW[$w>Ub&b!Ğ "c|0e >`tj`Fiespb8/_Sc!0EGy<2[y1`9.  5sto@ tnI𙊀;$& _vt-Lӹpi; a+qE"TDEH_ǠVɸyʨfĨQg? h _º6Zzˆ1_ur9VS!K!,.yaN2Z)&'N &^ɝ `,; C08TV^mh@'d _D~ekR)o!gRC=0ca) 3l "rDQI('c` (h hԛF8>D+ĩA܂.GHZ2V Hβ!ʍ_郌ėGB?Ȁ'|`6s@Tj$Fb0\XEǥ=aɨ=2X{N1 UD-C-qOQ,D_4.ΫU>0sDԼc9h$dhsIT7ʏԈ^+[1RgC#jbB8ZQAUxFi0Ö4hL2BŦ 1%ʚAG< :%zO[[[>8 zC8қ(yQ%ϕN_ee޾}{4՜:r@<۶Ԯ]g|6f; ?4ARTcـDBG7Oũ9‰r)ՄDׂ/ !Q=wMgyfOyuק\1xt l+9}&4EE sxB^o>"XpEy$ :t x`0—2-=/|իtU $I+U8X5PHP tӪW >bq!nX`Abd1Gp7:&!;ve`+O%79D3j:H3hgD7 x-;:^{i?+FoC6\Eƛ_WXa_W?vM7esa&s|C^{oMo}_'vID|ꫯڷk=ξ"|8===D˧zlj*?D9*k|K:R9AWHQeQ@JE4B*nTh7yEՁ4L**+XWD28^lrpZK?=0>&RFL~ .$$j 226 E|WF'{qrk?`S~S>NHb$$𫲈j{ >UÇ F-"嗕Qe) !.ܬ8 UYBPX8-JA*l֡gNDa.2~H N Tsq8%1Ӑ3Y2\P6_QQ0#%:72e8Ҡ<I7RBj35qGREX6o{I @ & ˎ|'Vppy(q{fU*i!tq9fCH\c%1dCU%U֎e]G%-KJ "aFx4uR}(EiiһAKQj]gK`N\XXO&+D48b7|H=< H}-*%0PWQAp1mN๲uY^` nFZ/7PPDщD<ĄAi1$.pt@C` τ~[1BQKq<,ŧ䝎Ddmfz8C=?xk֎hiobѵ'n~팧Oe6&r'kb3]!K_AXO<^og;= 8>Y0Q{'K˿_HmB?@"|~EyjFU;=R]|$BٹE#zIXrO;6[(UT22j%R)7&\nyݔIlǶ):aо4aƥ> _pӈOC_JWDm䕨M!h#jLDW: Ye`*孌T8;" JPDOoRDnhIx%op 8'rO6O3^)/<\"x%iV[`9HRsYHZ3MaΟ4sTLM05KoԅeS[]35^ -\aƂijj̹3?ڪ .6|7vTdr!Wak "  XD^QOOW)Ȟ$- L^g #{X SDK*MsmF3c޴/UZ 8 Z[+jWuu|/-+AO9:K*0o_sRFI|VU]7@31Y6!@ҏg]ܾL 0R$f W *y.S?/no ]]TkmkR㮎qp54WRh" JOMsGڤtg|Q; z! 5 tZ 'D 5/A`2 dfE,%%c&jaX%Bnqʍn1ú"X3 N<9bEVKĂI>Uh@җwףmF `۪n 2Z( wL1^D;,A :RXX؂jBȜL N"I!Lkv.j\!-|_ <6%I^E~p RJ{[j*)ly:yKR@h#0E<Nz jeNTDU5'cՙi%FX<_{I`09sٷgvʇ'f>]Gm/Xкdђ~7zɚBl~~ڹnGr~wWM\Og,$FeAs)[©,{۶mZ*iEtttYկwqOQ mn^@$>}'V_r1v|GI4C JϥRyHVgG';{.ZhhKε=y;BWRxbrBC~聟_x];o#n$g{68Kw{]ttŲp`UVV=xTg4,NG+N .% ,1'*aX$0YyGϱ{tj%i3=W7c@g2BάS1LٔG'zȦeO`F皑&bh@Tcf;^b7ia)b0GUoѩg Te yXH,D*sDBO|VJn#ts}xʚL:$ %EPvv3xqI?udɲ ojiYZ]Sﵴ4cJKDNi2I!͛_{c#LTv83#UIEXzިzfy! ; 8ux֧ÙL*]xpSQs9N"nޘ;UYMwBrVl8Vf5i ڰw°Wά[Ǐb?>{C]r&`i\I6Fg:ذ.ڛ5@ƁlUis (f7> 3\ v%!sK.05Y2W=б KAQ ^*{1 A);"m`ҩY*m|jj-b8œS+/ qXqtYiFgGgISÖinjxŨS&8g2ZŎ-fUq6[ ϥԡS ú^JQ$R Xfi) l&S\tclna2|fy.N\"b)kay])C5C/.fQDc`tȎ(ᐺ1g2E\)>0ia)DF2s ՗rAEܰ0PBk&4r?QLwZMLHrBC-Ex$Slު7mLReuCG&:$UΝLs5= a~ c簮y+X֚8X}'++oEX"rٚz93Q*fg~Ti 4rsͪ}X$wGmZ7GUҫ͍ H3ur۪X]6 )\>~ 'ɥqxTDAErMgn+2h/2"#3Z2٤24Ak!VR}Ld]ќ)gbc!nロЦ`gȉ'f9d hgVwK''pǾwt8~/=˯<{=vjA̯PZ+{uwCKÚ+Ru5o~qrtb3b͓M G&ߔ6Qr$iYChfF%Zz(ҊJV"gnߌ$#APGM> #+s=C7 ̇$'9k9hM ^z " !x(fuudx"O {#ݮ]7dՁV@W.x!szTw'!Pq>d"2Q/].`pf<`8K~O~iU%bS7v`[K_rʊ!( ϑBs.you"4t0DGh_7 -j~]l =Z]7Q>̷d~K?|@V ".&7]|h@؆[hp|nʢYG]ufm;9md{e5C#W_}SC ^}C'NsWD[xÓC}/^{k ?ÌC}⻺o]醛Q2c dnᇿEt]QuȻn]dɁKW=~nyNvE+Ώ;zXuyEቱǎ7/XԲyw4Uw-SOs{4vj];3==fK:+9:<2}hlo.z]WspoS[3CaljXӝmݍM3J<:℣ ttltӚ+/=G+V55dp~'}SΞ9wnn0q }'/X\7xh.574KH'OkMҞEM-[LͶjI}C=Cͬ]mG;?1%^^F%]OTU-gŢeLmfcnpt9Guas$a;{l{뢦N?ZOa׌iDG+D_:NN2@][˦=㐧A)/ 'ȏ1STpFz WO[)75Ij$[Ѕ4 E:%$QS.^Y߈@51Xz,xfJ0H'ke)ό )}TW2HG/K8s$H)JLrЧOA&OcżS5oQݻu5u <⒚*Zʺxln}rp`977`5fbrTVWreUVTo LH@$jES= :'E370x`ʥshzhhz<.2?ef~D]c+[LJs۶md(XtYuT?'dx+.E+ʺ ͷo('B` ®KJaiiC.=4k)kêNH>_W\IN )ߏq'J1Bꟺ|Z9Q4&^gL9V "T B6BБLyȂQTwxS8k-iaM-=<7(?{E}Hq}܎n;zhNǏ~poutv7lU^z_oTT%gO~>[[V?6lOqiUIK{SemyLT׾{[~; IڏcΊڊ籯GyƆ#onik=?z77>36nنǞawW/R=hʺKs#?W.(j]q7X48{gk]Z^_~fw O/\VW԰ qIGbqQْeE/}Ҋ"gx^|㥝wl߽[nyׇ#E[Ͽhcǎoe-Y6wYemz۳7^p}C?Ծ|qMy+t+ǗLMLMƞQ?+.,\:qΥKU=pW߶ݼww:ӱ=oR LsgjŕzMؚvm\i #[⫻˚k ~7m*E_ұq׿+M˛\d '_ʫ}/~O +7mr&". RǫHA5jbI~㰅XP(.WV#7 7څwvc}1 # TXIL[wYTzAC A%X)9n'q4$s,s)9EASblR$?Aʘ3$H ~?/e+g/͞UBDzGH@]ɴZԶ@1մ/$B箻淾;n9]<ԓO.ll8M{*̝h]p߾,rvs[Bg<& ROd}W5˄&8ggg]}e;0dLT FA,:FvX{#|0Ձsǎi4Y\8d>-^#+{)B[z hcxj0KG+]u甮WgyxgeTϙ"9@e'Ɖ1.74H2LBe7!F,VNs 8F)%ٳc3ftj=SH|8kWuģ$" RPyH@EgҢH鲮έ}{G܏ϣ^Bͷ`).lZh7,hlq"pku$k֭9޻YvՂ ]\cg Scx eu5B hJDninнٛo W1?ݶs}V صqpf_-M-u'7xjsg7o֖^WN>ѾkIW[{`]uuqqspâhz+}}wV.Z,F_|6fݚkuuw>t~s55:ϩNN&ީmgUTW{hu] Tbq֕6_VOĎ LLM,qPc㙾^Kk[: |=[-:s`0rNp_Y}bKcN۝ WU6vtv]~ iS'yy>qӖxhGݕx,sC}Z_yuv̙Vw$KڑO8n\%=zn%193{}.o^xwM^ݑN^yap%GO[>>XPCօ-;nj'{`LA b_/)a ى.n/E/#S*̿Nh~ )yyȀA,99O=޶1վ'. tvtyNV}{B$B" ͒@IyJҴpg{O2Ir3gن˥p{A݇KCH*k*?sgXܾswy~nq$ kN={qk[[G~uϞw{l"Dbʊ6Yc%Q{&wKNU$WRfvt~A8 ꂜgsF.(wc;;;ۡR<| YKL:)E:ˢ!Ch{O.$#0reRXf&R/TaDLP!;WAuRDF ōYJ&yKK*s+6VF$֮jvf s.jYOx f:wd``~Px2BO$A%_ZŸyd:BXTl"_͖N=xCM e%U2z.ZuԦsOӚ9z^qK-D  p:Q|ae¢v7;(8ll|zlw' UWg[W-oĹѵkM_>qlьбSO.[kSGN/Ys*~o5s;ydDz^{ّڶ/ԑz:WvݺSN`Ꮄ [kO ,m^230S6]vɢ97R?Ǟx ׬Xsށu3ִ^r}uQ%1Nś7\짼yne:u$F̽g\qc{{`¬.w\.y<:-tԑEH E( }"HH%{3}wmYD{ƛzYYYY>_VU=z 3ru0Zݐ}nƪ6Veyٔ-o֩1/r[ZC3ݾv+э#z 16`++pR3?\\NL/)+M+oj^,.-)/8'S('p2՞Ί 1fegOM/r**)yqLʚe2i,&4GJe>سoޝ|풜m /_4lH  *V9pmwoݳ0۹sX)=y]mxt@ް;7=7*h' Ǥ$7:諗/Lϯ-{˳Q{'}[vW;z67-,=wcVG[Hoxnh!. œGLi==_b1#T1%O[K?d~r`ү߼}۷`LmT=6jL*n2:!yAL8,"E q⩎Ij;l[FA" l*O&h"#g6{Jc5^STM1Ӏi%F*ע+N< ʒqe<[,6*@%_@(1 y7 yYQQT%ILCR^Ѡ\6EL1YXy:WAlZ*j\Sj|;b`ٹ &L֙33QR$A. ^ ل8"$RZ:9 |ritqĔa'e,|Pą7A dΫ爥\ Yc 8@HâHQ+[P#f^̍ }ᐼ {*>*%)[l̷޹lD`5لl§$$4J)a|rb@$Uϭ7hB@@-_%J"NZ.*BAbPz?t|K3ѻ9H8ui((82~hRqZ24;+I=49\T^]q梊⏽L~<ת*3Hfh{ 3|3mЙtČ`J]FgFdp?Bzנ=t:nBC*Zl70+3A" v-an w;UjaO <3c}AP$vi8$38 ٵbcOd5̌ѻuJniKr "46D@6ۓ ep+|"6?'Ⱦ{"'@krE#K# *Rt!)ը ~h&2O)s=dY%b"S+5s"%Q LcD ?ͽ"n!лH zbʼnhov쥉%hZ$~qG~$}L1}) .ް,*eT:<@ǎp}]VfAAeP=liO7TTUTiGsFx ?~ΉT9+ Gbk|_09_ulm>f^`< E!'A3_b|)"rʘ$3hf=b*/Cpܜկ~_:'>, D@G?L]Ȉp<|Ay>9EA&#"5XL9B WI$N0Adot6vb$Xm(sd Lyr 956I{hh.lvuFYZXXD:',BAṈSwFSఁpLuᕸ trPM#MyeL /ɌD=t) DNC#5 }Ba()$E"$lIX~ I@t44  ؼ21:Nь̳jZJZJ^XśqkRrwii>!,^B)@f\Q~a lSde!-FzHZd=:=4S%LlZTa^g4 Qt@( A"*`-8 k=d4ʟMgXPLȸ-~ڍ$P-E@X2kp?X039r; HD@2IG@dX$5icUhq)5՜X(P$;>M+k.G٠zQ/,܎{g^lvXwM'y[6oN?Iwva~v8-oWkD"#n"t`=ѓںgKKt\YUyeiqkg@w۾lxӦMRUv}JAf`c ('8tI3 &E1N<|V d"]Ctiq>a%\p[}% W^!ڇǏlG^AOj ؆OOx)X # @{(7~jf,d )Ct$)?O"h&Tz(/:r$ ]ܐ% %pc Pűhx184-k}ί)Tb$ K8</S&d%dOfGu"/PSXFvhEjDzHYfYfш"XCRI$*>yqd͖Y|4_BaH$]Dϧ@#z(z#)JVٜ:d-Wpq( 6EcA ".O5˳Z;%>irqxQT8 ~15lSA([>zv Am~(TYi9HZ95Q ޴kJqVޔml41J{(,).U|t)~!]{eHA\;5=z>4 fJ h?Z+3P<@IDAT,Yppʤ+I@BbF|-lBP?vT}HBGJ9 R Oͩǯ7Y$'_nv ^[eT|'|!w_x상Z+yN_X OLLNoڻ{O;M [$CDCK\v)-+5#0wΛ}_~Oש‚߾~պ.-mg G}rCW @ۀ>(L.)G X|֠d^#񠎑WGƯŅ&gj2;p֭FhWut6D0l٥e?Uֹ-gM >\xy(c/&F%L3G=wwnqf1':rIBN1Y*&.-6$"Ch@Sdq$maM4kRe). 1# _,Rd%-:}x?f3ٳgʹ ս'hjI{P-:sj׮f))oiiwf<~=o;[SUv$ض`G[ JfU`Ϋa990ЏiV$ǧS۶OzK+Z[ob᝱ $ Gˋfrs Y*)?-5-;;ܷ{oGo32LO.__fRg^wn#ߑdg2*炋2"[ҳŌl3@M7o}pҫsW{i(VǼ#({_+.#a~~!>};¢{k}ƮPpk\zˎ0=#cAN{/$H bxn'>Rnr6pҪoݖD,M̍ mIL5Vou%6!Cn.u$A%vICuPStuDw_|IF cD11}E!4J]}(qS\ewǀx/,z;ń Ia y`c3&of# Fqx#/@xʍx4"IGS:R.0I Z NX` «2A&q(v 2XeFŒ@$-G@8  Sd\8yţxx A"S< ym/sA'fedRbӉĒ9CiBxĄbI: BX㐮t1JYq'AV I'J~44i OeOYȪG#fMDEV `q hdT!.AL6#)F|AiQVʀDE H8< LxUӂ *6W4e0-[ G<5HWP Ȗ Šb*|@~A:1; Q B`|У|=LC"JYp3|ff'k"Yd;|65O TԀZDVF=I7,wFG_gӲn\Y`KB )9=3;11~ڕֻm_DgdՖlf:UNs־V_8_Y\=533US]B̌ʚʻl„iqf[%ŜLlm]K+f=/\)ʁΏwV_ sjkߺf{Kmd={938>88֏&s*}=فrkav639mvr=RE}}y9h, {s Q PVdP޼#I:((YE~fRHgO.ʼJ@+Y66զ{2;z=Ngcm\x 3.-3lXUQ548 ,L &sYoo/˯l]_JUUlARURV\r_9UURkȮ/tgME <|rz2WdWwz`-Ρ򴤴n2T7ZoRMۚ'Ƹgd4=-mse2ZՎ6|®+߃=熠y!׈(QvҡXCTof HusgM#,>Y{Dn6۰tK"RDR|Ȣ'VVB.9|@Wc̴DGAݞWb QHa(Y QjЁ Tdܣc ~iT 0Iײz(}eR^5R| xL6%?I ?Jш8YB& 4HyP& ~gH{(Kqy–%~;ꋍEr+-  -IͅfG1KYZ"f`X*2$gn`7no -   ӞQ"zQxE{k|kqh /*(=pU:>|RmlߐRb;@ΰɩU>iF>&kCRdvlbe,N4"䘘q6<9ve\W''8~p9&c7П!X$ S*LDh줖f_ ` >). mQ'?hi[_xWzESytZ 5c "G%`dl~vIIK4dF$yEGK`lBg |*yP$G> 9ɈQd$ hVM`2fa\FҡH^ȭhkل_8ZT8! M5Te+х*,˲,R)"qS,-< K%!tYɝ%:ʆ|SAߘƐʀ)YM ; =mb%9JcBgdLBcX᭭}#*rk cSG ɀdAD J*'[ʴx8~E+*"3lѥ($l-81d/pCO|<-jbiDRPPcajr W:#J|9iu@ )OZ_<2)M$Y@[0S⒣Y?>A8Ԕ HB3h D4JDM,NuQ#O$r0|IR')ä=ԁe [>)TzT ,@t& dA򁔒'E/hf-"Xlj`O= "$TJ,Y #Z33"=3KhÉO/#O^)pk4I^ U9&$㕿V!!@+Aa҈ Jt:4Q$9MKCc@ G2C)N.d0 }yC~T,t"QIh7hKR.k\8<4] lHWl<ʯ$hQ[m&6u  A+ n-:8T?x4|FD`Д̅+lH̢#j~gI>*xS=@6ry%I pqұc PNڣ7:~];w2cSSZ2Ie@cGR`=ߝ!}K2U }5ӑeD?3( oG*j`Tj}6qDtQ`ERhq2s%`2K1ĭaPmWO-ٺ8Kn{v8l.1#pC}ţ/%ې~Mƺ6'ե$iD.OsB+Ie\IA1@0r} 0raQqcpCD?zGF>m"BchyiV*Pa1K+}'i1BB*q(R!"b?οw`]BK _E"XH weeRt0ltWXC`ig7'+Gڒ0- N^:eҚYTfng\YR ej`@9 c9D VlR=Dfwusv~jI3'Ks=Ht72hnG$(F HyNuئ@R== /="D]BA?fcuFic^{iF!  aid+PC橧z{{t>4!ȩ8PpL`rYCASPj__R'%xU&7Qd+F(F|+NHՈSu@ERڽ2>Mp~_X{&O1 5'' VH Ay 732{9 ,_Cxm.xa%bĀ&kx D#~aWa@(a KA~Б a-t$@ -B-RG$ɇ:UQfD 2y$62o2}K'/:u\hPṱgNp#`&,rY򺧎>8^NQnӻ#9'Z7ܽկ+]_YfHWR;f&e-ҹpkEqr>O=H[tq3wG yjP!Z^ >p$۝%{@)[+_HK~9|loNHxFmxO|A.thAN1ۛ?g<1IfLK!HFG90p,)hB/%OZj7o$`^ֶufYY۷tZgttiWb U;v ⇎CgN8oSN裏 | r[M,<&h,נ)j(c@o}Y<`QHYPtXDF^J@<[ 0(%jG]4E>K"]d%,#fe-̵ KL[ 1sVvˏW+5} MSxf*z(DK3 10bƂz,O,HR3T yGO+AnDӵRUȆElA#H!N,%b!~͔TZ%f?C%IhXE`,ڀ4h_` +q4l٘i'^+q hWŴZ.vd@@BJKN:'5mLȏ" ӻ;3ne X~>jqj65UVUWf L - StNc(lrq29c 5IJr~ +g.93u CY9Iٮ4>xHrvZZr畗^ۼ5h(!"$ՕnZ8w# ,W~'/V3YZ/NfαqWmO>ZxOЊ*[B $%57l̳b5 ~I{߻oѮlx6LOHI9mu-#3;b%Q 뭗ܙR6:7'_׸}+9/}t֫=Pa]I̳G` 21alirl~ҙ^,ѾJ=fqgw-;X+ ƴܵ}kVQLj9p@r"<|OH kch1fjL"`1JE=T7xxE:g 5(#PH>yF#(x|95 yF& AC5X?xUr~Gx5b4%CJ>r,5534 nhCP rhiJ66 3cnQ,,@U|| D\hk&@{^uřr9|!dN2U'ڼcy}LrbnWoބv{%;WN<G؜yɃe54tx8'C~B%D bvnݸ9v XY ,^p93'sNHAZ$KW*Vk 75 Б9ӷKƤW\Xջkpcqɞ4K A8*'Bp`=ɭҗ]LrAnv$m69> DWGoefv uN{onm\xP^Kw}mw 2 ff.]<* W>k^Rjʫ[id>gSmeݾ;uu.\X1 xܠwp,{ivYRUab%Ob2ajjtb)8Voчf](;旸,:Z=05ȴ%Ⱦ1FܛҰD6,qG}Vc`^Ѕ9~EAܮюᚪޑJ㨮cYlK.\_op`ףg=--A ۺ;YTcX&}AN>WU Ay2tCUҳDBӎǥg;Svm⧗JY0*=ŕW8w7U-{gܕ+RUVP0TgN__`LWd$'v`=wPQ#a8D7 *NjA7rbiUVVٳHf/EgKK p pPuq AߑZO~BeGO'oB iW%%:ݞ 7ux RR1.Nbc+Tƥ XD*/̥@ʊR=isg6W$R9(\~3n-ڙ@Mym=9ŝ^^,Ď{lqgsQcU g吮h6jF*Y ¬,ІVGYw"S"WqNIq^IuIu=D! ys+)(e-ML4!0͈ptȠVJRIe}D(C6 &<҇{+!6E2>6Vme3+9{7Tּƛ;¶ݶ*ܜ|z 0aA?yP`Fi .A 7,Bs} t?WذHAJR$vpNh aM!1C<(}Yp 5.oF( {:;PB jkƝfbW[^09@SSd4@.LqA B2&!"IBN3Y 3DiS;` vs9.5 %튺3|F^'.H!xOlBIH2*P_όa=(It3Ny`T ;%(P9R|oѲHFh]DyM" %b_cYoJ^('Z 1K4XN4.hGY/g#i s(>QO I.@ۆ@uF1dѡ؊o>j\OMFs w*tIvgOLwVzi9ڄ cfu\J'XC.!Q*87" ~t%d(' b@> Y, ̞5e-.ۅRrEx=U*YG;G1LBRbBJI+M'಻j+j!JO=3M*4taNdez8^' LÑ, yyEvv61d mt[WM [0J'Q8aSpk$"?a*P , ᓪ9&WJX''xjǬ; /@gY)r#ˆzI)` :w^1ɣ\DSSGZaו(ɧ$wQynٚLMdudId95͎\JdFP®)0Ur6$ 3Sk+.q_}ka*0°pSP}0pvz6 b̙3H?EФAL}.{. tTk@YDƪSȳΈtŖvc}}}3"<,BC"9_}U@ C344{h+?Hc0Oʏف p"?Q5lD% R4CJ9h"?5$i $~Ġ2^Qx$΅~ʘ CEB5O }k)` AbAҤ@2Hd<ފJd19k\Ă'Vm\h3 G< mEn^MbL κ߶?31=!\0cA2›,FP?nWÆ?2 HMQH&}rU'_*.@@+kݽ}q,a̖$fŚCb 5㐘 ŨcM?aL^lDAX:r2;` CRh" a`ڊ֠51`ye"cQfّf}`Ĉb'!οyml~jZ$5b D8PJHccy} S\C5lZq2 VFBac`ߠ7uRq.L:8ULL#'}I;N\V]Qyƍ?_[л (rqvN6_A؆0k1 KrO<~\A|K \;<00REx GVw$$8D()D,kg " xahP_!(/nظ +**бirD 2Q )jְ16hrWdb5Td"Nr"L%pvY縛tq$ib "*)A`{c!2hPP;1ǯ Vgsf;V9o#\::7Z T[E\F4_`hC½=YN]N8\ gpy5nmza6хъUFoz~[z0:?;k\[/A*."*4810KVsKs7H64RGklfڍ+E%/4&4XHWCm\TcS2YٙX DžF]hk|\`=XX/Dwz+zl3╋Hr__Pkf(8_.}imL$$"6b0[Wٜl [,2o5Bht^vy) '.3ج67DcBB& %R~^3מ}%BR塸cADbXBڕ-t<d1gA 9~ic9d!Wmk֫++a-+U*!B!C^rअj~H!鳟,S Չ@3㊙K_PӥV:k^2с+ ~x`" M@y V0a J\@Ba 8~_@+I@ @xϯiZg' oi)-ad j>&Z,YN}ew|x!%&e"OF 8߀bEVX8lCgk+dJ!ʁ/8Jz{ { id3hƯJL +I* %#A (tbZe$N 'oS#QЯȱQ@,pfJx,WfXᔨIK Dǧ]/~]aT!?垀H͸dJo3@žufQ`KfqJPT8OW?SRh*DHP(G"12JQRJ~J((UvF`0%93?K'Ԏ,8};B9sf>>_]|iF~fpO?++lqo_B:p@w`{C}KG9\[jԶb^g㊛ݭA_ZF=<~ W.^fOҳ)(`X~4ythtvznjj湧۔U.WJsm.]TX^]~gG?+'eKfz^Cu;'ޞNUlwVםږp`;jϜraR hF$+HlTN@BL,K)4BX@MyS>yTf+=NH [A܀+EDBi)Ji08JDI} ,rEԉJ髸cEA #8Ը *v a9=\˴&]Q qiQ:/H$_hI:B`C/6 &"Ǧr/A^aZps)xx8eϒTAKok@NJHH@l9rzbCEdܤX5'XX ݽwWAIh[w3YT^.g={c-G?3Ȳ&ZZ53hB`>іq幙ΡUuutVJclttۡF!&3'y솋egݾށ-p )zܞ#\|l=NC8F*o׍ u2=y"UY#zȧVbz ȍ8$d<|B]!+2Jhgqk/Y 71330(Q%DdPV9 r 2.ljbJ(bOXxŏܣhȫ,OO(XI(QTfiE$-+ lEPCE B,8XXA{@c1L njJ۬31Pڋ_FDE$*MKJq kĔ6`#Ҩ`$!ɩx0;9Dl &RS$ud8JY=PY6#4!Ŵ5 ,I݋ ) Pgб~"TRMMh=-p4r )%*#'EB{D"| piGY*gWmI9dy4IpgP[X5") ɰ(8t#ydmFT &`Y)Zo( }УQ.!Yh:;;467tr5ag{GSK~[kǞ}SڒJfOr[RfmoR{7q-ž'Ogqsoܹkpp~A͎[6qkؙ cc;޽& }dj.[ϡ0َcѻ wVQvټ&E6>3~⪜p#2z~t0(-.meyGg6ݽf_sm)f3s \;?y7DXGQ418r&w>s4^tc]-UZڷir18=PW eu+#[3+wҒJ8w\IiI\(>1?׍.UW8K`Şxu b/#Ǔ n;{\+3 ͍͝:uL2v 'VkisװNwwn\b(ȾC)ʥ''&;:;sr{F ځ=׵l{P"^Byk|tmѻ|w>.7;41+`x_p$pr &G:5P53_% >);S,O_30NNO޺} Yjv<%Pk5uxtat o0$jѡGQa+7>}%[ 8fug< <H1$/xl`H^lْ5ڥ3}}OH2 jݩ[ԩS:U 7iSꝑCp "`8BY@ yp+}rQ 5w[pu[}|E[-7˝ȭ2thآ֔O:s.ج"{ K)NFfd,1phey"|.PPYܴܕ"}nCɣVxzzJ 6l4ibent,ze3J$3X2Z (\tŃ̢$t ` !hJi xH (?-t,JW&MJ,"vQ(eEGJf`4X&PCoȆ3Su57Ւlc}.Ԋ}zKv3O@n?{H8vVdrxf&$:xbf1 C"N;U"0PLn`/'Oa>btHy`n'.C;'@ׁIP921 ~`fI6DqG"e{r:f*|loMFiK2"[Lq fs!R'@r>ם"dvA_#jp~ 93ϲٛ!!Ρy\W}wK'&~=>5Ƀ$wD8ƞl#'F`ŶJ&h'xdE,lYӑ7kѹL xc4 0g?H22Q6Dxl$&+!'[}v|n1sG KNDɥPI1a9@9Sɩ\~/{ӛX,9ݾG'Z 8],T^HrS )|(:3}ĩ664?vDIIi_wҥ-.c?sLXMjt6b w ܔ #d"l J@ y): _5[/@A:ɷKaa!]Xp\J6Ă-vгY8Ƞ״&:hRs4FJc-\֣%iC E8 ~K$C2!eX_S"⑮hѪ.e8]"7?"čM<h?LJ'"Tw/a =w^sQ%)rz&_\1 (vq'09M0CE̓RLB2% _ҥI\(u!`dy҄ J@2<.b^rR),!#j:) MX#\1މ%M/餫?SAC22I<dRᩜ[J£2XHpŠO|;w\/CAz9bS@6+bLfرl;sªߙ;EbG H,TW-fd=-+-HƓ9l)@?>{0:lg7iЙbC䈹^F<9aJB(x[  .Xvc2%t7smȃ'eay2"6^F RڠXf6 8HVw8O d$[|0{ٺ@4 oH @X{ MF u)8' \csH,z|;lźrb?2t'|d\v)) 8 GYnޫ^ˎV6gȟ{͎kBOА25&"ؒ?l%EI#rs tgdldl(O M !BNGHǕ~ǃE-*%IZ Sz^~%#C7..->?]UZLjȀ \Sfooocj y睬!p 7pJ>!lX#ؕG@aqzPP>#D$PQGG3 > T,<*D9n^".F }PI4\A/օ X#3(B^Bf2.-KZ+κg5)+mXekh4?VafaY״ P/ G(2'O.C. <3hLcAT*.n+] =#z7X]lQ4̅\n-)N[cшPxPuKk%WxP~RZ& O_zo5i|t/"~Wi>U"ƁؙN3'QձQIdTNj ̥Lj>lM_e رRɔ좳oK4 |e.ɉ|ǐ@C+I"Xbw@Sevqu @hz|pf`N'p߈mobi &.9}'pX"ydjQzRBD{гG=?D/ Kp<4:e#eL:GD' ҁ! b>FE]AI1 s4J:\vhҍ^ t hg0perJ+4AO'ˎ;-z#C׋E\l9~NK&i -EZЦOPĒf&R|B <$@ދ'dD TclYy+WU*]Q"n8G~8~Nfleg 1 6;.[K? ^#p6#ueD䲤/gZuYin2#Nѱ`o;FrK%os^:>羯n4ۻwfPOhgo-[nOj$ǰ8o=#lU/~ ׿v6m'? =n?dey xfڵ U__9{JDwmD$xEFd{ņwqLJ>!R|Eٳ-I"]9.h3\R|ԞƖ%DB jwZ4J*MA"&.ByNY 2,E&#En_e)LhՅG\—FH g_YE^piia32%iBG)-:L&2i rgJ[l\ܬe[+Rwƕp&y8 +|/P3MʌU7dI%,DC)Q@r^ !0fVFbtFNLKT}%VNAB+͐PC@䤌;RZ' 1J/LK5bXC?<ۄ|ݟHI5\f7|2uz(x2BTl\8v3Cs9)زK'6Ad#_aYK(LБٰpFh"3%$,QOHEf] cO|* 2$VRY#NC\|2G$TL 06dR/fLXLęHTXR<0pК͖`ۣ/ӼbIO$jfE$获cɢj9 P{'CYj leI}Q B6Y tB0` D#;Ty19M`x$o4y!),“eJKB`@k%87`) 8Ƙ˲eL#Va8OKgL4[ODjJ[tZcU}R$J+@ t4!d˴n2?70^Yn!y+,F`2y37::3>1\U5) ׏S[w̸Zei3 ׷P@l̀8&n z J~ӟr4 Sqet%hΝ;ǎrlY*H@0>LcF=N{zz1?ͦ`;݌/tmѐ>я-9x  td" ~_0iH` ?Oګ#lAjfB (J1%A Pn}D4K}lG_FZ$J2XO8?gA#Yc=Z[+_,k@r g: $ȕ[1.hc"|#h9,D!yoOjIܚR!-A\^O]lzWHc&׈WZia2Mi2"ʤG$NDe7#@"`N?Őϣ#\ Of(QZ':7!|!lE,bfRe_$[^I)ݧ t m|Z]9%G߀P&""JkpC_a7L \a'1]Mk%,lV,Ұd/jT$3|R&p2"Iw-Ԕd#,1J?f^R@(1W8O1H:0ޙIa~ ^C\=KY98S]!eFh3cꖹئ,Gi:?ޱa۹#CW=3(?}҆fVTUfcc7v %|[@Ѽ`q Qِ KƋ?tHw!LpPTCԉEZ>ņA)~,x<5WУ{ߏMbxMVj^DBӌy\GrCKWR2rK℉;]p܊-ՕJ殥w8N/K7<2oa$ mMʳp_o̹L!UHȩ2#Hw҂0Pja![ğ Mf&8T^8S?e 09'|4^!*as׀2<<3s9P$!xzno=ve1ÞdJHS%'e2gxƀit0:a 7#݂dVi/ -+c k^SRjpK'G3xdI{. 1K $`A%Pm̑`2Q•~%z l]SsW'h SNER l#d"Lg92u; FıwO#)gXK *NS,(ȁ:FkvƊ<& zR` J, ћ)4O tZb4ütpb1Ĕ( r.،D \MP{ C{dHj)SĢg&TF>*)h0w>,\ LAʁ<4yג*CJ,C)1@r2lnbēD)Ƃ6( )^*`WMPTJ(e5G 5WJDͧA$;2T0S&X㡐Dl'nJWQ^@F"x8L:@36p)bYhЛdser@4M*iל~ЛGf8s|2`(#:|k_SXo//~i/2~\B!Z4L>ÆU:zZF` z/Nghxގ >&?a@b!{߿)Ȼ|'9V_gid+Tz^ЇAl 않@:Wg?#]C&CSi؇a}O|hd*b񒷗z.8 #)[ʑ+eLęAN\ކjCfcSa + '_U)QTTE1hW8x|Cc75 A·X|IZ ղ/ >Y ; C3w3 \ ot-^KiAT8Ň[^_YZPWwˑbL4 XI8F2v ,$] F$a.bVsKrɣuODJk>Z ##"8@"N$AB&#"'!YE$2$ot#|就xA^bSG#(cj2\RjBt|bIL3F)h/.aDm$\E^+>LqИPMR]E$(;gfg=>ًm>oXHţ3lc(%v2a'EZ(XSEY$ JRZU >@ ڝ*K~IF ݁MĖٵ8)$ĊŶBē<^7$c]SxLXsQL+q3GZU&I@Ҡ7j aÀKLE($w!]6H 9 f*V’oL QΙNte%AWIdbUc-btWCCǎ0x0R x4|kqIH-oHݿE,2K.8m^rTr *؆ k.G"R&% > 7,  `XTR90x+(++).-.*_]vll=}_cS#Sx3k̩ԠI6aǿO@KܙbC*V(i |ӂBCn d- ,"Fi!6z&8 A׮z'ڰ ٳPsj! (p۷pgQ&(8IF!*;FbDYq^$9J/蓢(I:742Y] Tv];W-_6`ecɗ §2aJ'FF}Ӹi`FEo.TIp% g Ʉ$e~!k!dE 0[x|̙TGO#2њoj:eCJ]M2!G :4j;pcCƣ̹ktWzaW<njIE82sV&K%2,ݘU㾸gΞ0Wyjr:Idl)k,E`B)J SkLFN8=Oa Xx3eؐҒc!Ai.D$1Pqȣ 7<{E^n Fӣ?ʂ)vab/2/_T-[VȲeK\ Y;DkRgTcQBC&?% 4CVO$`a`MPyI NÞ gR* xQFW|4R;E QYH*FΔ{؄cDa M-2YSD͢erۢG+R*q_TVfY$K׺•E3i`cW gArQ7.(/Xknfv5UkGteEeŀzrn`Z4g֬g3|ss0r-fcy9!@FtO#;YA6I $E"àcVD0'':0u'Y'W<* 3O'- $ B!>ZdDB<跜w"QBֵ X.Uи`bqIvrc$ATBsI{KLΣL ߬H*W"/s6cP˂xXLbXk1p7q e >X #~zSwv4RCHb@!@c,%J?TJrNPʄpX P@"?!07I% X)g9% +t_f01s^Q{Vk {JM>JcpP5:9 O_&pY lp|3?#<#0KF &#Nmf.CyE5+^>X{ɧe,0;%rsId'Q})'!QP([BG`SnżQF/i!GRӍAG CXhhxAQ7hFG5hLtl!)hD<2-ñ͐2,nV*'w@aZhma \$2.ȬO&S%^$|RTPD@VPe -&49IU-bX'7)6TP r[>`յ@) eD+bEFuui )%HbBQWMvBdEBIdL!.SSLSI$~@+ D?@,%|Km!UF1=T$>&.DlF RjO0%A6*'@>Nie'Cd#`] `-8>JzC,A&A:)"J[ JpWtt(>4\=:;>V%~=S- e3AƔLb乓D^UYuk6Dd96,Aڶqos |N gx`(7˶C(SZQ<88TYV=<83qyjOV/ˀ8%vPmG+J+1P"3l|! Y EKcI@\T<M)-mdOmL\nA-4hBNs]m99܉ىɊޖ s 0LNBޤĎ%bttUVJ:d:m%(lъJ:; zrUKSU`tس5#PSí\YV0r !Qߴ;"TGIʁL tzܑ]WUjjnbwhrL!!0U LV7$ɭ( ^EA]UdL!}Qj]ָ,( i5KfRCһq7cfbl m!O(@KfRVTad4JIzjaʗd3~TS#$i&SG0Ҥ# 0T^i_8nDOOsSd⭾ҀH#9 A*)FIU^#şG]3͊N@+}+q] 7jRC.`t2œDƉgX:]LEI[ۇGhg&@WLC (kx``^:bfcDgȢ^u- Hϳ& Mܷr~@͡e؋A*CÊH&2R때 %-`I(蕆VW .6 Q]0CxadyGi93;)J}]XsOF]4>ɯ|+7ٙǎCÇat&A0YO._tnnDljH89 FgX+$t'(ƩZh2 X[Y' >=к zW-__jUh/ 䆛nh3tG;v$mٴ@zHYriw_oztwnhlhe˵e)^ /,*ZnmwosLt`۵wy%\f5Lm9ٺz#ǟҿ#sg;cKhQi'WZMF(]~xtg8{u+s~^wu㪶s?{vmY=:;rlkzhҵೞǏs׮Zz(F̹9Mk6uw,oX ={cNO_YdjګJ Jڢ.G]q֣M7ecQkye芧haH5*\|Us5)iePe T6#27,w!O 7_ tԤ(ZŸˢ +qEpG [AcwyܡQJ}ćKeWV\%>A,2@nX^FǕb4.GrY΅6l109+[`D -~jfjGD$()e33hQgf⑸* `9S!- Z5xEslJVUQ9<8DGɗg544)W%Ř.H>9C&e^ԓlܴq]UeN,#c,ARE_Fi^E$j4ʀ9 ZDs,JkNsauKDx0dxOX%2G %( ~':B545RP tj*JJ*Yҧ~òv&qv71qDu۝eN21į|IS}9Eɨ@ȮvmAo߰6W0-nMk7?y%[wXz|Bd9T8}ö,ʰCe/ϝ!xI^}E I IuA ;]QQelN6 65-N(- Ѧ/]:5;gf֖wv琳*%"bfK>CWsxGxs`ݱmkc]Ǣ̅gnZWR?n_ٲ}*(/_Zvg?鶍6Txcfjh\wk[V:1<1g{MU3Yr{(`,}z.9s.4oXLƍNwnMCH̓32I`NAA0HLJϬh?Jm~o?R1G9a-̋%}+zBdp#?`H*XtȂSfhIdv;3ETO~sX'!;bB)6Jy6&F %&\Jfghe9@Mf&ȝl_!?m.797OhjƈK%8p|zl&2ֺHcC}Ǚs@+NSt(wg'iyy--9Gׯ07먔-7'wzr#![Ƀ?b%fjojr{fFwmfc/[>ND^,L C d^ @XoMOO͠KAuﮬ)]Buwu~7~[mm~QeEHbfzz&Ά6fnTtA $Q]C#ã,pʎ:i-MwYMB'CTru@speE=^w'f󨐣aG#} WfȠXXOoG&Og{*9} eX1?<;ssDx>bgl2vL&gS#ޑ^O6$vC 9t]a{s38O:Ŝ{}Q 5JEJI$K{a2naPg^CZ{zG552˚ sF0cm[@2 R@Ȟ  m8ȕ9&2gfgMcUH<9*k,/~gi#0 7|ñvWuuu(Ћw_\hU|ǂ?Io0D@lL@1.J YMXz.@oP"$>I,ȴ+%%KC  S,s"av"C73\T6%\kl@v ; p(@XC\)nI + uc*$  >ĨnPe AOANdfǟP4( `9ncG+%1d&hmWl.zi~D@ Td0 SHzN70n`N@dɬ/#!OA1T:C$<%BKz-Oʏ",G%Ib[ q[P`;"Mb&R#4Q*KD(xec2/'=Dke Slݳ쒙¼`v`(a=9MeMqpjp|Yl<m[#:()/9q:?7 4w{/Y]RY37-;G&4:Ŭ bdf |^@"hUCUUK*'JJQ9dXRQs\TxS5 ;;w3EmUNgNݾn[?7K]@@EQ%rg{s+i=y%.Y tn`Vve<_ֺWQI~I,=rM-'Ü # rVFsDH[Q(+:OY$ߔRwI-95CQtVngWo_Nj)XZyyklM#qΒG[s-{]'MK$X[U_nj0_:p-7|T+©}pokWڑz*Oy L84696]'m;w0CWx0e9ޕg?sÍ7<ԓr7M~} C{ax"2S$@0gw_LGwvu[fbh<7"XT0s%1P:( / S|ʩ4h,7exBHTAm#7<; d"dX]JVy: Gx"$Ntblђˈh K_.rA EtM 83n 3/j*UPcTQ+nXӼqI#p˝wr3.ϮWM}Yfʪ)C;WH=ykw$ ҼҢ"2`@ε;TwSl,k #BlD["jP#;퉱dn KEIJ=l*?txE#+LɠA ͳ|⑼.Y25fAl4?P.] b-6JNVk$)Qył陹p~ yXi& /q9'b }l+ F5qs$a*)$. ʌ-#.Ej0Y3nȁB‹O 'D[(m`6Lt|Y"P](yDEQH%&\F,蕼(N6`=GVm\SY[*șe*yC:3M,O#wdXAKeiD6u  (&C@D:z ނFM0DE(.p#Hzr khL7>#GfPsX%Cesh^~.9 M=3ۗ__/2>0]%[{vIjxCNsts=P1ap+S,ΨR܃`;$>pG>ѡl\?>\d@^/r;?_ZijM'9ؚ T@,rsShÂXJl O@7'!c> F0XY۬M A62E6͞8e s#73٨-Iփ#taHvNd4= lfx:6-mfXmHj -NLW)8Q@Y6ζG#2WN&doT?QjC1GSQ"Efbw#+dv%QK%'Ι,ؐs(HzϏ ;M'r-+}ݑdD Ro_RK KXĄ6Ivvwbtg8<1qޫ;ܞHԴq>׳fꦺIخٲȗ9^ßl_nZ?qc0!Ƣ+$"x*CТId% !JW !0" A  bP 1CpKYxPiʇgQ}ssY.c[TA)T6H#w|8<5;>_72@%sӍ ۟&>slpɖ\mT2/dd_ ؉ $b;".#v ׊{;ɻ.&o3%i]y84b&8 c?7p}{߃>ș,/xk_7.TEt ?h8 GG{wY1S2֨#9}-`'':VZp[={աzG G4|NCFu}!6_$Ŷy_!c!'s;k/T~KTW @ Jo?{~6xX"}ទfTrr7/sD=c-={~PװmӶcmZ j!rOf芥9Vb7lI9z4Kٶ,P6h&qcsm~A xܰa}5Cbu]?N $hюST_Rb=zd~^ZՃE˛V1ճ|I]LtiʆJI@$PPn a,+ոִfŽ\_Wf~5&{raݱ$dN,)M'{l K7Q)b/U}ʼnS>hcoPU~^*(e}ٮU+V'O?60:T?|gmS;(p&cBr-lz-Ûp3Vч>aw;n㹱YH\bDz@lX97򦦒&J͗mֲog+FcmݲCLN bIQm6Bmwn2Ŗu͵\uM``emP#zى遾p`O6r]\a=^e}"RQqаGmZAgi E٭߳uaawS_[ωlEbr6]\bѬE!/*W֥756Q=?aܰtxL/ߘO`׍g] | {"!#lM@j/_p쎏c 2(štI{D~!:u{r&`^vK_@f'hlS&hX@VA 8裡dF&Z8>Cy)€7t<֦Ň 2ЗR 1j$@^ໜOĶnܑzZ>24T{ CHf'b@ n倕'/4_6#mաosA,AWh2K8dY|r.A׏. K)fX+ʙs|tq# 0 ̘1&T`$GEٰ֒Z8%0,aNjn^-2E(&o.Km=]aIEbΝ;1mG{n0u|P2i6b+_n!p_|g$Py@B555^}9667 ztlj +gʑ˭GWHME:lsfBkeaN&'FbDW_vMڟ>pplt|6>}m|vlDt*f*rKg+>qC:δ7>stծEWX܈4TtO<* 39O{l|[?seJaH풚{gN;|Lf9uD!XIv۱QM7563P|/e[2u9+4`fnlxlA\D-m PMFqJ'=mtO=ypzrHSddX.y '3JhDFf(GɡZV_0bI5|dzѭOCɥ(b HM AW6S涘;B?8xR`,+^H'x1@OHEZA')8\nI@ 4BC#L[fE9P\NOt.L!#We {1KXP2[n!V6&s /ҹSllGgUU"G~XI`nvV,"PO9)~voLkL/z!P# V /}KЃ(M_|Z+@E^H$ނ(L?>!k}:bQTL;2k B4h |FgHH\D{)2C-r⃖WDG2!C! # ~/? 6)2TLB2 N@F#3fY/8~4T"F(HR-iY仠كL{.2c'KC`AW?{SsHQ 322w7 f t?}=?M7LW=],9bCJ}?n6Wmk+VNN :,mYʊ?Mk{PlذNvm۾w܁}?ۀLɱt hQ_I[>e'ϧӌ ggf?Cau;ԁHKkU)3ףǢ̧'CsdgcbJEB#LACFD927G^aE N5HTT|d"z@KC>#yk\51S!08s~K0'c&g*(C,dh/4(B6ϐL0e\x c' -p]ơ@xyz1Z8ǣ0Bli>c`OwiJXk w>T2d$P"ōPf[hdc/vSco MT\s)9{'xDd0$k/fU9**ՕN@w٨ϣ#L$qy=BV#\6JpJA8ey ׍bhEEgznm|rO] fxh0JёQYMi|m޼뮬>ߏbSCѲw|rV Gpʒ%ӟfn`ر?n>Fhjr )\3SB|pgyԒj$R5῿Z>/9S\ ` K/pp]H@JMW$ppQgDcJ:oqVL, I;E+HIg1zل.y ꚽUu !GvV^i+Č8㧳gc3ٚ[eY;Xo VRl~W8G [&zg s ^[Nl@^UMW,40ȁ )s-eJ@yxK11ML eMM nINxP@+rИjQʰN|=90BIDZhLHTa"sTN>'@FSlR+8 B|(qhPz!=wd-~/81䢌 :r10,ИGl-hN?z嚙Y<ťER>@#7;,D鿘Amo2Jbר^,r|RɺAx$M! |u5]FOQx TN`v;"| w ĕ)J%6.-).*7?K -0u Nj%yI9p(7H03fΜ6јXYa"m2c4v[$'836ͭ༕W}ìWRͭ>DMP>Pܟ)E:PSW:E8蔜%b*hO>uQ|zoh{([@ALA|r7ghW|gd6HPu6Bnh*t/>m+_8؞A*×;qX+.u.n(m,j<97X?SUOyW\(Ѣ۞^lyx;yrێMDR+Igd9:~XM]ߝCZ[0ec2Z b'>S,(o 64Rd泓}":t`<ܟ4ʶ6; l/CCpdg~&VLd>rHUYs\5|͊\eAhe^@ 꺚\%F.߿*!wKOYi[j*jlhl>u.YTBVњ!'"}R'3hmhWrO#ao0L?᷿m"ٱ2-5lnlQO?TuMAu]._lKNW[']C ȟOBx)8՜$Lv!7#VpaQr'R(C Z| >_E ?0Ǟ17OGΌ .yGd<u>ȯ `@" `uE DoF#zJЮYឍBDBR>&F6էAqy>@q%<*wbf{pilp.a2B&%lYi9/#']é-'/̀t7DQp O8 J_S>#i0%͓<N'=bf#-A# `n; 2.(bq{x,.hrF}6r]9.=к[bYz==cW]ö4i$W =}Ok޵wޣ':ZK*l`G<:vUܽ+w~?no%W_q#ֻ3⼙@zc'_=v|F^rOxW:qƢ%k\Vn;sG6ujɧ0oٚE(R?SGs@檊//^ٳ洶P:Z;_b]=^~ƛnܾ{gg{gVGz"su7,&^z%=o6>>(^ꋉAZC.m鹧]~ŝ߾}T¥Ԅ_/6k_Tp6r>&#o 59Ǖ,]ЕU7\sӝM?8PS^tZƭ  eTp*Mo|qVTLߡo2EmX>&<8"wr$S|x?HbL(weu`M r\eIuu5;-8ҲcKrVS d\HuZ@Bs|gLq5J&B7sO8tm鲥4pl}WQG1< ׮\S=[*kͲYr7wM7AҮ`޹g7^ż;ӱxbGQ([5oP&O|݆/9oO߻e.W^rW^Oo~k-+.hhTm/Wj^Z.]~i7>6Sf ח0:t% .Y~ߺ+̳Oキ:koԡѦTUm#PD /M:ƜM+ 0`]=[YViY?qRWG+\jb _O}M[礃Ԑ{lSJ\TP emի =\쪫6]hoAU"[yH4Շ >>ALV'PIol !Dd>it2i4P(O[nLعG1x-b Ƕ:6ۓHp /PjˊM2>g# >;MqepXT$[ Y0XfHI!lSL#3Q#ؓtcW2iK&LCV;V,ɆOC9`A8H#\G $,*  T$?$0IXND #W "H rhѪJ2{ <=JN9"% ;L`vsЃ< Qc%O<Įm&}m{v쮟T2w岕]':L)P=uS&%V[)U"h=g.i=}h{2e=ဒ^zhh{:a}n11;2xhߡSҽv5m?qn\s7 tvu>CC=#W%#[:'UM(x艇]k&_yf˩cfN>0X\erS8.ສZd:6gYSl|狟/$-]Z&[;]kοsnSDJBxטՁ,GP_2s1$>Jb-i ]ae. ()̖W4DLե DID;GA%0RQ(IPc\s54ys]iq(H 9RpUI2'f \;b4ffA0b70&SbYYFOB7v{:)lm h9άR]y,--uIdS,,(nu*B}zLd0ܪ >AϐH 2d xoGHE R5S4LX38n*iQ9,9d T0H:y456' 犓yypi_nѬ/St .:zD; s-'Nb[Tc.TG+QSW7.rI/d[R~bi(gW,n^2a&Zza:(1&pS) |oRuZN<9- čL .%d>-Cs?>Cˆx '>qfA+# ;-p IEFL G ^>JKA-boY?#: tuQ1TTeUTUlQS3NJVW԰x1sb#1ԕ y H>OZ6ғR}:5CFYaIV·sGE]sU.Z驯խL-hceΏ.-*ڔ,@RE+id6]sU%9G saӅM +***+^W& k#7wW}v|Pk 2puVRVl#]Lk.33/SZP:`ȏS`?<)*|GCi_S& Ϳ@IDATlȳl~MYZRlC[\q̆2HhB?SV j]X ¼v9߄4dIT%`- I8(IE'&`**e&͐yH+љ]Q $$$:,JvLrx$Q w;2 ")z~<3!|U8i; 1׃4eՑP0v |#(O$G3-vct[6-G4'¡AtJu]:1aRpO i1ѥt4'ogi?G?Q- ;w CI*N€xC&G<ʗGqGZ 9UNNh1=}nO.U _ӊ@ҥ}( B"@ȡ;ʙD~AKe&*UltK "rѣy} y9ɑ`>r=xpE.HQ$OxBIˊ&E<"1l8#ϧQ3b-,JXM}!.5tv,Mo`qcU]M[wЀ=v͘<ךUKLWd4-줫t#Ch*ނ§{q)SQhT0S,+iUz~q)N %[m8ip  e%Ür,Mi%z~)&pSڄ:FAPmVW-BcjA{0hHEq:[bdT wHiw JʪJ=[FT¥|m'O Nu>s%%!c=h}[,[HxSW[Qy`+uKو2Ҝ+&hfAYJ%Ped---z ] {}\I}-}\Ev, J,F!Yc )` N,˩+{U|xB%d[  ˆ(onD8=\fI`WÓB˼i] 9>OS/~L7(޵k *`)'wy$|ÁE8veN1+5P}6'GՎ;x:83*k*u<1ZvUW_Xh%x2%yV; @5#=?#M/<}d뭷7;aM%RN-n؂v:8wϡ&f̚ݱi 3:qѝvjˆ-))&9ڱx9-9zPڊOh;^_=i$+0}Gw4nK{tm2B)=lyunמݥeԠY3b'MܺgkUQuFgΙcˆ'^xR7<ɥ-/m*W=w܎}|kt~T_$&s@F-h'OǧlWi^xŬKB6X2f{S}JWDh^F*"և{\0H,2 z]E3b 1ڛ. ZJKt҅KnvJB 0KEăiW9Z]SG&433Mmw ̊..lʔI@jnn&yWj^x!*/%KFRpiWT IP6lؠe+I= ))Cs( RPuϪgBnT5SBa =*j Ov @E[Y0YcQ'5,)ݑ@n9xGtvX랽GJsi>綫E؋ʰB:.%;rZC T`Ꚍ\5_2VIQB;>-Š<f'>e'#3=|>?ȋp?y죪\vj9AY~]ǎ͖CX\xBk3&5ٳ ij~qօ}#=Uve>g|{ܦ'~qN /m޺ck:sK?sZf?>o|r_za|[H/l4?NHH̩3]ҮTG[EM۶tu_z ՟8*i-z >]voپxZ3ioN=u߄_ApP.;d =Լir~k'TS^ۺsKum|fΞȦGx si?ZjOܰtTr:Dyt8jq|9dΕWj 489 ˆˣ61kN^);bp칧l?pxƂO>߸eO.\ީKx?4ƁŌ N ' q[|;A1Ӆ. Dٰa+` OkM IT]yؽL#7n?xKmXܨvrY¸Ϧ1,A%Vv}_ƫNzA'@?D?C*Bf`f S.zGġN+OuE,oҤLd?A ( < SS1a8-AxG?0Ȕ0Rat:-YI.h|QR<߮'@|Pe\!/4H$1HC;2Aq70>ƓNqs\ jlr9ɍNy'ROrb#)P oWăii샩+H)L 7Cv>dۄ2` < *,)`̊bg՘Rzclg' B|0<=L?YPnV=vss̮m*8|6d^ھxCmocKlzY"3q,)-/]tţTkS\ޭV̙ҴWm n߱rʎ;w &\y˳N\?yƴv/X4k *Mvvw6?;W^ۯp'Z[Oӏ=>{ Uw9{j׬.Bܿu,pS5hpΩS'MqΚ9~ZCֿ̬"ELn`ւ۷; J&jʊJڕFE[Š'O2}e[_|y&\ ye$u\g,MO/iIWu,'MB6Qv9-;'N:xʂ~Sߚ5kvW{_foed2 BezEu3!vi9G(+/}KV|2+9AdCL]s&2{[Hˁi`wf2f0fT__c$'Yc&%Ud+}He3BV}Sg6_}SB曝\*MdkMRSA›v!zd0 oQ0v+-Όg%CD}P6ѓ<$Q4U | QHU+rHL>[MJWY@eC3HSIX!4g8"Sj0.'^_B<<:Lxe0C?J"JEcJU1}DK7 S>::]hYU J݆[d0*RT7RQ^eLYcYG֭0+*I˸SKqio`8A%B~,-NKY?xUAə*X:z6l=Q1/._rw?4e/m9|d\MY Oomf7]7O/+*߻ygM5qG~py0;xp灆UE='{lP5n߿fE\㏎t4/j9tpϩ96ks<|FȾz}$i'8 H >O0A'7렅ԔZA4g`Qss3!gޘ 2AO0=-Y~=CO0&R9P Yu >@+'!* s"9p>ڋ"֢Ix-BvQbp WX;wk܎PXZeW[ o:F !UKh.֎3$\ϙLtxZ`@f˓X 1Feg"* lNL<8mg2az/䒢r6ϙ3=PK,[~*m[}k2k7[—_Lu_Fn ppJ/Kiqzf-yû=׽vt`_\4ԙZ3}ٚtˤ,7I\vIB.t%43p7NnSb^EK /+Zԑ c#WI8kG6R:}7܊rg (;YB7eThV9s m N;W gMw 5k/&MfYt#h9?gS| FrIY9z@TmR.F51r^eQR%gt%$.P(Ѓ BjG9~(@p@t,4X;鉜EZgF,`[fGO+oeqG~eJhTLKug$S\6IN^(j=y{`']=5*T([tee%';XMwtI 7.Eo[O{{;2kV#憵T4p*n2Pbg!KnߨsZ:PƔ]Va; V:re22(ߞ; ÿwN3+2IS>>AOqX_5u xRf 9hA7&w2Q/RLW}#/ׂH= s%Iց9)z__]K2;I29}#__Gf ;)U|8[Ĥ"inI,n?f-i*ZD7`O`PN{0(lW@E¤2*UȚd=0V3pg[*0A@7!I1!,SQ d A %(/`S@ (܂yOҊ&u'@b(#(  N]eoݳg K/^>~/;v7>"Xn-@HOʁ0Iqy1mCBsĒ b0nWm9#w@oIYqT@Α"/nrɪ +Mτ͜3+,@Rz@Hj+]7|g1^P?wf `4dF,=%4G#6!;DBiWb&q%XJ{TbcGLVZM݁G"BJ>|3,!RWKo~V.hYZN“3)Jv*k{j-O[N?NJd5q16'p+ꝞTKRC( >dx2өWGN[" &]U֊̚$76WRRSWzbsdzaLBęnsr012jhQ('|و,o'!.!S{x:ۨ2QS/!t~Ƨd~/Qt ?ȐBEtqd ϑJ齙O>T/AOd' Wy(`D%'0<2Og>pi)Hq|."hj}I}9Q8̞{);i'ե#ʇn;߽FYfޜ9[O޽uʺϟZtv$0A{EZeSS9`7n3izQXEcl>%<6$*FVVGx+Ph~xso h5I^$c 2}Dp;_T%%&U6?=uWm߾w)tNk_[啫| Z<<}^tYȻb>]W-){wM[pYYv/s ,߶}[Ee-<ѐ~ղ/+ofG_o߅azjllv yui%k.ӁQ7\p֗_rϿ|O_EkyfSWG+M3O`UR[2F}KWXnUhGN}g.=uv}\lE;pѵgsZ\H 8bIb"Ґ5L!(-oѣ{H9Ou-XD^ G>M'5ˊ9GӤ.\fSYƄhW1If[-Ltd26"3\ɇC@Pn''%G0f s'x>=,G6C&ʃ jE|̍NoOt'<|FyIx'Ju1kb588W.z={*4\Vp@6] n4D6!?Yw v0й'2:9o8+I>;" < Zȸt kBޑ%_QWƪNVGJ'Q\[:Z{N?eag9CLRH4N"_ހ͆eXfm=q̘m(b΋%IЮ,d}BЈzJ+ =#---Bt\ ĸy.aJKSg%z+Da!ZTR\V6U9~d==';Ovu.;.1١wϵ7ްl~v%WPјܻe:@Mu˞qSO?>oz V]nqԮ#{|E~+K}5UKf\sc7:|b%&V]{ێ/ 6<ă&u/ZxtoAʲoHIzG<9+!ʺQ(G\8GZlz`1wMdANEOr@PG5|Byzx#4b IH1OH<]uEZ,4zH]7x`^> " ]O:ȑTAjZ/LѢd ?xP$dJhZX OIs|,Pʠ-6>[<N WAw$T [WZ!A 9Ovh*O#bP32d$0 SH"|`|ɩ]ZVʮ]ǎUBQ BpTШ"p7p8?RhB#`r>Go1M MsD]9ף/gCZJt -xvf";Ed>! SohxZ_)3&OmcjԪte*p}Oo{})Ӧ93f/kYJLm߲}j `]bαֺށYflr;L7L!ujy˗,.UVoK 8w*Kx]_[0'']A ;S Zf|s6DR V%J:={A~Hu?ܑ@H >3wyw_'ϻz%}jR{g6cVEC F4agV 2'KX ,?y3V6芸=2B|ՖCfg@`d4mtKn $P"_[Gw3A(+E CDѡ:\'/|0B0XO~OzVByE!TA6.l?T[}ɟAH7>#'I,i OfC @gŌˤKarbRrnH3}%n1*K)nۿ[YA1%)b'MD<8jc^_KѦ[Dmձ +Dal5xjJOZ2#^p)EhpTh?:) 5rϲeO*ٽzˋ/ʊNm e}:=Ӻc0;meM.]e啿ߚ8jłhiRI,}민ʁv.|]eU? +W)Ǟ޴i[Х}*VGݙu^eOp9 O'4$eE*g:7-V|Vv'9(.¾9 ,\@^ 4dF蚑"we.h%>9lK"h`֤VO7P;Ѻ SXΛu 8Ecsnwbe Lh2n:, 'M]*Y4cɢ:ĤL/1}i#딿 S77y'k1`J);kAQSܮ^k(0R*.^2miHoxG8}iQ5ҬX K*ϟU9Yo}ZvMHj!/Ү+CLGxgSUwPaֶwz{Mi_ۉOí *8| h]Κ2ħgڴinnA( K7ި] l>-q {+i '¬u80?tUܖ`fR_Yߦ/Ge a ݑTڶ˜ޑk~|@/V =HFt _җl{D}GL`szj:Dرú~\dd`{$yʱEFЃ`:rШ+ꀷOOT $˄')gr$HNsFW 6 ff ;!9d+GG \ WQ[-XmRI£#4OdLc2]T`BTꤍ*0S0-*c,dRgKőAdQV0iErc w;P{OҪ*'uЭmuum9jהF,Msz]!_}'!5 뮝倘qBa٢15ST %"-i5iEeN *)/+n |avNc:EkGCctϙ93=Z)!>WK{VW{ܚ8 RgǮTvHiӫk7L{iS.;M3|>h WIVK._YWA ZBss:"WDSD>ʄshw7{n::):`RĨO7HB7Na =CGݡ'tFBo:[*=<9J^)Fm(Yp&;!сovm8˄R-ܰ0>e1AL dYKpx:Пٟ99 rP{<~x0fsDʸ~Fɯ?`'al||-OY % >h4 ]>x8'8oh4` pZHV(IxNUT.}FK5AOP!>2 slXrA1&51~^rTU.*&3jрrz+,0A ՛J9D<6N|: uPCZ3Ŋ]'gN:eNY:kM?lTG*"֋' Βb7V ]sbToDA8ԧ|)ȡ8UoiKMr뾲5}i֧X'c}";I&Ң9k|(΄358Z~H?\Q̱4~V|D]^i`{[40NHː, <U&@bx0g#HLL / bsCe!NemD=Ct%F"smq<%8X%5{, gsUۨY IQ w%/Kp R[ \ &8sJteBgCЈLKѳucQ3IK^4#嬅H;9t yTJP쟽l/]ӛ/GM԰>_WTV;w|bk/^4Jߜ5{>YZJ%gUk ?[g7~+1}lK=}=+_qUeC5LaLtRAS{Ёd4-%(ܹ$և Xmzkj(vr06j q~z=nJ.cdG( }$-Vg 7*ҍ,%KNݵgen:m]w#3u/˓&O:r؜d)pjkӡv}Рۿ!&ZK/ⲅl={u.^ȆڧFkzTa&Q֩(,K$fw0֢dYy"&ʚΒ^]T1iJEի3@ HtaR.ڵ<Ҍ*恟2K2VDex}* +GMMMW: 2p22STNuLFhtbԥ)%U[7S>Ux6]<5~߾)+)y Y.UH}ru(WJaG{zJ2@)v15`U `LJw[ cLMd@`H[I[I1:I(TpIl~X βzՑ~=WA3W4szd+<*_?!*8KpPĆ^VJ^jpJ~sezȾ<GG'[98@DiRBA Z$E)z:kf`WhKG:Aj)DJz>4WF☇O pNy=.QNjNb^EYOI7C-0ೄq-;(+)MXSHqOI 4JX6RDp>Y2*[j9ա&r|dDtjcfM-->gÿKÆ|hM}Ǘ,^g5k/r8Gk[ko{Gn},]۹m+Oѝ8gh>0˲jwIه{쉧{g>mP[ǩ޾`2<]7\i-/<ceͅvn vS?/_؉/ʗlon۔".Et!<|U3mӳrYC?(n<-/3HRk/;C6tS#ȯә sD@Î=- `It5E677;!Zȝ;v\yZ@ %+*{N89ɕ5Tg *\מ.4˖]fW5iDYΎvۯ~c[d%s}{v/3a0H gT+}#F;' z?P@ѣ,ߠyЙrJee^A̹PYwsNz`AmFNzqT ]lv(&2(H$ѓmȈP`Џ*֔!OoRStbYV(BJy4H17t%%vÆ 4@ɧ8))oē#@H2 bDGB暓K @O. ;|`߉>t2 \MFY!7n}i96.WQA_TeԥnLxˈy/q}rxWR$}0).! xMW7QO>w"gZPx0zk~ŋO:U?qҊi϶u۷r7 S, ^޶f.i^{̋4PdbãCX_St [p4z+ei+-;&޺cO<o$rܷS0iR}YE׿^Rz6@IDATbT)4k^|Zg>cEW\vJ4g~wLt*~o>oL>:ԮS#$71F0ϳ,F. WN n$D Pr0:6e-'x0"@ <|BJ Ds0lwTprQ8E FzLjI 3@B+uf9Ճ[ѫ]l-4&80@U{YLgex bV"<6D|$ s  ߃6>%H%yS+BJU4ϕԅjR]m,auVl! n0>|\9dS~`ȲXT| Ċj'3Tx4,:cr!XYYO)kܐS|0*X`p g0|aSt6 _~ 7J/PQiҒ ݋'O,/ $9^xg^W䡿 jbE׫k,nq[;-W}ƹx=qQ0f10O 8ܧ3p#QEV7F*,W^g~U*P-!")Twq\³ϙ*.e9횂)&K]w?ک ('_,(*+bal$=R4X+?W^Åie8_K>IF}#pW5븛QeˋjWٖf(@-' =NW!4L&m4QM.DKB*SuiSj~F+ɲdқ,pnhb&ͅ;zzSI4;io88DFM,rSX)$rX& 7osK[V^6ПCy"p3C:X!WÎ"&x K)t.r;7muM%kpE &|nqU^!8 DD1V H%Te2ZN (>̞ $ܩLN\$.A"ԙ^ #4`)IDK.,78!w0D\Y3Y[\`-0x$á4"L5JqqA @%[Ӷ)!}=n2ObCFj';Uj͓c)O)٘ QX>Bŭ"b,GxD @L8"qݷ,Dhq236ɿ { }Kp7D؄FD>݁ (@2%,MZ2fjs)=m;vtBZ ]CΈ!Ͼ# G`xG|q ”ZӋCe O86h8DSI⁇6>Գ5'ShMN jI•i 9!N2Ӻ ^:iY3J {_\kcsTJ֔V FEaH{6F6wc\۩Sũʇ$ TUYt==y{Ibҙsfϙՙ YVS{2{{9`_efdRXS /#}i`bl$iU [%%Ɔ50K҄lnd[oFvv Ek3怄<>S$F% ~']r_bWGQy h5Π[6pF6i EH: W^ӝNk1/9%I,&zұ/2WuV@qۊuSMMM R\o|J#;ԗE!JLO6E,2]82S>4 `<$GO MNP$}IDOyfʟX0h">i)R Zpxa%? +9IA J ?wڅ6slUBI"ӮDѸqժ`H]sr.$3Gp[w#3!Բ|'bIHp ,(J0 IFECij>UdŐԉ'd #)MګZO44U刯 @VaI^rXiM1 p'6y.9%ޯyڤ^Te24MHO1Z IQ)*<5;IJv=1 ct&S'%́QR.F{晪aVA_ TmQTbbS@t.Q,)agMz94RL0j4*o#AtC|7 *b x ٻ0ώ@s ={r$4 3H!cmY??/z߷[Y9 i4As$M=& aXvݪSN:UuD%̀C 1Ϻ~ɢR&89 W4 h x"|_mH6hٟTKP܈Rx @hI~H(B\7ʧ(bj:±'Cu0)+lTqP5>dGAN\*.2!dxvhr,$DC]DxI z+ *V4v\[i!!J.d.GrxC ($8!Qq tfVkDTIfGL57Y*.ݝjSpopϬqPO|iM+SR =)V q)$Ia[{9G!HjY|dFڬckҨfj &} 'x ʬdN:e2JSK!'&ΔD|n!SRvPƉ+RPH:^ &<Շ&MR)rڭXO܀sDĺggoZH'[Rnl6].'0K4&[meRgHC+r^p D]Ri٤g`QsPt2K8Džu> UE찅K ?ʩt`3FGV'eca)6X' H CO qއ]FEyXer^Az+V'0'泺R(PlG+AB(mL_1fҊ~{B")$ xbкb?F`pXYvQ.J*hP( >xNYrO7pbNsܾt"9酽3pHzLF zTY8HSS:T]]5mTEJrq f!pyP <8_OeB1!Xa|͚3g&~X* VQHl d$NR&3Y@50)}Μ H޾n'i2 ,*+h!gϝ Uq7x uXΊe0`зTj|GZd2s7uFuQA5CsI' Ft3NV_ZXJ#)#1*MiNA#=Ν9?vts6ꢚn(U8H1rl >6j̨*;KK) Bg)S~IZ}eQSڱŮUt%ƖiωU9ڰ@9?}U[TC]sںe!^r2=]4s.i/Iιwa޽v%}sz'N|c8xyD+ӟey֏CK? !@uJ[2S֞b3?lC8=Z֮]pIP˚)XDZ(¶m؇-'΄E] g֥wm޹~#Smd]Rx< z\K=:>`>$QiaLVO|աV XjP[GIMPuZ[[/8ݞj"GJ3Z?яR*yFv)*n[T*YS1>#@q9BѳdR T?ޣ>Jw|ěC ]ꡇR@<␇%ks4ŗd^"1$Ƕ ꯕs9KWByӸLR=K6L)]O&rCq* <Q'l <^V0TM4+%KٍvYIԬbU7xNCCzY,jv+eeen)w :ʳkKe|-Oo)r VŦA*DoIh !=> 74{tkAzMQIkgͯižS?xnՊWm?}]%ͽvlW^W{~CnTӴۨ-gN?sm4z>um[*j*Ξ'?IjW\8a&ݾ}nSB8QgF*WZl*i8ٹs?x¬gTKEص{/]{o}w+*A'gF' mZ&3DtXW0r W9O+N3b>N(`Iq>#J0RJ^X/n_!>s}h;aͷTVWػW8<:ށcgu],4C;;Yk6a"yءnƍs<Ɲ3[Ҫs=wN_kY2>2fOWoz׻}“㦎[0{C?h8ߴ{I%]!kY&NtBn\p&|۶lٷǞ~e73˵Lki,M7M4yM˿?f/SS]c'vut0?Y8˰.('Y[ d9  Ok-$4$Id7wX >#@HB]c*&9%LBϓ{hHQ5Ċҿ+y+ĂQxeq0zA֊~RF MJ.wsjYQ2*Tf H!KE@ 2tF,v #*<óR 2Y<:9gr י}Ǎ,|˖-C~]ءdLJXYQÏО* T5'ܱsմJ:v1݉MRI%EI7_0<]tb{=otysM.cm9*VmۺS9ydGyȽr]*Q@ih={z]jA*FTbӂߢb+O8p)Fm\IL|mKkj"C.u\o 8p.wpCA˞ _l2jcq[[27]_;/>ls<%Aئ }+j I:sGo۽-uN`UV<}urʚƚ#J Hk) { Ԏr3#zjʊ˭ݺu ;c*ZEKW;9.E$ey%͍c}6[bQVVaɑe]=N|乢qc'(km.*,9SU^UW]WWQZTQ-mVYi7m2'&KF4֧晖&='//e}*6ؕsV++-onP߄θzhGkvm|]󭋖L~eQg_ׁ0tػ*YSy!,keEQsc;3cj&N,6Oq,U6;{;=0u4oܸ\[{vݫC\t!H 9+lku>]htߝ>:CENy8wTޙ$@s2YaQ8*bȧJmb2ʝ)KIF Sj3H}Mh&©5wWvMj -%۷l;rEقoZ|cchXn A go&~y)sf;w߻7ҫf֜'Nn>eQ-'Ni_'#z%>V~dw wnDwwUW~;jnۼOx uյwǞ۟yiԠzAxMF{T}U`ܘ1H+7sWI`.tuX8u¬'3B li׬ f@Ɓ0$NP7 70P\(OT+na ϭmʼns'-Y~Θ~[_J٨8n"KUU056Š]{v7V7mj2ġ'MZWQ_[Z7p܈(-,in,///+-.LdRQ5M.,L],UT‹Ko3ͱwE^#ڏv[S).\&7OzaƉZcgsoka_%򵷩Q=XWbImjrq~( JbŋnlQDCK]9lS"3nxXX(Ȃ*(Kex: @*@ [D'b.wQ:;OH +V0~`bI FHFdZQCegO:(TRA{y !PӐF'T5KQ8 pq?$('G|fN0i7?ȔHMa+W rX\8Ͼ0IUr0L_!8 ZM[~ ͛?a&C2~~]zC>  r  aŕ?zwt>Z'm޴G֬[~Y7j>.+ݕ'8þ-x1|e[ҍ֭ /+7rr>U΍JmKKʡ<m-r7MMCg&Nev3F|[XRٷ"QR/ Oƞ~&ÚI)L÷WC+/i%D4,`%tt߱ DŽ|O[Rta}%3/(\V:M JOiF ZmZU`FSq a3vho7döZVj*rqʮGPσF9WdKK 0*q,enOe&?zzӬv]8@0N%W5|Ϟ=6~b8$ IHXp1ZLSSXVQ*T MU?bԅ,dtLs:Xے{wW fpeEKĎ v7!r֫ N Hy OFܓ /́A}'[g쉧[f}u݈tYt3v@u60":պb0ﳐc_^O`N5e} w@Qya tMiOzR?" M/G53ۤq'>&0t^:)/,6]Ju4ef٣T)-N&DD3Kf/&h%fmyOa68|;Wʤ.uL+$϶+Q+ӆa@xZ>[ʝx ZNBGkvG$E{5LO%3tr:o +*= ӷ)Z&^uMS_a/QtuPRz,!JͼnuK:G4 VSRH tMiHt訢8h}"a$Sf^՗+멧=YlQ2R=\2SpEL" ZNT8cFdgS3}yIL} ֫\0%U՝D0 fQpi@sjҪNFA'^s?mPy w*>VGxxr`KDuE%5HJwjYQ$ʇql`,-0q)+:Q%'reUm ؆@;(5ftZvWQ..d"?qBxROu'/OϦME9u$V`=*]4y2FD c:qud=_W_Ώ3AΝvitmqcyO1]+#H''uX oi*ɧ$*t$eR4`ַ_hLa3Em**4Ȩ.7aegD?nt+D4vmݵc ï\I6.4(ˏo~Y_qѤss_mWc6$8I;ͲfHXtG0tB e29`_o $S44;+Ȭ&m sRa:C&뿒6ɚF :#g,m^<2 Z"ٸQ-wRvqeyLTc,c$>nFdJCkuƪH1aN8G@%XIPNPoE+%@7u6^(W+ 2<@"\xpqцN3n 026^#/ EqQp >Z?<0ˋ~~E^-032Щ%&jCI{^SK˫s9T/Ibsp@wb@J]RZtݽ]% ,FdaU 攪~=BKZ= :S`i<#J8=KrۋuU5vl( {LB85sM#9s!Qpx$&!b9UőfoQCd$05U H51w tkI,X^eI<:[SNy8zC:5eI|c55o !V[,_bq[vl=֖,g_8{;%vأ-vᬙ3>??gI0̺ n]˖/Y~-ܺjժ(Uk~ƍCzli ֋>;wu2k{[}w;2Jv-X,_Bkx~:#G.]z֬]SQYqw\77tf=F4G?ʨ`~u-[f3ϣKn^ryIca#ثU"S %'mMdں"u]P%uS:xWQ0ăqE&yv耙DoTr $ĸ) c(|̱:ߠMu;$,/ e2_)e8 ^T)GߗuImd$wpiZ&T0bB?U_Er֫F.9*^e#-XO9敋L$ 0~!?F\A^b}z@e?$QyA-gc #/2)50`8a~)XX^3oHT<ɰ5,ի^)iFٱP^t8lL\0xSNٺm=Ñ-I_ 1+T*U{&gxE !5;=hK3T5HJTIb<[RQ|GOD:.$Gi 4 Ó%|RLu?:E='H@R 1$ oa~iwiAhA I{ Pbd0?#\$L:ؿ B)Dŋ:ujTLҚ'֝@ۅ{ymw2c&\'{=o'O_]fU ϯ]Cٺy˃?>F]~!]w„`@?aɓ #m1{G=}Ե Rlp%%UVzԽ[P\s̜1g~q]YD"h~xg:}>ZQ<Ƭ'{z Z5'peUbzGIYpM2CV lHz%=ɟ!(eL3Pz˚M ӉO H'*ŒJJofӰ fVԢ9iΡ^tDwW$:Ke"xz g+?G `?pFHf6;_&S[I6z%&7 r/ NS'O<\ 9c;䯻vy:BbM$… "ȞTC&D8^WH`>?b4*45v$Z}G-o.BxNfk*J,]N636.+[a,L/,4Kg^γě5VmZ!VdtÚ 8-vY'qٌT<ߝ;wϘ1}֬w]V)X|ƍ9sf={䩓o{=)Kjl7AreP=Rda{m.Y(jژ6AC$b-/L2 ̨w^7^+.ي 3R 5CAHx5.URVŚnei0ߋ *T/3bH3M/^S<&؆I5E} t x}I|^Q?= '. .<*2qRvQb.*uI…3Op XN୧$jnsV{UA̫eFNTW"| %ʺgh27Xf=Oza 9FyȽJM{d&a\}9T@"ì yxqH-$//GFrk$d+aη߸ǑxHU]Yi.0!Aq.'vTT Sr[gowdJ:} F>niTJAGI7$X{jG+Ar<}WiuD\%-.N)eY$< -OM~MUpEA2Ȯ݅mK&zpw/ziNoW߅²{9f*ѵ*c4R0*':I6HH-C<`vD6a4tM }C&*A^EDf 8m|1Op@x3JWDQE\?&6=cBr[=(tZ]:9`Đ3{ T4!K=p՚'O}jo@IDAT,+1&JRXe\Ӻ||9ܙfN 7?&s?ulBX8]ap]<8cI#'ǵI2*0OɟM F  (u))$31!9(J "3_mILVIr[:A'+`x`+]!~OQ0z~hú ƍ.Ϗ=Ҭ}[6Rwr`ŒDMqf&|[ߢ8NFsc_m&a'WE4."E:ңHLS4<9ۈuAV2Pݴ3}|ɑ0$c9L&Bך0c? w\gEC E]MpS]ѯ WG\<;K([$_8Pg-I9(/e=O %g |(2,i,gFmXa5G m* ڈ h}7r<wyñ"~Ha~ƃ9*%BDyrkj'BH01SXbPk9A`ԗd#O!䰅G\jdTW0$%gBEp .Rxd0( `GOdžjj&L |/oZx vMvǮw3洵ٰu]EYŢ9Vzaxͺ5w~Ǵ M(=zDS QG=ql9ԝ{v8k, #nʍ+O>3c̺gW>C-3hnIS1+564غ?isXM[vni:;}={>u6kzzG7޹{ҔI 5u+uΓk_;aWnPw-{)3<{Ϯy38Nf\uUݦ_HANxr^8 T/yB :%!%1LR7uЂ%.d%ȯB,tɦ.h {mX7n¸궎]ݰhu z }МLWe|xұ`Γ4[H4;3Ė=I|p7HbeUBTCEi*X¡Y40m kKP[[[?B0LDii[ذ/7!856+quEP&kw)*c ?]i_G@ ѣ3T^;%:(HD!bYLt]cƫ05L' *!tdtYooB1Y*JFpR|k)x`z-^yڠV:\s<ē RUpo|߀ŽhlXv,Y*6^Tx<X!<9$<%u !`<N1'!ۏ'00 tA+C)6@*%%E6:r]L7:}ھ ^xAq~oW5]5g+ ;߸YJJth޸xڔֳmmIN?GGF75ڼooj ӴD'.pLR:G*Nuzrݓ ٔb,|sAme]M|FۺS5;N;ʲ mNk>SPIaN+ (Q{gcv/\SO4;-׷3]g2sso\z)S/}[nzvEN杷`C{˫;JJGIyPN6eLgҥ$8Ô`ge˩D)0 T$StRE,%r`IzI~+ǀl]o7߲ġyҴ{,3JأyD Z~HF6@}6MX)ȉWF_` |%P y5>& WX*Y ;͞'< ^.Vp2_R^Q[%1j>"AnftoJ\@&II5 [ZZ/&DbZ3Q$~X N13_ _*Jz 1h{+Xdw'Jkk:=$RTcCԅ-1* @,Fulݚ3f:vV_wt^8zS*Ν}3 yqG}!:(.dgB_-;m("Tyg﹤)q E168 '{bl:MJؕS]6~'WwTP²3*Y5zK+K|CiϹ 0$_Ttx  V$6')!p-!C@j GT.yd-HtFT9 D^x9vbSSB8Fe)՞={q.2S&N#韤iYVS6/NlE?ɪ.D+,Jnx7c G?jڰD]xb ×hmm}A9uB2(N$G2N5wb3RrXjqB8\ð)=TT[ܲvݚ-#2ĆG4%Rߤ[X~]:P;{x-Q奕55U5F97>pל?qyE3ݲ̝4g֭'Lr|1L>db Kj,Od:IH2*LsIE] &Z)#: l*6Ӯ5'0Iח(9p'J&I{U#D֌?x- Tlg65Ȇ# y+ v"D$\kr #Wx"6Brp?Ԡ[[pr]BO؄T ``tx#u+b*i3`@e2HMcuB52Yn xk)-Q?#|CFZbD.\~:KM/L0!RT3r6a 'BjeI{8 OT|Ŋv $4m'Q_z5$0~EzUW O~ AA@KODWU>b_O%JK(RƷLڥ-YTô寢|ْ#Q߸YkgMY4rfq6~tQNORN9%CZhjHo|q^N\k+jWt!L&B'(}yݧ:N}oϜ184rХw2ٲr 7wPIIBleA(`Bt1ǰN+/ؾa[nE_ƽ"Pj!V"6ufx5ơ& UB`D`#@F*2ʅ O4i}!yC~.= `L+`v8G0OLȎRC"ml&#p̀jΣ>TSVބq-)|F`= NTū!TIp2!NH̍ O;<?/SG+|ӟ``c2aS>`UYVhaꖝ+A|ǐK"TFc7`<G?z6=%aˡ  a`YԻ* Dr!ԯW#Cg\:Ӛ-O&1`&sᏁD\<9GK˽?9K< ⑅pKJaRtIk.C!V:z3ei< 8E2bĚ$9~W%6ZR㹡ZUeN8_GT+=bc"uM^2kLUphF1zW@J{skZ7ӔeTl>\}-Т 1ܳg[]i,P }z :6Ԃ(arG8(/ 908Zx` x ŅNdHU+;wXr= 5P4_VГvTVut]((r($]5[P]Zvđo=o?gOz;mUp©-yg{;'a(kk < 7u; ugڽ.ʍuB j?C{=y}H0m=rsڏ=ӹ\&d}z_TN,8{#Ξ:_I:5iT*3G7lHR{7ohoiW-;$ ΃Hx(ckƤ9_wqd۩M7Bg.l B.=}5T_tuw]Ώ8{ЉC(J1NB) ݕYPRFN^3:م};*Kϟ?WTR.ZZͭ67-al8$`$Ӑ˗k'їQGȮC|Xkm& J+ohV2K%䦇5B&>e\0n)"ߦhfkf lxɟɯO#1~cb غZu*0.Fr=X dEY`v((굏=~hvb 9FhfP4 C[=-_bSR--J( gRfY2t=0‰kHJu(x茧MGx4u0|0($ /y)1GУD>I? W.9$!C\Bx. *#5#6~; Ѕ{ F]I$Y'@00WkV9ou2rLqIW]wrU6?릶L{nj~+[097QT3g Ͽ)^iCg3gהUoݸk,0>tJ©V[>} wTWvm/ܷw^W=۶l*5y֬Yi2.deޅGzdŒG7?oZ:}4εyvf<_|vlnՙsGo\~K۰Zϝ6g̨1_743~l6/nlC=hoٲu[L3+4$lKiS0F$I&׫V♤(,3W&et8~;B3:8"?)ؖbsAfP9YAz>O`'> [!S b"Ocx࡙ٲNwٽ{^ՄHzm؄d=|u:D H{Y$Μ;Mc8y2M\7?o'W?9n];v;8y /~qߑ#ϏeE%Iix;XZYT$6f|_k=/ٺʊҮ#J+;~g1ŭ\̹3~)9GMx20ƦMg9umK񒚲T3-5wVǴnܵςJkFl,(\fPűT}]z,F̤৲-ƳtR쫪6@% M*UADD'?lڭ#os \%?:m^cywؙ]'Xs`϶ݽ-Ϝ2ׁ.ް~G?5SsSgtu[WYVyhsO66.okXBٹmLj ;m;o++:js{ˊ|qs F>Ç^DZƶ9tġ#j  j?hZAkްIG6X,w7qis˚ yť?| jζ޾}/p!Gt?ܳΞ23k.5i׀sz([IREݻPcF~_֛*h#=ݭSǭ[|e[mq={vm>~DUIiy~F77BdĔEV.M3AC#׫uf h"3ntg-H%n +ط FI2l3S5O1x5yǦŖczҠG ng?\ks:-Hنԡ h$4 0KVi6z@:2L1N5k!f6ϠJ`rAL50tf"G1nS -[xEiAvG$ٙ 12Z#{01e(%BSUXG ziKnP ?2Th]jA w$m2O#6y!<{9. Zxү!+$p' < L<{傱`. ! l2zvP"S&ϔc‰W\^!Tj0~5HMlHP)(De&"9QhC' @8TTG>+0YycMY?h2& A̍%D }?(Wt !4uC<BŶ'}f˶#nsd >:Ο[z݂kfNMSrN.4dҬ WeD$>#nmuz7`0HI<ēX/ xUdOّ-S Q!Z\_ 1 KjT0g.Id#$\xx  '{r!018]s#3[qGZUQSci[{\ˁ/SոM%"100pQ`Fp9BT`ȭp$/I䗧b% _-xxxxhYR<d$$H%DҍxR-{a砙JZhX/ OI"!`dakY R'^*v@)1+ťE6X%5EK(Aca2lMcqtZWBstڷ^gKC!#cG[.1.LOgrO;"BDtΨ!#R$* W.H1"W$Sqji-]sٯO3^3+{e|Qi䵊e(FK'-pȐn3CQ}Brz?#V2GD.,,hbj 3 & bR,Lմ\+pY~ROŤu1VR1_k.iQdȒ\ck Ew {@.}h*ipG`4f )࠶[,@_ᴰnBpЪ@&&Bҙg>6sϯO, ''Ƈ)OzfdTc;r=^s3d`y%ۓeW&7y)kr,*c/c_؍P|/SpC7v.^’ 9EE!]b{01Ns/ڕnx S?a%E+)O)nƨUQ~(?hRZv`fp'(G ja#{,D1)皇cC@c19SBQ4\Ԓh5.E Nub^/<%8<4E&S֗h@XaOb_j,fq*esɌ"IYFZ{Z;,Wa`,vw-nOb uGj#>2j<dZEᵲ| [pu/oݺL yiϚ15X"i^@P|[PCDG&^gt4jÆזÑ%U |k`Ξ[/EP w &5)SeJ^]QӿhPRU= Fs3u)H`luFYz gCH馔!ƘJiTGt0EDN1OIRא&˪*i/== q5p኏ZP0LTW7R>U(|IԌ*3h{԰(mHXfږ3r],D_6iA# MXEyn1I=ky$B {5rP99 e-_6q )Y3!*l";>f%zٙ`.:uƭ]VWz0qulפ w%:<՚LJlie!$6ZQA^'d:=Cӫգiӹ@岟ڄ6R>ӴP}ݗҡI:`or9oxD䞜=ln%?p Sv6S'`]$ܸŃ+M譥" `ĺR%pN/5kMS! \cz+<#qv RMg4Zk\0# SUeņpK/ue.v렦kk7~˥q,ooJeTҜKIPdyN N^!H.͔g^;;2^l8}9K =}`"dE$ ⨇̸1# Esyn=>F|-Xf{%M" +tőv=H WY8x23#( 4Gx USf9+2TY#0Ypvżz_XMV234a/?k;IhZ9GJƚJV OPLvYlx8m N챸r .J{Jb܉qn$g\/|O8ȇ9qmwԖ-]< n~أO>Sg-eQd&~fzM9pP᎜g[^ >PT~~ jPpoOWLm؊G"#̶mۼMPZ=#ڸ?g[^'/͛7.Xū۴iZ}24H*KA7c'$}pIśib+i}_gȨ퟼>8(mimm?Ua͐d_ʊS)ݦi ̥>O /bse;ohyDwR.9և>!]0%DF&h^%>VF%gR' 8z`Aנ\FO`LG#.)OIȤeAZ+ XZF厷BEP"R(qX 5Yej|L=L. <KHeiFeFU\I9e N0S% o_2 5@/$X!4CpdE 2]]Y6>gm7Zlwu5go>>Zv'nۍ702;nM_y˝⾗p~sh@zh},[HSSSu]Lto;J R˯$U*R_ᒣH}`<`z[bKh ʽ2:},+>3SX e!.!]MsM4D||8/ٟK@ _)D PM {tg)VVx%cUK0˭V2;)Ub6(˙giYeoeΥ$2fZooe/c~,ķsC"fмܢcT TM/|˪9܈Dpd`L`х,N<GBVʽBbIWY&l)FzҥFKEۤL-g24C45>,V[ qYcjNu a00V3IYeJK t]L?p @+8dIͬj=4At&0d>k@u7V@η)]oƻ]&Ks/ߔL2=7Vٻg]>O=v7|'ſN|I ׼5 ~tЗ _ӝ:*+,7vXA50޽<H$,x=0i2H.|.9ZU$NDı%R;u=!>LReUZw~F*Pa ~,H-4W]AZ% lMJT 7&;[)q!]e"ڛM+ĉj6`;vCnlܸ Y(PW(d[6u&MîiuHY`_*OXyG~4_W)͉ow/:ww~zǿo>|r>g[uʩq=wo~ oz]w>[ӝNq$\c;;ʱaX3I+90 F$&JG$4XlNwZu49-2;S%P,Z "]WT|$1fWb@IDATV)&ޒ-M!+3uY +-l[_y(77)c@k&$B\xhY"ŠhA u3(|j }CSm>A6YM~*pTeUR+CJƯf¥6e84gDS-qp8%$*&Jqh.:KeZmmh1#US'8ɹW@KcNFI9$`NĶ/~]ïWW@SJs@|Cˍɟ$O"S'LCYc[]I?@CVȼ{w֎+\}Pefo @& ¦.J%BIM 4ԡ5 ,b' ~ - ϹoמL|38zQ7'>qcwW<ٿv1{g5|ӌ [\~:ZskFA:౩x)jq(eH_huU@Vlb3#4 0{I(li\xo9Kw`o(b%9ﱖrFo؈Jmor/9bgq҇Itp.ucbDAK}i%JC(au$+Z-LbyL_ Zd,oc`v%lB[K0IhF: 01u^E\uZ3k,a \M *8pQx}Œ?ys@~,?dzzZ6x%tHMn[VU;Ol?:J)>[&" MV괛͘ 0q Y=wv쁔g1d"Ikβul[fJnmnqͣH==;m/Mm92!ٕ^ \ԑAF́/a8YkC^xe:so'Ue/yG?7~uM?(z>}9z~Ԕ>zg8"r/psPG&aR8xoXB.":!Tx^2;<L ꒟9FS18oec]tdޔϢ_LNԍhEg%bvAYSޥ&Ny޳KVɫ|2[SZfH!)ƑwEfP<ƏyK,X :@ [ VhH+Mu,s iEC]h[S/ab$֦WM_;.Бq1,-m S_3D o/0E5GͅK/TPr؆V-6:g_58lUDpҌ3؊lL$36T[~u\QZS1CҜ}jku}e'/bcwveZqz!De AʅXj܄h=<"pӥJ(5VCE@gT?uFZk:ׅY"5]73΢}k_}ۯ/By3k:*,ۻ|?'޷cOر{FG# J_wC<` ^`;2==͏)`G[G֎"Ӑs;ރ䌣[JvJ LlN 7Ē9|(^(\Vl-ai%!k Pc حNx 2sC1]SV)фcEqI 2+X0şM@`Ox-OJswxŠ*#ïD.4XMb`۳ٷUƫh:{d*8пdZ G]v7e`Mm g5$Rt,I=wY&d"=qZytUnCk}O;䗖?M2!Yg˝dɢUlK%0<['FชHFWqdu'tΌDCZ#(m{9,Wn>OXInkULiRM6S֋&"AeLZ) 5̢=F0 "FEqVv#JxE%|tA2 .4NщBi TqnD6iTg?棰eUD]fR&\? )9Nȩ!ڗ-_}P3ǜpܽCw|Ho^ 6tFKr#AC"< eu}IM(m(1q ΍޲A;";riK".j!|:Lu`*7">Ԕm-$ U)tC+!q0Q(@8vt(ӳ  ˔<<AtuW/fxN[ZGgIQ\ 1B R/K(zu.7U殯:C&.6M.ó/F=š2:Qy{Tk]GX 1"慬xV!K ^c+pq dIV4azuUWՇ+ZP(> ˟Uijk4v>ĺ棵&_4-ϊ$\DA,&`ީYu\i^( maeHJ`j }#qbafl9 ҄UMTєD~(lU%iFX㦻-JA]MxѶ(Au+C0~8nݺU %r(g^c%0#0O dS7阰UHCȒ=w*oڒE E*(w2Π ^"F]H ӗiZQ+<$%t :7Z)FIZ;} n6 KL%|AX pQ4ANЃ*laFwFc1p?*uqгUC"F i8UJ{ЀUAAcp{7sDʡꏘX>BSwv ,#m+CM!IA `L0<𢇘dbK:2iT׀5 ,:")G!k2rSsYB$]s{Jphf#B9>S1g M+x?n(J }% }hGBB 1<,HLUJp׾ѪUs^JyȪѭ!_#Z°^@R.034jI.3eHTT5w1-Fv 9CLrsqo:ܴiSUfF%r0}(T\†dT6e IdFGRϞwj#%:[f4Æb?Ɉ<&L4JI: FD@&_G4j5ZN;Nl[͊ @5zYI\vXG;=6dژjqљ=-7qcPghb:HMHdjɄ4)$7@_03VwkB&Q | 8[_,E]qCX EcovI{>~Wq 'gٱ Oo_ypP p\=>͉]HX,((>+Pun`kb!b}ᓾt (t"[Z6""0'+Ö4t OݩkȈ ZGCHMCC ` MP+t/E82+>P{0j^D=w{맣?>@-8ŸOi~lym6?;r6gŐ@ReA]GiUgNZO{k_|1zj2R_svihbqsGG#DeeᙂnQa*_\Z|7[X/+<+'k fdP.;R=\ ReUO;ecCE8+w\uU>r%8SX#B4ԗjEC_3Ce\[q|GD% B#mӤV6 :qJ.Պ#sqx͒$; X4#E+M> 20)I@M@I4:'{s{{[3qK=9x='R~@U/I/ N=Tcr-̇LOO@69vh\Y? S'bKT^Dk8P B%6Ű5Ql^bL"2Q'KcAp8}5EIotL~otlzY.{xx+*Y/F298蠦N&A&^̨3SZYR˘"Cj*. bA #)ؚ;IqB}5p@\y׺XW%>g{g8Y#c#x!j|w[7n@27de֭9W_Ǭۦg=G#/7=ފp)J%U;s ᛟ"ј(Z"C`-sS3iWF= [TR(ntw "ҹt4bSSSFa#/(E}?@cB'AdQH",pLP+,uԕ>@_d/) nHۤබ|2Mȃa76L͔yhƍ(M4;K"%d wy-J82Ott`*7mD4=PљDq$ڒ;&sΑLo)gT@'sNI)az1Wr)@@lwi)S(O) M\"1ʶW.]},  U.Gchn,PxF;Ha|Wv&?1 OδED-'A}D$B 6'ZEϾ|V1oE-jܸ8S[J]*;#0%8 HhLD@'J(gXOd(B 0<͹/rz}5Tu^s p jeq)s˶UZfϙٱPݟuoe~\-ʮn v/.ȡ#GH;|ZS$8Vn-`CO>|` eaI*&{s8Q`b^|.yWj+EH_UJ_w`z{Ǵb# P0g ƇHY9j%T.hԔ]5i) %R`hT+zMD*J*>\m8.# FZ1cTgaL$U2)Rjی=́"7KMD W l*=e4 ג8ItyI,EX@.S5144o-Zct@m@=VyҲl»^]hEY˹Xٜ̉`%\ IY)!x=3h>&Ug$P#I5b븊J L`GJs5zd\HzEzYTŐDcU>Ap6]Pa##:Cej4j:IgHR }&5|(﷔DfV(UdSF*XUѡ]IJHg !Ea. ~5- BWmjA?#Ócc';gr|̞HJ"[9[u7nՇ4ATJ,CH ֞ ވyeRw<[Iq=COE/"[$IdlDXKpˍH Jȱ,B=&3:/h+Y{_N6NKZeG$ 8 ^%Uת@F elwz[W %7gI"qߟ K d 9f%fgk%`BV)W0jE f hI ?0f]j'O IHT}o7)|gs/uW 5ri{5q3VPY\$uYd@F"ؖB ֩VkXSg$ME%%N03HY>(joV  7ua\jzhvbv4R.1a4xdׂfї\D[g(`BUUNqpV+QgP8S žto.qSG4:aPT= I 5$W,2\MUb0}kdUؚrX5.ZC@ %non$+Voz hE[q*<|,\zskXcCљ]gg]w휽{f;ܱo 1ļg[{ꀁSZxN$+8Nܚ;E[F%zNBJ4==mSDϧ7nb 2Y^Hۛeo/:k '" vzc *VgcRXi;͢ϩըeb9B;N5<֫WL \_OZ1$*$zZ m|, &]Pؐ07Y8%q иd@+a5`؍,5̯A97XK:OHT# <,{l-U`շ{ ѵ%D= =YauOgcEv%LgaZE%C gqF\GO'|G喇hh$րV|+-Z11~OA :G+OҵD+ 7'ltPW_}4c, eQ,yDWUѳ?%d%ćP]?n4 ٍm2ɭ,jF  gz1j#, YF6騉~ עA) vb[lZgsaB2diaoȊI;% DnJL2C>CzpkYcE q$J>^Pkϑ#t_#9/ Ih H$2:)oc&R+4:ZŽF#qBNG*ҾWՒ g( !k.z2c6d|hDLMM-JJM`14N&Fz,U)vuę²nǏrMG좖 "z'R,Cm'9`&ChSriu/f`Y!VW* hmt0e'7e,:MCx2L $qX)kfpIDm"FiG>c|ѫWѨO,4btfwGǽ<7;sZ058.pZ-]s zX ,Zܤ58D0,'x!Itl# BVnb48Hk'|VV|%$2E<Q\ +"YDR=M fl'& @4dcN#D/d 0m@5EDdJU[eqrp ? фl+E*}uDIhJK̈osot-H6.8(~"3S+Ð8A2g䖶"p_`n93X/$ɍ&2 ȽduNXՒ-aJ(apJ_ʃ)&?ܻSSSD'D[AҤc]L7x SlT2^K'G,e8MTBF=< qKL1X|!0$8dLOO@P;գd3:sR^@ } = $fj K0frч5b e_ʬaC 󵶋Q,&" ~-Xdl ^*[d O3YG6| YxߍVh 9.W5U^ұ*Lȭ CTŅ[W"WԊ]5ψ"=>U\^HV.fU𬗫TIl߷[WEY`#3"21ږkЁ> FE"&q&EǼѼ 3 4B^B.=ȸqC0X`QhpH.v|E"kw#Eijx֣u颮 pE8A Ur0Oq[d%qq4lfƍoIs%mZJ D "uw 24֑I_cg*z&ױg;71AQfэ,,ScrIxA2% 5a03^&.)J?!=dJ#e~rM ]?Ix%A7^jc;hb4utd=y9JW #%FDގЄ,@mq &Hށ* N4ŦMg󫮺 >ZM0i O5*h 8,Pv"bi~[ovMM ͏wG;`C)/lkb*5.cL@@H \pha ԖPDT@{0OMWV!a"%4A!ů&J+l6HD3ux"Dܶm[`͆aLJA@#Mh& ք,MnU{r(W8iOU@-\B@= 7Ȣ?v}b6LM ѷE j:i \VWڴ8㨥^F$X-"nl≡~Wr@!ЄsRL:&uI48 !M#4bt8ӄhٳ_5XZ=Eqlj?2H5f$5ȰEO%&:RkEfV|R\(Gf7j45]3ba l,.)ʥ8s >1eSч:jZL)I0fU1&%.E5e%feqf<_G{ǿn86392~+_gg&+)d8q#Zi77XDm6D"'9j#ųqJt*@Y8 w:55%omh^8$-Mg55N)XX& 2/9vH O8ҍ)<@w!nX'עj 3}3R >ֳebhP2 .3/%*A[ ΞSЊn) Ri_B`B:xŤ,uO\-l%d~ RX'8c@8 7M|;V 7v{ٷtA̛QM\maAK;Wiw׶ 9WuYGȨ.srP q7e7n+YΈZ/oY9> BmW-.袗>%Vjr˟$pd&~n)/y$:C2VuM(5פ!>/RO*\GÀbM O>=*y$/햣;xOxXذU٥̝amU[旷5 ;=[ X4j|lXn:GWL5n<8Pӭ 0K?P{U{EKU9`K7`y(O^iaOż$~2;5?soh͠}W2d 6Qhbtqr`R2.jjpggWhkH"D s~/Ŝe8pV.ze2TTeVY*rIۺFI-[zD=(XɈp1%TcB &e038D\^~$,0ԕyIׯ?7.v__|?̱5R%F{6+{D7~m7q~YK !›7\s}+)g_ {;YMFX- aN㲢W_Wv饗/OPC8SHIhۜD^b) ]{8m% v+@^iҝP% 5"Y~/AVܷdϴ*k:$AD|v)1dɮ!@[:؆ 9?~ehoƲ/y_YODg!Y8i>MxLԏdQahD>2xtY/̤L4L%LK5LCX0lWSJ k:jHM0+Z {KrA۶mN tj;nN灘+ߒ'tk!is?Uߪ^)Αp[؄8GpDdfݵ>fBXn横 ? *uwmV(\cBg":+:a  *A $[`(0( M`M+m2jd@ƛbI\s@+Xƨm88+.QØ,u/2zT.8# ۈhb Q@ q͝/f|֛jyx_^*JC#{w}Giw ? 8}]O']z^mx6Xj"*qAlmHrb8t>vo!x?y\Ac$lDBu2?rh06??JPA[q'H>A()Os@k5 q:!:.-JZm{R,߬,T[Am2*KKh;_Vdϓ$6{f1߶qt9H4 I3 _*٬vV"E: O O0T^<<;;#d%g{LP]Q#bdPt\c|l@`WlFdg'E˅0)m%ˉ .Ŕ25+L='&"ğC#L9eup02lػAevpX SY30(5e`ZA9$ō^QVQަWT:8A˕YM , U0B$W;ĚL7boQ(06<͋qIblE+Ky0ed[AB`?b) ;2|ZJS.2y* /63HU~ CI 萱5=%)5lcpL6:~ؽe,nhmLh+wG͈PJH1!W%Zx ċ"]b߶j"mjl𱧝۾ޝG?f~#ǯƎn=%/~|ELFp#p;6Ip/<WtFS߂DЄ32XOÖ؂IN 6QOFy 13ju)Y.+̉Cz鞒K:+20AD,Ucee &p- +;T,>q`ef?|쏖{c~f9֝mrk7-K|,fI{vq' 6, CO}YO<=.S0\|3k1KP Qy4Tg/~^1&Pw0h@U45pHB2/8Y2zxJ}Kxj9 %D U!ZHmDx0n &JFf@IDAT #2^R@@$d@h,>شH/ 0qZȗo՟̑G널-vs3Cs&%ܽ{\>Aq!a,ڑfj"e`IM1'D2$mx[8Dk"t pT 555%7&du 6B~EQm1ѭ1.R悹@* ; h|]ldWC@D>: Gj@ ڐI3k&e=t!t[L2# w6#2˺pўm L*t;$813[&Opkݗn zUZU3sC6iJ@:?<6y?~=n4(?) X֓녿UxӜr7i9D{w}6“#cΏ5u?l)yų}Ar;N9deWԤqRѤ#–"xp8tb5V Mjc Jj0YԳ]i!٫(VJwBU=* uׄ2EGd96TbVj{9Ba-)t#g2+>J(ׄ-V*0EsĐTUdAx[2`}?a>=.42㞻ԧ< 5hy Xn%(`L\MafC=D5 n\==LHgeZIŵpӄ;T"ZYU TYJUv$X~/t,e6kU ,aYʂYf13CL K4L)NY۞Ysp{7X=3{}|>ǥȵhdT;pqM t- n1|h ARD PB2jVh6.ND4J՘K.CS9&dGyM*n%*0 lelU=L2Fz!*7B!b]Yg\j 02&|,-|voS5Y+,%@"Bj¶Yd- Ssv0\Daw^U ?j#$LP/RM( &]W<7Muh+ 5N,^V$6jnc6Ͳajfasow23)|Ԉrj ^oc`"V^U PMVUIOHwB<G̉*̈zvH/#Ht>$qBnm;U)He׷\VG8'$LF}*yL_L{lx䍧ûɱ2UV]C:;w3f4U-f]R%uƕH =>4A>a >r% [qfLwգH@tcVD $<_0.C *52delIN^uT: ᜃLIiCs&i˟uѡQύ9g#Y88M|8&D|w˶O3>Y,*g߳OǞXMNV5 ϳ ,ptJ41bKЃՐZ]Va3X$ ]jǦ}%cjij _&)X ͂MNPӱ/ ̺tWO אEQq9~ gDm=hB{b|hx:C@_ mw4t|X }QhAbk_CR+Dy͖L+$8ʻ<*>CC#^]IdA~ˡcmY/FR}a4!@t 1$25cWC.yY Wr2g~)wbbG(f,Bى:GGǵpP".Օ2LtБHtzGۉ%A+\虎z)^T'u$ѠgJ'dDgq+]\ʓfm]bm XWfJ,/K%>oN4)/iy8<>Г0/| ¯@l.{V"P8QLy,VʤE墉l:H̉FW 2!c &G פ83c.BY٦{$ط ͠PN(@I<1T Z=|DX&Vn &]Ȫ |%X, ɥ@%Jrk8 —  sk#&w9616{Hye8k9oy[)9pP߯s}JRk9ˊB-7WCs9_뮻 W]unTzG{뼒> 2ɖS; pq9Vjzdu1j+KԷM?2x}Ӵ84)=40܊!RՉԴ5&C<}==3<0=2YTv>n1j~n ={\b$j+5hN ܎mAD1B1D{qqf= sgwXX钲d#4GT1r^O+"UtAG G<^fO"iB܁JՌR''n# 2~C3Ņ9 g].c,a`DZ"YY/nh5td+/\I%i 綔t_dhf*HUj"/Q"^ʾ^5!e $X|xg>LVvNN Uo8('X>%Y?AcSM,3>XH]*̈Vֿozŏh)dH QĞ}m|ug[7hbtj{ե^jJWJj{٦ox Th5T}i\(3kppE#׊a- d & ʱyJbĊdAd \  hۥ>a~fsk#Ϸjc;dibvJN^׾VmNEd؎z7F8n@כL=09oB"暦 po{]pbs{@CToF\ 5-bǸAn.`ǙOgN<;z==k&d2ГI@aK ([F!<47A'bVBI@0Bm[}wz +꺧Nsԩs_9pqcH d$ Zն ۮ}nW6HUM\"^%@k0RǼ۷D H"xE9ҀO h--`?>(Ʒpm7񁃖fēmo-BW[G>6#Ѷo-,>|AW[I:.A?ΗW tVz͋T4ZXN_ۛ9/,YI'M+d]Z%OUł\h{I"LD͏ul N Bj |tD?C5 -}%%j0̧ekLLw5xݟqSeY$Ī]OիWs]F k:CJՔ2>rElȭ΍!0WN/u,͔ύO D}!ۿw=ۙdCpUCē6naGY2qw.Y0| ʊak|7}Ov3:9pnʺV0H$ڊ)'̊)GjI)*%Xq qg<<fG庂!@krdh@%"\h.^}ryyK^gh$:* %8LBFxXX$gtCkr{קRMBNCD@VKV A ޏk)2׹`4#g>oi`jJ[OH t̴&3IZ*9c|rHׯuW_wWq7ڷy7വ9GEMX-8O8^IcA Bz/9;%,yQn6oYLR>R`yUrEME`BR"'C6:]'M.:$QbZ,n, +' Y̗ܔhsWsYa$L6o '3Wfbww``sαOjpk~~8W]0?G`m, gi~!١PPH$WiݟwyKTGTi]wBH4eI4=+L~pZIIIrs\ u±Ga]Ы 겻skpiD{s`9GZB55r=|#CEfH-F3fB]p>h@$Di }dgB2<rsro;)g>afC>6i?m5lq vJeu䇗_nY-ۡ90bW.< j1&?'ߍebWX]8ͦ<0.pC}@5@Ċ&GhB=9Yi;֘ جcRd?l[\3^3h"pJоݵ ІE؉+.}F4iqKZYaS_+\Tʖyh2Nk$5 Uv2^)UYujܒSd8LB얹΅Q*,dppQS+A~Fq4rd5&\m^.NPdDK-HRL)-I5`` spy}XcYF٫j̞ /*PGU?uV"6Ô0)&ÀQ& 3. iFsLuoWmyׯ`"]@LC ;!#z$^)eΎgcTv;֣i4F7H3?(.v3- {?,Giq&dl$09_1Q2Q10-kQ\[zfȭ}"sOxDѴ~H6l`9g6z[D<~Io$1[A cjU .wE!˼û&fK,[FӂuؒNMݏIv?ݶ6ރWUtB~ .GÜ!V^[daEY54^8gF'_y|V$Mi)R-]в%[1 =%~f#_] ibBMLl1 _]@Adɬ-(Wg[ge8"B& !G ;\2)D4S ubt njS>ga`v4dizU(^9)w1wZp^?&3"v̝|55kl,VO4/x #(-Mbd&-I0ۻ>AGɖq8|&*/`/}.9ASE3C:OSY6DJDRYgYS\9%'kFi~Xi ")' ><Mlx#XI.!JfY@HL kG6eIǖB Rc [)ăfAw*L z8mITp"O!\Ղnw8jI| C3 NFI5+9h~ <3u8Xf;@fΥ)ȏK-dNIAJZwBZդ QuL4_Sq\48}ֶM0e" mAN=dR8C q@?3W3WB'oBfgmYg$$BYRd&"h}FYձ"Q߮E8VE(,Y@ǚ\^KT-gMYlBvg^;󕷋HH\S"&X [SSw©Z~?CzIwz,#Y+SNOn@%鄅Ee QUHU 1!DH BN.U~f:{{. *c:~К0=g1KFg&b d>6(bϢhEsHș11Cn1Tk$p0ǟ-9oU2%+(o}+.ʩu-ў/SMTSִMZ$8CKYeH$loYu$Tܔ# ;ȆEx.$wksӎR,FX6 i7|R{Ȫ?u k t C4ȃmAGG6lGS_s OL| (5G5v^BuDQ, xI&FG]e6?nKǖSO?l<;οۿ~幯Xڻ铍FGW'$# #;G0"ޭ :a+?, a xͮs@TWC`'S(LvbfeNSv1\f>XKDpdؘjFyATfVg!`U(M,zIhw'Zi;s}7 M>x6 AZձOt9 g>2+|5.2ߵG-Z3pF[Y4-57P@izMw(xLs$QDl'r5t$0 m஠4yFň "8bip2~SP'l$T')`!_-!UH+1i>aAQ&xKӁL F'} Bpp^|2ݨ LhqVyLn!>Cq< j,GaB+- ƙ*_\*:Xq}>2k7`)+s|e 2cJx_bHOII:Br[dSFx8'lU"+՟L +KeUǣtP ұaR0=JޘW=Bq׀I2ҹGʖ #aIzUGHh"VZvLᡩ@i,i :Dxie#X Gα4d8 k8.[+^yTedY8B\DMV 4:dUĊ3 (WqugzUgpïxI*;m2Ͻ^<ŲWxgw6~|NKO??}t%^}bCSm|߇,s"Zr(*W'J2[7"Hun] Cd\sh, TNY #e lWhjh(/ݍN'hctG(`v-h(B_$ Gͦ=3[wX”DuLddc[Oo_cvIcmQFGSWEv"KK*.A?bC\32рmB\@AZ2L)˗.x^[وWL<鰦O$IDtg5:bTd6@$ N j߉Me55K#AZ/YK`*R̸,U XZv$#lhw\pT'"ء)H,੦S$)T|tiPK.X tȦBc~DQb*,]*)C\5.~M۸xo'ADWȆ eP]Yk؁4裬`fv=LSz d׹S-Hsʿb7ſV$?9^[,(Ez5le.`|/_Ջ6n`h[w{{w?򸮶.d_ zN k٥O18xAR.c3鮺:ݢEw͟F:Bʌnq|o(T9h1WU%IVu.IvXVJXv@prk[F7Ǘ7݊W%€%ř(T㠴>"E$k ?!+ŵ'YQT5i.I8C~Ҥ21\ Z#@'U*&m8̾D 1JZC2ë{oXF*{Ц((Jvfe!Ѱ& IhMCՖTD< cd4Lx(ҚxZjv0t.4?~g9I M_P vb8#"++bTq@ D {"gDڰU-B0o# WcI^-x0)/٧!k֬1/7ˇTDAq? %Y$r:"EkX:T 2{ ǖ4c)T.WRN5W~'H}   .oIǟ~Ա=r{=dCFm)ж/EN:[ozTڨQ0(䙢H"㲖eX]F[9vZ"}!K s+#oqGG}:6<_[W۾Eo;W.wAw7~r?230YXd kLrs[~izor#{z;g9>6LY**.dO@Ԉ^-LyL)")^p жz՘ (r0S4?Z BLmB="CLc_j]V)̩XC8M[M`X7@lnz&"9 6D4GLK{ |)j_ I"WmQ'^|mXY8bh(Q?9\(CzI+5p$$ "pR}Axy, (&*L>)+:]F sulڵ9Wn*qdK'mqˉA,qqX/"SIWϴDԨ%lezzO9do__C7oQcE*?pt6#bbW7O}=k쵊Oa= p4zduuhwOJըLf l8\"VIwu6-H3Rۢ8d[{1aTvx@Bsdi(SP([#`s%VQ(35zQ?%]I"!?RǺHraM *e^< B_x3 {9XWX>&dg#I[Rrgi.G?%s5Sh#x95QV3`1!4!v{րjsᲤkX\:ۺ榫.d5۞x:6Fi ջjedِ|dY &+a0Nek##W}A0) j(Ԏ^}n>hU2Nl2Ǩhsښ o9t1/9E4sˁK׭];oF?'ëFgq"(g A+(z˱ gTeBr[!1ZI(222xgWg z7m1kesw ">ŗj QİeM/¡("-(jBz B惯h jeH}Ƚ,j1~9.LY4=9 L0IIժ biy8+(j;tC3MO[mnK#fjr"FǶ^Ixs6om}L! '?fW1,F&:r]uVG9  V>O)5k[2 R} 29,,W~t0jW'!mduNތO@ƻz7%Ky6AXeNU9r3CuI v|]W\[vY8TJg%PKX5Di@,H-@.JkwQ:n|őbctΗFiYФb{L|P$* RD&HD @YRNlHQtbv3~@QH5Car +1Zo/hκqq& .K3&yl!*1\t=qw*?{9 )+O~_;Zs/09 Ӓ6nז\`R)NJ˜N3K$JzGRV=G&*HYZ%,6\1q7 iA/Kӌ=\ uShfDH] ܣw84"$ep 4G*ڵvWk@0S<Ȋ (jx\@- 0Z k9MMCBM~MNp:I\v>ӫV _Dd؞Qc4c*Q" mXQְEQE۶n:3?ozTui%\2!|ǁ \gQ7fL0#-pIS7rK*to΍YKd2˄{0+q9 :K^sΆ~l<=qL#dd5rm* %h>}s/Wie'V>K3¯ӗ1_ٹ܅Q>c=Flէ,*a 5tuv}k_@w׽rp<~?۶n;%<яQj!+_}o ̷G+aU+TN^W[b4cce-KL*a""]{hD;KΎVZU PXQYgFGBN0FlU/ǣ٭H/rC.ólHxɂ<7=XꢲOx.FrI˚a꽋$+%\!hW#Uh s3UPȁβoro[&*Wx]^x.T/ۿ|;N0Vi1[1]ၥ9͚}SǪqZO-lTiT>} XƆȊseCwwkX=|\ [C[#a,Jihs%#,뮻b`&LoO5nSX}= {GS]x+n萠eق͢7gMzֳ̗!]Z^qa,ibYSCc>0S]+bp1"Q/y7:xsӉ`*`j - xY7~ɳF A W6kpAh$xVSua۵`JͱvE/ P+  .ar ˞}Kz;t_*MiKz:naGuiօ^.\~~|-6* Fkݖdbb/,jIkCY,_r~Wcn$]aw:U12bB-PjGX{ al >΢jfMCz_{R#WƬ/SN@MN #%kZ^PV/BG` tI7OJq L߈Ifֺh=)TQ^I!^iJ{pzJ**KBꡭ2rʖr`J,ʳ9YߩUR),W/926:8|c+\*`0U9^²)qUs yP;1dEK,d%MKiU"l[dfDpADګ=H* IyiAvC*ԎzYޖvV,[Qs%OAPb(Mƌl8* j.o| vM6;)* @f1-it6>š XdʒJc3C?>b& B]9]$ZNP4χ1[u$$3i# #{{ĠmگZ"*e^5 L`EgOY;zh?Qg-؁c=XS^skdcε֜%$fk-o1U29 i4y{kqժUyke~E8&@^ס|yBzZ!L%L3<˺@p+˷3x;lpImM3^Jx`xEғ)H5TJ Q kL5I1!_s61mx_؏1jVk;InhKr:־HB*l fjV~#7u}rWyu4m3RRI,&hfq Y-V ˱pTGRSX;^H*1=d=&7F:z"Mtۚ}Qn (Fj5ZCu/x :uPA=ҘS wdW2r23:#8 ;ZCl^M@ʔsC9V XY`H}a a6S&A!ԋB*7x;85PW7GL$<9R/!5EH=./EV3J`#y}YZOI`^3v]l21ѝBG>Gi"IlrÑG98<ȾWZ.s7N l˰ev\-?x _QSDȇ\iˮRK/0Ec2 AA\pYVzT$ Ie)]Ȅև`)-jҒieYײ?XN*btYXT'o߼ikq͸*&TSjkRMyNb@W7G-ySљ7PI umC /;t꒪.eSRdpD3%Y xU2XKXM)>.Kx{w ʊ@&@U^\SY&]tcжz_h]P*HȪ_GXb`JO@rZx4VHԫ8 0{\өֶV6v4(1LIRc !p?HM)\|i Kjnk"܉&vt"&2YXrLEV~5_H}bҲUobvZ)%e4EhPWrζ+GW<4ho]m[QA/4Nk U:cm:9,i\YpsHcԤ.RYav>ϓB06 4췰,TAuGĻMv͝ۆ9mz泜x?2$Juf;~ett b 8| T 'pgP ȘVe] S9DDvQ߈]RrV(H^]]<|_, 4+t'*>Ax #Mf_ dBe_Z,\1m-Y,Coo饳m[6ol[رޮbcmV1ntp/ŗqPNjiXsoY;W*fnB.3Rw.c҈ %,Q%TUTwK-a"L~s¨AmMh!GM܊F&&-@.eJY:4 gbGE%uK5c5M?4ڈ u*^맙n7$pbAN̶"iGZ4e>j\i#*(ewLKk.NS EY]t8 0-սTD%T&V@p Tq+mdщ|Wd/ojvKؾ(RMxpCʀ;QK c/x/mt+~~+u],:{XjRA1X;O~>sW{KfL|漗l|ꓟ|ޯ<~_sÏ!2{{| _t?]ǩ/,R{P 詨m9NE*޿]t[ >uZc&Gl P,"rQ,SAA)>00E3j8 6+?X>+$@\ܳ[OnjU+ܪ Ԋcv'^f&X DF N#`X,0 u"S6e>i6 V>SewB^T]KT$ fq4aД.=׶,NԲRuEHpj%YB`aY!8BmJREjRxuЩ$}LEh"HK!c𕥙KL NəFYc;$3<?q '>.?~_^x8;#Ÿ[~o]nšr-jm>W&u2 4kF #x?OԚj6}uqT[j,#zVM)A$k/@"C!b$@MĴ1eGBZ|*ֲGN*dQ̙no:8NR/`w)j&/6{Kt4Ą o-&ʶ`%q}*䪕`JBjJ#j5Nk*]HE4\F.Jf:#۞ૂeGӛ8uOBބu"Ehg[Ď H_3"9 K woMxԬ8G.ӋTd(e!9 h) uRjY lF8p5={y3z2ڬ #9pcTh4}ef/XA'v`4?P@ޤ X=6<q)Hg7oF?^q2Xq,}n2#^s5 !V+իx2_]z/|=Wɫ_ֵמyƙ|<qס+V[5ڭ+<}/ r){uK_*CD+Kj*>5` RiO*Hݝm[vلAhSʾ-#;ֈp1\!~߿)q~a]Gy[wﭷrF&&! i*cv{w GSeJVe?Կ>5_&M ~.=2BoKFs*j: REUZJ]#j~P\t=QũBA$@$ri0ꊊ{ 0%9T(k5ڮ'"ә͕*T|&:sweא]ga& )Zj)^C\N7ɜR*1="㑨qv]y ,QWlߺc~=g|4 +z{oWbʴXЄu ؂MbȘ;ad־x ]/} jD4Uا#*I.Gꐇ>te |yg{Ǣ AԌO?tw -6e}8Q(m1l~ -QxAx‰7'x'Z"K}ȣp![,:"!IQ3=a??!' =B':S}FRI܉٪\TJ˖nŰJvi| T*-ipJ ;kvv"+2&U,Qr1=*j`T|dͣ9X$$6d2@FDޒOȣ8:e<߇QvA6|棋yWi)%NiNXGW9P>D좈Mţ Q4Sc ߹DЬQc p위;Q bSW(Lv/jZ\ܬB]ZL{BY]ȅ ..c?v>~i@F5Yj{V |_ɂ|h6uݖ ( jpm%>V|]uUH%"i'f`# TӞ4=D<3M\I?G?vo|kf͚7 }ncbcdx)u_>!gZ[ںa9 E&'U_A\.ukt#o<ēֵ+W>auhgpC/t! Ҏei}B!!>_Jc[~[Q-ַEa٥S{瑐.xOB+Xah`3Fy83U3n 7 k~w߳gߌCΛobX<.+8K}Ȋ}} ^~z{dk_/kiց|Pmu/˕\eE*uI>:^|?WHq :E|`UWδ-ܧ\(*43H_Q\_i,X1`g3׾5t␗i]a;u:vV@La 6@<%)ApC@.~EQk);{`B& AwTߐtq O|BIP=ԭEJeM# aUIغ}guh&81fQ' 6#ibGĻKfi1ؼ< YxQ(|zOk@#DI|y6_ t=}}z矿O}l# [:]Tm:A=eOy͡[nU Mf;sfiA]loGXW ̈؁Ĝ]^\nIԎ$:|pWnqGr֡9)yG5(7(wЬK-+\To7}wk劕kc5(شHTIAD4)$4vWj#NEͺ<"wO8aKYlԗU9Xr+04TBg1tΓE8u,Y;'}Q-s:h*kf2̖y%KoX_:Eْ/Xa]6ns7?+–M\Dc͛eCvM`$ WZ\ |McT`j*Km@Œ*F*KB 7E T1^=Kr1rs:;Ş: {<␥-h[VEp`td؈27/oEm%Pr%ZATwYڕVN'3>f1>N9:բK"ūpܬ{!z[K^(c |b{L]̠Q50%T [@yGjkTpxԘ 0GGKU*`)t|^˙ݦ-ir"VC3i,P5q#ړan͛3l',4#Ĝ |̏ټcEݝmrT oŠ'3RپM@3I!fu>} bAB.^oQ!Z|_N~]eU>KhЉ"ć%p(*juGV19[bQ,J.&;,EѦ G3֜7R 9 X筞s9[kkҾ}-wi {rgө P;LUi?bj(Cj9߷4p]+grbr zՇVFo\roLMX^^jC;Eh2' H![ !rSDL 1#RV>ܲ\|X>67ջ]sx^ 'HaX% |W**yZVS*RIȟVT˫<L&}$D]RMV߲ zMrzFgXu8:[|YGX"(ZgYH~dICJn}#[*I9_@@0kN}y5k*pxKfXg@V#Җ3yBWŅ:묳JGeq'IDɒ'q \|ʙ̅f3s饗@-7ջ]uţb!mk qMSwewt:CVrGT>"!UdE-0 `|^GVSMU*whBi_ <%`jj!ØSt23N+Ed.l!͙_1ƲQ%at1gSl25͸\ϝ)[VE r|X~fIm[9wˊAʬ;!p{ShV+,Txq\yYu; V vsMb_NBҐ="㲤ͥd"- KZVycWc8NbW!Z:Gk/64\[TifL9`B`eIWڱ NY},Y t HԉoߺWܫ#,Rl(D|lRJ$%.:l9=/+Zt1rJq[Bs:"Xq=EsNe (5}lU 4wroIWK]Ng*#k٧X a#.Mcp$HPHMwQӪgRž滧Tb@fŸh`b<U^I 3O M3 :\ź7QH핉+sAo}_G{9 3#8S愄 É]f,rJ R ;_eK嗟]fֲEY're'j,[=4_tщq'3~K!X#>BjrUFf-߰Wn(7$U("n uEfiZhBʭ,r^I3Hyg2ޱcsKPl6%CKi g*}ba&he'| $ Pj!8C|yh6 XS͹-مT#,RH>SHx&]/vH3ޭ4A ER#S|Wj=_vOkmhz/-ݔf=wO8Xc`Qg Her&te.);] W_}O Gr]B3vFL>nZz>ZC X}Ea3"j*'Юqn̑+/,~W_׵uw~C÷7}װ;vm9xf[cC*L#a1ZT7 N3#f@ | DP)tpP]l{ٯ~)X X-Z;nen iav!ʼ vuUމ*!EqVQtoJiߋN !4lo/v5*g#YݽHX"+6B}D3J?OZ/!𨔐K< TʕC&ˣ1)3)I@҈(HhCA\QsI֊,(H ˶<,WN%N~!Fi+섈HCy #T~%_[=M&y4=Mzcl2.0ؒ.9K ԝa|fU,|Z_L*&&ZeY:^$32H v~]w/솸Yv{zks^] s=?"u';-q_u'X^9qQ?}_gO{Szܴe_痜‚ĺD9ٻ1mdM^@QZ7}*u` 6Z\c,pzs+~LЉ+fۨ_-=/1T<;:w/tmw6ܒ*5KM,%F0hv71?bGw亐|o=2 YfZX8^1FKès_AS=9>:D Q3@#:خ D+ȂB=Q̐VP;Rr%ЁO <1F0dŊxС:8&RT8g+ʨf} ~Ma ~(4,-0Z\UVNsq;?jaU1 V " O(h@3PijX,Y+h爵LjF.ps0\n?WܡX>|~Wnڵr*Y?:P*_W9O)[9?]w.ufSnx˖9fu6')^~+u~kW> ?;{7-[ߔwfCkE YHg:)4ԝ6* 3T~X΁Uܐ\:!eL[n[-_^fC{Gxo~ц͛63$]päXf-?wߵtR.Bgu[r<(d~s/.t]wu`-bvuQQa 5,wzJMԚK1wmlE8ѺqOg)Gu6 G".iqvܫ88qlHsˋ.9?_a1i"a77z{!Ҋ#a0jȾ-t{^{U`4r7^"g#3{7 Q69M `|dpϻO>/7x\{2ּrn.Ff|UgQ7qL[OG⽫+W^OYxClil _E(_B Iw Ae1ɸ 8b'MrGM9cCHNT{- r:~c8)1CN3ћ㈛iS)-m#u`XmYlI/54޺ -^51ͯ};L%˾)54egLG^76=ax+qt?|.\y]7|;gy֬}e]+q&*\7WĽ2xƖc^r\bM$24J^Ѳeysj--Bv(ЛqȃGЧu.G[+4@4.Ȫƴɟ{31$0t%"Fg Qd-@<2_i`%ҴS Tjg휘XK;HDnΪ뮻?!v ˠBut)yBFM[|]bCPb C>^V=kvb+!谳_ۿ??]w64o~̘1oC}IMM+_}_>YO<6=?Rq:q<>n3U9$p%贝-!y%gДL6:mA7vw7I!`Q)&8mF%\WFxT9ӓo nc< 03N$4,R3Qf^o"IIU INoς(W??p(k($9I)}_4X[n_nOʁ7s5ʨDAP=U@{ͪv_U^]JQ> +m[D_+]988i6woM=>R<;ְ!]vb(d@T4^+pp|+iPoB\WWCkcƸ9qMG9x/C0sQ&mN{ɋKo6s/b6V' g$\|e8[M;SFˢ0QQ8i wm l$*V,u'(~zDuaM-J =&wxY$zWchZKGsWd晵;\e6kaT!@E=K=[XӔKso.(fjz6ۂFPHB@nheي?sWb: !d!Jc"W4n6>B riS^RrdV*LuOy3B"o!Ѣa^zG^W_\>q6c$[36:FwCLi9쐃<6nhiđ:h]9b'N?y.:&Ms o/^EP_t1E'YxpGm2K'6›|;3\( ڂFo>s*2l& BMY`'f#z/aTH?3+DÝ-ݷ1;eH++6ch>?ݩoj2snۼDqGΩRhwWAs)m;NbHsضivm4o挆Y33yL&L29LԔլI{:2_L8_\3:ͰjlcH.h@)Ɔ?XK*O(mAwPvKo!WUIИB-2^b$K1ϵKJ DKgVLVg@XBU@(Az!PHg? {c"1_>=q14YNl /L=8[!iB$+Il/Ktmx|aj✃XOZĺusTm>~9kuLw_ߔ$+0  G/E'T;|b &b|>JL8H3=n9tkW_I[ZN[~FmZeĸ3НNo]_>}s<ͱ2hSvrv;{GQʕ=,I>]=-n_d{s4'EG:بRMh9 bW*RN5۔ Qиu)NY!a &]rV-5ϸU5.\H AC\#0,E[- nJ1<e3XCVUE!6F~e^Jj-#݂'r/Iy)6"ѯ򠍺'p[d Qt嶳w/>={;=W~g^ٺq_7rۏy5oWN쐦~4 @!a'4̮Җ&G6 Iqrmϱi3\ر?{ػ w;ݛ0Tg:?8CW\cg7iju7{Wi~CB!80WUkA%lB`1o{SjV. wCr1]X8rS5,!TH/ObK+:S[n4y6 4L<Κ9cڏ|[wc/|sgח:fͷ{7\|SE]Zu:|~٘[.O"n}5z;-:;ijҚa=X MmS^tkuD0lo1;k:%'/9lǭ5:fl'mJs\]9΁"*9ٚAoR*Ib?Zz9K4̨\a4|1Xc~J3"\P449vT ؎ aP=H)@ *VtzU cS&;Kfyܖ[g8sp8X<0;ytůr,7u񫯾Q=^zD9RW\q[V/ss{>O8yZg筷JfLv͘d9+ck?m?OG͘xǯn4I0erm_ǥM9~)UF`(}zRqAv%B vZS\SH9\Yރ:9P=hj1ok]~ S?mS6^ZZ qLy:6,pnXjB@&q ,+q9 v'F2p.) %$ ]K>s;W vDs``TQ +Ɗ9X{٩4uѱZQ@Gp?3<0'ډeX\v_9ȗs_+ܵ7Wj̖7}<g3Xv­IAM̭i7U)Knw>|ל#亳^s^eqb{mҸB]XFVwSq(tw])D ҳ0í>vݺ'?2ѽ%,`OQ ےk>e-ytEO"Щf\҃ӧ#A CVWԳP**D? fLK&]JXY|Jg$sTde,Oj=vnXX!@\+p)fh*\ܦA0i`"oPDj s6r U(;mz'{3 fWf7d* []TzhS)y+#. !*\bY XQV }= x[jk9yf-^WC9t&6cSus5n՜1-c|%M4^K``F}Re +zдy7ۛKi:">(779̕y4md|/iQ?3?oPڤ-歛|xU_IJEV _BQUtI^׈#I狰iMLptF]h,!D-j %DeU-hWZ*Lzk%PcНPMĶ'О"$-Q.h-q9@ 1U(ry}ֿh:fRr|:݁ &KohMžQ"gXB)Qp l!ݼ51VuGj+﷩RrG)0=Yi8վĤTbHU* `&.vRFxR\S)uUtL"h-* 8;+ N n՚<Ĉ77eԉܰUO9m\~=tkUcvq|wK[8N3lgg)U pgH@({ ֨U~X` CnPJC'J<9j2<B!V]Ӻ , L(.2Jo}B bPJrK,Ih0$fUeʨIPe*]J4,<;RGdXR=TGzBHjL}?!3/{lb .t}/>ՌRR2V;#;v2 2@. ffSSYH+7vj]ɻ m;N=/֒硓kG@&EZZ4Giy ͻoф吔5SP.&.&S*.:RIS8(hs/qw(4F cEshnM'cШ 0@ErfDA&df:tu ^mDBƈ=8$G'CCQM}7MXw w\2ioOU2Uؼeֶ4}M=ݝ[z]wXmUb|'MuC>Qi7ne{^sV#|~T$(".3ה7DXI:$ytUPJ}\I`FM@ʗ乫p48J(kOƟʐs`68HMPqd |;aS@10VSQT4xaZ# * Wƪ;e{vSছnkg?sUg͈%}B@I%#Zb1Lt7#L>4~ӰgT֯}[֭_r'V7yDroXjYg?)KNH\o^H{: NȆ$U,րjiz_5ΣXŒR)71jZeF7l|K]p#hLcxFߠjFzRqKԽ~o^VL13֮}G6}Ys-`}=SL5}}kr2&&Cřuu#]+Xp/jm-mtv X_ f͛G` Jp F0 C*.Ơ~ŽEXX{`!8c%e(#diG6 y9nMAb.R <!qTM, $ eD/W͠I$%?ץE\n}9736U\gxm7]o9 RA*=7.(/ + ֕V)Y0g>Gxtpچ9I`t}J4A&h[6K| WnzZ3/Wĺړk]=7~z-3zo]uU&X=fuskmuYSܼ~5W^uUWo޸)樴< ç)`]EۿĈ5@FCqAJcL&c{M02ۥ<*\|#(VXT>~w~#??~ʗ,^OruNڵkZJ/X;{=[띏{G{u?ѤݕklYyÏ-6ltۭ?~pJ]wݥĸKpV.mM VS[7ዟ򪫯Օmm7?믿>WxQBaHte)/=K#Ӈ /%,/0>j XOy+k֬x%Q4b=-~KwX) +U4JTP8ͤrg cE<+F!奚Ί#US755%_!(I<#[5 Uo]Y(4Pl$iiZ* ;*A)[ ϾMP4FK @E{ ~:tG>]ts9XʲQ ͒]oGN^0uM[W?~z/=^p!n76<9=Y[njsjäv4_#͜s3O_wSUǎ -Dm"d2"&>7R_'S"4^P4_鈜G6jJإ(T]fB@bo1Rr2|K'c\}o38C'J/_~Jxq58XW^ymH3yk{w~ 27e͍m~7o&0,8k<.^X[bҹJH2^x$Ah4O8 ]6;ť8ʊ"bu1 ׽ YTxpRϻA2P@]#jBn2RaQEUz'$7MYj.f.(@O<^蘫/XOp,:_-j 5Gt8>ӮBǼ_(xvgY{'?5,lXrBׯ7[oI'ƶ!ѭU6q8_>U±ӧ\ 8e@uLo⸆P-﹕۷򄅸qơ0]mϻyDƤ Ezv{V^` QD4!gR$m܃Qpo$PUO~w駟,Y_(W{_:8\bS5__Gyܓ{NG߬3pkc73mi3_ϟ6+e'wwݳ'5=g.[׿q衇lH%< JS酚ξ./tu[ԣ_G][o7g6{߽iƌYKM Kǐ{N@P>0KØEuV]JYKV 4{/``ld02Me13GKSW&<.ruHy>Cahc-i~ oXck ˦Ϝ/T*ph"s6m17EaQ Rp2 H ɥ 9!G>*ЛĢ+lg_Vʴi$a%} PSHܔ.V4RR bv i 3XÔeEH =1(1؆ 1!U624AzH۳7\˝L3]Bt4}w5P_w`B{хͱ`ȅtXZ dx1)Ev"yp4y1G_z饧z1w=}{m(C: ~(Ԙ;y_?='?c3|̻z|D~'Zۼ}≳;ٞX:ak /XKn;gSko妶t8[:ӗ^mڐ L|ՍƐ @#AI`R}J0Ǜ 2Ãj`K,bxIo#e Rٰ$1yQA^3ǣ" /SY F,! 2Ȉ!!3[^4ސ.0:{(zƴ(EG3rK4UĩG~^{^k\zT?zt ZITj501gzQYQk BzڧqЌRg-!9li-j!{"*}M Ml<9>BPZlBmknK.iK[,VF}wDF@l(bرݏ?jK|̬cfu*g )3'wif↗#;[ xF}(J<@\$,X]`(+X*71S i,rgZ,VTEvIiȈLgRJ,{B4V$ +Cr4Q`E)3'mS:1d1;Κ6 ̣-)W? nA* {{#(ia_k`;+uETi`XFiL*0/,BcAV9O<-%kkmp) 4}ߞ?>c|püXPPSg&t' :ʡ[:MXGv:H;8sӮ~bz6n[؀ :_dh`8%P?1(&H㊭ڋ&nMVmFTAَmcL8k:(GLÃ{M*JqIx޿ UrGL}:0Q#"إ@Qx 02}f\B1 Gf8L10u N, KoNϰޭ͓.1e % /Ja6m1oEgJslQ} I/[#U :o`b RˡdsxT $px!Y&RC.ɩE0ΐV!l2M0A9¨KI@('<JS&)E!gT,8hK܄f ٭-m]cg[tJoEì#W5E ޓƻ0\~_9a^'wr >#ѫӀ,, !B 891 cu) `4lG3KLbCG]S{!u:q[**q~" M-c5~:Ɔ1u1,ǞU1-u(s<"ᤥ}9{Wz5wEi`h+4F7Mj]n309t@Ʃ5x\x,%3r |/2J㢗lޙOgyr6G:m`8'p3 z ڙp6 BH: 0IڷJ/! |UȨU@ q@tY\ 9mڲßit-nl/ߴQD]w8n. DK5ǏvhzzjhH:⯳a31 pXrr I'$X@n*B @k B6NEFHu)H_hYI=<$˸;QĐ8bjd`qI$d -W%KPTw *>od %5{y L*#GpAsN5to\{aj蚿\,J!^|atPcsBϗ 5uwVݿH m )CFÉF1#j LQR6D-@JALF |QRlL R. s0GFp\(܂uiGɁ1q<)VAX79! 6㵠doѓ.t|)A?U=ɑ$"8])ZQ %~UP6PCd!SI |5c)<`#W/1$!88_w ې|xvĒXך"#ezIuׯ n&LgMGozՃ^\0\w> hֻ^uI=]뮻aM[lf47)j>f2ghظH+tN}t:h]Ì::a65pe'.^"&$ Uu5 C \F[%;ʕ+a:}(I֘zxGi>$>$e.Hcj>>ukSi$U4ur79lv RoYS\Oz 旭ԣn6]d s GmBf2ꟻ1LU0YIӬ쑳fдX&W'Vmi[^I<fϒYy[oQE^s7Tgr7BܵrOLcYCKP"˖-sw30c_|Wxh <Ƿ ̙Xzo>C%HRJd5Q VTc / Q]"X[=Bb<6dG 1HP+Džl,eۯNn{;iuY^YM2mOm$/L=1J)`R$^I=1keaܒt|5&,2K4fUSHRVYBr *#&O7>bs|d@lHLʐ7t:$z{0ܷEE^筧+~NhCzs]B\Q(:/|#[y0)M&IgRY07`SUrMQk' s` &ZлR.,RG1 n#(\"IUdaY*0T6V2"CF,#>0d 2_0UZl\1F<мUVZ67Q KɛuKZB2nB-u8Ʊ/}AgAs+_`=2ߏra-\x$_Y1c[sOs\yI?~!:52 *mUh5lnP3XaE:v-FˌȖ6=TvY7aF#I̚ecCc\[( ,pe01nG`~zj4_>s:W~i2'L%\b1cL:u>g?qy""APKnNh0 Zeͤ'W=@~4u2l T!sTzN0FfZ!/F̑vlux|)]Jy]rAU (b~yb(bPd/x-[O ؃Y˿p_c X<<@h̛Έrjl8]aXGp!d%BTX.öFLJZ;&Rn\!sr4FSoU#-dΘ 6%⒆b" un:ύ.YkAp`ۻI-kT`LeKE,:[8:GP0q88TLY8HżZn` Z 9Yͻ#8j EYsKL o>_cy<'8s!Njf3MMw 7i{}xꔉKN=gUW~gCgL|IS7SogvϻړO>!~+jVx³Zr\в0!Tr5\ Jo%l l!OJAdFJFRPVq;b:'k^IuҴF&z&M瘥 1QlUOA22R\XX.=2X 1 A2T;::|A Eؤ"X𪹼lmsC}10)ްP/۰#_/?A#͸xĢE6l@IDAT-_KNdfvN|Ox{p?|+-߾7@苨.tοS`7`P p@5ieBab+FMt+T@vi%ksȸ;NwhAWmBDrEmV XÐRټ(>49JCΝͮ\$*((!,b.$ ؐ( O"$5XAMv£NH`5,|[]}u}ۗibgGyCJ~IՄφ0|_uQjԎ[KWx"67ӹZlѡ,[=) a|DoG<Q*{BmA>{\'N#Eߤ)cnH#Fwu W$OkS'be@.n7>(8%=;S+N>çBۇ>u:Գ1mIkΨEua+tPSz2.CFTTl)Z(]<q'.\ pp<00E6u$y>9ʅ,ŕ(edc&q piԚeHBVY*çkVIk>fIyY+ZPoL0;BnDOdݘ,Rxlb ͵40v-Yi\0헵񔢥hPU:ۘfF'YKK mM6J5:m6,ZCӲ@r*CA7qӰ&NH4rǵ5gHgb;Oٸv,55t7=`sO6aYޮgq5 i+dI%xHIouSQ-v :5jb 0W_嶗?nWGze8{V\kX +-ʐX@{U&h!T %>׊RWz.O!Zmꪫ0avoLi0ΓM"E9 p!fHNQ]JzfeCkU"e`z =F˵3'1 +@ I.{QĞl`TnD$$ԂA#5⠯3ڍw9q2ss(ClmMV#IO"EHXD-(B$“Ov#x6sի!=)/|>zc>JMxCnH5-",ظfaњu7f-Z6dqƎqb'v'w[Vnذuң&LLOHG3h87i_~VZe&Guj`A͝{#ےF_E2C{>ǍKoէfR7<6u@|.Tnut>EZfJozskϱODY!2l cxnbV.i{JxLgm =SdIxLbAˋ>>O.-v Hҍ𥬂~P8[$?Z= yE(`ΌQzY={R87 >:, ZTڱjN#s)*MhH*^N>2OJђUEx8}ReEB|v<8-ߠ|0栯38C.Ok nwͯǍ޷mUGHob',ycfʕ+MxKo޼I:kw6x;ؐfCKr@606秿r+O7VlŨMD{}֮#7y94cָ15Ge߻r1λΞ^-hє5}QsKy_<6mCn'>s^ֶtCm5g̙Lwze[qTؽwZ><Nw3_{MG`){1se T }vܰu놹sK vKJr!4 Pfg9O ڎrmBŸtJٟ\Ùo\W m?hKwc#_z|O}7<\'wKͯg__,>n|~Ɵu?󎦖w7rk_|gjpQÜc<ÚTu?k֬-*k p`Nj] }雘 /6 twttX˃: Џ%FJ11D1D)`BKdh:v[@9U[MIي p5UbF )ْT6# Ij0nB4B`$3U1Pܰm i+4.joo]&`^Z^,[ ݗamAeX Y+bv3W\90Dĉx]NAmvkLU=x6J26N8 9 H=zGIX L nTaJo ᅸ!K0".ƒGChPmڹN2wNE0%)a9aE0Ra|f4,CK!1jU8X!fqS r9"UnaJK9G#%^T$J)eP,j_vJ'RĶy?x`lH%xfgN10m"֦Ni̧}?;  [ZniɛN9u=蚩ZlxY}Zdg/ȣ:N8a捳^{!ˏ[;W;bNhf?ŪWmjǫT~[]S9!j>?c1ˋ":尛}3@Idm2$$ d% 2f[Sʉ  %".!zH|vD0~tCrqޑȂ- ; pp)K\l/L=L4܂p+|`pAPr ǔ8DU\`$3UR]ICx[M .GcRw |GFuū9|2V ۥ + hb1!/;(H9vS8L,mm:8x#,.m|Y;+X;#ÎҮ} 0t5<k,:眅f.v _dݶ^~1[ļV[+iOX~&Nl9a;4/k%Xկ= 7RHPs8.~$46櫺7 XpWaz%.구 ☩b@D"5 ޏN*-T뙝,ez,];xlJ}p.@81$AlQzWczi<Lp]AUM( :BY-wׇW*((%݆/R(v:.ћ1u0BvD  KpGL-QX^Pcю"5. p$9 %Iv" Jp(.C: & ]F8@rb"$xHQ!*@!x܊@ 2nJAk{(&6Bf4<4ླ*kV´z|39M!~sbT-_gv_ɣIgb9"x*ŻiinJ]N~31Kظ?ˮ=^-cEʞRSު:(Y y!>dykYgDJ lj⎧䐫$dg:DW[QV+Vp;қ8<'Kg7x:_O?tUcfz%i"c2!7o{DV=T[@̺2RG)'y`^\ $&UQU)|Nڐ8j84ZŒ^h Lm"dRe-P](Fư,c0 AP#} RbT$; *lUN?$sRL3hLeG-vzy^t0y(#h"n9#;tBu |,&6et26|Cʗ.bd?AZg!rd+mnդ٩,ϓm :h:r TU^\fđ!Hvhx9ڼ}j&|D7Eԧ>׽uP|+_9+?ٌDG99L^h߶V'cu Kw#3%e7_c7|j9;3KR}-MD*Hq%Ho'tY, D]9*vC\ej"SAOc`01xpSG.EqR p-`ЋK!!1C%rB0 Q8]bX)MFkr)Iv@]J8OQ*iq7e{8q5(\cR-Wٰ4v!МP]M M&mrje2_szZf>S D)c,%IK ]z)r52Gp. ۨ|\ ζybygw<-SnèbIEF; {G\rga`m#i{v 8j ;>1I!W41&>DZ{K^{ZSS`~W~%{uѩ}/W 7˗{w饗^r%Z/zX;вEMv2ojR1u}voTNbx1KG[@ dKLC-U!8UwT19j \r~&50h)٢1/ոЖpJ jt)'$nACO+D* qݖa܇!F xV(8}>x}=8 yEo;7,ӥ+LRl ` jM? =^Ϣ`E?[p{؃vM)ʣa_[31'%1f*>GIJYyR#~@CSꅜb+>ф+]4́%>I'Hh.sϹN\PF/!ɹ:si8%sP:3CHT+` ӟZԋ3m=p1JwJ43-{s2dFd;uI#q>I&Yl^x|hr9լǘIWzEm|+B@; r<˜P,^&c?̥8FPJ Y :u帿ftxT}'<ʍj _':\5lS8007c3/ˉm ޔ2hC0!IJ-h5Etv$^N6#JURϦeabڏ0 _=m*1%Ea2eJ Oq!]GT.]$Z|u056~Qq}DHD vko09DPbF} deҡ#=;d}eҦ(}DH~{Háv\(H9By=۔?t2##!8 ]7,+RKlWq$؊QJ}r(D0;E&T1(nhxBU҇8$L|y_C'lb}Ϝ W\* >ĕy{OMF֋XYuNR` F,vYquȬ r 6gr0&ooVUY<hxx0@svS@T17A%g"+Lu yLٵI>STǦI, qៀ< Ah?7(~gьfK3jI^d-eo1 H $/^#@bL >^ !la7ւhwd˲ZFf_6뜞3wf$ٖdIѹuTWשӇvEDMxqmʓKn4K!݊.Jokj#vrS.90R p3Zᒑ$ISˁ$htY 4Ìs +`ͭXG6ɠJ (A DbTg,!I"|'o= 567+uE %dA v )t>m?R>M3 oϻ*]32b+9_":isMV8T]0 q,h&X)(4UC=7C}v$Į:n<049B^TL*Eh=[CR0v_t,!I ,}`Si*yɥRÌ(aZhT!IrEHbQ BYn4[#Dض6J/ן<\h]0/3SC~T),*.Y~HD9t%7 `K)kNWK@GmZ0d.k9kTP9.=6}#V0ǛF QK V׳IJ𩧞3(+O(9T9S lÝR$00gjk3)́ʊ?clz A+xaeBz&L(t׾ɥ4qE\+%^sb8$ !DA4ϊ0!43$Cg/& Db`3jDOw&f&l'bl16/eկi}̕~!?BA /3NCQXX0b@(  c@+#Wkԋ@@^QKMY"I% l4D Sբ-(%Zb U է?i4M+//Q/*78WY,"UBG(*gpePr a;T sRU 0 IRzSO ~]jYnO<-e?38!}E,7AtPHAFF2<-<̯R I#{E#A ĺZF|%ST:'G'%ĬXpB87#μ ֆPHa5{"pEDʂ`抣g@zUrzOr镨,l7~ZdLX$FQrX( :{ 2j2 #%\9ik:5Ӝp03G)H&E%ͅx43ΙF|-iSCv1KnsXE_-ۍA g X]D<_e(bC{@sp y^g.[3B;2TvUG2 ;rspT{MX~ǖ7WYg ]km#t,*%mOmm>5IֿwX>b";m.Ta ²h3v:Ĩ=$MK5/RvʣQX:1-bUB9\*BC#bA"-8@j-E*9SMv0Ùs2rC^/ G)j jp־xPӢ>Wi=̕QrتRCXE\ 21qW_K࢕Ú?'eD r $REc|9aٔ8kNb)fЈtfEdROEL G;i7(~7IDDP+Dȍ! R`N2e?b?[P W9=SS2G?\yML҆O1R$֟Hzx5-5!f6eNu9„ffP L|jai楻K@MI Ĉ3 *ԛ@ 1-:rs;òڒmY,ܸx*NL);#!K>HQ,wƅy{#/"Kfdج] qEDA} BXv IU2N &_sܗv"@W ;Yϋ .3x~VG*gN1{.pݑ M) LLpɚ3P`0HYRx+pXGp O6@Wa~)S ?CƛB_(V{H d"[0X j= vVa>bnL':A()ѸiӦ+/.(jմYy ǚZ" rСWX fSla*jz7_(̋O2^s5^\93 ෹CS.ʱqh4[w)"0,bu "OJ;_)gw[b-rl?2KL⛆pRo~_lHv,Y?drﻷ$ t|s(7q"YH/sꢌƣҧpDL{ve ƸUPMcߗ,&rrd %,ˢEd45ì]ȣz/*@O_UdZ4+{%-(W?GLzjgNp[ 略y%p!%khg |lwgRa޸?f۶9yy ]=@VNQrkjkOܳ#k6oo.̽ګ^۰w iq#'CT|ذ7,nBxfxJ5y܊ dɊ1c2-&Glkf]`$KԜv5Y] PՕXO|m7 +e oپ%X8**>dBp*/;gt60aGIOsY >{%GB;:sLcHP?Fb0]9P ĥƜd]w! %֎7VdOќ^}w/k.,[#^Gk$am gtPy5 HfY`Ȯ(F-٭O"Pٹ`ȓkM605EedQy0[ īH]> Ȟ &ը6]gH#Ezj6u7^,b畺T^Aַݴye'q͂Z䂖:pVBx&k/5Fk\ n8'YG O8=t0h[ L^l ON/Qsν7)g,*ɕLg ˗M}(+u :Zs KH((ʰ .T Dq}2_dblU0 L M eiSY%8a# A1fn0YNP GMZsp̲xLB啣F>Q~1c$ BΒo̱(>רs 6@Xdc$[֠nmHqc%Og 0g?d\;3%r%̈́= \8][f׮]˷e1@auul΁{&I(xH1]/:oE:[TI R γxKDXmefbdma|)0;D(PR^X Vs%ČD“b(2bg'BJ%e?_2gU9%ˋ`:shV.k.+C=)}*#Kn6lh5Ӟ/>6OXmDT0]FZxDyL$ֽv݁o䰱0}S]TgK#?`t(]S_[\FԶbxyq^aSη_{}CKGk47rb16l?Y8iU:5zh9Ł#bŸ"0hHckcGMΎ1*ˋGV5;rKطe e;kV~Nae_u2!4lmJ}oGZk\ә=|4s'kqQ>paf&TNiimk"9!_$'M_oknX>Q|52`.0 92LRX9*y%a^0L;WJxG n=&U: 1L'PmE!&WlhGe5:+xq Y?a)),>|8[፱lXdgDDFdg}lūxfsg1cKyPQ'NHpu&o`_(3M'kO1rXVi_,R_w>V;TSWRpF{)Wʘ suaFRlL,rnݶB=^n1w j`_'{;_>[MHߓXkw*BhU/>D&h9S?*g`)C47d'gEg/$~Qh$8>G6%>ٟ/ 'ޑex#@o.3شk|*t/nlkyH777<#L޷ߔStPϳA R&wQ?3L1^lk0]\6`5 >{9 o0uruɑ#Ǝ'&:;B1*΍~vFMPа#ۚk4|P[u^_=yM2hHm;yz!|?7\:tݺ*?r|,L4ڇe0{Ϭ$ }cFpI]pmϒ n 0f-;j[O6c&n)+~_> |>Kx`lixw__rڰaۻ3׾5&"bw<-CooDȘկ~κuGu=#5fL%l=})seE#Kںuw+}=?׾2s֬'.^Ν5e(;5tKKDx%wAm0"rJB\%8|fao뮃<>% VpSW4k*7Jc_,r֢5-RIґnj*f*o fKrjX.-oPXZI^ w=]Rx&5U ܬ ]WN|} 15?fK}GD?0M/NzY_xx5cD}H`T8KH5kmMt̺b:;Ϙ9|o<ʎ M=^sh{JiTb6_3cMUl>a{CFjI)K5'O?n<&f N+ZxTGV ILɾ(bPI)ât8UPSk kkjjiff&O\J]$>q;>mm3Ϩk?LԔqsùdЍ0h H&sA2k$Q J~Z6dGQ>C[JrfDYnbSu}G }y0yeӦL8H(|t@):ps;Q1Vו֕n#|q2|ЈFOhm9^\R7nP,a_Yf_}gNMg!Mg$ߥ,+eEW2-V~i?ECG<[hT.yRu\ҭM701'*$?XM|Au˘c<> ysī;x ]03l^J)J+**~!sX%"ȁVdk6d` 8^XFmD8+nq;hgF'qTnrS ʡ9ã`,%x \ILKj)ӕl0)6u)RS]pq^f5-8S/=\&{P^қDay,OٖeqHX:6b dޏy%`5<"/*jtSTQRt6Й7'`cܬlt#93ќ,VoYVI9gkL g@ s,6DqS/}շFUt38V-!/ 6MڳM R1zhb,ҩa !;")%iayϽJuFfU~oU@y?rG؞TNfH]1&٣]Z~5LQ%;Z1+x >PEEŔ)SnѣGCSŚ*oIC݂;;9P>| Ӆı-Z7c^?Ç[8[d,YBTHFۧYxuס^xaYeQ2"W:dH۩Sزh h9ɦ)}Nie咸!(Lm-MpvN" Th]4MlȄG[>K@eBƌKeew/6Ձ*i2fߝҲl) &$ͥ5p+Ҧ*˾ WBzi4(`ͥg/=4&4$.@ aKH_*͆ rA#gZqQ*UXa/,|,dzH @ČX* Di^A}ŇN('#9SʢL=M6 eDbF<` ~=NXȍAE&^G\](md> 1%'rmQA6ͫFcCd[l4:x#gNo{Eq<1GK(?+[q EAu`tH1V xL8ISsDjX(' p B&/7yKR!7'okiaX; B4p}x"nl\iӨlvS._HC7rnbzn^l|-WڊV))4rxWV[[+R-l&QNW\UH#I"dY{giCyI4(e$Ρ}]*)QfJ魶<|xM|H^nmMm+@ :h$Oq`_ C܇(:<DXx<"% p<#)xp"#o*"(FxB<89J2tr& cYWFӫdзfY"4j?eVˎ GÜ)Gb8mHʷ r!3(?*gZ 5Ex[MֻB(ΙKôPST[OE{;r?Aeiԇ4@!criയ!7G@ yz05vD\9k)& 1΄1̼>Cg7d$]L^f.YtT-ڛ JF DQ!Lbh*xco /1LD$.aEr j&!'OqM<(#˖\28۶@D]PZ/C$DrxY{i$y-`pb {5XK'[RP,t;+{%,#KkF[[%V2K `aeݧd iԈS~ǥ` uDMh¥CL!hqȠZʈAYEOIFQ|]'ۑch a]3fIvkīBQD,Q^f!&(DxTM-qЈ-mpL'4.K4t[sIY/ r\y53c0*H쑯I/lJM3DCAcwWXzkzi&ДN P^^Nر,HWg|&`-+܁,)CJ :$EcٻfѶhr#/CݔvѵHPHStI+nZKLi6EF647ǙT ~n)%9 ;&9u -`zknMr[|G|9 FH9+lB]P9Tz[o4Khh Z7J6߁qO8S`Pa8ѼtLzL̎]b]_@V5/ޒ kIu4jo7śr]n(4Ϋ((&35*[4|S"fyXHcD!yY.s,NI0+u(!vLI(e<;+0n1G5<㴉<c&FCj L. +/2Љ^yOz71cAv`Tm|koS μ$&j߱:glUп wqFe˗/g?5"Y9i04Cj#%ئG}k_yY6fb,v(-Eh[,Myռ *€%`.@eg(>̍QPڎ(Yo^%b,MRνrMPLzbUꕠz6$9ëu.UD]k/=z+`)%vG;رۊ;!)[["asǎh[ m%oa/+ P:88y|4g"v K)0d Ȩe|>dA_dKɾŧeqؒ:Xpc0?x^d֏i Գ},Ż_~cKjB}A%[Xzak\oݤ5.tX-eKc#|ԐUF½ܬM0IϭۄsHAPJh0v`X"uLTF@+Cī⣄HcnY,gY8'S`yqd-$3}e[+›:Y" 6 s,ץmYȄRn4R viM@)ݡ#!v{ԀB)Z5* ш|_R`G{T"O0:e?I^6-;Tmƍqnq>OH%S2C.ˆkpɡHx'|c 'sPu N<$T:2u3|p~e Ss=8U?0'>DrF9xAaFQ.( O 7xmF䉯>?SlkgϞe˖d\|xs>O6}W W_Mċˑ#GiB >v(Le=^&Ԥ>gz5Щ.QetuBOVCE̛*Ing`˳g*&ɲXZ)mze{F-W1޼[r'B@@ol'z/,ӛKam͕\} 0xHݼh]_߳]g̊([3\͛T*aΕplm/ Q OmAgԡ HJb> -f*ݙ;bcyWt-/ҎmۙBYpՕ=Xqрuu}ʆ!_=Ebl7[of?4~K/EьP~G>Dk]xkoÚ 7|Η||9}Y o07꾪%M1.eq틛\RO g73sɟʐ~NRE3O}W]uҳ݀(\S"ӧӒ%KƖ.]W PኡU>,a0(W_5yj&>w/ [-|HV`x7#,94[֫PWת{I3|8>6_ `$=$<]",&oW Sm7+^Kn},6{o./^ 6@dgc#8p2ngds(MO/ 'xA;AJ2b'FC|NmRKbcEc*Y=EZUꀱRo# U:_JgqǑ ~'C&tnt7+ GrYo7^oolo^]sӭ -xG8rsΞo<:|ذ⒒o3 N>|mW^y_ "Fýݫ-`peXehljf"l,9i.slŔw&91N+*toxÎ;qF|$ jB D_d)gV '|{f:3w,O#uO(t(B WiСL&G)'C1?r.>%Ç+c! e׭=\Et~"s#ϋ Qo5&|(Z!<<{2eM =H9Sf.>½->RN-Q+d*Q+|c(ID/٦Y[`HKʠTK8CiKN);޵c'4>gWXՀ`uV Sv:cp,W{G."9eU44w9"*_Ak(|v@E*[:j9Wԟ= i'͘1hte{ by>KΙsży P*&׭0hpCcsUG^xo #,yXΛ7=f)!(l LH$2FVs,=z dj. 9(M2^Ћ%og9M݉1h9Y+W|qd׊wuvB-pUs:@CՕPbX&,e,YhD \BOxS*QpTZG^p##d ):xϖHF8 )l6$(}CK^jŁEBYd.-_O"ټT*t@DTH=2]!wam teqP$KnE[&~y-eH顚Z"P 4=Jg&%$`o`pYօMuVT)OBEƙ4s,/Qy[nޛW=x3LDGXxNS2[V2X(;'Y,alK}aim*K^Y$[,*yK7UW760Д 8BD*ޑ1ÃdON0ࡊb{)Tt#GXX`Gn[]Q4ϡCoA?%Ӕ A^߱};Ki~Z alGL=GJ.͡q,9r ts \yr\T :Of~TNm͸&Q s/#45'/2VZ9n1xGn6&YL/:iVw-@qһhP%b. +$*:{_E.P).Ed.zIB!$8wks |8"ᖶr5gEd:8OÓņldueވ?ısMIe%َ-#F]8AZq] ;Kflgqf9<>a"m#qM mstqd9 K'Mҝno@d5Af` ̥d9\zdO!rIR~]zx/W^=Y9v-жhe2L[@  >QRz9i./ ^*`=ꁥBt^b#wHAy*((oH%Z\ҋ}:;9WVOzC*Rx4P,LpI)+ / IχV&:ūR)Rj+!ÍKʥDU> U@A-$`Ηn+"n."W [QY6I7%8#L(!3îT1x2Yɀg4䒱#sI3F%#Y&dKO";`x`4t2[eC/)ϡh")!Idz>K9yg冃f̃yd^~300eě?^AAH C5s&qEHxRMCFFUzW< e.MFtK3Gv`Z:Fii=3cD$Buq֛~V[r/1z!+RJ l1fPZت ZqtiFXQ8ïNE`T4|#Qpf3]Z@oĆ&Ɵ ,NZWHKFR}mriYLS }5CI&,]UVɨkO{':#7%^<&`VQrOźkIYK7~bֳΊ`eς%U,V( tX5Hm!VF`oW8# ,O(OCI!`IK-}gyf!)oh^B4Xs78]dSl5F?5].ׂ``زe qt<Ȍ @W^af?aoL\8@l¨ sJalJ+amR CjBj۶me>P1c֬Yn,b2(wͦʸhZyicHb3"C#Wes;;]tPB/`IBB|֭8 4ʕ+qę_۲0l4T gVp&pvaz7lя޻{O4bmH0cm9>{ć ־vdo:ןj9<iij߾mz>z·U6OcyY\i>y[^T_w*Hp;wn7CdmMM-bb?яP$Dꫯ"dtg(3('#Rv4t6"Uh@@:x{GݹFZ$n/KC1<ձf\b_Sr17 0<&B]$ Y||Bqr֮C^cdߜ\@+\v&I?剁 cǚN`YhH;w t;H,;$3t _RvCw wn~ޠa$ 3f\.u.UqH|z@`5@.zs=ՒKK?[|]Q?>xM/9UGMV\m[Zv`e t 3طx",|jDMsz{a*xĴkkb7ߴޏ ,3e)޾mCgϚQ} ߽7Ʉ/lF|饗4eb<{`2K :9:уT!< I"LnဉB98.\%'n3QaG0=tʗH񵜊AC wmX{lw]§N77aɍ}tƍvCvĉ76־즛nCg2WD&v".t}P羪oI׳hzm"T!cYiK=3z k贇RY/rZ-i`o L S4 /ḠN Yh"qy̒p6j`/ ~ D$άybtą"H⹎Kև:Ƞ!;40,`s+U (g`˙qU 4 HF # e1CU jE ! ,>f\*-=QK}MRiګWnehfALyy9 !"sS_f(JGbh1U] dUUu"_*B2sƜH$R9wu/.e{AJJG"QB3f_peg*~֖N'"ƍooĩ?K 9O!G0ʅLD6Ç5ePq1 څ0MlrYP-.bP%Ptq>jlwB(T-uɋp?XPiqImnϚ5 $_aO#" Y((<bY4u;nw缜\ޑ=c&'?IRoXL&D| A` {1p{ް~]5599,Q3z4ԣF|{~֏3KR?vQ164w~aJڹV%p!-#0F\s93w"KWrźJP hR1jL= ӧji()TpMR=9{sY2(3YD/JzY&]VƓronk`* M+]У9SI3+BS C#6<[I\JC<"vq ! J ᅹC.ml9cӠPX*J4RQ4%-nZC2o#Cf׶zHI"Xh^8 I2"U$hllPTpoU&$**n ar |_y<*:¢fЋ8 Fr*37wGG|QC (dbGB#&iz!eNXW\"5&~ _ ش ᩀFAɇwh5HNEa+ b BZxAAf?PA$mL1݌yi~n0h? $.qakd/?q,lb0!G=`#<K^'/K,a$"d9 GAz/o%:m=DL _yen^|Ǟ$tSTÿ9k Y}Lr AL~ SS*}a{aKTz^*FcS g>ﲕ&0pldZOO}236襗978` /$R%Hɖ%Y-ڹ$O?8Y/ɎcKu:H]$%I3Bx)7W}u;+,qPw"̡WIb8>E*{m{w#Ymm Kp&afMHEgB/0-GvhrS?o,U9F+ SΐO)KҢܐX77 cd eo6R!#NI,} FuQ%Nbc Ł~ЕjT3pF tSu =|5wwXL2Vya 14"h` =55<1JGS'_5\V 9( LYWZqv$CiY){ ^~i+SzcTtWWΝX֬1W/zS$OŠ2o#0Uj>*SkTWuɯb Z58~m+ߐ69F[ݻ-*qš6bB9 TV{;d d&|C]AϦRa[nnNڲuJK0zS^xKu5/hlg:rS l+t.-_*))mp gÓ.Xp9<ݵż-hrf!|VYD_vdW$^rFP|"Jewͤ-6r+1yU2XSzҷH j@yN  Xڣ) A^35xC`KC1>~ $] ( qG,*9fRP_"쌁%78~KaLvb aƒ^fλt9TN+&K?ytjA)`*Ԉ;% 0?>V^ZIw[~TF1g' UJ s6$}2< 2$5Rb,;'x;6?fi?Qig7igԱ'kfmj} ˖-9uE771 sKuǙ? Fce_6ViYqk[IOw rgE+;~ŊQFCk_˔lBGWoeҒElzm 3Sɨ!y8l&v.C0h\L&aENf49eXrh u?pК?-d;n "}†< eB!`t~UI](d9 a [UhD'JB)DsQTyⵤT2&pt 8fgl[sF T9b㐙wDxBS'Ԗ ʌyJ Ӎ;¥4!˯T><"0FuH.$YޔC6=;oiݯ-]h~36#x4xUe.;z:"rhX.<~'_ڱyo]]'O}+P --bY?/!*U[2zɟs?VRFxu0;?NkZWTbD!y^zy2S1C0rJ'ARIՇbT2YSLM=nD 6\PA<%42 ab3M7?ӡXeG%O.Rƺ+)-e}]^FӜKB`S&FSͣd%f 4up+ricP3ʑu? /0rJ Inҧ7 &@f4SHc@*X PW% Jʠ@0'”ѣOUW9.d"l \,iRK^ҁLKq>HFHNI QQƯ(sۉx lⳌ ϫϰB|:u&QdeeXH ]x%=N 3R.-.*L>D}B-RQ# kx-pZ,9s~$VM`cQp2X(dI:u^pp.㍤WT,a$=SzRu:iP4m\g2[%LB0p HEtהȬl7 j6E2'Mxgcmco삋"&ؙMBi/K&"~hı`" DmW x[8rdokUk? iK'~6DgXzC?zׯYH--NNw8Q&9H1' nڼU#1 FbqN 8queT va]] lܹ#??<#9.8d_ui.FTxRYz5 Sݡyǝ)< PaEGko@r|n:*ՔXZ|gϞ~m %}_䰆x┳RPR FGބ'-ʛ[AZo' {7m޻uǬekVņ\sCʝ+O4F'w{`UW BA;w_v LJm|-Z4w2i;I i)G*=C&HʦnEzSw I&k+=Qkc2T jq!9%oVcY^qPץdsaHht0xqvd[7\>NF]5J`d4[ .Q%N nhCETdiTI% ,x ܾNjX$Sz!8*0BBc#bSͻn` Tb)naQw5gn<,oOFsEcjyvB iصk7`ںҚ={p۰\zzFu  rOvPϱX- $l}WuF8R+U^Y17LZif)UuIX#O]gBgZdH爤$e^S#T^˄0bi0FAbs.%zv51V (=(d:%'`s%3y cdٱT [@lHh\@6F%Sd@b%#(UlukLJ cB Ŝ,xׅ0T 2!0Ƞ5kFn|5 |c2_DcqmLLSJua?ڸOf!mx:ru8/؛e4!54DRD3"t/|m9ҺeˎճGW0/+1{_a!˄2]5IFFJJc#lǔNc'fHof[83sʚ]1H`, mj Ր g}&$_bDm!: p^嗹3=۾1CI)+Zw 6/m԰%ȼ… rnrL(vىIި0X[j 9klփ73Q}JLz! vF/| $"QHSL(}t+jkݼiˏ>ЃE"%j BтxieJXeJc"NGB/$rDO4*LъS'F3**874RphiaVMahdX',3#ܘt8XH('K$1"2,Hv;]I3C |D!'' TabZ7%_^R][:$ZR:?ZDwa(md2VU~ RO/hؘSjfYcۈ#Vs+wU"@[[۝wywttr-Ipg3_=g~eSlʕ)r$(/Dzk.{.T-`m8qӦhlf͜{nؒr(ÉYC?!k_^'8 WG:zdgUU=dHttp$NxpEeEgEzWVUQ )H1އʫg[lp7[~E9)D j.H j3qޝ?c4@v_ )A"9*!Ӓګd> Ki#/Xs|آ($ī#Ј(44 ^L2BU(_ ^O'LJP(\FQ*V=-A@\(`4L 3a :ߎk^yŪ+V, lE꜖-E9q2x0UfV; BwLF.`1sH.rm$-s44r) G,VpGJC)u emDNe%E=ķX*'S#\8;{H: ɳQ98J'[fbqcdˌ .(IF1M{2$;}ي a2qhM 3FFYlȎR͘)"#nW@5VnГM$TK 3}Kitb(5:VZR-WJ@%a0+{'g6nb)/mKGki 5 ' y#~I9hP-&mS]7eFD 7aEbznJ$FG &VQaAOob4-iüv3jU|Fu"мzHmꆆ9!42ZV[3@cФ,kY,'C4\bs,=<U#CZFS8g0(d&] Ry|z_ܔ*270ahl<cyQo.Y~bd[t ΋Hro3Q)†QBǣNo^*ʈ}ȳaRԶ2!nh}%]RB0%zH0t IBSѤ!0`AN嶙0 CȈ0Rc}tQ6Ű#|9RH]Rbd]'6%n9a edv8T7'TTpqn`|Ɉ cSڰ_950p21$ 5\p$0_$ F@wg LZ9c=[wbAƘX=QXWc ' q>wq&RaQ3ä46,%IR Cn9SK>Ap-1Xuu 0rňlrr _NgJ-R1x0 88݉2 Ÿҙ-v 2H![먦Ɋntd$aO*#dZtFodP{Afs E'XrħIu?N&/8J+ʑgU/xA+E9$&ǔ9E  {[K{%ԈVImCx)ye%R"0G(7dqjM'1vYΨ(o!'s Og 5$ƳT_tLpWSrf&(OrOi.q#ߚ@HBCOl AdRRX(HqMs2~f[!i< BnY:`{Ɯ9sn݊BK.n*[_x0l/znS3k/dh[e尴Hq=9 fTUbP(f!XeD?| uT+/߶b?5sƜ˯XZKEUY1sllG7~Jp"$3KKCǎq`mme}L6ӡ2<}W]5* 3/1ޕXh@+,w'_L ;qh(,U,oobřa97XM"Tk6hcV(Z>xh2k@Iu,gy9Gnú@ YfURV.(GS4]23̎vY޳u.1)ؾ"a]UɇJqR3J$7Ya|,s#Z,P8(kC32:d0X5@}m ֈYV/rPVbLV4gzmJko,ݼHh4i51D|ML", I\yycLex082K|l˞y6ihΑFc\+{+9#-Ó Nw//O]tE/YzZm'NvA~?󚫒^h7'VR߳_]][vI&W_NcO{eʡ/)/{ /W f2eh5#w"XļQΎE+5_\\>2ns'=T_EŌ6QKK?Z}*p.^$ө46{?[5k.DGcGSe{8<8DV,~͹_gZ"[}jQ#Ԯl[Q>d{O->cYUFܳk/jdpg˛R{#XގHBpl/Z3D~9-ޖ. Ot(JIt ^'9$,֏CbGQ1 jdHBpoG;yp`IY)TXn!;G{{8eFìt/2DZ\k$3 `jvR9aM`T20Xi24pw\\)d.QKb$&Jk-ǫlO,ʐD6XE<~t 1Xy%d  @Ăt:O%SMHWbB C9d̒)+Mq2Zz`K"b>4gt9~0gb![ 8͵W Ox'7͔u1ATtZ uGajDdE `py9u'6ʆ l++nUB>4 JK ~nªEj֯P߲e9zcX3z۸q@DP"EJ/v4rXsozĮ{߁mvo:4<h+m1x#)ʊJ*?wu9@P{+}v#TV^z-@$GQM͛ @ȪGc|ppqD4SsS~D `o0/8ܕLJkK/Gx?+,X snj,i '!Ԅ6<@tJ&i?҃Of:t&;[UY͞qüԤ&TƢ"9$$]lxÂGSx!9-#8J&-KKFF{솆{zڣTI<|TtwΛ;SoCPYI@׮>vt[XbL  vD C=eh/`K;E9RŋHw">.ɆYHs[m,>g`G*+CGzj#;BH& %$T=vXBuL`LbjNXLX" m[Т$ 1- 2ޱjjHs=rW]1_EիWcK1ݵhѢ~xgַEg˙* R J\v-҇aBߓ  F+Fj_>qX$|5WtԫO>qkV?ul;pUѺݛ^//]z/=Byi%W]1no!Xw@aJdtO(]Q*b&gŝ:7K-~ RJ\h@6-MQ@ZBSJ%K px#ʒyQw%3"^؁bxtU `T aԖb*o.q t%9\Ӗ1qI9e^)\N휞#B$tC*PIzBQ qWQbXd)⒜or{L*Rk]eΡf$Z֔ģ,/Ϊ-Cլ5Pͫg`a<^d$Ze([1;򊢋"UJҾ]fWr5s0Wh4Z22ŝ;93~Ede1tlRvzp{=7xq襗fC7ݴY˯hd|c\9|,K|ηp3OmE}=!K.[.Q&(9R#)5 [C(Q-ŧOhrBRTBE.TsjL*Q f JrWxiT;j&kn=M?44e9jEޟDt*-'ꪫP-/p͇>{w`@IDATa❌G58`?aiqV]q\eȁX w|3[lYd _KWJ?w1D{\{?<73f17::?w-~['?W/\=6%FN}? 3%n&s+sNFe&x6oIބ+sׇL<aXi|q3d@ޠ2ո4 A*ƈ P&O.`>#?1rO"v"m&ς$NUWLe#frk|3T3 BUs㣡7J2CwDŽw +cl$7i'yτ!' &i'"! i-A-07&H&6i:nf> ' 63 )//a`:(Kjg΂]*/="4&W`9I*]T[G9̓RLN\Y {cjĝ84q\T,gdtuu)**Rd{n4VĪ\$6hq\6|56T͒sWb.WUg-UgZqJB[? f֖*6CcƢR> UWŤA:pQyBqzpu VLIҬa"7&g4̙~+w'P7+jkfni>amn喒yM]}{~_r3*xя@Ռܵ&~ȫuuQhsz)r '(SCat4bb؞e38k2}*s'' #g#ťGzzOkj{C}CLHzW*]IA#Ü1On+ 䉻lhnWV}[[Jt"ŗEфUTWm~ReeyHs\N kT/bNޒm6ĭeerCHeH&x޽tptHHDUd*HFec4FH\̣0IgIsjIM?c_^5{OcI1-=uȑc$/wu;z&8p`IiMG=v&7I D9^^Vv/|v:N_<Lw?'Oqt牞S>˘Ow G2~y޽y!ģ0TueJO+],&9ˌV#Y9QՔ#AZ( Ω|{"&Z0* A[ZZxR!0AaFT5BKzCS=ۻ {+#x@>4+Tz6Wa}A1iֶvZ0~+=R!C LdE2֘QmF,78cKWzL}̿k9nb4%Kњ樔R#h"1.ZZWe_^ z{C׽BN҂WHan`jt٪+ܷ֮YӰ`{@4zɧ5]yi1/[V5(/&5PK㧶9O uk sÈ)A.>Ȁ8:׫BF>LhHeeiljZ  >%|(v6"Jbxͦ=xU $dX\ȀȦ[iBp'c?9bHT ʔeA[3k u80o)bW1AzDr^F#OZ6v5*򙦧n̍,h)˨|GPQU|sg֖=/Z}EC];t"6n>ye6U3^zqө}#E\tg6 p8^=38eNUh1@hRWqZ>a&rjuh ҞiT!B,pZP` Tl#6iU[9|/)ŰkhÇ<& %;v޿嵭\$^Nf[#w{nѶf#dIXIkR`HiB1$nhܼDā$"[>9py(7ˋ /)"\@(5Ɗ!]k^䅽'NvEQ?]JD %}QNOBF Fsy}>.i 0yÍ(]xY^PZ, D!"&IK6xh]' `&% dXᒐ>@n12:i>1p*_FKz0csi|+ifykukn|՜# I}yi On %e@Dg.'K6 K YJ\X`_{cU8! ՀkC7]7v/qrJ{U "J$zeyn_rUcqx Zq\JrS>a``m9FMݧhX>c|_b%if1 q4kJXdD  Qhr+t"hoi=<OeJI\&d1؈- 4ڋFQ2+?ՙ0Pz7ekɩ7 Z8OFȋK!Vby"'ÌVJsHBLfN~C3P" xz+R[i9HzmZ='*ѐ־J0O2PvcL M " syZ-`@<򐴝SiA`YtW& @q{~Zq*!g9T&djS5#9it+3h" g/a'y$WdjSe.`bh @+^84ȖZfD^ WE 'bkcZdL (n5`ؘ  ᣥbIȶI,&NǘKs>YbY1&8m`$q|Cj-œd*Rm9I..N^C8go؟9Ɲ#.uɠHw O-"^ڶVr 'Pr'ɜtANiZc@s^z TM$14y LF}xjy(1浈 ]i ,A^_n|r1٢1@ ".,Ȁ >Yn~Fe0oHڧI(oNH7 >S(`"ME+ j"mőѡBhhwRÓ.T+OKA-t`vލ2nfcHYz\c Ac:dxHHè_fK 4M`B3$IC0~qƯdRvY%t&HG-$ zYLP2DVƢ `.Oh}`䒖rw;ۘɕDJQ9s!Z)[֋!$jjv43='&FJh- ĒcQ1DGGٴI?!JB@L4NF@G{nԥ%q<Ţ3_Pb҂ H\:Lv3UјȐL V&KI`v}'&RLPI9al%8^],^Yjmme5z-GD1>ɝV_Uj#E# PЕo It BO<眑7)j[iA( Q  XZ|)N-1 L O((.zs}x>E&:DEGu/O_F|X!|+_뮻`& €dgKU1)J Ɋ{3р3K>ޜn&N;~~kݺu3g"AFS *-V\?O|B3b(]eg:ڸyl~{[v$9pĨJݰV!2b<&İc >y&9ZCIΡ⌒ [w -zyӦǟXO~r廯+>u=Hdzy--'ӔW=8HAhp(I=aA g\ѧ Jy1DVhc*>/271\.rт ME D`8\<5ш(58LTqş[RT]SQjy'#0Q,:t[.Y 4. aeH kM*`-Y.&J`Ɛ_g*igJP)%Xg意s$1Y hLT#`3Cg˥eU7F&t8He2vhXuezh*xQ  <5"iR~HE~4 MD6bґAbQP:[%")|sqGJXO-OGAP ®gTtd!u <qgSMw~G.=~0V??޶m'ӟtu~سw/[ۮm;#ʗK T؂ ?_W]~z{n܇~v7}ݶG_۲ N:94ΒݽǃK.X̡eK\v <}Yn ^҅bV( Fi22s)>H ڼΨE'g3-Z~,߫>u\CX>L>YSl4"D糚"\z`y@ĉEBܸ? 0 S+ʒX` a.B4SDW2ceYҺveѓ<5lPƀPIŘ @Qtiv{sШIF@N`2yb[_y /xgta!^z㐗Z AEͦ7 Tf&6oɡ# DDPU4>%'~ B'T'ԋpxsub %rvcEPLi2`&H88͚.+dR>7 #6Y+DJ?_5&ZyT8??J*(79ogmqqYBgVAV\i}n%@ +osL4`tVx:g~:L6I$xwkF'@8 ,$Z:Sþ O>y,^brA!0H#ruMH 1*7IaꈹScI^`iF4L(e3C1Y  8sj1,T)}1,W@'(<[rD8,OFLPgL03HGxT*N_$ sϝ%LhW1dPLU|#OT)9t*`M *%0 <=l,櫨(;гI9wV7j6-scK~%\}5-[zoEao}qj ^Z8-TZ&9Gv,7z^ʕt:KMr=ݽ|̊akKmYh!7\p+^C>u o'y.(*V!H_F:8Yvv<)[ Hy g\nG 9@T?1ͅ}24>r }ehkiithxPϐR 﫼R2` <O fH>sDԠr V }|. qj?! dZj@b!F}^0J`F+6i҃_?ɬ! d>|}?Ξtxmۯf ϛ\y+%I(׋}UVn?̚G{[oٳoO?6d%5>]i^m먚?,oiEjZxd)8?e! r_G88q&琚N^* :VW؅#@'Y ϛP@?H2&$Eޢ4I4 0/8,_;#0MːJc`8%-Tau8Tkin1CTr}#K.FꝯRJ3O^QS}i]o}up2Lv0hUU/_~ E.kk[絴.\ݞ,_Q>pHYY~%5c݋ 8LI=v++=.Ȯ2&!جx%(2. ،pVȼ4>R3N4ASҜ %Q+E;R}Eȋ$hSp#*5<`l!+z@J!Oaq5G771Ya- Jp偟+!d4|m7_?2O'F"&OeH"Bt#3%5eQGN5 P8Ia`b - ċ#.4RZ3PX) (`4(kVN1SÚ D(I:yRUmxS#ׯ%MQgGK|G[G8}I|&g`E KZ<>P8%P]RLT&0`%f>Ab$ F* `p3} (>.X%-j$]q,U =H1r^!mH#)&\SAƭTt9;GJbq̯1(XaSsv;0OqY w&n6tee؊ꫯXxJV\.ꠁ ˚SWC"h&U:d@|""bW>}nX+)䌦-ޤ@ O7YP*CZx?!-5'3zFa2ʍxZS2e A?iTi h]Q\¹A*8u&ht0OVӅ ѭ9Fpv@j aJ/0h8``DzA9+&X:<+ JQR -.4 % O <-n?DUH)a(o ,Qi*Gd2#_rƸXwhRCUKbZD /@U ЧVh DQS] |Zj]W#qSMoxa[̝y8Ǻ zix". ($= \4)$t}OE5抲'pd䖚!qQiq80I:cQ>MbFdL @?$ZP;Oհ50x87)+B@@ - >J:I1~r77H3&>L&OSde7Oc&\b,|}؏~7 $tF 7LtD 浇> /'D14u> E:[]O(] NaD$-&JJk?0  (ԁFT0j&Tr /2 >2U䆂%7]AVDž81hpby&|RCz* }!*Z{(f dZ +DPn(+'K fS=g"]RJ sf+D".zj+wpT%-8]# 5֊G`x%cEr3_t,TZV.IH:8g@0 KQE0`Y'Wv4/T&_P&9d 6Rړ( A_ AKqf q$-@\z7!`hQ&TʗʒOnɅ3AB2d :52=K2 jfQЈ Ʉ20OIOHcǂa^OjGQm rcf1Vy0X`--,`i`4H≣p+5 ޝ@kv®[R' Jn $L H#]lPh^6v-]PP@EimDF  I*3PV~{{N*߽{J;&EjM",a7M/A`} ?R-Zƾ%>Rj+! l6ij g>ͯI\H^U}&0QgdOUDL \0ȢF'P ]kVi.p NW RļlSq;JʷGVŖV=Z32XԷp_>"IJBKQ1RS(WMNn&<4Zɩ+KSTZQw{ʭ>L1%`Ocfj֢Wa dKЁv._a~hyöظfs1Ӑؚݲ̀eE(r\TD6f.FEH(@"r.1 !1etԘpG& .JC, !i`rDu=Qh$F&=Viu}KofWt@ M NUSRZ=G`Npzt!^$?3UqY (N_@0Ai\J4S{X+/ RXvx,Q+JGlC-)KV3o*HeH:g&z0\!*%ƪzØ._^jU=Rɡ+LˑD-EB͢ A?QB0ZxOLAOr2ƊjЏm LTdQ '2y,}-cFtR4 L=K;5} Ad (GWI3($=x)(e]ࠔ&oM٘ ^AƯ =\R[%V96Ȓf/?*{l1qꀟ.s(euz8jF۸t=&Ltu_%yktnM,.s֯yyH/&x#zS,dz> Y#GGUNN ĺ7,?#+U\*NU>ABWb#^4@Y?0l(Q6jXQ ԗNڶ-ľqґ [PJ{8z/ULct(BK&a WjD LO>I,}L(& 'eodӊZpc Wkz4q$b-"?8lU ZZ,7\ aMidA 5) ؽG&blT+4ykmO0瀞Dm,";v_qeOFZPd̓~u׳MśݔX2QKxݴh"Erꡌ+۬Uh\R?*Brؓ!_i:DVbaEXُ1Yy_CBA+dѨE3E iC%NK9uu__Vj\u߯}~.)MoY,n'-pJ Ҕ; PT*mGuPBW"#'GV ҩ}^ȤE°Oë  cWX|LsCfqxjQ +*YiWDcSG4oj"(RGr] Fe$EW]#ЍG*?Y"ۧDEI@vILJ"8J[L"STGB;\175:6 8Ћ1NKO8G&&j/J*6Z.71fAoDӜT V;l߾ľ DYoŘVof"7J5 BbVI G; h>BHcM-J̐ie̓ njF4q5ɲLhE`۠TV@`z+ JձƁ&Vˢj'|]j7X)xn1׺ k/J-2)-AkE7HpY }hw]QFWӓy  7߽7񍾉c!B==ybҼ)[׎Cp M/tGI8MIRW0]u Z:U*Y_adkQ=fU:4l ;idO'{KއA>D,\ѯ7ƫ"^ER:eX[BRxe+W4uXJyL1Z/͈. J-> RE1!J&DnjE)SyXM`R{)I\bβ[HDڮo yIXZYbjf:!YQDNkeTST c 1Bjܤ[ 1 Xڀa6FBC`󣩝׮"/㒬B'7o馫K_ROFNhHC'M|hpLϓ/ZKn!u)"D:Jroz& >:\ktW,MOX4L' $c3Y#M$OAt1uuJ[|HH9ZCif }8O#Hl,_=Dfl =#q-JV%Hz5s]o1Q`4Z QsR#d&]T㛔24я<ΏJ|S7a2ӓm?__}Z]Pbc&ABl98ei@l8WLiq0$cS!>H޸;CI,cX!G#h{m@qB b0 RnMNhWR̭z]@bW(  _Iy`5b<}_VִصƖ%RdhmگEc7 -VZvҒ`ЦpMxl?~٨8a:??! FoZ>1U7iIwPݽVlM׫onQd-A(M HI9@܊í(M3MW5H;2E*M9mE+i#mYf/ϛǘ"8&6̼a6 9)|"&^O0 F0& `?)a4v/zы^uCYVfg GyNF!J)$1!5Xvrx&u,\xBۿu)䷿/,PJ0P/Kf??ѸH"*R% fЇ>WLM2=ySTzDrV:"4T:ܧi!]W9{kǒhimh"pn.moo JM^D%6M5hZ@&ro?u_uq(i-gtA??`G, r~ pdɫ^u*4ef>foiZ|Q⓱$}bZ1!E!_id NQ cC*j fI<(%%cHjD6ݐo७ƴ6"vBYCddDj>Xʆetb6\֮܃f\>1-򶷽dn~eL3lti_n%M6016C,p s+ˆ,Vpt!f+R@giik[QM)2?Z L~ /cHC~802@\eu_W,K:. t6 Lu1ch?E_I;^AN" )ֈ(C 8"1Xho BWLΰ qBXKb՛9 BoGth}N=,f}!V/QSY[,wkAL^7vYpMEk!ʢ@feIi&ARlɢ42[d!_>&efQbh[#Yv̘ƋLQ1"q0fU@ډuYo) ƶ OH)Su ZH`(2~#Pa8iqLE֍V *V"|70@\sv?яe/3oVĘPR"O+ &*,#~kgq#h/&2MֱD"!#0ŐE@̘1H9[[xM6uMWU[HO0pYJ[$+ьi£w ib&ށ6SEzX@IDAT ^8cAOhdu&=a{eXbCBG`zM>J|#\Y#pur+U)W0ITG$\-lYi  d곤, `WѨ_ڜBT#O Zء]-ֵlEuK߶UaauȁȢ#'!3V&7bdon<Ҟv (͗hl?Y0Zdw fGF~imKAdj txռq8JgZ77'5\j/%qZ١$ް3ZA @f>d|tܥ-UUZ ]9F41by"CxCJ*saRCWVU.$0k L`zXpAD]50bZ9rrmix ڸT̽_L=&8U,$0 Rj$-< D^a('a9+k=6DS*2"*ɱ#Ox%Z ċK ( ru<3{;.ڣ#崫Doq2lH2K0<ԁ `} @i .:JA#iȤ蕲ˆ@!:|M6 c ֶ Ap} ^FQpuH!3`OZdC2pdSx3m) hCH`Sa%XIcTL~t5!C5fӈtWb*Ƿ25Nr 6=Ia3uYe(, dQ6,HRu1 RqP7h v" .2@\W`08L PF՝.H.q%_ ™c|}@g8X۷oR YZ&0"F}HRi.]!Z8"pVx0lI&0?fԔWRh`E7:fAkf R&'+j3)ic}~k&7TVK}N QnWtuwQá?#?gك@oƺ|`aOXK{1avZ`t=oiRoD"Vw˳BBB_Ш i l# F8]wTu-¬E!-RgvMdD*]bW%cZi&ϾvZIIOaG pb\91L*U|dVHE&2T B`PM+-f{vS50t*"Nh4BZ)WlB!^Ul);f3jB 1 ?JяG+E] RYHC,@¤0 NBS"5I-jd#% a k# Qʟ{$F&YZZ$bS)H&i>KDyәh0Ufm,;?\ BX*,EE\Ǣ( ?9nXԗ"£j){2٠™@< $iiemӆˇJh>*RK `苖.FWG#˯D{n|Wo4}3 8y7l[TDl}|_+վkDo&OkjH18ğn|2ַ)ü+ ێ.6݃i4 0ol0aF_؏Fe_X;Mg#30iOhlG7m>zǙg=us~Rh($ZZAȶN@hd = -6Kgk T1 }L @k[ɭZ&M k_c)WP$q Rȴ9 @%&d\JR1t> \c2@f%[F(KZ5G-& Z !Ę@5yUKJy] ^1+uA'gAqd@Cl $Udq.R, @ =U|,--ˀ0hDBo9Ԛ~U|! ./!P~N +j`~BT#g5pُ~@xǃ^A)T򮇯p/pn [[7|s@u>e]W$X׾(oD)|;雾G%;R@i--nH)!Z~E)ݶ\cu"T뎺`X& L';HE 2q*%hZm)dFQZi-~+;(ŷ4kħ Ki])C6T2H^ww" 1͈&d=àA+ڸyq% ƺM6y_b m6l(0'Yf ٸb$H`bgy}I2`N!/3xUYC:R P#J[$.Yx+%0ZA F14ʈH!6I@/0»`лD"cHz JH}2 <xюELB4a%qϫfL4*h/Nq@σ>jow~q#mN\8Y&VD#NlhI|bƑ,A^:槠=Z}7|~O6FY7Q}؃ԭ2xE ar^'%zk^cʇ~G>@U`DnR02XwJ`pP- ^)8X;tm&iA"@zHK`/~__Xu[iSm *eoo;ek"mD9OT,[/"6",Y-Sq\ uW/f yP#h&.u U={ W~tfM-ercJʤi id!dvi*BƤ5%3zgiL+j}(*'%3)m-#RS&c2LV=---a CB4%!>ܘf< VQ~rOwO?2!!-$HԮj6 VďK|з T]ř "!M A&& |АWb(*Og@#h&ZZÒ5Ȧ=0Ei`G$]i>v ZdTkbqY[|EQG;- .K<ydR 8iEhqwq~g3^qx/.+XW-BŦ 7ᕯ|ťOyR`*TDiȰ丒|X>1BǞZsz RW'r_ZZ2d^}#|VL&#dsN :Pm;a GBb(W~WR0UDXl>)U;XtElRZ֮Fkp ۇ¨E:aItmq=)O={mܸnpi.?c =WM9-ӲҶ2SEGHn Pv)v> Hɉi٥-k:VV4-/SYi^A/K.zlO @6ʛ±Eh}=¥C%=U 04TaؔBb@=]1#Rx46l(тTm;ϲȮ];-xS.q(Trx1m^Yr!K:c c0Q/E`@HjTsêZ1RN@O,b@dCQ8 }˚d)c!$Qd6=IC HQਔ߅BU!ذD-"r"fwU: ʸXťR]6WV||ӓ FQ%-˗>""bhhkL5p8]isyv 7pMY†|v'񓧞*.n(W}ynݑ-'l9wWd`z$?AP)_ #l:z!0vxY;Y+0Xi.2C NV?E4a@V0k%2x2CHFaDEϩ=0HYxp4߿oQ~*Ⱥ;߽GK .Bl oG6u, (Mc:Ǒ% $W% -WbfZ:,} Aak窒[[L Lk9l.'hd6jEF!1>Aa\Ϡ Uߣ,\ί^ȡ a6ʌ6bhx @SG8: 0}4S[4euܝ۞gܵϻO sU˺Cd,&-PٳWd Vv汙倐GCxT)Wxrd ]t2aRx6v -*\@~wy2 SEq!$ :ˇjBfoN_fsﰔ@n7%*E]dnMX&#Я8x9{wmߨW!ml-F.l0aCd, $"p,*#9y[W[}L!GEti"CxdB)MncUroh,i # fBU.}ttLrUg ]-WҴHumύ'9z\=sGmOxf><q[-^pAjA}cݫø{L,ݽwg=[6t{{+T$/?x#6ox}Y\{?tSox}~M's=e֤ 0րbye[^63CwwOV++#t-!;'j>ꗁ@P@>k`@ Y1A"6kTߚ*y!3itw@]b5o Q-Rjݹumˇl޼Iwd4l@JT\葻f%''Ӻg]{__v^"J*goJzQٰoNmɬG8RKf?W$*RSǪX:tkR(7֓]v]wk}F]r rZq@b!4כ7F0KU]hI'߸㦷~)'nWsb,b:X4ќSXJe!:( Mt&)_Ȫ;"+rzdEl1^(oG"e*7z4 'CPETfs&jgrd O$ {Zj EBIutօ.1 /zы8.TcEMQ!5-^gx  02,0ΔA?ZMciG=_eC_|2mt'?}vO o9|lF{%DyA_7\v*^:EX]sG_«pm{A Gz_"cl!f\A1atlb_ .dz.aRV+:.G4N< +%7\gs AJ?tZ5#LBPW4Mn)?#}/xA}V+#:[mʱg- i˄e",b:;{h-Z<, Q2N` 9꠨,m-W^#}XWבپ3V.̼d4ERoQ2* ٧ ʇ%uJEr;-k<̭_>X≍;:o)?!y܎o7;ujy}g@^u|#>u ~GY[W_ݵ|ʙGm=07S-߰p]*r˫ Nۮܸa?~tcEO2I"wg;yg]~}9'x 7ٟ5m޼$w/𒗼ɡ;O^+hsSXP?x;=!$2 ^r((};߶dMtEp ~7=yvô?Z>x؋fv>w{}\ﺫik?i0iW$|9ۮ7W2qܧ|̷Z- Ox(4g^C\D<uX xX蠐v>$#rdZiOD?=c{o}_.IbsУ((e,:b |W]YdJ Z(Uu>]3=qAG N4APDoٷi15R0 6,MX$#j<50Q鴤ILk 8 :ȶ\Ƀ VlVWOޖ ns)?5?7S2*=a2;)iүq4KЖ|}nUa@ Ac;ڻA6;s=G|jLEח`92b.ټo O߷?~SSO=xgno<nD*^vD/{˼LgIk` y2vZl&0R_!a2G*jF0cQ 3I~% cj5s-Y /%G<;&%ڱcV[c>ă%uS'lfXC"Dp!vլb!Q.>'" ([jȏ7#D3P}0rF -RJTKes ^_jU>R6YlԽcQS bxUW"]-SN+Car B*-b/%/֋%+zgo/?>gq.y%gu& ՞cO9M>jǥ62X5_0iC#\$.rx{pX%G]q{uwӽݫqC`QbCnvYW]pӅ߃q Ow}O~ʓ¾\vjp==a-lgnSO7irV˯Qn񵄅EGaˉ'[k`VudLyh29N?͞1PWaK3S'ot<\B)٬ԅKZ>8jkRQIOx/hERtlG҆ny.2xZ ϰ-cSr&)N+>"\ol>5r9GS:JFSBy7Ȓ&D&S5 OrE) C4N, 2WUY;6q<|D3q)l61liAG\pᅤݡMKH@@`q>o}2X(s3zو\ovҷq9>z?(7Bnzny0^SHҧP ?)UcӍ )f,!fRACF=pIj!օ ; D%%?SYż,RA NPQBYV >ٖMB7xGpՇ!Q.!ElATA;',t,=L aR bP&nBcA2i Ky .n /q"dR ZYcѦz.ˇ  ڣrK$֕U.<5;n/w/};nV=߆ &I6e>  K6!3Vk \C,]n +(7z:}#:x a=XfK2pu0V]UoU u=FwjV>%b߽oM7o~˅9i78YO CW|~6Ӓك,L#|.MA>0r?^Ĥ)3RNI^G=+L),aP#oib.Ccd$Ж&I{,KO&nWvIR*g2Y;N Rt󭷝P>ƃF/U] t9Q/3}GeZ\w{Kuv{]>Xˍ=G9]Jk#[]bUlcC"QHuܳ$#xUf樔{\͛n;;eOpU"VijaO ( 0p0j(EBO>KhVjXaf6+۟G1#d!# XϻB#PҒ.ǿYS\bjDTH#)mF]f4Xa6 (I_pSN>1g?^&ϙ;(mK!9-!ƫ&q}݁Fc]"aRH{^%+E_9q'7~Te޼i'ҏJDPt2k<ܺ{19ۿ[- q~ퟣ3N_o+?K[,J>&&[LK437 b,541_hE3\} #vmN'X܆Yfuxckutt0W[6 Po>{@Kd`Bi>D \AC i;-a&\3ǚ=#󪢮 NŴbN:Oe0fQgipuNp 0C^X{gvrZ5l\Z"yD%3͝ο:QZbٓ/yͫqb9ЕSN"^Y*#:6̉lP9vTSnCUVEN+7E@AC资)Ϡ0 MȾT7j['AwC{%!E f`ZE)m"^I9Sl]夶 NDn͐P:7GV _!Zxo-3,=CPe k}>.w)ݻ?rv)nf[ugz7]mb I.KCffDŽ[%Ye_J!HݘI2YAl$J-UY&@Yi<5}gYD|('`qBt;=ݻo烻Ⱥc-[n픫/5lܼ̐/ 0L>rAiC4JgGediڐPaZAdD < 808#xdLwܾE"G-)&'UI!lAZmL(ϓehc!䁽lGK p$E]cUڴ ر_/CJ b-2ZAK߆ oy} 0Y oL pdJu>f#mPڭ*#|}¤zܰia=DSμw߾nz2mxg؜A]oث|_U2]V1+4_LBXNQrB6}8 8jT, "V{Kpnyψdw,t5zh1ЂG&"a΅ptB?3Rў #),bDq1gi/8lT:YŮ7U';hߖ%MP˂F0EQ>%JSDʴo8l'B#|(=-feS@wĢcmR;tiƔUN/uݗnjMnMdӍt#m( C}]|N× hmlo yCuf+uKtep)OC`awPlB{E"WR!G늺mAj)td Ɩd-xU֒q?wnkKb c9M%?Ե#LPk)޻x‰w__>gR9\)sW^bwx*rLOSJ"ˆx(Q%dW߈oZ̢Oxlњv:Taɢ>0MSR&A`zxG\]5]Q;6:-V8I{}`٘ީ=̫HX>*68T':&o5$B{`&GK (&*' Vݪp`I`Ă4J| coq{xsHb!QXT$=6U' af OJ ݎdāpߞ[o{^`3vv舝%z+y^QY{@;܂,vBq9N&+ BYN0"o{#  3ü,Mu0&CBQZYZB촡Ʀh@ƴō&E٦ۻ-k_< 硼8_TF"zZ{Z-3W/R]/o,BJ/d9c4{ QB,7xU^nZYvfjĒSZ_ _B$&AKpMӴ'>(;Yz@d\c Iv꘭lG]|ޒCY* :W^!۽gg፿}pϏy}kaâ-¯6+z+ΔFv(7b0j:{} 44UoEVD&ĉ "N6%$*J֖E՝;rEʩCڀʠl@HK/uXbhvwִ[zBc}w:uЅf'0ÞȴC i6àVr[ߊoٓlYԚ)#9$Z23N,M!iٜk .F7VW3VҊ#w*]҅ҭ'`?tP,-u빧z-{T`3N xa8([ i#hb}l_^jTVc ci s(aļA ɖ 3C Z3ۊ XQl<9xmUC^%epg,;,?XrG>c5ͣf\gSQImҗJըܖ*B %Ǔ%STZSa"#k'\㇎>[4JKf5 =S M*na[ ~۱ c>q6Ld`-ndU,q4R!;ZakT5O`stDa2XUN kcR͎NU-{ǀNW^iG&&V A27x٘R;*DHmcv1S`\Ƕ`TZr`*6+H~y>^ u 73S F٬߻Sa9]e>]~Th1F>k (Vcњ>' 2A:-7'KʄgY(jL.r,M?ّf?Pm) ,C`z>ΰ/ŴOwk5w>ܲ/se4A oڈ h}vV50(1RtaMlllf`2 ,N̓eV{>PVQdžjٴpp@K[l5]ZNfyqII)1 NzcXך}@OT[X`QVeS4wk=3)&z[Щv|j]Q*XyYY8lɮ/|oͨ֞UXPpH &Y |P -i;B oU!EHWa~%(FM![S[8ӌ~i`Zu-MOi$ +ґ0S+pB9AJkg2x|KpJ0#)X_޸i/'v k"6(wXBC$gR0|IDAT}%6.}3viX7"śUY`ZB";IJ);n"X/bI SpYWk$ t,tuIi >(ӤiAblUƤf%n֝=I"'~1Mʉm,al֫.GʓU))(Q'-ñ*fJl:ZZYlfɛdб#*M$#w$w31M 1KOiBZ kT.4B/,֪a:aZ/ztPL.uKUdf+F1Q-,Jqo[T]-{ S45[t#R?0 DQ_70E1L{*V/Z7 8Ҏ"@E#E.PЭY8]WЎ$+'ӑ`(5Ǹ#ɸV?+ѓ~S6J獄E;XYQ}Tʆ|+BfIEEΐ3*̐%WJ7U)kX[eBf8Ih5]Ce< U^u6*DEaq360 cLjYS{C{O̮# C±=(,5sI5Xk;f)HuE5m- n}'ui yDH,?i"Ɔ";CȤ@8pd[]=0%I hWL*؍igǦ6 յR@cRb>T}{ҢRhƖ``Q jWt(Kvj&Թ#cBE- e˒pHdD5m L h&>34 1pT:ƌzkifB;c(9ce)gj()'(#;C?#0%Pvd"jnCGt⒩WiLMYK߱zVoH)}9$mV%K qpU`knO hkH"A) WR\U^MiAVP+A r%_ɵd\bIϻFLhf\#4>w)' %dpKAd td(Y4LCHV#3ҲYzz\:Wh 46 B/hqIENDB`fltk-1.4.3/fluid/documentation/make_header0000755000175000017500000000356415004135251020744 0ustar albrechtalbrecht#!/bin/sh # # Create a new LaTeX header file for doxygen PDF docs # # Note: this LaTeX file depends on Doxygen and LaTeX versions, resp. # and needs therefore to be created with current Doxygen and LaTeX # versions on the build system. # # Usage: # # $ sh make_header doxygen_path input-file output-file # # where # - 'doxygen_path' is the full path to the doxygen executable # or just 'doxygen'. If the full path is used an arbitrary # doxygen executable and thus doxygen version can be used. # - 'input-file' is the pure (LaTeX) title page (template) # - 'output-file' is the generated (LaTeX) title page (template) # that is used by `make' or `cmake` to generate the final LaTeX # page header (combined doxygen template + FLTK title page). # #======================================================================= # This script requires a posix shell and uses the following commands: # cat, rm and sed and (obviously) doxygen #======================================================================= # input and output file names DOXY_CMD="$1" FLTK_HEAD="$2" DOXY_HEAD="$3" # temp file DOXY_TEMP="doxy-header.tex.$$" if test x$FLTK_HEAD = x; then echo "usage: $0 fltk-header-file output-file" exit 1 fi if test x$DOXY_HEAD = x; then echo "usage: $0 fltk-header-file output-file" exit 1 fi # Create the doxygen LaTeX header template and replace the LaTeX # code between (and including) the lines containing # - 'begin{titlepage}' and # - 'end{titlepage}' # with our PDF document title page (LaTeX code) and write the # result to $DOXY_HEAD. "$DOXY_CMD" -w latex $DOXY_TEMP /dev/null /dev/null # combine three parts of these files to the output file # using '( ... ) > $DOXY_HEAD' to write (concatenate) # all three parts to one file ( sed -e'/begin{titlepage}/,$d' < $DOXY_TEMP cat $FLTK_HEAD sed -e'1,/end{titlepage}/d' < $DOXY_TEMP ) > $DOXY_HEAD # cleanup rm -f $DOXY_TEMP fltk-1.4.3/fluid/documentation/CMakeLists.txt0000644000175000017500000001463615004135251021333 0ustar albrechtalbrecht# # CMakeLists.txt to build docs for the FLTK project using CMake (www.cmake.org) # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # set(DOCS) set(YEAR "") set(CURRENT_DATE "") #------------------------------------------------ # generate files used for both HTML and PDF docs #------------------------------------------------ if(FLTK_BUILD_FLUID_DOCS OR FLTK_BUILD_PDF_DOCS) # create required variables string(TIMESTAMP YEAR "%Y" UTC) # note: current locale is used for abbreviated month string(TIMESTAMP CURRENT_DATE "%b %d, %Y" UTC) string(TIMESTAMP PDF_DATE "D:%Y%m%d%H%M%SZ" UTC) string(TIMESTAMP TODAY "%B %d, %Y" UTC) string(REPLACE " 0" " " TODAY "${TODAY}") # Find "short" doxygen version if it was built from Git # Note: this is still needed in CMake 3.15.0 but later CMake versions # (notably 3.25) remove the Git revision in 'DOXYGEN_VERSION'. # Todo: Find the "first good" CMake version and remove this redundant # code once we require this as our minimal version and replace the # variable DOXYGEN_VERSION_SHORT with DOXYGEN_VERSION below. if(DOXYGEN_FOUND) # strip trailing git revision if doxygen was built from source string(REGEX REPLACE " .*$" "" DOXYGEN_VERSION_SHORT ${DOXYGEN_VERSION}) endif(DOXYGEN_FOUND) # configure copyright.dox (includes current year) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/copyright.dox.in ${CMAKE_CURRENT_BINARY_DIR}/copyright.dox @ONLY ) # configure generated.dox (includes date and versions) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/generated.dox.in ${CMAKE_CURRENT_BINARY_DIR}/generated.dox @ONLY ) endif(FLTK_BUILD_FLUID_DOCS OR FLTK_BUILD_PDF_DOCS) #------------------------------- # build FLUID html documentation #------------------------------- if(FLTK_BUILD_FLUID_DOCS) #list(APPEND DOCS html) # generate Doxygen file "Doxyfile" set(GENERATE_FLUID_HTML YES) set(GENERATE_LATEX NO) set(LATEX_HEADER "") set(FL_HTML_INDEX "FL_HTML_INDEX") set(DOXYFILE "Doxyfile") set(LOGFILE "${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}_error.log") # configure Doxygen input file for HTML docs (Doxyfile.in) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}.in @ONLY ) # convert Doxyfile to used doxygen version add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/convert_doxyfile ${DOXYGEN_EXECUTABLE} ${DOXYFILE}.in ${DOXYFILE} ${LOGFILE} BYPRODUCTS ${LOGFILE} COMMENT "Converting ${DOXYFILE} to doxygen version ${DOXYGEN_VERSION_SHORT}" VERBATIM ) # generate screen shot using FLUID --autodoc target_dir # generate HTML documentation add_custom_target(fluid_docs COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/src/ COMMAND fltk::fluid -scheme gtk+ --autodoc ${CMAKE_CURRENT_BINARY_DIR}/src/ COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating HTML documentation" VERBATIM ) add_dependencies(fluid_docs fltk::fluid) endif(FLTK_BUILD_FLUID_DOCS) #-------------------------- # build pdf documentation #-------------------------- if(FLTK_BUILD_PDF_DOCS AND FLTK_BUILD_FLUID_DOCS) # generate Doxygen input file "Doxybook" set(GENERATE_FLUID_HTML NO) set(GENERATE_LATEX YES) set(LATEX_HEADER "${CMAKE_CURRENT_BINARY_DIR}/fluid-book.tex") set(FL_HTML_INDEX "FL_NO_HTML_INDEX") set(DOXYFILE "Doxybook") set(LOGFILE "${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}_error.log") # configure Doxygen input file for PDF docs (Doxybook.in) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}.in @ONLY ) # convert Doxybook to current doxygen version set(DOXY_VERSION "${DOXYGEN_VERSION_SHORT}") # add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/convert_doxyfile ${DOXYGEN_EXECUTABLE} ${DOXYFILE}.in ${DOXYFILE} ${LOGFILE} BYPRODUCTS ${LOGFILE} COMMENT "Converting ${DOXYFILE} to doxygen version ${DOXYGEN_VERSION_SHORT}" VERBATIM ) # generate LaTeX title fluid-title.tex configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/fluid-title.tex.in ${CMAKE_CURRENT_BINARY_DIR}/fluid-title.tex @ONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/make_pdf.in ${CMAKE_CURRENT_BINARY_DIR}/make_pdf @ONLY ) # generate fluid.pdf add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/fluid.pdf COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/make_header ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/fluid-title.tex ${CMAKE_CURRENT_BINARY_DIR}/fluid-book.tex COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE} COMMAND ${CMAKE_CURRENT_BINARY_DIR}/make_pdf COMMAND cp -f latex/refman.pdf fluid.pdf DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE} ${CMAKE_CURRENT_BINARY_DIR}/fluid-title.tex WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating FLUID PDF documentation" VERBATIM ) # add target 'pdf' add_custom_target(fluid_pdf DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/fluid.pdf ) add_dependencies(fluid_pdf fluid_docs) endif(FLTK_BUILD_PDF_DOCS AND FLTK_BUILD_FLUID_DOCS) #--------------------------------------- # install FLUID html + pdf documentation #--------------------------------------- if(FLTK_INSTALL_FLUID_DOCS AND FLTK_BUILD_FLUID_DOCS) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION ${FLTK_DATADIR}/doc/fltk/fluid ) endif(FLTK_INSTALL_FLUID_DOCS AND FLTK_BUILD_FLUID_DOCS) if(FLTK_INSTALL_PDF_DOCS AND FLTK_BUILD_PDF_DOCS AND FLTK_BUILD_FLUID_DOCS) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/fluid.pdf DESTINATION ${FLTK_DATADIR}/doc/fltk/ ) endif(FLTK_INSTALL_PDF_DOCS AND FLTK_BUILD_PDF_DOCS AND FLTK_BUILD_FLUID_DOCS) fltk-1.4.3/fluid/documentation/generated.dox.in0000644000175000017500000000021115004135251021632 0ustar albrechtalbrecht
Generated on @CURRENT_DATE@ from Git revision @FLTK_GIT_REVISION@ by Doxygen version @DOXYGEN_VERSION_SHORT@ fltk-1.4.3/fluid/fluid.plist0000644000175000017500000000274115004135251016074 0ustar albrechtalbrecht CFBundleInfoDictionaryVersion 6.0 CFBundleExecutable fluid CFBundleIdentifier org.fltk.fluid CFBundleVersion 1.4.3 CFBundleDevelopmentRegion English NSHumanReadableCopyright Copyright 1998-2025 by Bill Spitzak and others CFAppleHelpAnchor help CFBundleName Fluid CFBundlePackageType APPL CFBundleSignature FLID CFBundleIconFile fluid.icns CFBundleShortVersionString 1.4.3 CFBundleGetInfoString 1.4.3, Copyright 1998-2025 by Bill Spitzak and others CFBundleDocumentTypes CFBundleTypeExtensions fl CFBundleTypeIconFile fluid.icns CFBundleTypeName FLUID Designer File CFBundleTypeOSTypes Flid CFBundleTypeRole Editor NSHighResolutionCapable fltk-1.4.3/fluid/ExternalCodeEditor_WIN32.h0000644000175000017500000000370715004135251020476 0ustar albrechtalbrecht// // External code editor management class for Windows // // Handles starting and keeping track of an external text editor, // including process start, temp file creation/removal, bookkeeping, killing.. // #ifndef _EXTCODEEDITOR_H #define _EXTCODEEDITOR_H /* We require at least Windows 2000 (WINVER == 0x0500) for GetFileSizeEx(). */ /* This must be defined before #include - MinGW doesn't do that. */ #if !defined(WINVER) || (WINVER < 0x0500) # ifdef WINVER # undef WINVER # endif # define WINVER 0x0500 #endif #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) # ifdef _WIN32_WINNT # undef _WIN32_WINNT # endif # define _WIN32_WINNT 0x0500 #endif #include /* CreateFile().. */ #include /* sprintf().. */ class ExternalCodeEditor { PROCESS_INFORMATION pinfo_; // CreateProcess() handle to running process FILETIME file_mtime_; // last modify time of the file (used to determine if file changed) LARGE_INTEGER file_size_; // last file size (used to determine if changed) const char * filename_; // tmpfilename editor uses protected: void kill_editor(); void reap_cleanup(); const char *create_tmpdir(); const char *tmp_filename(); int start_editor(const char *cmd, const char *filename); void set_filename(const char *val); public: ExternalCodeEditor(); ~ExternalCodeEditor(); int is_editing(); int reap_editor(DWORD *pid_reaped=NULL); void close_editor(); const char *filename() { return filename_; } int open_editor(const char *editor_cmd, const char *code); int handle_changes(const char **code, int force=0); int remove_tmpfile(); // Public static methods static void start_update_timer(); static void stop_update_timer(); static const char* tmpdir_name(); static void tmpdir_clear(); static int editors_open(); static void set_update_timer_callback(Fl_Timeout_Handler); }; #endif /*_EXTCODEEDITOR_H */ fltk-1.4.3/fluid/settings_panel.h0000644000175000017500000001236115004135251017103 0ustar albrechtalbrecht// // Setting and shell dialogs for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #ifndef settings_panel_h #define settings_panel_h #include #include "fluid.h" #include "widget_browser.h" #include "Fd_Snap_Action.h" #include "shell_command.h" #include #include #include "fluid_filename.h" #include #include /** // initialize the scheme from preferences */ void init_scheme(void); extern struct Fl_Menu_Item *dbmanager_item; extern void i18n_cb(Fl_Choice *,void *); extern void scheme_cb(Fl_Scheme_Choice *, void *); extern int w_settings_shell_list_selected; #include extern Fl_Double_Window *script_panel; #include extern Fl_Text_Editor *script_input; #include extern void propagate_load(Fl_Group*, void*); #include extern Fl_Return_Button *script_panel_ok; #include extern Fl_Button *script_panel_cancel; #include Fl_Double_Window* make_script_panel(); extern Fl_Double_Window *settings_window; #include extern Fl_Tabs *w_settings_tabs; extern Fl_Group *w_settings_general_tab; extern void scheme_cb(Fl_Scheme_Choice*, void*); extern Fl_Scheme_Choice *scheme_choice; #include extern Fl_Check_Button *tooltips_button; extern Fl_Check_Button *completion_button; extern Fl_Check_Button *openlast_button; extern Fl_Check_Button *prevpos_button; extern Fl_Check_Button *show_comments_button; #include extern Fl_Spinner *recent_spinner; extern Fl_Check_Button *use_external_editor_button; #include extern Fl_Input *editor_command_input; extern void toggle_guides_cb(Fl_Check_Button*, void*); extern Fl_Check_Button *guides_button; extern void toggle_restricted_cb(Fl_Check_Button*, void*); extern Fl_Check_Button *restricted_button; extern void toggle_ghosted_outline_cb(Fl_Check_Button*, void*); extern Fl_Check_Button *ghosted_outline_button; extern Fl_Group *w_settings_project_tab; extern Fl_Input *header_file_input; extern Fl_Input *code_file_input; extern Fl_Check_Button *include_H_from_C_button; extern Fl_Check_Button *use_FL_COMMAND_button; extern Fl_Check_Button *utf8_in_src_button; extern Fl_Check_Button *avoid_early_includes_button; extern Fl_Check_Button *w_proj_mergeback; extern Fl_Group *w_settings_layout_tab; #include extern Fl_Choice *layout_choice; #include extern Fl_Menu_Button *w_layout_menu; #include extern void edit_layout_preset_cb(Fl_Button*, long); extern Fl_Button *preset_choice[3]; #include extern Fl_Menu_Item fontmenu_w_default[]; extern Fl_Group *w_settings_shell_tab; #include extern Fl_Browser *w_settings_shell_list; extern Fl_Group *w_settings_shell_toolbox; extern Fl_Button *w_settings_shell_dup; extern Fl_Button *w_settings_shell_remove; extern Fl_Menu_Button *w_settings_shell_menu; extern Fl_Button *w_settings_shell_play; extern Fl_Group *w_settings_shell_cmd; #include extern Fl_Text_Editor *w_settings_shell_command; extern Fl_Menu_Button *w_settings_shell_text_macros; extern Fl_Box *w_settings_shell_fd_project; extern Fl_Box *w_settings_shell_fd_user; extern Fl_Group *w_settings_i18n_tab; extern void i18n_type_cb(Fl_Choice*, void*); extern Fl_Choice *i18n_type_chooser; extern Fl_Group *i18n_gnu_group; extern Fl_Input *i18n_gnu_include_input; extern Fl_Input *i18n_gnu_conditional_input; extern Fl_Input *i18n_gnu_function_input; extern Fl_Input *i18n_gnu_static_function_input; extern Fl_Group *i18n_posix_group; extern Fl_Input *i18n_pos_include_input; extern Fl_Input *i18n_pos_conditional_input; extern Fl_Input *i18n_pos_file_input; #include extern Fl_Int_Input *i18n_pos_set_input; #include extern Fl_Group *w_settings_user_tab; extern Fl_Menu_Item fontmenu[]; extern Fl_Menu_Item colormenu[]; extern Fl_Choice *w_settings_user_commenttext; Fl_Double_Window* make_settings_window(); extern Fl_Menu_Item menu_layout_choice[]; extern Fl_Menu_Item menu_w_layout_menu[]; #define w_layout_menu_rename (menu_w_layout_menu+0) extern Fl_Menu_Item *w_layout_menu_storage[4]; #define w_layout_menu_load (menu_w_layout_menu+5) #define w_layout_menu_save (menu_w_layout_menu+6) #define w_layout_menu_delete (menu_w_layout_menu+7) extern Fl_Menu_Item menu_w_settings_shell_menu[]; extern Fl_Menu_Item menu_Store[]; extern Fl_Menu_Item menu_Condition[]; extern Fl_Menu_Item menu_w_settings_shell_text_macros[]; extern Fl_Menu_Item menu_i18n_type_chooser[]; extern Fl_Double_Window *shell_run_window; #include extern Fl_Terminal *shell_run_terminal; extern Fl_Return_Button *shell_run_button; Fl_Double_Window* make_shell_window(); #endif fltk-1.4.3/fluid/Fl_Function_Type.h0000644000175000017500000002020515004135251017267 0ustar albrechtalbrecht// // C function type header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_FL_FUNCTION_TYPE_H #define _FLUID_FL_FUNCTION_TYPE_H #include "Fl_Type.h" #include "Fluid_Image.h" #ifdef _WIN32 #include "ExternalCodeEditor_WIN32.h" #else #include "ExternalCodeEditor_UNIX.h" #endif #include #include #include #include #include #include extern class Fl_Class_Type *current_class; int has_toplevel_function(const char *rtype, const char *sig); const char *c_check(const char *c, int type = 0); // ---- Fl_Function_Type declaration class Fl_Function_Type : public Fl_Type { typedef Fl_Type super; const char* return_type; char public_, cdecl_, constructor, havewidgets; public: Fl_Function_Type(); ~Fl_Function_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; void open() FL_OVERRIDE; int ismain() {return name_ == 0;} const char *type_name() FL_OVERRIDE {return "Function";} const char *title() FL_OVERRIDE { return name() ? name() : "main()"; } int can_have_children() const FL_OVERRIDE {return 1;} int is_code_block() const FL_OVERRIDE {return 1;} int is_public() const FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Function; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Function) ? true : super::is_a(inID); } void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; int has_signature(const char *, const char*) const; }; // ---- Fl_Code_Type declaration class Fl_Code_Type : public Fl_Type { typedef Fl_Type super; ExternalCodeEditor editor_; int cursor_position_; int code_input_scroll_row; int code_input_scroll_col; public: Fl_Code_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; void write(Fd_Project_Writer &f) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE { } void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "code";} int is_code_block() const FL_OVERRIDE {return 0;} ID id() const FL_OVERRIDE { return ID_Code; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Code) ? true : super::is_a(inID); } int is_public() const FL_OVERRIDE { return -1; } int is_editing(); int reap_editor(); int handle_editor_changes(); }; // ---- Fl_CodeBlock_Type declaration class Fl_CodeBlock_Type : public Fl_Type { typedef Fl_Type super; const char* after; public: Fl_CodeBlock_Type(); ~Fl_CodeBlock_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "codeblock";} int is_code_block() const FL_OVERRIDE {return 1;} int can_have_children() const FL_OVERRIDE {return 1;} int is_public() const FL_OVERRIDE { return -1; } ID id() const FL_OVERRIDE { return ID_CodeBlock; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_CodeBlock) ? true : super::is_a(inID); } void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; }; // ---- Fl_Decl_Type declaration class Fl_Decl_Type : public Fl_Type { typedef Fl_Type super; protected: char public_; char static_; public: Fl_Decl_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE { } void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "decl";} void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; int is_public() const FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Decl; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Decl) ? true : super::is_a(inID); } }; // ---- Fl_Data_Type declaration class Fl_Data_Type : public Fl_Decl_Type { typedef Fl_Decl_Type super; const char *filename_; int text_mode_; public: Fl_Data_Type(); ~Fl_Data_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE {} void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "data";} void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Data; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Data) ? true : super::is_a(inID); } }; // ---- Fl_DeclBlock_Type declaration class Fl_DeclBlock_Type : public Fl_Type { typedef Fl_Type super; enum { CODE_IN_HEADER = 1, CODE_IN_SOURCE = 2, STATIC_IN_HEADER = 4, STATIC_IN_SOURCE = 8 }; const char* after; ///< code after all children of this block int write_map_; ///< see enum above public: Fl_DeclBlock_Type(); ~Fl_DeclBlock_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; void write_static(Fd_Code_Writer& f) FL_OVERRIDE; void write_static_after(Fd_Code_Writer& f) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "declblock";} void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; int can_have_children() const FL_OVERRIDE {return 1;} int is_decl_block() const FL_OVERRIDE {return 1;} int is_public() const FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_DeclBlock; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_DeclBlock) ? true : super::is_a(inID); } }; // ---- Fl_Comment_Type declaration class Fl_Comment_Type : public Fl_Type { typedef Fl_Type super; char in_c_, in_h_, style_; public: Fl_Comment_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE { } void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "comment";} void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; int is_public() const FL_OVERRIDE { return 1; } ID id() const FL_OVERRIDE { return ID_Comment; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Comment) ? true : super::is_a(inID); } }; // ---- Fl_Class_Type declaration class Fl_Class_Type : public Fl_Type { typedef Fl_Type super; const char* subclass_of; char public_; const char* class_prefix; public: Fl_Class_Type(); ~Fl_Class_Type(); // state variables for output: char write_public_state; // true when public: has been printed Fl_Class_Type* parent_class; // save class if nested // Fl_Type *make(Strategy strategy) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; void open() FL_OVERRIDE; const char *type_name() FL_OVERRIDE {return "class";} int can_have_children() const FL_OVERRIDE {return 1;} int is_decl_block() const FL_OVERRIDE {return 1;} int is_class() const FL_OVERRIDE {return 1;} int is_public() const FL_OVERRIDE; ID id() const FL_OVERRIDE { return ID_Class; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Class) ? true : super::is_a(inID); } void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; // class prefix attribute access void prefix(const char* p); const char* prefix() const {return class_prefix;} }; #endif // _FLUID_FL_FUNCTION_TYPE_H fltk-1.4.3/fluid/CMakeLists.txt0000644000175000017500000001621315004135251016453 0ustar albrechtalbrecht# # CMakeLists.txt to build fluid for the FLTK project using CMake (www.cmake.org) # # Copyright 1998-2025 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # # Targets that will be built: fluid, fluid-shared, and fluid-cmd (Windows only) set(TARGETS "") # Defaults to be used and potentially modified later set(BACKEND_APPLE FALSE) # FIXME: should be global, e.g. FLTK_BACKEND_APPLE set(ICON_NAME "") set(ICON_PATH "") set(SUFFIX "UNIX") # suffix for platform specific source files # platform specific settings if(APPLE AND NOT FLTK_BACKEND_X11) # macOS "native" set(BACKEND_APPLE TRUE) set(ICON_NAME fluid.icns) set(ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/icons/${ICON_NAME}") elseif(WIN32) set(SUFFIX "WIN32") endif() # This macro is used to avoid duplicate code to create executable programs. # This must be a macro because it changes at least one global variable: TARGETS. # This macro also uses some (local) variables defined above. # In the future this might be converted to a function to avoid side effects. macro(make_target TARGET GUI SOURCES LIBS EXPORT_NAME) if(ICON_PATH) list(APPEND SOURCES ${ICON_PATH}) # macOS only endif() # message(STATUS "[fluid] make_target ${TARGET} ${GUI} ${SOURCES} ${LIBS} ${EXPORT_NAME}") # Options WIN32 and MACOSX_BUNDLE build a Windows GUI program or macOS bundle, # respectively. Both options are ignored on other platforms. if(${GUI}) add_executable(${TARGET} WIN32 MACOSX_BUNDLE ${SOURCES}) else() add_executable(${TARGET} ${SOURCES}) endif(${GUI}) list(APPEND TARGETS ${TARGET}) if(BACKEND_APPLE) # set bundle properties set_target_properties(${TARGET} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/${TARGET}.plist") set_target_properties(${TARGET} PROPERTIES MACOSX_BUNDLE_ICON_FILE ${ICON_NAME}) set_target_properties(${TARGET} PROPERTIES XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.fltk.${TARGET}") # install command line tool install(PROGRAMS $ DESTINATION ${FLTK_BINDIR}) # create macOS bundle wrapper script set(WRAPPER "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/${TARGET}") add_custom_command( TARGET ${TARGET} POST_BUILD COMMAND cp ${FLTK_SOURCE_DIR}/CMake/macOS-bundle-wrapper.in ${WRAPPER} COMMAND chmod u+x,g+x,o+x ${WRAPPER} BYPRODUCTS ${WRAPPER} VERBATIM ) unset(WRAPPER) endif(BACKEND_APPLE) target_link_libraries(${TARGET} PRIVATE ${LIBS}) set_target_properties(${TARGET} PROPERTIES EXPORT_NAME ${EXPORT_NAME}) endmacro(make_target TARGET GUI SOURCES LIBS EXPORT_NAME) # Main source and header files used for the executable because macOS (Xcode) # needs at least one source file (main.cxx) to link the main program properly set(MAIN_FILES fluid.cxx fluid.h) # Source files for 'fluid-lib': all source files except ${MAIN_FILES} set(CPPFILES CodeEditor.cxx StyleParse.cxx Fd_Snap_Action.cxx Fl_Function_Type.cxx Fl_Grid_Type.cxx Fl_Group_Type.cxx Fl_Menu_Type.cxx Fl_Type.cxx Fl_Widget_Type.cxx Fl_Window_Type.cxx Fl_Button_Type.cxx Fluid_Image.cxx about_panel.cxx align_widget.cxx settings_panel.cxx autodoc.cxx code.cxx custom_widgets.cxx factory.cxx file.cxx fluid_filename.cxx function_panel.cxx mergeback.cxx pixmaps.cxx shell_command.cxx codeview_panel.cxx template_panel.cxx undo.cxx widget_browser.cxx widget_panel.cxx ExternalCodeEditor_${SUFFIX}.cxx ) # List header files in Apple's Xcode IDE set(HEADERFILES CodeEditor.h Fd_Snap_Action.h Fl_Function_Type.h Fl_Grid_Type.h Fl_Group_Type.h Fl_Menu_Type.h Fl_Type.h Fl_Widget_Type.h Fl_Window_Type.h Fl_Button_Type.h Fluid_Image.h StyleParse.h about_panel.h align_widget.h settings_panel.h autodoc.h code.h comments.h custom_widgets.h factory.h file.h function_panel.h mergeback.h print_panel.h pixmaps.h shell_command.h codeview_panel.h template_panel.h undo.h widget_browser.h widget_panel.h ExternalCodeEditor_${SUFFIX}.h ) source_group("Header Files" FILES ${HEADERFILES}) # Build a local object library to avoid compiling all source files # multiple times for all fluid targets on Windows (fluid + fluid-cmd). add_library(fluid-lib OBJECT EXCLUDE_FROM_ALL) target_sources(fluid-lib PRIVATE ${CPPFILES} ${HEADERFILES}) target_include_directories(fluid-lib PUBLIC .) target_link_libraries(fluid-lib PUBLIC fltk::images) # Build targets make_target(fluid TRUE "${MAIN_FILES}" fluid-lib fluid) # Build the console app on Windows # This is done for all Windows targets, even if cross-compiling. if(WIN32) make_target(fluid-cmd FALSE "${MAIN_FILES}" fluid-lib fluid-cmd) set(FLTK_FLUID_EXECUTABLE fltk::fluid-cmd) else() set(FLTK_FLUID_EXECUTABLE fltk::fluid) endif() # Add the "shared" executable (linked against the shared FLTK libs). # Note 1: only the GUI version is built as "shared" executable. # Note 2: For MSVC we need the special object library 'call_main'. if(FLTK_BUILD_SHARED_LIBS) add_library(fluid-lib-shared OBJECT EXCLUDE_FROM_ALL) target_sources(fluid-lib-shared PRIVATE ${CPPFILES} ${HEADERFILES}) target_include_directories(fluid-lib-shared PUBLIC .) if(MSVC) target_link_libraries(fluid-lib-shared PUBLIC fltk::fltk-shared) else() target_link_libraries(fluid-lib-shared PUBLIC fltk::images-shared) endif(MSVC) if(MSVC) make_target(fluid-shared TRUE "${MAIN_FILES}" "fluid-lib-shared;call_main" fluid-shared) else() make_target(fluid-shared TRUE "${MAIN_FILES}" fluid-lib-shared fluid-shared) endif() # experimental # if(NOT WIN32) # set(FLTK_FLUID_EXECUTABLE fltk::fluid-shared) # message(STATUS "** experimental ** FLTK_FLUID_EXECUTABLE = ${FLTK_FLUID_EXECUTABLE}") # endif() endif(FLTK_BUILD_SHARED_LIBS) # export the variable FLTK_FLUID_EXECUTABLE to the parent scope set(FLTK_FLUID_EXECUTABLE "${FLTK_FLUID_EXECUTABLE}" PARENT_SCOPE) # Create aliases for all targets foreach(tgt ${TARGETS}) add_executable(fltk::${tgt} ALIAS ${tgt}) endforeach() # Install the GUI and (on Windows only) the commandline tool 'fluid-cmd' # message(STATUS "Fluid: INSTALL TARGETS: ${TARGETS}") install(TARGETS ${TARGETS} EXPORT FLTK-Targets RUNTIME DESTINATION ${FLTK_BINDIR} LIBRARY DESTINATION ${FLTK_LIBDIR} ARCHIVE DESTINATION ${FLTK_LIBDIR} BUNDLE DESTINATION ${FLTK_BINDIR} # macOS: bundles ) # Install desktop files if(UNIX) install(FILES fluid.desktop DESTINATION ${FLTK_DATADIR}/applications ) # Install mime-type file(x-fluid.desktop method is deprecated) install(FILES fluid.xml DESTINATION ${FLTK_DATADIR}/mime/packages ) # Install desktop icons foreach(icon 32 48 64 128) install(FILES icons/fluid-${icon}.png DESTINATION ${FLTK_DATADIR}/icons/hicolor/${icon}x${icon}/apps RENAME fluid.png ) endforeach() endif(UNIX) fltk-1.4.3/fluid/StyleParse.cxx0000644000175000017500000002145615004135251016537 0ustar albrechtalbrecht// // Syntax highlighting for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // Copyright 2020 Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "StyleParse.h" #include #include #include #include // bsearch() // Sorted list of C/C++ keywords... static const char * const code_keywords[] = { "and", "and_eq", "asm", "bitand", "bitor", "break", "case", "catch", "compl", "continue", "default", "delete", "do", "else", "false", "for", "goto", "if", "new", "not", "not_eq", "operator", "or", "or_eq", "return", "switch", "template", "this", "throw", "true", "try", "while", "xor", "xor_eq" }; // Sorted list of C/C++ types... static const char * const code_types[] = { "auto", "bool", "char", "class", "const", "const_cast", "double", "dynamic_cast", "enum", "explicit", "extern", "float", "friend", "inline", "int", "long", "mutable", "namespace", "private", "protected", "public", "register", "short", "signed", "sizeof", "static", "static_cast", "struct", "template", "typedef", "typename", "union", "unsigned", "virtual", "void", "volatile" }; // 'compare_keywords()' - Compare two keywords... extern "C" { static int compare_keywords(const void *a, const void *b) { return strcmp(*((const char **)a), *((const char **)b)); } } // See if 'find' is a C/C++ keyword. // Refer to bsearch(3) for return value. // static void* search_keywords(char *find) { return bsearch(&find, code_keywords, sizeof(code_keywords) / sizeof(code_keywords[0]), sizeof(code_keywords[0]), compare_keywords); } // See if 'find' is a C/C++ type. // Refer to bsearch(3) for return value. // static void* search_types(char *find) { return bsearch(&find, code_types, sizeof(code_types) / sizeof(code_types[0]), sizeof(code_types[0]), compare_keywords); } // Handle style parsing over a character // Handles updating col counter when \n encountered. // Applies the current style, advances to next text + style char. // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_over_char(int handle_crlf) { char c = *tbuff; // End of line? if ( handle_crlf ) { if ( c == '\n' ) { lwhite = 1; // restart leading white flag } else { // End of leading white? (used by #directive) if ( !strchr(" \t", c) ) lwhite = 0; } } // Adjust and advance // If handling crlfs, zero col on crlf. If not handling, let col continue to count past crlf // e.g. for multiline #define's that have lines ending in backslashes. // col = (c=='\n') ? (handle_crlf ? 0 : col) : col+1; // column counter tbuff++; // advance text ptr *sbuff++ = style; // apply style & advance its ptr if ( --len <= 0 ) return 0; // keep track of length return 1; } // Parse over white space using current style // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_over_white() { while ( len > 0 && strchr(" \t", *tbuff)) { if ( !parse_over_char() ) return 0; } return 1; } // Parse over non-white alphabetic text // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_over_alpha() { while ( len > 0 && isalpha(*tbuff) ) { if ( !parse_over_char() ) return 0; } return 1; } // Parse to end of line in specified style. // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_to_eol(char s) { char save = style; style = s; while ( *tbuff != '\n' ) { if ( !parse_over_char() ) return 0; } style = save; return 1; } // Parse a block comment until end of comment or buffer. // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_block_comment() { char save = style; style = 'C'; // block comment style while ( len > 0 ) { if ( strncmp(tbuff, "*/", 2) == 0 ) { if ( !parse_over_char() ) return 0; // handle '*' if ( !parse_over_char() ) return 0; // handle '/' break; } if ( !parse_over_char() ) return 0; // handle comment text } style = save; // revert style return 1; } // Copy keyword from tbuff -> keyword[] buffer void StyleParse::buffer_keyword() { char *key = keyword; char *kend = key + sizeof(keyword) - 1; // end of buffer for ( const char *s=tbuff; (islower(*s) || *s=='_') && (key < kend); *key++ = *s++ ) { } *key = 0; // terminate } // Parse over specified 'key'word in specified style 's'. // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_over_key(const char *key, char s) { char save = style; style = s; // Parse over the keyword while applying style to sbuff while ( *key++ ) { if ( !parse_over_char() ) return 0; } last = 1; style = save; return 1; } // Parse over angle brackets <..> in specified style. // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_over_angles(char s) { if ( *tbuff != '<' ) return 1; // not <..>, early exit char save = style; style = s; // Parse over angle brackets in specified style while ( len > 0 && *tbuff != '>' ) { if ( !parse_over_char() ) return 0; } // parse over '<' and angle content if ( !parse_over_char() ) return 0; // parse over trailing '>' style = save; return 1; } // Parse line for possible keyword // spi.keyword[] will contain parsed word. // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_keyword() { // Parse into 'keyword' buffer buffer_keyword(); char *key = keyword; // C/C++ type? (void, char..) if ( search_types(key) ) return parse_over_key(key, 'F'); // 'type' style // C/C++ Keyword? (switch, return..) else if ( search_keywords(key) ) return parse_over_key(key, 'G'); // 'keyword' style // Not a type or keyword? Parse over it return parse_over_key(key, style); } // Style parse a quoted string, either "" or ''. // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_quoted_string(char quote_char, // e.g. '"' or '\'' char in_style) { // style for quoted text style = in_style; // start string style if ( !parse_over_char() ) return 0; // parse over opening quote // Parse until closing quote reached char c; while ( len > 0 ) { c = tbuff[0]; if ( c == quote_char ) { // Closing quote? Parse and done if ( !parse_over_char() ) return 0; // close quote break; } else if ( c == '\\' ) { // Escape sequence? Parse over, continue if ( !parse_over_char() ) return 0; // escape if ( !parse_over_char() ) return 0; // char being escaped continue; } // Keep parsing until end of buffer or closing quote.. if ( !parse_over_char() ) return 0; } style = 'A'; // revert normal style return 1; } // Style parse a directive (#include, #define..) // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_directive() { style = 'E'; // start directive style if ( !parse_over_char() ) return 0; // Parse over '#' if ( !parse_over_white() ) return 0; // Parse over any whitespace after '#' if ( !parse_over_alpha() ) return 0; // Parse over the directive style = 'A'; // revert normal style if ( !parse_over_white() ) return 0; // Parse over white after directive if ( !parse_over_angles('D')) return 0; // #include <..> (if any) return 1; } // Style parse a line comment to end of line. // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_line_comment() { return parse_to_eol('B'); } // Parse a backslash escape character sequence. // Purposefully don't 'handle' \n, since an escaped \n should be // a continuation of a line, such as in a multiline #directive. // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_escape() { const char no_crlf = 0; if ( !parse_over_char(no_crlf) ) return 0; // backslash if ( !parse_over_char(no_crlf) ) return 0; // char escaped return 1; } // Parse all other non-specific characters // Returns 0 if hit end of buffer, 1 otherwise. // int StyleParse::parse_all_else() { last = isalnum(*tbuff) || *tbuff == '_' || *tbuff == '.'; return parse_over_char(); } fltk-1.4.3/fluid/codeview_panel.fl0000644000175000017500000004031115004135251017216 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} comment {// // Code dialogs for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // } {in_source in_header } decl {\#include "fluid.h"} {private local } decl {\#include "file.h"} {private local } decl {\#include "../src/flstring.h"} {selected private local } decl {\#include } {private local } decl {\#include } {private local } decl {char *cv_source_filename = NULL;} {private local } decl {char *cv_header_filename = NULL;} {private local } decl {char *cv_design_filename = NULL;} {private local } decl {int cv_code_choice;} {public local } decl {extern void select_only(Fl_Type *o);} {private global } decl {extern void reveal_in_browser(Fl_Type *t);} {private global } Function {update_codeview_position()} { comment {Update the header and source code highlighting depending on the currently selected object The Code View system offers an immediate preview of the code files that will be generated by FLUID. It also marks the code generated for the last selected item in the header and the source file.} open return_type void } { code {if (!codeview_panel || !codeview_panel->visible()) return; if (cv_autoposition->value()==0) return; if (codeview_panel && codeview_panel->visible() && Fl_Type::current) { int pos0 = 0, pos1 = 0; if (cv_source->visible_r()) { switch (cv_code_choice) { case 0: // prolog: not yet (include statements) pos0 = Fl_Type::current->code1_start; pos1 = Fl_Type::current->code2_end; break; case 1: // static: callbacks, menu declarations pos0 = Fl_Type::current->code_static_start; pos1 = Fl_Type::current->code_static_end; break; case 2: // code: entire implementation block including children pos0 = Fl_Type::current->code1_start; pos1 = Fl_Type::current->code2_end; break; case 3: // code1: all implementation code before the children pos0 = Fl_Type::current->code1_start; pos1 = Fl_Type::current->code1_end; break; case 4: // code1: all implementation code before the children pos0 = Fl_Type::current->code2_start; pos1 = Fl_Type::current->code2_end; break; } if (pos0>=0) { if (pos1buffer()->line_end(pos0); cv_source->buffer()->highlight(pos0, pos1); int line = cv_source->buffer()->count_lines(0, pos0); cv_source->scroll(line, 0); } } if (cv_header->visible_r()) { switch (cv_code_choice) { case 0: // prolog: not yet (include statements) case 1: // static: callbacks, menu declarations pos0 = Fl_Type::current->header_static_start; pos1 = Fl_Type::current->header_static_end; break; case 2: // code: entire implementation block including children pos0 = Fl_Type::current->header1_start; pos1 = Fl_Type::current->header2_end; break; case 3: // code1: all implementation code before the children pos0 = Fl_Type::current->header1_start; pos1 = Fl_Type::current->header1_end; break; case 4: // code1: all implementation code before the children pos0 = Fl_Type::current->header2_start; pos1 = Fl_Type::current->header2_end; break; } if (pos0>=0) { if (pos1buffer()->line_end(pos0); cv_header->buffer()->highlight(pos0, pos1); int line = cv_header->buffer()->count_lines(0, pos0); cv_header->scroll(line, 0); } } if (cv_project->visible_r()) { switch (cv_code_choice) { case 0: // prolog: not yet (include statements) case 1: // static: callbacks, menu declarations case 2: // code: entire implementation block including children pos0 = Fl_Type::current->proj1_start; pos1 = Fl_Type::current->proj2_end; break; case 3: // code1: all implementation code before the children pos0 = Fl_Type::current->proj1_start; pos1 = Fl_Type::current->proj1_end; break; case 4: // code1: all implementation code before the children pos0 = Fl_Type::current->proj2_start; pos1 = Fl_Type::current->proj2_end; break; } if (pos0>=0) { if (pos1buffer()->line_end(pos0); cv_project->buffer()->highlight(pos0, pos1); int line = cv_project->buffer()->count_lines(0, pos0); cv_project->scroll(line, 0); } } }} {} } Function {update_codeview_position_cb(class Fl_Tabs*, void*)} { comment {Callback to update the codeview position.} open return_type void } { code {// make sure that the selected tab shows the current view update_codeview_cb(0,0); // highlight the selected widget in the selected tab update_codeview_position();} {} } Function {update_codeview_cb(class Fl_Button*, void*)} { comment {Generate a header, source, strings, or design file in a temporary directory and load those into the Code Viewer widgets.} open return_type void } { code {if (!codeview_panel || !codeview_panel->visible()) return; if (!cv_source_filename) { cv_source_filename = (char*)malloc(FL_PATH_MAX); fl_strlcpy(cv_source_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_source_filename, "codeview_tmp.cxx", FL_PATH_MAX); } if (!cv_header_filename) { cv_header_filename = (char*)malloc(FL_PATH_MAX); fl_strlcpy(cv_header_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_header_filename, "codeview_tmp.h", FL_PATH_MAX); } if (!cv_design_filename) { cv_design_filename = (char*)malloc(FL_PATH_MAX); fl_strlcpy(cv_design_filename, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_design_filename, "codeview_tmp.fl", FL_PATH_MAX); } if (cv_project->visible_r()) { write_file(cv_design_filename, false, true); int top = cv_project->top_line(); cv_project->buffer()->loadfile(cv_design_filename); cv_project->scroll(top, 0); } else if (cv_strings->visible_r()) { static const char *exts[] = { ".txt", ".po", ".msg" }; char fn[FL_PATH_MAX+1]; fl_strlcpy(fn, get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(fn, "strings", FL_PATH_MAX); fl_filename_setext(fn, FL_PATH_MAX, exts[g_project.i18n_type]); write_strings(fn); int top = cv_strings->top_line(); cv_strings->buffer()->loadfile(fn); cv_strings->scroll(top, 0); } else if (cv_source->visible_r() || cv_header->visible_r()) { Fl_String code_file_name_bak = g_project.code_file_name; g_project.code_file_name = cv_source_filename; Fl_String header_file_name_bak = g_project.header_file_name; g_project.header_file_name = cv_header_filename; // generate the code and load the files Fd_Code_Writer f; // generate files if (f.write_code(cv_source_filename, cv_header_filename, true)) { // load file into source editor int pos = cv_source->top_line(); cv_source->buffer()->loadfile(cv_source_filename); cv_source->scroll(pos, 0); // load file into header editor pos = cv_header->top_line(); cv_header->buffer()->loadfile(cv_header_filename); cv_header->scroll(pos, 0); // update the source code highlighting update_codeview_position(); } g_project.code_file_name = code_file_name_bak; g_project.header_file_name = header_file_name_bak; }} {} } Function {update_codeview_timer(void*)} { comment {This is called by the timer itself } open return_type void } { code {update_codeview_cb(0,0);} {} } Function {codeview_defer_update()} {open return_type void } { code {// we will only update earliest 0.5 seconds after the last change, and only // if no other change was made, so dragging a widget will not generate any // CPU load Fl::remove_timeout(update_codeview_timer, 0); Fl::add_timeout(0.5, update_codeview_timer, 0);} {} } Function {codeview_toggle_visibility()} { comment {Show or hide the source code preview. The state is stored in the app preferences. } open return_type void } { code {if (!codeview_panel) { make_codeview(); codeview_panel->callback((Fl_Callback*)toggle_codeview_cb); Fl_Preferences svp(fluid_prefs, "codeview"); int autorefresh; svp.get("autorefresh", autorefresh, 1); cv_autorefresh->value(autorefresh); int autoposition; svp.get("autoposition", autoposition, 1); cv_autoposition->value(autoposition); int tab; svp.get("tab", tab, 0); if (tab>=0 && tabchildren()) cv_tab->value(cv_tab->child(tab)); svp.get("code_choice", cv_code_choice, 2); cv_code_choice_w->value(cv_code_choice_w->find_item_with_argument(cv_code_choice)); if (!position_window(codeview_panel,"codeview_pos", 0, 320, 120, 550, 500)) return; } if (codeview_panel->visible()) { codeview_panel->hide(); codeview_item->label("Show Code View"); } else { codeview_panel->show(); codeview_item->label("Hide Code View"); update_codeview_cb(0,0); }} {} } Function {make_codeview()} {open } { Fl_Window codeview_panel { label {Code View} callback toggle_codeview_cb open xywh {389 507 520 515} type Double align 80 resizable size_range {384 120 0 0} visible } { Fl_Tabs cv_tab { callback update_codeview_position_cb open xywh {10 10 500 440} selection_color 4 labelcolor 7 resizable } { Fl_Group cv_source_tab { label Source open xywh {10 35 500 415} labelsize 13 resizable } { Fl_Text_Editor cv_source { xywh {10 40 500 410} textfont 4 textsize 11 resizable code0 {\#include "CodeEditor.h"} code1 {o->linenumber_width(60);} code2 {o->linenumber_size(o->Fl_Text_Display::textsize());} class CodeViewer } } Fl_Group {} { label Header open xywh {10 35 500 415} labelsize 13 hide } { Fl_Text_Editor cv_header { xywh {10 40 500 410} textfont 4 textsize 11 resizable code0 {\#include "CodeEditor.h"} code1 {o->linenumber_width(60);} code2 {o->linenumber_size(o->Fl_Text_Display::textsize());} class CodeViewer } } Fl_Group {} { label Strings open xywh {10 35 500 415} labelsize 13 hide } { Fl_Text_Display cv_strings { xywh {10 40 500 410} textfont 4 textsize 11 resizable code1 {o->linenumber_width(60);} code2 {o->linenumber_size(o->Fl_Text_Display::textsize());} class TextViewer } } Fl_Group {} { label Project open xywh {10 35 500 415} labelsize 13 hide } { Fl_Text_Display cv_project { xywh {10 40 500 410} textfont 4 textsize 11 resizable code1 {o->linenumber_width(60);} code2 {o->linenumber_size(o->Fl_Text_Display::textsize());} class TextViewer } } } Fl_Group cv_find_row {open xywh {10 460 500 20} } { Fl_Button cv_find_text_case { label aA xywh {244 460 25 20} type Toggle labelsize 11 } Fl_Input cv_find_text { label {Find:} callback {Fl_Text_Display *e = NULL; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { e = cv_header; } else if (cv_project->visible_r()) { e = cv_project; } if (e) { Fl_Text_Buffer *b = e->buffer(); int pos = e->insert_position(); int found = b->search_forward(pos, o->value(), &pos, cv_find_text_case->value()); if (found) { b->select(pos, pos + (int)strlen(o->value())); e->insert_position(pos); e->show_insert_position(); } }} xywh {40 460 200 20} labelsize 11 when 15 textsize 11 } Fl_Button {} { label {<<} callback {Fl_Text_Display *e = NULL; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { e = cv_header; } else if (cv_project->visible_r()) { e = cv_project; } if (e) { const char *needle = cv_find_text->value(); Fl_Text_Buffer *b = e->buffer(); int pos = e->insert_position()-1; if (pos < 0) pos = b->length()-1; int found = b->search_backward(pos, needle, &pos, cv_find_text_case->value()); if (!found) found = b->search_backward(b->length()-1, needle, &pos, cv_find_text_case->value()); if (found) { b->select(pos, pos + (int)strlen(needle)); e->insert_position(pos); e->show_insert_position(); } }} xywh {273 460 25 20} labelsize 11 } Fl_Button {} { label {>>} callback {Fl_Text_Display *e = NULL; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { e = cv_header; } else if (cv_project->visible_r()) { e = cv_project; } if (e) { const char *needle = cv_find_text->value(); Fl_Text_Buffer *b = e->buffer(); int pos = e->insert_position() + 1; if (pos+1 >= b->length()) pos = 0; int found = b->search_forward(pos, needle, &pos, cv_find_text_case->value()); if (!found && (pos > 0)) found = b->search_forward(0, needle, &pos, cv_find_text_case->value()); if (found) { b->select(pos, pos + (int)strlen(needle)); e->insert_position(pos); e->show_insert_position(); } }} xywh {298 460 25 20} labelsize 11 } Fl_Button {} { label Reveal callback {if (codeview_panel && codeview_panel->visible()) { Fl_Type *node = NULL; if (cv_source->visible_r()) node = Fl_Type::find_in_text(0, cv_source->insert_position()); else if (cv_header->visible_r()) node = Fl_Type::find_in_text(1, cv_header->insert_position()); else if (cv_project->visible_r()) node = Fl_Type::find_in_text(2, cv_project->insert_position()); if (node) { select_only(node); reveal_in_browser(node); if (Fl::event_clicks()==1) // double click node->open(); } }} xywh {327 460 61 20} labelsize 11 } Fl_Box {} { xywh {490 460 20 20} resizable } } Fl_Group cv_settings_row {open xywh {10 485 500 20} } { Fl_Button {} { label Refresh callback update_codeview_cb xywh {10 485 61 20} labelsize 11 } Fl_Light_Button cv_autorefresh { label {Auto-Refresh} xywh {77 485 91 20} labelsize 11 code0 {o->callback((Fl_Callback*)update_codeview_cb);} } Fl_Light_Button cv_autoposition { label {Auto-Position} xywh {172 485 89 20} labelsize 11 } Fl_Choice cv_code_choice_w { callback {cv_code_choice = (int)o->mvalue()->argument(); update_codeview_position();} open xywh {265 485 70 20} down_box BORDER_BOX labelsize 11 textsize 11 } { MenuItem {} { label prolog user_data 0 user_data_type long tooltip {Include statements in header or source code} xywh {0 0 100 20} labelsize 11 hide } MenuItem {} { label static user_data 1 user_data_type long tooltip {static declarations in source code} xywh {10 10 100 20} labelsize 11 } MenuItem {} { label code user_data 2 user_data_type long tooltip {widget code block including children} xywh {20 20 100 20} labelsize 11 } MenuItem {} { label {code 1} user_data 3 user_data_type long tooltip {widget code block before children} xywh {30 30 100 20} labelsize 11 } MenuItem {} { label {code 2} user_data 4 user_data_type long tooltip {widget code block after children} xywh {40 40 100 20} labelsize 11 } } Fl_Box {} { xywh {375 485 80 20} resizable } Fl_Button {} { label Close callback toggle_codeview_b_cb xywh {460 485 50 20} labelsize 11 } } } } comment { //} {in_source in_header } fltk-1.4.3/fluid/Fl_Widget_Type.h0000644000175000017500000000776515004135251016745 0ustar albrechtalbrecht// // Widget type header file for the Fast Light Tool Kit (FLTK). // // Type for creating all subclasses of Fl_Widget // This should have the widget pointer in it, but it is still in the // Fl_Type base class. // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_FL_WIDGET_TYPE_H #define _FLUID_FL_WIDGET_TYPE_H #include "Fl_Type.h" #define NUM_EXTRA_CODE 4 class Fl_Widget_Type; class Fluid_Image; extern void* const LOAD; extern Fl_Widget_Type *current_widget; // one of the selected ones extern const char* subclassname(Fl_Type* l); extern int is_name(const char *c); void selection_changed(Fl_Type* new_current); Fl_Type *sort(Fl_Type *parent); void comment_cb(class Fl_Text_Editor* i, void *v); class Fl_Widget_Type : public Fl_Type { typedef Fl_Type super; virtual Fl_Widget *widget(int,int,int,int) = 0; virtual Fl_Widget_Type *_make() = 0; // virtual constructor void setlabel(const char *) FL_OVERRIDE; const char *extra_code_[NUM_EXTRA_CODE]; const char *subclass_; const char *tooltip_; const char *image_name_; const char *inactive_name_; uchar hotspot_; protected: /// This variable is set for visible windows in batch mode. /// We can't open a window in batch mode, even if we want the "visible" flags /// set, so we need a second place to store this information while also /// disabling the output of the "hide" property by the Widget Type. uchar override_visible_; void write_static(Fd_Code_Writer& f) FL_OVERRIDE; void write_code1(Fd_Code_Writer& f) FL_OVERRIDE; void write_widget_code(Fd_Code_Writer& f); void write_extra_code(Fd_Code_Writer& f); void write_block_close(Fd_Code_Writer& f); void write_code2(Fd_Code_Writer& f) FL_OVERRIDE; void write_color(Fd_Code_Writer& f, const char*, Fl_Color); Fl_Widget *live_widget; public: Fl_Widget *o; int public_; int bind_image_; int compress_image_; int bind_deimage_; int compress_deimage_; int scale_image_w_, scale_image_h_; int scale_deimage_w_, scale_deimage_h_; Fluid_Image *image; void setimage(Fluid_Image *); Fluid_Image *inactive; void setinactive(Fluid_Image *); Fl_Widget_Type(); Fl_Type *make(Strategy strategy) FL_OVERRIDE; void open() FL_OVERRIDE; const char *extra_code(int n) const {return extra_code_[n];} void extra_code(int n,const char *); const char *subclass() const {return subclass_;} void subclass(const char *); const char *tooltip() const {return tooltip_;} void tooltip(const char *); const char *image_name() const {return image_name_;} void image_name(const char *); const char *inactive_name() const {return inactive_name_;} void inactive_name(const char *); uchar hotspot() const {return hotspot_;} void hotspot(uchar v) {hotspot_ = v;} uchar resizable() const; void resizable(uchar v); virtual int textstuff(int what, Fl_Font &, int &, Fl_Color &); virtual Fl_Menu_Item *subtypes(); ID id() const FL_OVERRIDE { return ID_Widget_; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Widget_) ? true : super::is_a(inID); } int is_widget() const FL_OVERRIDE; int is_true_widget() const FL_OVERRIDE { return 1; } int is_public() const FL_OVERRIDE; void write_properties(Fd_Project_Writer &f) FL_OVERRIDE; void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE; int read_fdesign(const char*, const char*) FL_OVERRIDE; Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; Fl_Widget *propagate_live_mode(Fl_Group* grp); void leave_live_mode() FL_OVERRIDE; void copy_properties() FL_OVERRIDE; virtual void ideal_size(int &w, int &h); ~Fl_Widget_Type(); void redraw(); }; extern Fl_Window *the_panel; #endif // _FLUID_FL_WIDGET_TYPE_H fltk-1.4.3/fluid/widget_panel.h0000644000175000017500000002166215004135251016532 0ustar albrechtalbrecht// // Widget panel for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #ifndef widget_panel_h #define widget_panel_h #include #include "custom_widgets.h" #include extern Fl_Double_Window *image_panel_window; #include extern void propagate_load(Fl_Group*, void*); extern Fl_Group *image_panel_imagegroup; #include #include extern Fl_Box *image_panel_data; extern Fluid_Coord_Input *image_panel_imagew; extern Fluid_Coord_Input *image_panel_imageh; #include #include extern void compress_image_cb(Fl_Check_Button*, void*); extern void bind_image_cb(Fl_Check_Button*, void*); extern Fl_Group *image_panel_deimagegroup; extern Fl_Box *image_panel_dedata; extern Fluid_Coord_Input *image_panel_deimagew; extern Fluid_Coord_Input *image_panel_deimageh; extern void compress_deimage_cb(Fl_Check_Button*, void*); extern void bind_deimage_cb(Fl_Check_Button*, void*); extern Fl_Button *image_panel_close; Fl_Double_Window* make_image_panel(); void run_image_panel(); #include extern Fl_Tabs *widget_tabs; extern Fl_Group *wp_gui_tab; #include extern void label_cb(Fl_Input*, void*); extern Fl_Input *wp_gui_label; #include extern Fl_Menu_Item labeltypemenu[]; extern void labeltype_cb(Fl_Choice*, void*); extern void image_cb(Fl_Input*, void*); extern Fl_Input *widget_image_input; extern void image_browse_cb(Fl_Button*, void*); extern void inactive_cb(Fl_Input*, void*); extern Fl_Input *widget_deimage_input; extern void inactive_browse_cb(Fl_Button*, void*); extern Fl_Group *wp_gui_alignment; extern void align_cb(Fl_Button*, void*); extern void align_text_image_cb(Fl_Choice*, void*); extern void align_position_cb(Fl_Choice*, void*); extern void position_group_cb(Fl_Group*, void*); extern void x_cb(Fluid_Coord_Input*, void*); extern Fluid_Coord_Input *widget_x_input; extern void y_cb(Fluid_Coord_Input*, void*); extern Fluid_Coord_Input *widget_y_input; extern void w_cb(Fluid_Coord_Input*, void*); extern Fluid_Coord_Input *widget_w_input; extern void h_cb(Fluid_Coord_Input*, void*); extern Fluid_Coord_Input *widget_h_input; extern void wc_relative_cb(Fl_Choice*, void*); extern void flex_size_group_cb(Fl_Group*, void*); extern Fl_Group *wp_gui_flexp; #include extern void flex_size_cb(Fl_Value_Input*, void*); extern Fl_Value_Input *widget_flex_size; extern void flex_fixed_cb(Fl_Check_Button*, void*); extern Fl_Check_Button *widget_flex_fixed; extern void values_group_cb(Fl_Group*, void*); extern Fl_Group *wp_gui_values; extern void slider_size_cb(Fl_Value_Input*, void*); extern void min_cb(Fl_Value_Input*, void*); extern void max_cb(Fl_Value_Input*, void*); extern void step_cb(Fl_Value_Input*, void*); extern void value_cb(Fl_Value_Input*, void*); extern void flex_margin_group_cb(Fl_Group*, void*); extern Fl_Group *wp_gui_margins; extern void flex_margin_left_cb(Fl_Value_Input*, void*); extern void flex_margin_top_cb(Fl_Value_Input*, void*); extern void flex_margin_right_cb(Fl_Value_Input*, void*); extern void flex_margin_bottom_cb(Fl_Value_Input*, void*); extern void flex_margin_gap_cb(Fl_Value_Input*, void*); extern void size_range_group_cb(Fl_Group*, void*); extern Fl_Group *wp_gui_sizerange; extern void min_w_cb(Fl_Value_Input*, void*); extern void min_h_cb(Fl_Value_Input*, void*); extern void set_min_size_cb(Fl_Button*, void*); extern void max_w_cb(Fl_Value_Input*, void*); extern void max_h_cb(Fl_Value_Input*, void*); extern void set_max_size_cb(Fl_Button*, void*); #include extern void shortcut_in_cb(Fl_Shortcut_Button*, void*); extern Fl_Shortcut_Button *wp_gui_shortcut; extern Fl_Group *wp_gui_xclass; extern void xclass_cb(Fl_Input*, void*); #include extern void border_cb(Fl_Light_Button*, void*); extern void modal_cb(Fl_Light_Button*, void*); extern void non_modal_cb(Fl_Light_Button*, void*); extern Fl_Group *wp_gui_attributes; extern void visible_cb(Fl_Light_Button*, void*); extern void active_cb(Fl_Light_Button*, void*); extern void resizable_cb(Fl_Light_Button*, void*); extern void hotspot_cb(Fl_Light_Button*, void*); extern void tooltip_cb(Fl_Input*, void*); extern Fl_Input *wp_gui_tooltip; extern Fl_Group *wp_style_tab; extern Fl_Group *wp_style_label; extern Fl_Menu_Item fontmenu[]; extern void labelfont_cb(Fl_Choice*, void*); extern void labelsize_cb(Fl_Value_Input*, void*); extern void labelcolor_cb(Fl_Button*, void*); extern Fl_Button *w_labelcolor; #include extern Fl_Menu_Item colormenu[]; extern void labelcolor_menu_cb(Fl_Menu_Button*, void*); extern Fl_Group *wp_style_box; extern Fl_Menu_Item boxmenu[]; extern void box_cb(Fl_Choice*, void*); extern void color_cb(Fl_Button*, void*); extern Fl_Button *w_color; extern void color_menu_cb(Fl_Menu_Button*, void*); extern Fl_Group *wp_style_downbox; extern void down_box_cb(Fl_Choice*, void*); extern void color2_cb(Fl_Button*, void*); extern Fl_Button *w_selectcolor; extern void color2_menu_cb(Fl_Menu_Button*, void*); extern Fl_Group *wp_style_text; extern void textfont_cb(Fl_Choice*, void*); extern void textsize_cb(Fl_Value_Input*, void*); extern void textcolor_cb(Fl_Button*, void*); extern Fl_Button *w_textcolor; extern void textcolor_menu_cb(Fl_Menu_Button*, void*); extern void h_label_margin_cb(Fl_Value_Input*, void*); extern void v_label_margin_cb(Fl_Value_Input*, void*); extern void image_spacing_cb(Fl_Value_Input*, void*); extern void compact_cb(Fl_Light_Button*, void*); extern Fl_Group *wp_cpp_tab; extern Fl_Group *wp_cpp_class; extern void subclass_cb(Fl_Input*, void*); extern void subtype_cb(Fl_Choice*, void*); extern Fl_Group *wp_cpp_name; extern void name_cb(Fl_Input*, void*); extern void name_public_member_cb(Fl_Choice*, void*); extern void name_public_cb(Fl_Choice*, void*); extern void v_input_cb(Fl_Input*, void*); extern Fl_Input *v_input[4]; #include #include extern Fl_Text_Editor *wComment; #include "CodeEditor.h" extern void callback_cb(CodeEditor*, void*); extern CodeEditor *wCallback; extern Fl_Group *wp_cpp_callback; extern void user_data_cb(Fl_Input*, void*); extern Fl_Menu_Item whenmenu[]; extern void when_cb(Fl_Menu_Button*, void*); #include extern void user_data_type_cb(Fl_Input_Choice*, void*); extern Fl_Box *w_when_box; extern Fl_Group *widget_tab_grid_child; extern void grid_set_row_cb(Fluid_Coord_Input*, void*); extern Fluid_Coord_Input *widget_grid_row_input; extern void grid_dec_row_cb(Fl_Button*, void*); extern void grid_inc_row_cb(Fl_Button*, void*); extern void grid_set_col_cb(Fluid_Coord_Input*, void*); extern Fluid_Coord_Input *widget_grid_col_input; extern void grid_dec_col_cb(Fl_Button*, void*); extern void grid_inc_col_cb(Fl_Button*, void*); extern Fl_Box *widget_grid_transient; extern Fl_Box *widget_grid_unlinked; extern Fl_Group *wp_gridc_align; extern void grid_align_horizontal_cb(Fl_Choice*, void*); extern void grid_align_vertical_cb(Fl_Choice*, void*); extern Fl_Group *wp_gridc_size; extern void grid_set_min_wdt_cb(Fluid_Coord_Input*, void*); extern void grid_set_min_hgt_cb(Fluid_Coord_Input*, void*); extern void grid_set_rowspan_cb(Fluid_Coord_Input*, void*); extern Fluid_Coord_Input *widget_grid_rowspan_input; extern void grid_dec_rowspan_cb(Fl_Button*, void*); extern void grid_inc_rowspan_cb(Fl_Button*, void*); extern void grid_set_colspan_cb(Fluid_Coord_Input*, void*); extern Fluid_Coord_Input *widget_grid_colspan_input; extern void grid_dec_colspan_cb(Fl_Button*, void*); extern void grid_inc_colspan_cb(Fl_Button*, void*); extern Fl_Group *widget_tab_grid; extern Fluid_Coord_Input *widget_grid_rows; extern Fluid_Coord_Input *widget_grid_cols; extern Fl_Group *wp_grid_margin; extern Fl_Group *wp_grid_gaps; extern Fluid_Coord_Input *widget_grid_curr_row; extern Fl_Group *widget_grid_curr_row_attributes; extern Fluid_Coord_Input *widget_grid_curr_col; extern Fl_Group *widget_grid_curr_col_attributes; extern Fl_Tabs *widget_tabs_repo; extern void live_mode_cb(Fl_Button*, void*); extern Fl_Button *wLiveMode; extern void overlay_cb(Fl_Button*, void*); extern Fl_Button *overlay_button; #include extern void ok_cb(Fl_Return_Button*, void*); Fl_Double_Window* make_widget_panel(); extern Fl_Menu_Item menu_[]; extern Fl_Menu_Item menu_1[]; extern Fl_Menu_Item menu_Children[]; extern Fl_Menu_Item menu_2[]; extern Fl_Menu_Item menu_3[]; extern Fl_Menu_Item menu_4[]; extern Fl_Menu_Item menu_Horizontal[]; #define GRID_LEFT (menu_Horizontal+0) extern Fl_Menu_Item menu_Vertical[]; #endif fltk-1.4.3/fluid/Fl_Widget_Type.cxx0000644000175000017500000036115015004135251017307 0ustar albrechtalbrecht// // Widget type code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Widget_Type.h" #include "fluid.h" #include "Fl_Window_Type.h" #include "Fl_Group_Type.h" #include "Fl_Menu_Type.h" #include "Fl_Function_Type.h" #include "file.h" #include "code.h" #include "Fluid_Image.h" #include "settings_panel.h" #include "widget_panel.h" #include "undo.h" #include "mergeback.h" #include #include #include #include #include #include #include #include #include #include "../src/flstring.h" #include #include // Make an Fl_Widget_Type subclass instance. // It figures out the automatic size and parent of the new widget, // creates the Fl_Widget (by calling the virtual function _make), // adds it to the Fl_Widget hierarchy, creates a new Fl_Type // instance, sets the widget pointers, and makes all the display // update correctly... int Fl_Widget_Type::is_widget() const {return 1;} int Fl_Widget_Type::is_public() const {return public_;} const char* subclassname(Fl_Type* l) { if (l->is_a(ID_Menu_Bar)) { Fl_Menu_Bar_Type *mb = static_cast(l); if (mb->is_sys_menu_bar()) return mb->sys_menubar_name(); } if (l->is_widget()) { Fl_Widget_Type* p = (Fl_Widget_Type*)l; const char* c = p->subclass(); if (c) return c; if (l->is_class()) return "Fl_Group"; if (p->o->type() == FL_DOUBLE_WINDOW) return "Fl_Double_Window"; if (p->id() == ID_Input) { if (p->o->type() == FL_FLOAT_INPUT) return "Fl_Float_Input"; if (p->o->type() == FL_INT_INPUT) return "Fl_Int_Input"; } } return l->type_name(); } // Return the ideal widget size... void Fl_Widget_Type::ideal_size(int &w, int &h) { w = 120; h = 100; Fd_Snap_Action::better_size(w, h); } /** Make a new Widget node. \param[in] strategy is Strategy::AS_LAST_CHILD or Strategy::AFTER_CURRENT \return new node */ Fl_Type *Fl_Widget_Type::make(Strategy strategy) { Fl_Type *anchor = Fl_Type::current, *pp = anchor; if (pp && (strategy.placement() == Strategy::AFTER_CURRENT)) pp = pp->parent; while (pp && !pp->is_a(ID_Group)) { anchor = pp; strategy.placement(Strategy::AFTER_CURRENT); pp = pp->parent; } if (!pp || !pp->is_true_widget() || !anchor->is_true_widget()) { fl_message("Please select a group widget or window"); return 0; } Fl_Widget_Type* p = (Fl_Widget_Type*)pp; Fl_Widget_Type* q = (Fl_Widget_Type*)anchor; // Figure out a border between widget and window: int B = p->o->w()/2; if (p->o->h()/2 < B) B = p->o->h()/2; if (B>25) B = 25; int ULX,ULY; // parent's origin in window if (!p->is_a(ID_Window)) { // if it is a group, add corner ULX = p->o->x(); ULY = p->o->y(); } else { ULX = ULY = 0; } // Figure out a position and size for the widget int X,Y,W,H; if (is_a(ID_Group)) { // fill the parent with the widget X = ULX+B; W = p->o->w()-B; Y = ULY+B; H = p->o->h()-B; } else if (q != p) { // copy position and size of current widget W = q->o->w(); H = q->o->h(); X = q->o->x()+W; Y = q->o->y(); if (X+W > ULX+p->o->w()) { X = q->o->x(); Y = q->o->y()+H; if (Y+H > ULY+p->o->h()) Y = ULY+B; } } else { // just make it small and square... X = ULX+B; Y = ULY+B; W = H = B; } // Construct the Fl_Type: Fl_Widget_Type *t = _make(); if (!o) o = widget(0,0,100,100); // create template widget t->factory = this; // Construct the Fl_Widget: t->o = widget(X,Y,W,H); if (strategy.source() == Strategy::FROM_FILE) t->o->label(0); else if (t->o->label()) t->label(t->o->label()); // allow editing t->o->user_data((void*)t); // Put it in the parent: // ((Fl_Group *)(p->o))->add(t->o); (done by Fl_Type::add()) // add to browser: t->add(anchor, strategy); t->redraw(); return t; } void Fl_Widget_Type::setimage(Fluid_Image *i) { if (i == image || is_a(ID_Window)) return; if (image) image->decrement(); if (i) i->increment(); image = i; if (i) { i->image(o); if (o->image() && (scale_image_w_ || scale_image_h_)) { int iw = scale_image_w_>0 ? scale_image_w_ : o->image()->data_w(); int ih = scale_image_h_>0 ? scale_image_h_ : o->image()->data_h(); o->image()->scale(iw, ih, 0, 1); } } else { o->image(0); //scale_image_w_ = scale_image_h_ = 0; } redraw(); } void Fl_Widget_Type::setinactive(Fluid_Image *i) { if (i == inactive || is_a(ID_Window)) return; if (inactive) inactive->decrement(); if (i) i->increment(); inactive = i; if (i) { i->deimage(o); if (o->deimage()) { int iw = scale_deimage_w_>0 ? scale_deimage_w_ : o->deimage()->data_w(); int ih = scale_deimage_h_>0 ? scale_deimage_h_ : o->deimage()->data_h(); o->deimage()->scale(iw, ih, 0, 1); } } else { o->deimage(0); //scale_deimage_w_ = scale_deimage_h_ = 0; } redraw(); } void Fl_Widget_Type::setlabel(const char *n) { o->label(n); redraw(); } Fl_Widget_Type::Fl_Widget_Type() : override_visible_(0) { for (int n=0; nwindow(); delete o; if (win) win->redraw(); } if (subclass_) free((void*)subclass_); if (tooltip_) free((void*)tooltip_); if (image_name_) { free((void*)image_name_); if (image) image->decrement(); } if (inactive_name_) { free((void*)inactive_name_); if (inactive) inactive->decrement(); } for (int n=0; ntooltip(n); } void Fl_Widget_Type::image_name(const char *n) { setimage(Fluid_Image::find(n)); storestring(n,image_name_); } void Fl_Widget_Type::inactive_name(const char *n) { setinactive(Fluid_Image::find(n)); storestring(n,inactive_name_); } void Fl_Widget_Type::redraw() { Fl_Type *t = this; if (is_a(ID_Menu_Item)) { // find the menu button that parents this menu: do t = t->parent; while (t && t->is_a(ID_Menu_Item)); // kludge to cause build_menu to be called again: if (t) t->add_child(0, 0); } else { while (t->parent && t->parent->is_widget()) t = t->parent; ((Fl_Widget_Type*)t)->o->redraw(); } } // the recursive part sorts all children, returns pointer to next: Fl_Type *sort(Fl_Type *parent) { Fl_Type *f,*n=0; for (f = parent ? parent->next : Fl_Type::first; ; f = n) { if (!f || (parent && f->level <= parent->level)) break; n = sort(f); if (!f->selected || !f->is_true_widget()) continue; Fl_Widget* fw = ((Fl_Widget_Type*)f)->o; Fl_Type *g; // we will insert before this for (g = parent ? parent->next : Fl_Type::first; g != f; g = g->next) { if (!g->selected || g->level > f->level) continue; Fl_Widget* gw = ((Fl_Widget_Type*)g)->o; if (gw->y() > fw->y()) break; if (gw->y() == fw->y() && gw->x() > fw->x()) break; } if (g != f) f->move_before(g); } if (parent) parent->layout_widget(); return f; } //////////////////////////////////////////////////////////////// // The control panels! Fl_Window *the_panel; // All the callbacks use the argument to indicate whether to load or store. // This avoids the need for pointers to all the widgets, and keeps the // code localized in the callbacks. // A value of LOAD means to load. The hope is that this will not collide // with any actual useful values for the argument. I also use this to // initialized parts of the widget that are nyi by fluid. Fl_Widget_Type *current_widget; // one of the selected ones void* const LOAD = (void *)"LOAD"; // "magic" pointer to indicate that we need to load values into the dialog static int numselected; // number selected static int haderror; void name_cb(Fl_Input* o, void *v) { if (v == LOAD) { static char buf[1024]; if (numselected != 1) { snprintf(buf, sizeof(buf), "Widget Properties (%d widgets)", numselected); o->hide(); } else { o->value(current_widget->name()); o->show(); snprintf(buf, sizeof(buf), "%s Properties", current_widget->title()); } the_panel->label(buf); } else { if (numselected == 1) { current_widget->name(o->value()); // I don't update window title, as it probably is being closed // and wm2 (a window manager) barfs if you retitle and then // hide a window: // ((Fl_Window*)(o->parent()->parent()->parent()))->label(current_widget->title()); } } } void name_public_member_cb(Fl_Choice* i, void* v) { if (v == LOAD) { i->value(current_widget->public_); if (current_widget->is_in_class()) i->show(); else i->hide(); } else { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type *w = ((Fl_Widget_Type*)o); if (w->is_in_class()) { w->public_ = i->value(); } else { // if this is not in a class, it can be only private or public w->public_ = (i->value()>0); } mod = 1; } } if (mod) { set_modflag(1); redraw_browser(); } } } void name_public_cb(Fl_Choice* i, void* v) { if (v == LOAD) { i->value(current_widget->public_>0); if (current_widget->is_in_class()) i->hide(); else i->show(); } else { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { ((Fl_Widget_Type*)o)->public_ = i->value(); mod = 1; } } if (mod) { set_modflag(1); redraw_browser(); } } } /* Treating UNDO for text widget. Goal: we want to continuously update the UI while the user is typing text (changing the label, in this case). Code View does deferred updates, and the widget browser and widget panel update on every keystroke. At the same time, we want to limit undo actions to few and logical units. Caveats: 1: the text widget has its own undo handling for the text field, but we may want to do a global undo 2: every o->label() call will create an undo entry, but we want only one single event for all selected widgets 3: we want a single undo for the entire editing phase, but still propagate changes as they happen The edit process has these main states: 1: starting to edit [first_change==1 && !unfocus]; we must create a single undo checkpoint before anything changes 2: continue editing [first_change==0 && !unfocus]; we must suspend any undo checkpoints 3: done editing, unfocus [first_change==0 && unfocus]; we must make sure that undo checkpoints are enabled again 4: losing focus without editing [first_change==1 && unfocus]; don't create and checkpoints We must also check: 1: changing focus without changing text (works) 2: copy and paste, drag and drop operations (works) 3: save operation without unfocus event (works) */ void label_cb(Fl_Input* i, void *v) { static int first_change = 1; if (v == LOAD) { i->value(current_widget->label()); first_change = 1; } else { if (i->changed()) { undo_suspend(); int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { if (!mod) { if (first_change) { undo_resume(); undo_checkpoint(); undo_suspend(); first_change = 0; } mod = 1; } o->label(i->value()); } } undo_resume(); if (mod) set_modflag(1); } int r = (int)Fl::callback_reason(); if ( (r == FL_REASON_LOST_FOCUS) || (r == FL_REASON_ENTER_KEY) ) first_change = 1; } } static Fl_Input *image_input; void image_cb(Fl_Input* i, void *v) { if (v == LOAD) { image_input = i; if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { i->activate(); i->value(((Fl_Widget_Type*)current_widget)->image_name()); } else i->deactivate(); } else { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { ((Fl_Widget_Type*)o)->image_name(i->value()); mod = 1; } } if (mod) set_modflag(1); } } void image_browse_cb(Fl_Button* b, void *v) { if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) b->activate(); else b->deactivate(); } else { int mod = 0; if (ui_find_image(image_input->value())) { image_input->value(ui_find_image_name); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { ((Fl_Widget_Type*)o)->image_name(ui_find_image_name); mod = 1; } } if (mod) set_modflag(1); } } } void bind_image_cb(Fl_Check_Button* b, void *v) { if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { b->activate(); b->value(current_widget->bind_image_); } else { b->deactivate(); } } else { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { ((Fl_Widget_Type*)o)->bind_image_ = b->value(); mod = 1; } } if (mod) set_modflag(1); } } void compress_image_cb(Fl_Check_Button* b, void *v) { if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { b->activate(); b->value(!current_widget->compress_image_); } else { b->deactivate(); } } else { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { ((Fl_Widget_Type*)o)->compress_image_ = !b->value(); mod = 1; } } if (mod) set_modflag(1); } } static Fl_Input *inactive_input; void inactive_cb(Fl_Input* i, void *v) { if (v == LOAD) { inactive_input = i; if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { i->activate(); i->value(((Fl_Widget_Type*)current_widget)->inactive_name()); } else i->deactivate(); } else { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { ((Fl_Widget_Type*)o)->inactive_name(i->value()); mod = 1; } } if (mod) set_modflag(1); } } void inactive_browse_cb(Fl_Button* b, void *v) { if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) b->activate(); else b->deactivate(); } else { int mod = 0; if (ui_find_image(inactive_input->value())) { inactive_input->value(ui_find_image_name); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { ((Fl_Widget_Type*)o)->inactive_name(ui_find_image_name); mod = 1; } } if (mod) set_modflag(1); } } } void bind_deimage_cb(Fl_Check_Button* b, void *v) { if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { b->activate(); b->value(current_widget->bind_deimage_); } else { b->deactivate(); } } else { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { ((Fl_Widget_Type*)o)->bind_deimage_ = b->value(); mod = 1; } } if (mod) set_modflag(1); } } void compress_deimage_cb(Fl_Check_Button* b, void *v) { if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { b->activate(); b->value(!current_widget->compress_deimage_); } else { b->deactivate(); } } else { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { ((Fl_Widget_Type*)o)->compress_deimage_ = !b->value(); mod = 1; } } if (mod) set_modflag(1); } } void tooltip_cb(Fl_Input* i, void *v) { if (v == LOAD) { if (current_widget->is_widget()) { i->activate(); i->value(((Fl_Widget_Type*)current_widget)->tooltip()); } else i->deactivate(); } else { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { ((Fl_Widget_Type*)o)->tooltip(i->value()); mod = 1; } } if (mod) set_modflag(1); } } Fluid_Coord_Input *x_input, *y_input, *w_input, *h_input; static int widget_i = 0; static int vars_i_cb(const Fluid_Coord_Input*, void *v) { return widget_i; } static int vars_x_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = (Fl_Type*)v; if (t->is_widget()) return ((Fl_Widget_Type*)t)->o->x(); return 0; } static int vars_y_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = (Fl_Type*)v; if (t->is_widget()) return ((Fl_Widget_Type*)t)->o->y(); return 0; } static int vars_w_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = (Fl_Type*)v; if (t->is_widget()) return ((Fl_Widget_Type*)t)->o->w(); return 0; } static int vars_h_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = (Fl_Type*)v; if (t->is_widget()) return ((Fl_Widget_Type*)t)->o->h(); return 0; } static int vars_px_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = ((Fl_Type*)v)->parent; if (t && t->is_widget()) return ((Fl_Widget_Type*)t)->o->x(); return 0; } static int vars_py_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = ((Fl_Type*)v)->parent; if (t && t->is_widget()) return ((Fl_Widget_Type*)t)->o->y(); return 0; } static int vars_pw_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = ((Fl_Type*)v)->parent; if (t && t->is_widget()) return ((Fl_Widget_Type*)t)->o->w(); return 0; } static int vars_ph_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = ((Fl_Type*)v)->parent; if (t && t->is_widget()) return ((Fl_Widget_Type*)t)->o->h(); return 0; } static int vars_sx_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = ((Fl_Type*)v)->prev_sibling(); if (t && t->is_widget()) return ((Fl_Widget_Type*)t)->o->x(); return 0; } static int vars_sy_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = ((Fl_Type*)v)->prev_sibling(); if (t && t->is_widget()) return ((Fl_Widget_Type*)t)->o->y(); return 0; } static int vars_sw_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = ((Fl_Type*)v)->prev_sibling(); if (t && t->is_widget()) return ((Fl_Widget_Type*)t)->o->w(); return 0; } static int vars_sh_cb(const Fluid_Coord_Input*, void *v) { Fl_Type *t = ((Fl_Type*)v)->prev_sibling(); if (t && t->is_widget()) return ((Fl_Widget_Type*)t)->o->h(); return 0; } static int bbox_x, bbox_y, bbox_r, bbox_b; static int bbox_min(int a, int b) { return (ab) ? a : b; } static void calculate_bbox(Fl_Type *p) { char first = 1; bbox_x = bbox_y = bbox_r = bbox_b = 0; for (p=p->first_child(); p; p=p->next_sibling()) { if (p->is_widget()) { Fl_Widget *o = ((Fl_Widget_Type*)p)->o; if (first) { bbox_x = o->x(); bbox_y = o->y(); bbox_r = o->x() + o->w(); bbox_b = o->y() + o->h(); first = 0; } else { bbox_x = bbox_min(bbox_x, o->x()); bbox_y = bbox_min(bbox_y, o->y()); bbox_r = bbox_max(bbox_r, o->x() + o->w()); bbox_b = bbox_max(bbox_b, o->y() + o->h()); } } } } static int vars_cx_cb(const Fluid_Coord_Input*, void *v) { calculate_bbox((Fl_Type*)v); return bbox_x; } static int vars_cy_cb(const Fluid_Coord_Input*, void *v) { calculate_bbox((Fl_Type*)v); return bbox_y; } static int vars_cw_cb(const Fluid_Coord_Input*, void *v) { calculate_bbox((Fl_Type*)v); return bbox_r - bbox_x; } static int vars_ch_cb(const Fluid_Coord_Input*, void *v) { calculate_bbox((Fl_Type*)v); return bbox_b - bbox_y; } Fluid_Coord_Input_Vars widget_vars[] = { { "i", vars_i_cb }, // zero based counter of selected widgets { "x", vars_x_cb }, // position and size of current widget { "y", vars_y_cb }, { "w", vars_w_cb }, { "h", vars_h_cb }, { "px", vars_px_cb }, // position and size of parent widget { "py", vars_py_cb }, { "pw", vars_pw_cb }, { "ph", vars_ph_cb }, { "sx", vars_sx_cb }, // position and size of previous sibling { "sy", vars_sy_cb }, { "sw", vars_sw_cb }, { "sh", vars_sh_cb }, { "cx", vars_cx_cb }, // position and size of bounding box of all children { "cy", vars_cy_cb }, { "cw", vars_cw_cb }, { "ch", vars_ch_cb }, { 0 } }; void x_cb(Fluid_Coord_Input *i, void *v) { if (v == LOAD) { x_input = i; if (current_widget->is_true_widget()) { i->value(((Fl_Widget_Type *)current_widget)->o->x()); x_input->activate(); } else x_input->deactivate(); } else { undo_checkpoint(); widget_i = 0; int mod = 0; int v = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_true_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; i->variables(widget_vars, o); v = i->value(); w->resize(v, w->y(), w->w(), w->h()); if (w->window()) w->window()->redraw(); widget_i++; mod = 1; } } if (mod) { set_modflag(1); i->value(v); // change the displayed value to the result of the last // calculation. Keep the formula if it was not used. } } } void y_cb(Fluid_Coord_Input *i, void *v) { if (v == LOAD) { y_input = i; if (current_widget->is_true_widget()) { i->value(((Fl_Widget_Type *)current_widget)->o->y()); y_input->activate(); } else y_input->deactivate(); } else { undo_checkpoint(); widget_i = 0; int mod = 0; int v = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_true_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; i->variables(widget_vars, o); v = i->value(); w->resize(w->x(), v, w->w(), w->h()); if (w->window()) w->window()->redraw(); widget_i++; mod = 1; } } if (mod) { set_modflag(1); i->value(v); } } } void w_cb(Fluid_Coord_Input *i, void *v) { if (v == LOAD) { w_input = i; if (current_widget->is_true_widget()) { i->value(((Fl_Widget_Type *)current_widget)->o->w()); w_input->activate(); } else w_input->deactivate(); } else { undo_checkpoint(); widget_i = 0; int mod = 0; int v = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_true_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; i->variables(widget_vars, o); v = i->value(); w->resize(w->x(), w->y(), v, w->h()); if (w->window()) w->window()->redraw(); widget_i++; mod = 1; } } if (mod) { set_modflag(1); i->value(v); } } } void h_cb(Fluid_Coord_Input *i, void *v) { if (v == LOAD) { h_input = i; if (current_widget->is_true_widget()) { i->value(((Fl_Widget_Type *)current_widget)->o->h()); h_input->activate(); } else h_input->deactivate(); } else { undo_checkpoint(); widget_i = 0; int mod = 0; int v = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_true_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; i->variables(widget_vars, o); v = i->value(); w->resize(w->x(), w->y(), w->w(), v); if (w->window()) w->window()->redraw(); widget_i++; mod = 1; } } if (mod) { set_modflag(1); i->value(v); } } } void wc_relative_cb(Fl_Choice *i, void *v) { if (v == LOAD) { if (current_widget->is_a(ID_Widget_Class)) { i->show(); i->value(((Fl_Widget_Class_Type *)current_widget)->wc_relative); } else { i->hide(); } } else { int mod = 0; undo_checkpoint(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && current_widget->is_a(ID_Widget_Class)) { Fl_Widget_Class_Type *t = (Fl_Widget_Class_Type *)o; t->wc_relative = i->value(); mod = 1; } } if (mod) set_modflag(1); } } //////////////////////////////////////////////////////////////// // turn number to string or string to number for saving to file: // does not work for hierarchical menus! const char *item_name(Fl_Menu_Item* m, int i) { if (m) { while (m->label()) { if (m->argument() == i) return m->label(); m++; } } static char buffer[20]; sprintf(buffer, "%d", i); return buffer; } int item_number(Fl_Menu_Item* m, const char* i) { if (!i) return 0; if (m && i) { if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3; while (m->label()) { if (!strcmp(m->label(), i)) return int(m->argument()); m++; } } return atoi(i); } #define ZERO_ENTRY 1000 Fl_Menu_Item boxmenu[] = { {"NO_BOX",0,0,(void *)ZERO_ENTRY}, {"boxes",0,0,0,FL_SUBMENU}, {"UP_BOX",0,0,(void *)FL_UP_BOX}, {"DOWN_BOX",0,0,(void *)FL_DOWN_BOX}, {"FLAT_BOX",0,0,(void *)FL_FLAT_BOX}, {"BORDER_BOX",0,0,(void *)FL_BORDER_BOX}, {"THIN_UP_BOX",0,0,(void *)FL_THIN_UP_BOX}, {"THIN_DOWN_BOX",0,0,(void *)FL_THIN_DOWN_BOX}, {"ENGRAVED_BOX",0,0,(void *)FL_ENGRAVED_BOX}, {"EMBOSSED_BOX",0,0,(void *)FL_EMBOSSED_BOX}, {"ROUND_UP_BOX",0,0,(void *)FL_ROUND_UP_BOX}, {"ROUND_DOWN_BOX",0,0,(void *)FL_ROUND_DOWN_BOX}, {"DIAMOND_UP_BOX",0,0,(void *)FL_DIAMOND_UP_BOX}, {"DIAMOND_DOWN_BOX",0,0,(void *)FL_DIAMOND_DOWN_BOX}, {"SHADOW_BOX",0,0,(void *)FL_SHADOW_BOX}, {"ROUNDED_BOX",0,0,(void *)FL_ROUNDED_BOX}, {"RSHADOW_BOX",0,0,(void *)FL_RSHADOW_BOX}, {"RFLAT_BOX",0,0,(void *)FL_RFLAT_BOX}, {"OVAL_BOX",0,0,(void *)FL_OVAL_BOX}, {"OSHADOW_BOX",0,0,(void *)FL_OSHADOW_BOX}, {"OFLAT_BOX",0,0,(void *)FL_OFLAT_BOX}, {"PLASTIC_UP_BOX",0,0,(void *)FL_PLASTIC_UP_BOX}, {"PLASTIC_DOWN_BOX",0,0,(void *)FL_PLASTIC_DOWN_BOX}, {"PLASTIC_THIN_UP_BOX",0,0,(void *)FL_PLASTIC_THIN_UP_BOX}, {"PLASTIC_THIN_DOWN_BOX",0,0,(void *)FL_PLASTIC_THIN_DOWN_BOX}, {"PLASTIC_ROUND_UP_BOX",0,0,(void *)FL_PLASTIC_ROUND_UP_BOX}, {"PLASTIC_ROUND_DOWN_BOX",0,0,(void *)FL_PLASTIC_ROUND_DOWN_BOX}, {"GTK_UP_BOX",0,0,(void *)FL_GTK_UP_BOX}, {"GTK_DOWN_BOX",0,0,(void *)FL_GTK_DOWN_BOX}, {"GTK_THIN_UP_BOX",0,0,(void *)FL_GTK_THIN_UP_BOX}, {"GTK_THIN_DOWN_BOX",0,0,(void *)FL_GTK_THIN_DOWN_BOX}, {"GTK_ROUND_UP_BOX",0,0,(void *)FL_GTK_ROUND_UP_BOX}, {"GTK_ROUND_DOWN_BOX",0,0,(void *)FL_GTK_ROUND_DOWN_BOX}, {"GLEAM_UP_BOX",0,0,(void *)FL_GLEAM_UP_BOX}, {"GLEAM_DOWN_BOX",0,0,(void *)FL_GLEAM_DOWN_BOX}, {"GLEAM_THIN_UP_BOX",0,0,(void *)FL_GLEAM_THIN_UP_BOX}, {"GLEAM_THIN_DOWN_BOX",0,0,(void *)FL_GLEAM_THIN_DOWN_BOX}, {"GLEAM_ROUND_UP_BOX",0,0,(void *)FL_GLEAM_ROUND_UP_BOX}, {"GLEAM_ROUND_DOWN_BOX",0,0,(void *)FL_GLEAM_ROUND_DOWN_BOX}, {"OXY_UP_BOX",0,0,(void *)FL_OXY_UP_BOX}, {"OXY_DOWN_BOX",0,0,(void *)FL_OXY_DOWN_BOX}, {"OXY_THIN_UP_BOX",0,0,(void *)FL_OXY_THIN_UP_BOX}, {"OXY_THIN_DOWN_BOX",0,0,(void *)FL_OXY_THIN_DOWN_BOX}, {"OXY_ROUND_UP_BOX",0,0,(void *)FL_OXY_ROUND_UP_BOX}, {"OXY_ROUND_DOWN_BOX",0,0,(void *)FL_OXY_ROUND_DOWN_BOX}, {"OXY_BUTTON_UP_BOX",0,0,(void *)FL_OXY_BUTTON_UP_BOX}, {"OXY_BUTTON_DOWN_BOX",0,0,(void *)FL_OXY_BUTTON_DOWN_BOX}, {0}, {"frames",0,0,0,FL_SUBMENU}, {"UP_FRAME",0,0,(void *)FL_UP_FRAME}, {"DOWN_FRAME",0,0,(void *)FL_DOWN_FRAME}, {"THIN_UP_FRAME",0,0,(void *)FL_THIN_UP_FRAME}, {"THIN_DOWN_FRAME",0,0,(void *)FL_THIN_DOWN_FRAME}, {"ENGRAVED_FRAME",0,0,(void *)FL_ENGRAVED_FRAME}, {"EMBOSSED_FRAME",0,0,(void *)FL_EMBOSSED_FRAME}, {"BORDER_FRAME",0,0,(void *)FL_BORDER_FRAME}, {"SHADOW_FRAME",0,0,(void *)FL_SHADOW_FRAME}, {"ROUNDED_FRAME",0,0,(void *)FL_ROUNDED_FRAME}, {"OVAL_FRAME",0,0,(void *)FL_OVAL_FRAME}, {"PLASTIC_UP_FRAME",0,0,(void *)FL_PLASTIC_UP_FRAME}, {"PLASTIC_DOWN_FRAME",0,0,(void *)FL_PLASTIC_DOWN_FRAME}, {"GTK_UP_FRAME",0,0,(void *)FL_GTK_UP_FRAME}, {"GTK_DOWN_FRAME",0,0,(void *)FL_GTK_DOWN_FRAME}, {"GTK_THIN_UP_FRAME",0,0,(void *)FL_GTK_THIN_UP_FRAME}, {"GTK_THIN_DOWN_FRAME",0,0,(void *)FL_GTK_THIN_DOWN_FRAME}, {"GLEAM_UP_FRAME",0,0,(void *)FL_GLEAM_UP_FRAME}, {"GLEAM_DOWN_FRAME",0,0,(void *)FL_GLEAM_DOWN_FRAME}, {"OXY_UP_FRAME",0,0,(void *)FL_OXY_UP_FRAME}, {"OXY_DOWN_FRAME",0,0,(void *)FL_OXY_DOWN_FRAME}, {"OXY_THIN_UP_FRAME",0,0,(void *)FL_OXY_THIN_UP_FRAME}, {"OXY_THIN_DOWN_FRAME",0,0,(void *)FL_OXY_THIN_DOWN_FRAME}, {0}, {0}}; const char *boxname(int i) { if (!i) i = ZERO_ENTRY; for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) if (boxmenu[j].argument() == i) return boxmenu[j].label(); return 0; } int boxnumber(const char *i) { if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3; for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) if (boxmenu[j].label() && !strcmp(boxmenu[j].label(), i)) { return int(boxmenu[j].argument()); } return 0; } void box_cb(Fl_Choice* i, void *v) { if (v == LOAD) { if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); int n = current_widget->o->box(); if (!n) n = ZERO_ENTRY; for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) if (boxmenu[j].argument() == n) {i->value(j); break;} } else { int mod = 0; int m = i->value(); int n = int(boxmenu[m].argument()); if (!n) return; // should not happen if (n == ZERO_ENTRY) n = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; q->o->box((Fl_Boxtype)n); q->redraw(); mod = 1; } } if (mod) set_modflag(1); } } void down_box_cb(Fl_Choice* i, void *v) { if (v == LOAD) { int n; if (current_widget->is_a(ID_Button)) n = ((Fl_Button*)(current_widget->o))->down_box(); else if (current_widget->is_a(ID_Input_Choice)) n = ((Fl_Input_Choice*)(current_widget->o))->down_box(); else if (current_widget->is_a(ID_Menu_Manager_)) n = ((Fl_Menu_*)(current_widget->o))->down_box(); else { i->deactivate(); return; } i->activate(); if (!n) n = ZERO_ENTRY; for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) if (boxmenu[j].argument() == n) {i->value(j); break;} } else { int mod = 0; int m = i->value(); int n = int(boxmenu[m].argument()); if (!n) return; // should not happen if (n == ZERO_ENTRY) n = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected) { if (o->is_a(ID_Button)) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; ((Fl_Button*)(q->o))->down_box((Fl_Boxtype)n); if (((Fl_Button*)(q->o))->value()) q->redraw(); } else if (o->is_a(ID_Input_Choice)) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; ((Fl_Input_Choice*)(q->o))->down_box((Fl_Boxtype)n); } else if (o->is_a(ID_Menu_Manager_)) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; ((Fl_Menu_*)(q->o))->down_box((Fl_Boxtype)n); } mod = 1; } } if (mod) set_modflag(1); } } void compact_cb(Fl_Light_Button* i, void* v) { if (v == LOAD) { uchar n; if (current_widget->is_a(ID_Button) && !current_widget->is_a(ID_Menu_Item)) { n = ((Fl_Button*)(current_widget->o))->compact(); i->value(n); i->show(); } else { i->hide(); } } else { int mod = 0; uchar n = (uchar)i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_a(ID_Button) && !o->is_a(ID_Menu_Item)) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; uchar v = ((Fl_Button*)(q->o))->compact(); if (n != v) { if (!mod) { mod = 1; undo_checkpoint(); } ((Fl_Button*)(q->o))->compact(n); q->redraw(); } } } if (mod) set_modflag(1); } } //////////////////////////////////////////////////////////////// Fl_Menu_Item whenmenu[] = { // set individual bits {"FL_WHEN_CHANGED",0,0,(void*)FL_WHEN_CHANGED, FL_MENU_TOGGLE}, {"FL_WHEN_NOT_CHANGED",0,0,(void*)FL_WHEN_NOT_CHANGED, FL_MENU_TOGGLE}, {"FL_WHEN_RELEASE",0,0,(void*)FL_WHEN_RELEASE, FL_MENU_TOGGLE}, {"FL_WHEN_ENTER_KEY",0,0,(void*)FL_WHEN_ENTER_KEY, FL_MENU_TOGGLE}, {"FL_WHEN_CLOSED",0,0,(void*)FL_WHEN_CLOSED, FL_MENU_TOGGLE|FL_MENU_DIVIDER}, // set bit combinations {"FL_WHEN_NEVER",0,0,(void*)FL_WHEN_NEVER}, {"FL_WHEN_RELEASE_ALWAYS",0,0,(void*)FL_WHEN_RELEASE_ALWAYS}, {"FL_WHEN_ENTER_KEY_ALWAYS",0,0,(void*)FL_WHEN_ENTER_KEY_ALWAYS}, {"FL_WHEN_ENTER_KEY_CHANGED",0,0,(void*)FL_WHEN_ENTER_KEY_CHANGED}, {0}}; static Fl_Menu_Item whensymbolmenu[] = { /* 0 */ {"FL_WHEN_NEVER",0,0,(void*)FL_WHEN_NEVER}, /* 1 */ {"FL_WHEN_CHANGED",0,0,(void*)FL_WHEN_CHANGED}, /* 2 */ {"FL_WHEN_NOT_CHANGED",0,0,(void*)FL_WHEN_NOT_CHANGED}, /* 3 */ {"FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED",0,0,(void*)(FL_WHEN_CHANGED|FL_WHEN_NOT_CHANGED)}, /* 4 */ {"FL_WHEN_RELEASE",0,0,(void*)FL_WHEN_RELEASE}, /* 5 */ {"FL_WHEN_CHANGED | FL_WHEN_RELEASE",0,0,(void*)(FL_WHEN_CHANGED|FL_WHEN_RELEASE)}, /* 6 */ {"FL_WHEN_RELEASE_ALWAYS",0,0,(void*)FL_WHEN_RELEASE_ALWAYS}, /* 7 */ {"FL_WHEN_CHANGED | FL_WHEN_RELEASE_ALWAYS",0,0,(void*)(FL_WHEN_CHANGED|FL_WHEN_RELEASE_ALWAYS)}, /* 8 */ {"FL_WHEN_ENTER_KEY",0,0,(void*)FL_WHEN_ENTER_KEY}, /* 9 */ {"FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY",0,0,(void*)(FL_WHEN_CHANGED|FL_WHEN_ENTER_KEY)}, /* 10 */ {"FL_WHEN_ENTER_KEY_ALWAYS",0,0,(void*)FL_WHEN_ENTER_KEY_ALWAYS}, /* 11 */ {"FL_WHEN_ENTER_KEY_CHANGED",0,0,(void*)FL_WHEN_ENTER_KEY_CHANGED}, /* 12 */ {"FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY",0,0,(void*)(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY)}, /* 13 */ {"FL_WHEN_RELEASE | FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY",0,0,(void*)(FL_WHEN_RELEASE|FL_WHEN_CHANGED|FL_WHEN_ENTER_KEY)}, /* 14 */ {"FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY_ALWAYS",0,0,(void*)(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY_ALWAYS)}, /* 15 */ {"FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY_CHANGED",0,0,(void*)(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY_CHANGED)}, {0} }; // Return a text string representing the Fl_When value n const char* when_symbol_name(int n) { static char sym[128]; if (n == FL_WHEN_CLOSED) { strcpy(sym, "FL_WHEN_CLOSED"); } else { strcpy(sym, whensymbolmenu[n&15].label()); if (n & FL_WHEN_CLOSED) strcat(sym, " | FL_WHEN_CLOSED"); } return sym; } // Set the check marks in the "when()" menu according to the Fl_When value n void set_whenmenu(int n) { if (n&FL_WHEN_CHANGED) whenmenu[0].set(); else whenmenu[0].clear(); if (n&FL_WHEN_NOT_CHANGED) whenmenu[1].set(); else whenmenu[1].clear(); if (n&FL_WHEN_RELEASE) whenmenu[2].set(); else whenmenu[2].clear(); if (n&FL_WHEN_ENTER_KEY) whenmenu[3].set(); else whenmenu[3].clear(); if (n&FL_WHEN_CLOSED) whenmenu[4].set(); else whenmenu[4].clear(); } void when_cb(Fl_Menu_Button* i, void *v) { if (v == LOAD) { if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); int n = current_widget->o->when(); set_whenmenu(n); w_when_box->copy_label(when_symbol_name(n)); } else { int mod = 0; int n = 0; if (i->mvalue() && ((i->mvalue()->flags & FL_MENU_TOGGLE) == 0) ) { n = (int)i->mvalue()->argument(); set_whenmenu(n); } else { if (whenmenu[0].value()) n |= FL_WHEN_CHANGED; if (whenmenu[1].value()) n |= FL_WHEN_NOT_CHANGED; if (whenmenu[2].value()) n |= FL_WHEN_RELEASE; if (whenmenu[3].value()) n |= FL_WHEN_ENTER_KEY; if (whenmenu[4].value()) n |= FL_WHEN_CLOSED; } w_when_box->copy_label(when_symbol_name(n)); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; q->o->when(n); mod = 1; } } if (mod) set_modflag(1); } } uchar Fl_Widget_Type::resizable() const { if (is_a(ID_Window)) return ((Fl_Window*)o)->resizable() != 0; Fl_Group* p = (Fl_Group*)o->parent(); if (p) return p->resizable() == o; else return 0; } void Fl_Widget_Type::resizable(uchar v) { if (v) { if (resizable()) return; if (is_a(ID_Window)) ((Fl_Window*)o)->resizable(o); else { Fl_Group* p = (Fl_Group*)o->parent(); if (p) p->resizable(o); } } else { if (!resizable()) return; if (is_a(ID_Window)) { ((Fl_Window*)o)->resizable(0); } else { Fl_Group* p = (Fl_Group*)o->parent(); if (p) p->resizable(0); } } } void resizable_cb(Fl_Light_Button* i,void* v) { if (v == LOAD) { if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} if (numselected > 1) {i->deactivate(); return;} i->activate(); i->value(current_widget->resizable()); } else { undo_checkpoint(); current_widget->resizable(i->value()); set_modflag(1); } } void hotspot_cb(Fl_Light_Button* i,void* v) { if (v == LOAD) { if (numselected > 1) {i->deactivate(); return;} if (current_widget->is_a(ID_Menu_Item)) i->label("divider"); else i->label("hotspot"); i->activate(); i->value(current_widget->hotspot()); } else { undo_checkpoint(); current_widget->hotspot(i->value()); if (current_widget->is_a(ID_Menu_Item)) { current_widget->redraw(); return; } if (i->value()) { Fl_Type *p = current_widget->parent; if (!p || !p->is_widget()) return; while (!p->is_a(ID_Window)) p = p->parent; for (Fl_Type *o = p->next; o && o->level > p->level; o = o->next) { if (o->is_widget() && o != current_widget) ((Fl_Widget_Type*)o)->hotspot(0); } } set_modflag(1); } } void visible_cb(Fl_Light_Button* i, void* v) { if (v == LOAD) { i->value(current_widget->o->visible()); if (current_widget->is_a(ID_Window)) i->deactivate(); else i->activate(); } else { int mod = 0; int n = i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { if (!mod) { mod = 1; undo_checkpoint(); } Fl_Widget_Type* q = (Fl_Widget_Type*)o; n ? q->o->show() : q->o->hide(); q->redraw(); if (n && q->parent && q->parent->type_name()) { if (q->parent->is_a(ID_Tabs)) { ((Fl_Tabs *)q->o->parent())->value(q->o); } else if (q->parent->is_a(ID_Wizard)) { ((Fl_Wizard *)q->o->parent())->value(q->o); } } } } if (mod) { set_modflag(1); redraw_browser(); } } } void active_cb(Fl_Light_Button* i, void* v) { if (v == LOAD) { i->value(current_widget->o->active()); if (current_widget->is_a(ID_Window)) i->deactivate(); else i->activate(); } else { int mod = 0; int n = i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { if (!mod) { mod = 1; undo_checkpoint(); } Fl_Widget_Type* q = (Fl_Widget_Type*)o; n ? q->o->activate() : q->o->deactivate(); q->redraw(); } } if (mod) set_modflag(1); } } //////////////////////////////////////////////////////////////// Fl_Menu_Item fontmenu[] = { {"Helvetica"}, {"Helvetica bold"}, {"Helvetica italic"}, {"Helvetica bold italic"}, {"Courier"}, {"Courier bold"}, {"Courier italic"}, {"Courier bold italic"}, {"Times"}, {"Times bold"}, {"Times italic"}, {"Times bold italic"}, {"Symbol"}, {"Terminal"}, {"Terminal Bold"}, {"Zapf Dingbats"}, {NULL} }; Fl_Menu_Item fontmenu_w_default[] = { {"", 0, NULL, NULL, FL_MENU_DIVIDER}, {"Helvetica"}, {"Helvetica bold"}, {"Helvetica italic"}, {"Helvetica bold italic"}, {"Courier"}, {"Courier bold"}, {"Courier italic"}, {"Courier bold italic"}, {"Times"}, {"Times bold"}, {"Times italic"}, {"Times bold italic"}, {"Symbol"}, {"Terminal"}, {"Terminal Bold"}, {"Zapf Dingbats"}, {NULL} }; void labelfont_cb(Fl_Choice* i, void *v) { if (v == LOAD) { int n = current_widget->o->labelfont(); if (n > 15) n = 0; i->value(n); } else { int mod = 0; int n = i->value(); if (n <= 0) n = layout->labelfont; if (n <= 0) n = FL_HELVETICA; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; q->o->labelfont(n); q->redraw(); mod = 1; } } if (mod) set_modflag(1); } } void labelsize_cb(Fl_Value_Input* i, void *v) { int n; if (v == LOAD) { n = current_widget->o->labelsize(); } else { int mod = 0; n = int(i->value()); if (n <= 0) n = layout->labelsize; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; q->o->labelsize(n); q->redraw(); mod = 1; } } if (mod) set_modflag(1); } i->value(n); } extern const char *ui_find_image_name; Fl_Menu_Item labeltypemenu[] = { {"NORMAL_LABEL",0,0,(void*)0}, {"SHADOW_LABEL",0,0,(void*)FL_SHADOW_LABEL}, {"ENGRAVED_LABEL",0,0,(void*)FL_ENGRAVED_LABEL}, {"EMBOSSED_LABEL",0,0,(void*)FL_EMBOSSED_LABEL}, {"NO_LABEL",0,0,(void*)(FL_NO_LABEL)}, {0}}; void labeltype_cb(Fl_Choice* i, void *v) { if (v == LOAD) { int n; n = current_widget->o->labeltype(); i->when(FL_WHEN_RELEASE); for (int j = 0; j < int(sizeof(labeltypemenu)/sizeof(*labeltypemenu)); j++) if (labeltypemenu[j].argument() == n) {i->value(j); break;} } else { int mod = 0; int m = i->value(); int n = int(labeltypemenu[m].argument()); if (n<0) return; // should not happen for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* p = (Fl_Widget_Type*)o; p->o->labeltype((Fl_Labeltype)n); p->redraw(); mod = 1; } } if (mod) set_modflag(1); } } //////////////////////////////////////////////////////////////// Fl_Menu_Item colormenu[] = { { "Foreground Color", 0, 0, (void*)(fl_intptr_t)FL_FOREGROUND_COLOR, 0, 0, FL_HELVETICA, 11}, { "Background Color", 0, 0, (void*)(fl_intptr_t)FL_BACKGROUND_COLOR, 0, 0, FL_HELVETICA, 11}, { "Background Color 2", 0, 0, (void*)(fl_intptr_t)FL_BACKGROUND2_COLOR, 0, 0, FL_HELVETICA, 11}, { "Selection Color", 0, 0, (void*)(fl_intptr_t)FL_SELECTION_COLOR, 0, 0, FL_HELVETICA, 11}, { "Inactive Color", 0, 0, (void*)(fl_intptr_t)FL_INACTIVE_COLOR, FL_MENU_DIVIDER, 0, FL_HELVETICA, 11}, { "Black", 0, 0, (void*)(fl_intptr_t)FL_BLACK, 0, 0, FL_HELVETICA, 11}, { "White", 0, 0, (void*)(fl_intptr_t)FL_WHITE, FL_MENU_DIVIDER, 0, FL_HELVETICA, 11}, { "Gray 0", 0, 0, (void*)(fl_intptr_t)FL_GRAY0, 0, 0, FL_HELVETICA, 11}, { "Dark 3", 0, 0, (void*)(fl_intptr_t)FL_DARK3, 0, 0, FL_HELVETICA, 11}, { "Dark 2", 0, 0, (void*)(fl_intptr_t)FL_DARK2, 0, 0, FL_HELVETICA, 11}, { "Dark 1", 0, 0, (void*)(fl_intptr_t)FL_DARK1, 0, 0, FL_HELVETICA, 11}, { "Light 1", 0, 0, (void*)(fl_intptr_t)FL_LIGHT1, 0, 0, FL_HELVETICA, 11}, { "Light 2", 0, 0, (void*)(fl_intptr_t)FL_LIGHT2, 0, 0, FL_HELVETICA, 11}, { "Light 3", 0, 0, (void*)(fl_intptr_t)FL_LIGHT3, 0, 0, FL_HELVETICA, 11}, { 0 } }; void color_common(Fl_Color c) { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; q->o->color(c); q->o->redraw(); if (q->parent && q->parent->is_a(ID_Tabs)) { if (q->o->parent()) q->o->parent()->redraw(); } mod = 1; } } if (mod) set_modflag(1); } void color_cb(Fl_Button* i, void *v) { Fl_Color c = current_widget->o->color(); if (v == LOAD) { if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); } else { Fl_Color d = fl_show_colormap(c); if (d == c) return; c = d; color_common(c); } i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); } void color_menu_cb(Fl_Menu_Button* i, void *v) { Fl_Color c = current_widget->o->color(); if (v == LOAD) { if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); } else { Fl_Color d = (Fl_Color)(i->mvalue()->argument()); if (d == c) return; c = d; color_common(c); w_color->color(c); w_color->labelcolor(fl_contrast(FL_BLACK,c)); w_color->redraw(); } } void color2_common(Fl_Color c) { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; q->o->selection_color(c); q->o->redraw(); mod = 1; } } if (mod) set_modflag(1); } void color2_cb(Fl_Button* i, void *v) { Fl_Color c = current_widget->o->selection_color(); if (v == LOAD) { if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); } else { Fl_Color d = fl_show_colormap(c); if (d == c) return; c = d; color2_common(c); } i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); } void color2_menu_cb(Fl_Menu_Button* i, void *v) { Fl_Color c = current_widget->o->selection_color(); if (v == LOAD) { if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); } else { Fl_Color d = (Fl_Color)(i->mvalue()->argument()); if (d == c) return; c = d; color2_common(c); w_selectcolor->color(c); w_selectcolor->labelcolor(fl_contrast(FL_BLACK,c)); w_selectcolor->redraw(); } } void labelcolor_common(Fl_Color c) { int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; q->o->labelcolor(c); q->redraw(); mod = 1; } } if (mod) set_modflag(1); } void labelcolor_cb(Fl_Button* i, void *v) { Fl_Color c = current_widget->o->labelcolor(); if (v != LOAD) { Fl_Color d = fl_show_colormap(c); if (d == c) return; c = d; labelcolor_common(c); } i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); } void labelcolor_menu_cb(Fl_Menu_Button* i, void *v) { Fl_Color c = current_widget->o->labelcolor(); if (v != LOAD) { Fl_Color d = (Fl_Color)(i->mvalue()->argument()); if (d == c) return; c = d; labelcolor_common(c); w_labelcolor->color(c); w_labelcolor->labelcolor(fl_contrast(FL_BLACK,c)); w_labelcolor->redraw(); } } static Fl_Button* relative(Fl_Widget* o, int i) { Fl_Group* g = (Fl_Group*)(o->parent()); return (Fl_Button*)(g->child(g->find(*o)+i)); } static Fl_Menu_Item alignmenu[] = { {"FL_ALIGN_CENTER",0,0,(void*)(fl_intptr_t)(FL_ALIGN_CENTER)}, {"FL_ALIGN_TOP",0,0,(void*)(fl_intptr_t)(FL_ALIGN_TOP)}, {"FL_ALIGN_BOTTOM",0,0,(void*)(fl_intptr_t)(FL_ALIGN_BOTTOM)}, {"FL_ALIGN_LEFT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_LEFT)}, {"FL_ALIGN_RIGHT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_RIGHT)}, {"FL_ALIGN_INSIDE",0,0,(void*)(fl_intptr_t)(FL_ALIGN_INSIDE)}, {"FL_ALIGN_CLIP",0,0,(void*)(fl_intptr_t)(FL_ALIGN_CLIP)}, {"FL_ALIGN_WRAP",0,0,(void*)(fl_intptr_t)(FL_ALIGN_WRAP)}, {"FL_ALIGN_TEXT_OVER_IMAGE",0,0,(void*)(fl_intptr_t)(FL_ALIGN_TEXT_OVER_IMAGE)}, {"FL_ALIGN_TOP_LEFT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_TOP_LEFT)}, {"FL_ALIGN_TOP_RIGHT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_TOP_RIGHT)}, {"FL_ALIGN_BOTTOM_LEFT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_BOTTOM_LEFT)}, {"FL_ALIGN_BOTTOM_RIGHT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_BOTTOM_RIGHT)}, {"FL_ALIGN_LEFT_TOP",0,0,(void*)(fl_intptr_t)(FL_ALIGN_LEFT_TOP)}, {"FL_ALIGN_RIGHT_TOP",0,0,(void*)(fl_intptr_t)(FL_ALIGN_RIGHT_TOP)}, {"FL_ALIGN_LEFT_BOTTOM",0,0,(void*)(fl_intptr_t)(FL_ALIGN_LEFT_BOTTOM)}, {"FL_ALIGN_RIGHT_BOTTOM",0,0,(void*)(fl_intptr_t)(FL_ALIGN_RIGHT_BOTTOM)}, {0}}; void align_cb(Fl_Button* i, void *v) { Fl_Align b = Fl_Align(fl_uintptr_t(i->user_data())); if (v == LOAD) { if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); i->value(current_widget->o->align() & b); } else { int mod = 0; undo_checkpoint(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; Fl_Align x = q->o->align(); Fl_Align y; if (i->value()) { y = x | b; if (b == FL_ALIGN_LEFT || b == FL_ALIGN_TOP) { Fl_Button *b1 = relative(i,+1); b1->clear(); y = y & ~(b1->argument()); } if (b == FL_ALIGN_RIGHT || b == FL_ALIGN_BOTTOM) { Fl_Button *b1 = relative(i,-1); b1->clear(); y = y & ~(b1->argument()); } } else { y = x & ~b; } if (x != y) { q->o->align(y); q->redraw(); mod = 1; } } } if (mod) set_modflag(1); } } void align_position_cb(Fl_Choice *i, void *v) { if (v == LOAD) { if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); Fl_Menu_Item *mi = (Fl_Menu_Item*)i->menu(); Fl_Align b = current_widget->o->align() & FL_ALIGN_POSITION_MASK; for (;mi->text;mi++) { if ((Fl_Align)(mi->argument())==b) i->value(mi); } } else { const Fl_Menu_Item *mi = i->menu() + i->value(); Fl_Align b = Fl_Align(fl_uintptr_t(mi->user_data())); int mod = 0; undo_checkpoint(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; Fl_Align x = q->o->align(); Fl_Align y = (x & ~FL_ALIGN_POSITION_MASK) | b; if (x != y) { q->o->align(y); q->redraw(); mod = 1; } } } if (mod) set_modflag(1); } } void align_text_image_cb(Fl_Choice *i, void *v) { if (v == LOAD) { if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); Fl_Menu_Item *mi = (Fl_Menu_Item*)i->menu(); Fl_Align b = current_widget->o->align() & FL_ALIGN_IMAGE_MASK; for (;mi->text;mi++) { if ((Fl_Align)(mi->argument())==b) i->value(mi); } } else { const Fl_Menu_Item *mi = i->menu() + i->value(); Fl_Align b = Fl_Align(fl_uintptr_t(mi->user_data())); int mod = 0; undo_checkpoint(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; Fl_Align x = q->o->align(); Fl_Align y = (x & ~FL_ALIGN_IMAGE_MASK) | b; if (x != y) { q->o->align(y); q->redraw(); mod = 1; } } } if (mod) set_modflag(1); } } //////////////////////////////////////////////////////////////// void callback_cb(CodeEditor* i, void *v) { if (v == LOAD) { const char *cbtext = current_widget->callback(); i->buffer()->text( cbtext ? cbtext : "" ); } else { int mod = 0; char *c = i->buffer()->text(); const char *d = c_check(c); if (d) { fl_message("Error in callback: %s",d); if (i->window()) i->window()->make_current(); haderror = 1; } for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected) { o->callback(c); mod = 1; } } if (mod) set_modflag(1); free(c); } } void comment_cb(Fl_Text_Editor* i, void *v) { if (v == LOAD) { const char *cmttext = current_widget->comment(); i->buffer()->text( cmttext ? cmttext : "" ); } else { int mod = 0; char *c = i->buffer()->text(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected) { o->comment(c); mod = 1; } } if (mod) set_modflag(1); free(c); } } void user_data_cb(Fl_Input *i, void *v) { if (v == LOAD) { i->value(current_widget->user_data()); } else { int mod = 0; const char *c = i->value(); const char *d = c_check(c); if (d) {fl_message("Error in user_data: %s",d); haderror = 1; return;} for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected) { o->user_data(c); mod = 1; } } if (mod) set_modflag(1); } } void user_data_type_cb(Fl_Input_Choice *i, void *v) { static const char *dflt = "void*"; if (v == LOAD) { const char *c = current_widget->user_data_type(); if (!c) c = dflt; i->value(c); } else { int mod = 0; const char *c = i->value(); const char *d = c_check(c); if (!*c) i->value(dflt); else if (!strcmp(c,dflt)) c = 0; if (!d) { if (c && *c && c[strlen(c)-1] != '*' && strcmp(c,"long")) d = "must be pointer or long"; } if (d) {fl_message("Error in type: %s",d); haderror = 1; return;} for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected) { o->user_data_type(c); mod = 1; } } if (mod) set_modflag(1); } } // "v_attributes" let user type in random code for attribute settings: void v_input_cb(Fl_Input* i, void* v) { int n = fl_int(i->user_data()); if (v == LOAD) { i->value(current_widget->extra_code(n)); } else { int mod = 0; const char *c = i->value(); const char *d = c_check(c&&c[0]=='#' ? c+1 : c); if (d) {fl_message("Error in %s: %s",i->label(),d); haderror = 1; return;} for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type *t = (Fl_Widget_Type*)o; t->extra_code(n,c); mod = 1; } } if (mod) set_modflag(1); } } void subclass_cb(Fl_Input* i, void* v) { if (v == LOAD) { if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); i->value(current_widget->subclass()); } else { int mod = 0; const char *c = i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type *t = (Fl_Widget_Type*)o; t->subclass(c); mod = 1; } } if (mod) set_modflag(1); } } //////////////////////////////////////////////////////////////// // textstuff: set textfont, textsize, textcolor attributes: // default widget returns 0 to indicate not-implemented: // The first parameter specifies the operation: // 0: get all values // 1: set the text font // 2: set the text size // 3: set the text color // 4: get all default values for this type int Fl_Widget_Type::textstuff(int, Fl_Font&, int&, Fl_Color&) { return 0; } void textfont_cb(Fl_Choice* i, void* v) { Fl_Font n; int s; Fl_Color c; if (v == LOAD) { if (!current_widget->textstuff(0,n,s,c)) {i->deactivate(); return;} i->activate(); if (n > 15) n = FL_HELVETICA; i->value(n); } else { int mod = 0; n = (Fl_Font)i->value(); if (n <= 0) n = layout->textfont; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; q->textstuff(1,n,s,c); q->o->redraw(); mod = 1; } } if (mod) set_modflag(1); } } void textsize_cb(Fl_Value_Input* i, void* v) { Fl_Font n; int s; Fl_Color c; if (v == LOAD) { if (!current_widget->textstuff(0,n,s,c)) {i->deactivate(); return;} i->activate(); } else { int mod = 0; s = int(i->value()); if (s <= 0) s = layout->textsize; if (s <= 0) s = layout->labelsize; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; q->textstuff(2,n,s,c); q->o->redraw(); mod = 1; } } if (mod) set_modflag(1); } i->value(s); } void textcolor_common(Fl_Color c) { Fl_Font n; int s; int mod = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; q->textstuff(3,n,s,c); q->o->redraw(); mod = 1; } } if (mod) set_modflag(1); } void textcolor_cb(Fl_Button* i, void* v) { Fl_Font n; int s; Fl_Color c; if (v == LOAD) { if (!current_widget->textstuff(0,n,s,c)) {i->deactivate(); return;} i->activate(); } else { c = i->color(); Fl_Color d = fl_show_colormap(c); if (d == c) return; c = d; textcolor_common(c); } i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); } void textcolor_menu_cb(Fl_Menu_Button* i, void* v) { Fl_Font n; int s; Fl_Color c; if (v == LOAD) { if (!current_widget->textstuff(0,n,s,c)) {i->deactivate(); return;} i->activate(); } else { c = i->color(); Fl_Color d = (Fl_Color)(i->mvalue()->argument()); if (d == c) return; c = d; textcolor_common(c); w_textcolor->color(c); w_textcolor->labelcolor(fl_contrast(FL_BLACK,c)); w_textcolor->redraw(); } } void image_spacing_cb(Fl_Value_Input* i, void* v) { int s; if (v == LOAD) { if (!current_widget->is_true_widget()) { i->deactivate(); i->value(0); } else { i->activate(); i->value(((Fl_Widget_Type*)current_widget)->o->label_image_spacing()); } } else { int mod = 0; s = int(i->value()); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_true_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; if (q->o->label_image_spacing() != s) { q->o->label_image_spacing(s); if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels q->o->redraw(); mod = 1; } } } if (mod) set_modflag(1); } } void h_label_margin_cb(Fl_Value_Input* i, void* v) { int s; if (v == LOAD) { if (!current_widget->is_true_widget()) { i->deactivate(); i->value(0); } else { i->activate(); i->value(((Fl_Widget_Type*)current_widget)->o->horizontal_label_margin()); } } else { int mod = 0; s = int(i->value()); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_true_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; if (q->o->horizontal_label_margin() != s) { q->o->horizontal_label_margin(s); if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels q->o->redraw(); mod = 1; } } } if (mod) set_modflag(1); } } void v_label_margin_cb(Fl_Value_Input* i, void* v) { int s; if (v == LOAD) { if (!current_widget->is_true_widget()) { i->deactivate(); i->value(0); } else { i->activate(); i->value(((Fl_Widget_Type*)current_widget)->o->vertical_label_margin()); } } else { int mod = 0; s = int(i->value()); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_true_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; if (q->o->vertical_label_margin() != s) { q->o->vertical_label_margin(s); if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels q->o->redraw(); mod = 1; } } } if (mod) set_modflag(1); } } //////////////////////////////////////////////////////////////// // Kludges to the panel for subclasses: void min_w_cb(Fl_Value_Input* i, void* v) { if (v == LOAD) { if (!current_widget->is_a(ID_Window)) return; i->value(((Fl_Window_Type*)current_widget)->sr_min_w); } else { int mod = 0; undo_checkpoint(); int n = (int)i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_a(ID_Window)) { ((Fl_Window_Type*)current_widget)->sr_min_w = n; mod = 1; } } if (mod) set_modflag(1); } } void min_h_cb(Fl_Value_Input* i, void* v) { if (v == LOAD) { if (!current_widget->is_a(ID_Window)) return; i->value(((Fl_Window_Type*)current_widget)->sr_min_h); } else { int mod = 0; undo_checkpoint(); int n = (int)i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_a(ID_Window)) { ((Fl_Window_Type*)current_widget)->sr_min_h = n; mod = 1; } } if (mod) set_modflag(1); } } void max_w_cb(Fl_Value_Input* i, void* v) { if (v == LOAD) { if (!current_widget->is_a(ID_Window)) return; i->value(((Fl_Window_Type*)current_widget)->sr_max_w); } else { int mod = 0; undo_checkpoint(); int n = (int)i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_a(ID_Window)) { ((Fl_Window_Type*)current_widget)->sr_max_w = n; mod = 1; } } if (mod) set_modflag(1); } } void max_h_cb(Fl_Value_Input* i, void* v) { if (v == LOAD) { if (!current_widget->is_a(ID_Window)) return; i->value(((Fl_Window_Type*)current_widget)->sr_max_h); } else { int mod = 0; undo_checkpoint(); int n = (int)i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_a(ID_Window)) { ((Fl_Window_Type*)current_widget)->sr_max_h = n; mod = 1; } } if (mod) set_modflag(1); } } void set_min_size_cb(Fl_Button*, void* v) { if (v == LOAD) { } else { int mod = 0; undo_checkpoint(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_a(ID_Window)) { Fl_Window_Type *win = (Fl_Window_Type*)current_widget; win->sr_min_w = win->o->w(); win->sr_min_h = win->o->h(); mod = 1; } } propagate_load(the_panel, LOAD); if (mod) set_modflag(1); } } void set_max_size_cb(Fl_Button*, void* v) { if (v == LOAD) { } else { int mod = 0; undo_checkpoint(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_a(ID_Window)) { Fl_Window_Type *win = (Fl_Window_Type*)current_widget; win->sr_max_w = win->o->w(); win->sr_max_h = win->o->h(); mod = 1; } } propagate_load(the_panel, LOAD); if (mod) set_modflag(1); } } void slider_size_cb(Fl_Value_Input* i, void* v) { if (v == LOAD) { if (!current_widget->is_a(ID_Slider)) {i->deactivate(); return;} i->activate(); i->value(((Fl_Slider*)(current_widget->o))->slider_size()); } else { int mod = 0; undo_checkpoint(); double n = i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; if (q->is_a(ID_Slider)) { ((Fl_Slider*)(q->o))->slider_size(n); q->o->redraw(); mod = 1; } } } if (mod) set_modflag(1); } } void min_cb(Fl_Value_Input* i, void* v) { if (v == LOAD) { if (current_widget->is_a(ID_Valuator_)) { i->activate(); i->value(((Fl_Valuator*)(current_widget->o))->minimum()); } else if (current_widget->is_a(ID_Spinner)) { i->activate(); i->value(((Fl_Spinner*)(current_widget->o))->minimum()); } else { i->deactivate(); return; } } else { int mod = 0; undo_checkpoint(); double n = i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; if (q->is_a(ID_Valuator_)) { ((Fl_Valuator*)(q->o))->minimum(n); q->o->redraw(); mod = 1; } else if (q->is_a(ID_Spinner)) { ((Fl_Spinner*)(q->o))->minimum(n); q->o->redraw(); mod = 1; } } } if (mod) set_modflag(1); } } void max_cb(Fl_Value_Input* i, void* v) { if (v == LOAD) { if (current_widget->is_a(ID_Valuator_)) { i->activate(); i->value(((Fl_Valuator*)(current_widget->o))->maximum()); } else if (current_widget->is_a(ID_Spinner)) { i->activate(); i->value(((Fl_Spinner*)(current_widget->o))->maximum()); } else { i->deactivate(); return; } } else { int mod = 0; undo_checkpoint(); double n = i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; if (q->is_a(ID_Valuator_)) { ((Fl_Valuator*)(q->o))->maximum(n); q->o->redraw(); mod = 1; } else if (q->is_a(ID_Spinner)) { ((Fl_Spinner*)(q->o))->maximum(n); q->o->redraw(); mod = 1; } } } if (mod) set_modflag(1); } } void step_cb(Fl_Value_Input* i, void* v) { if (v == LOAD) { if (current_widget->is_a(ID_Valuator_)) { i->activate(); i->value(((Fl_Valuator*)(current_widget->o))->step()); } else if (current_widget->is_a(ID_Spinner)) { i->activate(); i->value(((Fl_Spinner*)(current_widget->o))->step()); } else { i->deactivate(); return; } } else { int mod = 0; undo_checkpoint(); double n = i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; if (q->is_a(ID_Valuator_)) { ((Fl_Valuator*)(q->o))->step(n); q->o->redraw(); mod = 1; } else if (q->is_a(ID_Spinner)) { ((Fl_Spinner*)(q->o))->step(n); q->o->redraw(); mod = 1; } } } if (mod) set_modflag(1); } } void value_cb(Fl_Value_Input* i, void* v) { if (v == LOAD) { if (current_widget->is_a(ID_Valuator_)) { i->activate(); i->value(((Fl_Valuator*)(current_widget->o))->value()); } else if (current_widget->is_button()) { i->activate(); i->value(((Fl_Button*)(current_widget->o))->value()); } else if (current_widget->is_a(ID_Spinner)) { i->activate(); i->value(((Fl_Spinner*)(current_widget->o))->value()); } else i->deactivate(); } else { int mod = 0; undo_checkpoint(); double n = i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; if (q->is_a(ID_Valuator_)) { ((Fl_Valuator*)(q->o))->value(n); mod = 1; } else if (q->is_button()) { ((Fl_Button*)(q->o))->value(n != 0); if (q->is_a(ID_Menu_Item)) q->redraw(); mod = 1; } else if (q->is_a(ID_Spinner)) { ((Fl_Spinner*)(q->o))->value(n); mod = 1; } } } if (mod) set_modflag(1); } } // The following three callbacks cooperate, showing only one of the groups of // widgets that use the same space in the dialog. void values_group_cb(Fl_Group* g, void* v) { if (v == LOAD) { if ( current_widget->is_a(ID_Flex) || current_widget->is_a(ID_Grid) || current_widget->is_a(ID_Window)) { g->hide(); } else { g->show(); } propagate_load(g, v); } } void flex_margin_group_cb(Fl_Group* g, void* v) { if (v == LOAD) { if (current_widget->is_a(ID_Flex)) { g->show(); } else { g->hide(); } propagate_load(g, v); } } void size_range_group_cb(Fl_Group* g, void* v) { if (v == LOAD) { if (current_widget->is_a(ID_Window)) { g->show(); } else { g->hide(); } propagate_load(g, v); } } static void flex_margin_cb(Fl_Value_Input* i, void* v, void (*load_margin)(Fl_Flex*,Fl_Value_Input*), int (*update_margin)(Fl_Flex*,int)) { if (v == LOAD) { if (current_widget->is_a(ID_Flex)) { load_margin((Fl_Flex*)current_widget->o, i); } } else { int mod = 0; int new_value = (int)i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_a(ID_Flex)) { Fl_Flex_Type* q = (Fl_Flex_Type*)o; Fl_Flex* w = (Fl_Flex*)q->o; if (update_margin(w, new_value)) { w->layout(); mod = 1; } } } if (mod) set_modflag(1); } } static void load_left_margin(Fl_Flex *w, Fl_Value_Input* i) { int v; w->margin(&v, NULL, NULL, NULL); i->value((double)v); } static int update_left_margin(Fl_Flex *w, int new_value) { int l, t, r, b; w->margin(&l, &t, &r, &b); if (new_value!=l) { w->margin(new_value, t, r, b); return 1; } else { return 0; } } void flex_margin_left_cb(Fl_Value_Input* i, void* v) { flex_margin_cb(i, v, load_left_margin, update_left_margin); } static void load_top_margin(Fl_Flex *w, Fl_Value_Input* i) { int v; w->margin(NULL, &v, NULL, NULL); i->value((double)v); } static int update_top_margin(Fl_Flex *w, int new_value) { int l, t, r, b; w->margin(&l, &t, &r, &b); if (new_value!=t) { w->margin(l, new_value, r, b); return 1; } else { return 0; } } void flex_margin_top_cb(Fl_Value_Input* i, void* v) { flex_margin_cb(i, v, load_top_margin, update_top_margin); } static void load_right_margin(Fl_Flex *w, Fl_Value_Input* i) { int v; w->margin(NULL, NULL, &v, NULL); i->value((double)v); } static int update_right_margin(Fl_Flex *w, int new_value) { int l, t, r, b; w->margin(&l, &t, &r, &b); if (new_value!=r) { w->margin(l, t, new_value, b); return 1; } else { return 0; } } void flex_margin_right_cb(Fl_Value_Input* i, void* v) { flex_margin_cb(i, v, load_right_margin, update_right_margin); } static void load_bottom_margin(Fl_Flex *w, Fl_Value_Input* i) { int v; w->margin(NULL, NULL, NULL, &v); i->value((double)v); } static int update_bottom_margin(Fl_Flex *w, int new_value) { int l, t, r, b; w->margin(&l, &t, &r, &b); if (new_value!=b) { w->margin(l, t, r, new_value); return 1; } else { return 0; } } void flex_margin_bottom_cb(Fl_Value_Input* i, void* v) { flex_margin_cb(i, v, load_bottom_margin, update_bottom_margin); } static void load_gap(Fl_Flex *w, Fl_Value_Input* i) { int v = w->gap(); i->value((double)v); } static int update_gap(Fl_Flex *w, int new_value) { int g = w->gap(); if (new_value!=g) { w->gap(new_value); return 1; } else { return 0; } } void flex_margin_gap_cb(Fl_Value_Input* i, void* v) { flex_margin_cb(i, v, load_gap, update_gap); } void position_group_cb(Fl_Group* g, void* v) { if (v == LOAD) { if (Fl_Flex_Type::parent_is_flex(current_widget)) { g->hide(); } else { g->show(); } } propagate_load(g, v); } void flex_size_group_cb(Fl_Group* g, void* v) { if (v == LOAD) { if (Fl_Flex_Type::parent_is_flex(current_widget)) { g->show(); } else { g->hide(); } } propagate_load(g, v); } void flex_size_cb(Fl_Value_Input* i, void* v) { if (v == LOAD) { if (Fl_Flex_Type::parent_is_flex(current_widget)) { i->value(Fl_Flex_Type::size(current_widget)); } } else { int mod = 0; int new_size = (int)i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget() && Fl_Flex_Type::parent_is_flex(o)) { Fl_Widget* w = (Fl_Widget*)((Fl_Widget_Type*)o)->o; Fl_Flex* f = (Fl_Flex*)((Fl_Flex_Type*)o->parent)->o; int was_fixed = f->fixed(w); if (new_size==0) { if (was_fixed) { f->fixed(w, 0); f->layout(); widget_flex_fixed->value(0); mod = 1; } } else { int old_size = Fl_Flex_Type::size(o); if (old_size!=new_size || !was_fixed) { f->fixed(w, new_size); f->layout(); widget_flex_fixed->value(1); mod = 1; } } } } if (mod) set_modflag(1); } } void flex_fixed_cb(Fl_Check_Button* i, void* v) { if (v == LOAD) { if (Fl_Flex_Type::parent_is_flex(current_widget)) { i->value(Fl_Flex_Type::is_fixed(current_widget)); } } else { int mod = 0; int new_fixed = (int)i->value(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget() && Fl_Flex_Type::parent_is_flex(o)) { Fl_Widget* w = (Fl_Widget*)((Fl_Widget_Type*)o)->o; Fl_Flex* f = (Fl_Flex*)((Fl_Flex_Type*)o->parent)->o; int was_fixed = f->fixed(w); if (new_fixed==0) { if (was_fixed) { f->fixed(w, 0); f->layout(); mod = 1; } } else { if (!was_fixed) { f->fixed(w, Fl_Flex_Type::size(o)); f->layout(); mod = 1; } } } } if (mod) set_modflag(1); } } //////////////////////////////////////////////////////////////// // subtypes: Fl_Menu_Item *Fl_Widget_Type::subtypes() {return 0;} void subtype_cb(Fl_Choice* i, void* v) { static Fl_Menu_Item empty_type_menu[] = { {"Normal",0,0,(void*)0}, {0}}; if (v == LOAD) { Fl_Menu_Item* m = current_widget->subtypes(); if (!m) { i->menu(empty_type_menu); i->value(0); i->deactivate(); } else { i->menu(m); int j; for (j = 0;; j++) { if (!m[j].text) {j = 0; break;} if (current_widget->is_a(ID_Spinner)) { if (m[j].argument() == ((Fl_Spinner*)current_widget->o)->type()) break; } else { if (m[j].argument() == current_widget->o->type()) break; } } i->value(j); i->activate(); } i->redraw(); } else { int mod = 0; int n = int(i->mvalue()->argument()); Fl_Menu_Item* m = current_widget->subtypes(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_widget()) { Fl_Widget_Type* q = (Fl_Widget_Type*)o; if (q->subtypes()==m) { if (q->is_a(ID_Spinner)) ((Fl_Spinner*)q->o)->type(n); else if (q->is_a(ID_Flex)) ((Fl_Flex_Type*)q)->change_subtype_to(n); else q->o->type(n); q->redraw(); mod = 1; } } } if (mod) set_modflag(1); } } //////////////////////////////////////////////////////////////// void propagate_load(Fl_Group* g, void* v) { if (v == LOAD) { Fl_Widget*const* a = g->array(); for (int i=g->children(); i--;) { Fl_Widget* o = *a++; o->do_callback(o, LOAD, FL_REASON_USER); } } } void set_cb(Fl_Button*, void*) { haderror = 0; Fl_Widget*const* a = the_panel->array(); for (int i=the_panel->children(); i--;) { Fl_Widget* o = *a++; if (o->changed()) { o->do_callback(); if (haderror) return; o->clear_changed(); } } } void ok_cb(Fl_Return_Button* o, void* v) { set_cb(o,v); if (!haderror) the_panel->hide(); } void toggle_overlays(Fl_Widget *,void *); // in Fl_Window_Type.cxx void overlay_cb(Fl_Button*o,void *v) { toggle_overlays(o,v); } void leave_live_mode_cb(Fl_Widget*, void*); void live_mode_cb(Fl_Button*o,void *) { /// \todo live mode should end gracefully when the application quits /// or when the user closes the live widget static Fl_Type *live_type = 0L; static Fl_Widget *live_widget = 0L; static Fl_Window *live_window = 0L; // if 'o' is 0, we must quit live mode if (!o) { o = wLiveMode; o->value(0); } if (o->value()) { if (numselected == 1) { Fl_Group::current(0L); live_widget = current_widget->enter_live_mode(1); if (live_widget) { live_type = current_widget; Fl_Group::current(0); int w = live_widget->w(); int h = live_widget->h(); live_window = new Fl_Double_Window(w+20, h+55, "Fluid Live Resize"); live_window->box(FL_FLAT_BOX); live_window->color(FL_GREEN); Fl_Group *rsz = new Fl_Group(0, h+20, 130, 35); rsz->box(FL_NO_BOX); Fl_Box *rsz_dummy = new Fl_Box(110, h+20, 1, 25); rsz_dummy->box(FL_NO_BOX); rsz->resizable(rsz_dummy); Fl_Button *btn = new Fl_Button(10, h+20, 100, 25, "Exit Live Resize"); btn->labelsize(12); btn->callback(leave_live_mode_cb); rsz->end(); live_window->add(live_widget); live_widget->position(10, 10); live_window->resizable(live_widget); live_window->set_modal(); // block all other UI live_window->callback(leave_live_mode_cb); if (current_widget->is_a(ID_Window)) { Fl_Window_Type *w = (Fl_Window_Type*)current_widget; int mw = w->sr_min_w; if (mw>0) mw += 20; int mh = w->sr_min_h; if (mh>0) mh += 55; int MW = w->sr_max_w; if (MW>0) MW += 20; int MH = w->sr_max_h; if (MH>2) MH += 55; if (mw || mh || MW || MH) live_window->size_range(mw, mh, MW, MH); } live_window->show(); live_widget->show(); } else o->value(0); } else o->value(0); } else { if (live_type) live_type->leave_live_mode(); if (live_window) { live_window->hide(); Fl::delete_widget(live_window); } live_type = 0L; live_widget = 0L; live_window = 0L; } } // update the panel according to current widget set: void load_panel() { if (!the_panel) return; // find all the Fl_Widget subclasses currently selected: numselected = 0; current_widget = 0; if (Fl_Type::current) { if (Fl_Type::current->is_widget()) current_widget=(Fl_Widget_Type*)Fl_Type::current; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->is_widget() && o->selected) { numselected++; if (!current_widget) current_widget = (Fl_Widget_Type*)o; } } } if (current_widget && current_widget->is_a(ID_Grid)) { if (widget_tab_grid->parent()!=widget_tabs) widget_tabs->add(widget_tab_grid); } else { if (widget_tab_grid->parent()==widget_tabs) { widget_tabs_repo->add(widget_tab_grid); } } if (current_widget && current_widget->parent && current_widget->parent->is_a(ID_Grid)) { if (widget_tab_grid_child->parent()!=widget_tabs) widget_tabs->add(widget_tab_grid_child); } else { if (widget_tab_grid_child->parent()==widget_tabs) { widget_tabs_repo->add(widget_tab_grid_child); } } if (numselected) propagate_load(the_panel, LOAD); else the_panel->hide(); } extern Fl_Window *widgetbin_panel; // This is called when user double-clicks an item, open or update the panel: void Fl_Widget_Type::open() { bool adjust_position = false; if (!the_panel) { the_panel = make_widget_panel(); adjust_position = true; } load_panel(); if (numselected) { the_panel->show(); if (adjust_position) { if (widgetbin_panel && widgetbin_panel->visible()) { if ( (the_panel->x()+the_panel->w() > widgetbin_panel->x()) && (the_panel->x() < widgetbin_panel->x()+widgetbin_panel->w()) && (the_panel->y()+the_panel->h() > widgetbin_panel->y()) && (the_panel->y() < widgetbin_panel->y()+widgetbin_panel->h()) ) { if (widgetbin_panel->y()+widgetbin_panel->h()+the_panel->h() > Fl::h()) the_panel->position(the_panel->x(), widgetbin_panel->y()-the_panel->h()-30); else the_panel->position(the_panel->x(), widgetbin_panel->y()+widgetbin_panel->h()+30); } } } } } extern void redraw_overlays(); extern void check_redraw_corresponding_parent(Fl_Type*); extern void redraw_browser(); extern void update_codeview_position(); // Called when ui changes what objects are selected: // p is selected object, null for all deletions (we must throw away // old panel in that case, as the object may no longer exist) void selection_changed(Fl_Type *p) { // store all changes to the current selected objects: if (p && the_panel && the_panel->visible()) { set_cb(0,0); // if there was an error, we try to leave the selected set unchanged: if (haderror) { Fl_Type *q = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { o->new_selected = o->selected; if (!q && o->selected) q = o; } if (!p || !p->selected) p = q; Fl_Type::current = p; redraw_browser(); return; } } // update the selected flags to new set: Fl_Type *q = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) { o->selected = o->new_selected; if (!q && o->selected) q = o; } if (!p || !p->selected) p = q; Fl_Type::current = p; check_redraw_corresponding_parent(p); redraw_overlays(); // load the panel with the new settings: load_panel(); // update the code viewer to show the code for the selected object update_codeview_position(); } //////////////////////////////////////////////////////////////// // Writing the C code: // test to see if user named a function, or typed in code: int is_name(const char *c) { for (; *c; c++) if ((ispunct(*c)||*c=='\n') && *c!='_' && *c!=':') return 0; return 1; } // Test to see if name() is an array entry. If so, and this is the // highest number, return name[num+1]. Return null if not the highest // number or a field or function. Return name() if not an array entry. const char *array_name(Fl_Widget_Type *o) { const char *c = o->name(); if (!c) return 0; const char *d; for (d = c; *d != '['; d++) { if (!*d) return c; if (ispunct(*d) && *d!='_') return 0; } int num = atoi(d+1); int sawthis = 0; Fl_Type *t = o->prev; Fl_Type *tp = o; const char *cn = o->class_name(1); for (; t && t->class_name(1) == cn; tp = t, t = t->prev) {/*empty*/} for (t = tp; t && t->class_name(1) == cn; t = t->next) { if (t == o) {sawthis=1; continue;} const char *e = t->name(); if (!e) continue; if (strncmp(c,e,d-c)) continue; int n1 = atoi(e+(d-c)+1); if (n1 > num || (n1==num && sawthis)) return 0; } static char buffer[128]; // MRS: we want strncpy() here... strncpy(buffer,c,d-c+1); snprintf(buffer+(d-c+1),sizeof(buffer) - (d-c+1), "%d]",num+1); return buffer; } // Test to see if extra code is a declaration: int isdeclare(const char *c) { while (isspace(*c)) c++; if (*c == '#') return 1; if (!strncmp(c,"extern",6)) return 1; if (!strncmp(c,"typedef",7)) return 1; if (!strncmp(c,"using",5)) return 1; return 0; } void Fl_Widget_Type::write_static(Fd_Code_Writer& f) { const char* t = subclassname(this); if (!subclass() || (is_class() && !strncmp(t, "Fl_", 3))) { f.write_h_once("#include "); f.write_h_once("#include ", t); } for (int n=0; n < NUM_EXTRA_CODE; n++) { if (extra_code(n) && isdeclare(extra_code(n))) f.write_h_once("%s", extra_code(n)); } if (callback() && is_name(callback())) { int write_extern_declaration = 1; char buf[1024]; snprintf(buf, 1023, "%s(*)", callback()); if (is_in_class()) { if (has_function("static void", buf)) write_extern_declaration = 0; } else { if (has_toplevel_function(0L, buf)) write_extern_declaration = 0; } if (write_extern_declaration) f.write_h_once("extern void %s(%s*, %s);", callback(), t, user_data_type() ? user_data_type() : "void*"); } const char* k = class_name(1); const char* c = array_name(this); if (c && !k && !is_class()) { f.write_c("\n"); if (!public_) f.write_c("static "); else f.write_h("extern %s *%s;\n", t, c); if (strchr(c, '[') == NULL) f.write_c("%s *%s=(%s *)0;\n", t, c, t); else f.write_c("%s *%s={(%s *)0};\n", t, c, t); } if (callback() && !is_name(callback())) { // see if 'o' or 'v' used, to prevent unused argument warnings: int use_o = 0; int use_v = 0; const char *d; for (d = callback(); *d;) { if (*d == 'o' && !is_id(d[1])) use_o = 1; if (*d == 'v' && !is_id(d[1])) use_v = 1; do d++; while (is_id(*d)); while (*d && !is_id(*d)) d++; } const char* cn = callback_name(f); if (k) { f.write_c("\nvoid %s::%s_i(%s*", k, cn, t); } else { f.write_c("\nstatic void %s(%s*", cn, t); } if (use_o) f.write_c(" o"); const char* ut = user_data_type() ? user_data_type() : "void*"; f.write_c(", %s", ut); if (use_v) f.write_c(" v"); f.write_c(") {\n"); // Matt: disabled f.tag(FD_TAG_GENERIC, 0); f.write_c_indented(callback(), 1, 0); if (*(d-1) != ';' && *(d-1) != '}') { const char *p = strrchr(callback(), '\n'); if (p) p ++; else p = callback(); // Only add trailing semicolon if the last line is not a preprocessor // statement... if (*p != '#' && *p) f.write_c(";"); } f.write_c("\n"); // Matt: disabled f.tag(FD_TAG_WIDGET_CALLBACK, get_uid()); f.write_c("}\n"); if (k) { f.write_c("void %s::%s(%s* o, %s v) {\n", k, cn, t, ut); f.write_c("%s((%s*)(o", f.indent(1), k); Fl_Type *q = 0; for (Fl_Type* p = parent; p && p->is_widget(); q = p, p = p->parent) f.write_c("->parent()"); if (!q || !q->is_a(ID_Widget_Class)) f.write_c("->user_data()"); f.write_c("))->%s_i(o,v);\n}\n", cn); } } if (image) { if (!f.c_contains(image)) image->write_static(f, compress_image_); } if (inactive) { if (!f.c_contains(inactive)) inactive->write_static(f, compress_deimage_); } } void Fl_Widget_Type::write_code1(Fd_Code_Writer& f) { const char* t = subclassname(this); const char *c = array_name(this); if (c) { if (class_name(1)) { f.write_public(public_); f.write_h("%s%s *%s;\n", f.indent(1), t, c); } } if (class_name(1) && callback() && !is_name(callback())) { const char* cn = callback_name(f); const char* ut = user_data_type() ? user_data_type() : "void*"; f.write_public(0); f.write_h("%sinline void %s_i(%s*, %s);\n", f.indent(1), cn, t, ut); f.write_h("%sstatic void %s(%s*, %s);\n", f.indent(1), cn, t, ut); } // figure out if local variable will be used (prevent compiler warnings): int wused = !name() && is_a(ID_Window); const char *ptr; f.varused = wused; if (!name() && !f.varused) { f.varused |= can_have_children(); if (!f.varused) { f.varused_test = 1; write_widget_code(f); f.varused_test = 0; } } if (!f.varused) { for (int n=0; n < NUM_EXTRA_CODE; n++) if (extra_code(n) && !isdeclare(extra_code(n))) { int instring = 0; int inname = 0; int incomment = 0; int incppcomment = 0; for (ptr = extra_code(n); *ptr; ptr ++) { if (instring) { if (*ptr == '\\') ptr++; else if (*ptr == '\"') instring = 0; } else if (inname && !isalnum(*ptr & 255)) { inname = 0; } else if (*ptr == '/' && ptr[1]=='*') { incomment = 1; ptr++; } else if (incomment) { if (*ptr == '*' && ptr[1]=='/') { incomment = 0; ptr++; } } else if (*ptr == '/' && ptr[1]=='/') { incppcomment = 1; ptr++; } else if (incppcomment) { if (*ptr == '\n') incppcomment = 0; } else if (*ptr == '\"') { instring = 1; } else if (isalnum(*ptr & 255) || *ptr == '_') { size_t len = strspn(ptr, "0123456789_" "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); if (!strncmp(ptr, "o", len)) { f.varused = 1; break; } else { ptr += len - 1; } } } } } f.write_c("%s{ ", f.indent()); write_comment_inline_c(f); if (f.varused) f.write_c("%s* o = ", t); if (name()) f.write_c("%s = ", name()); if (is_a(ID_Window)) { // Handle special case where user is faking a Fl_Group type as a window, // there is no 2-argument constructor in that case: if (!strstr(t, "Window")) f.write_c("new %s(0, 0, %d, %d", t, o->w(), o->h()); else f.write_c("new %s(%d, %d", t, o->w(), o->h()); } else if (is_a(ID_Menu_Bar) && ((Fl_Menu_Bar_Type*)this)->is_sys_menu_bar() && is_in_class()) { f.write_c("(%s*)new %s(%d, %d, %d, %d", t, ((Fl_Menu_Bar_Type*)this)->sys_menubar_proxy_name(), o->x(), o->y(), o->w(), o->h()); } else { f.write_c("new %s(%d, %d, %d, %d", t, o->x(), o->y(), o->w(), o->h()); } if (label() && *label()) { f.write_c(", "); switch (g_project.i18n_type) { case FD_I18N_NONE : /* None */ f.write_cstring(label()); break; case FD_I18N_GNU : /* GNU gettext */ f.write_c("%s(", g_project.i18n_gnu_function.c_str()); f.write_cstring(label()); f.write_c(")"); break; case FD_I18N_POSIX : /* POSIX catgets */ f.write_c("catgets(%s,%s,%d,", g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), g_project.i18n_pos_set.c_str(), msgnum()); f.write_cstring(label()); f.write_c(")"); break; } } f.write_c(");\n"); f.indentation++; // Avoid compiler warning for unused variable. // Also avoid quality control warnings about incorrect allocation error handling. if (wused) f.write_c("%sw = o; (void)w;\n", f.indent()); write_widget_code(f); } void Fl_Widget_Type::write_color(Fd_Code_Writer& f, const char* field, Fl_Color color) { const char* color_name = 0; switch (color) { case FL_FOREGROUND_COLOR: color_name = "FL_FOREGROUND_COLOR"; break; case FL_BACKGROUND2_COLOR: color_name = "FL_BACKGROUND2_COLOR"; break; case FL_INACTIVE_COLOR: color_name = "FL_INACTIVE_COLOR"; break; case FL_SELECTION_COLOR: color_name = "FL_SELECTION_COLOR"; break; case FL_GRAY0: color_name = "FL_GRAY0"; break; case FL_DARK3: color_name = "FL_DARK3"; break; case FL_DARK2: color_name = "FL_DARK2"; break; case FL_DARK1: color_name = "FL_DARK1"; break; case FL_BACKGROUND_COLOR: color_name = "FL_BACKGROUND_COLOR"; break; case FL_LIGHT1: color_name = "FL_LIGHT1"; break; case FL_LIGHT2: color_name = "FL_LIGHT2"; break; case FL_LIGHT3: color_name = "FL_LIGHT3"; break; case FL_BLACK: color_name = "FL_BLACK"; break; case FL_RED: color_name = "FL_RED"; break; case FL_GREEN: color_name = "FL_GREEN"; break; case FL_YELLOW: color_name = "FL_YELLOW"; break; case FL_BLUE: color_name = "FL_BLUE"; break; case FL_MAGENTA: color_name = "FL_MAGENTA"; break; case FL_CYAN: color_name = "FL_CYAN"; break; case FL_DARK_RED: color_name = "FL_DARK_RED"; break; case FL_DARK_GREEN: color_name = "FL_DARK_GREEN"; break; case FL_DARK_YELLOW: color_name = "FL_DARK_YELLOW"; break; case FL_DARK_BLUE: color_name = "FL_DARK_BLUE"; break; case FL_DARK_MAGENTA: color_name = "FL_DARK_MAGENTA"; break; case FL_DARK_CYAN: color_name = "FL_DARK_CYAN"; break; case FL_WHITE: color_name = "FL_WHITE"; break; } const char *var = is_class() ? "this" : name() ? name() : "o"; if (color_name) { f.write_c("%s%s->%s(%s);\n", f.indent(), var, field, color_name); } else { f.write_c("%s%s->%s((Fl_Color)%d);\n", f.indent(), var, field, color); } } // this is split from write_code1(Fd_Code_Writer& f) for Fl_Window_Type: void Fl_Widget_Type::write_widget_code(Fd_Code_Writer& f) { Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o; const char *var = is_class() ? "this" : name() ? name() : "o"; if (tooltip() && *tooltip()) { f.write_c("%s%s->tooltip(",f.indent(), var); switch (g_project.i18n_type) { case FD_I18N_NONE : /* None */ f.write_cstring(tooltip()); break; case FD_I18N_GNU : /* GNU gettext */ f.write_c("%s(", g_project.i18n_gnu_function.c_str()); f.write_cstring(tooltip()); f.write_c(")"); break; case FD_I18N_POSIX : /* POSIX catgets */ f.write_c("catgets(%s,%s,%d,", g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), g_project.i18n_pos_set.c_str(), msgnum() + 1); f.write_cstring(tooltip()); f.write_c(")"); break; } f.write_c(");\n"); } if (is_a(ID_Spinner) && ((Fl_Spinner*)o)->type() != ((Fl_Spinner*)tplate)->type()) f.write_c("%s%s->type(%d);\n", f.indent(), var, ((Fl_Spinner*)o)->type()); else if (o->type() != tplate->type() && !is_a(ID_Window)) f.write_c("%s%s->type(%d);\n", f.indent(), var, o->type()); if (o->box() != tplate->box() || subclass()) f.write_c("%s%s->box(FL_%s);\n", f.indent(), var, boxname(o->box())); // write shortcut command if needed int shortcut = 0; if (is_button()) shortcut = ((Fl_Button*)o)->shortcut(); else if (is_a(ID_Input)) shortcut = ((Fl_Input_*)o)->shortcut(); else if (is_a(ID_Value_Input)) shortcut = ((Fl_Value_Input*)o)->shortcut(); else if (is_a(ID_Text_Display)) shortcut = ((Fl_Text_Display*)o)->shortcut(); if (shortcut) { int s = shortcut; f.write_c("%s%s->shortcut(", f.indent(), var); if (g_project.use_FL_COMMAND) { if (s & FL_CTRL) { f.write_c("FL_CONTROL|"); s &= ~FL_CTRL; } if (s & FL_META) { f.write_c("FL_COMMAND|"); s &= ~FL_META; } } else { if (s & FL_CTRL) { f.write_c("FL_CTRL|"); s &= ~FL_CTRL; } if (s & FL_META) { f.write_c("FL_META|"); s &= ~FL_META; } } if (s & FL_SHIFT) { f.write_c("FL_SHIFT|"); s &= ~FL_SHIFT; } if (s & FL_ALT) { f.write_c("FL_ALT|"); s &= ~FL_ALT; } if ((s < 127) && isprint(s)) f.write_c("'%c');\n", s); else f.write_c("0x%x);\n", s); } if (is_a(ID_Button)) { Fl_Button* b = (Fl_Button*)o; if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var, boxname(b->down_box())); if (b->value()) f.write_c("%s%s->value(1);\n", f.indent(), var); if (b->compact()) f.write_c("%s%s->compact(%d);\n", f.indent(), var, b->compact()); } else if (is_a(ID_Input_Choice)) { Fl_Input_Choice* b = (Fl_Input_Choice*)o; if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var, boxname(b->down_box())); } else if (is_a(ID_Menu_Manager_)) { Fl_Menu_* b = (Fl_Menu_*)o; if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var, boxname(b->down_box())); } if (o->color() != tplate->color() || subclass()) write_color(f, "color", o->color()); if (o->selection_color() != tplate->selection_color() || subclass()) write_color(f, "selection_color", o->selection_color()); if (image) { image->write_code(f, bind_image_, var); if (scale_image_w_ || scale_image_h_) { f.write_c("%s%s->image()->scale(", f.indent(), var); if (scale_image_w_>0) f.write_c("%d, ", scale_image_w_); else f.write_c("%s->image()->data_w(), ", var); if (scale_image_h_>0) f.write_c("%d, 0, 1);\n", scale_image_h_); else f.write_c("%s->image()->data_h(), 0, 1);\n", var); } } if (inactive) { inactive->write_code(f, bind_deimage_, var, 1); if (scale_deimage_w_ || scale_deimage_h_) { f.write_c("%s%s->deimage()->scale(", f.indent(), var); if (scale_deimage_w_>0) f.write_c("%d, ", scale_deimage_w_); else f.write_c("%s->deimage()->data_w(), ", var); if (scale_deimage_h_>0) f.write_c("%d, 0, 1);\n", scale_deimage_h_); else f.write_c("%s->deimage()->data_h(), 0, 1);\n", var); } } if (o->labeltype() != tplate->labeltype() || subclass()) f.write_c("%s%s->labeltype(FL_%s);\n", f.indent(), var, item_name(labeltypemenu, o->labeltype())); if (o->labelfont() != tplate->labelfont() || subclass()) f.write_c("%s%s->labelfont(%d);\n", f.indent(), var, o->labelfont()); if (o->labelsize() != tplate->labelsize() || subclass()) f.write_c("%s%s->labelsize(%d);\n", f.indent(), var, o->labelsize()); if (o->labelcolor() != tplate->labelcolor() || subclass()) write_color(f, "labelcolor", o->labelcolor()); if (o->horizontal_label_margin() != tplate->horizontal_label_margin()) f.write_c("%s%s->horizontal_label_margin(%d);\n", f.indent(), var, o->horizontal_label_margin()); if (o->vertical_label_margin() != tplate->vertical_label_margin()) f.write_c("%s%s->vertical_label_margin(%d);\n", f.indent(), var, o->vertical_label_margin()); if (o->label_image_spacing() != tplate->label_image_spacing()) f.write_c("%s%s->label_image_spacing(%d);\n", f.indent(), var, o->label_image_spacing()); if (is_a(ID_Valuator_)) { Fl_Valuator* v = (Fl_Valuator*)o; Fl_Valuator* t = (Fl_Valuator*)(tplate); if (v->minimum()!=t->minimum()) f.write_c("%s%s->minimum(%g);\n", f.indent(), var, v->minimum()); if (v->maximum()!=t->maximum()) f.write_c("%s%s->maximum(%g);\n", f.indent(), var, v->maximum()); if (v->step()!=t->step()) f.write_c("%s%s->step(%g);\n", f.indent(), var, v->step()); if (v->value()) { if (is_a(ID_Scrollbar)) { // Fl_Scrollbar::value(double) is not available f.write_c("%s%s->Fl_Slider::value(%g);\n", f.indent(), var, v->value()); } else { f.write_c("%s%s->value(%g);\n", f.indent(), var, v->value()); } } if (is_a(ID_Slider)) { double x = ((Fl_Slider*)v)->slider_size(); double y = ((Fl_Slider*)t)->slider_size(); if (x != y) f.write_c("%s%s->slider_size(%g);\n", f.indent(), var, x); } } if (is_a(ID_Spinner)) { Fl_Spinner* v = (Fl_Spinner*)o; Fl_Spinner* t = (Fl_Spinner*)(tplate); if (v->minimum()!=t->minimum()) f.write_c("%s%s->minimum(%g);\n", f.indent(), var, v->minimum()); if (v->maximum()!=t->maximum()) f.write_c("%s%s->maximum(%g);\n", f.indent(), var, v->maximum()); if (v->step()!=t->step()) f.write_c("%s%s->step(%g);\n", f.indent(), var, v->step()); if (v->value()!=1.0f) f.write_c("%s%s->value(%g);\n", f.indent(), var, v->value()); } {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) { Fl_Font g; int s; Fl_Color c; textstuff(0,g,s,c); if (g != ff) f.write_c("%s%s->textfont(%d);\n", f.indent(), var, g); if (s != fs) f.write_c("%s%s->textsize(%d);\n", f.indent(), var, s); if (c != fc) write_color(f, "textcolor", c); }} const char* ud = user_data(); if (class_name(1) && !parent->is_widget()) ud = "this"; if (callback()) { f.write_c("%s%s->callback((Fl_Callback*)%s", f.indent(), var, callback_name(f)); if (ud) f.write_c(", (void*)(%s));\n", ud); else f.write_c(");\n"); } else if (ud) { f.write_c("%s%s->user_data((void*)(%s));\n", f.indent(), var, ud); } if (o->align() != tplate->align() || subclass()) { int i = o->align(); f.write_c("%s%s->align(Fl_Align(%s", f.indent(), var, item_name(alignmenu, i & ~FL_ALIGN_INSIDE)); if (i & FL_ALIGN_INSIDE) f.write_c("|FL_ALIGN_INSIDE"); f.write_c("));\n"); } Fl_When ww = o->when(); if (ww != tplate->when() || subclass()) f.write_c("%s%s->when(%s);\n", f.indent(), var, when_symbol_name(ww)); if (!o->visible() && o->parent()) f.write_c("%s%s->hide();\n", f.indent(), var); if (!o->active()) f.write_c("%s%s->deactivate();\n", f.indent(), var); if (!is_a(ID_Group) && resizable()) f.write_c("%sFl_Group::current()->resizable(%s);\n", f.indent(), var); if (hotspot()) { if (is_class()) f.write_c("%shotspot(%s);\n", f.indent(), var); else if (is_a(ID_Window)) f.write_c("%s%s->hotspot(%s);\n", f.indent(), var, var); else f.write_c("%s%s->window()->hotspot(%s);\n", f.indent(), var, var); } } void Fl_Widget_Type::write_extra_code(Fd_Code_Writer& f) { for (int n=0; n < NUM_EXTRA_CODE; n++) if (extra_code(n) && !isdeclare(extra_code(n))) f.write_c("%s%s\n", f.indent(), extra_code(n)); } void Fl_Widget_Type::write_block_close(Fd_Code_Writer& f) { f.indentation--; f.write_c("%s} // %s* %s\n", f.indent(), subclassname(this), name() ? name() : "o"); } void Fl_Widget_Type::write_code2(Fd_Code_Writer& f) { write_extra_code(f); write_block_close(f); } //////////////////////////////////////////////////////////////// void Fl_Widget_Type::write_properties(Fd_Project_Writer &f) { Fl_Type::write_properties(f); f.write_indent(level+1); switch (public_) { case 0: f.write_string("private"); break; case 1: break; case 2: f.write_string("protected"); break; } if (tooltip() && *tooltip()) { f.write_string("tooltip"); f.write_word(tooltip()); } if (image_name() && *image_name()) { if (scale_image_w_ || scale_image_h_) f.write_string("scale_image {%d %d}", scale_image_w_, scale_image_h_); f.write_string("image"); f.write_word(image_name()); f.write_string("compress_image %d", compress_image_); } if (bind_image_) f.write_string("bind_image 1"); if (inactive_name() && *inactive_name()) { if (scale_deimage_w_ || scale_deimage_h_) f.write_string("scale_deimage {%d %d}", scale_deimage_w_, scale_deimage_h_); f.write_string("deimage"); f.write_word(inactive_name()); f.write_string("compress_deimage %d", compress_deimage_); } if (bind_deimage_) f.write_string("bind_deimage 1"); f.write_string("xywh {%d %d %d %d}", o->x(), o->y(), o->w(), o->h()); Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o; if (is_a(ID_Spinner) && ((Fl_Spinner*)o)->type() != ((Fl_Spinner*)tplate)->type()) { f.write_string("type"); f.write_word(item_name(subtypes(), ((Fl_Spinner*)o)->type())); } else if (subtypes() && (o->type() != tplate->type() || is_a(ID_Window))) { f.write_string("type"); f.write_word(item_name(subtypes(), o->type())); } if (o->box() != tplate->box()) { f.write_string("box"); f.write_word(boxname(o->box()));} if (is_a(ID_Input)) { Fl_Input_* b = (Fl_Input_*)o; if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); } if (is_a(ID_Value_Input)) { Fl_Value_Input* b = (Fl_Value_Input*)o; if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); } if (is_a(ID_Text_Display)) { Fl_Text_Display* b = (Fl_Text_Display*)o; if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); } if (is_a(ID_Button)) { Fl_Button* b = (Fl_Button*)o; if (b->down_box()) { f.write_string("down_box"); f.write_word(boxname(b->down_box()));} if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); if (b->value()) f.write_string("value 1"); } else if (is_a(ID_Input_Choice)) { Fl_Input_Choice* b = (Fl_Input_Choice*)o; if (b->down_box()) { f.write_string("down_box"); f.write_word(boxname(b->down_box()));} } else if (is_a(ID_Menu_)) { Fl_Menu_* b = (Fl_Menu_*)o; if (b->down_box()) { f.write_string("down_box"); f.write_word(boxname(b->down_box()));} } if (o->color()!=tplate->color()) f.write_string("color %d", o->color()); if (o->selection_color()!=tplate->selection_color()) f.write_string("selection_color %d", o->selection_color()); if (o->labeltype()!=tplate->labeltype()) { f.write_string("labeltype"); f.write_word(item_name(labeltypemenu, o->labeltype())); } if (o->labelfont()!=tplate->labelfont()) f.write_string("labelfont %d", o->labelfont()); if (o->labelsize()!=tplate->labelsize()) f.write_string("labelsize %d", o->labelsize()); if (o->labelcolor()!=tplate->labelcolor()) f.write_string("labelcolor %d", o->labelcolor()); if (o->align()!=tplate->align()) f.write_string("align %d", o->align()); if (o->horizontal_label_margin()!=tplate->horizontal_label_margin()) f.write_string("h_label_margin %d", o->horizontal_label_margin()); if (o->vertical_label_margin()!=tplate->vertical_label_margin()) f.write_string("v_label_margin %d", o->vertical_label_margin()); if (o->label_image_spacing()!=tplate->label_image_spacing()) f.write_string("image_spacing %d", o->label_image_spacing()); if (o->when() != tplate->when()) f.write_string("when %d", o->when()); if (is_a(ID_Valuator_)) { Fl_Valuator* v = (Fl_Valuator*)o; Fl_Valuator* t = (Fl_Valuator*)(tplate); if (v->minimum()!=t->minimum()) f.write_string("minimum %g",v->minimum()); if (v->maximum()!=t->maximum()) f.write_string("maximum %g",v->maximum()); if (v->step()!=t->step()) f.write_string("step %g",v->step()); if (v->value()!=0.0) f.write_string("value %g",v->value()); if (is_a(ID_Slider)) { double x = ((Fl_Slider*)v)->slider_size(); double y = ((Fl_Slider*)t)->slider_size(); if (x != y) f.write_string("slider_size %g", x); } } if (is_a(ID_Spinner)) { Fl_Spinner* v = (Fl_Spinner*)o; Fl_Spinner* t = (Fl_Spinner*)(tplate); if (v->minimum()!=t->minimum()) f.write_string("minimum %g",v->minimum()); if (v->maximum()!=t->maximum()) f.write_string("maximum %g",v->maximum()); if (v->step()!=t->step()) f.write_string("step %g",v->step()); if (v->value()!=1.0) f.write_string("value %g",v->value()); } {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) { Fl_Font ft; int s; Fl_Color c; textstuff(0,ft,s,c); if (ft != ff) f.write_string("textfont %d", ft); if (s != fs) f.write_string("textsize %d", s); if (c != fc) f.write_string("textcolor %d", c); }} if (!o->visible() && !override_visible_) f.write_string("hide"); if (!o->active()) f.write_string("deactivate"); if (resizable()) f.write_string("resizable"); if (hotspot()) f.write_string(is_a(ID_Menu_Item) ? "divider" : "hotspot"); for (int n=0; n < NUM_EXTRA_CODE; n++) if (extra_code(n)) { f.write_indent(level+1); f.write_string("code%d",n); f.write_word(extra_code(n)); } if (subclass()) { f.write_indent(level+1); f.write_string("class"); f.write_word(subclass()); } } void Fl_Widget_Type::read_property(Fd_Project_Reader &f, const char *c) { int x,y,w,h; Fl_Font ft; int s; Fl_Color cc; if (!strcmp(c,"private")) { public_ = 0; } else if (!strcmp(c,"protected")) { public_ = 2; } else if (!strcmp(c,"xywh")) { if (sscanf(f.read_word(),"%d %d %d %d",&x,&y,&w,&h) == 4) { x += pasteoffset; y += pasteoffset; // FIXME temporary change! if (f.read_version>=2.0 && o->parent() && o->parent()!=o->window()) { x += o->parent()->x(); y += o->parent()->y(); } o->resize(x,y,w,h); } } else if (!strcmp(c,"tooltip")) { tooltip(f.read_word()); } else if (!strcmp(c,"scale_image")) { if (sscanf(f.read_word(),"%d %d",&w,&h) == 2) { scale_image_w_ = w; scale_image_h_ = h; } } else if (!strcmp(c,"image")) { image_name(f.read_word()); // starting in 2023, `image` is always followed by `compress_image` // the code below is for compatibility with older .fl files const char *ext = fl_filename_ext(image_name_); if ( strcmp(ext, ".jpg") && strcmp(ext, ".png") && strcmp(ext, ".svg") && strcmp(ext, ".svgz")) compress_image_ = 0; // if it is neither of those, default to uncompressed } else if (!strcmp(c,"bind_image")) { bind_image_ = (int)atol(f.read_word()); } else if (!strcmp(c,"compress_image")) { compress_image_ = (int)atol(f.read_word()); } else if (!strcmp(c,"scale_deimage")) { if (sscanf(f.read_word(),"%d %d",&w,&h) == 2) { scale_deimage_w_ = w; scale_deimage_h_ = h; } } else if (!strcmp(c,"deimage")) { inactive_name(f.read_word()); // starting in 2023, `deimage` is always followed by `compress_deimage` // the code below is for compatibility with older .fl files const char *ext = fl_filename_ext(inactive_name_); if ( strcmp(ext, ".jpg") && strcmp(ext, ".png") && strcmp(ext, ".svg") && strcmp(ext, ".svgz")) compress_deimage_ = 0; // if it is neither of those, default to uncompressed } else if (!strcmp(c,"bind_deimage")) { bind_deimage_ = (int)atol(f.read_word()); } else if (!strcmp(c,"compress_deimage")) { compress_deimage_ = (int)atol(f.read_word()); } else if (!strcmp(c,"type")) { if (is_a(ID_Spinner)) ((Fl_Spinner*)o)->type(item_number(subtypes(), f.read_word())); else o->type(item_number(subtypes(), f.read_word())); } else if (!strcmp(c,"box")) { const char* value = f.read_word(); if ((x = boxnumber(value))) { if (x == ZERO_ENTRY) x = 0; o->box((Fl_Boxtype)x); } else if (sscanf(value,"%d",&x) == 1) o->box((Fl_Boxtype)x); } else if (is_a(ID_Button) && !strcmp(c,"down_box")) { const char* value = f.read_word(); if ((x = boxnumber(value))) { if (x == ZERO_ENTRY) x = 0; ((Fl_Button*)o)->down_box((Fl_Boxtype)x); } } else if (is_a(ID_Input_Choice) && !strcmp(c,"down_box")) { const char* value = f.read_word(); if ((x = boxnumber(value))) { if (x == ZERO_ENTRY) x = 0; ((Fl_Input_Choice*)o)->down_box((Fl_Boxtype)x); } } else if (is_a(ID_Menu_) && !strcmp(c,"down_box")) { const char* value = f.read_word(); if ((x = boxnumber(value))) { if (x == ZERO_ENTRY) x = 0; ((Fl_Menu_*)o)->down_box((Fl_Boxtype)x); } } else if (is_button() && !strcmp(c,"value")) { const char* value = f.read_word(); ((Fl_Button*)o)->value(atoi(value)); } else if (!strcmp(c,"color")) { const char *cw = f.read_word(); if (cw[0]=='0' && cw[1]=='x') { sscanf(cw,"0x%x",&x); o->color(x); } else { int n = sscanf(cw,"%d %d",&x,&y); if (n == 2) { // back compatibility... if (x != 47) o->color(x); o->selection_color(y); } else { o->color(x); } } } else if (!strcmp(c,"selection_color")) { if (sscanf(f.read_word(),"%d",&x)) o->selection_color(x); } else if (!strcmp(c,"labeltype")) { c = f.read_word(); if (!strcmp(c,"image")) { Fluid_Image *i = Fluid_Image::find(label()); if (!i) f.read_error("Image file '%s' not found", label()); else setimage(i); image_name(label()); label(""); } else { o->labeltype((Fl_Labeltype)item_number(labeltypemenu,c)); } } else if (!strcmp(c,"labelfont")) { if (sscanf(f.read_word(),"%d",&x) == 1) o->labelfont(x); } else if (!strcmp(c,"labelsize")) { if (sscanf(f.read_word(),"%d",&x) == 1) o->labelsize(x); } else if (!strcmp(c,"labelcolor")) { if (sscanf(f.read_word(),"%d",&x) == 1) o->labelcolor(x); } else if (!strcmp(c,"align")) { if (sscanf(f.read_word(),"%d",&x) == 1) o->align(x); } else if (!strcmp(c,"h_label_margin")) { if (sscanf(f.read_word(),"%d",&x) == 1) o->horizontal_label_margin(x); } else if (!strcmp(c,"v_label_margin")) { if (sscanf(f.read_word(),"%d",&x) == 1) o->vertical_label_margin(x); } else if (!strcmp(c,"image_spacing")) { if (sscanf(f.read_word(),"%d",&x) == 1) o->label_image_spacing(x); } else if (!strcmp(c,"when")) { if (sscanf(f.read_word(),"%d",&x) == 1) o->when(x); } else if (!strcmp(c,"minimum")) { if (is_a(ID_Valuator_)) ((Fl_Valuator*)o)->minimum(strtod(f.read_word(),0)); if (is_a(ID_Spinner)) ((Fl_Spinner*)o)->minimum(strtod(f.read_word(),0)); } else if (!strcmp(c,"maximum")) { if (is_a(ID_Valuator_)) ((Fl_Valuator*)o)->maximum(strtod(f.read_word(),0)); if (is_a(ID_Spinner)) ((Fl_Spinner*)o)->maximum(strtod(f.read_word(),0)); } else if (!strcmp(c,"step")) { if (is_a(ID_Valuator_)) ((Fl_Valuator*)o)->step(strtod(f.read_word(),0)); if (is_a(ID_Spinner)) ((Fl_Spinner*)o)->step(strtod(f.read_word(),0)); } else if (!strcmp(c,"value")) { if (is_a(ID_Valuator_)) ((Fl_Valuator*)o)->value(strtod(f.read_word(),0)); if (is_a(ID_Spinner)) ((Fl_Spinner*)o)->value(strtod(f.read_word(),0)); } else if ( (!strcmp(c,"slider_size") || !strcmp(c,"size")) && is_a(ID_Slider)) { ((Fl_Slider*)o)->slider_size(strtod(f.read_word(),0)); } else if (!strcmp(c,"textfont")) { if (sscanf(f.read_word(),"%d",&x) == 1) {ft=(Fl_Font)x; textstuff(1,ft,s,cc);} } else if (!strcmp(c,"textsize")) { if (sscanf(f.read_word(),"%d",&x) == 1) {s=x; textstuff(2,ft,s,cc);} } else if (!strcmp(c,"textcolor")) { if (sscanf(f.read_word(),"%d",&x) == 1) {cc=(Fl_Color)x;textstuff(3,ft,s,cc);} } else if (!strcmp(c,"hide")) { o->hide(); } else if (!strcmp(c,"deactivate")) { o->deactivate(); } else if (!strcmp(c,"resizable")) { resizable(1); } else if (!strcmp(c,"hotspot") || !strcmp(c, "divider")) { hotspot(1); } else if (!strcmp(c,"class")) { subclass(f.read_word()); } else if (!strcmp(c,"shortcut")) { int shortcut = (int)strtol(f.read_word(),0,0); if (is_button()) ((Fl_Button*)o)->shortcut(shortcut); else if (is_a(ID_Input)) ((Fl_Input_*)o)->shortcut(shortcut); else if (is_a(ID_Value_Input)) ((Fl_Value_Input*)o)->shortcut(shortcut); else if (is_a(ID_Text_Display)) ((Fl_Text_Display*)o)->shortcut(shortcut); } else { if (!strncmp(c,"code",4)) { int n = atoi(c+4); if (n >= 0 && n <= NUM_EXTRA_CODE) { extra_code(n,f.read_word()); return; } } else if (!strcmp(c,"extra_code")) { extra_code(0,f.read_word()); return; } Fl_Type::read_property(f, c); } } Fl_Menu_Item boxmenu1[] = { // these extra ones are for looking up fdesign saved strings: {"NO_FRAME", 0,0,(void *)FL_NO_BOX}, {"ROUNDED3D_UPBOX", 0,0,(void *)_FL_ROUND_UP_BOX}, {"ROUNDED3D_DOWNBOX", 0,0,(void *)_FL_ROUND_DOWN_BOX}, {"OVAL3D_UPBOX", 0,0,(void *)_FL_ROUND_UP_BOX}, {"OVAL3D_DOWNBOX", 0,0,(void *)_FL_ROUND_DOWN_BOX}, {"0", 0,0,(void *)ZERO_ENTRY}, {"1", 0,0,(void *)FL_UP_BOX}, {"2", 0,0,(void *)FL_DOWN_BOX}, {"3", 0,0,(void *)FL_FLAT_BOX}, {"4", 0,0,(void *)FL_BORDER_BOX}, {"5", 0,0,(void *)FL_SHADOW_BOX}, {"6", 0,0,(void *)FL_FRAME_BOX}, {"7", 0,0,(void *)FL_ROUNDED_BOX}, {"8", 0,0,(void *)FL_RFLAT_BOX}, {"9", 0,0,(void *)FL_RSHADOW_BOX}, {"10", 0,0,(void *)FL_UP_FRAME}, {"11", 0,0,(void *)FL_DOWN_FRAME}, {0}}; int lookup_symbol(const char *, int &, int numberok = 0); int Fl_Widget_Type::read_fdesign(const char* propname, const char* value) { int v; if (!strcmp(propname,"box")) { float x,y,w,h; if (sscanf(value,"%f %f %f %f",&x,&y,&w,&h) == 4) { if (fdesign_flip) { Fl_Type *p; for (p = parent; p && !p->is_a(ID_Window); p = p->parent) {/*empty*/} if (p && p->is_widget()) y = ((Fl_Widget_Type*)p)->o->h()-(y+h); } x += pasteoffset; y += pasteoffset; o->resize(int(x),int(y),int(w),int(h)); } } else if (!strcmp(propname,"label")) { label(value); } else if (!strcmp(propname,"name")) { this->name(value); } else if (!strcmp(propname,"callback")) { callback(value); user_data_type("long"); } else if (!strcmp(propname,"argument")) { user_data(value); } else if (!strcmp(propname,"shortcut")) { if (value[0]) { char buf[128]; sprintf(buf,"o->shortcut(\"%s\");",value); extra_code(0,buf); } } else if (!strcmp(propname,"style")) { if (!strncmp(value,"FL_NORMAL",9)) return 1; if (!lookup_symbol(value,v,1)) return 0; o->labelfont(v); o->labeltype((Fl_Labeltype)(v>>8)); } else if (!strcmp(propname,"size")) { if (!lookup_symbol(value,v,1)) return 0; o->labelsize(v); } else if (!strcmp(propname,"type")) { if (!strncmp(value,"NORMAL",6)) return 1; if (lookup_symbol(value,v,1)) {o->type(v); return 1;} if (!strcmp(value+strlen(value)-5,"FRAME")) goto TRY_BOXTYPE; if (!strcmp(value+strlen(value)-3,"BOX")) goto TRY_BOXTYPE; return 0; } else if (!strcmp(propname,"lcol")) { if (!lookup_symbol(value,v,1)) return 0; o->labelcolor(v); } else if (!strcmp(propname,"return")) { if (!lookup_symbol(value,v,0)) return 0; o->when(v|FL_WHEN_RELEASE); } else if (!strcmp(propname,"alignment")) { if (!lookup_symbol(value,v)) { // convert old numeric values: int v1 = atoi(value); if (v1 <= 0 && strcmp(value,"0")) return 0; v = 0; if (v1 >= 5) {v = FL_ALIGN_INSIDE; v1 -= 5;} switch (v1) { case 0: v += FL_ALIGN_TOP; break; case 1: v += FL_ALIGN_BOTTOM; break; case 2: v += FL_ALIGN_LEFT; break; case 3: v += FL_ALIGN_RIGHT; break; case 4: v += FL_ALIGN_CENTER; break; default: return 0; } } o->align(v); } else if (!strcmp(propname,"resizebox")) { resizable(1); } else if (!strcmp(propname,"colors")) { char* p = (char*)value; while (*p != ' ') {if (!*p) return 0; p++;} *p = 0; int v1; if (!lookup_symbol(value,v,1) || !lookup_symbol(p+1,v1,1)) { *p=' '; return 0;} o->color(v,v1); } else if (!strcmp(propname,"resize")) { return !strcmp(value,"FL_RESIZE_ALL"); } else if (!strcmp(propname,"gravity")) { return !strcmp(value,"FL_NoGravity FL_NoGravity"); } else if (!strcmp(propname,"boxtype")) { TRY_BOXTYPE: int x = boxnumber(value); if (!x) {x = item_number(boxmenu1, value); if (x < 0) return 0;} if (x == ZERO_ENTRY) { x = 0; if (o->box() != ((Fl_Widget_Type*)factory)->o->box()) return 1; // kludge for frame } o->box((Fl_Boxtype)x); } else { return 0; } return 1; } void leave_live_mode_cb(Fl_Widget*, void*) { live_mode_cb(0, 0); } Fl_Widget *Fl_Widget_Type::enter_live_mode(int) { live_widget = widget(o->x(), o->y(), o->w(), o->h()); if (live_widget) copy_properties(); return live_widget; } Fl_Widget* Fl_Widget_Type::propagate_live_mode(Fl_Group* grp) { live_widget = grp; copy_properties(); Fl_Type *n; for (n = next; n && n->level > level; n = n->next) { if (n->level == level+1) { Fl_Widget* proxy_child = n->enter_live_mode(); if (proxy_child && n->is_widget() && ((Fl_Widget_Type*)n)->resizable()) { grp->resizable(proxy_child); } } } grp->end(); live_widget = grp; copy_properties_for_children(); return live_widget; } void Fl_Widget_Type::leave_live_mode() { } /** copy all properties from the edit widget to the live widget */ void Fl_Widget_Type::copy_properties() { if (!live_widget) return; Fl_Font ff = 0; int fs = 0; Fl_Color fc = 0; textstuff(0, ff, fs, fc); // copy all attributes common to all widget types Fl_Widget *w = live_widget; w->label(o->label()); w->tooltip(tooltip()); w->type(o->type()); w->box(o->box()); w->color(o->color()); w->selection_color(o->selection_color()); w->labeltype(o->labeltype()); w->labelfont(o->labelfont()); w->labelsize(o->labelsize()); w->labelcolor(o->labelcolor()); w->align(o->align()); w->when(o->when()); // copy all attributes specific to widgets derived from Fl_Button if (is_button()) { Fl_Button* d = (Fl_Button*)live_widget, *s = (Fl_Button*)o; d->down_box(s->down_box()); d->shortcut(s->shortcut()); d->value(s->value()); } // copy all attributes specific to widgets derived from Fl_Input_ if (is_a(ID_Input)) { Fl_Input_* d = (Fl_Input_*)live_widget, *s = (Fl_Input_*)o; d->shortcut(s->shortcut()); d->textfont(ff); d->textsize(fs); d->textcolor(fc); } // copy all attributes specific to widgets derived from Fl_Value_Input if (is_a(ID_Value_Input)) { Fl_Value_Input* d = (Fl_Value_Input*)live_widget, *s = (Fl_Value_Input*)o; d->shortcut(s->shortcut()); d->textfont(ff); d->textsize(fs); d->textcolor(fc); } // copy all attributes specific to widgets derived from Fl_Text_Display if (is_a(ID_Text_Display)) { Fl_Text_Display* d = (Fl_Text_Display*)live_widget, *s = (Fl_Text_Display*)o; d->shortcut(s->shortcut()); d->textfont(ff); d->textsize(fs); d->textcolor(fc); } // copy all attributes specific to Fl_Valuator and derived classes if (is_a(ID_Valuator_)) { Fl_Valuator* d = (Fl_Valuator*)live_widget, *s = (Fl_Valuator*)o; d->minimum(s->minimum()); d->maximum(s->maximum()); d->step(s->step()); d->value(s->value()); if (is_a(ID_Slider)) { Fl_Slider *d = (Fl_Slider*)live_widget, *s = (Fl_Slider*)o; d->slider_size(s->slider_size()); } } // copy all attributes specific to Fl_Spinner and derived classes if (is_a(ID_Spinner)) { Fl_Spinner* d = (Fl_Spinner*)live_widget, *s = (Fl_Spinner*)o; d->minimum(s->minimum()); d->maximum(s->maximum()); d->step(s->step()); d->value(s->value()); } if (!o->visible()) w->hide(); if (!o->active()) w->deactivate(); } fltk-1.4.3/fluid/factory.cxx0000644000175000017500000016274315004135251016120 0ustar albrechtalbrecht// // Widget factory code for the Fast Light Tool Kit (FLTK). // // Type classes for most of the fltk widgets. Most of the work // is done by code in Fl_Widget_Type.cxx. Also a factory instance // of each of these type classes. // // This file also contains the "new" menu, which has a pointer // to a factory instance for every class (both the ones defined // here and ones in other files) // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "factory.h" #include "fluid.h" #include "Fl_Group_Type.h" #include "Fl_Grid_Type.h" #include "Fl_Menu_Type.h" #include "Fd_Snap_Action.h" #include "pixmaps.h" #include "undo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../src/flstring.h" #include #include // ---- Browser Types -------------------------------------------------- MARK: - // ---- Browser_Base ---- static Fl_Menu_Item browser_base_type_menu[] = { {"No Select", 0, 0, (void*)FL_NORMAL_BROWSER}, {"Select", 0, 0, (void*)FL_SELECT_BROWSER}, {"Hold", 0, 0, (void*)FL_HOLD_BROWSER}, {"Multi", 0, 0, (void*)FL_MULTI_BROWSER}, {0} }; /** \brief This is the base class for some browsers types. This class will not be instantiated. */ class Fl_Browser_Base_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE { return browser_base_type_menu; } int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Browser_ *myo = (Fl_Browser_*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); break; case 2: myo->textsize(s); break; case 3: myo->textcolor(c); break; } return 1; } public: void ideal_size(int &w, int &h) FL_OVERRIDE { w = 120; h = 160; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Browser_"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Browser_"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Browser* b = new Fl_Browser(x, y, w, h); return b; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Browser_Base_Type(); } ID id() const FL_OVERRIDE { return ID_Browser_; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Browser_) ? true : super::is_a(inID); } }; static Fl_Browser_Base_Type Fl_Browser_Base_type; // ---- Browser ---- /** \brief Handle a plain browser widget. Most of the work is already done in Fl_Browser_Base_Type. */ class Fl_Browser_Type : public Fl_Browser_Base_Type { typedef Fl_Browser_Base_Type super; public: const char *type_name() FL_OVERRIDE { return "Fl_Browser"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Browser"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Browser* b = new Fl_Browser(x, y, w, h); // Fl_Browser::add calls fl_height(), which requires the X display open. // Avoid this when compiling so it works w/o a display: if (!batch_mode) { char buffer[20]; for (int i = 1; i <= 20; i++) { sprintf(buffer,"Browser Line %d",i); b->add(buffer); } } return b; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Browser_Type(); } ID id() const FL_OVERRIDE { return ID_Browser; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Browser) ? true : super::is_a(inID); } }; static Fl_Browser_Type Fl_Browser_type; // ---- Check Browser ---- /** \brief Manage the Check Browser. The Fl_Check_Browser is derived form Fl_Browser_ (underline!), not Fl_Browser. */ class Fl_Check_Browser_Type : public Fl_Browser_Base_Type { typedef Fl_Browser_Base_Type super; public: const char *type_name() FL_OVERRIDE { return "Fl_Check_Browser"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::CheckBrowser"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Check_Browser* b = new Fl_Check_Browser(x, y, w, h); // Fl_Check_Browser::add calls fl_height(), which requires the X display open. // Avoid this when compiling so it works w/o a display: if (!batch_mode) { char buffer[20]; for (int i = 1; i <= 20; i++) { sprintf(buffer,"Browser Line %d",i); b->add(buffer); } } return b; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Check_Browser_Type(); } ID id() const FL_OVERRIDE { return ID_Check_Browser; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Check_Browser) ? true : super::is_a(inID); } }; static Fl_Check_Browser_Type Fl_Check_Browser_type; // ---- File Browser ---- /** \brief Manage the File Browser, not to be confused with the file dialog. As oppoesed to the Hold, Multi, and Select Browser, this is not a subclass, but its own implementation, based on Fl_Browser. */ class Fl_File_Browser_Type : public Fl_Browser_Type { typedef Fl_Browser_Type super; public: const char *type_name() FL_OVERRIDE { return "Fl_File_Browser"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::FileBrowser"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_File_Browser* b = new Fl_File_Browser(x, y, w, h); if (!batch_mode) b->load("."); return b; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_File_Browser_Type(); } ID id() const FL_OVERRIDE { return ID_File_Browser; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_File_Browser) ? true : super::is_a(inID); } }; static Fl_File_Browser_Type Fl_File_Browser_type; // ---- Tree Type ------------------------------------------------------ MARK: - /** \brief Handle the Tree widget. Fl_Tree is derived from Fl_Group, but FLUID does not support extended Fl_Tree functionality, so we derive the Type from Fl_Widget_Type. \note Updating item_labelfont etc. does not refresh any of the existing items in the tree, so I decided against implementig those via the labelfont UI. */ class Fl_Tree_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { w = 120; h = 160; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Tree"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::TreeBrowser"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Tree* b = new Fl_Tree(x, y, w, h); if (!batch_mode) { b->add("/A1/B1/C1"); b->add("/A1/B1/C2"); b->add("/A1/B2/C1"); b->add("/A1/B2/C2"); b->add("/A2/B1/C1"); b->add("/A2/B1/C2"); b->add("/A2/B2/C1"); b->add("/A2/B2/C2"); } return b; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Tree_Type(); } ID id() const FL_OVERRIDE { return ID_Tree; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Tree) ? true : super::is_a(inID); } }; static Fl_Tree_Type Fl_Tree_type; // ---- Help Viewer ---------------------------------------------------- MARK: - /** \brief Handle the Help View widget. Fl_Help_View is derived from Fl_Group, but supporting children is not useful, so we derive from Fl_Widget_Type. */ class Fl_Help_View_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Help_View *myo = (Fl_Help_View*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); break; case 2: myo->textsize(s); break; case 3: myo->textcolor(c); break; } return 1; } public: void ideal_size(int &w, int &h) FL_OVERRIDE { w = 160; h = 120; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Help_View"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::HelpView"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Help_View *myo = new Fl_Help_View(x, y, w, h); if (!batch_mode) { myo->value("

Fl_Help_View Widget

" "

This is a Fl_Help_View widget.

"); } return myo; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Help_View_Type(); } ID id() const FL_OVERRIDE { return ID_Help_View; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Help_View) ? true : super::is_a(inID); } }; static Fl_Help_View_Type Fl_Help_View_type; // ---- Valuators ------------------------------------------------------ MARK: - // ---- Valuator Base ---- /** \brief Just a base class for all valuators. */ class Fl_Valuator_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; public: const char *type_name() FL_OVERRIDE { return "Fl_Valuator"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Valuator"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Slider(x, y, w, h, "Valuator"); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Valuator_Type(); } ID id() const FL_OVERRIDE { return ID_Valuator_; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Valuator_) ? true : super::is_a(inID); } }; static Fl_Valuator_Type Fl_Valuator_type; // ---- Counter ---- static Fl_Menu_Item counter_type_menu[] = { { "Normal", 0, 0, (void*)FL_NORMAL_COUNTER }, { "Simple", 0, 0, (void*)FL_SIMPLE_COUNTER }, { 0 } }; /** \brief Manage the Counter widget. Strictly speaking, the ideal size should derive from the textsize not the labelsize. */ class Fl_Counter_Type : public Fl_Valuator_Type { typedef Fl_Valuator_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE { return counter_type_menu; } int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Counter *myo = (Fl_Counter*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); break; case 2: myo->textsize(s); break; case 3: myo->textcolor(c); break; } return 1; } public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->textsize_not_null() + 8; w = layout->textsize_not_null() * 4 + 4 * h; // make room for the arrows Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Counter"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Counter"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Counter(x, y, w, h, "counter:"); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Counter_Type(); } ID id() const FL_OVERRIDE { return ID_Counter; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Counter) ? true : super::is_a(inID); } }; static Fl_Counter_Type Fl_Counter_type; // ---- Adjuster ---- /** \brief Handle Adjuster widgets which are derived from valuators. */ class Fl_Adjuster_Type : public Fl_Valuator_Type { typedef Fl_Valuator_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->labelsize + 8; w = 3 * h; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Adjuster"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Adjuster"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Adjuster(x, y, w, h); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Adjuster_Type(); } ID id() const FL_OVERRIDE { return ID_Adjuster; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Adjuster) ? true : super::is_a(inID); } }; static Fl_Adjuster_Type Fl_Adjuster_type; // ---- Dial ---- static Fl_Menu_Item dial_type_menu[] = { { "Dot", 0, 0, (void*)0 }, { "Line", 0, 0, (void*)FL_LINE_DIAL }, { "Fill", 0, 0, (void*)FL_FILL_DIAL }, { 0 } }; /** \brief Manage dials. */ class Fl_Dial_Type : public Fl_Valuator_Type { typedef Fl_Valuator_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE { return dial_type_menu; } public: void ideal_size(int &w, int &h) FL_OVERRIDE { w = 60; h = 60; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Dial"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Dial"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Dial(x, y, w, h); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Dial_Type(); } ID id() const FL_OVERRIDE { return ID_Dial; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Dial) ? true : super::is_a(inID); } }; static Fl_Dial_Type Fl_Dial_type; // ---- Roller ---- static Fl_Menu_Item roller_type_menu[] = { { "Vertical", 0, 0, (void*)0 }, { "Horizontal", 0, 0, (void*)FL_HORIZONTAL }, { 0 } }; /** \brief Manage Roller widgets. They are vertical by default. */ class Fl_Roller_Type : public Fl_Valuator_Type { typedef Fl_Valuator_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE { return roller_type_menu; } public: void ideal_size(int &w, int &h) FL_OVERRIDE { w = layout->labelsize + 8; h = 4 * w; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Roller"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Roller"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Roller(x, y, w, h); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Roller_Type(); } ID id() const FL_OVERRIDE { return ID_Roller; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Roller) ? true : super::is_a(inID); } }; static Fl_Roller_Type Fl_Roller_type; // ---- Slider ---- static Fl_Menu_Item slider_type_menu[] = { { "Vertical", 0, 0, (void*)FL_VERT_SLIDER }, { "Horizontal", 0, 0, (void*)FL_HOR_SLIDER }, { "Vert Fill", 0, 0, (void*)FL_VERT_FILL_SLIDER }, { "Horz Fill", 0, 0, (void*)FL_HOR_FILL_SLIDER }, { "Vert Knob", 0, 0, (void*)FL_VERT_NICE_SLIDER }, { "Horz Knob", 0, 0, (void*)FL_HOR_NICE_SLIDER }, { 0 } }; /** \brief Manage Slider widgets. They are vertical by default. Fl_Value_Slider has its own type. */ class Fl_Slider_Type : public Fl_Valuator_Type { typedef Fl_Valuator_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE { return slider_type_menu; } public: void ideal_size(int &w, int &h) FL_OVERRIDE { w = layout->labelsize + 8; h = 4 * w; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Slider"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Slider"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Slider(x, y, w, h, "slider:"); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Slider_Type(); } ID id() const FL_OVERRIDE { return ID_Slider; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Slider) ? true : super::is_a(inID); } }; static Fl_Slider_Type Fl_Slider_type; // ---- Scrollbar ---- static Fl_Menu_Item scrollbar_type_menu[] = { { "Vertical", 0, 0, (void*)FL_VERT_SLIDER }, { "Horizontal", 0, 0, (void*)FL_HOR_SLIDER }, { 0 } }; /** \brief Manage Scrollbars which are derived from Sliders. */ class Fl_Scrollbar_Type : public Fl_Slider_Type { typedef Fl_Slider_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE { return scrollbar_type_menu; } public: const char *type_name() FL_OVERRIDE { return "Fl_Scrollbar"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Scrollbar"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Scrollbar(x, y, w, h); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Scrollbar_Type(); } ID id() const FL_OVERRIDE { return ID_Scrollbar; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Scrollbar) ? true : super::is_a(inID); } }; static Fl_Scrollbar_Type Fl_Scrollbar_type; // ---- Value Slider ---- /** \brief Manage Value Sliders and their text settings. */ class Fl_Value_Slider_Type : public Fl_Slider_Type { typedef Fl_Slider_Type super; int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Value_Slider *myo = (Fl_Value_Slider*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); break; case 2: myo->textsize(s); break; case 3: myo->textcolor(c); break; } return 1; } public: const char *type_name() FL_OVERRIDE { return "Fl_Value_Slider"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::ValueSlider"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Value_Slider(x, y, w, h, "slider:"); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Value_Slider_Type(); } ID id() const FL_OVERRIDE { return ID_Value_Slider; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Value_Slider) ? true : super::is_a(inID); } }; static Fl_Value_Slider_Type Fl_Value_Slider_type; // ---- Value Input ---- /** \brief Manage Value Inputs and their text settings. */ class Fl_Value_Input_Type : public Fl_Valuator_Type { typedef Fl_Valuator_Type super; int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Value_Input *myo = (Fl_Value_Input*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); break; case 2: myo->textsize(s); break; case 3: myo->textcolor(c); break; } return 1; } public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->textsize_not_null() + 8; w = layout->textsize_not_null() * 4 + 8; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Value_Input"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::ValueInput"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Value_Input *myo = new Fl_Value_Input(x, y, w, h, "value:"); return myo; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Value_Input_Type(); } ID id() const FL_OVERRIDE { return ID_Value_Input; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Value_Input) ? true : super::is_a(inID); } }; static Fl_Value_Input_Type Fl_Value_Input_type; // ---- Value Output ---- /** \brief Handle Value Output widgets, no shortcut with Value Input unfortunately. */ class Fl_Value_Output_Type : public Fl_Valuator_Type { typedef Fl_Valuator_Type super; int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Value_Output *myo = (Fl_Value_Output*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); break; case 2: myo->textsize(s); break; case 3: myo->textcolor(c); break; } return 1; } public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->textsize_not_null() + 8; w = layout->textsize_not_null() * 4 + 8; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Value_Output"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::ValueOutput"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Value_Output *myo = new Fl_Value_Output(x, y, w, h, "value:"); return myo; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Value_Output_Type(); } ID id() const FL_OVERRIDE { return ID_Value_Output; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Value_Output) ? true : super::is_a(inID); } }; static Fl_Value_Output_Type Fl_Value_Output_type; // ---- Input ---------------------------------------------------------- MARK: - // ---- Input ---- static Fl_Menu_Item input_type_menu[] = { { "Normal", 0, 0, (void*)FL_NORMAL_INPUT }, { "Multiline", 0, 0, (void*)FL_MULTILINE_INPUT }, { "Secret", 0, 0, (void*)FL_SECRET_INPUT }, { "Int", 0, 0, (void*)FL_INT_INPUT }, { "Float", 0, 0, (void*)FL_FLOAT_INPUT }, {0} }; /** \brief Manage simple text input widgets. The managed class is derived from Fl_Input_, but for simplicity, deriving from Fl_Widget_Type seems sufficient here. */ class Fl_Input_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE { return input_type_menu; } int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Input_ *myo = (Fl_Input_*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); break; case 2: myo->textsize(s); break; case 3: myo->textcolor(c); break; } return 1; } public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->textsize_not_null() + 8; w = layout->textsize_not_null() * 6 + 8; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Input"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Input"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Input *myo = new Fl_Input(x, y, w, h, "input:"); myo->value("Text Input"); return myo; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Input_Type(); } ID id() const FL_OVERRIDE { return ID_Input; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Input) ? true : super::is_a(inID); } void copy_properties() FL_OVERRIDE { Fl_Widget_Type::copy_properties(); Fl_Input_ *d = (Fl_Input_*)live_widget, *s = (Fl_Input_*)o; d->textfont(s->textfont()); d->textsize(s->textsize()); d->textcolor(s->textcolor()); d->shortcut(s->shortcut()); } }; static Fl_Input_Type Fl_Input_type; // ---- File Input ---- /** \brief Manage file name input widgets. */ class Fl_File_Input_Type : public Fl_Input_Type { typedef Fl_Input_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE { return NULL; } // Don't inherit. public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->textsize_not_null() + 8 + 10; // Directoy bar is additional 10 pixels high w = layout->textsize_not_null() * 10 + 8; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_File_Input"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::FileInput"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_File_Input *myo = new Fl_File_Input(x, y, w, h, "file:"); myo->value("/usr/include/FL/Fl.H"); return myo; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_File_Input_Type(); } ID id() const FL_OVERRIDE { return ID_File_Input; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_File_Input) ? true : super::is_a(inID); } }; static Fl_File_Input_Type Fl_File_Input_type; // ---- Output ---- static Fl_Menu_Item output_type_menu[] = { { "Normal", 0, 0, (void*)FL_NORMAL_OUTPUT }, { "Multiline", 0, 0, (void*)FL_MULTILINE_OUTPUT }, { 0 } }; /** \brief Manage Output widgets, derived from Input. */ class Fl_Output_Type : public Fl_Input_Type { typedef Fl_Input_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE { return output_type_menu; } public: const char *type_name() FL_OVERRIDE { return "Fl_Output"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Output"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Output *myo = new Fl_Output(x, y, w, h, "output:"); myo->value("Text Output"); return myo; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Output_Type(); } ID id() const FL_OVERRIDE { return ID_Output; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Output) ? true : super::is_a(inID); } }; static Fl_Output_Type Fl_Output_type; // ---- Text Editor ---------------------------------------------------- MARK: - // ---- Text Display ---- /** \brief Manage the Text Display as a base class. Fl_Text_Display is actually derived from Fl_Group, but for FLUID, deriving the type from Widget is better. */ class Fl_Text_Display_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Text_Display *myo = (Fl_Text_Display*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); break; case 2: myo->textsize(s); break; case 3: myo->textcolor(c); break; } return 1; } public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->textsize_not_null() * 4 + 8; w = layout->textsize_not_null() * 10 + 8; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Text_Display"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::TextDisplay"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Text_Display *myo = new Fl_Text_Display(x, y, w, h); if (!batch_mode) { Fl_Text_Buffer *b = new Fl_Text_Buffer(); b->text("Lorem ipsum dolor\nsit amet, consetetur\nsadipscing elitr"); myo->buffer(b); } return myo; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Text_Display_Type(); } ID id() const FL_OVERRIDE { return ID_Text_Display; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Text_Display) ? true : super::is_a(inID); } }; static Fl_Text_Display_Type Fl_Text_Display_type; // ---- Text Editor ---- /** \brief Manage Text Editors based on Text Display. */ class Fl_Text_Editor_Type : public Fl_Text_Display_Type { typedef Fl_Text_Display_Type super; public: const char *type_name() FL_OVERRIDE {return "Fl_Text_Editor";} const char *alt_type_name() FL_OVERRIDE {return "fltk::TextEditor";} Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Text_Editor *myo = new Fl_Text_Editor(x, y, w, h); if (!batch_mode) { Fl_Text_Buffer *b = new Fl_Text_Buffer(); b->text("Lorem ipsum dolor\nsit amet, consetetur\nsadipscing elitr"); myo->buffer(b); } return myo; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Text_Editor_Type(); } ID id() const FL_OVERRIDE { return ID_Text_Editor; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Text_Editor) ? true : super::is_a(inID); } }; static Fl_Text_Editor_Type Fl_Text_Editor_type; // ---- Terminal ---- /** Use this terminal instead of Fl_Terminal to capture resize actions. */ class Fl_Terminal_Proxy : public Fl_Terminal { public: Fl_Terminal_Proxy(int x, int y, int w, int h, const char *l=NULL) : Fl_Terminal(x, y, w, h, l) { } void print_sample_text() { clear_screen_home(false); append("> ls -als"); } void resize(int x, int y, int w, int h) FL_OVERRIDE { Fl_Terminal::resize(x, y, w, h); // After a resize, the top text vanishes, so make sure we redraw it. print_sample_text(); } }; /** Use this terminal in batch mode to avoid opening a DISPLAY connection. */ class Fl_Batchmode_Terminal : public Fl_Group { public: Fl_Font tfont_; int tsize_; Fl_Color tcolor_; Fl_Batchmode_Terminal(int x, int y, int w, int h, const char *l=NULL) : Fl_Group(x, y, w, h, l) { // set the defaults that Fl_Terminal would set box(FL_DOWN_BOX); color(FL_FOREGROUND_COLOR); selection_color(FL_BACKGROUND_COLOR); labeltype(FL_NORMAL_LABEL); labelfont(0); labelsize(14); labelcolor(FL_FOREGROUND_COLOR); tfont_ = 4; tcolor_ = 0xd0d0d000; tsize_ = 14; align(Fl_Align(FL_ALIGN_TOP)); when(FL_WHEN_RELEASE); end(); } }; /** \brief Manage a terminal widget. */ class Fl_Terminal_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; public: const char *type_name() FL_OVERRIDE { return "Fl_Terminal"; } // Older .fl files with Fl_Simple_Terminal will create a Fl_Terminal instead. const char *alt_type_name() FL_OVERRIDE { return "Fl_Simple_Terminal"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Widget *ret = NULL; if (batch_mode) { ret = new Fl_Batchmode_Terminal(x, y, w, h); } else { Fl_Terminal_Proxy *term = new Fl_Terminal_Proxy(x, y, w+100, h); ret = term; } return ret; } int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { if (batch_mode) { Fl_Batchmode_Terminal *myo = (Fl_Batchmode_Terminal*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: case 0: f = (Fl_Font)myo->tfont_; s = myo->tsize_; c = myo->tcolor_; break; case 1: myo->tfont_ = f; break; case 2: myo->tsize_ = s; break; case 3: myo->tcolor_ = c; break; } } else { Fl_Terminal_Proxy *myo = (Fl_Terminal_Proxy*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); myo->print_sample_text(); break; case 2: myo->textsize(s); myo->print_sample_text(); break; case 3: myo->textcolor(c); myo->print_sample_text(); break; } } return 1; } Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Terminal_Type();} ID id() const FL_OVERRIDE { return ID_Terminal; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Terminal) ? true : super::is_a(inID); } }; static Fl_Terminal_Type Fl_Terminal_type; // ---- Other ---------------------------------------------------------- MARK: - // ---- Box ---- /** \brief Manage box widgets. Ideal size is set to 100x100, snapped to layout. */ class Fl_Box_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { w = 100; h = 100; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Box"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Widget"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Box(x, y, w, h, "label"); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Box_Type(); } ID id() const FL_OVERRIDE { return ID_Box; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Box) ? true : super::is_a(inID); } }; static Fl_Box_Type Fl_Box_type; // ---- Clock ---- /** \brief Manage Clock widgets. Ideal size is set to 80x80 snapped to layout. */ class Fl_Clock_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { w = 80; h = 80; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Clock"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Clock"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Clock(x, y, w, h); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Clock_Type(); } ID id() const FL_OVERRIDE { return ID_Clock; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Clock) ? true : super::is_a(inID); } }; static Fl_Clock_Type Fl_Clock_type; // ---- Progress ---- /** \brief Manage a Progress widget. Ideal size is set to match the label font and label text width times 3. \note minimum, maximum, and value must be set via extra code fields. */ class Fl_Progress_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->labelsize + 8; w = layout->labelsize * 12; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Progress"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::ProgressBar"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { Fl_Progress *myo = new Fl_Progress(x, y, w, h, "label"); myo->value(50); return myo; } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Progress_Type(); } ID id() const FL_OVERRIDE { return ID_Progress; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Progress) ? true : super::is_a(inID); } }; static Fl_Progress_Type Fl_Progress_type; // ---- Spinner ---- static Fl_Menu_Item spinner_type_menu[] = { { "Integer", 0, 0, (void*)FL_INT_INPUT }, { "Float", 0, 0, (void*)FL_FLOAT_INPUT }, { 0 } }; /** \brief Manage Spinner widgets. \note Fl_Spinner is derived from Fl_Group, *not* Fl_Valuator as one may expect. For FLUID, this means some special handling and no Group support. */ class Fl_Spinner_Type : public Fl_Widget_Type { typedef Fl_Widget_Type super; Fl_Menu_Item *subtypes() FL_OVERRIDE { return spinner_type_menu; } int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { Fl_Spinner *myo = (Fl_Spinner*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); switch (w) { case 4: case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; case 1: myo->textfont(f); break; case 2: myo->textsize(s); break; case 3: myo->textcolor(c); break; } return 1; } public: void ideal_size(int &w, int &h) FL_OVERRIDE { h = layout->textsize_not_null() + 8; w = layout->textsize_not_null() * 4 + 8; Fd_Snap_Action::better_size(w, h); } const char *type_name() FL_OVERRIDE { return "Fl_Spinner"; } const char *alt_type_name() FL_OVERRIDE { return "fltk::Spinner"; } Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { return new Fl_Spinner(x, y, w, h, "spinner:"); } Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Spinner_Type(); } ID id() const FL_OVERRIDE { return ID_Spinner; } bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Spinner) ? true : super::is_a(inID); } }; static Fl_Spinner_Type Fl_Spinner_type; // ---- Type Factory --------------------------------------------------- MARK: - extern class Fl_Function_Type Fl_Function_type; extern class Fl_Code_Type Fl_Code_type; extern class Fl_CodeBlock_Type Fl_CodeBlock_type; extern class Fl_Data_Type Fl_Data_type; extern class Fl_Decl_Type Fl_Decl_type; extern class Fl_DeclBlock_Type Fl_DeclBlock_type; extern class Fl_Comment_Type Fl_Comment_type; extern class Fl_Class_Type Fl_Class_type; extern class Fl_Window_Type Fl_Window_type; extern class Fl_Widget_Class_Type Fl_Widget_Class_type; extern class Fl_Group_Type Fl_Group_type; extern class Fl_Pack_Type Fl_Pack_type; extern class Fl_Flex_Type Fl_Flex_type; extern class Fl_Grid_Type Fl_Grid_type; extern class Fl_Tabs_Type Fl_Tabs_type; extern class Fl_Scroll_Type Fl_Scroll_type; extern class Fl_Table_Type Fl_Table_type; extern class Fl_Tile_Type Fl_Tile_type; extern class Fl_Input_Choice_Type Fl_Input_Choice_type; extern class Fl_Choice_Type Fl_Choice_type; extern class Fl_Menu_Bar_Type Fl_Menu_Bar_type; extern class Fl_Menu_Button_Type Fl_Menu_Button_type; extern class Fl_Menu_Item_Type Fl_Menu_Item_type; extern class Fl_Checkbox_Menu_Item_Type Fl_Checkbox_Menu_Item_type; extern class Fl_Radio_Menu_Item_Type Fl_Radio_Menu_Item_type; extern class Fl_Submenu_Type Fl_Submenu_type; extern class Fl_Wizard_Type Fl_Wizard_type; extern class Fl_Button_Type Fl_Button_type; extern class Fl_Return_Button_Type Fl_Return_Button_type; extern class Fl_Light_Button_Type Fl_Light_Button_type; extern class Fl_Check_Button_Type Fl_Check_Button_type; extern class Fl_Repeat_Button_Type Fl_Repeat_Button_type; extern class Fl_Round_Button_Type Fl_Round_Button_type; extern void select(Fl_Type *,int); extern void select_only(Fl_Type *); /** List all known types. This is used to convert a type name into a pointer to the prototype. This list may contain types that are supported in .fl files, but not available in the *New* menu. \note Make sure that this array stays synchronized to `Fl_Menu_Item New_Menu[]` further down in this file. */ static Fl_Type *known_types[] = { // functions (Fl_Type*)&Fl_Function_type, (Fl_Type*)&Fl_Code_type, (Fl_Type*)&Fl_CodeBlock_type, (Fl_Type*)&Fl_Decl_type, (Fl_Type*)&Fl_DeclBlock_type, (Fl_Type*)&Fl_Class_type, (Fl_Type*)&Fl_Widget_Class_type, (Fl_Type*)&Fl_Comment_type, (Fl_Type*)&Fl_Data_type, // groups (Fl_Type*)&Fl_Window_type, (Fl_Type*)&Fl_Group_type, (Fl_Type*)&Fl_Pack_type, (Fl_Type*)&Fl_Flex_type, (Fl_Type*)&Fl_Tabs_type, (Fl_Type*)&Fl_Scroll_type, (Fl_Type*)&Fl_Tile_type, (Fl_Type*)&Fl_Wizard_type, (Fl_Type*)&Fl_Grid_type, // buttons (Fl_Type*)&Fl_Button_type, (Fl_Type*)&Fl_Return_Button_type, (Fl_Type*)&Fl_Light_Button_type, (Fl_Type*)&Fl_Check_Button_type, (Fl_Type*)&Fl_Repeat_Button_type, (Fl_Type*)&Fl_Round_Button_type, // valuators (Fl_Type*)&Fl_Slider_type, (Fl_Type*)&Fl_Scrollbar_type, (Fl_Type*)&Fl_Value_Slider_type, (Fl_Type*)&Fl_Adjuster_type, (Fl_Type*)&Fl_Counter_type, (Fl_Type*)&Fl_Spinner_type, (Fl_Type*)&Fl_Dial_type, (Fl_Type*)&Fl_Roller_type, (Fl_Type*)&Fl_Value_Input_type, (Fl_Type*)&Fl_Value_Output_type, // text (Fl_Type*)&Fl_Input_type, (Fl_Type*)&Fl_Output_type, (Fl_Type*)&Fl_Text_Editor_type, (Fl_Type*)&Fl_Text_Display_type, (Fl_Type*)&Fl_File_Input_type, (Fl_Type*)&Fl_Terminal_type, // menus (Fl_Type*)&Fl_Menu_Bar_type, (Fl_Type*)&Fl_Menu_Button_type, (Fl_Type*)&Fl_Choice_type, (Fl_Type*)&Fl_Input_Choice_type, (Fl_Type*)&Fl_Submenu_type, (Fl_Type*)&Fl_Menu_Item_type, (Fl_Type*)&Fl_Checkbox_Menu_Item_type, (Fl_Type*)&Fl_Radio_Menu_Item_type, // browsers (Fl_Type*)&Fl_Browser_type, (Fl_Type*)&Fl_Check_Browser_type, (Fl_Type*)&Fl_File_Browser_type, (Fl_Type*)&Fl_Tree_type, (Fl_Type*)&Fl_Help_View_type, (Fl_Type*)&Fl_Table_type, // misc (Fl_Type*)&Fl_Box_type, (Fl_Type*)&Fl_Clock_type, (Fl_Type*)&Fl_Progress_type, }; /** Create and add a new widget to the widget tree. Fluid will try to set a default position for widgets to the user's expectation. Using the context menu will put new widgets at the position of the mouse click. Pulldown menu and bin actions will generate widgets no too far from previously added widgets in the same group. Widgets can be added by dragging them from the widget bin to the desired location. By setting the strategy, widgets are added as the last child of a group (this is done when reading them from a file), or close to the current widget, which the user would expect in interactive mode. \param[in] inPrototype pointer to one of the FL_..._type prototype; note the lower case 't' in type. \param[in] strategy add after current or as last child \param[in] and_open if set to true, call open() on the widget after creating it \return the newly created type or NULL \see add_new_widget_from_file(const char*, int) add_new_widget_from_user(Fl_Type*, int) add_new_widget_from_user(const char*, int) */ Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy, bool and_open) { undo_checkpoint(); undo_suspend(); Fl_Type *t = ((Fl_Type*)inPrototype)->make(strategy); if (t) { if (t->is_widget() && !t->is_a(ID_Window)) { Fl_Widget_Type *wt = (Fl_Widget_Type *)t; bool changed = false; // Set font sizes... changed |= (wt->o->labelsize() != layout->labelsize); wt->o->labelsize(layout->labelsize); if (layout->labelfont >= 0) { changed |= (wt->o->labelfont() != layout->labelfont); wt->o->labelfont(layout->labelfont); } Fl_Font fc, f = layout->textfont; int sc, s = layout->textsize; Fl_Color cc, c; wt->textstuff(0, fc, sc, cc); if ((f >= 0) && (fc != f)) { changed = true; wt->textstuff(1, f, s, c); } if ((s > 0) && (sc != s)) { changed = true; wt->textstuff(2, f, s, c); } if (changed && t->is_a(ID_Menu_Item)) { Fl_Type * tt = t->parent; while (tt && !tt->is_a(ID_Menu_Manager_)) tt = tt->parent; if (tt) ((Fl_Menu_Manager_Type*)tt)->build_menu(); } } if (t->is_true_widget() && !t->is_a(ID_Window)) { // Resize and/or reposition new widget... Fl_Widget_Type *wt = (Fl_Widget_Type *)t; // The parent field is already set at this point, so we can use that // inside ideal_size(). int w = 0, h = 0; wt->ideal_size(w, h); if ((t->parent && t->parent->is_a(ID_Flex))) { if (Fl_Window_Type::popupx != 0x7FFFFFFF) ((Fl_Flex_Type*)t->parent)->insert_child_at(((Fl_Widget_Type*)t)->o, Fl_Window_Type::popupx, Fl_Window_Type::popupy); t->parent->layout_widget(); } else if ( wt->is_a(ID_Group) && wt->parent && wt->parent->is_a(ID_Tabs) //&& (Fl_Window_Type::popupx == 0x7FFFFFFF) && (layout->top_tabs_margin > 0)) { // If the widget is a group and the parent is tabs and the top tabs // margin is set (and the user is not requesting a specific position) // then prefit the group correctly to the Tabs container. Fl_Widget *po = ((Fl_Tabs_Type*)wt->parent)->o; wt->o->resize(po->x(), po->y() + layout->top_tabs_margin, po->w(), po->h() - layout->top_tabs_margin); } else if ( wt->is_a(ID_Menu_Bar) && wt->parent && wt->parent->is_a(ID_Window) && (wt->prev == wt->parent)) { // If this is the first child of a window, make the menu bar as wide as // the window and drop it at 0, 0. Otherwise just use the suggested size. w = wt->o->window()->w(); wt->o->resize(0, 0, w, h); } else { if (Fl_Window_Type::popupx != 0x7FFFFFFF) { // If this callback was called from the RMB popup menu in a window, // popupx and popupy will contain the mouse coordinates at RMB event. wt->o->resize(Fl_Window_Type::popupx, Fl_Window_Type::popupy, w, h); } else { // If popupx is invalid, use the default position and find a good // size for the widget. wt->o->size(w, h); } } if (t->parent && t->parent->is_a(ID_Grid)) { if (Fl_Window_Type::popupx != 0x7FFFFFFF) { ((Fl_Grid_Type*)t->parent)->insert_child_at(((Fl_Widget_Type*)t)->o, Fl_Window_Type::popupx, Fl_Window_Type::popupy); } else { ((Fl_Grid_Type*)t->parent)->insert_child_at_next_free_cell(((Fl_Widget_Type*)t)->o); } } } if (t->is_a(ID_Window)) { int x = 0, y = 0, w = 480, h = 320; Fl_Window_Type *wt = (Fl_Window_Type *)t; wt->ideal_size(w, h); if (main_window) { int sx, sy, sw, sh; Fl_Window *win = main_window; int screen = Fl::screen_num(win->x(), win->y()); Fl::screen_work_area(sx, sy, sw, sh, screen); x = sx + sw/2 - w/2; y = sy + sh/2 - h/2; } wt->o->resize(x, y, w, h); } // make the new widget visible select_only(t); set_modflag(1); if (and_open) t->open(); } else { undo_current --; undo_last --; } undo_resume(); return t; } /** Create and add a new widget to the widget tree. \param[in] inName find the right prototype by this name \param[in] strategy where to add the node \param[in] and_open if set to true, call open() on the widget after creating it \return the newly created type or NULL \see add_new_widget_from_file(const char*, int) add_new_widget_from_user(Fl_Type*, int) add_new_widget_from_user(const char*, int) */ Fl_Type *add_new_widget_from_user(const char *inName, Strategy strategy, bool and_open) { Fl_Type *prototype = typename_to_prototype(inName); if (prototype) return add_new_widget_from_user(prototype, strategy, and_open); else return NULL; } /** Callback for all non-widget menu items. */ static void cbf(Fl_Widget *, void *v) { Fl_Type *t = NULL; if (Fl_Type::current && Fl_Type::current->can_have_children()) t = ((Fl_Type*)v)->make(Strategy::AS_LAST_CHILD); else t = ((Fl_Type*)v)->make(Strategy::AFTER_CURRENT); select_only(t); } /** Callback for all widget menu items. \param[in] v cast to Fl_Type to get the prototype of the type that the user wants to create. */ static void cb(Fl_Widget *, void *v) { Fl_Type *t = NULL; if (Fl_Type::current && Fl_Type::current->can_have_children()) t = add_new_widget_from_user((Fl_Type*)v, Strategy::AS_LAST_CHILD); else t = add_new_widget_from_user((Fl_Type*)v, Strategy::AFTER_CURRENT); select_only(t); } /** \note Make sure that this menu stays synchronized to `Fl_Type *known_types[]` defined further up in this file. */ Fl_Menu_Item New_Menu[] = { {"Code",0,0,0,FL_SUBMENU}, {"Function/Method",0,cbf,(void*)&Fl_Function_type}, {"Code",0,cbf,(void*)&Fl_Code_type}, {"Code Block",0,cbf,(void*)&Fl_CodeBlock_type}, {"Declaration",0,cbf,(void*)&Fl_Decl_type}, {"Declaration Block",0,cbf,(void*)&Fl_DeclBlock_type}, {"Class",0,cbf,(void*)&Fl_Class_type}, {"Widget Class",0,cb,(void*)&Fl_Widget_Class_type}, {"Comment",0,cbf,(void*)&Fl_Comment_type}, {"Inlined Data",0,cbf,(void*)&Fl_Data_type}, {0}, {"Group",0,0,0,FL_SUBMENU}, {0,0,cb,(void*)&Fl_Window_type}, {0,0,cb,(void*)&Fl_Group_type}, {0,0,cb,(void*)&Fl_Pack_type}, {0,0,cb,(void*)&Fl_Flex_type}, {0,0,cb,(void*)&Fl_Tabs_type}, {0,0,cb,(void*)&Fl_Scroll_type}, {0,0,cb,(void*)&Fl_Tile_type}, {0,0,cb,(void*)&Fl_Wizard_type}, {0,0,cb,(void*)&Fl_Grid_type}, {0}, {"Buttons",0,0,0,FL_SUBMENU}, {0,0,cb,(void*)&Fl_Button_type}, {0,0,cb,(void*)&Fl_Return_Button_type}, {0,0,cb,(void*)&Fl_Light_Button_type}, {0,0,cb,(void*)&Fl_Check_Button_type}, {0,0,cb,(void*)&Fl_Repeat_Button_type}, {0,0,cb,(void*)&Fl_Round_Button_type}, {0}, {"Valuators",0,0,0,FL_SUBMENU}, {0,0,cb,(void*)&Fl_Slider_type}, {0,0,cb,(void*)&Fl_Scrollbar_type}, {0,0,cb,(void*)&Fl_Value_Slider_type}, {0,0,cb,(void*)&Fl_Adjuster_type}, {0,0,cb,(void*)&Fl_Counter_type}, {0,0,cb,(void*)&Fl_Spinner_type}, {0,0,cb,(void*)&Fl_Dial_type}, {0,0,cb,(void*)&Fl_Roller_type}, {0,0,cb,(void*)&Fl_Value_Input_type}, {0,0,cb,(void*)&Fl_Value_Output_type}, {0}, {"Text",0,0,0,FL_SUBMENU}, {0,0,cb,(void*)&Fl_Input_type}, {0,0,cb,(void*)&Fl_Output_type}, {0,0,cb,(void*)&Fl_Text_Editor_type}, {0,0,cb,(void*)&Fl_Text_Display_type}, {0,0,cb,(void*)&Fl_File_Input_type}, {0,0,cb,(void*)&Fl_Terminal_type}, {0}, {"Menus",0,0,0,FL_SUBMENU}, {0,0,cb,(void*)&Fl_Menu_Bar_type}, {0,0,cb,(void*)&Fl_Menu_Button_type}, {0,0,cb,(void*)&Fl_Choice_type}, {0,0,cb,(void*)&Fl_Input_Choice_type}, {0,0,cb, (void*)&Fl_Submenu_type}, {0,0,cb, (void*)&Fl_Menu_Item_type}, {"Checkbox Menu Item",0,cb, (void*)&Fl_Checkbox_Menu_Item_type}, {"Radio Menu Item",0,cb, (void*)&Fl_Radio_Menu_Item_type}, {0}, {"Browsers",0,0,0,FL_SUBMENU}, {0,0,cb,(void*)&Fl_Browser_type}, {0,0,cb,(void*)&Fl_Check_Browser_type}, {0,0,cb,(void*)&Fl_File_Browser_type}, {0,0,cb,(void*)&Fl_Tree_type}, {0,0,cb,(void*)&Fl_Help_View_type}, {0,0,cb,(void*)&Fl_Table_type}, {0}, {"Other",0,0,0,FL_SUBMENU}, {0,0,cb,(void*)&Fl_Box_type}, {0,0,cb,(void*)&Fl_Clock_type}, {0,0,cb,(void*)&Fl_Progress_type}, {0}, {0}}; #include /** Modify a menuitem to display an icon in front of the label. This is implemented using Fl_Multi_Label as the labeltype (FL_MULTI_LABEL). The icon may be null. If ic is null only the text is assigned to the label and Fl_Multi_Label is not used. \param[in] mi pointer to tme menu item that will be modified \param[in] ic icon for the menu, may be NULL \param[in] txt new label text, may *not* be NULL, will not be copied */ static void make_iconlabel(Fl_Menu_Item *mi, Fl_Image *ic, const char *txt) { if (ic) { char *t1 = new char[strlen(txt)+6]; strcpy(t1, " "); strcat(t1, txt); strcat(t1, "..."); Fl_Multi_Label *ml = new Fl_Multi_Label; ml->labela = (char*)ic; ml->labelb = t1; ml->typea = FL_IMAGE_LABEL; ml->typeb = FL_NORMAL_LABEL; ml->label(mi); } else { if (txt != mi->text) mi->label(txt); } } /** Create the labels and icons for the `New_Menu` array. Names and icons are taken from the referenced prototypes. */ void fill_in_New_Menu() { for (unsigned i = 0; i < sizeof(New_Menu)/sizeof(*New_Menu); i++) { Fl_Menu_Item *m = New_Menu+i; if (m->user_data()) { Fl_Type *t = (Fl_Type*)m->user_data(); if (m->text) { make_iconlabel( m, pixmap[t->id()], m->label() ); } else { const char *n = t->type_name(); if (!strncmp(n,"Fl_",3)) n += 3; if (!strncmp(n,"fltk::",6)) n += 6; make_iconlabel( m, pixmap[t->id()], n ); } } } } /** Find the correct prototype for a given type name. \param[in] inName a C string that must match type_name() or alt_type_name() of one of the known Fl_Type classes. \return the matching prototype or NULL */ Fl_Type *typename_to_prototype(const char *inName) { if (inName==NULL || *inName==0) return NULL; for (unsigned i = 0; i < sizeof(known_types)/sizeof(*known_types); i++) { Fl_Type *prototype = known_types[i]; if (fl_ascii_strcasecmp(inName, prototype->type_name())==0) return prototype; if (fl_ascii_strcasecmp(inName, prototype->alt_type_name())==0) return prototype; } return NULL; } /** Create and add a new type node to the widget tree. This is used by the .fl file reader. New types are always created as the last child of the first compatible parent. New widgets have a default setup. Their position, size and label will be read next in the file. \param[in] inName a C string that described the type we want \param[in] strategy add after current or as last child \return the type node that was created or NULL \see add_new_widget_from_file(const char*, int) add_new_widget_from_user(Fl_Type*, int) add_new_widget_from_user(const char*, int) */ Fl_Type *add_new_widget_from_file(const char *inName, Strategy strategy) { Fl_Type *prototype = typename_to_prototype(inName); if (!prototype) return NULL; Fl_Type *new_node = prototype->make(strategy); return new_node; } //////////////////////////////////////////////////////////////// // Since I have included all the .H files, do this table here: // This table is only used to read fdesign files: struct symbol {const char *name; int value;}; /** Table with all symbols known by the "fdesign" format reader. This table does not need to be sorted alphabetically. */ static symbol table[] = { {"BLACK", FL_BLACK}, {"RED", FL_RED}, {"GREEN", FL_GREEN}, {"YELLOW", FL_YELLOW}, {"BLUE", FL_BLUE}, {"MAGENTA", FL_MAGENTA}, {"CYAN", FL_CYAN}, {"WHITE", FL_WHITE}, {"LCOL", FL_BLACK}, {"COL1", FL_GRAY}, {"MCOL", FL_LIGHT1}, {"LEFT_BCOL", FL_LIGHT3}, {"TOP_BCOL", FL_LIGHT2}, {"BOTTOM_BCOL", FL_DARK2}, {"RIGHT_BCOL", FL_DARK3}, {"INACTIVE", FL_INACTIVE_COLOR}, {"INACTIVE_COL", FL_INACTIVE_COLOR}, {"FREE_COL1", FL_FREE_COLOR}, {"FREE_COL2", FL_FREE_COLOR+1}, {"FREE_COL3", FL_FREE_COLOR+2}, {"FREE_COL4", FL_FREE_COLOR+3}, {"FREE_COL5", FL_FREE_COLOR+4}, {"FREE_COL6", FL_FREE_COLOR+5}, {"FREE_COL7", FL_FREE_COLOR+6}, {"FREE_COL8", FL_FREE_COLOR+7}, {"FREE_COL9", FL_FREE_COLOR+8}, {"FREE_COL10", FL_FREE_COLOR+9}, {"FREE_COL11", FL_FREE_COLOR+10}, {"FREE_COL12", FL_FREE_COLOR+11}, {"FREE_COL13", FL_FREE_COLOR+12}, {"FREE_COL14", FL_FREE_COLOR+13}, {"FREE_COL15", FL_FREE_COLOR+14}, {"FREE_COL16", FL_FREE_COLOR+15}, {"TOMATO", 131}, {"INDIANRED", 164}, {"SLATEBLUE", 195}, {"DARKGOLD", 84}, {"PALEGREEN", 157}, {"ORCHID", 203}, {"DARKCYAN", 189}, {"DARKTOMATO", 113}, {"WHEAT", 174}, {"ALIGN_CENTER", FL_ALIGN_CENTER}, {"ALIGN_TOP", FL_ALIGN_TOP}, {"ALIGN_BOTTOM", FL_ALIGN_BOTTOM}, {"ALIGN_LEFT", FL_ALIGN_LEFT}, {"ALIGN_RIGHT", FL_ALIGN_RIGHT}, {"ALIGN_INSIDE", FL_ALIGN_INSIDE}, {"ALIGN_TOP_LEFT", FL_ALIGN_TOP | FL_ALIGN_LEFT}, {"ALIGN_TOP_RIGHT", FL_ALIGN_TOP | FL_ALIGN_RIGHT}, {"ALIGN_BOTTOM_LEFT", FL_ALIGN_BOTTOM | FL_ALIGN_LEFT}, {"ALIGN_BOTTOM_RIGHT", FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT}, {"ALIGN_CENTER|FL_ALIGN_INSIDE", FL_ALIGN_CENTER|FL_ALIGN_INSIDE}, {"ALIGN_TOP|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_INSIDE}, {"ALIGN_BOTTOM|FL_ALIGN_INSIDE", FL_ALIGN_BOTTOM|FL_ALIGN_INSIDE}, {"ALIGN_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_LEFT|FL_ALIGN_INSIDE}, {"ALIGN_RIGHT|FL_ALIGN_INSIDE", FL_ALIGN_RIGHT|FL_ALIGN_INSIDE}, {"ALIGN_INSIDE|FL_ALIGN_INSIDE", FL_ALIGN_INSIDE|FL_ALIGN_INSIDE}, {"ALIGN_TOP_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE}, {"ALIGN_TOP_RIGHT|FL_ALIGN_INSIDE", FL_ALIGN_TOP|FL_ALIGN_RIGHT|FL_ALIGN_INSIDE}, {"ALIGN_BOTTOM_LEFT|FL_ALIGN_INSIDE", FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_INSIDE}, {"ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE",FL_ALIGN_BOTTOM|FL_ALIGN_RIGHT|FL_ALIGN_INSIDE}, {"ALIGN_LEFT_TOP", FL_ALIGN_TOP | FL_ALIGN_LEFT}, {"ALIGN_RIGHT_TOP", FL_ALIGN_TOP | FL_ALIGN_RIGHT}, {"ALIGN_LEFT_BOTTOM", FL_ALIGN_BOTTOM | FL_ALIGN_LEFT}, {"ALIGN_RIGHT_BOTTOM", FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT}, {"INVALID_STYLE", 255}, {"NORMAL_STYLE", FL_HELVETICA}, {"BOLD_STYLE", FL_HELVETICA|FL_BOLD}, {"ITALIC_STYLE", FL_HELVETICA|FL_ITALIC}, {"BOLDITALIC_STYLE", FL_HELVETICA|FL_BOLD|FL_ITALIC}, {"FIXED_STYLE", FL_COURIER}, {"FIXEDBOLD_STYLE", FL_COURIER|FL_BOLD}, {"FIXEDITALIC_STYLE", FL_COURIER|FL_ITALIC}, {"FIXEDBOLDITALIC_STYLE", FL_COURIER|FL_BOLD|FL_ITALIC}, {"TIMES_STYLE", FL_TIMES}, {"TIMESBOLD_STYLE", FL_TIMES|FL_BOLD}, {"TIMESITALIC_STYLE", FL_TIMES|FL_ITALIC}, {"TIMESBOLDITALIC_STYLE", FL_TIMES|FL_BOLD|FL_ITALIC}, {"SHADOW_STYLE", (_FL_SHADOW_LABEL<<8)}, {"ENGRAVED_STYLE", (_FL_ENGRAVED_LABEL<<8)}, {"EMBOSSED_STYLE", (_FL_EMBOSSED_LABEL<<0)}, {"TINY_SIZE", 8}, {"SMALL_SIZE", 11}, {"NORMAL_SIZE", FL_NORMAL_SIZE}, {"MEDIUM_SIZE", 18}, {"LARGE_SIZE", 24}, {"HUGE_SIZE", 32}, {"DEFAULT_SIZE", FL_NORMAL_SIZE}, {"TINY_FONT", 8}, {"SMALL_FONT", 11}, {"NORMAL_FONT", FL_NORMAL_SIZE}, {"MEDIUM_FONT", 18}, {"LARGE_FONT", 24}, {"HUGE_FONT", 32}, {"NORMAL_FONT1", 11}, {"NORMAL_FONT2", FL_NORMAL_SIZE}, {"DEFAULT_FONT", 11}, {"RETURN_END_CHANGED", 0}, {"RETURN_CHANGED", 1}, {"RETURN_END", 2}, {"RETURN_ALWAYS", 3}, {"PUSH_BUTTON", FL_TOGGLE_BUTTON}, {"RADIO_BUTTON", FL_RADIO_BUTTON}, {"HIDDEN_BUTTON", FL_HIDDEN_BUTTON}, {"SELECT_BROWSER", FL_SELECT_BROWSER}, {"HOLD_BROWSER", FL_HOLD_BROWSER}, {"MULTI_BROWSER", FL_MULTI_BROWSER}, {"SIMPLE_COUNTER", FL_SIMPLE_COUNTER}, {"LINE_DIAL", FL_LINE_DIAL}, {"FILL_DIAL", FL_FILL_DIAL}, {"VERT_SLIDER", FL_VERT_SLIDER}, {"HOR_SLIDER", FL_HOR_SLIDER}, {"VERT_FILL_SLIDER", FL_VERT_FILL_SLIDER}, {"HOR_FILL_SLIDER", FL_HOR_FILL_SLIDER}, {"VERT_NICE_SLIDER", FL_VERT_NICE_SLIDER}, {"HOR_NICE_SLIDER", FL_HOR_NICE_SLIDER}, }; /** \brief Find a symbol in an array of name/value pairs and return the value. If numberok is 0, and the symbol was not found, v remains unchanged and the function returns 0. If numberok is set and no label matched, the symbol is interpreted as a string containing an integer. If the string is not an integer, v is set to 0 and the function returns 0. If the symbol is found, or the integer could be read, v is set to the value, and the function returns 1. \param[in] name find a symbol by this name, a leading "FL_" is ignored \param[out] v value associated to the symbol, or the integer value \param[in] numberok if set, the symbol can also be a text representing an integer number \return 0 if the symbol was not found and the integer was not valid \return 1 otherwise and set v */ int lookup_symbol(const char *name, int &v, int numberok) { if ((name[0]=='F') && (name[1]=='L') && (name[2]=='_')) name += 3; for (int i=0; i < int(sizeof(table)/sizeof(*table)); i++) { if (!fl_ascii_strcasecmp(name,table[i].name)) { v = table[i].value; return 1; } } if (numberok && ((v = atoi(name)) || !strcmp(name,"0"))) return 1; return 0; } fltk-1.4.3/fluid/widget_panel.cxx0000644000175000017500000030747415004135251017115 0ustar albrechtalbrecht// // Widget panel for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #include "widget_panel.h" #include "undo.h" #include "Fl_Widget_Type.h" #include "Fl_Grid_Type.h" #include extern void set_modflag(int mf, int mfc=-1); Fl_Double_Window *image_panel_window=(Fl_Double_Window *)0; static void cb_image_panel_window(Fl_Double_Window* o, void* v) { propagate_load(o, v); } Fl_Group *image_panel_imagegroup=(Fl_Group *)0; Fl_Box *image_panel_data=(Fl_Box *)0; static void cb_image_panel_data(Fl_Box* o, void* v) { if (v == LOAD) { Fl_Shared_Image *img = Fl_Shared_Image::get(widget_image_input->value()); o->user_data(img); if (img) { char buf[256]; snprintf(buf, 255, "%d x %d pixels, %d channels", img->data_w(), img->data_h(), img->d()); o->copy_label(buf); image_panel_imagegroup->activate(); } else if (widget_image_input->value() && widget_image_input->value()[0]) { o->label("Can't load image"); image_panel_imagegroup->activate(); } else { o->label("... x ... pixels, ..."); image_panel_imagegroup->deactivate(); } } } Fluid_Coord_Input *image_panel_imagew=(Fluid_Coord_Input *)0; static void cb_image_panel_imagew(Fluid_Coord_Input* o, void* v) { if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { o->value(current_widget->scale_image_w_); } } else { int mod = 0; for (Fl_Type *t = Fl_Type::first; t; t = t->next) { if (t->selected && t->is_widget()) { Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); wt->scale_image_w_ = o->value(); Fl_Image *img = wt->o->image(); if (img) { int iw = wt->scale_image_w_; if (iw<=0) iw = img->data_w(); int ih = wt->scale_image_h_; if (ih<=0) ih = img->data_w(); img->scale(iw, ih, 0, 1); wt->o->redraw(); if (wt->o->parent()) wt->o->parent()->redraw(); } mod = 1; } } if (mod) set_modflag(1); } } Fluid_Coord_Input *image_panel_imageh=(Fluid_Coord_Input *)0; static void cb_image_panel_imageh(Fluid_Coord_Input* o, void* v) { if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { o->value(current_widget->scale_image_h_); } } else { int mod = 0; for (Fl_Type *t = Fl_Type::first; t; t = t->next) { if (t->selected && t->is_widget()) { Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); wt->scale_image_h_ = o->value(); Fl_Image *img = wt->o->image(); if (img) { int iw = wt->scale_image_w_; if (iw<=0) iw = img->data_w(); int ih = wt->scale_image_h_; if (ih<=0) ih = img->data_w(); img->scale(iw, ih, 0, 1); wt->o->redraw(); if (wt->o->parent()) wt->o->parent()->redraw(); } mod = 1; } } if (mod) set_modflag(1); } } static void cb_Reset(Fl_Button*, void* v) { if (v != LOAD) { image_panel_imagew->value(0); image_panel_imageh->value(0); image_panel_imagew->do_callback(); image_panel_imageh->do_callback(); } } Fl_Group *image_panel_deimagegroup=(Fl_Group *)0; Fl_Box *image_panel_dedata=(Fl_Box *)0; static void cb_image_panel_dedata(Fl_Box* o, void* v) { if (v == LOAD) { Fl_Shared_Image *img = Fl_Shared_Image::get(widget_deimage_input->value()); o->user_data(img); if (img) { char buf[256]; snprintf(buf, 255, "%d x %d pixels, %d channels", img->data_w(), img->data_h(), img->d()); o->copy_label(buf); image_panel_deimagegroup->activate(); } else if (widget_deimage_input->value() && widget_deimage_input->value()[0]) { o->label("Can't load image"); image_panel_deimagegroup->activate(); } else { o->label("... x ... pixels, ..."); image_panel_deimagegroup->deactivate(); } } } Fluid_Coord_Input *image_panel_deimagew=(Fluid_Coord_Input *)0; static void cb_image_panel_deimagew(Fluid_Coord_Input* o, void* v) { if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { o->value(current_widget->scale_deimage_w_); } } else { int mod = 0; for (Fl_Type *t = Fl_Type::first; t; t = t->next) { if (t->selected && t->is_widget()) { Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); wt->scale_deimage_w_ = o->value(); Fl_Image *img = wt->o->deimage(); if (img) { int iw = wt->scale_deimage_w_; if (iw<=0) iw = img->data_w(); int ih = wt->scale_deimage_h_; if (ih<=0) ih = img->data_w(); img->scale(iw, ih, 0, 1); wt->o->redraw(); if (wt->o->parent()) wt->o->parent()->redraw(); } mod = 1; } } if (mod) set_modflag(1); } } Fluid_Coord_Input *image_panel_deimageh=(Fluid_Coord_Input *)0; static void cb_image_panel_deimageh(Fluid_Coord_Input* o, void* v) { if (v == LOAD) { if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { o->value(current_widget->scale_deimage_h_); } } else { int mod = 0; for (Fl_Type *t = Fl_Type::first; t; t = t->next) { if (t->selected && t->is_widget()) { Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); wt->scale_deimage_h_ = o->value(); Fl_Image *img = wt->o->deimage(); if (img) { int iw = wt->scale_deimage_w_; if (iw<=0) iw = img->data_w(); int ih = wt->scale_deimage_h_; if (ih<=0) ih = img->data_w(); img->scale(iw, ih, 0, 1); wt->o->redraw(); if (wt->o->parent()) wt->o->parent()->redraw(); } mod = 1; } } if (mod) set_modflag(1); } } static void cb_Reset1(Fl_Button*, void* v) { if (v != LOAD) { image_panel_deimagew->value(0); image_panel_deimageh->value(0); image_panel_deimagew->do_callback(); image_panel_deimageh->do_callback(); } } Fl_Button *image_panel_close=(Fl_Button *)0; static void cb_image_panel_close(Fl_Button*, void* v) { if (v != LOAD) image_panel_window->hide(); } /** Create a panel for editing widget image data */ Fl_Double_Window* make_image_panel() { { image_panel_window = new Fl_Double_Window(260, 332, "Image Options"); image_panel_window->callback((Fl_Callback*)cb_image_panel_window); { image_panel_imagegroup = new Fl_Group(10, 15, 235, 125); image_panel_imagegroup->callback((Fl_Callback*)propagate_load); { Fl_Box* o = new Fl_Box(75, 15, 170, 20, " ---- Active Image ----"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); } // Fl_Box* o { image_panel_data = new Fl_Box(75, 35, 170, 20, "... x ... pixels, ..."); image_panel_data->labelsize(11); image_panel_data->callback((Fl_Callback*)cb_image_panel_data); image_panel_data->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); } // Fl_Box* image_panel_data { Fl_Group* o = new Fl_Group(75, 75, 170, 20); o->callback((Fl_Callback*)propagate_load); { image_panel_imagew = new Fluid_Coord_Input(75, 75, 55, 20, "Width:"); image_panel_imagew->tooltip("Scale image to this width in pixel units"); image_panel_imagew->box(FL_DOWN_BOX); image_panel_imagew->color(FL_BACKGROUND2_COLOR); image_panel_imagew->selection_color(FL_SELECTION_COLOR); image_panel_imagew->labeltype(FL_NORMAL_LABEL); image_panel_imagew->labelfont(0); image_panel_imagew->labelsize(11); image_panel_imagew->labelcolor(FL_FOREGROUND_COLOR); image_panel_imagew->textsize(11); image_panel_imagew->callback((Fl_Callback*)cb_image_panel_imagew); image_panel_imagew->align(Fl_Align(FL_ALIGN_TOP_LEFT)); image_panel_imagew->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* image_panel_imagew { image_panel_imageh = new Fluid_Coord_Input(135, 75, 55, 20, "Height:"); image_panel_imageh->tooltip("Scale image to this height in pixel units"); image_panel_imageh->box(FL_DOWN_BOX); image_panel_imageh->color(FL_BACKGROUND2_COLOR); image_panel_imageh->selection_color(FL_SELECTION_COLOR); image_panel_imageh->labeltype(FL_NORMAL_LABEL); image_panel_imageh->labelfont(0); image_panel_imageh->labelsize(11); image_panel_imageh->labelcolor(FL_FOREGROUND_COLOR); image_panel_imageh->textsize(11); image_panel_imageh->callback((Fl_Callback*)cb_image_panel_imageh); image_panel_imageh->align(Fl_Align(FL_ALIGN_TOP_LEFT)); image_panel_imageh->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* image_panel_imageh { Fl_Button* o = new Fl_Button(195, 75, 50, 20, "Reset"); o->tooltip("Reset scale to original size"); o->labelsize(11); o->callback((Fl_Callback*)cb_Reset); } // Fl_Button* o o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(10, 75, 60, 20, "Scale:"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(10, 100, 60, 20, "Storage:"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Check_Button* o = new Fl_Check_Button(75, 100, 170, 20, "convert to raw pixel data"); o->tooltip("if unchecked, keep the image in its original format and store the data as is;" " if checked, convert the image and store it as uncompressed RGB or grayscale p" "ixel data"); o->down_box(FL_DOWN_BOX); o->labelsize(11); o->callback((Fl_Callback*)compress_image_cb); } // Fl_Check_Button* o { Fl_Check_Button* o = new Fl_Check_Button(75, 120, 170, 20, "bind to widget"); o->tooltip("bind the image to the widget, so it will be deleted automatically"); o->down_box(FL_DOWN_BOX); o->labelsize(11); o->callback((Fl_Callback*)bind_image_cb); o->window()->hotspot(o); } // Fl_Check_Button* o image_panel_imagegroup->end(); } // Fl_Group* image_panel_imagegroup { image_panel_deimagegroup = new Fl_Group(10, 155, 235, 125); image_panel_deimagegroup->callback((Fl_Callback*)propagate_load); { Fl_Box* o = new Fl_Box(75, 155, 170, 20, " ---- Inactive Image ----"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); } // Fl_Box* o { image_panel_dedata = new Fl_Box(75, 175, 170, 20, "... x ... pixels, ..."); image_panel_dedata->labelsize(11); image_panel_dedata->callback((Fl_Callback*)cb_image_panel_dedata); image_panel_dedata->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); } // Fl_Box* image_panel_dedata { Fl_Group* o = new Fl_Group(75, 215, 170, 20); o->callback((Fl_Callback*)propagate_load); { image_panel_deimagew = new Fluid_Coord_Input(75, 215, 55, 20, "Width:"); image_panel_deimagew->tooltip("Scale image to this width in pixel units"); image_panel_deimagew->box(FL_DOWN_BOX); image_panel_deimagew->color(FL_BACKGROUND2_COLOR); image_panel_deimagew->selection_color(FL_SELECTION_COLOR); image_panel_deimagew->labeltype(FL_NORMAL_LABEL); image_panel_deimagew->labelfont(0); image_panel_deimagew->labelsize(11); image_panel_deimagew->labelcolor(FL_FOREGROUND_COLOR); image_panel_deimagew->textsize(11); image_panel_deimagew->callback((Fl_Callback*)cb_image_panel_deimagew); image_panel_deimagew->align(Fl_Align(FL_ALIGN_TOP_LEFT)); image_panel_deimagew->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* image_panel_deimagew { image_panel_deimageh = new Fluid_Coord_Input(135, 215, 55, 20, "Height:"); image_panel_deimageh->tooltip("Scale image to this height in pixel units"); image_panel_deimageh->box(FL_DOWN_BOX); image_panel_deimageh->color(FL_BACKGROUND2_COLOR); image_panel_deimageh->selection_color(FL_SELECTION_COLOR); image_panel_deimageh->labeltype(FL_NORMAL_LABEL); image_panel_deimageh->labelfont(0); image_panel_deimageh->labelsize(11); image_panel_deimageh->labelcolor(FL_FOREGROUND_COLOR); image_panel_deimageh->textsize(11); image_panel_deimageh->callback((Fl_Callback*)cb_image_panel_deimageh); image_panel_deimageh->align(Fl_Align(FL_ALIGN_TOP_LEFT)); image_panel_deimageh->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* image_panel_deimageh { Fl_Button* o = new Fl_Button(195, 215, 50, 20, "Reset"); o->tooltip("Reset scale to original size"); o->labelsize(11); o->callback((Fl_Callback*)cb_Reset1); } // Fl_Button* o o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(10, 215, 60, 20, "Scale:"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(10, 240, 60, 20, "Storage:"); o->labelfont(1); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Check_Button* o = new Fl_Check_Button(75, 240, 170, 20, "convert to raw pixel data"); o->tooltip("if unchecked, keep the image in its original format and store the data as is;" " if checked, convert the image and store it as uncompressed RGB or grayscale p" "ixel data"); o->down_box(FL_DOWN_BOX); o->labelsize(11); o->callback((Fl_Callback*)compress_deimage_cb); } // Fl_Check_Button* o { Fl_Check_Button* o = new Fl_Check_Button(75, 260, 170, 20, "bind to widget"); o->tooltip("bind the image to the widget, so it will be deleted automatically"); o->down_box(FL_DOWN_BOX); o->labelsize(11); o->callback((Fl_Callback*)bind_deimage_cb); } // Fl_Check_Button* o image_panel_deimagegroup->end(); } // Fl_Group* image_panel_deimagegroup { image_panel_close = new Fl_Button(165, 295, 80, 20, "Close"); image_panel_close->labelsize(11); image_panel_close->callback((Fl_Callback*)cb_image_panel_close); } // Fl_Button* image_panel_close image_panel_window->set_modal(); image_panel_window->end(); } // Fl_Double_Window* image_panel_window return image_panel_window; } void run_image_panel() { if (!image_panel_window) make_image_panel(); image_panel_window->do_callback(image_panel_window, LOAD); Fl::pushed(0); Fl_Window *g = Fl::grab(); if (g) Fl::grab(0); image_panel_window->show(); while (image_panel_window->shown()) Fl::wait(); if (g) Fl::grab(g); Fl_Shared_Image *img = (Fl_Shared_Image*)image_panel_data->user_data(); if (img) { img->release(); image_panel_data->user_data(NULL); } } Fl_Tabs *widget_tabs=(Fl_Tabs *)0; static void cb_widget_tabs(Fl_Tabs* o, void* v) { propagate_load((Fl_Group *)o,v); } Fl_Group *wp_gui_tab=(Fl_Group *)0; Fl_Input *wp_gui_label=(Fl_Input *)0; Fl_Input *widget_image_input=(Fl_Input *)0; static void cb_(Fl_Button*, void* v) { if (v != LOAD) { run_image_panel(); } } Fl_Input *widget_deimage_input=(Fl_Input *)0; Fl_Group *wp_gui_alignment=(Fl_Group *)0; Fl_Menu_Item menu_[] = { {" Image Alignment ", 0, 0, (void*)((fl_intptr_t)0xFFFFFFFF), 1, (uchar)FL_NORMAL_LABEL, 2, 10, 0}, {"image over text", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_IMAGE_OVER_TEXT), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"text over image", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_TEXT_OVER_IMAGE), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"text next to image", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_TEXT_NEXT_TO_IMAGE), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"image next to text", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_IMAGE_NEXT_TO_TEXT), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"image is backdrop", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_IMAGE_BACKDROP), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Menu_Item menu_1[] = { {" Inside && Outside ", 0, 0, (void*)((fl_intptr_t)0xFFFFFFFF), 1, (uchar)FL_NORMAL_LABEL, 2, 10, 0}, {"top left", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_TOP_LEFT), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"top", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_TOP), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"top right", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_TOP_RIGHT), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"left", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_LEFT), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"center", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_CENTER), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"right", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_RIGHT), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"bottom left", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_BOTTOM_LEFT), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"bottom", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_BOTTOM), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"bottom right", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_BOTTOM_RIGHT), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {" Outside Alignment ", 0, 0, (void*)((fl_intptr_t)0xFFFFFFFF), 1, (uchar)FL_NORMAL_LABEL, 2, 10, 0}, {"left top", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_LEFT_TOP), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"right top", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_RIGHT_TOP), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"left bottom", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_LEFT_BOTTOM), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {"right bottom", 0, 0, (void*)((fl_intptr_t)FL_ALIGN_RIGHT_BOTTOM), 0, (uchar)FL_NORMAL_LABEL, 0, 9, 0}, {0,0,0,0,0,0,0,0,0} }; Fluid_Coord_Input *widget_x_input=(Fluid_Coord_Input *)0; Fluid_Coord_Input *widget_y_input=(Fluid_Coord_Input *)0; Fluid_Coord_Input *widget_w_input=(Fluid_Coord_Input *)0; Fluid_Coord_Input *widget_h_input=(Fluid_Coord_Input *)0; Fl_Menu_Item menu_Children[] = { {"Fixed", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"Reposition", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"Resize", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Group *wp_gui_flexp=(Fl_Group *)0; Fl_Value_Input *widget_flex_size=(Fl_Value_Input *)0; Fl_Check_Button *widget_flex_fixed=(Fl_Check_Button *)0; Fl_Group *wp_gui_values=(Fl_Group *)0; Fl_Group *wp_gui_margins=(Fl_Group *)0; Fl_Group *wp_gui_sizerange=(Fl_Group *)0; Fl_Shortcut_Button *wp_gui_shortcut=(Fl_Shortcut_Button *)0; Fl_Group *wp_gui_xclass=(Fl_Group *)0; Fl_Group *wp_gui_attributes=(Fl_Group *)0; Fl_Input *wp_gui_tooltip=(Fl_Input *)0; Fl_Group *wp_style_tab=(Fl_Group *)0; Fl_Group *wp_style_label=(Fl_Group *)0; Fl_Button *w_labelcolor=(Fl_Button *)0; Fl_Group *wp_style_box=(Fl_Group *)0; Fl_Button *w_color=(Fl_Button *)0; Fl_Group *wp_style_downbox=(Fl_Group *)0; Fl_Button *w_selectcolor=(Fl_Button *)0; Fl_Group *wp_style_text=(Fl_Group *)0; Fl_Button *w_textcolor=(Fl_Button *)0; Fl_Group *wp_cpp_tab=(Fl_Group *)0; Fl_Group *wp_cpp_class=(Fl_Group *)0; Fl_Group *wp_cpp_name=(Fl_Group *)0; Fl_Menu_Item menu_2[] = { {"private", 0, 0, (void*)(0), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"public", 0, 0, (void*)(1), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"protected", 0, 0, (void*)(2), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Menu_Item menu_3[] = { {"local", 0, 0, (void*)(0), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"global", 0, 0, (void*)(1), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Input *v_input[4]={(Fl_Input *)0}; static void cb_1(Fl_Tile*, void* v) { wComment->do_callback(wComment, v); wCallback->do_callback(wCallback, v); } Fl_Text_Editor *wComment=(Fl_Text_Editor *)0; CodeEditor *wCallback=(CodeEditor *)0; Fl_Group *wp_cpp_callback=(Fl_Group *)0; Fl_Menu_Item menu_4[] = { {"void*", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {"long", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Box *w_when_box=(Fl_Box *)0; Fl_Group *widget_tab_grid_child=(Fl_Group *)0; Fluid_Coord_Input *widget_grid_row_input=(Fluid_Coord_Input *)0; Fluid_Coord_Input *widget_grid_col_input=(Fluid_Coord_Input *)0; Fl_Box *widget_grid_transient=(Fl_Box *)0; static void cb_widget_grid_transient(Fl_Box* o, void* v) { if (v==LOAD) { Fl_Widget *child = ((Fl_Widget_Type*)current_widget)->o; Fl_Grid_Proxy *g = ((Fl_Grid_Proxy*)((Fl_Widget_Type*)current_widget->parent)->o); // Fl_Grid::Cell *cell = g->cell(child); // Fl_Grid::Cell *tcell = g->transient_cell(child); widget_grid_transient->hide(); widget_grid_unlinked->hide(); if (g->transient_cell(child)) { widget_grid_transient->show(); } else if (!g->cell(child)) { widget_grid_unlinked->show(); } } } Fl_Box *widget_grid_unlinked=(Fl_Box *)0; Fl_Group *wp_gridc_align=(Fl_Group *)0; Fl_Menu_Item menu_Horizontal[] = { {"GRID_LEFT", 0, 0, (void*)((fl_intptr_t)FL_GRID_LEFT), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"GRID_CENTER", 0, 0, (void*)((fl_intptr_t)FL_GRID_CENTER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"GRID_RIGHT", 0, 0, (void*)((fl_intptr_t)FL_GRID_RIGHT), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"GRID_FILL", 0, 0, (void*)((fl_intptr_t)FL_GRID_HORIZONTAL), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Menu_Item menu_Vertical[] = { {"GRID_TOP", 0, 0, (void*)((fl_intptr_t)FL_GRID_TOP), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"GRID_CENTER", 0, 0, (void*)((fl_intptr_t)FL_GRID_CENTER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"GRID_BOTTOM", 0, 0, (void*)((fl_intptr_t)FL_GRID_BOTTOM), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"GRID_FILL", 0, 0, (void*)((fl_intptr_t)FL_GRID_VERTICAL), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; Fl_Group *wp_gridc_size=(Fl_Group *)0; Fluid_Coord_Input *widget_grid_rowspan_input=(Fluid_Coord_Input *)0; Fluid_Coord_Input *widget_grid_colspan_input=(Fluid_Coord_Input *)0; Fl_Group *widget_tab_grid=(Fl_Group *)0; Fluid_Coord_Input *widget_grid_rows=(Fluid_Coord_Input *)0; static void cb_widget_grid_rows(Fluid_Coord_Input* o, void* v) { // grid_rows_cb Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; if (v == LOAD) { o->value(grid->rows()); } else { int m = o->value(), old_m = grid->rows(); if (m < 1) { m = 1; o->value(m); } if (m < old_m) { // TODO: verify that this will not unlink existings cells // Offer a dialog with "delete children", "unlink cells", "cancel" } if (m != old_m) { undo_checkpoint(); grid->layout(m, grid->cols()); grid->need_layout(true); set_modflag(1); widget_tab_grid->do_callback(widget_tab_grid, LOAD); } } } static void cb_2(Fl_Button*, void* v) { if (v != LOAD) { widget_grid_rows->value( widget_grid_rows->value()-1 ); widget_grid_rows->do_callback(); } } static void cb_3(Fl_Button*, void* v) { if (v != LOAD) { widget_grid_rows->value( widget_grid_rows->value()+1 ); widget_grid_rows->do_callback(); } } Fluid_Coord_Input *widget_grid_cols=(Fluid_Coord_Input *)0; static void cb_widget_grid_cols(Fluid_Coord_Input* o, void* v) { // grid_rows_cb Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; if (v == LOAD) { o->value(grid->cols()); } else { int m = o->value(), old_m = grid->cols(); if (m < 1) { m = 1; o->value(m); } if (m < old_m) { // TODO: verify that this will not unlink existings cells // Offer a dialog with "delete children", "unlink cells", "cancel" } if (m != old_m) { undo_checkpoint(); grid->layout(grid->rows(), m); grid->need_layout(true); set_modflag(1); widget_tab_grid->do_callback(widget_tab_grid, LOAD); } } } static void cb_4(Fl_Button*, void* v) { if (v != LOAD) { widget_grid_cols->value( widget_grid_cols->value()-1 ); widget_grid_cols->do_callback(); } } static void cb_5(Fl_Button*, void* v) { if (v != LOAD) { widget_grid_cols->value( widget_grid_cols->value()+1 ); widget_grid_cols->do_callback(); } } Fl_Group *wp_grid_margin=(Fl_Group *)0; static void cb_Left(Fl_Value_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int m = 0; if (v == LOAD) { grid->margin(&m, NULL, NULL, NULL); o->value(m); } else { int m = (int)o->value(), old_m; grid->margin(&old_m, NULL, NULL, NULL); if (m != old_m) { undo_checkpoint(); grid->margin(m, -1, -1, -1); grid->need_layout(true); set_modflag(1); } } } static void cb_Top(Fl_Value_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int m = 0; if (v == LOAD) { grid->margin(NULL, &m, NULL, NULL); o->value(m); } else { int m = (int)o->value(), old_m; grid->margin(NULL, &old_m, NULL, NULL); if (m != old_m) { undo_checkpoint(); grid->margin(-1, m, -1, -1); grid->need_layout(true); set_modflag(1); } } } static void cb_Right(Fl_Value_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int m = 0; if (v == LOAD) { grid->margin(NULL, NULL, &m, NULL); o->value(m); } else { int m = (int)o->value(), old_m; grid->margin(NULL, NULL, &old_m, NULL); if (m != old_m) { undo_checkpoint(); grid->margin(-1, -1, m, -1); grid->need_layout(true); set_modflag(1); } } } static void cb_Bottom(Fl_Value_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int m = 0; if (v == LOAD) { grid->margin(NULL, NULL, NULL, &m); o->value(m); } else { int m = (int)o->value(), old_m; grid->margin(NULL, NULL, NULL, &old_m); if (m != old_m) { undo_checkpoint(); grid->margin(-1, -1, -1, m); grid->need_layout(true); set_modflag(1); } } } Fl_Group *wp_grid_gaps=(Fl_Group *)0; static void cb_Row(Fl_Value_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; if (v == LOAD) { int m = 0; grid->gap(&m, NULL); o->value(m); } else { int m = (int)o->value(), old_m, m2; grid->gap(&old_m, &m2); if (m != old_m) { undo_checkpoint(); grid->gap(m, m2); grid->need_layout(true); set_modflag(1); } } } static void cb_Col(Fl_Value_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; if (v == LOAD) { int m = 0; grid->gap(NULL, &m); o->value(m); } else { int m = (int)o->value(), old_m, m2; grid->gap(&m2, &old_m); if (m != old_m) { undo_checkpoint(); grid->gap(m2, m); grid->need_layout(true); set_modflag(1); } } } static void cb_Row1(Fl_Group* o, void* v) { if (v == LOAD) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (grid) o->activate(); else o->deactivate(); propagate_load(o, v); } } Fluid_Coord_Input *widget_grid_curr_row=(Fluid_Coord_Input *)0; static void cb_widget_grid_curr_row(Fluid_Coord_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int r = o->value(), old_r = r; if (r < 0) r = 0; if (r >= grid->rows()) r = grid->rows()-1; if (r != old_r) o->value(r); if (v == LOAD) { // will automatically propagate } else { widget_grid_curr_row_attributes->do_callback(widget_grid_curr_row_attributes, LOAD); } } static void cb_6(Fl_Button*, void* v) { if (v != LOAD) { widget_grid_curr_row->value( widget_grid_curr_row->value()-1 ); widget_grid_curr_row->do_callback(); } } static void cb_7(Fl_Button*, void* v) { if (v != LOAD) { widget_grid_curr_row->value( widget_grid_curr_row->value()+1 ); widget_grid_curr_row->do_callback(); } } Fl_Group *widget_grid_curr_row_attributes=(Fl_Group *)0; static void cb_Height(Fluid_Coord_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int r = widget_grid_curr_row->value(); if (v == LOAD) { o->value(grid->row_height(r)); } else { int h = o->value(), old_h = grid->row_height(r); if (h < 0) h = 0; if (h != old_h) { undo_checkpoint(); grid->row_height(r, h); grid->need_layout(true); set_modflag(1); } } } static void cb_Weight(Fluid_Coord_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int r = widget_grid_curr_row->value(); if (v == LOAD) { o->value(grid->row_weight(r)); } else { int h = o->value(), old_h = grid->row_weight(r); if (h < 0) h = 0; if (h != old_h) { undo_checkpoint(); grid->row_weight(r, h); grid->need_layout(true); set_modflag(1); } } } static void cb_Gap(Fluid_Coord_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int r = widget_grid_curr_row->value(); if (v == LOAD) { o->value(grid->row_gap(r)); } else { int h = o->value(), old_h = grid->row_gap(r); if (h < -1) h = -1; if (h != old_h) { undo_checkpoint(); grid->row_gap(r, h); grid->need_layout(true); set_modflag(1); } } } Fluid_Coord_Input *widget_grid_curr_col=(Fluid_Coord_Input *)0; static void cb_widget_grid_curr_col(Fluid_Coord_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int c = o->value(), old_c = c; if (c < 0) c = 0; if (c >= grid->cols()) c = grid->cols()-1; if (c != old_c) o->value(c); if (v == LOAD) { // will automatically propagate } else { widget_grid_curr_col_attributes->do_callback(widget_grid_curr_col_attributes, LOAD); } } static void cb_8(Fl_Button*, void* v) { if (v != LOAD) { widget_grid_curr_col->value( widget_grid_curr_col->value()-1 ); widget_grid_curr_col->do_callback(); } } static void cb_9(Fl_Button*, void* v) { if (v != LOAD) { widget_grid_curr_col->value( widget_grid_curr_col->value()+1 ); widget_grid_curr_col->do_callback(); } } Fl_Group *widget_grid_curr_col_attributes=(Fl_Group *)0; static void cb_Width(Fluid_Coord_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int c = widget_grid_curr_col->value(); if (v == LOAD) { o->value(grid->col_width(c)); } else { int h = o->value(), old_h = grid->col_width(c); if (h < 0) h = 0; if (h != old_h) { undo_checkpoint(); grid->col_width(c, h); grid->need_layout(true); set_modflag(1); } } } static void cb_Weight1(Fluid_Coord_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int c = widget_grid_curr_col->value(); if (v == LOAD) { o->value(grid->col_weight(c)); } else { int h = o->value(), old_h = grid->col_weight(c); if (h < 0) h = 0; if (h != old_h) { undo_checkpoint(); grid->col_weight(c, h); grid->need_layout(true); set_modflag(1); } } } static void cb_Gap1(Fluid_Coord_Input* o, void* v) { Fl_Grid *grid = Fl_Grid_Type::selected(); if (!grid) return; int c = widget_grid_curr_col->value(); if (v == LOAD) { o->value(grid->col_gap(c)); } else { int h = o->value(), old_h = grid->col_gap(c); if (h < -1) h = -1; if (h != old_h) { undo_checkpoint(); grid->col_gap(c, h); grid->need_layout(true); set_modflag(1); } } } Fl_Tabs *widget_tabs_repo=(Fl_Tabs *)0; Fl_Button *wLiveMode=(Fl_Button *)0; Fl_Button *overlay_button=(Fl_Button *)0; /** Create a panel that can be used with all known widgets */ Fl_Double_Window* make_widget_panel() { Fl_Double_Window* w; { // Use a Double Window to avoid flickering. Fl_Double_Window* o = new Fl_Double_Window(420, 400); w = o; (void)w; o->labelsize(11); o->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); o->hotspot(o); { Fl_Tabs* o = widget_tabs = new Fl_Tabs(10, 10, 400, 350); widget_tabs->selection_color((Fl_Color)12); widget_tabs->labelsize(11); widget_tabs->labelcolor(FL_BACKGROUND2_COLOR); widget_tabs->callback((Fl_Callback*)cb_widget_tabs); widget_tabs->when(FL_WHEN_NEVER); { wp_gui_tab = new Fl_Group(10, 30, 400, 330, "GUI"); wp_gui_tab->labelsize(11); wp_gui_tab->callback((Fl_Callback*)propagate_load); wp_gui_tab->when(FL_WHEN_NEVER); { Fl_Group* o = new Fl_Group(95, 40, 309, 20, "Label:"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { wp_gui_label = new Fl_Input(95, 40, 190, 20); wp_gui_label->tooltip("The label text for the widget.\nUse Ctrl-J for newlines."); wp_gui_label->labelfont(1); wp_gui_label->labelsize(11); wp_gui_label->textsize(11); wp_gui_label->callback((Fl_Callback*)label_cb); wp_gui_label->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY_CHANGED); Fl_Group::current()->resizable(wp_gui_label); } // Fl_Input* wp_gui_label { Fl_Choice* o = new Fl_Choice(285, 40, 119, 20); o->tooltip("The label style for the widget."); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)labeltype_cb); o->menu(labeltypemenu); } // Fl_Choice* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(95, 65, 309, 20, "Image:"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { widget_image_input = new Fl_Input(95, 65, 200, 20); widget_image_input->tooltip("The active image for the widget."); widget_image_input->labelfont(1); widget_image_input->labelsize(11); widget_image_input->textsize(11); widget_image_input->callback((Fl_Callback*)image_cb); Fl_Group::current()->resizable(widget_image_input); } // Fl_Input* widget_image_input { Fl_Button* o = new Fl_Button(295, 65, 89, 20, "Browse..."); o->tooltip("Click to choose the active image."); o->labelsize(11); o->callback((Fl_Callback*)image_browse_cb); o->align(Fl_Align(256)); } // Fl_Button* o { Fl_Button* o = new Fl_Button(384, 65, 20, 20, "..."); o->tooltip("more image options"); o->callback((Fl_Callback*)cb_); } // Fl_Button* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(95, 90, 309, 20, "Inactive:"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { widget_deimage_input = new Fl_Input(95, 90, 200, 20); widget_deimage_input->tooltip("The inactive image for the widget."); widget_deimage_input->labelfont(1); widget_deimage_input->labelsize(11); widget_deimage_input->textsize(11); widget_deimage_input->callback((Fl_Callback*)inactive_cb); Fl_Group::current()->resizable(widget_deimage_input); } // Fl_Input* widget_deimage_input { Fl_Button* o = new Fl_Button(295, 90, 89, 20, "Browse..."); o->tooltip("Click to choose the inactive image."); o->labelsize(11); o->callback((Fl_Callback*)inactive_browse_cb); } // Fl_Button* o o->end(); } // Fl_Group* o { wp_gui_alignment = new Fl_Group(95, 115, 312, 20, "Alignment:"); wp_gui_alignment->labelfont(1); wp_gui_alignment->labelsize(11); wp_gui_alignment->callback((Fl_Callback*)propagate_load); wp_gui_alignment->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Button* o = new Fl_Button(95, 115, 30, 20, "Clip"); o->tooltip("Clip the label to the inside of the widget."); o->type(1); o->selection_color(FL_INACTIVE_COLOR); o->labelsize(11); o->callback((Fl_Callback*)align_cb, (void*)((fl_intptr_t)FL_ALIGN_CLIP)); o->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)); } // Fl_Button* o { Fl_Button* o = new Fl_Button(130, 115, 38, 20, "Wrap"); o->tooltip("Wrap the label text."); o->type(1); o->selection_color(FL_INACTIVE_COLOR); o->labelsize(11); o->callback((Fl_Callback*)align_cb, (void*)((fl_intptr_t)FL_ALIGN_WRAP)); } // Fl_Button* o { Fl_Button* o = new Fl_Button(278, 115, 20, 20, "@-1<-"); o->tooltip("Left-align the label."); o->type(1); o->selection_color(FL_INACTIVE_COLOR); o->labelsize(11); o->labelcolor(FL_INACTIVE_COLOR); o->callback((Fl_Callback*)align_cb, (void*)((fl_intptr_t)FL_ALIGN_LEFT)); o->hide(); } // Fl_Button* o { Fl_Button* o = new Fl_Button(303, 115, 20, 20, "@-1->"); o->tooltip("Right-align the label."); o->type(1); o->selection_color(FL_INACTIVE_COLOR); o->labelsize(11); o->labelcolor(FL_INACTIVE_COLOR); o->callback((Fl_Callback*)align_cb, (void*)((fl_intptr_t)FL_ALIGN_RIGHT)); o->hide(); } // Fl_Button* o { Fl_Button* o = new Fl_Button(328, 115, 20, 20, "@-18"); o->tooltip("Top-align the label."); o->type(1); o->selection_color(FL_INACTIVE_COLOR); o->labelsize(11); o->labelcolor(FL_INACTIVE_COLOR); o->callback((Fl_Callback*)align_cb, (void*)((fl_intptr_t)FL_ALIGN_TOP)); o->hide(); } // Fl_Button* o { Fl_Button* o = new Fl_Button(353, 115, 20, 20, "@-12"); o->tooltip("Bottom-align the label."); o->type(1); o->selection_color(FL_INACTIVE_COLOR); o->labelsize(11); o->labelcolor(FL_INACTIVE_COLOR); o->callback((Fl_Callback*)align_cb, (void*)((fl_intptr_t)FL_ALIGN_BOTTOM)); o->hide(); } // Fl_Button* o { Fl_Choice* o = new Fl_Choice(172, 115, 116, 20); o->down_box(FL_BORDER_BOX); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)align_text_image_cb); o->menu(menu_); } // Fl_Choice* o { Fl_Choice* o = new Fl_Choice(293, 115, 86, 20); o->down_box(FL_BORDER_BOX); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)align_position_cb); o->menu(menu_1); } // Fl_Choice* o { Fl_Button* o = new Fl_Button(384, 115, 20, 20, "@-3square"); o->tooltip("Show the label inside the widget."); o->type(1); o->selection_color(FL_INACTIVE_COLOR); o->labelsize(11); o->labelcolor(FL_INACTIVE_COLOR); o->callback((Fl_Callback*)align_cb, (void*)((fl_intptr_t)FL_ALIGN_INSIDE)); } // Fl_Button* o { Fl_Box* o = new Fl_Box(406, 115, 1, 20); o->labelsize(11); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_gui_alignment->end(); } // Fl_Group* wp_gui_alignment { Fl_Group* o = new Fl_Group(95, 150, 314, 20, "Position:"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)position_group_cb); o->align(Fl_Align(FL_ALIGN_LEFT)); { widget_x_input = new Fluid_Coord_Input(95, 150, 55, 20, "X:"); widget_x_input->tooltip("The X position of the widget as a number or formula.\nFormulas can be simple " "math, including the variables\nx, px, sx, cx, and i"); widget_x_input->box(FL_DOWN_BOX); widget_x_input->color(FL_BACKGROUND2_COLOR); widget_x_input->selection_color(FL_SELECTION_COLOR); widget_x_input->labeltype(FL_NORMAL_LABEL); widget_x_input->labelfont(0); widget_x_input->labelsize(11); widget_x_input->labelcolor(FL_FOREGROUND_COLOR); widget_x_input->textsize(11); widget_x_input->callback((Fl_Callback*)x_cb); widget_x_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_x_input->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_x_input { widget_y_input = new Fluid_Coord_Input(155, 150, 55, 20, "Y:"); widget_y_input->tooltip("The Y position of the widget as a number or formula.\nFormulas can be simple " "math, including the variables\ny, py, sy, cy, and i"); widget_y_input->box(FL_DOWN_BOX); widget_y_input->color(FL_BACKGROUND2_COLOR); widget_y_input->selection_color(FL_SELECTION_COLOR); widget_y_input->labeltype(FL_NORMAL_LABEL); widget_y_input->labelfont(0); widget_y_input->labelsize(11); widget_y_input->labelcolor(FL_FOREGROUND_COLOR); widget_y_input->textsize(11); widget_y_input->callback((Fl_Callback*)y_cb); widget_y_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_y_input->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_y_input { widget_w_input = new Fluid_Coord_Input(215, 150, 55, 20, "Width:"); widget_w_input->tooltip("The width of the widget as a number or formula.\nFormulas can be simple math," " including the variables\nw, pw, sw, cw, and i"); widget_w_input->box(FL_DOWN_BOX); widget_w_input->color(FL_BACKGROUND2_COLOR); widget_w_input->selection_color(FL_SELECTION_COLOR); widget_w_input->labeltype(FL_NORMAL_LABEL); widget_w_input->labelfont(0); widget_w_input->labelsize(11); widget_w_input->labelcolor(FL_FOREGROUND_COLOR); widget_w_input->textsize(11); widget_w_input->callback((Fl_Callback*)w_cb); widget_w_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_w_input->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_w_input { widget_h_input = new Fluid_Coord_Input(275, 150, 55, 20, "Height:"); widget_h_input->tooltip("The height of the widget as a number or formula.\nFormulas can be simple math" ", including the variables\nh, ph, sh, ch, and i"); widget_h_input->box(FL_DOWN_BOX); widget_h_input->color(FL_BACKGROUND2_COLOR); widget_h_input->selection_color(FL_SELECTION_COLOR); widget_h_input->labeltype(FL_NORMAL_LABEL); widget_h_input->labelfont(0); widget_h_input->labelsize(11); widget_h_input->labelcolor(FL_FOREGROUND_COLOR); widget_h_input->textsize(11); widget_h_input->callback((Fl_Callback*)h_cb); widget_h_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_h_input->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_h_input { Fl_Choice* o = new Fl_Choice(335, 150, 64, 20, "Children:"); o->tooltip("When instantiating a widget class, the children can either be fixed in their " "original position, automatically be repositioned, or both repsositioned and re" "sized to fit the container."); o->down_box(FL_BORDER_BOX); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)wc_relative_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->menu(menu_Children); } // Fl_Choice* o { Fl_Box* o = new Fl_Box(399, 150, 1, 20); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { // This group is only visible if the parent is an Fl_Flex widget wp_gui_flexp = new Fl_Group(95, 150, 314, 20, "Flex Parent:"); wp_gui_flexp->labelfont(1); wp_gui_flexp->labelsize(11); wp_gui_flexp->callback((Fl_Callback*)flex_size_group_cb); wp_gui_flexp->align(Fl_Align(FL_ALIGN_LEFT)); wp_gui_flexp->hide(); { widget_flex_size = new Fl_Value_Input(95, 150, 55, 20, "Size:"); widget_flex_size->tooltip("Fixed Width or Height for a horizontal or vertical Fl_Flex Parent."); widget_flex_size->labelsize(11); widget_flex_size->textsize(11); widget_flex_size->callback((Fl_Callback*)flex_size_cb); widget_flex_size->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* widget_flex_size { widget_flex_fixed = new Fl_Check_Button(155, 150, 55, 20, "fixed"); widget_flex_fixed->tooltip("If checked, the size of the widget stays fixed."); widget_flex_fixed->down_box(FL_DOWN_BOX); widget_flex_fixed->labelsize(11); widget_flex_fixed->callback((Fl_Callback*)flex_fixed_cb); } // Fl_Check_Button* widget_flex_fixed { Fl_Box* o = new Fl_Box(398, 150, 1, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_gui_flexp->end(); } // Fl_Group* wp_gui_flexp { wp_gui_values = new Fl_Group(95, 185, 300, 20, "Values:"); wp_gui_values->labelfont(1); wp_gui_values->labelsize(11); wp_gui_values->callback((Fl_Callback*)values_group_cb); wp_gui_values->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Value_Input* o = new Fl_Value_Input(95, 185, 55, 20, "Size:"); o->tooltip("The size of the slider."); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)slider_size_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(155, 185, 55, 20, "Minimum:"); o->tooltip("The minimum value of the widget."); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)min_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(215, 185, 55, 20, "Maximum:"); o->tooltip("The maximum value of the widget."); o->labelsize(11); o->value(1); o->textsize(11); o->callback((Fl_Callback*)max_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(275, 185, 55, 20, "Step:"); o->tooltip("The resolution of the widget value."); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)step_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(335, 185, 55, 20, "Value:"); o->tooltip("The current widget value."); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)value_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(395, 185, 0, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_gui_values->end(); } // Fl_Group* wp_gui_values { // This group is only visible for Fl_Flex widgets wp_gui_margins = new Fl_Group(95, 185, 300, 20, "Margins:"); wp_gui_margins->labelfont(1); wp_gui_margins->labelsize(11); wp_gui_margins->callback((Fl_Callback*)flex_margin_group_cb); wp_gui_margins->align(Fl_Align(FL_ALIGN_LEFT)); wp_gui_margins->hide(); { Fl_Value_Input* o = new Fl_Value_Input(95, 185, 55, 20, "Left:"); o->tooltip("Left margin in group."); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)flex_margin_left_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(155, 185, 55, 20, "Top:"); o->tooltip("Top margin in group."); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)flex_margin_top_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(215, 185, 55, 20, "Right:"); o->tooltip("Right margin in group."); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)flex_margin_right_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(275, 185, 55, 20, "Bottom:"); o->tooltip("Bottom margin in group."); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)flex_margin_bottom_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(335, 185, 55, 20, "Gap:"); o->tooltip("Gap between children."); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)flex_margin_gap_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(395, 185, 0, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_gui_margins->end(); } // Fl_Group* wp_gui_margins { wp_gui_sizerange = new Fl_Group(95, 185, 300, 20, "Size Range:"); wp_gui_sizerange->labelfont(1); wp_gui_sizerange->labelsize(11); wp_gui_sizerange->callback((Fl_Callback*)size_range_group_cb); wp_gui_sizerange->align(Fl_Align(FL_ALIGN_LEFT)); wp_gui_sizerange->hide(); { Fl_Value_Input* o = new Fl_Value_Input(95, 185, 55, 20, "Minimum Size:"); o->tooltip("The size of the slider."); o->labelsize(11); o->maximum(2048); o->step(1); o->textsize(11); o->callback((Fl_Callback*)min_w_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(155, 185, 55, 20); o->tooltip("The minimum value of the widget."); o->labelsize(11); o->maximum(2048); o->step(1); o->textsize(11); o->callback((Fl_Callback*)min_h_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Button* o = new Fl_Button(215, 185, 25, 20, "set"); o->labelsize(11); o->callback((Fl_Callback*)set_min_size_cb); } // Fl_Button* o { Fl_Value_Input* o = new Fl_Value_Input(245, 185, 55, 20, "Maximum Size:"); o->tooltip("The maximum value of the widget."); o->labelsize(11); o->maximum(2048); o->step(1); o->textsize(11); o->callback((Fl_Callback*)max_w_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(305, 185, 55, 20); o->tooltip("The resolution of the widget value."); o->labelsize(11); o->maximum(2048); o->step(1); o->textsize(11); o->callback((Fl_Callback*)max_h_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Button* o = new Fl_Button(365, 185, 25, 20, "set"); o->labelsize(11); o->callback((Fl_Callback*)set_max_size_cb); } // Fl_Button* o { Fl_Box* o = new Fl_Box(395, 185, 0, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_gui_sizerange->end(); } // Fl_Group* wp_gui_sizerange { Fl_Group* o = new Fl_Group(95, 210, 310, 20, "Shortcut:"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { // This is a special button that grabs keystrokes directly wp_gui_shortcut = new Fl_Shortcut_Button(95, 210, 310, 20); wp_gui_shortcut->tooltip("The shortcut key for the widget.\nUse \'Backspace\' key to clear."); wp_gui_shortcut->box(FL_DOWN_BOX); wp_gui_shortcut->color(FL_BACKGROUND2_COLOR); wp_gui_shortcut->selection_color((Fl_Color)12); wp_gui_shortcut->labeltype(FL_NORMAL_LABEL); wp_gui_shortcut->labelfont(0); wp_gui_shortcut->labelsize(11); wp_gui_shortcut->labelcolor(FL_FOREGROUND_COLOR); wp_gui_shortcut->callback((Fl_Callback*)shortcut_in_cb); wp_gui_shortcut->align(Fl_Align(FL_ALIGN_CENTER)); wp_gui_shortcut->when(FL_WHEN_CHANGED); } // Fl_Shortcut_Button* wp_gui_shortcut o->end(); } // Fl_Group* o { wp_gui_xclass = new Fl_Group(95, 235, 300, 20, "X Class:"); wp_gui_xclass->labelfont(1); wp_gui_xclass->labelsize(11); wp_gui_xclass->callback((Fl_Callback*)propagate_load); wp_gui_xclass->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Input* o = new Fl_Input(95, 235, 95, 20, ":"); o->tooltip("The X resource class."); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)xclass_cb); Fl_Group::current()->resizable(o); } // Fl_Input* o { Fl_Light_Button* o = new Fl_Light_Button(195, 235, 60, 20, "Border"); o->tooltip("Add a border around the window."); o->selection_color((Fl_Color)1); o->labelsize(11); o->callback((Fl_Callback*)border_cb); } // Fl_Light_Button* o { Fl_Light_Button* o = new Fl_Light_Button(260, 235, 55, 20, "Modal"); o->tooltip("Make the window modal."); o->selection_color((Fl_Color)1); o->labelsize(11); o->callback((Fl_Callback*)modal_cb); } // Fl_Light_Button* o { Fl_Light_Button* o = new Fl_Light_Button(320, 235, 75, 20, "Nonmodal"); o->tooltip("Make the window non-modal."); o->selection_color((Fl_Color)1); o->labelsize(11); o->callback((Fl_Callback*)non_modal_cb); o->align(Fl_Align(132|FL_ALIGN_INSIDE)); } // Fl_Light_Button* o wp_gui_xclass->end(); } // Fl_Group* wp_gui_xclass { wp_gui_attributes = new Fl_Group(95, 260, 305, 20, "Attributes:"); wp_gui_attributes->labelfont(1); wp_gui_attributes->labelsize(11); wp_gui_attributes->callback((Fl_Callback*)propagate_load); wp_gui_attributes->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Light_Button* o = new Fl_Light_Button(95, 260, 60, 20, "Visible"); o->tooltip("Show the widget."); o->selection_color((Fl_Color)1); o->labelsize(11); o->callback((Fl_Callback*)visible_cb); } // Fl_Light_Button* o { Fl_Light_Button* o = new Fl_Light_Button(160, 260, 60, 20, "Active"); o->tooltip("Activate the widget."); o->selection_color((Fl_Color)1); o->labelsize(11); o->callback((Fl_Callback*)active_cb); } // Fl_Light_Button* o { Fl_Light_Button* o = new Fl_Light_Button(225, 260, 75, 20, "Resizable"); o->tooltip("Make the widget resizable."); o->selection_color((Fl_Color)1); o->labelsize(11); o->callback((Fl_Callback*)resizable_cb); o->when(FL_WHEN_CHANGED); } // Fl_Light_Button* o { Fl_Light_Button* o = new Fl_Light_Button(305, 260, 70, 20, "Hotspot"); o->tooltip("Center the window under this widget."); o->selection_color((Fl_Color)1); o->labelsize(11); o->callback((Fl_Callback*)hotspot_cb); o->when(FL_WHEN_CHANGED); } // Fl_Light_Button* o { Fl_Box* o = new Fl_Box(395, 260, 0, 20); o->labelsize(11); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_gui_attributes->end(); } // Fl_Group* wp_gui_attributes { wp_gui_tooltip = new Fl_Input(95, 285, 310, 20, "Tooltip:"); wp_gui_tooltip->tooltip("The tooltip text for the widget.\nUse Ctrl-J for newlines."); wp_gui_tooltip->labelfont(1); wp_gui_tooltip->labelsize(11); wp_gui_tooltip->textsize(11); wp_gui_tooltip->callback((Fl_Callback*)tooltip_cb); } // Fl_Input* wp_gui_tooltip { Fl_Box* o = new Fl_Box(95, 305, 300, 5); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_gui_tab->end(); Fl_Group::current()->resizable(wp_gui_tab); } // Fl_Group* wp_gui_tab { wp_style_tab = new Fl_Group(10, 30, 400, 330, "Style"); wp_style_tab->labelsize(11); wp_style_tab->callback((Fl_Callback*)propagate_load); wp_style_tab->when(FL_WHEN_NEVER); wp_style_tab->hide(); { wp_style_label = new Fl_Group(99, 40, 305, 20, "Label Font:"); wp_style_label->labelfont(1); wp_style_label->labelsize(11); wp_style_label->callback((Fl_Callback*)propagate_load); wp_style_label->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Choice* o = new Fl_Choice(99, 40, 148, 20); o->tooltip("The style of the label text."); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)labelfont_cb); Fl_Group::current()->resizable(o); o->menu(fontmenu); } // Fl_Choice* o { Fl_Value_Input* o = new Fl_Value_Input(247, 40, 49, 20); o->tooltip("The size of the label text."); o->labelsize(11); o->maximum(100); o->step(1); o->value(14); o->textsize(11); o->callback((Fl_Callback*)labelsize_cb); } // Fl_Value_Input* o { w_labelcolor = new Fl_Button(296, 40, 90, 20, "Label Color"); w_labelcolor->tooltip("The color of the label text."); w_labelcolor->labelsize(11); w_labelcolor->callback((Fl_Callback*)labelcolor_cb); } // Fl_Button* w_labelcolor { Fl_Menu_Button* o = new Fl_Menu_Button(386, 40, 18, 20); o->callback((Fl_Callback*)labelcolor_menu_cb); o->menu(colormenu); } // Fl_Menu_Button* o wp_style_label->end(); } // Fl_Group* wp_style_label { wp_style_box = new Fl_Group(99, 65, 305, 20, "Box:"); wp_style_box->labelfont(1); wp_style_box->labelsize(11); wp_style_box->callback((Fl_Callback*)propagate_load); wp_style_box->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Choice* o = new Fl_Choice(100, 65, 196, 20); o->tooltip("The \"up\" box of the widget."); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)box_cb); Fl_Group::current()->resizable(o); o->menu(boxmenu); } // Fl_Choice* o { w_color = new Fl_Button(296, 65, 90, 20, "Color"); w_color->tooltip("The background color of the widget."); w_color->labelsize(11); w_color->callback((Fl_Callback*)color_cb); } // Fl_Button* w_color { Fl_Menu_Button* o = new Fl_Menu_Button(386, 65, 18, 20); o->callback((Fl_Callback*)color_menu_cb); o->menu(colormenu); } // Fl_Menu_Button* o wp_style_box->end(); } // Fl_Group* wp_style_box { wp_style_downbox = new Fl_Group(99, 90, 305, 20, "Down Box:"); wp_style_downbox->labelfont(1); wp_style_downbox->labelsize(11); wp_style_downbox->callback((Fl_Callback*)propagate_load); wp_style_downbox->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Choice* o = new Fl_Choice(99, 90, 197, 20); o->tooltip("The \"down\" box of the widget."); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)down_box_cb); Fl_Group::current()->resizable(o); o->menu(boxmenu); } // Fl_Choice* o { w_selectcolor = new Fl_Button(296, 90, 90, 20, "Select Color"); w_selectcolor->tooltip("The selection color of the widget."); w_selectcolor->labelsize(11); w_selectcolor->callback((Fl_Callback*)color2_cb); } // Fl_Button* w_selectcolor { Fl_Menu_Button* o = new Fl_Menu_Button(386, 90, 18, 20); o->callback((Fl_Callback*)color2_menu_cb); o->menu(colormenu); } // Fl_Menu_Button* o wp_style_downbox->end(); } // Fl_Group* wp_style_downbox { wp_style_text = new Fl_Group(99, 115, 305, 20, "Text Font:"); wp_style_text->labelfont(1); wp_style_text->labelsize(11); wp_style_text->callback((Fl_Callback*)propagate_load); wp_style_text->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Choice* o = new Fl_Choice(99, 115, 148, 20); o->tooltip("The value text style."); o->box(FL_DOWN_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)textfont_cb); Fl_Group::current()->resizable(o); o->menu(fontmenu); } // Fl_Choice* o { Fl_Value_Input* o = new Fl_Value_Input(247, 115, 49, 20); o->tooltip("The value text size."); o->labelsize(11); o->maximum(100); o->step(1); o->value(14); o->textsize(11); o->callback((Fl_Callback*)textsize_cb); } // Fl_Value_Input* o { w_textcolor = new Fl_Button(296, 115, 90, 20, "Text Color"); w_textcolor->tooltip("The value text color."); w_textcolor->labelsize(11); w_textcolor->callback((Fl_Callback*)textcolor_cb); } // Fl_Button* w_textcolor { Fl_Menu_Button* o = new Fl_Menu_Button(386, 115, 18, 20); o->callback((Fl_Callback*)textcolor_menu_cb); o->menu(colormenu); } // Fl_Menu_Button* o wp_style_text->end(); } // Fl_Group* wp_style_text { Fl_Group* o = new Fl_Group(99, 150, 242, 20, "Label Margin:"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Value_Input* o = new Fl_Value_Input(99, 150, 55, 20, "Horizontal:"); o->tooltip("Spacing between label and the horizontally aligned side of the widget."); o->labelsize(11); o->minimum(-127); o->maximum(128); o->step(1); o->textsize(11); o->callback((Fl_Callback*)h_label_margin_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(159, 150, 55, 20, "Vertical:"); o->tooltip("Spacing between label and the vertically aligned side of the widget."); o->labelsize(11); o->minimum(-127); o->maximum(127); o->step(1); o->textsize(11); o->callback((Fl_Callback*)v_label_margin_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(219, 150, 55, 20, "Text to Image:"); o->tooltip("Gap between label image and text in pixels"); o->labelsize(11); o->maximum(255); o->step(1); o->textsize(11); o->callback((Fl_Callback*)image_spacing_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(281, 150, 60, 20); o->labelsize(11); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { Fl_Light_Button* o = new Fl_Light_Button(99, 175, 90, 20, "Compact"); o->tooltip("use compact box types for closely set buttons"); o->selection_color((Fl_Color)1); o->labelsize(11); o->callback((Fl_Callback*)compact_cb); } // Fl_Light_Button* o { Fl_Box* o = new Fl_Box(195, 205, 40, 40); o->labelsize(11); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_style_tab->end(); } // Fl_Group* wp_style_tab { wp_cpp_tab = new Fl_Group(10, 30, 400, 330, "C++"); wp_cpp_tab->labelsize(11); wp_cpp_tab->callback((Fl_Callback*)propagate_load); wp_cpp_tab->when(FL_WHEN_NEVER); wp_cpp_tab->hide(); { wp_cpp_class = new Fl_Group(95, 40, 310, 20, "Class:"); wp_cpp_class->labelfont(1); wp_cpp_class->labelsize(11); wp_cpp_class->callback((Fl_Callback*)propagate_load); wp_cpp_class->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Input* o = new Fl_Input(95, 40, 172, 20); o->tooltip("The widget subclass."); o->labelfont(1); o->labelsize(11); o->textfont(4); o->textsize(11); o->callback((Fl_Callback*)subclass_cb, (void*)(4)); Fl_Group::current()->resizable(o); } // Fl_Input* o { Fl_Choice* o = new Fl_Choice(267, 40, 138, 20); o->tooltip("The widget subtype."); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)subtype_cb); } // Fl_Choice* o wp_cpp_class->end(); } // Fl_Group* wp_cpp_class { wp_cpp_name = new Fl_Group(95, 65, 310, 20, "Name:"); wp_cpp_name->labelfont(1); wp_cpp_name->labelsize(11); wp_cpp_name->callback((Fl_Callback*)propagate_load); wp_cpp_name->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Input* o = new Fl_Input(95, 65, 235, 20); o->tooltip("The name of the widget."); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)name_cb); Fl_Group::current()->resizable(o); } // Fl_Input* o { Fl_Choice* o = new Fl_Choice(330, 65, 75, 20); o->tooltip("Change member access attribute."); o->down_box(FL_BORDER_BOX); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)name_public_member_cb); o->when(FL_WHEN_CHANGED); o->menu(menu_2); } // Fl_Choice* o { Fl_Choice* o = new Fl_Choice(330, 65, 75, 20); o->tooltip("Change widget accessibility."); o->down_box(FL_BORDER_BOX); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)name_public_cb); o->when(FL_WHEN_CHANGED); o->hide(); o->menu(menu_3); } // Fl_Choice* o wp_cpp_name->end(); } // Fl_Group* wp_cpp_name { v_input[0] = new Fl_Input(95, 90, 310, 20, "Extra Code:"); v_input[0]->tooltip("Extra initialization code for the widget."); v_input[0]->labelfont(1); v_input[0]->labelsize(11); v_input[0]->textfont(4); v_input[0]->textsize(11); v_input[0]->callback((Fl_Callback*)v_input_cb, (void*)(0)); } // Fl_Input* v_input[0] { v_input[1] = new Fl_Input(95, 110, 310, 20); v_input[1]->tooltip("Extra initialization code for the widget."); v_input[1]->labelsize(11); v_input[1]->textfont(4); v_input[1]->textsize(11); v_input[1]->callback((Fl_Callback*)v_input_cb, (void*)(1)); } // Fl_Input* v_input[1] { v_input[2] = new Fl_Input(95, 130, 310, 20); v_input[2]->tooltip("Extra initialization code for the widget."); v_input[2]->labelsize(11); v_input[2]->textfont(4); v_input[2]->textsize(11); v_input[2]->callback((Fl_Callback*)v_input_cb, (void*)(2)); } // Fl_Input* v_input[2] { v_input[3] = new Fl_Input(95, 150, 310, 20); v_input[3]->tooltip("Extra initialization code for the widget."); v_input[3]->labelsize(11); v_input[3]->textfont(4); v_input[3]->textsize(11); v_input[3]->callback((Fl_Callback*)v_input_cb, (void*)(3)); } // Fl_Input* v_input[3] { Fl_Tile* o = new Fl_Tile(95, 175, 310, 130); o->callback((Fl_Callback*)cb_1); { Fl_Group* o = new Fl_Group(95, 175, 310, 48); o->box(FL_FLAT_BOX); { wComment = new Fl_Text_Editor(95, 175, 310, 45, "Comment:"); wComment->tooltip("Write a comment that will appear in the source code and in the widget tree ov" "erview."); wComment->box(FL_DOWN_BOX); wComment->labelfont(1); wComment->labelsize(11); wComment->textfont(6); wComment->textsize(11); wComment->textcolor((Fl_Color)59); wComment->align(Fl_Align(FL_ALIGN_LEFT)); wComment->when(FL_WHEN_CHANGED); Fl_Group::current()->resizable(wComment); wComment->buffer(new Fl_Text_Buffer()); wComment->callback((Fl_Callback*)comment_cb); } // Fl_Text_Editor* wComment o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(95, 223, 310, 82); o->box(FL_FLAT_BOX); { wCallback = new CodeEditor(95, 225, 310, 80, "Callback:"); wCallback->tooltip("The callback function or code for the widget. Use the variable name \'o\' to " "access the Widget pointer and \'v\' to access the user value."); wCallback->box(FL_DOWN_BOX); wCallback->color(FL_BACKGROUND2_COLOR); wCallback->selection_color(FL_SELECTION_COLOR); wCallback->labeltype(FL_NORMAL_LABEL); wCallback->labelfont(1); wCallback->labelsize(11); wCallback->labelcolor(FL_FOREGROUND_COLOR); wCallback->textfont(4); wCallback->textsize(11); wCallback->callback((Fl_Callback*)callback_cb); wCallback->align(Fl_Align(FL_ALIGN_LEFT)); wCallback->when(FL_WHEN_RELEASE); Fl_Group::current()->resizable(wCallback); } // CodeEditor* wCallback o->end(); } // Fl_Group* o o->end(); Fl_Group::current()->resizable(o); } // Fl_Tile* o { wp_cpp_callback = new Fl_Group(95, 310, 310, 20, "User Data:"); wp_cpp_callback->labelfont(1); wp_cpp_callback->labelsize(11); wp_cpp_callback->callback((Fl_Callback*)propagate_load); wp_cpp_callback->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Input* o = new Fl_Input(95, 310, 158, 20); o->tooltip("The user data to pass into the callback code."); o->labelfont(1); o->labelsize(11); o->textfont(4); o->textsize(11); o->callback((Fl_Callback*)user_data_cb); Fl_Group::current()->resizable(o); } // Fl_Input* o { Fl_Menu_Button* o = new Fl_Menu_Button(260, 310, 145, 20, "When"); o->tooltip("When to call the callback function."); o->box(FL_THIN_UP_BOX); o->down_box(FL_BORDER_BOX); o->labelfont(1); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)when_cb); o->when(FL_WHEN_CHANGED); o->menu(whenmenu); } // Fl_Menu_Button* o wp_cpp_callback->end(); } // Fl_Group* wp_cpp_callback { Fl_Group* o = new Fl_Group(95, 332, 310, 26, "Type:"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Input_Choice* o = new Fl_Input_Choice(95, 335, 158, 20); o->tooltip("The type of the user data."); o->labelfont(1); o->labelsize(11); o->textfont(4); o->textsize(11); o->callback((Fl_Callback*)user_data_type_cb); Fl_Group::current()->resizable(o); o->menu(menu_4); } // Fl_Input_Choice* o { w_when_box = new Fl_Box(260, 332, 145, 26, "FL_WHEN_NEVER"); w_when_box->box(FL_FLAT_BOX); w_when_box->selection_color((Fl_Color)1); w_when_box->labelsize(8); w_when_box->align(Fl_Align(193|FL_ALIGN_INSIDE)); } // Fl_Box* w_when_box o->end(); } // Fl_Group* o wp_cpp_tab->end(); } // Fl_Group* wp_cpp_tab { widget_tab_grid_child = new Fl_Group(10, 30, 400, 330, "Grid Child"); widget_tab_grid_child->labelsize(11); widget_tab_grid_child->callback((Fl_Callback*)propagate_load); widget_tab_grid_child->hide(); { Fl_Group* o = new Fl_Group(95, 60, 315, 20, "Location:"); o->box(FL_FLAT_BOX); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { widget_grid_row_input = new Fluid_Coord_Input(95, 60, 40, 20, "Row:"); widget_grid_row_input->box(FL_DOWN_BOX); widget_grid_row_input->color(FL_BACKGROUND2_COLOR); widget_grid_row_input->selection_color(FL_SELECTION_COLOR); widget_grid_row_input->labeltype(FL_NORMAL_LABEL); widget_grid_row_input->labelfont(0); widget_grid_row_input->labelsize(11); widget_grid_row_input->labelcolor(FL_FOREGROUND_COLOR); widget_grid_row_input->textsize(11); widget_grid_row_input->callback((Fl_Callback*)grid_set_row_cb); widget_grid_row_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_grid_row_input->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_grid_row_input { Fl_Group* o = new Fl_Group(135, 60, 30, 20); { Fl_Button* o = new Fl_Button(135, 60, 15, 20, "-"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)grid_dec_row_cb); o->clear_visible_focus(); } // Fl_Button* o { Fl_Button* o = new Fl_Button(150, 60, 15, 20, "+"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)grid_inc_row_cb); o->clear_visible_focus(); } // Fl_Button* o o->end(); } // Fl_Group* o { widget_grid_col_input = new Fluid_Coord_Input(175, 60, 40, 20, "Column:"); widget_grid_col_input->box(FL_DOWN_BOX); widget_grid_col_input->color(FL_BACKGROUND2_COLOR); widget_grid_col_input->selection_color(FL_SELECTION_COLOR); widget_grid_col_input->labeltype(FL_NORMAL_LABEL); widget_grid_col_input->labelfont(0); widget_grid_col_input->labelsize(11); widget_grid_col_input->labelcolor(FL_FOREGROUND_COLOR); widget_grid_col_input->textsize(11); widget_grid_col_input->callback((Fl_Callback*)grid_set_col_cb); widget_grid_col_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_grid_col_input->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_grid_col_input { Fl_Group* o = new Fl_Group(215, 60, 30, 20); { Fl_Button* o = new Fl_Button(215, 60, 15, 20, "-"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)grid_dec_col_cb); o->clear_visible_focus(); } // Fl_Button* o { Fl_Button* o = new Fl_Button(230, 60, 15, 20, "+"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)grid_inc_col_cb); o->clear_visible_focus(); } // Fl_Button* o o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(395, 60, 1, 20); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o { widget_grid_transient = new Fl_Box(250, 60, 80, 20, "TRANSIENT"); widget_grid_transient->labelsize(11); widget_grid_transient->labelcolor((Fl_Color)1); widget_grid_transient->callback((Fl_Callback*)cb_widget_grid_transient); } // Fl_Box* widget_grid_transient { widget_grid_unlinked = new Fl_Box(250, 60, 80, 20, "UNLINKED"); widget_grid_unlinked->labelsize(11); widget_grid_unlinked->labelcolor((Fl_Color)1); widget_grid_unlinked->hide(); } // Fl_Box* widget_grid_unlinked o->end(); } // Fl_Group* o { wp_gridc_align = new Fl_Group(95, 100, 315, 20, "Align:"); wp_gridc_align->labelfont(1); wp_gridc_align->labelsize(11); wp_gridc_align->callback((Fl_Callback*)propagate_load); wp_gridc_align->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Choice* o = new Fl_Choice(95, 100, 115, 20, "Horizontal"); o->down_box(FL_BORDER_BOX); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)grid_align_horizontal_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->menu(menu_Horizontal); } // Fl_Choice* o { Fl_Choice* o = new Fl_Choice(215, 100, 115, 20, "Vertical"); o->down_box(FL_BORDER_BOX); o->labelsize(11); o->textsize(11); o->callback((Fl_Callback*)grid_align_vertical_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->menu(menu_Vertical); } // Fl_Choice* o { Fl_Box* o = new Fl_Box(395, 100, 1, 20); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_gridc_align->end(); } // Fl_Group* wp_gridc_align { wp_gridc_size = new Fl_Group(95, 135, 315, 20, "Min. Size:"); wp_gridc_size->labelfont(1); wp_gridc_size->labelsize(11); wp_gridc_size->callback((Fl_Callback*)propagate_load); wp_gridc_size->align(Fl_Align(FL_ALIGN_LEFT)); { Fluid_Coord_Input* o = new Fluid_Coord_Input(95, 135, 55, 20, "Width:"); o->box(FL_DOWN_BOX); o->color(FL_BACKGROUND2_COLOR); o->selection_color(FL_SELECTION_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(11); o->labelcolor(FL_FOREGROUND_COLOR); o->textsize(11); o->callback((Fl_Callback*)grid_set_min_wdt_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* o { Fluid_Coord_Input* o = new Fluid_Coord_Input(155, 135, 55, 20, "Height:"); o->box(FL_DOWN_BOX); o->color(FL_BACKGROUND2_COLOR); o->selection_color(FL_SELECTION_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(11); o->labelcolor(FL_FOREGROUND_COLOR); o->textsize(11); o->callback((Fl_Callback*)grid_set_min_hgt_cb); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* o { Fl_Box* o = new Fl_Box(395, 135, 1, 20); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_gridc_size->end(); } // Fl_Group* wp_gridc_size { Fl_Group* o = new Fl_Group(95, 170, 315, 20, "Span:"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { widget_grid_rowspan_input = new Fluid_Coord_Input(95, 170, 40, 20, "Row Span:"); widget_grid_rowspan_input->box(FL_DOWN_BOX); widget_grid_rowspan_input->color(FL_BACKGROUND2_COLOR); widget_grid_rowspan_input->selection_color(FL_SELECTION_COLOR); widget_grid_rowspan_input->labeltype(FL_NORMAL_LABEL); widget_grid_rowspan_input->labelfont(0); widget_grid_rowspan_input->labelsize(11); widget_grid_rowspan_input->labelcolor(FL_FOREGROUND_COLOR); widget_grid_rowspan_input->textsize(11); widget_grid_rowspan_input->callback((Fl_Callback*)grid_set_rowspan_cb); widget_grid_rowspan_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_grid_rowspan_input->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_grid_rowspan_input { Fl_Group* o = new Fl_Group(135, 170, 30, 20); { Fl_Button* o = new Fl_Button(135, 170, 15, 20, "-"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)grid_dec_rowspan_cb); o->clear_visible_focus(); } // Fl_Button* o { Fl_Button* o = new Fl_Button(150, 170, 15, 20, "+"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)grid_inc_rowspan_cb); o->clear_visible_focus(); } // Fl_Button* o o->end(); } // Fl_Group* o { widget_grid_colspan_input = new Fluid_Coord_Input(175, 170, 40, 20, "Col. Span:"); widget_grid_colspan_input->box(FL_DOWN_BOX); widget_grid_colspan_input->color(FL_BACKGROUND2_COLOR); widget_grid_colspan_input->selection_color(FL_SELECTION_COLOR); widget_grid_colspan_input->labeltype(FL_NORMAL_LABEL); widget_grid_colspan_input->labelfont(0); widget_grid_colspan_input->labelsize(11); widget_grid_colspan_input->labelcolor(FL_FOREGROUND_COLOR); widget_grid_colspan_input->textsize(11); widget_grid_colspan_input->callback((Fl_Callback*)grid_set_colspan_cb); widget_grid_colspan_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_grid_colspan_input->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_grid_colspan_input { Fl_Group* o = new Fl_Group(215, 170, 30, 20); { Fl_Button* o = new Fl_Button(215, 170, 15, 20, "-"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)grid_dec_colspan_cb); o->clear_visible_focus(); } // Fl_Button* o { Fl_Button* o = new Fl_Button(230, 170, 15, 20, "+"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)grid_inc_colspan_cb); o->clear_visible_focus(); } // Fl_Button* o o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(395, 170, 1, 20); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(95, 350, 300, 5); o->labelsize(11); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o widget_tab_grid_child->end(); } // Fl_Group* widget_tab_grid_child { widget_tab_grid = new Fl_Group(10, 30, 400, 330, "Grid"); widget_tab_grid->labelsize(11); widget_tab_grid->callback((Fl_Callback*)propagate_load); widget_tab_grid->hide(); { Fl_Group* o = new Fl_Group(95, 60, 315, 20, "Grid Layout:"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { widget_grid_rows = new Fluid_Coord_Input(95, 60, 40, 20, "Rows:"); widget_grid_rows->tooltip("Number of horizontal rows in the Grid group"); widget_grid_rows->box(FL_DOWN_BOX); widget_grid_rows->color(FL_BACKGROUND2_COLOR); widget_grid_rows->selection_color(FL_SELECTION_COLOR); widget_grid_rows->labeltype(FL_NORMAL_LABEL); widget_grid_rows->labelfont(0); widget_grid_rows->labelsize(11); widget_grid_rows->labelcolor(FL_FOREGROUND_COLOR); widget_grid_rows->textsize(11); widget_grid_rows->callback((Fl_Callback*)cb_widget_grid_rows); widget_grid_rows->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_grid_rows->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_grid_rows { Fl_Group* o = new Fl_Group(135, 60, 30, 20); { Fl_Button* o = new Fl_Button(135, 60, 15, 20, "-"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)cb_2); o->clear_visible_focus(); } // Fl_Button* o { Fl_Button* o = new Fl_Button(150, 60, 15, 20, "+"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)cb_3); o->clear_visible_focus(); } // Fl_Button* o o->end(); } // Fl_Group* o { widget_grid_cols = new Fluid_Coord_Input(175, 60, 40, 20, "Columns:"); widget_grid_cols->tooltip("Number of vertical columns in the Grid group"); widget_grid_cols->box(FL_DOWN_BOX); widget_grid_cols->color(FL_BACKGROUND2_COLOR); widget_grid_cols->selection_color(FL_SELECTION_COLOR); widget_grid_cols->labeltype(FL_NORMAL_LABEL); widget_grid_cols->labelfont(0); widget_grid_cols->labelsize(11); widget_grid_cols->labelcolor(FL_FOREGROUND_COLOR); widget_grid_cols->textsize(11); widget_grid_cols->callback((Fl_Callback*)cb_widget_grid_cols); widget_grid_cols->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_grid_cols->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_grid_cols { Fl_Group* o = new Fl_Group(215, 60, 30, 20); { Fl_Button* o = new Fl_Button(215, 60, 15, 20, "-"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)cb_4); o->clear_visible_focus(); } // Fl_Button* o { Fl_Button* o = new Fl_Button(230, 60, 15, 20, "+"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)cb_5); o->clear_visible_focus(); } // Fl_Button* o o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(396, 60, 0, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { wp_grid_margin = new Fl_Group(95, 100, 315, 20, "Margins:"); wp_grid_margin->labelfont(1); wp_grid_margin->labelsize(11); wp_grid_margin->callback((Fl_Callback*)propagate_load); wp_grid_margin->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Value_Input* o = new Fl_Value_Input(95, 100, 55, 20, "Left:"); o->tooltip("Left margin in group."); o->labelsize(11); o->maximum(1000); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Left); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(155, 100, 55, 20, "Top:"); o->tooltip("Top margin in group."); o->labelsize(11); o->maximum(1000); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Top); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(215, 100, 55, 20, "Right:"); o->tooltip("Right margin in group."); o->labelsize(11); o->maximum(1000); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Right); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(275, 100, 55, 20, "Bottom:"); o->tooltip("Bottom margin in group."); o->labelsize(11); o->maximum(1000); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Bottom); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(396, 100, 0, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_grid_margin->end(); } // Fl_Group* wp_grid_margin { wp_grid_gaps = new Fl_Group(95, 135, 315, 20, "Gaps:"); wp_grid_gaps->labelfont(1); wp_grid_gaps->labelsize(11); wp_grid_gaps->callback((Fl_Callback*)propagate_load); wp_grid_gaps->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Value_Input* o = new Fl_Value_Input(95, 135, 55, 20, "Row:"); o->tooltip("Gap between children."); o->labelsize(11); o->maximum(1000); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Row); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(155, 135, 55, 20, "Col:"); o->tooltip("Gap between children."); o->labelsize(11); o->maximum(1000); o->step(1); o->textsize(11); o->callback((Fl_Callback*)cb_Col); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(396, 135, 0, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o wp_grid_gaps->end(); } // Fl_Group* wp_grid_gaps { Fl_Group* o = new Fl_Group(95, 175, 315, 20, "Row:"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)cb_Row1); o->align(Fl_Align(FL_ALIGN_LEFT)); { widget_grid_curr_row = new Fluid_Coord_Input(95, 175, 40, 20, "Index"); widget_grid_curr_row->box(FL_DOWN_BOX); widget_grid_curr_row->color(FL_BACKGROUND2_COLOR); widget_grid_curr_row->selection_color(FL_SELECTION_COLOR); widget_grid_curr_row->labeltype(FL_NORMAL_LABEL); widget_grid_curr_row->labelfont(0); widget_grid_curr_row->labelsize(11); widget_grid_curr_row->labelcolor(FL_FOREGROUND_COLOR); widget_grid_curr_row->textsize(11); widget_grid_curr_row->callback((Fl_Callback*)cb_widget_grid_curr_row); widget_grid_curr_row->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_grid_curr_row->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_grid_curr_row { Fl_Group* o = new Fl_Group(135, 175, 30, 20); o->callback((Fl_Callback*)propagate_load); { Fl_Button* o = new Fl_Button(135, 175, 15, 20, "-"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)cb_6); o->clear_visible_focus(); } // Fl_Button* o { Fl_Button* o = new Fl_Button(150, 175, 15, 20, "+"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)cb_7); o->clear_visible_focus(); } // Fl_Button* o o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(165, 175, 15, 20, ":"); o->labelsize(11); } // Fl_Box* o { widget_grid_curr_row_attributes = new Fl_Group(180, 175, 175, 20); widget_grid_curr_row_attributes->callback((Fl_Callback*)propagate_load); { Fluid_Coord_Input* o = new Fluid_Coord_Input(180, 175, 55, 20, "Height:"); o->box(FL_DOWN_BOX); o->color(FL_BACKGROUND2_COLOR); o->selection_color(FL_SELECTION_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(11); o->labelcolor(FL_FOREGROUND_COLOR); o->textsize(11); o->callback((Fl_Callback*)cb_Height); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* o { Fluid_Coord_Input* o = new Fluid_Coord_Input(240, 175, 55, 20, "Weight:"); o->box(FL_DOWN_BOX); o->color(FL_BACKGROUND2_COLOR); o->selection_color(FL_SELECTION_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(11); o->labelcolor(FL_FOREGROUND_COLOR); o->textsize(11); o->callback((Fl_Callback*)cb_Weight); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* o { Fluid_Coord_Input* o = new Fluid_Coord_Input(300, 175, 55, 20, "Gap:"); o->box(FL_DOWN_BOX); o->color(FL_BACKGROUND2_COLOR); o->selection_color(FL_SELECTION_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(11); o->labelcolor(FL_FOREGROUND_COLOR); o->textsize(11); o->callback((Fl_Callback*)cb_Gap); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* o widget_grid_curr_row_attributes->end(); } // Fl_Group* widget_grid_curr_row_attributes { Fl_Box* o = new Fl_Box(400, 175, 1, 20); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(95, 210, 315, 20, "Column:"); o->labelfont(1); o->labelsize(11); o->callback((Fl_Callback*)propagate_load); o->align(Fl_Align(FL_ALIGN_LEFT)); { widget_grid_curr_col = new Fluid_Coord_Input(95, 210, 40, 20, "Index"); widget_grid_curr_col->box(FL_DOWN_BOX); widget_grid_curr_col->color(FL_BACKGROUND2_COLOR); widget_grid_curr_col->selection_color(FL_SELECTION_COLOR); widget_grid_curr_col->labeltype(FL_NORMAL_LABEL); widget_grid_curr_col->labelfont(0); widget_grid_curr_col->labelsize(11); widget_grid_curr_col->labelcolor(FL_FOREGROUND_COLOR); widget_grid_curr_col->textsize(11); widget_grid_curr_col->callback((Fl_Callback*)cb_widget_grid_curr_col); widget_grid_curr_col->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_grid_curr_col->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* widget_grid_curr_col { Fl_Group* o = new Fl_Group(135, 210, 30, 20); { Fl_Button* o = new Fl_Button(135, 210, 15, 20, "-"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)cb_8); o->clear_visible_focus(); } // Fl_Button* o { Fl_Button* o = new Fl_Button(150, 210, 15, 20, "+"); o->compact(1); o->labelsize(11); o->callback((Fl_Callback*)cb_9); o->clear_visible_focus(); } // Fl_Button* o o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(165, 210, 15, 20, ":"); o->labelsize(11); } // Fl_Box* o { widget_grid_curr_col_attributes = new Fl_Group(180, 210, 175, 20); widget_grid_curr_col_attributes->callback((Fl_Callback*)propagate_load); { Fluid_Coord_Input* o = new Fluid_Coord_Input(180, 210, 55, 20, "Width:"); o->box(FL_DOWN_BOX); o->color(FL_BACKGROUND2_COLOR); o->selection_color(FL_SELECTION_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(11); o->labelcolor(FL_FOREGROUND_COLOR); o->textsize(11); o->callback((Fl_Callback*)cb_Width); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* o { Fluid_Coord_Input* o = new Fluid_Coord_Input(240, 210, 55, 20, "Weight:"); o->box(FL_DOWN_BOX); o->color(FL_BACKGROUND2_COLOR); o->selection_color(FL_SELECTION_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(11); o->labelcolor(FL_FOREGROUND_COLOR); o->textsize(11); o->callback((Fl_Callback*)cb_Weight1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* o { Fluid_Coord_Input* o = new Fluid_Coord_Input(300, 210, 55, 20, "Gap:"); o->box(FL_DOWN_BOX); o->color(FL_BACKGROUND2_COLOR); o->selection_color(FL_SELECTION_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(11); o->labelcolor(FL_FOREGROUND_COLOR); o->textsize(11); o->callback((Fl_Callback*)cb_Gap1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->when(FL_WHEN_RELEASE); } // Fluid_Coord_Input* o widget_grid_curr_col_attributes->end(); } // Fl_Group* widget_grid_curr_col_attributes { Fl_Box* o = new Fl_Box(400, 210, 1, 20); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(95, 350, 300, 5); o->labelsize(11); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o widget_tab_grid->end(); } // Fl_Group* widget_tab_grid o->show(); widget_tabs->end(); Fl_Group::current()->resizable(widget_tabs); } // Fl_Tabs* widget_tabs { Fl_Tabs* o = widget_tabs_repo = new Fl_Tabs(10, 10, 400, 350); widget_tabs_repo->hide(); { Fl_Group* o = new Fl_Group(10, 30, 400, 330); o->end(); Fl_Group::current()->resizable(o); } // Fl_Group* o o->hide(); widget_tabs_repo->end(); } // Fl_Tabs* widget_tabs_repo { Fl_Group* o = new Fl_Group(10, 370, 400, 20); o->labelsize(11); { wLiveMode = new Fl_Button(10, 370, 80, 20, "Live &Resize"); wLiveMode->tooltip("Create a live duplicate of the selected widgets to test resizing and menu beh" "avior."); wLiveMode->type(1); wLiveMode->labelsize(10); wLiveMode->callback((Fl_Callback*)live_mode_cb); } // Fl_Button* wLiveMode { overlay_button = new Fl_Button(94, 370, 80, 20, "Hide &Overlays"); overlay_button->tooltip("Hide the widget overlay box."); overlay_button->labelsize(10); overlay_button->callback((Fl_Callback*)overlay_cb); } // Fl_Button* overlay_button { // Hidden resizable box Fl_Box* o = new Fl_Box(258, 370, 72, 20); o->labelsize(11); o->hide(); Fl_Group::current()->resizable(o); } // Fl_Box* o { Fl_Return_Button* o = new Fl_Return_Button(330, 370, 80, 20, "Close"); o->labelsize(11); o->callback((Fl_Callback*)ok_cb); } // Fl_Return_Button* o o->end(); } // Fl_Group* o o->size_range(420, 400); o->size_range(o->w(), o->h()); o->end(); } // Fl_Double_Window* o return w; } fltk-1.4.3/fluid/codeview_panel.h0000644000175000017500000000340415004135251017046 0ustar albrechtalbrecht// // Code dialogs for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #ifndef codeview_panel_h #define codeview_panel_h #include extern int cv_code_choice; void update_codeview_position(); void update_codeview_position_cb(class Fl_Tabs*, void*); void update_codeview_cb(class Fl_Button*, void*); void update_codeview_timer(void*); void codeview_defer_update(); void codeview_toggle_visibility(); #include extern void toggle_codeview_cb(Fl_Double_Window*, void*); extern Fl_Double_Window *codeview_panel; #include extern Fl_Tabs *cv_tab; #include extern Fl_Group *cv_source_tab; #include "CodeEditor.h" extern CodeViewer *cv_source; extern CodeViewer *cv_header; extern TextViewer *cv_strings; extern TextViewer *cv_project; extern Fl_Group *cv_find_row; #include extern Fl_Button *cv_find_text_case; #include extern Fl_Input *cv_find_text; #include extern Fl_Group *cv_settings_row; #include extern Fl_Light_Button *cv_autorefresh; extern Fl_Light_Button *cv_autoposition; #include extern Fl_Choice *cv_code_choice_w; extern void toggle_codeview_b_cb(Fl_Button*, void*); Fl_Double_Window* make_codeview(); extern Fl_Menu_Item menu_cv_code_choice_w[]; #endif // fltk-1.4.3/fluid/function_panel.h0000644000175000017500000000773215004135251017076 0ustar albrechtalbrecht// // Code dialogs for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #ifndef function_panel_h #define function_panel_h #include #include extern Fl_Double_Window *function_panel; #include #include extern Fl_Choice *f_public_member_choice; extern Fl_Choice *f_public_choice; #include extern Fl_Light_Button *f_c_button; #include #include extern Fl_Input *f_name_input; extern Fl_Input *f_return_type_input; #include extern Fl_Text_Editor *f_comment_input; #include extern Fl_Return_Button *f_panel_ok; #include extern Fl_Button *f_panel_cancel; Fl_Double_Window* make_function_panel(); extern Fl_Menu_Item menu_f_public_member_choice[]; extern Fl_Menu_Item menu_f_public_choice[]; extern Fl_Double_Window *code_panel; #include "CodeEditor.h" extern CodeEditor *code_input; extern Fl_Return_Button *code_panel_ok; extern Fl_Button *code_panel_cancel; Fl_Double_Window* make_code_panel(); extern Fl_Double_Window *codeblock_panel; extern Fl_Input *code_before_input; extern Fl_Input *code_after_input; extern Fl_Return_Button *codeblock_panel_ok; extern Fl_Button *codeblock_panel_cancel; Fl_Double_Window* make_codeblock_panel(); extern Fl_Double_Window *declblock_panel; extern Fl_Input *declblock_before_input; extern Fl_Input *declblock_after_input; #include extern Fl_Check_Button *declblock_code_source; extern Fl_Check_Button *declblock_static_source; extern Fl_Check_Button *declblock_code_header; extern Fl_Check_Button *declblock_static_header; extern Fl_Text_Editor *declblock_comment_input; extern Fl_Return_Button *declblock_panel_ok; extern Fl_Button *declblock_panel_cancel; Fl_Double_Window* make_declblock_panel(); extern Fl_Double_Window *decl_panel; extern Fl_Choice *decl_choice; extern Fl_Choice *decl_class_choice; #include extern CodeEditor *decl_input; extern Fl_Text_Editor *decl_comment_input; extern Fl_Return_Button *decl_panel_ok; extern Fl_Button *decl_panel_cancel; Fl_Double_Window* make_decl_panel(); extern Fl_Menu_Item menu_decl_choice[]; extern Fl_Menu_Item menu_decl_class_choice[]; extern Fl_Double_Window *data_panel; extern Fl_Choice *data_choice; extern Fl_Choice *data_class_choice; extern Fl_Choice *data_mode; extern Fl_Input *data_input; extern Fl_Input *data_filename; extern Fl_Button *data_filebrowser; extern Fl_Text_Editor *data_comment_input; extern Fl_Return_Button *data_panel_ok; extern Fl_Button *data_panel_cancel; Fl_Double_Window* make_data_panel(); extern Fl_Menu_Item menu_data_choice[]; extern Fl_Menu_Item menu_data_class_choice[]; extern Fl_Menu_Item menu_data_mode[]; extern Fl_Double_Window *class_panel; extern Fl_Light_Button *c_public_button; extern Fl_Input *c_name_input; extern Fl_Input *c_subclass_input; extern Fl_Text_Editor *c_comment_input; extern Fl_Return_Button *c_panel_ok; extern Fl_Button *c_panel_cancel; Fl_Double_Window* make_class_panel(); extern Fl_Double_Window *comment_panel; extern Fl_Text_Editor *comment_input; extern Fl_Return_Button *comment_panel_ok; extern Fl_Button *comment_panel_cancel; extern Fl_Light_Button *comment_in_source; extern Fl_Light_Button *comment_in_header; #include extern Fl_Menu_Button *comment_predefined; extern Fl_Button *comment_load; Fl_Double_Window* make_comment_panel(); void type_make_cb(Fl_Widget*,void*d); #include extern Fl_Window *widgetbin_panel; Fl_Window* make_widgetbin(); #endif // fltk-1.4.3/fluid/Fl_Window_Type.cxx0000644000175000017500000013725015004135251017335 0ustar albrechtalbrecht// // Window type code file for the Fast Light Tool Kit (FLTK). // // The widget describing an Fl_Window. This is also all the code // for interacting with the overlay, which allows the user to // select, move, and resize the children widgets. // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Window_Type.h" #include "Fl_Group_Type.h" #include "Fl_Grid_Type.h" #include "fluid.h" #include "widget_browser.h" #include "undo.h" #include "settings_panel.h" #include "file.h" #include "code.h" #include "widget_panel.h" #include "factory.h" #include "Fd_Snap_Action.h" #include #include #include #include #include #include #include #include #include #include "../src/flstring.h" #include #include #include extern Fl_Window *the_panel; extern void draw_width(int x, int y, int r, Fl_Align a); extern void draw_height(int x, int y, int b, Fl_Align a); extern Fl_Preferences fluid_prefs; // Update the XYWH values in the widget panel... static void update_xywh() { if (current_widget && current_widget->is_widget()) { Fl_Widget *o = ((Fl_Widget_Type *)current_widget)->o; widget_x_input->value(o->x()); widget_y_input->value(o->y()); widget_w_input->value(o->w()); widget_h_input->value(o->h()); if (Fl_Flex_Type::parent_is_flex(current_widget)) { widget_flex_size->value(Fl_Flex_Type::size(current_widget)); widget_flex_fixed->value(Fl_Flex_Type::is_fixed(current_widget)); } } } void i18n_type_cb(Fl_Choice *c, void *v) { if (v == LOAD) { c->value(g_project.i18n_type); } else { undo_checkpoint(); g_project.i18n_type = static_cast(c->value()); set_modflag(1); } switch (g_project.i18n_type) { case FD_I18N_NONE : /* None */ i18n_gnu_group->hide(); i18n_posix_group->hide(); break; case FD_I18N_GNU : /* GNU gettext */ i18n_gnu_group->show(); i18n_posix_group->hide(); break; case FD_I18N_POSIX : /* POSIX cat */ i18n_gnu_group->hide(); i18n_posix_group->show(); break; } // make sure that the outside labels are redrawn too. w_settings_i18n_tab->redraw(); } void show_grid_cb(Fl_Widget *, void *) { settings_window->show(); w_settings_tabs->value(w_settings_layout_tab); } void show_settings_cb(Fl_Widget *, void *) { settings_window->hotspot(settings_window); settings_window->show(); } //////////////////////////////////////////////////////////////// Fl_Menu_Item window_type_menu[] = { {"Single",0,0,(void*)FL_WINDOW}, {"Double",0,0,(void*)(FL_DOUBLE_WINDOW)}, {0}}; static int overlays_invisible; // The following Fl_Widget is used to simulate the windows. It has // an overlay for the fluid ui, and special-cases the FL_NO_BOX. class Overlay_Window : public Fl_Overlay_Window { void draw() FL_OVERRIDE; void draw_overlay() FL_OVERRIDE; static void close_cb(Overlay_Window *self, void*); public: Fl_Window_Type *window; int handle(int) FL_OVERRIDE; Overlay_Window(int W,int H) : Fl_Overlay_Window(W,H) { Fl_Group::current(0); callback((Fl_Callback*)close_cb); } void resize(int,int,int,int) FL_OVERRIDE; uchar *read_image(int &ww, int &hh); }; /** \brief User closes the window, so we mark the .fl file as changed. Mark the .fl file a changed, but don;t mark the source files as changed. \param self pointer to this window */ void Overlay_Window::close_cb(Overlay_Window *self, void*) { if (self->visible()) set_modflag(1, -2); self->hide(); } // Use this when drawing flat boxes while editing, so users can see the outline, // even if the group and its parent have the same color. static void fd_flat_box_ghosted(int x, int y, int w, int h, Fl_Color c) { fl_rectf(x, y, w, h, Fl::box_color(c)); fl_rect(x, y, w, h, Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, c, .1f))); } void Overlay_Window::draw() { const int CHECKSIZE = 8; // see if box is clear or a frame or rounded: if ((damage()&FL_DAMAGE_ALL) && (!box() || (box()>=4&&!(box()&2)) || box()>=_FL_ROUNDED_BOX)) { // if so, draw checkerboard so user can see what areas are clear: for (int Y = 0; Y < h(); Y += CHECKSIZE) for (int X = 0; X < w(); X += CHECKSIZE) { fl_color(((Y/(2*CHECKSIZE))&1) != ((X/(2*CHECKSIZE))&1) ? FL_WHITE : FL_BLACK); fl_rectf(X,Y,CHECKSIZE,CHECKSIZE); } } if (show_ghosted_outline) { Fl_Box_Draw_F *old_flat_box = Fl::get_boxtype(FL_FLAT_BOX); Fl::set_boxtype(FL_FLAT_BOX, fd_flat_box_ghosted, 0, 0, 0, 0); Fl_Overlay_Window::draw(); Fl::set_boxtype(FL_FLAT_BOX, old_flat_box, 0, 0, 0, 0); } else { Fl_Overlay_Window::draw(); } } extern Fl_Window *main_window; // Read an image of the overlay window uchar *Overlay_Window::read_image(int &ww, int &hh) { // Create an off-screen buffer for the window... //main_window->make_current(); make_current(); ww = w(); hh = h(); Fl_Offscreen offscreen = fl_create_offscreen(ww, hh); uchar *pixels; // Redraw the window into the offscreen buffer... fl_begin_offscreen(offscreen); if (!shown()) image(Fl::scheme_bg_); redraw(); draw(); // Read the screen image... pixels = fl_read_image(0, 0, 0, ww, hh); fl_end_offscreen(); // Cleanup and return... fl_delete_offscreen(offscreen); main_window->make_current(); return pixels; } void Overlay_Window::draw_overlay() { window->draw_overlay(); } int Overlay_Window::handle(int e) { int ret = window->handle(e); if (ret==0) { switch (e) { case FL_SHOW: case FL_HIDE: ret = Fl_Overlay_Window::handle(e); } } return ret; } /** Make and add a new Window node. \param[in] strategy is Strategy::AS_LAST_CHILD or Strategy::AFTER_CURRENT \return new node */ Fl_Type *Fl_Window_Type::make(Strategy strategy) { Fl_Type *anchor = Fl_Type::current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && (!p->is_code_block() || p->is_a(ID_Widget_Class))) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } if (!p) { fl_message("Please select a function"); return 0; } Fl_Window_Type *myo = new Fl_Window_Type(); if (!this->o) {// template widget this->o = new Fl_Window(100,100); Fl_Group::current(0); } myo->factory = this; myo->drag = 0; myo->numselected = 0; Overlay_Window *w = new Overlay_Window(100, 100); w->size_range(10, 10); w->window = myo; myo->o = w; myo->add(anchor, strategy); myo->modal = 0; myo->non_modal = 0; return myo; } void Fl_Window_Type::add_child(Fl_Type* cc, Fl_Type* before) { if (!cc->is_widget()) return; Fl_Widget_Type* c = (Fl_Widget_Type*)cc; Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; ((Fl_Window*)o)->insert(*(c->o), b); o->redraw(); } void Fl_Window_Type::remove_child(Fl_Type* cc) { Fl_Widget_Type* c = (Fl_Widget_Type*)cc; ((Fl_Window*)o)->remove(c->o); o->redraw(); } void Fl_Window_Type::move_child(Fl_Type* cc, Fl_Type* before) { Fl_Widget_Type* c = (Fl_Widget_Type*)cc; ((Fl_Window*)o)->remove(c->o); Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; ((Fl_Window*)o)->insert(*(c->o), b); o->redraw(); } //////////////////////////////////////////////////////////////// /** \brief Show the Window Type editor window without setting the modified flag. \see Fl_Window_Type::open() */ void Fl_Window_Type::open_() { Overlay_Window *w = (Overlay_Window *)o; if (w->shown()) { w->show(); Fl_Widget_Type::open(); } else { Fl_Widget *p = w->resizable(); if (!p) w->resizable(w); w->show(); w->resizable(p); } w->image(Fl::scheme_bg_); } /** \brief Show the Window Type editor window and set the modified flag if needed. Double-click on window widget shows the window, or if already shown, it shows the control panel. \see Fl_Window_Type::open_() */ void Fl_Window_Type::open() { Overlay_Window *w = (Overlay_Window *)o; if (!w->visible()) { set_modflag(1, -2); } open_(); } // Read an image of the window uchar *Fl_Window_Type::read_image(int &ww, int &hh) { Overlay_Window *w = (Overlay_Window *)o; int hidden = !w->shown(); w->show(); // make it the front window // Read the screen image... uchar *idata = w->read_image(ww, hh); if (hidden) w->hide(); return idata; } void Fl_Window_Type::ideal_size(int &w, int &h) { w = 480; h = 320; if (main_window) { int sx, sy, sw, sh; Fl_Window *win = main_window; int screen = Fl::screen_num(win->x(), win->y()); Fl::screen_work_area(sx, sy, sw, sh, screen); w = fd_min(w, sw*3/4); h = fd_min(h, sh*3/4); } Fd_Snap_Action::better_size(w, h); } // control panel items: void modal_cb(Fl_Light_Button* i, void* v) { if (v == LOAD) { if (!current_widget->is_a(ID_Window)) {i->hide(); return;} i->show(); i->value(((Fl_Window_Type *)current_widget)->modal); } else { undo_checkpoint(); ((Fl_Window_Type *)current_widget)->modal = i->value(); set_modflag(1); } } void non_modal_cb(Fl_Light_Button* i, void* v) { if (v == LOAD) { if (!current_widget->is_a(ID_Window)) {i->hide(); return;} i->show(); i->value(((Fl_Window_Type *)current_widget)->non_modal); } else { undo_checkpoint(); ((Fl_Window_Type *)current_widget)->non_modal = i->value(); set_modflag(1); } } void border_cb(Fl_Light_Button* i, void* v) { if (v == LOAD) { if (!current_widget->is_a(ID_Window)) {i->hide(); return;} i->show(); i->value(((Fl_Window*)(current_widget->o))->border()); } else { undo_checkpoint(); ((Fl_Window*)(current_widget->o))->border(i->value()); set_modflag(1); } } void xclass_cb(Fl_Input* i, void* v) { if (v == LOAD) { if (current_widget->is_a(ID_Window)) { i->show(); i->parent()->show(); i->value(((Fl_Window_Type *)current_widget)->xclass); } else { i->hide(); i->parent()->hide(); // hides the "X Class:" label as well } } else { int mod = 0; undo_checkpoint(); for (Fl_Type *o = Fl_Type::first; o; o = o->next) { if (o->selected && o->is_a(ID_Window)) { mod = 1; Fl_Window_Type *wt = (Fl_Window_Type *)o; storestring(i->value(), wt->xclass); ((Fl_Window*)(wt->o))->xclass(wt->xclass); } } if (mod) set_modflag(1); } } //////////////////////////////////////////////////////////////// void Fl_Window_Type::setlabel(const char *n) { if (o) ((Fl_Window *)o)->label(n); } // make() is called on this widget when user picks window off New menu: Fl_Window_Type Fl_Window_type; // Resize from window manager... void Overlay_Window::resize(int X,int Y,int W,int H) { // Make sure we don't create undo checkpoints if the window does not actually change. // Some WMs seem to send spurious resize events. if (X!=x() || Y!=y() || W!=w() || H!=h()) { // Set a checkpoint on the first resize event, ignore further resizes until // a different type of checkpoint is triggered. if (undo_checkpoint_once(kUndoWindowResize)) set_modflag(1); } Fl_Widget* t = resizable(); if (Fl_Type::allow_layout == 0) { resizable(0); } // do not set the mod flag if the window was not resized. In FLUID, all // windows are opened without a given x/y position, so modifying x/y // should not mark the project as dirty if (W!=w() || H!=h()) set_modflag(1); Fl_Overlay_Window::resize(X,Y,W,H); resizable(t); update_xywh(); } // calculate actual move by moving mouse position (mx,my) to // nearest multiple of gridsize, and snap to original position void Fl_Window_Type::newdx() { int mydx, mydy; mydx = mx-x1; mydy = my-y1; if (!(drag & (FD_DRAG | FD_BOX | FD_LEFT | FD_RIGHT))) { mydx = 0; dx = 0; } if (!(drag & (FD_DRAG | FD_BOX | FD_TOP | FD_BOTTOM))) { mydy = 0; dy = 0; } if (show_guides && (drag & (FD_DRAG|FD_TOP|FD_LEFT|FD_BOTTOM|FD_RIGHT))) { Fl_Type *selection = 0L; // special power for the first selected widget for (Fl_Type *q=next; q && q->level>level; q = q->next) { if (q->selected && q->is_true_widget()) { selection = q; break; } } Fd_Snap_Data data = { mydx, mydy, bx, by, br, bt, drag, 4, 4, mydx, mydy, (Fl_Widget_Type*)selection, this }; Fd_Snap_Action::check_all(data); if (data.x_dist < 4) mydx = data.dx_out; if (data.y_dist < 4) mydy = data.dy_out; } if (dx != mydx || dy != mydy) { dx = mydx; dy = mydy; ((Overlay_Window *)o)->redraw_overlay(); } } // Move a widget according to dx and dy calculated above void Fl_Window_Type::newposition(Fl_Widget_Type *myo,int &X,int &Y,int &R,int &T) { X = myo->o->x(); Y = myo->o->y(); R = X+myo->o->w(); T = Y+myo->o->h(); if (!drag) return; if (drag&FD_DRAG) { X += dx; Y += dy; R += dx; T += dy; } else { if (drag&FD_LEFT) { if (X==bx) { X += dx; } else { if (Xbr+dx) R = br+dx; } } if (drag&FD_BOTTOM) { if (T==bt) { T += dy; } else { if (T>bt+dx) T = bt+dx; } } } if (R h) { for (; yp < h; yp+=size) fl_line(x, y+yp, x+yp, y); for (; yp < w; yp+=size) fl_line(x+yp-h, y+h, x+yp, y); for (; yp < w+h; yp+=size) fl_line(x+yp-h, y+h, x+w, y+yp-w); } else { for (; yp < w; yp+=size) fl_line(x, y+yp, x+yp, y); for (; yp < h; yp+=size) fl_line(x, y+yp, x+w, y+yp-w); for (; yp < h+w; yp+=size) fl_line(x+yp-h, y+h, x+w, y+yp-w); } } /** \brief Draw a hatch pattern over all children that overlap the bounds of this box. \param[in] group check all children of this group \param[in] x, y, w, h bounding box of this group */ void Fl_Window_Type::draw_out_of_bounds(Fl_Widget_Type *group, int x, int y, int w, int h) { for (Fl_Type *p = group->next; p && p->level>group->level; p = p->next) { if (p->level == group->level+1 && p->is_true_widget()) { Fl_Widget *o = ((Fl_Widget_Type*)p)->o; if (o->x() < x) fd_hatch(o->x(), o->y(), x-o->x(), o->h()); if (o->y() < y) fd_hatch(o->x(), o->y(), o->w(), y-o->y()); if (o->x()+o->w() > x+w) fd_hatch(x+w, o->y(), (o->x()+o->w())-(x+w), o->h()); if (o->y()+o->h() > y+h) fd_hatch(o->x(), y+h, o->w(), (o->y()+o->h())-(y+h)); } } } /** \brief Draw a hatch pattern for all groups that have out of bounds children. */ void Fl_Window_Type::draw_out_of_bounds() { // get every group in the hierarchy, then draw any overlap of a direct child with that group fl_color(FL_DARK_RED); draw_out_of_bounds(this, 0, 0, o->w(), o->h()); for (Fl_Type *q=next; q && q->level>level; q = q->next) { // don't do this for Fl_Scroll (which we currently can't handle in FLUID anyway) if (q->is_a(ID_Group) && !q->is_a(ID_Scroll)) { Fl_Widget_Type *w = (Fl_Widget_Type*)q; draw_out_of_bounds(w, w->o->x(), w->o->y(), w->o->w(), w->o->h()); } } fl_color(FL_RED); } /** \brief Compare all children in the same level and hatch overlapping areas. */ void Fl_Window_Type::draw_overlaps() { fl_color(FL_DARK_YELLOW); // loop through all widgets in this window for (Fl_Type *q=next; q && q->level>level; q = q->next) { // is it a valid widget if (q->is_true_widget()) { Fl_Widget_Type *w = (Fl_Widget_Type*)q; // is the widget visible if (w->o->visible()) { int x = w->o->x(), y = w->o->y(); int r = x + w->o->w(), b = y + w->o->h(); for (Fl_Type *p=q->next; p && p->level>=q->level; p = p->next) { if (p->level==q->level && p->is_true_widget()) { Fl_Widget_Type *wp = (Fl_Widget_Type*)p; if (wp->o->visible()) { int px = fd_max(x, wp->o->x()); int py = fd_max(y, wp->o->y()); int pr = fd_min(r, wp->o->x() + wp->o->w()); int pb = fd_min(b, wp->o->y() + wp->o->h()); if (pr > px && pb > py) fd_hatch(px, py, pr-px, pb-py); } } } } else { int l = q->level; for (; q && q->next && q->next->level>l; q = q->next) { } } } } fl_color(FL_RED); } void Fl_Window_Type::draw_overlay() { if (recalc) { bx = o->w(); by = o->h(); br = 0; bt = 0; numselected = 0; for (Fl_Type *q=next; q && q->level>level; q=q->next) if (q->selected && q->is_true_widget()) { numselected++; Fl_Widget_Type* myo = (Fl_Widget_Type*)q; if (myo->o->x() < bx) bx = myo->o->x(); if (myo->o->y() < by) by = myo->o->y(); if (myo->o->x()+myo->o->w() > br) br = myo->o->x()+myo->o->w(); if (myo->o->y()+myo->o->h() > bt) bt = myo->o->y()+myo->o->h(); } recalc = 0; sx = bx; sy = by; sr = br; st = bt; } fl_color(FL_RED); if (drag==FD_BOX && (x1 != mx || y1 != my)) { int x = x1; int r = mx; if (x > r) {x = mx; r = x1;} int y = y1; int b = my; if (y > b) {y = my; b = y1;} fl_rect(x,y,r-x,b-y); } if (overlays_invisible && !drag) return; if (show_restricted) { draw_out_of_bounds(); draw_overlaps(); // TODO: for Fl_Tile, find all areas that are not covered by visible children } if (selected) fl_rect(0,0,o->w(),o->h()); if (!numselected) return; int mybx,myby,mybr,mybt; int mysx,mysy,mysr,myst; mybx = mysx = o->w(); myby = mysy = o->h(); mybr = mysr = 0; mybt = myst = 0; Fl_Type *selection = 0L; // special power for the first selected widget for (Fl_Type *q=next; q && q->level>level; q = q->next) if (q->selected && q->is_true_widget()) { if (!selection) selection = q; Fl_Widget_Type* myo = (Fl_Widget_Type*)q; int x,y,r,t; newposition(myo,x,y,r,t); if (show_guides) { // If we are in a drag operation, and the parent is a grid, show the grid overlay if (drag && q->parent && q->parent->is_a(ID_Grid)) { Fl_Grid_Proxy *grid = ((Fl_Grid_Proxy*)((Fl_Grid_Type*)q->parent)->o); grid->draw_overlay(); } } if (!show_guides || !drag || numselected != 1) { if (Fl_Flex_Type::parent_is_flex(q) && Fl_Flex_Type::is_fixed(q)) { Fl_Flex *flex = ((Fl_Flex*)((Fl_Flex_Type*)q->parent)->o); Fl_Widget *wgt = myo->o; if (flex->horizontal()) { draw_width(wgt->x(), wgt->y()+15, wgt->x()+wgt->w(), FL_ALIGN_CENTER); } else { draw_height(wgt->x()+15, wgt->y(), wgt->y()+wgt->h(), FL_ALIGN_CENTER); } } else if (q->is_a(ID_Grid)) { Fl_Grid_Proxy *grid = ((Fl_Grid_Proxy*)((Fl_Grid_Type*)q)->o); grid->draw_overlay(); } fl_rect(x,y,r-x,t-y); } if (x < mysx) mysx = x; if (y < mysy) mysy = y; if (r > mysr) mysr = r; if (t > myst) myst = t; if (!(myo->o->align() & FL_ALIGN_INSIDE)) { // Adjust left/right/top/bottom for top/bottom labels... int ww, hh; ww = (myo->o->align() & FL_ALIGN_WRAP) ? myo->o->w() : 0; hh = myo->o->labelsize(); myo->o->measure_label(ww, hh); if (myo->o->align() & FL_ALIGN_TOP) y -= hh; else if (myo->o->align() & FL_ALIGN_BOTTOM) t += hh; else if (myo->o->align() & FL_ALIGN_LEFT) x -= ww + 4; else if (myo->o->align() & FL_ALIGN_RIGHT) r += ww + 4; } if (x < mybx) mybx = x; if (y < myby) myby = y; if (r > mybr) mybr = r; if (t > mybt) mybt = t; } if (selected) return; // align the snapping selection box with the box we draw. sx = mysx; sy = mysy; sr = mysr; st = myst; // Draw selection box + resize handles... // draw box including all labels fl_focus_rect(mybx,myby,mybr-mybx,mybt-myby); // issue #816 // draw box excluding labels fl_rect(mysx,mysy,mysr-mysx,myst-mysy); fl_rectf(mysx,mysy,5,5); fl_rectf(mysr-5,mysy,5,5); fl_rectf(mysr-5,myst-5,5,5); fl_rectf(mysx,myst-5,5,5); if (show_guides && (drag & (FD_DRAG|FD_TOP|FD_LEFT|FD_BOTTOM|FD_RIGHT))) { Fd_Snap_Data data = { dx, dy, sx, sy, sr, st, drag, 4, 4, dx, dy, (Fl_Widget_Type*)selection, this}; Fd_Snap_Action::draw_all(data); } } extern Fl_Menu_Item Main_Menu[]; // Calculate new bounding box of selected widgets: void Fl_Window_Type::fix_overlay() { overlay_item->label("Hide O&verlays"); if (overlay_button) overlay_button->label("Hide &Overlays"); overlays_invisible = 0; recalc = 1; ((Overlay_Window *)(this->o))->redraw_overlay(); } // check if we must redraw any parent of tabs/wizard type void check_redraw_corresponding_parent(Fl_Type *s) { Fl_Widget_Type * prev_parent = 0; if( !s || !s->selected || !s->is_widget()) return; for (Fl_Type *i=s; i && i->parent; i=i->parent) { if (i->is_a(ID_Group) && prev_parent) { if (i->is_a(ID_Tabs)) { ((Fl_Tabs*)((Fl_Widget_Type*)i)->o)->value(prev_parent->o); return; } if (i->is_a(ID_Wizard)) { ((Fl_Wizard*)((Fl_Widget_Type*)i)->o)->value(prev_parent->o); return; } } if (i->is_a(ID_Group) && s->is_widget()) prev_parent = (Fl_Widget_Type*)i; } } // do that for every window (when selected set changes): void redraw_overlays() { for (Fl_Type *o=Fl_Type::first; o; o=o->next) if (o->is_a(ID_Window)) ((Fl_Window_Type*)o)->fix_overlay(); } void toggle_overlays(Fl_Widget *,void *) { overlays_invisible = !overlays_invisible; if (overlays_invisible) { overlay_item->label("Show O&verlays"); if (overlay_button) overlay_button->label("Show &Overlays"); } else { overlay_item->label("Hide O&verlays"); if (overlay_button) overlay_button->label("Hide &Overlays"); } for (Fl_Type *o=Fl_Type::first; o; o=o->next) if (o->is_a(ID_Window)) { Fl_Widget_Type* w = (Fl_Widget_Type*)o; ((Overlay_Window*)(w->o))->redraw_overlay(); } } /** \brief User changes settings to show positioning guides in layout editor overlay. This is called from the main menu and from the check button in the Settings dialog. */ void toggle_guides(Fl_Widget *,void *) { show_guides = !show_guides; fluid_prefs.set("show_guides", show_guides); if (show_guides) guides_item->label("Hide Guides"); else guides_item->label("Show Guides"); if (guides_button) guides_button->value(show_guides); for (Fl_Type *o=Fl_Type::first; o; o=o->next) { if (o->is_a(ID_Window)) { Fl_Widget_Type* w = (Fl_Widget_Type*)o; ((Overlay_Window*)(w->o))->redraw_overlay(); } } } /** \brief User changes settings to show positioning guides in layout editor overlay. This is called from the check button in the Settings dialog. */ void toggle_guides_cb(Fl_Check_Button *o, void *v) { toggle_guides(NULL, NULL); } /** \brief User changes settings to show overlapping and out of bounds widgets. This is called from the main menu and from the check button in the Settings dialog. */ void toggle_restricted(Fl_Widget *,void *) { show_restricted = !show_restricted; fluid_prefs.set("show_restricted", show_restricted); if (show_restricted) restricted_item->label("Hide Restricted"); else restricted_item->label("Show Restricted"); if (restricted_button) restricted_button->value(show_restricted); for (Fl_Type *o=Fl_Type::first; o; o=o->next) { if (o->is_a(ID_Window)) { Fl_Widget_Type* w = (Fl_Widget_Type*)o; ((Overlay_Window*)(w->o))->redraw_overlay(); } } } /** \brief User changes settings to show low contrast groups with a ghosted outline. */ void toggle_ghosted_outline_cb(Fl_Check_Button *,void *) { show_ghosted_outline = !show_ghosted_outline; fluid_prefs.set("show_ghosted_outline", show_ghosted_outline); for (Fl_Type *o=Fl_Type::first; o; o=o->next) { if (o->is_a(ID_Window)) { Fl_Widget_Type* w = (Fl_Widget_Type*)o; ((Overlay_Window*)(w->o))->redraw(); } } } /** \brief User changes settings to show overlapping and out of bounds widgets. This is called from the check button in the Settings dialog. */ void toggle_restricted_cb(Fl_Check_Button *o, void *v) { toggle_restricted(NULL, NULL); } extern void select(Fl_Type *,int); extern void select_only(Fl_Type *); extern void deselect(); extern Fl_Type* in_this_only; extern void fix_group_size(Fl_Type *t); extern Fl_Menu_Item Main_Menu[]; extern Fl_Menu_Item New_Menu[]; /** Move the selected children according to current dx, dy, drag state. This is somewhat of a do-all function that received many additions when new widget types were added. In the default case, moving a group will simply move all descendants with it. When resizing, children are resized to fit within the group. This is not ideal for widgets that are moved or resized within a group that manages the layout of its children. We must create a more universal way to modify move events per widget type. \param[in] key if key is not 0, it contains the code of the keypress that caused this call. This must only be set when handle FL_KEYBOARD events. */ void Fl_Window_Type::moveallchildren(int key) { bool update_widget_panel = false; undo_checkpoint(); Fl_Type *i; for (i=next; i && i->level>level;) { if (i->selected && i->is_true_widget()) { Fl_Widget_Type* myo = (Fl_Widget_Type*)i; int x,y,r,t,ow=myo->o->w(),oh=myo->o->h(); newposition(myo,x,y,r,t); if (myo->is_a(ID_Flex) || myo->is_a(ID_Grid)) { // Flex and Grid need to be able to layout their children. allow_layout++; myo->o->resize(x,y,r-x,t-y); allow_layout--; } else { // Other groups are resized without affecting their children, however // they move their children if the entire widget is moved. myo->o->resize(x,y,r-x,t-y); } if (Fl_Flex_Type::parent_is_flex(myo)) { // If the border of a Flex child is move, give that child a fixed size // so that the user request is reflected. Fl_Flex_Type* ft = (Fl_Flex_Type*)myo->parent; Fl_Flex* f = (Fl_Flex*)ft->o; if (key) { ft->keyboard_move_child(myo, key); } else if (drag & FD_DRAG) { ft->insert_child_at(myo->o, Fl::event_x(), Fl::event_y()); } else { if (f->horizontal()) { if (myo->o->w()!=ow) { f->fixed(myo->o, myo->o->w()); f->layout(); } } else { if (myo->o->h()!=oh) { f->fixed(myo->o, myo->o->h()); f->layout(); } } } // relayout the Flex parent allow_layout++; f->layout(); allow_layout--; } else if (myo->parent && myo->parent->is_a(ID_Grid)) { Fl_Grid_Type* gt = (Fl_Grid_Type*)myo->parent; Fl_Grid* g = (Fl_Grid*)gt->o; if (key) { gt->keyboard_move_child(myo, key); } else { if (drag & FD_DRAG) { gt->insert_child_at(myo->o, Fl::event_x(), Fl::event_y()); } else { gt->child_resized(myo); } } allow_layout++; g->layout(); allow_layout--; update_widget_panel = true; } else if (myo->parent && myo->parent->is_a(ID_Group)) { Fl_Group_Type* gt = (Fl_Group_Type*)myo->parent; ((Fl_Group*)gt->o)->init_sizes(); } // move all the children, whether selected or not: Fl_Type* p; for (p = myo->next; p && p->level>myo->level; p = p->next) if (p->is_true_widget() && !myo->is_a(ID_Flex) && !myo->is_a(ID_Grid)) { Fl_Widget_Type* myo2 = (Fl_Widget_Type*)p; int X,Y,R,T; newposition(myo2,X,Y,R,T); myo2->o->resize(X,Y,R-X,T-Y); } i = p; } else { i = i->next; } } for (i=next; i && i->level>level; i=i->next) fix_group_size(i); o->redraw(); recalc = 1; ((Overlay_Window *)(this->o))->redraw_overlay(); set_modflag(1); dx = dy = 0; update_xywh(); if (update_widget_panel && the_panel && the_panel->visible()) { propagate_load(the_panel, LOAD); } } int Fl_Window_Type::popupx = 0x7FFFFFFF; // mark as invalid (MAXINT) int Fl_Window_Type::popupy = 0x7FFFFFFF; int Fl_Window_Type::handle(int event) { static Fl_Type* selection = NULL; switch (event) { case FL_DND_ENTER: // printf("DND enter\n"); case FL_DND_DRAG: // printf("DND drag\n"); { // find the innermost item clicked on: selection = this; for (Fl_Type* i=next; i && i->level>level; i=i->next) if (i->is_a(ID_Group)) { Fl_Widget_Type* myo = (Fl_Widget_Type*)i; if (Fl::event_inside(myo->o) && myo->o->visible_r()) { selection = myo; if (Fl::event_clicks()==1) reveal_in_browser(myo); } } if (selection && !selection->selected) { select_only(selection); ((Overlay_Window *)o)->redraw_overlay(); } } Fl::belowmouse(o); return 1; case FL_DND_RELEASE: // printf("DND release\n"); Fl::belowmouse(o); return 1; case FL_PASTE: // printf("DND paste\n"); { Fl_Type *prototype = typename_to_prototype(Fl::event_text()); if (prototype==NULL) { // it's not a FLUID type, so it could be the filename of an image const char *cfn = Fl::event_text(); // printf("DND is filename %s?\n", cfn); if ((cfn == NULL) || (*cfn == 0)) return 0; if (strlen(cfn) >= FL_PATH_MAX) return 0; char fn[FL_PATH_MAX+1]; // some platform prepend "file://" or "computer://" or similar text const char *sep = strstr(cfn, "://"); if (sep) strcpy(fn, sep+3); else strcpy(fn, cfn); // remove possibly trailing \r\n int n = (int)strlen(fn)-1; if (fn[n] == '\n') fn[n--] = 0; if (fn[n] == '\r') fn[n--] = 0; // on X11 and Wayland (?), filenames need to be decoded #if (defined(FLTK_USE_X11) || defined(FLTK_USE_WAYLAND)) fl_decode_uri(fn); #endif // does a file by that name actually exist? if (fl_access(fn, 4)==-1) return 0; // but is this an image file? Fl_Image *img = Fl_Shared_Image::get(fn); if (!img || (img->ld() < 0)) return 0; // ok, so it is an image - now add it as image() or deimage() to the widget // printf("DND check for target %s\n", fn); Fl_Widget_Type *tgt = NULL; for (Fl_Type* i=next; i && i->level>level; i=i->next) { if (i->is_widget()) { Fl_Widget_Type* myo = (Fl_Widget_Type*)i; if (Fl::event_inside(myo->o) && myo->o->visible_r()) tgt = myo; } } if (tgt) { char rel[FL_PATH_MAX+1]; enter_project_dir(); fl_filename_relative(rel, FL_PATH_MAX, fn); leave_project_dir(); // printf("DND image = %s\n", fn); if (Fl::get_key(FL_Alt_L) || Fl::get_key(FL_Alt_R)) { //if (Fl::event_alt()) { // TODO: X11/Wayland does not set the e_state on DND events tgt->inactive_name(rel); tgt->compress_deimage_ = 1; tgt->bind_deimage_ = 0; } else { tgt->image_name(rel); tgt->compress_image_ = 1; tgt->bind_image_ = 0; } select_only(tgt); tgt->open(); } return 1; } in_this_only = this; popupx = Fl::event_x(); popupy = Fl::event_y(); // If the selected widget at dnd start and the drop target are the same, // or in the same group, add after selection. Otherwise, just add // at the end of the selected group. if ( Fl_Type::current_dnd->group() && selection && selection->group() && Fl_Type::current_dnd->group()==selection->group()) { Fl_Type *cc = Fl_Type::current; Fl_Type::current = Fl_Type::current_dnd; add_new_widget_from_user(prototype, Strategy::AS_LAST_CHILD); Fl_Type::current = cc; } else { add_new_widget_from_user(prototype, Strategy::AS_LAST_CHILD); } popupx = 0x7FFFFFFF; popupy = 0x7FFFFFFF; // mark as invalid (MAXINT) in_this_only = NULL; widget_browser->display(Fl_Type::current); widget_browser->rebuild(); return 1; } case FL_PUSH: x1 = mx = Fl::event_x(); y1 = my = Fl::event_y(); drag = dx = dy = 0; // test for popup menu: if (Fl::event_button() >= 3) { in_this_only = this; // modifies how some menu items work. static const Fl_Menu_Item* myprev; popupx = mx; popupy = my; const Fl_Menu_Item* m = New_Menu->popup(mx,my,"New",myprev); if (m && m->callback()) {myprev = m; m->do_callback(this->o);} popupx = 0x7FFFFFFF; popupy = 0x7FFFFFFF; // mark as invalid (MAXINT) in_this_only = 0; return 1; } // find the innermost item clicked on: selection = this; {for (Fl_Type* i=next; i && i->level>level; i=i->next) if (i->is_true_widget()) { Fl_Widget_Type* myo = (Fl_Widget_Type*)i; for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent()) if (!o1->visible()) goto CONTINUE2; if (Fl::event_inside(myo->o)) { selection = myo; if (Fl::event_clicks()==1) reveal_in_browser(myo); } CONTINUE2:; }} // see if user grabs edges of selected region: if (numselected && !(Fl::event_state(FL_SHIFT)) && mx<=br+2 && mx>=bx-2 && my<=bt+2 && my>=by-2) { if (mx >= br-5) drag |= FD_RIGHT; else if (mx <= bx+5) drag |= FD_LEFT; if (my >= bt-5) drag |= FD_BOTTOM; else if (my <= by+5) drag |= FD_TOP; if (!drag) drag = FD_DRAG; } // do object-specific selection of other objects: {Fl_Type* t = selection->click_test(mx, my); if (t) { //if (t == selection) return 1; // indicates mouse eaten w/o change if (Fl::event_state(FL_SHIFT)) { Fl::event_is_click(0); select(t, !t->selected); } else { deselect(); select(t, 1); if (t->is_a(ID_Menu_Item)) t->open(); } selection = t; drag = 0; } else { if (!drag) drag = FD_BOX; // if all else fails, start a new selection region }} return 1; case FL_DRAG: if (!drag) return 0; mx = Fl::event_x(); my = Fl::event_y(); newdx(); return 1; case FL_RELEASE: if (!drag) return 0; mx = Fl::event_x(); my = Fl::event_y(); if (drag != FD_BOX && (dx || dy || !Fl::event_is_click())) { if (dx || dy) moveallchildren(); } else if ((Fl::event_clicks() || Fl::event_state(FL_CTRL))) { Fl_Widget_Type::open(); } else { if (mxlevel>level; i=i->next) if (i->is_true_widget()) { Fl_Widget_Type* myo = (Fl_Widget_Type*)i; for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent()) if (!o1->visible()) goto CONTINUE; if (Fl::event_inside(myo->o)) selection = myo; if (myo && myo->o && myo->o->x()>=x1 && myo->o->y()>y1 && myo->o->x()+myo->o->w()o->y()+myo->o->h()selected : 1); } CONTINUE:; } // if nothing in box, select what was clicked on: if (selection && !n) { select(selection, toggle ? !selection->selected : 1); } } drag = 0; ((Overlay_Window *)o)->redraw_overlay(); return 1; case FL_KEYBOARD: { int backtab = 0; switch (Fl::event_key()) { case FL_Escape: ((Fl_Window*)o)->hide(); return 1; case FL_Tab: { if (Fl::event_state(FL_SHIFT)) backtab = 1; // find current child: Fl_Type *i = Fl_Type::current; while (i && !i->is_true_widget()) i = i->parent; if (!i) return 0; Fl_Type *p = i->parent; while (p && p != this) p = p->parent; if (!p || !p->is_widget()) { i = next; if (!i || i->level <= level) return 0; } p = i; for (;;) { i = backtab ? i->prev : i->next; if (!i || i->level <= level) {i = p; break;} if (i->is_true_widget()) break; } deselect(); select(i,1); return 1;} case FL_Left: dx = -1; dy = 0; goto ARROW; case FL_Right: dx = +1; dy = 0; goto ARROW; case FL_Up: dx = 0; dy = -1; goto ARROW; case FL_Down: dx = 0; dy = +1; goto ARROW; ARROW: drag = (Fl::event_state(FL_SHIFT)) ? (FD_RIGHT|FD_BOTTOM) : FD_DRAG; if (Fl::event_state(FL_COMMAND)) { int x_step, y_step; if (drag & (FD_RIGHT|FD_BOTTOM)) Fd_Snap_Action::get_resize_stepsize(x_step, y_step); else Fd_Snap_Action::get_move_stepsize(x_step, y_step); dx *= x_step; dy *= y_step; } moveallchildren(Fl::event_key()); drag = 0; return 1; case 'o': toggle_overlays(0, 0); break; default: return 0; }} case FL_SHORTCUT: { in_this_only = this; // modifies how some menu items work. const Fl_Menu_Item* m = Main_Menu->test_shortcut(); if (m && m->callback()) m->do_callback(this->o); in_this_only = 0; return (m != 0);} default: return 0; } } //////////////////////////////////////////////////////////////// /** Write the C++ code that comes before the children of the window are written. \param f the source code output stream */ void Fl_Window_Type::write_code1(Fd_Code_Writer& f) { Fl_Widget_Type::write_code1(f); } /** Write the C++ code that comes after the children of the window are written. \param f the source code output stream */ void Fl_Window_Type::write_code2(Fd_Code_Writer& f) { const char *var = is_class() ? "this" : name() ? name() : "o"; // make the window modal or non-modal if (modal) { f.write_c("%s%s->set_modal();\n", f.indent(), var); } else if (non_modal) { f.write_c("%s%s->set_non_modal();\n", f.indent(), var); } // clear the window border if (!((Fl_Window*)o)->border()) { f.write_c("%s%s->clear_border();\n", f.indent(), var); } // set the xclass of the window if (xclass) { f.write_c("%s%s->xclass(", f.indent(), var); f.write_cstring(xclass); f.write_c(");\n"); } // make the window resizable if (((Fl_Window*)o)->resizable() == o) f.write_c("%s%s->resizable(%s);\n", f.indent(), var, var); // set the size range last if (sr_max_w || sr_max_h) { f.write_c("%s%s->size_range(%d, %d, %d, %d);\n", f.indent(), var, sr_min_w, sr_min_h, sr_max_w, sr_max_h); } else if (sr_min_w || sr_min_h) { f.write_c("%s%s->size_range(%d, %d);\n", f.indent(), var, sr_min_w, sr_min_h); } // insert extra code from user, may call `show()` write_extra_code(f); // stop adding widgets to this window f.write_c("%s%s->end();\n", f.indent(), var); write_block_close(f); } void Fl_Window_Type::write_properties(Fd_Project_Writer &f) { Fl_Widget_Type::write_properties(f); if (modal) f.write_string("modal"); else if (non_modal) f.write_string("non_modal"); if (!((Fl_Window*)o)->border()) f.write_string("noborder"); if (xclass) {f.write_string("xclass"); f.write_word(xclass);} if (sr_min_w || sr_min_h || sr_max_w || sr_max_h) f.write_string("size_range {%d %d %d %d}", sr_min_w, sr_min_h, sr_max_w, sr_max_h); if (o->visible() || override_visible_) f.write_string("visible"); } void Fl_Window_Type::read_property(Fd_Project_Reader &f, const char *c) { if (!strcmp(c,"modal")) { modal = 1; } else if (!strcmp(c,"non_modal")) { non_modal = 1; } else if (!strcmp(c, "visible")) { if (batch_mode) // don't actually open any windows in batch mode override_visible_ = 1; else // in interactive mode, we simply show the window open_(); } else if (!strcmp(c,"noborder")) { ((Fl_Window*)o)->border(0); } else if (!strcmp(c,"xclass")) { storestring(f.read_word(),xclass); ((Fl_Window*)o)->xclass(xclass); } else if (!strcmp(c,"size_range")) { int mw, mh, MW, MH; if (sscanf(f.read_word(),"%d %d %d %d",&mw,&mh,&MW,&MH) == 4) { sr_min_w = mw; sr_min_h = mh; sr_max_w = MW; sr_max_h = MH; } } else if (!strcmp(c,"xywh")) { Fl_Widget_Type::read_property(f, c); pasteoffset = 0; // make it not apply to contents } else { Fl_Widget_Type::read_property(f, c); } } int Fl_Window_Type::read_fdesign(const char* propname, const char* value) { int x; o->box(FL_NO_BOX); // because fdesign always puts an Fl_Box next if (!strcmp(propname,"Width")) { if (sscanf(value,"%d",&x) == 1) o->size(x,o->h()); } else if (!strcmp(propname,"Height")) { if (sscanf(value,"%d",&x) == 1) o->size(o->w(),x); } else if (!strcmp(propname,"NumberofWidgets")) { return 1; // we can figure out count from file } else if (!strcmp(propname,"border")) { if (sscanf(value,"%d",&x) == 1) ((Fl_Window*)o)->border(x); } else if (!strcmp(propname,"title")) { label(value); } else { return Fl_Widget_Type::read_fdesign(propname,value); } return 1; } /////////////////////////////////////////////////////////////////////// Fl_Widget_Class_Type Fl_Widget_Class_type; Fl_Widget_Class_Type *current_widget_class = 0; /** Create and add a new Widget Class node. \param[in] strategy add after current or as last child \return new node */ Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) { Fl_Type *anchor = Fl_Type::current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && (!p->is_decl_block() || (p->is_widget() && p->is_class()))) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } Fl_Widget_Class_Type *myo = new Fl_Widget_Class_Type(); myo->name("UserInterface"); if (!this->o) {// template widget this->o = new Fl_Window(100,100); Fl_Group::current(0); } myo->factory = this; myo->drag = 0; myo->numselected = 0; Overlay_Window *w = new Overlay_Window(100, 100); w->size_range(10, 10); w->window = myo; myo->o = w; myo->add(anchor, strategy); myo->modal = 0; myo->non_modal = 0; myo->wc_relative = 0; return myo; } void Fl_Widget_Class_Type::write_properties(Fd_Project_Writer &f) { Fl_Window_Type::write_properties(f); if (wc_relative==1) f.write_string("position_relative"); else if (wc_relative==2) f.write_string("position_relative_rescale"); } void Fl_Widget_Class_Type::read_property(Fd_Project_Reader &f, const char *c) { if (!strcmp(c,"position_relative")) { wc_relative = 1; } else if (!strcmp(c,"position_relative_rescale")) { wc_relative = 2; } else { Fl_Window_Type::read_property(f, c); } } // Convert A::B::C::D to D (i.e. keep only innermost name) // This is useful for classes that contain a namespace component static const char *trimclassname(const char *n) { if (!n) return NULL; const char *nn; while((nn = strstr(n, "::"))) { n = nn + 2; } return(n); } void Fl_Widget_Class_Type::write_code1(Fd_Code_Writer& f) { #if 0 Fl_Widget_Type::write_code1(Fd_Code_Writer& f); #endif // 0 current_widget_class = this; write_public_state = 1; const char *c = subclass(); if (!c) c = "Fl_Group"; f.write_c("\n"); write_comment_h(f); f.write_h("\nclass %s : public %s {\n", name(), c); if (strstr(c, "Window")) { f.write_h("%svoid _%s();\n", f.indent(1), trimclassname(name())); f.write_h("public:\n"); f.write_h("%s%s(int X, int Y, int W, int H, const char *L = 0);\n", f.indent(1), trimclassname(name())); f.write_h("%s%s(int W, int H, const char *L = 0);\n", f.indent(1), trimclassname(name())); f.write_h("%s%s();\n", f.indent(1), trimclassname(name())); // a constructor with all four dimensions plus label f.write_c("%s::%s(int X, int Y, int W, int H, const char *L) :\n", name(), trimclassname(name())); f.write_c("%s%s(X, Y, W, H, L)\n{\n", f.indent(1), c); f.write_c("%s_%s();\n", f.indent(1), trimclassname(name())); f.write_c("}\n\n"); // a constructor with just the size and label. The window manager will position the window f.write_c("%s::%s(int W, int H, const char *L) :\n", name(), trimclassname(name())); f.write_c("%s%s(0, 0, W, H, L)\n{\n", f.indent(1), c); f.write_c("%sclear_flag(16);\n", f.indent(1)); f.write_c("%s_%s();\n", f.indent(1), trimclassname(name())); f.write_c("}\n\n"); // a constructor that takes size and label from the Fluid database f.write_c("%s::%s() :\n", name(), trimclassname(name())); f.write_c("%s%s(0, 0, %d, %d, ", f.indent(1), c, o->w(), o->h()); const char *cstr = label(); if (cstr) f.write_cstring(cstr); else f.write_c("0"); f.write_c(")\n{\n"); f.write_c("%sclear_flag(16);\n", f.indent(1)); f.write_c("%s_%s();\n", f.indent(1), trimclassname(name())); f.write_c("}\n\n"); f.write_c("void %s::_%s() {\n", name(), trimclassname(name())); // f.write_c("%s%s *w = this;\n", f.indent(1), name()); } else { f.write_h("public:\n"); f.write_h("%s%s(int X, int Y, int W, int H, const char *L = 0);\n", f.indent(1), trimclassname(name())); f.write_c("%s::%s(int X, int Y, int W, int H, const char *L) :\n", name(), trimclassname(name())); if (wc_relative==1) f.write_c("%s%s(0, 0, W, H, L)\n{\n", f.indent(1), c); else if (wc_relative==2) f.write_c("%s%s(0, 0, %d, %d, L)\n{\n", f.indent(1), c, o->w(), o->h()); else f.write_c("%s%s(X, Y, W, H, L)\n{\n", f.indent(1), c); } // f.write_c("%s%s *o = this;\n", f.indent(1), name()); f.indentation++; write_widget_code(f); } /** Write the C++ code that comes after the children of the window are written. \param f the source code output stream */ void Fl_Widget_Class_Type::write_code2(Fd_Code_Writer& f) { // make the window modal or non-modal if (modal) { f.write_c("%sset_modal();\n", f.indent()); } else if (non_modal) { f.write_c("%sset_non_modal();\n", f.indent()); } // clear the window border if (!((Fl_Window*)o)->border()) f.write_c("%sclear_border();\n", f.indent()); // set the xclass of the window if (xclass) { f.write_c("%sxclass(", f.indent()); f.write_cstring(xclass); f.write_c(");\n"); } // make the window resizable if (((Fl_Window*)o)->resizable() == o) f.write_c("%sresizable(this);\n", f.indent()); // insert extra code from user write_extra_code(f); // stop adding widgets to this window f.write_c("%send();\n", f.indent()); // reposition or resize the Widget Class to fit into the target if (wc_relative==1) f.write_c("%sposition(X, Y);\n", f.indent()); else if (wc_relative==2) f.write_c("%sresize(X, Y, W, H);\n", f.indent()); f.indentation--; f.write_c("}\n"); } //////////////////////////////////////////////////////////////// // live mode support Fl_Widget *Fl_Window_Type::enter_live_mode(int) { Fl_Window *win = new Fl_Window(10, 10, o->w(), o->h()); return propagate_live_mode(win); } void Fl_Window_Type::leave_live_mode() { } /** copy all properties from the edit widget to the live widget */ void Fl_Window_Type::copy_properties() { Fl_Window *self = static_cast(o); Fl_Window *live = static_cast(live_widget); if (self->resizable() == self) live->resizable(live); Fl_Widget_Type::copy_properties(); } fltk-1.4.3/fluid/StyleParse.h0000644000175000017500000000353215004135251016157 0ustar albrechtalbrecht// // Syntax highlighting for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // Copyright 2020 Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef StyleParse_h #define StyleParse_h // Class to manage style parsing, friend of CodeEditor class StyleParse { public: const char *tbuff; // text buffer char *sbuff; // style buffer int len; // running length char style; // current style char lwhite; // leading white space (1=white, 0=past white) int col; // line's column counter char keyword[40]; // keyword parsing buffer char last; // flag for keyword parsing StyleParse() { tbuff = 0; sbuff = 0; len = 0; style = 0; lwhite = 1; col = 0; last = 0; } // Methods to aid in parsing int parse_over_char(int handle_crlf=1); int parse_over_white(); int parse_over_alpha(); int parse_to_eol(char s); int parse_block_comment(); // "/* text.. */" void buffer_keyword(); int parse_over_key(const char *key, char s); int parse_over_angles(char s); int parse_keyword(); // "switch" int parse_quoted_string(char quote_char, char in_style); // "hello", 'x' int parse_directive(); // "#define" int parse_line_comment(); // "// text.." int parse_escape(); // "\'" int parse_all_else(); // all other code }; #endif // StyleParse_h fltk-1.4.3/fluid/Fl_Function_Type.cxx0000644000175000017500000017320615004135251017654 0ustar albrechtalbrecht// // C function type code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Function_Type.h" #include "fluid.h" #include "Fl_Window_Type.h" #include "Fl_Group_Type.h" #include "widget_browser.h" #include "file.h" #include "code.h" #include "function_panel.h" #include "comments.h" #include "mergeback.h" #include "undo.h" #include #include #include #include "../src/flstring.h" #include /// Set a current class, so that the code of the children is generated correctly. Fl_Class_Type *current_class = NULL; /** \brief Return 1 if the list contains a function with the given signature at the top level. Fl_Widget_Type uses this to check if a callback by a certain signature is already defined by the user within this file. If not, Fl_Widget_Type will generate an `extern $sig$;` statement. \param[in] rtype return type, can be NULL to avoid checking (not used by Fl_Widget_Type) \param[in] sig function signature \return 1 if found. */ int has_toplevel_function(const char *rtype, const char *sig) { Fl_Type *child; for (child = Fl_Type::first; child; child = child->next) { if (!child->is_in_class() && child->is_a(ID_Function)) { const Fl_Function_Type *fn = (const Fl_Function_Type*)child; if (fn->has_signature(rtype, sig)) return 1; } } return 0; } //////////////////////////////////////////////////////////////// // quick check of any C code for legality, returns an error message static char buffer[128]; // for error messages /** Check a quoted string contains a character. This is used to find a matching " or ' in a string. \param[inout] c start searching here, return where we found \c type \param[in] type find this character \return NULL if the character was found, else a pointer to a static string with an error message */ const char *_q_check(const char * & c, int type) { for (;;) switch (*c++) { case '\0': sprintf(buffer,"missing %c",type); return buffer; case '\\': if (*c) c++; break; default: if (*(c-1) == type) return 0; } } /** Check normal code, match brackets and parenthesis. Recursively run a line of code and make sure that {, [, ", ', and ( are matched. \param[inout] c start searching here, return the end of the search \param[in] type find this character match \return NULL if the character was found, else a pointer to a static string with an error message */ const char *_c_check(const char * & c, int type) { const char *d; for (;;) switch (*c++) { case 0: if (!type) return 0; sprintf(buffer, "missing '%c'", type); return buffer; case '/': // Skip comments as needed... if (*c == '/') { while (*c != '\n' && *c) c++; } else if (*c == '*') { c++; while ((*c != '*' || c[1] != '/') && *c) c++; if (*c == '*') c+=2; else { return "missing '*/'"; } } break; // case '#': // // treat cpp directives as a comment: // // Matt: a '#' character can appear as a concatenation when defining macros // // Matt: so instead we just silently ignore the '#' // while (*c != '\n' && *c) c++; // break; case '{': if (type==')') goto UNEXPECTED; d = _c_check(c,'}'); if (d) return d; break; case '(': d = _c_check(c,')'); if (d) return d; break; case '[': d = _c_check(c,']'); if (d) return d; break; case '\"': d = _q_check(c,'\"'); if (d) return d; break; case '\'': d = _q_check(c,'\''); if (d) return d; break; case '}': case ')': case ']': UNEXPECTED: if (type == *(c-1)) return 0; sprintf(buffer, "unexpected '%c'", *(c-1)); return buffer; } } /** Check legality of c code (sort of) and return error: Make sure that {, ", ', and ( are matched. \param[in] c start searching here \param[in] type find this character match (default is 0) \return NULL if the character was found, else a pointer to a static string with an error message \note This function checks every conceivable line of code, which is not always wanted. It can't differentiate characters in comments, and the user may well intend to leave a curly bracket open (i.e. namespace { ... } ). We should make this option user selectable. */ const char *c_check(const char *c, int type) { return _c_check(c,type); } // ---- Fl_Function_Type implementation /** \class Fl_Function_Type Manage a C++ function node in the Fluid design. A function can have a signature (name followed by arguments), a return type and a comment section. If can be local or global, and it can be declared a C or C++ function. */ /// Prototype for a function to be used by the factory. Fl_Function_Type Fl_Function_type; /** Create a new function. */ Fl_Function_Type::Fl_Function_Type() : Fl_Type(), return_type(0L), public_(0), cdecl_(0), constructor(0), havewidgets(0) { } /** Destructor. */ Fl_Function_Type::~Fl_Function_Type() { if (return_type) free((void*)return_type); } /** Create a new function for the widget tree. \param[in] strategy add new function after current or as last child \return the new node */ Fl_Type *Fl_Function_Type::make(Strategy strategy) { Fl_Type *anchor = Fl_Type::current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_decl_block()) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } Fl_Function_Type *o = new Fl_Function_Type(); o->name("make_window()"); o->return_type = 0; o->add(anchor, strategy); o->factory = this; o->public_ = 1; o->cdecl_ = 0; return o; } /** Write function specific properties to an .fl file. - "private"/"public" indicates the state of the function - "C" is written if we want a C signature instead of C++ - "return_type" is followed by the return type of the function */ void Fl_Function_Type::write_properties(Fd_Project_Writer &f) { Fl_Type::write_properties(f); switch (public_) { case 0: f.write_string("private"); break; case 2: f.write_string("protected"); break; } if (cdecl_) f.write_string("C"); if (return_type) { f.write_string("return_type"); f.write_word(return_type); } } /** Read function specific properties fron an .fl file. \param[in] c read from this string */ void Fl_Function_Type::read_property(Fd_Project_Reader &f, const char *c) { if (!strcmp(c,"private")) { public_ = 0; } else if (!strcmp(c,"protected")) { public_ = 2; } else if (!strcmp(c,"C")) { cdecl_ = 1; } else if (!strcmp(c,"return_type")) { storestring(f.read_word(),return_type); } else { Fl_Type::read_property(f, c); } } /** Open the function_panel dialog box to edit this function. */ void Fl_Function_Type::open() { // fill dialog box if (!function_panel) make_function_panel(); f_return_type_input->value(return_type); f_name_input->value(name()); if (is_in_class()) { f_public_member_choice->value(public_); f_public_member_choice->show(); f_public_choice->hide(); f_c_button->hide(); } else { f_public_choice->value(public_); f_public_choice->show(); f_public_member_choice->hide(); f_c_button->show(); } f_c_button->value(cdecl_); const char *c = comment(); f_comment_input->buffer()->text(c?c:""); function_panel->show(); const char* message = 0; for (;;) { // repeat as long as there are errors // - message loop until OK or cancel is pressed for (;;) { Fl_Widget* w = Fl::readqueue(); if (w == f_panel_cancel) goto BREAK2; else if (w == f_panel_ok) break; else if (!w) Fl::wait(); } // - check syntax const char *c = f_name_input->value(); while (isspace(*c)) c++; message = c_check(c); if (!message) { const char *d = c; for (; *d != '('; d++) if (isspace(*d) || !*d) break; if (*c && *d != '(') message = "must be 'name(arguments)'"; } if (!message) { c = f_return_type_input->value(); message = c_check(c); } // - alert user if (message) { int v = fl_choice("Potential syntax error detected: %s", "Continue Editing", "Ignore Error", NULL, message); if (v==0) continue; // Continue Editing //if (v==1) { } // Ignore Error and close dialog } // - copy dialog data to target variables int mod = 0; name(f_name_input->value()); storestring(f_return_type_input->value(), return_type); if (is_in_class()) { if (public_ != f_public_member_choice->value()) { mod = 1; public_ = f_public_member_choice->value(); redraw_browser(); } } else { if (public_ != f_public_choice->value()) { mod = 1; public_ = f_public_choice->value(); redraw_browser(); } } if (cdecl_ != f_c_button->value()) { mod = 1; cdecl_ = f_c_button->value(); } c = f_comment_input->buffer()->text(); if (c && *c) { if (!comment() || strcmp(c, comment())) { set_modflag(1); redraw_browser(); } comment(c); } else { if (comment()) { set_modflag(1); redraw_browser(); } comment(0); } if (c) free((void*)c); if (mod) set_modflag(1); break; } BREAK2: function_panel->hide(); } /** Return 1 if the function is global. \return 1 if public, 0 if local. */ int Fl_Function_Type::is_public() const { return public_; } static bool fd_isspace(int c) { return (c>0 && c<128 && isspace(c)); } // code duplication: see int is_id(char c) in code.cxx static bool fd_iskeyword(int c) { return (c>0 && c<128 && (isalnum(c) || c=='_')); } // remove all function default parameters and `override` keyword static void clean_function_for_implementation(char *out, const char *function_name) { char *sptr = out; const char *nptr = function_name; int skips=0,skipc=0; int nc=0,plevel=0; bool arglist_done = false; for (;*nptr; nc++,nptr++) { if (arglist_done && fd_isspace(nptr[0])) { // skip `override` and `FL_OVERRIDE` keywords if they are following the list of arguments if (strncmp(nptr+1, "override", 8)==0 && !fd_iskeyword(nptr[9])) { nptr += 8; continue; } else if (strncmp(nptr+1, "FL_OVERRIDE", 11)==0 && !fd_iskeyword(nptr[12])) { nptr += 11; continue; } } if (!skips && *nptr=='(') plevel++; else if (!skips && *nptr==')') { plevel--; if (plevel==0) arglist_done = true; } if ( *nptr=='"' && !(nc && *(nptr-1)=='\\') ) skips = skips ? 0 : 1; else if(!skips && *nptr=='\'' && !(nc && *(nptr-1)=='\\')) skipc = skipc ? 0 : 1; if(!skips && !skipc && plevel==1 && *nptr =='=' && !(nc && *(nptr-1)=='\'') ) { // ignore '=' case while(*++nptr && (skips || skipc || ( (*nptr!=',' && *nptr!=')') || plevel!=1) )) { if ( *nptr=='"' && *(nptr-1)!='\\' ) skips = skips ? 0 : 1; else if(!skips && *nptr=='\'' && *(nptr-1)!='\\') skipc = skipc ? 0 : 1; if (!skips && !skipc && *nptr=='(') plevel++; else if (!skips && *nptr==')') plevel--; } if (*nptr==')') if (--plevel==0) arglist_done = true; } if (sptr < (out + 1024 - 1)) *sptr++ = *nptr; } *sptr = '\0'; } /** Write the code for the source and the header file. This writes the code that goes \b before all children of this class. \see write_code2(Fd_Code_Writer& f) */ void Fl_Function_Type::write_code1(Fd_Code_Writer& f) { constructor=0; havewidgets = 0; Fl_Type *child; // if the function has no children (hence no body), Fluid will not generate // the function either. This is great if you decide to implement that function // inside another module char havechildren = 0; for (child = next; child && child->level > level; child = child->next) { havechildren = 1; if (child->is_widget()) { havewidgets = 1; break; } } if (havechildren) f.write_c("\n"); if (ismain()) { if (havechildren) f.write_c("int main(int argc, char **argv) {\n"); } else { const char* rtype = return_type; const char* star = ""; // from matt: let the user type "static " at the start of type // in order to declare a static method; int is_static = 0; int is_virtual = 0; if (rtype) { if (!strcmp(rtype,"static")) {is_static = 1; rtype = 0;} else if (!strncmp(rtype, "static ",7)) {is_static = 1; rtype += 7;} } if (rtype) { if (!strcmp(rtype, "virtual")) {is_virtual = 1; rtype = 0;} else if (!strncmp(rtype, "virtual ",8)) {is_virtual = 1; rtype += 8;} } if (!rtype) { if (havewidgets) { rtype = subclassname(child); star = "*"; } else rtype = "void"; } const char* k = class_name(0); if (k) { f.write_public(public_); if (havechildren) write_comment_c(f); if (name()[0] == '~') constructor = 1; else { size_t n = strlen(k); if (!strncmp(name(), k, n) && name()[n] == '(') constructor = 1; } f.write_h("%s", f.indent(1)); if (is_static) f.write_h("static "); if (is_virtual) f.write_h("virtual "); if (!constructor) { f.write_h("%s%s ", rtype, star); if (havechildren) f.write_c("%s%s ", rtype, star); } // if this is a subclass, only f.write_h() the part before the ':' char s[1024], *sptr = s; char *nptr = (char *)name(); while (*nptr) { if (*nptr == ':') { if (nptr[1] != ':') break; // Copy extra ":" for "class::member"... *sptr++ = *nptr++; } *sptr++ = *nptr++; } *sptr = '\0'; if (s[strlen(s)-1] == '}') { // special case for inlined functions f.write_h("%s\n", s); } else { f.write_h("%s;\n", s); } if (havechildren) { clean_function_for_implementation(s, name()); f.write_c("%s::%s {\n", k, s); } } else { if (havechildren) write_comment_c(f); if (public_==1) { if (cdecl_) f.write_h("extern \"C\" { %s%s %s; }\n", rtype, star, name()); else f.write_h("%s%s %s;\n", rtype, star, name()); } else if (public_==2) { // write neither the prototype nor static, the function may be declared elsewhere } else { if (havechildren) f.write_c("static "); } // write everything but the default parameters (if any) char s[1024]; if (havechildren) { clean_function_for_implementation(s, name()); f.write_c("%s%s %s {\n", rtype, star, s); } } } if (havewidgets && child && !child->name()) f.write_c("%s%s* w;\n", f.indent(1), subclassname(child)); f.indentation++; } /** Write the code for the source and the header file. This writes the code that goes \b after all children of this class. \see write_code1(Fd_Code_Writer& f) */ void Fl_Function_Type::write_code2(Fd_Code_Writer& f) { Fl_Type *child; const char *var = "w"; char havechildren = 0; for (child = next; child && child->level > level; child = child->next) { havechildren = 1; if (child->is_a(ID_Window) && child->name()) var = child->name(); } if (ismain()) { if (havewidgets) f.write_c("%s%s->show(argc, argv);\n", f.indent(1), var); if (havechildren) f.write_c("%sreturn Fl::run();\n", f.indent(1)); } else if (havewidgets && !constructor && !return_type) { f.write_c("%sreturn %s;\n", f.indent(1), var); } if (havechildren) f.write_c("}\n"); f.indentation = 0; } /** Check if the return type and signature s match. \param[in] rtype function return type \param[in] sig function name followed by arguments \return 1 if they match, 0 if not */ int Fl_Function_Type::has_signature(const char *rtype, const char *sig) const { if (rtype && !return_type) return 0; if (!name()) return 0; if ( (rtype==0L || strcmp(return_type, rtype)==0) && fl_filename_match(name(), sig)) { return 1; } return 0; } // ---- Fl_Code_Type declaration /** \class Fl_Code_Type Manage a block of C++ code in the Fluid design. This node manages an arbitrary block of code inside a function that will be written into the source code file. Fl_Code_Block has no comment field. However, the first line of code will be shown in the widget browser. */ /// Prototype for code to be used by the factory. Fl_Code_Type Fl_Code_type; /** Constructor. */ Fl_Code_Type::Fl_Code_Type() : cursor_position_(0), code_input_scroll_row(0), code_input_scroll_col(0) {} /** Make a new code node. If the parent node is not a function, a message box will pop up and the request will be ignored. \param[in] strategy add code after current or as last child \return new Code node */ Fl_Type *Fl_Code_Type::make(Strategy strategy) { Fl_Type *anchor = Fl_Type::current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_code_block()) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } if (!p) { fl_message("Please select a function"); return 0; } Fl_Code_Type *o = new Fl_Code_Type(); o->name("printf(\"Hello, World!\\n\");"); o->add(anchor, strategy); o->factory = this; return o; } /** Open the code_panel or an external editor to edit this code section. */ void Fl_Code_Type::open() { // Using an external code editor? Open it.. if ( G_use_external_editor && G_external_editor_command[0] ) { const char *cmd = G_external_editor_command; const char *code = name(); if (!code) code = ""; if ( editor_.open_editor(cmd, code) == 0 ) return; // return if editor opened ok, fall thru to built-in if not } // Use built-in code editor.. if (!code_panel) make_code_panel(); const char *text = name(); code_input->buffer()->text( text ? text : "" ); code_input->insert_position(cursor_position_); code_input->scroll(code_input_scroll_row, code_input_scroll_col); code_panel->show(); const char* message = 0; for (;;) { // repeat as long as there are errors for (;;) { Fl_Widget* w = Fl::readqueue(); if (w == code_panel_cancel) goto BREAK2; else if (w == code_panel_ok) break; else if (!w) Fl::wait(); } char*c = code_input->buffer()->text(); message = c_check(c); if (message) { int v = fl_choice("Potential syntax error detected: %s", "Continue Editing", "Ignore Error", NULL, message); if (v==0) continue; // Continue Editing //if (v==1) { } // Ignore Error and close dialog } name(c); free(c); break; } cursor_position_ = code_input->insert_position(); code_input_scroll_row = code_input->scroll_row(); code_input_scroll_col = code_input->scroll_col(); BREAK2: code_panel->hide(); } /** Grab changes from an external editor and write this node. */ void Fl_Code_Type::write(Fd_Project_Writer &f) { // External editor changes? If so, load changes into ram, update mtime/size if ( handle_editor_changes() == 1 ) { main_window->redraw(); // tell fluid to redraw; edits may affect tree's contents } Fl_Type::write(f); } /** Write the code block with the correct indentation. */ void Fl_Code_Type::write_code1(Fd_Code_Writer& f) { // External editor changes? If so, load changes into ram, update mtime/size if ( handle_editor_changes() == 1 ) { main_window->redraw(); // tell fluid to redraw; edits may affect tree's contents } // Matt: disabled f.tag(FD_TAG_GENERIC, 0); f.write_c_indented(name(), 0, '\n'); // Matt: disabled f.tag(FD_TAG_CODE, get_uid()); } /** See if external editor is open. */ int Fl_Code_Type::is_editing() { return editor_.is_editing(); } /** Reap the editor's pid \return -2: editor not open \return -1: wait failed \return 0: process still running \return \>0: process finished + reaped (returns pid) */ int Fl_Code_Type::reap_editor() { return editor_.reap_editor(); } /** Handle external editor file modifications. If changed, record keeping is updated and file's contents is loaded into ram \return 0: file unchanged or not editing \return 1: file changed, internal records updated, 'code' has new content \return -1: error getting file info (get_ms_errmsg() has reason) \todo Figure out how saving a fluid file can be intercepted to grab current contents of editor file.. */ int Fl_Code_Type::handle_editor_changes() { const char *newcode = 0; switch ( editor_.handle_changes(&newcode) ) { case 1: { // (1)=changed name(newcode); // update value in ram free((void*)newcode); return 1; } case -1: return -1; // (-1)=error -- couldn't read file (dialog showed reason) default: break; // (0)=no change } return 0; } // ---- Fl_CodeBlock_Type implementation /** \class Fl_CodeBlock_Type Manage two blocks of C++ code enclosing its children. This node manages two lines of code that enclose all children of this node. This is usually an if..then clause. \todo this node could support multiple lines of code for each block. */ /// Prototype for a block of code to be used by the factory. Fl_CodeBlock_Type Fl_CodeBlock_type; /** Constructor. */ Fl_CodeBlock_Type::Fl_CodeBlock_Type() : Fl_Type(), after(NULL) { } /** Destructor. */ Fl_CodeBlock_Type::~Fl_CodeBlock_Type() { if (after) free((void*)after); } /** Make a new code block. If the parent node is not a function or another codeblock, a message box will pop up and the request will be ignored. \param[in] strategy add after current or as last child \return new CodeBlock */ Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) { Fl_Type *anchor = Fl_Type::current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_code_block()) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } if (!p) { fl_message("Please select a function"); return 0; } Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type(); o->name("if (test())"); o->after = 0; o->add(anchor, strategy); o->factory = this; return o; } /** Write the specific properties for this node. - "after" is followed by the code that comes after the children The "before" code is stored in the name() field. */ void Fl_CodeBlock_Type::write_properties(Fd_Project_Writer &f) { Fl_Type::write_properties(f); if (after) { f.write_string("after"); f.write_word(after); } } /** Read the node specific properties. */ void Fl_CodeBlock_Type::read_property(Fd_Project_Reader &f, const char *c) { if (!strcmp(c,"after")) { storestring(f.read_word(),after); } else { Fl_Type::read_property(f, c); } } /** Open the codeblock_panel. */ void Fl_CodeBlock_Type::open() { if (!codeblock_panel) make_codeblock_panel(); code_before_input->value(name()); code_after_input->value(after); codeblock_panel->show(); const char* message = 0; for (;;) { // repeat as long as there are errors // event loop for (;;) { Fl_Widget* w = Fl::readqueue(); if (w == codeblock_panel_cancel) goto BREAK2; else if (w == codeblock_panel_ok) break; else if (!w) Fl::wait(); } // check for syntax errors message = c_check(code_before_input->value()); if (!message) { message = c_check(code_after_input->value()); } // alert user if (message) { int v = fl_choice("Potential syntax error detected: %s", "Continue Editing", "Ignore Error", NULL, message); if (v==0) continue; // Continue Editing //if (v==1) { } // Ignore Error and close dialog } // write to variables name(code_before_input->value()); storestring(code_after_input->value(), after); break; } BREAK2: codeblock_panel->hide(); } /** Write the "before" code. */ void Fl_CodeBlock_Type::write_code1(Fd_Code_Writer& f) { const char* c = name(); f.write_c("%s%s {\n", f.indent(), c ? c : ""); f.indentation++; } /** Write the "after" code. */ void Fl_CodeBlock_Type::write_code2(Fd_Code_Writer& f) { f.indentation--; if (after) f.write_c("%s} %s\n", f.indent(), after); else f.write_c("%s}\n", f.indent()); } // ---- Fl_Decl_Type declaration /** \class Fl_Decl_Type Manage the C/C++ declaration of a variable. This node manages a single line of code that can be in the header or the source code, and can be made static. \todo this node could support multiple lines. */ /// Prototype for a declaration to be used by the factory. Fl_Decl_Type Fl_Decl_type; /** Constructor. */ Fl_Decl_Type::Fl_Decl_Type() : public_(0), static_(1) { } /** Return 1 if this declaration and its parents are public. */ int Fl_Decl_Type::is_public() const { Fl_Type *p = parent; while (p && !p->is_decl_block()) p = p->parent; if(p && p->is_public() && public_) return public_; else if(!p) return public_; return 0; } /** Make a new declaration. \param[in] strategy add after current or as last child \return new Declaration node */ Fl_Type *Fl_Decl_Type::make(Strategy strategy) { Fl_Type *anchor = Fl_Type::current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_decl_block()) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } Fl_Decl_Type *o = new Fl_Decl_Type(); o->public_ = 0; o->static_ = 1; o->name("int x;"); o->add(anchor, strategy); o->factory = this; return o; } /** Write the specific properties. - "private"/"public"/"protected" - "local"/"global" if this is static or not */ void Fl_Decl_Type::write_properties(Fd_Project_Writer &f) { Fl_Type::write_properties(f); switch (public_) { case 0: f.write_string("private"); break; case 1: f.write_string("public"); break; case 2: f.write_string("protected"); break; } if (static_) f.write_string("local"); else f.write_string("global"); } /** Read the specific properties. */ void Fl_Decl_Type::read_property(Fd_Project_Reader &f, const char *c) { if (!strcmp(c,"public")) { public_ = 1; } else if (!strcmp(c,"private")) { public_ = 0; } else if (!strcmp(c,"protected")) { public_ = 2; } else if (!strcmp(c,"local")) { static_ = 1; } else if (!strcmp(c,"global")) { static_ = 0; } else { Fl_Type::read_property(f, c); } } /** Open the decl_panel to edit this node. */ void Fl_Decl_Type::open() { if (!decl_panel) make_decl_panel(); decl_input->buffer()->text(name()); if (is_in_class()) { decl_class_choice->value(public_); decl_class_choice->show(); decl_choice->hide(); } else { decl_choice->value((public_&1)|((static_&1)<<1)); decl_choice->show(); decl_class_choice->hide(); } const char *c = comment(); decl_comment_input->buffer()->text(c?c:""); decl_panel->show(); const char* message = 0; for (;;) { // repeat as long as there are errors // event loop for (;;) { Fl_Widget* w = Fl::readqueue(); if (w == decl_panel_cancel) goto BREAK2; else if (w == decl_panel_ok) break; else if (!w) Fl::wait(); } // check values const char*c = decl_input->buffer()->text(); while (isspace(*c)) c++; message = c_check(c&&c[0]=='#' ? c+1 : c); // alert user if (message) { int v = fl_choice("Potential syntax error detected: %s", "Continue Editing", "Ignore Error", NULL, message); if (v==0) continue; // Continue Editing //if (v==1) { } // Ignore Error and close dialog } // copy vlaues name(c); if (is_in_class()) { if (public_!=decl_class_choice->value()) { set_modflag(1); public_ = decl_class_choice->value(); } } else { if (public_!=(decl_choice->value()&1)) { set_modflag(1); public_ = (decl_choice->value()&1); } if (static_!=((decl_choice->value()>>1)&1)) { set_modflag(1); static_ = ((decl_choice->value()>>1)&1); } } c = decl_comment_input->buffer()->text(); if (c && *c) { if (!comment() || strcmp(c, comment())) { set_modflag(1); redraw_browser(); } comment(c); } else { if (comment()) { set_modflag(1); redraw_browser(); } comment(0); } if (c) free((void*)c); break; } BREAK2: decl_panel->hide(); } /** Write the code to the source and header files. \todo There are a lot of side effect in this node depending on the given text and the parent node. They need to be understood and documented. */ void Fl_Decl_Type::write_code1(Fd_Code_Writer& f) { const char* c = name(); if (!c) return; // handle a few keywords differently if inside a class if (is_in_class() && ( (!strncmp(c,"class",5) && isspace(c[5])) || (!strncmp(c,"typedef",7) && isspace(c[7])) || (!strncmp(c,"FL_EXPORT",9) && isspace(c[9])) || (!strncmp(c,"struct",6) && isspace(c[6])) || (!strncmp(c,"enum",4) && isspace(c[4])) ) ) { f.write_public(public_); write_comment_h(f, f.indent(1)); f.write_h("%s%s\n", f.indent(1), c); return; } // handle putting #include, extern, using or typedef into decl: if ( (!isalpha(*c) && *c != '~') || (!strncmp(c,"extern",6) && isspace(c[6])) || (!strncmp(c,"class",5) && isspace(c[5])) || (!strncmp(c,"typedef",7) && isspace(c[7])) || (!strncmp(c,"using",5) && isspace(c[5])) || (!strncmp(c,"FL_EXPORT",9) && isspace(c[9])) // || !strncmp(c,"struct",6) && isspace(c[6]) ) { if (public_) { write_comment_h(f); f.write_h("%s\n", c); } else { write_comment_c(f); f.write_c("%s\n", c); } return; } // find the first C++ style comment const char* e = c+strlen(c), *csc = c; while (cscc && e[-1]==' ') e--; if (class_name(1)) { f.write_public(public_); write_comment_h(f, f.indent(1)); f.write_hc(f.indent(1), int(e-c), c, csc); } else { if (public_) { if (static_) f.write_h("extern "); else write_comment_h(f); f.write_hc("", int(e-c), c, csc); if (static_) { write_comment_c(f); f.write_cc("", int(e-c), c, csc); } } else { write_comment_c(f); if (static_) f.write_c("static "); f.write_cc("", int(e-c), c, csc); } } } // ---- Fl_Data_Type declaration /** \class Fl_Data_Type Manage data from an external arbitrary file. The content of the file will be stored in binary inside the generated code. This can be used to store images inline in the source code, */ /// Prototype for a data node to be used by the factory. Fl_Data_Type Fl_Data_type; /** Constructor. */ Fl_Data_Type::Fl_Data_Type() : Fl_Decl_Type(), filename_(NULL), text_mode_(0) { } /** Destructor. */ Fl_Data_Type::~Fl_Data_Type() { if (filename_) free((void*)filename_); } /** Create an empty inline data node. \param[in] strategy add after current or as last child \return new inline data node */ Fl_Type *Fl_Data_Type::make(Strategy strategy) { Fl_Type *anchor = Fl_Type::current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_decl_block()) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } Fl_Data_Type *o = new Fl_Data_Type(); o->public_ = 1; o->static_ = 1; o->filename_ = 0; o->text_mode_ = 0; o->name("myInlineData"); o->add(anchor, strategy); o->factory = this; return o; } /** Write additional properties. - "filename" followed by the filename of the file to inline - "textmode" if data is written in ASCII vs. binary */ void Fl_Data_Type::write_properties(Fd_Project_Writer &f) { Fl_Decl_Type::write_properties(f); if (filename_) { f.write_string("filename"); f.write_word(filename_); } if (text_mode_ == 1) { f.write_string("textmode"); } if (text_mode_ == 2) { f.write_string("compressed"); } } /** Read specific properties. */ void Fl_Data_Type::read_property(Fd_Project_Reader &f, const char *c) { if (!strcmp(c,"filename")) { storestring(f.read_word(), filename_, 1); } else if (!strcmp(c,"textmode")) { text_mode_ = 1; } else if (!strcmp(c,"compressed")) { text_mode_ = 2; } else { Fl_Decl_Type::read_property(f, c); } } /** Open the data_panel to edit this node. */ void Fl_Data_Type::open() { if (!data_panel) make_data_panel(); data_input->value(name()); if (is_in_class()) { data_class_choice->value(public_); data_class_choice->show(); data_choice->hide(); } else { data_choice->value((public_&1)|((static_&1)<<1)); data_choice->show(); data_class_choice->hide(); } data_mode->value(text_mode_); data_filename->value(filename_?filename_:""); const char *c = comment(); data_comment_input->buffer()->text(c?c:""); data_panel->show(); for (;;) { // repeat as long as there are errors for (;;) { Fl_Widget* w = Fl::readqueue(); if (w == data_panel_cancel) goto BREAK2; else if (w == data_panel_ok) break; else if (w == data_filebrowser) { enter_project_dir(); const char *fn = fl_file_chooser("Load Inline Data", 0L, data_filename->value(), 1); leave_project_dir(); if (fn) { if (strcmp(fn, data_filename->value())) set_modflag(1); data_filename->value(fn); } } else if (!w) Fl::wait(); } // store the variable name: const char*c = data_input->value(); char *s = fl_strdup(c), *p = s, *q, *n; for (;;++p) { // remove leading spaces if (!isspace((unsigned char)(*p))) break; } n = p; if ( (!isalpha((unsigned char)(*p))) && ((*p)!='_') && ((*p)!=':') ) goto OOPS; ++p; for (;;++p) { if ( (!isalnum((unsigned char)(*p))) && ((*p)!='_') && ((*p)!=':') ) break; } q = p; for (;;++q) { if (!*q) break; if (!isspace((unsigned char)(*q))) goto OOPS; } *p = 0; // remove trailing spaces if (n==q) { OOPS: int v = fl_choice("%s", "Continue Editing", "Ignore Error", NULL, "Variable name must be a C identifier"); if (v==0) { free(s); continue; } // Continue Editing //if (v==1) { } // Ignore Error and close dialog } undo_checkpoint(); name(n); free(s); // store flags if (is_in_class()) { if (public_!=data_class_choice->value()) { set_modflag(1); public_ = data_class_choice->value(); } } else { if (public_!=(data_choice->value()&1)) { set_modflag(1); public_ = (data_choice->value()&1); } if (static_!=((data_choice->value()>>1)&1)) { set_modflag(1); static_ = ((data_choice->value()>>1)&1); } } text_mode_ = data_mode->value(); if (text_mode_ < 0) text_mode_ = 0; if (text_mode_ > 2) text_mode_ = 2; // store the filename c = data_filename->value(); if (filename_ && strcmp(filename_, data_filename->value())) set_modflag(1); else if (!filename_ && *c) set_modflag(1); if (filename_) { free((void*)filename_); filename_ = 0L; } if (c && *c) filename_ = fl_strdup(c); // store the comment c = data_comment_input->buffer()->text(); if (c && *c) { if (!comment() || strcmp(c, comment())) { set_modflag(1); redraw_browser(); } comment(c); } else { if (comment()) { set_modflag(1); redraw_browser(); } comment(0); } if (c) free((void*)c); set_modflag(1); break; } BREAK2: data_panel->hide(); } /** Write the content of the external file inline into the source code. */ void Fl_Data_Type::write_code1(Fd_Code_Writer& f) { const char *message = 0; const char *c = name(); if (!c) return; const char *fn = filename_; char *data = 0; int nData = -1; int uncompressedDataSize = 0; // path should be set correctly already if (filename_ && !f.write_codeview) { enter_project_dir(); FILE *f = fl_fopen(filename_, "rb"); leave_project_dir(); if (!f) { message = "Can't include data from file. Can't open"; } else { fseek(f, 0, SEEK_END); nData = (int)ftell(f); fseek(f, 0, SEEK_SET); if (nData) { data = (char*)calloc(nData, 1); if (fread(data, nData, 1, f)==0) { /* use default */ } if (text_mode_ == 2) { uncompressedDataSize = nData; uLong nzData = compressBound(nData); Bytef *zdata = (Bytef*)::malloc(nzData); if (compress(zdata, &nzData, (Bytef*)data, nData) != Z_OK) { /* error */ } ::free(data); data = (char*)zdata; nData = (int)nzData; } } fclose(f); } } else { fn = filename_ ? filename_ : ""; } if (is_in_class()) { f.write_public(public_); if (text_mode_ == 1) { f.write_h("%sstatic const char *%s;\n", f.indent(1), c); f.write_c("\n"); write_comment_c(f); f.write_c("const char *%s::%s = /* text inlined from %s */\n", class_name(1), c, fn); if (message) f.write_c("#error %s %s\n", message, fn); f.write_cstring(data, nData); } else if (text_mode_ == 2) { f.write_h("%sstatic int %s_size;\n", f.indent(1), c); f.write_h("%sstatic unsigned char %s[%d];\n", f.indent(1), c, nData); f.write_c("\n"); write_comment_c(f); f.write_c("int %s::%s_size = %d;\n", class_name(1), c, uncompressedDataSize); f.write_c("unsigned char %s::%s[%d] = /* data compressed and inlined from %s */\n", class_name(1), c, nData, fn); if (message) f.write_c("#error %s %s\n", message, fn); f.write_cdata(data, nData); } else { f.write_h("%sstatic unsigned char %s[%d];\n", f.indent(1), c, nData); f.write_c("\n"); write_comment_c(f); f.write_c("unsigned char %s::%s[%d] = /* data inlined from %s */\n", class_name(1), c, nData, fn); if (message) f.write_c("#error %s %s\n", message, fn); f.write_cdata(data, nData); } f.write_c(";\n"); } else { // the "header only" option does not apply here! if (public_) { if (static_) { if (text_mode_ == 1) { f.write_h("extern const char *%s;\n", c); f.write_c("\n"); write_comment_c(f); f.write_c("const char *%s = /* text inlined from %s */\n", c, fn); if (message) f.write_c("#error %s %s\n", message, fn); f.write_cstring(data, nData); } else if (text_mode_ == 2) { f.write_h("extern int %s_size;\n", c); f.write_h("extern unsigned char %s[%d];\n", c, nData); f.write_c("\n"); write_comment_c(f); f.write_c("int %s_size = %d;\n", c, uncompressedDataSize); f.write_c("unsigned char %s[%d] = /* data compressed and inlined from %s */\n", c, nData, fn); if (message) f.write_c("#error %s %s\n", message, fn); f.write_cdata(data, nData); } else { f.write_h("extern unsigned char %s[%d];\n", c, nData); f.write_c("\n"); write_comment_c(f); f.write_c("unsigned char %s[%d] = /* data inlined from %s */\n", c, nData, fn); if (message) f.write_c("#error %s %s\n", message, fn); f.write_cdata(data, nData); } f.write_c(";\n"); } else { write_comment_h(f); f.write_h("#error Unsupported declaration loading inline data %s\n", fn); if (text_mode_ == 1) f.write_h("const char *%s = \"abc...\";\n", c); else f.write_h("unsigned char %s[3] = { 1, 2, 3 };\n", c); } } else { f.write_c("\n"); write_comment_c(f); if (static_) f.write_c("static "); if (text_mode_ == 1) { f.write_c("const char *%s = /* text inlined from %s */\n", c, fn); if (message) f.write_c("#error %s %s\n", message, fn); f.write_cstring(data, nData); } else if (text_mode_ == 2) { f.write_c("int %s_size = %d;\n", c, uncompressedDataSize); if (static_) f.write_c("static "); f.write_c("unsigned char %s[%d] = /* data compressed and inlined from %s */\n", c, nData, fn); if (message) f.write_c("#error %s %s\n", message, fn); f.write_cdata(data, nData); } else { f.write_c("unsigned char %s[%d] = /* data inlined from %s */\n", c, nData, fn); if (message) f.write_c("#error %s %s\n", message, fn); f.write_cdata(data, nData); } f.write_c(";\n"); } } // if we are in interactive mode, we pop up a warning dialog // giving the error: (batch_mode && !write_codeview) ??? if (message && !f.write_codeview) { if (batch_mode) fprintf(stderr, "FLUID ERROR: %s %s\n", message, fn); else fl_alert("%s\n%s\n", message, fn); } if (data) free(data); } // ---- Fl_DeclBlock_Type declaration /** \class Fl_DeclBlock_Type Manage a declaration block. Declaration blocks have two text field that are written before and after the children of this block. This block is located at the top level and is written to the source file, and to the header file, if declared public. */ /// Prototype for a declaration block to be used by the factory. Fl_DeclBlock_Type Fl_DeclBlock_type; /** Constructor. */ Fl_DeclBlock_Type::Fl_DeclBlock_Type() : Fl_Type(), after(NULL), write_map_(CODE_IN_SOURCE) { } /** Destructor. */ Fl_DeclBlock_Type::~Fl_DeclBlock_Type() { if (after) ::free((void*)after); } /** Return 1 if this block is public. */ int Fl_DeclBlock_Type::is_public() const { return ((write_map_&CODE_IN_HEADER) != 0); } /** Create a new declaration block. \param[in] strategy add after current or as last child \return new Declaration Block node */ Fl_Type *Fl_DeclBlock_Type::make(Strategy strategy) { Fl_Type *anchor = Fl_Type::current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_decl_block()) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type(); o->name("#if 1"); o->write_map_ = CODE_IN_SOURCE; o->after = fl_strdup("#endif"); o->add(anchor, strategy); o->factory = this; return o; } /** Write the specific properties. - "public"/"protected" - "after" followed by the second code block. */ void Fl_DeclBlock_Type::write_properties(Fd_Project_Writer &f) { Fl_Type::write_properties(f); // deprecated if (is_public()) f.write_string("public"); // new way to map declaration block to various parts of the generated code if (write_map_ != CODE_IN_SOURCE) f.write_string("map %d", write_map_); f.write_string("after"); f.write_word(after); } /** Read the specific properties. */ void Fl_DeclBlock_Type::read_property(Fd_Project_Reader &f, const char *c) { if(!strcmp(c,"public")) { write_map_ |= CODE_IN_HEADER; } else if(!strcmp(c,"protected")) { // } else if(!strcmp(c,"map")) { write_map_ = (int)atol(f.read_word()); } else if (!strcmp(c,"after")) { storestring(f.read_word(),after); } else { Fl_Type::read_property(f, c); } } /** Open the declblock_panel to edit this node. */ void Fl_DeclBlock_Type::open() { // build dialog box if (!declblock_panel) make_declblock_panel(); // preset all values declblock_before_input->value(name()); declblock_after_input->value(after); declblock_static_header->value(write_map_ & STATIC_IN_HEADER); declblock_static_source->value(write_map_ & STATIC_IN_SOURCE); declblock_code_header->value(write_map_ & CODE_IN_HEADER); declblock_code_source->value(write_map_ & CODE_IN_SOURCE); const char *c = comment(); declblock_comment_input->buffer()->text(c?c:""); // show modal dialog and loop until satisfied declblock_panel->show(); const char* message = 0; for (;;) { // repeat as long as there are errors for (;;) { Fl_Widget* w = Fl::readqueue(); if (w == declblock_panel_cancel) goto BREAK2; else if (w == declblock_panel_ok) break; else if (!w) Fl::wait(); } // verify user input const char* a = declblock_before_input->value(); while (isspace(*a)) a++; const char* b = declblock_after_input->value(); while (isspace(*b)) b++; message = c_check(a&&a[0]=='#' ? a+1 : a); if (!message) message = c_check(b&&b[0]=='#' ? b+1 : b); if (message) { int v = fl_choice("Potential syntax error detected: %s", "Continue Editing", "Ignore Error", NULL, message); if (v==0) continue; // Continue Editing //if (v==1) { } // Ignore Error and close dialog } // store user choices in data structure name(a); storestring(b, after); if (write_map_ & STATIC_IN_HEADER) { if (declblock_static_header->value()==0) { write_map_ &= ~STATIC_IN_HEADER; set_modflag(1); } } else { if (declblock_static_header->value()) { write_map_ |= STATIC_IN_HEADER; set_modflag(1); } } if (write_map_ & STATIC_IN_SOURCE) { if (declblock_static_source->value()==0) { write_map_ &= ~STATIC_IN_SOURCE; set_modflag(1); } } else { if (declblock_static_source->value()) { write_map_ |= STATIC_IN_SOURCE; set_modflag(1); } } if (write_map_ & CODE_IN_HEADER) { if (declblock_code_header->value()==0) { write_map_ &= ~CODE_IN_HEADER; set_modflag(1); } } else { if (declblock_code_header->value()) { write_map_ |= CODE_IN_HEADER; set_modflag(1); } } if (write_map_ & CODE_IN_SOURCE) { if (declblock_code_source->value()==0) { write_map_ &= ~CODE_IN_SOURCE; set_modflag(1); } } else { if (declblock_code_source->value()) { write_map_ |= CODE_IN_SOURCE; set_modflag(1); } } c = declblock_comment_input->buffer()->text(); if (c && *c) { if (!comment() || strcmp(c, comment())) { set_modflag(1); redraw_browser(); } comment(c); } else { if (comment()) { set_modflag(1); redraw_browser(); } comment(0); } if (c) free((void*)c); break; } BREAK2: declblock_panel->hide(); } /** Write the \b before static code to the source file, and to the header file if declared public. The before code is stored in the name() field. */ void Fl_DeclBlock_Type::write_static(Fd_Code_Writer& f) { const char* c = name(); if (c && *c) { if (write_map_ & STATIC_IN_HEADER) f.write_h("%s\n", c); if (write_map_ & STATIC_IN_SOURCE) f.write_c("%s\n", c); } } /** Write the \b after static code to the source file, and to the header file if declared public. */ void Fl_DeclBlock_Type::write_static_after(Fd_Code_Writer& f) { const char* c = after; if (c && *c) { if (write_map_ & STATIC_IN_HEADER) f.write_h("%s\n", c); if (write_map_ & STATIC_IN_SOURCE) f.write_c("%s\n", c); } } /** Write the \b before code to the source file, and to the header file if declared public. The before code is stored in the name() field. */ void Fl_DeclBlock_Type::write_code1(Fd_Code_Writer& f) { const char* c = name(); if (c && *c) { if (write_map_ & CODE_IN_HEADER) f.write_h("%s\n", c); if (write_map_ & CODE_IN_SOURCE) f.write_c("%s\n", c); } } /** Write the \b after code to the source file, and to the header file if declared public. */ void Fl_DeclBlock_Type::write_code2(Fd_Code_Writer& f) { const char* c = after; if (c && *c) { if (write_map_ & CODE_IN_HEADER) f.write_h("%s\n", c); if (write_map_ & CODE_IN_SOURCE) f.write_c("%s\n", c); } } // ---- Fl_Comment_Type declaration /** \class Fl_Comment_Type Manage a comment node. The comment field takes one or more lines of ASCII text. If the text starts with a '/' and a '*', Fluid assumes that the text is already formatted. If not, every line will be preceded with "// ". */ /// Prototype for a comment node to be used by the factory. Fl_Comment_Type Fl_Comment_type; /** Constructor. */ Fl_Comment_Type::Fl_Comment_Type() : in_c_(1), in_h_(1), style_(0) { } /** Make a new comment node. \param[in] strategy add after current or as last child \return new Comment node */ Fl_Type *Fl_Comment_Type::make(Strategy strategy) { Fl_Type *anchor = Fl_Type::current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_code_block()) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } Fl_Comment_Type *o = new Fl_Comment_Type(); o->in_c_ = 1; o->in_h_ = 1; o->style_ = 0; o->name("my comment"); o->add(anchor, strategy); o->factory = this; return o; } /** Write respective properties. - "in_source"/"not_in_source" if the comment will be written to the source code - "in_header"/"not_in_header" if the comment will be written to the header file */ void Fl_Comment_Type::write_properties(Fd_Project_Writer &f) { Fl_Type::write_properties(f); if (in_c_) f.write_string("in_source"); else f.write_string("not_in_source"); if (in_h_) f.write_string("in_header"); else f.write_string("not_in_header"); } /** Read extra properties. */ void Fl_Comment_Type::read_property(Fd_Project_Reader &f, const char *c) { if (!strcmp(c,"in_source")) { in_c_ = 1; } else if (!strcmp(c,"not_in_source")) { in_c_ = 0; } else if (!strcmp(c,"in_header")) { in_h_ = 1; } else if (!strcmp(c,"not_in_header")) { in_h_ = 0; } else { Fl_Type::read_property(f, c); } } /** Load available preset comments. Fluid comes with GPL and LGPL preset for comments. Users can add their own presets which are stored per user in a separate preferences database. */ static void load_comments_preset(Fl_Preferences &menu) { static const char * const predefined_comment[] = { "GNU Public License v3/GPL Header", "GNU Public License v3/GPL Footer", "GNU Public License v3/LGPL Header", "GNU Public License v3/LGPL Footer", "FLTK/Header" }; int i, n; menu.get("n", n, -1); if (n == -1) menu.set("n", 5); menu.set("version", 10400); Fl_Preferences db(Fl_Preferences::USER_L, "fltk.org", "fluid_comments"); for (i=0; i<5; i++) { menu.set(Fl_Preferences::Name(i), predefined_comment[i]); db.set(predefined_comment[i], comment_text[i]); } } /** Open the comment_panel to edit this node. */ void Fl_Comment_Type::open() { if (!comment_panel) make_comment_panel(); const char *text = name(); { int i=0, n=0, version = 0; Fl_Preferences menu(Fl_Preferences::USER_L, "fltk.org", "fluid_comments_menu"); comment_predefined->clear(); comment_predefined->add("_Edit/Add current comment..."); comment_predefined->add("_Edit/Remove last selection..."); menu.get("version", version, -1); if (version < 10400) load_comments_preset(menu); menu.get("n", n, 0); for (i=0;iadd(text); free(text); } } comment_input->buffer()->text( text ? text : "" ); comment_in_source->value(in_c_); comment_in_header->value(in_h_); comment_panel->show(); char itempath[FL_PATH_MAX]; itempath[0] = 0; int last_selected_item = 0; for (;;) { // repeat as long as there are errors for (;;) { Fl_Widget* w = Fl::readqueue(); if (w == comment_panel_cancel) goto BREAK2; else if (w == comment_panel_ok) break; else if (w == comment_predefined) { if (comment_predefined->value()==1) { // add the current comment to the database const char *xname = fl_input( "Please enter a name to reference the current\ncomment in your database.\n\n" "Use forward slashes '/' to create submenus.", "My Comment"); if (xname) { char *name = fl_strdup(xname); for (char*s=name;*s;s++) if (*s==':') *s = ';'; int n; Fl_Preferences db(Fl_Preferences::USER_L, "fltk.org", "fluid_comments"); db.set(name, comment_input->buffer()->text()); Fl_Preferences menu(Fl_Preferences::USER_L, "fltk.org", "fluid_comments_menu"); menu.get("n", n, 0); menu.set(Fl_Preferences::Name(n), name); menu.set("n", ++n); comment_predefined->add(name); free(name); } } else if (comment_predefined->value()==2) { // remove the last selected comment from the database if (itempath[0]==0 || last_selected_item==0) { fl_message("Please select an entry from this menu first."); } else if (fl_choice("Are you sure that you want to delete the entry\n" "\"%s\"\nfrom the database?", "Cancel", "Delete", NULL, itempath)) { Fl_Preferences db(Fl_Preferences::USER_L, "fltk.org", "fluid_comments"); db.deleteEntry(itempath); comment_predefined->remove(last_selected_item); Fl_Preferences menu(Fl_Preferences::USER_L, "fltk.org", "fluid_comments_menu"); int i, n; for (i=4, n=0; isize(); i++) { const Fl_Menu_Item *mi = comment_predefined->menu()+i; if (comment_predefined->item_pathname(itempath, 255, mi)==0) { if (itempath[0]=='/') memmove(itempath, itempath+1, 255); if (itempath[0]) menu.set(Fl_Preferences::Name(n++), itempath); } } menu.set("n", n); } } else { // load the selected comment from the database if (comment_predefined->item_pathname(itempath, 255)==0) { if (itempath[0]=='/') memmove(itempath, itempath+1, 255); Fl_Preferences db(Fl_Preferences::USER_L, "fltk.org", "fluid_comments"); char *text; db.get(itempath, text, "(no text found in data base)"); comment_input->buffer()->text(text); free(text); last_selected_item = comment_predefined->value(); } } } else if (w == comment_load) { // load a comment from disk fl_file_chooser_ok_label("Use File"); const char *fname = fl_file_chooser("Pick a comment", 0L, 0L); fl_file_chooser_ok_label(NULL); if (fname) { if (comment_input->buffer()->loadfile(fname)) { fl_alert("Error loading file\n%s", fname); } } } else if (!w) Fl::wait(); } char*c = comment_input->buffer()->text(); name(c); free(c); int mod = 0; if (in_c_ != comment_in_source->value()) { in_c_ = comment_in_source->value(); mod = 1; } if (in_h_ != comment_in_header->value()) { in_h_ = comment_in_header->value(); mod = 1; } if (mod) set_modflag(1); break; } BREAK2: comment_panel->hide(); } /** Write the comment to the files. */ void Fl_Comment_Type::write_code1(Fd_Code_Writer& f) { const char* c = name(); if (!c) return; if (!in_c_ && !in_h_) return; // find out if there is already a valid comment: const char *s = c; while (isspace(*s)) s++; // if this seems to be a C style comment, copy the block as is // (it's up to the user to correctly close the comment) if (s[0]=='/' && s[1]=='*') { if (in_h_) f.write_h("%s\n", c); if (in_c_) f.write_c("%s\n", c); return; } // copy the comment line by line, add the double slash if needed char *txt = fl_strdup(c); char *b = txt, *e = txt; for (;;) { // find the end of the line and set it to NUL while (*e && *e!='\n') e++; char eol = *e; *e = 0; // check if there is a C++ style comment at the beginning of the line char *s = b; while (isspace(*s)) s++; if (s!=e && ( s[0]!='/' || s[1]!='/') ) { // if no comment marker was found, we add one ourselves if (in_h_) f.write_h("// "); if (in_c_) f.write_c("// "); } // now copy the rest of the line if (in_h_) f.write_h("%s\n", b); if (in_c_) f.write_c("%s\n", b); if (eol==0) break; *e++ = eol; b = e; } free(txt); } // ---- Fl_Class_Type declaration /** \class Fl_Class_Type Manage a class declaration and implementation. */ /// Prototype for a class node to be used by the factory. Fl_Class_Type Fl_Class_type; /** Constructor. */ Fl_Class_Type::Fl_Class_Type() : Fl_Type(), subclass_of(NULL), public_(1), class_prefix(NULL) { } /** Destructor. */ Fl_Class_Type::~Fl_Class_Type() { if (subclass_of) free((void*)subclass_of); if (class_prefix) free((void*)class_prefix); } /** Return 1 if this class is marked public. */ int Fl_Class_Type::is_public() const { return public_; } /** Set the prefixx string. */ void Fl_Class_Type::prefix(const char*p) { free((void*) class_prefix); class_prefix=fl_strdup(p ? p : "" ); } /** Make a new class node. \param[in] strategy add after current or as last child \return new Class node */ Fl_Type *Fl_Class_Type::make(Strategy strategy) { Fl_Type *anchor = Fl_Type::current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_decl_block()) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } Fl_Class_Type *o = new Fl_Class_Type(); o->name("UserInterface"); o->class_prefix = NULL; o->subclass_of = NULL; o->public_ = 1; o->add(anchor, strategy); o->factory = this; return o; } /** Write the respective properties. - ":" followed by the super class - "private"/"protected" */ void Fl_Class_Type::write_properties(Fd_Project_Writer &f) { Fl_Type::write_properties(f); if (subclass_of) { f.write_string(":"); f.write_word(subclass_of); } switch (public_) { case 0: f.write_string("private"); break; case 2: f.write_string("protected"); break; } } /** Read additional properties. */ void Fl_Class_Type::read_property(Fd_Project_Reader &f, const char *c) { if (!strcmp(c,"private")) { public_ = 0; } else if (!strcmp(c,"protected")) { public_ = 2; } else if (!strcmp(c,":")) { storestring(f.read_word(), subclass_of); } else { Fl_Type::read_property(f, c); } } /** Open the class_panel to edit the class name and superclass name. */ void Fl_Class_Type::open() { if (!class_panel) make_class_panel(); char fullname[FL_PATH_MAX]=""; if (prefix() && strlen(prefix())) sprintf(fullname,"%s %s",prefix(),name()); else strcpy(fullname, name()); c_name_input->value(fullname); c_subclass_input->value(subclass_of); c_public_button->value(public_); const char *c = comment(); c_comment_input->buffer()->text(c?c:""); class_panel->show(); const char* message = 0; char *na=0,*pr=0,*p=0; // name and prefix substrings for (;;) { // repeat as long as there are errors // we don;t give the option to ignore this error here because code depends // on this being a C++ identifier if (message) fl_alert("%s", message); for (;;) { Fl_Widget* w = Fl::readqueue(); if (w == c_panel_cancel) goto BREAK2; else if (w == c_panel_ok) break; else if (!w) Fl::wait(); } const char*c = c_name_input->value(); char *s = fl_strdup(c); size_t len = strlen(s); if (!*s) goto OOPS; p = (char*) (s+len-1); while (p>=s && isspace(*p)) *(p--)='\0'; if (p=s && is_id(*p)) p--; if ( (ps) *p--='\0'; while (p>=s && isspace(*p)) *(p--)='\0'; while (p>=s && is_id(*p)) p--; if (pvalue(); message = c_check(c); if (message) { free((void*)s);continue;} name(na); prefix(pr); free((void*)s); storestring(c, subclass_of); if (public_ != c_public_button->value()) { public_ = c_public_button->value(); set_modflag(1); } c = c_comment_input->buffer()->text(); if (c && *c) { if (!comment() || strcmp(c, comment())) { set_modflag(1); redraw_browser(); } comment(c); } else { if (comment()) { set_modflag(1); redraw_browser(); } comment(0); } if (c) free((void*)c); break; } BREAK2: class_panel->hide(); } /** Write the header code that declares this class. */ void Fl_Class_Type::write_code1(Fd_Code_Writer& f) { parent_class = current_class; current_class = this; write_public_state = 0; f.write_h("\n"); write_comment_h(f); if (prefix() && strlen(prefix())) f.write_h("class %s %s ", prefix(), name()); else f.write_h("class %s ", name()); if (subclass_of) f.write_h(": %s ", subclass_of); f.write_h("{\n"); } /** Write the header code that ends the declaration of this class. */ void Fl_Class_Type::write_code2(Fd_Code_Writer& f) { f.write_h("};\n"); current_class = parent_class; } /** Return 1 if this class contains a function with the given signature. */ int Fl_Type::has_function(const char *rtype, const char *sig) const { Fl_Type *child; for (child = next; child && child->level > level; child = child->next) { if (child->level == level+1 && child->is_a(ID_Function)) { const Fl_Function_Type *fn = (const Fl_Function_Type*)child; if (fn->has_signature(rtype, sig)) return 1; } } return 0; } fltk-1.4.3/fluid/mergeback.cxx0000644000175000017500000004165615004135251016370 0ustar albrechtalbrecht// // MergeBack routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #if 0 // Matt: disabled #include "mergeback.h" #include "fluid.h" #include "code.h" #include "undo.h" #include "Fl_Function_Type.h" #include "Fl_Widget_Type.h" #include #include #include #include #include #include #include extern void propagate_load(Fl_Group*, void*); extern void load_panel(); extern void redraw_browser(); // TODO: add application user setting to control mergeback // [] new projects default to mergeback // [] check mergeback when loading project // [] check mergeback when app gets focus // [] always apply if safe // TODO: command line option for mergeback // -mb or --merge-back // -mbs or --merge-back-if-safe // NOTE: automatic mergeback on timer when file changes if app focus doesn't work // NOTE: allow the user to edit comment blocks /** Merge external changes in a source code file back into the current project. This experimental function reads a source code file line by line. When it encounters a special tag in a line, the crc32 stored in the tag is compared to the crc32 that was calculated from the code lines since the previous tag. If the crc's differ, the user has modified the source file externally, and the given block differs from the block as it was generated by FLUID. Depending on the block type, the user has modified the widget code (FD_TAG_GENERIC), which can not be transferred back into the project. Modifications to code blocks and callbacks (CODE, CALLBACK) can be merged back into the project. Their corresponding Fl_Type is found using the unique node id that is part of the tag. The block is only merged back if the crc's from the project and from the edited block differ. The caller must make sure that this code file was generated by the currently loaded project. The user is informed in detailed dialogs what the function discovered and offered to merge or cancel if appropriate. Just in case this function is destructive, "undo" restores the state before a MergeBack. Callers can set different task. FD_MERGEBACK_ANALYSE checks if there are any modifications in the code file and returns -1 if there was an error, or a bit field where bit 0 is set if internal structures were modified, bit 1 if code was changed, and bit 2 if modified blocks were found, but no Type node. Bit 3 is set, if code was changed in the code file *and* the project. FD_MERGEBACK_INTERACTIVE checks for changes and presents a status dialog box to the user if there were conflicting changes or if a mergeback is possible, presenting the user the option to merge or cancel. Returns 0 if the project remains unchanged, and 1 if the user merged changes back. -1 is returned if an invalid tag was found. FD_MERGEBACK_APPLY merges all changes back into the project without any interaction. Returns 0 if nothing changed, and 1 if it merged any changes back. FD_MERGEBACK_APPLY_IF_SAFE merges changes back only if there are no conflicts. Returns 0 if nothing changed, and 1 if it merged any changes back, and -1 if there were conflicts. \note this function is currently part of Fd_Code_Writer to get easy access to our crc32 code that also wrote the code file originally. \param[in] s path and filename of the source code file \param[in] task see above \return -1 if an error was found in a tag \return -2 if no code file was found \return see above */ int merge_back(const Fl_String &s, const Fl_String &p, int task) { if (g_project.write_mergeback_data) { Fd_Mergeback mergeback; return mergeback.merge_back(s, p, task); } else { // nothing to be done if the mergeback option is disabled in the project return 0; } } /** Allocate and initialize MergeBack class. */ Fd_Mergeback::Fd_Mergeback() : code(NULL), line_no(0), tag_error(0), num_changed_code(0), num_changed_structure(0), num_uid_not_found(0), num_possible_override(0) { } /** Release allocated resources. */ Fd_Mergeback::~Fd_Mergeback() { if (code) ::fclose(code); } /** Remove the first two spaces at every line start. \param[inout] s block of C code */ void Fd_Mergeback::unindent(char *s) { char *d = s; bool line_start = true; while (*s) { if (line_start) { if (*s>0 && isspace(*s)) s++; if (*s>0 && isspace(*s)) s++; line_start = false; } if (*s=='\r') s++; if (*s=='\n') line_start = true; *d++ = *s++; } *d = 0; } /** Read a block of text from the source file and remove the leading two spaces in every line. \param[in] start start of the block within the file \param[in] end end of text within the file \return a string holding the text that was found in the file */ Fl_String Fd_Mergeback::read_and_unindent_block(long start, long end) { long bsize = end-start; long here = ::ftell(code); ::fseek(code, start, SEEK_SET); char *block = (char*)::malloc(bsize+1); size_t n = ::fread(block, bsize, 1, code); if (n!=1) block[0] = 0; // read error else block[bsize] = 0; unindent(block); Fl_String str = block; ::free(block); ::fseek(code, here, SEEK_SET); return str; } /** Tell user the results of our MergeBack analysis and pop up a dialog to give the user a choice to merge or cancel. \return 1 if the user wants to merge (choice dialog was shown) \return 0 if there is nothing to merge (no dialog was shown) \return -1 if the user wants to cancel or an error occurred or an issue was presented (message or choice dialog was shown) */ int Fd_Mergeback::ask_user_to_merge(const Fl_String &code_filename, const Fl_String &proj_filename) { if (tag_error) { fl_message("Comparing\n \"%s\"\nto\n \"%s\"\n\n" "MergeBack found an error in line %d while reading tags\n" "from the source code. Merging code back is not possible.", code_filename.c_str(), proj_filename.c_str(), line_no); return -1; } if (!num_changed_code && !num_changed_structure) { return 0; } if (num_changed_structure && !num_changed_code) { fl_message("Comparing\n \"%1$s\"\nto\n \"%2$s\"\n\n" "MergeBack found %3$d modifications in the project structure\n" "of the source code. These kind of changes can no be\n" "merged back and will be lost when the source code is\n" "generated again from the open project.", code_filename.c_str(), proj_filename.c_str(), num_changed_structure); return -1; } Fl_String msg = "Comparing\n \"%1$s\"\nto\n \"%2$s\"\n\n" "MergeBack found %3$d modifications in the source code."; if (num_possible_override) msg += "\n\nWARNING: %6$d of these modified blocks appear to also have\n" "changed in the project. Merging will override changes in\n" "the project with changes from the source code file."; if (num_uid_not_found) msg += "\n\nWARNING: for %4$d of these modifications no Type node\n" "can be found and these modification can't be merged back."; if (!num_possible_override && !num_uid_not_found) msg += "\nMerging these changes back appears to be safe."; if (num_changed_structure) msg += "\n\nWARNING: %5$d modifications were found in the project\n" "structure. These kind of changes can no be merged back\n" "and will be lost when the source code is generated again\n" "from the open project."; if (num_changed_code==num_uid_not_found) { fl_message(msg.c_str(), code_filename.c_str(), proj_filename.c_str(), num_changed_code, num_uid_not_found, num_changed_structure, num_possible_override); return -1; } else { msg += "\n\nClick Cancel to abort the MergeBack operation.\n" "Click Merge to merge all code changes back into\n" "the open project."; int c = fl_choice(msg.c_str(), "Cancel", "Merge", NULL, code_filename.c_str(), proj_filename.c_str(), num_changed_code, num_uid_not_found, num_changed_structure, num_possible_override); if (c==0) return -1; return 1; } } /** Analyse the block and its corresponding widget callback. Return findings in num_changed_code, num_changed_code, and num_uid_not_found. */ void Fd_Mergeback::analyse_callback(unsigned long code_crc, unsigned long tag_crc, int uid) { Fl_Type *tp = Fl_Type::find_by_uid(uid); if (tp && tp->is_true_widget()) { Fl_String cb = tp->callback(); cb += "\n"; unsigned long project_crc = Fd_Code_Writer::block_crc(cb.c_str()); // check if the code and project crc are the same, so this modification was already applied if (project_crc!=code_crc) { num_changed_code++; // check if the block change on the project side as well, so we may override changes if (project_crc!=tag_crc) { num_possible_override++; } } } else { num_uid_not_found++; num_changed_code++; } } /** Analyse the block and its corresponding Code Type. Return findings in num_changed_code, num_changed_code, and num_uid_not_found. */ void Fd_Mergeback::analyse_code(unsigned long code_crc, unsigned long tag_crc, int uid) { Fl_Type *tp = Fl_Type::find_by_uid(uid); if (tp && tp->is_a(ID_Code)) { Fl_String code = tp->name(); code += "\n"; unsigned long project_crc = Fd_Code_Writer::block_crc(code.c_str()); // check if the code and project crc are the same, so this modification was already applied if (project_crc!=code_crc) { num_changed_code++; // check if the block change on the project side as well, so we may override changes if (project_crc!=tag_crc) { num_possible_override++; } } } else { num_changed_code++; num_uid_not_found++; } } /** Analyse the code file and return findings in class member variables. The code file must be open for reading already. * tag_error is set if a tag was found, but could not be read * line_no returns the line where an error occurred * num_changed_code is set to the number of changed code blocks in the file. Code changes can be merged back to the project. * num_changed_structure is set to the number of structural changes. Structural changes outside of code blocks can not be read back. * num_uid_not_found number of blocks that were modified, but the corresponding type or widget can not be found in the project * num_possible_override number of blocks that were changed in the code file, but also were changed in the project. \return -1 if reading a tag failed, otherwise 0 */ int Fd_Mergeback::analyse() { // initialize local variables unsigned long code_crc = 0; bool line_start = true; char line[1024]; // bail if the caller has not opened a file yet if (!code) return 0; // initialize member variables to return our findings line_no = 0; tag_error = 0; num_changed_code = 0; num_changed_structure = 0; num_uid_not_found = 0; num_possible_override = 0; code_crc = 0; // loop through all lines in the code file ::fseek(code, 0, SEEK_SET); for (;;) { // get the next line until end of file if (fgets(line, 1023, code)==0) break; line_no++; const char *tag = strstr(line, "//~fl~"); if (!tag) { // if this line has no tag, add the contents to the CRC and continue code_crc = Fd_Code_Writer::block_crc(line, -1, code_crc, &line_start); } else { // if this line has a tag, read all tag data int tag_type = -1, uid = 0; unsigned long tag_crc = 0; int n = sscanf(tag, "//~fl~%d~%04x~%08lx~~", &tag_type, &uid, &tag_crc); if (n!=3 || tag_type<0 || tag_type>FD_TAG_LAST ) { tag_error = 1; return -1; } if (code_crc != tag_crc) { switch (tag_type) { case FD_TAG_GENERIC: num_changed_structure++; break; case FD_TAG_MENU_CALLBACK: case FD_TAG_WIDGET_CALLBACK: analyse_callback(code_crc, tag_crc, uid); break; case FD_TAG_CODE: analyse_code(code_crc, tag_crc, uid); break; } } // reset everything for the next block code_crc = 0; line_start = true; } } return 0; } /** Apply callback mergebacks from the code file to the project. \return 1 if the project changed */ int Fd_Mergeback::apply_callback(long block_end, long block_start, unsigned long code_crc, int uid) { Fl_Type *tp = Fl_Type::find_by_uid(uid); if (tp && tp->is_true_widget()) { Fl_String cb = tp->callback(); cb += "\n"; unsigned long project_crc = Fd_Code_Writer::block_crc(cb.c_str()); if (project_crc!=code_crc) { tp->callback(read_and_unindent_block(block_start, block_end).c_str()); return 1; } } return 0; } /** Apply callback mergebacks from the code file to the project. \return 1 if the project changed */ int Fd_Mergeback::apply_code(long block_end, long block_start, unsigned long code_crc, int uid) { Fl_Type *tp = Fl_Type::find_by_uid(uid); if (tp && tp->is_a(ID_Code)) { Fl_String cb = tp->name(); cb += "\n"; unsigned long project_crc = Fd_Code_Writer::block_crc(cb.c_str()); if (project_crc!=code_crc) { tp->name(read_and_unindent_block(block_start, block_end).c_str()); return 1; } } return 0; } /** Apply all possible mergebacks from the code file to the project. The code file must be open for reading already. \return -1 if reading a tag failed, 0 if nothing changed, 1 if the project changed */ int Fd_Mergeback::apply() { // initialize local variables unsigned long code_crc = 0; bool line_start = true; char line[1024]; int changed = 0; long block_start = 0; long block_end = 0; // bail if the caller has not opened a file yet if (!code) return 0; // initialize member variables to return our findings line_no = 0; tag_error = 0; code_crc = 0; // loop through all lines in the code file ::fseek(code, 0, SEEK_SET); for (;;) { // get the next line until end of file if (fgets(line, 1023, code)==0) break; line_no++; const char *tag = strstr(line, "//~fl~"); if (!tag) { // if this line has no tag, add the contents to the CRC and continue code_crc = Fd_Code_Writer::block_crc(line, -1, code_crc, &line_start); block_end = ::ftell(code); } else { // if this line has a tag, read all tag data int tag_type = -1, uid = 0; unsigned long tag_crc = 0; int n = sscanf(tag, "//~fl~%d~%04x~%08lx~~", &tag_type, &uid, &tag_crc); if (n!=3 || tag_type<0 || tag_type>FD_TAG_LAST ) { tag_error = 1; return -1; } if (code_crc != tag_crc) { if (tag_type==FD_TAG_MENU_CALLBACK || tag_type==FD_TAG_WIDGET_CALLBACK) { changed |= apply_callback(block_end, block_start, code_crc, uid); } else if (tag_type==FD_TAG_CODE) { changed |= apply_code(block_end, block_start, code_crc, uid); } } // reset everything for the next block code_crc = 0; line_start = true; block_start = ::ftell(code); } } return changed; } /** Dispatch the MergeBack into analysis, interactive, or apply directly. \param[in] s source code filename and path \param[in] task one of FD_MERGEBACK_ANALYSE, FD_MERGEBACK_INTERACTIVE, FD_MERGEBACK_APPLY_IF_SAFE, or FD_MERGEBACK_APPLY \return -1 if an error was found in a tag \return -2 if no code file was found \return See more at ::merge_back(const Fl_String &s, int task). */ int Fd_Mergeback::merge_back(const Fl_String &s, const Fl_String &p, int task) { int ret = 0; code = fl_fopen(s.c_str(), "rb"); if (!code) return -2; do { // no actual loop, just make sure we close the code file if (task == FD_MERGEBACK_ANALYSE) { analyse(); if (tag_error) {ret = -1; break; } if (num_changed_structure) ret |= 1; if (num_changed_code) ret |= 2; if (num_uid_not_found) ret |= 4; if (num_possible_override) ret |= 8; break; } if (task == FD_MERGEBACK_INTERACTIVE) { analyse(); ret = ask_user_to_merge(s, p); if (ret != 1) return ret; task = FD_MERGEBACK_APPLY; // fall through } if (task == FD_MERGEBACK_APPLY_IF_SAFE) { analyse(); if (tag_error || num_changed_structure || num_possible_override) { ret = -1; break; } if (num_changed_code==0) { ret = 0; break; } task = FD_MERGEBACK_APPLY; // fall through } if (task == FD_MERGEBACK_APPLY) { ret = apply(); if (ret == 1) { set_modflag(1); redraw_browser(); load_panel(); } ret = 1; // avoid message box in caller } } while (0); fclose(code); code = NULL; return ret; } #endif fltk-1.4.3/fluid/settings_panel.fl0000644000175000017500000020062315004135251017255 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} snap { ver 1 current_suite {FLUID (based on FLTK)} current_preset 0 suite { name {FLUID (based on FLTK)} preset { 1 15 15 15 15 0 0 10 10 10 10 0 0 25 25 20 10 4 20 4 8 0 14 0 14 } preset { 1 10 10 10 10 0 0 10 10 10 10 0 0 20 20 20 10 5 20 5 5 0 11 0 11 } preset { 1 10 10 10 10 0 0 10 10 10 10 0 0 18 18 16 8 2 16 4 2 0 10 0 10 } } } comment {// // Setting and shell dialogs for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // } {in_source in_header } decl {\#include "fluid.h"} {public global } decl {\#include "undo.h"} {private global } decl {\#include "widget_browser.h"} {public global } decl {\#include "Fd_Snap_Action.h"} {public global } decl {\#include "shell_command.h"} {public global } decl {\#include } {public local } decl {\#include } {public local } decl {\#include "fluid_filename.h"} {public local } decl {\#include } {public local } decl {\#include } {public local } decl {\#include } {private global } decl {\#include } {private global } decl {\#include } {private global } decl {\#include } {private global } decl {\#include "../src/flstring.h"} {private global } decl {void init_scheme(void);} { comment {// initialize the scheme from preferences} public global } decl {extern struct Fl_Menu_Item *dbmanager_item;} {public local } decl {extern void i18n_cb(Fl_Choice *,void *);} {public local } decl {void scheme_cb(Fl_Scheme_Choice *, void *);} {public local } decl {int w_settings_shell_list_selected;} {public local } Function {cb_Comments(Fl_Choice* o, void* v)} {open private return_type void } { code {Fl_Font *font = (Fl_Font*)o->user_data(); if (v == LOAD) { o->value(*font); } else { *font = (int)o->value(); widget_browser->redraw(); widget_browser->save_prefs(); }} {} } Function {cb_Color_Chip(Fl_Button* o, void* v)} {open private return_type void } { code {Fl_Color *color = (Fl_Color*)o->user_data(); if (v == LOAD) { o->color(*color); o->redraw(); } else { Fl_Color d = fl_show_colormap(*color); *color = d; o->color(d); widget_browser->redraw(); widget_browser->save_prefs(); }} {} } Function {cb_Color_Choice(Fl_Menu_Button* o, void* v)} {open private return_type void } { code {if (v != LOAD) { Fl_Color *color = (Fl_Color*)o->user_data(); Fl_Color d = (Fl_Color)(o->mvalue()->argument()); *color = d; o->parent()->do_callback(o->parent(), LOAD); widget_browser->redraw(); widget_browser->save_prefs(); }} {} } Function {make_script_panel()} {open } { Fl_Window script_panel { label {Shell Script Editor} callback {if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape) return; // ignore Escape script_panel->hide(); // otherwise hide..} open xywh {764 319 540 180} type Double labelsize 11 resizable code0 {o->size_range(200, 150);} modal visible } { Fl_Text_Editor script_input { xywh {10 10 520 130} box DOWN_BOX labelsize 11 when 13 textfont 4 textsize 11 resizable code0 {script_input->buffer(new Fl_Text_Buffer);} } Fl_Group {} { callback propagate_load open xywh {10 150 520 20} labelsize 11 } { Fl_Return_Button script_panel_ok { label OK xywh {400 150 60 20} labelsize 11 hotspot } Fl_Button script_panel_cancel { label Cancel xywh {470 150 60 20} labelsize 11 } Fl_Box {} { xywh {10 150 380 20} labelsize 11 resizable } } } code {// Enable line numbers script_input->linenumber_width(60); script_input->linenumber_size(script_input->Fl_Text_Display::textsize());} {} } Function {make_settings_window()} {open } { Fl_Window settings_window { label {FLUID Settings} open xywh {392 362 340 580} type Double align 80 resizable size_range {340 580 0 0} visible } { Fl_Tabs w_settings_tabs { callback {propagate_load(o, v);} open xywh {10 10 320 530} selection_color 12 labelsize 11 labelcolor 255 resizable } { Fl_Group w_settings_general_tab { label General open selected scale_image {36 24} image {icons/general_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11 resizable } { Fl_Group {} { callback {propagate_load(o, v);} open xywh {120 78 130 25} } { Fl_Choice scheme_choice { label {Scheme: } callback scheme_cb open xywh {120 78 120 25} down_box BORDER_BOX labelfont 1 labelsize 11 code0 {init_scheme();} class Fl_Scheme_Choice } {} Fl_Box {} { xywh {240 78 10 25} hide resizable } } Fl_Box {} { label {Options: } xywh {120 115 0 20} labelfont 1 labelsize 11 align 4 } Fl_Check_Button tooltips_button { label {Show Tooltips} callback {Fl_Tooltip::enable(tooltips_button->value()); fluid_prefs.set("show_tooltips", tooltips_button->value());} xywh {120 115 200 20} down_box DOWN_BOX labelsize 11 code0 {int b;} code1 {fluid_prefs.get("show_tooltips", b, 1);} code2 {tooltips_button->value(b);} code3 {Fl_Tooltip::enable(b);} } Fl_Check_Button completion_button { label {Show Completion Dialogs} callback {fluid_prefs.set("show_completion_dialogs", completion_button->value());} xywh {120 135 200 20} down_box DOWN_BOX labelsize 11 code0 {int b;} code1 {fluid_prefs.get("show_completion_dialogs", b, 1);} code2 {completion_button->value(b);} } Fl_Check_Button openlast_button { label {Open Previous File on Startup} callback {fluid_prefs.set("open_previous_file", openlast_button->value());} xywh {120 155 200 20} down_box DOWN_BOX labelsize 11 code0 {int b;} code1 {fluid_prefs.get("open_previous_file", b, 0);} code2 {openlast_button->value(b);} } Fl_Check_Button prevpos_button { label {Remember Window Positions} callback {fluid_prefs.set("prev_window_pos", prevpos_button->value());} xywh {120 175 200 20} down_box DOWN_BOX labelsize 11 code0 {int b;} code1 {fluid_prefs.get("prev_window_pos", b, 1);} code2 {prevpos_button->value(b);} } Fl_Check_Button show_comments_button { label {Show Comments in Browser} callback {show_comments = show_comments_button->value(); fluid_prefs.set("show_comments", show_comments); redraw_browser();} xywh {120 195 200 20} down_box DOWN_BOX labelsize 11 code1 {fluid_prefs.get("show_comments", show_comments, 1);} code2 {show_comments_button->value(show_comments);} } Fl_Group {} { callback {propagate_load(o, v);} open xywh {120 225 50 20} } { Fl_Spinner recent_spinner { label {\# Recent Files:} callback {fluid_prefs.set("recent_files", recent_spinner->value()); load_history();} xywh {120 225 40 20} labelfont 1 labelsize 11 when 1 maximum 10 textsize 11 code0 {int c;} code1 {fluid_prefs.get("recent_files", c, 5);} code2 {recent_spinner->maximum(10);} code3 {recent_spinner->value(c);} } Fl_Box {} { xywh {160 225 10 20} hide resizable } } Fl_Check_Button use_external_editor_button { label {Use for Code Nodes} callback {G_use_external_editor = use_external_editor_button->value(); fluid_prefs.set("use_external_editor", G_use_external_editor); redraw_browser();} xywh {120 275 200 20} down_box DOWN_BOX labelsize 11 code1 {fluid_prefs.get("use_external_editor", G_use_external_editor, 0);} code2 {use_external_editor_button->value(G_use_external_editor);} } Fl_Input editor_command_input { label {External Editor:} callback {strncpy(G_external_editor_command, editor_command_input->value(), sizeof(G_external_editor_command)-1); G_external_editor_command[sizeof(G_external_editor_command)-1] = 0; fluid_prefs.set("external_editor_command", G_external_editor_command); redraw_browser();} tooltip {The editor command to open your external text editor. Include any necessary flags to ensure your editor does not background itself. Examples: gvim -f gedit emacs} xywh {120 255 200 20} labelfont 1 labelsize 11 when 1 textfont 4 textsize 11 code1 {fluid_prefs.get("external_editor_command", G_external_editor_command, "", sizeof(G_external_editor_command)-1);} code2 {editor_command_input->value(G_external_editor_command);} } Fl_Box {} { label {Overlays: } xywh {120 300 0 20} labelfont 1 labelsize 11 align 4 } Fl_Check_Button guides_button { label {Show Positioning Guides} callback toggle_guides_cb tooltip {show guides that help to position and resize widgets and enable snapping} xywh {120 300 200 20} down_box DOWN_BOX labelsize 11 code0 {o->value(show_guides);} } Fl_Check_Button restricted_button { label {Show Restricted Areas} callback toggle_restricted_cb tooltip {show overlapping and out of bounds areas, show unfilled areas in Fl_Pack groups} xywh {120 320 200 20} down_box DOWN_BOX labelsize 11 code0 {o->value(show_restricted);} } Fl_Check_Button ghosted_outline_button { label {Show Ghosted Group Outlines} callback toggle_ghosted_outline_cb tooltip {groups with no box type or flat boxtypes without contrast will be rendered with a dim outline in the editing window only} xywh {120 340 200 20} down_box DOWN_BOX labelsize 11 code0 {o->value(show_ghosted_outline);} } Fl_Box {} { xywh {120 530 200 10} hide resizable } } Fl_Group w_settings_project_tab { label Project callback {propagate_load(o, v);} open scale_image {36 24} image {icons/document_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11 hide } { Fl_Group {} {open xywh {100 78 220 30} } { Fl_Box {} { label {Use "name.ext" to set a file name or just ".ext" to set extension.} xywh {100 78 210 30} labelsize 11 align 148 } Fl_Box {} { xywh {310 78 10 30} hide resizable } } Fl_Input header_file_input { label {Header File:} user_data 1 user_data_type {void*} callback {if (v == LOAD) { o->value(g_project.header_file_name.c_str()); } else { if (strcmp(g_project.header_file_name.c_str(), o->value())) { g_project.header_file_name = o->value(); set_modflag(1); } }} tooltip {The name of the generated header file.} xywh {100 112 220 20} box THIN_DOWN_BOX labelfont 1 labelsize 11 when 1 textfont 4 textsize 11 } Fl_Input code_file_input { label {Code File:} user_data 1 user_data_type {void*} callback {if (v == LOAD) { o->value(g_project.code_file_name.c_str()); } else { if (strcmp(g_project.code_file_name.c_str(), o->value())) { g_project.code_file_name = o->value(); set_modflag(1); } }} tooltip {The name of the generated code file.} xywh {100 137 220 20} box THIN_DOWN_BOX labelfont 1 labelsize 11 when 1 textfont 4 textsize 11 } Fl_Check_Button include_H_from_C_button { label {Include Header from Code} callback {if (v == LOAD) { o->value(g_project.include_H_from_C); } else { if (g_project.include_H_from_C != o->value()) { set_modflag(1); g_project.include_H_from_C = o->value(); } }} tooltip {Include the header file from the code file.} xywh {100 162 220 20} down_box DOWN_BOX labelsize 11 } Fl_Box {} { label {Options: } xywh {100 205 0 20} labelfont 1 labelsize 11 align 4 } Fl_Check_Button use_FL_COMMAND_button { label {Menu shortcuts use FL_COMMAND} callback {if (v == LOAD) { o->value(g_project.use_FL_COMMAND); } else { if (g_project.use_FL_COMMAND != o->value()) { set_modflag(1); g_project.use_FL_COMMAND = o->value(); } }} tooltip {Replace FL_CTRL and FL_META with FL_COMMAND when generating menu shortcuts} xywh {100 205 220 20} down_box DOWN_BOX labelsize 11 } Fl_Check_Button utf8_in_src_button { label {allow Unicode UTF-8 in source code} callback {if (v == LOAD) { o->value(g_project.utf8_in_src); } else { if (g_project.utf8_in_src != o->value()) { set_modflag(1); g_project.utf8_in_src = o->value(); } }} tooltip {For older compilers, characters outside of the printable ASCII range are escaped using octal notation `\\0123`. If this option is checked, Fluid will write UTF-8 characters unchanged.} xywh {100 230 220 20} down_box DOWN_BOX labelsize 11 } Fl_Check_Button avoid_early_includes_button { label {avoid early include of Fl.H} callback {if (v == LOAD) { o->value(g_project.avoid_early_includes); } else { if (g_project.avoid_early_includes != o->value()) { set_modflag(1); g_project.avoid_early_includes = o->value(); } }} tooltip {Do not emit \#include until it is needed by another include file.} xywh {100 255 220 20} down_box DOWN_BOX labelsize 11 } Fl_Box {} { label {Experimental: } xywh {100 283 0 20} labelfont 1 labelsize 11 align 4 hide } Fl_Check_Button w_proj_mergeback { label {generate MergeBack data} callback {if (v == LOAD) { o->value(g_project.write_mergeback_data); } else { if (g_project.write_mergeback_data != o->value()) { set_modflag(1); g_project.write_mergeback_data = o->value(); } }} comment {// Matt: disabled} tooltip {MergeBack is a feature under construction that allows changes in code files to be merged back into the project file. Checking this option will generate additional data in code and project files.} xywh {100 283 220 20} down_box DOWN_BOX labelsize 11 hide } Fl_Box {} { xywh {100 530 220 10} hide resizable } } Fl_Group w_settings_layout_tab { label Layout callback {propagate_load(o, v);} open scale_image {36 24} image {icons/layout_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11 hide } { Fl_Box {} { label {Layout:} xywh {25 78 60 24} labelfont 1 labelsize 11 align 24 } Fl_Choice layout_choice { callback {if (v == LOAD) { o->value(g_layout_list.current_suite()); } else { int index = o->value(); g_layout_list.current_suite(index); g_layout_list.update_dialogs(); }} xywh {85 78 187 24} down_box BORDER_BOX } { MenuItem {} { label FLTK xywh {0 0 31 20} } MenuItem {} { label Grid xywh {0 0 31 20} } } Fl_Button {} { label {+} callback {// Clone the current layout suite if (v == LOAD) return; Fl_String old_name = "Copy of "; old_name.append(g_layout_list[g_layout_list.current_suite()].name_); const char *new_name = fl_input("Enter a name for the new layout:", old_name.c_str()); if (new_name == NULL) return; g_layout_list.add(new_name); g_layout_list.update_dialogs();} xywh {272 78 24 24} } Fl_Menu_Button w_layout_menu { callback {if (v == LOAD) { Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()]; if (suite.storage_ == FD_STORE_INTERNAL) { w_layout_menu_rename->deactivate(); for (int i=1; i<4; i++) w_layout_menu_storage[i]->deactivate(); w_layout_menu_delete->deactivate(); } else { w_layout_menu_rename->activate(); for (int i=1; i<4; i++) w_layout_menu_storage[i]->activate(); w_layout_menu_delete->activate(); } w_layout_menu_storage[suite.storage_]->setonly(); }} open xywh {296 78 24 24} } { MenuItem w_layout_menu_rename { label {Rename...} callback {// Rename the current layout suite Fl_String old_name = g_layout_list[g_layout_list.current_suite()].name_; const char *new_name = fl_input("Enter a new name for the layout:", old_name.c_str()); if (new_name == NULL) return; g_layout_list.rename(new_name); g_layout_list.update_dialogs();} xywh {0 0 31 20} divider } MenuItem {w_layout_menu_storage[0]} { label {@fd_beaker FLUID Built-In} callback {Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()]; suite.storage(FD_STORE_INTERNAL); g_layout_list.update_dialogs();} xywh {0 0 31 20} type Radio deactivate } MenuItem {w_layout_menu_storage[1]} { label {@fd_user User Preference} callback {Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()]; suite.storage(FD_STORE_USER); g_layout_list.update_dialogs();} xywh {0 0 31 20} type Radio } MenuItem {w_layout_menu_storage[2]} { label {@fd_project Store in .fl Project File} callback {Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()]; suite.storage(FD_STORE_PROJECT); g_layout_list.update_dialogs();} xywh {0 0 31 20} type Radio } MenuItem {w_layout_menu_storage[3]} { label {@fd_file Store in External File} callback {Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()]; suite.storage(FD_STORE_FILE); g_layout_list.update_dialogs();} xywh {0 0 31 20} type Radio divider } MenuItem w_layout_menu_load { label {Load...} callback {// Give the user a file chooser and load that file Fl_Native_File_Chooser fnfc; fnfc.title("Load Layout Settings:"); fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE); fnfc.options(Fl_Native_File_Chooser::USE_FILTER_EXT); fnfc.filter("FLUID Layouts\\t*.fll\\n"); if (fnfc.show() != 0) return; const char *new_filename = fnfc.filename(); if (!new_filename) return; g_layout_list.load(new_filename); //g_layout_list.current_suite(n); g_layout_list.update_dialogs();} xywh {0 0 31 20} } MenuItem w_layout_menu_save { label {Save...} callback {// Give the user a file chooser with a suggested name Fl_Native_File_Chooser fnfc; fnfc.title("Save Layout Settings:"); fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | Fl_Native_File_Chooser::USE_FILTER_EXT); fnfc.filter("FLUID Layouts\\t*.fll\\n"); Fl_String filename = g_layout_list.filename_; fnfc.directory(fl_filename_path(filename).c_str()); fnfc.preset_file(fl_filename_name(filename).c_str()); if (fnfc.show() != 0) return; const char *new_filename = fnfc.filename(); if (!new_filename) return; g_layout_list.filename_ = new_filename; g_layout_list.save(new_filename);} xywh {0 0 31 20} divider code0 {\#include } } MenuItem w_layout_menu_delete { label Delete callback {// remove the current suite g_layout_list.remove(g_layout_list.current_suite()); g_layout_list.update_dialogs();} xywh {0 0 31 20} } } Fl_Box {} { label {Preset:} xywh {25 107 60 20} labelfont 1 labelsize 11 align 24 } Fl_Group {} { callback propagate_load open xywh {85 107 235 20} labelsize 11 } { Fl_Button {preset_choice[0]} { label Application user_data 0 user_data_type long callback edit_layout_preset_cb xywh {85 107 78 20} type Radio value 1 selection_color 45 labelsize 11 compact 1 } Fl_Button {preset_choice[1]} { label Dialog user_data 1 user_data_type long callback edit_layout_preset_cb xywh {163 107 79 20} type Radio selection_color 45 labelsize 11 compact 1 } Fl_Button {preset_choice[2]} { label Toolbox user_data 2 user_data_type long callback edit_layout_preset_cb xywh {242 107 78 20} type Radio selection_color 45 labelsize 11 compact 1 } } Fl_Box {} { label {---- Window ----} xywh {85 132 235 20} labelfont 1 labelsize 11 align 20 } Fl_Box {} { label {Margins:} xywh {25 167 60 20} labelsize 11 align 24 } Fl_Value_Input {} { label {Left:} callback {if (v == LOAD) { o->value((double)layout->left_window_margin); } else { layout->left_window_margin = (int)o->value(); }} xywh {85 167 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { label {Top:} callback {if (v == LOAD) { o->value((double)layout->top_window_margin); } else { layout->top_window_margin = (int)o->value(); }} xywh {145 167 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { label {Right:} callback {if (v == LOAD) { o->value((double)layout->right_window_margin); } else { layout->right_window_margin = (int)o->value(); }} xywh {205 167 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { label {Bottom:} callback {if (v == LOAD) { o->value((double)layout->bottom_window_margin); } else { layout->bottom_window_margin = (int)o->value(); }} xywh {265 167 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Box {} { label {Grid:} xywh {32 201 53 20} labelsize 11 align 24 } Fl_Value_Input {} { label {Horizontal:} callback {if (v == LOAD) { o->value((double)layout->window_grid_x); } else { layout->window_grid_x = (int)o->value(); }} xywh {85 201 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { label {Vertical:} callback {if (v == LOAD) { o->value((double)layout->window_grid_y); } else { layout->window_grid_y = (int)o->value(); }} xywh {145 201 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Box {} { label {---- Group ----} xywh {85 226 235 20} labelfont 1 labelsize 11 align 20 } Fl_Box {} { label {Margins:} xywh {25 261 60 20} labelsize 11 align 24 } Fl_Value_Input {} { label {Left:} callback {if (v == LOAD) { o->value((double)layout->left_group_margin); } else { layout->left_group_margin = (int)o->value(); }} xywh {85 261 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { label {Top:} callback {if (v == LOAD) { o->value((double)layout->top_group_margin); } else { layout->top_group_margin = (int)o->value(); }} xywh {145 261 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { label {Right:} callback {if (v == LOAD) { o->value((double)layout->right_group_margin); } else { layout->right_group_margin = (int)o->value(); }} xywh {205 261 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { label {Bottom:} callback {if (v == LOAD) { o->value((double)layout->bottom_group_margin); } else { layout->bottom_group_margin = (int)o->value(); }} xywh {265 261 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Box {} { label {Grid:} xywh {32 295 53 20} labelsize 11 align 24 } Fl_Value_Input {} { label {Horizontal:} callback {if (v == LOAD) { o->value((double)layout->group_grid_x); } else { layout->group_grid_x = (int)o->value(); }} xywh {85 295 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { label {Vertical:} callback {if (v == LOAD) { o->value((double)layout->group_grid_y); } else { layout->group_grid_y = (int)o->value(); }} xywh {145 295 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Box {} { label {---- Tabs ----} xywh {85 320 235 20} labelfont 1 labelsize 11 align 20 } Fl_Box {} { label {Margins:} xywh {25 355 60 20} labelsize 11 align 24 } Fl_Value_Input {} { label {Top:} callback {if (v == LOAD) { o->value((double)layout->top_tabs_margin); } else { layout->top_tabs_margin = (int)o->value(); }} xywh {85 355 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { label {Bottom:} callback {if (v == LOAD) { o->value((double)layout->bottom_tabs_margin); } else { layout->bottom_tabs_margin = (int)o->value(); }} xywh {145 355 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Box {} { label {---- Widget ----} xywh {85 380 235 20} labelfont 1 labelsize 11 align 20 } Fl_Box {} { label {Horizontal:} xywh {25 415 60 20} labelsize 11 align 24 } Fl_Value_Input {} { label {Minimum:} callback {if (v == LOAD) { o->value((double)layout->widget_min_w); } else { layout->widget_min_w = (int)o->value(); }} xywh {85 414 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { label {Increment:} callback {if (v == LOAD) { o->value((double)layout->widget_inc_w); } else { layout->widget_inc_w = (int)o->value(); }} xywh {145 414 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { label {Gap:} callback {if (v == LOAD) { o->value((double)layout->widget_gap_x); } else { layout->widget_gap_x = (int)o->value(); }} xywh {205 414 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Box {} { label {Vertical:} xywh {32 440 53 20} labelsize 11 align 24 } Fl_Value_Input {} { callback {if (v == LOAD) { o->value((double)layout->widget_min_h); } else { layout->widget_min_h = (int)o->value(); }} xywh {85 440 55 20} labelsize 11 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { callback {if (v == LOAD) { o->value((double)layout->widget_inc_h); } else { layout->widget_inc_h = (int)o->value(); }} xywh {145 440 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { callback {if (v == LOAD) { o->value((double)layout->widget_gap_y); } else { layout->widget_gap_y = (int)o->value(); }} xywh {205 440 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } Fl_Group {} { label {Label Font:} callback propagate_load open xywh {85 465 201 20} labelsize 11 align 4 } { Fl_Choice {} { callback {if (v == LOAD) { o->value(layout->labelfont+1); } else { layout->labelfont = (int)o->value()-1; }} open tooltip {The style of the label text.} xywh {85 465 150 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item fontmenu_w_default[];} code1 {o->menu(fontmenu_w_default);} } {} Fl_Value_Input {} { callback {if (v == LOAD) { o->value(layout->labelsize); } else { layout->labelsize = (int)o->value(); }} tooltip {The size of the label text.} xywh {235 465 50 20} labelsize 11 minimum 1 maximum 1000 step 1 value 14 textsize 11 } } Fl_Group {} { label {Text Font:} callback propagate_load open xywh {85 490 200 20} labelsize 11 align 4 } { Fl_Choice {} { callback {if (v == LOAD) { o->value(layout->textfont+1); } else { layout->textfont = (int)o->value()-1; }} open tooltip {The value text style.} xywh {85 490 150 20} box DOWN_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 code0 {extern Fl_Menu_Item fontmenu_w_default[];} code1 {o->menu(fontmenu_w_default);} } {} Fl_Value_Input {} { callback {if (v == LOAD) { o->value(layout->textsize); } else { layout->textsize = (int)o->value(); }} tooltip {The value text size.} xywh {235 490 50 20} labelsize 11 maximum 1000 step 1 value 14 textsize 11 } } Fl_Box {} { xywh {325 535 5 5} hide resizable } } Fl_Group w_settings_shell_tab { label Shell callback propagate_load open scale_image {36 24} image {icons/shell_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11 hide } { Fl_Group {} { callback propagate_load open xywh {10 90 320 132} } { Fl_Browser w_settings_shell_list { label {Shell command list:} callback {if (v == LOAD) { // load from g_shell_config if (g_shell_config) { o->clear(); w_settings_shell_list_selected = 0; for (int i=0; ilist_size; i++) { Fd_Shell_Command *cmd = g_shell_config->list[i]; o->add(cmd->name.c_str()); if (cmd->storage == FD_STORE_USER) o->icon(i+1, w_settings_shell_fd_user->image()); else if (cmd->storage == FD_STORE_PROJECT) o->icon(i+1, w_settings_shell_fd_project->image()); } } } else { // int prev_selected = w_settings_shell_list_selected; w_settings_shell_list_selected = 0; int selected = w_settings_shell_list->value(); if (selected) { if (w_settings_shell_list->selected(selected)) w_settings_shell_list_selected = selected; } w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); }} xywh {100 90 220 110} type Multi labelfont 1 labelsize 11 align 4 textsize 13 resizable } Fl_Group w_settings_shell_toolbox { callback {if (v==LOAD) { propagate_load(o, v); }} open xywh {100 200 220 22} } { Fl_Button {} { label {+} callback {if (v != LOAD) { int selected = w_settings_shell_list_selected; Fd_Shell_Command *cmd = new Fd_Shell_Command("new shell command"); g_shell_config->insert(selected, cmd); w_settings_shell_list->insert(selected+1, cmd->name.c_str()); w_settings_shell_list->deselect(); w_settings_shell_list->value(selected+1); if (cmd->storage == FD_STORE_USER) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); } else if (cmd->storage == FD_STORE_PROJECT) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); set_modflag(1); } w_settings_shell_list->do_callback(); w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); g_shell_config->rebuild_shell_menu(); }} tooltip {insert a new shell command into the list after the selected command} xywh {100 200 24 22} labelfont 1 labelsize 11 } Fl_Button w_settings_shell_dup { label {++} callback {int selected = w_settings_shell_list_selected; if (v==LOAD) { if (selected) { o->activate(); } else { o->deactivate(); } } else { if (!selected) return; Fd_Shell_Command *cmd = new Fd_Shell_Command(g_shell_config->list[selected-1]); g_shell_config->insert(selected, cmd); w_settings_shell_list->insert(selected+1, cmd->name.c_str()); w_settings_shell_list->deselect(); w_settings_shell_list->value(selected+1); if (cmd->storage == FD_STORE_USER) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); } else if (cmd->storage == FD_STORE_PROJECT) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); set_modflag(1); } w_settings_shell_list->do_callback(); w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); g_shell_config->rebuild_shell_menu(); }} tooltip {duplicate the selected shell command and insert it into the list} xywh {124 200 24 22} labelfont 1 labelsize 11 deactivate } Fl_Button w_settings_shell_remove { label DEL callback {int selected = w_settings_shell_list_selected; if (v==LOAD) { if (selected) { o->activate(); } else { o->deactivate(); } } else { if (!selected) return; int ret = fl_choice("Delete the shell command\\n\\"%s\\"?\\n\\nThis can not be undone.", "Delete", "Cancel", NULL, g_shell_config->list[selected-1]->name.c_str()); if (ret==1) return; if (g_shell_config->at(selected-1)->storage == FD_STORE_PROJECT) set_modflag(1); g_shell_config->remove(selected-1); w_settings_shell_list->remove(selected); if (selected <= w_settings_shell_list->size()) w_settings_shell_list->value(selected); else w_settings_shell_list->value(0); w_settings_shell_list->do_callback(); w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); g_shell_config->rebuild_shell_menu(); }} tooltip {remove the selected shell command - this can not be undone} xywh {148 200 24 22} labelsize 10 deactivate } Fl_Menu_Button w_settings_shell_menu {open xywh {172 200 24 22} labelsize 11 textsize 11 } { MenuItem {} { label {Import...} callback {if (v != LOAD) Fd_Shell_Command_List::import_from_file();} tooltip {import shell commands from an external file} xywh {90 90 100 20} labelsize 11 } MenuItem {} { label {Export selected...} callback {if (v != LOAD) Fd_Shell_Command_List::export_selected();} tooltip {export selected shell commands to an external file} xywh {10 10 100 20} labelsize 11 } MenuItem {} { label {Example Scripts:} xywh {20 20 100 20} labelfont 1 labelsize 10 hide deactivate } MenuItem {} { label {Compile with fltk-config} xywh {30 30 100 20} labelsize 11 hide } MenuItem {} { label {Build and run} xywh {40 40 100 20} labelsize 11 hide } MenuItem {} { label {Build with Xcode on macOS} xywh {50 50 100 20} labelsize 11 hide } MenuItem {} { label {Build with CMake} xywh {60 60 100 20} labelsize 11 hide } } Fl_Box {} { xywh {253 200 13 22} hide resizable } Fl_Button {} { label T callback {if (v!=LOAD) show_terminal_window();} tooltip {show terminal window} xywh {246 200 24 22} labelfont 5 labelsize 11 } Fl_Button w_settings_shell_play { label Run callback {int selected = w_settings_shell_list_selected; if (v==LOAD) { if (selected) { o->activate(); } else { o->deactivate(); } } else { if (!selected) return; Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->run(); }} tooltip {run the selected shell command} xywh {270 200 50 22} labelsize 11 deactivate } } } Fl_Group w_settings_shell_cmd { callback {if (v==LOAD) { int selected = w_settings_shell_list_selected; if (selected) { o->activate(); } else { o->deactivate(); } propagate_load(o, v); }} open xywh {10 235 320 291} resizable } { Fl_Input {} { label {Name:} callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->name.c_str()); } else { o->value(""); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->name = o->value(); w_settings_shell_list->text(selected, o->value()); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} tooltip {file the shell command under this name in the shell command list} xywh {100 246 220 20} labelfont 1 labelsize 11 when 13 textfont 4 textsize 11 } Fl_Input {} { label {Menu Label:} callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->label.c_str()); } else { o->value(""); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->label = o->value(); cmd->update_shell_menu(); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} tooltip {label text for the Shell menu in the main menu bar} xywh {100 272 220 20} labelfont 1 labelsize 11 textfont 4 textsize 11 } Fl_Group {} { callback {propagate_load(o, v);} open xywh {100 297 140 71} } { Fl_Button {} { label Shortcut callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->shortcut); //o->default_value(o->value()); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->shortcut = o->value(); cmd->update_shell_menu(); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} tooltip {an optional keyboard shortcut to run this shell command} xywh {100 297 130 20} labelsize 11 align 16 code0 {\#include } class Fl_Shortcut_Button } Fl_Choice {} { label {Store:} callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { Fd_Tool_Store ts = g_shell_config->list[selected-1]->storage; o->value(o->find_item_with_argument((long)ts)); } else { o->value(o->find_item_with_argument((long)FD_STORE_USER)); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; Fd_Tool_Store ts = (Fd_Tool_Store)(o->mvalue()->argument()); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); cmd->storage = ts; //w_settings_shell_list->text(selected, cmd->name.c_str()); if (cmd->storage == FD_STORE_USER) w_settings_shell_list->icon(selected, w_settings_shell_fd_user->image()); else if (cmd->storage == FD_STORE_PROJECT) w_settings_shell_list->icon(selected, w_settings_shell_fd_project->image()); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} open tooltip {store this shell command as a user setting or save it with the .fl project file} xywh {100 322 130 20} down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 } { MenuItem {} { label {@fd_user User Setting} user_data FD_STORE_USER user_data_type long xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {@fd_project Project File} user_data FD_STORE_PROJECT user_data_type long xywh {0 0 100 20} labelsize 11 } } Fl_Choice {} { label {Condition:} callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { int cond = g_shell_config->list[selected-1]->condition; o->value(o->find_item_with_argument(cond)); } else { o->value(o->find_item_with_argument(0)); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int cond = (int)(o->mvalue()->argument()); cmd->condition = cond; g_shell_config->rebuild_shell_menu(); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} open tooltip {add this command to the main menu bar only if this condition is true} xywh {100 348 130 20} down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 } { MenuItem {} { label {all platforms} user_data {Fd_Shell_Command::ALWAYS} user_data_type long xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {Windows only} user_data {Fd_Shell_Command::WIN_ONLY} user_data_type long xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {Linux only} user_data {Fd_Shell_Command::UX_ONLY} user_data_type long xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {macOS only} user_data {Fd_Shell_Command::MAC_ONLY} user_data_type long xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {Linux and macOS} user_data {Fd_Shell_Command::MAC_AND_UX_ONLY} user_data_type long xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {don't use} user_data {Fd_Shell_Command::NEVER} user_data_type long xywh {0 0 100 20} labelsize 11 } } Fl_Box {} { xywh {230 297 10 71} hide resizable } } Fl_Input {} { label {Label:} callback {if (v == LOAD) { // o->value(g_shell_command.c_str()); } else { // g_shell_command = o->value(); }} xywh {230 348 90 20} labelfont 1 labelsize 11 textfont 4 textsize 11 hide } Fl_Group {} { callback propagate_load open xywh {100 373 220 80} resizable } { Fl_Text_Editor w_settings_shell_command { label {Shell script:} callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->buffer()->text(g_shell_config->list[selected-1]->command.c_str()); } else { o->buffer()->text(""); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->command = o->buffer()->text(); if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} xywh {100 373 196 80} labelfont 1 labelsize 11 align 4 textfont 4 textsize 12 resizable code0 {o->buffer(new Fl_Text_Buffer);} } Fl_Group {} {open xywh {296 373 24 80} } { Fl_Menu_Button w_settings_shell_text_macros { callback {const Fl_Menu_Item *mi = o->mvalue(); if (mi) { char buffer[256]; fl_strlcpy(buffer, mi->label(), 255); int n = (int)strlen(buffer)-1; if (buffer[n]=='@') buffer[n] = 0; char *word = buffer; if (word[0]=='@') word++; if (w_settings_shell_command->buffer()->selected()) { int start = 0, end = 0; w_settings_shell_command->buffer()->selection_position(&start, &end); w_settings_shell_command->buffer()->replace(start, end, word); } else { int pos = w_settings_shell_command->insert_position(); w_settings_shell_command->buffer()->insert(pos, word); } w_settings_shell_command->do_callback(w_settings_shell_command, (void*)NULL); }} open tooltip {a list of text replacements available for the shell script} xywh {296 373 24 22} labelsize 11 textsize 11 } { MenuItem {} { label {@@BASENAME@@} xywh {80 80 100 20} labelfont 4 labelsize 11 } MenuItem {} { label {@@PROJECTFILE_PATH@@} xywh {0 0 100 20} labelfont 4 labelsize 11 } MenuItem {} { label {@@PROJECTFILE_NAME@@} xywh {10 10 100 20} labelfont 4 labelsize 11 } MenuItem {} { label {@@CODEFILE_PATH@@} xywh {20 20 100 20} labelfont 4 labelsize 11 } MenuItem {} { label {@@CODEFILE_NAME@@} xywh {30 30 100 20} labelfont 4 labelsize 11 } MenuItem {} { label {@@HEADERFILE_PATH@@} xywh {40 40 100 20} labelfont 4 labelsize 11 } MenuItem {} { label {@@HEADERFILE_NAME@@} xywh {50 50 100 20} labelfont 4 labelsize 11 } MenuItem {} { label {@@TEXTFILE_PATH@@} xywh {60 60 100 20} labelfont 4 labelsize 11 } MenuItem {} { label {@@TEXTFILE_NAME@@} xywh {70 70 100 20} labelfont 4 labelsize 11 } MenuItem {} { label {@@FLTK_CONFIG@@} comment {Not yet implemented} xywh {70 70 100 20} labelfont 4 labelsize 11 hide } MenuItem {} { label {@@TMPDIR@@} xywh {70 70 100 20} labelfont 4 labelsize 11 } } Fl_Button {} { label {@+1fd_zoom} callback {if (!script_panel) make_script_panel(); script_input->buffer()->text(w_settings_shell_command->buffer()->text()); script_panel->show(); for (;;) { Fl_Widget* w = Fl::readqueue(); if (w == script_panel_cancel) goto BREAK2; else if (w == script_panel_ok) break; else if (!w) Fl::wait(); } w_settings_shell_command->buffer()->text(script_input->buffer()->text()); w_settings_shell_command->do_callback(); BREAK2: script_panel->hide();} tooltip {open the big code editor} xywh {296 395 24 22} labelsize 11 } Fl_Box {} { xywh {296 417 24 10} hide resizable } } } Fl_Check_Button {} { label {save .fl project file} callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_PROJECT); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (v) { cmd->flags |= Fd_Shell_Command::SAVE_PROJECT; } else { cmd->flags &= ~Fd_Shell_Command::SAVE_PROJECT; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} tooltip {save the project to the .fl file before running the command} xywh {100 458 110 20} down_box DOWN_BOX labelsize 11 } Fl_Check_Button {} { label {save source code} callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_SOURCECODE); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (v) { cmd->flags |= Fd_Shell_Command::SAVE_SOURCECODE; } else { cmd->flags &= ~Fd_Shell_Command::SAVE_SOURCECODE; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} tooltip {generate the source code and header file before running the command} xywh {100 478 110 19} down_box DOWN_BOX labelsize 11 } Fl_Check_Button {} { label {save i18n strings} callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::SAVE_STRINGS); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (v) { cmd->flags |= Fd_Shell_Command::SAVE_STRINGS; } else { cmd->flags &= ~Fd_Shell_Command::SAVE_STRINGS; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} tooltip {save the internationalisation strings before running the command} xywh {100 498 110 20} down_box DOWN_BOX labelsize 11 } Fl_Check_Button {} { label {show terminal} callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(!(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::DONT_SHOW_TERMINAL)); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (!v) { cmd->flags |= Fd_Shell_Command::DONT_SHOW_TERMINAL; } else { cmd->flags &= ~Fd_Shell_Command::DONT_SHOW_TERMINAL; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} tooltip {show the terminal window when launching this script} xywh {214 458 106 20} down_box DOWN_BOX labelsize 11 } Fl_Check_Button {} { label {clear terminal} callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::CLEAR_TERMINAL); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (v) { cmd->flags |= Fd_Shell_Command::CLEAR_TERMINAL; } else { cmd->flags &= ~Fd_Shell_Command::CLEAR_TERMINAL; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} tooltip {clear the teminal window before running this script} xywh {214 478 106 19} down_box DOWN_BOX labelsize 11 } Fl_Check_Button {} { label {clear term history} callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { o->value(g_shell_config->list[selected-1]->flags & Fd_Shell_Command::CLEAR_HISTORY); } else { o->value(0); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; int v = o->value(); if (v) { cmd->flags |= Fd_Shell_Command::CLEAR_HISTORY; } else { cmd->flags &= ~Fd_Shell_Command::CLEAR_HISTORY; } if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); } }} tooltip {clear the teminal history in the terminal window} xywh {214 498 106 19} down_box DOWN_BOX labelsize 11 } } Fl_Box w_settings_shell_fd_project { image {pixmaps/fd_project.png} compress_image 1 bind_image 1 bind_deimage 1 xywh {20 70 16 15} labelsize 11 hide deactivate code0 {o->image()->scale(16, 16);} } Fl_Box w_settings_shell_fd_user { image {pixmaps/fd_user.png} compress_image 1 bind_image 1 bind_deimage 1 xywh {20 70 16 15} labelsize 11 hide deactivate code0 {o->image()->scale(16, 16);} } } Fl_Group w_settings_i18n_tab { label Locale callback {propagate_load(o, v);} open scale_image {36 24} image {icons/language_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11 hide } { Fl_Group {} { callback propagate_load open xywh {100 78 170 20} } { Fl_Choice i18n_type_chooser { label {i18n Library:} callback i18n_type_cb open tooltip {Type of internationalization to use.} xywh {100 78 160 20} box THIN_UP_BOX down_box BORDER_BOX labelsize 11 textsize 11 } { MenuItem {} { label None xywh {0 -11 100 20} labelsize 11 } MenuItem {} { label {GNU gettext} xywh {0 -11 100 20} labelsize 11 } MenuItem {} { label {POSIX catgets} xywh {0 -11 100 20} labelsize 11 } } Fl_Box {} { xywh {260 78 10 20} hide resizable } } Fl_Group i18n_gnu_group { callback {propagate_load(o, v);} open xywh {100 103 220 95} } { Fl_Input i18n_gnu_include_input { label {\#include:} callback {if (v == LOAD) { o->value(g_project.i18n_gnu_include.c_str()); } else { undo_checkpoint(); g_project.i18n_gnu_include = o->value(); set_modflag(1); }} tooltip {The include file for internationalization.} xywh {100 103 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Input i18n_gnu_conditional_input { label {Conditional:} callback {if (v == LOAD) { o->value(g_project.i18n_gnu_conditional.c_str()); } else { undo_checkpoint(); g_project.i18n_gnu_conditional = o->value(); set_modflag(1); }} tooltip {only include the header file if this preprocessor macro is defined, for example FLTK_GETTEXT_FOUND} xywh {100 128 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Input i18n_gnu_function_input { label {Function:} callback {if (v == LOAD) { o->value(g_project.i18n_gnu_function.c_str()); } else { undo_checkpoint(); g_project.i18n_gnu_function = o->value(); set_modflag(1); }} tooltip {The function to call to translate labels and tooltips, usually "gettext" or "_"} xywh {100 153 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Input i18n_gnu_static_function_input { label {Static Function:} callback {if (v == LOAD) { o->value(g_project.i18n_gnu_static_function.c_str()); } else { undo_checkpoint(); g_project.i18n_gnu_static_function = o->value(); set_modflag(1); }} tooltip {function to call to translate static text, The function to call to internationalize labels and tooltips, usually "gettext_noop" or "N_"} xywh {100 178 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } } Fl_Group i18n_posix_group { callback {propagate_load(o, v);} open xywh {100 103 220 95} hide } { Fl_Input i18n_pos_include_input { label {\#include:} callback {if (v == LOAD) { o->value(g_project.i18n_pos_include.c_str()); } else { undo_checkpoint(); g_project.i18n_pos_include = o->value(); set_modflag(1); }} tooltip {The include file for internationalization.} xywh {100 103 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Input i18n_pos_conditional_input { label {Conditional:} callback {if (v == LOAD) { o->value(g_project.i18n_pos_conditional.c_str()); } else { undo_checkpoint(); g_project.i18n_pos_conditional = o->value(); set_modflag(1); }} tooltip {only include the header file if this preprocessor macro is defined, for example FLTK_GETTEXT_FOUND} xywh {100 128 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Input i18n_pos_file_input { label {Catalog:} callback {if (v == LOAD) { o->value(g_project.i18n_pos_file.c_str()); } else { undo_checkpoint(); g_project.i18n_pos_file = o->value(); set_modflag(1); }} tooltip {The name of the message catalog.} xywh {100 153 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Group {} { callback {propagate_load(o, v);} open xywh {100 178 90 20} } { Fl_Input i18n_pos_set_input { label {Set:} callback {if (v == LOAD) { o->value(g_project.i18n_pos_set.c_str()); } else { undo_checkpoint(); g_project.i18n_pos_set = o->value(); set_modflag(1); }} tooltip {The message set number.} xywh {100 178 80 20} type Int box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Box {} { xywh {180 178 10 20} hide resizable } } } Fl_Box {} { xywh {100 530 220 10} hide resizable } } Fl_Group w_settings_user_tab { label User callback {propagate_load(o, v);} open scale_image {36 24} image {icons/user_circle_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11 hide code0 {\#include } } { Fl_Box {} { label {---- Widget Browser ----} xywh {100 84 220 20} labelfont 1 labelsize 11 align 20 } Fl_Group {} { callback propagate_load open xywh {100 112 220 20} } { Fl_Choice {} { label {Label:} user_data {&Widget_Browser::label_font} callback cb_Comments open xywh {100 112 151 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item fontmenu[];} code1 {o->menu(fontmenu);} } {} Fl_Button {} { user_data {&Widget_Browser::label_color} callback cb_Color_Chip xywh {251 112 51 20} labelsize 11 } Fl_Menu_Button {} { user_data {&Widget_Browser::label_color} callback cb_Color_Choice open xywh {302 112 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} } {} } Fl_Group {} { callback propagate_load open xywh {100 137 220 20} } { Fl_Choice {} { label {Class:} user_data {&Widget_Browser::class_font} callback cb_Comments open xywh {100 137 151 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item fontmenu[];} code1 {o->menu(fontmenu);} } {} Fl_Button {} { user_data {&Widget_Browser::class_color} callback cb_Color_Chip xywh {251 137 51 20} labelsize 11 } Fl_Menu_Button {} { user_data {&Widget_Browser::class_color} callback cb_Color_Choice open xywh {302 137 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} } {} } Fl_Group {} { callback propagate_load open xywh {100 162 220 20} } { Fl_Choice {} { label {Function:} user_data {&Widget_Browser::func_font} callback cb_Comments open xywh {100 162 151 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item fontmenu[];} code1 {o->menu(fontmenu);} } {} Fl_Button {} { user_data {&Widget_Browser::func_color} callback cb_Color_Chip xywh {251 162 51 20} labelsize 11 } Fl_Menu_Button {} { user_data {&Widget_Browser::func_color} callback cb_Color_Choice open xywh {302 162 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} } {} } Fl_Group {} { callback propagate_load open xywh {100 187 220 20} } { Fl_Choice {} { label {Name:} user_data {&Widget_Browser::name_font} callback cb_Comments open xywh {100 187 151 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item fontmenu[];} code1 {o->menu(fontmenu);} } {} Fl_Button {} { user_data {&Widget_Browser::name_color} callback cb_Color_Chip xywh {251 187 51 20} labelsize 11 } Fl_Menu_Button {} { user_data {&Widget_Browser::name_color} callback cb_Color_Choice open xywh {302 187 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} } {} } Fl_Group {} { callback propagate_load open xywh {100 212 220 20} } { Fl_Choice {} { label {Code:} user_data {&Widget_Browser::code_font} callback cb_Comments open xywh {100 212 151 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item fontmenu[];} code1 {o->menu(fontmenu);} } {} Fl_Button {} { user_data {&Widget_Browser::code_color} callback cb_Color_Chip xywh {251 212 51 20} labelsize 11 } Fl_Menu_Button {} { user_data {&Widget_Browser::code_color} callback cb_Color_Choice open xywh {302 212 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} } {} } Fl_Group {} { callback propagate_load open xywh {100 237 220 20} } { Fl_Choice w_settings_user_commenttext { label {Comments:} user_data {&Widget_Browser::comment_font} callback cb_Comments open xywh {100 237 151 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item fontmenu[];} code1 {o->menu(fontmenu);} } {} Fl_Button {} { user_data {&Widget_Browser::comment_color} callback cb_Color_Chip xywh {251 237 51 20} labelsize 11 } Fl_Menu_Button {} { user_data {&Widget_Browser::comment_color} callback cb_Color_Choice open xywh {302 237 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} } {} } } } Fl_Group {} {open xywh {10 550 320 20} } { Fl_Button {} { label Close callback {if (g_shell_config) g_shell_config->write(fluid_prefs, FD_STORE_USER); g_layout_list.write(fluid_prefs, FD_STORE_USER); settings_window->hide();} tooltip {Close this dialog.} xywh {230 550 100 20} labelsize 11 } Fl_Box {} { xywh {220 550 10 20} hide resizable } } } code {w_settings_tabs->do_callback(w_settings_tabs, LOAD);} {} } Function {make_shell_window()} {open } { Fl_Window shell_run_window { label {Shell Command Output} open xywh {769 584 555 430} type Double align 80 resizable visible } { Fl_Terminal shell_run_terminal { xywh {10 10 535 375} resizable code0 {shell_run_terminal->ansi(1);} code1 {shell_run_terminal->history_lines(1000);} } Fl_Group {} {open xywh {10 395 535 25} } { Fl_Button {} { label Clear callback {// clear screen, clear scrollback, home cursor shell_run_terminal->append("\\033[2J\\033[3J\\033[H");} xywh {10 395 94 25} } Fl_Box {} { xywh {104 395 341 25} hide resizable } Fl_Return_Button shell_run_button { label Close callback {Fl_Preferences pos(fluid_prefs, "shell_run_Window_pos"); pos.set("x", shell_run_window->x()); pos.set("y", shell_run_window->y()); pos.set("w", shell_run_window->w()); pos.set("h", shell_run_window->h()); shell_run_window->hide();} xywh {445 395 100 25} } } } } decl {Fl_Menu_Item *w_layout_menu_storage[4];} {private global } fltk-1.4.3/fluid/factory.h0000644000175000017500000000173315004135251015534 0ustar albrechtalbrecht// // Widget type header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_FACTORY_H #define _FLUID_FACTORY_H #include "Fl_Type.h" struct Fl_Menu_Item; extern Fl_Menu_Item New_Menu[]; void fill_in_New_Menu(); Fl_Type *typename_to_prototype(const char *inName); Fl_Type *add_new_widget_from_file(const char *inName, Strategy strategy); Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy, bool and_open=true); Fl_Type *add_new_widget_from_user(const char *inName, Strategy strategy, bool and_open=true); #endif // _FLUID_FACTORY_H fltk-1.4.3/fluid/shell_command.cxx0000644000175000017500000007560415004135251017255 0ustar albrechtalbrecht// // FLUID main entry for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // in progress: // FLUID comes with example shell commands to build the current project file // and run the project. This is accomplished by calling `fltk-config` on the // files generated by FLUID, and by calling the executable directly. // // If the user wants more complex commands, he can add or modify them in the // "Shell" settings panel. Modified shell commands are saved with the .fl // file. // The Shell panel has a list of shell commands in the upper half. Under the // list are buttons to add, duplicate, and delete shell commands. A popup // menu offers import and export functionality and a list of sample scripts. // We may want to add up and down buttons, so the user can change the // order of commands. // Selecting any shell command in the list fills in and activates a list of // options in the lower half of the panel. Those settings are: // - Name: the name of the shell command in the list // - Label: the label in the pulldown menu (could be the same as name?) // - Shortcut: shortcut key to launch the command // - Storage: where to store this shell command // - Condition: pulldown menu to make the entry conditional for various // target platforms, for example, a "Windows only" entry would only be added // to the Shell menu on a Windows machine. Other options could be: // - Linux only, macOS only, never (to make a list header!?), inactive? // - Command: a multiline input for the actual shell command // - Variables: a pulldown menu that insert variable names like $ // - options to save project, code, and strings before running // - test-run button // TODO: add @APPDIR@? // TODO: get a macro to find `fltk-config` @FLTK_CONFIG@ // TODO: add an input field so the user can insert their preferred file and path for fltk-config (user setting) // `fltk-config` is actually tricky to find // for live builds, we could check the program launch directory // if we know where build/Xcode/bin/Debug/fluid is, we // may or may not find ./build/Xcode/fltk-config // on macOS with homebrew, we find /opt/homebrew/bin/fltk-config but the user // can set their own install path. // We can query the shell path, but that requires knowing the users shell (echo $SHELL). // We can run the shell as a login shell with `-l`, so the user $PTH is set: /bin/bash -l -c 'fltk-config' // The shell should output the path of the fltk-config that it found and why it is using that one. // This can also output the fltk-config version. // TODO: add a bunch of sensible sample shell commands // TODO: when this new feature is used for the very first time, import two or three samples as initial user setting // TODO: make the settings dialog resizable // TODO: make g_shell_config static, not a pointer, but don't load anything in batch mode // FEATURE: Fd_Tool_Store icons are currently redundant with @file and @save and could be improved // FEATURE: hostname, username, getenv support? // FEATURE: add the files ./fluid.prefs and ./fluid.user.prefs as tool locations // FEATURE: interpret compiler output, for example: clang, and highlight errors and warnings // `.../shell_command.cxx:71:2: error: test` // `71 | #error test` // `clang++: error: no such file or directory: '.../shell_command.o'` // would make the error message clickable in the shell window and could select the widget, // open the matching editor in the widget panel, and highlight the line in SourceView. /* Some ideas: default shell is in $SHELL on linux and macOS On macOS, we can write Apple Scripts: #!/usr/bin/env osascript say "@BASENAME@" osascript < #include #include #include #include static Fl_String fltk_config_cmd; static Fl_Process s_proc; /** See if shell command is running (public) */ bool shell_command_running() { return s_proc.desc() ? true : false; } /** Reads an entry from the group. A default value must be supplied. The return value indicates if the value was available (non-zero) or the default was used (0). \param[in] prefs preference group \param[in] key name of entry \param[out] value returned from preferences or default value if none was set \param[in] defaultValue default value to be used if no preference was set \return 0 if the default value was used */ char preferences_get(Fl_Preferences &prefs, const char *key, Fl_String &value, const Fl_String &defaultValue) { char *v = NULL; char ret = prefs.get(key, v, defaultValue.c_str()); value = v; ::free(v); return ret; } /** Sets an entry (name/value pair). The return value indicates if there was a problem storing the data in memory. However it does not reflect if the value was actually stored in the preference file. \param[in] prefs preference group \param[in] entry name of entry \param[in] value set this entry to value (stops at the first nul character). \return 0 if setting the value failed */ char preferences_set(Fl_Preferences &prefs, const char *key, const Fl_String &value) { return prefs.set(key, value.c_str()); } /** \class Fl_Process Launch an external shell command. */ /** Create a process manager */ Fl_Process::Fl_Process() { _fpt= NULL; } /** Destroy the project manager. */ Fl_Process::~Fl_Process() { // TODO: check what we need to do if a task is still running if (_fpt) close(); } /** Open a process. \param[in] cmd the shell command that we want to run \param[in] mode "r" or "w" for creating a stream that can read or write \return a stream that is redirected from the shell command stdout */ FILE * Fl_Process::popen(const char *cmd, const char *mode) { #if defined(_WIN32) && !defined(__CYGWIN__) // PRECONDITIONS if (!mode || !*mode || (*mode!='r' && *mode!='w') ) return NULL; if (_fpt) close(); // close first before reuse ptmode = *mode; pin[0] = pin[1] = pout[0] = pout[1] = perr[0] = perr[1] = INVALID_HANDLE_VALUE; // stderr to stdout wanted ? int fusion = (strstr(cmd,"2>&1") !=NULL); // Create windows pipes if (!createPipe(pin) || !createPipe(pout) || (!fusion && !createPipe(perr) ) ) return freeHandles(); // error // Initialize Startup Info ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = pin[0]; si.hStdOutput = pout[1]; si.hStdError = fusion ? pout[1] : perr [1]; if ( CreateProcess(NULL, (LPTSTR) cmd,NULL,NULL,TRUE, DETACHED_PROCESS,NULL,NULL, &si, &pi)) { // don't need theses handles inherited by child process: clean_close(pin[0]); clean_close(pout[1]); clean_close(perr[1]); HANDLE & h = *mode == 'r' ? pout[0] : pin[1]; _fpt = _fdopen(_open_osfhandle((fl_intptr_t) h,_O_BINARY),mode); h= INVALID_HANDLE_VALUE; // reset the handle pointer that is shared // with _fpt so we don't free it twice } if (!_fpt) freeHandles(); return _fpt; #else _fpt=::popen(cmd,mode); return _fpt; #endif } /** Close the current process. */ int Fl_Process::close() { #if defined(_WIN32) && !defined(__CYGWIN__) if (_fpt) { fclose(_fpt); clean_close(perr[0]); clean_close(pin[1]); clean_close(pout[0]); _fpt = NULL; return 0; } return -1; #else int ret = ::pclose(_fpt); _fpt=NULL; return ret; #endif } /** non-null if file is open. \return the current file descriptor of the process' stdout */ FILE *Fl_Process::desc() const { return _fpt; } /** Receive a single line from the current process. \param[out] line buffer to receive the line \param[in] s size of the provided buffer \return NULL if an error occurred, otherwise a pointer to the string */ char *Fl_Process::get_line(char * line, size_t s) const { return _fpt ? fgets(line, (int)s, _fpt) : NULL; } // returns fileno(FILE*): // (file must be open, i.e. _fpt must be non-null) // *FIXME* we should find a better solution for the 'fileno' issue // non null if file is open int Fl_Process::get_fileno() const { #ifdef _MSC_VER return _fileno(_fpt); // suppress MSVC warning #else return fileno(_fpt); #endif } #if defined(_WIN32) && !defined(__CYGWIN__) bool Fl_Process::createPipe(HANDLE * h, BOOL bInheritHnd) { SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = bInheritHnd; return CreatePipe (&h[0],&h[1],&sa,0) ? true : false; } FILE *Fl_Process::freeHandles() { clean_close(pin[0]); clean_close(pin[1]); clean_close(pout[0]); clean_close(pout[1]); clean_close(perr[0]); clean_close(perr[1]); return NULL; // convenient for error management } void Fl_Process::clean_close(HANDLE& h) { if (h!= INVALID_HANDLE_VALUE) CloseHandle(h); h = INVALID_HANDLE_VALUE; } #endif /** Prepare FLUID for running a shell command according to the command flags. \param[in] flags set various flags to save the project, code, and string before running the command \return false if the previous command is still running */ static bool prepare_shell_command(int flags) { // settings_window->hide(); if (s_proc.desc()) { fl_alert("Previous shell command still running!"); return false; } if (flags & Fd_Shell_Command::SAVE_PROJECT) { save_cb(0, 0); } if (flags & Fd_Shell_Command::SAVE_SOURCECODE) { write_code_files(true); } if (flags & Fd_Shell_Command::SAVE_STRINGS) { write_strings_cb(0, 0); } return true; } /** Called by the file handler when the command is finished. */ void shell_proc_done() { shell_run_terminal->append("... END SHELL COMMAND ...\n"); shell_run_button->activate(); shell_run_window->label("FLUID Shell"); fl_beep(); } void shell_timer_cb(void*) { if (!s_proc.desc()) { shell_proc_done(); } else { Fl::add_timeout(0.25, shell_timer_cb); } } // Support the full piped shell command... void shell_pipe_cb(FL_SOCKET, void*) { char line[1024]=""; // Line from command output... if (s_proc.get_line(line, sizeof(line)) != NULL) { // Add the line to the output list... shell_run_terminal->append(line); } else { // End of file; tell the parent... Fl::remove_timeout(shell_timer_cb); Fl::remove_fd(s_proc.get_fileno()); s_proc.close(); shell_proc_done(); } } /** Find the script `fltk-config` that most closely relates to this version of FLUID. This is not implemented yet. */ //static void find_fltk_config() { // //} static void expand_macro(Fl_String &cmd, const Fl_String ¯o, const Fl_String &content) { for (int i=0;;) { i = cmd.find(macro, i); if (i==Fl_String::npos) break; cmd.replace(i, macro.size(), content); } } static void expand_macros(Fl_String &cmd) { expand_macro(cmd, "@BASENAME@", g_project.basename()); expand_macro(cmd, "@PROJECTFILE_PATH@", g_project.projectfile_path()); expand_macro(cmd, "@PROJECTFILE_NAME@", g_project.projectfile_name()); expand_macro(cmd, "@CODEFILE_PATH@", g_project.codefile_path()); expand_macro(cmd, "@CODEFILE_NAME@", g_project.codefile_name()); expand_macro(cmd, "@HEADERFILE_PATH@", g_project.headerfile_path()); expand_macro(cmd, "@HEADERFILE_NAME@", g_project.headerfile_name()); expand_macro(cmd, "@TEXTFILE_PATH@", g_project.stringsfile_path()); expand_macro(cmd, "@TEXTFILE_NAME@", g_project.stringsfile_name()); // TODO: implement finding the script `fltk-config` for all platforms // if (cmd.find("@FLTK_CONFIG@") != Fl_String::npos) { // find_fltk_config(); // expand_macro(cmd, "@FLTK_CONFIG@", fltk_config_cmd.c_str()); // } if (cmd.find("@TMPDIR@") != Fl_String::npos) expand_macro(cmd, "@TMPDIR@", get_tmpdir()); } /** Show the terminal window where it was last positioned. */ void show_terminal_window() { Fl_Preferences pos(fluid_prefs, "shell_run_Window_pos"); int x, y, w, h; pos.get("x", x, -1); pos.get("y", y, 0); pos.get("w", w, 640); pos.get("h", h, 480); if (x!=-1) { shell_run_window->resize(x, y, w, h); } shell_run_window->show(); } /** Prepare for and run a shell command. \param[in] cmd the command that is sent to `/bin/sh -c ...` or `cmd.exe` on Windows machines \param[in] flags various flags in preparation of the command */ void run_shell_command(const Fl_String &cmd, int flags) { if (cmd.empty()) { fl_alert("No shell command entered!"); return; } if (!prepare_shell_command(flags)) return; Fl_String expanded_cmd = cmd; expand_macros(expanded_cmd); if ( ((flags & Fd_Shell_Command::DONT_SHOW_TERMINAL) == 0) && (!shell_run_window->visible())) { show_terminal_window(); } // Show the output window and clear things... if (flags & Fd_Shell_Command::CLEAR_TERMINAL) shell_run_terminal->printf("\033[2J\033[H"); if (flags & Fd_Shell_Command::CLEAR_HISTORY) shell_run_terminal->printf("\033[3J"); shell_run_terminal->scrollbar->value(0); shell_run_terminal->printf("\033[0;32m%s\033[0m\n", expanded_cmd.c_str()); shell_run_window->label(expanded_cmd.c_str()); if (s_proc.popen((char *)expanded_cmd.c_str()) == NULL) { shell_run_terminal->printf("\033[1;31mUnable to run shell command: %s\033[0m\n", strerror(errno)); shell_run_window->label("FLUID Shell"); return; } shell_run_button->deactivate(); // if the function below does not for some reason, we will check periodically // to see if the command is done Fl::add_timeout(0.25, shell_timer_cb); // this will tell us when the shell command is done Fl::add_fd(s_proc.get_fileno(), shell_pipe_cb); } /** Create an empty shell command structure. */ Fd_Shell_Command::Fd_Shell_Command() : shortcut(0), storage(FD_STORE_USER), condition(0), flags(0), shell_menu_item_(NULL) { } /** Copy the aspects of a shell command dataset into a new shell command. \param[in] rhs copy from this prototype */ Fd_Shell_Command::Fd_Shell_Command(const Fd_Shell_Command *rhs) : name(rhs->name), label(rhs->label), shortcut(rhs->shortcut), storage(rhs->storage), condition(rhs->condition), condition_data(rhs->condition_data), command(rhs->command), flags(rhs->flags), shell_menu_item_(NULL) { } /** Create a default storage for a shell command and how it is accessible in FLUID. \param[in] name is used as a stand-in for the command name and label */ Fd_Shell_Command::Fd_Shell_Command(const Fl_String &in_name) : name(in_name), label(in_name), shortcut(0), storage(FD_STORE_USER), condition(Fd_Shell_Command::ALWAYS), command("echo \"Hello, FLUID!\""), flags(Fd_Shell_Command::SAVE_PROJECT|Fd_Shell_Command::SAVE_SOURCECODE), shell_menu_item_(NULL) { } /** Create a storage for a shell command and how it is accessible in FLUID. \param[in] in_name name of this command in the command list in the settings panel \param[in] in_label label text in the main pulldown menu \param[in] in_shortcut a keyboard shortcut that will also appear in the main menu \param[in] in_storage storage location for this command \param[in] in_condition commands can be hidden for certain platforms by setting a condition \param[in] in_condition_data more details for future conditions, i.e. per user, per host, etc. \param[in] in_command the shell command that we want to run \param[in] in_flags some flags to tell FLUID to save the project, code, or strings before running the command */ Fd_Shell_Command::Fd_Shell_Command(const Fl_String &in_name, const Fl_String &in_label, Fl_Shortcut in_shortcut, Fd_Tool_Store in_storage, int in_condition, const Fl_String &in_condition_data, const Fl_String &in_command, int in_flags) : name(in_name), label(in_label), shortcut(in_shortcut), storage(in_storage), condition(in_condition), condition_data(in_condition_data), command(in_command), flags(in_flags), shell_menu_item_(NULL) { } /** Run this command now. Will open the Shell Panel and execute the command if no other command is currently running. */ void Fd_Shell_Command::run() { if (!command.empty()) run_shell_command(command, flags); } /** Update the shell submenu in main menu with the shortcut and a copy of the label. */ void Fd_Shell_Command::update_shell_menu() { if (shell_menu_item_) { const char *old_label = shell_menu_item_->label(); // can be NULL const char *new_label = label.c_str(); // never NULL if (!old_label || (old_label && strcmp(old_label, new_label))) { if (old_label) ::free((void*)old_label); shell_menu_item_->label(fl_strdup(new_label)); } shell_menu_item_->shortcut(shortcut); } } /** Check if the set condition is met. \return true if this command appears in the main menu */ bool Fd_Shell_Command::is_active() { switch (condition) { case ALWAYS: return true; case NEVER: return false; #ifdef _WIN32 case MAC_ONLY: return false; case UX_ONLY: return false; case WIN_ONLY: return true; case MAC_AND_UX_ONLY: return false; #elif defined(__APPLE__) case MAC_ONLY: return true; case UX_ONLY: return false; case WIN_ONLY: return false; case MAC_AND_UX_ONLY: return true; #else case MAC_ONLY: return false; case UX_ONLY: return true; case WIN_ONLY: return false; case MAC_AND_UX_ONLY: return true; #endif case USER_ONLY: return false; // TODO: get user name case HOST_ONLY: return false; // TODO: get host name case ENV_ONLY: { const char *value = fl_getenv(condition_data.c_str()); if (value && *value) return true; return false; } } return false; } void Fd_Shell_Command::read(Fl_Preferences &prefs) { int tmp; preferences_get(prefs, "name", name, ""); preferences_get(prefs, "label", label, ""); prefs.get("shortcut", tmp, 0); shortcut = (Fl_Shortcut)tmp; prefs.get("storage", tmp, -1); if (tmp != -1) storage = (Fd_Tool_Store)tmp; prefs.get("condition", condition, ALWAYS); preferences_get(prefs, "condition_data", condition_data, ""); preferences_get(prefs, "command", command, ""); prefs.get("flags", flags, 0); } void Fd_Shell_Command::write(Fl_Preferences &prefs, bool save_location) { preferences_set(prefs, "name", name); preferences_set(prefs, "label", label); if (shortcut != 0) prefs.set("shortcut", (int)shortcut); if (save_location) prefs.set("storage", (int)storage); if (condition != ALWAYS) prefs.set("condition", condition); if (!condition_data.empty()) preferences_set(prefs, "condition_data", condition_data); if (!command.empty()) preferences_set(prefs, "command", command); if (flags != 0) prefs.set("flags", flags); } void Fd_Shell_Command::read(class Fd_Project_Reader *in) { const char *c = in->read_word(1); if (strcmp(c, "{")!=0) return; // expecting start of group storage = FD_STORE_PROJECT; for (;;) { c = in->read_word(1); if (strcmp(c, "}")==0) break; // end of command list else if (strcmp(c, "name")==0) name = in->read_word(); else if (strcmp(c, "label")==0) label = in->read_word(); else if (strcmp(c, "shortcut")==0) shortcut = in->read_int(); else if (strcmp(c, "condition")==0) condition = in->read_int(); else if (strcmp(c, "condition_data")==0) condition_data = in->read_word(); else if (strcmp(c, "command")==0) command = in->read_word(); else if (strcmp(c, "flags")==0) flags = in->read_int(); else in->read_word(); // skip an unknown word } } void Fd_Shell_Command::write(class Fd_Project_Writer *out) { out->write_string("\n command {"); out->write_string("\n name "); out->write_word(name.c_str()); out->write_string("\n label "); out->write_word(label.c_str()); if (shortcut) out->write_string("\n shortcut %d", shortcut); if (condition) out->write_string("\n condition %d", condition); if (!condition_data.empty()) { out->write_string("\n condition_data "); out->write_word(condition_data.c_str()); } if (!command.empty()) { out->write_string("\n command "); out->write_word(command.c_str()); } if (flags) out->write_string("\n flags %d", flags); out->write_string("\n }"); } /** Manage a list of shell commands and their parameters. */ Fd_Shell_Command_List::Fd_Shell_Command_List() : list(NULL), list_size(0), list_capacity(0), shell_menu_(NULL) { } /** Release all shell commands and destroy this class. */ Fd_Shell_Command_List::~Fd_Shell_Command_List() { clear(); } /** Return the shell command at the given index. \param[in] index must be between 0 and list_size-1 \return a pointer to the shell command data */ Fd_Shell_Command *Fd_Shell_Command_List::at(int index) const { return list[index]; } /** Clear all shell commands. */ void Fd_Shell_Command_List::clear() { if (list) { for (int i=0; i=0; i--) { if (list[i]->storage == storage) { remove(i); } } } /** Read shell configuration from a preferences group. */ void Fd_Shell_Command_List::read(Fl_Preferences &prefs, Fd_Tool_Store storage) { // import the old shell commands from previous user settings if (&fluid_prefs == &prefs) { int version; prefs.get("shell_commands_version", version, 0); if (version == 0) { int save_fl, save_code, save_strings; Fd_Shell_Command *cmd = new Fd_Shell_Command(); cmd->storage = FD_STORE_USER; cmd->name = "Sample Shell Command"; cmd->label = "Sample Shell Command"; cmd->shortcut = FL_ALT+'g'; preferences_get(fluid_prefs, "shell_command", cmd->command, "echo \"Sample Shell Command\""); fluid_prefs.get("shell_savefl", save_fl, 1); fluid_prefs.get("shell_writecode", save_code, 1); fluid_prefs.get("shell_writemsgs", save_strings, 0); if (save_fl) cmd->flags |= Fd_Shell_Command::SAVE_PROJECT; if (save_code) cmd->flags |= Fd_Shell_Command::SAVE_SOURCECODE; if (save_strings) cmd->flags |= Fd_Shell_Command::SAVE_STRINGS; add(cmd); } version = 1; prefs.set("shell_commands_version", version); } Fl_Preferences shell_commands(prefs, "shell_commands"); int n = shell_commands.groups(); for (int i=0; istorage = FD_STORE_USER; cmd->read(cmd_prefs); add(cmd); } } /** Write shell configuration to a preferences group. */ void Fd_Shell_Command_List::write(Fl_Preferences &prefs, Fd_Tool_Store storage) { Fl_Preferences shell_commands(prefs, "shell_commands"); shell_commands.delete_all_groups(); int index = 0; for (int i=0; istorage == FD_STORE_USER) { Fl_Preferences cmd(shell_commands, Fl_Preferences::Name(index++)); list[i]->write(cmd); } } } /** Read shell configuration from a project file. */ void Fd_Shell_Command_List::read(Fd_Project_Reader *in) { const char *c = in->read_word(1); if (strcmp(c, "{")!=0) return; // expecting start of group clear(FD_STORE_PROJECT); for (;;) { c = in->read_word(1); if (strcmp(c, "}")==0) break; // end of command list else if (strcmp(c, "command")==0) { Fd_Shell_Command *cmd = new Fd_Shell_Command(); add(cmd); cmd->read(in); } else { in->read_word(); // skip an unknown group } } } /** Write shell configuration to a project file. */ void Fd_Shell_Command_List::write(Fd_Project_Writer *out) { int n_in_project_file = 0; for (int i=0; istorage == FD_STORE_PROJECT) n_in_project_file++; } if (n_in_project_file > 0) { out->write_string("\nshell_commands {"); for (int i=0; istorage == FD_STORE_PROJECT) list[i]->write(out); } out->write_string("\n}"); } } /** Add a previously created shell command to the end of the list. \param[in] cmd a pointer to the command that we want to add */ void Fd_Shell_Command_List::add(Fd_Shell_Command *cmd) { if (list_size == list_capacity) { list_capacity += 16; list = (Fd_Shell_Command**)::realloc(list, list_capacity * sizeof(Fd_Shell_Command*)); } list[list_size++] = cmd; } /** Insert a newly created shell command at the given position in the list. \param[in] index must be between 0 and list_size-1 \param[in] cmd a pointer to the command that we want to add */ void Fd_Shell_Command_List::insert(int index, Fd_Shell_Command *cmd) { if (list_size == list_capacity) { list_capacity += 16; list = (Fd_Shell_Command**)::realloc(list, list_capacity * sizeof(Fd_Shell_Command*)); } ::memmove(list+index+1, list+index, (list_size-index)*sizeof(Fd_Shell_Command**)); list_size++; list[index] = cmd; } /** Remove and delete the command at the given index. \param[in] index must be between 0 and list_size-1 */ void Fd_Shell_Command_List::remove(int index) { delete list[index]; list_size--; ::memmove(list+index, list+index+1, (list_size-index)*sizeof(Fd_Shell_Command**)); } /** This is called whenever the user clicks a shell command menu in the main menu. \param[in] u cast tp long to get the index of the shell command */ void menu_shell_cmd_cb(Fl_Widget*, void *u) { long index = (long)(fl_intptr_t)u; g_shell_config->list[index]->run(); } /** This is called when the user selects the menu to edit the shell commands. It pops up the setting panel at the shell settings tab. */ void menu_shell_customize_cb(Fl_Widget*, void*) { settings_window->show(); w_settings_tabs->value(w_settings_shell_tab); } /** Rebuild the entire shell submenu from scratch and replace the old menu. */ void Fd_Shell_Command_List::rebuild_shell_menu() { static Fl_Menu_Item *shell_submenu = NULL; if (!shell_submenu) shell_submenu = (Fl_Menu_Item*)main_menubar->find_item(menu_marker); int i, j, num_active_items = 0; // count the active commands for (i=0; iis_active()) num_active_items++; } // allocate a menu item array Fl_Menu_Item *mi = (Fl_Menu_Item*)::calloc(num_active_items+2, sizeof(Fl_Menu_Item)); // set the menu item pointer for all active commands for (i=j=0; iis_active()) { cmd->shell_menu_item_ = mi + j; mi[j].callback(menu_shell_cmd_cb); mi[j].argument(i); cmd->update_shell_menu(); j++; } } if (j>0) mi[j-1].flags |= FL_MENU_DIVIDER; mi[j].label(fl_strdup("Customize...")); mi[j].shortcut(FL_ALT+'x'); mi[j].callback(menu_shell_customize_cb); // replace the old menu array with the new one Fl_Menu_Item *mi_old = shell_menu_; shell_menu_ = mi; shell_submenu->user_data(shell_menu_); // free all resources from the old menu if (mi_old && (mi_old != default_menu)) { for (i=0; ; i++) { const char *label = mi_old[i].label(); if (!label) break; ::free((void*)label); } ::free(mi_old); } } /** Tell the settings dialog to query this list and update its GUI elements. */ void Fd_Shell_Command_List::update_settings_dialog() { if (w_settings_shell_tab) w_settings_shell_tab->do_callback(w_settings_shell_tab, LOAD); } /** The default shell submenu in batch mode. */ Fl_Menu_Item Fd_Shell_Command_List::default_menu[] = { { "Customize...", FL_ALT+'x', menu_shell_customize_cb }, { NULL } }; /** Used to find the shell submenu within the main menu tree. */ void Fd_Shell_Command_List::menu_marker(Fl_Widget*, void*) { // intentionally left empty } /** Export all selected shell commands to an external file. Verify that g_shell_config and w_settings_shell_list are not NULL. Open a file chooser and export all items that are selected in w_settings_shell_list into an external file. */ void Fd_Shell_Command_List::export_selected() { if (!g_shell_config || (g_shell_config->list_size == 0)) return; if (!w_settings_shell_list) return; Fl_Native_File_Chooser dialog; dialog.title("Export selected shell commands:"); dialog.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); dialog.filter("FLUID Files\t*.flcmd\n"); dialog.directory(g_project.projectfile_path().c_str()); dialog.preset_file((g_project.basename() + ".flcmd").c_str()); if (dialog.show() != 0) return; Fl_Preferences file(dialog.filename(), "flcmd.fluid.fltk.org", NULL, (Fl_Preferences::Root)(Fl_Preferences::C_LOCALE|Fl_Preferences::CLEAR)); Fl_Preferences shell_commands(file, "shell_commands"); int i, index = 0, n = w_settings_shell_list->size(); for (i = 0; i < n; i++) { if (w_settings_shell_list->selected(i+1)) { Fl_Preferences cmd(shell_commands, Fl_Preferences::Name(index++)); g_shell_config->list[i]->write(cmd, true); } } } /** Import shell commands from an external file and add them to the list. Verify that g_shell_config and w_settings_shell_list are not NULL. Open a file chooser and import all items. */ void Fd_Shell_Command_List::import_from_file() { if (!g_shell_config || (g_shell_config->list_size == 0)) return; if (!w_settings_shell_list) return; Fl_Native_File_Chooser dialog; dialog.title("Import shell commands:"); dialog.type(Fl_Native_File_Chooser::BROWSE_FILE); dialog.filter("FLUID Files\t*.flcmd\n"); dialog.directory(g_project.projectfile_path().c_str()); dialog.preset_file((g_project.basename() + ".flcmd").c_str()); if (dialog.show() != 0) return; Fl_Preferences file(dialog.filename(), "flcmd.fluid.fltk.org", NULL, Fl_Preferences::C_LOCALE); Fl_Preferences shell_commands(file, "shell_commands"); int i, n = shell_commands.groups(); for (i = 0; i < n; i++) { Fl_Preferences cmd_prefs(shell_commands, Fl_Preferences::Name(i)); Fd_Shell_Command *cmd = new Fd_Shell_Command(); cmd->storage = FD_STORE_USER; cmd->read(cmd_prefs); g_shell_config->add(cmd); } w_settings_shell_list->do_callback(w_settings_shell_list, LOAD); w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); w_settings_shell_toolbox->do_callback(w_settings_shell_toolbox, LOAD); g_shell_config->rebuild_shell_menu(); } /** A pointer to the list of shell commands if we are not in batch mode. */ Fd_Shell_Command_List *g_shell_config = NULL; fltk-1.4.3/fluid/ExternalCodeEditor_UNIX.cxx0000644000175000017500000004351515004135251021033 0ustar albrechtalbrecht// // External code editor management class for Unix // // Note: This entire file Unix only #include "ExternalCodeEditor_UNIX.h" #include "fluid.h" #include /* Fl_Timeout_Handler.. */ #include /* fl_alert() */ #include /* fl_strdup() */ #include /* errno */ #include /* strerror() */ #include /* stat().. */ #include #include /* waitpid().. */ #include /* open().. */ #include /* kill().. */ #include #include /* free().. */ #include /* snprintf().. */ // Static local data static int L_editors_open = 0; // keep track of #editors open static Fl_Timeout_Handler L_update_timer_cb = 0; // app's update timer callback // [Static/Local] See if file exists static int is_file(const char *filename) { struct stat buf; if ( stat(filename, &buf) < 0 ) return(0); return(S_ISREG(buf.st_mode) ? 1 : 0); // regular file? } // [Static/Local] See if dir exists static int is_dir(const char *dirname) { struct stat buf; if ( stat(dirname, &buf) < 0 ) return(0); return(S_ISDIR(buf.st_mode) ? 1 : 0); // a dir? } // ---- ExternalCodeEditor implementation /** \class ExternalCodeEditor Support for an external C++ code editor for Fluid Code block. This class can launch and quit a user defined program for editing code outside of Fluid. It observes changes in the external file and updates the Fluid widget to stay synchronized. */ /** Create the manager for external code editors. */ ExternalCodeEditor::ExternalCodeEditor() { pid_ = -1; filename_ = 0; file_mtime_ = 0; file_size_ = 0; alert_pipe_[0] = alert_pipe_[1] = -1; alert_pipe_open_ = false; } /** Destroy the manager. This also closes the external editor. */ ExternalCodeEditor::~ExternalCodeEditor() { if ( G_debug ) printf("ExternalCodeEditor() DTOR CALLED (this=%p, pid=%ld)\n", (void*)this, (long)pid_); close_editor(); // close editor, delete tmp file set_filename(0); // free()s filename if (alert_pipe_open_) { Fl::remove_fd(alert_pipe_[0]); if (alert_pipe_[0] != -1) ::close(alert_pipe_[0]); if (alert_pipe_[1] != -1) ::close(alert_pipe_[1]); } } /** Set the filename for the file we wish to edit. Handles memory allocation/free. If set to NULL, frees memory. \param[in] val new filename */ void ExternalCodeEditor::set_filename(const char *val) { if ( filename_ ) free((void*)filename_); filename_ = val ? fl_strdup(val) : 0; } /** Is editor running? \return 1 if we are currently editing a file. */ int ExternalCodeEditor::is_editing() { return( (pid_ != -1) ? 1 : 0 ); } /** Wait for editor to close */ void ExternalCodeEditor::close_editor() { if ( G_debug ) printf("close_editor() called: pid=%ld\n", long(pid_)); // Wait until editor is closed + reaped while ( is_editing() ) { switch ( reap_editor() ) { case -2: // no editor running (unlikely to happen) return; case -1: // error fl_alert("Error reaping external editor\n" "pid=%ld file=%s", long(pid_), filename()); break; case 0: // process still running switch ( fl_choice("Please close external editor\npid=%ld file=%s", "Force Close", // button 0 "Closed", // button 1 0, // button 2 long(pid_), filename() ) ) { case 0: // Force Close kill_editor(); continue; case 1: // Closed? try to reap continue; } break; case 1: // process reaped return; } } } /** Kill the running editor (if any). Kills the editor, reaps the process, and removes the tmp file. The dtor calls this to ensure no editors remain running when fluid exits. */ void ExternalCodeEditor::kill_editor() { if ( G_debug ) printf("kill_editor() called: pid=%ld\n", (long)pid_); if ( !is_editing() ) return; // editor not running? return.. kill(pid_, SIGTERM); // kill editor int wcount = 0; while ( is_editing() ) { // and wait for editor to finish.. usleep(100000); // 1/10th sec delay gives editor time to close itself pid_t pid_reaped; switch ( reap_editor(&pid_reaped) ) { case -2: // editor not running (unlikely to happen) return; case -1: // error fl_alert("Can't seem to close editor of file: %s\n" "waitpid() returned: %s\n" "Please close editor and hit OK", filename(), strerror(errno)); continue; case 0: // process still running if ( ++wcount > 3 ) { // retry 3x with 1/10th delay before showing dialog fl_alert("Can't seem to close editor of file: %s\n" "Please close editor and hit OK", filename()); } continue; case 1: // process reaped (reap_editor() sets pid_ to -1) if ( G_debug ) printf("*** REAPED KILLED EXTERNAL EDITOR: PID %ld\n", (long)pid_reaped); break; } } return; } /** Handle if file changed since last check, and update records if so. Load new data into 'code', which caller must free(). If 'force' set, forces reload even if file size/time didn't change. \param[in] code \param[in] force \return 0 if file unchanged or not editing \return 1 if file changed, internal records updated, 'code' has new content \return -1 error getting file info (strerror() has reason) */ int ExternalCodeEditor::handle_changes(const char **code, int force) { code[0] = 0; if ( !is_editing() ) return 0; // Get current time/size info, see if file changed int changed = 0; { struct stat sbuf; if ( stat(filename(), &sbuf) < 0 ) return(-1); // TODO: show fl_alert(), do this in win32 too, adjust func call docs above time_t now_mtime = sbuf.st_mtime; size_t now_size = sbuf.st_size; // OK, now see if file changed; update records if so if ( now_mtime != file_mtime_ ) { changed = 1; file_mtime_ = now_mtime; } if ( now_size != file_size_ ) { changed = 1; file_size_ = now_size; } } // No changes? done if ( !changed && !force ) return 0; // Changes? Load file, and fallthru to close() int fd = open(filename(), O_RDONLY); if ( fd < 0 ) { fl_alert("ERROR: can't open '%s': %s", filename(), strerror(errno)); return -1; } int ret = 0; char *buf = (char*)malloc(file_size_ + 1); ssize_t count = read(fd, buf, file_size_); if ( count == -1 ) { fl_alert("ERROR: read() %s: %s", filename(), strerror(errno)); free((void*)buf); ret = -1; } else if ( (long)count != (long)file_size_ ) { fl_alert("ERROR: read() failed for %s:\n" "expected %ld bytes, only got %ld", filename(), long(file_size_), long(count)); ret = -1; } else { // Success -- file loaded OK buf[count] = '\0'; code[0] = buf; // return pointer to allocated buffer ret = 1; } close(fd); return ret; } /** Remove the tmp file (if it exists), and zero out filename/mtime/size. \return -1 on error (dialog is posted as to why) \return 0 no file to remove \return 1 -- file was removed */ int ExternalCodeEditor::remove_tmpfile() { const char *tmpfile = filename(); if ( !tmpfile ) return 0; // Filename set? remove (if exists) and zero filename/mtime/size if ( is_file(tmpfile) ) { if ( G_debug ) printf("Removing tmpfile '%s'\n", tmpfile); if ( remove(tmpfile) < 0 ) { fl_alert("WARNING: Can't remove() '%s': %s", tmpfile, strerror(errno)); return -1; } } set_filename(0); file_mtime_ = 0; file_size_ = 0; return 1; } /** Return tmpdir name for this fluid instance. \return pointer to static memory. */ const char* ExternalCodeEditor::tmpdir_name() { static char dirname[100]; snprintf(dirname, sizeof(dirname), "/tmp/.fluid-%ld", (long)getpid()); return dirname; } /** Clear the external editor's tempdir. Static so that the main program can call it on exit to clean up. */ void ExternalCodeEditor::tmpdir_clear() { const char *tmpdir = tmpdir_name(); if ( is_dir(tmpdir) ) { if ( G_debug ) printf("Removing tmpdir '%s'\n", tmpdir); if ( rmdir(tmpdir) < 0 ) { fl_alert("WARNING: Can't rmdir() '%s': %s", tmpdir, strerror(errno)); } } } /** Creates temp dir (if doesn't exist) and returns the dirname as a static string. \return NULL on error, dialog shows reason. */ const char* ExternalCodeEditor::create_tmpdir() { const char *dirname = tmpdir_name(); if ( ! is_dir(dirname) ) { if ( mkdir(dirname, 0777) < 0 ) { fl_alert("can't create directory '%s': %s", dirname, strerror(errno)); return NULL; } } return dirname; } /** Returns temp filename in static buffer. \return NULL if can't, posts dialog explaining why. */ const char* ExternalCodeEditor::tmp_filename() { static char path[FL_PATH_MAX+1]; const char *tmpdir = create_tmpdir(); if ( !tmpdir ) return 0; const char *ext = g_project.code_file_name.c_str(); // e.g. ".cxx" snprintf(path, FL_PATH_MAX, "%s/%p%s", tmpdir, (void*)this, ext); path[FL_PATH_MAX] = 0; return path; } /** Save string 'code' to 'filename', returning file's mtime/size. 'code' can be NULL -- writes an empty file if so. \return 0 on success \return -1 on error (posts dialog with reason) */ static int save_file(const char *filename, const char *code) { if ( code == 0 ) code = ""; // NULL? write an empty file int fd = open(filename, O_WRONLY|O_CREAT, 0666); if ( fd == -1 ) { fl_alert("ERROR: open() '%s': %s", filename, strerror(errno)); return -1; } ssize_t clen = strlen(code); ssize_t count = write(fd, code, clen); int ret = 0; if ( count == -1 ) { fl_alert("ERROR: write() '%s': %s", filename, strerror(errno)); ret = -1; // fallthru to close() } else if ( count != clen ) { fl_alert("ERROR: write() '%s': wrote only %lu bytes, expected %lu", filename, (unsigned long)count, (unsigned long)clen); ret = -1; // fallthru to close() } close(fd); return(ret); } /** Convert string 's' to array of argv[], useful for execve(). - 's' will be modified (words will be NULL separated) - argv[] will end up pointing to the words of 's' - Caller must free argv with: free(argv); \return -1 in case of memory allocation error \return number of arguments in argv (same value as in argc) */ static int make_args(char *s, // string containing words (gets trashed!) int *aargc, // pointer to argc char ***aargv) { // pointer to argv char *ss, **argv; if ((argv=(char**)malloc(sizeof(char*) * (strlen(s)/2)))==NULL) { return -1; } int t; for(t=0; (t==0)?(ss=strtok(s," \t")):(ss=strtok(0," \t")); t++) { argv[t] = ss; } argv[t] = 0; aargv[0] = argv; aargc[0] = t; return(t); } /** If no alert pipe is open yet, try to create the pipe and hook it up the the fd callback. The alert pipe is used to communicate from the forked process to the main FLTK app in case launching the editor failed. */ void ExternalCodeEditor::open_alert_pipe() { if (!alert_pipe_open_) { if (::pipe(alert_pipe_) == 0) { Fl::add_fd(alert_pipe_[0], FL_READ, alert_pipe_cb, this); alert_pipe_open_ = true; } else { alert_pipe_[0] = alert_pipe_[1] = -1; } } } /** Start editor in background (fork/exec) \return 0 on success, leaves editor child process running as 'pid_' \return -1 on error, posts dialog with reason (child exits) */ int ExternalCodeEditor::start_editor(const char *editor_cmd, const char *filename) { if ( G_debug ) printf("start_editor() cmd='%s', filename='%s'\n", editor_cmd, filename); char cmd[1024]; snprintf(cmd, sizeof(cmd), "%s %s", editor_cmd, filename); command_line_ = editor_cmd; open_alert_pipe(); // Fork editor to background.. switch ( pid_ = fork() ) { case -1: // error fl_alert("couldn't fork(): %s", strerror(errno)); return -1; case 0: { // child // NOTE: OSX wants minimal code between fork/exec, see Apple TN2083 // NOTE: no FLTK calls after a fork. Use a pipe to tell the app if the // command can't launch int nargs; char **args = 0; if (make_args(cmd, &nargs, &args) > 0) { execvp(args[0], args); // run command - doesn't return if succeeds if (alert_pipe_open_) { int err = errno; if (::write(alert_pipe_[1], &err, sizeof(int)) != sizeof(int)) { // should not happen, but if it does, at least we tried } } exit(1); } exit(1); // break; } default: // parent if ( L_editors_open++ == 0 ) // first editor? start timers { start_update_timer(); } if ( G_debug ) printf("--- EDITOR STARTED: pid_=%ld #open=%d\n", (long)pid_, L_editors_open); break; } return 0; } /** Try to reap external editor process. If 'pid_reaped' not NULL, returns PID of reaped editor. \return -2: editor not open \return -1: waitpid() failed (errno has reason) \return 0: process still running \return 1: process finished + reaped ('pid_reaped' has pid), pid_ set to -1. Handles removing tmpfile/zeroing file_mtime/file_size/filename \return If return value <=0, 'pid_reaped' is set to zero. */ int ExternalCodeEditor::reap_editor(pid_t *pid_reaped) { if ( pid_reaped ) *pid_reaped = 0; if ( !is_editing() ) return -2; int status = 0; pid_t wpid; switch (wpid = waitpid(pid_, &status, WNOHANG)) { case -1: // waitpid() failed return -1; case 0: // process didn't reap, still running return 0; default: // process reaped if ( pid_reaped ) *pid_reaped = wpid; // return pid to caller remove_tmpfile(); // also zeroes mtime/size pid_ = -1; if ( --L_editors_open <= 0 ) { stop_update_timer(); } break; } if ( G_debug ) printf("*** EDITOR REAPED: pid=%ld #open=%d\n", long(wpid), L_editors_open); return 1; } /** Open external editor using 'editor_cmd' to edit 'code'. 'code' contains multiline code to be edited as a temp file. 'code' can be NULL -- edits an empty file if so. \return 0 if succeeds \return -1 if can't open editor (already open, etc), errors were shown to user in a dialog */ int ExternalCodeEditor::open_editor(const char *editor_cmd, const char *code) { // Make sure a temp filename exists if ( !filename() ) { set_filename(tmp_filename()); if ( !filename() ) return -1; } // See if tmpfile already exists or editor already open if ( is_file(filename()) ) { if ( is_editing() ) { // See if editor recently closed but not reaped; try to reap pid_t wpid; switch ( reap_editor(&wpid) ) { case -2: // no editor running? (unlikely if is_editing() true) break; case -1: // waitpid() failed fl_alert("ERROR: waitpid() failed: %s\nfile='%s', pid=%ld", strerror(errno), filename(), (long)pid_); return -1; case 0: // process still running fl_alert("Editor Already Open\n file='%s'\n pid=%ld", filename(), (long)pid_); return 0; case 1: // process reaped, wpid is pid reaped if ( G_debug ) printf("*** REAPED EXTERNAL EDITOR: PID %ld\n", (long)wpid); break; // fall thru to open new editor instance } // Reinstate tmp filename (reap_editor() clears it) set_filename(tmp_filename()); } } if ( save_file(filename(), code) < 0 ) { return -1; // errors were shown in dialog } // Update mtime/size from closed file struct stat sbuf; if ( stat(filename(), &sbuf) < 0 ) { fl_alert("ERROR: can't stat('%s'): %s", filename(), strerror(errno)); return -1; } file_mtime_ = sbuf.st_mtime; file_size_ = sbuf.st_size; if ( start_editor(editor_cmd, filename()) < 0 ) { // open file in external editor if ( G_debug ) printf("Editor failed to start\n"); return -1; // errors were shown in dialog } return 0; } /** Start update timer. */ void ExternalCodeEditor::start_update_timer() { if ( !L_update_timer_cb ) return; if ( G_debug ) printf("--- TIMER: STARTING UPDATES\n"); Fl::add_timeout(2.0, L_update_timer_cb); } /** Stop update timer. */ void ExternalCodeEditor::stop_update_timer() { if ( !L_update_timer_cb ) return; if ( G_debug ) printf("--- TIMER: STOPPING UPDATES\n"); Fl::remove_timeout(L_update_timer_cb); } /** Set app's external editor update timer callback. This is the app's callback callback we start while editors are open, and stop when all editors are closed. */ void ExternalCodeEditor::set_update_timer_callback(Fl_Timeout_Handler cb) { L_update_timer_cb = cb; } /** See if any external editors are open. App's timer cb can see if any editors need checking.. */ int ExternalCodeEditor::editors_open() { return L_editors_open; } /** It the forked process can't run the editor, it will send the errno through a pipe. */ void ExternalCodeEditor::alert_pipe_cb(FL_SOCKET s, void* d) { ExternalCodeEditor* self = (ExternalCodeEditor*)d; self->last_error_ = 0; if (::read(s, &self->last_error_, sizeof(int)) != sizeof(int)) return; const char* cmd = self->command_line_.c_str(); if (cmd && *cmd) { if (cmd[0] == '/') { // is this an absolute filename? fl_alert("Can't launch external editor '%s':\n%s\n\ncmd: \"%s\"", fl_filename_name(cmd), strerror(self->last_error_), cmd); } else { char pwd[FL_PATH_MAX+1]; fl_getcwd(pwd, FL_PATH_MAX); fl_alert("Can't launch external editor '%s':\n%s\n\ncmd: \"%s\"\npwd: \"%s\"", fl_filename_name(cmd), strerror(self->last_error_), cmd, pwd); } } } fltk-1.4.3/fluid/fluid_filename.cxx0000644000175000017500000001726015004135251017405 0ustar albrechtalbrecht// // Filename expansion routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file fluid/fluid_filename.cxx \brief File names and URI utility functions for FLUID only. This file defines all fl_filename* functions using Fl_String and also includes the main header file . \note This file contains some filename functions using Fl_String which which are used in FLTK 1.4.x but will be removed in the next minor or major release after 1.4.x (i.e. 1.5 or maybe 4.0). \note This entire file should become obsolete in 1.5 or higher, whatever the next release after 1.4.x will be. We'll use std::string instead! */ #include #include #include #include #include "../src/Fl_String.H" // NOTE: FLTK 1.4.x only ! #include "../src/flstring.h" /** Return a new string that contains the name part of the filename. \param[in] filename file path and name \return the name part of a filename \see fl_filename_name(const char *filename) */ Fl_String fl_filename_name(const Fl_String &filename) { return Fl_String(fl_filename_name(filename.c_str())); } /** Return a new string that contains the path part of the filename. \param[in] filename file path and name \return the path part of a filename without the name \see fl_filename_name(const char *filename) */ Fl_String fl_filename_path(const Fl_String &filename) { const char *base = filename.c_str(); const char *name = fl_filename_name(base); if (name) { return Fl_String(base, (int)(name-base)); } else { return Fl_String(); } } /** Return a new string that contains the filename extension. \param[in] filename file path and name \return the filename extension including the prepending '.', or an empty string if the filename has no extension \see fl_filename_ext(const char *buf) */ Fl_String fl_filename_ext(const Fl_String &filename) { return Fl_String(fl_filename_ext(filename.c_str())); } /** Return a copy of the old filename with the new extension. \param[in] filename file path and name \param[in] new_extension new filename extension, starts with a '.' \return the new filename \see fl_filename_setext(char *to, int tolen, const char *ext) */ Fl_String fl_filename_setext(const Fl_String &filename, const Fl_String &new_extension) { char buffer[FL_PATH_MAX]; fl_strlcpy(buffer, filename.c_str(), FL_PATH_MAX); fl_filename_setext(buffer, FL_PATH_MAX, new_extension.c_str()); return Fl_String(buffer); } /** Expands a filename containing shell variables and tilde (~). \param[in] from file path and name \return the new, expanded filename \see fl_filename_expand(char *to, int tolen, const char *from) */ Fl_String fl_filename_expand(const Fl_String &from) { char buffer[FL_PATH_MAX]; fl_filename_expand(buffer, FL_PATH_MAX, from.c_str()); return Fl_String(buffer); } /** Makes a filename absolute from a filename relative to the current working directory. \param[in] from relative filename \return the new, absolute filename \see fl_filename_absolute(char *to, int tolen, const char *from) */ Fl_String fl_filename_absolute(const Fl_String &from) { char buffer[FL_PATH_MAX]; fl_filename_absolute(buffer, FL_PATH_MAX, from.c_str()); return Fl_String(buffer); } /** Append the relative filename `from` to the absolute filename `base` to form the new absolute path. \param[in] from relative filename \param[in] base `from` is relative to this absolute file path \return the new, absolute filename \see fl_filename_absolute(char *to, int tolen, const char *from, const char *base) */ Fl_String fl_filename_absolute(const Fl_String &from, const Fl_String &base) { char buffer[FL_PATH_MAX]; fl_filename_absolute(buffer, FL_PATH_MAX, from.c_str(), base.c_str()); return Fl_String(buffer); } /** Makes a filename relative to the current working directory. \param[in] from file path and name \return the new, relative filename \see fl_filename_relative(char *to, int tolen, const char *from) */ Fl_String fl_filename_relative(const Fl_String &from) { char buffer[FL_PATH_MAX]; fl_filename_relative(buffer, FL_PATH_MAX, from.c_str()); return Fl_String(buffer); } /** Makes a filename relative to any directory. \param[in] from file path and name \param[in] base relative to this absolute path \return the new, relative filename \see fl_filename_relative(char *to, int tolen, const char *from, const char *base) */ Fl_String fl_filename_relative(const Fl_String &from, const Fl_String &base) { char buffer[FL_PATH_MAX]; fl_filename_relative(buffer, FL_PATH_MAX, from.c_str(), base.c_str()); return Fl_String(buffer); } /** Cross-platform function to get the current working directory as a UTF-8 encoded value in an Fl_String. \return the CWD encoded as UTF-8 */ Fl_String fl_getcwd() { char buffer[FL_PATH_MAX]; fl_getcwd(buffer, FL_PATH_MAX); return Fl_String(buffer); } /** Return a shortened filename for limited display width. Replace the start uf a path with "~" if it matches the home directory. If the remaining filename has more than the give number of characters, it will be shortened by replacing parts of the path with an ellipsis ("..."). The shortened name can no longer be used to open a file. This is purely to make as much information visible while fitting into a give space. \param[in] filename absolute path and name, UTF-8 aware \param[in[ max_chars maximum number of characters in result, including ellipsis \return shortened file path and name */ Fl_String fl_filename_shortened(const Fl_String &filename, int max_chars) { // Insert this as the ellipsis static const char *ell = "..."; static const int ell_bytes = 3; // Replace the start of a path with "~" if it matches the home directory static Fl_String tilde = "~/"; static Fl_String home; static int home_chars = -1; if (home_chars==-1) { home = fl_filename_expand(tilde); home_chars = fl_utf_nb_char((const uchar*)home.c_str(), home.size()); } Fl_String homed_filename; #if defined(_WIN32) || defined(__APPLE__) bool starts_with_home = fl_utf_strncasecmp(home.c_str(), filename.c_str(), home_chars)==0; #else bool starts_with_home = ::strncmp(home.c_str(), filename.c_str(), home.size())==0; #endif if (starts_with_home) { homed_filename = tilde + filename.substr(home.size()); } else { homed_filename = filename; } // C style pointer will stay valid until filename is modified. const unsigned char *u8str = reinterpret_cast(homed_filename.c_str()); // Count the number of UTF-8 characters in the name. int num_chars = fl_utf_nb_char(u8str, homed_filename.size()); if (num_chars+ell_bytes-1 > max_chars) { // Create a new string by replacing characters in the middle. int remove_chars = num_chars - max_chars + ell_bytes; int left_chars = (max_chars - ell_bytes)/2; // int right_chars = max_chars - left_chars - 3; // int right_start_char = num_chars - right_chars; // Convert character counts into byte counts. int left_bytes = fl_utf8strlen(homed_filename.c_str(), left_chars); int right_start_byte = fl_utf8strlen(homed_filename.c_str()+left_bytes, remove_chars) + left_bytes; return homed_filename.substr(0, left_bytes) + ell + homed_filename.substr(right_start_byte); } else { // Nothing to change. return homed_filename; } } fltk-1.4.3/fluid/align_widget.cxx0000644000175000017500000002702515004135251017077 0ustar albrechtalbrecht// // Alignment code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "align_widget.h" #include "fluid.h" #include "Fl_Group_Type.h" #include "undo.h" #include #include /** the first behavior always uses the first selected widget as a reference the second behavior uses the largest widget (most extreme positions) as a reference. */ #define BREAK_ON_FIRST break //#define BREAK_ON_FIRST void align_widget_cb(Fl_Widget*, long how) { const int max = 32768, min = -32768; int left, right, top, bot, wdt, hgt, n; Fl_Type *o; int changed = 0; switch ( how ) { //---- align case 10: // align left left = max; for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; if (w->x()x(); BREAK_ON_FIRST; } if (left!=max) for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Type::allow_layout++; w->resize(left, w->y(), w->w(), w->h()); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 11: // align h.center left = max; right = min; for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; if (w->x()x(); if (w->x()+w->w()>right) right = w->x()+w->w(); BREAK_ON_FIRST; } if (left!=max) { int center2 = left+right; for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Type::allow_layout++; w->resize((center2-w->w())/2, w->y(), w->w(), w->h()); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } } break; case 12: // align right right = min; for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; if (w->x()+w->w()>right) right = w->x()+w->w(); BREAK_ON_FIRST; } if (right!=min) for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Type::allow_layout++; w->resize(right-w->w(), w->y(), w->w(), w->h()); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 13: // align top top = max; for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; if (w->y()y(); BREAK_ON_FIRST; } if (top!=max) for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Type::allow_layout++; w->resize(w->x(), top, w->w(), w->h()); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 14: // align v.center top = max; bot = min; for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; if (w->y()y(); if (w->y()+w->h()>bot) bot = w->y()+w->h(); BREAK_ON_FIRST; } if (top!=max) { int center2 = top+bot; for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Type::allow_layout++; w->resize(w->x(), (center2-w->h())/2, w->w(), w->h()); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } } break; case 15: // align bottom bot = min; for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; if (w->y()+w->h()>bot) bot = w->y()+w->h(); BREAK_ON_FIRST; } if (bot!=min) for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Type::allow_layout++; w->resize( w->x(), bot-w->h(), w->w(), w->h()); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; //---- space evenly case 20: // space evenly across left = max; right = min; wdt = 0; n = 0; for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; if (w->x()x(); if (w->x()+w->w()>right) right = w->x()+w->w(); wdt += w->w(); n++; } wdt = (right-left)-wdt; n--; if (n>0) { wdt = wdt/n*n; // make sure that all gaps are the same, possibly moving the rightmost widget int cnt = 0, wsum = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Type::allow_layout++; w->resize(left+wsum+wdt*cnt/n, w->y(), w->w(), w->h()); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); cnt++; wsum += w->w(); } } break; case 21: // space evenly down top = max; bot = min; hgt = 0, n = 0; for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; if (w->y()y(); if (w->y()+w->h()>bot) bot = w->y()+w->h(); hgt += w->h(); n++; } hgt = (bot-top)-hgt; n--; if (n>0) { hgt = hgt/n*n; // make sure that all gaps are the same, possibly moving the rightmost widget int cnt = 0, hsum = 0; for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Type::allow_layout++; w->resize(w->x(), top+hsum+hgt*cnt/n, w->w(), w->h()); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); cnt++; hsum += w->h(); } } break; //---- make same size case 30: // same width wdt = min; for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; if (w->w()>wdt) wdt = w->w(); BREAK_ON_FIRST; } if (wdt!=min) for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Type::allow_layout++; w->resize(w->x(), w->y(), wdt, w->h()); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 31: // same height hgt = min; for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; if (w->h()>hgt) hgt = w->h(); BREAK_ON_FIRST; } if (hgt!=min) for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Type::allow_layout++; w->resize( w->x(), w->y(), w->w(), hgt); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 32: // same size hgt = min; wdt = min; for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { Fl_Widget *w = ((Fl_Widget_Type *)o)->o; if (w->w()>wdt) wdt = w->w(); if (w->h()>hgt) hgt = w->h(); BREAK_ON_FIRST; } if (hgt!=min) for (Fl_Type *o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Type::allow_layout++; w->resize( w->x(), w->y(), wdt, hgt); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; //---- center in group case 40: // center hor for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget() && o->parent) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Widget *p = ((Fl_Widget_Type *)o->parent)->o; int center2; if (w->window() == p) center2 = p->w(); else center2 = 2*p->x()+p->w(); Fl_Type::allow_layout++; w->resize((center2-w->w())/2, w->y(), w->w(), w->h()); Fl_Type::allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 41: // center vert for (o = Fl_Type::first; o; o = o->next) if (o->selected && o->is_widget() && o->parent) { if (!changed) { changed = 1; undo_checkpoint(); } Fl_Widget *w = ((Fl_Widget_Type *)o)->o; Fl_Widget *p = ((Fl_Widget_Type *)o->parent)->o; int center2; if (w->window() == p) center2 = p->h(); else center2 = 2*p->y()+p->h(); Fl_Type::allow_layout++; w->resize(w->x(), (center2-w->h())/2, w->w(), w->h()); Fl_Type::allow_layout--; set_modflag(1); w->redraw(); if (w->window()) w->window()->redraw(); } break; } if (changed) set_modflag(1); } fltk-1.4.3/fluid/custom_widgets.h0000644000175000017500000000527415004135251017131 0ustar albrechtalbrecht// // Shortcut header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FLUID_SHORTCUT_BUTTON_H #define _FLUID_SHORTCUT_BUTTON_H #include #include // Adding drag and drop for dragging widgets into windows. class Widget_Bin_Button : public Fl_Button { public: int handle(int) FL_OVERRIDE; Widget_Bin_Button(int X,int Y,int W,int H, const char* l = 0) : Fl_Button(X,Y,W,H,l) { } }; // Adding drag and drop functionality to drag window prototypes onto the desktop. class Widget_Bin_Window_Button : public Fl_Button { public: int handle(int) FL_OVERRIDE; Widget_Bin_Window_Button(int X,int Y,int W,int H, const char* l = 0) : Fl_Button(X,Y,W,H,l) { } }; // Callback signature for function returning the value of a variable. typedef int (Fluid_Coord_Callback)(class Fluid_Coord_Input const *, void*); // Entry for a list of variables available to an input field. // Fluid_Coord_Input::variables() expects an array of Fluid_Coord_Input_Vars // with the last entry's name_ set to NULL. typedef struct Fluid_Coord_Input_Vars { const char *name_; Fluid_Coord_Callback *callback_; } Fluid_Coord_Input_Vars; // A text input widget that understands simple math. class Fluid_Coord_Input : public Fl_Input { Fl_Callback *user_callback_; Fluid_Coord_Input_Vars *vars_; void *vars_user_data_; static void callback_handler_cb(Fluid_Coord_Input *This, void *v); void callback_handler(void *v); int eval_var(uchar *&s) const; int eval(uchar *&s, int prio) const; int eval(const char *s) const; public: Fluid_Coord_Input(int x, int y, int w, int h, const char *l=0L); /** Return the text in the widget text field. */ const char *text() const { return Fl_Input::value(); } /** Set the text in the text field */ void text(const char *v) { Fl_Input::value(v); } int value() const; void value(int v); /** Set the general callback for this widget. */ void callback(Fl_Callback *cb) { user_callback_ = cb; } /** Set the list of the available variables \param vars array of variables, last entry `has name_` set to `NULL` \param user_data is forwarded to the Variable callback */ void variables(Fluid_Coord_Input_Vars *vars, void *user_data) { vars_ = vars; vars_user_data_ = user_data; } int handle(int) FL_OVERRIDE; }; #endif fltk-1.4.3/fluid/about_panel.h0000644000175000017500000000167315004135251016361 0ustar albrechtalbrecht// // About dialog for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #ifndef about_panel_h #define about_panel_h #include #include extern void show_help(const char *name); #include #include "../src/flstring.h" extern Fl_Double_Window *about_panel; #include #include #include Fl_Double_Window* make_about_panel(); extern unsigned char fluid_flow_chart_800_png[41559]; #endif fltk-1.4.3/fluid/Fluid_Image.h0000644000175000017500000000400615004135251016226 0ustar albrechtalbrecht// // Image header file for the Fast Light Tool Kit (FLTK). // // This class stores the image labels for widgets in fluid. This is // not a class in FLTK itself, and will produce different types of // code depending on what the image type is. // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FLUID_IMAGE_H #define FLUID_IMAGE_H #include #include "code.h" class Fluid_Image { bool is_animated_gif_; const char *name_; int refcount; Fl_Shared_Image *img; const char *function_name_; protected: Fluid_Image(const char *name); // no public constructor ~Fluid_Image(); // no public destructor size_t write_static_binary(Fd_Code_Writer& f, const char* fmt); size_t write_static_text(Fd_Code_Writer& f, const char* fmt); void write_static_rgb(Fd_Code_Writer& f, const char* idata_name); public: int written; static Fluid_Image* find(const char *); void decrement(); // reference counting & automatic free void increment(); void image(Fl_Widget *); // set the image of this widget void deimage(Fl_Widget *); // set the deimage of this widget void write_static(Fd_Code_Writer& f, int compressed); void write_initializer(Fd_Code_Writer& f, const char *type_name, const char *format, ...); void write_code(Fd_Code_Writer& f, int bind, const char *var, int inactive = 0); void write_inline(Fd_Code_Writer& f, int inactive = 0); void write_file_error(Fd_Code_Writer& f, const char *fmt); const char *name() const {return name_;} }; // pop up file chooser and return a legal image selected by user, // or zero for any errors: Fluid_Image *ui_find_image(const char *); extern const char *ui_find_image_name; #endif fltk-1.4.3/fluid/template_panel.h0000644000175000017500000000245515004135251017061 0ustar albrechtalbrecht// // FLUID template support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // generated by Fast Light User Interface Designer (fluid) version 1.0402 #ifndef template_panel_h #define template_panel_h #include #include extern Fl_Double_Window *template_panel; #include extern Fl_Browser *template_browser; #include extern Fl_Box *template_preview; #include extern Fl_Input *template_name; extern Fl_Input *template_instance; #include #include extern Fl_Button *template_delete; #include extern Fl_Return_Button *template_submit; Fl_Double_Window* make_template_panel(); void template_clear(); void template_delete_cb(Fl_Button *, void *); void template_install(const char *path, const char *name, const uchar *inSrc, int inSrcLen, int inDstLen); void template_load(); #endif fltk-1.4.3/fltk.spec.in0000644000175000017500000000617615004135251015040 0ustar albrechtalbrecht# # RPM spec file for FLTK. # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # %define version @FLTK_VERSION@ %define release 1 %define prefix /usr Summary: Fast Light Tool Kit (FLTK) Name: fltk Version: %{version} Release: %{release} License: LGPL Group: System Environment/Libraries Source: https://www.fltk.org/pub/fltk/%{version}/fltk-%{version}-source.tar.gz URL: https://www.fltk.org/ Packager: FLTK Developer # use BuildRoot so as not to disturb the version already installed BuildRoot: /var/tmp/fltk-%{PACKAGE_VERSION} %description The Fast Light Tool Kit ("FLTK") is a cross-platform C++ GUI toolkit for UNIX(r)/Linux(r) (X11), Microsoft(r) Windows(r), and macOS(r). FLTK provides modern GUI functionality without bloat and supports 3D graphics via OpenGL(r) and its built-in GLUT emulation. %package devel Summary: FLTK Development Environment Group: Development/Libraries %description devel Install fltk-devel if you need to develop FLTK applications. You'll need to install the fltk package if you plan to run dynamically linked applications. %package games Summary: FLTK Games Group: Games %description games Install fltk-games to play Block Attack!, Checkers, or Sudoku on your computer. %prep %setup %build CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} --mandir=%{_mandir} --enable-largefile --enable-shared --enable-threads --enable-xft --enable-xinerama # If we got this far, all prerequisite libraries must be here. make %install # these lines just make sure the directory structure in the # RPM_BUILD_ROOT exists rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT make -e DESTDIR=$RPM_BUILD_ROOT install install-desktop %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %dir %{prefix}/lib %{prefix}/lib/libfltk*.so.* %files devel %defattr(-,root,root) %dir %{prefix}/bin %{prefix}/bin/fltk-config %{prefix}/bin/fltk-options %{prefix}/bin/fluid %dir %{prefix}/include/FL %{prefix}/include/FL/* %{prefix}/include/Fl %dir %{prefix}/lib %{prefix}/lib/libfltk*.so %{prefix}/lib/libfltk*.a %dir %{_mandir} %{_mandir}/cat1/* %{_mandir}/cat3/* %{_mandir}/man1/* %{_mandir}/man3/* %dir %{prefix}/share/doc/fltk %{prefix}/share/doc/fltk/* %dir %{prefix}/share/applications %{prefix}/share/applications/* %dir %{prefix}/share/icons %{prefix}/share/icons/hicolor/*/apps/fluid.png %dir %{prefix}/share/mimelnk %{prefix}/share/mimelnk/* %files games %dir %{prefix}/bin %{prefix}/bin/blocks %{prefix}/bin/checkers %{prefix}/bin/sudoku %dir %{_mandir} %{_mandir}/cat6/* %{_mandir}/man6/* %dir %{prefix}/share/applications %{prefix}/share/applications/* %dir %{prefix}/share/icons %{prefix}/share/icons/hicolor/*/apps/blocks.png %{prefix}/share/icons/hicolor/*/apps/checkers.png %{prefix}/share/icons/hicolor/*/apps/sudoku.png fltk-1.4.3/GL/0000755000175000017500000000000015004135251013107 5ustar albrechtalbrechtfltk-1.4.3/GL/glut.h0000644000175000017500000000077715004135251014246 0ustar albrechtalbrecht// // GLUT compatibility header for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include fltk-1.4.3/jpeg/0000755000175000017500000000000015004135251013532 5ustar albrechtalbrechtfltk-1.4.3/jpeg/jcparam.c0000644000175000017500000004723415004135251015325 0ustar albrechtalbrecht/* * jcparam.c * * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2003-2022 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains optional default-setting code for the JPEG compressor. * Applications do not have to use this file, but those that don't use it * must know a lot more about the innards of the JPEG code. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Quantization table setup routines */ GLOBAL(void) jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline) /* Define a quantization table equal to the basic_table times * a scale factor (given as a percentage). * If force_baseline is TRUE, the computed quantization table entries * are limited to 1..255 for JPEG baseline compatibility. */ { JQUANT_TBL ** qtblptr; int i; long temp; /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; if (*qtblptr == NULL) *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); for (i = 0; i < DCTSIZE2; i++) { temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; /* limit the values to the valid range */ if (temp <= 0L) temp = 1L; if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ if (force_baseline && temp > 255L) temp = 255L; /* limit to baseline range if requested */ (*qtblptr)->quantval[i] = (UINT16) temp; } /* Initialize sent_table FALSE so table will be written to JPEG file. */ (*qtblptr)->sent_table = FALSE; } /* These are the sample quantization tables given in JPEG spec section K.1. * NOTE: chrominance DC value is changed from 17 to 16 for lossless support. * The spec says that the values given produce "good" quality, * and when divided by 2, "very good" quality. */ static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99 }; static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { 16, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }; GLOBAL(void) jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline) /* Set or change the 'quality' (quantization) setting, using default tables * and straight percentage-scaling quality scales. * This entry point allows different scalings for luminance and chrominance. */ { /* Set up two quantization tables using the specified scaling */ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, cinfo->q_scale_factor[0], force_baseline); jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, cinfo->q_scale_factor[1], force_baseline); } GLOBAL(void) jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, boolean force_baseline) /* Set or change the 'quality' (quantization) setting, using default tables * and a straight percentage-scaling quality scale. In most cases it's better * to use jpeg_set_quality (below); this entry point is provided for * applications that insist on a linear percentage scaling. */ { /* Set up two quantization tables using the specified scaling */ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, scale_factor, force_baseline); jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, scale_factor, force_baseline); } GLOBAL(int) jpeg_quality_scaling (int quality) /* Convert a user-specified quality rating to a percentage scaling factor * for an underlying quantization table, using our recommended scaling curve. * The input 'quality' factor should be 0 (terrible) to 100 (very good). */ { /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ if (quality <= 0) quality = 1; if (quality > 100) quality = 100; /* The basic table is used as-is (scaling 100) for a quality of 50. * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table * to make all the table entries 1 (hence, minimum quantization loss). * Qualities 1..50 are converted to scaling percentage 5000/Q. */ if (quality < 50) quality = 5000 / quality; else quality = 200 - quality*2; return quality; } GLOBAL(void) jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) /* Set or change the 'quality' (quantization) setting, using default tables. * This is the standard quality-adjusting entry point for typical user * interfaces; only those who want detailed control over quantization tables * would use the preceding routines directly. */ { /* Convert user 0-100 rating to percentage scaling */ quality = jpeg_quality_scaling(quality); /* Set up standard quality tables */ jpeg_set_linear_quality(cinfo, quality, force_baseline); } /* * Reset standard Huffman tables */ LOCAL(void) std_huff_tables (j_compress_ptr cinfo) { if (cinfo->dc_huff_tbl_ptrs[0] != NULL) (void) jpeg_std_huff_table((j_common_ptr) cinfo, TRUE, 0); if (cinfo->ac_huff_tbl_ptrs[0] != NULL) (void) jpeg_std_huff_table((j_common_ptr) cinfo, FALSE, 0); if (cinfo->dc_huff_tbl_ptrs[1] != NULL) (void) jpeg_std_huff_table((j_common_ptr) cinfo, TRUE, 1); if (cinfo->ac_huff_tbl_ptrs[1] != NULL) (void) jpeg_std_huff_table((j_common_ptr) cinfo, FALSE, 1); } /* * Default parameter setup for compression. * * Applications that don't choose to use this routine must do their * own setup of all these parameters. Alternately, you can call this * to establish defaults and then alter parameters selectively. This * is the recommended approach since, if we add any new parameters, * your code will still work (they'll be set to reasonable defaults). */ GLOBAL(void) jpeg_set_defaults (j_compress_ptr cinfo) { int i; /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Allocate comp_info array large enough for maximum component count. * Array is made permanent in case application wants to compress * multiple images at same param settings. */ if (cinfo->comp_info == NULL) cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, MAX_COMPONENTS * SIZEOF(jpeg_component_info)); /* Initialize everything not dependent on the color space */ cinfo->scale_num = 1; /* 1:1 scaling */ cinfo->scale_denom = 1; cinfo->data_precision = BITS_IN_JSAMPLE; /* Set up two quantization tables using default quality of 75 */ jpeg_set_quality(cinfo, 75, TRUE); /* Reset standard Huffman tables */ std_huff_tables(cinfo); /* Initialize default arithmetic coding conditioning */ for (i = 0; i < NUM_ARITH_TBLS; i++) { cinfo->arith_dc_L[i] = 0; cinfo->arith_dc_U[i] = 1; cinfo->arith_ac_K[i] = 5; } /* Default is no multiple-scan output */ cinfo->scan_info = NULL; cinfo->num_scans = 0; /* Expect normal source image, not raw downsampled data */ cinfo->raw_data_in = FALSE; /* The standard Huffman tables are only valid for 8-bit data precision. * If the precision is higher, use arithmetic coding. * (Alternatively, using Huffman coding would be possible with forcing * optimization on so that usable tables will be computed, or by * supplying default tables that are valid for the desired precision.) * Otherwise, use Huffman coding by default. */ cinfo->arith_code = cinfo->data_precision > 8 ? TRUE : FALSE; /* By default, don't do extra passes to optimize entropy coding */ cinfo->optimize_coding = FALSE; /* By default, use the simpler non-cosited sampling alignment */ cinfo->CCIR601_sampling = FALSE; /* By default, apply fancy downsampling */ cinfo->do_fancy_downsampling = TRUE; /* No input smoothing */ cinfo->smoothing_factor = 0; /* DCT algorithm preference */ cinfo->dct_method = JDCT_DEFAULT; /* No restart markers */ cinfo->restart_interval = 0; cinfo->restart_in_rows = 0; /* Fill in default JFIF marker parameters. Note that whether the marker * will actually be written is determined by jpeg_set_colorspace. * * By default, the library emits JFIF version code 1.01. * An application that wants to emit JFIF 1.02 extension markers should set * JFIF_minor_version to 2. We could probably get away with just defaulting * to 1.02, but there may still be some decoders in use that will complain * about that; saying 1.01 should minimize compatibility problems. * * For wide gamut colorspaces (BG_RGB and BG_YCC), the major version will be * overridden by jpeg_set_colorspace and set to 2. */ cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ cinfo->JFIF_minor_version = 1; cinfo->density_unit = 0; /* Pixel size is unknown by default */ cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ cinfo->Y_density = 1; /* No color transform */ cinfo->color_transform = JCT_NONE; /* Choose JPEG colorspace based on input space, set defaults accordingly */ jpeg_default_colorspace(cinfo); } /* * Select an appropriate JPEG colorspace for in_color_space. */ GLOBAL(void) jpeg_default_colorspace (j_compress_ptr cinfo) { switch (cinfo->in_color_space) { case JCS_UNKNOWN: jpeg_set_colorspace(cinfo, JCS_UNKNOWN); break; case JCS_GRAYSCALE: jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); break; case JCS_RGB: jpeg_set_colorspace(cinfo, JCS_YCbCr); break; case JCS_YCbCr: jpeg_set_colorspace(cinfo, JCS_YCbCr); break; case JCS_CMYK: jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ break; case JCS_YCCK: jpeg_set_colorspace(cinfo, JCS_YCCK); break; case JCS_BG_RGB: /* No translation for now -- conversion to BG_YCC not yet supportet */ jpeg_set_colorspace(cinfo, JCS_BG_RGB); break; case JCS_BG_YCC: jpeg_set_colorspace(cinfo, JCS_BG_YCC); break; default: ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); } } /* * Set the JPEG colorspace, and choose colorspace-dependent default values. */ GLOBAL(void) jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) { jpeg_component_info * compptr; int ci; #define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ (compptr = &cinfo->comp_info[index], \ compptr->component_id = (id), \ compptr->h_samp_factor = (hsamp), \ compptr->v_samp_factor = (vsamp), \ compptr->quant_tbl_no = (quant), \ compptr->dc_tbl_no = (dctbl), \ compptr->ac_tbl_no = (actbl) ) /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* For all colorspaces, we use Q and Huff tables 0 for luminance components, * tables 1 for chrominance components. */ cinfo->jpeg_color_space = colorspace; cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ switch (colorspace) { case JCS_UNKNOWN: cinfo->num_components = cinfo->input_components; if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); for (ci = 0; ci < cinfo->num_components; ci++) { SET_COMP(ci, ci, 1,1, 0, 0,0); } break; case JCS_GRAYSCALE: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 1; /* JFIF specifies component ID 1 */ SET_COMP(0, 0x01, 1,1, 0, 0,0); break; case JCS_RGB: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ cinfo->num_components = 3; SET_COMP(0, 0x52 /* 'R' */, 1,1, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); SET_COMP(2, 0x42 /* 'B' */, 1,1, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); break; case JCS_YCbCr: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 3; /* JFIF specifies component IDs 1,2,3 */ /* We default to 2x2 subsamples of chrominance */ SET_COMP(0, 0x01, 2,2, 0, 0,0); SET_COMP(1, 0x02, 1,1, 1, 1,1); SET_COMP(2, 0x03, 1,1, 1, 1,1); break; case JCS_CMYK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ cinfo->num_components = 4; SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); break; case JCS_YCCK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ cinfo->num_components = 4; SET_COMP(0, 0x01, 2,2, 0, 0,0); SET_COMP(1, 0x02, 1,1, 1, 1,1); SET_COMP(2, 0x03, 1,1, 1, 1,1); SET_COMP(3, 0x04, 2,2, 0, 0,0); break; case JCS_BG_RGB: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->JFIF_major_version = 2; /* Set JFIF major version = 2 */ cinfo->num_components = 3; /* Add offset 0x20 to the normal R/G/B component IDs */ SET_COMP(0, 0x72 /* 'r' */, 1,1, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); SET_COMP(1, 0x67 /* 'g' */, 1,1, 0, 0,0); SET_COMP(2, 0x62 /* 'b' */, 1,1, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); break; case JCS_BG_YCC: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->JFIF_major_version = 2; /* Set JFIF major version = 2 */ cinfo->num_components = 3; /* Add offset 0x20 to the normal Cb/Cr component IDs */ /* We default to 2x2 subsamples of chrominance */ SET_COMP(0, 0x01, 2,2, 0, 0,0); SET_COMP(1, 0x22, 1,1, 1, 1,1); SET_COMP(2, 0x23, 1,1, 1, 1,1); break; default: ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); } } #ifdef C_PROGRESSIVE_SUPPORTED LOCAL(jpeg_scan_info *) fill_a_scan (jpeg_scan_info * scanptr, int ci, int Ss, int Se, int Ah, int Al) /* Support routine: generate one scan for specified component */ { scanptr->comps_in_scan = 1; scanptr->component_index[0] = ci; scanptr->Ss = Ss; scanptr->Se = Se; scanptr->Ah = Ah; scanptr->Al = Al; scanptr++; return scanptr; } LOCAL(jpeg_scan_info *) fill_scans (jpeg_scan_info * scanptr, int ncomps, int Ss, int Se, int Ah, int Al) /* Support routine: generate one scan for each component */ { int ci; for (ci = 0; ci < ncomps; ci++) { scanptr->comps_in_scan = 1; scanptr->component_index[0] = ci; scanptr->Ss = Ss; scanptr->Se = Se; scanptr->Ah = Ah; scanptr->Al = Al; scanptr++; } return scanptr; } LOCAL(jpeg_scan_info *) fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) /* Support routine: generate interleaved DC scan if possible, else N scans */ { int ci; if (ncomps <= MAX_COMPS_IN_SCAN) { /* Single interleaved DC scan */ scanptr->comps_in_scan = ncomps; for (ci = 0; ci < ncomps; ci++) scanptr->component_index[ci] = ci; scanptr->Ss = scanptr->Se = 0; scanptr->Ah = Ah; scanptr->Al = Al; scanptr++; } else { /* Noninterleaved DC scan for each component */ scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); } return scanptr; } /* * Create a recommended progressive-JPEG script. * cinfo->num_components and cinfo->jpeg_color_space must be correct. */ GLOBAL(void) jpeg_simple_progression (j_compress_ptr cinfo) { int ncomps = cinfo->num_components; int nscans; jpeg_scan_info * scanptr; /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Figure space needed for script. Calculation must match code below! */ if (ncomps == 3 && (cinfo->jpeg_color_space == JCS_YCbCr || cinfo->jpeg_color_space == JCS_BG_YCC)) { /* Custom script for YCC color images. */ nscans = 10; } else { /* All-purpose script for other color spaces. */ if (ncomps > MAX_COMPS_IN_SCAN) nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ else nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ } /* Allocate space for script. * We need to put it in the permanent pool in case the application performs * multiple compressions without changing the settings. To avoid a memory * leak if jpeg_simple_progression is called repeatedly for the same JPEG * object, we try to re-use previously allocated space, and we allocate * enough space to handle YCC even if initially asked for grayscale. */ if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { cinfo->script_space_size = MAX(nscans, 10); cinfo->script_space = (jpeg_scan_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, cinfo->script_space_size * SIZEOF(jpeg_scan_info)); } scanptr = cinfo->script_space; cinfo->scan_info = scanptr; cinfo->num_scans = nscans; if (ncomps == 3 && (cinfo->jpeg_color_space == JCS_YCbCr || cinfo->jpeg_color_space == JCS_BG_YCC)) { /* Custom script for YCC color images. */ /* Initial DC scan */ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); /* Initial AC scan: get some luma data out in a hurry */ scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); /* Chroma data is too small to be worth expending many scans on */ scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); /* Complete spectral selection for luma AC */ scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); /* Refine next bit of luma AC */ scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); /* Finish DC successive approximation */ scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); /* Finish AC successive approximation */ scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); /* Luma bottom bit comes last since it's usually largest scan */ scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); } else { /* All-purpose script for other color spaces. */ /* Successive approximation first pass */ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); /* Successive approximation second pass */ scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); /* Successive approximation final pass */ scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); } } #endif /* C_PROGRESSIVE_SUPPORTED */ fltk-1.4.3/jpeg/filelist.txt0000644000175000017500000002064515004135251016115 0ustar albrechtalbrechtIJG JPEG LIBRARY: FILE LIST Copyright (C) 1994-2020, Thomas G. Lane, Guido Vollbeding. This file is part of the Independent JPEG Group's software. For conditions of distribution and use, see the accompanying README file. Here is a road map to the files in the IJG JPEG distribution. The distribution includes the JPEG library proper, plus two application programs ("cjpeg" and "djpeg") which use the library to convert JPEG files to and from some other popular image formats. A third application "jpegtran" uses the library to do lossless conversion between different variants of JPEG. There are also two stand-alone applications, "rdjpgcom" and "wrjpgcom". THE JPEG LIBRARY ================ Include files: jpeglib.h JPEG library's exported data and function declarations. jconfig.h Configuration declarations. Note: this file is not present in the distribution; it is generated during installation. jmorecfg.h Additional configuration declarations; need not be changed for a standard installation. jerror.h Declares JPEG library's error and trace message codes. jinclude.h Central include file used by all IJG .c files to reference system include files. jpegint.h JPEG library's internal data structures. jdct.h Private declarations for forward & reverse DCT subsystems. jmemsys.h Private declarations for memory management subsystem. jversion.h Version information. Applications using the library should include jpeglib.h (which in turn includes jconfig.h and jmorecfg.h). Optionally, jerror.h may be included if the application needs to reference individual JPEG error codes. The other include files are intended for internal use and would not normally be included by an application program. (cjpeg/djpeg/etc do use jinclude.h, since its function is to improve portability of the whole IJG distribution. Most other applications will directly include the system include files they want, and hence won't need jinclude.h.) C source code files: These files contain most of the functions intended to be called directly by an application program: jcapimin.c Application program interface: core routines for compression. jcapistd.c Application program interface: standard compression. jdapimin.c Application program interface: core routines for decompression. jdapistd.c Application program interface: standard decompression. jcomapi.c Application program interface routines common to compression and decompression. jcparam.c Compression parameter setting helper routines. jctrans.c API and library routines for transcoding compression. jdtrans.c API and library routines for transcoding decompression. Compression side of the library: jcinit.c Initialization: determines which other modules to use. jcmaster.c Master control: setup and inter-pass sequencing logic. jcmainct.c Main buffer controller (preprocessor => JPEG compressor). jcprepct.c Preprocessor buffer controller. jccoefct.c Buffer controller for DCT coefficient buffer. jccolor.c Color space conversion. jcsample.c Downsampling. jcdctmgr.c DCT manager (DCT implementation selection & control). jfdctint.c Forward DCT using slow-but-accurate integer method. jfdctfst.c Forward DCT using faster, less accurate integer method. jfdctflt.c Forward DCT using floating-point arithmetic. jchuff.c Huffman entropy coding. jcarith.c Arithmetic entropy coding. jcmarker.c JPEG marker writing. jdatadst.c Data destination managers for memory and stdio output. Decompression side of the library: jdmaster.c Master control: determines which other modules to use. jdinput.c Input controller: controls input processing modules. jdmainct.c Main buffer controller (JPEG decompressor => postprocessor). jdcoefct.c Buffer controller for DCT coefficient buffer. jdpostct.c Postprocessor buffer controller. jdmarker.c JPEG marker reading. jdhuff.c Huffman entropy decoding. jdarith.c Arithmetic entropy decoding. jddctmgr.c IDCT manager (IDCT implementation selection & control). jidctint.c Inverse DCT using slow-but-accurate integer method. jidctfst.c Inverse DCT using faster, less accurate integer method. jidctflt.c Inverse DCT using floating-point arithmetic. jdsample.c Upsampling. jdcolor.c Color space conversion. jdmerge.c Merged upsampling/color conversion (faster, lower quality). jquant1.c One-pass color quantization using a fixed-spacing colormap. jquant2.c Two-pass color quantization using a custom-generated colormap. Also handles one-pass quantization to an externally given map. jdatasrc.c Data source managers for memory and stdio input. Support files for both compression and decompression: jaricom.c Tables for common use in arithmetic entropy encoding and decoding routines. jerror.c Standard error handling routines (application replaceable). jmemmgr.c System-independent (more or less) memory management code. jutils.c Miscellaneous utility routines. jmemmgr.c relies on a system-dependent memory management module. The IJG distribution includes the following implementations of the system-dependent module: jmemnobs.c "No backing store": assumes adequate virtual memory exists. jmemansi.c Makes temporary files with ANSI-standard routine tmpfile(). jmemname.c Makes temporary files with program-generated file names. jmemdos.c Custom implementation for MS-DOS (16-bit environment only): can use extended and expanded memory as well as temp files. jmemmac.c Custom implementation for Apple Macintosh. Exactly one of the system-dependent modules should be configured into an installed JPEG library (see install.txt for hints about which one to use). On unusual systems you may find it worthwhile to make a special system-dependent memory manager. Non-C source code files: jmemdosa.asm 80x86 assembly code support for jmemdos.c; used only in MS-DOS-specific configurations of the JPEG library. CJPEG/DJPEG/JPEGTRAN ==================== Include files: cdjpeg.h Declarations shared by cjpeg/djpeg/jpegtran modules. cderror.h Additional error and trace message codes for cjpeg et al. transupp.h Declarations for jpegtran support routines in transupp.c. C source code files: cjpeg.c Main program for cjpeg. cjpegalt.c Main program for cjpeg with alternate user interface. djpeg.c Main program for djpeg. djpegalt.c Main program for djpeg with alternate user interface. jpegtran.c Main program for jpegtran. cdjpeg.c Utility routines used by all three programs. rdcolmap.c Code to read a colormap file for djpeg's "-map" switch. rdswitch.c Code to process some of cjpeg's more complex switches. Also used by jpegtran. transupp.c Support code for jpegtran: lossless image manipulations. Image file reader modules for cjpeg: rdbmp.c BMP file input. rdgif.c GIF file input. rdppm.c PPM/PGM file input. rdrle.c Utah RLE file input. rdtarga.c Targa file input. Image file writer modules for djpeg: wrbmp.c BMP file output. wrgif.c GIF file output. wrppm.c PPM/PGM file output. wrrle.c Utah RLE file output. wrtarga.c Targa file output. RDJPGCOM/WRJPGCOM ================= C source code files: rdjpgcom.c Stand-alone rdjpgcom application. wrjpgcom.c Stand-alone wrjpgcom application. These programs do not depend on the IJG library. They do use jconfig.h and jinclude.h, only to improve portability. ADDITIONAL FILES ================ Documentation (see README for a guide to the documentation files): README Master documentation file. *.txt Other documentation files. *.1 Documentation in Unix man page format. change.log Version-to-version change highlights. example.c Sample code for calling JPEG library. Configuration/installation files and programs (see install.txt for more info): configure Unix shell script to perform automatic configuration. configure.ac Source file for use with Autoconf to generate configure. ltmain.sh Support scripts for configure (from GNU libtool). config.guess config.sub depcomp missing ar-lib compile install-sh Install shell script for those Unix systems lacking one. Makefile.in Makefile input for configure. Makefile.am Source file for use with Automake to generate Makefile.in. ckconfig.c Program to generate jconfig.h on non-Unix systems. jconfig.txt Template for making jconfig.h by hand. mak*.* Sample makefiles for particular systems. jconfig.* Sample jconfig.h for particular systems. libjpeg.map Script to generate shared library with versioned symbols. libjpeg.pc.in libjpeg.pc pkg-config file input for configure. aclocal.m4 M4 macro definitions for use with Autoconf. Test files (see install.txt for test procedure): test*.* Source and comparison files for confidence test. These are binary image files, NOT text files. fltk-1.4.3/jpeg/makedepend0000644000175000017500000001674115004135251015563 0ustar albrechtalbrecht# DO NOT DELETE THIS LINE -- make depend depends on it. jaricom.o: fltk_jpeg_prefix.h jaricom.o: jconfig.h jaricom.o: jerror.h jaricom.o: jinclude.h jaricom.o: jmorecfg.h jaricom.o: jpegint.h jaricom.o: jpeglib.h jcapimin.o: fltk_jpeg_prefix.h jcapimin.o: jconfig.h jcapimin.o: jerror.h jcapimin.o: jinclude.h jcapimin.o: jmorecfg.h jcapimin.o: jpegint.h jcapimin.o: jpeglib.h jcapistd.o: fltk_jpeg_prefix.h jcapistd.o: jconfig.h jcapistd.o: jerror.h jcapistd.o: jinclude.h jcapistd.o: jmorecfg.h jcapistd.o: jpegint.h jcapistd.o: jpeglib.h jcarith.o: fltk_jpeg_prefix.h jcarith.o: jconfig.h jcarith.o: jerror.h jcarith.o: jinclude.h jcarith.o: jmorecfg.h jcarith.o: jpegint.h jcarith.o: jpeglib.h jccoefct.o: fltk_jpeg_prefix.h jccoefct.o: jconfig.h jccoefct.o: jerror.h jccoefct.o: jinclude.h jccoefct.o: jmorecfg.h jccoefct.o: jpegint.h jccoefct.o: jpeglib.h jccolor.o: fltk_jpeg_prefix.h jccolor.o: jconfig.h jccolor.o: jerror.h jccolor.o: jinclude.h jccolor.o: jmorecfg.h jccolor.o: jpegint.h jccolor.o: jpeglib.h jcdctmgr.o: fltk_jpeg_prefix.h jcdctmgr.o: jconfig.h jcdctmgr.o: jdct.h jcdctmgr.o: jerror.h jcdctmgr.o: jinclude.h jcdctmgr.o: jmorecfg.h jcdctmgr.o: jpegint.h jcdctmgr.o: jpeglib.h jchuff.o: fltk_jpeg_prefix.h jchuff.o: jconfig.h jchuff.o: jerror.h jchuff.o: jinclude.h jchuff.o: jmorecfg.h jchuff.o: jpegint.h jchuff.o: jpeglib.h jcinit.o: fltk_jpeg_prefix.h jcinit.o: jconfig.h jcinit.o: jerror.h jcinit.o: jinclude.h jcinit.o: jmorecfg.h jcinit.o: jpegint.h jcinit.o: jpeglib.h jcmainct.o: fltk_jpeg_prefix.h jcmainct.o: jconfig.h jcmainct.o: jerror.h jcmainct.o: jinclude.h jcmainct.o: jmorecfg.h jcmainct.o: jpegint.h jcmainct.o: jpeglib.h jcmarker.o: fltk_jpeg_prefix.h jcmarker.o: jconfig.h jcmarker.o: jerror.h jcmarker.o: jinclude.h jcmarker.o: jmorecfg.h jcmarker.o: jpegint.h jcmarker.o: jpeglib.h jcmaster.o: fltk_jpeg_prefix.h jcmaster.o: jconfig.h jcmaster.o: jerror.h jcmaster.o: jinclude.h jcmaster.o: jmorecfg.h jcmaster.o: jpegint.h jcmaster.o: jpeglib.h jcomapi.o: fltk_jpeg_prefix.h jcomapi.o: jconfig.h jcomapi.o: jerror.h jcomapi.o: jinclude.h jcomapi.o: jmorecfg.h jcomapi.o: jpegint.h jcomapi.o: jpeglib.h jcparam.o: fltk_jpeg_prefix.h jcparam.o: jconfig.h jcparam.o: jerror.h jcparam.o: jinclude.h jcparam.o: jmorecfg.h jcparam.o: jpegint.h jcparam.o: jpeglib.h jcprepct.o: fltk_jpeg_prefix.h jcprepct.o: jconfig.h jcprepct.o: jerror.h jcprepct.o: jinclude.h jcprepct.o: jmorecfg.h jcprepct.o: jpegint.h jcprepct.o: jpeglib.h jcsample.o: fltk_jpeg_prefix.h jcsample.o: jconfig.h jcsample.o: jerror.h jcsample.o: jinclude.h jcsample.o: jmorecfg.h jcsample.o: jpegint.h jcsample.o: jpeglib.h jctrans.o: fltk_jpeg_prefix.h jctrans.o: jconfig.h jctrans.o: jerror.h jctrans.o: jinclude.h jctrans.o: jmorecfg.h jctrans.o: jpegint.h jctrans.o: jpeglib.h jdapimin.o: fltk_jpeg_prefix.h jdapimin.o: jconfig.h jdapimin.o: jerror.h jdapimin.o: jinclude.h jdapimin.o: jmorecfg.h jdapimin.o: jpegint.h jdapimin.o: jpeglib.h jdapistd.o: fltk_jpeg_prefix.h jdapistd.o: jconfig.h jdapistd.o: jerror.h jdapistd.o: jinclude.h jdapistd.o: jmorecfg.h jdapistd.o: jpegint.h jdapistd.o: jpeglib.h jdarith.o: fltk_jpeg_prefix.h jdarith.o: jconfig.h jdarith.o: jerror.h jdarith.o: jinclude.h jdarith.o: jmorecfg.h jdarith.o: jpegint.h jdarith.o: jpeglib.h jdatadst.o: fltk_jpeg_prefix.h jdatadst.o: jconfig.h jdatadst.o: jerror.h jdatadst.o: jinclude.h jdatadst.o: jmorecfg.h jdatadst.o: jpegint.h jdatadst.o: jpeglib.h jdatasrc.o: fltk_jpeg_prefix.h jdatasrc.o: jconfig.h jdatasrc.o: jerror.h jdatasrc.o: jinclude.h jdatasrc.o: jmorecfg.h jdatasrc.o: jpegint.h jdatasrc.o: jpeglib.h jdcoefct.o: fltk_jpeg_prefix.h jdcoefct.o: jconfig.h jdcoefct.o: jerror.h jdcoefct.o: jinclude.h jdcoefct.o: jmorecfg.h jdcoefct.o: jpegint.h jdcoefct.o: jpeglib.h jdcolor.o: fltk_jpeg_prefix.h jdcolor.o: jconfig.h jdcolor.o: jerror.h jdcolor.o: jinclude.h jdcolor.o: jmorecfg.h jdcolor.o: jpegint.h jdcolor.o: jpeglib.h jddctmgr.o: fltk_jpeg_prefix.h jddctmgr.o: jconfig.h jddctmgr.o: jdct.h jddctmgr.o: jerror.h jddctmgr.o: jinclude.h jddctmgr.o: jmorecfg.h jddctmgr.o: jpegint.h jddctmgr.o: jpeglib.h jdhuff.o: fltk_jpeg_prefix.h jdhuff.o: jconfig.h jdhuff.o: jerror.h jdhuff.o: jinclude.h jdhuff.o: jmorecfg.h jdhuff.o: jpegint.h jdhuff.o: jpeglib.h jdinput.o: fltk_jpeg_prefix.h jdinput.o: jconfig.h jdinput.o: jerror.h jdinput.o: jinclude.h jdinput.o: jmorecfg.h jdinput.o: jpegint.h jdinput.o: jpeglib.h jdmainct.o: fltk_jpeg_prefix.h jdmainct.o: jconfig.h jdmainct.o: jerror.h jdmainct.o: jinclude.h jdmainct.o: jmorecfg.h jdmainct.o: jpegint.h jdmainct.o: jpeglib.h jdmarker.o: fltk_jpeg_prefix.h jdmarker.o: jconfig.h jdmarker.o: jerror.h jdmarker.o: jinclude.h jdmarker.o: jmorecfg.h jdmarker.o: jpegint.h jdmarker.o: jpeglib.h jdmaster.o: fltk_jpeg_prefix.h jdmaster.o: jconfig.h jdmaster.o: jerror.h jdmaster.o: jinclude.h jdmaster.o: jmorecfg.h jdmaster.o: jpegint.h jdmaster.o: jpeglib.h jdmerge.o: fltk_jpeg_prefix.h jdmerge.o: jconfig.h jdmerge.o: jerror.h jdmerge.o: jinclude.h jdmerge.o: jmorecfg.h jdmerge.o: jpegint.h jdmerge.o: jpeglib.h jdpostct.o: fltk_jpeg_prefix.h jdpostct.o: jconfig.h jdpostct.o: jerror.h jdpostct.o: jinclude.h jdpostct.o: jmorecfg.h jdpostct.o: jpegint.h jdpostct.o: jpeglib.h jdsample.o: fltk_jpeg_prefix.h jdsample.o: jconfig.h jdsample.o: jerror.h jdsample.o: jinclude.h jdsample.o: jmorecfg.h jdsample.o: jpegint.h jdsample.o: jpeglib.h jdtrans.o: fltk_jpeg_prefix.h jdtrans.o: jconfig.h jdtrans.o: jerror.h jdtrans.o: jinclude.h jdtrans.o: jmorecfg.h jdtrans.o: jpegint.h jdtrans.o: jpeglib.h jerror.o: fltk_jpeg_prefix.h jerror.o: jconfig.h jerror.o: jerror.h jerror.o: jinclude.h jerror.o: jmorecfg.h jerror.o: jpegint.h jerror.o: jpeglib.h jerror.o: jversion.h jfdctflt.o: fltk_jpeg_prefix.h jfdctflt.o: jconfig.h jfdctflt.o: jdct.h jfdctflt.o: jerror.h jfdctflt.o: jinclude.h jfdctflt.o: jmorecfg.h jfdctflt.o: jpegint.h jfdctflt.o: jpeglib.h jfdctfst.o: fltk_jpeg_prefix.h jfdctfst.o: jconfig.h jfdctfst.o: jdct.h jfdctfst.o: jerror.h jfdctfst.o: jinclude.h jfdctfst.o: jmorecfg.h jfdctfst.o: jpegint.h jfdctfst.o: jpeglib.h jfdctint.o: fltk_jpeg_prefix.h jfdctint.o: jconfig.h jfdctint.o: jdct.h jfdctint.o: jerror.h jfdctint.o: jinclude.h jfdctint.o: jmorecfg.h jfdctint.o: jpegint.h jfdctint.o: jpeglib.h jidctflt.o: fltk_jpeg_prefix.h jidctflt.o: jconfig.h jidctflt.o: jdct.h jidctflt.o: jerror.h jidctflt.o: jinclude.h jidctflt.o: jmorecfg.h jidctflt.o: jpegint.h jidctflt.o: jpeglib.h jidctfst.o: fltk_jpeg_prefix.h jidctfst.o: jconfig.h jidctfst.o: jdct.h jidctfst.o: jerror.h jidctfst.o: jinclude.h jidctfst.o: jmorecfg.h jidctfst.o: jpegint.h jidctfst.o: jpeglib.h jidctint.o: fltk_jpeg_prefix.h jidctint.o: jconfig.h jidctint.o: jdct.h jidctint.o: jerror.h jidctint.o: jinclude.h jidctint.o: jmorecfg.h jidctint.o: jpegint.h jidctint.o: jpeglib.h jmemmgr.o: fltk_jpeg_prefix.h jmemmgr.o: jconfig.h jmemmgr.o: jerror.h jmemmgr.o: jinclude.h jmemmgr.o: jmemsys.h jmemmgr.o: jmorecfg.h jmemmgr.o: jpegint.h jmemmgr.o: jpeglib.h jmemnobs.o: fltk_jpeg_prefix.h jmemnobs.o: jconfig.h jmemnobs.o: jerror.h jmemnobs.o: jinclude.h jmemnobs.o: jmemsys.h jmemnobs.o: jmorecfg.h jmemnobs.o: jpegint.h jmemnobs.o: jpeglib.h jquant1.o: fltk_jpeg_prefix.h jquant1.o: jconfig.h jquant1.o: jerror.h jquant1.o: jinclude.h jquant1.o: jmorecfg.h jquant1.o: jpegint.h jquant1.o: jpeglib.h jquant2.o: fltk_jpeg_prefix.h jquant2.o: jconfig.h jquant2.o: jerror.h jquant2.o: jinclude.h jquant2.o: jmorecfg.h jquant2.o: jpegint.h jquant2.o: jpeglib.h jutils.o: fltk_jpeg_prefix.h jutils.o: jconfig.h jutils.o: jerror.h jutils.o: jinclude.h jutils.o: jmorecfg.h jutils.o: jpegint.h jutils.o: jpeglib.h fltk-1.4.3/jpeg/jdapistd.c0000644000175000017500000002226115004135251015503 0ustar albrechtalbrecht/* * jdapistd.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2002-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface code for the decompression half * of the JPEG library. These are the "standard" API routines that are * used in the normal full-decompression case. They are not used by a * transcoding-only application. Note that if an application links in * jpeg_start_decompress, it will end up linking in the entire decompressor. * We thus must separate this file from jdapimin.c to avoid linking the * whole decompression library into a transcoder. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Forward declarations */ LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); /* * Decompression initialization. * jpeg_read_header must be completed before calling this. * * If a multipass operating mode was selected, this will do all but the * last pass, and thus may take a great deal of time. * * Returns FALSE if suspended. The return value need be inspected only if * a suspending data source is used. */ GLOBAL(boolean) jpeg_start_decompress (j_decompress_ptr cinfo) { if (cinfo->global_state == DSTATE_READY) { /* First call: initialize master control, select active modules */ jinit_master_decompress(cinfo); if (cinfo->buffered_image) { /* No more work here; expecting jpeg_start_output next */ cinfo->global_state = DSTATE_BUFIMAGE; return TRUE; } cinfo->global_state = DSTATE_PRELOAD; } if (cinfo->global_state == DSTATE_PRELOAD) { /* If file has multiple scans, absorb them all into the coef buffer */ if (cinfo->inputctl->has_multiple_scans) { #ifdef D_MULTISCAN_FILES_SUPPORTED for (;;) { int retcode; /* Call progress monitor hook if present */ if (cinfo->progress != NULL) (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); /* Absorb some more input */ retcode = (*cinfo->inputctl->consume_input) (cinfo); if (retcode == JPEG_SUSPENDED) return FALSE; if (retcode == JPEG_REACHED_EOI) break; /* Advance progress counter if appropriate */ if (cinfo->progress != NULL && (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { /* jdmaster underestimated number of scans; ratchet up one scan */ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; } } } #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif /* D_MULTISCAN_FILES_SUPPORTED */ } cinfo->output_scan_number = cinfo->input_scan_number; } else if (cinfo->global_state != DSTATE_PRESCAN) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Perform any dummy output passes, and set up for the final pass */ return output_pass_setup(cinfo); } /* * Set up for an output pass, and perform any dummy pass(es) needed. * Common subroutine for jpeg_start_decompress and jpeg_start_output. * Entry: global_state = DSTATE_PRESCAN only if previously suspended. * Exit: If done, returns TRUE and sets global_state for proper output mode. * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. */ LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo) { if (cinfo->global_state != DSTATE_PRESCAN) { /* First call: do pass setup */ (*cinfo->master->prepare_for_output_pass) (cinfo); cinfo->output_scanline = 0; cinfo->global_state = DSTATE_PRESCAN; } /* Loop over any required dummy passes */ while (cinfo->master->is_dummy_pass) { #ifdef QUANT_2PASS_SUPPORTED /* Crank through the dummy pass */ while (cinfo->output_scanline < cinfo->output_height) { JDIMENSION last_scanline; /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->output_scanline; cinfo->progress->pass_limit = (long) cinfo->output_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Process some data */ last_scanline = cinfo->output_scanline; (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, &cinfo->output_scanline, (JDIMENSION) 0); if (cinfo->output_scanline == last_scanline) return FALSE; /* No progress made, must suspend */ } /* Finish up dummy pass, and set up for another one */ (*cinfo->master->finish_output_pass) (cinfo); (*cinfo->master->prepare_for_output_pass) (cinfo); cinfo->output_scanline = 0; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif /* QUANT_2PASS_SUPPORTED */ } /* Ready for application to drive output pass through * jpeg_read_scanlines or jpeg_read_raw_data. */ cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; return TRUE; } /* * Read some scanlines of data from the JPEG decompressor. * * The return value will be the number of lines actually read. * This may be less than the number requested in several cases, * including bottom of image, data source suspension, and operating * modes that emit multiple scanlines at a time. * * Note: we warn about excess calls to jpeg_read_scanlines() since * this likely signals an application programmer error. However, * an oversize buffer (max_lines > scanlines remaining) is not an error. */ GLOBAL(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines) { JDIMENSION row_ctr; if (cinfo->global_state != DSTATE_SCANNING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->output_scanline >= cinfo->output_height) { WARNMS(cinfo, JWRN_TOO_MUCH_DATA); return 0; } /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->output_scanline; cinfo->progress->pass_limit = (long) cinfo->output_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Process some data */ row_ctr = 0; (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); cinfo->output_scanline += row_ctr; return row_ctr; } /* * Alternate entry point to read raw data. * Processes exactly one iMCU row per call, unless suspended. */ GLOBAL(JDIMENSION) jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, JDIMENSION max_lines) { JDIMENSION lines_per_iMCU_row; if (cinfo->global_state != DSTATE_RAW_OK) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->output_scanline >= cinfo->output_height) { WARNMS(cinfo, JWRN_TOO_MUCH_DATA); return 0; } /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->output_scanline; cinfo->progress->pass_limit = (long) cinfo->output_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Verify that at least one iMCU row can be returned. */ lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size; if (max_lines < lines_per_iMCU_row) ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Decompress directly into user's buffer. */ if (! (*cinfo->coef->decompress_data) (cinfo, data)) return 0; /* suspension forced, can do nothing more */ /* OK, we processed one iMCU row. */ cinfo->output_scanline += lines_per_iMCU_row; return lines_per_iMCU_row; } /* Additional entry points for buffered-image mode. */ #ifdef D_MULTISCAN_FILES_SUPPORTED /* * Initialize for an output pass in buffered-image mode. */ GLOBAL(boolean) jpeg_start_output (j_decompress_ptr cinfo, int scan_number) { if (cinfo->global_state != DSTATE_BUFIMAGE && cinfo->global_state != DSTATE_PRESCAN) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Limit scan number to valid range */ if (scan_number <= 0) scan_number = 1; if (cinfo->inputctl->eoi_reached && scan_number > cinfo->input_scan_number) scan_number = cinfo->input_scan_number; cinfo->output_scan_number = scan_number; /* Perform any dummy output passes, and set up for the real pass */ return output_pass_setup(cinfo); } /* * Finish up after an output pass in buffered-image mode. * * Returns FALSE if suspended. The return value need be inspected only if * a suspending data source is used. */ GLOBAL(boolean) jpeg_finish_output (j_decompress_ptr cinfo) { if ((cinfo->global_state == DSTATE_SCANNING || cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { /* Terminate this pass. */ /* We do not require the whole pass to have been completed. */ (*cinfo->master->finish_output_pass) (cinfo); cinfo->global_state = DSTATE_BUFPOST; } else if (cinfo->global_state != DSTATE_BUFPOST) { /* BUFPOST = repeat call after a suspension, anything else is error */ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); } /* Read markers looking for SOS or EOI */ while (cinfo->input_scan_number <= cinfo->output_scan_number && ! cinfo->inputctl->eoi_reached) { if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) return FALSE; /* Suspend, come back later */ } cinfo->global_state = DSTATE_BUFIMAGE; return TRUE; } #endif /* D_MULTISCAN_FILES_SUPPORTED */ fltk-1.4.3/jpeg/change.log0000644000175000017500000004746415004135251015501 0ustar albrechtalbrechtCHANGE LOG for Independent JPEG Group's JPEG software Version 9f 14-Jan-2024 ----------------------- Add build system for C++Builder/RAD Studio. Add build system for Xcode (beside configure). Add ARM64EC (Emulation Compatible) platform support in the Visual Studio build. Version 9e 16-Jan-2022 ----------------------- Include alternate user interface files for cjpeg/djpeg. jcparam.c: change default chrominance DC quantization factor for lossless support. Note: Requires rebuild of test images. rdgif.c, cderror.h: add sanity check for GIF image dimensions. Thank to Casper Sun for cjpeg potential vulnerability report. Add ARM and ARM64 platform support in the Visual Studio build. Version 9d 12-Jan-2020 ----------------------- Optimize the optimal Huffman code table generation to produce slightly smaller files. Thank to John Korejwa for suggestion. Note: Requires rebuild of testimgp.jpg. Decoding Huffman: Use default tables if tables are not defined. Thank to Simone Azzalin for report (Motion JPEG), and to Martin Strunz for hint. Add sanity check in optimal Huffman code table generation. Thank to Adam Farley for suggestion. rdtarga.c: use read_byte(), with EOF check, instead of getc() in read_*_pixel(). Thank to Chijin Zhou for cjpeg potential vulnerability report. jmemnobs.c: respect the max_memory_to_use setting in jpeg_mem_available() computation. Thank to Sheng Shu and Dongdong She for djpeg potential vulnerability report. jdarith.c, jdhuff.c: avoid left shift of negative value compiler warning in decode_mcu_AC_refine(). Thank to Indu Bhagat for suggestion. Add x64 (64-bit) platform support, avoid compiler warnings. Thank to Jonathan Potter, Feiyun Wang, and Sheng Shu for suggestion. Adjust libjpeg version specification for pkg-config file. Thank to Chen Chen for suggestion. Restore GIF read and write support from libjpeg version 6a. Thank to Wolfgang Werner (W.W.) Heinz for suggestion. Improve consistency in raw (downsampled) image data processing mode. Thank to Zhongyuan Zhou for hint. Avoid out of bounds array read (AC derived table pointers) in start pass in jdhuff.c. Thank to Peng Li for report. Improve code sanity (jdhuff.c). Thank to Reza Mirzazade farkhani for reports. Add jpegtran -drop option; add options to the crop extension and wipe to fill the extra area with content from the source image region, instead of gray out. Version 9c 14-Jan-2018 ----------------------- jpegtran: add an option to the -wipe switch to fill the region with the average of adjacent blocks, instead of gray out. Thank to Caitlyn Feddock and Maddie Ziegler for inspiration. Make range extension bits adjustable (in jpegint.h). Thank to Robin Watts for suggestion. Provide macros for fflush() and ferror() in jinclude.h in order to facilitate adaption by applications using an own FILE class. Thank to Gerhard Huber for suggestion. Add libjpeg pkg-config file. Thank to Mark Lavi, Vincent Torri, Patrick McMunn, and Huw Davies for suggestion. Add sanity checks in cjpeg image reader modules. Thank to Bingchang, Liu for reports. Version 9b 17-Jan-2016 ----------------------- Improvements and optimizations in DCT and color calculations. Normalize range limit array composition and access pattern. Thank to Sia Furler and Maddie Ziegler for inspiration. Use merged upsample with scaled DCT sizes larger than 8. Thank to Taylor Hatala for inspiration. Check for excessive comment lengths in argument parsing in wrjpgcom.c. Thank to Julian Cohen for hint. Add makefile.b32 for use with Borland C++ 32-bit (bcc32). Thank to Joe Slater for contribution. Document 'f' specifier for jpegtran -crop specification. Thank to Michele Martone for suggestion. Use defined value from header instead of hardwired number in rdswitch.c. Thank to Robert Sprowson for hint. Version 9a 19-Jan-2014 ----------------------- Add support for wide gamut color spaces (JFIF version 2). Improve clarity and accuracy in color conversion modules. Note: Requires rebuild of test images. Extend the bit depth support to all values from 8 to 12 (BITS_IN_JSAMPLE configuration option in jmorecfg.h). jpegtran now supports N bits sample data precision with all N from 8 to 12 in a single instance. Thank to Roland Fassauer for inspiration. Try to resolve issues with new boolean type definition. Thank also to v4hn for suggestion. Enable option to use default Huffman tables for lossless compression (for hardware solution), and in this case improve lossless RGB compression with reversible color transform. Thank to Benny Alexandar for hint. Extend the entropy decoding structure, so that extraneous bytes between compressed scan data and following marker can be reported correctly. Thank to Nigel Tao for hint. Add jpegtran -wipe option and extension for -crop. Thank to Andrew Senior, David Clunie, and Josef Schmid for suggestion. Version 9 13-Jan-2013 ---------------------- Add cjpeg -rgb1 option to create an RGB JPEG file, and insert a simple reversible color transform into the processing which significantly improves the compression. The recommended command for lossless coding of RGB images is now cjpeg -rgb1 -block 1 -arithmetic. As said, this option improves the compression significantly, but the files are not compatible with JPEG decoders prior to IJG v9 due to the included color transform. The used color transform and marker signaling is compatible with other JPEG standards (e.g., JPEG-LS part 2). Remove the automatic de-ANSI-fication support (Automake 1.12). Thank also to Nitin A Kamble for suggestion. Add remark for jpeg_mem_dest() in jdatadst.c. Thank to Elie-Gregoire Khoury for the hint. Support files with invalid component identifiers (created by Adobe PDF). Thank to Robin Watts for the suggestion. Adapt full buffer case in jcmainct.c for use with scaled DCT. Thank to Sergii Biloshytskyi for the suggestion. Add type identifier for declaration of noreturn functions. Thank to Brett L. Moore for the suggestion. Correct argument type in format string, avoid compiler warnings. Thank to Vincent Torri for hint. Add missing #include directives in configuration checks, avoid configuration errors. Thank to John Spencer for the hint. Version 8d 15-Jan-2012 ----------------------- Add cjpeg -rgb option to create RGB JPEG files. Using this switch suppresses the conversion from RGB colorspace input to the default YCbCr JPEG colorspace. This feature allows true lossless JPEG coding of RGB color images. The recommended command for this purpose is currently cjpeg -rgb -block 1 -arithmetic. SmartScale capable decoder (introduced with IJG JPEG 8) required. Thank to Michael Koch for the initial suggestion. Add option to disable the region adjustment in the transupp crop code. Thank to Jeffrey Friedl for the suggestion. Thank to Richard Jones and Edd Dawson for various minor corrections. Thank to Akim Demaille for configure.ac cleanup. Version 8c 16-Jan-2011 ----------------------- Add option to compression library and cjpeg (-block N) to use different DCT block size. All N from 1 to 16 are possible. Default is 8 (baseline format). Larger values produce higher compression, smaller values produce higher quality. SmartScale capable decoder (introduced with IJG JPEG 8) required. Version 8b 16-May-2010 ----------------------- Repair problem in new memory source manager with corrupt JPEG data. Thank to Ted Campbell and Samuel Chun for the report. Repair problem in Makefile.am test target. Thank to anonymous user for the report. Support MinGW installation with automatic configure. Thank to Volker Grabsch for the suggestion. Version 8a 28-Feb-2010 ----------------------- Writing tables-only datastreams via jpeg_write_tables works again. Support 32-bit BMPs (RGB image with Alpha channel) for read in cjpeg. Thank to Brett Blackham for the suggestion. Improve accuracy in floating point IDCT calculation. Thank to Robert Hooke for the hint. Version 8 10-Jan-2010 ---------------------- jpegtran now supports the same -scale option as djpeg for "lossless" resize. An implementation of the JPEG SmartScale extension is required for this feature. A (draft) specification of the JPEG SmartScale extension is available as a contributed document at ITU and ISO. Revision 2 or later of the document is required (latest document version is Revision 3). The SmartScale extension will enable more features beside lossless resize in future implementations, as described in the document (new compression options). Add sanity check in BMP reader module to avoid cjpeg crash for empty input image (thank to Isaev Ildar of ISP RAS, Moscow, RU for reporting this error). Add data source and destination managers for read from and write to memory buffers. New API functions jpeg_mem_src and jpeg_mem_dest. Thank to Roberto Boni from Italy for the suggestion. Version 7 27-Jun-2009 ---------------------- New scaled DCTs implemented. djpeg now supports scalings N/8 with all N from 1 to 16. cjpeg now supports scalings 8/N with all N from 1 to 16. Scaled DCTs with size larger than 8 are now also used for resolving the common 2x2 chroma subsampling case without additional spatial resampling. Separate spatial resampling for those kind of files is now only necessary for N>8 scaling cases. Furthermore, separate scaled DCT functions are provided for direct resolving of the common asymmetric subsampling cases (2x1 and 1x2) without additional spatial resampling. cjpeg -quality option has been extended for support of separate quality settings for luminance and chrominance (or in general, for every provided quantization table slot). New API function jpeg_default_qtables() and q_scale_factor array in library. Added -nosmooth option to cjpeg, complementary to djpeg. New variable "do_fancy_downsampling" in library, complement to fancy upsampling. Fancy upsampling now uses direct DCT scaling with sizes larger than 8. The old method is not reversible and has been removed. Support arithmetic entropy encoding and decoding. Added files jaricom.c, jcarith.c, jdarith.c. Straighten the file structure: Removed files jidctred.c, jcphuff.c, jchuff.h, jdphuff.c, jdhuff.h. jpegtran has a new "lossless" cropping feature. Implement -perfect option in jpegtran, new API function jtransform_perfect_transform() in transupp. (DP 204_perfect.dpatch) Better error messages for jpegtran fopen failure. (DP 203_jpegtran_errmsg.dpatch) Fix byte order issue with 16bit PPM/PGM files in rdppm.c/wrppm.c: according to Netpbm, the de facto standard implementation of the PNM formats, the most significant byte is first. (DP 203_rdppm.dpatch) Add -raw option to rdjpgcom not to mangle the output. (DP 205_rdjpgcom_raw.dpatch) Make rdjpgcom locale aware. (DP 201_rdjpgcom_locale.dpatch) Add extern "C" to jpeglib.h. This avoids the need to put extern "C" { ... } around #include "jpeglib.h" in your C++ application. Defining the symbol DONT_USE_EXTERN_C in the configuration prevents this. (DP 202_jpeglib.h_c++.dpatch) Version 6b 27-Mar-1998 ----------------------- jpegtran has new features for lossless image transformations (rotation and flipping) as well as "lossless" reduction to grayscale. jpegtran now copies comments by default; it has a -copy switch to enable copying all APPn blocks as well, or to suppress comments. (Formerly it always suppressed comments and APPn blocks.) jpegtran now also preserves JFIF version and resolution information. New decompressor library feature: COM and APPn markers found in the input file can be saved in memory for later use by the application. (Before, you had to code this up yourself with a custom marker processor.) There is an unused field "void * client_data" now in compress and decompress parameter structs; this may be useful in some applications. JFIF version number information is now saved by the decoder and accepted by the encoder. jpegtran uses this to copy the source file's version number, to ensure "jpegtran -copy all" won't create bogus files that contain JFXX extensions but claim to be version 1.01. Applications that generate their own JFXX extension markers also (finally) have a supported way to cause the encoder to emit JFIF version number 1.02. djpeg's trace mode reports JFIF 1.02 thumbnail images as such, rather than as unknown APP0 markers. In -verbose mode, djpeg and rdjpgcom will try to print the contents of APP12 markers as text. Some digital cameras store useful text information in APP12 markers. Handling of truncated data streams is more robust: blocks beyond the one in which the error occurs will be output as uniform gray, or left unchanged if decoding a progressive JPEG. The appearance no longer depends on the Huffman tables being used. Huffman tables are checked for validity much more carefully than before. To avoid the Unisys LZW patent, djpeg's GIF output capability has been changed to produce "uncompressed GIFs", and cjpeg's GIF input capability has been removed altogether. We're not happy about it either, but there seems to be no good alternative. The configure script now supports building libjpeg as a shared library on many flavors of Unix (all the ones that GNU libtool knows how to build shared libraries for). Use "./configure --enable-shared" to try this out. New jconfig file and makefiles for Microsoft Visual C++ and Developer Studio. Also, a jconfig file and a build script for Metrowerks CodeWarrior on Apple Macintosh. makefile.dj has been updated for DJGPP v2, and there are miscellaneous other minor improvements in the makefiles. jmemmac.c now knows how to create temporary files following Mac System 7 conventions. djpeg's -map switch is now able to read raw-format PPM files reliably. cjpeg -progressive -restart no longer generates any unnecessary DRI markers. Multiple calls to jpeg_simple_progression for a single JPEG object no longer leak memory. Version 6a 7-Feb-96 -------------------- Library initialization sequence modified to detect version mismatches and struct field packing mismatches between library and calling application. This change requires applications to be recompiled, but does not require any application source code change. All routine declarations changed to the style "GLOBAL(type) name ...", that is, GLOBAL, LOCAL, METHODDEF, EXTERN are now macros taking the routine's return type as an argument. This makes it possible to add Microsoft-style linkage keywords to all the routines by changing just these macros. Note that any application code that was using these macros will have to be changed. DCT coefficient quantization tables are now stored in normal array order rather than zigzag order. Application code that calls jpeg_add_quant_table, or otherwise manipulates quantization tables directly, will need to be changed. If you need to make such code work with either older or newer versions of the library, a test like "#if JPEG_LIB_VERSION >= 61" is recommended. djpeg's trace capability now dumps DQT tables in natural order, not zigzag order. This allows the trace output to be made into a "-qtables" file more easily. New system-dependent memory manager module for use on Apple Macintosh. Fix bug in cjpeg's -smooth option: last one or two scanlines would be duplicates of the prior line unless the image height mod 16 was 1 or 2. Repair minor problems in VMS, BCC, MC6 makefiles. New configure script based on latest GNU Autoconf. Correct the list of include files needed by MetroWerks C for ccommand(). Numerous small documentation updates. Version 6 2-Aug-95 ------------------- Progressive JPEG support: library can read and write full progressive JPEG files. A "buffered image" mode supports incremental decoding for on-the-fly display of progressive images. Simply recompiling an existing IJG-v5-based decoder with v6 should allow it to read progressive files, though of course without any special progressive display. New "jpegtran" application performs lossless transcoding between different JPEG formats; primarily, it can be used to convert baseline to progressive JPEG and vice versa. In support of jpegtran, the library now allows lossless reading and writing of JPEG files as DCT coefficient arrays. This ability may be of use in other applications. Notes for programmers: * We changed jpeg_start_decompress() to be able to suspend; this makes all decoding modes available to suspending-input applications. However, existing applications that use suspending input will need to be changed to check the return value from jpeg_start_decompress(). You don't need to do anything if you don't use a suspending data source. * We changed the interface to the virtual array routines: access_virt_array routines now take a count of the number of rows to access this time. The last parameter to request_virt_array routines is now interpreted as the maximum number of rows that may be accessed at once, but not necessarily the height of every access. Version 5b 15-Mar-95 --------------------- Correct bugs with grayscale images having v_samp_factor > 1. jpeg_write_raw_data() now supports output suspension. Correct bugs in "configure" script for case of compiling in a directory other than the one containing the source files. Repair bug in jquant1.c: sometimes didn't use as many colors as it could. Borland C makefile and jconfig file work under either MS-DOS or OS/2. Miscellaneous improvements to documentation. Version 5a 7-Dec-94 -------------------- Changed color conversion roundoff behavior so that grayscale values are represented exactly. (This causes test image files to change.) Make ordered dither use 16x16 instead of 4x4 pattern for a small quality improvement. New configure script based on latest GNU Autoconf. Fix configure script to handle CFLAGS correctly. Rename *.auto files to *.cfg, so that configure script still works if file names have been truncated for DOS. Fix bug in rdbmp.c: didn't allow for extra data between header and image. Modify rdppm.c/wrppm.c to handle 2-byte raw PPM/PGM formats for 12-bit data. Fix several bugs in rdrle.c. NEED_SHORT_EXTERNAL_NAMES option was broken. Revise jerror.h/jerror.c for more flexibility in message table. Repair oversight in jmemname.c NO_MKTEMP case: file could be there but unreadable. Version 5 24-Sep-94 -------------------- Version 5 represents a nearly complete redesign and rewrite of the IJG software. Major user-visible changes include: * Automatic configuration simplifies installation for most Unix systems. * A range of speed vs. image quality tradeoffs are supported. This includes resizing of an image during decompression: scaling down by a factor of 1/2, 1/4, or 1/8 is handled very efficiently. * New programs rdjpgcom and wrjpgcom allow insertion and extraction of text comments in a JPEG file. The application programmer's interface to the library has changed completely. Notable improvements include: * We have eliminated the use of callback routines for handling the uncompressed image data. The application now sees the library as a set of routines that it calls to read or write image data on a scanline-by-scanline basis. * The application image data is represented in a conventional interleaved- pixel format, rather than as a separate array for each color channel. This can save a copying step in many programs. * The handling of compressed data has been cleaned up: the application can supply routines to source or sink the compressed data. It is possible to suspend processing on source/sink buffer overrun, although this is not supported in all operating modes. * All static state has been eliminated from the library, so that multiple instances of compression or decompression can be active concurrently. * JPEG abbreviated datastream formats are supported, ie, quantization and Huffman tables can be stored separately from the image data. * And not only that, but the documentation of the library has improved considerably! The last widely used release before the version 5 rewrite was version 4A of 18-Feb-93. Change logs before that point have been discarded, since they are not of much interest after the rewrite. fltk-1.4.3/jpeg/jmemmgr.c0000644000175000017500000012010515004135251015333 0ustar albrechtalbrecht/* * jmemmgr.c * * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2011-2019 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the JPEG system-independent memory management * routines. This code is usable across a wide variety of machines; most * of the system dependencies have been isolated in a separate file. * The major functions provided here are: * * pool-based allocation and freeing of memory; * * policy decisions about how to divide available memory among the * virtual arrays; * * control logic for swapping virtual arrays between main memory and * backing storage. * The separate system-dependent file provides the actual backing-storage * access code, and it contains the policy decision about how much total * main memory to use. * This file is system-dependent in the sense that some of its functions * are unnecessary in some systems. For example, if there is enough virtual * memory so that backing storage will never be used, much of the virtual * array control logic could be removed. (Of course, if you have that much * memory then you shouldn't care about a little bit of unused code...) */ #define JPEG_INTERNALS #define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ #include "jinclude.h" #include "jpeglib.h" #include "jmemsys.h" /* import the system-dependent declarations */ #ifndef NO_GETENV #ifndef HAVE_STDLIB_H /* should declare getenv() */ extern char * getenv JPP((const char * name)); #endif #endif /* * Some important notes: * The allocation routines provided here must never return NULL. * They should exit to error_exit if unsuccessful. * * It's not a good idea to try to merge the sarray and barray routines, * even though they are textually almost the same, because samples are * usually stored as bytes while coefficients are shorts or ints. Thus, * in machines where byte pointers have a different representation from * word pointers, the resulting machine code could not be the same. */ /* * Many machines require storage alignment: longs must start on 4-byte * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() * always returns pointers that are multiples of the worst-case alignment * requirement, and we had better do so too. * There isn't any really portable way to determine the worst-case alignment * requirement. This module assumes that the alignment requirement is * multiples of sizeof(ALIGN_TYPE). * By default, we define ALIGN_TYPE as double. This is necessary on some * workstations (where doubles really do need 8-byte alignment) and will work * fine on nearly everything. If your machine has lesser alignment needs, * you can save a few bytes by making ALIGN_TYPE smaller. * The only place I know of where this will NOT work is certain Macintosh * 680x0 compilers that define double as a 10-byte IEEE extended float. * Doing 10-byte alignment is counterproductive because longwords won't be * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have * such a compiler. */ #ifndef ALIGN_TYPE /* so can override from jconfig.h */ #define ALIGN_TYPE double #endif /* * We allocate objects from "pools", where each pool is gotten with a single * request to jpeg_get_small() or jpeg_get_large(). There is no per-object * overhead within a pool, except for alignment padding. Each pool has a * header with a link to the next pool of the same class. * Small and large pool headers are identical except that the latter's * link pointer must be FAR on 80x86 machines. * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple * of the alignment requirement of ALIGN_TYPE. */ typedef union small_pool_struct * small_pool_ptr; typedef union small_pool_struct { struct { small_pool_ptr next; /* next in list of pools */ size_t bytes_used; /* how many bytes already used within pool */ size_t bytes_left; /* bytes still available in this pool */ } hdr; ALIGN_TYPE dummy; /* included in union to ensure alignment */ } small_pool_hdr; typedef union large_pool_struct FAR * large_pool_ptr; typedef union large_pool_struct { struct { large_pool_ptr next; /* next in list of pools */ size_t bytes_used; /* how many bytes already used within pool */ size_t bytes_left; /* bytes still available in this pool */ } hdr; ALIGN_TYPE dummy; /* included in union to ensure alignment */ } large_pool_hdr; /* * Here is the full definition of a memory manager object. */ typedef struct { struct jpeg_memory_mgr pub; /* public fields */ /* Each pool identifier (lifetime class) names a linked list of pools. */ small_pool_ptr small_list[JPOOL_NUMPOOLS]; large_pool_ptr large_list[JPOOL_NUMPOOLS]; /* Since we only have one lifetime class of virtual arrays, only one * linked list is necessary (for each datatype). Note that the virtual * array control blocks being linked together are actually stored somewhere * in the small-pool list. */ jvirt_sarray_ptr virt_sarray_list; jvirt_barray_ptr virt_barray_list; /* This counts total space obtained from jpeg_get_small/large */ size_t total_space_allocated; /* alloc_sarray and alloc_barray set this value for use by virtual * array routines. */ JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ } my_memory_mgr; typedef my_memory_mgr * my_mem_ptr; /* * The control blocks for virtual arrays. * Note that these blocks are allocated in the "small" pool area. * System-dependent info for the associated backing store (if any) is hidden * inside the backing_store_info struct. */ struct jvirt_sarray_control { JSAMPARRAY mem_buffer; /* => the in-memory buffer */ JDIMENSION rows_in_array; /* total virtual array height */ JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ JDIMENSION rows_in_mem; /* height of memory buffer */ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ JDIMENSION cur_start_row; /* first logical row # in the buffer */ JDIMENSION first_undef_row; /* row # of first uninitialized row */ boolean pre_zero; /* pre-zero mode requested? */ boolean dirty; /* do current buffer contents need written? */ boolean b_s_open; /* is backing-store data valid? */ jvirt_sarray_ptr next; /* link to next virtual sarray control block */ backing_store_info b_s_info; /* System-dependent control info */ }; struct jvirt_barray_control { JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ JDIMENSION rows_in_array; /* total virtual array height */ JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ JDIMENSION rows_in_mem; /* height of memory buffer */ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ JDIMENSION cur_start_row; /* first logical row # in the buffer */ JDIMENSION first_undef_row; /* row # of first uninitialized row */ boolean pre_zero; /* pre-zero mode requested? */ boolean dirty; /* do current buffer contents need written? */ boolean b_s_open; /* is backing-store data valid? */ jvirt_barray_ptr next; /* link to next virtual barray control block */ backing_store_info b_s_info; /* System-dependent control info */ }; #ifdef MEM_STATS /* optional extra stuff for statistics */ LOCAL(void) print_mem_stats (j_common_ptr cinfo, int pool_id) { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; small_pool_ptr shdr_ptr; large_pool_ptr lhdr_ptr; /* Since this is only a debugging stub, we can cheat a little by using * fprintf directly rather than going through the trace message code. * This is helpful because message parm array can't handle longs. */ fprintf(stderr, "Freeing pool %d, total space = %ld\n", pool_id, (long) mem->total_space_allocated); for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; lhdr_ptr = lhdr_ptr->hdr.next) { fprintf(stderr, " Large chunk used %ld\n", (long) lhdr_ptr->hdr.bytes_used); } for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; shdr_ptr = shdr_ptr->hdr.next) { fprintf(stderr, " Small chunk used %ld free %ld\n", (long) shdr_ptr->hdr.bytes_used, (long) shdr_ptr->hdr.bytes_left); } } #endif /* MEM_STATS */ LOCAL(noreturn_t) out_of_memory (j_common_ptr cinfo, int which) /* Report an out-of-memory error and stop execution */ /* If we compiled MEM_STATS support, report alloc requests before dying */ { #ifdef MEM_STATS cinfo->err->trace_level = 2; /* force self_destruct to report stats */ #endif ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); } /* * Allocation of "small" objects. * * For these, we use pooled storage. When a new pool must be created, * we try to get enough space for the current request plus a "slop" factor, * where the slop will be the amount of leftover space in the new pool. * The speed vs. space tradeoff is largely determined by the slop values. * A different slop value is provided for each pool class (lifetime), * and we also distinguish the first pool of a class from later ones. * NOTE: the values given work fairly well on both 16- and 32-bit-int * machines, but may be too small if longs are 64 bits or more. */ static const size_t first_pool_slop[JPOOL_NUMPOOLS] = { 1600, /* first PERMANENT pool */ 16000 /* first IMAGE pool */ }; static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = { 0, /* additional PERMANENT pools */ 5000 /* additional IMAGE pools */ }; #define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ METHODDEF(void *) alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) /* Allocate a "small" object */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; small_pool_ptr hdr_ptr, prev_hdr_ptr; size_t odd_bytes, min_request, slop; char * data_ptr; /* Check for unsatisfiable request (do now to ensure no overflow below) */ if (sizeofobject > (size_t) MAX_ALLOC_CHUNK - SIZEOF(small_pool_hdr)) out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); if (odd_bytes > 0) sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; /* See if space is available in any existing pool */ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ prev_hdr_ptr = NULL; hdr_ptr = mem->small_list[pool_id]; while (hdr_ptr != NULL) { if (hdr_ptr->hdr.bytes_left >= sizeofobject) break; /* found pool with enough space */ prev_hdr_ptr = hdr_ptr; hdr_ptr = hdr_ptr->hdr.next; } /* Time to make a new pool? */ if (hdr_ptr == NULL) { /* min_request is what we need now, slop is what will be leftover */ min_request = sizeofobject + SIZEOF(small_pool_hdr); if (prev_hdr_ptr == NULL) /* first pool in class? */ slop = first_pool_slop[pool_id]; else slop = extra_pool_slop[pool_id]; /* Don't ask for more than MAX_ALLOC_CHUNK */ if (slop > (size_t) MAX_ALLOC_CHUNK - min_request) slop = (size_t) MAX_ALLOC_CHUNK - min_request; /* Try to get space, if fail reduce slop and try again */ for (;;) { hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); if (hdr_ptr != NULL) break; slop /= 2; if (slop < MIN_SLOP) /* give up when it gets real small */ out_of_memory(cinfo, 2); /* jpeg_get_small failed */ } mem->total_space_allocated += min_request + slop; /* Success, initialize the new pool header and add to end of list */ hdr_ptr->hdr.next = NULL; hdr_ptr->hdr.bytes_used = 0; hdr_ptr->hdr.bytes_left = sizeofobject + slop; if (prev_hdr_ptr == NULL) /* first pool in class? */ mem->small_list[pool_id] = hdr_ptr; else prev_hdr_ptr->hdr.next = hdr_ptr; } /* OK, allocate the object from the current pool */ data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ hdr_ptr->hdr.bytes_used += sizeofobject; hdr_ptr->hdr.bytes_left -= sizeofobject; return (void *) data_ptr; } /* * Allocation of "large" objects. * * The external semantics of these are the same as "small" objects, * except that FAR pointers are used on 80x86. However the pool * management heuristics are quite different. We assume that each * request is large enough that it may as well be passed directly to * jpeg_get_large; the pool management just links everything together * so that we can free it all on demand. * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY * structures. The routines that create these structures (see below) * deliberately bunch rows together to ensure a large request size. */ METHODDEF(void FAR *) alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) /* Allocate a "large" object */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; large_pool_ptr hdr_ptr; size_t odd_bytes; /* Check for unsatisfiable request (do now to ensure no overflow below) */ if (sizeofobject > (size_t) MAX_ALLOC_CHUNK - SIZEOF(large_pool_hdr)) out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); if (odd_bytes > 0) sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; /* Always make a new pool */ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + SIZEOF(large_pool_hdr)); if (hdr_ptr == NULL) out_of_memory(cinfo, 4); /* jpeg_get_large failed */ mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); /* Success, initialize the new pool header and add to list */ hdr_ptr->hdr.next = mem->large_list[pool_id]; /* We maintain space counts in each pool header for statistical purposes, * even though they are not needed for allocation. */ hdr_ptr->hdr.bytes_used = sizeofobject; hdr_ptr->hdr.bytes_left = 0; mem->large_list[pool_id] = hdr_ptr; return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ } /* * Creation of 2-D sample arrays. * The pointers are in near heap, the samples themselves in FAR heap. * * To minimize allocation overhead and to allow I/O of large contiguous * blocks, we allocate the sample rows in groups of as many rows as possible * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. * NB: the virtual array control routines, later in this file, know about * this chunking of rows. The rowsperchunk value is left in the mem manager * object so that it can be saved away if this sarray is the workspace for * a virtual array. */ METHODDEF(JSAMPARRAY) alloc_sarray (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows) /* Allocate a 2-D sample array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; JSAMPARRAY result; JSAMPROW workspace; JDIMENSION rowsperchunk, currow, i; long ltemp; /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK - SIZEOF(large_pool_hdr)) / ((long) samplesperrow * SIZEOF(JSAMPLE)); if (ltemp <= 0) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long) numrows) rowsperchunk = (JDIMENSION) ltemp; else rowsperchunk = numrows; mem->last_rowsperchunk = rowsperchunk; /* Get space for row pointers (small object) */ result = (JSAMPARRAY) alloc_small(cinfo, pool_id, (size_t) numrows * SIZEOF(JSAMPROW)); /* Get the rows themselves (large objects) */ currow = 0; while (currow < numrows) { rowsperchunk = MIN(rowsperchunk, numrows - currow); workspace = (JSAMPROW) alloc_large(cinfo, pool_id, (size_t) rowsperchunk * (size_t) samplesperrow * SIZEOF(JSAMPLE)); for (i = rowsperchunk; i > 0; i--) { result[currow++] = workspace; workspace += samplesperrow; } } return result; } /* * Creation of 2-D coefficient-block arrays. * This is essentially the same as the code for sample arrays, above. */ METHODDEF(JBLOCKARRAY) alloc_barray (j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow, JDIMENSION numrows) /* Allocate a 2-D coefficient-block array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; JBLOCKARRAY result; JBLOCKROW workspace; JDIMENSION rowsperchunk, currow, i; long ltemp; /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK - SIZEOF(large_pool_hdr)) / ((long) blocksperrow * SIZEOF(JBLOCK)); if (ltemp <= 0) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long) numrows) rowsperchunk = (JDIMENSION) ltemp; else rowsperchunk = numrows; mem->last_rowsperchunk = rowsperchunk; /* Get space for row pointers (small object) */ result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, (size_t) numrows * SIZEOF(JBLOCKROW)); /* Get the rows themselves (large objects) */ currow = 0; while (currow < numrows) { rowsperchunk = MIN(rowsperchunk, numrows - currow); workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, (size_t) rowsperchunk * (size_t) blocksperrow * SIZEOF(JBLOCK)); for (i = rowsperchunk; i > 0; i--) { result[currow++] = workspace; workspace += blocksperrow; } } return result; } /* * About virtual array management: * * The above "normal" array routines are only used to allocate strip buffers * (as wide as the image, but just a few rows high). Full-image-sized buffers * are handled as "virtual" arrays. The array is still accessed a strip at a * time, but the memory manager must save the whole array for repeated * accesses. The intended implementation is that there is a strip buffer in * memory (as high as is possible given the desired memory limit), plus a * backing file that holds the rest of the array. * * The request_virt_array routines are told the total size of the image and * the maximum number of rows that will be accessed at once. The in-memory * buffer must be at least as large as the maxaccess value. * * The request routines create control blocks but not the in-memory buffers. * That is postponed until realize_virt_arrays is called. At that time the * total amount of space needed is known (approximately, anyway), so free * memory can be divided up fairly. * * The access_virt_array routines are responsible for making a specific strip * area accessible (after reading or writing the backing file, if necessary). * Note that the access routines are told whether the caller intends to modify * the accessed strip; during a read-only pass this saves having to rewrite * data to disk. The access routines are also responsible for pre-zeroing * any newly accessed rows, if pre-zeroing was requested. * * In current usage, the access requests are usually for nonoverlapping * strips; that is, successive access start_row numbers differ by exactly * num_rows = maxaccess. This means we can get good performance with simple * buffer dump/reload logic, by making the in-memory buffer be a multiple * of the access height; then there will never be accesses across bufferload * boundaries. The code will still work with overlapping access requests, * but it doesn't handle bufferload overlaps very efficiently. */ METHODDEF(jvirt_sarray_ptr) request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, JDIMENSION samplesperrow, JDIMENSION numrows, JDIMENSION maxaccess) /* Request a virtual 2-D sample array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; jvirt_sarray_ptr result; /* Only IMAGE-lifetime virtual arrays are currently supported */ if (pool_id != JPOOL_IMAGE) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ /* get control block */ result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, SIZEOF(struct jvirt_sarray_control)); result->mem_buffer = NULL; /* marks array not yet realized */ result->rows_in_array = numrows; result->samplesperrow = samplesperrow; result->maxaccess = maxaccess; result->pre_zero = pre_zero; result->b_s_open = FALSE; /* no associated backing-store object */ result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ mem->virt_sarray_list = result; return result; } METHODDEF(jvirt_barray_ptr) request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION maxaccess) /* Request a virtual 2-D coefficient-block array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; jvirt_barray_ptr result; /* Only IMAGE-lifetime virtual arrays are currently supported */ if (pool_id != JPOOL_IMAGE) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ /* get control block */ result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, SIZEOF(struct jvirt_barray_control)); result->mem_buffer = NULL; /* marks array not yet realized */ result->rows_in_array = numrows; result->blocksperrow = blocksperrow; result->maxaccess = maxaccess; result->pre_zero = pre_zero; result->b_s_open = FALSE; /* no associated backing-store object */ result->next = mem->virt_barray_list; /* add to list of virtual arrays */ mem->virt_barray_list = result; return result; } METHODDEF(void) realize_virt_arrays (j_common_ptr cinfo) /* Allocate the in-memory buffers for any unrealized virtual arrays */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; long bytesperrow, space_per_minheight, maximum_space; long avail_mem, minheights, max_minheights; jvirt_sarray_ptr sptr; jvirt_barray_ptr bptr; /* Compute the minimum space needed (maxaccess rows in each buffer) * and the maximum space needed (full image height in each buffer). * These may be of use to the system-dependent jpeg_mem_available routine. */ space_per_minheight = 0; maximum_space = 0; for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->mem_buffer == NULL) { /* if not realized yet */ bytesperrow = (long) sptr->samplesperrow * SIZEOF(JSAMPLE); space_per_minheight += (long) sptr->maxaccess * bytesperrow; maximum_space += (long) sptr->rows_in_array * bytesperrow; } } for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->mem_buffer == NULL) { /* if not realized yet */ bytesperrow = (long) bptr->blocksperrow * SIZEOF(JBLOCK); space_per_minheight += (long) bptr->maxaccess * bytesperrow; maximum_space += (long) bptr->rows_in_array * bytesperrow; } } if (space_per_minheight <= 0) return; /* no unrealized arrays, no work */ /* Determine amount of memory to actually use; this is system-dependent. */ avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, (long) mem->total_space_allocated); /* If the maximum space needed is available, make all the buffers full * height; otherwise parcel it out with the same number of minheights * in each buffer. */ if (avail_mem >= maximum_space) max_minheights = 1000000000L; else { max_minheights = avail_mem / space_per_minheight; /* If there doesn't seem to be enough space, try to get the minimum * anyway. This allows a "stub" implementation of jpeg_mem_available(). */ if (max_minheights <= 0) max_minheights = 1; } /* Allocate the in-memory buffers and initialize backing store as needed. */ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->mem_buffer == NULL) { /* if not realized yet */ minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; if (minheights <= max_minheights) { /* This buffer fits in memory */ sptr->rows_in_mem = sptr->rows_in_array; } else { /* It doesn't fit in memory, create backing store. */ sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); jpeg_open_backing_store(cinfo, & sptr->b_s_info, (long) sptr->rows_in_array * (long) sptr->samplesperrow * (long) SIZEOF(JSAMPLE)); sptr->b_s_open = TRUE; } sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, sptr->samplesperrow, sptr->rows_in_mem); sptr->rowsperchunk = mem->last_rowsperchunk; sptr->cur_start_row = 0; sptr->first_undef_row = 0; sptr->dirty = FALSE; } } for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->mem_buffer == NULL) { /* if not realized yet */ minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; if (minheights <= max_minheights) { /* This buffer fits in memory */ bptr->rows_in_mem = bptr->rows_in_array; } else { /* It doesn't fit in memory, create backing store. */ bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); jpeg_open_backing_store(cinfo, & bptr->b_s_info, (long) bptr->rows_in_array * (long) bptr->blocksperrow * (long) SIZEOF(JBLOCK)); bptr->b_s_open = TRUE; } bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, bptr->blocksperrow, bptr->rows_in_mem); bptr->rowsperchunk = mem->last_rowsperchunk; bptr->cur_start_row = 0; bptr->first_undef_row = 0; bptr->dirty = FALSE; } } } LOCAL(void) do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) /* Do backing store read or write of a virtual sample array */ { long bytesperrow, file_offset, byte_count, rows, thisrow, i; bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); file_offset = (long) ptr->cur_start_row * bytesperrow; /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { /* One chunk, but check for short chunk at end of buffer */ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); /* Transfer no more than is currently defined */ thisrow = (long) ptr->cur_start_row + i; rows = MIN(rows, (long) ptr->first_undef_row - thisrow); /* Transfer no more than fits in file */ rows = MIN(rows, (long) ptr->rows_in_array - thisrow); if (rows <= 0) /* this chunk might be past end of file! */ break; byte_count = rows * bytesperrow; if (writing) (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); else (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); file_offset += byte_count; } } LOCAL(void) do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) /* Do backing store read or write of a virtual coefficient-block array */ { long bytesperrow, file_offset, byte_count, rows, thisrow, i; bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); file_offset = (long) ptr->cur_start_row * bytesperrow; /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { /* One chunk, but check for short chunk at end of buffer */ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); /* Transfer no more than is currently defined */ thisrow = (long) ptr->cur_start_row + i; rows = MIN(rows, (long) ptr->first_undef_row - thisrow); /* Transfer no more than fits in file */ rows = MIN(rows, (long) ptr->rows_in_array - thisrow); if (rows <= 0) /* this chunk might be past end of file! */ break; byte_count = rows * bytesperrow; if (writing) (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); else (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); file_offset += byte_count; } } METHODDEF(JSAMPARRAY) access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, JDIMENSION start_row, JDIMENSION num_rows, boolean writable) /* Access the part of a virtual sample array starting at start_row */ /* and extending for num_rows rows. writable is true if */ /* caller intends to modify the accessed area. */ { JDIMENSION end_row = start_row + num_rows; JDIMENSION undef_row; /* debugging check */ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || ptr->mem_buffer == NULL) ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); /* Make the desired part of the virtual array accessible */ if (start_row < ptr->cur_start_row || end_row > ptr->cur_start_row + ptr->rows_in_mem) { if (! ptr->b_s_open) ERREXIT(cinfo, JERR_VIRTUAL_BUG); /* Flush old buffer contents if necessary */ if (ptr->dirty) { do_sarray_io(cinfo, ptr, TRUE); ptr->dirty = FALSE; } /* Decide what part of virtual array to access. * Algorithm: if target address > current window, assume forward scan, * load starting at target address. If target address < current window, * assume backward scan, load so that target area is top of window. * Note that when switching from forward write to forward read, will have * start_row = 0, so the limiting case applies and we load from 0 anyway. */ if (start_row > ptr->cur_start_row) { ptr->cur_start_row = start_row; } else { /* use long arithmetic here to avoid overflow & unsigned problems */ long ltemp; ltemp = (long) end_row - (long) ptr->rows_in_mem; if (ltemp < 0) ltemp = 0; /* don't fall off front end of file */ ptr->cur_start_row = (JDIMENSION) ltemp; } /* Read in the selected part of the array. * During the initial write pass, we will do no actual read * because the selected part is all undefined. */ do_sarray_io(cinfo, ptr, FALSE); } /* Ensure the accessed part of the array is defined; prezero if needed. * To improve locality of access, we only prezero the part of the array * that the caller is about to access, not the entire in-memory array. */ if (ptr->first_undef_row < end_row) { if (ptr->first_undef_row < start_row) { if (writable) /* writer skipped over a section of array */ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); undef_row = start_row; /* but reader is allowed to read ahead */ } else { undef_row = ptr->first_undef_row; } if (writable) ptr->first_undef_row = end_row; if (ptr->pre_zero) { size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ end_row -= ptr->cur_start_row; while (undef_row < end_row) { FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); undef_row++; } } else { if (! writable) /* reader looking at undefined data */ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); } } /* Flag the buffer dirty if caller will write in it */ if (writable) ptr->dirty = TRUE; /* Return address of proper part of the buffer */ return ptr->mem_buffer + (start_row - ptr->cur_start_row); } METHODDEF(JBLOCKARRAY) access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, JDIMENSION start_row, JDIMENSION num_rows, boolean writable) /* Access the part of a virtual block array starting at start_row */ /* and extending for num_rows rows. writable is true if */ /* caller intends to modify the accessed area. */ { JDIMENSION end_row = start_row + num_rows; JDIMENSION undef_row; /* debugging check */ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || ptr->mem_buffer == NULL) ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); /* Make the desired part of the virtual array accessible */ if (start_row < ptr->cur_start_row || end_row > ptr->cur_start_row + ptr->rows_in_mem) { if (! ptr->b_s_open) ERREXIT(cinfo, JERR_VIRTUAL_BUG); /* Flush old buffer contents if necessary */ if (ptr->dirty) { do_barray_io(cinfo, ptr, TRUE); ptr->dirty = FALSE; } /* Decide what part of virtual array to access. * Algorithm: if target address > current window, assume forward scan, * load starting at target address. If target address < current window, * assume backward scan, load so that target area is top of window. * Note that when switching from forward write to forward read, will have * start_row = 0, so the limiting case applies and we load from 0 anyway. */ if (start_row > ptr->cur_start_row) { ptr->cur_start_row = start_row; } else { /* use long arithmetic here to avoid overflow & unsigned problems */ long ltemp; ltemp = (long) end_row - (long) ptr->rows_in_mem; if (ltemp < 0) ltemp = 0; /* don't fall off front end of file */ ptr->cur_start_row = (JDIMENSION) ltemp; } /* Read in the selected part of the array. * During the initial write pass, we will do no actual read * because the selected part is all undefined. */ do_barray_io(cinfo, ptr, FALSE); } /* Ensure the accessed part of the array is defined; prezero if needed. * To improve locality of access, we only prezero the part of the array * that the caller is about to access, not the entire in-memory array. */ if (ptr->first_undef_row < end_row) { if (ptr->first_undef_row < start_row) { if (writable) /* writer skipped over a section of array */ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); undef_row = start_row; /* but reader is allowed to read ahead */ } else { undef_row = ptr->first_undef_row; } if (writable) ptr->first_undef_row = end_row; if (ptr->pre_zero) { size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ end_row -= ptr->cur_start_row; while (undef_row < end_row) { FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); undef_row++; } } else { if (! writable) /* reader looking at undefined data */ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); } } /* Flag the buffer dirty if caller will write in it */ if (writable) ptr->dirty = TRUE; /* Return address of proper part of the buffer */ return ptr->mem_buffer + (start_row - ptr->cur_start_row); } /* * Release all objects belonging to a specified pool. */ METHODDEF(void) free_pool (j_common_ptr cinfo, int pool_id) { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; small_pool_ptr shdr_ptr; large_pool_ptr lhdr_ptr; size_t space_freed; if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ #ifdef MEM_STATS if (cinfo->err->trace_level > 1) print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ #endif /* If freeing IMAGE pool, close any virtual arrays first */ if (pool_id == JPOOL_IMAGE) { jvirt_sarray_ptr sptr; jvirt_barray_ptr bptr; for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->b_s_open) { /* there may be no backing store */ sptr->b_s_open = FALSE; /* prevent recursive close if error */ (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); } } mem->virt_sarray_list = NULL; for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->b_s_open) { /* there may be no backing store */ bptr->b_s_open = FALSE; /* prevent recursive close if error */ (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); } } mem->virt_barray_list = NULL; } /* Release large objects */ lhdr_ptr = mem->large_list[pool_id]; mem->large_list[pool_id] = NULL; while (lhdr_ptr != NULL) { large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; space_freed = lhdr_ptr->hdr.bytes_used + lhdr_ptr->hdr.bytes_left + SIZEOF(large_pool_hdr); jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); mem->total_space_allocated -= space_freed; lhdr_ptr = next_lhdr_ptr; } /* Release small objects */ shdr_ptr = mem->small_list[pool_id]; mem->small_list[pool_id] = NULL; while (shdr_ptr != NULL) { small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; space_freed = shdr_ptr->hdr.bytes_used + shdr_ptr->hdr.bytes_left + SIZEOF(small_pool_hdr); jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); mem->total_space_allocated -= space_freed; shdr_ptr = next_shdr_ptr; } } /* * Close up shop entirely. * Note that this cannot be called unless cinfo->mem is non-NULL. */ METHODDEF(void) self_destruct (j_common_ptr cinfo) { int pool; /* Close all backing store, release all memory. * Releasing pools in reverse order might help avoid fragmentation * with some (brain-damaged) malloc libraries. */ for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { free_pool(cinfo, pool); } /* Release the memory manager control block too. */ jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); cinfo->mem = NULL; /* ensures I will be called only once */ jpeg_mem_term(cinfo); /* system-dependent cleanup */ } /* * Memory manager initialization. * When this is called, only the error manager pointer is valid in cinfo! */ GLOBAL(void) jinit_memory_mgr (j_common_ptr cinfo) { my_mem_ptr mem; long max_to_use; int pool; size_t test_mac; cinfo->mem = NULL; /* for safety if init fails */ /* Check for configuration errors. * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably * doesn't reflect any real hardware alignment requirement. * The test is a little tricky: for X>0, X and X-1 have no one-bits * in common if and only if X is a power of 2, ie has only one one-bit. * Some compilers may give an "unreachable code" warning here; ignore it. */ if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be * a multiple of SIZEOF(ALIGN_TYPE). * Again, an "unreachable code" warning may be ignored here. * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. */ test_mac = (size_t) MAX_ALLOC_CHUNK; if ((long) test_mac != MAX_ALLOC_CHUNK || (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ /* Attempt to allocate memory manager's control block */ mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); if (mem == NULL) { jpeg_mem_term(cinfo); /* system-dependent cleanup */ ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); } /* OK, fill in the method pointers */ mem->pub.alloc_small = alloc_small; mem->pub.alloc_large = alloc_large; mem->pub.alloc_sarray = alloc_sarray; mem->pub.alloc_barray = alloc_barray; mem->pub.request_virt_sarray = request_virt_sarray; mem->pub.request_virt_barray = request_virt_barray; mem->pub.realize_virt_arrays = realize_virt_arrays; mem->pub.access_virt_sarray = access_virt_sarray; mem->pub.access_virt_barray = access_virt_barray; mem->pub.free_pool = free_pool; mem->pub.self_destruct = self_destruct; /* Make MAX_ALLOC_CHUNK accessible to other modules */ mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; /* Initialize working state */ mem->pub.max_memory_to_use = max_to_use; for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { mem->small_list[pool] = NULL; mem->large_list[pool] = NULL; } mem->virt_sarray_list = NULL; mem->virt_barray_list = NULL; mem->total_space_allocated = SIZEOF(my_memory_mgr); /* Declare ourselves open for business */ cinfo->mem = &mem->pub; /* Check for an environment variable JPEGMEM; if found, override the * default max_memory setting from jpeg_mem_init. Note that the * surrounding application may again override this value. * If your system doesn't support getenv(), define NO_GETENV to disable * this feature. */ #ifndef NO_GETENV { char * memenv; if ((memenv = getenv("JPEGMEM")) != NULL) { char ch = 'x'; if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { if (ch == 'm' || ch == 'M') max_to_use *= 1000L; mem->pub.max_memory_to_use = max_to_use * 1000L; } } } #endif } fltk-1.4.3/jpeg/jversion.h0000644000175000017500000000061415004135251015543 0ustar albrechtalbrecht/* * jversion.h * * Copyright (C) 1991-2024, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains software version identification. */ #define JVERSION "9f 14-Jan-2024" #define JCOPYRIGHT "Copyright (C) 2024, Thomas G. Lane, Guido Vollbeding" fltk-1.4.3/jpeg/jcomapi.c0000644000175000017500000001766215004135251015334 0ustar albrechtalbrecht/* * jcomapi.c * * Copyright (C) 1994-1997, Thomas G. Lane. * Modified 2019 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface routines that are used for both * compression and decompression. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Abort processing of a JPEG compression or decompression operation, * but don't destroy the object itself. * * For this, we merely clean up all the nonpermanent memory pools. * Note that temp files (virtual arrays) are not allowed to belong to * the permanent pool, so we will be able to close all temp files here. * Closing a data source or destination, if necessary, is the application's * responsibility. */ GLOBAL(void) jpeg_abort (j_common_ptr cinfo) { int pool; /* Do nothing if called on a not-initialized or destroyed JPEG object. */ if (cinfo->mem == NULL) return; /* Releasing pools in reverse order might help avoid fragmentation * with some (brain-damaged) malloc libraries. */ for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { (*cinfo->mem->free_pool) (cinfo, pool); } /* Reset overall state for possible reuse of object */ if (cinfo->is_decompressor) { cinfo->global_state = DSTATE_START; /* Try to keep application from accessing now-deleted marker list. * A bit kludgy to do it here, but this is the most central place. */ ((j_decompress_ptr) cinfo)->marker_list = NULL; } else { cinfo->global_state = CSTATE_START; } } /* * Destruction of a JPEG object. * * Everything gets deallocated except the master jpeg_compress_struct itself * and the error manager struct. Both of these are supplied by the application * and must be freed, if necessary, by the application. (Often they are on * the stack and so don't need to be freed anyway.) * Closing a data source or destination, if necessary, is the application's * responsibility. */ GLOBAL(void) jpeg_destroy (j_common_ptr cinfo) { /* We need only tell the memory manager to release everything. */ /* NB: mem pointer is NULL if memory mgr failed to initialize. */ if (cinfo->mem != NULL) (*cinfo->mem->self_destruct) (cinfo); cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ cinfo->global_state = 0; /* mark it destroyed */ } /* * Convenience routines for allocating quantization and Huffman tables. * (Would jutils.c be a more reasonable place to put these?) */ GLOBAL(JQUANT_TBL *) jpeg_alloc_quant_table (j_common_ptr cinfo) { JQUANT_TBL *tbl; tbl = (JQUANT_TBL *) (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); tbl->sent_table = FALSE; /* make sure this is false in any new table */ return tbl; } GLOBAL(JHUFF_TBL *) jpeg_alloc_huff_table (j_common_ptr cinfo) { JHUFF_TBL *tbl; tbl = (JHUFF_TBL *) (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); tbl->sent_table = FALSE; /* make sure this is false in any new table */ return tbl; } /* * Set up the standard Huffman tables (cf. JPEG standard section K.3). * IMPORTANT: these are only valid for 8-bit data precision! * (Would jutils.c be a more reasonable place to put this?) */ GLOBAL(JHUFF_TBL *) jpeg_std_huff_table (j_common_ptr cinfo, boolean isDC, int tblno) { JHUFF_TBL **htblptr, *htbl; const UINT8 *bits, *val; int nsymbols, len; static const UINT8 bits_dc_luminance[17] = { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_luminance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 bits_dc_chrominance[17] = { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_chrominance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 bits_ac_luminance[17] = { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; static const UINT8 val_ac_luminance[] = { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; static const UINT8 bits_ac_chrominance[17] = { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; static const UINT8 val_ac_chrominance[] = { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; if (cinfo->is_decompressor) { if (isDC) htblptr = ((j_decompress_ptr) cinfo)->dc_huff_tbl_ptrs; else htblptr = ((j_decompress_ptr) cinfo)->ac_huff_tbl_ptrs; } else { if (isDC) htblptr = ((j_compress_ptr) cinfo)->dc_huff_tbl_ptrs; else htblptr = ((j_compress_ptr) cinfo)->ac_huff_tbl_ptrs; } switch (tblno) { case 0: if (isDC) { bits = bits_dc_luminance; val = val_dc_luminance; } else { bits = bits_ac_luminance; val = val_ac_luminance; } break; case 1: if (isDC) { bits = bits_dc_chrominance; val = val_dc_chrominance; } else { bits = bits_ac_chrominance; val = val_ac_chrominance; } break; default: ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); return NULL; /* avoid compiler warnings for uninitialized variables */ } if (htblptr[tblno] == NULL) htblptr[tblno] = jpeg_alloc_huff_table(cinfo); htbl = htblptr[tblno]; /* Copy the number-of-symbols-of-each-code-length counts */ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); /* Validate the counts. We do this here mainly so we can copy the right * number of symbols from the val[] array, without risking marching off * the end of memory. jxhuff.c will do a more thorough test later. */ nsymbols = 0; for (len = 1; len <= 16; len++) nsymbols += bits[len]; if (nsymbols > 256) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); if (nsymbols > 0) MEMCOPY(htbl->huffval, val, nsymbols * SIZEOF(UINT8)); /* Initialize sent_table FALSE so table will be written to JPEG file. */ htbl->sent_table = FALSE; return htbl; } fltk-1.4.3/jpeg/jdapimin.c0000644000175000017500000003236215004135251015477 0ustar albrechtalbrecht/* * jdapimin.c * * Copyright (C) 1994-1998, Thomas G. Lane. * Modified 2009-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface code for the decompression half * of the JPEG library. These are the "minimum" API routines that may be * needed in either the normal full-decompression case or the * transcoding-only case. * * Most of the routines intended to be called directly by an application * are in this file or in jdapistd.c. But also see jcomapi.c for routines * shared by compression and decompression, and jdtrans.c for the transcoding * case. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Initialization of a JPEG decompression object. * The error manager must already be set up (in case memory manager fails). */ GLOBAL(void) jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) { int i; /* Guard against version mismatches between library and caller. */ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ if (version != JPEG_LIB_VERSION) ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); if (structsize != SIZEOF(struct jpeg_decompress_struct)) ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); /* For debugging purposes, we zero the whole master structure. * But the application has already set the err pointer, and may have set * client_data, so we have to save and restore those fields. * Note: if application hasn't set client_data, tools like Purify may * complain here. */ { struct jpeg_error_mgr * err = cinfo->err; void * client_data = cinfo->client_data; /* ignore Purify complaint here */ MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); cinfo->err = err; cinfo->client_data = client_data; } cinfo->is_decompressor = TRUE; /* Initialize a memory manager instance for this object */ jinit_memory_mgr((j_common_ptr) cinfo); /* Zero out pointers to permanent structures. */ cinfo->progress = NULL; cinfo->src = NULL; for (i = 0; i < NUM_QUANT_TBLS; i++) cinfo->quant_tbl_ptrs[i] = NULL; for (i = 0; i < NUM_HUFF_TBLS; i++) { cinfo->dc_huff_tbl_ptrs[i] = NULL; cinfo->ac_huff_tbl_ptrs[i] = NULL; } /* Initialize marker processor so application can override methods * for COM, APPn markers before calling jpeg_read_header. */ cinfo->marker_list = NULL; jinit_marker_reader(cinfo); /* And initialize the overall input controller. */ jinit_input_controller(cinfo); /* OK, I'm ready */ cinfo->global_state = DSTATE_START; } /* * Destruction of a JPEG decompression object */ GLOBAL(void) jpeg_destroy_decompress (j_decompress_ptr cinfo) { jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ } /* * Abort processing of a JPEG decompression operation, * but don't destroy the object itself. */ GLOBAL(void) jpeg_abort_decompress (j_decompress_ptr cinfo) { jpeg_abort((j_common_ptr) cinfo); /* use common routine */ } /* * Set default decompression parameters. */ LOCAL(void) default_decompress_parms (j_decompress_ptr cinfo) { int cid0, cid1, cid2, cid3; /* Guess the input colorspace, and set output colorspace accordingly. */ /* Note application may override our guesses. */ switch (cinfo->num_components) { case 1: cinfo->jpeg_color_space = JCS_GRAYSCALE; cinfo->out_color_space = JCS_GRAYSCALE; break; case 3: cid0 = cinfo->comp_info[0].component_id; cid1 = cinfo->comp_info[1].component_id; cid2 = cinfo->comp_info[2].component_id; /* For robust detection of standard colorspaces * regardless of the presence of special markers, * check component IDs from SOF marker first. */ if (cid0 == 0x01 && cid1 == 0x02 && cid2 == 0x03) cinfo->jpeg_color_space = JCS_YCbCr; else if (cid0 == 0x01 && cid1 == 0x22 && cid2 == 0x23) cinfo->jpeg_color_space = JCS_BG_YCC; else if (cid0 == 0x52 && cid1 == 0x47 && cid2 == 0x42) cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ else if (cid0 == 0x72 && cid1 == 0x67 && cid2 == 0x62) cinfo->jpeg_color_space = JCS_BG_RGB; /* ASCII 'r', 'g', 'b' */ else if (cinfo->saw_JFIF_marker) cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ else if (cinfo->saw_Adobe_marker) { switch (cinfo->Adobe_transform) { case 0: cinfo->jpeg_color_space = JCS_RGB; break; case 1: cinfo->jpeg_color_space = JCS_YCbCr; break; default: WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ } } else { TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ } /* Always guess RGB is proper output colorspace. */ cinfo->out_color_space = JCS_RGB; break; case 4: cid0 = cinfo->comp_info[0].component_id; cid1 = cinfo->comp_info[1].component_id; cid2 = cinfo->comp_info[2].component_id; cid3 = cinfo->comp_info[3].component_id; /* For robust detection of standard colorspaces * regardless of the presence of special markers, * check component IDs from SOF marker first. */ if (cid0 == 0x01 && cid1 == 0x02 && cid2 == 0x03 && cid3 == 0x04) cinfo->jpeg_color_space = JCS_YCCK; else if (cid0 == 0x43 && cid1 == 0x4D && cid2 == 0x59 && cid3 == 0x4B) cinfo->jpeg_color_space = JCS_CMYK; /* ASCII 'C', 'M', 'Y', 'K' */ else if (cinfo->saw_Adobe_marker) { switch (cinfo->Adobe_transform) { case 0: cinfo->jpeg_color_space = JCS_CMYK; break; case 2: cinfo->jpeg_color_space = JCS_YCCK; break; default: WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ } } else { /* Unknown IDs and no special markers, assume straight CMYK. */ cinfo->jpeg_color_space = JCS_CMYK; } cinfo->out_color_space = JCS_CMYK; break; default: cinfo->jpeg_color_space = JCS_UNKNOWN; cinfo->out_color_space = JCS_UNKNOWN; } /* Set defaults for other decompression parameters. */ cinfo->scale_num = cinfo->block_size; /* 1:1 scaling */ cinfo->scale_denom = cinfo->block_size; cinfo->output_gamma = 1.0; cinfo->buffered_image = FALSE; cinfo->raw_data_out = FALSE; cinfo->dct_method = JDCT_DEFAULT; cinfo->do_fancy_upsampling = TRUE; cinfo->do_block_smoothing = TRUE; cinfo->quantize_colors = FALSE; /* We set these in case application only sets quantize_colors. */ cinfo->dither_mode = JDITHER_FS; #ifdef QUANT_2PASS_SUPPORTED cinfo->two_pass_quantize = TRUE; #else cinfo->two_pass_quantize = FALSE; #endif cinfo->desired_number_of_colors = 256; cinfo->colormap = NULL; /* Initialize for no mode change in buffered-image mode. */ cinfo->enable_1pass_quant = FALSE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; } /* * Decompression startup: read start of JPEG datastream to see what's there. * Need only initialize JPEG object and supply a data source before calling. * * This routine will read as far as the first SOS marker (ie, actual start of * compressed data), and will save all tables and parameters in the JPEG * object. It will also initialize the decompression parameters to default * values, and finally return JPEG_HEADER_OK. On return, the application may * adjust the decompression parameters and then call jpeg_start_decompress. * (Or, if the application only wanted to determine the image parameters, * the data need not be decompressed. In that case, call jpeg_abort or * jpeg_destroy to release any temporary space.) * If an abbreviated (tables only) datastream is presented, the routine will * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then * re-use the JPEG object to read the abbreviated image datastream(s). * It is unnecessary (but OK) to call jpeg_abort in this case. * The JPEG_SUSPENDED return code only occurs if the data source module * requests suspension of the decompressor. In this case the application * should load more source data and then re-call jpeg_read_header to resume * processing. * If a non-suspending data source is used and require_image is TRUE, then the * return code need not be inspected since only JPEG_HEADER_OK is possible. * * This routine is now just a front end to jpeg_consume_input, with some * extra error checking. */ GLOBAL(int) jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) { int retcode; if (cinfo->global_state != DSTATE_START && cinfo->global_state != DSTATE_INHEADER) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); retcode = jpeg_consume_input(cinfo); switch (retcode) { case JPEG_REACHED_SOS: retcode = JPEG_HEADER_OK; break; case JPEG_REACHED_EOI: if (require_image) /* Complain if application wanted an image */ ERREXIT(cinfo, JERR_NO_IMAGE); /* Reset to start state; it would be safer to require the application to * call jpeg_abort, but we can't change it now for compatibility reasons. * A side effect is to free any temporary memory (there shouldn't be any). */ jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ retcode = JPEG_HEADER_TABLES_ONLY; break; case JPEG_SUSPENDED: /* no work */ break; } return retcode; } /* * Consume data in advance of what the decompressor requires. * This can be called at any time once the decompressor object has * been created and a data source has been set up. * * This routine is essentially a state machine that handles a couple * of critical state-transition actions, namely initial setup and * transition from header scanning to ready-for-start_decompress. * All the actual input is done via the input controller's consume_input * method. */ GLOBAL(int) jpeg_consume_input (j_decompress_ptr cinfo) { int retcode = JPEG_SUSPENDED; /* NB: every possible DSTATE value should be listed in this switch */ switch (cinfo->global_state) { case DSTATE_START: /* Start-of-datastream actions: reset appropriate modules */ (*cinfo->inputctl->reset_input_controller) (cinfo); /* Initialize application's data source module */ (*cinfo->src->init_source) (cinfo); cinfo->global_state = DSTATE_INHEADER; /*FALLTHROUGH*/ case DSTATE_INHEADER: retcode = (*cinfo->inputctl->consume_input) (cinfo); if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ /* Set up default parameters based on header data */ default_decompress_parms(cinfo); /* Set global state: ready for start_decompress */ cinfo->global_state = DSTATE_READY; } break; case DSTATE_READY: /* Can't advance past first SOS until start_decompress is called */ retcode = JPEG_REACHED_SOS; break; case DSTATE_PRELOAD: case DSTATE_PRESCAN: case DSTATE_SCANNING: case DSTATE_RAW_OK: case DSTATE_BUFIMAGE: case DSTATE_BUFPOST: case DSTATE_STOPPING: retcode = (*cinfo->inputctl->consume_input) (cinfo); break; default: ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); } return retcode; } /* * Have we finished reading the input file? */ GLOBAL(boolean) jpeg_input_complete (j_decompress_ptr cinfo) { /* Check for valid jpeg object */ if (cinfo->global_state < DSTATE_START || cinfo->global_state > DSTATE_STOPPING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); return cinfo->inputctl->eoi_reached; } /* * Is there more than one scan? */ GLOBAL(boolean) jpeg_has_multiple_scans (j_decompress_ptr cinfo) { /* Only valid after jpeg_read_header completes */ if (cinfo->global_state < DSTATE_READY || cinfo->global_state > DSTATE_STOPPING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); return cinfo->inputctl->has_multiple_scans; } /* * Finish JPEG decompression. * * This will normally just verify the file trailer and release temp storage. * * Returns FALSE if suspended. The return value need be inspected only if * a suspending data source is used. */ GLOBAL(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo) { if ((cinfo->global_state == DSTATE_SCANNING || cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { /* Terminate final pass of non-buffered mode */ if (cinfo->output_scanline < cinfo->output_height) ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); (*cinfo->master->finish_output_pass) (cinfo); cinfo->global_state = DSTATE_STOPPING; } else if (cinfo->global_state == DSTATE_BUFIMAGE) { /* Finishing after a buffered-image operation */ cinfo->global_state = DSTATE_STOPPING; } else if (cinfo->global_state != DSTATE_STOPPING) { /* STOPPING = repeat call after a suspension, anything else is error */ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); } /* Read until EOI */ while (! cinfo->inputctl->eoi_reached) { if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) return FALSE; /* Suspend, come back later */ } /* Do final cleanup */ (*cinfo->src->term_source) (cinfo); /* We can use jpeg_abort to release memory and reset global_state */ jpeg_abort((j_common_ptr) cinfo); return TRUE; } fltk-1.4.3/jpeg/jutils.c0000644000175000017500000001502515004135251015213 0ustar albrechtalbrecht/* * jutils.c * * Copyright (C) 1991-1996, Thomas G. Lane. * Modified 2009-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains tables and miscellaneous utility routines needed * for both compression and decompression. * Note we prefix all global names with "j" to minimize conflicts with * a surrounding application. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element * of a DCT block read in natural order (left to right, top to bottom). */ #if 0 /* This table is not actually needed in v6a */ const int jpeg_zigzag_order[DCTSIZE2] = { 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63 }; #endif /* * jpeg_natural_order[i] is the natural-order position of the i'th element * of zigzag order. * * When reading corrupted data, the Huffman decoders could attempt * to reference an entry beyond the end of this array (if the decoded * zero run length reaches past the end of the block). To prevent * wild stores without adding an inner-loop test, we put some extra * "63"s after the real entries. This will cause the extra coefficient * to be stored in location 63 of the block, not somewhere random. * The worst case would be a run-length of 15, which means we need 16 * fake entries. */ const int jpeg_natural_order[DCTSIZE2+16] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ 63, 63, 63, 63, 63, 63, 63, 63 }; const int jpeg_natural_order7[7*7+16] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 14, 21, 28, 35, 42, 49, 50, 43, 36, 29, 22, 30, 37, 44, 51, 52, 45, 38, 46, 53, 54, 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ 63, 63, 63, 63, 63, 63, 63, 63 }; const int jpeg_natural_order6[6*6+16] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 41, 34, 27, 20, 13, 21, 28, 35, 42, 43, 36, 29, 37, 44, 45, 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ 63, 63, 63, 63, 63, 63, 63, 63 }; const int jpeg_natural_order5[5*5+16] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 12, 19, 26, 33, 34, 27, 20, 28, 35, 36, 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ 63, 63, 63, 63, 63, 63, 63, 63 }; const int jpeg_natural_order4[4*4+16] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 25, 18, 11, 19, 26, 27, 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ 63, 63, 63, 63, 63, 63, 63, 63 }; const int jpeg_natural_order3[3*3+16] = { 0, 1, 8, 16, 9, 2, 10, 17, 18, 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ 63, 63, 63, 63, 63, 63, 63, 63 }; const int jpeg_natural_order2[2*2+16] = { 0, 1, 8, 9, 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ 63, 63, 63, 63, 63, 63, 63, 63 }; /* * Arithmetic utilities */ GLOBAL(long) jdiv_round_up (long a, long b) /* Compute a/b rounded up to next integer, ie, ceil(a/b) */ /* Assumes a >= 0, b > 0 */ { return (a + b - 1L) / b; } GLOBAL(long) jround_up (long a, long b) /* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ /* Assumes a >= 0, b > 0 */ { a += b - 1L; return a - (a % b); } /* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays * and coefficient-block arrays. This won't work on 80x86 because the arrays * are FAR and we're assuming a small-pointer memory model. However, some * DOS compilers provide far-pointer versions of memcpy() and memset() even * in the small-model libraries. These will be used if USE_FMEM is defined. * Otherwise, the routines below do it the hard way. (The performance cost * is not all that great, because these routines aren't very heavily used.) */ #ifndef NEED_FAR_POINTERS /* normal case, same as regular macro */ #define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) #else /* 80x86 case, define if we can */ #ifdef USE_FMEM #define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) #else /* This function is for use by the FMEMZERO macro defined in jpegint.h. * Do not call this function directly, use the FMEMZERO macro instead. */ GLOBAL(void) jzero_far (void FAR * target, size_t bytestozero) /* Zero out a chunk of FAR memory. */ /* This might be sample-array data, block-array data, or alloc_large data. */ { register char FAR * ptr = (char FAR *) target; register size_t count; for (count = bytestozero; count > 0; count--) { *ptr++ = 0; } } #endif #endif GLOBAL(void) jcopy_sample_rows (JSAMPARRAY input_array, JSAMPARRAY output_array, int num_rows, JDIMENSION num_cols) /* Copy some rows of samples from one place to another. * num_rows rows are copied from *input_array++ to *output_array++; * these areas may overlap for duplication. * The source and destination arrays must be at least as wide as num_cols. */ { register JSAMPROW inptr, outptr; #ifdef FMEMCOPY register size_t count = (size_t) num_cols * SIZEOF(JSAMPLE); #else register JDIMENSION count; #endif register int row; for (row = num_rows; row > 0; row--) { inptr = *input_array++; outptr = *output_array++; #ifdef FMEMCOPY FMEMCOPY(outptr, inptr, count); #else for (count = num_cols; count > 0; count--) *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ #endif } } GLOBAL(void) jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks) /* Copy a row of coefficient blocks from one place to another. */ { #ifdef FMEMCOPY FMEMCOPY(output_row, input_row, (size_t) num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); #else register JCOEFPTR inptr, outptr; register long count; inptr = (JCOEFPTR) input_row; outptr = (JCOEFPTR) output_row; for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { *outptr++ = *inptr++; } #endif } fltk-1.4.3/jpeg/jfdctint.c0000644000175000017500000046644515004135251015526 0ustar albrechtalbrecht/* * jfdctint.c * * Copyright (C) 1991-1996, Thomas G. Lane. * Modification developed 2003-2018 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a slow-but-accurate integer implementation of the * forward DCT (Discrete Cosine Transform). * * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT * on each column. Direct algorithms are also available, but they are * much more complex and seem not to be any faster when reduced to code. * * This implementation is based on an algorithm described in * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. * The primary algorithm described there uses 11 multiplies and 29 adds. * We use their alternate method with 12 multiplies and 32 adds. * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. * * We also provide FDCT routines with various input sample block sizes for * direct resolution reduction or enlargement and for direct resolving the * common 2x1 and 1x2 subsampling cases without additional resampling: NxN * (N=1...16), 2NxN, and Nx2N (N=1...8) pixels for one 8x8 output DCT block. * * For N<8 we fill the remaining block coefficients with zero. * For N>8 we apply a partial N-point FDCT on the input samples, computing * just the lower 8 frequency coefficients and discarding the rest. * * We must scale the output coefficients of the N-point FDCT appropriately * to the standard 8-point FDCT level by 8/N per 1-D pass. This scaling * is folded into the constant multipliers (pass 2) and/or final/initial * shifting. * * CAUTION: We rely on the FIX() macro except for the N=1,2,4,8 cases * since there would be too many additional constants to pre-calculate. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_ISLOW_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ #endif /* * The poop on this scaling stuff is as follows: * * Each 1-D DCT step produces outputs which are a factor of sqrt(N) * larger than the true DCT outputs. The final outputs are therefore * a factor of N larger than desired; since N=8 this can be cured by * a simple right shift at the end of the algorithm. The advantage of * this arrangement is that we save two multiplications per 1-D DCT, * because the y0 and y4 outputs need not be divided by sqrt(N). * In the IJG code, this factor of 8 is removed by the quantization step * (in jcdctmgr.c), NOT in this module. * * We have to do addition and subtraction of the integer inputs, which * is no problem, and multiplication by fractional constants, which is * a problem to do in integer arithmetic. We multiply all the constants * by CONST_SCALE and convert them to integer constants (thus retaining * CONST_BITS bits of precision in the constants). After doing a * multiplication we have to divide the product by CONST_SCALE, with proper * rounding, to produce the correct output. This division can be done * cheaply as a right shift of CONST_BITS bits. We postpone shifting * as long as possible so that partial sums can be added together with * full fractional precision. * * The outputs of the first pass are scaled up by PASS1_BITS bits so that * they are represented to better-than-integral precision. These outputs * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word * with the recommended scaling. (For 12-bit sample data, the intermediate * array is INT32 anyway.) * * To avoid overflow of the 32-bit intermediate results in pass 2, we must * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis * shows that the values given below are the most effective. */ #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 13 #define PASS1_BITS 2 #else #define CONST_BITS 13 #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 13 #define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ #define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ #define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ #define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ #define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ #define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ #define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ #define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ #define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ #define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ #define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ #define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ #else #define FIX_0_298631336 FIX(0.298631336) #define FIX_0_390180644 FIX(0.390180644) #define FIX_0_541196100 FIX(0.541196100) #define FIX_0_765366865 FIX(0.765366865) #define FIX_0_899976223 FIX(0.899976223) #define FIX_1_175875602 FIX(1.175875602) #define FIX_1_501321110 FIX(1.501321110) #define FIX_1_847759065 FIX(1.847759065) #define FIX_1_961570560 FIX(1.961570560) #define FIX_2_053119869 FIX(2.053119869) #define FIX_2_562915447 FIX(2.562915447) #define FIX_3_072711026 FIX(3.072711026) #endif /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * For 8-bit samples with the recommended scaling, all the variable * and constant values involved are no more than 16 bits wide, so a * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. * For 12-bit samples, a full 32-bit multiplication will be needed. */ #if BITS_IN_JSAMPLE == 8 #define MULTIPLY(var,const) MULTIPLY16C16(var,const) #else #define MULTIPLY(var,const) ((var) * (const)) #endif /* * Perform the forward DCT on one block of samples. */ GLOBAL(void) jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * cK represents sqrt(2) * cos(K*pi/16). */ dataptr = data; for (ctr = 0; ctr < DCTSIZE; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "c1" should be "c6". */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); tmp10 = tmp0 + tmp3; tmp12 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp13 = tmp1 - tmp2; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS); dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); dataptr[2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ CONST_BITS-PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * i0..i3 in the paper are tmp0..tmp3 here. */ tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp0 += z1 + tmp12; tmp3 += z1 + tmp13; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp1 += z1 + tmp13; tmp2 += z1 + tmp12; dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS-PASS1_BITS); dataptr[5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); dataptr[7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * cK represents sqrt(2) * cos(K*pi/16). */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "c1" should be "c6". */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; /* Add fudge factor here for final descale. */ tmp10 = tmp0 + tmp3 + (ONE << (PASS1_BITS-1)); tmp12 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp13 = tmp1 - tmp2; tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS+PASS1_BITS-1); dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ CONST_BITS+PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * i0..i3 in the paper are tmp0..tmp3 here. */ tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS+PASS1_BITS-1); tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp0 += z1 + tmp12; tmp3 += z1 + tmp13; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp1 += z1 + tmp13; tmp2 += z1 + tmp12; dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } #ifdef DCT_SCALING_SUPPORTED /* * Perform the forward DCT on a 7x7 sample block. */ GLOBAL(void) jpeg_fdct_7x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12; INT32 z1, z2, z3; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * cK represents sqrt(2) * cos(K*pi/14). */ dataptr = data; for (ctr = 0; ctr < 7; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[6]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[5]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[4]); tmp3 = GETJSAMPLE(elemptr[3]); tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[6]); tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[5]); tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]); z1 = tmp0 + tmp2; /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS); tmp3 += tmp3; z1 -= tmp3; z1 -= tmp3; z1 = MULTIPLY(z1, FIX(0.353553391)); /* (c2+c6-c4)/2 */ z2 = MULTIPLY(tmp0 - tmp2, FIX(0.920609002)); /* (c2+c4-c6)/2 */ z3 = MULTIPLY(tmp1 - tmp2, FIX(0.314692123)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS-PASS1_BITS); z1 -= z2; z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */ dataptr[4] = (DCTELEM) DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */ CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS); /* Odd part */ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(0.935414347)); /* (c3+c1-c5)/2 */ tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.170262339)); /* (c3+c5-c1)/2 */ tmp0 = tmp1 - tmp2; tmp1 += tmp2; tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.378756276)); /* -c1 */ tmp1 += tmp2; tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.613604268)); /* c5 */ tmp0 += tmp3; tmp2 += tmp3 + MULTIPLY(tmp12, FIX(1.870828693)); /* c3+c1-c5 */ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/7)**2 = 64/49, which we fold * into the constant multipliers: * cK now represents sqrt(2) * cos(K*pi/14) * 64/49. */ dataptr = data; for (ctr = 0; ctr < 7; ctr++) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*6]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*5]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*4]; tmp3 = dataptr[DCTSIZE*3]; tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*6]; tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*5]; tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*4]; z1 = tmp0 + tmp2; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */ CONST_BITS+PASS1_BITS); tmp3 += tmp3; z1 -= tmp3; z1 -= tmp3; z1 = MULTIPLY(z1, FIX(0.461784020)); /* (c2+c6-c4)/2 */ z2 = MULTIPLY(tmp0 - tmp2, FIX(1.202428084)); /* (c2+c4-c6)/2 */ z3 = MULTIPLY(tmp1 - tmp2, FIX(0.411026446)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS+PASS1_BITS); z1 -= z2; z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS); /* Odd part */ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.221765677)); /* (c3+c1-c5)/2 */ tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.222383464)); /* (c3+c5-c1)/2 */ tmp0 = tmp1 - tmp2; tmp1 += tmp2; tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.800824523)); /* -c1 */ tmp1 += tmp2; tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.801442310)); /* c5 */ tmp0 += tmp3; tmp2 += tmp3 + MULTIPLY(tmp12, FIX(2.443531355)); /* c3+c1-c5 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 6x6 sample block. */ GLOBAL(void) jpeg_fdct_6x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2; INT32 tmp10, tmp11, tmp12; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * cK represents sqrt(2) * cos(K*pi/12). */ dataptr = data; for (ctr = 0; ctr < 6; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); tmp10 = tmp0 + tmp2; tmp12 = tmp0 - tmp2; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS); dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ CONST_BITS-PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ CONST_BITS-PASS1_BITS); /* Odd part */ tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ CONST_BITS-PASS1_BITS); dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS)); dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS); dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << PASS1_BITS)); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/6)**2 = 16/9, which we fold * into the constant multipliers: * cK now represents sqrt(2) * cos(K*pi/12) * 16/9. */ dataptr = data; for (ctr = 0; ctr < 6; ctr++) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; tmp10 = tmp0 + tmp2; tmp12 = tmp0 - tmp2; tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ CONST_BITS+PASS1_BITS); /* Odd part */ tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 5x5 sample block. */ GLOBAL(void) jpeg_fdct_5x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2; INT32 tmp10, tmp11; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * We scale the results further by 2 as part of output adaption * scaling for different DCT size. * cK represents sqrt(2) * cos(K*pi/10). */ dataptr = data; for (ctr = 0; ctr < 5; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[4]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[3]); tmp2 = GETJSAMPLE(elemptr[2]); tmp10 = tmp0 + tmp1; tmp11 = tmp0 - tmp1; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << (PASS1_BITS+1)); tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */ tmp10 -= tmp2 << 2; tmp10 = MULTIPLY(tmp10, FIX(0.353553391)); /* (c2-c4)/2 */ dataptr[2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS-PASS1_BITS-1); dataptr[4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS-PASS1_BITS-1); /* Odd part */ tmp10 = MULTIPLY(tmp0 + tmp1, FIX(0.831253876)); /* c3 */ dataptr[1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */ CONST_BITS-PASS1_BITS-1); dataptr[3] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */ CONST_BITS-PASS1_BITS-1); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/5)**2 = 64/25, which we partially * fold into the constant multipliers (other part was done in pass 1): * cK now represents sqrt(2) * cos(K*pi/10) * 32/25. */ dataptr = data; for (ctr = 0; ctr < 5; ctr++) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*4]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*3]; tmp2 = dataptr[DCTSIZE*2]; tmp10 = tmp0 + tmp1; tmp11 = tmp0 - tmp1; tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*4]; tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*3]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */ CONST_BITS+PASS1_BITS); tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */ tmp10 -= tmp2 << 2; tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS+PASS1_BITS); /* Odd part */ tmp10 = MULTIPLY(tmp0 + tmp1, FIX(1.064004961)); /* c3 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */ CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 4x4 sample block. */ GLOBAL(void) jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1; INT32 tmp10, tmp11; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * We must also scale the output by (8/4)**2 = 2**2, which we add here. * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ dataptr = data; for (ctr = 0; ctr < 4; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+2)); dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+2)); /* Odd part */ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS-PASS1_BITS-3); dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ CONST_BITS-PASS1_BITS-2); dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ CONST_BITS-PASS1_BITS-2); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ dataptr = data; for (ctr = 0; ctr < 4; ctr++) { /* Even part */ /* Add fudge factor here for final descale. */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3] + (ONE << (PASS1_BITS-1)); tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS); /* Odd part */ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS+PASS1_BITS-1); dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 3x3 sample block. */ GLOBAL(void) jpeg_fdct_3x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * We scale the results further by 2**2 as part of output adaption * scaling for different DCT size. * cK represents sqrt(2) * cos(K*pi/6). */ dataptr = data; for (ctr = 0; ctr < 3; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[2]); tmp1 = GETJSAMPLE(elemptr[1]); tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+2)); dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */ CONST_BITS-PASS1_BITS-2); /* Odd part */ dataptr[1] = (DCTELEM) DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */ CONST_BITS-PASS1_BITS-2); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/3)**2 = 64/9, which we partially * fold into the constant multipliers (other part was done in pass 1): * cK now represents sqrt(2) * cos(K*pi/6) * 16/9. */ dataptr = data; for (ctr = 0; ctr < 3; ctr++) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*2]; tmp1 = dataptr[DCTSIZE*1]; tmp2 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*2]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */ CONST_BITS+PASS1_BITS); /* Odd part */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */ CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 2x2 sample block. */ GLOBAL(void) jpeg_fdct_2x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { DCTELEM tmp0, tmp1, tmp2, tmp3; JSAMPROW elemptr; /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT. */ /* Row 0 */ elemptr = sample_data[0] + start_col; tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[1]); tmp1 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[1]); /* Row 1 */ elemptr = sample_data[1] + start_col; tmp2 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[1]); tmp3 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[1]); /* Pass 2: process columns. * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/2)**2 = 2**4. */ /* Column 0 */ /* Apply unsigned->signed conversion. */ data[DCTSIZE*0] = (tmp0 + tmp2 - 4 * CENTERJSAMPLE) << 4; data[DCTSIZE*1] = (tmp0 - tmp2) << 4; /* Column 1 */ data[DCTSIZE*0+1] = (tmp1 + tmp3) << 4; data[DCTSIZE*1+1] = (tmp1 - tmp3) << 4; } /* * Perform the forward DCT on a 1x1 sample block. */ GLOBAL(void) jpeg_fdct_1x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { DCTELEM dcval; /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); dcval = GETJSAMPLE(sample_data[0][start_col]); /* We leave the result scaled up by an overall factor of 8. */ /* We must also scale the output by (8/1)**2 = 2**6. */ /* Apply unsigned->signed conversion. */ data[0] = (dcval - CENTERJSAMPLE) << 6; } /* * Perform the forward DCT on a 9x9 sample block. */ GLOBAL(void) jpeg_fdct_9x9 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1, z2; DCTELEM workspace[8]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * we scale the results further by 2 as part of output adaption * scaling for different DCT size. * cK represents sqrt(2) * cos(K*pi/18). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[8]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[7]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[6]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[5]); tmp4 = GETJSAMPLE(elemptr[4]); tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[8]); tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[7]); tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[6]); tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[5]); z1 = tmp0 + tmp2 + tmp3; z2 = tmp1 + tmp4; /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((z1 + z2 - 9 * CENTERJSAMPLE) << 1); dataptr[6] = (DCTELEM) DESCALE(MULTIPLY(z1 - z2 - z2, FIX(0.707106781)), /* c6 */ CONST_BITS-1); z1 = MULTIPLY(tmp0 - tmp2, FIX(1.328926049)); /* c2 */ z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(0.707106781)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.083350441)) /* c4 */ + z1 + z2, CONST_BITS-1); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.245575608)) /* c8 */ + z1 - z2, CONST_BITS-1); /* Odd part */ dataptr[3] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.224744871)), /* c3 */ CONST_BITS-1); tmp11 = MULTIPLY(tmp11, FIX(1.224744871)); /* c3 */ tmp0 = MULTIPLY(tmp10 + tmp12, FIX(0.909038955)); /* c5 */ tmp1 = MULTIPLY(tmp10 + tmp13, FIX(0.483689525)); /* c7 */ dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp0 + tmp1, CONST_BITS-1); tmp2 = MULTIPLY(tmp12 - tmp13, FIX(1.392728481)); /* c1 */ dataptr[5] = (DCTELEM) DESCALE(tmp0 - tmp11 - tmp2, CONST_BITS-1); dataptr[7] = (DCTELEM) DESCALE(tmp1 - tmp11 + tmp2, CONST_BITS-1); ctr++; if (ctr != DCTSIZE) { if (ctr == 9) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/9)**2 = 64/81, which we partially * fold into the constant multipliers and final/initial shifting: * cK now represents sqrt(2) * cos(K*pi/18) * 128/81. */ dataptr = data; wsptr = workspace; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*0]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*7]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*6]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*5]; tmp4 = dataptr[DCTSIZE*4]; tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*0]; tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*7]; tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*6]; tmp13 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*5]; z1 = tmp0 + tmp2 + tmp3; z2 = tmp1 + tmp4; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(z1 + z2, FIX(1.580246914)), /* 128/81 */ CONST_BITS+2); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(MULTIPLY(z1 - z2 - z2, FIX(1.117403309)), /* c6 */ CONST_BITS+2); z1 = MULTIPLY(tmp0 - tmp2, FIX(2.100031287)); /* c2 */ z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(1.117403309)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.711961190)) /* c4 */ + z1 + z2, CONST_BITS+2); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.388070096)) /* c8 */ + z1 - z2, CONST_BITS+2); /* Odd part */ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.935399303)), /* c3 */ CONST_BITS+2); tmp11 = MULTIPLY(tmp11, FIX(1.935399303)); /* c3 */ tmp0 = MULTIPLY(tmp10 + tmp12, FIX(1.436506004)); /* c5 */ tmp1 = MULTIPLY(tmp10 + tmp13, FIX(0.764348879)); /* c7 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp0 + tmp1, CONST_BITS+2); tmp2 = MULTIPLY(tmp12 - tmp13, FIX(2.200854883)); /* c1 */ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp0 - tmp11 - tmp2, CONST_BITS+2); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp1 - tmp11 + tmp2, CONST_BITS+2); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 10x10 sample block. */ GLOBAL(void) jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4; INT32 tmp10, tmp11, tmp12, tmp13, tmp14; DCTELEM workspace[8*2]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * we scale the results further by 2 as part of output adaption * scaling for different DCT size. * cK represents sqrt(2) * cos(K*pi/20). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[9]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[8]); tmp12 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[7]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[6]); tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[5]); tmp10 = tmp0 + tmp4; tmp13 = tmp0 - tmp4; tmp11 = tmp1 + tmp3; tmp14 = tmp1 - tmp3; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[9]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[8]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[7]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]); tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << 1); tmp12 += tmp12; dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */ MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ CONST_BITS-1); tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */ CONST_BITS-1); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */ CONST_BITS-1); /* Odd part */ tmp10 = tmp0 + tmp4; tmp11 = tmp1 - tmp3; dataptr[5] = (DCTELEM) ((tmp10 - tmp11 - tmp2) << 1); tmp2 <<= CONST_BITS; dataptr[1] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */ MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ CONST_BITS-1); tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */ MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */ (tmp11 << (CONST_BITS - 1)) - tmp2; dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-1); dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-1); ctr++; if (ctr != DCTSIZE) { if (ctr == 10) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/10)**2 = 16/25, which we partially * fold into the constant multipliers and final/initial shifting: * cK now represents sqrt(2) * cos(K*pi/20) * 32/25. */ dataptr = data; wsptr = workspace; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*1]; tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*0]; tmp12 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*7]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*6]; tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5]; tmp10 = tmp0 + tmp4; tmp13 = tmp0 - tmp4; tmp11 = tmp1 + tmp3; tmp14 = tmp1 - tmp3; tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*1]; tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*0]; tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*7]; tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*6]; tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */ CONST_BITS+2); tmp12 += tmp12; dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */ MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ CONST_BITS+2); tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */ CONST_BITS+2); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */ CONST_BITS+2); /* Odd part */ tmp10 = tmp0 + tmp4; tmp11 = tmp1 - tmp3; dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */ CONST_BITS+2); tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */ MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ CONST_BITS+2); tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */ MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */ MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+2); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+2); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on an 11x11 sample block. */ GLOBAL(void) jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; INT32 tmp10, tmp11, tmp12, tmp13, tmp14; INT32 z1, z2, z3; DCTELEM workspace[8*3]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * we scale the results further by 2 as part of output adaption * scaling for different DCT size. * cK represents sqrt(2) * cos(K*pi/22). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[10]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[9]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[8]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[7]); tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[6]); tmp5 = GETJSAMPLE(elemptr[5]); tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[10]); tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[9]); tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[8]); tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[7]); tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[6]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 - 11 * CENTERJSAMPLE) << 1); tmp5 += tmp5; tmp0 -= tmp5; tmp1 -= tmp5; tmp2 -= tmp5; tmp3 -= tmp5; tmp4 -= tmp5; z1 = MULTIPLY(tmp0 + tmp3, FIX(1.356927976)) + /* c2 */ MULTIPLY(tmp2 + tmp4, FIX(0.201263574)); /* c10 */ z2 = MULTIPLY(tmp1 - tmp3, FIX(0.926112931)); /* c6 */ z3 = MULTIPLY(tmp0 - tmp1, FIX(1.189712156)); /* c4 */ dataptr[2] = (DCTELEM) DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.018300590)) /* c2+c8-c6 */ - MULTIPLY(tmp4, FIX(1.390975730)), /* c4+c10 */ CONST_BITS-1); dataptr[4] = (DCTELEM) DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.062335650)) /* c4-c6-c10 */ - MULTIPLY(tmp2, FIX(1.356927976)) /* c2 */ + MULTIPLY(tmp4, FIX(0.587485545)), /* c8 */ CONST_BITS-1); dataptr[6] = (DCTELEM) DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.620527200)) /* c2+c4-c6 */ - MULTIPLY(tmp2, FIX(0.788749120)), /* c8+c10 */ CONST_BITS-1); /* Odd part */ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.286413905)); /* c3 */ tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.068791298)); /* c5 */ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.764581576)); /* c7 */ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.719967871)) /* c7+c5+c3-c1 */ + MULTIPLY(tmp14, FIX(0.398430003)); /* c9 */ tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.764581576)); /* -c7 */ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.399818907)); /* -c1 */ tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.276416582)) /* c9+c7+c1-c3 */ - MULTIPLY(tmp14, FIX(1.068791298)); /* c5 */ tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.398430003)); /* c9 */ tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(1.989053629)) /* c9+c5+c3-c7 */ + MULTIPLY(tmp14, FIX(1.399818907)); /* c1 */ tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.305598626)) /* c1+c5-c9-c7 */ - MULTIPLY(tmp14, FIX(1.286413905)); /* c3 */ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-1); dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-1); dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-1); dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS-1); ctr++; if (ctr != DCTSIZE) { if (ctr == 11) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/11)**2 = 64/121, which we partially * fold into the constant multipliers and final/initial shifting: * cK now represents sqrt(2) * cos(K*pi/22) * 128/121. */ dataptr = data; wsptr = workspace; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*2]; tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*1]; tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*0]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*7]; tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*6]; tmp5 = dataptr[DCTSIZE*5]; tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*2]; tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*1]; tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*0]; tmp13 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*7]; tmp14 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*6]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5, FIX(1.057851240)), /* 128/121 */ CONST_BITS+2); tmp5 += tmp5; tmp0 -= tmp5; tmp1 -= tmp5; tmp2 -= tmp5; tmp3 -= tmp5; tmp4 -= tmp5; z1 = MULTIPLY(tmp0 + tmp3, FIX(1.435427942)) + /* c2 */ MULTIPLY(tmp2 + tmp4, FIX(0.212906922)); /* c10 */ z2 = MULTIPLY(tmp1 - tmp3, FIX(0.979689713)); /* c6 */ z3 = MULTIPLY(tmp0 - tmp1, FIX(1.258538479)); /* c4 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.077210542)) /* c2+c8-c6 */ - MULTIPLY(tmp4, FIX(1.471445400)), /* c4+c10 */ CONST_BITS+2); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.065941844)) /* c4-c6-c10 */ - MULTIPLY(tmp2, FIX(1.435427942)) /* c2 */ + MULTIPLY(tmp4, FIX(0.621472312)), /* c8 */ CONST_BITS+2); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.714276708)) /* c2+c4-c6 */ - MULTIPLY(tmp2, FIX(0.834379234)), /* c8+c10 */ CONST_BITS+2); /* Odd part */ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.360834544)); /* c3 */ tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.130622199)); /* c5 */ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.808813568)); /* c7 */ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.819470145)) /* c7+c5+c3-c1 */ + MULTIPLY(tmp14, FIX(0.421479672)); /* c9 */ tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.808813568)); /* -c7 */ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.480800167)); /* -c1 */ tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.350258864)) /* c9+c7+c1-c3 */ - MULTIPLY(tmp14, FIX(1.130622199)); /* c5 */ tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.421479672)); /* c9 */ tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(2.104122847)) /* c9+c5+c3-c7 */ + MULTIPLY(tmp14, FIX(1.480800167)); /* c1 */ tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.381129125)) /* c1+c5-c9-c7 */ - MULTIPLY(tmp14, FIX(1.360834544)); /* c3 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+2); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+2); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 12x12 sample block. */ GLOBAL(void) jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; DCTELEM workspace[8*4]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT. * cK represents sqrt(2) * cos(K*pi/24). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[11]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[10]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[9]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[8]); tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[7]); tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[6]); tmp10 = tmp0 + tmp5; tmp13 = tmp0 - tmp5; tmp11 = tmp1 + tmp4; tmp14 = tmp1 - tmp4; tmp12 = tmp2 + tmp3; tmp15 = tmp2 - tmp3; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[11]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[10]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[9]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[8]); tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]); tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) (tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE); dataptr[6] = (DCTELEM) (tmp13 - tmp14 - tmp15); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */ CONST_BITS); dataptr[2] = (DCTELEM) DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */ CONST_BITS); /* Odd part */ tmp10 = MULTIPLY(tmp1 + tmp4, FIX_0_541196100); /* c9 */ tmp14 = tmp10 + MULTIPLY(tmp1, FIX_0_765366865); /* c3-c9 */ tmp15 = tmp10 - MULTIPLY(tmp4, FIX_1_847759065); /* c3+c9 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */ + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */ + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */ - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */ - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS); dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS); ctr++; if (ctr != DCTSIZE) { if (ctr == 12) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/12)**2 = 4/9, which we partially * fold into the constant multipliers and final shifting: * cK now represents sqrt(2) * cos(K*pi/24) * 8/9. */ dataptr = data; wsptr = workspace; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*3]; tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*2]; tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*1]; tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*0]; tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*7]; tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*6]; tmp10 = tmp0 + tmp5; tmp13 = tmp0 - tmp5; tmp11 = tmp1 + tmp4; tmp14 = tmp1 - tmp4; tmp12 = tmp2 + tmp3; tmp15 = tmp2 - tmp3; tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*3]; tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*2]; tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*1]; tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*0]; tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*7]; tmp5 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*6]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */ CONST_BITS+1); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */ CONST_BITS+1); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */ CONST_BITS+1); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */ MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ CONST_BITS+1); /* Odd part */ tmp10 = MULTIPLY(tmp1 + tmp4, FIX(0.481063200)); /* c9 */ tmp14 = tmp10 + MULTIPLY(tmp1, FIX(0.680326102)); /* c3-c9 */ tmp15 = tmp10 - MULTIPLY(tmp4, FIX(1.642452502)); /* c3+c9 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */ + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */ + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */ - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */ - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+1); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+1); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+1); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+1); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 13x13 sample block. */ GLOBAL(void) jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; INT32 z1, z2; DCTELEM workspace[8*5]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT. * cK represents sqrt(2) * cos(K*pi/26). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[12]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[11]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[10]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[9]); tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[8]); tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[7]); tmp6 = GETJSAMPLE(elemptr[6]); tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[12]); tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[11]); tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[10]); tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[9]); tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[8]); tmp15 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[7]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) (tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6 - 13 * CENTERJSAMPLE); tmp6 += tmp6; tmp0 -= tmp6; tmp1 -= tmp6; tmp2 -= tmp6; tmp3 -= tmp6; tmp4 -= tmp6; tmp5 -= tmp6; dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.373119086)) + /* c2 */ MULTIPLY(tmp1, FIX(1.058554052)) + /* c6 */ MULTIPLY(tmp2, FIX(0.501487041)) - /* c10 */ MULTIPLY(tmp3, FIX(0.170464608)) - /* c12 */ MULTIPLY(tmp4, FIX(0.803364869)) - /* c8 */ MULTIPLY(tmp5, FIX(1.252223920)), /* c4 */ CONST_BITS); z1 = MULTIPLY(tmp0 - tmp2, FIX(1.155388986)) - /* (c4+c6)/2 */ MULTIPLY(tmp3 - tmp4, FIX(0.435816023)) - /* (c2-c10)/2 */ MULTIPLY(tmp1 - tmp5, FIX(0.316450131)); /* (c8-c12)/2 */ z2 = MULTIPLY(tmp0 + tmp2, FIX(0.096834934)) - /* (c4-c6)/2 */ MULTIPLY(tmp3 + tmp4, FIX(0.937303064)) + /* (c2+c10)/2 */ MULTIPLY(tmp1 + tmp5, FIX(0.486914739)); /* (c8+c12)/2 */ dataptr[4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS); dataptr[6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS); /* Odd part */ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.322312651)); /* c3 */ tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.163874945)); /* c5 */ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.937797057)) + /* c7 */ MULTIPLY(tmp14 + tmp15, FIX(0.338443458)); /* c11 */ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(2.020082300)) + /* c3+c5+c7-c1 */ MULTIPLY(tmp14, FIX(0.318774355)); /* c9-c11 */ tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.937797057)) - /* c7 */ MULTIPLY(tmp11 + tmp12, FIX(0.338443458)); /* c11 */ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.163874945)); /* -c5 */ tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(0.837223564)) - /* c5+c9+c11-c3 */ MULTIPLY(tmp14, FIX(2.341699410)); /* c1+c7 */ tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.657217813)); /* -c9 */ tmp2 += tmp4 + tmp6 - MULTIPLY(tmp12, FIX(1.572116027)) + /* c1+c5-c9-c11 */ MULTIPLY(tmp15, FIX(2.260109708)); /* c3+c7 */ tmp3 += tmp5 + tmp6 + MULTIPLY(tmp13, FIX(2.205608352)) - /* c3+c5+c9-c7 */ MULTIPLY(tmp15, FIX(1.742345811)); /* c1+c11 */ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS); dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS); ctr++; if (ctr != DCTSIZE) { if (ctr == 13) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/13)**2 = 64/169, which we partially * fold into the constant multipliers and final shifting: * cK now represents sqrt(2) * cos(K*pi/26) * 128/169. */ dataptr = data; wsptr = workspace; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*4]; tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*3]; tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*2]; tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*1]; tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*0]; tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*7]; tmp6 = dataptr[DCTSIZE*6]; tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*4]; tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*3]; tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*2]; tmp13 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*1]; tmp14 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*0]; tmp15 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*7]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6, FIX(0.757396450)), /* 128/169 */ CONST_BITS+1); tmp6 += tmp6; tmp0 -= tmp6; tmp1 -= tmp6; tmp2 -= tmp6; tmp3 -= tmp6; tmp4 -= tmp6; tmp5 -= tmp6; dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.039995521)) + /* c2 */ MULTIPLY(tmp1, FIX(0.801745081)) + /* c6 */ MULTIPLY(tmp2, FIX(0.379824504)) - /* c10 */ MULTIPLY(tmp3, FIX(0.129109289)) - /* c12 */ MULTIPLY(tmp4, FIX(0.608465700)) - /* c8 */ MULTIPLY(tmp5, FIX(0.948429952)), /* c4 */ CONST_BITS+1); z1 = MULTIPLY(tmp0 - tmp2, FIX(0.875087516)) - /* (c4+c6)/2 */ MULTIPLY(tmp3 - tmp4, FIX(0.330085509)) - /* (c2-c10)/2 */ MULTIPLY(tmp1 - tmp5, FIX(0.239678205)); /* (c8-c12)/2 */ z2 = MULTIPLY(tmp0 + tmp2, FIX(0.073342435)) - /* (c4-c6)/2 */ MULTIPLY(tmp3 + tmp4, FIX(0.709910013)) + /* (c2+c10)/2 */ MULTIPLY(tmp1 + tmp5, FIX(0.368787494)); /* (c8+c12)/2 */ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+1); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS+1); /* Odd part */ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.001514908)); /* c3 */ tmp2 = MULTIPLY(tmp10 + tmp12, FIX(0.881514751)); /* c5 */ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.710284161)) + /* c7 */ MULTIPLY(tmp14 + tmp15, FIX(0.256335874)); /* c11 */ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.530003162)) + /* c3+c5+c7-c1 */ MULTIPLY(tmp14, FIX(0.241438564)); /* c9-c11 */ tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.710284161)) - /* c7 */ MULTIPLY(tmp11 + tmp12, FIX(0.256335874)); /* c11 */ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(0.881514751)); /* -c5 */ tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(0.634110155)) - /* c5+c9+c11-c3 */ MULTIPLY(tmp14, FIX(1.773594819)); /* c1+c7 */ tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.497774438)); /* -c9 */ tmp2 += tmp4 + tmp6 - MULTIPLY(tmp12, FIX(1.190715098)) + /* c1+c5-c9-c11 */ MULTIPLY(tmp15, FIX(1.711799069)); /* c3+c7 */ tmp3 += tmp5 + tmp6 + MULTIPLY(tmp13, FIX(1.670519935)) - /* c3+c5+c9-c7 */ MULTIPLY(tmp15, FIX(1.319646532)); /* c1+c11 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+1); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+1); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+1); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+1); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 14x14 sample block. */ GLOBAL(void) jpeg_fdct_14x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; DCTELEM workspace[8*6]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT. * cK represents sqrt(2) * cos(K*pi/28). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[13]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[12]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[11]); tmp13 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[10]); tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[9]); tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[8]); tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[7]); tmp10 = tmp0 + tmp6; tmp14 = tmp0 - tmp6; tmp11 = tmp1 + tmp5; tmp15 = tmp1 - tmp5; tmp12 = tmp2 + tmp4; tmp16 = tmp2 - tmp4; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[13]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[12]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[11]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[10]); tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[9]); tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]); tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) (tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE); tmp13 += tmp13; dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */ MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ CONST_BITS); tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */ + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ CONST_BITS); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */ - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ CONST_BITS); /* Odd part */ tmp10 = tmp1 + tmp2; tmp11 = tmp5 - tmp4; dataptr[7] = (DCTELEM) (tmp0 - tmp10 + tmp3 - tmp11 - tmp6); tmp3 <<= CONST_BITS; tmp10 = MULTIPLY(tmp10, - FIX(0.158341681)); /* -c13 */ tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */ tmp10 += tmp11 - tmp3; tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */ MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ dataptr[5] = (DCTELEM) DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */ + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ CONST_BITS); tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */ MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ dataptr[3] = (DCTELEM) DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */ - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ CONST_BITS); dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp12 + tmp3 + tmp6 - MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ CONST_BITS); ctr++; if (ctr != DCTSIZE) { if (ctr == 14) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/14)**2 = 16/49, which we partially * fold into the constant multipliers and final shifting: * cK now represents sqrt(2) * cos(K*pi/28) * 32/49. */ dataptr = data; wsptr = workspace; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*5]; tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*4]; tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*3]; tmp13 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*2]; tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*1]; tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*0]; tmp6 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7]; tmp10 = tmp0 + tmp6; tmp14 = tmp0 - tmp6; tmp11 = tmp1 + tmp5; tmp15 = tmp1 - tmp5; tmp12 = tmp2 + tmp4; tmp16 = tmp2 - tmp4; tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*5]; tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*4]; tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*3]; tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*2]; tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*1]; tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*0]; tmp6 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13, FIX(0.653061224)), /* 32/49 */ CONST_BITS+1); tmp13 += tmp13; dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */ MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ CONST_BITS+1); tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */ + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ CONST_BITS+1); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */ - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ CONST_BITS+1); /* Odd part */ tmp10 = tmp1 + tmp2; tmp11 = tmp5 - tmp4; dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6, FIX(0.653061224)), /* 32/49 */ CONST_BITS+1); tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */ tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */ tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */ tmp10 += tmp11 - tmp3; tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */ MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */ + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ CONST_BITS+1); tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */ MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */ - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ CONST_BITS+1); dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp12 + tmp3 - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ CONST_BITS+1); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 15x15 sample block. */ GLOBAL(void) jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; INT32 z1, z2, z3; DCTELEM workspace[8*7]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT. * cK represents sqrt(2) * cos(K*pi/30). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[14]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[13]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[12]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[11]); tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[10]); tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[9]); tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[8]); tmp7 = GETJSAMPLE(elemptr[7]); tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[14]); tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[13]); tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[12]); tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[11]); tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[10]); tmp15 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[9]); tmp16 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[8]); z1 = tmp0 + tmp4 + tmp5; z2 = tmp1 + tmp3 + tmp6; z3 = tmp2 + tmp7; /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) (z1 + z2 + z3 - 15 * CENTERJSAMPLE); z3 += z3; dataptr[6] = (DCTELEM) DESCALE(MULTIPLY(z1 - z3, FIX(1.144122806)) - /* c6 */ MULTIPLY(z2 - z3, FIX(0.437016024)), /* c12 */ CONST_BITS); tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7; z1 = MULTIPLY(tmp3 - tmp2, FIX(1.531135173)) - /* c2+c14 */ MULTIPLY(tmp6 - tmp2, FIX(2.238241955)); /* c4+c8 */ z2 = MULTIPLY(tmp5 - tmp2, FIX(0.798468008)) - /* c8-c14 */ MULTIPLY(tmp0 - tmp2, FIX(0.091361227)); /* c2-c4 */ z3 = MULTIPLY(tmp0 - tmp3, FIX(1.383309603)) + /* c2 */ MULTIPLY(tmp6 - tmp5, FIX(0.946293579)) + /* c8 */ MULTIPLY(tmp1 - tmp4, FIX(0.790569415)); /* (c6+c12)/2 */ dataptr[2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS); dataptr[4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS); /* Odd part */ tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16, FIX(1.224744871)); /* c5 */ tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.344997024)) + /* c3 */ MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.831253876)); /* c9 */ tmp12 = MULTIPLY(tmp12, FIX(1.224744871)); /* c5 */ tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.406466353)) + /* c1 */ MULTIPLY(tmp11 + tmp14, FIX(1.344997024)) + /* c3 */ MULTIPLY(tmp13 + tmp15, FIX(0.575212477)); /* c11 */ tmp0 = MULTIPLY(tmp13, FIX(0.475753014)) - /* c7-c11 */ MULTIPLY(tmp14, FIX(0.513743148)) + /* c3-c9 */ MULTIPLY(tmp16, FIX(1.700497885)) + tmp4 + tmp12; /* c1+c13 */ tmp3 = MULTIPLY(tmp10, - FIX(0.355500862)) - /* -(c1-c7) */ MULTIPLY(tmp11, FIX(2.176250899)) - /* c3+c9 */ MULTIPLY(tmp15, FIX(0.869244010)) + tmp4 - tmp12; /* c11+c13 */ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS); dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS); ctr++; if (ctr != DCTSIZE) { if (ctr == 15) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/15)**2 = 64/225, which we partially * fold into the constant multipliers and final shifting: * cK now represents sqrt(2) * cos(K*pi/30) * 256/225. */ dataptr = data; wsptr = workspace; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*6]; tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*5]; tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*4]; tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*3]; tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*2]; tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*1]; tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*0]; tmp7 = dataptr[DCTSIZE*7]; tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*6]; tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*5]; tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*4]; tmp13 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*3]; tmp14 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*2]; tmp15 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*1]; tmp16 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*0]; z1 = tmp0 + tmp4 + tmp5; z2 = tmp1 + tmp3 + tmp6; z3 = tmp2 + tmp7; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(z1 + z2 + z3, FIX(1.137777778)), /* 256/225 */ CONST_BITS+2); z3 += z3; dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(MULTIPLY(z1 - z3, FIX(1.301757503)) - /* c6 */ MULTIPLY(z2 - z3, FIX(0.497227121)), /* c12 */ CONST_BITS+2); tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7; z1 = MULTIPLY(tmp3 - tmp2, FIX(1.742091575)) - /* c2+c14 */ MULTIPLY(tmp6 - tmp2, FIX(2.546621957)); /* c4+c8 */ z2 = MULTIPLY(tmp5 - tmp2, FIX(0.908479156)) - /* c8-c14 */ MULTIPLY(tmp0 - tmp2, FIX(0.103948774)); /* c2-c4 */ z3 = MULTIPLY(tmp0 - tmp3, FIX(1.573898926)) + /* c2 */ MULTIPLY(tmp6 - tmp5, FIX(1.076671805)) + /* c8 */ MULTIPLY(tmp1 - tmp4, FIX(0.899492312)); /* (c6+c12)/2 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS+2); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS+2); /* Odd part */ tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16, FIX(1.393487498)); /* c5 */ tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.530307725)) + /* c3 */ MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.945782187)); /* c9 */ tmp12 = MULTIPLY(tmp12, FIX(1.393487498)); /* c5 */ tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.600246161)) + /* c1 */ MULTIPLY(tmp11 + tmp14, FIX(1.530307725)) + /* c3 */ MULTIPLY(tmp13 + tmp15, FIX(0.654463974)); /* c11 */ tmp0 = MULTIPLY(tmp13, FIX(0.541301207)) - /* c7-c11 */ MULTIPLY(tmp14, FIX(0.584525538)) + /* c3-c9 */ MULTIPLY(tmp16, FIX(1.934788705)) + tmp4 + tmp12; /* c1+c13 */ tmp3 = MULTIPLY(tmp10, - FIX(0.404480980)) - /* -(c1-c7) */ MULTIPLY(tmp11, FIX(2.476089912)) - /* c3+c9 */ MULTIPLY(tmp15, FIX(0.989006518)) + tmp4 - tmp12; /* c11+c13 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+2); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+2); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 16x16 sample block. */ GLOBAL(void) jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; DCTELEM workspace[DCTSIZE2]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * cK represents sqrt(2) * cos(K*pi/32). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[15]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[14]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[13]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[12]); tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[11]); tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[10]); tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[9]); tmp7 = GETJSAMPLE(elemptr[7]) + GETJSAMPLE(elemptr[8]); tmp10 = tmp0 + tmp7; tmp14 = tmp0 - tmp7; tmp11 = tmp1 + tmp6; tmp15 = tmp1 - tmp6; tmp12 = tmp2 + tmp5; tmp16 = tmp2 - tmp5; tmp13 = tmp3 + tmp4; tmp17 = tmp3 - tmp4; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[15]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[14]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[13]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[12]); tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[11]); tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[10]); tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]); tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ CONST_BITS-PASS1_BITS); tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ CONST_BITS-PASS1_BITS); /* Odd part */ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); ctr++; if (ctr != DCTSIZE) { if (ctr == DCTSIZE * 2) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/16)**2 = 1/2**2. * cK represents sqrt(2) * cos(K*pi/32). */ dataptr = data; wsptr = workspace; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*3]; tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*2]; tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*1]; tmp7 = dataptr[DCTSIZE*7] + wsptr[DCTSIZE*0]; tmp10 = tmp0 + tmp7; tmp14 = tmp0 - tmp7; tmp11 = tmp1 + tmp6; tmp15 = tmp1 - tmp6; tmp12 = tmp2 + tmp5; tmp16 = tmp2 - tmp5; tmp13 = tmp3 + tmp4; tmp17 = tmp3 - tmp4; tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*3]; tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*2]; tmp6 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*1]; tmp7 = dataptr[DCTSIZE*7] - wsptr[DCTSIZE*0]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+2); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ CONST_BITS+PASS1_BITS+2); tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+10 */ CONST_BITS+PASS1_BITS+2); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ CONST_BITS+PASS1_BITS+2); /* Odd part */ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+2); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+2); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS+2); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS+2); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 16x8 sample block. * * 16-point FDCT in pass 1 (rows), 8-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; INT32 z1; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32). */ dataptr = data; ctr = 0; for (ctr = 0; ctr < DCTSIZE; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[15]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[14]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[13]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[12]); tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[11]); tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[10]); tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[9]); tmp7 = GETJSAMPLE(elemptr[7]) + GETJSAMPLE(elemptr[8]); tmp10 = tmp0 + tmp7; tmp14 = tmp0 - tmp7; tmp11 = tmp1 + tmp6; tmp15 = tmp1 - tmp6; tmp12 = tmp2 + tmp5; tmp16 = tmp2 - tmp5; tmp13 = tmp3 + tmp4; tmp17 = tmp3 - tmp4; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[15]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[14]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[13]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[12]); tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[11]); tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[10]); tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]); tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ CONST_BITS-PASS1_BITS); tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ CONST_BITS-PASS1_BITS); /* Odd part */ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by 8/16 = 1/2. * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "c1" should be "c6". */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp10 = tmp0 + tmp3; tmp12 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp13 = tmp1 - tmp2; tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS+1); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS+1); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ CONST_BITS+PASS1_BITS+1); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * i0..i3 in the paper are tmp0..tmp3 here. */ tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp0 += z1 + tmp12; tmp3 += z1 + tmp13; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp1 += z1 + tmp13; tmp2 += z1 + tmp12; dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+PASS1_BITS+1); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 14x7 sample block. * * 14-point FDCT in pass 1 (rows), 7-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_14x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; INT32 z1, z2, z3; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Zero bottom row of output coefficient block. */ MEMZERO(&data[DCTSIZE*7], SIZEOF(DCTELEM) * DCTSIZE); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28). */ dataptr = data; for (ctr = 0; ctr < 7; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[13]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[12]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[11]); tmp13 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[10]); tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[9]); tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[8]); tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[7]); tmp10 = tmp0 + tmp6; tmp14 = tmp0 - tmp6; tmp11 = tmp1 + tmp5; tmp15 = tmp1 - tmp5; tmp12 = tmp2 + tmp4; tmp16 = tmp2 - tmp4; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[13]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[12]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[11]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[10]); tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[9]); tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]); tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE) << PASS1_BITS); tmp13 += tmp13; dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */ MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ CONST_BITS-PASS1_BITS); tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */ + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */ - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ CONST_BITS-PASS1_BITS); /* Odd part */ tmp10 = tmp1 + tmp2; tmp11 = tmp5 - tmp4; dataptr[7] = (DCTELEM) ((tmp0 - tmp10 + tmp3 - tmp11 - tmp6) << PASS1_BITS); tmp3 <<= CONST_BITS; tmp10 = MULTIPLY(tmp10, - FIX(0.158341681)); /* -c13 */ tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */ tmp10 += tmp11 - tmp3; tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */ MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ dataptr[5] = (DCTELEM) DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */ + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ CONST_BITS-PASS1_BITS); tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */ MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ dataptr[3] = (DCTELEM) DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */ - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ CONST_BITS-PASS1_BITS); dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp12 + tmp3 + tmp6 - MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/14)*(8/7) = 32/49, which we * partially fold into the constant multipliers and final shifting: * 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14) * 64/49. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*6]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*5]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*4]; tmp3 = dataptr[DCTSIZE*3]; tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*6]; tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*5]; tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*4]; z1 = tmp0 + tmp2; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */ CONST_BITS+PASS1_BITS+1); tmp3 += tmp3; z1 -= tmp3; z1 -= tmp3; z1 = MULTIPLY(z1, FIX(0.461784020)); /* (c2+c6-c4)/2 */ z2 = MULTIPLY(tmp0 - tmp2, FIX(1.202428084)); /* (c2+c4-c6)/2 */ z3 = MULTIPLY(tmp1 - tmp2, FIX(0.411026446)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS+PASS1_BITS+1); z1 -= z2; z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */ CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS+1); /* Odd part */ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.221765677)); /* (c3+c1-c5)/2 */ tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.222383464)); /* (c3+c5-c1)/2 */ tmp0 = tmp1 - tmp2; tmp1 += tmp2; tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.800824523)); /* -c1 */ tmp1 += tmp2; tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.801442310)); /* c5 */ tmp0 += tmp3; tmp2 += tmp3 + MULTIPLY(tmp12, FIX(2.443531355)); /* c3+c1-c5 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS+1); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 12x6 sample block. * * 12-point FDCT in pass 1 (rows), 6-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_12x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Zero 2 bottom rows of output coefficient block. */ MEMZERO(&data[DCTSIZE*6], SIZEOF(DCTELEM) * DCTSIZE * 2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24). */ dataptr = data; for (ctr = 0; ctr < 6; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[11]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[10]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[9]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[8]); tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[7]); tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[6]); tmp10 = tmp0 + tmp5; tmp13 = tmp0 - tmp5; tmp11 = tmp1 + tmp4; tmp14 = tmp1 - tmp4; tmp12 = tmp2 + tmp3; tmp15 = tmp2 - tmp3; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[11]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[10]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[9]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[8]); tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]); tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE) << PASS1_BITS); dataptr[6] = (DCTELEM) ((tmp13 - tmp14 - tmp15) << PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */ CONST_BITS-PASS1_BITS); dataptr[2] = (DCTELEM) DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */ CONST_BITS-PASS1_BITS); /* Odd part */ tmp10 = MULTIPLY(tmp1 + tmp4, FIX_0_541196100); /* c9 */ tmp14 = tmp10 + MULTIPLY(tmp1, FIX_0_765366865); /* c3-c9 */ tmp15 = tmp10 - MULTIPLY(tmp4, FIX_1_847759065); /* c3+c9 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */ + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */ + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */ - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */ - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/12)*(8/6) = 8/9, which we * partially fold into the constant multipliers and final shifting: * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12) * 16/9. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; tmp10 = tmp0 + tmp2; tmp12 = tmp0 - tmp2; tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ CONST_BITS+PASS1_BITS+1); /* Odd part */ tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS+1); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 10x5 sample block. * * 10-point FDCT in pass 1 (rows), 5-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_10x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4; INT32 tmp10, tmp11, tmp12, tmp13, tmp14; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Zero 3 bottom rows of output coefficient block. */ MEMZERO(&data[DCTSIZE*5], SIZEOF(DCTELEM) * DCTSIZE * 3); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20). */ dataptr = data; for (ctr = 0; ctr < 5; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[9]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[8]); tmp12 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[7]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[6]); tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[5]); tmp10 = tmp0 + tmp4; tmp13 = tmp0 - tmp4; tmp11 = tmp1 + tmp3; tmp14 = tmp1 - tmp3; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[9]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[8]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[7]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]); tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << PASS1_BITS); tmp12 += tmp12; dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */ MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ CONST_BITS-PASS1_BITS); tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */ CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */ CONST_BITS-PASS1_BITS); /* Odd part */ tmp10 = tmp0 + tmp4; tmp11 = tmp1 - tmp3; dataptr[5] = (DCTELEM) ((tmp10 - tmp11 - tmp2) << PASS1_BITS); tmp2 <<= CONST_BITS; dataptr[1] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */ MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ CONST_BITS-PASS1_BITS); tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */ MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */ (tmp11 << (CONST_BITS - 1)) - tmp2; dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-PASS1_BITS); dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/10)*(8/5) = 32/25, which we * fold into the constant multipliers: * 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10) * 32/25. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*4]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*3]; tmp2 = dataptr[DCTSIZE*2]; tmp10 = tmp0 + tmp1; tmp11 = tmp0 - tmp1; tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*4]; tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*3]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */ CONST_BITS+PASS1_BITS); tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */ tmp10 -= tmp2 << 2; tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS+PASS1_BITS); /* Odd part */ tmp10 = MULTIPLY(tmp0 + tmp1, FIX(1.064004961)); /* c3 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */ CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on an 8x4 sample block. * * 8-point FDCT in pass 1 (rows), 4-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Zero 4 bottom rows of output coefficient block. */ MEMZERO(&data[DCTSIZE*4], SIZEOF(DCTELEM) * DCTSIZE * 4); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * We must also scale the output by 8/4 = 2, which we add here. * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ dataptr = data; for (ctr = 0; ctr < 4; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "c1" should be "c6". */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); tmp10 = tmp0 + tmp3; tmp12 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp13 = tmp1 - tmp2; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << (PASS1_BITS+1)); dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << (PASS1_BITS+1)); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-2); dataptr[2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ CONST_BITS-PASS1_BITS-1); dataptr[6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ CONST_BITS-PASS1_BITS-1); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * i0..i3 in the paper are tmp0..tmp3 here. */ tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-2); tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp0 += z1 + tmp12; tmp3 += z1 + tmp13; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp1 += z1 + tmp13; tmp2 += z1 + tmp12; dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS-PASS1_BITS-1); dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS-PASS1_BITS-1); dataptr[5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS-1); dataptr[7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS-PASS1_BITS-1); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * 4-point FDCT kernel, * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ /* Add fudge factor here for final descale. */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3] + (ONE << (PASS1_BITS-1)); tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS); /* Odd part */ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS+PASS1_BITS-1); dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 6x3 sample block. * * 6-point FDCT in pass 1 (rows), 3-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_6x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2; INT32 tmp10, tmp11, tmp12; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * We scale the results further by 2 as part of output adaption * scaling for different DCT size. * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ dataptr = data; for (ctr = 0; ctr < 3; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); tmp10 = tmp0 + tmp2; tmp12 = tmp0 - tmp2; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << (PASS1_BITS+1)); dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ CONST_BITS-PASS1_BITS-1); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ CONST_BITS-PASS1_BITS-1); /* Odd part */ tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ CONST_BITS-PASS1_BITS-1); dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << (PASS1_BITS+1))); dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << (PASS1_BITS+1)); dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << (PASS1_BITS+1))); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/6)*(8/3) = 32/9, which we partially * fold into the constant multipliers (other part was done in pass 1): * 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6) * 16/9. */ dataptr = data; for (ctr = 0; ctr < 6; ctr++) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*2]; tmp1 = dataptr[DCTSIZE*1]; tmp2 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*2]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */ CONST_BITS+PASS1_BITS); /* Odd part */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */ CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 4x2 sample block. * * 4-point FDCT in pass 1 (rows), 2-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_4x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { DCTELEM tmp0, tmp2, tmp10, tmp12, tmp4, tmp5; INT32 tmp1, tmp3, tmp11, tmp13; INT32 z1, z2, z3; JSAMPROW elemptr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT. * 4-point FDCT kernel, * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ /* Row 0 */ elemptr = sample_data[0] + start_col; /* Even part */ tmp4 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); tmp5 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); tmp0 = tmp4 + tmp5; tmp2 = tmp4 - tmp5; /* Odd part */ z2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); z3 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-3-1); tmp1 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ /* Row 1 */ elemptr = sample_data[1] + start_col; /* Even part */ tmp4 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); tmp5 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); tmp10 = tmp4 + tmp5; tmp12 = tmp4 - tmp5; /* Odd part */ z2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); z3 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ tmp11 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp13 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ /* Pass 2: process columns. * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/4)*(8/2) = 2**3. */ /* Column 0 */ /* Apply unsigned->signed conversion. */ data[DCTSIZE*0] = (tmp0 + tmp10 - 8 * CENTERJSAMPLE) << 3; data[DCTSIZE*1] = (tmp0 - tmp10) << 3; /* Column 1 */ data[DCTSIZE*0+1] = (DCTELEM) RIGHT_SHIFT(tmp1 + tmp11, CONST_BITS-3); data[DCTSIZE*1+1] = (DCTELEM) RIGHT_SHIFT(tmp1 - tmp11, CONST_BITS-3); /* Column 2 */ data[DCTSIZE*0+2] = (tmp2 + tmp12) << 3; data[DCTSIZE*1+2] = (tmp2 - tmp12) << 3; /* Column 3 */ data[DCTSIZE*0+3] = (DCTELEM) RIGHT_SHIFT(tmp3 + tmp13, CONST_BITS-3); data[DCTSIZE*1+3] = (DCTELEM) RIGHT_SHIFT(tmp3 - tmp13, CONST_BITS-3); } /* * Perform the forward DCT on a 2x1 sample block. * * 2-point FDCT in pass 1 (rows), 1-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_2x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { DCTELEM tmp0, tmp1; JSAMPROW elemptr; /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); elemptr = sample_data[0] + start_col; tmp0 = GETJSAMPLE(elemptr[0]); tmp1 = GETJSAMPLE(elemptr[1]); /* We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/2)*(8/1) = 2**5. */ /* Even part */ /* Apply unsigned->signed conversion. */ data[0] = (tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5; /* Odd part */ data[1] = (tmp0 - tmp1) << 5; } /* * Perform the forward DCT on an 8x16 sample block. * * 8-point FDCT in pass 1 (rows), 16-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; INT32 z1; DCTELEM workspace[DCTSIZE2]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "c1" should be "c6". */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); tmp10 = tmp0 + tmp3; tmp12 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp13 = tmp1 - tmp2; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS); dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ CONST_BITS-PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * i0..i3 in the paper are tmp0..tmp3 here. */ tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp0 += z1 + tmp12; tmp3 += z1 + tmp13; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp1 += z1 + tmp13; tmp2 += z1 + tmp12; dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS); dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS-PASS1_BITS); ctr++; if (ctr != DCTSIZE) { if (ctr == DCTSIZE * 2) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by 8/16 = 1/2. * 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32). */ dataptr = data; wsptr = workspace; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*3]; tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*2]; tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*1]; tmp7 = dataptr[DCTSIZE*7] + wsptr[DCTSIZE*0]; tmp10 = tmp0 + tmp7; tmp14 = tmp0 - tmp7; tmp11 = tmp1 + tmp6; tmp15 = tmp1 - tmp6; tmp12 = tmp2 + tmp5; tmp16 = tmp2 - tmp5; tmp13 = tmp3 + tmp4; tmp17 = tmp3 - tmp4; tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*3]; tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*2]; tmp6 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*1]; tmp7 = dataptr[DCTSIZE*7] - wsptr[DCTSIZE*0]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+1); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ CONST_BITS+PASS1_BITS+1); tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ CONST_BITS+PASS1_BITS+1); /* Odd part */ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS+1); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 7x14 sample block. * * 7-point FDCT in pass 1 (rows), 14-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; INT32 z1, z2, z3; DCTELEM workspace[8*6]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[6]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[5]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[4]); tmp3 = GETJSAMPLE(elemptr[3]); tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[6]); tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[5]); tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]); z1 = tmp0 + tmp2; /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS); tmp3 += tmp3; z1 -= tmp3; z1 -= tmp3; z1 = MULTIPLY(z1, FIX(0.353553391)); /* (c2+c6-c4)/2 */ z2 = MULTIPLY(tmp0 - tmp2, FIX(0.920609002)); /* (c2+c4-c6)/2 */ z3 = MULTIPLY(tmp1 - tmp2, FIX(0.314692123)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS-PASS1_BITS); z1 -= z2; z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */ dataptr[4] = (DCTELEM) DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */ CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS); /* Odd part */ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(0.935414347)); /* (c3+c1-c5)/2 */ tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.170262339)); /* (c3+c5-c1)/2 */ tmp0 = tmp1 - tmp2; tmp1 += tmp2; tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.378756276)); /* -c1 */ tmp1 += tmp2; tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.613604268)); /* c5 */ tmp0 += tmp3; tmp2 += tmp3 + MULTIPLY(tmp12, FIX(1.870828693)); /* c3+c1-c5 */ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS); ctr++; if (ctr != DCTSIZE) { if (ctr == 14) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/7)*(8/14) = 32/49, which we * fold into the constant multipliers: * 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28) * 32/49. */ dataptr = data; wsptr = workspace; for (ctr = 0; ctr < 7; ctr++) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*5]; tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*4]; tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*3]; tmp13 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*2]; tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*1]; tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*0]; tmp6 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7]; tmp10 = tmp0 + tmp6; tmp14 = tmp0 - tmp6; tmp11 = tmp1 + tmp5; tmp15 = tmp1 - tmp5; tmp12 = tmp2 + tmp4; tmp16 = tmp2 - tmp4; tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*5]; tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*4]; tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*3]; tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*2]; tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*1]; tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*0]; tmp6 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13, FIX(0.653061224)), /* 32/49 */ CONST_BITS+PASS1_BITS); tmp13 += tmp13; dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */ MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ CONST_BITS+PASS1_BITS); tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */ + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */ - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ CONST_BITS+PASS1_BITS); /* Odd part */ tmp10 = tmp1 + tmp2; tmp11 = tmp5 - tmp4; dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6, FIX(0.653061224)), /* 32/49 */ CONST_BITS+PASS1_BITS); tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */ tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */ tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */ tmp10 += tmp11 - tmp3; tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */ MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */ + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ CONST_BITS+PASS1_BITS); tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */ MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */ - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp12 + tmp3 - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 6x12 sample block. * * 6-point FDCT in pass 1 (rows), 12-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_6x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; DCTELEM workspace[8*4]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); tmp10 = tmp0 + tmp2; tmp12 = tmp0 - tmp2; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS); dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ CONST_BITS-PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ CONST_BITS-PASS1_BITS); /* Odd part */ tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ CONST_BITS-PASS1_BITS); dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS)); dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS); dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << PASS1_BITS)); ctr++; if (ctr != DCTSIZE) { if (ctr == 12) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/6)*(8/12) = 8/9, which we * fold into the constant multipliers: * 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24) * 8/9. */ dataptr = data; wsptr = workspace; for (ctr = 0; ctr < 6; ctr++) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*3]; tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*2]; tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*1]; tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*0]; tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*7]; tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*6]; tmp10 = tmp0 + tmp5; tmp13 = tmp0 - tmp5; tmp11 = tmp1 + tmp4; tmp14 = tmp1 - tmp4; tmp12 = tmp2 + tmp3; tmp15 = tmp2 - tmp3; tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*3]; tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*2]; tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*1]; tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*0]; tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*7]; tmp5 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*6]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */ MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ CONST_BITS+PASS1_BITS); /* Odd part */ tmp10 = MULTIPLY(tmp1 + tmp4, FIX(0.481063200)); /* c9 */ tmp14 = tmp10 + MULTIPLY(tmp1, FIX(0.680326102)); /* c3-c9 */ tmp15 = tmp10 - MULTIPLY(tmp4, FIX(1.642452502)); /* c3+c9 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */ + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */ + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */ - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */ - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 5x10 sample block. * * 5-point FDCT in pass 1 (rows), 10-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_5x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4; INT32 tmp10, tmp11, tmp12, tmp13, tmp14; DCTELEM workspace[8*2]; DCTELEM *dataptr; DCTELEM *wsptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10). */ dataptr = data; ctr = 0; for (;;) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[4]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[3]); tmp2 = GETJSAMPLE(elemptr[2]); tmp10 = tmp0 + tmp1; tmp11 = tmp0 - tmp1; tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << PASS1_BITS); tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */ tmp10 -= tmp2 << 2; tmp10 = MULTIPLY(tmp10, FIX(0.353553391)); /* (c2-c4)/2 */ dataptr[2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS-PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS-PASS1_BITS); /* Odd part */ tmp10 = MULTIPLY(tmp0 + tmp1, FIX(0.831253876)); /* c3 */ dataptr[1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */ CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */ CONST_BITS-PASS1_BITS); ctr++; if (ctr != DCTSIZE) { if (ctr == 10) break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/5)*(8/10) = 32/25, which we * fold into the constant multipliers: * 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20) * 32/25. */ dataptr = data; wsptr = workspace; for (ctr = 0; ctr < 5; ctr++) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*1]; tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*0]; tmp12 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*7]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*6]; tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5]; tmp10 = tmp0 + tmp4; tmp13 = tmp0 - tmp4; tmp11 = tmp1 + tmp3; tmp14 = tmp1 - tmp3; tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*1]; tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*0]; tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*7]; tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*6]; tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */ CONST_BITS+PASS1_BITS); tmp12 += tmp12; dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */ MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ CONST_BITS+PASS1_BITS); tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */ CONST_BITS+PASS1_BITS); /* Odd part */ tmp10 = tmp0 + tmp4; tmp11 = tmp1 - tmp3; dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */ CONST_BITS+PASS1_BITS); tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */ MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ CONST_BITS+PASS1_BITS); tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */ MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */ MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 4x8 sample block. * * 4-point FDCT in pass 1 (rows), 8-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * We must also scale the output by 8/4 = 2, which we add here. * 4-point FDCT kernel, * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ dataptr = data; for (ctr = 0; ctr < DCTSIZE; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+1)); dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+1)); /* Odd part */ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS-PASS1_BITS-2); dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ CONST_BITS-PASS1_BITS-1); dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ CONST_BITS-PASS1_BITS-1); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ dataptr = data; for (ctr = 0; ctr < 4; ctr++) { /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "c1" should be "c6". */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; /* Add fudge factor here for final descale. */ tmp10 = tmp0 + tmp3 + (ONE << (PASS1_BITS-1)); tmp12 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp13 = tmp1 - tmp2; tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS+PASS1_BITS-1); dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ CONST_BITS+PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * i0..i3 in the paper are tmp0..tmp3 here. */ tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS+PASS1_BITS-1); tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp0 += z1 + tmp12; tmp3 += z1 + tmp13; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp1 += z1 + tmp13; tmp2 += z1 + tmp12; dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 3x6 sample block. * * 3-point FDCT in pass 1 (rows), 6-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_3x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1, tmp2; INT32 tmp10, tmp11, tmp12; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT; * furthermore, we scale the results by 2**PASS1_BITS. * We scale the results further by 2 as part of output adaption * scaling for different DCT size. * 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6). */ dataptr = data; for (ctr = 0; ctr < 6; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[2]); tmp1 = GETJSAMPLE(elemptr[1]); tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+1)); dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */ CONST_BITS-PASS1_BITS-1); /* Odd part */ dataptr[1] = (DCTELEM) DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */ CONST_BITS-PASS1_BITS-1); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/6)*(8/3) = 32/9, which we partially * fold into the constant multipliers (other part was done in pass 1): * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12) * 16/9. */ dataptr = data; for (ctr = 0; ctr < 3; ctr++) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; tmp10 = tmp0 + tmp2; tmp12 = tmp0 - tmp2; tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ CONST_BITS+PASS1_BITS); /* Odd part */ tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 2x4 sample block. * * 2-point FDCT in pass 1 (rows), 4-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_2x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { INT32 tmp0, tmp1; INT32 tmp10, tmp11; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: process rows. * Note results are scaled up by sqrt(8) compared to a true DCT. */ dataptr = data; for (ctr = 0; ctr < 4; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part */ tmp0 = GETJSAMPLE(elemptr[0]); tmp1 = GETJSAMPLE(elemptr[1]); /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) (tmp0 + tmp1 - 2 * CENTERJSAMPLE); /* Odd part */ dataptr[1] = (DCTELEM) (tmp0 - tmp1); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/2)*(8/4) = 2**3. * 4-point FDCT kernel, * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ dataptr = data; for (ctr = 0; ctr < 2; ctr++) { /* Even part */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; dataptr[DCTSIZE*0] = (DCTELEM) ((tmp0 + tmp1) << 3); dataptr[DCTSIZE*2] = (DCTELEM) ((tmp0 - tmp1) << 3); /* Odd part */ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS-3-1); dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ CONST_BITS-3); dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ CONST_BITS-3); dataptr++; /* advance pointer to next column */ } } /* * Perform the forward DCT on a 1x2 sample block. * * 1-point FDCT in pass 1 (rows), 2-point in pass 2 (columns). */ GLOBAL(void) jpeg_fdct_1x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { DCTELEM tmp0, tmp1; /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); /* Pass 1: empty. */ /* Pass 2: process columns. * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/1)*(8/2) = 2**5. */ /* Even part */ tmp0 = GETJSAMPLE(sample_data[0][start_col]); tmp1 = GETJSAMPLE(sample_data[1][start_col]); /* Apply unsigned->signed conversion. */ data[DCTSIZE*0] = (tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5; /* Odd part */ data[DCTSIZE*1] = (tmp0 - tmp1) << 5; } #endif /* DCT_SCALING_SUPPORTED */ #endif /* DCT_ISLOW_SUPPORTED */ fltk-1.4.3/jpeg/jdsample.c0000644000175000017500000002651215004135251015503 0ustar albrechtalbrecht/* * jdsample.c * * Copyright (C) 1991-1996, Thomas G. Lane. * Modified 2002-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains upsampling routines. * * Upsampling input data is counted in "row groups". A row group * is defined to be (v_samp_factor * DCT_v_scaled_size / min_DCT_v_scaled_size) * sample rows of each component. Upsampling will normally produce * max_v_samp_factor pixel rows from each row group (but this could vary * if the upsampler is applying a scale factor of its own). * * An excellent reference for image resampling is * Digital Image Warping, George Wolberg, 1990. * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Pointer to routine to upsample a single component */ typedef JMETHOD(void, upsample1_ptr, (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPIMAGE output_data_ptr)); /* Private subobject */ typedef struct { struct jpeg_upsampler pub; /* public fields */ /* Color conversion buffer. When using separate upsampling and color * conversion steps, this buffer holds one upsampled row group until it * has been color converted and output. * Note: we do not allocate any storage for component(s) which are full-size, * ie do not need rescaling. The corresponding entry of color_buf[] is * simply set to point to the input data array, thereby avoiding copying. */ JSAMPARRAY color_buf[MAX_COMPONENTS]; /* Per-component upsampling method pointers */ upsample1_ptr methods[MAX_COMPONENTS]; int next_row_out; /* counts rows emitted from color_buf */ JDIMENSION rows_to_go; /* counts rows remaining in image */ /* Height of an input row group for each component. */ int rowgroup_height[MAX_COMPONENTS]; /* These arrays save pixel expansion factors so that int_expand need not * recompute them each time. They are unused for other upsampling methods. */ UINT8 h_expand[MAX_COMPONENTS]; UINT8 v_expand[MAX_COMPONENTS]; } my_upsampler; typedef my_upsampler * my_upsample_ptr; /* * Initialize for an upsampling pass. */ METHODDEF(void) start_pass_upsample (j_decompress_ptr cinfo) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; /* Mark the conversion buffer empty */ upsample->next_row_out = cinfo->max_v_samp_factor; /* Initialize total-height counter for detecting bottom of image */ upsample->rows_to_go = cinfo->output_height; } /* * Control routine to do upsampling (and color conversion). * * In this version we upsample each component independently. * We upsample one row group into the conversion buffer, then apply * color conversion a row at a time. */ METHODDEF(void) sep_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; int ci; jpeg_component_info * compptr; JDIMENSION num_rows; /* Fill the conversion buffer, if it's empty */ if (upsample->next_row_out >= cinfo->max_v_samp_factor) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Don't bother to upsample an uninteresting component. */ if (! compptr->component_needed) continue; /* Invoke per-component upsample method. Notice we pass a POINTER * to color_buf[ci], so that fullsize_upsample can change it. */ (*upsample->methods[ci]) (cinfo, compptr, input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), upsample->color_buf + ci); } upsample->next_row_out = 0; } /* Color-convert and emit rows */ /* How many we have in the buffer: */ num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); /* Not more than the distance to the end of the image. Need this test * in case the image height is not a multiple of max_v_samp_factor: */ if (num_rows > upsample->rows_to_go) num_rows = upsample->rows_to_go; /* And not more than what the client can accept: */ out_rows_avail -= *out_row_ctr; if (num_rows > out_rows_avail) num_rows = out_rows_avail; (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, (JDIMENSION) upsample->next_row_out, output_buf + *out_row_ctr, (int) num_rows); /* Adjust counts */ *out_row_ctr += num_rows; upsample->rows_to_go -= num_rows; upsample->next_row_out += num_rows; /* When the buffer is emptied, declare this input row group consumed */ if (upsample->next_row_out >= cinfo->max_v_samp_factor) (*in_row_group_ctr)++; } /* * These are the routines invoked by sep_upsample to upsample pixel values * of a single component. One row group is processed per call. */ /* * For full-size components, we just make color_buf[ci] point at the * input buffer, and thus avoid copying any data. Note that this is * safe only because sep_upsample doesn't declare the input row group * "consumed" until we are done color converting and emitting it. */ METHODDEF(void) fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPIMAGE output_data_ptr) { *output_data_ptr = input_data; } /* * This version handles any integral sampling ratios. * This is not used for typical JPEG files, so it need not be fast. * Nor, for that matter, is it particularly accurate: the algorithm is * simple replication of the input pixel onto the corresponding output * pixels. The hi-falutin sampling literature refers to this as a * "box filter". A box filter tends to introduce visible artifacts, * so if you are actually going to use 3:1 or 4:1 sampling ratios * you would be well advised to improve this code. */ METHODDEF(void) int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPIMAGE output_data_ptr) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; JSAMPARRAY output_data, output_end; register JSAMPROW inptr, outptr; register JSAMPLE invalue; register int h; JSAMPROW outend; int h_expand, v_expand; h_expand = upsample->h_expand[compptr->component_index]; v_expand = upsample->v_expand[compptr->component_index]; output_data = *output_data_ptr; output_end = output_data + cinfo->max_v_samp_factor; for (; output_data < output_end; output_data += v_expand) { /* Generate one output row with proper horizontal expansion */ inptr = *input_data++; outptr = *output_data; outend = outptr + cinfo->output_width; while (outptr < outend) { invalue = *inptr++; /* don't need GETJSAMPLE() here */ for (h = h_expand; h > 0; h--) { *outptr++ = invalue; } } /* Generate any additional output rows by duplicating the first one */ if (v_expand > 1) { jcopy_sample_rows(output_data, output_data + 1, v_expand - 1, cinfo->output_width); } } } /* * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. * It's still a box filter. */ METHODDEF(void) h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPIMAGE output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; register JSAMPLE invalue; JSAMPROW outend; int outrow; for (outrow = 0; outrow < cinfo->max_v_samp_factor; outrow++) { inptr = input_data[outrow]; outptr = output_data[outrow]; outend = outptr + cinfo->output_width; while (outptr < outend) { invalue = *inptr++; /* don't need GETJSAMPLE() here */ *outptr++ = invalue; *outptr++ = invalue; } } } /* * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. * It's still a box filter. */ METHODDEF(void) h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPIMAGE output_data_ptr) { JSAMPARRAY output_data, output_end; register JSAMPROW inptr, outptr; register JSAMPLE invalue; JSAMPROW outend; output_data = *output_data_ptr; output_end = output_data + cinfo->max_v_samp_factor; for (; output_data < output_end; output_data += 2) { inptr = *input_data++; outptr = *output_data; outend = outptr + cinfo->output_width; while (outptr < outend) { invalue = *inptr++; /* don't need GETJSAMPLE() here */ *outptr++ = invalue; *outptr++ = invalue; } jcopy_sample_rows(output_data, output_data + 1, 1, cinfo->output_width); } } /* * Module initialization routine for upsampling. */ GLOBAL(void) jinit_upsampler (j_decompress_ptr cinfo) { my_upsample_ptr upsample; int ci; jpeg_component_info * compptr; int h_in_group, v_in_group, h_out_group, v_out_group; upsample = (my_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_upsampler)); cinfo->upsample = &upsample->pub; upsample->pub.start_pass = start_pass_upsample; upsample->pub.upsample = sep_upsample; upsample->pub.need_context_rows = FALSE; /* until we find out differently */ if (cinfo->CCIR601_sampling) /* this isn't supported */ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); /* Verify we can handle the sampling factors, select per-component methods, * and create storage as needed. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Don't bother to upsample an uninteresting component. */ if (! compptr->component_needed) continue; /* Compute size of an "input group" after IDCT scaling. This many samples * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. */ h_in_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / cinfo->min_DCT_h_scaled_size; v_in_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / cinfo->min_DCT_v_scaled_size; h_out_group = cinfo->max_h_samp_factor; v_out_group = cinfo->max_v_samp_factor; upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ if (h_in_group == h_out_group && v_in_group == v_out_group) { /* Fullsize components can be processed without any work. */ upsample->methods[ci] = fullsize_upsample; continue; /* don't need to allocate buffer */ } if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) { /* Special case for 2h1v upsampling */ upsample->methods[ci] = h2v1_upsample; } else if (h_in_group * 2 == h_out_group && v_in_group * 2 == v_out_group) { /* Special case for 2h2v upsampling */ upsample->methods[ci] = h2v2_upsample; } else if ((h_out_group % h_in_group) == 0 && (v_out_group % v_in_group) == 0) { /* Generic integral-factors upsampling method */ upsample->methods[ci] = int_upsample; upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) jround_up((long) cinfo->output_width, (long) cinfo->max_h_samp_factor), (JDIMENSION) cinfo->max_v_samp_factor); } } fltk-1.4.3/jpeg/jmemnobs.c0000644000175000017500000000553615004135251015521 0ustar albrechtalbrecht/* * jmemnobs.c * * Copyright (C) 1992-1996, Thomas G. Lane. * Modified 2019 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides a really simple implementation of the system- * dependent portion of the JPEG memory manager. This implementation * assumes that no backing-store files are needed: all required space * can be obtained from malloc(). * This is very portable in the sense that it'll compile on almost anything, * but you'd better have lots of main memory (or virtual memory) if you want * to process big images. * Note that the max_memory_to_use option is respected by this implementation. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jmemsys.h" /* import the system-dependent declarations */ #ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ extern void * malloc JPP((size_t size)); extern void free JPP((void *ptr)); #endif /* * Memory allocation and freeing are controlled by the regular library * routines malloc() and free(). */ GLOBAL(void *) jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) { return (void *) malloc(sizeofobject); } GLOBAL(void) jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) { free(object); } /* * "Large" objects are treated the same as "small" ones. * NB: although we include FAR keywords in the routine declarations, * this file won't actually work in 80x86 small/medium model; at least, * you probably won't be able to process useful-size images in only 64KB. */ GLOBAL(void FAR *) jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) { return (void FAR *) malloc(sizeofobject); } GLOBAL(void) jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) { free(object); } /* * This routine computes the total memory space available for allocation. */ GLOBAL(long) jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, long max_bytes_needed, long already_allocated) { if (cinfo->mem->max_memory_to_use) return cinfo->mem->max_memory_to_use - already_allocated; /* Here we say, "we got all you want bud!" */ return max_bytes_needed; } /* * Backing store (temporary file) management. * Since jpeg_mem_available always promised the moon, * this should never be called and we can just error out. */ GLOBAL(void) jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed) { ERREXIT(cinfo, JERR_NO_BACKING_STORE); } /* * These routines take care of any system-dependent initialization and * cleanup required. Here, there isn't any. */ GLOBAL(long) jpeg_mem_init (j_common_ptr cinfo) { return 0; /* just set max_memory_to_use to 0 */ } GLOBAL(void) jpeg_mem_term (j_common_ptr cinfo) { /* no work */ } fltk-1.4.3/jpeg/jcapimin.c0000644000175000017500000002225015004135251015471 0ustar albrechtalbrecht/* * jcapimin.c * * Copyright (C) 1994-1998, Thomas G. Lane. * Modified 2003-2010 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface code for the compression half * of the JPEG library. These are the "minimum" API routines that may be * needed in either the normal full-compression case or the transcoding-only * case. * * Most of the routines intended to be called directly by an application * are in this file or in jcapistd.c. But also see jcparam.c for * parameter-setup helper routines, jcomapi.c for routines shared by * compression and decompression, and jctrans.c for the transcoding case. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Initialization of a JPEG compression object. * The error manager must already be set up (in case memory manager fails). */ GLOBAL(void) jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) { int i; /* Guard against version mismatches between library and caller. */ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ if (version != JPEG_LIB_VERSION) ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); if (structsize != SIZEOF(struct jpeg_compress_struct)) ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); /* For debugging purposes, we zero the whole master structure. * But the application has already set the err pointer, and may have set * client_data, so we have to save and restore those fields. * Note: if application hasn't set client_data, tools like Purify may * complain here. */ { struct jpeg_error_mgr * err = cinfo->err; void * client_data = cinfo->client_data; /* ignore Purify complaint here */ MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); cinfo->err = err; cinfo->client_data = client_data; } cinfo->is_decompressor = FALSE; /* Initialize a memory manager instance for this object */ jinit_memory_mgr((j_common_ptr) cinfo); /* Zero out pointers to permanent structures. */ cinfo->progress = NULL; cinfo->dest = NULL; cinfo->comp_info = NULL; for (i = 0; i < NUM_QUANT_TBLS; i++) { cinfo->quant_tbl_ptrs[i] = NULL; cinfo->q_scale_factor[i] = 100; } for (i = 0; i < NUM_HUFF_TBLS; i++) { cinfo->dc_huff_tbl_ptrs[i] = NULL; cinfo->ac_huff_tbl_ptrs[i] = NULL; } /* Must do it here for emit_dqt in case jpeg_write_tables is used */ cinfo->block_size = DCTSIZE; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2-1; cinfo->script_space = NULL; cinfo->input_gamma = 1.0; /* in case application forgets */ /* OK, I'm ready */ cinfo->global_state = CSTATE_START; } /* * Destruction of a JPEG compression object */ GLOBAL(void) jpeg_destroy_compress (j_compress_ptr cinfo) { jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ } /* * Abort processing of a JPEG compression operation, * but don't destroy the object itself. */ GLOBAL(void) jpeg_abort_compress (j_compress_ptr cinfo) { jpeg_abort((j_common_ptr) cinfo); /* use common routine */ } /* * Forcibly suppress or un-suppress all quantization and Huffman tables. * Marks all currently defined tables as already written (if suppress) * or not written (if !suppress). This will control whether they get emitted * by a subsequent jpeg_start_compress call. * * This routine is exported for use by applications that want to produce * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but * since it is called by jpeg_start_compress, we put it here --- otherwise * jcparam.o would be linked whether the application used it or not. */ GLOBAL(void) jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) { int i; JQUANT_TBL * qtbl; JHUFF_TBL * htbl; for (i = 0; i < NUM_QUANT_TBLS; i++) { if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) qtbl->sent_table = suppress; } for (i = 0; i < NUM_HUFF_TBLS; i++) { if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) htbl->sent_table = suppress; if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) htbl->sent_table = suppress; } } /* * Finish JPEG compression. * * If a multipass operating mode was selected, this may do a great deal of * work including most of the actual output. */ GLOBAL(void) jpeg_finish_compress (j_compress_ptr cinfo) { JDIMENSION iMCU_row; if (cinfo->global_state == CSTATE_SCANNING || cinfo->global_state == CSTATE_RAW_OK) { /* Terminate first pass */ if (cinfo->next_scanline < cinfo->image_height) ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); (*cinfo->master->finish_pass) (cinfo); } else if (cinfo->global_state != CSTATE_WRCOEFS) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Perform any remaining passes */ while (! cinfo->master->is_last_pass) { (*cinfo->master->prepare_for_pass) (cinfo); for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) iMCU_row; cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* We bypass the main controller and invoke coef controller directly; * all work is being done from the coefficient buffer. */ if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) ERREXIT(cinfo, JERR_CANT_SUSPEND); } (*cinfo->master->finish_pass) (cinfo); } /* Write EOI, do final cleanup */ (*cinfo->marker->write_file_trailer) (cinfo); (*cinfo->dest->term_destination) (cinfo); /* We can use jpeg_abort to release memory and reset global_state */ jpeg_abort((j_common_ptr) cinfo); } /* * Write a special marker. * This is only recommended for writing COM or APPn markers. * Must be called after jpeg_start_compress() and before * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). */ GLOBAL(void) jpeg_write_marker (j_compress_ptr cinfo, int marker, const JOCTET *dataptr, unsigned int datalen) { JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); if (cinfo->next_scanline != 0 || (cinfo->global_state != CSTATE_SCANNING && cinfo->global_state != CSTATE_RAW_OK && cinfo->global_state != CSTATE_WRCOEFS)) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ while (datalen--) { (*write_marker_byte) (cinfo, *dataptr); dataptr++; } } /* Same, but piecemeal. */ GLOBAL(void) jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) { if (cinfo->next_scanline != 0 || (cinfo->global_state != CSTATE_SCANNING && cinfo->global_state != CSTATE_RAW_OK && cinfo->global_state != CSTATE_WRCOEFS)) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); } GLOBAL(void) jpeg_write_m_byte (j_compress_ptr cinfo, int val) { (*cinfo->marker->write_marker_byte) (cinfo, val); } /* * Alternate compression function: just write an abbreviated table file. * Before calling this, all parameters and a data destination must be set up. * * To produce a pair of files containing abbreviated tables and abbreviated * image data, one would proceed as follows: * * initialize JPEG object * set JPEG parameters * set destination to table file * jpeg_write_tables(cinfo); * set destination to image file * jpeg_start_compress(cinfo, FALSE); * write data... * jpeg_finish_compress(cinfo); * * jpeg_write_tables has the side effect of marking all tables written * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress * will not re-emit the tables unless it is passed write_all_tables=TRUE. */ GLOBAL(void) jpeg_write_tables (j_compress_ptr cinfo) { if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); /* Initialize the marker writer ... bit of a crock to do it here. */ jinit_marker_writer(cinfo); /* Write them tables! */ (*cinfo->marker->write_tables_only) (cinfo); /* And clean up. */ (*cinfo->dest->term_destination) (cinfo); /* * In library releases up through v6a, we called jpeg_abort() here to free * any working memory allocated by the destination manager and marker * writer. Some applications had a problem with that: they allocated space * of their own from the library memory manager, and didn't want it to go * away during write_tables. So now we do nothing. This will cause a * memory leak if an app calls write_tables repeatedly without doing a full * compression cycle or otherwise resetting the JPEG object. However, that * seems less bad than unexpectedly freeing memory in the normal case. * An app that prefers the old behavior can call jpeg_abort for itself after * each call to jpeg_write_tables(). */ } fltk-1.4.3/jpeg/jdatasrc.c0000644000175000017500000002175115004135251015477 0ustar albrechtalbrecht/* * jdatasrc.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2009-2022 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains decompression data source routines for the case of * reading JPEG data from memory or from a file (or any stdio stream). * While these routines are sufficient for most applications, * some will want to use a different source manager. * IMPORTANT: we assume that fread() will correctly transcribe an array of * JOCTETs from 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. */ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jerror.h" /* Expanded data source object for stdio input */ #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ typedef struct { struct jpeg_source_mgr pub; /* public fields */ FILE * infile; /* source stream */ JOCTET buffer[INPUT_BUF_SIZE]; /* input buffer */ boolean start_of_file; /* have we gotten any data yet? */ } my_source_mgr; typedef my_source_mgr * my_src_ptr; /* * Initialize source --- called by jpeg_read_header * before any data is actually read. */ METHODDEF(void) init_source (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; /* We reset the empty-input-file flag for each image, * but we don't clear the input buffer. * This is correct behavior for reading a series of images from one source. */ src->start_of_file = TRUE; } METHODDEF(void) init_mem_source (j_decompress_ptr cinfo) { /* no work necessary here */ } /* * Fill the input buffer --- called whenever buffer is emptied. * * In typical applications, this should read fresh data into the buffer * (ignoring the current state of next_input_byte & bytes_in_buffer), * reset the pointer & count to the start of the buffer, and return TRUE * indicating that the buffer has been reloaded. It is not necessary to * fill the buffer entirely, only to obtain at least one more byte. * * There is no such thing as an EOF return. If the end of the file has been * reached, the routine has a choice of ERREXIT() or inserting fake data into * the buffer. In most cases, generating a warning message and inserting a * fake EOI marker is the best course of action --- this will allow the * decompressor to output however much of the image is there. However, * the resulting error message is misleading if the real problem is an empty * input file, so we handle that case specially. * * In applications that need to be able to suspend compression due to input * not being available yet, a FALSE return indicates that no more data can be * obtained right now, but more may be forthcoming later. In this situation, * the decompressor will return to its caller (with an indication of the * number of scanlines it has read, if any). The application should resume * decompression after it has loaded more data into the input buffer. Note * that there are substantial restrictions on the use of suspension --- see * the documentation. * * When suspending, the decompressor will back up to a convenient restart point * (typically the start of the current MCU). next_input_byte & bytes_in_buffer * indicate where the restart point will be if the current call returns FALSE. * Data beyond this point must be rescanned after resumption, so move it to * the front of the buffer rather than discarding it. */ METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; size_t nbytes; nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); if (nbytes <= 0) { if (src->start_of_file) /* Treat empty input file as fatal error */ ERREXIT(cinfo, JERR_INPUT_EMPTY); WARNMS(cinfo, JWRN_JPEG_EOF); /* Insert a fake EOI marker */ src->buffer[0] = (JOCTET) 0xFF; src->buffer[1] = (JOCTET) JPEG_EOI; nbytes = 2; } src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer = nbytes; src->start_of_file = FALSE; return TRUE; } METHODDEF(boolean) fill_mem_input_buffer (j_decompress_ptr cinfo) { static const JOCTET mybuffer[4] = { (JOCTET) 0xFF, (JOCTET) JPEG_EOI, 0, 0 }; /* The whole JPEG data is expected to reside in the supplied memory * buffer, so any request for more data beyond the given buffer size * is treated as an error. */ WARNMS(cinfo, JWRN_JPEG_EOF); /* Insert a fake EOI marker */ cinfo->src->next_input_byte = mybuffer; cinfo->src->bytes_in_buffer = 2; return TRUE; } /* * Skip data --- used to skip over a potentially large amount of * uninteresting data (such as an APPn marker). * * Writers of suspendable-input applications must note that skip_input_data * is not granted the right to give a suspension return. If the skip extends * beyond the data currently in the buffer, the buffer can be marked empty so * that the next read will cause a fill_input_buffer call that can suspend. * Arranging for additional bytes to be discarded before reloading the input * buffer is the application writer's problem. */ METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes) { struct jpeg_source_mgr * src = cinfo->src; size_t nbytes; /* Just a dumb implementation for now. Could use fseek() except * it doesn't work on pipes. Not clear that being smart is worth * any trouble anyway --- large skips are infrequent. */ if (num_bytes > 0) { nbytes = (size_t) num_bytes; while (nbytes > src->bytes_in_buffer) { nbytes -= src->bytes_in_buffer; (void) (*src->fill_input_buffer) (cinfo); /* note we assume that fill_input_buffer will never return FALSE, * so suspension need not be handled. */ } src->next_input_byte += nbytes; src->bytes_in_buffer -= nbytes; } } /* * An additional method that can be provided by data source modules is the * resync_to_restart method for error recovery in the presence of RST markers. * For the moment, this source module just uses the default resync method * provided by the JPEG library. That method assumes that no backtracking * is possible. */ /* * Terminate source --- called by jpeg_finish_decompress * after all data has been read. Often a no-op. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ METHODDEF(void) term_source (j_decompress_ptr cinfo) { /* no work necessary here */ } /* * Prepare for input from a stdio stream. * The caller must have already opened the stream, * and is responsible for closing it after finishing decompression. */ GLOBAL(void) jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) { my_src_ptr src; /* The source object including the input buffer is made permanent so that * a series of JPEG images can be read from the same file by calling * jpeg_stdio_src only before the first one. (If we discarded the buffer * at the end of one image, we'd likely lose the start of the next one.) * This makes it unsafe to use this manager and a different source * manager serially with the same JPEG object. Caveat programmer. */ if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_source_mgr)); } src = (my_src_ptr) cinfo->src; src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->pub.term_source = term_source; src->infile = infile; src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ src->pub.next_input_byte = NULL; /* until buffer loaded */ } /* * Prepare for input from a supplied memory buffer. * The buffer must contain the whole JPEG data. */ GLOBAL(void) jpeg_mem_src (j_decompress_ptr cinfo, const unsigned char * inbuffer, size_t insize) { struct jpeg_source_mgr * src; if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */ ERREXIT(cinfo, JERR_INPUT_EMPTY); /* The source object is made permanent so that a series of JPEG images * can be read from the same buffer by calling jpeg_mem_src only before * the first one. */ if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(struct jpeg_source_mgr)); } src = cinfo->src; src->init_source = init_mem_source; src->fill_input_buffer = fill_mem_input_buffer; src->skip_input_data = skip_input_data; src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->term_source = term_source; src->bytes_in_buffer = insize; src->next_input_byte = (const JOCTET *) inbuffer; } fltk-1.4.3/jpeg/structure.txt0000644000175000017500000014455515004135251016351 0ustar albrechtalbrechtIJG JPEG LIBRARY: SYSTEM ARCHITECTURE Copyright (C) 1991-2013, Thomas G. Lane, Guido Vollbeding. This file is part of the Independent JPEG Group's software. For conditions of distribution and use, see the accompanying README file. This file provides an overview of the architecture of the IJG JPEG software; that is, the functions of the various modules in the system and the interfaces between modules. For more precise details about any data structure or calling convention, see the include files and comments in the source code. We assume that the reader is already somewhat familiar with the JPEG standard. The README file includes references for learning about JPEG. The file libjpeg.txt describes the library from the viewpoint of an application programmer using the library; it's best to read that file before this one. Also, the file coderules.txt describes the coding style conventions we use. In this document, JPEG-specific terminology follows the JPEG standard: A "component" means a color channel, e.g., Red or Luminance. A "sample" is a single component value (i.e., one number in the image data). A "coefficient" is a frequency coefficient (a DCT transform output number). A "block" is an array of samples or coefficients. An "MCU" (minimum coded unit) is an interleaved set of blocks of size determined by the sampling factors, or a single block in a noninterleaved scan. We do not use the terms "pixel" and "sample" interchangeably. When we say pixel, we mean an element of the full-size image, while a sample is an element of the downsampled image. Thus the number of samples may vary across components while the number of pixels does not. (This terminology is not used rigorously throughout the code, but it is used in places where confusion would otherwise result.) *** System features *** The IJG distribution contains two parts: * A subroutine library for JPEG compression and decompression. * cjpeg/djpeg, two sample applications that use the library to transform JFIF JPEG files to and from several other image formats. cjpeg/djpeg are of no great intellectual complexity: they merely add a simple command-line user interface and I/O routines for several uncompressed image formats. This document concentrates on the library itself. We desire the library to be capable of supporting all JPEG baseline, extended sequential, and progressive DCT processes. The library does not support the hierarchical or lossless processes defined in the standard. Within these limits, any set of compression parameters allowed by the JPEG spec should be readable for decompression. (We can be more restrictive about what formats we can generate.) Although the system design allows for all parameter values, some uncommon settings are not yet implemented and may never be; nonintegral sampling ratios are the prime example. Furthermore, we treat 8-bit vs. 12-bit data precision as a compile-time switch, not a run-time option, because most machines can store 8-bit pixels much more compactly than 12-bit. By itself, the library handles only interchange JPEG datastreams --- in particular the widely used JFIF file format. The library can be used by surrounding code to process interchange or abbreviated JPEG datastreams that are embedded in more complex file formats. (For example, libtiff uses this library to implement JPEG compression within the TIFF file format.) The library includes a substantial amount of code that is not covered by the JPEG standard but is necessary for typical applications of JPEG. These functions preprocess the image before JPEG compression or postprocess it after decompression. They include colorspace conversion, downsampling/upsampling, and color quantization. This code can be omitted if not needed. A wide range of quality vs. speed tradeoffs are possible in JPEG processing, and even more so in decompression postprocessing. The decompression library provides multiple implementations that cover most of the useful tradeoffs, ranging from very-high-quality down to fast-preview operation. On the compression side we have generally not provided low-quality choices, since compression is normally less time-critical. It should be understood that the low-quality modes may not meet the JPEG standard's accuracy requirements; nonetheless, they are useful for viewers. *** Portability issues *** Portability is an essential requirement for the library. The key portability issues that show up at the level of system architecture are: 1. Memory usage. We want the code to be able to run on PC-class machines with limited memory. Images should therefore be processed sequentially (in strips), to avoid holding the whole image in memory at once. Where a full-image buffer is necessary, we should be able to use either virtual memory or temporary files. 2. Near/far pointer distinction. To run efficiently on 80x86 machines, the code should distinguish "small" objects (kept in near data space) from "large" ones (kept in far data space). This is an annoying restriction, but fortunately it does not impact code quality for less brain-damaged machines, and the source code clutter turns out to be minimal with sufficient use of pointer typedefs. 3. Data precision. We assume that "char" is at least 8 bits, "short" and "int" at least 16, "long" at least 32. The code will work fine with larger data sizes, although memory may be used inefficiently in some cases. However, the JPEG compressed datastream must ultimately appear on external storage as a sequence of 8-bit bytes if it is to conform to the standard. This may pose a problem on machines where char is wider than 8 bits. The library represents compressed data as an array of values of typedef JOCTET. If no data type exactly 8 bits wide is available, custom data source and data destination modules must be written to unpack and pack the chosen JOCTET datatype into 8-bit external representation. *** System overview *** The compressor and decompressor are each divided into two main sections: the JPEG compressor or decompressor proper, and the preprocessing or postprocessing functions. The interface between these two sections is the image data that the official JPEG spec regards as its input or output: this data is in the colorspace to be used for compression, and it is downsampled to the sampling factors to be used. The preprocessing and postprocessing steps are responsible for converting a normal image representation to or from this form. (Those few applications that want to deal with YCbCr downsampled data can skip the preprocessing or postprocessing step.) Looking more closely, the compressor library contains the following main elements: Preprocessing: * Color space conversion (e.g., RGB to YCbCr). * Edge expansion and downsampling. Optionally, this step can do simple smoothing --- this is often helpful for low-quality source data. JPEG proper: * MCU assembly, DCT, quantization. * Entropy coding (sequential or progressive, Huffman or arithmetic). In addition to these modules we need overall control, marker generation, and support code (memory management & error handling). There is also a module responsible for physically writing the output data --- typically this is just an interface to fwrite(), but some applications may need to do something else with the data. The decompressor library contains the following main elements: JPEG proper: * Entropy decoding (sequential or progressive, Huffman or arithmetic). * Dequantization, inverse DCT, MCU disassembly. Postprocessing: * Upsampling. Optionally, this step may be able to do more general rescaling of the image. * Color space conversion (e.g., YCbCr to RGB). This step may also provide gamma adjustment [ currently it does not ]. * Optional color quantization (e.g., reduction to 256 colors). * Optional color precision reduction (e.g., 24-bit to 15-bit color). [This feature is not currently implemented.] We also need overall control, marker parsing, and a data source module. The support code (memory management & error handling) can be shared with the compression half of the library. There may be several implementations of each of these elements, particularly in the decompressor, where a wide range of speed/quality tradeoffs is very useful. It must be understood that some of the best speedups involve merging adjacent steps in the pipeline. For example, upsampling, color space conversion, and color quantization might all be done at once when using a low-quality ordered-dither technique. The system architecture is designed to allow such merging where appropriate. Note: it is convenient to regard edge expansion (padding to block boundaries) as a preprocessing/postprocessing function, even though the JPEG spec includes it in compression/decompression. We do this because downsampling/upsampling can be simplified a little if they work on padded data: it's not necessary to have special cases at the right and bottom edges. Therefore the interface buffer is always an integral number of blocks wide and high, and we expect compression preprocessing to pad the source data properly. Padding will occur only to the next block (block_size-sample) boundary. In an interleaved-scan situation, additional dummy blocks may be used to fill out MCUs, but the MCU assembly and disassembly logic will create or discard these blocks internally. (This is advantageous for speed reasons, since we avoid DCTing the dummy blocks. It also permits a small reduction in file size, because the compressor can choose dummy block contents so as to minimize their size in compressed form. Finally, it makes the interface buffer specification independent of whether the file is actually interleaved or not.) Applications that wish to deal directly with the downsampled data must provide similar buffering and padding for odd-sized images. *** Poor man's object-oriented programming *** It should be clear by now that we have a lot of quasi-independent processing steps, many of which have several possible behaviors. To avoid cluttering the code with lots of switch statements, we use a simple form of object-style programming to separate out the different possibilities. For example, two different color quantization algorithms could be implemented as two separate modules that present the same external interface; at runtime, the calling code will access the proper module indirectly through an "object". We can get the limited features we need while staying within portable C. The basic tool is a function pointer. An "object" is just a struct containing one or more function pointer fields, each of which corresponds to a method name in real object-oriented languages. During initialization we fill in the function pointers with references to whichever module we have determined we need to use in this run. Then invocation of the module is done by indirecting through a function pointer; on most machines this is no more expensive than a switch statement, which would be the only other way of making the required run-time choice. The really significant benefit, of course, is keeping the source code clean and well structured. We can also arrange to have private storage that varies between different implementations of the same kind of object. We do this by making all the module-specific object structs be separately allocated entities, which will be accessed via pointers in the master compression or decompression struct. The "public" fields or methods for a given kind of object are specified by a commonly known struct. But a module's initialization code can allocate a larger struct that contains the common struct as its first member, plus additional private fields. With appropriate pointer casting, the module's internal functions can access these private fields. (For a simple example, see jdatadst.c, which implements the external interface specified by struct jpeg_destination_mgr, but adds extra fields.) (Of course this would all be a lot easier if we were using C++, but we are not yet prepared to assume that everyone has a C++ compiler.) An important benefit of this scheme is that it is easy to provide multiple versions of any method, each tuned to a particular case. While a lot of precalculation might be done to select an optimal implementation of a method, the cost per invocation is constant. For example, the upsampling step might have a "generic" method, plus one or more "hardwired" methods for the most popular sampling factors; the hardwired methods would be faster because they'd use straight-line code instead of for-loops. The cost to determine which method to use is paid only once, at startup, and the selection criteria are hidden from the callers of the method. This plan differs a little bit from usual object-oriented structures, in that only one instance of each object class will exist during execution. The reason for having the class structure is that on different runs we may create different instances (choose to execute different modules). You can think of the term "method" as denoting the common interface presented by a particular set of interchangeable functions, and "object" as denoting a group of related methods, or the total shared interface behavior of a group of modules. *** Overall control structure *** We previously mentioned the need for overall control logic in the compression and decompression libraries. In IJG implementations prior to v5, overall control was mostly provided by "pipeline control" modules, which proved to be large, unwieldy, and hard to understand. To improve the situation, the control logic has been subdivided into multiple modules. The control modules consist of: 1. Master control for module selection and initialization. This has two responsibilities: 1A. Startup initialization at the beginning of image processing. The individual processing modules to be used in this run are selected and given initialization calls. 1B. Per-pass control. This determines how many passes will be performed and calls each active processing module to configure itself appropriately at the beginning of each pass. End-of-pass processing, where necessary, is also invoked from the master control module. Method selection is partially distributed, in that a particular processing module may contain several possible implementations of a particular method, which it will select among when given its initialization call. The master control code need only be concerned with decisions that affect more than one module. 2. Data buffering control. A separate control module exists for each inter-processing-step data buffer. This module is responsible for invoking the processing steps that write or read that data buffer. Each buffer controller sees the world as follows: input data => processing step A => buffer => processing step B => output data | | | ------------------ controller ------------------ The controller knows the dataflow requirements of steps A and B: how much data they want to accept in one chunk and how much they output in one chunk. Its function is to manage its buffer and call A and B at the proper times. A data buffer control module may itself be viewed as a processing step by a higher-level control module; thus the control modules form a binary tree with elementary processing steps at the leaves of the tree. The control modules are objects. A considerable amount of flexibility can be had by replacing implementations of a control module. For example: * Merging of adjacent steps in the pipeline is done by replacing a control module and its pair of processing-step modules with a single processing- step module. (Hence the possible merges are determined by the tree of control modules.) * In some processing modes, a given interstep buffer need only be a "strip" buffer large enough to accommodate the desired data chunk sizes. In other modes, a full-image buffer is needed and several passes are required. The control module determines which kind of buffer is used and manipulates virtual array buffers as needed. One or both processing steps may be unaware of the multi-pass behavior. In theory, we might be able to make all of the data buffer controllers interchangeable and provide just one set of implementations for all. In practice, each one contains considerable special-case processing for its particular job. The buffer controller concept should be regarded as an overall system structuring principle, not as a complete description of the task performed by any one controller. *** Compression object structure *** Here is a sketch of the logical structure of the JPEG compression library: |-- Colorspace conversion |-- Preprocessing controller --| | |-- Downsampling Main controller --| | |-- Forward DCT, quantize |-- Coefficient controller --| |-- Entropy encoding This sketch also describes the flow of control (subroutine calls) during typical image data processing. Each of the components shown in the diagram is an "object" which may have several different implementations available. One or more source code files contain the actual implementation(s) of each object. The objects shown above are: * Main controller: buffer controller for the subsampled-data buffer, which holds the preprocessed input data. This controller invokes preprocessing to fill the subsampled-data buffer, and JPEG compression to empty it. There is usually no need for a full-image buffer here; a strip buffer is adequate. * Preprocessing controller: buffer controller for the downsampling input data buffer, which lies between colorspace conversion and downsampling. Note that a unified conversion/downsampling module would probably replace this controller entirely. * Colorspace conversion: converts application image data into the desired JPEG color space; also changes the data from pixel-interleaved layout to separate component planes. Processes one pixel row at a time. * Downsampling: performs reduction of chroma components as required. Optionally may perform pixel-level smoothing as well. Processes a "row group" at a time, where a row group is defined as Vmax pixel rows of each component before downsampling, and Vk sample rows afterwards (remember Vk differs across components). Some downsampling or smoothing algorithms may require context rows above and below the current row group; the preprocessing controller is responsible for supplying these rows via proper buffering. The downsampler is responsible for edge expansion at the right edge (i.e., extending each sample row to a multiple of block_size samples); but the preprocessing controller is responsible for vertical edge expansion (i.e., duplicating the bottom sample row as needed to make a multiple of block_size rows). * Coefficient controller: buffer controller for the DCT-coefficient data. This controller handles MCU assembly, including insertion of dummy DCT blocks when needed at the right or bottom edge. When performing Huffman-code optimization or emitting a multiscan JPEG file, this controller is responsible for buffering the full image. The equivalent of one fully interleaved MCU row of subsampled data is processed per call, even when the JPEG file is noninterleaved. * Forward DCT and quantization: Perform DCT, quantize, and emit coefficients. Works on one or more DCT blocks at a time. (Note: the coefficients are now emitted in normal array order, which the entropy encoder is expected to convert to zigzag order as necessary. Prior versions of the IJG code did the conversion to zigzag order within the quantization step.) * Entropy encoding: Perform Huffman or arithmetic entropy coding and emit the coded data to the data destination module. Works on one MCU per call. For progressive JPEG, the same DCT blocks are fed to the entropy coder during each pass, and the coder must emit the appropriate subset of coefficients. In addition to the above objects, the compression library includes these objects: * Master control: determines the number of passes required, controls overall and per-pass initialization of the other modules. * Marker writing: generates JPEG markers (except for RSTn, which is emitted by the entropy encoder when needed). * Data destination manager: writes the output JPEG datastream to its final destination (e.g., a file). The destination manager supplied with the library knows how to write to a stdio stream or to a memory buffer; for other behaviors, the surrounding application may provide its own destination manager. * Memory manager: allocates and releases memory, controls virtual arrays (with backing store management, where required). * Error handler: performs formatting and output of error and trace messages; determines handling of nonfatal errors. The surrounding application may override some or all of this object's methods to change error handling. * Progress monitor: supports output of "percent-done" progress reports. This object represents an optional callback to the surrounding application: if wanted, it must be supplied by the application. The error handler, destination manager, and progress monitor objects are defined as separate objects in order to simplify application-specific customization of the JPEG library. A surrounding application may override individual methods or supply its own all-new implementation of one of these objects. The object interfaces for these objects are therefore treated as part of the application interface of the library, whereas the other objects are internal to the library. The error handler and memory manager are shared by JPEG compression and decompression; the progress monitor, if used, may be shared as well. *** Decompression object structure *** Here is a sketch of the logical structure of the JPEG decompression library: |-- Entropy decoding |-- Coefficient controller --| | |-- Dequantize, Inverse DCT Main controller --| | |-- Upsampling |-- Postprocessing controller --| |-- Colorspace conversion |-- Color quantization |-- Color precision reduction As before, this diagram also represents typical control flow. The objects shown are: * Main controller: buffer controller for the subsampled-data buffer, which holds the output of JPEG decompression proper. This controller's primary task is to feed the postprocessing procedure. Some upsampling algorithms may require context rows above and below the current row group; when this is true, the main controller is responsible for managing its buffer so as to make context rows available. In the current design, the main buffer is always a strip buffer; a full-image buffer is never required. * Coefficient controller: buffer controller for the DCT-coefficient data. This controller handles MCU disassembly, including deletion of any dummy DCT blocks at the right or bottom edge. When reading a multiscan JPEG file, this controller is responsible for buffering the full image. (Buffering DCT coefficients, rather than samples, is necessary to support progressive JPEG.) The equivalent of one fully interleaved MCU row of subsampled data is processed per call, even when the source JPEG file is noninterleaved. * Entropy decoding: Read coded data from the data source module and perform Huffman or arithmetic entropy decoding. Works on one MCU per call. For progressive JPEG decoding, the coefficient controller supplies the prior coefficients of each MCU (initially all zeroes), which the entropy decoder modifies in each scan. * Dequantization and inverse DCT: like it says. Note that the coefficients buffered by the coefficient controller have NOT been dequantized; we merge dequantization and inverse DCT into a single step for speed reasons. When scaled-down output is asked for, simplified DCT algorithms may be used that need fewer coefficients and emit fewer samples per DCT block, not the full 8x8. Works on one DCT block at a time. * Postprocessing controller: buffer controller for the color quantization input buffer, when quantization is in use. (Without quantization, this controller just calls the upsampler.) For two-pass quantization, this controller is responsible for buffering the full-image data. * Upsampling: restores chroma components to full size. (May support more general output rescaling, too. Note that if undersized DCT outputs have been emitted by the DCT module, this module must adjust so that properly sized outputs are created.) Works on one row group at a time. This module also calls the color conversion module, so its top level is effectively a buffer controller for the upsampling->color conversion buffer. However, in all but the highest-quality operating modes, upsampling and color conversion are likely to be merged into a single step. * Colorspace conversion: convert from JPEG color space to output color space, and change data layout from separate component planes to pixel-interleaved. Works on one pixel row at a time. * Color quantization: reduce the data to colormapped form, using either an externally specified colormap or an internally generated one. This module is not used for full-color output. Works on one pixel row at a time; may require two passes to generate a color map. Note that the output will always be a single component representing colormap indexes. In the current design, the output values are JSAMPLEs, so an 8-bit compilation cannot quantize to more than 256 colors. This is unlikely to be a problem in practice. * Color reduction: this module handles color precision reduction, e.g., generating 15-bit color (5 bits/primary) from JPEG's 24-bit output. Not quite clear yet how this should be handled... should we merge it with colorspace conversion??? Note that some high-speed operating modes might condense the entire postprocessing sequence to a single module (upsample, color convert, and quantize in one step). In addition to the above objects, the decompression library includes these objects: * Master control: determines the number of passes required, controls overall and per-pass initialization of the other modules. This is subdivided into input and output control: jdinput.c controls only input-side processing, while jdmaster.c handles overall initialization and output-side control. * Marker reading: decodes JPEG markers (except for RSTn). * Data source manager: supplies the input JPEG datastream. The source manager supplied with the library knows how to read from a stdio stream or from a memory buffer; for other behaviors, the surrounding application may provide its own source manager. * Memory manager: same as for compression library. * Error handler: same as for compression library. * Progress monitor: same as for compression library. As with compression, the data source manager, error handler, and progress monitor are candidates for replacement by a surrounding application. *** Decompression input and output separation *** To support efficient incremental display of progressive JPEG files, the decompressor is divided into two sections that can run independently: 1. Data input includes marker parsing, entropy decoding, and input into the coefficient controller's DCT coefficient buffer. Note that this processing is relatively cheap and fast. 2. Data output reads from the DCT coefficient buffer and performs the IDCT and all postprocessing steps. For a progressive JPEG file, the data input processing is allowed to get arbitrarily far ahead of the data output processing. (This occurs only if the application calls jpeg_consume_input(); otherwise input and output run in lockstep, since the input section is called only when the output section needs more data.) In this way the application can avoid making extra display passes when data is arriving faster than the display pass can run. Furthermore, it is possible to abort an output pass without losing anything, since the coefficient buffer is read-only as far as the output section is concerned. See libjpeg.txt for more detail. A full-image coefficient array is only created if the JPEG file has multiple scans (or if the application specifies buffered-image mode anyway). When reading a single-scan file, the coefficient controller normally creates only a one-MCU buffer, so input and output processing must run in lockstep in this case. jpeg_consume_input() is effectively a no-op in this situation. The main impact of dividing the decompressor in this fashion is that we must be very careful with shared variables in the cinfo data structure. Each variable that can change during the course of decompression must be classified as belonging to data input or data output, and each section must look only at its own variables. For example, the data output section may not depend on any of the variables that describe the current scan in the JPEG file, because these may change as the data input section advances into a new scan. The progress monitor is (somewhat arbitrarily) defined to treat input of the file as one pass when buffered-image mode is not used, and to ignore data input work completely when buffered-image mode is used. Note that the library has no reliable way to predict the number of passes when dealing with a progressive JPEG file, nor can it predict the number of output passes in buffered-image mode. So the work estimate is inherently bogus anyway. No comparable division is currently made in the compression library, because there isn't any real need for it. *** Data formats *** Arrays of pixel sample values use the following data structure: typedef something JSAMPLE; a pixel component value, 0..MAXJSAMPLE typedef JSAMPLE *JSAMPROW; ptr to a row of samples typedef JSAMPROW *JSAMPARRAY; ptr to a list of rows typedef JSAMPARRAY *JSAMPIMAGE; ptr to a list of color-component arrays The basic element type JSAMPLE will typically be one of unsigned char, (signed) char, or short. Short will be used if samples wider than 8 bits are to be supported (this is a compile-time option). Otherwise, unsigned char is used if possible. If the compiler only supports signed chars, then it is necessary to mask off the value when reading. Thus, all reads of JSAMPLE values must be coded as "GETJSAMPLE(value)", where the macro will be defined as "((value) & 0xFF)" on signed-char machines and "((int) (value))" elsewhere. With these conventions, JSAMPLE values can be assumed to be >= 0. This helps simplify correct rounding during downsampling, etc. The JPEG standard's specification that sample values run from -128..127 is accommodated by subtracting 128 from the sample value in the DCT step. Similarly, during decompression the output of the IDCT step will be immediately shifted back to 0..255. (NB: different values are required when 12-bit samples are in use. The code is written in terms of MAXJSAMPLE and CENTERJSAMPLE, which will be defined as 255 and 128 respectively in an 8-bit implementation, and as 4095 and 2048 in a 12-bit implementation.) We use a pointer per row, rather than a two-dimensional JSAMPLE array. This choice costs only a small amount of memory and has several benefits: * Code using the data structure doesn't need to know the allocated width of the rows. This simplifies edge expansion/compression, since we can work in an array that's wider than the logical picture width. * Indexing doesn't require multiplication; this is a performance win on many machines. * Arrays with more than 64K total elements can be supported even on machines where malloc() cannot allocate chunks larger than 64K. * The rows forming a component array may be allocated at different times without extra copying. This trick allows some speedups in smoothing steps that need access to the previous and next rows. Note that each color component is stored in a separate array; we don't use the traditional layout in which the components of a pixel are stored together. This simplifies coding of modules that work on each component independently, because they don't need to know how many components there are. Furthermore, we can read or write each component to a temporary file independently, which is helpful when dealing with noninterleaved JPEG files. In general, a specific sample value is accessed by code such as GETJSAMPLE(image[colorcomponent][row][col]) where col is measured from the image left edge, but row is measured from the first sample row currently in memory. Either of the first two indexings can be precomputed by copying the relevant pointer. Since most image-processing applications prefer to work on images in which the components of a pixel are stored together, the data passed to or from the surrounding application uses the traditional convention: a single pixel is represented by N consecutive JSAMPLE values, and an image row is an array of (# of color components)*(image width) JSAMPLEs. One or more rows of data can be represented by a pointer of type JSAMPARRAY in this scheme. This scheme is converted to component-wise storage inside the JPEG library. (Applications that want to skip JPEG preprocessing or postprocessing will have to contend with component-wise storage.) Arrays of DCT-coefficient values use the following data structure: typedef short JCOEF; a 16-bit signed integer typedef JCOEF JBLOCK[DCTSIZE2]; an 8x8 block of coefficients typedef JBLOCK *JBLOCKROW; ptr to one horizontal row of 8x8 blocks typedef JBLOCKROW *JBLOCKARRAY; ptr to a list of such rows typedef JBLOCKARRAY *JBLOCKIMAGE; ptr to a list of color component arrays The underlying type is at least a 16-bit signed integer; while "short" is big enough on all machines of interest, on some machines it is preferable to use "int" for speed reasons, despite the storage cost. Coefficients are grouped into 8x8 blocks (but we always use #defines DCTSIZE and DCTSIZE2 rather than "8" and "64"). The contents of a coefficient block may be in either "natural" or zigzagged order, and may be true values or divided by the quantization coefficients, depending on where the block is in the processing pipeline. In the current library, coefficient blocks are kept in natural order everywhere; the entropy codecs zigzag or dezigzag the data as it is written or read. The blocks contain quantized coefficients everywhere outside the DCT/IDCT subsystems. (This latter decision may need to be revisited to support variable quantization a la JPEG Part 3.) Notice that the allocation unit is now a row of 8x8 coefficient blocks, corresponding to block_size rows of samples. Otherwise the structure is much the same as for samples, and for the same reasons. On machines where malloc() can't handle a request bigger than 64Kb, this data structure limits us to rows of less than 512 JBLOCKs, or a picture width of 4000+ pixels. This seems an acceptable restriction. On 80x86 machines, the bottom-level pointer types (JSAMPROW and JBLOCKROW) must be declared as "far" pointers, but the upper levels can be "near" (implying that the pointer lists are allocated in the DS segment). We use a #define symbol FAR, which expands to the "far" keyword when compiling on 80x86 machines and to nothing elsewhere. *** Suspendable processing *** In some applications it is desirable to use the JPEG library as an incremental, memory-to-memory filter. In this situation the data source or destination may be a limited-size buffer, and we can't rely on being able to empty or refill the buffer at arbitrary times. Instead the application would like to have control return from the library at buffer overflow/underrun, and then resume compression or decompression at a later time. This scenario is supported for simple cases. (For anything more complex, we recommend that the application "bite the bullet" and develop real multitasking capability.) The libjpeg.txt file goes into more detail about the usage and limitations of this capability; here we address the implications for library structure. The essence of the problem is that the entropy codec (coder or decoder) must be prepared to stop at arbitrary times. In turn, the controllers that call the entropy codec must be able to stop before having produced or consumed all the data that they normally would handle in one call. That part is reasonably straightforward: we make the controller call interfaces include "progress counters" which indicate the number of data chunks successfully processed, and we require callers to test the counter rather than just assume all of the data was processed. Rather than trying to restart at an arbitrary point, the current Huffman codecs are designed to restart at the beginning of the current MCU after a suspension due to buffer overflow/underrun. At the start of each call, the codec's internal state is loaded from permanent storage (in the JPEG object structures) into local variables. On successful completion of the MCU, the permanent state is updated. (This copying is not very expensive, and may even lead to *improved* performance if the local variables can be registerized.) If a suspension occurs, the codec simply returns without updating the state, thus effectively reverting to the start of the MCU. Note that this implies leaving some data unprocessed in the source/destination buffer (ie, the compressed partial MCU). The data source/destination module interfaces are specified so as to make this possible. This also implies that the data buffer must be large enough to hold a worst-case compressed MCU; a couple thousand bytes should be enough. In a successive-approximation AC refinement scan, the progressive Huffman decoder has to be able to undo assignments of newly nonzero coefficients if it suspends before the MCU is complete, since decoding requires distinguishing previously-zero and previously-nonzero coefficients. This is a bit tedious but probably won't have much effect on performance. Other variants of Huffman decoding need not worry about this, since they will just store the same values again if forced to repeat the MCU. This approach would probably not work for an arithmetic codec, since its modifiable state is quite large and couldn't be copied cheaply. Instead it would have to suspend and resume exactly at the point of the buffer end. The JPEG marker reader is designed to cope with suspension at an arbitrary point. It does so by backing up to the start of the marker parameter segment, so the data buffer must be big enough to hold the largest marker of interest. Again, a couple KB should be adequate. (A special "skip" convention is used to bypass COM and APPn markers, so these can be larger than the buffer size without causing problems; otherwise a 64K buffer would be needed in the worst case.) The JPEG marker writer currently does *not* cope with suspension. We feel that this is not necessary; it is much easier simply to require the application to ensure there is enough buffer space before starting. (An empty 2K buffer is more than sufficient for the header markers; and ensuring there are a dozen or two bytes available before calling jpeg_finish_compress() will suffice for the trailer.) This would not work for writing multi-scan JPEG files, but we simply do not intend to support that capability with suspension. *** Memory manager services *** The JPEG library's memory manager controls allocation and deallocation of memory, and it manages large "virtual" data arrays on machines where the operating system does not provide virtual memory. Note that the same memory manager serves both compression and decompression operations. In all cases, allocated objects are tied to a particular compression or decompression master record, and they will be released when that master record is destroyed. The memory manager does not provide explicit deallocation of objects. Instead, objects are created in "pools" of free storage, and a whole pool can be freed at once. This approach helps prevent storage-leak bugs, and it speeds up operations whenever malloc/free are slow (as they often are). The pools can be regarded as lifetime identifiers for objects. Two pools/lifetimes are defined: * JPOOL_PERMANENT lasts until master record is destroyed * JPOOL_IMAGE lasts until done with image (JPEG datastream) Permanent lifetime is used for parameters and tables that should be carried across from one datastream to another; this includes all application-visible parameters. Image lifetime is used for everything else. (A third lifetime, JPOOL_PASS = one processing pass, was originally planned. However it was dropped as not being worthwhile. The actual usage patterns are such that the peak memory usage would be about the same anyway; and having per-pass storage substantially complicates the virtual memory allocation rules --- see below.) The memory manager deals with three kinds of object: 1. "Small" objects. Typically these require no more than 10K-20K total. 2. "Large" objects. These may require tens to hundreds of K depending on image size. Semantically they behave the same as small objects, but we distinguish them for two reasons: * On MS-DOS machines, large objects are referenced by FAR pointers, small objects by NEAR pointers. * Pool allocation heuristics may differ for large and small objects. Note that individual "large" objects cannot exceed the size allowed by type size_t, which may be 64K or less on some machines. 3. "Virtual" objects. These are large 2-D arrays of JSAMPLEs or JBLOCKs (typically large enough for the entire image being processed). The memory manager provides stripwise access to these arrays. On machines without virtual memory, the rest of the array may be swapped out to a temporary file. (Note: JSAMPARRAY and JBLOCKARRAY data structures are a combination of large objects for the data proper and small objects for the row pointers. For convenience and speed, the memory manager provides single routines to create these structures. Similarly, virtual arrays include a small control block and a JSAMPARRAY or JBLOCKARRAY working buffer, all created with one call.) In the present implementation, virtual arrays are only permitted to have image lifespan. (Permanent lifespan would not be reasonable, and pass lifespan is not very useful since a virtual array's raison d'etre is to store data for multiple passes through the image.) We also expect that only "small" objects will be given permanent lifespan, though this restriction is not required by the memory manager. In a non-virtual-memory machine, some performance benefit can be gained by making the in-memory buffers for virtual arrays be as large as possible. (For small images, the buffers might fit entirely in memory, so blind swapping would be very wasteful.) The memory manager will adjust the height of the buffers to fit within a prespecified maximum memory usage. In order to do this in a reasonably optimal fashion, the manager needs to allocate all of the virtual arrays at once. Therefore, there isn't a one-step allocation routine for virtual arrays; instead, there is a "request" routine that simply allocates the control block, and a "realize" routine (called just once) that determines space allocation and creates all of the actual buffers. The realize routine must allow for space occupied by non-virtual large objects. (We don't bother to factor in the space needed for small objects, on the grounds that it isn't worth the trouble.) To support all this, we establish the following protocol for doing business with the memory manager: 1. Modules must request virtual arrays (which may have only image lifespan) during the initial setup phase, i.e., in their jinit_xxx routines. 2. All "large" objects (including JSAMPARRAYs and JBLOCKARRAYs) must also be allocated during initial setup. 3. realize_virt_arrays will be called at the completion of initial setup. The above conventions ensure that sufficient information is available for it to choose a good size for virtual array buffers. Small objects of any lifespan may be allocated at any time. We expect that the total space used for small objects will be small enough to be negligible in the realize_virt_arrays computation. In a virtual-memory machine, we simply pretend that the available space is infinite, thus causing realize_virt_arrays to decide that it can allocate all the virtual arrays as full-size in-memory buffers. The overhead of the virtual-array access protocol is very small when no swapping occurs. A virtual array can be specified to be "pre-zeroed"; when this flag is set, never-yet-written sections of the array are set to zero before being made available to the caller. If this flag is not set, never-written sections of the array contain garbage. (This feature exists primarily because the equivalent logic would otherwise be needed in jdcoefct.c for progressive JPEG mode; we may as well make it available for possible other uses.) The first write pass on a virtual array is required to occur in top-to-bottom order; read passes, as well as any write passes after the first one, may access the array in any order. This restriction exists partly to simplify the virtual array control logic, and partly because some file systems may not support seeking beyond the current end-of-file in a temporary file. The main implication of this restriction is that rearrangement of rows (such as converting top-to-bottom data order to bottom-to-top) must be handled while reading data out of the virtual array, not while putting it in. *** Memory manager internal structure *** To isolate system dependencies as much as possible, we have broken the memory manager into two parts. There is a reasonably system-independent "front end" (jmemmgr.c) and a "back end" that contains only the code likely to change across systems. All of the memory management methods outlined above are implemented by the front end. The back end provides the following routines for use by the front end (none of these routines are known to the rest of the JPEG code): jpeg_mem_init, jpeg_mem_term system-dependent initialization/shutdown jpeg_get_small, jpeg_free_small interface to malloc and free library routines (or their equivalents) jpeg_get_large, jpeg_free_large interface to FAR malloc/free in MSDOS machines; else usually the same as jpeg_get_small/jpeg_free_small jpeg_mem_available estimate available memory jpeg_open_backing_store create a backing-store object read_backing_store, manipulate a backing-store object write_backing_store, close_backing_store On some systems there will be more than one type of backing-store object (specifically, in MS-DOS a backing store file might be an area of extended memory as well as a disk file). jpeg_open_backing_store is responsible for choosing how to implement a given object. The read/write/close routines are method pointers in the structure that describes a given object; this lets them be different for different object types. It may be necessary to ensure that backing store objects are explicitly released upon abnormal program termination. For example, MS-DOS won't free extended memory by itself. To support this, we will expect the main program or surrounding application to arrange to call self_destruct (typically via jpeg_destroy) upon abnormal termination. This may require a SIGINT signal handler or equivalent. We don't want to have the back end module install its own signal handler, because that would pre-empt the surrounding application's ability to control signal handling. The IJG distribution includes several memory manager back end implementations. Usually the same back end should be suitable for all applications on a given system, but it is possible for an application to supply its own back end at need. *** Implications of DNL marker *** Some JPEG files may use a DNL marker to postpone definition of the image height (this would be useful for a fax-like scanner's output, for instance). In these files the SOF marker claims the image height is 0, and you only find out the true image height at the end of the first scan. We could read these files as follows: 1. Upon seeing zero image height, replace it by 65535 (the maximum allowed). 2. When the DNL is found, update the image height in the global image descriptor. This implies that control modules must avoid making copies of the image height, and must re-test for termination after each MCU row. This would be easy enough to do. In cases where image-size data structures are allocated, this approach will result in very inefficient use of virtual memory or much-larger-than-necessary temporary files. This seems acceptable for something that probably won't be a mainstream usage. People might have to forgo use of memory-hogging options (such as two-pass color quantization or noninterleaved JPEG files) if they want efficient conversion of such files. (One could improve efficiency by demanding a user-supplied upper bound for the height, less than 65536; in most cases it could be much less.) The standard also permits the SOF marker to overestimate the image height, with a DNL to give the true, smaller height at the end of the first scan. This would solve the space problems if the overestimate wasn't too great. However, it implies that you don't even know whether DNL will be used. This leads to a couple of very serious objections: 1. Testing for a DNL marker must occur in the inner loop of the decompressor's Huffman decoder; this implies a speed penalty whether the feature is used or not. 2. There is no way to hide the last-minute change in image height from an application using the decoder. Thus *every* application using the IJG library would suffer a complexity penalty whether it cared about DNL or not. We currently do not support DNL because of these problems. A different approach is to insist that DNL-using files be preprocessed by a separate program that reads ahead to the DNL, then goes back and fixes the SOF marker. This is a much simpler solution and is probably far more efficient. Even if one wants piped input, buffering the first scan of the JPEG file needs a lot smaller temp file than is implied by the maximum-height method. For this approach we'd simply treat DNL as a no-op in the decompressor (at most, check that it matches the SOF image height). We will not worry about making the compressor capable of outputting DNL. Something similar to the first scheme above could be applied if anyone ever wants to make that work. fltk-1.4.3/jpeg/jaricom.c0000644000175000017500000001173215004135251015326 0ustar albrechtalbrecht/* * jaricom.c * * Developed 1997-2011 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains probability estimation tables for common use in * arithmetic entropy encoding and decoding routines. * * This data represents Table D.3 in the JPEG spec (D.2 in the draft), * ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81, and Table 24 * in the JBIG spec, ISO/IEC IS 11544 and CCITT Recommendation ITU-T T.82. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* The following #define specifies the packing of the four components * into the compact INT32 representation. * Note that this formula must match the actual arithmetic encoder * and decoder implementation. The implementation has to be changed * if this formula is changed. * The current organization is leaned on Markus Kuhn's JBIG * implementation (jbig_tab.c). */ #define V(i,a,b,c,d) (((INT32)a << 16) | ((INT32)c << 8) | ((INT32)d << 7) | b) const INT32 jpeg_aritab[113+1] = { /* * Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS */ V( 0, 0x5a1d, 1, 1, 1 ), V( 1, 0x2586, 14, 2, 0 ), V( 2, 0x1114, 16, 3, 0 ), V( 3, 0x080b, 18, 4, 0 ), V( 4, 0x03d8, 20, 5, 0 ), V( 5, 0x01da, 23, 6, 0 ), V( 6, 0x00e5, 25, 7, 0 ), V( 7, 0x006f, 28, 8, 0 ), V( 8, 0x0036, 30, 9, 0 ), V( 9, 0x001a, 33, 10, 0 ), V( 10, 0x000d, 35, 11, 0 ), V( 11, 0x0006, 9, 12, 0 ), V( 12, 0x0003, 10, 13, 0 ), V( 13, 0x0001, 12, 13, 0 ), V( 14, 0x5a7f, 15, 15, 1 ), V( 15, 0x3f25, 36, 16, 0 ), V( 16, 0x2cf2, 38, 17, 0 ), V( 17, 0x207c, 39, 18, 0 ), V( 18, 0x17b9, 40, 19, 0 ), V( 19, 0x1182, 42, 20, 0 ), V( 20, 0x0cef, 43, 21, 0 ), V( 21, 0x09a1, 45, 22, 0 ), V( 22, 0x072f, 46, 23, 0 ), V( 23, 0x055c, 48, 24, 0 ), V( 24, 0x0406, 49, 25, 0 ), V( 25, 0x0303, 51, 26, 0 ), V( 26, 0x0240, 52, 27, 0 ), V( 27, 0x01b1, 54, 28, 0 ), V( 28, 0x0144, 56, 29, 0 ), V( 29, 0x00f5, 57, 30, 0 ), V( 30, 0x00b7, 59, 31, 0 ), V( 31, 0x008a, 60, 32, 0 ), V( 32, 0x0068, 62, 33, 0 ), V( 33, 0x004e, 63, 34, 0 ), V( 34, 0x003b, 32, 35, 0 ), V( 35, 0x002c, 33, 9, 0 ), V( 36, 0x5ae1, 37, 37, 1 ), V( 37, 0x484c, 64, 38, 0 ), V( 38, 0x3a0d, 65, 39, 0 ), V( 39, 0x2ef1, 67, 40, 0 ), V( 40, 0x261f, 68, 41, 0 ), V( 41, 0x1f33, 69, 42, 0 ), V( 42, 0x19a8, 70, 43, 0 ), V( 43, 0x1518, 72, 44, 0 ), V( 44, 0x1177, 73, 45, 0 ), V( 45, 0x0e74, 74, 46, 0 ), V( 46, 0x0bfb, 75, 47, 0 ), V( 47, 0x09f8, 77, 48, 0 ), V( 48, 0x0861, 78, 49, 0 ), V( 49, 0x0706, 79, 50, 0 ), V( 50, 0x05cd, 48, 51, 0 ), V( 51, 0x04de, 50, 52, 0 ), V( 52, 0x040f, 50, 53, 0 ), V( 53, 0x0363, 51, 54, 0 ), V( 54, 0x02d4, 52, 55, 0 ), V( 55, 0x025c, 53, 56, 0 ), V( 56, 0x01f8, 54, 57, 0 ), V( 57, 0x01a4, 55, 58, 0 ), V( 58, 0x0160, 56, 59, 0 ), V( 59, 0x0125, 57, 60, 0 ), V( 60, 0x00f6, 58, 61, 0 ), V( 61, 0x00cb, 59, 62, 0 ), V( 62, 0x00ab, 61, 63, 0 ), V( 63, 0x008f, 61, 32, 0 ), V( 64, 0x5b12, 65, 65, 1 ), V( 65, 0x4d04, 80, 66, 0 ), V( 66, 0x412c, 81, 67, 0 ), V( 67, 0x37d8, 82, 68, 0 ), V( 68, 0x2fe8, 83, 69, 0 ), V( 69, 0x293c, 84, 70, 0 ), V( 70, 0x2379, 86, 71, 0 ), V( 71, 0x1edf, 87, 72, 0 ), V( 72, 0x1aa9, 87, 73, 0 ), V( 73, 0x174e, 72, 74, 0 ), V( 74, 0x1424, 72, 75, 0 ), V( 75, 0x119c, 74, 76, 0 ), V( 76, 0x0f6b, 74, 77, 0 ), V( 77, 0x0d51, 75, 78, 0 ), V( 78, 0x0bb6, 77, 79, 0 ), V( 79, 0x0a40, 77, 48, 0 ), V( 80, 0x5832, 80, 81, 1 ), V( 81, 0x4d1c, 88, 82, 0 ), V( 82, 0x438e, 89, 83, 0 ), V( 83, 0x3bdd, 90, 84, 0 ), V( 84, 0x34ee, 91, 85, 0 ), V( 85, 0x2eae, 92, 86, 0 ), V( 86, 0x299a, 93, 87, 0 ), V( 87, 0x2516, 86, 71, 0 ), V( 88, 0x5570, 88, 89, 1 ), V( 89, 0x4ca9, 95, 90, 0 ), V( 90, 0x44d9, 96, 91, 0 ), V( 91, 0x3e22, 97, 92, 0 ), V( 92, 0x3824, 99, 93, 0 ), V( 93, 0x32b4, 99, 94, 0 ), V( 94, 0x2e17, 93, 86, 0 ), V( 95, 0x56a8, 95, 96, 1 ), V( 96, 0x4f46, 101, 97, 0 ), V( 97, 0x47e5, 102, 98, 0 ), V( 98, 0x41cf, 103, 99, 0 ), V( 99, 0x3c3d, 104, 100, 0 ), V( 100, 0x375e, 99, 93, 0 ), V( 101, 0x5231, 105, 102, 0 ), V( 102, 0x4c0f, 106, 103, 0 ), V( 103, 0x4639, 107, 104, 0 ), V( 104, 0x415e, 103, 99, 0 ), V( 105, 0x5627, 105, 106, 1 ), V( 106, 0x50e7, 108, 107, 0 ), V( 107, 0x4b85, 109, 103, 0 ), V( 108, 0x5597, 110, 109, 0 ), V( 109, 0x504f, 111, 107, 0 ), V( 110, 0x5a10, 110, 111, 1 ), V( 111, 0x5522, 112, 109, 0 ), V( 112, 0x59eb, 112, 111, 1 ), /* * This last entry is used for fixed probability estimate of 0.5 * as suggested in Section 10.3 Table 5 of ITU-T Rec. T.851. */ V( 113, 0x5a1d, 113, 113, 0 ) }; fltk-1.4.3/jpeg/jquant2.c0000644000175000017500000013651615004135251015276 0ustar albrechtalbrecht/* * jquant2.c * * Copyright (C) 1991-1996, Thomas G. Lane. * Modified 2011-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains 2-pass color quantization (color mapping) routines. * These routines provide selection of a custom color map for an image, * followed by mapping of the image to that color map, with optional * Floyd-Steinberg dithering. * It is also possible to use just the second pass to map to an arbitrary * externally-given color map. * * Note: ordered dithering is not supported, since there isn't any fast * way to compute intercolor distances; it's unclear that ordered dither's * fundamental assumptions even hold with an irregularly spaced color map. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #ifdef QUANT_2PASS_SUPPORTED /* * This module implements the well-known Heckbert paradigm for color * quantization. Most of the ideas used here can be traced back to * Heckbert's seminal paper * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. * * In the first pass over the image, we accumulate a histogram showing the * usage count of each possible color. To keep the histogram to a reasonable * size, we reduce the precision of the input; typical practice is to retain * 5 or 6 bits per color, so that 8 or 4 different input values are counted * in the same histogram cell. * * Next, the color-selection step begins with a box representing the whole * color space, and repeatedly splits the "largest" remaining box until we * have as many boxes as desired colors. Then the mean color in each * remaining box becomes one of the possible output colors. * * The second pass over the image maps each input pixel to the closest output * color (optionally after applying a Floyd-Steinberg dithering correction). * This mapping is logically trivial, but making it go fast enough requires * considerable care. * * Heckbert-style quantizers vary a good deal in their policies for choosing * the "largest" box and deciding where to cut it. The particular policies * used here have proved out well in experimental comparisons, but better ones * may yet be found. * * In earlier versions of the IJG code, this module quantized in YCbCr color * space, processing the raw upsampled data without a color conversion step. * This allowed the color conversion math to be done only once per colormap * entry, not once per pixel. However, that optimization precluded other * useful optimizations (such as merging color conversion with upsampling) * and it also interfered with desired capabilities such as quantizing to an * externally-supplied colormap. We have therefore abandoned that approach. * The present code works in the post-conversion color space, typically RGB. * * To improve the visual quality of the results, we actually work in scaled * RGB space, giving G distances more weight than R, and R in turn more than * B. To do everything in integer math, we must use integer scale factors. * The 2/3/1 scale factors used here correspond loosely to the relative * weights of the colors in the NTSC grayscale equation. * If you want to use this code to quantize a non-RGB color space, you'll * probably need to change these scale factors. */ #define R_SCALE 2 /* scale R distances by this much */ #define G_SCALE 3 /* scale G distances by this much */ #define B_SCALE 1 /* and B by this much */ /* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B * and B,G,R orders. If you define some other weird order in jmorecfg.h, * you'll get compile errors until you extend this logic. In that case * you'll probably want to tweak the histogram sizes too. */ #if RGB_RED == 0 #define C0_SCALE R_SCALE #endif #if RGB_BLUE == 0 #define C0_SCALE B_SCALE #endif #if RGB_GREEN == 1 #define C1_SCALE G_SCALE #endif #if RGB_RED == 2 #define C2_SCALE R_SCALE #endif #if RGB_BLUE == 2 #define C2_SCALE B_SCALE #endif /* * First we have the histogram data structure and routines for creating it. * * The number of bits of precision can be adjusted by changing these symbols. * We recommend keeping 6 bits for G and 5 each for R and B. * If you have plenty of memory and cycles, 6 bits all around gives marginally * better results; if you are short of memory, 5 bits all around will save * some space but degrade the results. * To maintain a fully accurate histogram, we'd need to allocate a "long" * (preferably unsigned long) for each cell. In practice this is overkill; * we can get by with 16 bits per cell. Few of the cell counts will overflow, * and clamping those that do overflow to the maximum value will give close- * enough results. This reduces the recommended histogram size from 256Kb * to 128Kb, which is a useful savings on PC-class machines. * (In the second pass the histogram space is re-used for pixel mapping data; * in that capacity, each cell must be able to store zero to the number of * desired colors. 16 bits/cell is plenty for that too.) * Since the JPEG code is intended to run in small memory model on 80x86 * machines, we can't just allocate the histogram in one chunk. Instead * of a true 3-D array, we use a row of pointers to 2-D arrays. Each * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that * on 80x86 machines, the pointer row is in near memory but the actual * arrays are in far memory (same arrangement as we use for image arrays). */ #define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ /* These will do the right thing for either R,G,B or B,G,R color order, * but you may not like the results for other color orders. */ #define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ #define HIST_C1_BITS 6 /* bits of precision in G histogram */ #define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ /* Number of elements along histogram axes. */ #define HIST_C0_ELEMS (1<cquantize; register JSAMPROW ptr; register histptr histp; register hist3d histogram = cquantize->histogram; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { ptr = input_buf[row]; for (col = width; col > 0; col--) { /* get pixel value and index into the histogram */ histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] [GETJSAMPLE(ptr[1]) >> C1_SHIFT] [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; /* increment, check for overflow and undo increment if so. */ if (++(*histp) <= 0) (*histp)--; ptr += 3; } } } /* * Next we have the really interesting routines: selection of a colormap * given the completed histogram. * These routines work with a list of "boxes", each representing a rectangular * subset of the input color space (to histogram precision). */ typedef struct { /* The bounds of the box (inclusive); expressed as histogram indexes */ int c0min, c0max; int c1min, c1max; int c2min, c2max; /* The volume (actually 2-norm) of the box */ INT32 volume; /* The number of nonzero histogram cells within this box */ long colorcount; } box; typedef box * boxptr; LOCAL(boxptr) find_biggest_color_pop (boxptr boxlist, int numboxes) /* Find the splittable box with the largest color population */ /* Returns NULL if no splittable boxes remain */ { register boxptr boxp; register int i; register long maxc = 0; boxptr which = NULL; for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->colorcount > maxc && boxp->volume > 0) { which = boxp; maxc = boxp->colorcount; } } return which; } LOCAL(boxptr) find_biggest_volume (boxptr boxlist, int numboxes) /* Find the splittable box with the largest (scaled) volume */ /* Returns NULL if no splittable boxes remain */ { register boxptr boxp; register int i; register INT32 maxv = 0; boxptr which = NULL; for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->volume > maxv) { which = boxp; maxv = boxp->volume; } } return which; } LOCAL(void) update_box (j_decompress_ptr cinfo, boxptr boxp) /* Shrink the min/max bounds of a box to enclose only nonzero elements, */ /* and recompute its volume and population */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; histptr histp; int c0,c1,c2; int c0min,c0max,c1min,c1max,c2min,c2max; INT32 dist0,dist1,dist2; long ccount; c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; if (c0max > c0min) for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c0min = c0min = c0; goto have_c0min; } } have_c0min: if (c0max > c0min) for (c0 = c0max; c0 >= c0min; c0--) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c0max = c0max = c0; goto have_c0max; } } have_c0max: if (c1max > c1min) for (c1 = c1min; c1 <= c1max; c1++) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c1min = c1min = c1; goto have_c1min; } } have_c1min: if (c1max > c1min) for (c1 = c1max; c1 >= c1min; c1--) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c1max = c1max = c1; goto have_c1max; } } have_c1max: if (c2max > c2min) for (c2 = c2min; c2 <= c2max; c2++) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1min][c2]; for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) if (*histp != 0) { boxp->c2min = c2min = c2; goto have_c2min; } } have_c2min: if (c2max > c2min) for (c2 = c2max; c2 >= c2min; c2--) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1min][c2]; for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) if (*histp != 0) { boxp->c2max = c2max = c2; goto have_c2max; } } have_c2max: /* Update box volume. * We use 2-norm rather than real volume here; this biases the method * against making long narrow boxes, and it has the side benefit that * a box is splittable iff norm > 0. * Since the differences are expressed in histogram-cell units, * we have to shift back to JSAMPLE units to get consistent distances; * after which, we scale according to the selected distance scale factors. */ dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; /* Now scan remaining volume of box and compute population */ ccount = 0; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++, histp++) if (*histp != 0) { ccount++; } } boxp->colorcount = ccount; } LOCAL(int) median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, int desired_colors) /* Repeatedly select and split the largest box until we have enough boxes */ { int n,lb; int c0,c1,c2,cmax; register boxptr b1,b2; while (numboxes < desired_colors) { /* Select box to split. * Current algorithm: by population for first half, then by volume. */ if (numboxes*2 <= desired_colors) { b1 = find_biggest_color_pop(boxlist, numboxes); } else { b1 = find_biggest_volume(boxlist, numboxes); } if (b1 == NULL) /* no splittable boxes left! */ break; b2 = &boxlist[numboxes]; /* where new box will go */ /* Copy the color bounds to the new box. */ b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; /* Choose which axis to split the box on. * Current algorithm: longest scaled axis. * See notes in update_box about scaling distances. */ c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; /* We want to break any ties in favor of green, then red, blue last. * This code does the right thing for R,G,B or B,G,R color orders only. */ #if RGB_RED == 0 cmax = c1; n = 1; if (c0 > cmax) { cmax = c0; n = 0; } if (c2 > cmax) { n = 2; } #else cmax = c1; n = 1; if (c2 > cmax) { cmax = c2; n = 2; } if (c0 > cmax) { n = 0; } #endif /* Choose split point along selected axis, and update box bounds. * Current algorithm: split at halfway point. * (Since the box has been shrunk to minimum volume, * any split will produce two nonempty subboxes.) * Note that lb value is max for lower box, so must be < old max. */ switch (n) { case 0: lb = (b1->c0max + b1->c0min) / 2; b1->c0max = lb; b2->c0min = lb+1; break; case 1: lb = (b1->c1max + b1->c1min) / 2; b1->c1max = lb; b2->c1min = lb+1; break; case 2: lb = (b1->c2max + b1->c2min) / 2; b1->c2max = lb; b2->c2min = lb+1; break; } /* Update stats for boxes */ update_box(cinfo, b1); update_box(cinfo, b2); numboxes++; } return numboxes; } LOCAL(void) compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) /* Compute representative color for a box, put it in colormap[icolor] */ { /* Current algorithm: mean weighted by pixels (not colors) */ /* Note it is important to get the rounding correct! */ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; histptr histp; int c0,c1,c2; int c0min,c0max,c1min,c1max,c2min,c2max; long count; long total = 0; long c0total = 0; long c1total = 0; long c2total = 0; c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) { if ((count = *histp++) != 0) { total += count; c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; } } } cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); } LOCAL(void) select_colors (j_decompress_ptr cinfo, int desired_colors) /* Master routine for color selection */ { boxptr boxlist; int numboxes; int i; /* Allocate workspace for box list */ boxlist = (boxptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); /* Initialize one box containing whole space */ numboxes = 1; boxlist[0].c0min = 0; boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; boxlist[0].c1min = 0; boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; boxlist[0].c2min = 0; boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; /* Shrink it to actually-used volume and set its statistics */ update_box(cinfo, & boxlist[0]); /* Perform median-cut to produce final box list */ numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); /* Compute the representative color for each box, fill colormap */ for (i = 0; i < numboxes; i++) compute_color(cinfo, & boxlist[i], i); cinfo->actual_number_of_colors = numboxes; TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); } /* * These routines are concerned with the time-critical task of mapping input * colors to the nearest color in the selected colormap. * * We re-use the histogram space as an "inverse color map", essentially a * cache for the results of nearest-color searches. All colors within a * histogram cell will be mapped to the same colormap entry, namely the one * closest to the cell's center. This may not be quite the closest entry to * the actual input color, but it's almost as good. A zero in the cache * indicates we haven't found the nearest color for that cell yet; the array * is cleared to zeroes before starting the mapping pass. When we find the * nearest color for a cell, its colormap index plus one is recorded in the * cache for future use. The pass2 scanning routines call fill_inverse_cmap * when they need to use an unfilled entry in the cache. * * Our method of efficiently finding nearest colors is based on the "locally * sorted search" idea described by Heckbert and on the incremental distance * calculation described by Spencer W. Thomas in chapter III.1 of Graphics * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that * the distances from a given colormap entry to each cell of the histogram can * be computed quickly using an incremental method: the differences between * distances to adjacent cells themselves differ by a constant. This allows a * fairly fast implementation of the "brute force" approach of computing the * distance from every colormap entry to every histogram cell. Unfortunately, * it needs a work array to hold the best-distance-so-far for each histogram * cell (because the inner loop has to be over cells, not colormap entries). * The work array elements have to be INT32s, so the work array would need * 256Kb at our recommended precision. This is not feasible in DOS machines. * * To get around these problems, we apply Thomas' method to compute the * nearest colors for only the cells within a small subbox of the histogram. * The work array need be only as big as the subbox, so the memory usage * problem is solved. Furthermore, we need not fill subboxes that are never * referenced in pass2; many images use only part of the color gamut, so a * fair amount of work is saved. An additional advantage of this * approach is that we can apply Heckbert's locality criterion to quickly * eliminate colormap entries that are far away from the subbox; typically * three-fourths of the colormap entries are rejected by Heckbert's criterion, * and we need not compute their distances to individual cells in the subbox. * The speed of this approach is heavily influenced by the subbox size: too * small means too much overhead, too big loses because Heckbert's criterion * can't eliminate as many colormap entries. Empirically the best subbox * size seems to be about 1/512th of the histogram (1/8th in each direction). * * Thomas' article also describes a refined method which is asymptotically * faster than the brute-force method, but it is also far more complex and * cannot efficiently be applied to small subboxes. It is therefore not * useful for programs intended to be portable to DOS machines. On machines * with plenty of memory, filling the whole histogram in one shot with Thomas' * refined method might be faster than the present code --- but then again, * it might not be any faster, and it's certainly more complicated. */ /* log2(histogram cells in update box) for each axis; this can be adjusted */ #define BOX_C0_LOG (HIST_C0_BITS-3) #define BOX_C1_LOG (HIST_C1_BITS-3) #define BOX_C2_LOG (HIST_C2_BITS-3) #define BOX_C0_ELEMS (1<actual_number_of_colors; int maxc0, maxc1, maxc2; int centerc0, centerc1, centerc2; int i, x, ncolors; INT32 minmaxdist, min_dist, max_dist, tdist; INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ /* Compute true coordinates of update box's upper corner and center. * Actually we compute the coordinates of the center of the upper-corner * histogram cell, which are the upper bounds of the volume we care about. * Note that since ">>" rounds down, the "center" values may be closer to * min than to max; hence comparisons to them must be "<=", not "<". */ maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); centerc0 = (minc0 + maxc0) >> 1; maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); centerc1 = (minc1 + maxc1) >> 1; maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); centerc2 = (minc2 + maxc2) >> 1; /* For each color in colormap, find: * 1. its minimum squared-distance to any point in the update box * (zero if color is within update box); * 2. its maximum squared-distance to any point in the update box. * Both of these can be found by considering only the corners of the box. * We save the minimum distance for each color in mindist[]; * only the smallest maximum distance is of interest. */ minmaxdist = 0x7FFFFFFFL; for (i = 0; i < numcolors; i++) { /* We compute the squared-c0-distance term, then add in the other two. */ x = GETJSAMPLE(cinfo->colormap[0][i]); if (x < minc0) { tdist = (x - minc0) * C0_SCALE; min_dist = tdist*tdist; tdist = (x - maxc0) * C0_SCALE; max_dist = tdist*tdist; } else if (x > maxc0) { tdist = (x - maxc0) * C0_SCALE; min_dist = tdist*tdist; tdist = (x - minc0) * C0_SCALE; max_dist = tdist*tdist; } else { /* within cell range so no contribution to min_dist */ min_dist = 0; if (x <= centerc0) { tdist = (x - maxc0) * C0_SCALE; max_dist = tdist*tdist; } else { tdist = (x - minc0) * C0_SCALE; max_dist = tdist*tdist; } } x = GETJSAMPLE(cinfo->colormap[1][i]); if (x < minc1) { tdist = (x - minc1) * C1_SCALE; min_dist += tdist*tdist; tdist = (x - maxc1) * C1_SCALE; max_dist += tdist*tdist; } else if (x > maxc1) { tdist = (x - maxc1) * C1_SCALE; min_dist += tdist*tdist; tdist = (x - minc1) * C1_SCALE; max_dist += tdist*tdist; } else { /* within cell range so no contribution to min_dist */ if (x <= centerc1) { tdist = (x - maxc1) * C1_SCALE; max_dist += tdist*tdist; } else { tdist = (x - minc1) * C1_SCALE; max_dist += tdist*tdist; } } x = GETJSAMPLE(cinfo->colormap[2][i]); if (x < minc2) { tdist = (x - minc2) * C2_SCALE; min_dist += tdist*tdist; tdist = (x - maxc2) * C2_SCALE; max_dist += tdist*tdist; } else if (x > maxc2) { tdist = (x - maxc2) * C2_SCALE; min_dist += tdist*tdist; tdist = (x - minc2) * C2_SCALE; max_dist += tdist*tdist; } else { /* within cell range so no contribution to min_dist */ if (x <= centerc2) { tdist = (x - maxc2) * C2_SCALE; max_dist += tdist*tdist; } else { tdist = (x - minc2) * C2_SCALE; max_dist += tdist*tdist; } } mindist[i] = min_dist; /* save away the results */ if (max_dist < minmaxdist) minmaxdist = max_dist; } /* Now we know that no cell in the update box is more than minmaxdist * away from some colormap entry. Therefore, only colors that are * within minmaxdist of some part of the box need be considered. */ ncolors = 0; for (i = 0; i < numcolors; i++) { if (mindist[i] <= minmaxdist) colorlist[ncolors++] = (JSAMPLE) i; } return ncolors; } LOCAL(void) find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) /* Find the closest colormap entry for each cell in the update box, * given the list of candidate colors prepared by find_nearby_colors. * Return the indexes of the closest entries in the bestcolor[] array. * This routine uses Thomas' incremental distance calculation method to * find the distance from a colormap entry to successive cells in the box. */ { int ic0, ic1, ic2; int i, icolor; register INT32 * bptr; /* pointer into bestdist[] array */ JSAMPLE * cptr; /* pointer into bestcolor[] array */ INT32 dist0, dist1; /* initial distance values */ register INT32 dist2; /* current distance in inner loop */ INT32 xx0, xx1; /* distance increments */ register INT32 xx2; INT32 inc0, inc1, inc2; /* initial values for increments */ /* This array holds the distance to the nearest-so-far color for each cell */ INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; /* Initialize best-distance for each cell of the update box */ bptr = bestdist; for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) *bptr++ = 0x7FFFFFFFL; /* For each color selected by find_nearby_colors, * compute its distance to the center of each cell in the box. * If that's less than best-so-far, update best distance and color number. */ /* Nominal steps between cell centers ("x" in Thomas article) */ #define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) #define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) #define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) for (i = 0; i < numcolors; i++) { icolor = GETJSAMPLE(colorlist[i]); /* Compute (square of) distance from minc0/c1/c2 to this color */ inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; dist0 = inc0*inc0; inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; dist0 += inc1*inc1; inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; dist0 += inc2*inc2; /* Form the initial difference increments */ inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; /* Now loop over all cells in box, updating distance per Thomas method */ bptr = bestdist; cptr = bestcolor; xx0 = inc0; for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { dist1 = dist0; xx1 = inc1; for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { dist2 = dist1; xx2 = inc2; for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { if (dist2 < *bptr) { *bptr = dist2; *cptr = (JSAMPLE) icolor; } dist2 += xx2; xx2 += 2 * STEP_C2 * STEP_C2; bptr++; cptr++; } dist1 += xx1; xx1 += 2 * STEP_C1 * STEP_C1; } dist0 += xx0; xx0 += 2 * STEP_C0 * STEP_C0; } } } LOCAL(void) fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) /* Fill the inverse-colormap entries in the update box that contains */ /* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ /* we can fill as many others as we wish.) */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; int minc0, minc1, minc2; /* lower left corner of update box */ int ic0, ic1, ic2; register JSAMPLE * cptr; /* pointer into bestcolor[] array */ register histptr cachep; /* pointer into main cache array */ /* This array lists the candidate colormap indexes. */ JSAMPLE colorlist[MAXNUMCOLORS]; int numcolors; /* number of candidate colors */ /* This array holds the actually closest colormap index for each cell. */ JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; /* Convert cell coordinates to update box ID */ c0 >>= BOX_C0_LOG; c1 >>= BOX_C1_LOG; c2 >>= BOX_C2_LOG; /* Compute true coordinates of update box's origin corner. * Actually we compute the coordinates of the center of the corner * histogram cell, which are the lower bounds of the volume we care about. */ minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); /* Determine which colormap entries are close enough to be candidates * for the nearest entry to some cell in the update box. */ numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); /* Determine the actually nearest colors. */ find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, bestcolor); /* Save the best color numbers (plus 1) in the main cache array */ c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ c1 <<= BOX_C1_LOG; c2 <<= BOX_C2_LOG; cptr = bestcolor; for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { cachep = & histogram[c0+ic0][c1+ic1][c2]; for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); } } } } /* * Map some rows of pixels to the output colormapped representation. */ METHODDEF(void) pass2_no_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; register JSAMPROW inptr, outptr; register histptr cachep; register int c0, c1, c2; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { inptr = input_buf[row]; outptr = output_buf[row]; for (col = width; col > 0; col--) { /* get pixel value and index into the cache */ c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; cachep = & histogram[c0][c1][c2]; /* If we have not seen this color before, find nearest colormap entry */ /* and update the cache */ if (*cachep == 0) fill_inverse_cmap(cinfo, c0,c1,c2); /* Now emit the colormap index for this cell */ *outptr++ = (JSAMPLE) (*cachep - 1); } } } METHODDEF(void) pass2_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ register FSERRPTR errorptr; /* => fserrors[] at column before current */ JSAMPROW inptr; /* => current input pixel */ JSAMPROW outptr; /* => current output pixel */ histptr cachep; int dir; /* +1 or -1 depending on direction */ int dir3; /* 3*dir, for advancing inptr & errorptr */ int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; JSAMPLE *range_limit = cinfo->sample_range_limit; int *error_limit = cquantize->error_limiter; JSAMPROW colormap0 = cinfo->colormap[0]; JSAMPROW colormap1 = cinfo->colormap[1]; JSAMPROW colormap2 = cinfo->colormap[2]; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { inptr = input_buf[row]; outptr = output_buf[row]; if (cquantize->on_odd_row) { /* work right to left in this row */ inptr += (width-1) * 3; /* so point to rightmost pixel */ outptr += width-1; dir = -1; dir3 = -3; errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ cquantize->on_odd_row = FALSE; /* flip for next time */ } else { /* work left to right in this row */ dir = 1; dir3 = 3; errorptr = cquantize->fserrors; /* => entry before first real column */ cquantize->on_odd_row = TRUE; /* flip for next time */ } /* Preset error values: no error propagated to first pixel from left */ cur0 = cur1 = cur2 = 0; /* and no error propagated to row below yet */ belowerr0 = belowerr1 = belowerr2 = 0; bpreverr0 = bpreverr1 = bpreverr2 = 0; for (col = width; col > 0; col--) { /* curN holds the error propagated from the previous pixel on the * current line. Add the error propagated from the previous line * to form the complete error correction term for this pixel, and * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct * for either sign of the error value. * Note: errorptr points to *previous* column's array entry. */ cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); /* Limit the error using transfer function set by init_error_limit. * See comments with init_error_limit for rationale. */ cur0 = error_limit[cur0]; cur1 = error_limit[cur1]; cur2 = error_limit[cur2]; /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. * The maximum error is +- MAXJSAMPLE (or less with error limiting); * this sets the required size of the range_limit array. */ cur0 += GETJSAMPLE(inptr[0]); cur1 += GETJSAMPLE(inptr[1]); cur2 += GETJSAMPLE(inptr[2]); cur0 = GETJSAMPLE(range_limit[cur0]); cur1 = GETJSAMPLE(range_limit[cur1]); cur2 = GETJSAMPLE(range_limit[cur2]); /* Index into the cache with adjusted pixel value */ cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; /* If we have not seen this color before, find nearest colormap */ /* entry and update the cache */ if (*cachep == 0) fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); /* Now emit the colormap index for this cell */ { register int pixcode = *cachep - 1; *outptr = (JSAMPLE) pixcode; /* Compute representation error for this pixel */ cur0 -= GETJSAMPLE(colormap0[pixcode]); cur1 -= GETJSAMPLE(colormap1[pixcode]); cur2 -= GETJSAMPLE(colormap2[pixcode]); } /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the * next-line error sums left by 1 column. */ { register LOCFSERROR bnexterr, delta; bnexterr = cur0; /* Process component 0 */ delta = cur0 * 2; cur0 += delta; /* form error * 3 */ errorptr[0] = (FSERROR) (bpreverr0 + cur0); cur0 += delta; /* form error * 5 */ bpreverr0 = belowerr0 + cur0; belowerr0 = bnexterr; cur0 += delta; /* form error * 7 */ bnexterr = cur1; /* Process component 1 */ delta = cur1 * 2; cur1 += delta; /* form error * 3 */ errorptr[1] = (FSERROR) (bpreverr1 + cur1); cur1 += delta; /* form error * 5 */ bpreverr1 = belowerr1 + cur1; belowerr1 = bnexterr; cur1 += delta; /* form error * 7 */ bnexterr = cur2; /* Process component 2 */ delta = cur2 * 2; cur2 += delta; /* form error * 3 */ errorptr[2] = (FSERROR) (bpreverr2 + cur2); cur2 += delta; /* form error * 5 */ bpreverr2 = belowerr2 + cur2; belowerr2 = bnexterr; cur2 += delta; /* form error * 7 */ } /* At this point curN contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the * next line have been shifted over. We are therefore ready to move on. */ inptr += dir3; /* Advance pixel pointers to next column */ outptr += dir; errorptr += dir3; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error values into the * final fserrors[] entry. Note we need not unload belowerrN because * it is for the dummy column before or after the actual array. */ errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ errorptr[1] = (FSERROR) bpreverr1; errorptr[2] = (FSERROR) bpreverr2; } } /* * Initialize the error-limiting transfer function (lookup table). * The raw F-S error computation can potentially compute error values of up to * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be * much less, otherwise obviously wrong pixels will be created. (Typical * effects include weird fringes at color-area boundaries, isolated bright * pixels in a dark area, etc.) The standard advice for avoiding this problem * is to ensure that the "corners" of the color cube are allocated as output * colors; then repeated errors in the same direction cannot cause cascading * error buildup. However, that only prevents the error from getting * completely out of hand; Aaron Giles reports that error limiting improves * the results even with corner colors allocated. * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty * well, but the smoother transfer function used below is even better. Thanks * to Aaron Giles for this idea. */ LOCAL(void) init_error_limit (j_decompress_ptr cinfo) /* Allocate and fill in the error_limiter table */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; int * table; int in, out; table = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ cquantize->error_limiter = table; #define STEPSIZE ((MAXJSAMPLE+1)/16) /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ out = 0; for (in = 0; in < STEPSIZE; in++, out++) { table[in] = out; table[-in] = -out; } /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { table[in] = out; table[-in] = -out; } /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ for (; in <= MAXJSAMPLE; in++) { table[in] = out; table[-in] = -out; } #undef STEPSIZE } /* * Finish up at the end of each pass. */ METHODDEF(void) finish_pass1 (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; /* Select the representative colors and fill in cinfo->colormap */ cinfo->colormap = cquantize->sv_colormap; select_colors(cinfo, cquantize->desired); /* Force next pass to zero the color index table */ cquantize->needs_zeroed = TRUE; } METHODDEF(void) finish_pass2 (j_decompress_ptr cinfo) { /* no work */ } /* * Initialize for each processing pass. */ METHODDEF(void) start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; int i; /* Only F-S dithering or no dithering is supported. */ /* If user asks for ordered dither, give him F-S. */ if (cinfo->dither_mode != JDITHER_NONE) cinfo->dither_mode = JDITHER_FS; if (is_pre_scan) { /* Set up method pointers */ cquantize->pub.color_quantize = prescan_quantize; cquantize->pub.finish_pass = finish_pass1; cquantize->needs_zeroed = TRUE; /* Always zero histogram */ } else { /* Set up method pointers */ if (cinfo->dither_mode == JDITHER_FS) cquantize->pub.color_quantize = pass2_fs_dither; else cquantize->pub.color_quantize = pass2_no_dither; cquantize->pub.finish_pass = finish_pass2; /* Make sure color count is acceptable */ i = cinfo->actual_number_of_colors; if (i < 1) ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); if (i > MAXNUMCOLORS) ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); if (cinfo->dither_mode == JDITHER_FS) { size_t arraysize = ((size_t) cinfo->output_width + (size_t) 2) * (3 * SIZEOF(FSERROR)); /* Allocate Floyd-Steinberg workspace if we didn't already. */ if (cquantize->fserrors == NULL) cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); /* Initialize the propagated errors to zero. */ FMEMZERO((void FAR *) cquantize->fserrors, arraysize); /* Make the error-limit table if we didn't already. */ if (cquantize->error_limiter == NULL) init_error_limit(cinfo); cquantize->on_odd_row = FALSE; } } /* Zero the histogram or inverse color map, if necessary */ if (cquantize->needs_zeroed) { for (i = 0; i < HIST_C0_ELEMS; i++) { FMEMZERO((void FAR *) histogram[i], HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); } cquantize->needs_zeroed = FALSE; } } /* * Switch to a new external colormap between output passes. */ METHODDEF(void) new_color_map_2_quant (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; /* Reset the inverse color map */ cquantize->needs_zeroed = TRUE; } /* * Module initialization routine for 2-pass color quantization. */ GLOBAL(void) jinit_2pass_quantizer (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize; int i; cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_cquantizer)); cinfo->cquantize = &cquantize->pub; cquantize->pub.start_pass = start_pass_2_quant; cquantize->pub.new_color_map = new_color_map_2_quant; cquantize->fserrors = NULL; /* flag optional arrays not allocated */ cquantize->error_limiter = NULL; /* Make sure jdmaster didn't give me a case I can't handle */ if (cinfo->out_color_components != 3) ERREXIT(cinfo, JERR_NOTIMPL); /* Allocate the histogram/inverse colormap storage */ cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); for (i = 0; i < HIST_C0_ELEMS; i++) { cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); } cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ /* Allocate storage for the completed colormap, if required. * We do this now since it is FAR storage and may affect * the memory manager's space calculations. */ if (cinfo->enable_2pass_quant) { /* Make sure color count is acceptable */ int desired = cinfo->desired_number_of_colors; /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ if (desired < 8) ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); /* Make sure colormap indexes can be represented by JSAMPLEs */ if (desired > MAXNUMCOLORS) ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); cquantize->desired = desired; } else cquantize->sv_colormap = NULL; /* Only F-S dithering or no dithering is supported. */ /* If user asks for ordered dither, give him F-S. */ if (cinfo->dither_mode != JDITHER_NONE) cinfo->dither_mode = JDITHER_FS; /* Allocate Floyd-Steinberg workspace if necessary. * This isn't really needed until pass 2, but again it is FAR storage. * Although we will cope with a later change in dither_mode, * we do not promise to honor max_memory_to_use if dither_mode changes. */ if (cinfo->dither_mode == JDITHER_FS) { cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, ((size_t) cinfo->output_width + (size_t) 2) * (3 * SIZEOF(FSERROR))); /* Might as well create the error-limiting table too. */ init_error_limit(cinfo); } } #endif /* QUANT_2PASS_SUPPORTED */ fltk-1.4.3/jpeg/jpegint.h0000644000175000017500000004306415004135251015352 0ustar albrechtalbrecht/* * jpegint.h * * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 1997-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides common declarations for the various JPEG modules. * These declarations are considered internal to the JPEG library; most * applications using the library shouldn't need to include this file. */ /* Declarations for both compression & decompression */ typedef enum { /* Operating modes for buffer controllers */ JBUF_PASS_THRU, /* Plain stripwise operation */ /* Remaining modes require a full-image buffer to have been created */ JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ } J_BUF_MODE; /* Values of global_state field (jdapi.c has some dependencies on ordering!) */ #define CSTATE_START 100 /* after create_compress */ #define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ #define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ #define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ #define DSTATE_START 200 /* after create_decompress */ #define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ #define DSTATE_READY 202 /* found SOS, ready for start_decompress */ #define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ #define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ #define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ #define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ #define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ #define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ #define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ #define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ /* Declarations for compression modules */ /* Master control module */ struct jpeg_comp_master { JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); /* State variables made visible to other modules */ boolean call_pass_startup; /* True if pass_startup must be called */ boolean is_last_pass; /* True during last pass */ }; /* Main buffer control (downsampled-data buffer) */ struct jpeg_c_main_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, process_data, (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); }; /* Compression preprocessing (downsampling input buffer control) */ struct jpeg_c_prep_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail)); }; /* Coefficient buffer control */ struct jpeg_c_coef_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, JSAMPIMAGE input_buf)); }; /* Colorspace conversion */ struct jpeg_color_converter { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); JMETHOD(void, color_convert, (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)); }; /* Downsampling */ struct jpeg_downsampler { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); JMETHOD(void, downsample, (j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_index, JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)); boolean need_context_rows; /* TRUE if need rows above & below */ }; /* Forward DCT (also controls coefficient quantization) */ typedef JMETHOD(void, forward_DCT_ptr, (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_col, JDIMENSION num_blocks)); struct jpeg_forward_dct { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); /* It is useful to allow each component to have a separate FDCT method. */ forward_DCT_ptr forward_DCT[MAX_COMPONENTS]; }; /* Entropy encoding */ struct jpeg_entropy_encoder { JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)); JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); }; /* Marker writing */ struct jpeg_marker_writer { JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); /* These routines are exported to allow insertion of extra markers */ /* Probably only COM and APPn markers should be written this way */ JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, unsigned int datalen)); JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); }; /* Declarations for decompression modules */ /* Master control module */ struct jpeg_decomp_master { JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); /* State variables made visible to other modules */ boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ }; /* Input control module */ struct jpeg_input_controller { JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); /* State variables made visible to other modules */ boolean has_multiple_scans; /* True if file has multiple scans */ boolean eoi_reached; /* True when EOI has been consumed */ }; /* Main buffer control (downsampled-data buffer) */ struct jpeg_d_main_controller { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, process_data, (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); }; /* Coefficient buffer control */ struct jpeg_d_coef_controller { JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); /* Pointer to array of coefficient virtual arrays, or NULL if none */ jvirt_barray_ptr *coef_arrays; }; /* Decompression postprocessing (color quantization buffer control) */ struct jpeg_d_post_controller { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); }; /* Marker reading & parsing */ struct jpeg_marker_reader { JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); /* Read markers until SOS or EOI. * Returns same codes as are defined for jpeg_consume_input: * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. */ JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); /* Read a restart marker --- exported for use by entropy decoder only */ jpeg_marker_parser_method read_restart_marker; /* State of marker reader --- nominally internal, but applications * supplying COM or APPn handlers might like to know the state. */ boolean saw_SOI; /* found SOI? */ boolean saw_SOF; /* found SOF? */ int next_restart_num; /* next restart number expected (0-7) */ unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ }; /* Entropy decoding */ struct jpeg_entropy_decoder { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data)); JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); }; /* Inverse DCT (also performs dequantization) */ typedef JMETHOD(void, inverse_DCT_method_ptr, (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); struct jpeg_inverse_dct { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); /* It is useful to allow each component to have a separate IDCT method. */ inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; }; /* Upsampling (note that upsampler must also call color converter) */ struct jpeg_upsampler { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(void, upsample, (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); boolean need_context_rows; /* TRUE if need rows above & below */ }; /* Colorspace conversion */ struct jpeg_color_deconverter { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(void, color_convert, (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)); }; /* Color quantization or color precision reduction */ struct jpeg_color_quantizer { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)); JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); }; /* Definition of range extension bits for decompression processes. * See the comments with prepare_range_limit_table (in jdmaster.c) * for more info. * The recommended default value for normal applications is 2. * Applications with special requirements may use a different value. * For example, Ghostscript wants to use 3 for proper handling of * wacky images with oversize coefficient values. */ #define RANGE_BITS 2 #define RANGE_CENTER (CENTERJSAMPLE << RANGE_BITS) /* Miscellaneous useful macros */ #undef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #undef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) /* We assume that right shift corresponds to signed division by 2 with * rounding towards minus infinity. This is correct for typical "arithmetic * shift" instructions that shift in copies of the sign bit. But some * C compilers implement >> with an unsigned shift. For these machines you * must define RIGHT_SHIFT_IS_UNSIGNED. * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. * It is only applied with constant shift counts. SHIFT_TEMPS must be * included in the variables of any routine using RIGHT_SHIFT. */ #ifdef RIGHT_SHIFT_IS_UNSIGNED #define SHIFT_TEMPS INT32 shift_temp; #define RIGHT_SHIFT(x,shft) \ ((shift_temp = (x)) < 0 ? \ (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ (shift_temp >> (shft))) #else #define SHIFT_TEMPS #define RIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif /* Descale and correctly round an INT32 value that's scaled by N bits. * We assume RIGHT_SHIFT rounds towards minus infinity, so adding * the fudge factor is correct for either sign of X. */ #define DESCALE(x,n) RIGHT_SHIFT((x) + ((INT32) 1 << ((n)-1)), n) /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jinit_compress_master jICompress #define jinit_c_master_control jICMaster #define jinit_c_main_controller jICMainC #define jinit_c_prep_controller jICPrepC #define jinit_c_coef_controller jICCoefC #define jinit_color_converter jICColor #define jinit_downsampler jIDownsampler #define jinit_forward_dct jIFDCT #define jinit_huff_encoder jIHEncoder #define jinit_arith_encoder jIAEncoder #define jinit_marker_writer jIMWriter #define jinit_master_decompress jIDMaster #define jinit_d_main_controller jIDMainC #define jinit_d_coef_controller jIDCoefC #define jinit_d_post_controller jIDPostC #define jinit_input_controller jIInCtlr #define jinit_marker_reader jIMReader #define jinit_huff_decoder jIHDecoder #define jinit_arith_decoder jIADecoder #define jinit_inverse_dct jIIDCT #define jinit_upsampler jIUpsampler #define jinit_color_deconverter jIDColor #define jinit_1pass_quantizer jI1Quant #define jinit_2pass_quantizer jI2Quant #define jinit_merged_upsampler jIMUpsampler #define jinit_memory_mgr jIMemMgr #define jdiv_round_up jDivRound #define jround_up jRound #define jzero_far jZeroFar #define jcopy_sample_rows jCopySamples #define jcopy_block_row jCopyBlocks #define jpeg_zigzag_order jZIGTable #define jpeg_natural_order jZAGTable #define jpeg_natural_order7 jZAG7Table #define jpeg_natural_order6 jZAG6Table #define jpeg_natural_order5 jZAG5Table #define jpeg_natural_order4 jZAG4Table #define jpeg_natural_order3 jZAG3Table #define jpeg_natural_order2 jZAG2Table #define jpeg_aritab jAriTab #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays * and coefficient-block arrays. This won't work on 80x86 because the arrays * are FAR and we're assuming a small-pointer memory model. However, some * DOS compilers provide far-pointer versions of memcpy() and memset() even * in the small-model libraries. These will be used if USE_FMEM is defined. * Otherwise, the routines in jutils.c do it the hard way. */ #ifndef NEED_FAR_POINTERS /* normal case, same as regular macro */ #define FMEMZERO(target,size) MEMZERO(target,size) #else /* 80x86 case */ #ifdef USE_FMEM #define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) #else EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); #define FMEMZERO(target,size) jzero_far(target, size) #endif #endif /* Compression module initialization routines */ EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, boolean transcode_only)); EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); /* Decompression module initialization routines */ EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); /* Memory manager initialization */ EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); /* Utility routines in jutils.c */ EXTERN(long) jdiv_round_up JPP((long a, long b)); EXTERN(long) jround_up JPP((long a, long b)); EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, JSAMPARRAY output_array, int num_rows, JDIMENSION num_cols)); EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks)); /* Constant tables in jutils.c */ #if 0 /* This table is not actually needed in v6a */ extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ #endif extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ extern const int jpeg_natural_order7[]; /* zz to natural order for 7x7 block */ extern const int jpeg_natural_order6[]; /* zz to natural order for 6x6 block */ extern const int jpeg_natural_order5[]; /* zz to natural order for 5x5 block */ extern const int jpeg_natural_order4[]; /* zz to natural order for 4x4 block */ extern const int jpeg_natural_order3[]; /* zz to natural order for 3x3 block */ extern const int jpeg_natural_order2[]; /* zz to natural order for 2x2 block */ /* Arithmetic coding probability estimation tables in jaricom.c */ extern const INT32 jpeg_aritab[]; /* Suppress undefined-structure complaints if necessary. */ #ifdef INCOMPLETE_TYPES_BROKEN #ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ struct jvirt_sarray_control { long dummy; }; struct jvirt_barray_control { long dummy; }; #endif #endif /* INCOMPLETE_TYPES_BROKEN */ fltk-1.4.3/jpeg/usage.txt0000644000175000017500000010346415004135251015407 0ustar albrechtalbrechtUSAGE instructions for the Independent JPEG Group's JPEG software ================================================================= This file describes usage of the JPEG conversion programs cjpeg and djpeg, as well as the utility programs jpegtran, rdjpgcom and wrjpgcom. (See the other documentation files if you wish to use the JPEG library within your own programs.) If you are on a Unix machine you may prefer to read the Unix-style manual pages in files cjpeg.1, djpeg.1, jpegtran.1, rdjpgcom.1, wrjpgcom.1. INTRODUCTION These programs implement JPEG image encoding, decoding, and transcoding. JPEG (pronounced "jay-peg") is a standardized compression method for full-color and grayscale images. GENERAL USAGE We provide two programs, cjpeg to compress an image file into JPEG format, and djpeg to decompress a JPEG file back into a conventional image format. On Unix-like systems, you say: cjpeg [switches] [imagefile] >jpegfile or djpeg [switches] [jpegfile] >imagefile The programs read the specified input file, or standard input if none is named. They always write to standard output (with trace/error messages to standard error). These conventions are handy for piping images between programs. On most non-Unix systems, you say: cjpeg [switches] imagefile jpegfile or djpeg [switches] jpegfile imagefile i.e., both the input and output files are named on the command line. This style is a little more foolproof, and it loses no functionality if you don't have pipes. (You can get this style on Unix too, if you prefer, by defining TWO_FILE_COMMANDLINE when you compile the programs; see install.txt.) You can also say: cjpeg [switches] -outfile jpegfile imagefile or djpeg [switches] -outfile imagefile jpegfile This syntax works on all systems, so it is useful for scripts. The currently supported image file formats are: PPM (PBMPLUS color format), PGM (PBMPLUS grayscale format), BMP, GIF, Targa, and RLE (Utah Raster Toolkit format). (RLE is supported only if the URT library is available, which it isn't on most non-Unix systems.) cjpeg recognizes the input image format automatically, with the exception of some Targa-format files. You have to tell djpeg which format to generate. JPEG files are in the standard JFIF file format. There are other, less widely used JPEG-based file formats, but we don't support them. All switch names may be abbreviated; for example, -grayscale may be written -gray or -gr. Most of the "basic" switches can be abbreviated to as little as one letter. Upper and lower case are equivalent (-BMP is the same as -bmp). British spellings are also accepted (e.g., -greyscale), though for brevity these are not mentioned below. CJPEG DETAILS The basic command line switches for cjpeg are: -quality N[,...] Scale quantization tables to adjust image quality. Quality is 0 (worst) to 100 (best); default is 75. (See below for more info.) -grayscale Create monochrome JPEG file from color input. Be sure to use this switch when compressing a grayscale BMP or GIF file, because cjpeg isn't bright enough to notice whether a BMP or GIF file uses only shades of gray. By saying -grayscale, you'll get a smaller JPEG file that takes less time to process. -rgb Create RGB JPEG file. Using this switch suppresses the conversion from RGB colorspace input to the default YCbCr JPEG colorspace. You can use this switch in combination with the -block N switch (see below) for lossless JPEG coding. See also the -rgb1 switch below. -optimize Perform optimization of entropy encoding parameters. Without this, default encoding parameters are used. -optimize usually makes the JPEG file a little smaller, but cjpeg runs somewhat slower and needs much more memory. Image quality and speed of decompression are unaffected by -optimize. -progressive Create progressive JPEG file (see below). -scale M/N Scale the output image by a factor M/N. Currently supported scale factors are M/N with all N from 1 to 16, where M is the destination DCT size, which is 8 by default (see -block N switch below). -targa Input file is Targa format. Targa files that contain an "identification" field will not be automatically recognized by cjpeg; for such files you must specify -targa to make cjpeg treat the input as Targa format. For most Targa files, you won't need this switch. The -quality switch lets you trade off compressed file size against quality of the reconstructed image: the higher the quality setting, the larger the JPEG file, and the closer the output image will be to the original input. Normally you want to use the lowest quality setting (smallest file) that decompresses into something visually indistinguishable from the original image. For this purpose the quality setting should be between 50 and 95; the default of 75 is often about right. If you see defects at -quality 75, then go up 5 or 10 counts at a time until you are happy with the output image. (The optimal setting will vary from one image to another.) -quality 100 will generate a quantization table of all 1's, minimizing loss in the quantization step (but there is still information loss in subsampling, as well as roundoff error). This setting is mainly of interest for experimental purposes. Quality values above about 95 are NOT recommended for normal use; the compressed file size goes up dramatically for hardly any gain in output image quality. In the other direction, quality values below 50 will produce very small files of low image quality. Settings around 5 to 10 might be useful in preparing an index of a large image library, for example. Try -quality 2 (or so) for some amusing Cubist effects. (Note: quality values below about 25 generate 2-byte quantization tables, which are considered optional in the JPEG standard. cjpeg emits a warning message when you give such a quality value, because some other JPEG programs may be unable to decode the resulting file. Use -baseline if you need to ensure compatibility at low quality values.) The -quality option has been extended in IJG version 7 for support of separate quality settings for luminance and chrominance (or in general, for every provided quantization table slot). This feature is useful for high-quality applications which cannot accept the damage of color data by coarse subsampling settings. You can now easily reduce the color data amount more smoothly with finer control without separate subsampling. The resulting file is fully compliant with standard JPEG decoders. Note that the -quality ratings refer to the quantization table slots, and that the last value is replicated if there are more q-table slots than parameters. The default q-table slots are 0 for luminance and 1 for chrominance with default tables as given in the JPEG standard. This is compatible with the old behaviour in case that only one parameter is given, which is then used for both luminance and chrominance (slots 0 and 1). More or custom quantization tables can be set with -qtables and assigned to components with -qslots parameter (see the "wizard" switches below). CAUTION: You must explicitly add -sample 1x1 for efficient separate color quality selection, since the default value used by library is 2x2! The -progressive switch creates a "progressive JPEG" file. In this type of JPEG file, the data is stored in multiple scans of increasing quality. If the file is being transmitted over a slow communications link, the decoder can use the first scan to display a low-quality image very quickly, and can then improve the display with each subsequent scan. The final image is exactly equivalent to a standard JPEG file of the same quality setting, and the total file size is about the same --- often a little smaller. Switches for advanced users: -arithmetic Use arithmetic coding. CAUTION: arithmetic coded JPEG is not yet widely implemented, so many decoders will be unable to view an arithmetic coded JPEG file at all. -block N Set DCT block size. All N from 1 to 16 are possible. Default is 8 (baseline format). Larger values produce higher compression, smaller values produce higher quality (exact DCT stage possible with 1 or 2; with the default quality of 75 and default quantization tables the DCT+Quantization stage is lossless for N=1). CAUTION: An implementation of the JPEG SmartScale extension is required for this feature. SmartScale enabled JPEG is not yet widely implemented, so many decoders will be unable to view a SmartScale extended JPEG file at all. -rgb1 Create RGB JPEG file with reversible color transform. Works like the -rgb switch (see above) and inserts a simple reversible color transform into the processing which significantly improves the compression. Use this switch in combination with the -block N switch (see above) for lossless JPEG coding. CAUTION: A decoder with inverse color transform support is required for this feature. Reversible color transform support is not yet widely implemented, so many decoders will be unable to view a reversible color transformed JPEG file at all. -bgycc Create big gamut YCC JPEG file. In this type of encoding the color difference components are quantized further by a factor of 2 compared to the normal Cb/Cr values, thus creating space to allow larger color values with higher saturation than the normal gamut limits to be encoded. In order to compensate for the loss of color fidelity compared to a normal YCC encoded file, the color quantization tables can be adjusted accordingly. For example, cjpeg -bgycc -quality 80,90 will give similar results as cjpeg -quality 80. CAUTION: For correct decompression a decoder with big gamut YCC support (JFIF version 2) is required. An old decoder may or may not display a big gamut YCC encoded JPEG file, depending on JFIF version check and corresponding warning/error configuration. In case of a granted decompression the old decoder will display the image with half saturated colors. -dct int Use integer DCT method (default). -dct fast Use fast integer DCT (less accurate). -dct float Use floating-point DCT method. The float method is very slightly more accurate than the int method, but is much slower unless your machine has very fast floating-point hardware. Also note that results of the floating-point method may vary slightly across machines, while the integer methods should give the same results everywhere. The fast integer method is much less accurate than the other two. -nosmooth Don't use high-quality downsampling. -restart N Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is attached to the number. -restart 0 (the default) means no restart markers. -smooth N Smooth the input image to eliminate dithering noise. N, ranging from 1 to 100, indicates the strength of smoothing. 0 (the default) means no smoothing. -maxmemory N Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, -max 4m selects 4000000 bytes. If more space is needed, temporary files will be used. -verbose Enable debug printout. More -v's give more printout. or -debug Also, version information is printed at startup. The -restart option inserts extra markers that allow a JPEG decoder to resynchronize after a transmission error. Without restart markers, any damage to a compressed file will usually ruin the image from the point of the error to the end of the image; with restart markers, the damage is usually confined to the portion of the image up to the next restart marker. Of course, the restart markers occupy extra space. We recommend -restart 1 for images that will be transmitted across unreliable networks such as Usenet. The -smooth option filters the input to eliminate fine-scale noise. This is often useful when converting dithered images to JPEG: a moderate smoothing factor of 10 to 50 gets rid of dithering patterns in the input file, resulting in a smaller JPEG file and a better-looking image. Too large a smoothing factor will visibly blur the image, however. Switches for wizards: -baseline Force baseline-compatible quantization tables to be generated. This clamps quantization values to 8 bits even at low quality settings. (This switch is poorly named, since it does not ensure that the output is actually baseline JPEG. For example, you can use -baseline and -progressive together.) -qtables file Use the quantization tables given in the specified text file. -qslots N[,...] Select which quantization table to use for each color component. -sample HxV[,...] Set JPEG sampling factors for each color component. -scans file Use the scan script given in the specified text file. The "wizard" switches are intended for experimentation with JPEG. If you don't know what you are doing, DON'T USE THEM. These switches are documented further in the file wizard.txt. DJPEG DETAILS The basic command line switches for djpeg are: -colors N Reduce image to at most N colors. This reduces the or -quantize N number of colors used in the output image, so that it can be displayed on a colormapped display or stored in a colormapped file format. For example, if you have an 8-bit display, you'd need to reduce to 256 or fewer colors. (-colors is the recommended name, -quantize is provided only for backwards compatibility.) -fast Select recommended processing options for fast, low quality output. (The default options are chosen for highest quality output.) Currently, this is equivalent to "-dct fast -nosmooth -onepass -dither ordered". -grayscale Force grayscale output even if JPEG file is color. Useful for viewing on monochrome displays; also, djpeg runs noticeably faster in this mode. -rgb Force RGB output even if JPEG file is grayscale. This is provided to support applications that don't want to cope with grayscale as a separate case. -scale M/N Scale the output image by a factor M/N. Currently supported scale factors are M/N with all M from 1 to 16, where N is the source DCT size, which is 8 for baseline JPEG. If the /N part is omitted, then M specifies the DCT scaled size to be applied on the given input. For baseline JPEG this is equivalent to M/8 scaling, since the source DCT size for baseline JPEG is 8. Scaling is handy if the image is larger than your screen; also, djpeg runs much faster when scaling down the output. -bmp Select BMP output format (Windows flavor). 8-bit colormapped format is emitted if -colors or -grayscale is specified, or if the JPEG file is grayscale; otherwise, 24-bit full-color format is emitted. -gif Select GIF output format (LZW compressed). Since GIF does not support more than 256 colors, -colors 256 is assumed (unless you specify a smaller number of colors). If you specify -fast, the default number of colors is 216. -gif0 Select GIF output format (uncompressed). Since GIF does not support more than 256 colors, -colors 256 is assumed (unless you specify a smaller number of colors). If you specify -fast, the default number of colors is 216. -os2 Select BMP output format (OS/2 1.x flavor). 8-bit colormapped format is emitted if -colors or -grayscale is specified, or if the JPEG file is grayscale; otherwise, 24-bit full-color format is emitted. -pnm Select PBMPLUS (PPM/PGM) output format (this is the default format). PGM is emitted if the JPEG file is grayscale or if -grayscale is specified; otherwise PPM is emitted. -rle Select RLE output format. (Requires URT library.) -targa Select Targa output format. Grayscale format is emitted if the JPEG file is grayscale or if -grayscale is specified; otherwise, colormapped format is emitted if -colors is specified; otherwise, 24-bit full-color format is emitted. Switches for advanced users: -dct int Use integer DCT method (default). -dct fast Use fast integer DCT (less accurate). -dct float Use floating-point DCT method. The float method is very slightly more accurate than the int method, but is much slower unless your machine has very fast floating-point hardware. Also note that results of the floating-point method may vary slightly across machines, while the integer methods should give the same results everywhere. The fast integer method is much less accurate than the other two. -dither fs Use Floyd-Steinberg dithering in color quantization. -dither ordered Use ordered dithering in color quantization. -dither none Do not use dithering in color quantization. By default, Floyd-Steinberg dithering is applied when quantizing colors; this is slow but usually produces the best results. Ordered dither is a compromise between speed and quality; no dithering is fast but usually looks awful. Note that these switches have no effect unless color quantization is being done. Ordered dither is only available in -onepass mode. -map FILE Quantize to the colors used in the specified image file. This is useful for producing multiple files with identical color maps, or for forcing a predefined set of colors to be used. The FILE must be a GIF or PPM file. This option overrides -colors and -onepass. -nosmooth Don't use high-quality upsampling. -onepass Use one-pass instead of two-pass color quantization. The one-pass method is faster and needs less memory, but it produces a lower-quality image. -onepass is ignored unless you also say -colors N. Also, the one-pass method is always used for grayscale output (the two-pass method is no improvement then). -maxmemory N Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, -max 4m selects 4000000 bytes. If more space is needed, temporary files will be used. -verbose Enable debug printout. More -v's give more printout. or -debug Also, version information is printed at startup. HINTS FOR CJPEG Color GIF files are not the ideal input for JPEG; JPEG is really intended for compressing full-color (24-bit) images. In particular, don't try to convert cartoons, line drawings, and other images that have only a few distinct colors. GIF works great on these, JPEG does not. If you want to convert a GIF to JPEG, you should experiment with cjpeg's -quality and -smooth options to get a satisfactory conversion. -smooth 10 or so is often helpful. Avoid running an image through a series of JPEG compression/decompression cycles. Image quality loss will accumulate; after ten or so cycles the image may be noticeably worse than it was after one cycle. It's best to use a lossless format while manipulating an image, then convert to JPEG format when you are ready to file the image away. The -optimize option to cjpeg is worth using when you are making a "final" version for posting or archiving. It's also a win when you are using low quality settings to make very small JPEG files; the percentage improvement is often a lot more than it is on larger files. (At present, -optimize mode is always selected when generating progressive JPEG files.) HINTS FOR DJPEG To get a quick preview of an image, use the -grayscale and/or -scale switches. "-grayscale -scale 1/8" is the fastest case. Several options are available that trade off image quality to gain speed. "-fast" turns on the recommended settings. "-dct fast" and/or "-nosmooth" gain speed at a small sacrifice in quality. When producing a color-quantized image, "-onepass -dither ordered" is fast but much lower quality than the default behavior. "-dither none" may give acceptable results in two-pass mode, but is seldom tolerable in one-pass mode. If you are fortunate enough to have very fast floating point hardware, "-dct float" may be even faster than "-dct fast". But on most machines "-dct float" is slower than "-dct int"; in this case it is not worth using, because its theoretical accuracy advantage is too small to be significant in practice. Two-pass color quantization requires a good deal of memory; on MS-DOS machines it may run out of memory even with -maxmemory 0. In that case you can still decompress, with some loss of image quality, by specifying -onepass for one-pass quantization. HINTS FOR BOTH PROGRAMS If more space is needed than will fit in the available main memory (as determined by -maxmemory), temporary files will be used. (MS-DOS versions will try to get extended or expanded memory first.) The temporary files are often rather large: in typical cases they occupy three bytes per pixel, for example 3*800*600 = 1.44Mb for an 800x600 image. If you don't have enough free disk space, leave out -progressive and -optimize (for cjpeg) or specify -onepass (for djpeg). On MS-DOS, the temporary files are created in the directory named by the TMP or TEMP environment variable, or in the current directory if neither of those exist. Amiga implementations put the temp files in the directory named by JPEGTMP:, so be sure to assign JPEGTMP: to a disk partition with adequate free space. The default memory usage limit (-maxmemory) is set when the software is compiled. If you get an "insufficient memory" error, try specifying a smaller -maxmemory value, even -maxmemory 0 to use the absolute minimum space. You may want to recompile with a smaller default value if this happens often. On machines that have "environment" variables, you can define the environment variable JPEGMEM to set the default memory limit. The value is specified as described for the -maxmemory switch. JPEGMEM overrides the default value specified when the program was compiled, and itself is overridden by an explicit -maxmemory switch. On MS-DOS machines, -maxmemory is the amount of main (conventional) memory to use. (Extended or expanded memory is also used if available.) Most DOS-specific versions of this software do their own memory space estimation and do not need you to specify -maxmemory. JPEGTRAN jpegtran performs various useful transformations of JPEG files. It can translate the coded representation from one variant of JPEG to another, for example from baseline JPEG to progressive JPEG or vice versa. It can also perform some rearrangements of the image data, for example turning an image from landscape to portrait format by rotation. For EXIF files and JPEG files containing Exif data, you may prefer to use exiftran instead. jpegtran works by rearranging the compressed data (DCT coefficients), without ever fully decoding the image. Therefore, its transformations are lossless: there is no image degradation at all, which would not be true if you used djpeg followed by cjpeg to accomplish the same conversion. But by the same token, jpegtran cannot perform lossy operations such as changing the image quality. However, while the image data is losslessly transformed, metadata can be removed. See the -copy option for specifics. jpegtran uses a command line syntax similar to cjpeg or djpeg. On Unix-like systems, you say: jpegtran [switches] [inputfile] >outputfile On most non-Unix systems, you say: jpegtran [switches] inputfile outputfile where both the input and output files are JPEG files. To specify the coded JPEG representation used in the output file, jpegtran accepts a subset of the switches recognized by cjpeg: -optimize Perform optimization of entropy encoding parameters. -progressive Create progressive JPEG file. -arithmetic Use arithmetic coding. -restart N Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is attached to the number. -scans file Use the scan script given in the specified text file. See the previous discussion of cjpeg for more details about these switches. If you specify none of these switches, you get a plain baseline-JPEG output file. The quality setting and so forth are determined by the input file. The image can be losslessly transformed by giving one of these switches: -flip horizontal Mirror image horizontally (left-right). -flip vertical Mirror image vertically (top-bottom). -rotate 90 Rotate image 90 degrees clockwise. -rotate 180 Rotate image 180 degrees. -rotate 270 Rotate image 270 degrees clockwise (or 90 ccw). -transpose Transpose image (across UL-to-LR axis). -transverse Transverse transpose (across UR-to-LL axis). The transpose transformation has no restrictions regarding image dimensions. The other transformations operate rather oddly if the image dimensions are not a multiple of the iMCU size (usually 8 or 16 pixels), because they can only transform complete blocks of DCT coefficient data in the desired way. jpegtran's default behavior when transforming an odd-size image is designed to preserve exact reversibility and mathematical consistency of the transformation set. As stated, transpose is able to flip the entire image area. Horizontal mirroring leaves any partial iMCU column at the right edge untouched, but is able to flip all rows of the image. Similarly, vertical mirroring leaves any partial iMCU row at the bottom edge untouched, but is able to flip all columns. The other transforms can be built up as sequences of transpose and flip operations; for consistency, their actions on edge pixels are defined to be the same as the end result of the corresponding transpose-and-flip sequence. For practical use, you may prefer to discard any untransformable edge pixels rather than having a strange-looking strip along the right and/or bottom edges of a transformed image. To do this, add the -trim switch: -trim Drop non-transformable edge blocks. Obviously, a transformation with -trim is not reversible, so strictly speaking jpegtran with this switch is not lossless. Also, the expected mathematical equivalences between the transformations no longer hold. For example, "-rot 270 -trim" trims only the bottom edge, but "-rot 90 -trim" followed by "-rot 180 -trim" trims both edges. If you are only interested in perfect transformation, add the -perfect switch: -perfect Fails with an error if the transformation is not perfect. For example you may want to do jpegtran -rot 90 -perfect foo.jpg || djpeg foo.jpg | pnmflip -r90 | cjpeg to do a perfect rotation if available or an approximated one if not. We also offer a lossless-crop option, which discards data outside a given image region but losslessly preserves what is inside. Like the rotate and flip transforms, lossless crop is restricted by the current JPEG format: the upper left corner of the selected region must fall on an iMCU boundary. If this does not hold for the given crop parameters, we silently move the upper left corner up and/or left to make it so, simultaneously increasing the region dimensions to keep the lower right crop corner unchanged. (Thus, the output image covers at least the requested region, but may cover more.) The adjustment of the region dimensions may be optionally disabled by attaching an 'f' character ("force") to the width or height number. The image can be losslessly cropped by giving the switch: -crop WxH+X+Y Crop to a rectangular subarea of width W, height H starting at point X,Y. Crop extension: The width or height parameters can be made larger than the source image. In this case the extra area is filled in with zero (neutral gray). A larger width parameter has two more options: Attaching an 'f' character ("flatten") to the width number will fill in the extra area with the DC of the adjacent block, instead of gray out. Attaching an 'r' character ("reflect") to the width number will fill in the extra area with repeated reflections of the source region, instead of gray out. A complementary lossless-wipe option is provided to discard (gray out) data inside a given image region while losslessly preserving what is outside: -wipe WxH+X+Y Wipe (gray out) a rectangular subarea of width W, height H starting at point X,Y. Attaching an 'f' character ("flatten") to the width number will fill the region with the average of adjacent blocks, instead of gray out. In case the wipe region and outside area form two horizontally adjacent rectangles, attaching an 'r' character ("reflect") to the width number will fill the region with repeated reflections of the outside area, instead of gray out. Another option is lossless-drop, which replaces data at a given image position by another image: -drop +X+Y filename Drop another image Both source images must have the same subsampling values. It is best if they also have the same quantization, otherwise quantization adaption occurs. The trim option can be used with the drop option to requantize the drop file to the source file. Other not-strictly-lossless transformation switches are: -grayscale Force grayscale output. This option discards the chrominance channels if the input image is YCbCr (ie, a standard color JPEG), resulting in a grayscale JPEG file. The luminance channel is preserved exactly, so this is a better method of reducing to grayscale than decompression, conversion, and recompression. This switch is particularly handy for fixing a monochrome picture that was mistakenly encoded as a color JPEG. (In such a case, the space savings from getting rid of the near-empty chroma channels won't be large; but the decoding time for a grayscale JPEG is substantially less than that for a color JPEG.) -scale M/N Scale the output image by a factor M/N. Currently supported scale factors are M/N with all M from 1 to 16, where N is the source DCT size, which is 8 for baseline JPEG. If the /N part is omitted, then M specifies the DCT scaled size to be applied on the given input. For baseline JPEG this is equivalent to M/8 scaling, since the source DCT size for baseline JPEG is 8. CAUTION: An implementation of the JPEG SmartScale extension is required for this feature. SmartScale enabled JPEG is not yet widely implemented, so many decoders will be unable to view a SmartScale extended JPEG file at all. jpegtran also recognizes these switches that control what to do with "extra" markers, such as comment blocks: -copy none Copy no extra markers from source file. This setting suppresses all comments and other metadata in the source file. -copy comments Copy only comment markers. This setting copies comments from the source file, but discards any other metadata. -copy all Copy all extra markers. This setting preserves metadata found in the source file, such as JFIF thumbnails, Exif data, and Photoshop settings. In some files these extra markers can be sizable. Note that this option will copy thumbnails as-is; they will not be transformed. The default behavior is -copy comments. (Note: in IJG releases v6 and v6a, jpegtran always did the equivalent of -copy none.) Additional switches recognized by jpegtran are: -outfile filename -maxmemory N -verbose -debug These work the same as in cjpeg or djpeg. THE COMMENT UTILITIES The JPEG standard allows "comment" (COM) blocks to occur within a JPEG file. Although the standard doesn't actually define what COM blocks are for, they are widely used to hold user-supplied text strings. This lets you add annotations, titles, index terms, etc to your JPEG files, and later retrieve them as text. COM blocks do not interfere with the image stored in the JPEG file. The maximum size of a COM block is 64K, but you can have as many of them as you like in one JPEG file. We provide two utility programs to display COM block contents and add COM blocks to a JPEG file. rdjpgcom searches a JPEG file and prints the contents of any COM blocks on standard output. The command line syntax is rdjpgcom [-raw] [-verbose] [inputfilename] The switch "-raw" (or just "-r") causes rdjpgcom to also output non-printable characters in comments, which are normally escaped for security reasons. The switch "-verbose" (or just "-v") causes rdjpgcom to also display the JPEG image dimensions. If you omit the input file name from the command line, the JPEG file is read from standard input. (This may not work on some operating systems, if binary data can't be read from stdin.) wrjpgcom adds a COM block, containing text you provide, to a JPEG file. Ordinarily, the COM block is added after any existing COM blocks, but you can delete the old COM blocks if you wish. wrjpgcom produces a new JPEG file; it does not modify the input file. DO NOT try to overwrite the input file by directing wrjpgcom's output back into it; on most systems this will just destroy your file. The command line syntax for wrjpgcom is similar to cjpeg's. On Unix-like systems, it is wrjpgcom [switches] [inputfilename] The output file is written to standard output. The input file comes from the named file, or from standard input if no input file is named. On most non-Unix systems, the syntax is wrjpgcom [switches] inputfilename outputfilename where both input and output file names must be given explicitly. wrjpgcom understands three switches: -replace Delete any existing COM blocks from the file. -comment "Comment text" Supply new COM text on command line. -cfile name Read text for new COM block from named file. (Switch names can be abbreviated.) If you have only one line of comment text to add, you can provide it on the command line with -comment. The comment text must be surrounded with quotes so that it is treated as a single argument. Longer comments can be read from a text file. If you give neither -comment nor -cfile, then wrjpgcom will read the comment text from standard input. (In this case an input image file name MUST be supplied, so that the source JPEG file comes from somewhere else.) You can enter multiple lines, up to 64KB worth. Type an end-of-file indicator (usually control-D or control-Z) to terminate the comment text entry. wrjpgcom will not add a COM block if the provided comment string is empty. Therefore -replace -comment "" can be used to delete all COM blocks from a file. These utility programs do not depend on the IJG JPEG library. In particular, the source code for rdjpgcom is intended as an illustration of the minimum amount of code required to parse a JPEG file header correctly. fltk-1.4.3/jpeg/jdinput.c0000644000175000017500000006053315004135251015362 0ustar albrechtalbrecht/* * jdinput.c * * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2002-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains input control logic for the JPEG decompressor. * These routines are concerned with controlling the decompressor's input * processing (marker reading and coefficient decoding). The actual input * reading is done in jdmarker.c, jdhuff.c, and jdarith.c. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private state */ typedef struct { struct jpeg_input_controller pub; /* public fields */ int inheaders; /* Nonzero until first SOS is reached */ } my_input_controller; typedef my_input_controller * my_inputctl_ptr; /* Forward declarations */ METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); /* * Routines to calculate various quantities related to the size of the image. */ /* * Compute output image dimensions and related values. * NOTE: this is exported for possible use by application. * Hence it mustn't do anything that can't be done twice. */ GLOBAL(void) jpeg_core_output_dimensions (j_decompress_ptr cinfo) /* Do computations that are needed before master selection phase. * This function is used for transcoding and full decompression. */ { #ifdef IDCT_SCALING_SUPPORTED int ci; jpeg_component_info *compptr; /* Compute actual output image dimensions and DCT scaling choices. */ if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom) { /* Provide 1/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 1; cinfo->min_DCT_v_scaled_size = 1; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 2) { /* Provide 2/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 2L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 2L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 2; cinfo->min_DCT_v_scaled_size = 2; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 3) { /* Provide 3/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 3L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 3L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 3; cinfo->min_DCT_v_scaled_size = 3; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 4) { /* Provide 4/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 4L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 4L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 4; cinfo->min_DCT_v_scaled_size = 4; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 5) { /* Provide 5/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 5L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 5L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 5; cinfo->min_DCT_v_scaled_size = 5; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 6) { /* Provide 6/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 6L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 6L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 6; cinfo->min_DCT_v_scaled_size = 6; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 7) { /* Provide 7/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 7L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 7L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 7; cinfo->min_DCT_v_scaled_size = 7; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 8) { /* Provide 8/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 8L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 8L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 8; cinfo->min_DCT_v_scaled_size = 8; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 9) { /* Provide 9/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 9L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 9L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 9; cinfo->min_DCT_v_scaled_size = 9; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 10) { /* Provide 10/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 10L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 10L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 10; cinfo->min_DCT_v_scaled_size = 10; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 11) { /* Provide 11/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 11L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 11L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 11; cinfo->min_DCT_v_scaled_size = 11; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 12) { /* Provide 12/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 12L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 12L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 12; cinfo->min_DCT_v_scaled_size = 12; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 13) { /* Provide 13/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 13L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 13L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 13; cinfo->min_DCT_v_scaled_size = 13; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 14) { /* Provide 14/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 14L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 14L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 14; cinfo->min_DCT_v_scaled_size = 14; } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 15) { /* Provide 15/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 15L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 15L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 15; cinfo->min_DCT_v_scaled_size = 15; } else { /* Provide 16/block_size scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * 16L, (long) cinfo->block_size); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * 16L, (long) cinfo->block_size); cinfo->min_DCT_h_scaled_size = 16; cinfo->min_DCT_v_scaled_size = 16; } /* Recompute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size; compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size; } #else /* !IDCT_SCALING_SUPPORTED */ /* Hardwire it to "no scaling" */ cinfo->output_width = cinfo->image_width; cinfo->output_height = cinfo->image_height; /* initial_setup has already initialized DCT_scaled_size, * and has computed unscaled downsampled_width and downsampled_height. */ #endif /* IDCT_SCALING_SUPPORTED */ } LOCAL(void) initial_setup (j_decompress_ptr cinfo) /* Called once, when first SOS marker is reached */ { int ci; jpeg_component_info *compptr; /* Make sure image isn't bigger than I can handle */ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); /* Only 8 to 12 bits data precision are supported for DCT based JPEG */ if (cinfo->data_precision < 8 || cinfo->data_precision > 12) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo, JERR_BAD_SAMPLING); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } /* Derive block_size, natural_order, and lim_Se */ if (cinfo->is_baseline || (cinfo->progressive_mode && cinfo->comps_in_scan)) { /* no pseudo SOS marker */ cinfo->block_size = DCTSIZE; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2-1; } else switch (cinfo->Se) { case (1*1-1): cinfo->block_size = 1; cinfo->natural_order = jpeg_natural_order; /* not needed */ cinfo->lim_Se = cinfo->Se; break; case (2*2-1): cinfo->block_size = 2; cinfo->natural_order = jpeg_natural_order2; cinfo->lim_Se = cinfo->Se; break; case (3*3-1): cinfo->block_size = 3; cinfo->natural_order = jpeg_natural_order3; cinfo->lim_Se = cinfo->Se; break; case (4*4-1): cinfo->block_size = 4; cinfo->natural_order = jpeg_natural_order4; cinfo->lim_Se = cinfo->Se; break; case (5*5-1): cinfo->block_size = 5; cinfo->natural_order = jpeg_natural_order5; cinfo->lim_Se = cinfo->Se; break; case (6*6-1): cinfo->block_size = 6; cinfo->natural_order = jpeg_natural_order6; cinfo->lim_Se = cinfo->Se; break; case (7*7-1): cinfo->block_size = 7; cinfo->natural_order = jpeg_natural_order7; cinfo->lim_Se = cinfo->Se; break; case (8*8-1): cinfo->block_size = 8; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2-1; break; case (9*9-1): cinfo->block_size = 9; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2-1; break; case (10*10-1): cinfo->block_size = 10; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2-1; break; case (11*11-1): cinfo->block_size = 11; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2-1; break; case (12*12-1): cinfo->block_size = 12; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2-1; break; case (13*13-1): cinfo->block_size = 13; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2-1; break; case (14*14-1): cinfo->block_size = 14; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2-1; break; case (15*15-1): cinfo->block_size = 15; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2-1; break; case (16*16-1): cinfo->block_size = 16; cinfo->natural_order = jpeg_natural_order; cinfo->lim_Se = DCTSIZE2-1; break; default: ERREXIT4(cinfo, JERR_BAD_PROGRESSION, cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); } /* We initialize DCT_scaled_size and min_DCT_scaled_size to block_size. * In the full decompressor, * this will be overridden by jpeg_calc_output_dimensions in jdmaster.c; * but in the transcoder, * jpeg_calc_output_dimensions is not used, so we must do it here. */ cinfo->min_DCT_h_scaled_size = cinfo->block_size; cinfo->min_DCT_v_scaled_size = cinfo->block_size; /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { compptr->DCT_h_scaled_size = cinfo->block_size; compptr->DCT_v_scaled_size = cinfo->block_size; /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* downsampled_width and downsampled_height will also be overridden by * jdmaster.c if we are doing full decompression. The transcoder library * doesn't use these values, but the calling application might. */ /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) cinfo->max_h_samp_factor); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) cinfo->max_v_samp_factor); /* Mark component needed, until color conversion says otherwise */ compptr->component_needed = TRUE; /* Mark no quantization table yet saved for component */ compptr->quant_table = NULL; } /* Compute number of fully interleaved MCU rows. */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* Decide whether file contains multiple scans */ if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) cinfo->inputctl->has_multiple_scans = TRUE; else cinfo->inputctl->has_multiple_scans = FALSE; } LOCAL(void) per_scan_setup (j_decompress_ptr cinfo) /* Do computations that are needed before processing a JPEG scan */ /* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ { int ci, mcublks, tmp; jpeg_component_info *compptr; if (cinfo->comps_in_scan == 1) { /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; /* Overall image size in MCUs */ cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; compptr->MCU_sample_width = compptr->DCT_h_scaled_size; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height * as the number of block rows present in the last iMCU row. */ tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (tmp == 0) tmp = compptr->v_samp_factor; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; } else { /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, MAX_COMPS_IN_SCAN); /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, (long) (cinfo->max_h_samp_factor * cinfo->block_size)); cinfo->MCU_rows_in_scan = cinfo->total_iMCU_rows; cinfo->blocks_in_MCU = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Sampling factors give # of blocks of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_h_scaled_size; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = tmp; tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); if (tmp == 0) tmp = compptr->MCU_height; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } } } /* * Save away a copy of the Q-table referenced by each component present * in the current scan, unless already saved during a prior scan. * * In a multiple-scan JPEG file, the encoder could assign different components * the same Q-table slot number, but change table definitions between scans * so that each component uses a different Q-table. (The IJG encoder is not * currently capable of doing this, but other encoders might.) Since we want * to be able to dequantize all the components at the end of the file, this * means that we have to save away the table actually used for each component. * We do this by copying the table at the start of the first scan containing * the component. * The JPEG spec prohibits the encoder from changing the contents of a Q-table * slot between scans of a component using that slot. If the encoder does so * anyway, this decoder will simply use the Q-table values that were current * at the start of the first scan for the component. * * The decompressor output side looks only at the saved quant tables, * not at the current Q-table slots. */ LOCAL(void) latch_quant_tables (j_decompress_ptr cinfo) { int ci, qtblno; jpeg_component_info *compptr; JQUANT_TBL * qtbl; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* No work if we already saved Q-table for this component */ if (compptr->quant_table != NULL) continue; /* Make sure specified quantization table is present */ qtblno = compptr->quant_tbl_no; if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo->quant_tbl_ptrs[qtblno] == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); /* OK, save away the quantization table */ qtbl = (JQUANT_TBL *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(JQUANT_TBL)); MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); compptr->quant_table = qtbl; } } /* * Initialize the input modules to read a scan of compressed data. * The first call to this is done by jdmaster.c after initializing * the entire decompressor (during jpeg_start_decompress). * Subsequent calls come from consume_markers, below. */ METHODDEF(void) start_input_pass (j_decompress_ptr cinfo) { per_scan_setup(cinfo); latch_quant_tables(cinfo); (*cinfo->entropy->start_pass) (cinfo); (*cinfo->coef->start_input_pass) (cinfo); cinfo->inputctl->consume_input = cinfo->coef->consume_data; } /* * Finish up after inputting a compressed-data scan. * This is called by the coefficient controller after it's read all * the expected data of the scan. */ METHODDEF(void) finish_input_pass (j_decompress_ptr cinfo) { (*cinfo->entropy->finish_pass) (cinfo); cinfo->inputctl->consume_input = consume_markers; } /* * Read JPEG markers before, between, or after compressed-data scans. * Change state as necessary when a new scan is reached. * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. * * The consume_input method pointer points either here or to the * coefficient controller's consume_data routine, depending on whether * we are reading a compressed data segment or inter-segment markers. * * Note: This function should NOT return a pseudo SOS marker (with zero * component number) to the caller. A pseudo marker received by * read_markers is processed and then skipped for other markers. */ METHODDEF(int) consume_markers (j_decompress_ptr cinfo) { my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; int val; if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ return JPEG_REACHED_EOI; for (;;) { /* Loop to pass pseudo SOS marker */ val = (*cinfo->marker->read_markers) (cinfo); switch (val) { case JPEG_REACHED_SOS: /* Found SOS */ if (inputctl->inheaders) { /* 1st SOS */ if (inputctl->inheaders == 1) initial_setup(cinfo); if (cinfo->comps_in_scan == 0) { /* pseudo SOS marker */ inputctl->inheaders = 2; break; } inputctl->inheaders = 0; /* Note: start_input_pass must be called by jdmaster.c * before any more input can be consumed. jdapimin.c is * responsible for enforcing this sequencing. */ } else { /* 2nd or later SOS marker */ if (! inputctl->pub.has_multiple_scans) ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ if (cinfo->comps_in_scan == 0) /* unexpected pseudo SOS marker */ break; start_input_pass(cinfo); } return val; case JPEG_REACHED_EOI: /* Found EOI */ inputctl->pub.eoi_reached = TRUE; if (inputctl->inheaders) { /* Tables-only datastream, apparently */ if (cinfo->marker->saw_SOF) ERREXIT(cinfo, JERR_SOF_NO_SOS); } else { /* Prevent infinite loop in coef ctlr's decompress_data routine * if user set output_scan_number larger than number of scans. */ if (cinfo->output_scan_number > cinfo->input_scan_number) cinfo->output_scan_number = cinfo->input_scan_number; } return val; case JPEG_SUSPENDED: return val; default: return val; } } } /* * Reset state to begin a fresh datastream. */ METHODDEF(void) reset_input_controller (j_decompress_ptr cinfo) { my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; inputctl->pub.consume_input = consume_markers; inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ inputctl->pub.eoi_reached = FALSE; inputctl->inheaders = 1; /* Reset other modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->marker->reset_marker_reader) (cinfo); /* Reset progression state -- would be cleaner if entropy decoder did this */ cinfo->coef_bits = NULL; } /* * Initialize the input controller module. * This is called only once, when the decompression object is created. */ GLOBAL(void) jinit_input_controller (j_decompress_ptr cinfo) { my_inputctl_ptr inputctl; /* Create subobject in permanent pool */ inputctl = (my_inputctl_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_input_controller)); cinfo->inputctl = &inputctl->pub; /* Initialize method pointers */ inputctl->pub.consume_input = consume_markers; inputctl->pub.reset_input_controller = reset_input_controller; inputctl->pub.start_input_pass = start_input_pass; inputctl->pub.finish_input_pass = finish_input_pass; /* Initialize state: can't use reset_input_controller since we don't * want to try to reset other modules yet. */ inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ inputctl->pub.eoi_reached = FALSE; inputctl->inheaders = 1; } fltk-1.4.3/jpeg/jdcoefct.c0000644000175000017500000006116115004135251015464 0ustar albrechtalbrecht/* * jdcoefct.c * * Copyright (C) 1994-1997, Thomas G. Lane. * Modified 2002-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the coefficient buffer controller for decompression. * This controller is the top level of the JPEG decompressor proper. * The coefficient buffer lies between entropy decoding and inverse-DCT steps. * * In buffered-image mode, this controller is the interface between * input-oriented processing and output-oriented processing. * Also, the input side (only) is used when reading a file for transcoding. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Block smoothing is only applicable for progressive JPEG, so: */ #ifndef D_PROGRESSIVE_SUPPORTED #undef BLOCK_SMOOTHING_SUPPORTED #endif /* Private buffer controller object */ typedef struct { struct jpeg_d_coef_controller pub; /* public fields */ /* These variables keep track of the current location of the input side. */ /* cinfo->input_iMCU_row is also used for this. */ JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ int MCU_vert_offset; /* counts MCU rows within iMCU row */ int MCU_rows_per_iMCU_row; /* number of such rows needed */ /* The output side's location is represented by cinfo->output_iMCU_row. */ /* In single-pass modes, it's sufficient to buffer just one MCU. * We append a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, * and let the entropy decoder write into that workspace each time. * In multi-pass modes, this array points to the current MCU's blocks * within the virtual arrays; it is used only by the input side. */ JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; #ifdef D_MULTISCAN_FILES_SUPPORTED /* In multi-pass modes, we need a virtual block array for each component. */ jvirt_barray_ptr whole_image[MAX_COMPONENTS]; #endif #ifdef BLOCK_SMOOTHING_SUPPORTED /* When doing block smoothing, we latch coefficient Al values here */ int * coef_bits_latch; #define SAVED_COEFS 6 /* we save coef_bits[0..5] */ #endif /* Workspace for single-pass modes (omitted otherwise). */ JBLOCK blk_buffer[D_MAX_BLOCKS_IN_MCU]; } my_coef_controller; typedef my_coef_controller * my_coef_ptr; /* Forward declarations */ METHODDEF(int) decompress_onepass JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); #ifdef D_MULTISCAN_FILES_SUPPORTED METHODDEF(int) decompress_data JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); #endif #ifdef BLOCK_SMOOTHING_SUPPORTED LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); METHODDEF(int) decompress_smooth_data JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); #endif LOCAL(void) start_iMCU_row (j_decompress_ptr cinfo) /* Reset within-iMCU-row counters for a new row (input side) */ { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* In an interleaved scan, an MCU row is the same as an iMCU row. * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. * But at the bottom of the image, process only what's left. */ if (cinfo->comps_in_scan > 1) { coef->MCU_rows_per_iMCU_row = 1; } else { if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; else coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; } coef->MCU_ctr = 0; coef->MCU_vert_offset = 0; } /* * Initialize for an input processing pass. */ METHODDEF(void) start_input_pass (j_decompress_ptr cinfo) { cinfo->input_iMCU_row = 0; start_iMCU_row(cinfo); } /* * Initialize for an output processing pass. */ METHODDEF(void) start_output_pass (j_decompress_ptr cinfo) { #ifdef BLOCK_SMOOTHING_SUPPORTED my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* If multipass, check to see whether to use block smoothing on this pass */ if (coef->pub.coef_arrays != NULL) { if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) coef->pub.decompress_data = decompress_smooth_data; else coef->pub.decompress_data = decompress_data; } #endif cinfo->output_iMCU_row = 0; } /* * Decompress and return some data in the single-pass case. * Always attempts to emit one fully interleaved MCU row ("iMCU" row). * Input and output must run in lockstep since we have only a one-MCU buffer. * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. * * NB: output_buf contains a plane for each component in image, * which we index according to the component's SOF position. */ METHODDEF(int) decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int ci, xindex, yindex, yoffset, useful_width; JBLOCKROW blkp; JSAMPARRAY output_ptr; JDIMENSION start_col, output_col; jpeg_component_info *compptr; inverse_DCT_method_ptr inverse_DCT; /* Loop to process as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { blkp = coef->blk_buffer; /* pointer to current DCT block within MCU */ /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ if (cinfo->lim_Se) /* can bypass in DC only case */ MEMZERO(blkp, cinfo->blocks_in_MCU * SIZEOF(JBLOCK)); if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return JPEG_SUSPENDED; } /* Determine where data should go in output_buf and do the IDCT thing. * We skip dummy blocks at the right and bottom edges (but blkp gets * incremented past them!). */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Don't bother to IDCT an uninteresting component. */ if (! compptr->component_needed) { blkp += compptr->MCU_blocks; continue; } inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; output_ptr = output_buf[compptr->component_index] + yoffset * compptr->DCT_v_scaled_size; useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; start_col = MCU_col_num * compptr->MCU_sample_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (cinfo->input_iMCU_row < last_iMCU_row || yoffset + yindex < compptr->last_row_height) { output_col = start_col; for (xindex = 0; xindex < useful_width; xindex++) { (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) (blkp + xindex), output_ptr, output_col); output_col += compptr->DCT_h_scaled_size; } output_ptr += compptr->DCT_v_scaled_size; } blkp += compptr->MCU_width; } } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->MCU_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ cinfo->output_iMCU_row++; if (++(cinfo->input_iMCU_row) <= last_iMCU_row) { start_iMCU_row(cinfo); return JPEG_ROW_COMPLETED; } /* Completed the scan */ (*cinfo->inputctl->finish_input_pass) (cinfo); return JPEG_SCAN_COMPLETED; } /* * Dummy consume-input routine for single-pass operation. */ METHODDEF(int) dummy_consume_data (j_decompress_ptr cinfo) { return JPEG_SUSPENDED; /* Always indicate nothing was done */ } #ifdef D_MULTISCAN_FILES_SUPPORTED /* * Consume input data and store it in the full-image coefficient buffer. * We read as much as one fully interleaved MCU row ("iMCU" row) per call, * ie, v_samp_factor block rows for each component in the scan. * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. */ METHODDEF(int) consume_data (j_decompress_ptr cinfo) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ int ci, xindex, yindex, yoffset; JDIMENSION start_col; JBLOCKARRAY blkp; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; /* Align the virtual buffers for the components used in this scan. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; buffer[ci] = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], cinfo->input_iMCU_row * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, TRUE); /* Note: entropy decoder expects buffer to be zeroed, * but this is handled automatically by the memory manager * because we requested a pre-zeroed array. */ } /* Loop to process one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) { /* Construct list of pointers to DCT blocks belonging to this MCU */ blkp = coef->MCU_buffer; /* pointer to current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; start_col = MCU_col_num * compptr->MCU_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { buffer_ptr = buffer[ci][yoffset + yindex] + start_col; xindex = compptr->MCU_width; do { *blkp++ = buffer_ptr++; } while (--xindex); } } /* Try to fetch the MCU. */ if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return JPEG_SUSPENDED; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->MCU_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { start_iMCU_row(cinfo); return JPEG_ROW_COMPLETED; } /* Completed the scan */ (*cinfo->inputctl->finish_input_pass) (cinfo); return JPEG_SCAN_COMPLETED; } /* * Decompress and return some data in the multi-pass case. * Always attempts to emit one fully interleaved MCU row ("iMCU" row). * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. * * NB: output_buf contains a plane for each component in image. */ METHODDEF(int) decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION block_num; int ci, block_row, block_rows; JBLOCKARRAY buffer; JBLOCKROW buffer_ptr; JSAMPARRAY output_ptr; JDIMENSION output_col; jpeg_component_info *compptr; inverse_DCT_method_ptr inverse_DCT; /* Force some input to be done if we are getting ahead of the input. */ while (cinfo->input_scan_number < cinfo->output_scan_number || (cinfo->input_scan_number == cinfo->output_scan_number && cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) return JPEG_SUSPENDED; } /* OK, output from the virtual arrays. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Don't bother to IDCT an uninteresting component. */ if (! compptr->component_needed) continue; /* Align the virtual buffer for this component. */ buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], cinfo->output_iMCU_row * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); /* Count non-dummy DCT block rows in this iMCU row. */ if (cinfo->output_iMCU_row < last_iMCU_row) block_rows = compptr->v_samp_factor; else { /* NB: can't use last_row_height here; it is input-side-dependent! */ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } inverse_DCT = cinfo->idct->inverse_DCT[ci]; output_ptr = output_buf[ci]; /* Loop over all DCT blocks to be processed. */ for (block_row = 0; block_row < block_rows; block_row++) { buffer_ptr = buffer[block_row]; output_col = 0; for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, output_ptr, output_col); buffer_ptr++; output_col += compptr->DCT_h_scaled_size; } output_ptr += compptr->DCT_v_scaled_size; } } if (++(cinfo->output_iMCU_row) <= last_iMCU_row) return JPEG_ROW_COMPLETED; return JPEG_SCAN_COMPLETED; } #endif /* D_MULTISCAN_FILES_SUPPORTED */ #ifdef BLOCK_SMOOTHING_SUPPORTED /* * This code applies interblock smoothing as described by section K.8 * of the JPEG standard: the first 5 AC coefficients are estimated from * the DC values of a DCT block and its 8 neighboring blocks. * We apply smoothing only for progressive JPEG decoding, and only if * the coefficients it can estimate are not yet known to full precision. */ /* Natural-order array positions of the first 5 zigzag-order coefficients */ #define Q01_POS 1 #define Q10_POS 8 #define Q20_POS 16 #define Q11_POS 9 #define Q02_POS 2 /* * Determine whether block smoothing is applicable and safe. * We also latch the current states of the coef_bits[] entries for the * AC coefficients; otherwise, if the input side of the decompressor * advances into a new scan, we might think the coefficients are known * more accurately than they really are. */ LOCAL(boolean) smoothing_ok (j_decompress_ptr cinfo) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; boolean smoothing_useful = FALSE; int ci, coefi; jpeg_component_info *compptr; JQUANT_TBL * qtable; int * coef_bits; int * coef_bits_latch; if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) return FALSE; /* Allocate latch area if not already done */ if (coef->coef_bits_latch == NULL) coef->coef_bits_latch = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * (SAVED_COEFS * SIZEOF(int))); coef_bits_latch = coef->coef_bits_latch; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* All components' quantization values must already be latched. */ if ((qtable = compptr->quant_table) == NULL) return FALSE; /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ if (qtable->quantval[0] == 0 || qtable->quantval[Q01_POS] == 0 || qtable->quantval[Q10_POS] == 0 || qtable->quantval[Q20_POS] == 0 || qtable->quantval[Q11_POS] == 0 || qtable->quantval[Q02_POS] == 0) return FALSE; /* DC values must be at least partly known for all components. */ coef_bits = cinfo->coef_bits[ci]; if (coef_bits[0] < 0) return FALSE; /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ for (coefi = 1; coefi <= 5; coefi++) { coef_bits_latch[coefi] = coef_bits[coefi]; if (coef_bits[coefi] != 0) smoothing_useful = TRUE; } coef_bits_latch += SAVED_COEFS; } return smoothing_useful; } /* * Variant of decompress_data for use when doing block smoothing. */ METHODDEF(int) decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION block_num, last_block_column; int ci, block_row, block_rows, access_rows; JBLOCKARRAY buffer; JBLOCKROW buffer_ptr, prev_block_row, next_block_row; JSAMPARRAY output_ptr; JDIMENSION output_col; jpeg_component_info *compptr; inverse_DCT_method_ptr inverse_DCT; boolean first_row, last_row; JBLOCK workspace; int *coef_bits; JQUANT_TBL *quanttbl; INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; int Al, pred; /* Force some input to be done if we are getting ahead of the input. */ while (cinfo->input_scan_number <= cinfo->output_scan_number && ! cinfo->inputctl->eoi_reached) { if (cinfo->input_scan_number == cinfo->output_scan_number) { /* If input is working on current scan, we ordinarily want it to * have completed the current row. But if input scan is DC, * we want it to keep one row ahead so that next block row's DC * values are up to date. */ JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) break; } if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) return JPEG_SUSPENDED; } /* OK, output from the virtual arrays. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Don't bother to IDCT an uninteresting component. */ if (! compptr->component_needed) continue; /* Count non-dummy DCT block rows in this iMCU row. */ if (cinfo->output_iMCU_row < last_iMCU_row) { block_rows = compptr->v_samp_factor; access_rows = block_rows * 2; /* this and next iMCU row */ last_row = FALSE; } else { /* NB: can't use last_row_height here; it is input-side-dependent! */ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; access_rows = block_rows; /* this iMCU row only */ last_row = TRUE; } /* Align the virtual buffer for this component. */ if (cinfo->output_iMCU_row > 0) { access_rows += compptr->v_samp_factor; /* prior iMCU row too */ buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, (JDIMENSION) access_rows, FALSE); buffer += compptr->v_samp_factor; /* point to current iMCU row */ first_row = FALSE; } else { buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); first_row = TRUE; } /* Fetch component-dependent info */ coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); quanttbl = compptr->quant_table; Q00 = quanttbl->quantval[0]; Q01 = quanttbl->quantval[Q01_POS]; Q10 = quanttbl->quantval[Q10_POS]; Q20 = quanttbl->quantval[Q20_POS]; Q11 = quanttbl->quantval[Q11_POS]; Q02 = quanttbl->quantval[Q02_POS]; inverse_DCT = cinfo->idct->inverse_DCT[ci]; output_ptr = output_buf[ci]; /* Loop over all DCT blocks to be processed. */ for (block_row = 0; block_row < block_rows; block_row++) { buffer_ptr = buffer[block_row]; if (first_row && block_row == 0) prev_block_row = buffer_ptr; else prev_block_row = buffer[block_row-1]; if (last_row && block_row == block_rows-1) next_block_row = buffer_ptr; else next_block_row = buffer[block_row+1]; /* We fetch the surrounding DC values using a sliding-register approach. * Initialize all nine here so as to do the right thing on narrow pics. */ DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; DC7 = DC8 = DC9 = (int) next_block_row[0][0]; output_col = 0; last_block_column = compptr->width_in_blocks - 1; for (block_num = 0; block_num <= last_block_column; block_num++) { /* Fetch current DCT block into workspace so we can modify it. */ jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); /* Update DC values */ if (block_num < last_block_column) { DC3 = (int) prev_block_row[1][0]; DC6 = (int) buffer_ptr[1][0]; DC9 = (int) next_block_row[1][0]; } /* Compute coefficient estimates per K.8. * An estimate is applied only if coefficient is still zero, * and is not known to be fully accurate. */ /* AC01 */ if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { num = 36 * Q00 * (DC4 - DC6); if (num >= 0) { pred = (int) (((Q01<<7) + num) / (Q01<<8)); if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { pred = (int) (((Q10<<7) + num) / (Q10<<8)); if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { pred = (int) (((Q20<<7) + num) / (Q20<<8)); if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { pred = (int) (((Q11<<7) + num) / (Q11<<8)); if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { pred = (int) (((Q02<<7) + num) / (Q02<<8)); if (Al > 0 && pred >= (1< 0 && pred >= (1<DCT_h_scaled_size; } output_ptr += compptr->DCT_v_scaled_size; } } if (++(cinfo->output_iMCU_row) <= last_iMCU_row) return JPEG_ROW_COMPLETED; return JPEG_SCAN_COMPLETED; } #endif /* BLOCK_SMOOTHING_SUPPORTED */ /* * Initialize coefficient buffer controller. */ GLOBAL(void) jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; if (need_full_buffer) { #ifdef D_MULTISCAN_FILES_SUPPORTED /* Allocate a full-image virtual array for each component, */ /* padded to a multiple of samp_factor DCT blocks in each direction. */ /* Note we ask for a pre-zeroed array. */ int ci, access_rows; jpeg_component_info *compptr; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller) - SIZEOF(coef->blk_buffer)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { access_rows = compptr->v_samp_factor; #ifdef BLOCK_SMOOTHING_SUPPORTED /* If block smoothing could be used, need a bigger window */ if (cinfo->progressive_mode) access_rows *= 3; #endif coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) access_rows); } coef->pub.consume_data = consume_data; coef->pub.decompress_data = decompress_data; coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { /* We only need a single-MCU buffer. */ JBLOCKARRAY blkp; JBLOCKROW buffer_ptr; int bi; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); buffer_ptr = coef->blk_buffer; if (cinfo->lim_Se == 0) /* DC only case: want to bypass later */ MEMZERO(buffer_ptr, SIZEOF(coef->blk_buffer)); blkp = coef->MCU_buffer; bi = D_MAX_BLOCKS_IN_MCU; do { *blkp++ = buffer_ptr++; } while (--bi); coef->pub.consume_data = dummy_consume_data; coef->pub.decompress_data = decompress_onepass; coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ } coef->pub.start_input_pass = start_input_pass; coef->pub.start_output_pass = start_output_pass; #ifdef BLOCK_SMOOTHING_SUPPORTED coef->coef_bits_latch = NULL; #endif cinfo->coef = &coef->pub; } fltk-1.4.3/jpeg/jdmerge.c0000644000175000017500000003634015004135251015321 0ustar albrechtalbrecht/* * jdmerge.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2013-2022 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains code for merged upsampling/color conversion. * * This file combines functions from jdsample.c and jdcolor.c; * read those files first to understand what's going on. * * When the chroma components are to be upsampled by simple replication * (ie, box filtering), we can save some work in color conversion by * calculating all the output pixels corresponding to a pair of chroma * samples at one time. In the conversion equations * R = Y + K1 * Cr * G = Y + K2 * Cb + K3 * Cr * B = Y + K4 * Cb * only the Y term varies among the group of pixels corresponding to a pair * of chroma samples, so the rest of the terms can be calculated just once. * At typical sampling ratios, this eliminates half or three-quarters * of the multiplications needed for color conversion. * * This file currently provides implementations for the following cases: * YCC => RGB color conversion only (YCbCr or BG_YCC). * Sampling ratios of 2h1v or 2h2v. * No scaling needed at upsample time. * Corner-aligned (non-CCIR601) sampling alignment. * Other special cases could be added, but in most applications these * are the only common cases. (For uncommon cases we fall back on * the more general code in jdsample.c and jdcolor.c.) */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #ifdef UPSAMPLE_MERGING_SUPPORTED #if RANGE_BITS < 2 /* Deliberate syntax err */ Sorry, this code requires 2 or more range extension bits. #endif /* Private subobject */ typedef struct { struct jpeg_upsampler pub; /* public fields */ /* Pointer to routine to do actual upsampling/conversion of one row group */ JMETHOD(void, upmethod, (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)); /* Private state for YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ int * Cb_b_tab; /* => table for Cb to B conversion */ INT32 * Cr_g_tab; /* => table for Cr to G conversion */ INT32 * Cb_g_tab; /* => table for Cb to G conversion */ /* For 2:1 vertical sampling, we produce two output rows at a time. * We need a "spare" row buffer to hold the second output row if the * application provides just a one-row buffer; we also use the spare * to discard the dummy last row if the image height is odd. */ JSAMPROW spare_row; boolean spare_full; /* T if spare buffer is occupied */ JDIMENSION out_row_width; /* samples per output row */ JDIMENSION rows_to_go; /* counts rows remaining in image */ } my_upsampler; typedef my_upsampler * my_upsample_ptr; #define SCALEBITS 16 /* speediest right-shift on some machines */ #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L<RGB and BG_YCC->RGB colorspace conversion. * This is taken directly from jdcolor.c; see that file for more info. */ LOCAL(void) build_ycc_rgb_table (j_decompress_ptr cinfo) /* Normal case, sYCC */ { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; int i; INT32 x; SHIFT_TEMPS upsample->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); upsample->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); upsample->Cr_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); upsample->Cb_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ /* Cr=>R value is nearest int to 1.402 * x */ upsample->Cr_r_tab[i] = (int) DESCALE(FIX(1.402) * x, SCALEBITS); /* Cb=>B value is nearest int to 1.772 * x */ upsample->Cb_b_tab[i] = (int) DESCALE(FIX(1.772) * x, SCALEBITS); /* Cr=>G value is scaled-up -0.714136286 * x */ upsample->Cr_g_tab[i] = (- FIX(0.714136286)) * x; /* Cb=>G value is scaled-up -0.344136286 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ upsample->Cb_g_tab[i] = (- FIX(0.344136286)) * x + ONE_HALF; } } LOCAL(void) build_bg_ycc_rgb_table (j_decompress_ptr cinfo) /* Wide gamut case, bg-sYCC */ { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; int i; INT32 x; SHIFT_TEMPS upsample->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); upsample->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); upsample->Cr_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); upsample->Cb_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ /* Cr=>R value is nearest int to 2.804 * x */ upsample->Cr_r_tab[i] = (int) DESCALE(FIX(2.804) * x, SCALEBITS); /* Cb=>B value is nearest int to 3.544 * x */ upsample->Cb_b_tab[i] = (int) DESCALE(FIX(3.544) * x, SCALEBITS); /* Cr=>G value is scaled-up -1.428272572 * x */ upsample->Cr_g_tab[i] = (- FIX(1.428272572)) * x; /* Cb=>G value is scaled-up -0.688272572 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ upsample->Cb_g_tab[i] = (- FIX(0.688272572)) * x + ONE_HALF; } } /* * Initialize for an upsampling pass. */ METHODDEF(void) start_pass_merged_upsample (j_decompress_ptr cinfo) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; /* Mark the spare buffer empty */ upsample->spare_full = FALSE; /* Initialize total-height counter for detecting bottom of image */ upsample->rows_to_go = cinfo->output_height; } /* * Control routine to do upsampling (and color conversion). * * The control routine just handles the row buffering considerations. */ METHODDEF(void) merged_2v_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) /* 2:1 vertical sampling case: may need a spare row. */ { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; JSAMPROW work_ptrs[2]; JDIMENSION num_rows; /* number of rows returned to caller */ if (upsample->spare_full) { /* If we have a spare row saved from a previous cycle, just return it. */ jcopy_sample_rows(& upsample->spare_row, output_buf + *out_row_ctr, 1, upsample->out_row_width); num_rows = 1; upsample->spare_full = FALSE; } else { /* Figure number of rows to return to caller. */ num_rows = 2; /* Not more than the distance to the end of the image. */ if (num_rows > upsample->rows_to_go) num_rows = upsample->rows_to_go; /* And not more than what the client can accept: */ out_rows_avail -= *out_row_ctr; if (num_rows > out_rows_avail) num_rows = out_rows_avail; /* Create output pointer array for upsampler. */ work_ptrs[0] = output_buf[*out_row_ctr]; if (num_rows > 1) { work_ptrs[1] = output_buf[*out_row_ctr + 1]; } else { work_ptrs[1] = upsample->spare_row; upsample->spare_full = TRUE; } /* Now do the upsampling. */ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); } /* Adjust counts */ *out_row_ctr += num_rows; upsample->rows_to_go -= num_rows; /* When the buffer is emptied, declare this input row group consumed */ if (! upsample->spare_full) (*in_row_group_ctr)++; } METHODDEF(void) merged_1v_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) /* 1:1 vertical sampling case: much easier, never need a spare row. */ { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; /* Just do the upsampling. */ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, output_buf + *out_row_ctr); /* Adjust counts */ (*out_row_ctr)++; (*in_row_group_ctr)++; } /* * These are the routines invoked by the control routines to do * the actual upsampling/conversion. One row group is processed per call. * * Note: since we may be writing directly into application-supplied buffers, * we have to be honest about the output width; we can't assume the buffer * has been rounded up to an even width. */ /* * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. */ METHODDEF(void) h2v1_merged_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; register JSAMPROW outptr; JSAMPROW inptr0, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; int * Crrtab = upsample->Cr_r_tab; int * Cbbtab = upsample->Cb_b_tab; INT32 * Crgtab = upsample->Cr_g_tab; INT32 * Cbgtab = upsample->Cb_g_tab; SHIFT_TEMPS inptr0 = input_buf[0][in_row_group_ctr]; inptr1 = input_buf[1][in_row_group_ctr]; inptr2 = input_buf[2][in_row_group_ctr]; outptr = output_buf[0]; /* Loop for each pair of output pixels */ for (col = cinfo->output_width >> 1; col > 0; col--) { /* Do the chroma part of the calculation */ cb = GETJSAMPLE(*inptr1++); cr = GETJSAMPLE(*inptr2++); cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; cred = Crrtab[cr]; /* Fetch 2 Y values and emit 2 pixels */ y = GETJSAMPLE(*inptr0++); outptr[RGB_RED] = range_limit[y + cred]; outptr[RGB_GREEN] = range_limit[y + cgreen]; outptr[RGB_BLUE] = range_limit[y + cblue]; outptr += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr0++); outptr[RGB_RED] = range_limit[y + cred]; outptr[RGB_GREEN] = range_limit[y + cgreen]; outptr[RGB_BLUE] = range_limit[y + cblue]; outptr += RGB_PIXELSIZE; } /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { y = GETJSAMPLE(*inptr0); cb = GETJSAMPLE(*inptr1); cr = GETJSAMPLE(*inptr2); outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; outptr[RGB_GREEN] = range_limit[y + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))]; outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; } } /* * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. */ METHODDEF(void) h2v2_merged_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; register JSAMPROW outptr0, outptr1; JSAMPROW inptr00, inptr01, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; int * Crrtab = upsample->Cr_r_tab; int * Cbbtab = upsample->Cb_b_tab; INT32 * Crgtab = upsample->Cr_g_tab; INT32 * Cbgtab = upsample->Cb_g_tab; SHIFT_TEMPS inptr00 = input_buf[0][in_row_group_ctr*2]; inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; inptr1 = input_buf[1][in_row_group_ctr]; inptr2 = input_buf[2][in_row_group_ctr]; outptr0 = output_buf[0]; outptr1 = output_buf[1]; /* Loop for each group of output pixels */ for (col = cinfo->output_width >> 1; col > 0; col--) { /* Do the chroma part of the calculation */ cb = GETJSAMPLE(*inptr1++); cr = GETJSAMPLE(*inptr2++); cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; cred = Crrtab[cr]; /* Fetch 4 Y values and emit 4 pixels */ y = GETJSAMPLE(*inptr00++); outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; outptr0 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr00++); outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; outptr0 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr01++); outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; outptr1 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr01++); outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; outptr1 += RGB_PIXELSIZE; } /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { cb = GETJSAMPLE(*inptr1); cr = GETJSAMPLE(*inptr2); cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; cred = Crrtab[cr]; y = GETJSAMPLE(*inptr00); outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; y = GETJSAMPLE(*inptr01); outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; } } /* * Module initialization routine for merged upsampling/color conversion. * * NB: this is called under the conditions determined by use_merged_upsample() * in jdmaster.c. That routine MUST correspond to the actual capabilities * of this module; no safety checks are made here. */ GLOBAL(void) jinit_merged_upsampler (j_decompress_ptr cinfo) { my_upsample_ptr upsample; upsample = (my_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_upsampler)); cinfo->upsample = &upsample->pub; upsample->pub.start_pass = start_pass_merged_upsample; upsample->pub.need_context_rows = FALSE; upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; if (cinfo->max_v_samp_factor == 2) { upsample->pub.upsample = merged_2v_upsample; upsample->upmethod = h2v2_merged_upsample; /* Allocate a spare row buffer */ upsample->spare_row = (JSAMPROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t) upsample->out_row_width * SIZEOF(JSAMPLE)); } else { upsample->pub.upsample = merged_1v_upsample; upsample->upmethod = h2v1_merged_upsample; /* No spare row needed */ upsample->spare_row = NULL; } if (cinfo->jpeg_color_space == JCS_BG_YCC) build_bg_ycc_rgb_table(cinfo); else build_ycc_rgb_table(cinfo); } #endif /* UPSAMPLE_MERGING_SUPPORTED */ fltk-1.4.3/jpeg/libjpeg.txt0000644000175000017500000047771315004135251015732 0ustar albrechtalbrechtUSING THE IJG JPEG LIBRARY Copyright (C) 1994-2023, Thomas G. Lane, Guido Vollbeding. This file is part of the Independent JPEG Group's software. For conditions of distribution and use, see the accompanying README file. This file describes how to use the IJG JPEG library within an application program. Read it if you want to write a program that uses the library. The file example.c provides heavily commented skeleton code for calling the JPEG library. Also see jpeglib.h (the include file to be used by application programs) for full details about data structures and function parameter lists. The library source code, of course, is the ultimate reference. Note that there have been *major* changes from the application interface presented by IJG version 4 and earlier versions. The old design had several inherent limitations, and it had accumulated a lot of cruft as we added features while trying to minimize application-interface changes. We have sacrificed backward compatibility in the version 5 rewrite, but we think the improvements justify this. TABLE OF CONTENTS ----------------- Overview: Functions provided by the library Outline of typical usage Basic library usage: Data formats Compression details Decompression details Mechanics of usage: include files, linking, etc Advanced features: Compression parameter selection Decompression parameter selection Special color spaces Error handling Compressed data handling (source and destination managers) I/O suspension Progressive JPEG support Buffered-image mode Abbreviated datastreams and multiple images Special markers Raw (downsampled) image data Really raw data: DCT coefficients Progress monitoring Memory management Memory usage Library compile-time options Portability considerations Notes for MS-DOS implementors You should read at least the overview and basic usage sections before trying to program with the library. The sections on advanced features can be read if and when you need them. OVERVIEW ======== Functions provided by the library --------------------------------- The IJG JPEG library provides C code to read and write JPEG-compressed image files. The surrounding application program receives or supplies image data a scanline at a time, using a straightforward uncompressed image format. All details of color conversion and other preprocessing/postprocessing can be handled by the library. The library includes a substantial amount of code that is not covered by the JPEG standard but is necessary for typical applications of JPEG. These functions preprocess the image before JPEG compression or postprocess it after decompression. They include colorspace conversion, downsampling/upsampling, and color quantization. The application indirectly selects use of this code by specifying the format in which it wishes to supply or receive image data. For example, if colormapped output is requested, then the decompression library automatically invokes color quantization. A wide range of quality vs. speed tradeoffs are possible in JPEG processing, and even more so in decompression postprocessing. The decompression library provides multiple implementations that cover most of the useful tradeoffs, ranging from very-high-quality down to fast-preview operation. On the compression side we have generally not provided low-quality choices, since compression is normally less time-critical. It should be understood that the low-quality modes may not meet the JPEG standard's accuracy requirements; nonetheless, they are useful for viewers. A word about functions *not* provided by the library. We handle a subset of the ISO JPEG standard; most baseline, extended-sequential, and progressive JPEG processes are supported. (Our subset includes all features now in common use.) Unsupported ISO options include: * Hierarchical storage * Lossless JPEG * DNL marker * Nonintegral subsampling ratios We support 8-bit to 12-bit data precision, but this is a compile-time choice rather than a run-time choice; hence it is difficult to use different precisions in a single application. By itself, the library handles only interchange JPEG datastreams --- in particular the widely used JFIF file format. The library can be used by surrounding code to process interchange or abbreviated JPEG datastreams that are embedded in more complex file formats. (For example, this library is used by the free LIBTIFF library to support JPEG compression in TIFF.) Outline of typical usage ------------------------ The rough outline of a JPEG compression operation is: Allocate and initialize a JPEG compression object Specify the destination for the compressed data (eg, a file) Set parameters for compression, including image size & colorspace jpeg_start_compress(...); while (scan lines remain to be written) jpeg_write_scanlines(...); jpeg_finish_compress(...); Release the JPEG compression object A JPEG compression object holds parameters and working state for the JPEG library. We make creation/destruction of the object separate from starting or finishing compression of an image; the same object can be re-used for a series of image compression operations. This makes it easy to re-use the same parameter settings for a sequence of images. Re-use of a JPEG object also has important implications for processing abbreviated JPEG datastreams, as discussed later. The image data to be compressed is supplied to jpeg_write_scanlines() from in-memory buffers. If the application is doing file-to-file compression, reading image data from the source file is the application's responsibility. The library emits compressed data by calling a "data destination manager", which typically will write the data into a file; but the application can provide its own destination manager to do something else. Similarly, the rough outline of a JPEG decompression operation is: Allocate and initialize a JPEG decompression object Specify the source of the compressed data (eg, a file) Call jpeg_read_header() to obtain image info Set parameters for decompression jpeg_start_decompress(...); while (scan lines remain to be read) jpeg_read_scanlines(...); jpeg_finish_decompress(...); Release the JPEG decompression object This is comparable to the compression outline except that reading the datastream header is a separate step. This is helpful because information about the image's size, colorspace, etc is available when the application selects decompression parameters. For example, the application can choose an output scaling ratio that will fit the image into the available screen size. The decompression library obtains compressed data by calling a data source manager, which typically will read the data from a file; but other behaviors can be obtained with a custom source manager. Decompressed data is delivered into in-memory buffers passed to jpeg_read_scanlines(). It is possible to abort an incomplete compression or decompression operation by calling jpeg_abort(); or, if you do not need to retain the JPEG object, simply release it by calling jpeg_destroy(). JPEG compression and decompression objects are two separate struct types. However, they share some common fields, and certain routines such as jpeg_destroy() can work on either type of object. The JPEG library has no static variables: all state is in the compression or decompression object. Therefore it is possible to process multiple compression and decompression operations concurrently, using multiple JPEG objects. Both compression and decompression can be done in an incremental memory-to- memory fashion, if suitable source/destination managers are used. See the section on "I/O suspension" for more details. BASIC LIBRARY USAGE =================== Data formats ------------ Before diving into procedural details, it is helpful to understand the image data format that the JPEG library expects or returns. The standard input image format is a rectangular array of pixels, with each pixel having the same number of "component" or "sample" values (color channels). You must specify how many components there are and the colorspace interpretation of the components. Most applications will use RGB data (three components per pixel) or grayscale data (one component per pixel). PLEASE NOTE THAT RGB DATA IS THREE SAMPLES PER PIXEL, GRAYSCALE ONLY ONE. A remarkable number of people manage to miss this, only to find that their programs don't work with grayscale JPEG files. There is no provision for colormapped input. JPEG files are always full-color or full grayscale (or sometimes another colorspace such as CMYK). You can feed in a colormapped image by expanding it to full-color format. However JPEG often doesn't work very well with source data that has been colormapped, because of dithering noise. This is discussed in more detail in the JPEG FAQ and the other references mentioned in the README file. Pixels are stored by scanlines, with each scanline running from left to right. The component values for each pixel are adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit RGB color. Each scanline is an array of data type JSAMPLE --- which is typically "unsigned char", unless you've changed jmorecfg.h. (You can also change the RGB pixel layout, say to B,G,R order, by modifying jmorecfg.h. But see the restrictions listed in that file before doing so.) A 2-D array of pixels is formed by making a list of pointers to the starts of scanlines; so the scanlines need not be physically adjacent in memory. Even if you process just one scanline at a time, you must make a one-element pointer array to conform to this structure. Pointers to JSAMPLE rows are of type JSAMPROW, and the pointer to the pointer array is of type JSAMPARRAY. The library accepts or supplies one or more complete scanlines per call. It is not possible to process part of a row at a time. Scanlines are always processed top-to-bottom. You can process an entire image in one call if you have it all in memory, but usually it's simplest to process one scanline at a time. For best results, source data values should have the precision specified by BITS_IN_JSAMPLE (normally 8 bits). For instance, if you choose to compress data that's only 6 bits/channel, you should left-justify each value in a byte before passing it to the compressor. If you need to compress data that has more than 8 bits/channel, compile with BITS_IN_JSAMPLE = 9 to 12. (See "Library compile-time options", later.) The data format returned by the decompressor is the same in all details, except that colormapped output is supported. (Again, a JPEG file is never colormapped. But you can ask the decompressor to perform on-the-fly color quantization to deliver colormapped output.) If you request colormapped output then the returned data array contains a single JSAMPLE per pixel; its value is an index into a color map. The color map is represented as a 2-D JSAMPARRAY in which each row holds the values of one color component, that is, colormap[i][j] is the value of the i'th color component for pixel value (map index) j. Note that since the colormap indexes are stored in JSAMPLEs, the maximum number of colors is limited by the size of JSAMPLE (ie, at most 256 colors for an 8-bit JPEG library). Compression details ------------------- Here we revisit the JPEG compression outline given in the overview. 1. Allocate and initialize a JPEG compression object. A JPEG compression object is a "struct jpeg_compress_struct". (It also has a bunch of subsidiary structures which are allocated via malloc(), but the application doesn't control those directly.) This struct can be just a local variable in the calling routine, if a single routine is going to execute the whole JPEG compression sequence. Otherwise it can be static or allocated from malloc(). You will also need a structure representing a JPEG error handler. The part of this that the library cares about is a "struct jpeg_error_mgr". If you are providing your own error handler, you'll typically want to embed the jpeg_error_mgr struct in a larger structure; this is discussed later under "Error handling". For now we'll assume you are just using the default error handler. The default error handler will print JPEG error/warning messages on stderr, and it will call exit() if a fatal error occurs. You must initialize the error handler structure, store a pointer to it into the JPEG object's "err" field, and then call jpeg_create_compress() to initialize the rest of the JPEG object. Typical code for this step, if you are using the default error handler, is struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; ... cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_create_compress allocates a small amount of memory, so it could fail if you are out of memory. In that case it will exit via the error handler; that's why the error handler must be initialized first. 2. Specify the destination for the compressed data (eg, a file). As previously mentioned, the JPEG library delivers compressed data to a "data destination" module. The library includes one data destination module which knows how to write to memory or to a file (or any stdio stream). You can use your own destination module if you want to do something else, as discussed later. If you use the standard destination module, you must open the target stdio stream beforehand. Typical code for this step looks like: FILE * outfile; ... if ((outfile = fopen(filename, "wb")) == NULL) { fprintf(stderr, "can't open %s\n", filename); exit(1); } jpeg_stdio_dest(&cinfo, outfile); where the last line invokes the standard destination module. WARNING: it is critical that the binary compressed data be delivered to the output file unchanged. On non-Unix systems the stdio library may perform newline translation or otherwise corrupt binary data. To suppress this behavior, you may need to use a "b" option to fopen (as shown above), or use setmode() or another routine to put the stdio stream in binary mode. See cjpeg.c and djpeg.c for code that has been found to work on many systems. You can select the data destination after setting other parameters (step 3), if that's more convenient. You may not change the destination between calling jpeg_start_compress() and jpeg_finish_compress(). 3. Set parameters for compression, including image size & colorspace. You must supply information about the source image by setting the following fields in the JPEG object (cinfo structure): image_width Width of image, in pixels image_height Height of image, in pixels input_components Number of color channels (samples per pixel) in_color_space Color space of source image The image dimensions are, hopefully, obvious. JPEG supports image dimensions of 1 to 64K pixels in either direction. The input color space is typically RGB or grayscale, and input_components is 3 or 1 accordingly. (See "Special color spaces", later, for more info.) The in_color_space field must be assigned one of the J_COLOR_SPACE enum constants, typically JCS_RGB or JCS_GRAYSCALE. JPEG has a large number of compression parameters that determine how the image is encoded. Most applications don't need or want to know about all these parameters. You can set all the parameters to reasonable defaults by calling jpeg_set_defaults(); then, if there are particular values you want to change, you can do so after that. The "Compression parameter selection" section tells about all the parameters. You must set in_color_space correctly before calling jpeg_set_defaults(), because the defaults depend on the source image colorspace. However the other three source image parameters need not be valid until you call jpeg_start_compress(). There's no harm in calling jpeg_set_defaults() more than once, if that happens to be convenient. Typical code for a 24-bit RGB source image is cinfo.image_width = Width; /* image width and height, in pixels */ cinfo.image_height = Height; cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ jpeg_set_defaults(&cinfo); /* Make optional parameter settings here */ 4. jpeg_start_compress(...); After you have established the data destination and set all the necessary source image info and other parameters, call jpeg_start_compress() to begin a compression cycle. This will initialize internal state, allocate working storage, and emit the first few bytes of the JPEG datastream header. Typical code: jpeg_start_compress(&cinfo, TRUE); The "TRUE" parameter ensures that a complete JPEG interchange datastream will be written. This is appropriate in most cases. If you think you might want to use an abbreviated datastream, read the section on abbreviated datastreams, below. Once you have called jpeg_start_compress(), you may not alter any JPEG parameters or other fields of the JPEG object until you have completed the compression cycle. 5. while (scan lines remain to be written) jpeg_write_scanlines(...); Now write all the required image data by calling jpeg_write_scanlines() one or more times. You can pass one or more scanlines in each call, up to the total image height. In most applications it is convenient to pass just one or a few scanlines at a time. The expected format for the passed data is discussed under "Data formats", above. Image data should be written in top-to-bottom scanline order. The JPEG spec contains some weasel wording about how top and bottom are application-defined terms (a curious interpretation of the English language...) but if you want your files to be compatible with everyone else's, you WILL use top-to-bottom order. If the source data must be read in bottom-to-top order, you can use the JPEG library's virtual array mechanism to invert the data efficiently. Examples of this can be found in the sample application cjpeg. The library maintains a count of the number of scanlines written so far in the next_scanline field of the JPEG object. Usually you can just use this variable as the loop counter, so that the loop test looks like "while (cinfo.next_scanline < cinfo.image_height)". Code for this step depends heavily on the way that you store the source data. example.c shows the following code for the case of a full-size 2-D source array containing 3-byte RGB pixels: JSAMPROW row_pointer[1]; /* pointer to a single row */ int row_stride; /* physical row width in buffer */ row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_write_scanlines() returns the number of scanlines actually written. This will normally be equal to the number passed in, so you can usually ignore the return value. It is different in just two cases: * If you try to write more scanlines than the declared image height, the additional scanlines are ignored. * If you use a suspending data destination manager, output buffer overrun will cause the compressor to return before accepting all the passed lines. This feature is discussed under "I/O suspension", below. The normal stdio destination manager will NOT cause this to happen. In any case, the return value is the same as the change in the value of next_scanline. 6. jpeg_finish_compress(...); After all the image data has been written, call jpeg_finish_compress() to complete the compression cycle. This step is ESSENTIAL to ensure that the last bufferload of data is written to the data destination. jpeg_finish_compress() also releases working memory associated with the JPEG object. Typical code: jpeg_finish_compress(&cinfo); If using the stdio destination manager, don't forget to close the output stdio stream (if necessary) afterwards. If you have requested a multi-pass operating mode, such as Huffman code optimization, jpeg_finish_compress() will perform the additional passes using data buffered by the first pass. In this case jpeg_finish_compress() may take quite a while to complete. With the default compression parameters, this will not happen. It is an error to call jpeg_finish_compress() before writing the necessary total number of scanlines. If you wish to abort compression, call jpeg_abort() as discussed below. After completing a compression cycle, you may dispose of the JPEG object as discussed next, or you may use it to compress another image. In that case return to step 2, 3, or 4 as appropriate. If you do not change the destination manager, the new datastream will be written to the same target. If you do not change any JPEG parameters, the new datastream will be written with the same parameters as before. Note that you can change the input image dimensions freely between cycles, but if you change the input colorspace, you should call jpeg_set_defaults() to adjust for the new colorspace; and then you'll need to repeat all of step 3. 7. Release the JPEG compression object. When you are done with a JPEG compression object, destroy it by calling jpeg_destroy_compress(). This will free all subsidiary memory (regardless of the previous state of the object). Or you can call jpeg_destroy(), which works for either compression or decompression objects --- this may be more convenient if you are sharing code between compression and decompression cases. (Actually, these routines are equivalent except for the declared type of the passed pointer. To avoid gripes from ANSI C compilers, jpeg_destroy() should be passed a j_common_ptr.) If you allocated the jpeg_compress_struct structure from malloc(), freeing it is your responsibility --- jpeg_destroy() won't. Ditto for the error handler structure. Typical code: jpeg_destroy_compress(&cinfo); 8. Aborting. If you decide to abort a compression cycle before finishing, you can clean up in either of two ways: * If you don't need the JPEG object any more, just call jpeg_destroy_compress() or jpeg_destroy() to release memory. This is legitimate at any point after calling jpeg_create_compress() --- in fact, it's safe even if jpeg_create_compress() fails. * If you want to re-use the JPEG object, call jpeg_abort_compress(), or call jpeg_abort() which works on both compression and decompression objects. This will return the object to an idle state, releasing any working memory. jpeg_abort() is allowed at any time after successful object creation. Note that cleaning up the data destination, if required, is your responsibility; neither of these routines will call term_destination(). (See "Compressed data handling", below, for more about that.) jpeg_destroy() and jpeg_abort() are the only safe calls to make on a JPEG object that has reported an error by calling error_exit (see "Error handling" for more info). The internal state of such an object is likely to be out of whack. Either of these two routines will return the object to a known state. Decompression details --------------------- Here we revisit the JPEG decompression outline given in the overview. 1. Allocate and initialize a JPEG decompression object. This is just like initialization for compression, as discussed above, except that the object is a "struct jpeg_decompress_struct" and you call jpeg_create_decompress(). Error handling is exactly the same. Typical code: struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; ... cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); (Both here and in the IJG code, we usually use variable name "cinfo" for both compression and decompression objects.) 2. Specify the source of the compressed data (eg, a file). As previously mentioned, the JPEG library reads compressed data from a "data source" module. The library includes one data source module which knows how to read from memory or from a file (or any stdio stream). You can use your own source module if you want to do something else, as discussed later. If you use the standard source module, you must open the source stdio stream beforehand. Typical code for this step looks like: FILE * infile; ... if ((infile = fopen(filename, "rb")) == NULL) { fprintf(stderr, "can't open %s\n", filename); exit(1); } jpeg_stdio_src(&cinfo, infile); where the last line invokes the standard source module. WARNING: it is critical that the binary compressed data be read unchanged. On non-Unix systems the stdio library may perform newline translation or otherwise corrupt binary data. To suppress this behavior, you may need to use a "b" option to fopen (as shown above), or use setmode() or another routine to put the stdio stream in binary mode. See cjpeg.c and djpeg.c for code that has been found to work on many systems. You may not change the data source between calling jpeg_read_header() and jpeg_finish_decompress(). If you wish to read a series of JPEG images from a single source file, you should repeat the jpeg_read_header() to jpeg_finish_decompress() sequence without reinitializing either the JPEG object or the data source module; this prevents buffered input data from being discarded. 3. Call jpeg_read_header() to obtain image info. Typical code for this step is just jpeg_read_header(&cinfo, TRUE); This will read the source datastream header markers, up to the beginning of the compressed data proper. On return, the image dimensions and other info have been stored in the JPEG object. The application may wish to consult this information before selecting decompression parameters. More complex code is necessary if * A suspending data source is used --- in that case jpeg_read_header() may return before it has read all the header data. See "I/O suspension", below. The normal stdio source manager will NOT cause this to happen. * Abbreviated JPEG files are to be processed --- see the section on abbreviated datastreams. Standard applications that deal only in interchange JPEG files need not be concerned with this case either. It is permissible to stop at this point if you just wanted to find out the image dimensions and other header info for a JPEG file. In that case, call jpeg_destroy() when you are done with the JPEG object, or call jpeg_abort() to return it to an idle state before selecting a new data source and reading another header. 4. Set parameters for decompression. jpeg_read_header() sets appropriate default decompression parameters based on the properties of the image (in particular, its colorspace). However, you may well want to alter these defaults before beginning the decompression. For example, the default is to produce full color output from a color file. If you want colormapped output you must ask for it. Other options allow the returned image to be scaled and allow various speed/quality tradeoffs to be selected. "Decompression parameter selection", below, gives details. If the defaults are appropriate, nothing need be done at this step. Note that all default values are set by each call to jpeg_read_header(). If you reuse a decompression object, you cannot expect your parameter settings to be preserved across cycles, as you can for compression. You must set desired parameter values each time. 5. jpeg_start_decompress(...); Once the parameter values are satisfactory, call jpeg_start_decompress() to begin decompression. This will initialize internal state, allocate working memory, and prepare for returning data. Typical code is just jpeg_start_decompress(&cinfo); If you have requested a multi-pass operating mode, such as 2-pass color quantization, jpeg_start_decompress() will do everything needed before data output can begin. In this case jpeg_start_decompress() may take quite a while to complete. With a single-scan (non progressive) JPEG file and default decompression parameters, this will not happen; jpeg_start_decompress() will return quickly. After this call, the final output image dimensions, including any requested scaling, are available in the JPEG object; so is the selected colormap, if colormapped output has been requested. Useful fields include output_width image width and height, as scaled output_height out_color_components # of color components in out_color_space output_components # of color components returned per pixel colormap the selected colormap, if any actual_number_of_colors number of entries in colormap output_components is 1 (a colormap index) when quantizing colors; otherwise it equals out_color_components. It is the number of JSAMPLE values that will be emitted per pixel in the output arrays. Typically you will need to allocate data buffers to hold the incoming image. You will need output_width * output_components JSAMPLEs per scanline in your output buffer, and a total of output_height scanlines will be returned. Note: if you are using the JPEG library's internal memory manager to allocate data buffers (as djpeg does), then the manager's protocol requires that you request large buffers *before* calling jpeg_start_decompress(). This is a little tricky since the output_XXX fields are not normally valid then. You can make them valid by calling jpeg_calc_output_dimensions() after setting the relevant parameters (scaling, output color space, and quantization flag). 6. while (scan lines remain to be read) jpeg_read_scanlines(...); Now you can read the decompressed image data by calling jpeg_read_scanlines() one or more times. At each call, you pass in the maximum number of scanlines to be read (ie, the height of your working buffer); jpeg_read_scanlines() will return up to that many lines. The return value is the number of lines actually read. The format of the returned data is discussed under "Data formats", above. Don't forget that grayscale and color JPEGs will return different data formats! Image data is returned in top-to-bottom scanline order. If you must write out the image in bottom-to-top order, you can use the JPEG library's virtual array mechanism to invert the data efficiently. Examples of this can be found in the sample application djpeg. The library maintains a count of the number of scanlines returned so far in the output_scanline field of the JPEG object. Usually you can just use this variable as the loop counter, so that the loop test looks like "while (cinfo.output_scanline < cinfo.output_height)". (Note that the test should NOT be against image_height, unless you never use scaling. The image_height field is the height of the original unscaled image.) The return value always equals the change in the value of output_scanline. If you don't use a suspending data source, it is safe to assume that jpeg_read_scanlines() reads at least one scanline per call, until the bottom of the image has been reached. If you use a buffer larger than one scanline, it is NOT safe to assume that jpeg_read_scanlines() fills it. (The current implementation returns only a few scanlines per call, no matter how large a buffer you pass.) So you must always provide a loop that calls jpeg_read_scanlines() repeatedly until the whole image has been read. 7. jpeg_finish_decompress(...); After all the image data has been read, call jpeg_finish_decompress() to complete the decompression cycle. This causes working memory associated with the JPEG object to be released. Typical code: jpeg_finish_decompress(&cinfo); If using the stdio source manager, don't forget to close the source stdio stream if necessary. It is an error to call jpeg_finish_decompress() before reading the correct total number of scanlines. If you wish to abort decompression, call jpeg_abort() as discussed below. After completing a decompression cycle, you may dispose of the JPEG object as discussed next, or you may use it to decompress another image. In that case return to step 2 or 3 as appropriate. If you do not change the source manager, the next image will be read from the same source. 8. Release the JPEG decompression object. When you are done with a JPEG decompression object, destroy it by calling jpeg_destroy_decompress() or jpeg_destroy(). The previous discussion of destroying compression objects applies here too. Typical code: jpeg_destroy_decompress(&cinfo); 9. Aborting. You can abort a decompression cycle by calling jpeg_destroy_decompress() or jpeg_destroy() if you don't need the JPEG object any more, or jpeg_abort_decompress() or jpeg_abort() if you want to reuse the object. The previous discussion of aborting compression cycles applies here too. Mechanics of usage: include files, linking, etc ----------------------------------------------- Applications using the JPEG library should include the header file jpeglib.h to obtain declarations of data types and routines. Before including jpeglib.h, include system headers that define at least the typedefs FILE and size_t. On ANSI-conforming systems, including is sufficient; on older Unix systems, you may need to define size_t. If the application needs to refer to individual JPEG library error codes, also include jerror.h to define those symbols. jpeglib.h indirectly includes the files jconfig.h and jmorecfg.h. If you are installing the JPEG header files in a system directory, you will want to install all four files: jpeglib.h, jerror.h, jconfig.h, jmorecfg.h. The most convenient way to include the JPEG code into your executable program is to prepare a library file ("libjpeg.a", or a corresponding name on non-Unix machines) and reference it at your link step. If you use only half of the library (only compression or only decompression), only that much code will be included from the library, unless your linker is hopelessly brain-damaged. The supplied makefiles build libjpeg.a automatically (see install.txt). While you can build the JPEG library as a shared library if the whim strikes you, we don't really recommend it. The trouble with shared libraries is that at some point you'll probably try to substitute a new version of the library without recompiling the calling applications. That generally doesn't work because the parameter struct declarations usually change with each new version. In other words, the library's API is *not* guaranteed binary compatible across versions; we only try to ensure source-code compatibility. (In hindsight, it might have been smarter to hide the parameter structs from applications and introduce a ton of access functions instead. Too late now, however.) On some systems your application may need to set up a signal handler to ensure that temporary files are deleted if the program is interrupted. This is most critical if you are on MS-DOS and use the jmemdos.c memory manager back end; it will try to grab extended memory for temp files, and that space will NOT be freed automatically. See cjpeg.c or djpeg.c for an example signal handler. It may be worth pointing out that the core JPEG library does not actually require the stdio library: only the default source/destination managers and error handler need it. You can use the library in a stdio-less environment if you replace those modules and use jmemnobs.c (or another memory manager of your own devising). More info about the minimum system library requirements may be found in jinclude.h. ADVANCED FEATURES ================= Compression parameter selection ------------------------------- This section describes all the optional parameters you can set for JPEG compression, as well as the "helper" routines provided to assist in this task. Proper setting of some parameters requires detailed understanding of the JPEG standard; if you don't know what a parameter is for, it's best not to mess with it! See REFERENCES in the README file for pointers to more info about JPEG. It's a good idea to call jpeg_set_defaults() first, even if you plan to set all the parameters; that way your code is more likely to work with future JPEG libraries that have additional parameters. For the same reason, we recommend you use a helper routine where one is provided, in preference to twiddling cinfo fields directly. The helper routines are: jpeg_set_defaults (j_compress_ptr cinfo) This routine sets all JPEG parameters to reasonable defaults, using only the input image's color space (field in_color_space, which must already be set in cinfo). Many applications will only need to use this routine and perhaps jpeg_set_quality(). jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) Sets the JPEG file's colorspace (field jpeg_color_space) as specified, and sets other color-space-dependent parameters appropriately. See "Special color spaces", below, before using this. A large number of parameters, including all per-component parameters, are set by this routine; if you want to twiddle individual parameters you should call jpeg_set_colorspace() before rather than after. jpeg_default_colorspace (j_compress_ptr cinfo) Selects an appropriate JPEG colorspace based on cinfo->in_color_space, and calls jpeg_set_colorspace(). This is actually a subroutine of jpeg_set_defaults(). It's broken out in case you want to change just the colorspace-dependent JPEG parameters. jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) Constructs JPEG quantization tables appropriate for the indicated quality setting. The quality value is expressed on the 0..100 scale recommended by IJG (cjpeg's "-quality" switch uses this routine). Note that the exact mapping from quality values to tables may change in future IJG releases as more is learned about DCT quantization. If the force_baseline parameter is TRUE, then the quantization table entries are constrained to the range 1..255 for full JPEG baseline compatibility. In the current implementation, this only makes a difference for quality settings below 25, and it effectively prevents very small/low quality files from being generated. The IJG decoder is capable of reading the non-baseline files generated at low quality settings when force_baseline is FALSE, but other decoders may not be. jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, boolean force_baseline) Same as jpeg_set_quality() except that the generated tables are the sample tables given in the JPEC spec section K.1, multiplied by the specified scale factor (which is expressed as a percentage; thus scale_factor = 100 reproduces the spec's tables). Note that larger scale factors give lower quality. This entry point is useful for conforming to the Adobe PostScript DCT conventions, but we do not recommend linear scaling as a user-visible quality scale otherwise. force_baseline again constrains the computed table entries to 1..255. int jpeg_quality_scaling (int quality) Converts a value on the IJG-recommended quality scale to a linear scaling percentage. Note that this routine may change or go away in future releases --- IJG may choose to adopt a scaling method that can't be expressed as a simple scalar multiplier, in which case the premise of this routine collapses. Caveat user. jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline) Set default quantization tables with linear q_scale_factor[] values (see below). jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline) Allows an arbitrary quantization table to be created. which_tbl indicates which table slot to fill. basic_table points to an array of 64 unsigned ints given in normal array order. These values are multiplied by scale_factor/100 and then clamped to the range 1..65535 (or to 1..255 if force_baseline is TRUE). CAUTION: prior to library version 6a, jpeg_add_quant_table expected the basic table to be given in JPEG zigzag order. If you need to write code that works with either older or newer versions of this routine, you must check the library version number. Something like "#if JPEG_LIB_VERSION >= 61" is the right test. jpeg_simple_progression (j_compress_ptr cinfo) Generates a default scan script for writing a progressive-JPEG file. This is the recommended method of creating a progressive file, unless you want to make a custom scan sequence. You must ensure that the JPEG color space is set correctly before calling this routine. Compression parameters (cinfo fields) include: boolean arith_code If TRUE, use arithmetic coding. If FALSE, use Huffman coding. int block_size Set DCT block size. All N from 1 to 16 are possible. Default is 8 (baseline format). Larger values produce higher compression, smaller values produce higher quality. An exact DCT stage is possible with 1 or 2. With the default quality of 75 and default quantization tables the DCT+Quantization stage is lossless for value 1. Note that values other than 8 require a SmartScale capable decoder, introduced with IJG JPEG 8. Setting the block_size parameter for compression works with version 8c and later. J_DCT_METHOD dct_method Selects the algorithm used for the DCT step. Choices are: JDCT_ISLOW: slow but accurate integer algorithm JDCT_IFAST: faster, less accurate integer method JDCT_FLOAT: floating-point method JDCT_DEFAULT: default method (normally JDCT_ISLOW) JDCT_FASTEST: fastest method (normally JDCT_IFAST) The FLOAT method is very slightly more accurate than the ISLOW method, but may give different results on different machines due to varying roundoff behavior. The integer methods should give the same results on all machines. On machines with sufficiently fast FP hardware, the floating-point method may also be the fastest. The IFAST method is considerably less accurate than the other two; its use is not recommended if high quality is a concern. JDCT_DEFAULT and JDCT_FASTEST are macros configurable by each installation. unsigned int scale_num, scale_denom Scale the image by the fraction scale_num/scale_denom. Default is 1/1, or no scaling. Currently, the supported scaling ratios are M/N with all N from 1 to 16, where M is the destination DCT size, which is 8 by default (see block_size parameter above). (The library design allows for arbitrary scaling ratios but this is not likely to be implemented any time soon.) J_COLOR_SPACE jpeg_color_space int num_components The JPEG color space and corresponding number of components; see "Special color spaces", below, for more info. We recommend using jpeg_set_colorspace() if you want to change these. J_COLOR_TRANSFORM color_transform Internal color transform identifier, writes LSE marker if nonzero (requires decoder with inverse color transform support, introduced with IJG JPEG 9). Two values are currently possible: JCT_NONE and JCT_SUBTRACT_GREEN. Set this value for lossless RGB application *before* calling jpeg_set_colorspace(), because entropy table assignment in jpeg_set_colorspace() depends on color_transform. boolean optimize_coding TRUE causes the compressor to compute optimal Huffman coding tables for the image. This requires an extra pass over the data and therefore costs a good deal of space and time. The default is FALSE, which tells the compressor to use the supplied or default Huffman tables. In most cases optimal tables save only a few percent of file size compared to the default tables. Note that when this is TRUE, you need not supply Huffman tables at all, and any you do supply will be overwritten. unsigned int restart_interval int restart_in_rows To emit restart markers in the JPEG file, set one of these nonzero. Set restart_interval to specify the exact interval in MCU blocks. Set restart_in_rows to specify the interval in MCU rows. (If restart_in_rows is not 0, then restart_interval is set after the image width in MCUs is computed.) Defaults are zero (no restarts). One restart marker per MCU row is often a good choice. NOTE: the overhead of restart markers is higher in grayscale JPEG files than in color files, and MUCH higher in progressive JPEGs. If you use restarts, you may want to use larger intervals in those cases. const jpeg_scan_info * scan_info int num_scans By default, scan_info is NULL; this causes the compressor to write a single-scan sequential JPEG file. If not NULL, scan_info points to an array of scan definition records of length num_scans. The compressor will then write a JPEG file having one scan for each scan definition record. This is used to generate noninterleaved or progressive JPEG files. The library checks that the scan array defines a valid JPEG scan sequence. (jpeg_simple_progression creates a suitable scan definition array for progressive JPEG.) This is discussed further under "Progressive JPEG support". boolean do_fancy_downsampling If TRUE, use direct DCT scaling with DCT size > 8 for downsampling of chroma components. If FALSE, use only DCT size <= 8 and simple separate downsampling. Default is TRUE. For better image stability in multiple generation compression cycles it is preferable that this value matches the corresponding do_fancy_upsampling value in decompression. int smoothing_factor If non-zero, the input image is smoothed; the value should be 1 for minimal smoothing to 100 for maximum smoothing. Consult jcsample.c for details of the smoothing algorithm. The default is zero. boolean write_JFIF_header If TRUE, a JFIF APP0 marker is emitted. jpeg_set_defaults() and jpeg_set_colorspace() set this TRUE if a JFIF-legal JPEG color space (ie, YCbCr or grayscale) is selected, otherwise FALSE. UINT8 JFIF_major_version UINT8 JFIF_minor_version The version number to be written into the JFIF marker. jpeg_set_defaults() initializes the version to 1.01 (major=minor=1). You should set it to 1.02 (major=1, minor=2) if you plan to write any JFIF 1.02 extension markers. UINT8 density_unit UINT16 X_density UINT16 Y_density The resolution information to be written into the JFIF marker; not used otherwise. density_unit may be 0 for unknown, 1 for dots/inch, or 2 for dots/cm. The default values are 0,1,1 indicating square pixels of unknown size. boolean write_Adobe_marker If TRUE, an Adobe APP14 marker is emitted. jpeg_set_defaults() and jpeg_set_colorspace() set this TRUE if JPEG color space RGB, CMYK, or YCCK is selected, otherwise FALSE. It is generally a bad idea to set both write_JFIF_header and write_Adobe_marker. In fact, you probably shouldn't change the default settings at all --- the default behavior ensures that the JPEG file's color space can be recognized by the decoder. JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS] Pointers to coefficient quantization tables, one per table slot, or NULL if no table is defined for a slot. Usually these should be set via one of the above helper routines; jpeg_add_quant_table() is general enough to define any quantization table. The other routines will set up table slot 0 for luminance quality and table slot 1 for chrominance. int q_scale_factor[NUM_QUANT_TBLS] Linear quantization scaling factors (percentage, initialized 100) for use with jpeg_default_qtables(). See rdswitch.c and cjpeg.c for an example of usage. Note that the q_scale_factor[] fields are the "linear" scales, so you have to convert from user-defined ratings via jpeg_quality_scaling(). Here is an example code which corresponds to cjpeg -quality 90,70: jpeg_set_defaults(cinfo); /* Set luminance quality 90. */ cinfo->q_scale_factor[0] = jpeg_quality_scaling(90); /* Set chrominance quality 70. */ cinfo->q_scale_factor[1] = jpeg_quality_scaling(70); jpeg_default_qtables(cinfo, force_baseline); CAUTION: You must also set 1x1 subsampling for efficient separate color quality selection, since the default value used by library is 2x2: cinfo->comp_info[0].v_samp_factor = 1; cinfo->comp_info[0].h_samp_factor = 1; JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS] JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS] Pointers to Huffman coding tables, one per table slot, or NULL if no table is defined for a slot. Slots 0 and 1 are filled with the JPEG sample tables by jpeg_set_defaults(). If you need to allocate more table structures, jpeg_alloc_huff_table() may be used. Note that optimal Huffman tables can be computed for an image by setting optimize_coding, as discussed above; there's seldom any need to mess with providing your own Huffman tables. The actual dimensions of the JPEG image that will be written to the file are given by the following fields. These are computed from the input image dimensions and the compression parameters by jpeg_start_compress(). You can also call jpeg_calc_jpeg_dimensions() to obtain the values that will result from the current parameter settings. This can be useful if you are trying to pick a scaling ratio that will get close to a desired target size. JDIMENSION jpeg_width Actual dimensions of output image. JDIMENSION jpeg_height Per-component parameters are stored in the struct cinfo.comp_info[i] for component number i. Note that components here refer to components of the JPEG color space, *not* the source image color space. A suitably large comp_info[] array is allocated by jpeg_set_defaults(); if you choose not to use that routine, it's up to you to allocate the array. int component_id The one-byte identifier code to be recorded in the JPEG file for this component. For the standard color spaces, we recommend you leave the default values alone. int h_samp_factor int v_samp_factor Horizontal and vertical sampling factors for the component; must be 1..4 according to the JPEG standard. Note that larger sampling factors indicate a higher-resolution component; many people find this behavior quite unintuitive. The default values are 2,2 for luminance components and 1,1 for chrominance components, except for grayscale where 1,1 is used. int quant_tbl_no Quantization table number for component. The default value is 0 for luminance components and 1 for chrominance components. int dc_tbl_no int ac_tbl_no DC and AC entropy coding table numbers. The default values are 0 for luminance components and 1 for chrominance components. int component_index Must equal the component's index in comp_info[]. (Beginning in release v6, the compressor library will fill this in automatically; you don't have to.) Decompression parameter selection --------------------------------- Decompression parameter selection is somewhat simpler than compression parameter selection, since all of the JPEG internal parameters are recorded in the source file and need not be supplied by the application. (Unless you are working with abbreviated files, in which case see "Abbreviated datastreams", below.) Decompression parameters control the postprocessing done on the image to deliver it in a format suitable for the application's use. Many of the parameters control speed/quality tradeoffs, in which faster decompression may be obtained at the price of a poorer-quality image. The defaults select the highest quality (slowest) processing. The following fields in the JPEG object are set by jpeg_read_header() and may be useful to the application in choosing decompression parameters: JDIMENSION image_width Width and height of image JDIMENSION image_height int num_components Number of color components J_COLOR_SPACE jpeg_color_space Colorspace of image boolean saw_JFIF_marker TRUE if a JFIF APP0 marker was seen UINT8 JFIF_major_version Version information from JFIF marker UINT8 JFIF_minor_version UINT8 density_unit Resolution data from JFIF marker UINT16 X_density UINT16 Y_density boolean saw_Adobe_marker TRUE if an Adobe APP14 marker was seen UINT8 Adobe_transform Color transform code from Adobe marker The JPEG color space, unfortunately, is something of a guess since the JPEG standard proper does not provide a way to record it. In practice most files adhere to the JFIF or Adobe conventions, and the decoder will recognize these correctly. See "Special color spaces", below, for more info. The decompression parameters that determine the basic properties of the returned image are: J_COLOR_SPACE out_color_space Output color space. jpeg_read_header() sets an appropriate default based on jpeg_color_space; typically it will be RGB or grayscale. The application can change this field to request output in a different colorspace. For example, set it to JCS_GRAYSCALE to get grayscale output from a color file. (This is useful for previewing: grayscale output is faster than full color since the color components need not be processed.) Note that not all possible color space transforms are currently implemented; you may need to extend jdcolor.c if you want an unusual conversion. unsigned int scale_num, scale_denom Scale the image by the fraction scale_num/scale_denom. Currently, the supported scaling ratios are M/N with all M from 1 to 16, where N is the source DCT size, which is 8 for baseline JPEG. (The library design allows for arbitrary scaling ratios but this is not likely to be implemented any time soon.) The values are initialized by jpeg_read_header() with the source DCT size. For baseline JPEG this is 8/8. If you change only the scale_num value while leaving the other unchanged, then this specifies the DCT scaled size to be applied on the given input. For baseline JPEG this is equivalent to M/8 scaling, since the source DCT size for baseline JPEG is 8. Smaller scaling ratios permit significantly faster decoding since fewer pixels need be processed and a simpler IDCT method can be used. boolean quantize_colors If set TRUE, colormapped output will be delivered. Default is FALSE, meaning that full-color output will be delivered. The next three parameters are relevant only if quantize_colors is TRUE. int desired_number_of_colors Maximum number of colors to use in generating a library-supplied color map (the actual number of colors is returned in a different field). Default 256. Ignored when the application supplies its own color map. boolean two_pass_quantize If TRUE, an extra pass over the image is made to select a custom color map for the image. This usually looks a lot better than the one-size- fits-all colormap that is used otherwise. Default is TRUE. Ignored when the application supplies its own color map. J_DITHER_MODE dither_mode Selects color dithering method. Supported values are: JDITHER_NONE no dithering: fast, very low quality JDITHER_ORDERED ordered dither: moderate speed and quality JDITHER_FS Floyd-Steinberg dither: slow, high quality Default is JDITHER_FS. (At present, ordered dither is implemented only in the single-pass, standard-colormap case. If you ask for ordered dither when two_pass_quantize is TRUE or when you supply an external color map, you'll get F-S dithering.) When quantize_colors is TRUE, the target color map is described by the next two fields. colormap is set to NULL by jpeg_read_header(). The application can supply a color map by setting colormap non-NULL and setting actual_number_of_colors to the map size. Otherwise, jpeg_start_decompress() selects a suitable color map and sets these two fields itself. [Implementation restriction: at present, an externally supplied colormap is only accepted for 3-component output color spaces.] JSAMPARRAY colormap The color map, represented as a 2-D pixel array of out_color_components rows and actual_number_of_colors columns. Ignored if not quantizing. CAUTION: if the JPEG library creates its own colormap, the storage pointed to by this field is released by jpeg_finish_decompress(). Copy the colormap somewhere else first, if you want to save it. int actual_number_of_colors The number of colors in the color map. Additional decompression parameters that the application may set include: J_DCT_METHOD dct_method Selects the algorithm used for the DCT step. Choices are the same as described above for compression. boolean do_fancy_upsampling If TRUE, use direct DCT scaling with DCT size > 8 for upsampling of chroma components. If FALSE, use only DCT size <= 8 and simple separate upsampling. Default is TRUE. For better image stability in multiple generation compression cycles it is preferable that this value matches the corresponding do_fancy_downsampling value in compression. boolean do_block_smoothing If TRUE, interblock smoothing is applied in early stages of decoding progressive JPEG files; if FALSE, not. Default is TRUE. Early progression stages look "fuzzy" with smoothing, "blocky" without. In any case, block smoothing ceases to be applied after the first few AC coefficients are known to full accuracy, so it is relevant only when using buffered-image mode for progressive images. boolean enable_1pass_quant boolean enable_external_quant boolean enable_2pass_quant These are significant only in buffered-image mode, which is described in its own section below. The output image dimensions are given by the following fields. These are computed from the source image dimensions and the decompression parameters by jpeg_start_decompress(). You can also call jpeg_calc_output_dimensions() to obtain the values that will result from the current parameter settings. This can be useful if you are trying to pick a scaling ratio that will get close to a desired target size. It's also important if you are using the JPEG library's memory manager to allocate output buffer space, because you are supposed to request such buffers *before* jpeg_start_decompress(). JDIMENSION output_width Actual dimensions of output image. JDIMENSION output_height int out_color_components Number of color components in out_color_space. int output_components Number of color components returned. int rec_outbuf_height Recommended height of scanline buffer. When quantizing colors, output_components is 1, indicating a single color map index per pixel. Otherwise it equals out_color_components. The output arrays are required to be output_width * output_components JSAMPLEs wide. rec_outbuf_height is the recommended minimum height (in scanlines) of the buffer passed to jpeg_read_scanlines(). If the buffer is smaller, the library will still work, but time will be wasted due to unnecessary data copying. In high-quality modes, rec_outbuf_height is always 1, but some faster, lower-quality modes set it to larger values (typically 2 to 4). If you are going to ask for a high-speed processing mode, you may as well go to the trouble of honoring rec_outbuf_height so as to avoid data copying. (An output buffer larger than rec_outbuf_height lines is OK, but won't provide any material speed improvement over that height.) Special color spaces -------------------- The JPEG standard itself is "color blind" and doesn't specify any particular color space. It is customary to convert color data to a luminance/chrominance color space before compressing, since this permits greater compression. The existing JPEG file interchange format standards specify YCbCr or GRAYSCALE data (JFIF version 1), GRAYSCALE, RGB, YCbCr, CMYK, or YCCK (Adobe), or BG_RGB or BG_YCC (big gamut color spaces, JFIF version 2). For special applications such as multispectral images, other color spaces can be used, but it must be understood that such files will be unportable. The JPEG library can handle the most common colorspace conversions (namely RGB <=> YCbCr and CMYK <=> YCCK). It can also deal with data of an unknown color space, passing it through without conversion. If you deal extensively with an unusual color space, you can easily extend the library to understand additional color spaces and perform appropriate conversions. For compression, the source data's color space is specified by field in_color_space. This is transformed to the JPEG file's color space given by jpeg_color_space. jpeg_set_defaults() chooses a reasonable JPEG color space depending on in_color_space, but you can override this by calling jpeg_set_colorspace(). Of course you must select a supported transformation. jccolor.c currently supports the following transformations: RGB => YCbCr RGB => GRAYSCALE RGB => BG_YCC YCbCr => GRAYSCALE YCbCr => BG_YCC CMYK => YCCK plus the null transforms: GRAYSCALE => GRAYSCALE, RGB => RGB, BG_RGB => BG_RGB, YCbCr => YCbCr, BG_YCC => BG_YCC, CMYK => CMYK, YCCK => YCCK, and UNKNOWN => UNKNOWN. The file interchange format standards (JFIF and Adobe) specify APPn markers that indicate the color space of the JPEG file. It is important to ensure that these are written correctly, or omitted if the JPEG file's color space is not one of the ones supported by the interchange standards. jpeg_set_colorspace() will set the compression parameters to include or omit the APPn markers properly, so long as it is told the truth about the JPEG color space. For example, if you are writing some random 3-component color space without conversion, don't try to fake out the library by setting in_color_space and jpeg_color_space to JCS_YCbCr; use JCS_UNKNOWN. You may want to write an APPn marker of your own devising to identify the colorspace --- see "Special markers", below. When told that the color space is UNKNOWN, the library will default to using luminance-quality compression parameters for all color components. You may well want to change these parameters. See the source code for jpeg_set_colorspace(), in jcparam.c, for details. For decompression, the JPEG file's color space is given in jpeg_color_space, and this is transformed to the output color space out_color_space. jpeg_read_header's setting of jpeg_color_space can be relied on if the file conforms to JFIF or Adobe conventions, but otherwise it is no better than a guess. If you know the JPEG file's color space for certain, you can override jpeg_read_header's guess by setting jpeg_color_space. jpeg_read_header also selects a default output color space based on (its guess of) jpeg_color_space; set out_color_space to override this. Again, you must select a supported transformation. jdcolor.c currently supports YCbCr => RGB YCbCr => GRAYSCALE BG_YCC => RGB BG_YCC => GRAYSCALE RGB => GRAYSCALE GRAYSCALE => RGB YCCK => CMYK as well as the null transforms. (Since GRAYSCALE=>RGB is provided, an application can force grayscale JPEGs to look like color JPEGs if it only wants to handle one case.) The two-pass color quantizer, jquant2.c, is specialized to handle RGB data (it weights distances appropriately for RGB colors). You'll need to modify the code if you want to use it for non-RGB output color spaces. Note that jquant2.c is used to map to an application-supplied colormap as well as for the normal two-pass colormap selection process. CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK JPEG files: 0 represents 100% ink coverage, rather than 0% ink as you'd expect. This is arguably a bug in Photoshop, but if you need to work with Photoshop CMYK files, you will have to deal with it in your application. We cannot "fix" this in the library by inverting the data during the CMYK<=>YCCK transform, because that would break other applications, notably Ghostscript. Photoshop versions prior to 3.0 write EPS files containing JPEG-encoded CMYK data in the same inverted-YCCK representation used in bare JPEG files, but the surrounding PostScript code performs an inversion using the PS image operator. I am told that Photoshop 3.0 will write uninverted YCCK in EPS/JPEG files, and will omit the PS-level inversion. (But the data polarity used in bare JPEG files will not change in 3.0.) In either case, the JPEG library must not invert the data itself, or else Ghostscript would read these EPS files incorrectly. Error handling -------------- When the default error handler is used, any error detected inside the JPEG routines will cause a message to be printed on stderr, followed by exit(). You can supply your own error handling routines to override this behavior and to control the treatment of nonfatal warnings and trace/debug messages. The file example.c illustrates the most common case, which is to have the application regain control after an error rather than exiting. The JPEG library never writes any message directly; it always goes through the error handling routines. Three classes of messages are recognized: * Fatal errors: the library cannot continue. * Warnings: the library can continue, but the data is corrupt, and a damaged output image is likely to result. * Trace/informational messages. These come with a trace level indicating the importance of the message; you can control the verbosity of the program by adjusting the maximum trace level that will be displayed. You may, if you wish, simply replace the entire JPEG error handling module (jerror.c) with your own code. However, you can avoid code duplication by only replacing some of the routines depending on the behavior you need. This is accomplished by calling jpeg_std_error() as usual, but then overriding some of the method pointers in the jpeg_error_mgr struct, as illustrated by example.c. All of the error handling routines will receive a pointer to the JPEG object (a j_common_ptr which points to either a jpeg_compress_struct or a jpeg_decompress_struct; if you need to tell which, test the is_decompressor field). This struct includes a pointer to the error manager struct in its "err" field. Frequently, custom error handler routines will need to access additional data which is not known to the JPEG library or the standard error handler. The most convenient way to do this is to embed either the JPEG object or the jpeg_error_mgr struct in a larger structure that contains additional fields; then casting the passed pointer provides access to the additional fields. Again, see example.c for one way to do it. (Beginning with IJG version 6b, there is also a void pointer "client_data" in each JPEG object, which the application can also use to find related data. The library does not touch client_data at all.) The individual methods that you might wish to override are: error_exit (j_common_ptr cinfo) Receives control for a fatal error. Information sufficient to generate the error message has been stored in cinfo->err; call output_message to display it. Control must NOT return to the caller; generally this routine will exit() or longjmp() somewhere. Typically you would override this routine to get rid of the exit() default behavior. Note that if you continue processing, you should clean up the JPEG object with jpeg_abort() or jpeg_destroy(). output_message (j_common_ptr cinfo) Actual output of any JPEG message. Override this to send messages somewhere other than stderr. Note that this method does not know how to generate a message, only where to send it. format_message (j_common_ptr cinfo, char * buffer) Constructs a readable error message string based on the error info stored in cinfo->err. This method is called by output_message. Few applications should need to override this method. One possible reason for doing so is to implement dynamic switching of error message language. emit_message (j_common_ptr cinfo, int msg_level) Decide whether or not to emit a warning or trace message; if so, calls output_message. The main reason for overriding this method would be to abort on warnings. msg_level is -1 for warnings, 0 and up for trace messages. Only error_exit() and emit_message() are called from the rest of the JPEG library; the other two are internal to the error handler. The actual message texts are stored in an array of strings which is pointed to by the field err->jpeg_message_table. The messages are numbered from 0 to err->last_jpeg_message, and it is these code numbers that are used in the JPEG library code. You could replace the message texts (for instance, with messages in French or German) by changing the message table pointer. See jerror.h for the default texts. CAUTION: this table will almost certainly change or grow from one library version to the next. It may be useful for an application to add its own message texts that are handled by the same mechanism. The error handler supports a second "add-on" message table for this purpose. To define an addon table, set the pointer err->addon_message_table and the message numbers err->first_addon_message and err->last_addon_message. If you number the addon messages beginning at 1000 or so, you won't have to worry about conflicts with the library's built-in messages. See the sample applications cjpeg/djpeg for an example of using addon messages (the addon messages are defined in cderror.h). Actual invocation of the error handler is done via macros defined in jerror.h: ERREXITn(...) for fatal errors WARNMSn(...) for corrupt-data warnings TRACEMSn(...) for trace and informational messages. These macros store the message code and any additional parameters into the error handler struct, then invoke the error_exit() or emit_message() method. The variants of each macro are for varying numbers of additional parameters. The additional parameters are inserted into the generated message using standard printf() format codes. See jerror.h and jerror.c for further details. Compressed data handling (source and destination managers) ---------------------------------------------------------- The JPEG compression library sends its compressed data to a "destination manager" module. The default destination manager just writes the data to a memory buffer or to a stdio stream, but you can provide your own manager to do something else. Similarly, the decompression library calls a "source manager" to obtain the compressed data; you can provide your own source manager if you want the data to come from somewhere other than a memory buffer or a stdio stream. In both cases, compressed data is processed a bufferload at a time: the destination or source manager provides a work buffer, and the library invokes the manager only when the buffer is filled or emptied. (You could define a one-character buffer to force the manager to be invoked for each byte, but that would be rather inefficient.) The buffer's size and location are controlled by the manager, not by the library. For example, the memory source manager just makes the buffer pointer and length point to the original data in memory. In this case the buffer-reload procedure will be invoked only if the decompressor ran off the end of the datastream, which would indicate an erroneous datastream. The work buffer is defined as an array of datatype JOCTET, which is generally "char" or "unsigned char". On a machine where char is not exactly 8 bits wide, you must define JOCTET as a wider data type and then modify the data source and destination modules to transcribe the work arrays into 8-bit units on external storage. A data destination manager struct contains a pointer and count defining the next byte to write in the work buffer and the remaining free space: JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ The library increments the pointer and decrements the count until the buffer is filled. The manager's empty_output_buffer method must reset the pointer and count. The manager is expected to remember the buffer's starting address and total size in private fields not visible to the library. A data destination manager provides three methods: init_destination (j_compress_ptr cinfo) Initialize destination. This is called by jpeg_start_compress() before any data is actually written. It must initialize next_output_byte and free_in_buffer. free_in_buffer must be initialized to a positive value. empty_output_buffer (j_compress_ptr cinfo) This is called whenever the buffer has filled (free_in_buffer reaches zero). In typical applications, it should write out the *entire* buffer (use the saved start address and buffer length; ignore the current state of next_output_byte and free_in_buffer). Then reset the pointer & count to the start of the buffer, and return TRUE indicating that the buffer has been dumped. free_in_buffer must be set to a positive value when TRUE is returned. A FALSE return should only be used when I/O suspension is desired (this operating mode is discussed in the next section). term_destination (j_compress_ptr cinfo) Terminate destination --- called by jpeg_finish_compress() after all data has been written. In most applications, this must flush any data remaining in the buffer. Use either next_output_byte or free_in_buffer to determine how much data is in the buffer. term_destination() is NOT called by jpeg_abort() or jpeg_destroy(). If you want the destination manager to be cleaned up during an abort, you must do it yourself. You will also need code to create a jpeg_destination_mgr struct, fill in its method pointers, and insert a pointer to the struct into the "dest" field of the JPEG compression object. This can be done in-line in your setup code if you like, but it's probably cleaner to provide a separate routine similar to the jpeg_stdio_dest() or jpeg_mem_dest() routines of the supplied destination managers. Decompression source managers follow a parallel design, but with some additional frammishes. The source manager struct contains a pointer and count defining the next byte to read from the work buffer and the number of bytes remaining: const JOCTET * next_input_byte; /* => next byte to read from buffer */ size_t bytes_in_buffer; /* # of bytes remaining in buffer */ The library increments the pointer and decrements the count until the buffer is emptied. The manager's fill_input_buffer method must reset the pointer and count. In most applications, the manager must remember the buffer's starting address and total size in private fields not visible to the library. A data source manager provides five methods: init_source (j_decompress_ptr cinfo) Initialize source. This is called by jpeg_read_header() before any data is actually read. Unlike init_destination(), it may leave bytes_in_buffer set to 0 (in which case a fill_input_buffer() call will occur immediately). fill_input_buffer (j_decompress_ptr cinfo) This is called whenever bytes_in_buffer has reached zero and more data is wanted. In typical applications, it should read fresh data into the buffer (ignoring the current state of next_input_byte and bytes_in_buffer), reset the pointer & count to the start of the buffer, and return TRUE indicating that the buffer has been reloaded. It is not necessary to fill the buffer entirely, only to obtain at least one more byte. bytes_in_buffer MUST be set to a positive value if TRUE is returned. A FALSE return should only be used when I/O suspension is desired (this mode is discussed in the next section). skip_input_data (j_decompress_ptr cinfo, long num_bytes) Skip num_bytes worth of data. The buffer pointer and count should be advanced over num_bytes input bytes, refilling the buffer as needed. This is used to skip over a potentially large amount of uninteresting data (such as an APPn marker). In some applications it may be possible to optimize away the reading of the skipped data, but it's not clear that being smart is worth much trouble; large skips are uncommon. bytes_in_buffer may be zero on return. A zero or negative skip count should be treated as a no-op. resync_to_restart (j_decompress_ptr cinfo, int desired) This routine is called only when the decompressor has failed to find a restart (RSTn) marker where one is expected. Its mission is to find a suitable point for resuming decompression. For most applications, we recommend that you just use the default resync procedure, jpeg_resync_to_restart(). However, if you are able to back up in the input data stream, or if you have a-priori knowledge about the likely location of restart markers, you may be able to do better. Read the read_restart_marker() and jpeg_resync_to_restart() routines in jdmarker.c if you think you'd like to implement your own resync procedure. term_source (j_decompress_ptr cinfo) Terminate source --- called by jpeg_finish_decompress() after all data has been read. Often a no-op. For both fill_input_buffer() and skip_input_data(), there is no such thing as an EOF return. If the end of the file has been reached, the routine has a choice of exiting via ERREXIT() or inserting fake data into the buffer. In most cases, generating a warning message and inserting a fake EOI marker is the best course of action --- this will allow the decompressor to output however much of the image is there. In pathological cases, the decompressor may swallow the EOI and again demand data ... just keep feeding it fake EOIs. jdatasrc.c illustrates the recommended error recovery behavior. term_source() is NOT called by jpeg_abort() or jpeg_destroy(). If you want the source manager to be cleaned up during an abort, you must do it yourself. You will also need code to create a jpeg_source_mgr struct, fill in its method pointers, and insert a pointer to the struct into the "src" field of the JPEG decompression object. This can be done in-line in your setup code if you like, but it's probably cleaner to provide a separate routine similar to the jpeg_stdio_src() or jpeg_mem_src() routines of the supplied source managers. For more information, consult the memory and stdio source and destination managers in jdatasrc.c and jdatadst.c. I/O suspension -------------- Some applications need to use the JPEG library as an incremental memory-to- memory filter: when the compressed data buffer is filled or emptied, they want control to return to the outer loop, rather than expecting that the buffer can be emptied or reloaded within the data source/destination manager subroutine. The library supports this need by providing an "I/O suspension" mode, which we describe in this section. The I/O suspension mode is not a panacea: nothing is guaranteed about the maximum amount of time spent in any one call to the library, so it will not eliminate response-time problems in single-threaded applications. If you need guaranteed response time, we suggest you "bite the bullet" and implement a real multi-tasking capability. To use I/O suspension, cooperation is needed between the calling application and the data source or destination manager; you will always need a custom source/destination manager. (Please read the previous section if you haven't already.) The basic idea is that the empty_output_buffer() or fill_input_buffer() routine is a no-op, merely returning FALSE to indicate that it has done nothing. Upon seeing this, the JPEG library suspends operation and returns to its caller. The surrounding application is responsible for emptying or refilling the work buffer before calling the JPEG library again. Compression suspension: For compression suspension, use an empty_output_buffer() routine that returns FALSE; typically it will not do anything else. This will cause the compressor to return to the caller of jpeg_write_scanlines(), with the return value indicating that not all the supplied scanlines have been accepted. The application must make more room in the output buffer, adjust the output buffer pointer/count appropriately, and then call jpeg_write_scanlines() again, pointing to the first unconsumed scanline. When forced to suspend, the compressor will backtrack to a convenient stopping point (usually the start of the current MCU); it will regenerate some output data when restarted. Therefore, although empty_output_buffer() is only called when the buffer is filled, you should NOT write out the entire buffer after a suspension. Write only the data up to the current position of next_output_byte/free_in_buffer. The data beyond that point will be regenerated after resumption. Because of the backtracking behavior, a good-size output buffer is essential for efficiency; you don't want the compressor to suspend often. (In fact, an overly small buffer could lead to infinite looping, if a single MCU required more data than would fit in the buffer.) We recommend a buffer of at least several Kbytes. You may want to insert explicit code to ensure that you don't call jpeg_write_scanlines() unless there is a reasonable amount of space in the output buffer; in other words, flush the buffer before trying to compress more data. The compressor does not allow suspension while it is trying to write JPEG markers at the beginning and end of the file. This means that: * At the beginning of a compression operation, there must be enough free space in the output buffer to hold the header markers (typically 600 or so bytes). The recommended buffer size is bigger than this anyway, so this is not a problem as long as you start with an empty buffer. However, this restriction might catch you if you insert large special markers, such as a JFIF thumbnail image, without flushing the buffer afterwards. * When you call jpeg_finish_compress(), there must be enough space in the output buffer to emit any buffered data and the final EOI marker. In the current implementation, half a dozen bytes should suffice for this, but for safety's sake we recommend ensuring that at least 100 bytes are free before calling jpeg_finish_compress(). A more significant restriction is that jpeg_finish_compress() cannot suspend. This means you cannot use suspension with multi-pass operating modes, namely Huffman code optimization and multiple-scan output. Those modes write the whole file during jpeg_finish_compress(), which will certainly result in buffer overrun. (Note that this restriction applies only to compression, not decompression. The decompressor supports input suspension in all of its operating modes.) Decompression suspension: For decompression suspension, use a fill_input_buffer() routine that simply returns FALSE (except perhaps during error recovery, as discussed below). This will cause the decompressor to return to its caller with an indication that suspension has occurred. This can happen at four places: * jpeg_read_header(): will return JPEG_SUSPENDED. * jpeg_start_decompress(): will return FALSE, rather than its usual TRUE. * jpeg_read_scanlines(): will return the number of scanlines already completed (possibly 0). * jpeg_finish_decompress(): will return FALSE, rather than its usual TRUE. The surrounding application must recognize these cases, load more data into the input buffer, and repeat the call. In the case of jpeg_read_scanlines(), increment the passed pointers past any scanlines successfully read. Just as with compression, the decompressor will typically backtrack to a convenient restart point before suspending. When fill_input_buffer() is called, next_input_byte/bytes_in_buffer point to the current restart point, which is where the decompressor will backtrack to if FALSE is returned. The data beyond that position must NOT be discarded if you suspend; it needs to be re-read upon resumption. In most implementations, you'll need to shift this data down to the start of your work buffer and then load more data after it. Again, this behavior means that a several-Kbyte work buffer is essential for decent performance; furthermore, you should load a reasonable amount of new data before resuming decompression. (If you loaded, say, only one new byte each time around, you could waste a LOT of cycles.) The skip_input_data() source manager routine requires special care in a suspension scenario. This routine is NOT granted the ability to suspend the decompressor; it can decrement bytes_in_buffer to zero, but no more. If the requested skip distance exceeds the amount of data currently in the input buffer, then skip_input_data() must set bytes_in_buffer to zero and record the additional skip distance somewhere else. The decompressor will immediately call fill_input_buffer(), which should return FALSE, which will cause a suspension return. The surrounding application must then arrange to discard the recorded number of bytes before it resumes loading the input buffer. (Yes, this design is rather baroque, but it avoids complexity in the far more common case where a non-suspending source manager is used.) If the input data has been exhausted, we recommend that you emit a warning and insert dummy EOI markers just as a non-suspending data source manager would do. This can be handled either in the surrounding application logic or within fill_input_buffer(); the latter is probably more efficient. If fill_input_buffer() knows that no more data is available, it can set the pointer/count to point to a dummy EOI marker and then return TRUE just as though it had read more data in a non-suspending situation. The decompressor does not attempt to suspend within standard JPEG markers; instead it will backtrack to the start of the marker and reprocess the whole marker next time. Hence the input buffer must be large enough to hold the longest standard marker in the file. Standard JPEG markers should normally not exceed a few hundred bytes each (DHT tables are typically the longest). We recommend at least a 2K buffer for performance reasons, which is much larger than any correct marker is likely to be. For robustness against damaged marker length counts, you may wish to insert a test in your application for the case that the input buffer is completely full and yet the decoder has suspended without consuming any data --- otherwise, if this situation did occur, it would lead to an endless loop. (The library can't provide this test since it has no idea whether "the buffer is full", or even whether there is a fixed-size input buffer.) The input buffer would need to be 64K to allow for arbitrary COM or APPn markers, but these are handled specially: they are either saved into allocated memory, or skipped over by calling skip_input_data(). In the former case, suspension is handled correctly, and in the latter case, the problem of buffer overrun is placed on skip_input_data's shoulders, as explained above. Note that if you provide your own marker handling routine for large markers, you should consider how to deal with buffer overflow. Multiple-buffer management: In some applications it is desirable to store the compressed data in a linked list of buffer areas, so as to avoid data copying. This can be handled by having empty_output_buffer() or fill_input_buffer() set the pointer and count to reference the next available buffer; FALSE is returned only if no more buffers are available. Although seemingly straightforward, there is a pitfall in this approach: the backtrack that occurs when FALSE is returned could back up into an earlier buffer. For example, when fill_input_buffer() is called, the current pointer & count indicate the backtrack restart point. Since fill_input_buffer() will set the pointer and count to refer to a new buffer, the restart position must be saved somewhere else. Suppose a second call to fill_input_buffer() occurs in the same library call, and no additional input data is available, so fill_input_buffer must return FALSE. If the JPEG library has not moved the pointer/count forward in the current buffer, then *the correct restart point is the saved position in the prior buffer*. Prior buffers may be discarded only after the library establishes a restart point within a later buffer. Similar remarks apply for output into a chain of buffers. The library will never attempt to backtrack over a skip_input_data() call, so any skipped data can be permanently discarded. You still have to deal with the case of skipping not-yet-received data, however. It's much simpler to use only a single buffer; when fill_input_buffer() is called, move any unconsumed data (beyond the current pointer/count) down to the beginning of this buffer and then load new data into the remaining buffer space. This approach requires a little more data copying but is far easier to get right. Progressive JPEG support ------------------------ Progressive JPEG rearranges the stored data into a series of scans of increasing quality. In situations where a JPEG file is transmitted across a slow communications link, a decoder can generate a low-quality image very quickly from the first scan, then gradually improve the displayed quality as more scans are received. The final image after all scans are complete is identical to that of a regular (sequential) JPEG file of the same quality setting. Progressive JPEG files are often slightly smaller than equivalent sequential JPEG files, but the possibility of incremental display is the main reason for using progressive JPEG. The IJG encoder library generates progressive JPEG files when given a suitable "scan script" defining how to divide the data into scans. Creation of progressive JPEG files is otherwise transparent to the encoder. Progressive JPEG files can also be read transparently by the decoder library. If the decoding application simply uses the library as defined above, it will receive a final decoded image without any indication that the file was progressive. Of course, this approach does not allow incremental display. To perform incremental display, an application needs to use the decoder library's "buffered-image" mode, in which it receives a decoded image multiple times. Each displayed scan requires about as much work to decode as a full JPEG image of the same size, so the decoder must be fairly fast in relation to the data transmission rate in order to make incremental display useful. However, it is possible to skip displaying the image and simply add the incoming bits to the decoder's coefficient buffer. This is fast because only Huffman decoding need be done, not IDCT, upsampling, colorspace conversion, etc. The IJG decoder library allows the application to switch dynamically between displaying the image and simply absorbing the incoming bits. A properly coded application can automatically adapt the number of display passes to suit the time available as the image is received. Also, a final higher-quality display cycle can be performed from the buffered data after the end of the file is reached. Progressive compression: To create a progressive JPEG file (or a multiple-scan sequential JPEG file), set the scan_info cinfo field to point to an array of scan descriptors, and perform compression as usual. Instead of constructing your own scan list, you can call the jpeg_simple_progression() helper routine to create a recommended progression sequence; this method should be used by all applications that don't want to get involved in the nitty-gritty of progressive scan sequence design. (If you want to provide user control of scan sequences, you may wish to borrow the scan script reading code found in rdswitch.c, so that you can read scan script files just like cjpeg's.) When scan_info is not NULL, the compression library will store DCT'd data into a buffer array as jpeg_write_scanlines() is called, and will emit all the requested scans during jpeg_finish_compress(). This implies that multiple-scan output cannot be created with a suspending data destination manager, since jpeg_finish_compress() does not support suspension. We should also note that the compressor currently forces Huffman optimization mode when creating a progressive JPEG file, because the default Huffman tables are unsuitable for progressive files. Progressive decompression: When buffered-image mode is not used, the decoder library will read all of a multi-scan file during jpeg_start_decompress(), so that it can provide a final decoded image. (Here "multi-scan" means either progressive or multi-scan sequential.) This makes multi-scan files transparent to the decoding application. However, existing applications that used suspending input with version 5 of the IJG library will need to be modified to check for a suspension return from jpeg_start_decompress(). To perform incremental display, an application must use the library's buffered-image mode. This is described in the next section. Buffered-image mode ------------------- In buffered-image mode, the library stores the partially decoded image in a coefficient buffer, from which it can be read out as many times as desired. This mode is typically used for incremental display of progressive JPEG files, but it can be used with any JPEG file. Each scan of a progressive JPEG file adds more data (more detail) to the buffered image. The application can display in lockstep with the source file (one display pass per input scan), or it can allow input processing to outrun display processing. By making input and display processing run independently, it is possible for the application to adapt progressive display to a wide range of data transmission rates. The basic control flow for buffered-image decoding is jpeg_create_decompress() set data source jpeg_read_header() set overall decompression parameters cinfo.buffered_image = TRUE; /* select buffered-image mode */ jpeg_start_decompress() for (each output pass) { adjust output decompression parameters if required jpeg_start_output() /* start a new output pass */ for (all scanlines in image) { jpeg_read_scanlines() display scanlines } jpeg_finish_output() /* terminate output pass */ } jpeg_finish_decompress() jpeg_destroy_decompress() This differs from ordinary unbuffered decoding in that there is an additional level of looping. The application can choose how many output passes to make and how to display each pass. The simplest approach to displaying progressive images is to do one display pass for each scan appearing in the input file. In this case the outer loop condition is typically while (! jpeg_input_complete(&cinfo)) and the start-output call should read jpeg_start_output(&cinfo, cinfo.input_scan_number); The second parameter to jpeg_start_output() indicates which scan of the input file is to be displayed; the scans are numbered starting at 1 for this purpose. (You can use a loop counter starting at 1 if you like, but using the library's input scan counter is easier.) The library automatically reads data as necessary to complete each requested scan, and jpeg_finish_output() advances to the next scan or end-of-image marker (hence input_scan_number will be incremented by the time control arrives back at jpeg_start_output()). With this technique, data is read from the input file only as needed, and input and output processing run in lockstep. After reading the final scan and reaching the end of the input file, the buffered image remains available; it can be read additional times by repeating the jpeg_start_output()/jpeg_read_scanlines()/jpeg_finish_output() sequence. For example, a useful technique is to use fast one-pass color quantization for display passes made while the image is arriving, followed by a final display pass using two-pass quantization for highest quality. This is done by changing the library parameters before the final output pass. Changing parameters between passes is discussed in detail below. In general the last scan of a progressive file cannot be recognized as such until after it is read, so a post-input display pass is the best approach if you want special processing in the final pass. When done with the image, be sure to call jpeg_finish_decompress() to release the buffered image (or just use jpeg_destroy_decompress()). If input data arrives faster than it can be displayed, the application can cause the library to decode input data in advance of what's needed to produce output. This is done by calling the routine jpeg_consume_input(). The return value is one of the following: JPEG_REACHED_SOS: reached an SOS marker (the start of a new scan) JPEG_REACHED_EOI: reached the EOI marker (end of image) JPEG_ROW_COMPLETED: completed reading one MCU row of compressed data JPEG_SCAN_COMPLETED: completed reading last MCU row of current scan JPEG_SUSPENDED: suspended before completing any of the above (JPEG_SUSPENDED can occur only if a suspending data source is used.) This routine can be called at any time after initializing the JPEG object. It reads some additional data and returns when one of the indicated significant events occurs. (If called after the EOI marker is reached, it will immediately return JPEG_REACHED_EOI without attempting to read more data.) The library's output processing will automatically call jpeg_consume_input() whenever the output processing overtakes the input; thus, simple lockstep display requires no direct calls to jpeg_consume_input(). But by adding calls to jpeg_consume_input(), you can absorb data in advance of what is being displayed. This has two benefits: * You can limit buildup of unprocessed data in your input buffer. * You can eliminate extra display passes by paying attention to the state of the library's input processing. The first of these benefits only requires interspersing calls to jpeg_consume_input() with your display operations and any other processing you may be doing. To avoid wasting cycles due to backtracking, it's best to call jpeg_consume_input() only after a hundred or so new bytes have arrived. This is discussed further under "I/O suspension", above. (Note: the JPEG library currently is not thread-safe. You must not call jpeg_consume_input() from one thread of control if a different library routine is working on the same JPEG object in another thread.) When input arrives fast enough that more than one new scan is available before you start a new output pass, you may as well skip the output pass corresponding to the completed scan. This occurs for free if you pass cinfo.input_scan_number as the target scan number to jpeg_start_output(). The input_scan_number field is simply the index of the scan currently being consumed by the input processor. You can ensure that this is up-to-date by emptying the input buffer just before calling jpeg_start_output(): call jpeg_consume_input() repeatedly until it returns JPEG_SUSPENDED or JPEG_REACHED_EOI. The target scan number passed to jpeg_start_output() is saved in the cinfo.output_scan_number field. The library's output processing calls jpeg_consume_input() whenever the current input scan number and row within that scan is less than or equal to the current output scan number and row. Thus, input processing can "get ahead" of the output processing but is not allowed to "fall behind". You can achieve several different effects by manipulating this interlock rule. For example, if you pass a target scan number greater than the current input scan number, the output processor will wait until that scan starts to arrive before producing any output. (To avoid an infinite loop, the target scan number is automatically reset to the last scan number when the end of image is reached. Thus, if you specify a large target scan number, the library will just absorb the entire input file and then perform an output pass. This is effectively the same as what jpeg_start_decompress() does when you don't select buffered-image mode.) When you pass a target scan number equal to the current input scan number, the image is displayed no faster than the current input scan arrives. The final possibility is to pass a target scan number less than the current input scan number; this disables the input/output interlock and causes the output processor to simply display whatever it finds in the image buffer, without waiting for input. (However, the library will not accept a target scan number less than one, so you can't avoid waiting for the first scan.) When data is arriving faster than the output display processing can advance through the image, jpeg_consume_input() will store data into the buffered image beyond the point at which the output processing is reading data out again. If the input arrives fast enough, it may "wrap around" the buffer to the point where the input is more than one whole scan ahead of the output. If the output processing simply proceeds through its display pass without paying attention to the input, the effect seen on-screen is that the lower part of the image is one or more scans better in quality than the upper part. Then, when the next output scan is started, you have a choice of what target scan number to use. The recommended choice is to use the current input scan number at that time, which implies that you've skipped the output scans corresponding to the input scans that were completed while you processed the previous output scan. In this way, the decoder automatically adapts its speed to the arriving data, by skipping output scans as necessary to keep up with the arriving data. When using this strategy, you'll want to be sure that you perform a final output pass after receiving all the data; otherwise your last display may not be full quality across the whole screen. So the right outer loop logic is something like this: do { absorb any waiting input by calling jpeg_consume_input() final_pass = jpeg_input_complete(&cinfo); adjust output decompression parameters if required jpeg_start_output(&cinfo, cinfo.input_scan_number); ... jpeg_finish_output() } while (! final_pass); rather than quitting as soon as jpeg_input_complete() returns TRUE. This arrangement makes it simple to use higher-quality decoding parameters for the final pass. But if you don't want to use special parameters for the final pass, the right loop logic is like this: for (;;) { absorb any waiting input by calling jpeg_consume_input() jpeg_start_output(&cinfo, cinfo.input_scan_number); ... jpeg_finish_output() if (jpeg_input_complete(&cinfo) && cinfo.input_scan_number == cinfo.output_scan_number) break; } In this case you don't need to know in advance whether an output pass is to be the last one, so it's not necessary to have reached EOF before starting the final output pass; rather, what you want to test is whether the output pass was performed in sync with the final input scan. This form of the loop will avoid an extra output pass whenever the decoder is able (or nearly able) to keep up with the incoming data. When the data transmission speed is high, you might begin a display pass, then find that much or all of the file has arrived before you can complete the pass. (You can detect this by noting the JPEG_REACHED_EOI return code from jpeg_consume_input(), or equivalently by testing jpeg_input_complete().) In this situation you may wish to abort the current display pass and start a new one using the newly arrived information. To do so, just call jpeg_finish_output() and then start a new pass with jpeg_start_output(). A variant strategy is to abort and restart display if more than one complete scan arrives during an output pass; this can be detected by noting JPEG_REACHED_SOS returns and/or examining cinfo.input_scan_number. This idea should be employed with caution, however, since the display process might never get to the bottom of the image before being aborted, resulting in the lower part of the screen being several passes worse than the upper. In most cases it's probably best to abort an output pass only if the whole file has arrived and you want to begin the final output pass immediately. When receiving data across a communication link, we recommend always using the current input scan number for the output target scan number; if a higher-quality final pass is to be done, it should be started (aborting any incomplete output pass) as soon as the end of file is received. However, many other strategies are possible. For example, the application can examine the parameters of the current input scan and decide whether to display it or not. If the scan contains only chroma data, one might choose not to use it as the target scan, expecting that the scan will be small and will arrive quickly. To skip to the next scan, call jpeg_consume_input() until it returns JPEG_REACHED_SOS or JPEG_REACHED_EOI. Or just use the next higher number as the target scan for jpeg_start_output(); but that method doesn't let you inspect the next scan's parameters before deciding to display it. In buffered-image mode, jpeg_start_decompress() never performs input and thus never suspends. An application that uses input suspension with buffered-image mode must be prepared for suspension returns from these routines: * jpeg_start_output() performs input only if you request 2-pass quantization and the target scan isn't fully read yet. (This is discussed below.) * jpeg_read_scanlines(), as always, returns the number of scanlines that it was able to produce before suspending. * jpeg_finish_output() will read any markers following the target scan, up to the end of the file or the SOS marker that begins another scan. (But it reads no input if jpeg_consume_input() has already reached the end of the file or a SOS marker beyond the target output scan.) * jpeg_finish_decompress() will read until the end of file, and thus can suspend if the end hasn't already been reached (as can be tested by calling jpeg_input_complete()). jpeg_start_output(), jpeg_finish_output(), and jpeg_finish_decompress() all return TRUE if they completed their tasks, FALSE if they had to suspend. In the event of a FALSE return, the application must load more input data and repeat the call. Applications that use non-suspending data sources need not check the return values of these three routines. It is possible to change decoding parameters between output passes in the buffered-image mode. The decoder library currently supports only very limited changes of parameters. ONLY THE FOLLOWING parameter changes are allowed after jpeg_start_decompress() is called: * dct_method can be changed before each call to jpeg_start_output(). For example, one could use a fast DCT method for early scans, changing to a higher quality method for the final scan. * dither_mode can be changed before each call to jpeg_start_output(); of course this has no impact if not using color quantization. Typically one would use ordered dither for initial passes, then switch to Floyd-Steinberg dither for the final pass. Caution: changing dither mode can cause more memory to be allocated by the library. Although the amount of memory involved is not large (a scanline or so), it may cause the initial max_memory_to_use specification to be exceeded, which in the worst case would result in an out-of-memory failure. * do_block_smoothing can be changed before each call to jpeg_start_output(). This setting is relevant only when decoding a progressive JPEG image. During the first DC-only scan, block smoothing provides a very "fuzzy" look instead of the very "blocky" look seen without it; which is better seems a matter of personal taste. But block smoothing is nearly always a win during later stages, especially when decoding a successive-approximation image: smoothing helps to hide the slight blockiness that otherwise shows up on smooth gradients until the lowest coefficient bits are sent. * Color quantization mode can be changed under the rules described below. You *cannot* change between full-color and quantized output (because that would alter the required I/O buffer sizes), but you can change which quantization method is used. When generating color-quantized output, changing quantization method is a very useful way of switching between high-speed and high-quality display. The library allows you to change among its three quantization methods: 1. Single-pass quantization to a fixed color cube. Selected by cinfo.two_pass_quantize = FALSE and cinfo.colormap = NULL. 2. Single-pass quantization to an application-supplied colormap. Selected by setting cinfo.colormap to point to the colormap (the value of two_pass_quantize is ignored); also set cinfo.actual_number_of_colors. 3. Two-pass quantization to a colormap chosen specifically for the image. Selected by cinfo.two_pass_quantize = TRUE and cinfo.colormap = NULL. (This is the default setting selected by jpeg_read_header, but it is probably NOT what you want for the first pass of progressive display!) These methods offer successively better quality and lesser speed. However, only the first method is available for quantizing in non-RGB color spaces. IMPORTANT: because the different quantizer methods have very different working-storage requirements, the library requires you to indicate which one(s) you intend to use before you call jpeg_start_decompress(). (If we did not require this, the max_memory_to_use setting would be a complete fiction.) You do this by setting one or more of these three cinfo fields to TRUE: enable_1pass_quant Fixed color cube colormap enable_external_quant Externally-supplied colormap enable_2pass_quant Two-pass custom colormap All three are initialized FALSE by jpeg_read_header(). But jpeg_start_decompress() automatically sets TRUE the one selected by the current two_pass_quantize and colormap settings, so you only need to set the enable flags for any other quantization methods you plan to change to later. After setting the enable flags correctly at jpeg_start_decompress() time, you can change to any enabled quantization method by setting two_pass_quantize and colormap properly just before calling jpeg_start_output(). The following special rules apply: 1. You must explicitly set cinfo.colormap to NULL when switching to 1-pass or 2-pass mode from a different mode, or when you want the 2-pass quantizer to be re-run to generate a new colormap. 2. To switch to an external colormap, or to change to a different external colormap than was used on the prior pass, you must call jpeg_new_colormap() after setting cinfo.colormap. NOTE: if you want to use the same colormap as was used in the prior pass, you should not do either of these things. This will save some nontrivial switchover costs. (These requirements exist because cinfo.colormap will always be non-NULL after completing a prior output pass, since both the 1-pass and 2-pass quantizers set it to point to their output colormaps. Thus you have to do one of these two things to notify the library that something has changed. Yup, it's a bit klugy, but it's necessary to do it this way for backwards compatibility.) Note that in buffered-image mode, the library generates any requested colormap during jpeg_start_output(), not during jpeg_start_decompress(). When using two-pass quantization, jpeg_start_output() makes a pass over the buffered image to determine the optimum color map; it therefore may take a significant amount of time, whereas ordinarily it does little work. The progress monitor hook is called during this pass, if defined. It is also important to realize that if the specified target scan number is greater than or equal to the current input scan number, jpeg_start_output() will attempt to consume input as it makes this pass. If you use a suspending data source, you need to check for a FALSE return from jpeg_start_output() under these conditions. The combination of 2-pass quantization and a not-yet-fully-read target scan is the only case in which jpeg_start_output() will consume input. Application authors who support buffered-image mode may be tempted to use it for all JPEG images, even single-scan ones. This will work, but it is inefficient: there is no need to create an image-sized coefficient buffer for single-scan images. Requesting buffered-image mode for such an image wastes memory. Worse, it can cost time on large images, since the buffered data has to be swapped out or written to a temporary file. If you are concerned about maximum performance on baseline JPEG files, you should use buffered-image mode only when the incoming file actually has multiple scans. This can be tested by calling jpeg_has_multiple_scans(), which will return a correct result at any time after jpeg_read_header() completes. It is also worth noting that when you use jpeg_consume_input() to let input processing get ahead of output processing, the resulting pattern of access to the coefficient buffer is quite nonsequential. It's best to use the memory manager jmemnobs.c if you can (ie, if you have enough real or virtual main memory). If not, at least make sure that max_memory_to_use is set as high as possible. If the JPEG memory manager has to use a temporary file, you will probably see a lot of disk traffic and poor performance. (This could be improved with additional work on the memory manager, but we haven't gotten around to it yet.) In some applications it may be convenient to use jpeg_consume_input() for all input processing, including reading the initial markers; that is, you may wish to call jpeg_consume_input() instead of jpeg_read_header() during startup. This works, but note that you must check for JPEG_REACHED_SOS and JPEG_REACHED_EOI return codes as the equivalent of jpeg_read_header's codes. Once the first SOS marker has been reached, you must call jpeg_start_decompress() before jpeg_consume_input() will consume more input; it'll just keep returning JPEG_REACHED_SOS until you do. If you read a tables-only file this way, jpeg_consume_input() will return JPEG_REACHED_EOI without ever returning JPEG_REACHED_SOS; be sure to check for this case. If this happens, the decompressor will not read any more input until you call jpeg_abort() to reset it. It is OK to call jpeg_consume_input() even when not using buffered-image mode, but in that case it's basically a no-op after the initial markers have been read: it will just return JPEG_SUSPENDED. Abbreviated datastreams and multiple images ------------------------------------------- A JPEG compression or decompression object can be reused to process multiple images. This saves a small amount of time per image by eliminating the "create" and "destroy" operations, but that isn't the real purpose of the feature. Rather, reuse of an object provides support for abbreviated JPEG datastreams. Object reuse can also simplify processing a series of images in a single input or output file. This section explains these features. A JPEG file normally contains several hundred bytes worth of quantization and Huffman tables. In a situation where many images will be stored or transmitted with identical tables, this may represent an annoying overhead. The JPEG standard therefore permits tables to be omitted. The standard defines three classes of JPEG datastreams: * "Interchange" datastreams contain an image and all tables needed to decode the image. These are the usual kind of JPEG file. * "Abbreviated image" datastreams contain an image, but are missing some or all of the tables needed to decode that image. * "Abbreviated table specification" (henceforth "tables-only") datastreams contain only table specifications. To decode an abbreviated image, it is necessary to load the missing table(s) into the decoder beforehand. This can be accomplished by reading a separate tables-only file. A variant scheme uses a series of images in which the first image is an interchange (complete) datastream, while subsequent ones are abbreviated and rely on the tables loaded by the first image. It is assumed that once the decoder has read a table, it will remember that table until a new definition for the same table number is encountered. It is the application designer's responsibility to figure out how to associate the correct tables with an abbreviated image. While abbreviated datastreams can be useful in a closed environment, their use is strongly discouraged in any situation where data exchange with other applications might be needed. Caveat designer. The JPEG library provides support for reading and writing any combination of tables-only datastreams and abbreviated images. In both compression and decompression objects, a quantization or Huffman table will be retained for the lifetime of the object, unless it is overwritten by a new table definition. To create abbreviated image datastreams, it is only necessary to tell the compressor not to emit some or all of the tables it is using. Each quantization and Huffman table struct contains a boolean field "sent_table", which normally is initialized to FALSE. For each table used by the image, the header-writing process emits the table and sets sent_table = TRUE unless it is already TRUE. (In normal usage, this prevents outputting the same table definition multiple times, as would otherwise occur because the chroma components typically share tables.) Thus, setting this field to TRUE before calling jpeg_start_compress() will prevent the table from being written at all. If you want to create a "pure" abbreviated image file containing no tables, just call "jpeg_suppress_tables(&cinfo, TRUE)" after constructing all the tables. If you want to emit some but not all tables, you'll need to set the individual sent_table fields directly. To create an abbreviated image, you must also call jpeg_start_compress() with a second parameter of FALSE, not TRUE. Otherwise jpeg_start_compress() will force all the sent_table fields to FALSE. (This is a safety feature to prevent abbreviated images from being created accidentally.) To create a tables-only file, perform the same parameter setup that you normally would, but instead of calling jpeg_start_compress() and so on, call jpeg_write_tables(&cinfo). This will write an abbreviated datastream containing only SOI, DQT and/or DHT markers, and EOI. All the quantization and Huffman tables that are currently defined in the compression object will be emitted unless their sent_tables flag is already TRUE, and then all the sent_tables flags will be set TRUE. A sure-fire way to create matching tables-only and abbreviated image files is to proceed as follows: create JPEG compression object set JPEG parameters set destination to tables-only file jpeg_write_tables(&cinfo); set destination to image file jpeg_start_compress(&cinfo, FALSE); write data... jpeg_finish_compress(&cinfo); Since the JPEG parameters are not altered between writing the table file and the abbreviated image file, the same tables are sure to be used. Of course, you can repeat the jpeg_start_compress() ... jpeg_finish_compress() sequence many times to produce many abbreviated image files matching the table file. You cannot suppress output of the computed Huffman tables when Huffman optimization is selected. (If you could, there'd be no way to decode the image...) Generally, you don't want to set optimize_coding = TRUE when you are trying to produce abbreviated files. In some cases you might want to compress an image using tables which are not stored in the application, but are defined in an interchange or tables-only file readable by the application. This can be done by setting up a JPEG decompression object to read the specification file, then copying the tables into your compression object. See jpeg_copy_critical_parameters() for an example of copying quantization tables. To read abbreviated image files, you simply need to load the proper tables into the decompression object before trying to read the abbreviated image. If the proper tables are stored in the application program, you can just allocate the table structs and fill in their contents directly. For example, to load a fixed quantization table into table slot "n": if (cinfo.quant_tbl_ptrs[n] == NULL) cinfo.quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) &cinfo); quant_ptr = cinfo.quant_tbl_ptrs[n]; /* quant_ptr is JQUANT_TBL* */ for (i = 0; i < 64; i++) { /* Qtable[] is desired quantization table, in natural array order */ quant_ptr->quantval[i] = Qtable[i]; } Code to load a fixed Huffman table is typically (for AC table "n"): if (cinfo.ac_huff_tbl_ptrs[n] == NULL) cinfo.ac_huff_tbl_ptrs[n] = jpeg_alloc_huff_table((j_common_ptr) &cinfo); huff_ptr = cinfo.ac_huff_tbl_ptrs[n]; /* huff_ptr is JHUFF_TBL* */ for (i = 1; i <= 16; i++) { /* counts[i] is number of Huffman codes of length i bits, i=1..16 */ huff_ptr->bits[i] = counts[i]; } for (i = 0; i < 256; i++) { /* symbols[] is the list of Huffman symbols, in code-length order */ huff_ptr->huffval[i] = symbols[i]; } (Note that trying to set cinfo.quant_tbl_ptrs[n] to point directly at a constant JQUANT_TBL object is not safe. If the incoming file happened to contain a quantization table definition, your master table would get overwritten! Instead allocate a working table copy and copy the master table into it, as illustrated above. Ditto for Huffman tables, of course.) You might want to read the tables from a tables-only file, rather than hard-wiring them into your application. The jpeg_read_header() call is sufficient to read a tables-only file. You must pass a second parameter of FALSE to indicate that you do not require an image to be present. Thus, the typical scenario is create JPEG decompression object set source to tables-only file jpeg_read_header(&cinfo, FALSE); set source to abbreviated image file jpeg_read_header(&cinfo, TRUE); set decompression parameters jpeg_start_decompress(&cinfo); read data... jpeg_finish_decompress(&cinfo); In some cases, you may want to read a file without knowing whether it contains an image or just tables. In that case, pass FALSE and check the return value from jpeg_read_header(): it will be JPEG_HEADER_OK if an image was found, JPEG_HEADER_TABLES_ONLY if only tables were found. (A third return value, JPEG_SUSPENDED, is possible when using a suspending data source manager.) Note that jpeg_read_header() will not complain if you read an abbreviated image for which you haven't loaded the missing tables; the missing-table check occurs later, in jpeg_start_decompress(). It is possible to read a series of images from a single source file by repeating the jpeg_read_header() ... jpeg_finish_decompress() sequence, without releasing/recreating the JPEG object or the data source module. (If you did reinitialize, any partial bufferload left in the data source buffer at the end of one image would be discarded, causing you to lose the start of the next image.) When you use this method, stored tables are automatically carried forward, so some of the images can be abbreviated images that depend on tables from earlier images. If you intend to write a series of images into a single destination file, you might want to make a specialized data destination module that doesn't flush the output buffer at term_destination() time. This would speed things up by some trifling amount. Of course, you'd need to remember to flush the buffer after the last image. You can make the later images be abbreviated ones by passing FALSE to jpeg_start_compress(). Special markers --------------- Some applications may need to insert or extract special data in the JPEG datastream. The JPEG standard provides marker types "COM" (comment) and "APP0" through "APP15" (application) to hold application-specific data. Unfortunately, the use of these markers is not specified by the standard. COM markers are fairly widely used to hold user-supplied text. The JFIF file format spec uses APP0 markers with specified initial strings to hold certain data. Adobe applications use APP14 markers beginning with the string "Adobe" for miscellaneous data. Other APPn markers are rarely seen, but might contain almost anything. If you wish to store user-supplied text, we recommend you use COM markers and place readable 7-bit ASCII text in them. Newline conventions are not standardized --- expect to find LF (Unix style), CR/LF (DOS style), or CR (Mac style). A robust COM reader should be able to cope with random binary garbage, including nulls, since some applications generate COM markers containing non-ASCII junk. (But yours should not be one of them.) For program-supplied data, use an APPn marker, and be sure to begin it with an identifying string so that you can tell whether the marker is actually yours. It's probably best to avoid using APP0 or APP14 for any private markers. (NOTE: the upcoming SPIFF standard will use APP8 markers; we recommend you not use APP8 markers for any private purposes, either.) Keep in mind that at most 65533 bytes can be put into one marker, but you can have as many markers as you like. By default, the IJG compression library will write a JFIF APP0 marker if the selected JPEG colorspace is grayscale or YCbCr, or an Adobe APP14 marker if the selected colorspace is RGB, CMYK, or YCCK. You can disable this, but we don't recommend it. The decompression library will recognize JFIF and Adobe markers and will set the JPEG colorspace properly when one is found. You can write special markers immediately following the datastream header by calling jpeg_write_marker() after jpeg_start_compress() and before the first call to jpeg_write_scanlines(). When you do this, the markers appear after the SOI and the JFIF APP0 and Adobe APP14 markers (if written), but before all else. Specify the marker type parameter as "JPEG_COM" for COM or "JPEG_APP0 + n" for APPn. (Actually, jpeg_write_marker will let you write any marker type, but we don't recommend writing any other kinds of marker.) For example, to write a user comment string pointed to by comment_text: jpeg_write_marker(cinfo, JPEG_COM, comment_text, strlen(comment_text)); If it's not convenient to store all the marker data in memory at once, you can instead call jpeg_write_m_header() followed by multiple calls to jpeg_write_m_byte(). If you do it this way, it's your responsibility to call jpeg_write_m_byte() exactly the number of times given in the length parameter to jpeg_write_m_header(). (This method lets you empty the output buffer partway through a marker, which might be important when using a suspending data destination module. In any case, if you are using a suspending destination, you should flush its buffer after inserting any special markers. See "I/O suspension".) Or, if you prefer to synthesize the marker byte sequence yourself, you can just cram it straight into the data destination module. If you are writing JFIF 1.02 extension markers (thumbnail images), don't forget to set cinfo.JFIF_minor_version = 2 so that the encoder will write the correct JFIF version number in the JFIF header marker. The library's default is to write version 1.01, but that's wrong if you insert any 1.02 extension markers. (We could probably get away with just defaulting to 1.02, but there used to be broken decoders that would complain about unknown minor version numbers. To reduce compatibility risks it's safest not to write 1.02 unless you are actually using 1.02 extensions.) When reading, two methods of handling special markers are available: 1. You can ask the library to save the contents of COM and/or APPn markers into memory, and then examine them at your leisure afterwards. 2. You can supply your own routine to process COM and/or APPn markers on-the-fly as they are read. The first method is simpler to use, especially if you are using a suspending data source; writing a marker processor that copes with input suspension is not easy (consider what happens if the marker is longer than your available input buffer). However, the second method conserves memory since the marker data need not be kept around after it's been processed. For either method, you'd normally set up marker handling after creating a decompression object and before calling jpeg_read_header(), because the markers of interest will typically be near the head of the file and so will be scanned by jpeg_read_header. Once you've established a marker handling method, it will be used for the life of that decompression object (potentially many datastreams), unless you change it. Marker handling is determined separately for COM markers and for each APPn marker code. To save the contents of special markers in memory, call jpeg_save_markers(cinfo, marker_code, length_limit) where marker_code is the marker type to save, JPEG_COM or JPEG_APP0+n. (To arrange to save all the special marker types, you need to call this routine 17 times, for COM and APP0-APP15.) If the incoming marker is longer than length_limit data bytes, only length_limit bytes will be saved; this parameter allows you to avoid chewing up memory when you only need to see the first few bytes of a potentially large marker. If you want to save all the data, set length_limit to 0xFFFF; that is enough since marker lengths are only 16 bits. As a special case, setting length_limit to 0 prevents that marker type from being saved at all. (That is the default behavior, in fact.) After jpeg_read_header() completes, you can examine the special markers by following the cinfo->marker_list pointer chain. All the special markers in the file appear in this list, in order of their occurrence in the file (but omitting any markers of types you didn't ask for). Both the original data length and the saved data length are recorded for each list entry; the latter will not exceed length_limit for the particular marker type. Note that these lengths exclude the marker length word, whereas the stored representation within the JPEG file includes it. (Hence the maximum data length is really only 65533.) It is possible that additional special markers appear in the file beyond the SOS marker at which jpeg_read_header stops; if so, the marker list will be extended during reading of the rest of the file. This is not expected to be common, however. If you are short on memory you may want to reset the length limit to zero for all marker types after finishing jpeg_read_header, to ensure that the max_memory_to_use setting cannot be exceeded due to addition of later markers. The marker list remains stored until you call jpeg_finish_decompress or jpeg_abort, at which point the memory is freed and the list is set to empty. (jpeg_destroy also releases the storage, of course.) Note that the library is internally interested in APP0 and APP14 markers; if you try to set a small nonzero length limit on these types, the library will silently force the length up to the minimum it wants. (But you can set a zero length limit to prevent them from being saved at all.) Also, in a 16-bit environment, the maximum length limit may be constrained to less than 65533 by malloc() limitations. It is therefore best not to assume that the effective length limit is exactly what you set it to be. If you want to supply your own marker-reading routine, you do it by calling jpeg_set_marker_processor(). A marker processor routine must have the signature boolean jpeg_marker_parser_method (j_decompress_ptr cinfo) Although the marker code is not explicitly passed, the routine can find it in cinfo->unread_marker. At the time of call, the marker proper has been read from the data source module. The processor routine is responsible for reading the marker length word and the remaining parameter bytes, if any. Return TRUE to indicate success. (FALSE should be returned only if you are using a suspending data source and it tells you to suspend. See the standard marker processors in jdmarker.c for appropriate coding methods if you need to use a suspending data source.) If you override the default APP0 or APP14 processors, it is up to you to recognize JFIF and Adobe markers if you want colorspace recognition to occur properly. We recommend copying and extending the default processors if you want to do that. (A better idea is to save these marker types for later examination by calling jpeg_save_markers(); that method doesn't interfere with the library's own processing of these markers.) jpeg_set_marker_processor() and jpeg_save_markers() are mutually exclusive --- if you call one it overrides any previous call to the other, for the particular marker type specified. A simple example of an external COM processor can be found in djpeg.c. Also, see jpegtran.c for an example of using jpeg_save_markers. Raw (downsampled) image data ---------------------------- Some applications need to supply already-downsampled image data to the JPEG compressor, or to receive raw downsampled data from the decompressor. The library supports this requirement by allowing the application to write or read raw data, bypassing the normal preprocessing or postprocessing steps. The interface is different from the standard one and is somewhat harder to use. If your interest is merely in bypassing color conversion, we recommend that you use the standard interface and simply set jpeg_color_space = in_color_space (or jpeg_color_space = out_color_space for decompression). The mechanism described in this section is necessary only to supply or receive downsampled image data, in which not all components have the same dimensions. To compress raw data, you must supply the data in the colorspace to be used in the JPEG file (please read the earlier section on Special color spaces) and downsampled to the sampling factors specified in the JPEG parameters. You must supply the data in the format used internally by the JPEG library, namely a JSAMPIMAGE array. This is an array of pointers to two-dimensional arrays, each of type JSAMPARRAY. Each 2-D array holds the values for one color component. This structure is necessary since the components are of different sizes. If the image dimensions are not a multiple of the MCU size, you must also pad the data correctly (usually, this is done by replicating the last column and/or row). The data must be padded to a multiple of a DCT block in each component: that is, each downsampled row must contain a multiple of DCT_h_scaled_size valid samples, and there must be a multiple of DCT_v_scaled_size sample rows for each component. (For applications such as conversion of digital TV images, the standard image size is usually a multiple of the DCT block size, so that no padding need actually be done.) The procedure for compression of raw data is basically the same as normal compression, except that you call jpeg_write_raw_data() in place of jpeg_write_scanlines(). Before calling jpeg_start_compress(), you must do the following: * Set cinfo->raw_data_in to TRUE. (It is set FALSE by jpeg_set_defaults().) This notifies the library that you will be supplying raw data. * Ensure jpeg_color_space is correct --- an explicit jpeg_set_colorspace() call is a good idea. Note that since color conversion is bypassed, in_color_space is ignored, except that jpeg_set_defaults() uses it to choose the default jpeg_color_space setting. * Ensure the sampling factors, cinfo->comp_info[i].h_samp_factor and cinfo->comp_info[i].v_samp_factor, are correct. Since these indicate the dimensions of the data you are supplying, it's wise to set them explicitly, rather than assuming the library's defaults are what you want. To pass raw data to the library, call jpeg_write_raw_data() in place of jpeg_write_scanlines(). The two routines work similarly except that jpeg_write_raw_data takes a JSAMPIMAGE data array rather than JSAMPARRAY. The scanlines count passed to and returned from jpeg_write_raw_data is measured in terms of the component with the largest v_samp_factor. jpeg_write_raw_data() processes one MCU row per call, which is to say v_samp_factor*min_DCT_v_scaled_size sample rows of each component. The passed num_lines value must be at least max_v_samp_factor*min_DCT_v_scaled_size, and the return value will be exactly that amount (or possibly some multiple of that amount, in future library versions). This is true even on the last call at the bottom of the image; don't forget to pad your data as necessary. The required dimensions of the supplied data can be computed for each component as cinfo->comp_info[i].width_in_blocks * cinfo->comp_info[i].DCT_h_scaled_size samples per row cinfo->comp_info[i].height_in_blocks * cinfo->comp_info[i].DCT_v_scaled_size rows in image after jpeg_start_compress() has initialized those fields. If the valid data is smaller than this, it must be padded appropriately. For some sampling factors and image sizes, additional dummy DCT blocks are inserted to make the image a multiple of the MCU dimensions. The library creates such dummy blocks itself; it does not read them from your supplied data. Therefore you need never pad by more than DCT_scaled_size samples. An example may help here. Assume 2h2v downsampling of YCbCr data, that is cinfo->comp_info[0].h_samp_factor = 2 for Y cinfo->comp_info[0].v_samp_factor = 2 cinfo->comp_info[1].h_samp_factor = 1 for Cb cinfo->comp_info[1].v_samp_factor = 1 cinfo->comp_info[2].h_samp_factor = 1 for Cr cinfo->comp_info[2].v_samp_factor = 1 and suppose that the nominal image dimensions (cinfo->image_width and cinfo->image_height) are 101x101 pixels. Then jpeg_start_compress() will compute downsampled_width = 101 and width_in_blocks = 13 for Y, downsampled_width = 51 and width_in_blocks = 7 for Cb and Cr (and the same for the height fields). You must pad the Y data to at least 13*8 = 104 columns and rows, the Cb/Cr data to at least 7*8 = 56 columns and rows. The MCU height is max_v_samp_factor = 2 DCT rows so you must pass at least 16 scanlines on each call to jpeg_write_raw_data(), which is to say 16 actual sample rows of Y and 8 each of Cb and Cr. A total of 7 MCU rows are needed, so you must pass a total of 7*16 = 112 "scanlines". The last DCT block row of Y data is dummy, so it doesn't matter what you pass for it in the data arrays, but the scanlines count must total up to 112 so that all of the Cb and Cr data gets passed. Output suspension is supported with raw-data compression: if the data destination module suspends, jpeg_write_raw_data() will return 0. In this case the same data rows must be passed again on the next call. Decompression with raw data output implies bypassing all postprocessing: you cannot ask for color quantization, for instance. More seriously, you must deal with the color space and sampling factors present in the incoming file. If your application only handles, say, 2h1v YCbCr data, you must check for and fail on other color spaces or other sampling factors. The library will not convert to a different color space for you. To obtain raw data output, set cinfo->raw_data_out = TRUE before jpeg_start_decompress() (it is set FALSE by jpeg_read_header()). Be sure to verify that the color space and sampling factors are ones you can handle. Then call jpeg_read_raw_data() in place of jpeg_read_scanlines(). The decompression process is otherwise the same as usual. jpeg_read_raw_data() returns one MCU row per call, and thus you must pass a buffer of at least max_v_samp_factor*min_DCT_v_scaled_size scanlines (scanline counting is the same as for raw-data compression). The buffer you pass must be large enough to hold the actual data plus padding to DCT-block boundaries. As with compression, any entirely dummy DCT blocks are not processed so you need not allocate space for them, but the total scanline count includes them. The above example of computing buffer dimensions for raw-data compression is equally valid for decompression. Input suspension is supported with raw-data decompression: if the data source module suspends, jpeg_read_raw_data() will return 0. You can also use buffered-image mode to read raw data in multiple passes. Really raw data: DCT coefficients --------------------------------- It is possible to read or write the contents of a JPEG file as raw DCT coefficients. This facility is mainly intended for use in lossless transcoding between different JPEG file formats. Other possible applications include lossless cropping of a JPEG image, lossless reassembly of a multi-strip or multi-tile TIFF/JPEG file into a single JPEG datastream, etc. To read the contents of a JPEG file as DCT coefficients, open the file and do jpeg_read_header() as usual. But instead of calling jpeg_start_decompress() and jpeg_read_scanlines(), call jpeg_read_coefficients(). This will read the entire image into a set of virtual coefficient-block arrays, one array per component. The return value is a pointer to an array of virtual-array descriptors. Each virtual array can be accessed directly using the JPEG memory manager's access_virt_barray method (see Memory management, below, and also read structure.txt's discussion of virtual array handling). Or, for simple transcoding to a different JPEG file format, the array list can just be handed directly to jpeg_write_coefficients(). Each block in the block arrays contains quantized coefficient values in normal array order (not JPEG zigzag order). The block arrays contain only DCT blocks containing real data; any entirely-dummy blocks added to fill out interleaved MCUs at the right or bottom edges of the image are discarded during reading and are not stored in the block arrays. (The size of each block array can be determined from the width_in_blocks and height_in_blocks fields of the component's comp_info entry.) This is also the data format expected by jpeg_write_coefficients(). When you are done using the virtual arrays, call jpeg_finish_decompress() to release the array storage and return the decompression object to an idle state; or just call jpeg_destroy() if you don't need to reuse the object. If you use a suspending data source, jpeg_read_coefficients() will return NULL if it is forced to suspend; a non-NULL return value indicates successful completion. You need not test for a NULL return value when using a non-suspending data source. It is also possible to call jpeg_read_coefficients() to obtain access to the decoder's coefficient arrays during a normal decode cycle in buffered-image mode. This frammish might be useful for progressively displaying an incoming image and then re-encoding it without loss. To do this, decode in buffered- image mode as discussed previously, then call jpeg_read_coefficients() after the last jpeg_finish_output() call. The arrays will be available for your use until you call jpeg_finish_decompress(). To write the contents of a JPEG file as DCT coefficients, you must provide the DCT coefficients stored in virtual block arrays. You can either pass block arrays read from an input JPEG file by jpeg_read_coefficients(), or allocate virtual arrays from the JPEG compression object and fill them yourself. In either case, jpeg_write_coefficients() is substituted for jpeg_start_compress() and jpeg_write_scanlines(). Thus the sequence is * Create compression object * Set all compression parameters as necessary * Request virtual arrays if needed * jpeg_write_coefficients() * jpeg_finish_compress() * Destroy or re-use compression object jpeg_write_coefficients() is passed a pointer to an array of virtual block array descriptors; the number of arrays is equal to cinfo.num_components. The virtual arrays need only have been requested, not realized, before jpeg_write_coefficients() is called. A side-effect of jpeg_write_coefficients() is to realize any virtual arrays that have been requested from the compression object's memory manager. Thus, when obtaining the virtual arrays from the compression object, you should fill the arrays after calling jpeg_write_coefficients(). The data is actually written out when you call jpeg_finish_compress(); jpeg_write_coefficients() only writes the file header. When writing raw DCT coefficients, it is crucial that the JPEG quantization tables and sampling factors match the way the data was encoded, or the resulting file will be invalid. For transcoding from an existing JPEG file, we recommend using jpeg_copy_critical_parameters(). This routine initializes all the compression parameters to default values (like jpeg_set_defaults()), then copies the critical information from a source decompression object. The decompression object should have just been used to read the entire JPEG input file --- that is, it should be awaiting jpeg_finish_decompress(). jpeg_write_coefficients() marks all tables stored in the compression object as needing to be written to the output file (thus, it acts like jpeg_start_compress(cinfo, TRUE)). This is for safety's sake, to avoid emitting abbreviated JPEG files by accident. If you really want to emit an abbreviated JPEG file, call jpeg_suppress_tables(), or set the tables' individual sent_table flags, between calling jpeg_write_coefficients() and jpeg_finish_compress(). Progress monitoring ------------------- Some applications may need to regain control from the JPEG library every so often. The typical use of this feature is to produce a percent-done bar or other progress display. (For a simple example, see cjpeg.c or djpeg.c.) Although you do get control back frequently during the data-transferring pass (the jpeg_read_scanlines or jpeg_write_scanlines loop), any additional passes will occur inside jpeg_finish_compress or jpeg_start_decompress; those routines may take a long time to execute, and you don't get control back until they are done. You can define a progress-monitor routine which will be called periodically by the library. No guarantees are made about how often this call will occur, so we don't recommend you use it for mouse tracking or anything like that. At present, a call will occur once per MCU row, scanline, or sample row group, whichever unit is convenient for the current processing mode; so the wider the image, the longer the time between calls. During the data transferring pass, only one call occurs per call of jpeg_read_scanlines or jpeg_write_scanlines, so don't pass a large number of scanlines at once if you want fine resolution in the progress count. (If you really need to use the callback mechanism for time-critical tasks like mouse tracking, you could insert additional calls inside some of the library's inner loops.) To establish a progress-monitor callback, create a struct jpeg_progress_mgr, fill in its progress_monitor field with a pointer to your callback routine, and set cinfo->progress to point to the struct. The callback will be called whenever cinfo->progress is non-NULL. (This pointer is set to NULL by jpeg_create_compress or jpeg_create_decompress; the library will not change it thereafter. So if you allocate dynamic storage for the progress struct, make sure it will live as long as the JPEG object does. Allocating from the JPEG memory manager with lifetime JPOOL_PERMANENT will work nicely.) You can use the same callback routine for both compression and decompression. The jpeg_progress_mgr struct contains four fields which are set by the library: long pass_counter; /* work units completed in this pass */ long pass_limit; /* total number of work units in this pass */ int completed_passes; /* passes completed so far */ int total_passes; /* total number of passes expected */ During any one pass, pass_counter increases from 0 up to (not including) pass_limit; the step size is usually but not necessarily 1. The pass_limit value may change from one pass to another. The expected total number of passes is in total_passes, and the number of passes already completed is in completed_passes. Thus the fraction of work completed may be estimated as completed_passes + (pass_counter/pass_limit) -------------------------------------------- total_passes ignoring the fact that the passes may not be equal amounts of work. When decompressing, pass_limit can even change within a pass, because it depends on the number of scans in the JPEG file, which isn't always known in advance. The computed fraction-of-work-done may jump suddenly (if the library discovers it has overestimated the number of scans) or even decrease (in the opposite case). It is not wise to put great faith in the work estimate. When using the decompressor's buffered-image mode, the progress monitor work estimate is likely to be completely unhelpful, because the library has no way to know how many output passes will be demanded of it. Currently, the library sets total_passes based on the assumption that there will be one more output pass if the input file end hasn't yet been read (jpeg_input_complete() isn't TRUE), but no more output passes if the file end has been reached when the output pass is started. This means that total_passes will rise as additional output passes are requested. If you have a way of determining the input file size, estimating progress based on the fraction of the file that's been read will probably be more useful than using the library's value. Memory management ----------------- This section covers some key facts about the JPEG library's built-in memory manager. For more info, please read structure.txt's section about the memory manager, and consult the source code if necessary. All memory and temporary file allocation within the library is done via the memory manager. If necessary, you can replace the "back end" of the memory manager to control allocation yourself (for example, if you don't want the library to use malloc() and free() for some reason). Some data is allocated "permanently" and will not be freed until the JPEG object is destroyed. Most data is allocated "per image" and is freed by jpeg_finish_compress, jpeg_finish_decompress, or jpeg_abort. You can call the memory manager yourself to allocate structures that will automatically be freed at these times. Typical code for this is ptr = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, size); Use JPOOL_PERMANENT to get storage that lasts as long as the JPEG object. Use alloc_large instead of alloc_small for anything bigger than a few Kbytes. There are also alloc_sarray and alloc_barray routines that automatically build 2-D sample or block arrays. The library's minimum space requirements to process an image depend on the image's width, but not on its height, because the library ordinarily works with "strip" buffers that are as wide as the image but just a few rows high. Some operating modes (eg, two-pass color quantization) require full-image buffers. Such buffers are treated as "virtual arrays": only the current strip need be in memory, and the rest can be swapped out to a temporary file. If you use the simplest memory manager back end (jmemnobs.c), then no temporary files are used; virtual arrays are simply malloc()'d. Images bigger than memory can be processed only if your system supports virtual memory. The other memory manager back ends support temporary files of various flavors and thus work in machines without virtual memory. They may also be useful on Unix machines if you need to process images that exceed available swap space. When using temporary files, the library will make the in-memory buffers for its virtual arrays just big enough to stay within a "maximum memory" setting. Your application can set this limit by setting cinfo->mem->max_memory_to_use after creating the JPEG object. (Of course, there is still a minimum size for the buffers, so the max-memory setting is effective only if it is bigger than the minimum space needed.) If you allocate any large structures yourself, you must allocate them before jpeg_start_compress() or jpeg_start_decompress() in order to have them counted against the max memory limit. Also keep in mind that space allocated with alloc_small() is ignored, on the assumption that it's too small to be worth worrying about; so a reasonable safety margin should be left when setting max_memory_to_use. If you use the jmemname.c or jmemdos.c memory manager back end, it is important to clean up the JPEG object properly to ensure that the temporary files get deleted. (This is especially crucial with jmemdos.c, where the "temporary files" may be extended-memory segments; if they are not freed, DOS will require a reboot to recover the memory.) Thus, with these memory managers, it's a good idea to provide a signal handler that will trap any early exit from your program. The handler should call either jpeg_abort() or jpeg_destroy() for any active JPEG objects. A handler is not needed with jmemnobs.c, and shouldn't be necessary with jmemansi.c or jmemmac.c either, since the C library is supposed to take care of deleting files made with tmpfile(). Memory usage ------------ Working memory requirements while performing compression or decompression depend on image dimensions, image characteristics (such as colorspace and JPEG process), and operating mode (application-selected options). As of v6b, the decompressor requires: 1. About 24K in more-or-less-fixed-size data. This varies a bit depending on operating mode and image characteristics (particularly color vs. grayscale), but it doesn't depend on image dimensions. 2. Strip buffers (of size proportional to the image width) for IDCT and upsampling results. The worst case for commonly used sampling factors is about 34 bytes * width in pixels for a color image. A grayscale image only needs about 8 bytes per pixel column. 3. A full-image DCT coefficient buffer is needed to decode a multi-scan JPEG file (including progressive JPEGs), or whenever you select buffered-image mode. This takes 2 bytes/coefficient. At typical 2x2 sampling, that's 3 bytes per pixel for a color image. Worst case (1x1 sampling) requires 6 bytes/pixel. For grayscale, figure 2 bytes/pixel. 4. To perform 2-pass color quantization, the decompressor also needs a 128K color lookup table and a full-image pixel buffer (3 bytes/pixel). This does not count any memory allocated by the application, such as a buffer to hold the final output image. The above figures are valid for 8-bit JPEG data precision and a machine with 32-bit ints. For 9-bit to 12-bit JPEG data, double the size of the strip buffers and quantization pixel buffer. The "fixed-size" data will be somewhat smaller with 16-bit ints, larger with 64-bit ints. Also, CMYK or other unusual color spaces will require different amounts of space. The full-image coefficient and pixel buffers, if needed at all, do not have to be fully RAM resident; you can have the library use temporary files instead when the total memory usage would exceed a limit you set. (But if your OS supports virtual memory, it's probably better to just use jmemnobs and let the OS do the swapping.) The compressor's memory requirements are similar, except that it has no need for color quantization. Also, it needs a full-image DCT coefficient buffer if Huffman-table optimization is asked for, even if progressive mode is not requested. If you need more detailed information about memory usage in a particular situation, you can enable the MEM_STATS code in jmemmgr.c. Library compile-time options ---------------------------- A number of compile-time options are available by modifying jmorecfg.h. The IJG code currently supports 8-bit to 12-bit sample data precision by defining BITS_IN_JSAMPLE as 8, 9, 10, 11, or 12. Note that a value larger than 8 causes JSAMPLE to be larger than a char, so it affects the surrounding application's image data. The sample applications cjpeg and djpeg can support deeper than 8-bit data only for PPM and GIF file formats; you must disable the other file formats to compile a 9-bit to 12-bit cjpeg or djpeg. (install.txt has more information about that.) Run-time selection and conversion of data precision are currently not supported and may be added later. Exception: The transcoding part (jpegtran) supports all settings in a single instance, since it operates on the level of DCT coefficients and not sample values. (If you need to include an 8-bit library and a 9-bit to 12-bit library for compression or decompression in a single application, you could probably do it by defining NEED_SHORT_EXTERNAL_NAMES for just one of the copies. You'd have to access the 8-bit and the 9-bit to 12-bit copies from separate application source files. This is untested ... if you try it, we'd like to hear whether it works!) Note that the standard Huffman tables are only valid for 8-bit data precision. If you selected more than 8-bit data precision, cjpeg uses arithmetic coding by default. The Huffman encoder normally uses entropy optimization to compute usable tables for higher precision. Otherwise, you'll have to supply different default Huffman tables. You may also want to supply your own DCT quantization tables; the existing quality-scaling code has been developed for 8-bit use, and probably doesn't generate especially good tables for 9-bit to 12-bit. The maximum number of components (color channels) in the image is determined by MAX_COMPONENTS. The JPEG standard allows up to 255 components, but we expect that few applications will need more than four or so. On machines with unusual data type sizes, you may be able to improve performance or reduce memory space by tweaking the various typedefs in jmorecfg.h. In particular, on some RISC CPUs, access to arrays of "short"s is quite slow; consider trading memory for speed by making JCOEF, INT16, and UINT16 be "int" or "unsigned int". UINT8 is also a candidate to become int. You probably don't want to make JSAMPLE be int unless you have lots of memory to burn. You can reduce the size of the library by compiling out various optional functions. To do this, undefine xxx_SUPPORTED symbols as necessary. You can also save a few K by not having text error messages in the library; the standard error message table occupies about 5Kb. This is particularly reasonable for embedded applications where there's no good way to display a message anyway. To do this, remove the creation of the message table (jpeg_std_message_table[]) from jerror.c, and alter format_message to do something reasonable without it. You could output the numeric value of the message code number, for example. If you do this, you can also save a couple more K by modifying the TRACEMSn() macros in jerror.h to expand to nothing; you don't need trace capability anyway, right? Portability considerations -------------------------- The JPEG library has been written to be extremely portable; the sample applications cjpeg and djpeg are slightly less so. This section summarizes the design goals in this area. (If you encounter any bugs that cause the library to be less portable than is claimed here, we'd appreciate hearing about them.) The code works fine on ANSI C, C++, and pre-ANSI C compilers, using any of the popular system include file setups, and some not-so-popular ones too. See install.txt for configuration procedures. The code is not dependent on the exact sizes of the C data types. As distributed, we make the assumptions that char is at least 8 bits wide short is at least 16 bits wide int is at least 16 bits wide long is at least 32 bits wide (These are the minimum requirements of the ANSI C standard.) Wider types will work fine, although memory may be used inefficiently if char is much larger than 8 bits or short is much bigger than 16 bits. The code should work equally well with 16- or 32-bit ints. In a system where these assumptions are not met, you may be able to make the code work by modifying the typedefs in jmorecfg.h. However, you will probably have difficulty if int is less than 16 bits wide, since references to plain int abound in the code. char can be either signed or unsigned, although the code runs faster if an unsigned char type is available. If char is wider than 8 bits, you will need to redefine JOCTET and/or provide custom data source/destination managers so that JOCTET represents exactly 8 bits of data on external storage. The JPEG library proper does not assume ASCII representation of characters. But some of the image file I/O modules in cjpeg/djpeg do have ASCII dependencies in file-header manipulation; so does cjpeg's select_file_type() routine. The JPEG library does not rely heavily on the C library. In particular, C stdio is used only by the data source/destination modules and the error handler, all of which are application-replaceable. (cjpeg/djpeg are more heavily dependent on stdio.) malloc and free are called only from the memory manager "back end" module, so you can use a different memory allocator by replacing that one file. The code generally assumes that C names must be unique in the first 15 characters. However, global function names can be made unique in the first 6 characters by defining NEED_SHORT_EXTERNAL_NAMES. More info about porting the code may be gleaned by reading jconfig.txt, jmorecfg.h, and jinclude.h. Notes for MS-DOS implementors ----------------------------- The IJG code is designed to work efficiently in 80x86 "small" or "medium" memory models (i.e., data pointers are 16 bits unless explicitly declared "far"; code pointers can be either size). You may be able to use small model to compile cjpeg or djpeg by itself, but you will probably have to use medium model for any larger application. This won't make much difference in performance. You *will* take a noticeable performance hit if you use a large-data memory model (perhaps 10%-25%), and you should avoid "huge" model if at all possible. The JPEG library typically needs 2Kb-3Kb of stack space. It will also malloc about 20K-30K of near heap space while executing (and lots of far heap, but that doesn't count in this calculation). This figure will vary depending on selected operating mode, and to a lesser extent on image size. There is also about 5Kb-6Kb of constant data which will be allocated in the near data segment (about 4Kb of this is the error message table). Thus you have perhaps 20K available for other modules' static data and near heap space before you need to go to a larger memory model. The C library's static data will account for several K of this, but that still leaves a good deal for your needs. (If you are tight on space, you could reduce the sizes of the I/O buffers allocated by jdatasrc.c and jdatadst.c, say from 4K to 1K. Another possibility is to move the error message table to far memory; this should be doable with only localized hacking on jerror.c.) About 2K of the near heap space is "permanent" memory that will not be released until you destroy the JPEG object. This is only an issue if you save a JPEG object between compression or decompression operations. Far data space may also be a tight resource when you are dealing with large images. The most memory-intensive case is decompression with two-pass color quantization, or single-pass quantization to an externally supplied color map. This requires a 128Kb color lookup table plus strip buffers amounting to about 40 bytes per column for typical sampling ratios (eg, about 25600 bytes for a 640-pixel-wide image). You may not be able to process wide images if you have large data structures of your own. Of course, all of these concerns vanish if you use a 32-bit flat-memory-model compiler, such as DJGPP or Watcom C. We highly recommend flat model if you can use it; the JPEG library is significantly faster in flat model. fltk-1.4.3/jpeg/jcapistd.c0000644000175000017500000001346415004135251015507 0ustar albrechtalbrecht/* * jcapistd.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface code for the compression half * of the JPEG library. These are the "standard" API routines that are * used in the normal full-compression case. They are not used by a * transcoding-only application. Note that if an application links in * jpeg_start_compress, it will end up linking in the entire compressor. * We thus must separate this file from jcapimin.c to avoid linking the * whole compression library into a transcoder. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Compression initialization. * Before calling this, all parameters and a data destination must be set up. * * We require a write_all_tables parameter as a failsafe check when writing * multiple datastreams from the same compression object. Since prior runs * will have left all the tables marked sent_table=TRUE, a subsequent run * would emit an abbreviated stream (no tables) by default. This may be what * is wanted, but for safety's sake it should not be the default behavior: * programmers should have to make a deliberate choice to emit abbreviated * images. Therefore the documentation and examples should encourage people * to pass write_all_tables=TRUE; then it will take active thought to do the * wrong thing. */ GLOBAL(void) jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) { if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (write_all_tables) jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); /* Perform master selection of active modules */ jinit_compress_master(cinfo); /* Set up for the first pass */ (*cinfo->master->prepare_for_pass) (cinfo); /* Ready for application to drive first pass through jpeg_write_scanlines * or jpeg_write_raw_data. */ cinfo->next_scanline = 0; cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); } /* * Write some scanlines of data to the JPEG compressor. * * The return value will be the number of lines actually written. * This should be less than the supplied num_lines only in case that * the data destination module has requested suspension of the compressor, * or if more than image_height scanlines are passed in. * * Note: we warn about excess calls to jpeg_write_scanlines() since * this likely signals an application programmer error. However, * excess scanlines passed in the last valid call are *silently* ignored, * so that the application need not adjust num_lines for end-of-image * when using a multiple-scanline buffer. */ GLOBAL(JDIMENSION) jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines) { JDIMENSION row_ctr, rows_left; if (cinfo->global_state != CSTATE_SCANNING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->next_scanline >= cinfo->image_height) WARNMS(cinfo, JWRN_TOO_MUCH_DATA); /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->next_scanline; cinfo->progress->pass_limit = (long) cinfo->image_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Give master control module another chance if this is first call to * jpeg_write_scanlines. This lets output of the frame/scan headers be * delayed so that application can write COM, etc, markers between * jpeg_start_compress and jpeg_write_scanlines. */ if (cinfo->master->call_pass_startup) (*cinfo->master->pass_startup) (cinfo); /* Ignore any extra scanlines at bottom of image. */ rows_left = cinfo->image_height - cinfo->next_scanline; if (num_lines > rows_left) num_lines = rows_left; row_ctr = 0; (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); cinfo->next_scanline += row_ctr; return row_ctr; } /* * Alternate entry point to write raw data. * Processes exactly one iMCU row per call, unless suspended. */ GLOBAL(JDIMENSION) jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, JDIMENSION num_lines) { JDIMENSION lines_per_iMCU_row; if (cinfo->global_state != CSTATE_RAW_OK) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->next_scanline >= cinfo->image_height) { WARNMS(cinfo, JWRN_TOO_MUCH_DATA); return 0; } /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->next_scanline; cinfo->progress->pass_limit = (long) cinfo->image_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Give master control module another chance if this is first call to * jpeg_write_raw_data. This lets output of the frame/scan headers be * delayed so that application can write COM, etc, markers between * jpeg_start_compress and jpeg_write_raw_data. */ if (cinfo->master->call_pass_startup) (*cinfo->master->pass_startup) (cinfo); /* Verify that at least one iMCU row has been passed. */ lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size; if (num_lines < lines_per_iMCU_row) ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Directly compress the row. */ if (! (*cinfo->coef->compress_data) (cinfo, data)) { /* If compressor did not consume the whole row, suspend processing. */ return 0; } /* OK, we processed one iMCU row. */ cinfo->next_scanline += lines_per_iMCU_row; return lines_per_iMCU_row; } fltk-1.4.3/jpeg/coderules.txt0000644000175000017500000001236415004135251016266 0ustar albrechtalbrechtIJG JPEG LIBRARY: CODING RULES Copyright (C) 1991-1996, Thomas G. Lane. This file is part of the Independent JPEG Group's software. For conditions of distribution and use, see the accompanying README file. Since numerous people will be contributing code and bug fixes, it's important to establish a common coding style. The goal of using similar coding styles is much more important than the details of just what that style is. In general we follow the recommendations of "Recommended C Style and Coding Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and Brader). This document is available in the IJG FTP archive (see jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl). Block comments should be laid out thusly: /* * Block comments in this style. */ We indent statements in K&R style, e.g., if (test) { then-part; } else { else-part; } with two spaces per indentation level. (This indentation convention is handled automatically by GNU Emacs and many other text editors.) Multi-word names should be written in lower case with underscores, e.g., multi_word_name (not multiWordName). Preprocessor symbols and enum constants are similar but upper case (MULTI_WORD_NAME). Names should be unique within the first fifteen characters. (On some older systems, global names must be unique within six characters. We accommodate this without cluttering the source code by using macros to substitute shorter names.) We use function prototypes everywhere; we rely on automatic source code transformation to feed prototype-less C compilers. Transformation is done by the simple and portable tool 'ansi2knr.c' (courtesy of Ghostscript). ansi2knr is not very bright, so it imposes a format requirement on function declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions should be written in the following style: LOCAL(int *) function_name (int a, char *b) { code... } Note that each function definition must begin with GLOBAL(type), LOCAL(type), or METHODDEF(type). These macros expand to "static type" or just "type" as appropriate. They provide a readable indication of the routine's usage and can readily be changed for special needs. (For instance, special linkage keywords can be inserted for use in Windows DLLs.) ansi2knr does not transform method declarations (function pointers in structs). We handle these with a macro JMETHOD, defined as #ifdef HAVE_PROTOTYPES #define JMETHOD(type,methodname,arglist) type (*methodname) arglist #else #define JMETHOD(type,methodname,arglist) type (*methodname) () #endif which is used like this: struct function_pointers { JMETHOD(void, init_entropy_encoder, (int somearg, jparms *jp)); JMETHOD(void, term_entropy_encoder, (void)); }; Note the set of parentheses surrounding the parameter list. A similar solution is used for forward and external function declarations (see the EXTERN and JPP macros). If the code is to work on non-ANSI compilers, we cannot rely on a prototype declaration to coerce actual parameters into the right types. Therefore, use explicit casts on actual parameters whenever the actual parameter type is not identical to the formal parameter. Beware of implicit conversions to "int". It seems there are some non-ANSI compilers in which the sizeof() operator is defined to return int, yet size_t is defined as long. Needless to say, this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(), so that the result is guaranteed to be of type size_t. The JPEG library is intended to be used within larger programs. Furthermore, we want it to be reentrant so that it can be used by applications that process multiple images concurrently. The following rules support these requirements: 1. Avoid direct use of file I/O, "malloc", error report printouts, etc; pass these through the common routines provided. 2. Minimize global namespace pollution. Functions should be declared static wherever possible. (Note that our method-based calling conventions help this a lot: in many modules only the initialization function will ever need to be called directly, so only that function need be externally visible.) All global function names should begin with "jpeg_", and should have an abbreviated name (unique in the first six characters) substituted by macro when NEED_SHORT_EXTERNAL_NAMES is set. 3. Don't use global variables; anything that must be used in another module should be in the common data structures. 4. Don't use static variables except for read-only constant tables. Variables that should be private to a module can be placed into private structures (see the system architecture document, structure.txt). 5. Source file names should begin with "j" for files that are part of the library proper; source files that are not part of the library, such as cjpeg.c and djpeg.c, do not begin with "j". Keep source file names to eight characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers. Keep compression and decompression code in separate source files --- some applications may want only one half of the library. Note: these rules (particularly #4) are not followed religiously in the modules that are used in cjpeg/djpeg but are not part of the JPEG library proper. Those modules are not really intended to be used in other applications. fltk-1.4.3/jpeg/README0000644000175000017500000004443715004135251014426 0ustar albrechtalbrechtThe Independent JPEG Group's JPEG software ========================================== README for release 9f of 14-Jan-2024 ==================================== This distribution contains the ninth public release of the Independent JPEG Group's free JPEG software. You are welcome to redistribute this software and to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. This software is the work of Tom Lane, Guido Vollbeding, Philip Gladstone, Bill Allombert, Jim Boucher, Lee Crocker, Bob Friesenhahn, Ben Jackson, John Korejwa, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers, and other members of the Independent JPEG Group. IJG is not affiliated with the ISO/IEC JTC1/SC29/WG1 standards committee (previously known as JPEG, together with ITU-T SG16). DOCUMENTATION ROADMAP ===================== This file contains the following sections: OVERVIEW General description of JPEG and the IJG software. LEGAL ISSUES Copyright, lack of warranty, terms of distribution. REFERENCES Where to learn more about JPEG. ARCHIVE LOCATIONS Where to find newer versions of this software. ACKNOWLEDGMENTS Special thanks. FILE FORMAT WARS Software *not* to get. TO DO Plans for future IJG releases. Other documentation files in the distribution are: User documentation: install.txt How to configure and install the IJG software. usage.txt Usage instructions for cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom. *.1 Unix-style man pages for programs (same info as usage.txt). wizard.txt Advanced usage instructions for JPEG wizards only. cdaltui.txt Description of alternate user interface for cjpeg/djpeg. change.log Version-to-version change highlights. Programmer and internal documentation: libjpeg.txt How to use the JPEG library in your own programs. example.c Sample code for calling the JPEG library. structure.txt Overview of the JPEG library's internal structure. filelist.txt Road map of IJG files. coderules.txt Coding style rules --- please read if you contribute code. Please read at least the files install.txt and usage.txt. Some information can also be found in the JPEG FAQ (Frequently Asked Questions) article. See ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. If you want to understand how the JPEG code works, we suggest reading one or more of the REFERENCES, then looking at the documentation files (in roughly the order listed) before diving into the code. OVERVIEW ======== This package contains C software to implement JPEG image encoding, decoding, and transcoding. JPEG (pronounced "jay-peg") is a standardized compression method for full-color and grayscale images. This software implements JPEG baseline, extended-sequential, and progressive compression processes. Provision is made for supporting all variants of these processes, although some uncommon parameter settings aren't implemented yet. We have made no provision for supporting the hierarchical or lossless processes defined in the standard. We provide a set of library routines for reading and writing JPEG image files, plus two sample applications "cjpeg" and "djpeg", which use the library to perform conversion between JPEG and some other popular image file formats. The library is intended to be reused in other applications. In order to support file conversion and viewing software, we have included considerable functionality beyond the bare JPEG coding/decoding capability; for example, the color quantization modules are not strictly part of JPEG decoding, but they are essential for output to colormapped file formats or colormapped displays. These extra functions can be compiled out of the library if not required for a particular application. We have also included "jpegtran", a utility for lossless transcoding between different JPEG processes, and "rdjpgcom" and "wrjpgcom", two simple applications for inserting and extracting textual comments in JFIF files. The emphasis in designing this software has been on achieving portability and flexibility, while also making it fast enough to be useful. In particular, the software is not intended to be read as a tutorial on JPEG. (See the REFERENCES section for introductory material.) Rather, it is intended to be reliable, portable, industrial-strength code. We do not claim to have achieved that goal in every aspect of the software, but we strive for it. We welcome the use of this software as a component of commercial products. No royalty is required, but we do ask for an acknowledgement in product documentation, as described under LEGAL ISSUES. LEGAL ISSUES ============ In plain English: 1. We don't promise that this software works. (But if you find any bugs, please let us know!) 2. You can use this software for whatever you want. You don't have to pay us. 3. You may not pretend that you wrote this software. If you use it in a program, you must acknowledge somewhere in your documentation that you've used the IJG code. In legalese: The authors make NO WARRANTY or representation, either express or implied, with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. This software is copyright (C) 1991-2024, Thomas G. Lane, Guido Vollbeding. All Rights Reserved except as specified below. Permission is hereby granted to use, copy, modify, and distribute this software (or portions thereof) for any purpose, without fee, subject to these conditions: (1) If any part of the source code for this software is distributed, then this README file must be included, with this copyright and no-warranty notice unaltered; and any additions, deletions, or changes to the original files must be clearly indicated in accompanying documentation. (2) If only executable code is distributed, then the accompanying documentation must state that "this software is based in part on the work of the Independent JPEG Group". (3) Permission for use of this software is granted only if the user accepts full responsibility for any undesirable consequences; the authors accept NO LIABILITY for damages of any kind. These conditions apply to any software derived from or based on the IJG code, not just to the unmodified library. If you use our work, you ought to acknowledge us. Permission is NOT granted for the use of any IJG author's name or company name in advertising or publicity relating to this software or products derived from it. This software may be referred to only as "the Independent JPEG Group's software". We specifically permit and encourage the use of this software as the basis of commercial products, provided that all warranty or liability claims are assumed by the product vendor. The Unix configuration script "configure" was produced with GNU Autoconf. It is copyright by the Free Software Foundation but is freely distributable. The same holds for its supporting scripts (config.guess, config.sub, ltmain.sh). Another support script, install-sh, is copyright by X Consortium but is also freely distributable. REFERENCES ========== We recommend reading one or more of these references before trying to understand the innards of the JPEG software. The best short technical introduction to the JPEG compression algorithm is Wallace, Gregory K. "The JPEG Still Picture Compression Standard", Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. (Adjacent articles in that issue discuss MPEG motion picture compression, applications of JPEG, and related topics.) If you don't have the CACM issue handy, a PDF file containing a revised version of Wallace's article is available at https://www.ijg.org/files/Wallace.JPEG.pdf. The file (actually a preprint for an article that appeared in IEEE Trans. Consumer Electronics) omits the sample images that appeared in CACM, but it includes corrections and some added material. Note: the Wallace article is copyright ACM and IEEE, and it may not be used for commercial purposes. A somewhat less technical, more leisurely introduction to JPEG can be found in "The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides good explanations and example C code for a multitude of compression methods including JPEG. It is an excellent source if you are comfortable reading C code but don't know much about data compression in general. The book's JPEG sample code is far from industrial-strength, but when you are ready to look at a full implementation, you've got one here... The best currently available description of JPEG is the textbook "JPEG Still Image Data Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. The book includes the complete text of the ISO JPEG standards (DIS 10918-1 and draft DIS 10918-2). Although this is by far the most detailed and comprehensive exposition of JPEG publicly available, we point out that it is still missing an explanation of the most essential properties and algorithms of the underlying DCT technology. If you think that you know about DCT-based JPEG after reading this book, then you are in delusion. The real fundamentals and corresponding potential of DCT-based JPEG are not publicly known so far, and that is the reason for all the mistaken developments taking place in the image coding domain. The original JPEG standard is divided into two parts, Part 1 being the actual specification, while Part 2 covers compliance testing methods. Part 1 is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS 10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 2: Compliance testing" and has document numbers ISO/IEC IS 10918-2, ITU-T T.83. IJG JPEG 8 introduced an implementation of the JPEG SmartScale extension which is specified in two documents: A contributed document at ITU and ISO with title "ITU-T JPEG-Plus Proposal for Extending ITU-T T.81 for Advanced Image Coding", April 2006, Geneva, Switzerland. The latest version of this document is Revision 3. And a contributed document ISO/IEC JTC1/SC29/WG1 N 5799 with title "Evolution of JPEG", June/July 2011, Berlin, Germany. IJG JPEG 9 introduces a reversible color transform for improved lossless compression which is described in a contributed document ISO/IEC JTC1/SC29/ WG1 N 6080 with title "JPEG 9 Lossless Coding", June/July 2012, Paris, France. The JPEG standard does not specify all details of an interchangeable file format. For the omitted details we follow the "JFIF" conventions, version 2. JFIF version 1 has been adopted as Recommendation ITU-T T.871 (05/2011) : Information technology - Digital compression and coding of continuous-tone still images: JPEG File Interchange Format (JFIF). It is available as a free download in PDF file format from https://www.itu.int/rec/T-REC-T.871. A PDF file of the older JFIF document is available at https://www.w3.org/Graphics/JPEG/jfif3.pdf. The TIFF 6.0 file format specification can be obtained by FTP from ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 (Compression tag 7). Copies of this Note can be obtained from https://www.ijg.org/files/. It is expected that the next revision of the TIFF spec will replace the 6.0 JPEG design with the Note's design. Although IJG's own code does not support TIFF/JPEG, the free libtiff library uses our library to implement TIFF/JPEG per the Note. ARCHIVE LOCATIONS ================= The "official" archive site for this software is www.ijg.org. The most recent released version can always be found there in directory "files". This particular version will be archived in Windows-compatible "zip" archive format as https://www.ijg.org/files/jpegsr9f.zip, and in Unix-compatible "tar.gz" archive format as https://www.ijg.org/files/jpegsrc.v9f.tar.gz. The JPEG FAQ (Frequently Asked Questions) article is a source of some general information about JPEG. It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ and other news.answers archive sites, including the official news.answers archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu with body send usenet/news.answers/jpeg-faq/part1 send usenet/news.answers/jpeg-faq/part2 ACKNOWLEDGMENTS =============== Thank to Juergen Bruder for providing me with a copy of the common DCT algorithm article, only to find out that I had come to the same result in a more direct and comprehensible way with a more generative approach. Thank to Istvan Sebestyen and Joan L. Mitchell for inviting me to the ITU JPEG (Study Group 16) meeting in Geneva, Switzerland. Thank to Thomas Wiegand and Gary Sullivan for inviting me to the Joint Video Team (MPEG & ITU) meeting in Geneva, Switzerland. Thank to Thomas Richter and Daniel Lee for inviting me to the ISO/IEC JTC1/SC29/WG1 (previously known as JPEG, together with ITU-T SG16) meeting in Berlin, Germany. Thank to John Korejwa and Massimo Ballerini for inviting me to fruitful consultations in Boston, MA and Milan, Italy. Thank to Hendrik Elstner, Roland Fassauer, Simone Zuck, Guenther Maier-Gerber, Walter Stoeber, Fred Schmitz, and Norbert Braunagel for corresponding business development. Thank to Nico Zschach and Dirk Stelling of the technical support team at the Digital Images company in Halle for providing me with extra equipment for configuration tests. Thank to Richard F. Lyon (then of Foveon Inc.) for fruitful communication about JPEG configuration in Sigma Photo Pro software. Thank to Andrew Finkenstadt for hosting the ijg.org site. Thank to Thomas G. Lane for the original design and development of this singular software package. Thank to Lars Goehler, Andreas Heinecke, Sebastian Fuss, Yvonne Roebert, Andrej Werner, Ulf-Dietrich Braumann, and Nina Ssymank for support and public relations. FILE FORMAT WARS ================ The ISO/IEC JTC1/SC29/WG1 standards committee (previously known as JPEG, together with ITU-T SG16) currently promotes different formats containing the name "JPEG" which is misleading because these formats are incompatible with original DCT-based JPEG and are based on faulty technologies. IJG therefore does not and will not support such momentary mistakes (see REFERENCES). There exist also distributions under the name "OpenJPEG" promoting such kind of formats which is misleading because they don't support original JPEG images. We have no sympathy for the promotion of inferior formats. Indeed, one of the original reasons for developing this free software was to help force convergence on common, interoperable format standards for JPEG files. Don't use an incompatible file format! (In any case, our decoder will remain capable of reading existing JPEG image files indefinitely.) The ISO committee pretends to be "responsible for the popular JPEG" in their public reports which is not true because they don't respond to actual requirements for the maintenance of the original JPEG specification. Furthermore, the ISO committee pretends to "ensure interoperability" with their standards which is not true because their "standards" support only application-specific and proprietary use cases and contain mathematically incorrect code. There are currently different distributions in circulation containing the name "libjpeg" which is misleading because they don't have the features and are incompatible with formats supported by actual IJG libjpeg distributions. One of those fakes is released by members of the ISO committee and just uses the name of libjpeg for misdirection of people, similar to the abuse of the name JPEG as described above, while having nothing in common with actual IJG libjpeg distributions and containing mathematically incorrect code. The other one claims to be a "derivative" or "fork" of the original libjpeg, but violates the license conditions as described under LEGAL ISSUES above and violates basic C programming properties. We have no sympathy for the release of misleading, incorrect and illegal distributions derived from obsolete code bases. Don't use an obsolete code base! According to the UCC (Uniform Commercial Code) law, IJG has the lawful and legal right to foreclose on certain standardization bodies and other institutions or corporations that knowingly perform substantial and systematic deceptive acts and practices, fraud, theft, and damaging of the value of the people of this planet without their knowing, willing and intentional consent. The titles, ownership, and rights of these institutions and all their assets are now duly secured and held in trust for the free people of this planet. People of the planet, on every country, may have a financial interest in the assets of these former principals, agents, and beneficiaries of the foreclosed institutions and corporations. IJG asserts what is: that each man, woman, and child has unalienable value and rights granted and deposited in them by the Creator and not any one of the people is subordinate to any artificial principality, corporate fiction or the special interest of another without their appropriate knowing, willing and intentional consent made by contract or accommodation agreement. IJG expresses that which already was. The people have already determined and demanded that public administration entities, national governments, and their supporting judicial systems must be fully transparent, accountable, and liable. IJG has secured the value for all concerned free people of the planet. A partial list of foreclosed institutions and corporations ("Hall of Shame") is currently prepared and will be published later. TO DO ===== Version 9 is the second release of a new generation JPEG standard to overcome the limitations of the original JPEG specification, and is the first true source reference JPEG codec. More features are being prepared for coming releases... Please send bug reports, offers of help, etc. to jpeg-info@ijg.org. fltk-1.4.3/jpeg/wizard.txt0000644000175000017500000002303715004135251015600 0ustar albrechtalbrechtAdvanced usage instructions for the Independent JPEG Group's JPEG software ========================================================================== This file describes cjpeg's "switches for wizards". The "wizard" switches are intended for experimentation with JPEG by persons who are reasonably knowledgeable about the JPEG standard. If you don't know what you are doing, DON'T USE THESE SWITCHES. You'll likely produce files with worse image quality and/or poorer compression than you'd get from the default settings. Furthermore, these switches must be used with caution when making files intended for general use, because not all JPEG decoders will support unusual JPEG parameter settings. Quantization Table Adjustment ----------------------------- Ordinarily, cjpeg starts with a default set of tables (the same ones given as examples in the JPEG standard) and scales them up or down according to the -quality setting. The details of the scaling algorithm can be found in jcparam.c. At very low quality settings, some quantization table entries can get scaled up to values exceeding 255. Although 2-byte quantization values are supported by the IJG software, this feature is not in baseline JPEG and is not supported by all implementations. If you need to ensure wide compatibility of low-quality files, you can constrain the scaled quantization values to no more than 255 by giving the -baseline switch. Note that use of -baseline will result in poorer quality for the same file size, since more bits than necessary are expended on higher AC coefficients. You can substitute a different set of quantization values by using the -qtables switch: -qtables file Use the quantization tables given in the named file. The specified file should be a text file containing decimal quantization values. The file should contain one to four tables, each of 64 elements. The tables are implicitly numbered 0,1,etc. in order of appearance. Table entries appear in normal array order (NOT in the zigzag order in which they will be stored in the JPEG file). Quantization table files are free format, in that arbitrary whitespace can appear between numbers. Also, comments can be included: a comment starts with '#' and extends to the end of the line. Here is an example file that duplicates the default quantization tables: # Quantization tables given in JPEG spec, section K.1 # This is table 0 (the luminance table): 16 11 10 16 24 40 51 61 12 12 14 19 26 58 60 55 14 13 16 24 40 57 69 56 14 17 22 29 51 87 80 62 18 22 37 56 68 109 103 77 24 35 55 64 81 104 113 92 49 64 78 87 103 121 120 101 72 92 95 98 112 100 103 99 # This is table 1 (the chrominance table): 17 18 24 47 99 99 99 99 18 21 26 66 99 99 99 99 24 26 56 99 99 99 99 99 47 66 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 If the -qtables switch is used without -quality, then the specified tables are used exactly as-is. If both -qtables and -quality are used, then the tables taken from the file are scaled in the same fashion that the default tables would be scaled for that quality setting. If -baseline appears, then the quantization values are constrained to the range 1-255. By default, cjpeg will use quantization table 0 for luminance components and table 1 for chrominance components. To override this choice, use the -qslots switch: -qslots N[,...] Select which quantization table to use for each color component. The -qslots switch specifies a quantization table number for each color component, in the order in which the components appear in the JPEG SOF marker. For example, to create a separate table for each of Y,Cb,Cr, you could provide a -qtables file that defines three quantization tables and say "-qslots 0,1,2". If -qslots gives fewer table numbers than there are color components, then the last table number is repeated as necessary. Sampling Factor Adjustment -------------------------- By default, cjpeg uses 2:1 horizontal and vertical downsampling when compressing YCbCr data, and no downsampling for all other color spaces. You can override this default with the -sample switch: -sample HxV[,...] Set JPEG sampling factors for each color component. The -sample switch specifies the JPEG sampling factors for each color component, in the order in which they appear in the JPEG SOF marker. If you specify fewer HxV pairs than there are components, the remaining components are set to 1x1 sampling. For example, the default YCbCr setting is equivalent to "-sample 2x2,1x1,1x1", which can be abbreviated to "-sample 2x2". There are still some JPEG decoders in existence that support only 2x1 sampling (also called 4:2:2 sampling). Compatibility with such decoders can be achieved by specifying "-sample 2x1". This is not recommended unless really necessary, since it increases file size and encoding/decoding time with very little quality gain. Multiple Scan / Progression Control ----------------------------------- By default, cjpeg emits a single-scan sequential JPEG file. The -progressive switch generates a progressive JPEG file using a default series of progression parameters. You can create multiple-scan sequential JPEG files or progressive JPEG files with custom progression parameters by using the -scans switch: -scans file Use the scan sequence given in the named file. The specified file should be a text file containing a "scan script". The script specifies the contents and ordering of the scans to be emitted. Each entry in the script defines one scan. A scan definition specifies the components to be included in the scan, and for progressive JPEG it also specifies the progression parameters Ss,Se,Ah,Al for the scan. Scan definitions are separated by semicolons (';'). A semicolon after the last scan definition is optional. Each scan definition contains one to four component indexes, optionally followed by a colon (':') and the four progressive-JPEG parameters. The component indexes denote which color component(s) are to be transmitted in the scan. Components are numbered in the order in which they appear in the JPEG SOF marker, with the first component being numbered 0. (Note that these indexes are not the "component ID" codes assigned to the components, just positional indexes.) The progression parameters for each scan are: Ss Zigzag index of first coefficient included in scan Se Zigzag index of last coefficient included in scan Ah Zero for first scan of a coefficient, else Al of prior scan Al Successive approximation low bit position for scan If the progression parameters are omitted, the values 0,63,0,0 are used, producing a sequential JPEG file. cjpeg automatically determines whether the script represents a progressive or sequential file, by observing whether Ss and Se values other than 0 and 63 appear. (The -progressive switch is not needed to specify this; in fact, it is ignored when -scans appears.) The scan script must meet the JPEG restrictions on progression sequences. (cjpeg checks that the spec's requirements are obeyed.) Scan script files are free format, in that arbitrary whitespace can appear between numbers and around punctuation. Also, comments can be included: a comment starts with '#' and extends to the end of the line. For additional legibility, commas or dashes can be placed between values. (Actually, any single punctuation character other than ':' or ';' can be inserted.) For example, the following two scan definitions are equivalent: 0 1 2: 0 63 0 0; 0,1,2 : 0-63, 0,0 ; Here is an example of a scan script that generates a partially interleaved sequential JPEG file: 0; # Y only in first scan 1 2; # Cb and Cr in second scan Here is an example of a progressive scan script using only spectral selection (no successive approximation): # Interleaved DC scan for Y,Cb,Cr: 0,1,2: 0-0, 0, 0 ; # AC scans: 0: 1-2, 0, 0 ; # First two Y AC coefficients 0: 3-5, 0, 0 ; # Three more 1: 1-63, 0, 0 ; # All AC coefficients for Cb 2: 1-63, 0, 0 ; # All AC coefficients for Cr 0: 6-9, 0, 0 ; # More Y coefficients 0: 10-63, 0, 0 ; # Remaining Y coefficients Here is an example of a successive-approximation script. This is equivalent to the default script used by "cjpeg -progressive" for YCbCr images: # Initial DC scan for Y,Cb,Cr (lowest bit not sent) 0,1,2: 0-0, 0, 1 ; # First AC scan: send first 5 Y AC coefficients, minus 2 lowest bits: 0: 1-5, 0, 2 ; # Send all Cr,Cb AC coefficients, minus lowest bit: # (chroma data is usually too small to be worth subdividing further; # but note we send Cr first since eye is least sensitive to Cb) 2: 1-63, 0, 1 ; 1: 1-63, 0, 1 ; # Send remaining Y AC coefficients, minus 2 lowest bits: 0: 6-63, 0, 2 ; # Send next-to-lowest bit of all Y AC coefficients: 0: 1-63, 2, 1 ; # At this point we've sent all but the lowest bit of all coefficients. # Send lowest bit of DC coefficients 0,1,2: 0-0, 1, 0 ; # Send lowest bit of AC coefficients 2: 1-63, 1, 0 ; 1: 1-63, 1, 0 ; # Y AC lowest bit scan is last; it's usually the largest scan 0: 1-63, 1, 0 ; It may be worth pointing out that this script is tuned for quality settings of around 50 to 75. For lower quality settings, you'd probably want to use a script with fewer stages of successive approximation (otherwise the initial scans will be really bad). For higher quality settings, you might want to use more stages of successive approximation (so that the initial scans are not too large). fltk-1.4.3/jpeg/jpeglib.h0000644000175000017500000014040015004135251015316 0ustar albrechtalbrecht/* * jpeglib.h * * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2002-2022 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file defines the application interface for the JPEG library. * Most applications using the library need only include this file, * and perhaps jerror.h if they want to know the exact error codes. */ #ifndef JPEGLIB_H #define JPEGLIB_H /* * First we include the configuration files that record how this * installation of the JPEG library is set up. jconfig.h can be * generated automatically for many systems. jmorecfg.h contains * manual configuration options that most people need not worry about. */ #ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ #include "jconfig.h" /* widely used configuration options */ #endif #include "jmorecfg.h" /* seldom changed options */ #ifdef __cplusplus #ifndef DONT_USE_EXTERN_C extern "C" { #endif #endif /* Version IDs for the JPEG library. * Might be useful for tests like "#if JPEG_LIB_VERSION >= 90". */ #define JPEG_LIB_VERSION 90 /* Compatibility version 9.0 */ #define JPEG_LIB_VERSION_MAJOR 9 #define JPEG_LIB_VERSION_MINOR 6 /* Various constants determining the sizes of things. * All of these are specified by the JPEG standard, * so don't change them if you want to be compatible. */ #define DCTSIZE 8 /* The basic DCT block is 8x8 coefficients */ #define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ #define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ #define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ #define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ #define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ #define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ /* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU * to handle it. We even let you do this from the jconfig.h file. However, * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe * sometimes emits noncompliant files doesn't mean you should too. */ #define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ #ifndef D_MAX_BLOCKS_IN_MCU #define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ #endif /* Data structures for images (arrays of samples and of DCT coefficients). * On 80x86 machines, the image arrays are too big for near pointers, * but the pointer arrays can fit in near memory. */ typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ /* Types for JPEG compression parameters and working tables. */ /* DCT coefficient quantization tables. */ typedef struct { /* This array gives the coefficient quantizers in natural array order * (not the zigzag order in which they are stored in a JPEG DQT marker). * CAUTION: IJG versions prior to v6a kept this array in zigzag order. */ UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ /* This field is used only during compression. It's initialized FALSE when * the table is created, and set TRUE when it's been output to the file. * You could suppress output of a table by setting this to TRUE. * (See jpeg_suppress_tables for an example.) */ boolean sent_table; /* TRUE when table has been output */ } JQUANT_TBL; /* Huffman coding tables. */ typedef struct { /* These two fields directly represent the contents of a JPEG DHT marker */ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ /* length k bits; bits[0] is unused */ UINT8 huffval[256]; /* The symbols, in order of incr code length */ /* This field is used only during compression. It's initialized FALSE when * the table is created, and set TRUE when it's been output to the file. * You could suppress output of a table by setting this to TRUE. * (See jpeg_suppress_tables for an example.) */ boolean sent_table; /* TRUE when table has been output */ } JHUFF_TBL; /* Basic info about one component (color channel). */ typedef struct { /* These values are fixed over the whole image. */ /* For compression, they must be supplied by parameter setup; */ /* for decompression, they are read from the SOF marker. */ int component_id; /* identifier for this component (0..255) */ int component_index; /* its index in SOF or cinfo->comp_info[] */ int h_samp_factor; /* horizontal sampling factor (1..4) */ int v_samp_factor; /* vertical sampling factor (1..4) */ int quant_tbl_no; /* quantization table selector (0..3) */ /* These values may vary between scans. */ /* For compression, they must be supplied by parameter setup; */ /* for decompression, they are read from the SOS marker. */ /* The decompressor output side may not use these variables. */ int dc_tbl_no; /* DC entropy table selector (0..3) */ int ac_tbl_no; /* AC entropy table selector (0..3) */ /* Remaining fields should be treated as private by applications. */ /* These values are computed during compression or decompression startup: */ /* Component's size in DCT blocks. * Any dummy blocks added to complete an MCU are not counted; therefore * these values do not depend on whether a scan is interleaved or not. */ JDIMENSION width_in_blocks; JDIMENSION height_in_blocks; /* Size of a DCT block in samples, * reflecting any scaling we choose to apply during the DCT step. * Values from 1 to 16 are supported. * Note that different components may receive different DCT scalings. */ int DCT_h_scaled_size; int DCT_v_scaled_size; /* The downsampled dimensions are the component's actual, unpadded number * of samples at the main buffer (preprocessing/compression interface); * DCT scaling is included, so * downsampled_width = * ceil(image_width * Hi/Hmax * DCT_h_scaled_size/block_size) * and similarly for height. */ JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_height; /* actual height in samples */ /* For decompression, in cases where some of the components will be * ignored (eg grayscale output from YCbCr image), we can skip most * computations for the unused components. * For compression, some of the components will need further quantization * scale by factor of 2 after DCT (eg BG_YCC output from normal RGB input). * The field is first set TRUE for decompression, FALSE for compression * in initial_setup, and then adapted in color conversion setup. */ boolean component_needed; /* These values are computed before starting a scan of the component. */ /* The decompressor output side may not use these variables. */ int MCU_width; /* number of blocks per MCU, horizontally */ int MCU_height; /* number of blocks per MCU, vertically */ int MCU_blocks; /* MCU_width * MCU_height */ int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ int last_col_width; /* # of non-dummy blocks across in last MCU */ int last_row_height; /* # of non-dummy blocks down in last MCU */ /* Saved quantization table for component; NULL if none yet saved. * See jdinput.c comments about the need for this information. * This field is currently used only for decompression. */ JQUANT_TBL * quant_table; /* Private per-component storage for DCT or IDCT subsystem. */ void * dct_table; } jpeg_component_info; /* The script for encoding a multiple-scan file is an array of these: */ typedef struct { int comps_in_scan; /* number of components encoded in this scan */ int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ int Ss, Se; /* progressive JPEG spectral selection parms */ int Ah, Al; /* progressive JPEG successive approx. parms */ } jpeg_scan_info; /* The decompressor can save APPn and COM markers in a list of these: */ typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; struct jpeg_marker_struct { jpeg_saved_marker_ptr next; /* next in list, or NULL */ UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ unsigned int original_length; /* # bytes of data in the file */ unsigned int data_length; /* # bytes of data saved at data[] */ JOCTET FAR * data; /* the data contained in the marker */ /* the marker length word is not counted in data_length or original_length */ }; /* Known color spaces. */ typedef enum { JCS_UNKNOWN, /* error/unspecified */ JCS_GRAYSCALE, /* monochrome */ JCS_RGB, /* red/green/blue, standard RGB (sRGB) */ JCS_YCbCr, /* Y/Cb/Cr (also known as YUV), standard YCC */ JCS_CMYK, /* C/M/Y/K */ JCS_YCCK, /* Y/Cb/Cr/K */ JCS_BG_RGB, /* big gamut red/green/blue, bg-sRGB */ JCS_BG_YCC /* big gamut Y/Cb/Cr, bg-sYCC */ } J_COLOR_SPACE; /* Supported color transforms. */ typedef enum { JCT_NONE = 0, JCT_SUBTRACT_GREEN = 1 } J_COLOR_TRANSFORM; /* DCT/IDCT algorithm options. */ typedef enum { JDCT_ISLOW, /* slow but accurate integer algorithm */ JDCT_IFAST, /* faster, less accurate integer method */ JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ } J_DCT_METHOD; #ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ #define JDCT_DEFAULT JDCT_ISLOW #endif #ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ #define JDCT_FASTEST JDCT_IFAST #endif /* Dithering options for decompression. */ typedef enum { JDITHER_NONE, /* no dithering */ JDITHER_ORDERED, /* simple ordered dither */ JDITHER_FS /* Floyd-Steinberg error diffusion dither */ } J_DITHER_MODE; /* Common fields between JPEG compression and decompression master structs. */ #define jpeg_common_fields \ struct jpeg_error_mgr * err; /* Error handler module */\ struct jpeg_memory_mgr * mem; /* Memory manager module */\ struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ void * client_data; /* Available for use by application */\ boolean is_decompressor; /* So common code can tell which is which */\ int global_state /* For checking call sequence validity */ /* Routines that are to be used by both halves of the library are declared * to receive a pointer to this structure. There are no actual instances of * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. */ struct jpeg_common_struct { jpeg_common_fields; /* Fields common to both master struct types */ /* Additional fields follow in an actual jpeg_compress_struct or * jpeg_decompress_struct. All three structs must agree on these * initial fields! (This would be a lot cleaner in C++.) */ }; typedef struct jpeg_common_struct * j_common_ptr; typedef struct jpeg_compress_struct * j_compress_ptr; typedef struct jpeg_decompress_struct * j_decompress_ptr; /* Master record for a compression instance */ struct jpeg_compress_struct { jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ /* Destination for compressed data */ struct jpeg_destination_mgr * dest; /* Description of source image --- these fields must be filled in by * outer application before starting compression. in_color_space must * be correct before you can even call jpeg_set_defaults(). */ JDIMENSION image_width; /* input image width */ JDIMENSION image_height; /* input image height */ int input_components; /* # of color components in input image */ J_COLOR_SPACE in_color_space; /* colorspace of input image */ double input_gamma; /* image gamma of input image */ /* Compression parameters --- these fields must be set before calling * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to * initialize everything to reasonable defaults, then changing anything * the application specifically wants to change. That way you won't get * burnt when new parameters are added. Also note that there are several * helper routines to simplify changing parameters. */ unsigned int scale_num, scale_denom; /* fraction by which to scale image */ JDIMENSION jpeg_width; /* scaled JPEG image width */ JDIMENSION jpeg_height; /* scaled JPEG image height */ /* Dimensions of actual JPEG image that will be written to file, * derived from input dimensions by scaling factors above. * These fields are computed by jpeg_start_compress(). * You can also use jpeg_calc_jpeg_dimensions() to determine these values * in advance of calling jpeg_start_compress(). */ int data_precision; /* bits of precision in image data */ int num_components; /* # of color components in JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; int q_scale_factor[NUM_QUANT_TBLS]; /* ptrs to coefficient quantization tables, or NULL if not defined, * and corresponding scale factors (percentage, initialized 100). */ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; /* ptrs to Huffman coding tables, or NULL if not defined */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ int num_scans; /* # of entries in scan_info array */ const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ /* The default value of scan_info is NULL, which causes a single-scan * sequential JPEG file to be emitted. To create a multi-scan file, * set num_scans and scan_info to point to an array of scan definitions. */ boolean raw_data_in; /* TRUE=caller supplies downsampled data */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ int smoothing_factor; /* 1..100, or 0 for no input smoothing */ J_DCT_METHOD dct_method; /* DCT algorithm selector */ /* The restart interval can be specified in absolute MCUs by setting * restart_interval, or in MCU rows by setting restart_in_rows * (in which case the correct restart_interval will be figured * for each scan). */ unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ int restart_in_rows; /* if > 0, MCU rows per restart interval */ /* Parameters controlling emission of special markers. */ boolean write_JFIF_header; /* should a JFIF marker be written? */ UINT8 JFIF_major_version; /* What to write for the JFIF version number */ UINT8 JFIF_minor_version; /* These three values are not used by the JPEG code, merely copied */ /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ /* ratio is defined by X_density/Y_density even when density_unit=0. */ UINT8 density_unit; /* JFIF code for pixel size units */ UINT16 X_density; /* Horizontal pixel density */ UINT16 Y_density; /* Vertical pixel density */ boolean write_Adobe_marker; /* should an Adobe marker be written? */ J_COLOR_TRANSFORM color_transform; /* Color transform identifier, writes LSE marker if nonzero */ /* State variable: index of next scanline to be written to * jpeg_write_scanlines(). Application may use this to control its * processing loop, e.g., "while (next_scanline < image_height)". */ JDIMENSION next_scanline; /* 0 .. image_height-1 */ /* Remaining fields are known throughout compressor, but generally * should not be touched by a surrounding application. */ /* * These fields are computed during compression startup */ boolean progressive_mode; /* TRUE if scan script uses progressive mode */ int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ /* The coefficient controller receives data in units of MCU rows as defined * for fully interleaved scans (whether the JPEG file is interleaved or not). * There are v_samp_factor * DCT_v_scaled_size sample rows of each component * in an "iMCU" (interleaved MCU) row. */ /* * These fields are valid during any one scan. * They describe the components and MCUs actually appearing in the scan. */ int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ int blocks_in_MCU; /* # of DCT blocks per MCU */ int MCU_membership[C_MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ /* i'th block in an MCU */ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ int block_size; /* the basic DCT block size: 1..16 */ const int * natural_order; /* natural-order position array */ int lim_Se; /* min( Se, DCTSIZE2-1 ) */ /* * Links to compression subobjects (methods and private variables of modules) */ struct jpeg_comp_master * master; struct jpeg_c_main_controller * main; struct jpeg_c_prep_controller * prep; struct jpeg_c_coef_controller * coef; struct jpeg_marker_writer * marker; struct jpeg_color_converter * cconvert; struct jpeg_downsampler * downsample; struct jpeg_forward_dct * fdct; struct jpeg_entropy_encoder * entropy; jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ int script_space_size; }; /* Master record for a decompression instance */ struct jpeg_decompress_struct { jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ /* Source of compressed data */ struct jpeg_source_mgr * src; /* Basic description of image --- filled in by jpeg_read_header(). */ /* Application may inspect these values to decide how to process image. */ JDIMENSION image_width; /* nominal image width (from SOF marker) */ JDIMENSION image_height; /* nominal image height */ int num_components; /* # of color components in JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ /* Decompression processing parameters --- these fields must be set before * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes * them to default values. */ J_COLOR_SPACE out_color_space; /* colorspace for output */ unsigned int scale_num, scale_denom; /* fraction by which to scale image */ double output_gamma; /* image gamma wanted in output */ boolean buffered_image; /* TRUE=multiple output passes */ boolean raw_data_out; /* TRUE=downsampled data wanted */ J_DCT_METHOD dct_method; /* IDCT algorithm selector */ boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ boolean quantize_colors; /* TRUE=colormapped output wanted */ /* the following are ignored if not quantize_colors: */ J_DITHER_MODE dither_mode; /* type of color dithering to use */ boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ int desired_number_of_colors; /* max # colors to use in created colormap */ /* these are significant only in buffered-image mode: */ boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ boolean enable_external_quant;/* enable future use of external colormap */ boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ /* Description of actual output image that will be returned to application. * These fields are computed by jpeg_start_decompress(). * You can also use jpeg_calc_output_dimensions() to determine these values * in advance of calling jpeg_start_decompress(). */ JDIMENSION output_width; /* scaled image width */ JDIMENSION output_height; /* scaled image height */ int out_color_components; /* # of color components in out_color_space */ int output_components; /* # of color components returned */ /* output_components is 1 (a colormap index) when quantizing colors; * otherwise it equals out_color_components. */ int rec_outbuf_height; /* min recommended height of scanline buffer */ /* If the buffer passed to jpeg_read_scanlines() is less than this many rows * high, space and time will be wasted due to unnecessary data copying. * Usually rec_outbuf_height will be 1 or 2, at most 4. */ /* When quantizing colors, the output colormap is described by these fields. * The application can supply a colormap by setting colormap non-NULL before * calling jpeg_start_decompress; otherwise a colormap is created during * jpeg_start_decompress or jpeg_start_output. * The map has out_color_components rows and actual_number_of_colors columns. */ int actual_number_of_colors; /* number of entries in use */ JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ /* State variables: these variables indicate the progress of decompression. * The application may examine these but must not modify them. */ /* Row index of next scanline to be read from jpeg_read_scanlines(). * Application may use this to control its processing loop, e.g., * "while (output_scanline < output_height)". */ JDIMENSION output_scanline; /* 0 .. output_height-1 */ /* Current input scan number and number of iMCU rows completed in scan. * These indicate the progress of the decompressor input side. */ int input_scan_number; /* Number of SOS markers seen so far */ JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ /* The "output scan number" is the notional scan being displayed by the * output side. The decompressor will not allow output scan/row number * to get ahead of input scan/row, but it can fall arbitrarily far behind. */ int output_scan_number; /* Nominal scan number being displayed */ JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ /* Current progression status. coef_bits[c][i] indicates the precision * with which component c's DCT coefficient i (in zigzag order) is known. * It is -1 when no data has yet been received, otherwise it is the point * transform (shift) value for the most recent scan of the coefficient * (thus, 0 at completion of the progression). * This pointer is NULL when reading a non-progressive file. */ int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ /* Internal JPEG parameters --- the application usually need not look at * these fields. Note that the decompressor output side may not use * any parameters that can change between scans. */ /* Quantization and Huffman tables are carried forward across input * datastreams when processing abbreviated JPEG datastreams. */ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; /* ptrs to coefficient quantization tables, or NULL if not defined */ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; /* ptrs to Huffman coding tables, or NULL if not defined */ /* These parameters are never carried across datastreams, since they * are given in SOF/SOS markers or defined to be reset by SOI. */ int data_precision; /* bits of precision in image data */ jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ /* These fields record data obtained from optional markers recognized by * the JPEG library. */ boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ UINT8 JFIF_major_version; /* JFIF version number */ UINT8 JFIF_minor_version; UINT8 density_unit; /* JFIF code for pixel size units */ UINT16 X_density; /* Horizontal pixel density */ UINT16 Y_density; /* Vertical pixel density */ boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ UINT8 Adobe_transform; /* Color transform code from Adobe marker */ J_COLOR_TRANSFORM color_transform; /* Color transform identifier derived from LSE marker, otherwise zero */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ /* Aside from the specific data retained from APPn markers known to the * library, the uninterpreted contents of any or all APPn and COM markers * can be saved in a list for examination by the application. */ jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ /* Remaining fields are known throughout decompressor, but generally * should not be touched by a surrounding application. */ /* * These fields are computed during decompression startup */ int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ /* The coefficient controller's input and output progress is measured in * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows * in fully interleaved JPEG scans, but are used whether the scan is * interleaved or not. We define an iMCU row as v_samp_factor DCT block * rows of each component. Therefore, the IDCT output contains * v_samp_factor * DCT_v_scaled_size sample rows of a component per iMCU row. */ JSAMPLE * sample_range_limit; /* table for fast range-limiting */ /* * These fields are valid during any one scan. * They describe the components and MCUs actually appearing in the scan. * Note that the decompressor output side must not use these fields. */ int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ int blocks_in_MCU; /* # of DCT blocks per MCU */ int MCU_membership[D_MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ /* i'th block in an MCU */ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ /* These fields are derived from Se of first SOS marker. */ int block_size; /* the basic DCT block size: 1..16 */ const int * natural_order; /* natural-order position array for entropy decode */ int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ /* This field is shared between entropy decoder and marker parser. * It is either zero or the code of a JPEG marker that has been * read from the data source, but has not yet been processed. */ int unread_marker; /* * Links to decompression subobjects (methods, private variables of modules) */ struct jpeg_decomp_master * master; struct jpeg_d_main_controller * main; struct jpeg_d_coef_controller * coef; struct jpeg_d_post_controller * post; struct jpeg_input_controller * inputctl; struct jpeg_marker_reader * marker; struct jpeg_entropy_decoder * entropy; struct jpeg_inverse_dct * idct; struct jpeg_upsampler * upsample; struct jpeg_color_deconverter * cconvert; struct jpeg_color_quantizer * cquantize; }; /* "Object" declarations for JPEG modules that may be supplied or called * directly by the surrounding application. * As with all objects in the JPEG library, these structs only define the * publicly visible methods and state variables of a module. Additional * private fields may exist after the public ones. */ /* Error handler object */ struct jpeg_error_mgr { /* Error exit handler: does not return to caller */ JMETHOD(noreturn_t, error_exit, (j_common_ptr cinfo)); /* Conditionally emit a trace or warning message */ JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); /* Routine that actually outputs a trace or error message */ JMETHOD(void, output_message, (j_common_ptr cinfo)); /* Format a message string for the most recent JPEG error or message */ JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); #define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ /* Reset error state variables at start of a new image */ JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); /* The message ID code and any parameters are saved here. * A message can have one string parameter or up to 8 int parameters. */ int msg_code; #define JMSG_STR_PARM_MAX 80 union { int i[8]; char s[JMSG_STR_PARM_MAX]; } msg_parm; /* Standard state variables for error facility */ int trace_level; /* max msg_level that will be displayed */ /* For recoverable corrupt-data errors, we emit a warning message, * but keep going unless emit_message chooses to abort. emit_message * should count warnings in num_warnings. The surrounding application * can check for bad data by seeing if num_warnings is nonzero at the * end of processing. */ long num_warnings; /* number of corrupt-data warnings */ /* These fields point to the table(s) of error message strings. * An application can change the table pointer to switch to a different * message list (typically, to change the language in which errors are * reported). Some applications may wish to add additional error codes * that will be handled by the JPEG library error mechanism; the second * table pointer is used for this purpose. * * First table includes all errors generated by JPEG library itself. * Error code 0 is reserved for a "no such error string" message. */ const char * const * jpeg_message_table; /* Library errors */ int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ /* Second table can be added by application (see cjpeg/djpeg for example). * It contains strings numbered first_addon_message..last_addon_message. */ const char * const * addon_message_table; /* Non-library errors */ int first_addon_message; /* code for first string in addon table */ int last_addon_message; /* code for last string in addon table */ }; /* Progress monitor object */ struct jpeg_progress_mgr { JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); long pass_counter; /* work units completed in this pass */ long pass_limit; /* total number of work units in this pass */ int completed_passes; /* passes completed so far */ int total_passes; /* total number of passes expected */ }; /* Data destination object for compression */ struct jpeg_destination_mgr { JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ JMETHOD(void, init_destination, (j_compress_ptr cinfo)); JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); JMETHOD(void, term_destination, (j_compress_ptr cinfo)); }; /* Data source object for decompression */ struct jpeg_source_mgr { const JOCTET * next_input_byte; /* => next byte to read from buffer */ size_t bytes_in_buffer; /* # of bytes remaining in buffer */ JMETHOD(void, init_source, (j_decompress_ptr cinfo)); JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); JMETHOD(void, term_source, (j_decompress_ptr cinfo)); }; /* Memory manager object. * Allocates "small" objects (a few K total), "large" objects (tens of K), * and "really big" objects (virtual arrays with backing store if needed). * The memory manager does not allow individual objects to be freed; rather, * each created object is assigned to a pool, and whole pools can be freed * at once. This is faster and more convenient than remembering exactly what * to free, especially where malloc()/free() are not too speedy. * NB: alloc routines never return NULL. They exit to error_exit if not * successful. */ #define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ #define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ #define JPOOL_NUMPOOLS 2 typedef struct jvirt_sarray_control * jvirt_sarray_ptr; typedef struct jvirt_barray_control * jvirt_barray_ptr; struct jpeg_memory_mgr { /* Method pointers */ JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, size_t sizeofobject)); JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, size_t sizeofobject)); JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows)); JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow, JDIMENSION numrows)); JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, int pool_id, boolean pre_zero, JDIMENSION samplesperrow, JDIMENSION numrows, JDIMENSION maxaccess)); JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, int pool_id, boolean pre_zero, JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION maxaccess)); JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, jvirt_sarray_ptr ptr, JDIMENSION start_row, JDIMENSION num_rows, boolean writable)); JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, jvirt_barray_ptr ptr, JDIMENSION start_row, JDIMENSION num_rows, boolean writable)); JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); JMETHOD(void, self_destruct, (j_common_ptr cinfo)); /* Limit on memory allocation for this JPEG object. (Note that this is * merely advisory, not a guaranteed maximum; it only affects the space * used for virtual-array buffers.) May be changed by outer application * after creating the JPEG object. */ long max_memory_to_use; /* Maximum allocation request accepted by alloc_large. */ long max_alloc_chunk; }; /* Routine signature for application-supplied marker processing methods. * Need not pass marker code since it is stored in cinfo->unread_marker. */ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); /* Declarations for routines called by application. * The JPP macro hides prototype parameters from compilers that can't cope. * Note JPP requires double parentheses. */ #ifdef HAVE_PROTOTYPES #define JPP(arglist) arglist #else #define JPP(arglist) () #endif /* Short forms of external names for systems with brain-damaged linkers. * We shorten external names to be unique in the first six letters, which * is good enough for all known systems. * (If your compiler itself needs names to be unique in less than 15 * characters, you are out of luck. Get a better compiler.) */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_std_error jStdError #define jpeg_CreateCompress jCreaCompress #define jpeg_CreateDecompress jCreaDecompress #define jpeg_destroy_compress jDestCompress #define jpeg_destroy_decompress jDestDecompress #define jpeg_stdio_dest jStdDest #define jpeg_stdio_src jStdSrc #define jpeg_mem_dest jMemDest #define jpeg_mem_src jMemSrc #define jpeg_set_defaults jSetDefaults #define jpeg_set_colorspace jSetColorspace #define jpeg_default_colorspace jDefColorspace #define jpeg_set_quality jSetQuality #define jpeg_set_linear_quality jSetLQuality #define jpeg_default_qtables jDefQTables #define jpeg_add_quant_table jAddQuantTable #define jpeg_quality_scaling jQualityScaling #define jpeg_simple_progression jSimProgress #define jpeg_suppress_tables jSuppressTables #define jpeg_alloc_quant_table jAlcQTable #define jpeg_alloc_huff_table jAlcHTable #define jpeg_std_huff_table jStdHTable #define jpeg_start_compress jStrtCompress #define jpeg_write_scanlines jWrtScanlines #define jpeg_finish_compress jFinCompress #define jpeg_calc_jpeg_dimensions jCjpegDimensions #define jpeg_write_raw_data jWrtRawData #define jpeg_write_marker jWrtMarker #define jpeg_write_m_header jWrtMHeader #define jpeg_write_m_byte jWrtMByte #define jpeg_write_tables jWrtTables #define jpeg_read_header jReadHeader #define jpeg_start_decompress jStrtDecompress #define jpeg_read_scanlines jReadScanlines #define jpeg_finish_decompress jFinDecompress #define jpeg_read_raw_data jReadRawData #define jpeg_has_multiple_scans jHasMultScn #define jpeg_start_output jStrtOutput #define jpeg_finish_output jFinOutput #define jpeg_input_complete jInComplete #define jpeg_new_colormap jNewCMap #define jpeg_consume_input jConsumeInput #define jpeg_core_output_dimensions jCoreDimensions #define jpeg_calc_output_dimensions jCalcDimensions #define jpeg_save_markers jSaveMarkers #define jpeg_set_marker_processor jSetMarker #define jpeg_read_coefficients jReadCoefs #define jpeg_write_coefficients jWrtCoefs #define jpeg_copy_critical_parameters jCopyCrit #define jpeg_abort_compress jAbrtCompress #define jpeg_abort_decompress jAbrtDecompress #define jpeg_abort jAbort #define jpeg_destroy jDestroy #define jpeg_resync_to_restart jResyncRestart #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Default error-management setup */ EXTERN(struct jpeg_error_mgr *) jpeg_std_error JPP((struct jpeg_error_mgr * err)); /* Initialization of JPEG compression objects. * jpeg_create_compress() and jpeg_create_decompress() are the exported * names that applications should call. These expand to calls on * jpeg_CreateCompress and jpeg_CreateDecompress with additional information * passed for version mismatch checking. * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. */ #define jpeg_create_compress(cinfo) \ jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ (size_t) sizeof(struct jpeg_compress_struct)) #define jpeg_create_decompress(cinfo) \ jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ (size_t) sizeof(struct jpeg_decompress_struct)) EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, int version, size_t structsize)); EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, int version, size_t structsize)); /* Destruction of JPEG compression objects */ EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); /* Standard data source and destination managers: stdio streams. */ /* Caller is responsible for opening the file before and closing after. */ EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); /* Data source and destination managers: memory buffers. */ EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, unsigned char ** outbuffer, size_t * outsize)); EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, const unsigned char * inbuffer, size_t insize)); /* Default parameter setup for compression */ EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); /* Compression parameter setup aids */ EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, J_COLOR_SPACE colorspace)); EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, boolean force_baseline)); EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, int scale_factor, boolean force_baseline)); EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, boolean force_baseline)); EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline)); EXTERN(int) jpeg_quality_scaling JPP((int quality)); EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, boolean suppress)); EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); EXTERN(JHUFF_TBL *) jpeg_std_huff_table JPP((j_common_ptr cinfo, boolean isDC, int tblno)); /* Main entry points for compression */ EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, boolean write_all_tables)); EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines)); EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); /* Precalculate JPEG dimensions for current compression parameters. */ EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); /* Replaces jpeg_write_scanlines when writing raw downsampled data. */ EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, JSAMPIMAGE data, JDIMENSION num_lines)); /* Write a special marker. See libjpeg.txt concerning safe usage. */ EXTERN(void) jpeg_write_marker JPP((j_compress_ptr cinfo, int marker, const JOCTET * dataptr, unsigned int datalen)); /* Same, but piecemeal. */ EXTERN(void) jpeg_write_m_header JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); EXTERN(void) jpeg_write_m_byte JPP((j_compress_ptr cinfo, int val)); /* Alternate compression function: just write an abbreviated table file */ EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); /* Decompression startup: read start of JPEG datastream to see what's there */ EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, boolean require_image)); /* Return value is one of: */ #define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ #define JPEG_HEADER_OK 1 /* Found valid image datastream */ #define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ /* If you pass require_image = TRUE (normal case), you need not check for * a TABLES_ONLY return code; an abbreviated file will cause an error exit. * JPEG_SUSPENDED is only possible if you use a data source module that can * give a suspension return (the stdio source module doesn't). */ /* Main entry points for decompression */ EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines)); EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); /* Replaces jpeg_read_scanlines when reading raw downsampled data. */ EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, JSAMPIMAGE data, JDIMENSION max_lines)); /* Additional entry points for buffered-image mode. */ EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, int scan_number)); EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); /* Return value is one of: */ /* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ #define JPEG_REACHED_SOS 1 /* Reached start of new scan */ #define JPEG_REACHED_EOI 2 /* Reached end of image */ #define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ #define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ /* Precalculate output dimensions for current decompression parameters. */ EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); /* Control saving of COM and APPn markers into marker_list. */ EXTERN(void) jpeg_save_markers JPP((j_decompress_ptr cinfo, int marker_code, unsigned int length_limit)); /* Install a special processing method for COM or APPn markers. */ EXTERN(void) jpeg_set_marker_processor JPP((j_decompress_ptr cinfo, int marker_code, jpeg_marker_parser_method routine)); /* Read or write raw DCT coefficients --- useful for lossless transcoding. */ EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo)); /* If you choose to abort compression or decompression before completing * jpeg_finish_(de)compress, then you need to clean up to release memory, * temporary files, etc. You can just call jpeg_destroy_(de)compress * if you're done with the JPEG object, but if you want to clean it up and * reuse it, call this: */ EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); /* Generic versions of jpeg_abort and jpeg_destroy that work on either * flavor of JPEG object. These may be more convenient in some places. */ EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); /* Default restart-marker-resync procedure for use by data source modules */ EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, int desired)); /* These marker codes are exported since applications and data source modules * are likely to want to use them. */ #define JPEG_RST0 0xD0 /* RST0 marker code */ #define JPEG_EOI 0xD9 /* EOI marker code */ #define JPEG_APP0 0xE0 /* APP0 marker code */ #define JPEG_COM 0xFE /* COM marker code */ /* If we have a brain-damaged compiler that emits warnings (or worse, errors) * for structure definitions that are never filled in, keep it quiet by * supplying dummy definitions for the various substructures. */ #ifdef INCOMPLETE_TYPES_BROKEN #ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ struct jvirt_sarray_control { long dummy; }; struct jvirt_barray_control { long dummy; }; struct jpeg_comp_master { long dummy; }; struct jpeg_c_main_controller { long dummy; }; struct jpeg_c_prep_controller { long dummy; }; struct jpeg_c_coef_controller { long dummy; }; struct jpeg_marker_writer { long dummy; }; struct jpeg_color_converter { long dummy; }; struct jpeg_downsampler { long dummy; }; struct jpeg_forward_dct { long dummy; }; struct jpeg_entropy_encoder { long dummy; }; struct jpeg_decomp_master { long dummy; }; struct jpeg_d_main_controller { long dummy; }; struct jpeg_d_coef_controller { long dummy; }; struct jpeg_d_post_controller { long dummy; }; struct jpeg_input_controller { long dummy; }; struct jpeg_marker_reader { long dummy; }; struct jpeg_entropy_decoder { long dummy; }; struct jpeg_inverse_dct { long dummy; }; struct jpeg_upsampler { long dummy; }; struct jpeg_color_deconverter { long dummy; }; struct jpeg_color_quantizer { long dummy; }; #endif /* JPEG_INTERNALS */ #endif /* INCOMPLETE_TYPES_BROKEN */ /* * The JPEG library modules define JPEG_INTERNALS before including this file. * The internal structure declarations are read only when that is true. * Applications using the library should not include jpegint.h, but may wish * to include jerror.h. */ #ifdef JPEG_INTERNALS #include "jpegint.h" /* fetch private declarations */ #include "jerror.h" /* fetch error codes too */ #endif #ifdef __cplusplus #ifndef DONT_USE_EXTERN_C } #endif #endif #endif /* JPEGLIB_H */ fltk-1.4.3/jpeg/jdarith.c0000644000175000017500000005732515004135251015337 0ustar albrechtalbrecht/* * jdarith.c * * Developed 1997-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains portable arithmetic entropy decoding routines for JPEG * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81). * * Both sequential and progressive modes are supported in this single module. * * Suspension is not currently supported in this module. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Expanded entropy decoder object for arithmetic decoding. */ typedef struct { struct jpeg_entropy_decoder pub; /* public fields */ INT32 c; /* C register, base of coding interval + input bit buffer */ INT32 a; /* A register, normalized size of coding interval */ int ct; /* bit shift counter, # of bits left in bit buffer part of C */ /* init: ct = -16 */ /* run: ct = 0..7 */ /* error: ct = -1 */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ /* Pointers to statistics areas (these workspaces have image lifespan) */ unsigned char * dc_stats[NUM_ARITH_TBLS]; unsigned char * ac_stats[NUM_ARITH_TBLS]; /* Statistics bin for coding with fixed probability 0.5 */ unsigned char fixed_bin[4]; } arith_entropy_decoder; typedef arith_entropy_decoder * arith_entropy_ptr; /* The following two definitions specify the allocation chunk size * for the statistics area. * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least * 49 statistics bins for DC, and 245 statistics bins for AC coding. * * We use a compact representation with 1 byte per statistics bin, * thus the numbers directly represent byte sizes. * This 1 byte per statistics bin contains the meaning of the MPS * (more probable symbol) in the highest bit (mask 0x80), and the * index into the probability estimation state machine table * in the lower bits (mask 0x7F). */ #define DC_STAT_BINS 64 #define AC_STAT_BINS 256 LOCAL(int) get_byte (j_decompress_ptr cinfo) /* Read next input byte; we do not support suspension in this module. */ { struct jpeg_source_mgr * src = cinfo->src; if (src->bytes_in_buffer == 0) if (! (*src->fill_input_buffer) (cinfo)) ERREXIT(cinfo, JERR_CANT_SUSPEND); src->bytes_in_buffer--; return GETJOCTET(*src->next_input_byte++); } /* * The core arithmetic decoding routine (common in JPEG and JBIG). * This needs to go as fast as possible. * Machine-dependent optimization facilities * are not utilized in this portable implementation. * However, this code should be fairly efficient and * may be a good base for further optimizations anyway. * * Return value is 0 or 1 (binary decision). * * Note: I've changed the handling of the code base & bit * buffer register C compared to other implementations * based on the standards layout & procedures. * While it also contains both the actual base of the * coding interval (16 bits) and the next-bits buffer, * the cut-point between these two parts is floating * (instead of fixed) with the bit shift counter CT. * Thus, we also need only one (variable instead of * fixed size) shift for the LPS/MPS decision, and * we can do away with any renormalization update * of C (except for new data insertion, of course). * * I've also introduced a new scheme for accessing * the probability estimation state machine table, * derived from Markus Kuhn's JBIG implementation. */ LOCAL(int) arith_decode (j_decompress_ptr cinfo, unsigned char *st) { register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; register unsigned char nl, nm; register INT32 qe, temp; register int sv, data; /* Renormalization & data input per section D.2.6 */ while (e->a < 0x8000L) { if (--e->ct < 0) { /* Need to fetch next data byte */ if (cinfo->unread_marker) data = 0; /* stuff zero data */ else { data = get_byte(cinfo); /* read next input byte */ if (data == 0xFF) { /* zero stuff or marker code */ do data = get_byte(cinfo); while (data == 0xFF); /* swallow extra 0xFF bytes */ if (data == 0) data = 0xFF; /* discard stuffed zero byte */ else { /* Note: Different from the Huffman decoder, hitting * a marker while processing the compressed data * segment is legal in arithmetic coding. * The convention is to supply zero data * then until decoding is complete. */ cinfo->unread_marker = data; data = 0; } } } e->c = (e->c << 8) | data; /* insert data into C register */ if ((e->ct += 8) < 0) /* update bit shift counter */ /* Need more initial bytes */ if (++e->ct == 0) /* Got 2 initial bytes -> re-init A and exit loop */ e->a = 0x8000L; /* => e->a = 0x10000L after loop exit */ } e->a <<= 1; } /* Fetch values from our compact representation of Table D.3(D.2): * Qe values and probability estimation state machine */ sv = *st; qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ /* Decode & estimation procedures per sections D.2.4 & D.2.5 */ temp = e->a - qe; e->a = temp; temp <<= e->ct; if (e->c >= temp) { e->c -= temp; /* Conditional LPS (less probable symbol) exchange */ if (e->a < qe) { e->a = qe; *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ } else { e->a = qe; *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ sv ^= 0x80; /* Exchange LPS/MPS */ } } else if (e->a < 0x8000L) { /* Conditional MPS (more probable symbol) exchange */ if (e->a < qe) { *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ sv ^= 0x80; /* Exchange LPS/MPS */ } else { *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ } } return sv >> 7; } /* * Check for a restart marker & resynchronize decoder. */ LOCAL(void) process_restart (j_decompress_ptr cinfo) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; int ci; jpeg_component_info * compptr; /* Advance past the RSTn marker */ if (! (*cinfo->marker->read_restart_marker) (cinfo)) ERREXIT(cinfo, JERR_CANT_SUSPEND); /* Re-initialize statistics areas */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); /* Reset DC predictions to 0 */ entropy->last_dc_val[ci] = 0; entropy->dc_context[ci] = 0; } if ((! cinfo->progressive_mode && cinfo->lim_Se) || (cinfo->progressive_mode && cinfo->Ss)) { MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); } } /* Reset arithmetic decoding variables */ entropy->c = 0; entropy->a = 0; entropy->ct = -16; /* force reading 2 initial bytes to fill C */ /* Reset restart counter */ entropy->restarts_to_go = cinfo->restart_interval; } /* * Arithmetic MCU decoding. * Each of these routines decodes and returns one MCU's worth of * arithmetic-compressed coefficients. * The coefficients are reordered from zigzag order into natural array order, * but are not dequantized. * * The i'th block of the MCU is stored into the block pointed to by * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. */ /* * MCU decoding for DC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; JBLOCKROW block; unsigned char *st; int blkn, ci, tbl, sign; int v, m; /* Process restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) process_restart(cinfo); entropy->restarts_to_go--; } if (entropy->ct == -1) return TRUE; /* if error do nothing */ /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { block = MCU_data[blkn]; ci = cinfo->MCU_membership[blkn]; tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; /* Figure F.19: Decode_DC_DIFF */ if (arith_decode(cinfo, st) == 0) entropy->dc_context[ci] = 0; else { /* Figure F.21: Decoding nonzero value v */ /* Figure F.22: Decoding the sign of v */ sign = arith_decode(cinfo, st + 1); st += 2; st += sign; /* Figure F.23: Decoding the magnitude category of v */ if ((m = arith_decode(cinfo, st)) != 0) { st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ while (arith_decode(cinfo, st)) { if ((m <<= 1) == (int) 0x8000U) { WARNMS(cinfo, JWRN_ARITH_BAD_CODE); entropy->ct = -1; /* magnitude overflow */ return TRUE; } st += 1; } } /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) entropy->dc_context[ci] = 0; /* zero diff category */ else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ else entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ v = m; /* Figure F.24: Decoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) if (arith_decode(cinfo, st)) v |= m; v += 1; if (sign) v = -v; entropy->last_dc_val[ci] += v; } /* Scale and output the DC coefficient (assumes jpeg_natural_order[0]=0) */ (*block)[0] = (JCOEF) (entropy->last_dc_val[ci] << cinfo->Al); } return TRUE; } /* * MCU decoding for AC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; JBLOCKROW block; unsigned char *st; int tbl, sign, k; int v, m; const int * natural_order; /* Process restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) process_restart(cinfo); entropy->restarts_to_go--; } if (entropy->ct == -1) return TRUE; /* if error do nothing */ natural_order = cinfo->natural_order; /* There is always only one block per MCU */ block = MCU_data[0]; tbl = cinfo->cur_comp_info[0]->ac_tbl_no; /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ /* Figure F.20: Decode_AC_coefficients */ k = cinfo->Ss - 1; do { st = entropy->ac_stats[tbl] + 3 * k; if (arith_decode(cinfo, st)) break; /* EOB flag */ for (;;) { k++; if (arith_decode(cinfo, st + 1)) break; st += 3; if (k >= cinfo->Se) { WARNMS(cinfo, JWRN_ARITH_BAD_CODE); entropy->ct = -1; /* spectral overflow */ return TRUE; } } /* Figure F.21: Decoding nonzero value v */ /* Figure F.22: Decoding the sign of v */ sign = arith_decode(cinfo, entropy->fixed_bin); st += 2; /* Figure F.23: Decoding the magnitude category of v */ if ((m = arith_decode(cinfo, st)) != 0) { if (arith_decode(cinfo, st)) { m <<= 1; st = entropy->ac_stats[tbl] + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); while (arith_decode(cinfo, st)) { if ((m <<= 1) == (int) 0x8000U) { WARNMS(cinfo, JWRN_ARITH_BAD_CODE); entropy->ct = -1; /* magnitude overflow */ return TRUE; } st += 1; } } } v = m; /* Figure F.24: Decoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) if (arith_decode(cinfo, st)) v |= m; v += 1; if (sign) v = -v; /* Scale and output coefficient in natural (dezigzagged) order */ (*block)[natural_order[k]] = (JCOEF) (v << cinfo->Al); } while (k < cinfo->Se); return TRUE; } /* * MCU decoding for DC successive approximation refinement scan. * Note: we assume such scans can be multi-component, * although the spec is not very clear on the point. */ METHODDEF(boolean) decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; unsigned char *st; JCOEF p1; int blkn; /* Process restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) process_restart(cinfo); entropy->restarts_to_go--; } st = entropy->fixed_bin; /* use fixed probability estimation */ p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { /* Encoded data is simply the next bit of the two's-complement DC value */ if (arith_decode(cinfo, st)) MCU_data[blkn][0][0] |= p1; } return TRUE; } /* * MCU decoding for AC successive approximation refinement scan. */ METHODDEF(boolean) decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; JBLOCKROW block; JCOEFPTR thiscoef; unsigned char *st; int tbl, k, kex; JCOEF p1, m1; const int * natural_order; /* Process restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) process_restart(cinfo); entropy->restarts_to_go--; } if (entropy->ct == -1) return TRUE; /* if error do nothing */ natural_order = cinfo->natural_order; /* There is always only one block per MCU */ block = MCU_data[0]; tbl = cinfo->cur_comp_info[0]->ac_tbl_no; p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ m1 = -p1; /* -1 in the bit position being coded */ /* Establish EOBx (previous stage end-of-block) index */ kex = cinfo->Se; do { if ((*block)[natural_order[kex]]) break; } while (--kex); k = cinfo->Ss - 1; do { st = entropy->ac_stats[tbl] + 3 * k; if (k >= kex) if (arith_decode(cinfo, st)) break; /* EOB flag */ for (;;) { thiscoef = *block + natural_order[++k]; if (*thiscoef) { /* previously nonzero coef */ if (arith_decode(cinfo, st + 2)) { if (*thiscoef < 0) *thiscoef += m1; else *thiscoef += p1; } break; } if (arith_decode(cinfo, st + 1)) { /* newly nonzero coef */ if (arith_decode(cinfo, entropy->fixed_bin)) *thiscoef = m1; else *thiscoef = p1; break; } st += 3; if (k >= cinfo->Se) { WARNMS(cinfo, JWRN_ARITH_BAD_CODE); entropy->ct = -1; /* spectral overflow */ return TRUE; } } } while (k < cinfo->Se); return TRUE; } /* * Decode one MCU's worth of arithmetic-compressed coefficients. */ METHODDEF(boolean) decode_mcu (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; jpeg_component_info * compptr; JBLOCKROW block; unsigned char *st; int blkn, ci, tbl, sign, k; int v, m; const int * natural_order; /* Process restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) process_restart(cinfo); entropy->restarts_to_go--; } if (entropy->ct == -1) return TRUE; /* if error do nothing */ natural_order = cinfo->natural_order; /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { block = MCU_data[blkn]; ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ tbl = compptr->dc_tbl_no; /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; /* Figure F.19: Decode_DC_DIFF */ if (arith_decode(cinfo, st) == 0) entropy->dc_context[ci] = 0; else { /* Figure F.21: Decoding nonzero value v */ /* Figure F.22: Decoding the sign of v */ sign = arith_decode(cinfo, st + 1); st += 2; st += sign; /* Figure F.23: Decoding the magnitude category of v */ if ((m = arith_decode(cinfo, st)) != 0) { st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ while (arith_decode(cinfo, st)) { if ((m <<= 1) == (int) 0x8000U) { WARNMS(cinfo, JWRN_ARITH_BAD_CODE); entropy->ct = -1; /* magnitude overflow */ return TRUE; } st += 1; } } /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) entropy->dc_context[ci] = 0; /* zero diff category */ else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ else entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ v = m; /* Figure F.24: Decoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) if (arith_decode(cinfo, st)) v |= m; v += 1; if (sign) v = -v; entropy->last_dc_val[ci] += v; } (*block)[0] = (JCOEF) entropy->last_dc_val[ci]; /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ if (cinfo->lim_Se == 0) continue; tbl = compptr->ac_tbl_no; k = 0; /* Figure F.20: Decode_AC_coefficients */ do { st = entropy->ac_stats[tbl] + 3 * k; if (arith_decode(cinfo, st)) break; /* EOB flag */ for (;;) { k++; if (arith_decode(cinfo, st + 1)) break; st += 3; if (k >= cinfo->lim_Se) { WARNMS(cinfo, JWRN_ARITH_BAD_CODE); entropy->ct = -1; /* spectral overflow */ return TRUE; } } /* Figure F.21: Decoding nonzero value v */ /* Figure F.22: Decoding the sign of v */ sign = arith_decode(cinfo, entropy->fixed_bin); st += 2; /* Figure F.23: Decoding the magnitude category of v */ if ((m = arith_decode(cinfo, st)) != 0) { if (arith_decode(cinfo, st)) { m <<= 1; st = entropy->ac_stats[tbl] + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); while (arith_decode(cinfo, st)) { if ((m <<= 1) == (int) 0x8000U) { WARNMS(cinfo, JWRN_ARITH_BAD_CODE); entropy->ct = -1; /* magnitude overflow */ return TRUE; } st += 1; } } } v = m; /* Figure F.24: Decoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) if (arith_decode(cinfo, st)) v |= m; v += 1; if (sign) v = -v; (*block)[natural_order[k]] = (JCOEF) v; } while (k < cinfo->lim_Se); } return TRUE; } /* * Initialize for an arithmetic-compressed scan. */ METHODDEF(void) start_pass (j_decompress_ptr cinfo) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; int ci, tbl; jpeg_component_info * compptr; if (cinfo->progressive_mode) { /* Validate progressive scan parameters */ if (cinfo->Ss == 0) { if (cinfo->Se != 0) goto bad; } else { /* need not check Ss/Se < 0 since they came from unsigned bytes */ if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) goto bad; /* AC scans may have only one component */ if (cinfo->comps_in_scan != 1) goto bad; } if (cinfo->Ah != 0) { /* Successive approximation refinement scan: must have Al = Ah-1. */ if (cinfo->Ah-1 != cinfo->Al) goto bad; } if (cinfo->Al > 13) { /* need not check for < 0 */ bad: ERREXIT4(cinfo, JERR_BAD_PROGRESSION, cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); } /* Update progression status, and verify that scan order is legal. * Note that inter-scan inconsistencies are treated as warnings * not fatal errors ... not clear if this is right way to behave. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; if (cinfo->Ah != expected) WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); coef_bit_ptr[coefi] = cinfo->Al; } } /* Select MCU decoding routine */ if (cinfo->Ah == 0) { if (cinfo->Ss == 0) entropy->pub.decode_mcu = decode_mcu_DC_first; else entropy->pub.decode_mcu = decode_mcu_AC_first; } else { if (cinfo->Ss == 0) entropy->pub.decode_mcu = decode_mcu_DC_refine; else entropy->pub.decode_mcu = decode_mcu_AC_refine; } } else { /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. * This ought to be an error condition, but we make it a warning. */ if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || (cinfo->Se < DCTSIZE2 && cinfo->Se != cinfo->lim_Se)) WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); /* Select MCU decoding routine */ entropy->pub.decode_mcu = decode_mcu; } /* Allocate & initialize requested statistics areas */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { tbl = compptr->dc_tbl_no; if (tbl < 0 || tbl >= NUM_ARITH_TBLS) ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); if (entropy->dc_stats[tbl] == NULL) entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); /* Initialize DC predictions to 0 */ entropy->last_dc_val[ci] = 0; entropy->dc_context[ci] = 0; } if ((! cinfo->progressive_mode && cinfo->lim_Se) || (cinfo->progressive_mode && cinfo->Ss)) { tbl = compptr->ac_tbl_no; if (tbl < 0 || tbl >= NUM_ARITH_TBLS) ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); if (entropy->ac_stats[tbl] == NULL) entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); } } /* Initialize arithmetic decoding variables */ entropy->c = 0; entropy->a = 0; entropy->ct = -16; /* force reading 2 initial bytes to fill C */ /* Initialize restart counter */ entropy->restarts_to_go = cinfo->restart_interval; } /* * Finish up at the end of an arithmetic-compressed scan. */ METHODDEF(void) finish_pass (j_decompress_ptr cinfo) { /* no work necessary here */ } /* * Module initialization routine for arithmetic entropy decoding. */ GLOBAL(void) jinit_arith_decoder (j_decompress_ptr cinfo) { arith_entropy_ptr entropy; int i; entropy = (arith_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(arith_entropy_decoder)); cinfo->entropy = &entropy->pub; entropy->pub.start_pass = start_pass; entropy->pub.finish_pass = finish_pass; /* Mark tables unallocated */ for (i = 0; i < NUM_ARITH_TBLS; i++) { entropy->dc_stats[i] = NULL; entropy->ac_stats[i] = NULL; } /* Initialize index for fixed probability estimation */ entropy->fixed_bin[0] = 113; if (cinfo->progressive_mode) { /* Create progression status table */ int *coef_bit_ptr, ci; cinfo->coef_bits = (int (*)[DCTSIZE2]) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * DCTSIZE2 * SIZEOF(int)); coef_bit_ptr = & cinfo->coef_bits[0][0]; for (ci = 0; ci < cinfo->num_components; ci++) for (i = 0; i < DCTSIZE2; i++) *coef_bit_ptr++ = -1; } } fltk-1.4.3/jpeg/jdtrans.c0000644000175000017500000001167515004135251015355 0ustar albrechtalbrecht/* * jdtrans.c * * Copyright (C) 1995-1997, Thomas G. Lane. * Modified 2000-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains library routines for transcoding decompression, * that is, reading raw DCT coefficient arrays from an input JPEG file. * The routines in jdapimin.c will also be needed by a transcoder. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Forward declarations */ LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); /* * Read the coefficient arrays from a JPEG file. * jpeg_read_header must be completed before calling this. * * The entire image is read into a set of virtual coefficient-block arrays, * one per component. The return value is a pointer to the array of * virtual-array descriptors. These can be manipulated directly via the * JPEG memory manager, or handed off to jpeg_write_coefficients(). * To release the memory occupied by the virtual arrays, call * jpeg_finish_decompress() when done with the data. * * An alternative usage is to simply obtain access to the coefficient arrays * during a buffered-image-mode decompression operation. This is allowed * after any jpeg_finish_output() call. The arrays can be accessed until * jpeg_finish_decompress() is called. (Note that any call to the library * may reposition the arrays, so don't rely on access_virt_barray() results * to stay valid across library calls.) * * Returns NULL if suspended. This case need be checked only if * a suspending data source is used. */ GLOBAL(jvirt_barray_ptr *) jpeg_read_coefficients (j_decompress_ptr cinfo) { if (cinfo->global_state == DSTATE_READY) { /* First call: initialize active modules */ transdecode_master_selection(cinfo); cinfo->global_state = DSTATE_RDCOEFS; } if (cinfo->global_state == DSTATE_RDCOEFS) { /* Absorb whole file into the coef buffer */ for (;;) { int retcode; /* Call progress monitor hook if present */ if (cinfo->progress != NULL) (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); /* Absorb some more input */ retcode = (*cinfo->inputctl->consume_input) (cinfo); if (retcode == JPEG_SUSPENDED) return NULL; if (retcode == JPEG_REACHED_EOI) break; /* Advance progress counter if appropriate */ if (cinfo->progress != NULL && (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { /* startup underestimated number of scans; ratchet up one scan */ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; } } } /* Set state so that jpeg_finish_decompress does the right thing */ cinfo->global_state = DSTATE_STOPPING; } /* At this point we should be in state DSTATE_STOPPING if being used * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access * to the coefficients during a full buffered-image-mode decompression. */ if ((cinfo->global_state == DSTATE_STOPPING || cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { return cinfo->coef->coef_arrays; } /* Oops, improper usage */ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); return NULL; /* keep compiler happy */ } /* * Master selection of decompression modules for transcoding. * This substitutes for jdmaster.c's initialization of the full decompressor. */ LOCAL(void) transdecode_master_selection (j_decompress_ptr cinfo) { /* This is effectively a buffered-image operation. */ cinfo->buffered_image = TRUE; /* Compute output image dimensions and related values. */ jpeg_core_output_dimensions(cinfo); /* Entropy decoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) jinit_arith_decoder(cinfo); else { jinit_huff_decoder(cinfo); } /* Always get a full-image coefficient buffer. */ jinit_d_coef_controller(cinfo, TRUE); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); /* Initialize input side of decompressor to consume first scan. */ (*cinfo->inputctl->start_input_pass) (cinfo); /* Initialize progress monitoring. */ if (cinfo->progress != NULL) { int nscans; /* Estimate number of scans to set pass_limit. */ if (cinfo->progressive_mode) { /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ nscans = 2 + 3 * cinfo->num_components; } else if (cinfo->inputctl->has_multiple_scans) { /* For a nonprogressive multiscan file, estimate 1 scan per component. */ nscans = cinfo->num_components; } else { nscans = 1; } cinfo->progress->pass_counter = 0L; cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; cinfo->progress->completed_passes = 0; cinfo->progress->total_passes = 1; } } fltk-1.4.3/jpeg/jmemsys.h0000644000175000017500000002004615004135251015374 0ustar albrechtalbrecht/* * jmemsys.h * * Copyright (C) 1992-1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This include file defines the interface between the system-independent * and system-dependent portions of the JPEG memory manager. No other * modules need include it. (The system-independent portion is jmemmgr.c; * there are several different versions of the system-dependent portion.) * * This file works as-is for the system-dependent memory managers supplied * in the IJG distribution. You may need to modify it if you write a * custom memory manager. If system-dependent changes are needed in * this file, the best method is to #ifdef them based on a configuration * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR * and USE_MAC_MEMMGR. */ /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_get_small jGetSmall #define jpeg_free_small jFreeSmall #define jpeg_get_large jGetLarge #define jpeg_free_large jFreeLarge #define jpeg_mem_available jMemAvail #define jpeg_open_backing_store jOpenBackStore #define jpeg_mem_init jMemInit #define jpeg_mem_term jMemTerm #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* * These two functions are used to allocate and release small chunks of * memory. (Typically the total amount requested through jpeg_get_small is * no more than 20K or so; this will be requested in chunks of a few K each.) * Behavior should be the same as for the standard library functions malloc * and free; in particular, jpeg_get_small must return NULL on failure. * On most systems, these ARE malloc and free. jpeg_free_small is passed the * size of the object being freed, just in case it's needed. * On an 80x86 machine using small-data memory model, these manage near heap. */ EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, size_t sizeofobject)); /* * These two functions are used to allocate and release large chunks of * memory (up to the total free space designated by jpeg_mem_available). * The interface is the same as above, except that on an 80x86 machine, * far pointers are used. On most other machines these are identical to * the jpeg_get/free_small routines; but we keep them separate anyway, * in case a different allocation strategy is desirable for large chunks. */ EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, size_t sizeofobject)); EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, size_t sizeofobject)); /* * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may * be requested in a single call to jpeg_get_large (and jpeg_get_small for that * matter, but that case should never come into play). This macro is needed * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. * On those machines, we expect that jconfig.h will provide a proper value. * On machines with 32-bit flat address spaces, any large constant may be used. * * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type * size_t and will be a multiple of sizeof(align_type). */ #ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ #define MAX_ALLOC_CHUNK 1000000000L #endif /* * This routine computes the total space still available for allocation by * jpeg_get_large. If more space than this is needed, backing store will be * used. NOTE: any memory already allocated must not be counted. * * There is a minimum space requirement, corresponding to the minimum * feasible buffer sizes; jmemmgr.c will request that much space even if * jpeg_mem_available returns zero. The maximum space needed, enough to hold * all working storage in memory, is also passed in case it is useful. * Finally, the total space already allocated is passed. If no better * method is available, cinfo->mem->max_memory_to_use - already_allocated * is often a suitable calculation. * * It is OK for jpeg_mem_available to underestimate the space available * (that'll just lead to more backing-store access than is really necessary). * However, an overestimate will lead to failure. Hence it's wise to subtract * a slop factor from the true available space. 5% should be enough. * * On machines with lots of virtual memory, any large constant may be returned. * Conversely, zero may be returned to always use the minimum amount of memory. */ EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, long min_bytes_needed, long max_bytes_needed, long already_allocated)); /* * This structure holds whatever state is needed to access a single * backing-store object. The read/write/close method pointers are called * by jmemmgr.c to manipulate the backing-store object; all other fields * are private to the system-dependent backing store routines. */ #define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ #ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ typedef unsigned short XMSH; /* type of extended-memory handles */ typedef unsigned short EMSH; /* type of expanded-memory handles */ typedef union { short file_handle; /* DOS file handle if it's a temp file */ XMSH xms_handle; /* handle if it's a chunk of XMS */ EMSH ems_handle; /* handle if it's a chunk of EMS */ } handle_union; #endif /* USE_MSDOS_MEMMGR */ #ifdef USE_MAC_MEMMGR /* Mac-specific junk */ #include #endif /* USE_MAC_MEMMGR */ typedef struct backing_store_struct * backing_store_ptr; typedef struct backing_store_struct { /* Methods for reading/writing/closing this backing-store object */ JMETHOD(void, read_backing_store, (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)); JMETHOD(void, write_backing_store, (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)); JMETHOD(void, close_backing_store, (j_common_ptr cinfo, backing_store_ptr info)); /* Private fields for system-dependent backing-store management */ #ifdef USE_MSDOS_MEMMGR /* For the MS-DOS manager (jmemdos.c), we need: */ handle_union handle; /* reference to backing-store storage object */ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ #else #ifdef USE_MAC_MEMMGR /* For the Mac manager (jmemmac.c), we need: */ short temp_file; /* file reference number to temp file */ FSSpec tempSpec; /* the FSSpec for the temp file */ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ #else /* For a typical implementation with temp files, we need: */ FILE * temp_file; /* stdio reference to temp file */ char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ #endif #endif } backing_store_info; /* * Initial opening of a backing-store object. This must fill in the * read/write/close pointers in the object. The read/write routines * may take an error exit if the specified maximum file size is exceeded. * (If jpeg_mem_available always returns a large value, this routine can * just take an error exit.) */ EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed)); /* * These routines take care of any system-dependent initialization and * cleanup required. jpeg_mem_init will be called before anything is * allocated (and, therefore, nothing in cinfo is of use except the error * manager pointer). It should return a suitable default value for * max_memory_to_use; this may subsequently be overridden by the surrounding * application. (Note that max_memory_to_use is only important if * jpeg_mem_available chooses to consult it ... no one else will.) * jpeg_mem_term may assume that all requested memory has been freed and that * all opened backing-store objects have been closed. */ EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); fltk-1.4.3/jpeg/jccolor.c0000644000175000017500000004577615004135251015354 0ustar albrechtalbrecht/* * jccolor.c * * Copyright (C) 1991-1996, Thomas G. Lane. * Modified 2011-2023 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains input colorspace conversion routines. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private subobject */ typedef struct { struct jpeg_color_converter pub; /* public fields */ /* Private state for RGB->YCC conversion */ INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ } my_color_converter; typedef my_color_converter * my_cconvert_ptr; /**************** RGB -> YCbCr conversion: most common case **************/ /* * YCbCr is defined per Recommendation ITU-R BT.601-7 (03/2011), * previously known as Recommendation CCIR 601-1, except that Cb and Cr * are normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. * sRGB (standard RGB color space) is defined per IEC 61966-2-1:1999. * sYCC (standard luma-chroma-chroma color space with extended gamut) * is defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex F. * bg-sRGB and bg-sYCC (big gamut standard color spaces) * are defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex G. * Note that the derived conversion coefficients given in some of these * documents are imprecise. The general conversion equations are * Y = Kr * R + (1 - Kr - Kb) * G + Kb * B * Cb = (B - Y) / (1 - Kb) / K * Cr = (R - Y) / (1 - Kr) / K * With Kr = 0.299 and Kb = 0.114 (derived according to SMPTE RP 177-1993 * from the 1953 FCC NTSC primaries and CIE Illuminant C), K = 2 for sYCC, * the conversion equations to be implemented are therefore * Y = 0.299 * R + 0.587 * G + 0.114 * B * Cb = -0.168735892 * R - 0.331264108 * G + 0.5 * B + CENTERJSAMPLE * Cr = 0.5 * R - 0.418687589 * G - 0.081312411 * B + CENTERJSAMPLE * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) * were not represented exactly. Now we sacrifice exact representation of * maximum red and maximum blue in order to get exact grayscales. * * To avoid floating-point arithmetic, we represent the fractional constants * as integers scaled up by 2^16 (about 4 digits precision); we have to divide * the products by 2^16, with appropriate rounding, to get the correct answer. * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times R,G,B for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); * for 9-bit to 12-bit samples it is still acceptable. It's not very * reasonable for 16-bit samples, but if you want lossless storage * you shouldn't be changing colorspace anyway. * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included * in the tables to save adding them separately in the inner loop. */ #define SCALEBITS 16 /* speediest right-shift on some machines */ #define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L< Y section */ #define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ #define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ #define R_CB_OFF (3*(MAXJSAMPLE+1)) #define G_CB_OFF (4*(MAXJSAMPLE+1)) #define B_CB_OFF (5*(MAXJSAMPLE+1)) #define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ #define G_CR_OFF (6*(MAXJSAMPLE+1)) #define B_CR_OFF (7*(MAXJSAMPLE+1)) #define TABLE_SIZE (8*(MAXJSAMPLE+1)) /* * Initialize for RGB->YCC colorspace conversion. */ METHODDEF(void) rgb_ycc_start (j_compress_ptr cinfo) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; INT32 * rgb_ycc_tab; INT32 i; /* Allocate and fill in the conversion tables. */ cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, TABLE_SIZE * SIZEOF(INT32)); for (i = 0; i <= MAXJSAMPLE; i++) { rgb_ycc_tab[i+R_Y_OFF] = FIX(0.299) * i; rgb_ycc_tab[i+G_Y_OFF] = FIX(0.587) * i; rgb_ycc_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF; rgb_ycc_tab[i+R_CB_OFF] = (- FIX(0.168735892)) * i; rgb_ycc_tab[i+G_CB_OFF] = (- FIX(0.331264108)) * i; /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. * This ensures that the maximum output will round to MAXJSAMPLE * not MAXJSAMPLE+1, and thus that we don't have to range-limit. */ rgb_ycc_tab[i+B_CB_OFF] = (i << (SCALEBITS-1)) + CBCR_OFFSET + ONE_HALF-1; /* B=>Cb and R=>Cr tables are the same rgb_ycc_tab[i+R_CR_OFF] = (i << (SCALEBITS-1)) + CBCR_OFFSET + ONE_HALF-1; */ rgb_ycc_tab[i+G_CR_OFF] = (- FIX(0.418687589)) * i; rgb_ycc_tab[i+B_CR_OFF] = (- FIX(0.081312411)) * i; } } /* * Convert some rows of samples to the JPEG colorspace. * * Note that we change from the application's interleaved-pixel format * to our internal noninterleaved, one-plane-per-component format. The * input buffer is therefore three times as wide as the output buffer. * * A starting row offset is provided only for the output buffer. The * caller can easily adjust the passed input_buf value to accommodate * any row offset required on that side. */ METHODDEF(void) rgb_ycc_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int r, g, b; register INT32 * ctab = cconvert->rgb_ycc_tab; register JSAMPROW inptr; register JSAMPROW outptr0, outptr1, outptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr0 = output_buf[0][output_row]; outptr1 = output_buf[1][output_row]; outptr2 = output_buf[2][output_row]; output_row++; for (col = 0; col < num_cols; col++) { r = GETJSAMPLE(inptr[RGB_RED]); g = GETJSAMPLE(inptr[RGB_GREEN]); b = GETJSAMPLE(inptr[RGB_BLUE]); inptr += RGB_PIXELSIZE; /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ outptr0[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); /* Cb */ outptr1[col] = (JSAMPLE) ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) >> SCALEBITS); /* Cr */ outptr2[col] = (JSAMPLE) ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) >> SCALEBITS); } } } /**************** Cases other than RGB -> YCbCr **************/ /* * Convert some rows of samples to the JPEG colorspace. * This version handles RGB->grayscale conversion, * which is the same as the RGB->Y portion of RGB->YCbCr. * We assume rgb_ycc_start has been called (we only use the Y tables). */ METHODDEF(void) rgb_gray_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register INT32 y; register INT32 * ctab = cconvert->rgb_ycc_tab; register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr = output_buf[0][output_row++]; for (col = 0; col < num_cols; col++) { y = ctab[R_Y_OFF + GETJSAMPLE(inptr[RGB_RED])]; y += ctab[G_Y_OFF + GETJSAMPLE(inptr[RGB_GREEN])]; y += ctab[B_Y_OFF + GETJSAMPLE(inptr[RGB_BLUE])]; inptr += RGB_PIXELSIZE; outptr[col] = (JSAMPLE) (y >> SCALEBITS); } } } /* * Convert some rows of samples to the JPEG colorspace. * This version handles Adobe-style CMYK->YCCK conversion, * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the * same conversion as above, while passing K (black) unchanged. * We assume rgb_ycc_start has been called. */ METHODDEF(void) cmyk_ycck_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int r, g, b; register INT32 * ctab = cconvert->rgb_ycc_tab; register JSAMPROW inptr; register JSAMPROW outptr0, outptr1, outptr2, outptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr0 = output_buf[0][output_row]; outptr1 = output_buf[1][output_row]; outptr2 = output_buf[2][output_row]; outptr3 = output_buf[3][output_row]; output_row++; for (col = 0; col < num_cols; col++) { r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); /* K passes through as-is */ outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ inptr += 4; /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ outptr0[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); /* Cb */ outptr1[col] = (JSAMPLE) ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) >> SCALEBITS); /* Cr */ outptr2[col] = (JSAMPLE) ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) >> SCALEBITS); } } } /* * Convert some rows of samples to the JPEG colorspace. * [R,G,B] to [R-G,G,B-G] conversion with modulo calculation * (forward reversible color transform). * This can be seen as an adaption of the general RGB->YCbCr * conversion equation with Kr = Kb = 0, while replacing the * normalization by modulo calculation. */ METHODDEF(void) rgb_rgb1_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { register int r, g, b; register JSAMPROW inptr; register JSAMPROW outptr0, outptr1, outptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr0 = output_buf[0][output_row]; outptr1 = output_buf[1][output_row]; outptr2 = output_buf[2][output_row]; output_row++; for (col = 0; col < num_cols; col++) { r = GETJSAMPLE(inptr[RGB_RED]); g = GETJSAMPLE(inptr[RGB_GREEN]); b = GETJSAMPLE(inptr[RGB_BLUE]); inptr += RGB_PIXELSIZE; /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD * (modulo) operator is equivalent to the bitmask operator AND. */ outptr0[col] = (JSAMPLE) ((r - g + CENTERJSAMPLE) & MAXJSAMPLE); outptr1[col] = (JSAMPLE) g; outptr2[col] = (JSAMPLE) ((b - g + CENTERJSAMPLE) & MAXJSAMPLE); } } } /* * Convert some rows of samples to the JPEG colorspace. * This version handles grayscale output with no conversion. * The source can be either plain grayscale or YCC (since Y == gray). */ METHODDEF(void) grayscale_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION count; register int instride = cinfo->input_components; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr = output_buf[0][output_row++]; for (count = num_cols; count > 0; count--) { *outptr++ = *inptr; /* don't need GETJSAMPLE() here */ inptr += instride; } } } /* * Convert some rows of samples to the JPEG colorspace. * No colorspace conversion, but change from interleaved * to separate-planes representation. */ METHODDEF(void) rgb_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { register JSAMPROW inptr; register JSAMPROW outptr0, outptr1, outptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr0 = output_buf[0][output_row]; outptr1 = output_buf[1][output_row]; outptr2 = output_buf[2][output_row]; output_row++; for (col = 0; col < num_cols; col++) { /* We can dispense with GETJSAMPLE() here */ outptr0[col] = inptr[RGB_RED]; outptr1[col] = inptr[RGB_GREEN]; outptr2[col] = inptr[RGB_BLUE]; inptr += RGB_PIXELSIZE; } } } /* * Convert some rows of samples to the JPEG colorspace. * This version handles multi-component colorspaces without conversion. * We assume input_components == num_components. */ METHODDEF(void) null_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION count; register int num_comps = cinfo->num_components; JDIMENSION num_cols = cinfo->image_width; int ci; while (--num_rows >= 0) { /* It seems fastest to make a separate pass for each component. */ for (ci = 0; ci < num_comps; ci++) { inptr = input_buf[0] + ci; outptr = output_buf[ci][output_row]; for (count = num_cols; count > 0; count--) { *outptr++ = *inptr; /* don't need GETJSAMPLE() here */ inptr += num_comps; } } input_buf++; output_row++; } } /* * Empty method for start_pass. */ METHODDEF(void) null_method (j_compress_ptr cinfo) { /* no work needed */ } /* * Module initialization routine for input colorspace conversion. */ GLOBAL(void) jinit_color_converter (j_compress_ptr cinfo) { my_cconvert_ptr cconvert; cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_converter)); cinfo->cconvert = &cconvert->pub; /* set start_pass to null method until we find out differently */ cconvert->pub.start_pass = null_method; /* Make sure input_components agrees with in_color_space */ switch (cinfo->in_color_space) { case JCS_GRAYSCALE: if (cinfo->input_components != 1) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; case JCS_RGB: case JCS_BG_RGB: #if RGB_PIXELSIZE != 3 if (cinfo->input_components != RGB_PIXELSIZE) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; #endif /* else share code with YCbCr */ case JCS_YCbCr: case JCS_BG_YCC: if (cinfo->input_components != 3) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; case JCS_CMYK: case JCS_YCCK: if (cinfo->input_components != 4) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; default: /* JCS_UNKNOWN can be anything */ if (cinfo->input_components < 1) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); } /* Support color transform only for RGB colorspaces */ if (cinfo->color_transform && cinfo->jpeg_color_space != JCS_RGB && cinfo->jpeg_color_space != JCS_BG_RGB) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); /* Check num_components, set conversion method based on requested space */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); switch (cinfo->in_color_space) { case JCS_GRAYSCALE: case JCS_YCbCr: case JCS_BG_YCC: cconvert->pub.color_convert = grayscale_convert; break; case JCS_RGB: cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = rgb_gray_convert; break; default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } break; case JCS_RGB: case JCS_BG_RGB: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space != cinfo->jpeg_color_space) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); switch (cinfo->color_transform) { case JCT_NONE: cconvert->pub.color_convert = rgb_convert; break; case JCT_SUBTRACT_GREEN: cconvert->pub.color_convert = rgb_rgb1_convert; break; default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } break; case JCS_YCbCr: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); switch (cinfo->in_color_space) { case JCS_RGB: cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = rgb_ycc_convert; break; case JCS_YCbCr: cconvert->pub.color_convert = null_convert; break; default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } break; case JCS_BG_YCC: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); switch (cinfo->in_color_space) { case JCS_RGB: /* For conversion from normal RGB input to BG_YCC representation, * the Cb/Cr values are first computed as usual, and then * quantized further after DCT processing by a factor of * 2 in reference to the nominal quantization factor. */ /* need quantization scale by factor of 2 after DCT */ cinfo->comp_info[1].component_needed = TRUE; cinfo->comp_info[2].component_needed = TRUE; /* compute normal YCC first */ cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = rgb_ycc_convert; break; case JCS_YCbCr: /* need quantization scale by factor of 2 after DCT */ cinfo->comp_info[1].component_needed = TRUE; cinfo->comp_info[2].component_needed = TRUE; /*FALLTHROUGH*/ case JCS_BG_YCC: /* Pass through for BG_YCC input */ cconvert->pub.color_convert = null_convert; break; default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } break; case JCS_CMYK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space != JCS_CMYK) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cconvert->pub.color_convert = null_convert; break; case JCS_YCCK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); switch (cinfo->in_color_space) { case JCS_CMYK: cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = cmyk_ycck_convert; break; case JCS_YCCK: cconvert->pub.color_convert = null_convert; break; default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } break; default: /* allow null conversion of JCS_UNKNOWN */ if (cinfo->jpeg_color_space != cinfo->in_color_space || cinfo->num_components != cinfo->input_components) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cconvert->pub.color_convert = null_convert; } } fltk-1.4.3/jpeg/jidctint.c0000644000175000017500000055074015004135251015521 0ustar albrechtalbrecht/* * jidctint.c * * Copyright (C) 1991-1998, Thomas G. Lane. * Modification developed 2002-2018 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a slow-but-accurate integer implementation of the * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine * must also perform dequantization of the input coefficients. * * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT * on each row (or vice versa, but it's more convenient to emit a row at * a time). Direct algorithms are also available, but they are much more * complex and seem not to be any faster when reduced to code. * * This implementation is based on an algorithm described in * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. * The primary algorithm described there uses 11 multiplies and 29 adds. * We use their alternate method with 12 multiplies and 32 adds. * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. * * We also provide IDCT routines with various output sample block sizes for * direct resolution reduction or enlargement and for direct resolving the * common 2x1 and 1x2 subsampling cases without additional resampling: NxN * (N=1...16), 2NxN, and Nx2N (N=1...8) pixels for one 8x8 input DCT block. * * For N<8 we simply take the corresponding low-frequency coefficients of * the 8x8 input DCT block and apply an NxN point IDCT on the sub-block * to yield the downscaled outputs. * This can be seen as direct low-pass downsampling from the DCT domain * point of view rather than the usual spatial domain point of view, * yielding significant computational savings and results at least * as good as common bilinear (averaging) spatial downsampling. * * For N>8 we apply a partial NxN IDCT on the 8 input coefficients as * lower frequencies and higher frequencies assumed to be zero. * It turns out that the computational effort is similar to the 8x8 IDCT * regarding the output size. * Furthermore, the scaling and descaling is the same for all IDCT sizes. * * CAUTION: We rely on the FIX() macro except for the N=1,2,4,8 cases * since there would be too many additional constants to pre-calculate. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_ISLOW_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ #endif /* * The poop on this scaling stuff is as follows: * * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) * larger than the true IDCT outputs. The final outputs are therefore * a factor of N larger than desired; since N=8 this can be cured by * a simple right shift at the end of the algorithm. The advantage of * this arrangement is that we save two multiplications per 1-D IDCT, * because the y0 and y4 inputs need not be divided by sqrt(N). * * We have to do addition and subtraction of the integer inputs, which * is no problem, and multiplication by fractional constants, which is * a problem to do in integer arithmetic. We multiply all the constants * by CONST_SCALE and convert them to integer constants (thus retaining * CONST_BITS bits of precision in the constants). After doing a * multiplication we have to divide the product by CONST_SCALE, with proper * rounding, to produce the correct output. This division can be done * cheaply as a right shift of CONST_BITS bits. We postpone shifting * as long as possible so that partial sums can be added together with * full fractional precision. * * The outputs of the first pass are scaled up by PASS1_BITS bits so that * they are represented to better-than-integral precision. These outputs * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word * with the recommended scaling. (To scale up 12-bit sample data further, an * intermediate INT32 array would be needed.) * * To avoid overflow of the 32-bit intermediate results in pass 2, we must * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis * shows that the values given below are the most effective. */ #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 13 #define PASS1_BITS 2 #else #define CONST_BITS 13 #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 13 #define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ #define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ #define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ #define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ #define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ #define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ #define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ #define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ #define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ #define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ #define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ #define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ #else #define FIX_0_298631336 FIX(0.298631336) #define FIX_0_390180644 FIX(0.390180644) #define FIX_0_541196100 FIX(0.541196100) #define FIX_0_765366865 FIX(0.765366865) #define FIX_0_899976223 FIX(0.899976223) #define FIX_1_175875602 FIX(1.175875602) #define FIX_1_501321110 FIX(1.501321110) #define FIX_1_847759065 FIX(1.847759065) #define FIX_1_961570560 FIX(1.961570560) #define FIX_2_053119869 FIX(2.053119869) #define FIX_2_562915447 FIX(2.562915447) #define FIX_3_072711026 FIX(3.072711026) #endif /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * For 8-bit samples with the recommended scaling, all the variable * and constant values involved are no more than 16 bits wide, so a * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. * For 12-bit samples, a full 32-bit multiplication will be needed. */ #if BITS_IN_JSAMPLE == 8 #define MULTIPLY(var,const) MULTIPLY16C16(var,const) #else #define MULTIPLY(var,const) ((var) * (const)) #endif /* Dequantize a coefficient by multiplying it by the multiplier-table * entry; produce an int result. In this module, both inputs and result * are 16 bits or less, so either int or short multiply will work. */ #define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) /* * Perform dequantization and inverse DCT on one block of coefficients. * * Optimized algorithm with 12 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/16). */ GLOBAL(void) jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * Note results are scaled up by sqrt(8) compared to a true IDCT; * furthermore, we scale the results by 2**PASS1_BITS. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { /* Due to quantization, we will usually find that many of the input * coefficients are zero, especially the AC terms. We can exploit this * by short-circuiting the IDCT calculation for any column in which all * the AC terms are zero. In that case each output is equal to the * DC coefficient (with scale factor as needed). * With typical images and quantization tables, half or more of the * column DCT calculations can be simplified this way. */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; wsptr[DCTSIZE*2] = dcval; wsptr[DCTSIZE*3] = dcval; wsptr[DCTSIZE*4] = dcval; wsptr[DCTSIZE*5] = dcval; wsptr[DCTSIZE*6] = dcval; wsptr[DCTSIZE*7] = dcval; inptr++; /* advance pointers to next column */ quantptr++; wsptr++; continue; } /* Even part: reverse the even part of the forward DCT. * The rotator is c(-6). */ z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z2 <<= CONST_BITS; z3 <<= CONST_BITS; /* Add fudge factor here for final descale. */ z2 += ONE << (CONST_BITS-PASS1_BITS-1); tmp0 = z2 + z3; tmp1 = z2 - z3; z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ tmp10 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; tmp11 = tmp1 + tmp3; tmp12 = tmp1 - tmp3; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } /* Pass 2: process rows from work array, store into output array. * Note that we must descale the results by a factor of 8 == 2**3, * and also undo the PASS1_BITS scaling. */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { outptr = output_buf[ctr] + output_col; /* Add range center and fudge factor for final descale and range-limit. */ z2 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); /* Rows of zeroes can be exploited in the same way as we did with columns. * However, the column calculation has created many nonzero AC terms, so * the simplification applies less often (typically 5% to 10% of the time). * On machines with very fast multiplication, it's possible that the * test takes more time than it's worth. In that case this section * may be commented out. */ #ifndef NO_ZERO_ROW_TEST if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ JSAMPLE dcval = range_limit[(int) RIGHT_SHIFT(z2, PASS1_BITS+3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; outptr[2] = dcval; outptr[3] = dcval; outptr[4] = dcval; outptr[5] = dcval; outptr[6] = dcval; outptr[7] = dcval; wsptr += DCTSIZE; /* advance pointer to next row */ continue; } #endif /* Even part: reverse the even part of the forward DCT. * The rotator is c(-6). */ z3 = (INT32) wsptr[4]; tmp0 = (z2 + z3) << CONST_BITS; tmp1 = (z2 - z3) << CONST_BITS; z2 = (INT32) wsptr[2]; z3 = (INT32) wsptr[6]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ tmp10 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; tmp11 = tmp1 + tmp3; tmp12 = tmp1 - tmp3; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = (INT32) wsptr[7]; tmp1 = (INT32) wsptr[5]; tmp2 = (INT32) wsptr[3]; tmp3 = (INT32) wsptr[1]; z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } #ifdef IDCT_SCALING_SUPPORTED /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a reduced-size 7x7 output block. * * Optimized algorithm with 12 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/14). */ GLOBAL(void) jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[7*7]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp13 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp13 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp13 += ONE << (CONST_BITS-PASS1_BITS-1); z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ tmp0 = z1 + z3; z2 -= tmp0; tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */ tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ tmp0 = tmp1 - tmp2; tmp1 += tmp2; tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ tmp1 += tmp2; z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ tmp0 += z2; tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ /* Final output stage */ wsptr[7*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); wsptr[7*6] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); wsptr[7*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); wsptr[7*5] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); wsptr[7*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); wsptr[7*4] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); wsptr[7*3] = (int) RIGHT_SHIFT(tmp13, CONST_BITS-PASS1_BITS); } /* Pass 2: process 7 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 7; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp13 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp13 <<= CONST_BITS; z1 = (INT32) wsptr[2]; z2 = (INT32) wsptr[4]; z3 = (INT32) wsptr[6]; tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ tmp0 = z1 + z3; z2 -= tmp0; tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */ tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ tmp0 = tmp1 - tmp2; tmp1 += tmp2; tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ tmp1 += tmp2; z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ tmp0 += z2; tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 7; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a reduced-size 6x6 output block. * * Optimized algorithm with 3 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/12). */ GLOBAL(void) jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[6*6]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp0 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ tmp1 = tmp0 + tmp10; tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS); tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ tmp10 = tmp1 + tmp0; tmp12 = tmp1 - tmp0; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); tmp1 = (z1 - z2 - z3) << PASS1_BITS; /* Final output stage */ wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); wsptr[6*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); wsptr[6*1] = (int) (tmp11 + tmp1); wsptr[6*4] = (int) (tmp11 - tmp1); wsptr[6*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); wsptr[6*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); } /* Pass 2: process 6 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 6; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp0 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; tmp2 = (INT32) wsptr[4]; tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ tmp1 = tmp0 + tmp10; tmp11 = tmp0 - tmp10 - tmp10; tmp10 = (INT32) wsptr[2]; tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ tmp10 = tmp1 + tmp0; tmp12 = tmp1 - tmp0; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); tmp1 = (z1 - z2 - z3) << CONST_BITS; /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 6; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a reduced-size 5x5 output block. * * Optimized algorithm with 5 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/10). */ GLOBAL(void) jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp10, tmp11, tmp12; INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[5*5]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp12 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp12 += ONE << (CONST_BITS-PASS1_BITS-1); tmp0 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */ z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */ z3 = tmp12 + z2; tmp10 = z3 + z1; tmp11 = z3 - z1; tmp12 -= z2 << 2; /* Odd part */ z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ /* Final output stage */ wsptr[5*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); wsptr[5*4] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); wsptr[5*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); wsptr[5*3] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); wsptr[5*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS); } /* Pass 2: process 5 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 5; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp12 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp12 <<= CONST_BITS; tmp0 = (INT32) wsptr[2]; tmp1 = (INT32) wsptr[4]; z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */ z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */ z3 = tmp12 + z2; tmp10 = z3 + z1; tmp11 = z3 - z1; tmp12 -= z2 << 2; /* Odd part */ z2 = (INT32) wsptr[1]; z3 = (INT32) wsptr[3]; z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 5; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a reduced-size 4x4 output block. * * Optimized algorithm with 3 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. */ GLOBAL(void) jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp2, tmp10, tmp12; INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[4*4]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp10 = (tmp0 + tmp2) << PASS1_BITS; tmp12 = (tmp0 - tmp2) << PASS1_BITS; /* Odd part */ /* Same rotation as in the even part of the 8x8 LL&M IDCT */ z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ CONST_BITS-PASS1_BITS); tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ CONST_BITS-PASS1_BITS); /* Final output stage */ wsptr[4*0] = (int) (tmp10 + tmp0); wsptr[4*3] = (int) (tmp10 - tmp0); wsptr[4*1] = (int) (tmp12 + tmp2); wsptr[4*2] = (int) (tmp12 - tmp2); } /* Pass 2: process 4 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 4; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp0 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp2 = (INT32) wsptr[2]; tmp10 = (tmp0 + tmp2) << CONST_BITS; tmp12 = (tmp0 - tmp2) << CONST_BITS; /* Odd part */ /* Same rotation as in the even part of the 8x8 LL&M IDCT */ z2 = (INT32) wsptr[1]; z3 = (INT32) wsptr[3]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 4; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a reduced-size 3x3 output block. * * Optimized algorithm with 2 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/6). */ GLOBAL(void) jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp2, tmp10, tmp12; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[3*3]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp0 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ tmp10 = tmp0 + tmp12; tmp2 = tmp0 - tmp12 - tmp12; /* Odd part */ tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ /* Final output stage */ wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); wsptr[3*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); wsptr[3*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); } /* Pass 2: process 3 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 3; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp0 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; tmp2 = (INT32) wsptr[2]; tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ tmp10 = tmp0 + tmp12; tmp2 = tmp0 - tmp12 - tmp12; /* Odd part */ tmp12 = (INT32) wsptr[1]; tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 3; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a reduced-size 2x2 output block. * * Multiplication-less algorithm. */ GLOBAL(void) jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; ISLOW_MULT_TYPE * quantptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); ISHIFT_TEMPS /* Pass 1: process columns from input. */ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; /* Column 0 */ tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); /* Add range center and fudge factor for final descale and range-limit. */ tmp4 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); tmp0 = tmp4 + tmp5; tmp2 = tmp4 - tmp5; /* Column 1 */ tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0+1], quantptr[DCTSIZE*0+1]); tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1+1], quantptr[DCTSIZE*1+1]); tmp1 = tmp4 + tmp5; tmp3 = tmp4 - tmp5; /* Pass 2: process 2 rows, store into output array. */ /* Row 0 */ outptr = output_buf[0] + output_col; outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; /* Row 1 */ outptr = output_buf[1] + output_col; outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp2 + tmp3, 3) & RANGE_MASK]; outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp2 - tmp3, 3) & RANGE_MASK]; } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a reduced-size 1x1 output block. * * We hardly need an inverse DCT routine for this: just take the * average pixel value, which is one-eighth of the DC coefficient. */ GLOBAL(void) jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { DCTELEM dcval; ISLOW_MULT_TYPE * quantptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); ISHIFT_TEMPS /* 1x1 is trivial: just take the DC coefficient divided by 8. */ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; dcval = DEQUANTIZE(coef_block[0], quantptr[0]); /* Add range center and fudge factor for descale and range-limit. */ dcval += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); output_buf[0][output_col] = range_limit[(int) IRIGHT_SHIFT(dcval, 3) & RANGE_MASK]; } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 9x9 output block. * * Optimized algorithm with 10 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/18). */ GLOBAL(void) jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13, tmp14; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*9]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp0 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */ tmp1 = tmp0 + tmp3; tmp2 = tmp0 - tmp3 - tmp3; tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */ tmp11 = tmp2 + tmp0; tmp14 = tmp2 - tmp0 - tmp0; tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */ tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */ tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */ tmp10 = tmp1 + tmp0 - tmp3; tmp12 = tmp1 - tmp0 + tmp2; tmp13 = tmp1 - tmp2 + tmp3; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */ tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */ tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */ tmp0 = tmp2 + tmp3 - z2; tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */ tmp2 += z2 - tmp1; tmp3 += z2 + tmp1; tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */ /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); wsptr[8*8] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); wsptr[8*7] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); wsptr[8*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); wsptr[8*6] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); wsptr[8*3] = (int) RIGHT_SHIFT(tmp13 + tmp3, CONST_BITS-PASS1_BITS); wsptr[8*5] = (int) RIGHT_SHIFT(tmp13 - tmp3, CONST_BITS-PASS1_BITS); wsptr[8*4] = (int) RIGHT_SHIFT(tmp14, CONST_BITS-PASS1_BITS); } /* Pass 2: process 9 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 9; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp0 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; z1 = (INT32) wsptr[2]; z2 = (INT32) wsptr[4]; z3 = (INT32) wsptr[6]; tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */ tmp1 = tmp0 + tmp3; tmp2 = tmp0 - tmp3 - tmp3; tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */ tmp11 = tmp2 + tmp0; tmp14 = tmp2 - tmp0 - tmp0; tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */ tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */ tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */ tmp10 = tmp1 + tmp0 - tmp3; tmp12 = tmp1 - tmp0 + tmp2; tmp13 = tmp1 - tmp2 + tmp3; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; z4 = (INT32) wsptr[7]; z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */ tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */ tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */ tmp0 = tmp2 + tmp3 - z2; tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */ tmp2 += z2 - tmp1; tmp3 += z2 + tmp1; tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 10x10 output block. * * Optimized algorithm with 12 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/20). */ GLOBAL(void) jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14; INT32 tmp20, tmp21, tmp22, tmp23, tmp24; INT32 z1, z2, z3, z4, z5; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*10]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 <<= CONST_BITS; /* Add fudge factor here for final descale. */ z3 += ONE << (CONST_BITS-PASS1_BITS-1); z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ tmp10 = z3 + z1; tmp11 = z3 - z2; tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ CONST_BITS-PASS1_BITS); z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ tmp20 = tmp10 + tmp12; tmp24 = tmp10 - tmp12; tmp21 = tmp11 + tmp13; tmp23 = tmp11 - tmp13; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp11 = z2 + z4; tmp13 = z2 - z4; tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ z5 = z3 << CONST_BITS; z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ z4 = z5 + tmp12; tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1)); tmp12 = (z1 - tmp13 - z3) << PASS1_BITS; tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); wsptr[8*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); wsptr[8*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); wsptr[8*2] = (int) (tmp22 + tmp12); wsptr[8*7] = (int) (tmp22 - tmp12); wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); wsptr[8*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); wsptr[8*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); } /* Pass 2: process 10 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 10; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ z3 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); z3 <<= CONST_BITS; z4 = (INT32) wsptr[4]; z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ tmp10 = z3 + z1; tmp11 = z3 - z2; tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */ z2 = (INT32) wsptr[2]; z3 = (INT32) wsptr[6]; z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ tmp20 = tmp10 + tmp12; tmp24 = tmp10 - tmp12; tmp21 = tmp11 + tmp13; tmp23 = tmp11 - tmp13; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; z3 <<= CONST_BITS; z4 = (INT32) wsptr[7]; tmp11 = z2 + z4; tmp13 = z2 - z4; tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ z4 = z3 + tmp12; tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1)); tmp12 = ((z1 - tmp13) << CONST_BITS) - z3; tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing an 11x11 output block. * * Optimized algorithm with 24 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/22). */ GLOBAL(void) jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*11]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp10 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp10 += ONE << (CONST_BITS-PASS1_BITS-1); z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */ tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */ z4 = z1 + z3; tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */ z4 -= z2; tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ tmp21 = tmp20 + tmp23 + tmp25 - MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ tmp24 += tmp25; tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp11 = z1 + z2; tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */ tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */ tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */ tmp11 += z1; tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); wsptr[8*10] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); wsptr[8*9] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); wsptr[8*8] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); wsptr[8*7] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); wsptr[8*6] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); wsptr[8*5] = (int) RIGHT_SHIFT(tmp25, CONST_BITS-PASS1_BITS); } /* Pass 2: process 11 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 11; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp10 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp10 <<= CONST_BITS; z1 = (INT32) wsptr[2]; z2 = (INT32) wsptr[4]; z3 = (INT32) wsptr[6]; tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */ tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */ z4 = z1 + z3; tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */ z4 -= z2; tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ tmp21 = tmp20 + tmp23 + tmp25 - MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ tmp24 += tmp25; tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; z4 = (INT32) wsptr[7]; tmp11 = z1 + z2; tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */ tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */ tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */ tmp11 += z1; tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 12x12 output block. * * Optimized algorithm with 15 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/24). */ GLOBAL(void) jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*12]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 <<= CONST_BITS; /* Add fudge factor here for final descale. */ z3 += ONE << (CONST_BITS-PASS1_BITS-1); z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ tmp10 = z3 + z4; tmp11 = z3 - z4; z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ z1 <<= CONST_BITS; z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z2 <<= CONST_BITS; tmp12 = z1 - z2; tmp21 = z3 + tmp12; tmp24 = z3 - tmp12; tmp12 = z4 + z2; tmp20 = tmp10 + tmp12; tmp25 = tmp10 - tmp12; tmp12 = z4 - z1 - z2; tmp22 = tmp11 + tmp12; tmp23 = tmp11 - tmp12; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ tmp10 = z1 + z3; tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ z1 -= z4; z2 -= z3; z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); wsptr[8*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); wsptr[8*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); wsptr[8*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); wsptr[8*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); wsptr[8*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); wsptr[8*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); } /* Pass 2: process 12 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 12; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ z3 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); z3 <<= CONST_BITS; z4 = (INT32) wsptr[4]; z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ tmp10 = z3 + z4; tmp11 = z3 - z4; z1 = (INT32) wsptr[2]; z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ z1 <<= CONST_BITS; z2 = (INT32) wsptr[6]; z2 <<= CONST_BITS; tmp12 = z1 - z2; tmp21 = z3 + tmp12; tmp24 = z3 - tmp12; tmp12 = z4 + z2; tmp20 = tmp10 + tmp12; tmp25 = tmp10 - tmp12; tmp12 = z4 - z1 - z2; tmp22 = tmp11 + tmp12; tmp23 = tmp11 - tmp12; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; z4 = (INT32) wsptr[7]; tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ tmp10 = z1 + z3; tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ z1 -= z4; z2 -= z3; z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 13x13 output block. * * Optimized algorithm with 29 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/26). */ GLOBAL(void) jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*13]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z1 <<= CONST_BITS; /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); tmp10 = z3 + z4; tmp11 = z3 - z4; tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */ tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */ tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */ tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */ tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */ tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */ tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */ tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */ tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */ tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */ tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */ tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */ tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */ /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */ tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */ tmp15 = z1 + z4; tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */ tmp11 += tmp14; tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */ tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */ tmp12 += tmp14; tmp13 += tmp14; tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ tmp14 += z1; tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); wsptr[8*12] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); wsptr[8*11] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); wsptr[8*10] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); wsptr[8*9] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); wsptr[8*8] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); wsptr[8*7] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); wsptr[8*6] = (int) RIGHT_SHIFT(tmp26, CONST_BITS-PASS1_BITS); } /* Pass 2: process 13 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 13; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ z1 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); z1 <<= CONST_BITS; z2 = (INT32) wsptr[2]; z3 = (INT32) wsptr[4]; z4 = (INT32) wsptr[6]; tmp10 = z3 + z4; tmp11 = z3 - z4; tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */ tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */ tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */ tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */ tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */ tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */ tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */ tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */ tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */ tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */ tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */ tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */ tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */ /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; z4 = (INT32) wsptr[7]; tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */ tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */ tmp15 = z1 + z4; tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */ tmp11 += tmp14; tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */ tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */ tmp12 += tmp14; tmp13 += tmp14; tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ tmp14 += z1; tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 14x14 output block. * * Optimized algorithm with 20 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/28). */ GLOBAL(void) jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*14]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z1 <<= CONST_BITS; /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ tmp10 = z1 + z2; tmp11 = z1 + z3; tmp12 = z1 - z4; tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ CONST_BITS-PASS1_BITS); z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ MULTIPLY(z2, FIX(1.378756276)); /* c2 */ tmp20 = tmp10 + tmp13; tmp26 = tmp10 - tmp13; tmp21 = tmp11 + tmp14; tmp25 = tmp11 - tmp14; tmp22 = tmp12 + tmp15; tmp24 = tmp12 - tmp15; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp13 = z4 << CONST_BITS; tmp14 = z1 + z3; tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ z1 -= z2; tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */ tmp16 += tmp15; z1 += z4; z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */ tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ tmp13 = (z1 - z3) << PASS1_BITS; /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); wsptr[8*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); wsptr[8*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); wsptr[8*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); wsptr[8*3] = (int) (tmp23 + tmp13); wsptr[8*10] = (int) (tmp23 - tmp13); wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); wsptr[8*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); wsptr[8*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); wsptr[8*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); } /* Pass 2: process 14 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 14; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ z1 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); z1 <<= CONST_BITS; z4 = (INT32) wsptr[4]; z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ tmp10 = z1 + z2; tmp11 = z1 + z3; tmp12 = z1 - z4; tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */ z1 = (INT32) wsptr[2]; z2 = (INT32) wsptr[6]; z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ MULTIPLY(z2, FIX(1.378756276)); /* c2 */ tmp20 = tmp10 + tmp13; tmp26 = tmp10 - tmp13; tmp21 = tmp11 + tmp14; tmp25 = tmp11 - tmp14; tmp22 = tmp12 + tmp15; tmp24 = tmp12 - tmp15; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; z4 = (INT32) wsptr[7]; z4 <<= CONST_BITS; tmp14 = z1 + z3; tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ z1 -= z2; tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */ tmp16 += tmp15; tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */ tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ tmp13 = ((z1 - z3) << CONST_BITS) + z4; /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 15x15 output block. * * Optimized algorithm with 22 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/30). */ GLOBAL(void) jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*15]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z1 <<= CONST_BITS; /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */ tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */ tmp12 = z1 - tmp10; tmp13 = z1 + tmp11; z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */ z4 = z2 - z3; z3 += z2; tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */ tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */ z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */ tmp20 = tmp13 + tmp10 + tmp11; tmp23 = tmp12 - tmp10 + tmp11 + z2; tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */ tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */ tmp25 = tmp13 - tmp10 - tmp11; tmp26 = tmp12 + tmp10 - tmp11 - z2; tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */ tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */ tmp21 = tmp12 + tmp10 + tmp11; tmp24 = tmp13 - tmp10 + tmp11; tmp11 += tmp11; tmp22 = z1 + tmp11; /* c10 = c6-c12 */ tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */ /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z4 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp13 = z2 - z4; tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */ tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */ tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */ tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */ tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */ z2 = z1 - z4; tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */ tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */ tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */ tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */ z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */ tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */ tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */ /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); wsptr[8*14] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); wsptr[8*13] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); wsptr[8*12] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); wsptr[8*11] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); wsptr[8*10] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); wsptr[8*9] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); wsptr[8*8] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); wsptr[8*7] = (int) RIGHT_SHIFT(tmp27, CONST_BITS-PASS1_BITS); } /* Pass 2: process 15 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 15; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ z1 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); z1 <<= CONST_BITS; z2 = (INT32) wsptr[2]; z3 = (INT32) wsptr[4]; z4 = (INT32) wsptr[6]; tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */ tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */ tmp12 = z1 - tmp10; tmp13 = z1 + tmp11; z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */ z4 = z2 - z3; z3 += z2; tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */ tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */ z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */ tmp20 = tmp13 + tmp10 + tmp11; tmp23 = tmp12 - tmp10 + tmp11 + z2; tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */ tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */ tmp25 = tmp13 - tmp10 - tmp11; tmp26 = tmp12 + tmp10 - tmp11 - z2; tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */ tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */ tmp21 = tmp12 + tmp10 + tmp11; tmp24 = tmp13 - tmp10 + tmp11; tmp11 += tmp11; tmp22 = z1 + tmp11; /* c10 = c6-c12 */ tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */ /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z4 = (INT32) wsptr[5]; z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */ z4 = (INT32) wsptr[7]; tmp13 = z2 - z4; tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */ tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */ tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */ tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */ tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */ z2 = z1 - z4; tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */ tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */ tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */ tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */ z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */ tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */ tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 16x16 output block. * * Optimized algorithm with 28 multiplications in the 1-D kernel. * cK represents sqrt(2) * cos(K*pi/32). */ GLOBAL(void) jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*16]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp0 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ tmp10 = tmp0 + tmp1; tmp11 = tmp0 - tmp1; tmp12 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z3 = z1 - z2; z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ tmp20 = tmp10 + tmp0; tmp27 = tmp10 - tmp0; tmp21 = tmp12 + tmp1; tmp26 = tmp12 - tmp1; tmp22 = tmp13 + tmp2; tmp25 = tmp13 - tmp2; tmp23 = tmp11 + tmp3; tmp24 = tmp11 - tmp3; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp11 = z1 + z3; tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ tmp13 = tmp10 + tmp11 + tmp12 - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ z2 += z4; z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ tmp1 += z1; tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ tmp12 += z2; z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ tmp2 += z2; tmp3 += z2; z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ tmp10 += z2; tmp11 += z2; /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS); wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS); wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS); wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS); wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS); wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS); wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS); wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS); wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS); wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS); wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS); wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS); wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS); wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS); wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); } /* Pass 2: process 16 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 16; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp0 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; z1 = (INT32) wsptr[4]; tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ tmp10 = tmp0 + tmp1; tmp11 = tmp0 - tmp1; tmp12 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; z1 = (INT32) wsptr[2]; z2 = (INT32) wsptr[6]; z3 = z1 - z2; z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ tmp20 = tmp10 + tmp0; tmp27 = tmp10 - tmp0; tmp21 = tmp12 + tmp1; tmp26 = tmp12 - tmp1; tmp22 = tmp13 + tmp2; tmp25 = tmp13 - tmp2; tmp23 = tmp11 + tmp3; tmp24 = tmp11 - tmp3; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; z4 = (INT32) wsptr[7]; tmp11 = z1 + z3; tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ tmp13 = tmp10 + tmp11 + tmp12 - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ z2 += z4; z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ tmp1 += z1; tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ tmp12 += z2; z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ tmp2 += z2; tmp3 += z2; z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ tmp10 += z2; tmp11 += z2; /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 16x8 output block. * * 8-point IDCT in pass 1 (columns), 16-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*8]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * Note results are scaled up by sqrt(8) compared to a true IDCT; * furthermore, we scale the results by 2**PASS1_BITS. * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { /* Due to quantization, we will usually find that many of the input * coefficients are zero, especially the AC terms. We can exploit this * by short-circuiting the IDCT calculation for any column in which all * the AC terms are zero. In that case each output is equal to the * DC coefficient (with scale factor as needed). * With typical images and quantization tables, half or more of the * column DCT calculations can be simplified this way. */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; wsptr[DCTSIZE*2] = dcval; wsptr[DCTSIZE*3] = dcval; wsptr[DCTSIZE*4] = dcval; wsptr[DCTSIZE*5] = dcval; wsptr[DCTSIZE*6] = dcval; wsptr[DCTSIZE*7] = dcval; inptr++; /* advance pointers to next column */ quantptr++; wsptr++; continue; } /* Even part: reverse the even part of the forward DCT. * The rotator is c(-6). */ z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z2 <<= CONST_BITS; z3 <<= CONST_BITS; /* Add fudge factor here for final descale. */ z2 += ONE << (CONST_BITS-PASS1_BITS-1); tmp0 = z2 + z3; tmp1 = z2 - z3; z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ tmp10 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; tmp11 = tmp1 + tmp3; tmp12 = tmp1 - tmp3; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } /* Pass 2: process 8 rows from work array, store into output array. * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). */ wsptr = workspace; for (ctr = 0; ctr < 8; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp0 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; z1 = (INT32) wsptr[4]; tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ tmp10 = tmp0 + tmp1; tmp11 = tmp0 - tmp1; tmp12 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; z1 = (INT32) wsptr[2]; z2 = (INT32) wsptr[6]; z3 = z1 - z2; z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ tmp20 = tmp10 + tmp0; tmp27 = tmp10 - tmp0; tmp21 = tmp12 + tmp1; tmp26 = tmp12 - tmp1; tmp22 = tmp13 + tmp2; tmp25 = tmp13 - tmp2; tmp23 = tmp11 + tmp3; tmp24 = tmp11 - tmp3; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; z4 = (INT32) wsptr[7]; tmp11 = z1 + z3; tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ tmp13 = tmp10 + tmp11 + tmp12 - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ z2 += z4; z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ tmp1 += z1; tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ tmp12 += z2; z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ tmp2 += z2; tmp3 += z2; z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ tmp10 += z2; tmp11 += z2; /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 14x7 output block. * * 7-point IDCT in pass 1 (columns), 14-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*7]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp23 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp23 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp23 += ONE << (CONST_BITS-PASS1_BITS-1); z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ tmp10 = z1 + z3; z2 -= tmp10; tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */ tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ tmp10 = tmp11 - tmp12; tmp11 += tmp12; tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ tmp11 += tmp12; z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ tmp10 += z2; tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); wsptr[8*6] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); wsptr[8*5] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); wsptr[8*4] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); wsptr[8*3] = (int) RIGHT_SHIFT(tmp23, CONST_BITS-PASS1_BITS); } /* Pass 2: process 7 rows from work array, store into output array. * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). */ wsptr = workspace; for (ctr = 0; ctr < 7; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ z1 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); z1 <<= CONST_BITS; z4 = (INT32) wsptr[4]; z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ tmp10 = z1 + z2; tmp11 = z1 + z3; tmp12 = z1 - z4; tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */ z1 = (INT32) wsptr[2]; z2 = (INT32) wsptr[6]; z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ MULTIPLY(z2, FIX(1.378756276)); /* c2 */ tmp20 = tmp10 + tmp13; tmp26 = tmp10 - tmp13; tmp21 = tmp11 + tmp14; tmp25 = tmp11 - tmp14; tmp22 = tmp12 + tmp15; tmp24 = tmp12 - tmp15; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; z4 = (INT32) wsptr[7]; z4 <<= CONST_BITS; tmp14 = z1 + z3; tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ z1 -= z2; tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */ tmp16 += tmp15; tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */ tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ tmp13 = ((z1 - z3) << CONST_BITS) + z4; /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 12x6 output block. * * 6-point IDCT in pass 1 (columns), 12-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*6]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp10 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp10 += ONE << (CONST_BITS-PASS1_BITS-1); tmp12 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */ tmp11 = tmp10 + tmp20; tmp21 = RIGHT_SHIFT(tmp10 - tmp20 - tmp20, CONST_BITS-PASS1_BITS); tmp20 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */ tmp20 = tmp11 + tmp10; tmp22 = tmp11 - tmp10; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ tmp10 = tmp11 + ((z1 + z2) << CONST_BITS); tmp12 = tmp11 + ((z3 - z2) << CONST_BITS); tmp11 = (z1 - z2 - z3) << PASS1_BITS; /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); wsptr[8*5] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) (tmp21 + tmp11); wsptr[8*4] = (int) (tmp21 - tmp11); wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); wsptr[8*3] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); } /* Pass 2: process 6 rows from work array, store into output array. * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). */ wsptr = workspace; for (ctr = 0; ctr < 6; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ z3 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); z3 <<= CONST_BITS; z4 = (INT32) wsptr[4]; z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ tmp10 = z3 + z4; tmp11 = z3 - z4; z1 = (INT32) wsptr[2]; z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ z1 <<= CONST_BITS; z2 = (INT32) wsptr[6]; z2 <<= CONST_BITS; tmp12 = z1 - z2; tmp21 = z3 + tmp12; tmp24 = z3 - tmp12; tmp12 = z4 + z2; tmp20 = tmp10 + tmp12; tmp25 = tmp10 - tmp12; tmp12 = z4 - z1 - z2; tmp22 = tmp11 + tmp12; tmp23 = tmp11 - tmp12; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; z4 = (INT32) wsptr[7]; tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ tmp10 = z1 + z3; tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ z1 -= z4; z2 -= z3; z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 10x5 output block. * * 5-point IDCT in pass 1 (columns), 10-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14; INT32 tmp20, tmp21, tmp22, tmp23, tmp24; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*5]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp12 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp12 += ONE << (CONST_BITS-PASS1_BITS-1); tmp13 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp14 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */ z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */ z3 = tmp12 + z2; tmp10 = z3 + z1; tmp11 = z3 - z1; tmp12 -= z2 << 2; /* Odd part */ z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp13, CONST_BITS-PASS1_BITS); wsptr[8*4] = (int) RIGHT_SHIFT(tmp10 - tmp13, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp14, CONST_BITS-PASS1_BITS); wsptr[8*3] = (int) RIGHT_SHIFT(tmp11 - tmp14, CONST_BITS-PASS1_BITS); wsptr[8*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS); } /* Pass 2: process 5 rows from work array, store into output array. * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). */ wsptr = workspace; for (ctr = 0; ctr < 5; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ z3 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); z3 <<= CONST_BITS; z4 = (INT32) wsptr[4]; z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ tmp10 = z3 + z1; tmp11 = z3 - z2; tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */ z2 = (INT32) wsptr[2]; z3 = (INT32) wsptr[6]; z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ tmp20 = tmp10 + tmp12; tmp24 = tmp10 - tmp12; tmp21 = tmp11 + tmp13; tmp23 = tmp11 - tmp13; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; z3 <<= CONST_BITS; z4 = (INT32) wsptr[7]; tmp11 = z2 + z4; tmp13 = z2 - z4; tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ z4 = z3 + tmp12; tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1)); tmp12 = ((z1 - tmp13) << CONST_BITS) - z3; tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing an 8x4 output block. * * 4-point IDCT in pass 1 (columns), 8-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*4]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * 4-point IDCT kernel, * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp10 = (tmp0 + tmp2) << PASS1_BITS; tmp12 = (tmp0 - tmp2) << PASS1_BITS; /* Odd part */ /* Same rotation as in the even part of the 8x8 LL&M IDCT */ z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ CONST_BITS-PASS1_BITS); tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ CONST_BITS-PASS1_BITS); /* Final output stage */ wsptr[8*0] = (int) (tmp10 + tmp0); wsptr[8*3] = (int) (tmp10 - tmp0); wsptr[8*1] = (int) (tmp12 + tmp2); wsptr[8*2] = (int) (tmp12 - tmp2); } /* Pass 2: process rows from work array, store into output array. * Note that we must descale the results by a factor of 8 == 2**3, * and also undo the PASS1_BITS scaling. * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ wsptr = workspace; for (ctr = 0; ctr < 4; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part: reverse the even part of the forward DCT. * The rotator is c(-6). */ /* Add range center and fudge factor for final descale and range-limit. */ z2 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); z3 = (INT32) wsptr[4]; tmp0 = (z2 + z3) << CONST_BITS; tmp1 = (z2 - z3) << CONST_BITS; z2 = (INT32) wsptr[2]; z3 = (INT32) wsptr[6]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ tmp10 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; tmp11 = tmp1 + tmp3; tmp12 = tmp1 - tmp3; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = (INT32) wsptr[7]; tmp1 = (INT32) wsptr[5]; tmp2 = (INT32) wsptr[3]; tmp3 = (INT32) wsptr[1]; z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 6x3 output block. * * 3-point IDCT in pass 1 (columns), 6-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[6*3]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp0 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ tmp10 = tmp0 + tmp12; tmp2 = tmp0 - tmp12 - tmp12; /* Odd part */ tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ /* Final output stage */ wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); wsptr[6*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); wsptr[6*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); } /* Pass 2: process 3 rows from work array, store into output array. * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ wsptr = workspace; for (ctr = 0; ctr < 3; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp0 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; tmp2 = (INT32) wsptr[4]; tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ tmp1 = tmp0 + tmp10; tmp11 = tmp0 - tmp10 - tmp10; tmp10 = (INT32) wsptr[2]; tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ tmp10 = tmp1 + tmp0; tmp12 = tmp1 - tmp0; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); tmp1 = (z1 - z2 - z3) << CONST_BITS; /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 6; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 4x2 output block. * * 2-point IDCT in pass 1 (columns), 4-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_4x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp2, tmp10, tmp12; INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; INT32 * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; INT32 workspace[4*2]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); /* Odd part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); /* Final output stage */ wsptr[4*0] = tmp10 + tmp0; wsptr[4*1] = tmp10 - tmp0; } /* Pass 2: process 2 rows from work array, store into output array. * 4-point IDCT kernel, * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. */ wsptr = workspace; for (ctr = 0; ctr < 2; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp0 = wsptr[0] + ((((INT32) RANGE_CENTER) << 3) + (ONE << 2)); tmp2 = wsptr[2]; tmp10 = (tmp0 + tmp2) << CONST_BITS; tmp12 = (tmp0 - tmp2) << CONST_BITS; /* Odd part */ /* Same rotation as in the even part of the 8x8 LL&M IDCT */ z2 = wsptr[1]; z3 = wsptr[3]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS+3) & RANGE_MASK]; wsptr += 4; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 2x1 output block. * * 1-point IDCT in pass 1 (columns), 2-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_2x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { DCTELEM tmp0, tmp1; ISLOW_MULT_TYPE * quantptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); ISHIFT_TEMPS /* Pass 1: empty. */ /* Pass 2: process 1 row from input, store into output array. */ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; outptr = output_buf[0] + output_col; /* Even part */ tmp0 = DEQUANTIZE(coef_block[0], quantptr[0]); /* Add range center and fudge factor for final descale and range-limit. */ tmp0 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); /* Odd part */ tmp1 = DEQUANTIZE(coef_block[1], quantptr[1]); /* Final output stage */ outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing an 8x16 output block. * * 16-point IDCT in pass 1 (columns), 8-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[8*16]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp0 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ tmp10 = tmp0 + tmp1; tmp11 = tmp0 - tmp1; tmp12 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z3 = z1 - z2; z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ tmp20 = tmp10 + tmp0; tmp27 = tmp10 - tmp0; tmp21 = tmp12 + tmp1; tmp26 = tmp12 - tmp1; tmp22 = tmp13 + tmp2; tmp25 = tmp13 - tmp2; tmp23 = tmp11 + tmp3; tmp24 = tmp11 - tmp3; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp11 = z1 + z3; tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ tmp13 = tmp10 + tmp11 + tmp12 - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ z2 += z4; z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ tmp1 += z1; tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ tmp12 += z2; z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ tmp2 += z2; tmp3 += z2; z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ tmp10 += z2; tmp11 += z2; /* Final output stage */ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS); wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS); wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS); wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS); wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS); wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS); wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS); wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS); wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS); wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS); wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS); wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS); wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS); wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS); wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS); wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); } /* Pass 2: process rows from work array, store into output array. * Note that we must descale the results by a factor of 8 == 2**3, * and also undo the PASS1_BITS scaling. * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ wsptr = workspace; for (ctr = 0; ctr < 16; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part: reverse the even part of the forward DCT. * The rotator is c(-6). */ /* Add range center and fudge factor for final descale and range-limit. */ z2 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); z3 = (INT32) wsptr[4]; tmp0 = (z2 + z3) << CONST_BITS; tmp1 = (z2 - z3) << CONST_BITS; z2 = (INT32) wsptr[2]; z3 = (INT32) wsptr[6]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ tmp10 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; tmp11 = tmp1 + tmp3; tmp12 = tmp1 - tmp3; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = (INT32) wsptr[7]; tmp1 = (INT32) wsptr[5]; tmp2 = (INT32) wsptr[3]; tmp3 = (INT32) wsptr[1]; z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 7x14 output block. * * 14-point IDCT in pass 1 (columns), 7-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[7*14]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z1 <<= CONST_BITS; /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ tmp10 = z1 + z2; tmp11 = z1 + z3; tmp12 = z1 - z4; tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ CONST_BITS-PASS1_BITS); z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ MULTIPLY(z2, FIX(1.378756276)); /* c2 */ tmp20 = tmp10 + tmp13; tmp26 = tmp10 - tmp13; tmp21 = tmp11 + tmp14; tmp25 = tmp11 - tmp14; tmp22 = tmp12 + tmp15; tmp24 = tmp12 - tmp15; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp13 = z4 << CONST_BITS; tmp14 = z1 + z3; tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ z1 -= z2; tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */ tmp16 += tmp15; z1 += z4; z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */ tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ tmp13 = (z1 - z3) << PASS1_BITS; /* Final output stage */ wsptr[7*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); wsptr[7*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); wsptr[7*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); wsptr[7*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); wsptr[7*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); wsptr[7*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); wsptr[7*3] = (int) (tmp23 + tmp13); wsptr[7*10] = (int) (tmp23 - tmp13); wsptr[7*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); wsptr[7*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); wsptr[7*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); wsptr[7*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); wsptr[7*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); wsptr[7*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); } /* Pass 2: process 14 rows from work array, store into output array. * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). */ wsptr = workspace; for (ctr = 0; ctr < 14; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp23 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp23 <<= CONST_BITS; z1 = (INT32) wsptr[2]; z2 = (INT32) wsptr[4]; z3 = (INT32) wsptr[6]; tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ tmp10 = z1 + z3; z2 -= tmp10; tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */ tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ tmp10 = tmp11 - tmp12; tmp11 += tmp12; tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ tmp11 += tmp12; z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ tmp10 += z2; tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 7; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 6x12 output block. * * 12-point IDCT in pass 1 (columns), 6-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; INT32 z1, z2, z3, z4; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[6*12]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 <<= CONST_BITS; /* Add fudge factor here for final descale. */ z3 += ONE << (CONST_BITS-PASS1_BITS-1); z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ tmp10 = z3 + z4; tmp11 = z3 - z4; z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ z1 <<= CONST_BITS; z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z2 <<= CONST_BITS; tmp12 = z1 - z2; tmp21 = z3 + tmp12; tmp24 = z3 - tmp12; tmp12 = z4 + z2; tmp20 = tmp10 + tmp12; tmp25 = tmp10 - tmp12; tmp12 = z4 - z1 - z2; tmp22 = tmp11 + tmp12; tmp23 = tmp11 - tmp12; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ tmp10 = z1 + z3; tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ z1 -= z4; z2 -= z3; z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ /* Final output stage */ wsptr[6*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); wsptr[6*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); wsptr[6*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); wsptr[6*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); wsptr[6*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); wsptr[6*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); wsptr[6*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); wsptr[6*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); wsptr[6*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); wsptr[6*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); wsptr[6*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); wsptr[6*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); } /* Pass 2: process 12 rows from work array, store into output array. * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ wsptr = workspace; for (ctr = 0; ctr < 12; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp10 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp10 <<= CONST_BITS; tmp12 = (INT32) wsptr[4]; tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */ tmp11 = tmp10 + tmp20; tmp21 = tmp10 - tmp20 - tmp20; tmp20 = (INT32) wsptr[2]; tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */ tmp20 = tmp11 + tmp10; tmp22 = tmp11 - tmp10; /* Odd part */ z1 = (INT32) wsptr[1]; z2 = (INT32) wsptr[3]; z3 = (INT32) wsptr[5]; tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ tmp10 = tmp11 + ((z1 + z2) << CONST_BITS); tmp12 = tmp11 + ((z3 - z2) << CONST_BITS); tmp11 = (z1 - z2 - z3) << CONST_BITS; /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 6; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 5x10 output block. * * 10-point IDCT in pass 1 (columns), 5-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14; INT32 tmp20, tmp21, tmp22, tmp23, tmp24; INT32 z1, z2, z3, z4, z5; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[5*10]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 <<= CONST_BITS; /* Add fudge factor here for final descale. */ z3 += ONE << (CONST_BITS-PASS1_BITS-1); z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ tmp10 = z3 + z1; tmp11 = z3 - z2; tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ CONST_BITS-PASS1_BITS); z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ tmp20 = tmp10 + tmp12; tmp24 = tmp10 - tmp12; tmp21 = tmp11 + tmp13; tmp23 = tmp11 - tmp13; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp11 = z2 + z4; tmp13 = z2 - z4; tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ z5 = z3 << CONST_BITS; z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ z4 = z5 + tmp12; tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1)); tmp12 = (z1 - tmp13 - z3) << PASS1_BITS; tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ /* Final output stage */ wsptr[5*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); wsptr[5*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); wsptr[5*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); wsptr[5*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); wsptr[5*2] = (int) (tmp22 + tmp12); wsptr[5*7] = (int) (tmp22 - tmp12); wsptr[5*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); wsptr[5*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); wsptr[5*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); wsptr[5*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); } /* Pass 2: process 10 rows from work array, store into output array. * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). */ wsptr = workspace; for (ctr = 0; ctr < 10; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp12 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp12 <<= CONST_BITS; tmp13 = (INT32) wsptr[2]; tmp14 = (INT32) wsptr[4]; z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */ z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */ z3 = tmp12 + z2; tmp10 = z3 + z1; tmp11 = z3 - z1; tmp12 -= z2 << 2; /* Odd part */ z2 = (INT32) wsptr[1]; z3 = (INT32) wsptr[3]; z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp13, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp14, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 5; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 4x8 output block. * * 8-point IDCT in pass 1 (columns), 4-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[4*8]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * Note results are scaled up by sqrt(8) compared to a true IDCT; * furthermore, we scale the results by 2**PASS1_BITS. * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 4; ctr > 0; ctr--) { /* Due to quantization, we will usually find that many of the input * coefficients are zero, especially the AC terms. We can exploit this * by short-circuiting the IDCT calculation for any column in which all * the AC terms are zero. In that case each output is equal to the * DC coefficient (with scale factor as needed). * With typical images and quantization tables, half or more of the * column DCT calculations can be simplified this way. */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; wsptr[4*0] = dcval; wsptr[4*1] = dcval; wsptr[4*2] = dcval; wsptr[4*3] = dcval; wsptr[4*4] = dcval; wsptr[4*5] = dcval; wsptr[4*6] = dcval; wsptr[4*7] = dcval; inptr++; /* advance pointers to next column */ quantptr++; wsptr++; continue; } /* Even part: reverse the even part of the forward DCT. * The rotator is c(-6). */ z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); z2 <<= CONST_BITS; z3 <<= CONST_BITS; /* Add fudge factor here for final descale. */ z2 += ONE << (CONST_BITS-PASS1_BITS-1); tmp0 = z2 + z3; tmp1 = z2 - z3; z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ tmp10 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; tmp11 = tmp1 + tmp3; tmp12 = tmp1 - tmp3; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ wsptr[4*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); wsptr[4*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); wsptr[4*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); wsptr[4*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); wsptr[4*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); wsptr[4*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); wsptr[4*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); wsptr[4*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } /* Pass 2: process 8 rows from work array, store into output array. * 4-point IDCT kernel, * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. */ wsptr = workspace; for (ctr = 0; ctr < 8; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp0 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp2 = (INT32) wsptr[2]; tmp10 = (tmp0 + tmp2) << CONST_BITS; tmp12 = (tmp0 - tmp2) << CONST_BITS; /* Odd part */ /* Same rotation as in the even part of the 8x8 LL&M IDCT */ z2 = (INT32) wsptr[1]; z3 = (INT32) wsptr[3]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 4; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 3x6 output block. * * 6-point IDCT in pass 1 (columns), 3-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[3*6]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp0 <<= CONST_BITS; /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ tmp1 = tmp0 + tmp10; tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS); tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ tmp10 = tmp1 + tmp0; tmp12 = tmp1 - tmp0; /* Odd part */ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); tmp1 = (z1 - z2 - z3) << PASS1_BITS; /* Final output stage */ wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); wsptr[3*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); wsptr[3*1] = (int) (tmp11 + tmp1); wsptr[3*4] = (int) (tmp11 - tmp1); wsptr[3*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); wsptr[3*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); } /* Pass 2: process 6 rows from work array, store into output array. * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). */ wsptr = workspace; for (ctr = 0; ctr < 6; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp0 = (INT32) wsptr[0] + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; tmp2 = (INT32) wsptr[2]; tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ tmp10 = tmp0 + tmp12; tmp2 = tmp0 - tmp12 - tmp12; /* Odd part */ tmp12 = (INT32) wsptr[1]; tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += 3; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 2x4 output block. * * 4-point IDCT in pass 1 (columns), 2-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp2, tmp10, tmp12; INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; INT32 * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; INT32 workspace[2*4]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. * 4-point IDCT kernel, * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = 0; ctr < 2; ctr++, inptr++, quantptr++, wsptr++) { /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp10 = (tmp0 + tmp2) << CONST_BITS; tmp12 = (tmp0 - tmp2) << CONST_BITS; /* Odd part */ /* Same rotation as in the even part of the 8x8 LL&M IDCT */ z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ /* Final output stage */ wsptr[2*0] = tmp10 + tmp0; wsptr[2*3] = tmp10 - tmp0; wsptr[2*1] = tmp12 + tmp2; wsptr[2*2] = tmp12 - tmp2; } /* Pass 2: process 4 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 4; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ /* Add range center and fudge factor for final descale and range-limit. */ tmp10 = wsptr[0] + ((((INT32) RANGE_CENTER) << (CONST_BITS+3)) + (ONE << (CONST_BITS+2))); /* Odd part */ tmp0 = wsptr[1]; /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+3) & RANGE_MASK]; wsptr += 2; /* advance pointer to next row */ } } /* * Perform dequantization and inverse DCT on one block of coefficients, * producing a 1x2 output block. * * 2-point IDCT in pass 1 (columns), 1-point in pass 2 (rows). */ GLOBAL(void) jpeg_idct_1x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { DCTELEM tmp0, tmp1; ISLOW_MULT_TYPE * quantptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); ISHIFT_TEMPS /* Process 1 column from input, store into output array. */ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; /* Even part */ tmp0 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); /* Add range center and fudge factor for final descale and range-limit. */ tmp0 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); /* Odd part */ tmp1 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); /* Final output stage */ output_buf[0][output_col] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; output_buf[1][output_col] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; } #endif /* IDCT_SCALING_SUPPORTED */ #endif /* DCT_ISLOW_SUPPORTED */ fltk-1.4.3/jpeg/jdct.h0000644000175000017500000004232315004135251014633 0ustar albrechtalbrecht/* * jdct.h * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2002-2023 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This include file contains common declarations for the forward and * inverse DCT modules. These declarations are private to the DCT managers * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. * The individual DCT algorithms are kept in separate files to ease * machine-dependent tuning (e.g., assembly coding). */ /* * A forward DCT routine is given a pointer to an input sample array and * a pointer to a work area of type DCTELEM[]; the DCT is to be performed * in-place in that buffer. Type DCTELEM is int for 8-bit samples, INT32 * for 12-bit samples. (NOTE: Floating-point DCT implementations use an * array of type FAST_FLOAT, instead.) * The input data is to be fetched from the sample array starting at a * specified column. (Any row offset needed will be applied to the array * pointer before it is passed to the FDCT code.) * Note that the number of samples fetched by the FDCT routine is * DCT_h_scaled_size * DCT_v_scaled_size. * The DCT outputs are returned scaled up by a factor of 8; they therefore * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This * convention improves accuracy in integer implementations and saves some * work in floating-point ones. * Quantization of the output coefficients is done by jcdctmgr.c. */ #if BITS_IN_JSAMPLE == 8 typedef int DCTELEM; /* 16 or 32 bits is fine */ #else typedef INT32 DCTELEM; /* must have 32 bits */ #endif typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col)); /* * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer * to an output sample array. The routine must dequantize the input data as * well as perform the IDCT; for dequantization, it uses the multiplier table * pointed to by compptr->dct_table. The output data is to be placed into the * sample array starting at a specified column. (Any row offset needed will * be applied to the array pointer before it is passed to the IDCT code.) * Note that the number of samples emitted by the IDCT routine is * DCT_h_scaled_size * DCT_v_scaled_size. */ /* typedef inverse_DCT_method_ptr is declared in jpegint.h */ /* * Each IDCT routine has its own ideas about the best dct_table element type. */ typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ #if BITS_IN_JSAMPLE == 8 typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ #define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ #else typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ #define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ #endif typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ /* * Each IDCT routine is responsible for range-limiting its results and * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could * be quite far out of range if the input data is corrupt, so a bulletproof * range-limiting step is required. We use a mask-and-table-lookup method * to do the combined operations quickly, assuming that RANGE_CENTER * (defined in jpegint.h) is a power of 2. See the comments with * prepare_range_limit_table (in jdmaster.c) for more info. */ #define RANGE_MASK (RANGE_CENTER * 2 - 1) #define RANGE_SUBSET (RANGE_CENTER - CENTERJSAMPLE) #define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit - RANGE_SUBSET) /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_fdct_islow jFDislow #define jpeg_fdct_ifast jFDifast #define jpeg_fdct_float jFDfloat #define jpeg_fdct_7x7 jFD7x7 #define jpeg_fdct_6x6 jFD6x6 #define jpeg_fdct_5x5 jFD5x5 #define jpeg_fdct_4x4 jFD4x4 #define jpeg_fdct_3x3 jFD3x3 #define jpeg_fdct_2x2 jFD2x2 #define jpeg_fdct_1x1 jFD1x1 #define jpeg_fdct_9x9 jFD9x9 #define jpeg_fdct_10x10 jFD10x10 #define jpeg_fdct_11x11 jFD11x11 #define jpeg_fdct_12x12 jFD12x12 #define jpeg_fdct_13x13 jFD13x13 #define jpeg_fdct_14x14 jFD14x14 #define jpeg_fdct_15x15 jFD15x15 #define jpeg_fdct_16x16 jFD16x16 #define jpeg_fdct_16x8 jFD16x8 #define jpeg_fdct_14x7 jFD14x7 #define jpeg_fdct_12x6 jFD12x6 #define jpeg_fdct_10x5 jFD10x5 #define jpeg_fdct_8x4 jFD8x4 #define jpeg_fdct_6x3 jFD6x3 #define jpeg_fdct_4x2 jFD4x2 #define jpeg_fdct_2x1 jFD2x1 #define jpeg_fdct_8x16 jFD8x16 #define jpeg_fdct_7x14 jFD7x14 #define jpeg_fdct_6x12 jFD6x12 #define jpeg_fdct_5x10 jFD5x10 #define jpeg_fdct_4x8 jFD4x8 #define jpeg_fdct_3x6 jFD3x6 #define jpeg_fdct_2x4 jFD2x4 #define jpeg_fdct_1x2 jFD1x2 #define jpeg_idct_islow jRDislow #define jpeg_idct_ifast jRDifast #define jpeg_idct_float jRDfloat #define jpeg_idct_7x7 jRD7x7 #define jpeg_idct_6x6 jRD6x6 #define jpeg_idct_5x5 jRD5x5 #define jpeg_idct_4x4 jRD4x4 #define jpeg_idct_3x3 jRD3x3 #define jpeg_idct_2x2 jRD2x2 #define jpeg_idct_1x1 jRD1x1 #define jpeg_idct_9x9 jRD9x9 #define jpeg_idct_10x10 jRD10x10 #define jpeg_idct_11x11 jRD11x11 #define jpeg_idct_12x12 jRD12x12 #define jpeg_idct_13x13 jRD13x13 #define jpeg_idct_14x14 jRD14x14 #define jpeg_idct_15x15 jRD15x15 #define jpeg_idct_16x16 jRD16x16 #define jpeg_idct_16x8 jRD16x8 #define jpeg_idct_14x7 jRD14x7 #define jpeg_idct_12x6 jRD12x6 #define jpeg_idct_10x5 jRD10x5 #define jpeg_idct_8x4 jRD8x4 #define jpeg_idct_6x3 jRD6x3 #define jpeg_idct_4x2 jRD4x2 #define jpeg_idct_2x1 jRD2x1 #define jpeg_idct_8x16 jRD8x16 #define jpeg_idct_7x14 jRD7x14 #define jpeg_idct_6x12 jRD6x12 #define jpeg_idct_5x10 jRD5x10 #define jpeg_idct_4x8 jRD4x8 #define jpeg_idct_3x6 jRD3x6 #define jpeg_idct_2x4 jRD2x4 #define jpeg_idct_1x2 jRD1x2 #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Extern declarations for the forward and inverse DCT routines. */ EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_7x7 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_6x6 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_5x5 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_4x4 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_3x3 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_2x2 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_1x1 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_9x9 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_10x10 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_11x11 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_12x12 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_13x13 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_14x14 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_15x15 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_16x16 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_16x8 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_14x7 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_12x6 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_10x5 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_8x4 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_6x3 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_4x2 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_2x1 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_8x16 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_7x14 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_6x12 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_5x10 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_4x8 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_3x6 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_2x4 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_fdct_1x2 JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_idct_islow JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_ifast JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_float JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_7x7 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_6x6 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_5x5 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_4x4 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_3x3 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_2x2 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_1x1 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_9x9 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_10x10 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_11x11 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_12x12 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_13x13 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_14x14 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_15x15 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_16x16 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_16x8 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_14x7 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_12x6 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_10x5 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_8x4 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_6x3 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_4x2 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_2x1 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_8x16 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_7x14 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_6x12 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_5x10 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_4x8 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_3x6 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_2x4 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_1x2 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); /* * Macros for handling fixed-point arithmetic; these are used by many * but not all of the DCT/IDCT modules. * * All values are expected to be of type INT32. * Fractional constants are scaled left by CONST_BITS bits. * CONST_BITS is defined within each module using these macros, * and may differ from one module to the next. */ #define ONE ((INT32) 1) #define CONST_SCALE (ONE << CONST_BITS) /* Convert a positive real constant to an integer scaled by CONST_SCALE. * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, * thus causing a lot of useless floating-point operations at run time. */ #define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * This macro is used only when the two inputs will actually be no more than * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a * full 32x32 multiply. This provides a useful speedup on many machines. * Unfortunately there is no way to specify a 16x16->32 multiply portably * in C, but some C compilers will do the right thing if you provide the * correct combination of casts. */ #ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ #define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) #endif #ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ #define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) #endif #ifndef MULTIPLY16C16 /* default definition */ #define MULTIPLY16C16(var,const) ((var) * (const)) #endif /* Same except both inputs are variables. */ #ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ #define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) #endif #ifndef MULTIPLY16V16 /* default definition */ #define MULTIPLY16V16(var1,var2) ((var1) * (var2)) #endif /* Like RIGHT_SHIFT, but applies to a DCTELEM. * We assume that int right shift is unsigned if INT32 right shift is. */ #ifdef RIGHT_SHIFT_IS_UNSIGNED #define ISHIFT_TEMPS DCTELEM ishift_temp; #if BITS_IN_JSAMPLE == 8 #define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ #else #define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ #endif #define IRIGHT_SHIFT(x,shft) \ ((ishift_temp = (x)) < 0 ? \ (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ (ishift_temp >> (shft))) #else #define ISHIFT_TEMPS #define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif fltk-1.4.3/jpeg/jdmaster.c0000644000175000017500000004511015004135251015510 0ustar albrechtalbrecht/* * jdmaster.c * * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2002-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains master control logic for the JPEG decompressor. * These routines are concerned with selecting the modules to be executed * and with determining the number of passes and the work to be done in each * pass. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private state */ typedef struct { struct jpeg_decomp_master pub; /* public fields */ int pass_number; /* # of passes completed */ boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ /* Saved references to initialized quantizer modules, * in case we need to switch modes. */ struct jpeg_color_quantizer * quantizer_1pass; struct jpeg_color_quantizer * quantizer_2pass; } my_decomp_master; typedef my_decomp_master * my_master_ptr; /* * Determine whether merged upsample/color conversion should be used. * CRUCIAL: this must match the actual capabilities of jdmerge.c! */ LOCAL(boolean) use_merged_upsample (j_decompress_ptr cinfo) { #ifdef UPSAMPLE_MERGING_SUPPORTED /* Merging is the equivalent of plain box-filter upsampling. */ /* The following condition is only needed if fancy shall select * a different upsampling method. In our current implementation * fancy only affects the DCT scaling, thus we can use fancy * upsampling and merged upsample simultaneously, in particular * with scaled DCT sizes larger than the default DCTSIZE. */ #if 0 if (cinfo->do_fancy_upsampling) return FALSE; #endif if (cinfo->CCIR601_sampling) return FALSE; /* jdmerge.c only supports YCC=>RGB color conversion */ if ((cinfo->jpeg_color_space != JCS_YCbCr && cinfo->jpeg_color_space != JCS_BG_YCC) || cinfo->num_components != 3 || cinfo->out_color_space != JCS_RGB || cinfo->out_color_components != RGB_PIXELSIZE || cinfo->color_transform) return FALSE; /* and it only handles 2h1v or 2h2v sampling ratios */ if (cinfo->comp_info[0].h_samp_factor != 2 || cinfo->comp_info[1].h_samp_factor != 1 || cinfo->comp_info[2].h_samp_factor != 1 || cinfo->comp_info[0].v_samp_factor > 2 || cinfo->comp_info[1].v_samp_factor != 1 || cinfo->comp_info[2].v_samp_factor != 1) return FALSE; /* furthermore, it doesn't work if we've scaled the IDCTs differently */ if (cinfo->comp_info[0].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || cinfo->comp_info[1].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || cinfo->comp_info[2].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || cinfo->comp_info[0].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || cinfo->comp_info[1].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || cinfo->comp_info[2].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size) return FALSE; /* ??? also need to test for upsample-time rescaling, when & if supported */ return TRUE; /* by golly, it'll work... */ #else return FALSE; #endif } /* * Compute output image dimensions and related values. * NOTE: this is exported for possible use by application. * Hence it mustn't do anything that can't be done twice. * Also note that it may be called before the master module is initialized! */ GLOBAL(void) jpeg_calc_output_dimensions (j_decompress_ptr cinfo) /* Do computations that are needed before master selection phase. * This function is used for full decompression. */ { int ci, i; jpeg_component_info *compptr; /* Prevent application from calling me at wrong times */ if (cinfo->global_state != DSTATE_READY) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Compute core output image dimensions and DCT scaling choices. */ jpeg_core_output_dimensions(cinfo); #ifdef IDCT_SCALING_SUPPORTED /* In selecting the actual DCT scaling for each component, we try to * scale up the chroma components via IDCT scaling rather than upsampling. * This saves time if the upsampler gets to use 1:1 scaling. * Note this code adapts subsampling ratios which are powers of 2. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { int ssize = 1; if (! cinfo->raw_data_out) while (cinfo->min_DCT_h_scaled_size * ssize <= (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { ssize = ssize * 2; } compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; ssize = 1; if (! cinfo->raw_data_out) while (cinfo->min_DCT_v_scaled_size * ssize <= (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { ssize = ssize * 2; } compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; /* We don't support IDCT ratios larger than 2. */ if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; /* Recompute downsampled dimensions of components; * application needs to know these if using raw downsampled data. */ /* Size in samples, after IDCT scaling */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), (long) (cinfo->max_v_samp_factor * cinfo->block_size)); } #endif /* IDCT_SCALING_SUPPORTED */ /* Report number of components in selected colorspace. */ /* This should correspond to the actual code in the color conversion module. */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: cinfo->out_color_components = 1; break; case JCS_RGB: case JCS_BG_RGB: cinfo->out_color_components = RGB_PIXELSIZE; break; default: /* YCCK <=> CMYK conversion or same colorspace as in file */ i = 0; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) if (compptr->component_needed) i++; /* count output color components */ cinfo->out_color_components = i; } cinfo->output_components = (cinfo->quantize_colors ? 1 : cinfo->out_color_components); /* See if upsampler will want to emit more than one row at a time */ if (use_merged_upsample(cinfo)) cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; else cinfo->rec_outbuf_height = 1; } /* * Several decompression processes need to range-limit values to the range * 0..MAXJSAMPLE; the input value may fall somewhat outside this range * due to noise introduced by quantization, roundoff error, etc. These * processes are inner loops and need to be as fast as possible. On most * machines, particularly CPUs with pipelines or instruction prefetch, * a (subscript-check-less) C table lookup * x = sample_range_limit[x]; * is faster than explicit tests * if (x < 0) x = 0; * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; * These processes all use a common table prepared by the routine below. * * For most steps we can mathematically guarantee that the initial value * of x is within 2*(MAXJSAMPLE+1) of the legal range, so a table running * from -2*(MAXJSAMPLE+1) to 3*MAXJSAMPLE+2 is sufficient. But for the * initial limiting step (just after the IDCT), a wildly out-of-range value * is possible if the input data is corrupt. To avoid any chance of indexing * off the end of memory and getting a bad-pointer trap, we perform the * post-IDCT limiting thus: * x = (sample_range_limit - SUBSET)[(x + CENTER) & MASK]; * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit * samples. Under normal circumstances this is more than enough range and * a correct output will be generated; with bogus input data the mask will * cause wraparound, and we will safely generate a bogus-but-in-range output. * For the post-IDCT step, we want to convert the data from signed to unsigned * representation by adding CENTERJSAMPLE at the same time that we limit it. * This is accomplished with SUBSET = CENTER - CENTERJSAMPLE. * * Note that the table is allocated in near data space on PCs; it's small * enough and used often enough to justify this. */ LOCAL(void) prepare_range_limit_table (j_decompress_ptr cinfo) /* Allocate and fill in the sample_range_limit table */ { JSAMPLE * table; int i; table = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (RANGE_CENTER * 2 + MAXJSAMPLE + 1) * SIZEOF(JSAMPLE)); /* First segment of range limit table: limit[x] = 0 for x < 0 */ MEMZERO(table, RANGE_CENTER * SIZEOF(JSAMPLE)); table += RANGE_CENTER; /* allow negative subscripts of table */ cinfo->sample_range_limit = table; /* Main part of range limit table: limit[x] = x */ for (i = 0; i <= MAXJSAMPLE; i++) table[i] = (JSAMPLE) i; /* End of range limit table: limit[x] = MAXJSAMPLE for x > MAXJSAMPLE */ for (; i <= MAXJSAMPLE + RANGE_CENTER; i++) table[i] = MAXJSAMPLE; } /* * Master selection of decompression modules. * This is done once at jpeg_start_decompress time. We determine * which modules will be used and give them appropriate initialization calls. * We also initialize the decompressor input side to begin consuming data. * * Since jpeg_read_header has finished, we know what is in the SOF * and (first) SOS markers. We also have all the application parameter * settings. */ LOCAL(void) master_selection (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; boolean use_c_buffer; long samplesperrow; JDIMENSION jd_samplesperrow; /* For now, precision must match compiled-in value... */ if (cinfo->data_precision != BITS_IN_JSAMPLE) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Initialize dimensions and other stuff */ jpeg_calc_output_dimensions(cinfo); prepare_range_limit_table(cinfo); /* Sanity check on image dimensions */ if (cinfo->output_height <= 0 || cinfo->output_width <= 0 || cinfo->out_color_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); /* Width of an output scanline must be representable as JDIMENSION. */ samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; jd_samplesperrow = (JDIMENSION) samplesperrow; if ((long) jd_samplesperrow != samplesperrow) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); /* Initialize my private state */ master->pass_number = 0; master->using_merged_upsample = use_merged_upsample(cinfo); /* Color quantizer selection */ master->quantizer_1pass = NULL; master->quantizer_2pass = NULL; /* No mode changes if not using buffered-image mode. */ if (! cinfo->quantize_colors || ! cinfo->buffered_image) { cinfo->enable_1pass_quant = FALSE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; } if (cinfo->quantize_colors) { if (cinfo->raw_data_out) ERREXIT(cinfo, JERR_NOTIMPL); /* 2-pass quantizer only works in 3-component color space. */ if (cinfo->out_color_components != 3) { cinfo->enable_1pass_quant = TRUE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; cinfo->colormap = NULL; } else if (cinfo->colormap != NULL) { cinfo->enable_external_quant = TRUE; } else if (cinfo->two_pass_quantize) { cinfo->enable_2pass_quant = TRUE; } else { cinfo->enable_1pass_quant = TRUE; } if (cinfo->enable_1pass_quant) { #ifdef QUANT_1PASS_SUPPORTED jinit_1pass_quantizer(cinfo); master->quantizer_1pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } /* We use the 2-pass code to map to external colormaps. */ if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { #ifdef QUANT_2PASS_SUPPORTED jinit_2pass_quantizer(cinfo); master->quantizer_2pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } /* If both quantizers are initialized, the 2-pass one is left active; * this is necessary for starting with quantization to an external map. */ } /* Post-processing: in particular, color conversion first */ if (! cinfo->raw_data_out) { if (master->using_merged_upsample) { #ifdef UPSAMPLE_MERGING_SUPPORTED jinit_merged_upsampler(cinfo); /* does color conversion too */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { jinit_color_deconverter(cinfo); jinit_upsampler(cinfo); } jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); } /* Inverse DCT */ jinit_inverse_dct(cinfo); /* Entropy decoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) jinit_arith_decoder(cinfo); else { jinit_huff_decoder(cinfo); } /* Initialize principal buffer controllers. */ use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; jinit_d_coef_controller(cinfo, use_c_buffer); if (! cinfo->raw_data_out) jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); /* Initialize input side of decompressor to consume first scan. */ (*cinfo->inputctl->start_input_pass) (cinfo); #ifdef D_MULTISCAN_FILES_SUPPORTED /* If jpeg_start_decompress will read the whole file, initialize * progress monitoring appropriately. The input step is counted * as one pass. */ if (cinfo->progress != NULL && ! cinfo->buffered_image && cinfo->inputctl->has_multiple_scans) { int nscans; /* Estimate number of scans to set pass_limit. */ if (cinfo->progressive_mode) { /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ nscans = 2 + 3 * cinfo->num_components; } else { /* For a nonprogressive multiscan file, estimate 1 scan per component. */ nscans = cinfo->num_components; } cinfo->progress->pass_counter = 0L; cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; cinfo->progress->completed_passes = 0; cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); /* Count the input pass as done */ master->pass_number++; } #endif /* D_MULTISCAN_FILES_SUPPORTED */ } /* * Per-pass setup. * This is called at the beginning of each output pass. We determine which * modules will be active during this pass and give them appropriate * start_pass calls. We also set is_dummy_pass to indicate whether this * is a "real" output pass or a dummy pass for color quantization. * (In the latter case, jdapistd.c will crank the pass to completion.) */ METHODDEF(void) prepare_for_output_pass (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; if (master->pub.is_dummy_pass) { #ifdef QUANT_2PASS_SUPPORTED /* Final pass of 2-pass quantization */ master->pub.is_dummy_pass = FALSE; (*cinfo->cquantize->start_pass) (cinfo, FALSE); (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif /* QUANT_2PASS_SUPPORTED */ } else { if (cinfo->quantize_colors && cinfo->colormap == NULL) { /* Select new quantization method */ if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { cinfo->cquantize = master->quantizer_2pass; master->pub.is_dummy_pass = TRUE; } else if (cinfo->enable_1pass_quant) { cinfo->cquantize = master->quantizer_1pass; } else { ERREXIT(cinfo, JERR_MODE_CHANGE); } } (*cinfo->idct->start_pass) (cinfo); (*cinfo->coef->start_output_pass) (cinfo); if (! cinfo->raw_data_out) { if (! master->using_merged_upsample) (*cinfo->cconvert->start_pass) (cinfo); (*cinfo->upsample->start_pass) (cinfo); if (cinfo->quantize_colors) (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); (*cinfo->post->start_pass) (cinfo, (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); } } /* Set up progress monitor's pass info if present */ if (cinfo->progress != NULL) { cinfo->progress->completed_passes = master->pass_number; cinfo->progress->total_passes = master->pass_number + (master->pub.is_dummy_pass ? 2 : 1); /* In buffered-image mode, we assume one more output pass if EOI not * yet reached, but no more passes if EOI has been reached. */ if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); } } } /* * Finish up at end of an output pass. */ METHODDEF(void) finish_output_pass (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; if (cinfo->quantize_colors) (*cinfo->cquantize->finish_pass) (cinfo); master->pass_number++; } #ifdef D_MULTISCAN_FILES_SUPPORTED /* * Switch to a new external colormap between output passes. */ GLOBAL(void) jpeg_new_colormap (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; /* Prevent application from calling me at wrong times */ if (cinfo->global_state != DSTATE_BUFIMAGE) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->quantize_colors && cinfo->enable_external_quant && cinfo->colormap != NULL) { /* Select 2-pass quantizer for external colormap use */ cinfo->cquantize = master->quantizer_2pass; /* Notify quantizer of colormap change */ (*cinfo->cquantize->new_color_map) (cinfo); master->pub.is_dummy_pass = FALSE; /* just in case */ } else ERREXIT(cinfo, JERR_MODE_CHANGE); } #endif /* D_MULTISCAN_FILES_SUPPORTED */ /* * Initialize master decompression control and select active modules. * This is performed at the start of jpeg_start_decompress. */ GLOBAL(void) jinit_master_decompress (j_decompress_ptr cinfo) { my_master_ptr master; master = (my_master_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_decomp_master)); cinfo->master = &master->pub; master->pub.prepare_for_output_pass = prepare_for_output_pass; master->pub.finish_output_pass = finish_output_pass; master->pub.is_dummy_pass = FALSE; master_selection(cinfo); } fltk-1.4.3/jpeg/jccoefct.c0000644000175000017500000003772715004135251015476 0ustar albrechtalbrecht/* * jccoefct.c * * Copyright (C) 1994-1997, Thomas G. Lane. * Modified 2003-2022 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the coefficient buffer controller for compression. * This controller is the top level of the JPEG compressor proper. * The coefficient buffer lies between forward-DCT and entropy encoding steps. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* We use a full-image coefficient buffer when doing Huffman optimization, * and also for writing multiple-scan JPEG files. In all cases, the DCT * step is run during the first pass, and subsequent passes need only read * the buffered coefficients. */ #ifdef ENTROPY_OPT_SUPPORTED #define FULL_COEF_BUFFER_SUPPORTED #else #ifdef C_MULTISCAN_FILES_SUPPORTED #define FULL_COEF_BUFFER_SUPPORTED #endif #endif /* Private buffer controller object */ typedef struct { struct jpeg_c_coef_controller pub; /* public fields */ JDIMENSION iMCU_row_num; /* iMCU row # within image */ JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ int MCU_vert_offset; /* counts MCU rows within iMCU row */ int MCU_rows_per_iMCU_row; /* number of such rows needed */ /* For single-pass compression, it's sufficient to buffer just one MCU * (although this may prove a bit slow in practice). * We append a workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, * and reuse it for each MCU constructed and sent. * In multi-pass modes, this array points to the current MCU's blocks * within the virtual arrays. */ JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; /* In multi-pass modes, we need a virtual block array for each component. */ jvirt_barray_ptr whole_image[MAX_COMPONENTS]; /* Workspace for single-pass compression (omitted otherwise). */ JBLOCK blk_buffer[C_MAX_BLOCKS_IN_MCU]; } my_coef_controller; typedef my_coef_controller * my_coef_ptr; /* Forward declarations */ METHODDEF(boolean) compress_data JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); #ifdef FULL_COEF_BUFFER_SUPPORTED METHODDEF(boolean) compress_first_pass JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); METHODDEF(boolean) compress_output JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); #endif LOCAL(void) start_iMCU_row (j_compress_ptr cinfo) /* Reset within-iMCU-row counters for a new row */ { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* In an interleaved scan, an MCU row is the same as an iMCU row. * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. * But at the bottom of the image, process only what's left. */ if (cinfo->comps_in_scan > 1) { coef->MCU_rows_per_iMCU_row = 1; } else { if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; else coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; } coef->MCU_ctr = 0; coef->MCU_vert_offset = 0; } /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; coef->iMCU_row_num = 0; start_iMCU_row(cinfo); switch (pass_mode) { case JBUF_PASS_THRU: if (coef->whole_image[0] != NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->pub.compress_data = compress_data; break; #ifdef FULL_COEF_BUFFER_SUPPORTED case JBUF_SAVE_AND_PASS: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->pub.compress_data = compress_first_pass; break; case JBUF_CRANK_DEST: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->pub.compress_data = compress_output; break; #endif default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); } } /* * Process some data in the single-pass case. * We process the equivalent of one fully interleaved MCU row ("iMCU" row) * per call, ie, v_samp_factor block rows for each component in the image. * Returns TRUE if the iMCU row is completed, FALSE if suspended. * * NB: input_buf contains a plane for each component in image, * which we index according to the component's SOF position. */ METHODDEF(boolean) compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int ci, xindex, yindex, yoffset, blockcnt; JBLOCKROW blkp; JSAMPARRAY input_ptr; JDIMENSION xpos; jpeg_component_info *compptr; forward_DCT_ptr forward_DCT; /* Loop to write as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { /* Determine where data comes from in input_buf and do the DCT thing. * Each call on forward_DCT processes a horizontal row of DCT blocks as * wide as an MCU. Dummy blocks at the right or bottom edge are filled in * specially. The data in them does not matter for image reconstruction, * so we fill them with values that will encode to the smallest amount of * data, viz: all zeroes in the AC entries, DC entries equal to previous * block's DC value. (Thanks to Thomas Kinsman for this idea.) */ blkp = coef->blk_buffer; /* pointer to current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; forward_DCT = cinfo->fdct->forward_DCT[compptr->component_index]; input_ptr = input_buf[compptr->component_index] + yoffset * compptr->DCT_v_scaled_size; /* ypos == (yoffset + yindex) * compptr->DCT_v_scaled_size */ blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; xpos = MCU_col_num * compptr->MCU_sample_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yoffset + yindex < compptr->last_row_height) { (*forward_DCT) (cinfo, compptr, input_ptr, blkp, xpos, (JDIMENSION) blockcnt); input_ptr += compptr->DCT_v_scaled_size; blkp += blockcnt; /* Dummy blocks at right edge */ if ((xindex = compptr->MCU_width - blockcnt) == 0) continue; } else { /* At bottom of image, need a whole row of dummy blocks */ xindex = compptr->MCU_width; } /* Fill in any dummy blocks needed in this row */ MEMZERO(blkp, xindex * SIZEOF(JBLOCK)); do { blkp[0][0] = blkp[-1][0]; blkp++; } while (--xindex); } } /* Try to write the MCU. In event of a suspension failure, we will * re-DCT the MCU on restart (a bit inefficient, could be fixed...) */ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return FALSE; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->MCU_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ coef->iMCU_row_num++; start_iMCU_row(cinfo); return TRUE; } #ifdef FULL_COEF_BUFFER_SUPPORTED /* * Process some data in the first pass of a multi-pass case. * We process the equivalent of one fully interleaved MCU row ("iMCU" row) * per call, ie, v_samp_factor block rows for each component in the image. * This amount of data is read from the source buffer, DCT'd and quantized, * and saved into the virtual arrays. We also generate suitable dummy blocks * as needed at the right and lower edges. (The dummy blocks are constructed * in the virtual arrays, which have been padded appropriately.) This makes * it possible for subsequent passes not to worry about real vs. dummy blocks. * * We must also emit the data to the entropy encoder. This is conveniently * done by calling compress_output() after we've loaded the current strip * of the virtual arrays. * * NB: input_buf contains a plane for each component in image. All * components are DCT'd and loaded into the virtual arrays in this pass. * However, it may be that only a subset of the components are emitted to * the entropy encoder during this first pass; be careful about looking * at the scan-dependent variables (MCU dimensions, etc). */ METHODDEF(boolean) compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION blocks_across, MCUs_across, MCUindex; int bi, ci, h_samp_factor, block_row, block_rows, ndummy; JCOEF lastDC; jpeg_component_info *compptr; JBLOCKARRAY buffer; JBLOCKROW thisblockrow, lastblockrow; JSAMPARRAY input_ptr; forward_DCT_ptr forward_DCT; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Align the virtual buffer for this component. */ buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, TRUE); /* Count non-dummy DCT block rows in this iMCU row. */ if (coef->iMCU_row_num < last_iMCU_row) block_rows = compptr->v_samp_factor; else { /* NB: can't use last_row_height here, since may not be set! */ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } blocks_across = compptr->width_in_blocks; h_samp_factor = compptr->h_samp_factor; /* Count number of dummy blocks to be added at the right margin. */ ndummy = (int) (blocks_across % h_samp_factor); if (ndummy > 0) ndummy = h_samp_factor - ndummy; forward_DCT = cinfo->fdct->forward_DCT[ci]; input_ptr = input_buf[ci]; /* Perform DCT for all non-dummy blocks in this iMCU row. Each call * on forward_DCT processes a complete horizontal row of DCT blocks. */ for (block_row = 0; block_row < block_rows; block_row++) { thisblockrow = buffer[block_row]; (*forward_DCT) (cinfo, compptr, input_ptr, thisblockrow, (JDIMENSION) 0, blocks_across); input_ptr += compptr->DCT_v_scaled_size; if (ndummy > 0) { /* Create dummy blocks at the right edge of the image. */ thisblockrow += blocks_across; /* => first dummy block */ FMEMZERO((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); lastDC = thisblockrow[-1][0]; for (bi = 0; bi < ndummy; bi++) { thisblockrow[bi][0] = lastDC; } } } /* If at end of image, create dummy block rows as needed. * The tricky part here is that within each MCU, we want the DC values * of the dummy blocks to match the last real block's DC value. * This squeezes a few more bytes out of the resulting file... */ if (block_row < compptr->v_samp_factor) { blocks_across += ndummy; /* include lower right corner */ MCUs_across = blocks_across / h_samp_factor; do { thisblockrow = buffer[block_row]; lastblockrow = buffer[block_row-1]; FMEMZERO((void FAR *) thisblockrow, (size_t) blocks_across * SIZEOF(JBLOCK)); for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { lastDC = lastblockrow[h_samp_factor-1][0]; for (bi = 0; bi < h_samp_factor; bi++) { thisblockrow[bi][0] = lastDC; } thisblockrow += h_samp_factor; /* advance to next MCU in row */ lastblockrow += h_samp_factor; } } while (++block_row < compptr->v_samp_factor); } } /* NB: compress_output will increment iMCU_row_num if successful. * A suspension return will result in redoing all the work above next time. */ /* Emit data to the entropy encoder, sharing code with subsequent passes */ return compress_output(cinfo, input_buf); } /* * Process some data in subsequent passes of a multi-pass case. * We process the equivalent of one fully interleaved MCU row ("iMCU" row) * per call, ie, v_samp_factor block rows for each component in the scan. * The data is obtained from the virtual arrays and fed to the entropy coder. * Returns TRUE if the iMCU row is completed, FALSE if suspended. * * NB: input_buf is ignored; it is likely to be a NULL pointer. */ METHODDEF(boolean) compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ int ci, xindex, yindex, yoffset; JDIMENSION start_col; JBLOCKARRAY blkp; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; /* Align the virtual buffers for the components used in this scan. * NB: during first pass, this is safe only because the buffers will * already be aligned properly, so jmemmgr.c won't need to do any I/O. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; buffer[ci] = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); } /* Loop to process one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) { /* Construct list of pointers to DCT blocks belonging to this MCU */ blkp = coef->MCU_buffer; /* pointer to current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; start_col = MCU_col_num * compptr->MCU_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { buffer_ptr = buffer[ci][yoffset + yindex] + start_col; xindex = compptr->MCU_width; do { *blkp++ = buffer_ptr++; } while (--xindex); } } /* Try to write the MCU. */ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return FALSE; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->MCU_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ coef->iMCU_row_num++; start_iMCU_row(cinfo); return TRUE; } #endif /* FULL_COEF_BUFFER_SUPPORTED */ /* * Initialize coefficient buffer controller. */ GLOBAL(void) jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; if (need_full_buffer) { #ifdef FULL_COEF_BUFFER_SUPPORTED /* Allocate a full-image virtual array for each component, */ /* padded to a multiple of samp_factor DCT blocks in each direction. */ int ci; jpeg_component_info *compptr; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller) - SIZEOF(coef->blk_buffer)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { /* We only need a single-MCU buffer. */ JBLOCKARRAY blkp; JBLOCKROW buffer_ptr; int bi; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); blkp = coef->MCU_buffer; buffer_ptr = coef->blk_buffer; bi = C_MAX_BLOCKS_IN_MCU; do { *blkp++ = buffer_ptr++; } while (--bi); coef->whole_image[0] = NULL; /* flag for no virtual arrays */ } coef->pub.start_pass = start_pass_coef; cinfo->coef = &coef->pub; } fltk-1.4.3/jpeg/jchuff.c0000644000175000017500000014426615004135251015160 0ustar albrechtalbrecht/* * jchuff.c * * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2006-2023 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy encoding routines. * Both sequential and progressive modes are supported in this single module. * * Much of the complexity here has to do with supporting output suspension. * If the data destination module demands suspension, we want to be able to * back up to the start of the current MCU. To do this, we copy state * variables into local working storage, and update them back to the * permanent JPEG objects only upon successful completion of an MCU. * * We do not support output suspension for the progressive JPEG mode, since * the library currently does not allow multiple-scan files to be written * with output suspension. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* The legal range of a DCT coefficient is * -1024 .. +1023 for 8-bit sample data precision; * -16384 .. +16383 for 12-bit sample data precision. * Hence the magnitude should always fit in sample data precision + 2 bits. */ /* Derived data constructed for each Huffman table */ typedef struct { unsigned int ehufco[256]; /* code for each symbol */ char ehufsi[256]; /* length of code for each symbol */ /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ } c_derived_tbl; /* Expanded entropy encoder object for Huffman encoding. * * The savable_state subrecord contains fields that change within an MCU, * but must not be updated permanently until we complete the MCU. */ typedef struct { INT32 put_buffer; /* current bit-accumulation buffer */ int put_bits; /* # of bits now in it */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state; /* This macro is to work around compilers with missing or broken * structure assignment. You'll need to fix this code if you have * such a compiler and you change MAX_COMPS_IN_SCAN. */ #ifndef NO_STRUCT_ASSIGN #define ASSIGN_STATE(dest,src) ((dest) = (src)) #else #if MAX_COMPS_IN_SCAN == 4 #define ASSIGN_STATE(dest,src) \ ((dest).put_buffer = (src).put_buffer, \ (dest).put_bits = (src).put_bits, \ (dest).last_dc_val[0] = (src).last_dc_val[0], \ (dest).last_dc_val[1] = (src).last_dc_val[1], \ (dest).last_dc_val[2] = (src).last_dc_val[2], \ (dest).last_dc_val[3] = (src).last_dc_val[3]) #endif #endif typedef struct { struct jpeg_entropy_encoder pub; /* public fields */ savable_state saved; /* Bit buffer & DC state at start of MCU */ /* These fields are NOT loaded into local working state. */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ int next_restart_num; /* next restart number to write (0-7) */ /* Pointers to derived tables (these workspaces have image lifespan) */ c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; /* Statistics tables for optimization */ long * dc_count_ptrs[NUM_HUFF_TBLS]; long * ac_count_ptrs[NUM_HUFF_TBLS]; /* Following fields used only in progressive mode */ /* Mode flag: TRUE for optimization, FALSE for actual data output */ boolean gather_statistics; /* next_output_byte/free_in_buffer are local copies of cinfo->dest fields. */ JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ /* Coding status for AC components */ int ac_tbl_no; /* the table number of the single component */ unsigned int EOBRUN; /* run length of EOBs */ unsigned int BE; /* # of buffered correction bits before MCU */ char * bit_buffer; /* buffer for correction bits (1 per char) */ /* packing correction bits tightly would save some space but cost time... */ } huff_entropy_encoder; typedef huff_entropy_encoder * huff_entropy_ptr; /* Working state while writing an MCU (sequential mode). * This struct contains all the fields that are needed by subroutines. */ typedef struct { JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ savable_state cur; /* Current bit buffer & DC state */ j_compress_ptr cinfo; /* dump_buffer needs access to this */ } working_state; /* MAX_CORR_BITS is the number of bits the AC refinement correction-bit * buffer can hold. Larger sizes may slightly improve compression, but * 1000 is already well into the realm of overkill. * The minimum safe size is 64 bits. */ #define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ /* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. * We assume that int right shift is unsigned if INT32 right shift is, * which should be safe. */ #ifdef RIGHT_SHIFT_IS_UNSIGNED #define ISHIFT_TEMPS int ishift_temp; #define IRIGHT_SHIFT(x,shft) \ ((ishift_temp = (x)) < 0 ? \ (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ (ishift_temp >> (shft))) #else #define ISHIFT_TEMPS #define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif /* * Compute the derived values for a Huffman table. * This routine also performs some validation checks on the table. */ LOCAL(void) jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, c_derived_tbl ** pdtbl) { JHUFF_TBL *htbl; c_derived_tbl *dtbl; int p, i, l, lastp, si, maxsymbol; char huffsize[257]; unsigned int huffcode[257]; unsigned int code; /* Note that huffsize[] and huffcode[] are filled in code-length order, * paralleling the order of the symbols themselves in htbl->huffval[]. */ /* Find the input Huffman table */ if (tblno < 0 || tblno >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); htbl = isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; if (htbl == NULL) htbl = jpeg_std_huff_table((j_common_ptr) cinfo, isDC, tblno); /* Allocate a workspace if we haven't already done so. */ if (*pdtbl == NULL) *pdtbl = (c_derived_tbl *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(c_derived_tbl)); dtbl = *pdtbl; /* Figure C.1: make table of Huffman code length for each symbol */ p = 0; for (l = 1; l <= 16; l++) { i = (int) htbl->bits[l]; if (i < 0 || p + i > 256) /* protect against table overrun */ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); while (i--) huffsize[p++] = (char) l; } huffsize[p] = 0; lastp = p; /* Figure C.2: generate the codes themselves */ /* We also validate that the counts represent a legal Huffman code tree. */ code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while (((int) huffsize[p]) == si) { huffcode[p++] = code; code++; } /* code is now 1 more than the last code used for codelength si; but * it must still fit in si bits, since no code is allowed to be all ones. */ if (((INT32) code) >= (((INT32) 1) << si)) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); code <<= 1; si++; } /* Figure C.3: generate encoding tables */ /* These are code and size indexed by symbol value */ /* Set all codeless symbols to have code length 0; * this lets us detect duplicate VAL entries here, and later * allows emit_bits to detect any attempt to emit such symbols. */ MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); /* This is also a convenient place to check for out-of-range * and duplicated VAL entries. We allow 0..255 for AC symbols * but only 0..15 for DC. (We could constrain them further * based on data depth and mode, but this seems enough.) */ maxsymbol = isDC ? 15 : 255; for (p = 0; p < lastp; p++) { i = htbl->huffval[p]; if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); dtbl->ehufco[i] = huffcode[p]; dtbl->ehufsi[i] = huffsize[p]; } } /* Outputting bytes to the file. * NB: these must be called only when actually outputting, * that is, entropy->gather_statistics == FALSE. */ /* Emit a byte, taking 'action' if must suspend. */ #define emit_byte_s(state,val,action) \ { *(state)->next_output_byte++ = (JOCTET) (val); \ if (--(state)->free_in_buffer == 0) \ if (! dump_buffer_s(state)) \ { action; } } /* Emit a byte */ #define emit_byte_e(entropy,val) \ { *(entropy)->next_output_byte++ = (JOCTET) (val); \ if (--(entropy)->free_in_buffer == 0) \ dump_buffer_e(entropy); } LOCAL(boolean) dump_buffer_s (working_state * state) /* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ { struct jpeg_destination_mgr * dest = state->cinfo->dest; if (! (*dest->empty_output_buffer) (state->cinfo)) return FALSE; /* After a successful buffer dump, must reset buffer pointers */ state->next_output_byte = dest->next_output_byte; state->free_in_buffer = dest->free_in_buffer; return TRUE; } LOCAL(void) dump_buffer_e (huff_entropy_ptr entropy) /* Empty the output buffer; we do not support suspension in this case. */ { struct jpeg_destination_mgr * dest = entropy->cinfo->dest; if (! (*dest->empty_output_buffer) (entropy->cinfo)) ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); /* After a successful buffer dump, must reset buffer pointers */ entropy->next_output_byte = dest->next_output_byte; entropy->free_in_buffer = dest->free_in_buffer; } /* Outputting bits to the file */ /* Only the right 24 bits of put_buffer are used; the valid bits are * left-justified in this part. At most 16 bits can be passed to emit_bits * in one call, and we never retain more than 7 bits in put_buffer * between calls, so 24 bits are sufficient. */ INLINE LOCAL(boolean) emit_bits_s (working_state * state, unsigned int code, int size) /* Emit some bits; return TRUE if successful, FALSE if must suspend */ { /* This routine is heavily used, so it's worth coding tightly. */ register INT32 put_buffer; register int put_bits; /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); /* mask off any extra bits in code */ put_buffer = ((INT32) code) & ((((INT32) 1) << size) - 1); /* new number of bits in buffer */ put_bits = size + state->cur.put_bits; put_buffer <<= 24 - put_bits; /* align incoming bits */ /* and merge with old buffer contents */ put_buffer |= state->cur.put_buffer; while (put_bits >= 8) { int c = (int) ((put_buffer >> 16) & 0xFF); emit_byte_s(state, c, return FALSE); if (c == 0xFF) { /* need to stuff a zero byte? */ emit_byte_s(state, 0, return FALSE); } put_buffer <<= 8; put_bits -= 8; } state->cur.put_buffer = put_buffer; /* update state variables */ state->cur.put_bits = put_bits; return TRUE; } INLINE LOCAL(void) emit_bits_e (huff_entropy_ptr entropy, unsigned int code, int size) /* Emit some bits, unless we are in gather mode */ { /* This routine is heavily used, so it's worth coding tightly. */ register INT32 put_buffer; register int put_bits; /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); if (entropy->gather_statistics) return; /* do nothing if we're only getting stats */ /* mask off any extra bits in code */ put_buffer = ((INT32) code) & ((((INT32) 1) << size) - 1); /* new number of bits in buffer */ put_bits = size + entropy->saved.put_bits; put_buffer <<= 24 - put_bits; /* align incoming bits */ /* and merge with old buffer contents */ put_buffer |= entropy->saved.put_buffer; while (put_bits >= 8) { int c = (int) ((put_buffer >> 16) & 0xFF); emit_byte_e(entropy, c); if (c == 0xFF) { /* need to stuff a zero byte? */ emit_byte_e(entropy, 0); } put_buffer <<= 8; put_bits -= 8; } entropy->saved.put_buffer = put_buffer; /* update variables */ entropy->saved.put_bits = put_bits; } LOCAL(boolean) flush_bits_s (working_state * state) { if (! emit_bits_s(state, 0x7F, 7)) /* fill any partial byte with ones */ return FALSE; state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ state->cur.put_bits = 0; return TRUE; } LOCAL(void) flush_bits_e (huff_entropy_ptr entropy) { emit_bits_e(entropy, 0x7F, 7); /* fill any partial byte with ones */ entropy->saved.put_buffer = 0; /* and reset bit-buffer to empty */ entropy->saved.put_bits = 0; } /* * Emit (or just count) a Huffman symbol. */ INLINE LOCAL(void) emit_dc_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) { if (entropy->gather_statistics) entropy->dc_count_ptrs[tbl_no][symbol]++; else { c_derived_tbl * tbl = entropy->dc_derived_tbls[tbl_no]; emit_bits_e(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); } } INLINE LOCAL(void) emit_ac_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) { if (entropy->gather_statistics) entropy->ac_count_ptrs[tbl_no][symbol]++; else { c_derived_tbl * tbl = entropy->ac_derived_tbls[tbl_no]; emit_bits_e(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); } } /* * Emit bits from a correction bit buffer. */ LOCAL(void) emit_buffered_bits (huff_entropy_ptr entropy, char * bufstart, unsigned int nbits) { if (entropy->gather_statistics) return; /* no real work */ while (nbits > 0) { emit_bits_e(entropy, (unsigned int) (*bufstart), 1); bufstart++; nbits--; } } /* * Emit any pending EOBRUN symbol. */ LOCAL(void) emit_eobrun (huff_entropy_ptr entropy) { register int temp, nbits; if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ temp = entropy->EOBRUN; nbits = 0; while ((temp >>= 1)) nbits++; /* safety check: shouldn't happen given limited correction-bit buffer */ if (nbits > 14) ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); emit_ac_symbol(entropy, entropy->ac_tbl_no, nbits << 4); if (nbits) emit_bits_e(entropy, entropy->EOBRUN, nbits); entropy->EOBRUN = 0; /* Emit any buffered correction bits */ emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); entropy->BE = 0; } } /* * Emit a restart marker & resynchronize predictions. */ LOCAL(boolean) emit_restart_s (working_state * state, int restart_num) { int ci; if (! flush_bits_s(state)) return FALSE; emit_byte_s(state, 0xFF, return FALSE); emit_byte_s(state, JPEG_RST0 + restart_num, return FALSE); /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) state->cur.last_dc_val[ci] = 0; /* The restart counter is not updated until we successfully write the MCU. */ return TRUE; } LOCAL(void) emit_restart_e (huff_entropy_ptr entropy, int restart_num) { int ci; emit_eobrun(entropy); if (! entropy->gather_statistics) { flush_bits_e(entropy); emit_byte_e(entropy, 0xFF); emit_byte_e(entropy, JPEG_RST0 + restart_num); } if (entropy->cinfo->Ss == 0) { /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) entropy->saved.last_dc_val[ci] = 0; } else { /* Re-initialize all AC-related fields to 0 */ entropy->EOBRUN = 0; entropy->BE = 0; } } /* * MCU encoding for DC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; register int temp, temp2; register int nbits; int max_coef_bits; int blkn, ci, tbl; ISHIFT_TEMPS entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; /* Emit restart marker if needed */ if (cinfo->restart_interval) if (entropy->restarts_to_go == 0) emit_restart_e(entropy, entropy->next_restart_num); /* Since we're encoding a difference, the range limit is twice as much. */ max_coef_bits = cinfo->data_precision + 3; /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; /* Compute the DC value after the required point transform by Al. * This is simply an arithmetic right shift. */ temp = IRIGHT_SHIFT((int) (MCU_data[blkn][0][0]), cinfo->Al); /* DC differences are figured on the point-transformed values. */ if ((temp2 = temp - entropy->saved.last_dc_val[ci]) == 0) { /* Count/emit the Huffman-coded symbol for the number of bits */ emit_dc_symbol(entropy, tbl, 0); continue; } entropy->saved.last_dc_val[ci] = temp; /* Encode the DC coefficient difference per section G.1.2.1 */ if ((temp = temp2) < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative input, want temp2 = bitwise complement of abs(input) */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; do nbits++; /* there must be at least one 1 bit */ while ((temp >>= 1)); /* Check for out-of-range coefficient values */ if (nbits > max_coef_bits) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count/emit the Huffman-coded symbol for the number of bits */ emit_dc_symbol(entropy, tbl, nbits); /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ emit_bits_e(entropy, (unsigned int) temp2, nbits); } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; /* Update restart-interval state too */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } return TRUE; } /* * MCU encoding for AC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; const int * natural_order; JBLOCKROW block; register int temp, temp2; register int nbits; register int r, k; int Se, Al, max_coef_bits; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; /* Emit restart marker if needed */ if (cinfo->restart_interval) if (entropy->restarts_to_go == 0) emit_restart_e(entropy, entropy->next_restart_num); Se = cinfo->Se; Al = cinfo->Al; natural_order = cinfo->natural_order; max_coef_bits = cinfo->data_precision + 2; /* Encode the MCU data block */ block = MCU_data[0]; /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ r = 0; /* r = run length of zeros */ for (k = cinfo->Ss; k <= Se; k++) { if ((temp = (*block)[natural_order[k]]) == 0) { r++; continue; } /* We must apply the point transform by Al. For AC coefficients this * is an integer division with rounding towards 0. To do this portably * in C, we shift after obtaining the absolute value; so the code is * interwoven with finding the abs value (temp) and output bits (temp2). */ if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* Apply the point transform, and watch out for case */ /* that nonzero coef is zero after point transform. */ if ((temp >>= Al) == 0) { r++; continue; } /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ temp2 = ~temp; } else { /* Apply the point transform, and watch out for case */ /* that nonzero coef is zero after point transform. */ if ((temp >>= Al) == 0) { r++; continue; } temp2 = temp; } /* Emit any pending EOBRUN */ if (entropy->EOBRUN > 0) emit_eobrun(entropy); /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { emit_ac_symbol(entropy, entropy->ac_tbl_no, 0xF0); r -= 16; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; do nbits++; /* there must be at least one 1 bit */ while ((temp >>= 1)); /* Check for out-of-range coefficient values */ if (nbits > max_coef_bits) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count/emit Huffman symbol for run length / number of bits */ emit_ac_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ emit_bits_e(entropy, (unsigned int) temp2, nbits); r = 0; /* reset zero run length */ } if (r > 0) { /* If there are trailing zeroes, */ entropy->EOBRUN++; /* count an EOB */ if (entropy->EOBRUN == 0x7FFF) emit_eobrun(entropy); /* force it out to avoid overflow */ } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; /* Update restart-interval state too */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } return TRUE; } /* * MCU encoding for DC successive approximation refinement scan. * Note: we assume such scans can be multi-component, * although the spec is not very clear on the point. */ METHODDEF(boolean) encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int Al, blkn; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; /* Emit restart marker if needed */ if (cinfo->restart_interval) if (entropy->restarts_to_go == 0) emit_restart_e(entropy, entropy->next_restart_num); Al = cinfo->Al; /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { /* We simply emit the Al'th bit of the DC coefficient value. */ emit_bits_e(entropy, (unsigned int) (MCU_data[blkn][0][0] >> Al), 1); } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; /* Update restart-interval state too */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } return TRUE; } /* * MCU encoding for AC successive approximation refinement scan. */ METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; const int * natural_order; JBLOCKROW block; register int temp; register int r, k; int Se, Al; int EOB; char *BR_buffer; unsigned int BR; int absvalues[DCTSIZE2]; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; /* Emit restart marker if needed */ if (cinfo->restart_interval) if (entropy->restarts_to_go == 0) emit_restart_e(entropy, entropy->next_restart_num); Se = cinfo->Se; Al = cinfo->Al; natural_order = cinfo->natural_order; /* Encode the MCU data block */ block = MCU_data[0]; /* It is convenient to make a pre-pass to determine the transformed * coefficients' absolute values and the EOB position. */ EOB = 0; for (k = cinfo->Ss; k <= Se; k++) { temp = (*block)[natural_order[k]]; /* We must apply the point transform by Al. For AC coefficients this * is an integer division with rounding towards 0. To do this portably * in C, we shift after obtaining the absolute value. */ if (temp < 0) temp = -temp; /* temp is abs value of input */ temp >>= Al; /* apply the point transform */ absvalues[k] = temp; /* save abs value for main pass */ if (temp == 1) EOB = k; /* EOB = index of last newly-nonzero coef */ } /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ r = 0; /* r = run length of zeros */ BR = 0; /* BR = count of buffered bits added now */ BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ for (k = cinfo->Ss; k <= Se; k++) { if ((temp = absvalues[k]) == 0) { r++; continue; } /* Emit any required ZRLs, but not if they can be folded into EOB */ while (r > 15 && k <= EOB) { /* emit any pending EOBRUN and the BE correction bits */ emit_eobrun(entropy); /* Emit ZRL */ emit_ac_symbol(entropy, entropy->ac_tbl_no, 0xF0); r -= 16; /* Emit buffered correction bits that must be associated with ZRL */ emit_buffered_bits(entropy, BR_buffer, BR); BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ BR = 0; } /* If the coef was previously nonzero, it only needs a correction bit. * NOTE: a straight translation of the spec's figure G.7 would suggest * that we also need to test r > 15. But if r > 15, we can only get here * if k > EOB, which implies that this coefficient is not 1. */ if (temp > 1) { /* The correction bit is the next bit of the absolute value. */ BR_buffer[BR++] = (char) (temp & 1); continue; } /* Emit any pending EOBRUN and the BE correction bits */ emit_eobrun(entropy); /* Count/emit Huffman symbol for run length / number of bits */ emit_ac_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); /* Emit output bit for newly-nonzero coef */ temp = ((*block)[natural_order[k]] < 0) ? 0 : 1; emit_bits_e(entropy, (unsigned int) temp, 1); /* Emit buffered correction bits that must be associated with this code */ emit_buffered_bits(entropy, BR_buffer, BR); BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ BR = 0; r = 0; /* reset zero run length */ } if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ entropy->EOBRUN++; /* count an EOB */ entropy->BE += BR; /* concat my correction bits to older ones */ /* We force out the EOB if we risk either: * 1. overflow of the EOB counter; * 2. overflow of the correction bit buffer during the next MCU. */ if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) emit_eobrun(entropy); } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; /* Update restart-interval state too */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } return TRUE; } /* Encode a single block's worth of coefficients */ LOCAL(boolean) encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, c_derived_tbl *dctbl, c_derived_tbl *actbl) { register int temp, temp2; register int nbits; register int r, k; int Se = state->cinfo->lim_Se; int max_coef_bits = state->cinfo->data_precision + 3; const int * natural_order = state->cinfo->natural_order; /* Encode the DC coefficient difference per section F.1.2.1 */ if ((temp = block[0] - last_dc_val) == 0) { /* Emit the Huffman-coded symbol for the number of bits */ if (! emit_bits_s(state, dctbl->ehufco[0], dctbl->ehufsi[0])) return FALSE; } else { if ((temp2 = temp) < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative input, want temp2 = bitwise complement of abs(input) */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; do nbits++; /* there must be at least one 1 bit */ while ((temp >>= 1)); /* Check for out-of-range coefficient values. * Since we're encoding a difference, the range limit is twice as much. */ if (nbits > max_coef_bits) ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); /* Emit the Huffman-coded symbol for the number of bits */ if (! emit_bits_s(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) return FALSE; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (! emit_bits_s(state, (unsigned int) temp2, nbits)) return FALSE; } /* Encode the AC coefficients per section F.1.2.2 */ r = 0; /* r = run length of zeros */ for (k = 1; k <= Se; k++) { if ((temp = block[natural_order[k]]) == 0) { r++; continue; } /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { if (! emit_bits_s(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) return FALSE; r -= 16; } if ((temp2 = temp) < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; do nbits++; /* there must be at least one 1 bit */ while ((temp >>= 1)); /* Check for out-of-range coefficient values. * Use ">=" instead of ">" so can use the * same one larger limit from DC check here. */ if (nbits >= max_coef_bits) ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); /* Emit Huffman symbol for run length / number of bits */ temp = (r << 4) + nbits; if (! emit_bits_s(state, actbl->ehufco[temp], actbl->ehufsi[temp])) return FALSE; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (! emit_bits_s(state, (unsigned int) temp2, nbits)) return FALSE; r = 0; /* reset zero run length */ } /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) if (! emit_bits_s(state, actbl->ehufco[0], actbl->ehufsi[0])) return FALSE; return TRUE; } /* * Encode and output one MCU's worth of Huffman-compressed coefficients. */ METHODDEF(boolean) encode_mcu_huff (j_compress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; working_state state; int blkn, ci; jpeg_component_info * compptr; /* Load up working state */ state.next_output_byte = cinfo->dest->next_output_byte; state.free_in_buffer = cinfo->dest->free_in_buffer; ASSIGN_STATE(state.cur, entropy->saved); state.cinfo = cinfo; /* Emit restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! emit_restart_s(&state, entropy->next_restart_num)) return FALSE; } /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; if (! encode_one_block(&state, MCU_data[blkn][0], state.cur.last_dc_val[ci], entropy->dc_derived_tbls[compptr->dc_tbl_no], entropy->ac_derived_tbls[compptr->ac_tbl_no])) return FALSE; /* Update last_dc_val */ state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; } /* Completed MCU, so update state */ cinfo->dest->next_output_byte = state.next_output_byte; cinfo->dest->free_in_buffer = state.free_in_buffer; ASSIGN_STATE(entropy->saved, state.cur); /* Update restart-interval state too */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } return TRUE; } /* * Finish up at the end of a Huffman-compressed scan. */ METHODDEF(void) finish_pass_huff (j_compress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; working_state state; if (cinfo->progressive_mode) { entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; /* Flush out any buffered data */ emit_eobrun(entropy); flush_bits_e(entropy); cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; } else { /* Load up working state ... flush_bits needs it */ state.next_output_byte = cinfo->dest->next_output_byte; state.free_in_buffer = cinfo->dest->free_in_buffer; ASSIGN_STATE(state.cur, entropy->saved); state.cinfo = cinfo; /* Flush out the last data */ if (! flush_bits_s(&state)) ERREXIT(cinfo, JERR_CANT_SUSPEND); /* Update state */ cinfo->dest->next_output_byte = state.next_output_byte; cinfo->dest->free_in_buffer = state.free_in_buffer; ASSIGN_STATE(entropy->saved, state.cur); } } /* * Huffman coding optimization. * * We first scan the supplied data and count the number of uses of each symbol * that is to be Huffman-coded. (This process MUST agree with the code above.) * Then we build a Huffman coding tree for the observed counts. * Symbols which are not needed at all for the particular image are not * assigned any code, which saves space in the DHT marker as well as in * the compressed data. */ /* Process a single block's worth of coefficients */ LOCAL(void) htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, long dc_counts[], long ac_counts[]) { register int temp; register int nbits; register int r, k; int Se = cinfo->lim_Se; int max_coef_bits = cinfo->data_precision + 3; const int * natural_order = cinfo->natural_order; /* Encode the DC coefficient difference per section F.1.2.1 */ if ((temp = block[0] - last_dc_val) == 0) { /* Count the Huffman symbol for the number of bits */ dc_counts[0]++; } else { if (temp < 0) temp = -temp; /* temp is abs value of input */ /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; do nbits++; /* there must be at least one 1 bit */ while ((temp >>= 1)); /* Check for out-of-range coefficient values. * Since we're encoding a difference, the range limit is twice as much. */ if (nbits > max_coef_bits) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count the Huffman symbol for the number of bits */ dc_counts[nbits]++; } /* Encode the AC coefficients per section F.1.2.2 */ r = 0; /* r = run length of zeros */ for (k = 1; k <= Se; k++) { if ((temp = block[natural_order[k]]) == 0) { r++; continue; } /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { ac_counts[0xF0]++; r -= 16; } if (temp < 0) temp = -temp; /* temp is abs value of input */ /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; do nbits++; /* there must be at least one 1 bit */ while ((temp >>= 1)); /* Check for out-of-range coefficient values. * Use ">=" instead of ">" so can use the * same one larger limit from DC check here. */ if (nbits >= max_coef_bits) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count Huffman symbol for run length / number of bits */ ac_counts[(r << 4) + nbits]++; r = 0; /* reset zero run length */ } /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) ac_counts[0]++; } /* * Trial-encode one MCU's worth of Huffman-compressed coefficients. * No data is actually output, so no suspension return is possible. */ METHODDEF(boolean) encode_mcu_gather (j_compress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int blkn, ci; jpeg_component_info * compptr; /* Take care of restart intervals if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) entropy->saved.last_dc_val[ci] = 0; /* Update restart state */ entropy->restarts_to_go = cinfo->restart_interval; } entropy->restarts_to_go--; } for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], entropy->dc_count_ptrs[compptr->dc_tbl_no], entropy->ac_count_ptrs[compptr->ac_tbl_no]); entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; } return TRUE; } /* * Generate the best Huffman code table for the given counts, fill htbl. * * The JPEG standard requires that no symbol be assigned a codeword of all * one bits (so that padding bits added at the end of a compressed segment * can't look like a valid code). Because of the canonical ordering of * codewords, this just means that there must be an unused slot in the * longest codeword length category. Section K.2 of the JPEG spec suggests * reserving such a slot by pretending that symbol 256 is a valid symbol * with count 1. In theory that's not optimal; giving it count zero but * including it in the symbol set anyway should give a better Huffman code. * But the theoretically better code actually seems to come out worse in * practice, because it produces more all-ones bytes (which incur stuffed * zero bytes in the final file). In any case the difference is tiny. * * The JPEG standard requires Huffman codes to be no more than 16 bits long. * If some symbols have a very small but nonzero probability, the Huffman tree * must be adjusted to meet the code length restriction. We currently use * the adjustment method suggested in JPEG section K.2. This method is *not* * optimal; it may not choose the best possible limited-length code. But * typically only very-low-frequency symbols will be given less-than-optimal * lengths, so the code is almost optimal. Experimental comparisons against * an optimal limited-length-code algorithm indicate that the difference is * microscopic --- usually less than a hundredth of a percent of total size. * So the extra complexity of an optimal algorithm doesn't seem worthwhile. */ LOCAL(void) jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) { #define MAX_CLEN 32 /* assumed maximum initial code length */ UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ int codesize[257]; /* codesize[k] = code length of symbol k */ int others[257]; /* next symbol in current branch of tree */ int c1, c2, i, j; UINT8 *p; long v; freq[256] = 1; /* make sure 256 has a nonzero count */ /* Including the pseudo-symbol 256 in the Huffman procedure guarantees * that no real symbol is given code-value of all ones, because 256 * will be placed last in the largest codeword category. * In the symbol list build procedure this element serves as sentinel * for the zero run loop. */ #ifndef DONT_USE_FANCY_HUFF_OPT /* Build list of symbols sorted in order of descending frequency */ /* This approach has several benefits (thank to John Korejwa for the idea): * 1. * If a codelength category is split during the length limiting procedure * below, the feature that more frequent symbols are assigned shorter * codewords remains valid for the adjusted code. * 2. * To reduce consecutive ones in a Huffman data stream (thus reducing the * number of stuff bytes in JPEG) it is preferable to follow 0 branches * (and avoid 1 branches) as much as possible. This is easily done by * assigning symbols to leaves of the Huffman tree in order of decreasing * frequency, with no secondary sort based on codelengths. * 3. * The symbol list can be built independently from the assignment of code * lengths by the Huffman procedure below. * Note: The symbol list build procedure must be performed first, because * the Huffman procedure assigning the codelengths clobbers the frequency * counts! */ /* Here we use the others array as a linked list of nonzero frequencies * to be sorted. Already sorted elements are removed from the list. */ /* Building list */ /* This item does not correspond to a valid symbol frequency and is used * as starting index. */ j = 256; for (i = 0;; i++) { if (freq[i] == 0) /* skip zero frequencies */ continue; if (i > 255) break; others[j] = i; /* this symbol value */ j = i; /* previous symbol value */ } others[j] = -1; /* mark end of list */ /* Sorting list */ p = htbl->huffval; while ((c1 = others[256]) >= 0) { v = freq[c1]; i = c1; /* first symbol value */ j = 256; /* pseudo symbol value for starting index */ while ((c2 = others[c1]) >= 0) { if (freq[c2] > v) { v = freq[c2]; i = c2; /* this symbol value */ j = c1; /* previous symbol value */ } c1 = c2; } others[j] = others[i]; /* remove this symbol i from list */ *p++ = (UINT8) i; } #endif /* DONT_USE_FANCY_HUFF_OPT */ /* This algorithm is explained in section K.2 of the JPEG standard */ MEMZERO(bits, SIZEOF(bits)); MEMZERO(codesize, SIZEOF(codesize)); for (i = 0; i < 257; i++) others[i] = -1; /* init links to empty */ /* Huffman's basic algorithm to assign optimal code lengths to symbols */ for (;;) { /* Find the smallest nonzero frequency, set c1 = its symbol */ /* In case of ties, take the larger symbol number */ c1 = -1; v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v) { v = freq[i]; c1 = i; } } /* Find the next smallest nonzero frequency, set c2 = its symbol */ /* In case of ties, take the larger symbol number */ c2 = -1; v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v && i != c1) { v = freq[i]; c2 = i; } } /* Done if we've merged everything into one frequency */ if (c2 < 0) break; /* Else merge the two counts/trees */ freq[c1] += freq[c2]; freq[c2] = 0; /* Increment the codesize of everything in c1's tree branch */ codesize[c1]++; while (others[c1] >= 0) { c1 = others[c1]; codesize[c1]++; } others[c1] = c2; /* chain c2 onto c1's tree branch */ /* Increment the codesize of everything in c2's tree branch */ codesize[c2]++; while (others[c2] >= 0) { c2 = others[c2]; codesize[c2]++; } } /* Now count the number of symbols of each code length */ for (i = 0; i <= 256; i++) { if (codesize[i]) { /* The JPEG standard seems to think that this can't happen, */ /* but I'm paranoid... */ if (codesize[i] > MAX_CLEN) ERREXIT(cinfo, JERR_HUFF_CLEN_OUTOFBOUNDS); bits[codesize[i]]++; } } /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure * Huffman procedure assigned any such lengths, we must adjust the coding. * Here is what the JPEG spec says about how this next bit works: * Since symbols are paired for the longest Huffman code, the symbols are * removed from this length category two at a time. The prefix for the pair * (which is one bit shorter) is allocated to one of the pair; then, * skipping the BITS entry for that prefix length, a code word from the next * shortest nonzero BITS entry is converted into a prefix for two code words * one bit longer. */ for (i = MAX_CLEN; i > 16; i--) { while (bits[i] > 0) { j = i - 2; /* find length of new prefix to be used */ while (bits[j] == 0) { if (j == 0) ERREXIT(cinfo, JERR_HUFF_CLEN_OUTOFBOUNDS); j--; } bits[i] -= 2; /* remove two symbols */ bits[i-1]++; /* one goes in this length */ bits[j+1] += 2; /* two new symbols in this length */ bits[j]--; /* symbol of this length is now a prefix */ } } /* Remove the count for the pseudo-symbol 256 from the largest codelength */ while (bits[i] == 0) /* find largest codelength still in use */ i--; bits[i]--; /* Return final symbol counts (only for lengths 0..16) */ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); #ifdef DONT_USE_FANCY_HUFF_OPT /* Return a list of the symbols sorted by code length */ /* Note: Due to the codelength changes made above, it can happen * that more frequent symbols are assigned longer codewords. */ p = htbl->huffval; for (i = 1; i <= MAX_CLEN; i++) { for (j = 0; j <= 255; j++) { if (codesize[j] == i) { *p++ = (UINT8) j; } } } #endif /* DONT_USE_FANCY_HUFF_OPT */ /* Set sent_table FALSE so updated table will be written to JPEG file. */ htbl->sent_table = FALSE; } /* * Finish up a statistics-gathering pass and create the new Huffman tables. */ METHODDEF(void) finish_pass_gather (j_compress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci, tbl; jpeg_component_info * compptr; JHUFF_TBL **htblptr; boolean did_dc[NUM_HUFF_TBLS]; boolean did_ac[NUM_HUFF_TBLS]; if (cinfo->progressive_mode) /* Flush out buffered data (all we care about is counting the EOB symbol) */ emit_eobrun(entropy); /* It's important not to apply jpeg_gen_optimal_table more than once * per table, because it clobbers the input frequency counts! */ MEMZERO(did_dc, SIZEOF(did_dc)); MEMZERO(did_ac, SIZEOF(did_ac)); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* DC needs no table for refinement scan */ if (cinfo->Ss == 0 && cinfo->Ah == 0) { tbl = compptr->dc_tbl_no; if (! did_dc[tbl]) { htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[tbl]); did_dc[tbl] = TRUE; } } /* AC needs no table when not present */ if (cinfo->Se) { tbl = compptr->ac_tbl_no; if (! did_ac[tbl]) { htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[tbl]); did_ac[tbl] = TRUE; } } } } /* * Initialize for a Huffman-compressed scan. * If gather_statistics is TRUE, we do not output anything during the scan, * just count the Huffman symbols used and generate Huffman code tables. */ METHODDEF(void) start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci, tbl; jpeg_component_info * compptr; if (gather_statistics) entropy->pub.finish_pass = finish_pass_gather; else entropy->pub.finish_pass = finish_pass_huff; if (cinfo->progressive_mode) { entropy->cinfo = cinfo; entropy->gather_statistics = gather_statistics; /* We assume jcmaster.c already validated the scan parameters. */ /* Select execution routine */ if (cinfo->Ah == 0) { if (cinfo->Ss == 0) entropy->pub.encode_mcu = encode_mcu_DC_first; else entropy->pub.encode_mcu = encode_mcu_AC_first; } else { if (cinfo->Ss == 0) entropy->pub.encode_mcu = encode_mcu_DC_refine; else { entropy->pub.encode_mcu = encode_mcu_AC_refine; /* AC refinement needs a correction bit buffer */ if (entropy->bit_buffer == NULL) entropy->bit_buffer = (char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, MAX_CORR_BITS * SIZEOF(char)); } } /* Initialize AC stuff */ entropy->ac_tbl_no = cinfo->cur_comp_info[0]->ac_tbl_no; entropy->EOBRUN = 0; entropy->BE = 0; } else { if (gather_statistics) entropy->pub.encode_mcu = encode_mcu_gather; else entropy->pub.encode_mcu = encode_mcu_huff; } for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* DC needs no table for refinement scan */ if (cinfo->Ss == 0 && cinfo->Ah == 0) { tbl = compptr->dc_tbl_no; if (gather_statistics) { /* Check for invalid table index */ /* (make_c_derived_tbl does this in the other path) */ if (tbl < 0 || tbl >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); /* Allocate and zero the statistics tables */ /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ if (entropy->dc_count_ptrs[tbl] == NULL) entropy->dc_count_ptrs[tbl] = (long *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 257 * SIZEOF(long)); MEMZERO(entropy->dc_count_ptrs[tbl], 257 * SIZEOF(long)); } else { /* Compute derived values for Huffman tables */ /* We may do this more than once for a table, but it's not expensive */ jpeg_make_c_derived_tbl(cinfo, TRUE, tbl, & entropy->dc_derived_tbls[tbl]); } /* Initialize DC predictions to 0 */ entropy->saved.last_dc_val[ci] = 0; } /* AC needs no table when not present */ if (cinfo->Se) { tbl = compptr->ac_tbl_no; if (gather_statistics) { if (tbl < 0 || tbl >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); if (entropy->ac_count_ptrs[tbl] == NULL) entropy->ac_count_ptrs[tbl] = (long *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 257 * SIZEOF(long)); MEMZERO(entropy->ac_count_ptrs[tbl], 257 * SIZEOF(long)); } else { jpeg_make_c_derived_tbl(cinfo, FALSE, tbl, & entropy->ac_derived_tbls[tbl]); } } } /* Initialize bit buffer to empty */ entropy->saved.put_buffer = 0; entropy->saved.put_bits = 0; /* Initialize restart stuff */ entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num = 0; } /* * Module initialization routine for Huffman entropy encoding. */ GLOBAL(void) jinit_huff_encoder (j_compress_ptr cinfo) { huff_entropy_ptr entropy; int i; entropy = (huff_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(huff_entropy_encoder)); cinfo->entropy = &entropy->pub; entropy->pub.start_pass = start_pass_huff; /* Mark tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; } if (cinfo->progressive_mode) entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ } fltk-1.4.3/jpeg/jcmaster.c0000644000175000017500000005474215004135251015522 0ustar albrechtalbrecht/* * jcmaster.c * * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2003-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains master control logic for the JPEG compressor. * These routines are concerned with parameter validation, initial setup, * and inter-pass control (determining the number of passes and the work * to be done in each pass). */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private state */ typedef enum { main_pass, /* input data, also do first output step */ huff_opt_pass, /* Huffman code optimization pass */ output_pass /* data output pass */ } c_pass_type; typedef struct { struct jpeg_comp_master pub; /* public fields */ c_pass_type pass_type; /* the type of the current pass */ int pass_number; /* # of passes completed */ int total_passes; /* total # of passes needed */ int scan_number; /* current index in scan_info[] */ } my_comp_master; typedef my_comp_master * my_master_ptr; /* * Support routines that do various essential calculations. */ LOCAL(void) initial_setup (j_compress_ptr cinfo) /* Do computations that are needed before master selection phase */ { int ci, ssize; jpeg_component_info *compptr; /* Sanity check on block_size */ if (cinfo->block_size < 1 || cinfo->block_size > 16) ERREXIT2(cinfo, JERR_BAD_DCTSIZE, cinfo->block_size, cinfo->block_size); /* Derive natural_order from block_size */ switch (cinfo->block_size) { case 2: cinfo->natural_order = jpeg_natural_order2; break; case 3: cinfo->natural_order = jpeg_natural_order3; break; case 4: cinfo->natural_order = jpeg_natural_order4; break; case 5: cinfo->natural_order = jpeg_natural_order5; break; case 6: cinfo->natural_order = jpeg_natural_order6; break; case 7: cinfo->natural_order = jpeg_natural_order7; break; default: cinfo->natural_order = jpeg_natural_order; } /* Derive lim_Se from block_size */ cinfo->lim_Se = cinfo->block_size < DCTSIZE ? cinfo->block_size * cinfo->block_size - 1 : DCTSIZE2-1; /* Sanity check on image dimensions */ if (cinfo->jpeg_height <= 0 || cinfo->jpeg_width <= 0 || cinfo->num_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); /* Make sure image isn't bigger than I can handle */ if ((long) cinfo->jpeg_height > (long) JPEG_MAX_DIMENSION || (long) cinfo->jpeg_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); /* Only 8 to 12 bits data precision are supported for DCT based JPEG */ if (cinfo->data_precision < 8 || cinfo->data_precision > 12) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo, JERR_BAD_SAMPLING); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Fill in the correct component_index value; don't rely on application */ compptr->component_index = ci; /* In selecting the actual DCT scaling for each component, we try to * scale down the chroma components via DCT scaling rather than downsampling. * This saves time if the downsampler gets to use 1:1 scaling. * Note this code adapts subsampling ratios which are powers of 2. */ ssize = 1; #ifdef DCT_SCALING_SUPPORTED if (! cinfo->raw_data_in) while (cinfo->min_DCT_h_scaled_size * ssize <= (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { ssize = ssize * 2; } #endif compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; ssize = 1; #ifdef DCT_SCALING_SUPPORTED if (! cinfo->raw_data_in) while (cinfo->min_DCT_v_scaled_size * ssize <= (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { ssize = ssize * 2; } #endif compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; /* We don't support DCT ratios larger than 2. */ if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_width * (long) compptr->h_samp_factor, (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_height * (long) compptr->v_samp_factor, (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_width * (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_height * (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* Don't need quantization scale after DCT, * until color conversion says otherwise. */ compptr->component_needed = FALSE; } /* Compute number of fully interleaved MCU rows (number of times that * main controller will call coefficient controller). */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_height, (long) (cinfo->max_v_samp_factor * cinfo->block_size)); } #ifdef C_MULTISCAN_FILES_SUPPORTED LOCAL(void) validate_script (j_compress_ptr cinfo) /* Verify that the scan script in cinfo->scan_info[] is valid; also * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. */ { const jpeg_scan_info * scanptr; int scanno, ncomps, ci, coefi, thisi; int Ss, Se, Ah, Al; boolean component_sent[MAX_COMPONENTS]; #ifdef C_PROGRESSIVE_SUPPORTED int * last_bitpos_ptr; int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; /* -1 until that coefficient has been seen; then last Al for it */ #endif if (cinfo->num_scans <= 0) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; * for progressive JPEG, no scan can have this. */ scanptr = cinfo->scan_info; if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { #ifdef C_PROGRESSIVE_SUPPORTED cinfo->progressive_mode = TRUE; last_bitpos_ptr = & last_bitpos[0][0]; for (ci = 0; ci < cinfo->num_components; ci++) for (coefi = 0; coefi < DCTSIZE2; coefi++) *last_bitpos_ptr++ = -1; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { cinfo->progressive_mode = FALSE; for (ci = 0; ci < cinfo->num_components; ci++) component_sent[ci] = FALSE; } for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { /* Validate component indexes */ ncomps = scanptr->comps_in_scan; if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); for (ci = 0; ci < ncomps; ci++) { thisi = scanptr->component_index[ci]; if (thisi < 0 || thisi >= cinfo->num_components) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); /* Components must appear in SOF order within each scan */ if (ci > 0 && thisi <= scanptr->component_index[ci-1]) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); } /* Validate progression parameters */ Ss = scanptr->Ss; Se = scanptr->Se; Ah = scanptr->Ah; Al = scanptr->Al; if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that * seems wrong: the upper bound ought to depend on data precision. * Perhaps they really meant 0..N+1 for N-bit precision. * Here we allow 0..10 for 8-bit data; Al larger than 10 results in * out-of-range reconstructed DC values during the first DC scan, * which might cause problems for some decoders. */ if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || Ah < 0 || Ah > (cinfo->data_precision > 8 ? 13 : 10) || Al < 0 || Al > (cinfo->data_precision > 8 ? 13 : 10)) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); if (Ss == 0) { if (Se != 0) /* DC and AC together not OK */ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } else { if (ncomps != 1) /* AC scans must be for only one component */ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } for (ci = 0; ci < ncomps; ci++) { last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); for (coefi = Ss; coefi <= Se; coefi++) { if (last_bitpos_ptr[coefi] < 0) { /* first scan of this coefficient */ if (Ah != 0) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } else { /* not first scan */ if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } last_bitpos_ptr[coefi] = Al; } } #endif } else { /* For sequential JPEG, all progression parameters must be these: */ if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); /* Make sure components are not sent twice */ for (ci = 0; ci < ncomps; ci++) { thisi = scanptr->component_index[ci]; if (component_sent[thisi]) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); component_sent[thisi] = TRUE; } } } /* Now verify that everything got sent. */ if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED /* For progressive mode, we only check that at least some DC data * got sent for each component; the spec does not require that all bits * of all coefficients be transmitted. Would it be wiser to enforce * transmission of all coefficient bits?? */ for (ci = 0; ci < cinfo->num_components; ci++) { if (last_bitpos[ci][0] < 0) ERREXIT(cinfo, JERR_MISSING_DATA); } #endif } else { for (ci = 0; ci < cinfo->num_components; ci++) { if (! component_sent[ci]) ERREXIT(cinfo, JERR_MISSING_DATA); } } } LOCAL(void) reduce_script (j_compress_ptr cinfo) /* Adapt scan script for use with reduced block size; * assume that script has been validated before. */ { jpeg_scan_info * scanptr; int idxout, idxin; /* Circumvent const declaration for this function */ scanptr = (jpeg_scan_info *) cinfo->scan_info; idxout = 0; for (idxin = 0; idxin < cinfo->num_scans; idxin++) { /* After skipping, idxout becomes smaller than idxin */ if (idxin != idxout) /* Copy rest of data; * note we stay in given chunk of allocated memory. */ scanptr[idxout] = scanptr[idxin]; if (scanptr[idxout].Ss > cinfo->lim_Se) /* Entire scan out of range - skip this entry */ continue; if (scanptr[idxout].Se > cinfo->lim_Se) /* Limit scan to end of block */ scanptr[idxout].Se = cinfo->lim_Se; idxout++; } cinfo->num_scans = idxout; } #endif /* C_MULTISCAN_FILES_SUPPORTED */ LOCAL(void) select_scan_parameters (j_compress_ptr cinfo) /* Set up the scan parameters for the current scan */ { int ci; #ifdef C_MULTISCAN_FILES_SUPPORTED if (cinfo->scan_info != NULL) { /* Prepare for current scan --- the script is already validated */ my_master_ptr master = (my_master_ptr) cinfo->master; const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; cinfo->comps_in_scan = scanptr->comps_in_scan; for (ci = 0; ci < scanptr->comps_in_scan; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[scanptr->component_index[ci]]; } if (cinfo->progressive_mode) { cinfo->Ss = scanptr->Ss; cinfo->Se = scanptr->Se; cinfo->Ah = scanptr->Ah; cinfo->Al = scanptr->Al; return; } } else #endif { /* Prepare for single sequential-JPEG scan containing all components */ if (cinfo->num_components > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPS_IN_SCAN); cinfo->comps_in_scan = cinfo->num_components; for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; } } cinfo->Ss = 0; cinfo->Se = cinfo->block_size * cinfo->block_size - 1; cinfo->Ah = 0; cinfo->Al = 0; } LOCAL(void) per_scan_setup (j_compress_ptr cinfo) /* Do computations that are needed before processing a JPEG scan */ /* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ { int ci, mcublks, tmp; jpeg_component_info *compptr; if (cinfo->comps_in_scan == 1) { /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; /* Overall image size in MCUs */ cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; compptr->MCU_sample_width = compptr->DCT_h_scaled_size; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height * as the number of block rows present in the last iMCU row. */ tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (tmp == 0) tmp = compptr->v_samp_factor; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; } else { /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, MAX_COMPS_IN_SCAN); /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_width, (long) (cinfo->max_h_samp_factor * cinfo->block_size)); cinfo->MCU_rows_in_scan = cinfo->total_iMCU_rows; cinfo->blocks_in_MCU = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Sampling factors give # of blocks of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_h_scaled_size; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = tmp; tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); if (tmp == 0) tmp = compptr->MCU_height; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } } /* Convert restart specified in rows to actual MCU count. */ /* Note that count must fit in 16 bits, so we provide limiting. */ if (cinfo->restart_in_rows > 0) { long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); } } /* * Per-pass setup. * This is called at the beginning of each pass. We determine which modules * will be active during this pass and give them appropriate start_pass calls. * We also set is_last_pass to indicate whether any more passes will be * required. */ METHODDEF(void) prepare_for_pass (j_compress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; switch (master->pass_type) { case main_pass: /* Initial pass: will collect input data, and do either Huffman * optimization or data output for the first scan. */ select_scan_parameters(cinfo); per_scan_setup(cinfo); if (! cinfo->raw_data_in) { (*cinfo->cconvert->start_pass) (cinfo); (*cinfo->downsample->start_pass) (cinfo); (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); } (*cinfo->fdct->start_pass) (cinfo); (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); (*cinfo->coef->start_pass) (cinfo, (master->total_passes > 1 ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); if (cinfo->optimize_coding) { /* No immediate data output; postpone writing frame/scan headers */ master->pub.call_pass_startup = FALSE; } else { /* Will write frame/scan headers at first jpeg_write_scanlines call */ master->pub.call_pass_startup = TRUE; } break; #ifdef ENTROPY_OPT_SUPPORTED case huff_opt_pass: /* Do Huffman optimization for a scan after the first one. */ select_scan_parameters(cinfo); per_scan_setup(cinfo); if (cinfo->Ss != 0 || cinfo->Ah == 0) { (*cinfo->entropy->start_pass) (cinfo, TRUE); (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); master->pub.call_pass_startup = FALSE; break; } /* Special case: Huffman DC refinement scans need no Huffman table * and therefore we can skip the optimization pass for them. */ master->pass_type = output_pass; master->pass_number++; /*FALLTHROUGH*/ #endif case output_pass: /* Do a data-output pass. */ /* We need not repeat per-scan setup if prior optimization pass did it. */ if (! cinfo->optimize_coding) { select_scan_parameters(cinfo); per_scan_setup(cinfo); } (*cinfo->entropy->start_pass) (cinfo, FALSE); (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); /* We emit frame/scan headers now */ if (master->scan_number == 0) (*cinfo->marker->write_frame_header) (cinfo); (*cinfo->marker->write_scan_header) (cinfo); master->pub.call_pass_startup = FALSE; break; default: ERREXIT(cinfo, JERR_NOT_COMPILED); } master->pub.is_last_pass = (master->pass_number == master->total_passes-1); /* Set up progress monitor's pass info if present */ if (cinfo->progress != NULL) { cinfo->progress->completed_passes = master->pass_number; cinfo->progress->total_passes = master->total_passes; } } /* * Special start-of-pass hook. * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. * In single-pass processing, we need this hook because we don't want to * write frame/scan headers during jpeg_start_compress; we want to let the * application write COM markers etc. between jpeg_start_compress and the * jpeg_write_scanlines loop. * In multi-pass processing, this routine is not used. */ METHODDEF(void) pass_startup (j_compress_ptr cinfo) { cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ (*cinfo->marker->write_frame_header) (cinfo); (*cinfo->marker->write_scan_header) (cinfo); } /* * Finish up at end of pass. */ METHODDEF(void) finish_pass_master (j_compress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; /* The entropy coder always needs an end-of-pass call, * either to analyze statistics or to flush its output buffer. */ (*cinfo->entropy->finish_pass) (cinfo); /* Update state for next pass */ switch (master->pass_type) { case main_pass: /* next pass is either output of scan 0 (after optimization) * or output of scan 1 (if no optimization). */ master->pass_type = output_pass; if (! cinfo->optimize_coding) master->scan_number++; break; case huff_opt_pass: /* next pass is always output of current scan */ master->pass_type = output_pass; break; case output_pass: /* next pass is either optimization or output of next scan */ if (cinfo->optimize_coding) master->pass_type = huff_opt_pass; master->scan_number++; break; } master->pass_number++; } /* * Initialize master compression control. */ GLOBAL(void) jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) { my_master_ptr master; master = (my_master_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_comp_master)); cinfo->master = &master->pub; master->pub.prepare_for_pass = prepare_for_pass; master->pub.pass_startup = pass_startup; master->pub.finish_pass = finish_pass_master; master->pub.is_last_pass = FALSE; /* Validate parameters, determine derived values */ initial_setup(cinfo); if (cinfo->scan_info != NULL) { #ifdef C_MULTISCAN_FILES_SUPPORTED validate_script(cinfo); if (cinfo->block_size < DCTSIZE) reduce_script(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { cinfo->progressive_mode = FALSE; cinfo->num_scans = 1; } if (cinfo->optimize_coding) cinfo->arith_code = FALSE; /* disable arithmetic coding */ else if (! cinfo->arith_code && (cinfo->progressive_mode || (cinfo->block_size > 1 && cinfo->block_size < DCTSIZE))) /* TEMPORARY HACK ??? */ /* assume default tables no good for progressive or reduced AC mode */ cinfo->optimize_coding = TRUE; /* force Huffman optimization */ /* Initialize my private state */ if (transcode_only) { /* no main pass in transcoding */ if (cinfo->optimize_coding) master->pass_type = huff_opt_pass; else master->pass_type = output_pass; } else { /* for normal compression, first pass is always this type: */ master->pass_type = main_pass; } master->scan_number = 0; master->pass_number = 0; if (cinfo->optimize_coding) master->total_passes = cinfo->num_scans * 2; else master->total_passes = cinfo->num_scans; } fltk-1.4.3/jpeg/jcmainct.c0000644000175000017500000002267015004135251015475 0ustar albrechtalbrecht/* * jcmainct.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2003-2012 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the main buffer controller for compression. * The main buffer lies between the pre-processor and the JPEG * compressor proper; it holds downsampled data in the JPEG colorspace. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Note: currently, there is no operating mode in which a full-image buffer * is needed at this step. If there were, that mode could not be used with * "raw data" input, since this module is bypassed in that case. However, * we've left the code here for possible use in special applications. */ #undef FULL_MAIN_BUFFER_SUPPORTED /* Private buffer controller object */ typedef struct { struct jpeg_c_main_controller pub; /* public fields */ JDIMENSION cur_iMCU_row; /* number of current iMCU row */ JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ boolean suspended; /* remember if we suspended output */ J_BUF_MODE pass_mode; /* current operating mode */ /* If using just a strip buffer, this points to the entire set of buffers * (we allocate one for each component). In the full-image case, this * points to the currently accessible strips of the virtual arrays. */ JSAMPARRAY buffer[MAX_COMPONENTS]; #ifdef FULL_MAIN_BUFFER_SUPPORTED /* If using full-image storage, this array holds pointers to virtual-array * control blocks for each component. Unused if not full-image storage. */ jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; #endif } my_main_controller; typedef my_main_controller * my_main_ptr; /* Forward declarations */ METHODDEF(void) process_data_simple_main JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); #ifdef FULL_MAIN_BUFFER_SUPPORTED METHODDEF(void) process_data_buffer_main JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); #endif /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_main_ptr mainp = (my_main_ptr) cinfo->main; /* Do nothing in raw-data mode. */ if (cinfo->raw_data_in) return; mainp->cur_iMCU_row = 0; /* initialize counters */ mainp->rowgroup_ctr = 0; mainp->suspended = FALSE; mainp->pass_mode = pass_mode; /* save mode for use by process_data */ switch (pass_mode) { case JBUF_PASS_THRU: #ifdef FULL_MAIN_BUFFER_SUPPORTED if (mainp->whole_image[0] != NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif mainp->pub.process_data = process_data_simple_main; break; #ifdef FULL_MAIN_BUFFER_SUPPORTED case JBUF_SAVE_SOURCE: case JBUF_CRANK_DEST: case JBUF_SAVE_AND_PASS: if (mainp->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); mainp->pub.process_data = process_data_buffer_main; break; #endif default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } } /* * Process some data. * This routine handles the simple pass-through mode, * where we have only a strip buffer. */ METHODDEF(void) process_data_simple_main (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail) { my_main_ptr mainp = (my_main_ptr) cinfo->main; while (mainp->cur_iMCU_row < cinfo->total_iMCU_rows) { /* Read input data if we haven't filled the main buffer yet */ if (mainp->rowgroup_ctr < (JDIMENSION) cinfo->min_DCT_v_scaled_size) (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, mainp->buffer, &mainp->rowgroup_ctr, (JDIMENSION) cinfo->min_DCT_v_scaled_size); /* If we don't have a full iMCU row buffered, return to application for * more data. Note that preprocessor will always pad to fill the iMCU row * at the bottom of the image. */ if (mainp->rowgroup_ctr != (JDIMENSION) cinfo->min_DCT_v_scaled_size) return; /* Send the completed row to the compressor */ if (! (*cinfo->coef->compress_data) (cinfo, mainp->buffer)) { /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if * it happened to be the last row of the image, the application would * think we were done. */ if (! mainp->suspended) { (*in_row_ctr)--; mainp->suspended = TRUE; } return; } /* We did finish the row. Undo our little suspension hack if a previous * call suspended; then mark the main buffer empty. */ if (mainp->suspended) { (*in_row_ctr)++; mainp->suspended = FALSE; } mainp->rowgroup_ctr = 0; mainp->cur_iMCU_row++; } } #ifdef FULL_MAIN_BUFFER_SUPPORTED /* * Process some data. * This routine handles all of the modes that use a full-size buffer. */ METHODDEF(void) process_data_buffer_main (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail) { my_main_ptr mainp = (my_main_ptr) cinfo->main; int ci; jpeg_component_info *compptr; boolean writing = (mainp->pass_mode != JBUF_CRANK_DEST); while (mainp->cur_iMCU_row < cinfo->total_iMCU_rows) { /* Realign the virtual buffers if at the start of an iMCU row. */ if (mainp->rowgroup_ctr == 0) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { mainp->buffer[ci] = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, mainp->whole_image[ci], mainp->cur_iMCU_row * ((JDIMENSION) (compptr->v_samp_factor * cinfo->min_DCT_v_scaled_size)), (JDIMENSION) (compptr->v_samp_factor * cinfo->min_DCT_v_scaled_size), writing); } /* In a read pass, pretend we just read some source data. */ if (! writing) { *in_row_ctr += (JDIMENSION) (cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size); mainp->rowgroup_ctr = (JDIMENSION) cinfo->min_DCT_v_scaled_size; } } /* If a write pass, read input data until the current iMCU row is full. */ /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ if (writing) { (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, mainp->buffer, &mainp->rowgroup_ctr, (JDIMENSION) cinfo->min_DCT_v_scaled_size); /* Return to application if we need more data to fill the iMCU row. */ if (mainp->rowgroup_ctr < (JDIMENSION) cinfo->min_DCT_v_scaled_size) return; } /* Emit data, unless this is a sink-only pass. */ if (mainp->pass_mode != JBUF_SAVE_SOURCE) { if (! (*cinfo->coef->compress_data) (cinfo, mainp->buffer)) { /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if * it happened to be the last row of the image, the application would * think we were done. */ if (! mainp->suspended) { (*in_row_ctr)--; mainp->suspended = TRUE; } return; } /* We did finish the row. Undo our little suspension hack if a previous * call suspended; then mark the main buffer empty. */ if (mainp->suspended) { (*in_row_ctr)++; mainp->suspended = FALSE; } } /* If get here, we are done with this iMCU row. Mark buffer empty. */ mainp->rowgroup_ctr = 0; mainp->cur_iMCU_row++; } } #endif /* FULL_MAIN_BUFFER_SUPPORTED */ /* * Initialize main buffer controller. */ GLOBAL(void) jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_main_ptr mainp; int ci; jpeg_component_info *compptr; mainp = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); cinfo->main = &mainp->pub; mainp->pub.start_pass = start_pass_main; /* We don't need to create a buffer in raw-data mode. */ if (cinfo->raw_data_in) return; /* Create the buffer. It holds downsampled data, so each component * may be of a different size. */ if (need_full_buffer) { #ifdef FULL_MAIN_BUFFER_SUPPORTED /* Allocate a full-image virtual array for each component */ /* Note we pad the bottom to a multiple of the iMCU height */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { mainp->whole_image[ci] = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, compptr->width_in_blocks * ((JDIMENSION) compptr->DCT_h_scaled_size), ((JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor)) * ((JDIMENSION) cinfo->min_DCT_v_scaled_size), (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { #ifdef FULL_MAIN_BUFFER_SUPPORTED mainp->whole_image[0] = NULL; /* flag for no virtual arrays */ #endif /* Allocate a strip buffer for each component */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { mainp->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * ((JDIMENSION) compptr->DCT_h_scaled_size), (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); } } } fltk-1.4.3/jpeg/Makefile0000644000175000017500000000614615004135251015201 0ustar albrechtalbrecht# ************************************************************************* # FLTK - DO NOT CHANGE when upgrading the JPEG library, unless required. * # ************************************************************************* # # JPEG library makefile for the Fast Light Toolkit (FLTK). # # Copyright 1997-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # include ../makeinclude # # Object files... # OBJS = \ jaricom.o \ jcapimin.o \ jcapistd.o \ jcarith.o \ jccoefct.o \ jccolor.o \ jcdctmgr.o \ jchuff.o \ jcinit.o \ jcmainct.o \ jcmarker.o \ jcmaster.o \ jcomapi.o \ jcparam.o \ jcprepct.o \ jcsample.o \ jctrans.o \ jdapimin.o \ jdapistd.o \ jdarith.o \ jdatadst.o \ jdatasrc.o \ jdcoefct.o \ jdcolor.o \ jddctmgr.o \ jdhuff.o \ jdinput.o \ jdmainct.o \ jdmarker.o \ jdmaster.o \ jdmerge.o \ jdpostct.o \ jdsample.o \ jdtrans.o \ jerror.o \ jfdctflt.o \ jfdctfst.o \ jfdctint.o \ jidctflt.o \ jidctfst.o \ jidctint.o \ jmemmgr.o \ jmemnobs.o \ jquant1.o \ jquant2.o \ jutils.o LIBJPEG = ../lib/libfltk_jpeg$(LIBEXT) # # Make all targets... # all: $(LIBJPEG) # # Clean all targets and object files... # clean: $(RM) $(OBJS) $(RM) $(LIBJPEG) # # Install everything... # install: $(LIBJPEG) echo "Installing $(LIBJPEG) in $(libdir)..." -$(INSTALL_DIR) "$(DESTDIR)$(libdir)" $(INSTALL_LIB) $(LIBJPEG) "$(DESTDIR)$(libdir)" $(RANLIB) "$(DESTDIR)$(libdir)/libfltk_jpeg$(LIBEXT)" echo "Installing jpeg headers in $(includedir)/FL/images..." -$(INSTALL_DIR) "$(DESTDIR)$(includedir)/FL/images" $(INSTALL_DATA) jconfig.h "$(DESTDIR)$(includedir)/FL/images" $(INSTALL_DATA) jerror.h "$(DESTDIR)$(includedir)/FL/images" $(INSTALL_DATA) jmorecfg.h "$(DESTDIR)$(includedir)/FL/images" $(INSTALL_DATA) jpeglib.h "$(DESTDIR)$(includedir)/FL/images" $(INSTALL_DATA) fltk_jpeg_prefix.h "$(DESTDIR)$(includedir)/FL/images" # # Uninstall everything... # uninstall: echo "Uninstalling libfltk_jpeg$(LIBEXT) in $(libdir)..." $(RM) "$(libdir)/libfltk_jpeg$(LIBEXT)" echo "Uninstalling jpeg headers in $(includedir)/FL/images..." $(RM) "$(includedir)/FL/images/jconfig.h" $(RM) "$(includedir)/FL/images/jerror.h" $(RM) "$(includedir)/FL/images/jmorecfg.h" $(RM) "$(includedir)/FL/images/jpeglib.h" $(RM) "$(includedir)/FL/images/fltk_jpeg_prefix.h" # # libfltk_jpeg.a # $(LIBJPEG): $(OBJS) echo Archiving $@... $(RM) $@ $(LIBCOMMAND) $@ $(OBJS) $(RANLIB) $@ # # Make dependencies... # depend: $(OBJS:.o=.c) makedepend -Y -I.. -f makedepend -w 20 $(OBJS:.o=.c) echo "# DO NOT DELETE THIS LINE -- make depend depends on it." > makedepend.tmp echo "" >> makedepend.tmp grep '^[a-zA-Z]' makedepend | ( LC_ALL=C sort -u -f >> makedepend.tmp; ) mv makedepend.tmp makedepend include makedepend $(OBJS): ../makeinclude fltk-1.4.3/jpeg/jinclude.h0000644000175000017500000001334115004135251015502 0ustar albrechtalbrecht/* * jinclude.h * * Copyright (C) 1991-1994, Thomas G. Lane. * Modified 2017-2022 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file exists to provide a single place to fix any problems with * including the wrong system include files. (Common problems are taken * care of by the standard jconfig symbols, but on really weird systems * you may have to edit this file.) * * NOTE: this file is NOT intended to be included by applications using * the JPEG library. Most applications need only include jpeglib.h. */ /* Include auto-config file to find out which system include files we need. */ #include "jconfig.h" /* auto configuration options */ #define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ /* * We need the NULL macro and size_t typedef. * On an ANSI-conforming system it is sufficient to include . * Otherwise, we get them from or ; we may have to * pull in as well. * Note that the core JPEG library does not require ; * only the default error handler and data source/destination modules do. * But we must pull it in because of the references to FILE in jpeglib.h. * You can remove those references if you want to compile without . */ #ifdef HAVE_STDDEF_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef NEED_SYS_TYPES_H #include #endif #include /* * We need memory copying and zeroing functions, plus strncpy(). * ANSI and System V implementations declare these in . * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). * Some systems may declare memset and memcpy in . * * NOTE: we assume the size parameters to these functions are of type size_t. * Change the casts in these macros if not! */ #ifdef NEED_BSD_STRINGS #include #define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) #define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) #else /* not BSD, assume ANSI/SysV string lib */ #include #define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) #define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) #endif /* * In ANSI C, and indeed any rational implementation, size_t is also the * type returned by sizeof(). However, it seems there are some irrational * implementations out there, in which sizeof() returns an int even though * size_t is defined as long or unsigned long. To ensure consistent results * we always use this SIZEOF() macro in place of using sizeof() directly. */ #define SIZEOF(object) ((size_t) sizeof(object)) /* * The modules that use fread() and fwrite() always invoke them through * these macros. On some systems you may need to twiddle the argument casts. * CAUTION: argument order is different from underlying functions! * * Furthermore, macros are provided for fflush() and ferror() in order * to facilitate adaption by applications using an own FILE class. * * You can define your own custom file I/O functions in jconfig.h and * #define JPEG_HAVE_FILE_IO_CUSTOM there to prevent redefinition here. * * You can #define JPEG_USE_FILE_IO_CUSTOM in jconfig.h to use custom file * I/O functions implemented in Delphi VCL (Visual Component Library) * in Vcl.Imaging.jpeg.pas for the TJPEGImage component utilizing * the Delphi RTL (Run-Time Library) TMemoryStream component: * * procedure jpeg_stdio_src(var cinfo: jpeg_decompress_struct; * input_file: TStream); external; * * procedure jpeg_stdio_dest(var cinfo: jpeg_compress_struct; * output_file: TStream); external; * * function jfread(var buf; recsize, reccount: Integer; S: TStream): Integer; * begin * Result := S.Read(buf, recsize * reccount); * end; * * function jfwrite(const buf; recsize, reccount: Integer; S: TStream): Integer; * begin * Result := S.Write(buf, recsize * reccount); * end; * * function jfflush(S: TStream): Integer; * begin * Result := 0; * end; * * function jferror(S: TStream): Integer; * begin * Result := 0; * end; * * TMemoryStream of Delphi RTL has the distinctive feature to provide dynamic * memory buffer management with a file/stream-based interface, particularly for * the write (output) operation, which is easier to apply compared with direct * implementations as given in jdatadst.c for memory destination. Those direct * implementations of dynamic memory write tend to be more difficult to use, * so providing an option like TMemoryStream may be a useful alternative. * * The CFile/CMemFile classes of the Microsoft Foundation Class (MFC) Library * may be used in a similar fashion. */ #ifndef JPEG_HAVE_FILE_IO_CUSTOM #ifdef JPEG_USE_FILE_IO_CUSTOM extern size_t jfread(void * __ptr, size_t __size, size_t __n, FILE * __stream); extern size_t jfwrite(const void * __ptr, size_t __size, size_t __n, FILE * __stream); extern int jfflush(FILE * __stream); extern int jferror(FILE * __fp); #define JFREAD(file,buf,sizeofbuf) \ ((size_t) jfread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) #define JFWRITE(file,buf,sizeofbuf) \ ((size_t) jfwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) #define JFFLUSH(file) jfflush(file) #define JFERROR(file) jferror(file) #else #define JFREAD(file,buf,sizeofbuf) \ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) #define JFWRITE(file,buf,sizeofbuf) \ ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) #define JFFLUSH(file) fflush(file) #define JFERROR(file) ferror(file) #endif #endif fltk-1.4.3/jpeg/install.txt0000644000175000017500000016124515004135251015752 0ustar albrechtalbrechtINSTALLATION INSTRUCTIONS for the Independent JPEG Group's JPEG software Copyright (C) 1991-2023, Thomas G. Lane, Guido Vollbeding. This file is part of the Independent JPEG Group's software. For conditions of distribution and use, see the accompanying README file. This file explains how to configure and install the IJG software. We have tried to make this software extremely portable and flexible, so that it can be adapted to almost any environment. The downside of this decision is that the installation process is complicated. We have provided shortcuts to simplify the task on common systems. But in any case, you will need at least a little familiarity with C programming and program build procedures for your system. If you are only using this software as part of a larger program, the larger program's installation procedure may take care of configuring the IJG code. For example, Ghostscript's installation script will configure the IJG code. You don't need to read this file if you just want to compile Ghostscript. If you are on a Unix machine, you may not need to read this file at all. Try doing ./configure make make test If that doesn't complain, do make install (better do "make -n install" first to see if the makefile will put the files where you want them). Read further if you run into snags or want to customize the code for your system. TABLE OF CONTENTS ----------------- Before you start Configuring the software: using the automatic "configure" script using one of the supplied jconfig and makefile files by hand Building the software Testing the software Installing the software Optional stuff Optimization Hints for specific systems BEFORE YOU START ================ Before installing the software you must unpack the distributed source code. Since you are reading this file, you have probably already succeeded in this task. However, there is a potential for error if you needed to convert the files to the local standard text file format (for example, if you are on MS-DOS you may have converted LF end-of-line to CR/LF). You must apply such conversion to all the files EXCEPT those whose names begin with "test". The test files contain binary data; if you change them in any way then the self-test will give bad results. Please check the last section of this file to see if there are hints for the specific machine or compiler you are using. CONFIGURING THE SOFTWARE ======================== To configure the IJG code for your system, you need to create two files: * jconfig.h: contains values for system-dependent #define symbols. * Makefile: controls the compilation process. (On a non-Unix machine, you may create "project files" or some other substitute for a Makefile. jconfig.h is needed in any environment.) We provide three different ways to generate these files: * On a Unix system, you can just run the "configure" script. * We provide sample jconfig files and makefiles for popular machines; if your machine matches one of the samples, just copy the right sample files to jconfig.h and Makefile. * If all else fails, read the instructions below and make your own files. Configuring the software using the automatic "configure" script --------------------------------------------------------------- If you are on a Unix machine, you can just type ./configure and let the configure script construct appropriate configuration files. If you're using "csh" on an old version of System V, you might need to type sh configure instead to prevent csh from trying to execute configure itself. Expect configure to run for a few minutes, particularly on slower machines; it works by compiling a series of test programs. Configure was created with GNU Autoconf and it follows the usual conventions for GNU configure scripts. It makes a few assumptions that you may want to override. You can do this by providing optional switches to configure: * Configure will build both static and shared libraries, if possible. If you want to build libjpeg only as a static library, say ./configure --disable-shared If you want to build libjpeg only as a shared library, say ./configure --disable-static Configure uses GNU libtool to take care of system-dependent shared library building methods. * Configure will use gcc (GNU C compiler) if it's available, otherwise cc. To force a particular compiler to be selected, use the CC option, for example ./configure CC='cc' The same method can be used to include any unusual compiler switches. For example, on HP-UX you probably want to say ./configure CC='cc -Aa' to get HP's compiler to run in ANSI mode. * The default CFLAGS setting is "-g" for non-gcc compilers, "-g -O2" for gcc. You can override this by saying, for example, ./configure CFLAGS='-O2' if you want to compile without debugging support. * Configure will set up the makefile so that "make install" will install files into /usr/local/bin, /usr/local/man, etc. You can specify an installation prefix other than "/usr/local" by giving configure the option "--prefix=PATH". * If you don't have a lot of swap space, you may need to enable the IJG software's internal virtual memory mechanism. To do this, give the option "--enable-maxmem=N" where N is the default maxmemory limit in megabytes. This is discussed in more detail under "Selecting a memory manager", below. You probably don't need to worry about this on reasonably-sized Unix machines, unless you plan to process very large images. Configure has some other features that are useful if you are cross-compiling or working in a network of multiple machine types; but if you need those features, you probably already know how to use them. Configuring the software using one of the supplied jconfig and makefile files ----------------------------------------------------------------------------- If you have one of these systems, you can just use the provided configuration files: Makefile jconfig file System and/or compiler makefile.manx jconfig.manx Amiga, Manx Aztec C makefile.sas jconfig.sas Amiga, SAS C makeproj.mac jconfig.mac Apple Macintosh, Metrowerks CodeWarrior makefile.xc jconfig.xc Apple Mac, Xcode 15 mak*jpeg.st jconfig.st Atari ST/Mega/STE/TT/Falcon, Pure C or Turbo C makefile.bcc jconfig.bcc MS-DOS or OS/2, Borland C makefile.dj jconfig.dj MS-DOS, DJGPP (Delorie's port of GNU C) makefile.mc6 jconfig.mc6 MS-DOS, Microsoft C (16-bit only) makefile.wat jconfig.wat MS-DOS, OS/2, or Windows NT, Watcom C makefile.vc jconfig.vc Windows, MS Visual C++ makefile.vs jconfig.vc Windows, MS Visual C++ 6 Developer Studio make*.vc6 makefile.vs jconfig.vc Windows, Visual Studio 2019-2022 version 16-17 make*.v16 makefile.b32 jconfig.vc Windows, C++Builder/RAD Studio 10.4-11 mak*jpeg.bcb makefile.b32 jconfig.vc Windows, Embarcadero C++ for Win32 (bcc32) makefile.c32 jconfig.vc Windows, Embarcadero C++ for Win32 (bcc32c) makefile.d32 makefile.x32 jconfig.vc Windows, Embarcadero C++ for Win32 (bcc32x) makefile.b64 jconfig.vc Windows, Embarcadero C++ for Win64 (bcc64) makefile.mms jconfig.vms Digital VMS, with MMS software makefile.vms jconfig.vms Digital VMS, without MMS software Copy the proper jconfig file to jconfig.h and the makefile to Makefile (or whatever your system uses as the standard makefile name). For more info see the appropriate system-specific hints section near the end of this file. Configuring the software by hand -------------------------------- First, generate a jconfig.h file. If you are moderately familiar with C, the comments in jconfig.txt should be enough information to do this; just copy jconfig.txt to jconfig.h and edit it appropriately. Otherwise, you may prefer to use the ckconfig.c program. You will need to compile and execute ckconfig.c by hand --- we hope you know at least enough to do that. ckconfig.c may not compile the first try (in fact, the whole idea is for it to fail if anything is going to). If you get compile errors, fix them by editing ckconfig.c according to the directions given in ckconfig.c. Once you get it to run, it will write a suitable jconfig.h file, and will also print out some advice about which makefile to use. You may also want to look at the canned jconfig files, if there is one for a system similar to yours. Second, select a makefile and copy it to Makefile (or whatever your system uses as the standard makefile name). The most generic makefiles we provide are makefile.ansi: if your C compiler supports function prototypes makefile.unix: if not. (You have function prototypes if ckconfig.c put "#define HAVE_PROTOTYPES" in jconfig.h.) You may want to start from one of the other makefiles if there is one for a system similar to yours. Look over the selected Makefile and adjust options as needed. In particular you may want to change the CC and CFLAGS definitions. For instance, if you are using GCC, set CC=gcc. If you had to use any compiler switches to get ckconfig.c to work, make sure the same switches are in CFLAGS. If you are on a system that doesn't use makefiles, you'll need to set up project files (or whatever you do use) to compile all the source files and link them into executable files cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom. See the file lists in any of the makefiles to find out which files go into each program. Note that the provided makefiles all make a "library" file libjpeg first, but you don't have to do that if you don't want to; the file lists identify which source files are actually needed for compression, decompression, or both. As a last resort, you can make a batch script that just compiles everything and links it all together; makefile.vms is an example of this (it's for VMS systems that have no make-like utility). Here are comments about some specific configuration decisions you'll need to make: Command line style ------------------ These programs can use a Unix-like command line style which supports redirection and piping, like this: cjpeg inputfile >outputfile cjpeg outputfile source program | cjpeg >outputfile The simpler "two file" command line style is just cjpeg inputfile outputfile You may prefer the two-file style, particularly if you don't have pipes. You MUST use two-file style on any system that doesn't cope well with binary data fed through stdin/stdout; this is true for some MS-DOS compilers, for example. If you're not on a Unix system, it's safest to assume you need two-file style. (But if your compiler provides either the Posix-standard fdopen() library routine or a Microsoft-compatible setmode() routine, you can safely use the Unix command line style, by defining USE_FDOPEN or USE_SETMODE respectively.) To use the two-file style, make jconfig.h say "#define TWO_FILE_COMMANDLINE". Selecting a memory manager -------------------------- The IJG code is capable of working on images that are too big to fit in main memory; data is swapped out to temporary files as necessary. However, the code to do this is rather system-dependent. We provide five different memory managers: * jmemansi.c This version uses the ANSI-standard library routine tmpfile(), which not all non-ANSI systems have. On some systems tmpfile() may put the temporary file in a non-optimal location; if you don't like what it does, use jmemname.c. * jmemname.c This version creates named temporary files. For anything except a Unix machine, you'll need to configure the select_file_name() routine appropriately; see the comments near the head of jmemname.c. If you use this version, define NEED_SIGNAL_CATCHER in jconfig.h to make sure the temp files are removed if the program is aborted. * jmemnobs.c (That stands for No Backing Store :-).) This will compile on almost any system, but it assumes you have enough main memory or virtual memory to hold the biggest images you work with. * jmemdos.c This should be used with most 16-bit MS-DOS compilers. See the system-specific notes about MS-DOS for more info. IMPORTANT: if you use this, define USE_MSDOS_MEMMGR in jconfig.h, and include the assembly file jmemdosa.asm in the programs. The supplied makefiles and jconfig files for 16-bit MS-DOS compilers already do both. * jmemmac.c Custom version for Apple Macintosh; see the system-specific notes for Macintosh for more info. To use a particular memory manager, change the SYSDEPMEM variable in your makefile to equal the corresponding object file name (for example, jmemansi.o or jmemansi.obj for jmemansi.c). If you have plenty of (real or virtual) main memory, just use jmemnobs.c. "Plenty" means about ten bytes for every pixel in the largest images you plan to process, so a lot of systems don't meet this criterion. If yours doesn't, try jmemansi.c first. If that doesn't compile, you'll have to use jmemname.c; be sure to adjust select_file_name() for local conditions. You may also need to change unlink() to remove() in close_backing_store(). Except with jmemnobs.c or jmemmac.c, you need to adjust the DEFAULT_MAX_MEM setting to a reasonable value for your system (either by adding a #define for DEFAULT_MAX_MEM to jconfig.h, or by adding a -D switch to the Makefile). This value limits the amount of data space the program will attempt to allocate. Code and static data space isn't counted, so the actual memory needs for cjpeg or djpeg are typically 100 to 150Kb more than the max-memory setting. Larger max-memory settings reduce the amount of I/O needed to process a large image, but too large a value can result in "insufficient memory" failures. On most Unix machines (and other systems with virtual memory), just set DEFAULT_MAX_MEM to several million and forget it. At the other end of the spectrum, for MS-DOS machines you probably can't go much above 300K to 400K. (On MS-DOS the value refers to conventional memory only. Extended/expanded memory is handled separately by jmemdos.c.) BUILDING THE SOFTWARE ===================== Now you should be able to compile the software. Just say "make" (or whatever's necessary to start the compilation). Have a cup of coffee. Here are some things that could go wrong: If your compiler complains about undefined structures, you should be able to shut it up by putting "#define INCOMPLETE_TYPES_BROKEN" in jconfig.h. If you have trouble with missing system include files or inclusion of the wrong ones, read jinclude.h. This shouldn't happen if you used configure or ckconfig.c to set up jconfig.h. There are a fair number of routines that do not use all of their parameters; some compilers will issue warnings about this, which you can ignore. There are also a few configuration checks that may give "unreachable code" warnings. Any other warning deserves investigation. If you don't have a getenv() library routine, define NO_GETENV. Also see the system-specific hints, below. TESTING THE SOFTWARE ==================== As a quick test of functionality we've included a small sample image in several forms: testorig.jpg Starting point for the djpeg tests. testimg.ppm The output of djpeg testorig.jpg testimg.gif The output of djpeg -gif testorig.jpg testimg.bmp The output of djpeg -bmp -colors 256 testorig.jpg testimg.jpg The output of cjpeg testimg.ppm testprog.jpg Progressive-mode equivalent of testorig.jpg. testimgp.jpg The output of cjpeg -progressive -optimize testimg.ppm (The first- and second-generation .jpg files aren't identical since the default compression parameters are lossy.) If you can generate duplicates of the testimg* files then you probably have working programs. With most of the makefiles, "make test" will perform the necessary comparisons. If you're using a makefile that doesn't provide the test option, run djpeg and cjpeg by hand and compare the output files to testimg* with whatever binary file comparison tool you have. The files should be bit-for-bit identical. If the programs complain "MAX_ALLOC_CHUNK is wrong, please fix", then you need to reduce MAX_ALLOC_CHUNK to a value that fits in type size_t. Try adding "#define MAX_ALLOC_CHUNK 65520L" to jconfig.h. A less likely configuration error is "ALIGN_TYPE is wrong, please fix": defining ALIGN_TYPE as long should take care of that one. If the cjpeg test run fails with "Missing Huffman code table entry", it's a good bet that you needed to define RIGHT_SHIFT_IS_UNSIGNED. Go back to the configuration step and run ckconfig.c. (This is a good plan for any other test failure, too.) If you are using Unix (one-file) command line style on a non-Unix system, it's a good idea to check that binary I/O through stdin/stdout actually works. You should get the same results from "djpeg out.ppm" as from "djpeg -outfile out.ppm testorig.jpg". Note that the makefiles all use the latter style and therefore do not exercise stdin/stdout! If this check fails, try recompiling with USE_SETMODE or USE_FDOPEN defined. If it still doesn't work, better use two-file style. If you chose a memory manager other than jmemnobs.c, you should test that temporary-file usage works. Try "djpeg -bmp -colors 256 -max 0 testorig.jpg" and make sure its output matches testimg.bmp. If you have any really large images handy, try compressing them with -optimize and/or decompressing with -colors 256 to make sure your DEFAULT_MAX_MEM setting is not too large. NOTE: this is far from an exhaustive test of the JPEG software; some modules, such as 1-pass color quantization, are not exercised at all. It's just a quick test to give you some confidence that you haven't missed something major. INSTALLING THE SOFTWARE ======================= Once you're done with the above steps, you can install the software by copying the executable files (cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom) to wherever you normally install programs. On Unix systems, you'll also want to put the man pages (cjpeg.1, djpeg.1, jpegtran.1, rdjpgcom.1, wrjpgcom.1) in the man-page directory. The pre-fab makefiles don't support this step since there's such a wide variety of installation procedures on different systems. If you generated a Makefile with the "configure" script, you can just say make install to install the programs and their man pages into the standard places. (You'll probably need to be root to do this.) We recommend first saying make -n install to see where configure thought the files should go. You may need to edit the Makefile, particularly if your system's conventions for man page filenames don't match what configure expects. If you want to install the IJG library itself, for use in compiling other programs besides ours, then you need to put the four include files jpeglib.h jerror.h jconfig.h jmorecfg.h into your include-file directory, and put the library file libjpeg.a (extension may vary depending on system) wherever library files go. If you generated a Makefile with "configure", it will do what it thinks is the right thing if you say make install-lib OPTIONAL STUFF ============== Progress monitor: If you like, you can #define PROGRESS_REPORT (in jconfig.h) to enable display of percent-done progress reports. The routine provided in cdjpeg.c merely prints percentages to stderr, but you can customize it to do something fancier. Utah RLE file format support: We distribute the software with support for RLE image files (Utah Raster Toolkit format) disabled, because the RLE support won't compile without the Utah library. If you have URT version 3.1 or later, you can enable RLE support as follows: 1. #define RLE_SUPPORTED in jconfig.h. 2. Add a -I option to CFLAGS in the Makefile for the directory containing the URT .h files (typically the "include" subdirectory of the URT distribution). 3. Add -L... -lrle to LDLIBS in the Makefile, where ... specifies the directory containing the URT "librle.a" file (typically the "lib" subdirectory of the URT distribution). Support for 9-bit to 12-bit deep pixel data: The IJG code currently allows 8, 9, 10, 11, or 12 bits sample data precision. (For color, this means 8 to 12 bits per channel, of course.) If you need to work with deeper than 8-bit data, you can compile the IJG code for 9-bit to 12-bit operation. To do so: 1. In jmorecfg.h, define BITS_IN_JSAMPLE as 9, 10, 11, or 12 rather than 8. 2. In jconfig.h, undefine BMP_SUPPORTED, RLE_SUPPORTED, and TARGA_SUPPORTED, because the code for those formats doesn't handle deeper than 8-bit data and won't even compile. (The PPM code does work, as explained below. The GIF code works too; it scales 8-bit GIF data to and from 12-bit depth automatically.) 3. Compile. Don't expect "make test" to pass, since the supplied test files are for 8-bit data. Currently, 9-bit to 12-bit support does not work on 16-bit-int machines. Run-time selection and conversion of data precision are currently not supported and may be added later. Exception: The transcoding part (jpegtran) supports all settings in a single instance, since it operates on the level of DCT coefficients and not sample values. The PPM reader (rdppm.c) can read deeper than 8-bit data from either text-format or binary-format PPM and PGM files. Binary-format PPM/PGM files which have a maxval greater than 255 are assumed to use 2 bytes per sample, MSB first (big-endian order). As of early 1995, 2-byte binary format is not officially supported by the PBMPLUS library, but it is expected that a future release of PBMPLUS will support it. Note that the PPM reader will read files of any maxval regardless of the BITS_IN_JSAMPLE setting; incoming data is automatically rescaled to maxval=MAXJSAMPLE as appropriate for the cjpeg bit depth. The PPM writer (wrppm.c) will normally write 2-byte binary PPM or PGM format, maxval=MAXJSAMPLE, when compiled with BITS_IN_JSAMPLE>8. Since this format is not yet widely supported, you can disable it by compiling wrppm.c with PPM_NORAWWORD defined; then the data is scaled down to 8 bits to make a standard 1-byte/sample PPM or PGM file. (Yes, this means still another copy of djpeg to keep around. But hopefully you won't need it for very long. Poskanzer's supposed to get that new PBMPLUS release out Real Soon Now.) Of course, if you are working with 9-bit to 12-bit data, you probably have it stored in some other, nonstandard format. In that case you'll probably want to write your own I/O modules to read and write your format. Note: The standard Huffman tables are only valid for 8-bit data precision. If you selected more than 8-bit data precision, cjpeg uses arithmetic coding by default. The Huffman encoder normally uses entropy optimization to compute usable tables for higher precision. Otherwise, you'll have to supply different default Huffman tables. Removing code: If you need to make a smaller version of the JPEG software, some optional functions can be removed at compile time. See the xxx_SUPPORTED #defines in jconfig.h and jmorecfg.h. If at all possible, we recommend that you leave in decoder support for all valid JPEG files, to ensure that you can read anyone's output. Taking out support for image file formats that you don't use is the most painless way to make the programs smaller. Another possibility is to remove some of the DCT methods: in particular, the "IFAST" method may not be enough faster than the others to be worth keeping on your machine. (If you do remove ISLOW or IFAST, be sure to redefine JDCT_DEFAULT or JDCT_FASTEST to a supported method, by adding a #define in jconfig.h.) OPTIMIZATION ============ Unless you own a Cray, you'll probably be interested in making the JPEG software go as fast as possible. This section covers some machine-dependent optimizations you may want to try. We suggest that before trying any of this, you first get the basic installation to pass the self-test step. Repeat the self-test after any optimization to make sure that you haven't broken anything. The integer DCT routines perform a lot of multiplications. These multiplications must yield 32-bit results, but none of their input values are more than 16 bits wide. On many machines, notably the 680x0 and 80x86 CPUs, a 16x16=>32 bit multiply instruction is faster than a full 32x32=>32 bit multiply. Unfortunately there is no portable way to specify such a multiplication in C, but some compilers can generate one when you use the right combination of casts. See the MULTIPLYxxx macro definitions in jdct.h. If your compiler makes "int" be 32 bits and "short" be 16 bits, defining SHORTxSHORT_32 is fairly likely to work. When experimenting with alternate definitions, be sure to test not only whether the code still works (use the self-test), but also whether it is actually faster --- on some compilers, alternate definitions may compute the right answer, yet be slower than the default. Timing cjpeg on a large PGM (grayscale) input file is the best way to check this, as the DCT will be the largest fraction of the runtime in that mode. (Note: some of the distributed compiler-specific jconfig files already contain #define switches to select appropriate MULTIPLYxxx definitions.) If your machine has sufficiently fast floating point hardware, you may find that the float DCT method is faster than the integer DCT methods, even after tweaking the integer multiply macros. In that case you may want to make the float DCT be the default method. (The only objection to this is that float DCT results may vary slightly across machines.) To do that, add "#define JDCT_DEFAULT JDCT_FLOAT" to jconfig.h. Even if you don't change the default, you should redefine JDCT_FASTEST, which is the method selected by djpeg's -fast switch. Don't forget to update the documentation files (usage.txt and/or cjpeg.1, djpeg.1) to agree with what you've done. If access to "short" arrays is slow on your machine, it may be a win to define type JCOEF as int rather than short. This will cost a good deal of memory though, particularly in some multi-pass modes, so don't do it unless you have memory to burn and short is REALLY slow. If your compiler can compile function calls in-line, make sure the INLINE macro in jmorecfg.h is defined as the keyword that marks a function inline-able. Some compilers have a switch that tells the compiler to inline any function it thinks is profitable (e.g., -finline-functions for gcc). Enabling such a switch is likely to make the compiled code bigger but faster. In general, it's worth trying the maximum optimization level of your compiler, and experimenting with any optional optimizations such as loop unrolling. (Unfortunately, far too many compilers have optimizer bugs ... be prepared to back off if the code fails self-test.) If you do any experimentation along these lines, please report the optimal settings to jpeg-info@ijg.org so we can mention them in future releases. Be sure to specify your machine and compiler version. HINTS FOR SPECIFIC SYSTEMS ========================== We welcome reports on changes needed for systems not mentioned here. Submit 'em to jpeg-info@ijg.org. Also, if configure or ckconfig.c is wrong about how to configure the JPEG software for your system, please let us know. Acorn RISC OS: (Thanks to Simon Middleton for these hints on compiling with Desktop C.) After renaming the files according to Acorn conventions, take a copy of makefile.ansi, change all occurrences of 'libjpeg.a' to 'libjpeg.o' and change these definitions as indicated: CFLAGS= -throwback -IC: -Wn LDLIBS=C:o.Stubs SYSDEPMEM=jmemansi.o LN=Link AR=LibFile -c -o Also add a new line '.c.o:; $(cc) $< $(cflags) -c -o $@'. Remove the lines '$(RM) libjpeg.o' and '$(AR2) libjpeg.o' and the 'jconfig.h' dependency section. Copy jconfig.txt to jconfig.h. Edit jconfig.h to define TWO_FILE_COMMANDLINE and CHAR_IS_UNSIGNED. Run the makefile using !AMU not !Make. If you want to use the 'clean' and 'test' makefile entries then you will have to fiddle with the syntax a bit and rename the test files. Amiga: SAS C 6.50 reportedly is too buggy to compile the IJG code properly. A patch to update to 6.51 is available from SAS or AmiNet FTP sites. The supplied config files are set up to use jmemname.c as the memory manager, with temporary files being created on the device named by "JPEGTMP:". Atari ST/Mega/STE/TT/Falcon: Copy the project files makcjpeg.st, makdjpeg.st, maktjpeg.st, and makljpeg.st to cjpeg.prj, djpeg.prj, jpegtran.prj, and libjpeg.prj respectively. The project files should work as-is with Pure C. For Turbo C, change library filenames "pc..." to "tc..." in each project file. Note that libjpeg.prj selects jmemansi.c as the recommended memory manager. You'll probably want to adjust the DEFAULT_MAX_MEM setting --- you want it to be a couple hundred K less than your normal free memory. Put "#define DEFAULT_MAX_MEM nnnn" into jconfig.h to do this. To use the 68881/68882 coprocessor for the floating point DCT, add the compiler option "-8" to the project files and replace pcfltlib.lib with pc881lib.lib in cjpeg.prj and djpeg.prj. Or if you don't have a coprocessor, you may prefer to remove the float DCT code by undefining DCT_FLOAT_SUPPORTED in jmorecfg.h (since without a coprocessor, the float code will be too slow to be useful). In that case, you can delete pcfltlib.lib from the project files. Note that you must make libjpeg.lib before making cjpeg.ttp, djpeg.ttp, or jpegtran.ttp. You'll have to perform the self-test by hand. We haven't bothered to include project files for rdjpgcom and wrjpgcom. Those source files should just be compiled by themselves; they don't depend on the JPEG library. You can use the default.prj project file of the Pure C distribution to make the programs. There is a bug in some older versions of the Turbo C library which causes the space used by temporary files created with "tmpfile()" not to be freed after an abnormal program exit. If you check your disk afterwards, you will find cluster chains that are allocated but not used by a file. This should not happen in cjpeg/djpeg/jpegtran, since we enable a signal catcher to explicitly close temp files before exiting. But if you use the JPEG library with your own code, be sure to supply a signal catcher, or else use a different system-dependent memory manager. Cray: Should you be so fortunate as to be running JPEG on a Cray YMP, there is a compiler bug in old versions of Cray's Standard C (prior to 3.1). If you still have an old compiler, you'll need to insert a line reading "#pragma novector" just before the loop for (i = 1; i <= (int) htbl->bits[l]; i++) huffsize[p++] = (char) l; in fix_huff_tbl (in V5beta1, line 204 of jchuff.c and line 176 of jdhuff.c). [This bug may or may not still occur with the current IJG code, but it's probably a dead issue anyway...] HP-UX: If you have HP-UX 7.05 or later with the "software development" C compiler, you should run the compiler in ANSI mode. If using the configure script, say ./configure CC='cc -Aa' (or -Ae if you prefer). If configuring by hand, use makefile.ansi and add "-Aa" to the CFLAGS line in the makefile. If you have a pre-7.05 system, or if you are using the non-ANSI C compiler delivered with a minimum HP-UX system, then you must use makefile.unix (and do NOT add -Aa); or just run configure without the CC option. On HP 9000 series 800 machines, the HP C compiler is buggy in revisions prior to A.08.07. If you get complaints about "not a typedef name", you'll have to use makefile.unix, or run configure without the CC option. Macintosh, generic comments: The supplied user-interface files (cjpeg.c, djpeg.c, etc) are set up to provide a Unix-style command line interface. You can use this interface on the Mac by means of the ccommand() library routine provided by Metrowerks CodeWarrior or Think C. This is only appropriate for testing the library, however; to make a user-friendly equivalent of cjpeg/djpeg you'd really want to develop a Mac-style user interface. There isn't a complete example available at the moment, but there are some helpful starting points: 1. Sam Bushell's free "To JPEG" applet provides drag-and-drop conversion to JPEG under System 7 and later. This only illustrates how to use the compression half of the library, but it does a very nice job of that part. The CodeWarrior source code is available from http://www.pobox.com/~jsam. 2. Jim Brunner prepared a Mac-style user interface for both compression and decompression. Unfortunately, it hasn't been updated since IJG v4, and the library's API has changed considerably since then. Still it may be of some help, particularly as a guide to compiling the IJG code under Think C. Jim's code is available from the Info-Mac archives, at sumex-aim.stanford.edu or mirrors thereof; see file /info-mac/dev/src/jpeg-convert-c.hqx. jmemmac.c is the recommended memory manager back end for Macintosh. It uses NewPtr/DisposePtr instead of malloc/free, and has a Mac-specific implementation of jpeg_mem_available(). It also creates temporary files that follow Mac conventions. (That part of the code relies on System-7-or-later OS functions. See the comments in jmemmac.c if you need to run it on System 6.) NOTE that USE_MAC_MEMMGR must be defined in jconfig.h to use jmemmac.c. You can also use jmemnobs.c, if you don't care about handling images larger than available memory. If you use any memory manager back end other than jmemmac.c, we recommend replacing "malloc" and "free" by "NewPtr" and "DisposePtr", because Mac C libraries often have peculiar implementations of malloc/free. (For instance, free() may not return the freed space to the Mac Memory Manager. This is undesirable for the IJG code because jmemmgr.c already clumps space requests.) Macintosh, Metrowerks CodeWarrior: The Unix-command-line-style interface can be used by defining USE_CCOMMAND. You'll also need to define TWO_FILE_COMMANDLINE to avoid stdin/stdout. This means that when using the cjpeg/djpeg programs, you'll have to type the input and output file names in the "Arguments" text-edit box, rather than using the file radio buttons. (Perhaps USE_FDOPEN or USE_SETMODE would eliminate the problem, but I haven't heard from anyone who's tried it.) On 680x0 Macs, Metrowerks defines type "double" as a 10-byte IEEE extended float. jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power of 2. Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint. The supplied configuration file jconfig.mac can be used for your jconfig.h; it includes all the recommended symbol definitions. If you have AppleScript installed, you can run the supplied script makeproj.mac to create CodeWarrior project files for the library and the testbed applications, then build the library and applications. (Thanks to Dan Sears and Don Agro for this nifty hack, which saves us from trying to maintain CodeWarrior project files as part of the IJG distribution...) Macintosh, Think C: The documentation in Jim Brunner's "JPEG Convert" source code (see above) includes detailed build instructions for Think C; it's probably somewhat out of date for the current release, but may be helpful. If you want to build the minimal command line version, proceed as follows. You'll have to prepare project files for the programs; we don't include any in the distribution since they are not text files. Use the file lists in any of the supplied makefiles as a guide. Also add the ANSI and Unix C libraries in a separate segment. You may need to divide the JPEG files into more than one segment; we recommend dividing compression and decompression modules. Define USE_CCOMMAND in jconfig.h so that the ccommand() routine is called. You must also define TWO_FILE_COMMANDLINE because stdin/stdout don't handle binary data correctly. On 680x0 Macs, Think C defines type "double" as a 12-byte IEEE extended float. jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power of 2. Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint. jconfig.mac should work as a jconfig.h configuration file for Think C, but the makeproj.mac AppleScript script is specific to CodeWarrior. Sorry. MIPS R3000: MIPS's cc version 1.31 has a rather nasty optimization bug. Don't use -O if you have that compiler version. (Use "cc -V" to check the version.) Note that the R3000 chip is found in workstations from DEC and others. MS-DOS, generic comments for 16-bit compilers: The IJG code is designed to work well in 80x86 "small" or "medium" memory models (i.e., data pointers are 16 bits unless explicitly declared "far"; code pointers can be either size). You may be able to use small model to compile cjpeg or djpeg by itself, but you will probably have to use medium model for any larger application. This won't make much difference in performance. You *will* take a noticeable performance hit if you use a large-data memory model, and you should avoid "huge" model if at all possible. Be sure that NEED_FAR_POINTERS is defined in jconfig.h if you use a small-data memory model; be sure it is NOT defined if you use a large-data model. (The supplied makefiles and jconfig files for Borland and Microsoft C compile in medium model and define NEED_FAR_POINTERS.) The DOS-specific memory manager, jmemdos.c, should be used if possible. It needs some assembly-code routines which are in jmemdosa.asm; make sure your makefile assembles that file and includes it in the library. If you don't have a suitable assembler, you can get pre-assembled object files for jmemdosa by FTP from ftp.uu.net:/graphics/jpeg/jdosaobj.zip. (DOS-oriented distributions of the IJG source code often include these object files.) When using jmemdos.c, jconfig.h must define USE_MSDOS_MEMMGR and must set MAX_ALLOC_CHUNK to less than 64K (65520L is a typical value). If your C library's far-heap malloc() can't allocate blocks that large, reduce MAX_ALLOC_CHUNK to whatever it can handle. If you can't use jmemdos.c for some reason --- for example, because you don't have an assembler to assemble jmemdosa.asm --- you'll have to fall back to jmemansi.c or jmemname.c. You'll probably still need to set MAX_ALLOC_CHUNK in jconfig.h, because most DOS C libraries won't malloc() more than 64K at a time. IMPORTANT: if you use jmemansi.c or jmemname.c, you will have to compile in a large-data memory model in order to get the right stdio library. Too bad. wrjpgcom needs to be compiled in large model, because it malloc()s a 64KB work area to hold the comment text. If your C library's malloc can't handle that, reduce MAX_COM_LENGTH as necessary in wrjpgcom.c. Most MS-DOS compilers treat stdin/stdout as text files, so you must use two-file command line style. But if your compiler has either fdopen() or setmode(), you can use one-file style if you like. To do this, define USE_SETMODE or USE_FDOPEN so that stdin/stdout will be set to binary mode. (USE_SETMODE seems to work with more DOS compilers than USE_FDOPEN.) You should test that I/O through stdin/stdout produces the same results as I/O to explicitly named files... the "make test" procedures in the supplied makefiles do NOT use stdin/stdout. MS-DOS, generic comments for 32-bit compilers: None of the above comments about memory models apply if you are using a 32-bit flat-memory-space environment, such as DJGPP or Watcom C. (And you should use one if you have it, as performance will be much better than 8086-compatible code!) For flat-memory-space compilers, do NOT define NEED_FAR_POINTERS, and do NOT use jmemdos.c. Use jmemnobs.c if the environment supplies adequate virtual memory, otherwise use jmemansi.c or jmemname.c. You'll still need to be careful about binary I/O through stdin/stdout. See the last paragraph of the previous section. MS-DOS, Borland C: Be sure to convert all the source files to DOS text format (CR/LF newlines). Although Borland C will often work OK with unmodified Unix (LF newlines) source files, sometimes it will give bogus compile errors. "Illegal character '#'" is the most common such error. (This is true with Borland C 3.1, but perhaps is fixed in newer releases.) If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE. jconfig.bcc already includes #define USE_SETMODE to make this work. (fdopen does not work correctly.) MS-DOS, Microsoft C: makefile.mc6 works with Microsoft C, DOS Visual C++, etc. It should only be used if you want to build a 16-bit (small or medium memory model) program. If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE. jconfig.mc6 already includes #define USE_SETMODE to make this work. (fdopen does not work correctly.) Note that this makefile assumes that the working copy of itself is called "makefile". If you want to call it something else, say "makefile.mak", be sure to adjust the dependency line that reads "$(RFILE) : makefile". Otherwise the make will fail because it doesn't know how to create "makefile". Worse, some releases of Microsoft's make utilities give an incorrect error message in this situation. Old versions of MS C fail with an "out of macro expansion space" error because they can't cope with the macro TRACEMS8 (defined in jerror.h). If this happens to you, the easiest solution is to change TRACEMS8 to expand to nothing. You'll lose the ability to dump out JPEG coefficient tables with djpeg -debug -debug, but at least you can compile. Original MS C 6.0 is very buggy; it compiles incorrect code unless you turn off optimization entirely (remove -O from CFLAGS). 6.00A is better, but it still generates bad code if you enable loop optimizations (-Ol or -Ox). MS C 8.0 crashes when compiling jquant1.c with optimization switch /Oo ... which is on by default. To work around this bug, compile that one file with /Oo-. Microsoft Windows (all versions), generic comments: Some Windows system include files define typedef boolean as "unsigned char". The IJG code also defines typedef boolean, but we make it an "enum" by default. This doesn't affect the IJG programs because we don't import those Windows include files. But if you use the JPEG library in your own program, and some of your program's files import one definition of boolean while some import the other, you can get all sorts of mysterious problems. A good preventive step is to make the IJG library use "unsigned char" for boolean. To do that, add something like this to your jconfig.h file: /* Define "boolean" as unsigned char, not enum, per Windows custom */ #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ typedef unsigned char boolean; #endif #ifndef FALSE /* in case these macros already exist */ #define FALSE 0 /* values of boolean */ #endif #ifndef TRUE #define TRUE 1 #endif #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ (This is already in jconfig.vc, by the way.) windef.h contains the declarations #define far #define FAR far Since jmorecfg.h tries to define FAR as empty, you may get a compiler warning if you include both jpeglib.h and windef.h (which windows.h includes). To suppress the warning, you can put "#ifndef FAR"/"#endif" around the line "#define FAR" in jmorecfg.h. (Something like this is already in jmorecfg.h, by the way.) When using the library in a Windows application, you will almost certainly want to modify or replace the error handler module jerror.c, since our default error handler does a couple of inappropriate things: 1. it tries to write error and warning messages on stderr; 2. in event of a fatal error, it exits by calling exit(). A simple stopgap solution for problem 1 is to replace the line fprintf(stderr, "%s\n", buffer); (in output_message in jerror.c) with MessageBox(GetActiveWindow(),buffer,"JPEG Error",MB_OK|MB_ICONERROR); It's highly recommended that you at least do that much, since otherwise error messages will disappear into nowhere. (Beginning with IJG v6b, this code is already present in jerror.c; just define USE_WINDOWS_MESSAGEBOX in jconfig.h to enable it.) The proper solution for problem 2 is to return control to your calling application after a library error. This can be done with the setjmp/longjmp technique discussed in libjpeg.txt and illustrated in example.c. (NOTE: some older Windows C compilers provide versions of setjmp/longjmp that don't actually work under Windows. You may need to use the Windows system functions Catch and Throw instead.) The recommended memory manager under Windows is jmemnobs.c; in other words, let Windows do any virtual memory management needed. You should NOT use jmemdos.c nor jmemdosa.asm under Windows. For Windows 3.1, we recommend compiling in medium or large memory model; for newer Windows versions, use a 32-bit flat memory model. (See the MS-DOS sections above for more info about memory models.) In the 16-bit memory models only, you'll need to put #define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ into jconfig.h to limit allocation chunks to 64Kb. (Without that, you'd have to use huge memory model, which slows things down unnecessarily.) jmemnobs.c works without modification in large or flat memory models, but to use medium model, you need to modify its jpeg_get_large and jpeg_free_large routines to allocate far memory. In any case, you might like to replace its calls to malloc and free with direct calls on Windows memory allocation functions. You may also want to modify jdatasrc.c and jdatadst.c to use Windows file operations rather than fread/fwrite. This is only necessary if your C compiler doesn't provide a competent implementation of C stdio functions. You might want to tweak the RGB_xxx macros in jmorecfg.h so that the library will accept or deliver color pixels in BGR sample order, not RGB; BGR order is usually more convenient under Windows. Note that this change will break the sample applications cjpeg/djpeg, but the library itself works fine. Many people want to convert the IJG library into a DLL. This is reasonably straightforward, but watch out for the following: 1. Don't try to compile as a DLL in small or medium memory model; use large model, or even better, 32-bit flat model. Many places in the IJG code assume the address of a local variable is an ordinary (not FAR) pointer; that isn't true in a medium-model DLL. 2. Microsoft C cannot pass file pointers between applications and DLLs. (See Microsoft Knowledge Base, PSS ID Number Q50336.) So jdatasrc.c and jdatadst.c don't work if you open a file in your application and then pass the pointer to the DLL. One workaround is to make jdatasrc.c/jdatadst.c part of your main application rather than part of the DLL. 3. You'll probably need to modify the macros GLOBAL() and EXTERN() to attach suitable linkage keywords to the exported routine names. Similarly, you'll want to modify METHODDEF() and JMETHOD() to ensure function pointers are declared in a way that lets application routines be called back through the function pointers. These macros are in jmorecfg.h. Typical definitions for a 16-bit DLL are: #define GLOBAL(type) type _far _pascal _loadds _export #define EXTERN(type) extern type _far _pascal _loadds #define METHODDEF(type) static type _far _pascal #define JMETHOD(type,methodname,arglist) \ type (_far _pascal *methodname) arglist For a 32-bit DLL you may want something like #define GLOBAL(type) __declspec(dllexport) type #define EXTERN(type) extern __declspec(dllexport) type Although not all the GLOBAL routines are actually intended to be called by the application, the performance cost of making them all DLL entry points is negligible. The unmodified IJG library presents a very C-specific application interface, so the resulting DLL is only usable from C or C++ applications. There has been some talk of writing wrapper code that would present a simpler interface usable from other languages, such as Visual Basic. This is on our to-do list but hasn't been very high priority --- any volunteers out there? Microsoft Windows, Borland C: The provided jconfig.bcc should work OK in a 32-bit Windows environment, but you'll need to tweak it in a 16-bit environment (you'd need to define NEED_FAR_POINTERS and MAX_ALLOC_CHUNK). Beware that makefile.bcc will need alteration if you want to use it for Windows --- in particular, you should use jmemnobs.c not jmemdos.c under Windows. Borland C++ 4.5 fails with an internal compiler error when trying to compile jdmerge.c in 32-bit mode. If enough people complain, perhaps Borland will fix it. In the meantime, the simplest known workaround is to add a redundant definition of the variable range_limit in h2v1_merged_upsample(), at the head of the block that handles odd image width (about line 268 in v6 jdmerge.c): /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { register JSAMPLE * range_limit = cinfo->sample_range_limit; /* ADD THIS */ cb = GETJSAMPLE(*inptr1); Pretty bizarre, especially since the very similar routine h2v2_merged_upsample doesn't trigger the bug. Recent reports suggest that this bug does not occur with "bcc32a" (the Pentium-optimized version of the compiler). Another report from a user of Borland C 4.5 was that incorrect code (leading to a color shift in processed images) was produced if any of the following optimization switch combinations were used: -Ot -Og -Ot -Op -Ot -Om So try backing off on optimization if you see such a problem. (Are there several different releases all numbered "4.5"??) Microsoft Windows, Microsoft Visual C++: jconfig.vc should work OK with any Microsoft compiler for a 32-bit memory model. makefile.vc is intended for command-line use. (If you are using the Developer Studio environment, you may prefer the DevStudio project files; see below.) IJG JPEG 7 adds extern "C" to jpeglib.h. This avoids the need to put extern "C" { ... } around #include "jpeglib.h" in your C++ application. You can also force VC++ to treat the library as C++ code by renaming all the *.c files to *.cpp (and adjusting the makefile to match). In this case you also need to define the symbol DONT_USE_EXTERN_C in the configuration to prevent jpeglib.h from using extern "C". Microsoft Windows, Microsoft Visual C++ 6 Developer Studio: We include makefiles that should work as project files in Developer Studio 6.0 or later. There is a library makefile that builds the IJG library as a static Win32 library, and application makefiles that build the sample applications as Win32 console applications. (Even if you only want the library, we recommend building the applications so that you can run the self-test.) To use: 1. Open the Windows Command Prompt, change to the source directory and execute the command line nmake /f makefile.vs setup-vc6 If you get an error message saying that the "nmake" command could not be found, execute the command "%ProgramFiles%\Microsoft Visual Studio\VC98\Bin\VCVARS32" to set the environment for using Microsoft Visual C++ tools, and repeat the nmake call. This will move jconfig.vc to jconfig.h and makefiles to project files. (Note that the renaming is critical!) Alternatively you can use nmake /f makefile.vs setupcopy-vc6 This will create renamed copies of the files, which allows to repeat the setup later. 2. Open the workspace file jpeg.dsw, build the library project. (If you are using Developer Studio more recent than 6.0, you'll probably get a message saying that the project files are being updated.) 3. Open the workspace file apps.dsw, build the application projects. 4. To perform the self-test, execute the command line nmake /f makefile.vs test-build 5. Move the application .exe files from the Release folder to an appropriate location on your path. Microsoft Windows, Microsoft Visual Studio 2019-2022 version 16-17: We include makefiles that should work as project files in Visual Studio 2019-2022 version 16-17 or later. There is a library makefile that builds the IJG library as a static Win32/x64/ARM/ARM64/ARM64EC library, and application makefiles that build the sample applications as Win32/x64/ARM/ARM64/ARM64EC console applications. (Even if you only want the library, we recommend building the applications so that you can run the self-test.) To use: 1. Ensure you’ve checked the item "Desktop development with C++" in the Workloads tab of Visual Studio Installer. Open the Developer Command Prompt for VS 2019-2022, change to the source directory and execute the command line nmake /f makefile.vs setup-v16 This will move jconfig.vc to jconfig.h and makefiles to project files. (Note that the renaming is critical!) Alternatively you can use nmake /f makefile.vs setupcopy-v16 This will create renamed copies of the files, which allows to repeat the setup later. 2. Open the solution file jpeg.sln, build the library project. a) If you are using Visual Studio more recent than 2022 version 17, you'll possibly get a message saying that the project files are being updated. b) If necessary, open the project properties and adapt the Windows Target Platform Version (or Windows SDK Version) in the Configuration Properties, General section. c) If you get a warning saying that a platform cannot be found, you can either * forgo the platform and ignore the warning, or * remove the platform in the Configuration Manager, or * install the corresponding platform build tools in Visual Studio Installer (Workloads tab Optional components or Individual components tab). d) If you want to build x64 code, change the platform setting from Win32 to x64. You can build Win32 and x64 versions side by side. e) If you want to build ARM/ARM64/ARM64EC code, change the platform setting to ARM/ARM64/ARM64EC. Ensure you’ve installed the ARM/ARM64/ARM64EC build tools in Visual Studio Installer (Workloads tab Optional components or Individual components tab). You can build Win32/x64/ARM/ARM64/ARM64EC versions side by side. 3. Open the solution file apps.sln, build the application projects. 4. To perform the self-test, execute the command line nmake /f makefile.vs test-32 for the Win32 build, or on a 64-bit system nmake /f makefile.vs test-64 for the x64 build. Note: test options for ARM code will be added as soon as Windows on ARM reference devices are available. To date there are no Windows on ARM reference devices available. 5. Move the application .exe files from the Release folder to an appropriate location on your path. Microsoft Windows, Embarcadero C++Builder/RAD Studio 10.4-11: We include makefiles that should work as project files in C++Builder/RAD Studio 10.4-11 or later. There is a library makefile that builds the IJG library as a static Win32/Win64 library, and application makefiles that build the sample applications as Win32/Win64 console applications. (Even if you only want the library, we recommend building the applications so that you can run the self-test.) To use: 1. Open the RAD Studio Command Prompt (or the standard Windows Command Prompt, since the environment is set system-wide during RAD Studio installation), change to the source directory and execute the command line make -fmakefile.b32 setup-cb This will move jconfig.vc to jconfig.h and makefiles to project files. (Note that the renaming is critical!) Alternatively you can use make -fmakefile.b32 setupcopy-cb This will create renamed copies of the files, which allows to repeat the setup later. (You can use one of the other makefiles .c32, .d32, .x32, or .b64 instead of .b32.) 2. Open the project file jpeg.cbproj, build the library project. a) By default, the classic Borland compiler (bcc32) is used for the Win32 build. To enable the Clang-based compiler for a specific project, select Project > Options > C++ Compiler and deselect the Use classic Borland compiler option. b) If you want to build Win64 code, change the platform setting from Windows 32 Bit to Windows 64 Bit. You can build Win32 and Win64 versions side by side. 3. Open the project group file apps.groupproj, build the application projects. 4. To perform the self-test, execute the command line make -fmakefile.b32 test-32 for the Win32 build, or on a 64-bit system make -fmakefile.b32 test-64 for the Win64 build. 5. Move the application .exe files from the Release folder to an appropriate location on your path. OS/2, Borland C++: Watch out for optimization bugs in older Borland compilers; you may need to back off the optimization switch settings. See the comments in makefile.bcc. SGI: On some SGI systems, you may need to set "AR2= ar -ts" in the Makefile. If you are using configure, you can do this by saying ./configure RANLIB='ar -ts' This change is not needed on all SGIs. Use it only if the make fails at the stage of linking the completed programs. On the MIPS R4000 architecture (Indy, etc.), the compiler option "-mips2" reportedly speeds up the float DCT method substantially, enough to make it faster than the default int method (but still slower than the fast int method). If you use -mips2, you may want to alter the default DCT method to be float. To do this, put "#define JDCT_DEFAULT JDCT_FLOAT" in jconfig.h. VMS: On an Alpha/VMS system with MMS, be sure to use the "/Marco=Alpha=1" qualifier with MMS when building the JPEG package. VAX/VMS v5.5-1 may have problems with the test step of the build procedure reporting differences when it compares the original and test images. If the error points to the last block of the files, it is most likely bogus and may be safely ignored. It seems to be because the files are Stream_LF and Backup/Compare has difficulty with the (presumably) null padded files. This problem was not observed on VAX/VMS v6.1 or AXP/VMS v6.1. fltk-1.4.3/jpeg/jcsample.c0000644000175000017500000004673615004135251015514 0ustar albrechtalbrecht/* * jcsample.c * * Copyright (C) 1991-1996, Thomas G. Lane. * Modified 2003-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains downsampling routines. * * Downsampling input data is counted in "row groups". A row group * is defined to be max_v_samp_factor pixel rows of each component, * from which the downsampler produces v_samp_factor sample rows. * A single row group is processed in each call to the downsampler module. * * The downsampler is responsible for edge-expansion of its output data * to fill an integral number of DCT blocks horizontally. The source buffer * may be modified if it is helpful for this purpose (the source buffer is * allocated wide enough to correspond to the desired output width). * The caller (the prep controller) is responsible for vertical padding. * * The downsampler may request "context rows" by setting need_context_rows * during startup. In this case, the input arrays will contain at least * one row group's worth of pixels above and below the passed-in data; * the caller will create dummy rows at image top and bottom by replicating * the first or last real pixel row. * * An excellent reference for image resampling is * Digital Image Warping, George Wolberg, 1990. * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. * * The downsampling algorithm used here is a simple average of the source * pixels covered by the output pixel. The hi-falutin sampling literature * refers to this as a "box filter". In general the characteristics of a box * filter are not very good, but for the specific cases we normally use (1:1 * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not * nearly so bad. If you intend to use other sampling ratios, you'd be well * advised to improve this code. * * A simple input-smoothing capability is provided. This is mainly intended * for cleaning up color-dithered GIF input files (if you find it inadequate, * we suggest using an external filtering program such as pnmconvol). When * enabled, each input pixel P is replaced by a weighted sum of itself and its * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, * where SF = (smoothing_factor / 1024). * Currently, smoothing is only supported for 2h2v sampling factors. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Pointer to routine to downsample a single component */ typedef JMETHOD(void, downsample1_ptr, (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data)); /* Private subobject */ typedef struct { struct jpeg_downsampler pub; /* public fields */ /* Downsampling method pointers, one per component */ downsample1_ptr methods[MAX_COMPONENTS]; /* Height of an output row group for each component. */ int rowgroup_height[MAX_COMPONENTS]; /* These arrays save pixel expansion factors so that int_downsample need not * recompute them each time. They are unused for other downsampling methods. */ UINT8 h_expand[MAX_COMPONENTS]; UINT8 v_expand[MAX_COMPONENTS]; } my_downsampler; typedef my_downsampler * my_downsample_ptr; /* * Initialize for a downsampling pass. */ METHODDEF(void) start_pass_downsample (j_compress_ptr cinfo) { /* no work for now */ } /* * Expand a component horizontally from width input_cols to width output_cols, * by duplicating the rightmost samples. */ LOCAL(void) expand_right_edge (JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols, JDIMENSION output_cols) { register JSAMPROW ptr; register JSAMPLE pixval; register int count; int row; int numcols = (int) (output_cols - input_cols); if (numcols > 0) { for (row = 0; row < num_rows; row++) { ptr = image_data[row] + input_cols; pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ for (count = numcols; count > 0; count--) *ptr++ = pixval; } } } /* * Do downsampling for a whole row group (all components). * * In this version we simply downsample each component independently. */ METHODDEF(void) sep_downsample (j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_index, JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) { my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; int ci; jpeg_component_info * compptr; JSAMPARRAY in_ptr, out_ptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { in_ptr = input_buf[ci] + in_row_index; out_ptr = output_buf[ci] + (out_row_group_index * downsample->rowgroup_height[ci]); (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); } } /* * Downsample pixel values of a single component. * One row group is processed per call. * This version handles arbitrary integral sampling ratios, without smoothing. * Note that this version is not actually used for customary sampling ratios. */ METHODDEF(void) int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; JSAMPROW inptr, outptr; INT32 outvalue; h_expand = downsample->h_expand[compptr->component_index]; v_expand = downsample->v_expand[compptr->component_index]; numpix = h_expand * v_expand; numpix2 = numpix/2; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * h_expand); inrow = outrow = 0; while (inrow < cinfo->max_v_samp_factor) { outptr = output_data[outrow]; for (outcol = 0, outcol_h = 0; outcol < output_cols; outcol++, outcol_h += h_expand) { outvalue = 0; for (v = 0; v < v_expand; v++) { inptr = input_data[inrow+v] + outcol_h; for (h = 0; h < h_expand; h++) { outvalue += (INT32) GETJSAMPLE(*inptr++); } } *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); } inrow += v_expand; outrow++; } } /* * Downsample pixel values of a single component. * This version handles the special case of a full-size component, * without smoothing. */ METHODDEF(void) fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { /* Copy the data */ jcopy_sample_rows(input_data, output_data, cinfo->max_v_samp_factor, cinfo->image_width); /* Edge-expand */ expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width, compptr->width_in_blocks * compptr->DCT_h_scaled_size); } /* * Downsample pixel values of a single component. * This version handles the common case of 2:1 horizontal and 1:1 vertical, * without smoothing. * * A note about the "bias" calculations: when rounding fractional values to * integer, we do not want to always round 0.5 up to the next integer. * If we did that, we'd introduce a noticeable bias towards larger values. * Instead, this code is arranged so that 0.5 will be rounded up or down at * alternate pixel locations (a simple ordered dither pattern). */ METHODDEF(void) h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow; JDIMENSION outcol; JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr, outptr; register int bias; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * 2); for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { outptr = output_data[inrow]; inptr = input_data[inrow]; bias = 0; /* bias = 0,1,0,1,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + bias) >> 1); bias ^= 1; /* 0=>1, 1=>0 */ inptr += 2; } } } /* * Downsample pixel values of a single component. * This version handles the standard case of 2:1 horizontal and 2:1 vertical, * without smoothing. */ METHODDEF(void) h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION outcol; JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr0, inptr1, outptr; register int bias; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * 2); inrow = outrow = 0; while (inrow < cinfo->max_v_samp_factor) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; bias = 1; /* bias = 1,2,1,2,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + bias) >> 2); bias ^= 3; /* 1=>2, 2=>1 */ inptr0 += 2; inptr1 += 2; } inrow += 2; outrow++; } } #ifdef INPUT_SMOOTHING_SUPPORTED /* * Downsample pixel values of a single component. * This version handles the standard case of 2:1 horizontal and 2:1 vertical, * with smoothing. One row of context is required. */ METHODDEF(void) h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION colctr; JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, cinfo->image_width, output_cols * 2); /* We don't bother to form the individual "smoothed" input pixel values; * we can directly compute the output which is the average of the four * smoothed values. Each of the four member pixels contributes a fraction * (1-8*SF) to its own smoothed image and a fraction SF to each of the three * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final * output. The four corner-adjacent neighbor pixels contribute a fraction * SF to just one smoothed pixel, or SF/4 to the final output; while the * eight edge-adjacent neighbors contribute SF to each of two smoothed * pixels, or SF/2 overall. In order to use integer arithmetic, these * factors are scaled by 2^16 = 65536. * Also recall that SF = smoothing_factor / 1024. */ memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ inrow = outrow = 0; while (inrow < cinfo->max_v_samp_factor) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; above_ptr = input_data[inrow-1]; below_ptr = input_data[inrow+2]; /* Special case for first column: pretend column -1 is same as column 0 */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); neighsum += neighsum; neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; for (colctr = output_cols - 2; colctr > 0; colctr--) { /* sum of pixels directly mapped to this output element */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); /* sum of edge-neighbor pixels */ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); /* The edge-neighbors count twice as much as corner-neighbors */ neighsum += neighsum; /* Add in the corner-neighbors */ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); /* form final output scaled up by 2^16 */ membersum = membersum * memberscale + neighsum * neighscale; /* round, descale and output it */ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; } /* Special case for last column */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); neighsum += neighsum; neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); membersum = membersum * memberscale + neighsum * neighscale; *outptr = (JSAMPLE) ((membersum + 32768) >> 16); inrow += 2; outrow++; } } /* * Downsample pixel values of a single component. * This version handles the special case of a full-size component, * with smoothing. One row of context is required. */ METHODDEF(void) fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow; JDIMENSION colctr; JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; int colsum, lastcolsum, nextcolsum; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, cinfo->image_width, output_cols); /* Each of the eight neighbor pixels contributes a fraction SF to the * smoothed pixel, while the main pixel contributes (1-8*SF). In order * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. * Also recall that SF = smoothing_factor / 1024. */ memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { outptr = output_data[inrow]; inptr = input_data[inrow]; above_ptr = input_data[inrow-1]; below_ptr = input_data[inrow+1]; /* Special case for first column */ colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + GETJSAMPLE(*inptr); membersum = GETJSAMPLE(*inptr++); nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(*inptr); neighsum = colsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; for (colctr = output_cols - 2; colctr > 0; colctr--) { membersum = GETJSAMPLE(*inptr++); above_ptr++; below_ptr++; nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(*inptr); neighsum = lastcolsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; } /* Special case for last column */ membersum = GETJSAMPLE(*inptr); neighsum = lastcolsum + (colsum - membersum) + colsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr = (JSAMPLE) ((membersum + 32768) >> 16); } } #endif /* INPUT_SMOOTHING_SUPPORTED */ /* * Module initialization routine for downsampling. * Note that we must select a routine for each component. */ GLOBAL(void) jinit_downsampler (j_compress_ptr cinfo) { my_downsample_ptr downsample; int ci; jpeg_component_info * compptr; boolean smoothok = TRUE; int h_in_group, v_in_group, h_out_group, v_out_group; downsample = (my_downsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_downsampler)); cinfo->downsample = &downsample->pub; downsample->pub.start_pass = start_pass_downsample; downsample->pub.downsample = sep_downsample; downsample->pub.need_context_rows = FALSE; if (cinfo->CCIR601_sampling) ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); /* Verify we can handle the sampling factors, and set up method pointers */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Compute size of an "output group" for DCT scaling. This many samples * are to be converted from max_h_samp_factor * max_v_samp_factor pixels. */ h_out_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / cinfo->min_DCT_h_scaled_size; v_out_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / cinfo->min_DCT_v_scaled_size; h_in_group = cinfo->max_h_samp_factor; v_in_group = cinfo->max_v_samp_factor; downsample->rowgroup_height[ci] = v_out_group; /* save for use later */ if (h_in_group == h_out_group && v_in_group == v_out_group) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { downsample->methods[ci] = fullsize_smooth_downsample; downsample->pub.need_context_rows = TRUE; } else #endif downsample->methods[ci] = fullsize_downsample; } else if (h_in_group == h_out_group * 2 && v_in_group == v_out_group) { smoothok = FALSE; downsample->methods[ci] = h2v1_downsample; } else if (h_in_group == h_out_group * 2 && v_in_group == v_out_group * 2) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { downsample->methods[ci] = h2v2_smooth_downsample; downsample->pub.need_context_rows = TRUE; } else #endif downsample->methods[ci] = h2v2_downsample; } else if ((h_in_group % h_out_group) == 0 && (v_in_group % v_out_group) == 0) { smoothok = FALSE; downsample->methods[ci] = int_downsample; downsample->h_expand[ci] = (UINT8) (h_in_group / h_out_group); downsample->v_expand[ci] = (UINT8) (v_in_group / v_out_group); } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); } #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor && !smoothok) TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); #endif } fltk-1.4.3/jpeg/jerror.c0000644000175000017500000001725215004135251015210 0ustar albrechtalbrecht/* * jerror.c * * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2012-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains simple error-reporting and trace-message routines. * These are suitable for Unix-like systems and others where writing to * stderr is the right thing to do. Many applications will want to replace * some or all of these routines. * * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, * you get a Windows-specific hack to display error messages in a dialog box. * It ain't much, but it beats dropping error messages into the bit bucket, * which is what happens to output to stderr under most Windows C compilers. * * These routines are used by both the compression and decompression code. */ #ifdef USE_WINDOWS_MESSAGEBOX #include #endif /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jversion.h" #include "jerror.h" #ifndef EXIT_FAILURE /* define exit() codes if not provided */ #define EXIT_FAILURE 1 #endif /* * Create the message string table. * We do this from the master message list in jerror.h by re-reading * jerror.h with a suitable definition for macro JMESSAGE. * The message table is made an external symbol just in case any applications * want to refer to it directly. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_std_message_table jMsgTable #endif #define JMESSAGE(code,string) string , const char * const jpeg_std_message_table[] = { #include "jerror.h" NULL }; /* * Error exit handler: must not return to caller. * * Applications may override this if they want to get control back after * an error. Typically one would longjmp somewhere instead of exiting. * The setjmp buffer can be made a private field within an expanded error * handler object. Note that the info needed to generate an error message * is stored in the error object, so you can generate the message now or * later, at your convenience. * You should make sure that the JPEG object is cleaned up (with jpeg_abort * or jpeg_destroy) at some point. */ METHODDEF(noreturn_t) error_exit (j_common_ptr cinfo) { /* Always display the message */ (*cinfo->err->output_message) (cinfo); /* Let the memory manager delete any temp files before we die */ jpeg_destroy(cinfo); exit(EXIT_FAILURE); } /* * Actual output of an error or trace message. * Applications may override this method to send JPEG messages somewhere * other than stderr. * * On Windows, printing to stderr is generally completely useless, * so we provide optional code to produce an error-dialog popup. * Most Windows applications will still prefer to override this routine, * but if they don't, it'll do something at least marginally useful. * * NOTE: to use the library in an environment that doesn't support the * C stdio library, you may have to delete the call to fprintf() entirely, * not just not use this routine. */ METHODDEF(void) output_message (j_common_ptr cinfo) { char buffer[JMSG_LENGTH_MAX]; /* Create the message */ (*cinfo->err->format_message) (cinfo, buffer); #ifdef USE_WINDOWS_MESSAGEBOX /* Display it in a message dialog box */ MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", MB_OK | MB_ICONERROR); #else /* Send it to stderr, adding a newline */ fprintf(stderr, "%s\n", buffer); #endif } /* * Decide whether to emit a trace or warning message. * msg_level is one of: * -1: recoverable corrupt-data warning, may want to abort. * 0: important advisory messages (always display to user). * 1: first level of tracing detail. * 2,3,...: successively more detailed tracing messages. * An application might override this method if it wanted to abort on warnings * or change the policy about which messages to display. */ METHODDEF(void) emit_message (j_common_ptr cinfo, int msg_level) { struct jpeg_error_mgr * err = cinfo->err; if (msg_level < 0) { /* It's a warning message. Since corrupt files may generate many warnings, * the policy implemented here is to show only the first warning, * unless trace_level >= 3. */ if (err->num_warnings == 0 || err->trace_level >= 3) (*err->output_message) (cinfo); /* Always count warnings in num_warnings. */ err->num_warnings++; } else { /* It's a trace message. Show it if trace_level >= msg_level. */ if (err->trace_level >= msg_level) (*err->output_message) (cinfo); } } /* * Format a message string for the most recent JPEG error or message. * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX * characters. Note that no '\n' character is added to the string. * Few applications should need to override this method. */ METHODDEF(void) format_message (j_common_ptr cinfo, char * buffer) { struct jpeg_error_mgr * err = cinfo->err; int msg_code = err->msg_code; const char * msgtext = NULL; const char * msgptr; char ch; boolean isstring; /* Look up message string in proper table */ if (msg_code > 0 && msg_code <= err->last_jpeg_message) { msgtext = err->jpeg_message_table[msg_code]; } else if (err->addon_message_table != NULL && msg_code >= err->first_addon_message && msg_code <= err->last_addon_message) { msgtext = err->addon_message_table[msg_code - err->first_addon_message]; } /* Defend against bogus message number */ if (msgtext == NULL) { err->msg_parm.i[0] = msg_code; msgtext = err->jpeg_message_table[0]; } /* Check for string parameter, as indicated by %s in the message text */ isstring = FALSE; msgptr = msgtext; while ((ch = *msgptr++) != '\0') { if (ch == '%') { if (*msgptr == 's') isstring = TRUE; break; } } /* Format the message into the passed buffer */ if (isstring) sprintf(buffer, msgtext, err->msg_parm.s); else sprintf(buffer, msgtext, err->msg_parm.i[0], err->msg_parm.i[1], err->msg_parm.i[2], err->msg_parm.i[3], err->msg_parm.i[4], err->msg_parm.i[5], err->msg_parm.i[6], err->msg_parm.i[7]); } /* * Reset error state variables at start of a new image. * This is called during compression startup to reset trace/error * processing to default state, without losing any application-specific * method pointers. An application might possibly want to override * this method if it has additional error processing state. */ METHODDEF(void) reset_error_mgr (j_common_ptr cinfo) { cinfo->err->num_warnings = 0; /* trace_level is not reset since it is an application-supplied parameter */ cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ } /* * Fill in the standard error-handling methods in a jpeg_error_mgr object. * Typical call is: * struct jpeg_compress_struct cinfo; * struct jpeg_error_mgr err; * * cinfo.err = jpeg_std_error(&err); * after which the application may override some of the methods. */ GLOBAL(struct jpeg_error_mgr *) jpeg_std_error (struct jpeg_error_mgr * err) { err->error_exit = error_exit; err->emit_message = emit_message; err->output_message = output_message; err->format_message = format_message; err->reset_error_mgr = reset_error_mgr; err->trace_level = 0; /* default = no tracing */ err->num_warnings = 0; /* no warnings emitted yet */ err->msg_code = 0; /* may be useful as a flag for "no error" */ /* Initialize message table pointers */ err->jpeg_message_table = jpeg_std_message_table; err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; err->addon_message_table = NULL; err->first_addon_message = 0; /* for safety */ err->last_addon_message = 0; return err; } fltk-1.4.3/jpeg/jerror.h0000644000175000017500000003437415004135251015221 0ustar albrechtalbrecht/* * jerror.h * * Copyright (C) 1994-1997, Thomas G. Lane. * Modified 1997-2018 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file defines the error and message codes for the JPEG library. * Edit this file to add new codes, or to translate the message strings to * some other language. * A set of error-reporting macros are defined too. Some applications using * the JPEG library may wish to include this file to get the error codes * and/or the macros. */ /* * To define the enum list of message codes, include this file without * defining macro JMESSAGE. To create a message string table, include it * again with a suitable JMESSAGE definition (see jerror.c for an example). */ #ifndef JMESSAGE #ifndef JERROR_H /* First time through, define the enum list */ #define JMAKE_ENUM_LIST #else /* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ #define JMESSAGE(code,string) #endif /* JERROR_H */ #endif /* JMESSAGE */ #ifdef JMAKE_ENUM_LIST typedef enum { #define JMESSAGE(code,string) code , #endif /* JMAKE_ENUM_LIST */ JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ /* For maintenance convenience, list is alphabetical by message code name */ JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") JMESSAGE(JERR_BAD_DROP_SAMPLING, "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") JMESSAGE(JERR_BAD_LIB_VERSION, "Wrong JPEG library version: library is %d, caller expects %d") JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") JMESSAGE(JERR_BAD_PROGRESSION, "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") JMESSAGE(JERR_BAD_PROG_SCRIPT, "Invalid progressive parameters at scan script entry %d") JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") JMESSAGE(JERR_BAD_STRUCT_SIZE, "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") JMESSAGE(JERR_EMS_READ, "Read from EMS failed") JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") JMESSAGE(JERR_FILE_READ, "Input file read error") JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") JMESSAGE(JERR_HUFF_CLEN_OUTOFBOUNDS, "Huffman code size table out of bounds") JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, "Cannot transcode due to multiple use of quantization table %d") JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") JMESSAGE(JERR_NOTIMPL, "Not implemented yet") JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") JMESSAGE(JERR_QUANT_COMPONENTS, "Cannot quantize more than %d color components") JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") JMESSAGE(JERR_SOF_BEFORE, "Invalid JPEG file structure: %s before SOF") JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") JMESSAGE(JERR_TFILE_WRITE, "Write failed on temporary file --- out of disk space?") JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") JMESSAGE(JERR_XMS_READ, "Read from XMS failed") JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) JMESSAGE(JMSG_VERSION, JVERSION) JMESSAGE(JTRC_16BIT_TABLES, "Caution: quantization tables are too coarse for baseline JPEG") JMESSAGE(JTRC_ADOBE, "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") JMESSAGE(JTRC_DRI, "Define Restart Interval %u") JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") JMESSAGE(JTRC_EOI, "End Of Image") JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, "Warning: thumbnail image size does not match data length %u") JMESSAGE(JTRC_JFIF_EXTENSION, "JFIF extension marker: type 0x%02x, length %u") JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") JMESSAGE(JTRC_RST, "RST%d") JMESSAGE(JTRC_SMOOTH_NOTIMPL, "Smoothing not supported with nonstandard sampling ratios") JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") JMESSAGE(JTRC_SOI, "Start of Image") JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") JMESSAGE(JTRC_THUMB_JPEG, "JFIF extension marker: JPEG-compressed thumbnail image, length %u") JMESSAGE(JTRC_THUMB_PALETTE, "JFIF extension marker: palette thumbnail image, length %u") JMESSAGE(JTRC_THUMB_RGB, "JFIF extension marker: RGB thumbnail image, length %u") JMESSAGE(JTRC_UNKNOWN_IDS, "Unrecognized component IDs %d %d %d, assuming YCbCr") JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") JMESSAGE(JWRN_BOGUS_PROGRESSION, "Inconsistent progression sequence for component %d coefficient %d") JMESSAGE(JWRN_EXTRANEOUS_DATA, "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") JMESSAGE(JWRN_MUST_RESYNC, "Corrupt JPEG data: found marker 0x%02x instead of RST%d") JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") #ifdef JMAKE_ENUM_LIST JMSG_LASTMSGCODE } J_MESSAGE_CODE; #undef JMAKE_ENUM_LIST #endif /* JMAKE_ENUM_LIST */ /* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ #undef JMESSAGE #ifndef JERROR_H #define JERROR_H /* Macros to simplify using the error and trace message stuff */ /* The first parameter is either type of cinfo pointer */ /* Fatal errors (print message and exit) */ #define ERREXIT(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT1(cinfo,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT2(cinfo,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT3(cinfo,code,p1,p2,p3) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (cinfo)->err->msg_parm.i[2] = (p3), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (cinfo)->err->msg_parm.i[2] = (p3), \ (cinfo)->err->msg_parm.i[3] = (p4), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (cinfo)->err->msg_parm.i[2] = (p3), \ (cinfo)->err->msg_parm.i[3] = (p4), \ (cinfo)->err->msg_parm.i[4] = (p5), \ (cinfo)->err->msg_parm.i[5] = (p6), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXITS(cinfo,code,str) \ ((cinfo)->err->msg_code = (code), \ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define MAKESTMT(stuff) do { stuff } while (0) /* Nonfatal errors (we can keep going, but the data is probably corrupt) */ #define WARNMS(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) #define WARNMS1(cinfo,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) #define WARNMS2(cinfo,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) /* Informational/debugging messages */ #define TRACEMS(cinfo,lvl,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS1(cinfo,lvl,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS2(cinfo,lvl,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ _mp[4] = (p5); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMSS(cinfo,lvl,code,str) \ ((cinfo)->err->msg_code = (code), \ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #endif /* JERROR_H */ fltk-1.4.3/jpeg/jidctflt.c0000644000175000017500000002025215004135251015502 0ustar albrechtalbrecht/* * jidctflt.c * * Copyright (C) 1994-1998, Thomas G. Lane. * Modified 2010-2017 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a floating-point implementation of the * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine * must also perform dequantization of the input coefficients. * * This implementation should be more accurate than either of the integer * IDCT implementations. However, it may not give the same results on all * machines because of differences in roundoff behavior. Speed will depend * on the hardware's floating point capacity. * * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT * on each row (or vice versa, but it's more convenient to emit a row at * a time). Direct algorithms are also available, but they are much more * complex and seem not to be any faster when reduced to code. * * This implementation is based on Arai, Agui, and Nakajima's algorithm for * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in * Japanese, but the algorithm is described in the Pennebaker & Mitchell * JPEG textbook (see REFERENCES section in file README). The following code * is based directly on figure 4-8 in P&M. * While an 8-point DCT cannot be done in less than 11 multiplies, it is * possible to arrange the computation so that many of the multiplies are * simple scalings of the final outputs. These multiplies can then be * folded into the multiplications or divisions by the JPEG quantization * table entries. The AA&N method leaves only 5 multiplies and 29 adds * to be done in the DCT itself. * The primary disadvantage of this method is that with a fixed-point * implementation, accuracy is lost due to imprecise representation of the * scaled quantization values. However, that problem does not arise if * we use floating point arithmetic. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_FLOAT_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ #endif /* Dequantize a coefficient by multiplying it by the multiplier-table * entry; produce a float result. */ #define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) /* * Perform dequantization and inverse DCT on one block of coefficients. * * cK represents cos(K*pi/16). */ GLOBAL(void) jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FAST_FLOAT tmp10, tmp11, tmp12, tmp13; FAST_FLOAT z5, z10, z11, z12, z13; JCOEFPTR inptr; FLOAT_MULT_TYPE * quantptr; FAST_FLOAT * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { /* Due to quantization, we will usually find that many of the input * coefficients are zero, especially the AC terms. We can exploit this * by short-circuiting the IDCT calculation for any column in which all * the AC terms are zero. In that case each output is equal to the * DC coefficient (with scale factor as needed). * With typical images and quantization tables, half or more of the * column DCT calculations can be simplified this way. */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; wsptr[DCTSIZE*2] = dcval; wsptr[DCTSIZE*3] = dcval; wsptr[DCTSIZE*4] = dcval; wsptr[DCTSIZE*5] = dcval; wsptr[DCTSIZE*6] = dcval; wsptr[DCTSIZE*7] = dcval; inptr++; /* advance pointers to next column */ quantptr++; wsptr++; continue; } /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); tmp10 = tmp0 + tmp2; /* phase 3 */ tmp11 = tmp0 - tmp2; tmp13 = tmp1 + tmp3; /* phases 5-3 */ tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ tmp0 = tmp10 + tmp13; /* phase 2 */ tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; /* Odd part */ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); z13 = tmp6 + tmp5; /* phase 6 */ z10 = tmp6 - tmp5; z11 = tmp4 + tmp7; z12 = tmp4 - tmp7; tmp7 = z11 + z13; /* phase 5 */ tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; tmp4 = tmp10 - tmp5; wsptr[DCTSIZE*0] = tmp0 + tmp7; wsptr[DCTSIZE*7] = tmp0 - tmp7; wsptr[DCTSIZE*1] = tmp1 + tmp6; wsptr[DCTSIZE*6] = tmp1 - tmp6; wsptr[DCTSIZE*2] = tmp2 + tmp5; wsptr[DCTSIZE*5] = tmp2 - tmp5; wsptr[DCTSIZE*3] = tmp3 + tmp4; wsptr[DCTSIZE*4] = tmp3 - tmp4; inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } /* Pass 2: process rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { outptr = output_buf[ctr] + output_col; /* Rows of zeroes can be exploited in the same way as we did with columns. * However, the column calculation has created many nonzero AC terms, so * the simplification applies less often (typically 5% to 10% of the time). * And testing floats for zero is relatively expensive, so we don't bother. */ /* Even part */ /* Prepare range-limit and float->int conversion */ z5 = wsptr[0] + (((FAST_FLOAT) RANGE_CENTER) + ((FAST_FLOAT) 0.5)); tmp10 = z5 + wsptr[4]; tmp11 = z5 - wsptr[4]; tmp13 = wsptr[2] + wsptr[6]; tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ tmp0 = tmp10 + tmp13; tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; /* Odd part */ z13 = wsptr[5] + wsptr[3]; z10 = wsptr[5] - wsptr[3]; z11 = wsptr[1] + wsptr[7]; z12 = wsptr[1] - wsptr[7]; tmp7 = z11 + z13; /* phase 5 */ tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; tmp4 = tmp10 - tmp5; /* Final output stage: float->int conversion and range-limit */ outptr[0] = range_limit[(int) (tmp0 + tmp7) & RANGE_MASK]; outptr[7] = range_limit[(int) (tmp0 - tmp7) & RANGE_MASK]; outptr[1] = range_limit[(int) (tmp1 + tmp6) & RANGE_MASK]; outptr[6] = range_limit[(int) (tmp1 - tmp6) & RANGE_MASK]; outptr[2] = range_limit[(int) (tmp2 + tmp5) & RANGE_MASK]; outptr[5] = range_limit[(int) (tmp2 - tmp5) & RANGE_MASK]; outptr[3] = range_limit[(int) (tmp3 + tmp4) & RANGE_MASK]; outptr[4] = range_limit[(int) (tmp3 - tmp4) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } #endif /* DCT_FLOAT_SUPPORTED */ fltk-1.4.3/jpeg/jcdctmgr.c0000644000175000017500000003571115004135251015502 0ustar albrechtalbrecht/* * jcdctmgr.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2003-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the forward-DCT management logic. * This code selects a particular DCT implementation to be used, * and it performs related housekeeping chores including coefficient * quantization. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ /* Private subobject for this module */ typedef struct { struct jpeg_forward_dct pub; /* public fields */ /* Pointer to the DCT routine actually in use */ forward_DCT_method_ptr do_dct[MAX_COMPONENTS]; #ifdef DCT_FLOAT_SUPPORTED /* Same as above for the floating-point case. */ float_DCT_method_ptr do_float_dct[MAX_COMPONENTS]; #endif } my_fdct_controller; typedef my_fdct_controller * my_fdct_ptr; /* The allocated post-DCT divisor tables -- big enough for any * supported variant and not identical to the quant table entries, * because of scaling (especially for an unnormalized DCT) -- * are pointed to by dct_table in the per-component comp_info * structures. Each table is given in normal array order. */ typedef union { DCTELEM int_array[DCTSIZE2]; #ifdef DCT_FLOAT_SUPPORTED FAST_FLOAT float_array[DCTSIZE2]; #endif } divisor_table; /* The current scaled-DCT routines require ISLOW-style divisor tables, * so be sure to compile that code if either ISLOW or SCALING is requested. */ #ifdef DCT_ISLOW_SUPPORTED #define PROVIDE_ISLOW_TABLES #else #ifdef DCT_SCALING_SUPPORTED #define PROVIDE_ISLOW_TABLES #endif #endif /* * Perform forward DCT on one or more blocks of a component. * * The input samples are taken from the sample_data[] array starting at * position start_col, and moving to the right for any additional blocks. * The quantized coefficients are returned in coef_blocks[]. */ METHODDEF(void) forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_col, JDIMENSION num_blocks) /* This version is used for integer DCT implementations. */ { /* This routine is heavily used, so it's worth coding it tightly. */ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; forward_DCT_method_ptr do_dct = fdct->do_dct[compptr->component_index]; DCTELEM * divisors = (DCTELEM *) compptr->dct_table; DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) { /* Perform the DCT */ (*do_dct) (workspace, sample_data, start_col); /* Quantize/descale the coefficients, and store into coef_blocks[] */ { register DCTELEM temp, qval; register int i; register JCOEFPTR output_ptr = coef_blocks[bi]; for (i = 0; i < DCTSIZE2; i++) { qval = divisors[i]; temp = workspace[i]; /* Divide the coefficient value by qval, ensuring proper rounding. * Since C does not specify the direction of rounding for negative * quotients, we have to force the dividend positive for portability. * * In most files, at least half of the output values will be zero * (at default quantization settings, more like three-quarters...) * so we should ensure that this case is fast. On many machines, * a comparison is enough cheaper than a divide to make a special test * a win. Since both inputs will be nonnegative, we need only test * for a < b to discover whether a/b is 0. * If your machine's division is fast enough, define FAST_DIVIDE. */ #ifdef FAST_DIVIDE #define DIVIDE_BY(a,b) a /= b #else #define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 #endif if (temp < 0) { temp = -temp; temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); temp = -temp; } else { temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); } output_ptr[i] = (JCOEF) temp; } } } } #ifdef DCT_FLOAT_SUPPORTED METHODDEF(void) forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_col, JDIMENSION num_blocks) /* This version is used for floating-point DCT implementations. */ { /* This routine is heavily used, so it's worth coding it tightly. */ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; float_DCT_method_ptr do_dct = fdct->do_float_dct[compptr->component_index]; FAST_FLOAT * divisors = (FAST_FLOAT *) compptr->dct_table; FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) { /* Perform the DCT */ (*do_dct) (workspace, sample_data, start_col); /* Quantize/descale the coefficients, and store into coef_blocks[] */ { register FAST_FLOAT temp; register int i; register JCOEFPTR output_ptr = coef_blocks[bi]; for (i = 0; i < DCTSIZE2; i++) { /* Apply the quantization and scaling factor */ temp = workspace[i] * divisors[i]; /* Round to nearest integer. * Since C does not specify the direction of rounding for negative * quotients, we have to force the dividend positive for portability. * The maximum coefficient size is +-16K (for 12-bit data), so this * code should work for either 16-bit or 32-bit ints. */ output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); } } } } #endif /* DCT_FLOAT_SUPPORTED */ /* * Initialize for a processing pass. * Verify that all referenced Q-tables are present, and set up * the divisor table for each one. * In the current implementation, DCT of all components is done during * the first pass, even if only some components will be output in the * first scan. Hence all components should be examined here. */ METHODDEF(void) start_pass_fdctmgr (j_compress_ptr cinfo) { my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; int ci, qtblno, i; jpeg_component_info *compptr; int method = 0; JQUANT_TBL * qtbl; DCTELEM * dtbl; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Select the proper DCT routine for this component's scaling */ switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) { #ifdef DCT_SCALING_SUPPORTED case ((1 << 8) + 1): fdct->do_dct[ci] = jpeg_fdct_1x1; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((2 << 8) + 2): fdct->do_dct[ci] = jpeg_fdct_2x2; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((3 << 8) + 3): fdct->do_dct[ci] = jpeg_fdct_3x3; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((4 << 8) + 4): fdct->do_dct[ci] = jpeg_fdct_4x4; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((5 << 8) + 5): fdct->do_dct[ci] = jpeg_fdct_5x5; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((6 << 8) + 6): fdct->do_dct[ci] = jpeg_fdct_6x6; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((7 << 8) + 7): fdct->do_dct[ci] = jpeg_fdct_7x7; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((9 << 8) + 9): fdct->do_dct[ci] = jpeg_fdct_9x9; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((10 << 8) + 10): fdct->do_dct[ci] = jpeg_fdct_10x10; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((11 << 8) + 11): fdct->do_dct[ci] = jpeg_fdct_11x11; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((12 << 8) + 12): fdct->do_dct[ci] = jpeg_fdct_12x12; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((13 << 8) + 13): fdct->do_dct[ci] = jpeg_fdct_13x13; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((14 << 8) + 14): fdct->do_dct[ci] = jpeg_fdct_14x14; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((15 << 8) + 15): fdct->do_dct[ci] = jpeg_fdct_15x15; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((16 << 8) + 16): fdct->do_dct[ci] = jpeg_fdct_16x16; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((16 << 8) + 8): fdct->do_dct[ci] = jpeg_fdct_16x8; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((14 << 8) + 7): fdct->do_dct[ci] = jpeg_fdct_14x7; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((12 << 8) + 6): fdct->do_dct[ci] = jpeg_fdct_12x6; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((10 << 8) + 5): fdct->do_dct[ci] = jpeg_fdct_10x5; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((8 << 8) + 4): fdct->do_dct[ci] = jpeg_fdct_8x4; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((6 << 8) + 3): fdct->do_dct[ci] = jpeg_fdct_6x3; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((4 << 8) + 2): fdct->do_dct[ci] = jpeg_fdct_4x2; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((2 << 8) + 1): fdct->do_dct[ci] = jpeg_fdct_2x1; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((8 << 8) + 16): fdct->do_dct[ci] = jpeg_fdct_8x16; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((7 << 8) + 14): fdct->do_dct[ci] = jpeg_fdct_7x14; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((6 << 8) + 12): fdct->do_dct[ci] = jpeg_fdct_6x12; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((5 << 8) + 10): fdct->do_dct[ci] = jpeg_fdct_5x10; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((4 << 8) + 8): fdct->do_dct[ci] = jpeg_fdct_4x8; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((3 << 8) + 6): fdct->do_dct[ci] = jpeg_fdct_3x6; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((2 << 8) + 4): fdct->do_dct[ci] = jpeg_fdct_2x4; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; case ((1 << 8) + 2): fdct->do_dct[ci] = jpeg_fdct_1x2; method = JDCT_ISLOW; /* jfdctint uses islow-style table */ break; #endif case ((DCTSIZE << 8) + DCTSIZE): switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: fdct->do_dct[ci] = jpeg_fdct_islow; method = JDCT_ISLOW; break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: fdct->do_dct[ci] = jpeg_fdct_ifast; method = JDCT_IFAST; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: fdct->do_float_dct[ci] = jpeg_fdct_float; method = JDCT_FLOAT; break; #endif default: ERREXIT(cinfo, JERR_NOT_COMPILED); } break; default: ERREXIT2(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); } qtblno = compptr->quant_tbl_no; /* Make sure specified quantization table is present */ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo->quant_tbl_ptrs[qtblno] == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); qtbl = cinfo->quant_tbl_ptrs[qtblno]; /* Create divisor table from quant table */ switch (method) { #ifdef PROVIDE_ISLOW_TABLES case JDCT_ISLOW: /* For LL&M IDCT method, divisors are equal to raw quantization * coefficients multiplied by 8 (to counteract scaling). */ dtbl = (DCTELEM *) compptr->dct_table; for (i = 0; i < DCTSIZE2; i++) { dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << (compptr->component_needed ? 4 : 3); } fdct->pub.forward_DCT[ci] = forward_DCT; break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: { /* For AA&N IDCT method, divisors are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * We apply a further scale factor of 8. */ #define CONST_BITS 14 static const INT16 aanscales[DCTSIZE2] = { /* precomputed values scaled up by 14 bits */ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 }; SHIFT_TEMPS dtbl = (DCTELEM *) compptr->dct_table; for (i = 0; i < DCTSIZE2; i++) { dtbl[i] = (DCTELEM) DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], (INT32) aanscales[i]), compptr->component_needed ? CONST_BITS-4 : CONST_BITS-3); } } fdct->pub.forward_DCT[ci] = forward_DCT; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: { /* For float AA&N IDCT method, divisors are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * We apply a further scale factor of 8. * What's actually stored is 1/divisor so that the inner loop can * use a multiplication rather than a division. */ FAST_FLOAT * fdtbl = (FAST_FLOAT *) compptr->dct_table; int row, col; static const double aanscalefactor[DCTSIZE] = { 1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958, 0.541196100, 0.275899379 }; i = 0; for (row = 0; row < DCTSIZE; row++) { for (col = 0; col < DCTSIZE; col++) { fdtbl[i] = (FAST_FLOAT) (1.0 / ((double) qtbl->quantval[i] * aanscalefactor[row] * aanscalefactor[col] * (compptr->component_needed ? 16.0 : 8.0))); i++; } } } fdct->pub.forward_DCT[ci] = forward_DCT_float; break; #endif default: ERREXIT(cinfo, JERR_NOT_COMPILED); } } } /* * Initialize FDCT manager. */ GLOBAL(void) jinit_forward_dct (j_compress_ptr cinfo) { my_fdct_ptr fdct; int ci; jpeg_component_info *compptr; fdct = (my_fdct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_fdct_controller)); cinfo->fdct = &fdct->pub; fdct->pub.start_pass = start_pass_fdctmgr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Allocate a divisor table for each component */ compptr->dct_table = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(divisor_table)); } } fltk-1.4.3/jpeg/fltk_jpeg_prefix.h0000644000175000017500000002062515004135251017232 0ustar albrechtalbrecht#define _jcopy_block_row fltk__jcopy_block_row #define _jcopy_sample_rows fltk__jcopy_sample_rows #define _jdiv_round_up fltk__jdiv_round_up #define _jinit_1pass_quantizer fltk__jinit_1pass_quantizer #define _jinit_2pass_quantizer fltk__jinit_2pass_quantizer #define _jinit_arith_decoder fltk__jinit_arith_decoder #define _jinit_arith_encoder fltk__jinit_arith_encoder #define _jinit_c_coef_controller fltk__jinit_c_coef_controller #define _jinit_c_main_controller fltk__jinit_c_main_controller #define _jinit_c_master_control fltk__jinit_c_master_control #define _jinit_c_prep_controller fltk__jinit_c_prep_controller #define _jinit_color_converter fltk__jinit_color_converter #define _jinit_color_deconverter fltk__jinit_color_deconverter #define _jinit_compress_master fltk__jinit_compress_master #define _jinit_d_coef_controller fltk__jinit_d_coef_controller #define _jinit_d_main_controller fltk__jinit_d_main_controller #define _jinit_d_post_controller fltk__jinit_d_post_controller #define _jinit_downsampler fltk__jinit_downsampler #define _jinit_forward_dct fltk__jinit_forward_dct #define _jinit_huff_decoder fltk__jinit_huff_decoder #define _jinit_huff_encoder fltk__jinit_huff_encoder #define _jinit_input_controller fltk__jinit_input_controller #define _jinit_inverse_dct fltk__jinit_inverse_dct #define _jinit_marker_reader fltk__jinit_marker_reader #define _jinit_marker_writer fltk__jinit_marker_writer #define _jinit_master_decompress fltk__jinit_master_decompress #define _jinit_memory_mgr fltk__jinit_memory_mgr #define _jinit_merged_upsampler fltk__jinit_merged_upsampler #define _jinit_upsampler fltk__jinit_upsampler #define _jpeg_CreateCompress fltk__jpeg_CreateCompress #define _jpeg_CreateDecompress fltk__jpeg_CreateDecompress #define _jpeg_abort fltk__jpeg_abort #define _jpeg_abort_compress fltk__jpeg_abort_compress #define _jpeg_abort_decompress fltk__jpeg_abort_decompress #define _jpeg_add_quant_table fltk__jpeg_add_quant_table #define _jpeg_alloc_huff_table fltk__jpeg_alloc_huff_table #define _jpeg_alloc_quant_table fltk__jpeg_alloc_quant_table #define _jpeg_aritab fltk__jpeg_aritab #define _jpeg_calc_jpeg_dimensions fltk__jpeg_calc_jpeg_dimensions #define _jpeg_calc_output_dimensions fltk__jpeg_calc_output_dimensions #define _jpeg_consume_input fltk__jpeg_consume_input #define _jpeg_copy_critical_parameters fltk__jpeg_copy_critical_parameters #define _jpeg_core_output_dimensions fltk__jpeg_core_output_dimensions #define _jpeg_default_colorspace fltk__jpeg_default_colorspace #define _jpeg_default_qtables fltk__jpeg_default_qtables #define _jpeg_destroy fltk__jpeg_destroy #define _jpeg_destroy_compress fltk__jpeg_destroy_compress #define _jpeg_destroy_decompress fltk__jpeg_destroy_decompress #define _jpeg_fdct_10x10 fltk__jpeg_fdct_10x10 #define _jpeg_fdct_10x5 fltk__jpeg_fdct_10x5 #define _jpeg_fdct_11x11 fltk__jpeg_fdct_11x11 #define _jpeg_fdct_12x12 fltk__jpeg_fdct_12x12 #define _jpeg_fdct_12x6 fltk__jpeg_fdct_12x6 #define _jpeg_fdct_13x13 fltk__jpeg_fdct_13x13 #define _jpeg_fdct_14x14 fltk__jpeg_fdct_14x14 #define _jpeg_fdct_14x7 fltk__jpeg_fdct_14x7 #define _jpeg_fdct_15x15 fltk__jpeg_fdct_15x15 #define _jpeg_fdct_16x16 fltk__jpeg_fdct_16x16 #define _jpeg_fdct_16x8 fltk__jpeg_fdct_16x8 #define _jpeg_fdct_1x1 fltk__jpeg_fdct_1x1 #define _jpeg_fdct_1x2 fltk__jpeg_fdct_1x2 #define _jpeg_fdct_2x1 fltk__jpeg_fdct_2x1 #define _jpeg_fdct_2x2 fltk__jpeg_fdct_2x2 #define _jpeg_fdct_2x4 fltk__jpeg_fdct_2x4 #define _jpeg_fdct_3x3 fltk__jpeg_fdct_3x3 #define _jpeg_fdct_3x6 fltk__jpeg_fdct_3x6 #define _jpeg_fdct_4x2 fltk__jpeg_fdct_4x2 #define _jpeg_fdct_4x4 fltk__jpeg_fdct_4x4 #define _jpeg_fdct_4x8 fltk__jpeg_fdct_4x8 #define _jpeg_fdct_5x10 fltk__jpeg_fdct_5x10 #define _jpeg_fdct_5x5 fltk__jpeg_fdct_5x5 #define _jpeg_fdct_6x12 fltk__jpeg_fdct_6x12 #define _jpeg_fdct_6x3 fltk__jpeg_fdct_6x3 #define _jpeg_fdct_6x6 fltk__jpeg_fdct_6x6 #define _jpeg_fdct_7x14 fltk__jpeg_fdct_7x14 #define _jpeg_fdct_7x7 fltk__jpeg_fdct_7x7 #define _jpeg_fdct_8x16 fltk__jpeg_fdct_8x16 #define _jpeg_fdct_8x4 fltk__jpeg_fdct_8x4 #define _jpeg_fdct_9x9 fltk__jpeg_fdct_9x9 #define _jpeg_fdct_float fltk__jpeg_fdct_float #define _jpeg_fdct_ifast fltk__jpeg_fdct_ifast #define _jpeg_fdct_islow fltk__jpeg_fdct_islow #define _jpeg_finish_compress fltk__jpeg_finish_compress #define _jpeg_finish_decompress fltk__jpeg_finish_decompress #define _jpeg_finish_output fltk__jpeg_finish_output #define _jpeg_free_large fltk__jpeg_free_large #define _jpeg_free_small fltk__jpeg_free_small #define _jpeg_get_large fltk__jpeg_get_large #define _jpeg_get_small fltk__jpeg_get_small #define _jpeg_has_multiple_scans fltk__jpeg_has_multiple_scans #define _jpeg_idct_10x10 fltk__jpeg_idct_10x10 #define _jpeg_idct_10x5 fltk__jpeg_idct_10x5 #define _jpeg_idct_11x11 fltk__jpeg_idct_11x11 #define _jpeg_idct_12x12 fltk__jpeg_idct_12x12 #define _jpeg_idct_12x6 fltk__jpeg_idct_12x6 #define _jpeg_idct_13x13 fltk__jpeg_idct_13x13 #define _jpeg_idct_14x14 fltk__jpeg_idct_14x14 #define _jpeg_idct_14x7 fltk__jpeg_idct_14x7 #define _jpeg_idct_15x15 fltk__jpeg_idct_15x15 #define _jpeg_idct_16x16 fltk__jpeg_idct_16x16 #define _jpeg_idct_16x8 fltk__jpeg_idct_16x8 #define _jpeg_idct_1x1 fltk__jpeg_idct_1x1 #define _jpeg_idct_1x2 fltk__jpeg_idct_1x2 #define _jpeg_idct_2x1 fltk__jpeg_idct_2x1 #define _jpeg_idct_2x2 fltk__jpeg_idct_2x2 #define _jpeg_idct_2x4 fltk__jpeg_idct_2x4 #define _jpeg_idct_3x3 fltk__jpeg_idct_3x3 #define _jpeg_idct_3x6 fltk__jpeg_idct_3x6 #define _jpeg_idct_4x2 fltk__jpeg_idct_4x2 #define _jpeg_idct_4x4 fltk__jpeg_idct_4x4 #define _jpeg_idct_4x8 fltk__jpeg_idct_4x8 #define _jpeg_idct_5x10 fltk__jpeg_idct_5x10 #define _jpeg_idct_5x5 fltk__jpeg_idct_5x5 #define _jpeg_idct_6x12 fltk__jpeg_idct_6x12 #define _jpeg_idct_6x3 fltk__jpeg_idct_6x3 #define _jpeg_idct_6x6 fltk__jpeg_idct_6x6 #define _jpeg_idct_7x14 fltk__jpeg_idct_7x14 #define _jpeg_idct_7x7 fltk__jpeg_idct_7x7 #define _jpeg_idct_8x16 fltk__jpeg_idct_8x16 #define _jpeg_idct_8x4 fltk__jpeg_idct_8x4 #define _jpeg_idct_9x9 fltk__jpeg_idct_9x9 #define _jpeg_idct_float fltk__jpeg_idct_float #define _jpeg_idct_ifast fltk__jpeg_idct_ifast #define _jpeg_idct_islow fltk__jpeg_idct_islow #define _jpeg_input_complete fltk__jpeg_input_complete #define _jpeg_mem_available fltk__jpeg_mem_available #define _jpeg_mem_dest fltk__jpeg_mem_dest #define _jpeg_mem_init fltk__jpeg_mem_init #define _jpeg_mem_src fltk__jpeg_mem_src #define _jpeg_mem_term fltk__jpeg_mem_term #define _jpeg_natural_order fltk__jpeg_natural_order #define _jpeg_natural_order2 fltk__jpeg_natural_order2 #define _jpeg_natural_order3 fltk__jpeg_natural_order3 #define _jpeg_natural_order4 fltk__jpeg_natural_order4 #define _jpeg_natural_order5 fltk__jpeg_natural_order5 #define _jpeg_natural_order6 fltk__jpeg_natural_order6 #define _jpeg_natural_order7 fltk__jpeg_natural_order7 #define _jpeg_new_colormap fltk__jpeg_new_colormap #define _jpeg_open_backing_store fltk__jpeg_open_backing_store #define _jpeg_quality_scaling fltk__jpeg_quality_scaling #define _jpeg_read_coefficients fltk__jpeg_read_coefficients #define _jpeg_read_header fltk__jpeg_read_header #define _jpeg_read_raw_data fltk__jpeg_read_raw_data #define _jpeg_read_scanlines fltk__jpeg_read_scanlines #define _jpeg_resync_to_restart fltk__jpeg_resync_to_restart #define _jpeg_save_markers fltk__jpeg_save_markers #define _jpeg_set_colorspace fltk__jpeg_set_colorspace #define _jpeg_set_defaults fltk__jpeg_set_defaults #define _jpeg_set_linear_quality fltk__jpeg_set_linear_quality #define _jpeg_set_marker_processor fltk__jpeg_set_marker_processor #define _jpeg_set_quality fltk__jpeg_set_quality #define _jpeg_simple_progression fltk__jpeg_simple_progression #define _jpeg_start_compress fltk__jpeg_start_compress #define _jpeg_start_decompress fltk__jpeg_start_decompress #define _jpeg_start_output fltk__jpeg_start_output #define _jpeg_std_error fltk__jpeg_std_error #define _jpeg_std_huff_table fltk__jpeg_std_huff_table #define _jpeg_std_message_table fltk__jpeg_std_message_table #define _jpeg_stdio_dest fltk__jpeg_stdio_dest #define _jpeg_stdio_src fltk__jpeg_stdio_src #define _jpeg_suppress_tables fltk__jpeg_suppress_tables #define _jpeg_write_coefficients fltk__jpeg_write_coefficients #define _jpeg_write_m_byte fltk__jpeg_write_m_byte #define _jpeg_write_m_header fltk__jpeg_write_m_header #define _jpeg_write_marker fltk__jpeg_write_marker #define _jpeg_write_raw_data fltk__jpeg_write_raw_data #define _jpeg_write_scanlines fltk__jpeg_write_scanlines #define _jpeg_write_tables fltk__jpeg_write_tables #define _jround_up fltk__jround_up fltk-1.4.3/jpeg/jcarith.c0000644000175000017500000006714415004135251015336 0ustar albrechtalbrecht/* * jcarith.c * * Developed 1997-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains portable arithmetic entropy encoding routines for JPEG * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81). * * Both sequential and progressive modes are supported in this single module. * * Suspension is not currently supported in this module. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Expanded entropy encoder object for arithmetic encoding. */ typedef struct { struct jpeg_entropy_encoder pub; /* public fields */ INT32 c; /* C register, base of coding interval, layout as in sec. D.1.3 */ INT32 a; /* A register, normalized size of coding interval */ INT32 sc; /* counter for stacked 0xFF values which might overflow */ INT32 zc; /* counter for pending 0x00 output values which might * * be discarded at the end ("Pacman" termination) */ int ct; /* bit shift counter, determines when next byte will be written */ int buffer; /* buffer for most recent output byte != 0xFF */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ int next_restart_num; /* next restart number to write (0-7) */ /* Pointers to statistics areas (these workspaces have image lifespan) */ unsigned char * dc_stats[NUM_ARITH_TBLS]; unsigned char * ac_stats[NUM_ARITH_TBLS]; /* Statistics bin for coding with fixed probability 0.5 */ unsigned char fixed_bin[4]; } arith_entropy_encoder; typedef arith_entropy_encoder * arith_entropy_ptr; /* The following two definitions specify the allocation chunk size * for the statistics area. * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least * 49 statistics bins for DC, and 245 statistics bins for AC coding. * * We use a compact representation with 1 byte per statistics bin, * thus the numbers directly represent byte sizes. * This 1 byte per statistics bin contains the meaning of the MPS * (more probable symbol) in the highest bit (mask 0x80), and the * index into the probability estimation state machine table * in the lower bits (mask 0x7F). */ #define DC_STAT_BINS 64 #define AC_STAT_BINS 256 /* NOTE: Uncomment the following #define if you want to use the * given formula for calculating the AC conditioning parameter Kx * for spectral selection progressive coding in section G.1.3.2 * of the spec (Kx = Kmin + SRL (8 + Se - Kmin) 4). * Although the spec and P&M authors claim that this "has proven * to give good results for 8 bit precision samples", I'm not * convinced yet that this is really beneficial. * Early tests gave only very marginal compression enhancements * (a few - around 5 or so - bytes even for very large files), * which would turn out rather negative if we'd suppress the * DAC (Define Arithmetic Conditioning) marker segments for * the default parameters in the future. * Note that currently the marker writing module emits 12-byte * DAC segments for a full-component scan in a color image. * This is not worth worrying about IMHO. However, since the * spec defines the default values to be used if the tables * are omitted (unlike Huffman tables, which are required * anyway), one might optimize this behaviour in the future, * and then it would be disadvantageous to use custom tables if * they don't provide sufficient gain to exceed the DAC size. * * On the other hand, I'd consider it as a reasonable result * that the conditioning has no significant influence on the * compression performance. This means that the basic * statistical model is already rather stable. * * Thus, at the moment, we use the default conditioning values * anyway, and do not use the custom formula. * #define CALCULATE_SPECTRAL_CONDITIONING */ /* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. * We assume that int right shift is unsigned if INT32 right shift is, * which should be safe. */ #ifdef RIGHT_SHIFT_IS_UNSIGNED #define ISHIFT_TEMPS int ishift_temp; #define IRIGHT_SHIFT(x,shft) \ ((ishift_temp = (x)) < 0 ? \ (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ (ishift_temp >> (shft))) #else #define ISHIFT_TEMPS #define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif LOCAL(void) emit_byte (int val, j_compress_ptr cinfo) /* Write next output byte; we do not support suspension in this module. */ { struct jpeg_destination_mgr * dest = cinfo->dest; *dest->next_output_byte++ = (JOCTET) val; if (--dest->free_in_buffer == 0) if (! (*dest->empty_output_buffer) (cinfo)) ERREXIT(cinfo, JERR_CANT_SUSPEND); } /* * Finish up at the end of an arithmetic-compressed scan. */ METHODDEF(void) finish_pass (j_compress_ptr cinfo) { arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; INT32 temp; /* Section D.1.8: Termination of encoding */ /* Find the e->c in the coding interval with the largest * number of trailing zero bits */ if ((temp = (e->a - 1 + e->c) & 0xFFFF0000L) < e->c) e->c = temp + 0x8000L; else e->c = temp; /* Send remaining bytes to output */ e->c <<= e->ct; if (e->c & 0xF8000000L) { /* One final overflow has to be handled */ if (e->buffer >= 0) { if (e->zc) do emit_byte(0x00, cinfo); while (--e->zc); emit_byte(e->buffer + 1, cinfo); if (e->buffer + 1 == 0xFF) emit_byte(0x00, cinfo); } e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ e->sc = 0; } else { if (e->buffer == 0) ++e->zc; else if (e->buffer >= 0) { if (e->zc) do emit_byte(0x00, cinfo); while (--e->zc); emit_byte(e->buffer, cinfo); } if (e->sc) { if (e->zc) do emit_byte(0x00, cinfo); while (--e->zc); do { emit_byte(0xFF, cinfo); emit_byte(0x00, cinfo); } while (--e->sc); } } /* Output final bytes only if they are not 0x00 */ if (e->c & 0x7FFF800L) { if (e->zc) /* output final pending zero bytes */ do emit_byte(0x00, cinfo); while (--e->zc); emit_byte((int) ((e->c >> 19) & 0xFF), cinfo); if (((e->c >> 19) & 0xFF) == 0xFF) emit_byte(0x00, cinfo); if (e->c & 0x7F800L) { emit_byte((int) ((e->c >> 11) & 0xFF), cinfo); if (((e->c >> 11) & 0xFF) == 0xFF) emit_byte(0x00, cinfo); } } } /* * The core arithmetic encoding routine (common in JPEG and JBIG). * This needs to go as fast as possible. * Machine-dependent optimization facilities * are not utilized in this portable implementation. * However, this code should be fairly efficient and * may be a good base for further optimizations anyway. * * Parameter 'val' to be encoded may be 0 or 1 (binary decision). * * Note: I've added full "Pacman" termination support to the * byte output routines, which is equivalent to the optional * Discard_final_zeros procedure (Figure D.15) in the spec. * Thus, we always produce the shortest possible output * stream compliant to the spec (no trailing zero bytes, * except for FF stuffing). * * I've also introduced a new scheme for accessing * the probability estimation state machine table, * derived from Markus Kuhn's JBIG implementation. */ LOCAL(void) arith_encode (j_compress_ptr cinfo, unsigned char *st, int val) { register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; register unsigned char nl, nm; register INT32 qe, temp; register int sv; /* Fetch values from our compact representation of Table D.3(D.2): * Qe values and probability estimation state machine */ sv = *st; qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ /* Encode & estimation procedures per sections D.1.4 & D.1.5 */ e->a -= qe; if (val != (sv >> 7)) { /* Encode the less probable symbol */ if (e->a >= qe) { /* If the interval size (qe) for the less probable symbol (LPS) * is larger than the interval size for the MPS, then exchange * the two symbols for coding efficiency, otherwise code the LPS * as usual: */ e->c += e->a; e->a = qe; } *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ } else { /* Encode the more probable symbol */ if (e->a >= 0x8000L) return; /* A >= 0x8000 -> ready, no renormalization required */ if (e->a < qe) { /* If the interval size (qe) for the less probable symbol (LPS) * is larger than the interval size for the MPS, then exchange * the two symbols for coding efficiency: */ e->c += e->a; e->a = qe; } *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ } /* Renormalization & data output per section D.1.6 */ do { e->a <<= 1; e->c <<= 1; if (--e->ct == 0) { /* Another byte is ready for output */ temp = e->c >> 19; if (temp > 0xFF) { /* Handle overflow over all stacked 0xFF bytes */ if (e->buffer >= 0) { if (e->zc) do emit_byte(0x00, cinfo); while (--e->zc); emit_byte(e->buffer + 1, cinfo); if (e->buffer + 1 == 0xFF) emit_byte(0x00, cinfo); } e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ e->sc = 0; /* Note: The 3 spacer bits in the C register guarantee * that the new buffer byte can't be 0xFF here * (see page 160 in the P&M JPEG book). */ /* New output byte, might overflow later */ e->buffer = (int) (temp & 0xFF); } else if (temp == 0xFF) { ++e->sc; /* stack 0xFF byte (which might overflow later) */ } else { /* Output all stacked 0xFF bytes, they will not overflow any more */ if (e->buffer == 0) ++e->zc; else if (e->buffer >= 0) { if (e->zc) do emit_byte(0x00, cinfo); while (--e->zc); emit_byte(e->buffer, cinfo); } if (e->sc) { if (e->zc) do emit_byte(0x00, cinfo); while (--e->zc); do { emit_byte(0xFF, cinfo); emit_byte(0x00, cinfo); } while (--e->sc); } /* New output byte (can still overflow) */ e->buffer = (int) (temp & 0xFF); } e->c &= 0x7FFFFL; e->ct += 8; } } while (e->a < 0x8000L); } /* * Emit a restart marker & resynchronize predictions. */ LOCAL(void) emit_restart (j_compress_ptr cinfo, int restart_num) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; int ci; jpeg_component_info * compptr; finish_pass(cinfo); emit_byte(0xFF, cinfo); emit_byte(JPEG_RST0 + restart_num, cinfo); /* Re-initialize statistics areas */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* DC needs no table for refinement scan */ if (cinfo->Ss == 0 && cinfo->Ah == 0) { MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); /* Reset DC predictions to 0 */ entropy->last_dc_val[ci] = 0; entropy->dc_context[ci] = 0; } /* AC needs no table when not present */ if (cinfo->Se) { MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); } } /* Reset arithmetic encoding variables */ entropy->c = 0; entropy->a = 0x10000L; entropy->sc = 0; entropy->zc = 0; entropy->ct = 11; entropy->buffer = -1; /* empty */ } /* * MCU encoding for DC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; unsigned char *st; int blkn, ci, tbl; int v, v2, m; ISHIFT_TEMPS /* Emit restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { emit_restart(cinfo, entropy->next_restart_num); entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; /* Compute the DC value after the required point transform by Al. * This is simply an arithmetic right shift. */ m = IRIGHT_SHIFT((int) (MCU_data[blkn][0][0]), cinfo->Al); /* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */ /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; /* Figure F.4: Encode_DC_DIFF */ if ((v = m - entropy->last_dc_val[ci]) == 0) { arith_encode(cinfo, st, 0); entropy->dc_context[ci] = 0; /* zero diff category */ } else { entropy->last_dc_val[ci] = m; arith_encode(cinfo, st, 1); /* Figure F.6: Encoding nonzero value v */ /* Figure F.7: Encoding the sign of v */ if (v > 0) { arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ st += 2; /* Table F.4: SP = S0 + 2 */ entropy->dc_context[ci] = 4; /* small positive diff category */ } else { v = -v; arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ st += 3; /* Table F.4: SN = S0 + 3 */ entropy->dc_context[ci] = 8; /* small negative diff category */ } /* Figure F.8: Encoding the magnitude category of v */ m = 0; if (v -= 1) { arith_encode(cinfo, st, 1); m = 1; v2 = v; st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ while (v2 >>= 1) { arith_encode(cinfo, st, 1); m <<= 1; st += 1; } } arith_encode(cinfo, st, 0); /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) entropy->dc_context[ci] = 0; /* zero diff category */ else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) entropy->dc_context[ci] += 8; /* large diff category */ /* Figure F.9: Encoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) arith_encode(cinfo, st, (m & v) ? 1 : 0); } } return TRUE; } /* * MCU encoding for AC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; const int * natural_order; JBLOCKROW block; unsigned char *st; int tbl, k, ke; int v, v2, m; /* Emit restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { emit_restart(cinfo, entropy->next_restart_num); entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } natural_order = cinfo->natural_order; /* Encode the MCU data block */ block = MCU_data[0]; tbl = cinfo->cur_comp_info[0]->ac_tbl_no; /* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */ /* Establish EOB (end-of-block) index */ ke = cinfo->Se; do { /* We must apply the point transform by Al. For AC coefficients this * is an integer division with rounding towards 0. To do this portably * in C, we shift after obtaining the absolute value. */ if ((v = (*block)[natural_order[ke]]) >= 0) { if (v >>= cinfo->Al) break; } else { v = -v; if (v >>= cinfo->Al) break; } } while (--ke); /* Figure F.5: Encode_AC_Coefficients */ for (k = cinfo->Ss - 1; k < ke;) { st = entropy->ac_stats[tbl] + 3 * k; arith_encode(cinfo, st, 0); /* EOB decision */ for (;;) { if ((v = (*block)[natural_order[++k]]) >= 0) { if (v >>= cinfo->Al) { arith_encode(cinfo, st + 1, 1); arith_encode(cinfo, entropy->fixed_bin, 0); break; } } else { v = -v; if (v >>= cinfo->Al) { arith_encode(cinfo, st + 1, 1); arith_encode(cinfo, entropy->fixed_bin, 1); break; } } arith_encode(cinfo, st + 1, 0); st += 3; } st += 2; /* Figure F.8: Encoding the magnitude category of v */ m = 0; if (v -= 1) { arith_encode(cinfo, st, 1); m = 1; v2 = v; if (v2 >>= 1) { arith_encode(cinfo, st, 1); m <<= 1; st = entropy->ac_stats[tbl] + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); while (v2 >>= 1) { arith_encode(cinfo, st, 1); m <<= 1; st += 1; } } } arith_encode(cinfo, st, 0); /* Figure F.9: Encoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) arith_encode(cinfo, st, (m & v) ? 1 : 0); } /* Encode EOB decision only if k < cinfo->Se */ if (k < cinfo->Se) { st = entropy->ac_stats[tbl] + 3 * k; arith_encode(cinfo, st, 1); } return TRUE; } /* * MCU encoding for DC successive approximation refinement scan. * Note: we assume such scans can be multi-component, * although the spec is not very clear on the point. */ METHODDEF(boolean) encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKARRAY MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; unsigned char *st; int Al, blkn; /* Emit restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { emit_restart(cinfo, entropy->next_restart_num); entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } st = entropy->fixed_bin; /* use fixed probability estimation */ Al = cinfo->Al; /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { /* We simply emit the Al'th bit of the DC coefficient value. */ arith_encode(cinfo, st, (MCU_data[blkn][0][0] >> Al) & 1); } return TRUE; } /* * MCU encoding for AC successive approximation refinement scan. */ METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKARRAY MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; const int * natural_order; JBLOCKROW block; unsigned char *st; int tbl, k, ke, kex; int v; /* Emit restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { emit_restart(cinfo, entropy->next_restart_num); entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } natural_order = cinfo->natural_order; /* Encode the MCU data block */ block = MCU_data[0]; tbl = cinfo->cur_comp_info[0]->ac_tbl_no; /* Section G.1.3.3: Encoding of AC coefficients */ /* Establish EOB (end-of-block) index */ ke = cinfo->Se; do { /* We must apply the point transform by Al. For AC coefficients this * is an integer division with rounding towards 0. To do this portably * in C, we shift after obtaining the absolute value. */ if ((v = (*block)[natural_order[ke]]) >= 0) { if (v >>= cinfo->Al) break; } else { v = -v; if (v >>= cinfo->Al) break; } } while (--ke); /* Establish EOBx (previous stage end-of-block) index */ for (kex = ke; kex > 0; kex--) if ((v = (*block)[natural_order[kex]]) >= 0) { if (v >>= cinfo->Ah) break; } else { v = -v; if (v >>= cinfo->Ah) break; } /* Figure G.10: Encode_AC_Coefficients_SA */ for (k = cinfo->Ss - 1; k < ke;) { st = entropy->ac_stats[tbl] + 3 * k; if (k >= kex) arith_encode(cinfo, st, 0); /* EOB decision */ for (;;) { if ((v = (*block)[natural_order[++k]]) >= 0) { if (v >>= cinfo->Al) { if (v >> 1) /* previously nonzero coef */ arith_encode(cinfo, st + 2, (v & 1)); else { /* newly nonzero coef */ arith_encode(cinfo, st + 1, 1); arith_encode(cinfo, entropy->fixed_bin, 0); } break; } } else { v = -v; if (v >>= cinfo->Al) { if (v >> 1) /* previously nonzero coef */ arith_encode(cinfo, st + 2, (v & 1)); else { /* newly nonzero coef */ arith_encode(cinfo, st + 1, 1); arith_encode(cinfo, entropy->fixed_bin, 1); } break; } } arith_encode(cinfo, st + 1, 0); st += 3; } } /* Encode EOB decision only if k < cinfo->Se */ if (k < cinfo->Se) { st = entropy->ac_stats[tbl] + 3 * k; arith_encode(cinfo, st, 1); } return TRUE; } /* * Encode and output one MCU's worth of arithmetic-compressed coefficients. */ METHODDEF(boolean) encode_mcu (j_compress_ptr cinfo, JBLOCKARRAY MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; const int * natural_order; JBLOCKROW block; unsigned char *st; int tbl, k, ke; int v, v2, m; int blkn, ci; jpeg_component_info * compptr; /* Emit restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { emit_restart(cinfo, entropy->next_restart_num); entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } natural_order = cinfo->natural_order; /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { block = MCU_data[blkn]; ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; /* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */ tbl = compptr->dc_tbl_no; /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; /* Figure F.4: Encode_DC_DIFF */ if ((v = (*block)[0] - entropy->last_dc_val[ci]) == 0) { arith_encode(cinfo, st, 0); entropy->dc_context[ci] = 0; /* zero diff category */ } else { entropy->last_dc_val[ci] = (*block)[0]; arith_encode(cinfo, st, 1); /* Figure F.6: Encoding nonzero value v */ /* Figure F.7: Encoding the sign of v */ if (v > 0) { arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ st += 2; /* Table F.4: SP = S0 + 2 */ entropy->dc_context[ci] = 4; /* small positive diff category */ } else { v = -v; arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ st += 3; /* Table F.4: SN = S0 + 3 */ entropy->dc_context[ci] = 8; /* small negative diff category */ } /* Figure F.8: Encoding the magnitude category of v */ m = 0; if (v -= 1) { arith_encode(cinfo, st, 1); m = 1; v2 = v; st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ while (v2 >>= 1) { arith_encode(cinfo, st, 1); m <<= 1; st += 1; } } arith_encode(cinfo, st, 0); /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) entropy->dc_context[ci] = 0; /* zero diff category */ else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) entropy->dc_context[ci] += 8; /* large diff category */ /* Figure F.9: Encoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) arith_encode(cinfo, st, (m & v) ? 1 : 0); } /* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */ if ((ke = cinfo->lim_Se) == 0) continue; tbl = compptr->ac_tbl_no; /* Establish EOB (end-of-block) index */ do { if ((*block)[natural_order[ke]]) break; } while (--ke); /* Figure F.5: Encode_AC_Coefficients */ for (k = 0; k < ke;) { st = entropy->ac_stats[tbl] + 3 * k; arith_encode(cinfo, st, 0); /* EOB decision */ while ((v = (*block)[natural_order[++k]]) == 0) { arith_encode(cinfo, st + 1, 0); st += 3; } arith_encode(cinfo, st + 1, 1); /* Figure F.6: Encoding nonzero value v */ /* Figure F.7: Encoding the sign of v */ if (v > 0) { arith_encode(cinfo, entropy->fixed_bin, 0); } else { v = -v; arith_encode(cinfo, entropy->fixed_bin, 1); } st += 2; /* Figure F.8: Encoding the magnitude category of v */ m = 0; if (v -= 1) { arith_encode(cinfo, st, 1); m = 1; v2 = v; if (v2 >>= 1) { arith_encode(cinfo, st, 1); m <<= 1; st = entropy->ac_stats[tbl] + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); while (v2 >>= 1) { arith_encode(cinfo, st, 1); m <<= 1; st += 1; } } } arith_encode(cinfo, st, 0); /* Figure F.9: Encoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) arith_encode(cinfo, st, (m & v) ? 1 : 0); } /* Encode EOB decision only if k < cinfo->lim_Se */ if (k < cinfo->lim_Se) { st = entropy->ac_stats[tbl] + 3 * k; arith_encode(cinfo, st, 1); } } return TRUE; } /* * Initialize for an arithmetic-compressed scan. */ METHODDEF(void) start_pass (j_compress_ptr cinfo, boolean gather_statistics) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; int ci, tbl; jpeg_component_info * compptr; if (gather_statistics) /* Make sure to avoid that in the master control logic! * We are fully adaptive here and need no extra * statistics gathering pass! */ ERREXIT(cinfo, JERR_NOT_COMPILED); /* We assume jcmaster.c already validated the progressive scan parameters. */ /* Select execution routines */ if (cinfo->progressive_mode) { if (cinfo->Ah == 0) { if (cinfo->Ss == 0) entropy->pub.encode_mcu = encode_mcu_DC_first; else entropy->pub.encode_mcu = encode_mcu_AC_first; } else { if (cinfo->Ss == 0) entropy->pub.encode_mcu = encode_mcu_DC_refine; else entropy->pub.encode_mcu = encode_mcu_AC_refine; } } else entropy->pub.encode_mcu = encode_mcu; /* Allocate & initialize requested statistics areas */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* DC needs no table for refinement scan */ if (cinfo->Ss == 0 && cinfo->Ah == 0) { tbl = compptr->dc_tbl_no; if (tbl < 0 || tbl >= NUM_ARITH_TBLS) ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); if (entropy->dc_stats[tbl] == NULL) entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); /* Initialize DC predictions to 0 */ entropy->last_dc_val[ci] = 0; entropy->dc_context[ci] = 0; } /* AC needs no table when not present */ if (cinfo->Se) { tbl = compptr->ac_tbl_no; if (tbl < 0 || tbl >= NUM_ARITH_TBLS) ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); if (entropy->ac_stats[tbl] == NULL) entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); #ifdef CALCULATE_SPECTRAL_CONDITIONING if (cinfo->progressive_mode) /* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */ cinfo->arith_ac_K[tbl] = cinfo->Ss + ((8 + cinfo->Se - cinfo->Ss) >> 4); #endif } } /* Initialize arithmetic encoding variables */ entropy->c = 0; entropy->a = 0x10000L; entropy->sc = 0; entropy->zc = 0; entropy->ct = 11; entropy->buffer = -1; /* empty */ /* Initialize restart stuff */ entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num = 0; } /* * Module initialization routine for arithmetic entropy encoding. */ GLOBAL(void) jinit_arith_encoder (j_compress_ptr cinfo) { arith_entropy_ptr entropy; int i; entropy = (arith_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(arith_entropy_encoder)); cinfo->entropy = &entropy->pub; entropy->pub.start_pass = start_pass; entropy->pub.finish_pass = finish_pass; /* Mark tables unallocated */ for (i = 0; i < NUM_ARITH_TBLS; i++) { entropy->dc_stats[i] = NULL; entropy->ac_stats[i] = NULL; } /* Initialize index for fixed probability estimation */ entropy->fixed_bin[0] = 113; } fltk-1.4.3/jpeg/jdpostct.c0000644000175000017500000002277315004135251015543 0ustar albrechtalbrecht/* * jdpostct.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the decompression postprocessing controller. * This controller manages the upsampling, color conversion, and color * quantization/reduction steps; specifically, it controls the buffering * between upsample/color conversion and color quantization/reduction. * * If no color quantization/reduction is required, then this module has no * work to do, and it just hands off to the upsample/color conversion code. * An integrated upsample/convert/quantize process would replace this module * entirely. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private buffer controller object */ typedef struct { struct jpeg_d_post_controller pub; /* public fields */ /* Color quantization source buffer: this holds output data from * the upsample/color conversion step to be passed to the quantizer. * For two-pass color quantization, we need a full-image buffer; * for one-pass operation, a strip buffer is sufficient. */ jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ JDIMENSION strip_height; /* buffer size in rows */ /* for two-pass mode only: */ JDIMENSION starting_row; /* row # of first row in current strip */ JDIMENSION next_row; /* index of next row to fill/empty in strip */ } my_post_controller; typedef my_post_controller * my_post_ptr; /* Forward declarations */ METHODDEF(void) post_process_1pass JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) post_process_prepass JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); METHODDEF(void) post_process_2pass JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #endif /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) { my_post_ptr post = (my_post_ptr) cinfo->post; switch (pass_mode) { case JBUF_PASS_THRU: if (cinfo->quantize_colors) { /* Single-pass processing with color quantization. */ post->pub.post_process_data = post_process_1pass; /* We could be doing buffered-image output before starting a 2-pass * color quantization; in that case, jinit_d_post_controller did not * allocate a strip buffer. Use the virtual-array buffer as workspace. */ if (post->buffer == NULL) { post->buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, post->whole_image, (JDIMENSION) 0, post->strip_height, TRUE); } } else { /* For single-pass processing without color quantization, * I have no work to do; just call the upsampler directly. */ post->pub.post_process_data = cinfo->upsample->upsample; } break; #ifdef QUANT_2PASS_SUPPORTED case JBUF_SAVE_AND_PASS: /* First pass of 2-pass quantization */ if (post->whole_image == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); post->pub.post_process_data = post_process_prepass; break; case JBUF_CRANK_DEST: /* Second pass of 2-pass quantization */ if (post->whole_image == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); post->pub.post_process_data = post_process_2pass; break; #endif /* QUANT_2PASS_SUPPORTED */ default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } post->starting_row = post->next_row = 0; } /* * Process some data in the one-pass (strip buffer) case. * This is used for color precision reduction as well as one-pass quantization. */ METHODDEF(void) post_process_1pass (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION num_rows, max_rows; /* Fill the buffer, but not more than what we can dump out in one go. */ /* Note we rely on the upsampler to detect bottom of image. */ max_rows = out_rows_avail - *out_row_ctr; if (max_rows > post->strip_height) max_rows = post->strip_height; num_rows = 0; (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, in_row_groups_avail, post->buffer, &num_rows, max_rows); /* Quantize and emit data. */ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer, output_buf + *out_row_ctr, (int) num_rows); *out_row_ctr += num_rows; } #ifdef QUANT_2PASS_SUPPORTED /* * Process some data in the first pass of 2-pass quantization. */ METHODDEF(void) post_process_prepass (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION old_next_row, num_rows; /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { post->buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, post->whole_image, post->starting_row, post->strip_height, TRUE); } /* Upsample some data (up to a strip height's worth). */ old_next_row = post->next_row; (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, in_row_groups_avail, post->buffer, &post->next_row, post->strip_height); /* Allow quantizer to scan new data. No data is emitted, */ /* but we advance out_row_ctr so outer loop can tell when we're done. */ if (post->next_row > old_next_row) { num_rows = post->next_row - old_next_row; (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, (JSAMPARRAY) NULL, (int) num_rows); *out_row_ctr += num_rows; } /* Advance if we filled the strip. */ if (post->next_row >= post->strip_height) { post->starting_row += post->strip_height; post->next_row = 0; } } /* * Process some data in the second pass of 2-pass quantization. */ METHODDEF(void) post_process_2pass (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION num_rows, max_rows; /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { post->buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, post->whole_image, post->starting_row, post->strip_height, FALSE); } /* Determine number of rows to emit. */ num_rows = post->strip_height - post->next_row; /* available in strip */ max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ if (num_rows > max_rows) num_rows = max_rows; /* We have to check bottom of image here, can't depend on upsampler. */ max_rows = cinfo->output_height - post->starting_row; if (num_rows > max_rows) num_rows = max_rows; /* Quantize and emit data. */ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + post->next_row, output_buf + *out_row_ctr, (int) num_rows); *out_row_ctr += num_rows; /* Advance if we filled the strip. */ post->next_row += num_rows; if (post->next_row >= post->strip_height) { post->starting_row += post->strip_height; post->next_row = 0; } } #endif /* QUANT_2PASS_SUPPORTED */ /* * Initialize postprocessing controller. */ GLOBAL(void) jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_post_ptr post; post = (my_post_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_post_controller)); cinfo->post = (struct jpeg_d_post_controller *) post; post->pub.start_pass = start_pass_dpost; post->whole_image = NULL; /* flag for no virtual arrays */ post->buffer = NULL; /* flag for no strip buffer */ /* Create the quantization buffer, if needed */ if (cinfo->quantize_colors) { /* The buffer strip height is max_v_samp_factor, which is typically * an efficient number of rows for upsampling to return. * (In the presence of output rescaling, we might want to be smarter?) */ post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; if (need_full_buffer) { /* Two-pass color quantization: need full-image storage. */ /* We round up the number of rows to a multiple of the strip height. */ #ifdef QUANT_2PASS_SUPPORTED post->whole_image = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, cinfo->output_width * cinfo->out_color_components, (JDIMENSION) jround_up((long) cinfo->output_height, (long) post->strip_height), post->strip_height); #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif /* QUANT_2PASS_SUPPORTED */ } else { /* One-pass color quantization: just make a strip buffer. */ post->buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width * cinfo->out_color_components, post->strip_height); } } } fltk-1.4.3/jpeg/jdmarker.c0000644000175000017500000013140015004135251015474 0ustar albrechtalbrecht/* * jdmarker.c * * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2009-2019 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to decode JPEG datastream markers. * Most of the complexity arises from our desire to support input * suspension: if not all of the data for a marker is available, * we must exit back to the application. On resumption, we reprocess * the marker. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" typedef enum { /* JPEG marker codes */ M_SOF0 = 0xc0, M_SOF1 = 0xc1, M_SOF2 = 0xc2, M_SOF3 = 0xc3, M_SOF5 = 0xc5, M_SOF6 = 0xc6, M_SOF7 = 0xc7, M_JPG = 0xc8, M_SOF9 = 0xc9, M_SOF10 = 0xca, M_SOF11 = 0xcb, M_SOF13 = 0xcd, M_SOF14 = 0xce, M_SOF15 = 0xcf, M_DHT = 0xc4, M_DAC = 0xcc, M_RST0 = 0xd0, M_RST1 = 0xd1, M_RST2 = 0xd2, M_RST3 = 0xd3, M_RST4 = 0xd4, M_RST5 = 0xd5, M_RST6 = 0xd6, M_RST7 = 0xd7, M_SOI = 0xd8, M_EOI = 0xd9, M_SOS = 0xda, M_DQT = 0xdb, M_DNL = 0xdc, M_DRI = 0xdd, M_DHP = 0xde, M_EXP = 0xdf, M_APP0 = 0xe0, M_APP1 = 0xe1, M_APP2 = 0xe2, M_APP3 = 0xe3, M_APP4 = 0xe4, M_APP5 = 0xe5, M_APP6 = 0xe6, M_APP7 = 0xe7, M_APP8 = 0xe8, M_APP9 = 0xe9, M_APP10 = 0xea, M_APP11 = 0xeb, M_APP12 = 0xec, M_APP13 = 0xed, M_APP14 = 0xee, M_APP15 = 0xef, M_JPG0 = 0xf0, M_JPG8 = 0xf8, M_JPG13 = 0xfd, M_COM = 0xfe, M_TEM = 0x01, M_ERROR = 0x100 } JPEG_MARKER; /* Private state */ typedef struct { struct jpeg_marker_reader pub; /* public fields */ /* Application-overridable marker processing methods */ jpeg_marker_parser_method process_COM; jpeg_marker_parser_method process_APPn[16]; /* Limit on marker data length to save for each marker type */ unsigned int length_limit_COM; unsigned int length_limit_APPn[16]; /* Status of COM/APPn marker saving */ jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ unsigned int bytes_read; /* data bytes read so far in marker */ /* Note: cur_marker is not linked into marker_list until it's all read. */ } my_marker_reader; typedef my_marker_reader * my_marker_ptr; /* * Macros for fetching data from the data source module. * * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect * the current restart point; we update them only when we have reached a * suitable place to restart if a suspension occurs. */ /* Declare and initialize local copies of input pointer/count */ #define INPUT_VARS(cinfo) \ struct jpeg_source_mgr * datasrc = (cinfo)->src; \ const JOCTET * next_input_byte = datasrc->next_input_byte; \ size_t bytes_in_buffer = datasrc->bytes_in_buffer /* Unload the local copies --- do this only at a restart boundary */ #define INPUT_SYNC(cinfo) \ ( datasrc->next_input_byte = next_input_byte, \ datasrc->bytes_in_buffer = bytes_in_buffer ) /* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ #define INPUT_RELOAD(cinfo) \ ( next_input_byte = datasrc->next_input_byte, \ bytes_in_buffer = datasrc->bytes_in_buffer ) /* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, * but we must reload the local copies after a successful fill. */ #define MAKE_BYTE_AVAIL(cinfo,action) \ if (bytes_in_buffer == 0) { \ if (! (*datasrc->fill_input_buffer) (cinfo)) \ { action; } \ INPUT_RELOAD(cinfo); \ } /* Read a byte into variable V. * If must suspend, take the specified action (typically "return FALSE"). */ #define INPUT_BYTE(cinfo,V,action) \ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ bytes_in_buffer--; \ V = GETJOCTET(*next_input_byte++); ) /* As above, but read two bytes interpreted as an unsigned 16-bit integer. * V should be declared unsigned int or perhaps INT32. */ #define INPUT_2BYTES(cinfo,V,action) \ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ bytes_in_buffer--; \ V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ MAKE_BYTE_AVAIL(cinfo,action); \ bytes_in_buffer--; \ V += GETJOCTET(*next_input_byte++); ) /* * Routines to process JPEG markers. * * Entry condition: JPEG marker itself has been read and its code saved * in cinfo->unread_marker; input restart point is just after the marker. * * Exit: if return TRUE, have read and processed any parameters, and have * updated the restart point to point after the parameters. * If return FALSE, was forced to suspend before reaching end of * marker parameters; restart point has not been moved. Same routine * will be called again after application supplies more input data. * * This approach to suspension assumes that all of a marker's parameters * can fit into a single input bufferload. This should hold for "normal" * markers. Some COM/APPn markers might have large parameter segments * that might not fit. If we are simply dropping such a marker, we use * skip_input_data to get past it, and thereby put the problem on the * source manager's shoulders. If we are saving the marker's contents * into memory, we use a slightly different convention: when forced to * suspend, the marker processor updates the restart point to the end of * what it's consumed (ie, the end of the buffer) before returning FALSE. * On resumption, cinfo->unread_marker still contains the marker code, * but the data source will point to the next chunk of marker data. * The marker processor must retain internal state to deal with this. * * Note that we don't bother to avoid duplicate trace messages if a * suspension occurs within marker parameters. Other side effects * require more care. */ LOCAL(boolean) get_soi (j_decompress_ptr cinfo) /* Process an SOI marker */ { int i; TRACEMS(cinfo, 1, JTRC_SOI); if (cinfo->marker->saw_SOI) ERREXIT(cinfo, JERR_SOI_DUPLICATE); /* Reset all parameters that are defined to be reset by SOI */ for (i = 0; i < NUM_ARITH_TBLS; i++) { cinfo->arith_dc_L[i] = 0; cinfo->arith_dc_U[i] = 1; cinfo->arith_ac_K[i] = 5; } cinfo->restart_interval = 0; /* Set initial assumptions for colorspace etc */ cinfo->jpeg_color_space = JCS_UNKNOWN; cinfo->color_transform = JCT_NONE; cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ cinfo->saw_JFIF_marker = FALSE; cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ cinfo->JFIF_minor_version = 1; cinfo->density_unit = 0; cinfo->X_density = 1; cinfo->Y_density = 1; cinfo->saw_Adobe_marker = FALSE; cinfo->Adobe_transform = 0; cinfo->marker->saw_SOI = TRUE; return TRUE; } LOCAL(boolean) get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, boolean is_arith) /* Process a SOFn marker */ { INT32 length; int c, ci, i; jpeg_component_info * compptr; INPUT_VARS(cinfo); cinfo->is_baseline = is_baseline; cinfo->progressive_mode = is_prog; cinfo->arith_code = is_arith; INPUT_2BYTES(cinfo, length, return FALSE); INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); length -= 8; TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, (int) cinfo->image_width, (int) cinfo->image_height, cinfo->num_components); if (cinfo->marker->saw_SOF) ERREXIT(cinfo, JERR_SOF_DUPLICATE); /* We don't support files in which the image height is initially specified */ /* as 0 and is later redefined by DNL. As long as we have to check that, */ /* might as well have a general sanity check. */ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || cinfo->num_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); if (length != (cinfo->num_components * 3)) ERREXIT(cinfo, JERR_BAD_LENGTH); if (cinfo->comp_info == NULL) /* do only once, even if suspend */ cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * SIZEOF(jpeg_component_info)); for (ci = 0; ci < cinfo->num_components; ci++) { INPUT_BYTE(cinfo, c, return FALSE); /* Check to see whether component id has already been seen */ /* (in violation of the spec, but unfortunately seen in some */ /* files). If so, create "fake" component id equal to the */ /* max id seen so far + 1. */ for (i = 0, compptr = cinfo->comp_info; i < ci; i++, compptr++) { if (c == compptr->component_id) { compptr = cinfo->comp_info; c = compptr->component_id; compptr++; for (i = 1; i < ci; i++, compptr++) { if (compptr->component_id > c) c = compptr->component_id; } c++; break; } } compptr->component_id = c; compptr->component_index = ci; INPUT_BYTE(cinfo, c, return FALSE); compptr->h_samp_factor = (c >> 4) & 15; compptr->v_samp_factor = (c ) & 15; INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, compptr->component_id, compptr->h_samp_factor, compptr->v_samp_factor, compptr->quant_tbl_no); } cinfo->marker->saw_SOF = TRUE; INPUT_SYNC(cinfo); return TRUE; } LOCAL(boolean) get_sos (j_decompress_ptr cinfo) /* Process a SOS marker */ { INT32 length; int c, ci, i, n; jpeg_component_info * compptr; INPUT_VARS(cinfo); if (! cinfo->marker->saw_SOF) ERREXITS(cinfo, JERR_SOF_BEFORE, "SOS"); INPUT_2BYTES(cinfo, length, return FALSE); INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ TRACEMS1(cinfo, 1, JTRC_SOS, n); if (length != (n * 2 + 6) || n > MAX_COMPS_IN_SCAN || (n == 0 && !cinfo->progressive_mode)) /* pseudo SOS marker only allowed in progressive mode */ ERREXIT(cinfo, JERR_BAD_LENGTH); cinfo->comps_in_scan = n; /* Collect the component-spec parameters */ for (i = 0; i < n; i++) { INPUT_BYTE(cinfo, c, return FALSE); /* Detect the case where component id's are not unique, and, if so, */ /* create a fake component id using the same logic as in get_sof. */ /* Note: This also ensures that all of the SOF components are */ /* referenced in the single scan case, which prevents access to */ /* uninitialized memory in later decoding stages. */ for (ci = 0; ci < i; ci++) { if (c == cinfo->cur_comp_info[ci]->component_id) { c = cinfo->cur_comp_info[0]->component_id; for (ci = 1; ci < i; ci++) { compptr = cinfo->cur_comp_info[ci]; if (compptr->component_id > c) c = compptr->component_id; } c++; break; } } for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (c == compptr->component_id) goto id_found; } ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, c); id_found: cinfo->cur_comp_info[i] = compptr; INPUT_BYTE(cinfo, c, return FALSE); compptr->dc_tbl_no = (c >> 4) & 15; compptr->ac_tbl_no = (c ) & 15; TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, compptr->component_id, compptr->dc_tbl_no, compptr->ac_tbl_no); } /* Collect the additional scan parameters Ss, Se, Ah/Al. */ INPUT_BYTE(cinfo, c, return FALSE); cinfo->Ss = c; INPUT_BYTE(cinfo, c, return FALSE); cinfo->Se = c; INPUT_BYTE(cinfo, c, return FALSE); cinfo->Ah = (c >> 4) & 15; cinfo->Al = (c ) & 15; TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); /* Prepare to scan data & restart markers */ cinfo->marker->next_restart_num = 0; /* Count another (non-pseudo) SOS marker */ if (n) cinfo->input_scan_number++; INPUT_SYNC(cinfo); return TRUE; } #ifdef D_ARITH_CODING_SUPPORTED LOCAL(boolean) get_dac (j_decompress_ptr cinfo) /* Process a DAC marker */ { INT32 length; int index, val; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; while (length > 0) { INPUT_BYTE(cinfo, index, return FALSE); INPUT_BYTE(cinfo, val, return FALSE); length -= 2; TRACEMS2(cinfo, 1, JTRC_DAC, index, val); if (index < 0 || index >= (2*NUM_ARITH_TBLS)) ERREXIT1(cinfo, JERR_DAC_INDEX, index); if (index >= NUM_ARITH_TBLS) { /* define AC table */ cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; } else { /* define DC table */ cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); cinfo->arith_dc_U[index] = (UINT8) (val >> 4); if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) ERREXIT1(cinfo, JERR_DAC_VALUE, val); } } if (length != 0) ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_SYNC(cinfo); return TRUE; } #else /* ! D_ARITH_CODING_SUPPORTED */ #define get_dac(cinfo) skip_variable(cinfo) #endif /* D_ARITH_CODING_SUPPORTED */ LOCAL(boolean) get_dht (j_decompress_ptr cinfo) /* Process a DHT marker */ { INT32 length; UINT8 bits[17]; UINT8 huffval[256]; int i, index, count; JHUFF_TBL **htblptr; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; while (length > 16) { INPUT_BYTE(cinfo, index, return FALSE); TRACEMS1(cinfo, 1, JTRC_DHT, index); bits[0] = 0; count = 0; for (i = 1; i <= 16; i++) { INPUT_BYTE(cinfo, bits[i], return FALSE); count += bits[i]; } length -= 1 + 16; TRACEMS8(cinfo, 2, JTRC_HUFFBITS, bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7], bits[8]); TRACEMS8(cinfo, 2, JTRC_HUFFBITS, bits[9], bits[10], bits[11], bits[12], bits[13], bits[14], bits[15], bits[16]); /* Here we just do minimal validation of the counts to avoid walking * off the end of our table space. jdhuff.c will check more carefully. */ if (count > 256 || ((INT32) count) > length) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); for (i = 0; i < count; i++) INPUT_BYTE(cinfo, huffval[i], return FALSE); length -= count; if (index & 0x10) { /* AC table definition */ index -= 0x10; htblptr = &cinfo->ac_huff_tbl_ptrs[index]; } else { /* DC table definition */ htblptr = &cinfo->dc_huff_tbl_ptrs[index]; } if (index < 0 || index >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_DHT_INDEX, index); if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); if (count > 0) MEMCOPY((*htblptr)->huffval, huffval, count * SIZEOF(UINT8)); } if (length != 0) ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_SYNC(cinfo); return TRUE; } LOCAL(boolean) get_dqt (j_decompress_ptr cinfo) /* Process a DQT marker */ { INT32 length, count, i; int n, prec; unsigned int tmp; JQUANT_TBL *quant_ptr; const int *natural_order; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; while (length > 0) { length--; INPUT_BYTE(cinfo, n, return FALSE); prec = n >> 4; n &= 0x0F; TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); if (n >= NUM_QUANT_TBLS) ERREXIT1(cinfo, JERR_DQT_INDEX, n); if (cinfo->quant_tbl_ptrs[n] == NULL) cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); quant_ptr = cinfo->quant_tbl_ptrs[n]; if (prec) { if (length < DCTSIZE2 * 2) { /* Initialize full table for safety. */ for (i = 0; i < DCTSIZE2; i++) { quant_ptr->quantval[i] = 1; } count = length >> 1; } else count = DCTSIZE2; } else { if (length < DCTSIZE2) { /* Initialize full table for safety. */ for (i = 0; i < DCTSIZE2; i++) { quant_ptr->quantval[i] = 1; } count = length; } else count = DCTSIZE2; } switch ((int) count) { case (2*2): natural_order = jpeg_natural_order2; break; case (3*3): natural_order = jpeg_natural_order3; break; case (4*4): natural_order = jpeg_natural_order4; break; case (5*5): natural_order = jpeg_natural_order5; break; case (6*6): natural_order = jpeg_natural_order6; break; case (7*7): natural_order = jpeg_natural_order7; break; default: natural_order = jpeg_natural_order; } for (i = 0; i < count; i++) { if (prec) INPUT_2BYTES(cinfo, tmp, return FALSE); else INPUT_BYTE(cinfo, tmp, return FALSE); /* We convert the zigzag-order table to natural array order. */ quant_ptr->quantval[natural_order[i]] = (UINT16) tmp; } if (cinfo->err->trace_level >= 2) { for (i = 0; i < DCTSIZE2; i += 8) { TRACEMS8(cinfo, 2, JTRC_QUANTVALS, quant_ptr->quantval[i], quant_ptr->quantval[i+1], quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); } } length -= count; if (prec) length -= count; } if (length != 0) ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_SYNC(cinfo); return TRUE; } LOCAL(boolean) get_dri (j_decompress_ptr cinfo) /* Process a DRI marker */ { INT32 length; unsigned int tmp; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); if (length != 4) ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_2BYTES(cinfo, tmp, return FALSE); TRACEMS1(cinfo, 1, JTRC_DRI, tmp); cinfo->restart_interval = tmp; INPUT_SYNC(cinfo); return TRUE; } LOCAL(boolean) get_lse (j_decompress_ptr cinfo) /* Process an LSE marker */ { INT32 length; unsigned int tmp; int cid; INPUT_VARS(cinfo); if (! cinfo->marker->saw_SOF) ERREXITS(cinfo, JERR_SOF_BEFORE, "LSE"); if (cinfo->num_components < 3) goto bad; INPUT_2BYTES(cinfo, length, return FALSE); if (length != 24) ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_BYTE(cinfo, tmp, return FALSE); if (tmp != 0x0D) /* ID inverse transform specification */ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); INPUT_2BYTES(cinfo, tmp, return FALSE); if (tmp != MAXJSAMPLE) goto bad; /* MAXTRANS */ INPUT_BYTE(cinfo, tmp, return FALSE); if (tmp != 3) goto bad; /* Nt=3 */ INPUT_BYTE(cinfo, cid, return FALSE); if (cid != cinfo->comp_info[1].component_id) goto bad; INPUT_BYTE(cinfo, cid, return FALSE); if (cid != cinfo->comp_info[0].component_id) goto bad; INPUT_BYTE(cinfo, cid, return FALSE); if (cid != cinfo->comp_info[2].component_id) goto bad; INPUT_BYTE(cinfo, tmp, return FALSE); if (tmp != 0x80) goto bad; /* F1: CENTER1=1, NORM1=0 */ INPUT_2BYTES(cinfo, tmp, return FALSE); if (tmp != 0) goto bad; /* A(1,1)=0 */ INPUT_2BYTES(cinfo, tmp, return FALSE); if (tmp != 0) goto bad; /* A(1,2)=0 */ INPUT_BYTE(cinfo, tmp, return FALSE); if (tmp != 0) goto bad; /* F2: CENTER2=0, NORM2=0 */ INPUT_2BYTES(cinfo, tmp, return FALSE); if (tmp != 1) goto bad; /* A(2,1)=1 */ INPUT_2BYTES(cinfo, tmp, return FALSE); if (tmp != 0) goto bad; /* A(2,2)=0 */ INPUT_BYTE(cinfo, tmp, return FALSE); if (tmp != 0) goto bad; /* F3: CENTER3=0, NORM3=0 */ INPUT_2BYTES(cinfo, tmp, return FALSE); if (tmp != 1) goto bad; /* A(3,1)=1 */ INPUT_2BYTES(cinfo, tmp, return FALSE); if (tmp != 0) { /* A(3,2)=0 */ bad: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } /* OK, valid transform that we can handle. */ cinfo->color_transform = JCT_SUBTRACT_GREEN; INPUT_SYNC(cinfo); return TRUE; } /* * Routines for processing APPn and COM markers. * These are either saved in memory or discarded, per application request. * APP0 and APP14 are specially checked to see if they are * JFIF and Adobe markers, respectively. */ #define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ #define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ #define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ LOCAL(void) examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, unsigned int datalen, INT32 remaining) /* Examine first few bytes from an APP0. * Take appropriate action if it is a JFIF marker. * datalen is # of bytes at data[], remaining is length of rest of marker data. */ { INT32 totallen = (INT32) datalen + remaining; if (datalen >= APP0_DATA_LEN && GETJOCTET(data[0]) == 0x4A && GETJOCTET(data[1]) == 0x46 && GETJOCTET(data[2]) == 0x49 && GETJOCTET(data[3]) == 0x46 && GETJOCTET(data[4]) == 0) { /* Found JFIF APP0 marker: save info */ cinfo->saw_JFIF_marker = TRUE; cinfo->JFIF_major_version = GETJOCTET(data[5]); cinfo->JFIF_minor_version = GETJOCTET(data[6]); cinfo->density_unit = GETJOCTET(data[7]); cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); /* Check version. * Major version must be 1 or 2, anything else signals an incompatible * change. * (We used to treat this as an error, but now it's a nonfatal warning, * because some bozo at Hijaak couldn't read the spec.) * Minor version should be 0..2, but process anyway if newer. */ if (cinfo->JFIF_major_version != 1 && cinfo->JFIF_major_version != 2) WARNMS2(cinfo, JWRN_JFIF_MAJOR, cinfo->JFIF_major_version, cinfo->JFIF_minor_version); /* Generate trace messages */ TRACEMS5(cinfo, 1, JTRC_JFIF, cinfo->JFIF_major_version, cinfo->JFIF_minor_version, cinfo->X_density, cinfo->Y_density, cinfo->density_unit); /* Validate thumbnail dimensions and issue appropriate messages */ if (GETJOCTET(data[12]) | GETJOCTET(data[13])) TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, GETJOCTET(data[12]), GETJOCTET(data[13])); totallen -= APP0_DATA_LEN; if (totallen != ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); } else if (datalen >= 6 && GETJOCTET(data[0]) == 0x4A && GETJOCTET(data[1]) == 0x46 && GETJOCTET(data[2]) == 0x58 && GETJOCTET(data[3]) == 0x58 && GETJOCTET(data[4]) == 0) { /* Found JFIF "JFXX" extension APP0 marker */ /* The library doesn't actually do anything with these, * but we try to produce a helpful trace message. */ switch (GETJOCTET(data[5])) { case 0x10: TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); break; case 0x11: TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); break; case 0x13: TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); break; default: TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, GETJOCTET(data[5]), (int) totallen); } } else { /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); } } LOCAL(void) examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, unsigned int datalen, INT32 remaining) /* Examine first few bytes from an APP14. * Take appropriate action if it is an Adobe marker. * datalen is # of bytes at data[], remaining is length of rest of marker data. */ { unsigned int version, flags0, flags1, transform; if (datalen >= APP14_DATA_LEN && GETJOCTET(data[0]) == 0x41 && GETJOCTET(data[1]) == 0x64 && GETJOCTET(data[2]) == 0x6F && GETJOCTET(data[3]) == 0x62 && GETJOCTET(data[4]) == 0x65) { /* Found Adobe APP14 marker */ version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); transform = GETJOCTET(data[11]); TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); cinfo->saw_Adobe_marker = TRUE; cinfo->Adobe_transform = (UINT8) transform; } else { /* Start of APP14 does not match "Adobe", or too short */ TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); } } METHODDEF(boolean) get_interesting_appn (j_decompress_ptr cinfo) /* Process an APP0 or APP14 marker without saving it */ { INT32 length; JOCTET b[APPN_DATA_LEN]; unsigned int i, numtoread; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; /* get the interesting part of the marker data */ if (length >= APPN_DATA_LEN) numtoread = APPN_DATA_LEN; else if (length > 0) numtoread = (unsigned int) length; else numtoread = 0; for (i = 0; i < numtoread; i++) INPUT_BYTE(cinfo, b[i], return FALSE); length -= numtoread; /* process it */ switch (cinfo->unread_marker) { case M_APP0: examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); break; case M_APP14: examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); break; default: /* can't get here unless jpeg_save_markers chooses wrong processor */ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); } /* skip any remaining data -- could be lots */ INPUT_SYNC(cinfo); if (length > 0) (*cinfo->src->skip_input_data) (cinfo, (long) length); return TRUE; } #ifdef SAVE_MARKERS_SUPPORTED METHODDEF(boolean) save_marker (j_decompress_ptr cinfo) /* Save an APPn or COM marker into the marker list */ { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; jpeg_saved_marker_ptr cur_marker = marker->cur_marker; unsigned int bytes_read, data_length; JOCTET FAR * data; INT32 length = 0; INPUT_VARS(cinfo); if (cur_marker == NULL) { /* begin reading a marker */ INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; if (length >= 0) { /* watch out for bogus length word */ /* figure out how much we want to save */ unsigned int limit; if (cinfo->unread_marker == (int) M_COM) limit = marker->length_limit_COM; else limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; if ((unsigned int) length < limit) limit = (unsigned int) length; /* allocate and initialize the marker item */ cur_marker = (jpeg_saved_marker_ptr) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(struct jpeg_marker_struct) + limit); cur_marker->next = NULL; cur_marker->marker = (UINT8) cinfo->unread_marker; cur_marker->original_length = (unsigned int) length; cur_marker->data_length = limit; /* data area is just beyond the jpeg_marker_struct */ data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); marker->cur_marker = cur_marker; marker->bytes_read = 0; bytes_read = 0; data_length = limit; } else { /* deal with bogus length word */ bytes_read = data_length = 0; data = NULL; } } else { /* resume reading a marker */ bytes_read = marker->bytes_read; data_length = cur_marker->data_length; data = cur_marker->data + bytes_read; } while (bytes_read < data_length) { INPUT_SYNC(cinfo); /* move the restart point to here */ marker->bytes_read = bytes_read; /* If there's not at least one byte in buffer, suspend */ MAKE_BYTE_AVAIL(cinfo, return FALSE); /* Copy bytes with reasonable rapidity */ while (bytes_read < data_length && bytes_in_buffer > 0) { *data++ = *next_input_byte++; bytes_in_buffer--; bytes_read++; } } /* Done reading what we want to read */ if (cur_marker != NULL) { /* will be NULL if bogus length word */ /* Add new marker to end of list */ if (cinfo->marker_list == NULL) { cinfo->marker_list = cur_marker; } else { jpeg_saved_marker_ptr prev = cinfo->marker_list; while (prev->next != NULL) prev = prev->next; prev->next = cur_marker; } /* Reset pointer & calc remaining data length */ data = cur_marker->data; length = cur_marker->original_length - data_length; } /* Reset to initial state for next marker */ marker->cur_marker = NULL; /* Process the marker if interesting; else just make a generic trace msg */ switch (cinfo->unread_marker) { case M_APP0: examine_app0(cinfo, data, data_length, length); break; case M_APP14: examine_app14(cinfo, data, data_length, length); break; default: TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) (data_length + length)); } /* skip any remaining data -- could be lots */ INPUT_SYNC(cinfo); /* do before skip_input_data */ if (length > 0) (*cinfo->src->skip_input_data) (cinfo, (long) length); return TRUE; } #endif /* SAVE_MARKERS_SUPPORTED */ METHODDEF(boolean) skip_variable (j_decompress_ptr cinfo) /* Skip over an unknown or uninteresting variable-length marker */ { INT32 length; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); INPUT_SYNC(cinfo); /* do before skip_input_data */ if (length > 0) (*cinfo->src->skip_input_data) (cinfo, (long) length); return TRUE; } /* * Find the next JPEG marker, save it in cinfo->unread_marker. * Returns FALSE if had to suspend before reaching a marker; * in that case cinfo->unread_marker is unchanged. * * Note that the result might not be a valid marker code, * but it will never be 0 or FF. */ LOCAL(boolean) next_marker (j_decompress_ptr cinfo) { int c; INPUT_VARS(cinfo); for (;;) { INPUT_BYTE(cinfo, c, return FALSE); /* Skip any non-FF bytes. * This may look a bit inefficient, but it will not occur in a valid file. * We sync after each discarded byte so that a suspending data source * can discard the byte from its buffer. */ while (c != 0xFF) { cinfo->marker->discarded_bytes++; INPUT_SYNC(cinfo); INPUT_BYTE(cinfo, c, return FALSE); } /* This loop swallows any duplicate FF bytes. Extra FFs are legal as * pad bytes, so don't count them in discarded_bytes. We assume there * will not be so many consecutive FF bytes as to overflow a suspending * data source's input buffer. */ do { INPUT_BYTE(cinfo, c, return FALSE); } while (c == 0xFF); if (c != 0) break; /* found a valid marker, exit loop */ /* Reach here if we found a stuffed-zero data sequence (FF/00). * Discard it and loop back to try again. */ cinfo->marker->discarded_bytes += 2; INPUT_SYNC(cinfo); } if (cinfo->marker->discarded_bytes != 0) { WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); cinfo->marker->discarded_bytes = 0; } cinfo->unread_marker = c; INPUT_SYNC(cinfo); return TRUE; } LOCAL(boolean) first_marker (j_decompress_ptr cinfo) /* Like next_marker, but used to obtain the initial SOI marker. */ /* For this marker, we do not allow preceding garbage or fill; otherwise, * we might well scan an entire input file before realizing it ain't JPEG. * If an application wants to process non-JFIF files, it must seek to the * SOI before calling the JPEG library. */ { int c, c2; INPUT_VARS(cinfo); INPUT_BYTE(cinfo, c, return FALSE); INPUT_BYTE(cinfo, c2, return FALSE); if (c != 0xFF || c2 != (int) M_SOI) ERREXIT2(cinfo, JERR_NO_SOI, c, c2); cinfo->unread_marker = c2; INPUT_SYNC(cinfo); return TRUE; } /* * Read markers until SOS or EOI. * * Returns same codes as are defined for jpeg_consume_input: * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. * * Note: This function may return a pseudo SOS marker (with zero * component number) for treat by input controller's consume_input. * consume_input itself should filter out (skip) the pseudo marker * after processing for the caller. */ METHODDEF(int) read_markers (j_decompress_ptr cinfo) { /* Outer loop repeats once for each marker. */ for (;;) { /* Collect the marker proper, unless we already did. */ /* NB: first_marker() enforces the requirement that SOI appear first. */ if (cinfo->unread_marker == 0) { if (! cinfo->marker->saw_SOI) { if (! first_marker(cinfo)) return JPEG_SUSPENDED; } else { if (! next_marker(cinfo)) return JPEG_SUSPENDED; } } /* At this point cinfo->unread_marker contains the marker code and the * input point is just past the marker proper, but before any parameters. * A suspension will cause us to return with this state still true. */ switch (cinfo->unread_marker) { case M_SOI: if (! get_soi(cinfo)) return JPEG_SUSPENDED; break; case M_SOF0: /* Baseline */ if (! get_sof(cinfo, TRUE, FALSE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF1: /* Extended sequential, Huffman */ if (! get_sof(cinfo, FALSE, FALSE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF2: /* Progressive, Huffman */ if (! get_sof(cinfo, FALSE, TRUE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF9: /* Extended sequential, arithmetic */ if (! get_sof(cinfo, FALSE, FALSE, TRUE)) return JPEG_SUSPENDED; break; case M_SOF10: /* Progressive, arithmetic */ if (! get_sof(cinfo, FALSE, TRUE, TRUE)) return JPEG_SUSPENDED; break; /* Currently unsupported SOFn types */ case M_SOF3: /* Lossless, Huffman */ case M_SOF5: /* Differential sequential, Huffman */ case M_SOF6: /* Differential progressive, Huffman */ case M_SOF7: /* Differential lossless, Huffman */ case M_JPG: /* Reserved for JPEG extensions */ case M_SOF11: /* Lossless, arithmetic */ case M_SOF13: /* Differential sequential, arithmetic */ case M_SOF14: /* Differential progressive, arithmetic */ case M_SOF15: /* Differential lossless, arithmetic */ ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); break; case M_SOS: if (! get_sos(cinfo)) return JPEG_SUSPENDED; cinfo->unread_marker = 0; /* processed the marker */ return JPEG_REACHED_SOS; case M_EOI: TRACEMS(cinfo, 1, JTRC_EOI); cinfo->unread_marker = 0; /* processed the marker */ return JPEG_REACHED_EOI; case M_DAC: if (! get_dac(cinfo)) return JPEG_SUSPENDED; break; case M_DHT: if (! get_dht(cinfo)) return JPEG_SUSPENDED; break; case M_DQT: if (! get_dqt(cinfo)) return JPEG_SUSPENDED; break; case M_DRI: if (! get_dri(cinfo)) return JPEG_SUSPENDED; break; case M_JPG8: if (! get_lse(cinfo)) return JPEG_SUSPENDED; break; case M_APP0: case M_APP1: case M_APP2: case M_APP3: case M_APP4: case M_APP5: case M_APP6: case M_APP7: case M_APP8: case M_APP9: case M_APP10: case M_APP11: case M_APP12: case M_APP13: case M_APP14: case M_APP15: if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ cinfo->unread_marker - (int) M_APP0]) (cinfo)) return JPEG_SUSPENDED; break; case M_COM: if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) return JPEG_SUSPENDED; break; case M_RST0: /* these are all parameterless */ case M_RST1: case M_RST2: case M_RST3: case M_RST4: case M_RST5: case M_RST6: case M_RST7: case M_TEM: TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); break; case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ if (! skip_variable(cinfo)) return JPEG_SUSPENDED; break; default: /* must be DHP, EXP, JPGn, or RESn */ /* For now, we treat the reserved markers as fatal errors since they are * likely to be used to signal incompatible JPEG Part 3 extensions. * Once the JPEG 3 version-number marker is well defined, this code * ought to change! */ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); } /* Successfully processed marker, so reset state variable */ cinfo->unread_marker = 0; } /* end loop */ } /* * Read a restart marker, which is expected to appear next in the datastream; * if the marker is not there, take appropriate recovery action. * Returns FALSE if suspension is required. * * This is called by the entropy decoder after it has read an appropriate * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder * has already read a marker from the data source. Under normal conditions * cinfo->unread_marker will be reset to 0 before returning; if not reset, * it holds a marker which the decoder will be unable to read past. */ METHODDEF(boolean) read_restart_marker (j_decompress_ptr cinfo) { /* Obtain a marker unless we already did. */ /* Note that next_marker will complain if it skips any data. */ if (cinfo->unread_marker == 0) { if (! next_marker(cinfo)) return FALSE; } if (cinfo->unread_marker == ((int) M_RST0 + cinfo->marker->next_restart_num)) { /* Normal case --- swallow the marker and let entropy decoder continue */ TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); cinfo->unread_marker = 0; } else { /* Uh-oh, the restart markers have been messed up. */ /* Let the data source manager determine how to resync. */ if (! (*cinfo->src->resync_to_restart) (cinfo, cinfo->marker->next_restart_num)) return FALSE; } /* Update next-restart state */ cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; return TRUE; } /* * This is the default resync_to_restart method for data source managers * to use if they don't have any better approach. Some data source managers * may be able to back up, or may have additional knowledge about the data * which permits a more intelligent recovery strategy; such managers would * presumably supply their own resync method. * * read_restart_marker calls resync_to_restart if it finds a marker other than * the restart marker it was expecting. (This code is *not* used unless * a nonzero restart interval has been declared.) cinfo->unread_marker is * the marker code actually found (might be anything, except 0 or FF). * The desired restart marker number (0..7) is passed as a parameter. * This routine is supposed to apply whatever error recovery strategy seems * appropriate in order to position the input stream to the next data segment. * Note that cinfo->unread_marker is treated as a marker appearing before * the current data-source input point; usually it should be reset to zero * before returning. * Returns FALSE if suspension is required. * * This implementation is substantially constrained by wanting to treat the * input as a data stream; this means we can't back up. Therefore, we have * only the following actions to work with: * 1. Simply discard the marker and let the entropy decoder resume at next * byte of file. * 2. Read forward until we find another marker, discarding intervening * data. (In theory we could look ahead within the current bufferload, * without having to discard data if we don't find the desired marker. * This idea is not implemented here, in part because it makes behavior * dependent on buffer size and chance buffer-boundary positions.) * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). * This will cause the entropy decoder to process an empty data segment, * inserting dummy zeroes, and then we will reprocess the marker. * * #2 is appropriate if we think the desired marker lies ahead, while #3 is * appropriate if the found marker is a future restart marker (indicating * that we have missed the desired restart marker, probably because it got * corrupted). * We apply #2 or #3 if the found marker is a restart marker no more than * two counts behind or ahead of the expected one. We also apply #2 if the * found marker is not a legal JPEG marker code (it's certainly bogus data). * If the found marker is a restart marker more than 2 counts away, we do #1 * (too much risk that the marker is erroneous; with luck we will be able to * resync at some future point). * For any valid non-restart JPEG marker, we apply #3. This keeps us from * overrunning the end of a scan. An implementation limited to single-scan * files might find it better to apply #2 for markers other than EOI, since * any other marker would have to be bogus data in that case. */ GLOBAL(boolean) jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) { int marker = cinfo->unread_marker; int action = 1; /* Always put up a warning. */ WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); /* Outer loop handles repeated decision after scanning forward. */ for (;;) { if (marker < (int) M_SOF0) action = 2; /* invalid marker */ else if (marker < (int) M_RST0 || marker > (int) M_RST7) action = 3; /* valid non-restart marker */ else { if (marker == ((int) M_RST0 + ((desired+1) & 7)) || marker == ((int) M_RST0 + ((desired+2) & 7))) action = 3; /* one of the next two expected restarts */ else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || marker == ((int) M_RST0 + ((desired-2) & 7))) action = 2; /* a prior restart, so advance */ else action = 1; /* desired restart or too far away */ } TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); switch (action) { case 1: /* Discard marker and let entropy decoder resume processing. */ cinfo->unread_marker = 0; return TRUE; case 2: /* Scan to the next marker, and repeat the decision loop. */ if (! next_marker(cinfo)) return FALSE; marker = cinfo->unread_marker; break; case 3: /* Return without advancing past this marker. */ /* Entropy decoder will be forced to process an empty segment. */ return TRUE; } } /* end loop */ } /* * Reset marker processing state to begin a fresh datastream. */ METHODDEF(void) reset_marker_reader (j_decompress_ptr cinfo) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; cinfo->comp_info = NULL; /* until allocated by get_sof */ cinfo->input_scan_number = 0; /* no SOS seen yet */ cinfo->unread_marker = 0; /* no pending marker */ marker->pub.saw_SOI = FALSE; /* set internal state too */ marker->pub.saw_SOF = FALSE; marker->pub.discarded_bytes = 0; marker->cur_marker = NULL; } /* * Initialize the marker reader module. * This is called only once, when the decompression object is created. */ GLOBAL(void) jinit_marker_reader (j_decompress_ptr cinfo) { my_marker_ptr marker; int i; /* Create subobject in permanent pool */ marker = (my_marker_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_marker_reader)); cinfo->marker = &marker->pub; /* Initialize public method pointers */ marker->pub.reset_marker_reader = reset_marker_reader; marker->pub.read_markers = read_markers; marker->pub.read_restart_marker = read_restart_marker; /* Initialize COM/APPn processing. * By default, we examine and then discard APP0 and APP14, * but simply discard COM and all other APPn. */ marker->process_COM = skip_variable; marker->length_limit_COM = 0; for (i = 0; i < 16; i++) { marker->process_APPn[i] = skip_variable; marker->length_limit_APPn[i] = 0; } marker->process_APPn[0] = get_interesting_appn; marker->process_APPn[14] = get_interesting_appn; /* Reset marker processing state */ reset_marker_reader(cinfo); } /* * Control saving of COM and APPn markers into marker_list. */ #ifdef SAVE_MARKERS_SUPPORTED GLOBAL(void) jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, unsigned int length_limit) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; long maxlength; jpeg_marker_parser_method processor; /* Length limit mustn't be larger than what we can allocate * (should only be a concern in a 16-bit environment). */ maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); if (((long) length_limit) > maxlength) length_limit = (unsigned int) maxlength; /* Choose processor routine to use. * APP0/APP14 have special requirements. */ if (length_limit) { processor = save_marker; /* If saving APP0/APP14, save at least enough for our internal use. */ if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) length_limit = APP0_DATA_LEN; else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) length_limit = APP14_DATA_LEN; } else { processor = skip_variable; /* If discarding APP0/APP14, use our regular on-the-fly processor. */ if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) processor = get_interesting_appn; } if (marker_code == (int) M_COM) { marker->process_COM = processor; marker->length_limit_COM = length_limit; } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { marker->process_APPn[marker_code - (int) M_APP0] = processor; marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; } else ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); } #endif /* SAVE_MARKERS_SUPPORTED */ /* * Install a special processing method for COM or APPn markers. */ GLOBAL(void) jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, jpeg_marker_parser_method routine) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; if (marker_code == (int) M_COM) marker->process_COM = routine; else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) marker->process_APPn[marker_code - (int) M_APP0] = routine; else ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); } fltk-1.4.3/jpeg/jquant1.c0000644000175000017500000007506215004135251015273 0ustar albrechtalbrecht/* * jquant1.c * * Copyright (C) 1991-1996, Thomas G. Lane. * Modified 2011-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains 1-pass color quantization (color mapping) routines. * These routines provide mapping to a fixed color map using equally spaced * color values. Optional Floyd-Steinberg or ordered dithering is available. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #ifdef QUANT_1PASS_SUPPORTED /* * The main purpose of 1-pass quantization is to provide a fast, if not very * high quality, colormapped output capability. A 2-pass quantizer usually * gives better visual quality; however, for quantized grayscale output this * quantizer is perfectly adequate. Dithering is highly recommended with this * quantizer, though you can turn it off if you really want to. * * In 1-pass quantization the colormap must be chosen in advance of seeing the * image. We use a map consisting of all combinations of Ncolors[i] color * values for the i'th component. The Ncolors[] values are chosen so that * their product, the total number of colors, is no more than that requested. * (In most cases, the product will be somewhat less.) * * Since the colormap is orthogonal, the representative value for each color * component can be determined without considering the other components; * then these indexes can be combined into a colormap index by a standard * N-dimensional-array-subscript calculation. Most of the arithmetic involved * can be precalculated and stored in the lookup table colorindex[]. * colorindex[i][j] maps pixel value j in component i to the nearest * representative value (grid plane) for that component; this index is * multiplied by the array stride for component i, so that the * index of the colormap entry closest to a given pixel value is just * sum( colorindex[component-number][pixel-component-value] ) * Aside from being fast, this scheme allows for variable spacing between * representative values with no additional lookup cost. * * If gamma correction has been applied in color conversion, it might be wise * to adjust the color grid spacing so that the representative colors are * equidistant in linear space. At this writing, gamma correction is not * implemented by jdcolor, so nothing is done here. */ /* Declarations for ordered dithering. * * We use a standard 16x16 ordered dither array. The basic concept of ordered * dithering is described in many references, for instance Dale Schumacher's * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). * In place of Schumacher's comparisons against a "threshold" value, we add a * "dither" value to the input pixel and then round the result to the nearest * output value. The dither value is equivalent to (0.5 - threshold) times * the distance between output values. For ordered dithering, we assume that * the output colors are equally spaced; if not, results will probably be * worse, since the dither may be too much or too little at a given point. * * The normal calculation would be to form pixel value + dither, range-limit * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. * We can skip the separate range-limiting step by extending the colorindex * table in both directions. */ #define ODITHER_SIZE 16 /* dimension of dither matrix */ /* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ #define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ #define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { /* Bayer's order-4 dither array. Generated by the code given in * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. * The values in this array must range from 0 to ODITHER_CELLS-1. */ { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } }; /* Declarations for Floyd-Steinberg dithering. * * Errors are accumulated into the array fserrors[], at a resolution of * 1/16th of a pixel count. The error at a given pixel is propagated * to its not-yet-processed neighbors using the standard F-S fractions, * ... (here) 7/16 * 3/16 5/16 1/16 * We work left-to-right on even rows, right-to-left on odd rows. * * We can get away with a single array (holding one row's worth of errors) * by using it to store the current row's errors at pixel columns not yet * processed, but the next row's errors at columns already processed. We * need only a few extra variables to hold the errors immediately around the * current column. (If we are lucky, those variables are in registers, but * even if not, they're probably cheaper to access than array elements are.) * * The fserrors[] array is indexed [component#][position]. * We provide (#columns + 2) entries per component; the extra entry at each * end saves us from special-casing the first and last pixels. * * Note: on a wide image, we might not have enough room in a PC's near data * segment to hold the error array; so it is allocated with alloc_large. */ #if BITS_IN_JSAMPLE == 8 typedef INT16 FSERROR; /* 16 bits should be enough */ typedef int LOCFSERROR; /* use 'int' for calculation temps */ #else typedef INT32 FSERROR; /* may need more than 16 bits */ typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ #endif typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ /* Private subobject */ #define MAX_Q_COMPS 4 /* max components I can handle */ typedef struct { struct jpeg_color_quantizer pub; /* public fields */ /* Initially allocated colormap is saved here */ JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ int sv_actual; /* number of entries in use */ JSAMPARRAY colorindex; /* Precomputed mapping for speed */ /* colorindex[i][j] = index of color closest to pixel value j in component i, * premultiplied as described above. Since colormap indexes must fit into * JSAMPLEs, the entries of this array will too. */ boolean is_padded; /* is the colorindex padded for odither? */ int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ /* Variables for ordered dithering */ int row_index; /* cur row's vertical index in dither matrix */ ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ /* Variables for Floyd-Steinberg dithering */ FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ boolean on_odd_row; /* flag to remember which row we are on */ } my_cquantizer; typedef my_cquantizer * my_cquantize_ptr; /* * Policy-making subroutines for create_colormap and create_colorindex. * These routines determine the colormap to be used. The rest of the module * only assumes that the colormap is orthogonal. * * * select_ncolors decides how to divvy up the available colors * among the components. * * output_value defines the set of representative values for a component. * * largest_input_value defines the mapping from input values to * representative values for a component. * Note that the latter two routines may impose different policies for * different components, though this is not currently done. */ LOCAL(int) select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) /* Determine allocation of desired colors to components, */ /* and fill in Ncolors[] array to indicate choice. */ /* Return value is total number of colors (product of Ncolors[] values). */ { int nc = cinfo->out_color_components; /* number of color components */ int max_colors = cinfo->desired_number_of_colors; int total_colors, iroot, i, j; boolean changed; long temp; static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; /* We can allocate at least the nc'th root of max_colors per component. */ /* Compute floor(nc'th root of max_colors). */ iroot = 1; do { iroot++; temp = iroot; /* set temp = iroot ** nc */ for (i = 1; i < nc; i++) temp *= iroot; } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ iroot--; /* now iroot = floor(root) */ /* Must have at least 2 color values per component */ if (iroot < 2) ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); /* Initialize to iroot color values for each component */ total_colors = 1; for (i = 0; i < nc; i++) { Ncolors[i] = iroot; total_colors *= iroot; } /* We may be able to increment the count for one or more components without * exceeding max_colors, though we know not all can be incremented. * Sometimes, the first component can be incremented more than once! * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) * In RGB colorspace, try to increment G first, then R, then B. */ do { changed = FALSE; for (i = 0; i < nc; i++) { j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); /* calculate new total_colors if Ncolors[j] is incremented */ temp = total_colors / Ncolors[j]; temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ if (temp > (long) max_colors) break; /* won't fit, done with this pass */ Ncolors[j]++; /* OK, apply the increment */ total_colors = (int) temp; changed = TRUE; } } while (changed); return total_colors; } LOCAL(int) output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) /* Return j'th output value, where j will range from 0 to maxj */ /* The output values must fall in 0..MAXJSAMPLE in increasing order */ { /* We always provide values 0 and MAXJSAMPLE for each component; * any additional values are equally spaced between these limits. * (Forcing the upper and lower values to the limits ensures that * dithering can't produce a color outside the selected gamut.) */ return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); } LOCAL(int) largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) /* Return largest input value that should map to j'th output value */ /* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ { /* Breakpoints are halfway between values returned by output_value */ return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); } /* * Create the colormap. */ LOCAL(void) create_colormap (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; JSAMPARRAY colormap; /* Created colormap */ int total_colors; /* Number of distinct output colors */ int i,j,k, nci, blksize, blkdist, ptr, val; /* Select number of colors for each component */ total_colors = select_ncolors(cinfo, cquantize->Ncolors); /* Report selected color counts */ if (cinfo->out_color_components == 3) TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, total_colors, cquantize->Ncolors[0], cquantize->Ncolors[1], cquantize->Ncolors[2]); else TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); /* Allocate and fill in the colormap. */ /* The colors are ordered in the map in standard row-major order, */ /* i.e. rightmost (highest-indexed) color changes most rapidly. */ colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); /* blksize is number of adjacent repeated entries for a component */ /* blkdist is distance between groups of identical entries for a component */ blkdist = total_colors; for (i = 0; i < cinfo->out_color_components; i++) { /* fill in colormap entries for i'th color component */ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ blksize = blkdist / nci; for (j = 0; j < nci; j++) { /* Compute j'th output value (out of nci) for component */ val = output_value(cinfo, i, j, nci-1); /* Fill in all colormap entries that have this value of this component */ for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { /* fill in blksize entries beginning at ptr */ for (k = 0; k < blksize; k++) colormap[i][ptr+k] = (JSAMPLE) val; } } blkdist = blksize; /* blksize of this color is blkdist of next */ } /* Save the colormap in private storage, * where it will survive color quantization mode changes. */ cquantize->sv_colormap = colormap; cquantize->sv_actual = total_colors; } /* * Create the color index table. */ LOCAL(void) create_colorindex (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; JSAMPROW indexptr; int i,j,k, nci, blksize, val, pad; /* For ordered dither, we pad the color index tables by MAXJSAMPLE in * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). * This is not necessary in the other dithering modes. However, we * flag whether it was done in case user changes dithering mode. */ if (cinfo->dither_mode == JDITHER_ORDERED) { pad = MAXJSAMPLE*2; cquantize->is_padded = TRUE; } else { pad = 0; cquantize->is_padded = FALSE; } cquantize->colorindex = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) (MAXJSAMPLE+1 + pad), (JDIMENSION) cinfo->out_color_components); /* blksize is number of adjacent repeated entries for a component */ blksize = cquantize->sv_actual; for (i = 0; i < cinfo->out_color_components; i++) { /* fill in colorindex entries for i'th color component */ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ blksize = blksize / nci; /* adjust colorindex pointers to provide padding at negative indexes. */ if (pad) cquantize->colorindex[i] += MAXJSAMPLE; /* in loop, val = index of current output value, */ /* and k = largest j that maps to current val */ indexptr = cquantize->colorindex[i]; val = 0; k = largest_input_value(cinfo, i, 0, nci-1); for (j = 0; j <= MAXJSAMPLE; j++) { while (j > k) /* advance val if past boundary */ k = largest_input_value(cinfo, i, ++val, nci-1); /* premultiply so that no multiplication needed in main processing */ indexptr[j] = (JSAMPLE) (val * blksize); } /* Pad at both ends if necessary */ if (pad) for (j = 1; j <= MAXJSAMPLE; j++) { indexptr[-j] = indexptr[0]; indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; } } } /* * Create an ordered-dither array for a component having ncolors * distinct output values. */ LOCAL(ODITHER_MATRIX_PTR) make_odither_array (j_decompress_ptr cinfo, int ncolors) { ODITHER_MATRIX_PTR odither; int j,k; INT32 num,den; odither = (ODITHER_MATRIX_PTR) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(ODITHER_MATRIX)); /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). * Hence the dither value for the matrix cell with fill order f * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). * On 16-bit-int machine, be careful to avoid overflow. */ den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1)); for (j = 0; j < ODITHER_SIZE; j++) { for (k = 0; k < ODITHER_SIZE; k++) { num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) * MAXJSAMPLE; /* Ensure round towards zero despite C's lack of consistency * about rounding negative values in integer division... */ odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); } } return odither; } /* * Create the ordered-dither tables. * Components having the same number of representative colors may * share a dither table. */ LOCAL(void) create_odither_tables (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; ODITHER_MATRIX_PTR odither; int i, j, nci; for (i = 0; i < cinfo->out_color_components; i++) { nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ odither = NULL; /* search for matching prior component */ for (j = 0; j < i; j++) { if (nci == cquantize->Ncolors[j]) { odither = cquantize->odither[j]; break; } } if (odither == NULL) /* need a new table? */ odither = make_odither_array(cinfo, nci); cquantize->odither[i] = odither; } } /* * Map some rows of pixels to the output colormapped representation. */ METHODDEF(void) color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* General case, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; JSAMPARRAY colorindex = cquantize->colorindex; register int pixcode, ci; register JSAMPROW ptrin, ptrout; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; register int nc = cinfo->out_color_components; for (row = 0; row < num_rows; row++) { ptrin = input_buf[row]; ptrout = output_buf[row]; for (col = width; col > 0; col--) { pixcode = 0; for (ci = 0; ci < nc; ci++) { pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); } *ptrout++ = (JSAMPLE) pixcode; } } } METHODDEF(void) color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* Fast path for out_color_components==3, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register int pixcode; register JSAMPROW ptrin, ptrout; JSAMPROW colorindex0 = cquantize->colorindex[0]; JSAMPROW colorindex1 = cquantize->colorindex[1]; JSAMPROW colorindex2 = cquantize->colorindex[2]; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { ptrin = input_buf[row]; ptrout = output_buf[row]; for (col = width; col > 0; col--) { pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); *ptrout++ = (JSAMPLE) pixcode; } } } METHODDEF(void) quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* General case, with ordered dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register JSAMPROW input_ptr; register JSAMPROW output_ptr; JSAMPROW colorindex_ci; int * dither; /* points to active row of dither matrix */ int row_index, col_index; /* current indexes into dither matrix */ int nc = cinfo->out_color_components; int ci; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ FMEMZERO((void FAR *) output_buf[row], (size_t) width * SIZEOF(JSAMPLE)); row_index = cquantize->row_index; for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; output_ptr = output_buf[row]; colorindex_ci = cquantize->colorindex[ci]; dither = cquantize->odither[ci][row_index]; col_index = 0; for (col = width; col > 0; col--) { /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, * select output value, accumulate into output code for this pixel. * Range-limiting need not be done explicitly, as we have extended * the colorindex table to produce the right answers for out-of-range * inputs. The maximum dither is +- MAXJSAMPLE; this sets the * required amount of padding. */ *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; input_ptr += nc; output_ptr++; col_index = (col_index + 1) & ODITHER_MASK; } } /* Advance row index for next row */ row_index = (row_index + 1) & ODITHER_MASK; cquantize->row_index = row_index; } } METHODDEF(void) quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* Fast path for out_color_components==3, with ordered dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register int pixcode; register JSAMPROW input_ptr; register JSAMPROW output_ptr; JSAMPROW colorindex0 = cquantize->colorindex[0]; JSAMPROW colorindex1 = cquantize->colorindex[1]; JSAMPROW colorindex2 = cquantize->colorindex[2]; int * dither0; /* points to active row of dither matrix */ int * dither1; int * dither2; int row_index, col_index; /* current indexes into dither matrix */ int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { row_index = cquantize->row_index; input_ptr = input_buf[row]; output_ptr = output_buf[row]; dither0 = cquantize->odither[0][row_index]; dither1 = cquantize->odither[1][row_index]; dither2 = cquantize->odither[2][row_index]; col_index = 0; for (col = width; col > 0; col--) { pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + dither0[col_index]]); pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + dither1[col_index]]); pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + dither2[col_index]]); *output_ptr++ = (JSAMPLE) pixcode; col_index = (col_index + 1) & ODITHER_MASK; } row_index = (row_index + 1) & ODITHER_MASK; cquantize->row_index = row_index; } } METHODDEF(void) quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* General case, with Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register LOCFSERROR cur; /* current error or pixel value */ LOCFSERROR belowerr; /* error for pixel below cur */ LOCFSERROR bpreverr; /* error for below/prev col */ LOCFSERROR bnexterr; /* error for below/next col */ LOCFSERROR delta; register FSERRPTR errorptr; /* => fserrors[] at column before current */ register JSAMPROW input_ptr; register JSAMPROW output_ptr; JSAMPROW colorindex_ci; JSAMPROW colormap_ci; int pixcode; int nc = cinfo->out_color_components; int dir; /* 1 for left-to-right, -1 for right-to-left */ int dirnc; /* dir * nc */ int ci; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; JSAMPLE *range_limit = cinfo->sample_range_limit; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ FMEMZERO((void FAR *) output_buf[row], (size_t) width * SIZEOF(JSAMPLE)); for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; output_ptr = output_buf[row]; if (cquantize->on_odd_row) { /* work right to left in this row */ input_ptr += (width-1) * nc; /* so point to rightmost pixel */ output_ptr += width-1; dir = -1; dirnc = -nc; errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ } else { /* work left to right in this row */ dir = 1; dirnc = nc; errorptr = cquantize->fserrors[ci]; /* => entry before first column */ } colorindex_ci = cquantize->colorindex[ci]; colormap_ci = cquantize->sv_colormap[ci]; /* Preset error values: no error propagated to first pixel from left */ cur = 0; /* and no error propagated to row below yet */ belowerr = bpreverr = 0; for (col = width; col > 0; col--) { /* cur holds the error propagated from the previous pixel on the * current line. Add the error propagated from the previous line * to form the complete error correction term for this pixel, and * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct * for either sign of the error value. * Note: errorptr points to *previous* column's array entry. */ cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. * The maximum error is +- MAXJSAMPLE; this sets the required size * of the range_limit array. */ cur += GETJSAMPLE(*input_ptr); cur = GETJSAMPLE(range_limit[cur]); /* Select output value, accumulate into output code for this pixel */ pixcode = GETJSAMPLE(colorindex_ci[cur]); *output_ptr += (JSAMPLE) pixcode; /* Compute actual representation error at this pixel */ /* Note: we can do this even though we don't have the final */ /* pixel code, because the colormap is orthogonal. */ cur -= GETJSAMPLE(colormap_ci[pixcode]); /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the * next-line error sums left by 1 column. */ bnexterr = cur; delta = cur * 2; cur += delta; /* form error * 3 */ errorptr[0] = (FSERROR) (bpreverr + cur); cur += delta; /* form error * 5 */ bpreverr = belowerr + cur; belowerr = bnexterr; cur += delta; /* form error * 7 */ /* At this point cur contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the * next line have been shifted over. We are therefore ready to move on. */ input_ptr += dirnc; /* advance input ptr to next column */ output_ptr += dir; /* advance output ptr to next column */ errorptr += dir; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error value into the * final fserrors[] entry. Note we need not unload belowerr because * it is for the dummy column before or after the actual array. */ errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ } cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); } } /* * Allocate workspace for Floyd-Steinberg errors. */ LOCAL(void) alloc_fs_workspace (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; size_t arraysize; int i; arraysize = ((size_t) cinfo->output_width + (size_t) 2) * SIZEOF(FSERROR); for (i = 0; i < cinfo->out_color_components; i++) { cquantize->fserrors[i] = (FSERRPTR) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); } } /* * Initialize for one-pass color quantization. */ METHODDEF(void) start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; size_t arraysize; int i; /* Install my colormap. */ cinfo->colormap = cquantize->sv_colormap; cinfo->actual_number_of_colors = cquantize->sv_actual; /* Initialize for desired dithering mode. */ switch (cinfo->dither_mode) { case JDITHER_NONE: if (cinfo->out_color_components == 3) cquantize->pub.color_quantize = color_quantize3; else cquantize->pub.color_quantize = color_quantize; break; case JDITHER_ORDERED: if (cinfo->out_color_components == 3) cquantize->pub.color_quantize = quantize3_ord_dither; else cquantize->pub.color_quantize = quantize_ord_dither; cquantize->row_index = 0; /* initialize state for ordered dither */ /* If user changed to ordered dither from another mode, * we must recreate the color index table with padding. * This will cost extra space, but probably isn't very likely. */ if (! cquantize->is_padded) create_colorindex(cinfo); /* Create ordered-dither tables if we didn't already. */ if (cquantize->odither[0] == NULL) create_odither_tables(cinfo); break; case JDITHER_FS: cquantize->pub.color_quantize = quantize_fs_dither; cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ /* Allocate Floyd-Steinberg workspace if didn't already. */ if (cquantize->fserrors[0] == NULL) alloc_fs_workspace(cinfo); /* Initialize the propagated errors to zero. */ arraysize = ((size_t) cinfo->output_width + (size_t) 2) * SIZEOF(FSERROR); for (i = 0; i < cinfo->out_color_components; i++) FMEMZERO((void FAR *) cquantize->fserrors[i], arraysize); break; default: ERREXIT(cinfo, JERR_NOT_COMPILED); } } /* * Finish up at the end of the pass. */ METHODDEF(void) finish_pass_1_quant (j_decompress_ptr cinfo) { /* no work in 1-pass case */ } /* * Switch to a new external colormap between output passes. * Shouldn't get to this module! */ METHODDEF(void) new_color_map_1_quant (j_decompress_ptr cinfo) { ERREXIT(cinfo, JERR_MODE_CHANGE); } /* * Module initialization routine for 1-pass color quantization. */ GLOBAL(void) jinit_1pass_quantizer (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize; cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_cquantizer)); cinfo->cquantize = &cquantize->pub; cquantize->pub.start_pass = start_pass_1_quant; cquantize->pub.finish_pass = finish_pass_1_quant; cquantize->pub.new_color_map = new_color_map_1_quant; cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ /* Make sure my internal arrays won't overflow */ if (cinfo->out_color_components > MAX_Q_COMPS) ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); /* Make sure colormap indexes can be represented by JSAMPLEs */ if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); /* Create the colormap and color index table. */ create_colormap(cinfo); create_colorindex(cinfo); /* Allocate Floyd-Steinberg workspace now if requested. * We do this now since it is FAR storage and may affect the memory * manager's space calculations. If the user changes to FS dither * mode in a later pass, we will allocate the space then, and will * possibly overrun the max_memory_to_use setting. */ if (cinfo->dither_mode == JDITHER_FS) alloc_fs_workspace(cinfo); } #endif /* QUANT_1PASS_SUPPORTED */ fltk-1.4.3/jpeg/CMakeLists.txt0000644000175000017500000000725215004135251016300 0ustar albrechtalbrecht# # JPEG library CMake configuration for the Fast Light Toolkit (FLTK). # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # # memmgr back ends: compile only one of these into a working library # (For now, let's use the mode that requires the image fit into memory. # This is the recommended mode for Win32 anyway.) set(systemdependent_SRCS jmemnobs.c) # library object files common to compression and decompression set(common_SRCS jaricom.c jcomapi.c jutils.c jerror.c jmemmgr.c ) # compression library object files set(compression_SRCS jcapimin.c jcapistd.c jcarith.c jctrans.c jcparam.c jdatadst.c jcinit.c jcmaster.c jcmarker.c jcmainct.c jcprepct.c jccoefct.c jccolor.c jcsample.c jchuff.c jcdctmgr.c jfdctfst.c jfdctflt.c jfdctint.c ) # decompression library object files set(decompression_SRCS jdapimin.c jdapistd.c jdarith.c jdtrans.c jdatasrc.c jdmaster.c jdinput.c jdmarker.c jdhuff.c jdmainct.c jdcoefct.c jdpostct.c jddctmgr.c jidctfst.c jidctflt.c jidctint.c jdsample.c jdcolor.c jquant1.c jquant2.c jdmerge.c ) list(APPEND BUILD_SRCS "${systemdependent_SRCS};${common_SRCS}") list(APPEND BUILD_SRCS "${compression_SRCS};${decompression_SRCS}") ####################################################################### # Set common variables for static and shared builds ####################################################################### set(_include_dirs $ $ ) # Suppress Visual Studio compiler warnings set(msvc_warnings /wd4267) ####################################################################### # Build the static library ####################################################################### fl_add_library(fltk_jpeg STATIC "${BUILD_SRCS}") set(target fltk_jpeg) target_include_directories(${target} PUBLIC ${_include_dirs}) if(MSVC) target_compile_options(${target} PRIVATE ${msvc_warnings}) endif(MSVC) list(APPEND FLTK_IMAGE_LIBRARIES fltk::jpeg) # Propagate to parent scope (modified by fl_add_library and here) set(FLTK_LIBRARIES ${FLTK_LIBRARIES} PARENT_SCOPE) set(FLTK_IMAGE_LIBRARIES ${FLTK_IMAGE_LIBRARIES} PARENT_SCOPE) ####################################################################### # Build the shared library (optional) ####################################################################### if(FLTK_BUILD_SHARED_LIBS) # ensure to export all symbols for Windows DLL's set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) fl_add_library(fltk_jpeg SHARED "${BUILD_SRCS}") set(target fltk_jpeg-shared) target_include_directories(${target} PUBLIC ${_include_dirs}) if(MSVC) target_compile_options(${target} PRIVATE ${msvc_warnings}) endif(MSVC) list(APPEND FLTK_IMAGE_LIBRARIES_SHARED fltk::jpeg-shared) # Propagate to parent scope (modified by fl_add_library and here) set(FLTK_LIBRARIES_SHARED ${FLTK_LIBRARIES_SHARED} PARENT_SCOPE) set(FLTK_IMAGE_LIBRARIES_SHARED ${FLTK_IMAGE_LIBRARIES_SHARED} PARENT_SCOPE) endif(FLTK_BUILD_SHARED_LIBS) ####################################################################### # Install the library headers ####################################################################### install(FILES jconfig.h jerror.h jmorecfg.h jpeglib.h fltk_jpeg_prefix.h DESTINATION ${FLTK_INCLUDEDIR}/FL/images ) fltk-1.4.3/jpeg/jmorecfg.h0000644000175000017500000003562315004135251015510 0ustar albrechtalbrecht/* * jmorecfg.h * * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 1997-2022 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains additional configuration options that customize the * JPEG software for special applications or support machine-dependent * optimizations. Most users will not need to touch this file. */ /* * Define BITS_IN_JSAMPLE as either * 8 for 8-bit sample values (the usual setting) * 9 for 9-bit sample values * 10 for 10-bit sample values * 11 for 11-bit sample values * 12 for 12-bit sample values * Only 8, 9, 10, 11, and 12 bits sample data precision are supported for * full-feature DCT processing. Further depths up to 16-bit may be added * later for the lossless modes of operation. * Run-time selection and conversion of data precision will be added later * and are currently not supported, sorry. * Exception: The transcoding part (jpegtran) supports all settings in a * single instance, since it operates on the level of DCT coefficients and * not sample values. The DCT coefficients are of the same type (16 bits) * in all cases (see below). */ #define BITS_IN_JSAMPLE 8 /* use 8, 9, 10, 11, or 12 */ /* * Maximum number of components (color channels) allowed in JPEG image. * To meet the letter of the JPEG spec, set this to 255. However, darn * few applications need more than 4 channels (maybe 5 for CMYK + alpha * mask). We recommend 10 as a reasonable compromise; use 4 if you are * really short on memory. (Each allowed component costs a hundred or so * bytes of storage, whether actually used in an image or not.) */ #define MAX_COMPONENTS 10 /* maximum number of image components */ /* * Basic data types. * You may need to change these if you have a machine with unusual data * type sizes; for example, "char" not 8 bits, "short" not 16 bits, * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, * but it had better be at least 16. */ /* Representation of a single sample (pixel element value). * We frequently allocate large arrays of these, so it's important to keep * them small. But if you have memory to burn and access to char or short * arrays is very slow on your hardware, you might want to change these. */ #if BITS_IN_JSAMPLE == 8 /* JSAMPLE should be the smallest type that will hold the values 0..255. * You can use a signed char by having GETJSAMPLE mask it with 0xFF. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JSAMPLE; #define GETJSAMPLE(value) ((int) (value)) #else /* not HAVE_UNSIGNED_CHAR */ typedef char JSAMPLE; #ifdef CHAR_IS_UNSIGNED #define GETJSAMPLE(value) ((int) (value)) #else #define GETJSAMPLE(value) ((int) (value) & 0xFF) #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ #define MAXJSAMPLE 255 #define CENTERJSAMPLE 128 #endif /* BITS_IN_JSAMPLE == 8 */ #if BITS_IN_JSAMPLE == 9 /* JSAMPLE should be the smallest type that will hold the values 0..511. * On nearly all machines "short" will do nicely. */ typedef short JSAMPLE; #define GETJSAMPLE(value) ((int) (value)) #define MAXJSAMPLE 511 #define CENTERJSAMPLE 256 #endif /* BITS_IN_JSAMPLE == 9 */ #if BITS_IN_JSAMPLE == 10 /* JSAMPLE should be the smallest type that will hold the values 0..1023. * On nearly all machines "short" will do nicely. */ typedef short JSAMPLE; #define GETJSAMPLE(value) ((int) (value)) #define MAXJSAMPLE 1023 #define CENTERJSAMPLE 512 #endif /* BITS_IN_JSAMPLE == 10 */ #if BITS_IN_JSAMPLE == 11 /* JSAMPLE should be the smallest type that will hold the values 0..2047. * On nearly all machines "short" will do nicely. */ typedef short JSAMPLE; #define GETJSAMPLE(value) ((int) (value)) #define MAXJSAMPLE 2047 #define CENTERJSAMPLE 1024 #endif /* BITS_IN_JSAMPLE == 11 */ #if BITS_IN_JSAMPLE == 12 /* JSAMPLE should be the smallest type that will hold the values 0..4095. * On nearly all machines "short" will do nicely. */ typedef short JSAMPLE; #define GETJSAMPLE(value) ((int) (value)) #define MAXJSAMPLE 4095 #define CENTERJSAMPLE 2048 #endif /* BITS_IN_JSAMPLE == 12 */ /* Representation of a DCT frequency coefficient. * This should be a signed value of at least 16 bits; "short" is usually OK. * Again, we allocate large arrays of these, but you can change to int * if you have memory to burn and "short" is really slow. */ typedef short JCOEF; /* Compressed datastreams are represented as arrays of JOCTET. * These must be EXACTLY 8 bits wide, at least once they are written to * external storage. Note that when using the stdio data source/destination * managers, this is also the data type passed to fread/fwrite. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JOCTET; #define GETJOCTET(value) (value) #else /* not HAVE_UNSIGNED_CHAR */ typedef char JOCTET; #ifdef CHAR_IS_UNSIGNED #define GETJOCTET(value) (value) #else #define GETJOCTET(value) ((value) & 0xFF) #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ /* These typedefs are used for various table entries and so forth. * They must be at least as wide as specified; but making them too big * won't cost a huge amount of memory, so we don't provide special * extraction code like we did for JSAMPLE. (In other words, these * typedefs live at a different point on the speed/space tradeoff curve.) */ /* UINT8 must hold at least the values 0..255. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char UINT8; #else /* not HAVE_UNSIGNED_CHAR */ #ifdef CHAR_IS_UNSIGNED typedef char UINT8; #else /* not CHAR_IS_UNSIGNED */ typedef short UINT8; #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ /* UINT16 must hold at least the values 0..65535. */ #ifdef HAVE_UNSIGNED_SHORT typedef unsigned short UINT16; #else /* not HAVE_UNSIGNED_SHORT */ typedef unsigned int UINT16; #endif /* HAVE_UNSIGNED_SHORT */ /* INT16 must hold at least the values -32768..32767. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ typedef short INT16; #endif /* INT32 must hold at least signed 32-bit values. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ #ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ #ifndef _BASETSD_H /* MinGW is slightly different */ #ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ typedef long INT32; #endif #endif #endif #endif /* Datatype used for image dimensions. The JPEG standard only supports * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore * "unsigned int" is sufficient on all machines. However, if you need to * handle larger images and you don't mind deviating from the spec, you * can change this datatype. */ typedef unsigned int JDIMENSION; #define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ /* These macros are used in all function definitions and extern declarations. * You could modify them if you need to change function linkage conventions; * in particular, you'll need to do that to make the library a Windows DLL. * Another application is to make all functions global for use with debuggers * or code profilers that require it. */ /* a function called through method pointers: */ #define METHODDEF(type) static type /* a function used only in its module: */ #define LOCAL(type) static type /* a function referenced thru EXTERNs: */ #define GLOBAL(type) type /* a reference to a GLOBAL function: */ #define EXTERN(type) extern type /* This macro is used to declare a "method", that is, a function pointer. * We want to supply prototype parameters if the compiler can cope. * Note that the arglist parameter must be parenthesized! * Again, you can customize this if you need special linkage keywords. */ #ifdef HAVE_PROTOTYPES #define JMETHOD(type,methodname,arglist) type (*methodname) arglist #else #define JMETHOD(type,methodname,arglist) type (*methodname) () #endif /* The noreturn type identifier is used to declare functions * which cannot return. * Compilers can thus create more optimized code and perform * better checks for warnings and errors. * Static analyzer tools can make improved inferences about * execution paths and are prevented from giving false alerts. * * Unfortunately, the proposed specifications of corresponding * extensions in the Dec 2011 ISO C standard revision (C11), * GCC, MSVC, etc. are not viable. * Thus we introduce a user defined type to declare noreturn * functions at least for clarity. A proper compiler would * have a suitable noreturn type to match in place of void. */ #ifndef HAVE_NORETURN_T typedef void noreturn_t; #endif /* Here is the pseudo-keyword for declaring pointers that must be "far" * on 80x86 machines. Most of the specialized coding for 80x86 is handled * by just saying "FAR *" where such a pointer is needed. In a few places * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. */ #ifndef FAR #ifdef NEED_FAR_POINTERS #define FAR far #else #define FAR #endif #endif /* * On a few systems, type boolean and/or its values FALSE, TRUE may appear * in standard header files. Or you may have conflicts with application- * specific header files that you want to include together with these files. * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. */ #ifndef HAVE_BOOLEAN #if defined FALSE || defined TRUE || defined QGLOBAL_H /* Qt3 defines FALSE and TRUE as "const" variables in qglobal.h */ typedef int boolean; #ifndef FALSE /* in case these macros already exist */ #define FALSE 0 /* values of boolean */ #endif #ifndef TRUE #define TRUE 1 #endif #else typedef enum { FALSE = 0, TRUE = 1 } boolean; #endif #endif /* * The remaining options affect code selection within the JPEG library, * but they don't need to be visible to most applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. */ #ifdef JPEG_INTERNALS #define JPEG_INTERNAL_OPTIONS #endif #ifdef JPEG_INTERNAL_OPTIONS /* * These defines indicate whether to include various optional functions. * Undefining some of these symbols will produce a smaller but less capable * library. Note that you can leave certain source files out of the * compilation/linking process if you've #undef'd the corresponding symbols. * (You may HAVE to do that if your compiler doesn't like null source files.) */ /* Capability options common to encoder and decoder: */ #define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ #define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ #define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ /* Encoder capability options: */ #define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN) */ #define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW) */ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ /* Note: if you selected more than 8-bit data precision, it is dangerous to * turn off ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only * good for 8-bit precision, so arithmetic coding is recommended for higher * precision. The Huffman encoder normally uses entropy optimization to * compute usable tables for higher precision. Otherwise, you'll have to * supply different default Huffman tables. * The exact same statements apply for progressive JPEG: the default tables * don't work for progressive mode. (This may get fixed, however.) */ #define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ /* Decoder capability options: */ #define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN) */ #define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires DCT_ISLOW) */ #define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ #define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ #undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ #define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ #define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ #define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ /* more capability options later, no doubt */ /* * Ordering of RGB data in scanlines passed to or from the application. * If your application wants to deal with data in the order B,G,R, just * #define JPEG_USE_RGB_CUSTOM in jconfig.h, or define your own custom * order in jconfig.h and #define JPEG_HAVE_RGB_CUSTOM. * You can also deal with formats such as R,G,B,X (one extra byte per pixel) * by changing RGB_PIXELSIZE. * Note that changing the offsets will also change * the order in which colormap data is organized. * RESTRICTIONS: * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. * 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE * is not 3 (they don't understand about dummy color components!). * So you can't use color quantization if you change that value. */ #ifndef JPEG_HAVE_RGB_CUSTOM #ifdef JPEG_USE_RGB_CUSTOM #define RGB_RED 2 /* Offset of Red in an RGB scanline element */ #define RGB_GREEN 1 /* Offset of Green */ #define RGB_BLUE 0 /* Offset of Blue */ #else #define RGB_RED 0 /* Offset of Red in an RGB scanline element */ #define RGB_GREEN 1 /* Offset of Green */ #define RGB_BLUE 2 /* Offset of Blue */ #endif #define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ #endif /* Definitions for speed-related optimizations. */ /* If your compiler supports inline functions, define INLINE * as the inline keyword; otherwise define it as empty. */ #ifndef INLINE #ifdef __GNUC__ /* for instance, GNU C knows about inline */ #define INLINE __inline__ #endif #ifndef INLINE #define INLINE /* default is to define it as empty */ #endif #endif /* On some machines (notably 68000 series) "int" is 32 bits, but multiplying * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER * as short on such a machine. MULTIPLIER must be at least 16 bits wide. */ #ifndef MULTIPLIER #define MULTIPLIER int /* type for fastest integer multiply */ #endif /* FAST_FLOAT should be either float or double, whichever is done faster * by your compiler. (Note that this type is only used in the floating point * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) * Typically, float is faster in ANSI C compilers, while double is faster in * pre-ANSI compilers (because they insist on converting to double anyway). * The code below therefore chooses float if we have ANSI-style prototypes. */ #ifndef FAST_FLOAT #ifdef HAVE_PROTOTYPES #define FAST_FLOAT float #else #define FAST_FLOAT double #endif #endif #endif /* JPEG_INTERNAL_OPTIONS */ fltk-1.4.3/jpeg/jcmarker.c0000644000175000017500000004474215004135251015507 0ustar albrechtalbrecht/* * jcmarker.c * * Copyright (C) 1991-1998, Thomas G. Lane. * Modified 2003-2019 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to write JPEG datastream markers. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" typedef enum { /* JPEG marker codes */ M_SOF0 = 0xc0, M_SOF1 = 0xc1, M_SOF2 = 0xc2, M_SOF3 = 0xc3, M_SOF5 = 0xc5, M_SOF6 = 0xc6, M_SOF7 = 0xc7, M_JPG = 0xc8, M_SOF9 = 0xc9, M_SOF10 = 0xca, M_SOF11 = 0xcb, M_SOF13 = 0xcd, M_SOF14 = 0xce, M_SOF15 = 0xcf, M_DHT = 0xc4, M_DAC = 0xcc, M_RST0 = 0xd0, M_RST1 = 0xd1, M_RST2 = 0xd2, M_RST3 = 0xd3, M_RST4 = 0xd4, M_RST5 = 0xd5, M_RST6 = 0xd6, M_RST7 = 0xd7, M_SOI = 0xd8, M_EOI = 0xd9, M_SOS = 0xda, M_DQT = 0xdb, M_DNL = 0xdc, M_DRI = 0xdd, M_DHP = 0xde, M_EXP = 0xdf, M_APP0 = 0xe0, M_APP1 = 0xe1, M_APP2 = 0xe2, M_APP3 = 0xe3, M_APP4 = 0xe4, M_APP5 = 0xe5, M_APP6 = 0xe6, M_APP7 = 0xe7, M_APP8 = 0xe8, M_APP9 = 0xe9, M_APP10 = 0xea, M_APP11 = 0xeb, M_APP12 = 0xec, M_APP13 = 0xed, M_APP14 = 0xee, M_APP15 = 0xef, M_JPG0 = 0xf0, M_JPG8 = 0xf8, M_JPG13 = 0xfd, M_COM = 0xfe, M_TEM = 0x01, M_ERROR = 0x100 } JPEG_MARKER; /* Private state */ typedef struct { struct jpeg_marker_writer pub; /* public fields */ unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ } my_marker_writer; typedef my_marker_writer * my_marker_ptr; /* * Basic output routines. * * Note that we do not support suspension while writing a marker. * Therefore, an application using suspension must ensure that there is * enough buffer space for the initial markers (typ. 600-700 bytes) before * calling jpeg_start_compress, and enough space to write the trailing EOI * (a few bytes) before calling jpeg_finish_compress. Multipass compression * modes are not supported at all with suspension, so those two are the only * points where markers will be written. */ LOCAL(void) emit_byte (j_compress_ptr cinfo, int val) /* Emit a byte */ { struct jpeg_destination_mgr * dest = cinfo->dest; *(dest->next_output_byte)++ = (JOCTET) val; if (--dest->free_in_buffer == 0) { if (! (*dest->empty_output_buffer) (cinfo)) ERREXIT(cinfo, JERR_CANT_SUSPEND); } } LOCAL(void) emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) /* Emit a marker code */ { emit_byte(cinfo, 0xFF); emit_byte(cinfo, (int) mark); } LOCAL(void) emit_2bytes (j_compress_ptr cinfo, int value) /* Emit a 2-byte integer; these are always MSB first in JPEG files */ { emit_byte(cinfo, (value >> 8) & 0xFF); emit_byte(cinfo, value & 0xFF); } /* * Routines to write specific marker types. */ LOCAL(int) emit_dqt (j_compress_ptr cinfo, int index) /* Emit a DQT marker */ /* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ { JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; int prec; int i; if (qtbl == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); prec = 0; for (i = 0; i <= cinfo->lim_Se; i++) { if (qtbl->quantval[cinfo->natural_order[i]] > 255) prec = 1; } if (! qtbl->sent_table) { emit_marker(cinfo, M_DQT); emit_2bytes(cinfo, prec ? cinfo->lim_Se * 2 + 2 + 1 + 2 : cinfo->lim_Se + 1 + 1 + 2); emit_byte(cinfo, index + (prec<<4)); for (i = 0; i <= cinfo->lim_Se; i++) { /* The table entries must be emitted in zigzag order. */ unsigned int qval = qtbl->quantval[cinfo->natural_order[i]]; if (prec) emit_byte(cinfo, (int) (qval >> 8)); emit_byte(cinfo, (int) (qval & 0xFF)); } qtbl->sent_table = TRUE; } return prec; } LOCAL(void) emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) /* Emit a DHT marker */ { JHUFF_TBL * htbl; int length, i; if (is_ac) { htbl = cinfo->ac_huff_tbl_ptrs[index]; index += 0x10; /* output index has AC bit set */ } else { htbl = cinfo->dc_huff_tbl_ptrs[index]; } if (htbl == NULL) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); if (! htbl->sent_table) { emit_marker(cinfo, M_DHT); length = 0; for (i = 1; i <= 16; i++) length += htbl->bits[i]; emit_2bytes(cinfo, length + 2 + 1 + 16); emit_byte(cinfo, index); for (i = 1; i <= 16; i++) emit_byte(cinfo, htbl->bits[i]); for (i = 0; i < length; i++) emit_byte(cinfo, htbl->huffval[i]); htbl->sent_table = TRUE; } } LOCAL(void) emit_dac (j_compress_ptr cinfo) /* Emit a DAC marker */ /* Since the useful info is so small, we want to emit all the tables in */ /* one DAC marker. Therefore this routine does its own scan of the table. */ { #ifdef C_ARITH_CODING_SUPPORTED char dc_in_use[NUM_ARITH_TBLS]; char ac_in_use[NUM_ARITH_TBLS]; int length, i; jpeg_component_info *compptr; for (i = 0; i < NUM_ARITH_TBLS; i++) dc_in_use[i] = ac_in_use[i] = 0; for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; /* DC needs no table for refinement scan */ if (cinfo->Ss == 0 && cinfo->Ah == 0) dc_in_use[compptr->dc_tbl_no] = 1; /* AC needs no table when not present */ if (cinfo->Se) ac_in_use[compptr->ac_tbl_no] = 1; } length = 0; for (i = 0; i < NUM_ARITH_TBLS; i++) length += dc_in_use[i] + ac_in_use[i]; if (length) { emit_marker(cinfo, M_DAC); emit_2bytes(cinfo, length*2 + 2); for (i = 0; i < NUM_ARITH_TBLS; i++) { if (dc_in_use[i]) { emit_byte(cinfo, i); emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); } if (ac_in_use[i]) { emit_byte(cinfo, i + 0x10); emit_byte(cinfo, cinfo->arith_ac_K[i]); } } } #endif /* C_ARITH_CODING_SUPPORTED */ } LOCAL(void) emit_dri (j_compress_ptr cinfo) /* Emit a DRI marker */ { emit_marker(cinfo, M_DRI); emit_2bytes(cinfo, 4); /* fixed length */ emit_2bytes(cinfo, (int) cinfo->restart_interval); } LOCAL(void) emit_lse_ict (j_compress_ptr cinfo) /* Emit an LSE inverse color transform specification marker */ { /* Support only 1 transform */ if (cinfo->color_transform != JCT_SUBTRACT_GREEN || cinfo->num_components < 3) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); emit_marker(cinfo, M_JPG8); emit_2bytes(cinfo, 24); /* fixed length */ emit_byte(cinfo, 0x0D); /* ID inverse transform specification */ emit_2bytes(cinfo, MAXJSAMPLE); /* MAXTRANS */ emit_byte(cinfo, 3); /* Nt=3 */ emit_byte(cinfo, cinfo->comp_info[1].component_id); emit_byte(cinfo, cinfo->comp_info[0].component_id); emit_byte(cinfo, cinfo->comp_info[2].component_id); emit_byte(cinfo, 0x80); /* F1: CENTER1=1, NORM1=0 */ emit_2bytes(cinfo, 0); /* A(1,1)=0 */ emit_2bytes(cinfo, 0); /* A(1,2)=0 */ emit_byte(cinfo, 0); /* F2: CENTER2=0, NORM2=0 */ emit_2bytes(cinfo, 1); /* A(2,1)=1 */ emit_2bytes(cinfo, 0); /* A(2,2)=0 */ emit_byte(cinfo, 0); /* F3: CENTER3=0, NORM3=0 */ emit_2bytes(cinfo, 1); /* A(3,1)=1 */ emit_2bytes(cinfo, 0); /* A(3,2)=0 */ } LOCAL(void) emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) /* Emit a SOF marker */ { int ci; jpeg_component_info *compptr; emit_marker(cinfo, code); emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ /* Make sure image isn't bigger than SOF field can handle */ if ((long) cinfo->jpeg_height > 65535L || (long) cinfo->jpeg_width > 65535L) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); emit_byte(cinfo, cinfo->data_precision); emit_2bytes(cinfo, (int) cinfo->jpeg_height); emit_2bytes(cinfo, (int) cinfo->jpeg_width); emit_byte(cinfo, cinfo->num_components); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { emit_byte(cinfo, compptr->component_id); emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); emit_byte(cinfo, compptr->quant_tbl_no); } } LOCAL(void) emit_sos (j_compress_ptr cinfo) /* Emit a SOS marker */ { int i, td, ta; jpeg_component_info *compptr; emit_marker(cinfo, M_SOS); emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ emit_byte(cinfo, cinfo->comps_in_scan); for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; emit_byte(cinfo, compptr->component_id); /* We emit 0 for unused field(s); this is recommended by the P&M text * but does not seem to be specified in the standard. */ /* DC needs no table for refinement scan */ td = cinfo->Ss == 0 && cinfo->Ah == 0 ? compptr->dc_tbl_no : 0; /* AC needs no table when not present */ ta = cinfo->Se ? compptr->ac_tbl_no : 0; emit_byte(cinfo, (td << 4) + ta); } emit_byte(cinfo, cinfo->Ss); emit_byte(cinfo, cinfo->Se); emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); } LOCAL(void) emit_pseudo_sos (j_compress_ptr cinfo) /* Emit a pseudo SOS marker */ { emit_marker(cinfo, M_SOS); emit_2bytes(cinfo, 2 + 1 + 3); /* length */ emit_byte(cinfo, 0); /* Ns */ emit_byte(cinfo, 0); /* Ss */ emit_byte(cinfo, cinfo->block_size * cinfo->block_size - 1); /* Se */ emit_byte(cinfo, 0); /* Ah/Al */ } LOCAL(void) emit_jfif_app0 (j_compress_ptr cinfo) /* Emit a JFIF-compliant APP0 marker */ { /* * Length of APP0 block (2 bytes) * Block ID (4 bytes - ASCII "JFIF") * Zero byte (1 byte to terminate the ID string) * Version Major, Minor (2 bytes - major first) * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) * Xdpu (2 bytes - dots per unit horizontal) * Ydpu (2 bytes - dots per unit vertical) * Thumbnail X size (1 byte) * Thumbnail Y size (1 byte) */ emit_marker(cinfo, M_APP0); emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ emit_byte(cinfo, 0x46); emit_byte(cinfo, 0x49); emit_byte(cinfo, 0x46); emit_byte(cinfo, 0); emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ emit_byte(cinfo, cinfo->JFIF_minor_version); emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ emit_2bytes(cinfo, (int) cinfo->X_density); emit_2bytes(cinfo, (int) cinfo->Y_density); emit_byte(cinfo, 0); /* No thumbnail image */ emit_byte(cinfo, 0); } LOCAL(void) emit_adobe_app14 (j_compress_ptr cinfo) /* Emit an Adobe APP14 marker */ { /* * Length of APP14 block (2 bytes) * Block ID (5 bytes - ASCII "Adobe") * Version Number (2 bytes - currently 100) * Flags0 (2 bytes - currently 0) * Flags1 (2 bytes - currently 0) * Color transform (1 byte) * * Although Adobe TN 5116 mentions Version = 101, all the Adobe files * now in circulation seem to use Version = 100, so that's what we write. * * We write the color transform byte as 1 if the JPEG color space is * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with * whether the encoder performed a transformation, which is pretty useless. */ emit_marker(cinfo, M_APP14); emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ emit_byte(cinfo, 0x64); emit_byte(cinfo, 0x6F); emit_byte(cinfo, 0x62); emit_byte(cinfo, 0x65); emit_2bytes(cinfo, 100); /* Version */ emit_2bytes(cinfo, 0); /* Flags0 */ emit_2bytes(cinfo, 0); /* Flags1 */ switch (cinfo->jpeg_color_space) { case JCS_YCbCr: emit_byte(cinfo, 1); /* Color transform = 1 */ break; case JCS_YCCK: emit_byte(cinfo, 2); /* Color transform = 2 */ break; default: emit_byte(cinfo, 0); /* Color transform = 0 */ } } /* * These routines allow writing an arbitrary marker with parameters. * The only intended use is to emit COM or APPn markers after calling * write_file_header and before calling write_frame_header. * Other uses are not guaranteed to produce desirable results. * Counting the parameter bytes properly is the caller's responsibility. */ METHODDEF(void) write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) /* Emit an arbitrary marker header */ { if (datalen > (unsigned int) 65533) /* safety check */ ERREXIT(cinfo, JERR_BAD_LENGTH); emit_marker(cinfo, (JPEG_MARKER) marker); emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ } METHODDEF(void) write_marker_byte (j_compress_ptr cinfo, int val) /* Emit one byte of marker parameters following write_marker_header */ { emit_byte(cinfo, val); } /* * Write datastream header. * This consists of an SOI and optional APPn markers. * We recommend use of the JFIF marker, but not the Adobe marker, * when using YCbCr or grayscale data. The JFIF marker is also used * for other standard JPEG colorspaces. The Adobe marker is helpful * to distinguish RGB, CMYK, and YCCK colorspaces. * Note that an application can write additional header markers after * jpeg_start_compress returns. */ METHODDEF(void) write_file_header (j_compress_ptr cinfo) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; emit_marker(cinfo, M_SOI); /* first the SOI */ /* SOI is defined to reset restart interval to 0 */ marker->last_restart_interval = 0; if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ emit_jfif_app0(cinfo); if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ emit_adobe_app14(cinfo); } /* * Write frame header. * This consists of DQT and SOFn markers, * a conditional LSE marker and a conditional pseudo SOS marker. * Note that we do not emit the SOF until we have emitted the DQT(s). * This avoids compatibility problems with incorrect implementations that * try to error-check the quant table numbers as soon as they see the SOF. */ METHODDEF(void) write_frame_header (j_compress_ptr cinfo) { int ci, prec; boolean is_baseline; jpeg_component_info *compptr; /* Emit DQT for each quantization table. * Note that emit_dqt() suppresses any duplicate tables. */ prec = 0; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { prec += emit_dqt(cinfo, compptr->quant_tbl_no); } /* now prec is nonzero iff there are any 16-bit quant tables. */ /* Check for a non-baseline specification. * Note we assume that Huffman table numbers won't be changed later. */ if (cinfo->arith_code || cinfo->progressive_mode || cinfo->data_precision != 8 || cinfo->block_size != DCTSIZE) { is_baseline = FALSE; } else { is_baseline = TRUE; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) is_baseline = FALSE; } if (prec && is_baseline) { is_baseline = FALSE; /* If it's baseline except for quantizer size, warn the user */ TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); } } /* Emit the proper SOF marker */ if (cinfo->arith_code) { if (cinfo->progressive_mode) emit_sof(cinfo, M_SOF10); /* SOF code for progressive arithmetic */ else emit_sof(cinfo, M_SOF9); /* SOF code for sequential arithmetic */ } else { if (cinfo->progressive_mode) emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ else if (is_baseline) emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ else emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ } /* Check to emit LSE inverse color transform specification marker */ if (cinfo->color_transform) emit_lse_ict(cinfo); /* Check to emit pseudo SOS marker */ if (cinfo->progressive_mode && cinfo->block_size != DCTSIZE) emit_pseudo_sos(cinfo); } /* * Write scan header. * This consists of DHT or DAC markers, optional DRI, and SOS. * Compressed data will be written following the SOS. */ METHODDEF(void) write_scan_header (j_compress_ptr cinfo) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; int i; jpeg_component_info *compptr; if (cinfo->arith_code) { /* Emit arith conditioning info. We may have some duplication * if the file has multiple scans, but it's so small it's hardly * worth worrying about. */ emit_dac(cinfo); } else { /* Emit Huffman tables. * Note that emit_dht() suppresses any duplicate tables. */ for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; /* DC needs no table for refinement scan */ if (cinfo->Ss == 0 && cinfo->Ah == 0) emit_dht(cinfo, compptr->dc_tbl_no, FALSE); /* AC needs no table when not present */ if (cinfo->Se) emit_dht(cinfo, compptr->ac_tbl_no, TRUE); } } /* Emit DRI if required --- note that DRI value could change for each scan. * We avoid wasting space with unnecessary DRIs, however. */ if (cinfo->restart_interval != marker->last_restart_interval) { emit_dri(cinfo); marker->last_restart_interval = cinfo->restart_interval; } emit_sos(cinfo); } /* * Write datastream trailer. */ METHODDEF(void) write_file_trailer (j_compress_ptr cinfo) { emit_marker(cinfo, M_EOI); } /* * Write an abbreviated table-specification datastream. * This consists of SOI, DQT and DHT tables, and EOI. * Any table that is defined and not marked sent_table = TRUE will be * emitted. Note that all tables will be marked sent_table = TRUE at exit. */ METHODDEF(void) write_tables_only (j_compress_ptr cinfo) { int i; emit_marker(cinfo, M_SOI); for (i = 0; i < NUM_QUANT_TBLS; i++) { if (cinfo->quant_tbl_ptrs[i] != NULL) (void) emit_dqt(cinfo, i); } if (! cinfo->arith_code) { for (i = 0; i < NUM_HUFF_TBLS; i++) { if (cinfo->dc_huff_tbl_ptrs[i] != NULL) emit_dht(cinfo, i, FALSE); if (cinfo->ac_huff_tbl_ptrs[i] != NULL) emit_dht(cinfo, i, TRUE); } } emit_marker(cinfo, M_EOI); } /* * Initialize the marker writer module. */ GLOBAL(void) jinit_marker_writer (j_compress_ptr cinfo) { my_marker_ptr marker; /* Create the subobject */ marker = (my_marker_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_marker_writer)); cinfo->marker = &marker->pub; /* Initialize method pointers */ marker->pub.write_file_header = write_file_header; marker->pub.write_frame_header = write_frame_header; marker->pub.write_scan_header = write_scan_header; marker->pub.write_file_trailer = write_file_trailer; marker->pub.write_tables_only = write_tables_only; marker->pub.write_marker_header = write_marker_header; marker->pub.write_marker_byte = write_marker_byte; /* Initialize private state */ marker->last_restart_interval = 0; } fltk-1.4.3/jpeg/jctrans.c0000644000175000017500000003420115004135251015342 0ustar albrechtalbrecht/* * jctrans.c * * Copyright (C) 1995-1998, Thomas G. Lane. * Modified 2000-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains library routines for transcoding compression, * that is, writing raw DCT coefficient arrays to an output JPEG file. * The routines in jcapimin.c will also be needed by a transcoder. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Forward declarations */ LOCAL(void) transencode_master_selection JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); LOCAL(void) transencode_coef_controller JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); /* * Compression initialization for writing raw-coefficient data. * Before calling this, all parameters and a data destination must be set up. * Call jpeg_finish_compress() to actually write the data. * * The number of passed virtual arrays must match cinfo->num_components. * Note that the virtual arrays need not be filled or even realized at * the time write_coefficients is called; indeed, if the virtual arrays * were requested from this compression object's memory manager, they * typically will be realized during this routine and filled afterwards. */ GLOBAL(void) jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Mark all tables to be written */ jpeg_suppress_tables(cinfo, FALSE); /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); /* Perform master selection of active modules */ transencode_master_selection(cinfo, coef_arrays); /* Wait for jpeg_finish_compress() call */ cinfo->next_scanline = 0; /* so jpeg_write_marker works */ cinfo->global_state = CSTATE_WRCOEFS; } /* * Initialize the compression object with default parameters, * then copy from the source object all parameters needed for lossless * transcoding. Parameters that can be varied without loss (such as * scan script and Huffman optimization) are left in their default states. */ GLOBAL(void) jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, j_compress_ptr dstinfo) { JQUANT_TBL ** qtblptr; jpeg_component_info *incomp, *outcomp; JQUANT_TBL *c_quant, *slot_quant; int tblno, ci, coefi; /* Safety check to ensure start_compress not called yet. */ if (dstinfo->global_state != CSTATE_START) ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); /* Copy fundamental image dimensions */ dstinfo->image_width = srcinfo->image_width; dstinfo->image_height = srcinfo->image_height; dstinfo->input_components = srcinfo->num_components; dstinfo->in_color_space = srcinfo->jpeg_color_space; dstinfo->jpeg_width = srcinfo->output_width; dstinfo->jpeg_height = srcinfo->output_height; dstinfo->min_DCT_h_scaled_size = srcinfo->min_DCT_h_scaled_size; dstinfo->min_DCT_v_scaled_size = srcinfo->min_DCT_v_scaled_size; /* Initialize all parameters to default values */ jpeg_set_defaults(dstinfo); /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. * Fix it to get the right header markers for the image colorspace. * Note: Entropy table assignment in jpeg_set_colorspace * depends on color_transform. * Adaption is also required for setting the appropriate * entropy coding mode dependent on image data precision. */ dstinfo->color_transform = srcinfo->color_transform; jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); dstinfo->data_precision = srcinfo->data_precision; dstinfo->arith_code = srcinfo->data_precision > 8 ? TRUE : FALSE; dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; /* Copy the source's quantization tables. */ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; if (*qtblptr == NULL) *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); MEMCOPY((*qtblptr)->quantval, srcinfo->quant_tbl_ptrs[tblno]->quantval, SIZEOF((*qtblptr)->quantval)); (*qtblptr)->sent_table = FALSE; } } /* Copy the source's per-component info. * Note we assume jpeg_set_defaults has allocated the dest comp_info array. */ dstinfo->num_components = srcinfo->num_components; if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, MAX_COMPONENTS); for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; ci < dstinfo->num_components; ci++, incomp++, outcomp++) { outcomp->component_id = incomp->component_id; outcomp->h_samp_factor = incomp->h_samp_factor; outcomp->v_samp_factor = incomp->v_samp_factor; outcomp->quant_tbl_no = incomp->quant_tbl_no; /* Make sure saved quantization table for component matches the qtable * slot. If not, the input file re-used this qtable slot. * IJG encoder currently cannot duplicate this. */ tblno = outcomp->quant_tbl_no; if (tblno < 0 || tblno >= NUM_QUANT_TBLS || srcinfo->quant_tbl_ptrs[tblno] == NULL) ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); slot_quant = srcinfo->quant_tbl_ptrs[tblno]; c_quant = incomp->quant_table; if (c_quant != NULL) { for (coefi = 0; coefi < DCTSIZE2; coefi++) { if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); } } /* Note: we do not copy the source's entropy table assignments; * instead we rely on jpeg_set_colorspace to have made a suitable choice. */ } /* Also copy JFIF version and resolution information, if available. * Strictly speaking this isn't "critical" info, but it's nearly * always appropriate to copy it if available. In particular, * if the application chooses to copy JFIF 1.02 extension markers from * the source file, we need to copy the version to make sure we don't * emit a file that has 1.02 extensions but a claimed version of 1.01. */ if (srcinfo->saw_JFIF_marker) { if (srcinfo->JFIF_major_version == 1 || srcinfo->JFIF_major_version == 2) { dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; } dstinfo->density_unit = srcinfo->density_unit; dstinfo->X_density = srcinfo->X_density; dstinfo->Y_density = srcinfo->Y_density; } } LOCAL(void) jpeg_calc_trans_dimensions (j_compress_ptr cinfo) /* Do computations that are needed before master selection phase */ { if (cinfo->min_DCT_h_scaled_size != cinfo->min_DCT_v_scaled_size) ERREXIT2(cinfo, JERR_BAD_DCTSIZE, cinfo->min_DCT_h_scaled_size, cinfo->min_DCT_v_scaled_size); cinfo->block_size = cinfo->min_DCT_h_scaled_size; } /* * Master selection of compression modules for transcoding. * This substitutes for jcinit.c's initialization of the full compressor. */ LOCAL(void) transencode_master_selection (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { /* Do computations that are needed before master selection phase */ jpeg_calc_trans_dimensions(cinfo); /* Initialize master control (includes parameter checking/processing) */ jinit_c_master_control(cinfo, TRUE /* transcode only */); /* Entropy encoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) jinit_arith_encoder(cinfo); else { jinit_huff_encoder(cinfo); } /* We need a special coefficient buffer controller. */ transencode_coef_controller(cinfo, coef_arrays); jinit_marker_writer(cinfo); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); /* Write the datastream header (SOI, JFIF) immediately. * Frame and scan headers are postponed till later. * This lets application insert special markers after the SOI. */ (*cinfo->marker->write_file_header) (cinfo); } /* * The rest of this file is a special implementation of the coefficient * buffer controller. This is similar to jccoefct.c, but it handles only * output from presupplied virtual arrays. Furthermore, we generate any * dummy padding blocks on-the-fly rather than expecting them to be present * in the arrays. */ /* Private buffer controller object */ typedef struct { struct jpeg_c_coef_controller pub; /* public fields */ JDIMENSION iMCU_row_num; /* iMCU row # within image */ JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ int MCU_vert_offset; /* counts MCU rows within iMCU row */ int MCU_rows_per_iMCU_row; /* number of such rows needed */ /* Virtual block array for each component. */ jvirt_barray_ptr * whole_image; /* Workspace for constructing dummy blocks at right/bottom edges. */ JBLOCK dummy_buffer[C_MAX_BLOCKS_IN_MCU]; } my_coef_controller; typedef my_coef_controller * my_coef_ptr; LOCAL(void) start_iMCU_row (j_compress_ptr cinfo) /* Reset within-iMCU-row counters for a new row */ { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; /* In an interleaved scan, an MCU row is the same as an iMCU row. * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. * But at the bottom of the image, process only what's left. */ if (cinfo->comps_in_scan > 1) { coef->MCU_rows_per_iMCU_row = 1; } else { if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; else coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; } coef->MCU_ctr = 0; coef->MCU_vert_offset = 0; } /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; if (pass_mode != JBUF_CRANK_DEST) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->iMCU_row_num = 0; start_iMCU_row(cinfo); } /* * Process some data. * We process the equivalent of one fully interleaved MCU row ("iMCU" row) * per call, ie, v_samp_factor block rows for each component in the scan. * The data is obtained from the virtual arrays and fed to the entropy coder. * Returns TRUE if the iMCU row is completed, FALSE if suspended. * * NB: input_buf is ignored; it is likely to be a NULL pointer. */ METHODDEF(boolean) compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int blkn, ci, xindex, yindex, yoffset, blockcnt; JDIMENSION start_col; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; /* Align the virtual buffers for the components used in this scan. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; buffer[ci] = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); } /* Loop to process one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { /* Construct list of pointers to DCT blocks belonging to this MCU */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; start_col = MCU_col_num * compptr->MCU_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yoffset + yindex < compptr->last_row_height) { /* Fill in pointers to real blocks in this row */ buffer_ptr = buffer[ci][yoffset + yindex] + start_col; xindex = blockcnt; do { MCU_buffer[blkn++] = buffer_ptr++; } while (--xindex); /* Dummy blocks at right edge */ if ((xindex = compptr->MCU_width - blockcnt) == 0) continue; } else { /* At bottom of image, need a whole row of dummy blocks */ xindex = compptr->MCU_width; } /* Fill in any dummy blocks needed in this row. * Dummy blocks are filled in the same way as in jccoefct.c: * all zeroes in the AC entries, DC entries equal to previous * block's DC value. The init routine has already zeroed the * AC entries, so we need only set the DC entries correctly. */ buffer_ptr = coef->dummy_buffer + blkn; do { buffer_ptr[0][0] = MCU_buffer[blkn-1][0][0]; MCU_buffer[blkn++] = buffer_ptr++; } while (--xindex); } } /* Try to write the MCU. */ if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return FALSE; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->MCU_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ coef->iMCU_row_num++; start_iMCU_row(cinfo); return TRUE; } /* * Initialize coefficient buffer controller. * * Each passed coefficient array must be the right size for that * coefficient: width_in_blocks wide and height_in_blocks high, * with unitheight at least v_samp_factor. */ LOCAL(void) transencode_coef_controller (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { my_coef_ptr coef; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); cinfo->coef = &coef->pub; coef->pub.start_pass = start_pass_coef; coef->pub.compress_data = compress_output; /* Save pointer to virtual arrays */ coef->whole_image = coef_arrays; /* Pre-zero space for dummy DCT blocks */ MEMZERO(coef->dummy_buffer, SIZEOF(coef->dummy_buffer)); } fltk-1.4.3/jpeg/jconfig.h0000644000175000017500000000423315004135251015324 0ustar albrechtalbrecht/* FLTK *************************************************************** */ /* FLTK Comments marked with FLTK show modifications for FLTK which */ /* FLTK should probably be preserved when the JPEG lib is upgraded. */ /* FLTK *************************************************************** */ /* FLTK: enable symbol prefixes, see README.bundled-libs.txt */ #include "fltk_jpeg_prefix.h" /* jconfig.h. Generated from jconfig.cfg by configure. */ /* jconfig.cfg --- source file edited by configure script */ /* see jconfig.txt for explanations */ #define HAVE_PROTOTYPES 1 #define HAVE_UNSIGNED_CHAR 1 #define HAVE_UNSIGNED_SHORT 1 /* #undef void */ /* #undef const */ /* #undef CHAR_IS_UNSIGNED */ /* #define HAVE_STDDEF_H 1 */ /* FLTK */ #define HAVE_STDLIB_H 1 /* #define HAVE_LOCALE_H 1 */ /* FLTK */ /* #undef NEED_BSD_STRINGS */ /* #undef NEED_SYS_TYPES_H */ /* #undef NEED_FAR_POINTERS */ /* #undef NEED_SHORT_EXTERNAL_NAMES */ /* Define this if you get warnings about undefined structures. */ /* #undef INCOMPLETE_TYPES_BROKEN */ /* Define "boolean" as unsigned char, not enum, on Windows systems. */ #ifdef _WIN32 #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ typedef unsigned char boolean; #endif #ifndef FALSE /* in case these macros already exist */ #define FALSE 0 /* values of boolean */ #endif #ifndef TRUE #define TRUE 1 #endif #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ #endif #ifdef JPEG_INTERNALS /* #undef RIGHT_SHIFT_IS_UNSIGNED */ /* #define INLINE __inline__ */ /* FLTK */ /* These are for configuring the JPEG memory manager. */ /* #undef DEFAULT_MAX_MEM */ /* #undef NO_MKTEMP */ #endif /* JPEG_INTERNALS */ #ifdef JPEG_CJPEG_DJPEG #define BMP_SUPPORTED /* BMP image file format */ #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ /* #undef RLE_SUPPORTED */ #define TARGA_SUPPORTED /* Targa image file format */ /* #undef TWO_FILE_COMMANDLINE */ /* #undef NEED_SIGNAL_CATCHER */ /* #undef DONT_USE_B_MODE */ /* Define this if you want percent-done progress reports from cjpeg/djpeg. */ /* #undef PROGRESS_REPORT */ #endif /* JPEG_CJPEG_DJPEG */ fltk-1.4.3/jpeg/jddctmgr.c0000644000175000017500000003013415004135251015475 0ustar albrechtalbrecht/* * jddctmgr.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2002-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the inverse-DCT management logic. * This code selects a particular IDCT implementation to be used, * and it performs related housekeeping chores. No code in this file * is executed per IDCT step, only during output pass setup. * * Note that the IDCT routines are responsible for performing coefficient * dequantization as well as the IDCT proper. This module sets up the * dequantization multiplier table needed by the IDCT routine. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ /* * The decompressor input side (jdinput.c) saves away the appropriate * quantization table for each component at the start of the first scan * involving that component. (This is necessary in order to correctly * decode files that reuse Q-table slots.) * When we are ready to make an output pass, the saved Q-table is converted * to a multiplier table that will actually be used by the IDCT routine. * The multiplier table contents are IDCT-method-dependent. To support * application changes in IDCT method between scans, we can remake the * multiplier tables if necessary. * In buffered-image mode, the first output pass may occur before any data * has been seen for some components, and thus before their Q-tables have * been saved away. To handle this case, multiplier tables are preset * to zeroes; the result of the IDCT will be a neutral gray level. */ /* Private subobject for this module */ typedef struct { struct jpeg_inverse_dct pub; /* public fields */ /* This array contains the IDCT method code that each multiplier table * is currently set up for, or -1 if it's not yet set up. * The actual multiplier tables are pointed to by dct_table in the * per-component comp_info structures. */ int cur_method[MAX_COMPONENTS]; } my_idct_controller; typedef my_idct_controller * my_idct_ptr; /* Allocated multiplier tables: big enough for any supported variant */ typedef union { ISLOW_MULT_TYPE islow_array[DCTSIZE2]; #ifdef DCT_IFAST_SUPPORTED IFAST_MULT_TYPE ifast_array[DCTSIZE2]; #endif #ifdef DCT_FLOAT_SUPPORTED FLOAT_MULT_TYPE float_array[DCTSIZE2]; #endif } multiplier_table; /* The current scaled-IDCT routines require ISLOW-style multiplier tables, * so be sure to compile that code if either ISLOW or SCALING is requested. */ #ifdef DCT_ISLOW_SUPPORTED #define PROVIDE_ISLOW_TABLES #else #ifdef IDCT_SCALING_SUPPORTED #define PROVIDE_ISLOW_TABLES #endif #endif /* * Prepare for an output pass. * Here we select the proper IDCT routine for each component and build * a matching multiplier table. */ METHODDEF(void) start_pass (j_decompress_ptr cinfo) { my_idct_ptr idct = (my_idct_ptr) cinfo->idct; int ci, i; jpeg_component_info *compptr; int method = 0; inverse_DCT_method_ptr method_ptr = NULL; JQUANT_TBL * qtbl; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Select the proper IDCT routine for this component's scaling */ switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) { #ifdef IDCT_SCALING_SUPPORTED case ((1 << 8) + 1): method_ptr = jpeg_idct_1x1; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((2 << 8) + 2): method_ptr = jpeg_idct_2x2; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((3 << 8) + 3): method_ptr = jpeg_idct_3x3; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((4 << 8) + 4): method_ptr = jpeg_idct_4x4; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((5 << 8) + 5): method_ptr = jpeg_idct_5x5; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((6 << 8) + 6): method_ptr = jpeg_idct_6x6; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((7 << 8) + 7): method_ptr = jpeg_idct_7x7; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((9 << 8) + 9): method_ptr = jpeg_idct_9x9; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((10 << 8) + 10): method_ptr = jpeg_idct_10x10; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((11 << 8) + 11): method_ptr = jpeg_idct_11x11; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((12 << 8) + 12): method_ptr = jpeg_idct_12x12; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((13 << 8) + 13): method_ptr = jpeg_idct_13x13; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((14 << 8) + 14): method_ptr = jpeg_idct_14x14; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((15 << 8) + 15): method_ptr = jpeg_idct_15x15; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((16 << 8) + 16): method_ptr = jpeg_idct_16x16; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((16 << 8) + 8): method_ptr = jpeg_idct_16x8; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((14 << 8) + 7): method_ptr = jpeg_idct_14x7; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((12 << 8) + 6): method_ptr = jpeg_idct_12x6; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((10 << 8) + 5): method_ptr = jpeg_idct_10x5; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((8 << 8) + 4): method_ptr = jpeg_idct_8x4; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((6 << 8) + 3): method_ptr = jpeg_idct_6x3; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((4 << 8) + 2): method_ptr = jpeg_idct_4x2; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((2 << 8) + 1): method_ptr = jpeg_idct_2x1; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((8 << 8) + 16): method_ptr = jpeg_idct_8x16; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((7 << 8) + 14): method_ptr = jpeg_idct_7x14; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((6 << 8) + 12): method_ptr = jpeg_idct_6x12; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((5 << 8) + 10): method_ptr = jpeg_idct_5x10; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((4 << 8) + 8): method_ptr = jpeg_idct_4x8; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((3 << 8) + 6): method_ptr = jpeg_idct_3x6; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((2 << 8) + 4): method_ptr = jpeg_idct_2x4; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; case ((1 << 8) + 2): method_ptr = jpeg_idct_1x2; method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; #endif case ((DCTSIZE << 8) + DCTSIZE): switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: method_ptr = jpeg_idct_islow; method = JDCT_ISLOW; break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: method_ptr = jpeg_idct_ifast; method = JDCT_IFAST; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: method_ptr = jpeg_idct_float; method = JDCT_FLOAT; break; #endif default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; } break; default: ERREXIT2(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); break; } idct->pub.inverse_DCT[ci] = method_ptr; /* Create multiplier table from quant table. * However, we can skip this if the component is uninteresting * or if we already built the table. Also, if no quant table * has yet been saved for the component, we leave the * multiplier table all-zero; we'll be reading zeroes from the * coefficient controller's buffer anyway. */ if (! compptr->component_needed || idct->cur_method[ci] == method) continue; qtbl = compptr->quant_table; if (qtbl == NULL) /* happens if no data yet for component */ continue; idct->cur_method[ci] = method; switch (method) { #ifdef PROVIDE_ISLOW_TABLES case JDCT_ISLOW: { /* For LL&M IDCT method, multipliers are equal to raw quantization * coefficients, but are stored as ints to ensure access efficiency. */ ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; for (i = 0; i < DCTSIZE2; i++) { ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; } } break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: { /* For AA&N IDCT method, multipliers are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * For integer operation, the multiplier table is to be scaled by * IFAST_SCALE_BITS. */ IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; #define CONST_BITS 14 static const INT16 aanscales[DCTSIZE2] = { /* precomputed values scaled up by 14 bits */ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 }; SHIFT_TEMPS for (i = 0; i < DCTSIZE2; i++) { ifmtbl[i] = (IFAST_MULT_TYPE) DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], (INT32) aanscales[i]), CONST_BITS-IFAST_SCALE_BITS); } } break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: { /* For float AA&N IDCT method, multipliers are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * We apply a further scale factor of 1/8. */ FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; int row, col; static const double aanscalefactor[DCTSIZE] = { 1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958, 0.541196100, 0.275899379 }; i = 0; for (row = 0; row < DCTSIZE; row++) { for (col = 0; col < DCTSIZE; col++) { fmtbl[i] = (FLOAT_MULT_TYPE) ((double) qtbl->quantval[i] * aanscalefactor[row] * aanscalefactor[col] * 0.125); i++; } } } break; #endif default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; } } } /* * Initialize IDCT manager. */ GLOBAL(void) jinit_inverse_dct (j_decompress_ptr cinfo) { my_idct_ptr idct; int ci; jpeg_component_info *compptr; idct = (my_idct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_idct_controller)); cinfo->idct = &idct->pub; idct->pub.start_pass = start_pass; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Allocate and pre-zero a multiplier table for each component */ compptr->dct_table = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(multiplier_table)); MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); /* Mark multiplier table not yet set up for any method */ idct->cur_method[ci] = -1; } } fltk-1.4.3/jpeg/jdmainct.c0000644000175000017500000005044515004135251015477 0ustar albrechtalbrecht/* * jdmainct.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2002-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the main buffer controller for decompression. * The main buffer lies between the JPEG decompressor proper and the * post-processor; it holds downsampled data in the JPEG colorspace. * * Note that this code is bypassed in raw-data mode, since the application * supplies the equivalent of the main buffer in that case. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * In the current system design, the main buffer need never be a full-image * buffer; any full-height buffers will be found inside the coefficient or * postprocessing controllers. Nonetheless, the main controller is not * trivial. Its responsibility is to provide context rows for upsampling/ * rescaling, and doing this in an efficient fashion is a bit tricky. * * Postprocessor input data is counted in "row groups". A row group is * defined to be (v_samp_factor * DCT_v_scaled_size / min_DCT_v_scaled_size) * sample rows of each component. (We require DCT_scaled_size values to be * chosen such that these numbers are integers. In practice DCT_scaled_size * values will likely be powers of two, so we actually have the stronger * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) * Upsampling will typically produce max_v_samp_factor pixel rows from each * row group (times any additional scale factor that the upsampler is * applying). * * The coefficient controller will deliver data to us one iMCU row at a time; * each iMCU row contains v_samp_factor * DCT_v_scaled_size sample rows, or * exactly min_DCT_v_scaled_size row groups. (This amount of data corresponds * to one row of MCUs when the image is fully interleaved.) Note that the * number of sample rows varies across components, but the number of row * groups does not. Some garbage sample rows may be included in the last iMCU * row at the bottom of the image. * * Depending on the vertical scaling algorithm used, the upsampler may need * access to the sample row(s) above and below its current input row group. * The upsampler is required to set need_context_rows TRUE at global selection * time if so. When need_context_rows is FALSE, this controller can simply * obtain one iMCU row at a time from the coefficient controller and dole it * out as row groups to the postprocessor. * * When need_context_rows is TRUE, this controller guarantees that the buffer * passed to postprocessing contains at least one row group's worth of samples * above and below the row group(s) being processed. Note that the context * rows "above" the first passed row group appear at negative row offsets in * the passed buffer. At the top and bottom of the image, the required * context rows are manufactured by duplicating the first or last real sample * row; this avoids having special cases in the upsampling inner loops. * * The amount of context is fixed at one row group just because that's a * convenient number for this controller to work with. The existing * upsamplers really only need one sample row of context. An upsampler * supporting arbitrary output rescaling might wish for more than one row * group of context when shrinking the image; tough, we don't handle that. * (This is justified by the assumption that downsizing will be handled mostly * by adjusting the DCT_scaled_size values, so that the actual scale factor at * the upsample step needn't be much less than one.) * * To provide the desired context, we have to retain the last two row groups * of one iMCU row while reading in the next iMCU row. (The last row group * can't be processed until we have another row group for its below-context, * and so we have to save the next-to-last group too for its above-context.) * We could do this most simply by copying data around in our buffer, but * that'd be very slow. We can avoid copying any data by creating a rather * strange pointer structure. Here's how it works. We allocate a workspace * consisting of M+2 row groups (where M = min_DCT_v_scaled_size is the number * of row groups per iMCU row). We create two sets of redundant pointers to * the workspace. Labeling the physical row groups 0 to M+1, the synthesized * pointer lists look like this: * M+1 M-1 * master pointer --> 0 master pointer --> 0 * 1 1 * ... ... * M-3 M-3 * M-2 M * M-1 M+1 * M M-2 * M+1 M-1 * 0 0 * We read alternate iMCU rows using each master pointer; thus the last two * row groups of the previous iMCU row remain un-overwritten in the workspace. * The pointer lists are set up so that the required context rows appear to * be adjacent to the proper places when we pass the pointer lists to the * upsampler. * * The above pictures describe the normal state of the pointer lists. * At top and bottom of the image, we diddle the pointer lists to duplicate * the first or last sample row as necessary (this is cheaper than copying * sample rows around). * * This scheme breaks down if M < 2, ie, min_DCT_v_scaled_size is 1. In that * situation each iMCU row provides only one row group so the buffering logic * must be different (eg, we must read two iMCU rows before we can emit the * first row group). For now, we simply do not support providing context * rows when min_DCT_v_scaled_size is 1. That combination seems unlikely to * be worth providing --- if someone wants a 1/8th-size preview, they probably * want it quick and dirty, so a context-free upsampler is sufficient. */ /* Private buffer controller object */ typedef struct { struct jpeg_d_main_controller pub; /* public fields */ /* Pointer to allocated workspace (M or M+2 row groups). */ JSAMPARRAY buffer[MAX_COMPONENTS]; JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ /* Remaining fields are only used in the context case. */ boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ /* These are the master pointers to the funny-order pointer lists. */ JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ int whichptr; /* indicates which pointer set is now in use */ int context_state; /* process_data state machine status */ JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ } my_main_controller; typedef my_main_controller * my_main_ptr; /* context_state values: */ #define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ #define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ #define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ /* Forward declarations */ METHODDEF(void) process_data_simple_main JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); METHODDEF(void) process_data_context_main JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) process_data_crank_post JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #endif LOCAL(void) alloc_funny_pointers (j_decompress_ptr cinfo) /* Allocate space for the funny pointer lists. * This is done only once, not once per pass. */ { my_main_ptr mainp = (my_main_ptr) cinfo->main; int ci, rgroup; int M = cinfo->min_DCT_v_scaled_size; jpeg_component_info *compptr; JSAMPARRAY xbuf; /* Get top-level space for component array pointers. * We alloc both arrays with one call to save a few cycles. */ mainp->xbuffer[0] = (JSAMPIMAGE) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); mainp->xbuffer[1] = mainp->xbuffer[0] + cinfo->num_components; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (! compptr->component_needed) continue; /* skip uninteresting component */ rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ /* Get space for pointer lists --- M+4 row groups in each list. * We alloc both pointer lists with one call to save a few cycles. */ xbuf = (JSAMPARRAY) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); xbuf += rgroup; /* want one row group at negative offsets */ mainp->xbuffer[0][ci] = xbuf; xbuf += rgroup * (M + 4); mainp->xbuffer[1][ci] = xbuf; } } LOCAL(void) make_funny_pointers (j_decompress_ptr cinfo) /* Create the funny pointer lists discussed in the comments above. * The actual workspace is already allocated (in mainp->buffer), * and the space for the pointer lists is allocated too. * This routine just fills in the curiously ordered lists. * This will be repeated at the beginning of each pass. */ { my_main_ptr mainp = (my_main_ptr) cinfo->main; int ci, i, rgroup; int M = cinfo->min_DCT_v_scaled_size; jpeg_component_info *compptr; JSAMPARRAY buf, xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (! compptr->component_needed) continue; /* skip uninteresting component */ rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ xbuf0 = mainp->xbuffer[0][ci]; xbuf1 = mainp->xbuffer[1][ci]; /* First copy the workspace pointers as-is */ buf = mainp->buffer[ci]; for (i = 0; i < rgroup * (M + 2); i++) { xbuf0[i] = xbuf1[i] = buf[i]; } /* In the second list, put the last four row groups in swapped order */ for (i = 0; i < rgroup * 2; i++) { xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; } /* The wraparound pointers at top and bottom will be filled later * (see set_wraparound_pointers, below). Initially we want the "above" * pointers to duplicate the first actual data line. This only needs * to happen in xbuffer[0]. */ for (i = 0; i < rgroup; i++) { xbuf0[i - rgroup] = xbuf0[0]; } } } LOCAL(void) set_wraparound_pointers (j_decompress_ptr cinfo) /* Set up the "wraparound" pointers at top and bottom of the pointer lists. * This changes the pointer list state from top-of-image to the normal state. */ { my_main_ptr mainp = (my_main_ptr) cinfo->main; int ci, i, rgroup; int M = cinfo->min_DCT_v_scaled_size; jpeg_component_info *compptr; JSAMPARRAY xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (! compptr->component_needed) continue; /* skip uninteresting component */ rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ xbuf0 = mainp->xbuffer[0][ci]; xbuf1 = mainp->xbuffer[1][ci]; for (i = 0; i < rgroup; i++) { xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; xbuf0[rgroup*(M+2) + i] = xbuf0[i]; xbuf1[rgroup*(M+2) + i] = xbuf1[i]; } } } LOCAL(void) set_bottom_pointers (j_decompress_ptr cinfo) /* Change the pointer lists to duplicate the last sample row at the bottom * of the image. whichptr indicates which xbuffer holds the final iMCU row. * Also sets rowgroups_avail to indicate number of nondummy row groups in row. */ { my_main_ptr mainp = (my_main_ptr) cinfo->main; int ci, i, rgroup, iMCUheight, rows_left; jpeg_component_info *compptr; JSAMPARRAY xbuf; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (! compptr->component_needed) continue; /* skip uninteresting component */ /* Count sample rows in one iMCU row and in one row group */ iMCUheight = compptr->v_samp_factor * compptr->DCT_v_scaled_size; rgroup = iMCUheight / cinfo->min_DCT_v_scaled_size; /* Count nondummy sample rows remaining for this component */ rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); if (rows_left == 0) rows_left = iMCUheight; /* Count nondummy row groups. Should get same answer for each component, * so we need only do it once. */ if (ci == 0) { mainp->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); } /* Duplicate the last real sample row rgroup*2 times; this pads out the * last partial rowgroup and ensures at least one full rowgroup of context. */ xbuf = mainp->xbuffer[mainp->whichptr][ci]; for (i = 0; i < rgroup * 2; i++) { xbuf[rows_left + i] = xbuf[rows_left-1]; } } } /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) { my_main_ptr mainp = (my_main_ptr) cinfo->main; switch (pass_mode) { case JBUF_PASS_THRU: if (cinfo->upsample->need_context_rows) { mainp->pub.process_data = process_data_context_main; make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ mainp->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ mainp->context_state = CTX_PREPARE_FOR_IMCU; mainp->iMCU_row_ctr = 0; mainp->buffer_full = FALSE; /* Mark buffer empty */ } else { /* Simple case with no context needed */ mainp->pub.process_data = process_data_simple_main; mainp->rowgroup_ctr = mainp->rowgroups_avail; /* Mark buffer empty */ } break; #ifdef QUANT_2PASS_SUPPORTED case JBUF_CRANK_DEST: /* For last pass of 2-pass quantization, just crank the postprocessor */ mainp->pub.process_data = process_data_crank_post; break; #endif default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); } } /* * Process some data. * This handles the simple case where no context is required. */ METHODDEF(void) process_data_simple_main (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_main_ptr mainp = (my_main_ptr) cinfo->main; /* Read input data if we haven't filled the main buffer yet */ if (mainp->rowgroup_ctr >= mainp->rowgroups_avail) { if (! (*cinfo->coef->decompress_data) (cinfo, mainp->buffer)) return; /* suspension forced, can do nothing more */ mainp->rowgroup_ctr = 0; /* OK, we have an iMCU row to work with */ } /* Note: at the bottom of the image, we may pass extra garbage row groups * to the postprocessor. The postprocessor has to check for bottom * of image anyway (at row resolution), so no point in us doing it too. */ /* Feed the postprocessor */ (*cinfo->post->post_process_data) (cinfo, mainp->buffer, &mainp->rowgroup_ctr, mainp->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); } /* * Process some data. * This handles the case where context rows must be provided. */ METHODDEF(void) process_data_context_main (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_main_ptr mainp = (my_main_ptr) cinfo->main; /* Read input data if we haven't filled the main buffer yet */ if (! mainp->buffer_full) { if (! (*cinfo->coef->decompress_data) (cinfo, mainp->xbuffer[mainp->whichptr])) return; /* suspension forced, can do nothing more */ mainp->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ mainp->iMCU_row_ctr++; /* count rows received */ } /* Postprocessor typically will not swallow all the input data it is handed * in one call (due to filling the output buffer first). Must be prepared * to exit and restart. This switch lets us keep track of how far we got. * Note that each case falls through to the next on successful completion. */ switch (mainp->context_state) { case CTX_POSTPONED_ROW: /* Call postprocessor using previously set pointers for postponed row */ (*cinfo->post->post_process_data) (cinfo, mainp->xbuffer[mainp->whichptr], &mainp->rowgroup_ctr, mainp->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); if (mainp->rowgroup_ctr < mainp->rowgroups_avail) return; /* Need to suspend */ mainp->context_state = CTX_PREPARE_FOR_IMCU; if (*out_row_ctr >= out_rows_avail) return; /* Postprocessor exactly filled output buf */ /*FALLTHROUGH*/ case CTX_PREPARE_FOR_IMCU: /* Prepare to process first M-1 row groups of this iMCU row */ mainp->rowgroup_ctr = 0; mainp->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size - 1); /* Check for bottom of image: if so, tweak pointers to "duplicate" * the last sample row, and adjust rowgroups_avail to ignore padding rows. */ if (mainp->iMCU_row_ctr == cinfo->total_iMCU_rows) set_bottom_pointers(cinfo); mainp->context_state = CTX_PROCESS_IMCU; /*FALLTHROUGH*/ case CTX_PROCESS_IMCU: /* Call postprocessor using previously set pointers */ (*cinfo->post->post_process_data) (cinfo, mainp->xbuffer[mainp->whichptr], &mainp->rowgroup_ctr, mainp->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); if (mainp->rowgroup_ctr < mainp->rowgroups_avail) return; /* Need to suspend */ /* After the first iMCU, change wraparound pointers to normal state */ if (mainp->iMCU_row_ctr == 1) set_wraparound_pointers(cinfo); /* Prepare to load new iMCU row using other xbuffer list */ mainp->whichptr ^= 1; /* 0=>1 or 1=>0 */ mainp->buffer_full = FALSE; /* Still need to process last row group of this iMCU row, */ /* which is saved at index M+1 of the other xbuffer */ mainp->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 1); mainp->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 2); mainp->context_state = CTX_POSTPONED_ROW; } } /* * Process some data. * Final pass of two-pass quantization: just call the postprocessor. * Source data will be the postprocessor controller's internal buffer. */ #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) process_data_crank_post (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, (JDIMENSION *) NULL, (JDIMENSION) 0, output_buf, out_row_ctr, out_rows_avail); } #endif /* QUANT_2PASS_SUPPORTED */ /* * Initialize main buffer controller. */ GLOBAL(void) jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_main_ptr mainp; int ci, rgroup, ngroups; jpeg_component_info *compptr; mainp = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); cinfo->main = &mainp->pub; mainp->pub.start_pass = start_pass_main; if (need_full_buffer) /* shouldn't happen */ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); /* Allocate the workspace. * ngroups is the number of row groups we need. */ if (cinfo->upsample->need_context_rows) { if (cinfo->min_DCT_v_scaled_size < 2) /* unsupported, see comments above */ ERREXIT(cinfo, JERR_NOTIMPL); alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ ngroups = cinfo->min_DCT_v_scaled_size + 2; } else { /* There are always min_DCT_v_scaled_size row groups in an iMCU row. */ ngroups = cinfo->min_DCT_v_scaled_size; mainp->rowgroups_avail = (JDIMENSION) ngroups; } for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (! compptr->component_needed) continue; /* skip uninteresting component */ rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ mainp->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * ((JDIMENSION) compptr->DCT_h_scaled_size), (JDIMENSION) (rgroup * ngroups)); } } fltk-1.4.3/jpeg/jdcolor.c0000644000175000017500000006065215004135251015343 0ustar albrechtalbrecht/* * jdcolor.c * * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2011-2023 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains output colorspace conversion routines. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #if RANGE_BITS < 2 /* Deliberate syntax err */ Sorry, this code requires 2 or more range extension bits. #endif /* Private subobject */ typedef struct { struct jpeg_color_deconverter pub; /* public fields */ /* Private state for YCbCr->RGB and BG_YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ int * Cb_b_tab; /* => table for Cb to B conversion */ INT32 * Cr_g_tab; /* => table for Cr to G conversion */ INT32 * Cb_g_tab; /* => table for Cb to G conversion */ /* Private state for RGB->Y conversion */ INT32 * R_y_tab; /* => table for R to Y conversion */ INT32 * G_y_tab; /* => table for G to Y conversion */ INT32 * B_y_tab; /* => table for B to Y conversion */ } my_color_deconverter; typedef my_color_deconverter * my_cconvert_ptr; /*************** YCbCr -> RGB conversion: most common case **************/ /*************** BG_YCC -> RGB conversion: less common case **************/ /*************** RGB -> Y conversion: less common case **************/ /* * YCbCr is defined per Recommendation ITU-R BT.601-7 (03/2011), * previously known as Recommendation CCIR 601-1, except that Cb and Cr * are normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. * sRGB (standard RGB color space) is defined per IEC 61966-2-1:1999. * sYCC (standard luma-chroma-chroma color space with extended gamut) * is defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex F. * bg-sRGB and bg-sYCC (big gamut standard color spaces) * are defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex G. * Note that the derived conversion coefficients given in some of these * documents are imprecise. The general conversion equations are * * R = Y + K * (1 - Kr) * Cr * G = Y - K * (Kb * (1 - Kb) * Cb + Kr * (1 - Kr) * Cr) / (1 - Kr - Kb) * B = Y + K * (1 - Kb) * Cb * * Y = Kr * R + (1 - Kr - Kb) * G + Kb * B * * With Kr = 0.299 and Kb = 0.114 (derived according to SMPTE RP 177-1993 * from the 1953 FCC NTSC primaries and CIE Illuminant C), K = 2 for sYCC, * the conversion equations to be implemented are therefore * * R = Y + 1.402 * Cr * G = Y - 0.344136286 * Cb - 0.714136286 * Cr * B = Y + 1.772 * Cb * * Y = 0.299 * R + 0.587 * G + 0.114 * B * * where Cb and Cr represent the incoming values less CENTERJSAMPLE. * For bg-sYCC, with K = 4, the equations are * * R = Y + 2.804 * Cr * G = Y - 0.688272572 * Cb - 1.428272572 * Cr * B = Y + 3.544 * Cb * * To avoid floating-point arithmetic, we represent the fractional constants * as integers scaled up by 2^16 (about 4 digits precision); we have to divide * the products by 2^16, with appropriate rounding, to get the correct answer. * Notice that Y, being an integral input, does not contribute any fraction * so it need not participate in the rounding. * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times Cb and Cr for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); * for 9-bit to 12-bit samples it is still acceptable. It's not very * reasonable for 16-bit samples, but if you want lossless storage * you shouldn't be changing colorspace anyway. * The Cr=>R and Cb=>B values can be rounded to integers in advance; * the values for the G calculation are left scaled up, * since we must add them together before rounding. */ #define SCALEBITS 16 /* speediest right-shift on some machines */ #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L<RGB and BG_YCC->RGB colorspace conversion. */ LOCAL(void) build_ycc_rgb_table (j_decompress_ptr cinfo) /* Normal case, sYCC */ { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; int i; INT32 x; SHIFT_TEMPS cconvert->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cr_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); cconvert->Cb_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ /* Cr=>R value is nearest int to 1.402 * x */ cconvert->Cr_r_tab[i] = (int) DESCALE(FIX(1.402) * x, SCALEBITS); /* Cb=>B value is nearest int to 1.772 * x */ cconvert->Cb_b_tab[i] = (int) DESCALE(FIX(1.772) * x, SCALEBITS); /* Cr=>G value is scaled-up -0.714136286 * x */ cconvert->Cr_g_tab[i] = (- FIX(0.714136286)) * x; /* Cb=>G value is scaled-up -0.344136286 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ cconvert->Cb_g_tab[i] = (- FIX(0.344136286)) * x + ONE_HALF; } } LOCAL(void) build_bg_ycc_rgb_table (j_decompress_ptr cinfo) /* Wide gamut case, bg-sYCC */ { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; int i; INT32 x; SHIFT_TEMPS cconvert->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cr_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); cconvert->Cb_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ /* Cr=>R value is nearest int to 2.804 * x */ cconvert->Cr_r_tab[i] = (int) DESCALE(FIX(2.804) * x, SCALEBITS); /* Cb=>B value is nearest int to 3.544 * x */ cconvert->Cb_b_tab[i] = (int) DESCALE(FIX(3.544) * x, SCALEBITS); /* Cr=>G value is scaled-up -1.428272572 * x */ cconvert->Cr_g_tab[i] = (- FIX(1.428272572)) * x; /* Cb=>G value is scaled-up -0.688272572 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ cconvert->Cb_g_tab[i] = (- FIX(0.688272572)) * x + ONE_HALF; } } /* * Convert some rows of samples to the output colorspace. * * Note that we change from noninterleaved, one-plane-per-component format * to interleaved-pixel format. The output buffer is therefore three times * as wide as the input buffer. * * A starting row offset is provided only for the input buffer. The caller * can easily adjust the passed output_buf value to accommodate any row * offset required on that side. */ METHODDEF(void) ycc_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; register int * Crrtab = cconvert->Cr_r_tab; register int * Cbbtab = cconvert->Cb_b_tab; register INT32 * Crgtab = cconvert->Cr_g_tab; register INT32 * Cbgtab = cconvert->Cb_g_tab; SHIFT_TEMPS while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); /* Range-limiting is essential due to noise introduced by DCT losses, * for extended gamut (sYCC) and wide gamut (bg-sYCC) encodings. */ outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; outptr[RGB_GREEN] = range_limit[y + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))]; outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; outptr += RGB_PIXELSIZE; } } } /**************** Cases other than YCC -> RGB ****************/ /* * Initialize for RGB->grayscale colorspace conversion. */ LOCAL(void) build_rgb_y_table (j_decompress_ptr cinfo) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; INT32 i; cconvert->R_y_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); cconvert->G_y_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); cconvert->B_y_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0; i <= MAXJSAMPLE; i++) { cconvert->R_y_tab[i] = FIX(0.299) * i; cconvert->G_y_tab[i] = FIX(0.587) * i; cconvert->B_y_tab[i] = FIX(0.114) * i + ONE_HALF; } } /* * Convert RGB to grayscale. */ METHODDEF(void) rgb_gray_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register INT32 y; register INT32 * Rytab = cconvert->R_y_tab; register INT32 * Gytab = cconvert->G_y_tab; register INT32 * Bytab = cconvert->B_y_tab; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { y = Rytab[GETJSAMPLE(inptr0[col])]; y += Gytab[GETJSAMPLE(inptr1[col])]; y += Bytab[GETJSAMPLE(inptr2[col])]; outptr[col] = (JSAMPLE) (y >> SCALEBITS); } } } /* * Convert some rows of samples to the output colorspace. * [R-G,G,B-G] to [R,G,B] conversion with modulo calculation * (inverse color transform). * This can be seen as an adaption of the general YCbCr->RGB * conversion equation with Kr = Kb = 0, while replacing the * normalization by modulo calculation. */ METHODDEF(void) rgb1_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { register int r, g, b; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { r = GETJSAMPLE(inptr0[col]); g = GETJSAMPLE(inptr1[col]); b = GETJSAMPLE(inptr2[col]); /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD * (modulo) operator is equivalent to the bitmask operator AND. */ outptr[RGB_RED] = (JSAMPLE) ((r + g - CENTERJSAMPLE) & MAXJSAMPLE); outptr[RGB_GREEN] = (JSAMPLE) g; outptr[RGB_BLUE] = (JSAMPLE) ((b + g - CENTERJSAMPLE) & MAXJSAMPLE); outptr += RGB_PIXELSIZE; } } } /* * [R-G,G,B-G] to grayscale conversion with modulo calculation * (inverse color transform). */ METHODDEF(void) rgb1_gray_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int r, g, b; register INT32 y; register INT32 * Rytab = cconvert->R_y_tab; register INT32 * Gytab = cconvert->G_y_tab; register INT32 * Bytab = cconvert->B_y_tab; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { r = GETJSAMPLE(inptr0[col]); g = GETJSAMPLE(inptr1[col]); b = GETJSAMPLE(inptr2[col]); /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD * (modulo) operator is equivalent to the bitmask operator AND. */ y = Rytab[(r + g - CENTERJSAMPLE) & MAXJSAMPLE]; y += Gytab[g]; y += Bytab[(b + g - CENTERJSAMPLE) & MAXJSAMPLE]; outptr[col] = (JSAMPLE) (y >> SCALEBITS); } } } /* * Convert some rows of samples to the output colorspace. * No colorspace change, but conversion from separate-planes * to interleaved representation. */ METHODDEF(void) rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { /* We can dispense with GETJSAMPLE() here */ outptr[RGB_RED] = inptr0[col]; outptr[RGB_GREEN] = inptr1[col]; outptr[RGB_BLUE] = inptr2[col]; outptr += RGB_PIXELSIZE; } } } /* * Color conversion for no colorspace change: just copy the data, * converting from separate-planes to interleaved representation. * Note: Omit uninteresting components in output buffer. */ METHODDEF(void) null_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { register JSAMPROW outptr; register JSAMPROW inptr; register JDIMENSION count; register int out_comps = cinfo->out_color_components; JDIMENSION num_cols = cinfo->output_width; JSAMPROW startptr; int ci; jpeg_component_info *compptr; while (--num_rows >= 0) { /* It seems fastest to make a separate pass for each component. */ startptr = *output_buf++; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (! compptr->component_needed) continue; /* skip uninteresting component */ inptr = input_buf[ci][input_row]; outptr = startptr++; for (count = num_cols; count > 0; count--) { *outptr = *inptr++; /* don't need GETJSAMPLE() here */ outptr += out_comps; } } input_row++; } } /* * Color conversion for grayscale: just copy the data. * This also works for YCC -> grayscale conversion, in which * we just copy the Y (luminance) component and ignore chrominance. */ METHODDEF(void) grayscale_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { jcopy_sample_rows(input_buf[0] + input_row, output_buf, num_rows, cinfo->output_width); } /* * Convert grayscale to RGB: just duplicate the graylevel three times. * This is provided to support applications that don't want to cope * with grayscale as a separate case. */ METHODDEF(void) gray_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { register JSAMPROW outptr; register JSAMPROW inptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; while (--num_rows >= 0) { inptr = input_buf[0][input_row++]; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { /* We can dispense with GETJSAMPLE() here */ outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; outptr += RGB_PIXELSIZE; } } } /* * Convert some rows of samples to the output colorspace. * This version handles Adobe-style YCCK->CMYK conversion, * where we convert YCbCr to R=1-C, G=1-M, and B=1-Y using the * same conversion as above, while passing K (black) unchanged. * We assume build_ycc_rgb_table has been called. */ METHODDEF(void) ycck_cmyk_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2, inptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; register int * Crrtab = cconvert->Cr_r_tab; register int * Cbbtab = cconvert->Cb_b_tab; register INT32 * Crgtab = cconvert->Cr_g_tab; register INT32 * Cbgtab = cconvert->Cb_g_tab; SHIFT_TEMPS while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; inptr3 = input_buf[3][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); /* Range-limiting is essential due to noise introduced by DCT losses, * and for extended gamut encodings (sYCC). */ outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS)))]; outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ /* K passes through unchanged */ outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ outptr += 4; } } } /* * Convert CMYK to YK part of YCCK for colorless output. * We assume build_rgb_y_table has been called. */ METHODDEF(void) cmyk_yk_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register INT32 y; register INT32 * Rytab = cconvert->R_y_tab; register INT32 * Gytab = cconvert->G_y_tab; register INT32 * Bytab = cconvert->B_y_tab; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2, inptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; inptr3 = input_buf[3][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { y = Rytab[MAXJSAMPLE - GETJSAMPLE(inptr0[col])]; y += Gytab[MAXJSAMPLE - GETJSAMPLE(inptr1[col])]; y += Bytab[MAXJSAMPLE - GETJSAMPLE(inptr2[col])]; outptr[0] = (JSAMPLE) (y >> SCALEBITS); /* K passes through unchanged */ outptr[1] = inptr3[col]; /* don't need GETJSAMPLE here */ outptr += 2; } } } /* * Empty method for start_pass. */ METHODDEF(void) start_pass_dcolor (j_decompress_ptr cinfo) { /* no work needed */ } /* * Module initialization routine for output colorspace conversion. */ GLOBAL(void) jinit_color_deconverter (j_decompress_ptr cinfo) { my_cconvert_ptr cconvert; int ci, i; cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_deconverter)); cinfo->cconvert = &cconvert->pub; cconvert->pub.start_pass = start_pass_dcolor; /* Make sure num_components agrees with jpeg_color_space */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; case JCS_RGB: case JCS_YCbCr: case JCS_BG_RGB: case JCS_BG_YCC: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; case JCS_CMYK: case JCS_YCCK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; default: /* JCS_UNKNOWN can be anything */ if (cinfo->num_components < 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); } /* Support color transform only for RGB colorspaces */ if (cinfo->color_transform && cinfo->jpeg_color_space != JCS_RGB && cinfo->jpeg_color_space != JCS_BG_RGB) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); /* Set out_color_components and conversion method based on requested space. * Also adjust the component_needed flags for any unused components, * so that earlier pipeline stages can avoid useless computation. */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: cinfo->out_color_components = 1; switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: case JCS_YCbCr: case JCS_BG_YCC: cconvert->pub.color_convert = grayscale_convert; /* For color->grayscale conversion, only the Y (0) component is needed */ for (ci = 1; ci < cinfo->num_components; ci++) cinfo->comp_info[ci].component_needed = FALSE; break; case JCS_RGB: switch (cinfo->color_transform) { case JCT_NONE: cconvert->pub.color_convert = rgb_gray_convert; break; case JCT_SUBTRACT_GREEN: cconvert->pub.color_convert = rgb1_gray_convert; break; default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } build_rgb_y_table(cinfo); break; default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } break; case JCS_RGB: cinfo->out_color_components = RGB_PIXELSIZE; switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: cconvert->pub.color_convert = gray_rgb_convert; break; case JCS_YCbCr: cconvert->pub.color_convert = ycc_rgb_convert; build_ycc_rgb_table(cinfo); break; case JCS_BG_YCC: cconvert->pub.color_convert = ycc_rgb_convert; build_bg_ycc_rgb_table(cinfo); break; case JCS_RGB: switch (cinfo->color_transform) { case JCT_NONE: cconvert->pub.color_convert = rgb_convert; break; case JCT_SUBTRACT_GREEN: cconvert->pub.color_convert = rgb1_rgb_convert; break; default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } break; default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } break; case JCS_BG_RGB: if (cinfo->jpeg_color_space != JCS_BG_RGB) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cinfo->out_color_components = RGB_PIXELSIZE; switch (cinfo->color_transform) { case JCT_NONE: cconvert->pub.color_convert = rgb_convert; break; case JCT_SUBTRACT_GREEN: cconvert->pub.color_convert = rgb1_rgb_convert; break; default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } break; case JCS_CMYK: if (cinfo->jpeg_color_space != JCS_YCCK) goto def_label; cinfo->out_color_components = 4; cconvert->pub.color_convert = ycck_cmyk_convert; build_ycc_rgb_table(cinfo); break; case JCS_YCCK: if (cinfo->jpeg_color_space != JCS_CMYK || /* Support only YK part of YCCK for colorless output */ ! cinfo->comp_info[0].component_needed || cinfo->comp_info[1].component_needed || cinfo->comp_info[2].component_needed || ! cinfo->comp_info[3].component_needed) goto def_label; cinfo->out_color_components = 2; /* Need all components on input side */ cinfo->comp_info[1].component_needed = TRUE; cinfo->comp_info[2].component_needed = TRUE; cconvert->pub.color_convert = cmyk_yk_convert; build_rgb_y_table(cinfo); break; default: def_label: /* permit null conversion to same output space */ if (cinfo->out_color_space != cinfo->jpeg_color_space) /* unsupported non-null conversion */ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); i = 0; for (ci = 0; ci < cinfo->num_components; ci++) if (cinfo->comp_info[ci].component_needed) i++; /* count output color components */ cinfo->out_color_components = i; cconvert->pub.color_convert = null_convert; } if (cinfo->quantize_colors) cinfo->output_components = 1; /* single colormapped output component */ else cinfo->output_components = cinfo->out_color_components; } fltk-1.4.3/jpeg/jfdctflt.c0000644000175000017500000001364115004135251015503 0ustar albrechtalbrecht/* * jfdctflt.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2003-2017 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a floating-point implementation of the * forward DCT (Discrete Cosine Transform). * * This implementation should be more accurate than either of the integer * DCT implementations. However, it may not give the same results on all * machines because of differences in roundoff behavior. Speed will depend * on the hardware's floating point capacity. * * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT * on each column. Direct algorithms are also available, but they are * much more complex and seem not to be any faster when reduced to code. * * This implementation is based on Arai, Agui, and Nakajima's algorithm for * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in * Japanese, but the algorithm is described in the Pennebaker & Mitchell * JPEG textbook (see REFERENCES section in file README). The following code * is based directly on figure 4-8 in P&M. * While an 8-point DCT cannot be done in less than 11 multiplies, it is * possible to arrange the computation so that many of the multiplies are * simple scalings of the final outputs. These multiplies can then be * folded into the multiplications or divisions by the JPEG quantization * table entries. The AA&N method leaves only 5 multiplies and 29 adds * to be done in the DCT itself. * The primary disadvantage of this method is that with a fixed-point * implementation, accuracy is lost due to imprecise representation of the * scaled quantization values. However, that problem does not arise if * we use floating point arithmetic. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_FLOAT_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ #endif /* * Perform the forward DCT on one block of samples. * * cK represents cos(K*pi/16). */ GLOBAL(void) jpeg_fdct_float (FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col) { FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FAST_FLOAT tmp10, tmp11, tmp12, tmp13; FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; FAST_FLOAT *dataptr; JSAMPROW elemptr; int ctr; /* Pass 1: process rows. */ dataptr = data; for (ctr = 0; ctr < DCTSIZE; ctr++) { elemptr = sample_data[ctr] + start_col; /* Load data into workspace */ tmp0 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7])); tmp7 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7])); tmp1 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6])); tmp6 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6])); tmp2 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5])); tmp5 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5])); tmp3 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4])); tmp4 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4])); /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; /* Apply unsigned->signed conversion. */ dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ dataptr[4] = tmp10 - tmp11; z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ dataptr[2] = tmp13 + z1; /* phase 5 */ dataptr[6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[5] = z13 + z2; /* phase 6 */ dataptr[3] = z13 - z2; dataptr[1] = z11 + z4; dataptr[7] = z11 - z4; dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ dataptr[DCTSIZE*4] = tmp10 - tmp11; z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ dataptr[DCTSIZE*6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ dataptr[DCTSIZE*3] = z13 - z2; dataptr[DCTSIZE*1] = z11 + z4; dataptr[DCTSIZE*7] = z11 - z4; dataptr++; /* advance pointer to next column */ } } #endif /* DCT_FLOAT_SUPPORTED */ fltk-1.4.3/jpeg/jcprepct.c0000644000175000017500000002771115004135251015520 0ustar albrechtalbrecht/* * jcprepct.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2003-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the compression preprocessing controller. * This controller manages the color conversion, downsampling, * and edge expansion steps. * * Most of the complexity here is associated with buffering input rows * as required by the downsampler. See the comments at the head of * jcsample.c for the downsampler's needs. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* At present, jcsample.c can request context rows only for smoothing. * In the future, we might also need context rows for CCIR601 sampling * or other more-complex downsampling procedures. The code to support * context rows should be compiled only if needed. */ #ifdef INPUT_SMOOTHING_SUPPORTED #define CONTEXT_ROWS_SUPPORTED #endif /* * For the simple (no-context-row) case, we just need to buffer one * row group's worth of pixels for the downsampling step. At the bottom of * the image, we pad to a full row group by replicating the last pixel row. * The downsampler's last output row is then replicated if needed to pad * out to a full iMCU row. * * When providing context rows, we must buffer three row groups' worth of * pixels. Three row groups are physically allocated, but the row pointer * arrays are made five row groups high, with the extra pointers above and * below "wrapping around" to point to the last and first real row groups. * This allows the downsampler to access the proper context rows. * At the top and bottom of the image, we create dummy context rows by * copying the first or last real pixel row. This copying could be avoided * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the * trouble on the compression side. */ /* Private buffer controller object */ typedef struct { struct jpeg_c_prep_controller pub; /* public fields */ /* Downsampling input buffer. This buffer holds color-converted data * until we have enough to do a downsample step. */ JSAMPARRAY color_buf[MAX_COMPONENTS]; JDIMENSION rows_to_go; /* counts rows remaining in source image */ int next_buf_row; /* index of next row to store in color_buf */ #ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ int this_row_group; /* starting row index of group to process */ int next_buf_stop; /* downsample when we reach this index */ #endif } my_prep_controller; typedef my_prep_controller * my_prep_ptr; /* * Initialize for a processing pass. */ METHODDEF(void) start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; if (pass_mode != JBUF_PASS_THRU) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); /* Initialize total-height counter for detecting bottom of image */ prep->rows_to_go = cinfo->image_height; /* Mark the conversion buffer empty */ prep->next_buf_row = 0; #ifdef CONTEXT_ROWS_SUPPORTED /* Preset additional state variables for context mode. * These aren't used in non-context mode, so we needn't test which mode. */ prep->this_row_group = 0; /* Set next_buf_stop to stop after two row groups have been read in. */ prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; #endif } /* * Expand an image vertically from height input_rows to height output_rows, * by duplicating the bottom row. */ LOCAL(void) expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows, int output_rows) { register int row; for (row = input_rows; row < output_rows; row++) { jcopy_sample_rows(image_data + input_rows - 1, image_data + row, 1, num_cols); } } /* * Process some data in the simple no-context case. * * Preprocessor output data is counted in "row groups". A row group * is defined to be v_samp_factor sample rows of each component. * Downsampling will produce this much data from each max_v_samp_factor * input rows. */ METHODDEF(void) pre_process_data (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; int numrows, ci; JDIMENSION inrows; jpeg_component_info * compptr; while (*in_row_ctr < in_rows_avail && *out_row_group_ctr < out_row_groups_avail) { /* Do color conversion to fill the conversion buffer. */ inrows = in_rows_avail - *in_row_ctr; numrows = cinfo->max_v_samp_factor - prep->next_buf_row; numrows = (int) MIN((JDIMENSION) numrows, inrows); (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, prep->color_buf, (JDIMENSION) prep->next_buf_row, numrows); *in_row_ctr += numrows; prep->next_buf_row += numrows; prep->rows_to_go -= numrows; /* If at bottom of image, pad to fill the conversion buffer. */ if (prep->rows_to_go == 0 && prep->next_buf_row < cinfo->max_v_samp_factor) { for (ci = 0; ci < cinfo->num_components; ci++) { expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, prep->next_buf_row, cinfo->max_v_samp_factor); } prep->next_buf_row = cinfo->max_v_samp_factor; } /* If we've filled the conversion buffer, empty it. */ if (prep->next_buf_row == cinfo->max_v_samp_factor) { (*cinfo->downsample->downsample) (cinfo, prep->color_buf, (JDIMENSION) 0, output_buf, *out_row_group_ctr); prep->next_buf_row = 0; (*out_row_group_ctr)++; } /* If at bottom of image, pad the output to a full iMCU height. * Note we assume the caller is providing a one-iMCU-height output buffer! */ if (prep->rows_to_go == 0 && *out_row_group_ctr < out_row_groups_avail) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { numrows = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / cinfo->min_DCT_v_scaled_size; expand_bottom_edge(output_buf[ci], compptr->width_in_blocks * compptr->DCT_h_scaled_size, (int) (*out_row_group_ctr * numrows), (int) (out_row_groups_avail * numrows)); } *out_row_group_ctr = out_row_groups_avail; break; /* can exit outer loop without test */ } } } #ifdef CONTEXT_ROWS_SUPPORTED /* * Process some data in the context case. */ METHODDEF(void) pre_process_context (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; int numrows, ci; int buf_height = cinfo->max_v_samp_factor * 3; JDIMENSION inrows; while (*out_row_group_ctr < out_row_groups_avail) { if (*in_row_ctr < in_rows_avail) { /* Do color conversion to fill the conversion buffer. */ inrows = in_rows_avail - *in_row_ctr; numrows = prep->next_buf_stop - prep->next_buf_row; numrows = (int) MIN((JDIMENSION) numrows, inrows); (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, prep->color_buf, (JDIMENSION) prep->next_buf_row, numrows); /* Pad at top of image, if first time through */ if (prep->rows_to_go == cinfo->image_height) { for (ci = 0; ci < cinfo->num_components; ci++) { int row; for (row = 1; row <= cinfo->max_v_samp_factor; row++) { jcopy_sample_rows(prep->color_buf[ci], prep->color_buf[ci] - row, 1, cinfo->image_width); } } } *in_row_ctr += numrows; prep->next_buf_row += numrows; prep->rows_to_go -= numrows; } else { /* Return for more data, unless we are at the bottom of the image. */ if (prep->rows_to_go != 0) break; /* When at bottom of image, pad to fill the conversion buffer. */ if (prep->next_buf_row < prep->next_buf_stop) { for (ci = 0; ci < cinfo->num_components; ci++) { expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, prep->next_buf_row, prep->next_buf_stop); } prep->next_buf_row = prep->next_buf_stop; } } /* If we've gotten enough data, downsample a row group. */ if (prep->next_buf_row == prep->next_buf_stop) { (*cinfo->downsample->downsample) (cinfo, prep->color_buf, (JDIMENSION) prep->this_row_group, output_buf, *out_row_group_ctr); (*out_row_group_ctr)++; /* Advance pointers with wraparound as necessary. */ prep->this_row_group += cinfo->max_v_samp_factor; if (prep->this_row_group >= buf_height) prep->this_row_group = 0; if (prep->next_buf_row >= buf_height) prep->next_buf_row = 0; prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; } } } /* * Create the wrapped-around downsampling input buffer needed for context mode. */ LOCAL(void) create_context_buffer (j_compress_ptr cinfo) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; int rgroup_height = cinfo->max_v_samp_factor; int ci, i; jpeg_component_info * compptr; JSAMPARRAY true_buffer, fake_buffer; /* Grab enough space for fake row pointers for all the components; * we need five row groups' worth of pointers for each component. */ fake_buffer = (JSAMPARRAY) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (cinfo->num_components * 5 * rgroup_height) * SIZEOF(JSAMPROW)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Allocate the actual buffer space (3 row groups) for this component. * We make the buffer wide enough to allow the downsampler to edge-expand * horizontally within the buffer, if it so chooses. */ true_buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) (((long) compptr->width_in_blocks * cinfo->min_DCT_h_scaled_size * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION) (3 * rgroup_height)); /* Copy true buffer row pointers into the middle of the fake row array */ MEMCOPY(fake_buffer + rgroup_height, true_buffer, 3 * rgroup_height * SIZEOF(JSAMPROW)); /* Fill in the above and below wraparound pointers */ for (i = 0; i < rgroup_height; i++) { fake_buffer[i] = true_buffer[2 * rgroup_height + i]; fake_buffer[4 * rgroup_height + i] = true_buffer[i]; } prep->color_buf[ci] = fake_buffer + rgroup_height; fake_buffer += 5 * rgroup_height; /* point to space for next component */ } } #endif /* CONTEXT_ROWS_SUPPORTED */ /* * Initialize preprocessing controller. */ GLOBAL(void) jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_prep_ptr prep; int ci; jpeg_component_info * compptr; if (need_full_buffer) /* safety check */ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); prep = (my_prep_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_prep_controller)); cinfo->prep = &prep->pub; prep->pub.start_pass = start_pass_prep; /* Allocate the color conversion buffer. * We make the buffer wide enough to allow the downsampler to edge-expand * horizontally within the buffer, if it so chooses. */ if (cinfo->downsample->need_context_rows) { /* Set up to provide context rows */ #ifdef CONTEXT_ROWS_SUPPORTED prep->pub.pre_process_data = pre_process_context; create_context_buffer(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { /* No context, just make it tall enough for one row group */ prep->pub.pre_process_data = pre_process_data; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) (((long) compptr->width_in_blocks * cinfo->min_DCT_h_scaled_size * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION) cinfo->max_v_samp_factor); } } } fltk-1.4.3/jpeg/jfdctfst.c0000644000175000017500000001752515004135251015517 0ustar albrechtalbrecht/* * jfdctfst.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2003-2017 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a fast, not so accurate integer implementation of the * forward DCT (Discrete Cosine Transform). * * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT * on each column. Direct algorithms are also available, but they are * much more complex and seem not to be any faster when reduced to code. * * This implementation is based on Arai, Agui, and Nakajima's algorithm for * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in * Japanese, but the algorithm is described in the Pennebaker & Mitchell * JPEG textbook (see REFERENCES section in file README). The following code * is based directly on figure 4-8 in P&M. * While an 8-point DCT cannot be done in less than 11 multiplies, it is * possible to arrange the computation so that many of the multiplies are * simple scalings of the final outputs. These multiplies can then be * folded into the multiplications or divisions by the JPEG quantization * table entries. The AA&N method leaves only 5 multiplies and 29 adds * to be done in the DCT itself. * The primary disadvantage of this method is that with fixed-point math, * accuracy is lost due to imprecise representation of the scaled * quantization values. The smaller the quantization table entry, the less * precise the scaled value, so this implementation does worse with high- * quality-setting files than with low-quality ones. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_IFAST_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ #endif /* Scaling decisions are generally the same as in the LL&M algorithm; * see jfdctint.c for more details. However, we choose to descale * (right shift) multiplication products as soon as they are formed, * rather than carrying additional fractional bits into subsequent additions. * This compromises accuracy slightly, but it lets us save a few shifts. * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) * everywhere except in the multiplications proper; this saves a good deal * of work on 16-bit-int machines. * * Again to save a few shifts, the intermediate results between pass 1 and * pass 2 are not upscaled, but are represented only to integral precision. * * A final compromise is to represent the multiplicative constants to only * 8 fractional bits, rather than 13. This saves some shifting work on some * machines, and may also reduce the cost of multiplication (since there * are fewer one-bits in the constants). */ #define CONST_BITS 8 /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 8 #define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */ #define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */ #define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */ #define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */ #else #define FIX_0_382683433 FIX(0.382683433) #define FIX_0_541196100 FIX(0.541196100) #define FIX_0_707106781 FIX(0.707106781) #define FIX_1_306562965 FIX(1.306562965) #endif /* We can gain a little more speed, with a further compromise in accuracy, * by omitting the addition in a descaling shift. This yields an incorrectly * rounded result half the time... */ #ifndef USE_ACCURATE_ROUNDING #undef DESCALE #define DESCALE(x,n) RIGHT_SHIFT(x, n) #endif /* Multiply a DCTELEM variable by an INT32 constant, and immediately * descale to yield a DCTELEM result. */ #define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) /* * Perform the forward DCT on one block of samples. * * cK represents cos(K*pi/16). */ GLOBAL(void) jpeg_fdct_ifast (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; DCTELEM z1, z2, z3, z4, z5, z11, z13; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. */ dataptr = data; for (ctr = 0; ctr < DCTSIZE; ctr++) { elemptr = sample_data[ctr] + start_col; /* Load data into workspace */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); tmp7 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); tmp6 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); tmp5 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); tmp4 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; /* Apply unsigned->signed conversion. */ dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ dataptr[4] = tmp10 - tmp11; z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ dataptr[2] = tmp13 + z1; /* phase 5 */ dataptr[6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[5] = z13 + z2; /* phase 6 */ dataptr[3] = z13 - z2; dataptr[1] = z11 + z4; dataptr[7] = z11 - z4; dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ dataptr[DCTSIZE*4] = tmp10 - tmp11; z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ dataptr[DCTSIZE*6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ dataptr[DCTSIZE*3] = z13 - z2; dataptr[DCTSIZE*1] = z11 + z4; dataptr[DCTSIZE*7] = z11 - z4; dataptr++; /* advance pointer to next column */ } } #endif /* DCT_IFAST_SUPPORTED */ fltk-1.4.3/jpeg/jconfig.txt0000644000175000017500000001327515004135251015722 0ustar albrechtalbrecht/* * jconfig.txt * * Copyright (C) 1991-1994, Thomas G. Lane. * Modified 2009-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file documents the configuration options that are required to * customize the JPEG software for a particular system. * * The actual configuration options for a particular installation are stored * in jconfig.h. On many machines, jconfig.h can be generated automatically * or copied from one of the "canned" jconfig files that we supply. But if * you need to generate a jconfig.h file by hand, this file tells you how. * * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. * EDIT A COPY NAMED JCONFIG.H. */ /* * These symbols indicate the properties of your machine or compiler. * #define the symbol if yes, #undef it if no. */ /* Does your compiler support function prototypes? * (If not, you also need to use ansi2knr, see install.txt) */ #define HAVE_PROTOTYPES /* Does your compiler support the declaration "unsigned char" ? * How about "unsigned short" ? */ #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* Define "void" as "char" if your compiler doesn't know about type void. * NOTE: be sure to define void such that "void *" represents the most general * pointer type, e.g., that returned by malloc(). */ /* #define void char */ /* Define "const" as empty if your compiler doesn't know the "const" keyword. */ /* #define const */ /* Define this if an ordinary "char" type is unsigned. * If you're not sure, leaving it undefined will work at some cost in speed. * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. */ #undef CHAR_IS_UNSIGNED /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDDEF_H /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDLIB_H /* Define this if your system does not have an ANSI/SysV , * but does have a BSD-style . */ #undef NEED_BSD_STRINGS /* Define this if your system does not provide typedef size_t in any of the * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in * instead. */ #undef NEED_SYS_TYPES_H /* For 80x86 machines, you need to define NEED_FAR_POINTERS, * unless you are using a large-data memory model or 80386 flat-memory mode. * On less brain-damaged CPUs this symbol must not be defined. * (Defining this symbol causes large data structures to be referenced through * "far" pointers and to be allocated with a special version of malloc.) */ #undef NEED_FAR_POINTERS /* Define this if your linker needs global names to be unique in less * than the first 15 characters. */ #undef NEED_SHORT_EXTERNAL_NAMES /* Although a real ANSI C compiler can deal perfectly well with pointers to * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you * actually get "missing structure definition" warnings or errors while * compiling the JPEG code. */ #undef INCOMPLETE_TYPES_BROKEN /* Define "boolean" as unsigned char, not enum, on Windows systems. */ #ifdef _WIN32 #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ typedef unsigned char boolean; #endif #ifndef FALSE /* in case these macros already exist */ #define FALSE 0 /* values of boolean */ #endif #ifndef TRUE #define TRUE 1 #endif #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ #endif /* * The following options affect code selection within the JPEG library, * but they don't need to be visible to applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS has been defined. */ #ifdef JPEG_INTERNALS /* Define this if your compiler implements ">>" on signed values as a logical * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, * which is the normal and rational definition. */ #undef RIGHT_SHIFT_IS_UNSIGNED #endif /* JPEG_INTERNALS */ /* * The remaining options do not affect the JPEG library proper, * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). * Other applications can ignore these. */ #ifdef JPEG_CJPEG_DJPEG /* These defines indicate which image (non-JPEG) file formats are allowed. */ #define BMP_SUPPORTED /* BMP image file format */ #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ /* Define this if you want to name both input and output files on the command * line, rather than using stdout and optionally stdin. You MUST do this if * your system can't cope with binary I/O to stdin/stdout. See comments at * head of cjpeg.c or djpeg.c. */ #undef TWO_FILE_COMMANDLINE /* Define this if your system needs explicit cleanup of temporary files. * This is crucial under MS-DOS, where the temporary "files" may be areas * of extended memory; on most other systems it's not as important. */ #undef NEED_SIGNAL_CATCHER /* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). * This is necessary on systems that distinguish text files from binary files, * and is harmless on most systems that don't. If you have one of the rare * systems that complains about the "b" spec, define this symbol. */ #undef DONT_USE_B_MODE /* Define this if you want percent-done progress reports from cjpeg/djpeg. */ #undef PROGRESS_REPORT #endif /* JPEG_CJPEG_DJPEG */ fltk-1.4.3/jpeg/jidctfst.c0000644000175000017500000003065615004135251015522 0ustar albrechtalbrecht/* * jidctfst.c * * Copyright (C) 1994-1998, Thomas G. Lane. * Modified 2015-2017 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a fast, not so accurate integer implementation of the * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine * must also perform dequantization of the input coefficients. * * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT * on each row (or vice versa, but it's more convenient to emit a row at * a time). Direct algorithms are also available, but they are much more * complex and seem not to be any faster when reduced to code. * * This implementation is based on Arai, Agui, and Nakajima's algorithm for * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in * Japanese, but the algorithm is described in the Pennebaker & Mitchell * JPEG textbook (see REFERENCES section in file README). The following code * is based directly on figure 4-8 in P&M. * While an 8-point DCT cannot be done in less than 11 multiplies, it is * possible to arrange the computation so that many of the multiplies are * simple scalings of the final outputs. These multiplies can then be * folded into the multiplications or divisions by the JPEG quantization * table entries. The AA&N method leaves only 5 multiplies and 29 adds * to be done in the DCT itself. * The primary disadvantage of this method is that with fixed-point math, * accuracy is lost due to imprecise representation of the scaled * quantization values. The smaller the quantization table entry, the less * precise the scaled value, so this implementation does worse with high- * quality-setting files than with low-quality ones. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef DCT_IFAST_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ #endif /* Scaling decisions are generally the same as in the LL&M algorithm; * see jidctint.c for more details. However, we choose to descale * (right shift) multiplication products as soon as they are formed, * rather than carrying additional fractional bits into subsequent additions. * This compromises accuracy slightly, but it lets us save a few shifts. * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) * everywhere except in the multiplications proper; this saves a good deal * of work on 16-bit-int machines. * * The dequantized coefficients are not integers because the AA&N scaling * factors have been incorporated. We represent them scaled up by PASS1_BITS, * so that the first and second IDCT rounds have the same input scaling. * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to * avoid a descaling shift; this compromises accuracy rather drastically * for small quantization table entries, but it saves a lot of shifts. * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, * so we use a much larger scaling factor to preserve accuracy. * * A final compromise is to represent the multiplicative constants to only * 8 fractional bits, rather than 13. This saves some shifting work on some * machines, and may also reduce the cost of multiplication (since there * are fewer one-bits in the constants). */ #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 8 #define PASS1_BITS 2 #else #define CONST_BITS 8 #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 8 #define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */ #define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */ #define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */ #define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */ #else #define FIX_1_082392200 FIX(1.082392200) #define FIX_1_414213562 FIX(1.414213562) #define FIX_1_847759065 FIX(1.847759065) #define FIX_2_613125930 FIX(2.613125930) #endif /* We can gain a little more speed, with a further compromise in accuracy, * by omitting the addition in a descaling shift. This yields an incorrectly * rounded result half the time... */ #ifndef USE_ACCURATE_ROUNDING #undef DESCALE #define DESCALE(x,n) RIGHT_SHIFT(x, n) #endif /* Multiply a DCTELEM variable by an INT32 constant, and immediately * descale to yield a DCTELEM result. */ #define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) /* Dequantize a coefficient by multiplying it by the multiplier-table * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 * multiplication will do. For 12-bit data, the multiplier table is * declared INT32, so a 32-bit multiply will be used. */ #if BITS_IN_JSAMPLE == 8 #define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) #else #define DEQUANTIZE(coef,quantval) \ DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) #endif /* * Perform dequantization and inverse DCT on one block of coefficients. * * cK represents cos(K*pi/16). */ GLOBAL(void) jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; DCTELEM z5, z10, z11, z12, z13; JCOEFPTR inptr; IFAST_MULT_TYPE * quantptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS /* for DESCALE */ ISHIFT_TEMPS /* for IRIGHT_SHIFT */ /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { /* Due to quantization, we will usually find that many of the input * coefficients are zero, especially the AC terms. We can exploit this * by short-circuiting the IDCT calculation for any column in which all * the AC terms are zero. In that case each output is equal to the * DC coefficient (with scale factor as needed). * With typical images and quantization tables, half or more of the * column DCT calculations can be simplified this way. */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; wsptr[DCTSIZE*2] = dcval; wsptr[DCTSIZE*3] = dcval; wsptr[DCTSIZE*4] = dcval; wsptr[DCTSIZE*5] = dcval; wsptr[DCTSIZE*6] = dcval; wsptr[DCTSIZE*7] = dcval; inptr++; /* advance pointers to next column */ quantptr++; wsptr++; continue; } /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); tmp10 = tmp0 + tmp2; /* phase 3 */ tmp11 = tmp0 - tmp2; tmp13 = tmp1 + tmp3; /* phases 5-3 */ tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ tmp0 = tmp10 + tmp13; /* phase 2 */ tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; /* Odd part */ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); z13 = tmp6 + tmp5; /* phase 6 */ z10 = tmp6 - tmp5; z11 = tmp4 + tmp7; z12 = tmp4 - tmp7; tmp7 = z11 + z13; /* phase 5 */ tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ tmp10 = z5 - MULTIPLY(z12, FIX_1_082392200); /* 2*(c2-c6) */ tmp12 = z5 - MULTIPLY(z10, FIX_2_613125930); /* 2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; tmp4 = tmp10 - tmp5; wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); wsptr[DCTSIZE*3] = (int) (tmp3 + tmp4); wsptr[DCTSIZE*4] = (int) (tmp3 - tmp4); inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } /* Pass 2: process rows from work array, store into output array. * Note that we must descale the results by a factor of 8 == 2**3, * and also undo the PASS1_BITS scaling. */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { outptr = output_buf[ctr] + output_col; /* Add range center and fudge factor for final descale and range-limit. */ z5 = (DCTELEM) wsptr[0] + ((((DCTELEM) RANGE_CENTER) << (PASS1_BITS+3)) + (1 << (PASS1_BITS+2))); /* Rows of zeroes can be exploited in the same way as we did with columns. * However, the column calculation has created many nonzero AC terms, so * the simplification applies less often (typically 5% to 10% of the time). * On machines with very fast multiplication, it's possible that the * test takes more time than it's worth. In that case this section * may be commented out. */ #ifndef NO_ZERO_ROW_TEST if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ JSAMPLE dcval = range_limit[(int) IRIGHT_SHIFT(z5, PASS1_BITS+3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; outptr[2] = dcval; outptr[3] = dcval; outptr[4] = dcval; outptr[5] = dcval; outptr[6] = dcval; outptr[7] = dcval; wsptr += DCTSIZE; /* advance pointer to next row */ continue; } #endif /* Even part */ tmp10 = z5 + (DCTELEM) wsptr[4]; tmp11 = z5 - (DCTELEM) wsptr[4]; tmp13 = (DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]; tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) - tmp13; /* 2*c4 */ tmp0 = tmp10 + tmp13; tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; /* Odd part */ z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; tmp7 = z11 + z13; /* phase 5 */ tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ tmp10 = z5 - MULTIPLY(z12, FIX_1_082392200); /* 2*(c2-c6) */ tmp12 = z5 - MULTIPLY(z10, FIX_2_613125930); /* 2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; tmp4 = tmp10 - tmp5; /* Final output stage: scale down by a factor of 8 and range-limit */ outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp7, PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp7, PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp1 + tmp6, PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) IRIGHT_SHIFT(tmp1 - tmp6, PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) IRIGHT_SHIFT(tmp2 + tmp5, PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) IRIGHT_SHIFT(tmp2 - tmp5, PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) IRIGHT_SHIFT(tmp3 + tmp4, PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) IRIGHT_SHIFT(tmp3 - tmp4, PASS1_BITS+3) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } #endif /* DCT_IFAST_SUPPORTED */ fltk-1.4.3/jpeg/jdatadst.c0000644000175000017500000002044115004135251015475 0ustar albrechtalbrecht/* * jdatadst.c * * Copyright (C) 1994-1996, Thomas G. Lane. * Modified 2009-2022 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains compression data destination routines for the case of * emitting JPEG data to memory or to a file (or any stdio stream). * While these routines are sufficient for most applications, * some will want to use a different destination manager. * IMPORTANT: we assume that fwrite() will correctly transcribe an array of * JOCTETs into 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. */ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jerror.h" #ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ extern void * malloc JPP((size_t size)); extern void free JPP((void *ptr)); #endif /* Expanded data destination object for stdio output */ #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ typedef struct { struct jpeg_destination_mgr pub; /* public fields */ FILE * outfile; /* target stream */ JOCTET buffer[OUTPUT_BUF_SIZE]; /* output buffer */ } my_destination_mgr; typedef my_destination_mgr * my_dest_ptr; /* Expanded data destination object for memory output */ typedef struct { struct jpeg_destination_mgr pub; /* public fields */ unsigned char ** outbuffer; /* target buffer */ size_t * outsize; unsigned char * newbuffer; /* newly allocated buffer */ JOCTET * buffer; /* start of buffer */ size_t bufsize; } my_mem_destination_mgr; typedef my_mem_destination_mgr * my_mem_dest_ptr; /* * Initialize destination --- called by jpeg_start_compress * before any data is actually written. */ METHODDEF(void) init_destination (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } METHODDEF(void) init_mem_destination (j_compress_ptr cinfo) { /* no work necessary here */ } /* * Empty the output buffer --- called whenever buffer fills up. * * In typical applications, this should write the entire output buffer * (ignoring the current state of next_output_byte & free_in_buffer), * reset the pointer & count to the start of the buffer, and return TRUE * indicating that the buffer has been dumped. * * In applications that need to be able to suspend compression due to output * overrun, a FALSE return indicates that the buffer cannot be emptied now. * In this situation, the compressor will return to its caller (possibly with * an indication that it has not accepted all the supplied scanlines). The * application should resume compression after it has made more room in the * output buffer. Note that there are substantial restrictions on the use of * suspension --- see the documentation. * * When suspending, the compressor will back up to a convenient restart point * (typically the start of the current MCU). next_output_byte & free_in_buffer * indicate where the restart point will be if the current call returns FALSE. * Data beyond this point will be regenerated after resumption, so do not * write it out when emptying the buffer externally. */ METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != (size_t) OUTPUT_BUF_SIZE) ERREXIT(cinfo, JERR_FILE_WRITE); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; } METHODDEF(boolean) empty_mem_output_buffer (j_compress_ptr cinfo) { size_t nextsize; JOCTET * nextbuffer; my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; /* Try to allocate new buffer with double size */ nextsize = dest->bufsize * 2; nextbuffer = (JOCTET *) malloc(nextsize); if (nextbuffer == NULL) ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 11); MEMCOPY(nextbuffer, dest->buffer, dest->bufsize); if (dest->newbuffer != NULL) free(dest->newbuffer); dest->newbuffer = nextbuffer; dest->pub.next_output_byte = nextbuffer + dest->bufsize; dest->pub.free_in_buffer = dest->bufsize; dest->buffer = nextbuffer; dest->bufsize = nextsize; return TRUE; } /* * Terminate destination --- called by jpeg_finish_compress * after all data has been written. Usually needs to flush buffer. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ METHODDEF(void) term_destination (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; /* Write any data remaining in the buffer */ if (datacount > 0) { if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) ERREXIT(cinfo, JERR_FILE_WRITE); } JFFLUSH(dest->outfile); /* Make sure we wrote the output file OK */ if (JFERROR(dest->outfile)) ERREXIT(cinfo, JERR_FILE_WRITE); } METHODDEF(void) term_mem_destination (j_compress_ptr cinfo) { my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; *dest->outbuffer = dest->buffer; *dest->outsize = dest->bufsize - dest->pub.free_in_buffer; } /* * Prepare for output to a stdio stream. * The caller must have already opened the stream, * and is responsible for closing it after finishing compression. */ GLOBAL(void) jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) { my_dest_ptr dest; /* The destination object is made permanent so that multiple JPEG images * can be written to the same file without re-executing jpeg_stdio_dest. * This makes it dangerous to use this manager and a different destination * manager serially with the same JPEG object, because their private object * sizes may be different. Caveat programmer. */ if (cinfo->dest == NULL) { /* first time for this JPEG object? */ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_destination_mgr)); } dest = (my_dest_ptr) cinfo->dest; dest->pub.init_destination = init_destination; dest->pub.empty_output_buffer = empty_output_buffer; dest->pub.term_destination = term_destination; dest->outfile = outfile; } /* * Prepare for output to a memory buffer. * The caller may supply an own initial buffer with appropriate size. * Otherwise, or when the actual data output exceeds the given size, * the library adapts the buffer size as necessary. * The standard library functions malloc/free are used for allocating * larger memory, so the buffer is available to the application after * finishing compression, and then the application is responsible for * freeing the requested memory. * Note: An initial buffer supplied by the caller is expected to be * managed by the application. The library does not free such buffer * when allocating a larger buffer. */ GLOBAL(void) jpeg_mem_dest (j_compress_ptr cinfo, unsigned char ** outbuffer, size_t * outsize) { my_mem_dest_ptr dest; if (outbuffer == NULL || outsize == NULL) /* sanity check */ ERREXIT(cinfo, JERR_BUFFER_SIZE); /* The destination object is made permanent so that multiple JPEG images * can be written to the same buffer without re-executing jpeg_mem_dest. */ if (cinfo->dest == NULL) { /* first time for this JPEG object? */ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_mem_destination_mgr)); } dest = (my_mem_dest_ptr) cinfo->dest; dest->pub.init_destination = init_mem_destination; dest->pub.empty_output_buffer = empty_mem_output_buffer; dest->pub.term_destination = term_mem_destination; dest->outbuffer = outbuffer; dest->outsize = outsize; dest->newbuffer = NULL; if (*outbuffer == NULL || *outsize == 0) { /* Allocate initial buffer */ dest->newbuffer = *outbuffer = (unsigned char *) malloc(OUTPUT_BUF_SIZE); if (dest->newbuffer == NULL) ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); *outsize = OUTPUT_BUF_SIZE; } dest->pub.next_output_byte = dest->buffer = *outbuffer; dest->pub.free_in_buffer = dest->bufsize = *outsize; } fltk-1.4.3/jpeg/jcinit.c0000644000175000017500000002464715004135251015173 0ustar albrechtalbrecht/* * jcinit.c * * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2003-2017 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains initialization logic for the JPEG compressor. * This routine is in charge of selecting the modules to be executed and * making an initialization call to each one. * * Logically, this code belongs in jcmaster.c. It's split out because * linking this routine implies linking the entire compression library. * For a transcoding-only application, we want to be able to use jcmaster.c * without linking in the whole library. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Compute JPEG image dimensions and related values. * NOTE: this is exported for possible use by application. * Hence it mustn't do anything that can't be done twice. */ GLOBAL(void) jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo) /* Do computations that are needed before master selection phase */ { /* Sanity check on input image dimensions to prevent overflow in * following calculations. * We do check jpeg_width and jpeg_height in initial_setup in jcmaster.c, * but image_width and image_height can come from arbitrary data, * and we need some space for multiplication by block_size. */ if (((long) cinfo->image_width >> 24) || ((long) cinfo->image_height >> 24)) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); #ifdef DCT_SCALING_SUPPORTED /* Compute actual JPEG image dimensions and DCT scaling choices. */ if (cinfo->scale_num >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/1 scaling */ cinfo->jpeg_width = cinfo->image_width * cinfo->block_size; cinfo->jpeg_height = cinfo->image_height * cinfo->block_size; cinfo->min_DCT_h_scaled_size = 1; cinfo->min_DCT_v_scaled_size = 1; } else if (cinfo->scale_num * 2 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/2 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 2L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 2L); cinfo->min_DCT_h_scaled_size = 2; cinfo->min_DCT_v_scaled_size = 2; } else if (cinfo->scale_num * 3 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/3 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 3L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 3L); cinfo->min_DCT_h_scaled_size = 3; cinfo->min_DCT_v_scaled_size = 3; } else if (cinfo->scale_num * 4 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/4 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 4L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 4L); cinfo->min_DCT_h_scaled_size = 4; cinfo->min_DCT_v_scaled_size = 4; } else if (cinfo->scale_num * 5 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/5 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 5L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 5L); cinfo->min_DCT_h_scaled_size = 5; cinfo->min_DCT_v_scaled_size = 5; } else if (cinfo->scale_num * 6 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/6 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 6L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 6L); cinfo->min_DCT_h_scaled_size = 6; cinfo->min_DCT_v_scaled_size = 6; } else if (cinfo->scale_num * 7 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/7 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 7L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 7L); cinfo->min_DCT_h_scaled_size = 7; cinfo->min_DCT_v_scaled_size = 7; } else if (cinfo->scale_num * 8 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/8 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 8L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 8L); cinfo->min_DCT_h_scaled_size = 8; cinfo->min_DCT_v_scaled_size = 8; } else if (cinfo->scale_num * 9 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/9 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 9L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 9L); cinfo->min_DCT_h_scaled_size = 9; cinfo->min_DCT_v_scaled_size = 9; } else if (cinfo->scale_num * 10 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/10 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 10L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 10L); cinfo->min_DCT_h_scaled_size = 10; cinfo->min_DCT_v_scaled_size = 10; } else if (cinfo->scale_num * 11 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/11 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 11L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 11L); cinfo->min_DCT_h_scaled_size = 11; cinfo->min_DCT_v_scaled_size = 11; } else if (cinfo->scale_num * 12 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/12 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 12L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 12L); cinfo->min_DCT_h_scaled_size = 12; cinfo->min_DCT_v_scaled_size = 12; } else if (cinfo->scale_num * 13 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/13 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 13L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 13L); cinfo->min_DCT_h_scaled_size = 13; cinfo->min_DCT_v_scaled_size = 13; } else if (cinfo->scale_num * 14 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/14 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 14L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 14L); cinfo->min_DCT_h_scaled_size = 14; cinfo->min_DCT_v_scaled_size = 14; } else if (cinfo->scale_num * 15 >= cinfo->scale_denom * cinfo->block_size) { /* Provide block_size/15 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 15L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 15L); cinfo->min_DCT_h_scaled_size = 15; cinfo->min_DCT_v_scaled_size = 15; } else { /* Provide block_size/16 scaling */ cinfo->jpeg_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 16L); cinfo->jpeg_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 16L); cinfo->min_DCT_h_scaled_size = 16; cinfo->min_DCT_v_scaled_size = 16; } #else /* !DCT_SCALING_SUPPORTED */ /* Hardwire it to "no scaling" */ cinfo->jpeg_width = cinfo->image_width; cinfo->jpeg_height = cinfo->image_height; cinfo->min_DCT_h_scaled_size = DCTSIZE; cinfo->min_DCT_v_scaled_size = DCTSIZE; #endif /* DCT_SCALING_SUPPORTED */ } /* * Master selection of compression modules. * This is done once at the start of processing an image. We determine * which modules will be used and give them appropriate initialization calls. */ GLOBAL(void) jinit_compress_master (j_compress_ptr cinfo) { long samplesperrow; JDIMENSION jd_samplesperrow; /* For now, precision must match compiled-in value... */ if (cinfo->data_precision != BITS_IN_JSAMPLE) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Sanity check on input image dimensions */ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || cinfo->input_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); /* Width of an input scanline must be representable as JDIMENSION. */ samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; jd_samplesperrow = (JDIMENSION) samplesperrow; if ((long) jd_samplesperrow != samplesperrow) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); /* Compute JPEG image dimensions and related values. */ jpeg_calc_jpeg_dimensions(cinfo); /* Initialize master control (includes parameter checking/processing) */ jinit_c_master_control(cinfo, FALSE /* full compression */); /* Preprocessing */ if (! cinfo->raw_data_in) { jinit_color_converter(cinfo); jinit_downsampler(cinfo); jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); } /* Forward DCT */ jinit_forward_dct(cinfo); /* Entropy encoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) jinit_arith_encoder(cinfo); else { jinit_huff_encoder(cinfo); } /* Need a full-image coefficient buffer in any multi-pass mode. */ jinit_c_coef_controller(cinfo, (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); jinit_marker_writer(cinfo); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); /* Write the datastream header (SOI) immediately. * Frame and scan headers are postponed till later. * This lets application insert special markers after the SOI. */ (*cinfo->marker->write_file_header) (cinfo); } fltk-1.4.3/jpeg/jdhuff.c0000644000175000017500000013717715004135251015164 0ustar albrechtalbrecht/* * jdhuff.c * * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2006-2020 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy decoding routines. * Both sequential and progressive modes are supported in this single module. * * Much of the complexity here has to do with supporting input suspension. * If the data source module demands suspension, we want to be able to back * up to the start of the current MCU. To do this, we copy state variables * into local working storage, and update them back to the permanent * storage only upon successful completion of an MCU. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Derived data constructed for each Huffman table */ #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ typedef struct { /* Basic tables: (element [0] of each array is unused) */ INT32 maxcode[18]; /* largest code of length k (-1 if none) */ /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ INT32 valoffset[17]; /* huffval[] offset for codes of length k */ /* valoffset[k] = huffval[] index of 1st symbol of code length k, less * the smallest code of length k; so given a code of length k, the * corresponding symbol is huffval[code + valoffset[k]] */ /* Link to public Huffman table (needed only in jpeg_huff_decode) */ JHUFF_TBL *pub; /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of * the input data stream. If the next Huffman code is no more * than HUFF_LOOKAHEAD bits long, we can obtain its length and * the corresponding symbol directly from these tables. */ int look_nbits[1< 32 bits on your machine, and shifting/masking longs is * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE * appropriately should be a win. Unfortunately we can't define the size * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) * because not all machines measure sizeof in 8-bit bytes. */ typedef struct { /* Bitreading state saved across MCUs */ bit_buf_type get_buffer; /* current bit-extraction buffer */ int bits_left; /* # of unused bits in it */ } bitread_perm_state; typedef struct { /* Bitreading working state within an MCU */ /* Current data source location */ /* We need a copy, rather than munging the original, in case of suspension */ const JOCTET * next_input_byte; /* => next byte to read from source */ size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ /* Bit input buffer --- note these values are kept in register variables, * not in this struct, inside the inner loops. */ bit_buf_type get_buffer; /* current bit-extraction buffer */ int bits_left; /* # of unused bits in it */ /* Pointer needed by jpeg_fill_bit_buffer. */ j_decompress_ptr cinfo; /* back link to decompress master record */ } bitread_working_state; /* Macros to declare and load/save bitread local variables. */ #define BITREAD_STATE_VARS \ register bit_buf_type get_buffer; \ register int bits_left; \ bitread_working_state br_state #define BITREAD_LOAD_STATE(cinfop,permstate) \ br_state.cinfo = cinfop; \ br_state.next_input_byte = cinfop->src->next_input_byte; \ br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ get_buffer = permstate.get_buffer; \ bits_left = permstate.bits_left; #define BITREAD_SAVE_STATE(cinfop,permstate) \ cinfop->src->next_input_byte = br_state.next_input_byte; \ cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ permstate.get_buffer = get_buffer; \ permstate.bits_left = bits_left /* * These macros provide the in-line portion of bit fetching. * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer * before using GET_BITS, PEEK_BITS, or DROP_BITS. * The variables get_buffer and bits_left are assumed to be locals, * but the state struct might not be (jpeg_huff_decode needs this). * CHECK_BIT_BUFFER(state,n,action); * Ensure there are N bits in get_buffer; if suspend, take action. * val = GET_BITS(n); * Fetch next N bits. * val = PEEK_BITS(n); * Fetch next N bits without removing them from the buffer. * DROP_BITS(n); * Discard next N bits. * The value N should be a simple variable, not an expression, because it * is evaluated multiple times. */ #define CHECK_BIT_BUFFER(state,nbits,action) \ { if (bits_left < (nbits)) { \ if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ { action; } \ get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } #define GET_BITS(nbits) \ (((int) (get_buffer >> (bits_left -= (nbits)))) & BIT_MASK(nbits)) #define PEEK_BITS(nbits) \ (((int) (get_buffer >> (bits_left - (nbits)))) & BIT_MASK(nbits)) #define DROP_BITS(nbits) \ (bits_left -= (nbits)) /* * Code for extracting next Huffman-coded symbol from input bit stream. * Again, this is time-critical and we make the main paths be macros. * * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits * without looping. Usually, more than 95% of the Huffman codes will be 8 * or fewer bits long. The few overlength codes are handled with a loop, * which need not be inline code. * * Notes about the HUFF_DECODE macro: * 1. Near the end of the data segment, we may fail to get enough bits * for a lookahead. In that case, we do it the hard way. * 2. If the lookahead table contains no entry, the next code must be * more than HUFF_LOOKAHEAD bits long. * 3. jpeg_huff_decode returns -1 if forced to suspend. */ #define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ { register int nb, look; \ if (bits_left < HUFF_LOOKAHEAD) { \ if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ get_buffer = state.get_buffer; bits_left = state.bits_left; \ if (bits_left < HUFF_LOOKAHEAD) { \ nb = 1; goto slowlabel; \ } \ } \ look = PEEK_BITS(HUFF_LOOKAHEAD); \ if ((nb = htbl->look_nbits[look]) != 0) { \ DROP_BITS(nb); \ result = htbl->look_sym[look]; \ } else { \ nb = HUFF_LOOKAHEAD+1; \ slowlabel: \ if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ { failaction; } \ get_buffer = state.get_buffer; bits_left = state.bits_left; \ } \ } /* * Expanded entropy decoder object for Huffman decoding. * * The savable_state subrecord contains fields that change within an MCU, * but must not be updated permanently until we complete the MCU. */ typedef struct { unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state; /* This macro is to work around compilers with missing or broken * structure assignment. You'll need to fix this code if you have * such a compiler and you change MAX_COMPS_IN_SCAN. */ #ifndef NO_STRUCT_ASSIGN #define ASSIGN_STATE(dest,src) ((dest) = (src)) #else #if MAX_COMPS_IN_SCAN == 4 #define ASSIGN_STATE(dest,src) \ ((dest).EOBRUN = (src).EOBRUN, \ (dest).last_dc_val[0] = (src).last_dc_val[0], \ (dest).last_dc_val[1] = (src).last_dc_val[1], \ (dest).last_dc_val[2] = (src).last_dc_val[2], \ (dest).last_dc_val[3] = (src).last_dc_val[3]) #endif #endif typedef struct { struct jpeg_entropy_decoder pub; /* public fields */ /* These fields are loaded into local variables at start of each MCU. * In case of suspension, we exit WITHOUT updating them. */ bitread_perm_state bitstate; /* Bit buffer at start of MCU */ savable_state saved; /* Other state at start of MCU */ /* These fields are NOT loaded into local working state. */ boolean insufficient_data; /* set TRUE after emitting warning */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ /* Following two fields used only in progressive mode */ /* Pointers to derived tables (these workspaces have image lifespan) */ d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ /* Following fields used only in sequential mode */ /* Pointers to derived tables (these workspaces have image lifespan) */ d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; /* Precalculated info set up by start_pass for use in decode_mcu: */ /* Pointers to derived tables to be used for each block within an MCU */ d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; /* Whether we care about the DC and AC coefficient values for each block */ int coef_limit[D_MAX_BLOCKS_IN_MCU]; } huff_entropy_decoder; typedef huff_entropy_decoder * huff_entropy_ptr; static const int jpeg_zigzag_order[8][8] = { { 0, 1, 5, 6, 14, 15, 27, 28 }, { 2, 4, 7, 13, 16, 26, 29, 42 }, { 3, 8, 12, 17, 25, 30, 41, 43 }, { 9, 11, 18, 24, 31, 40, 44, 53 }, { 10, 19, 23, 32, 39, 45, 52, 54 }, { 20, 22, 33, 38, 46, 51, 55, 60 }, { 21, 34, 37, 47, 50, 56, 59, 61 }, { 35, 36, 48, 49, 57, 58, 62, 63 } }; static const int jpeg_zigzag_order7[7][7] = { { 0, 1, 5, 6, 14, 15, 27 }, { 2, 4, 7, 13, 16, 26, 28 }, { 3, 8, 12, 17, 25, 29, 38 }, { 9, 11, 18, 24, 30, 37, 39 }, { 10, 19, 23, 31, 36, 40, 45 }, { 20, 22, 32, 35, 41, 44, 46 }, { 21, 33, 34, 42, 43, 47, 48 } }; static const int jpeg_zigzag_order6[6][6] = { { 0, 1, 5, 6, 14, 15 }, { 2, 4, 7, 13, 16, 25 }, { 3, 8, 12, 17, 24, 26 }, { 9, 11, 18, 23, 27, 32 }, { 10, 19, 22, 28, 31, 33 }, { 20, 21, 29, 30, 34, 35 } }; static const int jpeg_zigzag_order5[5][5] = { { 0, 1, 5, 6, 14 }, { 2, 4, 7, 13, 15 }, { 3, 8, 12, 16, 21 }, { 9, 11, 17, 20, 22 }, { 10, 18, 19, 23, 24 } }; static const int jpeg_zigzag_order4[4][4] = { { 0, 1, 5, 6 }, { 2, 4, 7, 12 }, { 3, 8, 11, 13 }, { 9, 10, 14, 15 } }; static const int jpeg_zigzag_order3[3][3] = { { 0, 1, 5 }, { 2, 4, 6 }, { 3, 7, 8 } }; static const int jpeg_zigzag_order2[2][2] = { { 0, 1 }, { 2, 3 } }; /* * Compute the derived values for a Huffman table. * This routine also performs some validation checks on the table. */ LOCAL(void) jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, d_derived_tbl ** pdtbl) { JHUFF_TBL *htbl; d_derived_tbl *dtbl; int p, i, l, si, numsymbols; int lookbits, ctr; char huffsize[257]; unsigned int huffcode[257]; unsigned int code; /* Note that huffsize[] and huffcode[] are filled in code-length order, * paralleling the order of the symbols themselves in htbl->huffval[]. */ /* Find the input Huffman table */ if (tblno < 0 || tblno >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); htbl = isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; if (htbl == NULL) htbl = jpeg_std_huff_table((j_common_ptr) cinfo, isDC, tblno); /* Allocate a workspace if we haven't already done so. */ if (*pdtbl == NULL) *pdtbl = (d_derived_tbl *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(d_derived_tbl)); dtbl = *pdtbl; dtbl->pub = htbl; /* fill in back link */ /* Figure C.1: make table of Huffman code length for each symbol */ p = 0; for (l = 1; l <= 16; l++) { i = (int) htbl->bits[l]; if (i < 0 || p + i > 256) /* protect against table overrun */ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); while (i--) huffsize[p++] = (char) l; } huffsize[p] = 0; numsymbols = p; /* Figure C.2: generate the codes themselves */ /* We also validate that the counts represent a legal Huffman code tree. */ code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while (((int) huffsize[p]) == si) { huffcode[p++] = code; code++; } /* code is now 1 more than the last code used for codelength si; but * it must still fit in si bits, since no code is allowed to be all ones. */ if (((INT32) code) >= (((INT32) 1) << si)) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); code <<= 1; si++; } /* Figure F.15: generate decoding tables for bit-sequential decoding */ p = 0; for (l = 1; l <= 16; l++) { if (htbl->bits[l]) { /* valoffset[l] = huffval[] index of 1st symbol of code length l, * minus the minimum code of length l */ dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; p += htbl->bits[l]; dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ } else { dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ } } dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ /* Compute lookahead tables to speed up decoding. * First we set all the table entries to 0, indicating "too long"; * then we iterate through the Huffman codes that are short enough and * fill in all the entries that correspond to bit sequences starting * with that code. */ MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); p = 0; for (l = 1; l <= HUFF_LOOKAHEAD; l++) { for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { /* l = current code's length, p = its index in huffcode[] & huffval[]. */ /* Generate left-justified code followed by all possible bit sequences */ lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { dtbl->look_nbits[lookbits] = l; dtbl->look_sym[lookbits] = htbl->huffval[p]; lookbits++; } } } /* Validate symbols as being reasonable. * For AC tables, we make no check, but accept all byte values 0..255. * For DC tables, we require the symbols to be in range 0..15. * (Tighter bounds could be applied depending on the data depth and mode, * but this is sufficient to ensure safe decoding.) */ if (isDC) { for (i = 0; i < numsymbols; i++) { int sym = htbl->huffval[i]; if (sym < 0 || sym > 15) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); } } } /* * Out-of-line code for bit fetching. * Note: current values of get_buffer and bits_left are passed as parameters, * but are returned in the corresponding fields of the state struct. * * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width * of get_buffer to be used. (On machines with wider words, an even larger * buffer could be used.) However, on some machines 32-bit shifts are * quite slow and take time proportional to the number of places shifted. * (This is true with most PC compilers, for instance.) In this case it may * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. */ #ifdef SLOW_SHIFT_32 #define MIN_GET_BITS 15 /* minimum allowable value */ #else #define MIN_GET_BITS (BIT_BUF_SIZE-7) #endif LOCAL(boolean) jpeg_fill_bit_buffer (bitread_working_state * state, register bit_buf_type get_buffer, register int bits_left, int nbits) /* Load up the bit buffer to a depth of at least nbits */ { /* Copy heavily used state fields into locals (hopefully registers) */ register const JOCTET * next_input_byte = state->next_input_byte; register size_t bytes_in_buffer = state->bytes_in_buffer; j_decompress_ptr cinfo = state->cinfo; /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ /* (It is assumed that no request will be for more than that many bits.) */ /* We fail to do so only if we hit a marker or are forced to suspend. */ if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ while (bits_left < MIN_GET_BITS) { register int c; /* Attempt to read a byte */ if (bytes_in_buffer == 0) { if (! (*cinfo->src->fill_input_buffer) (cinfo)) return FALSE; next_input_byte = cinfo->src->next_input_byte; bytes_in_buffer = cinfo->src->bytes_in_buffer; } bytes_in_buffer--; c = GETJOCTET(*next_input_byte++); /* If it's 0xFF, check and discard stuffed zero byte */ if (c == 0xFF) { /* Loop here to discard any padding FF's on terminating marker, * so that we can save a valid unread_marker value. NOTE: we will * accept multiple FF's followed by a 0 as meaning a single FF data * byte. This data pattern is not valid according to the standard. */ do { if (bytes_in_buffer == 0) { if (! (*cinfo->src->fill_input_buffer) (cinfo)) return FALSE; next_input_byte = cinfo->src->next_input_byte; bytes_in_buffer = cinfo->src->bytes_in_buffer; } bytes_in_buffer--; c = GETJOCTET(*next_input_byte++); } while (c == 0xFF); if (c == 0) { /* Found FF/00, which represents an FF data byte */ c = 0xFF; } else { /* Oops, it's actually a marker indicating end of compressed data. * Save the marker code for later use. * Fine point: it might appear that we should save the marker into * bitread working state, not straight into permanent state. But * once we have hit a marker, we cannot need to suspend within the * current MCU, because we will read no more bytes from the data * source. So it is OK to update permanent state right away. */ cinfo->unread_marker = c; /* See if we need to insert some fake zero bits. */ goto no_more_bytes; } } /* OK, load c into get_buffer */ get_buffer = (get_buffer << 8) | c; bits_left += 8; } /* end while */ } else { no_more_bytes: /* We get here if we've read the marker that terminates the compressed * data segment. There should be enough bits in the buffer register * to satisfy the request; if so, no problem. */ if (nbits > bits_left) { /* Uh-oh. Report corrupted data to user and stuff zeroes into * the data stream, so that we can produce some kind of image. * We use a nonvolatile flag to ensure that only one warning message * appears per data segment. */ if (! ((huff_entropy_ptr) cinfo->entropy)->insufficient_data) { WARNMS(cinfo, JWRN_HIT_MARKER); ((huff_entropy_ptr) cinfo->entropy)->insufficient_data = TRUE; } /* Fill the buffer with zero bits */ get_buffer <<= MIN_GET_BITS - bits_left; bits_left = MIN_GET_BITS; } } /* Unload the local registers */ state->next_input_byte = next_input_byte; state->bytes_in_buffer = bytes_in_buffer; state->get_buffer = get_buffer; state->bits_left = bits_left; return TRUE; } /* * Figure F.12: extend sign bit. * On some machines, a shift and sub will be faster than a table lookup. */ #ifdef AVOID_TABLES #define BIT_MASK(nbits) ((1<<(nbits))-1) #define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) - ((1<<(s))-1) : (x)) #else #define BIT_MASK(nbits) bmask[nbits] #define HUFF_EXTEND(x,s) ((x) <= bmask[(s) - 1] ? (x) - bmask[s] : (x)) static const int bmask[16] = /* bmask[n] is mask for n rightmost bits */ { 0, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF }; #endif /* AVOID_TABLES */ /* * Out-of-line code for Huffman code decoding. */ LOCAL(int) jpeg_huff_decode (bitread_working_state * state, register bit_buf_type get_buffer, register int bits_left, d_derived_tbl * htbl, int min_bits) { register int l = min_bits; register INT32 code; /* HUFF_DECODE has determined that the code is at least min_bits */ /* bits long, so fetch that many bits in one swoop. */ CHECK_BIT_BUFFER(*state, l, return -1); code = GET_BITS(l); /* Collect the rest of the Huffman code one bit at a time. */ /* This is per Figure F.16 in the JPEG spec. */ while (code > htbl->maxcode[l]) { code <<= 1; CHECK_BIT_BUFFER(*state, 1, return -1); code |= GET_BITS(1); l++; } /* Unload the local registers */ state->get_buffer = get_buffer; state->bits_left = bits_left; /* With garbage input we may reach the sentinel value l = 17. */ if (l > 16) { WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); return 0; /* fake a zero as the safest result */ } return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; } /* * Finish up at the end of a Huffman-compressed scan. */ METHODDEF(void) finish_pass_huff (j_decompress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; /* Throw away any unused bits remaining in bit buffer; */ /* include any full bytes in next_marker's count of discarded bytes */ cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; entropy->bitstate.bits_left = 0; } /* * Check for a restart marker & resynchronize decoder. * Returns FALSE if must suspend. */ LOCAL(boolean) process_restart (j_decompress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci; finish_pass_huff(cinfo); /* Advance past the RSTn marker */ if (! (*cinfo->marker->read_restart_marker) (cinfo)) return FALSE; /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) entropy->saved.last_dc_val[ci] = 0; /* Re-init EOB run count, too */ entropy->saved.EOBRUN = 0; /* Reset restart counter */ entropy->restarts_to_go = cinfo->restart_interval; /* Reset out-of-data flag, unless read_restart_marker left us smack up * against a marker. In that case we will end up treating the next data * segment as empty, and we can avoid producing bogus output pixels by * leaving the flag set. */ if (cinfo->unread_marker == 0) entropy->insufficient_data = FALSE; return TRUE; } /* * Huffman MCU decoding. * Each of these routines decodes and returns one MCU's worth of * Huffman-compressed coefficients. * The coefficients are reordered from zigzag order into natural array order, * but are not dequantized. * * The i'th block of the MCU is stored into the block pointed to by * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. * (Wholesale zeroing is usually a little faster than retail...) * * We return FALSE if data source requested suspension. In that case no * changes have been made to permanent state. (Exception: some output * coefficients may already have been assigned. This is harmless for * spectral selection, since we'll just re-assign them on the next call. * Successive approximation AC refinement has to be more careful, however.) */ /* * MCU decoding for DC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int Al = cinfo->Al; register int s, r; int blkn, ci; JBLOCKROW block; BITREAD_STATE_VARS; savable_state state; d_derived_tbl * tbl; jpeg_component_info * compptr; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* If we've run out of data, just leave the MCU set to zeroes. * This way, we return uniform gray for the remainder of the segment. */ if (! entropy->insufficient_data) { /* Load up working state */ BITREAD_LOAD_STATE(cinfo, entropy->bitstate); ASSIGN_STATE(state, entropy->saved); /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { block = MCU_data[blkn]; ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; tbl = entropy->derived_tbls[compptr->dc_tbl_no]; /* Decode a single block's worth of coefficients */ /* Section F.2.2.1: decode the DC coefficient difference */ HUFF_DECODE(s, br_state, tbl, return FALSE, label1); if (s) { CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); } /* Convert DC difference to actual value, update last_dc_val */ s += state.last_dc_val[ci]; state.last_dc_val[ci] = s; /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ (*block)[0] = (JCOEF) (s << Al); } /* Completed MCU, so update state */ BITREAD_SAVE_STATE(cinfo, entropy->bitstate); ASSIGN_STATE(entropy->saved, state); } /* Account for restart interval if using restarts */ if (cinfo->restart_interval) entropy->restarts_to_go--; return TRUE; } /* * MCU decoding for AC initial scan (either spectral selection, * or first pass of successive approximation). */ METHODDEF(boolean) decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; register int s, k, r; unsigned int EOBRUN; int Se, Al; const int * natural_order; JBLOCKROW block; BITREAD_STATE_VARS; d_derived_tbl * tbl; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* If we've run out of data, just leave the MCU set to zeroes. * This way, we return uniform gray for the remainder of the segment. */ if (! entropy->insufficient_data) { /* Load up working state. * We can avoid loading/saving bitread state if in an EOB run. */ EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ /* There is always only one block per MCU */ if (EOBRUN) /* if it's a band of zeroes... */ EOBRUN--; /* ...process it now (we do nothing) */ else { BITREAD_LOAD_STATE(cinfo, entropy->bitstate); Se = cinfo->Se; Al = cinfo->Al; natural_order = cinfo->natural_order; block = MCU_data[0]; tbl = entropy->ac_derived_tbl; for (k = cinfo->Ss; k <= Se; k++) { HUFF_DECODE(s, br_state, tbl, return FALSE, label2); r = s >> 4; s &= 15; if (s) { k += r; CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); /* Scale and output coefficient in natural (dezigzagged) order */ (*block)[natural_order[k]] = (JCOEF) (s << Al); } else { if (r != 15) { /* EOBr, run length is 2^r + appended bits */ if (r) { /* EOBr, r > 0 */ EOBRUN = 1 << r; CHECK_BIT_BUFFER(br_state, r, return FALSE); r = GET_BITS(r); EOBRUN += r; EOBRUN--; /* this band is processed at this moment */ } break; /* force end-of-band */ } k += 15; /* ZRL: skip 15 zeroes in band */ } } BITREAD_SAVE_STATE(cinfo, entropy->bitstate); } /* Completed MCU, so update state */ entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ } /* Account for restart interval if using restarts */ if (cinfo->restart_interval) entropy->restarts_to_go--; return TRUE; } /* * MCU decoding for DC successive approximation refinement scan. * Note: we assume such scans can be multi-component, * although the spec is not very clear on the point. */ METHODDEF(boolean) decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; JCOEF p1; int blkn; BITREAD_STATE_VARS; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* Not worth the cycles to check insufficient_data here, * since we will not change the data anyway if we read zeroes. */ /* Load up working state */ BITREAD_LOAD_STATE(cinfo, entropy->bitstate); p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { /* Encoded data is simply the next bit of the two's-complement DC value */ CHECK_BIT_BUFFER(br_state, 1, return FALSE); if (GET_BITS(1)) MCU_data[blkn][0][0] |= p1; /* Note: since we use |=, repeating the assignment later is safe */ } /* Completed MCU, so update state */ BITREAD_SAVE_STATE(cinfo, entropy->bitstate); /* Account for restart interval if using restarts */ if (cinfo->restart_interval) entropy->restarts_to_go--; return TRUE; } /* * MCU decoding for AC successive approximation refinement scan. */ METHODDEF(boolean) decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; register int s, k, r; unsigned int EOBRUN; int Se; JCOEF p1, m1; const int * natural_order; JBLOCKROW block; JCOEFPTR thiscoef; BITREAD_STATE_VARS; d_derived_tbl * tbl; int num_newnz; int newnz_pos[DCTSIZE2]; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* If we've run out of data, don't modify the MCU. */ if (! entropy->insufficient_data) { Se = cinfo->Se; p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ m1 = -p1; /* -1 in the bit position being coded */ natural_order = cinfo->natural_order; /* Load up working state */ BITREAD_LOAD_STATE(cinfo, entropy->bitstate); EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ /* There is always only one block per MCU */ block = MCU_data[0]; tbl = entropy->ac_derived_tbl; /* If we are forced to suspend, we must undo the assignments to any newly * nonzero coefficients in the block, because otherwise we'd get confused * next time about which coefficients were already nonzero. * But we need not undo addition of bits to already-nonzero coefficients; * instead, we can test the current bit to see if we already did it. */ num_newnz = 0; /* initialize coefficient loop counter to start of band */ k = cinfo->Ss; if (EOBRUN == 0) { do { HUFF_DECODE(s, br_state, tbl, goto undoit, label3); r = s >> 4; s &= 15; if (s) { if (s != 1) /* size of new coef should always be 1 */ WARNMS(cinfo, JWRN_HUFF_BAD_CODE); CHECK_BIT_BUFFER(br_state, 1, goto undoit); if (GET_BITS(1)) s = p1; /* newly nonzero coef is positive */ else s = m1; /* newly nonzero coef is negative */ } else { if (r != 15) { EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ if (r) { CHECK_BIT_BUFFER(br_state, r, goto undoit); r = GET_BITS(r); EOBRUN += r; } break; /* rest of block is handled by EOB logic */ } /* note s = 0 for processing ZRL */ } /* Advance over already-nonzero coefs and r still-zero coefs, * appending correction bits to the nonzeroes. A correction bit is 1 * if the absolute value of the coefficient must be increased. */ do { thiscoef = *block + natural_order[k]; if (*thiscoef) { CHECK_BIT_BUFFER(br_state, 1, goto undoit); if (GET_BITS(1)) { if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ if (*thiscoef >= 0) *thiscoef += p1; else *thiscoef += m1; } } } else { if (--r < 0) break; /* reached target zero coefficient */ } k++; } while (k <= Se); if (s) { int pos = natural_order[k]; /* Output newly nonzero coefficient */ (*block)[pos] = (JCOEF) s; /* Remember its position in case we have to suspend */ newnz_pos[num_newnz++] = pos; } k++; } while (k <= Se); } if (EOBRUN) { /* Scan any remaining coefficient positions after the end-of-band * (the last newly nonzero coefficient, if any). Append a correction * bit to each already-nonzero coefficient. A correction bit is 1 * if the absolute value of the coefficient must be increased. */ do { thiscoef = *block + natural_order[k]; if (*thiscoef) { CHECK_BIT_BUFFER(br_state, 1, goto undoit); if (GET_BITS(1)) { if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ if (*thiscoef >= 0) *thiscoef += p1; else *thiscoef += m1; } } } k++; } while (k <= Se); /* Count one block completed in EOB run */ EOBRUN--; } /* Completed MCU, so update state */ BITREAD_SAVE_STATE(cinfo, entropy->bitstate); entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ } /* Account for restart interval if using restarts */ if (cinfo->restart_interval) entropy->restarts_to_go--; return TRUE; undoit: /* Re-zero any output coefficients that we made newly nonzero */ while (num_newnz) (*block)[newnz_pos[--num_newnz]] = 0; return FALSE; } /* * Decode one MCU's worth of Huffman-compressed coefficients, * partial blocks. */ METHODDEF(boolean) decode_mcu_sub (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; const int * natural_order; int Se, blkn; BITREAD_STATE_VARS; savable_state state; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* If we've run out of data, just leave the MCU set to zeroes. * This way, we return uniform gray for the remainder of the segment. */ if (! entropy->insufficient_data) { natural_order = cinfo->natural_order; Se = cinfo->lim_Se; /* Load up working state */ BITREAD_LOAD_STATE(cinfo, entropy->bitstate); ASSIGN_STATE(state, entropy->saved); /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { JBLOCKROW block = MCU_data[blkn]; d_derived_tbl * htbl; register int s, k, r; int coef_limit, ci; /* Decode a single block's worth of coefficients */ /* Section F.2.2.1: decode the DC coefficient difference */ htbl = entropy->dc_cur_tbls[blkn]; HUFF_DECODE(s, br_state, htbl, return FALSE, label1); htbl = entropy->ac_cur_tbls[blkn]; k = 1; coef_limit = entropy->coef_limit[blkn]; if (coef_limit) { /* Convert DC difference to actual value, update last_dc_val */ if (s) { CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); } ci = cinfo->MCU_membership[blkn]; s += state.last_dc_val[ci]; state.last_dc_val[ci] = s; /* Output the DC coefficient */ (*block)[0] = (JCOEF) s; /* Section F.2.2.2: decode the AC coefficients */ /* Since zeroes are skipped, output area must be cleared beforehand */ for (; k < coef_limit; k++) { HUFF_DECODE(s, br_state, htbl, return FALSE, label2); r = s >> 4; s &= 15; if (s) { k += r; CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); /* Output coefficient in natural (dezigzagged) order. * Note: the extra entries in natural_order[] will save us * if k > Se, which could happen if the data is corrupted. */ (*block)[natural_order[k]] = (JCOEF) s; } else { if (r != 15) goto EndOfBlock; k += 15; } } } else { if (s) { CHECK_BIT_BUFFER(br_state, s, return FALSE); DROP_BITS(s); } } /* Section F.2.2.2: decode the AC coefficients */ /* In this path we just discard the values */ for (; k <= Se; k++) { HUFF_DECODE(s, br_state, htbl, return FALSE, label3); r = s >> 4; s &= 15; if (s) { k += r; CHECK_BIT_BUFFER(br_state, s, return FALSE); DROP_BITS(s); } else { if (r != 15) break; k += 15; } } EndOfBlock: ; } /* Completed MCU, so update state */ BITREAD_SAVE_STATE(cinfo, entropy->bitstate); ASSIGN_STATE(entropy->saved, state); } /* Account for restart interval if using restarts */ if (cinfo->restart_interval) entropy->restarts_to_go--; return TRUE; } /* * Decode one MCU's worth of Huffman-compressed coefficients, * full-size blocks. */ METHODDEF(boolean) decode_mcu (j_decompress_ptr cinfo, JBLOCKARRAY MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int blkn; BITREAD_STATE_VARS; savable_state state; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* If we've run out of data, just leave the MCU set to zeroes. * This way, we return uniform gray for the remainder of the segment. */ if (! entropy->insufficient_data) { /* Load up working state */ BITREAD_LOAD_STATE(cinfo, entropy->bitstate); ASSIGN_STATE(state, entropy->saved); /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { JBLOCKROW block = MCU_data[blkn]; d_derived_tbl * htbl; register int s, k, r; int coef_limit, ci; /* Decode a single block's worth of coefficients */ /* Section F.2.2.1: decode the DC coefficient difference */ htbl = entropy->dc_cur_tbls[blkn]; HUFF_DECODE(s, br_state, htbl, return FALSE, label1); htbl = entropy->ac_cur_tbls[blkn]; k = 1; coef_limit = entropy->coef_limit[blkn]; if (coef_limit) { /* Convert DC difference to actual value, update last_dc_val */ if (s) { CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); } ci = cinfo->MCU_membership[blkn]; s += state.last_dc_val[ci]; state.last_dc_val[ci] = s; /* Output the DC coefficient */ (*block)[0] = (JCOEF) s; /* Section F.2.2.2: decode the AC coefficients */ /* Since zeroes are skipped, output area must be cleared beforehand */ for (; k < coef_limit; k++) { HUFF_DECODE(s, br_state, htbl, return FALSE, label2); r = s >> 4; s &= 15; if (s) { k += r; CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); /* Output coefficient in natural (dezigzagged) order. * Note: the extra entries in jpeg_natural_order[] will save us * if k >= DCTSIZE2, which could happen if the data is corrupted. */ (*block)[jpeg_natural_order[k]] = (JCOEF) s; } else { if (r != 15) goto EndOfBlock; k += 15; } } } else { if (s) { CHECK_BIT_BUFFER(br_state, s, return FALSE); DROP_BITS(s); } } /* Section F.2.2.2: decode the AC coefficients */ /* In this path we just discard the values */ for (; k < DCTSIZE2; k++) { HUFF_DECODE(s, br_state, htbl, return FALSE, label3); r = s >> 4; s &= 15; if (s) { k += r; CHECK_BIT_BUFFER(br_state, s, return FALSE); DROP_BITS(s); } else { if (r != 15) break; k += 15; } } EndOfBlock: ; } /* Completed MCU, so update state */ BITREAD_SAVE_STATE(cinfo, entropy->bitstate); ASSIGN_STATE(entropy->saved, state); } /* Account for restart interval if using restarts */ if (cinfo->restart_interval) entropy->restarts_to_go--; return TRUE; } /* * Initialize for a Huffman-compressed scan. */ METHODDEF(void) start_pass_huff_decoder (j_decompress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci, blkn, tbl, i; jpeg_component_info * compptr; if (cinfo->progressive_mode) { /* Validate progressive scan parameters */ if (cinfo->Ss == 0) { if (cinfo->Se != 0) goto bad; } else { /* need not check Ss/Se < 0 since they came from unsigned bytes */ if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) goto bad; /* AC scans may have only one component */ if (cinfo->comps_in_scan != 1) goto bad; } if (cinfo->Ah != 0) { /* Successive approximation refinement scan: must have Al = Ah-1. */ if (cinfo->Ah-1 != cinfo->Al) goto bad; } if (cinfo->Al > 13) { /* need not check for < 0 */ /* Arguably the maximum Al value should be less than 13 for 8-bit * precision, but the spec doesn't say so, and we try to be liberal * about what we accept. Note: large Al values could result in * out-of-range DC coefficients during early scans, leading to bizarre * displays due to overflows in the IDCT math. But we won't crash. */ bad: ERREXIT4(cinfo, JERR_BAD_PROGRESSION, cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); } /* Update progression status, and verify that scan order is legal. * Note that inter-scan inconsistencies are treated as warnings * not fatal errors ... not clear if this is right way to behave. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; if (cinfo->Ah != expected) WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); coef_bit_ptr[coefi] = cinfo->Al; } } /* Select MCU decoding routine */ if (cinfo->Ah == 0) { if (cinfo->Ss == 0) entropy->pub.decode_mcu = decode_mcu_DC_first; else entropy->pub.decode_mcu = decode_mcu_AC_first; } else { if (cinfo->Ss == 0) entropy->pub.decode_mcu = decode_mcu_DC_refine; else entropy->pub.decode_mcu = decode_mcu_AC_refine; } for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Make sure requested tables are present, and compute derived tables. * We may build same derived table more than once, but it's not expensive. */ if (cinfo->Ss == 0) { if (cinfo->Ah == 0) { /* DC refinement needs no table */ tbl = compptr->dc_tbl_no; jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, & entropy->derived_tbls[tbl]); } } else { tbl = compptr->ac_tbl_no; jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, & entropy->derived_tbls[tbl]); /* remember the single active table */ entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; } /* Initialize DC predictions to 0 */ entropy->saved.last_dc_val[ci] = 0; } /* Initialize private state variables */ entropy->saved.EOBRUN = 0; } else { /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. * This ought to be an error condition, but we make it a warning because * there are some baseline files out there with all zeroes in these bytes. */ if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || ((cinfo->is_baseline || cinfo->Se < DCTSIZE2) && cinfo->Se != cinfo->lim_Se)) WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); /* Select MCU decoding routine */ /* We retain the hard-coded case for full-size blocks. * This is not necessary, but it appears that this version is slightly * more performant in the given implementation. * With an improved implementation we would prefer a single optimized * function. */ if (cinfo->lim_Se != DCTSIZE2-1) entropy->pub.decode_mcu = decode_mcu_sub; else entropy->pub.decode_mcu = decode_mcu; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Compute derived values for Huffman tables */ /* We may do this more than once for a table, but it's not expensive */ tbl = compptr->dc_tbl_no; jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, & entropy->dc_derived_tbls[tbl]); if (cinfo->lim_Se) { /* AC needs no table when not present */ tbl = compptr->ac_tbl_no; jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, & entropy->ac_derived_tbls[tbl]); } /* Initialize DC predictions to 0 */ entropy->saved.last_dc_val[ci] = 0; } /* Precalculate decoding info for each block in an MCU of this scan */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; /* Precalculate which table to use for each block */ entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; entropy->ac_cur_tbls[blkn] = /* AC needs no table when not present */ cinfo->lim_Se ? entropy->ac_derived_tbls[compptr->ac_tbl_no] : NULL; /* Decide whether we really care about the coefficient values */ if (compptr->component_needed) { ci = compptr->DCT_v_scaled_size; i = compptr->DCT_h_scaled_size; switch (cinfo->lim_Se) { case (1*1-1): entropy->coef_limit[blkn] = 1; break; case (2*2-1): if (ci <= 0 || ci > 2) ci = 2; if (i <= 0 || i > 2) i = 2; entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order2[ci - 1][i - 1]; break; case (3*3-1): if (ci <= 0 || ci > 3) ci = 3; if (i <= 0 || i > 3) i = 3; entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order3[ci - 1][i - 1]; break; case (4*4-1): if (ci <= 0 || ci > 4) ci = 4; if (i <= 0 || i > 4) i = 4; entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order4[ci - 1][i - 1]; break; case (5*5-1): if (ci <= 0 || ci > 5) ci = 5; if (i <= 0 || i > 5) i = 5; entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order5[ci - 1][i - 1]; break; case (6*6-1): if (ci <= 0 || ci > 6) ci = 6; if (i <= 0 || i > 6) i = 6; entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order6[ci - 1][i - 1]; break; case (7*7-1): if (ci <= 0 || ci > 7) ci = 7; if (i <= 0 || i > 7) i = 7; entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order7[ci - 1][i - 1]; break; default: if (ci <= 0 || ci > 8) ci = 8; if (i <= 0 || i > 8) i = 8; entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order[ci - 1][i - 1]; } } else { entropy->coef_limit[blkn] = 0; } } } /* Initialize bitread state variables */ entropy->bitstate.bits_left = 0; entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ entropy->insufficient_data = FALSE; /* Initialize restart counter */ entropy->restarts_to_go = cinfo->restart_interval; } /* * Module initialization routine for Huffman entropy decoding. */ GLOBAL(void) jinit_huff_decoder (j_decompress_ptr cinfo) { huff_entropy_ptr entropy; int i; entropy = (huff_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(huff_entropy_decoder)); cinfo->entropy = &entropy->pub; entropy->pub.start_pass = start_pass_huff_decoder; entropy->pub.finish_pass = finish_pass_huff; if (cinfo->progressive_mode) { /* Create progression status table */ int *coef_bit_ptr, ci; cinfo->coef_bits = (int (*)[DCTSIZE2]) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * DCTSIZE2 * SIZEOF(int)); coef_bit_ptr = & cinfo->coef_bits[0][0]; for (ci = 0; ci < cinfo->num_components; ci++) for (i = 0; i < DCTSIZE2; i++) *coef_bit_ptr++ = -1; /* Mark derived tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { entropy->derived_tbls[i] = NULL; } } else { /* Mark derived tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; } } } fltk-1.4.3/README.txt0000644000175000017500000001734715004135251014317 0ustar albrechtalbrechtREADME - Fast Light Tool Kit (FLTK) Version 1.4.3 ------------------------------------------------- WHAT IS FLTK? The Fast Light Tool Kit is a cross-platform C++ GUI toolkit for UNIX®/Linux® (X11 or Wayland), Microsoft® Windows®, and macOS®. FLTK provides modern GUI functionality without bloat and supports 3D graphics via OpenGL® and its built-in GLUT emulation. It was originally developed by Mr. Bill Spitzak and is currently maintained by a small group of developers across the world with a central repository on GitHub. https://www.fltk.org/ https://github.com/fltk/fltk/ LICENSING FLTK comes with complete free source code. FLTK is available under the terms of the GNU Library General Public License with exceptions (e.g. for static linking). Contrary to popular belief, it can be used in commercial software! (Even Bill Gates could use it.) ON-LINE DOCUMENTATION The documentation in HTML and PDF forms can be created by Doxygen from the source files. HTML and PDF versions of this documentation is also available from the FLTK web site at: https://www.fltk.org/documentation.php BUILDING AND INSTALLING FLTK UNDER UNIX AND macOS Beginning with FLTK 1.4 the main and recommended build system is CMake. CMake is a "build system generator" and can be used to create Makefile's, Ninja build files, Xcode (macOS), Visual Studio (Windows) IDE files and many more. Please see README.CMake.txt for further information. Alternatively FLTK can be built with autoconf + make, the build system used in FLTK 1.3 and earlier versions. Please be aware that the following information may be outdated because it is no longer actively maintained. Note: autoconf + configure + make is still supported in FLTK 1.4.x but will be removed in FLTK 1.5.0 or any higher version. In most cases you can just type "make". This will run configure with the default (no) options and then compile everything. FLTK uses GNU autoconf to configure itself for your UNIX platform. The main things that the configure script will look for are the X11, OpenGL (or Mesa), and JPEG header and library files. Make sure that they are in the standard include/library locations. If they aren't you need to define the CFLAGS, CXXFLAGS, and LDFLAGS environment variables. If you aren't using "gcc", "g++", "c++", or "CC" for your C++ compiler, you'll also need to set the CXX environment variable. Similarly, if you aren't using "gcc" or "cc" for your C compiler you'll need to set the CC environment variable. You can run configure yourself to get the exact setup you need. Type "./configure ". Options include: --help - display help and exit --enable-cygwin - Enable the Cygwin DLL (Cygwin only) --enable-debug - Enable debugging code & symbols --disable-forms - Disable generation of the forms library --disable-gl - Disable OpenGL support --enable-shared - Enable generation of shared libraries --enable-threads - Enable multithreading support --enable-xft - Enable the Xft library (anti-aliased fonts) --enable-pango - Draw text with the pango library --disable-wayland - Force building for X11 only (no Wayland support) --enable-x11 - Force building for X11 (macOS and Cygwin) --disable-x11 - Force building for Wayland only (Linux/Unix) --bindir=/path - Set the location for executables [default = /usr/local/bin] --libdir=/path - Set the location for libraries [default = /usr/local/lib] --includedir=/path - Set the location for include files. [default = /usr/local/include] --prefix=/dir - Set the directory prefix for files [default = /usr/local] For more options please see './configure --help'. When the configure script is done you can just run the "make" command. This will build the library, FLUID tool, and all of the test programs. To install the library, become root and type "make install". This will copy the "fluid" executable to "bindir", the header files to "includedir", and the library files to "libdir". To install additional files and icons to be used by the main desktop environments such as KDE, GNOME and XFCE, you will also need to run "make install-desktop" as root. GIT USERS If you've just checked out a fresh copy of FLTK from Git (GitHub), you'll need to generate an initial version of 'configure' by running 'make makeinclude' or 'make clean' (we don't include a copy of configure in git). MAKE TARGETS make -- builds the library + test programs (does not install) make install -- builds and installs make clean -- clean for a rebuild make distclean -- like 'clean', but also removes docs, configure, fltk-config ( cd src; make ) -- builds just the fltk libraries BUILDING FLTK UNDER MICROSOFT WINDOWS There are two ways to build FLTK under Microsoft Windows. The first is to use CMake to create the Visual C++ project or NMake files in your favorite development directory, then build FLTK with Visual Studio. The second method is to use a GNU-based development tool. To build with the Cygwin or MinGW tools, use the supplied configure script as specified in the UNIX section above: ./configure ...options... See README.Windows.txt and README.CMake.txt for more info. BUILDING HTML DOCUMENTATION If you want to build the HTML documentation: ( cd documentation && make html ) If you want to build the PDF documentation: ( cd documentation && make pdf ) FLTK uses doxygen for documentation, so you'll at least need doxygen installed for creating html docs, and LaTeX for creating PDF docs. INTERNET RESOURCES FLTK is available on the 'net in a bunch of locations: - WWW: https://www.fltk.org/ https://www.fltk.org/bugs.php [for reporting bugs] https://www.fltk.org/software.php [source code] GENERAL QUESTIONS To join the FLTK mailing list, go the following web page: https://groups.google.com/forum/#!forum/fltkgeneral You can find detailed instructions how you can register for the mailing list (even w/o a Google mail address) at the bottom of this page: https://www.fltk.org/newsgroups.php REPORTING BUGS If you are new to FLTK, or have general questions about how to use FLTK, or aren't sure if you found a bug, please ask first on the fltk.general group forum at: https://groups.google.com/forum/#!forum/fltkgeneral See paragraph GENERAL QUESTIONS above for more info. If you are sure you found a bug, please see the following page for further information: https://www.fltk.org/bugs.php TRADEMARKS Microsoft and Windows are registered trademarks of Microsoft Corporation. UNIX is a registered trademark of the X/Open Group, Inc. OpenGL is a registered trademark of Silicon Graphics, Inc. macOS is a registered trademark of Apple Computers, Inc. COPYRIGHT FLTK is copyright 1998-2025 by Bill Spitzak and others, see the CREDITS.txt file for more info. This library is free software. Distribution and use rights are outlined in the file "COPYING" which should have been included with this file. If this file is missing or damaged, see the license at: https://www.fltk.org/COPYING.php fltk-1.4.3/CREDITS.txt0000644000175000017500000000273015004135251014445 0ustar albrechtalbrechtCREDITS - Fast Light Tool Kit (FLTK) ------------------------------------- This file lists the people responsible for the toolkit you are now using. If you've been looking for your name in lights but we've forgotten you here, please use the report on the following page, and we'll update this file accordingly: https://www.fltk.org/bugs.php CORE DEVELOPERS The following people do the day-to-day development of FLTK: Greg Ercolano Manolo Gouy Ian MacArthur Matthias Melcher Albrecht Schlosser These people have previously been active developers of FLTK: Fabien Costantini Craig P. Earls Curtis Edwards Gustavo Hime Talbot Hughes Lauri Kasanen Robert Kesterson Pierre Ossman James Dean Palmer Vincent Penne Bill Spitzak Michael Sweet Carl Thompson Nafees Bin Zafar OTHER CONTRIBUTORS The following people have contributed fixes or enhancements to FLTK: Laszlo Z. Antal (LZA) Teun Burgers Paul Chambers Stephen Davies Yuri D'Elia Domingo Alvarez Duarte Yuri Fedorchenko George Garvey Duncan Gibson Daniel Harding Mikael Hultgren Stuart Levy Jean-Marc Lienher (OksiD) Howard Lightstone Mike Lindner Alexander Mai Alexander Rabi James Roth Ivan Nieto (Mr.Satan) Jamie Snape Andrea Suatoni Michael Surette Paul Sydney Aaron Ucko Emanuele Vicentini Josef Vitu Jim Wilson Ken Yarnall fltk-1.4.3/autogen.sh0000755000175000017500000000137315004135251014612 0ustar albrechtalbrecht#! /bin/sh # # This file is no longer referred to in the documentation, it's kept # for backwards compatibility only. # # Just run `autoconf` instead to generate `configure` and you're done. # # The old README.Unix.txt stated that it should be executed from within # the "FLTK source-code directory", hence changing directories is not # useful and would break if the user's home directory contained spaces. # Changing directories has been removed in FLTK 1.4.0 and this file # has been simplified substantially. # # Instead of executing it as documented in pre-1.4 README files the new docs # instruct to just execute `autoconf` which is sufficient and equivalent to # the old instructions. autoconf --force || exit 1 test -n "$NOCONFIGURE" || ./configure "$@" fltk-1.4.3/configure0000755000175000017500000117561115004146477014544 0ustar albrechtalbrecht#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.71 for fltk 1.4.3. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="as_nop=: if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else \$as_nop case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else \$as_nop exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else $as_nop as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and $0: https://github.com/fltk/fltk/issues about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='fltk' PACKAGE_TARNAME='fltk' PACKAGE_VERSION='1.4.3' PACKAGE_STRING='fltk 1.4.3' PACKAGE_BUGREPORT='https://github.com/fltk/fltk/issues' PACKAGE_URL='https://www.fltk.org/' ac_unique_file="src/Fl.cxx" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_STDIO_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_c_list= ac_subst_vars='LTLIBOBJS LIBOBJS BINARY_DIR MAKEDEPEND CAT6EXT CAT3EXT CAT1EXT BUILD UNINSTALL_DESKTOP INSTALL_DESKTOP LIBDECORDBUS LIBDECORDIR FLUIDDIR THREADS OSX_ONLY HLINKS GLLIBS FTCONFIG X_EXTRA_LIBS X_LIBS X_PRE_LIBS X_CFLAGS CPP XMKMF HAVE_PTHREAD_MUTEX_RECURSIVE PTHREAD_FLAGS ZLIBINC ZLIB HAVE_PNG_H PNGINC PNG JPEGINC JPEG STATICIMAGELIBS IMAGELIBS AUDIOLIBS LARGEFILE RC LIBCOMMAND AR RANLIB DOXYDOC NROFF INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM FLTK_OPTIONS FLUID_BUILD FLUID SHAREDSUFFIX CAIRODSONAME IMGDSONAME GLDSONAME DSONAME DSOLINK DSOFLAGS DSOCOMMAND LINKSHARED LINKFLTKFORMS FLDSONAME FLLIBBASENAME FLLIBNAME CAIROLIBBASENAME IMGLIBBASENAME GLLIBBASENAME LIBBASENAME LINKFLTKIMG LINKFLTKGL LINKFLTK LIBNAME LIBEXT CAIROLIBNAME IMGLIBNAME GLLIBNAME GLDEMOS FLTKCAIROOPTION LINKFLTKCAIRO CAIROLIBS CAIROFLAGS CAIRODIR TESTDIR OPTIM ARCHFLAGS PKGCONFIG ac_ct_CXX CXXFLAGS CXX OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC host_os host_vendor host_cpu host build_os build_vendor build_cpu build FL_ABI_VERSION FL_DSO_VERSION FLTK_VERSION_PATCH FLTK_VERSION_MINOR FLTK_VERSION_MAJOR FLTK_VERSION target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_archflags with_optim enable_cairo enable_cairoext enable_cp936 enable_cygwin enable_debug enable_test enable_forms enable_gl enable_localjpeg enable_localpng enable_localzlib enable_pango enable_wayland enable_usecairo enable_use_std enable_print enable_shared enable_svg enable_threads enable_x11 enable_xcursor enable_xfixes enable_xft enable_xinerama enable_xrender enable_fluid enable_gdiplus with_abiversion enable_largefile with_links with_x ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CXX CXXFLAGS CCC XMKMF CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures fltk 1.4.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/fltk] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF X features: --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of fltk 1.4.3:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-cairo add support for Fl_Cairo_Window --enable-cairoext use FLTK code instrumentation for Cairo extended use --enable-cp936 turn on CP936 --enable-cygwin use the Cygwin DLL (default=no) --enable-debug turn on debugging --disable-test build test programs (default=yes) --disable-forms build Forms compatibility library (default=yes) --disable-gl turn off OpenGL support --enable-localjpeg use local JPEG library (default=auto) --enable-localpng use local PNG library (default=auto) --enable-localzlib use local ZLIB library (default=auto) --enable-pango turn on Pango support --disable-wayland turn off hybrid Wayland/X11 support --enable-usecairo all drawing to X11 windows uses Cairo --enable-use_std allow FLTK to use std::string etc. --disable-print turn off print support (X11) --enable-shared turn on shared libraries --disable-svg disable SVG support --disable-threads turn off multi-threading support --enable-x11 use X11 with Cygwin or macOS (default=no) --disable-xcursor turn off Xcursor support --disable-xfixes turn off Xfixes support --disable-xft turn off Xft support --disable-xinerama turn off Xinerama support --disable-xrender turn off Xrender support --disable-fluid turn off fluid building --disable-gdiplus don't use GDI+ for antialiased graphics --disable-largefile omit support for large files Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-archflags="flags" use custom architecture flags (default=none, macOS values include "-arch arm64", "-arch i386", "-arch ppc", and "-arch x86_64") --with-optim="flags" use custom optimization flags --with-abiversion Build with FL_ABI_VERSION, e.g. 10304 for FLTK 1.3.4 --with-links make header links for common misspellings (default=no) --with-x use the X Window System Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags XMKMF Path to xmkmf, Makefile generator for X Window System CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . fltk home page: . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF fltk configure 1.4.3 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_run LINENO # ---------------------- # Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that # executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: program exited with status $ac_status" >&5 printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=$ac_mid; break else $as_nop as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_lo=$ac_mid; break else $as_nop as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done else $as_nop ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=$ac_mid else $as_nop as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval (void) { return $2; } static unsigned long int ulongval (void) { return $2; } #include #include int main (void) { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : echo >>conftest.val; read $3 &5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. */ #include #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main (void) { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by fltk $as_me 1.4.3, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' // Does the compiler advertise C99 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' // Does the compiler advertise C11 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " # Test code for whether the C++ compiler supports C++98 (global declarations) ac_cxx_conftest_cxx98_globals=' // Does the compiler advertise C++98 conformance? #if !defined __cplusplus || __cplusplus < 199711L # error "Compiler does not advertise C++98 conformance" #endif // These inclusions are to reject old compilers that // lack the unsuffixed header files. #include #include // and are *not* freestanding headers in C++98. extern void assert (int); namespace std { extern int strcmp (const char *, const char *); } // Namespaces, exceptions, and templates were all added after "C++ 2.0". using std::exception; using std::strcmp; namespace { void test_exception_syntax() { try { throw "test"; } catch (const char *s) { // Extra parentheses suppress a warning when building autoconf itself, // due to lint rules shared with more typical C programs. assert (!(strcmp) (s, "test")); } } template struct test_template { T const val; explicit test_template(T t) : val(t) {} template T add(U u) { return static_cast(u) + val; } }; } // anonymous namespace ' # Test code for whether the C++ compiler supports C++98 (body of main) ac_cxx_conftest_cxx98_main=' assert (argc); assert (! argv[0]); { test_exception_syntax (); test_template tt (2.0); assert (tt.add (4) == 6.0); assert (true && !false); } ' # Test code for whether the C++ compiler supports C++11 (global declarations) ac_cxx_conftest_cxx11_globals=' // Does the compiler advertise C++ 2011 conformance? #if !defined __cplusplus || __cplusplus < 201103L # error "Compiler does not advertise C++11 conformance" #endif namespace cxx11test { constexpr int get_val() { return 20; } struct testinit { int i; double d; }; class delegate { public: delegate(int n) : n(n) {} delegate(): delegate(2354) {} virtual int getval() { return this->n; }; protected: int n; }; class overridden : public delegate { public: overridden(int n): delegate(n) {} virtual int getval() override final { return this->n * 2; } }; class nocopy { public: nocopy(int i): i(i) {} nocopy() = default; nocopy(const nocopy&) = delete; nocopy & operator=(const nocopy&) = delete; private: int i; }; // for testing lambda expressions template Ret eval(Fn f, Ret v) { return f(v); } // for testing variadic templates and trailing return types template auto sum(V first) -> V { return first; } template auto sum(V first, Args... rest) -> V { return first + sum(rest...); } } ' # Test code for whether the C++ compiler supports C++11 (body of main) ac_cxx_conftest_cxx11_main=' { // Test auto and decltype auto a1 = 6538; auto a2 = 48573953.4; auto a3 = "String literal"; int total = 0; for (auto i = a3; *i; ++i) { total += *i; } decltype(a2) a4 = 34895.034; } { // Test constexpr short sa[cxx11test::get_val()] = { 0 }; } { // Test initializer lists cxx11test::testinit il = { 4323, 435234.23544 }; } { // Test range-based for int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; for (auto &x : array) { x += 23; } } { // Test lambda expressions using cxx11test::eval; assert (eval ([](int x) { return x*2; }, 21) == 42); double d = 2.0; assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0); assert (d == 5.0); assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0); assert (d == 5.0); } { // Test use of variadic templates using cxx11test::sum; auto a = sum(1); auto b = sum(1, 2); auto c = sum(1.0, 2.0, 3.0); } { // Test constructor delegation cxx11test::delegate d1; cxx11test::delegate d2(); cxx11test::delegate d3(45); } { // Test override and final cxx11test::overridden o1(55464); } { // Test nullptr char *c = nullptr; } { // Test template brackets test_template<::test_template> v(test_template(12)); } { // Unicode literals char const *utf8 = u8"UTF-8 string \u2500"; char16_t const *utf16 = u"UTF-8 string \u2500"; char32_t const *utf32 = U"UTF-32 string \u2500"; } ' # Test code for whether the C compiler supports C++11 (complete). ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals} ${ac_cxx_conftest_cxx11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_cxx_conftest_cxx98_main} ${ac_cxx_conftest_cxx11_main} return ok; } " # Test code for whether the C compiler supports C++98 (complete). ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals} int main (int argc, char **argv) { int ok = 0; ${ac_cxx_conftest_cxx98_main} return ok; } " as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" # Auxiliary files required by this configure script. ac_aux_files="install-sh config.guess config.sub" # Locations in which to look for auxiliary files. ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.." # Search for a directory containing all of the required auxiliary files, # $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. # If we don't find one directory that contains all the files we need, # we report the set of missing files from the *first* directory in # $ac_aux_dir_candidates and give up. ac_missing_aux_files="" ac_first_candidate=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in $ac_aux_dir_candidates do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 ac_aux_dir_found=yes ac_install_sh= for ac_aux in $ac_aux_files do # As a special case, if "install-sh" is required, that requirement # can be satisfied by any of "install-sh", "install.sh", or "shtool", # and $ac_install_sh is set appropriately for whichever one is found. if test x"$ac_aux" = x"install-sh" then if test -f "${as_dir}install-sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 ac_install_sh="${as_dir}install-sh -c" elif test -f "${as_dir}install.sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 ac_install_sh="${as_dir}install.sh -c" elif test -f "${as_dir}shtool"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 ac_install_sh="${as_dir}shtool install -c" else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} install-sh" else break fi fi else if test -f "${as_dir}${ac_aux}"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" else break fi fi fi done if test "$ac_aux_dir_found" = yes; then ac_aux_dir="$as_dir" break fi ac_first_candidate=false as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. if test -f "${ac_aux_dir}config.guess"; then ac_config_guess="$SHELL ${ac_aux_dir}config.guess" fi if test -f "${ac_aux_dir}config.sub"; then ac_config_sub="$SHELL ${ac_aux_dir}config.sub" fi if test -f "$ac_aux_dir/configure"; then ac_configure="$SHELL ${ac_aux_dir}configure" fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu FLTK_VERSION="1.4.3" FLTK_VERSION_MAJOR=$(echo 1.4.3 | awk -F. '{print $1}') FLTK_VERSION_MINOR=$(echo 1.4.3 | awk -F. '{print $2}') FLTK_VERSION_PATCH=$(echo 1.4.3 | awk -F. '{print $3}') FL_DSO_VERSION="${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR}" FL_ABI_VERSION="${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR}.0" # Make sure we can run config.sub. $SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 printf %s "checking build system type... " >&6; } if test ${ac_cv_build+y} then : printf %s "(cached) " >&6 else $as_nop ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 printf "%s\n" "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 printf %s "checking host system type... " >&6; } if test ${ac_cv_host+y} then : printf %s "(cached) " >&6 else $as_nop if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 printf "%s\n" "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac if test "$host" != "$build" then : fltk_cross_compiling="yes" else $as_nop fltk_cross_compiling="no" fi CFLAGS="${CFLAGS:=}" CPPFLAGS="${CPPFLAGS:=}" CXXFLAGS="${CXXFLAGS:=}" DSOFLAGS="${DSOFLAGS:=}" LDFLAGS="${LDFLAGS:=}" LIBS="${LDFLAGS:=}" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else $as_nop ac_file='' fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CXX+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 printf "%s\n" "$CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CXX+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 printf "%s\n" "$ac_ct_CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5 printf %s "checking whether the compiler supports GNU C++... " >&6; } if test ${ac_cv_cxx_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+y} ac_save_CXXFLAGS=$CXXFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 printf %s "checking whether $CXX accepts -g... " >&6; } if test ${ac_cv_prog_cxx_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes else $as_nop CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : else $as_nop ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 printf "%s\n" "$ac_cv_prog_cxx_g" >&6; } if test $ac_test_CXXFLAGS; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_prog_cxx_stdcxx=no if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 printf %s "checking for $CXX option to enable C++11 features... " >&6; } if test ${ac_cv_prog_cxx_cxx11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cxx_cxx11=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx11_program _ACEOF for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx11" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX fi if test "x$ac_cv_prog_cxx_cxx11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cxx_cxx11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx11" fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11 ac_prog_cxx_stdcxx=cxx11 fi fi if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 printf %s "checking for $CXX option to enable C++98 features... " >&6; } if test ${ac_cv_prog_cxx_cxx98+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cxx_cxx98=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx98_program _ACEOF for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx98=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx98" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX fi if test "x$ac_cv_prog_cxx_cxx98" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cxx_cxx98" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx98" fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98 ac_prog_cxx_stdcxx=cxx98 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PKGCONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $PKGCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKGCONFIG="$PKGCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PKGCONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKGCONFIG=$ac_cv_path_PKGCONFIG if test -n "$PKGCONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5 printf "%s\n" "$PKGCONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_path_PKGCONFIG"; then ac_pt_PKGCONFIG=$PKGCONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_PKGCONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $ac_pt_PKGCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKGCONFIG="$ac_pt_PKGCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKGCONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKGCONFIG=$ac_cv_path_ac_pt_PKGCONFIG if test -n "$ac_pt_PKGCONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKGCONFIG" >&5 printf "%s\n" "$ac_pt_PKGCONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_PKGCONFIG" = x; then PKGCONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKGCONFIG=$ac_pt_PKGCONFIG fi else PKGCONFIG="$ac_cv_path_PKGCONFIG" fi ARCHFLAGS="${ARCHFLAGS:=}" # Check whether --with-archflags was given. if test ${with_archflags+y} then : withval=$with_archflags; ARCHFLAGS="$withval" fi OPTIM="${OPTIM:=}" # Check whether --with-optim was given. if test ${with_optim+y} then : withval=$with_optim; OPTIM="$withval" fi # Check whether --enable-cairo was given. if test ${enable_cairo+y} then : enableval=$enable_cairo; fi # Check whether --enable-cairoext was given. if test ${enable_cairoext+y} then : enableval=$enable_cairoext; fi # Check whether --enable-cp936 was given. if test ${enable_cp936+y} then : enableval=$enable_cp936; fi if test x$enable_cp936 = xyes then : CFLAGS="$CFLAGS -DCP936" fi # Check whether --enable-cygwin was given. if test ${enable_cygwin+y} then : enableval=$enable_cygwin; fi # Check whether --enable-debug was given. if test ${enable_debug+y} then : enableval=$enable_debug; fi if test x$enable_debug = xyes then : DEBUGFLAG="-g " else $as_nop DEBUGFLAG="" fi # Check whether --enable-test was given. if test ${enable_test+y} then : enableval=$enable_test; fi if test x$enable_test = xno then : TESTDIR="" else $as_nop TESTDIR="test" fi # Check whether --enable-forms was given. if test ${enable_forms+y} then : enableval=$enable_forms; fi # Check whether --enable-gl was given. if test ${enable_gl+y} then : enableval=$enable_gl; fi # Check whether --enable-localjpeg was given. if test ${enable_localjpeg+y} then : enableval=$enable_localjpeg; fi # Check whether --enable-localpng was given. if test ${enable_localpng+y} then : enableval=$enable_localpng; fi # Check whether --enable-localzlib was given. if test ${enable_localzlib+y} then : enableval=$enable_localzlib; fi # Check whether --enable-pango was given. if test ${enable_pango+y} then : enableval=$enable_pango; fi # Check whether --enable-wayland was given. if test ${enable_wayland+y} then : enableval=$enable_wayland; fi # Check whether --enable-usecairo was given. if test ${enable_usecairo+y} then : enableval=$enable_usecairo; fi # Check whether --enable-use_std was given. if test ${enable_use_std+y} then : enableval=$enable_use_std; fi # Check whether --enable-print was given. if test ${enable_print+y} then : enableval=$enable_print; fi if test x$enable_print = xno then : printf "%s\n" "#define FL_NO_PRINT_SUPPORT Disable X11 print support?" >>confdefs.h fi # Check whether --enable-shared was given. if test ${enable_shared+y} then : enableval=$enable_shared; fi # Check whether --enable-svg was given. if test ${enable_svg+y} then : enableval=$enable_svg; fi if test x$enable_svg != xno then : printf "%s\n" "#define FLTK_USE_SVG 1" >>confdefs.h fi # Check whether --enable-threads was given. if test ${enable_threads+y} then : enableval=$enable_threads; fi # Check whether --enable-x11 was given. if test ${enable_x11+y} then : enableval=$enable_x11; fi # Check whether --enable-xcursor was given. if test ${enable_xcursor+y} then : enableval=$enable_xcursor; fi # Check whether --enable-xfixes was given. if test ${enable_xfixes+y} then : enableval=$enable_xfixes; fi # Check whether --enable-xft was given. if test ${enable_xft+y} then : enableval=$enable_xft; fi # Check whether --enable-xinerama was given. if test ${enable_xinerama+y} then : enableval=$enable_xinerama; fi # Check whether --enable-xrender was given. if test ${enable_xrender+y} then : enableval=$enable_xrender; fi # Check whether --enable-fluid was given. if test ${enable_fluid+y} then : enableval=$enable_fluid; fi case $host_os in #( cygwin* | mingw*) : # Check whether --enable-gdiplus was given. if test ${enable_gdiplus+y} then : enableval=$enable_gdiplus; fi gdiplus_found=no if test x$enable_gdiplus != xno then : for ac_header in wtypes.h gdiplus.h do : as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include " if eval test \"x\$"$as_ac_Header"\" = x"yes" then : cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF printf "%s\n" "#define USE_GDIPLUS 1" >>confdefs.h LIBS="-lgdiplus $LIBS" gdiplus_found=yes fi done fi ;; #( *) : ;; esac if test x$enable_pango = xyes -a x$enable_xft = xno then : as_fn_error $? "--disable-xft and --enable-pango are incompatible because Xft is necessary for Pango." "$LINENO" 5 fi # TODO: Fix long long test if test "x$with_archflags" != x then : CFLAGS="$CFLAGS $with_archflags" fi BUILD="" host_os_gui=$host_os case $host_os in #( cygwin*) : # Handle Cygwin option *first*, before all other tests. if test x$enable_cygwin = xyes then : # we target Cygwin in combination with X11 if test x$enable_x11 = xyes then : host_os_gui="X11$host_os" fi fi ;; #( darwin*) : if test x$enable_x11 = xyes then : host_os_gui="X11" macosversion=$(sw_vers -productVersion | cut -d. -f2) macosversion_maj=$(sw_vers -productVersion | cut -d. -f1) if test $macosversion_maj -ge 11 -o $macosversion -ge 13 then : CXXFLAGS="$CXXFLAGS -mmacosx-version-min=10.9 -D_LIBCPP_HAS_THREAD_API_PTHREAD" fi fi ;; #( *) : ;; esac LINKFLTK="../lib/libfltk.a" LINKFLTKGL="../lib/libfltk_gl.a" LINKFLTKIMG="../lib/libfltk_images.a" GLDEMOS="gldemos" LIBEXT=".a" LIBNAME="../lib/libfltk.a" GLLIBNAME="../lib/libfltk_gl.a" IMGLIBNAME="../lib/libfltk_images.a" CAIROLIBNAME="../lib/libfltk_cairo.a" LIBBASENAME="libfltk.a" GLLIBBASENAME="libfltk_gl.a" IMGLIBBASENAME="libfltk_images.a" CAIROLIBBASENAME="libfltk_cairo.a" if test x$enable_forms != xno then : build_forms="yes" LINKFLTKFORMS="../lib/libfltk_forms.a" FLLIBNAME="../lib/libfltk_forms.a" FLLIBBASENAME="libfltk_forms.a" printf "%s\n" "#define FLTK_HAVE_FORMS 1" >>confdefs.h else $as_nop build_forms="no" LINKFLTKFORMS="" FLLIBNAME="" FLLIBBASENAME="" fi CAIRODIR="" CAIROFLAGS="" LINKFLTKCAIRO="" FLTKCAIROOPTION="" CAIROLIBS="" if test x$enable_cairoext = xyes then : if $PKGCONFIG --exists cairo then : printf "%s\n" "#define FLTK_HAVE_CAIROEXT 1" >>confdefs.h printf "%s\n" "#define FLTK_HAVE_CAIRO 1" >>confdefs.h CAIRODIR="cairo" CAIROFLAGS="$($PKGCONFIG --cflags cairo)" CAIROLIBS="$($PKGCONFIG --libs cairo)" CXXFLAGS="$CAIROFLAGS $CXXFLAGS" LINKFLTKCAIRO="../lib/libfltk_cairo.a" FLTKCAIROOPTION="-L ../cairo -lfltk_cairo$SHAREDSUFFIX" LIBS="$CAIROLIBS $LIBS" LINKFLTK="$LINKFLTK $LINKFLTKCAIRO" else $as_nop as_fn_error $? "Cairo requested but not found." "$LINENO" 5 fi elif test x$enable_cairo = xyes then : if $PKGCONFIG --exists cairo then : printf "%s\n" "#define FLTK_HAVE_CAIRO 1" >>confdefs.h CAIRODIR="cairo" CAIROFLAGS="$($PKGCONFIG --cflags cairo)" CAIROLIBS="$($PKGCONFIG --libs cairo)" CXXFLAGS="$CAIROFLAGS $CXXFLAGS" LINKFLTKCAIRO="../lib/libfltk_cairo.a" FLTKCAIROOPTION="-L ../cairo -lfltk_cairo$SHAREDSUFFIX" else $as_nop as_fn_error $? "Cairo requested but not found." "$LINENO" 5 fi fi # Check whether --with-abiversion was given. if test ${with_abiversion+y} then : withval=$with_abiversion; fi has_abiversion="$with_abiversion" if test "x$has_abiversion" = xyes -o "x$has_abiversion" = xno then : has_abiversion="" fi if test "x$has_abiversion" != x then : printf "%s\n" "#define FL_ABI_VERSION $has_abiversion" >>confdefs.h fi if test "x$enable_shared" = xyes then : PICFLAG=1 SHAREDSUFFIX="" FLUID="fluid-shared" FLTK_OPTIONS="fltk-options-shared" case $host_os in #( darwin*) : DSONAME="libfltk.$FL_DSO_VERSION.dylib" FLDSONAME="libfltk_forms.$FL_DSO_VERSION.dylib" GLDSONAME="libfltk_gl.$FL_DSO_VERSION.dylib" IMGDSONAME="libfltk_images.$FL_DSO_VERSION.dylib" CAIRODSONAME="libfltk_cairo.$FL_DSO_VERSION.dylib" DSOCOMMAND="\$(CXX) \$(ARCHFLAGS) \$(DSOFLAGS) -dynamiclib -lc -o" ;; #( solaris*) : DSONAME="libfltk.so.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.so.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.so.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.so.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.so.$FL_DSO_VERSION" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-soname,\$@ \$(LDLIBS) -shared -fPIC $DEBUGFLAG -o" if test "x$libdir" != "x/usr/lib" then : DSOLINK="-R$libdir" fi ;; #( hpux*) : DSONAME="libfltk.sl.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.sl.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.sl.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.sl.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.sl.$FL_DSO_VERSION" DSOCOMMAND="ld \$(DSOFLAGS) -b -z +h \$@ $DEBUGFLAG -o" if test "x$libdir" != "x/usr/lib" then : DSOLINK="-Wl,-rpath,$libdir" fi ;; #( irix*) : DSONAME="libfltk.so.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.so.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.so.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.so.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.so.$FL_DSO_VERSION" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-soname,\$@,-set_version,sgi1.1 \$(LDLIBS) -shared $DEBUGFLAG -o" if test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/usr/lib32" -a "x$libdir" != "x/usr/lib64" then : DSOLINK="-Wl,-rpath,$libdir" fi ;; #( osf*) : DSONAME="libfltk.so.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.so.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.so.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.so.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.so.$FL_DSO_VERSION" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-soname,\$@ \$(LDLIBS) -shared $DEBUGFLAG -o" if test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/usr/lib32" then : DSOLINK="-Wl,-rpath,$libdir" fi ;; #( linux*|*bsd*) : DSONAME="libfltk.so.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.so.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.so.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.so.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.so.$FL_DSO_VERSION" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-soname,\$@ \$(LDLIBS) -shared -fPIC $DEBUGFLAG -o" # See if the compiler supports -fvisibility... { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the compiler supports -fvisibility" >&5 printf %s "checking if the compiler supports -fvisibility... " >&6; } if test ${ac_cv_cxx_fvisibility+y} then : printf %s "(cached) " >&6 else $as_nop OLDCXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -fvisibility=hidden" ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_cxx_fvisibility=yes else $as_nop ac_cv_cxx_fvisibility=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CXXFLAGS="$OLDCXXFLAGS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_fvisibility" >&5 printf "%s\n" "$ac_cv_cxx_fvisibility" >&6; } if test x"$ac_cv_cxx_fvisibility" = xyes then : OPTIM="$OPTIM -fvisibility=hidden" fi # See if the compiler supports -fvisibility-inlines-hidden... { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the compiler supports -fvisibility-inlines-hidden" >&5 printf %s "checking if the compiler supports -fvisibility-inlines-hidden... " >&6; } if test ${ac_cv_cxx_fvisibility_inlines+y} then : printf %s "(cached) " >&6 else $as_nop OLDCXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden" ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_cxx_fvisibility_inlines=yes else $as_nop ac_cv_cxx_fvisibility_inlines=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CXXFLAGS="$OLDCXXFLAGS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_fvisibility_inlines" >&5 printf "%s\n" "$ac_cv_cxx_fvisibility_inlines" >&6; } if test x"$ac_cv_cxx_fvisibility_inlines" = xyes then : CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden" fi if test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/usr/lib64" then : DSOLINK="-Wl,-rpath,$libdir" fi ;; #( aix*) : DSONAME="libfltk_s.a" FLDSONAME="libfltk_forms_s.a" GLDSONAME="libfltk_gl_s.a" IMGDSONAME="libfltk_images_s.a" CAIRODSONAME="libfltk_cairo_s.a" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-bexpall,-bM:SRE,-bnoentry -o" SHAREDSUFFIX="_s" ;; #( cygwin* | mingw*) : PICFLAG=0 if test x$enable_cygwin != xyes then : DSONAME="mgwfltknox-$FL_DSO_VERSION.dll" FLDSONAME="mgwfltknox_forms-$FL_DSO_VERSION.dll" GLDSONAME="mgwfltknox_gl-$FL_DSO_VERSION.dll" IMGDSONAME="mgwfltknox_images-$FL_DSO_VERSION.dll" CAIRODSONAME="mgwfltknox_cairo-$FL_DSO_VERSION.dll" elif test x$enable_x11 = xyes then : DSONAME="cygfltk-$FL_DSO_VERSION.dll" FLDSONAME="cygfltk_forms-$FL_DSO_VERSION.dll" GLDSONAME="cygfltk_gl-$FL_DSO_VERSION.dll" IMGDSONAME="cygfltk_images-$FL_DSO_VERSION.dll" CAIRODSONAME="cygfltk_cairo-$FL_DSO_VERSION.dll" else $as_nop DSONAME="cygfltknox-$FL_DSO_VERSION.dll" FLDSONAME="cygfltknox_forms-$FL_DSO_VERSION.dll" GLDSONAME="cygfltknox_gl-$FL_DSO_VERSION.dll" IMGDSONAME="cygfltknox_images-$FL_DSO_VERSION.dll" CAIRODSONAME="cygfltknox_cairo-$FL_DSO_VERSION.dll" fi #----------------------------------------------------------- # -Wl,--enable-runtime-pseudo-reloc: See str 1585 # appears to be necessary for older binutils versions < 2.16 #----------------------------------------------------------- LDFLAGS="$LDFLAGS -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -shared -Wl,--whole-archive -Wl,--export-all-symbols -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-auto-import -Wl,--enable-auto-image-base -o \$@" ;; #( *) : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Shared libraries may not be supported. Trying -shared option with compiler." >&5 printf "%s\n" "$as_me: WARNING: Shared libraries may not be supported. Trying -shared option with compiler." >&2;} DSONAME="libfltk.so.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.so.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.so.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.so.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.so.$FL_DSO_VERSION" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-soname,\$@ \$(LDLIBS) -shared $DEBUGFLAG -o" ;; #( *) : ;; esac LINKSHARED="-L../src $FLTKCAIROOPTION -lfltk_images$SHAREDSUFFIX -lfltk$SHAREDSUFFIX" else $as_nop DSOCOMMAND="echo" DSOLINK="" DSONAME="" FLDSONAME="" GLDSONAME="" IMGDSONAME="" CAIRODSONAME="" PICFLAG=0 SHAREDSUFFIX="" FLUID="fluid" FLTK_OPTIONS="fltk-options" LINKSHARED="$LINKFLTKCAIRO ../lib/libfltk_images.a ../lib/libfltk.a" fi if test x$build_forms = xno then : FLDSONAME="" fi if test "x$fltk_cross_compiling" = xyes then : FLUID_BUILD="fluid" else $as_nop FLUID_BUILD="../fluid/fluid$EXEEXT" fi # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 printf %s "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test ${ac_cv_path_install+y} then : printf %s "(cached) " >&6 else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac # Account for fact that we put trailing slashes in our PATH walk. case $as_dir in #(( ./ | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test ${ac_cv_path_install+y}; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 printf "%s\n" "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' case $host_os in #( osf*) : INSTALL="$(pwd)/install-sh -c" ;; #( *) : ;; esac if test "x$INSTALL" = "x$ac_install_sh" then : # Use full path to install-sh script... INSTALL="$(pwd)/install-sh -c" fi for ac_prog in nroff groff do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_NROFF+y} then : printf %s "(cached) " >&6 else $as_nop case $NROFF in [\\/]* | ?:[\\/]*) ac_cv_path_NROFF="$NROFF" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_NROFF="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi NROFF=$ac_cv_path_NROFF if test -n "$NROFF"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NROFF" >&5 printf "%s\n" "$NROFF" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$NROFF" && break done test -n "$NROFF" || NROFF="echo" # Extract the first word of "doxygen", so it can be a program name with args. set dummy doxygen; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_DOXYDOC+y} then : printf %s "(cached) " >&6 else $as_nop case $DOXYDOC in [\\/]* | ?:[\\/]*) ac_cv_path_DOXYDOC="$DOXYDOC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_DOXYDOC="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi DOXYDOC=$ac_cv_path_DOXYDOC if test -n "$DOXYDOC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DOXYDOC" >&5 printf "%s\n" "$DOXYDOC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_AR+y} then : printf %s "(cached) " >&6 else $as_nop case $AR in [\\/]* | ?:[\\/]*) ac_cv_path_AR="$AR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_AR="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi AR=$ac_cv_path_AR if test -n "$AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 printf "%s\n" "$AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_path_AR"; then ac_pt_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_AR+y} then : printf %s "(cached) " >&6 else $as_nop case $ac_pt_AR in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_AR="$ac_pt_AR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_AR="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_AR=$ac_cv_path_ac_pt_AR if test -n "$ac_pt_AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_AR" >&5 printf "%s\n" "$ac_pt_AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_AR" = x; then AR="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_pt_AR fi else AR="$ac_cv_path_AR" fi if test "x$AR" = "x:" then : as_fn_error $? "Configure could not find the library archiver, aborting." "$LINENO" 5 fi if test "x$RANLIB" != "x:" then : LIBCOMMAND="$AR cr" else $as_nop LIBCOMMAND="$AR crs" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. set dummy ${ac_tool_prefix}windres; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_RC+y} then : printf %s "(cached) " >&6 else $as_nop case $RC in [\\/]* | ?:[\\/]*) ac_cv_path_RC="$RC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_RC="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi RC=$ac_cv_path_RC if test -n "$RC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RC" >&5 printf "%s\n" "$RC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_path_RC"; then ac_pt_RC=$RC # Extract the first word of "windres", so it can be a program name with args. set dummy windres; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_RC+y} then : printf %s "(cached) " >&6 else $as_nop case $ac_pt_RC in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_RC="$ac_pt_RC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_RC="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_RC=$ac_cv_path_ac_pt_RC if test -n "$ac_pt_RC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_RC" >&5 printf "%s\n" "$ac_pt_RC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_RC" = x; then RC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RC=$ac_pt_RC fi else RC="$ac_cv_path_RC" fi ac_header= ac_cache= for ac_item in $ac_header_c_list do if test $ac_cache; then ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then printf "%s\n" "#define $ac_item 1" >> confdefs.h fi ac_header= ac_cache= elif test $ac_header; then ac_cache=$ac_item else ac_header=$ac_item fi done if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes then : printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 printf %s "checking size of short... " >&6; } if test ${ac_cv_sizeof_short+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default" then : else $as_nop if test "$ac_cv_type_short" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (short) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_short=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 printf "%s\n" "$ac_cv_sizeof_short" >&6; } printf "%s\n" "#define SIZEOF_SHORT $ac_cv_sizeof_short" >>confdefs.h # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 printf %s "checking size of int... " >&6; } if test ${ac_cv_sizeof_int+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default" then : else $as_nop if test "$ac_cv_type_int" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (int) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_int=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 printf "%s\n" "$ac_cv_sizeof_int" >&6; } printf "%s\n" "#define SIZEOF_INT $ac_cv_sizeof_int" >>confdefs.h # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 printf %s "checking size of long... " >&6; } if test ${ac_cv_sizeof_long+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default" then : else $as_nop if test "$ac_cv_type_long" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_long=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 printf "%s\n" "$ac_cv_sizeof_long" >&6; } printf "%s\n" "#define SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h if test $ac_cv_sizeof_short -eq 2 then : printf "%s\n" "#define U16 unsigned short" >>confdefs.h fi if test $ac_cv_sizeof_int -eq 4 then : printf "%s\n" "#define U32 unsigned" >>confdefs.h elif test $ac_cv_sizeof_long -eq 4 then : printf "%s\n" "#define U32 unsigned long" >>confdefs.h fi case $host_os in #( darwin*) : ;; #( *) : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 printf %s "checking whether byte ordering is bigendian... " >&6; } if test ${ac_cv_c_bigendian+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO" then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else $as_nop ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else $as_nop ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ unsigned short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; unsigned short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } unsigned short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; unsigned short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main (void) { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main (void) { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : ac_cv_c_bigendian=no else $as_nop ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 printf "%s\n" "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac if test $ac_cv_sizeof_int -eq 8 then : printf "%s\n" "#define U64 unsigned" >>confdefs.h elif test $ac_cv_sizeof_long -eq 8 then : printf "%s\n" "#define U64 unsigned long" >>confdefs.h fi ;; #( *) : ;; esac ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`printf "%s\n" "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 printf %s "checking for $ac_hdr that defines DIR... " >&6; } if eval test \${$as_ac_Header+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include <$ac_hdr> int main (void) { if ((DIR *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$as_ac_Header=yes" else $as_nop eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$as_ac_Header { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test \"x\$"$as_ac_Header"\" = x"yes" then : cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 printf %s "checking for library containing opendir... " >&6; } if test ${ac_cv_search_opendir+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char opendir (); int main (void) { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO" then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_opendir+y} then : break fi done if test ${ac_cv_search_opendir+y} then : else $as_nop ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 printf "%s\n" "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 printf %s "checking for library containing opendir... " >&6; } if test ${ac_cv_search_opendir+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char opendir (); int main (void) { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO" then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_opendir+y} then : break fi done if test ${ac_cv_search_opendir+y} then : else $as_nop ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 printf "%s\n" "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi ac_fn_c_check_header_compile "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default" if test "x$ac_cv_header_sys_select_h" = xyes then : printf "%s\n" "#define HAVE_SYS_SELECT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/stdtypes.h" "ac_cv_header_sys_stdtypes_h" "$ac_includes_default" if test "x$ac_cv_header_sys_stdtypes_h" = xyes then : printf "%s\n" "#define HAVE_SYS_STDTYPES_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we have the POSIX compatible scandir() prototype" >&5 printf %s "checking whether we have the POSIX compatible scandir() prototype... " >&6; } if test ${ac_cv_cxx_scandir_posix+y} then : printf %s "(cached) " >&6 else $as_nop ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int func (const char *d, dirent ***list, void *sort) { int n = scandir(d, list, 0, (int(*)(const dirent **, const dirent **))sort); return n; } int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_cxx_scandir_posix=yes else $as_nop ac_cv_cxx_scandir_posix=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_scandir_posix" >&5 printf "%s\n" "$ac_cv_cxx_scandir_posix" >&6; } if test "x$ac_cv_cxx_scandir_posix" = xyes then : printf "%s\n" "#define HAVE_SCANDIR 1" >>confdefs.h printf "%s\n" "#define HAVE_SCANDIR_POSIX 1" >>confdefs.h else $as_nop ac_fn_c_check_func "$LINENO" "scandir" "ac_cv_func_scandir" if test "x$ac_cv_func_scandir" = xyes then : case $host_os in #( solaris* | *qnx*) : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Not using $host_os scandir emulation function." >&5 printf "%s\n" "$as_me: WARNING: Not using $host_os scandir emulation function." >&2;} ;; #( *) : printf "%s\n" "#define HAVE_SCANDIR 1" >>confdefs.h ;; #( *) : ;; esac fi fi ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf" if test "x$ac_cv_func_vsnprintf" = xyes then : case $host_os in #( hpux1020) : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Not using built-in vsnprintf function because you are running HP-UX 10.20." >&5 printf "%s\n" "$as_me: WARNING: Not using built-in vsnprintf function because you are running HP-UX 10.20." >&2;} ;; #( osf4) : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Not using built-in vsnprintf function because you are running Tru64 4.0." >&5 printf "%s\n" "$as_me: WARNING: Not using built-in vsnprintf function because you are running Tru64 4.0." >&2;} ;; #( *) : printf "%s\n" "#define HAVE_VSNPRINTF 1" >>confdefs.h ;; #( *) : ;; esac fi ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf" if test "x$ac_cv_func_snprintf" = xyes then : case $host_os in #( hpux1020) : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Not using built-in snprintf function because you are running HP-UX 10.20." >&5 printf "%s\n" "$as_me: WARNING: Not using built-in snprintf function because you are running HP-UX 10.20." >&2;} ;; #( osf4) : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Not using built-in snprintf function because you are running Tru64 4.0." >&5 printf "%s\n" "$as_me: WARNING: Not using built-in snprintf function because you are running Tru64 4.0." >&2;} ;; #( *) : printf "%s\n" "#define HAVE_SNPRINTF 1" >>confdefs.h ;; #( *) : ;; esac fi ac_fn_c_check_header_compile "$LINENO" "strings.h" "ac_cv_header_strings_h" "$ac_includes_default" if test "x$ac_cv_header_strings_h" = xyes then : printf "%s\n" "#define HAVE_STRINGS_H 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strcasecmp" "ac_cv_func_strcasecmp" if test "x$ac_cv_func_strcasecmp" = xyes then : printf "%s\n" "#define HAVE_STRCASECMP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat" if test "x$ac_cv_func_strlcat" = xyes then : printf "%s\n" "#define HAVE_STRLCAT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" if test "x$ac_cv_func_strlcpy" = xyes then : printf "%s\n" "#define HAVE_STRLCPY 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" if test "x$ac_cv_header_locale_h" = xyes then : printf "%s\n" "#define HAVE_LOCALE_H 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "localeconv" "ac_cv_func_localeconv" if test "x$ac_cv_func_localeconv" = xyes then : printf "%s\n" "#define HAVE_LOCALECONV 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setenv" "ac_cv_func_setenv" if test "x$ac_cv_func_setenv" = xyes then : printf "%s\n" "#define HAVE_SETENV 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing pow" >&5 printf %s "checking for library containing pow... " >&6; } if test ${ac_cv_search_pow+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char pow (); int main (void) { return pow (); ; return 0; } _ACEOF for ac_lib in '' m do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO" then : ac_cv_search_pow=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_pow+y} then : break fi done if test ${ac_cv_search_pow+y} then : else $as_nop ac_cv_search_pow=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pow" >&5 printf "%s\n" "$ac_cv_search_pow" >&6; } ac_res=$ac_cv_search_pow if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi ac_fn_c_check_header_compile "$LINENO" "math.h" "ac_cv_header_math_h" "$ac_includes_default" if test "x$ac_cv_header_math_h" = xyes then : printf "%s\n" "#define HAVE_MATH_H 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "trunc" "ac_cv_func_trunc" if test "x$ac_cv_func_trunc" = xyes then : printf "%s\n" "#define HAVE_TRUNC 1" >>confdefs.h fi # Check whether --enable-largefile was given. if test ${enable_largefile+y} then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 printf %s "checking for special C compiler options needed for large files... " >&6; } if test ${ac_cv_sys_largefile_CC+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : break fi rm -f core conftest.err conftest.$ac_objext conftest.beam CC="$CC -n32" if ac_fn_c_try_compile "$LINENO" then : ac_cv_sys_largefile_CC=' -n32'; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 printf "%s\n" "$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 printf %s "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } if test ${ac_cv_sys_file_offset_bits+y} then : printf %s "(cached) " >&6 else $as_nop while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_sys_file_offset_bits=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_sys_file_offset_bits=64; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 printf "%s\n" "$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) printf "%s\n" "#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits" >>confdefs.h ;; esac rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 printf %s "checking for _LARGE_FILES value needed for large files... " >&6; } if test ${ac_cv_sys_large_files+y} then : printf %s "(cached) " >&6 else $as_nop while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_sys_large_files=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_sys_large_files=1; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 printf "%s\n" "$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) printf "%s\n" "#define _LARGE_FILES $ac_cv_sys_large_files" >>confdefs.h ;; esac rm -rf conftest* fi fi LARGEFILE="" if test x$enable_largefile != xno then : LARGEFILE="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE" if test x$ac_cv_sys_large_files = x1 then : LARGEFILE="$LARGEFILE -D_LARGE_FILES" fi if test x$ac_cv_sys_file_offset_bits = x64 then : LARGEFILE="$LARGEFILE -D_FILE_OFFSET_BITS=64" fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5 printf %s "checking for long long int... " >&6; } if test ${ac_cv_c_long_long+y} then : printf %s "(cached) " >&6 else $as_nop if test "$GCC" = yes then : ac_cv_c_long_long=yes else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { long long int i; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_long_long=yes else $as_nop ac_cv_c_long_long=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_long_long" >&5 printf "%s\n" "$ac_cv_c_long_long" >&6; } if test $ac_cv_c_long_long = yes then : printf "%s\n" "#define HAVE_LONG_LONG 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dlsym" >&5 printf %s "checking for library containing dlsym... " >&6; } if test ${ac_cv_search_dlsym+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlsym (); int main (void) { return dlsym (); ; return 0; } _ACEOF for ac_lib in '' dl do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO" then : ac_cv_search_dlsym=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_dlsym+y} then : break fi done if test ${ac_cv_search_dlsym+y} then : else $as_nop ac_cv_search_dlsym=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlsym" >&5 printf "%s\n" "$ac_cv_search_dlsym" >&6; } ac_res=$ac_cv_search_dlsym if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" printf "%s\n" "#define HAVE_DLSYM 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" if test "x$ac_cv_header_dlfcn_h" = xyes then : printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h fi AUDIOLIBS="" case $host_os in #( cygwin* | mingw*) : AUDIOLIBS="-lwinmm" ;; #( darwin*) : AUDIOLIBS="-framework CoreAudio" ;; #( *) : ac_fn_c_check_header_compile "$LINENO" "alsa/asoundlib.h" "ac_cv_header_alsa_asoundlib_h" "$ac_includes_default" if test "x$ac_cv_header_alsa_asoundlib_h" = xyes then : printf "%s\n" "#define HAVE_ALSA_ASOUNDLIB_H 1" >>confdefs.h AUDIOLIBS="-lasound" fi ;; #( *) : ;; esac SAVELIBS="$LIBS" IMAGELIBS="" STATICIMAGELIBS="" # Handle the JPEG lib linking mode (use fltk local or system lib) # If --enable-(resp. --disable-)localjpeg parameter is not set by user # Then we check the JPEG lib usability, with result in sysjpeglib_ok variable # Check for System lib use if automatic mode or --disable-localjpeg is requested sysjpeglib_ok=no sysjpeginc_ok=no if test x$enable_localjpeg != xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for jpeg_CreateCompress in -ljpeg" >&5 printf %s "checking for jpeg_CreateCompress in -ljpeg... " >&6; } if test ${ac_cv_lib_jpeg_jpeg_CreateCompress+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ljpeg $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char jpeg_CreateCompress (); int main (void) { return jpeg_CreateCompress (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_jpeg_jpeg_CreateCompress=yes else $as_nop ac_cv_lib_jpeg_jpeg_CreateCompress=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_jpeg_CreateCompress" >&5 printf "%s\n" "$ac_cv_lib_jpeg_jpeg_CreateCompress" >&6; } if test "x$ac_cv_lib_jpeg_jpeg_CreateCompress" = xyes then : ac_fn_c_check_header_compile "$LINENO" "jpeglib.h" "ac_cv_header_jpeglib_h" "$ac_includes_default" if test "x$ac_cv_header_jpeglib_h" = xyes then : sysjpeginc_ok=yes fi if test x$sysjpeginc_ok = xyes then : sysjpeglib_ok=yes fi fi fi # Now set the jpeg lib and include flags according to the requested mode and availability if test x$enable_localjpeg = xyes -o x$sysjpeglib_ok = xno then : JPEGINC="-I../jpeg" JPEG="jpeg" IMAGELIBS="-lfltk_jpeg $IMAGELIBS" STATICIMAGELIBS="\$libdir/libfltk_jpeg.a $STATICIMAGELIBS" printf "%s\n" "#define HAVE_LIBJPEG 1" >>confdefs.h # Finally, warn user if system lib was requested but not found if test x$enable_localjpeg = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find system jpeg lib or header: choosing the local lib mode." >&5 printf "%s\n" "$as_me: WARNING: Cannot find system jpeg lib or header: choosing the local lib mode." >&2;} fi else $as_nop JPEGINC="" JPEG="" IMAGELIBS="-ljpeg $IMAGELIBS" STATICIMAGELIBS="-ljpeg $STATICIMAGELIBS" printf "%s\n" "#define HAVE_LIBJPEG 1" >>confdefs.h fi # Handle the ZLIB lib linking mode (use fltk local or system lib) # If --enable-(resp. --disable-)localzlib parameter is not set by user # Then we check the ZLIB lib usability, with result in syszlib_ok variable # Check for System lib use if automatic mode or --disable-localzlib is requested syszlib_ok=no syszinc_ok=no if test x$enable_localzlib != xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gzgets in -lz" >&5 printf %s "checking for gzgets in -lz... " >&6; } if test ${ac_cv_lib_z_gzgets+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char gzgets (); int main (void) { return gzgets (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_z_gzgets=yes else $as_nop ac_cv_lib_z_gzgets=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzgets" >&5 printf "%s\n" "$ac_cv_lib_z_gzgets" >&6; } if test "x$ac_cv_lib_z_gzgets" = xyes then : ac_fn_c_check_header_compile "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes then : syszinc_ok=yes fi if test x$syszinc_ok = xyes then : syszlib_ok=yes fi fi fi # Handle the PNG lib linking mode (use fltk local or system lib) # If --enable-(resp. --disable-)localpng parameter is not set by user # Then we check the png lib usability with result in syspng_lib variable # Now check if system lib is usable, we check Lib AND include availability with inc variant, # but only, if the builtin lib is not requested syspnglib_ok=no syspnginc_ok=no if test x$enable_localpng != xyes -a x$PKGCONFIG != x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libpng-1.6.x" >&5 printf %s "checking for libpng-1.6.x... " >&6; } if $PKGCONFIG --exists libpng16 then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HAVE_PNG_H 1" >>confdefs.h syspnginc_ok=yes syspnglib_ok=yes PNGINC="$($PKGCONFIG --cflags libpng16)" IMAGELIBS="$($PKGCONFIG --libs libpng16) $IMAGELIBS" STATICIMAGELIBS="$($PKGCONFIG --libs libpng16) $STATICIMAGELIBS" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test x$enable_localpng != xyes -a $syspnglib_ok = no then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for png_read_info in -lpng" >&5 printf %s "checking for png_read_info in -lpng... " >&6; } if test ${ac_cv_lib_png_png_read_info+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpng $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char png_read_info (); int main (void) { return png_read_info (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_png_png_read_info=yes else $as_nop ac_cv_lib_png_png_read_info=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png_png_read_info" >&5 printf "%s\n" "$ac_cv_lib_png_png_read_info" >&6; } if test "x$ac_cv_lib_png_png_read_info" = xyes then : ac_fn_c_check_header_compile "$LINENO" "png.h" "ac_cv_header_png_h" "$ac_includes_default" if test "x$ac_cv_header_png_h" = xyes then : printf "%s\n" "#define HAVE_PNG_H 1" >>confdefs.h syspnginc_ok=yes fi ac_fn_c_check_header_compile "$LINENO" "libpng/png.h" "ac_cv_header_libpng_png_h" "$ac_includes_default" if test "x$ac_cv_header_libpng_png_h" = xyes then : syspnginc_ok=yes fi if test x$syspnginc_ok = xyes then : syspnglib_ok=yes fi fi fi # If we use the system zlib, we must also use the system png lib and vice versa. # If either of them is not available, we fall back to using both local libraries if test x$syspnglib_ok = xyes -a x$syszlib_ok != xyes then : syspnglib_ok=no enable_localpng=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Local z lib selected: overriding png lib to local for compatibility." >&5 printf "%s\n" "$as_me: WARNING: Local z lib selected: overriding png lib to local for compatibility." >&2;} fi if test x$syszlib_ok = xyes -a x$syspnglib_ok != xyes then : syszlib_ok=no enable_localzlib=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Local png lib selected: overriding z lib to local for compatibility." >&5 printf "%s\n" "$as_me: WARNING: Local png lib selected: overriding z lib to local for compatibility." >&2;} fi # Now set the Z lib and include flags according to the requested mode and availability if test x$enable_localzlib = xyes -o x$syszlib_ok = xno then : ZLIBINC="-I../zlib" ZLIB="zlib" LIBS="-lfltk_z $LIBS" IMAGELIBS="-lfltk_z $IMAGELIBS" STATICIMAGELIBS="\$libdir/libfltk_z.a $STATICIMAGELIBS" printf "%s\n" "#define HAVE_LIBZ 1" >>confdefs.h ac_cv_lib_z_gzgets=no # fc: is still necessary ? # Finally, warn user if system lib was requested but not found if test x$enable_localzlib = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find system z lib or header: choosing the local lib mode." >&5 printf "%s\n" "$as_me: WARNING: Cannot find system z lib or header: choosing the local lib mode." >&2;} fi else $as_nop ZLIBINC="" ZLIB="" LIBS="-lz $LIBS" IMAGELIBS="-lz $IMAGELIBS" STATICIMAGELIBS="-lz $STATICIMAGELIBS" printf "%s\n" "#define HAVE_LIBZ 1" >>confdefs.h fi # The following is executed if the png lib was not found usable or if local lib is required explicitly if test x$enable_localpng = xyes -o x$syspnglib_ok = xno then : PNGINC="-I../png" PNG="png" IMAGELIBS="-lfltk_png $IMAGELIBS" STATICIMAGELIBS="\$libdir/libfltk_png.a $STATICIMAGELIBS" printf "%s\n" "#define HAVE_LIBPNG 1" >>confdefs.h printf "%s\n" "#define HAVE_PNG_H 1" >>confdefs.h printf "%s\n" "#define HAVE_PNG_GET_VALID 1" >>confdefs.h printf "%s\n" "#define HAVE_PNG_SET_TRNS_TO_ALPHA 1" >>confdefs.h # Finally, warn user if system lib was requested but not found if test x$enable_localpng = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find system png lib or header: choosing the local lib mode." >&5 printf "%s\n" "$as_me: WARNING: Cannot find system png lib or header: choosing the local lib mode." >&2;} fi else $as_nop PNGINC="" PNG="" IMAGELIBS="-lpng $IMAGELIBS" STATICIMAGELIBS="-lpng $STATICIMAGELIBS" printf "%s\n" "#define HAVE_LIBPNG 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for png_get_valid in -lpng" >&5 printf %s "checking for png_get_valid in -lpng... " >&6; } if test ${ac_cv_lib_png_png_get_valid+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpng $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char png_get_valid (); int main (void) { return png_get_valid (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_png_png_get_valid=yes else $as_nop ac_cv_lib_png_png_get_valid=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png_png_get_valid" >&5 printf "%s\n" "$ac_cv_lib_png_png_get_valid" >&6; } if test "x$ac_cv_lib_png_png_get_valid" = xyes then : printf "%s\n" "#define HAVE_PNG_GET_VALID 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for png_set_tRNS_to_alpha in -lpng" >&5 printf %s "checking for png_set_tRNS_to_alpha in -lpng... " >&6; } if test ${ac_cv_lib_png_png_set_tRNS_to_alpha+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpng $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char png_set_tRNS_to_alpha (); int main (void) { return png_set_tRNS_to_alpha (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_png_png_set_tRNS_to_alpha=yes else $as_nop ac_cv_lib_png_png_set_tRNS_to_alpha=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png_png_set_tRNS_to_alpha" >&5 printf "%s\n" "$ac_cv_lib_png_png_set_tRNS_to_alpha" >&6; } if test "x$ac_cv_lib_png_png_set_tRNS_to_alpha" = xyes then : printf "%s\n" "#define HAVE_PNG_SET_TRNS_TO_ALPHA 1" >>confdefs.h fi fi # Control the usage of the nanosvg lib and SVG output LIBS="$SAVELIBS" have_pthread=no PTHREAD_FLAGS="" check_pthread=yes case $host_os in #( mingw*) : check_pthread=no ;; #( cygwin*) : if test "x$enable_cygwin" != xyes then : check_pthread=no fi ;; #( *) : ;; esac if test "x$enable_threads" != xno -a x$check_pthread = xyes then : ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes then : printf "%s\n" "#define HAVE_PTHREAD_H 1" >>confdefs.h fi if test x$ac_cv_header_pthread_h = xyes then : for flag in -lpthreads -lpthread -pthread; do { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create using $flag" >&5 printf %s "checking for pthread_create using $flag... " >&6; } SAVELIBS="$LIBS" LIBS="$flag $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { pthread_create(0, 0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : have_pthread=yes else $as_nop LIBS="$SAVELIBS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_pthread" >&5 printf "%s\n" "$have_pthread" >&6; } if test $have_pthread = yes then : printf "%s\n" "#define HAVE_PTHREAD 1" >>confdefs.h PTHREAD_FLAGS="-D_THREAD_SAFE -D_REENTRANT" # Solaris requires -D_POSIX_PTHREAD_SEMANTICS to # be POSIX-compliant... :( case $host_os in #( solaris*) : PTHREAD_FLAGS="$PTHREAD_FLAGS -D_POSIX_PTHREAD_SEMANTICS" ;; #( *) : ;; esac fi done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we have PTHREAD_MUTEX_RECURSIVE" >&5 printf %s "checking whether we have PTHREAD_MUTEX_RECURSIVE... " >&6; } if test ${ac_cv_pthread_mutex_recursive+y} then : printf %s "(cached) " >&6 else $as_nop ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { return PTHREAD_MUTEX_RECURSIVE; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_pthread_mutex_recursive=yes else $as_nop ac_cv_pthread_mutex_recursive=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_pthread_mutex_recursive" >&5 printf "%s\n" "$ac_cv_pthread_mutex_recursive" >&6; } if test x$ac_cv_pthread_mutex_recursive = xyes then : printf "%s\n" "#define HAVE_PTHREAD_MUTEX_RECURSIVE 1" >>confdefs.h fi fi fi HLINKS= OSX_ONLY=: THREADS= LIBDECORDIR="" LIBDECORDBUS="" FLUIDDIR="" # Check whether --with-links was given. if test ${with_links+y} then : withval=$with_links; fi INSTALL_DESKTOP="" UNINSTALL_DESKTOP="" if test x$enable_fluid != xno then : FLUIDDIR="fluid" fi if test x$enable_use_std = xyes then : printf "%s\n" "#define FLTK_USE_STD 1" >>confdefs.h fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 printf %s "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test ${ac_cv_prog_CPP+y} then : printf %s "(cached) " >&6 else $as_nop # Double quotes because $CC needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 printf "%s\n" "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for X" >&5 printf %s "checking for X... " >&6; } # Check whether --with-x was given. if test ${with_x+y} then : withval=$with_x; fi # $have_x is `yes', `no', `disabled', or empty when we do not yet know. if test "x$with_x" = xno; then # The user explicitly disabled X. have_x=disabled else case $x_includes,$x_libraries in #( *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( *,NONE | NONE,*) if test ${ac_cv_have_x+y} then : printf %s "(cached) " >&6 else $as_nop # One or both of the vars are not set, and there is no cached value. ac_x_includes=no ac_x_libraries=no # Do we need to do anything special at all? ac_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { XrmInitialize () ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : # We can compile and link X programs with no special options. ac_x_includes= ac_x_libraries= fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_save_LIBS" # If that didn't work, only try xmkmf and file system searches # for native compilation. if test x"$ac_x_includes" = xno && test "$cross_compiling" = no then : rm -f -r conftest.dir if mkdir conftest.dir; then cd conftest.dir cat >Imakefile <<'_ACEOF' incroot: @echo incroot='${INCROOT}' usrlibdir: @echo usrlibdir='${USRLIBDIR}' libdir: @echo libdir='${LIBDIR}' _ACEOF if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. for ac_var in incroot usrlibdir libdir; do eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" done # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. for ac_extension in a so sl dylib la dll; do if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && test -f "$ac_im_libdir/libX11.$ac_extension"; then ac_im_usrlibdir=$ac_im_libdir; break fi done # Screen out bogus values from the imake configuration. They are # bogus both because they are the default anyway, and because # using them would break gcc on systems where it needs fixed includes. case $ac_im_incroot in /usr/include) ac_x_includes= ;; *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; esac case $ac_im_usrlibdir in /usr/lib | /usr/lib64 | /lib | /lib64) ;; *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; esac fi cd .. rm -f -r conftest.dir fi # Standard set of common directories for X headers. # Check X11 before X11Rn because it is often a symlink to the current release. ac_x_header_dirs=' /usr/X11/include /usr/X11R7/include /usr/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11 /usr/include/X11R7 /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11/include /usr/local/X11R7/include /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11 /usr/local/include/X11R7 /usr/local/include/X11R6 /usr/local/include/X11R5 /usr/local/include/X11R4 /opt/X11/include /usr/X386/include /usr/x386/include /usr/XFree86/include/X11 /usr/include /usr/local/include /usr/unsupported/include /usr/athena/include /usr/local/x11r5/include /usr/lpp/Xamples/include /usr/openwin/include /usr/openwin/share/include' if test "$ac_x_includes" = no; then # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # We can compile using X headers with no special include directory. ac_x_includes= else $as_nop for ac_dir in $ac_x_header_dirs; do if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi done fi rm -f conftest.err conftest.i conftest.$ac_ext fi # $ac_x_includes = no if test "$ac_x_libraries" = no; then # Check for the libraries. # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { XrmInitialize () ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : LIBS=$ac_save_LIBS # We can link X programs with no special library path. ac_x_libraries= else $as_nop LIBS=$ac_save_LIBS for ac_dir in `printf "%s\n" "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` do # Don't even attempt the hair of trying to link an X program! for ac_extension in a so sl dylib la dll; do if test -r "$ac_dir/libX11.$ac_extension"; then ac_x_libraries=$ac_dir break 2 fi done done fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi # $ac_x_libraries = no fi # Record the results. case $ac_x_includes,$ac_x_libraries in #( no,* | *,no | *\'*) : # Didn't find X, or a directory has "'" in its name. ac_cv_have_x="have_x=no" ;; #( *) : # Record where we found X for the cache. ac_cv_have_x="have_x=yes\ ac_x_includes='$ac_x_includes'\ ac_x_libraries='$ac_x_libraries'" ;; esac fi ;; #( *) have_x=yes;; esac eval "$ac_cv_have_x" fi # $with_x != no if test "$have_x" != yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 printf "%s\n" "$have_x" >&6; } no_x=yes else # If each of the values was on the command line, it overrides each guess. test "x$x_includes" = xNONE && x_includes=$ac_x_includes test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes\ ac_x_includes='$x_includes'\ ac_x_libraries='$x_libraries'" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 printf "%s\n" "libraries $x_libraries, headers $x_includes" >&6; } fi case $host_os_gui in #( cygwin* | mingw*) : # Recent versions of Cygwin are seriously broken and the size # checks don't work because the shell puts out \r\n instead of # \n. Here we just force U32 to be defined to "unsigned"... printf "%s\n" "#define U32 unsigned" >>confdefs.h # We do no longer define WIN32 or _WIN32 (since FLTK 1.4.0) # and we don't need to define USE_OPENGL32 (added in svn r6657 # but never used, see STR #2147) # CFLAGS="-mwindows -D_WIN32 -DUSE_OPENGL32 $CFLAGS" # CXXFLAGS="-mwindows -D_WIN32 -DUSE_OPENGL32 $CXXFLAGS" LDFLAGS="-mwindows $LDFLAGS" DSOFLAGS="-mwindows $DSOFLAGS" LIBS="$LIBS -lole32 -luuid -lcomctl32 -lws2_32 -lwinspool" BUILD="WIN" if test "x$with_optim" = x then : with_optim="-O3" fi if test x$enable_gl != xno then : ac_fn_c_check_header_compile "$LINENO" "GL/gl.h" "ac_cv_header_GL_gl_h" "$ac_includes_default" if test "x$ac_cv_header_GL_gl_h" = xyes then : printf "%s\n" "#define HAVE_GL 1" >>confdefs.h GLLIBS="-lopengl32" fi ac_fn_c_check_header_compile "$LINENO" "GL/glu.h" "ac_cv_header_GL_glu_h" "$ac_includes_default" if test "x$ac_cv_header_GL_glu_h" = xyes then : printf "%s\n" "#define HAVE_GL_GLU_H 1" >>confdefs.h GLLIBS="-lglu32 $GLLIBS" fi else $as_nop LINKFLTKGL="" GLLIBNAME="" GLDSONAME="" GLDEMOS="" fi if test "x$enable_threads" != xno -a x$have_pthread = xyes then : printf "%s\n" "#define HAVE_PTHREAD 1" >>confdefs.h fi THREADS="threads$EXEEXT" # Don't make symlinks since Windows is not case sensitive. if test "x$with_links" != xyes then : HLINKS="#" fi ;; #( darwin*) : BUILD="OSX" # MacOS X uses Cocoa for graphics. LIBS="$LIBS -framework Cocoa" # Add weak-linked additional frameworks for increasingly high macOS versions ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if __MAC_OS_X_VERSION_MAX_ALLOWED < 110000 #error __MAC_OS_X_VERSION_MAX_ALLOWED < 110000 #endif int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : LIBS="$LIBS -weak_framework UniformTypeIdentifiers" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if __MAC_OS_X_VERSION_MAX_ALLOWED < 150000 #error __MAC_OS_X_VERSION_MAX_ALLOWED < 150000 #endif int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : LIBS="$LIBS -weak_framework ScreenCaptureKit" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test x$have_pthread = xyes then : printf "%s\n" "#define HAVE_PTHREAD 1" >>confdefs.h THREADS="threads$EXEEXT" fi if test x$enable_gl != xno then : printf "%s\n" "#define HAVE_GL 1" >>confdefs.h printf "%s\n" "#define HAVE_GL_GLU_H 1" >>confdefs.h GLLIBS="-framework OpenGL" else $as_nop LINKFLTKGL="" GLLIBNAME="" GLDSONAME="" GLDEMOS="" fi # Don't make symlinks because HFS+ is not case sensitive... if test "x$with_links" != xyes then : HLINKS="#" fi # Some steps are only done for OS X package management OSX_ONLY= # Install/Uninstall FLUID application INSTALL_DESKTOP="install-osx" UNINSTALL_DESKTOP="uninstall-osx" ;; #( *) : # All others are UNIX/X11... # This includes Cygwin target combined with X11 if test x$have_pthread = xyes then : printf "%s\n" "#define HAVE_PTHREAD 1" >>confdefs.h THREADS="threads$EXEEXT" fi if test x$enable_wayland != xno then : if test x$PKGCONFIG = x then : if test x$enable_wayland = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --enable-wayland: please install pkg-config." >&5 printf "%s\n" "$as_me: WARNING: --enable-wayland: please install pkg-config." >&2;} as_fn_error $? "Aborting." "$LINENO" 5 else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config is not found. Continuing with --disable-wayland" >&5 printf "%s\n" "$as_me: WARNING: pkg-config is not found. Continuing with --disable-wayland" >&2;} enable_wayland="no" fi else $as_nop missing="no" if $PKGCONFIG --exists 'wayland-client >= 1.18' then : else $as_nop missing="yes" fi if $PKGCONFIG --exists 'wayland-protocols >= 1.15' then : else $as_nop missing="yes" fi if $PKGCONFIG --exists wayland-cursor then : else $as_nop missing="yes" fi if $PKGCONFIG --exists xkbcommon then : else $as_nop missing="yes" fi if $PKGCONFIG --exists pangocairo then : else $as_nop missing="yes" fi if test x$missing = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: These packages 'wayland-client>=1.18 wayland-protocols>=1.15 wayland-cursor xkbcommon pangocairo' are required to build FLTK for wayland." >&5 printf "%s\n" "$as_me: WARNING: These packages 'wayland-client>=1.18 wayland-protocols>=1.15 wayland-cursor xkbcommon pangocairo' are required to build FLTK for wayland." >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: At least one of them is missing." >&5 printf "%s\n" "$as_me: WARNING: At least one of them is missing." >&2;} if test x$enable_wayland = xyes then : as_fn_error $? "Building for Wayland is not possible. Aborting." "$LINENO" 5 else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Continuing with --disable-wayland" >&5 printf "%s\n" "$as_me: WARNING: Continuing with --disable-wayland" >&2;} enable_wayland="no" fi fi fi fi if test x$enable_wayland != xno then : printf "%s\n" "#define FLTK_USE_CAIRO 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Turning on the usecairo option" >&5 printf "%s\n" "$as_me: Turning on the usecairo option" >&6;} BUILD="WAYLAND" printf "%s\n" "#define FLTK_USE_WAYLAND 1" >>confdefs.h graphics="Wayland" if test x$enable_x11 != xno then : printf "%s\n" "#define FLTK_USE_X11 1" >>confdefs.h # to build a hybrid Wayland/X11 library BUILD="WAYLANDX11" graphics="Wayland or X11 with cairo" fi if $PKGCONFIG --exists 'libdecor-0 >= 0.2.0' then : libdecor="system" plugin_dir="$($PKGCONFIG --variable=libdir libdecor-0)/libdecor/plugins-1" CFLAGS="$CFLAGS -DUSE_SYSTEM_LIBDECOR" CXXFLAGS="$CXXFLAGS -DUSE_SYSTEM_LIBDECOR" CFLAGS="$CFLAGS -DLIBDECOR_PLUGIN_DIR=\\\"$plugin_dir\\\" " LIBS="$LIBS $($PKGCONFIG --libs libdecor-0)" else $as_nop libdecor="bundled" CFLAGS="$CFLAGS -DUSE_SYSTEM_LIBDECOR=0 -DLIBDECOR_PLUGIN_DIR=\\\"\\\" " CXXFLAGS="$CXXFLAGS -DUSE_SYSTEM_LIBDECOR=0" fi LIBS="$LIBS $($PKGCONFIG --libs wayland-cursor) $($PKGCONFIG --libs wayland-client) $($PKGCONFIG --libs xkbcommon) $($PKGCONFIG --libs pangocairo) " if test x$enable_x11 != xno then : LIBS="$LIBS $($PKGCONFIG --libs x11)" fi LIBS="$LIBS -ldl" DSOFLAGS="$LIBS $DSOFLAGS" enable_pango=yes LIBDECORDIR="libdecor/build" if $PKGCONFIG --exists dbus-1 then : LIBDECORDBUS="-DHAS_DBUS $($PKGCONFIG --cflags dbus-1)" LIBS="$LIBS $($PKGCONFIG --libs dbus-1)" fi LDFLAGS="$LDFLAGS -rdynamic" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 printf %s "checking for library containing dlopen... " >&6; } if test ${ac_cv_search_dlopen+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlopen (); int main (void) { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO" then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_dlopen+y} then : break fi done if test ${ac_cv_search_dlopen+y} then : else $as_nop ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 printf "%s\n" "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi if test x$enable_gl != xno then : if $PKGCONFIG --exists gl then : if $PKGCONFIG --exists egl then : if $PKGCONFIG --exists wayland-egl then : printf "%s\n" "#define HAVE_GL 1" >>confdefs.h GLLIBS="$($PKGCONFIG --libs wayland-egl) $($PKGCONFIG --libs egl) $($PKGCONFIG --libs gl) $GLLIBS" fi fi fi if $PKGCONFIG --exists glu then : printf "%s\n" "#define HAVE_GL_GLU_H 1" >>confdefs.h GLLIBS="$($PKGCONFIG --libs glu) $GLLIBS" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for glXGetProcAddressARB in -lGL" >&5 printf %s "checking for glXGetProcAddressARB in -lGL... " >&6; } if test ${ac_cv_lib_GL_glXGetProcAddressARB+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lGL -lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char glXGetProcAddressARB (); int main (void) { return glXGetProcAddressARB (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_GL_glXGetProcAddressARB=yes else $as_nop ac_cv_lib_GL_glXGetProcAddressARB=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GL_glXGetProcAddressARB" >&5 printf "%s\n" "$ac_cv_lib_GL_glXGetProcAddressARB" >&6; } if test "x$ac_cv_lib_GL_glXGetProcAddressARB" = xyes then : printf "%s\n" "#define HAVE_GLXGETPROCADDRESSARB 1" >>confdefs.h fi else $as_nop LINKFLTKGL="" GLLIBNAME="" GLDSONAME="" GLDEMOS="" fi if test x$libdecor = xbundled then : gtk_found=no CFLAGS="$($PKGCONFIG --cflags gtk+-3.0) $CFLAGS" for ac_header in gtk/gtk.h do : ac_fn_c_check_header_compile "$LINENO" "gtk/gtk.h" "ac_cv_header_gtk_gtk_h" "$ac_includes_default" if test "x$ac_cv_header_gtk_gtk_h" = xyes then : printf "%s\n" "#define HAVE_GTK_GTK_H 1" >>confdefs.h CFLAGS="$CFLAGS -DHAVE_GTK" LIBS="$LIBS $($PKGCONFIG --libs gtk+-3.0)" gtk_found=yes fi done fi pango_found=no CFLAGS="$($PKGCONFIG --cflags pangocairo) $CFLAGS" CXXFLAGS="$($PKGCONFIG --cflags pangocairo) $CXXFLAGS" LIBS="$LIBS $($PKGCONFIG --libs pangocairo)" for ac_header in pango/pangocairo.h do : ac_fn_c_check_header_compile "$LINENO" "pango/pangocairo.h" "ac_cv_header_pango_pangocairo_h" "$ac_includes_default" if test "x$ac_cv_header_pango_pangocairo_h" = xyes then : printf "%s\n" "#define HAVE_PANGO_PANGOCAIRO_H 1" >>confdefs.h printf "%s\n" "#define USE_PANGO 1" >>confdefs.h printf "%s\n" "#define USE_XFT 1" >>confdefs.h pango_found=yes fi done if test x$pango_found != xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --enable-wayland: Pango libs and/or headers could not be found." >&5 printf "%s\n" "$as_me: --enable-wayland: Pango libs and/or headers could not be found." >&6;} as_fn_error $? "Aborting." "$LINENO" 5 fi if test x$enable_x11 != xno then : xinerama_found=no if $PKGCONFIG --exists xinerama then : printf "%s\n" "#define HAVE_XINERAMA 1" >>confdefs.h LIBS="$LIBS $($PKGCONFIG --libs xinerama)" xinerama_found=yes fi xcursor_found=no if $PKGCONFIG --exists xcursor then : printf "%s\n" "#define HAVE_XCURSOR 1" >>confdefs.h LIBS="$LIBS $($PKGCONFIG --libs xcursor)" xcursor_found=yes fi xfixes_found=no if $PKGCONFIG --exists xfixes then : printf "%s\n" "#define HAVE_XFIXES 1" >>confdefs.h LIBS="$LIBS $($PKGCONFIG --libs xfixes)" xfixes_found=yes fi xrender_found=no if $PKGCONFIG --exists xrender then : printf "%s\n" "#define HAVE_XRENDER 1" >>confdefs.h LIBS="$LIBS $($PKGCONFIG --libs xrender)" xrender_found=yes fi ac_fn_c_check_header_compile "$LINENO" "X11/Xregion.h" "ac_cv_header_X11_Xregion_h" "#include " if test "x$ac_cv_header_X11_Xregion_h" = xyes then : printf "%s\n" "#define HAVE_X11_XREGION_H 1" >>confdefs.h fi fi else $as_nop if test "$no_x" = yes; then # Not all programs may use this symbol, but it does not hurt to define it. printf "%s\n" "#define X_DISPLAY_MISSING 1" >>confdefs.h X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= else if test -n "$x_includes"; then X_CFLAGS="$X_CFLAGS -I$x_includes" fi # It would also be nice to do this for all -L options, not just this one. if test -n "$x_libraries"; then X_LIBS="$X_LIBS -L$x_libraries" # For Solaris; some versions of Sun CC require a space after -R and # others require no space. Words are not sufficient . . . . { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5 printf %s "checking whether -R must be followed by a space... " >&6; } ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" ac_xsave_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } X_LIBS="$X_LIBS -R$x_libraries" else $as_nop LIBS="$ac_xsave_LIBS -R $x_libraries" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } X_LIBS="$X_LIBS -R $x_libraries" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: neither works" >&5 printf "%s\n" "neither works" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ac_c_werror_flag=$ac_xsave_c_werror_flag LIBS=$ac_xsave_LIBS fi # Check for system-dependent libraries X programs must link with. # Do this before checking for the system-independent R6 libraries # (-lICE), since we may need -lsocket or whatever for X linking. if test "$ISC" = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" else # Martyn Johnson says this is needed for Ultrix, if the X # libraries were built with DECnet support. And Karl Berry says # the Alpha needs dnet_stub (dnet does not exist). ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XOpenDisplay (); int main (void) { return XOpenDisplay (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5 printf %s "checking for dnet_ntoa in -ldnet... " >&6; } if test ${ac_cv_lib_dnet_dnet_ntoa+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dnet_ntoa (); int main (void) { return dnet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dnet_dnet_ntoa=yes else $as_nop ac_cv_lib_dnet_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 printf "%s\n" "$ac_cv_lib_dnet_dnet_ntoa" >&6; } if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5 printf %s "checking for dnet_ntoa in -ldnet_stub... " >&6; } if test ${ac_cv_lib_dnet_stub_dnet_ntoa+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet_stub $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dnet_ntoa (); int main (void) { return dnet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dnet_stub_dnet_ntoa=yes else $as_nop ac_cv_lib_dnet_stub_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 printf "%s\n" "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_xsave_LIBS" # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, # to get the SysV transport functions. # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) # needs -lnsl. # The nsl library prevents programs from opening the X display # on Irix 5.2, according to T.E. Dickey. # The functions gethostbyname, getservbyname, and inet_addr are # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" if test "x$ac_cv_func_gethostbyname" = xyes then : fi if test $ac_cv_func_gethostbyname = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 printf %s "checking for gethostbyname in -lnsl... " >&6; } if test ${ac_cv_lib_nsl_gethostbyname+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char gethostbyname (); int main (void) { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_nsl_gethostbyname=yes else $as_nop ac_cv_lib_nsl_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 printf "%s\n" "$ac_cv_lib_nsl_gethostbyname" >&6; } if test "x$ac_cv_lib_nsl_gethostbyname" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" fi if test $ac_cv_lib_nsl_gethostbyname = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 printf %s "checking for gethostbyname in -lbsd... " >&6; } if test ${ac_cv_lib_bsd_gethostbyname+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char gethostbyname (); int main (void) { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_bsd_gethostbyname=yes else $as_nop ac_cv_lib_bsd_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 printf "%s\n" "$ac_cv_lib_bsd_gethostbyname" >&6; } if test "x$ac_cv_lib_bsd_gethostbyname" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" fi fi fi # lieder@skyler.mavd.honeywell.com says without -lsocket, # socket/setsockopt and other routines are undefined under SCO ODT # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary # on later versions), says Simon Leinen: it contains gethostby* # variants that don't use the name server (or something). -lsocket # must be given before -lnsl if both are needed. We assume that # if connect needs -lnsl, so does gethostbyname. ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" if test "x$ac_cv_func_connect" = xyes then : fi if test $ac_cv_func_connect = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 printf %s "checking for connect in -lsocket... " >&6; } if test ${ac_cv_lib_socket_connect+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char connect (); int main (void) { return connect (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_socket_connect=yes else $as_nop ac_cv_lib_socket_connect=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5 printf "%s\n" "$ac_cv_lib_socket_connect" >&6; } if test "x$ac_cv_lib_socket_connect" = xyes then : X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" fi fi # Guillermo Gomez says -lposix is necessary on A/UX. ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove" if test "x$ac_cv_func_remove" = xyes then : fi if test $ac_cv_func_remove = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5 printf %s "checking for remove in -lposix... " >&6; } if test ${ac_cv_lib_posix_remove+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lposix $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char remove (); int main (void) { return remove (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_posix_remove=yes else $as_nop ac_cv_lib_posix_remove=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5 printf "%s\n" "$ac_cv_lib_posix_remove" >&6; } if test "x$ac_cv_lib_posix_remove" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" fi fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat" if test "x$ac_cv_func_shmat" = xyes then : fi if test $ac_cv_func_shmat = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5 printf %s "checking for shmat in -lipc... " >&6; } if test ${ac_cv_lib_ipc_shmat+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lipc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char shmat (); int main (void) { return shmat (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_ipc_shmat=yes else $as_nop ac_cv_lib_ipc_shmat=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5 printf "%s\n" "$ac_cv_lib_ipc_shmat" >&6; } if test "x$ac_cv_lib_ipc_shmat" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" fi fi fi # Check for libraries that X11R6 Xt/Xaw programs need. ac_save_LDFLAGS=$LDFLAGS test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to # check for ICE first), but we must link in the order -lSM -lICE or # we get undefined symbols. So assume we have SM if we have ICE. # These have to be linked with before -lX11, unlike the other # libraries we check for below, so use a different variable. # John Interrante, Karl Berry { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5 printf %s "checking for IceConnectionNumber in -lICE... " >&6; } if test ${ac_cv_lib_ICE_IceConnectionNumber+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lICE $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char IceConnectionNumber (); int main (void) { return IceConnectionNumber (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_ICE_IceConnectionNumber=yes else $as_nop ac_cv_lib_ICE_IceConnectionNumber=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 printf "%s\n" "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes then : X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" fi LDFLAGS=$ac_save_LDFLAGS fi if test x$no_x = xyes then : as_fn_error $? "Configure could not find required X11 libraries, aborting." "$LINENO" 5 fi if test "x$X_PRE_LIBS" != x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring libraries \"$X_PRE_LIBS\" requested by configure." >&5 printf "%s\n" "$as_me: WARNING: Ignoring libraries \"$X_PRE_LIBS\" requested by configure." >&2;} fi LIBS="$LIBS -lX11 $X_EXTRA_LIBS" CFLAGS="$CFLAGS $X_CFLAGS" CXXFLAGS="$CXXFLAGS $X_CFLAGS" case $host_os in #( darwin*) : DARWIN_LDFLAGS="$LDFLAGS" ;; #( *) : ;; esac LDFLAGS="$X_LIBS $LDFLAGS" DSOFLAGS="$X_LIBS $DSOFLAGS" printf "%s\n" "#define FLTK_USE_X11 1" >>confdefs.h BUILD="X11" if test "x$x_includes" != x then : ac_cpp="$ac_cpp -I$x_includes" fi GLLIBS= if test x$enable_gl != xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 printf %s "checking for library containing dlopen... " >&6; } if test ${ac_cv_search_dlopen+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlopen (); int main (void) { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO" then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_dlopen+y} then : break fi done if test ${ac_cv_search_dlopen+y} then : else $as_nop ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 printf "%s\n" "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi ac_fn_c_check_header_compile "$LINENO" "GL/gl.h" "ac_cv_header_GL_gl_h" "$ac_includes_default" if test "x$ac_cv_header_GL_gl_h" = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for glXMakeCurrent in -lGL" >&5 printf %s "checking for glXMakeCurrent in -lGL... " >&6; } if test ${ac_cv_lib_GL_glXMakeCurrent+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lGL -lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char glXMakeCurrent (); int main (void) { return glXMakeCurrent (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_GL_glXMakeCurrent=yes else $as_nop ac_cv_lib_GL_glXMakeCurrent=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GL_glXMakeCurrent" >&5 printf "%s\n" "$ac_cv_lib_GL_glXMakeCurrent" >&6; } if test "x$ac_cv_lib_GL_glXMakeCurrent" = xyes then : printf "%s\n" "#define HAVE_GL 1" >>confdefs.h GLLIBS="-lGL" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for glXMakeCurrent in -lMesaGL" >&5 printf %s "checking for glXMakeCurrent in -lMesaGL... " >&6; } if test ${ac_cv_lib_MesaGL_glXMakeCurrent+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lMesaGL -lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char glXMakeCurrent (); int main (void) { return glXMakeCurrent (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_MesaGL_glXMakeCurrent=yes else $as_nop ac_cv_lib_MesaGL_glXMakeCurrent=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_MesaGL_glXMakeCurrent" >&5 printf "%s\n" "$ac_cv_lib_MesaGL_glXMakeCurrent" >&6; } if test "x$ac_cv_lib_MesaGL_glXMakeCurrent" = xyes then : printf "%s\n" "#define HAVE_GL 1" >>confdefs.h GLLIBS="-lMesaGL" fi , fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for glXGetProcAddressARB in -lGL" >&5 printf %s "checking for glXGetProcAddressARB in -lGL... " >&6; } if test ${ac_cv_lib_GL_glXGetProcAddressARB+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lGL -lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char glXGetProcAddressARB (); int main (void) { return glXGetProcAddressARB (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_GL_glXGetProcAddressARB=yes else $as_nop ac_cv_lib_GL_glXGetProcAddressARB=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GL_glXGetProcAddressARB" >&5 printf "%s\n" "$ac_cv_lib_GL_glXGetProcAddressARB" >&6; } if test "x$ac_cv_lib_GL_glXGetProcAddressARB" = xyes then : printf "%s\n" "#define HAVE_GLXGETPROCADDRESSARB 1" >>confdefs.h fi fi ac_fn_c_check_header_compile "$LINENO" "GL/glu.h" "ac_cv_header_GL_glu_h" "$ac_includes_default" if test "x$ac_cv_header_GL_glu_h" = xyes then : printf "%s\n" "#define HAVE_GL_GLU_H 1" >>confdefs.h if test x$ac_cv_lib_GL_glXMakeCurrent = xyes then : GLLIBS="-lGLU $GLLIBS" fi if test x$ac_cv_lib_MesaGL_glXMakeCurrent = xyes then : GLLIBS="-lMesaGLU $GLLIBS" fi fi if test x$ac_cv_lib_GL_glXMakeCurrent != xyes -a x$ac_cv_lib_MesaGL_glXMakeCurrent != xyes then : LINKFLTKGL="" GLLIBNAME="" GLDSONAME="" GLDEMOS="" fi else $as_nop LINKFLTKGL="" GLLIBNAME="" GLDSONAME="" GLDEMOS="" fi xinerama_found=no if test x$enable_xinerama != xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XineramaIsActive in -lXinerama" >&5 printf %s "checking for XineramaIsActive in -lXinerama... " >&6; } if test ${ac_cv_lib_Xinerama_XineramaIsActive+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXinerama $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XineramaIsActive (); int main (void) { return XineramaIsActive (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xinerama_XineramaIsActive=yes else $as_nop ac_cv_lib_Xinerama_XineramaIsActive=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xinerama_XineramaIsActive" >&5 printf "%s\n" "$ac_cv_lib_Xinerama_XineramaIsActive" >&6; } if test "x$ac_cv_lib_Xinerama_XineramaIsActive" = xyes then : printf "%s\n" "#define HAVE_XINERAMA 1" >>confdefs.h LIBS="-lXinerama $LIBS" xinerama_found=yes fi fi xft_found=no if test x$enable_xft != xno -a x$enable_wayland = xno then : # Try pkg-config first (freetype2 deprecated freetype-config from some version on) FT_FLAGS="" if test "x$PKGCONFIG" != x then : FT_FLAGS="$($PKGCONFIG --cflags xft)" if test "x$FT_FLAGS" = x then : FT_FLAGS="$($PKGCONFIG --cflags freetype2)" fi fi # if that failed, try freetype-config if test "x$FT_FLAGS" = x then : # Extract the first word of "freetype-config", so it can be a program name with args. set dummy freetype-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_FTCONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $FTCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_FTCONFIG="$FTCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_FTCONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi FTCONFIG=$ac_cv_path_FTCONFIG if test -n "$FTCONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FTCONFIG" >&5 printf "%s\n" "$FTCONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$FTCONFIG" != x then : FT_FLAGS="$($FTCONFIG --cflags)" else $as_nop # abort if both methods failed { printf "%s\n" "$as_me:${as_lineno-$LINENO}: please install pkg-config or use 'configure --disable-xft'." >&5 printf "%s\n" "$as_me: please install pkg-config or use 'configure --disable-xft'." >&6;} as_fn_error $? "Aborting." "$LINENO" 5 fi fi CPPFLAGS="$FT_FLAGS $CPPFLAGS" CXXFLAGS="$FT_FLAGS $CXXFLAGS" CFLAGS="$FT_FLAGS $CFLAGS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for FcPatternCreate in -lfontconfig" >&5 printf %s "checking for FcPatternCreate in -lfontconfig... " >&6; } if test ${ac_cv_lib_fontconfig_FcPatternCreate+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lfontconfig $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char FcPatternCreate (); int main (void) { return FcPatternCreate (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_fontconfig_FcPatternCreate=yes else $as_nop ac_cv_lib_fontconfig_FcPatternCreate=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fontconfig_FcPatternCreate" >&5 printf "%s\n" "$ac_cv_lib_fontconfig_FcPatternCreate" >&6; } if test "x$ac_cv_lib_fontconfig_FcPatternCreate" = xyes then : printf "%s\n" "#define HAVE_LIBFONTCONFIG 1" >>confdefs.h LIBS="-lfontconfig $LIBS" fi ac_fn_c_check_header_compile "$LINENO" "X11/Xft/Xft.h" "ac_cv_header_X11_Xft_Xft_h" "$ac_includes_default" if test "x$ac_cv_header_X11_Xft_Xft_h" = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XftDrawCreate in -lXft" >&5 printf %s "checking for XftDrawCreate in -lXft... " >&6; } if test ${ac_cv_lib_Xft_XftDrawCreate+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXft $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XftDrawCreate (); int main (void) { return XftDrawCreate (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xft_XftDrawCreate=yes else $as_nop ac_cv_lib_Xft_XftDrawCreate=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xft_XftDrawCreate" >&5 printf "%s\n" "$ac_cv_lib_Xft_XftDrawCreate" >&6; } if test "x$ac_cv_lib_Xft_XftDrawCreate" = xyes then : printf "%s\n" "#define USE_XFT 1" >>confdefs.h LIBS="-lXft $LIBS" BUILD="XFT" xft_found=yes fi fi fi if test x$enable_xft != xno -a x$xft_found != xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: could not find the required Xft headers and/or libraries." >&5 printf "%s\n" "$as_me: WARNING: could not find the required Xft headers and/or libraries." >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: please install Xft headers and libraries or use 'configure --disable-xft'." >&5 printf "%s\n" "$as_me: please install Xft headers and libraries or use 'configure --disable-xft'." >&6;} if test x$enable_xft = xyes then : as_fn_error $? "Aborting." "$LINENO" 5 fi fi if test x$enable_usecairo = xyes then : enable_pango=yes BUILD="CAIRO" printf "%s\n" "#define FLTK_USE_CAIRO 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Processing usecairo option" >&5 printf "%s\n" "$as_me: Processing usecairo option" >&6;} fi if test x$enable_pango = xyes -a x$xft_found = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: could not find the Xft headers and/or libraries required for Pango." >&5 printf "%s\n" "$as_me: WARNING: could not find the Xft headers and/or libraries required for Pango." >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: please install Xft headers and libraries or don't use configure with '--enable-pango'." >&5 printf "%s\n" "$as_me: please install Xft headers and libraries or don't use configure with '--enable-pango'." >&6;} as_fn_error $? "Aborting." "$LINENO" 5 fi pango_found=no if test x$enable_pango = xyes then : if test x$PKGCONFIG != x then : CXXFLAGS="$($PKGCONFIG --cflags pangocairo) $CXXFLAGS" case $host_os in #( darwin*) : ;; #( *) : CXXFLAGS="$($PKGCONFIG --cflags pangoxft) $CXXFLAGS" ;; #( *) : ;; esac case $host_os in #( darwin*) : DARWIN_SAVE_LIBS=$LIBS DARWIN_PANGO_LIBS="$($PKGCONFIG --libs pangocairo)" LIBS="$($PKGCONFIG --libs pangocairo) $LIBS" ;; #( *) : LIBS="$($PKGCONFIG --libs pangocairo --libs pangoxft) $LIBS" ;; #( *) : ;; esac else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --enable-pango: please install pkg-config. Continuing anyway." >&5 printf "%s\n" "$as_me: WARNING: --enable-pango: please install pkg-config. Continuing anyway." >&2;} fi CPPFLAGS="$CXXFLAGS" case $host_os in #( darwin*) : for ac_header in pango/pango.h do : ac_fn_c_check_header_compile "$LINENO" "pango/pango.h" "ac_cv_header_pango_pango_h" "$ac_includes_default" if test "x$ac_cv_header_pango_pango_h" = xyes then : printf "%s\n" "#define HAVE_PANGO_PANGO_H 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pango_layout_new in -lpango-1.0" >&5 printf %s "checking for pango_layout_new in -lpango-1.0... " >&6; } if test ${ac_cv_lib_pango_1_0_pango_layout_new+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpango-1.0 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char pango_layout_new (); int main (void) { return pango_layout_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_pango_1_0_pango_layout_new=yes else $as_nop ac_cv_lib_pango_1_0_pango_layout_new=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pango_1_0_pango_layout_new" >&5 printf "%s\n" "$ac_cv_lib_pango_1_0_pango_layout_new" >&6; } if test "x$ac_cv_lib_pango_1_0_pango_layout_new" = xyes then : printf "%s\n" "#define USE_PANGO 1" >>confdefs.h pango_found=yes LIBS=$DARWIN_SAVE_LIBS fi fi done ;; #( *) : for ac_header in pango/pango.h pango/pangoxft.h do : as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes" then : cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pango_layout_new in -lpango-1.0" >&5 printf %s "checking for pango_layout_new in -lpango-1.0... " >&6; } if test ${ac_cv_lib_pango_1_0_pango_layout_new+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpango-1.0 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char pango_layout_new (); int main (void) { return pango_layout_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_pango_1_0_pango_layout_new=yes else $as_nop ac_cv_lib_pango_1_0_pango_layout_new=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pango_1_0_pango_layout_new" >&5 printf "%s\n" "$ac_cv_lib_pango_1_0_pango_layout_new" >&6; } if test "x$ac_cv_lib_pango_1_0_pango_layout_new" = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pango_xft_render_layout in -lpangoxft-1.0" >&5 printf %s "checking for pango_xft_render_layout in -lpangoxft-1.0... " >&6; } if test ${ac_cv_lib_pangoxft_1_0_pango_xft_render_layout+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpangoxft-1.0 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char pango_xft_render_layout (); int main (void) { return pango_xft_render_layout (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_pangoxft_1_0_pango_xft_render_layout=yes else $as_nop ac_cv_lib_pangoxft_1_0_pango_xft_render_layout=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pangoxft_1_0_pango_xft_render_layout" >&5 printf "%s\n" "$ac_cv_lib_pangoxft_1_0_pango_xft_render_layout" >&6; } if test "x$ac_cv_lib_pangoxft_1_0_pango_xft_render_layout" = xyes then : printf "%s\n" "#define USE_PANGO 1" >>confdefs.h pango_found=yes fi fi fi done ;; #( *) : ;; esac if test x$pango_found != xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --enable-pango: Pango libs and/or headers could not be found." >&5 printf "%s\n" "$as_me: --enable-pango: Pango libs and/or headers could not be found." >&6;} as_fn_error $? "Aborting." "$LINENO" 5 fi fi xfixes_found=no if test x$enable_xfixes != xno then : ac_fn_c_check_header_compile "$LINENO" "X11/extensions/Xfixes.h" "ac_cv_header_X11_extensions_Xfixes_h" "#include " if test "x$ac_cv_header_X11_extensions_Xfixes_h" = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XFixesQueryExtension in -lXfixes" >&5 printf %s "checking for XFixesQueryExtension in -lXfixes... " >&6; } if test ${ac_cv_lib_Xfixes_XFixesQueryExtension+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXfixes $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XFixesQueryExtension (); int main (void) { return XFixesQueryExtension (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xfixes_XFixesQueryExtension=yes else $as_nop ac_cv_lib_Xfixes_XFixesQueryExtension=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xfixes_XFixesQueryExtension" >&5 printf "%s\n" "$ac_cv_lib_Xfixes_XFixesQueryExtension" >&6; } if test "x$ac_cv_lib_Xfixes_XFixesQueryExtension" = xyes then : printf "%s\n" "#define HAVE_XFIXES 1" >>confdefs.h LIBS="-lXfixes $LIBS" xfixes_found=yes fi fi fi xcursor_found=no if test x$enable_xcursor != xno then : ac_fn_c_check_header_compile "$LINENO" "X11/Xcursor/Xcursor.h" "ac_cv_header_X11_Xcursor_Xcursor_h" "#include " if test "x$ac_cv_header_X11_Xcursor_Xcursor_h" = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XcursorImageCreate in -lXcursor" >&5 printf %s "checking for XcursorImageCreate in -lXcursor... " >&6; } if test ${ac_cv_lib_Xcursor_XcursorImageCreate+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXcursor $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XcursorImageCreate (); int main (void) { return XcursorImageCreate (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xcursor_XcursorImageCreate=yes else $as_nop ac_cv_lib_Xcursor_XcursorImageCreate=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xcursor_XcursorImageCreate" >&5 printf "%s\n" "$ac_cv_lib_Xcursor_XcursorImageCreate" >&6; } if test "x$ac_cv_lib_Xcursor_XcursorImageCreate" = xyes then : printf "%s\n" "#define HAVE_XCURSOR 1" >>confdefs.h LIBS="-lXcursor $LIBS" xcursor_found=yes fi fi fi xrender_found=no if test x$enable_xrender != xno then : ac_fn_c_check_header_compile "$LINENO" "X11/extensions/Xrender.h" "ac_cv_header_X11_extensions_Xrender_h" "#include " if test "x$ac_cv_header_X11_extensions_Xrender_h" = xyes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XRenderQueryVersion in -lXrender" >&5 printf %s "checking for XRenderQueryVersion in -lXrender... " >&6; } if test ${ac_cv_lib_Xrender_XRenderQueryVersion+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXrender $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XRenderQueryVersion (); int main (void) { return XRenderQueryVersion (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xrender_XRenderQueryVersion=yes else $as_nop ac_cv_lib_Xrender_XRenderQueryVersion=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xrender_XRenderQueryVersion" >&5 printf "%s\n" "$ac_cv_lib_Xrender_XRenderQueryVersion" >&6; } if test "x$ac_cv_lib_Xrender_XRenderQueryVersion" = xyes then : printf "%s\n" "#define HAVE_XRENDER 1" >>confdefs.h LIBS="-lXrender $LIBS" xrender_found=yes fi fi fi case $host_os in #( darwin*) : if test x$pango_found = xyes then : #place X_LIBS after homebrew's pango libs LIBS="$DARWIN_PANGO_LIBS $X_LIBS $LIBS" #remove X_LIBS from LDFLAGS while keeping its initial content LDFLAGS="$DARWIN_LDFLAGS" fi ;; #( *) : ;; esac ac_fn_c_check_header_compile "$LINENO" "X11/Xregion.h" "ac_cv_header_X11_Xregion_h" "#include " if test "x$ac_cv_header_X11_Xregion_h" = xyes then : printf "%s\n" "#define HAVE_X11_XREGION_H 1" >>confdefs.h fi fi # Make symlinks since UNIX/Linux is case sensitive, # but Cygwin in general not. case $host_os in #( cygwin*) : HLINKS="#" ;; #( *) : ;; esac # Make symlinks since UNIX/Linux is case sensitive, # but only if explicitly configured (default=no) if test "x$with_links" != xyes then : HLINKS="#" fi # Install/Uninstall FLUID application support files INSTALL_DESKTOP="install-linux" UNINSTALL_DESKTOP="uninstall-linux" ;; #( *) : ;; esac case "$host_os" in #( *bsd* | darwin*) : # *BSD CAT1EXT=0 CAT3EXT=0 CAT6EXT=0 ;; #( irix*) : # SGI IRIX CAT1EXT=z CAT3EXT=z CAT6EXT=z ;; #( *) : # All others CAT1EXT=1 CAT3EXT=3 CAT6EXT=6 ;; #( *) : ;; esac if test "$mandir" = "\${prefix}/man" -a "$prefix" = "/usr" then : case "$host_os" in #( *bsd* | darwin* | linux*) : # *BSD, Darwin, and Linux mandir="\${prefix}/share/man" ;; #( irix*) : # SGI IRIX mandir="\${prefix}/share/catman" ;; #( *) : ;; esac fi if test "$prefix" = NONE then : prefix=/usr/local fi if test "$exec_prefix" = NONE then : exec_prefix="\${prefix}" fi case $host_os in #( irix1-5*) : ;; #( irix*) : if test "$libdir" = "\${exec_prefix}/lib" -a "$exec_prefix" = "\${prefix}" -a "$prefix" = "/usr" then : libdir="/usr/lib32" fi ;; #( *) : ;; esac MAKEDEPEND="\$(CXX) -M" if test -n "$GCC" then : # Show all standard warnings + unused variables, conversion errors, # and inlining problems when compiling... OPTIM="-Wall -Wunused -Wno-format-y2k $OPTIM" # The following additional warnings are useful for tracking down problems... #OPTIM="-Wshadow -Wconversion $OPTIM" # We know that Carbon is deprecated on OS X 10.4. To avoid hundreds of warnings # we will temporarily disable 'deprecated' warnings on OS X. case $host_os in #( darwin1-7) : ;; #( darwin*) : OPTIM="-Wno-deprecated-declarations $OPTIM" ;; #( *) : ;; esac # Set the default compiler optimizations... if test -z "$DEBUGFLAG" then : # # Note: Can't use -fomit-frame-pointer - prevents tools like # libsafe from working! # # Don't use -fforce-mem, -fforce-addr, or -fcaller-saves. # They all seem to make either no difference or enlarge # the code by a few hundred bytes. # # "-Os" seems to be the best compromise between speed and # code size. "-O3" and higher seem to make no effective # difference in the speed of the code, but does bloat the # library 10+%. # if test "x$with_optim" != x then : OPTIM="$with_optim $OPTIM" else $as_nop OPTIM="-Os $OPTIM" fi fi # Generate position-independent code when needed... if test $PICFLAG = 1 then : OPTIM="$OPTIM -fPIC" fi # See if GCC supports -fno-exceptions... { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if GCC supports -fno-exceptions" >&5 printf %s "checking if GCC supports -fno-exceptions... " >&6; } OLDCFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-exceptions" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : OPTIM="$OPTIM -fno-exceptions" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CFLAGS="$OLDCFLAGS" # See if GCC supports -fno-strict-aliasing... { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if GCC supports -fno-strict-aliasing" >&5 printf %s "checking if GCC supports -fno-strict-aliasing... " >&6; } OLDCFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-strict-aliasing" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : OPTIM="$OPTIM -fno-strict-aliasing" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CFLAGS="$OLDCFLAGS" # See if ld supports -no-undefined... { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if ld supports -no-undefined" >&5 printf %s "checking if ld supports -no-undefined... " >&6; } OLDLDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -Wl,-no-undefined" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : DSOFLAGS="$DSOFLAGS -Wl,-no-undefined" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$OLDLDFLAGS" # See if ld supports -Bsymbolic-functions... { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if ld supports -Bsymbolic-functions" >&5 printf %s "checking if ld supports -Bsymbolic-functions... " >&6; } OLDLDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -Wl,-Bsymbolic-functions" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : DSOFLAGS="$DSOFLAGS -Wl,-Bsymbolic-functions" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$OLDLDFLAGS" # See if toolchain supports a sectioned build... { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if toolchain supports sections" >&5 printf %s "checking if toolchain supports sections... " >&6; } OLDLDFLAGS="$LDFLAGS" OLDCFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS -Wl,-gc-sections" CFLAGS="$CFLAGS -ffunction-sections -fdata-sections" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : DSOFLAGS="$DSOFLAGS -Wl,-gc-sections" OPTIM="$OPTIM -ffunction-sections -fdata-sections" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$OLDLDFLAGS" CFLAGS="$OLDCFLAGS" # See if we are running Solaris; if so, try the -fpermissive option... # This option is required on some versions of Solaris to work around # bugs in the X headers up through Solaris 7. # # Unlike the other compiler/optimization settings, this one is placed # in CFLAGS and CXXFLAGS so that fltk-config will provide the option # to clients - otherwise client apps will not compile properly... case $host_os in #( solaris*) : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if GCC supports -fpermissive" >&5 printf %s "checking if GCC supports -fpermissive... " >&6; } OLDCFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fpermissive" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : CXXFLAGS="$CXXFLAGS -fpermissive" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop CFLAGS="$OLDCFLAGS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; #( *) : ;; esac else $as_nop case "$host_os" in #( irix*) : # Running some flavor of IRIX; see which version and # set things up according... if test "$uversion" -ge 62 then : # We are running IRIX 6.2 or higher; uncomment the following # lines if you don't have IDO 7.2 or higher: # # CXX="CC -n32 -mips3" # CC="cc -n32 -mips3" # LD="ld -n32 -mips3" # MAKEDEPEND="CC -M" if test "x`grep abi=n32 /etc/compiler.defaults`" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: FOR BEST RESULTS BEFORE COMPILING: setenv SGI_ABI \"-n32 -mips3\"" >&5 printf "%s\n" "$as_me: WARNING: FOR BEST RESULTS BEFORE COMPILING: setenv SGI_ABI \"-n32 -mips3\"" >&2;} fi OPTIM="-fullwarn $OPTIM" fi if test -z "$DEBUGFLAG" then : if test "x$with_optim" != x then : OPTIM="$with_optim $OPTIM" else $as_nop OPTIM="-O2 $OPTIM" if test $uversion -gt 62 then : OPTIM="-OPT:Olimit=4000 $OPTIM" fi fi fi ;; #( hpux*) : # Running HP-UX; these options should work for the HP compilers. if test -z "$DEBUGFLAG" then : if test "x$with_optim" != x then : OPTIM="$with_optim $OPTIM" else $as_nop OPTIM="+O2 $OPTIM" fi fi if test $PICFLAG = 1 then : OPTIM="+z $OPTIM" fi CXXFLAGS="$CXXFLAGS +W336,501,736,740,749,829" ;; #( OSF1*) : # Running Digital/Tru64 UNIX; these options should work for the # Digital/Compaq/NewHP compilers. if test -z "$DEBUGFLAG" then : if test "x$with_optim" != x then : OPTIM="$with_optim $OPTIM" else $as_nop OPTIM="-O2 $OPTIM" fi fi ;; #( solaris*) : # Solaris if test -z "$DEBUGFLAG" then : if test "x$with_optim" != x then : OPTIM="$with_optim $OPTIM" else $as_nop OPTIM="-xO3 $OPTIM" fi fi if test $PICFLAG = 1 then : OPTIM="-KPIC $OPTIM" fi ;; #( aix*) : if test -z "$DEBUGFLAG" then : if test "x$with_optim" != x then : OPTIM="$with_optim $OPTIM" else $as_nop OPTIM="-O2 $OPTIM" fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: The AIX C and C++ compilers are known not to correctly compile the FLTK library." >&5 printf "%s\n" "$as_me: WARNING: The AIX C and C++ compilers are known not to correctly compile the FLTK library." >&2;} ;; #( *) : # Running some other operating system; inform the user they # should contribute the necessary options via the STR form.. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Building FLTK with default compiler optimizations" >&5 printf "%s\n" "$as_me: WARNING: Building FLTK with default compiler optimizations" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Send the FLTK developers your uname and compiler options via https://www.fltk.org/bugs.php" >&5 printf "%s\n" "$as_me: WARNING: Send the FLTK developers your uname and compiler options via https://www.fltk.org/bugs.php" >&2;} ;; #( *) : ;; esac fi OPTIM="$DEBUGFLAG $OPTIM" case $host_os in #( darwin*) : if test "x$with_archflags" != x then : CFLAGS="$(echo $CFLAGS | sed -e 's/$with_archflags//g')" fi ;; #( *) : ;; esac case $host_os in #( mingw*) : # Determine the path where MSys has /usr installed msyspath="$(mount | grep '/usr ' | cut -d ' ' -f -1 | sed -e's,\\,/, g')" # Then substitute that in the Windows path instead of /usr printf "%s\n" "#define FLTK_DOCDIR \"$msyspath/local/share/doc/fltk\"" >>confdefs.h ;; #( *) : if test x$prefix = xNONE then : printf "%s\n" "#define FLTK_DOCDIR \"/usr/local/share/doc/fltk\"" >>confdefs.h else $as_nop printf "%s\n" "#define FLTK_DOCDIR \"$prefix/share/doc/fltk\"" >>confdefs.h fi ;; #( *) : ;; esac if test x$prefix = xNONE then : printf "%s\n" "#define FLTK_DATADIR \"/usr/local/share/fltk\"" >>confdefs.h else $as_nop printf "%s\n" "#define FLTK_DATADIR \"$prefix/share/fltk\"" >>confdefs.h fi echo "" echo "Configuration Summary" echo "-------------------------------------------------------------------------" case $host_os_gui in #( cygwin* | mingw*) : if test x$gdiplus_found = xyes then : graphics="GDI+" else $as_nop graphics="GDI" fi ;; #( darwin*) : graphics="Quartz" ;; #( *) : if test x$enable_wayland = xno then : graphics="X11" fi if test x$xft_found = xyes then : graphics="$graphics + Xft" fi if test x$xfixes_found = xyes then : graphics="$graphics + Xfixes" fi if test x$xinerama_found = xyes then : graphics="$graphics + Xinerama" fi if test x$xcursor_found = xyes then : graphics="$graphics + Xcursor" fi if test x$xrender_found = xyes then : graphics="$graphics + Xrender" fi if test x$enable_usecairo = xyes then : graphics="$graphics + Cairo" fi if test x$pango_found = xyes then : graphics="$graphics + Pango" fi ;; #( *) : ;; esac echo " Directories: prefix=$prefix" echo " bindir=$bindir" echo " datadir=$datadir" echo " datarootdir=$datarootdir" echo " exec_prefix=$exec_prefix" echo " includedir=$includedir" echo " libdir=$libdir" echo " mandir=$mandir" case $host_os in #( mingw*) : echo " MSys docpath=$msyspath/local/share/doc/fltk" ;; #( *) : ;; esac if test x$enable_fluid != xno then : echo " Build fluid: YES" else $as_nop echo " Build fluid: NO" fi if test x$enable_test != xno then : echo " Build tests: YES" else $as_nop echo " Build tests: NO" fi if test "$fltk_cross_compiling" = "yes" then : echo "Cross-compiling: YES" echo " Build: $build -> Host: $host" else $as_nop echo "Cross-compiling: NO" fi echo " Graphics: $graphics" if test x$JPEG = x then : echo "Image Libraries: JPEG=System" else $as_nop echo "Image Libraries: JPEG=Builtin" fi if test x$PNG = x then : echo " PNG=System" else $as_nop echo " PNG=Builtin" fi if test x$ZLIB = x then : echo " ZLIB=System" else $as_nop echo " ZLIB=Builtin" fi if test x$build_forms = xyes then : echo "Forms library: YES" else $as_nop echo "Forms library: NO" fi if test x$enable_cairo = xyes then : echo " CAIRO=lib" fi if test x$enable_cairoext = xyes then : echo " CAIRO=internal_use" fi if test x$enable_largefile != xno then : echo " Large Files: YES" else $as_nop echo " Large Files: NO" fi if test x$GLDEMOS = x then : echo " OpenGL: NO" else $as_nop echo " OpenGL: YES" fi if test x$THREADS = x then : echo " Threads: NO" else $as_nop echo " Threads: YES" fi if test x$enable_use_std != xyes then : echo " Allow std:: : NO" else $as_nop echo " Allow std:: : YES" fi BINARY_DIR= ac_config_headers="$ac_config_headers config.h:configh.in" ac_config_headers="$ac_config_headers FL/fl_config.h:fl_config.in" ac_config_files="$ac_config_files makeinclude fltk.list fltk-config fltk.spec FL/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by fltk $as_me 1.4.3, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to . fltk home page: ." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ fltk config.status 1.4.3 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" Copyright (C) 2021 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:configh.in" ;; "FL/fl_config.h") CONFIG_HEADERS="$CONFIG_HEADERS FL/fl_config.h:fl_config.in" ;; "makeinclude") CONFIG_FILES="$CONFIG_FILES makeinclude" ;; "fltk.list") CONFIG_FILES="$CONFIG_FILES fltk.list" ;; "fltk-config") CONFIG_FILES="$CONFIG_FILES fltk-config" ;; "fltk.spec") CONFIG_FILES="$CONFIG_FILES fltk.spec" ;; "FL/Makefile") CONFIG_FILES="$CONFIG_FILES FL/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi chmod +x fltk-config echo "" echo "-------------------------------------------------------------------------" echo " IMPORTANT NOTE:" echo "-------------------------------------------------------------------------" echo "" echo " FLTK 1.4.x will be the last version(s) of FLTK supporting" echo " autotools (configure + provided Makefiles) to build FLTK." echo " FLTK 1.5.0 and higher will only support FLTK builds using CMake." echo "" echo " We suggest to explore and use the CMake build system generators" echo " for your own FLTK builds as soon as possible. Some new FLTK build" echo " options will only be supported by CMake based builds." echo " Please see README.CMake.txt for details and instructions." echo "" echo " User projects that use CMake for their own build can benefit" echo " substantially if the FLTK library has been built using CMake." echo "" echo "-------------------------------------------------------------------------" echo "" fltk-1.4.3/fl_config.in0000644000175000017500000000336415004135251015071 0ustar albrechtalbrecht/* * Build configuration file for the Fast Light Tool Kit (FLTK). * * Copyright 1998-2024 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #ifndef _FL_fl_config_h_ #define _FL_fl_config_h_ /* * FL_ABI_VERSION (ABI version) * * define FL_ABI_VERSION: 1xxyy for 1.x.y (xx,yy with leading zero) */ #undef FL_ABI_VERSION /* * FLTK_HAVE_CAIRO * * Do we have the Cairo library available? */ #undef FLTK_HAVE_CAIRO /* * FLTK_HAVE_CAIROEXT * * Do we have the Cairo library available and want extended Cairo use in FLTK ? * This implies to link cairo.lib in all FLTK based apps. */ #undef FLTK_HAVE_CAIROEXT /* * FLTK_HAVE_FORMS * * Do we have the Forms compatibility library available? */ #undef FLTK_HAVE_FORMS /* * FLTK_USE_X11 * * Do we use X11 for the current platform? * */ #undef FLTK_USE_X11 /* * FLTK_USE_CAIRO * * Do we use Cairo to draw to the display? * */ #undef FLTK_USE_CAIRO /* * FLTK_USE_WAYLAND * * Do we use Wayland for the current platform? * */ #undef FLTK_USE_WAYLAND /* * FLTK_USE_STD * * May we use std::string and std::vector for the current build? * * This is a build configuration option which allows FLTK to add some * features based on std::string and std::vector in FLTK 1.4.x * */ #define FLTK_USE_STD 0 /* * FLTK_USE_SVG * * Do we want FLTK to read and write SVG-formatted files ? * */ #undef FLTK_USE_SVG #endif /* _FL_fl_config_h_ */ fltk-1.4.3/README.Wayland.txt0000644000175000017500000002430615004135251015706 0ustar albrechtalbrechtREADME.Wayland.txt - Wayland Platform Support for FLTK ------------------------------------------------------ Contents ======== 1 Introduction 2 Wayland Support for FLTK 2.1 Disabling Wayland for Backwards Compatibility 2.2 Configuration 2.3 Known Limitations 3 Platform Specific Notes 3.1 Debian and Derivatives (like Ubuntu, Mint, RaspberryPiOS) 3.2 Fedora 3.3 FreeBSD 1 Introduction ============== Version 1.4 of the FLTK library introduces support of the public FLTK API on the Wayland platform. It requires a Wayland-equipped OS, namely Linux or FreeBSD. Pre-existing platform-independent source code for FLTK 1.3.x should build and run unchanged with FLTK 1.4 and the Wayland platform. The code has been tested on Debian, Ubuntu, RaspberryPiOS and Fedora with 3 distinct Wayland compositors: Mutter (Gnome's compositor), Weston, and KWin. The code has also been tested under FreeBSD and the Sway Wayland compositor. CJK text-input methods, as well as dead and compose keys are supported. 2 Wayland Support for FLTK ========================== On Linux and FreeBSD systems, the FLTK library is by default configured so FLTK apps do all their windowing through the Wayland protocol, all their graphics with Cairo or EGL, and all text-drawing with Pango. If no Wayland compositor is available at run-time, FLTK apps fall back to using X11 for windowing. Cairo and Pango remain used for graphics and text, respectively. Environment variable FLTK_BACKEND can be used to control whether Wayland or X11 is used at run time as follows: - if FLTK_BACKEND is not defined, Wayland is used when possible, otherwise X11 is used; - if $FLTK_BACKEND equals "wayland", the library stops with error if no Wayland compositor is available; - if $FLTK_BACKEND equals "x11", the library uses X11 even if a Wayland compositor is available; - if $FLTK_BACKEND has another value, the library stops with error. On pure Wayland systems without the X11 headers and libraries, FLTK can be built with its Wayland backend only (see below). 2.1 Disabling Wayland for Backwards Compatibility --------------------------------------------------- Programs using X11 specific functions may need to disable the automatic detection of Wayland at runtime so they fall back to X11 only. It is possible to force a program linked to a Wayland-enabled FLTK library to use X11 in all situations by putting this declaration somewhere in the source code: FL_EXPORT bool fl_disable_wayland = true; FLTK source code and also X11-specific source code conceived for FLTK 1.3 should run with a Wayland-enabled FLTK 1.4 library with this single change. Note 1: this may require some linker flags to enable exporting symbols from *executable* programs which FLTK uses to "read" the global symbol 'fl_disable_wayland'. For GNU `ld` or any GNU compiler this would be "-rdynamic". Note 2: When building a user project with CMake 3.4 or higher, i.e. using cmake_minimum_required (VERSION 3.4) or any higher (minimum) CMake version users need to use at least one of the following techniques: Option 1: Set target property 'ENABLE_EXPORTS' on all executable targets that require to disable the Wayland backend. This is the preferred solution because it works per target. CMake example: set_target_properties(myprog PROPERTIES ENABLE_EXPORTS TRUE) Option 2: Set CMake policy CMP0065 to 'OLD' (i.e. pre-3.4 behavior) This is a quick solution but discouraged because setting CMake policies to 'OLD' is "deprecated by definition". CMake may issue warnings or ignore this in the future. CMake code: cmake_policy(SET CMP0065 OLD) Option 3: Set CMake variable 'CMAKE_ENABLE_EXPORTS' to 'TRUE'. Note: use this to be compatible with CMake < 3.27. Option 4: Set CMake variable 'CMAKE_EXECUTABLE_ENABLE_EXPORTS' to 'TRUE'. Note: new in CMake 3.27, ignored in older versions. Options 3 and 4 can be used as quick solutions like option 2 but these options affect all targets that are created while the CMake variable is set. As said above, option 1 should be preferred. This applies to the FLTK test and demo programs as well, hence we use option 1 in our build system. 2.2 Configuration ------------------ On Linux and FreeBSD systems equipped with the adequate software packages (see section 3 below), the default building procedure produces a Wayland/X11 hybrid library. On systems lacking all or part of Wayland-required packages, the default building procedure produces a X11-based library. Use "-D FLTK_BACKEND_WAYLAND=OFF" with CMake or "configure --disable-wayland" to build FLTK for the X11 library when the default would build for Wayland. CMake option FLTK_BACKEND_X11=OFF or configure argument "--disable-x11" can be used to produce a Wayland-only library which can be useful, e.g., when cross-compiling for systems that lack X11 headers and libraries. The FLTK Wayland platform uses a library called libdecor which handles window decorations (i.e., titlebars, shade). On very recent Linux distributions (e.g., Debian trixie) libdecor is available as Linux packages (libdecor-0-dev and libdecor-0-plugin-1-gtk). FLTK requires version 0.2.0 or more recent of these packages. When libdecor is not available or not recent enough, FLTK uses a copy of libdecor bundled in the FLTK source code. FLTK equipped with libdecor supports both the client-side decoration mode (CSD) and the server-side decoration mode (SSD) as determined by the active Wayland compositor. Mutter (gnome's Wayland compositor) and Weston use CSD mode, KWin and Sway use SSD mode. Furthermore, setting environment variable LIBDECOR_FORCE_CSD to 1 will make FLTK use CSD mode even if the compositor would have selected SSD mode. 2.3 Known Limitations ---------------------- * A deliberate design trait of Wayland makes application windows ignorant of their exact placement on screen. It's possible, though, to position a popup window relatively to another window. This allows FLTK to properly position menu and tooltip windows. But Fl_Window::position() has no effect on other top-level windows. * With Wayland, there is no way to know if a window is currently minimized, nor is there any way to programmatically unset minimization of a window. Consequently, Fl_Window::show() of a minimized window has no effect. * Although the FLTK API to read from and write to the system clipboard is fully functional, it's currently not possible for an app to be notified of changes to the content of the system clipboard, that is, Fl::add_clipboard_notify() has no effect. * Copying data to the clipboard is best done when the app has focus. Any copy operation performed when the app did not get the focus yet does not change the clipboard. A copy operation performed when the app has lost the focus is successful only if the type of the copied data, that is, text or image, is the same as the last data type copied when the app had the focus. * Narrow windows with a titlebar are silently forced to be wide enough for the titlebar to display window buttons and a few letters of the title. * Text input methods are known to work well for Chinese and Japanese. Feedback for other writing systems would be helpful. * Using OpenGL inside Wayland windows doesn't seem to work on RaspberryPi hardware, although it works inside X11 windows on the same hardware. * Drag-and-drop initiation from a subwindow doesn't work under the KDE/Plasma desktop. That is most probably a KWin bug because no such problem occurs with 3 other Wayland compositors (Mutter, Weston, Sway). A workaround is proposed in issue #997 of the FLTK github repository (https://github.com/fltk/fltk/issues/997). 3 Platform Specific Notes ========================= The following are notes about building FLTK for the Wayland platform on the various supported Linux distributions/OS. 3.1 Debian and Derivatives (like Ubuntu, Mint, RaspberryPiOS) ------------------------------------------------------------- Under Debian, the Wayland platform requires version 11 (a.k.a. Bullseye) or more recent. Under Ubuntu, the Wayland platform requires version 20.04 (focal fossa) or more recent. These packages are necessary to build the FLTK library, in addition to those listed in section 2.1 of file README.Unix.txt : - make - libpango1.0-dev - libwayland-dev - wayland-protocols - libxkbcommon-dev - libxinerama-dev <== except if option FLTK_BACKEND_X11=off is used - libdbus-1-dev <== recommended to query current cursor theme - libglew-dev <== necessary to use OpenGL version 3 or above - cmake <== if you plan to build with CMake - cmake-qt-gui <== if you plan to use the GUI of CMake - libdecor-0-dev <== recommended if available and if in version ≥ 0.2.0 - libgtk-3-dev <== highly recommended if libdecor-0-dev is not installed These packages allow to run FLTK apps under the Gnome-Wayland desktop: - gnome-core - libdecor-0-plugin-1-gtk <== install if libdecor-0-dev is installed These packages allow to run FLTK apps under the KDE/Plasma-Wayland desktop: - kde-plasma-desktop - plasma-workspace-wayland Package installation command: sudo apt-get install 3.2 Fedora ---------- The Wayland platform is known to work with Fedora version 35 or more recent. These packages are necessary to build the FLTK library, in addition to package groups listed in section 2.2 of file README.Unix.txt : - autoconf - wayland-devel - wayland-protocols-devel - cairo-devel - libxkbcommon-devel - pango-devel - mesa-libGLU-devel - dbus-devel <== recommended to query current cursor theme - libdecor-devel <== recommended, draws window titlebars - gtk3-devel <== highly recommended if libdecor-devel is not installed - glew-devel <== necessary to use OpenGL version 3 or above - cmake <== if you plan to build with CMake - cmake-gui <== if you plan to use the GUI of CMake Package installation command: sudo yum install 3.3 FreeBSD ----------- The Wayland platform is known to work with FreeBSD version 13.1 and the Sway compositor. These packages are necessary to build the FLTK library and use the Sway compositor: git autoconf pkgconf xorg urwfonts gnome glew seatd sway dmenu-wayland dmenu evdev-proto Package installation command: sudo pkg install fltk-1.4.3/README.abi-version.txt0000644000175000017500000000773415004135251016533 0ustar albrechtalbrechtConfiguration of the ABI Version for the Fast Light Toolkit (FLTK) ------------------------------------------------------------------ FLTK preserves the application binary interface (ABI) throughout patch versions, for instance all 1.4.x versions (x = patch version). This basically means that a program compiled and linked with FLTK 1.4.0 can run with a FLTK shared library (fltk.dll, fltk.so.1.4.x) of a later FLTK version 1.4.x, but not with a shared library of FLTK 1.5.0 or later. Since FLTK 1.3.1 the FLTK team began to introduce ABI-breaking features wrapped in so-called ABI guards in the library code, using a preprocessor macro. Since FLTK 1.4.0 the macro name is FL_ABI_VERSION: #if FL_ABI_VERSION >= 10401 ... new, ABI breaking code ... #else ... old, ABI preserving code ... #endif This documentation was written for FLTK 1.4.x but it applies to all later versions as well. Replace the version numbers given here with the version numbers of the version you are using. FLTK version 1.4.1 was chosen as an example only. How to Define the FLTK ABI Version ---------------------------------- To define the ABI version the preprocessor macro FL_ABI_VERSION must be defined as a number representing the ABI version in the form #define FL_ABI_VERSION 1xxyy where xx and yy are the minor and patch versions, resp. with leading zeroes, and '1' is the major version number. CMake generates the file FL/fl_config.h in the build folder given the version you select (see below). FLTK 1.4.x: see also below for how to select the ABI version with configure. For instance, the default ABI version for all FLTK 1.4.x versions is 10400 (the binary version of FLTK 1.4.0) but you can select another version, e.g. 10401 for FLTK 1.4.1 to enable the ABI features of FLTK 1.4.1 and all previous versions. The same applies to all higher FLTK versions. The default ABI version is always the lowest version (e.g. 10400). All following examples are written for FLTK 1.4.1, hence we use "10401" for the version number. Note: Since FLTK 1.4.3 (Git branch-1.4 after release 1.4.2) the highest selectable ABI version is FL_API_VERSION + 1 so you can use ABI features designated for the *next* FLTK release when using FLTK from Git with new ABI features included for the next release. How to select the ABI version with CMake ---------------------------------------- Use CMake to build the Makefile's and run 'make' or use any other CMake generator of your choice. To select the ABI version use one of the CMake configuration tools (cmake-gui or ccmake), or run CMake with these or similar commands: cd /path/to/fltk cmake . -B build [-G ] -D FLTK_ABI_VERSION:STRING=10401 The optional part '[-G ]' can be used to select a particular build tool that is not the default for the build platform, for instance '-G Ninja'. Further CMake options can be appended. Then execute cmake --build build or the selected build tool (-G ), e.g. `make`. For more information on how to use CMake with FLTK see README.CMake.txt. How to select the ABI version with configure (Unix, Linux, MinGW, MSYS, etc.) ----------------------------------------------------------------------------- Run make clean ./configure --with-abiversion=10401 make This will generate FL/fl_config.h and build FLTK as usual. Note: you should always make sure that you compile everything from scratch if you change the ABI version or any other configuration options, e.g. with `make clean'. General Note on CMake --------------------- CMake generates FL/fl_config.h in the build tree. You may run 'make install' to install the FLTK library including all headers in the chosen installation directory (set CMAKE_INSTALL_PREFIX to do this), although this is not necessary. The FLTK team recommends to use the FLTK library directly from the build folder. See README.CMake.txt for more information. fltk-1.4.3/share/0000755000175000017500000000000015004146477013723 5ustar albrechtalbrechtfltk-1.4.3/share/doc/0000755000175000017500000000000015004146502014455 5ustar albrechtalbrechtfltk-1.4.3/libdecor/0000755000175000017500000000000015004135251014370 5ustar albrechtalbrechtfltk-1.4.3/libdecor/LICENSE0000644000175000017500000000201415004135251015372 0ustar albrechtalbrechtMIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. fltk-1.4.3/libdecor/src/0000755000175000017500000000000015004135251015157 5ustar albrechtalbrechtfltk-1.4.3/libdecor/src/os-compatibility.h0000644000175000017500000000245415004135251020625 0ustar albrechtalbrecht/* * Copyright © 2012 Collabora, Ltd. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef OS_COMPATIBILITY_H #define OS_COMPATIBILITY_H #include int libdecor_os_create_anonymous_file(off_t size); #endif /* OS_COMPATIBILITY_H */ fltk-1.4.3/libdecor/src/libdecor.c0000644000175000017500000013247215004135251017117 0ustar albrechtalbrecht/* * Copyright © 2017-2018 Red Hat Inc. * Copyright © 2018 Jonas Ådahl * Copyright © 2019 Christian Rauch * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "config.h" #include #include #include #include #include #include #include "libdecor.h" #include "libdecor-fallback.h" #include "libdecor-plugin.h" #include "utils.h" #include "xdg-shell-client-protocol.h" #include "xdg-decoration-client-protocol.h" #ifdef HAVE_XDG_SHELL_V6 #define XDG_WM_BASE_VER 6 #else #define XDG_WM_BASE_VER 2 #endif struct libdecor { int ref_count; const struct libdecor_interface *iface; void *user_data; struct libdecor_plugin *plugin; bool plugin_ready; struct wl_display *wl_display; struct wl_registry *wl_registry; struct xdg_wm_base *xdg_wm_base; struct zxdg_decoration_manager_v1 *decoration_manager; struct wl_callback *init_callback; bool init_done; bool has_error; struct wl_list frames; }; struct libdecor_state { enum libdecor_window_state window_state; int content_width; int content_height; }; struct libdecor_limits { int min_width; int min_height; int max_width; int max_height; }; struct libdecor_configuration { uint32_t serial; bool has_window_state; enum libdecor_window_state window_state; bool has_size; int window_width; int window_height; }; struct libdecor_frame_private { int ref_count; struct libdecor *context; struct wl_surface *wl_surface; const struct libdecor_frame_interface *iface; void *user_data; struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; struct zxdg_toplevel_decoration_v1 *toplevel_decoration; bool pending_map; struct { char *app_id; char *title; struct libdecor_limits content_limits; struct xdg_toplevel *parent; } state; struct libdecor_configuration *pending_configuration; int content_width; int content_height; enum libdecor_window_state window_state; bool has_decoration_mode; enum zxdg_toplevel_decoration_v1_mode decoration_mode; enum libdecor_capabilities capabilities; enum libdecor_wm_capabilities wm_capabilities; /* original limits for interactive resize */ struct libdecor_limits interactive_limits; bool visible; }; struct libdecor_plugin_private { struct libdecor_plugin_interface *iface; }; /* gather all states at which a window is non-floating */ static const enum libdecor_window_state states_non_floating = LIBDECOR_WINDOW_STATE_MAXIMIZED | LIBDECOR_WINDOW_STATE_FULLSCREEN | LIBDECOR_WINDOW_STATE_TILED_LEFT | LIBDECOR_WINDOW_STATE_TILED_RIGHT | LIBDECOR_WINDOW_STATE_TILED_TOP | LIBDECOR_WINDOW_STATE_TILED_BOTTOM; static bool streql(const char *str1, const char *str2) { return (str1 && str2) && (strcmp(str1, str2) == 0); } static void do_map(struct libdecor_frame *frame); static bool state_is_floating(enum libdecor_window_state window_state) { return !(window_state & states_non_floating); } static void constrain_content_size(const struct libdecor_frame *frame, int *width, int *height) { const struct libdecor_limits lim = frame->priv->state.content_limits; if (lim.min_width > 0) *width = MAX(lim.min_width, *width); if (lim.max_width > 0) *width = MIN(*width, lim.max_width); if (lim.min_height > 0) *height = MAX(lim.min_height, *height); if (lim.max_height > 0) *height = MIN(*height, lim.max_height); } static bool frame_has_visible_client_side_decoration(struct libdecor_frame *frame) { /* visibility by client configuration */ const bool vis_client = frame->priv->visible; /* visibility by compositor configuration */ const bool vis_server = (frame->priv->decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE); return vis_client && vis_server; } LIBDECOR_EXPORT int libdecor_state_get_content_width(struct libdecor_state *state) { return state->content_width; } LIBDECOR_EXPORT int libdecor_state_get_content_height(struct libdecor_state *state) { return state->content_height; } LIBDECOR_EXPORT enum libdecor_window_state libdecor_state_get_window_state(struct libdecor_state *state) { return state->window_state; } LIBDECOR_EXPORT struct libdecor_state * libdecor_state_new(int width, int height) { struct libdecor_state *state; state = zalloc(sizeof *state); state->content_width = width; state->content_height = height; return state; } LIBDECOR_EXPORT void libdecor_state_free(struct libdecor_state *state) { free(state); } static struct libdecor_configuration * libdecor_configuration_new(void) { struct libdecor_configuration *configuration; configuration = zalloc(sizeof *configuration); return configuration; } static void libdecor_configuration_free(struct libdecor_configuration *configuration) { free(configuration); } static bool frame_get_window_size_for(struct libdecor_frame *frame, struct libdecor_state *state, int *window_width, int *window_height) { struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = context->plugin; *window_width = state->content_width; *window_height = state->content_height; if (frame_has_visible_client_side_decoration(frame) && plugin->priv->iface->frame_get_border_size) { int left, right, top, bottom; if (!plugin->priv->iface->frame_get_border_size( plugin, frame, NULL, &left, &right, &top, &bottom)) return false; *window_width += left + right; *window_height += top + bottom; } return true; } static void frame_set_window_geometry(struct libdecor_frame *frame, int32_t content_width, int32_t content_height) { struct libdecor_plugin *plugin = frame->priv->context->plugin; int x, y, width, height; int left, right, top, bottom; plugin->priv->iface->frame_get_border_size(plugin, frame, NULL, &left, &right, &top, &bottom); x = -left; y = -top; width = content_width + left + right; height = content_height + top + bottom; xdg_surface_set_window_geometry(frame->priv->xdg_surface, x, y, width, height); } LIBDECOR_EXPORT bool libdecor_configuration_get_content_size(struct libdecor_configuration *configuration, struct libdecor_frame *frame, int *width, int *height) { struct libdecor_plugin *plugin = frame->priv->context->plugin; /* get configured toplevel dimensions */ if (!configuration->has_size) return false; if (configuration->window_width == 0 || configuration->window_height == 0) return false; *width = configuration->window_width; *height = configuration->window_height; /* remove plugin-specific border size */ if (frame_has_visible_client_side_decoration(frame) && plugin->priv->iface->frame_get_border_size) { int left, right, top, bottom; /* Update window state for correct border size calculation */ frame->priv->window_state = configuration->window_state; if (!plugin->priv->iface->frame_get_border_size( plugin, frame, configuration, &left, &right, &top, &bottom)) return false; *width -= (left + right); *height -= (top + bottom); } /* constrain content dimensions manually */ if (state_is_floating(configuration->window_state)) { constrain_content_size(frame, width, height); } return true; } LIBDECOR_EXPORT bool libdecor_configuration_get_window_state(struct libdecor_configuration *configuration, enum libdecor_window_state *window_state) { if (!configuration->has_window_state) return false; *window_state = configuration->window_state; return true; } static void xdg_surface_configure(void *user_data, struct xdg_surface *xdg_surface, uint32_t serial) { struct libdecor_frame *frame = user_data; struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_configuration *configuration; configuration = frame_priv->pending_configuration; frame_priv->pending_configuration = NULL; if (!configuration) configuration = libdecor_configuration_new(); configuration->serial = serial; frame_priv->iface->configure(frame, configuration, frame_priv->user_data); libdecor_configuration_free(configuration); } static const struct xdg_surface_listener xdg_surface_listener = { xdg_surface_configure, }; static enum libdecor_window_state parse_states(struct wl_array *states) { enum libdecor_window_state pending_state = LIBDECOR_WINDOW_STATE_NONE; uint32_t *p; wl_array_for_each(p, states) { enum xdg_toplevel_state state = *p; switch (state) { case XDG_TOPLEVEL_STATE_FULLSCREEN: pending_state |= LIBDECOR_WINDOW_STATE_FULLSCREEN; break; case XDG_TOPLEVEL_STATE_MAXIMIZED: pending_state |= LIBDECOR_WINDOW_STATE_MAXIMIZED; break; case XDG_TOPLEVEL_STATE_ACTIVATED: pending_state |= LIBDECOR_WINDOW_STATE_ACTIVE; break; case XDG_TOPLEVEL_STATE_TILED_LEFT: pending_state |= LIBDECOR_WINDOW_STATE_TILED_LEFT; break; case XDG_TOPLEVEL_STATE_TILED_RIGHT: pending_state |= LIBDECOR_WINDOW_STATE_TILED_RIGHT; break; case XDG_TOPLEVEL_STATE_TILED_TOP: pending_state |= LIBDECOR_WINDOW_STATE_TILED_TOP; break; case XDG_TOPLEVEL_STATE_TILED_BOTTOM: pending_state |= LIBDECOR_WINDOW_STATE_TILED_BOTTOM; break; case XDG_TOPLEVEL_STATE_RESIZING: pending_state |= LIBDECOR_WINDOW_STATE_RESIZING; break; #ifdef HAVE_XDG_SHELL_V6 case XDG_TOPLEVEL_STATE_SUSPENDED: pending_state |= LIBDECOR_WINDOW_STATE_SUSPENDED; break; #endif default: break; } } return pending_state; } static void xdg_toplevel_configure(void *user_data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states) { struct libdecor_frame *frame = user_data; struct libdecor_frame_private *frame_priv = frame->priv; enum libdecor_window_state window_state; window_state = parse_states(states); frame_priv->pending_configuration = libdecor_configuration_new(); frame_priv->pending_configuration->has_size = true; frame_priv->pending_configuration->window_width = width; frame_priv->pending_configuration->window_height = height; frame_priv->pending_configuration->has_window_state = true; frame_priv->pending_configuration->window_state = window_state; } static void xdg_toplevel_close(void *user_data, struct xdg_toplevel *xdg_toplevel) { struct libdecor_frame *frame = user_data; struct libdecor_frame_private *frame_priv = frame->priv; frame_priv->iface->close(frame, frame_priv->user_data); } #ifdef HAVE_XDG_SHELL_V6 static void xdg_toplevel_configure_bounds(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height) { } static void xdg_toplevel_wm_capabilities(void *user_data, struct xdg_toplevel *xdg_toplevel, struct wl_array *capabilities) { struct libdecor_frame *frame = user_data; struct libdecor_frame_private *frame_priv = frame->priv; enum xdg_toplevel_wm_capabilities *wm_cap; frame_priv->wm_capabilities = 0; wl_array_for_each(wm_cap, capabilities) { switch (*wm_cap) { case XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU: frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_WINDOW_MENU; break; case XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE: frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MAXIMIZE; break; case XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN: frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_FULLSCREEN; break; case XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE: frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MINIMIZE; break; default: break; } } } #endif static const struct xdg_toplevel_listener xdg_toplevel_listener = { xdg_toplevel_configure, xdg_toplevel_close, #ifdef HAVE_XDG_SHELL_V6 xdg_toplevel_configure_bounds, xdg_toplevel_wm_capabilities, #endif }; static void toplevel_decoration_configure( void *data, struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, uint32_t mode) { struct libdecor_frame_private *frame_priv = (struct libdecor_frame_private *)data; /* Ignore any _configure calls after the first, they will be * from our set_mode call. */ if (!frame_priv->has_decoration_mode) { frame_priv->has_decoration_mode = true; frame_priv->decoration_mode = mode; } } static const struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration_listener = { toplevel_decoration_configure, }; void libdecor_frame_create_xdg_decoration(struct libdecor_frame_private *frame_priv) { if (!frame_priv->context->decoration_manager) return; frame_priv->toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( frame_priv->context->decoration_manager, frame_priv->xdg_toplevel); zxdg_toplevel_decoration_v1_add_listener( frame_priv->toplevel_decoration, &xdg_toplevel_decoration_listener, frame_priv); } static void init_shell_surface(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor *context = frame_priv->context; if (frame_priv->xdg_surface) return; frame_priv->xdg_surface = xdg_wm_base_get_xdg_surface(context->xdg_wm_base, frame_priv->wl_surface); xdg_surface_add_listener(frame_priv->xdg_surface, &xdg_surface_listener, frame); frame_priv->xdg_toplevel = xdg_surface_get_toplevel(frame_priv->xdg_surface); xdg_toplevel_add_listener(frame_priv->xdg_toplevel, &xdg_toplevel_listener, frame); frame_priv->decoration_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; frame_priv->toplevel_decoration = NULL; libdecor_frame_create_xdg_decoration(frame_priv); if (frame_priv->state.parent) { xdg_toplevel_set_parent(frame_priv->xdg_toplevel, frame_priv->state.parent); } if (frame_priv->state.title) { xdg_toplevel_set_title(frame_priv->xdg_toplevel, frame_priv->state.title); } if (frame_priv->state.app_id) { xdg_toplevel_set_app_id(frame_priv->xdg_toplevel, frame_priv->state.app_id); } if (frame_priv->pending_map) do_map(frame); } LIBDECOR_EXPORT struct libdecor_frame * libdecor_decorate(struct libdecor *context, struct wl_surface *wl_surface, const struct libdecor_frame_interface *iface, void *user_data) { struct libdecor_plugin *plugin = context->plugin; struct libdecor_frame *frame; struct libdecor_frame_private *frame_priv; if (context->has_error) return NULL; frame = plugin->priv->iface->frame_new(plugin); if (!frame) return NULL; frame_priv = zalloc(sizeof *frame_priv); frame->priv = frame_priv; frame_priv->ref_count = 1; frame_priv->context = context; frame_priv->wl_surface = wl_surface; frame_priv->iface = iface; frame_priv->user_data = user_data; frame_priv->wm_capabilities = LIBDECOR_WM_CAPABILITIES_WINDOW_MENU | LIBDECOR_WM_CAPABILITIES_MAXIMIZE | LIBDECOR_WM_CAPABILITIES_FULLSCREEN | LIBDECOR_WM_CAPABILITIES_MINIMIZE; wl_list_insert(&context->frames, &frame->link); libdecor_frame_set_capabilities(frame, LIBDECOR_ACTION_MOVE | LIBDECOR_ACTION_RESIZE | LIBDECOR_ACTION_MINIMIZE | LIBDECOR_ACTION_FULLSCREEN | LIBDECOR_ACTION_CLOSE); frame_priv->visible = true; if (context->init_done) init_shell_surface(frame); return frame; } LIBDECOR_EXPORT void libdecor_frame_ref(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; frame_priv->ref_count++; } LIBDECOR_EXPORT void libdecor_frame_unref(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; frame_priv->ref_count--; if (frame_priv->ref_count == 0) { struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = context->plugin; if (context->decoration_manager && frame_priv->toplevel_decoration) { zxdg_toplevel_decoration_v1_destroy(frame_priv->toplevel_decoration); frame_priv->toplevel_decoration = NULL; } wl_list_remove(&frame->link); if (frame_priv->xdg_toplevel) xdg_toplevel_destroy(frame_priv->xdg_toplevel); if (frame_priv->xdg_surface) xdg_surface_destroy(frame_priv->xdg_surface); plugin->priv->iface->frame_free(plugin, frame); free(frame_priv->state.title); free(frame_priv->state.app_id); free(frame_priv); free(frame); } } LIBDECOR_EXPORT void * libdecor_frame_get_user_data(struct libdecor_frame *frame) { return frame->priv->user_data; } LIBDECOR_EXPORT void libdecor_frame_set_user_data(struct libdecor_frame *frame, void *user_data) { frame->priv->user_data = user_data; } LIBDECOR_EXPORT void libdecor_frame_set_visibility(struct libdecor_frame *frame, bool visible) { struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = context->plugin; frame_priv->visible = visible; /* enable/disable decorations that are managed by the compositor. * Note that, as of xdg_decoration v1, this is just a hint and there is * no reliable way of disabling all decorations. In practice this should * work but per spec this is not guaranteed. * * See also: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/17 */ if (context->decoration_manager && frame_priv->toplevel_decoration && frame_priv->has_decoration_mode && frame_priv->decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) { zxdg_toplevel_decoration_v1_set_mode(frame_priv->toplevel_decoration, frame->priv->visible ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE); } /* enable/disable decorations that are managed by a plugin */ if (frame_has_visible_client_side_decoration(frame)) { /* show client-side decorations */ plugin->priv->iface->frame_commit(plugin, frame, NULL, NULL); } else { /* destroy client-side decorations */ plugin->priv->iface->frame_free(plugin, frame); } frame_set_window_geometry(frame, frame_priv->content_width, frame_priv->content_height); libdecor_frame_toplevel_commit(frame); } LIBDECOR_EXPORT bool libdecor_frame_is_visible(struct libdecor_frame *frame) { return frame->priv->visible; } LIBDECOR_EXPORT void libdecor_frame_set_parent(struct libdecor_frame *frame, struct libdecor_frame *parent) { struct libdecor_frame_private *frame_priv = frame->priv; if (!frame_priv->xdg_toplevel) return; frame_priv->state.parent = parent->priv->xdg_toplevel; xdg_toplevel_set_parent(frame_priv->xdg_toplevel, parent->priv->xdg_toplevel); } LIBDECOR_EXPORT void libdecor_frame_set_title(struct libdecor_frame *frame, const char *title) { struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor_plugin *plugin = frame_priv->context->plugin; if (!streql(frame_priv->state.title, title)) { free(frame_priv->state.title); frame_priv->state.title = strdup(title); if (!frame_priv->xdg_toplevel) return; xdg_toplevel_set_title(frame_priv->xdg_toplevel, title); plugin->priv->iface->frame_property_changed(plugin, frame); } } LIBDECOR_EXPORT const char * libdecor_frame_get_title(struct libdecor_frame *frame) { return frame->priv->state.title; } LIBDECOR_EXPORT void libdecor_frame_set_app_id(struct libdecor_frame *frame, const char *app_id) { struct libdecor_frame_private *frame_priv = frame->priv; free(frame_priv->state.app_id); frame_priv->state.app_id = strdup(app_id); if (!frame_priv->xdg_toplevel) return; xdg_toplevel_set_app_id(frame_priv->xdg_toplevel, app_id); } static void notify_on_capability_change(struct libdecor_frame *frame, const enum libdecor_capabilities old_capabilities) { struct libdecor_plugin *plugin = frame->priv->context->plugin; struct libdecor_state *state; if (frame->priv->capabilities == old_capabilities) return; if (frame->priv->content_width == 0 || frame->priv->content_height == 0) return; plugin->priv->iface->frame_property_changed(plugin, frame); if (!libdecor_frame_has_capability(frame, LIBDECOR_ACTION_RESIZE)) { frame->priv->interactive_limits = frame->priv->state.content_limits; /* set fixed window size */ libdecor_frame_set_min_content_size(frame, frame->priv->content_width, frame->priv->content_height); libdecor_frame_set_max_content_size(frame, frame->priv->content_width, frame->priv->content_height); } else { /* restore old limits */ frame->priv->state.content_limits = frame->priv->interactive_limits; } state = libdecor_state_new(frame->priv->content_width, frame->priv->content_height); libdecor_frame_commit(frame, state, NULL); libdecor_state_free(state); libdecor_frame_toplevel_commit(frame); } LIBDECOR_EXPORT void libdecor_frame_set_capabilities(struct libdecor_frame *frame, enum libdecor_capabilities capabilities) { const enum libdecor_capabilities old_capabilities = frame->priv->capabilities; frame->priv->capabilities |= capabilities; notify_on_capability_change(frame, old_capabilities); } LIBDECOR_EXPORT void libdecor_frame_unset_capabilities(struct libdecor_frame *frame, enum libdecor_capabilities capabilities) { const enum libdecor_capabilities old_capabilities = frame->priv->capabilities; frame->priv->capabilities &= ~capabilities; notify_on_capability_change(frame, old_capabilities); } LIBDECOR_EXPORT bool libdecor_frame_has_capability(struct libdecor_frame *frame, enum libdecor_capabilities capability) { return frame->priv->capabilities & capability; } LIBDECOR_EXPORT void libdecor_frame_popup_grab(struct libdecor_frame *frame, const char *seat_name) { struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = context->plugin; plugin->priv->iface->frame_popup_grab(plugin, frame, seat_name); } LIBDECOR_EXPORT void libdecor_frame_popup_ungrab(struct libdecor_frame *frame, const char *seat_name) { struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = context->plugin; plugin->priv->iface->frame_popup_ungrab(plugin, frame, seat_name); } LIBDECOR_EXPORT void libdecor_frame_dismiss_popup(struct libdecor_frame *frame, const char *seat_name) { struct libdecor_frame_private *frame_priv = frame->priv; frame_priv->iface->dismiss_popup(frame, seat_name, frame_priv->user_data); } LIBDECOR_EXPORT void libdecor_frame_show_window_menu(struct libdecor_frame *frame, struct wl_seat *wl_seat, uint32_t serial, int x, int y) { struct libdecor_frame_private *frame_priv = frame->priv; if (!frame_priv->xdg_toplevel) { fprintf(stderr, "Can't show window menu before being mapped\n"); return; } xdg_toplevel_show_window_menu(frame_priv->xdg_toplevel, wl_seat, serial, x, y); } LIBDECOR_EXPORT void libdecor_frame_translate_coordinate(struct libdecor_frame *frame, int content_x, int content_y, int *frame_x, int *frame_y) { struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = context->plugin; *frame_x = content_x; *frame_y = content_y; if (frame_has_visible_client_side_decoration(frame) && plugin->priv->iface->frame_get_border_size) { int left, top; plugin->priv->iface->frame_get_border_size(plugin, frame, NULL, &left, NULL, &top, NULL); *frame_x += left; *frame_y += top; } } LIBDECOR_EXPORT void libdecor_frame_set_min_content_size(struct libdecor_frame *frame, int content_width, int content_height) { struct libdecor_frame_private *frame_priv = frame->priv; frame_priv->state.content_limits.min_width = content_width; frame_priv->state.content_limits.min_height = content_height; } LIBDECOR_EXPORT void libdecor_frame_set_max_content_size(struct libdecor_frame *frame, int content_width, int content_height) { struct libdecor_frame_private *frame_priv = frame->priv; frame_priv->state.content_limits.max_width = content_width; frame_priv->state.content_limits.max_height = content_height; } LIBDECOR_EXPORT void libdecor_frame_get_min_content_size(const struct libdecor_frame *frame, int *content_width, int *content_height) { struct libdecor_frame_private *frame_priv = frame->priv; *content_width = frame_priv->state.content_limits.min_width; *content_height = frame_priv->state.content_limits.min_height; } LIBDECOR_EXPORT void libdecor_frame_get_max_content_size(const struct libdecor_frame *frame, int *content_width, int *content_height) { struct libdecor_frame_private *frame_priv = frame->priv; *content_width = frame_priv->state.content_limits.max_width; *content_height = frame_priv->state.content_limits.max_height; } LIBDECOR_EXPORT enum libdecor_capabilities libdecor_frame_get_capabilities(const struct libdecor_frame *frame) { return frame->priv->capabilities; } enum xdg_toplevel_resize_edge edge_to_xdg_edge(enum libdecor_resize_edge edge) { switch (edge) { case LIBDECOR_RESIZE_EDGE_NONE: return XDG_TOPLEVEL_RESIZE_EDGE_NONE; case LIBDECOR_RESIZE_EDGE_TOP: return XDG_TOPLEVEL_RESIZE_EDGE_TOP; case LIBDECOR_RESIZE_EDGE_BOTTOM: return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; case LIBDECOR_RESIZE_EDGE_LEFT: return XDG_TOPLEVEL_RESIZE_EDGE_LEFT; case LIBDECOR_RESIZE_EDGE_TOP_LEFT: return XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; case LIBDECOR_RESIZE_EDGE_BOTTOM_LEFT: return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; case LIBDECOR_RESIZE_EDGE_RIGHT: return XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; case LIBDECOR_RESIZE_EDGE_TOP_RIGHT: return XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; case LIBDECOR_RESIZE_EDGE_BOTTOM_RIGHT: return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; } abort(); } LIBDECOR_EXPORT void libdecor_frame_resize(struct libdecor_frame *frame, struct wl_seat *wl_seat, uint32_t serial, enum libdecor_resize_edge edge) { struct libdecor_frame_private *frame_priv = frame->priv; enum xdg_toplevel_resize_edge xdg_edge; xdg_edge = edge_to_xdg_edge(edge); xdg_toplevel_resize(frame_priv->xdg_toplevel, wl_seat, serial, xdg_edge); } LIBDECOR_EXPORT void libdecor_frame_move(struct libdecor_frame *frame, struct wl_seat *wl_seat, uint32_t serial) { struct libdecor_frame_private *frame_priv = frame->priv; xdg_toplevel_move(frame_priv->xdg_toplevel, wl_seat, serial); } LIBDECOR_EXPORT void libdecor_frame_set_minimized(struct libdecor_frame *frame) { xdg_toplevel_set_minimized(frame->priv->xdg_toplevel); } LIBDECOR_EXPORT void libdecor_frame_set_maximized(struct libdecor_frame *frame) { xdg_toplevel_set_maximized(frame->priv->xdg_toplevel); } LIBDECOR_EXPORT void libdecor_frame_unset_maximized(struct libdecor_frame *frame) { xdg_toplevel_unset_maximized(frame->priv->xdg_toplevel); } LIBDECOR_EXPORT void libdecor_frame_set_fullscreen(struct libdecor_frame *frame, struct wl_output *output) { xdg_toplevel_set_fullscreen(frame->priv->xdg_toplevel, output); } LIBDECOR_EXPORT void libdecor_frame_unset_fullscreen(struct libdecor_frame *frame) { xdg_toplevel_unset_fullscreen(frame->priv->xdg_toplevel); } LIBDECOR_EXPORT bool libdecor_frame_is_floating(struct libdecor_frame *frame) { return state_is_floating(frame->priv->window_state); } LIBDECOR_EXPORT void libdecor_frame_close(struct libdecor_frame *frame) { xdg_toplevel_close(frame, frame->priv->xdg_toplevel); } bool valid_limits(struct libdecor_frame_private *frame_priv) { if (frame_priv->state.content_limits.min_width > 0 && frame_priv->state.content_limits.max_width > 0 && frame_priv->state.content_limits.min_width > frame_priv->state.content_limits.max_width) return false; if (frame_priv->state.content_limits.min_height > 0 && frame_priv->state.content_limits.max_height > 0 && frame_priv->state.content_limits.min_height > frame_priv->state.content_limits.max_height) return false; return true; } static void libdecor_frame_apply_limits(struct libdecor_frame *frame, enum libdecor_window_state window_state) { struct libdecor_frame_private *frame_priv = frame->priv; if (!valid_limits(frame_priv)) { libdecor_notify_plugin_error( frame_priv->context, LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION, "minimum size (%i,%i) must be smaller than maximum size (%i,%i)", frame_priv->state.content_limits.min_width, frame_priv->state.content_limits.min_height, frame_priv->state.content_limits.max_width, frame_priv->state.content_limits.max_height); } /* If the frame is configured as non-resizable before the first * configure event is received, we have to manually set the min/max * limits with the configured content size afterwards. */ if (!libdecor_frame_has_capability(frame, LIBDECOR_ACTION_RESIZE)) { frame_priv->state.content_limits.min_width = frame_priv->content_width; frame_priv->state.content_limits.max_width = frame_priv->content_width; frame_priv->state.content_limits.min_height = frame_priv->content_height; frame_priv->state.content_limits.max_height = frame_priv->content_height; } if (frame_priv->state.content_limits.min_width > 0 && frame_priv->state.content_limits.min_height > 0) { struct libdecor_state state_min; int win_min_width, win_min_height; state_min.content_width = frame_priv->state.content_limits.min_width; state_min.content_height = frame_priv->state.content_limits.min_height; state_min.window_state = window_state; frame_get_window_size_for(frame, &state_min, &win_min_width, &win_min_height); xdg_toplevel_set_min_size(frame_priv->xdg_toplevel, win_min_width, win_min_height); } else { xdg_toplevel_set_min_size(frame_priv->xdg_toplevel, 0, 0); } if (frame_priv->state.content_limits.max_width > 0 && frame_priv->state.content_limits.max_height > 0) { struct libdecor_state state_max; int win_max_width, win_max_height; state_max.content_width = frame_priv->state.content_limits.max_width; state_max.content_height = frame_priv->state.content_limits.max_height; state_max.window_state = window_state; frame_get_window_size_for(frame, &state_max, &win_max_width, &win_max_height); xdg_toplevel_set_max_size(frame_priv->xdg_toplevel, win_max_width, win_max_height); } else { xdg_toplevel_set_max_size(frame_priv->xdg_toplevel, 0, 0); } } static void libdecor_frame_apply_state(struct libdecor_frame *frame, struct libdecor_state *state) { struct libdecor_frame_private *frame_priv = frame->priv; frame_priv->content_width = state->content_width; frame_priv->content_height = state->content_height; /* do not set limits in non-floating states */ if (state_is_floating(state->window_state)) { libdecor_frame_apply_limits(frame, state->window_state); } } LIBDECOR_EXPORT void libdecor_frame_toplevel_commit(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; frame_priv->iface->commit(frame, frame_priv->user_data); } LIBDECOR_EXPORT void libdecor_frame_commit(struct libdecor_frame *frame, struct libdecor_state *state, struct libdecor_configuration *configuration) { struct libdecor_frame_private *frame_priv = frame->priv; struct libdecor *context = frame_priv->context; struct libdecor_plugin *plugin = context->plugin; if (configuration && configuration->has_window_state) { frame_priv->window_state = configuration->window_state; state->window_state = configuration->window_state; } else { state->window_state = frame_priv->window_state; } libdecor_frame_apply_state(frame, state); /* switch between decoration modes */ if (frame_has_visible_client_side_decoration(frame)) { plugin->priv->iface->frame_commit(plugin, frame, state, configuration); } else { plugin->priv->iface->frame_free(plugin, frame); } frame_set_window_geometry(frame, frame_priv->content_width, frame_priv->content_height); if (configuration) { xdg_surface_ack_configure(frame_priv->xdg_surface, configuration->serial); } } static void do_map(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; frame_priv->pending_map = false; wl_surface_commit(frame_priv->wl_surface); } LIBDECOR_EXPORT void libdecor_frame_map(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; if (!frame_priv->xdg_surface) { frame_priv->pending_map = true; return; } do_map(frame); } LIBDECOR_EXPORT struct wl_surface * libdecor_frame_get_wl_surface(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; return frame_priv->wl_surface; } LIBDECOR_EXPORT struct xdg_surface * libdecor_frame_get_xdg_surface(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; return frame_priv->xdg_surface; } LIBDECOR_EXPORT struct xdg_toplevel * libdecor_frame_get_xdg_toplevel(struct libdecor_frame *frame) { return frame->priv->xdg_toplevel; } LIBDECOR_EXPORT int libdecor_frame_get_content_width(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; return frame_priv->content_width; } LIBDECOR_EXPORT int libdecor_frame_get_content_height(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; return frame_priv->content_height; } LIBDECOR_EXPORT enum libdecor_window_state libdecor_frame_get_window_state(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; return frame_priv->window_state; } LIBDECOR_EXPORT enum libdecor_wm_capabilities libdecor_frame_get_wm_capabilities(struct libdecor_frame *frame) { struct libdecor_frame_private *frame_priv = frame->priv; return frame_priv->wm_capabilities; } LIBDECOR_EXPORT int libdecor_plugin_init(struct libdecor_plugin *plugin, struct libdecor *context, struct libdecor_plugin_interface *iface) { plugin->priv = zalloc(sizeof (struct libdecor_plugin_private)); if (!plugin->priv) return -1; plugin->priv->iface = iface; return 0; } LIBDECOR_EXPORT void libdecor_plugin_release(struct libdecor_plugin *plugin) { free(plugin->priv); } static void xdg_wm_base_ping(void *user_data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) { xdg_wm_base_pong(xdg_wm_base, serial); } static const struct xdg_wm_base_listener xdg_wm_base_listener = { xdg_wm_base_ping, }; static void init_xdg_wm_base(struct libdecor *context, uint32_t id, uint32_t version) { context->xdg_wm_base = wl_registry_bind(context->wl_registry, id, &xdg_wm_base_interface, MIN(version,XDG_WM_BASE_VER)); xdg_wm_base_add_listener(context->xdg_wm_base, &xdg_wm_base_listener, context); } static void registry_handle_global(void *user_data, struct wl_registry *wl_registry, uint32_t id, const char *interface, uint32_t version) { struct libdecor *context = user_data; if (!strcmp(interface, xdg_wm_base_interface.name)) { init_xdg_wm_base(context, id, version); } else if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name)) { const char *force_csd = getenv("LIBDECOR_FORCE_CSD"); if (force_csd && atoi(force_csd)) { return; } context->decoration_manager = wl_registry_bind( context->wl_registry, id, &zxdg_decoration_manager_v1_interface, MIN(version,2)); } } static void registry_handle_global_remove(void *user_data, struct wl_registry *wl_registry, uint32_t name) { } static const struct wl_registry_listener registry_listener = { registry_handle_global, registry_handle_global_remove }; static bool is_compositor_compatible(struct libdecor *context) { if (!context->xdg_wm_base) return false; return true; } static void notify_error(struct libdecor *context, enum libdecor_error error, const char *message) { context->has_error = true; context->iface->error(context, error, message); context->plugin->priv->iface->destroy(context->plugin); } static void finish_init(struct libdecor *context) { struct libdecor_frame *frame; wl_list_for_each(frame, &context->frames, link) init_shell_surface(frame); } static void init_wl_display_callback(void *user_data, struct wl_callback *callback, uint32_t time) { struct libdecor *context = user_data; context->init_done = true; wl_callback_destroy(callback); context->init_callback = NULL; if (!is_compositor_compatible(context)) { notify_error(context, LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE, "Compositor is missing required interfaces"); } if (context->plugin_ready) { finish_init(context); } } static const struct wl_callback_listener init_wl_display_callback_listener = { init_wl_display_callback }; struct plugin_loader { struct wl_list link; void *lib; const struct libdecor_plugin_description *description; int priority; char *name; }; static int calculate_priority(const struct libdecor_plugin_description *plugin_description) { const char *current_desktop; int i; if (!plugin_description->priorities) return -1; current_desktop = getenv("XDG_CURRENT_DESKTOP"); i = 0; while (true) { struct libdecor_plugin_priority priority = plugin_description->priorities[i]; i++; if (priority.desktop) { char *tokens; char *saveptr; char *token; if (!current_desktop) continue; tokens = strdup(current_desktop); token = strtok_r(tokens, ":", &saveptr); while (token) { if (strcmp(priority.desktop, token) == 0) { free(tokens); return priority.priority; } token = strtok_r(NULL, ":", &saveptr); } free(tokens); } else { return priority.priority; } } return -1; } static bool check_symbol_conflicts(const struct libdecor_plugin_description *plugin_description, void *lib) { char * const *symbol; symbol = plugin_description->conflicting_symbols; while (*symbol) { dlerror(); void *sym = dlsym(RTLD_DEFAULT, *symbol); if (!dlerror()) { void *libsym = dlsym(lib, *symbol); if (!dlerror() && libsym != sym) { fprintf(stderr, "Plugin \"%s\" uses conflicting symbol \"%s\".\n", plugin_description->description, *symbol); return false; } } symbol++; } return true; } static struct plugin_loader * load_plugin_loader(struct libdecor *context, const char *path, const char *name) { char *ext; char *filename; void *lib; const struct libdecor_plugin_description *plugin_description; int priority; struct plugin_loader *plugin_loader; ext = strrchr(name, '.'); if (ext == NULL || strcmp(ext, ".so") != 0) return NULL; if (asprintf(&filename, "%s/%s", path, name) == -1) return NULL; lib = dlopen(filename, RTLD_NOW | RTLD_LAZY); free(filename); if (!lib) { fprintf(stderr, "Failed to load plugin: '%s'\n", dlerror()); return NULL; } plugin_description = dlsym(lib, "libdecor_plugin_description"); if (!plugin_description) { fprintf(stderr, "Failed to load plugin '%s': no plugin description symbol\n", name); dlclose(lib); return NULL; } if (plugin_description->api_version != LIBDECOR_PLUGIN_API_VERSION) { fprintf(stderr, "Plugin '%s' found, but it's incompatible " "(expected API version %d, but got %d)\n", name, LIBDECOR_PLUGIN_API_VERSION, plugin_description->api_version); dlclose(lib); return NULL; } if (!(plugin_description->capabilities & LIBDECOR_PLUGIN_CAPABILITY_BASE)) { dlclose(lib); return NULL; } if (!check_symbol_conflicts(plugin_description, lib)) { dlclose(lib); return NULL; } priority = calculate_priority(plugin_description); if (priority == -1) { fprintf(stderr, "Plugin '%s' found, but has an invalid description\n", name); dlclose(lib); return NULL; } plugin_loader = zalloc(sizeof *plugin_loader); plugin_loader->description = plugin_description; plugin_loader->lib = lib; plugin_loader->priority = priority; plugin_loader->name = strdup(name); return plugin_loader; } static bool plugin_loader_higher_priority(struct plugin_loader *plugin_loader, struct plugin_loader *best_plugin_loader) { return plugin_loader->priority > best_plugin_loader->priority; } static int init_plugins(struct libdecor *context) { const char *plugin_dir_env; char *all_plugin_dirs; char *plugin_dir; char *saveptr; DIR *dir; struct wl_list plugin_loaders; struct plugin_loader *plugin_loader, *tmp; struct plugin_loader *best_plugin_loader; struct libdecor_plugin *plugin; plugin_dir_env = getenv("LIBDECOR_PLUGIN_DIR"); if (!plugin_dir_env) { plugin_dir_env = LIBDECOR_PLUGIN_DIR; } all_plugin_dirs = strdup(plugin_dir_env); wl_list_init(&plugin_loaders); plugin_dir = strtok_r(all_plugin_dirs, ":", &saveptr); while (plugin_dir) { dir = opendir(plugin_dir); if (!dir) { fprintf(stderr, "Couldn't open plugin directory: %s\n", strerror(errno)); } else { while (true) { struct dirent *de; de = readdir(dir); if (!de) break; plugin_loader = load_plugin_loader(context, plugin_dir, de->d_name); if (!plugin_loader) continue; wl_list_insert(plugin_loaders.prev, &plugin_loader->link); } closedir(dir); } plugin_dir = strtok_r(NULL, ":", &saveptr); } free(all_plugin_dirs); retry_next: best_plugin_loader = NULL; wl_list_for_each(plugin_loader, &plugin_loaders, link) { if (!best_plugin_loader) { best_plugin_loader = plugin_loader; continue; } if (plugin_loader_higher_priority(plugin_loader, best_plugin_loader)) best_plugin_loader = plugin_loader; } if (!best_plugin_loader) return -1; plugin_loader = best_plugin_loader; plugin = plugin_loader->description->constructor(context); if (!plugin) { fprintf(stderr, "Failed to load plugin '%s': failed to init\n", plugin_loader->name); dlclose(plugin_loader->lib); wl_list_remove(&plugin_loader->link); free(plugin_loader->name); free(plugin_loader); goto retry_next; } context->plugin = plugin; wl_list_remove(&plugin_loader->link); free(plugin_loader->name); free(plugin_loader); wl_list_for_each_safe(plugin_loader, tmp, &plugin_loaders, link) { dlclose(plugin_loader->lib); free(plugin_loader->name); free(plugin_loader); } return 0; } LIBDECOR_EXPORT void * libdecor_get_user_data(struct libdecor *context) { return context->user_data; } LIBDECOR_EXPORT void libdecor_set_user_data(struct libdecor *context, void *user_data) { context->user_data = user_data; } LIBDECOR_EXPORT int libdecor_get_fd(struct libdecor *context) { struct libdecor_plugin *plugin = context->plugin; return plugin->priv->iface->get_fd(plugin); } LIBDECOR_EXPORT int libdecor_dispatch(struct libdecor *context, int timeout) { struct libdecor_plugin *plugin = context->plugin; return plugin->priv->iface->dispatch(plugin, timeout); } LIBDECOR_EXPORT struct wl_display * libdecor_get_wl_display(struct libdecor *context) { return context->wl_display; } LIBDECOR_EXPORT void libdecor_notify_plugin_ready(struct libdecor *context) { context->plugin_ready = true; if (context->init_done) finish_init(context); } LIBDECOR_EXPORT void libdecor_notify_plugin_error(struct libdecor *context, enum libdecor_error error, const char *__restrict fmt, ...) { char *msg = NULL; int nbytes = 0; va_list argp; if (context->has_error) return; va_start(argp, fmt); nbytes = vasprintf(&msg, fmt, argp); va_end(argp); if (nbytes>0) notify_error(context, error, msg); if (msg) free(msg); } LIBDECOR_EXPORT void libdecor_unref(struct libdecor *context) { context->ref_count--; if (context->ref_count == 0) { if (context->plugin) context->plugin->priv->iface->destroy(context->plugin); if (context->init_callback) wl_callback_destroy(context->init_callback); wl_registry_destroy(context->wl_registry); if (context->xdg_wm_base) xdg_wm_base_destroy(context->xdg_wm_base); if (context->decoration_manager) zxdg_decoration_manager_v1_destroy( context->decoration_manager); free(context); } } LIBDECOR_EXPORT struct libdecor * libdecor_new(struct wl_display *wl_display, const struct libdecor_interface *iface) { return libdecor_new_with_user_data(wl_display, iface, NULL); } LIBDECOR_EXPORT struct libdecor * libdecor_new_with_user_data(struct wl_display *wl_display, const struct libdecor_interface *iface, void *user_data) { struct libdecor *context; context = zalloc(sizeof *context); context->ref_count = 1; context->iface = iface; context->user_data = user_data; context->wl_display = wl_display; context->wl_registry = wl_display_get_registry(wl_display); wl_registry_add_listener(context->wl_registry, ®istry_listener, context); context->init_callback = wl_display_sync(context->wl_display); wl_callback_add_listener(context->init_callback, &init_wl_display_callback_listener, context); wl_list_init(&context->frames); if (init_plugins(context) != 0) { fprintf(stderr, "No plugins found, falling back on no decorations\n"); context->plugin = libdecor_fallback_plugin_new(context); } wl_display_flush(wl_display); return context; } fltk-1.4.3/libdecor/src/desktop-settings.c0000644000175000017500000001151715004135251020637 0ustar albrechtalbrecht/* * Copyright © 2019 Christian Rauch * Copyright © 2024 Colin Kinloch * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "desktop-settings.h" #include #include #include #include #include "config.h" static bool get_cursor_settings_from_env(char **theme, int *size) { char *env_xtheme; char *env_xsize; env_xtheme = getenv("XCURSOR_THEME"); if (env_xtheme != NULL) *theme = strdup(env_xtheme); env_xsize = getenv("XCURSOR_SIZE"); if (env_xsize != NULL) *size = atoi(env_xsize); return env_xtheme != NULL && env_xsize != NULL; } #ifdef HAS_DBUS #include static DBusMessage * get_setting_sync(DBusConnection *const connection, const char *key, const char *value) { DBusError error; dbus_bool_t success; DBusMessage *message; DBusMessage *reply; message = dbus_message_new_method_call( "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop", "org.freedesktop.portal.Settings", "Read"); success = dbus_message_append_args(message, DBUS_TYPE_STRING, &key, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID); if (!success) return NULL; dbus_error_init(&error); reply = dbus_connection_send_with_reply_and_block( connection, message, DBUS_TIMEOUT_USE_DEFAULT, &error); dbus_message_unref(message); if (dbus_error_is_set(&error)) { dbus_error_free(&error); return NULL; } dbus_error_free(&error); return reply; } static bool parse_type(DBusMessage *const reply, const int type, void *value) { DBusMessageIter iter[3]; dbus_message_iter_init(reply, &iter[0]); if (dbus_message_iter_get_arg_type(&iter[0]) != DBUS_TYPE_VARIANT) return false; dbus_message_iter_recurse(&iter[0], &iter[1]); if (dbus_message_iter_get_arg_type(&iter[1]) != DBUS_TYPE_VARIANT) return false; dbus_message_iter_recurse(&iter[1], &iter[2]); if (dbus_message_iter_get_arg_type(&iter[2]) != type) return false; dbus_message_iter_get_basic(&iter[2], value); return true; } bool libdecor_get_cursor_settings(char **theme, int *size) { static const char name[] = "org.gnome.desktop.interface"; static const char key_theme[] = "cursor-theme"; static const char key_size[] = "cursor-size"; DBusError error; DBusConnection *connection; DBusMessage *reply; const char *value_theme = NULL; dbus_error_init(&error); connection = dbus_bus_get(DBUS_BUS_SESSION, &error); if (dbus_error_is_set(&error)) goto fallback; reply = get_setting_sync(connection, name, key_theme); if (!reply) goto fallback; if (!parse_type(reply, DBUS_TYPE_STRING, &value_theme)) { dbus_message_unref(reply); goto fallback; } *theme = strdup(value_theme); dbus_message_unref(reply); reply = get_setting_sync(connection, name, key_size); if (!reply) goto fallback; if (!parse_type(reply, DBUS_TYPE_INT32, size)) { dbus_message_unref(reply); goto fallback; } dbus_message_unref(reply); return true; fallback: return get_cursor_settings_from_env(theme, size); } enum libdecor_color_scheme libdecor_get_color_scheme() { static const char name[] = "org.freedesktop.appearance"; static const char key_color_scheme[] = "color-scheme"; uint32_t color = 0; DBusError error; DBusConnection *connection; DBusMessage *reply; dbus_error_init(&error); connection = dbus_bus_get(DBUS_BUS_SESSION, &error); if (dbus_error_is_set(&error)) return 0; reply = get_setting_sync(connection, name, key_color_scheme); if (!reply) return 0; if (!parse_type(reply, DBUS_TYPE_UINT32, &color)) { dbus_message_unref(reply); return 0; } dbus_message_unref(reply); return color; } #else bool libdecor_get_cursor_settings(char **theme, int *size) { return get_cursor_settings_from_env(theme, size); } uint32_t libdecor_get_color_scheme() { return LIBDECOR_COLOR_SCHEME_DEFAULT; } #endif fltk-1.4.3/libdecor/src/desktop-settings.h0000644000175000017500000000271715004135251020646 0ustar albrechtalbrecht/* * Copyright © 2019 Christian Rauch * Copyright © 2024 Colin Kinloch * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #pragma once #include enum libdecor_color_scheme { LIBDECOR_COLOR_SCHEME_DEFAULT, LIBDECOR_COLOR_SCHEME_PREFER_DARK, LIBDECOR_COLOR_SCHEME_PREFER_LIGHT, }; bool libdecor_get_cursor_settings(char **theme, int *size); enum libdecor_color_scheme libdecor_get_color_scheme(); fltk-1.4.3/libdecor/src/os-compatibility.c0000644000175000017500000001177615004135251020627 0ustar albrechtalbrecht/* * Copyright © 2012 Collabora, Ltd. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "config.h" #include #include #include #include #include #include #include #ifdef HAVE_MEMFD_CREATE #include #endif #include "os-compatibility.h" #ifndef HAVE_MKOSTEMP static int set_cloexec_or_close(int fd) { long flags; if (fd == -1) return -1; flags = fcntl(fd, F_GETFD); if (flags == -1) goto err; if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) goto err; return fd; err: close(fd); return -1; } #endif static int create_tmpfile_cloexec(char *tmpname) { int fd; #ifdef HAVE_MKOSTEMP fd = mkostemp(tmpname, O_CLOEXEC); if (fd >= 0) unlink(tmpname); #else fd = mkstemp(tmpname); if (fd >= 0) { fd = set_cloexec_or_close(fd); unlink(tmpname); } #endif return fd; } static int os_resize_anonymous_file(int fd, off_t size) { #ifdef HAVE_POSIX_FALLOCATE sigset_t mask; sigset_t old_mask; /* posix_fallocate() might be interrupted, so we need to check * for EINTR and retry in that case. * However, in the presence of an alarm, the interrupt may trigger * repeatedly and prevent a large posix_fallocate() to ever complete * successfully, so we need to first block SIGALRM to prevent * this. */ sigemptyset(&mask); sigaddset(&mask, SIGALRM); sigprocmask(SIG_BLOCK, &mask, &old_mask); /* * Filesystems that do not support fallocate will return EINVAL or * EOPNOTSUPP. In this case we need to fall back to ftruncate */ do { errno = posix_fallocate(fd, 0, size); } while (errno == EINTR); sigprocmask(SIG_SETMASK, &old_mask, NULL); if (errno == 0) return 0; else if (errno != EINVAL && errno != EOPNOTSUPP) return -1; #endif if (ftruncate(fd, size) < 0) return -1; return 0; } /* * Create a new, unique, anonymous file of the given size, and * return the file descriptor for it. The file descriptor is set * CLOEXEC. The file is immediately suitable for mmap()'ing * the given size at offset zero. * * The file should not have a permanent backing store like a disk, * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. * * The file name is deleted from the file system. * * The file is suitable for buffer sharing between processes by * transmitting the file descriptor over Unix sockets using the * SCM_RIGHTS methods. * * If the C library implements posix_fallocate(), it is used to * guarantee that disk space is available for the file at the * given size. If disk space is insufficient, errno is set to ENOSPC. * If posix_fallocate() is not supported, program may receive * SIGBUS on accessing mmap()'ed file contents instead. * * If the C library implements memfd_create(), it is used to create the * file purely in memory, without any backing file name on the file * system, and then sealing off the possibility of shrinking it. This * can then be checked before accessing mmap()'ed file contents, to * make sure SIGBUS can't happen. It also avoids requiring * XDG_RUNTIME_DIR. */ int libdecor_os_create_anonymous_file(off_t size) { static const char template[] = "/libdecor-shared-XXXXXX"; const char *path; char *name; int fd; #ifdef HAVE_MEMFD_CREATE fd = memfd_create("libdecor", MFD_CLOEXEC | MFD_ALLOW_SEALING); if (fd >= 0) { /* We can add this seal before calling posix_fallocate(), as * the file is currently zero-sized anyway. * * There is also no need to check for the return value, we * couldn't do anything with it anyway. */ fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL); } else #endif { path = getenv("XDG_RUNTIME_DIR"); if (!path) { errno = ENOENT; return -1; } name = malloc(strlen(path) + sizeof(template)); if (!name) return -1; strcpy(name, path); strcat(name, template); fd = create_tmpfile_cloexec(name); free(name); if (fd < 0) return -1; } if (os_resize_anonymous_file(fd, size) < 0) { close(fd); return -1; } return fd; } fltk-1.4.3/libdecor/src/libdecor.h0000644000175000017500000003501215004135251017114 0ustar albrechtalbrecht/* * Copyright © 2017-2018 Red Hat Inc. * Copyright © 2018 Jonas Ådahl * Copyright © 2019 Christian Rauch * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef LIBDECOR_H #define LIBDECOR_H #include #include #ifdef __cplusplus extern "C" { #endif #if defined(__GNUC__) && __GNUC__ >= 4 #define LIBDECOR_EXPORT __attribute__ ((visibility("default"))) #else #define LIBDECOR_EXPORT #endif struct xdg_toplevel; /** \class libdecor * * \brief A libdecor context instance. */ struct libdecor; /** \class libdecor_frame * * \brief A frame used for decorating a Wayland surface. */ struct libdecor_frame; /** \class libdecor_configuration * * \brief An object representing a toplevel window configuration. */ struct libdecor_configuration; /** \class libdecor_state * * \brief An object corresponding to a configured content state. */ struct libdecor_state; enum libdecor_error { LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE, LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION, }; enum libdecor_window_state { LIBDECOR_WINDOW_STATE_NONE = 0, LIBDECOR_WINDOW_STATE_ACTIVE = 1 << 0, LIBDECOR_WINDOW_STATE_MAXIMIZED = 1 << 1, LIBDECOR_WINDOW_STATE_FULLSCREEN = 1 << 2, LIBDECOR_WINDOW_STATE_TILED_LEFT = 1 << 3, LIBDECOR_WINDOW_STATE_TILED_RIGHT = 1 << 4, LIBDECOR_WINDOW_STATE_TILED_TOP = 1 << 5, LIBDECOR_WINDOW_STATE_TILED_BOTTOM = 1 << 6, LIBDECOR_WINDOW_STATE_SUSPENDED = 1 << 7, LIBDECOR_WINDOW_STATE_RESIZING = 1 << 8, }; enum libdecor_resize_edge { LIBDECOR_RESIZE_EDGE_NONE, LIBDECOR_RESIZE_EDGE_TOP, LIBDECOR_RESIZE_EDGE_BOTTOM, LIBDECOR_RESIZE_EDGE_LEFT, LIBDECOR_RESIZE_EDGE_TOP_LEFT, LIBDECOR_RESIZE_EDGE_BOTTOM_LEFT, LIBDECOR_RESIZE_EDGE_RIGHT, LIBDECOR_RESIZE_EDGE_TOP_RIGHT, LIBDECOR_RESIZE_EDGE_BOTTOM_RIGHT, }; enum libdecor_capabilities { LIBDECOR_ACTION_MOVE = 1 << 0, LIBDECOR_ACTION_RESIZE = 1 << 1, LIBDECOR_ACTION_MINIMIZE = 1 << 2, LIBDECOR_ACTION_FULLSCREEN = 1 << 3, LIBDECOR_ACTION_CLOSE = 1 << 4, }; enum libdecor_wm_capabilities { LIBDECOR_WM_CAPABILITIES_WINDOW_MENU = 1 << 0, LIBDECOR_WM_CAPABILITIES_MAXIMIZE = 1 << 1, LIBDECOR_WM_CAPABILITIES_FULLSCREEN = 1 << 2, LIBDECOR_WM_CAPABILITIES_MINIMIZE = 1 << 3 }; struct libdecor_interface { /** * An error event */ void (* error)(struct libdecor *context, enum libdecor_error error, const char *message); /* Reserved */ void (* reserved0)(void); void (* reserved1)(void); void (* reserved2)(void); void (* reserved3)(void); void (* reserved4)(void); void (* reserved5)(void); void (* reserved6)(void); void (* reserved7)(void); void (* reserved8)(void); void (* reserved9)(void); }; /** * Interface for integrating a Wayland surface with libdecor. */ struct libdecor_frame_interface { /** * A new configuration was received. An application should respond to * this by creating a suitable libdecor_state, and apply it using * libdecor_frame_commit. */ void (* configure)(struct libdecor_frame *frame, struct libdecor_configuration *configuration, void *user_data); /** * The window was requested to be closed by the compositor. */ void (* close)(struct libdecor_frame *frame, void *user_data); /** * The window decoration asked to have the main surface to be * committed. This is required when the decoration is implemented using * synchronous subsurfaces. */ void (* commit)(struct libdecor_frame *frame, void *user_data); /** * Any mapped popup that has a grab on the given seat should be * dismissed. */ void (* dismiss_popup)(struct libdecor_frame *frame, const char *seat_name, void *user_data); /* Reserved */ void (* reserved0)(void); void (* reserved1)(void); void (* reserved2)(void); void (* reserved3)(void); void (* reserved4)(void); void (* reserved5)(void); void (* reserved6)(void); void (* reserved7)(void); void (* reserved8)(void); void (* reserved9)(void); }; /** * Remove a reference to the libdecor instance. When the reference count * reaches zero, it is freed. */ void libdecor_unref(struct libdecor *context); /** * Create a new libdecor context for the given wl_display. */ struct libdecor * libdecor_new(struct wl_display *display, const struct libdecor_interface *iface); /** * Create a new libdecor context for the given wl_display and attach user data. */ struct libdecor * libdecor_new_with_user_data(struct wl_display *display, const struct libdecor_interface *iface, void *user_data); /** * Get the user data associated with this libdecor context. */ void * libdecor_get_user_data(struct libdecor *context); /** * Set the user data associated with this libdecor context. */ void libdecor_set_user_data(struct libdecor *context, void *user_data); /** * Get the file descriptor used by libdecor. This is similar to * wl_display_get_fd(), thus should be polled, and when data is available, * libdecor_dispatch() should be called. */ int libdecor_get_fd(struct libdecor *context); /** * Dispatch events. This function should be called when data is available on * the file descriptor returned by libdecor_get_fd(). If timeout is zero, this * function will never block. */ int libdecor_dispatch(struct libdecor *context, int timeout); /** * Decorate the given content wl_surface. * * This will create an xdg_surface and an xdg_toplevel, and integrate it * properly with the windowing system, including creating appropriate * decorations when needed, as well as handle windowing integration events such * as resizing, moving, maximizing, etc. * * The passed wl_surface should only contain actual application content, * without any window decoration. */ struct libdecor_frame * libdecor_decorate(struct libdecor *context, struct wl_surface *surface, const struct libdecor_frame_interface *iface, void *user_data); /** * Add a reference to the frame object. */ void libdecor_frame_ref(struct libdecor_frame *frame); /** * Remove a reference to the frame object. When the reference count reaches * zero, the frame object is destroyed. */ void libdecor_frame_unref(struct libdecor_frame *frame); /** * Get the user data associated with this libdecor frame. */ void * libdecor_frame_get_user_data(struct libdecor_frame *frame); /** * Set the user data associated with this libdecor frame. */ void libdecor_frame_set_user_data(struct libdecor_frame *frame, void *user_data); /** * Set the visibility of the frame. * * If an application wants to be borderless, it can set the frame visibility to * false. */ void libdecor_frame_set_visibility(struct libdecor_frame *frame, bool visible); /** * Get the visibility of the frame. */ bool libdecor_frame_is_visible(struct libdecor_frame *frame); /** * Set the parent of the window. * * This can be used to stack multiple toplevel windows above or under each * other. */ void libdecor_frame_set_parent(struct libdecor_frame *frame, struct libdecor_frame *parent); /** * Set the title of the window. */ void libdecor_frame_set_title(struct libdecor_frame *frame, const char *title); /** * Get the title of the window. */ const char * libdecor_frame_get_title(struct libdecor_frame *frame); /** * Set the application ID of the window. */ void libdecor_frame_set_app_id(struct libdecor_frame *frame, const char *app_id); /** * Set new capabilities of the window. * * This determines whether e.g. a window decoration should show a maximize * button, etc. * * Setting a capability does not implicitly unset any other. */ void libdecor_frame_set_capabilities(struct libdecor_frame *frame, enum libdecor_capabilities capabilities); /** * Unset capabilities of the window. * * The opposite of libdecor_frame_set_capabilities. */ void libdecor_frame_unset_capabilities(struct libdecor_frame *frame, enum libdecor_capabilities capabilities); /** * Check whether the window has any of the given capabilities. */ bool libdecor_frame_has_capability(struct libdecor_frame *frame, enum libdecor_capabilities capability); /** * Show the window menu. */ void libdecor_frame_show_window_menu(struct libdecor_frame *frame, struct wl_seat *wl_seat, uint32_t serial, int x, int y); /** * Issue a popup grab on the window. Call this when a xdg_popup is mapped, so * that it can be properly dismissed by the decorations. */ void libdecor_frame_popup_grab(struct libdecor_frame *frame, const char *seat_name); /** * Release the popup grab. Call this when you unmap a popup. */ void libdecor_frame_popup_ungrab(struct libdecor_frame *frame, const char *seat_name); /** * Translate content surface local coordinates to toplevel window local * coordinates. * * This can be used to translate surface coordinates to coordinates useful for * e.g. showing the window menu, or positioning a popup. */ void libdecor_frame_translate_coordinate(struct libdecor_frame *frame, int surface_x, int surface_y, int *frame_x, int *frame_y); /** * Set the min content size. * * This translates roughly to xdg_toplevel_set_min_size(). */ void libdecor_frame_set_min_content_size(struct libdecor_frame *frame, int content_width, int content_height); /** * Set the max content size. * * This translates roughly to xdg_toplevel_set_max_size(). */ void libdecor_frame_set_max_content_size(struct libdecor_frame *frame, int content_width, int content_height); /** * Get the min content size. */ void libdecor_frame_get_min_content_size(const struct libdecor_frame *frame, int *content_width, int *content_height); /** * Get the max content size. */ void libdecor_frame_get_max_content_size(const struct libdecor_frame *frame, int *content_width, int *content_height); /** * Initiate an interactive resize. * * This roughly translates to xdg_toplevel_resize(). */ void libdecor_frame_resize(struct libdecor_frame *frame, struct wl_seat *wl_seat, uint32_t serial, enum libdecor_resize_edge edge); /** * Initiate an interactive move. * * This roughly translates to xdg_toplevel_move(). */ void libdecor_frame_move(struct libdecor_frame *frame, struct wl_seat *wl_seat, uint32_t serial); /** * Commit a new window state. This can be called on application driven resizes * when the window is floating, or in response to received configurations, i.e. * from e.g. interactive resizes or state changes. */ void libdecor_frame_commit(struct libdecor_frame *frame, struct libdecor_state *state, struct libdecor_configuration *configuration); /** * Minimize the window. * * Roughly translates to xdg_toplevel_set_minimized(). */ void libdecor_frame_set_minimized(struct libdecor_frame *frame); /** * Maximize the window. * * Roughly translates to xdg_toplevel_set_maximized(). */ void libdecor_frame_set_maximized(struct libdecor_frame *frame); /** * Unmaximize the window. * * Roughly translates to xdg_toplevel_unset_maximized(). */ void libdecor_frame_unset_maximized(struct libdecor_frame *frame); /** * Fullscreen the window. * * Roughly translates to xdg_toplevel_set_fullscreen(). */ void libdecor_frame_set_fullscreen(struct libdecor_frame *frame, struct wl_output *output); /** * Unfullscreen the window. * * Roughly translates to xdg_toplevel_unset_unfullscreen(). */ void libdecor_frame_unset_fullscreen(struct libdecor_frame *frame); /** * Return true if the window is floating. * * A window is floating when it's not maximized, tiled, fullscreen, or in any * similar way with a fixed size and state. * Note that this function uses the "applied" configuration. If this function * is used in the 'configure' callback, the provided configuration has to be * applied via 'libdecor_frame_commit' first, before it will reflect the current * window state from the provided configuration. */ bool libdecor_frame_is_floating(struct libdecor_frame *frame); /** * Close the window. * * Roughly translates to xdg_toplevel_close(). */ void libdecor_frame_close(struct libdecor_frame *frame); /** * Map the window. * * This will eventually result in the initial configure event. */ void libdecor_frame_map(struct libdecor_frame *frame); /** * Get the associated xdg_surface for content wl_surface. */ struct xdg_surface * libdecor_frame_get_xdg_surface(struct libdecor_frame *frame); /** * Get the associated xdg_toplevel for the content wl_surface. */ struct xdg_toplevel * libdecor_frame_get_xdg_toplevel(struct libdecor_frame *frame); /** * Get the supported window manager capabilities for the window. */ enum libdecor_wm_capabilities libdecor_frame_get_wm_capabilities(struct libdecor_frame *frame); /** * Create a new content surface state. */ struct libdecor_state * libdecor_state_new(int width, int height); /** * Free a content surface state. */ void libdecor_state_free(struct libdecor_state *state); /** * Get the expected size of the content for this configuration. * * If the configuration doesn't contain a size, false is returned. */ bool libdecor_configuration_get_content_size(struct libdecor_configuration *configuration, struct libdecor_frame *frame, int *width, int *height); /** * Get the window state for this configuration. * * If the configuration doesn't contain any associated window state, false is * returned, and the application should assume the window state remains * unchanged. */ bool libdecor_configuration_get_window_state(struct libdecor_configuration *configuration, enum libdecor_window_state *window_state); #ifdef __cplusplus } #endif #endif /* LIBDECOR_H */ fltk-1.4.3/libdecor/src/plugins/0000755000175000017500000000000015004135251016640 5ustar albrechtalbrechtfltk-1.4.3/libdecor/src/plugins/common/0000755000175000017500000000000015004135251020130 5ustar albrechtalbrechtfltk-1.4.3/libdecor/src/plugins/common/libdecor-cairo-blur.h0000644000175000017500000000034415004135251024122 0ustar albrechtalbrecht#pragma once #include int blur_surface(cairo_surface_t *surface, int margin); void render_shadow(cairo_t *cr, cairo_surface_t *surface, int x, int y, int width, int height, int margin, int top_margin); fltk-1.4.3/libdecor/src/plugins/common/libdecor-cairo-blur.c0000644000175000017500000001600115004135251024112 0ustar albrechtalbrecht/* * Copyright © 2008 Kristian Høgsberg * Copyright © 2012 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* * functions 'blur_surface' and 'render_shadow' from weston project: * https://gitlab.freedesktop.org/wayland/weston/raw/master/shared/cairo-util.c */ #include "libdecor-cairo-blur.h" #include #include #include /** * Compile-time computation of number of items in a hardcoded array. * * @param a the array being measured. * @return the number of items hardcoded into the array. */ #ifndef ARRAY_LENGTH #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) #endif int blur_surface(cairo_surface_t *surface, int margin) { int32_t width, height, stride, x, y, z, w; uint8_t *src, *dst; uint32_t *s, *d, a, p; int i, j, k, size, half; uint32_t kernel[71]; double f; size = ARRAY_LENGTH(kernel); width = cairo_image_surface_get_width(surface); height = cairo_image_surface_get_height(surface); stride = cairo_image_surface_get_stride(surface); src = cairo_image_surface_get_data(surface); dst = malloc(height * stride); if (dst == NULL) return -1; half = size / 2; a = 0; for (i = 0; i < size; i++) { f = (i - half); kernel[i] = exp(- f * f / ARRAY_LENGTH(kernel)) * 10000; a += kernel[i]; } for (i = 0; i < height; i++) { s = (uint32_t *) (src + i * stride); d = (uint32_t *) (dst + i * stride); for (j = 0; j < width; j++) { if (margin < j && j < width - margin) { d[j] = s[j]; continue; } x = 0; y = 0; z = 0; w = 0; for (k = 0; k < size; k++) { if (j - half + k < 0 || j - half + k >= width) continue; p = s[j - half + k]; x += (p >> 24) * kernel[k]; y += ((p >> 16) & 0xff) * kernel[k]; z += ((p >> 8) & 0xff) * kernel[k]; w += (p & 0xff) * kernel[k]; } d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a; } } for (i = 0; i < height; i++) { s = (uint32_t *) (dst + i * stride); d = (uint32_t *) (src + i * stride); for (j = 0; j < width; j++) { if (margin <= i && i < height - margin) { d[j] = s[j]; continue; } x = 0; y = 0; z = 0; w = 0; for (k = 0; k < size; k++) { if (i - half + k < 0 || i - half + k >= height) continue; s = (uint32_t *) (dst + (i - half + k) * stride); p = s[j]; x += (p >> 24) * kernel[k]; y += ((p >> 16) & 0xff) * kernel[k]; z += ((p >> 8) & 0xff) * kernel[k]; w += (p & 0xff) * kernel[k]; } d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a; } } free(dst); cairo_surface_mark_dirty(surface); return 0; } void render_shadow(cairo_t *cr, cairo_surface_t *surface, int x, int y, int width, int height, int margin, int top_margin) { cairo_pattern_t *pattern; cairo_matrix_t matrix; int i, fx, fy, shadow_height, shadow_width; cairo_set_source_rgba(cr, 0, 0, 0, 0.45); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); pattern = cairo_pattern_create_for_surface (surface); cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); for (i = 0; i < 4; i++) { /* when fy is set, then we are working with lower corners, * when fx is set, then we are working with right corners * * 00 ------- 01 * | | * | | * 10 ------- 11 */ fx = i & 1; fy = i >> 1; cairo_matrix_init_translate(&matrix, -x + fx * (128 - width), -y + fy * (128 - height)); cairo_pattern_set_matrix(pattern, &matrix); shadow_width = margin; shadow_height = fy ? margin : top_margin; /* if the shadows together are greater than the surface, we need * to fix it - set the shadow size to the half of * the size of surface. Also handle the case when the size is * not divisible by 2. In that case we need one part of the * shadow to be one pixel greater. !fy or !fx, respectively, * will do the work. */ if (height < 2 * shadow_height) shadow_height = (height + !fy) / 2; if (width < 2 * shadow_width) shadow_width = (width + !fx) / 2; cairo_reset_clip(cr); cairo_rectangle(cr, x + fx * (width - shadow_width), y + fy * (height - shadow_height), shadow_width, shadow_height); cairo_clip (cr); cairo_mask(cr, pattern); } shadow_width = width - 2 * margin; shadow_height = top_margin; if (height < 2 * shadow_height) shadow_height = height / 2; if (shadow_width > 0 && shadow_height) { /* Top stretch */ cairo_matrix_init_translate(&matrix, 60, 0); cairo_matrix_scale(&matrix, 8.0 / width, 1); cairo_matrix_translate(&matrix, -x - width / 2, -y); cairo_pattern_set_matrix(pattern, &matrix); cairo_rectangle(cr, x + margin, y, shadow_width, shadow_height); cairo_reset_clip(cr); cairo_rectangle(cr, x + margin, y, shadow_width, shadow_height); cairo_clip (cr); cairo_mask(cr, pattern); /* Bottom stretch */ cairo_matrix_translate(&matrix, 0, -height + 128); cairo_pattern_set_matrix(pattern, &matrix); cairo_reset_clip(cr); cairo_rectangle(cr, x + margin, y + height - margin, shadow_width, margin); cairo_clip (cr); cairo_mask(cr, pattern); } shadow_width = margin; if (width < 2 * shadow_width) shadow_width = width / 2; shadow_height = height - margin - top_margin; /* if height is smaller than sum of margins, * then the shadow is already done by the corners */ if (shadow_height > 0 && shadow_width) { /* Left stretch */ cairo_matrix_init_translate(&matrix, 0, 60); cairo_matrix_scale(&matrix, 1, 8.0 / height); cairo_matrix_translate(&matrix, -x, -y - height / 2); cairo_pattern_set_matrix(pattern, &matrix); cairo_reset_clip(cr); cairo_rectangle(cr, x, y + top_margin, shadow_width, shadow_height); cairo_clip (cr); cairo_mask(cr, pattern); /* Right stretch */ cairo_matrix_translate(&matrix, -width + 128, 0); cairo_pattern_set_matrix(pattern, &matrix); cairo_rectangle(cr, x + width - shadow_width, y + top_margin, shadow_width, shadow_height); cairo_reset_clip(cr); cairo_clip (cr); cairo_mask(cr, pattern); } cairo_pattern_destroy(pattern); cairo_reset_clip(cr); } fltk-1.4.3/libdecor/src/plugins/dummy/0000755000175000017500000000000015004135251017773 5ustar albrechtalbrechtfltk-1.4.3/libdecor/src/plugins/dummy/libdecor-dummy.c0000644000175000017500000000735515004135251023065 0ustar albrechtalbrecht/* * Copyright © 2021 Jonas Ådahl * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "config.h" #include "libdecor-plugin.h" #include #include #include #include #include #include "utils.h" struct libdecor_plugin_dummy { struct libdecor_plugin plugin; struct libdecor *context; }; static void libdecor_plugin_dummy_destroy(struct libdecor_plugin *plugin) { struct libdecor_plugin_dummy *plugin_dummy = (struct libdecor_plugin_dummy *) plugin; libdecor_plugin_release(plugin); free(plugin_dummy); } static struct libdecor_frame * libdecor_plugin_dummy_frame_new(struct libdecor_plugin *plugin) { struct libdecor_frame *frame; frame = zalloc(sizeof *frame); return frame; } static void libdecor_plugin_dummy_frame_free(struct libdecor_plugin *plugin, struct libdecor_frame *frame) { } static void libdecor_plugin_dummy_frame_commit(struct libdecor_plugin *plugin, struct libdecor_frame *frame, struct libdecor_state *state, struct libdecor_configuration *configuration) { } static void libdecor_plugin_dummy_frame_property_changed(struct libdecor_plugin *plugin, struct libdecor_frame *frame) { } static void libdecor_plugin_dummy_frame_popup_grab(struct libdecor_plugin *plugin, struct libdecor_frame *frame, const char *seat_name) { } static void libdecor_plugin_dummy_frame_popup_ungrab(struct libdecor_plugin *plugin, struct libdecor_frame *frame, const char *seat_name) { } static struct libdecor_plugin_interface dummy_plugin_iface = { .destroy = libdecor_plugin_dummy_destroy, .frame_new = libdecor_plugin_dummy_frame_new, .frame_free = libdecor_plugin_dummy_frame_free, .frame_commit = libdecor_plugin_dummy_frame_commit, .frame_property_changed = libdecor_plugin_dummy_frame_property_changed, .frame_popup_grab = libdecor_plugin_dummy_frame_popup_grab, .frame_popup_ungrab = libdecor_plugin_dummy_frame_popup_ungrab, }; static struct libdecor_plugin * libdecor_plugin_new(struct libdecor *context) { struct libdecor_plugin_dummy *plugin_dummy; plugin_dummy = zalloc(sizeof *plugin_dummy); libdecor_plugin_init(&plugin_dummy->plugin, context, &dummy_plugin_iface); plugin_dummy->context = context; libdecor_notify_plugin_ready(context); return &plugin_dummy->plugin; } static struct libdecor_plugin_priority priorities[] = { { NULL, LIBDECOR_PLUGIN_PRIORITY_LOW } }; LIBDECOR_EXPORT const struct libdecor_plugin_description libdecor_plugin_description = { .api_version = LIBDECOR_PLUGIN_API_VERSION, .capabilities = LIBDECOR_PLUGIN_CAPABILITY_BASE, .description = "dummy libdecor plugin", .priorities = priorities, .constructor = libdecor_plugin_new, }; fltk-1.4.3/libdecor/src/plugins/gtk/0000755000175000017500000000000015004135251017425 5ustar albrechtalbrechtfltk-1.4.3/libdecor/src/plugins/gtk/libdecor-gtk.c0000644000175000017500000023033415004135251022144 0ustar albrechtalbrecht/* * Copyright © 2018 Jonas Ådahl * Copyright © 2021 Christian Rauch * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "libdecor-plugin.h" #include "utils.h" #include "desktop-settings.h" #include "os-compatibility.h" #include #include "common/libdecor-cairo-blur.h" #include #include static const size_t SHADOW_MARGIN = 24; /* grabbable part of the border */ static const char *cursor_names[] = { "top_side", "bottom_side", "left_side", "top_left_corner", "bottom_left_corner", "right_side", "top_right_corner", "bottom_right_corner" }; enum header_element { HEADER_NONE, HEADER_FULL, /* entire header bar */ HEADER_TITLE, /* label */ HEADER_MIN, HEADER_MAX, HEADER_CLOSE, }; enum titlebar_gesture_state { TITLEBAR_GESTURE_STATE_INIT, TITLEBAR_GESTURE_STATE_BUTTON_PRESSED, TITLEBAR_GESTURE_STATE_CONSUMED, TITLEBAR_GESTURE_STATE_DISCARDED, }; struct header_element_data { const char *name; enum header_element type; /* pointer to button or NULL if not found*/ GtkWidget *widget; GtkStateFlags state; }; static void find_widget_by_name(GtkWidget *widget, void *data) { if (GTK_IS_WIDGET(widget)) { char *style_ctx = gtk_style_context_to_string( gtk_widget_get_style_context(widget), GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE); if (strstr(style_ctx, ((struct header_element_data *)data)->name)) { ((struct header_element_data *)data)->widget = widget; free(style_ctx); return; } free(style_ctx); } if (GTK_IS_CONTAINER(widget)) { /* recursively traverse container */ gtk_container_forall(GTK_CONTAINER(widget), &find_widget_by_name, data); } } static struct header_element_data find_widget_by_type(GtkWidget *widget, enum header_element type) { char* name = NULL; switch (type) { case HEADER_FULL: name = "headerbar.titlebar:"; break; case HEADER_TITLE: name = "label.title:"; break; case HEADER_MIN: name = ".minimize"; break; case HEADER_MAX: name = ".maximize"; break; case HEADER_CLOSE: name = ".close"; break; default: break; } struct header_element_data data = {.name = name, .type = type, .widget = NULL}; find_widget_by_name(widget, &data); return data; } static bool in_region(const cairo_rectangle_int_t *rect, const int *x, const int *y) { return (*x>=rect->x) & (*y>=rect->y) & (*x<(rect->x+rect->width)) & (*y<(rect->y+rect->height)); } static struct header_element_data get_header_focus(const GtkHeaderBar *header_bar, const int x, const int y) { /* we have to check child widgets (buttons, title) before the 'HDR_HDR' root widget */ static const enum header_element elems[] = {HEADER_TITLE, HEADER_MIN, HEADER_MAX, HEADER_CLOSE}; for (size_t i = 0; i < ARRAY_SIZE(elems); i++) { struct header_element_data elem = find_widget_by_type(GTK_WIDGET(header_bar), elems[i]); if (elem.widget) { GtkAllocation allocation; gtk_widget_get_allocation(GTK_WIDGET(elem.widget), &allocation); if (in_region(&allocation, &x, &y)) return elem; } } struct header_element_data elem_none = { .widget=NULL}; return elem_none; } static bool streq(const char *str1, const char *str2) { if (!str1 && !str2) return true; if (str1 && str2) return strcmp(str1, str2) == 0; return false; } enum decoration_type { DECORATION_TYPE_NONE, DECORATION_TYPE_ALL, DECORATION_TYPE_TITLE_ONLY }; enum component { NONE = 0, SHADOW, HEADER, }; struct seat { struct libdecor_plugin_gtk *plugin_gtk; char *name; struct wl_seat *wl_seat; struct wl_pointer *wl_pointer; struct wl_touch *wl_touch; struct wl_surface *cursor_surface; struct wl_cursor *current_cursor; int cursor_scale; struct wl_list cursor_outputs; struct wl_cursor_theme *cursor_theme; /* cursors for resize edges and corners */ struct wl_cursor *cursors[ARRAY_LENGTH(cursor_names)]; struct wl_cursor *cursor_left_ptr; struct wl_surface *pointer_focus; struct wl_surface *touch_focus; int pointer_x, pointer_y; uint32_t touch_down_time_stamp; uint32_t serial; bool grabbed; struct wl_list link; }; struct output { struct libdecor_plugin_gtk *plugin_gtk; struct wl_output *wl_output; uint32_t id; int scale; struct wl_list link; }; struct buffer { struct wl_buffer *wl_buffer; bool in_use; bool is_detached; void *data; size_t data_size; int width; int height; int scale; int buffer_width; int buffer_height; }; struct border_component { enum component type; struct wl_surface *wl_surface; struct wl_subsurface *wl_subsurface; struct buffer *buffer; bool opaque; struct wl_list output_list; int scale; struct wl_list child_components; /* border_component::link */ struct wl_list link; /* border_component::child_components */ }; struct surface_output { struct output *output; struct wl_list link; }; struct cursor_output { struct output *output; struct wl_list link; }; struct libdecor_frame_gtk { struct libdecor_frame frame; struct libdecor_plugin_gtk *plugin_gtk; int content_width; int content_height; enum libdecor_window_state window_state; enum decoration_type decoration_type; char *title; enum libdecor_capabilities capabilities; struct border_component *active; struct border_component *touch_active; struct border_component *focus; struct border_component *grab; bool shadow_showing; struct border_component shadow; GtkWidget *window; /* offscreen window for rendering */ GtkWidget *header; /* header bar with widgets */ struct border_component headerbar; struct header_element_data hdr_focus; /* store pre-processed shadow tile */ cairo_surface_t *shadow_blur; struct wl_list link; struct { enum titlebar_gesture_state state; int button_pressed_count; uint32_t first_pressed_button; uint32_t first_pressed_time; double pressed_x; double pressed_y; uint32_t pressed_serial; } titlebar_gesture; }; struct libdecor_plugin_gtk { struct libdecor_plugin plugin; struct wl_callback *globals_callback; struct wl_callback *globals_callback_shm; struct libdecor *context; struct wl_registry *wl_registry; struct wl_subcompositor *wl_subcompositor; struct wl_compositor *wl_compositor; struct wl_shm *wl_shm; struct wl_callback *shm_callback; bool has_argb; struct wl_list visible_frame_list; struct wl_list seat_list; struct wl_list output_list; char *cursor_theme_name; int cursor_size; uint32_t color_scheme_setting; int double_click_time_ms; int drag_threshold; }; static const char *libdecor_gtk_proxy_tag = "libdecor-gtk"; static bool own_proxy(struct wl_proxy *proxy) { if (!proxy) return false; return (wl_proxy_get_tag(proxy) == &libdecor_gtk_proxy_tag); } static bool own_surface(struct wl_surface *surface) { return own_proxy((struct wl_proxy *) surface); } static bool own_output(struct wl_output *output) { return own_proxy((struct wl_proxy *) output); } static bool moveable(struct libdecor_frame_gtk *frame_gtk) { return libdecor_frame_has_capability(&frame_gtk->frame, LIBDECOR_ACTION_MOVE); } static bool resizable(struct libdecor_frame_gtk *frame_gtk) { return libdecor_frame_has_capability(&frame_gtk->frame, LIBDECOR_ACTION_RESIZE); } static bool minimizable(struct libdecor_frame_gtk *frame_gtk) { return libdecor_frame_has_capability(&frame_gtk->frame, LIBDECOR_ACTION_MINIMIZE); } static bool closeable(struct libdecor_frame_gtk *frame_gtk) { return libdecor_frame_has_capability(&frame_gtk->frame, LIBDECOR_ACTION_CLOSE); } static void buffer_free(struct buffer *buffer); static void draw_border_component(struct libdecor_frame_gtk *frame_gtk, struct border_component *border_component, enum component component); static void send_cursor(struct seat *seat); static bool update_local_cursor(struct seat *seat); static void libdecor_plugin_gtk_destroy(struct libdecor_plugin *plugin) { struct libdecor_plugin_gtk *plugin_gtk = (struct libdecor_plugin_gtk *) plugin; struct seat *seat, *seat_tmp; struct output *output, *output_tmp; struct libdecor_frame_gtk *frame, *frame_tmp; if (plugin_gtk->globals_callback) wl_callback_destroy(plugin_gtk->globals_callback); if (plugin_gtk->globals_callback_shm) wl_callback_destroy(plugin_gtk->globals_callback_shm); if (plugin_gtk->shm_callback) wl_callback_destroy(plugin_gtk->shm_callback); wl_registry_destroy(plugin_gtk->wl_registry); wl_list_for_each_safe(seat, seat_tmp, &plugin_gtk->seat_list, link) { struct cursor_output *cursor_output, *tmp; if (seat->wl_pointer) wl_pointer_destroy(seat->wl_pointer); if (seat->wl_touch) wl_touch_destroy(seat->wl_touch); if (seat->cursor_surface) wl_surface_destroy(seat->cursor_surface); wl_seat_destroy(seat->wl_seat); if (seat->cursor_theme) wl_cursor_theme_destroy(seat->cursor_theme); wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link) { wl_list_remove(&cursor_output->link); free(cursor_output); } free(seat->name); free(seat); } wl_list_for_each_safe(output, output_tmp, &plugin_gtk->output_list, link) { if (wl_output_get_version (output->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION) wl_output_release(output->wl_output); else wl_output_destroy(output->wl_output); free(output); } wl_list_for_each_safe(frame, frame_tmp, &plugin_gtk->visible_frame_list, link) { wl_list_remove(&frame->link); } free(plugin_gtk->cursor_theme_name); if (plugin_gtk->wl_shm) wl_shm_destroy(plugin_gtk->wl_shm); if (plugin_gtk->wl_compositor) wl_compositor_destroy(plugin_gtk->wl_compositor); if (plugin_gtk->wl_subcompositor) wl_subcompositor_destroy(plugin_gtk->wl_subcompositor); libdecor_plugin_release(&plugin_gtk->plugin); free(plugin_gtk); } static struct libdecor_frame_gtk * libdecor_frame_gtk_new(struct libdecor_plugin_gtk *plugin_gtk) { struct libdecor_frame_gtk *frame_gtk = zalloc(sizeof *frame_gtk); cairo_t *cr; static const int size = 128; static const int boundary = 32; frame_gtk->plugin_gtk = plugin_gtk; frame_gtk->shadow_blur = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, size, size); wl_list_insert(&plugin_gtk->visible_frame_list, &frame_gtk->link); cr = cairo_create(frame_gtk->shadow_blur); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_rectangle(cr, boundary, boundary, size - 2 * boundary, size - 2 * boundary); cairo_fill(cr); cairo_destroy(cr); blur_surface(frame_gtk->shadow_blur, 64); return frame_gtk; } static int libdecor_plugin_gtk_get_fd(struct libdecor_plugin *plugin) { struct libdecor_plugin_gtk *plugin_gtk = (struct libdecor_plugin_gtk *) plugin; struct wl_display *wl_display = libdecor_get_wl_display(plugin_gtk->context); return wl_display_get_fd(wl_display); } static int libdecor_plugin_gtk_dispatch(struct libdecor_plugin *plugin, int timeout) { struct libdecor_plugin_gtk *plugin_gtk = (struct libdecor_plugin_gtk *) plugin; struct wl_display *wl_display = libdecor_get_wl_display(plugin_gtk->context); struct pollfd fds[1]; int ret; int dispatch_count = 0; while (g_main_context_iteration(NULL, FALSE)); while (wl_display_prepare_read(wl_display) != 0) dispatch_count += wl_display_dispatch_pending(wl_display); if (wl_display_flush(wl_display) < 0 && errno != EAGAIN) { wl_display_cancel_read(wl_display); return -errno; } fds[0] = (struct pollfd) { wl_display_get_fd(wl_display), POLLIN }; ret = poll(fds, ARRAY_SIZE (fds), timeout); if (ret > 0) { if (fds[0].revents & POLLIN) { wl_display_read_events(wl_display); dispatch_count += wl_display_dispatch_pending(wl_display); return dispatch_count; } else { wl_display_cancel_read(wl_display); return dispatch_count; } } else if (ret == 0) { wl_display_cancel_read(wl_display); return dispatch_count; } else { wl_display_cancel_read(wl_display); return -errno; } } static struct libdecor_frame * libdecor_plugin_gtk_frame_new(struct libdecor_plugin *plugin) { struct libdecor_plugin_gtk *plugin_gtk = (struct libdecor_plugin_gtk *) plugin; struct libdecor_frame_gtk *frame_gtk; frame_gtk = libdecor_frame_gtk_new(plugin_gtk); return &frame_gtk->frame; } static void toggle_maximized(struct libdecor_frame *const frame) { if (!resizable((struct libdecor_frame_gtk *)frame)) return; if (!(libdecor_frame_get_window_state(frame) & LIBDECOR_WINDOW_STATE_MAXIMIZED)) libdecor_frame_set_maximized(frame); else libdecor_frame_unset_maximized(frame); } static void buffer_release(void *user_data, struct wl_buffer *wl_buffer) { struct buffer *buffer = user_data; if (buffer->is_detached) buffer_free(buffer); else buffer->in_use = false; } static const struct wl_buffer_listener buffer_listener = { buffer_release }; static struct buffer * create_shm_buffer(struct libdecor_plugin_gtk *plugin_gtk, int width, int height, bool opaque, int scale) { struct wl_shm_pool *pool; int fd, size, buffer_width, buffer_height, stride; void *data; struct buffer *buffer; enum wl_shm_format buf_fmt; buffer_width = width * scale; buffer_height = height * scale; stride = buffer_width * 4; size = stride * buffer_height; fd = libdecor_os_create_anonymous_file(size); if (fd < 0) { fprintf(stderr, "creating a buffer file for %d B failed: %s\n", size, strerror(errno)); return NULL; } data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data == MAP_FAILED) { fprintf(stderr, "mmap failed: %s\n", strerror(errno)); close(fd); return NULL; } buf_fmt = opaque ? WL_SHM_FORMAT_XRGB8888 : WL_SHM_FORMAT_ARGB8888; pool = wl_shm_create_pool(plugin_gtk->wl_shm, fd, size); buffer = zalloc(sizeof *buffer); buffer->wl_buffer = wl_shm_pool_create_buffer(pool, 0, buffer_width, buffer_height, stride, buf_fmt); wl_buffer_add_listener(buffer->wl_buffer, &buffer_listener, buffer); wl_shm_pool_destroy(pool); close(fd); buffer->data = data; buffer->data_size = size; buffer->width = width; buffer->height = height; buffer->scale = scale; buffer->buffer_width = buffer_width; buffer->buffer_height = buffer_height; return buffer; } static void buffer_free(struct buffer *buffer) { if (buffer->wl_buffer) { wl_buffer_destroy(buffer->wl_buffer); munmap(buffer->data, buffer->data_size); buffer->wl_buffer = NULL; buffer->in_use = false; } free(buffer); } static void free_border_component(struct border_component *border_component) { if (border_component->wl_surface) { wl_subsurface_destroy(border_component->wl_subsurface); border_component->wl_subsurface = NULL; wl_surface_destroy(border_component->wl_surface); border_component->wl_surface = NULL; } if (border_component->buffer) { buffer_free(border_component->buffer); border_component->buffer = NULL; } if (border_component->output_list.next != NULL) { struct surface_output *surface_output, *surface_output_tmp; wl_list_for_each_safe(surface_output, surface_output_tmp, &border_component->output_list, link) { wl_list_remove(&surface_output->link); free(surface_output); } } } static void libdecor_plugin_gtk_frame_free(struct libdecor_plugin *plugin, struct libdecor_frame *frame) { struct libdecor_frame_gtk *frame_gtk = (struct libdecor_frame_gtk *) frame; g_clear_pointer (&frame_gtk->header, gtk_widget_destroy); g_clear_pointer (&frame_gtk->window, gtk_widget_destroy); free_border_component(&frame_gtk->headerbar); free_border_component(&frame_gtk->shadow); frame_gtk->shadow_showing = false; g_clear_pointer (&frame_gtk->shadow_blur, cairo_surface_destroy); g_clear_pointer (&frame_gtk->title, free); frame_gtk->decoration_type = DECORATION_TYPE_NONE; if (frame_gtk->link.next != NULL) wl_list_remove(&frame_gtk->link); } static bool is_border_surfaces_showing(struct libdecor_frame_gtk *frame_gtk) { return frame_gtk->shadow_showing; } static void hide_border_component(struct border_component *border_component) { if (!border_component->wl_surface) return; wl_surface_attach(border_component->wl_surface, NULL, 0, 0); wl_surface_commit(border_component->wl_surface); } static void hide_border_surfaces(struct libdecor_frame_gtk *frame_gtk) { hide_border_component(&frame_gtk->shadow); frame_gtk->shadow_showing = false; } static struct border_component * get_component_for_surface(struct libdecor_frame_gtk *frame_gtk, const struct wl_surface *surface) { if (frame_gtk->shadow.wl_surface == surface) return &frame_gtk->shadow; if (frame_gtk->headerbar.wl_surface == surface) return &frame_gtk->headerbar; return NULL; } static bool redraw_scale(struct libdecor_frame_gtk *frame_gtk, struct border_component *cmpnt) { struct surface_output *surface_output; int scale = 1; if (cmpnt->wl_surface == NULL) return false; wl_list_for_each(surface_output, &cmpnt->output_list, link) { scale = MAX(scale, surface_output->output->scale); } if (scale != cmpnt->scale) { cmpnt->scale = scale; if ((cmpnt->type != SHADOW) || is_border_surfaces_showing(frame_gtk)) { draw_border_component(frame_gtk, cmpnt, cmpnt->type); return true; } } return false; } static bool add_surface_output(struct libdecor_plugin_gtk *plugin_gtk, struct wl_output *wl_output, struct wl_list *list) { struct output *output; struct surface_output *surface_output; if (!own_output(wl_output)) return false; output = wl_output_get_user_data(wl_output); if (output == NULL) return false; surface_output = zalloc(sizeof *surface_output); surface_output->output = output; wl_list_insert(list, &surface_output->link); return true; } static void surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { struct libdecor_frame_gtk *frame_gtk = data; struct border_component *cmpnt; if (!(own_surface(wl_surface) && own_output(wl_output))) return; cmpnt = get_component_for_surface(frame_gtk, wl_surface); if (cmpnt == NULL) return; if (!add_surface_output(frame_gtk->plugin_gtk, wl_output, &cmpnt->output_list)) return; if (redraw_scale(frame_gtk, cmpnt)) libdecor_frame_toplevel_commit(&frame_gtk->frame); } static bool remove_surface_output(struct wl_list *list, const struct wl_output *wl_output) { struct surface_output *surface_output; wl_list_for_each(surface_output, list, link) { if (surface_output->output->wl_output == wl_output) { wl_list_remove(&surface_output->link); free(surface_output); return true; } } return false; } static void surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { struct libdecor_frame_gtk *frame_gtk = data; struct border_component *cmpnt; if (!(own_surface(wl_surface) && own_output(wl_output))) return; cmpnt = get_component_for_surface(frame_gtk, wl_surface); if (cmpnt == NULL) return; if (!remove_surface_output(&cmpnt->output_list, wl_output)) return; if (redraw_scale(frame_gtk, cmpnt)) libdecor_frame_toplevel_commit(&frame_gtk->frame); } static struct wl_surface_listener surface_listener = { surface_enter, surface_leave, }; static void create_surface_subsurface_pair(struct libdecor_frame_gtk *frame_gtk, struct wl_surface **out_wl_surface, struct wl_subsurface **out_wl_subsurface) { struct libdecor_plugin_gtk *plugin_gtk = frame_gtk->plugin_gtk; struct libdecor_frame *frame = &frame_gtk->frame; struct wl_compositor *wl_compositor = plugin_gtk->wl_compositor; struct wl_subcompositor *wl_subcompositor = plugin_gtk->wl_subcompositor; struct wl_surface *wl_surface; struct wl_surface *parent; struct wl_subsurface *wl_subsurface; wl_surface = wl_compositor_create_surface(wl_compositor); wl_proxy_set_tag((struct wl_proxy *) wl_surface, &libdecor_gtk_proxy_tag); parent = libdecor_frame_get_wl_surface(frame); wl_subsurface = wl_subcompositor_get_subsurface(wl_subcompositor, wl_surface, parent); *out_wl_surface = wl_surface; *out_wl_subsurface = wl_subsurface; } static void ensure_component(struct libdecor_frame_gtk *frame_gtk, struct border_component *cmpnt) { if (!cmpnt->wl_surface) { wl_list_init(&cmpnt->output_list); cmpnt->scale = 1; create_surface_subsurface_pair(frame_gtk, &cmpnt->wl_surface, &cmpnt->wl_subsurface); wl_surface_add_listener(cmpnt->wl_surface, &surface_listener, frame_gtk); } } static void ensure_border_surfaces(struct libdecor_frame_gtk *frame_gtk) { frame_gtk->shadow.type = SHADOW; frame_gtk->shadow.opaque = false; ensure_component(frame_gtk, &frame_gtk->shadow); } static void ensure_title_bar_surfaces(struct libdecor_frame_gtk *frame_gtk) { GtkStyleContext *context_hdr; frame_gtk->headerbar.type = HEADER; frame_gtk->headerbar.opaque = false; ensure_component(frame_gtk, &frame_gtk->headerbar); /* create an offscreen window with a header bar */ /* TODO: This should only be done once at frame consutrction, but then * the window and headerbar would not change style (e.g. backdrop) * after construction. So we just destroy and re-create them. */ /* avoid warning when restoring previously turned off decoration */ if (GTK_IS_WIDGET(frame_gtk->header)) { gtk_widget_destroy(frame_gtk->header); frame_gtk->header = NULL; } /* avoid warning when restoring previously turned off decoration */ if (GTK_IS_WIDGET(frame_gtk->window)) { gtk_widget_destroy(frame_gtk->window); frame_gtk->window = NULL; } frame_gtk->window = gtk_offscreen_window_new(); frame_gtk->header = gtk_header_bar_new(); g_object_get(gtk_widget_get_settings(frame_gtk->window), "gtk-double-click-time", &frame_gtk->plugin_gtk->double_click_time_ms, "gtk-dnd-drag-threshold", &frame_gtk->plugin_gtk->drag_threshold, NULL); /* set as "default" decoration */ g_object_set(frame_gtk->header, "title", libdecor_frame_get_title(&frame_gtk->frame), "has-subtitle", FALSE, "show-close-button", TRUE, NULL); context_hdr = gtk_widget_get_style_context(frame_gtk->header); gtk_style_context_add_class(context_hdr, GTK_STYLE_CLASS_TITLEBAR); gtk_style_context_add_class(context_hdr, "default-decoration"); gtk_window_set_titlebar(GTK_WINDOW(frame_gtk->window), frame_gtk->header); gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(frame_gtk->header), TRUE); gtk_window_set_resizable(GTK_WINDOW(frame_gtk->window), resizable(frame_gtk)); } static void calculate_component_size(struct libdecor_frame_gtk *frame_gtk, enum component component, int *component_x, int *component_y, int *component_width, int *component_height) { struct libdecor_frame *frame = &frame_gtk->frame; int content_width, content_height; content_width = libdecor_frame_get_content_width(frame); content_height = libdecor_frame_get_content_height(frame); /* avoid warning when restoring previously turned off decoration */ const int title_height = GTK_IS_WIDGET(frame_gtk->header) ? gtk_widget_get_allocated_height(frame_gtk->header) : 0; switch (component) { case NONE: *component_width = 0; *component_height = 0; return; case SHADOW: *component_x = -(int)SHADOW_MARGIN; *component_y = -(int)(SHADOW_MARGIN+title_height); *component_width = content_width + 2 * SHADOW_MARGIN; *component_height = content_height + 2 * SHADOW_MARGIN + title_height; return; case HEADER: *component_x = 0; /* reuse product of function call above */ *component_y = - title_height; *component_width = gtk_widget_get_allocated_width(frame_gtk->header); /* reuse product of function call above */ *component_height = title_height; return; } abort(); } static void array_append(enum header_element **array, size_t *n, enum header_element item) { (*n)++; *array = realloc(*array, (*n) * sizeof (enum header_element)); (*array)[(*n)-1] = item; } static void draw_header_background(struct libdecor_frame_gtk *frame_gtk, cairo_t *cr) { /* background */ GtkAllocation allocation; GtkStyleContext* style; gtk_widget_get_allocation(GTK_WIDGET(frame_gtk->header), &allocation); style = gtk_widget_get_style_context(frame_gtk->header); gtk_render_background(style, cr, allocation.x, allocation.y, allocation.width, allocation.height); } static void draw_header_title(struct libdecor_frame_gtk *frame_gtk, cairo_surface_t *surface) { /* title */ GtkWidget *label; GtkAllocation allocation; cairo_surface_t *label_surface = NULL; cairo_t *cr; label = find_widget_by_type(frame_gtk->header, HEADER_TITLE).widget; gtk_widget_get_allocation(label, &allocation); /* create subsection in which to draw label */ label_surface = cairo_surface_create_for_rectangle( surface, allocation.x, allocation.y, allocation.width, allocation.height); cr = cairo_create(label_surface); gtk_widget_size_allocate(label, &allocation); gtk_widget_draw(label, cr); cairo_destroy(cr); cairo_surface_destroy(label_surface); } static void draw_header_button(struct libdecor_frame_gtk *frame_gtk, cairo_t *cr, cairo_surface_t *surface, enum header_element button_type, enum libdecor_window_state window_state) { struct header_element_data elem; GtkWidget *button; GtkStyleContext* button_style; GtkStateFlags style_state; GtkAllocation allocation; gchar *icon_name; int scale; GtkWidget *icon_widget; GtkAllocation allocation_icon; GtkIconInfo* icon_info; double sx, sy; gint icon_width, icon_height; GdkPixbuf* icon_pixbuf; cairo_surface_t* icon_surface; gint width = 0, height = 0; gint left = 0, top = 0, right = 0, bottom = 0; GtkBorder border; GtkBorder padding; elem = find_widget_by_type(frame_gtk->header, button_type); button = elem.widget; if (!button) return; button_style = gtk_widget_get_style_context(button); style_state = elem.state; /* change style based on window state and focus */ if (!(window_state & LIBDECOR_WINDOW_STATE_ACTIVE)) { style_state |= GTK_STATE_FLAG_BACKDROP; } if (frame_gtk->hdr_focus.widget == button) { style_state |= GTK_STATE_FLAG_PRELIGHT; if (frame_gtk->hdr_focus.state & GTK_STATE_FLAG_ACTIVE) { style_state |= GTK_STATE_FLAG_ACTIVE; } } /* background */ gtk_widget_get_clip(button, &allocation); gtk_style_context_save(button_style); gtk_style_context_set_state(button_style, style_state); gtk_render_background(button_style, cr, allocation.x, allocation.y, allocation.width, allocation.height); gtk_render_frame(button_style, cr, allocation.x, allocation.y, allocation.width, allocation.height); gtk_style_context_restore(button_style); /* symbol */ switch (button_type) { case HEADER_MIN: icon_name = "window-minimize-symbolic"; break; case HEADER_MAX: icon_name = (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) ? "window-restore-symbolic" : "window-maximize-symbolic"; break; case HEADER_CLOSE: icon_name = "window-close-symbolic"; break; default: icon_name = NULL; break; } /* get scale */ cairo_surface_get_device_scale(surface, &sx, &sy); scale = (sx+sy) / 2.0; /* get original icon dimensions */ icon_widget = gtk_bin_get_child(GTK_BIN(button)); gtk_widget_get_allocation(icon_widget, &allocation_icon); /* icon info */ if (!gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &icon_width, &icon_height)) { icon_width = 16; icon_height = 16; } icon_info = gtk_icon_theme_lookup_icon_for_scale( gtk_icon_theme_get_default(), icon_name, icon_width, scale, (GtkIconLookupFlags)0); /* icon pixel buffer*/ gtk_style_context_save(button_style); gtk_style_context_set_state(button_style, style_state); icon_pixbuf = gtk_icon_info_load_symbolic_for_context( icon_info, button_style, NULL, NULL); icon_surface = gdk_cairo_surface_create_from_pixbuf(icon_pixbuf, scale, NULL); gtk_style_context_restore(button_style); /* dimensions and position */ gtk_style_context_get(button_style, gtk_style_context_get_state(button_style), "min-width", &width, "min-height", &height, NULL); if (width < icon_width) width = icon_width; if (height < icon_height) height = icon_height; gtk_style_context_get_border(button_style, gtk_style_context_get_state(button_style), &border); left += border.left; right += border.right; top += border.top; bottom += border.bottom; gtk_style_context_get_padding(button_style, gtk_style_context_get_state(button_style), &padding); left += padding.left; right += padding.right; top += padding.top; bottom += padding.bottom; width += left + right; height += top + bottom; gtk_render_icon_surface(gtk_widget_get_style_context(icon_widget), cr, icon_surface, allocation.x + ((width - icon_width) / 2), allocation.y + ((height - icon_height) / 2)); cairo_paint(cr); cairo_surface_destroy(icon_surface); g_object_unref(icon_pixbuf); } static void draw_header_buttons(struct libdecor_frame_gtk *frame_gtk, cairo_t *cr, cairo_surface_t *surface) { /* buttons */ enum libdecor_window_state window_state; enum header_element *buttons = NULL; size_t nbuttons = 0; window_state = libdecor_frame_get_window_state( (struct libdecor_frame*)frame_gtk); /* set buttons by capability */ if (minimizable(frame_gtk)) array_append(&buttons, &nbuttons, HEADER_MIN); if (resizable(frame_gtk)) array_append(&buttons, &nbuttons, HEADER_MAX); if (closeable(frame_gtk)) array_append(&buttons, &nbuttons, HEADER_CLOSE); for (size_t i = 0; i < nbuttons; i++) { draw_header_button(frame_gtk, cr, surface, buttons[i], window_state); } /* loop buttons */ free(buttons); } static void draw_header(struct libdecor_frame_gtk *frame_gtk, cairo_t *cr, cairo_surface_t *surface) { draw_header_background(frame_gtk, cr); draw_header_title(frame_gtk, surface); draw_header_buttons(frame_gtk, cr, surface); } static void draw_component_content(struct libdecor_frame_gtk *frame_gtk, struct buffer *buffer, int component_width, int component_height, enum component component) { cairo_surface_t *surface; cairo_t *cr; /* clear buffer */ memset(buffer->data, 0, buffer->data_size); surface = cairo_image_surface_create_for_data( buffer->data, CAIRO_FORMAT_ARGB32, buffer->buffer_width, buffer->buffer_height, cairo_format_stride_for_width( CAIRO_FORMAT_ARGB32, buffer->buffer_width) ); cr = cairo_create(surface); cairo_surface_set_device_scale(surface, buffer->scale, buffer->scale); /* background */ switch (component) { case NONE: break; case SHADOW: render_shadow(cr, frame_gtk->shadow_blur, -(int)SHADOW_MARGIN/2, -(int)SHADOW_MARGIN/2, buffer->width + SHADOW_MARGIN, buffer->height + SHADOW_MARGIN, 64, 64); break; case HEADER: draw_header(frame_gtk, cr, surface); break; } /* mask the toplevel surface */ if (component == SHADOW) { int component_x, component_y, component_width, component_height; calculate_component_size(frame_gtk, component, &component_x, &component_y, &component_width, &component_height); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_rectangle(cr, -component_x, -component_y, libdecor_frame_get_content_width( &frame_gtk->frame), libdecor_frame_get_content_height( &frame_gtk->frame)); cairo_fill(cr); } cairo_destroy(cr); cairo_surface_destroy(surface); } static void set_component_input_region(struct libdecor_frame_gtk *frame_gtk, struct border_component *border_component) { if (border_component->type == SHADOW && frame_gtk->shadow_showing) { struct wl_region *input_region; int component_x; int component_y; int component_width; int component_height; calculate_component_size(frame_gtk, border_component->type, &component_x, &component_y, &component_width, &component_height); /* * the input region is the outer surface size minus the inner * content size */ input_region = wl_compositor_create_region( frame_gtk->plugin_gtk->wl_compositor); wl_region_add(input_region, 0, 0, component_width, component_height); wl_region_subtract(input_region, -component_x, -component_y, libdecor_frame_get_content_width(&frame_gtk->frame), libdecor_frame_get_content_height(&frame_gtk->frame)); wl_surface_set_input_region(border_component->wl_surface, input_region); wl_region_destroy(input_region); } } static void draw_border_component(struct libdecor_frame_gtk *frame_gtk, struct border_component *border_component, enum component component) { struct libdecor_plugin_gtk *plugin_gtk = frame_gtk->plugin_gtk; struct buffer *old_buffer; struct buffer *buffer = NULL; int component_x; int component_y; int component_width; int component_height; int scale = border_component->scale; if (border_component->wl_surface == NULL) return; calculate_component_size(frame_gtk, component, &component_x, &component_y, &component_width, &component_height); set_component_input_region(frame_gtk, border_component); old_buffer = border_component->buffer; if (old_buffer) { if (!old_buffer->in_use && old_buffer->buffer_width == component_width * scale && old_buffer->buffer_height == component_height * scale) { buffer = old_buffer; } else { buffer_free(old_buffer); border_component->buffer = NULL; } } if (!buffer) buffer = create_shm_buffer(plugin_gtk, component_width, component_height, border_component->opaque, border_component->scale); draw_component_content(frame_gtk, buffer, component_width, component_height, component); wl_surface_attach(border_component->wl_surface, buffer->wl_buffer, 0, 0); wl_surface_set_buffer_scale(border_component->wl_surface, buffer->scale); buffer->in_use = true; wl_surface_commit(border_component->wl_surface); wl_surface_damage_buffer(border_component->wl_surface, 0, 0, component_width * scale, component_height * scale); wl_subsurface_set_position(border_component->wl_subsurface, component_x, component_y); border_component->buffer = buffer; } static void draw_border(struct libdecor_frame_gtk *frame_gtk) { draw_border_component(frame_gtk, &frame_gtk->shadow, SHADOW); frame_gtk->shadow_showing = true; } static void draw_title_bar(struct libdecor_frame_gtk *frame_gtk) { GtkAllocation allocation = {0, 0, frame_gtk->content_width, 0}; enum libdecor_window_state state; GtkStyleContext *style; int pref_width; int current_min_w, current_min_h, current_max_w, current_max_h, W, H; state = libdecor_frame_get_window_state((struct libdecor_frame*)frame_gtk); style = gtk_widget_get_style_context(frame_gtk->window); if (!(state & LIBDECOR_WINDOW_STATE_ACTIVE)) { gtk_widget_set_state_flags(frame_gtk->window, GTK_STATE_FLAG_BACKDROP, true); } else { gtk_widget_unset_state_flags(frame_gtk->window, GTK_STATE_FLAG_BACKDROP); } if (libdecor_frame_is_floating(&frame_gtk->frame)) { gtk_style_context_remove_class(style, "maximized"); } else { gtk_style_context_add_class(style, "maximized"); } gtk_widget_show_all(frame_gtk->window); /* set default width, using an empty title to estimate its smallest admissible value */ gtk_header_bar_set_title(GTK_HEADER_BAR(frame_gtk->header), ""); gtk_widget_get_preferred_width(frame_gtk->header, NULL, &pref_width); gtk_header_bar_set_title(GTK_HEADER_BAR(frame_gtk->header), libdecor_frame_get_title(&frame_gtk->frame)); libdecor_frame_get_min_content_size(&frame_gtk->frame, ¤t_min_w, ¤t_min_h); if (current_min_w < pref_width) { current_min_w = pref_width; libdecor_frame_set_min_content_size(&frame_gtk->frame, current_min_w, current_min_h); } libdecor_frame_get_max_content_size(&frame_gtk->frame, ¤t_max_w, ¤t_max_h); if (current_max_w && current_max_w < current_min_w) { libdecor_frame_set_max_content_size(&frame_gtk->frame, current_min_w, current_max_h); } W = libdecor_frame_get_content_width(&frame_gtk->frame); H = libdecor_frame_get_content_height(&frame_gtk->frame); if (W < current_min_w) { W = current_min_w; struct libdecor_state *libdecor_state = libdecor_state_new(W, H); libdecor_frame_commit(&frame_gtk->frame, libdecor_state, NULL); libdecor_state_free(libdecor_state); return; } /* set default height */ gtk_widget_get_preferred_height(frame_gtk->header, NULL, &allocation.height); gtk_widget_size_allocate(frame_gtk->header, &allocation); draw_border_component(frame_gtk, &frame_gtk->headerbar, HEADER); } static void draw_decoration(struct libdecor_frame_gtk *frame_gtk) { switch (frame_gtk->decoration_type) { case DECORATION_TYPE_NONE: if (frame_gtk->link.next != NULL) wl_list_remove(&frame_gtk->link); if (is_border_surfaces_showing(frame_gtk)) hide_border_surfaces(frame_gtk); hide_border_component(&frame_gtk->headerbar); break; case DECORATION_TYPE_ALL: /* show borders */ ensure_border_surfaces(frame_gtk); draw_border(frame_gtk); /* show title bar */ ensure_title_bar_surfaces(frame_gtk); draw_title_bar(frame_gtk); /* link frame */ if (frame_gtk->link.next == NULL) wl_list_insert( &frame_gtk->plugin_gtk->visible_frame_list, &frame_gtk->link); break; case DECORATION_TYPE_TITLE_ONLY: /* hide borders */ if (is_border_surfaces_showing(frame_gtk)) hide_border_surfaces(frame_gtk); /* show title bar */ ensure_title_bar_surfaces(frame_gtk); draw_title_bar(frame_gtk); /* link frame */ if (frame_gtk->link.next == NULL) wl_list_insert( &frame_gtk->plugin_gtk->visible_frame_list, &frame_gtk->link); break; } } static enum decoration_type window_state_to_decoration_type(enum libdecor_window_state window_state) { if (window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN) return DECORATION_TYPE_NONE; else if (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED || window_state & LIBDECOR_WINDOW_STATE_TILED_LEFT || window_state & LIBDECOR_WINDOW_STATE_TILED_RIGHT || window_state & LIBDECOR_WINDOW_STATE_TILED_TOP || window_state & LIBDECOR_WINDOW_STATE_TILED_BOTTOM) /* title bar, no shadows */ return DECORATION_TYPE_TITLE_ONLY; else /* title bar, shadows */ return DECORATION_TYPE_ALL; } static void libdecor_plugin_gtk_frame_commit(struct libdecor_plugin *plugin, struct libdecor_frame *frame, struct libdecor_state *state, struct libdecor_configuration *configuration) { struct libdecor_frame_gtk *frame_gtk = (struct libdecor_frame_gtk *) frame; enum libdecor_window_state old_window_state; enum libdecor_window_state new_window_state; int old_content_width, old_content_height; int new_content_width, new_content_height; enum decoration_type old_decoration_type; enum decoration_type new_decoration_type; old_window_state = frame_gtk->window_state; new_window_state = libdecor_frame_get_window_state(frame); old_content_width = frame_gtk->content_width; old_content_height = frame_gtk->content_height; new_content_width = libdecor_frame_get_content_width(frame); new_content_height = libdecor_frame_get_content_height(frame); old_decoration_type = frame_gtk->decoration_type; new_decoration_type = window_state_to_decoration_type(new_window_state); if (old_decoration_type == new_decoration_type && old_content_width == new_content_width && old_content_height == new_content_height && old_window_state == new_window_state) return; frame_gtk->content_width = new_content_width; frame_gtk->content_height = new_content_height; frame_gtk->window_state = new_window_state; frame_gtk->decoration_type = new_decoration_type; draw_decoration(frame_gtk); /* set fixed window size */ if (!resizable(frame_gtk)) { libdecor_frame_set_min_content_size(frame, frame_gtk->content_width, frame_gtk->content_height); libdecor_frame_set_max_content_size(frame, frame_gtk->content_width, frame_gtk->content_height); } } static void libdecor_plugin_gtk_frame_property_changed(struct libdecor_plugin *plugin, struct libdecor_frame *frame) { struct libdecor_frame_gtk *frame_gtk = (struct libdecor_frame_gtk *) frame; bool redraw_needed = false; const char *new_title; /* * when in SSD mode, the window title is not to be managed by GTK; * this is detected by frame_gtk->header not being a proper GTK widget */ if (!GTK_IS_WIDGET(frame_gtk->header)) return; new_title = libdecor_frame_get_title(frame); if (!streq(frame_gtk->title, new_title)) redraw_needed = true; free(frame_gtk->title); frame_gtk->title = NULL; if (new_title) frame_gtk->title = strdup(new_title); if (frame_gtk->capabilities != libdecor_frame_get_capabilities(frame)) { frame_gtk->capabilities = libdecor_frame_get_capabilities(frame); redraw_needed = true; } if (redraw_needed) { draw_decoration(frame_gtk); libdecor_frame_toplevel_commit(frame); } } static void update_component_focus(struct libdecor_frame_gtk *frame_gtk, struct wl_surface *surface, struct seat *seat) { static struct border_component *border_component; static struct border_component *child_component; static struct border_component *focus_component; border_component = get_component_for_surface(frame_gtk, surface); focus_component = border_component; wl_list_for_each(child_component, &border_component->child_components, link) { int component_x = 0, component_y = 0; int component_width = 0, component_height = 0; calculate_component_size(frame_gtk, child_component->type, &component_x, &component_y, &component_width, &component_height); if (seat->pointer_x >= component_x && seat->pointer_x < component_x + component_width && seat->pointer_y >= component_y && seat->pointer_y < component_y + component_height) { focus_component = child_component; break; } } if (frame_gtk->grab) frame_gtk->active = frame_gtk->grab; else frame_gtk->active = focus_component; frame_gtk->focus = focus_component; } static void sync_active_component(struct libdecor_frame_gtk *frame_gtk, struct seat *seat) { struct border_component *old_active; if (!seat->pointer_focus) return; old_active = frame_gtk->active; update_component_focus(frame_gtk, seat->pointer_focus, seat); if (old_active != frame_gtk->active) { draw_decoration(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); } if (update_local_cursor(seat)) send_cursor(seat); } static void synthesize_pointer_enter(struct seat *seat) { struct wl_surface *surface; struct libdecor_frame_gtk *frame_gtk; surface = seat->pointer_focus; if (!surface) return; frame_gtk = wl_surface_get_user_data(surface); if (!frame_gtk) return; update_component_focus(frame_gtk, seat->pointer_focus, seat); frame_gtk->grab = NULL; /* update decorations */ if (frame_gtk->active) { draw_decoration(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); } update_local_cursor(seat); send_cursor(seat); } static void synthesize_pointer_leave(struct seat *seat) { struct wl_surface *surface; struct libdecor_frame_gtk *frame_gtk; surface = seat->pointer_focus; if (!surface) return; frame_gtk = wl_surface_get_user_data(surface); if (!frame_gtk) return; if (!frame_gtk->active) return; frame_gtk->active = NULL; draw_decoration(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); update_local_cursor(seat); } static void libdecor_plugin_gtk_frame_popup_grab(struct libdecor_plugin *plugin, struct libdecor_frame *frame, const char *seat_name) { struct libdecor_frame_gtk *frame_gtk = (struct libdecor_frame_gtk *) frame; struct libdecor_plugin_gtk *plugin_gtk = frame_gtk->plugin_gtk; struct seat *seat; wl_list_for_each(seat, &plugin_gtk->seat_list, link) { if (streq(seat->name, seat_name)) { if (seat->grabbed) { fprintf(stderr, "libdecor-WARNING: Application " "tried to grab seat twice\n"); } synthesize_pointer_leave(seat); seat->grabbed = true; return; } } fprintf(stderr, "libdecor-WARNING: Application tried to grab unknown seat\n"); } static void libdecor_plugin_gtk_frame_popup_ungrab(struct libdecor_plugin *plugin, struct libdecor_frame *frame, const char *seat_name) { struct libdecor_frame_gtk *frame_gtk = (struct libdecor_frame_gtk *) frame; struct libdecor_plugin_gtk *plugin_gtk = frame_gtk->plugin_gtk; struct seat *seat; wl_list_for_each(seat, &plugin_gtk->seat_list, link) { if (streq(seat->name, seat_name)) { if (!seat->grabbed) { fprintf(stderr, "libdecor-WARNING: Application " "tried to ungrab seat twice\n"); } seat->grabbed = false; synthesize_pointer_enter(seat); sync_active_component(frame_gtk, seat); return; } } fprintf(stderr, "libdecor-WARNING: Application tried to ungrab unknown seat\n"); } static bool libdecor_plugin_gtk_frame_get_border_size(struct libdecor_plugin *plugin, struct libdecor_frame *frame, struct libdecor_configuration *configuration, int *left, int *right, int *top, int *bottom) { enum libdecor_window_state window_state; if (configuration) { if (!libdecor_configuration_get_window_state( configuration, &window_state)) return false; } else { window_state = libdecor_frame_get_window_state(frame); } if (left) *left = 0; if (right) *right = 0; if (bottom) *bottom = 0; if (top) { GtkWidget *header = ((struct libdecor_frame_gtk *)frame)->header; enum decoration_type type = window_state_to_decoration_type(window_state); /* avoid warnings after decoration has been turned off */ if (GTK_IS_WIDGET(header) && (type != DECORATION_TYPE_NONE)) { /* Redraw title bar to ensure size will be up-to-date */ if (configuration && type == DECORATION_TYPE_TITLE_ONLY) draw_title_bar((struct libdecor_frame_gtk *) frame); *top = gtk_widget_get_allocated_height(header); } else { *top = 0; } } return true; } static struct libdecor_plugin_interface gtk_plugin_iface = { .destroy = libdecor_plugin_gtk_destroy, .get_fd = libdecor_plugin_gtk_get_fd, .dispatch = libdecor_plugin_gtk_dispatch, .frame_new = libdecor_plugin_gtk_frame_new, .frame_free = libdecor_plugin_gtk_frame_free, .frame_commit = libdecor_plugin_gtk_frame_commit, .frame_property_changed = libdecor_plugin_gtk_frame_property_changed, .frame_popup_grab = libdecor_plugin_gtk_frame_popup_grab, .frame_popup_ungrab = libdecor_plugin_gtk_frame_popup_ungrab, .frame_get_border_size = libdecor_plugin_gtk_frame_get_border_size, }; static void init_wl_compositor(struct libdecor_plugin_gtk *plugin_gtk, uint32_t id, uint32_t version) { plugin_gtk->wl_compositor = wl_registry_bind(plugin_gtk->wl_registry, id, &wl_compositor_interface, MIN(version, 4)); } static void init_wl_subcompositor(struct libdecor_plugin_gtk *plugin_gtk, uint32_t id, uint32_t version) { plugin_gtk->wl_subcompositor = wl_registry_bind(plugin_gtk->wl_registry, id, &wl_subcompositor_interface, 1); } static void shm_format(void *user_data, struct wl_shm *wl_shm, uint32_t format) { struct libdecor_plugin_gtk *plugin_gtk = user_data; if (format == WL_SHM_FORMAT_ARGB8888) plugin_gtk->has_argb = true; } struct wl_shm_listener shm_listener = { shm_format }; static void shm_callback(void *user_data, struct wl_callback *callback, uint32_t time) { struct libdecor_plugin_gtk *plugin_gtk = user_data; struct libdecor *context = plugin_gtk->context; wl_callback_destroy(callback); plugin_gtk->globals_callback_shm = NULL; if (!plugin_gtk->has_argb) { libdecor_notify_plugin_error( context, LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE, "Compositor is missing required shm format"); return; } libdecor_notify_plugin_ready(context); } static const struct wl_callback_listener shm_callback_listener = { shm_callback }; static void init_wl_shm(struct libdecor_plugin_gtk *plugin_gtk, uint32_t id, uint32_t version) { struct libdecor *context = plugin_gtk->context; struct wl_display *wl_display = libdecor_get_wl_display(context); plugin_gtk->wl_shm = wl_registry_bind(plugin_gtk->wl_registry, id, &wl_shm_interface, 1); wl_shm_add_listener(plugin_gtk->wl_shm, &shm_listener, plugin_gtk); plugin_gtk->globals_callback_shm = wl_display_sync(wl_display); wl_callback_add_listener(plugin_gtk->globals_callback_shm, &shm_callback_listener, plugin_gtk); } static void cursor_surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { struct seat *seat = data; if (own_output(wl_output)) { struct cursor_output *cursor_output; cursor_output = zalloc(sizeof *cursor_output); cursor_output->output = wl_output_get_user_data(wl_output); wl_list_insert(&seat->cursor_outputs, &cursor_output->link); if (update_local_cursor(seat)) send_cursor(seat); } } static void cursor_surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { struct seat *seat = data; if (own_output(wl_output)) { struct cursor_output *cursor_output, *tmp; wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link) { if (cursor_output->output->wl_output == wl_output) { wl_list_remove(&cursor_output->link); free(cursor_output); } } if (update_local_cursor(seat)) send_cursor(seat); } } static struct wl_surface_listener cursor_surface_listener = { cursor_surface_enter, cursor_surface_leave, }; static void ensure_cursor_surface(struct seat *seat) { struct wl_compositor *wl_compositor = seat->plugin_gtk->wl_compositor; if (seat->cursor_surface) return; seat->cursor_surface = wl_compositor_create_surface(wl_compositor); wl_surface_add_listener(seat->cursor_surface, &cursor_surface_listener, seat); } static bool ensure_cursor_theme(struct seat *seat) { struct libdecor_plugin_gtk *plugin_gtk = seat->plugin_gtk; int scale = 1; struct wl_cursor_theme *theme; struct cursor_output *cursor_output; wl_list_for_each(cursor_output, &seat->cursor_outputs, link) { scale = MAX(scale, cursor_output->output->scale); } if (seat->cursor_theme && seat->cursor_scale == scale) return false; seat->cursor_scale = scale; theme = wl_cursor_theme_load(plugin_gtk->cursor_theme_name, plugin_gtk->cursor_size * scale, plugin_gtk->wl_shm); if (theme == NULL) return false; if (seat->cursor_theme) wl_cursor_theme_destroy(seat->cursor_theme); seat->cursor_theme = theme; for (unsigned int i = 0; i < ARRAY_LENGTH(cursor_names); i++) { seat->cursors[i] = wl_cursor_theme_get_cursor( seat->cursor_theme, cursor_names[i]); } seat->cursor_left_ptr = wl_cursor_theme_get_cursor(seat->cursor_theme, "left_ptr"); seat->current_cursor = seat->cursor_left_ptr; return true; } enum libdecor_resize_edge component_edge(const struct border_component *cmpnt, const int pointer_x, const int pointer_y, const int margin) { const bool top = pointer_y < margin * 2; const bool bottom = pointer_y > (cmpnt->buffer->height - margin * 2); const bool left = pointer_x < margin * 2; const bool right = pointer_x > (cmpnt->buffer->width - margin * 2); if (top) { if (left) return LIBDECOR_RESIZE_EDGE_TOP_LEFT; else if (right) return LIBDECOR_RESIZE_EDGE_TOP_RIGHT; else return LIBDECOR_RESIZE_EDGE_TOP; } else if (bottom) { if (left) return LIBDECOR_RESIZE_EDGE_BOTTOM_LEFT; else if (right) return LIBDECOR_RESIZE_EDGE_BOTTOM_RIGHT; else return LIBDECOR_RESIZE_EDGE_BOTTOM; } else if (left) { return LIBDECOR_RESIZE_EDGE_LEFT; } else if (right) { return LIBDECOR_RESIZE_EDGE_RIGHT; } else { return LIBDECOR_RESIZE_EDGE_NONE; } } static bool update_local_cursor(struct seat *seat) { if (!seat->pointer_focus) { seat->current_cursor = seat->cursor_left_ptr; return false; } if (!own_surface(seat->pointer_focus)) return false; struct libdecor_frame_gtk *frame_gtk = wl_surface_get_user_data(seat->pointer_focus); struct wl_cursor *wl_cursor = NULL; if (!frame_gtk || !frame_gtk->active) { seat->current_cursor = seat->cursor_left_ptr; return false; } bool theme_updated = ensure_cursor_theme(seat); if (frame_gtk->active->type == SHADOW && is_border_surfaces_showing(frame_gtk) && resizable(frame_gtk)) { enum libdecor_resize_edge edge; edge = component_edge(frame_gtk->active, seat->pointer_x, seat->pointer_y, SHADOW_MARGIN); if (edge != LIBDECOR_RESIZE_EDGE_NONE) wl_cursor = seat->cursors[edge - 1]; } else { wl_cursor = seat->cursor_left_ptr; } if (seat->current_cursor != wl_cursor) { seat->current_cursor = wl_cursor; return true; } return theme_updated; } static void send_cursor(struct seat *seat) { struct wl_cursor_image *image; struct wl_buffer *buffer; if (seat->pointer_focus == NULL || seat->current_cursor == NULL) return; image = seat->current_cursor->images[0]; buffer = wl_cursor_image_get_buffer(image); wl_surface_attach(seat->cursor_surface, buffer, 0, 0); wl_surface_set_buffer_scale(seat->cursor_surface, seat->cursor_scale); wl_surface_damage_buffer(seat->cursor_surface, 0, 0, image->width * seat->cursor_scale, image->height * seat->cursor_scale); wl_surface_commit(seat->cursor_surface); wl_pointer_set_cursor(seat->wl_pointer, seat->serial, seat->cursor_surface, image->hotspot_x / seat->cursor_scale, image->hotspot_y / seat->cursor_scale); } static void pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { if (!surface) return; struct seat *seat = data; struct libdecor_frame_gtk *frame_gtk; if (!own_surface(surface)) return; frame_gtk = wl_surface_get_user_data(surface); ensure_cursor_surface(seat); seat->pointer_x = wl_fixed_to_int(surface_x); seat->pointer_y = wl_fixed_to_int(surface_y); seat->serial = serial; seat->pointer_focus = surface; if (!frame_gtk) return; frame_gtk->active = get_component_for_surface(frame_gtk, surface); /* update decorations */ if (frame_gtk->active) { draw_decoration(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); } update_local_cursor(seat); send_cursor(seat); } static void pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) { if (!surface) return; struct seat *seat = data; struct libdecor_frame_gtk *frame_gtk; if (!own_surface(surface)) return; frame_gtk = wl_surface_get_user_data(surface); seat->pointer_focus = NULL; if (frame_gtk) { frame_gtk->titlebar_gesture.state = TITLEBAR_GESTURE_STATE_INIT; frame_gtk->titlebar_gesture.first_pressed_button = 0; frame_gtk->active = NULL; frame_gtk->hdr_focus.widget = NULL; frame_gtk->hdr_focus.type = HEADER_NONE; draw_decoration(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); update_local_cursor(seat); } } static void pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct seat *seat = data; struct libdecor_frame_gtk *frame_gtk; struct header_element_data new_focus; if (!seat->pointer_focus || !own_surface(seat->pointer_focus)) return; seat->pointer_x = wl_fixed_to_int(surface_x); seat->pointer_y = wl_fixed_to_int(surface_y); if (update_local_cursor(seat)) send_cursor(seat); frame_gtk = wl_surface_get_user_data(seat->pointer_focus); /* avoid warnings after decoration has been turned off */ if (!GTK_IS_WIDGET(frame_gtk->header) || frame_gtk->active->type != HEADER) { frame_gtk->hdr_focus.type = HEADER_NONE; } new_focus = get_header_focus(GTK_HEADER_BAR(frame_gtk->header), seat->pointer_x, seat->pointer_y); /* only update if widget change so that we keep the state */ if (frame_gtk->hdr_focus.widget != new_focus.widget) { frame_gtk->hdr_focus = new_focus; } frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_PRELIGHT; /* redraw with updated button visuals */ draw_title_bar(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); switch (frame_gtk->titlebar_gesture.state) { case TITLEBAR_GESTURE_STATE_BUTTON_PRESSED: if (frame_gtk->titlebar_gesture.first_pressed_button == BTN_LEFT) { if (ABS ((double) seat->pointer_x - (double) frame_gtk->titlebar_gesture.pressed_x) > frame_gtk->plugin_gtk->drag_threshold || ABS ((double) seat->pointer_y - (double) frame_gtk->titlebar_gesture.pressed_y) > frame_gtk->plugin_gtk->drag_threshold) { libdecor_frame_move(&frame_gtk->frame, seat->wl_seat, frame_gtk->titlebar_gesture.pressed_serial); } } case TITLEBAR_GESTURE_STATE_INIT: case TITLEBAR_GESTURE_STATE_CONSUMED: case TITLEBAR_GESTURE_STATE_DISCARDED: break; } } static void handle_button_on_shadow(struct libdecor_frame_gtk *frame_gtk, struct seat *seat, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { enum libdecor_resize_edge edge = LIBDECOR_RESIZE_EDGE_NONE; edge = component_edge(frame_gtk->active, seat->pointer_x, seat->pointer_y, SHADOW_MARGIN); if (edge != LIBDECOR_RESIZE_EDGE_NONE && resizable(frame_gtk)) { libdecor_frame_resize(&frame_gtk->frame, seat->wl_seat, serial, edge); } } enum titlebar_gesture { TITLEBAR_GESTURE_DOUBLE_CLICK, TITLEBAR_GESTURE_MIDDLE_CLICK, TITLEBAR_GESTURE_RIGHT_CLICK, }; static void handle_titlebar_gesture(struct libdecor_frame_gtk *frame_gtk, struct seat *seat, uint32_t serial, enum titlebar_gesture gesture) { switch (gesture) { case TITLEBAR_GESTURE_DOUBLE_CLICK: toggle_maximized(&frame_gtk->frame); break; case TITLEBAR_GESTURE_MIDDLE_CLICK: break; case TITLEBAR_GESTURE_RIGHT_CLICK: { const int title_height = gtk_widget_get_allocated_height(frame_gtk->header); libdecor_frame_show_window_menu(&frame_gtk->frame, seat->wl_seat, serial, seat->pointer_x, seat->pointer_y -title_height); } break; } } static void handle_button_on_header(struct libdecor_frame_gtk *frame_gtk, struct seat *seat, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { switch (frame_gtk->titlebar_gesture.state) { case TITLEBAR_GESTURE_STATE_INIT: if (state != WL_POINTER_BUTTON_STATE_PRESSED) return; if (button == BTN_RIGHT) { handle_titlebar_gesture(frame_gtk, seat, serial, TITLEBAR_GESTURE_RIGHT_CLICK); frame_gtk->titlebar_gesture.state = TITLEBAR_GESTURE_STATE_CONSUMED; } else { if (button == BTN_LEFT && frame_gtk->titlebar_gesture.first_pressed_button == BTN_LEFT && time - frame_gtk->titlebar_gesture.first_pressed_time < (uint32_t) frame_gtk->plugin_gtk->double_click_time_ms) { handle_titlebar_gesture(frame_gtk, seat, serial, TITLEBAR_GESTURE_DOUBLE_CLICK); frame_gtk->titlebar_gesture.state = TITLEBAR_GESTURE_STATE_CONSUMED; } else { frame_gtk->titlebar_gesture.first_pressed_button = button; frame_gtk->titlebar_gesture.first_pressed_time = time; frame_gtk->titlebar_gesture.pressed_x = seat->pointer_x; frame_gtk->titlebar_gesture.pressed_y = seat->pointer_y; frame_gtk->titlebar_gesture.pressed_serial = serial; frame_gtk->titlebar_gesture.state = TITLEBAR_GESTURE_STATE_BUTTON_PRESSED; } } frame_gtk->titlebar_gesture.button_pressed_count = 1; switch (frame_gtk->hdr_focus.type) { case HEADER_MIN: case HEADER_MAX: case HEADER_CLOSE: frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_ACTIVE; draw_title_bar(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); break; default: break; } break; case TITLEBAR_GESTURE_STATE_BUTTON_PRESSED: if (state == WL_POINTER_BUTTON_STATE_PRESSED) { frame_gtk->titlebar_gesture.state = TITLEBAR_GESTURE_STATE_DISCARDED; frame_gtk->titlebar_gesture.button_pressed_count++; } else { frame_gtk->titlebar_gesture.button_pressed_count--; if (frame_gtk->titlebar_gesture.button_pressed_count == 0) { frame_gtk->titlebar_gesture.state = TITLEBAR_GESTURE_STATE_INIT; if (frame_gtk->titlebar_gesture.first_pressed_button == button && button == BTN_LEFT) { libdecor_frame_ref(&frame_gtk->frame); switch (frame_gtk->hdr_focus.type) { case HEADER_MIN: if (minimizable(frame_gtk)) libdecor_frame_set_minimized( &frame_gtk->frame); break; case HEADER_MAX: toggle_maximized(&frame_gtk->frame); break; case HEADER_CLOSE: if (closeable(frame_gtk)) { libdecor_frame_close( &frame_gtk->frame); seat->pointer_focus = NULL; } break; default: break; } frame_gtk->hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; if (GTK_IS_WIDGET(frame_gtk->header)) { draw_title_bar(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); } libdecor_frame_unref(&frame_gtk->frame); } } else { frame_gtk->hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; if (GTK_IS_WIDGET(frame_gtk->header)) { draw_title_bar(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); } } } break; case TITLEBAR_GESTURE_STATE_CONSUMED: case TITLEBAR_GESTURE_STATE_DISCARDED: if (state == WL_POINTER_BUTTON_STATE_PRESSED) { frame_gtk->titlebar_gesture.button_pressed_count++; } else { frame_gtk->titlebar_gesture.button_pressed_count--; if (frame_gtk->titlebar_gesture.button_pressed_count == 0) { frame_gtk->titlebar_gesture.state = TITLEBAR_GESTURE_STATE_INIT; frame_gtk->titlebar_gesture.first_pressed_button = 0; } } break; } } static void pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { struct seat *seat = data; struct libdecor_frame_gtk *frame_gtk; if (!seat->pointer_focus || !own_surface(seat->pointer_focus)) return; frame_gtk = wl_surface_get_user_data(seat->pointer_focus); if (!frame_gtk) return; switch (frame_gtk->active->type) { case SHADOW: handle_button_on_shadow (frame_gtk, seat, serial, time, button, state); break; case HEADER: handle_button_on_header (frame_gtk, seat, serial, time, button, state); break; default: break; } } static void pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { } static struct wl_pointer_listener pointer_listener = { pointer_enter, pointer_leave, pointer_motion, pointer_button, pointer_axis }; static void update_touch_focus(struct seat *seat, struct libdecor_frame_gtk *frame_gtk, wl_fixed_t x, wl_fixed_t y) { /* avoid warnings after decoration has been turned off */ if (GTK_IS_WIDGET(frame_gtk->header) && frame_gtk->touch_active->type == HEADER) { struct header_element_data new_focus = get_header_focus( GTK_HEADER_BAR(frame_gtk->header), wl_fixed_to_int(x), wl_fixed_to_int(y)); /* only update if widget change so that we keep the state */ if (frame_gtk->hdr_focus.widget != new_focus.widget) { frame_gtk->hdr_focus = new_focus; } frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_PRELIGHT; /* redraw with updated button visuals */ draw_title_bar(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); } else { frame_gtk->hdr_focus.type = HEADER_NONE; } } static void touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y) { struct seat *seat = data; struct libdecor_frame_gtk *frame_gtk; if (!surface || !own_surface(surface)) return; frame_gtk = wl_surface_get_user_data(surface); if (!frame_gtk) return; seat->touch_focus = surface; frame_gtk->touch_active = get_component_for_surface(frame_gtk, surface); if (!frame_gtk->touch_active) return; update_touch_focus(seat, frame_gtk, x, y); /* update decorations */ draw_decoration(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); enum libdecor_resize_edge edge = LIBDECOR_RESIZE_EDGE_NONE; switch (frame_gtk->touch_active->type) { case SHADOW: edge = component_edge(frame_gtk->touch_active, wl_fixed_to_int(x), wl_fixed_to_int(y), SHADOW_MARGIN); break; case HEADER: switch (frame_gtk->hdr_focus.type) { case HEADER_MIN: case HEADER_MAX: case HEADER_CLOSE: frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_ACTIVE; draw_title_bar(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); break; default: if (time - seat->touch_down_time_stamp < (uint32_t)frame_gtk->plugin_gtk->double_click_time_ms) { toggle_maximized(&frame_gtk->frame); } else if (moveable(frame_gtk)) { seat->touch_down_time_stamp = time; libdecor_frame_move(&frame_gtk->frame, seat->wl_seat, serial); } break; } break; default: break; } if (edge != LIBDECOR_RESIZE_EDGE_NONE && resizable(frame_gtk)) { libdecor_frame_resize( &frame_gtk->frame, seat->wl_seat, serial, edge); } } static void touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id) { struct seat *seat = data; struct libdecor_frame_gtk *frame_gtk; if (!seat->touch_focus || !own_surface(seat->touch_focus)) return; frame_gtk = wl_surface_get_user_data(seat->touch_focus); if (!frame_gtk) return; if (!frame_gtk->touch_active) return; switch (frame_gtk->touch_active->type) { case HEADER: libdecor_frame_ref(&frame_gtk->frame); switch (frame_gtk->hdr_focus.type) { case HEADER_MIN: if (minimizable(frame_gtk)) { libdecor_frame_set_minimized( &frame_gtk->frame); } break; case HEADER_MAX: toggle_maximized(&frame_gtk->frame); break; case HEADER_CLOSE: if (closeable(frame_gtk)) { libdecor_frame_close( &frame_gtk->frame); seat->touch_focus = NULL; } break; default: break; } /* unset active/clicked state once released */ frame_gtk->hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE; if (GTK_IS_WIDGET(frame_gtk->header)) { draw_title_bar(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); } libdecor_frame_unref(&frame_gtk->frame); break; default: break; } seat->touch_focus = NULL; frame_gtk->touch_active = NULL; frame_gtk->hdr_focus.widget = NULL; frame_gtk->hdr_focus.type = HEADER_NONE; draw_decoration(frame_gtk); libdecor_frame_toplevel_commit(&frame_gtk->frame); } static void touch_motion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) { struct seat *seat = data; struct libdecor_frame_gtk *frame_gtk; if (!seat->touch_focus || !own_surface(seat->touch_focus)) return; frame_gtk = wl_surface_get_user_data(seat->touch_focus); if (!frame_gtk) return; update_touch_focus(seat, frame_gtk, x, y); } static void touch_frame(void *data, struct wl_touch *wl_touch) { } static void touch_cancel(void *data, struct wl_touch *wl_touch) { } static struct wl_touch_listener touch_listener = { touch_down, touch_up, touch_motion, touch_frame, touch_cancel }; static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) { struct seat *seat = data; if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !seat->wl_pointer) { seat->wl_pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); } else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer) { wl_pointer_release(seat->wl_pointer); seat->wl_pointer = NULL; } if ((capabilities & WL_SEAT_CAPABILITY_TOUCH) && !seat->wl_touch) { seat->wl_touch = wl_seat_get_touch(wl_seat); wl_touch_add_listener(seat->wl_touch, &touch_listener, seat); } else if (!(capabilities & WL_SEAT_CAPABILITY_TOUCH) && seat->wl_touch) { wl_touch_release(seat->wl_touch); seat->wl_touch = NULL; } } static void seat_name(void *data, struct wl_seat *wl_seat, const char *name) { /* avoid warning messages when opening/closing popup window */ struct seat *seat = (struct seat*)data; seat->name = strdup(name); } static struct wl_seat_listener seat_listener = { seat_capabilities, seat_name }; static void init_wl_seat(struct libdecor_plugin_gtk *plugin_gtk, uint32_t id, uint32_t version) { struct seat *seat; if (version < 3) { libdecor_notify_plugin_error( plugin_gtk->context, LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE, "%s version 3 required but only version %i is available\n", wl_seat_interface.name, version); } seat = zalloc(sizeof *seat); seat->cursor_scale = 1; seat->plugin_gtk = plugin_gtk; wl_list_init(&seat->cursor_outputs); wl_list_insert(&plugin_gtk->seat_list, &seat->link); seat->wl_seat = wl_registry_bind(plugin_gtk->wl_registry, id, &wl_seat_interface, 3); wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); } static void output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char *make, const char *model, int32_t transform) { } static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { } static void output_done(void *data, struct wl_output *wl_output) { struct output *output = data; struct libdecor_frame_gtk *frame_gtk; struct seat *seat; wl_list_for_each(frame_gtk, &output->plugin_gtk->visible_frame_list, link) { bool updated = false; updated |= redraw_scale(frame_gtk, &frame_gtk->shadow); if (updated) libdecor_frame_toplevel_commit(&frame_gtk->frame); } wl_list_for_each(seat, &output->plugin_gtk->seat_list, link) { if (update_local_cursor(seat)) send_cursor(seat); } } static void output_scale(void *data, struct wl_output *wl_output, int32_t factor) { struct output *output = data; output->scale = factor; } static struct wl_output_listener output_listener = { output_geometry, output_mode, output_done, output_scale }; static void init_wl_output(struct libdecor_plugin_gtk *plugin_gtk, uint32_t id, uint32_t version) { struct output *output; if (version < 2) { libdecor_notify_plugin_error( plugin_gtk->context, LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE, "%s version 2 required but only version %i is available\n", wl_output_interface.name, version); } output = zalloc(sizeof *output); output->plugin_gtk = plugin_gtk; wl_list_insert(&plugin_gtk->output_list, &output->link); output->id = id; output->wl_output = wl_registry_bind(plugin_gtk->wl_registry, id, &wl_output_interface, MIN (version, 3)); wl_proxy_set_tag((struct wl_proxy *) output->wl_output, &libdecor_gtk_proxy_tag); wl_output_add_listener(output->wl_output, &output_listener, output); } static void registry_handle_global(void *user_data, struct wl_registry *wl_registry, uint32_t id, const char *interface, uint32_t version) { struct libdecor_plugin_gtk *plugin_gtk = user_data; if (strcmp(interface, "wl_compositor") == 0) init_wl_compositor(plugin_gtk, id, version); else if (strcmp(interface, "wl_subcompositor") == 0) init_wl_subcompositor(plugin_gtk, id, version); else if (strcmp(interface, "wl_shm") == 0) init_wl_shm(plugin_gtk, id, version); else if (strcmp(interface, "wl_seat") == 0) init_wl_seat(plugin_gtk, id, version); else if (strcmp(interface, "wl_output") == 0) init_wl_output(plugin_gtk, id, version); } static void remove_surface_outputs(struct border_component *cmpnt, const struct output *output) { struct surface_output *surface_output; wl_list_for_each(surface_output, &cmpnt->output_list, link) { if (surface_output->output == output) { wl_list_remove(&surface_output->link); free(surface_output); break; } } } static void output_removed(struct libdecor_plugin_gtk *plugin_gtk, struct output *output) { struct libdecor_frame_gtk *frame_gtk; struct seat *seat; wl_list_for_each(frame_gtk, &plugin_gtk->visible_frame_list, link) { remove_surface_outputs(&frame_gtk->shadow, output); } wl_list_for_each(seat, &plugin_gtk->seat_list, link) { struct cursor_output *cursor_output; wl_list_for_each(cursor_output, &seat->cursor_outputs, link) { if (cursor_output->output == output) { wl_list_remove(&cursor_output->link); free(cursor_output); } } } wl_list_remove(&output->link); wl_output_destroy(output->wl_output); free(output); } static void registry_handle_global_remove(void *user_data, struct wl_registry *wl_registry, uint32_t name) { struct libdecor_plugin_gtk *plugin_gtk = user_data; struct output *output; wl_list_for_each(output, &plugin_gtk->output_list, link) { if (output->id == name) { output_removed(plugin_gtk, output); break; } } } static const struct wl_registry_listener registry_listener = { registry_handle_global, registry_handle_global_remove }; static bool has_required_globals(struct libdecor_plugin_gtk *plugin_gtk) { if (!plugin_gtk->wl_compositor) return false; if (!plugin_gtk->wl_subcompositor) return false; if (!plugin_gtk->wl_shm) return false; return true; } static void globals_callback(void *user_data, struct wl_callback *callback, uint32_t time) { struct libdecor_plugin_gtk *plugin_gtk = user_data; wl_callback_destroy(callback); plugin_gtk->globals_callback = NULL; } static const struct wl_callback_listener globals_callback_listener = { globals_callback }; static struct libdecor_plugin * libdecor_plugin_new(struct libdecor *context) { struct libdecor_plugin_gtk *plugin_gtk; struct wl_display *wl_display; #ifdef HAVE_GETTID /* Only support running on the main thread. */ if (getpid () != gettid ()) return NULL; #endif plugin_gtk = zalloc(sizeof *plugin_gtk); libdecor_plugin_init(&plugin_gtk->plugin, context, >k_plugin_iface); plugin_gtk->context = context; wl_list_init(&plugin_gtk->visible_frame_list); wl_list_init(&plugin_gtk->seat_list); wl_list_init(&plugin_gtk->output_list); /* fetch cursor theme and size*/ if (!libdecor_get_cursor_settings(&plugin_gtk->cursor_theme_name, &plugin_gtk->cursor_size)) { plugin_gtk->cursor_theme_name = NULL; plugin_gtk->cursor_size = 24; } plugin_gtk->color_scheme_setting = libdecor_get_color_scheme(); wl_display = libdecor_get_wl_display(context); plugin_gtk->wl_registry = wl_display_get_registry(wl_display); wl_registry_add_listener(plugin_gtk->wl_registry, ®istry_listener, plugin_gtk); plugin_gtk->globals_callback = wl_display_sync(wl_display); wl_callback_add_listener(plugin_gtk->globals_callback, &globals_callback_listener, plugin_gtk); wl_display_roundtrip(wl_display); if (!has_required_globals(plugin_gtk)) { fprintf(stderr, "libdecor-gtk-WARNING: Could not get required globals\n"); libdecor_plugin_gtk_destroy(&plugin_gtk->plugin); return NULL; } /* setup GTK context */ gdk_set_allowed_backends("wayland"); gtk_disable_setlocale(); if (!gtk_init_check(NULL, NULL)) { fprintf(stderr, "libdecor-gtk-WARNING: Failed to initialize GTK\n"); libdecor_plugin_gtk_destroy(&plugin_gtk->plugin); return NULL; } g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme", plugin_gtk->color_scheme_setting == LIBDECOR_COLOR_SCHEME_PREFER_DARK, NULL); return &plugin_gtk->plugin; } static struct libdecor_plugin_priority priorities[] = { { NULL, LIBDECOR_PLUGIN_PRIORITY_HIGH } }; LIBDECOR_EXPORT const struct libdecor_plugin_description libdecor_plugin_description = { .api_version = LIBDECOR_PLUGIN_API_VERSION, .capabilities = LIBDECOR_PLUGIN_CAPABILITY_BASE, .description = "GTK3 plugin", .priorities = priorities, .constructor = libdecor_plugin_new, .conflicting_symbols = { "png_free", NULL, }, }; fltk-1.4.3/libdecor/src/plugins/cairo/0000755000175000017500000000000015004135251017735 5ustar albrechtalbrechtfltk-1.4.3/libdecor/src/plugins/cairo/libdecor-cairo.c0000644000175000017500000021533015004135251022763 0ustar albrechtalbrecht/* * Copyright © 2018 Jonas Ådahl * Copyright © 2019 Christian Rauch * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "libdecor-plugin.h" #include "utils.h" #include "desktop-settings.h" #include "os-compatibility.h" #include #include #include "common/libdecor-cairo-blur.h" static const size_t SHADOW_MARGIN = 24; /* graspable part of the border */ static const size_t TITLE_HEIGHT = 24; static const size_t BUTTON_WIDTH = 32; static const size_t SYM_DIM = 14; static const uint32_t COL_TITLE = 0xFF080706; static const uint32_t COL_TITLE_INACT = 0xFF303030; static const uint32_t COL_BUTTON_MIN = 0xFFFFBB00; static const uint32_t COL_BUTTON_MAX = 0xFF238823; static const uint32_t COL_BUTTON_CLOSE = 0xFFFB6542; static const uint32_t COL_BUTTON_INACT = 0xFF404040; static const uint32_t COL_SYM = 0xFFF4F4EF; static const uint32_t COL_SYM_ACT = 0xFF20322A; static const uint32_t COL_SYM_INACT = 0xFF909090; static const uint32_t DOUBLE_CLICK_TIME_MS = 400; static const char *cursor_names[] = { "top_side", "bottom_side", "left_side", "top_left_corner", "bottom_left_corner", "right_side", "top_right_corner", "bottom_right_corner" }; /* color conversion function from 32bit integer to double components */ double red(const uint32_t *const col) { return ((const uint8_t*)(col))[2] / (double)(255); } double green(const uint32_t *const col) { return ((const uint8_t*)(col))[1] / (double)(255); } double blue(const uint32_t *const col) { return ((const uint8_t*)(col))[0] / (double)(255); } double alpha(const uint32_t *const col) { return ((const uint8_t*)(col))[3] / (double)(255); } void cairo_set_rgba32(cairo_t *cr, const uint32_t *const c) { cairo_set_source_rgba(cr, red(c), green(c), blue(c), alpha(c)); } static bool streql(const char *str1, const char *str2) { return (str1 && str2) && (strcmp(str1, str2) == 0); } enum decoration_type { DECORATION_TYPE_NONE, DECORATION_TYPE_ALL, DECORATION_TYPE_MAXIMIZED, DECORATION_TYPE_TILED }; enum component { NONE = 0, SHADOW, TITLE, BUTTON_MIN, BUTTON_MAX, BUTTON_CLOSE, }; enum composite_mode { COMPOSITE_SERVER, COMPOSITE_CLIENT, }; struct seat { struct libdecor_plugin_cairo *plugin_cairo; char *name; struct wl_seat *wl_seat; struct wl_pointer *wl_pointer; struct wl_surface *cursor_surface; struct wl_cursor *current_cursor; int cursor_scale; struct wl_list cursor_outputs; struct wl_cursor_theme *cursor_theme; /* cursors for resize edges and corners */ struct wl_cursor *cursors[ARRAY_LENGTH(cursor_names)]; struct wl_cursor *cursor_left_ptr; struct wl_surface *pointer_focus; int pointer_x, pointer_y; uint32_t pointer_button_time_stamp; uint32_t serial; bool grabbed; struct wl_list link; }; struct output { struct libdecor_plugin_cairo *plugin_cairo; struct wl_output *wl_output; uint32_t id; int scale; struct wl_list link; }; struct buffer { struct wl_buffer *wl_buffer; bool in_use; bool is_detached; void *data; size_t data_size; int width; int height; int scale; int buffer_width; int buffer_height; }; struct border_component { enum component type; bool is_hidden; bool opaque; enum composite_mode composite_mode; struct { struct wl_surface *wl_surface; struct wl_subsurface *wl_subsurface; struct buffer *buffer; struct wl_list output_list; int scale; } server; struct { cairo_surface_t *image; struct border_component *parent_component; } client; struct wl_list child_components; /* border_component::link */ struct wl_list link; /* border_component::child_components */ }; struct surface_output { struct output *output; struct wl_list link; }; struct cursor_output { struct output *output; struct wl_list link; }; struct libdecor_frame_cairo { struct libdecor_frame frame; struct libdecor_plugin_cairo *plugin_cairo; int content_width; int content_height; enum decoration_type decoration_type; enum libdecor_window_state window_state; char *title; enum libdecor_capabilities capabilities; struct border_component *focus; struct border_component *active; struct border_component *grab; bool shadow_showing; struct border_component shadow; struct { bool is_showing; struct border_component title; struct border_component min; struct border_component max; struct border_component close; } title_bar; /* store pre-processed shadow tile */ cairo_surface_t *shadow_blur; struct wl_list link; }; struct libdecor_plugin_cairo { struct libdecor_plugin plugin; struct wl_callback *globals_callback; struct wl_callback *globals_callback_shm; struct libdecor *context; struct wl_registry *wl_registry; struct wl_subcompositor *wl_subcompositor; struct wl_compositor *wl_compositor; struct wl_shm *wl_shm; struct wl_callback *shm_callback; bool has_argb; struct wl_list visible_frame_list; struct wl_list seat_list; struct wl_list output_list; char *cursor_theme_name; int cursor_size; PangoFontDescription *font; }; static const char *libdecor_cairo_proxy_tag = "libdecor-cairo"; static void sync_active_component(struct libdecor_frame_cairo *frame_cairo, struct seat *seat); static void synthesize_pointer_enter(struct seat *seat); static void synthesize_pointer_leave(struct seat *seat); static bool own_proxy(struct wl_proxy *proxy) { if (!proxy) return false; return (wl_proxy_get_tag(proxy) == &libdecor_cairo_proxy_tag); } static bool own_surface(struct wl_surface *surface) { return own_proxy((struct wl_proxy *) surface); } static bool own_output(struct wl_output *output) { return own_proxy((struct wl_proxy *) output); } static bool moveable(struct libdecor_frame_cairo *frame_cairo) { return libdecor_frame_has_capability(&frame_cairo->frame, LIBDECOR_ACTION_MOVE); } static bool resizable(struct libdecor_frame_cairo *frame_cairo) { return libdecor_frame_has_capability(&frame_cairo->frame, LIBDECOR_ACTION_RESIZE); } static bool minimizable(struct libdecor_frame_cairo *frame_cairo) { return libdecor_frame_has_capability(&frame_cairo->frame, LIBDECOR_ACTION_MINIMIZE); } static bool closeable(struct libdecor_frame_cairo *frame_cairo) { return libdecor_frame_has_capability(&frame_cairo->frame, LIBDECOR_ACTION_CLOSE); } static void buffer_free(struct buffer *buffer); static void draw_border_component(struct libdecor_frame_cairo *frame_cairo, struct border_component *border_component); static void send_cursor(struct seat *seat); static bool update_local_cursor(struct seat *seat); static void libdecor_plugin_cairo_destroy(struct libdecor_plugin *plugin) { struct libdecor_plugin_cairo *plugin_cairo = (struct libdecor_plugin_cairo *) plugin; struct seat *seat, *seat_tmp; struct output *output, *output_tmp; struct libdecor_frame_cairo *frame, *frame_tmp; if (plugin_cairo->globals_callback) wl_callback_destroy(plugin_cairo->globals_callback); if (plugin_cairo->globals_callback_shm) wl_callback_destroy(plugin_cairo->globals_callback_shm); if (plugin_cairo->shm_callback) wl_callback_destroy(plugin_cairo->shm_callback); wl_registry_destroy(plugin_cairo->wl_registry); wl_list_for_each_safe(seat, seat_tmp, &plugin_cairo->seat_list, link) { struct cursor_output *cursor_output, *tmp; if (seat->wl_pointer) wl_pointer_destroy(seat->wl_pointer); if (seat->cursor_surface) wl_surface_destroy(seat->cursor_surface); wl_seat_destroy(seat->wl_seat); if (seat->cursor_theme) wl_cursor_theme_destroy(seat->cursor_theme); wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link) { wl_list_remove(&cursor_output->link); free(cursor_output); } free(seat->name); free(seat); } wl_list_for_each_safe(output, output_tmp, &plugin_cairo->output_list, link) { if (wl_output_get_version (output->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION) wl_output_release(output->wl_output); else wl_output_destroy(output->wl_output); free(output); } wl_list_for_each_safe(frame, frame_tmp, &plugin_cairo->visible_frame_list, link) { wl_list_remove(&frame->link); } free(plugin_cairo->cursor_theme_name); if (plugin_cairo->wl_shm) wl_shm_destroy(plugin_cairo->wl_shm); pango_font_description_free(plugin_cairo->font); if (plugin_cairo->wl_compositor) wl_compositor_destroy(plugin_cairo->wl_compositor); if (plugin_cairo->wl_subcompositor) wl_subcompositor_destroy(plugin_cairo->wl_subcompositor); libdecor_plugin_release(&plugin_cairo->plugin); free(plugin_cairo); } static void init_server_component(struct border_component *border_component, enum component type) { border_component->composite_mode = COMPOSITE_SERVER; wl_list_init(&border_component->child_components); border_component->type = type; } static void init_client_component(struct border_component *border_component, struct border_component *parent, enum component type) { border_component->composite_mode = COMPOSITE_CLIENT; wl_list_init(&border_component->child_components); wl_list_insert(parent->child_components.prev, &border_component->link); border_component->client.parent_component = parent; border_component->type = type; } static void init_components(struct libdecor_frame_cairo *frame_cairo) { init_server_component(&frame_cairo->title_bar.title, TITLE); init_client_component(&frame_cairo->title_bar.min, &frame_cairo->title_bar.title, BUTTON_MIN); init_client_component(&frame_cairo->title_bar.max, &frame_cairo->title_bar.title, BUTTON_MAX); init_client_component(&frame_cairo->title_bar.close, &frame_cairo->title_bar.title, BUTTON_CLOSE); init_server_component(&frame_cairo->shadow, SHADOW); } static struct libdecor_frame_cairo * libdecor_frame_cairo_new(struct libdecor_plugin_cairo *plugin_cairo) { struct libdecor_frame_cairo *frame_cairo = zalloc(sizeof *frame_cairo); cairo_t *cr; static const int size = 128; static const int boundary = 32; frame_cairo->plugin_cairo = plugin_cairo; frame_cairo->shadow_blur = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, size, size); wl_list_insert(&plugin_cairo->visible_frame_list, &frame_cairo->link); init_components(frame_cairo); cr = cairo_create(frame_cairo->shadow_blur); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_rectangle(cr, boundary, boundary, size-2*boundary, size-2*boundary); cairo_fill(cr); cairo_destroy(cr); blur_surface(frame_cairo->shadow_blur, 64); return frame_cairo; } static int libdecor_plugin_cairo_get_fd(struct libdecor_plugin *plugin) { struct libdecor_plugin_cairo *plugin_cairo = (struct libdecor_plugin_cairo *) plugin; struct wl_display *wl_display = libdecor_get_wl_display(plugin_cairo->context); return wl_display_get_fd(wl_display); } static int libdecor_plugin_cairo_dispatch(struct libdecor_plugin *plugin, int timeout) { struct libdecor_plugin_cairo *plugin_cairo = (struct libdecor_plugin_cairo *) plugin; struct wl_display *wl_display = libdecor_get_wl_display(plugin_cairo->context); struct pollfd fds[1]; int ret; int dispatch_count = 0; while (wl_display_prepare_read(wl_display) != 0) dispatch_count += wl_display_dispatch_pending(wl_display); if (wl_display_flush(wl_display) < 0 && errno != EAGAIN) { wl_display_cancel_read(wl_display); return -errno; } fds[0] = (struct pollfd) { wl_display_get_fd(wl_display), POLLIN }; ret = poll(fds, ARRAY_SIZE (fds), timeout); if (ret > 0) { if (fds[0].revents & POLLIN) { wl_display_read_events(wl_display); dispatch_count += wl_display_dispatch_pending(wl_display); return dispatch_count; } else { wl_display_cancel_read(wl_display); return dispatch_count; } } else if (ret == 0) { wl_display_cancel_read(wl_display); return dispatch_count; } else { wl_display_cancel_read(wl_display); return -errno; } } static struct libdecor_frame * libdecor_plugin_cairo_frame_new(struct libdecor_plugin *plugin) { struct libdecor_plugin_cairo *plugin_cairo = (struct libdecor_plugin_cairo *) plugin; struct libdecor_frame_cairo *frame_cairo; frame_cairo = libdecor_frame_cairo_new(plugin_cairo); return &frame_cairo->frame; } static void toggle_maximized(struct libdecor_frame *const frame) { if (!resizable((struct libdecor_frame_cairo *)frame)) return; if (!(libdecor_frame_get_window_state(frame) & LIBDECOR_WINDOW_STATE_MAXIMIZED)) libdecor_frame_set_maximized(frame); else libdecor_frame_unset_maximized(frame); } static void buffer_release(void *user_data, struct wl_buffer *wl_buffer) { struct buffer *buffer = user_data; if (buffer->is_detached) buffer_free(buffer); else buffer->in_use = false; } static const struct wl_buffer_listener buffer_listener = { buffer_release }; static struct buffer * create_shm_buffer(struct libdecor_plugin_cairo *plugin_cairo, int width, int height, bool opaque, int scale) { struct wl_shm_pool *pool; int fd, size, buffer_width, buffer_height, stride; void *data; struct buffer *buffer; enum wl_shm_format buf_fmt; buffer_width = width * scale; buffer_height = height * scale; stride = buffer_width * 4; size = stride * buffer_height; fd = libdecor_os_create_anonymous_file(size); if (fd < 0) { fprintf(stderr, "creating a buffer file for %d B failed: %s\n", size, strerror(errno)); return NULL; } data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data == MAP_FAILED) { fprintf(stderr, "mmap failed: %s\n", strerror(errno)); close(fd); return NULL; } buf_fmt = opaque ? WL_SHM_FORMAT_XRGB8888 : WL_SHM_FORMAT_ARGB8888; pool = wl_shm_create_pool(plugin_cairo->wl_shm, fd, size); buffer = zalloc(sizeof *buffer); buffer->wl_buffer = wl_shm_pool_create_buffer(pool, 0, buffer_width, buffer_height, stride, buf_fmt); wl_buffer_add_listener(buffer->wl_buffer, &buffer_listener, buffer); wl_shm_pool_destroy(pool); close(fd); buffer->data = data; buffer->data_size = size; buffer->width = width; buffer->height = height; buffer->scale = scale; buffer->buffer_width = buffer_width; buffer->buffer_height = buffer_height; return buffer; } static void buffer_free(struct buffer *buffer) { if (buffer->wl_buffer) { wl_buffer_destroy(buffer->wl_buffer); munmap(buffer->data, buffer->data_size); buffer->wl_buffer = NULL; buffer->in_use = false; } free(buffer); } static void free_border_component(struct border_component *border_component) { struct surface_output *surface_output, *surface_output_tmp; if (border_component->server.wl_surface) { wl_subsurface_destroy(border_component->server.wl_subsurface); border_component->server.wl_subsurface = NULL; wl_surface_destroy(border_component->server.wl_surface); border_component->server.wl_surface = NULL; } if (border_component->server.buffer) { buffer_free(border_component->server.buffer); border_component->server.buffer = NULL; } if (border_component->client.image) { cairo_surface_destroy(border_component->client.image); border_component->client.image = NULL; } if (border_component->server.output_list.next != NULL) { wl_list_for_each_safe(surface_output, surface_output_tmp, &border_component->server.output_list, link) { wl_list_remove(&surface_output->link); free(surface_output); } } } static void libdecor_plugin_cairo_frame_free(struct libdecor_plugin *plugin, struct libdecor_frame *frame) { struct libdecor_plugin_cairo *plugin_cairo = (struct libdecor_plugin_cairo *) plugin; struct libdecor_frame_cairo *frame_cairo = (struct libdecor_frame_cairo *) frame; struct seat *seat; wl_list_for_each(seat, &plugin_cairo->seat_list, link) { if (seat->pointer_focus != NULL && wl_surface_get_user_data(seat->pointer_focus) == frame_cairo) seat->pointer_focus = NULL; } free_border_component(&frame_cairo->title_bar.title); free_border_component(&frame_cairo->title_bar.min); free_border_component(&frame_cairo->title_bar.max); free_border_component(&frame_cairo->title_bar.close); frame_cairo->title_bar.is_showing = false; free_border_component(&frame_cairo->shadow); frame_cairo->shadow_showing = false; if (frame_cairo->shadow_blur != NULL) { cairo_surface_destroy(frame_cairo->shadow_blur); frame_cairo->shadow_blur = NULL; } free(frame_cairo->title); frame_cairo->title = NULL; frame_cairo->decoration_type = DECORATION_TYPE_NONE; if (frame_cairo->link.next != NULL) wl_list_remove(&frame_cairo->link); } static bool is_border_surfaces_showing(struct libdecor_frame_cairo *frame_cairo) { return frame_cairo->shadow_showing; } static bool is_title_bar_surfaces_showing(struct libdecor_frame_cairo *frame_cairo) { return frame_cairo->title_bar.is_showing; } static struct border_component * get_server_component(struct border_component *border_component) { switch (border_component->composite_mode) { case COMPOSITE_SERVER: return border_component; case COMPOSITE_CLIENT: return get_server_component(border_component->client.parent_component); } return NULL; } static void redraw_border_component(struct libdecor_frame_cairo *frame_cairo, struct border_component *border_component) { struct border_component *server_component; server_component = get_server_component(border_component); draw_border_component(frame_cairo, server_component); } static void hide_border_component(struct libdecor_frame_cairo *frame_cairo, struct border_component *border_component) { border_component->is_hidden = true; switch (border_component->composite_mode) { case COMPOSITE_SERVER: if (!border_component->server.wl_surface) return; wl_surface_attach(border_component->server.wl_surface, NULL, 0, 0); wl_surface_commit(border_component->server.wl_surface); break; case COMPOSITE_CLIENT: redraw_border_component(frame_cairo, border_component); break; } } static void hide_border_surfaces(struct libdecor_frame_cairo *frame_cairo) { hide_border_component(frame_cairo, &frame_cairo->shadow); frame_cairo->shadow_showing = false; } static void hide_title_bar_surfaces(struct libdecor_frame_cairo *frame_cairo) { hide_border_component(frame_cairo, &frame_cairo->title_bar.title); hide_border_component(frame_cairo, &frame_cairo->title_bar.min); hide_border_component(frame_cairo, &frame_cairo->title_bar.max); hide_border_component(frame_cairo, &frame_cairo->title_bar.close); frame_cairo->title_bar.is_showing = false; } static struct border_component * get_component_for_surface(struct libdecor_frame_cairo *frame_cairo, struct wl_surface *surface) { if (frame_cairo->shadow.server.wl_surface == surface) return &frame_cairo->shadow; if (frame_cairo->title_bar.title.server.wl_surface == surface) return &frame_cairo->title_bar.title; return NULL; } static void calculate_component_size(struct libdecor_frame_cairo *frame_cairo, enum component component, int *component_x, int *component_y, int *component_width, int *component_height); static void update_component_focus(struct libdecor_frame_cairo *frame_cairo, struct wl_surface *surface, struct seat *seat) { static struct border_component *border_component; static struct border_component *child_component; static struct border_component *focus_component; border_component = get_component_for_surface(frame_cairo, surface); focus_component = border_component; wl_list_for_each(child_component, &border_component->child_components, link) { int component_x = 0, component_y = 0; int component_width = 0, component_height = 0; calculate_component_size(frame_cairo, child_component->type, &component_x, &component_y, &component_width, &component_height); if (seat->pointer_x >= component_x && seat->pointer_x < component_x + component_width && seat->pointer_y >= component_y && seat->pointer_y < component_y + component_height) { focus_component = child_component; break; } } if (frame_cairo->grab) frame_cairo->active = frame_cairo->grab; else frame_cairo->active = focus_component; frame_cairo->focus = focus_component; } static void ensure_component(struct libdecor_frame_cairo *frame_cairo, struct border_component *cmpnt); static bool redraw_scale(struct libdecor_frame_cairo *frame_cairo, struct border_component *cmpnt) { struct surface_output *surface_output; int scale = 1; if (cmpnt->is_hidden) return false; ensure_component(frame_cairo, cmpnt); wl_list_for_each(surface_output, &cmpnt->server.output_list, link) { scale = MAX(scale, surface_output->output->scale); } if (scale != cmpnt->server.scale) { cmpnt->server.scale = scale; if ((cmpnt->type != SHADOW) || is_border_surfaces_showing(frame_cairo)) { draw_border_component(frame_cairo, cmpnt); return true; } } return false; } static bool add_surface_output(struct libdecor_plugin_cairo *plugin_cairo, struct wl_output *wl_output, struct wl_list *list) { struct output *output; struct surface_output *surface_output; if (!own_output(wl_output)) return false; output = wl_output_get_user_data(wl_output); if (output == NULL) return false; surface_output = zalloc(sizeof *surface_output); surface_output->output = output; wl_list_insert(list, &surface_output->link); return true; } static void surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { struct libdecor_frame_cairo *frame_cairo = data; struct border_component *cmpnt; if (!(own_surface(wl_surface) && own_output(wl_output))) return; cmpnt = get_component_for_surface(frame_cairo, wl_surface); if (cmpnt == NULL) return; if (!add_surface_output(frame_cairo->plugin_cairo, wl_output, &cmpnt->server.output_list)) return; if (redraw_scale(frame_cairo, cmpnt)) libdecor_frame_toplevel_commit(&frame_cairo->frame); } static bool remove_surface_output(struct wl_list *list, struct wl_output *wl_output) { struct surface_output *surface_output; wl_list_for_each(surface_output, list, link) { if (surface_output->output->wl_output == wl_output) { wl_list_remove(&surface_output->link); free(surface_output); return true; } } return false; } static void surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { struct libdecor_frame_cairo *frame_cairo = data; struct border_component *cmpnt; if (!(own_surface(wl_surface) && own_output(wl_output))) return; cmpnt = get_component_for_surface(frame_cairo, wl_surface); if (cmpnt == NULL) return; if (!remove_surface_output(&cmpnt->server.output_list, wl_output)) return; if (redraw_scale(frame_cairo, cmpnt)) libdecor_frame_toplevel_commit(&frame_cairo->frame); } static struct wl_surface_listener surface_listener = { surface_enter, surface_leave, }; static void create_surface_subsurface_pair(struct libdecor_frame_cairo *frame_cairo, struct wl_surface **out_wl_surface, struct wl_subsurface **out_wl_subsurface) { struct libdecor_plugin_cairo *plugin_cairo = frame_cairo->plugin_cairo; struct libdecor_frame *frame = &frame_cairo->frame; struct wl_compositor *wl_compositor = plugin_cairo->wl_compositor; struct wl_subcompositor *wl_subcompositor = plugin_cairo->wl_subcompositor; struct wl_surface *wl_surface; struct wl_surface *parent; struct wl_subsurface *wl_subsurface; wl_surface = wl_compositor_create_surface(wl_compositor); wl_proxy_set_tag((struct wl_proxy *) wl_surface, &libdecor_cairo_proxy_tag); parent = libdecor_frame_get_wl_surface(frame); wl_subsurface = wl_subcompositor_get_subsurface(wl_subcompositor, wl_surface, parent); *out_wl_surface = wl_surface; *out_wl_subsurface = wl_subsurface; } static void ensure_component(struct libdecor_frame_cairo *frame_cairo, struct border_component *cmpnt) { switch (cmpnt->composite_mode) { case COMPOSITE_SERVER: if (!cmpnt->server.wl_surface) { wl_list_init(&cmpnt->server.output_list); cmpnt->server.scale = 1; create_surface_subsurface_pair(frame_cairo, &cmpnt->server.wl_surface, &cmpnt->server.wl_subsurface); wl_surface_add_listener(cmpnt->server.wl_surface, &surface_listener, frame_cairo); } break; case COMPOSITE_CLIENT: wl_list_init(&cmpnt->server.output_list); break; } cmpnt->is_hidden = false; } static void ensure_border_surfaces(struct libdecor_frame_cairo *frame_cairo) { int min_width, min_height, current_max_w, current_max_h; frame_cairo->shadow.opaque = false; ensure_component(frame_cairo, &frame_cairo->shadow); libdecor_frame_get_min_content_size(&frame_cairo->frame, &min_width, &min_height); min_width = MAX(min_width, (int)MAX(56, 4 * BUTTON_WIDTH)); min_height = MAX(min_height, (int)MAX(56, TITLE_HEIGHT + 1)); libdecor_frame_set_min_content_size(&frame_cairo->frame, min_width, min_height); libdecor_frame_get_max_content_size(&frame_cairo->frame, ¤t_max_w, ¤t_max_h); if (current_max_w && current_max_w < min_width) current_max_w = min_width; if (current_max_h && current_max_h < min_height) current_max_h = min_height; libdecor_frame_set_max_content_size(&frame_cairo->frame, current_max_w, current_max_h); } static void ensure_title_bar_surfaces(struct libdecor_frame_cairo *frame_cairo) { frame_cairo->title_bar.title.opaque = true; ensure_component(frame_cairo, &frame_cairo->title_bar.title); frame_cairo->title_bar.min.opaque = true; ensure_component(frame_cairo, &frame_cairo->title_bar.min); frame_cairo->title_bar.max.opaque = true; ensure_component(frame_cairo, &frame_cairo->title_bar.max); frame_cairo->title_bar.close.opaque = true; ensure_component(frame_cairo, &frame_cairo->title_bar.close); } static void calculate_component_size(struct libdecor_frame_cairo *frame_cairo, enum component component, int *component_x, int *component_y, int *component_width, int *component_height) { struct libdecor_frame *frame = &frame_cairo->frame; int content_width, content_height; content_width = libdecor_frame_get_content_width(frame); content_height = libdecor_frame_get_content_height(frame); switch (component) { case NONE: *component_width = 0; *component_height = 0; return; case SHADOW: *component_x = -(int)SHADOW_MARGIN; *component_y = -(int)(SHADOW_MARGIN+TITLE_HEIGHT); *component_width = content_width + 2 * SHADOW_MARGIN; *component_height = content_height + 2 * SHADOW_MARGIN + TITLE_HEIGHT; return; case TITLE: *component_x = 0; *component_y = -(int)TITLE_HEIGHT; *component_width = content_width; *component_height = TITLE_HEIGHT; return; case BUTTON_MIN: *component_x = content_width - 3 * BUTTON_WIDTH; *component_y = 0; *component_width = BUTTON_WIDTH; *component_height = TITLE_HEIGHT; return; case BUTTON_MAX: *component_x = content_width - 2 * BUTTON_WIDTH; *component_y = 0; *component_width = BUTTON_WIDTH; *component_height = TITLE_HEIGHT; return; case BUTTON_CLOSE: *component_x = content_width - BUTTON_WIDTH; *component_y = 0; *component_width = BUTTON_WIDTH; *component_height = TITLE_HEIGHT; return; } abort(); } static int border_component_get_scale(struct border_component *border_component) { switch (border_component->composite_mode) { case COMPOSITE_SERVER: return border_component->server.scale; case COMPOSITE_CLIENT: return border_component_get_scale( border_component->client.parent_component); } return 0; } static void draw_title_text(struct libdecor_frame_cairo *frame_cairo, cairo_t *cr, const int *title_width, bool active) { const uint32_t col_title = active ? COL_TITLE : COL_TITLE_INACT; const uint32_t col_title_text = active ? COL_SYM : COL_SYM_INACT; PangoLayout *layout; /* title fade out at buttons */ const int fade_width = 5 * BUTTON_WIDTH; int fade_start; cairo_pattern_t *fade; /* text position and dimensions */ int text_extents_width, text_extents_height; double text_x, text_y; double text_width, text_height; const char *title; title = libdecor_frame_get_title((struct libdecor_frame*) frame_cairo); if (!title) return; layout = pango_cairo_create_layout(cr); pango_layout_set_text(layout, title, -1); pango_layout_set_font_description(layout, frame_cairo->plugin_cairo->font); pango_layout_get_size(layout, &text_extents_width, &text_extents_height); /* set text position and dimensions */ text_width = text_extents_width / PANGO_SCALE; text_height = text_extents_height / PANGO_SCALE; text_x = *title_width / 2.0 - text_width / 2.0; text_x += MIN(0.0, ((*title_width - fade_width) - (text_x + text_width))); text_x = MAX(text_x, BUTTON_WIDTH); text_y = TITLE_HEIGHT / 2.0 - text_height / 2.0; /* draw title text */ cairo_move_to(cr, text_x, text_y); cairo_set_rgba32(cr, &col_title_text); pango_cairo_show_layout(cr, layout); /* draw fade-out from title text to buttons */ fade_start = *title_width - fade_width; fade = cairo_pattern_create_linear(fade_start, 0, fade_start + 2 * BUTTON_WIDTH, 0); cairo_pattern_add_color_stop_rgba(fade, 0, red(&col_title), green(&col_title), blue(&col_title), 0); cairo_pattern_add_color_stop_rgb(fade, 1, red(&col_title), green(&col_title), blue(&col_title)); cairo_rectangle(cr, fade_start, 0, fade_width, TITLE_HEIGHT); cairo_set_source(cr, fade); cairo_fill(cr); cairo_pattern_destroy(fade); g_object_unref(layout); } static void draw_component_content(struct libdecor_frame_cairo *frame_cairo, struct border_component *border_component, int component_width, int component_height, enum component component) { struct buffer *buffer; cairo_surface_t *surface = NULL; int width = 0, height = 0; int scale; cairo_t *cr; /* button symbol origin */ const double x = BUTTON_WIDTH / 2 - SYM_DIM / 2 + 0.5; const double y = TITLE_HEIGHT / 2 - SYM_DIM / 2 + 0.5; enum libdecor_window_state state; bool active; uint32_t col_title; bool cap_min, cap_max, cap_close; /* capabilities of decorations */ cap_min = minimizable(frame_cairo); cap_max = resizable(frame_cairo); cap_close = closeable(frame_cairo); scale = border_component_get_scale(border_component); state = libdecor_frame_get_window_state((struct libdecor_frame *) frame_cairo); active = state & LIBDECOR_WINDOW_STATE_ACTIVE; col_title = active ? COL_TITLE : COL_TITLE_INACT; /* clear buffer */ switch (border_component->composite_mode) { case COMPOSITE_SERVER: buffer = border_component->server.buffer; surface = cairo_image_surface_create_for_data( buffer->data, CAIRO_FORMAT_ARGB32, buffer->buffer_width, buffer->buffer_height, cairo_format_stride_for_width( CAIRO_FORMAT_ARGB32, buffer->buffer_width) ); cairo_surface_set_device_scale(surface, scale, scale); width = buffer->width; height = buffer->height; break; case COMPOSITE_CLIENT: surface = cairo_surface_reference(border_component->client.image); width = cairo_image_surface_get_width(surface); height = cairo_image_surface_get_height(surface); break; } cr = cairo_create(surface); cairo_save(cr); cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); cairo_restore(cr); /* background */ switch (component) { case NONE: break; case SHADOW: if (frame_cairo->decoration_type != DECORATION_TYPE_TILED) render_shadow(cr, frame_cairo->shadow_blur, -(int)SHADOW_MARGIN/2, -(int)SHADOW_MARGIN/2, width + SHADOW_MARGIN, height + SHADOW_MARGIN, 64, 64); break; case TITLE: cairo_set_rgba32(cr, &col_title); cairo_paint(cr); break; case BUTTON_MIN: if (cap_min && frame_cairo->active == &frame_cairo->title_bar.min) cairo_set_rgba32(cr, active ? &COL_BUTTON_MIN : &COL_BUTTON_INACT); else cairo_set_rgba32(cr, &col_title); cairo_paint(cr); break; case BUTTON_MAX: if (cap_max && frame_cairo->active == &frame_cairo->title_bar.max) cairo_set_rgba32(cr, active ? &COL_BUTTON_MAX : &COL_BUTTON_INACT); else cairo_set_rgba32(cr, &col_title); cairo_paint(cr); break; case BUTTON_CLOSE: if (cap_close && frame_cairo->active == &frame_cairo->title_bar.close) cairo_set_rgba32(cr, active ? &COL_BUTTON_CLOSE : &COL_BUTTON_INACT); else cairo_set_rgba32(cr, &col_title); cairo_paint(cr); break; } /* button symbols */ /* https://www.cairographics.org/FAQ/#sharp_lines */ cairo_set_line_width(cr, 1); switch (component) { case TITLE: draw_title_text(frame_cairo,cr, &component_width, active); break; case BUTTON_MIN: if (!active) { /* inactive: use single desaturated color */ cairo_set_rgba32(cr, &COL_SYM_INACT); } else { if (!cap_min || frame_cairo->active == &frame_cairo->title_bar.min) { /* active (a.k.a. prelight) */ cairo_set_rgba32(cr, &COL_SYM_ACT); } else { /* normal */ cairo_set_rgba32(cr, &COL_SYM); } } cairo_move_to(cr, x, y + SYM_DIM - 1); cairo_rel_line_to(cr, SYM_DIM - 1, 0); cairo_stroke(cr); break; case BUTTON_MAX: if (!active) { /* inactive: use single desaturated color */ cairo_set_rgba32(cr, &COL_SYM_INACT); } else { if (!cap_max || frame_cairo->active == &frame_cairo->title_bar.max) { /* active (a.k.a. prelight) */ cairo_set_rgba32(cr, &COL_SYM_ACT); } else { /* normal */ cairo_set_rgba32(cr, &COL_SYM); } } if (state & LIBDECOR_WINDOW_STATE_MAXIMIZED) { const size_t small = 12; cairo_rectangle(cr, x, y + SYM_DIM - small, small - 1, small - 1); cairo_move_to(cr, x + SYM_DIM - small, y + SYM_DIM - small); cairo_line_to(cr, x + SYM_DIM - small, y); cairo_rel_line_to(cr, small - 1, 0); cairo_rel_line_to(cr, 0, small - 1); cairo_line_to(cr, x + small - 1, y + small - 1); } else { cairo_rectangle(cr, x, y, SYM_DIM - 1, SYM_DIM - 1); } cairo_stroke(cr); break; case BUTTON_CLOSE: if (!active) { /* inactive: use single desaturated color */ cairo_set_rgba32(cr, &COL_SYM_INACT); } else { if (!cap_close || frame_cairo->active == &frame_cairo->title_bar.close) { /* active (a.k.a. prelight) */ cairo_set_rgba32(cr, &COL_SYM_ACT); } else { /* normal */ cairo_set_rgba32(cr, &COL_SYM); } } cairo_move_to(cr, x, y); cairo_rel_line_to(cr, SYM_DIM - 1, SYM_DIM - 1); cairo_move_to(cr, x + SYM_DIM - 1, y); cairo_line_to(cr, x, y + SYM_DIM - 1); cairo_stroke(cr); break; default: break; } /* mask the toplevel surface */ if (component == SHADOW) { int component_x, component_y, component_width, component_height; calculate_component_size(frame_cairo, component, &component_x, &component_y, &component_width, &component_height); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_rectangle(cr, -component_x, -component_y, libdecor_frame_get_content_width( &frame_cairo->frame), libdecor_frame_get_content_height( &frame_cairo->frame)); cairo_fill(cr); } cairo_destroy(cr); cairo_surface_destroy(surface); } static void set_component_input_region(struct libdecor_frame_cairo *frame_cairo, struct border_component *border_component) { if (border_component->type == SHADOW && frame_cairo->shadow_showing) { struct wl_region *input_region; int component_x; int component_y; int component_width; int component_height; calculate_component_size(frame_cairo, border_component->type, &component_x, &component_y, &component_width, &component_height); /* * the input region is the outer surface size minus the inner * content size */ input_region = wl_compositor_create_region( frame_cairo->plugin_cairo->wl_compositor); wl_region_add(input_region, 0, 0, component_width, component_height); wl_region_subtract(input_region, -component_x, -component_y, libdecor_frame_get_content_width(&frame_cairo->frame), libdecor_frame_get_content_height(&frame_cairo->frame)); wl_surface_set_input_region(border_component->server.wl_surface, input_region); wl_region_destroy(input_region); } } static void ensure_component_realized_server(struct libdecor_frame_cairo *frame_cairo, struct border_component *border_component, int component_width, int component_height, int scale) { struct buffer *old_buffer; struct buffer *buffer = NULL; old_buffer = border_component->server.buffer; if (old_buffer) { if (!old_buffer->in_use && old_buffer->buffer_width == component_width * scale && old_buffer->buffer_height == component_height * scale) { buffer = old_buffer; } else { buffer_free(old_buffer); border_component->server.buffer = NULL; } } if (!buffer) buffer = create_shm_buffer(frame_cairo->plugin_cairo, component_width, component_height, border_component->opaque, border_component->server.scale); border_component->server.buffer = buffer; } static void ensure_component_realized_client(struct libdecor_frame_cairo *frame_cairo, struct border_component *border_component, int component_width, int component_height, int scale) { cairo_surface_t *old_image; old_image = border_component->client.image; if (old_image) { int cairo_buffer_width; int cairo_buffer_height; double x_scale; double y_scale; cairo_surface_get_device_scale(old_image, &x_scale, &y_scale); cairo_buffer_width = (int) round(cairo_image_surface_get_width(old_image) * x_scale); cairo_buffer_height = (int) round(cairo_image_surface_get_height(old_image) * y_scale); if (cairo_buffer_width != component_width * scale || cairo_buffer_height != component_height * scale) { cairo_surface_destroy(old_image); border_component->client.image = NULL; } } if (!border_component->client.image) { cairo_surface_t *new_image; new_image = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, component_width * scale, component_height * scale); cairo_surface_set_device_scale(new_image, scale, scale); border_component->client.image = new_image; } } static void ensure_component_realized(struct libdecor_frame_cairo *frame_cairo, struct border_component *border_component, int component_width, int component_height, int scale) { switch (border_component->composite_mode) { case COMPOSITE_SERVER: ensure_component_realized_server(frame_cairo, border_component, component_width, component_height, scale); break; case COMPOSITE_CLIENT: ensure_component_realized_client(frame_cairo, border_component, component_width, component_height, scale); break; } } static cairo_t * create_cairo_for_parent(struct border_component *border_component) { struct border_component *parent = border_component->client.parent_component; struct buffer *buffer; struct border_component *server_component; cairo_surface_t *parent_surface; cairo_t *cr; switch (parent->composite_mode) { case COMPOSITE_SERVER: buffer = parent->server.buffer; parent_surface = cairo_image_surface_create_for_data( buffer->data, CAIRO_FORMAT_ARGB32, buffer->buffer_width, buffer->buffer_height, cairo_format_stride_for_width( CAIRO_FORMAT_ARGB32, buffer->buffer_width) ); cr = cairo_create(parent_surface); cairo_surface_destroy(parent_surface); cairo_scale(cr, buffer->scale, buffer->scale); return cr; case COMPOSITE_CLIENT: cr = cairo_create(parent->client.image); server_component = get_server_component(border_component); cairo_scale(cr, server_component->server.scale, server_component->server.scale); return cr; } return NULL; } static void draw_border_component(struct libdecor_frame_cairo *frame_cairo, struct border_component *border_component) { enum component component = border_component->type; struct buffer *buffer; cairo_t *cr; int component_x; int component_y; int component_width; int component_height; int scale; struct border_component *child_component; if (border_component->is_hidden) return; calculate_component_size(frame_cairo, component, &component_x, &component_y, &component_width, &component_height); set_component_input_region(frame_cairo, border_component); scale = border_component_get_scale(border_component); ensure_component_realized(frame_cairo, border_component, component_width, component_height, scale); draw_component_content(frame_cairo, border_component, component_width, component_height, component); switch(border_component->composite_mode) { case COMPOSITE_SERVER: buffer = border_component->server.buffer; wl_surface_attach(border_component->server.wl_surface, buffer->wl_buffer, 0, 0); wl_surface_set_buffer_scale(border_component->server.wl_surface, buffer->scale); buffer->in_use = true; wl_surface_commit(border_component->server.wl_surface); wl_surface_damage_buffer(border_component->server.wl_surface, 0, 0, component_width * scale, component_height * scale); wl_subsurface_set_position(border_component->server.wl_subsurface, component_x, component_y); break; case COMPOSITE_CLIENT: cr = create_cairo_for_parent(border_component); cairo_set_source_surface(cr, border_component->client.image, component_x, component_y); cairo_paint(cr); cairo_destroy(cr); break; } wl_list_for_each(child_component, &border_component->child_components, link) draw_border_component(frame_cairo, child_component); } static void draw_border(struct libdecor_frame_cairo *frame_cairo) { draw_border_component(frame_cairo, &frame_cairo->shadow); frame_cairo->shadow_showing = true; } static void draw_title_bar(struct libdecor_frame_cairo *frame_cairo) { draw_border_component(frame_cairo, &frame_cairo->title_bar.title); frame_cairo->title_bar.is_showing = true; } static void draw_decoration(struct libdecor_frame_cairo *frame_cairo) { switch (frame_cairo->decoration_type) { case DECORATION_TYPE_NONE: if (frame_cairo->link.next != NULL) wl_list_remove(&frame_cairo->link); if (is_border_surfaces_showing(frame_cairo)) hide_border_surfaces(frame_cairo); if (is_title_bar_surfaces_showing(frame_cairo)) hide_title_bar_surfaces(frame_cairo); break; case DECORATION_TYPE_TILED: case DECORATION_TYPE_ALL: /* show borders */ ensure_border_surfaces(frame_cairo); draw_border(frame_cairo); /* show title bar */ ensure_title_bar_surfaces(frame_cairo); draw_title_bar(frame_cairo); /* link frame */ if (frame_cairo->link.next == NULL) wl_list_insert( &frame_cairo->plugin_cairo->visible_frame_list, &frame_cairo->link); break; case DECORATION_TYPE_MAXIMIZED: /* hide borders */ if (is_border_surfaces_showing(frame_cairo)) hide_border_surfaces(frame_cairo); /* show title bar */ ensure_title_bar_surfaces(frame_cairo); draw_title_bar(frame_cairo); /* link frame */ if (frame_cairo->link.next == NULL) wl_list_insert( &frame_cairo->plugin_cairo->visible_frame_list, &frame_cairo->link); break; } } static enum decoration_type window_state_to_decoration_type(enum libdecor_window_state window_state) { if (window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN) return DECORATION_TYPE_NONE; else if (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) /* title bar, no shadows */ return DECORATION_TYPE_MAXIMIZED; else if (window_state & LIBDECOR_WINDOW_STATE_TILED_LEFT || window_state & LIBDECOR_WINDOW_STATE_TILED_RIGHT || window_state & LIBDECOR_WINDOW_STATE_TILED_TOP || window_state & LIBDECOR_WINDOW_STATE_TILED_BOTTOM) /* title bar, invisible shadows */ return DECORATION_TYPE_TILED; else /* title bar, shadows */ return DECORATION_TYPE_ALL; } static void libdecor_plugin_cairo_frame_commit(struct libdecor_plugin *plugin, struct libdecor_frame *frame, struct libdecor_state *state, struct libdecor_configuration *configuration) { struct libdecor_frame_cairo *frame_cairo = (struct libdecor_frame_cairo *) frame; enum libdecor_window_state old_window_state; enum libdecor_window_state new_window_state; int old_content_width, old_content_height; int new_content_width, new_content_height; enum decoration_type old_decoration_type; enum decoration_type new_decoration_type; old_window_state = frame_cairo->window_state; new_window_state = libdecor_frame_get_window_state(frame); old_content_width = frame_cairo->content_width; old_content_height = frame_cairo->content_height; new_content_width = libdecor_frame_get_content_width(frame); new_content_height = libdecor_frame_get_content_height(frame); old_decoration_type = frame_cairo->decoration_type; new_decoration_type = window_state_to_decoration_type(new_window_state); if (old_decoration_type == new_decoration_type && old_content_width == new_content_width && old_content_height == new_content_height && old_window_state == new_window_state) return; frame_cairo->content_width = new_content_width; frame_cairo->content_height = new_content_height; frame_cairo->decoration_type = new_decoration_type; frame_cairo->window_state = new_window_state; draw_decoration(frame_cairo); } static void libdecor_plugin_cairo_frame_property_changed(struct libdecor_plugin *plugin, struct libdecor_frame *frame) { struct libdecor_frame_cairo *frame_cairo = (struct libdecor_frame_cairo *) frame; bool redraw_needed = false; const char *new_title; new_title = libdecor_frame_get_title(frame); if (frame_cairo->title_bar.is_showing) { if (!streql(frame_cairo->title, new_title)) redraw_needed = true; } if (frame_cairo->title) { free(frame_cairo->title); frame_cairo->title = NULL; } if (new_title) { frame_cairo->title = strdup(new_title); } if (frame_cairo->capabilities != libdecor_frame_get_capabilities(frame)) { frame_cairo->capabilities = libdecor_frame_get_capabilities(frame); redraw_needed = true; } if (redraw_needed) { draw_decoration(frame_cairo); libdecor_frame_toplevel_commit(frame); } } static bool streq(const char *str1, const char *str2) { if (!str1 && !str2) return true; if (str1 && str2) return strcmp(str1, str2) == 0; return false; } static void libdecor_plugin_cairo_frame_popup_grab(struct libdecor_plugin *plugin, struct libdecor_frame *frame, const char *seat_name) { struct libdecor_frame_cairo *frame_cairo = (struct libdecor_frame_cairo *) frame; struct libdecor_plugin_cairo *plugin_cairo = frame_cairo->plugin_cairo; struct seat *seat; wl_list_for_each(seat, &plugin_cairo->seat_list, link) { if (streq(seat->name, seat_name)) { if (seat->grabbed) { fprintf(stderr, "libdecor-WARNING: Application " "tried to grab seat twice\n"); } synthesize_pointer_leave(seat); seat->grabbed = true; return; } } fprintf(stderr, "libdecor-WARNING: Application tried to grab unknown seat\n"); } static void libdecor_plugin_cairo_frame_popup_ungrab(struct libdecor_plugin *plugin, struct libdecor_frame *frame, const char *seat_name) { struct libdecor_frame_cairo *frame_cairo = (struct libdecor_frame_cairo *) frame; struct libdecor_plugin_cairo *plugin_cairo = frame_cairo->plugin_cairo; struct seat *seat; wl_list_for_each(seat, &plugin_cairo->seat_list, link) { if (streq(seat->name, seat_name)) { if (!seat->grabbed) { fprintf(stderr, "libdecor-WARNING: Application " "tried to ungrab seat twice\n"); } seat->grabbed = false; synthesize_pointer_enter(seat); sync_active_component(frame_cairo, seat); return; } } fprintf(stderr, "libdecor-WARNING: Application tried to ungrab unknown seat\n"); } static bool libdecor_plugin_cairo_frame_get_border_size(struct libdecor_plugin *plugin, struct libdecor_frame *frame, struct libdecor_configuration *configuration, int *left, int *right, int *top, int *bottom) { enum libdecor_window_state window_state; if (configuration) { if (!libdecor_configuration_get_window_state( configuration, &window_state)) return false; } else { window_state = libdecor_frame_get_window_state(frame); } if (left) *left = 0; if (right) *right = 0; if (bottom) *bottom = 0; if (top) { enum decoration_type type = window_state_to_decoration_type(window_state); if (((struct libdecor_frame_cairo *)frame)->title_bar.is_showing && (type != DECORATION_TYPE_NONE)) *top = TITLE_HEIGHT; else *top = 0; } return true; } static struct libdecor_plugin_interface cairo_plugin_iface = { .destroy = libdecor_plugin_cairo_destroy, .get_fd = libdecor_plugin_cairo_get_fd, .dispatch = libdecor_plugin_cairo_dispatch, .frame_new = libdecor_plugin_cairo_frame_new, .frame_free = libdecor_plugin_cairo_frame_free, .frame_commit = libdecor_plugin_cairo_frame_commit, .frame_property_changed = libdecor_plugin_cairo_frame_property_changed, .frame_popup_grab = libdecor_plugin_cairo_frame_popup_grab, .frame_popup_ungrab = libdecor_plugin_cairo_frame_popup_ungrab, .frame_get_border_size = libdecor_plugin_cairo_frame_get_border_size, }; static void init_wl_compositor(struct libdecor_plugin_cairo *plugin_cairo, uint32_t id, uint32_t version) { plugin_cairo->wl_compositor = wl_registry_bind(plugin_cairo->wl_registry, id, &wl_compositor_interface, MIN(version, 4)); } static void init_wl_subcompositor(struct libdecor_plugin_cairo *plugin_cairo, uint32_t id, uint32_t version) { plugin_cairo->wl_subcompositor = wl_registry_bind(plugin_cairo->wl_registry, id, &wl_subcompositor_interface, 1); } static void shm_format(void *user_data, struct wl_shm *wl_shm, uint32_t format) { struct libdecor_plugin_cairo *plugin_cairo = user_data; if (format == WL_SHM_FORMAT_ARGB8888) plugin_cairo->has_argb = true; } struct wl_shm_listener shm_listener = { shm_format }; static void shm_callback(void *user_data, struct wl_callback *callback, uint32_t time) { struct libdecor_plugin_cairo *plugin_cairo = user_data; struct libdecor *context = plugin_cairo->context; wl_callback_destroy(callback); plugin_cairo->globals_callback_shm = NULL; if (!plugin_cairo->has_argb) { libdecor_notify_plugin_error( context, LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE, "Compositor is missing required shm format"); return; } libdecor_notify_plugin_ready(context); } static const struct wl_callback_listener shm_callback_listener = { shm_callback }; static void init_wl_shm(struct libdecor_plugin_cairo *plugin_cairo, uint32_t id, uint32_t version) { struct libdecor *context = plugin_cairo->context; struct wl_display *wl_display = libdecor_get_wl_display(context); plugin_cairo->wl_shm = wl_registry_bind(plugin_cairo->wl_registry, id, &wl_shm_interface, 1); wl_shm_add_listener(plugin_cairo->wl_shm, &shm_listener, plugin_cairo); plugin_cairo->globals_callback_shm = wl_display_sync(wl_display); wl_callback_add_listener(plugin_cairo->globals_callback_shm, &shm_callback_listener, plugin_cairo); } static void cursor_surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { struct seat *seat = data; if(own_output(wl_output)) { struct cursor_output *cursor_output; cursor_output = zalloc(sizeof *cursor_output); cursor_output->output = wl_output_get_user_data(wl_output); wl_list_insert(&seat->cursor_outputs, &cursor_output->link); if (update_local_cursor(seat)) send_cursor(seat); } } static void cursor_surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { struct seat *seat = data; if(own_output(wl_output)) { struct cursor_output *cursor_output, *tmp; wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link) { if (cursor_output->output->wl_output == wl_output) { wl_list_remove(&cursor_output->link); free(cursor_output); } } if (update_local_cursor(seat)) send_cursor(seat); } } static struct wl_surface_listener cursor_surface_listener = { cursor_surface_enter, cursor_surface_leave, }; static void ensure_cursor_surface(struct seat *seat) { struct wl_compositor *wl_compositor = seat->plugin_cairo->wl_compositor; if (seat->cursor_surface) return; seat->cursor_surface = wl_compositor_create_surface(wl_compositor); wl_surface_add_listener(seat->cursor_surface, &cursor_surface_listener, seat); } static bool ensure_cursor_theme(struct seat *seat) { struct libdecor_plugin_cairo *plugin_cairo = seat->plugin_cairo; int scale = 1; struct wl_cursor_theme *theme; struct cursor_output *cursor_output; wl_list_for_each(cursor_output, &seat->cursor_outputs, link) { scale = MAX(scale, cursor_output->output->scale); } if (seat->cursor_theme && seat->cursor_scale == scale) return false; seat->cursor_scale = scale; theme = wl_cursor_theme_load(plugin_cairo->cursor_theme_name, plugin_cairo->cursor_size * scale, plugin_cairo->wl_shm); if (theme == NULL) return false; if (seat->cursor_theme) wl_cursor_theme_destroy(seat->cursor_theme); seat->cursor_theme = theme; for (unsigned int i = 0; i < ARRAY_LENGTH(cursor_names); i++) { seat->cursors[i] = wl_cursor_theme_get_cursor( seat->cursor_theme, cursor_names[i]); } seat->cursor_left_ptr = wl_cursor_theme_get_cursor(seat->cursor_theme, "left_ptr"); seat->current_cursor = seat->cursor_left_ptr; return true; } enum libdecor_resize_edge component_edge(const struct border_component *cmpnt, const int pointer_x, const int pointer_y, const int margin) { const bool top = pointer_y < margin * 2; const bool bottom = pointer_y > (cmpnt->server.buffer->height - margin * 2); const bool left = pointer_x < margin * 2; const bool right = pointer_x > (cmpnt->server.buffer->width - margin * 2); if (top) if (left) return LIBDECOR_RESIZE_EDGE_TOP_LEFT; else if (right) return LIBDECOR_RESIZE_EDGE_TOP_RIGHT; else return LIBDECOR_RESIZE_EDGE_TOP; else if (bottom) if (left) return LIBDECOR_RESIZE_EDGE_BOTTOM_LEFT; else if (right) return LIBDECOR_RESIZE_EDGE_BOTTOM_RIGHT; else return LIBDECOR_RESIZE_EDGE_BOTTOM; else if (left) return LIBDECOR_RESIZE_EDGE_LEFT; else if (right) return LIBDECOR_RESIZE_EDGE_RIGHT; else return LIBDECOR_RESIZE_EDGE_NONE; } static bool update_local_cursor(struct seat *seat) { if (!seat->pointer_focus) { seat->current_cursor = seat->cursor_left_ptr; return false; } if (!own_surface(seat->pointer_focus)) return false; struct libdecor_frame_cairo *frame_cairo = wl_surface_get_user_data(seat->pointer_focus); struct wl_cursor *wl_cursor = NULL; if (!frame_cairo || !frame_cairo->active) { seat->current_cursor = seat->cursor_left_ptr; return false; } bool theme_updated = ensure_cursor_theme(seat); if (frame_cairo->active->type == SHADOW && is_border_surfaces_showing(frame_cairo) && resizable(frame_cairo)) { enum libdecor_resize_edge edge; edge = component_edge(frame_cairo->active, seat->pointer_x, seat->pointer_y, SHADOW_MARGIN); if (edge != LIBDECOR_RESIZE_EDGE_NONE) wl_cursor = seat->cursors[edge - 1]; } else { wl_cursor = seat->cursor_left_ptr; } if (seat->current_cursor != wl_cursor) { seat->current_cursor = wl_cursor; return true; } return theme_updated; } static void send_cursor(struct seat *seat) { struct wl_cursor_image *image; struct wl_buffer *buffer; if (seat->pointer_focus == NULL || seat->current_cursor == NULL) return; image = seat->current_cursor->images[0]; buffer = wl_cursor_image_get_buffer(image); wl_surface_attach(seat->cursor_surface, buffer, 0, 0); wl_surface_set_buffer_scale(seat->cursor_surface, seat->cursor_scale); wl_surface_damage_buffer(seat->cursor_surface, 0, 0, image->width * seat->cursor_scale, image->height * seat->cursor_scale); wl_surface_commit(seat->cursor_surface); wl_pointer_set_cursor(seat->wl_pointer, seat->serial, seat->cursor_surface, image->hotspot_x / seat->cursor_scale, image->hotspot_y / seat->cursor_scale); } static void sync_active_component(struct libdecor_frame_cairo *frame_cairo, struct seat *seat) { struct border_component *old_active; if (!seat->pointer_focus) return; old_active = frame_cairo->active; update_component_focus(frame_cairo, seat->pointer_focus, seat); if (old_active != frame_cairo->active) { draw_decoration(frame_cairo); libdecor_frame_toplevel_commit(&frame_cairo->frame); } if (update_local_cursor(seat)) send_cursor(seat); } static void synthesize_pointer_enter(struct seat *seat) { struct wl_surface *surface; struct libdecor_frame_cairo *frame_cairo; surface = seat->pointer_focus; if (!surface) return; frame_cairo = wl_surface_get_user_data(surface); if (!frame_cairo) return; update_component_focus(frame_cairo, seat->pointer_focus, seat); frame_cairo->grab = NULL; /* update decorations */ if (frame_cairo->active) { draw_decoration(frame_cairo); libdecor_frame_toplevel_commit(&frame_cairo->frame); } update_local_cursor(seat); send_cursor(seat); } static void synthesize_pointer_leave(struct seat *seat) { struct wl_surface *surface; struct libdecor_frame_cairo *frame_cairo; surface = seat->pointer_focus; if (!surface) return; frame_cairo = wl_surface_get_user_data(surface); if (!frame_cairo) return; if (!frame_cairo->active) return; frame_cairo->active = NULL; draw_decoration(frame_cairo); libdecor_frame_toplevel_commit(&frame_cairo->frame); update_local_cursor(seat); } static void pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct seat *seat = data; if (!surface) return; if (!own_surface(surface)) return; ensure_cursor_surface(seat); seat->pointer_x = wl_fixed_to_int(surface_x); seat->pointer_y = wl_fixed_to_int(surface_y); seat->serial = serial; seat->pointer_focus = surface; if (seat->grabbed) return; synthesize_pointer_enter(seat); } static void pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) { struct seat *seat = data; if (!surface) return; if (!own_surface(surface)) return; synthesize_pointer_leave(seat); seat->pointer_focus = NULL; } static void pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct seat *seat = data; struct libdecor_frame_cairo *frame_cairo; seat->pointer_x = wl_fixed_to_int(surface_x); seat->pointer_y = wl_fixed_to_int(surface_y); if (seat->grabbed) return; if (!seat->pointer_focus) return; frame_cairo = wl_surface_get_user_data(seat->pointer_focus); sync_active_component(frame_cairo, seat); } static void pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { struct seat *seat = data; struct libdecor_frame_cairo *frame_cairo; if (!seat->pointer_focus || !own_surface(seat->pointer_focus)) return; frame_cairo = wl_surface_get_user_data(seat->pointer_focus); if (!frame_cairo) return; if (seat->grabbed) { libdecor_frame_dismiss_popup(&frame_cairo->frame, seat->name); return; } if (!frame_cairo->active) return; if (button == BTN_LEFT) { if (state == WL_POINTER_BUTTON_STATE_PRESSED) { enum libdecor_resize_edge edge = LIBDECOR_RESIZE_EDGE_NONE; frame_cairo->grab = NULL; switch (frame_cairo->active->type) { case SHADOW: edge = component_edge(frame_cairo->active, seat->pointer_x, seat->pointer_y, SHADOW_MARGIN); break; case TITLE: if (time-seat->pointer_button_time_stamp < DOUBLE_CLICK_TIME_MS) { toggle_maximized(&frame_cairo->frame); } else if (moveable(frame_cairo)) { seat->pointer_button_time_stamp = time; libdecor_frame_move(&frame_cairo->frame, seat->wl_seat, serial); } break; case BUTTON_MIN: case BUTTON_MAX: case BUTTON_CLOSE: frame_cairo->grab = frame_cairo->active; break; default: break; } if (edge != LIBDECOR_RESIZE_EDGE_NONE && resizable(frame_cairo)) { libdecor_frame_resize( &frame_cairo->frame, seat->wl_seat, serial, edge); } } else if (state == WL_POINTER_BUTTON_STATE_RELEASED && frame_cairo->grab) { libdecor_frame_ref(&frame_cairo->frame); if (frame_cairo->grab == frame_cairo->focus) { switch (frame_cairo->active->type) { case BUTTON_MIN: if (minimizable(frame_cairo)) libdecor_frame_set_minimized( &frame_cairo->frame); break; case BUTTON_MAX: toggle_maximized(&frame_cairo->frame); break; case BUTTON_CLOSE: if (closeable(frame_cairo)) libdecor_frame_close(&frame_cairo->frame); break; default: break; } } frame_cairo->grab = NULL; sync_active_component(frame_cairo, seat); libdecor_frame_unref(&frame_cairo->frame); } } else if (button == BTN_RIGHT && state == WL_POINTER_BUTTON_STATE_PRESSED && seat->pointer_focus == frame_cairo->title_bar.title.server.wl_surface) { libdecor_frame_show_window_menu(&frame_cairo->frame, seat->wl_seat, serial, seat->pointer_x, seat->pointer_y - TITLE_HEIGHT); } } static void pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { } static struct wl_pointer_listener pointer_listener = { pointer_enter, pointer_leave, pointer_motion, pointer_button, pointer_axis }; static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) { struct seat *seat = data; if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !seat->wl_pointer) { seat->wl_pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); } else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer) { wl_pointer_release(seat->wl_pointer); seat->wl_pointer = NULL; } } static void seat_name(void *data, struct wl_seat *wl_seat, const char *name) { struct seat *seat = data; seat->name = strdup(name); } static struct wl_seat_listener seat_listener = { seat_capabilities, seat_name }; static void init_wl_seat(struct libdecor_plugin_cairo *plugin_cairo, uint32_t id, uint32_t version) { struct seat *seat; if (version < 3) { libdecor_notify_plugin_error( plugin_cairo->context, LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE, "%s version 3 required but only version %i is available\n", wl_seat_interface.name, version); } seat = zalloc(sizeof *seat); seat->cursor_scale = 1; seat->plugin_cairo = plugin_cairo; wl_list_init(&seat->cursor_outputs); wl_list_insert(&plugin_cairo->seat_list, &seat->link); seat->wl_seat = wl_registry_bind(plugin_cairo->wl_registry, id, &wl_seat_interface, 3); wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); } static void output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char *make, const char *model, int32_t transform) { } static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { } static void output_done(void *data, struct wl_output *wl_output) { struct output *output = data; struct libdecor_frame_cairo *frame_cairo; struct seat *seat; wl_list_for_each(frame_cairo, &output->plugin_cairo->visible_frame_list, link) { bool updated = false; updated |= redraw_scale(frame_cairo, &frame_cairo->shadow); updated |= redraw_scale(frame_cairo, &frame_cairo->title_bar.title); if (updated) libdecor_frame_toplevel_commit(&frame_cairo->frame); } wl_list_for_each(seat, &output->plugin_cairo->seat_list, link) { if (update_local_cursor(seat)) send_cursor(seat); } } static void output_scale(void *data, struct wl_output *wl_output, int32_t factor) { struct output *output = data; output->scale = factor; } static struct wl_output_listener output_listener = { output_geometry, output_mode, output_done, output_scale }; static void init_wl_output(struct libdecor_plugin_cairo *plugin_cairo, uint32_t id, uint32_t version) { struct output *output; if (version < 2) { libdecor_notify_plugin_error( plugin_cairo->context, LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE, "%s version 2 required but only version %i is available\n", wl_output_interface.name, version); } output = zalloc(sizeof *output); output->plugin_cairo = plugin_cairo; wl_list_insert(&plugin_cairo->output_list, &output->link); output->id = id; output->wl_output = wl_registry_bind(plugin_cairo->wl_registry, id, &wl_output_interface, MIN (version, 3)); wl_proxy_set_tag((struct wl_proxy *) output->wl_output, &libdecor_cairo_proxy_tag); wl_output_add_listener(output->wl_output, &output_listener, output); } static void registry_handle_global(void *user_data, struct wl_registry *wl_registry, uint32_t id, const char *interface, uint32_t version) { struct libdecor_plugin_cairo *plugin_cairo = user_data; if (strcmp(interface, "wl_compositor") == 0) init_wl_compositor(plugin_cairo, id, version); else if (strcmp(interface, "wl_subcompositor") == 0) init_wl_subcompositor(plugin_cairo, id, version); else if (strcmp(interface, "wl_shm") == 0) init_wl_shm(plugin_cairo, id, version); else if (strcmp(interface, "wl_seat") == 0) init_wl_seat(plugin_cairo, id, version); else if (strcmp(interface, "wl_output") == 0) init_wl_output(plugin_cairo, id, version); } static void remove_surface_outputs(struct border_component *cmpnt, struct output *output) { struct surface_output *surface_output; wl_list_for_each(surface_output, &cmpnt->server.output_list, link) { if (surface_output->output == output) { wl_list_remove(&surface_output->link); free(surface_output); break; } } } static void output_removed(struct libdecor_plugin_cairo *plugin_cairo, struct output *output) { struct libdecor_frame_cairo *frame_cairo; struct seat *seat; wl_list_for_each(frame_cairo, &plugin_cairo->visible_frame_list, link) { remove_surface_outputs(&frame_cairo->shadow, output); remove_surface_outputs(&frame_cairo->title_bar.title, output); remove_surface_outputs(&frame_cairo->title_bar.min, output); remove_surface_outputs(&frame_cairo->title_bar.max, output); remove_surface_outputs(&frame_cairo->title_bar.close, output); } wl_list_for_each(seat, &plugin_cairo->seat_list, link) { struct cursor_output *cursor_output, *tmp; wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link) { if (cursor_output->output == output) { wl_list_remove(&cursor_output->link); free(cursor_output); } } } wl_list_remove(&output->link); wl_output_destroy(output->wl_output); free(output); } static void registry_handle_global_remove(void *user_data, struct wl_registry *wl_registry, uint32_t name) { struct libdecor_plugin_cairo *plugin_cairo = user_data; struct output *output; wl_list_for_each(output, &plugin_cairo->output_list, link) { if (output->id == name) { output_removed(plugin_cairo, output); break; } } } static const struct wl_registry_listener registry_listener = { registry_handle_global, registry_handle_global_remove }; static bool has_required_globals(struct libdecor_plugin_cairo *plugin_cairo) { if (!plugin_cairo->wl_compositor) return false; if (!plugin_cairo->wl_subcompositor) return false; if (!plugin_cairo->wl_shm) return false; return true; } static void globals_callback(void *user_data, struct wl_callback *callback, uint32_t time) { struct libdecor_plugin_cairo *plugin_cairo = user_data; wl_callback_destroy(callback); plugin_cairo->globals_callback = NULL; } static const struct wl_callback_listener globals_callback_listener = { globals_callback }; static struct libdecor_plugin * libdecor_plugin_new(struct libdecor *context) { struct libdecor_plugin_cairo *plugin_cairo; struct wl_display *wl_display; plugin_cairo = zalloc(sizeof *plugin_cairo); libdecor_plugin_init(&plugin_cairo->plugin, context, &cairo_plugin_iface); plugin_cairo->context = context; wl_list_init(&plugin_cairo->visible_frame_list); wl_list_init(&plugin_cairo->seat_list); wl_list_init(&plugin_cairo->output_list); /* fetch cursor theme and size*/ if (!libdecor_get_cursor_settings(&plugin_cairo->cursor_theme_name, &plugin_cairo->cursor_size)) { plugin_cairo->cursor_theme_name = NULL; plugin_cairo->cursor_size = 24; } /* define a sens-serif bold font at symbol size */ plugin_cairo->font = pango_font_description_new(); pango_font_description_set_family(plugin_cairo->font, "sans"); pango_font_description_set_weight(plugin_cairo->font, PANGO_WEIGHT_BOLD); pango_font_description_set_absolute_size(plugin_cairo->font, SYM_DIM * PANGO_SCALE); wl_display = libdecor_get_wl_display(context); plugin_cairo->wl_registry = wl_display_get_registry(wl_display); wl_registry_add_listener(plugin_cairo->wl_registry, ®istry_listener, plugin_cairo); plugin_cairo->globals_callback = wl_display_sync(wl_display); wl_callback_add_listener(plugin_cairo->globals_callback, &globals_callback_listener, plugin_cairo); wl_display_roundtrip(wl_display); if (!has_required_globals(plugin_cairo)) { fprintf(stderr, "libdecor-cairo-WARNING: Could not get required globals\n"); libdecor_plugin_cairo_destroy(&plugin_cairo->plugin); return NULL; } return &plugin_cairo->plugin; } static struct libdecor_plugin_priority priorities[] = { { NULL, LIBDECOR_PLUGIN_PRIORITY_MEDIUM } }; LIBDECOR_EXPORT const struct libdecor_plugin_description libdecor_plugin_description = { .api_version = LIBDECOR_PLUGIN_API_VERSION, .capabilities = LIBDECOR_PLUGIN_CAPABILITY_BASE, .description = "libdecor plugin using Cairo", .priorities = priorities, .constructor = libdecor_plugin_new, }; fltk-1.4.3/libdecor/src/utils.h0000644000175000017500000000302115004135251016464 0ustar albrechtalbrecht/* * Copyright © 2017 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef UTILS_H #define UTILS_H #include #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #ifndef ARRAY_LENGTH #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) #endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #endif static inline void * zalloc(size_t size) { return calloc(1, size); } #endif /* UTILS_H */ fltk-1.4.3/libdecor/src/libdecor-fallback.h0000644000175000017500000000254615004135251020657 0ustar albrechtalbrecht/* * Copyright © 2019 Jonas Ådahl * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef LIBDECOR_FALLBACK_H #define LIBDECOR_FALLBACK_H #include "libdecor.h" #include "libdecor-plugin.h" struct libdecor_plugin * libdecor_fallback_plugin_new(struct libdecor *context); #endif /* LIBDECOR_FALLBACK_H */ fltk-1.4.3/libdecor/src/libdecor-fallback.c0000644000175000017500000001223115004135251020642 0ustar albrechtalbrecht/* * Copyright © 2019 Jonas Ådahl * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "config.h" #include "libdecor-fallback.h" #include #include #include "utils.h" struct libdecor_plugin_fallback { struct libdecor_plugin plugin; struct libdecor *context; }; static void libdecor_plugin_fallback_destroy(struct libdecor_plugin *plugin) { libdecor_plugin_release(plugin); free(plugin); } static int libdecor_plugin_fallback_get_fd(struct libdecor_plugin *plugin) { struct libdecor_plugin_fallback *plugin_fallback = (struct libdecor_plugin_fallback *) plugin; struct wl_display *wl_display = libdecor_get_wl_display(plugin_fallback->context); return wl_display_get_fd(wl_display); } static int libdecor_plugin_fallback_dispatch(struct libdecor_plugin *plugin, int timeout) { struct libdecor_plugin_fallback *plugin_fallback = (struct libdecor_plugin_fallback *) plugin; struct wl_display *wl_display = libdecor_get_wl_display(plugin_fallback->context); struct pollfd fds[1]; int ret; int dispatch_count = 0; while (wl_display_prepare_read(wl_display) != 0) dispatch_count += wl_display_dispatch_pending(wl_display); if (wl_display_flush(wl_display) < 0 && errno != EAGAIN) { wl_display_cancel_read(wl_display); return -errno; } fds[0] = (struct pollfd) { wl_display_get_fd(wl_display), POLLIN }; ret = poll(fds, ARRAY_SIZE (fds), timeout); if (ret > 0) { if (fds[0].revents & POLLIN) { wl_display_read_events(wl_display); dispatch_count += wl_display_dispatch_pending(wl_display); return dispatch_count; } else { wl_display_cancel_read(wl_display); return dispatch_count; } } else if (ret == 0) { wl_display_cancel_read(wl_display); return dispatch_count; } else { wl_display_cancel_read(wl_display); return -errno; } } static struct libdecor_frame * libdecor_plugin_fallback_frame_new(struct libdecor_plugin *plugin) { struct libdecor_frame *frame; frame = zalloc(sizeof *frame); return frame; } static void libdecor_plugin_fallback_frame_free(struct libdecor_plugin *plugin, struct libdecor_frame *frame) { } static void libdecor_plugin_fallback_frame_commit(struct libdecor_plugin *plugin, struct libdecor_frame *frame, struct libdecor_state *state, struct libdecor_configuration *configuration) { } static void libdecor_plugin_fallback_frame_property_changed(struct libdecor_plugin *plugin, struct libdecor_frame *frame) { } static void libdecor_plugin_fallback_frame_popup_grab(struct libdecor_plugin *plugin, struct libdecor_frame *frame, const char *seat_name) { } static void libdecor_plugin_fallback_frame_popup_ungrab(struct libdecor_plugin *plugin, struct libdecor_frame *frame, const char *seat_name) { } static bool libdecor_plugin_fallback_frame_get_border_size(struct libdecor_plugin *plugin, struct libdecor_frame *frame, struct libdecor_configuration *configuration, int *left, int *right, int *top, int *bottom) { if (left) *left = 0; if (right) *right = 0; if (top) *top = 0; if (bottom) *bottom = 0; return true; } static struct libdecor_plugin_interface fallback_plugin_iface = { .destroy = libdecor_plugin_fallback_destroy, .get_fd = libdecor_plugin_fallback_get_fd, .dispatch = libdecor_plugin_fallback_dispatch, .frame_new = libdecor_plugin_fallback_frame_new, .frame_free = libdecor_plugin_fallback_frame_free, .frame_commit = libdecor_plugin_fallback_frame_commit, .frame_property_changed = libdecor_plugin_fallback_frame_property_changed, .frame_popup_grab = libdecor_plugin_fallback_frame_popup_grab, .frame_popup_ungrab = libdecor_plugin_fallback_frame_popup_ungrab, .frame_get_border_size = libdecor_plugin_fallback_frame_get_border_size, }; struct libdecor_plugin * libdecor_fallback_plugin_new(struct libdecor *context) { struct libdecor_plugin_fallback *plugin; plugin = zalloc(sizeof *plugin); libdecor_plugin_init(&plugin->plugin, context, &fallback_plugin_iface); plugin->context = context; libdecor_notify_plugin_ready(context); return &plugin->plugin; } fltk-1.4.3/libdecor/src/libdecor-plugin.h0000644000175000017500000001272315004135251020414 0ustar albrechtalbrecht/* * Copyright © 2017-2018 Red Hat Inc. * Copyright © 2018 Jonas Ådahl * Copyright © 2019 Christian Rauch * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef LIBDECOR_PLUGIN_H #define LIBDECOR_PLUGIN_H #include "libdecor.h" struct libdecor_frame_private; struct libdecor_frame { struct libdecor_frame_private *priv; struct wl_list link; }; struct libdecor_plugin_private; struct libdecor_plugin { struct libdecor_plugin_private *priv; }; typedef struct libdecor_plugin * (* libdecor_plugin_constructor)(struct libdecor *context); #define LIBDECOR_PLUGIN_PRIORITY_HIGH 1000 #define LIBDECOR_PLUGIN_PRIORITY_MEDIUM 100 #define LIBDECOR_PLUGIN_PRIORITY_LOW 0 struct libdecor_plugin_priority { const char *desktop; int priority; }; enum libdecor_plugin_capabilities { LIBDECOR_PLUGIN_CAPABILITY_BASE = 1 << 0, }; struct libdecor_plugin_description { /* API version the plugin is compatible with. */ int api_version; /* Human readable string describing the plugin. */ char *description; /* A plugin has a bitmask of capabilities. The plugin loader can use this * to load a plugin with the right capabilities. */ enum libdecor_plugin_capabilities capabilities; /* * The priorities field points to a list of per desktop priorities. * properties[i].desktop is matched against XDG_CURRENT_DESKTOP when * determining what plugin to use. The last entry in the list MUST have * the priorities[i].desktop pointer set to NULL as a default * priority. */ const struct libdecor_plugin_priority *priorities; /* Vfunc used for constructing a plugin instance. */ libdecor_plugin_constructor constructor; /* NULL terminated list of incompatible symbols. */ char *conflicting_symbols[1024]; }; struct libdecor_plugin_interface { void (* destroy)(struct libdecor_plugin *plugin); int (* get_fd)(struct libdecor_plugin *plugin); int (* dispatch)(struct libdecor_plugin *plugin, int timeout); struct libdecor_frame * (* frame_new)(struct libdecor_plugin *plugin); void (* frame_free)(struct libdecor_plugin *plugin, struct libdecor_frame *frame); void (* frame_commit)(struct libdecor_plugin *plugin, struct libdecor_frame *frame, struct libdecor_state *state, struct libdecor_configuration *configuration); void (*frame_property_changed)(struct libdecor_plugin *plugin, struct libdecor_frame *frame); void (* frame_popup_grab)(struct libdecor_plugin *plugin, struct libdecor_frame *frame, const char *seat_name); void (* frame_popup_ungrab)(struct libdecor_plugin *plugin, struct libdecor_frame *frame, const char *seat_name); bool (* frame_get_border_size)(struct libdecor_plugin *plugin, struct libdecor_frame *frame, struct libdecor_configuration *configuration, int *left, int *right, int *top, int *bottom); /* Reserved */ void (* reserved0)(void); void (* reserved1)(void); void (* reserved2)(void); void (* reserved3)(void); void (* reserved4)(void); void (* reserved5)(void); void (* reserved6)(void); void (* reserved7)(void); void (* reserved8)(void); void (* reserved9)(void); }; struct wl_surface * libdecor_frame_get_wl_surface(struct libdecor_frame *frame); int libdecor_frame_get_content_width(struct libdecor_frame *frame); int libdecor_frame_get_content_height(struct libdecor_frame *frame); enum libdecor_window_state libdecor_frame_get_window_state(struct libdecor_frame *frame); enum libdecor_capabilities libdecor_frame_get_capabilities(const struct libdecor_frame *frame); void libdecor_frame_dismiss_popup(struct libdecor_frame *frame, const char *seat_name); void libdecor_frame_toplevel_commit(struct libdecor_frame *frame); struct wl_display * libdecor_get_wl_display(struct libdecor *context); void libdecor_notify_plugin_ready(struct libdecor *context); void libdecor_notify_plugin_error(struct libdecor *context, enum libdecor_error error, const char *__restrict fmt, ...); int libdecor_state_get_content_width(struct libdecor_state *state); int libdecor_state_get_content_height(struct libdecor_state *state); enum libdecor_window_state libdecor_state_get_window_state(struct libdecor_state *state); int libdecor_plugin_init(struct libdecor_plugin *plugin, struct libdecor *context, struct libdecor_plugin_interface *iface); void libdecor_plugin_release(struct libdecor_plugin *plugin); #endif /* LIBDECOR_PLUGIN_H */ fltk-1.4.3/libdecor/build/0000755000175000017500000000000015004135251015467 5ustar albrechtalbrechtfltk-1.4.3/libdecor/build/fl_libdecor.c0000644000175000017500000001322615004135251020103 0ustar albrechtalbrecht// // Interface with the libdecor library for the Fast Light Tool Kit (FLTK). // // Copyright 2022-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* Improvements to libdecor.c without modifying libdecor.c itself */ #if ! USE_SYSTEM_LIBDECOR #include "xdg-shell-client-protocol.h" #ifdef XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION # define HAVE_XDG_SHELL_V6 1 #endif #include #include static void *dlopen_corrected(const char *, int); #define dlopen(A, B) dlopen_corrected(A, B) #include "fl_libdecor.h" #undef libdecor_new #define libdecor_new libdecor_new_orig #undef libdecor_frame_set_minimized #define libdecor_frame_set_minimized libdecor_frame_set_minimized_orig #include "../src/libdecor.c" #undef dlopen #undef libdecor_frame_set_minimized #undef libdecor_new #define libdecor_new fl_libdecor_new #define libdecor_frame_set_minimized fl_libdecor_frame_set_minimized extern bool fl_libdecor_using_weston(void); extern const struct libdecor_plugin_description *fl_libdecor_plugin_description; //#include // we have a built-in plugin so don't need a fallback one struct libdecor_plugin *libdecor_fallback_plugin_new(struct libdecor *context) { return NULL; } // see get_libdecor_plugin_description() explaining why this is useful static void *dlopen_corrected(const char *filename, int flags) { static int best_priority = -1; void *retval = dlopen(filename, flags); if (retval) { const struct libdecor_plugin_description *description = (const struct libdecor_plugin_description*)dlsym(retval, "libdecor_plugin_description"); if (description && description->priorities->priority > best_priority) { fl_libdecor_plugin_description = description; best_priority = description->priorities->priority; } } return retval; } void fl_libdecor_frame_set_minimized(struct libdecor_frame *frame) { static bool done = false; static bool using_weston = false; if (!done) { typedef bool (*ext_f)(void); volatile ext_f ext = fl_libdecor_using_weston; done = true; if (ext) using_weston = fl_libdecor_using_weston(); //fprintf(stderr, "fl_libdecor_using_weston=%p using_weston=%d\n", fl_libdecor_using_weston, using_weston); if (using_weston) { // determine the version of the running Weston compositor FILE *pipe = popen("weston --version", "r"); if (pipe) { char line[50], *p; int version = 0; p = fgets(line, sizeof(line), pipe); pclose(pipe); if (p) p = strchr(line, ' '); if (p) { sscanf(p, "%d", &version); // Weston version 10 has fixed the bug handled here if (version >= 10) using_weston = false; } } } } if (using_weston) libdecor_frame_set_visibility(frame, false); libdecor_frame_set_minimized_orig(frame); } /* By default, FLTK modifies libdecor's libdecor_new() function to determine the plugin as follows : 1) the directory pointed by environment variable LIBDECOR_PLUGIN_DIR or, in absence of this variable, by -DLIBDECOR_PLUGIN_DIR=xxx at build time is searched for a libdecor plugin; 2) if this directory does not exist or contains no plugin, the built-in plugin is used. * if FLTK was built with package libgtk-3-dev, the GTK plugin is used * if FLTK was built without package libgtk-3-dev, the Cairo plugin is used If FLTK was built with FLTK_USE_SYSTEM_LIBDECOR turned ON, the present modification isn't compiled, so the plugin-searching algorithm of libdecor_new() in libdecor-0.so is used. This corresponds to step 1) above and to use no titlebar is no plugin is found. N.B.: only the system package is built with a meaningful value of -DLIBDECOR_PLUGIN_DIR= so a plugin may be loaded that way only if FLTK was built with FLTK_USE_SYSTEM_LIBDECOR turned ON. */ struct libdecor *fl_libdecor_new(struct wl_display *wl_display, const struct libdecor_interface *iface) { struct libdecor *context; context = zalloc(sizeof *context); context->ref_count = 1; context->iface = iface; context->wl_display = wl_display; context->wl_registry = wl_display_get_registry(wl_display); wl_registry_add_listener(context->wl_registry, ®istry_listener, context); context->init_callback = wl_display_sync(context->wl_display); wl_callback_add_listener(context->init_callback, &init_wl_display_callback_listener, context); wl_list_init(&context->frames); // attempt to dynamically load a libdecor plugin with dlopen() if (init_plugins(context) != 0) { // attempt to load plugin by dlopen() // no plug-in was found by dlopen(), use built-in plugin instead // defined in the source code of the built-in plugin: libdecor-cairo.c or libdecor-gtk.c extern const struct libdecor_plugin_description libdecor_plugin_description; #if HAVE_GTK bool gdk_caution = false; if (getenv("GDK_BACKEND") && strcmp(getenv("GDK_BACKEND"), "x11") == 0) { // Environment variable GDK_BACKEND=x11 makes the .constructor below fail // for the built-in GTK plugin and then FLTK crashes (#1029). // Temporarily unset GDK_BACKEND to prevent that. gdk_caution = true; unsetenv("GDK_BACKEND"); } #endif context->plugin = libdecor_plugin_description.constructor(context); #if HAVE_GTK if (gdk_caution) putenv("GDK_BACKEND=x11"); #endif } wl_display_flush(wl_display); return context; } #endif //! USE_SYSTEM_LIBDECOR fltk-1.4.3/libdecor/build/Makefile0000644000175000017500000000622615004135251017135 0ustar albrechtalbrecht# # Library Makefile for the Fast Light Tool Kit (FLTK). # # Copyright 2022-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # include ../../makeinclude OBJECTS = fl_libdecor.o libdecor-cairo-blur.o fl_libdecor-plugins.o \ ../../src/xdg-decoration-protocol.o ../../src/xdg-shell-protocol.o \ ../../src/text-input-protocol.o ../../src/gtk-shell-protocol.o desktop-settings.o os-compatibility.o PROTOCOLS = `pkg-config --variable=pkgdatadir wayland-protocols` Linux_CFLAGS = FreeBSD_CFLAGS = -I/usr/local/include EXTRA_DECOR = ${${UNAME}_CFLAGS} CFLAGS_DECOR = -I. -I../.. -I../../src -I../src -I../src/plugins $(EXTRA_DECOR) -fPIC -D_GNU_SOURCE \ -DHAVE_MEMFD_CREATE -DHAVE_MKOSTEMP -DHAVE_POSIX_FALLOCATE all : $(OBJECTS) depend: : echo "libdecor/build: make depend..." fl_libdecor.o : fl_libdecor.c ../src/libdecor.c ../../src/xdg-shell-protocol.c ../../src/xdg-decoration-protocol.c ../../src/text-input-protocol.c ../../src/gtk-shell-protocol.c $(CC) $(CFLAGS) $(CFLAGS_DECOR) -c fl_libdecor.c -DLIBDECOR_PLUGIN_API_VERSION=1 fl_libdecor-plugins.o : fl_libdecor-plugins.c ../src/plugins/cairo/libdecor-cairo.c $(CC) $(CFLAGS) $(CFLAGS_DECOR) -c fl_libdecor-plugins.c -DLIBDECOR_PLUGIN_API_VERSION=1 libdecor-cairo-blur.o : ../src/plugins/common/libdecor-cairo-blur.c $(CC) $(CFLAGS_DECOR) -c ../src/plugins/common/libdecor-cairo-blur.c os-compatibility.o : ../src/os-compatibility.c $(CC) $(CFLAGS_DECOR) -c ../src/os-compatibility.c desktop-settings.o : ../src/desktop-settings.c $(CC) $(CFLAGS_DECOR) -c ../src/desktop-settings.c $(LIBDECORDBUS) ../../src/xdg-shell-protocol.c : wayland-scanner private-code $(PROTOCOLS)/stable/xdg-shell/xdg-shell.xml \ ../../src/xdg-shell-protocol.c wayland-scanner client-header $(PROTOCOLS)/stable/xdg-shell/xdg-shell.xml \ ../../src/xdg-shell-client-protocol.h ../../src/xdg-decoration-protocol.c : wayland-scanner private-code \ $(PROTOCOLS)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml \ ../../src/xdg-decoration-protocol.c wayland-scanner client-header \ $(PROTOCOLS)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml \ ../../src/xdg-decoration-client-protocol.h ../../src/text-input-protocol.c : wayland-scanner private-code \ $(PROTOCOLS)/unstable/text-input/text-input-unstable-v3.xml \ ../../src/text-input-protocol.c wayland-scanner client-header \ $(PROTOCOLS)/unstable/text-input/text-input-unstable-v3.xml \ ../../src/text-input-client-protocol.h ../../src/gtk-shell-protocol.c : wayland-scanner private-code \ gtk-shell.xml ../../src/gtk-shell-protocol.c wayland-scanner client-header \ gtk-shell.xml ../../src/gtk-shell-client-protocol.h install: echo "Nothing to install" uninstall: clean: $(RM) *.o ../../src/xdg-*.c ../../src/xdg-*.h ../../src/xdg-*.o ../../src/text-input-* ../../src/gtk-shell-* fltk-1.4.3/libdecor/build/fl_libdecor.h0000644000175000017500000001140415004135251020104 0ustar albrechtalbrecht// // Interface with the libdecor library for the Fast Light Tool Kit (FLTK). // // Copyright 2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_LIBDECOR_H #define FL_LIBDECOR_H #if ! USE_SYSTEM_LIBDECOR // add "fl_" prefix to libdecor.h symbols #define libdecor_unref fl_libdecor_unref #define libdecor_new fl_libdecor_new #define libdecor_new_with_user_data fl_libdecor_new_with_user_data #define libdecor_get_user_data fl_libdecor_get_user_data #define libdecor_set_user_data fl_libdecor_set_user_data #define libdecor_get_fd fl_libdecor_get_fd #define libdecor_dispatch fl_libdecor_dispatch #define libdecor_decorate fl_libdecor_decorate #define libdecor_frame_ref fl_libdecor_frame_ref #define libdecor_frame_unref fl_libdecor_frame_unref #define libdecor_frame_get_user_data fl_libdecor_frame_get_user_data #define libdecor_frame_set_user_data fl_libdecor_frame_set_user_data #define libdecor_frame_set_visibility fl_libdecor_frame_set_visibility #define libdecor_frame_is_visible fl_libdecor_frame_is_visible #define libdecor_frame_set_parent fl_libdecor_frame_set_parent #define libdecor_frame_set_title fl_libdecor_frame_set_title #define libdecor_frame_get_title fl_libdecor_frame_get_title #define libdecor_frame_set_app_id fl_libdecor_frame_set_app_id #define libdecor_frame_set_capabilities fl_libdecor_frame_set_capabilities #define libdecor_frame_unset_capabilities fl_libdecor_frame_unset_capabilitiesf #define libdecor_frame_has_capability fl_libdecor_frame_has_capability #define libdecor_frame_show_window_menu fl_libdecor_frame_show_window_menu #define libdecor_frame_popup_grab fl_libdecor_frame_popup_grab #define libdecor_frame_popup_ungrab fl_libdecor_frame_popup_ungrab #define libdecor_frame_translate_coordinate fl_libdecor_frame_translate_coordinate #define libdecor_frame_set_min_content_size fl_libdecor_frame_set_min_content_size #define libdecor_frame_set_max_content_size fl_libdecor_frame_set_max_content_size #define libdecor_frame_get_min_content_size fl_libdecor_frame_get_min_content_size #define libdecor_frame_get_max_content_size fl_libdecor_frame_get_max_content_size #define libdecor_frame_resize fl_libdecor_frame_resize #define libdecor_frame_move fl_libdecor_frame_move #define libdecor_frame_commit fl_libdecor_frame_commit #define libdecor_frame_set_minimized fl_libdecor_frame_set_minimized #define libdecor_frame_set_maximized fl_libdecor_frame_set_maximized #define libdecor_frame_unset_maximized fl_libdecor_frame_unset_maximized #define libdecor_frame_set_fullscreen fl_libdecor_frame_set_fullscreen #define libdecor_frame_unset_fullscreen fl_libdecor_frame_unset_fullscreen #define libdecor_frame_is_floating fl_libdecor_frame_is_floating #define libdecor_frame_close fl_libdecor_frame_close #define libdecor_frame_map fl_libdecor_frame_map #define libdecor_frame_get_xdg_surface fl_libdecor_frame_get_xdg_surface #define libdecor_frame_get_xdg_toplevel fl_libdecor_frame_get_xdg_toplevel #define libdecor_frame_get_wm_capabilities fl_libdecor_frame_get_wm_capabilities #define libdecor_state_new fl_libdecor_state_new #define libdecor_state_free fl_libdecor_state_free #define libdecor_configuration_get_content_size fl_libdecor_configuration_get_content_size #define libdecor_configuration_get_window_state fl_libdecor_configuration_get_window_state // add "fl_" prefix to libdecor-plugin.h symbols #define libdecor_frame_get_wl_surface fl_libdecor_frame_get_wl_surface #define libdecor_frame_get_content_width fl_libdecor_frame_get_content_width #define libdecor_frame_get_content_height fl_libdecor_frame_get_content_height #define libdecor_frame_get_window_state fl_libdecor_frame_get_window_state #define libdecor_frame_get_capabilities fl_libdecor_frame_get_capabilities #define libdecor_frame_dismiss_popup fl_libdecor_frame_dismiss_popup #define libdecor_frame_toplevel_commit fl_libdecor_frame_toplevel_commit #define libdecor_get_wl_display fl_libdecor_get_wl_display #define libdecor_notify_plugin_ready fl_libdecor_notify_plugin_ready #define libdecor_notify_plugin_error fl_libdecor_notify_plugin_error #define libdecor_state_get_content_width fl_libdecor_state_get_content_width #define libdecor_state_get_content_height fl_libdecor_state_get_content_height #define libdecor_state_get_window_state fl_libdecor_state_get_window_state #define libdecor_plugin_init fl_libdecor_plugin_init #define libdecor_plugin_release fl_libdecor_plugin_release #endif // ! USE_SYSTEM_LIBDECOR #include "../src/libdecor.h" #endif // ! FL_LIBDECOR_H fltk-1.4.3/libdecor/build/gtk-shell.xml0000644000175000017500000000656515004135251020117 0ustar albrechtalbrecht gtk_shell is a protocol extension providing additional features for clients implementing it. fltk-1.4.3/libdecor/build/fl_libdecor-plugins.c0000644000175000017500000002305615004135251021564 0ustar albrechtalbrecht// // Interface with the libdecor library for the Fast Light Tool Kit (FLTK). // // Copyright 2022-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* Support of interactions between FLTK and libdecor plugins, either dynamically loaded by dlopen() or built-in FLTK. Under USE_SYSTEM_LIBDECOR, the plugin can only be dynamically loaded. Under ! USE_SYSTEM_LIBDECOR, it can be dynamically loaded from a directory given in environment variable LIBDECOR_PLUGIN_DIR, or the built-in one is used. */ #include #include #include "fl_libdecor.h" #include #include #ifndef HAVE_GTK # define HAVE_GTK 0 #endif enum plugin_kind { UNKNOWN, SSD, CAIRO, GTK3 }; #if USE_SYSTEM_LIBDECOR # include "../src/libdecor-plugin.h" enum component {NONE}; /* details are not necessary*/ enum decoration_type {DECORATION_TYPE_NONE}; /* details are not necessary*/ struct buffer { // identical in libdecor-cairo.c and libdecor-gtk.c struct wl_buffer *wl_buffer; bool in_use; bool is_detached; void *data; size_t data_size; int width; int height; int scale; int buffer_width; int buffer_height; }; #else // !USE_SYSTEM_LIBDECOR const struct libdecor_plugin_description *fl_libdecor_plugin_description = NULL; # if HAVE_GTK # include "../src/plugins/gtk/libdecor-gtk.c" # else # include "../src/plugins/cairo/libdecor-cairo.c" # endif // HAVE_GTK #endif // USE_SYSTEM_LIBDECOR #if USE_SYSTEM_LIBDECOR || HAVE_GTK /* these definitions derive from libdecor/src/plugins/cairo/libdecor-cairo.c */ enum composite_mode {COMPOSITE_SERVER}; /* details are not necessary*/ struct border_component_cairo { enum component type; bool is_hidden; bool opaque; enum composite_mode composite_mode; struct { struct wl_surface *wl_surface; struct wl_subsurface *wl_subsurface; struct buffer *buffer; struct wl_list output_list; int scale; } server; struct { cairo_surface_t *image; struct border_component_cairo *parent_component; } client; struct wl_list child_components; /* border_component::link */ struct wl_list link; /* border_component::child_components */ }; struct libdecor_frame_cairo { struct libdecor_frame frame; struct libdecor_plugin_cairo *plugin_cairo; int content_width; int content_height; enum decoration_type decoration_type; enum libdecor_window_state window_state; char *title; enum libdecor_capabilities capabilities; struct border_component_cairo *focus; struct border_component_cairo *active; struct border_component_cairo *grab; bool shadow_showing; struct border_component_cairo shadow; struct { bool is_showing; struct border_component_cairo title; struct border_component_cairo min; struct border_component_cairo max; struct border_component_cairo close; } title_bar; /* store pre-processed shadow tile */ cairo_surface_t *shadow_blur; struct wl_list link; }; #endif // USE_SYSTEM_LIBDECOR || HAVE_GTK #if USE_SYSTEM_LIBDECOR || !HAVE_GTK /* Definitions derived from libdecor-gtk.c */ typedef struct _GtkWidget GtkWidget; enum header_element { HEADER_NONE }; /* details are not needed */ typedef enum { GTK_STATE_FLAG_NORMAL = 0 } GtkStateFlags; struct border_component_gtk { enum component type; struct wl_surface *wl_surface; struct wl_subsurface *wl_subsurface; struct buffer *buffer; bool opaque; struct wl_list output_list; int scale; struct wl_list child_components; /* border_component::link */ struct wl_list link; /* border_component::child_components */ }; struct header_element_data { const char* name; enum header_element type; GtkWidget *widget; GtkStateFlags state; }; struct libdecor_frame_gtk { struct libdecor_frame frame; struct libdecor_plugin_gtk *plugin_gtk; int content_width; int content_height; enum libdecor_window_state window_state; enum decoration_type decoration_type; char *title; enum libdecor_capabilities capabilities; struct border_component_gtk *active; struct border_component_gtk *touch_active; struct border_component_gtk *focus; struct border_component_gtk *grab; bool shadow_showing; struct border_component_gtk shadow; GtkWidget *window; /* offscreen window for rendering */ GtkWidget *header; /* header bar with widgets */ struct border_component_gtk headerbar; struct header_element_data hdr_focus; cairo_surface_t *shadow_blur; struct wl_list link; struct { enum titlebar_gesture_state {TITLEBAR_GESTURE_STATE_INIT} state; int button_pressed_count; uint32_t first_pressed_button; uint32_t first_pressed_time; double pressed_x; double pressed_y; uint32_t pressed_serial; } titlebar_gesture; }; #endif // USE_SYSTEM_LIBDECOR || !HAVE_GTK static unsigned char *gtk_titlebar_buffer(struct libdecor_frame *frame, int *width, int *height, int *stride) { struct libdecor_frame_gtk *lfg = (struct libdecor_frame_gtk *)frame; struct buffer *buffer = lfg->headerbar.buffer; *width = buffer->buffer_width; *height = buffer->buffer_height; *stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, buffer->buffer_width); return (unsigned char*)buffer->data; } static unsigned char *cairo_titlebar_buffer(struct libdecor_frame *frame, int *width, int *height, int *stride) { struct libdecor_frame_cairo *lfc = (struct libdecor_frame_cairo *)frame; struct buffer *buffer = lfc->title_bar.title.server.buffer; *width = buffer->buffer_width; *height = buffer->buffer_height; *stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, buffer->buffer_width); return (unsigned char*)buffer->data; } /* Although each plugin declares an exported global variable LIBDECOR_EXPORT const struct libdecor_plugin_description libdecor_plugin_description; these plugins are dlopen()'ed in libdecor.c without the RTLD_GLOBAL flag. Consequently their symbols are not discovered by dlsym(RTLD_DEFAULT, "symbol-name"). Under USE_SYSTEM_LIBDECOR, we repeat the dlopen() for the same plugin then dlsym() will report the address of libdecor_plugin_description. Under !USE_SYSTEM_LIBDECOR, we compile fl_libdecor.c which modifies the dlopen() to call dlsym(ld, "libdecor_plugin_description") just after the dlopen and memorizes this address. A plugin is loaded also if SSD. KWin has its own size limit, similar to that of GDK plugin */ static const char *get_libdecor_plugin_description() { static const struct libdecor_plugin_description *plugin_description = NULL; if (!plugin_description) { #if USE_SYSTEM_LIBDECOR char fname[PATH_MAX]; const char *dir = getenv("LIBDECOR_PLUGIN_DIR"); if (!dir) dir = LIBDECOR_PLUGIN_DIR; snprintf(fname, PATH_MAX, "%s/libdecor-gtk.so", dir); void *dl = dlopen(fname, RTLD_LAZY | RTLD_LOCAL); if (!dl) { snprintf(fname, PATH_MAX, "%s/libdecor-cairo.so", dir); dl = dlopen(fname, RTLD_LAZY | RTLD_LOCAL); } if (dl) plugin_description = (const struct libdecor_plugin_description*)dlsym(dl, "libdecor_plugin_description"); #else plugin_description = fl_libdecor_plugin_description; extern const struct libdecor_plugin_description libdecor_plugin_description; if (!plugin_description) plugin_description = &libdecor_plugin_description; #endif //if (plugin_description) puts(plugin_description->description); } return plugin_description ? plugin_description->description : NULL; } static enum plugin_kind get_plugin_kind(struct libdecor_frame *frame) { static enum plugin_kind kind = UNKNOWN; if (kind == UNKNOWN) { if (frame) { int X, Y = 0; libdecor_frame_translate_coordinate(frame, 0, 0, &X, &Y); if (Y == 0) { return SSD; } } const char *name = get_libdecor_plugin_description(); if (name && !strcmp(name, "GTK3 plugin")) kind = GTK3; else if (name && !strcmp(name, "libdecor plugin using Cairo")) kind = CAIRO; } return kind; } /* FLTK-added utility function to give access to the pixel array representing the titlebar of a window decorated by the cairo plugin of libdecor. frame: a libdecor-defined pointer given by fl_xid(win)->frame (with Fl_Window *win); *width, *height: returned assigned to the width and height in pixels of the titlebar; *stride: returned assigned to the number of bytes per line of the pixel array; return value: start of the pixel array, which is in BGRA order, or NULL. */ unsigned char *fl_libdecor_titlebar_buffer(struct libdecor_frame *frame, int *width, int *height, int *stride) { enum plugin_kind kind = get_plugin_kind(frame); if (kind == GTK3) { return gtk_titlebar_buffer(frame, width, height, stride); } else if (kind == CAIRO) { return cairo_titlebar_buffer(frame, width, height, stride); } return NULL; } /* Returns whether surface is the libdecor-created GTK-titlebar of frame */ bool fl_is_surface_from_GTK_titlebar (struct wl_surface *surface, struct libdecor_frame *frame, bool *using_GTK) { *using_GTK = (get_plugin_kind(NULL) == GTK3); if (!*using_GTK) return false; struct libdecor_frame_gtk *frame_gtk = (struct libdecor_frame_gtk*)frame; return (frame_gtk->headerbar.wl_surface == surface); } fltk-1.4.3/libdecor/README.md0000644000175000017500000000612215004135251015650 0ustar albrechtalbrecht# libdecor - A client-side decorations library for Wayland client libdecor is a library that can help Wayland clients draw window decorations for them. It aims to provide multiple backends that implements the decoration drawing. ## Dependencies Required: - `meson` >= 0.47 - `ninja` - `wayland-client` >= 1.18 - `wayland-protocols` >= 1.15 - `wayland-cursor` - `cairo` - `pangocairo` Recommended: - `dbus-1` (to query current cursor theme) Optional - `egl` (to build EGL example) - `opengl` - `xkbcommon` (to build cairo demo) Install via apt: `sudo apt install meson libwayland-dev wayland-protocols libpango1.0-dev libdbus-1-dev libegl-dev libopengl-dev libxkbcommon-dev` Install via dnf: `sudo dnf install meson wayland-devel wayland-protocols-devel pango-devel dbus-devel mesa-libEGL-devel libglvnd-devel libxkbcommon-devel` Newer meson versions can be installed via pip: `pip3 install -U meson`. ## Build & Install ### Quick Start To build and run the example program: 1. `meson build -Dinstall_demo=true && meson compile -C build` 2. `meson devenv -C build libdecor-demo` ### Release Builds The library and default plugins can be built and installed via: 1. `meson build --buildtype release` 2. `meson install -C build` where `build` is the build directory that will be created during this process. This will install by default to `/usr/local/`. To change this set the `prefix` during built, e.g. `meson build --buildtype release -Dprefix=$HOME/.local/`. Plugins will be installed into the same directory and from thereon will be selected automatically depending on their precedence. This behaviour can be overridden at runtime by setting the environment variable `LIBDECOR_PLUGIN_DIR` and pointing it to a directory with a valid plugin. ### Debug and Development Builds During development and when debugging, it is recommended to enable the AddressSanitizer and increase the warning level: 1. `meson build -Dinstall_demo=true -Db_sanitize=address -Dwarning_level=3` 2. `meson compile -C build` You may have to install `libasan6` (apt) or `libasan` (dnf). Otherwise linking will fail. By default `libdecor` will look for plugins in the target directory of the installation. Therefore, when running the demos directly from the `build` directory, no plugins will be found and the fallback plugin without any decorations will be used. On Meson 0.58.0 and above, this can be corrected using `devenv`, i.e., to run the demo: `meson devenv -C build libdecor-demo` On older Meson versions, the search path for plugins can be overridden by the environment variable `LIBDECOR_PLUGIN_DIR`. To use the `cairo` plugin, point to the plugin directory: `export LIBDECOR_PLUGIN_DIR=build/src/plugins/cairo/` and run the demo: `./build/demo/libdecor-demo`. ### Code of Conduct libdecor follows the Contributor Covenant, found at: https://www.freedesktop.org/wiki/CodeOfConduct Please conduct yourself in a respectful and civilised manner when interacting with community members on mailing lists, IRC, or bug trackers. The community represents the project as a whole, and abusive or bullying behaviour is not tolerated by the project. fltk-1.4.3/test/0000755000175000017500000000000015004135251013564 5ustar albrechtalbrechtfltk-1.4.3/test/CubeView.cxx0000644000175000017500000000762715004135251016035 0ustar albrechtalbrecht// // CubeView class implementation for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Note to editor: the following code can and should be copied // to the fluid tutorial in 'documentation/src/fluid.dox' // *without* '#if HAVE_GL' preprocessor statements, leaving // only those parts where the condition is true. // [\code in documentation/src/fluid.dox] #include "CubeView.h" #include #if HAVE_GL CubeView::CubeView(int x, int y, int w, int h, const char *l) : Fl_Gl_Window(x, y, w, h, l) #else CubeView::CubeView(int x, int y, int w, int h, const char *l) : Fl_Box(x, y, w, h, l) #endif /* HAVE_GL */ { Fl::use_high_res_GL(1); vAng = 0.0; hAng = 0.0; size = 10.0; xshift = 0.0; yshift = 0.0; /* The cube definition. These are the vertices of a unit cube * centered on the origin.*/ boxv0[0] = -0.5; boxv0[1] = -0.5; boxv0[2] = -0.5; boxv1[0] = 0.5; boxv1[1] = -0.5; boxv1[2] = -0.5; boxv2[0] = 0.5; boxv2[1] = 0.5; boxv2[2] = -0.5; boxv3[0] = -0.5; boxv3[1] = 0.5; boxv3[2] = -0.5; boxv4[0] = -0.5; boxv4[1] = -0.5; boxv4[2] = 0.5; boxv5[0] = 0.5; boxv5[1] = -0.5; boxv5[2] = 0.5; boxv6[0] = 0.5; boxv6[1] = 0.5; boxv6[2] = 0.5; boxv7[0] = -0.5; boxv7[1] = 0.5; boxv7[2] = 0.5; #if !HAVE_GL label("OpenGL is required for this demo to operate."); align(FL_ALIGN_WRAP | FL_ALIGN_INSIDE); #endif /* !HAVE_GL */ } #if HAVE_GL void CubeView::drawCube() { /* Draw a colored cube */ #define ALPHA 0.5 glShadeModel(GL_FLAT); glBegin(GL_QUADS); glColor4f(0.0, 0.0, 1.0, ALPHA); glVertex3fv(boxv0); glVertex3fv(boxv1); glVertex3fv(boxv2); glVertex3fv(boxv3); glColor4f(1.0, 1.0, 0.0, ALPHA); glVertex3fv(boxv0); glVertex3fv(boxv4); glVertex3fv(boxv5); glVertex3fv(boxv1); glColor4f(0.0, 1.0, 1.0, ALPHA); glVertex3fv(boxv2); glVertex3fv(boxv6); glVertex3fv(boxv7); glVertex3fv(boxv3); glColor4f(1.0, 0.0, 0.0, ALPHA); glVertex3fv(boxv4); glVertex3fv(boxv5); glVertex3fv(boxv6); glVertex3fv(boxv7); glColor4f(1.0, 0.0, 1.0, ALPHA); glVertex3fv(boxv0); glVertex3fv(boxv3); glVertex3fv(boxv7); glVertex3fv(boxv4); glColor4f(0.0, 1.0, 0.0, ALPHA); glVertex3fv(boxv1); glVertex3fv(boxv5); glVertex3fv(boxv6); glVertex3fv(boxv2); glEnd(); glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINES); glVertex3fv(boxv0); glVertex3fv(boxv1); glVertex3fv(boxv1); glVertex3fv(boxv2); glVertex3fv(boxv2); glVertex3fv(boxv3); glVertex3fv(boxv3); glVertex3fv(boxv0); glVertex3fv(boxv4); glVertex3fv(boxv5); glVertex3fv(boxv5); glVertex3fv(boxv6); glVertex3fv(boxv6); glVertex3fv(boxv7); glVertex3fv(boxv7); glVertex3fv(boxv4); glVertex3fv(boxv0); glVertex3fv(boxv4); glVertex3fv(boxv1); glVertex3fv(boxv5); glVertex3fv(boxv2); glVertex3fv(boxv6); glVertex3fv(boxv3); glVertex3fv(boxv7); glEnd(); } // drawCube void CubeView::draw() { if (!valid()) { glLoadIdentity(); glViewport(0, 0, pixel_w(), pixel_h()); glOrtho(-10, 10, -10, 10, -20050, 10000); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef((GLfloat)xshift, (GLfloat)yshift, 0); glRotatef((GLfloat)hAng, 0, 1, 0); glRotatef((GLfloat)vAng, 1, 0, 0); glScalef(float(size), float(size), float(size)); drawCube(); glPopMatrix(); } // [\endcode in documentation/src/fluid.dox] #endif /* HAVE_GL */ fltk-1.4.3/test/resize-arrows.h0000644000175000017500000000255215004135251016555 0ustar albrechtalbrecht// // Resize example for use in the Fast Light Tool Kit (FLTK) documentation. // // See Article #415: How does resizing work? // https://www.fltk.org/articles.php?L415 // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef RESIZE_ARROWS_H #define RESIZE_ARROWS_H #include #include /** Harrow is an Fl_Box with a horizontal arrow drawn across the middle. The arrow is drawn in black on a white background. By default, the box has no border, and the label is below the box. */ class Harrow : public Fl_Box { public: Harrow(int X, int Y, int W, int H, const char *T = 0); void draw() FL_OVERRIDE; }; /** Varrow is an Fl_Box with a vertical arrow drawn down the middle. The arrow is drawn in black on a white background. By default, the box has no border, and the label is to the right of the box. */ class Varrow : public Fl_Box { public: Varrow(int X, int Y, int W, int H, const char *T = 0); void draw() FL_OVERRIDE; }; #endif // RESIZE_ARROWS_H fltk-1.4.3/test/colbrowser.cxx0000644000175000017500000001455415004135251016502 0ustar albrechtalbrecht// // X Color Browser demo program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2019 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include // some constants #define MAX_RGB 3000 #define FL_FREE_COL4 ((Fl_Color)(FL_FREE_COLOR+3)) #define FL_INDIANRED ((Fl_Color)(164)) static Fl_Double_Window *cl; static Fl_Box *rescol; static Fl_Button *dbobj; static Fl_Hold_Browser *colbr; static Fl_Value_Slider *rs, *gs, *bs; static char dbname[FL_PATH_MAX]; static void create_form_cl(void); static int load_browser(const char *); typedef struct { int r, g, b; } RGBdb; static RGBdb rgbdb[MAX_RGB]; int main(int argc, char *argv[]) { int i; Fl::args_to_utf8(argc, argv); // for MSYS2/MinGW if (!Fl::args(argc, argv, i)) Fl::fatal(Fl::help); const char *dbname = (i < argc) ? argv[i] : "rgb.txt"; create_form_cl(); if (load_browser(dbname)) dbobj->label(dbname); else dbobj->label("None"); dbobj->redraw(); cl->size_range(cl->w(),cl->h(),2*cl->w(),2*cl->h()); cl->label("RGB Browser"); cl->free_position(); cl->show(argc,argv); return Fl::run(); } static void set_entry(int i) { RGBdb *db = rgbdb + i; Fl::set_color(FL_FREE_COL4, db->r, db->g, db->b); rs->value(db->r); gs->value(db->g); bs->value(db->b); rescol->redraw(); } static void br_cb(Fl_Widget *ob, long) { int r = ((Fl_Browser *)ob)->value(); if (r <= 0) return; set_entry(r - 1); } static int read_entry(FILE * fp, int *r, int *g, int *b, char *name) { int n; char buf[512], *p; if (!fgets(buf, sizeof(buf) - 1, fp)) return 0; if(buf[0] == '!') { if (fgets(buf,sizeof(buf)-1,fp)==0) { /* ignore */ } } if(sscanf(buf, " %d %d %d %n", r, g, b, &n) < 3) return 0; p = buf + n; /* squeeze out all spaces */ while (*p) { if (*p != ' ' && *p != '\n') *name++ = *p; p++; } *name = 0; return (feof(fp) || ferror(fp)) ? 0 : 1; } static int load_browser(const char *fname) { FILE *fp; RGBdb *db = rgbdb, *dbs = db + MAX_RGB; int r, g, b, lr = -1 , lg = -1, lb = -1; char name[256], buf[300]; if (!(fp = fl_fopen(fname, "r"))) { fl_alert("Load:\nCan't open '%s'", fname); return 0; } /* read the items */ for (; db < dbs && read_entry(fp, &r, &g, &b, name);) { db->r = r; db->g = g; db->b = b; /* unique the entries on the fly */ if (lr != r || lg != g || lb != b) { db++; lr = r; lg = g; lb = b; snprintf(buf, sizeof(buf), "(%3d %3d %3d) %s", r, g, b, name); colbr->add(buf); } } fclose(fp); if (db < dbs) db->r = 1000; /* sentinel */ else { db--; db->r = 1000; } colbr->topline(1); colbr->select(1,1); set_entry(0); return 1; } static int search_entry(int r, int g, int b) { RGBdb *db = rgbdb; int i, j, diffr, diffg, diffb; unsigned int diff, mindiff; mindiff = (unsigned int)~0; for (i = j = 0; db->r < 256; db++, i++) { diffr = r - db->r; diffg = g - db->g; diffb = b - db->b; #ifdef FL_LINEAR diff = unsigned(3.0 * (FL_abs(r - db->r)) + (5.9 * FL_abs(g - db->g)) + (1.1 * (FL_abs(b - db->b)))); #else diff = unsigned(3.0 * (diffr *diffr) + 5.9 * (diffg *diffg) + 1.1 * (diffb *diffb)); #endif if (mindiff > diff) { mindiff = diff; j = i; } } return j; } static void search_rgb(Fl_Widget *, long) { int r, g, b, i; int top = colbr->topline(); r = int(rs->value()); g = int(gs->value()); b = int(bs->value()); // fl_freeze_form(cl); Fl::set_color(FL_FREE_COL4, r, g, b); rescol->redraw(); i = search_entry(r, g, b); /* change topline only if necessary */ if(i < top || i > (top+15)) colbr->topline(i-8); colbr->select(i+1, 1); // fl_unfreeze_form(cl); } /* change database */ static void db_cb(Fl_Widget * ob, long) { const char *p = fl_input("Enter New Database Name", dbname); char buf[512]; if (!p || strcmp(p, dbname) == 0) return; strcpy(buf, p); if (load_browser(buf)) strcpy(dbname, buf); else ob->label(dbname); } static void done_cb(Fl_Widget *, long) { exit(0); } static void create_form_cl(void) { if (cl) return; cl = new Fl_Double_Window(400,385); cl->box(FL_UP_BOX); cl->color(FL_INDIANRED, FL_GRAY); Fl_Box *title = new Fl_Box(40, 10, 300, 30, "Color Browser"); title->box(FL_NO_BOX); title->labelcolor(FL_RED); title->labelsize(32); title->labelfont(FL_HELVETICA_BOLD); title->labeltype(FL_SHADOW_LABEL); dbobj = new Fl_Button(40, 50, 300, 25, ""); dbobj->type(FL_NORMAL_BUTTON); dbobj->box(FL_BORDER_BOX); dbobj->color(FL_INDIANRED,FL_INDIANRED); dbobj->callback(db_cb, 0); colbr = new Fl_Hold_Browser(10, 90, 280, 240, ""); colbr->textfont(FL_COURIER); colbr->callback(br_cb, 0); colbr->box(FL_DOWN_BOX); rescol = new Fl_Box(300, 90, 90, 35, ""); rescol->color(FL_FREE_COL4, FL_FREE_COL4); rescol->box(FL_BORDER_BOX); rs = new Fl_Value_Slider(300, 130, 30, 200, ""); rs->type(FL_VERT_FILL_SLIDER); rs->color(FL_INDIANRED, FL_RED); rs->bounds(0, 255); rs->precision(0); rs->callback(search_rgb, 0); rs->when(FL_WHEN_RELEASE); gs = new Fl_Value_Slider(330, 130, 30, 200, ""); gs->type(FL_VERT_FILL_SLIDER); gs->color(FL_INDIANRED, FL_GREEN); gs->bounds(0, 255); gs->precision(0); gs->callback(search_rgb, 1); gs->when(FL_WHEN_RELEASE); bs = new Fl_Value_Slider(360, 130, 30, 200, ""); bs->type(FL_VERT_FILL_SLIDER); bs->color(FL_INDIANRED, FL_BLUE); bs->bounds(0, 255); bs->precision(0); bs->callback(search_rgb, 2); bs->when(FL_WHEN_RELEASE); Fl_Button *done = new Fl_Button(160, 345, 80, 30, "Done"); done->type(FL_NORMAL_BUTTON); done->callback(done_cb, 0); cl->end(); cl->resizable(cl); } fltk-1.4.3/test/overlay.cxx0000644000175000017500000000371315004135251015775 0ustar albrechtalbrecht// // Overlay window test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include int width=10,height=10; class overlay : public Fl_Overlay_Window { public: overlay(int w,int h) : Fl_Overlay_Window(w,h) {} void draw_overlay() FL_OVERRIDE; }; void overlay::draw_overlay() { fl_color(FL_RED); fl_rect((w()-width)/2,(h()-height)/2,width,height); } overlay *ovl; void bcb1(Fl_Widget *,void *) {width+=20; ovl->redraw_overlay();} void bcb2(Fl_Widget *,void *) {width-=20; ovl->redraw_overlay();} void bcb3(Fl_Widget *,void *) {height+=20; ovl->redraw_overlay();} void bcb4(Fl_Widget *,void *) {height-=20; ovl->redraw_overlay();} int arg(int, char **argv, int& i) { Fl_Color n = (Fl_Color)atoi(argv[i]); if (n<=0) return 0; i++; uchar r,g,b; Fl::get_color(n,r,g,b); Fl::set_color(FL_RED,r,g,b); return i; } int main(int argc, char **argv) { int i=0; Fl::args(argc,argv,i,arg); ovl = new overlay(400,400); Fl_Button *b; b = new Fl_Button(50,50,100,100,"wider\n(a)"); b->callback(bcb1); b->shortcut('a'); b = new Fl_Button(250,50,100,100,"narrower\n(b)"); b->callback(bcb2); b->shortcut('b'); b = new Fl_Button(50,250,100,100,"taller\n(c)"); b->callback(bcb3); b->shortcut('c'); b = new Fl_Button(250,250,100,100,"shorter\n(d)"); b->callback(bcb4); b->shortcut('d'); ovl->resizable(ovl); ovl->end(); ovl->show(argc,argv); ovl->redraw_overlay(); return Fl::run(); } fltk-1.4.3/test/output.cxx0000644000175000017500000000456015004135251015655 0ustar albrechtalbrecht// // Output test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include // necessary for bug in mingw32? #include #include #include #include #include #include #include #include Fl_Output *text; Fl_Multiline_Output *text2; Fl_Input *input; Fl_Value_Slider *fonts; Fl_Value_Slider *sizes; Fl_Double_Window *window; void font_cb(Fl_Widget *,void *) { text->textfont(int(fonts->value())); text->redraw(); text2->textfont(int(fonts->value())); text2->redraw(); } void size_cb(Fl_Widget *,void *) { text->textsize(int(sizes->value())); text->redraw(); text2->textsize(int(sizes->value())); text2->redraw(); } void input_cb(Fl_Widget *,void *) { text->value(input->value()); text2->value(input->value()); } int main(int argc, char **argv) { window = new Fl_Double_Window(400,400); input = new Fl_Input(50,375,350,25); input->static_value("The quick brown fox\njumped over\nthe lazy dog."); input->when(FL_WHEN_CHANGED); input->callback(input_cb); sizes = new Fl_Hor_Value_Slider(50,350,350,25,"Size"); sizes->align(FL_ALIGN_LEFT); sizes->bounds(1,64); sizes->step(1); sizes->value(14); sizes->callback(size_cb); fonts = new Fl_Hor_Value_Slider(50,325,350,25,"Font"); fonts->align(FL_ALIGN_LEFT); fonts->bounds(0,15); fonts->step(1); fonts->value(0); fonts->callback(font_cb); text2 = new Fl_Multiline_Output(100,150,200,100,"Fl_Multiline_Output"); text2->value(input->value()); text2->align(FL_ALIGN_BOTTOM); text2->tooltip("This is an Fl_Multiline_Output widget."); window->resizable(text2); text = new Fl_Output(100,90,200,30,"Fl_Output"); text->value(input->value()); text->align(FL_ALIGN_BOTTOM); text->tooltip("This is an Fl_Output widget."); window->end(); window->show(argc,argv); return Fl::run(); } fltk-1.4.3/test/cairo_test.cxx0000644000175000017500000001654715004135251016461 0ustar albrechtalbrecht// // Cairo drawing test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include // includes #ifdef FLTK_HAVE_CAIRO // defined in since FLTK 1.4.0 #include #include #include #include #include #define DEF_WIDTH 0.03 // This demo program can be used in 3 modes. All 3 modes require configure // option --enable-cairo or CMake FLTK_OPTION_CAIRO_WINDOW. // // 1) using class Fl_Cairo_Window useful when all the content of a window // is drawn with Cairo. // This is achieved setting #define USE_FL_CAIRO_WINDOW 1 below // or // 2) showing how to draw in an Fl_Double_Window using both Cairo and // the FLTK drawing API. // This is achieved setting #define USE_FL_CAIRO_WINDOW 0 below // or // 3) showing how to use "cairo extended use". // This is achieved when FLTK was built with one more option // (configure --enable-cairoext or CMake FLTK_OPTION_CAIRO_EXT) // which defines the preprocessor variable FLTK_HAVE_CAIROEXT. // If Fl::cairo_autolink_context(true); is called at the beginning // of main(), any overridden draw() function gets access to an adequate // Cairo context with Fl::cairo_cc() without having to call // Fl::cairo_make_current(Fl_Window*). #define USE_FL_CAIRO_WINDOW 1 // draw centered text static void centered_text(cairo_t *cr, double x0, double y0, double w0, double h0, const char *my_text) { cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_OBLIQUE, CAIRO_FONT_WEIGHT_BOLD); cairo_set_source_rgba(cr, 0.9, 0.9, 0.4, 0.6); cairo_text_extents_t extents; cairo_text_extents(cr, my_text, &extents); double x = (extents.width / 2 + extents.x_bearing); double y = (extents.height / 2 + extents.y_bearing); cairo_move_to(cr, x0 + w0 / 2 - x, y0 + h0 / 2 - y); cairo_text_path(cr, my_text); cairo_fill_preserve(cr); cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_set_line_width(cr, 0.004); cairo_stroke(cr); cairo_set_line_width(cr, DEF_WIDTH); } // draw a button object with rounded corners and a label static void round_button(cairo_t *cr, double x0, double y0, double rect_width, double rect_height, double radius, double r, double g, double b) { double x1, y1; x1 = x0 + rect_width; y1 = y0 + rect_height; if (!rect_width || !rect_height) return; if (rect_width / 2 < radius) { if (rect_height / 2 < radius) { cairo_move_to(cr, x0, (y0 + y1) / 2); cairo_curve_to(cr, x0, y0, x0, y0, (x0 + x1) / 2, y0); cairo_curve_to(cr, x1, y0, x1, y0, x1, (y0 + y1) / 2); cairo_curve_to(cr, x1, y1, x1, y1, (x1 + x0) / 2, y1); cairo_curve_to(cr, x0, y1, x0, y1, x0, (y0 + y1) / 2); } else { cairo_move_to(cr, x0, y0 + radius); cairo_curve_to(cr, x0, y0, x0, y0, (x0 + x1) / 2, y0); cairo_curve_to(cr, x1, y0, x1, y0, x1, y0 + radius); cairo_line_to(cr, x1, y1 - radius); cairo_curve_to(cr, x1, y1, x1, y1, (x1 + x0) / 2, y1); cairo_curve_to(cr, x0, y1, x0, y1, x0, y1 - radius); } } else { if (rect_height / 2 < radius) { cairo_move_to(cr, x0, (y0 + y1) / 2); cairo_curve_to(cr, x0, y0, x0, y0, x0 + radius, y0); cairo_line_to(cr, x1 - radius, y0); cairo_curve_to(cr, x1, y0, x1, y0, x1, (y0 + y1) / 2); cairo_curve_to(cr, x1, y1, x1, y1, x1 - radius, y1); cairo_line_to(cr, x0 + radius, y1); cairo_curve_to(cr, x0, y1, x0, y1, x0, (y0 + y1) / 2); } else { cairo_move_to(cr, x0, y0 + radius); cairo_curve_to(cr, x0, y0, x0, y0, x0 + radius, y0); cairo_line_to(cr, x1 - radius, y0); cairo_curve_to(cr, x1, y0, x1, y0, x1, y0 + radius); cairo_line_to(cr, x1, y1 - radius); cairo_curve_to(cr, x1, y1, x1, y1, x1 - radius, y1); cairo_line_to(cr, x0 + radius, y1); cairo_curve_to(cr, x0, y1, x0, y1, x0, y1 - radius); } } cairo_close_path(cr); cairo_pattern_t *pat = // cairo_pattern_create_linear (0.0, 0.0, 0.0, 1.0); cairo_pattern_create_radial(0.25, 0.24, 0.11, 0.24, 0.14, 0.35); cairo_pattern_set_extend(pat, CAIRO_EXTEND_REFLECT); cairo_pattern_add_color_stop_rgba(pat, 1.0, r, g, b, 1); cairo_pattern_add_color_stop_rgba(pat, 0.0, 1, 1, 1, 1); cairo_set_source(cr, pat); cairo_fill_preserve(cr); cairo_pattern_destroy(pat); // cairo_set_source_rgb (cr, 0.5, 0.5, 1); cairo_fill_preserve (cr); cairo_set_source_rgba(cr, 0, 0, 0.5, 0.3); cairo_stroke(cr); cairo_set_font_size(cr, 0.075); centered_text(cr, x0, y0, rect_width, rect_height, "FLTK loves Cairo!"); } // draw the entire image (3 buttons), scaled to the given width and height void draw_image(cairo_t *cr, int w, int h) { cairo_set_line_width(cr, DEF_WIDTH); cairo_scale(cr, w, h); round_button(cr, 0.1, 0.1, 0.8, 0.2, 0.4, 1, 0, 0); round_button(cr, 0.1, 0.4, 0.8, 0.2, 0.4, 0, 1, 0); round_button(cr, 0.1, 0.7, 0.8, 0.2, 0.4, 0, 0, 1); } // draw_image() #if USE_FL_CAIRO_WINDOW && !defined(FLTK_HAVE_CAIROEXT) typedef Fl_Cairo_Window cairo_using_window; #else // !USE_FL_CAIRO_WINDOW || defined(FLTK_HAVE_CAIROEXT) class cairo_using_window : public Fl_Double_Window { void (*draw_with_cairo_)(cairo_using_window*, cairo_t*); public: cairo_using_window(int w, int h, const char *title) : Fl_Double_Window(w, h, title) { Fl_Box *box = new Fl_Box(FL_NO_BOX, 0, 0, w, 25, "Cairo and FLTK API in Fl_Double_Window"); box->labelfont(FL_TIMES_BOLD); box->labelsize(12); box->labelcolor(FL_BLUE); } void draw() FL_OVERRIDE { Fl_Window::draw(); // perform drawings with the FLTK API #ifndef FLTK_HAVE_CAIROEXT Fl::cairo_make_current(this); // announce Cairo will be used in this window #endif cairo_t *cc = Fl::cairo_cc(); // get the adequate Cairo context draw_with_cairo_(this, cc); // draw in this window using Cairo // flush Cairo drawings: necessary at least for Windows Fl::cairo_flush(cc); } void set_draw_cb( void (*cb)(cairo_using_window*, cairo_t*)) { draw_with_cairo_ = cb; } }; #endif // USE_FL_CAIRO_WINDOW // Cairo rendering cb called during Fl_Cairo_Window::draw() // or cairo_using_window::draw(). static void my_cairo_draw_cb(cairo_using_window *window, cairo_t *cr) { draw_image(cr, window->w(), window->h()); } int main(int argc, char **argv) { #ifdef FLTK_HAVE_CAIROEXT Fl::cairo_autolink_context(true); #endif cairo_using_window window(350, 350, "FLTK loves Cairo"); window.resizable(&window); window.color(FL_WHITE); window.set_draw_cb(my_cairo_draw_cb); window.show(argc, argv); return Fl::run(); } #else // (!FLTK_HAVE_CAIRO) #include int main(int argc, char **argv) { fl_message_title("This program needs a Cairo enabled FLTK library"); fl_message( "Please configure FLTK with Cairo enabled (--enable-cairo or --enable-cairoext)\n" "or one of the CMake options FLTK_OPTION_CAIRO_WINDOW or FLTK_OPTION_CAIRO_EXT, respectively."); return 0; } #endif // (FLTK_HAVE_CAIRO) fltk-1.4.3/test/makedepend0000644000175000017500000031330715004135251015613 0ustar albrechtalbrecht# DO NOT DELETE THIS LINE -- make depend depends on it. adjuster.o: ../FL/Enumerations.H adjuster.o: ../FL/Fl.H adjuster.o: ../FL/Fl_Adjuster.H adjuster.o: ../FL/fl_attr.h adjuster.o: ../FL/Fl_Bitmap.H adjuster.o: ../FL/Fl_Box.H adjuster.o: ../FL/Fl_Cairo.H adjuster.o: ../FL/fl_casts.H adjuster.o: ../FL/fl_config.h adjuster.o: ../FL/Fl_Double_Window.H adjuster.o: ../FL/Fl_Export.H adjuster.o: ../FL/Fl_Group.H adjuster.o: ../FL/Fl_Image.H adjuster.o: ../FL/fl_types.h adjuster.o: ../FL/fl_utf8.h adjuster.o: ../FL/Fl_Valuator.H adjuster.o: ../FL/Fl_Widget.H adjuster.o: ../FL/Fl_Window.H adjuster.o: ../FL/platform_types.h animated.o: ../FL/Enumerations.H animated.o: ../FL/Fl.H animated.o: ../FL/fl_attr.h animated.o: ../FL/Fl_Bitmap.H animated.o: ../FL/Fl_Button.H animated.o: ../FL/Fl_Cairo.H animated.o: ../FL/fl_casts.H animated.o: ../FL/fl_config.h animated.o: ../FL/Fl_Device.H animated.o: ../FL/Fl_Double_Window.H animated.o: ../FL/fl_draw.H animated.o: ../FL/Fl_Export.H animated.o: ../FL/Fl_Graphics_Driver.H animated.o: ../FL/Fl_Group.H animated.o: ../FL/Fl_Image.H animated.o: ../FL/Fl_Pixmap.H animated.o: ../FL/Fl_Plugin.H animated.o: ../FL/Fl_Preferences.H animated.o: ../FL/Fl_Rect.H animated.o: ../FL/Fl_RGB_Image.H animated.o: ../FL/fl_types.h animated.o: ../FL/fl_utf8.h animated.o: ../FL/Fl_Widget.H animated.o: ../FL/Fl_Window.H animated.o: ../FL/platform.H animated.o: ../FL/platform_types.h animated.o: ../FL/x11.H arc.o: ../FL/Enumerations.H arc.o: ../FL/Fl.H arc.o: ../FL/fl_attr.h arc.o: ../FL/Fl_Bitmap.H arc.o: ../FL/Fl_Cairo.H arc.o: ../FL/fl_casts.H arc.o: ../FL/fl_config.h arc.o: ../FL/Fl_Device.H arc.o: ../FL/Fl_Double_Window.H arc.o: ../FL/fl_draw.H arc.o: ../FL/Fl_Export.H arc.o: ../FL/Fl_Graphics_Driver.H arc.o: ../FL/Fl_Group.H arc.o: ../FL/Fl_Hor_Value_Slider.H arc.o: ../FL/Fl_Image.H arc.o: ../FL/Fl_Pixmap.H arc.o: ../FL/Fl_Plugin.H arc.o: ../FL/Fl_Preferences.H arc.o: ../FL/Fl_Rect.H arc.o: ../FL/Fl_RGB_Image.H arc.o: ../FL/Fl_Slider.H arc.o: ../FL/fl_types.h arc.o: ../FL/fl_utf8.h arc.o: ../FL/Fl_Valuator.H arc.o: ../FL/Fl_Value_Slider.H arc.o: ../FL/Fl_Widget.H arc.o: ../FL/Fl_Window.H arc.o: ../FL/platform_types.h ask.o: ../FL/Enumerations.H ask.o: ../FL/Fl.H ask.o: ../FL/fl_ask.H ask.o: ../FL/fl_attr.h ask.o: ../FL/Fl_Bitmap.H ask.o: ../FL/Fl_Box.H ask.o: ../FL/Fl_Button.H ask.o: ../FL/Fl_Cairo.H ask.o: ../FL/fl_casts.H ask.o: ../FL/fl_config.h ask.o: ../FL/Fl_Double_Window.H ask.o: ../FL/Fl_Export.H ask.o: ../FL/Fl_Group.H ask.o: ../FL/Fl_Image.H ask.o: ../FL/Fl_Input.H ask.o: ../FL/Fl_Input_.H ask.o: ../FL/Fl_Return_Button.H ask.o: ../FL/fl_types.h ask.o: ../FL/fl_utf8.h ask.o: ../FL/Fl_Widget.H ask.o: ../FL/Fl_Window.H ask.o: ../FL/platform_types.h bitmap.o: ../FL/Enumerations.H bitmap.o: ../FL/Fl.H bitmap.o: ../FL/fl_attr.h bitmap.o: ../FL/Fl_Bitmap.H bitmap.o: ../FL/Fl_Button.H bitmap.o: ../FL/Fl_Cairo.H bitmap.o: ../FL/fl_casts.H bitmap.o: ../FL/fl_config.h bitmap.o: ../FL/Fl_Double_Window.H bitmap.o: ../FL/Fl_Export.H bitmap.o: ../FL/Fl_Group.H bitmap.o: ../FL/Fl_Image.H bitmap.o: ../FL/Fl_Toggle_Button.H bitmap.o: ../FL/fl_types.h bitmap.o: ../FL/fl_utf8.h bitmap.o: ../FL/Fl_Widget.H bitmap.o: ../FL/Fl_Window.H bitmap.o: ../FL/platform_types.h bitmap.o: pixmaps/sorceress.xbm blocks.o: ../config.h blocks.o: ../FL/Enumerations.H blocks.o: ../FL/Fl.H blocks.o: ../FL/fl_attr.h blocks.o: ../FL/Fl_Bitmap.H blocks.o: ../FL/Fl_Button.H blocks.o: ../FL/Fl_Cairo.H blocks.o: ../FL/fl_casts.H blocks.o: ../FL/fl_config.h blocks.o: ../FL/Fl_Device.H blocks.o: ../FL/Fl_Double_Window.H blocks.o: ../FL/fl_draw.H blocks.o: ../FL/Fl_Export.H blocks.o: ../FL/Fl_Graphics_Driver.H blocks.o: ../FL/Fl_Group.H blocks.o: ../FL/Fl_Image.H blocks.o: ../FL/Fl_Pixmap.H blocks.o: ../FL/Fl_Plugin.H blocks.o: ../FL/Fl_Preferences.H blocks.o: ../FL/Fl_Rect.H blocks.o: ../FL/Fl_RGB_Image.H blocks.o: ../FL/Fl_Tiled_Image.H blocks.o: ../FL/fl_types.h blocks.o: ../FL/fl_utf8.h blocks.o: ../FL/Fl_Widget.H blocks.o: ../FL/Fl_Window.H blocks.o: ../FL/Fl_XBM_Image.H blocks.o: ../FL/Fl_XPM_Image.H blocks.o: ../FL/platform.H blocks.o: ../FL/platform_types.h blocks.o: ../FL/x11.H blocks.o: pixmaps/blast.xpm blocks.o: pixmaps/blue.xpm blocks.o: pixmaps/blue_bomb.xpm blocks.o: pixmaps/cyan.xpm blocks.o: pixmaps/cyan_bomb.xpm blocks.o: pixmaps/gray.xpm blocks.o: pixmaps/gray_bomb.xpm blocks.o: pixmaps/green.xpm blocks.o: pixmaps/green_bomb.xpm blocks.o: pixmaps/magenta.xpm blocks.o: pixmaps/magenta_bomb.xpm blocks.o: pixmaps/red.xpm blocks.o: pixmaps/red_bomb.xpm blocks.o: pixmaps/yellow.xpm blocks.o: pixmaps/yellow_bomb.xpm boxtype.o: ../FL/Enumerations.H boxtype.o: ../FL/Fl.H boxtype.o: ../FL/fl_attr.h boxtype.o: ../FL/Fl_Bitmap.H boxtype.o: ../FL/Fl_Button.H boxtype.o: ../FL/Fl_Cairo.H boxtype.o: ../FL/fl_casts.H boxtype.o: ../FL/Fl_Choice.H boxtype.o: ../FL/fl_config.h boxtype.o: ../FL/Fl_Device.H boxtype.o: ../FL/Fl_Double_Window.H boxtype.o: ../FL/fl_draw.H boxtype.o: ../FL/Fl_Export.H boxtype.o: ../FL/Fl_Graphics_Driver.H boxtype.o: ../FL/Fl_Group.H boxtype.o: ../FL/Fl_Image.H boxtype.o: ../FL/Fl_Menu_.H boxtype.o: ../FL/Fl_Menu_Item.H boxtype.o: ../FL/Fl_Multi_Label.H boxtype.o: ../FL/Fl_Pixmap.H boxtype.o: ../FL/Fl_Plugin.H boxtype.o: ../FL/Fl_Preferences.H boxtype.o: ../FL/Fl_Rect.H boxtype.o: ../FL/Fl_RGB_Image.H boxtype.o: ../FL/Fl_Scheme.H boxtype.o: ../FL/Fl_Scheme_Choice.H boxtype.o: ../FL/fl_types.h boxtype.o: ../FL/fl_utf8.h boxtype.o: ../FL/Fl_Widget.H boxtype.o: ../FL/Fl_Window.H boxtype.o: ../FL/platform_types.h browser.o: ../FL/Enumerations.H browser.o: ../FL/Fl.H browser.o: ../FL/fl_ask.H browser.o: ../FL/fl_attr.h browser.o: ../FL/Fl_Bitmap.H browser.o: ../FL/Fl_Browser.H browser.o: ../FL/Fl_Browser_.H browser.o: ../FL/Fl_Button.H browser.o: ../FL/Fl_Cairo.H browser.o: ../FL/fl_casts.H browser.o: ../FL/Fl_Choice.H browser.o: ../FL/fl_config.h browser.o: ../FL/Fl_Double_Window.H browser.o: ../FL/Fl_Export.H browser.o: ../FL/Fl_Group.H browser.o: ../FL/Fl_Image.H browser.o: ../FL/Fl_Input.H browser.o: ../FL/Fl_Input_.H browser.o: ../FL/Fl_Int_Input.H browser.o: ../FL/Fl_Menu_.H browser.o: ../FL/Fl_Menu_Item.H browser.o: ../FL/Fl_Multi_Label.H browser.o: ../FL/Fl_Rect.H browser.o: ../FL/Fl_Scrollbar.H browser.o: ../FL/Fl_Select_Browser.H browser.o: ../FL/Fl_Slider.H browser.o: ../FL/Fl_Terminal.H browser.o: ../FL/fl_types.h browser.o: ../FL/fl_utf8.h browser.o: ../FL/Fl_Valuator.H browser.o: ../FL/Fl_Widget.H browser.o: ../FL/Fl_Window.H browser.o: ../FL/platform_types.h button.o: ../FL/Enumerations.H button.o: ../FL/Fl.H button.o: ../FL/fl_ask.H button.o: ../FL/fl_attr.h button.o: ../FL/Fl_Button.H button.o: ../FL/Fl_Cairo.H button.o: ../FL/fl_casts.H button.o: ../FL/fl_config.h button.o: ../FL/Fl_Export.H button.o: ../FL/fl_types.h button.o: ../FL/fl_utf8.h button.o: ../FL/Fl_Window.H button.o: ../FL/platform_types.h buttons.o: ../FL/Enumerations.H buttons.o: ../FL/Fl.H buttons.o: ../FL/fl_attr.h buttons.o: ../FL/Fl_Button.H buttons.o: ../FL/Fl_Cairo.H buttons.o: ../FL/fl_casts.H buttons.o: ../FL/Fl_Check_Button.H buttons.o: ../FL/Fl_Choice.H buttons.o: ../FL/fl_config.h buttons.o: ../FL/Fl_Export.H buttons.o: ../FL/Fl_Image.H buttons.o: ../FL/Fl_Light_Button.H buttons.o: ../FL/Fl_Menu_.H buttons.o: ../FL/Fl_Menu_Item.H buttons.o: ../FL/Fl_Multi_Label.H buttons.o: ../FL/Fl_Repeat_Button.H buttons.o: ../FL/Fl_Return_Button.H buttons.o: ../FL/Fl_Round_Button.H buttons.o: ../FL/Fl_Scheme.H buttons.o: ../FL/Fl_Scheme_Choice.H buttons.o: ../FL/fl_types.h buttons.o: ../FL/fl_utf8.h buttons.o: ../FL/Fl_Widget.H buttons.o: ../FL/Fl_Window.H buttons.o: ../FL/platform_types.h cairo_test.o: ../FL/Enumerations.H cairo_test.o: ../FL/Fl.H cairo_test.o: ../FL/fl_attr.h cairo_test.o: ../FL/Fl_Bitmap.H cairo_test.o: ../FL/Fl_Box.H cairo_test.o: ../FL/Fl_Cairo.H cairo_test.o: ../FL/Fl_Cairo_Window.H cairo_test.o: ../FL/fl_casts.H cairo_test.o: ../FL/fl_config.h cairo_test.o: ../FL/Fl_Device.H cairo_test.o: ../FL/Fl_Double_Window.H cairo_test.o: ../FL/fl_draw.H cairo_test.o: ../FL/Fl_Export.H cairo_test.o: ../FL/Fl_Graphics_Driver.H cairo_test.o: ../FL/Fl_Group.H cairo_test.o: ../FL/Fl_Image.H cairo_test.o: ../FL/Fl_Pixmap.H cairo_test.o: ../FL/Fl_Plugin.H cairo_test.o: ../FL/Fl_Preferences.H cairo_test.o: ../FL/Fl_Rect.H cairo_test.o: ../FL/Fl_RGB_Image.H cairo_test.o: ../FL/fl_types.h cairo_test.o: ../FL/fl_utf8.h cairo_test.o: ../FL/Fl_Widget.H cairo_test.o: ../FL/Fl_Window.H cairo_test.o: ../FL/math.h cairo_test.o: ../FL/platform.H cairo_test.o: ../FL/platform_types.h cairo_test.o: ../FL/x11.H checkers.o: ../FL/Enumerations.H checkers.o: ../FL/Fl.H checkers.o: ../FL/fl_ask.H checkers.o: ../FL/fl_attr.h checkers.o: ../FL/Fl_Bitmap.H checkers.o: ../FL/Fl_Box.H checkers.o: ../FL/Fl_Cairo.H checkers.o: ../FL/fl_casts.H checkers.o: ../FL/fl_config.h checkers.o: ../FL/Fl_Device.H checkers.o: ../FL/Fl_Double_Window.H checkers.o: ../FL/fl_draw.H checkers.o: ../FL/Fl_Export.H checkers.o: ../FL/Fl_Graphics_Driver.H checkers.o: ../FL/Fl_Group.H checkers.o: ../FL/Fl_Image.H checkers.o: ../FL/Fl_Menu_Item.H checkers.o: ../FL/Fl_Multi_Label.H checkers.o: ../FL/Fl_Pixmap.H checkers.o: ../FL/Fl_Plugin.H checkers.o: ../FL/Fl_PNG_Image.H checkers.o: ../FL/Fl_Preferences.H checkers.o: ../FL/Fl_Rect.H checkers.o: ../FL/Fl_RGB_Image.H checkers.o: ../FL/Fl_Slider.H checkers.o: ../FL/fl_types.h checkers.o: ../FL/fl_utf8.h checkers.o: ../FL/Fl_Valuator.H checkers.o: ../FL/Fl_Value_Output.H checkers.o: ../FL/Fl_Widget.H checkers.o: ../FL/Fl_Window.H checkers.o: ../FL/platform_types.h checkers.o: checkers_pieces.h clipboard.o: ../FL/Enumerations.H clipboard.o: ../FL/filename.H clipboard.o: ../FL/Fl.H clipboard.o: ../FL/fl_ask.H clipboard.o: ../FL/fl_attr.h clipboard.o: ../FL/Fl_Bitmap.H clipboard.o: ../FL/Fl_Box.H clipboard.o: ../FL/Fl_Browser.H clipboard.o: ../FL/Fl_Browser_.H clipboard.o: ../FL/Fl_Button.H clipboard.o: ../FL/Fl_Cairo.H clipboard.o: ../FL/fl_casts.H clipboard.o: ../FL/Fl_Check_Button.H clipboard.o: ../FL/Fl_Choice.H clipboard.o: ../FL/fl_config.h clipboard.o: ../FL/Fl_Device.H clipboard.o: ../FL/Fl_Double_Window.H clipboard.o: ../FL/fl_draw.H clipboard.o: ../FL/Fl_Export.H clipboard.o: ../FL/Fl_File_Browser.H clipboard.o: ../FL/Fl_File_Chooser.H clipboard.o: ../FL/Fl_File_Icon.H clipboard.o: ../FL/Fl_File_Input.H clipboard.o: ../FL/Fl_Graphics_Driver.H clipboard.o: ../FL/Fl_Group.H clipboard.o: ../FL/Fl_Image.H clipboard.o: ../FL/Fl_Input.H clipboard.o: ../FL/Fl_Input_.H clipboard.o: ../FL/Fl_Light_Button.H clipboard.o: ../FL/Fl_Menu_.H clipboard.o: ../FL/Fl_Menu_Button.H clipboard.o: ../FL/Fl_Menu_Item.H clipboard.o: ../FL/Fl_Multi_Label.H clipboard.o: ../FL/Fl_Native_File_Chooser.H clipboard.o: ../FL/Fl_Pixmap.H clipboard.o: ../FL/Fl_Plugin.H clipboard.o: ../FL/Fl_PNG_Image.H clipboard.o: ../FL/Fl_Preferences.H clipboard.o: ../FL/Fl_Rect.H clipboard.o: ../FL/Fl_Return_Button.H clipboard.o: ../FL/Fl_RGB_Image.H clipboard.o: ../FL/Fl_Scrollbar.H clipboard.o: ../FL/Fl_Shared_Image.H clipboard.o: ../FL/Fl_Slider.H clipboard.o: ../FL/Fl_Tabs.H clipboard.o: ../FL/Fl_Text_Buffer.H clipboard.o: ../FL/Fl_Text_Display.H clipboard.o: ../FL/Fl_Tile.H clipboard.o: ../FL/fl_types.h clipboard.o: ../FL/fl_utf8.h clipboard.o: ../FL/Fl_Valuator.H clipboard.o: ../FL/Fl_Widget.H clipboard.o: ../FL/Fl_Window.H clipboard.o: ../FL/platform_types.h clock.o: ../FL/Enumerations.H clock.o: ../FL/Fl.H clock.o: ../FL/fl_attr.h clock.o: ../FL/Fl_Bitmap.H clock.o: ../FL/Fl_Cairo.H clock.o: ../FL/fl_casts.H clock.o: ../FL/Fl_Clock.H clock.o: ../FL/fl_config.h clock.o: ../FL/Fl_Double_Window.H clock.o: ../FL/Fl_Export.H clock.o: ../FL/Fl_Group.H clock.o: ../FL/Fl_Image.H clock.o: ../FL/Fl_Round_Clock.H clock.o: ../FL/fl_types.h clock.o: ../FL/fl_utf8.h clock.o: ../FL/Fl_Widget.H clock.o: ../FL/Fl_Window.H clock.o: ../FL/platform_types.h colbrowser.o: ../FL/Enumerations.H colbrowser.o: ../FL/filename.H colbrowser.o: ../FL/Fl.H colbrowser.o: ../FL/fl_ask.H colbrowser.o: ../FL/fl_attr.h colbrowser.o: ../FL/Fl_Bitmap.H colbrowser.o: ../FL/Fl_Box.H colbrowser.o: ../FL/Fl_Browser.H colbrowser.o: ../FL/Fl_Browser_.H colbrowser.o: ../FL/Fl_Button.H colbrowser.o: ../FL/Fl_Cairo.H colbrowser.o: ../FL/fl_casts.H colbrowser.o: ../FL/fl_config.h colbrowser.o: ../FL/Fl_Double_Window.H colbrowser.o: ../FL/Fl_Export.H colbrowser.o: ../FL/Fl_Group.H colbrowser.o: ../FL/Fl_Hold_Browser.H colbrowser.o: ../FL/Fl_Image.H colbrowser.o: ../FL/Fl_Scrollbar.H colbrowser.o: ../FL/Fl_Slider.H colbrowser.o: ../FL/fl_types.h colbrowser.o: ../FL/fl_utf8.h colbrowser.o: ../FL/Fl_Valuator.H colbrowser.o: ../FL/Fl_Value_Slider.H colbrowser.o: ../FL/Fl_Widget.H colbrowser.o: ../FL/Fl_Window.H colbrowser.o: ../FL/platform_types.h color_chooser.o: ../config.h color_chooser.o: ../FL/Enumerations.H color_chooser.o: ../FL/Fl.H color_chooser.o: ../FL/fl_attr.h color_chooser.o: ../FL/Fl_Bitmap.H color_chooser.o: ../FL/Fl_Box.H color_chooser.o: ../FL/Fl_Button.H color_chooser.o: ../FL/Fl_Cairo.H color_chooser.o: ../FL/fl_casts.H color_chooser.o: ../FL/Fl_Choice.H color_chooser.o: ../FL/Fl_Color_Chooser.H color_chooser.o: ../FL/fl_config.h color_chooser.o: ../FL/Fl_Device.H color_chooser.o: ../FL/fl_draw.H color_chooser.o: ../FL/Fl_Export.H color_chooser.o: ../FL/Fl_Graphics_Driver.H color_chooser.o: ../FL/Fl_Group.H color_chooser.o: ../FL/Fl_Image.H color_chooser.o: ../FL/Fl_Input.H color_chooser.o: ../FL/Fl_Input_.H color_chooser.o: ../FL/Fl_Menu_.H color_chooser.o: ../FL/Fl_Menu_Item.H color_chooser.o: ../FL/Fl_Multi_Label.H color_chooser.o: ../FL/Fl_Pixmap.H color_chooser.o: ../FL/Fl_Plugin.H color_chooser.o: ../FL/Fl_Preferences.H color_chooser.o: ../FL/Fl_Rect.H color_chooser.o: ../FL/Fl_Return_Button.H color_chooser.o: ../FL/Fl_RGB_Image.H color_chooser.o: ../FL/fl_show_colormap.H color_chooser.o: ../FL/fl_types.h color_chooser.o: ../FL/fl_utf8.h color_chooser.o: ../FL/Fl_Valuator.H color_chooser.o: ../FL/Fl_Value_Input.H color_chooser.o: ../FL/Fl_Widget.H color_chooser.o: ../FL/Fl_Window.H color_chooser.o: ../FL/platform.H color_chooser.o: ../FL/platform_types.h color_chooser.o: ../FL/x11.H color_chooser.o: list_visuals.cxx contrast.o: ../FL/Enumerations.H contrast.o: ../FL/Fl.H contrast.o: ../FL/fl_attr.h contrast.o: ../FL/Fl_Bitmap.H contrast.o: ../FL/Fl_Box.H contrast.o: ../FL/Fl_Button.H contrast.o: ../FL/Fl_Cairo.H contrast.o: ../FL/fl_casts.H contrast.o: ../FL/Fl_Choice.H contrast.o: ../FL/Fl_Color_Chooser.H contrast.o: ../FL/fl_config.h contrast.o: ../FL/Fl_Device.H contrast.o: ../FL/Fl_Double_Window.H contrast.o: ../FL/fl_draw.H contrast.o: ../FL/Fl_Export.H contrast.o: ../FL/Fl_Graphics_Driver.H contrast.o: ../FL/Fl_Group.H contrast.o: ../FL/Fl_Hor_Value_Slider.H contrast.o: ../FL/Fl_Image.H contrast.o: ../FL/Fl_Input.H contrast.o: ../FL/Fl_Input_.H contrast.o: ../FL/Fl_Light_Button.H contrast.o: ../FL/Fl_Menu_.H contrast.o: ../FL/Fl_Menu_Item.H contrast.o: ../FL/Fl_Multi_Label.H contrast.o: ../FL/Fl_Output.H contrast.o: ../FL/Fl_Pixmap.H contrast.o: ../FL/Fl_Plugin.H contrast.o: ../FL/Fl_Preferences.H contrast.o: ../FL/Fl_Radio_Round_Button.H contrast.o: ../FL/Fl_Rect.H contrast.o: ../FL/Fl_Return_Button.H contrast.o: ../FL/Fl_RGB_Image.H contrast.o: ../FL/Fl_Round_Button.H contrast.o: ../FL/Fl_Scrollbar.H contrast.o: ../FL/Fl_Slider.H contrast.o: ../FL/Fl_Terminal.H contrast.o: ../FL/fl_types.h contrast.o: ../FL/fl_utf8.h contrast.o: ../FL/Fl_Valuator.H contrast.o: ../FL/Fl_Value_Input.H contrast.o: ../FL/Fl_Value_Slider.H contrast.o: ../FL/Fl_Widget.H contrast.o: ../FL/Fl_Window.H contrast.o: ../FL/platform_types.h cube.o: ../config.h cube.o: ../FL/Enumerations.H cube.o: ../FL/Fl.H cube.o: ../FL/fl_ask.H cube.o: ../FL/fl_attr.h cube.o: ../FL/Fl_Bitmap.H cube.o: ../FL/Fl_Box.H cube.o: ../FL/Fl_Button.H cube.o: ../FL/Fl_Cairo.H cube.o: ../FL/fl_casts.H cube.o: ../FL/fl_config.h cube.o: ../FL/Fl_Device.H cube.o: ../FL/Fl_Export.H cube.o: ../FL/Fl_Gl_Window.H cube.o: ../FL/Fl_Grid.H cube.o: ../FL/Fl_Group.H cube.o: ../FL/Fl_Image.H cube.o: ../FL/Fl_Light_Button.H cube.o: ../FL/Fl_Menu_.H cube.o: ../FL/Fl_Menu_Bar.H cube.o: ../FL/Fl_Menu_Item.H cube.o: ../FL/Fl_Multi_Label.H cube.o: ../FL/Fl_Paged_Device.H cube.o: ../FL/Fl_Plugin.H cube.o: ../FL/Fl_Preferences.H cube.o: ../FL/Fl_Printer.H cube.o: ../FL/Fl_Radio_Light_Button.H cube.o: ../FL/Fl_Rect.H cube.o: ../FL/Fl_Slider.H cube.o: ../FL/Fl_Sys_Menu_Bar.H cube.o: ../FL/fl_types.h cube.o: ../FL/fl_utf8.h cube.o: ../FL/Fl_Valuator.H cube.o: ../FL/Fl_Widget.H cube.o: ../FL/Fl_Widget_Surface.H cube.o: ../FL/Fl_Window.H cube.o: ../FL/gl.h cube.o: ../FL/platform_types.h CubeMain.o: ../config.h CubeMain.o: ../FL/Enumerations.H CubeMain.o: ../FL/Fl.H CubeMain.o: ../FL/fl_attr.h CubeMain.o: ../FL/Fl_Bitmap.H CubeMain.o: ../FL/Fl_Cairo.H CubeMain.o: ../FL/fl_casts.H CubeMain.o: ../FL/fl_config.h CubeMain.o: ../FL/Fl_Double_Window.H CubeMain.o: ../FL/Fl_Export.H CubeMain.o: ../FL/Fl_Gl_Window.H CubeMain.o: ../FL/Fl_Group.H CubeMain.o: ../FL/Fl_Image.H CubeMain.o: ../FL/Fl_Roller.H CubeMain.o: ../FL/Fl_Slider.H CubeMain.o: ../FL/fl_types.h CubeMain.o: ../FL/fl_utf8.h CubeMain.o: ../FL/Fl_Valuator.H CubeMain.o: ../FL/Fl_Value_Slider.H CubeMain.o: ../FL/Fl_Widget.H CubeMain.o: ../FL/Fl_Window.H CubeMain.o: ../FL/gl.h CubeMain.o: ../FL/platform_types.h CubeMain.o: CubeView.h CubeMain.o: CubeViewUI.h CubeView.o: ../config.h CubeView.o: ../FL/Enumerations.H CubeView.o: ../FL/Fl.H CubeView.o: ../FL/fl_attr.h CubeView.o: ../FL/Fl_Bitmap.H CubeView.o: ../FL/Fl_Cairo.H CubeView.o: ../FL/fl_casts.H CubeView.o: ../FL/fl_config.h CubeView.o: ../FL/Fl_Export.H CubeView.o: ../FL/Fl_Gl_Window.H CubeView.o: ../FL/Fl_Group.H CubeView.o: ../FL/Fl_Image.H CubeView.o: ../FL/fl_types.h CubeView.o: ../FL/fl_utf8.h CubeView.o: ../FL/Fl_Widget.H CubeView.o: ../FL/Fl_Window.H CubeView.o: ../FL/gl.h CubeView.o: ../FL/platform_types.h CubeView.o: CubeView.h cursor.o: ../FL/Enumerations.H cursor.o: ../FL/Fl.H cursor.o: ../FL/fl_attr.h cursor.o: ../FL/Fl_Bitmap.H cursor.o: ../FL/Fl_Box.H cursor.o: ../FL/Fl_Cairo.H cursor.o: ../FL/fl_casts.H cursor.o: ../FL/Fl_Choice.H cursor.o: ../FL/fl_config.h cursor.o: ../FL/Fl_Device.H cursor.o: ../FL/Fl_Double_Window.H cursor.o: ../FL/fl_draw.H cursor.o: ../FL/Fl_Export.H cursor.o: ../FL/Fl_Graphics_Driver.H cursor.o: ../FL/Fl_Group.H cursor.o: ../FL/Fl_Hor_Value_Slider.H cursor.o: ../FL/Fl_Image.H cursor.o: ../FL/Fl_Menu_.H cursor.o: ../FL/Fl_Menu_Item.H cursor.o: ../FL/Fl_Multi_Label.H cursor.o: ../FL/Fl_Pixmap.H cursor.o: ../FL/Fl_Plugin.H cursor.o: ../FL/Fl_Preferences.H cursor.o: ../FL/Fl_Rect.H cursor.o: ../FL/Fl_RGB_Image.H cursor.o: ../FL/Fl_Slider.H cursor.o: ../FL/fl_types.h cursor.o: ../FL/fl_utf8.h cursor.o: ../FL/Fl_Valuator.H cursor.o: ../FL/Fl_Value_Slider.H cursor.o: ../FL/Fl_Widget.H cursor.o: ../FL/Fl_Window.H cursor.o: ../FL/platform_types.h cursor.o: ../fluid/pixmaps/compressed.xpm curve.o: ../FL/Enumerations.H curve.o: ../FL/Fl.H curve.o: ../FL/fl_attr.h curve.o: ../FL/Fl_Bitmap.H curve.o: ../FL/Fl_Button.H curve.o: ../FL/Fl_Cairo.H curve.o: ../FL/fl_casts.H curve.o: ../FL/fl_config.h curve.o: ../FL/Fl_Device.H curve.o: ../FL/Fl_Double_Window.H curve.o: ../FL/fl_draw.H curve.o: ../FL/Fl_Export.H curve.o: ../FL/Fl_Graphics_Driver.H curve.o: ../FL/Fl_Group.H curve.o: ../FL/Fl_Hor_Value_Slider.H curve.o: ../FL/Fl_Image.H curve.o: ../FL/Fl_Pixmap.H curve.o: ../FL/Fl_Plugin.H curve.o: ../FL/Fl_Preferences.H curve.o: ../FL/Fl_Rect.H curve.o: ../FL/Fl_RGB_Image.H curve.o: ../FL/Fl_Slider.H curve.o: ../FL/Fl_Toggle_Button.H curve.o: ../FL/fl_types.h curve.o: ../FL/fl_utf8.h curve.o: ../FL/Fl_Valuator.H curve.o: ../FL/Fl_Value_Slider.H curve.o: ../FL/Fl_Widget.H curve.o: ../FL/Fl_Window.H curve.o: ../FL/platform_types.h demo.o: ../FL/Enumerations.H demo.o: ../FL/filename.H demo.o: ../FL/Fl.H demo.o: ../FL/fl_ask.H demo.o: ../FL/fl_attr.h demo.o: ../FL/Fl_Bitmap.H demo.o: ../FL/Fl_Box.H demo.o: ../FL/Fl_Button.H demo.o: ../FL/Fl_Cairo.H demo.o: ../FL/fl_casts.H demo.o: ../FL/Fl_Choice.H demo.o: ../FL/fl_config.h demo.o: ../FL/Fl_Double_Window.H demo.o: ../FL/Fl_Export.H demo.o: ../FL/Fl_Group.H demo.o: ../FL/Fl_Image.H demo.o: ../FL/Fl_Menu_.H demo.o: ../FL/Fl_Menu_Button.H demo.o: ../FL/Fl_Menu_Item.H demo.o: ../FL/Fl_Multi_Label.H demo.o: ../FL/Fl_Rect.H demo.o: ../FL/Fl_Scheme.H demo.o: ../FL/Fl_Scheme_Choice.H demo.o: ../FL/Fl_Scrollbar.H demo.o: ../FL/Fl_Terminal.H demo.o: ../FL/fl_types.h demo.o: ../FL/fl_utf8.h demo.o: ../FL/Fl_Widget.H demo.o: ../FL/Fl_Window.H demo.o: ../FL/platform.H demo.o: ../FL/platform_types.h demo.o: ../FL/x11.H device.o: ../FL/Enumerations.H device.o: ../FL/filename.H device.o: ../FL/Fl.H device.o: ../FL/fl_ask.H device.o: ../FL/fl_attr.h device.o: ../FL/Fl_Bitmap.H device.o: ../FL/Fl_Box.H device.o: ../FL/Fl_Browser.H device.o: ../FL/Fl_Browser_.H device.o: ../FL/Fl_Button.H device.o: ../FL/Fl_Cairo.H device.o: ../FL/fl_casts.H device.o: ../FL/Fl_Check_Button.H device.o: ../FL/Fl_Choice.H device.o: ../FL/Fl_Clock.H device.o: ../FL/fl_config.h device.o: ../FL/Fl_Copy_Surface.H device.o: ../FL/Fl_Device.H device.o: ../FL/Fl_Double_Window.H device.o: ../FL/fl_draw.H device.o: ../FL/Fl_Export.H device.o: ../FL/Fl_File_Browser.H device.o: ../FL/Fl_File_Chooser.H device.o: ../FL/Fl_File_Icon.H device.o: ../FL/Fl_File_Input.H device.o: ../FL/Fl_Graphics_Driver.H device.o: ../FL/Fl_Group.H device.o: ../FL/Fl_Image.H device.o: ../FL/Fl_Image_Surface.H device.o: ../FL/Fl_Input.H device.o: ../FL/Fl_Input_.H device.o: ../FL/Fl_Light_Button.H device.o: ../FL/Fl_Menu_.H device.o: ../FL/Fl_Menu_Button.H device.o: ../FL/Fl_Menu_Item.H device.o: ../FL/Fl_Multi_Label.H device.o: ../FL/Fl_Native_File_Chooser.H device.o: ../FL/Fl_Paged_Device.H device.o: ../FL/Fl_PDF_File_Surface.H device.o: ../FL/Fl_Pixmap.H device.o: ../FL/Fl_Plugin.H device.o: ../FL/Fl_PostScript.H device.o: ../FL/Fl_Preferences.H device.o: ../FL/Fl_Printer.H device.o: ../FL/Fl_Radio_Round_Button.H device.o: ../FL/Fl_Rect.H device.o: ../FL/Fl_Return_Button.H device.o: ../FL/Fl_RGB_Image.H device.o: ../FL/Fl_Round_Button.H device.o: ../FL/Fl_Scrollbar.H device.o: ../FL/Fl_Shared_Image.H device.o: ../FL/Fl_Slider.H device.o: ../FL/Fl_SVG_File_Surface.H device.o: ../FL/Fl_Tile.H device.o: ../FL/fl_types.h device.o: ../FL/fl_utf8.h device.o: ../FL/Fl_Valuator.H device.o: ../FL/Fl_Widget.H device.o: ../FL/Fl_Widget_Surface.H device.o: ../FL/Fl_Window.H device.o: ../FL/platform_types.h device.o: pixmaps/porsche.xpm device.o: pixmaps/sorceress.xbm doublebuffer.o: ../FL/Enumerations.H doublebuffer.o: ../FL/Fl.H doublebuffer.o: ../FL/fl_attr.h doublebuffer.o: ../FL/Fl_Bitmap.H doublebuffer.o: ../FL/Fl_Box.H doublebuffer.o: ../FL/Fl_Cairo.H doublebuffer.o: ../FL/fl_casts.H doublebuffer.o: ../FL/fl_config.h doublebuffer.o: ../FL/Fl_Device.H doublebuffer.o: ../FL/Fl_Double_Window.H doublebuffer.o: ../FL/fl_draw.H doublebuffer.o: ../FL/Fl_Export.H doublebuffer.o: ../FL/Fl_Graphics_Driver.H doublebuffer.o: ../FL/Fl_Group.H doublebuffer.o: ../FL/Fl_Hor_Slider.H doublebuffer.o: ../FL/Fl_Image.H doublebuffer.o: ../FL/Fl_Pixmap.H doublebuffer.o: ../FL/Fl_Plugin.H doublebuffer.o: ../FL/Fl_Preferences.H doublebuffer.o: ../FL/Fl_Rect.H doublebuffer.o: ../FL/Fl_RGB_Image.H doublebuffer.o: ../FL/Fl_Single_Window.H doublebuffer.o: ../FL/Fl_Slider.H doublebuffer.o: ../FL/fl_types.h doublebuffer.o: ../FL/fl_utf8.h doublebuffer.o: ../FL/Fl_Valuator.H doublebuffer.o: ../FL/Fl_Widget.H doublebuffer.o: ../FL/Fl_Window.H doublebuffer.o: ../FL/math.h doublebuffer.o: ../FL/platform_types.h editor.o: ../FL/Enumerations.H editor.o: ../FL/filename.H editor.o: ../FL/Fl.H editor.o: ../FL/fl_ask.H editor.o: ../FL/fl_attr.h editor.o: ../FL/Fl_Bitmap.H editor.o: ../FL/Fl_Box.H editor.o: ../FL/Fl_Browser.H editor.o: ../FL/Fl_Browser_.H editor.o: ../FL/Fl_Button.H editor.o: ../FL/Fl_Cairo.H editor.o: ../FL/fl_casts.H editor.o: ../FL/Fl_Check_Button.H editor.o: ../FL/Fl_Choice.H editor.o: ../FL/fl_config.h editor.o: ../FL/Fl_Device.H editor.o: ../FL/Fl_Double_Window.H editor.o: ../FL/fl_draw.H editor.o: ../FL/Fl_Export.H editor.o: ../FL/Fl_File_Browser.H editor.o: ../FL/Fl_File_Chooser.H editor.o: ../FL/Fl_File_Icon.H editor.o: ../FL/Fl_File_Input.H editor.o: ../FL/Fl_Flex.H editor.o: ../FL/Fl_Graphics_Driver.H editor.o: ../FL/Fl_Group.H editor.o: ../FL/Fl_Image.H editor.o: ../FL/Fl_Input.H editor.o: ../FL/Fl_Input_.H editor.o: ../FL/Fl_Light_Button.H editor.o: ../FL/Fl_Menu_.H editor.o: ../FL/Fl_Menu_Bar.H editor.o: ../FL/Fl_Menu_Button.H editor.o: ../FL/Fl_Menu_Item.H editor.o: ../FL/Fl_Multi_Label.H editor.o: ../FL/Fl_Native_File_Chooser.H editor.o: ../FL/Fl_Pixmap.H editor.o: ../FL/Fl_Plugin.H editor.o: ../FL/Fl_Preferences.H editor.o: ../FL/Fl_Rect.H editor.o: ../FL/Fl_Return_Button.H editor.o: ../FL/Fl_RGB_Image.H editor.o: ../FL/Fl_Scrollbar.H editor.o: ../FL/Fl_Slider.H editor.o: ../FL/fl_string_functions.h editor.o: ../FL/Fl_Text_Buffer.H editor.o: ../FL/Fl_Text_Display.H editor.o: ../FL/Fl_Text_Editor.H editor.o: ../FL/Fl_Tile.H editor.o: ../FL/fl_types.h editor.o: ../FL/fl_utf8.h editor.o: ../FL/Fl_Valuator.H editor.o: ../FL/Fl_Widget.H editor.o: ../FL/Fl_Window.H editor.o: ../FL/platform.H editor.o: ../FL/platform_types.h editor.o: ../FL/x11.H fast_slow.o: ../FL/Enumerations.H fast_slow.o: ../FL/Fl.H fast_slow.o: ../FL/fl_attr.h fast_slow.o: ../FL/Fl_Bitmap.H fast_slow.o: ../FL/Fl_Box.H fast_slow.o: ../FL/Fl_Cairo.H fast_slow.o: ../FL/fl_casts.H fast_slow.o: ../FL/fl_config.h fast_slow.o: ../FL/Fl_Double_Window.H fast_slow.o: ../FL/Fl_Export.H fast_slow.o: ../FL/Fl_Group.H fast_slow.o: ../FL/Fl_Image.H fast_slow.o: ../FL/Fl_Slider.H fast_slow.o: ../FL/fl_types.h fast_slow.o: ../FL/fl_utf8.h fast_slow.o: ../FL/Fl_Valuator.H fast_slow.o: ../FL/Fl_Widget.H fast_slow.o: ../FL/Fl_Window.H fast_slow.o: ../FL/platform_types.h fast_slow.o: fast_slow.h file_chooser.o: ../FL/Enumerations.H file_chooser.o: ../FL/filename.H file_chooser.o: ../FL/Fl.H file_chooser.o: ../FL/fl_ask.H file_chooser.o: ../FL/fl_attr.h file_chooser.o: ../FL/Fl_Bitmap.H file_chooser.o: ../FL/Fl_Box.H file_chooser.o: ../FL/Fl_Browser.H file_chooser.o: ../FL/Fl_Browser_.H file_chooser.o: ../FL/Fl_Button.H file_chooser.o: ../FL/Fl_Cairo.H file_chooser.o: ../FL/fl_casts.H file_chooser.o: ../FL/Fl_Check_Button.H file_chooser.o: ../FL/Fl_Choice.H file_chooser.o: ../FL/fl_config.h file_chooser.o: ../FL/Fl_Double_Window.H file_chooser.o: ../FL/Fl_Export.H file_chooser.o: ../FL/Fl_File_Browser.H file_chooser.o: ../FL/Fl_File_Chooser.H file_chooser.o: ../FL/Fl_File_Icon.H file_chooser.o: ../FL/Fl_File_Input.H file_chooser.o: ../FL/Fl_Group.H file_chooser.o: ../FL/Fl_Image.H file_chooser.o: ../FL/Fl_Input.H file_chooser.o: ../FL/Fl_Input_.H file_chooser.o: ../FL/Fl_Light_Button.H file_chooser.o: ../FL/Fl_Menu_.H file_chooser.o: ../FL/Fl_Menu_Button.H file_chooser.o: ../FL/Fl_Menu_Item.H file_chooser.o: ../FL/Fl_Multi_Label.H file_chooser.o: ../FL/Fl_PNM_Image.H file_chooser.o: ../FL/Fl_Preferences.H file_chooser.o: ../FL/Fl_Rect.H file_chooser.o: ../FL/Fl_Return_Button.H file_chooser.o: ../FL/Fl_Scrollbar.H file_chooser.o: ../FL/Fl_Shared_Image.H file_chooser.o: ../FL/Fl_Slider.H file_chooser.o: ../FL/Fl_Terminal.H file_chooser.o: ../FL/Fl_Tile.H file_chooser.o: ../FL/fl_types.h file_chooser.o: ../FL/fl_utf8.h file_chooser.o: ../FL/Fl_Valuator.H file_chooser.o: ../FL/Fl_Widget.H file_chooser.o: ../FL/Fl_Window.H file_chooser.o: ../FL/platform_types.h flex_demo.o: ../FL/Enumerations.H flex_demo.o: ../FL/Fl.H flex_demo.o: ../FL/fl_attr.h flex_demo.o: ../FL/Fl_Bitmap.H flex_demo.o: ../FL/Fl_Box.H flex_demo.o: ../FL/Fl_Button.H flex_demo.o: ../FL/Fl_Cairo.H flex_demo.o: ../FL/fl_casts.H flex_demo.o: ../FL/fl_config.h flex_demo.o: ../FL/Fl_Double_Window.H flex_demo.o: ../FL/Fl_Export.H flex_demo.o: ../FL/Fl_Flex.H flex_demo.o: ../FL/Fl_Group.H flex_demo.o: ../FL/Fl_Image.H flex_demo.o: ../FL/Fl_Input.H flex_demo.o: ../FL/Fl_Input_.H flex_demo.o: ../FL/fl_types.h flex_demo.o: ../FL/fl_utf8.h flex_demo.o: ../FL/Fl_Widget.H flex_demo.o: ../FL/Fl_Window.H flex_demo.o: ../FL/platform_types.h flex_login.o: ../FL/Enumerations.H flex_login.o: ../FL/Fl.H flex_login.o: ../FL/fl_attr.h flex_login.o: ../FL/Fl_Bitmap.H flex_login.o: ../FL/Fl_Box.H flex_login.o: ../FL/Fl_Button.H flex_login.o: ../FL/Fl_Cairo.H flex_login.o: ../FL/fl_casts.H flex_login.o: ../FL/fl_config.h flex_login.o: ../FL/Fl_Double_Window.H flex_login.o: ../FL/Fl_Export.H flex_login.o: ../FL/Fl_Flex.H flex_login.o: ../FL/Fl_Group.H flex_login.o: ../FL/Fl_Image.H flex_login.o: ../FL/Fl_Input.H flex_login.o: ../FL/Fl_Input_.H flex_login.o: ../FL/fl_types.h flex_login.o: ../FL/fl_utf8.h flex_login.o: ../FL/Fl_Widget.H flex_login.o: ../FL/Fl_Window.H flex_login.o: ../FL/platform_types.h fltk-versions.o: ../FL/Enumerations.H fltk-versions.o: ../FL/Fl.H fltk-versions.o: ../FL/fl_ask.H fltk-versions.o: ../FL/fl_attr.h fltk-versions.o: ../FL/Fl_Box.H fltk-versions.o: ../FL/Fl_Cairo.H fltk-versions.o: ../FL/fl_casts.H fltk-versions.o: ../FL/fl_config.h fltk-versions.o: ../FL/Fl_Export.H fltk-versions.o: ../FL/Fl_Grid.H fltk-versions.o: ../FL/Fl_Group.H fltk-versions.o: ../FL/Fl_Rect.H fltk-versions.o: ../FL/fl_types.h fltk-versions.o: ../FL/fl_utf8.h fltk-versions.o: ../FL/Fl_Widget.H fltk-versions.o: ../FL/Fl_Window.H fltk-versions.o: ../FL/platform.H fltk-versions.o: ../FL/platform_types.h fltk-versions.o: ../FL/x11.H fonts.o: ../FL/Enumerations.H fonts.o: ../FL/filename.H fonts.o: ../FL/Fl.H fonts.o: ../FL/fl_ask.H fonts.o: ../FL/fl_attr.h fonts.o: ../FL/Fl_Bitmap.H fonts.o: ../FL/Fl_Box.H fonts.o: ../FL/Fl_Browser.H fonts.o: ../FL/Fl_Browser_.H fonts.o: ../FL/Fl_Button.H fonts.o: ../FL/Fl_Cairo.H fonts.o: ../FL/fl_casts.H fonts.o: ../FL/Fl_Check_Button.H fonts.o: ../FL/Fl_Choice.H fonts.o: ../FL/fl_config.h fonts.o: ../FL/Fl_Device.H fonts.o: ../FL/Fl_Double_Window.H fonts.o: ../FL/fl_draw.H fonts.o: ../FL/Fl_Export.H fonts.o: ../FL/Fl_File_Browser.H fonts.o: ../FL/Fl_File_Chooser.H fonts.o: ../FL/Fl_File_Icon.H fonts.o: ../FL/Fl_File_Input.H fonts.o: ../FL/Fl_Graphics_Driver.H fonts.o: ../FL/Fl_Group.H fonts.o: ../FL/Fl_Hold_Browser.H fonts.o: ../FL/Fl_Image.H fonts.o: ../FL/Fl_Input.H fonts.o: ../FL/Fl_Input_.H fonts.o: ../FL/Fl_Light_Button.H fonts.o: ../FL/Fl_Menu_.H fonts.o: ../FL/Fl_Menu_Button.H fonts.o: ../FL/Fl_Menu_Item.H fonts.o: ../FL/Fl_Multi_Label.H fonts.o: ../FL/Fl_Pixmap.H fonts.o: ../FL/Fl_Plugin.H fonts.o: ../FL/Fl_Preferences.H fonts.o: ../FL/Fl_Rect.H fonts.o: ../FL/Fl_Return_Button.H fonts.o: ../FL/Fl_RGB_Image.H fonts.o: ../FL/Fl_Scrollbar.H fonts.o: ../FL/Fl_Slider.H fonts.o: ../FL/Fl_Tile.H fonts.o: ../FL/fl_types.h fonts.o: ../FL/fl_utf8.h fonts.o: ../FL/Fl_Valuator.H fonts.o: ../FL/Fl_Widget.H fonts.o: ../FL/Fl_Window.H fonts.o: ../FL/platform_types.h forms.o: ../FL/Enumerations.H forms.o: ../FL/filename.H forms.o: ../FL/Fl.H forms.o: ../FL/fl_ask.H forms.o: ../FL/fl_attr.h forms.o: ../FL/Fl_Bitmap.H forms.o: ../FL/Fl_Box.H forms.o: ../FL/Fl_Browser.H forms.o: ../FL/Fl_Browser_.H forms.o: ../FL/Fl_Button.H forms.o: ../FL/Fl_Cairo.H forms.o: ../FL/fl_casts.H forms.o: ../FL/Fl_Chart.H forms.o: ../FL/Fl_Check_Button.H forms.o: ../FL/Fl_Choice.H forms.o: ../FL/Fl_Clock.H forms.o: ../FL/fl_config.h forms.o: ../FL/Fl_Counter.H forms.o: ../FL/Fl_Device.H forms.o: ../FL/Fl_Dial.H forms.o: ../FL/Fl_Double_Window.H forms.o: ../FL/fl_draw.H forms.o: ../FL/Fl_Export.H forms.o: ../FL/Fl_File_Browser.H forms.o: ../FL/Fl_File_Chooser.H forms.o: ../FL/Fl_File_Icon.H forms.o: ../FL/Fl_File_Input.H forms.o: ../FL/Fl_FormsBitmap.H forms.o: ../FL/Fl_FormsPixmap.H forms.o: ../FL/Fl_Free.H forms.o: ../FL/Fl_Graphics_Driver.H forms.o: ../FL/Fl_Group.H forms.o: ../FL/Fl_Image.H forms.o: ../FL/Fl_Input.H forms.o: ../FL/Fl_Input_.H forms.o: ../FL/Fl_Light_Button.H forms.o: ../FL/Fl_Menu_.H forms.o: ../FL/Fl_Menu_Button.H forms.o: ../FL/Fl_Menu_Item.H forms.o: ../FL/Fl_Multi_Label.H forms.o: ../FL/Fl_Pixmap.H forms.o: ../FL/Fl_Plugin.H forms.o: ../FL/Fl_Positioner.H forms.o: ../FL/Fl_Preferences.H forms.o: ../FL/Fl_Rect.H forms.o: ../FL/Fl_Return_Button.H forms.o: ../FL/Fl_RGB_Image.H forms.o: ../FL/Fl_Round_Button.H forms.o: ../FL/Fl_Scrollbar.H forms.o: ../FL/fl_show_colormap.H forms.o: ../FL/Fl_Slider.H forms.o: ../FL/Fl_Tile.H forms.o: ../FL/Fl_Timer.H forms.o: ../FL/fl_types.h forms.o: ../FL/fl_utf8.h forms.o: ../FL/Fl_Valuator.H forms.o: ../FL/Fl_Value_Slider.H forms.o: ../FL/Fl_Widget.H forms.o: ../FL/Fl_Window.H forms.o: ../FL/forms.H forms.o: ../FL/platform_types.h forms.o: pixmaps/sorceress.xbm fractals.o: ../config.h fractals.o: ../FL/Enumerations.H fractals.o: ../FL/Fl.H fractals.o: ../FL/fl_attr.h fractals.o: ../FL/Fl_Bitmap.H fractals.o: ../FL/Fl_Button.H fractals.o: ../FL/Fl_Cairo.H fractals.o: ../FL/fl_casts.H fractals.o: ../FL/fl_config.h fractals.o: ../FL/Fl_Export.H fractals.o: ../FL/Fl_Gl_Window.H fractals.o: ../FL/Fl_Group.H fractals.o: ../FL/Fl_Image.H fractals.o: ../FL/fl_types.h fractals.o: ../FL/fl_utf8.h fractals.o: ../FL/Fl_Widget.H fractals.o: ../FL/Fl_Window.H fractals.o: ../FL/gl.h fractals.o: ../FL/glu.h fractals.o: ../FL/glut.H fractals.o: ../FL/platform_types.h fractals.o: fracviewer.h fracviewer.o: ../config.h fracviewer.o: ../FL/Enumerations.H fracviewer.o: ../FL/Fl.H fracviewer.o: ../FL/fl_attr.h fracviewer.o: ../FL/Fl_Bitmap.H fracviewer.o: ../FL/Fl_Cairo.H fracviewer.o: ../FL/fl_casts.H fracviewer.o: ../FL/fl_config.h fracviewer.o: ../FL/Fl_Export.H fracviewer.o: ../FL/Fl_Gl_Window.H fracviewer.o: ../FL/Fl_Group.H fracviewer.o: ../FL/Fl_Image.H fracviewer.o: ../FL/fl_types.h fracviewer.o: ../FL/fl_utf8.h fracviewer.o: ../FL/Fl_Widget.H fracviewer.o: ../FL/Fl_Window.H fracviewer.o: ../FL/gl.h fracviewer.o: ../FL/glu.h fracviewer.o: ../FL/glut.H fracviewer.o: ../FL/platform_types.h fracviewer.o: fracviewer.h fullscreen.o: ../config.h fullscreen.o: ../FL/Enumerations.H fullscreen.o: ../FL/Fl.H fullscreen.o: ../FL/fl_ask.H fullscreen.o: ../FL/fl_attr.h fullscreen.o: ../FL/Fl_Bitmap.H fullscreen.o: ../FL/Fl_Browser.H fullscreen.o: ../FL/Fl_Browser_.H fullscreen.o: ../FL/Fl_Button.H fullscreen.o: ../FL/Fl_Cairo.H fullscreen.o: ../FL/fl_casts.H fullscreen.o: ../FL/fl_config.h fullscreen.o: ../FL/Fl_Export.H fullscreen.o: ../FL/Fl_Gl_Window.H fullscreen.o: ../FL/Fl_Group.H fullscreen.o: ../FL/Fl_Hor_Slider.H fullscreen.o: ../FL/Fl_Image.H fullscreen.o: ../FL/Fl_Input.H fullscreen.o: ../FL/Fl_Input_.H fullscreen.o: ../FL/Fl_Light_Button.H fullscreen.o: ../FL/Fl_Menu_.H fullscreen.o: ../FL/Fl_Menu_Button.H fullscreen.o: ../FL/Fl_Menu_Item.H fullscreen.o: ../FL/Fl_Multi_Label.H fullscreen.o: ../FL/Fl_Scrollbar.H fullscreen.o: ../FL/Fl_Single_Window.H fullscreen.o: ../FL/Fl_Slider.H fullscreen.o: ../FL/Fl_Toggle_Light_Button.H fullscreen.o: ../FL/fl_types.h fullscreen.o: ../FL/fl_utf8.h fullscreen.o: ../FL/Fl_Valuator.H fullscreen.o: ../FL/Fl_Widget.H fullscreen.o: ../FL/Fl_Window.H fullscreen.o: ../FL/gl.h fullscreen.o: ../FL/math.h fullscreen.o: ../FL/platform_types.h glpuzzle.o: ../config.h glpuzzle.o: ../FL/Enumerations.H glpuzzle.o: ../FL/Fl.H glpuzzle.o: ../FL/fl_attr.h glpuzzle.o: ../FL/Fl_Bitmap.H glpuzzle.o: ../FL/Fl_Cairo.H glpuzzle.o: ../FL/fl_casts.H glpuzzle.o: ../FL/fl_config.h glpuzzle.o: ../FL/Fl_Export.H glpuzzle.o: ../FL/Fl_Gl_Window.H glpuzzle.o: ../FL/Fl_Group.H glpuzzle.o: ../FL/Fl_Image.H glpuzzle.o: ../FL/fl_types.h glpuzzle.o: ../FL/fl_utf8.h glpuzzle.o: ../FL/Fl_Widget.H glpuzzle.o: ../FL/Fl_Window.H glpuzzle.o: ../FL/gl.h glpuzzle.o: ../FL/glu.h glpuzzle.o: ../FL/glut.H glpuzzle.o: ../FL/platform_types.h glpuzzle.o: trackball.c glpuzzle.o: trackball.h glut_test.o: ../FL/Enumerations.H glut_test.o: ../FL/Fl.H glut_test.o: ../FL/fl_attr.h glut_test.o: ../FL/Fl_Bitmap.H glut_test.o: ../FL/Fl_Cairo.H glut_test.o: ../FL/fl_casts.H glut_test.o: ../FL/fl_config.h glut_test.o: ../FL/Fl_Export.H glut_test.o: ../FL/Fl_Gl_Window.H glut_test.o: ../FL/Fl_Group.H glut_test.o: ../FL/Fl_Image.H glut_test.o: ../FL/fl_types.h glut_test.o: ../FL/fl_utf8.h glut_test.o: ../FL/Fl_Widget.H glut_test.o: ../FL/Fl_Window.H glut_test.o: ../FL/gl.h glut_test.o: ../FL/glut.H glut_test.o: ../FL/platform_types.h gl_overlay.o: ../config.h gl_overlay.o: ../FL/Enumerations.H gl_overlay.o: ../FL/Fl.H gl_overlay.o: ../FL/fl_attr.h gl_overlay.o: ../FL/Fl_Bitmap.H gl_overlay.o: ../FL/Fl_Button.H gl_overlay.o: ../FL/Fl_Cairo.H gl_overlay.o: ../FL/fl_casts.H gl_overlay.o: ../FL/fl_config.h gl_overlay.o: ../FL/Fl_Export.H gl_overlay.o: ../FL/Fl_Gl_Window.H gl_overlay.o: ../FL/Fl_Group.H gl_overlay.o: ../FL/Fl_Hor_Slider.H gl_overlay.o: ../FL/Fl_Image.H gl_overlay.o: ../FL/Fl_Slider.H gl_overlay.o: ../FL/Fl_Toggle_Button.H gl_overlay.o: ../FL/fl_types.h gl_overlay.o: ../FL/fl_utf8.h gl_overlay.o: ../FL/Fl_Valuator.H gl_overlay.o: ../FL/Fl_Widget.H gl_overlay.o: ../FL/Fl_Window.H gl_overlay.o: ../FL/gl.h gl_overlay.o: ../FL/math.h gl_overlay.o: ../FL/platform_types.h hello.o: ../FL/Enumerations.H hello.o: ../FL/Fl.H hello.o: ../FL/fl_attr.h hello.o: ../FL/Fl_Box.H hello.o: ../FL/Fl_Cairo.H hello.o: ../FL/fl_casts.H hello.o: ../FL/fl_config.h hello.o: ../FL/Fl_Export.H hello.o: ../FL/fl_types.h hello.o: ../FL/fl_utf8.h hello.o: ../FL/Fl_Window.H hello.o: ../FL/platform_types.h help_dialog.o: ../FL/Enumerations.H help_dialog.o: ../FL/filename.H help_dialog.o: ../FL/Fl.H help_dialog.o: ../FL/fl_attr.h help_dialog.o: ../FL/Fl_Bitmap.H help_dialog.o: ../FL/Fl_Box.H help_dialog.o: ../FL/Fl_Button.H help_dialog.o: ../FL/Fl_Cairo.H help_dialog.o: ../FL/fl_casts.H help_dialog.o: ../FL/fl_config.h help_dialog.o: ../FL/Fl_Device.H help_dialog.o: ../FL/Fl_Double_Window.H help_dialog.o: ../FL/fl_draw.H help_dialog.o: ../FL/Fl_Export.H help_dialog.o: ../FL/Fl_GIF_Image.H help_dialog.o: ../FL/Fl_Graphics_Driver.H help_dialog.o: ../FL/Fl_Group.H help_dialog.o: ../FL/Fl_Help_Dialog.H help_dialog.o: ../FL/Fl_Help_View.H help_dialog.o: ../FL/Fl_Image.H help_dialog.o: ../FL/Fl_Input.H help_dialog.o: ../FL/Fl_Input_.H help_dialog.o: ../FL/Fl_Pixmap.H help_dialog.o: ../FL/Fl_Plugin.H help_dialog.o: ../FL/Fl_Preferences.H help_dialog.o: ../FL/Fl_Rect.H help_dialog.o: ../FL/Fl_RGB_Image.H help_dialog.o: ../FL/Fl_Scrollbar.H help_dialog.o: ../FL/Fl_Slider.H help_dialog.o: ../FL/fl_types.h help_dialog.o: ../FL/fl_utf8.h help_dialog.o: ../FL/Fl_Valuator.H help_dialog.o: ../FL/Fl_Widget.H help_dialog.o: ../FL/Fl_Window.H help_dialog.o: ../FL/platform_types.h icon.o: ../FL/Enumerations.H icon.o: ../FL/Fl.H icon.o: ../FL/fl_attr.h icon.o: ../FL/Fl_Bitmap.H icon.o: ../FL/Fl_Cairo.H icon.o: ../FL/fl_casts.H icon.o: ../FL/Fl_Choice.H icon.o: ../FL/fl_config.h icon.o: ../FL/Fl_Double_Window.H icon.o: ../FL/Fl_Export.H icon.o: ../FL/Fl_Group.H icon.o: ../FL/Fl_Image.H icon.o: ../FL/Fl_Menu_.H icon.o: ../FL/Fl_Menu_Item.H icon.o: ../FL/Fl_Multi_Label.H icon.o: ../FL/Fl_RGB_Image.H icon.o: ../FL/fl_types.h icon.o: ../FL/fl_utf8.h icon.o: ../FL/Fl_Widget.H icon.o: ../FL/Fl_Window.H icon.o: ../FL/platform_types.h iconize.o: ../FL/Enumerations.H iconize.o: ../FL/Fl.H iconize.o: ../FL/fl_attr.h iconize.o: ../FL/Fl_Box.H iconize.o: ../FL/Fl_Button.H iconize.o: ../FL/Fl_Cairo.H iconize.o: ../FL/fl_casts.H iconize.o: ../FL/fl_config.h iconize.o: ../FL/Fl_Export.H iconize.o: ../FL/fl_types.h iconize.o: ../FL/fl_utf8.h iconize.o: ../FL/Fl_Window.H iconize.o: ../FL/platform_types.h image.o: ../config.h image.o: ../FL/Enumerations.H image.o: ../FL/Fl.H image.o: ../FL/fl_attr.h image.o: ../FL/Fl_Bitmap.H image.o: ../FL/Fl_Button.H image.o: ../FL/Fl_Cairo.H image.o: ../FL/fl_casts.H image.o: ../FL/fl_config.h image.o: ../FL/Fl_Double_Window.H image.o: ../FL/Fl_Export.H image.o: ../FL/Fl_Group.H image.o: ../FL/Fl_Image.H image.o: ../FL/Fl_Toggle_Button.H image.o: ../FL/fl_types.h image.o: ../FL/fl_utf8.h image.o: ../FL/Fl_Widget.H image.o: ../FL/Fl_Window.H image.o: ../FL/platform.H image.o: ../FL/platform_types.h image.o: ../FL/x11.H image.o: list_visuals.cxx inactive.o: ../FL/Enumerations.H inactive.o: ../FL/Fl.H inactive.o: ../FL/fl_attr.h inactive.o: ../FL/Fl_Bitmap.H inactive.o: ../FL/Fl_Box.H inactive.o: ../FL/Fl_Button.H inactive.o: ../FL/Fl_Cairo.H inactive.o: ../FL/fl_casts.H inactive.o: ../FL/Fl_Check_Button.H inactive.o: ../FL/Fl_Clock.H inactive.o: ../FL/fl_config.h inactive.o: ../FL/Fl_Dial.H inactive.o: ../FL/Fl_Double_Window.H inactive.o: ../FL/Fl_Export.H inactive.o: ../FL/Fl_Group.H inactive.o: ../FL/Fl_Image.H inactive.o: ../FL/Fl_Input.H inactive.o: ../FL/Fl_Input_.H inactive.o: ../FL/Fl_Light_Button.H inactive.o: ../FL/Fl_Menu_.H inactive.o: ../FL/Fl_Menu_Button.H inactive.o: ../FL/Fl_Menu_Item.H inactive.o: ../FL/Fl_Multi_Label.H inactive.o: ../FL/Fl_Roller.H inactive.o: ../FL/Fl_Round_Button.H inactive.o: ../FL/Fl_Scrollbar.H inactive.o: ../FL/Fl_Slider.H inactive.o: ../FL/fl_types.h inactive.o: ../FL/fl_utf8.h inactive.o: ../FL/Fl_Valuator.H inactive.o: ../FL/Fl_Value_Output.H inactive.o: ../FL/Fl_Widget.H inactive.o: ../FL/Fl_Window.H inactive.o: ../FL/platform_types.h inactive.o: inactive.h input.o: ../FL/Enumerations.H input.o: ../FL/Fl.H input.o: ../FL/fl_attr.h input.o: ../FL/Fl_Box.H input.o: ../FL/Fl_Button.H input.o: ../FL/Fl_Cairo.H input.o: ../FL/fl_casts.H input.o: ../FL/Fl_Choice.H input.o: ../FL/Fl_Color_Chooser.H input.o: ../FL/fl_config.h input.o: ../FL/Fl_Export.H input.o: ../FL/Fl_Float_Input.H input.o: ../FL/Fl_Group.H input.o: ../FL/Fl_Image.H input.o: ../FL/Fl_Input.H input.o: ../FL/Fl_Input_.H input.o: ../FL/Fl_Int_Input.H input.o: ../FL/Fl_Light_Button.H input.o: ../FL/Fl_Menu_.H input.o: ../FL/Fl_Menu_Item.H input.o: ../FL/Fl_Multiline_Input.H input.o: ../FL/Fl_Multi_Label.H input.o: ../FL/Fl_Rect.H input.o: ../FL/Fl_Return_Button.H input.o: ../FL/Fl_Scrollbar.H input.o: ../FL/Fl_Secret_Input.H input.o: ../FL/Fl_Terminal.H input.o: ../FL/Fl_Toggle_Button.H input.o: ../FL/fl_types.h input.o: ../FL/fl_utf8.h input.o: ../FL/Fl_Valuator.H input.o: ../FL/Fl_Value_Input.H input.o: ../FL/Fl_Widget.H input.o: ../FL/Fl_Window.H input.o: ../FL/platform_types.h input_choice.o: ../FL/Enumerations.H input_choice.o: ../FL/Fl.H input_choice.o: ../FL/fl_attr.h input_choice.o: ../FL/Fl_Bitmap.H input_choice.o: ../FL/Fl_Button.H input_choice.o: ../FL/Fl_Cairo.H input_choice.o: ../FL/fl_casts.H input_choice.o: ../FL/Fl_Check_Button.H input_choice.o: ../FL/Fl_Choice.H input_choice.o: ../FL/fl_config.h input_choice.o: ../FL/Fl_Double_Window.H input_choice.o: ../FL/Fl_Export.H input_choice.o: ../FL/Fl_Group.H input_choice.o: ../FL/Fl_Image.H input_choice.o: ../FL/Fl_Input.H input_choice.o: ../FL/Fl_Input_.H input_choice.o: ../FL/Fl_Input_Choice.H input_choice.o: ../FL/Fl_Light_Button.H input_choice.o: ../FL/Fl_Menu_.H input_choice.o: ../FL/Fl_Menu_Button.H input_choice.o: ../FL/Fl_Menu_Item.H input_choice.o: ../FL/Fl_Multi_Label.H input_choice.o: ../FL/Fl_Rect.H input_choice.o: ../FL/Fl_Scheme.H input_choice.o: ../FL/Fl_Scheme_Choice.H input_choice.o: ../FL/Fl_Scrollbar.H input_choice.o: ../FL/Fl_Terminal.H input_choice.o: ../FL/fl_types.h input_choice.o: ../FL/fl_utf8.h input_choice.o: ../FL/Fl_Widget.H input_choice.o: ../FL/Fl_Window.H input_choice.o: ../FL/platform_types.h keyboard.o: ../FL/Enumerations.H keyboard.o: ../FL/Fl.H keyboard.o: ../FL/fl_attr.h keyboard.o: ../FL/Fl_Box.H keyboard.o: ../FL/Fl_Button.H keyboard.o: ../FL/Fl_Cairo.H keyboard.o: ../FL/fl_casts.H keyboard.o: ../FL/fl_config.h keyboard.o: ../FL/Fl_Dial.H keyboard.o: ../FL/Fl_Export.H keyboard.o: ../FL/Fl_Input.H keyboard.o: ../FL/Fl_Input_.H keyboard.o: ../FL/Fl_Output.H keyboard.o: ../FL/fl_types.h keyboard.o: ../FL/fl_utf8.h keyboard.o: ../FL/Fl_Window.H keyboard.o: ../FL/platform_types.h keyboard.o: keyboard.h keyboard.o: keyboard_ui.h label.o: ../FL/Enumerations.H label.o: ../FL/Fl.H label.o: ../FL/fl_attr.h label.o: ../FL/Fl_Bitmap.H label.o: ../FL/Fl_Box.H label.o: ../FL/Fl_Button.H label.o: ../FL/Fl_Cairo.H label.o: ../FL/fl_casts.H label.o: ../FL/Fl_Choice.H label.o: ../FL/fl_config.h label.o: ../FL/Fl_Device.H label.o: ../FL/Fl_Double_Window.H label.o: ../FL/fl_draw.H label.o: ../FL/Fl_Export.H label.o: ../FL/Fl_Graphics_Driver.H label.o: ../FL/Fl_Group.H label.o: ../FL/Fl_Hor_Value_Slider.H label.o: ../FL/Fl_Image.H label.o: ../FL/Fl_Input.H label.o: ../FL/Fl_Input_.H label.o: ../FL/Fl_Menu_.H label.o: ../FL/Fl_Menu_Item.H label.o: ../FL/Fl_Multi_Label.H label.o: ../FL/Fl_Pixmap.H label.o: ../FL/Fl_Plugin.H label.o: ../FL/Fl_Preferences.H label.o: ../FL/Fl_Rect.H label.o: ../FL/Fl_RGB_Image.H label.o: ../FL/Fl_Slider.H label.o: ../FL/Fl_Toggle_Button.H label.o: ../FL/fl_types.h label.o: ../FL/fl_utf8.h label.o: ../FL/Fl_Valuator.H label.o: ../FL/Fl_Value_Slider.H label.o: ../FL/Fl_Widget.H label.o: ../FL/Fl_Window.H label.o: ../FL/platform_types.h label.o: pixmaps/blast.xpm line_style.o: ../FL/Enumerations.H line_style.o: ../FL/Fl.H line_style.o: ../FL/fl_attr.h line_style.o: ../FL/Fl_Bitmap.H line_style.o: ../FL/Fl_Box.H line_style.o: ../FL/Fl_Button.H line_style.o: ../FL/Fl_Cairo.H line_style.o: ../FL/fl_casts.H line_style.o: ../FL/Fl_Check_Button.H line_style.o: ../FL/Fl_Choice.H line_style.o: ../FL/fl_config.h line_style.o: ../FL/Fl_Device.H line_style.o: ../FL/Fl_Double_Window.H line_style.o: ../FL/fl_draw.H line_style.o: ../FL/Fl_Export.H line_style.o: ../FL/Fl_Graphics_Driver.H line_style.o: ../FL/Fl_Group.H line_style.o: ../FL/Fl_Image.H line_style.o: ../FL/Fl_Light_Button.H line_style.o: ../FL/Fl_Menu_.H line_style.o: ../FL/Fl_Menu_Item.H line_style.o: ../FL/Fl_Multi_Label.H line_style.o: ../FL/Fl_Pixmap.H line_style.o: ../FL/Fl_Plugin.H line_style.o: ../FL/Fl_Preferences.H line_style.o: ../FL/Fl_Rect.H line_style.o: ../FL/Fl_RGB_Image.H line_style.o: ../FL/Fl_Slider.H line_style.o: ../FL/fl_types.h line_style.o: ../FL/fl_utf8.h line_style.o: ../FL/Fl_Valuator.H line_style.o: ../FL/Fl_Value_Slider.H line_style.o: ../FL/Fl_Widget.H line_style.o: ../FL/Fl_Window.H line_style.o: ../FL/platform_types.h line_style_docs.o: ../FL/Enumerations.H line_style_docs.o: ../FL/Fl.H line_style_docs.o: ../FL/fl_attr.h line_style_docs.o: ../FL/Fl_Bitmap.H line_style_docs.o: ../FL/Fl_Box.H line_style_docs.o: ../FL/Fl_Cairo.H line_style_docs.o: ../FL/fl_casts.H line_style_docs.o: ../FL/fl_config.h line_style_docs.o: ../FL/Fl_Device.H line_style_docs.o: ../FL/Fl_Double_Window.H line_style_docs.o: ../FL/fl_draw.H line_style_docs.o: ../FL/Fl_Export.H line_style_docs.o: ../FL/Fl_Graphics_Driver.H line_style_docs.o: ../FL/Fl_Grid.H line_style_docs.o: ../FL/Fl_Group.H line_style_docs.o: ../FL/Fl_Image.H line_style_docs.o: ../FL/Fl_Pixmap.H line_style_docs.o: ../FL/Fl_Plugin.H line_style_docs.o: ../FL/Fl_Preferences.H line_style_docs.o: ../FL/Fl_Rect.H line_style_docs.o: ../FL/Fl_RGB_Image.H line_style_docs.o: ../FL/fl_types.h line_style_docs.o: ../FL/fl_utf8.h line_style_docs.o: ../FL/Fl_Widget.H line_style_docs.o: ../FL/Fl_Window.H line_style_docs.o: ../FL/platform_types.h list_visuals.o: ../config.h list_visuals.o: ../FL/Enumerations.H list_visuals.o: ../FL/fl_config.h list_visuals.o: ../FL/Fl_Export.H list_visuals.o: ../FL/fl_types.h list_visuals.o: ../FL/platform.H list_visuals.o: ../FL/platform_types.h list_visuals.o: ../FL/x11.H mandelbrot.o: ../FL/Enumerations.H mandelbrot.o: ../FL/Fl.H mandelbrot.o: ../FL/fl_attr.h mandelbrot.o: ../FL/Fl_Bitmap.H mandelbrot.o: ../FL/Fl_Box.H mandelbrot.o: ../FL/Fl_Button.H mandelbrot.o: ../FL/Fl_Cairo.H mandelbrot.o: ../FL/fl_casts.H mandelbrot.o: ../FL/fl_config.h mandelbrot.o: ../FL/Fl_Device.H mandelbrot.o: ../FL/Fl_Double_Window.H mandelbrot.o: ../FL/fl_draw.H mandelbrot.o: ../FL/Fl_Export.H mandelbrot.o: ../FL/Fl_Float_Input.H mandelbrot.o: ../FL/Fl_Graphics_Driver.H mandelbrot.o: ../FL/Fl_Group.H mandelbrot.o: ../FL/Fl_Image.H mandelbrot.o: ../FL/Fl_Input.H mandelbrot.o: ../FL/Fl_Input_.H mandelbrot.o: ../FL/Fl_Paged_Device.H mandelbrot.o: ../FL/Fl_Pixmap.H mandelbrot.o: ../FL/Fl_Plugin.H mandelbrot.o: ../FL/Fl_Preferences.H mandelbrot.o: ../FL/Fl_Printer.H mandelbrot.o: ../FL/Fl_Rect.H mandelbrot.o: ../FL/Fl_RGB_Image.H mandelbrot.o: ../FL/Fl_Slider.H mandelbrot.o: ../FL/fl_types.h mandelbrot.o: ../FL/fl_utf8.h mandelbrot.o: ../FL/Fl_Valuator.H mandelbrot.o: ../FL/Fl_Widget.H mandelbrot.o: ../FL/Fl_Widget_Surface.H mandelbrot.o: ../FL/Fl_Window.H mandelbrot.o: ../FL/platform_types.h mandelbrot.o: mandelbrot.h mandelbrot.o: mandelbrot_ui.h menubar.o: ../FL/Enumerations.H menubar.o: ../FL/Fl.H menubar.o: ../FL/fl_ask.H menubar.o: ../FL/fl_attr.h menubar.o: ../FL/Fl_Bitmap.H menubar.o: ../FL/Fl_Box.H menubar.o: ../FL/Fl_Button.H menubar.o: ../FL/Fl_Cairo.H menubar.o: ../FL/fl_casts.H menubar.o: ../FL/Fl_Choice.H menubar.o: ../FL/fl_config.h menubar.o: ../FL/Fl_Device.H menubar.o: ../FL/Fl_Double_Window.H menubar.o: ../FL/fl_draw.H menubar.o: ../FL/Fl_Export.H menubar.o: ../FL/Fl_Graphics_Driver.H menubar.o: ../FL/Fl_Group.H menubar.o: ../FL/Fl_Image.H menubar.o: ../FL/Fl_Menu_.H menubar.o: ../FL/Fl_Menu_Bar.H menubar.o: ../FL/Fl_Menu_Button.H menubar.o: ../FL/Fl_Menu_Item.H menubar.o: ../FL/Fl_Multi_Label.H menubar.o: ../FL/Fl_Pixmap.H menubar.o: ../FL/Fl_Plugin.H menubar.o: ../FL/Fl_Preferences.H menubar.o: ../FL/Fl_Rect.H menubar.o: ../FL/Fl_RGB_Image.H menubar.o: ../FL/Fl_Scheme.H menubar.o: ../FL/Fl_Scheme_Choice.H menubar.o: ../FL/Fl_Scrollbar.H menubar.o: ../FL/Fl_Slider.H menubar.o: ../FL/fl_string_functions.h menubar.o: ../FL/Fl_Sys_Menu_Bar.H menubar.o: ../FL/Fl_Terminal.H menubar.o: ../FL/Fl_Toggle_Button.H menubar.o: ../FL/fl_types.h menubar.o: ../FL/fl_utf8.h menubar.o: ../FL/Fl_Valuator.H menubar.o: ../FL/Fl_Value_Slider.H menubar.o: ../FL/Fl_Widget.H menubar.o: ../FL/Fl_Window.H menubar.o: ../FL/platform_types.h message.o: ../FL/Enumerations.H message.o: ../FL/Fl.H message.o: ../FL/fl_ask.H message.o: ../FL/fl_attr.h message.o: ../FL/Fl_Cairo.H message.o: ../FL/fl_casts.H message.o: ../FL/fl_config.h message.o: ../FL/Fl_Export.H message.o: ../FL/fl_types.h message.o: ../FL/fl_utf8.h message.o: ../FL/Fl_Window.H message.o: ../FL/platform_types.h minimum.o: ../FL/Enumerations.H minimum.o: ../FL/Fl.H minimum.o: ../FL/fl_attr.h minimum.o: ../FL/Fl_Bitmap.H minimum.o: ../FL/Fl_Box.H minimum.o: ../FL/Fl_Button.H minimum.o: ../FL/Fl_Cairo.H minimum.o: ../FL/fl_casts.H minimum.o: ../FL/fl_config.h minimum.o: ../FL/Fl_Double_Window.H minimum.o: ../FL/Fl_Export.H minimum.o: ../FL/Fl_Group.H minimum.o: ../FL/Fl_Image.H minimum.o: ../FL/Fl_Return_Button.H minimum.o: ../FL/Fl_Slider.H minimum.o: ../FL/fl_types.h minimum.o: ../FL/fl_utf8.h minimum.o: ../FL/Fl_Valuator.H minimum.o: ../FL/Fl_Widget.H minimum.o: ../FL/Fl_Window.H minimum.o: ../FL/platform_types.h native-filechooser.o: ../FL/Enumerations.H native-filechooser.o: ../FL/filename.H native-filechooser.o: ../FL/Fl.H native-filechooser.o: ../FL/fl_ask.H native-filechooser.o: ../FL/fl_attr.h native-filechooser.o: ../FL/Fl_Bitmap.H native-filechooser.o: ../FL/Fl_Box.H native-filechooser.o: ../FL/Fl_Browser.H native-filechooser.o: ../FL/Fl_Browser_.H native-filechooser.o: ../FL/Fl_Button.H native-filechooser.o: ../FL/Fl_Cairo.H native-filechooser.o: ../FL/fl_casts.H native-filechooser.o: ../FL/Fl_Check_Button.H native-filechooser.o: ../FL/Fl_Choice.H native-filechooser.o: ../FL/fl_config.h native-filechooser.o: ../FL/Fl_Device.H native-filechooser.o: ../FL/Fl_Double_Window.H native-filechooser.o: ../FL/fl_draw.H native-filechooser.o: ../FL/Fl_Export.H native-filechooser.o: ../FL/Fl_File_Browser.H native-filechooser.o: ../FL/Fl_File_Chooser.H native-filechooser.o: ../FL/Fl_File_Icon.H native-filechooser.o: ../FL/Fl_File_Input.H native-filechooser.o: ../FL/Fl_Graphics_Driver.H native-filechooser.o: ../FL/Fl_Group.H native-filechooser.o: ../FL/Fl_Help_View.H native-filechooser.o: ../FL/Fl_Image.H native-filechooser.o: ../FL/Fl_Input.H native-filechooser.o: ../FL/Fl_Input_.H native-filechooser.o: ../FL/Fl_Light_Button.H native-filechooser.o: ../FL/Fl_Menu_.H native-filechooser.o: ../FL/Fl_Menu_Button.H native-filechooser.o: ../FL/Fl_Menu_Item.H native-filechooser.o: ../FL/Fl_Multiline_Input.H native-filechooser.o: ../FL/Fl_Multi_Label.H native-filechooser.o: ../FL/Fl_Native_File_Chooser.H native-filechooser.o: ../FL/Fl_Pixmap.H native-filechooser.o: ../FL/Fl_Plugin.H native-filechooser.o: ../FL/Fl_Preferences.H native-filechooser.o: ../FL/Fl_Rect.H native-filechooser.o: ../FL/Fl_Return_Button.H native-filechooser.o: ../FL/Fl_RGB_Image.H native-filechooser.o: ../FL/Fl_Scrollbar.H native-filechooser.o: ../FL/Fl_Shared_Image.H native-filechooser.o: ../FL/Fl_Slider.H native-filechooser.o: ../FL/Fl_Terminal.H native-filechooser.o: ../FL/Fl_Tile.H native-filechooser.o: ../FL/fl_types.h native-filechooser.o: ../FL/fl_utf8.h native-filechooser.o: ../FL/Fl_Valuator.H native-filechooser.o: ../FL/Fl_Widget.H native-filechooser.o: ../FL/Fl_Window.H native-filechooser.o: ../FL/platform_types.h navigation.o: ../FL/Enumerations.H navigation.o: ../FL/Fl.H navigation.o: ../FL/fl_attr.h navigation.o: ../FL/Fl_Cairo.H navigation.o: ../FL/fl_casts.H navigation.o: ../FL/fl_config.h navigation.o: ../FL/Fl_Export.H navigation.o: ../FL/Fl_Input.H navigation.o: ../FL/Fl_Input_.H navigation.o: ../FL/Fl_Light_Button.H navigation.o: ../FL/fl_types.h navigation.o: ../FL/fl_utf8.h navigation.o: ../FL/Fl_Window.H navigation.o: ../FL/platform_types.h offscreen.o: ../FL/Enumerations.H offscreen.o: ../FL/Fl.H offscreen.o: ../FL/fl_attr.h offscreen.o: ../FL/Fl_Bitmap.H offscreen.o: ../FL/Fl_Box.H offscreen.o: ../FL/Fl_Cairo.H offscreen.o: ../FL/fl_casts.H offscreen.o: ../FL/fl_config.h offscreen.o: ../FL/Fl_Device.H offscreen.o: ../FL/Fl_Double_Window.H offscreen.o: ../FL/fl_draw.H offscreen.o: ../FL/Fl_Export.H offscreen.o: ../FL/Fl_Graphics_Driver.H offscreen.o: ../FL/Fl_Group.H offscreen.o: ../FL/Fl_Image.H offscreen.o: ../FL/Fl_Pixmap.H offscreen.o: ../FL/Fl_Plugin.H offscreen.o: ../FL/Fl_Preferences.H offscreen.o: ../FL/Fl_Rect.H offscreen.o: ../FL/Fl_RGB_Image.H offscreen.o: ../FL/fl_types.h offscreen.o: ../FL/fl_utf8.h offscreen.o: ../FL/Fl_Widget.H offscreen.o: ../FL/Fl_Window.H offscreen.o: ../FL/platform.H offscreen.o: ../FL/platform_types.h offscreen.o: ../FL/x11.H output.o: ../FL/Enumerations.H output.o: ../FL/Fl.H output.o: ../FL/fl_attr.h output.o: ../FL/Fl_Bitmap.H output.o: ../FL/Fl_Box.H output.o: ../FL/Fl_Button.H output.o: ../FL/Fl_Cairo.H output.o: ../FL/fl_casts.H output.o: ../FL/fl_config.h output.o: ../FL/Fl_Device.H output.o: ../FL/Fl_Double_Window.H output.o: ../FL/fl_draw.H output.o: ../FL/Fl_Export.H output.o: ../FL/Fl_Graphics_Driver.H output.o: ../FL/Fl_Group.H output.o: ../FL/Fl_Hor_Value_Slider.H output.o: ../FL/Fl_Image.H output.o: ../FL/Fl_Input.H output.o: ../FL/Fl_Input_.H output.o: ../FL/Fl_Multiline_Output.H output.o: ../FL/Fl_Output.H output.o: ../FL/Fl_Pixmap.H output.o: ../FL/Fl_Plugin.H output.o: ../FL/Fl_Preferences.H output.o: ../FL/Fl_Rect.H output.o: ../FL/Fl_RGB_Image.H output.o: ../FL/Fl_Slider.H output.o: ../FL/Fl_Toggle_Button.H output.o: ../FL/fl_types.h output.o: ../FL/fl_utf8.h output.o: ../FL/Fl_Valuator.H output.o: ../FL/Fl_Value_Input.H output.o: ../FL/Fl_Value_Slider.H output.o: ../FL/Fl_Widget.H output.o: ../FL/Fl_Window.H output.o: ../FL/platform_types.h overlay.o: ../FL/Enumerations.H overlay.o: ../FL/Fl.H overlay.o: ../FL/fl_attr.h overlay.o: ../FL/Fl_Bitmap.H overlay.o: ../FL/Fl_Button.H overlay.o: ../FL/Fl_Cairo.H overlay.o: ../FL/fl_casts.H overlay.o: ../FL/fl_config.h overlay.o: ../FL/Fl_Device.H overlay.o: ../FL/Fl_Double_Window.H overlay.o: ../FL/fl_draw.H overlay.o: ../FL/Fl_Export.H overlay.o: ../FL/Fl_Graphics_Driver.H overlay.o: ../FL/Fl_Group.H overlay.o: ../FL/Fl_Image.H overlay.o: ../FL/Fl_Overlay_Window.H overlay.o: ../FL/Fl_Pixmap.H overlay.o: ../FL/Fl_Plugin.H overlay.o: ../FL/Fl_Preferences.H overlay.o: ../FL/Fl_Rect.H overlay.o: ../FL/Fl_RGB_Image.H overlay.o: ../FL/fl_types.h overlay.o: ../FL/fl_utf8.h overlay.o: ../FL/Fl_Widget.H overlay.o: ../FL/Fl_Window.H overlay.o: ../FL/platform_types.h pack.o: ../FL/Enumerations.H pack.o: ../FL/Fl.H pack.o: ../FL/fl_attr.h pack.o: ../FL/Fl_Bitmap.H pack.o: ../FL/Fl_Button.H pack.o: ../FL/Fl_Cairo.H pack.o: ../FL/fl_casts.H pack.o: ../FL/fl_config.h pack.o: ../FL/Fl_Double_Window.H pack.o: ../FL/Fl_Export.H pack.o: ../FL/Fl_Flex.H pack.o: ../FL/Fl_Group.H pack.o: ../FL/Fl_Image.H pack.o: ../FL/Fl_Light_Button.H pack.o: ../FL/Fl_Pack.H pack.o: ../FL/Fl_Scroll.H pack.o: ../FL/Fl_Scrollbar.H pack.o: ../FL/Fl_Slider.H pack.o: ../FL/fl_types.h pack.o: ../FL/fl_utf8.h pack.o: ../FL/Fl_Valuator.H pack.o: ../FL/Fl_Value_Slider.H pack.o: ../FL/Fl_Widget.H pack.o: ../FL/Fl_Window.H pack.o: ../FL/platform_types.h pixmap.o: ../FL/Enumerations.H pixmap.o: ../FL/Fl.H pixmap.o: ../FL/Fl_Anim_GIF_Image.H pixmap.o: ../FL/fl_attr.h pixmap.o: ../FL/Fl_Bitmap.H pixmap.o: ../FL/Fl_Button.H pixmap.o: ../FL/Fl_Cairo.H pixmap.o: ../FL/fl_casts.H pixmap.o: ../FL/fl_config.h pixmap.o: ../FL/Fl_Double_Window.H pixmap.o: ../FL/Fl_Export.H pixmap.o: ../FL/Fl_GIF_Image.H pixmap.o: ../FL/Fl_Group.H pixmap.o: ../FL/Fl_Image.H pixmap.o: ../FL/Fl_Multi_Label.H pixmap.o: ../FL/Fl_Pixmap.H pixmap.o: ../FL/Fl_Toggle_Button.H pixmap.o: ../FL/fl_types.h pixmap.o: ../FL/fl_utf8.h pixmap.o: ../FL/Fl_Widget.H pixmap.o: ../FL/Fl_Window.H pixmap.o: ../FL/platform_types.h pixmap.o: pixmaps/animated_fluid_gif.h pixmap_browser.o: ../config.h pixmap_browser.o: ../FL/Enumerations.H pixmap_browser.o: ../FL/filename.H pixmap_browser.o: ../FL/Fl.H pixmap_browser.o: ../FL/fl_ask.H pixmap_browser.o: ../FL/fl_attr.h pixmap_browser.o: ../FL/Fl_Bitmap.H pixmap_browser.o: ../FL/Fl_Box.H pixmap_browser.o: ../FL/Fl_Browser.H pixmap_browser.o: ../FL/Fl_Browser_.H pixmap_browser.o: ../FL/Fl_Button.H pixmap_browser.o: ../FL/Fl_Cairo.H pixmap_browser.o: ../FL/fl_casts.H pixmap_browser.o: ../FL/Fl_Check_Button.H pixmap_browser.o: ../FL/Fl_Choice.H pixmap_browser.o: ../FL/fl_config.h pixmap_browser.o: ../FL/Fl_Device.H pixmap_browser.o: ../FL/Fl_Double_Window.H pixmap_browser.o: ../FL/Fl_Export.H pixmap_browser.o: ../FL/Fl_File_Browser.H pixmap_browser.o: ../FL/Fl_File_Chooser.H pixmap_browser.o: ../FL/Fl_File_Icon.H pixmap_browser.o: ../FL/Fl_File_Input.H pixmap_browser.o: ../FL/Fl_GIF_Image.H pixmap_browser.o: ../FL/Fl_Group.H pixmap_browser.o: ../FL/Fl_Image.H pixmap_browser.o: ../FL/Fl_Input.H pixmap_browser.o: ../FL/Fl_Input_.H pixmap_browser.o: ../FL/Fl_Light_Button.H pixmap_browser.o: ../FL/Fl_Menu_.H pixmap_browser.o: ../FL/Fl_Menu_Button.H pixmap_browser.o: ../FL/Fl_Menu_Item.H pixmap_browser.o: ../FL/fl_message.H pixmap_browser.o: ../FL/Fl_Multi_Label.H pixmap_browser.o: ../FL/Fl_Native_File_Chooser.H pixmap_browser.o: ../FL/Fl_Paged_Device.H pixmap_browser.o: ../FL/Fl_Pixmap.H pixmap_browser.o: ../FL/Fl_Plugin.H pixmap_browser.o: ../FL/Fl_Preferences.H pixmap_browser.o: ../FL/Fl_Printer.H pixmap_browser.o: ../FL/Fl_Return_Button.H pixmap_browser.o: ../FL/Fl_Scrollbar.H pixmap_browser.o: ../FL/Fl_Shared_Image.H pixmap_browser.o: ../FL/Fl_Slider.H pixmap_browser.o: ../FL/Fl_SVG_File_Surface.H pixmap_browser.o: ../FL/Fl_Tile.H pixmap_browser.o: ../FL/fl_types.h pixmap_browser.o: ../FL/fl_utf8.h pixmap_browser.o: ../FL/Fl_Valuator.H pixmap_browser.o: ../FL/Fl_Widget.H pixmap_browser.o: ../FL/Fl_Widget_Surface.H pixmap_browser.o: ../FL/Fl_Window.H pixmap_browser.o: ../FL/platform.H pixmap_browser.o: ../FL/platform_types.h pixmap_browser.o: ../FL/x11.H preferences.o: ../FL/Enumerations.H preferences.o: ../FL/filename.H preferences.o: ../FL/Fl.H preferences.o: ../FL/fl_ask.H preferences.o: ../FL/fl_attr.h preferences.o: ../FL/Fl_Bitmap.H preferences.o: ../FL/Fl_Box.H preferences.o: ../FL/Fl_Button.H preferences.o: ../FL/Fl_Cairo.H preferences.o: ../FL/fl_casts.H preferences.o: ../FL/Fl_Check_Button.H preferences.o: ../FL/Fl_Choice.H preferences.o: ../FL/fl_config.h preferences.o: ../FL/Fl_Double_Window.H preferences.o: ../FL/Fl_Export.H preferences.o: ../FL/Fl_Group.H preferences.o: ../FL/Fl_Image.H preferences.o: ../FL/Fl_Input.H preferences.o: ../FL/Fl_Input_.H preferences.o: ../FL/Fl_Int_Input.H preferences.o: ../FL/Fl_Light_Button.H preferences.o: ../FL/Fl_Menu_.H preferences.o: ../FL/Fl_Menu_Item.H preferences.o: ../FL/Fl_Multi_Label.H preferences.o: ../FL/Fl_Preferences.H preferences.o: ../FL/Fl_Round_Button.H preferences.o: ../FL/Fl_Slider.H preferences.o: ../FL/fl_types.h preferences.o: ../FL/fl_utf8.h preferences.o: ../FL/Fl_Valuator.H preferences.o: ../FL/Fl_Value_Slider.H preferences.o: ../FL/Fl_Widget.H preferences.o: ../FL/Fl_Window.H preferences.o: ../FL/platform_types.h preferences.o: preferences.h radio.o: ../FL/Enumerations.H radio.o: ../FL/Fl.H radio.o: ../FL/fl_attr.h radio.o: ../FL/Fl_Bitmap.H radio.o: ../FL/Fl_Button.H radio.o: ../FL/Fl_Cairo.H radio.o: ../FL/fl_casts.H radio.o: ../FL/Fl_Check_Button.H radio.o: ../FL/fl_config.h radio.o: ../FL/Fl_Double_Window.H radio.o: ../FL/Fl_Export.H radio.o: ../FL/Fl_Group.H radio.o: ../FL/Fl_Image.H radio.o: ../FL/Fl_Input.H radio.o: ../FL/Fl_Input_.H radio.o: ../FL/Fl_Light_Button.H radio.o: ../FL/Fl_Output.H radio.o: ../FL/Fl_Return_Button.H radio.o: ../FL/Fl_Round_Button.H radio.o: ../FL/fl_types.h radio.o: ../FL/fl_utf8.h radio.o: ../FL/Fl_Widget.H radio.o: ../FL/Fl_Window.H radio.o: ../FL/platform_types.h radio.o: radio.h resize-example1.o: ../FL/Enumerations.H resize-example1.o: ../FL/Fl.H resize-example1.o: ../FL/fl_attr.h resize-example1.o: ../FL/Fl_Bitmap.H resize-example1.o: ../FL/Fl_Box.H resize-example1.o: ../FL/Fl_Cairo.H resize-example1.o: ../FL/fl_casts.H resize-example1.o: ../FL/fl_config.h resize-example1.o: ../FL/Fl_Double_Window.H resize-example1.o: ../FL/Fl_Export.H resize-example1.o: ../FL/Fl_Group.H resize-example1.o: ../FL/Fl_Image.H resize-example1.o: ../FL/fl_types.h resize-example1.o: ../FL/fl_utf8.h resize-example1.o: ../FL/Fl_Widget.H resize-example1.o: ../FL/Fl_Window.H resize-example1.o: ../FL/platform_types.h resize-example1.o: resize-arrows.h resize-example2.o: ../FL/Enumerations.H resize-example2.o: ../FL/Fl.H resize-example2.o: ../FL/fl_attr.h resize-example2.o: ../FL/Fl_Bitmap.H resize-example2.o: ../FL/Fl_Box.H resize-example2.o: ../FL/Fl_Cairo.H resize-example2.o: ../FL/fl_casts.H resize-example2.o: ../FL/fl_config.h resize-example2.o: ../FL/Fl_Double_Window.H resize-example2.o: ../FL/Fl_Export.H resize-example2.o: ../FL/Fl_Group.H resize-example2.o: ../FL/Fl_Image.H resize-example2.o: ../FL/fl_types.h resize-example2.o: ../FL/fl_utf8.h resize-example2.o: ../FL/Fl_Widget.H resize-example2.o: ../FL/Fl_Window.H resize-example2.o: ../FL/platform_types.h resize-example2.o: resize-arrows.h resize-example3a.o: ../FL/Enumerations.H resize-example3a.o: ../FL/Fl.H resize-example3a.o: ../FL/fl_attr.h resize-example3a.o: ../FL/Fl_Bitmap.H resize-example3a.o: ../FL/Fl_Box.H resize-example3a.o: ../FL/Fl_Button.H resize-example3a.o: ../FL/Fl_Cairo.H resize-example3a.o: ../FL/fl_casts.H resize-example3a.o: ../FL/fl_config.h resize-example3a.o: ../FL/Fl_Double_Window.H resize-example3a.o: ../FL/Fl_Export.H resize-example3a.o: ../FL/Fl_Group.H resize-example3a.o: ../FL/Fl_Image.H resize-example3a.o: ../FL/fl_types.h resize-example3a.o: ../FL/fl_utf8.h resize-example3a.o: ../FL/Fl_Widget.H resize-example3a.o: ../FL/Fl_Window.H resize-example3a.o: ../FL/platform_types.h resize-example3a.o: resize-arrows.h resize-example3b.o: ../FL/Enumerations.H resize-example3b.o: ../FL/Fl.H resize-example3b.o: ../FL/fl_attr.h resize-example3b.o: ../FL/Fl_Bitmap.H resize-example3b.o: ../FL/Fl_Box.H resize-example3b.o: ../FL/Fl_Button.H resize-example3b.o: ../FL/Fl_Cairo.H resize-example3b.o: ../FL/fl_casts.H resize-example3b.o: ../FL/fl_config.h resize-example3b.o: ../FL/Fl_Double_Window.H resize-example3b.o: ../FL/Fl_Export.H resize-example3b.o: ../FL/Fl_Group.H resize-example3b.o: ../FL/Fl_Image.H resize-example3b.o: ../FL/fl_types.h resize-example3b.o: ../FL/fl_utf8.h resize-example3b.o: ../FL/Fl_Widget.H resize-example3b.o: ../FL/Fl_Window.H resize-example3b.o: ../FL/platform_types.h resize-example3b.o: resize-arrows.h resize-example3c.o: ../FL/Enumerations.H resize-example3c.o: ../FL/Fl.H resize-example3c.o: ../FL/fl_attr.h resize-example3c.o: ../FL/Fl_Bitmap.H resize-example3c.o: ../FL/Fl_Box.H resize-example3c.o: ../FL/Fl_Button.H resize-example3c.o: ../FL/Fl_Cairo.H resize-example3c.o: ../FL/fl_casts.H resize-example3c.o: ../FL/fl_config.h resize-example3c.o: ../FL/Fl_Double_Window.H resize-example3c.o: ../FL/Fl_Export.H resize-example3c.o: ../FL/Fl_Group.H resize-example3c.o: ../FL/Fl_Image.H resize-example3c.o: ../FL/fl_types.h resize-example3c.o: ../FL/fl_utf8.h resize-example3c.o: ../FL/Fl_Widget.H resize-example3c.o: ../FL/Fl_Window.H resize-example3c.o: ../FL/platform_types.h resize-example3c.o: resize-arrows.h resize-example4a.o: ../FL/Enumerations.H resize-example4a.o: ../FL/Fl.H resize-example4a.o: ../FL/fl_attr.h resize-example4a.o: ../FL/Fl_Bitmap.H resize-example4a.o: ../FL/Fl_Box.H resize-example4a.o: ../FL/Fl_Cairo.H resize-example4a.o: ../FL/fl_casts.H resize-example4a.o: ../FL/fl_config.h resize-example4a.o: ../FL/Fl_Double_Window.H resize-example4a.o: ../FL/Fl_Export.H resize-example4a.o: ../FL/Fl_Group.H resize-example4a.o: ../FL/Fl_Image.H resize-example4a.o: ../FL/fl_types.h resize-example4a.o: ../FL/fl_utf8.h resize-example4a.o: ../FL/Fl_Widget.H resize-example4a.o: ../FL/Fl_Window.H resize-example4a.o: ../FL/platform_types.h resize-example4a.o: resize-arrows.h resize-example4b.o: ../FL/Enumerations.H resize-example4b.o: ../FL/Fl.H resize-example4b.o: ../FL/fl_attr.h resize-example4b.o: ../FL/Fl_Bitmap.H resize-example4b.o: ../FL/Fl_Box.H resize-example4b.o: ../FL/Fl_Cairo.H resize-example4b.o: ../FL/fl_casts.H resize-example4b.o: ../FL/fl_config.h resize-example4b.o: ../FL/Fl_Double_Window.H resize-example4b.o: ../FL/Fl_Export.H resize-example4b.o: ../FL/Fl_Group.H resize-example4b.o: ../FL/Fl_Image.H resize-example4b.o: ../FL/fl_types.h resize-example4b.o: ../FL/fl_utf8.h resize-example4b.o: ../FL/Fl_Widget.H resize-example4b.o: ../FL/Fl_Window.H resize-example4b.o: ../FL/platform_types.h resize-example4b.o: resize-arrows.h resize-example5a.o: ../FL/Enumerations.H resize-example5a.o: ../FL/Fl.H resize-example5a.o: ../FL/fl_attr.h resize-example5a.o: ../FL/Fl_Bitmap.H resize-example5a.o: ../FL/Fl_Box.H resize-example5a.o: ../FL/Fl_Cairo.H resize-example5a.o: ../FL/fl_casts.H resize-example5a.o: ../FL/fl_config.h resize-example5a.o: ../FL/Fl_Double_Window.H resize-example5a.o: ../FL/Fl_Export.H resize-example5a.o: ../FL/Fl_Group.H resize-example5a.o: ../FL/Fl_Image.H resize-example5a.o: ../FL/fl_types.h resize-example5a.o: ../FL/fl_utf8.h resize-example5a.o: ../FL/Fl_Widget.H resize-example5a.o: ../FL/Fl_Window.H resize-example5a.o: ../FL/platform_types.h resize-example5a.o: resize-arrows.h resize-example5b.o: ../FL/Enumerations.H resize-example5b.o: ../FL/Fl.H resize-example5b.o: ../FL/fl_attr.h resize-example5b.o: ../FL/Fl_Bitmap.H resize-example5b.o: ../FL/Fl_Box.H resize-example5b.o: ../FL/Fl_Cairo.H resize-example5b.o: ../FL/fl_casts.H resize-example5b.o: ../FL/fl_config.h resize-example5b.o: ../FL/Fl_Double_Window.H resize-example5b.o: ../FL/Fl_Export.H resize-example5b.o: ../FL/Fl_Group.H resize-example5b.o: ../FL/Fl_Image.H resize-example5b.o: ../FL/fl_types.h resize-example5b.o: ../FL/fl_utf8.h resize-example5b.o: ../FL/Fl_Widget.H resize-example5b.o: ../FL/Fl_Window.H resize-example5b.o: ../FL/platform_types.h resize-example5b.o: resize-arrows.h resize-example5c.o: ../FL/Enumerations.H resize-example5c.o: ../FL/Fl.H resize-example5c.o: ../FL/fl_attr.h resize-example5c.o: ../FL/Fl_Bitmap.H resize-example5c.o: ../FL/Fl_Box.H resize-example5c.o: ../FL/Fl_Cairo.H resize-example5c.o: ../FL/fl_casts.H resize-example5c.o: ../FL/fl_config.h resize-example5c.o: ../FL/Fl_Double_Window.H resize-example5c.o: ../FL/Fl_Export.H resize-example5c.o: ../FL/Fl_Group.H resize-example5c.o: ../FL/Fl_Image.H resize-example5c.o: ../FL/fl_types.h resize-example5c.o: ../FL/fl_utf8.h resize-example5c.o: ../FL/Fl_Widget.H resize-example5c.o: ../FL/Fl_Window.H resize-example5c.o: ../FL/platform_types.h resize-example5c.o: resize-arrows.h resize.o: ../FL/Enumerations.H resize.o: ../FL/Fl.H resize.o: ../FL/fl_attr.h resize.o: ../FL/Fl_Bitmap.H resize.o: ../FL/Fl_Box.H resize.o: ../FL/Fl_Button.H resize.o: ../FL/Fl_Cairo.H resize.o: ../FL/fl_casts.H resize.o: ../FL/fl_config.h resize.o: ../FL/Fl_Double_Window.H resize.o: ../FL/Fl_Export.H resize.o: ../FL/Fl_Group.H resize.o: ../FL/Fl_Image.H resize.o: ../FL/fl_types.h resize.o: ../FL/fl_utf8.h resize.o: ../FL/Fl_Widget.H resize.o: ../FL/Fl_Window.H resize.o: ../FL/platform_types.h resize.o: resize.h resizebox.o: ../FL/Enumerations.H resizebox.o: ../FL/Fl.H resizebox.o: ../FL/fl_ask.H resizebox.o: ../FL/fl_attr.h resizebox.o: ../FL/Fl_Bitmap.H resizebox.o: ../FL/Fl_Box.H resizebox.o: ../FL/Fl_Button.H resizebox.o: ../FL/Fl_Cairo.H resizebox.o: ../FL/fl_casts.H resizebox.o: ../FL/fl_config.h resizebox.o: ../FL/Fl_Device.H resizebox.o: ../FL/Fl_Double_Window.H resizebox.o: ../FL/fl_draw.H resizebox.o: ../FL/Fl_Export.H resizebox.o: ../FL/Fl_Graphics_Driver.H resizebox.o: ../FL/Fl_Group.H resizebox.o: ../FL/Fl_Image.H resizebox.o: ../FL/fl_message.H resizebox.o: ../FL/Fl_Pixmap.H resizebox.o: ../FL/Fl_Plugin.H resizebox.o: ../FL/Fl_Preferences.H resizebox.o: ../FL/Fl_Radio_Button.H resizebox.o: ../FL/Fl_Rect.H resizebox.o: ../FL/Fl_RGB_Image.H resizebox.o: ../FL/fl_types.h resizebox.o: ../FL/fl_utf8.h resizebox.o: ../FL/Fl_Widget.H resizebox.o: ../FL/Fl_Window.H resizebox.o: ../FL/platform_types.h rotated_text.o: ../FL/Enumerations.H rotated_text.o: ../FL/Fl.H rotated_text.o: ../FL/fl_attr.h rotated_text.o: ../FL/Fl_Bitmap.H rotated_text.o: ../FL/Fl_Box.H rotated_text.o: ../FL/Fl_Button.H rotated_text.o: ../FL/Fl_Cairo.H rotated_text.o: ../FL/fl_casts.H rotated_text.o: ../FL/Fl_Choice.H rotated_text.o: ../FL/fl_config.h rotated_text.o: ../FL/Fl_Device.H rotated_text.o: ../FL/Fl_Double_Window.H rotated_text.o: ../FL/fl_draw.H rotated_text.o: ../FL/Fl_Export.H rotated_text.o: ../FL/Fl_Graphics_Driver.H rotated_text.o: ../FL/Fl_Group.H rotated_text.o: ../FL/Fl_Hor_Value_Slider.H rotated_text.o: ../FL/Fl_Image.H rotated_text.o: ../FL/Fl_Input.H rotated_text.o: ../FL/Fl_Input_.H rotated_text.o: ../FL/Fl_Menu_.H rotated_text.o: ../FL/Fl_Menu_Item.H rotated_text.o: ../FL/Fl_Multi_Label.H rotated_text.o: ../FL/Fl_Pixmap.H rotated_text.o: ../FL/Fl_Plugin.H rotated_text.o: ../FL/Fl_Preferences.H rotated_text.o: ../FL/Fl_Rect.H rotated_text.o: ../FL/Fl_RGB_Image.H rotated_text.o: ../FL/Fl_Slider.H rotated_text.o: ../FL/Fl_Toggle_Button.H rotated_text.o: ../FL/fl_types.h rotated_text.o: ../FL/fl_utf8.h rotated_text.o: ../FL/Fl_Valuator.H rotated_text.o: ../FL/Fl_Value_Slider.H rotated_text.o: ../FL/Fl_Widget.H rotated_text.o: ../FL/Fl_Window.H rotated_text.o: ../FL/platform_types.h scroll.o: ../FL/Enumerations.H scroll.o: ../FL/Fl.H scroll.o: ../FL/fl_attr.h scroll.o: ../FL/Fl_Bitmap.H scroll.o: ../FL/Fl_Box.H scroll.o: ../FL/Fl_Cairo.H scroll.o: ../FL/fl_casts.H scroll.o: ../FL/Fl_Choice.H scroll.o: ../FL/fl_config.h scroll.o: ../FL/Fl_Device.H scroll.o: ../FL/Fl_Double_Window.H scroll.o: ../FL/fl_draw.H scroll.o: ../FL/Fl_Export.H scroll.o: ../FL/Fl_Graphics_Driver.H scroll.o: ../FL/Fl_Group.H scroll.o: ../FL/Fl_Image.H scroll.o: ../FL/Fl_Light_Button.H scroll.o: ../FL/Fl_Menu_.H scroll.o: ../FL/Fl_Menu_Item.H scroll.o: ../FL/Fl_Multi_Label.H scroll.o: ../FL/Fl_Pixmap.H scroll.o: ../FL/Fl_Plugin.H scroll.o: ../FL/Fl_Preferences.H scroll.o: ../FL/Fl_Rect.H scroll.o: ../FL/Fl_RGB_Image.H scroll.o: ../FL/Fl_Scroll.H scroll.o: ../FL/Fl_Scrollbar.H scroll.o: ../FL/Fl_Slider.H scroll.o: ../FL/fl_types.h scroll.o: ../FL/fl_utf8.h scroll.o: ../FL/Fl_Valuator.H scroll.o: ../FL/Fl_Widget.H scroll.o: ../FL/Fl_Window.H scroll.o: ../FL/math.h scroll.o: ../FL/platform_types.h shape.o: ../config.h shape.o: ../FL/Enumerations.H shape.o: ../FL/Fl.H shape.o: ../FL/fl_attr.h shape.o: ../FL/Fl_Bitmap.H shape.o: ../FL/Fl_Cairo.H shape.o: ../FL/fl_casts.H shape.o: ../FL/fl_config.h shape.o: ../FL/Fl_Export.H shape.o: ../FL/Fl_Gl_Window.H shape.o: ../FL/Fl_Group.H shape.o: ../FL/Fl_Hor_Slider.H shape.o: ../FL/Fl_Image.H shape.o: ../FL/Fl_Slider.H shape.o: ../FL/fl_types.h shape.o: ../FL/fl_utf8.h shape.o: ../FL/Fl_Valuator.H shape.o: ../FL/Fl_Widget.H shape.o: ../FL/Fl_Window.H shape.o: ../FL/gl.h shape.o: ../FL/math.h shape.o: ../FL/platform_types.h subwindow.o: ../FL/Enumerations.H subwindow.o: ../FL/Fl.H subwindow.o: ../FL/fl_attr.h subwindow.o: ../FL/Fl_Box.H subwindow.o: ../FL/Fl_Button.H subwindow.o: ../FL/Fl_Cairo.H subwindow.o: ../FL/fl_casts.H subwindow.o: ../FL/fl_config.h subwindow.o: ../FL/Fl_Export.H subwindow.o: ../FL/Fl_Image.H subwindow.o: ../FL/Fl_Input.H subwindow.o: ../FL/Fl_Input_.H subwindow.o: ../FL/Fl_Menu_.H subwindow.o: ../FL/Fl_Menu_Button.H subwindow.o: ../FL/Fl_Menu_Item.H subwindow.o: ../FL/Fl_Multi_Label.H subwindow.o: ../FL/Fl_Toggle_Button.H subwindow.o: ../FL/fl_types.h subwindow.o: ../FL/fl_utf8.h subwindow.o: ../FL/Fl_Widget.H subwindow.o: ../FL/Fl_Window.H subwindow.o: ../FL/platform_types.h sudoku.o: ../config.h sudoku.o: ../FL/Enumerations.H sudoku.o: ../FL/filename.H sudoku.o: ../FL/Fl.H sudoku.o: ../FL/fl_ask.H sudoku.o: ../FL/fl_attr.h sudoku.o: ../FL/Fl_Bitmap.H sudoku.o: ../FL/Fl_Box.H sudoku.o: ../FL/Fl_Button.H sudoku.o: ../FL/Fl_Cairo.H sudoku.o: ../FL/fl_casts.H sudoku.o: ../FL/fl_config.h sudoku.o: ../FL/Fl_Device.H sudoku.o: ../FL/Fl_Double_Window.H sudoku.o: ../FL/fl_draw.H sudoku.o: ../FL/Fl_Export.H sudoku.o: ../FL/Fl_Graphics_Driver.H sudoku.o: ../FL/Fl_Group.H sudoku.o: ../FL/Fl_Help_Dialog.H sudoku.o: ../FL/Fl_Help_View.H sudoku.o: ../FL/Fl_Image.H sudoku.o: ../FL/Fl_Image_Surface.H sudoku.o: ../FL/Fl_Input.H sudoku.o: ../FL/Fl_Input_.H sudoku.o: ../FL/Fl_Menu_.H sudoku.o: ../FL/Fl_Menu_Bar.H sudoku.o: ../FL/Fl_Menu_Item.H sudoku.o: ../FL/Fl_Multi_Label.H sudoku.o: ../FL/Fl_Pixmap.H sudoku.o: ../FL/Fl_Plugin.H sudoku.o: ../FL/Fl_Preferences.H sudoku.o: ../FL/Fl_Rect.H sudoku.o: ../FL/Fl_RGB_Image.H sudoku.o: ../FL/Fl_Scrollbar.H sudoku.o: ../FL/Fl_Shared_Image.H sudoku.o: ../FL/Fl_Slider.H sudoku.o: ../FL/Fl_Sys_Menu_Bar.H sudoku.o: ../FL/fl_types.h sudoku.o: ../FL/fl_utf8.h sudoku.o: ../FL/Fl_Valuator.H sudoku.o: ../FL/Fl_Widget.H sudoku.o: ../FL/Fl_Widget_Surface.H sudoku.o: ../FL/Fl_Window.H sudoku.o: ../FL/math.h sudoku.o: ../FL/platform.H sudoku.o: ../FL/platform_types.h sudoku.o: ../FL/x11.H sudoku.o: pixmaps/sudoku.xbm symbols.o: ../FL/Enumerations.H symbols.o: ../FL/Fl.H symbols.o: ../FL/fl_attr.h symbols.o: ../FL/Fl_Bitmap.H symbols.o: ../FL/Fl_Box.H symbols.o: ../FL/Fl_Cairo.H symbols.o: ../FL/fl_casts.H symbols.o: ../FL/fl_config.h symbols.o: ../FL/Fl_Device.H symbols.o: ../FL/Fl_Double_Window.H symbols.o: ../FL/fl_draw.H symbols.o: ../FL/Fl_Export.H symbols.o: ../FL/Fl_Graphics_Driver.H symbols.o: ../FL/Fl_Group.H symbols.o: ../FL/Fl_Image.H symbols.o: ../FL/Fl_Pixmap.H symbols.o: ../FL/Fl_Plugin.H symbols.o: ../FL/Fl_Preferences.H symbols.o: ../FL/Fl_Rect.H symbols.o: ../FL/Fl_RGB_Image.H symbols.o: ../FL/Fl_Slider.H symbols.o: ../FL/fl_types.h symbols.o: ../FL/fl_utf8.h symbols.o: ../FL/Fl_Valuator.H symbols.o: ../FL/Fl_Value_Slider.H symbols.o: ../FL/Fl_Widget.H symbols.o: ../FL/Fl_Window.H symbols.o: ../FL/platform_types.h table.o: ../FL/Enumerations.H table.o: ../FL/Fl.H table.o: ../FL/fl_ask.H table.o: ../FL/fl_attr.h table.o: ../FL/Fl_Bitmap.H table.o: ../FL/Fl_Button.H table.o: ../FL/Fl_Cairo.H table.o: ../FL/fl_casts.H table.o: ../FL/Fl_Check_Button.H table.o: ../FL/Fl_Choice.H table.o: ../FL/fl_config.h table.o: ../FL/Fl_Device.H table.o: ../FL/fl_draw.H table.o: ../FL/Fl_Export.H table.o: ../FL/Fl_Graphics_Driver.H table.o: ../FL/Fl_Group.H table.o: ../FL/Fl_Image.H table.o: ../FL/Fl_Input.H table.o: ../FL/Fl_Input_.H table.o: ../FL/Fl_Light_Button.H table.o: ../FL/Fl_Menu_.H table.o: ../FL/Fl_Menu_Item.H table.o: ../FL/Fl_Multi_Label.H table.o: ../FL/Fl_Pixmap.H table.o: ../FL/Fl_Plugin.H table.o: ../FL/Fl_Preferences.H table.o: ../FL/Fl_Rect.H table.o: ../FL/Fl_RGB_Image.H table.o: ../FL/Fl_Scroll.H table.o: ../FL/Fl_Scrollbar.H table.o: ../FL/Fl_Slider.H table.o: ../FL/Fl_Table.H table.o: ../FL/Fl_Table_Row.H table.o: ../FL/Fl_Terminal.H table.o: ../FL/fl_types.h table.o: ../FL/fl_utf8.h table.o: ../FL/Fl_Valuator.H table.o: ../FL/Fl_Widget.H table.o: ../FL/Fl_Window.H table.o: ../FL/platform_types.h tabs.o: ../FL/Enumerations.H tabs.o: ../FL/Fl.H tabs.o: ../FL/fl_ask.H tabs.o: ../FL/fl_attr.h tabs.o: ../FL/Fl_Bitmap.H tabs.o: ../FL/Fl_Box.H tabs.o: ../FL/Fl_Button.H tabs.o: ../FL/Fl_Cairo.H tabs.o: ../FL/fl_casts.H tabs.o: ../FL/Fl_Choice.H tabs.o: ../FL/Fl_Clock.H tabs.o: ../FL/fl_config.h tabs.o: ../FL/Fl_Double_Window.H tabs.o: ../FL/Fl_Export.H tabs.o: ../FL/Fl_Group.H tabs.o: ../FL/Fl_Image.H tabs.o: ../FL/Fl_Input.H tabs.o: ../FL/Fl_Input_.H tabs.o: ../FL/Fl_Menu_.H tabs.o: ../FL/Fl_Menu_Item.H tabs.o: ../FL/Fl_Multi_Label.H tabs.o: ../FL/Fl_Return_Button.H tabs.o: ../FL/Fl_Tabs.H tabs.o: ../FL/fl_types.h tabs.o: ../FL/fl_utf8.h tabs.o: ../FL/Fl_Widget.H tabs.o: ../FL/Fl_Window.H tabs.o: ../FL/Fl_Wizard.H tabs.o: ../FL/platform_types.h tabs.o: tabs.h terminal.o: ../FL/Enumerations.H terminal.o: ../FL/Fl.H terminal.o: ../FL/fl_ask.H terminal.o: ../FL/fl_attr.h terminal.o: ../FL/Fl_Bitmap.H terminal.o: ../FL/Fl_Box.H terminal.o: ../FL/Fl_Button.H terminal.o: ../FL/Fl_Cairo.H terminal.o: ../FL/fl_casts.H terminal.o: ../FL/Fl_Check_Button.H terminal.o: ../FL/Fl_Choice.H terminal.o: ../FL/fl_config.h terminal.o: ../FL/Fl_Double_Window.H terminal.o: ../FL/Fl_Export.H terminal.o: ../FL/Fl_Group.H terminal.o: ../FL/Fl_Image.H terminal.o: ../FL/Fl_Input.H terminal.o: ../FL/Fl_Input_.H terminal.o: ../FL/Fl_Light_Button.H terminal.o: ../FL/Fl_Menu_.H terminal.o: ../FL/Fl_Menu_Item.H terminal.o: ../FL/Fl_Multi_Label.H terminal.o: ../FL/Fl_Rect.H terminal.o: ../FL/Fl_Repeat_Button.H terminal.o: ../FL/Fl_Scheme.H terminal.o: ../FL/Fl_Scheme_Choice.H terminal.o: ../FL/Fl_Scrollbar.H terminal.o: ../FL/Fl_Spinner.H terminal.o: ../FL/Fl_Terminal.H terminal.o: ../FL/fl_types.h terminal.o: ../FL/fl_utf8.h terminal.o: ../FL/Fl_Widget.H terminal.o: ../FL/Fl_Window.H terminal.o: ../FL/platform_types.h terminal.o: terminal.h threads.o: ../config.h threads.o: ../FL/Enumerations.H threads.o: ../FL/Fl.H threads.o: ../FL/fl_ask.H threads.o: ../FL/fl_attr.h threads.o: ../FL/Fl_Bitmap.H threads.o: ../FL/Fl_Browser.H threads.o: ../FL/Fl_Browser_.H threads.o: ../FL/Fl_Cairo.H threads.o: ../FL/fl_casts.H threads.o: ../FL/fl_config.h threads.o: ../FL/Fl_Double_Window.H threads.o: ../FL/Fl_Export.H threads.o: ../FL/Fl_Group.H threads.o: ../FL/Fl_Image.H threads.o: ../FL/Fl_Scrollbar.H threads.o: ../FL/Fl_Slider.H threads.o: ../FL/fl_types.h threads.o: ../FL/fl_utf8.h threads.o: ../FL/Fl_Valuator.H threads.o: ../FL/Fl_Value_Output.H threads.o: ../FL/Fl_Widget.H threads.o: ../FL/Fl_Window.H threads.o: ../FL/platform_types.h threads.o: threads.h tile.o: ../FL/Enumerations.H tile.o: ../FL/Fl.H tile.o: ../FL/fl_attr.h tile.o: ../FL/Fl_Bitmap.H tile.o: ../FL/Fl_Box.H tile.o: ../FL/Fl_Cairo.H tile.o: ../FL/fl_casts.H tile.o: ../FL/fl_config.h tile.o: ../FL/Fl_Double_Window.H tile.o: ../FL/Fl_Export.H tile.o: ../FL/Fl_Group.H tile.o: ../FL/Fl_Image.H tile.o: ../FL/Fl_Tile.H tile.o: ../FL/fl_types.h tile.o: ../FL/fl_utf8.h tile.o: ../FL/Fl_Widget.H tile.o: ../FL/Fl_Window.H tile.o: ../FL/platform_types.h tiled_image.o: ../config.h tiled_image.o: ../FL/Enumerations.H tiled_image.o: ../FL/Fl.H tiled_image.o: ../FL/fl_attr.h tiled_image.o: ../FL/Fl_Bitmap.H tiled_image.o: ../FL/Fl_Button.H tiled_image.o: ../FL/Fl_Cairo.H tiled_image.o: ../FL/fl_casts.H tiled_image.o: ../FL/fl_config.h tiled_image.o: ../FL/Fl_Double_Window.H tiled_image.o: ../FL/Fl_Export.H tiled_image.o: ../FL/Fl_Group.H tiled_image.o: ../FL/Fl_Image.H tiled_image.o: ../FL/Fl_Pixmap.H tiled_image.o: ../FL/Fl_Tiled_Image.H tiled_image.o: ../FL/fl_types.h tiled_image.o: ../FL/fl_utf8.h tiled_image.o: ../FL/Fl_Widget.H tiled_image.o: ../FL/Fl_Window.H tiled_image.o: ../FL/platform.H tiled_image.o: ../FL/platform_types.h tiled_image.o: ../FL/x11.H tiled_image.o: list_visuals.cxx tiled_image.o: pixmaps/tile.xpm tree.o: ../FL/Enumerations.H tree.o: ../FL/filename.H tree.o: ../FL/Fl.H tree.o: ../FL/fl_ask.H tree.o: ../FL/fl_attr.h tree.o: ../FL/Fl_Bitmap.H tree.o: ../FL/Fl_Box.H tree.o: ../FL/Fl_Browser.H tree.o: ../FL/Fl_Browser_.H tree.o: ../FL/Fl_Button.H tree.o: ../FL/Fl_Cairo.H tree.o: ../FL/fl_casts.H tree.o: ../FL/Fl_Check_Button.H tree.o: ../FL/Fl_Choice.H tree.o: ../FL/Fl_Color_Chooser.H tree.o: ../FL/fl_config.h tree.o: ../FL/Fl_Device.H tree.o: ../FL/Fl_Double_Window.H tree.o: ../FL/fl_draw.H tree.o: ../FL/Fl_Export.H tree.o: ../FL/Fl_File_Browser.H tree.o: ../FL/Fl_File_Chooser.H tree.o: ../FL/Fl_File_Icon.H tree.o: ../FL/Fl_File_Input.H tree.o: ../FL/Fl_Graphics_Driver.H tree.o: ../FL/Fl_Group.H tree.o: ../FL/Fl_Image.H tree.o: ../FL/Fl_Input.H tree.o: ../FL/Fl_Input_.H tree.o: ../FL/Fl_Light_Button.H tree.o: ../FL/Fl_Menu_.H tree.o: ../FL/Fl_Menu_Button.H tree.o: ../FL/Fl_Menu_Item.H tree.o: ../FL/fl_message.H tree.o: ../FL/Fl_Multi_Label.H tree.o: ../FL/Fl_Pixmap.H tree.o: ../FL/Fl_Plugin.H tree.o: ../FL/Fl_Preferences.H tree.o: ../FL/Fl_Rect.H tree.o: ../FL/Fl_Return_Button.H tree.o: ../FL/Fl_RGB_Image.H tree.o: ../FL/Fl_Scrollbar.H tree.o: ../FL/Fl_Slider.H tree.o: ../FL/Fl_Terminal.H tree.o: ../FL/Fl_Text_Buffer.H tree.o: ../FL/Fl_Text_Display.H tree.o: ../FL/Fl_Tile.H tree.o: ../FL/Fl_Tooltip.H tree.o: ../FL/Fl_Tree.H tree.o: ../FL/Fl_Tree_Item.H tree.o: ../FL/Fl_Tree_Item_Array.H tree.o: ../FL/Fl_Tree_Prefs.H tree.o: ../FL/fl_types.h tree.o: ../FL/fl_utf8.h tree.o: ../FL/Fl_Valuator.H tree.o: ../FL/Fl_Value_Input.H tree.o: ../FL/Fl_Value_Slider.H tree.o: ../FL/Fl_Widget.H tree.o: ../FL/Fl_Window.H tree.o: ../FL/platform_types.h tree.o: tree.h twowin.o: ../FL/Enumerations.H twowin.o: ../FL/Fl.H twowin.o: ../FL/fl_attr.h twowin.o: ../FL/Fl_Bitmap.H twowin.o: ../FL/Fl_Button.H twowin.o: ../FL/Fl_Cairo.H twowin.o: ../FL/fl_casts.H twowin.o: ../FL/fl_config.h twowin.o: ../FL/Fl_Double_Window.H twowin.o: ../FL/Fl_Export.H twowin.o: ../FL/Fl_Group.H twowin.o: ../FL/Fl_Image.H twowin.o: ../FL/Fl_Input.H twowin.o: ../FL/Fl_Input_.H twowin.o: ../FL/fl_types.h twowin.o: ../FL/fl_utf8.h twowin.o: ../FL/Fl_Widget.H twowin.o: ../FL/Fl_Window.H twowin.o: ../FL/platform_types.h unittests.o: ../FL/Enumerations.H unittests.o: ../FL/filename.H unittests.o: ../FL/Fl.H unittests.o: ../FL/fl_ask.H unittests.o: ../FL/fl_attr.h unittests.o: ../FL/Fl_Bitmap.H unittests.o: ../FL/Fl_Box.H unittests.o: ../FL/Fl_Browser.H unittests.o: ../FL/Fl_Browser_.H unittests.o: ../FL/Fl_Cairo.H unittests.o: ../FL/fl_casts.H unittests.o: ../FL/fl_config.h unittests.o: ../FL/Fl_Device.H unittests.o: ../FL/Fl_Double_Window.H unittests.o: ../FL/fl_draw.H unittests.o: ../FL/Fl_Export.H unittests.o: ../FL/Fl_Graphics_Driver.H unittests.o: ../FL/Fl_Group.H unittests.o: ../FL/Fl_Help_View.H unittests.o: ../FL/Fl_Hold_Browser.H unittests.o: ../FL/Fl_Image.H unittests.o: ../FL/Fl_Pixmap.H unittests.o: ../FL/Fl_Plugin.H unittests.o: ../FL/Fl_Preferences.H unittests.o: ../FL/Fl_Rect.H unittests.o: ../FL/Fl_RGB_Image.H unittests.o: ../FL/Fl_Scrollbar.H unittests.o: ../FL/Fl_Slider.H unittests.o: ../FL/fl_string_functions.h unittests.o: ../FL/Fl_Terminal.H unittests.o: ../FL/fl_types.h unittests.o: ../FL/fl_utf8.h unittests.o: ../FL/Fl_Valuator.H unittests.o: ../FL/Fl_Widget.H unittests.o: ../FL/Fl_Window.H unittests.o: ../FL/platform_types.h unittests.o: unittests.h unittest_about.o: ../FL/Enumerations.H unittest_about.o: ../FL/filename.H unittest_about.o: ../FL/Fl.H unittest_about.o: ../FL/fl_attr.h unittest_about.o: ../FL/Fl_Bitmap.H unittest_about.o: ../FL/Fl_Cairo.H unittest_about.o: ../FL/fl_casts.H unittest_about.o: ../FL/fl_config.h unittest_about.o: ../FL/Fl_Device.H unittest_about.o: ../FL/Fl_Double_Window.H unittest_about.o: ../FL/fl_draw.H unittest_about.o: ../FL/Fl_Export.H unittest_about.o: ../FL/Fl_Graphics_Driver.H unittest_about.o: ../FL/Fl_Group.H unittest_about.o: ../FL/Fl_Help_View.H unittest_about.o: ../FL/Fl_Image.H unittest_about.o: ../FL/Fl_Pixmap.H unittest_about.o: ../FL/Fl_Plugin.H unittest_about.o: ../FL/Fl_Preferences.H unittest_about.o: ../FL/Fl_Rect.H unittest_about.o: ../FL/Fl_RGB_Image.H unittest_about.o: ../FL/Fl_Scrollbar.H unittest_about.o: ../FL/Fl_Slider.H unittest_about.o: ../FL/fl_types.h unittest_about.o: ../FL/fl_utf8.h unittest_about.o: ../FL/Fl_Valuator.H unittest_about.o: ../FL/Fl_Widget.H unittest_about.o: ../FL/Fl_Window.H unittest_about.o: ../FL/platform_types.h unittest_about.o: unittests.h unittest_circles.o: ../config.h unittest_circles.o: ../FL/Enumerations.H unittest_circles.o: ../FL/Fl.H unittest_circles.o: ../FL/fl_attr.h unittest_circles.o: ../FL/Fl_Bitmap.H unittest_circles.o: ../FL/Fl_Box.H unittest_circles.o: ../FL/Fl_Cairo.H unittest_circles.o: ../FL/fl_casts.H unittest_circles.o: ../FL/fl_config.h unittest_circles.o: ../FL/Fl_Device.H unittest_circles.o: ../FL/Fl_Double_Window.H unittest_circles.o: ../FL/fl_draw.H unittest_circles.o: ../FL/Fl_Export.H unittest_circles.o: ../FL/Fl_Gl_Window.H unittest_circles.o: ../FL/Fl_Graphics_Driver.H unittest_circles.o: ../FL/Fl_Group.H unittest_circles.o: ../FL/Fl_Image.H unittest_circles.o: ../FL/Fl_Pixmap.H unittest_circles.o: ../FL/Fl_Plugin.H unittest_circles.o: ../FL/Fl_Preferences.H unittest_circles.o: ../FL/Fl_Rect.H unittest_circles.o: ../FL/Fl_RGB_Image.H unittest_circles.o: ../FL/fl_types.h unittest_circles.o: ../FL/fl_utf8.h unittest_circles.o: ../FL/Fl_Widget.H unittest_circles.o: ../FL/Fl_Window.H unittest_circles.o: ../FL/math.h unittest_circles.o: ../FL/platform_types.h unittest_circles.o: unittests.h unittest_complex_shapes.o: ../config.h unittest_complex_shapes.o: ../FL/Enumerations.H unittest_complex_shapes.o: ../FL/Fl.H unittest_complex_shapes.o: ../FL/fl_attr.h unittest_complex_shapes.o: ../FL/Fl_Bitmap.H unittest_complex_shapes.o: ../FL/Fl_Box.H unittest_complex_shapes.o: ../FL/Fl_Cairo.H unittest_complex_shapes.o: ../FL/fl_casts.H unittest_complex_shapes.o: ../FL/fl_config.h unittest_complex_shapes.o: ../FL/Fl_Device.H unittest_complex_shapes.o: ../FL/Fl_Dial.H unittest_complex_shapes.o: ../FL/Fl_Double_Window.H unittest_complex_shapes.o: ../FL/fl_draw.H unittest_complex_shapes.o: ../FL/Fl_Export.H unittest_complex_shapes.o: ../FL/Fl_Gl_Window.H unittest_complex_shapes.o: ../FL/Fl_Graphics_Driver.H unittest_complex_shapes.o: ../FL/Fl_Group.H unittest_complex_shapes.o: ../FL/Fl_Hor_Value_Slider.H unittest_complex_shapes.o: ../FL/Fl_Image.H unittest_complex_shapes.o: ../FL/Fl_Pixmap.H unittest_complex_shapes.o: ../FL/Fl_Plugin.H unittest_complex_shapes.o: ../FL/Fl_Positioner.H unittest_complex_shapes.o: ../FL/Fl_Preferences.H unittest_complex_shapes.o: ../FL/Fl_Rect.H unittest_complex_shapes.o: ../FL/Fl_RGB_Image.H unittest_complex_shapes.o: ../FL/Fl_Slider.H unittest_complex_shapes.o: ../FL/fl_types.h unittest_complex_shapes.o: ../FL/fl_utf8.h unittest_complex_shapes.o: ../FL/Fl_Valuator.H unittest_complex_shapes.o: ../FL/Fl_Value_Slider.H unittest_complex_shapes.o: ../FL/Fl_Widget.H unittest_complex_shapes.o: ../FL/Fl_Window.H unittest_complex_shapes.o: ../FL/platform_types.h unittest_complex_shapes.o: unittests.h unittest_core.o: ../FL/Enumerations.H unittest_core.o: ../FL/filename.H unittest_core.o: ../FL/Fl.H unittest_core.o: ../FL/fl_attr.h unittest_core.o: ../FL/Fl_Bitmap.H unittest_core.o: ../FL/Fl_Button.H unittest_core.o: ../FL/Fl_Cairo.H unittest_core.o: ../FL/fl_callback_macros.H unittest_core.o: ../FL/fl_casts.H unittest_core.o: ../FL/fl_config.h unittest_core.o: ../FL/Fl_Double_Window.H unittest_core.o: ../FL/Fl_Export.H unittest_core.o: ../FL/Fl_Group.H unittest_core.o: ../FL/Fl_Image.H unittest_core.o: ../FL/Fl_Preferences.H unittest_core.o: ../FL/Fl_Rect.H unittest_core.o: ../FL/Fl_Scrollbar.H unittest_core.o: ../FL/Fl_Terminal.H unittest_core.o: ../FL/fl_types.h unittest_core.o: ../FL/fl_utf8.h unittest_core.o: ../FL/Fl_Widget.H unittest_core.o: ../FL/Fl_Window.H unittest_core.o: ../FL/platform_types.h unittest_core.o: ../src/Fl_String.H unittest_core.o: unittests.h unittest_fast_shapes.o: ../config.h unittest_fast_shapes.o: ../FL/Enumerations.H unittest_fast_shapes.o: ../FL/Fl.H unittest_fast_shapes.o: ../FL/fl_attr.h unittest_fast_shapes.o: ../FL/Fl_Bitmap.H unittest_fast_shapes.o: ../FL/Fl_Box.H unittest_fast_shapes.o: ../FL/Fl_Cairo.H unittest_fast_shapes.o: ../FL/fl_casts.H unittest_fast_shapes.o: ../FL/fl_config.h unittest_fast_shapes.o: ../FL/Fl_Device.H unittest_fast_shapes.o: ../FL/Fl_Double_Window.H unittest_fast_shapes.o: ../FL/fl_draw.H unittest_fast_shapes.o: ../FL/Fl_Export.H unittest_fast_shapes.o: ../FL/Fl_Gl_Window.H unittest_fast_shapes.o: ../FL/Fl_Graphics_Driver.H unittest_fast_shapes.o: ../FL/Fl_Group.H unittest_fast_shapes.o: ../FL/Fl_Image.H unittest_fast_shapes.o: ../FL/Fl_Pixmap.H unittest_fast_shapes.o: ../FL/Fl_Plugin.H unittest_fast_shapes.o: ../FL/Fl_Preferences.H unittest_fast_shapes.o: ../FL/Fl_Rect.H unittest_fast_shapes.o: ../FL/Fl_RGB_Image.H unittest_fast_shapes.o: ../FL/fl_types.h unittest_fast_shapes.o: ../FL/fl_utf8.h unittest_fast_shapes.o: ../FL/Fl_Widget.H unittest_fast_shapes.o: ../FL/Fl_Window.H unittest_fast_shapes.o: ../FL/platform_types.h unittest_fast_shapes.o: unittests.h unittest_images.o: ../FL/Enumerations.H unittest_images.o: ../FL/Fl.H unittest_images.o: ../FL/fl_attr.h unittest_images.o: ../FL/Fl_Bitmap.H unittest_images.o: ../FL/Fl_Button.H unittest_images.o: ../FL/Fl_Cairo.H unittest_images.o: ../FL/fl_casts.H unittest_images.o: ../FL/Fl_Check_Button.H unittest_images.o: ../FL/fl_config.h unittest_images.o: ../FL/Fl_Device.H unittest_images.o: ../FL/Fl_Double_Window.H unittest_images.o: ../FL/fl_draw.H unittest_images.o: ../FL/Fl_Export.H unittest_images.o: ../FL/Fl_Graphics_Driver.H unittest_images.o: ../FL/Fl_Group.H unittest_images.o: ../FL/Fl_Image.H unittest_images.o: ../FL/Fl_Light_Button.H unittest_images.o: ../FL/Fl_Pixmap.H unittest_images.o: ../FL/Fl_Plugin.H unittest_images.o: ../FL/Fl_Preferences.H unittest_images.o: ../FL/Fl_Radio_Button.H unittest_images.o: ../FL/Fl_Rect.H unittest_images.o: ../FL/Fl_RGB_Image.H unittest_images.o: ../FL/fl_types.h unittest_images.o: ../FL/fl_utf8.h unittest_images.o: ../FL/Fl_Widget.H unittest_images.o: ../FL/Fl_Window.H unittest_images.o: ../FL/platform_types.h unittest_images.o: unittests.h unittest_points.o: ../config.h unittest_points.o: ../FL/Enumerations.H unittest_points.o: ../FL/Fl.H unittest_points.o: ../FL/fl_attr.h unittest_points.o: ../FL/Fl_Bitmap.H unittest_points.o: ../FL/Fl_Box.H unittest_points.o: ../FL/Fl_Cairo.H unittest_points.o: ../FL/fl_casts.H unittest_points.o: ../FL/fl_config.h unittest_points.o: ../FL/Fl_Device.H unittest_points.o: ../FL/Fl_Double_Window.H unittest_points.o: ../FL/fl_draw.H unittest_points.o: ../FL/Fl_Export.H unittest_points.o: ../FL/Fl_Gl_Window.H unittest_points.o: ../FL/Fl_Graphics_Driver.H unittest_points.o: ../FL/Fl_Group.H unittest_points.o: ../FL/Fl_Image.H unittest_points.o: ../FL/Fl_Pixmap.H unittest_points.o: ../FL/Fl_Plugin.H unittest_points.o: ../FL/Fl_Preferences.H unittest_points.o: ../FL/Fl_Rect.H unittest_points.o: ../FL/Fl_RGB_Image.H unittest_points.o: ../FL/fl_types.h unittest_points.o: ../FL/fl_utf8.h unittest_points.o: ../FL/Fl_Widget.H unittest_points.o: ../FL/Fl_Window.H unittest_points.o: ../FL/platform_types.h unittest_points.o: unittests.h unittest_schemes.o: ../FL/Enumerations.H unittest_schemes.o: ../FL/Fl.H unittest_schemes.o: ../FL/Fl_Adjuster.H unittest_schemes.o: ../FL/fl_attr.h unittest_schemes.o: ../FL/Fl_Bitmap.H unittest_schemes.o: ../FL/Fl_Box.H unittest_schemes.o: ../FL/Fl_Button.H unittest_schemes.o: ../FL/Fl_Cairo.H unittest_schemes.o: ../FL/fl_casts.H unittest_schemes.o: ../FL/Fl_Check_Button.H unittest_schemes.o: ../FL/Fl_Choice.H unittest_schemes.o: ../FL/Fl_Clock.H unittest_schemes.o: ../FL/fl_config.h unittest_schemes.o: ../FL/Fl_Counter.H unittest_schemes.o: ../FL/Fl_Device.H unittest_schemes.o: ../FL/Fl_Double_Window.H unittest_schemes.o: ../FL/fl_draw.H unittest_schemes.o: ../FL/Fl_Export.H unittest_schemes.o: ../FL/Fl_File_Input.H unittest_schemes.o: ../FL/Fl_Graphics_Driver.H unittest_schemes.o: ../FL/Fl_Group.H unittest_schemes.o: ../FL/Fl_Image.H unittest_schemes.o: ../FL/Fl_Input.H unittest_schemes.o: ../FL/Fl_Input_.H unittest_schemes.o: ../FL/Fl_Light_Button.H unittest_schemes.o: ../FL/Fl_Menu_.H unittest_schemes.o: ../FL/Fl_Menu_Item.H unittest_schemes.o: ../FL/Fl_Multi_Label.H unittest_schemes.o: ../FL/Fl_Output.H unittest_schemes.o: ../FL/Fl_Pixmap.H unittest_schemes.o: ../FL/Fl_Plugin.H unittest_schemes.o: ../FL/Fl_Preferences.H unittest_schemes.o: ../FL/Fl_Progress.H unittest_schemes.o: ../FL/Fl_Radio_Round_Button.H unittest_schemes.o: ../FL/Fl_Rect.H unittest_schemes.o: ../FL/Fl_RGB_Image.H unittest_schemes.o: ../FL/Fl_Roller.H unittest_schemes.o: ../FL/Fl_Round_Button.H unittest_schemes.o: ../FL/Fl_Scheme.H unittest_schemes.o: ../FL/Fl_Scheme_Choice.H unittest_schemes.o: ../FL/Fl_Scrollbar.H unittest_schemes.o: ../FL/Fl_Slider.H unittest_schemes.o: ../FL/Fl_Tabs.H unittest_schemes.o: ../FL/Fl_Text_Buffer.H unittest_schemes.o: ../FL/Fl_Text_Display.H unittest_schemes.o: ../FL/Fl_Text_Editor.H unittest_schemes.o: ../FL/fl_types.h unittest_schemes.o: ../FL/fl_utf8.h unittest_schemes.o: ../FL/Fl_Valuator.H unittest_schemes.o: ../FL/Fl_Value_Input.H unittest_schemes.o: ../FL/Fl_Value_Output.H unittest_schemes.o: ../FL/Fl_Value_Slider.H unittest_schemes.o: ../FL/Fl_Widget.H unittest_schemes.o: ../FL/Fl_Window.H unittest_schemes.o: ../FL/platform_types.h unittest_schemes.o: unittests.h unittest_scrollbarsize.o: ../FL/Enumerations.H unittest_scrollbarsize.o: ../FL/Fl.H unittest_scrollbarsize.o: ../FL/fl_attr.h unittest_scrollbarsize.o: ../FL/Fl_Bitmap.H unittest_scrollbarsize.o: ../FL/Fl_Box.H unittest_scrollbarsize.o: ../FL/Fl_Browser.H unittest_scrollbarsize.o: ../FL/Fl_Browser_.H unittest_scrollbarsize.o: ../FL/Fl_Cairo.H unittest_scrollbarsize.o: ../FL/fl_casts.H unittest_scrollbarsize.o: ../FL/fl_config.h unittest_scrollbarsize.o: ../FL/Fl_Device.H unittest_scrollbarsize.o: ../FL/Fl_Double_Window.H unittest_scrollbarsize.o: ../FL/fl_draw.H unittest_scrollbarsize.o: ../FL/Fl_Export.H unittest_scrollbarsize.o: ../FL/Fl_Graphics_Driver.H unittest_scrollbarsize.o: ../FL/Fl_Group.H unittest_scrollbarsize.o: ../FL/Fl_Image.H unittest_scrollbarsize.o: ../FL/Fl_Pixmap.H unittest_scrollbarsize.o: ../FL/Fl_Plugin.H unittest_scrollbarsize.o: ../FL/Fl_Preferences.H unittest_scrollbarsize.o: ../FL/Fl_Rect.H unittest_scrollbarsize.o: ../FL/Fl_RGB_Image.H unittest_scrollbarsize.o: ../FL/Fl_Scroll.H unittest_scrollbarsize.o: ../FL/Fl_Scrollbar.H unittest_scrollbarsize.o: ../FL/Fl_Slider.H unittest_scrollbarsize.o: ../FL/Fl_Table.H unittest_scrollbarsize.o: ../FL/Fl_Terminal.H unittest_scrollbarsize.o: ../FL/Fl_Text_Buffer.H unittest_scrollbarsize.o: ../FL/Fl_Text_Display.H unittest_scrollbarsize.o: ../FL/Fl_Tree.H unittest_scrollbarsize.o: ../FL/Fl_Tree_Item.H unittest_scrollbarsize.o: ../FL/Fl_Tree_Item_Array.H unittest_scrollbarsize.o: ../FL/Fl_Tree_Prefs.H unittest_scrollbarsize.o: ../FL/fl_types.h unittest_scrollbarsize.o: ../FL/fl_utf8.h unittest_scrollbarsize.o: ../FL/Fl_Valuator.H unittest_scrollbarsize.o: ../FL/Fl_Value_Slider.H unittest_scrollbarsize.o: ../FL/Fl_Widget.H unittest_scrollbarsize.o: ../FL/Fl_Window.H unittest_scrollbarsize.o: ../FL/platform_types.h unittest_scrollbarsize.o: unittests.h unittest_symbol.o: ../FL/Enumerations.H unittest_symbol.o: ../FL/Fl.H unittest_symbol.o: ../FL/fl_attr.h unittest_symbol.o: ../FL/Fl_Bitmap.H unittest_symbol.o: ../FL/Fl_Box.H unittest_symbol.o: ../FL/Fl_Cairo.H unittest_symbol.o: ../FL/fl_casts.H unittest_symbol.o: ../FL/fl_config.h unittest_symbol.o: ../FL/Fl_Device.H unittest_symbol.o: ../FL/Fl_Double_Window.H unittest_symbol.o: ../FL/fl_draw.H unittest_symbol.o: ../FL/Fl_Export.H unittest_symbol.o: ../FL/Fl_Graphics_Driver.H unittest_symbol.o: ../FL/Fl_Group.H unittest_symbol.o: ../FL/Fl_Image.H unittest_symbol.o: ../FL/Fl_Pixmap.H unittest_symbol.o: ../FL/Fl_Plugin.H unittest_symbol.o: ../FL/Fl_Preferences.H unittest_symbol.o: ../FL/Fl_Rect.H unittest_symbol.o: ../FL/Fl_RGB_Image.H unittest_symbol.o: ../FL/fl_types.h unittest_symbol.o: ../FL/fl_utf8.h unittest_symbol.o: ../FL/Fl_Widget.H unittest_symbol.o: ../FL/Fl_Window.H unittest_symbol.o: ../FL/platform_types.h unittest_symbol.o: unittests.h unittest_terminal.o: ../FL/Enumerations.H unittest_terminal.o: ../FL/Fl.H unittest_terminal.o: ../FL/fl_attr.h unittest_terminal.o: ../FL/Fl_Bitmap.H unittest_terminal.o: ../FL/Fl_Cairo.H unittest_terminal.o: ../FL/fl_casts.H unittest_terminal.o: ../FL/fl_config.h unittest_terminal.o: ../FL/Fl_Double_Window.H unittest_terminal.o: ../FL/Fl_Export.H unittest_terminal.o: ../FL/Fl_Group.H unittest_terminal.o: ../FL/Fl_Image.H unittest_terminal.o: ../FL/Fl_Rect.H unittest_terminal.o: ../FL/Fl_Scrollbar.H unittest_terminal.o: ../FL/Fl_Terminal.H unittest_terminal.o: ../FL/fl_types.h unittest_terminal.o: ../FL/fl_utf8.h unittest_terminal.o: ../FL/Fl_Widget.H unittest_terminal.o: ../FL/Fl_Window.H unittest_terminal.o: ../FL/platform_types.h unittest_terminal.o: unittests.h unittest_text.o: ../FL/Enumerations.H unittest_text.o: ../FL/Fl.H unittest_text.o: ../FL/fl_attr.h unittest_text.o: ../FL/Fl_Bitmap.H unittest_text.o: ../FL/Fl_Box.H unittest_text.o: ../FL/Fl_Button.H unittest_text.o: ../FL/Fl_Cairo.H unittest_text.o: ../FL/fl_casts.H unittest_text.o: ../FL/Fl_Check_Button.H unittest_text.o: ../FL/fl_config.h unittest_text.o: ../FL/Fl_Device.H unittest_text.o: ../FL/Fl_Double_Window.H unittest_text.o: ../FL/fl_draw.H unittest_text.o: ../FL/Fl_Export.H unittest_text.o: ../FL/Fl_Graphics_Driver.H unittest_text.o: ../FL/Fl_Group.H unittest_text.o: ../FL/Fl_Image.H unittest_text.o: ../FL/Fl_Light_Button.H unittest_text.o: ../FL/Fl_Pixmap.H unittest_text.o: ../FL/Fl_Plugin.H unittest_text.o: ../FL/Fl_Preferences.H unittest_text.o: ../FL/Fl_Rect.H unittest_text.o: ../FL/Fl_RGB_Image.H unittest_text.o: ../FL/fl_types.h unittest_text.o: ../FL/fl_utf8.h unittest_text.o: ../FL/Fl_Widget.H unittest_text.o: ../FL/Fl_Window.H unittest_text.o: ../FL/platform_types.h unittest_text.o: unittests.h unittest_unicode.o: ../FL/Enumerations.H unittest_unicode.o: ../FL/Fl.H unittest_unicode.o: ../FL/fl_attr.h unittest_unicode.o: ../FL/Fl_Bitmap.H unittest_unicode.o: ../FL/Fl_Cairo.H unittest_unicode.o: ../FL/fl_casts.H unittest_unicode.o: ../FL/Fl_Choice.H unittest_unicode.o: ../FL/fl_config.h unittest_unicode.o: ../FL/Fl_Device.H unittest_unicode.o: ../FL/Fl_Double_Window.H unittest_unicode.o: ../FL/fl_draw.H unittest_unicode.o: ../FL/Fl_Export.H unittest_unicode.o: ../FL/Fl_Graphics_Driver.H unittest_unicode.o: ../FL/Fl_Group.H unittest_unicode.o: ../FL/Fl_Hor_Value_Slider.H unittest_unicode.o: ../FL/Fl_Image.H unittest_unicode.o: ../FL/Fl_Input.H unittest_unicode.o: ../FL/Fl_Input_.H unittest_unicode.o: ../FL/Fl_Menu_.H unittest_unicode.o: ../FL/Fl_Menu_Item.H unittest_unicode.o: ../FL/Fl_Multiline_Input.H unittest_unicode.o: ../FL/Fl_Multi_Label.H unittest_unicode.o: ../FL/Fl_Pixmap.H unittest_unicode.o: ../FL/Fl_Plugin.H unittest_unicode.o: ../FL/Fl_Preferences.H unittest_unicode.o: ../FL/Fl_Rect.H unittest_unicode.o: ../FL/Fl_RGB_Image.H unittest_unicode.o: ../FL/Fl_Scrollbar.H unittest_unicode.o: ../FL/Fl_Slider.H unittest_unicode.o: ../FL/Fl_Text_Buffer.H unittest_unicode.o: ../FL/Fl_Text_Display.H unittest_unicode.o: ../FL/fl_types.h unittest_unicode.o: ../FL/fl_utf8.h unittest_unicode.o: ../FL/Fl_Valuator.H unittest_unicode.o: ../FL/Fl_Value_Slider.H unittest_unicode.o: ../FL/Fl_Widget.H unittest_unicode.o: ../FL/Fl_Window.H unittest_unicode.o: ../FL/platform_types.h unittest_unicode.o: unittests.h unittest_viewport.o: ../FL/Enumerations.H unittest_viewport.o: ../FL/Fl.H unittest_viewport.o: ../FL/fl_attr.h unittest_viewport.o: ../FL/Fl_Bitmap.H unittest_viewport.o: ../FL/Fl_Box.H unittest_viewport.o: ../FL/Fl_Cairo.H unittest_viewport.o: ../FL/fl_casts.H unittest_viewport.o: ../FL/fl_config.h unittest_viewport.o: ../FL/Fl_Device.H unittest_viewport.o: ../FL/Fl_Double_Window.H unittest_viewport.o: ../FL/fl_draw.H unittest_viewport.o: ../FL/Fl_Export.H unittest_viewport.o: ../FL/Fl_Graphics_Driver.H unittest_viewport.o: ../FL/Fl_Group.H unittest_viewport.o: ../FL/Fl_Image.H unittest_viewport.o: ../FL/Fl_Pixmap.H unittest_viewport.o: ../FL/Fl_Plugin.H unittest_viewport.o: ../FL/Fl_Preferences.H unittest_viewport.o: ../FL/Fl_Rect.H unittest_viewport.o: ../FL/Fl_RGB_Image.H unittest_viewport.o: ../FL/fl_types.h unittest_viewport.o: ../FL/fl_utf8.h unittest_viewport.o: ../FL/Fl_Widget.H unittest_viewport.o: ../FL/Fl_Window.H unittest_viewport.o: ../FL/platform_types.h unittest_viewport.o: unittests.h utf8.o: ../FL/Enumerations.H utf8.o: ../FL/Fl.H utf8.o: ../FL/fl_attr.h utf8.o: ../FL/Fl_Bitmap.H utf8.o: ../FL/Fl_Box.H utf8.o: ../FL/Fl_Browser.H utf8.o: ../FL/Fl_Browser_.H utf8.o: ../FL/Fl_Button.H utf8.o: ../FL/Fl_Cairo.H utf8.o: ../FL/fl_casts.H utf8.o: ../FL/Fl_Check_Button.H utf8.o: ../FL/Fl_Choice.H utf8.o: ../FL/fl_config.h utf8.o: ../FL/Fl_Device.H utf8.o: ../FL/Fl_Double_Window.H utf8.o: ../FL/fl_draw.H utf8.o: ../FL/Fl_Export.H utf8.o: ../FL/Fl_Graphics_Driver.H utf8.o: ../FL/Fl_Group.H utf8.o: ../FL/Fl_Hold_Browser.H utf8.o: ../FL/Fl_Image.H utf8.o: ../FL/Fl_Input.H utf8.o: ../FL/Fl_Input_.H utf8.o: ../FL/Fl_Light_Button.H utf8.o: ../FL/Fl_Menu_.H utf8.o: ../FL/Fl_Menu_Item.H utf8.o: ../FL/Fl_Multi_Label.H utf8.o: ../FL/Fl_Output.H utf8.o: ../FL/Fl_Pixmap.H utf8.o: ../FL/Fl_Plugin.H utf8.o: ../FL/Fl_Preferences.H utf8.o: ../FL/Fl_Rect.H utf8.o: ../FL/Fl_RGB_Image.H utf8.o: ../FL/Fl_Scroll.H utf8.o: ../FL/Fl_Scrollbar.H utf8.o: ../FL/Fl_Slider.H utf8.o: ../FL/fl_string_functions.h utf8.o: ../FL/Fl_Tile.H utf8.o: ../FL/fl_types.h utf8.o: ../FL/fl_utf8.h utf8.o: ../FL/Fl_Valuator.H utf8.o: ../FL/Fl_Value_Output.H utf8.o: ../FL/Fl_Widget.H utf8.o: ../FL/Fl_Window.H utf8.o: ../FL/platform_types.h valuators.o: ../FL/Enumerations.H valuators.o: ../FL/Fl.H valuators.o: ../FL/Fl_Adjuster.H valuators.o: ../FL/fl_attr.h valuators.o: ../FL/Fl_Bitmap.H valuators.o: ../FL/Fl_Box.H valuators.o: ../FL/Fl_Button.H valuators.o: ../FL/Fl_Cairo.H valuators.o: ../FL/fl_casts.H valuators.o: ../FL/fl_config.h valuators.o: ../FL/Fl_Counter.H valuators.o: ../FL/Fl_Dial.H valuators.o: ../FL/Fl_Double_Window.H valuators.o: ../FL/Fl_Export.H valuators.o: ../FL/Fl_Group.H valuators.o: ../FL/Fl_Image.H valuators.o: ../FL/Fl_Input.H valuators.o: ../FL/Fl_Input_.H valuators.o: ../FL/Fl_Rect.H valuators.o: ../FL/Fl_Repeat_Button.H valuators.o: ../FL/Fl_Roller.H valuators.o: ../FL/Fl_Scrollbar.H valuators.o: ../FL/Fl_Slider.H valuators.o: ../FL/Fl_Spinner.H valuators.o: ../FL/Fl_Terminal.H valuators.o: ../FL/fl_types.h valuators.o: ../FL/fl_utf8.h valuators.o: ../FL/Fl_Valuator.H valuators.o: ../FL/Fl_Value_Input.H valuators.o: ../FL/Fl_Value_Output.H valuators.o: ../FL/Fl_Value_Slider.H valuators.o: ../FL/Fl_Widget.H valuators.o: ../FL/Fl_Window.H valuators.o: ../FL/platform_types.h valuators.o: valuators.h windowfocus.o: ../FL/Enumerations.H windowfocus.o: ../FL/Fl.H windowfocus.o: ../FL/fl_attr.h windowfocus.o: ../FL/Fl_Bitmap.H windowfocus.o: ../FL/Fl_Box.H windowfocus.o: ../FL/Fl_Cairo.H windowfocus.o: ../FL/fl_casts.H windowfocus.o: ../FL/fl_config.h windowfocus.o: ../FL/Fl_Double_Window.H windowfocus.o: ../FL/Fl_Export.H windowfocus.o: ../FL/Fl_Group.H windowfocus.o: ../FL/Fl_Image.H windowfocus.o: ../FL/Fl_Input.H windowfocus.o: ../FL/Fl_Input_.H windowfocus.o: ../FL/fl_types.h windowfocus.o: ../FL/fl_utf8.h windowfocus.o: ../FL/Fl_Widget.H windowfocus.o: ../FL/Fl_Window.H windowfocus.o: ../FL/platform_types.h wizard.o: ../FL/Enumerations.H wizard.o: ../FL/Fl.H wizard.o: ../FL/fl_attr.h wizard.o: ../FL/Fl_Button.H wizard.o: ../FL/Fl_Cairo.H wizard.o: ../FL/fl_casts.H wizard.o: ../FL/fl_config.h wizard.o: ../FL/Fl_Export.H wizard.o: ../FL/Fl_Group.H wizard.o: ../FL/fl_types.h wizard.o: ../FL/fl_utf8.h wizard.o: ../FL/Fl_Widget.H wizard.o: ../FL/Fl_Window.H wizard.o: ../FL/Fl_Wizard.H wizard.o: ../FL/platform_types.h fltk-1.4.3/test/mac-resources/0000755000175000017500000000000015004135251016334 5ustar albrechtalbrechtfltk-1.4.3/test/mac-resources/sudoku.plist0000644000175000017500000000171015004135251020722 0ustar albrechtalbrecht CFBundleInfoDictionaryVersion 6.0 CFBundleExecutable sudoku CFBundleIdentifier org.fltk.sudoku CFBundleVersion 1.0 CFBundleDevelopmentRegion English NSHumanReadableCopyright Copyright 2005-2021 by Michael Sweet CFAppleHelpAnchor help CFBundleName sudoku CFBundlePackageType APPL CFBundleSignature FLSU CFBundleIconFile sudoku.icns CFBundleShortVersionString 1.0 CFBundleGetInfoString 1.0, Copyright 2005-2021 by Michael Sweet NSHighResolutionCapable fltk-1.4.3/test/mac-resources/editor.plist0000644000175000017500000000231215004135251020675 0ustar albrechtalbrecht CFBundleDevelopmentRegion English CFBundleDocumentTypes CFBundleTypeExtensions * CFBundleTypeName AllFiles CFBundleTypeRole Editor LSTypeIsPackage NSPersistentStoreTypeKey XML CFBundleExecutable editor CFBundleGetInfoString Part of the FLTK library. Please visit www.fltk.org. CFBundleIdentifier org.fltk.editor CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature FLTK CFBundleVersion 1.0 NSHumanReadableCopyright Copyright 1998-2024 by Bill Spitzak and others. NSHighResolutionCapable fltk-1.4.3/test/mac-resources/sudoku.icns0000644000175000017500000010415115004135251020526 0ustar albrechtalbrechticnsiICN#il32                        l8mkit32QYր.`LˀPÇ q4>q]z!6 Z݀j&DNbو҃ wCLsg!yGt[# BInX"@ܲȧ︗氐N86yx#ډBq;zu0-" Dr`0 wo/OKQ{&eԀv -߀P1|P ":?[ ˀ\_^3Gb =Axe w1L\Z8tb#>ESX# ; x~ǃ#؃)@"2~ ݅ 7~߈;7}QU.43 څ͇!m]3Ѐ P:7`݇ ۆÇ̀ʀ?† $95p:1ӆ ҄3$NA'+Ё݇6v~LԈoBzo&0։sz+CmӢ篔4eތ w Iu|IÇw@5 } W/EcUjaT Ɖg'QɍTX,$&. GڋxŒy"3֌U[%ލ3ڍLJw8i_kxN #~ZWk]À:8\Đ^D,M_ǀFlܑI G,Q{](jKԁDի@@@@ڲʌMoFNjUiąG x[ @ 'oy@r [Itk(ڈ'tq^:yH ˀ:|܁x57·†oۀW3χ-L ,ˀ گg&ˊlH{#ƀŅ IK܃! p Mʓ>QYր.`LˀPÇ q4>q]z!6 Z݀j&DNbو҃ wCLsg!yGt[# BInX"@ܲȧ︗氐N86yx#ډBq;zu0-" Dr`0 wo/OKQ{&eԀv -߀P1|P ":?[ ˀ\_^3Gb =Axe w1L\Z8tb#>ESX# ; x~ǃ#؃)@"2~ ݅ 7~߈;7}QU.43 څ͇!m]3Ѐ P:7`݇ ۆÇ̀ʀ?† $95p:1ӆ ҄3$NA'+Ё݇6v~LԈoBzo&0։sz+CmӢ篔4eތ w Iu|IÇw@5 } W/EcUjaT Ɖg'QɍTX,$&. GڋxŒy"3֌U[%ލ3ڍLJw8i_kxN #~ZWk]À:8\Đ^D,M_ǀFlܑI G,Q{](jKԁDի@@@@ڲʌMoFNjUiąG x[ @ 'oy@r [Itk(ڈ'tq^:yH ˀ:|܁x57·†oۀW3χ-L ,ˀ گg&ˊlH{#ƀŅ IK܃! p Mʓ>QYր.`LˀPÇ q4>q]z!6 Z݀j&DNbو҃ wCLsg!yGt[# BInX"@ܲȧ︗氐N86yx#ډBq;zu0-" Dr`0 wo/OKQ{&eԀv -߀P1|P ":?[ ˀ\_^3Gb =Axe w1L\Z8tb#>ESX# ; x~ǃ#؃)@"2~ ݅ 7~߈;7}QU.43 څ͇!m]3Ѐ P:7`݇ ۆÇ̀ʀ?† $95p:1ӆ ҄3$NA'+Ё݇6v~LԈoBzo&0։sz+CmӢ篔4eތ w Iu|IÇw@5 } W/EcUjaT Ɖg'QɍTX,$&. GڋxŒy"3֌U[%ލ3ڍLJw8i_kxN #~ZWk]À:8\Đ^D,M_ǀFlܑI G,Q{](jKԁDի@@t8mk@fltk-1.4.3/test/mac-resources/checkers.plist0000644000175000017500000000174415004135251021206 0ustar albrechtalbrecht CFBundleInfoDictionaryVersion 6.0 CFBundleExecutable checkers CFBundleIdentifier org.fltk.checkers CFBundleVersion 1.0 CFBundleDevelopmentRegion English NSHumanReadableCopyright Copyright 1997-2021 by Bill Spitzak and others CFAppleHelpAnchor help CFBundleName checkers CFBundlePackageType APPL CFBundleSignature FLCK CFBundleIconFile checkers.icns CFBundleShortVersionString 1.0 CFBundleGetInfoString 1.0, Copyright 1997-2021 by Bill Spitzak and others NSHighResolutionCapable fltk-1.4.3/test/mac-resources/blocks.plist0000644000175000017500000000171015004135251020665 0ustar albrechtalbrecht CFBundleInfoDictionaryVersion 6.0 CFBundleExecutable blocks CFBundleIdentifier org.fltk.blocks CFBundleVersion 1.0 CFBundleDevelopmentRegion English NSHumanReadableCopyright Copyright 2006-2021 by Michael Sweet CFAppleHelpAnchor help CFBundleName blocks CFBundlePackageType APPL CFBundleSignature BLKS CFBundleIconFile blocks.icns CFBundleShortVersionString 1.0 CFBundleGetInfoString 1.0, Copyright 2006-2021 by Michael Sweet NSHighResolutionCapable fltk-1.4.3/test/mac-resources/blocks.icns0000644000175000017500000014355115004135251020500 0ustar albrechtalbrechticnsiics#H????is32BᚉѾ¶˜wyBᝁ Ѿ$.1.Ӿ ¶K˜ ™vyD⛅'031ҾØ ❢>vxE Ҿҿ$/4. µ;šØ>vyDAvyG΋'031Ҿ'/41 Øp{=uyC&.2/>vxC=vxC(141'/4/ =uyC✣➁ &.2/ҿҾ ,ÙÙ>vxC=vxCᜏ̊(141'/4/ѿ µ Øo{s8mk~}||{zyxwvxICN#??????il32/ܵ.ְ̻̹²ѱʹ̱,³// ߵ/IswvyNڱ3ttyxx:2GHIKHM;̸Ѱ̼ þͰ.´0/ܵ.JrzvyO2ݶ2ְ5svyy|{>ٲ̻/=FCGIQ:ǽ°̹² ˶ѱʹѲ̺̱ ¾̱,³/.´2/uߵ/IswvyNLrvv{R(Ǟ'ڱ3ttyxx:9tvxzw>™2GHIKHM;1CJHJGN> ̸Ѱ̼þͰ~.´0 $(5ܷ4׳̼°͹ñҰ˺̳2õ5JtwwzO1ݵ06tuxxy;ر2FHJKLL=ʽ"ð ˸в˻¾˰-ó15ܷ41۵0ItwwxP׳ֲ5uszyz;̼ͻ2EGHL:°° ͹ñ̷°Ұ˺Ѳʻ̳¿˱2õ5.ó2JtwwzO1ݵ0 KsxvzS +ɠ*6tuxxy;ر9uvyzx?Ĝ2FHJKLL=ʽ2DJHLIM="ð˸в˻ ¾˰  -ó1 '+HrvuwN6uvw{|;2DGHKKN:JsvvyOIswvyO 6uvxyz<5tty;2FGJKMK<2GIJLJN<# HrvuwN4 ۶34ݷ36uvw{|;ղٳ2DGHKKN:λǽ±¯˸˶гʻг̺¿˱̲A0ó40´4JsvvyOIswvyO0߶/+Ơ*6uvxyz<5ttyL;رě2FGJKMK<2GIJLJN<©#ɿ˹ҳ˺̱.ó0(+l8mk~}||{zyxwvvutsrqpponmlvich#H??????????ih32 XִRU݁X ԰ Ǿ ķĺ Ź ºû»¸ ǹ Գ QʿW TYYܴT;bfgd=XYXeذ#kmnmqsnszy',KPNPORLSSV5ƻ¶'.,/.25499%öȀ÷    ùû «ԿɼҲ P̿X Xµ[#XִR 8_hfdjg?ZطUU݁X `\V[#԰#ikrousswts.׳#Ǿ5ILMLMNSUYX0#ķĺ&)+*.&+*4&ź¹#Ź ùĸ#ºû»¸  û «#ǹ տɺ#ԳľԴ QʿW Q˾X?TY W¶]YܴT;bffegd= >afhh?I¾¾EXYXe \g F˾Hذ#kmnmqsnszy'*loopspsryx/,KP NPORLSSV5.INGQRQRRW9ƻ¶'.,/.25499%,-/100,37; öȀ3÷     ùû( «(Կɼ*Ҳ) P̿X# BGXµ[ CH _׷Y \_ մ ȿ øĻ úĸ ¹û¹ö Ⱥ ¿Զ W˿^ [·`:bffefe<X׵T_eVX&jnmppsrrxy*ֱ+KMNPRTQTSW7Ҁ-2124497&ùĹúķú» Ȼ ÿѲ QʿX SĵZ#_׷YYصU:ceedeb= #\_WY^f#մұ#jonprqpsvy-#ȿɿ,JMKMNWQVQU6#øĻ¸û-.-.11585:%#úķúź ¹û¹öº¬ȺǺ¿ԶҳW˿^QɿY[·`Uô\:bffefe<X׵T >cfhgheAMÞH_eVX \g JL&jnmppsrrxy*ֱ+loop!spsrzy0+KMNPRTQTSW7Ҁ0KNQSRV8 ¹-212,4497&ùĹ,/.312.58;!úķ   +ú»  Ȼ ÿѲ QʿX FKSĵZGM:`deb= Xc &jqpontuuxx, ,ILMPOVHUQV3 .).012848:$    :bed<`eYe&jonppsrsxy*&llnnrtntzz),KLMOQTSURV6.JPOQPROTRW6.202335697&*1031487::&      :`deb=\طX[ٸW#XcZ\X]#&jqpontuuxx,Ѳ׳#,ILMPOVHUQV3ȿ#.).012848:$¸ļź¹#    úŻøŷ#ºĺú­ªƻԿȺѳӵUɿ[TʿZ!Xõ_Z·_:be]d<WٴTMI`eYeTXK̿L&jonppsxy*&llnnrtntzz)װ,KLMOQTSURV6.JPOQPROTRW6Ŧ.202335697&*1031487::&ļż (   Ķö+üĽ¹¹#éǺ#ľԲ QYFK!Tô[GLh8mk ~~}|{zzyxxvvvtstrqqooomlmkjkihiffgzit32ZC C*ʺ*CպC*ˍ*ƆؖCڀՀՂCƀڃڄƁمɣɁdžǁǺɀʂـǁɁǂ߀߀ǀʃɴʂʁɀʴƁʀʃƺƁƀ ƺǀ ʺ ˁƂ˺ˁ؁˺ƺǺ ƺƺǺ˂˺ǁǃغ ˺˂  ǰƺсCCǺ؁* Ǻр* C˺C* Ǻأ*CǺ˺ǣCDÂÀD-ì-1jj1DڻDy-φ-1݀ڃ͢ ~~y~yyy~D ڃڀD]~y~yy~~y~jрсυj]jjyjk~~y jy~kkkkπۀۂہ â1]jj[ ]k]]k]j[yQ[jj]k? ۀۀ Q[j]kOO]][Qj]OkOÂԀÀԀ̷??[?Q[?O?OO?O[Q[[]O]ԵõÄ õ̢?1?O?O?Q1Q1Q?O??OÃõÁ1?$? 1?1?11Q11Q1?πûûπÁ1$111?$?Ϳππ$$$11111$$ͿϿͿϻ$ 11111 фÀ1 ÷с÷÷ ÷ÿ ÷÷À  À÷À÷À ÷݁ìÀ÷сѷ÷ ÷À÷÷ÃÁс÷Á÷À ì1Á÷хDì÷ ѷ÷D÷рâ-÷ìÀ -D÷÷D-ÀѢ-DтDC C  I¹I*ʺ* ~f78ҹ8CպC $p II*ˍ *$ 88Ɔؖ~pp~~~ ́ўCڀՀՂC fpffpppp~ppp~~r rf I݅IƀڃڄƁr~~fpf~rrffp~r\r€݀݁Éمɣ$UfrrKr~pS~rr\r\\r\΃݃΂ӨɁdžǁǺU rFFrFKrUpSpfUr \\KπιɀʂـǁKUKF\KFF\K$S UrUKF\F\ ϹϹισϹιιɁǂ߀߀ǀ"FKK KF3G3F3FF7FFK$S$S$K77KF\F3ӄӼϹπʃɴʂʁɀ73G7K $$U7F 3GGҼüҼÀҼʴƁʀʃ3K33337KK $73G3üրÂƺƁƀ$333   7 773ùրց ƺǀ ʺ33  7F3̹ÁÆù ˁƂ  3¹ ¹̂˺ˁ  33 ¹€¹ ¹¹ù؁˺ ƺ  €Ǻ ƺƺ  ¹¯€¹Ǻ ‚¹¹˂˺ǁ $$ ހ¯€€ǃغ ˺ $ 3¯ ¹˂ $ ̂¹р¹ ¹ƒ̂ ¹ ǰ…€Ѩƺс $$ ¯€¹€щC C  $$ I ¹¹€IǺ؁ ¹ހ* Ǻр* $$ 8¹¹8 C˺C   $$ I ¹I* Ǻأ* $8¹́€8CǺ˺ǣC  I̹IDÂÀD 9f f9-ì-1jj1 ,jn-  ,zق߁©s,DڻDy~~&9˂߀ق߃¡9-φ- 1 & & ,قс٩,݀ڃ͢ ~~y~yyy~ ~~~~~sтـ߀فѩzD ڃڀD]~y~yy~~y~j X~~n 9€ˁ9рсυj]jjyjk~~y jy~kkkk&njnrnnjj~j~nr ~r,f€ˀ˦fπۀۂہ â1]jj[ ]k]]k]j[yQ[jj]k?,XjXjnn_njn_rCˀˀˀۀۀ Q[j]kOO]][Qj]OkORXXRX_XXjRjRjX_X ¹ÂԀÀԀ̷??[?Q[?O?OO?O[Q[[]O]CRRCXCXCXXRXC_ºԵõÄ õ̢?1?O?O?Q1Q1Q?O??OC=C=C_ÃõÁ1?$? 1?1?11Q11Q1?,-C -=--==&=&&=CπûûπÁ1$111?$?,- ---,&=,-CC Ϳππ$$$11111$$ -,&,,-- ͿϿͿϻ$ 11 111 &&&& фÀ1   ÷с÷÷  = ÷ÿ ÷÷À      À÷À     ÷À ÷     ݁ìÀ÷    z сѷ÷  z ÷À÷  zz÷ÃÁс   ÷Á÷À ì1    Á÷х     f fDì÷ ѷ÷D   9z9÷рâ     sz s-÷ìÀ -     ,,D÷÷D   ,z9-ÀѢ-   ,sz z,DтD 9fzzzzf9[øþä[FȸF[ָ[F̅FȆי[ۀրփ[ȀۃۄȆނɤɁ߄Ɂɸނ˃ۀɁɁހށɀȷɴȂȁɀȀۀȸȁ̂ ȸɀ̀ȸ øÀ́Ȃ̸À́ÃÀ̸ׁÀȸøøɸ ȸøȸøɾ̸̂ɁɃ׸ ̾ø̂ø þÀÁø øøÀ øɯȸøøÀ҆[À[ɸׁFøï ɸҀF [̸ø[Fø ɸפF[ɸ̸ɤ[CC/ja7-Ƕ-s}"C߼C//-ԅ-}߂̔Xs js}s}}}aCԁ߂C/hsjsjjsshsjs}/ /aXajahsjah }hh7 ԃƪEUMaXXUUaUhUUaaX jXaUUhUhhU߂فƀGMGUGUGUUGXEXMU GUhUUنكԁԪ7M:G:GE GMGG:UUƁƂ߀߁ƣ7/E/7:7/E/E77:G:ƷǀƁ"/"77":"7"/7:ǂƳƀ """""///"::ʼǼʀ   /  /""ʼǶǪǪ  Ǽ   ̃ȼ ȼȶȀ̂ȁȄȀȀȄȀȀ̀ ȃ̀C ̂CȂ- -CȁC-̂ԣ-CʶC[øþä[CCFȸF1ɻ1)f^;[ָ[ C໻C{$F̅ F1 1);Ȇיҗ{{{[ۀրփ [C Cfm{s{smȀۃۄȆɀmfm{ff{mms{{f{f{msss$ނɤـ؂Ѐū;f^fm^s^smfm^^sKɁ߄Ɂɸ ؀ лKKSKfKfS^^S^^ffQQf^S^s^^ނ˃ۀɁЂЀقЁK =SS=S=^=SSQKSS=^=^^ɁހށɀŵŵЀ3;K=K3=SKQQ)QQKKS=S=ȷɴȂȁɀŻɀ ;;3;$3=3K;3$;);;33=Ȁۀлŀ$3$3=3$;));;);$=ȸȁ̂Ҁɹ$3$)$))$== ȸɀ̀ȸҁ Ź$$$$$$$3 øÀ́Ȃ̻ɹ$̸À́à ̻Ҁŀ  $$À̸ׁÀ ȸ Żøøɸȸøȸøɾ̻́ŀ̸̂Ɂ̻łɃ׸̾҂̻ŀø̂øþ҂̻ŀÀÁøɂŁ øøÀøɯŻłȸøøÀ҆̃ Ҁ[À[CCɸׁ ŀłFøï ɸҀF1 1 [̸ø[CCFø ɸפF1̀٣1[ɸ̸ɤ[CCCCFi iF/ja7-Ƕ-%+in0% 9|ۂìu9s}"C߼C(F͂ۂàF//-ԅ -%( (%9ۂӁ۬9}߂̔ uӂۀہӬ|Xs js}s}}}aCԁ߂CXnFÀ́àF/hsjsjjsshsjs}/ (ninsnniiins s+iÀ̀Ɂͨi/aXajahsjah }hh7 ԃƪ+XiXinn^nin^sD̀̀̀EUMaXXUUaUhUUaaX jXaUUhUhhU߂فƀSXXSX^XXiSiSiX^X̀ÀGMGUGUGUUGXEXMU GUhUUنكԁԪDSSBXBXBXXSXB^ ý7M:G:GE GMGG:UUƁƂ߀߁ƣD@DBDBD@DBDB^7/E/7:7/E/E77:G:ƷǀƁ+0B D0@00@@(@((@DB"/"77":"7"/7:ǂƳƀ+0000+(@+0BB  """""///"::ʼǼʀ0+(++00    /  /""ʼ ǶǪǪ ((((   Ǽ    ̃ȼ/ ȼ  ȶȀ ̂ȁ|ȄȀȀ|ȄȀ||Ȁ̀  ȃ̀iiC ̂CF|FȂ!u|u- -% %99CȁC9|F-̂ԣ-%%9u| |9CʶCFi||||iF>=<<;;:?9fltk-1.4.3/test/mac-resources/checkers.icns0000644000175000017500000016746315004135251021022 0ustar albrechtalbrechticns3ICN#il32 пp7 :DD: 7p S˒S p ^ԥmm^ p *xmm* p /ˡνĽ/ p *m{ccxxսm* p ۽o} _ p ^Ľ^} }}^ p ո^}}}ٯkp Sܳo}Ѐ/xSbp Ꞃ}mDZBp m_}}cԒ9Upp:ۜc}}Sm(9UppDc}}Smm29UppDmmx}}>7 pp:mx}}3@{>,77pp Ή}}ԬK*4{9ĥm77pp Ǟ}e++*;m77pp Sx_j*\}}>S99pp ˽Ǘ+*1r}}I99pp ^8;qx}I^9Bpp /}I}*>9Upp *mmcSS>>9mٺm*>p /γĻ˯/>p *ܳmmɱx*gp ^mےmԙ^ p SS p7 (27, 7pkbBB9979>>gpUU79KUUpp7 :DD: 7p S˒S p ^ԥmm^ p *xmm* p /ˡνĽ/ p *m{ccxxսm* p ۽o} _ p ^Ľ^} }}^ p ո^}}}ٯkp Sܳo}Ѐ/xSbp Ꞃ}mDZBp m_}}cԒ9Upp:ۜc}}Sm(9UppDc}}Smm29UppDmmx}}>7 pp:mx}}3@{>,77pp Ή}}ԬK*4{9ĥm77pp Ǟ}e++*;m77pp Sx_j*\}}>S99pp ˽Ǘ+*1r}}I99pp ^8;qx}I^9Bpp /}I}*>9Upp *mmcSS>>9mٺm*>p /γĻ˯/>p *ܳmmɱx*gp ^mےmԙ^ p SS p7 (27, 7pkbBB9979>>gpUU79KUUppx{{xp{ ɩ{p{ Ķꯃ{p{ֶܶϳ핁{p{׺Ľh{{p{{ս[{p { A{p {Ľ ؏Gvp {ٺ?Ekp{ܳp{γnAA?<>p{{[ܳɶضkA?Agp{Aɶ۰}?A?tp{ G?౱kA?{px{ vE>gpUU79KUUpl8mkit32Copoonmmlkkjjiijjkllmnopqppoonmllkj iijjklmmnoppqponnmlkkjjiijjkklmnooppq ppoonmmlkkjijkklmnoqrqppom'fsInqqrssrqqppmM'y';oqqrrsrqqpom&7c'dpqrssrqqpom%[yO moqppol9VnpqrssrqqponDLޙ,nqqrssrqppomҧW_pqqrsrqqppol&rmoqppoole㴔,npqrssrqpponC⠵+nqqrsrqppol̫_pqqrsrqqpoolQ嬠BmoqpponlJynpqrsrqpponCy|ٵ+nqqrsrqqpool{l_pqqrqqponl,ň|ymoqrqpponloݑnpqrssrqpponC~~ܷ9!nqqrssrqpoolyt~Tpqqrsrqqponlo~ަjpqrqponl?}dž[_qqrsrrqpponC؇{ nqqrrsrrqpool󲘺g̫bBzu \rqqppom6zz0Xgpqpom؊٩ PmgqrqqppooD{L_[L߸.pnonoppn/W}S oqqpoppnL,r,8oqqpopopn  ?rt1cqqpopn-Rw]#qmmlmnogT7)5QonmnofI.2ulHopqnjkpqaJ~Z$opqjmkqo1JJIppqnmjnqo5llJoppqnimnqrlA˯͎Zoqrq_ tλvoqrq o,yFpqrqo/ʼlopqrsrku맭zoqqrsrqqp_к.oqqrsrqqn, ٗFqqrsrqnc쫸oqqrssrj9}~Roqrsrrqqp_zvoqrsrrqpn+wFqqrrsrrqqpn҅zioqqrsrsrjoֈgqrrsrrqpp^~~{oqrrsrrqpn+WnѸy 7qrrsrqqpnsØcqrrsri&~a/Lqrsttsrrqpp^q؎ᾅv`rrsttsrrqpn+򵢺tlrrsttsrqqpn~fӻGFqrrsriVҸm0qrsttsrrqpo^YJrrsttsrqqpm=w΀merrsstsrqqpmNݽք(qrsri|ֱՃ{[h nrsrqqpo^ÿdjD6rrsrqqpmKvװssPrrsrrqppmtÿ|[ohrsqiIұ9{Sjrsrqqpo^||KR -rrsrrqqpm5ƄEqkӳ Grrsrrqppm;㷎3jbrsrqj~\llrrsrrqqpo^WsL -h1rrsrrqppm+5A|Jrrsrrqqppm Yl2errsrqkUngmrsrqqppo^W"h[s2rqqppn+2.z{{LrsrqpomEsigrqrpk\lttr5qrqpo^TqP}gwOqrqpn+w_v[ hrqpngpj}l;/qrqpl/>Qqp o_zɀhqpn+ܺqpnzRJqpqpmwܖoqp_9鸲|oqpn,f屨:Gqpn[ oqpon$e6 oqqpoppndLj0oqqpoppnAb\Soqpopng=oqqpopoon_J-(/<[oa`_^__do `<$&stuuvuutsrqom¾rrx[ttuvuutsrqnĽ~uiuvwvvuutsro\ˈK@h(tuvvwvuutsqF°~>gS?tuvwvutsrp ۇ~*zz\uvvwvvutsroKΉI8k'vxwvutsp%wN,k{ uvwxxyxxwvutsGvʆ0In@vwwxyxxwvusq֨{ ZjYUvwxxyxxwvutsp惉b brxzyyxwvtqh2t]2wxyz{zzyywvutHω&:}u#Gwxyz9{zzyxwvurT#Ihfwxyzz{{zzyxwvtr.m{_$z|}||{{zywvswMeSMxz{||}||{yxwvJhrMVa߯gyz{||}7|{zyxwtiPeiR$xyz{||}}||{zyxvszR_S?}~}|{zxu9üǀhz|}~~}|{yxL貓ٲx{|}~~}{zyvͣ[Dz{|~~~}|{zxu! [}|zwky|~~}{zNӲ26z}~~}{xUi|}~|zwȝjp~{y"!F :{~~zc:LV|}zFJ*s|}y)H*qg_`_^]\[YW[{ywvtsjU804ETpy{zWYZ\]^]\ZXVh{ywutrgJ/52P\rz|oXY[\]^]\[ZXVszxvusq\@40=Lfxz|bXZ[]^]\[YWX|ywutrjV:-2?Kgpqq~}zywvtuuwxz|p$}|zxvutuvwy{}~>V~{yxvutuvxy{~~ ~}{ywutsrrqrrsr |zxwvuuvvxy{~r&~{zxvvuuvwxz|~@X}{ywvuvwy{}|zxvutsrsr~{yxvwyz}t(}{ywvwxy{}BZ|zxwvwxz|~ ~{ywvutsrssr}zywxy{~u)~|zxwxz|~C\}{yxwy{} }zxwuttsr~{yxxwxyz|~v+}{yxwwxy{}D]~|zyxwwxy{~ ~{yxvutsr|zyyxyy{}w,~|zyxxyz{~E^}{zxyz|~ |zxwvutr}{zyz|~x-|{zyyz{|~F_~|{yz{} }{yxwvuuts~|{z{}x-}|{zz{|}F_}{z{|~ ~|zyxwvvut}||{||~y-~}|{{|}~G`~}|{{|} }|zyxwu}~y-~}~G`~}~ ~}|{zyyxv~y-~~G`~~ }}|{{zxy-F` ~}|{ x-F_  }x,F_TFGFPEFGFcnFGFExZFGFJJFGFZxEFGFncFGFEPFGFT_F,x} _F-x z||} ~`F-xxz {{|}}~~`F~~-y~vx yyz{|}~~}~`G~}~-y~}uw xxyz{|}}|}~`G~}|}.y~}|~uv wwxyz{}}|{}~`G~}|{{|}~.y~|{{||}tv wwxyz{}}|{|}`G~||{{|}~-y}|{|}~uvvw xyz|}}|{{|}~`F~}|{{|}~-x~||{||}vw xxyz{|}}|}~_F~}|}-x~}|~wy zz{|}~~}~_F~}~-x~}y{ |}~~~_E~~,w~{} ~~^E+w }^D+v`^_`_^]i}^^_`_ ^^]vq^^_`_^^]c^^__`_g<(:<)9>)7})E3)D5)S`)/G)-G+)*pE)9>)8?)/ u*B\   u  *B  \   } $ u  *B #\" ~~}}|z   ~t*~B\~ ~}|{{zyx$ '$$% r~}|}}~t %% ~}|@}~F  '$" ;~}}||}}~! "!%% j~}|{zyyx v,2&''#'E~}||{{|}~t/%&%$ `~}|{@|}~L 2%$&&y~||{{||}01$&%$@}|{zyxxwu*( HU'('%<~}|{|}t#^?&%%& R~||{||~B!d,%&&#m}|{ |}~" 8X$&%%:~~}{zyxwwvu$)g7&& 2~}|{|}t "Cb#'&  F~|{|~F$UK)%#a}|{ |}~d;"&/y~}{zyxwwv t. QL"/|~}|{ |}t  `8#B~}|{|}~L  &e [}||{|}~3 FN# 2u~}|zyxxwu  60~}}| }~t > E~}| }~B P ^~}|}} =0x}|{zyyxwv   >~~}~t U~}~B p~} ~~  8~}|{{zzyw  Y~~t s~ B )~~ S~}}||{z%~t  B# P /  z~|t)A \xt jR3*,#.)Buxtu fH/(&/%4Qu|}tu \B#+,#.:`uyu oS3/(&/%Cqvsgou ."+&2lleg77WhhqE"14ytllt! +%)()}-[B( u#{|}~~ $ [ B) $ u   xzz{!|}}~  ~~9[  C~~) "   u~ " wxyzz{||~ ~}~[=~}~~)  o~~}~  vwxyz{{}~ %$% y~}|}~[ $%$ %~}|}~9%$%S~}|}~ $%(  }uvvwxyz{|};-$(##Q~}|{|}~[@%&#'!e~||{|}~>">$%(#%}|{||} 2/'(%) Utv!wwxxyz|}-!TL&"(%B~||{|~[% b9%)#&a}|{|}~)&'a)&"(/t~}|{|}-#IT&&,& Itv!wwxxyz|} )d/&% 9~}|{|~[ >\&%% P}|{|}~8 [H%& (l~}|{|} e6('?uwxxyz{|} RD;~}|{|}~[ d* P~}|{ |}~?:]&l}||{{||}  NK>vxyyz{{}~   2~}| }~[ = P~}}| }~( ;/e~}|}~ !7wy!zz{{|}~ Q~}~~[ g~~}~~( %~~}~  Ry{|}}~~  k[  (   C k|}~  [ $ >( $  q ~^ G.w xcG0208D_uW<2/0?HkiN9/25;SzydH32/8?Z {uxx6syvLa ~yu}!|sy}u ")B [ ~ 'u # )B &  \ ##~}|  ~u )~B   \~  ~}}||{!y |~}}|}}~tU # ~}}|}}~BO~}}||}}~   z~}|{zzy w%#'' h~}|{||~t )$$"y~}|{/|}~I !&&8}||{{||}*)$$ b~}{zyyxw u%&;>)'&'B}|{z{}~t!L1%''% \}|{z{|}H !M&'&%%u~|{z{|~& ,A'&'' ;}|zyxwvvut%)G^*('($8}{zyz{|~t!]H&((& M~|{zyz{}B "e5('&'  f}|zy z{}6^+&(( %3|}{yxwvuut r',g@+*  /|~|zyxyz{}t (g+'&A~|zyxyz|~I EX$) , !Z}{zyxxyy{|(_B,'2s~|zywvuts q'(GT82~~|zyxwxxy{}t [7 F}{yxxwxxz{~I!f `|zyxwwxyz|~( #>Y /y~|zxvutssrp  ( 0}~{yxwxyz|t 5  C}{yxwxy{}B <]|zyw xz|~ ) 0v~{ywvusrrq6p  G}{yxwvwwxz|t _}zywxy{}B  x~|zxw xy{~   ?~{ywvtsrrqzo    c}{yxwvwwxz|t z}zywwvwwy{}B  -~|zxwwvwxy{~ Z~{ywutsrqo/  }{yxwvvwxz|s *}zywwvwwyz}A "\~|zxwvvwxy{~ 7  }{ywutsrq+o,  }{yxwvvwxz|~x ?|zxwwvwwyz}P & #+e~|zxwvvwxy{}(   }{ywutsrqofI>7S]v}{ywvuvwy{}lP;;BUb|zxvu vwy|~}eI>>GRk~|ywutsqppoQQPOPPQRSUVXZ[]_`bcde dba_^\ZXWVUT UUWXZ\^_abcde dcba_]\ZXVUUT UVWY[\^`acde dcb`_][YWVUTUVXY[]_`bcdefghijkklmnQ \"aoEf="u~"+t 2^"S\!WvM mP [1RgՂ١3EٕyՂy΢ONՁ[pmPπ [[ݯ"gԀ٠3ݜԀxǦNԁ[GᩞBmOZ>u{fԁؠ2txЩԂxv|`NԁZ yxmOπ Zizy҄fԁؠ2xxزz+Ԃxlmxz}Cԁ/QсZmgݷkW%Ձ٠2}F fՀx[tl̈uՁZlg|l!RҁZnâs=j"փ٠2zpRFZւx(nϿ:vtvւZ]ҡw@{BTӁA[6pvo(Nh!ڠ3g`t[Հ9x԰~69pf[&op* SbUӀ?[ϠFc\ڡ3pCUxP<[րy]憊]rp؀[ՁAb`V?[E`Mzpa5ۡ3vExakv׀yWuZxayۀ׀[-WYtx_"-Xׁ4\vq{ֺ:Sۢ3|g֯Ҁ؀y rɏڀ؀\\}sSHZك\C璡 hۃܢ4tǭwpۃziSOۄ\/ѫ"e\ǂǀɹ\GmC fɀǀɘ:by &ǁv/bd!RɁǁ\CgNc]\[[Z[\] UB%  #?^]\[\]T7 *H]\[\] K. 2W^]\[\] UC(  =_`a_/fu\8]̓ձP:nJyՌ :w:7h%\\:]Á ռ_`5K]݀܁ۀݶNeh{݀܀ہݏzj4݀܀ہg ]]݀ۂ\bkᜢk]ۄܶMĭ{ۃ܏ҹ͋4ۃgTߞ]فپZc1utvC]ڃܵMok{ڄ܎l}5ڃfz~p|Y]؀׼Xdi~ԱUك۵Mvtsl{قێHcvǮo&قfh|wպQցֺWe"|tUз:؁ڴMa˃ش{jl؁ێ䩘i ؁ft[ǭ74Ձ;չVeRʯw\ڴLtzNUրڍ+luaր:e>zԳz{tԸUe~xϩxoMX ׁڴLۻܔY\4B׀ڍ:jΧhe׀eoiܻqvM` ԁԸTeEά{0pC׀ڴLqsAG9׀ڍ$ǹx؁ ێ"v%p ~؂f;h^ՁչVdTbjjg#ك۵MEfEr\kZكێ|lTkPՒكf[d_ra,ցֺWb${/?ڃ۵Mmtڃێ{Ϭ ڃ f m C8؃ؼYai·^ۂܶM)۩l{ۃ܏V֢*5ۂfMՑ^ڄھ[_T&^R;Yr/RLAd  V,^]^fgf WD%!'5Shf]PNMLMR^g X65?YhcZNNMLMWag I1#5Ech`VNNMLM[dg]E%&5Nhh]QNNMMLMMNS_\܃܀]^pyUg܂ޣ5YV2݀܁{7nXN܂]Y}t`aZڂ]K`g܃ۀݣ4wr܃z*í}婢N݀܂ۀ]nțhubX؁\ʨkgۄܢ4"ۃzPڱNۄ\բڄdWՀ\{{t}h"gڀ؀ܢ4nxysڄzrttN؀\bxyykDfVԀ\vxȬgكۢ33nvvȼb قyf|xu?ك\sycUՀԀ\:{̫ۥraIكۡ3۬ʷݭ}rµكy~̫wh`ك\)rҷޠ{_AVԀ\fcC5قۢ4sE{قy@q}mق\^ߪwc0VՀ\yٻϣs{jSڃܢ4ϔɛG \ڃz]gٻ紈zjڃ\v鿸~yqeX؀׀]L~B6] ܀ۀݣ5s{4]Hͷ]ۀڀ{|u!o}jۀڀ];~D3f#Zڀ^lE#`oޅޤ6f¾{'?c^ޅ|ȜqP_I ޅ^x~Z]l]݁ހ_t^(jxRw*70}rif}Ew?]`||&esXała kAYH~E9YgAJUѠ^DZ]CanGUI7fʁc*𖶯Ѹa:~ۥ̤L2cƀQkЅe籮\r<ģڻ#$ FxXew]dqg5 )oR ); Dy5 : ah 7bwWNO>NNMLJIGEIi~v`D;?Q`{~iEGIJLLMMLKJIGEVp~rV;A?\h~v]FHIKLM7LKJHFDay}hMAKWt|w`|l_,Dwl݂^m߀a.G߀xnۂۿ\oހb߀0Hހz pفٽZ q݀d2J{ qׁ׻X r݀e3L| sրֺWs݀f4Mހ}tպVt݀f5M~ tցVtހg5N~ uׁWug5NuؼY ug5N vۀۿ[ ug5N v߂^ug5N vbug4N ug}ug4M ulxE654>uo4456544R\4456544fzI456548urru845654Izf4456544\R4456544ou>456Exlт uM4gu}gˁ uN4gubƁ vN5gu^vN5gu [ۀ vN5gu Y vN6guX vN6guX uN6guYu~N5guZu~N5gt ]u~M4ft a u~M4fteɂ t~L3etj΂ t~L2et|o tOLMNMMLLWvkLMNMMLKd{_LMMN MMLKpsRLMMNONWwt-*,)-%sk5#3$B O66^y4(-'/sqysc1K}sk}sc 1K| sf  sc 1 K{  sa rc1 K{ sށ ]  `c 5  *{ Xہ [( - !3c%k;){ ( -فY&$CP!" *߀ bT7_߀1[# z.O'؁X$b2  ߀b9Y S߀5 LC! ߀z [3 ؁ X) KFbW/M;\ z#=E ف Y  /b 4P0G z4 ہ [,b a0 { &ށ^Gb0{ Ab| lb  0>{! hfwrb0J|rkrhc YA"1cfr|{ypc U7"@dku|{vlc J1(Ocox||{|sgc^A"1_er{||{zyqm ȸ˾r!yʁˢV&& Eʀ Įˇ3 #gʁ rvh͂ r|J0cr{dȂ r |J 1cq _Á q  |J  1 cq \q|J, ^q Z qqJ( Aq( !xXq1$ IJ6-5q(&!$PWqKD  :߀J Y1!߀X!q?L &!EXq\'1߀J5So'R@q]/"! :YـqI; 3J ["o. 0TqEC9[q *I3o2q  1^qIIq KbƂ qcI1qbfq |I-_q |kʃq|L5eqypqrfQ5 &2MrqrcE* -6YrqrW<' #)Ahrqr gS6! &.Isstuq݀޾f $݁ޜ; O݀ { rՀnzrc0J|rirc 1J{ rd rc 1J{ r `   jc 1  ={ h܀ \ !Uc# 8 '{ ! Pف Y"#8:%" 0cD) <h7D  z #9   )ցV#&E['$""&bVA "!Y1^."  z  .W$ "!! T%+e='%ۀb!`&"  M9>R#zX<&!  ҁ R' 'FR ڀc  U1S9 ` z8S :дQ  & c/P17 z$ϳP5ـc/k1z  .π#ϳO   Rc  1  z  IϳP-sc 1 Lz3 sЁ P,   s̳g0¿ΕA!Uy  sQ~eG9=ALd}xsnid`\ZXY\_chmrw|sS::2LUl|wqlgb^[YXEZ]`dioty~gL76poonlkigeautrtwrcgikmnnoonmljhfdfvsz˃uwkdhjlmno7nmljhfbmusuvxdfhjlmnoonnmkigeattrmniYoq>poonlkigdatu乱uqcgikmnnoonmljhfdfu|Ӷdwkdhjlmno7nmkjheamuǻfxdfhjlmnoonnlkigeast뱵liYoqponmlkifd`tܩdpcgikmnonmljhfcfuƸXkdhjlmno7nmkigeal곸лfdfhjlmnoonnlkigdasʭۤefYoq?pponmljifd`vо0cgikmnnoonmljhfcfhGdhjlmno7nmkigeal8Ufijlmnoonmlkigd`s׻ݹ#Voponmljhfd`ҿ1Ugikmn mkjhfce dhjlmnlkigeal7gijlmn mljhgd`ʸ>Eoponnmkjhfd`Q1giklmnmlkigecfӻ#Ghjkmnmlkigea} gijlmnmljhfd`cno nnmlkjhfd`̽ۀ;~"giklmnnmmlkigecfִ)>hjklmnnmmljigeaڲ(Vijlmmnnmlkjhfd`ͽֈmon mlljihfdaπ Rgikllm lkjigecfӁ 穥2hjklm lkjhgeaހ Jhjklm lkihfdaalnmllkjigfdap_*gijklkjhgecfXk2hijklkjihfeam}Y RhjklkjigfdaqV=kmlkkjjihgedaw\gijjkjihfedgg2hijkjjigfebn_y7IhijkjihgfdauYjkjiihgfedavȪP2ghiijiihgfedgx̧!Lghijiihgfdbnùghiijiihgfedauïa&hihggffedbwyOgghihggfeddgxGeghihggfedbnx&-gghihgffedbvxEfgfeddbxyl_Edfgfeeddhyyh> Uefgfeeddboyxh&+`ffgfeeddbvyql#'1OdcbabcQ5"9^dcbbabc \J/(Eggh`quutvòxvwxuceeffgd`afggffeyxxwͻxwwxnceeffg`cag3fdlyxxwѲvwxxhdeeffggdc`dggffdryxwxij|wwxwbeef ggd`dfiijkj]otuyywcefghhihhgffezyxypcefghhihhgfdlzxތxyheffghhihggfcsyx|yxcefgghijjkllk[mrlwcfghiijiihgedyȽ}ypcfghijihgfdky˷jyhefghijihgfcrxȽkxcfghiijklmlZk˶icfhijkkl;kjihgedyWpdghijkkllkkjihfck׾Vifghijkl kkjhgfcr۹fcfgijkkllmmnomXlӾ)\ghiklmllkjhgec/dgijkl@mlljihfcjXHfhijkllmllkjigfbs-WfhikllmnnonW]Agijklm lkjhgec Ugijllmlkihfcj%bhiklm lljigeb u;ghjklmnnopnW޶%gijllmlkjhfec;?hiklm lkihfbr릀 ZhjklmlljigebgijklmnnoppnWÛdijlmlkjhfdb]+hiklmljigfbzEhjklmlkjigebí^ijllmnnonW |p`ijllm llkihfdbρ $#hiklm lkjigfbnہ ܅=hjklm lkjhgeb uXijklmnonX_bLaijklkjigfdbܻWx&hijklkjhgebi|U@hjklkjihfeb~a^a[ijkllmnmYkdciijkjihgedcs'hijkjihfebj^GAhijkjjhgfebqe]hijkklmmk[m`*ghiijiihgfedcxˬDghiijihhgfebjy¿^ghiijiihgfedbqžx$ghiijkj]otFgghggfeedcyxG]gghgffedbjx&*fghggffedbqx?gghih_qwudPFdfgfeddcyyn}ߪ4 Zeffgfeeddbkyyeq&+cffgfeeddbryx`[Adffghgboqqp01O}U*Drdffedbdsrrf'*n6+]mdffedbhsrrS#3p3#oidffedbnr 8,L|Y-;sdffeddefeddcU@"$2PdeeddcbcdbcdU125no nnmljigebރ q1hjklmn mmkjhfeg۷ л!Qhjkmmn mlkihfbӶ gijlmn mlkigeb݃#np oonmlkigebҀ ~hjlmnmljhgeg޼/2ijlmn mkjhfc Oiklmnmlkigebʈ npyoonmlkigeb뇆6ijlmnnonnmljigegz3iklmnoonnmkjhfctlPjkmnnoonmlkihfb|H opoonmlkihfbV|-iklmnoWnmljigehuY4jkmnnoonnmkjhgco_aIjlmnnoonnlkihfcTt3npyoonmlkihfcy{%jklmnnonnmlkigfhob:jlmnnoonnmkjigdol0Yklmnnonnmlkjhfcvwߴnonnmlkjhgdyϱļ6?jkmmnmlkihfizǵYklmnmmkjigdp{jklmnmlkjhgdwϳ¼>1nonmlkjigdzzIYklmmnmmlkjhgj{{("hklmnmmljiheqz#(&CNbijlqqrqqppooigfedP4($0?Whijoqqrqqpoonhgffee]J/#(6B^ghil~~hihhijjkkllvhih iijjkkljtojihiijklj{hjihijjkkjl}~ijklmwikjklktokjklk|ikjkllmlk}jklmxjllkklmluplkklklmk|jklklmnmk}klmnmm xklmlmnluqlml|klmnoonk|kmnykmnluqmnl|kmnopnk|kmmnonylnonnluqmmnonl|kmmnopoj|lnonylnonmurnonnl|lnopoj|lnonylnonmurnonnl|lnopoj|lnnonzlnomurnnonnl|lnnopok|lnnonzmnonmurnnonnl|lnnopok}lnonzlnonmurnonnl|lnopnk}lnonzlnonnlurnonl|lnonl}lnonzlnonlurnonl|lnononl~lnzlnlurnl}lnomltutlnuqlounlrulmlurlnuolqunltutlmonl}lnrulnlznl~lnononl|lnonrulnonlznonl}lnonl|lnononrulnnononlznonl}knponl|lnonrulnnonlznonl}koponnl|lnnonnrumnonlznonnl|kopqqponl|lnoponrumopomznnoponl|joqpoonm}mnoopoonsvmoopomznnoopom|jprqppoom}mooppqppoosvmopqpomznoopqppoom|jqsrqqppm}mppqqrqposvnpqrqpn{oopqrqqppm|krtsrrqpn~npqrrs rrqqptwoqqrrsrrqqo{opqqrrsrrqpn|ksuttssrqo oqrsstsrqu xorrsst ssrro| pqrrsst ssrqo}ktvwv uutsrp prsttuuv uuttsrv xpsstuuv uuttsp} qrsttuuvutsrp}kvxyx wwvutsq qstuvw vvutsw yqtuvvw vuutq~ rstuvvw vutsq}lwyz yyxwvur ruvwxxy xxwvux zruvwxy xwvus stuvwxy xwvur~lyzz{ zzyxwvutxwvutts ttuvwvstvwxyyz yyxwvtuxwvutts ttuvwttuvwxyyzyxwwutvxvvuttssttuuwxstuvxxyz yyxwvutwwvuutsrql{p\luutsrqpqqrssvze[v~uutrqqpqrsttzx[_yyttsrqpqrstt~p[j}uttsrqppoonmm}0+mvwutrrqpqqrstvw^E|vvusrqqpqqrtuuA ]}wvtsrqqpqrstuu+#iwwutsrqppomg Txxvusrrqrstuwy=|xwvtsrqrsuvv ywutsrqrrsuvvl Exxvutsqqppon~ByywvtsrstuvxzI   3pyywutsrrqrrstuww zxvutsrqqrrstvwx  8yyxvusrqqpon  T{zxwutsrstuwy{} kzzxvutsr ssuvxxM  >t{ywvtsr stuvxxM{zywutsrqqpnw).j{ywvutstuvxz{? (@z{ywutstuwxy  N|zxwutstvwyyx)+a{yxvusrrqqpo^+  >|zxwutstuwxz|''1X{zxvutstuvwyy~* +q{ywvutstuvxzzb ) 8|zxwutsrrqoH" @N! & 5z{ywvutuvwy{} V8 K|zxwvutuvxzzt \$",f|zxwutuuwxzzH0Q"2w{yxvutsrqpK !`0,+y{zxwvuvwxz{} ;Z (@}{yxvuvwxzzyND"%/Z|zywvuvwy{{P]4 %(s|zxwvutssr pf IE ")v|zyxwv wxz|}0 Y1 3<}|zxwv wxyz{]  ,U}{yxwv wxy{{k?G ,o|{yxvvuttsq/ 7*x}{zxxw xyz|~U7 2?~|{yxw xz{{$I!.X}|zyxwwvwwxyz{{ 6 (7*r}{zywwvutr>88}}|zyyxyz{|~ 11O~}{zyx yz{{z "30j~|{zyxyz||G  :2|}|{yxxwwvus  =3S}|{zzyzz{|~j 43m~}|{zyz{|{C&=4~~}|{zyz{||":2M}|{zzyyxxwu  65Fx~}|{{z{{|}~j *4;S~~}}|{{z{{|{9 *:6j~}||{{z{{|( 57Et~}||{zyxw}8689F~~~}}|}}~s$ 586^~~}|}|W (489y~~}}|}|<388B~~~}}|{zy{~~qS8,.(/,Gz~}|~~gK1+)/)5S~}|~ ~]D(,.(/;e~~}|~~uT8/+)/)Fu~}|{y||}}~nbjp~ oUK^v|~fg_} jLHj|~zbbk}{dFTl~|~nfgn}rYJ]t}xzz{|}~}T&"^|~}||}~= ;n|}||}~} D~~}~}aXvxxyz{|}}~}? ]}||{||}}~  |}}||{||}~}p ~}||{||}}~}ISuvwxyyzz{||}}TK}}||{zyz{|}~" u}}|{{z{{|}}  ~}|{z{||}}c  Asuuvwwxxyz{|}}  U}}|{zyyx yyz{|}b $h}}|{zyyx yzz{}|( ;evxxyz{{|}| 246V~~}|{z{|}c  -:9j~~}}|{z{{|7 :7Bu~}||{{z{|}|-6>Vxzz{|}}|:$">29\~~~}}|}}q($(+4<6w~~~}}|}|O-7:2E~~}|}}|?##@6?Uzz{|}r]A*,+2>Y~}|}oQ6,)+:Ce~}|} ~cH3),/5Mt~~}|}s_C.-*3;V|\B9CX|~uor{S9;Kg|~ntq~}rQ39Q||~xtow~`E6DU|~wnty}~V  7}~}|}~+O|}|}~~}%m~}|}~~}d  1}~}|}}||{;0}~}||{|}}~ X}|{||}r  {~}||{ ||}~}E$}~}||{zyW #}~||{zzyzz{||~'  T}}|{{zzyzz{|}| w~}|{zzyzz{{|}}a }~}|{zzyxw    Bv~|{zyyxyyz{|}w  R}}|{zyyxyyz{||A  )h~}|{zyxyyz{}}  ?s~}{zyyxxwuj   *b~|{zyxwxyz{}1 ! $ Bs}|{yxxwxxyz|| D}}{zyxwxyz{|}r " #\~|{zyxwvutV 36!  *<~|{yxwvwwxz{}%E) -W~|zyxwvwxyz|E  $0p}{zxwwvwxyz||Z %: $ 5~|{yxwvutzrH ?V#! !+2{|zyxvvuvvwxy{}VA!!H~|zxwvvuvvwxz{|v^.! % /a}{yxwvvuvvwxz||J /W#!!%.w|{yxvvuttsqX #_8##% *w|zywvuvwyz|~$!_$ +<~|zxwvuvvxy{{~>Q"! ,U}{yxvuvwxz||\X;% " -n}{ywvutssr qp ?M ;'&-z|zxwvutuuvwxz|~: T/%6A~|zxwuutuuvwy{{ _1[}{ywvuutuuvxy{|t7R $ "*t}zywvutsr7p   >+y|zxwuuttuuwxz|~m-!3>~|zxvut uvwy{{A 5 //X}{ywvutuvwy{| "@,q}zywutssrqpP !$07B|zxwutuvxz|~  <5[~|zxvutuwxz{# >.t}{ywvutuvwy{|X ! *6;}zxwutsrrqoN(,* 8:_|zxwutuvxy|~+) $@3v~|zxvutuwxz{y'* 97C}{ywvutvwy{|T ",' 6?V}zxwutsrrqo='2=?\|zxwutuvwy{~! >?:q~|zxvutuvxz{h$?>U}zxwutsrrqoS<0&0D<;]~|zxvutuvwy{}?:"47=<:y~|zxvutuvxzzq;47:= #include #include #include #include double args[9] = { 20,20, 50,200, 100,20, 200,200, 0}; const char* name[9] = { "X0", "Y0", "X1", "Y1", "X2", "Y2", "X3", "Y3", "rotate"}; int points; class Drawing : public Fl_Widget { void draw() FL_OVERRIDE { fl_push_clip(x(),y(),w(),h()); fl_color(FL_DARK3); fl_rectf(x(),y(),w(),h()); fl_push_matrix(); if (args[8]) { fl_translate(x()+w()/2.0, y()+h()/2.0); fl_rotate(args[8]); fl_translate(-(x()+w()/2.0), -(y()+h()/2.0)); } fl_translate(x(),y()); if (!points) { fl_color(FL_WHITE); fl_begin_complex_polygon(); fl_curve(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]); fl_end_complex_polygon(); } fl_color(FL_BLACK); fl_begin_line(); fl_vertex(args[0],args[1]); fl_vertex(args[2],args[3]); fl_vertex(args[4],args[5]); fl_vertex(args[6],args[7]); fl_end_line(); fl_color(points ? FL_WHITE : FL_RED); points ? fl_begin_points() : fl_begin_line(); fl_curve(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]); points ? fl_end_points() : fl_end_line(); fl_pop_matrix(); fl_pop_clip(); } public: Drawing(int X,int Y,int W,int H) : Fl_Widget(X,Y,W,H) {} }; Drawing *d; void points_cb(Fl_Widget* o, void*) { points = ((Fl_Toggle_Button*)o)->value(); d->redraw(); } void slider_cb(Fl_Widget* o, void* v) { Fl_Slider* s = (Fl_Slider*)o; args[fl_intptr_t(v)] = s->value(); d->redraw(); } int main(int argc, char** argv) { Fl_Double_Window window(300,555); Drawing drawing(10,10,280,280); d = &drawing; int y = 300; for (int n = 0; n<9; n++) { Fl_Slider* s = new Fl_Hor_Value_Slider(50,y,240,25,name[n]); y += 25; s->minimum(0); s->maximum(280); if (n == 8) s->maximum(360); s->step(1); s->value(args[n]); s->align(FL_ALIGN_LEFT); s->callback(slider_cb, (void*)(fl_intptr_t)n); } Fl_Toggle_Button but(50,y,50,25,"points"); but.callback(points_cb); window.end(); window.show(argc,argv); return Fl::run(); } fltk-1.4.3/test/symbols.cxx0000644000175000017500000000711515004135251016004 0ustar albrechtalbrecht// // Symbol test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include int N = 0; #define W 70 #define H 70 #define ROWS 6 #define COLS 7 Fl_Double_Window *window; Fl_Value_Slider *orientation; Fl_Value_Slider *size; void slider_cb(Fl_Widget *, void *) { static char buf[80]; int val = (int)orientation->value(); int sze = (int)size->value(); for (int i = window->children(); i--; ) { // all window children Fl_Widget *wc = window->child(i); const char *l = (const char *)(wc->user_data()); if ( l && *l == '@' ) { // all children with '@' l ++; if ( wc->box() == FL_NO_BOX ) { // ascii legend? if (val&&sze) snprintf(buf, sizeof(buf), "@@%+d%d%s", sze, val, l); else if (val) snprintf(buf, sizeof(buf), "@@%d%s", val, l); else if (sze) snprintf(buf, sizeof(buf), "@@%+d%s", sze, l); else snprintf(buf, sizeof(buf), "@@%s", l); } else { // box with symbol if (val&&sze) snprintf(buf, sizeof(buf), "@%+d%d%s", sze, val, l); else if (val) snprintf(buf, sizeof(buf), "@%d%s", val, l); else if (sze) snprintf(buf, sizeof(buf), "@%+d%s", sze, l); else snprintf(buf, sizeof(buf), "@%s", l); } wc->copy_label(buf); } } window->redraw(); } void bt(const char *name) { int x = N%COLS; int y = N/COLS; char buf[255]; N++; x = x*W+10; y = y*H+10; snprintf(buf, sizeof(buf), "@%s", name); Fl_Box *a = new Fl_Box(x,y,W-20,H-20); a->box(FL_NO_BOX); a->copy_label(buf); a->align(FL_ALIGN_BOTTOM); a->labelsize(11); a->user_data((void *)name); Fl_Box *b = new Fl_Box(x,y,W-20,H-20); b->box(FL_UP_BOX); b->copy_label(name); b->labelcolor(FL_DARK3); b->user_data((void *)name); } int main(int argc, char ** argv) { window = new Fl_Double_Window(COLS*W,ROWS*H+60); bt("@->"); bt("@>"); bt("@>>"); bt("@>|"); bt("@>[]"); bt("@|>"); bt("@<-"); bt("@<"); bt("@<<"); bt("@|<"); bt("@[]<"); bt("@<|"); bt("@<->"); bt("@-->"); bt("@+"); bt("@->|"); bt("@||"); bt("@arrow"); bt("@returnarrow"); bt("@square"); bt("@circle"); bt("@line"); bt("@menu"); bt("@UpArrow"); bt("@DnArrow"); bt("@search"); bt("@FLTK"); bt("@filenew"); bt("@fileopen"); bt("@filesave"); bt("@filesaveas"); bt("@fileprint"); bt("@refresh"); bt("@reload"); bt("@undo"); bt("@redo"); bt("@import"); bt("@export"); orientation = new Fl_Value_Slider( (int)(window->w()*.05+.5), window->h()-40, (int)(window->w()*.42+.5), 16, "Orientation"); orientation->type(FL_HORIZONTAL); orientation->range(0.0, 9.0); orientation->value(0.0); orientation->step(1); orientation->callback(slider_cb, 0); size = new Fl_Value_Slider( (int)(window->w()*.53+.5), window->h()-40, (int)(window->w()*.42+.5), 16, "Size"); size->type(FL_HORIZONTAL); size->range(-3.0, 9.0); size->value(0.0); size->step(1); size->callback(slider_cb, 0); window->resizable(window); window->show(argc,argv); return Fl::run(); } fltk-1.4.3/test/shape.cxx0000644000175000017500000000464615004135251015422 0ustar albrechtalbrecht// // Tiny OpenGL demo program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #if HAVE_GL #include #include class shape_window : public Fl_Gl_Window { void draw() FL_OVERRIDE; public: int sides; shape_window(int x,int y,int w,int h,const char *l=0); }; shape_window::shape_window(int x,int y,int w,int h,const char *l) : Fl_Gl_Window(x,y,w,h,l) { sides = 3; } void shape_window::draw() { // the valid() property may be used to avoid reinitializing your // GL transformation for each redraw: if (!valid()) { valid(1); glLoadIdentity(); glViewport(0, 0, pixel_w(), pixel_h()); } // draw an amazing graphic: glClear(GL_COLOR_BUFFER_BIT); glColor3f(.5f, .6f, .7f); glBegin(GL_POLYGON); for (int j=0; j class shape_window : public Fl_Box { public: int sides; shape_window(int x,int y,int w,int h,const char *l=0) :Fl_Box(FL_DOWN_BOX,x,y,w,h,l){ label("This demo does\nnot work without GL"); } }; #endif // when you change the data, as in this callback, you must call redraw(): void sides_cb(Fl_Widget *o, void *p) { shape_window *sw = (shape_window *)p; sw->sides = int(((Fl_Slider *)o)->value()); sw->redraw(); } int main(int argc, char **argv) { Fl::use_high_res_GL(1); Fl_Window window(300, 330); // the shape window could be it's own window, but here we make it // a child window: shape_window sw(10, 10, 280, 280); // make it resize: window.resizable(&sw); // window.size_range(300,330,0,0,1,1,1); // add a knob to control it: Fl_Hor_Slider slider(50, 295, window.w()-60, 30, "Sides:"); slider.align(FL_ALIGN_LEFT); slider.callback(sides_cb,&sw); slider.value(sw.sides); slider.step(1); slider.bounds(3,40); window.end(); window.show(argc,argv); return Fl::run(); } fltk-1.4.3/test/CubeMain.cxx0000644000175000017500000000124715004135251015777 0ustar albrechtalbrecht// // CubeView class . // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "CubeViewUI.h" int main(int argc, char **argv) { CubeViewUI *cvui=new CubeViewUI; //Initial global objects. Fl::visual(FL_DOUBLE|FL_INDEX); cvui->show(argc, argv); return Fl::run(); } fltk-1.4.3/test/tile.cxx0000644000175000017500000000622415004135251015251 0ustar albrechtalbrecht// // Fl_Tile test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include // #define TEST_INACTIVE // #define CLASSIC_MODE int main(int argc, char** argv) { #if 0 // Sample code from Fl_Tile documentation Fl_Window win(400, 300, "My App"); Fl_Tile tile(0, 0, 400, 300); Fl_Box left_tool_box(0, 0, 100, 300, "Tools"); left_tool_box.box(FL_DOWN_BOX); tile.size_range(&left_tool_box, 50, 50); Fl_Box document(100, 0, 200, 300, "Document"); document.box(FL_DOWN_BOX); tile.size_range(&document, 100, 50); Fl_Box right_tool_box(300, 0, 100, 300, "More\nTools"); right_tool_box.box(FL_DOWN_BOX); tile.size_range(&right_tool_box, 50, 50); tile.end(); tile.resizable(document); win.end(); win.resizable(tile); win.size_range(200, 50); win.show(argc,argv); #else // new Fl_Tile test code Fl_Double_Window window(300, 300); window.box(FL_NO_BOX); window.resizable(window); Fl_Tile tile(0, 0, 300, 300); #ifndef CLASSIC_MODE tile.init_size_range(30, 30); // all children's size shall be at least 30x30 #endif // create the symmetrical resize box with dx and dy pixels distance, resp. // from the borders of the Fl_Tile widget before all other children #ifdef CLASSIC_MODE int dx = 20, dy = dx; // border width of resizable() Fl_Box r(tile.x()+dx,tile.y()+dy,tile.w()-2*dx,tile.h()-2*dy); tile.resizable(r); #endif Fl_Box box0(0,0,150,150,"0"); box0.box(FL_DOWN_BOX); box0.color(9); box0.labelsize(36); box0.align(FL_ALIGN_CLIP); #ifndef CLASSIC_MODE tile.resizable(&box0); #endif Fl_Double_Window w1(150,0,150,150,"1"); w1.box(FL_NO_BOX); Fl_Box box1(0,0,150,150,"1\nThis is a child window"); box1.box(FL_DOWN_BOX); box1.color(19); box1.labelsize(18); box1.align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE|FL_ALIGN_WRAP); w1.resizable(box1); w1.end(); // Fl_Tile tile2(0,150,150,150); Fl_Box box2a(0,150,70,150,"2a"); box2a.box(FL_DOWN_BOX); box2a.color(12); box2a.labelsize(36); box2a.align(FL_ALIGN_CLIP); Fl_Box box2b(70,150,80,150,"2b"); box2b.box(FL_DOWN_BOX); box2b.color(13); box2b.labelsize(36); box2b.align(FL_ALIGN_CLIP); // tile2.end(); // Fl_Tile tile3(150,150,150,150); Fl_Box box3a(150,150,150,70,"3a"); box3a.box(FL_DOWN_BOX); box3a.color(12); box3a.labelsize(36); box3a.align(FL_ALIGN_CLIP); Fl_Box box3b(150,150+70,150,80,"3b"); box3b.box(FL_DOWN_BOX); box3b.color(13); box3b.labelsize(36); box3b.align(FL_ALIGN_CLIP); // tile3.end(); tile.end(); window.end(); #ifdef TEST_INACTIVE // test inactive case tile.deactivate(); #endif w1.show(); window.size_range(90, 90); window.show(argc,argv); #endif // new Fl_Tile test code return Fl::run(); } fltk-1.4.3/test/flex_login.cxx0000644000175000017500000000707015004135251016442 0ustar albrechtalbrecht// // Fl_Flex demo program for the Fast Light Tool Kit (FLTK). // // Copyright 2020 by Karsten Pedersen // Copyright 2022-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include Fl_Button *create_button(const char *caption) { Fl_Button *rtn = new Fl_Button(0, 0, 100, 25, caption); rtn->color(fl_rgb_color(225, 225, 225)); return rtn; } // create widgets inside a column, i.e. parent is type(COLUMN) void buttons_panel(Fl_Flex *parent) { new Fl_Box(0, 0, 0, 0, ""); Fl_Box *title = new Fl_Box(0, 0, 0, 0, "Welcome to Fl_Flex"); title->align(FL_ALIGN_CENTER); title->labelfont(FL_BOLD + FL_ITALIC); title->labelsize(16); Fl_Flex *urow = new Fl_Flex(Fl_Flex::ROW); { Fl_Box *b = new Fl_Box(0, 0, 0, 0, "Username:"); b->align(FL_ALIGN_INSIDE | FL_ALIGN_RIGHT); Fl_Input *username = new Fl_Input(0, 0, 0, 0, ""); urow->fixed(username, 180); urow->end(); } Fl_Flex *prow = new Fl_Flex(Fl_Flex::ROW); { Fl_Box *b = new Fl_Box(0, 0, 0, 0, "Password:"); b->align(FL_ALIGN_INSIDE | FL_ALIGN_RIGHT); Fl_Input *password = new Fl_Input(0, 0, 0, 0, ""); prow->fixed(password, 180); prow->end(); } Fl_Box *pad = new Fl_Box(0, 0, 0, 0, ""); Fl_Flex *brow = new Fl_Flex(Fl_Flex::ROW); { new Fl_Box(0, 0, 0, 0, ""); Fl_Button *reg = create_button("Register"); Fl_Button *login = create_button("Login"); brow->fixed(reg, 80); brow->fixed(login, 80); brow->gap(20); brow->end(); } Fl_Box *b = new Fl_Box(0, 0, 0, 0, ""); parent->fixed(title, 60); parent->fixed(urow, 30); parent->fixed(prow, 30); parent->fixed(pad, 1); parent->fixed(brow, 30); parent->fixed(b, 30); } // create widgets inside a row, i.e. parent is type(ROW) void middle_panel(Fl_Flex *parent) { new Fl_Box(0, 0, 0, 0, ""); Fl_Box *box = new Fl_Box(0, 0, 0, 0, "Image"); box->box(FL_BORDER_BOX); box->color(fl_rgb_color(0, 200, 0)); Fl_Box *spacer = new Fl_Box(0, 0, 0, 0, ""); Fl_Flex *bp = new Fl_Flex(Fl_Flex::COLUMN); buttons_panel(bp); bp->end(); new Fl_Box(0, 0, 0, 0, ""); parent->fixed(box, 150); parent->fixed(spacer, 10); parent->fixed(bp, 300); } // The main panel consists of three "rows" inside a column, i.e. parent is // type(COLUMN). The middle panel has a fixed size (200) such that the two // boxes take the remaining space and middle_panel has all widgets. void mainPanel(Fl_Flex *parent) { new Fl_Box(0, 0, 0, 0, ""); // flexible separator Fl_Flex *mp = new Fl_Flex(Fl_Flex::ROW); middle_panel(mp); mp->end(); new Fl_Box(0, 0, 0, 0, ""); // flexible separator parent->fixed(mp, 200); } int main(int argc, char **argv) { Fl_Window *win = new Fl_Double_Window(100, 100, "Fl_Flex \"Login\" Layout"); Fl_Flex *col = new Fl_Flex(5, 5, 90, 90, Fl_Flex::COLUMN); mainPanel(col); col->end(); win->resizable(col); win->color(fl_rgb_color(250, 250, 250)); win->end(); win->resize(0, 0, 600, 300); // same size as grid_login win->size_range(550, 250); win->show(argc, argv); int ret = Fl::run(); delete win; // not necessary but useful to test for memory leaks return ret; } fltk-1.4.3/test/grid_login.cxx0000644000175000017500000000555315004135251016435 0ustar albrechtalbrecht// // Fl_Grid demo program for the Fast Light Tool Kit (FLTK). // // Copyright 2021 by Albrecht Schlosser // Copyright 2022-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include int main(int argc, char **argv) { Fl_Double_Window *win = new Fl_Double_Window(480, 200, "Fl_Grid \"Login\" Layout"); // Fl_Grid of 6 x 6 cells, margin 2 and gap 2 Fl_Grid *grid = new Fl_Grid(5, 5, 470, 190); grid->layout(6, 6, 2, 2); // 6 rows, 6 columns, margin 2, gap 2 // image (150x200) in left column Fl_Box *ibox = new Fl_Box(0, 0, 150, 200, "Image"); ibox->box(FL_BORDER_BOX); ibox->color(fl_rgb_color(0, 200, 0)); grid->widget(ibox, 1, 1, 4, 1, FL_GRID_CENTER); // the title spans 2 columns (3 - 4) Fl_Box *title = new Fl_Box(0, 0, 200, 60); title->label("Welcome to Fl_Grid"); title->align(FL_ALIGN_CENTER); title->labelfont(FL_BOLD + FL_ITALIC); title->labelsize(16); grid->widget(title, 1, 3, 1, 2, FL_GRID_HORIZONTAL | FL_GRID_CENTER); grid->col_width(2, 90); // placeholder for labels // input widgets with fixed height and horizontal stretching Fl_Input *i1 = new Fl_Input(0, 0, 150, 30, "Username:"); grid->widget(i1, 2, 3, 1, 2, FL_GRID_HORIZONTAL); grid->row_gap(2, 10); // gap below username Fl_Input *i2 = new Fl_Input(0, 0, 150, 30, "Password:"); grid->widget(i2, 3, 3, 1, 2, FL_GRID_HORIZONTAL); grid->row_gap(3, 10); // gap below password // register and login buttons Fl_Button *btr = new Fl_Button(0, 0, 80, 30, "Register"); grid->widget(btr, 4, 3, 1, 1, FL_GRID_HORIZONTAL); grid->col_gap(3, 20); // gap right of the register button Fl_Button *btl = new Fl_Button(0, 0, 80, 30, "Login"); grid->widget(btl, 4, 4, 1, 1, FL_GRID_HORIZONTAL); // set column and row weights for resizing behavior (optional) int cw[] = { 20, 0, 0, 10, 10, 20}; // column weights int rw[] = { 10, 0, 0, 0, 0, 10}; // row weights grid->col_weight(cw, 6); grid->row_weight(rw, 6); grid->end(); grid->layout(); // grid->debug(1); // grid->show_grid(1); // enable to display grid helper lines win->end(); grid->color(fl_rgb_color(250, 250, 250)); win->color(fl_rgb_color(250, 250, 250)); win->resizable(grid); win->resize(0, 0, 600, 300); // same size as flex_login win->size_range(550, 250); win->show(argc, argv); int ret = Fl::run(); delete win; // not necessary but useful to test for memory leaks return ret; } fltk-1.4.3/test/terminal.fl0000644000175000017500000037762615004135251015747 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 utf8_in_src header_name {.h} code_name {.cxx} comment {DEVELOPER README APPLICATION ----------- The Application class encompasses the entire application, and has the widget hierarchy declared by main_window(). SELF TESTS ---------- The "self tests" are all named test_xxx(), and are static functions because they were designed that way originally (testterm.cxx), so they remain static. They only need access to the global G_tty to access the terminal for printing, and handle their own state information. To add /new/ tests: 1. Create the test function similar to existing test_xxx(). 2. Add the function's name to the NextEscapeTest() function's This makes the new test become part of the self tests. NextEscapeTest() keeps track of the last test shown as a static value internally, and the integer argument tells it how to advance to the next test, either fwd or back. The tests themselves may keep state information, so that a single test might have several pages. The return value determines whether to recall the test again, or if it's on the last page. } {in_source not_in_header } decl {\#include } {public global } decl {\#include // rand()} {private global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#ifdef _WIN32} {public global } decl {\#include // _read()} {public global } decl {\#else} {public global } decl {\#include // read()} {public global } decl {\#endif} {public global } decl {MyTerminal *G_tty;} { comment {Global access to tty} private global } decl {Application *G_app;} { comment {Global access to application} private global } decl {////// TERMINAL RING BUFFER DEBUG CLASS //////} {private local } class MyTerminal { comment {Fl_Terminal derived class that can access ring buffer internals for debugging} open : {public Fl_Terminal} } { decl {Fl_Double_Window *ring_debug_win;} {private local } decl {Fl_Terminal *debug_tty;} {private local } decl {bool interactivecursor;} {private local } Function {MyTerminal(int X,int Y,int W,int H, const char *L=0):Fl_Terminal(X,Y,W,H,L)} { comment CTOR open } { code {ring_debug_win = 0; debug_tty = 0; interactivecursor = false;} {} } Function {show_ring_debug_window()} {return_type void } { code {// Show the internal ring debug window if (!ring_debug_win) { ring_debug_win = new Fl_Double_Window(1250,800,"Fl_Terminal Ring Buffer"); ring_debug_win->resizable(ring_debug_win); ring_debug_win->callback(debug_winquit_callback, (void*)this); debug_tty = new Fl_Terminal(0,0,ring_debug_win->w(),ring_debug_win->h()); debug_tty->textsize(7); debug_tty->redraw_style(NO_REDRAW); debug_tty->display_columns(400); ring_debug_win->end(); } ring_debug_win->show(); // Start timer to update ring debug updates Fl::add_timeout(.5, ring_debug_timer_callback, (void*)this);} {} } Function {interactive_cursor(bool val)} { comment {Enable/disable interactive cursor movement in test app} return_type void } { code {interactivecursor = val;} {} } Function {debug_winquit_callback2()} {return_type void } { code {// Hide debug window, disable its update timer ring_debug_win->hide(); Fl::remove_timeout(ring_debug_timer_callback, (void*)this);} {} } Function {debug_winquit_callback(Fl_Widget*,void *userdata)} {return_type {static void} } { code {MyTerminal *o = (MyTerminal*)userdata; o->debug_winquit_callback2();} {} } Function {horiz_bracket(int w)} { comment {Print a graphic horizontally oriented bracket of width w} return_type void } { code {debug_tty->append("┏"); for (int t=0; tprint_char("━"); } debug_tty->append("┓");} {} } Function {update_ring()} {open return_type void } { code {// Handle updating the ring debug window's contents int m1,m2,m3,m4; get_selection(m1,m2,m3,m4); // These reference the Fl_Terminal base class protected members int x = 5; debug_tty->append("\\033c"); // reset terminal (clear screen, history, home) debug_tty->append("\\033[s"); // save cursor debug_tty->printf("\\033[%dC \\033[7m Ring Index \\033[0m\\n", x); debug_tty->printf("\\033[%dC ring_rows(): %-3d Mouse Selection (srow,scol,erow,ecol)\\n", x, ring_rows()); debug_tty->printf("\\033[%dC ring_cols(): %-3d \\033[7m(%d,%d,%d,%d)\\033[0m\\n", x, ring_cols(), m1,m2,m3,m4); debug_tty->printf("\\033[%dC offset(): %-3d currentstyle->charflags=%02x\\n", x, offset(), (unsigned int)current_style().charflags()); // charflags(): show XTERM flags if any debug_tty->printf("\\033[%dC ", x); horiz_bracket(disp_cols()); debug_tty->printf("\\033[u"); // recall cursor x += disp_cols() + 11; debug_tty->printf("\\033[%dC \\033[7m History Index \\033[0m\\n", x); debug_tty->printf("\\033[%dC hist_rows(): %d hist_srow()=%d\\n", x, hist_rows(), hist_srow()); debug_tty->printf("\\033[%dC hist_cols(): %d hist_erow()=%d\\n", x, hist_cols(), hist_erow()); debug_tty->printf("\\033[%dC hist_use(): %d\\n", x, hist_use()); debug_tty->printf("\\033[%dC ", x); horiz_bracket(disp_cols()); debug_tty->append("\\033[u"); // recall cursor x += disp_cols() + 11; debug_tty->printf("\\033[%dC \\033[7m Display Index \\033[0m\\n", x); debug_tty->printf("\\033[%dC disp_rows(): %d disp_srow()=%d\\n", x, disp_rows(), disp_srow()); debug_tty->printf("\\033[%dC disp_cols(): %d disp_erow()=%d\\n", x, disp_cols(), disp_erow()); debug_tty->append("\\n"); debug_tty->printf("\\033[%dC ", x); horiz_bracket(disp_cols()); debug_tty->append("\\n"); { for ( int row=0; rowprintf("%3d R[", row); for ( int col=0; coltextattrib(u8c->attrib()); debug_tty->textfgcolor(u8c->fgcolor()); debug_tty->textbgcolor(u8c->bgcolor()); debug_tty->print_char(u8c->text_utf8()); // print the char in current style } debug_tty->append("\\033[0m"); // restore default fg/bg/attrib debug_tty->append("] "); // SHOW HISTORY if ( row < hist_rows() ) { u8c = u8c_ring_row(hist_srow() + row); debug_tty->printf("%3d H[", row); for ( int col=0; coltextattrib(u8c->attrib()); debug_tty->textfgcolor(u8c->fgcolor()); debug_tty->textbgcolor(u8c->bgcolor()); debug_tty->print_char(u8c->text_utf8()); // print the char in current style } debug_tty->append("\\033[0m"); // restore default fg/bg/attrib debug_tty->printf("] "); } else { debug_tty->append(" "); for ( int col=0; colappend(" "); } debug_tty->append(" "); } // SHOW DISPLAY if ( row < disp_rows() ) { u8c = u8c_ring_row(disp_srow() + row); debug_tty->printf("%3d D[", row); for ( int col=0; coltextattrib(u8c->attrib()); debug_tty->textfgcolor(u8c->fgcolor()); debug_tty->textbgcolor(u8c->bgcolor()); debug_tty->print_char(u8c->text_utf8()); // print the char in current style } debug_tty->append("\\033[0m"); // restore default fg/bg/attrib debug_tty->append("]\\033[K\\n"); } else { debug_tty->append("\\033[K\\n"); } } } debug_tty->printf("--- END\\033[0J\\n"); // clear eos} {} } Function {ring_debug_timer_callback2()} {open return_type void } { code {// Update the ring debug window update_ring(); // Redraw after all changes have been made ring_debug_win->redraw(); Fl::repeat_timeout(.10, ring_debug_timer_callback, (void*)this);} {} } Function {ring_debug_timer_callback(void* userdata)} {return_type {static void} } { code {MyTerminal *o = (MyTerminal*)userdata; o->ring_debug_timer_callback2();} {} } Function {handle(int e) FL_OVERRIDE} { comment {Event handler} return_type int } { code {switch (e) { case FL_KEYBOARD: { if (interactivecursor) { switch (Fl::event_key()) { case FL_Up: cursor_up(1,true); redraw(); return 1; case FL_Down: cursor_down(1,true); redraw(); return 1; case FL_Left: cursor_left(); redraw(); return 1; case FL_Right: cursor_right(); redraw(); return 1; } } break; } } return Fl_Terminal::handle(e);} {} } } decl {////// APPLICATION CLASS //////} {private local } class Application {open } { decl {int G_lines;} { comment {Line counter for +50 line test } private local } Function {Application()} { comment {// Ctor} } { code {// CTOR G_lines = 1; make_window(); // Do widget init in make_window()'s extra 'Code' section, not here.} {} } Function {show(int argc=0, char **argv=0)} { comment {Show the app window } return_type void } { code {if (argv) win->show(argc,argv); else win->show();} {} } Function {AppendTty(const char *s)} { comment {Append text to Fl_Terminal (and stdout if radio button set) } return_type void } { code {// Append to Fl_Terminal G_tty->append(s); // Send to stdout too? if (G_app->stdout_radio->value()) { printf("%s", s); fflush(stdout); }} {} } decl {////// ESC SELF TESTS //////} {private local } Function {NextEscapeTest(int dir)} { comment {Advance/Reverse thru escape code tests} open return_type {static void} } { code {// *** ADD NEW TESTS HERE *** typedef int (TestFunc)(bool); static int testret = 1; // last test return value static int testnum = 0; static TestFunc *tests[] = { test_firstpage, test_esc_attr, test_esc_rgbcolors, test_esc_fgbg_colors, test_esc_curpos, test_esc_tabstops, test_esc_insert_char, test_esc_clear_test, test_esc_delete_row, test_esc_insert_row, test_esc_scrolling // ^^^ INSERT NEW TEST FUNCS ABOVE THIS LINE ^^^ }; int numtests = sizeof(tests) / sizeof(TestFunc*); testnum += (dir * testret); // advance testnum only if last test isn't recall if (testnum >= numtests) testnum = 0; if (testnum < 0) testnum = numtests-1; if (dir == 10000) { // 1000: special case to reset all tests, run first test testnum = 0; // run first test for ( int i=0; icursor_col()!=0) G_tty->append("\\n"); ****/ // Run test, save return value testret = tests[testnum](false); G_tty->redraw();} {} } Function {show_test(const char **test, int &index)} { comment {Show test in test[] starting at 'index', returns 0 or 1 } return_type {static int} } { code {// Show test in test[] starting at 'index'. // 'index' is adjusted to point to next test. // Returns number to add to parent test index: // 0 - test shown, call here again for next page in this test // 1 - test shown, move on to next test for next time // while (test[index]) { G_app->AppendTty(test[index++]); if (strncmp(test[index-1], "--->", 4) == 0 ) { if (test[index] == NULL) { index = 0; return 1; } // rewind, tell parent to move to next test else { return 0; } // tell parent to call us again for next test } } index = 0; return 1; // hit end of test, reset} {} } Function {test_firstpage(bool reset)} { comment {--- 0000: Test unicode alignment} return_type {static int} } { code {(void) reset; // unused arg: quiets compiler warnings G_app->AppendTty( "\\033[0m\\033[H\\033[2J\\033[3J" // color/attr reset, home, cls, clear history "hello.\\nLine one\\nLine two\\n" "\\033[0;0;2m Dim text:\\033[31m red\\033[32m grn\\033[33m yel" "\\033[34m blu\\033[35m mag\\033[36m cyn\\033[37m wht\\n" "\\033[0;0;0m Normal text:\\033[31m red\\033[32m grn\\033[33m yel" "\\033[34m blu\\033[35m mag\\033[36m cyn\\033[37m wht\\n" "\\033[0;0;1m Bold text:\\033[31m red\\033[32m grn\\033[33m yel" "\\033[34m blu\\033[35m mag\\033[36m cyn\\033[37m wht\\n" "\\033[0;1;3m Bold Italic text:\\033[31m red\\033[32m grn\\033[33m yel" "\\033[34m blu\\033[35m mag\\033[36m cyn\\033[37m wht\\n" "\\033[0m\\n" // Language Language // Alignment Alignment // <-----> <----> "Here's some utf8: ||| AAA || AAA\\n" "╳╳ ██ ▏▏┌─┬┐ ┏━┳┓ ╔═╦╗ ██████ ||| AAA Hell Yeah Jim - English || AAA\\n" "╳╳ ██ ▏▏│ ││ ┃ ┃┃ ║ ║║ ██ ██ ||| AAA Первый рабочий - Russian || AAA\\n" "╳╳ ██ ▏▏├─┼┤ ┣━╋┫ ╠═╬╣ ██ ██ ||| AAA テキスト処理法 - Japanese || AAA\\n" "╳╳ ██ ▏▏└─┴┘ ┗━┻┛ ╚═╩╝ ██████ ||| AAA 香港增补字符集 - Chinese || AAA\\n" " ||| AAA || AAA\\n" "underbar: ______ ||| AAA || AAA\\n" " overbar: ‾‾‾‾‾‾ ||| AAA || AAA\\n" "\\n" "\\033[23X >> KEYBOARD KEYS: Arrow keys move cursor <<\\n" "\\033[23X >> 's'=speed test 'c'=colorbars <<\\n" "\\033[23X >> 'e'=next esc test 'E'=prev esc test <<\\n" "\\033[23X >> 'q'=quit <<\\n" "\\033[23X >> <<\\n" "\\033[23X >> <<\\n" "\\n" "Some floating text. >X<\\b\\033[D"); // put cursor between > < using BS and cursor_left return 1; // tell parent to move to next test} {} } Function {test_esc_attr(bool reset)} { comment {--- 0010: Test attributes} open return_type {static int} } { code {static int index = 0; const char *test[] = { // Screen 10 "\\033[H\\033[2J" "ESC TEST 0010: Attributes\\n", " \\033[0;2m Some Dim text [█]\\033[0m \\033[0m Normal text [█]\\033[0m \\033[0;1m Some Bold text [█]\\033[0m\\n" " \\033[2;3m Dim italic [█]\\033[0m \\033[3m Normal italic [█]\\033[0m \\033[1;3m Bold italic [█]\\033[0m\\n" " \\033[2;4m Dim underline [█]\\033[0m \\033[4m Normal underline [█]\\033[0m \\033[1;4m Bold underline [█]\\033[0m\\n" " \\033[2;5m Dim blinking [█]\\033[0m \\033[5m Normal blinking [█]\\033[0m \\033[1;5m Bold blinking [█]\\033[0m\\n" " \\033[2;7m Dim inverse [█]\\033[0m \\033[7m Normal inverse [█]\\033[0m \\033[1;7m Bold inverse [█]\\033[0m\\n" " \\033[2;9m Dim strikeout [█]\\033[0m \\033[9m Normal strikeout [█]\\033[0m \\033[1;9m Bold strikeout [█]\\033[0m\\n" "\\n" "Xterm Colors With Attributes\\n" " \\033[2;3m(Dim+Bold attributes should affect brightness of all xterm colors)\\033\\n" " \\033[2;30m Dim Blk(30) [█]\\033[0m \\033[30m Normal Blk(30) [█]\\033[0m \\033[1;30m Bold Blk(30) [█]\\033[0m\\n" " \\033[2;31m Dim Red(31) [█]\\033[0m \\033[31m Normal Red(31) [█]\\033[0m \\033[1;31m Bold Red(31) [█]\\033[0m\\n" " \\033[2;32m Dim Grn(32) [█]\\033[0m \\033[32m Normal Grn(32) [█]\\033[0m \\033[1;32m Bold Grn(32) [█]\\033[0m\\n" " \\033[2;33m Dim Yel(33) [█]\\033[0m \\033[33m Normal Yel(33) [█]\\033[0m \\033[1;33m Bold Yel(33) [█]\\033[0m\\n" " \\033[2;34m Dim Blu(34) [█]\\033[0m \\033[34m Normal Blu(34) [█]\\033[0m \\033[1;34m Bold Blu(34) [█]\\033[0m\\n" " \\033[2;35m Dim Mag(35) [█]\\033[0m \\033[35m Normal Mag(35) [█]\\033[0m \\033[1;35m Bold Mag(35) [█]\\033[0m\\n" " \\033[2;36m Dim Cyn(36) [█]\\033[0m \\033[36m Normal Cyn(36) [█]\\033[0m \\033[1;36m Bold Cyn(36) [█]\\033[0m\\n" " \\033[2;37m Dim ---(37) [█]\\033[0m \\033[37m Normal ---(37) [█]\\033[0m \\033[1;37m Bold ---(37) [█]\\033[0m\\n" " \\033[2;38m Dim ---(38) [█]\\033[0m \\033[38m Normal ---(38) [█]\\033[0m \\033[1;38m Bold ---(38) [█]\\033[0m\\n" " \\033[2;39m Dim Def(39) [█]\\033[0m \\033[39m Normal Def(39) [█]\\033[0m \\033[1;39m Bold Def(39) [█]\\033[0m\\n" "\\n" "Xterm Fg/Bg Colors With Attributes\\n" // walk fg colors 30..36, bg reset (49+0) " Fg Bold:\\033[1;49;30m█ Def █\\033[31m█ Red █\\033[32m█ Grn █\\033[33m█ Yel █\\033[34m█ Blu █\\033[35m█ Mag █\\033[36m█ Cyn █\\033[0m " " \\033[00;1;30m█ Def █\\033[31m█ Red █\\033[32m█ Grn █\\033[33m█ Yel █\\033[34m█ Blu █\\033[35m█ Mag █\\033[36m█ Cyn █\\033[0m\\n" " Fg Norm:\\033[0;49;30m█ Def █\\033[31m█ Red █\\033[32m█ Grn █\\033[33m█ Yel █\\033[34m█ Blu █\\033[35m█ Mag █\\033[36m█ Cyn █\\033[0m " " \\033[00;0;30m█ Def █\\033[31m█ Red █\\033[32m█ Grn █\\033[33m█ Yel █\\033[34m█ Blu █\\033[35m█ Mag █\\033[36m█ Cyn █\\033[0m\\n" " Fg Dim:\\033[2;49;30m█ Def █\\033[31m█ Red █\\033[32m█ Grn █\\033[33m█ Yel █\\033[34m█ Blu █\\033[35m█ Mag █\\033[36m█ Cyn █\\033[0m " " \\033[00;2;30m█ Def █\\033[31m█ Red █\\033[32m█ Grn █\\033[33m█ Yel █\\033[34m█ Blu █\\033[35m█ Mag █\\033[36m█ Cyn █\\033[0m\\n" "\\n" // walk bg colors 40..46, fg reset (39+0) " Bg Bold:\\033[1;39;40m█ Def █\\033[41m█ Red █\\033[42m█ Grn █\\033[43m█ Yel █\\033[44m█ Blu █\\033[45m█ Mag █\\033[46m█ Cyn █\\033[0m " " \\033[00;1;40m█ Def █\\033[41m█ Red █\\033[42m█ Grn █\\033[43m█ Yel █\\033[44m█ Blu █\\033[45m█ Mag █\\033[46m█ Cyn █\\033[0m\\n" " Bg Norm:\\033[0;39;40m█ Def █\\033[41m█ Red █\\033[42m█ Grn █\\033[43m█ Yel █\\033[44m█ Blu █\\033[45m█ Mag █\\033[46m█ Cyn █\\033[0m " " \\033[00;0;40m█ Def █\\033[41m█ Red █\\033[42m█ Grn █\\033[43m█ Yel █\\033[44m█ Blu █\\033[45m█ Mag █\\033[46m█ Cyn █\\033[0m\\n" " Bg Dim:\\033[2;39;40m█ Def █\\033[41m█ Red █\\033[42m█ Grn █\\033[43m█ Yel █\\033[44m█ Blu █\\033[45m█ Mag █\\033[46m█ Cyn █\\033[0m " " \\033[00;2;40m█ Def █\\033[41m█ Red █\\033[42m█ Grn █\\033[43m█ Yel █\\033[44m█ Blu █\\033[45m█ Mag █\\033[46m█ Cyn █\\033[0m\\n" "\\n", "---> Hit 'e' for next test: ", NULL }; if (reset) { index = 0; return 0; } return show_test(test, index);} {selected } } Function {test_esc_rgbcolors(bool reset)} { comment {--- 0020: Test RGB Colors} return_type {static int} } { code {static int index = 0; const char *test[] = { // Screen 20 "\\033[2J\\033[H" "ESC TEST 0020: RGB Colors\\n", "\\033[0m\\n", // NORMAL "\\tNormal Grayscale: \\033[38;2;32;32;32mXXX" "\\033[38;2;64;64;64mXXX" "\\033[38;2;96;96;96mXXX" "\\033[38;2;128;128;128mXXX", "\\033[38;2;160;160;160mXXX" "\\033[38;2;192;192;192mXXX" "\\033[38;2;224;224;224mXXX" "\\033[38;2;255;255;255mXXX", "\\033[38;2;255;0;0m\\n", // change to Red for next row "\\tNormal RedScale: \\033[38;2;32;0;0mXXX" "\\033[38;2;64;0;0mXXX" "\\033[38;2;96;0;0mXXX" "\\033[38;2;128;0;0mXXX", "\\033[38;2;160;0;0mXXX" "\\033[38;2;192;0;0mXXX" "\\033[38;2;224;0;0mXXX" "\\033[38;2;255;0;0mXXX", "\\033[38;2;0;255;0m\\n", // change to Grn for next row "\\tNormal GrnScale: \\033[38;2;0;32;0mXXX" "\\033[38;2;0;64;0mXXX" "\\033[38;2;0;96;0mXXX" "\\033[38;2;0;128;0mXXX", "\\033[38;2;0;160;0mXXX" "\\033[38;2;0;192;0mXXX" "\\033[38;2;0;224;0mXXX" "\\033[38;2;0;255;0mXXX", "\\033[38;2;0;0;255m\\n", // change to Blu for next row "\\tNormal BluScale: \\033[38;2;0;0;32mXXX" "\\033[38;2;0;0;64mXXX" "\\033[38;2;0;0;96mXXX" "\\033[38;2;0;0;128mXXX", "\\033[38;2;0;0;160mXXX" "\\033[38;2;0;0;192mXXX" "\\033[38;2;0;0;224mXXX" "\\033[38;2;0;0;255mXXX", "\\n", "\\033[0;3m\\n", // ITALIC "\\tItalic Grayscale: \\033[38;2;32;32;32mXXX" "\\033[38;2;64;64;64mXXX" "\\033[38;2;96;96;96mXXX" "\\033[38;2;128;128;128mXXX", "\\033[38;2;160;160;160mXXX" "\\033[38;2;192;192;192mXXX" "\\033[38;2;224;224;224mXXX" "\\033[38;2;255;255;255mXXX", "\\033[38;2;255;0;0m\\n", // change to Red for next row "\\tItalic RedScale: \\033[38;2;32;0;0mXXX" "\\033[38;2;64;0;0mXXX" "\\033[38;2;96;0;0mXXX" "\\033[38;2;128;0;0mXXX", "\\033[38;2;160;0;0mXXX" "\\033[38;2;192;0;0mXXX" "\\033[38;2;224;0;0mXXX" "\\033[38;2;255;0;0mXXX", "\\033[38;2;0;255;0m\\n", // change to Grn for next row "\\tItalic GrnScale: \\033[38;2;0;32;0mXXX" "\\033[38;2;0;64;0mXXX" "\\033[38;2;0;96;0mXXX" "\\033[38;2;0;128;0mXXX", "\\033[38;2;0;160;0mXXX" "\\033[38;2;0;192;0mXXX" "\\033[38;2;0;224;0mXXX" "\\033[38;2;0;255;0mXXX", "\\033[38;2;0;0;255m\\n", // change to Blu for next row "\\tItalic BluScale: \\033[38;2;0;0;32mXXX" "\\033[38;2;0;0;64mXXX" "\\033[38;2;0;0;96mXXX" "\\033[38;2;0;0;128mXXX", "\\033[38;2;0;0;160mXXX" "\\033[38;2;0;0;192mXXX" "\\033[38;2;0;0;224mXXX" "\\033[38;2;0;0;255mXXX", "\\n", "\\033[0;4m\\n", // UNDERLINE "\\tUnderl Grayscale: \\033[38;2;32;32;32mXXX" "\\033[38;2;64;64;64mXXX" "\\033[38;2;96;96;96mXXX" "\\033[38;2;128;128;128mXXX", "\\033[38;2;160;160;160mXXX" "\\033[38;2;192;192;192mXXX" "\\033[38;2;224;224;224mXXX" "\\033[38;2;255;255;255mXXX", "\\033[38;2;255;0;0m\\n", // change to Red for next row "\\tUnderl RedScale: \\033[38;2;32;0;0mXXX" "\\033[38;2;64;0;0mXXX" "\\033[38;2;96;0;0mXXX" "\\033[38;2;128;0;0mXXX", "\\033[38;2;160;0;0mXXX" "\\033[38;2;192;0;0mXXX" "\\033[38;2;224;0;0mXXX" "\\033[38;2;255;0;0mXXX", "\\033[38;2;0;255;0m\\n", // change to Grn for next row "\\tUnderl GrnScale: \\033[38;2;0;32;0mXXX" "\\033[38;2;0;64;0mXXX" "\\033[38;2;0;96;0mXXX" "\\033[38;2;0;128;0mXXX", "\\033[38;2;0;160;0mXXX" "\\033[38;2;0;192;0mXXX" "\\033[38;2;0;224;0mXXX" "\\033[38;2;0;255;0mXXX", "\\033[38;2;0;0;255m\\n", // change to Blu for next row "\\tUnderl BluScale: \\033[38;2;0;0;32mXXX" "\\033[38;2;0;0;64mXXX" "\\033[38;2;0;0;96mXXX" "\\033[38;2;0;0;128mXXX", "\\033[38;2;0;0;160mXXX" "\\033[38;2;0;0;192mXXX" "\\033[38;2;0;0;224mXXX" "\\033[38;2;0;0;255mXXX", "\\n", "\\033[0;7m\\n", // INVERSE "\\tInvers Grayscale: \\033[7;38;2;32;32;32mXXX" "\\033[38;2;64;64;64mXXX" "\\033[38;2;96;96;96mXXX" "\\033[38;2;128;128;128mXXX", "\\033[38;2;160;160;160mXXX" "\\033[38;2;192;192;192mXXX" "\\033[38;2;224;224;224mXXX" "\\033[38;2;255;255;255mXXX", "\\033[38;2;255;0;0m\\n", // change to Red for next row "\\tInvers RedScale: \\033[38;2;32;0;0mXXX" "\\033[38;2;64;0;0mXXX" "\\033[38;2;96;0;0mXXX" "\\033[38;2;128;0;0mXXX", "\\033[38;2;160;0;0mXXX" "\\033[38;2;192;0;0mXXX" "\\033[38;2;224;0;0mXXX" "\\033[38;2;255;0;0mXXX", "\\033[38;2;0;255;0m\\n", // change to Grn for next row "\\tInvers GrnScale: \\033[38;2;0;32;0mXXX" "\\033[38;2;0;64;0mXXX" "\\033[38;2;0;96;0mXXX" "\\033[38;2;0;128;0mXXX", "\\033[38;2;0;160;0mXXX" "\\033[38;2;0;192;0mXXX" "\\033[38;2;0;224;0mXXX" "\\033[38;2;0;255;0mXXX", "\\033[38;2;0;0;255m\\n", // change to Blu for next row "\\tInvers BluScale: \\033[38;2;0;0;32mXXX" "\\033[38;2;0;0;64mXXX" "\\033[38;2;0;0;96mXXX" "\\033[38;2;0;0;128mXXX", "\\033[38;2;0;0;160mXXX" "\\033[38;2;0;0;192mXXX" "\\033[38;2;0;0;224mXXX" "\\033[38;2;0;0;255mXXX", "\\033[0m\\n\\n", "---> Hit 'e' for next test: ", // Screen 21 "\\033[2J\\033[H" "ESC TEST 0021: RGB Color Ramps\\n", "\\n", "Red: ", "\\033[48;2;0;0;0m.\\033[48;2;1;0;0m.\\033[48;2;2;0;0m.\\033[48;2;3;0;0m.\\033[48;2;4;0;0m.\\033[48;2;5;0;0m.\\033[48;2;6;0;0m.\\033[48;2;7;0;0m.", "\\033[48;2;8;0;0m.\\033[48;2;9;0;0m.\\033[48;2;10;0;0m.\\033[48;2;11;0;0m.\\033[48;2;12;0;0m.\\033[48;2;13;0;0m.\\033[48;2;14;0;0m.\\033[48;2;15;0;0m.", "\\033[48;2;16;0;0m.\\033[48;2;17;0;0m.\\033[48;2;18;0;0m.\\033[48;2;19;0;0m.\\033[48;2;20;0;0m.\\033[48;2;21;0;0m.\\033[48;2;22;0;0m.\\033[48;2;23;0;0m.", "\\033[48;2;24;0;0m.\\033[48;2;25;0;0m.\\033[48;2;26;0;0m.\\033[48;2;27;0;0m.\\033[48;2;28;0;0m.\\033[48;2;29;0;0m.\\033[48;2;30;0;0m.\\033[48;2;31;0;0m.", "\\033[48;2;32;0;0m.\\033[48;2;33;0;0m.\\033[48;2;34;0;0m.\\033[48;2;35;0;0m.\\033[48;2;36;0;0m.\\033[48;2;37;0;0m.\\033[48;2;38;0;0m.\\033[48;2;39;0;0m.", "\\033[48;2;40;0;0m.\\033[48;2;41;0;0m.\\033[48;2;42;0;0m.\\033[48;2;43;0;0m.\\033[48;2;44;0;0m.\\033[48;2;45;0;0m.\\033[48;2;46;0;0m.\\033[48;2;47;0;0m.", "\\033[48;2;48;0;0m.\\033[48;2;49;0;0m.\\033[48;2;50;0;0m.\\033[48;2;51;0;0m.\\033[48;2;52;0;0m.\\033[48;2;53;0;0m.\\033[48;2;54;0;0m.\\033[48;2;55;0;0m.", "\\033[48;2;56;0;0m.\\033[48;2;57;0;0m.\\033[48;2;58;0;0m.\\033[48;2;59;0;0m.\\033[48;2;60;0;0m.\\033[48;2;61;0;0m.\\033[48;2;62;0;0m.\\033[48;2;63;0;0m.", "\\033[48;2;64;0;0m.\\033[48;2;65;0;0m.\\033[48;2;66;0;0m.\\033[48;2;67;0;0m.\\033[48;2;68;0;0m.\\033[48;2;69;0;0m.\\033[48;2;70;0;0m.\\033[48;2;71;0;0m.", "\\033[48;2;72;0;0m.\\033[48;2;73;0;0m.\\033[48;2;74;0;0m.\\033[48;2;75;0;0m.\\033[48;2;76;0;0m.\\033[48;2;77;0;0m.\\033[48;2;78;0;0m.\\033[48;2;79;0;0m.", "\\033[48;2;80;0;0m.\\033[48;2;81;0;0m.\\033[48;2;82;0;0m.\\033[48;2;83;0;0m.\\033[48;2;84;0;0m.\\033[48;2;85;0;0m.\\033[48;2;86;0;0m.\\033[48;2;87;0;0m.", "\\033[48;2;88;0;0m.\\033[48;2;89;0;0m.\\033[48;2;90;0;0m.\\033[48;2;91;0;0m.\\033[48;2;92;0;0m.\\033[48;2;93;0;0m.\\033[48;2;94;0;0m.\\033[48;2;95;0;0m.", "\\033[0m\\n ", "\\033[48;2;96;0;0m.\\033[48;2;97;0;0m.\\033[48;2;98;0;0m.\\033[48;2;99;0;0m.\\033[48;2;100;0;0m.\\033[48;2;101;0;0m.\\033[48;2;102;0;0m.\\033[48;2;103;0;0m.", "\\033[48;2;104;0;0m.\\033[48;2;105;0;0m.\\033[48;2;106;0;0m.\\033[48;2;107;0;0m.\\033[48;2;108;0;0m.\\033[48;2;109;0;0m.\\033[48;2;110;0;0m.\\033[48;2;111;0;0m.", "\\033[48;2;112;0;0m.\\033[48;2;113;0;0m.\\033[48;2;114;0;0m.\\033[48;2;115;0;0m.\\033[48;2;116;0;0m.\\033[48;2;117;0;0m.\\033[48;2;118;0;0m.\\033[48;2;119;0;0m.", "\\033[48;2;120;0;0m.\\033[48;2;121;0;0m.\\033[48;2;122;0;0m.\\033[48;2;123;0;0m.\\033[48;2;124;0;0m.\\033[48;2;125;0;0m.\\033[48;2;126;0;0m.\\033[48;2;127;0;0m.", "\\033[48;2;128;0;0m.\\033[48;2;129;0;0m.\\033[48;2;130;0;0m.\\033[48;2;131;0;0m.\\033[48;2;132;0;0m.\\033[48;2;133;0;0m.\\033[48;2;134;0;0m.\\033[48;2;135;0;0m.", "\\033[48;2;136;0;0m.\\033[48;2;137;0;0m.\\033[48;2;138;0;0m.\\033[48;2;139;0;0m.\\033[48;2;140;0;0m.\\033[48;2;141;0;0m.\\033[48;2;142;0;0m.\\033[48;2;143;0;0m.", "\\033[48;2;144;0;0m.\\033[48;2;145;0;0m.\\033[48;2;146;0;0m.\\033[48;2;147;0;0m.\\033[48;2;148;0;0m.\\033[48;2;149;0;0m.\\033[48;2;150;0;0m.\\033[48;2;151;0;0m.", "\\033[48;2;152;0;0m.\\033[48;2;153;0;0m.\\033[48;2;154;0;0m.\\033[48;2;155;0;0m.\\033[48;2;156;0;0m.\\033[48;2;157;0;0m.\\033[48;2;158;0;0m.\\033[48;2;159;0;0m.", "\\033[48;2;160;0;0m.\\033[48;2;161;0;0m.\\033[48;2;162;0;0m.\\033[48;2;163;0;0m.\\033[48;2;164;0;0m.\\033[48;2;165;0;0m.\\033[48;2;166;0;0m.\\033[48;2;167;0;0m.", "\\033[48;2;168;0;0m.\\033[48;2;169;0;0m.\\033[48;2;170;0;0m.\\033[48;2;171;0;0m.\\033[48;2;172;0;0m.\\033[48;2;173;0;0m.\\033[48;2;174;0;0m.\\033[48;2;175;0;0m.", "\\033[48;2;176;0;0m.\\033[48;2;177;0;0m.\\033[48;2;178;0;0m.\\033[48;2;179;0;0m.\\033[48;2;180;0;0m.\\033[48;2;181;0;0m.\\033[48;2;182;0;0m.\\033[48;2;183;0;0m.", "\\033[48;2;184;0;0m.\\033[48;2;185;0;0m.\\033[48;2;186;0;0m.\\033[48;2;187;0;0m.\\033[48;2;188;0;0m.\\033[48;2;189;0;0m.\\033[48;2;190;0;0m.\\033[48;2;191;0;0m.", "\\033[0m\\n ", "\\033[48;2;192;0;0m.\\033[48;2;193;0;0m.\\033[48;2;194;0;0m.\\033[48;2;195;0;0m.\\033[48;2;196;0;0m.\\033[48;2;197;0;0m.\\033[48;2;198;0;0m.\\033[48;2;199;0;0m.", "\\033[48;2;200;0;0m.\\033[48;2;201;0;0m.\\033[48;2;202;0;0m.\\033[48;2;203;0;0m.\\033[48;2;204;0;0m.\\033[48;2;205;0;0m.\\033[48;2;206;0;0m.\\033[48;2;207;0;0m.", "\\033[48;2;208;0;0m.\\033[48;2;209;0;0m.\\033[48;2;210;0;0m.\\033[48;2;211;0;0m.\\033[48;2;212;0;0m.\\033[48;2;213;0;0m.\\033[48;2;214;0;0m.\\033[48;2;215;0;0m.", "\\033[48;2;216;0;0m.\\033[48;2;217;0;0m.\\033[48;2;218;0;0m.\\033[48;2;219;0;0m.\\033[48;2;220;0;0m.\\033[48;2;221;0;0m.\\033[48;2;222;0;0m.\\033[48;2;223;0;0m.", "\\033[48;2;224;0;0m.\\033[48;2;225;0;0m.\\033[48;2;226;0;0m.\\033[48;2;227;0;0m.\\033[48;2;228;0;0m.\\033[48;2;229;0;0m.\\033[48;2;230;0;0m.\\033[48;2;231;0;0m.", "\\033[48;2;232;0;0m.\\033[48;2;233;0;0m.\\033[48;2;234;0;0m.\\033[48;2;235;0;0m.\\033[48;2;236;0;0m.\\033[48;2;237;0;0m.\\033[48;2;238;0;0m.\\033[48;2;239;0;0m.", "\\033[48;2;240;0;0m.\\033[48;2;241;0;0m.\\033[48;2;242;0;0m.\\033[48;2;243;0;0m.\\033[48;2;244;0;0m.\\033[48;2;245;0;0m.\\033[48;2;246;0;0m.\\033[48;2;247;0;0m.", "\\033[48;2;248;0;0m.\\033[48;2;249;0;0m.\\033[48;2;250;0;0m.\\033[48;2;251;0;0m.\\033[48;2;252;0;0m.\\033[48;2;253;0;0m.\\033[48;2;254;0;0m.\\033[48;2;255;0;0m.", "\\033[0m\\n", "\\n", "Grn: ", "\\033[48;2;0;0;0m.\\033[48;2;0;1;0m.\\033[48;2;0;2;0m.\\033[48;2;0;3;0m.\\033[48;2;0;4;0m.\\033[48;2;0;5;0m.\\033[48;2;0;6;0m.\\033[48;2;0;7;0m.", "\\033[48;2;0;8;0m.\\033[48;2;0;9;0m.\\033[48;2;0;10;0m.\\033[48;2;0;11;0m.\\033[48;2;0;12;0m.\\033[48;2;0;13;0m.\\033[48;2;0;14;0m.\\033[48;2;0;15;0m.", "\\033[48;2;0;16;0m.\\033[48;2;0;17;0m.\\033[48;2;0;18;0m.\\033[48;2;0;19;0m.\\033[48;2;0;20;0m.\\033[48;2;0;21;0m.\\033[48;2;0;22;0m.\\033[48;2;0;23;0m.", "\\033[48;2;0;24;0m.\\033[48;2;0;25;0m.\\033[48;2;0;26;0m.\\033[48;2;0;27;0m.\\033[48;2;0;28;0m.\\033[48;2;0;29;0m.\\033[48;2;0;30;0m.\\033[48;2;0;31;0m.", "\\033[48;2;0;32;0m.\\033[48;2;0;33;0m.\\033[48;2;0;34;0m.\\033[48;2;0;35;0m.\\033[48;2;0;36;0m.\\033[48;2;0;37;0m.\\033[48;2;0;38;0m.\\033[48;2;0;39;0m.", "\\033[48;2;0;40;0m.\\033[48;2;0;41;0m.\\033[48;2;0;42;0m.\\033[48;2;0;43;0m.\\033[48;2;0;44;0m.\\033[48;2;0;45;0m.\\033[48;2;0;46;0m.\\033[48;2;0;47;0m.", "\\033[48;2;0;48;0m.\\033[48;2;0;49;0m.\\033[48;2;0;50;0m.\\033[48;2;0;51;0m.\\033[48;2;0;52;0m.\\033[48;2;0;53;0m.\\033[48;2;0;54;0m.\\033[48;2;0;55;0m.", "\\033[48;2;0;56;0m.\\033[48;2;0;57;0m.\\033[48;2;0;58;0m.\\033[48;2;0;59;0m.\\033[48;2;0;60;0m.\\033[48;2;0;61;0m.\\033[48;2;0;62;0m.\\033[48;2;0;63;0m.", "\\033[48;2;0;64;0m.\\033[48;2;0;65;0m.\\033[48;2;0;66;0m.\\033[48;2;0;67;0m.\\033[48;2;0;68;0m.\\033[48;2;0;69;0m.\\033[48;2;0;70;0m.\\033[48;2;0;71;0m.", "\\033[48;2;0;72;0m.\\033[48;2;0;73;0m.\\033[48;2;0;74;0m.\\033[48;2;0;75;0m.\\033[48;2;0;76;0m.\\033[48;2;0;77;0m.\\033[48;2;0;78;0m.\\033[48;2;0;79;0m.", "\\033[48;2;0;80;0m.\\033[48;2;0;81;0m.\\033[48;2;0;82;0m.\\033[48;2;0;83;0m.\\033[48;2;0;84;0m.\\033[48;2;0;85;0m.\\033[48;2;0;86;0m.\\033[48;2;0;87;0m.", "\\033[48;2;0;88;0m.\\033[48;2;0;89;0m.\\033[48;2;0;90;0m.\\033[48;2;0;91;0m.\\033[48;2;0;92;0m.\\033[48;2;0;93;0m.\\033[48;2;0;94;0m.\\033[48;2;0;95;0m.", "\\033[0m\\n ", "\\033[48;2;0;96;0m.\\033[48;2;0;97;0m.\\033[48;2;0;98;0m.\\033[48;2;0;99;0m.\\033[48;2;0;100;0m.\\033[48;2;0;101;0m.\\033[48;2;0;102;0m.\\033[48;2;0;103;0m.", "\\033[48;2;0;104;0m.\\033[48;2;0;105;0m.\\033[48;2;0;106;0m.\\033[48;2;0;107;0m.\\033[48;2;0;108;0m.\\033[48;2;0;109;0m.\\033[48;2;0;110;0m.\\033[48;2;0;111;0m.", "\\033[48;2;0;112;0m.\\033[48;2;0;113;0m.\\033[48;2;0;114;0m.\\033[48;2;0;115;0m.\\033[48;2;0;116;0m.\\033[48;2;0;117;0m.\\033[48;2;0;118;0m.\\033[48;2;0;119;0m.", "\\033[48;2;0;120;0m.\\033[48;2;0;121;0m.\\033[48;2;0;122;0m.\\033[48;2;0;123;0m.\\033[48;2;0;124;0m.\\033[48;2;0;125;0m.\\033[48;2;0;126;0m.\\033[48;2;0;127;0m.", "\\033[48;2;0;128;0m.\\033[48;2;0;129;0m.\\033[48;2;0;130;0m.\\033[48;2;0;131;0m.\\033[48;2;0;132;0m.\\033[48;2;0;133;0m.\\033[48;2;0;134;0m.\\033[48;2;0;135;0m.", "\\033[48;2;0;136;0m.\\033[48;2;0;137;0m.\\033[48;2;0;138;0m.\\033[48;2;0;139;0m.\\033[48;2;0;140;0m.\\033[48;2;0;141;0m.\\033[48;2;0;142;0m.\\033[48;2;0;143;0m.", "\\033[48;2;0;144;0m.\\033[48;2;0;145;0m.\\033[48;2;0;146;0m.\\033[48;2;0;147;0m.\\033[48;2;0;148;0m.\\033[48;2;0;149;0m.\\033[48;2;0;150;0m.\\033[48;2;0;151;0m.", "\\033[48;2;0;152;0m.\\033[48;2;0;153;0m.\\033[48;2;0;154;0m.\\033[48;2;0;155;0m.\\033[48;2;0;156;0m.\\033[48;2;0;157;0m.\\033[48;2;0;158;0m.\\033[48;2;0;159;0m.", "\\033[48;2;0;160;0m.\\033[48;2;0;161;0m.\\033[48;2;0;162;0m.\\033[48;2;0;163;0m.\\033[48;2;0;164;0m.\\033[48;2;0;165;0m.\\033[48;2;0;166;0m.\\033[48;2;0;167;0m.", "\\033[48;2;0;168;0m.\\033[48;2;0;169;0m.\\033[48;2;0;170;0m.\\033[48;2;0;171;0m.\\033[48;2;0;172;0m.\\033[48;2;0;173;0m.\\033[48;2;0;174;0m.\\033[48;2;0;175;0m.", "\\033[48;2;0;176;0m.\\033[48;2;0;177;0m.\\033[48;2;0;178;0m.\\033[48;2;0;179;0m.\\033[48;2;0;180;0m.\\033[48;2;0;181;0m.\\033[48;2;0;182;0m.\\033[48;2;0;183;0m.", "\\033[48;2;0;184;0m.\\033[48;2;0;185;0m.\\033[48;2;0;186;0m.\\033[48;2;0;187;0m.\\033[48;2;0;188;0m.\\033[48;2;0;189;0m.\\033[48;2;0;190;0m.\\033[48;2;0;191;0m.", "\\033[0m\\n ", "\\033[48;2;0;192;0m.\\033[48;2;0;193;0m.\\033[48;2;0;194;0m.\\033[48;2;0;195;0m.\\033[48;2;0;196;0m.\\033[48;2;0;197;0m.\\033[48;2;0;198;0m.\\033[48;2;0;199;0m.", "\\033[48;2;0;200;0m.\\033[48;2;0;201;0m.\\033[48;2;0;202;0m.\\033[48;2;0;203;0m.\\033[48;2;0;204;0m.\\033[48;2;0;205;0m.\\033[48;2;0;206;0m.\\033[48;2;0;207;0m.", "\\033[48;2;0;208;0m.\\033[48;2;0;209;0m.\\033[48;2;0;210;0m.\\033[48;2;0;211;0m.\\033[48;2;0;212;0m.\\033[48;2;0;213;0m.\\033[48;2;0;214;0m.\\033[48;2;0;215;0m.", "\\033[48;2;0;216;0m.\\033[48;2;0;217;0m.\\033[48;2;0;218;0m.\\033[48;2;0;219;0m.\\033[48;2;0;220;0m.\\033[48;2;0;221;0m.\\033[48;2;0;222;0m.\\033[48;2;0;223;0m.", "\\033[48;2;0;224;0m.\\033[48;2;0;225;0m.\\033[48;2;0;226;0m.\\033[48;2;0;227;0m.\\033[48;2;0;228;0m.\\033[48;2;0;229;0m.\\033[48;2;0;230;0m.\\033[48;2;0;231;0m.", "\\033[48;2;0;232;0m.\\033[48;2;0;233;0m.\\033[48;2;0;234;0m.\\033[48;2;0;235;0m.\\033[48;2;0;236;0m.\\033[48;2;0;237;0m.\\033[48;2;0;238;0m.\\033[48;2;0;239;0m.", "\\033[48;2;0;240;0m.\\033[48;2;0;241;0m.\\033[48;2;0;242;0m.\\033[48;2;0;243;0m.\\033[48;2;0;244;0m.\\033[48;2;0;245;0m.\\033[48;2;0;246;0m.\\033[48;2;0;247;0m.", "\\033[48;2;0;248;0m.\\033[48;2;0;249;0m.\\033[48;2;0;250;0m.\\033[48;2;0;251;0m.\\033[48;2;0;252;0m.\\033[48;2;0;253;0m.\\033[48;2;0;254;0m.\\033[48;2;0;255;0m.", "\\033[0m\\n", "\\n", "Blu: ", "\\033[48;2;0;0;0m.\\033[48;2;0;0;1m.\\033[48;2;0;0;2m.\\033[48;2;0;0;3m.\\033[48;2;0;0;4m.\\033[48;2;0;0;5m.\\033[48;2;0;0;6m.\\033[48;2;0;0;7m.", "\\033[48;2;0;0;8m.\\033[48;2;0;0;9m.\\033[48;2;0;0;10m.\\033[48;2;0;0;11m.\\033[48;2;0;0;12m.\\033[48;2;0;0;13m.\\033[48;2;0;0;14m.\\033[48;2;0;0;15m.", "\\033[48;2;0;0;16m.\\033[48;2;0;0;17m.\\033[48;2;0;0;18m.\\033[48;2;0;0;19m.\\033[48;2;0;0;20m.\\033[48;2;0;0;21m.\\033[48;2;0;0;22m.\\033[48;2;0;0;23m.", "\\033[48;2;0;0;24m.\\033[48;2;0;0;25m.\\033[48;2;0;0;26m.\\033[48;2;0;0;27m.\\033[48;2;0;0;28m.\\033[48;2;0;0;29m.\\033[48;2;0;0;30m.\\033[48;2;0;0;31m.", "\\033[48;2;0;0;32m.\\033[48;2;0;0;33m.\\033[48;2;0;0;34m.\\033[48;2;0;0;35m.\\033[48;2;0;0;36m.\\033[48;2;0;0;37m.\\033[48;2;0;0;38m.\\033[48;2;0;0;39m.", "\\033[48;2;0;0;40m.\\033[48;2;0;0;41m.\\033[48;2;0;0;42m.\\033[48;2;0;0;43m.\\033[48;2;0;0;44m.\\033[48;2;0;0;45m.\\033[48;2;0;0;46m.\\033[48;2;0;0;47m.", "\\033[48;2;0;0;48m.\\033[48;2;0;0;49m.\\033[48;2;0;0;50m.\\033[48;2;0;0;51m.\\033[48;2;0;0;52m.\\033[48;2;0;0;53m.\\033[48;2;0;0;54m.\\033[48;2;0;0;55m.", "\\033[48;2;0;0;56m.\\033[48;2;0;0;57m.\\033[48;2;0;0;58m.\\033[48;2;0;0;59m.\\033[48;2;0;0;60m.\\033[48;2;0;0;61m.\\033[48;2;0;0;62m.\\033[48;2;0;0;63m.", "\\033[48;2;0;0;64m.\\033[48;2;0;0;65m.\\033[48;2;0;0;66m.\\033[48;2;0;0;67m.\\033[48;2;0;0;68m.\\033[48;2;0;0;69m.\\033[48;2;0;0;70m.\\033[48;2;0;0;71m.", "\\033[48;2;0;0;72m.\\033[48;2;0;0;73m.\\033[48;2;0;0;74m.\\033[48;2;0;0;75m.\\033[48;2;0;0;76m.\\033[48;2;0;0;77m.\\033[48;2;0;0;78m.\\033[48;2;0;0;79m.", "\\033[48;2;0;0;80m.\\033[48;2;0;0;81m.\\033[48;2;0;0;82m.\\033[48;2;0;0;83m.\\033[48;2;0;0;84m.\\033[48;2;0;0;85m.\\033[48;2;0;0;86m.\\033[48;2;0;0;87m.", "\\033[48;2;0;0;88m.\\033[48;2;0;0;89m.\\033[48;2;0;0;90m.\\033[48;2;0;0;91m.\\033[48;2;0;0;92m.\\033[48;2;0;0;93m.\\033[48;2;0;0;94m.\\033[48;2;0;0;95m.", "\\033[0m\\n ", "\\033[48;2;0;0;96m.\\033[48;2;0;0;97m.\\033[48;2;0;0;98m.\\033[48;2;0;0;99m.\\033[48;2;0;0;100m.\\033[48;2;0;0;101m.\\033[48;2;0;0;102m.\\033[48;2;0;0;103m.", "\\033[48;2;0;0;104m.\\033[48;2;0;0;105m.\\033[48;2;0;0;106m.\\033[48;2;0;0;107m.\\033[48;2;0;0;108m.\\033[48;2;0;0;109m.\\033[48;2;0;0;110m.\\033[48;2;0;0;111m.", "\\033[48;2;0;0;112m.\\033[48;2;0;0;113m.\\033[48;2;0;0;114m.\\033[48;2;0;0;115m.\\033[48;2;0;0;116m.\\033[48;2;0;0;117m.\\033[48;2;0;0;118m.\\033[48;2;0;0;119m.", "\\033[48;2;0;0;120m.\\033[48;2;0;0;121m.\\033[48;2;0;0;122m.\\033[48;2;0;0;123m.\\033[48;2;0;0;124m.\\033[48;2;0;0;125m.\\033[48;2;0;0;126m.\\033[48;2;0;0;127m.", "\\033[48;2;0;0;128m.\\033[48;2;0;0;129m.\\033[48;2;0;0;130m.\\033[48;2;0;0;131m.\\033[48;2;0;0;132m.\\033[48;2;0;0;133m.\\033[48;2;0;0;134m.\\033[48;2;0;0;135m.", "\\033[48;2;0;0;136m.\\033[48;2;0;0;137m.\\033[48;2;0;0;138m.\\033[48;2;0;0;139m.\\033[48;2;0;0;140m.\\033[48;2;0;0;141m.\\033[48;2;0;0;142m.\\033[48;2;0;0;143m.", "\\033[48;2;0;0;144m.\\033[48;2;0;0;145m.\\033[48;2;0;0;146m.\\033[48;2;0;0;147m.\\033[48;2;0;0;148m.\\033[48;2;0;0;149m.\\033[48;2;0;0;150m.\\033[48;2;0;0;151m.", "\\033[48;2;0;0;152m.\\033[48;2;0;0;153m.\\033[48;2;0;0;154m.\\033[48;2;0;0;155m.\\033[48;2;0;0;156m.\\033[48;2;0;0;157m.\\033[48;2;0;0;158m.\\033[48;2;0;0;159m.", "\\033[48;2;0;0;160m.\\033[48;2;0;0;161m.\\033[48;2;0;0;162m.\\033[48;2;0;0;163m.\\033[48;2;0;0;164m.\\033[48;2;0;0;165m.\\033[48;2;0;0;166m.\\033[48;2;0;0;167m.", "\\033[48;2;0;0;168m.\\033[48;2;0;0;169m.\\033[48;2;0;0;170m.\\033[48;2;0;0;171m.\\033[48;2;0;0;172m.\\033[48;2;0;0;173m.\\033[48;2;0;0;174m.\\033[48;2;0;0;175m.", "\\033[48;2;0;0;176m.\\033[48;2;0;0;177m.\\033[48;2;0;0;178m.\\033[48;2;0;0;179m.\\033[48;2;0;0;180m.\\033[48;2;0;0;181m.\\033[48;2;0;0;182m.\\033[48;2;0;0;183m.", "\\033[48;2;0;0;184m.\\033[48;2;0;0;185m.\\033[48;2;0;0;186m.\\033[48;2;0;0;187m.\\033[48;2;0;0;188m.\\033[48;2;0;0;189m.\\033[48;2;0;0;190m.\\033[48;2;0;0;191m.", "\\033[0m\\n ", "\\033[48;2;0;0;192m.\\033[48;2;0;0;193m.\\033[48;2;0;0;194m.\\033[48;2;0;0;195m.\\033[48;2;0;0;196m.\\033[48;2;0;0;197m.\\033[48;2;0;0;198m.\\033[48;2;0;0;199m.", "\\033[48;2;0;0;200m.\\033[48;2;0;0;201m.\\033[48;2;0;0;202m.\\033[48;2;0;0;203m.\\033[48;2;0;0;204m.\\033[48;2;0;0;205m.\\033[48;2;0;0;206m.\\033[48;2;0;0;207m.", "\\033[48;2;0;0;208m.\\033[48;2;0;0;209m.\\033[48;2;0;0;210m.\\033[48;2;0;0;211m.\\033[48;2;0;0;212m.\\033[48;2;0;0;213m.\\033[48;2;0;0;214m.\\033[48;2;0;0;215m.", "\\033[48;2;0;0;216m.\\033[48;2;0;0;217m.\\033[48;2;0;0;218m.\\033[48;2;0;0;219m.\\033[48;2;0;0;220m.\\033[48;2;0;0;221m.\\033[48;2;0;0;222m.\\033[48;2;0;0;223m.", "\\033[48;2;0;0;224m.\\033[48;2;0;0;225m.\\033[48;2;0;0;226m.\\033[48;2;0;0;227m.\\033[48;2;0;0;228m.\\033[48;2;0;0;229m.\\033[48;2;0;0;230m.\\033[48;2;0;0;231m.", "\\033[48;2;0;0;232m.\\033[48;2;0;0;233m.\\033[48;2;0;0;234m.\\033[48;2;0;0;235m.\\033[48;2;0;0;236m.\\033[48;2;0;0;237m.\\033[48;2;0;0;238m.\\033[48;2;0;0;239m.", "\\033[48;2;0;0;240m.\\033[48;2;0;0;241m.\\033[48;2;0;0;242m.\\033[48;2;0;0;243m.\\033[48;2;0;0;244m.\\033[48;2;0;0;245m.\\033[48;2;0;0;246m.\\033[48;2;0;0;247m.", "\\033[48;2;0;0;248m.\\033[48;2;0;0;249m.\\033[48;2;0;0;250m.\\033[48;2;0;0;251m.\\033[48;2;0;0;252m.\\033[48;2;0;0;253m.\\033[48;2;0;0;254m.\\033[48;2;0;0;255m.", "\\033[0m\\n ", "\\n", /** For generating an HSV hue ramp, see: https://en.wikipedia.org/wiki/HSL_and_HSV\#/media/File:HSV-RGB-comparison.svg Basically: 255 : RRRRRRR RRRRRRRR : R R : R R : R RED R : R R : R R : R R 0 : RRRRRRRRRRRRRRRR :..|......|......|......|......|......|......| 0 60 120 180 240 300 360 255 : GGGGGGGGGGGGGG : G G : G G : G G : G GREEN G : G G : G G 0 : G GGGGGGGGGGGGGGGG :..|......|......|......|......|......|......| 0 60 120 180 240 300 360 255 : BBBBBBBBBBBBBBB : B B : B B : B BLUE B : B B : B B : B B 0 : GBBBBBBBBBBBBBB B :..|......|......|......|......|......|......| 0 60 120 180 240 300 360 Here's some perl code that generates the Hue ramp: $count = 0; for ($t=0; $t<256;$t+=2) { printf("\\\\033[48;2;%03d;%03d;%03dm ",255,$t,0); if ((++$count % 8) == 0) { printf("\\n"); } } for ($t=0; $t<256;$t+=2) { printf("\\\\033[48;2;%03d;%03d;%03dm ",255-$t,255,0); if ((++$count % 8) == 0) { printf("\\n"); } } for ($t=0; $t<256;$t+=2) { printf("\\\\033[48;2;%03d;%03d;%03dm ",0,255,$t); if ((++$count % 8) == 0) { printf("\\n"); } } for ($t=0; $t<256;$t+=2) { printf("\\\\033[48;2;%03d;%03d;%03dm ",0,255-$t,255); if ((++$count % 8) == 0) { printf("\\n"); } } for ($t=0; $t<256;$t+=2) { printf("\\\\033[48;2;%03d;%03d;%03dm ",$t,0,255); if ((++$count % 8) == 0) { printf("\\n"); } } for ($t=0; $t<256;$t+=2) { printf("\\\\033[48;2;%03d;%03d;%03dm ",255,0,255-$t); if ((++$count % 8) == 0) { printf("\\n"); } } **/ "Hue: ", "\\033[48;2;255;000;000m.\\033[48;2;255;001;000m.\\033[48;2;255;002;000m.\\033[48;2;255;003;000m.\\033[48;2;255;004;000m.\\033[48;2;255;005;000m.\\033[48;2;255;006;000m.\\033[48;2;255;007;000m.", "\\033[48;2;255;008;000m.\\033[48;2;255;009;000m.\\033[48;2;255;010;000m.\\033[48;2;255;011;000m.\\033[48;2;255;012;000m.\\033[48;2;255;013;000m.\\033[48;2;255;014;000m.\\033[48;2;255;015;000m.", "\\033[48;2;255;016;000m.\\033[48;2;255;017;000m.\\033[48;2;255;018;000m.\\033[48;2;255;019;000m.\\033[48;2;255;020;000m.\\033[48;2;255;021;000m.\\033[48;2;255;022;000m.\\033[48;2;255;023;000m.", "\\033[48;2;255;024;000m.\\033[48;2;255;025;000m.\\033[48;2;255;026;000m.\\033[48;2;255;027;000m.\\033[48;2;255;028;000m.\\033[48;2;255;029;000m.\\033[48;2;255;030;000m.\\033[48;2;255;031;000m.", "\\033[48;2;255;032;000m.\\033[48;2;255;033;000m.\\033[48;2;255;034;000m.\\033[48;2;255;035;000m.\\033[48;2;255;036;000m.\\033[48;2;255;037;000m.\\033[48;2;255;038;000m.\\033[48;2;255;039;000m.", "\\033[48;2;255;040;000m.\\033[48;2;255;041;000m.\\033[48;2;255;042;000m.\\033[48;2;255;043;000m.\\033[48;2;255;044;000m.\\033[48;2;255;045;000m.\\033[48;2;255;046;000m.\\033[48;2;255;047;000m.", "\\033[48;2;255;048;000m.\\033[48;2;255;049;000m.\\033[48;2;255;050;000m.\\033[48;2;255;051;000m.\\033[48;2;255;052;000m.\\033[48;2;255;053;000m.\\033[48;2;255;054;000m.\\033[48;2;255;055;000m.", "\\033[48;2;255;056;000m.\\033[48;2;255;057;000m.\\033[48;2;255;058;000m.\\033[48;2;255;059;000m.\\033[48;2;255;060;000m.\\033[48;2;255;061;000m.\\033[48;2;255;062;000m.\\033[48;2;255;063;000m.", "\\033[48;2;255;064;000m.\\033[48;2;255;065;000m.\\033[48;2;255;066;000m.\\033[48;2;255;067;000m.\\033[48;2;255;068;000m.\\033[48;2;255;069;000m.\\033[48;2;255;070;000m.\\033[48;2;255;071;000m.", "\\033[48;2;255;072;000m.\\033[48;2;255;073;000m.\\033[48;2;255;074;000m.\\033[48;2;255;075;000m.\\033[48;2;255;076;000m.\\033[48;2;255;077;000m.\\033[48;2;255;078;000m.\\033[48;2;255;079;000m.", "\\033[48;2;255;080;000m.\\033[48;2;255;081;000m.\\033[48;2;255;082;000m.\\033[48;2;255;083;000m.\\033[48;2;255;084;000m.\\033[48;2;255;085;000m.\\033[48;2;255;086;000m.\\033[48;2;255;087;000m.", "\\033[48;2;255;088;000m.\\033[48;2;255;089;000m.\\033[48;2;255;090;000m.\\033[48;2;255;091;000m.\\033[48;2;255;092;000m.\\033[48;2;255;093;000m.\\033[48;2;255;094;000m.\\033[48;2;255;095;000m.", "\\033[0m\\n ", "\\033[48;2;255;096;000m.\\033[48;2;255;097;000m.\\033[48;2;255;098;000m.\\033[48;2;255;099;000m.\\033[48;2;255;100;000m.\\033[48;2;255;101;000m.\\033[48;2;255;102;000m.\\033[48;2;255;103;000m.", "\\033[48;2;255;104;000m.\\033[48;2;255;105;000m.\\033[48;2;255;106;000m.\\033[48;2;255;107;000m.\\033[48;2;255;108;000m.\\033[48;2;255;109;000m.\\033[48;2;255;110;000m.\\033[48;2;255;111;000m.", "\\033[48;2;255;112;000m.\\033[48;2;255;113;000m.\\033[48;2;255;114;000m.\\033[48;2;255;115;000m.\\033[48;2;255;116;000m.\\033[48;2;255;117;000m.\\033[48;2;255;118;000m.\\033[48;2;255;119;000m.", "\\033[48;2;255;120;000m.\\033[48;2;255;121;000m.\\033[48;2;255;122;000m.\\033[48;2;255;123;000m.\\033[48;2;255;124;000m.\\033[48;2;255;125;000m.\\033[48;2;255;126;000m.\\033[48;2;255;127;000m.", "\\033[48;2;255;128;000m.\\033[48;2;255;129;000m.\\033[48;2;255;130;000m.\\033[48;2;255;131;000m.\\033[48;2;255;132;000m.\\033[48;2;255;133;000m.\\033[48;2;255;134;000m.\\033[48;2;255;135;000m.", "\\033[48;2;255;136;000m.\\033[48;2;255;137;000m.\\033[48;2;255;138;000m.\\033[48;2;255;139;000m.\\033[48;2;255;140;000m.\\033[48;2;255;141;000m.\\033[48;2;255;142;000m.\\033[48;2;255;143;000m.", "\\033[48;2;255;144;000m.\\033[48;2;255;145;000m.\\033[48;2;255;146;000m.\\033[48;2;255;147;000m.\\033[48;2;255;148;000m.\\033[48;2;255;149;000m.\\033[48;2;255;150;000m.\\033[48;2;255;151;000m.", "\\033[48;2;255;152;000m.\\033[48;2;255;153;000m.\\033[48;2;255;154;000m.\\033[48;2;255;155;000m.\\033[48;2;255;156;000m.\\033[48;2;255;157;000m.\\033[48;2;255;158;000m.\\033[48;2;255;159;000m.", "\\033[48;2;255;160;000m.\\033[48;2;255;161;000m.\\033[48;2;255;162;000m.\\033[48;2;255;163;000m.\\033[48;2;255;164;000m.\\033[48;2;255;165;000m.\\033[48;2;255;166;000m.\\033[48;2;255;167;000m.", "\\033[48;2;255;168;000m.\\033[48;2;255;169;000m.\\033[48;2;255;170;000m.\\033[48;2;255;171;000m.\\033[48;2;255;172;000m.\\033[48;2;255;173;000m.\\033[48;2;255;174;000m.\\033[48;2;255;175;000m.", "\\033[48;2;255;176;000m.\\033[48;2;255;177;000m.\\033[48;2;255;178;000m.\\033[48;2;255;179;000m.\\033[48;2;255;180;000m.\\033[48;2;255;181;000m.\\033[48;2;255;182;000m.\\033[48;2;255;183;000m.", "\\033[48;2;255;184;000m.\\033[48;2;255;185;000m.\\033[48;2;255;186;000m.\\033[48;2;255;187;000m.\\033[48;2;255;188;000m.\\033[48;2;255;189;000m.\\033[48;2;255;190;000m.\\033[48;2;255;191;000m.", "\\033[0m\\n ", "\\033[48;2;255;192;000m.\\033[48;2;255;193;000m.\\033[48;2;255;194;000m.\\033[48;2;255;195;000m.\\033[48;2;255;196;000m.\\033[48;2;255;197;000m.\\033[48;2;255;198;000m.\\033[48;2;255;199;000m.", "\\033[48;2;255;200;000m.\\033[48;2;255;201;000m.\\033[48;2;255;202;000m.\\033[48;2;255;203;000m.\\033[48;2;255;204;000m.\\033[48;2;255;205;000m.\\033[48;2;255;206;000m.\\033[48;2;255;207;000m.", "\\033[48;2;255;208;000m.\\033[48;2;255;209;000m.\\033[48;2;255;210;000m.\\033[48;2;255;211;000m.\\033[48;2;255;212;000m.\\033[48;2;255;213;000m.\\033[48;2;255;214;000m.\\033[48;2;255;215;000m.", "\\033[48;2;255;216;000m.\\033[48;2;255;217;000m.\\033[48;2;255;218;000m.\\033[48;2;255;219;000m.\\033[48;2;255;220;000m.\\033[48;2;255;221;000m.\\033[48;2;255;222;000m.\\033[48;2;255;223;000m.", "\\033[48;2;255;224;000m.\\033[48;2;255;225;000m.\\033[48;2;255;226;000m.\\033[48;2;255;227;000m.\\033[48;2;255;228;000m.\\033[48;2;255;229;000m.\\033[48;2;255;230;000m.\\033[48;2;255;231;000m.", "\\033[48;2;255;232;000m.\\033[48;2;255;233;000m.\\033[48;2;255;234;000m.\\033[48;2;255;235;000m.\\033[48;2;255;236;000m.\\033[48;2;255;237;000m.\\033[48;2;255;238;000m.\\033[48;2;255;239;000m.", "\\033[48;2;255;240;000m.\\033[48;2;255;241;000m.\\033[48;2;255;242;000m.\\033[48;2;255;243;000m.\\033[48;2;255;244;000m.\\033[48;2;255;245;000m.\\033[48;2;255;246;000m.\\033[48;2;255;247;000m.", "\\033[48;2;255;248;000m.\\033[48;2;255;249;000m.\\033[48;2;255;250;000m.\\033[48;2;255;251;000m.\\033[48;2;255;252;000m.\\033[48;2;255;253;000m.\\033[48;2;255;254;000m.\\033[48;2;255;255;000m.", "\\033[48;2;255;255;000m.\\033[48;2;254;255;000m.\\033[48;2;253;255;000m.\\033[48;2;252;255;000m.\\033[48;2;251;255;000m.\\033[48;2;250;255;000m.\\033[48;2;249;255;000m.\\033[48;2;248;255;000m.", "\\033[48;2;247;255;000m.\\033[48;2;246;255;000m.\\033[48;2;245;255;000m.\\033[48;2;244;255;000m.\\033[48;2;243;255;000m.\\033[48;2;242;255;000m.\\033[48;2;241;255;000m.\\033[48;2;240;255;000m.", "\\033[48;2;239;255;000m.\\033[48;2;238;255;000m.\\033[48;2;237;255;000m.\\033[48;2;236;255;000m.\\033[48;2;235;255;000m.\\033[48;2;234;255;000m.\\033[48;2;233;255;000m.\\033[48;2;232;255;000m.", "\\033[48;2;231;255;000m.\\033[48;2;230;255;000m.\\033[48;2;229;255;000m.\\033[48;2;228;255;000m.\\033[48;2;227;255;000m.\\033[48;2;226;255;000m.\\033[48;2;225;255;000m.\\033[48;2;224;255;000m.", "\\033[0m\\n ", "\\033[48;2;223;255;000m.\\033[48;2;222;255;000m.\\033[48;2;221;255;000m.\\033[48;2;220;255;000m.\\033[48;2;219;255;000m.\\033[48;2;218;255;000m.\\033[48;2;217;255;000m.\\033[48;2;216;255;000m.", "\\033[48;2;215;255;000m.\\033[48;2;214;255;000m.\\033[48;2;213;255;000m.\\033[48;2;212;255;000m.\\033[48;2;211;255;000m.\\033[48;2;210;255;000m.\\033[48;2;209;255;000m.\\033[48;2;208;255;000m.", "\\033[48;2;207;255;000m.\\033[48;2;206;255;000m.\\033[48;2;205;255;000m.\\033[48;2;204;255;000m.\\033[48;2;203;255;000m.\\033[48;2;202;255;000m.\\033[48;2;201;255;000m.\\033[48;2;200;255;000m.", "\\033[48;2;199;255;000m.\\033[48;2;198;255;000m.\\033[48;2;197;255;000m.\\033[48;2;196;255;000m.\\033[48;2;195;255;000m.\\033[48;2;194;255;000m.\\033[48;2;193;255;000m.\\033[48;2;192;255;000m.", "\\033[48;2;191;255;000m.\\033[48;2;190;255;000m.\\033[48;2;189;255;000m.\\033[48;2;188;255;000m.\\033[48;2;187;255;000m.\\033[48;2;186;255;000m.\\033[48;2;185;255;000m.\\033[48;2;184;255;000m.", "\\033[48;2;183;255;000m.\\033[48;2;182;255;000m.\\033[48;2;181;255;000m.\\033[48;2;180;255;000m.\\033[48;2;179;255;000m.\\033[48;2;178;255;000m.\\033[48;2;177;255;000m.\\033[48;2;176;255;000m.", "\\033[48;2;175;255;000m.\\033[48;2;174;255;000m.\\033[48;2;173;255;000m.\\033[48;2;172;255;000m.\\033[48;2;171;255;000m.\\033[48;2;170;255;000m.\\033[48;2;169;255;000m.\\033[48;2;168;255;000m.", "\\033[48;2;167;255;000m.\\033[48;2;166;255;000m.\\033[48;2;165;255;000m.\\033[48;2;164;255;000m.\\033[48;2;163;255;000m.\\033[48;2;162;255;000m.\\033[48;2;161;255;000m.\\033[48;2;160;255;000m.", "\\033[48;2;159;255;000m.\\033[48;2;158;255;000m.\\033[48;2;157;255;000m.\\033[48;2;156;255;000m.\\033[48;2;155;255;000m.\\033[48;2;154;255;000m.\\033[48;2;153;255;000m.\\033[48;2;152;255;000m.", "\\033[48;2;151;255;000m.\\033[48;2;150;255;000m.\\033[48;2;149;255;000m.\\033[48;2;148;255;000m.\\033[48;2;147;255;000m.\\033[48;2;146;255;000m.\\033[48;2;145;255;000m.\\033[48;2;144;255;000m.", "\\033[48;2;143;255;000m.\\033[48;2;142;255;000m.\\033[48;2;141;255;000m.\\033[48;2;140;255;000m.\\033[48;2;139;255;000m.\\033[48;2;138;255;000m.\\033[48;2;137;255;000m.\\033[48;2;136;255;000m.", "\\033[48;2;135;255;000m.\\033[48;2;134;255;000m.\\033[48;2;133;255;000m.\\033[48;2;132;255;000m.\\033[48;2;131;255;000m.\\033[48;2;130;255;000m.\\033[48;2;129;255;000m.\\033[48;2;128;255;000m.", "\\033[0m\\n ", "\\033[48;2;127;255;000m.\\033[48;2;126;255;000m.\\033[48;2;125;255;000m.\\033[48;2;124;255;000m.\\033[48;2;123;255;000m.\\033[48;2;122;255;000m.\\033[48;2;121;255;000m.\\033[48;2;120;255;000m.", "\\033[48;2;119;255;000m.\\033[48;2;118;255;000m.\\033[48;2;117;255;000m.\\033[48;2;116;255;000m.\\033[48;2;115;255;000m.\\033[48;2;114;255;000m.\\033[48;2;113;255;000m.\\033[48;2;112;255;000m.", "\\033[48;2;111;255;000m.\\033[48;2;110;255;000m.\\033[48;2;109;255;000m.\\033[48;2;108;255;000m.\\033[48;2;107;255;000m.\\033[48;2;106;255;000m.\\033[48;2;105;255;000m.\\033[48;2;104;255;000m.", "\\033[48;2;103;255;000m.\\033[48;2;102;255;000m.\\033[48;2;101;255;000m.\\033[48;2;100;255;000m.\\033[48;2;099;255;000m.\\033[48;2;098;255;000m.\\033[48;2;097;255;000m.\\033[48;2;096;255;000m.", "\\033[48;2;095;255;000m.\\033[48;2;094;255;000m.\\033[48;2;093;255;000m.\\033[48;2;092;255;000m.\\033[48;2;091;255;000m.\\033[48;2;090;255;000m.\\033[48;2;089;255;000m.\\033[48;2;088;255;000m.", "\\033[48;2;087;255;000m.\\033[48;2;086;255;000m.\\033[48;2;085;255;000m.\\033[48;2;084;255;000m.\\033[48;2;083;255;000m.\\033[48;2;082;255;000m.\\033[48;2;081;255;000m.\\033[48;2;080;255;000m.", "\\033[48;2;079;255;000m.\\033[48;2;078;255;000m.\\033[48;2;077;255;000m.\\033[48;2;076;255;000m.\\033[48;2;075;255;000m.\\033[48;2;074;255;000m.\\033[48;2;073;255;000m.\\033[48;2;072;255;000m.", "\\033[48;2;071;255;000m.\\033[48;2;070;255;000m.\\033[48;2;069;255;000m.\\033[48;2;068;255;000m.\\033[48;2;067;255;000m.\\033[48;2;066;255;000m.\\033[48;2;065;255;000m.\\033[48;2;064;255;000m.", "\\033[48;2;063;255;000m.\\033[48;2;062;255;000m.\\033[48;2;061;255;000m.\\033[48;2;060;255;000m.\\033[48;2;059;255;000m.\\033[48;2;058;255;000m.\\033[48;2;057;255;000m.\\033[48;2;056;255;000m.", "\\033[48;2;055;255;000m.\\033[48;2;054;255;000m.\\033[48;2;053;255;000m.\\033[48;2;052;255;000m.\\033[48;2;051;255;000m.\\033[48;2;050;255;000m.\\033[48;2;049;255;000m.\\033[48;2;048;255;000m.", "\\033[48;2;047;255;000m.\\033[48;2;046;255;000m.\\033[48;2;045;255;000m.\\033[48;2;044;255;000m.\\033[48;2;043;255;000m.\\033[48;2;042;255;000m.\\033[48;2;041;255;000m.\\033[48;2;040;255;000m.", "\\033[48;2;039;255;000m.\\033[48;2;038;255;000m.\\033[48;2;037;255;000m.\\033[48;2;036;255;000m.\\033[48;2;035;255;000m.\\033[48;2;034;255;000m.\\033[48;2;033;255;000m.\\033[48;2;032;255;000m.", "\\033[0m\\n ", "\\033[48;2;031;255;000m.\\033[48;2;030;255;000m.\\033[48;2;029;255;000m.\\033[48;2;028;255;000m.\\033[48;2;027;255;000m.\\033[48;2;026;255;000m.\\033[48;2;025;255;000m.\\033[48;2;024;255;000m.", "\\033[48;2;023;255;000m.\\033[48;2;022;255;000m.\\033[48;2;021;255;000m.\\033[48;2;020;255;000m.\\033[48;2;019;255;000m.\\033[48;2;018;255;000m.\\033[48;2;017;255;000m.\\033[48;2;016;255;000m.", "\\033[48;2;015;255;000m.\\033[48;2;014;255;000m.\\033[48;2;013;255;000m.\\033[48;2;012;255;000m.\\033[48;2;011;255;000m.\\033[48;2;010;255;000m.\\033[48;2;009;255;000m.\\033[48;2;008;255;000m.", "\\033[48;2;007;255;000m.\\033[48;2;006;255;000m.\\033[48;2;005;255;000m.\\033[48;2;004;255;000m.\\033[48;2;003;255;000m.\\033[48;2;002;255;000m.\\033[48;2;001;255;000m.\\033[48;2;000;255;000m.", "\\033[48;2;000;255;000m.\\033[48;2;000;255;001m.\\033[48;2;000;255;002m.\\033[48;2;000;255;003m.\\033[48;2;000;255;004m.\\033[48;2;000;255;005m.\\033[48;2;000;255;006m.\\033[48;2;000;255;007m.", "\\033[48;2;000;255;008m.\\033[48;2;000;255;009m.\\033[48;2;000;255;010m.\\033[48;2;000;255;011m.\\033[48;2;000;255;012m.\\033[48;2;000;255;013m.\\033[48;2;000;255;014m.\\033[48;2;000;255;015m.", "\\033[48;2;000;255;016m.\\033[48;2;000;255;017m.\\033[48;2;000;255;018m.\\033[48;2;000;255;019m.\\033[48;2;000;255;020m.\\033[48;2;000;255;021m.\\033[48;2;000;255;022m.\\033[48;2;000;255;023m.", "\\033[48;2;000;255;024m.\\033[48;2;000;255;025m.\\033[48;2;000;255;026m.\\033[48;2;000;255;027m.\\033[48;2;000;255;028m.\\033[48;2;000;255;029m.\\033[48;2;000;255;030m.\\033[48;2;000;255;031m.", "\\033[48;2;000;255;032m.\\033[48;2;000;255;033m.\\033[48;2;000;255;034m.\\033[48;2;000;255;035m.\\033[48;2;000;255;036m.\\033[48;2;000;255;037m.\\033[48;2;000;255;038m.\\033[48;2;000;255;039m.", "\\033[48;2;000;255;040m.\\033[48;2;000;255;041m.\\033[48;2;000;255;042m.\\033[48;2;000;255;043m.\\033[48;2;000;255;044m.\\033[48;2;000;255;045m.\\033[48;2;000;255;046m.\\033[48;2;000;255;047m.", "\\033[48;2;000;255;048m.\\033[48;2;000;255;049m.\\033[48;2;000;255;050m.\\033[48;2;000;255;051m.\\033[48;2;000;255;052m.\\033[48;2;000;255;053m.\\033[48;2;000;255;054m.\\033[48;2;000;255;055m.", "\\033[48;2;000;255;056m.\\033[48;2;000;255;057m.\\033[48;2;000;255;058m.\\033[48;2;000;255;059m.\\033[48;2;000;255;060m.\\033[48;2;000;255;061m.\\033[48;2;000;255;062m.\\033[48;2;000;255;063m.", "\\033[0m\\n ", "\\033[48;2;000;255;064m.\\033[48;2;000;255;065m.\\033[48;2;000;255;066m.\\033[48;2;000;255;067m.\\033[48;2;000;255;068m.\\033[48;2;000;255;069m.\\033[48;2;000;255;070m.\\033[48;2;000;255;071m.", "\\033[48;2;000;255;072m.\\033[48;2;000;255;073m.\\033[48;2;000;255;074m.\\033[48;2;000;255;075m.\\033[48;2;000;255;076m.\\033[48;2;000;255;077m.\\033[48;2;000;255;078m.\\033[48;2;000;255;079m.", "\\033[48;2;000;255;080m.\\033[48;2;000;255;081m.\\033[48;2;000;255;082m.\\033[48;2;000;255;083m.\\033[48;2;000;255;084m.\\033[48;2;000;255;085m.\\033[48;2;000;255;086m.\\033[48;2;000;255;087m.", "\\033[48;2;000;255;088m.\\033[48;2;000;255;089m.\\033[48;2;000;255;090m.\\033[48;2;000;255;091m.\\033[48;2;000;255;092m.\\033[48;2;000;255;093m.\\033[48;2;000;255;094m.\\033[48;2;000;255;095m.", "\\033[48;2;000;255;096m.\\033[48;2;000;255;097m.\\033[48;2;000;255;098m.\\033[48;2;000;255;099m.\\033[48;2;000;255;100m.\\033[48;2;000;255;101m.\\033[48;2;000;255;102m.\\033[48;2;000;255;103m.", "\\033[48;2;000;255;104m.\\033[48;2;000;255;105m.\\033[48;2;000;255;106m.\\033[48;2;000;255;107m.\\033[48;2;000;255;108m.\\033[48;2;000;255;109m.\\033[48;2;000;255;110m.\\033[48;2;000;255;111m.", "\\033[48;2;000;255;112m.\\033[48;2;000;255;113m.\\033[48;2;000;255;114m.\\033[48;2;000;255;115m.\\033[48;2;000;255;116m.\\033[48;2;000;255;117m.\\033[48;2;000;255;118m.\\033[48;2;000;255;119m.", "\\033[48;2;000;255;120m.\\033[48;2;000;255;121m.\\033[48;2;000;255;122m.\\033[48;2;000;255;123m.\\033[48;2;000;255;124m.\\033[48;2;000;255;125m.\\033[48;2;000;255;126m.\\033[48;2;000;255;127m.", "\\033[48;2;000;255;128m.\\033[48;2;000;255;129m.\\033[48;2;000;255;130m.\\033[48;2;000;255;131m.\\033[48;2;000;255;132m.\\033[48;2;000;255;133m.\\033[48;2;000;255;134m.\\033[48;2;000;255;135m.", "\\033[48;2;000;255;136m.\\033[48;2;000;255;137m.\\033[48;2;000;255;138m.\\033[48;2;000;255;139m.\\033[48;2;000;255;140m.\\033[48;2;000;255;141m.\\033[48;2;000;255;142m.\\033[48;2;000;255;143m.", "\\033[48;2;000;255;144m.\\033[48;2;000;255;145m.\\033[48;2;000;255;146m.\\033[48;2;000;255;147m.\\033[48;2;000;255;148m.\\033[48;2;000;255;149m.\\033[48;2;000;255;150m.\\033[48;2;000;255;151m.", "\\033[48;2;000;255;152m.\\033[48;2;000;255;153m.\\033[48;2;000;255;154m.\\033[48;2;000;255;155m.\\033[48;2;000;255;156m.\\033[48;2;000;255;157m.\\033[48;2;000;255;158m.\\033[48;2;000;255;159m.", "\\033[0m\\n ", "\\033[48;2;000;255;160m.\\033[48;2;000;255;161m.\\033[48;2;000;255;162m.\\033[48;2;000;255;163m.\\033[48;2;000;255;164m.\\033[48;2;000;255;165m.\\033[48;2;000;255;166m.\\033[48;2;000;255;167m.", "\\033[48;2;000;255;168m.\\033[48;2;000;255;169m.\\033[48;2;000;255;170m.\\033[48;2;000;255;171m.\\033[48;2;000;255;172m.\\033[48;2;000;255;173m.\\033[48;2;000;255;174m.\\033[48;2;000;255;175m.", "\\033[48;2;000;255;176m.\\033[48;2;000;255;177m.\\033[48;2;000;255;178m.\\033[48;2;000;255;179m.\\033[48;2;000;255;180m.\\033[48;2;000;255;181m.\\033[48;2;000;255;182m.\\033[48;2;000;255;183m.", "\\033[48;2;000;255;184m.\\033[48;2;000;255;185m.\\033[48;2;000;255;186m.\\033[48;2;000;255;187m.\\033[48;2;000;255;188m.\\033[48;2;000;255;189m.\\033[48;2;000;255;190m.\\033[48;2;000;255;191m.", "\\033[48;2;000;255;192m.\\033[48;2;000;255;193m.\\033[48;2;000;255;194m.\\033[48;2;000;255;195m.\\033[48;2;000;255;196m.\\033[48;2;000;255;197m.\\033[48;2;000;255;198m.\\033[48;2;000;255;199m.", "\\033[48;2;000;255;200m.\\033[48;2;000;255;201m.\\033[48;2;000;255;202m.\\033[48;2;000;255;203m.\\033[48;2;000;255;204m.\\033[48;2;000;255;205m.\\033[48;2;000;255;206m.\\033[48;2;000;255;207m.", "\\033[48;2;000;255;208m.\\033[48;2;000;255;209m.\\033[48;2;000;255;210m.\\033[48;2;000;255;211m.\\033[48;2;000;255;212m.\\033[48;2;000;255;213m.\\033[48;2;000;255;214m.\\033[48;2;000;255;215m.", "\\033[48;2;000;255;216m.\\033[48;2;000;255;217m.\\033[48;2;000;255;218m.\\033[48;2;000;255;219m.\\033[48;2;000;255;220m.\\033[48;2;000;255;221m.\\033[48;2;000;255;222m.\\033[48;2;000;255;223m.", "\\033[48;2;000;255;224m.\\033[48;2;000;255;225m.\\033[48;2;000;255;226m.\\033[48;2;000;255;227m.\\033[48;2;000;255;228m.\\033[48;2;000;255;229m.\\033[48;2;000;255;230m.\\033[48;2;000;255;231m.", "\\033[48;2;000;255;232m.\\033[48;2;000;255;233m.\\033[48;2;000;255;234m.\\033[48;2;000;255;235m.\\033[48;2;000;255;236m.\\033[48;2;000;255;237m.\\033[48;2;000;255;238m.\\033[48;2;000;255;239m.", "\\033[48;2;000;255;240m.\\033[48;2;000;255;241m.\\033[48;2;000;255;242m.\\033[48;2;000;255;243m.\\033[48;2;000;255;244m.\\033[48;2;000;255;245m.\\033[48;2;000;255;246m.\\033[48;2;000;255;247m.", "\\033[48;2;000;255;248m.\\033[48;2;000;255;249m.\\033[48;2;000;255;250m.\\033[48;2;000;255;251m.\\033[48;2;000;255;252m.\\033[48;2;000;255;253m.\\033[48;2;000;255;254m.\\033[48;2;000;255;255m.", "\\033[0m\\n ", "\\033[48;2;000;255;255m.\\033[48;2;000;254;255m.\\033[48;2;000;253;255m.\\033[48;2;000;252;255m.\\033[48;2;000;251;255m.\\033[48;2;000;250;255m.\\033[48;2;000;249;255m.\\033[48;2;000;248;255m.", "\\033[48;2;000;247;255m.\\033[48;2;000;246;255m.\\033[48;2;000;245;255m.\\033[48;2;000;244;255m.\\033[48;2;000;243;255m.\\033[48;2;000;242;255m.\\033[48;2;000;241;255m.\\033[48;2;000;240;255m.", "\\033[48;2;000;239;255m.\\033[48;2;000;238;255m.\\033[48;2;000;237;255m.\\033[48;2;000;236;255m.\\033[48;2;000;235;255m.\\033[48;2;000;234;255m.\\033[48;2;000;233;255m.\\033[48;2;000;232;255m.", "\\033[48;2;000;231;255m.\\033[48;2;000;230;255m.\\033[48;2;000;229;255m.\\033[48;2;000;228;255m.\\033[48;2;000;227;255m.\\033[48;2;000;226;255m.\\033[48;2;000;225;255m.\\033[48;2;000;224;255m.", "\\033[48;2;000;223;255m.\\033[48;2;000;222;255m.\\033[48;2;000;221;255m.\\033[48;2;000;220;255m.\\033[48;2;000;219;255m.\\033[48;2;000;218;255m.\\033[48;2;000;217;255m.\\033[48;2;000;216;255m.", "\\033[48;2;000;215;255m.\\033[48;2;000;214;255m.\\033[48;2;000;213;255m.\\033[48;2;000;212;255m.\\033[48;2;000;211;255m.\\033[48;2;000;210;255m.\\033[48;2;000;209;255m.\\033[48;2;000;208;255m.", "\\033[48;2;000;207;255m.\\033[48;2;000;206;255m.\\033[48;2;000;205;255m.\\033[48;2;000;204;255m.\\033[48;2;000;203;255m.\\033[48;2;000;202;255m.\\033[48;2;000;201;255m.\\033[48;2;000;200;255m.", "\\033[48;2;000;199;255m.\\033[48;2;000;198;255m.\\033[48;2;000;197;255m.\\033[48;2;000;196;255m.\\033[48;2;000;195;255m.\\033[48;2;000;194;255m.\\033[48;2;000;193;255m.\\033[48;2;000;192;255m.", "\\033[48;2;000;191;255m.\\033[48;2;000;190;255m.\\033[48;2;000;189;255m.\\033[48;2;000;188;255m.\\033[48;2;000;187;255m.\\033[48;2;000;186;255m.\\033[48;2;000;185;255m.\\033[48;2;000;184;255m.", "\\033[48;2;000;183;255m.\\033[48;2;000;182;255m.\\033[48;2;000;181;255m.\\033[48;2;000;180;255m.\\033[48;2;000;179;255m.\\033[48;2;000;178;255m.\\033[48;2;000;177;255m.\\033[48;2;000;176;255m.", "\\033[48;2;000;175;255m.\\033[48;2;000;174;255m.\\033[48;2;000;173;255m.\\033[48;2;000;172;255m.\\033[48;2;000;171;255m.\\033[48;2;000;170;255m.\\033[48;2;000;169;255m.\\033[48;2;000;168;255m.", "\\033[48;2;000;167;255m.\\033[48;2;000;166;255m.\\033[48;2;000;165;255m.\\033[48;2;000;164;255m.\\033[48;2;000;163;255m.\\033[48;2;000;162;255m.\\033[48;2;000;161;255m.\\033[48;2;000;160;255m.", "\\033[0m\\n ", "\\033[48;2;000;159;255m.\\033[48;2;000;158;255m.\\033[48;2;000;157;255m.\\033[48;2;000;156;255m.\\033[48;2;000;155;255m.\\033[48;2;000;154;255m.\\033[48;2;000;153;255m.\\033[48;2;000;152;255m.", "\\033[48;2;000;151;255m.\\033[48;2;000;150;255m.\\033[48;2;000;149;255m.\\033[48;2;000;148;255m.\\033[48;2;000;147;255m.\\033[48;2;000;146;255m.\\033[48;2;000;145;255m.\\033[48;2;000;144;255m.", "\\033[48;2;000;143;255m.\\033[48;2;000;142;255m.\\033[48;2;000;141;255m.\\033[48;2;000;140;255m.\\033[48;2;000;139;255m.\\033[48;2;000;138;255m.\\033[48;2;000;137;255m.\\033[48;2;000;136;255m.", "\\033[48;2;000;135;255m.\\033[48;2;000;134;255m.\\033[48;2;000;133;255m.\\033[48;2;000;132;255m.\\033[48;2;000;131;255m.\\033[48;2;000;130;255m.\\033[48;2;000;129;255m.\\033[48;2;000;128;255m.", "\\033[48;2;000;127;255m.\\033[48;2;000;126;255m.\\033[48;2;000;125;255m.\\033[48;2;000;124;255m.\\033[48;2;000;123;255m.\\033[48;2;000;122;255m.\\033[48;2;000;121;255m.\\033[48;2;000;120;255m.", "\\033[48;2;000;119;255m.\\033[48;2;000;118;255m.\\033[48;2;000;117;255m.\\033[48;2;000;116;255m.\\033[48;2;000;115;255m.\\033[48;2;000;114;255m.\\033[48;2;000;113;255m.\\033[48;2;000;112;255m.", "\\033[48;2;000;111;255m.\\033[48;2;000;110;255m.\\033[48;2;000;109;255m.\\033[48;2;000;108;255m.\\033[48;2;000;107;255m.\\033[48;2;000;106;255m.\\033[48;2;000;105;255m.\\033[48;2;000;104;255m.", "\\033[48;2;000;103;255m.\\033[48;2;000;102;255m.\\033[48;2;000;101;255m.\\033[48;2;000;100;255m.\\033[48;2;000;099;255m.\\033[48;2;000;098;255m.\\033[48;2;000;097;255m.\\033[48;2;000;096;255m.", "\\033[48;2;000;095;255m.\\033[48;2;000;094;255m.\\033[48;2;000;093;255m.\\033[48;2;000;092;255m.\\033[48;2;000;091;255m.\\033[48;2;000;090;255m.\\033[48;2;000;089;255m.\\033[48;2;000;088;255m.", "\\033[48;2;000;087;255m.\\033[48;2;000;086;255m.\\033[48;2;000;085;255m.\\033[48;2;000;084;255m.\\033[48;2;000;083;255m.\\033[48;2;000;082;255m.\\033[48;2;000;081;255m.\\033[48;2;000;080;255m.", "\\033[48;2;000;079;255m.\\033[48;2;000;078;255m.\\033[48;2;000;077;255m.\\033[48;2;000;076;255m.\\033[48;2;000;075;255m.\\033[48;2;000;074;255m.\\033[48;2;000;073;255m.\\033[48;2;000;072;255m.", "\\033[48;2;000;071;255m.\\033[48;2;000;070;255m.\\033[48;2;000;069;255m.\\033[48;2;000;068;255m.\\033[48;2;000;067;255m.\\033[48;2;000;066;255m.\\033[48;2;000;065;255m.\\033[48;2;000;064;255m.", "\\033[0m\\n ", "\\033[48;2;000;063;255m.\\033[48;2;000;062;255m.\\033[48;2;000;061;255m.\\033[48;2;000;060;255m.\\033[48;2;000;059;255m.\\033[48;2;000;058;255m.\\033[48;2;000;057;255m.\\033[48;2;000;056;255m.", "\\033[48;2;000;055;255m.\\033[48;2;000;054;255m.\\033[48;2;000;053;255m.\\033[48;2;000;052;255m.\\033[48;2;000;051;255m.\\033[48;2;000;050;255m.\\033[48;2;000;049;255m.\\033[48;2;000;048;255m.", "\\033[48;2;000;047;255m.\\033[48;2;000;046;255m.\\033[48;2;000;045;255m.\\033[48;2;000;044;255m.\\033[48;2;000;043;255m.\\033[48;2;000;042;255m.\\033[48;2;000;041;255m.\\033[48;2;000;040;255m.", "\\033[48;2;000;039;255m.\\033[48;2;000;038;255m.\\033[48;2;000;037;255m.\\033[48;2;000;036;255m.\\033[48;2;000;035;255m.\\033[48;2;000;034;255m.\\033[48;2;000;033;255m.\\033[48;2;000;032;255m.", "\\033[48;2;000;031;255m.\\033[48;2;000;030;255m.\\033[48;2;000;029;255m.\\033[48;2;000;028;255m.\\033[48;2;000;027;255m.\\033[48;2;000;026;255m.\\033[48;2;000;025;255m.\\033[48;2;000;024;255m.", "\\033[48;2;000;023;255m.\\033[48;2;000;022;255m.\\033[48;2;000;021;255m.\\033[48;2;000;020;255m.\\033[48;2;000;019;255m.\\033[48;2;000;018;255m.\\033[48;2;000;017;255m.\\033[48;2;000;016;255m.", "\\033[48;2;000;015;255m.\\033[48;2;000;014;255m.\\033[48;2;000;013;255m.\\033[48;2;000;012;255m.\\033[48;2;000;011;255m.\\033[48;2;000;010;255m.\\033[48;2;000;009;255m.\\033[48;2;000;008;255m.", "\\033[48;2;000;007;255m.\\033[48;2;000;006;255m.\\033[48;2;000;005;255m.\\033[48;2;000;004;255m.\\033[48;2;000;003;255m.\\033[48;2;000;002;255m.\\033[48;2;000;001;255m.\\033[48;2;000;000;255m.", "\\033[48;2;000;000;255m.\\033[48;2;001;000;255m.\\033[48;2;002;000;255m.\\033[48;2;003;000;255m.\\033[48;2;004;000;255m.\\033[48;2;005;000;255m.\\033[48;2;006;000;255m.\\033[48;2;007;000;255m.", "\\033[48;2;008;000;255m.\\033[48;2;009;000;255m.\\033[48;2;010;000;255m.\\033[48;2;011;000;255m.\\033[48;2;012;000;255m.\\033[48;2;013;000;255m.\\033[48;2;014;000;255m.\\033[48;2;015;000;255m.", "\\033[48;2;016;000;255m.\\033[48;2;017;000;255m.\\033[48;2;018;000;255m.\\033[48;2;019;000;255m.\\033[48;2;020;000;255m.\\033[48;2;021;000;255m.\\033[48;2;022;000;255m.\\033[48;2;023;000;255m.", "\\033[48;2;024;000;255m.\\033[48;2;025;000;255m.\\033[48;2;026;000;255m.\\033[48;2;027;000;255m.\\033[48;2;028;000;255m.\\033[48;2;029;000;255m.\\033[48;2;030;000;255m.\\033[48;2;031;000;255m.", "\\033[0m\\n ", "\\033[48;2;032;000;255m.\\033[48;2;033;000;255m.\\033[48;2;034;000;255m.\\033[48;2;035;000;255m.\\033[48;2;036;000;255m.\\033[48;2;037;000;255m.\\033[48;2;038;000;255m.\\033[48;2;039;000;255m.", "\\033[48;2;040;000;255m.\\033[48;2;041;000;255m.\\033[48;2;042;000;255m.\\033[48;2;043;000;255m.\\033[48;2;044;000;255m.\\033[48;2;045;000;255m.\\033[48;2;046;000;255m.\\033[48;2;047;000;255m.", "\\033[48;2;048;000;255m.\\033[48;2;049;000;255m.\\033[48;2;050;000;255m.\\033[48;2;051;000;255m.\\033[48;2;052;000;255m.\\033[48;2;053;000;255m.\\033[48;2;054;000;255m.\\033[48;2;055;000;255m.", "\\033[48;2;056;000;255m.\\033[48;2;057;000;255m.\\033[48;2;058;000;255m.\\033[48;2;059;000;255m.\\033[48;2;060;000;255m.\\033[48;2;061;000;255m.\\033[48;2;062;000;255m.\\033[48;2;063;000;255m.", "\\033[48;2;064;000;255m.\\033[48;2;065;000;255m.\\033[48;2;066;000;255m.\\033[48;2;067;000;255m.\\033[48;2;068;000;255m.\\033[48;2;069;000;255m.\\033[48;2;070;000;255m.\\033[48;2;071;000;255m.", "\\033[48;2;072;000;255m.\\033[48;2;073;000;255m.\\033[48;2;074;000;255m.\\033[48;2;075;000;255m.\\033[48;2;076;000;255m.\\033[48;2;077;000;255m.\\033[48;2;078;000;255m.\\033[48;2;079;000;255m.", "\\033[48;2;080;000;255m.\\033[48;2;081;000;255m.\\033[48;2;082;000;255m.\\033[48;2;083;000;255m.\\033[48;2;084;000;255m.\\033[48;2;085;000;255m.\\033[48;2;086;000;255m.\\033[48;2;087;000;255m.", "\\033[48;2;088;000;255m.\\033[48;2;089;000;255m.\\033[48;2;090;000;255m.\\033[48;2;091;000;255m.\\033[48;2;092;000;255m.\\033[48;2;093;000;255m.\\033[48;2;094;000;255m.\\033[48;2;095;000;255m.", "\\033[48;2;096;000;255m.\\033[48;2;097;000;255m.\\033[48;2;098;000;255m.\\033[48;2;099;000;255m.\\033[48;2;100;000;255m.\\033[48;2;101;000;255m.\\033[48;2;102;000;255m.\\033[48;2;103;000;255m.", "\\033[48;2;104;000;255m.\\033[48;2;105;000;255m.\\033[48;2;106;000;255m.\\033[48;2;107;000;255m.\\033[48;2;108;000;255m.\\033[48;2;109;000;255m.\\033[48;2;110;000;255m.\\033[48;2;111;000;255m.", "\\033[48;2;112;000;255m.\\033[48;2;113;000;255m.\\033[48;2;114;000;255m.\\033[48;2;115;000;255m.\\033[48;2;116;000;255m.\\033[48;2;117;000;255m.\\033[48;2;118;000;255m.\\033[48;2;119;000;255m.", "\\033[48;2;120;000;255m.\\033[48;2;121;000;255m.\\033[48;2;122;000;255m.\\033[48;2;123;000;255m.\\033[48;2;124;000;255m.\\033[48;2;125;000;255m.\\033[48;2;126;000;255m.\\033[48;2;127;000;255m.", "\\033[0m\\n ", "\\033[48;2;128;000;255m.\\033[48;2;129;000;255m.\\033[48;2;130;000;255m.\\033[48;2;131;000;255m.\\033[48;2;132;000;255m.\\033[48;2;133;000;255m.\\033[48;2;134;000;255m.\\033[48;2;135;000;255m.", "\\033[48;2;136;000;255m.\\033[48;2;137;000;255m.\\033[48;2;138;000;255m.\\033[48;2;139;000;255m.\\033[48;2;140;000;255m.\\033[48;2;141;000;255m.\\033[48;2;142;000;255m.\\033[48;2;143;000;255m.", "\\033[48;2;144;000;255m.\\033[48;2;145;000;255m.\\033[48;2;146;000;255m.\\033[48;2;147;000;255m.\\033[48;2;148;000;255m.\\033[48;2;149;000;255m.\\033[48;2;150;000;255m.\\033[48;2;151;000;255m.", "\\033[48;2;152;000;255m.\\033[48;2;153;000;255m.\\033[48;2;154;000;255m.\\033[48;2;155;000;255m.\\033[48;2;156;000;255m.\\033[48;2;157;000;255m.\\033[48;2;158;000;255m.\\033[48;2;159;000;255m.", "\\033[48;2;160;000;255m.\\033[48;2;161;000;255m.\\033[48;2;162;000;255m.\\033[48;2;163;000;255m.\\033[48;2;164;000;255m.\\033[48;2;165;000;255m.\\033[48;2;166;000;255m.\\033[48;2;167;000;255m.", "\\033[48;2;168;000;255m.\\033[48;2;169;000;255m.\\033[48;2;170;000;255m.\\033[48;2;171;000;255m.\\033[48;2;172;000;255m.\\033[48;2;173;000;255m.\\033[48;2;174;000;255m.\\033[48;2;175;000;255m.", "\\033[48;2;176;000;255m.\\033[48;2;177;000;255m.\\033[48;2;178;000;255m.\\033[48;2;179;000;255m.\\033[48;2;180;000;255m.\\033[48;2;181;000;255m.\\033[48;2;182;000;255m.\\033[48;2;183;000;255m.", "\\033[48;2;184;000;255m.\\033[48;2;185;000;255m.\\033[48;2;186;000;255m.\\033[48;2;187;000;255m.\\033[48;2;188;000;255m.\\033[48;2;189;000;255m.\\033[48;2;190;000;255m.\\033[48;2;191;000;255m.", "\\033[48;2;192;000;255m.\\033[48;2;193;000;255m.\\033[48;2;194;000;255m.\\033[48;2;195;000;255m.\\033[48;2;196;000;255m.\\033[48;2;197;000;255m.\\033[48;2;198;000;255m.\\033[48;2;199;000;255m.", "\\033[48;2;200;000;255m.\\033[48;2;201;000;255m.\\033[48;2;202;000;255m.\\033[48;2;203;000;255m.\\033[48;2;204;000;255m.\\033[48;2;205;000;255m.\\033[48;2;206;000;255m.\\033[48;2;207;000;255m.", "\\033[48;2;208;000;255m.\\033[48;2;209;000;255m.\\033[48;2;210;000;255m.\\033[48;2;211;000;255m.\\033[48;2;212;000;255m.\\033[48;2;213;000;255m.\\033[48;2;214;000;255m.\\033[48;2;215;000;255m.", "\\033[48;2;216;000;255m.\\033[48;2;217;000;255m.\\033[48;2;218;000;255m.\\033[48;2;219;000;255m.\\033[48;2;220;000;255m.\\033[48;2;221;000;255m.\\033[48;2;222;000;255m.\\033[48;2;223;000;255m.", "\\033[0m\\n ", "\\033[48;2;224;000;255m.\\033[48;2;225;000;255m.\\033[48;2;226;000;255m.\\033[48;2;227;000;255m.\\033[48;2;228;000;255m.\\033[48;2;229;000;255m.\\033[48;2;230;000;255m.\\033[48;2;231;000;255m.", "\\033[48;2;232;000;255m.\\033[48;2;233;000;255m.\\033[48;2;234;000;255m.\\033[48;2;235;000;255m.\\033[48;2;236;000;255m.\\033[48;2;237;000;255m.\\033[48;2;238;000;255m.\\033[48;2;239;000;255m.", "\\033[48;2;240;000;255m.\\033[48;2;241;000;255m.\\033[48;2;242;000;255m.\\033[48;2;243;000;255m.\\033[48;2;244;000;255m.\\033[48;2;245;000;255m.\\033[48;2;246;000;255m.\\033[48;2;247;000;255m.", "\\033[48;2;248;000;255m.\\033[48;2;249;000;255m.\\033[48;2;250;000;255m.\\033[48;2;251;000;255m.\\033[48;2;252;000;255m.\\033[48;2;253;000;255m.\\033[48;2;254;000;255m.\\033[48;2;255;000;255m.", "\\033[48;2;255;000;255m.\\033[48;2;255;000;254m.\\033[48;2;255;000;253m.\\033[48;2;255;000;252m.\\033[48;2;255;000;251m.\\033[48;2;255;000;250m.\\033[48;2;255;000;249m.\\033[48;2;255;000;248m.", "\\033[48;2;255;000;247m.\\033[48;2;255;000;246m.\\033[48;2;255;000;245m.\\033[48;2;255;000;244m.\\033[48;2;255;000;243m.\\033[48;2;255;000;242m.\\033[48;2;255;000;241m.\\033[48;2;255;000;240m.", "\\033[48;2;255;000;239m.\\033[48;2;255;000;238m.\\033[48;2;255;000;237m.\\033[48;2;255;000;236m.\\033[48;2;255;000;235m.\\033[48;2;255;000;234m.\\033[48;2;255;000;233m.\\033[48;2;255;000;232m.", "\\033[48;2;255;000;231m.\\033[48;2;255;000;230m.\\033[48;2;255;000;229m.\\033[48;2;255;000;228m.\\033[48;2;255;000;227m.\\033[48;2;255;000;226m.\\033[48;2;255;000;225m.\\033[48;2;255;000;224m.", "\\033[48;2;255;000;223m.\\033[48;2;255;000;222m.\\033[48;2;255;000;221m.\\033[48;2;255;000;220m.\\033[48;2;255;000;219m.\\033[48;2;255;000;218m.\\033[48;2;255;000;217m.\\033[48;2;255;000;216m.", "\\033[48;2;255;000;215m.\\033[48;2;255;000;214m.\\033[48;2;255;000;213m.\\033[48;2;255;000;212m.\\033[48;2;255;000;211m.\\033[48;2;255;000;210m.\\033[48;2;255;000;209m.\\033[48;2;255;000;208m.", "\\033[48;2;255;000;207m.\\033[48;2;255;000;206m.\\033[48;2;255;000;205m.\\033[48;2;255;000;204m.\\033[48;2;255;000;203m.\\033[48;2;255;000;202m.\\033[48;2;255;000;201m.\\033[48;2;255;000;200m.", "\\033[48;2;255;000;199m.\\033[48;2;255;000;198m.\\033[48;2;255;000;197m.\\033[48;2;255;000;196m.\\033[48;2;255;000;195m.\\033[48;2;255;000;194m.\\033[48;2;255;000;193m.\\033[48;2;255;000;192m.", "\\033[0m\\n ", "\\033[48;2;255;000;191m.\\033[48;2;255;000;190m.\\033[48;2;255;000;189m.\\033[48;2;255;000;188m.\\033[48;2;255;000;187m.\\033[48;2;255;000;186m.\\033[48;2;255;000;185m.\\033[48;2;255;000;184m.", "\\033[48;2;255;000;183m.\\033[48;2;255;000;182m.\\033[48;2;255;000;181m.\\033[48;2;255;000;180m.\\033[48;2;255;000;179m.\\033[48;2;255;000;178m.\\033[48;2;255;000;177m.\\033[48;2;255;000;176m.", "\\033[48;2;255;000;175m.\\033[48;2;255;000;174m.\\033[48;2;255;000;173m.\\033[48;2;255;000;172m.\\033[48;2;255;000;171m.\\033[48;2;255;000;170m.\\033[48;2;255;000;169m.\\033[48;2;255;000;168m.", "\\033[48;2;255;000;167m.\\033[48;2;255;000;166m.\\033[48;2;255;000;165m.\\033[48;2;255;000;164m.\\033[48;2;255;000;163m.\\033[48;2;255;000;162m.\\033[48;2;255;000;161m.\\033[48;2;255;000;160m.", "\\033[48;2;255;000;159m.\\033[48;2;255;000;158m.\\033[48;2;255;000;157m.\\033[48;2;255;000;156m.\\033[48;2;255;000;155m.\\033[48;2;255;000;154m.\\033[48;2;255;000;153m.\\033[48;2;255;000;152m.", "\\033[48;2;255;000;151m.\\033[48;2;255;000;150m.\\033[48;2;255;000;149m.\\033[48;2;255;000;148m.\\033[48;2;255;000;147m.\\033[48;2;255;000;146m.\\033[48;2;255;000;145m.\\033[48;2;255;000;144m.", "\\033[48;2;255;000;143m.\\033[48;2;255;000;142m.\\033[48;2;255;000;141m.\\033[48;2;255;000;140m.\\033[48;2;255;000;139m.\\033[48;2;255;000;138m.\\033[48;2;255;000;137m.\\033[48;2;255;000;136m.", "\\033[48;2;255;000;135m.\\033[48;2;255;000;134m.\\033[48;2;255;000;133m.\\033[48;2;255;000;132m.\\033[48;2;255;000;131m.\\033[48;2;255;000;130m.\\033[48;2;255;000;129m.\\033[48;2;255;000;128m.", "\\033[48;2;255;000;127m.\\033[48;2;255;000;126m.\\033[48;2;255;000;125m.\\033[48;2;255;000;124m.\\033[48;2;255;000;123m.\\033[48;2;255;000;122m.\\033[48;2;255;000;121m.\\033[48;2;255;000;120m.", "\\033[48;2;255;000;119m.\\033[48;2;255;000;118m.\\033[48;2;255;000;117m.\\033[48;2;255;000;116m.\\033[48;2;255;000;115m.\\033[48;2;255;000;114m.\\033[48;2;255;000;113m.\\033[48;2;255;000;112m.", "\\033[48;2;255;000;111m.\\033[48;2;255;000;110m.\\033[48;2;255;000;109m.\\033[48;2;255;000;108m.\\033[48;2;255;000;107m.\\033[48;2;255;000;106m.\\033[48;2;255;000;105m.\\033[48;2;255;000;104m.", "\\033[48;2;255;000;103m.\\033[48;2;255;000;102m.\\033[48;2;255;000;101m.\\033[48;2;255;000;100m.\\033[48;2;255;000;099m.\\033[48;2;255;000;098m.\\033[48;2;255;000;097m.\\033[48;2;255;000;096m.", "\\033[0m\\n ", "\\033[48;2;255;000;095m.\\033[48;2;255;000;094m.\\033[48;2;255;000;093m.\\033[48;2;255;000;092m.\\033[48;2;255;000;091m.\\033[48;2;255;000;090m.\\033[48;2;255;000;089m.\\033[48;2;255;000;088m.", "\\033[48;2;255;000;087m.\\033[48;2;255;000;086m.\\033[48;2;255;000;085m.\\033[48;2;255;000;084m.\\033[48;2;255;000;083m.\\033[48;2;255;000;082m.\\033[48;2;255;000;081m.\\033[48;2;255;000;080m.", "\\033[48;2;255;000;079m.\\033[48;2;255;000;078m.\\033[48;2;255;000;077m.\\033[48;2;255;000;076m.\\033[48;2;255;000;075m.\\033[48;2;255;000;074m.\\033[48;2;255;000;073m.\\033[48;2;255;000;072m.", "\\033[48;2;255;000;071m.\\033[48;2;255;000;070m.\\033[48;2;255;000;069m.\\033[48;2;255;000;068m.\\033[48;2;255;000;067m.\\033[48;2;255;000;066m.\\033[48;2;255;000;065m.\\033[48;2;255;000;064m.", "\\033[48;2;255;000;063m.\\033[48;2;255;000;062m.\\033[48;2;255;000;061m.\\033[48;2;255;000;060m.\\033[48;2;255;000;059m.\\033[48;2;255;000;058m.\\033[48;2;255;000;057m.\\033[48;2;255;000;056m.", "\\033[48;2;255;000;055m.\\033[48;2;255;000;054m.\\033[48;2;255;000;053m.\\033[48;2;255;000;052m.\\033[48;2;255;000;051m.\\033[48;2;255;000;050m.\\033[48;2;255;000;049m.\\033[48;2;255;000;048m.", "\\033[48;2;255;000;047m.\\033[48;2;255;000;046m.\\033[48;2;255;000;045m.\\033[48;2;255;000;044m.\\033[48;2;255;000;043m.\\033[48;2;255;000;042m.\\033[48;2;255;000;041m.\\033[48;2;255;000;040m.", "\\033[48;2;255;000;039m.\\033[48;2;255;000;038m.\\033[48;2;255;000;037m.\\033[48;2;255;000;036m.\\033[48;2;255;000;035m.\\033[48;2;255;000;034m.\\033[48;2;255;000;033m.\\033[48;2;255;000;032m.", "\\033[48;2;255;000;031m.\\033[48;2;255;000;030m.\\033[48;2;255;000;029m.\\033[48;2;255;000;028m.\\033[48;2;255;000;027m.\\033[48;2;255;000;026m.\\033[48;2;255;000;025m.\\033[48;2;255;000;024m.", "\\033[48;2;255;000;023m.\\033[48;2;255;000;022m.\\033[48;2;255;000;021m.\\033[48;2;255;000;020m.\\033[48;2;255;000;019m.\\033[48;2;255;000;018m.\\033[48;2;255;000;017m.\\033[48;2;255;000;016m.", "\\033[48;2;255;000;015m.\\033[48;2;255;000;014m.\\033[48;2;255;000;013m.\\033[48;2;255;000;012m.\\033[48;2;255;000;011m.\\033[48;2;255;000;010m.\\033[48;2;255;000;009m.\\033[48;2;255;000;008m.", "\\033[48;2;255;000;007m.\\033[48;2;255;000;006m.\\033[48;2;255;000;005m.\\033[48;2;255;000;004m.\\033[48;2;255;000;003m.\\033[48;2;255;000;002m.\\033[48;2;255;000;001m.\\033[48;2;255;000;000m.", "\\033[0m\\n", "\\n", "---> Hit 'e' for next test: ", "\\033[2J\\033[H" "ESC TEST 0023: FG/BG Specific Reset\\n", "\\n", "Test fg reset: \\033[31mThis is red on norm bg\\033[39m, This is ESC[39m reset (norm fg on norm bg).\\033[m\\n", "Test bg reset: \\033[41mThis is norm fg on red bg\\033[49m, This is ESC[49m reset (norm fg on norm bg).\\033[m\\n", "\\n", "Test fg/bg with fg reset: \\033[32;44mThis is grn on blu\\033[39m, This is ESC[39m reset (norm fg on blu).\\033[m\\n", "Test fg/bg with bg reset: \\033[32;44mThis is grn on blu\\033[49m, This is ESC[49m reset (grn on norm bg).\\033[m\\n", "\\n", "---> Hit 'e' for next test: ", NULL }; if (reset) { index = 0; return 0; } return show_test(test, index);} {} } Function {test_esc_fgbg_colors(bool reset)} { comment {--- 0030: Test FG/BG Colors} return_type {static int} } { code {static int index = 0; const char *test[] = { // Screen 30 "\\033[2J\\033[H" "ESC TEST 0030: FG/BG Colors\\n", "\\n", " Foreground Colors:\\n", " \\033[2;31m" " Dim Red text \\033[0m \\033[0;32m" " Dim Grn text \\033[0m \\033[2;33m" " Dim Yel text \\033[0m\\n", " \\033[2;34m" " Dim Blu text \\033[0m \\033[0;35m" " Dim Mag text \\033[0m \\033[2;36m" " Dim Cyn text \\033[0m" " \\033[2;37m" " Dim Wht text \\033[0m\\n", " \\033[0;31m" " Nor Red text \\033[0m \\033[0;32m" " Nor Grn text \\033[0m \\033[2;33m" " Nor Yel text \\033[0m\\n", " \\033[0;34m" " Nor Blu text \\033[0m \\033[0;35m" " Nor Mag text \\033[0m \\033[0;36m" " Nor Cyn text \\033[0m" " \\033[0;37m" " Nor Wht text \\033[0m\\n", " \\033[1;31m" " Bold Red text \\033[0m \\033[1;32m" " Bold Grn text \\033[0m \\033[1;33m" " Bold Yel text \\033[0m\\n", " \\033[1;34m" " Bold Blu text \\033[0m \\033[1;35m" " Bold Mag \\033[0m \\033[1;36m" " Bold Cyn text \\033[0m" " \\033[1;37m" " Bold Wht text \\033[0m\\n", "\\n", " Background Colors:\\n", " \\033[2;37;41m"" Dim Red bg \\033[0m \\033[2;37;42m"" Dim Grn bg \\033[0m \\033[2;37;43m"" Dim Yel bg \\033[0m\\n", " \\033[2;37;44m"" Dim Blu bg \\033[0m \\033[2;37;45m"" Dim Mag bg \\033[0m \\033[2;37;46m"" Dim Cyn bg \\033[0m" " \\033[2;37;47m"" Dim Wht bg \\033[0m\\n", " \\033[0;37;41m"" Nor Red bg \\033[0m \\033[0;37;42m"" Nor Grn bg \\033[0m \\033[0;37;43m"" Nor Yel bg \\033[0m\\n", " \\033[0;37;44m"" Nor Blu bg \\033[0m \\033[0;37;45m"" Nor Mag bg \\033[0m \\033[0;37;46m"" Nor Cyn bg \\033[0m" " \\033[0;37;47m"" Nor Wht bg \\033[0m\\n", " \\033[1;37;41m"" Bold Red bg \\033[0m \\033[1;37;42m"" Bold Grn bg \\033[0m \\033[1;37;43m"" Bold Yel bg \\033[0m\\n", " \\033[1;37;44m"" Bold Blu bg \\033[0m \\033[1;37;45m"" Bold Mag bg \\033[0m \\033[1;37;46m"" Bold Cyn bg \\033[0m" " \\033[1;37;47m"" Bold Wht bg \\033[0m\\n", "\\n", "---> Hit 'e' for next test: ", NULL }; if (reset) { index = 0; return 0; } return show_test(test, index);} {} } Function {test_esc_curpos(bool reset)} { comment {--- 0040: Test Cursor Positioning} return_type {static int} } { code {static int index = 0; const char *test[] = { // Screen 40 "\\033[2J\\033[H" "ESC TEST 0040: Cursor Positioning\\n", "2:\\n", "3: 10 15 20 25 30 35 40 45 50 55 60 65 70\\n", "4: |----:----|----:----|----:----|----:----|----:----|----:----|\\n", "5:\\n", "6:\\n", "7:\\n", "\\033[5;10H" "X", "\\033[5;15H" "X", "\\033[5;20H" "X", "\\033[5;40H" "X", "\\033[5;45H" "X", "\\033[5;50H" "X", "\\033[6;10H" "|", "\\033[6;15H" "|", "\\033[6;20H" "|", "\\033[6;40H" "|", "\\033[6;45H" "|", "\\033[6;50H" "|", "\\033[7;10H" "10,5", "\\033[7;15H" "15,5", "\\033[7;20H" "20,5", "\\033[7;40H" "40,5", "\\033[7;45H" "45,5", "\\033[7;50H" "50,5", "\\033[8H\\n", "---> Hit 'e' for next test: ", NULL }; if (reset) { index = 0; return 0; } return show_test(test, index);} {} } Function {test_esc_tabstops(bool reset)} { comment {--- 0050: Tabstops: Default Tabstops} return_type {static int} } { code {static int index = 0; const char *test[] = { // Screen 50 // We use c to reset the terminal to default tabstops. "\\033c" "ESC TEST 0050: Tabs: Default Tabstops\\n", " A B C D E F G H I\\n", " | | | | | | | | |\\n", "\\tA\\tB\\tC\\tD-\\tE--\\tF-----\\tG------\\tH-------I\\n", "\\t\\tB\\t\\tD\\t\\tF\\t\\tH-------I\\n", "---> Hit 'e' for next test: ", // We use c to reset the terminal to default tabstops. // Should also clear screen and home cursor.. "\\033c" "ESC TEST 0051: Tabs: Change Tabstops\\n", "\\n", " 8 16 24 32 40 48 56 64 72\\n", "--------|-------|-------|-------|-------|-------|-------|-------|-------|\\n", "\\tX\\tX\\tX\\tX\\tX\\tX\\tX\\tX\\tX\\n", "\\n", "Setting new tabstops..\\033[3g\\n", ".\\033HT..\\033HT...\\033HT....\\033HT.....\\033HT......\\033HT.......\\033HT........\\033HT.........\\033HT\\n", "-|--|---|----|-----|------|-------|--------|---------|\\n", "\\tX\\tX\\tX\\tX\\tX\\tX\\tX\\tX\\tX\\tX\\n", "---> Hit 'e' for next test: ", "\\033c" "ESC TEST 0052: Tabs: Default Tabstops Again\\n", "\\n", "Back to normal tabstops:\\n", " 8 16 24 32 40 48 56 64 72\\n", "--------|-------|-------|-------|-------|-------|-------|-------|-------|\\n", "\\tX\\tX\\tX\\tX\\tX\\tX\\tX\\tX\\tX\\n", "\\n", "---> Hit 'e' for next test: ", NULL }; if (reset) { index = 0; return 0; } return show_test(test, index);} {} } Function {test_esc_insert_char(bool reset)} { comment {--- 0060: Insert Char} return_type {static int} } { code {static int index = 0; const char *test[] = { // Screen 60 "\\033[2J\\033[HESC TEST 0060: Insert Char (ESC[@)\\n", "\\n", " 10> 20> 30> 40> 50> 60> 70> 80>\\n", "4:34567890123456789012345678901234567890123456789012345678901234567890123456789\\n", "5:34567890123456789012345678901234567890123456789012345678901234567890123456789\\n", "6:34567890123456789012345678901234567890123456789012345678901234567890123456789\\n", "\\033[s\\033[5;29H\\033[1;31m>\\033[0m\\033[u", // save curs, movcur, bold/red, '>', norm, recall curs "\\n", "---> Hit 'e' to test INSERT 1 char at row/col 5/30 (right of '>'): \\033[K", "\\033[5;30H\\033[@\\033[8H", "---> Hit 'e' to test INSERT 1 char at row/col 5/30 (right of '>'): \\033[K", "\\033[5;30H\\033[@\\033[8H", "---> Hit 'e' to test INSERT 4 chars at row/col 5/30 (right of '>'): \\033[K", "\\033[5;30H\\033[4@\\033[8H", "---> Hit 'e' to test INSERT 4 chars at row/col 5/30 (right of '>'): \\033[K", "\\033[5;30H\\033[4@\\033[8H", "---> Hit 'e' to test DELETE 1 chars at row/col 5/20 (right of '>'): \\033[K", "\\033[5;30H\\033[P\\033[8H", "---> Hit 'e' to test DELETE 1 chars at row/col 5/20 (right of '>'): \\033[K", "\\033[5;30H\\033[P\\033[8H", "---> Hit 'e' to test DELETE 2 chars at row/col 5/20 (right of '>'): \\033[K", "\\033[5;30H\\033[2P\\033[8H", "---> Hit 'e' to test DELETE 4 chars at row/col 5/20 (right of '>'): \\033[K", "\\033[5;30H\\033[4P\\033[8H", "---> Hit 'e' to test DELETE 1 char at row/col 5/20 (right of '>'): \\033[K", "\\033[5;30H\\033[P\\033[8H", "---> Hit 'e' to test DELETE 1 char at row/col 5/20 (right of '>'): \\033[K", "\\033[5;30H\\033[P\\033[8H", "---> Hit 'e' to test DELETE 1 *EXTRA* char at row/col 5/20 (right of '>'): \\033[K", "\\033[5;30H\\033[P\\033[8H", "---> Hit 'e' for next test: \\033[K", NULL }; if (reset) { index = 0; return 0; } return show_test(test, index);} {} } Function {test_esc_clear_test(bool reset)} { comment {--- 0070: Clear Test ESC[K / ESC[K} return_type {static int} } { code {static int index = 0; const char *test[] = { // Screen 70 "\\033[2J\\033[H" "ESC TEST 0070: Clear Test (ESC[K / ESC[J)\\n", "2: 10> 20> 30> 40> 50> 60> 70> 80>\\n", "3:34567890123456789012345678901234567890123456789012345678901234567890123456789\\n", "4:3456789012345678901234 ERASE EOL->XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\\n", "5:YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY<-ERASE SOL 012345678901234567890123456789\\n", "6:34567890123456789012345678901234567890123456789012345678901234567890123456789\\n", "7:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n", "8:34567890123456789012345678901234567890123456789012345678901234567890123456789\\n", "9:3456789012345678901234 ERASE EOD->ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\\n", "0:ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\\n", "1:ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\\n", "2:ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\\n", "3:ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\\n", "4:ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\\n", "5:ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\\n", "6:ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\\n", "7:ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\\n", "\\n", "---> Hit 'e' to test ERASE EOL (should make X's disappear): ", "\\033[4;37H\\033[K\\n", // ERASE EOL "\\033[19H", "---> Hit 'e' to test ERASE SOL (should make Y's disappear): ", "\\033[5;37H\\033[1K\\n", // ERASE SOL "\\033[19H", "---> Hit 'e' to test ERASE LINE (should make F's disappear): ", "\\033[7;37H\\033[2K\\n", // ERASE LINE "\\033[19H", "---> Hit 'e' to test ERASE EOD (should make Z's disappear): ", "\\033[9;37H\\033[0J\\n", // ERASE EOD "\\033[19H", "---> Hit 'e' for next test: ", // Screen 71 "\\033[2J\\033[H" "ESC TEST 0071: Clear Test (ESC[K / ESC[J)\\n", "2: | | | | | |\\n", "3:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\\n", "4:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\\n", "5:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\\n", "6:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<-- ERASE SOD 567890123456789\\n", "7:3456789012345678901234567890123456789012345678901234567890123456789\\n", "8:3456789012345678901234567890123456789012345678901234567890123456789\\n", "9:3456789012345678901234567890123456789012345678901234567890123456789\\n", "\\033[19H", "---> Hit 'e' to test ERASE SOD (should make X's disappear): ", "\\033[6;40H\\033[1J\\n", // ERASE SOD "\\033[19H", "---> Hit 'e' for next test: \\033[K", NULL }; if (reset) { index = 0; return 0; } return show_test(test, index);} {} } Function {test_esc_delete_row(bool reset)} { comment {--- 0080: Delete Row - ESC[M} return_type {static int} } { code {static int index = 0; const char *test[] = { // Screen 80 "\\033[2J\\033[H" "ESC TEST 0080: Delete Row (ESC[M)\\n", "02:456789012345678901234567890123456789012345678901234567890123456789\\n", "03:456789012345678901234567890123456789012345678901234567890123456789\\n", "04:456789012345678901234567890123456789012345678901234567890123456789\\n", "05:456789012345678901234567890123456789012345678901234567890123456789\\n", "06:456789012345678901234567890123456789012345678901234567890123456789\\n", "07:456789012345678901234567890123456789012345678901234567890123456789\\n", "08:456789012345678901234567890123456789012345678901234567890123456789\\n", "09:456789012345678901234567890123456789012345678901234567890123456789\\n", "10:456789012345678901234567890123456789012345678901234567890123456789\\n", "\\n", "\\n", "\\n", "\\n", "\\n", "\\n", "\\n", "\\n", "\\n", "\\n", "\\n", "\\n", "\\n", "24:456789012345678901234567890123456789012345678901234567890123456789\\n", "25:456789012345678901234567890123456789012345678901234567890123456789", "\\033[12H", // to prompt row "---> Hit 'e' to test [1/4] DELETE LINE 3 with ESC[M: \\033[K", "\\033[2K", // clear prompt "\\033[3H", // move to line 3 "\\033[M", // delete line 3 "\\033[12H", // back to line 12H for prompt //"\\033[2K\\033[3H\\033[M", // clear prompt, to row 3, delete row //"\\033[12H", // to prompt row "---> Hit 'e' to test [2/4] DELETE 3 MORE LINES with ESC[3M: \\033[K", "\\033[2K\\033[3H\\033[3M", // clear prompt, to row 3, delete 3 rows "\\033[12H", // to prompt row "---> Hit 'e' to test [3/4] DELETE 3 MORE LINES with ESC[3M: \\033[K", "\\033[2K\\033[3H\\033[3M", // clear prompt, to row 3, delete 3 rows "\\033[12H", // to prompt row "---> Hit 'e' to test [4/4] DELETE 3 MORE LINES with ESC[3M: \\033[K", "\\033[2K\\033[3H\\033[3M", // clear prompt, to row 3, delete 3 rows "\\033[12H", // to prompt row "---> Hit 'e' for next test: ", NULL }; if (reset) { index = 0; return 0; } return show_test(test, index);} {} } Function {test_esc_insert_row(bool reset)} { comment {--- 0085: Insert Row - ESC[L} return_type {static int} } { code {static int index = 0; const char *test[] = { // Screen 71 "\\033[2J\\033[H" "ESC TEST 0085: Insert Row (ESC[L)\\n", "2:3456789012345678901234567890123456789012345678901234567890123456789\\n", "3:3456789012345678901234567890123456789012345678901234567890123456789\\n", "4:3456789012345678901234567890123456789012345678901234567890123456789\\n", "\\033[24H", "24:456789012345678901234567890123456789012345678901234567890123456789\\n", "25:456789012345678901234567890123456789012345678901234567890123456789", "\\033[12H", "---> Hit 'e' to test [1/3] INSERT 1 ROW AT LINE 3 with ESC[L: \\033[K", "\\033[2K\\033[3H\\033[L", // clear prompt, to row 3, insert row "\\033[12H", // to prompt row 17 "---> Hit 'e' to test [2/3] INSERT 3 ROWS AT LINE 3 with ESC[3L: \\033[K", "\\033[2K\\033[3H\\033[3L", // clear prompt, to row 3, insert 3 rows "\\033[12H", // to prompt row 17 "---> Hit 'e' for next test: ", NULL }; if (reset) { index = 0; return 0; } return show_test(test, index);} {} } Function {test_esc_scrolling(bool reset)} { comment {--- 0090: Scrolling Up/Down - [S / M} return_type {static int} } { code {static int index = 0; const char *test[] = { // Screen 90 "\\033[2J\\033[H" "ESC TEST 0090: Scrolling up/down\\n", "Line 2 🡅\\n", "Line 3 [A]\\n", "Line 4 🡅\\n", "Line 5 [B]\\n", "Line 6\\n", "Line 7\\n", "Line 8\\n", "Line 9\\n", "Line 10\\n", "Line 11\\n", "Line 12\\n", // Do this weird thing so the lines still appear in order in our code "\\033[200H\\033[10ABottom Line -10", "\\033[200H\\033[9ABottom Line -9", "\\033[200H\\033[8ABottom Line -8", "\\033[200H\\033[7ABottom Line -7", "\\033[200H\\033[6ABottom Line -6", "\\033[200H\\033[5ABottom Line -5 [D]", "\\033[200H\\033[4ABottom Line -4 🡇", "\\033[200H\\033[3ABottom Line -3", "\\033[200H\\033[2ABottom Line -2 [C]", "\\033[200H\\033[1ABottom Line -1 🡇", "\\033[200H" "Bottom Line 0", "\\033[15H", // Line 15 "---> Hit 'e' to SCROLL UP 1 with [S so top line at position [A]: \\033[K", "\\033[H\\033[S\\033[14H", // Line 14 because up one line "---> Hit 'e' to SCROLL UP 2 with [2S so top line at position [B]: \\033[K", "\\033[H\\033[2S\\033[12H", // Line 12 because up two more lines "---> Hit 'e' to SCROLL DOWN 1 with M at screen top: \\033[K", "\\033[H\\033M\\033[13H", // Line 13 because down 1 line "---> Hit 'e' to SCROLL DOWN 2 with 2xM: \\033[K", "\\033[H\\033M\\033M\\033[15H", // Line 15 because down 2 lines "---> Hit 'e' to SCROLL DOWN 1 with M for bottom line at posn [C]: \\033[K", "\\033[H\\033M\\033[16H", // Line 16 because down 1 lines "---> Hit 'e' to SCROLL DOWN 3 with 3xM for bottom line at posn [D]: \\033[K", "\\033[H\\033M\\033M\\033M\\033[19H", // Line 18 because down 3 lines //TODO Other ESC commands to scroll up/down? "---> Hit 'e' for next test: \\033[K", // Screen 100 "\\033[2J\\033[HESC TEST 0091: Cursor Save/Restore Test\\n", "\\n", " Cursor positon at 'A' was saved with ESC[s.\\n", "\\033[12;39H>\\033[1;31m\\033[s""A""\\033[0m<\\033[20H", "---> Hit 'e' to recall cursor position and change 'A' to 'B': \\033[K", "\\033[u\\033[1;32m""B\\033[0m\\033[20H", "---> Hit 'e' for next test: \\033[K", NULL }; if (reset) { index = 0; return 0; } return show_test(test, index);} {} } decl {////// OTHER SELF TESTS //////} {private local } Function {show_file(const char *filename)} { comment {Show the specified file in the terminal } return_type void } { code {// If cursor floating, do a crlf first if (G_tty->cursor_col()!=0) G_tty->append("\\n"); char s[1024]; FILE *fp = fopen(filename, "r"); if ( fp == NULL ) { snprintf(s, sizeof(s), "\\033[1;31m%s: %s\\033[0m\\n", filename, strerror(errno)); s[1023] = 0; G_tty->append_utf8(s); return; } while ( fgets(s, sizeof(s)-1, fp) ) { s[1023] = 0; G_tty->append(s); // append line to display } // Last line in file? Done fclose(fp); fp = NULL;} {} } Function {speed_test()} { comment {Run full screen random character update} return_type void } { code {// 50 iters of WxH random chars (no scrolling) // First, switch redraw style to none, so we can handle redraws() G_tty->redraw_style(Fl_Terminal::NO_REDRAW); // Clear screen, do 50 iterations of random chars G_tty->append("\\033[H"); // home int rows = G_tty->display_rows(); int cols = G_tty->display_columns(); for (int i=0; i<50; i++ ) { for ( int row=0; rowtextfgcolor_xterm(rand() % 8); // random fg uchar color for each char G_tty->plot_char(c, row, col); } } G_tty->redraw(); Fl::wait(0.005); } // leave test with white on black G_tty->append("\\033[c"); // reset terminal // back to rate limited G_tty->redraw_style(Fl_Terminal::RATE_LIMITED); // Show the Unicode alignment page test_firstpage(false);} {} } Function {show_colorbars()} { comment {Show colorbars in terminal } open return_type void } { code {// If cursor floating, do a crlf first if (G_tty->cursor_col()!=0) G_tty->append("\\n"); Fl_Color fgsave = G_tty->textfgcolor(); Fl_Color bgsave = G_tty->textbgcolor(); // ECR-1-1978 // grey yellow cyan green magenta red blue Fl_Color bars1[] = { 0xc0c0c000, 0xbfc03700, 0x2ac0bf00, 0x25c03300, 0xbe00bb00, 0xbd051800, 0x1600ba00 }; Fl_Color bars2[] = { 0x1600ba00, 0x11111100, 0xbe00bb00, 0x11111100, 0x2ac0bf00, 0x11111100, 0xc0c0c000 }; Fl_Color boxes[] = { 0x05214a00, 0xffffff00, 0x32006700, 0x11111100, 0x03030300, 0x11111100, 0x1d1d1d00, 0x11111100 }; // -I 100% wht Q+ superblack black 4% black // \\________________________________/ // pluge const char *bar = "███████████"; const char *box1= "██████████████"; const char *box2= "█████████████"; const char *pluge = "███"; G_tty->append("\\033[2J\\033[H"); // Print 75% bars: bars1[] { for ( int y=0; y<16; y++ ) { for ( int i=0; i<7; i++ ) { G_tty->textfgcolor(bars1[i]); G_tty->append(bar); } G_tty->append("\\n"); } } // Print strip: bars2[] { for ( int y=0; y<2; y++ ) { for ( int i=0; i<7; i++ ) { G_tty->textfgcolor(bars2[i]); G_tty->append(bar); } G_tty->append("\\n"); } } // Bottom boxes { for ( int y=0; y<7; y++ ) { for ( int i=0; i<8; i++ ) { G_tty->textfgcolor(boxes[i]); if ( i < 3 ) G_tty->append(box1); else if ( i < 4 ) G_tty->append(box2); else if ( i < 7 ) G_tty->append(pluge); else G_tty->append(box2); } if ( y < 6 ) G_tty->append("\\n"); } } // Restore fg/bg colors G_tty->textfgcolor(fgsave); G_tty->textbgcolor(bgsave);} {} } Function {unicode_alignment()} { comment {Show unicode alignment test } return_type void } { code {test_firstpage(true);} {} } Function {add_lines(int count)} { comment {Add specified number of test lines to tty} return_type void } { code {// If cursor floating, do a crlf first if (G_tty->cursor_col()!=0) G_tty->append("\\n"); for ( int t=0; tprintf("Line %04d -- AAA BBB CCC DDD\\n", G_lines++);} {} } Function {do_command(const char *cmd)} { comment {Run the command, output appends to terminal } return_type void } { code {// Run command in pipe, return output to tty // TODO: This should probably be reimplemented as a thread. // Also, I doubt this will work well on Windows. // If it's a real problem, open a file and 'tail' it ourselves instead. // \#ifdef _WIN32 \#define POPEN(a,b) _popen(a,b) // effin windows \#define PCLOSE(a) _pclose(a) \#define READ(a,b,c) _read(a,b,c) \#define FILENO(a) _fileno(a) \#define SSIZE_T int \#else \#define POPEN(a,b) popen(a,b) \#define PCLOSE(a) pclose(a) \#define READ(a,b,c) read(a,b,c) \#define FILENO(a) fileno(a) \#define SSIZE_T ssize_t \#endif // If cursor floating, do a crlf first if (G_tty->cursor_col()!=0) G_tty->append("\\n"); FILE *fp = POPEN(cmd, "r"); char s[4096]; if ( fp == NULL ) { sprintf(s, "\\033[0;31mCan't execute '%.200s': %s\\033[0m\\n", cmd, strerror(errno)); G_tty->append_utf8(s); return; } int fd = FILENO(fp); \#ifndef _WIN32 // Non-blocking IO keeps interface "alive" during slow commands. // Too bad Microsoft's implementation of the C library read() call // is so poor it doesn't properly support non-blocking IO or fcntl(). // fcntl(fd, F_SETFL, O_NONBLOCK); \#endif // Read in byte blocks G_tty->append(NULL); // (clears utf8 cache) while (1) { Fl::wait(0.05); SSIZE_T bytes = READ(fd, s, sizeof(s)); // shout in uppercase so windows can hear us if (bytes == -1 && errno == EAGAIN) continue; // no data yet else if (bytes > 0) G_tty->append(s, bytes); // write block to terminal, handles utf8 else break; // pipe closed } PCLOSE(fp); G_tty->append_ascii("\\033[33;2m<>\\033[0m\\n"); G_tty->redraw();} {} } decl {////// GUI LAYOUT //////} {private local } Function {parse_color(const char *val_str, Fl_Color &col)} { comment {Parse color in 'val_str', returns 0 and color in 'col', or -1 on error} return_type int } { code {unsigned long ival; if (sscanf(val_str, "\#%lx", &ival) == 1 ) { col = Fl_Color(ival); return 0; } if (sscanf(val_str, "%lu", &ival) == 1 ) { col = Fl_Color(ival); return 0; } fl_alert("Illegal color value '%s'\\n(can be e.g. '12' or '\#0c', etc)", val_str); return -1;} {} } Function {update_inputs()} { comment {Resync the inputs with widget's values} open return_type void } { code {// Scroll History scrollhistory_input->value( G_tty->history_rows() ); // Redraw rate redraw_rate_spinner->value( G_tty->redraw_rate() ); // Font Size fontsize_input->value( G_tty->textsize() ); // Scrollbar Size scrollbarsize_input->range(0, 80); scrollbarsize_input->step(1); scrollbarsize_input->value( G_tty->scrollbar_size() ); // show_unknown() enable/disable showunknown_radio->value( G_tty->show_unknown() ? 1 : 0 ); // ansi() enable/disable ansi_radio->value(tty ->ansi() ? 1 : 0 ); // box() choice switch ( G_tty->box() ) { case FL_UP_FRAME: box_choice->value(0); break; case FL_DOWN_FRAME: box_choice->value(1); break; case FL_THIN_UP_FRAME: box_choice->value(2); break; case FL_THIN_DOWN_FRAME: box_choice->value(3); break; case FL_ENGRAVED_FRAME: box_choice->value(4); break; case FL_EMBOSSED_FRAME: box_choice->value(5); break; case FL_BORDER_FRAME: box_choice->value(6); break; // --- case FL_UP_BOX: box_choice->value(7); break; case FL_DOWN_BOX: box_choice->value(8); break; case FL_FLAT_BOX: box_choice->value(9); break; case FL_THIN_UP_BOX: box_choice->value(10); break; case FL_THIN_DOWN_BOX: box_choice->value(11); break; case FL_BORDER_BOX: box_choice->value(12); break; case FL_NO_BOX: box_choice->value(13); break; default: box_choice->value(1); break; } // color() { char s[80]; sprintf(s, "\#%08x", G_tty->color()); color_input->value(s); } // textcolor() { char s[80]; sprintf(s, "\#%08x", G_tty->textcolor()); textcolor_input->value(s); } // textfg/bgcolor() { char s[80]; sprintf(s, "\#%08x", G_tty->textfgcolor()); textfgcolor_input->value(s); sprintf(s, "\#%08x", G_tty->textbgcolor()); textbgcolor_input->value(s); // defaults sprintf(s, "\#%08x", G_tty->textfgcolor_default()); textfgcolor_default_input->value(s); sprintf(s, "\#%08x", G_tty->textbgcolor_default()); textbgcolor_default_input->value(s); } // TODO: current_style().charflags() // cursorfg/bg color { char s[80]; sprintf(s, "\#%08x", G_tty->cursorfgcolor()); cursorfgcolor_input->value(s); sprintf(s, "\#%08x", G_tty->cursorbgcolor()); cursorbgcolor_input->value(s); } // Margins { int lt = G_tty->margin_left(); int rt = G_tty->margin_right(); int top = G_tty->margin_top(); int bot = G_tty->margin_bottom(); char s[100]; sprintf(s, "%d, %d, %d, %d", lt,rt,top,bot); margins_input->value(s); } // selectionfg/bgcolor() { char s[80]; sprintf(s, "\#%08x", G_tty->selectionfgcolor()); selectionfgcolor_input->value(s); sprintf(s, "\#%08x", G_tty->selectionbgcolor()); selectionbgcolor_input->value(s); } // output_translate() { int out = G_tty->output_translate(); outflags_lf_to_crlf->value((out&Fl_Terminal::LF_TO_CRLF) ? 1 : 0); outflags_lf_to_cr->value( (out&Fl_Terminal::LF_TO_CR) ? 1 : 0); outflags_cr_to_lf->value( (out&Fl_Terminal::CR_TO_LF) ? 1 : 0); }} {} } Function {handle_output_translate(void)} { comment {Handle the output_translation() flags} open return_type void } { code {// Handle combining output_translate() flags.. int out = 0; if ( outflags_lf_to_crlf->value() ) out |= Fl_Terminal::LF_TO_CRLF; if ( outflags_lf_to_cr->value() ) out |= Fl_Terminal::LF_TO_CR; if ( outflags_cr_to_lf->value() ) out |= Fl_Terminal::CR_TO_LF; G_tty->output_translate(Fl_Terminal::OutFlags(out));} {} } Function {make_window()} {open } { Fl_Window win { label {Fl_Terminal Test} callback {exit(0);} open xywh {831 66 897 838} type Double size_range {897 330 0 0} visible } { Fl_Spinner scrollhistory_input { label {Scroll History} callback {int val = int(scrollhistory_input->value() + .5); G_tty->history_rows(val);} tooltip {Scrollback history size. 10,000 max.} xywh {109 10 115 20} labelsize 10 minimum 0 maximum 10000 textsize 10 } Fl_Spinner fontsize_input { label {Font Size} callback {int val = int(fontsize_input->value() + .5); G_tty->textsize(val);} xywh {109 38 115 20} labelsize 10 textsize 10 } Fl_Spinner scrollbarsize_input { label {Scrollbar Size} callback {int val = int(scrollbarsize_input->value() + .5); G_tty->scrollbar_size(val); G_tty->redraw();} tooltip {Size of scrollbar width in pixels} xywh {109 67 115 20} labelsize 10 textsize 10 } Fl_Spinner redraw_rate_spinner { label {Min Redraw Time} callback {float rate = float(redraw_rate_spinner->value()); //printf("Setting redraw rate to %.2f\\n", rate); G_tty->redraw_rate(rate);} tooltip {Minimum time between redraws Default is 0.10 secs.} xywh {109 94 115 20} type Float labelsize 10 minimum 0.05 maximum 5 step 0.1 textsize 10 } Fl_Choice scheme_widget { label scheme open tooltip Scheme xywh {109 120 115 20} down_box BORDER_BOX labelsize 10 textsize 10 class Fl_Scheme_Choice } {} Fl_Choice box_choice { label {box()} open tooltip {The border box for the Fl_Terminal} xywh {109 147 115 20} down_box BORDER_BOX labelsize 10 textsize 10 } { MenuItem {} { label FL_UP_FRAME user_data FL_UP_FRAME user_data_type long callback {G_tty->box(FL_UP_FRAME); G_tty->redraw();} xywh {10 10 100 20} labelsize 8 } MenuItem {} { label FL_DOWN_FRAME user_data FL_DOWN_FRAME user_data_type long callback {G_tty->box(FL_DOWN_FRAME); G_tty->redraw();} xywh {10 10 100 20} labelsize 8 } MenuItem {} { label FL_THIN_UP_FRAME user_data FL_THIN_UP_FRAME user_data_type long callback {G_tty->box(FL_THIN_UP_FRAME); G_tty->redraw();} xywh {10 10 100 20} labelsize 8 } MenuItem {} { label FL_THIN_DOWN_FRAME user_data FL_THIN_DOWN_FRAME user_data_type long callback {G_tty->box(FL_THIN_DOWN_FRAME); G_tty->redraw();} xywh {10 10 100 20} labelsize 8 } MenuItem {} { label FL_ENGRAVED_FRAME user_data FL_ENGRAVED_FRAME user_data_type long callback {G_tty->box(FL_ENGRAVED_FRAME); G_tty->redraw();} xywh {10 10 100 20} labelsize 8 } MenuItem {} { label FL_EMBOSSED_FRAME user_data FL_EMBOSSED_FRAME user_data_type long callback {G_tty->box(FL_EMBOSSED_FRAME); G_tty->redraw();} xywh {10 10 100 20} labelsize 8 } MenuItem {} { label FL_BORDER_FRAME user_data FL_BORDER_FRAME user_data_type long callback {G_tty->box(FL_BORDER_FRAME); G_tty->redraw();} xywh {10 10 100 20} labelsize 8 divider } MenuItem {} { label FL_UP_BOX user_data FL_UP_BOX user_data_type long callback {G_tty->box(FL_UP_BOX); G_tty->redraw();} xywh {10 10 100 20} labelsize 8 } MenuItem {} { label FL_DOWN_BOX callback {G_tty->box(FL_DOWN_BOX); G_tty->redraw();} xywh {20 20 100 20} labelsize 8 } MenuItem {} { label FL_FLAT_BOX callback {G_tty->box(FL_FLAT_BOX); G_tty->redraw();} xywh {30 30 100 20} labelsize 8 } MenuItem {} { label FL_THIN_UP_BOX callback {G_tty->box(FL_THIN_UP_BOX); G_tty->redraw();} xywh {40 40 100 20} labelsize 8 } MenuItem {} { label FL_THIN_DOWN_BOX callback {G_tty->box(FL_THIN_DOWN_BOX); G_tty->redraw();} xywh {50 50 100 20} labelsize 8 } MenuItem {} { label FL_BORDER_BOX callback {G_tty->box(FL_BORDER_BOX); G_tty->redraw();} xywh {0 0 100 20} labelsize 8 } MenuItem {} { label FL_NO_BOX callback {G_tty->box(FL_NO_BOX); G_tty->redraw();} xywh {10 10 100 20} labelsize 8 } } Fl_Box {} { label {Lt, Rt, Top, Bot} xywh {110 172 114 15} labelsize 10 } Fl_Input margins_input { label Margins callback {int lt,rt,top,bot; const char *val = margins_input->value(); if (sscanf(val, "%d,%d,%d,%d",<,&rt,&top,&bot)!=4) { fl_alert("Margins: expected four comma separated integers"); return; } G_tty->margin_left(lt); G_tty->margin_right(rt); G_tty->margin_top(top); G_tty->margin_bottom(bot); G_tty->redraw();} xywh {110 187 114 20} labelsize 10 when 28 textsize 10 } Fl_Check_Button outflags_lf_to_crlf { label LF_TO_CRLF callback {handle_output_translate();} tooltip {Line-feed (\\n) performs carriage-return and line-feed (CRLF)} xywh {333 7 77 24} down_box DOWN_BOX labelsize 9 } Fl_Check_Button outflags_lf_to_cr { label LF_TO_CR callback {handle_output_translate();} tooltip {Line-feed (\\n) performs carriage-return (\\r)} xywh {432 7 70 24} down_box DOWN_BOX labelsize 9 } Fl_Check_Button outflags_cr_to_lf { label CR_TO_LF callback {handle_output_translate();} tooltip {Carriage-return (\\r) performs line-feed (\\n)} xywh {528 7 70 24} down_box DOWN_BOX labelsize 9 } Fl_Check_Button showunknown_radio { label {show_unknown()} callback {G_tty->show_unknown(showunknown_radio->value() ? true : false); G_tty->redraw();} tooltip {Shows unknown escape sequences/unprintable chars as "¿" character} xywh {331 31 105 24} down_box DOWN_BOX labelsize 9 } Fl_Check_Button interactivecursor_radio { label {Interactive Cursor} callback {bool val = interactivecursor_radio->value() ? true : false; G_tty->interactive_cursor(val);} tooltip {Allow Up/Dn/Lt/Rt keys to move cursor when terminal has focus} xywh {473 31 125 24} down_box DOWN_BOX labelsize 9 } Fl_Check_Button ansi_radio { label {ansi()} callback {G_tty->ansi(ansi_radio->value() ? true : false);} tooltip {Handle ANSI/xterm escape sequences} xywh {331 55 95 24} down_box DOWN_BOX labelsize 9 } Fl_Check_Button stdout_radio { label {Echo tests to stdout} tooltip {Also send test output to stdout} xywh {473 55 125 24} down_box DOWN_BOX labelsize 9 } Fl_Input textcolor_input { label {textcolor()} callback {Fl_Color c; if (parse_color(textcolor_input->value(), c) == -1 ) return; G_tty->textcolor(c); update_inputs(); //DEBUG ::printf("IVAL is %08lx\\n",ival); G_tty->redraw();} tooltip {The widget's text color. Has the effect of simultaneously setting: > textfgcolor() >textfgcolor_default() Can be decimal (e.g. 12) or hex (e.g. \#0c, \#0000000c, etc)} xywh {333 79 77 20} labelsize 9 when 28 textfont 4 textsize 9 } Fl_Input textfgcolor_input { label {textfgcolor()} callback {Fl_Color c; if (parse_color(textfgcolor_input->value(), c) == -1 ) return; G_tty->textfgcolor(c); update_inputs(); //DEBUG ::printf("IVAL is %08lx\\n",ival); G_tty->redraw();} tooltip {The text foreground color. Can be decimal (e.g. 12) or hex (e.g. \#0c, \#0000000c, etc)} xywh {333 103 77 20} labelsize 9 when 28 textfont 4 textsize 9 } Fl_Input textfgcolor_default_input { label {textfgcolor_default()} callback {Fl_Color c; if (parse_color(textfgcolor_default_input->value(), c) == -1 ) return; G_tty->textfgcolor_default(c); update_inputs(); //DEBUG ::printf("IVAL is %08lx\\n",ival); G_tty->redraw();} tooltip {The text foreground default color. Can be decimal (e.g. 12) or hex (e.g. \#0c, \#0000000c, etc)} xywh {333 127 77 20} labelsize 9 when 28 textfont 4 textsize 9 } Fl_Input cursorfgcolor_input { label {cursorfgcolor()} callback {Fl_Color c; if (parse_color(cursorfgcolor_input->value(), c) == -1 ) return; G_tty->cursorfgcolor(c); update_inputs(); //DEBUG ::printf("IVAL is %08lx\\n",ival); G_tty->redraw();} tooltip {Foreground color for text under the cursor.} xywh {333 151 77 20} labelsize 9 when 28 textfont 4 textsize 9 } Fl_Input selectionfgcolor_input { label {selectionfgcolor()} callback {Fl_Color c; if (parse_color(selectionfgcolor_input->value(), c) == -1 ) return; G_tty->selectionfgcolor(c); update_inputs(); //DEBUG ::printf("IVAL is %08lx\\n",ival); G_tty->redraw();} tooltip {The mouse selection foreground color. Can be decimal (e.g. 12) or hex (e.g. \#0c, \#0000000c, etc)} xywh {333 175 77 20} labelsize 9 when 28 textfont 4 textsize 9 } Fl_Input color_input { label {color()} callback {Fl_Color c; if (parse_color(color_input->value(), c) == -1 ) return; G_tty->color(c); update_inputs(); //DEBUG ::printf("IVAL is %08lx\\n",ival); G_tty->redraw();} tooltip {The widget's background color(). Can be decimal (e.g. 12) or hex (e.g. \#0c, \#0000000c, etc)} xywh {521 79 77 20} labelsize 9 when 28 textfont 4 textsize 9 } Fl_Input textbgcolor_input { label {textbgcolor()} callback {Fl_Color c; if (parse_color(textbgcolor_input->value(), c) == -1 ) return; G_tty->textbgcolor(c); update_inputs(); //DEBUG ::printf("IVAL is %08lx\\n",ival); G_tty->redraw();} tooltip {The text background color. Refer to the docs for the special value 0xffffffff. Can be decimal (e.g. 12) or hex (e.g. \#0c, \#0000000c, etc)} xywh {521 103 77 20} labelsize 9 when 28 textfont 4 textsize 9 } Fl_Input textbgcolor_default_input { label {textbgcolor_default()} callback {Fl_Color c; if (parse_color(textbgcolor_default_input->value(), c) == -1 ) return; G_tty->textbgcolor_default(c); update_inputs(); //DEBUG ::printf("IVAL is %08lx\\n",ival); G_tty->redraw();} tooltip {The text background default color. Refer to the docs for the special value 0xffffffff. Can be decimal (e.g. 12) or hex (e.g. \#0c, \#0000000c, etc)} xywh {521 127 77 20} labelsize 9 when 28 textfont 4 textsize 9 } Fl_Input cursorbgcolor_input { label {cursorbgcolor()} callback {Fl_Color c; if (parse_color(cursorbgcolor_input->value(), c) == -1 ) return; G_tty->cursorbgcolor(c); update_inputs(); //DEBUG ::printf("IVAL is %08lx\\n",ival); G_tty->redraw();} tooltip {Background color for the cursor. This is the cursor block's color} xywh {521 151 77 20} labelsize 9 when 28 textfont 4 textsize 9 } Fl_Input selectionbgcolor_input { label {selectionbgcolor()} callback {Fl_Color c; if (parse_color(selectionbgcolor_input->value(), c) == -1 ) return; G_tty->selectionbgcolor(c); update_inputs(); //DEBUG ::printf("IVAL is %08lx\\n",ival); G_tty->redraw();} tooltip {The mouse selection background color. Can be decimal (e.g. 12) or hex (e.g. \#0c, \#0000000c, etc)} xywh {521 175 77 20} labelsize 9 when 28 textfont 4 textsize 9 } Fl_Choice {} { label {Terminal Color} open tooltip {The (XTERM) colors can be influenced by Dim/Bold, whereas the (RGB) colors are not.} xywh {379 206 180 20} down_box BORDER_BOX labelsize 9 textsize 9 } { MenuItem {} { label {White on DarkAmber (XTERM)} callback {G_tty->color(0x30200000); // amber widget bg color G_tty->textfgcolor_xterm(7); // XTERM_WHITE (influenced by Dim/Bold) G_tty->textbgcolor(0xffffffff); // "see through" color update_inputs(); add_lines(5);} tooltip {Sets text fg to XTERM White, text bg to "see through", and widget's color() to amber. Text fg can be influenced by Dim/Bold.} xywh {10 10 100 20} labelsize 9 } MenuItem {} { label {White on Black (XTERM)} callback {G_tty->textfgcolor_xterm(7); // XTERM WHITE (influenced by Dim/Bold) G_tty->textbgcolor(0xffffffff); G_tty->color(0x00000000); update_inputs(); add_lines(5);} tooltip {Sets text fg to XTERM White, text bg to "see through", and widget's color() to black. Text fg can be influenced by Dim/Bold.} xywh {20 20 100 20} labelsize 9 divider } MenuItem {} { label {White on DarkAmber (RGB)} callback {G_tty->color(0x30200000); // amber widget bg color G_tty->textfgcolor(0xd0d0d000); G_tty->textbgcolor(0xffffffff); // "see through" color update_inputs(); add_lines(5);} xywh {20 20 100 20} labelsize 9 } MenuItem {} { label {White on Black (RGB)} callback {G_tty->textfgcolor(0xd0d0d000); G_tty->textbgcolor(0xffffffff); G_tty->color(0x00000000); update_inputs(); add_lines(5);} xywh {30 30 100 20} labelsize 9 } MenuItem {} { label {Black on White (RGB)} callback {G_tty->textfgcolor(0x00000000); G_tty->textbgcolor(0xd0d0d000); G_tty->color(0xd0d0d000); update_inputs(); add_lines(5);} xywh {20 20 100 20} labelsize 9 } MenuItem {} { label {Green on Dark Green (RGB)} callback {G_tty->textfgcolor(0x00d04000); G_tty->textbgcolor(0x00200800); G_tty->color(0x00200800); update_inputs(); add_lines(5);} xywh {30 30 100 20} labelsize 9 } MenuItem {} { label {Orange on Dark Orange (RGB)} callback {G_tty->textfgcolor(0xd0704000); G_tty->textbgcolor(0x20100000); G_tty->color(0x20100000); update_inputs(); add_lines(5);} xywh {40 40 100 20} labelsize 9 } } Fl_Group {} { label {Terminal Ops} open xywh {608 21 152 210} box ENGRAVED_FRAME labelsize 11 } { Fl_Button {} { label {Reset Terminal API} callback {G_tty->reset_terminal(); G_tty->redraw(); // Reset the 'Add +50' line counter to 1 G_lines = 1;} tooltip {Reset terminal using reset_terminal() Clears: screen, history, sets default tabstops, etc.} xywh {616 26 64 24} labelsize 8 } Fl_Button {} { label {Reset Terminal ANSI} callback {G_tty->append("\\033c"); // reset terminal G_tty->redraw(); // Reset the 'Add +50' line counter to 1 G_lines = 1;} tooltip {Reset terminal using ESC[c Clears: screen, history, sets default tabstops, etc.} xywh {686 26 64 24} labelsize 8 } Fl_Button {} { label {Home Cursor API} callback {G_tty->cursor_home(); G_tty->redraw();} tooltip {Moves cursor to home position (top/left) using cursor_home()} xywh {616 54 64 24} labelsize 8 } Fl_Button {} { label {Home Cursor ANSI} callback {G_tty->append("\\033[H"); G_tty->redraw();} tooltip {Moves cursor to home position (top/left) using ESC[H} xywh {686 54 64 24} labelsize 8 } Fl_Button {} { label {Clear History API} callback {G_tty->clear_history(); G_tty->redraw();} tooltip {Clear scrollback history using clear_history()} xywh {616 82 64 24} labelsize 8 } Fl_Button {} { label {Clear History ANSI} callback {G_tty->append("\\033[3J"); // clr history G_tty->redraw();} tooltip {Clear scrollback history using ESC[3J} xywh {686 82 64 24} labelsize 8 } Fl_Button {} { label {Clear Screen API} callback {G_tty->clear(); G_tty->redraw(); // Reset the 'Add +50' line counter to 1 G_lines = 1;} tooltip {Clear terminal screen using clear(). Moves what was on the screen to the scroll history.} xywh {616 110 64 24} labelsize 8 } Fl_Button {} { label {Clear Screen ANSI} callback {G_tty->append("\\033[H\\033[2J"); // home, cls G_tty->redraw(); // Reset the 'Add +50' line counter to 1 G_lines = 1;} tooltip {Clear terminal screen using ESC[H + ESC[2J Moves what was on the screen to the scroll history.} xywh {686 110 64 24} labelsize 8 } Fl_Group {} {open xywh {616 138 134 24} box FLAT_BOX color 45 } { Fl_Button {} { label {Clear Screen To Color} callback {Fl_Color c; if (parse_color(clear_color_input->value(), c) == -1 ) return; G_tty->clear(c); G_tty->redraw(); // Reset the 'Add +50' line counter to 1 G_lines = 1;} tooltip {Clear terminal screen to specific color Moves what was on the screen to the scroll history.} xywh {616 138 64 24} labelsize 8 } Fl_Input clear_color_input { tooltip {The color used by "Clear Screen To Color" button Can be decimal (e.g. 12) or hex (e.g. \#0c, \#ff000000, etc)} xywh {686 138 64 24} labelsize 9 when 28 textfont 4 textsize 9 code0 {clear_color_input->value("\#ff000000");} } } Fl_Button {} { label {Speed Test} callback {speed_test();} tooltip {Runs a full screen random chars/colors Shortcut: S} xywh {640 168 90 25} shortcut 0x73 labelsize 11 } Fl_Button {} { label {Ring Debug} callback {// Force scroll history to be small so we can see entire ring w/out scrolling if (scrollhistory_input->value() > 35) { scrollhistory_input->value(35); scrollhistory_input->do_callback(); } // Show debug window G_tty->show_ring_debug_window();} tooltip {Show the Fl_Terminal raw ring buffer contents. (Warning: This slows the UI and uses continuous cpu until closed)} xywh {640 198 90 25} labelsize 11 } } Fl_Group {} { label {Terminal Tests} xywh {767 21 115 210} box ENGRAVED_FRAME labelsize 11 } { Fl_Button {} { label {Unicode Alignment} callback {unicode_alignment();} tooltip {Show a Unicode screen alignment test Checks that troublesome Unicode chars don't cause misalignment} xywh {778 31 90 30} labelsize 9 } Fl_Button {} { label {+50 Lines} callback {add_lines(50);} tooltip {Add 50 lines of text to terminal. Tests screen history, scrollup} xywh {778 66 90 30} labelsize 9 } Fl_Button {} { label {Color Bars} callback {show_colorbars();} tooltip {Show colorbar test Tests API for setting colors Does *NOT* use ESC codes} xywh {778 101 90 30} labelsize 11 } Fl_Box {} { label {Self Tests} xywh {782 173 90 15} labelsize 10 } Fl_Button {} { label {@<<} callback {NextEscapeTest(-1);} comment {Move to previous test} tooltip {Reverse through the ESC code self tests Shortcut: SHIFT+E} xywh {778 191 40 30} shortcut 0x10065 labelsize 11 } Fl_Button {} { label {@>>} callback {NextEscapeTest(1);} comment {Move to next test} tooltip {Advance through the ESC code self tests Shortcut: 'e'} xywh {828 191 40 30} shortcut 0x65 labelsize 11 } } Fl_Input showfile_input { label {Show File} callback {showfile_input->deactivate(); // causes focus loss? command_input->deactivate(); win->redraw(); Fl::wait(.01); show_file(showfile_input->value()); showfile_input->activate(); command_input->activate(); Fl::focus(showfile_input); // return focus win->redraw();} tooltip {Type in the pathname of a file to cat to the screen} xywh {109 238 773 25} labelsize 12 when 10 textfont 4 } Fl_Input command_input { label Command callback {showfile_input->deactivate(); command_input->deactivate(); // causes focus loss? win->redraw(); Fl::wait(.01); do_command(command_input->value()); showfile_input->activate(); command_input->activate(); Fl::focus(command_input); // return focus win->redraw();} tooltip {Command to run. Hit ENTER to run command. The command's stdout will appear in terminal.} xywh {109 269 773 25} labelsize 12 when 12 textfont 4 } Fl_Terminal tty { xywh {10 302 872 524} class MyTerminal } } code {// CTOR G_tty = tty; // global access G_tty->color(0x30200000); // dark orange (makes true black easy to see) G_tty->textsize(12); // smaller text (RGB demo needs this) win->resizable(tty); command_input->when(FL_WHEN_ENTER_KEY_ALWAYS); command_input->take_focus(); // ensure command prompt has keyboard focus on startup \#ifdef _WIN32 showfile_input->value("c:\\\\Windows\\\\system.ini"); command_input->value("dir c:\\\\windows"); \#else showfile_input->value("/etc/login.defs"); command_input->value("ls -la --color && ping google.com -c 5"); \#endif // Sync input vals with widget's current values update_inputs();} {} } } decl {////// MAIN //////} {private local } Function {} {open } { code {G_tty = NULL; Application app; // sets G_tty G_app = &app; app.show(argc, argv); // Run the "firstpage" test app.test_firstpage(false);} {} } fltk-1.4.3/test/mandelbrot.h0000644000175000017500000000341215004135251016064 0ustar albrechtalbrecht// // Mandelbrot set header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #define USE_COLORS 0 // change to 1 to start in color mode class Drawing_Area : public Fl_Box { void draw() FL_OVERRIDE; public: uchar *buffer; int use_colors; int W,H; int dx, dy, dw, dh; // drawing box offsets int nextline; int drawn; int julia; int iterations; int brightness; double jX, jY; double X,Y,scale; int sx, sy, sw, sh; // selection box void erase_box(); int handle(int) FL_OVERRIDE; void resize(int,int,int,int) FL_OVERRIDE; void new_display(); void new_buffer(); enum { MAX_BRIGHTNESS = 16, DEFAULT_BRIGHTNESS = 16, DEFAULT_BRIGHTNESS_COLOR = 8, MAX_ITERATIONS = 14, DEFAULT_ITERATIONS = 7 }; Drawing_Area(int x,int y,int w,int h) : Fl_Box(x,y,w,h) { buffer = 0; use_colors = USE_COLORS; W = w; H = h; dx = dy = 0; // NOTE: as the box type is set *after* the constructor dw = dh = 0; // the actual offsets are determined in draw() nextline = 0; drawn = 0; julia = 0; X = Y = 0; scale = 4.0; iterations = 1< #include #include #include #include #include #include #include #include #include // Button callback: v == 0 ("input") or 1 ("password") void rename_button(Fl_Widget *o, void *v) { int what = fl_int(v); int ret = 0; #if (FLTK_USE_STD) std::string input; if (what == 0) { fl_message_icon_label("§"); input = fl_input_str(ret, 0, "Input (no size limit, use ctrl/j for newline):", o->label()); } else { fl_message_icon_label("€"); input = fl_password_str(ret, 20, "Enter password (max. 20 characters):", o->label()); } if (ret == 0) { o->copy_label(input.c_str()); o->redraw(); } #else const char *input; if (what == 0) { fl_message_icon_label("§"); input = fl_input("Input (no size limit, use ctrl/j for newline):", o->label()); if (!input) ret = 1; } else { fl_message_icon_label("€"); input = fl_password(20, "Enter password (max. 20 characters):", o->label()); if (!input) ret = 1; } if (ret == 0) { o->copy_label(input); o->redraw(); } #endif // FLTK_USE_STD } void window_callback(Fl_Widget *win, void *) { int hotspot = fl_message_hotspot(); fl_message_hotspot(0); fl_message_title("note: no hotspot set for this dialog"); int rep = fl_choice("Are you sure you want to quit?", "Cancel", "Quit", "Dunno"); fl_message_hotspot(hotspot); if (rep == 1) exit(0); else if (rep == 2) { // (Dunno) fl_message_position(win); fl_message_title("This dialog must be centered over the main window"); fl_message("Well, maybe you should know before we quit."); } } /* This timer callback shows a message dialog (fl_choice) window every 5 seconds to test "recursive" (aka nested) common dialogs. The timer can be stopped by clicking the button "Stop these funny popups" or pressing the Enter key. As it is currently implemented, clicking the "Close" button will reactivate the popups (only possible if "recursive" dialogs are enabled, see below). Note 1: This dialog box had been blocked in FLTK 1.3 if another common dialog was already open because the used window was a static (i.e. permanently allocated) Fl_Window instance. This has been fixed in FLTK 1.4. See STR #334 ("technical change : remove statics in fl_ask") and also STR #2751 ("Limit input field characters"). */ void timer_cb(void *) { static int stop = 0; static int n = 0; const double delta = 5.0; // delay of popups const int nmax = 10; // limit no. of popups n++; if (n >= nmax) stop = 1; Fl_Box *message_icon = (Fl_Box *)fl_message_icon(); if (stop) { message_icon->color(FL_WHITE); return; } Fl::repeat_timeout(delta, timer_cb); // Change the icon box color: Fl_Color c = message_icon->color(); c = (c + 1) % 32; if (c == message_icon->labelcolor()) c++; message_icon->color((Fl_Color)c); // test message title assignment with a local buffer { // local scope for buf char buf[40]; // test: use local variable snprintf(buf, 40, "Message #%d", n); // fill message title fl_message_title(buf); // set message title strcpy(buf, "** void **"); // overwrite buffer to be sure } // buf goes out of scope here // pop up a message: stop |= fl_choice( "Timeout. Click the 'Close' button or press Escape.\n" "Note: this message had been blocked in FLTK 1.3\n" "and earlier if another message window was open.\n" "This message should pop up every 5 seconds (max. 10 times)\n" "in FLTK 1.4 and later until stopped by clicking the button\n" "below or by pressing the Enter (Return) key.\n", "Close", "Stop these funny popups", NULL); } int main(int argc, char **argv) { char buffer[128] = "Test text"; char buffer2[128] = "MyPassword"; // This is a test to make sure automatic destructors work. Pop up // the question dialog several times and make sure it doesn't crash. Fl_Double_Window window(200, 105); Fl_Return_Button b(20, 10, 160, 35, buffer); b.callback(rename_button, (void *)(0)); Fl_Button b2(20, 50, 160, 35, buffer2); b2.callback(rename_button, (void *)(1)); window.end(); window.resizable(&b); window.show(argc, argv); // Also we test to see if the exit callback works: window.callback(window_callback); // Test: set default message window title: // fl_message_title_default("Default Message Title"); // Test: multiple (nested, aka "recursive") popups (see timer_cb()) Fl::add_timeout(5.0, timer_cb); return Fl::run(); } fltk-1.4.3/test/bitmap.cxx0000644000175000017500000000406015004135251015564 0ustar albrechtalbrecht// // Bitmap label test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include // include bitmap #include "pixmaps/sorceress.xbm" Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*overb,*inactb; Fl_Button *b; Fl_Double_Window *w; void button_cb(Fl_Widget *,void *) { int i = 0; if (leftb->value()) i |= FL_ALIGN_LEFT; if (rightb->value()) i |= FL_ALIGN_RIGHT; if (topb->value()) i |= FL_ALIGN_TOP; if (bottomb->value()) i |= FL_ALIGN_BOTTOM; if (insideb->value()) i |= FL_ALIGN_INSIDE; if (overb->value()) i |= FL_ALIGN_TEXT_OVER_IMAGE; b->align(i); if (inactb->value()) b->deactivate(); else b->activate(); w->redraw(); } int main(int argc, char **argv) { w = new Fl_Double_Window(400,400); b = new Fl_Button(140,160,120,120,"Bitmap"); b->image(new Fl_Bitmap(sorceress_bits,sorceress_width,sorceress_height)); leftb = new Fl_Toggle_Button(25,50,50,25,"left"); leftb->callback(button_cb); rightb = new Fl_Toggle_Button(75,50,50,25,"right"); rightb->callback(button_cb); topb = new Fl_Toggle_Button(125,50,50,25,"top"); topb->callback(button_cb); bottomb = new Fl_Toggle_Button(175,50,50,25,"bottom"); bottomb->callback(button_cb); insideb = new Fl_Toggle_Button(225,50,50,25,"inside"); insideb->callback(button_cb); overb = new Fl_Toggle_Button(25,75,100,25,"text over"); overb->callback(button_cb); inactb = new Fl_Toggle_Button(125,75,100,25,"inactive"); inactb->callback(button_cb); w->resizable(w); w->end(); w->show(argc, argv); return Fl::run(); } fltk-1.4.3/test/windowfocus.cxx0000644000175000017500000000266715004135251016672 0ustar albrechtalbrecht// // Cross-window show/focus test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2015 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include static Fl_Double_Window *win1, *win2; static Fl_Input *input1; static void popup(Fl_Widget *, void *) { win2->position(win1->x() + win1->w(), win1->y()); win2->show(); win2->wait_for_expose(); input1->take_focus(); } int main(int argc, char **argv) { win1 = new Fl_Double_Window(300, 200); win1->label("show() focus test"); Fl_Box *b = new Fl_Box(10, 10, 280, 130); b->label("Type something to pop the subwindow up. " "The focus should stay on the input, " "and you should be able to continue typing."); b->align(FL_ALIGN_WRAP | FL_ALIGN_LEFT | FL_ALIGN_INSIDE); input1 = new Fl_Input(10, 150, 150, 25); input1->when(FL_WHEN_CHANGED); input1->callback(popup); win1->end(); win2 = new Fl_Double_Window(300, 200); win2->label("window2"); win2->end(); win1->show(argc,argv); return Fl::run(); } fltk-1.4.3/test/resize-example5c.cxx0000644000175000017500000000630315004135251017474 0ustar albrechtalbrecht// // Resize example for use in the Fast Light Tool Kit (FLTK) documentation. // // See Article #415: How does resizing work? // https://www.fltk.org/articles.php?L415 // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "resize-arrows.h" #include // window, simplex and arrow dimensions int TLx = 35, TRx = 320, TLw = 260, Ww = 620; int TLy = 35, LGy = 100, TLh = 65, LGh = 70, LAh = 35, Wh = 175; Fl_Double_Window *window = 0; class Simplex : public Fl_Group { public: Simplex(int X, int Y, int W, int H, const char *T = 0); Fl_Box *m_boxA, *m_boxB, *m_boxC, *m_boxI; Fl_Group *m_group, *m_groupL, *m_groupR; }; Simplex::Simplex(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->box(FL_UP_BOX); m_group = new Fl_Group(X + 10, Y + 10, 240, 45); m_group->box(FL_UP_BOX); m_groupL = new Fl_Group(X + 10, Y + 15, 145, 35); m_groupL->box(FL_NO_BOX); m_boxA = new Fl_Box(X + 20, Y + 20, 80, 25, "A"); m_boxA->box(FL_UP_BOX); m_boxB = new Fl_Box(X + 110, Y + 20, 40, 25, "B"); m_boxB->box(FL_UP_BOX); m_groupL->resizable(m_boxA); m_groupL->end(); m_groupR = new Fl_Group(X + 155, Y + 15, 95, 35); m_groupR->box(FL_NO_BOX); m_boxC = new Fl_Box(X + 160, Y + 20, 80, 25, "C"); m_boxC->box(FL_UP_BOX); m_groupR->resizable(m_boxC); m_groupR->end(); int d = 20; m_boxI = new Fl_Box(X + 155 - d, Y + 40, 2 * d, 5); m_boxI->box(FL_FLAT_BOX); m_boxI->color(FL_YELLOW); m_group->resizable(m_boxI); m_group->end(); this->resizable(m_group); this->end(); } class Resizables : public Fl_Group { public: Resizables(int X, int Y, int W, int H, const char *T = 0); Simplex *TL, *TR; // top left, top right Harrow *LA, *RA; // left arrow, right arrow }; Resizables::Resizables(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { TL = new Simplex(X + TLx, Y + TLy, TLw, TLh, "Original"); TL->align(FL_ALIGN_TOP_LEFT); TR = new Simplex(X + TRx, Y + TLy, TLw, TLh, "Horizontally Resized"); TR->align(FL_ALIGN_TOP_LEFT); Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); LG->box(FL_NO_BOX); LG->color(FL_WHITE); LA = new Harrow(TL->m_boxI->x(), LG->y(), TL->m_boxI->w(), LAh, "Initial\nwidth"); LG->resizable(LA); LG->end(); Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); RG->box(FL_NO_BOX); RG->color(FL_WHITE); RA = new Harrow(TR->m_boxI->x(), RG->y(), TR->m_boxI->w(), LAh, "Resized\nwidth"); RG->resizable(RA); RG->end(); this->resizable(TR); this->end(); } int main(int argc, char **argv) { window = new Fl_Double_Window(Ww, Wh, "resize-example5c"); window->color(FL_WHITE); Resizables *resizables = new Resizables(0, 0, Ww, Wh); window->end(); window->resizable(resizables); window->size_range(Ww, Wh); window->show(argc, argv); window->size(Ww + 90, Wh); return Fl::run(); } fltk-1.4.3/test/handle_keys.cxx0000644000175000017500000003063415004135251016604 0ustar albrechtalbrecht// // Keyboard event test program for the Fast Light Tool Kit (FLTK). // // Copyright 2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include // free() // Global variables to simplify the code Fl_Check_Button *keydown = NULL; Fl_Check_Button *keyup = NULL; Fl_Check_Button *shortcut = NULL; Fl_Check_Button *scaling = NULL; // Text in the headline and after clearing the terminal buffer. For alignment ... // 1 2 3 4 5 6 7 8 // 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345 static const char *headline_text = "[nnn] Event Key Name, Flags: C A S M N L Text Unicode UTF-8/hex"; static const int lkn = 14; // length of key name field // Tooltip for headline and terminal widgets static const char *tt = "Flags:\n" "C=Ctrl, A=Alt, S=Shift, M=Meta\n" "N=NumLock, L=CapsLock"; // This table is a duplicate of the table in test/keyboard.cxx. // In the future this should be moved to the FLTK core so FLTK key // numbers can be translated to strings (key names) in user programs. struct keycode_table { int n; // key code const char* text; // key name } key_table[] = { { FL_Escape, "FL_Escape"}, { FL_BackSpace, "FL_BackSpace"}, { FL_Tab, "FL_Tab"}, { FL_Iso_Key, "FL_Iso_Key"}, { FL_Enter, "FL_Enter"}, { FL_Print, "FL_Print"}, { FL_Scroll_Lock, "FL_Scroll_Lock"}, { FL_Pause, "FL_Pause"}, { FL_Insert, "FL_Insert"}, { FL_Home, "FL_Home"}, { FL_Page_Up, "FL_Page_Up"}, { FL_Delete, "FL_Delete"}, { FL_End, "FL_End"}, { FL_Page_Down, "FL_Page_Down"}, { FL_Left, "FL_Left"}, { FL_Up, "FL_Up"}, { FL_Right, "FL_Right"}, { FL_Down, "FL_Down"}, { FL_Shift_L, "FL_Shift_L"}, { FL_Shift_R, "FL_Shift_R"}, { FL_Control_L, "FL_Control_L"}, { FL_Control_R, "FL_Control_R"}, { FL_Caps_Lock, "FL_Caps_Lock"}, { FL_Alt_L, "FL_Alt_L"}, { FL_Alt_R, "FL_Alt_R"}, { FL_Meta_L, "FL_Meta_L"}, { FL_Meta_R, "FL_Meta_R"}, { FL_Menu, "FL_Menu"}, { FL_Help, "FL_Help"}, { FL_Num_Lock, "FL_Num_Lock"}, { FL_KP_Enter, "FL_KP_Enter"}, { FL_Alt_Gr, "FL_Alt_Gr"} }; // This function is very similar to the code in test/keyboard.cxx. // In the future this should be moved to the FLTK core so FLTK key // numbers can be translated to strings (key names) in user programs. // Returns: // - function return is a pointer to the key name string // - parameter lg returns the length in characters (not bytes) // The latter can be used to align strings. // Todo: this function may not be complete yet and is // maybe not correct for all key values. const char *get_keyname(int k, int &lg) { static char buffer[32]; lg = 0; if (!k) { lg = 1; return "0"; } else if (k < 32) { // control character lg = sprintf(buffer, "^%c", (char)(k + 64)); } else if (k < 128) { // ASCII lg = snprintf(buffer, sizeof(buffer), "'%c'", k); } else if (k >= 0xa0 && k <= 0xff) { // ISO-8859-1 (international keyboards) char key[8]; int kl = fl_utf8encode((unsigned)k, key); key[kl] = '\0'; lg = snprintf(buffer, sizeof(buffer), "'%s'", key); } else if (k > FL_F && k <= FL_F_Last) { lg = snprintf(buffer, sizeof(buffer), "FL_F+%d", k - FL_F); } else if (k >= FL_KP && k <= FL_KP_Last) { if (k == FL_KP_Enter) lg = snprintf(buffer, sizeof(buffer), "FL_KP_Enter"); else lg = snprintf(buffer, sizeof(buffer), "FL_KP+'%c'", k-FL_KP); } else if (k >= FL_Button && k <= FL_Button+7) { lg = snprintf(buffer, sizeof(buffer), "FL_Button+%d", k-FL_Button); } else { lg = snprintf(buffer, sizeof(buffer), "0x%04x", k); for (int i = 0; i < int(sizeof(key_table)/sizeof(*key_table)); i++) { if (key_table[i].n == k) { lg = (int)strlen(key_table[i].text); return key_table[i].text; } } } return buffer; } class Terminal : public Fl_Terminal { public: int handle(int ev) FL_OVERRIDE { switch(ev) { case FL_KEYBOARD: case FL_KEYUP: case FL_SHORTCUT: return 0; } return Fl_Terminal::handle(ev); } Terminal(int X, int Y, int W, int H) : Fl_Terminal(X, Y, W, H) {} }; // Class to handle events class app : public Fl_Double_Window { protected: int handle(int) FL_OVERRIDE; public: // storage for the last event int eventnum; const char *eventname; Terminal *tty; Fl_Box *headline; app(int X, int Y, int W, int H, const char *L = 0) : Fl_Double_Window(X, Y, W, H, L) { eventname = NULL; eventnum = 0; headline = new Fl_Box(2, 0, W - 4, 25); headline->color(FL_LIGHT2); headline->box(FL_FLAT_BOX); headline->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); headline->labelfont(FL_COURIER); headline->labelsize(12); headline->label(headline_text); headline->tooltip(tt); tty = new Terminal(0, 25, W, H - 100); tty->color(FL_WHITE); tty->textfgcolor(fl_darker(FL_BLUE)); tty->selectionbgcolor(FL_BLUE); tty->selectionfgcolor(FL_WHITE); tty->textfont(FL_COURIER); tty->textsize(12); // tty->selection_color(FL_RED); tty->tooltip(tt); } int print_event(int ev); }; // print_event() counts and prints the current event. // Returns 1 if printed (used), 0 if suppressed. // The event counter is incremented only if the event is printed // and wraps at 1000. int app::print_event(int ev) { switch(ev) { case FL_KEYBOARD: if (!keydown->value()) return 0; tty->textfgcolor(FL_BLACK); break; case FL_KEYUP: if (!keyup->value()) return 0; tty->textfgcolor(FL_BLUE); break; case FL_SHORTCUT: if (!shortcut->value()) return 0; tty->textfgcolor(0x00aa0000); // dark green break; default: return 0; } eventnum++; eventnum %= 1000; eventname = fl_eventnames[ev]; tty->printf("[%3d] %-12s", eventnum, eventname); return 1; } // app::print_event() // Event handling int app::handle(int ev) { int res = Fl_Double_Window::handle(ev); // filter and output keyboard events only if (!print_event(ev)) return res; const char *etxt = Fl::event_text(); int ekey = Fl::event_key(); int elen = Fl::event_length(); char ctrl = (Fl::event_state() & FL_CTRL) ? 'C' : '.'; char alt = (Fl::event_state() & FL_ALT) ? 'A' : '.'; char shift = (Fl::event_state() & FL_SHIFT) ? 'S' : '.'; char meta = (Fl::event_state() & FL_META) ? 'M' : '.'; char numlk = (Fl::event_state() & FL_NUM_LOCK) ? 'N' : '.'; char capslk = (Fl::event_state() & FL_CAPS_LOCK) ? 'L' : '.'; int lg = 0; char ekns[12]; // event key (hex) as string sprintf(ekns, "0x%04x", ekey); // may be up to 10 chars tty->printf("%10s ", ekns); // event key number (hex) tty->printf("%s", get_keyname(ekey, lg)); if (lg < lkn) { for (int i = 0; i < lkn - lg; i++) { tty->append_ascii(" "); } } tty->printf("%c %c %c %c %c %c ", ctrl, alt, shift, meta, numlk, capslk); if (elen) { if (elen == 1 && etxt[0] < 32) { // control character (0-31) tty->printf("'^%c' ", (char)(etxt[0] + 64)); } else { tty->printf("'%s' ", etxt); } unsigned int ucs = fl_utf8decode(etxt, etxt + elen, NULL); tty->printf(" U+%04x ", ucs); for (int i = 0; i < Fl::event_length(); i++) { tty->printf(" %02x", Fl::event_text()[i]&0xff); } } else { tty->printf("'' "); } tty->textfgcolor(FL_BLACK); tty->printf("\n"); return res; } // app::handle() // Quit button callback: closes the window void quit_cb(Fl_Widget *w, void *) { w->window()->hide(); } // Clear button callback: clears the terminal widget void clear_cb(Fl_Button *b, void *) { Terminal *tty = ((app *)b->window())->tty; tty->clear_screen_home(); tty->clear_history(); tty->printf("%s\n", headline_text); // helpful if copied to the clipboard tty->redraw(); tty->take_focus(); } // Copy button callback: copies the selected text to the clipboard void copy_cb(Fl_Widget *b, void *) { Terminal *tty = ((app *)b->window())->tty; const char *what = "Full"; const char *text; int tlen = tty->selection_text_len(); if (tlen > 0) { text = tty->selection_text(); what = "Selected"; } else { text = tty->text(); } tlen = (int)strlen(text); Fl::copy(text, tlen, 1, Fl::clipboard_plain_text); tty->printf("[%s text copied to clipboard, length = %d]\n", what, tlen); free((void *)text); tty->take_focus(); } // Callback for all (light) buttons void toggle_cb(Fl_Widget *w, void *) { Terminal *tty = ((app *)w->window())->tty; tty->take_focus(); } // Toggle recognition of GUI scaling shortcuts void toggle_scaling(Fl_Widget *w, void *v) { int toggle = ((Fl_Button*)w)->value() ? 1 : 0; Fl::keyboard_screen_scaling(toggle); if (toggle) { Terminal *tty = ((app *)w->window())->tty; int simple_zoom = Fl::option(Fl::OPTION_SIMPLE_ZOOM_SHORTCUT); tty->printf("GUI-Scaling = %s, OPTION_SIMPLE_ZOOM_SHORTCUT = %s\n", toggle ? "ON" : "OFF", simple_zoom ? "ON" : "OFF"); } toggle_cb(w, v); // give focus to 'app' } // Window close callback (Esc does not close the window) void close_cb(Fl_Widget *win, void *) { if (Fl::event() == FL_SHORTCUT) return; win->hide(); } // Main program int main(int argc, char **argv) { #ifdef _WIN32 // Set an appropriate font for Wine on Linux (test only). // This is very likely not necessary on a real Windows system. // Set environment variable FLTK_USING_WINE to a non-empty string // to enable this feature, e.g. (in bash) `export FLTK_USING_WINE=1`. const char *using_wine = fl_getenv("FLTK_USING_WINE"); printf("FLTK_USING_WINE = %s\n", using_wine ? using_wine : ""); if (using_wine && *using_wine) { // Fl::set_font(FL_COURIER, " DejaVu Sans Mono"); // DejaVu Mono Fl::set_font(FL_COURIER, " Liberation Mono"); // Liberation Mono } #endif const int WW = 700, WH = 400; app *win = new app(0, 0, WW, WH); win->tty->box(FL_DOWN_BOX); win->tty->show_unknown(true); win->tty->textfgcolor(FL_BLACK); win->tty->printf("Please press any key ...\n"); Fl_Grid *grid = new Fl_Grid(0, WH - 75, WW, 75); grid->layout(2, 5, 5, 5); keydown = new Fl_Check_Button(0, 0, 80, 30, "Keydown"); grid->widget(keydown, 0, 0); keydown->value(1); keydown->callback(toggle_cb); keydown->tooltip("Show FL_KEYDOWN aka FL_KEYBOARD events"); keyup = new Fl_Check_Button(0, 0, 80, 30, "Keyup"); grid->widget(keyup, 0, 1); keyup->value(0); keyup->callback(toggle_cb); keyup->tooltip("Show FL_KEYUP events"); shortcut = new Fl_Check_Button(0, 0, 80, 30, "Shortcut"); grid->widget(shortcut, 0, 2); shortcut->value(0); shortcut->callback(toggle_cb); shortcut->tooltip("Show FL_SHORTCUT events"); scaling = new Fl_Check_Button(0, 0, 80, 30, "GUI scaling"); grid->widget(scaling, 0, 3); scaling->value(0); scaling->callback(toggle_scaling); scaling->tooltip("Use GUI scaling shortcuts"); toggle_scaling(scaling, 0); Fl_Button *clear = new Fl_Button(0, 0, 80, 30, "Clear"); grid->widget(clear, 1, 0); clear->callback((Fl_Callback *)clear_cb); clear->tooltip("Clear the display"); Fl_Button *copy = new Fl_Button(0, 0, 80, 30, "Copy"); grid->widget(copy, 1, 1); copy->callback(copy_cb); copy->tooltip("Copy terminal contents to clipboard"); Fl_Button *quit = new Fl_Button(WW - 70, WH - 50, 80, 30, "Quit"); grid->widget(quit, 1, 4); quit->box(FL_THIN_UP_BOX); quit->callback((Fl_Callback *)quit_cb); quit->tooltip("Exit the program"); grid->end(); win->end(); win->callback(close_cb); win->resizable(win->tty); win->size_range(660, 300); win->show(argc, argv); return Fl::run(); } fltk-1.4.3/test/animated.cxx0000644000175000017500000000730115004135251016073 0ustar albrechtalbrecht// // Alpha rendering benchmark program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include // These constants define the image dimensions and // the number of frames of the animation const unsigned int dim = 256; const unsigned int frames = 48; static Fl_RGB_Image *img[frames]; static uchar curframe; static void make_images() { unsigned i; for (i = 0; i < frames; i++) { const unsigned size = dim * dim * 4; uchar *data = new uchar[size]; memset(data, 0, size); // First a black box, 10x10 pixels in the top-left corner int x, y; for (x = 0; x < 10; x++) { for (y = 0; y < 10; y++) { data[y * dim * 4 + x * 4 + 3] = 255; } } // A fading sphere uchar alpha = 255; if (i < frames / 2) alpha = uchar(255 * (i / ((float) frames / 2))); else alpha = uchar(255 * (((frames / 2) - (i - frames / 2)) / ((float) frames / 2))); const int spherew = 60; const int spherex = (dim - spherew) / 2; const int maxdist = (spherew / 2) * (spherew / 2); for (x = spherex; x < spherex + spherew; x++) { for (y = 20; y < 20 + spherew; y++) { float distx = x - (spherex + (float) spherew / 2); float disty = y - (20 + (float) spherew / 2); float dist = distx * distx + disty * disty; if (dist > maxdist) continue; const float fill = dist / maxdist; const uchar grey = uchar(fill * 255); uchar myalpha = alpha; if (fill > 0.9) myalpha *= uchar((1.0f - fill) * 10); data[y * dim * 4 + x * 4 + 0] = grey; data[y * dim * 4 + x * 4 + 1] = grey; data[y * dim * 4 + x * 4 + 2] = grey; data[y * dim * 4 + x * 4 + 3] = myalpha; } } // A moving blob const float pos = (i / (float) frames) * 2 - 0.5f; const int xoffset = int(pos * dim); const int yoffset = 2 * dim / 3; const int w = dim / 4; for (x = -w; x < w; x++) { if (x + xoffset < 0 || x + xoffset >= (int)dim) continue; for (y = yoffset - w; y < yoffset + w; y++) { const uchar grey = abs(y - yoffset); data[y * dim * 4 + (x + xoffset) * 4 + 2] = grey; data[y * dim * 4 + (x + xoffset) * 4 + 3] = 127; } } img[i] = new Fl_RGB_Image(data, dim, dim, 4); } } class window: public Fl_Double_Window { public: window(int X, int Y, const char *lbl): Fl_Double_Window(X, Y, lbl) {} void draw() FL_OVERRIDE { Fl_Double_Window::draw(); // Test both cx/cy offset and clipping. Both borders should have a 5-pixel edge, // and the upper-left black box should not be visible. fl_push_clip(5, 5, w() - 5, h() - 5); img[curframe]->draw(0, 0, dim, dim, 5, 5); fl_pop_clip(); } }; static window *win; static void cb(void *) { win->redraw(); Fl::repeat_timeout(1.0f / 24, cb); curframe++; curframe %= frames; } int main(int argc, char **argv) { win = new window(256, 256, "Alpha rendering benchmark, watch CPU use"); win->color(fl_rgb_color(142, 0, 0)); make_images(); win->end(); win->show(argc, argv); Fl::add_timeout(1.0f / 24, cb); return Fl::run(); } fltk-1.4.3/test/unittest_core.cxx0000644000175000017500000003060515004135251017203 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include #include #include #include "../src/Fl_String.H" #include #include #include #include /* Test Fl_String constructor and assignment. */ TEST(Fl_String, Assignment) { Fl_String null; EXPECT_STREQ(null.c_str(), ""); // default initialisation is an empty string EXPECT_TRUE(null.empty()); Fl_String null2(NULL); EXPECT_STREQ(null2.c_str(), ""); // initialise with a NULL pointer gets an empty string EXPECT_TRUE(null2.empty()); Fl_String empty(""); EXPECT_STREQ(empty.c_str(), ""); // also, empty CString make empty Fl_String EXPECT_TRUE(empty.empty()); Fl_String text("hello"); EXPECT_STREQ(text.c_str(), "hello"); // Load some text from a CString EXPECT_EQ(text.size(), 5); // did we get the size right? EXPECT_EQ(text.strlen(), 5); // do we have a trailing 0 EXPECT_GE(text.capacity(), 5); // do we have the capacity EXPECT_TRUE(!text.empty()); // test the empty() method Fl_String text2("abcdef", 3); EXPECT_STREQ(text2.c_str(), "abc"); EXPECT_EQ(text2.size(), 3); Fl_String text3("abc\0def", 7); EXPECT_EQ(text3.strlen(), 3); EXPECT_EQ(text3.size(), 7); Fl_String text4(text); EXPECT_STREQ(text4.c_str(), "hello"); Fl_String text5 = text; EXPECT_STREQ(text5.c_str(), "hello"); Fl_String text6 = "yoohoo"; EXPECT_STREQ(text6.c_str(), "yoohoo"); return true; } /* Test methods that access Fl_String content and parts of it. */ TEST(Fl_String, Access) { Fl_String hello = "hello"; EXPECT_STREQ(hello.c_str(), "hello"); EXPECT_STREQ(hello.data(), "hello"); EXPECT_EQ(hello[1], 'e'); EXPECT_EQ(hello[hello.size()], 0); EXPECT_EQ(hello.at(1), 'e'); EXPECT_EQ(hello.at(-1), 0); EXPECT_EQ(hello.at(11), 0); hello[1] = 'a'; EXPECT_STREQ(hello.c_str(), "hallo"); hello.data()[1] = 'e'; EXPECT_STREQ(hello.c_str(), "hello"); return true; } /* Test the Fl_String capacity management. */ TEST(Fl_String, Capacity) { Fl_String hello; EXPECT_EQ(hello.capacity(), 0); hello = "hi"; EXPECT_STREQ(hello.c_str(), "hi"); EXPECT_GE(hello.capacity(), 2); hello = "the quick brown fox jumps over the lazy dog"; EXPECT_STREQ(hello.c_str(), "the quick brown fox jumps over the lazy dog"); EXPECT_GE(hello.capacity(), 41); int c = hello.capacity(); hello.reserve(c+100); EXPECT_STREQ(hello.c_str(), "the quick brown fox jumps over the lazy dog"); EXPECT_GE(hello.capacity(), 141); hello = "hi"; hello.shrink_to_fit(); EXPECT_EQ(hello.capacity(), 2); return true; } /* Test all methods that operate on Fl_String. */ TEST(Fl_String, Operations) { Fl_String empty; Fl_String hello = "Hello", world = "World"; hello.resize(4); EXPECT_STREQ(hello.c_str(), "Hell"); hello.clear(); EXPECT_TRUE(hello.empty()); hello = "Hello"; hello.insert(3, "-"); EXPECT_STREQ(hello.c_str(), "Hel-lo"); hello = "Hello"; hello.erase(2, 2); EXPECT_STREQ(hello.c_str(), "Heo"); hello = "Hello"; hello.push_back('!'); EXPECT_STREQ(hello.c_str(), "Hello!"); hello.pop_back(); EXPECT_STREQ(hello.c_str(), "Hello"); hello.append(world); EXPECT_STREQ(hello.c_str(), "HelloWorld"); hello.append("!"); EXPECT_STREQ(hello.c_str(), "HelloWorld!"); hello = "Hello"; hello += world; EXPECT_STREQ(hello.c_str(), "HelloWorld"); hello += "!"; EXPECT_STREQ(hello.c_str(), "HelloWorld!"); hello += '?'; EXPECT_STREQ(hello.c_str(), "HelloWorld!?"); hello = "Hello"; hello.replace(0, 0, "Say ", 4); EXPECT_STREQ(hello.c_str(), "Say Hello"); hello.replace(0, 4, ""); EXPECT_STREQ(hello.c_str(), "Hello"); hello.replace(2, 2, "bb"); EXPECT_STREQ(hello.c_str(), "Hebbo"); hello.replace(2, 2, "xxx"); EXPECT_STREQ(hello.c_str(), "Hexxxo"); hello.replace(2, 3, "ll"); EXPECT_STREQ(hello.c_str(), "Hello"); hello.replace(2, 0, NULL, 0); EXPECT_STREQ(hello.c_str(), "Hello"); hello.replace(Fl_String::npos, Fl_String::npos, world); EXPECT_STREQ(hello.c_str(), "HelloWorld"); hello = "Hello"; Fl_String sub = hello.substr(); EXPECT_STREQ(sub.c_str(), "Hello"); // check correct usage sub = hello.substr(2); EXPECT_STREQ(sub.c_str(), "llo"); sub = hello.substr(2, 2); EXPECT_STREQ(sub.c_str(), "ll"); sub = hello.substr(-1, 2); EXPECT_TRUE(sub.empty()); // check faulty values sub = hello.substr(20, 2); EXPECT_TRUE(sub.empty()); sub = empty.substr(0, 2); EXPECT_TRUE(sub.empty()); return true; } #if (0) // FIXME - Fl_String /* Test all Fl_String functions that are no part of the class. */ TEST(Fl_String, Non-Member Functions) { Fl_String a = "a", b = "b", empty = "", result; result = a + b; EXPECT_STREQ(result.c_str(), "ab"); result = a + empty; EXPECT_STREQ(result.c_str(), "a"); result = a + "c"; EXPECT_STREQ(result.c_str(), "ac"); result = empty + "x"; EXPECT_STREQ(result.c_str(), "x"); EXPECT_TRUE(!(a == b)); EXPECT_TRUE(a == a); EXPECT_FALSE((a != a)); // neq -erco EXPECT_TRUE((a != b)); // neq -erco EXPECT_TRUE(empty == empty); EXPECT_TRUE(a+b == "ab"); EXPECT_TRUE(a+"b" == "a" + b); return true; } /* Test additions to Fl_Preferences. */ TEST(Fl_String, fl_filename_...) { const Fl_String ref = "/test/me.txt"; Fl_String name = fl_filename_name(ref); EXPECT_STREQ(name.c_str(), "me.txt"); name = fl_filename_name(Fl_String("/test/")); EXPECT_STREQ(name.c_str(), ""); Fl_String path = fl_filename_path(ref); EXPECT_STREQ(path.c_str(), "/test/"); Fl_String ext = fl_filename_ext(ref); EXPECT_STREQ(ext.c_str(), ".txt"); ext = fl_filename_setext(ref, ".rtf"); EXPECT_STREQ(ext.c_str(), "/test/me.rtf"); fl_putenv("FL_UNITTEST=unit/test"); name = fl_filename_expand(Fl_String("abc/$FL_UNITTEST/xyz")); EXPECT_STREQ(name.c_str(), "abc/unit/test/xyz"); Fl_String abs = fl_filename_absolute(Fl_String("./abc/def.txt")); Fl_String rel = fl_filename_relative(abs); EXPECT_STREQ(rel.c_str(), "abc/def.txt"); EXPECT_STREQ(ref.c_str(), "/test/me.txt"); return true; } /* Test additions to Fl_Preferences. */ //TEST(Fl_Preferences, Strings) { // { // Fl_Preferences prefs(Fl_Preferences::USER_L, "fltk.org", "unittests"); // prefs.set("a", Fl_String()); // prefs.set("b", Fl_String("Hello")); // prefs.set("c", Fl_String("Hel\\l\nö")); // } // { // Fl_Preferences prefs(Fl_Preferences::USER_L, "fltk.org", "unittests"); // Fl_String r; // prefs.get("a", r, "x"); // EXPECT_STREQ(r.c_str(), ""); // prefs.get("b", r, "x"); // EXPECT_STREQ(r.c_str(), "Hello"); // prefs.get("c", r, "x"); // EXPECT_STREQ(r.c_str(), "Hel\\l\nö"); // prefs.get("d", r, "x"); // EXPECT_STREQ(r.c_str(), "x"); // } // return true; //} TEST(fl_filename, ext) { Fl_String r = fl_filename_ext("test.txt"); EXPECT_STREQ(r.c_str(), ".txt"); r = fl_filename_ext("test"); EXPECT_STREQ(r.c_str(), ""); r = fl_filename_ext(""); EXPECT_STREQ(r.c_str(), ""); return true; } TEST(fl_filename, setext) { Fl_String r = fl_filename_setext(Fl_String("test.txt"), ".rtf"); EXPECT_STREQ(r.c_str(), "test.rtf"); r = fl_filename_setext(Fl_String("test"), ".rtf"); EXPECT_STREQ(r.c_str(), "test.rtf"); r = fl_filename_setext(Fl_String("test.txt"), ""); EXPECT_STREQ(r.c_str(), "test"); r = fl_filename_setext(Fl_String(""), ".rtf"); EXPECT_STREQ(r.c_str(), ".rtf"); r = fl_filename_setext(Fl_String("path/test"), ".rtf"); EXPECT_STREQ(r.c_str(), "path/test.rtf"); return true; } TEST(fl_filename, relative) { Fl_String base = "/var/tmp/somedir"; Fl_String r = fl_filename_relative("/var/tmp/somedir/foo.txt", base); EXPECT_STREQ(r.c_str(), "foo.txt"); r = fl_filename_relative("/var/tmp/foo.txt", base); EXPECT_STREQ(r.c_str(), "../foo.txt"); r = fl_filename_relative("./foo.txt", base); EXPECT_STREQ(r.c_str(), "./foo.txt"); r = fl_filename_relative("../foo.txt", base); EXPECT_STREQ(r.c_str(), "../foo.txt"); return true; } TEST(fl_filename, absolute) { Fl_String base = "/var/tmp/somedir"; Fl_String r = fl_filename_absolute("foo.txt", base); EXPECT_STREQ(r.c_str(), "/var/tmp/somedir/foo.txt"); r = fl_filename_absolute("/var/tmp/foo.txt", base); EXPECT_STREQ(r.c_str(), "/var/tmp/foo.txt"); r = fl_filename_absolute("./foo.txt", base); EXPECT_STREQ(r.c_str(), "/var/tmp/somedir/foo.txt"); r = fl_filename_absolute("../foo.txt", base); EXPECT_STREQ(r.c_str(), "/var/tmp/foo.txt"); return true; } bool cb1a_ok = false, cb1b_ok = false, cb1c_ok = false; int cb1_alloc = 0; class MyString : public Fl_String { public: MyString() : Fl_String() { cb1_alloc++; } MyString(const MyString &str) : Fl_String(str) { cb1_alloc++; } MyString(const char *t) : Fl_String(t) { cb1_alloc++; } ~MyString() { cb1_alloc--; } }; void cb1(MyString a, int b) { cb1a_ok = true; if (strcmp(a.c_str(),"FLTK")==0) cb1b_ok = true; if (b==4) cb1c_ok = true; } /* Test callback macros. */ TEST(Fl_Callback_Macros, FL_FUNCTION_CALLBACK) { Fl_Group::current(NULL); Fl_Button *btn = new Fl_Button(10, 10, 100, 100); FL_FUNCTION_CALLBACK_2(btn, cb1, MyString, "FLTK", int, 4); do { class Fl_Callback_User_Data_240 : public Fl_Callback_User_Data { public: MyString a_; int b_; static void cb(Fl_Widget *w, void *user_data) { Fl_Callback_User_Data_240 *cbdata = (Fl_Callback_User_Data_240*)user_data; (void)cbdata; cb1(cbdata->a_, cbdata->b_); }; Fl_Callback_User_Data_240(MyString a, int b) : a_(a), b_(b) { } }; btn->callback(Fl_Callback_User_Data_240::cb, new Fl_Callback_User_Data_240("FLTK", 4), true); } while(0); btn->do_callback(); delete btn; EXPECT_TRUE(cb1a_ok); // callback called EXPECT_TRUE(cb1b_ok); // string stored correctly EXPECT_TRUE(cb1c_ok); // integer stored correctly EXPECT_TRUE(cb1_alloc==0); // string destroyed correctly (allocated as often as deallocated) return true; } TEST(Fl_Callback_Macros, FL_METHOD_CALLBACK) { Fl_Group::current(NULL); Fl_String *str = new Fl_String("FLTK"); Fl_Button *btn = new Fl_Button(10, 10, 100, 100); FL_METHOD_CALLBACK_2(btn, Fl_String, str, insert, int, 2, const char*, "XX"); btn->do_callback(); EXPECT_STREQ(str->c_str(), "FLXXTK"); delete btn; delete str; return true; } int cb3a = 0, cb3b = 0; TEST(Fl_Callback_Macros, FL_INLINE_CALLBACK) { Fl_Group::current(NULL); Fl_Button *btn = new Fl_Button(10, 10, 100, 100); FL_INLINE_CALLBACK_2(btn, int, a, 42, int, b, 16, { cb3a = a; cb3b = b; } ); btn->do_callback(); EXPECT_EQ(cb3a, 42); EXPECT_EQ(cb3b, 16); delete btn; return true; } #endif // FIXME - Fl_String // //------- test aspects of the FLTK core library ---------- // /* Create a tab with only a terminal window in it. When shown for the first time, unittest will visualize progress by runing all regsitered tests one-by-one every few miliseconds. When run in command line mode (option `--core`), all tests are executed at full speed. */ class Ut_Core_Test : public Fl_Group { Fl_Terminal *tty; bool suite_ran_; public: // Create the tab static Fl_Widget *create() { return new Ut_Core_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } // Constructor for this tab Ut_Core_Test(int x, int y, int w, int h) : Fl_Group(x, y, w, h), tty(NULL), suite_ran_(false) { tty = new Fl_Terminal(x+4, y+4, w-8, h-8, "Unittest Log"); tty->ansi(true); end(); Ut_Suite::tty = tty; } // Run one single test and repeat calling this until all tests are done static void timer_cb(void*) { // Run a test every few milliseconds to visualize the progress if (Ut_Suite::run_next_test()) Fl::repeat_timeout(0.15, timer_cb); } // Showing this tab for the first time will trigger the tests void show() FL_OVERRIDE { Fl_Group::show(); if (!suite_ran_) { Fl::add_timeout(0.5, timer_cb); suite_ran_ = true; } } }; // Register this tab with the unittest app. UnitTest core(UT_TEST_CORE, "Core Functionality", Ut_Core_Test::create); fltk-1.4.3/test/resize-example3b.cxx0000644000175000017500000000722715004135251017477 0ustar albrechtalbrecht// // Resize example for use in the Fast Light Tool Kit (FLTK) documentation. // // See Article #415: How does resizing work? // https://www.fltk.org/articles.php?L415 // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "resize-arrows.h" #include #include // resize dialog and arrow dimensions int TLx = 35, TRx = 270, TGx = 470, TLw = 200, TGw = 120, TAw = 35; int TLy = 35, BLy = 160, LGy = 250, TLh = 90, LGh = 90, LAh = 35; // window dimensions int Ww = 590, Wh = 340; Fl_Double_Window *window; class ResizeDialog : public Fl_Group { public: ResizeDialog(int X, int Y, int W, int H, const char *T = 0); Fl_Box *m_icon; Fl_Box *m_message; Fl_Button *m_button; }; ResizeDialog::ResizeDialog(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->align(FL_ALIGN_TOP_LEFT); this->box(FL_UP_BOX); m_icon = new Fl_Box(X + 10, Y + 10, 30, 30, "!"); m_icon->box(FL_DOWN_BOX); m_message = new Fl_Box(X + 50, Y + 10, 140, 30, "Out of Memory"); m_message->box(FL_DOWN_BOX); m_message->color(FL_YELLOW); m_button = new Fl_Button(X + 140, Y + 50, 50, 30, "Darn!"); this->end(); this->resizable(m_message); } class Resizables : public Fl_Group { public: Resizables(int X, int Y, int W, int H, const char *T = 0); ResizeDialog *TL, *TR, *BL, *BR; // topleft, topright, bottomleft, bottomright Harrow *LA, *RA; // left arrow, right arrow Varrow *TA, *BA; // top arrow, bottom arrow }; Resizables::Resizables(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->box(FL_UP_BOX); this->color(FL_WHITE); TL = new ResizeDialog(X + TLx, Y + TLy, TLw, TLh, "Original Size"); TL->resizable(0); TR = new ResizeDialog(X + TRx, Y + TLy, TLw, TLh, "Horizontally Resized"); BL = new ResizeDialog(X + TLx, Y + BLy, TLw, TLh, "Vertically Resized"); BR = new ResizeDialog(X + TRx, Y + BLy, TLw, TLh, "Horizontally and Vertically Resized"); Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); LG->box(FL_NO_BOX); LG->color(FL_WHITE); LA = new Harrow(BL->m_message->x(), LG->y(), BL->m_message->w(), LAh, "Initial\nwidth"); LG->resizable(LA); LG->end(); Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); RG->box(FL_NO_BOX); RG->color(FL_WHITE); RA = new Harrow(BR->m_message->x(), LG->y(), BL->m_message->w(), LAh, "Resized\nwidth"); RG->resizable(RA); RG->end(); Fl_Group *TG = new Fl_Group(X + TGx, Y + TLy, TGw, TLh); TG->box(FL_NO_BOX); TG->color(FL_WHITE); TA = new Varrow(TG->x(), TR->m_message->y(), TAw, TR->m_message->h(), "Initial\nheight"); TG->resizable(TA); TG->end(); Fl_Group *BG = new Fl_Group(X + TGx, Y + BLy, TGw, TLh); BG->box(FL_NO_BOX); BG->color(FL_WHITE); BA = new Varrow(BG->x(), BR->m_message->y(), TAw, BR->m_message->h(), "Resized\nheight"); BG->resizable(BA); BG->end(); this->resizable(BR); this->end(); } int main(int argc, char **argv) { window = new Fl_Double_Window(Ww, Wh, "resize-example3b"); window->color(FL_WHITE); Resizables *resizables = new Resizables(0, 0, Ww, Wh); window->end(); window->resizable(resizables); window->size_range(Ww, Wh); window->show(argc, argv); window->size(Ww + 50, Wh + 35); Fl::visible_focus(0); // suppress focus box return Fl::run(); } fltk-1.4.3/test/rgb.txt0000644000175000017500000006155015004135251015106 0ustar albrechtalbrecht! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $ 255 250 250 snow 248 248 255 ghost white 248 248 255 GhostWhite 245 245 245 white smoke 245 245 245 WhiteSmoke 220 220 220 gainsboro 255 250 240 floral white 255 250 240 FloralWhite 253 245 230 old lace 253 245 230 OldLace 250 240 230 linen 250 235 215 antique white 250 235 215 AntiqueWhite 255 239 213 papaya whip 255 239 213 PapayaWhip 255 235 205 blanched almond 255 235 205 BlanchedAlmond 255 228 196 bisque 255 218 185 peach puff 255 218 185 PeachPuff 255 222 173 navajo white 255 222 173 NavajoWhite 255 228 181 moccasin 255 248 220 cornsilk 255 255 240 ivory 255 250 205 lemon chiffon 255 250 205 LemonChiffon 255 245 238 seashell 240 255 240 honeydew 245 255 250 mint cream 245 255 250 MintCream 240 255 255 azure 240 248 255 alice blue 240 248 255 AliceBlue 230 230 250 lavender 255 240 245 lavender blush 255 240 245 LavenderBlush 255 228 225 misty rose 255 228 225 MistyRose 255 255 255 white 0 0 0 black 47 79 79 dark slate gray 47 79 79 DarkSlateGray 47 79 79 dark slate grey 47 79 79 DarkSlateGrey 105 105 105 dim gray 105 105 105 DimGray 105 105 105 dim grey 105 105 105 DimGrey 112 128 144 slate gray 112 128 144 SlateGray 112 128 144 slate grey 112 128 144 SlateGrey 119 136 153 light slate gray 119 136 153 LightSlateGray 119 136 153 light slate grey 119 136 153 LightSlateGrey 190 190 190 gray 190 190 190 grey 211 211 211 light grey 211 211 211 LightGrey 211 211 211 light gray 211 211 211 LightGray 25 25 112 midnight blue 25 25 112 MidnightBlue 0 0 128 navy 0 0 128 navy blue 0 0 128 NavyBlue 100 149 237 cornflower blue 100 149 237 CornflowerBlue 72 61 139 dark slate blue 72 61 139 DarkSlateBlue 106 90 205 slate blue 106 90 205 SlateBlue 123 104 238 medium slate blue 123 104 238 MediumSlateBlue 132 112 255 light slate blue 132 112 255 LightSlateBlue 0 0 205 medium blue 0 0 205 MediumBlue 65 105 225 royal blue 65 105 225 RoyalBlue 0 0 255 blue 30 144 255 dodger blue 30 144 255 DodgerBlue 0 191 255 deep sky blue 0 191 255 DeepSkyBlue 135 206 235 sky blue 135 206 235 SkyBlue 135 206 250 light sky blue 135 206 250 LightSkyBlue 70 130 180 steel blue 70 130 180 SteelBlue 176 196 222 light steel blue 176 196 222 LightSteelBlue 173 216 230 light blue 173 216 230 LightBlue 176 224 230 powder blue 176 224 230 PowderBlue 175 238 238 pale turquoise 175 238 238 PaleTurquoise 0 206 209 dark turquoise 0 206 209 DarkTurquoise 72 209 204 medium turquoise 72 209 204 MediumTurquoise 64 224 208 turquoise 0 255 255 cyan 224 255 255 light cyan 224 255 255 LightCyan 95 158 160 cadet blue 95 158 160 CadetBlue 102 205 170 medium aquamarine 102 205 170 MediumAquamarine 127 255 212 aquamarine 0 100 0 dark green 0 100 0 DarkGreen 85 107 47 dark olive green 85 107 47 DarkOliveGreen 143 188 143 dark sea green 143 188 143 DarkSeaGreen 46 139 87 sea green 46 139 87 SeaGreen 60 179 113 medium sea green 60 179 113 MediumSeaGreen 32 178 170 light sea green 32 178 170 LightSeaGreen 152 251 152 pale green 152 251 152 PaleGreen 0 255 127 spring green 0 255 127 SpringGreen 124 252 0 lawn green 124 252 0 LawnGreen 0 255 0 green 127 255 0 chartreuse 0 250 154 medium spring green 0 250 154 MediumSpringGreen 173 255 47 green yellow 173 255 47 GreenYellow 50 205 50 lime green 50 205 50 LimeGreen 154 205 50 yellow green 154 205 50 YellowGreen 34 139 34 forest green 34 139 34 ForestGreen 107 142 35 olive drab 107 142 35 OliveDrab 189 183 107 dark khaki 189 183 107 DarkKhaki 240 230 140 khaki 238 232 170 pale goldenrod 238 232 170 PaleGoldenrod 250 250 210 light goldenrod yellow 250 250 210 LightGoldenrodYellow 255 255 224 light yellow 255 255 224 LightYellow 255 255 0 yellow 255 215 0 gold 238 221 130 light goldenrod 238 221 130 LightGoldenrod 218 165 32 goldenrod 184 134 11 dark goldenrod 184 134 11 DarkGoldenrod 188 143 143 rosy brown 188 143 143 RosyBrown 205 92 92 indian red 205 92 92 IndianRed 139 69 19 saddle brown 139 69 19 SaddleBrown 160 82 45 sienna 205 133 63 peru 222 184 135 burlywood 245 245 220 beige 245 222 179 wheat 244 164 96 sandy brown 244 164 96 SandyBrown 210 180 140 tan 210 105 30 chocolate 178 34 34 firebrick 165 42 42 brown 233 150 122 dark salmon 233 150 122 DarkSalmon 250 128 114 salmon 255 160 122 light salmon 255 160 122 LightSalmon 255 165 0 orange 255 140 0 dark orange 255 140 0 DarkOrange 255 127 80 coral 240 128 128 light coral 240 128 128 LightCoral 255 99 71 tomato 255 69 0 orange red 255 69 0 OrangeRed 255 0 0 red 255 105 180 hot pink 255 105 180 HotPink 255 20 147 deep pink 255 20 147 DeepPink 255 192 203 pink 255 182 193 light pink 255 182 193 LightPink 219 112 147 pale violet red 219 112 147 PaleVioletRed 176 48 96 maroon 199 21 133 medium violet red 199 21 133 MediumVioletRed 208 32 144 violet red 208 32 144 VioletRed 255 0 255 magenta 238 130 238 violet 221 160 221 plum 218 112 214 orchid 186 85 211 medium orchid 186 85 211 MediumOrchid 153 50 204 dark orchid 153 50 204 DarkOrchid 148 0 211 dark violet 148 0 211 DarkViolet 138 43 226 blue violet 138 43 226 BlueViolet 160 32 240 purple 147 112 219 medium purple 147 112 219 MediumPurple 216 191 216 thistle 255 250 250 snow1 238 233 233 snow2 205 201 201 snow3 139 137 137 snow4 255 245 238 seashell1 238 229 222 seashell2 205 197 191 seashell3 139 134 130 seashell4 255 239 219 AntiqueWhite1 238 223 204 AntiqueWhite2 205 192 176 AntiqueWhite3 139 131 120 AntiqueWhite4 255 228 196 bisque1 238 213 183 bisque2 205 183 158 bisque3 139 125 107 bisque4 255 218 185 PeachPuff1 238 203 173 PeachPuff2 205 175 149 PeachPuff3 139 119 101 PeachPuff4 255 222 173 NavajoWhite1 238 207 161 NavajoWhite2 205 179 139 NavajoWhite3 139 121 94 NavajoWhite4 255 250 205 LemonChiffon1 238 233 191 LemonChiffon2 205 201 165 LemonChiffon3 139 137 112 LemonChiffon4 255 248 220 cornsilk1 238 232 205 cornsilk2 205 200 177 cornsilk3 139 136 120 cornsilk4 255 255 240 ivory1 238 238 224 ivory2 205 205 193 ivory3 139 139 131 ivory4 240 255 240 honeydew1 224 238 224 honeydew2 193 205 193 honeydew3 131 139 131 honeydew4 255 240 245 LavenderBlush1 238 224 229 LavenderBlush2 205 193 197 LavenderBlush3 139 131 134 LavenderBlush4 255 228 225 MistyRose1 238 213 210 MistyRose2 205 183 181 MistyRose3 139 125 123 MistyRose4 240 255 255 azure1 224 238 238 azure2 193 205 205 azure3 131 139 139 azure4 131 111 255 SlateBlue1 122 103 238 SlateBlue2 105 89 205 SlateBlue3 71 60 139 SlateBlue4 72 118 255 RoyalBlue1 67 110 238 RoyalBlue2 58 95 205 RoyalBlue3 39 64 139 RoyalBlue4 0 0 255 blue1 0 0 238 blue2 0 0 205 blue3 0 0 139 blue4 30 144 255 DodgerBlue1 28 134 238 DodgerBlue2 24 116 205 DodgerBlue3 16 78 139 DodgerBlue4 99 184 255 SteelBlue1 92 172 238 SteelBlue2 79 148 205 SteelBlue3 54 100 139 SteelBlue4 0 191 255 DeepSkyBlue1 0 178 238 DeepSkyBlue2 0 154 205 DeepSkyBlue3 0 104 139 DeepSkyBlue4 135 206 255 SkyBlue1 126 192 238 SkyBlue2 108 166 205 SkyBlue3 74 112 139 SkyBlue4 176 226 255 LightSkyBlue1 164 211 238 LightSkyBlue2 141 182 205 LightSkyBlue3 96 123 139 LightSkyBlue4 198 226 255 SlateGray1 185 211 238 SlateGray2 159 182 205 SlateGray3 108 123 139 SlateGray4 202 225 255 LightSteelBlue1 188 210 238 LightSteelBlue2 162 181 205 LightSteelBlue3 110 123 139 LightSteelBlue4 191 239 255 LightBlue1 178 223 238 LightBlue2 154 192 205 LightBlue3 104 131 139 LightBlue4 224 255 255 LightCyan1 209 238 238 LightCyan2 180 205 205 LightCyan3 122 139 139 LightCyan4 187 255 255 PaleTurquoise1 174 238 238 PaleTurquoise2 150 205 205 PaleTurquoise3 102 139 139 PaleTurquoise4 152 245 255 CadetBlue1 142 229 238 CadetBlue2 122 197 205 CadetBlue3 83 134 139 CadetBlue4 0 245 255 turquoise1 0 229 238 turquoise2 0 197 205 turquoise3 0 134 139 turquoise4 0 255 255 cyan1 0 238 238 cyan2 0 205 205 cyan3 0 139 139 cyan4 151 255 255 DarkSlateGray1 141 238 238 DarkSlateGray2 121 205 205 DarkSlateGray3 82 139 139 DarkSlateGray4 127 255 212 aquamarine1 118 238 198 aquamarine2 102 205 170 aquamarine3 69 139 116 aquamarine4 193 255 193 DarkSeaGreen1 180 238 180 DarkSeaGreen2 155 205 155 DarkSeaGreen3 105 139 105 DarkSeaGreen4 84 255 159 SeaGreen1 78 238 148 SeaGreen2 67 205 128 SeaGreen3 46 139 87 SeaGreen4 154 255 154 PaleGreen1 144 238 144 PaleGreen2 124 205 124 PaleGreen3 84 139 84 PaleGreen4 0 255 127 SpringGreen1 0 238 118 SpringGreen2 0 205 102 SpringGreen3 0 139 69 SpringGreen4 0 255 0 green1 0 238 0 green2 0 205 0 green3 0 139 0 green4 127 255 0 chartreuse1 118 238 0 chartreuse2 102 205 0 chartreuse3 69 139 0 chartreuse4 192 255 62 OliveDrab1 179 238 58 OliveDrab2 154 205 50 OliveDrab3 105 139 34 OliveDrab4 202 255 112 DarkOliveGreen1 188 238 104 DarkOliveGreen2 162 205 90 DarkOliveGreen3 110 139 61 DarkOliveGreen4 255 246 143 khaki1 238 230 133 khaki2 205 198 115 khaki3 139 134 78 khaki4 255 236 139 LightGoldenrod1 238 220 130 LightGoldenrod2 205 190 112 LightGoldenrod3 139 129 76 LightGoldenrod4 255 255 224 LightYellow1 238 238 209 LightYellow2 205 205 180 LightYellow3 139 139 122 LightYellow4 255 255 0 yellow1 238 238 0 yellow2 205 205 0 yellow3 139 139 0 yellow4 255 215 0 gold1 238 201 0 gold2 205 173 0 gold3 139 117 0 gold4 255 193 37 goldenrod1 238 180 34 goldenrod2 205 155 29 goldenrod3 139 105 20 goldenrod4 255 185 15 DarkGoldenrod1 238 173 14 DarkGoldenrod2 205 149 12 DarkGoldenrod3 139 101 8 DarkGoldenrod4 255 193 193 RosyBrown1 238 180 180 RosyBrown2 205 155 155 RosyBrown3 139 105 105 RosyBrown4 255 106 106 IndianRed1 238 99 99 IndianRed2 205 85 85 IndianRed3 139 58 58 IndianRed4 255 130 71 sienna1 238 121 66 sienna2 205 104 57 sienna3 139 71 38 sienna4 255 211 155 burlywood1 238 197 145 burlywood2 205 170 125 burlywood3 139 115 85 burlywood4 255 231 186 wheat1 238 216 174 wheat2 205 186 150 wheat3 139 126 102 wheat4 255 165 79 tan1 238 154 73 tan2 205 133 63 tan3 139 90 43 tan4 255 127 36 chocolate1 238 118 33 chocolate2 205 102 29 chocolate3 139 69 19 chocolate4 255 48 48 firebrick1 238 44 44 firebrick2 205 38 38 firebrick3 139 26 26 firebrick4 255 64 64 brown1 238 59 59 brown2 205 51 51 brown3 139 35 35 brown4 255 140 105 salmon1 238 130 98 salmon2 205 112 84 salmon3 139 76 57 salmon4 255 160 122 LightSalmon1 238 149 114 LightSalmon2 205 129 98 LightSalmon3 139 87 66 LightSalmon4 255 165 0 orange1 238 154 0 orange2 205 133 0 orange3 139 90 0 orange4 255 127 0 DarkOrange1 238 118 0 DarkOrange2 205 102 0 DarkOrange3 139 69 0 DarkOrange4 255 114 86 coral1 238 106 80 coral2 205 91 69 coral3 139 62 47 coral4 255 99 71 tomato1 238 92 66 tomato2 205 79 57 tomato3 139 54 38 tomato4 255 69 0 OrangeRed1 238 64 0 OrangeRed2 205 55 0 OrangeRed3 139 37 0 OrangeRed4 255 0 0 red1 238 0 0 red2 205 0 0 red3 139 0 0 red4 255 20 147 DeepPink1 238 18 137 DeepPink2 205 16 118 DeepPink3 139 10 80 DeepPink4 255 110 180 HotPink1 238 106 167 HotPink2 205 96 144 HotPink3 139 58 98 HotPink4 255 181 197 pink1 238 169 184 pink2 205 145 158 pink3 139 99 108 pink4 255 174 185 LightPink1 238 162 173 LightPink2 205 140 149 LightPink3 139 95 101 LightPink4 255 130 171 PaleVioletRed1 238 121 159 PaleVioletRed2 205 104 137 PaleVioletRed3 139 71 93 PaleVioletRed4 255 52 179 maroon1 238 48 167 maroon2 205 41 144 maroon3 139 28 98 maroon4 255 62 150 VioletRed1 238 58 140 VioletRed2 205 50 120 VioletRed3 139 34 82 VioletRed4 255 0 255 magenta1 238 0 238 magenta2 205 0 205 magenta3 139 0 139 magenta4 255 131 250 orchid1 238 122 233 orchid2 205 105 201 orchid3 139 71 137 orchid4 255 187 255 plum1 238 174 238 plum2 205 150 205 plum3 139 102 139 plum4 224 102 255 MediumOrchid1 209 95 238 MediumOrchid2 180 82 205 MediumOrchid3 122 55 139 MediumOrchid4 191 62 255 DarkOrchid1 178 58 238 DarkOrchid2 154 50 205 DarkOrchid3 104 34 139 DarkOrchid4 155 48 255 purple1 145 44 238 purple2 125 38 205 purple3 85 26 139 purple4 171 130 255 MediumPurple1 159 121 238 MediumPurple2 137 104 205 MediumPurple3 93 71 139 MediumPurple4 255 225 255 thistle1 238 210 238 thistle2 205 181 205 thistle3 139 123 139 thistle4 0 0 0 gray0 0 0 0 grey0 3 3 3 gray1 3 3 3 grey1 5 5 5 gray2 5 5 5 grey2 8 8 8 gray3 8 8 8 grey3 10 10 10 gray4 10 10 10 grey4 13 13 13 gray5 13 13 13 grey5 15 15 15 gray6 15 15 15 grey6 18 18 18 gray7 18 18 18 grey7 20 20 20 gray8 20 20 20 grey8 23 23 23 gray9 23 23 23 grey9 26 26 26 gray10 26 26 26 grey10 28 28 28 gray11 28 28 28 grey11 31 31 31 gray12 31 31 31 grey12 33 33 33 gray13 33 33 33 grey13 36 36 36 gray14 36 36 36 grey14 38 38 38 gray15 38 38 38 grey15 41 41 41 gray16 41 41 41 grey16 43 43 43 gray17 43 43 43 grey17 46 46 46 gray18 46 46 46 grey18 48 48 48 gray19 48 48 48 grey19 51 51 51 gray20 51 51 51 grey20 54 54 54 gray21 54 54 54 grey21 56 56 56 gray22 56 56 56 grey22 59 59 59 gray23 59 59 59 grey23 61 61 61 gray24 61 61 61 grey24 64 64 64 gray25 64 64 64 grey25 66 66 66 gray26 66 66 66 grey26 69 69 69 gray27 69 69 69 grey27 71 71 71 gray28 71 71 71 grey28 74 74 74 gray29 74 74 74 grey29 77 77 77 gray30 77 77 77 grey30 79 79 79 gray31 79 79 79 grey31 82 82 82 gray32 82 82 82 grey32 84 84 84 gray33 84 84 84 grey33 87 87 87 gray34 87 87 87 grey34 89 89 89 gray35 89 89 89 grey35 92 92 92 gray36 92 92 92 grey36 94 94 94 gray37 94 94 94 grey37 97 97 97 gray38 97 97 97 grey38 99 99 99 gray39 99 99 99 grey39 102 102 102 gray40 102 102 102 grey40 105 105 105 gray41 105 105 105 grey41 107 107 107 gray42 107 107 107 grey42 110 110 110 gray43 110 110 110 grey43 112 112 112 gray44 112 112 112 grey44 115 115 115 gray45 115 115 115 grey45 117 117 117 gray46 117 117 117 grey46 120 120 120 gray47 120 120 120 grey47 122 122 122 gray48 122 122 122 grey48 125 125 125 gray49 125 125 125 grey49 127 127 127 gray50 127 127 127 grey50 130 130 130 gray51 130 130 130 grey51 133 133 133 gray52 133 133 133 grey52 135 135 135 gray53 135 135 135 grey53 138 138 138 gray54 138 138 138 grey54 140 140 140 gray55 140 140 140 grey55 143 143 143 gray56 143 143 143 grey56 145 145 145 gray57 145 145 145 grey57 148 148 148 gray58 148 148 148 grey58 150 150 150 gray59 150 150 150 grey59 153 153 153 gray60 153 153 153 grey60 156 156 156 gray61 156 156 156 grey61 158 158 158 gray62 158 158 158 grey62 161 161 161 gray63 161 161 161 grey63 163 163 163 gray64 163 163 163 grey64 166 166 166 gray65 166 166 166 grey65 168 168 168 gray66 168 168 168 grey66 171 171 171 gray67 171 171 171 grey67 173 173 173 gray68 173 173 173 grey68 176 176 176 gray69 176 176 176 grey69 179 179 179 gray70 179 179 179 grey70 181 181 181 gray71 181 181 181 grey71 184 184 184 gray72 184 184 184 grey72 186 186 186 gray73 186 186 186 grey73 189 189 189 gray74 189 189 189 grey74 191 191 191 gray75 191 191 191 grey75 194 194 194 gray76 194 194 194 grey76 196 196 196 gray77 196 196 196 grey77 199 199 199 gray78 199 199 199 grey78 201 201 201 gray79 201 201 201 grey79 204 204 204 gray80 204 204 204 grey80 207 207 207 gray81 207 207 207 grey81 209 209 209 gray82 209 209 209 grey82 212 212 212 gray83 212 212 212 grey83 214 214 214 gray84 214 214 214 grey84 217 217 217 gray85 217 217 217 grey85 219 219 219 gray86 219 219 219 grey86 222 222 222 gray87 222 222 222 grey87 224 224 224 gray88 224 224 224 grey88 227 227 227 gray89 227 227 227 grey89 229 229 229 gray90 229 229 229 grey90 232 232 232 gray91 232 232 232 grey91 235 235 235 gray92 235 235 235 grey92 237 237 237 gray93 237 237 237 grey93 240 240 240 gray94 240 240 240 grey94 242 242 242 gray95 242 242 242 grey95 245 245 245 gray96 245 245 245 grey96 247 247 247 gray97 247 247 247 grey97 250 250 250 gray98 250 250 250 grey98 252 252 252 gray99 252 252 252 grey99 255 255 255 gray100 255 255 255 grey100 169 169 169 dark grey 169 169 169 DarkGrey 169 169 169 dark gray 169 169 169 DarkGray 0 0 139 dark blue 0 0 139 DarkBlue 0 139 139 dark cyan 0 139 139 DarkCyan 139 0 139 dark magenta 139 0 139 DarkMagenta 139 0 0 dark red 139 0 0 DarkRed 144 238 144 light green 144 238 144 LightGreen fltk-1.4.3/test/radio.fl0000644000175000017500000000764515004135251015221 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} Function {button_cb(Fl_Button *b, void *)} { comment {Buttons test callback} open private return_type void } { code {char msg[256]; sprintf(msg, "Label: '%s'\\nValue: %d\\nChanged: %d", b->label(), b->value(), b->changed()); cb_info->value(msg); cb_info->redraw(); printf("%s\\n",msg);} {selected } } Function {} {open } { Fl_Window {} {open xywh {470 366 369 214} type Double visible } { Fl_Button {} { label {&Fl_Button A1} tooltip {Normal button (callback called only when released)} xywh {20 10 160 30} labelsize 13 code0 {o->callback((Fl_Callback*) button_cb);} } Fl_Button {} { label {Fl_Button &A2} tooltip {Normal button with callback called when changed (push and released)} xywh {20 44 160 30} labelsize 13 when 1 code0 {o->callback((Fl_Callback*) button_cb);} } Fl_Return_Button {} { label {Fl_Return_Button &B} tooltip {Button with Return key as default shortcut} xywh {20 78 160 30} labelsize 13 code0 {o->callback((Fl_Callback*) button_cb);} } Fl_Light_Button {} { label {Fl_Light_Button &C} tooltip {Button with toggle state and a visual indicator of the current state} xywh {20 113 160 30} labelsize 13 code0 {o->callback((Fl_Callback*) button_cb);} } Fl_Check_Button {} { label {Fl_Check_Button &D} tooltip {Check button with toggle state} xywh {20 148 160 30} down_box DOWN_BOX labelsize 13 code0 {o->callback((Fl_Callback*) button_cb);} } Fl_Round_Button {} { label {Fl_Round_Button &E} tooltip {Round Button with toggle state} xywh {20 178 160 30} down_box ROUND_DOWN_BOX labelsize 13 code0 {o->callback((Fl_Callback*) button_cb);} } Fl_Group {} {open xywh {190 10 70 120} box THIN_UP_FRAME } { Fl_Round_Button {} { label {radio &1} tooltip {Radio button, only one button is set at a time, in the corresponding group.} xywh {190 10 70 30} type Radio down_box ROUND_DOWN_BOX code0 {o->callback((Fl_Callback*) button_cb);} } Fl_Round_Button {} { label {radio &2} tooltip {Radio button, only one button is set at a time, in the corresponding group.} xywh {190 40 70 30} type Radio down_box ROUND_DOWN_BOX code0 {o->callback((Fl_Callback*) button_cb);} } Fl_Round_Button {} { label {radio &3} tooltip {Radio button, only one button is set at a time, in the corresponding group.} xywh {190 70 70 30} type Radio down_box ROUND_DOWN_BOX code0 {o->callback((Fl_Callback*) button_cb);} } Fl_Round_Button {} { label {radio &4} tooltip {Radio button, only one button is set at a time, in the corresponding group.} xywh {190 100 70 30} type Radio down_box ROUND_DOWN_BOX code0 {o->callback((Fl_Callback*) button_cb);} } } Fl_Group {} {open xywh {270 10 90 120} box THIN_UP_BOX } { Fl_Button {} { label radio tooltip {Custom look button, only one button is set at a time, in the corresponding group.} xywh {280 20 20 20} type Radio selection_color 1 align 8 } Fl_Button {} { label radio tooltip {Custom look button, only one button is set at a time, in the corresponding group.} xywh {280 45 20 20} type Radio selection_color 1 align 8 } Fl_Button {} { label radio tooltip {Custom look button, only one button is set at a time, in the corresponding group.} xywh {280 70 20 20} type Radio selection_color 1 align 8 } Fl_Button {} { label radio tooltip {Custom look button, only one button is set at a time, in the corresponding group.} xywh {280 95 20 20} type Radio selection_color 1 align 8 } } Fl_Output cb_info { label {callback:} xywh {190 148 170 62} type Multiline align 133 textsize 12 } } } fltk-1.4.3/test/resize-example5a.cxx0000644000175000017500000000544215004135251017475 0ustar albrechtalbrecht// // Resize example for use in the Fast Light Tool Kit (FLTK) documentation. // // See Article #415: How does resizing work? // https://www.fltk.org/articles.php?L415 // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "resize-arrows.h" #include // window, simplex and arrow dimensions int TLx = 35, TRx = 320, TLw = 260, Ww = 620; int TLy = 35, LGy = 100, TLh = 65, LGh = 70, LAh = 35, Wh = 175; Fl_Double_Window *window = 0; class Simplex : public Fl_Group { public: Simplex(int X, int Y, int W, int H, const char *T = 0); Fl_Box *m_boxA, *m_boxB, *m_boxC; Fl_Group *m_group; }; Simplex::Simplex(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->box(FL_UP_BOX); m_group = new Fl_Group(X + 10, Y + 10, 240, 45); m_group->box(FL_UP_BOX); m_boxA = new Fl_Box(X + 20, Y + 20, 80, 25, "A"); m_boxA->box(FL_UP_BOX); m_boxB = new Fl_Box(X + 110, Y + 20, 40, 25, "B"); m_boxB->box(FL_UP_BOX); m_boxC = new Fl_Box(X + 160, Y + 20, 80, 25, "C"); m_boxC->box(FL_UP_BOX); m_group->color(FL_YELLOW); m_group->end(); this->resizable(m_group); this->end(); } class Resizables : public Fl_Group { public: Resizables(int X, int Y, int W, int H, const char *T = 0); Simplex *TL, *TR; // top left, top right Harrow *LA, *RA; // left arrow, right arrow }; Resizables::Resizables(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { TL = new Simplex(X + TLx, Y + TLy, TLw, TLh, "Original"); TL->align(FL_ALIGN_TOP_LEFT); TR = new Simplex(X + TRx, Y + TLy, TLw, TLh, "Horizontally Resized"); TR->align(FL_ALIGN_TOP_LEFT); Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); LG->box(FL_NO_BOX); LG->color(FL_WHITE); LA = new Harrow(TL->m_group->x(), LG->y(), TL->m_group->w(), LAh, "Initial\nwidth"); LG->resizable(LA); LG->end(); Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); RG->box(FL_NO_BOX); RG->color(FL_WHITE); RA = new Harrow(TR->m_group->x(), RG->y(), TR->m_group->w(), LAh, "Resized\nwidth"); RG->resizable(RA); RG->end(); this->resizable(TR); this->end(); } int main(int argc, char **argv) { window = new Fl_Double_Window(Ww, Wh, "resize-example5a"); window->color(FL_WHITE); Resizables *resizables = new Resizables(0, 0, Ww, Wh); window->end(); window->resizable(resizables); window->size_range(Ww, Wh); window->show(argc, argv); window->size(Ww + 90, Wh); return Fl::run(); } fltk-1.4.3/test/twowin.cxx0000644000175000017500000000247415004135251015646 0ustar albrechtalbrecht// // Cross-window focus test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2015 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include static Fl_Input *b1, *b2; static void cb1(Fl_Widget *, void *) { b2->take_focus(); } static void cb2(Fl_Widget *, void *) { b1->take_focus(); } int main(int argc, char **argv) { Fl_Double_Window *win1 = new Fl_Double_Window(200, 200); Fl_Button *bb1 = new Fl_Button(10, 10, 100, 100, "b1"); bb1->callback(cb1); b1 = new Fl_Input(10, 150, 100, 25); win1->label("win1"); win1->end(); Fl_Double_Window *win2 = new Fl_Double_Window(200, 200); Fl_Button *bb2 = new Fl_Button(10, 10, 100, 100, "b2"); bb2->callback(cb2); b2 = new Fl_Input(10, 150, 100, 25); win2->label("win2"); win2->end(); win1->position(200, 200); win2->position(400, 200); win1->show(argc,argv); win2->show(); return Fl::run(); } fltk-1.4.3/test/subwindow.cxx0000644000175000017500000001342615004135251016337 0ustar albrechtalbrecht// // Nested window test program for the Fast Light Tool Kit (FLTK). // // Test to make sure nested windows work. // Events should be reported for enter/exit and all mouse operations // Buttons and pop-up menu should work, indicating that mouse positions // are being correctly translated. // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #ifdef DEBUG #include #endif // Define DEBUG_POS for a subwindow positioning test. This will draw // the last typed character at the cursor position, if no input widget // currently has the focus. // Note: The typed character is saved in the derived testwindow class, // regardless of the definition of DEBUG_POS. Only drawing the character // depends on this define. #ifdef DEBUG_POS #include #endif class EnterExit : public Fl_Box { int handle(int) FL_OVERRIDE; public: EnterExit(int x, int y, int w, int h, const char *l) : Fl_Box(FL_BORDER_BOX,x,y,w,h,l) {} }; int EnterExit::handle(int e) { if (e == FL_ENTER) {color(FL_RED); redraw(); return 1;} else if (e == FL_LEAVE) {color(FL_GRAY); redraw(); return 1;} else return 0; } class testwindow : public Fl_Window { int handle(int) FL_OVERRIDE; void draw() FL_OVERRIDE; int cx, cy; char key; Fl_Cursor crsr; public: testwindow(Fl_Boxtype b,int x,int y,const char *l) : Fl_Window(x,y,l), crsr(FL_CURSOR_DEFAULT) {box(b); key = 0;} testwindow(Fl_Boxtype b,int x,int y,int w,int h,const char *l) : Fl_Window(x,y,w,h,l) {box(b); key = 0;} void use_cursor(Fl_Cursor c) { crsr = c; } }; void testwindow::draw() { #ifdef DEBUG printf("%s : draw\n",label()); #endif Fl_Window::draw(); #ifdef DEBUG_POS if (key) fl_draw(&key, 1, cx, cy); #endif } int testwindow::handle(int e) { #ifdef DEBUG if (e != FL_MOVE) printf("%s : %s\n",label(),fl_eventnames[e]); #endif if (crsr!=FL_CURSOR_DEFAULT) { if (e == FL_ENTER) cursor(crsr); if (e == FL_LEAVE) cursor(FL_CURSOR_DEFAULT); } if (Fl_Window::handle(e)) return 1; if (e == FL_FOCUS) return 1; if (e == FL_PUSH) {Fl::focus(this); return 1;} if (e == FL_KEYBOARD && Fl::event_text()[0]) { if (Fl::event_key() == FL_Escape || Fl::event_command()) return 0; key = Fl::event_text()[0]; cx = Fl::event_x(); cy = Fl::event_y(); redraw(); return 1; } return 0; } Fl_Menu_Button* popup; const char* bigmess = #if 1 "this|is|only|a test" #else "item1|item2|item3|item4|item5|" "submenu/item1|submenu/item2|submenu/item3|submenu/item4|" "submenu/sub/item1|submenu/sub/item2|submenu/sub/item3|" "item6|item7|item8|item9|item10|" "item21|item22|item23|item24|item25|" "submenu/item21|submenu/item22|submenu/item23|submenu/item24|" "submenu/sub/item21|submenu/sub/item22|submenu/sub/item23|" "item36|item37|item38|item39|item310|" "item31|item32|item33|item34|item35|" "submenu/item31|submenu/item32|submenu/item33|submenu/item34|" "submenu/sub/item31|submenu/sub/item32|submenu/sub/item33|" "item46|item47|item48|item49|item410|" "item41|item42|item43|item44|item45|" "submenu/item41|submenu/item42|submenu/item43|submenu/item44|" "submenu/sub/item41|submenu/sub/item42|submenu/sub/item43|" "item26|item27|item28|item29|item210|" "submenu2/item1|submenu2/item2|submenu2/item3|submenu2/item4|" "submenu2/sub/item1|submenu2/sub/item2|submenu2/sub/item3|" "item6|item7|item8|item9|item10|" "item21|item22|item23|item24|item25|" "submenu2/item21|submenu2/item22|submenu2/item23|submenu2/item24|" "submenu2/sub/item21|submenu2/sub/item22|submenu2/sub/item23|" "item36|item37|item38|item39|item310|" "item31|item32|item33|item34|item35|" "submenu2/item31|submenu2/item32|submenu2/item33|submenu2/item34|" "submenu2/sub/item31|submenu2/sub/item32|submenu2/sub/item33|" "item46|item47|item48|item49|item410|" "item41|item42|item43|item44|item45|" "submenu2/item41|submenu2/item42|submenu2/item43|submenu2/item44|" "submenu2/sub/item41|submenu2/sub/item42|submenu2/sub/item43|" "item26|item27|item28|item29|item210|" #endif ; int main(int argc, char **argv) { testwindow *window = new testwindow(FL_UP_BOX,400,400,"outer"); new Fl_Toggle_Button(310,310,80,80,"&outer"); new EnterExit(10,310,80,80,"enterexit"); new Fl_Input(160,310,140,25,"input1:"); new Fl_Input(160,340,140,25,"input2:"); (new Fl_Menu_Button(5,150,80,25,"menu&1"))->add(bigmess); testwindow *subwindow = new testwindow(FL_DOWN_BOX,100,100,200,200,"inner"); new Fl_Toggle_Button(110,110,80,80,"&inner"); new EnterExit(10,110,80,80,"enterexit"); (new Fl_Menu_Button(50,20,80,25,"menu&2"))->add(bigmess); new Fl_Input(55,50,140,25,"input1:"); new Fl_Input(55,80,140,25,"input2:"); subwindow->resizable(subwindow); window->resizable(subwindow); subwindow->end(); subwindow->use_cursor(FL_CURSOR_HAND); (new Fl_Box(FL_NO_BOX,0,0,400,100, "A child Fl_Window with children of its own may " "be useful for imbedding controls into a GL or display " "that needs a different visual. There are bugs with the " "origins being different between drawing and events, " "which I hope I have solved." )) -> align(FL_ALIGN_WRAP); popup = new Fl_Menu_Button(0,0,400,400); popup->type(Fl_Menu_Button::POPUP3); popup->add("This|is|a popup|menu"); popup->add(bigmess); window->show(argc, argv); return Fl::run(); } fltk-1.4.3/test/color_chooser.cxx0000644000175000017500000001005115004135251017145 0ustar albrechtalbrecht// // Color chooser test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include #include "list_visuals.cxx" int width = 100; int height = 100; uchar *image; Fl_Box *hint; void make_image() { image = new uchar[3*width*height]; uchar *p = image; for (int y = 0; y < height; y++) { double Y = double(y)/(height-1); for (int x = 0; x < width; x++) { double X = double(x)/(width-1); *p++ = uchar(255*((1-X)*(1-Y))); // red in upper-left *p++ = uchar(255*((1-X)*Y)); // green in lower-left *p++ = uchar(255*(X*Y)); // blue in lower-right } } } class Pens : public Fl_Box { void draw() FL_OVERRIDE; public: Pens(int X, int Y, int W, int H, const char* L) : Fl_Box(X,Y,W,H,L) {} }; void Pens::draw() { // use every color in the gray ramp: for (int i = 0; i < 3*8; i++) { fl_color((Fl_Color)(FL_GRAY_RAMP+i)); fl_line(x()+i, y(), x()+i, y()+h()); } } Fl_Color c = FL_GRAY; #define fullcolor_cell (FL_FREE_COLOR) void cb1(Fl_Widget *, void *v) { c = fl_show_colormap(c); Fl_Box* b = (Fl_Box*)v; b->color(c); hint->labelcolor(fl_contrast(FL_BLACK,c)); b->parent()->redraw(); } void cb2(Fl_Widget *, void *v) { uchar r,g,b; Fl::get_color(c,r,g,b); if (!fl_color_chooser("New color:",r,g,b,3)) return; c = fullcolor_cell; Fl::set_color(fullcolor_cell,r,g,b); Fl_Box* bx = (Fl_Box*)v; bx->color(fullcolor_cell); hint->labelcolor(fl_contrast(FL_BLACK,fullcolor_cell)); bx->parent()->redraw(); } int main(int argc, char ** argv) { Fl::set_color(fullcolor_cell,145,159,170); Fl_Window window(400,400); Fl_Box box(30,30,340,340); box.box(FL_THIN_DOWN_BOX); c = fullcolor_cell; box.color(c); Fl_Box hintbox(40,40,320,30,"Pick background color with buttons:"); hintbox.align(FL_ALIGN_INSIDE); hint = &hintbox; Fl_Button b1(120,80,180,30,"fl_show_colormap()"); b1.callback(cb1,&box); Fl_Button b2(120,120,180,30,"fl_color_chooser()"); b2.callback(cb2,&box); Fl_Box image_box(160,190,width,height,0); make_image(); (new Fl_RGB_Image(image, width, height))->label(&image_box); Fl_Box b(160,310,120,30,"Example of fl_draw_image()"); Pens p(60,180,3*8,120,"lines"); p.align(FL_ALIGN_TOP); int i = 1; if (!Fl::args(argc,argv,i) || i < argc-1) { printf("usage: %s visual-number\n" " - : default visual\n" " r : call Fl::visual(FL_RGB)\n" " c : call Fl::own_colormap()\n",argv[0]); #ifdef FLTK_USE_X11 printf(" # : use this visual with an empty colormap:\n"); list_visuals(); #endif puts(Fl::help); exit(1); } if (i!=argc) { if (argv[i][0] == 'r') { if (!Fl::visual(FL_RGB)) printf("Fl::visual(FL_RGB) returned false.\n"); } else if (argv[i][0] == 'c') { Fl::own_colormap(); } else if (argv[i][0] != '-') { #ifdef FLTK_USE_X11 int visid = atoi(argv[i]); fl_open_display(); XVisualInfo templt; int num; templt.visualid = visid; fl_visual = XGetVisualInfo(fl_display, VisualIDMask, &templt, &num); if (!fl_visual) Fl::fatal("No visual with id %d",visid); fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen), fl_visual->visual, AllocNone); fl_xpixel(FL_BLACK); // make sure black is allocated #else Fl::fatal("Visual id's not supported on Windows or MacOS."); #endif } } window.show(argc,argv); return Fl::run(); } fltk-1.4.3/test/unittests.cxx0000644000175000017500000003431515004135251016360 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Fltk unit tests // v0.1 - Greg combines Matthias + Ian's tests // v0.2 - Ian's 02/12/09 fixes applied // v0.3 - Fixes to circle desc, augmented extent tests, fixed indents, added show(argc,argv) // v1.0 - Submit for svn // v1.1 - Matthias seperated all tests into multiple source files for hopefully easier handling // NOTE: See README-unittests.txt for how to add new tests. #include "unittests.h" #include #include #include #include #include #include #include #include // fl_text_extents() #include // fl_strdup() #include // fl_message() #include // malloc, free class Ut_Main_Window *mainwin = NULL; class Fl_Hold_Browser *browser = NULL; int UnitTest::num_tests_ = 0; UnitTest *UnitTest::test_list_[200] = { 0 }; // ----- UnitTest ------------------------------------------------------ MARK: - UnitTest::UnitTest(int index, const char* label, Fl_Widget* (*create)()) : widget_(0L) { label_ = fl_strdup(label); create_ = create; add(index, this); } UnitTest::~UnitTest() { delete widget_; free(label_); } const char *UnitTest::label() { return label_; } void UnitTest::create() { widget_ = create_(); if (widget_) widget_->hide(); } void UnitTest::show() { if (widget_) widget_->show(); } void UnitTest::hide() { if (widget_) widget_->hide(); } void UnitTest::add(int index, UnitTest* t) { test_list_[index] = t; if (index >= num_tests_) num_tests_ = index+1; } // ----- Ut_Main_Window ------------------------------------------------ MARK: - Ut_Main_Window::Ut_Main_Window(int w, int h, const char *l) : Fl_Double_Window(w, h, l), draw_alignment_test_(0) { } void Ut_Main_Window::draw_alignment_indicators() { const int SZE = 16; // top left corner fl_color(FL_GREEN); fl_yxline(0, SZE, 0, SZE); fl_color(FL_RED); fl_yxline(-1, SZE, -1, SZE); fl_color(FL_WHITE); fl_rectf(3, 3, SZE-2, SZE-2); fl_color(FL_BLACK); fl_rect(3, 3, SZE-2, SZE-2); // bottom left corner fl_color(FL_GREEN); fl_yxline(0, h()-SZE-1, h()-1, SZE); fl_color(FL_RED); fl_yxline(-1, h()-SZE-1, h(), SZE); fl_color(FL_WHITE); fl_rectf(3, h()-SZE-1, SZE-2, SZE-2); fl_color(FL_BLACK); fl_rect(3, h()-SZE-1, SZE-2, SZE-2); // bottom right corner fl_color(FL_GREEN); fl_yxline(w()-1, h()-SZE-1, h()-1, w()-SZE-1); fl_color(FL_RED); fl_yxline(w(), h()-SZE-1, h(), w()-SZE-1); fl_color(FL_WHITE); fl_rectf(w()-SZE-1, h()-SZE-1, SZE-2, SZE-2); fl_color(FL_BLACK); fl_rect(w()-SZE-1, h()-SZE-1, SZE-2, SZE-2); // top right corner fl_color(FL_GREEN); fl_yxline(w()-1, SZE, 0, w()-SZE-1); fl_color(FL_RED); fl_yxline(w(), SZE, -1, w()-SZE-1); fl_color(FL_WHITE); fl_rectf(w()-SZE-1, 3, SZE-2, SZE-2); fl_color(FL_BLACK); fl_rect(w()-SZE-1, 3, SZE-2, SZE-2); } void Ut_Main_Window::draw() { Fl_Double_Window::draw(); if (draw_alignment_test_) { draw_alignment_indicators(); } } void Ut_Main_Window::test_alignment(int v) { draw_alignment_test_ = v; redraw(); } // ----- Ut_Test ------------------------------------------------------- MARK: - /** Create a unit test that can contain many test cases using EXPECT_*. Ut_Test should be instantiated by using the TEST(SUITE, NAME) macro. Multiple TEST() macros can be called within the same source file to generate an arbitrary number of tests. TEST() can be called in multiple source files of the same application. The constructor also registers the test with Ut_Suite and groups it by name. */ Ut_Test::Ut_Test(const char *suitename, const char *testname, Ut_Test_Call call) : name_(testname), call_(call), failed_(false), done_(false) { Ut_Suite *suite = Ut_Suite::locate(suitename); suite->add(this); } /** Run all cases inside the test and return false when the first case fails. */ bool Ut_Test::run(const char *suite) { Ut_Suite::printf("%s[ RUN ]%s %s.%s\n", Ut_Suite::green, Ut_Suite::normal, suite, name_); bool ret = call_(); if (ret) { Ut_Suite::printf("%s[ OK ]%s %s.%s\n", Ut_Suite::green, Ut_Suite::normal, suite, name_); failed_ = false; } else { Ut_Suite::printf("%s[ FAILED ]%s %s.%s\n", Ut_Suite::red, Ut_Suite::normal, suite, name_); failed_ = true; } done_ = true; return ret; } /** Print a message is the test was previously marked failed. */ void Ut_Test::print_failed(const char *suite) { if (failed_) { Ut_Suite::printf("%s[ FAILED ]%s %s.%s\n", Ut_Suite::red, Ut_Suite::normal, suite, name_); } } // ----- Ut_Suite ------------------------------------------------------ MARK: - Ut_Suite **Ut_Suite::suite_list_ = NULL; int Ut_Suite::suite_list_size_ = 0; int Ut_Suite::num_tests_ = 0; int Ut_Suite::num_passed_ = 0; int Ut_Suite::num_failed_ = 0; const char *Ut_Suite::red = "\033[31m"; const char *Ut_Suite::green = "\033[32m"; const char *Ut_Suite::normal = "\033[0m"; Fl_Terminal *Ut_Suite::tty = NULL; /** Switch the user of color escape sequnces in the log text. */ void Ut_Suite::color(int v) { if (v) { red = "\033[31m"; green = "\033[32m"; normal = "\033[0m"; } else { red = ""; green = ""; normal = ""; } } /** Create a suite that will group tests by the suite name. Ut_Suite is automatically instantiated by using the TEST(SUITE, NAME) macro. Multiple TEST() macros are grouped into suits by suite name. */ Ut_Suite::Ut_Suite(const char *name) : test_list_(NULL), test_list_size_(0), name_(name), done_(false) { } /** Add a test to the suite. This is done automatically by the TEST() macro. */ void Ut_Suite::add(Ut_Test *test) { if ( (test_list_size_ % 16) == 0 ) { test_list_ = (Ut_Test**)realloc(test_list_, (test_list_size_+16)*sizeof(Ut_Test*)); } test_list_[test_list_size_++] = test; } /** Static method that will find or create a suite by name. */ Ut_Suite *Ut_Suite::locate(const char *name) { for (int i=0; iname_)==0) return suite_list_[i]; } if ( (suite_list_size_ % 16) == 0 ) { suite_list_ = (Ut_Suite**)realloc(suite_list_, (suite_list_size_+16)*sizeof(Ut_Suite*)); } Ut_Suite *s = new Ut_Suite(name); suite_list_[suite_list_size_++] = s; return s; } /** Logs the start of a test suite run. */ void Ut_Suite::print_suite_epilog() { Ut_Suite::printf("%s[----------]%s %d test%s from %s\n", Ut_Suite::green, Ut_Suite::normal, test_list_size_, test_list_size_ == 1 ? "" : "s", name_); } /** Run all tests in a single suite, returning the number of failed tests. */ int Ut_Suite::run() { print_suite_epilog(); int num_tests_failed = 0; for (int i=0; irun(name_)) { num_tests_failed++; } } return num_tests_failed; } /** Static method to log all tests that are marked failed. */ void Ut_Suite::print_failed() { for (int i=0; iprint_failed(name_); } } /** Static method to log the start of a test run. */ void Ut_Suite::print_prolog() { int i; num_tests_ = 0; num_passed_ = 0; num_failed_ = 0; for (i=0; isize(); } Ut_Suite::printf("%s[==========]%s Running %d tests from %d test case%s.\n", Ut_Suite::green, Ut_Suite::normal, num_tests_, suite_list_size_, suite_list_size_ == 1 ? "" : "s"); } /** Static method to log the end of a test run. */ void Ut_Suite::print_epilog() { int i; Ut_Suite::printf("%s[==========]%s %d tests from %d test case%s ran.\n", Ut_Suite::green, Ut_Suite::normal, num_tests_, suite_list_size_, suite_list_size_ == 1 ? "" : "s"); if (num_passed_) { Ut_Suite::printf("%s[ PASSED ]%s %d test%s.\n", Ut_Suite::green, Ut_Suite::normal, num_passed_, num_passed_ == 1 ? "" : "s"); } if (num_failed_) { Ut_Suite::printf("%s[ FAILED ]%s %d test%s, listed below:\n", Ut_Suite::red, Ut_Suite::normal, num_failed_, num_failed_ == 1 ? "" : "s"); } for (i=0; iprint_failed(); } } /** Static method to run all tests in all test suites. Returns the number of failed tests. */ int Ut_Suite::run_all_tests() { print_prolog(); // loop through all suites which then loop through all tests for (int i=0; irun(); num_passed_ += suite_list_[i]->size() - n; num_failed_ += n; } print_epilog(); return num_failed_; } /** Static method to run all test, one-by-one, until done. Run all tests by calling `while (Ut_Suite::run_next_test()) { }`. This is used to visualise test progress with the terminal window by runnig test asynchronously and adding a noticable delay between calls. */ bool Ut_Suite::run_next_test() { // if all suites are done, print the ending text and return Ut_Suite *last = suite_list_[suite_list_size_-1]; if (last->done_) { print_epilog(); return false; } // if no tests ran yet, print the starting text Ut_Suite *first = suite_list_[0]; if (!first->done_ && !first->test_list_[0]->done_) { print_prolog(); } // now find the next test that hasn't ran yet for (int i=0; idone_) continue; if (!st->test_list_[0]->done_) st->print_suite_epilog(); for (int j=0; jtest_list_size_; j++) { if (st->test_list_[j]->done_) continue; if (st->test_list_[j]->run(st->name_)) num_passed_++; else num_failed_++; return true; } st->done_ = true; return true; } return true; } /** A printf that is redirected to the terminal or stdout. */ void Ut_Suite::printf(const char *format, ...) { va_list args; va_start(args, format); if (tty) { tty->vprintf(format, args); } else { vprintf(format, args); } va_end(args); } /** Log the result of a boolean case fail. */ void Ut_Suite::log_bool(const char *file, int line, const char *cond, bool result, bool expected) { Ut_Suite::printf("%s(%d): error:\n", file, line); Ut_Suite::printf("Value of: %s\n", cond); Ut_Suite::printf("Actual: %s\n", result ? "true" : "false"); Ut_Suite::printf("Expected: %s\n", expected ? "true" : "false"); } /** Log the result of a string comparison case fail. */ void Ut_Suite::log_string(const char *file, int line, const char *cond, const char *result, const char *expected) { Ut_Suite::printf("%s(%d): error:\n", file, line); Ut_Suite::printf("Value of: %s\n", cond); Ut_Suite::printf(" Actual: %s\n", result); Ut_Suite::printf("Expected: %s\n", expected); } /** Log the result of an integer comparison case fail. */ void Ut_Suite::log_int(const char *file, int line, const char *cond, int result, const char *expected) { Ut_Suite::printf("%s(%d): error:\n", file, line); Ut_Suite::printf("Value of: %s\n", cond); Ut_Suite::printf(" Actual: %d\n", result); Ut_Suite::printf("Expected: %s\n", expected); } // ----- main ---------------------------------------------------------- MARK: - // callback whenever the browser value changes void ui_browser_cb(Fl_Widget*, void*) { for ( int t=1; t<=browser->size(); t++ ) { UnitTest* ti = (UnitTest*)browser->data(t); if ( browser->selected(t) ) { ti->show(); } else { ti->hide(); } } } static bool run_core_tests_only = false; static int arg(int argc, char** argv, int& i) { if ( strcmp(argv[i], "--core") == 0 ) { run_core_tests_only = true; i++; return 1; } if ( strcmp(argv[i], "--color=0") == 0 ) { Ut_Suite::color(0); i++; return 1; } if ( strcmp(argv[i], "--color=1") == 0 ) { Ut_Suite::color(1); i++; return 1; } if ( (strcmp(argv[i], "--help") == 0) || (strcmp(argv[i], "-h") == 0) ) { return 0; } return 0; } // This is the main call. It creates the window and adds all previously // registered tests to the browser widget. int main(int argc, char** argv) { int i; Fl::args_to_utf8(argc, argv); // for MSYS2/MinGW if ( Fl::args(argc,argv,i,arg) == 0 ) { // unsupported argument found static const char *msg = "usage: %s \n" " --core : test core functionality only\n" " --color=1, --color=0 : print test output in color or plain text" " --help, -h : print this help page\n"; const char *app_name = NULL; if ( (argc > 0) && argv[0] && argv[0][0] ) app_name = fl_filename_name(argv[0]); if ( !app_name || !app_name[0]) app_name = "unittests"; #ifdef _MSC_VER fl_message(msg, app_name); #else fprintf(stderr, msg, app_name); #endif return 1; } if (run_core_tests_only) { return RUN_ALL_TESTS(); } Fl::get_system_colors(); Fl::scheme(Fl::scheme()); // init scheme before instantiating tests Fl::visual(FL_RGB); Fl::use_high_res_GL(1); mainwin = new Ut_Main_Window(UT_MAINWIN_W, UT_MAINWIN_H, "FLTK Unit Tests"); mainwin->size_range(UT_MAINWIN_W, UT_MAINWIN_H); browser = new Fl_Hold_Browser(UT_BROWSER_X, UT_BROWSER_Y, UT_BROWSER_W, UT_BROWSER_H, "Unit Tests"); browser->align(FL_ALIGN_TOP|FL_ALIGN_LEFT); browser->when(FL_WHEN_CHANGED); browser->callback(ui_browser_cb); browser->linespacing(2); int n = UnitTest::num_tests(); for (i=0; ibegin(); t->create(); mainwin->end(); browser->add(t->label(), (void*)t); } } mainwin->resizable(mainwin); mainwin->show(argc, argv); // Select first test in browser, and show that test. browser->select(UT_TEST_ABOUT+1); ui_browser_cb(browser, 0); return Fl::run(); } fltk-1.4.3/test/image.cxx0000644000175000017500000000770115004135251015377 0ustar albrechtalbrecht// // Fl_Image test program for the Fast Light Tool Kit (FLTK). // // Notice that Fl_Image is for a static, multiple-reuse image, such // as an icon or postage stamp. Use fl_draw_image to go directly // from an buffered image that changes often. // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include int width = 100; int height = 100; uchar *image; void make_image() { image = new uchar[4*width*height]; uchar *p = image; for (int y = 0; y < height; y++) { double Y = double(y)/(height-1); for (int x = 0; x < width; x++) { double X = double(x)/(width-1); *p++ = uchar(255*((1-X)*(1-Y))); // red in upper-left *p++ = uchar(255*((1-X)*Y)); // green in lower-left *p++ = uchar(255*(X*Y)); // blue in lower-right X -= 0.5; Y -= 0.5; int alpha = (int)(255 * sqrt(X * X + Y * Y)); if (alpha < 255) *p++ = uchar(alpha); // alpha transparency else *p++ = 255; Y += 0.5; } } } #include Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*overb,*inactb; Fl_Button *b; Fl_Double_Window *w; void button_cb(Fl_Widget *,void *) { int i = 0; if (leftb->value()) i |= FL_ALIGN_LEFT; if (rightb->value()) i |= FL_ALIGN_RIGHT; if (topb->value()) i |= FL_ALIGN_TOP; if (bottomb->value()) i |= FL_ALIGN_BOTTOM; if (insideb->value()) i |= FL_ALIGN_INSIDE; if (overb->value()) i |= FL_ALIGN_TEXT_OVER_IMAGE; b->align(i); if (inactb->value()) b->deactivate(); else b->activate(); w->redraw(); } #include #if defined(FLTK_USE_X11) #include "list_visuals.cxx" #endif int visid = -1; int arg(int argc, char **argv, int &i) { if (argv[i][1] == 'v') { if (i+1 >= argc) return 0; visid = atoi(argv[i+1]); i += 2; return 2; } return 0; } int main(int argc, char **argv) { #if defined(FLTK_USE_X11) int i = 1; Fl::args(argc,argv,i,arg); if (visid >= 0) { fl_open_display(); XVisualInfo templt; int num; templt.visualid = visid; fl_visual = XGetVisualInfo(fl_display, VisualIDMask, &templt, &num); if (!fl_visual) { fprintf(stderr, "No visual with id %d, use one of:\n",visid); list_visuals(); exit(1); } fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen), fl_visual->visual, AllocNone); fl_xpixel(FL_BLACK); // make sure black is allocated in overlay visuals } else { Fl::visual(FL_RGB); } #endif Fl_Double_Window window(400,400); ::w = &window; window.color(FL_WHITE); Fl_Button b(140,160,120,120,"Image w/Alpha"); ::b = &b; Fl_RGB_Image *rgb; Fl_Image *dergb; make_image(); rgb = new Fl_RGB_Image(image, width, height,4); dergb = rgb->copy(); dergb->inactive(); b.image(rgb); b.deimage(dergb); leftb = new Fl_Toggle_Button(25,50,50,25,"left"); leftb->callback(button_cb); rightb = new Fl_Toggle_Button(75,50,50,25,"right"); rightb->callback(button_cb); topb = new Fl_Toggle_Button(125,50,50,25,"top"); topb->callback(button_cb); bottomb = new Fl_Toggle_Button(175,50,50,25,"bottom"); bottomb->callback(button_cb); insideb = new Fl_Toggle_Button(225,50,50,25,"inside"); insideb->callback(button_cb); overb = new Fl_Toggle_Button(25,75,100,25,"text over"); overb->callback(button_cb); inactb = new Fl_Toggle_Button(125,75,100,25,"inactive"); inactb->callback(button_cb); window.resizable(window); window.end(); window.show(argc, argv); return Fl::run(); } fltk-1.4.3/test/help_dialog.html0000644000175000017500000002506515004135251016731 0ustar albrechtalbrecht Fl_Help_Dialog test - Fast Light Toolkit (FLTK)

Simple HTML Tests

Plain text paragraphs

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.

This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too.

Italic content. Bold content Big content. Small content. Underline content. Strike out content. Red font content. Orange #ff8800 font content. Blue font content.

This should be Helvetica. 0123456789
This should be Arial. 0123456789
This should be Sans. 0123456789
This should be Times. 0123456789
This should be Serif. 0123456789
This should be Courier. 0123456789
This should be Symbol. 0123456789

HTML Entities: named, hexadecimal, and decimal

Special characters, formatted as named "HTML Entities", e.g. "&euro;":
Euro and "dagger": "€" "†"
Umlaut characters : "ä" "ë" "ï" "ö" "ü" "ß"
Umlaut characters : "Ä" "Ë" "Ï" "Ö" "Ü"
Special characters : "•" "‰" "©" "™" "®"

Other scripts, formatted as hexadecimal "HTML Entities", e.g. "&#x20ac;":
(Should be the same symbols as below)
Euro and "dagger": "€" "†"
Japanese (Hiragana) : "ぐ" "の"
Japanese (Katakana) : "ダ" "ポ"
Chinese (CJK Unified Ideographs) : "中" "丳"

Other scripts, formatted as decimal "HTML Entities", e.g. "&#8364;":
(Should be the same symbols as above)
Euro and "dagger": "€" "†"
Japanese (Hiragana) : "ぐ" "の"
Japanese (Katakana) : "ダ" "ポ"
Chinese (CJK Unified Ideographs) : "中" "丳"

Preformatted paragraphs

The following 2 paragraphs should be indented 4 spaces.

    The licenses for most software are designed to take away
    your freedom to share and change it.  By contrast, the
    GNU General Public Licenses are intended to guarantee your
    freedom to share and change free software -- to make sure
    the software is free for all its users.

    This license, the Library General Public License, applies to
    some specially designated Free Software Foundation software,
    and to any other libraries whose authors decide to use it.
    You can use it for your libraries, too.

The following 2 paragraphs should be indented 8 spaces.

        The licenses for most software are designed to take away
        your freedom to share and change it.  By contrast, the
        GNU General Public Licenses are intended to guarantee
        your freedom to share and change free software --
        to make sure the software is free for all its users.

        This license, the Library General Public License,
        applies to some specially designated Free Software
        Foundation software, and to any other libraries whose
        authors decide to use it.  You can use it for your
        libraries, too.

The following text content should all be indented 4 spaces.

    Italic content. Bold content Big content.
    Small content. Underline content. Strike out content.
    Red font content. Orange #ff8800 font content.
    Blue font content.

Heading tests

This is H1 text

This is H2 text

This is H3 text

This is H4 text

This is H5 text
This is H6 text

UL tests

    This text should be indented in a UL.
    This should be a second line of indent.

  • First list item with default attributes
  • Second list item
  • Third list item
End of UL. Starting an OL:
    This text should be indented in an OL.
    This should be a second line of indent.

  1. First list item with default attributes
  2. Second list item
  3. Third list item
Another OL with start value 10:
  1. First list item (value 10)
  2. Second list item
  3. Third list item
End of OL. Starting a DL:
A DL has been started. This should be a list of terms. Some browsers display the description indented right relative to the terms, though I don't think FLTK's does this.

First term
Description of first term.
Second term
Description of second term goes here.
Third term
Description of third term goes here.
End of DL.

Nested OL/UL:

  1. First numbered Item
    • one thing
    • two things
    • three things
  2. Second numbered Item
    • one thing
    • two things
    • Three things

Simple 2 Column Non-border Table, No Headings
Column 1 Column 2
Aaa Aaa Aaa Xxx Xxx Xxx
Bbb Bbb Bbb Yyy Yyy Yyy
Ccc Ccc Ccc Zzz Zzz Zzz

Simple 2 Column Bordered Table, No Headings
Column 1 Column 2
Aaa Aaa Aaa Xxx Xxx Xxx
Bbb Bbb Bbb Yyy Yyy Yyy
Ccc Ccc Ccc Zzz Zzz Zzz

Simple Two Column Table With Borders And Heading
Table Heading  
Column 1 Column 2
Aaa Aaa Aaa Xxx Xxx Xxx
Bbb Bbb Bbb Yyy Yyy Yyy
Ccc Ccc Ccc Zzz Zzz Zzz

Simple Bordered Table With Heading And 10 Cell Padding + Spacing
Table Heading
Column 1 Column 2
Aaa Aaa Aaa Xxx Xxx Xxx
Bbb Bbb Bbb Yyy Yyy Yyy
Ccc Ccc Ccc Zzz Zzz Zzz

Simple Table Of Images, Two Columns, Three Rows
Table Heading
Column 1 Column 2
FLTK logo This is the FLTK logo
Tiny FLTK logo Tiny FLTK logo.
Animated FLTK logo Animated FLTK logo.
Fl_Value_Input This is an image of Fl_Value_Input
Fl_Value_Output This is an image of Fl_Value_Output

Testing Centered Text And Image

This text should be centered. What follows is a line break.
After the line break, still centered. What follows is a paragraph break.

This text should be in a paragraph break. This is paragraph #1 of 2.

This text should be in a paragraph break as well. This is paragraph #2 of 2.

What follows should be a centered image.
FLTK logo
That should be a centered image.

Testing Horizontal Line


This text should be between two horizontal lines.

Preformatted Indent Test

    This tests that tabs and space indenting work correctly.
    Each line should be one space right of the line preceding it
    unless otherwise specified:

0 Tab
 1 Space
  2 Space
   3 Space
    4 Space
     5 Space
      6 Space
       7 Space            __
        8 Space             |
    	4 Space + 1 Tab     |-- should all be
	1 Tab             __|   same indent level
	 1 Tab + 1 Space
	  1 Tab + 2 Space
	   1 Tab + 3 Space
	    1 Tab + 4 Space
	     1 Tab + 5 Space
	      1 Tab + 6 Space
	       1 Tab + 7 Space            __
	        1 Tab + 8 Space             |
    	        4 Space + 1 Tab + 8 Space   |-- should all be
		2 Tab                     __|   same indent level
		 2 Tab + 1 Space
		  2 Tab + 2 Space
		   2 Tab + 3 Space
		    ..
fltk-1.4.3/test/README.txt0000644000175000017500000000210615004135251015261 0ustar albrechtalbrechttest/README.txt - 20 Oct 1998 ----------------------------- This directory contains tests and demos of FL. In most cases you can learn a lot about how to program FL by looking at the source code. Type "make" to compile them all. The program "demo" is a graphical interface to run all the demos. (you may recognize this as a rewrite of an XForms program). Some of the more interesting programs: fractals: A GLUT program with FL controls added to it glpuzzle: A GLUT program with no modifications fullscreen: Demo of how to make your window toggle to fill screen list_visuals: necessary to debug X visual stuff mandelbrot: A true application, using panels built in Fluid menubar: Demo of how FL's menus work shiny: Demo of drawing FL's controls using OpenGL forms: An XForms program to demonstrate emulation colbrowser: Another XForms program that is actually useful ----------------------------------------------------- Note: this file is outdated and incomplete. (*FIXME*) ----------------------------------------------------- fltk-1.4.3/test/cursor.cxx0000644000175000017500000000751315004135251015633 0ustar albrechtalbrecht// // Cursor test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include "../fluid/pixmaps/compressed.xpm" Fl_Cursor cursor = FL_CURSOR_DEFAULT; Fl_Hor_Value_Slider *cursor_slider; void choice_cb(Fl_Widget *, void *v) { cursor = (Fl_Cursor)(fl_intptr_t)v; cursor_slider->value(cursor); fl_cursor(cursor); } void custom_cb(Fl_Widget *widget, void *) { Fl_Pixmap pxm(compressed_xpm); Fl_RGB_Image rgb(&pxm); rgb.scale(16,16); widget->top_window()->cursor(&rgb, rgb.w()/2, rgb.h()/2); } Fl_Menu_Item choices[] = { {"FL_CURSOR_DEFAULT",0,choice_cb,(void*)FL_CURSOR_DEFAULT}, {"FL_CURSOR_ARROW",0,choice_cb,(void*)FL_CURSOR_ARROW}, {"FL_CURSOR_CROSS",0,choice_cb,(void*)FL_CURSOR_CROSS}, {"FL_CURSOR_WAIT",0,choice_cb,(void*)FL_CURSOR_WAIT}, {"FL_CURSOR_INSERT",0,choice_cb,(void*)FL_CURSOR_INSERT}, {"FL_CURSOR_HAND",0,choice_cb,(void*)FL_CURSOR_HAND}, {"FL_CURSOR_HELP",0,choice_cb,(void*)FL_CURSOR_HELP}, {"FL_CURSOR_MOVE",0,choice_cb,(void*)FL_CURSOR_MOVE}, {"FL_CURSOR_NS",0,choice_cb,(void*)FL_CURSOR_NS}, {"FL_CURSOR_WE",0,choice_cb,(void*)FL_CURSOR_WE}, {"FL_CURSOR_NWSE",0,choice_cb,(void*)FL_CURSOR_NWSE}, {"FL_CURSOR_NESW",0,choice_cb,(void*)FL_CURSOR_NESW}, {"FL_CURSOR_N",0,choice_cb,(void*)FL_CURSOR_N}, {"FL_CURSOR_NE",0,choice_cb,(void*)FL_CURSOR_NE}, {"FL_CURSOR_E",0,choice_cb,(void*)FL_CURSOR_E}, {"FL_CURSOR_SE",0,choice_cb,(void*)FL_CURSOR_SE}, {"FL_CURSOR_S",0,choice_cb,(void*)FL_CURSOR_S}, {"FL_CURSOR_SW",0,choice_cb,(void*)FL_CURSOR_SW}, {"FL_CURSOR_W",0,choice_cb,(void*)FL_CURSOR_W}, {"FL_CURSOR_NW",0,choice_cb,(void*)FL_CURSOR_NW}, {"FL_CURSOR_NONE",0,choice_cb,(void*)FL_CURSOR_NONE}, {"custom cursor",0,custom_cb,NULL}, {0} }; void setcursor(Fl_Widget *o, void *) { Fl_Hor_Value_Slider *slider = (Fl_Hor_Value_Slider *)o; cursor = Fl_Cursor((int)slider->value()); fl_cursor(cursor); } // draw the label without any ^C or \nnn conversions: class CharBox : public Fl_Box { void draw() FL_OVERRIDE { fl_font(FL_FREE_FONT,14); fl_draw(label(), x()+w()/2, y()+h()/2); } public: CharBox(int X, int Y, int W, int H, const char* L) : Fl_Box(X,Y,W,H,L) {} }; int main(int argc, char **argv) { Fl_Double_Window window(400,300); Fl_Choice choice(80,100,200,25,"Cursor:"); choice.menu(choices); choice.callback(choice_cb); choice.when(FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED); Fl_Hor_Value_Slider slider1(80,180,310,30,"Cursor:"); cursor_slider = &slider1; slider1.align(FL_ALIGN_LEFT); slider1.step(1); slider1.precision(0); slider1.bounds(0,255); slider1.value(0); slider1.callback(setcursor); slider1.value(cursor); #if 0 // draw the manual's diagram of cursors... window.size(400,800); int y = 300; Fl::set_font(FL_FREE_FONT, "cursor"); char buf[100]; char *p = buf; for (Fl_Menu* m = choices; m->label(); m++) { Fl_Box* b = new Fl_Box(35,y,150,25,m->label()); b->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); int n = (int)(m->argument()); if (n == FL_CURSOR_NONE) break; if (n == FL_CURSOR_DEFAULT) n = FL_CURSOR_ARROW; p[0] = (char)((n-1)*2); p[1] = 0; b = new CharBox(15,y,20,20,p); p+=2; y += 25; } #endif window.resizable(window); window.end(); window.show(argc,argv); return Fl::run(); } fltk-1.4.3/test/resize.fl0000644000175000017500000000265215004135251015415 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} Function {} {open } { Fl_Window {} {open selected xywh {479 310 366 261} type Double resizable visible } { Fl_Button {} { label {@<-} callback {Fl_Window* w = o->window(); w->position(w->x()-50,w->y());} xywh {20 40 40 40} } Fl_Button {} { label {@2->} callback {Fl_Window* w = o->window(); w->position(w->x(),w->y()+50);} xywh {60 80 40 40} } Fl_Button {} { label {@->} callback {Fl_Window* w = o->window(); w->position(w->x()+50,w->y());} xywh {100 40 40 40} } Fl_Button {} { label {@8->} callback {Fl_Window* w = o->window(); w->position(w->x(),w->y()-50);} xywh {60 0 40 40} } Fl_Button {} { label grow callback {Fl_Window* w = o->window(); w->size(w->w()+20, w->h()+20);} xywh {30 130 110 40} labelfont 1 labelsize 18 } Fl_Button {} { label shrink callback {Fl_Window* w = o->window(); w->size(w->w()-20, w->h()-20);} xywh {30 190 110 40} labelfont 1 labelsize 18 } Fl_Box {} { label {This is a test of program-generated resize() of a window. The window should move or resize once when each button is clicked. The program and window manager should not go into fits echoing resizes back and forth!} xywh {150 10 160 220} box BORDER_BOX align 148 } } } fltk-1.4.3/test/README-unittests.txt0000644000175000017500000000726515004135251017334 0ustar albrechtalbrechtHOW TO CREATE A NEW UNIT TEST ----------------------------- 1) Create your new test/unittest_xxx.cxx file (or use an existing one) 2) In your new cxx file, define a class derived from Fl_Group for your test (e.g. Ut_Test_Foo). The following should be a good starting template for the new file: * * * // ..standard fltk src header goes here.. #include "unittests.h" // Needed for UnitTest class and enum constant // Widgets this test will use #include #include // Your class to do the test // Your test must do its work within the UT_TESTAREA_XYWH area. // class Ut_Test_Foo : public Fl_Group { public: static Fl_Widget *create() { return new Ut_Test_Foo(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } Ut_Test_Foo(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { .. } }; // Create an instance of your class and register it with the main app UnitTest testfoo(UT_TEST_FOO, "My foo tester", Ut_Test_Foo::create); * * * Note that the last line in the above is what "registers" your new test with the unittests main application: UnitTest testfoo(UT_TEST_FOO, "My foo tester", Ut_Test_Foo::create); ------- ----------- ------------- ------------------- | | | | | | | Your class's static create() method | | | | | Text name for your test that shows up in unittests browser | | | This will be defined as an enum constant in the next step | The global instance name for your test. 3) Add an entry anywhere to the enum {} at the top of the unittests.h file. Example: enum { UT_TEST_ABOUT = 0, UT_TEST_POINTS, ... UT_TEST_FOO, <-- ADD YOUR TEST CLASS NAME IN ALL CAPS ... }; 4) Add your new unittest_xxx.cxx file to: a) test/CMakeLists.txt -- cmake needs this b) test/Makefile -- configure needs this (?) You should then be able to use cmake to create a build directory that builds with your new test. e.g. mkdir build cmake .. ..and from there, you should be able to go through the common edit/make/run development cycle: make -j 4 <-- should build bin/test/unittests with your test bin/test/unittests <-- run unittests to check your work 5) That's it! GENERAL TEST PRACTICES ---------------------- UT_TESTAREA_X, Y, W, and H will be the position and size of the Group, and that the Group must expect to be resized, but not any smaller than that area. Try to include documentation that briefly recommends to the other devs what this test does and what to watch out for. If docs won't fit into the test area, either add a "?" button, or use a tooltip(). TEST REGISTRATION NOTES ----------------------- The mechanism of using an enum and the UnitTest instance allows us to ignore a test by simply not linking it (e.g. by choice with cmake). No changes to the source code are needed. The enumeration still needs an entry for everything that *may* be linked, even if it is not. fltk-1.4.3/test/CubeView.h0000644000175000017500000000642615004135251015456 0ustar albrechtalbrecht// // CubeView class definitions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef CUBEVIEW_H #define CUBEVIEW_H 1 // Note: The CubeView demo program can only be built if // (1) '' can be included (FLTK build) *or* // (2) 'HAVE_GL' has been defined prior to including this header. // Define 'HAVE_GL=1' on the compiler commandline to build // this program w/o 'config.h' (needs FLTK lib with GL). #ifndef HAVE_GL #include #endif // Note to editor: the following code can and should be copied // to the fluid tutorial in 'documentation/src/fluid.dox' // *without* '#if HAVE_GL' preprocessor statements, leaving // only those parts where the condition is true. // [\code in documentation/src/fluid.dox] #include #if HAVE_GL #include #include #else #include #endif /* HAVE_GL */ #if HAVE_GL class CubeView : public Fl_Gl_Window { #else class CubeView : public Fl_Box { #endif /* HAVE_GL */ public: CubeView(int x, int y, int w, int h, const char *l = 0); // This value determines the scaling factor used to draw the cube. double size; /* Set the rotation about the vertical (y) axis. * * This function is called by the horizontal roller in * CubeViewUI and the initialize button in CubeViewUI. */ void v_angle(double angle) { vAng = angle; } // Return the rotation about the vertical (y) axis. double v_angle() const { return vAng; } /* Set the rotation about the horizontal (x) axis. * * This function is called by the vertical roller in * CubeViewUI and the initialize button in CubeViewUI. */ void h_angle(double angle) { hAng = angle; } // The rotation about the horizontal (x) axis. double h_angle() const { return hAng; } /* Sets the x shift of the cube view camera. * * This function is called by the slider in CubeViewUI * and the initialize button in CubeViewUI. */ void panx(double x) { xshift = x; } /* Sets the y shift of the cube view camera. * * This function is called by the slider in CubeViewUI * and the initialize button in CubeViewUI. */ void pany(double y) { yshift = y; } #if HAVE_GL /* The widget class draw() FL_OVERRIDE. * * The draw() function initializes Gl for another round of * drawing, then calls specialized functions for drawing each * of the entities displayed in the cube view. */ void draw() FL_OVERRIDE; #endif /* HAVE_GL */ private: /* Draw the cube boundaries. * * Draw the faces of the cube using the boxv[] vertices, * using GL_LINE_LOOP for the faces. */ #if HAVE_GL void drawCube(); #else void drawCube() {} #endif /* HAVE_GL */ double vAng, hAng; double xshift, yshift; float boxv0[3]; float boxv1[3]; float boxv2[3]; float boxv3[3]; float boxv4[3]; float boxv5[3]; float boxv6[3]; float boxv7[3]; }; // [\endcode in documentation/src/fluid.dox] #endif // CUBEVIEW_H fltk-1.4.3/test/scroll.cxx0000644000175000017500000000663515004135251015620 0ustar albrechtalbrecht// // Fl_Scroll test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include class Drawing : public Fl_Widget { void draw() FL_OVERRIDE; public: Drawing(int X,int Y,int W,int H,const char* L) : Fl_Widget(X,Y,W,H,L) { align(FL_ALIGN_TOP); box(FL_FLAT_BOX); color(FL_WHITE); } }; void Drawing::draw() { draw_box(); fl_push_matrix(); fl_translate(x()+w()/2, y()+h()/2); fl_scale(w()/2, h()/2); fl_color(FL_BLACK); for (int i = 0; i < 20; i++) { for (int j = i+1; j < 20; j++) { fl_begin_line(); fl_vertex(cos(M_PI*i/10+.1), sin(M_PI*i/10+.1)); fl_vertex(cos(M_PI*j/10+.1), sin(M_PI*j/10+.1)); fl_end_line(); } } fl_pop_matrix(); } Fl_Scroll* thescroll; void box_cb(Fl_Widget* o, void*) { thescroll->box(((Fl_Button*)o)->value() ? FL_DOWN_FRAME : FL_NO_BOX); thescroll->redraw(); } void type_cb(Fl_Widget*, void* v) { thescroll->type((uchar)((fl_intptr_t)v)); thescroll->redraw(); } Fl_Menu_Item choices[] = { {"0", 0, type_cb, (void*)0}, {"HORIZONTAL", 0, type_cb, (void*)Fl_Scroll::HORIZONTAL}, {"VERTICAL", 0, type_cb, (void*)Fl_Scroll::VERTICAL}, {"BOTH", 0, type_cb, (void*)Fl_Scroll::BOTH}, {"HORIZONTAL_ALWAYS", 0, type_cb, (void*)Fl_Scroll::HORIZONTAL_ALWAYS}, {"VERTICAL_ALWAYS", 0, type_cb, (void*)Fl_Scroll::VERTICAL_ALWAYS}, {"BOTH_ALWAYS", 0, type_cb, (void*)Fl_Scroll::BOTH_ALWAYS}, {0} }; void align_cb(Fl_Widget*, void* v) { thescroll->scrollbar.align((uchar)((fl_intptr_t)v)); thescroll->redraw(); } Fl_Menu_Item align_choices[] = { {"left+top", 0, align_cb, (void*)(FL_ALIGN_LEFT+FL_ALIGN_TOP)}, {"left+bottom", 0, align_cb, (void*)(FL_ALIGN_LEFT+FL_ALIGN_BOTTOM)}, {"right+top", 0, align_cb, (void*)(FL_ALIGN_RIGHT+FL_ALIGN_TOP)}, {"right+bottom", 0, align_cb, (void*)(FL_ALIGN_RIGHT+FL_ALIGN_BOTTOM)}, {0} }; int main(int argc, char** argv) { Fl_Window window(5*75,400); window.box(FL_NO_BOX); Fl_Scroll scroll(0,0,5*75,300); int n = 0; for (int y=0; y<16; y++) for (int x=0; x<5; x++) { char buf[20]; snprintf(buf, 20,"%d",n++); Fl_Button* b = new Fl_Button(x*75,y*25+(y>=8?5*75:0),75,25); b->copy_label(buf); b->color(n); b->labelcolor(FL_WHITE); } Drawing drawing(0,8*25,5*75,5*75,0); scroll.end(); window.resizable(scroll); Fl_Box box(0,300,5*75,window.h()-300); // gray area below the scroll box.box(FL_FLAT_BOX); Fl_Light_Button but1(150, 310, 200, 25, "box"); but1.callback(box_cb); Fl_Choice choice(150, 335, 200, 25, "type():"); choice.menu(choices); choice.value(3); Fl_Choice achoice(150, 360, 200, 25, "scrollbar.align():"); achoice.menu(align_choices); achoice.value(3); thescroll = &scroll; //scroll.box(FL_DOWN_BOX); //scroll.type(Fl_Scroll::VERTICAL); window.end(); window.show(argc,argv); return Fl::run(); } fltk-1.4.3/test/unittest_images.cxx0000644000175000017500000002604215004135251017520 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include #include #include #include #include #include // Note: currently (March 2010) fl_draw_image() supports transparency with // alpha channel only on Apple (Mac OS X), but Fl_RGB_Image->draw() // supports transparency on all platforms ! // //------- test the image drawing capabilities of this implementation ---------- // // Parameters for fine tuning for developers. // Default values: CB=1, DX=0, IMG=1, LX=0, FLIPH=0 static int cb = 1; // 1 to show the checker board background for alpha images, // 0 otherwise static int dx = 0; // additional (undefined (0)) pixels per line, must be >= 0 // ignored (irrelevant), if LX == 0 (see below) static int img = 1; // 1 to use Fl_RGB_Image for drawing images with transparency, // 0 to use fl_draw_image() instead. // Note: as of Feb 2016, only 1 (Fl_RGB_Image) works with // alpha channel, 0 (fl_draw_image()) ignores the alpha // channel (FLTK 1.3.x). // There are plans to support transparency (alpha channel) // in fl_draw_image() in FLTK 1.4.0 and/or later. static int lx = 0; // 0 for default: ld() = 0, i.e. ld() defaults (internally) to w()*d() // +1: ld() = (w() + DX) * d() // -1 to flip image vertically: ld() = - ((w() + DX) * d()) static int flip_h = 0; // 1 = Flip image horizontally (only if IMG == 0) // 0 = Draw image normal, w/o horizontal flipping // ---------------------------------------------------------------------- // Test scenario for fl_draw_image() with pos. and neg. d and ld args: // ---------------------------------------------------------------------- // (1) set img = 0: normal, but w/o transparency: no checker board // (2) set lx = -1: images flipped vertically // (3) set flip_h = 1: images flipped vertically and horizontally // (4) set lx = 0: images flipped horizontally // (5) set flip_h = 0, IMG = 1: back to default (with transparency) // ---------------------------------------------------------------------- class Ut_Image_Test : public Fl_Group { static void build_imgs() { int x, y; uchar *dg, *dga, *drgb, *drgba; dg = img_gray = img_gray_base = (uchar*)malloc((128+dx)*128*1); dga = img_gray_a = img_gray_a_base = (uchar*)malloc((128+dx)*128*2); drgb = img_rgb = img_rgb_base = (uchar*)malloc((128+dx)*128*3); drgba = img_rgba = img_rgba_base = (uchar*)malloc((128+dx)*128*4); for (y=0; y<128; y++) { for (x=0; x<128; x++) { *drgba++ = *drgb++ = *dga++ = *dg++ = y<<1; *drgba++ = *drgb++ = x<<1; *drgba++ = *drgb++ = (127-x)<<1; *drgba++ = *dga++ = x+y; } if (dx > 0 && lx != 0) { memset(dg, 0,1*dx); dg += 1*dx; memset(dga, 0,2*dx); dga += 2*dx; memset(drgb, 0,3*dx); drgb += 3*dx; memset(drgba,0,4*dx); drgba += 4*dx; } } if (lx<0) { img_gray += 127*(128+dx); img_gray_a += 127*(128+dx)*2; img_rgb += 127*(128+dx)*3; img_rgba += 127*(128+dx)*4; } if (flip_h && !img ) { img_gray += 127; img_gray_a += 127*2; img_rgb += 127*3; img_rgba += 127*4; } i_g = new Fl_RGB_Image (img_gray ,128,128,1,lx*(128+dx)); i_ga = new Fl_RGB_Image (img_gray_a,128,128,2,lx*(128+dx)*2); i_rgb = new Fl_RGB_Image (img_rgb, 128,128,3,lx*(128+dx)*3); i_rgba = new Fl_RGB_Image (img_rgba, 128,128,4,lx*(128+dx)*4); } // build_imgs method ends void free_images() { if (i_rgba) { delete i_rgba; i_rgba = 0; } if (i_rgb) { delete i_rgb; i_rgb = 0; } if (i_ga) { delete i_ga; i_ga = 0; } if (i_g) { delete i_g; i_g = 0; } if (img_rgba_base) { free (img_rgba_base); img_rgba_base = 0; } if (img_rgb_base) { free (img_rgb_base); img_rgb_base = 0; } if (img_gray_a_base) { free (img_gray_a_base); img_gray_a_base = 0; } if (img_gray_base) { free (img_gray_base); img_gray_base = 0; } } // end of free_images method static void refresh_imgs_CB(Fl_Widget*,void *data) { Ut_Image_Test* it = (Ut_Image_Test*)data; it->free_images(); // release the previous images // determine the state for the next images cb = it->ck_CB->value(); img = it->ck_IMG->value(); flip_h = it->ck_FLIPH->value(); // read the LX state radio buttons if (it->rb_LXp1->value()) { lx = 1; } else if (it->rb_LXm1->value()) { lx = (-1); } else { lx = 0; } // construct the next images build_imgs(); it->redraw(); } public: static Fl_Widget *create() { build_imgs(); return new Ut_Image_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } // create method ends static uchar *img_gray_base; static uchar *img_gray_a_base; static uchar *img_rgb_base; static uchar *img_rgba_base; static uchar *img_gray; static uchar *img_gray_a; static uchar *img_rgb; static uchar *img_rgba; static Fl_RGB_Image *i_g; static Fl_RGB_Image *i_ga; static Fl_RGB_Image *i_rgb; static Fl_RGB_Image *i_rgba; // control widgets Fl_Group *ctr_grp; Fl_Check_Button *ck_CB; Fl_Check_Button *ck_IMG; Fl_Check_Button *ck_FLIPH; Fl_Radio_Button *rb_LXm1; Fl_Radio_Button *rb_LX0; Fl_Radio_Button *rb_LXp1; Fl_Button *refresh; Ut_Image_Test(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { label("Testing Image Drawing\n\n" "This test renders four images, two of them with a checker board\n" "visible through the graphics. Color and gray gradients should be\n" "visible. This does not test any image formats such as JPEG."); align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_WRAP); box(FL_BORDER_BOX); int cw = 90; int ch = 200; int cx = x + w - cw - 5; int cy = y + 10; ctr_grp = new Fl_Group(cx, cy, cw, ch); ck_CB = new Fl_Check_Button(cx+10, cy+10, cw-20, 30, "CB"); ck_CB->callback(refresh_imgs_CB, (void*)this); ck_CB->value(cb); ck_CB->tooltip("1 to show the checker board background for alpha images,\n" "0 otherwise"); ck_IMG = new Fl_Check_Button(cx+10, cy+40, cw-20, 30, "IMG"); ck_IMG->callback(refresh_imgs_CB, (void*)this); ck_IMG->value(img); ck_IMG->tooltip("1 to use Fl_RGB_Image for drawing images with transparency,\n" "0 to use fl_draw_image() instead."); ck_FLIPH = new Fl_Check_Button(cx+10, cy+70, cw-20, 30, "FLIPH"); ck_FLIPH->callback(refresh_imgs_CB, (void*)this); ck_FLIPH->value(flip_h); ck_FLIPH->tooltip("1 = Flip image horizontally (only if IMG == 0)\n" "0 = Draw image normal, w/o horizontal flipping"); Fl_Group *rd_grp = new Fl_Group(cx+10, cy+100, cw-20, 90, "LX"); rb_LXp1 = new Fl_Radio_Button(cx+15, cy+105, cw-30, 20, "+1"); rb_LXp1->callback(refresh_imgs_CB, (void*)this); rb_LX0 = new Fl_Radio_Button(cx+15, cy+125, cw-30, 20, "0"); rb_LX0->callback(refresh_imgs_CB, (void*)this); rb_LX0->tooltip("0 for default: ld() = 0, i.e. ld() defaults (internally) to w()*d()\n" "+1: ld() = (w() + DX) * d()\n" "-1 to flip image vertically: ld() = - ((w() + DX) * d())"); rb_LXm1 = new Fl_Radio_Button(cx+15, cy+145, cw-30, 20, "-1"); rb_LXm1->callback(refresh_imgs_CB, (void*)this); rb_LX0->value(1); rd_grp->box(FL_BORDER_BOX); rd_grp->align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_CENTER); rd_grp->end(); ctr_grp->box(FL_BORDER_BOX); ctr_grp->end(); end(); // make sure this ImageTest group is closed } // constructor ends void draw() FL_OVERRIDE { Fl_Group::draw(); // top left: RGB int xx = x()+10, yy = y()+10; fl_color(FL_BLACK); fl_rect(xx, yy, 130, 130); if (img) { i_rgb->draw(xx+1,yy+1); } else { if (!flip_h) { fl_draw_image(img_rgb, xx+1, yy+1, 128, 128, 3, lx*((128+dx)*3)); } else { fl_draw_image(img_rgb, xx+1, yy+1, 128, 128,-3, lx*((128+dx)*3)); } } fl_draw("RGB", xx+134, yy+64); // bottom left: RGBA xx = x()+10; yy = y()+10+134; fl_color(FL_BLACK); fl_rect(xx, yy, 130, 130); // black frame fl_color(FL_WHITE); fl_rectf(xx+1, yy+1, 128, 128); // white background if (cb) { // checker board fl_color(FL_BLACK); fl_rectf(xx+65, yy+1, 64, 64); fl_color(FL_BLACK); fl_rectf(xx+1, yy+65, 64, 64); } if (img) { i_rgba->draw(xx+1,yy+1); } else { if (!flip_h) { fl_draw_image(img_rgba, xx+1, yy+1, 128, 128, 4, lx*((128+dx)*4)); } else { fl_draw_image(img_rgba, xx+1, yy+1, 128, 128,-4, lx*((128+dx)*4)); } } fl_color(FL_BLACK); fl_draw("RGBA", xx+134, yy+64); // top right: Gray xx = x()+10+200; yy = y()+10; fl_color(FL_BLACK); fl_rect(xx, yy, 130, 130); if (img) { i_g->draw(xx+1,yy+1); } else { if (!flip_h) { fl_draw_image(img_gray, xx+1, yy+1, 128, 128, 1, lx*((128+dx)*1)); } else { fl_draw_image(img_gray, xx+1, yy+1, 128, 128,-1, lx*((128+dx)*1)); } } fl_draw("Gray", xx+134, yy+64); // bottom right: Gray+Alpha xx = x()+10+200; yy = y()+10+134; fl_color(FL_BLACK); fl_rect(xx, yy, 130, 130); // black frame fl_color(FL_WHITE); fl_rectf(xx+1, yy+1, 128, 128); // white background if (cb) { // checker board fl_color(FL_BLACK); fl_rectf(xx+65, yy+1, 64, 64); fl_color(FL_BLACK); fl_rectf(xx+1, yy+65, 64, 64); } if (img) { i_ga->draw(xx+1,yy+1); } else { if (!flip_h) { fl_draw_image(img_gray_a, xx+1, yy+1, 128, 128, 2, lx*((128+dx)*2)); } else { fl_draw_image(img_gray_a, xx+1, yy+1, 128, 128,-2, lx*((128+dx)*2)); } } fl_color(FL_BLACK); fl_draw("Gray+Alpha", xx+134, yy+64); } // draw method end }; uchar *Ut_Image_Test::img_gray_base = 0; uchar *Ut_Image_Test::img_gray_a_base = 0; uchar *Ut_Image_Test::img_rgb_base = 0; uchar *Ut_Image_Test::img_rgba_base = 0; uchar *Ut_Image_Test::img_gray = 0; uchar *Ut_Image_Test::img_gray_a = 0; uchar *Ut_Image_Test::img_rgb = 0; uchar *Ut_Image_Test::img_rgba = 0; Fl_RGB_Image *Ut_Image_Test::i_g = 0; Fl_RGB_Image *Ut_Image_Test::i_ga = 0; Fl_RGB_Image *Ut_Image_Test::i_rgb = 0; Fl_RGB_Image *Ut_Image_Test::i_rgba = 0; UnitTest images(UT_TEST_IMAGES, "Drawing Images", Ut_Image_Test::create); fltk-1.4.3/test/unittest_viewport.cxx0000644000175000017500000000312115004135251020123 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include #include // //------- test viewport clipping ---------- // class Ut_Viewport_Test : public Fl_Box { public: static Fl_Widget *create() { return new Ut_Viewport_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } Ut_Viewport_Test(int x, int y, int w, int h) : Fl_Box(x, y, w, h) { label("Testing Viewport Alignment\n\n" "Only green lines should be visible.\n" "If red lines are visible in the corners of this window,\n" "your viewport alignment and clipping is off.\n" "If there is a space between the green lines and the window border,\n" "the viewport is off, but some clipping may be working.\n" "Also, your window size may be off to begin with."); align(FL_ALIGN_INSIDE|FL_ALIGN_CENTER|FL_ALIGN_WRAP); box(FL_BORDER_BOX); } void show() FL_OVERRIDE { Fl_Box::show(); mainwin->test_alignment(1); } void hide() FL_OVERRIDE { Fl_Box::hide(); mainwin->test_alignment(0); } }; UnitTest viewport(UT_TEST_VIEWPORT, "Viewport Test", Ut_Viewport_Test::create); fltk-1.4.3/test/navigation.cxx0000644000175000017500000000456015004135251016454 0ustar albrechtalbrecht// // Navigation test program for the Fast Light Tool Kit (FLTK). // // Silly test of navigation keys. This is not a recommended method of // laying out your panels! // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #define WIDTH 600 #define HEIGHT 300 #define GRID 25 void ToggleArrowFocus_CB(Fl_Widget *w, void*) { Fl_Light_Button *b = (Fl_Light_Button*)w; Fl::option(Fl::OPTION_ARROW_FOCUS, b->value() ? true : false); } int main(int argc, char **argv) { if (argc > 1) srand(atoi(argv[1])); Fl_Window window(WIDTH,HEIGHT+40,argv[0]); // Include a toggle button to control arrow focus Fl_Light_Button arrowfocus_butt(10,HEIGHT+10,130,20," Arrow Focus"); arrowfocus_butt.callback(ToggleArrowFocus_CB); arrowfocus_butt.value(Fl::option(Fl::OPTION_ARROW_FOCUS) ? 1 : 0); // use default arrowfocus_butt.tooltip("Control horizontal arrow key focus navigation behavior.\n" "e.g. Fl::OPTION_ARROW_FOCUS"); window.end(); // don't auto-add children for (int i = 0; i<10000; i++) { // make up a random size of widget: int x = rand()%(WIDTH/GRID+1) * GRID; int y = rand()%(HEIGHT/GRID+1) * GRID; int w = rand()%(WIDTH/GRID+1) * GRID; if (w < x) {w = x-w; x-=w;} else {w = w-x;} int h = rand()%(HEIGHT/GRID+1) * GRID; if (h < y) {h = y-h; y-=h;} else {h = h-y;} if (w < GRID || h < GRID || w < h) continue; // find where to insert it and see if it intersects something: Fl_Widget *j = 0; int n; for (n=0; n < window.children(); n++) { Fl_Widget *o = window.child(n); if (xx()+o->w() && x+w>o->x() && yy()+o->h() && y+h>o->y()) break; if ( !j && ( yy() || (y==o->y() && xx()) ) ) j = o; } // skip if intersection: if (n < window.children()) continue; window.insert(*(new Fl_Input(x,y,w,h)),j); } window.show(argc, argv); return Fl::run(); } fltk-1.4.3/test/resize-arrows.cxx0000644000175000017500000000323015004135251017122 0ustar albrechtalbrecht// // Resize example for use in the Fast Light Tool Kit (FLTK) documentation. // // See Article #415: How does resizing work? // https://www.fltk.org/articles.php?L415 // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "resize-arrows.h" #include Harrow::Harrow(int X, int Y, int W, int H, const char *T) : Fl_Box(X, Y, W, H, T) { align(FL_ALIGN_BOTTOM); box(FL_NO_BOX); color(FL_WHITE); } void Harrow::draw() { Fl_Color old = fl_color(); int dx = 5, dy = 4; int my = y() + h() / 2; fl_rectf(x(), y(), w(), h(), FL_WHITE); fl_color(FL_BLACK); fl_polygon(x(), my, x() + dx, my - dy, x() + dx, my + dy); fl_line(x() + dx, my, x() + w() - dx, my); fl_polygon(x() + w(), my, x() + w() - dx, my + dy, x() + w() - dx, my - dy); fl_color(old); } Varrow::Varrow(int X, int Y, int W, int H, const char *T) : Fl_Box(X, Y, W, H, T) { align(FL_ALIGN_RIGHT); box(FL_NO_BOX); color(FL_WHITE); } void Varrow::draw() { Fl_Color old = fl_color(); int dx = 4, dy = 5; int mx = x() + w() / 2; fl_rectf(x(), y(), w(), h(), FL_WHITE); fl_color(FL_BLACK); fl_polygon(mx - dx, y() + dy, mx, y(), mx + dx, y() + dy); fl_line(mx, y() + dy, mx, y() + h() - dy); fl_polygon(mx - dx, y() + h() - dy, mx + dx, y() + h() - dy, mx, y() + h()); fl_color(old); } fltk-1.4.3/test/cube.cxx0000644000175000017500000003220715004135251015232 0ustar albrechtalbrecht// // OpenGL test program for the Fast Light Tool Kit (FLTK). // // Modified to have 2 cubes to test multiple OpenGL contexts // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Define 'HAVE_GL=1' on the compiler commandline to build this program // w/o 'config.h' (needs FLTK lib with GL), for instance like: // $ fltk-config --use-gl --compile cube.cxx -DHAVE_GL=1 // Use '-DHAVE_GL=0' to build and test w/o OpenGL support. #ifndef HAVE_GL #include // needed only for 'HAVE_GL' #endif // ... or uncomment the next line to test w/o OpenGL (see also above) // #undef HAVE_GL #include #include #include #include #include #include #include #include #include // demo printing #include // grid layout // Glocal constants and variables const double fps = 25.0; // desired frame rate (independent of speed slider) const double delay = 1.0/fps; // calculated timer delay int count = -2; // initialize loop (draw) counter int done = 0; // set to 1 in exit button callback Fl_Timestamp start; // taken at start of main or after reset #define DEBUG_TIMER (0) // >0: detailed debugging, see code (should be 0) #if (DEBUG_TIMER) const double dx = 0.001; // max. allowed deviation from delta time const double d_min = delay - dx; const double d_max = delay + dx; #endif // DEBUG_TIMER // Global pointers to widgets class cube_box; Fl_Window *form; Fl_Slider *speed, *size; Fl_Button *exit_button, *wire, *flat; cube_box *lt_cube, *rt_cube; #if !HAVE_GL class cube_box : public Fl_Box { public: double lasttime; int wire; double size; double speed; cube_box(int x,int y,int w,int h,const char *l=0) : Fl_Box(FL_DOWN_BOX,x,y,w,h,l) { label("This demo does\nnot work without GL"); } }; #else #include #include class cube_box : public Fl_Gl_Window { void draw() FL_OVERRIDE; int handle(int) FL_OVERRIDE; public: double lasttime; int wire; double size; double speed; cube_box(int x,int y,int w,int h,const char *l=0) : Fl_Gl_Window(x,y,w,h,l) { end(); lasttime = 0.0; box(FL_DOWN_FRAME); } }; /* The cube definition */ float v0[3] = {0.0, 0.0, 0.0}; float v1[3] = {1.0, 0.0, 0.0}; float v2[3] = {1.0, 1.0, 0.0}; float v3[3] = {0.0, 1.0, 0.0}; float v4[3] = {0.0, 0.0, 1.0}; float v5[3] = {1.0, 0.0, 1.0}; float v6[3] = {1.0, 1.0, 1.0}; float v7[3] = {0.0, 1.0, 1.0}; #define v3f(x) glVertex3fv(x) void drawcube(int wire) { /* Draw a colored cube */ glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); glColor3ub(0,0,255); v3f(v0); v3f(v1); v3f(v2); v3f(v3); glEnd(); glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); glColor3ub(0,255,255); v3f(v4); v3f(v5); v3f(v6); v3f(v7); glEnd(); glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); glColor3ub(255,0,255); v3f(v0); v3f(v1); v3f(v5); v3f(v4); glEnd(); glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); glColor3ub(255,255,0); v3f(v2); v3f(v3); v3f(v7); v3f(v6); glEnd(); glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); glColor3ub(0,255,0); v3f(v0); v3f(v4); v3f(v7); v3f(v3); glEnd(); glBegin(wire ? GL_LINE_LOOP : GL_POLYGON); glColor3ub(255,0,0); v3f(v1); v3f(v2); v3f(v6); v3f(v5); glEnd(); } void cube_box::draw() { lasttime = lasttime + speed; if (!valid()) { glLoadIdentity(); glViewport(0,0,pixel_w(),pixel_h()); glEnable(GL_DEPTH_TEST); glFrustum(-1,1,-1,1,2,10000); glTranslatef(0,0,-10); glClearColor(0.4f, 0.4f, 0.4f, 0); } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(float(lasttime*1.6),0,0,1); glRotatef(float(lasttime*4.2),1,0,0); glRotatef(float(lasttime*2.3),0,1,0); glTranslatef(-1.0f, 1.2f, -1.5f); glScalef(float(size),float(size),float(size)); drawcube(wire); glPopMatrix(); gl_color(FL_GRAY); glDisable(GL_DEPTH_TEST); gl_font(FL_HELVETICA_BOLD, 16 ); gl_draw(wire ? "Cube: wire" : "Cube: flat", -4.5f, -4.5f ); glEnable(GL_DEPTH_TEST); // draw additional FLTK widgets and graphics Fl_Gl_Window::draw(); } int cube_box::handle(int e) { switch (e) { case FL_ENTER: cursor(FL_CURSOR_CROSS); break; case FL_LEAVE: cursor(FL_CURSOR_DEFAULT); break; } return Fl_Gl_Window::handle(e); } // callback for overlay button (Fl_Button on OpenGL scene) void show_info_cb(Fl_Widget*, void*) { fl_message("This is an example of using FLTK widgets inside OpenGL windows.\n" "Multiple widgets can be added to Fl_Gl_Windows. They will be\n" "rendered as overlays over the scene."); } // overlay a button onto an OpenGL window (cube_box) // but don't change the current group Fl_Group::current() void overlay_button(cube_box *cube) { Fl_Group *curr = Fl_Group::current(); Fl_Group::current(0); Fl_Widget *w = new Fl_Button(10, 10, 120, 30, "FLTK over GL"); w->color(FL_FREE_COLOR); w->box(FL_BORDER_BOX); w->callback(show_info_cb); cube->add(w); Fl_Group::current(curr); } #endif // HAVE_GL void exit_cb(Fl_Widget *w = NULL, void *v = NULL) { #if HAVE_GL // display performance data on stdout and (for Windows!) in a message window double runtime = Fl::seconds_since(start); char buffer[120]; sprintf(buffer, "Count =%5d, time = %7.3f sec, fps = %5.2f, requested: %5.2f", count, runtime, count / runtime, fps); printf("%s\n", buffer); fflush(stdout); int choice = fl_choice("%s", "E&xit", "&Continue", "&Reset", buffer); switch(choice) { case 0: // exit program, close all windows done = 1; Fl::hide_all_windows(); break; case 2: // reset count = -2; printf("*** RESET ***\n"); fflush(stdout); break; default: // continue break; } #else done = 1; Fl::hide_all_windows(); #endif } #if HAVE_GL void timer_cb(void *data) { static Fl_Timestamp last = Fl::now(); static Fl_Timestamp now; count++; if (count == 0) { start = Fl::now(); last = start; } else if (count > 0) { now = Fl::now(); #if (DEBUG_TIMER) double delta = Fl::seconds_since(last); if ((delta < d_min || delta > d_max) && count > 1) { printf("Count =%5d, delay should be %7.5f but %7.5f is outside [%7.5f .. %7.5f]\n", count, delay, delta, d_min, d_max); fflush(stdout); } #endif // DEBUG_TIMER } #if (DEBUG_TIMER > 1) if (count > 0 && count <= DEBUG_TIMER) { // log the first N iterations double runtime = Fl::seconds_since(start); printf("Count =%5d, time = %7.3f sec, fps = %5.2f, requested: %5.2f\n", count, runtime, count / runtime, fps); fflush(stdout); } #endif // (DEBUG_TIMER > 1) lt_cube->redraw(); rt_cube->redraw(); Fl::repeat_timeout(delay, timer_cb); last = Fl::now(); } #endif // HAVE_GL void speed_cb(Fl_Widget *w, void *) { lt_cube->speed = rt_cube->speed = ((Fl_Slider *)w)->value(); } void size_cb(Fl_Widget *w, void *) { lt_cube->size = rt_cube->size = ((Fl_Slider *)w)->value(); } void flat_cb(Fl_Widget *w, void *) { int flat = ((Fl_Light_Button *)w)->value(); lt_cube->wire = 1 - flat; rt_cube->wire = flat; } void wire_cb(Fl_Widget *w, void *) { int wire = ((Fl_Light_Button *)w)->value(); lt_cube->wire = wire; rt_cube->wire = 1 - wire; } // print screen demo void print_cb(Fl_Widget *w, void *data) { Fl_Printer printer; Fl_Window *win = Fl::first_window(); if (!win) return; if (printer.start_job(1)) return; if (printer.start_page()) return; printer.scale(0.5, 0.5); printer.print_widget(win); printer.end_page(); printer.end_job(); } // Create a form that allows resizing for A and C (GL windows) with B fixed size/centered: // // |<--------------------------------------->|<---------------------->| // . lt_cube center : rt_cube . // . 350 100 : 350 . // . |<------------------->| |<-------->| |<------------------->| . // .................................................................... // : ....................... ............ ....................... : __ // : : : : : : : : // : : A : : B : : C : : h = 350 // : : : : : : : : // : :.....................: :..........: :.....................: : __ // :..................................................................: __ MARGIN // // | | | | | | // MARGIN GAP GAP #define MENUBAR_H 25 // menubar height #define MARGIN 20 // fixed margin around widgets #define GAP 20 // fixed gap between widgets void makeform(const char *name) { // Widget's XYWH's int form_w = 800 + 2 * MARGIN + 2 * GAP; // main window width int form_h = 350 + MENUBAR_H + 2 * MARGIN; // main window height // main window form = new Fl_Window(form_w, form_h, name); form->callback(exit_cb); // menu bar Fl_Sys_Menu_Bar *menubar = new Fl_Sys_Menu_Bar(0, 0, form_w, MENUBAR_H); menubar->add("File/Print window", FL_COMMAND+'p', print_cb); menubar->add("File/Quit", FL_COMMAND+'q', exit_cb); // Fl_Grid (layout) Fl_Grid *grid = new Fl_Grid(0, MENUBAR_H, form_w, 350 + 2 * MARGIN); grid->layout(4, 4, MARGIN, GAP); grid->box(FL_FLAT_BOX); // set column and row weights to control resizing behavior int cwe[] = {50, 0, 0, 50}; // column weights int rwe[] = { 0, 0, 50, 0}; // row weights grid->col_weight(cwe, 4); // set weights for resizing grid->row_weight(rwe, 4); // set weights for resizing // set non-default gaps for special layout purposes and labels grid->row_gap(0, 0); // no gap below wire button grid->row_gap(2, 50); // gap below sliders for labels // left GL window lt_cube = new cube_box(0, 0, 350, 350); // center group wire = new Fl_Radio_Light_Button( 0, 0, 100, 25, "Wire"); flat = new Fl_Radio_Light_Button( 0, 0, 100, 25, "Flat"); speed = new Fl_Slider(FL_VERT_SLIDER, 0, 0, 40, 90, "Speed"); size = new Fl_Slider(FL_VERT_SLIDER, 0, 0, 40, 90, "Size"); #if HAVE_GL exit_button = new Fl_Button( 0, 0, 100, 25, "Stats / E&xit"); #else exit_button = new Fl_Button( 0, 0, 100, 25, "E&xit"); #endif exit_button->callback(exit_cb); exit_button->tooltip("Display statistics (fps) and\nchoose to exit or continue\n"); // right GL window rt_cube = new cube_box(0, 0, 350, 350); // assign widgets to grid positions (R=row, C=col) and sizes // RS=rowspan, CS=colspan: R, C, RS, CS, optional alignment grid->widget(lt_cube, 0, 0, 4, 1); grid->widget(wire, 0, 1, 1, 2); grid->widget(flat, 1, 1, 1, 2); grid->widget(speed, 2, 1, 1, 1, FL_GRID_VERTICAL); grid->widget(size, 2, 2, 1, 1, FL_GRID_VERTICAL); grid->widget(exit_button, 3, 1, 1, 2); grid->widget(rt_cube, 0, 3, 4, 1); #if HAVE_GL overlay_button(lt_cube); // overlay a button onto the OpenGL window #endif // HAVE_GL form->end(); form->resizable(grid); form->size_range(form->w(), form->h()); // minimum window size } int main(int argc, char **argv) { Fl::use_high_res_GL(1); Fl::set_color(FL_FREE_COLOR, 255, 255, 0, 75); makeform(argv[0]); speed->bounds(6, 0); speed->value(lt_cube->speed = rt_cube->speed = 2.0); speed->callback(speed_cb); size->bounds(4, 0.2); size->value(lt_cube->size = rt_cube->size = 2.0); size->callback(size_cb); flat->value(1); flat->callback(flat_cb); wire->value(0); wire->callback(wire_cb); form->label("Cube Demo"); form->show(argc,argv); lt_cube->show(); rt_cube->show(); lt_cube->wire = wire->value(); rt_cube->wire = !wire->value(); lt_cube->size = rt_cube->size = size->value(); lt_cube->speed = rt_cube->speed = speed->value(); lt_cube->redraw(); rt_cube->redraw(); #if HAVE_GL #if (0) // share OpenGL contexts // This demonstrates how to manipulate OpenGL contexts. // In this case the same context is used by multiple windows (I'm not // sure if this is allowed on Win32, can somebody check?). // This fixes a bug on the XFree86 3.0 OpenGL where only one context per // program seems to work, but there are probably better uses for this! lt_cube->make_current(); // causes context to be created rt_cube->context(lt_cube->context()); // share the contexts #endif // share OpenGL contexts // with GL: use a timer for drawing and measure performance form->wait_for_expose(); Fl::add_timeout(0.1, timer_cb); // start timer int ret = Fl::run(); return ret; #else // w/o GL: no timer, no performance report return Fl::run(); #endif } fltk-1.4.3/test/message.cxx0000644000175000017500000000343015004135251015734 0ustar albrechtalbrecht// // Message test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include int main(int argc, char **argv) { Fl::scheme(NULL); Fl::args(argc, argv); Fl::get_system_colors(); fl_message("Spelling check sucessful, %d errors found with %g%% confidence", 1002, 100*(15/77.0)); fl_alert("Quantum fluctuations in the space-time continuum detected,\n" "you have %g seconds to comply.\n\n" "\"In physics, spacetime is any mathematical model that combines\n" "space and time into a single construct called the space-time\n" "continuum. Spacetime is usually interpreted with space being\n" "three-dimensional and time playing the role of the\n" "fourth dimension.\" - Wikipedia", 10.0); printf("fl_choice returned %d\n", fl_choice("Do you really want to %s?", "No", "Yes", 0L, "continue")); printf("fl_choice returned %d\n", fl_choice("Choose one of the following:","choice0","choice1","choice2")); const char *r; r = fl_input("Please enter a string for '%s':", "this is the default value", "testing"); printf("fl_input returned \"%s\"\n", r ? r : "NULL"); r = fl_password("Enter %s's password:", 0, "somebody"); printf("fl_password returned \"%s\"\n", r ? r : "NULL"); return 0; } fltk-1.4.3/test/tabs.fl0000644000175000017500000002535415004135251015051 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} Function {} {open } { Fl_Window foo_window { label {Comparison of Fl_Tab (left) vs. Fl_Wizard (right)} open xywh {330 402 660 400} type Double resizable visible } { Fl_Box {} { label {class Fl_Tabs} xywh {95 0 130 35} labeltype ENGRAVED_LABEL labelfont 1 } Fl_Tabs tabs_group { callback {Fl_Widget *sel_tab = o->value(); if (sel_tab) { printf("Callback called for tab \\"%s\\"\\n", sel_tab->label()); } else { printf("Callback called\\n"); }} open selected tooltip {the various index cards test different aspects of the Fl_Tabs widget} xywh {10 35 315 260} selection_color 4 labelcolor 7 resizable code0 {// tabs_group->handle_overflow(Fl_Tabs::OVERFLOW_PULLDOWN);} } { Fl_Group {} { label {Label&1} callback {if (Fl::callback_reason()==FL_REASON_CLOSED) o->parent()->remove(o);} tooltip {this tab tests correct keyboard navigation between text input fields} xywh {10 60 315 235} selection_color 1 when 16 resizable } { Fl_Input {} { label {input:} tooltip {This is the first input field} xywh {70 80 240 40} } Fl_Input {} { label {input2:} xywh {70 120 240 30} code0 {o->tooltip("");} } Fl_Input {} { label {input3:} xywh {70 150 240 80} } } Fl_Group {} { label {tab&2} callback {if (Fl::callback_reason()==FL_REASON_CLOSED) o->parent()->remove(o);} tooltip {tab2 tests among other things the cooperation of modal windows and tabs} xywh {10 60 315 235} selection_color 2 when 16 hide } { Fl_Button {} { label button1 callback {fl_message("Test to see if this modal window prevents you from " "changing the tabs. It should.");} xywh {20 85 100 30} code0 {\#include } } Fl_Input {} { label {input in box2} xywh {130 130 175 30} } Fl_Button {} { label {This is stuff inside the Fl_Group "tab2"} xywh {25 170 280 30} } Fl_Button {} { label {Test event blocking by modal window} callback {fl_message("Make sure you cannot change the tabs while this modal window is up");} xywh {25 200 280 30} code0 {\#include } } } Fl_Group {} { label {tab&3} callback {if (Fl::callback_reason()==FL_REASON_CLOSED) o->parent()->remove(o);} tooltip {tab3 checks for correct keyboard navigation} xywh {10 60 315 235} selection_color 3 when 16 hide } { Fl_Button {} { label button2 xywh {20 80 60 80} } Fl_Button {} { label button xywh {80 80 60 80} } Fl_Button {} { label button xywh {140 80 60 80} } } Fl_Group {} { label {&tab4} callback {if (Fl::callback_reason()==FL_REASON_CLOSED) o->parent()->remove(o);} tooltip {this tab shows the issue of indicating a selected tab if the tab layouts are very similar} xywh {10 60 315 235} selection_color 5 labeltype ENGRAVED_LABEL labelfont 2 when 16 hide } { Fl_Button {} { label button2 xywh {20 80 60 120} } Fl_Button {} { label button xywh {80 80 60 120} } Fl_Button {} { label button xywh {140 80 60 120} } } Fl_Group {} { label {@fileprint &print} tooltip {tab5 verifies if visibility requests are handled correctly} xywh {10 60 315 235} hide } { Fl_Button {} { label button2 tooltip {button2 has a different tooltip than tab5} xywh {20 80 60 80} } Fl_Button {} { label button xywh {90 80 60 80} } Fl_Clock {} { label {Make sure this clock does not use processor time when this tab is hidden or window is iconized} xywh {185 80 120 120} box OSHADOW_BOX color 238 selection_color 0 labelfont 8 labelsize 10 align 130 } Fl_Group {} {open xywh {20 190 40 55} box THIN_DOWN_BOX color 173 align 16 class Fl_Window } {} Fl_Group {} { label {subwindows:} open xywh {65 190 40 55} box THIN_DOWN_BOX color 167 class Fl_Window } {} Fl_Group {} {open xywh {110 190 40 55} box THIN_DOWN_BOX color 239 align 16 class Fl_Window } {} } } Fl_Box {} { label {class Fl_Wizard} xywh {410 0 130 35} labeltype ENGRAVED_LABEL labelfont 1 } Fl_Wizard wWizard {open xywh {330 35 320 260} } { Fl_Group {} { label Label1 tooltip {this tab tests correct keyboard navigation between text input fields} xywh {330 60 320 235} selection_color 1 hide resizable } { Fl_Input {} { label {input:} tooltip {This is the first input field} xywh {390 80 240 40} } Fl_Input {} { label {input2:} xywh {390 120 240 30} code0 {o->tooltip("");} } Fl_Input {} { label {input3:} xywh {390 150 240 80} } } Fl_Group {} { label tab2 tooltip {tab2 tests among other things the cooperation of modal windows and tabs} xywh {330 60 320 235} selection_color 2 } { Fl_Button {} { label button1 callback {fl_message("Test to see if this modal window prevents you from " "changing the tabs. It should.");} xywh {350 85 100 30} code0 {\#include } } Fl_Input {} { label {input in box2} xywh {455 130 175 30} } Fl_Button {} { label {This is stuff inside the Fl_Group "tab2"} xywh {350 170 280 30} } Fl_Button {} { label {Test event blocking by modal window} callback {fl_message("Make sure you cannot change the tabs while this modal window is up");} xywh {350 200 280 30} code0 {\#include } } } Fl_Group {} { label tab3 tooltip {tab3 checks for correct keyboard navigation} xywh {330 60 320 235} selection_color 3 hide } { Fl_Button {} { label button2 xywh {350 80 60 80} } Fl_Button {} { label button xywh {410 80 60 80} } Fl_Button {} { label button xywh {470 80 60 80} } } Fl_Group {} { label tab4 tooltip {this tab shows the issue of indicating a selected tab if the tab layouts are very similar} xywh {330 60 320 235} selection_color 5 labelfont 2 hide } { Fl_Button {} { label button2 xywh {350 80 60 120} } Fl_Button {} { label button xywh {410 80 60 120} } Fl_Button {} { label button xywh {470 80 60 120} } } Fl_Group {} { label { tab5 } open tooltip {tab5 verifies if visibility requests are handled correctly} xywh {330 60 320 235} labeltype ENGRAVED_LABEL hide } { Fl_Button {} { label button2 tooltip {button2 has a different tooltip than tab5} xywh {350 80 60 80} } Fl_Button {} { label button xywh {420 80 60 80} } Fl_Clock {} { label {Make sure this clock does not use processor time when this tab is hidden or window is iconized} xywh {510 80 120 120} box OSHADOW_BOX color 238 selection_color 0 labelfont 8 labelsize 10 align 130 } Fl_Group {} {open xywh {350 190 40 55} box THIN_DOWN_BOX color 173 align 16 class Fl_Window } {} Fl_Group {} { label {subwindows:} open xywh {395 190 40 55} box THIN_DOWN_BOX color 167 class Fl_Window } {} Fl_Group {} {open xywh {440 190 40 55} box THIN_DOWN_BOX color 239 align 16 class Fl_Window } {} } } Fl_Group {} { xywh {410 305 130 25} } { Fl_Button {} { label {@|<} callback {wWizard->value(wWizard->child(0));} tooltip {go to first page [Home]} xywh {410 305 30 25} shortcut 0xff50 } Fl_Button {} { label {@<} callback {wWizard->prev();} tooltip {go to previous page [left arrow]} xywh {440 305 30 25} shortcut 0xff51 } Fl_Button {} { label {@>} callback {wWizard->next();} tooltip {go to next page in wizard [right arrow]} xywh {480 305 30 25} shortcut 0xff53 } Fl_Button {} { label {@>|} callback {int last = wWizard->children()-1; wWizard->value(wWizard->child(last));} tooltip {go to last page [End]} xywh {510 305 30 25} shortcut 0xff57 } } Fl_Button {} { label {add tab} callback {static int n = 6; int X = tabs_group->x(), Y = tabs_group->y()+25; int W = tabs_group->w(), H = tabs_group->h()-25; Fl_Group::current(NULL); char buf[64]; snprintf(buf, 62, "tab%d", n); Fl_Group* new_tab = new Fl_Group(X, Y, W, H); new_tab->copy_label(buf); new_tab->when(FL_WHEN_CLOSED); new_tab->callback((Fl_Callback*)cb_tab); snprintf(buf, 62, "Empty tab %d.", n); Fl_Box* box = new Fl_Box(X+5, Y+5, W-10, H-10); box->copy_label(buf); box->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE)); tabs_group->add(new_tab); n++;} tooltip {Add more tabs to check overflow handling.} xywh {60 309 70 25} } Fl_Choice {} { label {overflow:} open tooltip {Change how Fl_Tabs handles more tabs than fit into the tabs space.} xywh {212 309 95 25} down_box BORDER_BOX } { MenuItem {} { label compress callback {tabs_group->handle_overflow(Fl_Tabs::OVERFLOW_COMPRESS);} xywh {0 0 31 20} } MenuItem {} { label clip callback {tabs_group->handle_overflow(Fl_Tabs::OVERFLOW_CLIP);} xywh {0 0 31 20} } MenuItem {} { label pulldown callback {tabs_group->handle_overflow(Fl_Tabs::OVERFLOW_PULLDOWN);} xywh {0 0 31 20} } MenuItem {} { label drag callback {tabs_group->handle_overflow(Fl_Tabs::OVERFLOW_DRAG);} xywh {0 0 31 20} } } Fl_Input {} { label {input:} xywh {60 345 250 25} } Fl_Button {} { label cancel callback {exit(1);} xywh {490 345 70 30} code0 {\#include } } Fl_Return_Button {} { label OK callback {exit(0);} xywh {570 345 70 30} code0 {\#include } } } } fltk-1.4.3/test/mandelbrot_ui.fl0000644000175000017500000000471315004135251016740 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} decl {\#include "mandelbrot.h"} {public local } decl {\#include } {private local } class Drawing_Window {open } { Function {make_window()} {open return_type void } { Fl_Window window {open xywh {255 66 450 520} type Single resizable code0 {o->size_range(220,220);} visible } { Fl_Box d { user_data this user_data_type {void*} xywh {20 80 410 430} box DOWN_BOX color 0 selection_color 47 resizable class Drawing_Area } Fl_Input x_input { label {x:} callback {d->X = atof(o->value());; d->new_display();} xywh {30 15 125 30} type Float box THIN_DOWN_BOX color 48 selection_color 7 labelfont 11 labelsize 16 textfont 11 textsize 12 code0 {o->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);} } Fl_Input y_input { label {y:} callback {d->Y = atof(o->value()); d->new_display();} xywh {175 15 125 30} type Float box THIN_DOWN_BOX color 48 selection_color 7 labelfont 11 labelsize 16 textfont 11 textsize 12 code0 {o->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);} } Fl_Input w_input { label {w:} callback {d->scale = atof(o->value()); d->new_display();} xywh {325 15 105 30} type Float box THIN_DOWN_BOX color 48 selection_color 7 labelfont 11 labelsize 16 textfont 11 textsize 12 code0 {o->when(FL_WHEN_ENTER_KEY|FL_WHEN_RELEASE);} } Fl_Slider {} { label {brightness:} callback {d->brightness = int(o->value()); d->new_display();} xywh {80 50 160 15} type Horizontal box THIN_DOWN_BOX labelsize 10 align 4 step 1 slider_size 0.1 code0 {o->bounds(0,d->MAX_BRIGHTNESS);} code2 {o->value(d->brightness);} code3 {o->slider(FL_UP_BOX);} } Fl_Box {} { label {left click: zoom out, drag: zoom in right click: Julia set, ctrl-M: mode, ctrl-P: Print} selected xywh {240 50 190 30} labelsize 8 align 24 } Fl_Slider {} { label {iterations:} callback {d->iterations = 1<value()); d->new_display();} xywh {80 65 160 15} type Horizontal box THIN_DOWN_BOX labelsize 10 align 4 step 1 slider_size 0.1 code0 {o->bounds(1,d->MAX_ITERATIONS);} code2 {o->value(d->DEFAULT_ITERATIONS);} code3 {o->slider(FL_UP_BOX);} } } } decl {void update_label();} {public local } } fltk-1.4.3/test/keyboard.cxx0000644000175000017500000001174015004135251016113 0ustar albrechtalbrecht// // Keyboard/event test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // Continuously display FLTK's event state. // // Known bugs: // // X insists on reporting the state *before* the shift key was // pressed, rather than after, on shift key events. I fixed this for // the mouse buttons, but it did not seem worth it for shift. // // X servers do not agree about any shift flags after except shift, ctrl, // lock, and alt. They may also not agree about the symbols for the extra // keys Micro$oft put on the keyboard. // // On IRIX the backslash key does not work. A bug in XKeysymToKeycode? // #include "keyboard_ui.h" #include // these are used to identify which buttons are which: void key_cb(Fl_Button*, void*) {} void shift_cb(Fl_Button*, void*) {} void wheel_cb(Fl_Dial*, void*) {} // This is used to stop Esc from exiting the program. // Other keystrokes like zoom keys (ctrl/+/-/0) must pass though. int handle(int e) { if (e == FL_SHORTCUT && Fl::event_key() == FL_Escape) return 1; return 0; } int MyWindow::handle(int msg) { if (msg == FL_MOUSEWHEEL) { roller_x->value( roller_x->value() + Fl::e_dx * roller_x->step() ); roller_y->value( roller_y->value() + Fl::e_dy * roller_y->step() ); return 1; } return 0; } struct keycode_table { int n; // key code const char* text; // key name } key_table[] = { { FL_Escape, "FL_Escape"}, { FL_BackSpace, "FL_BackSpace"}, { FL_Tab, "FL_Tab"}, { FL_Iso_Key, "FL_Iso_Key"}, { FL_Enter, "FL_Enter"}, { FL_Print, "FL_Print"}, { FL_Scroll_Lock, "FL_Scroll_Lock"}, { FL_Pause, "FL_Pause"}, { FL_Insert, "FL_Insert"}, { FL_Home, "FL_Home"}, { FL_Page_Up, "FL_Page_Up"}, { FL_Delete, "FL_Delete"}, { FL_End, "FL_End"}, { FL_Page_Down, "FL_Page_Down"}, { FL_Left, "FL_Left"}, { FL_Up, "FL_Up"}, { FL_Right, "FL_Right"}, { FL_Down, "FL_Down"}, { FL_Shift_L, "FL_Shift_L"}, { FL_Shift_R, "FL_Shift_R"}, { FL_Control_L, "FL_Control_L"}, { FL_Control_R, "FL_Control_R"}, { FL_Caps_Lock, "FL_Caps_Lock"}, { FL_Alt_L, "FL_Alt_L"}, { FL_Alt_R, "FL_Alt_R"}, { FL_Meta_L, "FL_Meta_L"}, { FL_Meta_R, "FL_Meta_R"}, { FL_Menu, "FL_Menu"}, { FL_Help, "FL_Help"}, { FL_Num_Lock, "FL_Num_Lock"}, { FL_KP_Enter, "FL_KP_Enter"}, { FL_Alt_Gr, "FL_Alt_Gr"} }; int main(int argc, char** argv) { Fl::add_handler(handle); MyWindow *window = make_window(); window->show(argc,argv); while (Fl::wait()) { const char *str; // update all the buttons with the current key and shift state: for (int c = 0; c < window->children(); c++) { Fl_Widget* b = window->child(c); if (b->callback() == (Fl_Callback*)key_cb) { int i = (int)b->argument(); if (!i) i = b->label()[0]; Fl_Button *btn = ((Fl_Button*)b); int state = Fl::event_key(i); if (btn->value()!=state) btn->value(state); } else if (b->callback() == (Fl_Callback*)shift_cb) { int i = (int)b->argument(); Fl_Button *btn = ((Fl_Button*)b); int state = Fl::event_state(i); if (btn->value()!=state) btn->value(state); } } // figure out the keyname: char buffer[100]; const char *keyname = buffer; int k = Fl::event_key(); if (!k) keyname = "0"; else if (k < 128) { // ASCII snprintf(buffer, sizeof(buffer), "'%c'", k); } else if (k >= 0xa0 && k <= 0xff) { // ISO-8859-1 (international keyboards) char key[8]; int kl = fl_utf8encode((unsigned)k, key); key[kl] = '\0'; snprintf(buffer, sizeof(buffer), "'%s'", key); } else if (k > FL_F && k <= FL_F_Last) { snprintf(buffer, sizeof(buffer), "FL_F+%d", k - FL_F); } else if (k >= FL_KP && k <= FL_KP_Last) { snprintf(buffer, sizeof(buffer), "FL_KP+'%c'", k-FL_KP); } else if (k >= FL_Button && k <= FL_Button+7) { snprintf(buffer, sizeof(buffer), "FL_Button+%d", k-FL_Button); } else { snprintf(buffer, sizeof(buffer), "0x%04x", k); for (int i = 0; i < int(sizeof(key_table)/sizeof(*key_table)); i++) if (key_table[i].n == k) {keyname = key_table[i].text; break;} } if (strcmp(key_output->value(), keyname)) key_output->value(keyname); str = Fl::event_text(); if (strcmp(text_output->value(), str)) text_output->value(str); } return 0; } fltk-1.4.3/test/browser.cxx0000644000175000017500000001440115004135251015773 0ustar albrechtalbrecht// // Browser test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* This is a test of how the browser draws lines. This is a second line. This is a third. That was a blank line above this. @r@_Right justify @c@_Center justify @_Left justify @bBold text @iItalic text @b@iBold Italic @fFixed width @f@bBold Fixed @f@iItalic Fixed @f@i@bBold Italic Fixed @lLarge @l@bLarge bold @sSmall @s@bSmall bold @s@iSmall italic @s@i@bSmall italic bold @uunderscore @C1RED @C2Green @C4Blue @N@.Inactive @@ start line with '@' @.@ alternative start line with '@' @l@@ start tall line with '@' @s@@ start small line with '@' #s## start line with '#' #s#.# alternative start line with '#' You should try different browser types: Fl_Browser Fl_Select_Browser Fl_Hold_Browser Fl_Multi_Browser */ #include #include #include #include #include #include #include #include #include #include #include #include Fl_Select_Browser *browser; Fl_Button *top, *bottom, *middle, *visible, *swap, *sort; Fl_Choice *btype; Fl_Choice *wtype; Fl_Int_Input *field; Fl_Terminal *tty = 0; typedef struct { const char *name; Fl_When wvalue; } WhenItem; // FL_WHEN chooser.. WhenItem when_items[] = { { "FL_WHEN_NEVER", FL_WHEN_NEVER }, { "FL_WHEN_CHANGED", FL_WHEN_CHANGED }, { "FL_WHEN_NOT_CHANGED", FL_WHEN_NOT_CHANGED }, { "FL_WHEN_RELEASE", FL_WHEN_RELEASE }, { "FL_WHEN_RELEASE_ALWAYS", FL_WHEN_RELEASE_ALWAYS }, { "FL_WHEN_ENTER_KEY", FL_WHEN_ENTER_KEY }, { "FL_WHEN_ENTER_KEY_ALWAYS", FL_WHEN_ENTER_KEY_ALWAYS }, { "FL_WHEN_ENTER_KEY_CHANGED", FL_WHEN_ENTER_KEY_CHANGED }, { "FL_WHEN_ENTER_KEY + FL_WHEN_RELEASE_ALWAYS", Fl_When(int(FL_WHEN_ENTER_KEY_CHANGED)+int(FL_WHEN_RELEASE_ALWAYS)) } // TODO: Perhaps other FL_WHEN_* combos are relevant }; void b_cb(Fl_Widget* o, void*) { tty->printf("callback, selection = \033[31m%d\033[0m, event_clicks = \033[32m%d\033[0m\n", ((Fl_Browser*)o)->value(), Fl::event_clicks()); } void show_cb(Fl_Widget *o, void *) { int line = atoi(field->value()); if (!line) { fl_alert("Please enter a number in the text field\n" "before clicking on the buttons."); return; } if (o == top) browser->topline(line); else if (o == bottom) browser->bottomline(line); else if (o == middle) browser->middleline(line); else browser->make_visible(line); } void swap_cb(Fl_Widget *, void *) { int a = -1, b = -1; for ( int t=0; tsize(); t++ ) { // find two selected items if ( browser->selected(t) ) { if ( a < 0 ) { a = t; } else { b = t; break; } } } browser->swap(a, b); // swap them } void sort_cb(Fl_Widget *, void *) { browser->sort(FL_SORT_ASCENDING); } void btype_cb(Fl_Widget *, void *) { for ( int t=1; t<=browser->size(); t++ ) browser->select(t,0); browser->select(1,0); // leave focus box on first line if ( strcmp(btype->text(),"Normal")==0) browser->type(FL_NORMAL_BROWSER); else if ( strcmp(btype->text(),"Select")==0) browser->type(FL_SELECT_BROWSER); else if ( strcmp(btype->text(),"Hold" )==0) browser->type(FL_HOLD_BROWSER); else if ( strcmp(btype->text(),"Multi" )==0) browser->type(FL_MULTI_BROWSER); browser->redraw(); } void wtype_cb(Fl_Widget *, void *) { if ( wtype->value() < 0 ) return; browser->when( when_items[wtype->value()].wvalue ); // when value based on array } int main(int argc, char **argv) { int i; Fl::args_to_utf8(argc, argv); // for MSYS2/MinGW if (!Fl::args(argc, argv, i)) Fl::fatal(Fl::help); const char *fname = (i < argc) ? argv[i] : "browser.cxx"; Fl_Double_Window window(720, 520, fname); browser = new Fl_Select_Browser(0, 0, window.w(), 350, 0); browser->type(FL_MULTI_BROWSER); browser->callback(b_cb); if (!browser->load(fname)) { fl_message("Can't load '%s'\n%s\n", fname, strerror(errno)); browser->add("This is a test of how the browser draws lines."); browser->add("This is a second line."); browser->add("This is a third."); browser->add("@bBold text"); browser->add("@iItalic text"); } browser->vposition(0); field = new Fl_Int_Input(55, 350, window.w()-55, 25, "Line #:"); field->callback(show_cb); top = new Fl_Button(0, 375, 80, 25, "Top"); top->callback(show_cb); bottom = new Fl_Button(80, 375, 80, 25, "Bottom"); bottom->callback(show_cb); middle = new Fl_Button(160, 375, 80, 25, "Middle"); middle->callback(show_cb); visible = new Fl_Button(240, 375, 80, 25, "Make Vis."); visible->callback(show_cb); swap = new Fl_Button(320, 375, 80, 25, "Swap"); swap->callback(swap_cb); swap->tooltip("Swaps two selected lines\n(Use CTRL-click to select two lines)"); sort = new Fl_Button(400, 375, 80, 25, "Sort"); sort->callback(sort_cb); btype = new Fl_Choice(480, 375, 80, 25); btype->add("Normal"); btype->add("Select"); btype->add("Hold"); btype->add("Multi"); btype->callback(btype_cb); btype->value(3); btype->tooltip("Changes the browser type()"); wtype = new Fl_Choice(560, 375, 160, 25); wtype->textsize(8); // Append items from when_items[] array { int len = sizeof(when_items) / sizeof(WhenItem); for ( int i=0; iadd(when_items[i].name); } wtype->callback(wtype_cb); wtype->value(4); // FL_WHEN_RELEASE_ALWAYS is Fl_Browser's default // Small terminal window for callback messages tty = new Fl_Terminal(0,400,720,120); tty->history_lines(50); tty->ansi(true); window.resizable(browser); window.show(argc,argv); return Fl::run(); } fltk-1.4.3/test/coordinates.cxx0000644000175000017500000000753515004135251016634 0ustar albrechtalbrecht// // Coordinate demonstration program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include "../src/flstring.h" // fl_snprintf() #include class Box : public Fl_Box { public: Box(int X, int Y, int W, int H, Fl_Color C, const char* T) : Fl_Box(X, Y, W, H, T) { align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER); box(FL_DOWN_BOX); labelcolor(C); labelsize(11); } }; class Title : public Fl_Box { public: Title(int X, int Y, int W, int H, Fl_Color C, const char* T) : Fl_Box(X, Y, W, H, T) { align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_TOP); box(FL_NO_BOX); labelcolor(C); labelsize(12); } }; class MainWindow : public Fl_Window { public: MainWindow(int X, int Y, const char* T) : Fl_Window(X, Y, T) { Fl_Window* tl_window = new Fl_Window(0, 0, 250, 100); tl_window->box(FL_ENGRAVED_BOX); /* Title* tl_title = */ new Title(10, 10, 230, 40, FL_RED, "Fl_Window TL(0, 0, 250, 100)\nx, y relative to main window"); /* Box* tl_box = */ new Box(25, 50, 200, 40, FL_RED, "Fl_Box tl(25, 50, 200, 40)\nx, y relative to TL window"); tl_window->end(); Fl_Window* br_window = new Fl_Window(250, 100, 250, 100); br_window->box(FL_ENGRAVED_BOX); /* Title* br_title = */ new Title(10, 10, 230, 40, FL_MAGENTA, "Fl_Window BR(250, 100, 250, 100)\nx, y relative to main window"); /* Box* br_box = */ new Box(25, 50, 200, 40, FL_MAGENTA, "Fl_Box br(25, 50, 200, 40)\nx, y relative to BR window"); br_window->end(); Fl_Group* tr_group = new Fl_Group(250, 0, 250, 100); tr_group->box(FL_ENGRAVED_BOX); /* Title* tr_title = */ new Title(260, 10, 230, 40, FL_BLUE, "Fl_Group TR(250, 0, 250, 100)\nx, y relative to main window"); /* Box* tr_box = */ new Box(275, 50, 200, 40, FL_BLUE, "Fl_Box tr(275, 50, 200, 40)\nx, y relative to main window"); tr_group->end(); Fl_Group* bl_group = new Fl_Group(0, 100, 250, 100); bl_group->box(FL_ENGRAVED_BOX); /* Title* bl_title = */ new Title(10, 110, 230, 40, FL_BLACK, "Fl_Group BL(0, 100, 250, 100)\nx, y relative to main window"); /* Box* bl_box = */ new Box(25, 150, 200, 40, FL_BLACK, "Fl_Box bl(25, 150, 200, 40)\nx, y relative to main window"); bl_group->end(); // member variable message_box = new Fl_Box(0, 201, 500, 30); message_box->align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER); message_box->box(FL_ENGRAVED_BOX); message_box->labelfont(FL_COURIER); message_box->labelsize(12); end(); } protected: int handle(int event) FL_OVERRIDE { static char buffer[128]; static const char* fmt = "Mouse position relative to main window: %3d,%3d"; int result = Fl_Window::handle(event); switch (event) { case FL_ENTER: case FL_LEAVE: result = 1; message_box->copy_label(""); break; case FL_MOVE: case FL_DRAG: result = 1; if (0 < Fl::event_x() && Fl::event_x() < w() && 0 < Fl::event_y() && Fl::event_y() < h()) { fl_snprintf(buffer, 128-1, fmt, Fl::event_x(), Fl::event_y()); message_box->copy_label(buffer); } else message_box->copy_label(""); break; default: break; } return result; } private: Fl_Box* message_box; }; int main(int argc, char** argv) { MainWindow window(500, 232, "FLTK Coordinate Systems"); window.show(argc, argv); return Fl::run(); } fltk-1.4.3/test/file_chooser.cxx0000644000175000017500000002510615004135251016755 0ustar albrechtalbrecht// // File chooser test program. // // Copyright 1999-2010 by Michael Sweet. // Copyright 2011-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // main() - Create a file chooser and wait for a selection to be made. // close_callback() - Close the main window... // fc_callback() - Handle choices in the file chooser... // pdf_check() - Check for and load the first page of a PDF file. // ps_check() - Check for and load the first page of a PostScript file. // show_callback() - Show the file chooser... // // extra_callback() - circle extra groups (none,group1,check_button); // // // Include necessary headers... // #include #include #include #include #include #include #include #include #include #include // exit() #include // setlocale().. #define TERMINAL_HEIGHT 120 #define TERMINAL_GREEN "\033[32m" #define TERMINAL_NORMAL "\033[0m" // // Globals... // Fl_Input *filter; Fl_File_Browser *files; Fl_File_Chooser *fc; Fl_Shared_Image *image = 0; Fl_Terminal *tty = 0; // for choosing extra groups Fl_Choice *ch_extra; // first extra group Fl_Group *encodings = (Fl_Group*)0; Fl_Choice *ch_enc; // second extra widget Fl_Check_Button *version = (Fl_Check_Button*)0; // // Functions... // void close_callback(void); void create_callback(void); void dir_callback(void); void fc_callback(Fl_File_Chooser *, void *); void multi_callback(void); Fl_Image *pdf_check(const char *, uchar *, int); Fl_Image *ps_check(const char *, uchar *, int); void show_callback(void); void extra_callback(Fl_Choice*,void*); // // 'main()' - Create a file chooser and wait for a selection to be made. // int // O - Exit status main(int argc, // I - Number of command-line arguments char *argv[]) // I - Command-line arguments { Fl_Double_Window *window;// Main window Fl_Button *button;// Buttons Fl_Group *grp; // Groups Fl_File_Icon *icon; // New file icon // Make the file chooser... setlocale(LC_ALL, ""); // enable multilanguage errors in file chooser Fl::scheme(NULL); Fl_File_Icon::load_system_icons(); fc = new Fl_File_Chooser(".", "*", Fl_File_Chooser::SINGLE, "Fl_File_Chooser Test"); fc->callback(fc_callback); // Register the PS and PDF image types... Fl_Shared_Image::add_handler(pdf_check); Fl_Shared_Image::add_handler(ps_check); // Make the main window... window = new Fl_Double_Window(400, 215+TERMINAL_HEIGHT, "File Chooser Test"); tty = new Fl_Terminal(0,215,window->w(),TERMINAL_HEIGHT); tty->ansi(true); tty->display_columns(100); // at least 100 cols wide, even tho actual window smaller // Group: limit resizing to filter input (not browse button) grp = new Fl_Group(0,10,400,25); grp->begin(); { filter = new Fl_Input(50, 10, 315, 25, "Filter:"); // Process standard arguments and find filter argument if present int argn = 1; while (argn < argc) { if (Fl::arg(argc, argv, argn) == 0) break; } if (argc > argn) filter->value(argv[argn]); else filter->value("PDF Files (*.pdf)\t" "PostScript Files (*.ps)\t" "Image Files (*.{bmp,gif,jpg,png})\t" "C/C++ Source Files (*.{c,C,cc,cpp,cxx})"); button = new Fl_Button(365, 10, 25, 25); button->tooltip("Click to open file browser.."); button->callback((Fl_Callback *)show_callback); if ( (icon = Fl_File_Icon::find(".", Fl_File_Icon::DIRECTORY)) ) { // Icon found; assign it.. button->labelcolor(FL_YELLOW); icon->label(button); } else { // Fallback if no icon found button->label(".."); } } grp->end(); grp->resizable(filter); // Group: prevent resizing of the light buttons grp = new Fl_Group(0,45,400,55); grp->begin(); { button = new Fl_Light_Button(50, 45, 80, 25, "MULTI"); button->callback((Fl_Callback *)multi_callback); button = new Fl_Light_Button(140, 45, 90, 25, "CREATE"); button->callback((Fl_Callback *)create_callback); button = new Fl_Light_Button(240, 45, 115, 25, "DIRECTORY"); button->callback((Fl_Callback *)dir_callback); // ch_extra = new Fl_Choice(150, 75, 150, 25, "Extra Group:"); ch_extra->add("none|encodings group|check button"); ch_extra->value(0); ch_extra->callback((Fl_Callback *)extra_callback); } grp->end(); grp->resizable(0); // files = new Fl_File_Browser(50, 105, 340, 75, "Files:"); files->align(FL_ALIGN_LEFT); // Prevent resizing close button, but keep at right edge of scrn grp = new Fl_Group(0,185,400,25); grp->begin(); { Fl_Box *invis = new Fl_Box(100,185,1,1); invis->box(FL_NO_BOX); button = new Fl_Button(310, 185, 80, 25, "Close"); button->callback((Fl_Callback *)close_callback); grp->resizable(invis); } grp->end(); window->resizable(files); window->end(); window->show(1, argv); Fl::run(); return (0); } void extra_callback(Fl_Choice*w,void*) { int val=w->value(); if (0 == val) fc->add_extra(NULL); else if (1 == val) { if(!encodings){ encodings=new Fl_Group(0,0,254,30); ch_enc=new Fl_Choice(152,2,100,25,"Choose Encoding:"); ch_enc->add("ASCII|Koi8-r|win1251|Utf-8"); encodings->end(); } fc->add_extra(encodings); } else { if (!version) { version = new Fl_Check_Button(5,0,200,25,"Save binary 1.0 version"); } fc->add_extra(version); } } // // 'close_callback()' - Close the main window... // void close_callback(void) { exit(0); } // // 'create_callback()' - Handle clicks on the create button. // void create_callback(void) { fc->type(fc->type() ^ Fl_File_Chooser::CREATE); } // // 'dir_callback()' - Handle clicks on the directory button. // void dir_callback(void) { fc->type(fc->type() ^ Fl_File_Chooser::DIRECTORY); } // // 'fc_callback()' - Handle choices in the file chooser... // void fc_callback(Fl_File_Chooser *fc, // I - File chooser void *data) // I - Data { const char *filename; // Current filename tty->printf("fc_callback(fc = %p, data = %p)\n", fc, data); filename = fc->value(); tty->printf(" filename = \"%s\"\n", filename ? filename : "(null)"); } // // 'multi_callback()' - Handle clicks on the multi button. // void multi_callback(void) { fc->type(fc->type() ^ Fl_File_Chooser::MULTI); } // // 'pdf_check()' - Check for and load the first page of a PDF file. // Fl_Image * // O - Page image or NULL pdf_check(const char *name, // I - Name of file uchar *header, // I - Header data int) // I - Length of header data (unused) { const char *home; // Home directory char preview[FL_PATH_MAX], // Preview filename command[3 * FL_PATH_MAX]; // Command if (memcmp(header, "%PDF", 4) != 0) return 0; home = fl_getenv("HOME"); snprintf(preview, FL_PATH_MAX, "%s/.preview.ppm", home ? home : ""); snprintf(command, sizeof(command), "gs -r100 -dFIXED -sDEVICE=ppmraw -dQUIET -dNOPAUSE -dBATCH " "-sstdout=\"%%stderr\" -sOUTPUTFILE=\'%s\' " "-dFirstPage=1 -dLastPage=1 \'%s\' 2>/dev/null", preview, name); if (fl_system(command)) return 0; return new Fl_PNM_Image(preview); } // // 'ps_check()' - Check for and load the first page of a PostScript file. // Fl_Image * // O - Page image or NULL ps_check(const char *name, // I - Name of file uchar *header, // I - Header data int) // I - Length of header data (unused) { const char *home; // Home directory char preview[FL_PATH_MAX], // Preview filename outname[FL_PATH_MAX], // Preview PS file command[3 * FL_PATH_MAX]; // Command FILE *in, // Input file *out; // Output file int page; // Current page char line[256]; // Line from file if (memcmp(header, "%!", 2) != 0) return 0; home = fl_getenv("HOME"); snprintf(preview, FL_PATH_MAX, "%s/.preview.ppm", home ? home : ""); if (memcmp(header, "%!PS", 4) == 0) { // PS file has DSC comments; extract the first page... snprintf(outname, FL_PATH_MAX, "%s/.preview.ps", home ? home : ""); if (strcmp(name, outname) != 0) { in = fl_fopen(name, "rb"); out = fl_fopen(outname, "wb"); page = 0; while (fgets(line, sizeof(line), in) != NULL) { if (strncmp(line, "%%Page:", 7) == 0) { page ++; if (page > 1) break; } fputs(line, out); } fclose(in); fclose(out); } } else { // PS file doesn't have DSC comments; do the whole file... strncpy(outname, name, sizeof(outname) - 1); outname[sizeof(outname) - 1] = '\0'; } snprintf(command, sizeof(command), "gs -r100 -dFIXED -sDEVICE=ppmraw -dQUIET -dNOPAUSE -dBATCH " "-sstdout=\"%%stderr\" -sOUTPUTFILE=\'%s\' \'%s\' 2>/dev/null", preview, outname); if (fl_system(command)) return 0; return new Fl_PNM_Image(preview); } // // 'show_callback()' - Show the file chooser... // void show_callback(void) { int i; // Looping var int count; // Number of files selected char relative[FL_PATH_MAX]; // Relative filename if (filter->value()[0]) fc->filter(filter->value()); fc->show(); while (fc->visible()) { Fl::wait(); } count = fc->count(); if (count > 0) { files->clear(); for (i = 1; i <= count; i ++) { if (!fc->value(i)) break; fl_filename_relative(relative, sizeof(relative), fc->value(i)); tty->printf("%d/%d) %sPicked: '%s'\n Relative: '%s'%s\n", i, count, TERMINAL_GREEN, fc->value(i), relative, TERMINAL_NORMAL); files->add(relative, Fl_File_Icon::find(fc->value(i), Fl_File_Icon::PLAIN)); } files->redraw(); } } fltk-1.4.3/test/doublebuffer.cxx0000644000175000017500000000665315004135251016766 0ustar albrechtalbrecht// // Double-buffering test program for the Fast Light Tool Kit (FLTK). // // This demo shows how double buffering helps, by drawing the // window in a particularily bad way. // // The single-buffered window will blink as it updates. The // double buffered one will not. It will take just as long // (or longer) to update, but often it will appear to be faster. // // This demo should work for both the GL and X versions of Fl, // even though the double buffering mechanism is totally different. // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include // this purposely draws each line 10 times to be slow: void star(int w, int h, int n) { fl_push_matrix(); fl_translate(w/2, h/2); fl_scale(w/2, h/2); for (int i = 0; i < n; i++) { for (int j = i+1; j < n; j++)/* for (int k=0; k<10; k++)*/ { fl_begin_line(); fl_vertex(cos(2*M_PI*i/n+.1), sin(2*M_PI*i/n+.1)); fl_vertex(cos(2*M_PI*j/n+.1), sin(2*M_PI*j/n+.1)); fl_end_line(); } } fl_pop_matrix(); } int sides[2] = {20,20}; void slider_cb(Fl_Widget* o, long v) { sides[v] = int(((Fl_Slider*)o)->value()); o->parent()->redraw(); } void bad_draw(int w,int h,int which) { // for (int i=0; i<10; i++) { // fl_color(7); fl_rectf(0,0,w,h); fl_color(0); star(w,h); // fl_color(0); fl_rectf(0,0,w,h); fl_color(7); star(w,h); // } fl_color(FL_BLACK); fl_rectf(0,0,w,h); fl_color(FL_WHITE); star(w,h,sides[which]); // for (int x=0; x #include #include #include #include #include #include #include // This test program can be modified by two #define's below to test Fl_Flex // as a drop-in replacement of Fl_Pack. The committed code should always use // the default settings documented below. // // Edit the following 2 #define's to modify the test scenario: #define USE_FLEX 0 // default 0 = use Fl_Pack, 1 = use Fl_Flex #define USE_SCROLL 1 // default 1 = put Fl_Pack or Fl_Flex inside Fl_Scroll // Do not edit #define's below #if USE_FLEX #define CONTAINER Fl_Flex #define USE_PACK 0 #else #define CONTAINER Fl_Pack #define USE_PACK 1 #endif CONTAINER *pack; // either Fl_Pack or Fl_Flex #if USE_SCROLL Fl_Scroll *scroll; #endif void type_cb(Fl_Light_Button *, long v) { for (int i = 0; i < pack->children(); i++) { Fl_Widget *o = pack->child(i); o->resize(0, 0, 25, 25); } pack->type(uchar(v)); #if USE_SCROLL pack->resize(scroll->x(), scroll->y(), scroll->w(), scroll->h()); #endif #if USE_FLEX pack->layout(); #else pack->parent()->redraw(); pack->redraw(); #endif } void spacing_cb(Fl_Value_Slider *o, long) { int s = int(o->value()); pack->spacing(s); #if USE_FLEX if (s > 4) pack->margin(4); else pack->margin(s); pack->layout(); #else pack->parent()->redraw(); #endif } int main(int argc, char **argv) { Fl_Double_Window *w = new Fl_Double_Window(360, 370); #if USE_SCROLL scroll = new Fl_Scroll(10, 10, 340, 285); #endif int nbuttons = 24; pack = new CONTAINER(10, 10, 340, 285); #if (USE_FLEX) pack->box(FL_DOWN_BOX); nbuttons = 12; #else pack->box(FL_DOWN_FRAME); #endif // create buttons: position (xx, xx) will be "fixed" by Fl_Pack/Fl_Flex int xx = 35; for (int i = 0; i < nbuttons; i++) { char ltxt[8]; snprintf(ltxt, 8, "b%d", i + 1); Fl_Button *b = new Fl_Button(xx, xx, 25, 25); b->copy_label(ltxt); xx += 10; } pack->end(); w->resizable(pack); #if USE_SCROLL scroll->end(); #endif { Fl_Light_Button *o = new Fl_Light_Button(10, 305, 165, 25, "HORIZONTAL"); o->type(FL_RADIO_BUTTON); o->callback((Fl_Callback *)type_cb, (void *)(CONTAINER::HORIZONTAL)); } { Fl_Light_Button *o = new Fl_Light_Button(185, 305, 165, 25, "VERTICAL"); o->type(FL_RADIO_BUTTON); o->value(1); o->callback((Fl_Callback *)type_cb, (void *)(CONTAINER::VERTICAL)); } { Fl_Value_Slider *o = new Fl_Value_Slider(100, 335, 250, 25, "Spacing: "); o->align(FL_ALIGN_LEFT); o->type(FL_HORIZONTAL); o->range(0, 30); o->step(1); o->callback((Fl_Callback *)spacing_cb); } w->end(); w->size_range(300, 300); w->show(argc, argv); return Fl::run(); } fltk-1.4.3/test/shadow_variables.cxx0000644000175000017500000000154615004135251017633 0ustar albrechtalbrecht// // Public header compilation test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // The following header file is generated by CMake and includes all // public FLTK headers: #include "include_all.h" #include int main() { printf("This program includes all FLTK header files for compilation.\n"); printf("It should be compiled with `g++ (clang++) -Wshadow ...` or similar.\n"); printf("This program does nothing.\n"); return 0; } fltk-1.4.3/test/line_style.cxx0000644000175000017500000001133615004135251016463 0ustar albrechtalbrecht// // Line style demo for the Fast Light Tool Kit (FLTK). // // Copyright 2000-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include Fl_Double_Window *form; Fl_Slider *sliders[9]; Fl_Choice *choice[3]; Fl_Check_Button *draw_line; class test_box: public Fl_Double_Window { void draw() FL_OVERRIDE; public: test_box(int x,int y,int w,int h,const char *l=0) : Fl_Double_Window(x,y,w,h,l) {} }*test; void test_box::draw() { Fl_Double_Window::draw(); fl_color((uchar)(sliders[0]->value()), (uchar)(sliders[1]->value()), (uchar)(sliders[2]->value())); // dashes char dashes[5]; dashes[0] = char(sliders[5]->value()); dashes[1] = char(sliders[6]->value()); dashes[2] = char(sliders[7]->value()); dashes[3] = char(sliders[8]->value()); dashes[4] = 0; fl_line_style( (int)(choice[0]->mvalue()->argument() + choice[1]->mvalue()->argument() + choice[2]->mvalue()->argument()), (int)(sliders[3]->value()), // width dashes); // draw the defined fl_rect and fl_vertex first and then // the additional one-pixel line, if enabled // sliders[4] = x/y coordinate translation (default = 10) for (int i=0; ivalue()+1; i++) { int move = (int)sliders[4]->value(); fl_rect(move,move,w()-20,h()-20); fl_begin_line(); fl_vertex(move+25, move+25); fl_vertex(w()-45+move, h()-45+move); fl_vertex(w()-50+move, move+25); fl_vertex(move+25, h()/2-10+move); fl_end_line(); // you must reset the line type when done: fl_line_style(FL_SOLID); fl_color(FL_BLACK); } } Fl_Menu_Item style_menu[] = { {"FL_SOLID", 0, 0, (void*)FL_SOLID}, {"FL_DASH", 0, 0, (void*)FL_DASH}, {"FL_DOT", 0, 0, (void*)FL_DOT}, {"FL_DASHDOT",0, 0, (void*)FL_DASHDOT}, {"FL_DASHDOTDOT", 0, 0, (void*)FL_DASHDOTDOT}, {0} }; Fl_Menu_Item cap_menu[] = { {"default", 0, 0, 0}, {"FL_CAP_FLAT", 0, 0, (void*)FL_CAP_FLAT}, {"FL_CAP_ROUND", 0, 0, (void*)FL_CAP_ROUND}, {"FL_CAP_SQUARE", 0, 0, (void*)FL_CAP_SQUARE}, {0} }; Fl_Menu_Item join_menu[] = { {"default", 0, 0, 0}, {"FL_JOIN_MITER", 0, 0, (void*)FL_JOIN_MITER}, {"FL_JOIN_ROUND", 0, 0, (void*)FL_JOIN_ROUND}, {"FL_JOIN_BEVEL", 0, 0, (void*)FL_JOIN_BEVEL}, {0} }; void do_redraw(Fl_Widget*,void*) { test->redraw(); } void makeform(const char *) { form = new Fl_Double_Window(500,250,"fl_line_style() test"); sliders[0]= new Fl_Value_Slider(280,10,180,20,"R"); sliders[0]->bounds(0,255); sliders[1]= new Fl_Value_Slider(280,30,180,20,"G"); sliders[1]->bounds(0,255); sliders[2]= new Fl_Value_Slider(280,50,180,20,"B"); sliders[2]->bounds(0,255); choice[0]= new Fl_Choice(280,70,180,20,"Style"); choice[0]->menu(style_menu); choice[1]= new Fl_Choice(280,90,180,20,"Cap"); choice[1]->menu(cap_menu); choice[2]= new Fl_Choice(280,110,180,20,"Join"); choice[2]->menu(join_menu); sliders[3]= new Fl_Value_Slider(280,130,180,20,"Width"); sliders[3]->bounds(0,20); sliders[4]= new Fl_Value_Slider(280,150,180,20,"Move"); sliders[4]->bounds(-10,20); draw_line = new Fl_Check_Button(280,170,20,20,"&Line"); draw_line->align(FL_ALIGN_LEFT); new Fl_Box (305,170,160,20,"add a 1-pixel black line"); sliders[5] = new Fl_Slider(200,210,70,20,"Dash"); sliders[5]->align(FL_ALIGN_TOP_LEFT); sliders[5]->bounds(0,40); sliders[6] = new Fl_Slider(270,210,70,20); sliders[6]->bounds(0,40); sliders[7] = new Fl_Slider(340,210,70,20); sliders[7]->bounds(0,40); sliders[8] = new Fl_Slider(410,210,70,20); sliders[8]->bounds(0,40); int i; for (i=0;i<9;i++) { sliders[i]->type(1); if (i<5) sliders[i]->align(FL_ALIGN_LEFT); sliders[i]->callback((Fl_Callback*)do_redraw); sliders[i]->step(1); } sliders[0]->value(255); // R sliders[1]->value(100); // G sliders[2]->value(100); // B sliders[4]->value(10); // move line coordinates draw_line->value(0); draw_line->callback((Fl_Callback*)do_redraw); for (i=0;i<3;i++) { choice[i]->value(0); choice[i]->callback((Fl_Callback*)do_redraw); } test = new test_box(0,0,200,200); test->end(); form->resizable(test); form->end(); } int main(int argc, char **argv) { makeform(argv[0]); form->show(argc,argv); return Fl::run(); } fltk-1.4.3/test/unittest_symbol.cxx0000644000175000017500000000757215004135251017567 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include #include // // Test symbol rendering // class Ut_Symbol_Test : public Fl_Widget { void draw_text_and_boxes(const char *txt, int X, int Y) { int wo = 0, ho = 0; fl_measure(txt, wo, ho, 1); // Draw fl_measure() rect fl_color(FL_RED); fl_rect(X, Y, wo, ho); // ////////////////////////////////////////////////////////////////////// // NOTE: fl_text_extents() currently does not support multiline strings.. // until it does, let's leave this out, as we do multiline tests.. // ////////////////////////////////////////////////////////////////////// // // draw fl_text_extents() glyph bounding box // int dx,dy; // fl_text_extents(txt, dx, dy, wo, ho); // fl_color(FL_GREEN); // fl_rect(X+dx, Y+dy, wo, ho); // // Draw text with symbols enabled fl_color(FL_BLACK); fl_draw(txt, X, Y, 10, 10, FL_ALIGN_INSIDE|FL_ALIGN_TOP|FL_ALIGN_LEFT, 0, 1); } public: static Fl_Widget *create() { return new Ut_Symbol_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } Ut_Symbol_Test(int x, int y, int w, int h) : Fl_Widget(x, y, w, h) { } void draw(void) FL_OVERRIDE { int x0 = x(); // origin is current window position for Fl_Box int y0 = y(); int w0 = w(); int h0 = h(); fl_push_clip(x0, y0, w0, h0); // reset local clipping { // set the background colour - slightly off-white to enhance the green bounding box fl_color(fl_gray_ramp(FL_NUM_GRAY - 3)); fl_rectf(x0, y0, w0, h0); int fsize = 25; fl_font(FL_HELVETICA, fsize); int xx = x0+10; int yy = y0+10; draw_text_and_boxes("Text" ,xx,yy); yy += fsize+10; // check no symbols draw_text_and_boxes("@->" ,xx,yy); yy += fsize+10; // check symbol alone draw_text_and_boxes("@-> " ,xx,yy); yy += fsize+10; // check symbol with trailing space draw_text_and_boxes("@-> Rt Arrow" ,xx,yy); yy += fsize+10; // check symbol at left edge draw_text_and_boxes("Lt Arrow @<-" ,xx,yy); yy += fsize+10; // check symbol at right edge draw_text_and_boxes("@-> Rt/Lt @<-" ,xx,yy); yy += fsize+10; // check symbol at lt+rt edges draw_text_and_boxes("@@ At/Lt @<-" ,xx,yy); yy += fsize+10; // check @@ at left, symbol at right draw_text_and_boxes("@-> Lt/At @@" ,xx,yy); yy += fsize+10; // check symbol at left, @@ at right draw_text_and_boxes("@@ At/At @@" ,xx,yy); yy += fsize+10; // check @@ at left+right xx = x0+200; yy = y0+10; draw_text_and_boxes("Line1\nLine2" ,xx,yy); yy += (fsize+10)*2; // check 2 lines, no symbol draw_text_and_boxes("@-> Line1\nLine2 @<-" ,xx,yy); yy += (fsize+10)*2; // check 2 lines, lt+rt symbols draw_text_and_boxes("@-> Line1\nLine2\nLine3 @<-",xx,yy); yy += (fsize+10)*3; // check 3 lines, lt+rt symbols draw_text_and_boxes("@@@@" ,xx,yy); yy += (fsize+10); // check abutting @@'s draw_text_and_boxes("@@ @@" ,xx,yy); yy += (fsize+10); // check @@'s with space sep fl_font(FL_HELVETICA, 14); fl_color(FL_RED); fl_draw("fl_measure bounding box in RED", x0+10,y0+h0-20); } fl_pop_clip(); // remove the local clip } }; UnitTest symbolExtents(UT_TEST_SYBOL, "Symbol Text", Ut_Symbol_Test::create); fltk-1.4.3/test/wizard.cxx0000644000175000017500000000342315004135251015612 0ustar albrechtalbrecht#include #include #include #include class Panel : public Fl_Group { public: Panel(int X, int Y, int W, int H, Fl_Color C, const char* T) : Fl_Group(X, Y, W, H, T) { align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER); box(FL_ENGRAVED_BOX); labelcolor(C); labelsize(20); end(); } }; class Wizard : public Fl_Wizard { public: Wizard(int X, int Y, int W, int H, const char* T=0) : Fl_Wizard(X, Y, W, H, T) { p1 = new Panel(X, Y, W, H, FL_RED, "Panel 1"); p2 = new Panel(X, Y, W, H, FL_MAGENTA, "Panel 2"); p3 = new Panel(X, Y, W, H, FL_BLUE, "Panel 3"); value(p1); } void next_panel() { Panel* p = (Panel*)value(); if (p == p3) value(p1); else next(); } void prev_panel() { Panel* p = (Panel*)value(); if (p == p1) value(p3); else prev(); } private: Panel *p1, *p2, *p3; }; void next_callback(Fl_Widget *widget, void *data) { Wizard *pWizard = (Wizard*)data; pWizard->next_panel(); } void prev_callback(Fl_Widget *widget, void *data) { Wizard *pWizard = (Wizard*)data; pWizard->prev_panel(); } int main(int argc, char** argv) { Fl_Window window(300, 165, "Fl_Wizard test"); Wizard wizard(5, 5, 290, 100); wizard.end(); Fl_Group buttons(5, 110, 290, 50); buttons.box(FL_ENGRAVED_BOX); Fl_Button prev_button( 15, 120, 110, 30, "@< Prev Panel"); prev_button.callback(prev_callback, (void*)&wizard); prev_button.align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_LEFT); Fl_Button next_button(175, 120, 110, 30, "Next Panel @>"); next_button.align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_RIGHT); next_button.callback(next_callback, (void*)&wizard); buttons.end(); window.end(); window.show(argc, argv); return Fl::run(); } fltk-1.4.3/test/line_style_docs.cxx0000644000175000017500000001110015004135251017460 0ustar albrechtalbrecht// // Line style image (docs) for the Fast Light Tool Kit (FLTK). // // Copyright 2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Notes to devs (and users): // // 1. Run this program to create the screenshot for the fl_line_style() docs. // Save a screenshot of its original size to documentation/src/fl_line_style.png // 2. For further tests it's possible to resize the window. Line sizes and widths // are adjusted (resized) as well, depending on the window size. // 3. Some lines may draw outside their boxes in unusual window width/height ratios. // These effects are intentionally ignored. #include #include #include #include #include // constants static const int sep = 22; // separation between items static int width[] = {1, 4}; // line widths (thin + thick/dyn.) // This class draws a box with one line style inside an Fl_Grid widget. // Row and column parameters are used to position the box inside the grid. class StyleBox : public Fl_Box { int style; // line style public: StyleBox(int S, int row, int col) // style, row, column : Fl_Box(0, 0, 0, 0) { box(FL_FLAT_BOX); color(FL_WHITE); style = S; Fl_Grid *grid = (Fl_Grid *)parent(); grid->widget(this, row, col, FL_GRID_FILL); } const char *style_str(int style) { switch(style) { case FL_SOLID : return "FL_SOLID" ; case FL_DASH : return "FL_DASH" ; case FL_DOT : return "FL_DOT" ; case FL_DASHDOT : return "FL_DASHDOT" ; case FL_DASHDOTDOT : return "FL_DASHDOTDOT" ; case FL_CAP_FLAT : return "FL_CAP_FLAT" ; case FL_CAP_ROUND : return "FL_CAP_ROUND" ; case FL_CAP_SQUARE : return "FL_CAP_SQUARE" ; case FL_JOIN_MITER : return "FL_JOIN_MITER" ; case FL_JOIN_ROUND : return "FL_JOIN_ROUND" ; case FL_JOIN_BEVEL : return "FL_JOIN_BEVEL" ; default : return "(?)"; } } void draw() FL_OVERRIDE { draw_box(); if (style < 0) // draw an empty box return; // set font and measure widest text fl_font(FL_HELVETICA, 12); fl_color(FL_BLACK); static int text_width = 0; if (!text_width) { int h = 0; // dummy fl_measure("FL_DASHDOTDOT", text_width, h); } // draw the text int X = x() + sep / 2; fl_draw(style_str(style), X, y() + h()/2 + fl_height()/2 - 2); // calculate dynamic line sizes and widths X += text_width + sep / 2; int dx = (w() - text_width - 5 * sep) / 4; // horizontal distance int dy = h() - sep; int Y = y() + sep / 2; if (dx >= 80 || dy >= 80) width[1] = 9; else if (dx >= 60 || dy >= 60) width[1] = 8; else if (dx >= 40 || dy >= 40) width[1] = 7; else width[1] = 5; // draw the lines for (int i = 0; i < 2; i++, X += dx + sep) { // thin + thick lines fl_line_style(style, width[i]); // ___ // | // | fl_line(X, Y, X + dx, Y, X + dx, Y + dy); X += dx + sep; // ___ // / // / fl_line(X, Y, X + dx, Y, X, Y + dy); } // restore line settings to default fl_line_style(FL_SOLID, 0); } }; int main(int argc, char **argv) { Fl_Double_Window win(740, 400, "fl_line_style()"); win.color(FL_WHITE); // create grid with a nice white 4px border and a // light gray background (color) so margins and gaps show thru Fl_Grid grid(4, 4, win.w() - 8, win.h() - 8); grid.box(FL_FLAT_BOX); grid.color(0xd0d0d000); grid.layout(6, 2, 4, 4); // 6 rows, 2 columns, ... // first column StyleBox sb00(FL_SOLID, 0, 0); StyleBox sb01(FL_DASH, 1, 0); StyleBox sb02(FL_DOT, 2, 0); StyleBox sb03(FL_DASHDOT, 3, 0); StyleBox sb04(FL_DASHDOTDOT, 4, 0); StyleBox sb05(-1, 5, 0); // empty box // second column StyleBox sb10(FL_CAP_FLAT, 0, 1); StyleBox sb11(FL_CAP_ROUND, 1, 1); StyleBox sb12(FL_CAP_SQUARE, 2, 1); StyleBox sb13(FL_JOIN_MITER, 3, 1); StyleBox sb14(FL_JOIN_ROUND, 4, 1); StyleBox sb15(FL_JOIN_BEVEL, 5, 1); grid.end(); win.end(); win.resizable(win); win.size_range(660, 340); // don't allow to shrink too much win.show(argc, argv); return Fl::run(); } fltk-1.4.3/test/button.cxx0000644000175000017500000000244015004135251015623 0ustar albrechtalbrecht// // Button/callback test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include void beepcb(Fl_Widget *, void *) { fl_beep(); fflush(stdout); } void exitcb(Fl_Widget *, void *) { exit(0); } #if 0 // test Fl::add_fd()... void stdin_cb(int, void*) { char buf[1000]; fgets(buf, sizeof(buf), stdin); printf("stdin callback\n"); } #endif int main(int argc, char ** argv) { Fl_Window *window = new Fl_Window(320,65); Fl_Button *b1 = new Fl_Button(20, 20, 80, 25, "&Beep"); b1->callback(beepcb,0); /*Fl_Button *b2 =*/ new Fl_Button(120,20, 80, 25, "&no op"); Fl_Button *b3 = new Fl_Button(220,20, 80, 25, "E&xit"); b3->callback(exitcb,0); window->end(); window->show(argc,argv); #if 0 Fl::add_fd(0, stdin_cb); #endif return Fl::run(); } fltk-1.4.3/test/native-filechooser.cxx0000644000175000017500000001405215004135251020100 0ustar albrechtalbrecht// // Simple test of the Fl_Native_File_Chooser. // // Copyright 1998-2016 by Bill Spitzak and others. // Copyright 2004 Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include /* strstr() */ #include #include /* fl_beep() */ #include #include #include #include #include #include #include #include #include #define TERMINAL_HEIGHT 120 // GLOBALS Fl_Input *G_filename = NULL; Fl_Multiline_Input *G_filter = NULL; Fl_Terminal *G_tty = NULL; void PickFile_CB(Fl_Widget*, void*) { // Create native chooser Fl_Native_File_Chooser native; native.title("Pick a file"); native.type(Fl_Native_File_Chooser::BROWSE_FILE); native.filter(G_filter->value()); native.preset_file(G_filename->value()); // Show native chooser switch ( native.show() ) { case -1: G_tty->printf("ERROR: %s\n", native.errmsg()); break; // ERROR case 1: G_tty->printf("*** CANCEL\n"); fl_beep(); break; // CANCEL default: // PICKED FILE if ( native.filename() ) { G_filename->value(native.filename()); G_tty->printf("filename='%s'\n", native.filename()); } else { G_filename->value("NULL"); G_tty->printf("filename='(null)'\n"); } break; } } void PickDir_CB(Fl_Widget*, void*) { // Create native chooser Fl_Native_File_Chooser native; native.title("Pick a Directory"); native.directory(G_filename->value()); native.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY); // Show native chooser switch ( native.show() ) { case -1: G_tty->printf("ERROR: %s\n", native.errmsg()); break; // ERROR case 1: G_tty->printf("*** CANCEL\n"); fl_beep(); break; // CANCEL default: // PICKED DIR if ( native.filename() ) { G_filename->value(native.filename()); G_tty->printf("dirname='%s'\n", native.filename()); } else { G_filename->value("NULL"); G_tty->printf("dirname='(null)'\n"); } break; } } int main(int argc, char **argv) { /* For a nicer looking browser under linux/unix, call fl_register_images() (If you do this, you'll need to link with fltk_images). That's required for the preview option of the GTK filechooser. In the unlikely situation where no native filechooser is found on the active Linux system, FLTK reverts to using its own file chooser (Fl_File_Chooser) which looks best if you also call Fl_File_Icon::load_system_icons(). None of that is useful for the native file chooser under macOS or Windows. */ #if defined(FLTK_USE_X11) || defined(FLTK_USE_WAYLAND) fl_register_images(); Fl_File_Icon::load_system_icons(); #endif int argn = 1; #ifdef __APPLE__ // OS X may add the process number as the first argument - ignore if (argc>argn && strncmp(argv[argn], "-psn_", 5)==0) ++argn; #endif // Parse preset filename (if any) char *filename = 0; if ( argc>argn && argv[argn][0] != '-' ) { filename = argv[argn++]; } Fl_Window *win = new Fl_Window(640, 400+TERMINAL_HEIGHT, "Native File Chooser Test"); win->size_range(win->w(), win->h(), 0, 0); win->begin(); { G_tty = new Fl_Terminal(0,400,win->w(),TERMINAL_HEIGHT); int x = 80, y = 10; G_filename = new Fl_Input(x, y, win->w()-80-10, 25, "Filename"); G_filename->value(filename ? filename : "."); G_filename->tooltip("Default filename"); y += G_filename->h() + 10; G_filter = new Fl_Multiline_Input(x, y, G_filename->w(), 100, "Filter"); G_filter->value("Text\t*.txt\n" "C Files\t*.{cxx,h,c,cpp}\n" "Tars\t*.{tar,tar.gz}\n" "Apps\t*.app"); G_filter->tooltip("Filter to be used for browser.\n" "An empty string may be used.\n"); y += G_filter->h() + 10; Fl_Help_View *view = new Fl_Help_View(x, y, G_filename->w(), 200); view->box(FL_FLAT_BOX); view->color(win->color()); #define TAB "<Tab>" view->textfont(FL_HELVETICA); view->textsize(10); view->value("The Filter can be one or more filter patterns, one per line.\n" "Patterns can be:
    \n" "
  • A single wildcard (e.g. \"*.txt\")
  • \n" "
  • Multiple wildcards (e.g. \"*.{cxx,h,H}\")
  • \n" "
  • A descriptive name followed by a " TAB " and a wildcard (e.g. \"Text Files" TAB "*.txt\")
  • \n" "
\n" "In the above \"Filter\" field, you can use Ctrl-I to enter " TAB " characters as needed.
\n" "Example:
\n"
                "\n"
                "    Text<Ctrl-I>*.txt\n"
                "    C Files<Ctrl-I>*.{cxx,h,c,cpp}\n"
                "    Tars<Ctrl-I>*.{tar,tar.gz}\n"
                "    Apps<Ctrl-I>*.app\n"
                "
\n"); Fl_Button *but = new Fl_Button(win->w()-x-10, win->h()-TERMINAL_HEIGHT-25-10, 80, 25, "Pick File"); but->callback(PickFile_CB); Fl_Button *butdir = new Fl_Button(but->x()-x-10, win->h()-TERMINAL_HEIGHT-25-10, 80, 25, "Pick Dir"); butdir->callback(PickDir_CB); win->resizable(G_filter); } win->end(); // Pass show() remaining args we haven't already parsed.. { char **args = argv+(argn-1); int nargs = argc-(argn-1); win->show(nargs, args); } return(Fl::run()); } fltk-1.4.3/test/clipboard.cxx0000644000175000017500000001631515004135251016255 0ustar albrechtalbrecht// // Clipboard display test application for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include #include // optional: display extra technical info about clipboard content if defined // #define DEBUG_CLIPBOARD_DATA #if defined(_WIN32) && defined(DEBUG_CLIPBOARD_DATA) #include #endif // _WIN32 && DEBUG_CLIPBOARD_DATA /* Displays and follows the content of the clipboard with either image or text data */ Fl_Box *image_box; Fl_Box *image_size; Fl_Text_Display *display; Fl_RGB_Image *cl_img = 0; // image from clipboard inline int fl_min(int a, int b) { return (a < b ? a : b); } // a box with a chess-like pattern below its image class chess : public Fl_Box { public: chess(int x, int y, int w, int h) : Fl_Box(FL_FLAT_BOX, x, y, w, h, 0) { align(FL_ALIGN_CENTER | FL_ALIGN_CLIP); } void draw() FL_OVERRIDE { draw_box(); Fl_Image *img = image(); if (img) { // draw the chess pattern below the box centered image int X = x() + (w() - img->w()) / 2; int Y = y() + (h() - img->h()) / 2; int W = img->w(); int H = img->h(); fl_push_clip(X, Y, W, H); fl_push_clip(x(), y(), w(), h()); fl_color(FL_WHITE); fl_rectf(X, Y, W, H); fl_color(FL_LIGHT2); const int side = 4, side2 = 2 * side; for (int j = Y; j < Y + H; j += side) { for (int i = X + (j - Y) % side2; i < X + W; i += side2) { fl_rectf(i, j, side, side); } } fl_pop_clip(); fl_pop_clip(); } draw_label(); // draw the box image } }; #define TAB_COLOR FL_DARK3 // use tabs to display either the image or textual content of the clipboard class clipboard_viewer : public Fl_Tabs { public: clipboard_viewer(int x, int y, int w, int h) : Fl_Tabs(x, y, w, h) {} int handle(int event) FL_OVERRIDE { if (event != FL_PASTE) return Fl_Tabs::handle(event); if (strcmp(Fl::event_clipboard_type(), Fl::clipboard_image) == 0) { // an image is being pasted cl_img = (Fl_RGB_Image *)Fl::event_clipboard(); // get it as an Fl_RGB_Image object if (!cl_img) return 1; char title[300]; snprintf(title, 300, "%dx%d", cl_img->w(), cl_img->h()); // display the image original size // optional: display extra technical info about clipboard content #if defined(_WIN32) && defined(DEBUG_CLIPBOARD_DATA) OpenClipboard(NULL); // char *p = title + strlen(title); int format = EnumClipboardFormats(0); if (format && format < CF_MAX) { snprintf(p, sizeof(title) - strlen(title), " %d", format); p += strlen(p); } while (format) { format = EnumClipboardFormats(format); if (format && format < CF_MAX) { snprintf(p, sizeof(title) - strlen(title), " %d", format); p += strlen(p); } } HANDLE h; if ((h = GetClipboardData(CF_DIB))) { LPBITMAPINFO lpBI = (LPBITMAPINFO)GlobalLock(h); snprintf(p, sizeof(title) - strlen(title), " biBitCount=%d biCompression=%d biClrUsed=%d", lpBI->bmiHeader.biBitCount, (int)lpBI->bmiHeader.biCompression, (int)lpBI->bmiHeader.biClrUsed); } CloseClipboard(); #endif // _WIN32 && DEBUG_CLIPBOARD_DATA Fl_Image *oldimg = image_box->image(); delete oldimg; if (cl_img->w() > image_box->w() || cl_img->h() > image_box->h()) cl_img->scale(image_box->w(), image_box->h()); image_box->image(cl_img); // show the scaled image image_size->copy_label(title); value(image_box->parent()); window()->redraw(); } else { // text is being pasted display->buffer()->text(Fl::event_text()); value(display); display->redraw(); } return 1; } }; clipboard_viewer *tabs; // clipboard viewer callback void cb(Fl_Widget *wid, clipboard_viewer *tabs) { if (Fl::clipboard_contains(Fl::clipboard_image)) { Fl::paste(*tabs, 1, Fl::clipboard_image); // try to find image in the clipboard return; } if (Fl::clipboard_contains(Fl::clipboard_plain_text)) Fl::paste(*tabs, 1, Fl::clipboard_plain_text); // also try to find text } // "Save PNG" callback void save_cb(Fl_Widget *wid, clipboard_viewer *tabs) { if (cl_img && !cl_img->fail()) { Fl_Native_File_Chooser fnfc; fnfc.title("Please select a .png file"); fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); fnfc.filter("PNG\t*.png\n"); fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | Fl_Native_File_Chooser::USE_FILTER_EXT); if (fnfc.show()) return; const char *filename = fnfc.filename(); if (filename) fl_write_png(filename, cl_img); } else { fl_message("%s", "No image available"); } } // called after clipboard was changed or at application activation void clip_callback(int source, void *data) { if (source == 1) cb(NULL, (clipboard_viewer *)data); } int main(int argc, char **argv) { fl_register_images(); // required for the X11 platform to allow pasting of images Fl_Window *win = new Fl_Window(500, 550, "FLTK Clipboard Viewer"); tabs = new clipboard_viewer(0, 0, 500, 500); Fl_Group *g = new Fl_Group(5, 30, 490, 460, Fl::clipboard_image); // will display the image form g->box(FL_FLAT_BOX); image_box = new chess(5, 30, 490, 450); image_size = new Fl_Box(FL_NO_BOX, 5, 485, 490, 10, 0); g->end(); g->selection_color(TAB_COLOR); Fl_Text_Buffer *buffer = new Fl_Text_Buffer(); display = new Fl_Text_Display(5, 30, 490, 460, Fl::clipboard_plain_text); // will display the text form display->buffer(buffer); display->selection_color(TAB_COLOR); display->textfont(FL_COURIER); // use fixed font for text display tabs->end(); tabs->resizable(display); Fl_Group *g2 = new Fl_Group(10, 510, 330, 25); Fl_Button *refresh = new Fl_Button(10, 510, 200, 25, "Refresh from clipboard"); refresh->callback((Fl_Callback *)cb, tabs); Fl_Button *save = new Fl_Button(220, 510, 100, 25, "Save PNG"); save->callback((Fl_Callback *)save_cb, tabs); g2->end(); g2->resizable(NULL); win->end(); win->resizable(tabs); win->show(argc, argv); // TEST: set another default background color #if (0) if (argc < 2) { Fl::set_color(FL_BACKGROUND_COLOR, 0xff, 0xee, 0xdd); Fl::set_color(FL_BACKGROUND2_COLOR, 0xdd, 0xee, 0xff); } #endif clip_callback(1, tabs); // use clipboard content at start Fl::add_clipboard_notify(clip_callback, tabs); // will update with new clipboard content Fl_Image::RGB_scaling(FL_RGB_SCALING_BILINEAR); // set bilinear image scaling method return Fl::run(); } fltk-1.4.3/test/valuators.fl0000644000175000017500000002043015004135251016126 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} Function {} {open } { Fl_Window {} { label {Valuator classes, showing values for type()} open xywh {409 271 580 640} type Double color 43 selection_color 43 code0 {\#include } visible } { Fl_Group {} { label Fl_Slider xywh {10 10 280 210} box ENGRAVED_BOX labelfont 1 align 17 } { Fl_Slider {} { label 0 user_data {"Fl_Slider FL_VERT_SLIDER"} callback callback tooltip {Vertical Slider} xywh {30 45 20 145} selection_color 1 labelsize 8 align 1 } Fl_Slider {} { label FL_VERT_FILL_SLIDER user_data {"Fl_Slider FL_VERT_FILL_SLIDER"} callback callback xywh {70 55 20 145} type {Vert Fill} selection_color 1 labelsize 8 } Fl_Slider {} { label FL_VERT_NICE_SLIDER user_data {"Fl_Slider FL_VERT_NICE_SLIDER"} callback callback xywh {105 45 20 145} type {Vert Knob} box FLAT_BOX color 10 selection_color 1 labelsize 8 align 1 } Fl_Slider {} { label FL_HORIZONTAL user_data {"Fl_Slider FL_HORIZONTAL"} callback callback xywh {140 80 130 20} type Horizontal selection_color 1 labelsize 8 } Fl_Slider {} { label FL_HOR_FILL_SLIDER user_data {"Fl_Slider FL_HOR_FILL_SLIDER"} callback callback xywh {140 120 130 20} type {Horz Fill} selection_color 1 labelsize 8 } Fl_Slider {} { label FL_HOR_NICE_SLIDER user_data {"Fl_Slider FL_HOR_NICE_SLIDER"} callback callback xywh {140 160 130 20} type {Horz Knob} box FLAT_BOX color 10 selection_color 1 labelsize 8 } } Fl_Group {} { label Fl_Value_Slider xywh {10 230 280 210} box ENGRAVED_BOX labelfont 1 align 17 } { Fl_Value_Slider {} { label 0 user_data {"FL_VERT_SLIDER"} callback callback tooltip {Value Slider} xywh {30 260 30 145} selection_color 1 labelsize 8 align 1 } Fl_Value_Slider {} { label FL_VERT_FILL_SLIDER user_data {"Fl_Value_Slider FL_VERT_FILL_SLIDER"} callback callback xywh {70 275 30 140} type {Vert Fill} selection_color 1 labelsize 8 } Fl_Value_Slider {} { label FL_VERT_NICE_SLIDER user_data {"Fl_Value_Slider FL_VERT_NICE_SLIDER"} callback callback xywh {110 260 20 145} type {Vert Knob} box FLAT_BOX color 10 selection_color 1 labelsize 8 align 1 } Fl_Value_Slider {} { label FL_HOR_SLIDER user_data {"Fl_Value_Slider FL_HOR_SLIDER"} callback callback xywh {140 290 130 20} type Horizontal selection_color 1 labelsize 8 } Fl_Value_Slider {} { label FL_HOR_FILL_SLIDER user_data {"Fl_Value_Slider FL_HOR_FILL_SLIDER"} callback callback xywh {140 330 130 20} type {Horz Fill} selection_color 1 labelsize 8 } Fl_Value_Slider {} { label FL_HOR_NICE_SLIDER user_data {"Fl_Value_Slider FL_HOR_NICE_SLIDER"} callback callback xywh {140 370 130 20} type {Horz Knob} box FLAT_BOX color 10 selection_color 1 labelsize 8 } } Fl_Group {} { label Fl_Value_Input xywh {10 450 135 50} box ENGRAVED_BOX labelfont 1 align 17 } { Fl_Value_Input {} { label 0 user_data {"Fl_Value_Input"} callback callback tooltip {Value Input} xywh {30 470 105 25} labelsize 8 maximum 100 step 0.1 } } Fl_Group {} { label Fl_Value_Output user_data {"Fl_Value_Output"} xywh {155 450 135 50} box ENGRAVED_BOX labelfont 1 align 17 } { Fl_Value_Output {} { label 0 callback callback tooltip {Value Output} xywh {170 470 105 25} labelsize 8 maximum 100 step 0.1 } } Fl_Group {} { label { Fl_Scrollbar} xywh {300 10 130 120} box ENGRAVED_BOX labelfont 1 align 21 } { Fl_Scrollbar {} { label FL_HORIZONTAL user_data {"Fl_Scrollbar FL_HORIZONTAL"} callback callback tooltip {Horizontal Scrollbar} xywh {305 55 95 20} type Horizontal labelsize 8 maximum 100 value 20 } Fl_Scrollbar {} { label {FL_VERTICAL (0) ->} user_data {"Fl_Scrollbar FL_VERTICAL"} callback callback tooltip {Vertical Scrollbar} xywh {405 30 20 90} labelsize 8 align 13 maximum 100 value 20 } } Fl_Group {} { label Fl_Adjuster xywh {440 10 130 120} box ENGRAVED_BOX labelfont 1 align 17 } { Fl_Adjuster {} { label {w()>h()} user_data {"Fl_Adjuster w()>h()"} callback callback tooltip {Horizontal Adjuster} xywh {450 60 75 25} labelsize 8 } Fl_Adjuster {} { label {w()wrap(0); // disable wrap mode} } } Fl_Group {} { label Fl_Dial xywh {300 270 270 105} box ENGRAVED_BOX labelfont 1 align 17 } { Fl_Dial {} { label 0 user_data {"Fl_Dial"} callback callback tooltip {Standard Dial} xywh {320 295 65 65} color 10 selection_color 1 labelsize 8 value 0.5 code0 {o->angles(0,315);} } Fl_Dial {} { label FL_LINE_DIAL user_data {"Fl_Dial FL_LINE_DIAL"} callback callback tooltip {Line Dial} xywh {400 295 65 65} type Line color 10 selection_color 1 labelsize 8 value 0.5 } Fl_Dial {} { label FL_FILL_DIAL user_data {"Fl_Dial FL_FILL_DIAL"} callback callback tooltip {Fill Dial} xywh {480 295 65 65} type Fill color 10 selection_color 1 labelsize 8 value 1 code0 {o->angles(0,360);} } } Fl_Group {} { label Fl_Roller xywh {300 385 150 115} box ENGRAVED_BOX labelfont 1 align 17 } { Fl_Roller {} { label 0 user_data {"Fl_Roller FL_VERTICAL"} callback callback tooltip {Vertical Roller} xywh {315 390 20 95} labelsize 8 } Fl_Roller {} { label FL_HORIZONTAL user_data {"Fl_Roller FL_HORIZONTAL"} callback callback tooltip {Horizontal Roller} xywh {345 430 90 20} type Horizontal labelsize 8 } } Fl_Box {} { label {Some widgets have color(FL_GREEN) and color2(FL_RED) to show the areas these effect.} xywh {460 385 110 115} box BORDER_FRAME color 0 selection_color 0 labelsize 11 align 128 } Fl_Terminal tty {selected xywh {10 513 560 117} code0 {o->ansi(true);} } } } Function {callback(Fl_Widget* o, void*)} {open return_type void } { code {const char *name = (const char*)(o->user_data() ? o->user_data() : "???"); tty->printf("callback(): %s value() = \\033[1m%g\\033[0m\\n", name, ((Fl_Valuator*)o)->value());} {} } Function {callback_spinner(Fl_Widget* o, void*)} { comment {Spinner doesn't derive from Fl_Valuator..} open return_type void } { code {const char *name = (const char*)(o->user_data() ? o->user_data() : "???"); tty->printf("callback(): %s value() = \\033[1m%g\\033[0m\\n", name, ((Fl_Spinner*)o)->value());} {} } fltk-1.4.3/test/input_choice.cxx0000644000175000017500000000514315004135251016764 0ustar albrechtalbrecht// // Test program for Fl_Input_Choice and Fl_Choice // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #define TERMINAL_HEIGHT 150 // Globals Fl_Terminal *G_tty = 0; void active_cb(Fl_Widget *w, void *data) { Fl_Check_Button *b = (Fl_Check_Button *)w; Fl_Group *g = (Fl_Group *)data; if (b->value()) { g->activate(); G_tty->printf("activate group\n"); } else { g->deactivate(); G_tty->printf("deactivate group\n"); } g->redraw(); if (b->changed()) { G_tty->printf("Callback: changed() is set\n"); b->clear_changed(); } } void input_choice_cb(Fl_Widget *, void *data) { Fl_Input_Choice *in = (Fl_Input_Choice *)data; G_tty->printf("Fl_Input_Choice value='%s'\n", (const char *)in->value()); } void choice_cb(Fl_Widget *, void *data) { Fl_Choice *in = (Fl_Choice *)data; G_tty->printf("Fl_Choice value='%d'\n", in->value()); } int main(int argc, char **argv) { Fl_Window *win = new Fl_Double_Window(300, 200 + TERMINAL_HEIGHT); G_tty = new Fl_Terminal(0, 200, win->w(), TERMINAL_HEIGHT); // this group can be activated and deactivated: Fl_Group *active_group = new Fl_Group(0, 0, 300, 120); // all *_Choice widgets must be aligned for easier visual comparison: Fl_Input_Choice *in = new Fl_Input_Choice(180, 40, 100, 25, "Fl_Input_Choice:"); in->callback(input_choice_cb, (void *)in); in->add("one"); in->add("two"); in->add("three"); in->value(0); Fl_Choice *choice = new Fl_Choice(180, 70, 100, 25, "Fl_Choice:"); choice->callback(choice_cb, (void *)choice); choice->add("aaa"); choice->add("bbb"); choice->add("ccc"); choice->value(1); active_group->end(); // Interactive control of scheme Fl_Scheme_Choice *sch = new Fl_Scheme_Choice(180, 120, 100, 25, "Choose scheme:"); sch->visible_focus(0); Fl_Check_Button *active = new Fl_Check_Button(50, 160, 160, 30, "Activate/deactivate"); active->callback(active_cb, (void *)active_group); active->value(1); win->end(); win->resizable(win); win->size_range(200, 160); win->show(argc, argv); Fl::run(); delete win; return 0; } fltk-1.4.3/test/Makefile0000644000175000017500000005044115004135251015230 0ustar albrechtalbrecht# # Test/demo program Makefile for the Fast Light Tool Kit (FLTK). # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # include ../makeinclude CPPUNITTEST = \ unittests.cxx \ unittest_about.cxx \ unittest_points.cxx \ unittest_complex_shapes.cxx \ unittest_fast_shapes.cxx \ unittest_circles.cxx \ unittest_text.cxx \ unittest_unicode.cxx \ unittest_symbol.cxx \ unittest_images.cxx \ unittest_viewport.cxx \ unittest_scrollbarsize.cxx \ unittest_schemes.cxx \ unittest_terminal.cxx \ unittest_core.cxx OBJUNITTEST = \ $(CPPUNITTEST:.cxx=.o) CPPFILES =\ adjuster.cxx \ animated.cxx \ arc.cxx \ ask.cxx \ bitmap.cxx \ blocks.cxx \ boxtype.cxx \ browser.cxx \ button.cxx \ buttons.cxx \ cairo_test.cxx \ checkers.cxx \ clipboard.cxx \ clock.cxx \ colbrowser.cxx \ color_chooser.cxx \ contrast.cxx \ cube.cxx \ CubeMain.cxx \ CubeView.cxx \ cursor.cxx \ curve.cxx \ demo.cxx \ device.cxx \ doublebuffer.cxx \ editor.cxx \ fast_slow.cxx \ file_chooser.cxx \ flex_demo.cxx \ flex_login.cxx \ fltk-versions.cxx \ fonts.cxx \ forms.cxx \ fractals.cxx \ fracviewer.cxx \ fullscreen.cxx \ gl_overlay.cxx \ glpuzzle.cxx \ glut_test.cxx \ grid_alignment \ grid_buttons \ grid_dialog \ grid_login \ hello.cxx \ help_dialog.cxx \ icon.cxx \ iconize.cxx \ image.cxx \ inactive.cxx \ input.cxx \ input_choice.cxx \ keyboard.cxx \ label.cxx \ line_style.cxx \ line_style_docs.cxx \ list_visuals.cxx \ mandelbrot.cxx \ menubar.cxx \ message.cxx \ minimum.cxx \ native-filechooser.cxx \ navigation.cxx \ offscreen.cxx \ output.cxx \ overlay.cxx \ pack.cxx \ pixmap_browser.cxx \ pixmap.cxx \ preferences.cxx \ radio.cxx \ resize.cxx \ resizebox.cxx \ resize-example1.cxx \ resize-example2.cxx \ resize-example3a.cxx \ resize-example3b.cxx \ resize-example3c.cxx \ resize-example4a.cxx \ resize-example4b.cxx \ resize-example5a.cxx \ resize-example5b.cxx \ resize-example5c.cxx \ rotated_text.cxx \ scroll.cxx \ shape.cxx \ subwindow.cxx \ sudoku.cxx \ symbols.cxx \ table.cxx \ tabs.cxx \ terminal.cxx \ threads.cxx \ tile.cxx \ tiled_image.cxx \ tree.cxx \ twowin.cxx \ utf8.cxx \ valuators.cxx \ windowfocus.cxx \ wizard.cxx \ $(CPPUNITTEST) ALL = \ animated$(EXEEXT) \ adjuster$(EXEEXT) \ arc$(EXEEXT) \ ask$(EXEEXT) \ bitmap$(EXEEXT) \ blocks$(EXEEXT) \ boxtype$(EXEEXT) \ browser$(EXEEXT) \ button$(EXEEXT) \ buttons$(EXEEXT) \ cairo_test$(EXEEXT) \ clipboard$(EXEEXT) \ clock$(EXEEXT) \ colbrowser$(EXEEXT) \ color_chooser$(EXEEXT) \ contrast$(EXEEXT) \ cursor$(EXEEXT) \ curve$(EXEEXT) \ demo$(EXEEXT) \ device$(EXEEXT) \ doublebuffer$(EXEEXT) \ editor$(EXEEXT) \ file_chooser$(EXEEXT) \ flex_demo$(EXEEXT) \ flex_login$(EXEEXT) \ fltk-versions$(EXEEXT) \ fonts$(EXEEXT) \ forms$(EXEEXT) \ grid_alignment$(EXEEXT) \ grid_buttons$(EXEEXT) \ grid_dialog$(EXEEXT) \ grid_login$(EXEEXT) \ hello$(EXEEXT) \ help_dialog$(EXEEXT) \ icon$(EXEEXT) \ iconize$(EXEEXT) \ image$(EXEEXT) \ input$(EXEEXT) \ input_choice$(EXEEXT) \ label$(EXEEXT) \ line_style$(EXEEXT) \ line_style_docs$(EXEEXT) \ list_visuals$(EXEEXT) \ menubar$(EXEEXT) \ message$(EXEEXT) \ minimum$(EXEEXT) \ native-filechooser$(EXEEXT) \ navigation$(EXEEXT) \ offscreen$(EXEEXT) \ output$(EXEEXT) \ overlay$(EXEEXT) \ pack$(EXEEXT) \ pixmap$(EXEEXT) \ pixmap_browser$(EXEEXT) \ device$(EXEEXT) \ resizebox$(EXEEXT) \ resize-example1$(EXEEXT) \ resize-example2$(EXEEXT) \ resize-example3a$(EXEEXT) \ resize-example3b$(EXEEXT) \ resize-example3c$(EXEEXT) \ resize-example4a$(EXEEXT) \ resize-example4b$(EXEEXT) \ resize-example5a$(EXEEXT) \ resize-example5b$(EXEEXT) \ resize-example5c$(EXEEXT) \ rotated_text$(EXEEXT) \ scroll$(EXEEXT) \ subwindow$(EXEEXT) \ sudoku$(EXEEXT) \ symbols$(EXEEXT) \ table$(EXEEXT) \ $(THREADS) \ tile$(EXEEXT) \ tiled_image$(EXEEXT) \ twowin$(EXEEXT) \ utf8$(EXEEXT) \ windowfocus$(EXEEXT) \ wizard$(EXEEXT) ALLFLUID = \ checkers$(EXEEXT) \ fast_slow$(EXEEXT) \ inactive$(EXEEXT) \ keyboard$(EXEEXT) \ mandelbrot$(EXEEXT) \ preferences$(EXEEXT) \ radio$(EXEEXT) \ resize$(EXEEXT) \ tabs$(EXEEXT) \ terminal$(EXEEXT) \ tree$(EXEEXT) \ valuators$(EXEEXT) \ CubeView$(EXEEXT) GLALL = \ cube$(EXEEXT) \ fractals$(EXEEXT) \ fullscreen$(EXEEXT) \ gl_overlay$(EXEEXT) \ glpuzzle$(EXEEXT) \ glut_test$(EXEEXT) \ shape$(EXEEXT) \ unittests$(EXEEXT) all: $(ALL) $(GLDEMOS) for dir in $(FLUIDDIR); do\ $(MAKE) $(MFLAGS) $(ALLFLUID);\ done gldemos: $(GLALL) depend: $(CPPFILES) makedepend -Y -I.. -f makedepend -w 20 $(CPPFILES) echo "# DO NOT DELETE THIS LINE -- make depend depends on it." > makedepend.tmp echo "" >> makedepend.tmp grep '^[a-zA-Z]' makedepend | ( LC_ALL=C sort -u -f >> makedepend.tmp; ) mv makedepend.tmp makedepend # Automatically generated dependencies... include makedepend clean: $(RM) $(ALL) $(ALLFLUID) $(GLALL) core $(RMDIR) *.app $(RM) *.o core.* *~ *.bck *.bak $(RM) CubeViewUI.cxx CubeViewUI.h $(RM) checkers_pieces.cxx checkers_pieces.h $(RM) fast_slow.cxx fast_slow.h $(RM) inactive.cxx inactive.h $(RM) keyboard_ui.cxx keyboard_ui.h $(RM) mandelbrot_ui.cxx mandelbrot_ui.h $(RM) preferences.cxx preferences.h $(RM) radio.cxx radio.h $(RM) resize.cxx resize.h $(RM) tabs.cxx tabs.h $(RM) terminal.cxx terminal.h $(RM) tree.cxx tree.h $(RM) valuators.cxx valuators.h install: all echo "Installing example programs to $(DESTDIR)$(docdir)/examples..." -$(INSTALL_DIR) "$(DESTDIR)$(docdir)/examples" for file in *.h *.cxx *.fl demo.menu; do \ $(INSTALL_DATA) $$file "$(DESTDIR)$(docdir)/examples"; \ done -$(INSTALL_DIR) "$(DESTDIR)$(docdir)/examples/pixmaps" for file in pixmaps/*.xbm pixmaps/*.xpm; do \ $(INSTALL_DATA) $$file "$(DESTDIR)$(docdir)/examples/pixmaps"; \ done install-linux: echo Installing games to $(DESTDIR)$(bindir)... -$(INSTALL_DIR) "$(DESTDIR)$(bindir)" -$(INSTALL_DIR) "$(DESTDIR)$(datadir)/applications" -$(INSTALL_DIR) "$(DESTDIR)$(datadir)/icons/hicolor/32x32/apps" -$(INSTALL_DIR) "$(DESTDIR)$(datadir)/icons/hicolor/128x128/apps" for game in blocks checkers sudoku; do \ $(INSTALL_BIN) $$game "$(DESTDIR)$(bindir)"; \ $(INSTALL_DATA) desktop/$$game.desktop "$(DESTDIR)$(datadir)/applications"; \ $(INSTALL_DATA) desktop/$$game-32.png "$(DESTDIR)$(datadir)/icons/hicolor/32x32/apps/$$game.png"; \ $(INSTALL_DATA) desktop/$$game-128.png "$(DESTDIR)$(datadir)/icons/hicolor/128x128/apps/$$game.png"; \ done install-osx: echo Installing games in $(DESTDIR)/Applications... for game in blocks checkers sudoku; do \ if test ! -d "$(DESTDIR)/Applications/$$game.app"; then \ $(INSTALL_DIR) "$(DESTDIR)/Applications/$$game.app"; \ $(INSTALL_DIR) "$(DESTDIR)/Applications/$$game.app/Contents"; \ $(INSTALL_DIR) "$(DESTDIR)/Applications/$$game.app/Contents/MacOS"; \ $(INSTALL_DIR) "$(DESTDIR)/Applications/$$game.app/Contents/Resources"; \ fi; \ $(INSTALL_DATA) $$game.app/Contents/Info.plist "$(DESTDIR)/Applications/$$game.app/Contents"; \ $(INSTALL_BIN) $$game.app/Contents/MacOS/$$game "$(DESTDIR)/Applications/$$game.app/Contents/MacOS"; \ $(INSTALL_DATA) $$game.app/Contents/Resources/$$game.icns "$(DESTDIR)/Applications/$$game.app/Contents/Resources"; \ done uninstall: echo "Removing examples programs from $(DESTDIR)$(docdir)/examples..." -$(RMDIR) "$(DESTDIR)$(docdir)/examples" uninstall-linux: echo Removing games from $(DESTDIR)$(bindir)... for game in blocks checkers sudoku; do \ $(RM) "$(DESTDIR)$(bindir)/$$game"; \ $(RM) "$(DESTDIR)$(datadir)/applications/$$game.desktop"; \ $(RM) "$(DESTDIR)$(datadir)/icons/hicolor/32x32/apps/$$game.png"; \ $(RM) "$(DESTDIR)$(datadir)/icons/hicolor/128x128/apps/$$game.png"; \ done uninstall-osx: echo Removing games from $(DESTDIR)/Applications... $(RMDIR) "$(DESTDIR)/Applications/blocks.app" $(RMDIR) "$(DESTDIR)/Applications/checkers.app" $(RMDIR) "$(DESTDIR)/Applications/sudoku.app" # FLUID file rules .fl.cxx .fl.h: echo Generating $@ and header from $<... $(FLUID_BUILD) -c $< # All demos depend on the FLTK library... $(ALL): $(LIBNAME) # General demos... unittests$(EXEEXT): $(OBJUNITTEST) adjuster$(EXEEXT): adjuster.o animated$(EXEEXT): animated.o arc$(EXEEXT): arc.o ask$(EXEEXT): ask.o bitmap$(EXEEXT): bitmap.o boxtype$(EXEEXT): boxtype.o browser$(EXEEXT): browser.o button$(EXEEXT): button.o buttons$(EXEEXT): buttons.o blocks$(EXEEXT): blocks.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) blocks.o -o $@ $(AUDIOLIBS) $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) $(RM) -f -r blocks.app $(OSX_ONLY) mkdir -p blocks.app/Contents/MacOS blocks.app/Contents/Resources $(OSX_ONLY) $(INSTALL_BIN) blocks$(EXEEXT) blocks.app/Contents/MacOS $(OSX_ONLY) $(INSTALL_BIN) mac-resources/blocks.icns blocks.app/Contents/Resources/ $(OSX_ONLY) $(INSTALL_BIN) mac-resources/blocks.plist blocks.app/Contents/Info.plist checkers$(EXEEXT): checkers.o checkers_pieces.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) checkers.o checkers_pieces.o -o $@ $(LINKFLTKIMG) $(LDLIBS) $(OSX_ONLY) $(RM) -f -r checkers.app $(OSX_ONLY) mkdir -p checkers.app/Contents/MacOS checkers.app/Contents/Resources $(OSX_ONLY) $(INSTALL_BIN) checkers$(EXEEXT) checkers.app/Contents/MacOS $(OSX_ONLY) $(INSTALL_BIN) mac-resources/checkers.icns checkers.app/Contents/Resources/ $(OSX_ONLY) $(INSTALL_BIN) mac-resources/checkers.plist checkers.app/Contents/Info.plist checkers.cxx: checkers_pieces.h checkers_pieces.o: checkers_pieces.h checkers_pieces.h: checkers_pieces.fl checkers_pieces.cxx: checkers_pieces.fl ../fluid/fluid$(EXEEXT) clipboard$(EXEEXT): clipboard.o $(IMGLIBNAME) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) clipboard.o -o $@ $(LINKFLTKIMG) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ clock$(EXEEXT): clock.o colbrowser$(EXEEXT): colbrowser.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ colbrowser.o $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ $(OSX_ONLY) mkdir -p colbrowser.app/Contents/Resources $(OSX_ONLY) cp -f rgb.txt colbrowser.app/Contents/Resources/ color_chooser$(EXEEXT): color_chooser.o contrast$(EXEEXT): contrast.o cursor$(EXEEXT): cursor.o curve$(EXEEXT): curve.o demo$(EXEEXT): demo.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ demo.o $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ $(OSX_ONLY) mkdir -p demo.app/Contents/Resources $(OSX_ONLY) cp -f demo.menu demo.app/Contents/Resources/ device$(EXEEXT): device.o $(IMGLIBNAME) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) device.o -o $@ $(LINKFLTKIMG) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ doublebuffer$(EXEEXT): doublebuffer.o editor$(EXEEXT): editor.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) editor.o -o $@ $(LINKFLTKIMG) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ $(OSX_ONLY) cp -f mac-resources/editor.plist editor.app/Contents/Info.plist fast_slow$(EXEEXT): fast_slow.o fast_slow.cxx: fast_slow.fl ../fluid/fluid$(EXEEXT) file_chooser$(EXEEXT): file_chooser.o $(IMGLIBNAME) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) file_chooser.o -o $@ $(LINKFLTKIMG) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ flex_demo$(EXEEXT): flex_demo.o flex_login$(EXEEXT): flex_login.o fltk-versions$(EXEEXT): fltk-versions.o fonts$(EXEEXT): fonts.o forms$(EXEEXT): forms.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ forms.o $(LINKFLTKFORMS) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ grid_alignment$(EXEEXT): grid_alignment.o grid_buttons$(EXEEXT): grid_buttons.o grid_dialog$(EXEEXT): grid_dialog.o grid_login$(EXEEXT): grid_login.o hello$(EXEEXT): hello.o help_dialog$(EXEEXT): help_dialog.o $(IMGLIBNAME) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) help_dialog.o -o $@ $(LINKFLTKIMG) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ $(OSX_ONLY) mkdir -p help_dialog.app/Contents/Resources $(OSX_ONLY) cp -f help_dialog.html help_dialog.app/Contents/Resources/ icon$(EXEEXT): icon.o iconize$(EXEEXT): iconize.o image$(EXEEXT): image.o inactive$(EXEEXT): inactive.o inactive.cxx: inactive.fl ../fluid/fluid$(EXEEXT) input$(EXEEXT): input.o input_choice$(EXEEXT): input_choice.o keyboard$(EXEEXT): keyboard_ui.o keyboard.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ keyboard.o keyboard_ui.o $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ keyboard_ui.o: keyboard_ui.h keyboard_ui.cxx: keyboard_ui.fl ../fluid/fluid$(EXEEXT) label$(EXEEXT): label.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ label.o $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ line_style$(EXEEXT): line_style.o line_style_docs$(EXEEXT): line_style_docs.o list_visuals$(EXEEXT): list_visuals.o mandelbrot$(EXEEXT): mandelbrot_ui.o mandelbrot.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ mandelbrot.o mandelbrot_ui.o $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ mandelbrot_ui.o: mandelbrot_ui.h mandelbrot_ui.cxx: mandelbrot_ui.fl ../fluid/fluid$(EXEEXT) menubar$(EXEEXT): menubar.o message$(EXEEXT): message.o minimum$(EXEEXT): minimum.o native-filechooser$(EXEEXT): native-filechooser.o $(IMGLIBNAME) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) native-filechooser.o -o $@ $(LINKFLTKIMG) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ navigation$(EXEEXT): navigation.o offscreen$(EXEEXT): offscreen.o output$(EXEEXT): output.o $(FLLIBNAME) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ output.o $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ overlay$(EXEEXT): overlay.o pack$(EXEEXT): pack.o pixmap$(EXEEXT): pixmap.o $(IMGLIBNAME) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ pixmap.o $(LINKFLTKIMG) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ pixmap_browser$(EXEEXT): pixmap_browser.o $(IMGLIBNAME) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) pixmap_browser.o -o $@ $(LINKFLTKIMG) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ preferences$(EXEEXT): preferences.o preferences.cxx: preferences.fl ../fluid/fluid$(EXEEXT) device$(EXEEXT): device.o radio$(EXEEXT): radio.o radio.cxx: radio.fl ../fluid/fluid$(EXEEXT) resize$(EXEEXT): resize.o resize.cxx: resize.fl ../fluid/fluid$(EXEEXT) resizebox$(EXEEXT): resizebox.o resize-example1$(EXEEXT): resize-example1.o resize-arrows.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) resize-example1.o resize-arrows.o -o $@ $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ resize-example2$(EXEEXT): resize-example2.o resize-arrows.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) resize-example2.o resize-arrows.o -o $@ $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ resize-example3a$(EXEEXT): resize-example3a.o resize-arrows.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) resize-example3a.o resize-arrows.o -o $@ $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ resize-example3b$(EXEEXT): resize-example3b.o resize-arrows.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) resize-example3b.o resize-arrows.o -o $@ $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ resize-example3c$(EXEEXT): resize-example3c.o resize-arrows.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) resize-example3c.o resize-arrows.o -o $@ $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ resize-example4a$(EXEEXT): resize-example4a.o resize-arrows.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) resize-example4a.o resize-arrows.o -o $@ $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ resize-example4b$(EXEEXT): resize-example4b.o resize-arrows.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) resize-example4b.o resize-arrows.o -o $@ $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ resize-example5a$(EXEEXT): resize-example5a.o resize-arrows.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) resize-example5a.o resize-arrows.o -o $@ $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ resize-example5b$(EXEEXT): resize-example5b.o resize-arrows.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) resize-example5b.o resize-arrows.o -o $@ $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ resize-example5c$(EXEEXT): resize-example5c.o resize-arrows.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) resize-example5c.o resize-arrows.o -o $@ $(LINKFLTK) $(LDLIBS) $(OSX_ONLY) ../fltk-config --post $@ rotated_text$(EXEEXT): rotated_text.o scroll$(EXEEXT): scroll.o subwindow$(EXEEXT): subwindow.o sudoku: sudoku.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) sudoku.o -o $@ $(AUDIOLIBS) $(LINKFLTKIMG) $(LDLIBS) $(OSX_ONLY) $(RM) -f -r sudoku.app $(OSX_ONLY) mkdir -p sudoku.app/Contents/MacOS sudoku.app/Contents/Resources $(OSX_ONLY) $(INSTALL_BIN) sudoku$(EXEEXT) sudoku.app/Contents/MacOS $(OSX_ONLY) $(INSTALL_BIN) mac-resources/sudoku.icns sudoku.app/Contents/Resources/ $(OSX_ONLY) $(INSTALL_BIN) mac-resources/sudoku.plist sudoku.app/Contents/Info.plist sudoku.exe: sudoku.o sudoku.rc echo Linking $@... $(RC) sudoku.rc sudokures.o $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) sudoku.o sudokures.o -o $@ $(AUDIOLIBS) $(LINKFLTKIMG) $(LDLIBS) symbols$(EXEEXT): symbols.o table$(EXEEXT): table.o tabs$(EXEEXT): tabs.o tabs.cxx: tabs.fl ../fluid/fluid$(EXEEXT) terminal$(EXEEXT): terminal.o terminal.cxx: terminal.fl ../fluid/fluid$(EXEEXT) threads$(EXEEXT): threads.o # This ensures that we have this dependency even if threads are not # enabled in the current tree... threads.o: threads.h tile$(EXEEXT): tile.o tiled_image$(EXEEXT): tiled_image.o tree$(EXEEXT): tree.o tree.cxx: tree.fl ../fluid/fluid$(EXEEXT) twowin$(EXEEXT): twowin.o valuators$(EXEEXT): valuators.o valuators.cxx: valuators.fl ../fluid/fluid$(EXEEXT) # All OpenGL demos depend on the FLTK and FLTK_GL libraries... $(GLALL): $(LIBNAME) $(GLLIBNAME) # OpenGL demos... CubeView$(EXEEXT): CubeMain.o CubeView.o CubeViewUI.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ \ CubeMain.o CubeView.o CubeViewUI.o \ $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) $(OSX_ONLY) ../fltk-config --post $@ CubeMain.o: CubeViewUI.h CubeView.h CubeViewUI.cxx CubeView.o: CubeView.h CubeViewUI.o: CubeViewUI.cxx CubeViewUI.h CubeViewUI.cxx: CubeViewUI.fl ../fluid/fluid$(EXEEXT) cube$(EXEEXT): cube.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ cube.o $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) $(OSX_ONLY) ../fltk-config --post $@ fractals$(EXEEXT): fractals.o fracviewer.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ fractals.o fracviewer.o $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) $(OSX_ONLY) ../fltk-config --post $@ fullscreen$(EXEEXT): fullscreen.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ fullscreen.o $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) $(OSX_ONLY) ../fltk-config --post $@ glpuzzle$(EXEEXT): glpuzzle.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ glpuzzle.o $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) $(OSX_ONLY) ../fltk-config --post $@ gl_overlay$(EXEEXT): gl_overlay.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ gl_overlay.o $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) $(OSX_ONLY) ../fltk-config --post $@ glut_test$(EXEEXT): glut_test.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ glut_test.o $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) $(OSX_ONLY) ../fltk-config --post $@ unittests$(EXEEXT): $(OBJUNITTEST) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJUNITTEST) $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) $(OSX_ONLY) ../fltk-config --post $@ shape$(EXEEXT): shape.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ shape.o $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) $(OSX_ONLY) ../fltk-config --post $@ cairo_test$(EXEEXT): cairo_test.o echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(CAIROFLAGS) $(LDFLAGS) -o $@ cairo_test.o $(LINKFLTK) $(CAIROLIBS) $(GLDLIBS) $(OSX_ONLY) ../fltk-config --post $@ fltk-1.4.3/test/tree.fl0000644000175000017500000020331015004135251015045 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {\#include } {public global } decl {int G_cb_counter = 0;} { comment {// Global callback event counter} private local } Function {reason_as_name(Fl_Tree_Reason reason)} { comment {Return an Fl_Tree_Reason as a text string name} return_type {const char*} } { code {switch ( reason ) { case FL_TREE_REASON_NONE: return("none"); case FL_TREE_REASON_SELECTED: return("selected"); case FL_TREE_REASON_DESELECTED: return("deselected"); case FL_TREE_REASON_OPENED: return("opened"); case FL_TREE_REASON_CLOSED: return("closed"); case FL_TREE_REASON_DRAGGED: return("dragged"); case FL_TREE_REASON_RESELECTED: return("reselected"); default: return("???"); }} {} } Function {Button_CB(Fl_Widget*w, void*data)} {open return_type void } { code {// Each push changes height so we can test 'Item h() from widget' // Cycle through larger sizes until 50, then wrap to normal size. // // In the case of 'ccc button', it is the child widget, so change // its size. // // In the case of the 'D1' and 'D2' buttons, the parent's Fl_Group // is the child, so change the size of that instead. // Fl_Widget *cw = strcmp(w->label(), "ccc button")==0 ? w : w->parent(); int height = cw->h(); height += 10; if ( height > 50 ) height = 20; cw->resize(cw->x(), cw->y(), cw->w(), height); tree->redraw(); // adjusted height tty->printf("'%s' button pushed (height=%d)\\n", w->label(), height);} {} } Function {AssignUserIcons()} { comment {Assign user icons to the items} open } { code {static const char *L_folder_xpm[] = { "11 11 3 1", ". c None", "x c \#d8d833", "@ c \#808011", "...........", ".....@@@@..", "....@xxxx@.", "@@@@@xxxx@@", "@xxxxxxxxx@", "@xxxxxxxxx@", "@xxxxxxxxx@", "@xxxxxxxxx@", "@xxxxxxxxx@", "@xxxxxxxxx@", "@@@@@@@@@@@"}; static Fl_Pixmap L_folder_pixmap(L_folder_xpm); static const char *L_document_xpm[] = { "11 11 3 1", ". c None", "x c \#d8d8f8", "@ c \#202060", ".@@@@@@@@@.", ".@xxxxxxx@.", ".@xxxxxxx@.", ".@xxxxxxx@.", ".@xxxxxxx@.", ".@xxxxxxx@.", ".@xxxxxxx@.", ".@xxxxxxx@.", ".@xxxxxxx@.", ".@xxxxxxx@.", ".@@@@@@@@@."}; static Fl_Pixmap L_document_pixmap(L_document_xpm); // Create deactivated version of document icon static Fl_Pixmap L_folder_deicon_pixmap(L_folder_xpm); // copy static Fl_Pixmap L_document_deicon_pixmap(L_document_xpm); // copy static int first = 1; if ( first ) { L_folder_deicon_pixmap.inactive(); L_document_deicon_pixmap.inactive(); first = 0; } // Assign user icons to tree items for ( Fl_Tree_Item *item = tree->first(); item; item=item->next()) { if ( usericon_radio->value() ) { // Assign custom icons if ( item->has_children() ) { item->usericon(&L_folder_pixmap); item->userdeicon(&L_folder_deicon_pixmap); } else { item->usericon(&L_document_pixmap); item->userdeicon(&L_document_deicon_pixmap); } } else { // Don't assign custom icons item->usericon(0); item->userdeicon(0); } } tree->redraw();} {} } Function {RebuildTree()} { comment {Rebuild the 'example tree' from scratch} open } { code {// REBUILD THE TREE TO MAKE CURRENT "DEFAULT" PREFS TAKE EFFECT tree->clear(); tree->add("Aaa"); tree->add("Bbb"); tree->add("Ccc"); tree->add("Ddd"); tree->add("Bbb/child-01"); tree->add("Bbb/child-01/111"); tree->add("Bbb/child-01/222"); tree->add("Bbb/child-01/333"); tree->add("Bbb/child-02"); tree->add("Bbb/child-03"); tree->add("Bbb/child-04"); { static Fl_Input *in = 0; // Assign an FLTK input widget to one of the items with a label() of its own (STR\#2832) Fl_Tree_Item *i; if ( ( i = tree->find_item("Bbb/child-02") ) != NULL ) { if ( !in ) { // only do this once at program startup tree->begin(); in = new Fl_Input(1,1,100,1,"Fl_Input test"); // we control w() only in->labelsize(10); in->textsize(10); in->align(FL_ALIGN_RIGHT); // show label to the right of the widget in->tooltip("Fl_Input inside tree.\\n" "The widget's label 'Fl_Input test' should appear to the widget's right."); } in->show(); i->widget(in); tree->end(); } } { static Fl_Button *but = 0; // Assign an FLTK widget to one of the items Fl_Tree_Item *i; if ( ( i = tree->find_item("Bbb/child-03") ) != NULL ) { if ( !but ) { // only do this once at program startup tree->begin(); but = new Fl_Button(1,1,140,1,"ccc button"); // we control w() only but->labelsize(10); but->callback(Button_CB); but->tooltip("Button inside tree.\\n" "If 'Item h() from widget' enabled, " "pressing button enlarges it."); } but->show(); i->widget(but); tree->end(); } } { // Assign an FLTK group to one of the items with widgets Fl_Tree_Item *i; const char *tipmsg = "A group of two buttons inside the tree.\\n" "If 'Item h() from widget' enabled, " "pressing either button enlarges the group " "and both buttons together."; if ( ( i = tree->find_item("Bbb/child-04") ) != NULL ) { static Fl_Group *grp = 0; if ( !grp ) { // only do this once at program startup tree->begin(); grp = new Fl_Group(100,100,140,18); // build group.. tree handles position grp->color(FL_WHITE); grp->begin(); Fl_Button *abut = new Fl_Button(grp->x()+0 ,grp->y()+2,65,15,"D1"); abut->labelsize(10); abut->callback(Button_CB); abut->tooltip(tipmsg); Fl_Button *bbut = new Fl_Button(grp->x()+75,grp->y()+2,65,15,"D2"); bbut->labelsize(10); bbut->callback(Button_CB); bbut->tooltip(tipmsg); grp->end(); grp->resizable(grp); tree->end(); } grp->show(); i->widget(grp); } } // Add an 'Ascending' node, and create it sorted tree->sortorder(FL_TREE_SORT_NONE); tree->add("Ascending")->close(); tree->sortorder(FL_TREE_SORT_ASCENDING); tree->add("Ascending/Zzz"); tree->add("Ascending/Xxx"); tree->add("Ascending/Aaa"); tree->add("Ascending/Bbb"); tree->add("Ascending/Yyy"); tree->add("Ascending/Ccc"); // Add a 'Descending' node, and create it sorted tree->sortorder(FL_TREE_SORT_NONE); tree->add("Descending")->close(); tree->sortorder(FL_TREE_SORT_DESCENDING); tree->add("Descending/Zzz"); tree->add("Descending/Xxx"); tree->add("Descending/Aaa"); tree->add("Descending/Bbb"); tree->add("Descending/Yyy"); tree->add("Descending/Ccc"); // Add a long line to trigger horiz scrollbar tree->sortorder(FL_TREE_SORT_NONE); tree->add("Long Line")->close(); tree->add("Long Line/The quick brown fox jumped over the lazy dog. 0123456789"); tree->add("Long Line/Longer Line")->close(); tree->add("Long Line/Longer Line/The quick brown fox jumped over the lazy dog. ---------------- 0123456789"); // Add 500 items in numerical order for ( int t=0; t<500; t++ ) { static char s[80]; snprintf(s, 80, "500 Items/item %04d", t+1); tree->add(s); } tree->close("500 Items"); // close the 500 items by default AssignUserIcons(); tree->redraw(); Fl_Group::current(0);} {} } Function {EditColor(Fl_Color &val)} { comment {Prompt the user to change the specified color} return_type Fl_Color } { code {// Returns: // 1 if color picked with new color in 'val' // 0 if user hit 'Cancel'. // uchar r,g,b; // Get the current color Fl::get_color(val,r,g,b); // Bring up a color chooser to edit it int ret = fl_color_chooser("Choose Color",r,g,b); val = fl_rgb_color(r,g,b); return(ret);} {} } Function {UpdateColorChips()} { comment {Updates the color chips with current colors from widget} open return_type void } { code {color_button->color(tree->color()); labelcolor_button->color(tree->labelcolor()); selection_color_button->color(tree->selection_color()); item_labelfgcolor_button->color(tree->item_labelfgcolor()); item_labelbgcolor_button->color(tree->item_labelbgcolor()); all_labelfgcolor_button->color(tree->item_labelfgcolor()); // use default all_labelbgcolor_button->color(tree->item_labelbgcolor()); // use default window->redraw();} {} } Function {GetTreeMarginBottom()} { comment {Get the current 'margin bottom' size Handles this as an ABI feature..} open return_type int } { code {return tree->marginbottom();} {} } Function {GetTreeWidgetMarginLeft()} { comment {Get the current 'margin bottom' size Handles this as an ABI feature..} open return_type int } { code {return tree->widgetmarginleft();} {} } Function {GetSelectedItemFGColor()} { comment {Return the selected item's fg color} open return_type Fl_Color } { code {Fl_Tree_Item *item; for ( item=tree->first(); item; item = tree->next(item) ) { if ( item->is_selected() ) { return(item->labelfgcolor()); } } // No items selected? Use default return(tree->item_labelfgcolor());} {} } Function {GetSelectedItemBGColor()} { comment {Return the selected item's bg color} open return_type Fl_Color } { code {Fl_Tree_Item *item; for ( item=tree->first(); item; item = tree->next(item) ) { if ( item->is_selected() ) { return(item->labelbgcolor()); } } // No items selected? Use default return(tree->item_labelbgcolor());} {} } Function {} {open } { Fl_Window window { label tree open xywh {456 262 1045 730} type Double visible } { Fl_Group tree { label Tree user_data 1234 callback {G_cb_counter++; // Increment callback counter whenever tree callback is invoked Fl_Tree_Item *item = tree->callback_item(); if ( item ) { tty->printf("TREE CALLBACK: label='%s' userdata=%ld reason=%s, changed=%d", item->label(), (long)(fl_intptr_t)tree->user_data(), reason_as_name(tree->callback_reason()), tree->changed() ? 1 : 0); // More than one click? show click count // Should only happen if reason==FL_TREE_REASON_RESELECTED. // if ( Fl::event_clicks() > 0 ) { tty->printf(", clicks=%d\\n", (Fl::event_clicks()+1)); } else { tty->printf("\\n"); } } else { tty->printf("TREE CALLBACK: reason=%s, changed=%d, item=(no item -- probably multiple items were changed at once)\\n", reason_as_name(tree->callback_reason()), tree->changed() ? 1 : 0); } tree->clear_changed();} open tooltip {Test tree} xywh {15 22 320 539} box DOWN_BOX color 55 selection_color 15 class Fl_Tree } {} Fl_Group {} {open xywh {350 5 681 556} code0 {o->resizable(0);} } { Fl_Group {} { label {Tree Globals} tooltip {These controls only affect the selected items. If no items are selected, all existing items in tree are modified.} xywh {350 23 330 389} box GTK_DOWN_BOX color 47 labelsize 12 } { Fl_Value_Slider margintop_slider { label {margintop()} user_data tree callback {int val = (int)margintop_slider->value(); tree->margintop(val); tree->redraw();} tooltip {Changes the top margin for the tree widget} xywh {505 36 155 16} type Horizontal color 46 selection_color 1 labelsize 10 align 4 textsize 9 code0 {o->value(tree->margintop());} code1 {o->range(0.0, 100.0);} code2 {o->step(1.0);} } Fl_Value_Slider marginleft_slider { label {marginleft()} user_data tree callback {int val = (int)marginleft_slider->value(); tree->marginleft(val); tree->redraw();} tooltip {Changes the left margin for the tree widget} xywh {505 56 155 16} type Horizontal color 46 selection_color 1 labelsize 10 align 4 textsize 9 code0 {o->value(tree->marginleft());} code1 {o->range(0.0, 200.0);} code2 {o->step(1.0);} } Fl_Value_Slider marginbottom_slider { label {marginbottom()} user_data tree callback {int val = (int)marginbottom_slider->value(); tree->marginbottom(val); tree->redraw();} tooltip {Changes the bottom margin for the tree Sets how far beyond bottom of tree you can scroll} xywh {505 76 155 16} type Horizontal color 46 selection_color 1 labelsize 10 align 4 textsize 9 code0 {o->value(GetTreeMarginBottom()); // handle ABI feature} code1 {o->range(0.0, 275.0);} code2 {o->step(1.0);} code3 {o->do_callback();} } Fl_Value_Slider linespacing_slider { label {linespacing()} user_data tree callback {int val = (int)linespacing_slider->value(); tree->linespacing(val); tree->redraw();} tooltip {Changes the spacing between items in the tree} xywh {505 96 155 16} type Horizontal color 46 selection_color 1 labelsize 10 align 4 textsize 9 code0 {o->value(tree->linespacing());} code1 {o->range(0.0, 100.0);} code2 {o->step(1.0);} } Fl_Value_Slider usericonmarginleft_slider { label {usericonmarginleft()} user_data tree callback {int val = (int)usericonmarginleft_slider->value(); tree->usericonmarginleft(val); tree->redraw();} tooltip {Changes the left margin for the user icons (if any)} xywh {505 116 155 16} type Horizontal color 46 selection_color 1 labelsize 10 align 4 textsize 9 code0 {o->value(tree->usericonmarginleft());} code1 {o->range(0.0, 100.0);} code2 {o->step(1.0);} } Fl_Value_Slider labelmarginleft_slider { label {labelmarginleft()} user_data tree callback {int val = (int)labelmarginleft_slider->value(); tree->labelmarginleft(val); tree->redraw();} tooltip {Changes the left margin for the item label} xywh {505 136 155 16} type Horizontal color 46 selection_color 1 labelsize 10 align 4 textsize 9 code0 {o->value(tree->labelmarginleft());} code1 {o->range(0.0, 100.0);} code2 {o->step(1.0);} } Fl_Value_Slider widgetmarginleft_slider { label {widgetmarginleft()} user_data tree callback {int val = (int)widgetmarginleft_slider->value(); tree->widgetmarginleft(val); tree->redraw();} tooltip {Changes the margin to the left of child FLTK widget() "Show label + widget" must be 'on' for this to take effect, i.e. item_draw_mode(FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET)} xywh {505 156 155 16} type Horizontal color 46 selection_color 1 labelsize 10 align 4 textsize 9 code0 {o->value(GetTreeWidgetMarginLeft()); // handle ABI feature} code1 {o->range(0.0, 100.0);} code2 {o->step(1.0);} code3 {o->do_callback();} } Fl_Value_Slider openchild_marginbottom_slider { label {openchild_marginbottom()} user_data tree callback {int val = (int)openchild_marginbottom_slider->value(); tree->openchild_marginbottom(val); tree->redraw();} tooltip {Changes the vertical space below an open child tree} xywh {505 176 155 16} type Horizontal color 46 selection_color 1 labelsize 10 align 4 textsize 9 code0 {o->value(tree->openchild_marginbottom());} code1 {o->range(0.0, 100.0);} code2 {o->step(1.0);} } Fl_Value_Slider connectorwidth_slider { label {connectorwidth()} user_data tree callback {tree->connectorwidth((int)connectorwidth_slider->value());} tooltip {Tests Fl_Tree::connectorwidth()} xywh {505 195 155 16} type Horizontal color 46 selection_color 1 labelsize 11 align 4 textsize 9 code0 {o->value(tree->connectorwidth());} code1 {o->range(1.0, 100.0);} code2 {o->step(1.0);} code3 {o->color(46); o->selection_color(FL_RED);} } Fl_Choice collapseicons_chooser { label {Collapse icons} callback {static const char *L_open_xpm[] = { \#ifdef __APPLE__ "11 11 3 1", ". c \#fefefe", "\# c \#444444", "@ c \#000000", "\#\#\#\#\#\#\#\#\#\#\#", "\#.........\#", "\#.........\#", "\#....@....\#", "\#....@....\#", "\#..@@@@@..\#", "\#....@....\#", "\#....@....\#", "\#.........\#", "\#.........\#", "\#\#\#\#\#\#\#\#\#\#\#" \#else "11 11 2 1", ". c None", "@ c \#000000", "...........", "....@......", "....@@.....", "....@@@....", "....@@@@...", "....@@@@@..", "....@@@@...", "....@@@....", "....@@.....", "....@......", "..........." \#endif }; static Fl_Pixmap L_openpixmap(L_open_xpm); static const char *L_close_xpm[] = { \#ifdef __APPLE__ "11 11 3 1", ". c \#fefefe", "\# c \#444444", "@ c \#000000", "\#\#\#\#\#\#\#\#\#\#\#", "\#.........\#", "\#.........\#", "\#.........\#", "\#.........\#", "\#..@@@@@..\#", "\#.........\#", "\#.........\#", "\#.........\#", "\#.........\#", "\#\#\#\#\#\#\#\#\#\#\#" \#else "11 11 2 1", ". c None", "@ c \#000000", "...........", "...........", "...........", "...........", ".@@@@@@@@@.", "..@@@@@@@..", "...@@@@@...", "....@@@....", ".....@.....", "...........", "..........." \#endif }; static Fl_Pixmap L_closepixmap(L_close_xpm); switch ( collapseicons_chooser->value() ) { case 0: tree->showcollapse(1); tree->openicon(0); tree->closeicon(0); break; case 1: tree->showcollapse(1); tree->openicon(&L_openpixmap); tree->closeicon(&L_closepixmap); break; case 2: tree->showcollapse(0); break; }} tooltip {Tests Fl_Tree::openicon(), Fl_Tree::closeicon() and Fl_Tree::showcollapse().} xywh {520 221 140 21} down_box BORDER_BOX labelsize 12 textsize 11 } { MenuItem {} { label Default xywh {10 10 36 21} labelsize 12 } MenuItem {} { label Custom xywh {20 20 36 21} labelsize 12 } MenuItem {} { label Off xywh {30 30 36 21} labelsize 12 } } Fl_Choice connectorstyle_chooser { label {Line style} callback {// CHANGE COLLAPSESTYLE switch ( connectorstyle_chooser->value() ) { case 0: tree->connectorstyle(FL_TREE_CONNECTOR_NONE); break; case 1: tree->connectorstyle(FL_TREE_CONNECTOR_DOTTED); break; case 2: tree->connectorstyle(FL_TREE_CONNECTOR_SOLID); break; }} tooltip {Tests Fl_Tree::connectorstyle() bit flags} xywh {520 245 140 21} down_box BORDER_BOX labelsize 12 textsize 11 code0 {switch (tree->connectorstyle()) { case FL_TREE_CONNECTOR_NONE: connectorstyle_chooser->value(0); break; case FL_TREE_CONNECTOR_DOTTED: connectorstyle_chooser->value(1); break; case FL_TREE_CONNECTOR_SOLID: connectorstyle_chooser->value(2); break; }} } { MenuItem {} { label None xywh {40 40 36 21} labelsize 12 } MenuItem {} { label Dotted xywh {20 20 36 21} labelsize 12 } MenuItem {} { label Solid xywh {30 30 36 21} labelsize 12 } } Fl_Choice selectmode_chooser { label {Selection Mode} callback {// Set selection mode switch ( selectmode_chooser->value() ) { case 0: tree->selectmode(FL_TREE_SELECT_NONE); break; // None case 1: tree->selectmode(FL_TREE_SELECT_SINGLE); break; // Single case 2: tree->selectmode(FL_TREE_SELECT_MULTI); break; // Multi case 3: tree->selectmode(FL_TREE_SELECT_SINGLE_DRAGGABLE); break; // Single draggable default: tree->selectmode(FL_TREE_SELECT_SINGLE); break; // Single }} tooltip {Tests Fl_Tree::selectmode() Sets how Fl_Tree handles mouse selection of tree items. NONE -- Not selectable by keyboard/mouse SINGLE -- Only one item at a time selectable by keyboard/mouse MULTI -- Multiple items selectable SINGLE+DRAG -- Lets user drag items to different position in tree} xywh {520 269 140 21} down_box BORDER_BOX labelsize 12 textsize 11 code0 {selectmode_chooser->value(2);} code1 {cb_selectmode_chooser(selectmode_chooser, (void*)0);} } { MenuItem {} { label None xywh {40 40 36 21} labelsize 12 } MenuItem {} { label Single xywh {50 50 36 21} labelsize 12 } MenuItem {} { label Multi xywh {60 60 36 21} labelsize 12 } MenuItem {} { label {Single + drag} xywh {70 70 36 21} labelsize 12 } } Fl_Choice reselectmode_chooser { label {Item Reselect Mode} callback {// Set reselection mode switch ( reselectmode_chooser->value() ) { case 0: tree->item_reselect_mode(FL_TREE_SELECTABLE_ONCE); break; case 1: tree->item_reselect_mode(FL_TREE_SELECTABLE_ALWAYS); break; }} tooltip {Tests Fl_Tree::item_reselect_mode(). Enables 'reselect' events. These happen when someone selects an item already selected (mouse drags or multi-clicks)} xywh {520 293 140 21} down_box BORDER_BOX labelsize 12 textsize 11 code0 {reselectmode_chooser->value(1);} code1 {reselectmode_chooser->do_callback();} } { MenuItem {} { label {Selectable Once} xywh {50 50 36 21} labelsize 12 } MenuItem {} { label {Selectable Always} xywh {60 60 36 21} labelsize 12 } } Fl_Choice whenmode_chooser { label When callback {// Set when mode switch ( whenmode_chooser->value() ) { case 0: tree->when(FL_WHEN_RELEASE); break; case 1: tree->when(FL_WHEN_CHANGED); break; case 2: tree->when(FL_WHEN_NEVER); break; default: tree->when(FL_WHEN_RELEASE); break; }} tooltip {Sets when() the tree's callback is invoked} xywh {520 319 140 21} down_box BORDER_BOX labelsize 12 textsize 11 code0 {whenmode_chooser->value(1);} code1 {cb_whenmode_chooser(whenmode_chooser, (void*)0);} } { MenuItem {} { label Changed xywh {50 50 36 21} labelsize 12 } MenuItem {} { label Released xywh {60 60 36 21} labelsize 12 } MenuItem {} { label Never xywh {70 70 36 21} labelsize 12 } } Fl_Check_Button usericon_radio { label {Enable user icons?} user_data tree callback {AssignUserIcons();} tooltip {Tests Fl_Tree_Item::usericon()} xywh {485 351 20 16} down_box DOWN_BOX labelsize 11 align 7 code0 {usericon_radio->value(1);} } Fl_Check_Button showroot_radio { label {Show root?} user_data tree callback {int onoff = showroot_radio->value(); tree->showroot(onoff);} tooltip {Tests tree->showroot();} xywh {485 368 20 16} down_box DOWN_BOX labelsize 11 align 7 code0 {int onoff = tree->showroot(); showroot_radio->value(onoff);} } Fl_Check_Button visiblefocus_checkbox { label {Visible focus?} user_data tree callback {int onoff = visiblefocus_checkbox->value(); tree->visible_focus(onoff);} tooltip {Toggles the tree's visible_focus() box} xywh {485 385 20 16} down_box DOWN_BOX labelsize 11 align 7 code0 {int onoff = tree->visible_focus(); visiblefocus_checkbox->value(onoff);} } Fl_Check_Button labelandwidget_radio { label {Show label + widget} callback {int flags = tree->item_draw_mode(); if ( labelandwidget_radio->value() ) { flags |= FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET; } else { flags &= ~FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET; } tree->item_draw_mode(flags); tree->redraw();} tooltip {Tests Fl_Tree::item_draw_mode(FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) Enables both label and widget() for display. When enabled, widget should appear to the right of the item's label. By default, the widget() is shown in place of the item's label.} xywh {645 351 20 16} down_box DOWN_BOX labelsize 11 align 7 code0 {labelandwidget_radio->value(0);} code1 {labelandwidget_radio->do_callback();} } Fl_Check_Button itemheightfromwidget_radio { label {Item h() from widget} callback {int flags = tree->item_draw_mode(); if ( itemheightfromwidget_radio->value() ) { flags |= FL_TREE_ITEM_HEIGHT_FROM_WIDGET; } else { flags &= ~FL_TREE_ITEM_HEIGHT_FROM_WIDGET; } tree->item_draw_mode(flags); tree->redraw();} tooltip {Tests Fl_Tree::item_draw_mode(FL_TREE_ITEM_HEIGHT_FROM_WIDGET) If enabled, item's height will track the widget()'s height. When enabled, click 'ccc button' or 'D1/D2' buttons to test.} xywh {645 368 20 16} down_box DOWN_BOX labelsize 11 align 7 code0 {itemheightfromwidget_radio->value(0);} code1 {itemheightfromwidget_radio->do_callback();} } Fl_Check_Button globalvisiblefocus_checkbox { label {Global visible focus?} user_data tree callback {int onoff = globalvisiblefocus_checkbox->value(); Fl::visible_focus(onoff);} tooltip {Toggles the global Fl::visible_focus()} xywh {645 385 20 16} down_box DOWN_BOX labelsize 11 align 7 code0 {int onoff = Fl::visible_focus(); globalvisiblefocus_checkbox->value(onoff);} } } Fl_Group {} { label {Test Operations} open tooltip {These controls only affect the defaults for new items that are created. These test the Fl_Tree_Prefs methods.} xywh {350 435 330 125} box GTK_DOWN_BOX color 47 labelsize 12 } { Fl_Group showitem_box { label {show_item() } xywh {370 460 70 82} box GTK_DOWN_BOX labelsize 11 } { Fl_Button {} { label Show callback {Fl_Tree_Item *item = tree->next_selected_item(); tree->show_item(item);} tooltip {Tests show_item() with no position specified. Makes the selected item visible IF it is off-screen. No change made if it is not off-screen.} xywh {385 469 40 17} labelsize 11 } Fl_Button {} { label Top callback {Fl_Tree_Item *item = tree->next_selected_item(); tree->show_item_top(item);} tooltip {Test show_item_top(). Scrolls selected item to the top of the display (only works if scrollbar showing) To use: 1) open '500 items' 2) select item 0010 3) Hit Top/Mid/Bot} xywh {385 486 40 16} labelsize 11 } Fl_Button {} { label Mid callback {Fl_Tree_Item *item = tree->next_selected_item(); tree->show_item_middle(item);} tooltip {Tests show_item_middle(). Scrolls the selected item to the middle of the display To use: 1) open '500 items' 2) select 'item 0010' 3) Hit Top/Mid/Bot} xywh {385 502 40 16} labelsize 11 } Fl_Button {} { label Bot callback {Fl_Tree_Item *item = tree->next_selected_item(); tree->show_item_bottom(item);} tooltip {Tests show_item_bottom(). Scrolls the selected item to the bottom of the display To use: 1) open '500 items' 2) select 'item 0010' 3) Hit Top/Mid/Bot} xywh {385 518 40 16} labelsize 11 } } Fl_Button openall_button { label {Open All} callback {for ( Fl_Tree_Item *item = tree->first(); item; item = tree->next(item) ) { if ( item->has_children() ) item->open(); } tree->redraw();} tooltip {Opens all nodes that have children} xywh {470 451 95 16} labelsize 9 } Fl_Button loaddb_button { label {Load Database...} callback {const char *filename = fl_file_chooser("Select a Preferences style Database", "Preferences(*.prefs)", 0L); if (filename) { tree->clear(); Fl_Preferences prefs(filename, 0L, 0L, Fl_Preferences::C_LOCALE); tree->load(prefs); tree->redraw(); }} tooltip {Load the contents of an Fl_Preferences database into the tree view} xywh {470 471 95 16} labelsize 9 } Fl_Button insertabove_button { label {Insert Above} callback {Fl_Tree_Item *item=tree->first(); while (item) { if ( item->is_selected() ) { tree->insert_above(item, "AaaAaa"); tree->insert_above(item, "BbbBbb"); tree->insert_above(item, "CccCcc"); } item = item->next(); } tree->redraw();} tooltip {Inserts three items above the selected items} xywh {470 491 95 16} labelsize 9 } Fl_Button rebuildtree_button { label {Rebuild Tree} callback {RebuildTree();} tooltip {Rebuilds the tree with defaults} xywh {470 511 95 16} labelsize 9 } Fl_Button showpathname_button { label {Show Pathname} callback {Fl_Tree_Item *item = tree->first_selected_item(); if ( !item ) { fl_message("No item was selected"); return; } char pathname[256]; switch ( tree->item_pathname(pathname, sizeof(pathname), item) ) { case 0: fl_message("Pathname for '%s' is: \\"%s\\"", (item->label() ? item->label() : "???"), pathname); break; case -1: fl_message("item_pathname() returned -1 (NOT FOUND)"); break; case -2: fl_message("item_pathname() returned -2 (STRING TOO LONG)"); break; }} tooltip {Tests Fl_Tree::item_pathname() Show the pathname for the selected item.} xywh {470 531 95 16} labelsize 9 } Fl_Button closeall_button { label {Close All} callback {for ( Fl_Tree_Item *item = tree->first(); item; item = tree->next(item) ) { if ( !item->is_root() && item->has_children() ) item->close(); } tree->redraw();} tooltip {Closes all nodes that have children (doesn't affect 'root')} xywh {570 451 95 16} labelsize 9 } Fl_Button clearall_button { label {Clear All} callback {tree->clear(); tree->redraw();} tooltip {Tests Fl_Tree::clear(). Clears all items} xywh {570 471 95 16} labelsize 9 } Fl_Button testcallbackflag_button { label {Test Callback Flag} callback {Fl_Tree_Item *root = tree->root(); tty->printf("--- Checking docallback off\\n"); if (!root) return; //// "OFF" TEST // open/close: Make sure these methods don't trigger cb G_cb_counter = 0; tree->close(root, 0); if ( G_cb_counter ) fl_alert("FAILED 'OFF' TEST\\n close(item) triggered cb!"); G_cb_counter = 0; tree->open(root, 0); if ( G_cb_counter ) fl_alert("FAILED 'OFF' TEST\\n open(item) triggered cb!"); G_cb_counter = 0; tree->open_toggle(root, 0); if ( G_cb_counter ) fl_alert("FAILED 'OFF' TEST\\n open_toggle(item) triggered cb!"); G_cb_counter = 0; tree->open("ROOT", 0); if ( G_cb_counter ) fl_alert("FAILED 'OFF' TEST\\n open(path) triggered cb!"); G_cb_counter = 0; tree->close("ROOT", 0); if ( G_cb_counter ) fl_alert("FAILED 'OFF' TEST\\n close(path) triggered cb!"); tree->open(root,0); // leave root open // select/deselect: Make sure these methods don't trigger cb G_cb_counter = 0; tree->select(root, 0); if ( G_cb_counter ) fl_alert("FAILED 'OFF' TEST\\n select(item) triggered cb!"); G_cb_counter = 0; tree->deselect(root, 0); if ( G_cb_counter ) fl_alert("FAILED 'OFF' TEST\\n deselect(item) triggered cb!"); G_cb_counter = 0; tree->select_toggle(root, 0); if ( G_cb_counter ) fl_alert("FAILED 'OFF' TEST\\n select_toggle(item) triggered cb!"); G_cb_counter = 0; tree->deselect("ROOT", 0); if ( G_cb_counter ) fl_alert("FAILED 'OFF' TEST\\n deselect(path) triggered cb!"); G_cb_counter = 0; tree->select("ROOT", 0); if ( G_cb_counter ) fl_alert("FAILED 'OFF' TEST\\n select(path) triggered cb!"); tree->deselect("ROOT"); // leave deselected //// "ON" TEST // open/close: Make sure these methods don't trigger cb G_cb_counter = 0; tree->close(root, 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n close(item) cb wasn't triggered!"); G_cb_counter = 0; tree->open(root, 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n open(item) cb wasn't triggered!"); G_cb_counter = 0; tree->open_toggle(root, 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n open_toggle(item) cb wasn't triggered!"); G_cb_counter = 0; tree->open(root, 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n open(item)[2] cb wasn't triggered!"); G_cb_counter = 0; tree->close(root, 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n close(item)[2] cb wasn't triggered!"); G_cb_counter = 0; tree->open("ROOT", 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n open(path) cb wasn't triggered!"); G_cb_counter = 0; tree->close("ROOT", 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n close(path) cb wasn't triggered!"); tree->open(root,0); // leave root open // select/deselect: Make sure these methods don't trigger cb G_cb_counter = 0; tree->select(root, 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n select(item) cb wasn't triggered!"); G_cb_counter = 0; tree->deselect(root, 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n deselect(item) cb wasn't triggered!"); G_cb_counter = 0; tree->select_toggle(root, 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n select_toggle(item) cb wasn't triggered!"); G_cb_counter = 0; tree->deselect("ROOT", 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n deselect(path) cb wasn't triggered!"); G_cb_counter = 0; tree->select("ROOT", 1); if ( !G_cb_counter ) fl_alert("FAILED 'ON' TEST\\n select(path) cb wasn't triggered!"); tree->deselect("ROOT"); // leave deselected //// "default" TEST (should be same as 'on' // open/close: Make sure these methods don't trigger cb G_cb_counter = 0; tree->close(root); if ( !G_cb_counter ) fl_alert("FAILED 'DEFAULT' TEST: close(item) cb wasn't triggered!"); G_cb_counter = 0; tree->open(root); if ( !G_cb_counter ) fl_alert("FAILED 'DEFAULT' TEST: open(item) cb wasn't triggered!"); G_cb_counter = 0; tree->open_toggle(root); if ( !G_cb_counter ) fl_alert("FAILED 'DEFAULT' TEST: open_toggle(item) cb wasn't triggered!"); G_cb_counter = 0; tree->open("ROOT"); if ( !G_cb_counter ) fl_alert("FAILED 'DEFAULT' TEST: open(path) cb wasn't triggered!"); G_cb_counter = 0; tree->close("ROOT"); if ( !G_cb_counter ) fl_alert("FAILED 'DEFAULT' TEST: close(path) cb wasn't triggered!"); tree->open(root,0); // leave root open // select/deselect: Make sure these methods don't trigger cb G_cb_counter = 0; tree->select(root); if ( !G_cb_counter ) fl_alert("FAILED 'DEFAULT' TEST\\n select(item) cb wasn't triggered!"); G_cb_counter = 0; tree->deselect(root); if ( !G_cb_counter ) fl_alert("FAILED 'DEFAULT' TEST\\n deselect(item) cb wasn't triggered!"); G_cb_counter = 0; tree->select_toggle(root); if ( !G_cb_counter ) fl_alert("FAILED 'DEFAULT' TEST\\n select_toggle(item) cb wasn't triggered!"); G_cb_counter = 0; tree->deselect("ROOT"); if ( !G_cb_counter ) fl_alert("FAILED 'DEFAULT' TEST\\n deselect(path) cb wasn't triggered!"); G_cb_counter = 0; tree->select("ROOT"); if ( !G_cb_counter ) fl_alert("FAILED 'DEFAULT' TEST\\n select(path) cb wasn't triggered!"); tree->deselect("ROOT"); // leave deselected fl_alert("TEST COMPLETED\\n If you didn't see any error dialogs, test PASSED.");} tooltip {Test the 'docallback' argument can disable callbacks.} xywh {570 491 95 16} labelsize 9 } Fl_Button testrootshowself_button { label {Root Show Self} callback {Fl_Tree_Item *root = tree->root(); tty->printf("--- Show Tree\\n"); if (root) root->show_self();} tooltip {Test the root->'show_self() method to show the entire tree on stdout} xywh {570 511 95 16} labelsize 9 } Fl_Button add20k_button { label {Add 20,000} callback {static int item_id = 501; Fl_Tree_Item *item=tree->first(); while (item) { if ( item->is_selected() ) { Fl_Tree_Item *parent = item->parent(); if ( parent == 0 ) parent = tree->root(); char s[80]; for ( int i=0; i<20000; i++ ) { snprintf(s, 80, "Item \#%d", item_id+i); tree->add(parent, s); } item_id += 20000; break; } item = item->next(); } tree->redraw();} tooltip {Adds 20,000 items to the selected item's parent} xywh {570 531 95 16} labelsize 9 } } Fl_Group {} { label {Selected Items} tooltip {These controls only affect the selected items. If no items are selected, all existing items in tree are modified.} xywh {696 23 335 246} box GTK_DOWN_BOX color 47 labelsize 12 } { Fl_Choice selected_labelfont_choice { label {Fl_Tree_Item::labelfont()} callback {// Find first item in tree Fl_Tree_Item *item = tree->first(); if ( !item ) return; // Get first item's font. Fl_Font val = (Fl_Font)selected_labelfont_choice->value(); // Get font value // Do selected items int count = 0; for ( item=tree->first(); item; item = tree->next(item) ) { if ( item->is_selected() ) { item->labelfont(val); count++; } } // No items selected? Do all.. if ( ! count ) { for ( item=tree->first(); item; item = tree->next(item) ) { item->labelfont(val); } } tree->redraw();} tooltip {Tests Fl_Tree_Item::labelfont(); Changes the font for the selected items's labels. If none selected, all are changed.} xywh {863 31 140 21} down_box BORDER_BOX labelsize 11 textsize 11 code0 {o->value((int)tree->item_labelfont()); // get tree's current font, assign to chooser} } { MenuItem {} { label Helvetica xywh {30 30 36 21} labelsize 12 } MenuItem {} { label {Helvetica Bold} xywh {40 40 36 21} labelsize 12 } MenuItem {} { label {Helvetica Italic} xywh {55 55 36 21} labelsize 12 } MenuItem {} { label {Helvetica Bold Italic} xywh {60 60 36 21} labelsize 12 } MenuItem {} { label Courier xywh {70 70 36 21} labelsize 12 } MenuItem {} { label {Courier Bold} xywh {80 80 36 21} labelsize 12 } MenuItem {} { label {Courier Italic} xywh {65 65 36 21} labelsize 12 } MenuItem {} { label {Courier Bold Italic} xywh {70 70 36 21} labelsize 12 } MenuItem {} { label Times xywh {80 80 36 21} labelsize 12 } MenuItem {} { label {Times Bold} xywh {90 90 36 21} labelsize 12 } MenuItem {} { label {Times Italic} xywh {75 75 36 21} labelsize 12 } MenuItem {} { label {Times Bold Italic} xywh {80 80 36 21} labelsize 12 } MenuItem {} { label Symbol xywh {90 90 36 21} labelsize 12 } MenuItem {} { label Screen xywh {100 100 36 21} labelsize 12 } MenuItem {} { label {Screen bold} xywh {85 85 36 21} labelsize 12 } MenuItem {} { label {Zapf Dingbats} xywh {90 90 36 21} labelsize 12 } } Fl_Value_Slider selected_labelsize_slider { label {Fl_Tree_Item::labelsize()} user_data tree callback {int size = (int)selected_labelsize_slider->value(); // DO SELECTED ITEMS int count = 0; Fl_Tree_Item *item; for ( item=tree->first(); item; item = tree->next(item) ) { if ( item->is_selected() ) { item->labelsize(size); count++; } } // NO ITEMS SELECTED? DO ALL if ( ! count ) { for ( item=tree->first(); item; item = tree->next(item) ) { item->labelsize(size); } } tree->redraw();} tooltip {Tests Fl_Tree_Item::labelsize(); Changes the font size of the selected items's labels. If none selected, all are changed.} xywh {863 55 140 16} type Horizontal color 46 selection_color 1 labelsize 11 align 4 textsize 12 code0 {o->value(tree->item_labelsize());} code1 {o->range(5.0, 200.0);} code2 {o->step(1.0);} code3 {o->color(46); o->selection_color(FL_RED);} } Fl_Button all_labelfgcolor_button { label {Fl_Tree_Item::labelfgcolor()} callback {// Get first item's color Fl_Color val = GetSelectedItemFGColor(); // Get color of first selected item if ( EditColor(val) == 0 ) return; // Let user edit color. (return if they hit 'Cancel') all_labelfgcolor_button->color(val); // update modified color to button // Do selected items int count = 0; Fl_Tree_Item *item; for ( item=tree->first(); item; item = tree->next(item) ) { if ( item->is_selected() ) { item->labelfgcolor(val); count++; } } // No items selected? Do all.. if ( ! count ) { for ( item=tree->first(); item; item = tree->next(item) ) { item->labelfgcolor(val); } } tree->redraw();} tooltip {Sets the Fl_Tree_Item::labelfgcolor() for the selected items. If none selected, all are changed.} xywh {863 81 16 16} box DOWN_BOX labelsize 11 align 7 code0 {o->color(GetSelectedItemFGColor());} } Fl_Button all_labelbgcolor_button { label {Fl_Tree_Item::labelbgcolor()} callback {// Get first item's color Fl_Color val = GetSelectedItemBGColor(); // Get color of first selected item if ( EditColor(val) == 0 ) return; // Let user edit color. (return if they hit 'Cancel') all_labelbgcolor_button->color(val); // update modified color to button // Do selected items int count = 0; Fl_Tree_Item *item; for ( item=tree->first(); item; item = tree->next(item) ) { if ( item->is_selected() ) { item->labelbgcolor(val); count++; } } // No items selected? Do all.. if ( ! count ) { for ( item=tree->first(); item; item = tree->next(item) ) { item->labelbgcolor(val); } } tree->redraw();} tooltip {Sets the Fl_Tree_Item::labelbgcolor() for the selected items. If none selected, all are changed.} xywh {863 99 16 16} box DOWN_BOX labelsize 11 align 7 code0 {o->color(GetSelectedItemBGColor());} } Fl_Light_Button deactivate_items_toggle { label { Deactivate Items} callback {int onoff = deactivate_items_toggle->value() ? 0 : 1; Fl_Tree_Item *item; int count = 0; for ( item=tree->first(); item; item = tree->next(item) ) { if ( item->is_selected() ) { item->activate(onoff); ++count; } } if ( count == 0 ) { for ( item=tree->first(); item; item = tree->next(item) ) { item->activate(onoff); } } tree->redraw();} tooltip {Toggle the deactivation state of the selected items. If none are selected, all are set.} xywh {758 134 100 16} selection_color 1 labelsize 9 } Fl_Light_Button deactivate_tree_toggle { label { Deactivate Tree} callback {if ( deactivate_tree_toggle->value() ) tree->deactivate(); else tree->activate();} tooltip {Deactivates the entire tree widget} xywh {758 154 100 16} selection_color 1 labelsize 9 } Fl_Light_Button bold_toggle { label { Bold Font} callback {int face = bold_toggle->value() ? FL_HELVETICA_BOLD : FL_HELVETICA; // DO SELECTED ITEMS int count = 0; Fl_Tree_Item *item; for ( item=tree->first(); item; item = tree->next(item) ) { if ( item->is_selected() ) { item->labelfont(face); count++; } } // NO ITEMS SELECTED? DO ALL if ( ! count ) { for ( item=tree->first(); item; item = tree->next(item) ) { item->labelfont(face); } } tree->redraw();} tooltip {Toggles bold font for selected items If nothing selected, all are changed} xywh {758 174 100 16} selection_color 1 labelsize 9 } Fl_Button showselected_button { label {Show Selected} callback {tty->printf("--- SELECTED ITEMS\\n"); for ( Fl_Tree_Item *item = tree->first_selected_item(); item; item = tree->next_selected_item(item) ) { tty->printf("\\t%s\\n", item->label() ? item->label() : "???"); }} tooltip {Clears the selected items} xywh {864 134 95 16} labelsize 9 } Fl_Button clearselected_button { label {Remove Selected} callback {Fl_Tree_Item *item=tree->first(); while (item) { if ( item->is_selected() ) { if ( tree->remove(item) == -1 ) break; item = tree->first(); } else { item = item->next(); } } tree->redraw();} tooltip {Removes the selected items} xywh {864 154 95 16} labelsize 9 } Fl_Button swapselected_button { label {Swap Selected} callback {Fl_Tree_Item *item=tree->first(); Fl_Tree_Item *a = 0, *b = 0; while (item) { if ( item->is_selected() ) { if ( !a ) a = item; else if ( !b ) b = item; else { fl_alert("Too many items selected. (must select only two)"); return; } } item = item->next(); } if ( !a || !b ) { fl_alert("Too few items selected. (you must select two)"); return; } Fl_Tree_Item *pa = a->parent(); Fl_Tree_Item *pb = b->parent(); if ( pa != pb ) { fl_alert("The two selected items must be siblings"); return; } pa->swap_children(a,b); tree->redraw();} tooltip {Tests the Fl_Tree_Item::swap_children() method Swaps two selected items (items must be siblings)} xywh {864 174 95 16} labelsize 9 } Fl_Button selectall_button { label {Select All} callback {tree->select_all(0); tree->redraw();} tooltip {Selects all items in the tree} xywh {714 199 95 16} labelsize 9 } Fl_Button deselectall_button { label {Deselect All} callback {tree->deselect_all(0); tree->redraw();} tooltip {Deselects all items in the tree} xywh {714 219 95 16} labelsize 9 } Fl_Button nextselected_button { label {next_selected()} callback {tty->printf("--- TEST next_selected():\\n"); tty->printf(" // Walk down the tree (forwards)\\n"); for ( Fl_Tree_Item *i=tree->first_selected_item(); i; i=tree->next_selected_item(i, FL_Down) ) { tty->printf(" Selected item: %s\\n", i->label()?i->label():""); } tty->printf(" // Walk up the tree (backwards)\\n"); for ( Fl_Tree_Item *i=tree->last_selected_item(); i; i=tree->next_selected_item(i, FL_Up) ) { tty->printf(" Selected item: %s\\n", i->label()?i->label():""); }} tooltip {Tests the Fl_Tree::next_selected() function} xywh {713 239 95 16} labelsize 9 } Fl_Light_Button bbbselect_toggle { label { Select Bbb} callback {// Toggle select of just the Bbb item (not children) Fl_Tree_Item *bbb = tree->find_item("/Bbb"); if ( !bbb) { fl_alert("FAIL: Couldn't find item '/Bbb'???"); return; } int onoff = bbbselect_toggle->value(); if ( onoff ) tree->select(bbb); // select /Bbb else tree->deselect(bbb); // deselect /Bbb} tooltip {Toggle selection of just the /Bbb item (Not children)} xywh {814 199 95 16} selection_color 1 labelsize 9 } Fl_Light_Button bbbselect2_toggle { label { Select Bbb+} callback {// Toggle select of just the Bbb item and its immediate children Fl_Tree_Item *bbb = tree->find_item("/Bbb"); if ( !bbb) { fl_alert("FAIL: Couldn't find item '/Bbb'???"); return; } int onoff = bbbselect2_toggle->value(); if ( onoff ) tree->select_all(bbb); // select /Bbb and its children else tree->deselect_all(bbb); // deselect /Bbb and its children} tooltip {Toggle selection of the /Bbb item and its children} xywh {814 219 95 16} selection_color 1 labelsize 9 } Fl_Light_Button bbbchild02select_toggle { label { Toggle child-02} callback {// Toggle select of just the /Bbb/child-02 item const char *pathname = "/Bbb/child-02"; int onoff = bbbchild02select_toggle->value(); int err = 0; if ( onoff ) err = tree->select(pathname); else err = tree->deselect(pathname); if ( err == -1 ) { fl_alert("FAIL: Couldn't find item '%s'",pathname); return; }} tooltip {Toggle the single item "/Bbb/child-02" using the item's "pathname".} xywh {814 239 95 16} selection_color 1 labelsize 9 } Fl_Light_Button rootselect_toggle { label {Select ROOT} callback {// Toggle select of ROOT item and its children Fl_Tree_Item *item = tree->find_item("/ROOT"); if ( !item) { fl_alert("FAIL: Couldn't find item '/ROOT'???"); return; } int onoff = rootselect_toggle->value(); if ( onoff ) tree->select(item); // select /ROOT and its children else tree->deselect(item); // deselect /ROOT and its children} tooltip {Toggle selection of the ROOT item} xywh {914 199 100 16} selection_color 1 labelsize 9 } Fl_Light_Button rootselect2_toggle { label {Select ROOT+} callback {// Toggle select of ROOT item and its children Fl_Tree_Item *item = tree->find_item("/ROOT"); if ( !item) { fl_alert("FAIL: Couldn't find item '/ROOT'???"); return; } int onoff = rootselect2_toggle->value(); if ( onoff ) tree->select_all(item); // select /ROOT and its children else tree->deselect_all(item); // deselect /ROOT and its children} tooltip {Toggle selection of the ROOT item and all children} xywh {914 219 100 16} selection_color 1 labelsize 9 } } Fl_Group {} { label {Tree Fonts + Colors} tooltip {These controls only affect the selected items. If no items are selected, all existing items in tree are modified.} xywh {695 298 335 186} box GTK_DOWN_BOX color 47 labelsize 12 } { Fl_Choice labelfont_choice { label {labelfont()} callback {Fl_Font val = (Fl_Font)labelfont_choice->value(); tree->labelfont(val); window->redraw();} tooltip {Sets the default font used for new items created. Does NOT affect existing items.} xywh {848 314 140 21} down_box BORDER_BOX labelsize 12 textsize 12 code0 {o->value((int)tree->labelfont()); // get tree's current font, assign to chooser} } { MenuItem {} { label Helvetica xywh {35 35 36 21} labelsize 12 } MenuItem {} { label {Helvetica Bold} xywh {45 45 36 21} labelsize 12 } MenuItem {} { label {Helvetica Italic} xywh {60 60 36 21} labelsize 12 } MenuItem {} { label {Helvetica Bold Italic} xywh {65 65 36 21} labelsize 12 } MenuItem {} { label Courier xywh {75 75 36 21} labelsize 12 } MenuItem {} { label {Courier Bold} xywh {85 85 36 21} labelsize 12 } MenuItem {} { label {Courier Italic} xywh {70 70 36 21} labelsize 12 } MenuItem {} { label {Courier Bold Italic} xywh {75 75 36 21} labelsize 12 } MenuItem {} { label Times xywh {85 85 36 21} labelsize 12 } MenuItem {} { label {Times Bold} xywh {95 95 36 21} labelsize 12 } MenuItem {} { label {Times Italic} xywh {80 80 36 21} labelsize 12 } MenuItem {} { label {Times Bold Italic} xywh {85 85 36 21} labelsize 12 } MenuItem {} { label Symbol xywh {95 95 36 21} labelsize 12 } MenuItem {} { label Screen xywh {105 105 36 21} labelsize 12 } MenuItem {} { label {Screen bold} xywh {90 90 36 21} labelsize 12 } MenuItem {} { label {Zapf Dingbats} xywh {95 95 36 21} labelsize 12 } } Fl_Value_Slider labelsize_slider { label {labelsize()} user_data tree callback {tree->labelsize((int)labelsize_slider->value()); window->redraw();} tooltip {Sets the font size for the tree's label(). This is also the font size that will be used to draw the items IF their size hasn't been set with Fl_Tree_Item::labelsize() or Fl_Tree::item_labelsize()} xywh {848 338 140 16} type Horizontal color 46 selection_color 1 labelsize 12 align 4 textsize 12 code0 {o->value((int)tree->labelsize());} code1 {o->range(1.0, 50.0);} code2 {o->step(1.0);} code3 {o->color(46); o->selection_color(FL_RED);} } Fl_Choice item_labelfont_choice { label {Item_labelfont()} callback {Fl_Font val = (Fl_Font)item_labelfont_choice->value(); tree->item_labelfont(val); tree->redraw();} tooltip {Sets the default font used for new items created. .Also affects any items whose font has NOT specifically been set with item->labelfont().} xywh {848 358 140 21} down_box BORDER_BOX labelsize 12 textsize 12 code0 {o->value((int)tree->item_labelfont());} } { MenuItem {} { label Helvetica xywh {25 25 36 21} labelsize 12 } MenuItem {} { label {Helvetica Bold} xywh {35 35 36 21} labelsize 12 } MenuItem {} { label {Helvetica Italic} xywh {50 50 36 21} labelsize 12 } MenuItem {} { label {Helvetica Bold Italic} xywh {55 55 36 21} labelsize 12 } MenuItem {} { label Courier xywh {65 65 36 21} labelsize 12 } MenuItem {} { label {Courier Bold} xywh {75 75 36 21} labelsize 12 } MenuItem {} { label {Courier Italic} xywh {60 60 36 21} labelsize 12 } MenuItem {} { label {Courier Bold Italic} xywh {65 65 36 21} labelsize 12 } MenuItem {} { label Times xywh {75 75 36 21} labelsize 12 } MenuItem {} { label {Times Bold} xywh {85 85 36 21} labelsize 12 } MenuItem {} { label {Times Italic} xywh {70 70 36 21} labelsize 12 } MenuItem {} { label {Times Bold Italic} xywh {75 75 36 21} labelsize 12 } MenuItem {} { label Symbol xywh {85 85 36 21} labelsize 12 } MenuItem {} { label Screen xywh {95 95 36 21} labelsize 12 } MenuItem {} { label {Screen bold} xywh {80 80 36 21} labelsize 12 } MenuItem {} { label {Zapf Dingbats} xywh {85 85 36 21} labelsize 12 } } Fl_Value_Slider item_labelsize_slider { label {item_labelsize()} user_data tree callback {tree->item_labelsize((int)item_labelsize_slider->value()); tree->redraw();} tooltip {Sets the default font size used for new items created. .Also affects any items whose font size has NOT specifically been set with item->labelsize().} xywh {848 383 140 16} type Horizontal color 46 selection_color 1 labelsize 12 align 4 textsize 12 code0 {o->value((int)tree->item_labelsize());} code1 {o->range(1.0, 50.0);} code2 {o->step(1.0);} code3 {o->color(46); o->selection_color(FL_RED);} } Fl_Button labelcolor_button { label {labelcolor()} callback {Fl_Color val = tree->labelcolor(); if ( EditColor(val) == 0 ) return; // Let user edit color. (return if they hit 'Cancel') labelcolor_button->color(val); // update modified color to button tree->labelcolor(val); window->redraw(); // affects window (tree's label is outside tree's area)} tooltip {Changes Fl_Tree::labelcolor(). This affects the text color of the widget's label.} xywh {813 414 16 16} box DOWN_BOX labelsize 11 align 7 code0 {o->color(tree->labelcolor());} } Fl_Button color_button { label {color()} callback {Fl_Color val = tree->color(); if ( EditColor(val) == 0 ) return; // Let user edit color. (return if they hit 'Cancel') color_button->color(val); // update modified color to button tree->color(val); UpdateColorChips(); tree->redraw();} tooltip {Changes Fl_Tree::color(). This affects the background color of the widget. It also affects the bg color of newly created items *if* Fl_Tree::item_labelbgcolor() hasn't been changed.} xywh {813 433 16 16} box DOWN_BOX labelsize 11 align 7 code0 {o->color(tree->color());} } Fl_Button selection_color_button { label {selection_color()} callback {Fl_Color val = tree->selection_color(); if ( EditColor(val) == 0 ) return; // Let user edit color. (return if they hit 'Cancel') selection_color_button->color(val); // update modified color to button tree->selection_color(val); tree->redraw();} tooltip {Sets the Fl_Tree::selection_color(). This affects the item's colors when they're selected.} xywh {813 452 16 16} box DOWN_BOX labelsize 11 align 7 code0 {o->color(tree->selection_color());} } Fl_Button item_labelfgcolor_button { label {item_labelfgcolor()} callback {Fl_Color val = tree->item_labelfgcolor(); if ( EditColor(val) == 0 ) return; // Let user edit color. (return if they hit 'Cancel') tree->item_labelfgcolor(val); // apply modified color to tree item_labelfgcolor_button->color(val); // update modified color to button tree->redraw();} tooltip {Sets the default label fg color for newly created items.} xywh {973 414 16 16} box DOWN_BOX labelsize 12 align 7 code0 {o->color(tree->item_labelfgcolor());} } Fl_Button item_labelbgcolor_button { label {item_labelbgcolor()} callback {Fl_Color val = tree->item_labelbgcolor(); if ( EditColor(val) == 0 ) return; // Let user edit color. (return if they hit 'Cancel') tree->item_labelbgcolor(val); // apply modified color to tree item_labelbgcolor_button->color(val); // update modified color to button tree->redraw();} tooltip {Sets the default label bg color for newly created items. When set, this overrides the default behavior of using Fl_Tree::color().} xywh {973 433 16 16} box DOWN_BOX labelsize 12 align 7 code0 {item_labelbgcolor_button->color(tree->item_labelbgcolor());} } Fl_Button x_item_labelbgcolor_button { label X callback {tree->item_labelbgcolor(0xffffffff); UpdateColorChips(); tree->redraw();} tooltip {Make the bgcolor 'transparent' (0xffffffff)} xywh {993 433 16 16} labelsize 10 align 16 } } Fl_Value_Slider tree_scrollbar_size_slider { label {Fl_Tree::scrollbar_size()} callback {tree->scrollbar_size((int)tree_scrollbar_size_slider->value()); tree->redraw();} tooltip {Tests Fl_Tree::scrollbar_size() effects on tree clipping. The value is normally 0, which causes Fl_Tree to use the global Fl::scrollbar_size() instead.} xywh {835 499 180 16} type Horizontal color 46 selection_color 1 labelsize 11 align 4 textsize 9 code0 {o->value(tree->scrollbar_size());} code1 {o->range(0.0, 30.0);} code2 {o->step(1.0);} code3 {o->color(46); o->selection_color(FL_RED);} } Fl_Value_Slider scrollbar_size_slider { label {Fl::scrollbar_size()} callback {Fl::scrollbar_size((int)scrollbar_size_slider->value()); tree->redraw();} tooltip {Tests Fl::scrollbar_size() effects on tree clipping} xywh {835 519 180 16} type Horizontal color 46 selection_color 1 labelsize 11 align 4 textsize 9 code0 {o->value(Fl::scrollbar_size());} code1 {o->range(5.0, 30.0);} code2 {o->step(1.0);} code3 {o->color(46); o->selection_color(FL_RED);} } Fl_Button testsuggs_button { label {Test Suggestions} callback {const char *helpmsg = "CHILD WIDGET SIZING TESTS\\n" "=========================\\n" " 1) Start program\\n" " 2) Click the 'ccc button' and D1/D2 buttons.\\n" " Their sizes should not change.\\n" " 3) Click the 'Item h() from widget' checkbox.\\n" " 4) Click the 'ccc button' and D1/D2 buttons.\\n" " Their sizes should change, getting larger vertically.\\n" " This validates that widget's size can affect the tree.\\n" " 5) Disable the checkbox, widgets should resize back to the\\n" " size of the other items.\\n" " 6) Hit ^A to select all items\\n" " 7) Under 'Selected Items', drag the 'Label Size' slider around.\\n" " All the item's height should change, as well as child widgets.\\n" " 8) Put Label Size' slider back to normal\\n" "\\n" "CHILD WIDGET + LABEL ITEM DRAWING TESTS\\n" "=======================================\\n" " 1) Start program\\n" " 2) Click 'Show label + widget'.\\n" " The widgets should all show item labels to their left.\\n" " 3) Disable same, item labels should disappear,\\n" " showing the widgets in their place.\\n" "\\n" "COLORS\\n" "======\\n" " 1) Start program\\n" " 2) Change 'Tree Fonts+Colors' -> color()\\n" " 3) Entire tree's background color will change, including items.\\n" " 4) Change the 'Tree Fonts + Colors -> item_labelbgcolor()'\\n" " 6) Click the '111' item to select it.\\n" " 7) Click 'Test Operations -> Insert Above'\\n" " New items should appear above the selected item using the new color.\\n" " This color will be different from the background color.\\n" " 8) Change the 'Tree Fonts+Colors' -> color()\\n" " The entire tree's bg should change, except the new items.\\n" " 9) Click the Tree Fonts+Colors -> item_labelbgcolor() 'X' button.\\n" " This resets item_labelbgcolor() to the default 'transparent' color (0xffffffff)\\n" " 10) Again, click the 'Insert Above' button.\\n" " New items will be created in the background color, and changing the color()\\n" " should affect the new items too.\\n" "\\n" "SCROLLING\\n" "=========\\n" " 1) Open '500 items' and 'Long Line' so that both scrollbars appear:\\n" " * The 'focus box' for the selected item should not be clipped\\n" " horizontally by the vertical scrollbar.\\n" " * Resizing the window horizontally should resize the focus box\\n" " * Scrolling vertically/horizontally should show reveal all\\n" " edges of the tree. One *exception* is the widget label\\n" " to the right of the 'ccc button'; labels aren't part\\n" " of the widget, and therefore don't affect scroll tabs\\n" " 2) Scroll vertical scroller to the middle of the tree\\n" " 3) Left click and drag up/down to extend the selection:\\n" " * Selection should autoscroll if you drag off the top/bottom\\n" " * Selection should work *even* if you drag horizontally\\n" " off the window edge; moving up/down outside the window\\n" " should continue to autoscroll\\n" " 4) Click either of the the scrollbar tabs and drag:\\n" " * Even if you drag off the scrollbar, the scrollbar\\n" " tab should continue to move\\n" " * Should continue to work if you drag off the window edge\\n" " horizontally drag off the window.\\n" " 5) Click 'Bbb' and hit 'Add 20,000', then position the\\n" " 'ccc button' so it's partially obscured by a scrollbar tab:\\n" " * Clicking the obscured button should work\\n" " * Clicking on the tab over the button should not 'click through'\\n" " to the button.\\n" ""; static Fl_Double_Window *helpwin = 0; static Fl_Text_Display *helpdisp = 0; static Fl_Text_Buffer *helpbuff = 0; if ( !helpwin ) { Fl_Group::current(0); // ensure we don't become child of other win helpwin = new Fl_Double_Window(600,600,"Test Suggestions"); helpdisp = new Fl_Text_Display(0,0,helpwin->w(),helpwin->h()); helpbuff = new Fl_Text_Buffer(); helpdisp->buffer(helpbuff); helpdisp->textfont(FL_COURIER); helpdisp->textsize(12); helpbuff->text(helpmsg); helpwin->end(); } helpwin->resizable(helpdisp); helpwin->show();} tooltip {Suggestions on how to do tests} xywh {935 545 95 16} labelsize 9 } } Fl_Box resizer_box { xywh {0 263 15 14} } Fl_Terminal tty {selected xywh {16 571 1014 149} } } code {// Initialize Tree tree->root_label("ROOT"); tree->item_reselect_mode(FL_TREE_SELECTABLE_ALWAYS); RebuildTree(); /*tree->show_self();*/} {} code {// FLTK stuff //Fl::scheme("gtk+"); Fl_Tooltip::size(10); // small font for tooltips window->resizable(tree); window->size_range(window->w(), window->h(), 0, 0); if ( tree->when() == FL_WHEN_CHANGED ) whenmode_chooser->value(0); else if ( tree->when() == FL_WHEN_RELEASE ) whenmode_chooser->value(1); else if ( tree->when() == FL_WHEN_NEVER ) whenmode_chooser->value(2);} {} } fltk-1.4.3/test/input.cxx0000644000175000017500000001311115004135251015444 0ustar albrechtalbrecht// // Input field test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include #include #include #define TERMINAL_HEIGHT 120 // Globals Fl_Terminal *G_tty = 0; void cb(Fl_Widget *ob) { G_tty->printf("Callback for %s '%s'\n",ob->label(),((Fl_Input*)ob)->value()); } int when = 0; Fl_Input *input[5]; void toggle_cb(Fl_Widget *o, long v) { if (((Fl_Toggle_Button*)o)->value()) when |= v; else when &= ~v; for (int i=0; i<5; i++) input[i]->when(when); } void test(Fl_Input *i) { if (i->changed()) { i->clear_changed(); G_tty->printf("%s '%s'\n",i->label(),i->value()); char utf8buf[10]; int last = fl_utf8encode(i->index(i->insert_position()), utf8buf); utf8buf[last] = 0; G_tty->printf("Symbol at cursor position: %s\n", utf8buf); } } void button_cb(Fl_Widget *,void *) { for (int i=0; i<5; i++) test(input[i]); } void color_cb(Fl_Widget* button, void* v) { Fl_Color c; switch ((fl_intptr_t)v) { case 0: c = FL_BACKGROUND2_COLOR; break; case 1: c = FL_SELECTION_COLOR; break; default: c = FL_FOREGROUND_COLOR; break; } uchar r,g,b; Fl::get_color(c, r,g,b); if (fl_color_chooser(0,r,g,b)) { Fl::set_color(c,r,g,b); Fl::redraw(); button->labelcolor(fl_contrast(FL_BLACK,c)); button->redraw(); } } void tabnav_cb(Fl_Widget *w, void *v) { Fl_Light_Button *b = (Fl_Light_Button*)w; Fl_Multiline_Input *fmi = (Fl_Multiline_Input*)v; fmi->tab_nav(b->value() ? 1 : 0); } void arrownav_cb(Fl_Widget *w, void *v) { Fl_Light_Button *b = (Fl_Light_Button*)w; Fl::option(Fl::OPTION_ARROW_FOCUS, b->value() ? true : false); } int main(int argc, char **argv) { // the following two lines set the correct color scheme, so that // calling fl_contrast below will return good results Fl::args(argc, argv); Fl::get_system_colors(); Fl_Window *window = new Fl_Window(400,420+TERMINAL_HEIGHT); G_tty = new Fl_Terminal(0,420,window->w(),TERMINAL_HEIGHT); int y = 10; input[0] = new Fl_Input(70,y,300,30,"Normal:"); y += 35; input[0]->tooltip("Normal input field"); // input[0]->cursor_color(FL_SELECTION_COLOR); // input[0]->maximum_size(20); // input[0]->static_value("this is a testgarbage"); input[1] = new Fl_Float_Input(70,y,300,30,"Float:"); y += 35; input[1]->tooltip("Input field for floating-point number (F1)"); input[1]->shortcut(FL_F+1); input[2] = new Fl_Int_Input(70,y,300,30,"Int:"); y += 35; input[2]->tooltip("Input field for integer number (F2)"); input[2]->shortcut(FL_F+2); input[3] = new Fl_Secret_Input(70,y,300,30,"&Secret:"); y += 35; input[3]->tooltip("Input field for password (Alt-S)"); input[4] = new Fl_Multiline_Input(70,y,300,100,"&Multiline:"); y += 105; input[4]->tooltip("Input field for short text with newlines (Alt-M)"); input[4]->wrap(1); for (int i = 0; i < 4; i++) { input[i]->when(0); input[i]->callback(cb); } int y1 = y; Fl_Button *b; b = new Fl_Toggle_Button(10,y,200,25,"FL_WHEN_CHANGED"); b->callback(toggle_cb, FL_WHEN_CHANGED); y += 25; b->tooltip("Do callback each time the text changes"); b = new Fl_Toggle_Button(10,y,200,25,"FL_WHEN_RELEASE"); b->callback(toggle_cb, FL_WHEN_RELEASE); y += 25; b->tooltip("Do callback when widget loses focus"); b = new Fl_Toggle_Button(10,y,200,25,"FL_WHEN_ENTER_KEY"); b->callback(toggle_cb, FL_WHEN_ENTER_KEY); y += 25; b->tooltip("Do callback when user hits Enter key"); b = new Fl_Toggle_Button(10,y,200,25,"FL_WHEN_NOT_CHANGED"); b->callback(toggle_cb, FL_WHEN_NOT_CHANGED); y += 25; b->tooltip("Do callback even if the text is not changed"); y += 5; b = new Fl_Button(10,y,200,25,"&print changed()"); y += 25; b->callback(button_cb); b->tooltip("Print widgets that have changed() flag set"); b = new Fl_Light_Button(10,y,100,25," Tab Nav"); b->tooltip("Control tab navigation for the multiline input field"); b->callback(tabnav_cb, (void*)input[4]); b->value(input[4]->tab_nav() ? 1 : 0); b = new Fl_Light_Button(110,y,100,25," Arrow Nav"); y += 25; b->tooltip("Control horizontal arrow key focus navigation behavior.\n" "e.g. Fl::OPTION_ARROW_FOCUS"); b->callback(arrownav_cb); b->value(input[4]->tab_nav() ? 1 : 0); b->value(Fl::option(Fl::OPTION_ARROW_FOCUS) ? 1 : 0); b = new Fl_Button(220,y1,120,25,"color"); y1 += 25; b->color(input[0]->color()); b->callback(color_cb, (void*)0); b->tooltip("Color behind the text"); b = new Fl_Button(220,y1,120,25,"selection_color"); y1 += 25; b->color(input[0]->selection_color()); b->callback(color_cb, (void*)1); b->labelcolor(fl_contrast(FL_BLACK,b->color())); b->tooltip("Color behind selected text"); b = new Fl_Button(220,y1,120,25,"textcolor"); y1 += 25; b->color(input[0]->textcolor()); b->callback(color_cb, (void*)2); b->labelcolor(fl_contrast(FL_BLACK,b->color())); b->tooltip("Color of the text"); window->end(); window->resizable(G_tty); window->show(argc,argv); return Fl::run(); } fltk-1.4.3/test/editor.cxx0000644000175000017500000010063615004135251015604 0ustar albrechtalbrecht// // A simple text editor program for the Fast Light Tool Kit (FLTK). // // This program is described in chapter "Designing a Simple Text Editor" // of the FLTK Programmer's Guide. // // Copyright 1998-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Enable tutorial code for each chapter by adjusting this macro to match // the chapter number. #define TUTORIAL_CHAPTER 10 // ---- Tutorial Chapter 1 ----------------------------------------------------- #if TUTORIAL_CHAPTER >= 1 #include #include Fl_Double_Window *app_window = NULL; void tut1_build_app_window() { app_window = new Fl_Double_Window(640, 480, "FLTK Editor"); } #endif #if TUTORIAL_CHAPTER == 1 int main (int argc, char **argv) { tut1_build_app_window(); app_window->show(argc, argv); return Fl::run(); } #endif // ---- Tutorial Chapter 2 ----------------------------------------------------- #if TUTORIAL_CHAPTER >= 2 #include #include #include #include Fl_Menu_Bar *app_menu_bar = NULL; bool text_changed = false; char app_filename[FL_PATH_MAX] = ""; void update_title() { const char *fname = NULL; if (app_filename[0]) fname = fl_filename_name(app_filename); if (fname) { char buf[FL_PATH_MAX + 3]; buf[FL_PATH_MAX + 2] = '\0'; // ensure that the buffer is always terminated if (text_changed) { snprintf(buf, FL_PATH_MAX+2, "%s *", fname); } else { snprintf(buf, FL_PATH_MAX+2, "%s", fname); } app_window->copy_label(buf); } else { app_window->label("FLTK Editor"); } } void set_changed(bool v) { if (v != text_changed) { text_changed = v; update_title(); } } void set_filename(const char *new_filename) { if (new_filename) { fl_strlcpy(app_filename, new_filename, FL_PATH_MAX); } else { app_filename[0] = 0; } update_title(); } #if TUTORIAL_CHAPTER < 4 void menu_quit_callback(Fl_Widget *, void *) { if (text_changed) { int c = fl_choice("Changes in your text have not been saved.\n" "Do you want to quit the editor anyway?", "Quit", "Cancel", NULL); if (c == 1) return; } Fl::hide_all_windows(); } #else void menu_quit_callback(Fl_Widget *, void *); #endif void tut2_build_app_menu_bar() { app_window->begin(); app_menu_bar = new Fl_Menu_Bar(0, 0, app_window->w(), 25); app_menu_bar->add("File/Quit Editor", FL_COMMAND|'q', menu_quit_callback); app_window->callback(menu_quit_callback); app_window->end(); } #endif #if TUTORIAL_CHAPTER == 2 int main (int argc, char **argv) { tut1_build_app_window(); tut2_build_app_menu_bar(); app_window->show(argc, argv); return Fl::run(); } #endif // ---- Tutorial Chapter 3 ----------------------------------------------------- #if TUTORIAL_CHAPTER >= 3 #include #include Fl_Text_Editor *app_editor = NULL; Fl_Text_Editor *app_split_editor = NULL; // for later Fl_Text_Buffer *app_text_buffer = NULL; void text_changed_callback(int, int n_inserted, int n_deleted, int, const char*, void*) { if (n_inserted || n_deleted) set_changed(true); } void menu_new_callback(Fl_Widget*, void*) { if (text_changed) { int c = fl_choice("Changes in your text have not been saved.\n" "Do you want to start a new text anyway?", "New", "Cancel", NULL); if (c == 1) return; } app_text_buffer->text(""); set_filename(NULL); set_changed(false); } void tut3_build_main_editor() { app_window->begin(); app_text_buffer = new Fl_Text_Buffer(); app_text_buffer->add_modify_callback(text_changed_callback, NULL); app_editor = new Fl_Text_Editor(0, app_menu_bar->h(), app_window->w(), app_window->h() - app_menu_bar->h()); app_editor->buffer(app_text_buffer); app_editor->textfont(FL_COURIER); app_window->resizable(app_editor); app_window->end(); // find the Quit menu and insert the New menu there int ix = app_menu_bar->find_index(menu_quit_callback); app_menu_bar->insert(ix, "New", FL_COMMAND+'n', menu_new_callback); } #endif #if TUTORIAL_CHAPTER == 3 int main (int argc, char **argv) { tut1_build_app_window(); tut2_build_app_menu_bar(); tut3_build_main_editor(); app_window->show(argc, argv); return Fl::run(); } #endif // ---- Tutorial Chapter 4 ----------------------------------------------------- #if TUTORIAL_CHAPTER >= 4 #include #include #include void menu_save_as_callback(Fl_Widget*, void*) { Fl_Native_File_Chooser file_chooser; file_chooser.title("Save File As..."); file_chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); if (app_filename[0]) { char temp_filename[FL_PATH_MAX]; fl_strlcpy(temp_filename, app_filename, FL_PATH_MAX); const char *name = fl_filename_name(temp_filename); if (name) { file_chooser.preset_file(name); temp_filename[name - temp_filename] = 0; file_chooser.directory(temp_filename); } } if (file_chooser.show() == 0) { if (app_text_buffer->savefile(file_chooser.filename()) == 0) { set_filename(file_chooser.filename()); set_changed(false); } else { fl_alert("Failed to save file\n%s\n%s", file_chooser.filename(), strerror(errno)); } } } void menu_save_callback(Fl_Widget*, void*) { if (!app_filename[0]) { menu_save_as_callback(NULL, NULL); } else { if (app_text_buffer->savefile(app_filename) == 0) { set_changed(false); } else { fl_alert("Failed to save file\n%s\n%s", app_filename, strerror(errno)); } } } void menu_quit_callback(Fl_Widget *, void *) { if (text_changed) { int r = fl_choice("The current file has not been saved.\n" "Would you like to save it now?", "Cancel", "Save", "Don't Save"); if (r == 0) // cancel return; if (r == 1) { // save menu_save_callback(NULL, NULL); return; } } Fl::hide_all_windows(); } void load(const char *filename) { if (app_text_buffer->loadfile(filename) == 0) { set_filename(filename); set_changed(false); } else { fl_alert("Failed to load file\n%s\n%s", filename, strerror(errno)); } } void menu_open_callback(Fl_Widget*, void*) { if (text_changed) { int r = fl_choice("The current file has not been saved.\n" "Would you like to save it now?", "Cancel", "Save", "Don't Save"); if (r == 0) // cancel return; if (r == 1) // save menu_save_callback(NULL, NULL); } Fl_Native_File_Chooser file_chooser; file_chooser.title("Open File..."); file_chooser.type(Fl_Native_File_Chooser::BROWSE_FILE); if (app_filename[0]) { char temp_filename[FL_PATH_MAX]; fl_strlcpy(temp_filename, app_filename, FL_PATH_MAX); const char *name = fl_filename_name(temp_filename); if (name) { file_chooser.preset_file(name); temp_filename[name - temp_filename] = 0; file_chooser.directory(temp_filename); } } if (file_chooser.show() == 0) load(file_chooser.filename()); } void tut4_add_file_support() { int ix = app_menu_bar->find_index(menu_quit_callback); app_menu_bar->insert(ix, "Open", FL_COMMAND+'o', menu_open_callback, NULL, FL_MENU_DIVIDER); app_menu_bar->insert(ix+1, "Save", FL_COMMAND+'s', menu_save_callback); app_menu_bar->insert(ix+2, "Save as...", FL_COMMAND+'S', menu_save_as_callback, NULL, FL_MENU_DIVIDER); } int args_handler(int argc, char **argv, int &i) { if (argv && argv[i] && argv[i][0]!='-') { load(argv[i]); i++; return 1; } return 0; } int tut4_handle_commandline_and_run(int &argc, char **argv) { int i = 0; Fl::args_to_utf8(argc, argv); Fl::args(argc, argv, i, args_handler); fl_open_callback(load); app_window->show(argc, argv); return Fl::run(); } #endif #if TUTORIAL_CHAPTER == 4 int main (int argc, char **argv) { tut1_build_app_window(); tut2_build_app_menu_bar(); tut3_build_main_editor(); tut4_add_file_support(); return tut4_handle_commandline_and_run(argc, argv); } #endif // ---- Tutorial Chapter 5 ----------------------------------------------------- #if TUTORIAL_CHAPTER >= 5 void menu_undo_callback(Fl_Widget*, void* v) { Fl_Widget *e = Fl::focus(); if (e && (e == app_editor || e == app_split_editor)) Fl_Text_Editor::kf_undo(0, (Fl_Text_Editor*)e); } void menu_redo_callback(Fl_Widget*, void* v) { Fl_Widget *e = Fl::focus(); if (e && (e == app_editor || e == app_split_editor)) Fl_Text_Editor::kf_redo(0, (Fl_Text_Editor*)e); } void menu_cut_callback(Fl_Widget*, void* v) { Fl_Widget *e = Fl::focus(); if (e && (e == app_editor || e == app_split_editor)) Fl_Text_Editor::kf_cut(0, (Fl_Text_Editor*)e); } void menu_copy_callback(Fl_Widget*, void* v) { Fl_Widget *e = Fl::focus(); if (e && (e == app_editor || e == app_split_editor)) Fl_Text_Editor::kf_copy(0, (Fl_Text_Editor*)e); } void menu_paste_callback(Fl_Widget*, void* v) { Fl_Widget *e = Fl::focus(); if (e && (e == app_editor || e == app_split_editor)) Fl_Text_Editor::kf_paste(0, (Fl_Text_Editor*)e); } void menu_delete_callback(Fl_Widget*, void*) { Fl_Widget *e = Fl::focus(); if (e && (e == app_editor || e == app_split_editor)) Fl_Text_Editor::kf_delete(0, (Fl_Text_Editor*)e); } void tut5_cut_copy_paste() { app_menu_bar->add("Edit/Undo", FL_COMMAND+'z', menu_undo_callback); app_menu_bar->add("Edit/Redo", FL_COMMAND+'Z', menu_redo_callback, NULL, FL_MENU_DIVIDER); app_menu_bar->add("Edit/Cut", FL_COMMAND+'x', menu_cut_callback); app_menu_bar->add("Edit/Copy", FL_COMMAND+'c', menu_copy_callback); app_menu_bar->add("Edit/Paste", FL_COMMAND+'v', menu_paste_callback); app_menu_bar->add("Edit/Delete", 0, menu_delete_callback); } #endif #if TUTORIAL_CHAPTER == 5 int main (int argc, char **argv) { tut1_build_app_window(); tut2_build_app_menu_bar(); tut3_build_main_editor(); tut4_add_file_support(); tut5_cut_copy_paste(); return tut4_handle_commandline_and_run(argc, argv); } #endif // ---- Tutorial Chapter 6 ----------------------------------------------------- #if TUTORIAL_CHAPTER >= 6 char last_find_text[1024] = ""; bool find_next(const char *needle) { Fl_Text_Editor *editor = app_editor; Fl_Widget *e = Fl::focus(); if (e && e == app_split_editor) editor = app_split_editor; int pos = editor->insert_position(); int found = app_text_buffer->search_forward(pos, needle, &pos); if (found) { app_text_buffer->select(pos, pos + (int)strlen(needle)); editor->insert_position(pos + (int)strlen(needle)); editor->show_insert_position(); return true; } else { fl_alert("No further occurrences of '%s' found!", needle); return false; } } void menu_find_callback(Fl_Widget*, void* v) { const char *find_text = fl_input("Find in text:", last_find_text); if (find_text) { fl_strlcpy(last_find_text, find_text, sizeof(last_find_text)); find_next(find_text); } } void menu_find_next_callback(Fl_Widget*, void* v) { if (last_find_text[0]) { find_next(last_find_text); } else { menu_find_callback(NULL, NULL); } } void tut6_implement_find() { app_menu_bar->add("Find/Find...", FL_COMMAND+'f', menu_find_callback); app_menu_bar->add("Find/Find Next", FL_COMMAND+'g', menu_find_next_callback, NULL, FL_MENU_DIVIDER); } #endif #if TUTORIAL_CHAPTER == 6 int main (int argc, char **argv) { tut1_build_app_window(); tut2_build_app_menu_bar(); tut3_build_main_editor(); tut4_add_file_support(); tut5_cut_copy_paste(); tut6_implement_find(); return tut4_handle_commandline_and_run(argc, argv); } #endif // ---- Tutorial Chapter 7 ----------------------------------------------------- #if TUTORIAL_CHAPTER >= 7 #include char last_replace_text[1024] = ""; void replace_selection(const char *new_text) { Fl_Text_Editor *editor = app_editor; Fl_Widget *e = Fl::focus(); if (e && e == app_split_editor) editor = app_split_editor; int start, end; if (app_text_buffer->selection_position(&start, &end)) { app_text_buffer->remove_selection(); app_text_buffer->insert(start, new_text); app_text_buffer->select(start, start + (int)strlen(new_text)); editor->insert_position(start + (int)strlen(new_text)); editor->show_insert_position(); } } class Replace_Dialog : public Fl_Double_Window { Fl_Input *find_text_input; Fl_Input *replace_text_input; Fl_Button *find_next_button; Fl_Button *replace_and_find_button; Fl_Button *close_button; public: Replace_Dialog(const char *label); void show() FL_OVERRIDE; private: static void find_next_callback(Fl_Widget*, void*); static void replace_and_find_callback(Fl_Widget*, void*); static void close_callback(Fl_Widget*, void*); }; Replace_Dialog *replace_dialog = NULL; Replace_Dialog::Replace_Dialog(const char *label) : Fl_Double_Window(430, 110, label) { find_text_input = new Fl_Input(100, 10, 320, 25, "Find:"); replace_text_input = new Fl_Input(100, 40, 320, 25, "Replace:"); Fl_Flex* button_field = new Fl_Flex(100, 70, w()-100, 40); button_field->type(Fl_Flex::HORIZONTAL); button_field->margin(0, 5, 10, 10); button_field->gap(10); find_next_button = new Fl_Button(0, 0, 0, 0, "Next"); find_next_button->callback(find_next_callback, this); replace_and_find_button = new Fl_Button(0, 0, 0, 0, "Replace"); replace_and_find_button->callback(replace_and_find_callback, this); close_button = new Fl_Button(0, 0, 0, 0, "Close"); close_button->callback(close_callback, this); button_field->end(); set_non_modal(); } void Replace_Dialog::show() { find_text_input->value(last_find_text); replace_text_input->value(last_replace_text); Fl_Double_Window::show(); } void Replace_Dialog::find_next_callback(Fl_Widget*, void* my_dialog) { Replace_Dialog *dlg = static_cast(my_dialog); fl_strlcpy(last_find_text, dlg->find_text_input->value(), sizeof(last_find_text)); fl_strlcpy(last_replace_text, dlg->replace_text_input->value(), sizeof(last_replace_text)); if (last_find_text[0]) find_next(last_find_text); } void Replace_Dialog::replace_and_find_callback(Fl_Widget*, void* my_dialog) { Replace_Dialog *dlg = static_cast(my_dialog); replace_selection(dlg->replace_text_input->value()); find_next_callback(NULL, my_dialog); } void Replace_Dialog::close_callback(Fl_Widget*, void* my_dialog) { Replace_Dialog *dlg = static_cast(my_dialog); dlg->hide(); } void menu_replace_callback(Fl_Widget*, void*) { if (!replace_dialog) replace_dialog = new Replace_Dialog("Find and Replace"); replace_dialog->show(); } void menu_replace_next_callback(Fl_Widget*, void*) { if (!last_find_text[0]) { menu_replace_callback(NULL, NULL); } else { replace_selection(last_replace_text); find_next(last_find_text); } } void tut7_implement_replace() { app_menu_bar->add("Find/Replace...", FL_COMMAND+'r', menu_replace_callback); app_menu_bar->add("Find/Replace Next", FL_COMMAND+'t', menu_replace_next_callback); } #endif #if TUTORIAL_CHAPTER == 7 int main (int argc, char **argv) { tut1_build_app_window(); tut2_build_app_menu_bar(); tut3_build_main_editor(); tut4_add_file_support(); tut5_cut_copy_paste(); tut6_implement_find(); tut7_implement_replace(); return tut4_handle_commandline_and_run(argc, argv); } #endif // ---- Tutorial Chapter 8 ----------------------------------------------------- #if TUTORIAL_CHAPTER >= 8 #include void menu_linenumbers_callback(Fl_Widget* w, void*) { Fl_Menu_Bar* menu = static_cast(w); const Fl_Menu_Item* linenumber_item = menu->mvalue(); if (linenumber_item->value()) { app_editor->linenumber_width(40); } else { app_editor->linenumber_width(0); } app_editor->redraw(); if (app_split_editor) { if (linenumber_item->value()) { app_split_editor->linenumber_width(40); } else { app_split_editor->linenumber_width(0); } app_split_editor->redraw(); } } void menu_wordwrap_callback(Fl_Widget* w, void*) { Fl_Menu_Bar* menu = static_cast(w); const Fl_Menu_Item* wordwrap_item = menu->mvalue(); if (wordwrap_item->value()) { app_editor->wrap_mode(Fl_Text_Display::WRAP_AT_BOUNDS, 0); } else { app_editor->wrap_mode(Fl_Text_Display::WRAP_NONE, 0); } app_editor->redraw(); if (app_split_editor) { if (wordwrap_item->value()) { app_split_editor->wrap_mode(Fl_Text_Display::WRAP_AT_BOUNDS, 0); } else { app_split_editor->wrap_mode(Fl_Text_Display::WRAP_NONE, 0); } app_split_editor->redraw(); } } void tut8_editor_features() { app_menu_bar->add("Window/Line Numbers", FL_COMMAND+'l', menu_linenumbers_callback, NULL, FL_MENU_TOGGLE); app_menu_bar->add("Window/Word Wrap", 0, menu_wordwrap_callback, NULL, FL_MENU_TOGGLE); } #endif #if TUTORIAL_CHAPTER == 8 int main (int argc, char **argv) { tut1_build_app_window(); tut2_build_app_menu_bar(); tut3_build_main_editor(); tut4_add_file_support(); tut5_cut_copy_paste(); tut6_implement_find(); tut7_implement_replace(); tut8_editor_features(); return tut4_handle_commandline_and_run(argc, argv); } #endif // ---- Tutorial Chapter 9 ----------------------------------------------------- #if TUTORIAL_CHAPTER >= 9 #include Fl_Tile *app_tile = NULL; void menu_split_callback(Fl_Widget* w, void*) { Fl_Menu_Bar* menu = static_cast(w); const Fl_Menu_Item* splitview_item = menu->mvalue(); if (splitview_item->value()) { int h_split = app_tile->h()/2; app_editor->size(app_tile->w(), h_split); app_split_editor->resize(app_tile->x(), app_tile->y() + h_split, app_tile->w(), app_tile->h() - h_split); app_split_editor->show(); } else { app_editor->size(app_tile->w(), app_tile->h()); app_split_editor->resize(app_tile->x(), app_tile->y()+app_tile->h(), app_tile->w(), 0); app_split_editor->hide(); } app_tile->resizable(app_editor); app_tile->init_sizes(); app_tile->redraw(); } void tut9_split_editor() { app_window->begin(); app_tile = new Fl_Tile(app_editor->x(), app_editor->y(), app_editor->w(), app_editor->h()); app_window->remove(app_editor); app_tile->add(app_editor); app_split_editor = new Fl_Text_Editor(app_tile->x(), app_tile->y()+app_tile->h(), app_tile->w(), 0); app_split_editor->buffer(app_text_buffer); app_split_editor->textfont(FL_COURIER); app_split_editor->hide(); app_tile->end(); app_tile->size_range(0, 25, 25); app_tile->size_range(1, 25, 25); app_tile->init_sizes(); app_window->end(); app_window->resizable(app_tile); app_tile->resizable(app_editor); app_menu_bar->add("Window/Split", FL_COMMAND+'i', menu_split_callback, NULL, FL_MENU_TOGGLE); } #endif #if TUTORIAL_CHAPTER == 9 int main (int argc, char **argv) { tut1_build_app_window(); tut2_build_app_menu_bar(); tut3_build_main_editor(); tut4_add_file_support(); tut5_cut_copy_paste(); tut6_implement_find(); tut7_implement_replace(); tut8_editor_features(); tut9_split_editor(); return tut4_handle_commandline_and_run(argc, argv); } #endif // ---- Tutorial Chapter 10 ---------------------------------------------------- #if TUTORIAL_CHAPTER >= 10 #include #include Fl_Text_Buffer *app_style_buffer = NULL; // Syntax highlighting stuff... #define TS 14 // default editor textsize Fl_Text_Display::Style_Table_Entry styletable[] = { // Style table #ifdef TESTING_ATTRIBUTES { FL_BLACK, FL_COURIER, TS }, // A - Plain { FL_DARK_GREEN, FL_HELVETICA_ITALIC, TS, Fl_Text_Display::ATTR_BGCOLOR, FL_LIGHT2 }, // B - Line comments { FL_DARK_GREEN, FL_HELVETICA_ITALIC, TS, Fl_Text_Display::ATTR_BGCOLOR_EXT, FL_LIGHT2 }, // C - Block comments { FL_BLUE, FL_COURIER, TS, Fl_Text_Display::ATTR_UNDERLINE }, // D - Strings { FL_DARK_RED, FL_COURIER, TS, Fl_Text_Display::ATTR_GRAMMAR }, // E - Directives { FL_DARK_RED, FL_COURIER_BOLD, TS, Fl_Text_Display::ATTR_STRIKE_THROUGH }, // F - Types { FL_BLUE, FL_COURIER_BOLD, TS, Fl_Text_Display::ATTR_SPELLING }, // G - Keywords #else { FL_BLACK, FL_COURIER, TS }, // A - Plain { FL_DARK_GREEN, FL_HELVETICA_ITALIC, TS }, // B - Line comments { FL_DARK_GREEN, FL_HELVETICA_ITALIC, TS }, // C - Block comments { FL_BLUE, FL_COURIER, TS }, // D - Strings { FL_DARK_RED, FL_COURIER, TS }, // E - Directives { FL_DARK_RED, FL_COURIER_BOLD, TS }, // F - Types { FL_BLUE, FL_COURIER_BOLD, TS }, // G - Keywords #endif }; const char *code_keywords[] = { // List of known C/C++ keywords... "and", "and_eq", "asm", "bitand", "bitor", "break", "case", "catch", "compl", "continue", "default", "delete", "do", "else", "false", "for", "goto", "if", "new", "not", "not_eq", "operator", "or", "or_eq", "return", "switch", "template", "this", "throw", "true", "try", "while", "xor", "xor_eq" }; const char *code_types[] = { // List of known C/C++ types... "auto", "bool", "char", "class", "const", "const_cast", "double", "dynamic_cast", "enum", "explicit", "extern", "float", "friend", "inline", "int", "long", "mutable", "namespace", "private", "protected", "public", "register", "short", "signed", "sizeof", "static", "static_cast", "struct", "template", "typedef", "typename", "union", "unsigned", "virtual", "void", "volatile" }; // // 'compare_keywords()' - Compare two keywords... // extern "C" { int compare_keywords(const void *a, const void *b) { return (strcmp(*((const char **)a), *((const char **)b))); } } // // 'style_parse()' - Parse text and produce style data. // void style_parse(const char *text, char *style, int length) { char current; int col; int last; char buf[255], *bufptr; const char *temp; // Style letters: // // A - Plain // B - Line comments // C - Block comments // D - Strings // E - Directives // F - Types // G - Keywords for (current = *style, col = 0, last = 0; length > 0; length --, text ++) { if (current == 'B' || current == 'F' || current == 'G') current = 'A'; if (current == 'A') { // Check for directives, comments, strings, and keywords... if (col == 0 && *text == '#') { // Set style to directive current = 'E'; } else if (strncmp(text, "//", 2) == 0) { current = 'B'; for (; length > 0 && *text != '\n'; length --, text ++) *style++ = 'B'; if (length == 0) break; } else if (strncmp(text, "/*", 2) == 0) { current = 'C'; } else if (strncmp(text, "\\\"", 2) == 0) { // Quoted quote... *style++ = current; *style++ = current; text ++; length --; col += 2; continue; } else if (*text == '\"') { current = 'D'; } else if (!last && (islower((*text)&255) || *text == '_')) { // Might be a keyword... for (temp = text, bufptr = buf; (islower((*temp)&255) || *temp == '_') && bufptr < (buf + sizeof(buf) - 1); *bufptr++ = *temp++) { // nothing } if (!islower((*temp)&255) && *temp != '_') { *bufptr = '\0'; bufptr = buf; if (bsearch(&bufptr, code_types, sizeof(code_types) / sizeof(code_types[0]), sizeof(code_types[0]), compare_keywords)) { while (text < temp) { *style++ = 'F'; text ++; length --; col ++; } text --; length ++; last = 1; continue; } else if (bsearch(&bufptr, code_keywords, sizeof(code_keywords) / sizeof(code_keywords[0]), sizeof(code_keywords[0]), compare_keywords)) { while (text < temp) { *style++ = 'G'; text ++; length --; col ++; } text --; length ++; last = 1; continue; } } } } else if (current == 'C' && strncmp(text, "*/", 2) == 0) { // Close a C comment... *style++ = current; *style++ = current; text ++; length --; current = 'A'; col += 2; continue; } else if (current == 'D') { // Continuing in string... if (strncmp(text, "\\\"", 2) == 0) { // Quoted end quote... *style++ = current; *style++ = current; text ++; length --; col += 2; continue; } else if (*text == '\"') { // End quote... *style++ = current; col ++; current = 'A'; continue; } } // Copy style info... if (current == 'A' && (*text == '{' || *text == '}')) *style++ = 'G'; else *style++ = current; col ++; last = isalnum((*text)&255) || *text == '_' || *text == '.'; if (*text == '\n') { // Reset column and possibly reset the style col = 0; if (current == 'B' || current == 'E') current = 'A'; } } } // // 'style_init()' - Initialize the style buffer... // void style_init(void) { char *style = new char[app_text_buffer->length() + 1]; char *text = app_text_buffer->text(); memset(style, 'A', app_text_buffer->length()); style[app_text_buffer->length()] = '\0'; if (!app_style_buffer) app_style_buffer = new Fl_Text_Buffer(app_text_buffer->length()); style_parse(text, style, app_text_buffer->length()); app_style_buffer->text(style); delete[] style; free(text); } // // 'style_unfinished_cb()' - Update unfinished styles. // void style_unfinished_cb(int, void*) { } // // 'style_update()' - Update the style buffer... // void style_update(int pos, // I - Position of update int nInserted, // I - Number of inserted chars int nDeleted, // I - Number of deleted chars int /*nRestyled*/, // I - Number of restyled chars const char * /*deletedText*/,// I - Text that was deleted void *cbArg) { // I - Callback data int start, // Start of text end; // End of text char last, // Last style on line *style, // Style data *text; // Text data // If this is just a selection change, just unselect the style buffer... if (nInserted == 0 && nDeleted == 0) { app_style_buffer->unselect(); return; } // Track changes in the text buffer... if (nInserted > 0) { // Insert characters into the style buffer... style = new char[nInserted + 1]; memset(style, 'A', nInserted); style[nInserted] = '\0'; app_style_buffer->replace(pos, pos + nDeleted, style); delete[] style; } else { // Just delete characters in the style buffer... app_style_buffer->remove(pos, pos + nDeleted); } // Select the area that was just updated to avoid unnecessary // callbacks... app_style_buffer->select(pos, pos + nInserted - nDeleted); // Re-parse the changed region; we do this by parsing from the // beginning of the previous line of the changed region to the end of // the line of the changed region... Then we check the last // style character and keep updating if we have a multi-line // comment character... start = app_text_buffer->line_start(pos); // if (start > 0) start = app_text_buffer->line_start(start - 1); end = app_text_buffer->line_end(pos + nInserted); text = app_text_buffer->text_range(start, end); style = app_style_buffer->text_range(start, end); if (start==end) last = 0; else last = style[end - start - 1]; // printf("start = %d, end = %d, text = \"%s\", style = \"%s\", last='%c'...\n", // start, end, text, style, last); style_parse(text, style, end - start); // printf("new style = \"%s\", new last='%c'...\n", // style, style[end - start - 1]); app_style_buffer->replace(start, end, style); ((Fl_Text_Editor *)cbArg)->redisplay_range(start, end); if (start==end || last != style[end - start - 1]) { // printf("Recalculate the rest of the buffer style\n"); // Either the user deleted some text, or the last character // on the line changed styles, so reparse the // remainder of the buffer... free(text); free(style); end = app_text_buffer->length(); text = app_text_buffer->text_range(start, end); style = app_style_buffer->text_range(start, end); style_parse(text, style, end - start); app_style_buffer->replace(start, end, style); ((Fl_Text_Editor *)cbArg)->redisplay_range(start, end); } free(text); free(style); } void menu_syntaxhighlight_callback(Fl_Widget* w, void*) { Fl_Menu_Bar* menu = static_cast(w); const Fl_Menu_Item* syntaxt_item = menu->mvalue(); if (syntaxt_item->value()) { style_init(); app_editor->highlight_data(app_style_buffer, styletable, sizeof(styletable) / sizeof(styletable[0]), 'A', style_unfinished_cb, 0); app_text_buffer->add_modify_callback(style_update, app_editor); } else { app_text_buffer->remove_modify_callback(style_update, app_editor); app_editor->highlight_data(NULL, NULL, 0, 'A', NULL, 0); } app_editor->redraw(); if (app_split_editor) { if (syntaxt_item->value()) { app_split_editor->highlight_data(app_style_buffer, styletable, sizeof(styletable) / sizeof(styletable[0]), 'A', style_unfinished_cb, 0); } else { app_split_editor->highlight_data(NULL, NULL, 0, 'A', NULL, 0); } app_split_editor->redraw(); } } void tut10_syntax_highlighting() { app_menu_bar->add("Window/Syntax Highlighting", 0, menu_syntaxhighlight_callback, NULL, FL_MENU_TOGGLE); } #endif #if TUTORIAL_CHAPTER == 10 int main (int argc, char **argv) { tut1_build_app_window(); tut2_build_app_menu_bar(); tut3_build_main_editor(); tut4_add_file_support(); tut5_cut_copy_paste(); tut6_implement_find(); tut7_implement_replace(); tut8_editor_features(); tut9_split_editor(); tut10_syntax_highlighting(); return tut4_handle_commandline_and_run(argc, argv); } #endif fltk-1.4.3/test/adjuster.cxx0000644000175000017500000000242015004135251016127 0ustar albrechtalbrecht// // Adjuster test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include void adjcb(Fl_Widget *o, void *v) { Fl_Adjuster *a = (Fl_Adjuster*)o; Fl_Box *b = (Fl_Box *)v; a->format((char *)(b->label())); b->redraw(); } int main(int argc, char ** argv) { Fl_Double_Window window(320,100,argv[0]); char buf1[100]; Fl_Box b1(FL_DOWN_BOX,20,30,80,25,buf1); b1.color(FL_WHITE); Fl_Adjuster a1(20+80,30,3*25,25); a1.callback(adjcb,&b1); adjcb(&a1,&b1); char buf2[100]; Fl_Box b2(FL_DOWN_BOX,20+80+4*25,30,80,25,buf2); b2.color(FL_WHITE); Fl_Adjuster a2(b2.x()+b2.w(),10,25,3*25); a2.callback(adjcb,&b2); adjcb(&a2,&b2); window.resizable(window); window.end(); window.show(argc, argv); return Fl::run(); } fltk-1.4.3/test/resizebox.cxx0000644000175000017500000000476115004135251016332 0ustar albrechtalbrecht// // Resize box test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #define W1 (big ? 60 : 40) #define B 0 #define W3 (5*W1+6*B) Fl_Double_Window *window; Fl_Box *box; int big = 0; void b_cb(Fl_Widget *,long w) { if (window->w() != W3 || window->h() != W3) { fl_message("Put window back to minimum size before changing"); return; } window->init_sizes(); switch (w) { case 0: box->hide(); window->box(FL_FLAT_BOX); window->resizable(0); return; case 8: box->resize(W1+B,W1,2*W1,B); break; case 2: box->resize(W1+B,W1+B+2*W1,2*W1,B); break; case 4: box->resize(W1+B,W1,B,2*W1); break; case 6: box->resize(W1+B+2*W1,W1+B,B,2*W1); break; } window->box(FL_NO_BOX); if (w == 6 || w == 4) box->label("re\nsiz\nab\nle"); else box->label("resizable"); box->show(); window->resizable(box); window->redraw(); } int main(int argc, char **argv) { window = new Fl_Double_Window(W3,W3); window->box(FL_NO_BOX); Fl_Box *n; for (int x = 0; x<4; x++) for (int y = 0; y<4; y++) { if ((x==1 || x==2) && (y==1 || y==2)) continue; n = new Fl_Box(FL_FRAME_BOX,x*(B+W1)+B,y*(B+W1)+B,W1,W1,0); n->color(x+y+8); } n = new Fl_Box(FL_FRAME_BOX,B,4*W1+5*B,4*W1+3*B,W1,0); n->color(12); n = new Fl_Box(FL_FRAME_BOX,4*W1+5*B,B,W1,5*W1+4*B,0); n->color(13); n = new Fl_Box(FL_FRAME_BOX,W1+B+B,W1+B+B,2*W1+B,2*W1+B,0); n->color(8); Fl_Button *b = new Fl_Radio_Button(W1+B+50,W1+B+30,20,20,"@6>"); b->callback(b_cb,6); (new Fl_Radio_Button(W1+B+30,W1+B+10,20,20,"@8>"))->callback(b_cb,8); (new Fl_Radio_Button(W1+B+10,W1+B+30,20,20,"@4>"))->callback(b_cb,4); (new Fl_Radio_Button(W1+B+30,W1+B+50,20,20,"@2>"))->callback(b_cb,2); (new Fl_Radio_Button(W1+B+30,W1+B+30,20,20,"off"))->callback(b_cb,0); box = new Fl_Box(FL_FLAT_BOX,0,0,0,0,"resizable"); box->color(FL_DARK2); b->set(); b->do_callback(); window->end(); window->size_range(W3,W3); window->show(argc,argv); return Fl::run(); } fltk-1.4.3/test/pixmap.cxx0000644000175000017500000000675615004135251015624 0ustar albrechtalbrecht// // Pixmap label test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include "pixmaps/animated_fluid_gif.h" #include Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*overb,*inactb; Fl_Button *b; Fl_Double_Window *w; Fl_Anim_GIF_Image *pixmap; Fl_Anim_GIF_Image *depixmap; void button_cb(Fl_Widget *wgt,void *) { int i = 0; if (leftb->value()) i |= FL_ALIGN_LEFT; if (rightb->value()) i |= FL_ALIGN_RIGHT; if (topb->value()) i |= FL_ALIGN_TOP; if (bottomb->value()) i |= FL_ALIGN_BOTTOM; if (insideb->value()) i |= FL_ALIGN_INSIDE; if (overb->value()) i |= FL_ALIGN_TEXT_OVER_IMAGE; b->align(i); if (inactb->value()) b->deactivate(); else b->activate(); w->redraw(); } void play_cb(Fl_Widget *wgt,void *) { pixmap->start(); depixmap->start(); } void stop_cb(Fl_Widget *wgt,void *) { pixmap->stop(); depixmap->stop(); } void step_cb(Fl_Widget *wgt,void *) { pixmap->next(); depixmap->next(); } int dvisual = 0; int arg(int, char **argv, int &i) { if (argv[i][1] == '8') {dvisual = 1; i++; return 1;} return 0; } #include int main(int argc, char **argv) { int i = 1; if (Fl::args(argc,argv,i,arg) < argc) Fl::fatal(" -8 # : use default visual\n%s\n", Fl::help); if (!dvisual) Fl::visual(FL_RGB); Fl_Double_Window window(400,440); ::w = &window; Fl_Button b(130,170,140,140,"Pixmap"); ::b = &b; Fl_Anim_GIF_Image::animate = true; pixmap = new Fl_Anim_GIF_Image("fluid", animated_fluid_gif, animated_fluid_gif_size, &b, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS); pixmap->speed(0.5); b.image(pixmap); depixmap = (Fl_Anim_GIF_Image*)pixmap->copy(); depixmap->inactive(); b.deimage(depixmap); // "bind" images to avoid memory leak reports (valgrind, asan) // note: these reports are benign because they appear at exit, but anyway b.bind_image(pixmap); b.bind_deimage(depixmap); leftb = new Fl_Toggle_Button(25,50,50,25,"left"); leftb->callback(button_cb); rightb = new Fl_Toggle_Button(75,50,50,25,"right"); rightb->callback(button_cb); topb = new Fl_Toggle_Button(125,50,50,25,"top"); topb->callback(button_cb); bottomb = new Fl_Toggle_Button(175,50,50,25,"bottom"); bottomb->callback(button_cb); insideb = new Fl_Toggle_Button(225,50,50,25,"inside"); insideb->callback(button_cb); overb = new Fl_Toggle_Button(25,75,100,25,"text over"); overb->callback(button_cb); inactb = new Fl_Toggle_Button(125,75,100,25,"inactive"); inactb->callback(button_cb); Fl_Button* play = new Fl_Button(300, 50, 25, 25, "@>"); play->labelcolor(FL_DARK2); play->callback(play_cb); Fl_Button* stop = new Fl_Button(325, 50, 25, 25, "@||"); stop->labelcolor(FL_DARK2); stop->callback(stop_cb); Fl_Button* step = new Fl_Button(350, 50, 25, 25, "@|>"); step->labelcolor(FL_DARK2); step->callback(step_cb); window.resizable(window); window.end(); window.show(argc,argv); return Fl::run(); } fltk-1.4.3/test/pixmaps/0000755000175000017500000000000015004135251015245 5ustar albrechtalbrechtfltk-1.4.3/test/pixmaps/magenta_bomb.xpm0000644000175000017500000000325215004135251020410 0ustar albrechtalbrecht/* XPM */ static const char * const magenta_bomb_xpm[] = { "32 32 32 1", " c #000100", ". c #3A033B", "+ c #410142", "@ c #48004B", "# c #6C006C", "$ c #541954", "% c #840084", "& c #9B009D", "* c #612F61", "= c #AC00AC", "- c #792A7D", "; c #BA00B9", "> c #C200C2", ", c #813285", "' c #D000D0", ") c #734472", "! c #B91EBA", "~ c #8E488B", "{ c #B034B1", "] c #855A85", "^ c #CD31CD", "/ c #C643C7", "( c #967098", "_ c #AC6DAC", ": c #C960CA", "< c #D859D8", "[ c #E770E7", "} c #E376E3", "| c #DD7CDD", "1 c #EF8BEF", "2 c #E894E8", "3 c #E7A2E8", " @%&>;;=;;>>>>;=;>>>=%@ ", " .&'^[1333333333333332:^;%. ", " @>'[22233333332333333333|^;@ ", " .'^121111112221112333333333^'. ", " &^1111111111222111122222_322'& ", "@><}}}1[1[[[}}1111[}}}|2|2|_2[>@", "%>}[}[[[[[[2_((((((2|[}|||||||>%", "=^<<<<<<[:_]((((((](]_:::::|:|/=", ";<<<<<<<:]]]]]]]]]]]]]]::::::::>", ";//<^<^:)))])])])])]]]]]<<:{::<=", "=/^^^;!={*.*.*.*$*$$$$$*$*$**!!{{{=", ";'>!=&..*.*.$$$$$$$$$$$$$$!;!!=!", ">>>>!{.....$.@+@@@$+$+$+$$;!;!!=", ";''>>=...++@+++++@@++...++;!;;;;", ";>'';;.++@@+.+..+++++..+++>;;===", ";;;>>>+++@++..++.+++++++++>;;===", "==;;;>%+@+@++.......++++@#>>;===", "=;;>>>=+@+@@+.........++@=''>===", ";;>>'''#@@+++...........#>'>';==", ";;>>'''^@@@++..........+=''>>>>;", ";;;>''''=@++++......+.+&>>''>>;;", "=;;>>'>;>=#.++++.....#&;>>'''''=", "%!;;>;;===;%#++++++#&;;;;>'''''%", "@;;;;;;=&==>;;>;>>>'>>;;>''''''@", " &=!;;==&&======>>''>>;>>'''''& ", " .;;;>;==&===&=;;>''';;>'''''>. ", " @;>>>;=&&==&=;>'>'>>>''''''@ ", " .&>>==;==&=&=>'>>>>;>'''{. ", " @%======&&=;>'>'>>>!%@ "}; fltk-1.4.3/test/pixmaps/checker.svg0000644000175000017500000002736715004135251017411 0ustar albrechtalbrecht Checkers image/svg+xml Checkers Jan 28 2022 Greg Ercolano, Matthias Melcher fltk.org fltk-1.4.3/test/pixmaps/black_checker.png0000644000175000017500000001374615004135251020526 0ustar albrechtalbrechtPNG  IHDRppK pHYs""S@tEXtSoftwarewww.inkscape.org<tEXtTitleCheckers) ,&tEXtAuthorGreg Ercolano, Matthias MelchercNtEXtCreation TimeJan 28 2022㫄bIDATx[#UzTw{zzMeQ@b%%]!He +"^BqDDJ5 R20`3L=[ٮ:_\>u\Kn{I\.߹Թ0\9ڼ:k f h\QK7\C2 SLos]W?C!?g~G"[|D4ED& B[\m{Z. sKKKgʨJu~]:0v*#1{"l۶Ojw »|L&c PwҎ@06 -a?1'n &TTfq Fu+=n6x~.FTzyuuN:uu6U nÇ:GܺpzIBؕJȅ ԩSgPX?PqW2ww};gD84aY[ :H?~ iC9,p39Gw ^RO>|umإ: xO<āD"sFDl t87{ĉTXhS3d 6Ȇ?bo N7LOMMk%~VVz>bPÇ|y!40nYXXy (Ã  c3333?ȥЄ6=| bz[p+*aH$N&Y6l{'oK$oi2yX,^*| 4!yDZ~ah g~,o!ā1䡧kT[/_ O6P`s=waoѾqQyC2&N/[vӨ WjD&AdH/, B6"20M3 Q7NNNƳ>`:CA <=h "ְmcss@>eY`}a H`ffT bCWŋ_Yg}w`wq1;;}{XVVVpyض]ԣR R I,,,`D"CSc2<<77!PQ'loajX^^Q(:BX./bnn^{-b0<_V*ծ!v[2g?HN>wy+++j&rMT*LLLs>P5MNN.f%*O dc=v`bbM"Jt:z gΜAV(4y J㜣Zb{{F\$B@CYTDt ?>Hbwtd2(JaSrџ^vJ;)`O?ݜ_, o6N<S]ޛa0 cPJH@>?Ȯ@ԟ_wu/+8rׇ-,<1ض Xb?Z"[TDq6=Yz~seC.믿|>?Tx R;zdDžBB 2{...;J"^}]ne|aD#"Rl> P]m]w]`r#G\QTBw5-H|@iS&$DDPKuȀM_Nd2Wdxgggy3!tMJŎ1"I?7h6>]*p8b+bpRjU'J>- [裏."`W7Rt>77W0]`Txg*Z#Ƚak'OjI\i.:j{P-ᶕFOoq'}߾}=E(c3h*Oϯ  !";w9G2D$.M“H:V2PtxbC=HJYJmkkkW=<9 A"a0h.STVbS8onnqkIORjpky@F1?SM`]c@`M<"clPVdhQzO ލ/_gq^^k (c, v1Wbn Nz>3OMMuQ Mw}2P}"cׄ eR)x`f;x9O8# l1O8Δ罔}DBI]U>e\yF9y/7Fv"MzT+2PJ>AӭG~1I T^$C(曣BH&D (W:<9"HhxIҘk|3 ;TPKEx^aAUCgf$"*mBq'$<@q8ND9s8獮0dkPT=HDEX,qQ* Dԛ AyzbaCh<a{ Ś!.dI㬆#!%xsrs[X8˽SӒ䞂9G:]pM3OGe}=/ˡP(V I.bnNuQg ҥKmuJBSi Ξ={aCh4䞀9Cs4`~S6 \[[+۶},l%" xrkkkʸNi;8u![7lMTY0Ʈjxs={҄ONT'~v S5M1Vj1u $<! h ~Zxs>} Byx~{Tv%*2LVvdh#a8ᣏ>ZiAiBO'UEvH;;; _i#Acǰ/Up*HZSXK@|'8zJD0 Tj>H/ 8zhB>W}54X%rl[5Q6==X,63oBY}cY!mf2Pйx !ja>;;{U?+++j8NMuɰYE}7*@k)nܹskj~¨1LLL0CkkkxGD$tX']*P_ũaOR` Qrۆht ^zFf_"KRY庪@B%D{yyeYoR J_q*rxQT|y~Hq)U&7*.UB% _}/ǩ[QԨtL/Bcq Q9@KIWGri4KS8 kkkxQ*mP xM4S꣢f_,,,>4q`6XPcOkVSYٶ F]e% yJh-}oI]mH$D"~J,0Ms,ڊB ;'{fS˹y76 mzqk?r ˲H$DvP/ckkg@«#XESMvJ鏓|- T/?ۿH Nur] OƫSN5[YQhβ (fS_Zh{U m㜚@h~irte4M$7=JN87x'Oe5 [@.)I쓵P@x*(t h0J=)hxP(177}Vf.åK; b8Η6 M[h@e[P ,&j9fgo?aK㼾tFK@ڶ !"rr4b?XOiDTuJR KKSjS}ԓuUbu3Rr_&?&8%czٶm&H}.@=zz#~7 ݳ;mi˲9FDB\ -4ǨAm=9l/l @J T˛ulިT*'9O1cB8Ζ8( o@uS<Za6†vuW569sZm+~4c<"* !.)YxGGKp j&]dzC^h]G潞h>Rӗ==y&SH&4 Xp7lU! B<e>ф\uTZӔ>%̼r^D^ai;:P}BB|!}=@$c3i^g~X16'"B'Wѓ/+,2|!T"Oʊ:IeCф('Lg!pXs>#$"!=RVD}m1Jv}P?j_-7P95iT9o%x3Tx[5t^7\꣪atކ[mBReg\# oI~}TƂ*U q? )zMs`7/Ӫd&奺P;t~VC2P^A|CQj AI&ZFNR սTS>_OSc <`x2Q]}y~,T?_Ut}_So ʣo96Lg VWk %%N{+m c #507B7C", ", c #00A7A9", "' c #5D8989", ") c #00B7B7", "! c #00C1C1", "~ c #2FB2B3", "{ c #6D9A9A", "] c #00CAC9", "^ c #4AB4B3", "/ c #05D4D2", "( c #36C8C9", "_ c #53C4C3", ": c #46D3D4", "< c #61D3D3", "[ c #75CECE", "} c #6FE2E1", "| c #82DFDE", "1 c #94E0E1", "2 c #89EFED", "3 c #A2ECEC", " #-,!))~))!)!!)~)!!!,-# ", " +;]:}2333333333333331<();+ ", " #!/}23333333333333333333[!!# ", " +!/322222221332223311111111:!+ ", " ;:2222222222|23222233111111|/; ", "#!:}|}222222|||}22222}|1[1[[1}]#", "-:<}}}}}}}}[^{{{{{{[[2}|[[[[[|!-", ",:}:}:}}}<{'''''''{'{{[<<|[[[<_,", "!:<<:}::_'>'>>'>'''''''[<<<[_<:!", ")(:::::^>>>>>>>>>>>''''>_::____~", ",((:::(>===>=>=>>>=>>>>>'(:___^,", "~(((](;===#========&&=*=*^(_^^~;", ")](()_&%%==%=%===*===*==*-~)^~~,", "!!!)~,=#.%%#%%%%*%******%=())~~,", ")]()~,.%%%%%%%%%%%%%%%%%%%()))~)", "(!]!)^.....$%$$$$$$$$$$$$$)))))~", "!]:])~...%$$.@#@@@@@.@.$@@))))))", ")]]]!(.$$.@@..@.@@@@@@..@$)))))~", "~!)!)!.$$%$.@....@#@.@@@#@()),,,", ",)!~!(&@@@@$...........@$&]!)),,", ")))!]]~$$$@$.........@@@$,:]!),,", "~)!!///&$$$@@...........&]]]!)))", "))!!://!%$$@...........@,]/]])))", "!))!///],@#$..........@;]]]]]!]!", ",)!)!!!!!,&.@#@......*,)!]]]/]!,", "-)~!!!)),));&@@@$.@&;!)))!/////-", "#)~))),,;,,)))!)!!:]]!!!!]/////#", " ;))))),;,,)~~,)!!]/]!)!]/////; ", " +)!!!!),,,,,,,)!]]/!()!/////!+ ", " #)]!)),,,,,,,)!!/!]!)!////]# ", " +;]!),,,,,;,)!]]!!!!!]//,+ ", " #-,))));,,,!!]!]!!!)-# "}; fltk-1.4.3/test/pixmaps/white_checker.png0000644000175000017500000001461015004135251020561 0ustar albrechtalbrechtPNG  IHDRppK pHYs""S@tEXtSoftwarewww.inkscape.org<tEXtTitleCheckers) ,&tEXtAuthorGreg Ercolano, Matthias MelchercNtEXtCreation TimeJan 28 2022㫄bIDATxylםǿ[eYuؖ^`SvW9QEZvafAlXoMcqqcn}q4AXvi"EQg8|4k]xg9>=%揕wSKHQ8/Dgw\뜦J'BX-o``ݻwf#_m[ε4V\Xm׬YNezba BH̗IfDQH$x9BNآ 9-@ڕ4Ν f{P~)Ky4<:<@d l@3A@(;*8y{'/eck(@woƋ?Ur `jAT ^Uv _&ƍ~<"r iKAf &''6lVtI*8q⿞x≏( \51󥪴. 8!MƊ;} RD>#H"{vرgVM#k֬ٲo߾eY"&VS-?27n>%| yjj]~}S{{ t:H$I IdYffCkk+<,ww~s o4b-K.unڴA\Y177aqqtVeٖl6YAWWZZZ}GO9KPT>{XO=p=B0;; LMM!ͪ~oA@,C2_|Պ6N^G}K.<8u'5{ADWsJ5g fٞ",˸pFGG 8cnGOOz< bX?|@$__d|t TyCwG8>$ Cp9j u+{L&%4Jeͩ^eTB@C(RZmt...Zz!^!ř3g@U[VB?vYL&#;yatt `1_"i"[g~TP+T*W^|Á 6?OWo /t I%BK, fggn"k=?Lj{zz&űfToMURJP(8Xm/p8A&jƣ# Ewb2 (iPv B= /;w|W6Fobii"MXi-Zd2ZD$Pk*5Hi\IћOR8tBЊZ~k|t?$) &.X[jhUS4۴{`_򗘝Z*ђFh-!vp8dbtt4a6Vz]`0wNCw `ddgΜi2|eu/rDN?U JSV Bnof~?>_fkbA67[V/=P?UDq?FS5[&''7ZrkBN: 549S=6yP؂@r)Ēv`|3!rV}nE,R+kB v}egϞLdcfSVr?rhiڌZQe>ŋNxfBHcf(fP؄0 5@;355tuuoF !k WfUFӌ 0r>X3k_~͛7yT\(2}@Ì>PZc'''o;f<=pl7 @fsm֛e^Md+T&w߽EspY (@GGv#7(JQ7 Rptw5)QXZ&Uhc077״p}fD=pt#N BZ (l6CfSVG{{{bjx|Mjl¡jVGH%UFTW[n] R|e^YMUX,5E$iiF-4Uc>~ggg Xx.Du&=13@6fa@> 2|ޱ$e}?|.**Bcfz&pt5Z)+\&Txꩧ#IiZ%UOj2[+7}*)hPZӿiJha=biu.Tl >prrBR 4]nR+8,O4- bč\iMcwZR+8H$@6\BHqeFia-xW􂗂PBHx<+z`J0IHt/->|c$mF+u\@"U#S!•IjBievv6JVS=y,Yn]ZeL&Q8@ Rëhxo޼i`GGG]M$JrvjGX&8(BA,̗4!D\. éJD"Q8ڵ$)f$̈́@[ GIόwO%IeA+`6#/ukH(u}\YxTy'N wڵp4y񱱱_F*/6(6Qc|,= DEC#ۿonxZ Z' ҁF̨A>?ZnmE2ȓ%>k}T7PCF(7rJl% ȕaSkׂVOte4JVbNH m `Y3zGl,9ݧdCQYIzĬVki\ɕ.B>ᵊJ6pS'+ o-ӸJjGl ;-sX464V +z@!0@54V /[OJv'>m/T.G c #1718B3", ", c #1616C2", "' c #2628CF", ") c #2C2BC6", "! c #2D30BD", "~ c #3D40D1", "{ c #4342BC", "] c #4344CA", "^ c #5253E1", "/ c #5858D4", "( c #5F5ECF", "_ c #6A69E7", ": c #6E6EDD", "< c #7273D2", "[ c #7E7FDD", "} c #7E7FEC", "| c #8D8DDF", "1 c #8F90EF", "2 c #9D9EED", "3 c #A6A6E8", " ;+.*$##$$**$*$#$*&&.+; ", " -@&)_133333333333333|:!$@- ", " ;%%}22122222222233333333['$; ", " -&'1111111|2|21111|2223|332'&- ", " @*}}}}1}}}1}1111111[|[||||||*. ", ";&/}[}}}}}}}[[[}}}}}[}[[||||[:&;", "+'::::_____:::<::__}_}:<<<<<[<)+", ">)/_/_____::(::::_____:(<<<<<<].", "*^//^/////(((((//_^_^_///(((((/$", "#]]]]^^{/{{{{/{//^^^^^^///{(((($", ".]~~~~]{{{{{{{]{]~~~~~~~]{]{{{(.", "#))))!!!{{{]!~!!~~'~''~~~]{{{{{.", "#))))!!!@!>!!))))''''''~)!!!{{+.", "$,,>>>@!>>)>,'''''''''''))!>!!!.", "$,,#>>>>.>,,&*%*'*''*',,,,,>>>>#", "&%%$#...#&&%*%***%%&*$,***,>#>>#", "$&%&*###&&%%&&&&,*&*,##$*$$#$$#$", "$&%%$$$*&%&**$$$&&&&&$#$***#,#.#", "$$$&$*&%%=&&$##$$**&&$**&&&$$#..", ".#$$&&%%%%%&,....##$#$$&%%&&$#.#", ".#$$&%%===%%&#.....###$&%%%&&#.#", "$$&&%=====%%$##.@..#.##&&&%%&$$#", "$$&&%==%==%&$###.....##$%&%&&$$$", "$$$&&%%%%%&&$$###..###$$&%&%&&$$", ".$$&&&&$$&$$*&&*$$#$$$$$$%%%%%&.", "+$$$$&####$&$&&&&&$$&$$$$&%=%%=+", ";##$$$#....$$&&&$&&%&&$$*&%==%%;", " @$,#$#.@..##.#$&&%%%&$&&=%%%%. ", " -$*$&&$.......#&&&%&&$&%==%%&- ", " ;$&&$#...#...$&%%%&&$&%=%=%; ", " -@%&$#..#...#$%&&&&&&&=%.- ", " ;+.#$#....#&&%%&&&&#+; "}; fltk-1.4.3/test/pixmaps/porsche.xpm0000644000175000017500000001062015004135251017435 0ustar albrechtalbrecht/* XPM */ static const char * const porsche_xpm[] = { "64 64 4 1", " c #background", ". c #000000000000", "X c #ffd100", "o c #FFFF00000000", " ", " .......................... ", " ..................................... ", " ............XXXXXXXXXXXXXXXXXXXXXXXX............ ", " ......XXXXXXX...XX...XXXXXXXX...XXXXXXXXXX...... ", " ..XXXXXXXXXX..X..XX..XXXX.XXXX..XXXXXXXXXXXXXX.. ", " ..XXXXXXXXXX..X..XX..XXX..XXXX..X...XXXXXXXXXX.. ", " ..XXXXXXXXXX..XXXXX..XX.....XX..XX.XXXXXXXXXXX.. ", " ..XXXXXXXXX.....XXX..XXX..XXXX..X.XXXXXXXXXXXX.. ", " ..XXXXXXXXXX..XXXXX..XXX..XXXX....XXXXXXXXXXXX.. ", " ..XXXXXXXXXX..XXXXX..XXX..XXXX..X..XXXXXXXXXXX.. ", " ..XXXXXXXXXX..XXXXX..XXX..X.XX..XX..XXXXXXXXXX.. ", " ..XXXXXXXXX....XXX....XXX..XX....XX..XXXXXXXXX.. ", " ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.. ", " ..XXXXXXXXX..........................XXXXXXXXX.. ", " ..XXX.......XXXXXXXXXXX...................XXXX.. ", " ......XX.XXX.XXX..XXXXX......................... ", " ..XXXXX.XXX.XXX.XXXX.XX......................... ", " ..XXXX.XXX.XX.......XXX......................... ", " ..XXXX.......XXXXXX..XX..ooooooooooooooooooooo.. ", " ..X.....XXXXXXXXXXXXXXX..ooooooooooooooooooooo.. ", " ..X...XXXXXXXXXXXXXXXXX..ooooooooooooooooooooo.. ", " ..X..XXXXXXX.XX.XXXXXXX..ooooooooooooooooooooo.. ", " ..XXXXX.XXX.XX.XXXXXXXX..ooooooooooooooooooooo.. ", " ..XXXX.XXX.XX.XX................................ ", " ..XXXX.X.........X....X.X.X..................... ", " ..XXXX...XXXXXXX.X..X...X.X.X.X................. ", " ..X....XXXXXXXXXX.X...X.X.X..................... ", " ..X...XXXXXXXXXX.XXXXXXXXXXXXXX................. ", " ..X..XXXXXX.XX.X.XXX...XXXXXXXX................. ", " ..XXXXX.XX.XX.XX.XX.....XXXXXXX.oooooooooooooo.. ", " ..XXXX.XX.XX.XX..XX.X...XXXXX.X.oooooooooooooo.. ", " ..XXXX.X.......X.XXXX...XXXX..X.oooooooooooooo.. ", " ..X......XXXXXX..XXXX...XXXX..X.oooooooooooooo.. ", " ..X...XXXXXXXXXX.XXX.....XXX.XX.oooooooooooooo.. ", " ..X..XXXXXXXXXXX.X...........XX.oooooooooooooo.. ", " .................X.X.........XX................. ", " .................X.X.XXXX....XX.XXXXXXXXXXXXXX.. ", " .................XXX.XXXXX.X.XX.XXX.XX.XXXXXXX.. ", " ................XXXX.XXX..X..X.XX.XX.XXX.XXX.. ", " ................XXXXXXXX.XX.XX.X.XX.XXX.XXXX.. ", " .................XXXXXX.XX.XX.X..........XXX.. ", " ..oooooooooooooo.XXXXXXXXXX....XXXXXXXX..X.. ", " ..ooooooooooooooo.XXXXXXXX....XXXXXXXXXXXX.. ", " ..ooooooooooooooo........XXXXXXX.XX.XXXX.. ", " ..oooooooooooooooooo..XXXXX.XXX.XX.XX.XX.. ", " ..ooooooooooooooooo..XXXX.XXX.XX.XX.XX.. ", " ..ooooooooooooooooo..XXX.XX........XXX.. ", " ....................XXX....XXXXXX..X.. ", " ...................XX...XXXXXXXXXXX. ", " ...................X...XXXXXXXXXXX.. ", " ..................X..XXXX.XXXXXX.. ", " .................XXX.XX.XX.XXX.. ", " ................XX.XX.XX.XXX.. ", " ..ooooooooooo..XX.......XX.. ", " ..oooooooooo..X...XXXX.X.. ", " ..ooooooooo..X..XXXXXX.. ", " ...ooooooo..X..XXXX... ", " ....ooooo..XXXXX.... ", " ....ooo..XXX.... ", " ....o..X.... ", " ........ ", " .... ", " "}; fltk-1.4.3/test/pixmaps/green.xpm0000644000175000017500000000324315004135251017075 0ustar albrechtalbrecht/* XPM */ static const char * const green_xpm[] = { "32 32 32 1", " c #000100", ". c #022D01", "+ c #004300", "@ c #007F00", "# c #009400", "$ c #00A301", "% c #00AA00", "& c #00B600", "* c #04BC0A", "= c #00C100", "- c #02C805", "; c #00CC00", "> c #24B329", ", c #00D400", "' c #18CA24", ") c #3FB740", "! c #31C733", "~ c #3FC640", "{ c #31D633", "] c #4FC650", "^ c #5DD45D", "/ c #5BD957", "( c #51DF54", "_ c #6BD16D", ": c #6AE26D", "< c #81DF81", "[ c #8DDB8C", "} c #7EE77F", "| c #79EE7A", "1 c #8FEF8F", "2 c #9DEC9D", "3 c #A6E7A5", " +@$=*&&&*====&&&===$@+ ", " .#;{:123333333333333[:!&#. ", " +-;|22222223222223333333<*=+ ", " .-,11111111221111122223[332!;. ", " #-}1}|}||1|111111}11<<[[[[[<;# ", "+*^}}}}|}||}}<<1||||}1<<[[[[[:;+", "@':^::|||||:___}}|||:|}_<_[_[_'@", "%{^:://///^_^^_^:/|(/::^______~%", "*(/////:^^^^_]]^^/((((:^^^]___]=", "%~~/~(/~]~]]~]]]/((((((//^]]]]^%", "%~!!!!~)))))~]~]~({({{{(~~~]))]$", "&!!!!~~))>))~!~!~!{({{(!~~~))))$", "&!!!*>>>>>>>>!!'{!{{{{{!!~>~)))$", "=-'*>&>%>&!*'--'{-''{-{'!!!%>#>%", "*='*>%$%&&'=-{;-'{-='=---=!&!%!%", "*--=&%%%&=;--;-=-=;=*&!**-=&&&&&", "=-;-=&%&==;;======--*&&&**&&&&&&", "*-;-=&**-,;==&&*==-==*&*=-*&&&%&", "&&=====;;,;=&&&&&*===&===-=*&&$%", "%&**==,,,,;-&%%%%%&&&**-;;;=&%%%", "%&&*-;,,,,,;=%%%$$%&%&*-;;;;=&%%", "&&=-,,,,,,,;=&$$$#%%%%&=-;;;-&&&", "**=-,,,,,,,=*&%$$$$%%%&=-;;;=*&&", "*&*=,,,,,,-=&=&&&%%%%&&*=-;;;===", "$*&*=-{=*===*=-==&&*&&*===;;;;;%", "@*&*==&%%&&*==--======*&*-;,,,;@", "+&&&&=&%$%%&=&*===-;;=&*=;,,,,,+", " #&&&&&%#$%%&%%&*-;;-=*=-,,,,,# ", " .&===&&$$$%$$%&==,;-=*=,,,,,-. ", " +&===&%$%%$$$&=;;;-==-,,,,-+ ", " .#-=&&%%%$$$&=-;=====;,,$. ", " +@$&&&%$$$%==----='&@+ "}; fltk-1.4.3/test/pixmaps/sorceress.xbm0000644000175000017500000001116415004135251017770 0ustar albrechtalbrecht#define sorceress_width 75 #define sorceress_height 75 static unsigned char sorceress_bits[] = { 0xfc, 0x7e, 0x40, 0x20, 0x90, 0x00, 0x07, 0x80, 0x23, 0x00, 0x00, 0xc6, 0xc1, 0x41, 0x98, 0xb8, 0x01, 0x07, 0x66, 0x00, 0x15, 0x9f, 0x03, 0x47, 0x8c, 0xc6, 0xdc, 0x7b, 0xcc, 0x00, 0xb0, 0x71, 0x0e, 0x4d, 0x06, 0x66, 0x73, 0x8e, 0x8f, 0x01, 0x18, 0xc4, 0x39, 0x4b, 0x02, 0x23, 0x0c, 0x04, 0x1e, 0x03, 0x0c, 0x08, 0xc7, 0xef, 0x08, 0x30, 0x06, 0x07, 0x1c, 0x02, 0x06, 0x30, 0x18, 0xae, 0xc8, 0x98, 0x3f, 0x78, 0x20, 0x06, 0x02, 0x20, 0x60, 0xa0, 0xc4, 0x1d, 0xc0, 0xff, 0x41, 0x04, 0xfa, 0x63, 0x80, 0xa1, 0xa4, 0x3d, 0x00, 0x84, 0xbf, 0x04, 0x0f, 0x06, 0xfc, 0xa1, 0x34, 0x6b, 0x01, 0x1c, 0xc9, 0x05, 0x06, 0xc7, 0x06, 0xbe, 0x11, 0x1e, 0x43, 0x30, 0x91, 0x05, 0xc3, 0x61, 0x02, 0x30, 0x1b, 0x30, 0xcc, 0x20, 0x11, 0x00, 0xc1, 0x3c, 0x03, 0x20, 0x0a, 0x00, 0xe8, 0x60, 0x21, 0x00, 0x61, 0x1b, 0xc1, 0x63, 0x08, 0xf0, 0xc6, 0xc7, 0x21, 0x03, 0xf8, 0x08, 0xe1, 0xcf, 0x0a, 0xfc, 0x4d, 0x99, 0x43, 0x07, 0x3c, 0x0c, 0xf1, 0x9f, 0x0b, 0xfc, 0x5b, 0x81, 0x47, 0x02, 0x16, 0x04, 0x31, 0x1c, 0x0b, 0x1f, 0x17, 0x89, 0x4d, 0x06, 0x1a, 0x04, 0x31, 0x38, 0x02, 0x07, 0x56, 0x89, 0x49, 0x04, 0x0b, 0x04, 0xb1, 0x72, 0x82, 0xa1, 0x54, 0x9a, 0x49, 0x04, 0x1d, 0x66, 0x50, 0xe7, 0xc2, 0xf0, 0x54, 0x9a, 0x58, 0x04, 0x0d, 0x62, 0xc1, 0x1f, 0x44, 0xfc, 0x51, 0x90, 0x90, 0x04, 0x86, 0x63, 0xe0, 0x74, 0x04, 0xef, 0x31, 0x1a, 0x91, 0x00, 0x02, 0xe2, 0xc1, 0xfd, 0x84, 0xf9, 0x30, 0x0a, 0x91, 0x00, 0x82, 0xa9, 0xc0, 0xb9, 0x84, 0xf9, 0x31, 0x16, 0x81, 0x00, 0x42, 0xa9, 0xdb, 0x7f, 0x0c, 0xff, 0x1c, 0x16, 0x11, 0x00, 0x02, 0x28, 0x0b, 0x07, 0x08, 0x60, 0x1c, 0x02, 0x91, 0x00, 0x46, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x16, 0x11, 0x02, 0x06, 0x29, 0x04, 0x00, 0x00, 0x00, 0x10, 0x16, 0x91, 0x06, 0xa6, 0x2a, 0x04, 0x00, 0x00, 0x00, 0x18, 0x24, 0x91, 0x04, 0x86, 0x2a, 0x04, 0x00, 0x00, 0x00, 0x18, 0x27, 0x93, 0x04, 0x96, 0x4a, 0x04, 0x00, 0x00, 0x00, 0x04, 0x02, 0x91, 0x04, 0x86, 0x4a, 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x23, 0x93, 0x04, 0x56, 0x88, 0x08, 0x00, 0x00, 0x00, 0x90, 0x21, 0x93, 0x04, 0x52, 0x0a, 0x09, 0x80, 0x01, 0x00, 0xd0, 0x21, 0x95, 0x04, 0x57, 0x0a, 0x0f, 0x80, 0x27, 0x00, 0xd8, 0x20, 0x9d, 0x04, 0x5d, 0x08, 0x1c, 0x80, 0x67, 0x00, 0xe4, 0x01, 0x85, 0x04, 0x79, 0x8a, 0x3f, 0x00, 0x00, 0x00, 0xf4, 0x11, 0x85, 0x06, 0x39, 0x08, 0x7d, 0x00, 0x00, 0x18, 0xb7, 0x10, 0x81, 0x03, 0x29, 0x12, 0xcb, 0x00, 0x7e, 0x30, 0x28, 0x00, 0x85, 0x03, 0x29, 0x10, 0xbe, 0x81, 0xff, 0x27, 0x0c, 0x10, 0x85, 0x03, 0x29, 0x32, 0xfa, 0xc1, 0xff, 0x27, 0x94, 0x11, 0x85, 0x03, 0x28, 0x20, 0x6c, 0xe1, 0xff, 0x07, 0x0c, 0x01, 0x85, 0x01, 0x28, 0x62, 0x5c, 0xe3, 0x8f, 0x03, 0x4e, 0x91, 0x80, 0x05, 0x39, 0x40, 0xf4, 0xc2, 0xff, 0x00, 0x9f, 0x91, 0x84, 0x05, 0x31, 0xc6, 0xe8, 0x07, 0x7f, 0x80, 0xcd, 0x00, 0xc4, 0x04, 0x31, 0x06, 0xc9, 0x0e, 0x00, 0xc0, 0x48, 0x88, 0xe0, 0x04, 0x79, 0x04, 0xdb, 0x12, 0x00, 0x30, 0x0c, 0xc8, 0xe4, 0x04, 0x6d, 0x06, 0xb6, 0x23, 0x00, 0x18, 0x1c, 0xc0, 0x84, 0x04, 0x25, 0x0c, 0xff, 0xc2, 0x00, 0x4e, 0x06, 0xb0, 0x80, 0x04, 0x3f, 0x8a, 0xb3, 0x83, 0xff, 0xc3, 0x03, 0x91, 0x84, 0x04, 0x2e, 0xd8, 0x0f, 0x3f, 0x00, 0x00, 0x5f, 0x83, 0x84, 0x04, 0x2a, 0x70, 0xfd, 0x7f, 0x00, 0x00, 0xc8, 0xc0, 0x84, 0x04, 0x4b, 0xe2, 0x2f, 0x01, 0x00, 0x08, 0x58, 0x60, 0x80, 0x04, 0x5b, 0x82, 0xff, 0x01, 0x00, 0x08, 0xd0, 0xa0, 0x84, 0x04, 0x72, 0x80, 0xe5, 0x00, 0x00, 0x08, 0xd2, 0x20, 0x44, 0x04, 0xca, 0x02, 0xff, 0x00, 0x00, 0x08, 0xde, 0xa0, 0x44, 0x04, 0x82, 0x02, 0x6d, 0x00, 0x00, 0x08, 0xf6, 0xb0, 0x40, 0x02, 0x82, 0x07, 0x3f, 0x00, 0x00, 0x08, 0x44, 0x58, 0x44, 0x02, 0x93, 0x3f, 0x1f, 0x00, 0x00, 0x30, 0x88, 0x4f, 0x44, 0x03, 0x83, 0x23, 0x3e, 0x00, 0x00, 0x00, 0x18, 0x60, 0xe0, 0x07, 0xe3, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x70, 0x70, 0xe4, 0x07, 0xc7, 0x1b, 0xfe, 0x01, 0x00, 0x00, 0xe0, 0x3c, 0xe4, 0x07, 0xc7, 0xe3, 0xfe, 0x1f, 0x00, 0x00, 0xff, 0x1f, 0xfc, 0x07, 0xc7, 0x03, 0xf8, 0x33, 0x00, 0xc0, 0xf0, 0x07, 0xff, 0x07, 0x87, 0x02, 0xfc, 0x43, 0x00, 0x60, 0xf0, 0xff, 0xff, 0x07, 0x8f, 0x06, 0xbe, 0x87, 0x00, 0x30, 0xf8, 0xff, 0xff, 0x07, 0x8f, 0x14, 0x9c, 0x8f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x07, 0x9f, 0x8d, 0x8a, 0x0f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x07, 0xbf, 0x0b, 0x80, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xff, 0x07, 0x7f, 0x3a, 0x80, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0x07, 0xff, 0x20, 0xc0, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0x07, 0xff, 0x01, 0xe0, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x07, 0xff, 0x0f, 0xf8, 0xff, 0x40, 0xe0, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0x40, 0xf0, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0x41, 0xf0, 0xff, 0xff, 0xff, 0x07}; fltk-1.4.3/test/pixmaps/cyan.xpm0000644000175000017500000000324215004135251016726 0ustar albrechtalbrecht/* XPM */ static const char * const cyan_xpm[] = { "32 32 32 1", " c #000100", ". c #143144", "+ c #0A4350", "@ c #038080", "# c #029795", "$ c #00A3A5", "% c #00ABAC", "& c #02B3B5", "* c #00BBBB", "= c #00C0C0", "- c #19B9BB", "; c #33B5B5", "> c #00CCCB", ", c #12C5C5", "' c #47B2B1", ") c #1AC9C9", "! c #09D2D1", "~ c #37C9CA", "{ c #46C5C6", "] c #24D9D8", "^ c #5CC5C3", "/ c #4BD0D1", "( c #55D8DA", "_ c #72D4D3", ": c #53E3E3", "< c #66E0E2", "[ c #7EE2E1", "} c #70ECED", "| c #94E0E1", "1 c #8DEFED", "2 c #A1ECEC", "3 c #ADE8E6", " +@$=*&&&***=*&&&*==$@+ ", " .#>![123333222233323|<~*#. ", " +,]}1211212222212232333||**+ ", " .,]1211111222221112|||||3||>>. ", " #)[11111}}11[11111111[|||||[!# ", "+*<}<<}}1}1}[[[1}1}}1[[___|_|<>+", "@)_[[<}}}}}<[__<<}}}}1[___|^|_)@", "%](((<<<<<__/___[}}}}:[__^_^^_^%", "-(((((((((_{{_{/_(}:}<<<(___^^/*", "&////(/{{{{^/{{^/]:::::(_(/{^{^&", "%{//!/{;';{;{{~{{/]:]:]/~~/{^{;%", "%==,~,*;;;;'*~~~~~/!]]()~{{{;''#", ";>/**;;;&;-;;~,)))//!!]~=---;';$", "*>=*;%;%;--*,)!)!>)!~!))~=~--%;%", ";),=;%%%--))))!))!)))~,)),{--&;%", "=)>**%$%*=)>!>)),,))--*=)=***;**", "*)!>**%&=)!,,,===,,,*;*;==**&*&&", "*,>,=***>!),**-*=,,>=***,=*&*&%&", "*&==**,>>!>=&%&&***=***=>,=*%%%%", "%****>>!!!!>*%%%%%&*&**,>>>==%$$", "%%*==>!]]!!>*%%$$%%%*%=,>>>>>*%%", "%==,!]]]]]!>*&$$##$%%%&*,>>>*=&;", "**=>!]]]]]!>**%$$#%%%%*=,>>>=**&", "***,)!!!!!,****=%%#%%%&*=>>>>==*", "$*&=,),**,=*======***==**,>>>>>%", "@=&-*=&%%&&*==>>======*&=,>]]!!@", "+&&=&*&%$%%*****==,>,=*==!!!]]!+", " #&&=*&$$#$%%%%*=,>>>=*=,!!!!!# ", " .&====%%$%%%$$%=>>>)=*,!]]!!,. ", " +*,==*%#$$%#%*=>!>,=-,!]]!!+ ", " .#,=*%%%%$#$&=,>,,,=,)!]$. ", " +@$&*%%%$$%,,,,,,,,%@+ "}; fltk-1.4.3/test/pixmaps/yellow.xpm0000644000175000017500000000324415004135251017311 0ustar albrechtalbrecht/* XPM */ static const char * const yellow_xpm[] = { "32 32 32 1", " c #000100", ". c #2A4602", "+ c #435B00", "@ c #818600", "# c #969900", "$ c #A3A400", "% c #B0AF00", "& c #B4B425", "* c #BAB800", "= c #BABE02", "- c #B4B73F", "; c #C0C300", "> c #C7C905", ", c #C6C821", "' c #CBCC00", ") c #CAC835", "! c #C9C943", "~ c #D1D201", "{ c #C7C94E", "] c #CACB5D", "^ c #D8D700", "/ c #D9DB3C", "( c #D5D67B", "_ c #DADB6D", ": c #DFDE57", "< c #DFDF64", "[ c #D9DB8A", "} c #EAEB76", "| c #E7E7A1", "1 c #EBEC82", "2 c #EEED91", "3 c #EEEF9C", " +@$;**%**==;=*%*=;;$@+ ", " .#'/<2||||||||||||||[_)*#. ", " +>^}32233||3|333||||||||(*=+ ", " .>'2222222233322223||||||||,'. ", " #,1111111112222212122[[[[[[[^# ", "+*:_111}}}}1_1(111}1111([[[[[_'+", "@,___}}}}}}_____1}}}}}_(((((((,@", "$/<<:<<<<<__](]]<}:}<}__](](](!$", "*:!>'''/,/'),,'>>,)*&&&%", "*>';*&$&*;''',>;;>>'****,*****%%", "*'~'**%%;>~'>,;***''****;;******", "*>'>;***>'^****;'*>>;***;,**%*%%", "%*;*;*''^'~>*%%*****,*;*'>,*%%$%", "%****''^~^~;*%%%%%*****''''>=%%$", "%**>;'^^^^^'*%$$$$%%%**>''''*%%%", "%**>^^^^^^~^*%%$#$$%%%**>'~''=%%", "*;*>'^^^^^~;*%%$$$#$$%**'>~';==*", ";***'^~'^~;;****%%%%%****>'';;*=", "%**;;>;**;;*;;;***%***;*;;'^~~>%", "@***,**%%****>''>;*;*;***>^~^~~@", "+*****%$#%%*****;>>'';***'^~^^~+", " #*****$$#%%%%****'''>*;'^~~~~# ", " .%;*,;%$$$$$$%**~^'>**>~^^^~>. ", " +*>'*%%$%%$$$**>'^';;*~^^~>+ ", " .#';*%$$%$$$*;';>>*>;~~^$. ", " +@#%**%$$$%>*>>>'*>$@+ "}; fltk-1.4.3/test/pixmaps/blast.xpm0000644000175000017500000000324315004135251017102 0ustar albrechtalbrecht/* XPM */ static const char * const blast_xpm[] = { "32 32 32 1", " c #905518", ". c #9F580E", "+ c #A36526", "@ c #AF6519", "# c #BF7429", "$ c #C77622", "% c #B67B3C", "& c #D07518", "* c #D88836", "= c #E48628", "- c #F28514", "; c #FF951C", "> c #FA9835", ", c #FF982A", "' c #F49F48", ") c #FFA82D", "! c #FFA93F", "~ c #FFBA1C", "{ c #FFB936", "] c #FFBA4C", "^ c #FFCA42", "/ c #FFD329", "( c #FFCF5E", "_ c #FFD94C", ": c #FFE946", "< c #FFFB3E", "[ c #FFFB55", "} c #FEFC69", "| c #FFFE82", "1 c #FFFFA3", "2 c #FEFFCB", "3 c #FEFFFC", " % . ....@@@#@@.+.+++% ", " %%++++.....@######@@@@.++ % ", " %%% %++@@.@@@#$$#######@++++%% ", " %%+%+####@@$&&=*=&&$$####@++%%+", "+%+%#####&&&&&==='===*$$###%%%%+", "%+%%%%**=*&&&&>,>,>-=>==*$*##%%%", " %#****'=>---,))!),>>>==***#%#+", " @%*'''>>>>;;,{{{))))>>>''**#%+", " ..@#*'!]]]{)){^__^^{]!!!'''###+", " ..@$=']]((^^~~:::/__^{((!>**##@", "....&&=>(_|[::/<}[<[::_((!>==###", "....&&--!_}|}[<[}[}}}||_]!>>**##", "@@$$&&--;{:|1|[<|}|}||}_^]>>=*##", "##$$=-,;)~~<121<2|121}}:^])>=*$#", "#*'''!]{^_<<<1313332|}}}^{!>>*##", "%*'']((|}}||||<333321|[[_^]>==*#", "*''''((||112333333321|}[_^]!>=*#", "%%*''!]^_[[[}<13332}<[<:_])>>*$#", "##*==,,)~_:<[|212311}[>=&$@@", " .@@$&'!({;;{/}::/~/_^)),>=*$#@+", " ..@$=''>,-;)^__~^{)^]),,==*$#@@", ". @##*'==&--){({));;,{>>==$$#@++", "%++#%**$&&--,!));;;-->>=&$$##@+%", " +%%##@@@@&=>>>>>>=-==='$$#@@+++", " %%+@@..&.$&='==-&&&&&$*$#@@.+% ", " %%+ ....@$$*==&$&&&@$$##@@+ % ", " % ....@#*#$$$#@@@@@##+@++ ", " ..@####@@@@@..+@++% "}; fltk-1.4.3/test/pixmaps/red_bomb.xpm0000644000175000017500000000324615004135251017551 0ustar albrechtalbrecht/* XPM */ static const char * const red_bomb_xpm[] = { "32 32 32 1", " c #000100", ". c #340001", "+ c #3C0100", "@ c #410003", "# c #440000", "$ c #760000", "% c #4E1414", "& c #A60000", "* c #B70000", "= c #5F2928", "- c #C30000", "; c #CE0000", "> c #D90000", ", c #BE1315", "' c #653A3B", ") c #733C3C", "! c #B92223", "~ c #D31A1D", "{ c #744A49", "] c #AE3232", "^ c #CD3B3B", "/ c #875B5B", "( c #C04848", "_ c #9A6E6E", ": c #D35A5A", "< c #C57170", "[ c #DF6D6D", "} c #D97D7D", "| c #ED8181", "1 c #DD8D8C", "2 c #EF9191", "3 c #EAA2A1", " #$&-*****----***---&$# ", " .&;~[2333333333333331[^*&. ", " @*~|23233333333333333333}!*# ", " .-~222222222332223333333331^-. ", " &,|||||||22||222|2|11}111112~& ", "@-:|||||||[||}}|||||||}}1<11}:-#", "$~[[[[[[[[[}_______<}|[}}<<}<},$", "&^:[::[::[>$####@+....+.+.++$;;;-*&*", "**--;>>;####@@+.+...@..#&;;----*", "***-;;;>*##+++@@.+++.@@&--;;;-*-", "&-*-;;-*;*$+#@##+@.@+$&*--;;;;-&", "$*******&*&&$###@@+$&****-;>>>>$", "#*****&&&&&&***------*-*-;;>>>;#", " &*****&&&&*&***---;;-*-;;>;;;& ", " .*-*-*&&&&&&&&&-;;;--*-;>>>;-. ", " #*;--*&&&&&&&*--;;---->;>>;# ", " .&--*&*&&&&&*-;------->>&. ", " #$&***&&&&&--;-----*$@ "}; fltk-1.4.3/test/pixmaps/gray.xpm0000644000175000017500000000324215004135251016736 0ustar albrechtalbrecht/* XPM */ static const char * const gray_xpm[] = { "32 32 32 1", " c #000100", ". c #2C393F", "+ c #394649", "@ c #666967", "# c #737572", "$ c #7A7C79", "% c #828481", "& c #878986", "* c #8C8E8B", "= c #90928F", "- c #939592", "; c #979996", "> c #999B98", ", c #9C9E9A", "' c #9FA19E", ") c #A1A0A4", "! c #A3A5A2", "~ c #A6A8A5", "{ c #A9ABA8", "] c #A9ACAF", "^ c #ABADAA", "/ c #AFB1AE", "( c #B3B5B3", "_ c #B9BBB8", ": c #BABDC0", "< c #C1C3BF", "[ c #C2C3C7", "} c #C7C9C6", "| c #CBCDCB", "1 c #D1D3D0", "2 c #D9DBD8", "3 c #DFE1DE", " +@%;-**=---;-=*=;>>%@+ ", " .$':[2332233333222231[]-#. ", " +)(|33333222333332222221[)-+ ", " .;(22233333121333322|12|1|2]'. ", " #]|221222221112233222[2||||1]$ ", "+)[|[[2[3[3[2[1[[2[222||[[[[|<)+", "@~[[||[111[[|[[|2221[2[|}<<[[|~@", "%:|<[|[[[|[[[:[[[[[21|[[[_:((_]&", "-(::[[[[[:((((]:[[|[||<<[_<:::];", "=((((_(({^]](]]](<[[|[[:(:((]((*", "&]]((()))!')^(^^]([[<<__(]({~)]%", "*~^]])'>-))'){)]^]((:_:]]{)))>)%", "=)~!''>)--);){{]^{{^(((])~~!)==%", ")~)))=**);;)']]{]]]]]]]{~!,)=)-&", "-',-**&*=)>)!{]~~~~!)!))])'>-==*", ")))))&&&=;!~])')))))>)>,'';))-)*", "-'!)=**)=)!)')-;>,''-=*-))**==)&", "),);))*))]);)*--)>)))-==-)=)*&**", "*))-==)'!{!;*&**==---)=)>))*)%&&", "%&==))!)]])))*&&**&)**))!'-))&%%", "**)=)){^{^~)=&&%$%&&**=)))]))**&", "**-)!{]]]]{)))&$%%%*&&*;'''>))**", ")=),]((((]!)*&&%$%$&&*)-))]);*)*", "==*)'!!'!~)*)))&)&&&&&*)>'')))-)", "%)*))))-);)-==)))&)&)*=-))!!))'%", "@=*=--*&&*==));-)=)=)))*->!]^^]@", "+=*=--*%$%&)&-)-))));-=)-){{]]]+", " #)*)*)&%$%&*&&*=;)!))*)){]]{~# ", " .*)*)*&&%&%%%%));]'))*>]{{])). ", " .=))))&%%&%%$&;,!)>-))!]]{~+ ", " .#;=&*)$&%%%)))!');-)'{]$. ", " +@$$)&)%$$&-,))>),;&@+ "}; fltk-1.4.3/test/pixmaps/animated_fluid_gif.h0000644000175000017500000002163715004135251021221 0ustar albrechtalbrecht static const size_t animated_fluid_gif_size = 2545; static const unsigned char animated_fluid_gif[] = {71,73,70,56,57,97,96,0,96,0,132,31,0,0,1,0,3,31,63,46,48,45,0,54,108,78,80, 77,64,123,116,124,126,123,125,173,98,107,166,116,171,204,63,220,233,19,253,254, 0,196,218,42,147,189,83,20,101,159,44,112,135,0,88,172,0,96,191,0,109,220,91, 161,140,68,152,169,38,140,205,0,128,255,15,133,249,45,146,236,47,148,254,108, 182,255,164,166,162,187,222,255,202,204,201,253,255,252,0,0,0,33,255,11,78,69, 84,83,67,65,80,69,50,46,48,3,1,0,0,0,33,249,4,5,10,0,31,0,44,0,0,0,0,96,0,96,0, 0,5,254,224,39,142,100,105,158,104,170,174,108,235,190,112,44,207,116,109,223, 120,110,2,124,239,3,186,160,238,71,36,14,34,61,161,18,86,244,13,32,78,139,5,201, 91,90,87,63,143,118,171,201,112,184,25,11,180,122,45,239,120,219,180,135,147, 241,174,219,223,164,121,46,234,169,211,108,111,87,163,149,211,205,118,119,96,28, 93,95,28,3,100,127,101,129,130,90,95,107,26,93,22,136,138,128,104,120,28,143, 90,124,121,97,80,149,139,151,142,109,164,111,134,153,99,160,87,140,155,145,153, 142,142,113,137,170,66,172,130,108,90,112,126,180,65,182,119,93,163,26,136,64, 188,181,162,183,112,111,25,169,197,189,199,119,121,143,108,204,205,57,190,120, 25,124,91,28,187,213,54,215,120,119,221,222,52,224,141,125,179,228,229,207,231, 105,227,234,49,230,231,239,240,47,242,141,244,245,45,247,130,249,250,88,236,218, 161,35,246,47,222,179,78,110,196,165,43,184,239,24,194,100,106,252,49,60,193, 232,33,41,77,3,39,50,17,101,17,226,22,137,26,73,84,36,69,50,225,199,133,33,254, 81,140,44,233,49,99,74,22,172,186,148,212,230,14,229,203,18,172,44,98,116,121, 51,133,47,66,26,118,158,36,216,147,98,64,129,32,95,242,83,72,180,40,206,163, 237,124,56,61,3,245,156,128,164,19,125,16,16,40,104,131,212,169,31,180,114,109, 100,224,171,83,31,99,149,37,236,64,192,236,77,31,27,198,178,204,48,180,105,72, 177,92,59,62,242,138,213,155,15,1,105,231,182,217,210,182,111,51,31,29,2,11,78, 83,216,38,60,196,105,61,8,166,91,211,49,57,31,6,34,171,37,185,147,175,229,195, 61,0,107,222,108,146,177,219,199,61,226,142,134,228,202,234,105,191,169,87,107, 246,108,23,52,15,213,178,35,211,86,135,55,183,230,198,181,85,193,245,189,250, 234,103,58,195,183,93,36,126,174,195,235,74,189,37,179,100,78,246,249,159,208, 216,88,10,165,238,1,56,45,200,91,38,115,23,100,60,120,168,219,106,196,143,103, 106,126,73,244,92,139,215,171,41,107,184,134,143,0,24,34,233,143,116,161,191, 255,11,251,5,40,224,128,4,6,24,128,117,198,0,254,16,128,4,82,52,232,224,131,16, 70,40,225,132,16,74,128,224,16,61,68,64,225,134,28,118,8,33,21,199,217,215,195, 0,30,150,104,226,132,99,132,56,67,15,1,104,248,32,6,48,62,120,193,137,52,98, 192,160,20,7,214,215,16,15,46,54,136,65,3,12,36,160,0,2,20,76,128,0,144,61,122, 120,65,3,9,84,112,227,139,8,28,144,0,3,10,56,41,133,4,57,182,183,98,15,16,60,88, 129,2,11,20,48,193,2,11,8,73,38,3,17,60,217,33,2,103,166,9,33,6,19,48,64,166,2, 110,74,145,162,150,27,241,64,226,131,114,162,201,166,2,14,200,185,64,3,117,118, 120,193,1,115,66,160,166,131,9,144,153,64,161,98,92,104,15,139,139,82,64,38,2, 16,68,48,1,5,16,128,25,38,164,28,126,57,36,168,82,92,32,40,166,139,102,137,39, 76,25,202,40,232,3,105,74,32,65,5,115,58,32,43,141,18,144,42,5,173,11,0,10,42, 150,58,62,197,67,151,47,38,170,225,140,108,150,169,40,174,183,74,152,172,2,138, 46,58,133,164,42,254,68,225,96,5,19,52,112,38,2,19,220,216,232,2,168,74,128,65, 145,7,80,192,32,156,155,58,152,65,5,69,54,43,5,5,9,36,48,193,183,13,44,27,225, 48,42,10,11,192,158,14,206,235,169,2,65,106,136,129,167,176,86,32,40,153,182, 90,128,232,160,26,82,224,233,160,79,98,208,232,144,7,23,96,111,132,170,202,224, 131,180,22,152,74,166,197,178,74,96,105,175,209,122,188,0,154,12,10,58,65,154, 23,12,76,230,202,231,202,233,235,152,189,218,202,177,20,17,100,105,144,158,18, 186,188,128,3,246,46,92,47,131,38,31,160,40,175,63,187,233,51,172,82,124,91,64, 154,52,51,144,233,134,22,246,101,109,132,35,51,96,179,20,130,62,205,32,175,10, 192,122,65,178,82,19,157,245,212,52,39,144,169,4,218,46,96,244,205,14,226,187, 234,125,20,38,171,246,141,24,144,249,243,178,81,71,43,232,219,82,180,253,54,6, 42,47,75,176,174,16,234,204,42,15,27,126,139,64,157,125,223,40,184,162,35,47,0, 235,141,93,67,109,172,5,35,67,235,238,134,254,146,250,144,100,132,135,75,78,38, 224,25,148,254,45,180,46,130,237,128,134,223,222,205,182,163,203,194,237,224, 157,62,177,184,97,222,100,70,219,177,167,94,115,158,168,4,19,120,58,180,20,125, 71,112,129,167,143,139,203,252,197,29,202,109,20,15,11,110,120,118,235,181,62, 112,128,5,52,215,27,168,227,16,32,192,224,228,13,60,160,55,200,109,91,94,0,5,38, 2,59,142,238,28,78,126,35,205,128,54,57,187,219,129,82,208,117,3,221,90,0,252, 1,7,144,128,167,140,118,36,48,133,13,101,237,59,141,15,136,213,184,143,65,78, 111,10,40,128,172,210,55,36,1,206,233,81,12,122,24,6,41,152,0,243,205,233,1,159, 235,16,238,234,48,162,14,185,204,115,13,50,216,201,130,247,165,147,193,12,81,10, 120,27,131,254,212,128,215,137,75,91,10,168,87,4,26,197,128,203,209,104,18,82, 185,218,134,120,165,67,7,229,42,86,13,58,34,18,143,232,174,92,133,236,74,76,12, 89,4,88,246,67,11,232,140,82,20,194,128,147,46,64,51,31,62,232,86,79,122,148, 226,141,158,104,196,207,49,72,2,51,234,216,25,171,104,129,170,253,32,0,27,146, 147,248,26,37,59,54,218,241,142,86,36,2,28,41,68,166,6,208,202,87,182,195,163, 32,39,164,42,234,109,8,1,10,152,82,15,17,55,200,70,74,168,144,10,226,144,3,40, 96,195,16,58,242,146,247,210,99,135,66,22,72,76,98,18,146,0,128,158,39,71,121, 34,9,224,238,141,1,72,165,42,87,201,202,86,186,242,149,176,140,165,44,103,201, 202,31,144,176,9,184,204,165,46,119,201,203,94,246,82,36,190,12,166,48,135,73, 76,34,76,175,152,200,76,102,49,75,16,2,0,33,249,4,5,10,0,31,0,44,30,0,4,0,38,0, 57,0,0,5,254,224,39,142,31,96,158,104,170,2,100,235,174,112,236,206,174,103, 223,56,158,210,60,205,113,185,91,111,152,201,136,56,25,100,50,232,25,246,126,71, 227,143,233,57,57,121,72,13,105,169,51,93,105,154,204,141,243,225,222,172,95, 151,70,227,209,126,128,65,116,186,85,92,127,168,115,44,156,218,204,147,236,111, 100,83,113,94,126,128,69,101,98,132,44,115,124,124,114,126,45,123,57,145,88,102, 56,149,60,110,153,156,157,158,159,160,161,162,149,142,120,145,165,76,164,168, 148,167,171,152,173,174,54,170,177,125,126,180,178,176,177,179,76,28,107,26,100, 163,34,97,69,69,192,162,74,196,197,163,201,201,155,160,204,196,206,159,208,117, 163,195,204,198,160,200,209,66,161,189,35,147,184,78,183,169,227,228,229,78,189, 191,231,226,62,208,225,186,154,208,108,231,150,212,240,174,238,247,236,181,36, 219,201,217,60,253,35,22,80,224,187,96,111,0,130,226,199,176,161,67,90,219,128, 61,196,49,144,204,68,27,3,139,93,244,144,49,137,175,143,32,67,138,244,149,225, 130,201,147,38,3,51,132,0,0,33,249,4,5,10,0,31,0,44,34,0,7,0,34,0,54,0,0,5,202, 224,39,138,94,105,158,168,57,174,236,154,190,104,43,143,112,237,205,179,13,227, 178,254,242,45,95,10,200,18,198,136,52,163,10,73,82,150,152,77,39,116,74,141,42, 167,206,39,52,123,171,122,191,224,176,120,76,46,155,207,232,244,151,195,230,156, 57,154,140,60,227,94,107,52,245,185,190,62,229,232,229,113,127,114,85,129,130, 134,83,1,126,130,23,134,25,136,138,127,140,135,80,137,141,134,124,76,144,127, 112,43,28,90,80,154,114,158,30,109,163,93,125,123,58,72,92,75,64,172,39,106,177, 76,175,63,69,175,112,119,152,46,172,133,162,61,92,161,190,182,89,141,26,65,92, 197,199,196,134,198,195,78,189,115,186,31,172,193,205,100,112,209,68,144,120, 102,208,116,180,90,193,25,26,224,93,222,114,229,34,231,25,233,31,25,23,240,241, 240,119,244,245,246,247,244,33,0,33,249,4,5,10,0,31,0,44,36,0,13,0,26,0,48,0,0, 5,196,224,39,138,156,102,114,99,170,174,100,230,186,26,43,143,220,107,163,243, 26,104,182,157,235,188,158,235,167,218,9,135,196,84,77,24,75,166,130,55,167, 106,153,209,224,164,88,44,103,123,205,150,162,217,207,177,155,164,246,178,208, 51,54,237,211,30,51,225,177,103,78,247,252,190,175,79,189,46,219,115,57,123, 124,44,129,132,123,125,133,136,42,0,139,136,137,41,139,0,141,30,93,100,31,144, 141,102,46,28,1,131,133,98,71,14,157,132,153,47,26,156,41,152,111,149,57,164, 154,104,76,97,164,171,101,39,78,84,86,97,31,108,25,128,146,83,71,26,146,118,79, 111,194,42,187,46,198,196,71,202,52,114,190,191,54,193,205,74,38,86,194,216,217, 218,219,136,102,171,194,178,43,146,173,188,42,227,170,199,214,234,214,25,23,238, 239,238,112,41,33,0,33,249,4,5,10,0,31,0,44,38,0,5,0,21,0,56,0,0,5,232,224,39, 142,80,52,158,104,202,101,25,151,190,98,166,105,172,11,167,44,171,125,156,125, 139,171,26,173,245,27,245,56,195,93,17,185,11,250,96,131,97,203,89,20,205,106, 181,170,199,99,67,102,127,219,174,231,11,3,132,129,231,159,57,204,217,186,223, 111,145,185,7,175,199,81,109,207,76,249,91,105,182,82,79,48,109,121,71,85,64,68, 135,39,52,127,112,76,26,130,136,132,133,57,58,47,121,34,92,149,57,28,1,153,118, 122,155,57,3,159,118,82,155,164,31,160,161,162,25,169,171,65,155,26,175,171,167, 53,158,170,171,154,58,79,186,160,138,192,193,194,39,190,118,55,73,160,0,0,120, 162,121,111,2,56,173,117,27,203,70,173,45,117,204,173,206,110,218,205,198,39, 215,191,39,177,156,197,110,73,96,231,235,117,71,189,190,167,124,240,162,74,186, 229,149,46,246,215,249,176,251,185,160,247,56,85,177,37,67,81,188,17,231,220,17, 99,199,176,225,186,61,16,35,74,220,19,2,0,59}; fltk-1.4.3/test/pixmaps/white_checker_king.png0000644000175000017500000001657415004135251021604 0ustar albrechtalbrechtPNG  IHDRppK pHYs""S@tEXtSoftwarewww.inkscape.org<tEXtTitleCheckers) ,&tEXtAuthorGreg Ercolano, Matthias MelchercNtEXtCreation TimeJan 28 2022㫄bIDATx]kp\}I+zX/˲EإGkfL 131dR&4~h)M[02@461%`AX ٖd^iv{={v={?st9s57؆/$dy5+]HHVwp-[2`2yʢ#9&Y__jeu$I !K!5ȴR:G)eʔ(,FFGGGex`+_e(;[&}3!TE4wu?N X JW@ֻ==u UMbpWmv4 TJ [S {G\7$Tʏ`0422r;xtxx82r"Vԑ@,Gq߿a%%z۶mQUա0ߐA71Ta:|$E IUāرcaQLa;"RٳW^Ao2Zrolll]mmω{Pr:~[nYHs#H9Sxh7"f WUU"w:}tMCQ0yZ2|>4ڭnx @$SH-… +ޗ$΋P" E(PUn^n$-poy`֭{"$Ӎ%ԩS+W|b_X,qb||H$p\$)on7؈6۷AYEh=Zbt rVXQJ166ӧOcppTJ+1qKA$A,g}˅:ttt>뮻N:عsgEu/]V9]'Bt*N8^ΚS8sA[[*|r4H$|7~:`&S^E:Y؛(xFS. ---, G 7d2 ! ,fٟAeill|%xUUu"sv$ DSSS$ t=]MMMKWX!8/rr)n(8tLe9FMߝ/92Kt=E4}LV s)r`kk68<~8~Y|9*J+RM6E9.d2]hYfk=6'TUG-#Hō'#-G"2sO4T|{r1Ũ 9 8ɓ+N:yB)MBSC$R 4 T A4tM+>@3 )[ZZntRQJ)lcc*OrSb\'kicy= 1Yz79"%p\*kT* 7.{=AND=߁>=WJxc˖-YjUrǸHQs',"ɀ6 )vR'jݔ|U&)|OyTSqHI3/7xc;`UBY̼ǎ[LUU [@oA=$bp9_\}aC' 듈~;ƹ;(L[c6lhB*V3hH'BqRyM,;RP"~5\.)y )%Xt{w4|{r\<UͶoٱT*%ȥD4pt'k/XXzs|D%li&x Jb2phw=r8ږ 3f*Vc˖-Fd\ 1WM:vZ.o+@!5$TF"|f(&.0d'YVt`mm%)cR3L83b\.#j T2y$r'h)N~v!K k֬YR3o^"I Y(+4;A GGF@HX;"r| =Q%Q][dbox*ӇGnjM-i7윫z5)銐>Q⹏Q* x`@QR ǁ2ylQ2X9O=\fIAf?]O=%emk8o DJ'_ !cX.*wU oȤIq^OBSWK%hv Bܗ}5?S(JYU}8,\)AllZ ~ tq[8#NVsu_ja@Bh>dNݾd=/vu`"B&?QЍ RcFZi9щ#ZŊҹ9 fEEyV(!xD BכnN5hhZcٖ@hYҨ݆|>=0eҵpym2;77( ##O)ېls15MHy,#b`Sf@>aͶKFT(1hq ,e3gTUEf)D@Α"~$v l\<]VTVC"DʔL5 OxI7kB\hhZkyE"(i緧N <5* Nvg OoihllFh;Bj͍Һ%.%QJ199i8VCЃ'kSP @ﴡDb`P%:888dULt ~_QNjEs1( #O4!7}I֡9Ԑu`C:99y`?t຺:$t{ߠY]}GH]^lm lOnϥKtvt,ZOO4A:qaj׮]|{ !,!hjj!F(!h&(u~@ YѣGCXq r ED:?H=cn@,splq`~cwC7m">3.(UU|cRM-]x<^raOO˗q.\;+KmP9k5Ν{-.@lLq,9Tg? )'C&LdJ\j,1l93dLEh?$ˍEEExsHNdy:33c& ARLMMa``###CF׾K~7\db4"`bl333ܼyIJ]WU5 b9 d2)\x`P뤇E vEnA~- f2@3bO8]f5\-ڢcd2t]e333tfffi:?22/9i^2!׋ϴI|1*ر[e˖AŏPc(J)(:vgW=v(e,#Ac|0T~dm&mp8l¡lB49rooV xXNϗ]/~?LNN21(#'6gr-,s=$\؈G''_OXwNϗ]sssz$T{<1wQX\6J):iӦڋőpX}/ƐaLl-pa =QC)%wk=W_}u^7bNNNʏ? M y `kb߿SYnzBaBq8?22߹s@!XaV' ?+Y 7nV-V}}}=x<>hm*c|dV'?^p@ی^RJ:4o^e1pgEԁ.ٳg,2?yF]dBFFے.@ } ]vEEEET*E{{{} gϞ C?`w4@>\V"QJ~1Y* ވ\'N49(q E8!EtJU*}(E*x}ɯd")TDV@Vl"x|;wW(,vf?$u$w (4 F\>q8wOg4lP|' ׅycE`idy@[U(HفcTNwbv: fd'%)1k*_hhA"@]-W (-xFZaDU8.7BB(04~F[5B#0Sqπ3 +nrJV+]BυQ#r?NglnE]IpˌhTb1E Oy16(*N;#qXH4. xZldH1"f@-:xZ$ufT8ߋ>O6|#{l(r5IENDB`fltk-1.4.3/test/pixmaps/green_bomb.xpm0000644000175000017500000000325015004135251020072 0ustar albrechtalbrecht/* XPM */ static const char * const green_bomb_xpm[] = { "32 32 32 1", " c #000100", ". c #003700", "+ c #003E00", "@ c #004405", "# c #004600", "$ c #005E00", "% c #1B541B", "& c #006E00", "* c #2C602D", "= c #008B00", "- c #3E6D3F", "; c #358335", "> c #00A800", ", c #4E7B4E", "' c #00B700", ") c #00C100", "! c #5E895F", "~ c #00CD00", "{ c #32B12E", "] c #40AA3D", "^ c #00D800", "/ c #28C42B", "( c #6D9A6E", "_ c #41C442", ": c #5CCB5D", "< c #58DA59", "[ c #7EC678", "} c #73D173", "| c #73E773", "1 c #83EB84", "2 c #93EB92", "3 c #A0E7A0", " @&>)'''''))))''')))>&# ", " .=~~|2333333333333332|/'=. ", " +~^1222233333323333333332''@ ", " .)~212122123222222333333333/). ", " =~12111111121211112222[3[322~= ", "@)<1|11|||||121111||1112}[[[}|~@", "=/|||||||||}[!((((([}|}1}}}[}})=", ">/<:<|<|<|(!!!(!((((((::|}1}}}_>", ")<<<<<<<:!!!!!!!!!!!!(!}<:<::}:)", "'_//", "'/////]-, --------*--;*--]_{_]]>", "'/////;.---.--***********;_{{{]>", ")~))>{**.-.*.%%%*%%*%****%//{{>>", "'))/>>..%.*%%%%%#%%%%%%%%%'/'/>'", ")~))'{...+++@@##%###@@@@#@)'/'/>", ")~~~)'.@@@@@@@@@@@#%#@@@@@''>'''", "))~))'++@@##+++@@#+#@+.+@+'''''>", ">)))')@####+.++++++++++@@@)''>>>", "'>')))&###@#+.....+++@+@#&~)'>>>", ">''))~>#####+........++@#>^~)'>>", "'')~~^^&####++......+.++&)~~~'''", "'))~~^^)$###@+.......+++>~~~))''", "'/')~^^)>#@+++++......#=~)~~~)))", ">''))))')>$++@@@#++++$>'))~~~~)>", "='''))''>')=&#+#+@+&>)'')~~^^^^=", "+'''''>>>>''))')))~)))'''~~^^~~#", " ='''''>=>>>>>'')~~~~)))~~^~~^= ", " .>)))''>=>>>>>'')~~~'))~^^^~~. ", " @))))'>>>>>=>>)~~~))))^^^~~+ ", " .=~)'>>>>>>>')~~~))))~^^>. ", " #&>'''>>=>>)~))))))>=@ "}; fltk-1.4.3/test/pixmaps/magenta.xpm0000644000175000017500000000324515004135251017413 0ustar albrechtalbrecht/* XPM */ static const char * const magenta_xpm[] = { "32 32 32 1", " c #000100", ". c #380F3F", "+ c #490754", "@ c #890089", "# c #9E02A1", "$ c #A800A6", "% c #AF00B1", "& c #B900B6", "* c #B902BE", "= c #C200C3", "- c #CC00C8", "; c #D100D2", "> c #DE00DB", ", c #CC18CC", "' c #C324C3", ") c #BC33BC", "! c #D629D5", "~ c #B93DB9", "{ c #D23BD2", "] c #D34BD2", "^ c #CF53D0", "/ c #CE5ECE", "( c #E551E4", "_ c #E366E3", ": c #D473D4", "< c #DD6DDD", "[ c #EB7BEC", "} c #E683E5", "| c #DD8BDD", "1 c #F18FF2", "2 c #F09BF0", "3 c #E7A2E8", " +@#=*&%&*====&%&===$@+ ", " .@=!_233333333333333|/{*@. ", " +;>[22223333332233333333|'=+ ", " .=!12111112222122233333333|{-. ", " @,}}}}1[1[[1}21111}1|||||3||;# ", "+=_<[[[[[[[[}:}[[[[[}}}|||||:<=+", "@=<<<_<[__[<<:::[[_[_[<::::|::'@", "${_/______>;;;=%$$#$$%%%*=;;;-=%%%", "&&=,-;>>;>;-=%%###$$%%&==--;=&%%", "&&*;->>>>>;=&%%$#$$$$$%==;,--=&&", "=*&=;;;;;;-&**&&%$$$$%&&-=;;=&==", "$*%*===*&===&===***&****==;;;-;$", "@&&&*=%$%%*&=---==&===*&&=-;>;;@", "+*&&&&&$#$%&**&=&;=-==**=;;;>;;+", " @****%$##$%%$&&==;;-=&=-;>;;;@ ", " .%&==*%$#$$$#$%&=;;-=&=;;>;-;. ", " +====&$$$$$$$&----=*==;>;>;+ ", " .#==&%$$%##$%=;;-====;;;#. ", " +@#%*%$$##%*===-=-&$@+ "}; fltk-1.4.3/test/pixmaps/black_checker_king.png0000644000175000017500000001623215004135251021527 0ustar albrechtalbrechtPNG  IHDRppK pHYs""S@tEXtSoftwarewww.inkscape.org<tEXtTitleCheckers) ,&tEXtAuthorGreg Ercolano, Matthias MelchercNtEXtCreation TimeJan 28 2022㫄bIDATxmy3zw{7$Y' F$cKm*b;ġ\䫿IUJBJU W`C`,t^tBinoofwgaw{zgvwfwT非ݝ>O?OO|tyuz%Lѯ\s+f[7qU"/$ @;x`lmmH5|y;?ږv}oEzho<!p!ӌ!)0\眃s^djYe4gklXt KKKZ%'$H65[4?;!_$| ^8`A~4M|^X,믿f PM\9Vl1S=x<{o8L2X^^{RLذ,j*^C7E6 ܑ#G !_kJ\~faaϝ; T ft'N^Ao{؀OK$/qT]9TJd2w@ ?H$^;U&X,t:=yڵ3hB+U%,'|3X?cS۴^Ǯ]Zlt[$ G4M{sc;TV麾7J]fOvԇD"9 1 ( X]]E.J* cu\}0P<$=d4}sAMD&2VVVP(`Q4$ "Ncll Xl8<<|̌qg+. rQmlliA, +++{md [ y%A똝ŻヒbRcR._qܹXlH'''P(\j2jm . wy?zߠzR ɠZ"LRWmrѪy  @L%9^~ZfK/… }&~eRj5x_2DhX\78h(dB3Ns~] }]D5eLNNBӴiĻJEo>ܚڕ)wGsҏf^~e={E[ON4MiDD 6TZ$$}׮]j_V*p),//ZXx"B`&! i)㌱\Z*&[nysh<y :rx*N>{ 'CVvTbcL D? $]whT*+a cc|S=QpcsZ}jRH۔nAuU*:u!i͟pch_rY" F HHKuH{&!{'^yF n?6x֛GO$]A N$Jijhh8p@Ip4xN>ž;*Ga,ڄhDۻ)pHq1B` oA,7y<о=q.WxB dOfG wDѽ ĤZ詁?nbw1_?HKIOp"H 6"EO8Єv0-B_T* ιK{!|(]>9XLı}]ׯۄ&BPpο _G)m9 qoH`,HOf@, ͨ<)Ui٢> |xu{(iHbbG-@햡b||'3 8dF)-D N;{@v^T~&ptt4'*qΡ4lIvP 4oOJ]Fn]c ~ac$'ދbJmOE7'/I>avѻcvQ&Dr !Rؽ5SF@ac9.]mF''o wP4W[W/ 4M@Sbh“d-ub{i3 , !܆9p_nx`o@#A)IwqF`Ժ3RNަ Rr@EeB͜yBȡ^b_X^ nwC_߉HDR 1 ;ƚ1.k:ޙI;8 q p GmF]1!wz7P]ȫbj܅xv4nq88!7K@' ^(׼bB/X^&%$B|]j*DN̡0D* 8 qFKo?3]yQC7݀f r68O1r]v0PVuΏI]5ad8 @7F0 UEH'x@)M4 OѥbYְpeb1Tp~ᒭV9iy^}Lxi 7,5PPn;ʄA!n-,gjHmQvpkb;Y a>)Bj PnTٱ  B2(wvS *y!2dPQwhԄBd3)>!r_eE†a&Ņ8iOkXVOHӥ P]S~}B`q[B- s+9sRl -"+kᴏRѓ5,2uPeфL&9異!0uūg[W3Dh s7(5yk eÄ1P:/O䕮7W>M|1CP&>@0757sKU' 5frq @rO&s.TC_E e5x9 +Y2k}|3rpzxI)XSSj!cLtBC&~ ZXF144 ^C ?4[A4+X/χ,+`{l| \ZZvX9dhxR\Y b>\+z1vXTԩT'z@[ .z =)8/^qCcWp>) %iƂRG @zu@P={uީcx^{Tv;'E?[[[4M?(8ٙCX UA W6^ oFOZSD^N!z~rr|vOo6{Wtb@P'ȞKZ@쭷/˲zsht:T,ku uí}u4P5בV*0bGPldda@5Z mmv:Eͼd!x!>V c, Q #\B ˗/Ӂ@$(895n+klIK$pFy ¥|z־_sssƒeYkhj05ػ$4Ѫ}-m\X.]ZjbFc LBӺsBmqX%߸;5", oii j81qX' O@utp |333_F\U4N0ēvh ZR(Z1*~4 ΊZq,pux.A쥩=aM(9QS5󋃙]$y/Pzȏ)K#քɲ,pn[ /---ɓ(ż 0Ki @ @Nޮ@t P%Z.{ozz+Fz12D4FUO~+g?C^YqƄeeຓ ue5JB4M$l"p&V*躎X,ܼ~bg}ovMSh_Qwym& (ƈ&&&hvpjYRaH$D6q' < VWW`^-$k߆@}$Ok|c; +89Mpyl:ŗt1.\Qx<>C֌ p[Տ2,`W'vϾ^hp1V+5Mҽs6WלˢvPn2ugDema,jNyi#})cˌ%44y 9M?x^?v-aL-o@,˨T*ck=bxN3res{&$] zzYCJ/a, ڝ4ͬa9J!$X2939hQ! Szb؄ e>N( 7kRVp˔4!$YjY"< wx :ᨨ6O}@+;,^BKXqare]jMӼGB9/1Ʈ9)9GG R&]dj/4D?A~#(y9}ѓ3O'o8D>iڴs!}61Vd8kܞhѬ\yTi EO KhSH/O/Z'"8Gu8!dT]MBR!BH4<92 yفN'*^8,|&TN%4(ΊJ$oH?* q|?IENDB`fltk-1.4.3/test/pixmaps/porsche1.xpm0000644000175000017500000001071115004135251017517 0ustar albrechtalbrecht/* XPM */ static const char * const porsche[] = { /* width height ncolors chars_per_pixel */ "64 64 4 1", /* colormap */ " c #background", ". c #000000", "X c #ffd100", "o c #FF0000", /* pixels */ " ................................................ ", " ................................................ ", " ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.. ", " ..XXXXXXXXXXXXXXXXXXXXXXX.......X..XXXXXXXXXXX.. ", " ..XXXXXXXXXXXXXXXXXXXXXXX.......X..XXXXXXXXXXX.. ", " ..XXXXXX...XXX..XX..XXXXX..XXXXXX..XXXXXXXXXXX.. ", " ..XXXXXX...XXX..XX..XXXXX..XXXXXX..XXXXXXXXXXX.. ", " ..XXXXXXX..XXXXXXX....XXX.....XXX..XXXXXXXXXXX.. ", " ..XXXXXXX..XXX..XX.....XX.....XXX..XXXXXXXXXXX.. ", " ..XXXXXXX..XXX..XX..X..XX..XXXXXX..XXXXXXXXXXX.. ", " ..XXXXXX....XX..XX.....XX..XXXXXX......XXXXXXX.. ", " ..XXXXXX....XX..XX....XXX..XXXXXX......XXXXXXX.. ", " ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.. ", " ................................................ ", " ..XXXXXXXXXXXXXXXXXXXXX......................... ", " ..XXXXXX.XXX.XXX..XXXXX......................... ", " ..XXXXX.XXX.XXX.XXXX.XX......................... ", " ..XXXX..XX..X.......XXX......................... ", " ..XXX........XXXXXX..XX..ooooooooooooooooooooo.. ", " ..XX....XXXXXXXXXXXXXXX..ooooooooooooooooooooo.. ", " ..X...XXXXXXXXXXXXXXXXX..ooooooooooooooooooooo.. ", " ..XXXXXXXXXX.XX.XXXXXXX..ooooooooooooooooooooo.. ", " ..XXXXX.XXX.XX.XXXXXXXX..ooooooooooooooooooooo.. ", " ..XXXX.XXX.XX.XX................................ ", " ..XXXX.X.........XXXXXXXXXXXXXX................. ", " ..XXX....XXXXXXX................................ ", " ..XX...XXXXXXXXX.XXXXXXXXXXXXXX................. ", " ..X...XXXXXXXXXX.XXX...XXXXXXXX................. ", " ..XXXXXXXXX.XX.X.XX.....XXXXXXX................. ", " ..XXXXX.XX.XX.XX.XX.X...XXXXX.X.oooooooooooooo.. ", " ..XXXX.XX.XX.XX..XXXX...XXXX..X.oooooooooooooo.. ", " ..XXX..X.......X.XXXX...XXXX..X.oooooooooooooo.. ", " ..XX.....XXXXXX..XXX.....XXX.XX.oooooooooooooo.. ", " ..X...XXXXXXXXXX.X...........XX.oooooooooooooo.. ", " ..XXXXXXXXXXXXXX.X.X.........XX.oooooooooooooo.. ", " .................X.X.XXXX....XX................. ", " .................XXX.XXXXX.X.XX.XXXXXXXXXXXXXX.. ", " .................XXXXXXXX..X..X.XXX.XX.XXXXXXX.. ", " ................XXXXXXXX.XX.XX.XX.XX.XXX.XXX.. ", " ................XXXXXXX.XX.XXX.X.XX.XXX.XXXX.. ", " .................XXXXXXXXXXXX.X..........XXX.. ", " ..oooooooooooooo.XXXXXXXXXX....XXXXXXXX..X.. ", " ..ooooooooooooooo.XXXXXXXX....XXXXXXXXXXXX.. ", " ..ooooooooooooooo........XXXXXXX.XX.XXXX.. ", " ..oooooooooooooooooo..XXXXX.XXX.XX.XX.XX.. ", " ..ooooooooooooooooo..XXXX.XXX.XX.XX.XX.. ", " ..ooooooooooooooooo..XXX..X........XXX.. ", " ....................XXX....XXXXXX..X.. ", " ...................XX...XXXXXXXXXXX. ", " ...................X...XXXXXXXXXXX.. ", " ..................XXXXXXXXXXXXXX.. ", " .................XXX.X.X.XXXXX.. ", " ................XX.X.X.XX.XX.. ", " ..ooooooooooo..XX.......XX.. ", " ..oooooooooo..X...XXXX.X.. ", " ..ooooooooo..X..XXXXXX.. ", " ...ooooooo..XXXXXXX... ", " ....ooooo..XXXXX.... ", " ....ooo..XXX.... ", " ....o..X.... ", " ........ ", " .... ", " .. ", " " } ; fltk-1.4.3/test/pixmaps/block.xcf_gz0000644000175000017500000000553115004135251017545 0ustar albrechtalbrechty\SW ZAj+k{jA($Fd!!{"X7삵کNk(tNEy/A|=w~|$%J.Aq5W<cΣ!B f8ud+$&ON9bd 8 -ҸLWOt.wXϢ|2Y)`\W,0r="6P09\GδGuVyLfLe]ɡhٻ" {,㘈Eu\Rۘy,؛m8X-L {ybkY[inJ??$"|Q(6ڣn?/w.KAW^e_oy۷½g?__?⥿}g/ŕ+W! ?yرOυaLi؆b M#Q [&?o?$a]&}߸q=IΝ?c3OMƝGI2oL IΠ.sIIߕU5 74465o ;H Рl4E eMB@-@}GFh{%dmxKk__B$!8Tv$ḬX޴з%+@{/*~׀I}?9oB8з ۤ9I};b{ ڏP(Vk4 07ga3PaSG{܁(u88:H`qQ.a*B5 HBEF1pĈƨĵWXb,n7鮞~k̔{W'w,޻n~ߚgK| MM)d\fbF ƀKREuS[N*Qյ6TufD_^`3+rj}Ӛ-IlF nXe~e3.=XS\Y2#$!q BZC[{7t\MeƪMyѓ'+3;{;R"l JT hw7E%'OU f+"$'ARPU Mb^J"+?W%I4j 7!>239:mB+(TbH#fG0=mM)vD򢺺aK̯kV# 1%UMYq߱]߮=׬ U+ DYhg硖TvsF \LT J"=08ЕTj3e\_`g(lO ( MuUi$B΋ O* uFLM7;w7cI2+LYj]qe6UlN7 k7DƄGsey5 bEZo(M|^Rej@4&@L OԖ7T33rߺ 48Hō ~ ;Pӡ~ {8#ZQgket7)O~JSRUOf.L 'sSu09 B=D"(@I)hO3B%#z" (l15m&s-DDbI|5daYXM=>Kt8mB5zH1 CF%hL(ೆsl\gCG=%y&"ʄ%D0g>!q`)1Yfltk-1.4.3/test/pixmaps/red.xpm0000644000175000017500000000324115004135251016545 0ustar albrechtalbrecht/* XPM */ static const char * const red_xpm[] = { "32 32 32 1", " c #000100", ". c #2D0001", "+ c #440000", "@ c #850000", "# c #A20000", "$ c #AC0001", "% c #B70000", "& c #C30000", "* c #D10000", "= c #AB1111", "- c #BF0C10", "; c #DD0000", "> c #CD191B", ", c #BB2222", "' c #B53A39", ") c #CF2F30", "! c #C33738", "~ c #C34746", "{ c #E14548", "] c #D44D4C", "^ c #CC5554", "/ c #E25858", "( c #DB6161", "_ c #D16867", ": c #E96A6B", "< c #E27373", "[ c #DA7D7E", "} c #EE8283", "| c #DD8D8C", "1 c #EF9191", "2 c #F09D9B", "3 c #E9A3A2", " +@#&%%%%%&&&&%%%&&&#@+ ", " .#*):1333333333333332(!$#. ", " +&><22223333332333333333[,%+ ", " .&)11111111122111233333333|)*. ", " #>}}1}}}}1}}|111}}}||[||||||># ", "+%/<<<}}:}<}}[<[}}}}}}[[[|||[(&+", "@)_<<<:<::<<_<<<<:::<<<[[[[[[[)@", "#)(((/(:::(_____<:::::(____[__!#", "%{^](//^^(^^^_^^((///:/(^^_^__^&", "%~]]]]]~~~^~^~^^~///{/]^^^~^_^^%", "$!!!!!]'~'~~~~~~~{{{{{{{~]~~'^^#", "%!){)!''''''!!!!!!!){){!!'~''''#", "%,),,,!!,',!,)))))))))))!!!''''#", "&>-,,====,=,,>>>>>>)>>>)),,,@''#", "%>--=====-->>>>>>>>>>)->>-),,==%", "&&&-$==#--&**&&&&&&&---%-------$", "&**&&%$%&&*&&&&-&&>&%%-%&&%$$--%", "%&*&&%%&&**&&-%%%&*&&%%&%&&%%%$$", "%%&&&%&&***&%$%%%%&&%%%&&&&%%$$$", "$%%%&&**;**&%$$$$$%%%%&***&&%$##", "$%%&&**;****&$$###$%%$%&&***&%%$", "%%&&**;;;;**%%#####$$%%%**&*&%$%", "%&&&*;*;*;*&%%$####$#$%%&***&&%%", "&%%&******&&%%%%$###$%%&&&&*&&&&", "#&%&&&&&&&&&&&&&&%%%%&%&&&***&&$", "@%%$&&$$$$%%&&&&&&&&%%&%%****;*@", "+%%%%&$###$%&%&&&&&**%%&%&*;*;*+", " @%$&%%###$$$%$%%&**&&&%**;**&# ", " .&%%&&$#######%&&***%&&**;**&. ", " +&*&&%$##$##$%&&**&&%&*;*;*+ ", " .#&&%%%#$###%&&&&&&&&*;*#. ", " +@#$$%%###$&&*&&&&&#@+ "}; fltk-1.4.3/test/pixmaps/gray_bomb.xpm0000644000175000017500000000324715004135251017742 0ustar albrechtalbrecht/* XPM */ static const char * const gray_bomb_xpm[] = { "32 32 32 1", " c #000100", ". c #2C2E2B", "+ c #313330", "@ c #2E393E", "# c #363835", "$ c #3B3A3D", "% c #3B3D3B", "& c #3B464A", "* c #454644", "= c #48464A", "- c #50514F", "; c #585A57", "> c #616260", ", c #686967", "' c #70716E", ") c #787A78", "! c #818380", "~ c #868885", "{ c #8B8D8A", "] c #8F908D", "^ c #939491", "/ c #969895", "( c #9B9D9A", "_ c #A1A3A0", ": c #A8AAA7", "< c #B0B3B0", "[ c #B9BBB8", "} c #C1C2C0", "| c #C9CBC8", "1 c #D2D3D1", "2 c #D9DBD8", "3 c #DFE1DE", " &,!/^]]]^////]]]/((!,& ", " @)_<12322232333322221}:^'@ ", " &(<133333313233332222221}_/& ", " @/}221233322113333221111111<_@ ", " )_1112223321212223212111}1}1<) ", "&^}1111111111}1111221111}}}}1}_&", ",:}}}111111<:]~]^^^<}11}}}}}}}:,", "]<}}}}}}}}]~))~)~~]~]^}}}}}<<}<~", "/}<}}}}}_)))))))))~)~)~<}}}<<<<^", "]<<<<}<_,',,'''))))))))):<}<<<<]", "]<<<<<<,>>>,,,>>>,,),,,,)<<<_::~", "]_::<_~>->->->>>>>>>,,,,>^__:^/)", "^___((,====-=-->=>>=>=>>=)_(^(^!", "^:_(^^=-=-=-=-==-==>-----=__/^^]", "^_((^~$$*%=*==-=--======-=_(^(^]", "^__(]].+$$$%%*$$$$$*$@*%%=((^^^]", "/_:_^]@.+$$$+$++$$+$$$$$+$^^^^]]", "^___^^..$##++..$++$+....$$^]^]]]", "]^^(^($+$$$$.....++$.$.@$.(^]]~~", "~]^^//>+$++.$@.@.@......$>_(]]!~", "]]^(__~@$$$$......$.$@$+$)<_^]~~", "]^((_<<;##$.$..........$=__:(^]]", "^^((:<<^&#$$...........$~____^^]", "^^^((___!$+.$.@.....@.$)(___(((^", "~^^^__(^^~=$..$.@....=)^/_:::_:~", ">^^^/^^]]]])=@.$..$=)^^^^(_<:<:,", "&]]^^]]))~~^^]]]^/__:(^^(__::::&", " )^]^^]]))~~]]]^^(_:_^(^_:<:::) ", " @^^(^^]~~])~)~]((___^/(:<_<_(@ ", " &^__(]])~]~)~^^_:__(^(_:<:_& ", " @)((]]]~~)~)^(__(((((_:<)@ ", " &,)]]]]])!]^(__(_((~>& "}; fltk-1.4.3/test/pixmaps/sudoku.xbm0000644000175000017500000000157315004135251017275 0ustar albrechtalbrecht#define sudoku_width 32 #define sudoku_height 32 static unsigned char sudoku_bits[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x0c, 0x30, 0xc0, 0x63, 0xcc, 0x33, 0xcf, 0x63, 0x4c, 0x33, 0xcc, 0x63, 0x4c, 0x33, 0xcc, 0x63, 0xcc, 0x33, 0xcc, 0x63, 0x0c, 0x33, 0xcc, 0x63, 0x0c, 0x33, 0xcc, 0x03, 0x0c, 0x30, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x0c, 0x30, 0xc0, 0xd3, 0xcc, 0x33, 0xcf, 0xd3, 0xcc, 0x30, 0xcc, 0xd3, 0xcc, 0x33, 0xce, 0xf3, 0xcc, 0x32, 0xce, 0xc3, 0xcc, 0x32, 0xcc, 0xc3, 0xcc, 0x33, 0xcf, 0x03, 0x0c, 0x30, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x0c, 0x30, 0xc0, 0xf3, 0xcc, 0x33, 0xcf, 0x83, 0x4c, 0x33, 0xc1, 0xf3, 0xcc, 0x33, 0xcf, 0x33, 0x4c, 0x33, 0xcc, 0x33, 0x4c, 0x33, 0xcc, 0xf3, 0xcc, 0x33, 0xcf, 0x03, 0x0c, 0x30, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; fltk-1.4.3/test/pixmaps/blue_bomb.xpm0000644000175000017500000000324715004135251017727 0ustar albrechtalbrecht/* XPM */ static const char * const blue_bomb_xpm[] = { "32 32 32 1", " c #000100", ". c #010047", "+ c #00033E", "@ c #010345", "# c #010577", "$ c #0000A4", "% c #0001B7", "& c #0000C3", "* c #0000D0", "= c #13252E", "- c #1A2147", "; c #1E1E57", "> c #2023BC", ", c #2526CD", "' c #343364", ") c #363699", "! c #3237C5", "~ c #373BB4", "{ c #474875", "] c #4E4FD4", "^ c #5252C6", "/ c #5B5A85", "( c #6D6D94", "_ c #6666CE", ": c #6465DE", "< c #6E6CAC", "[ c #7B7CDA", "} c #7C7DEB", "| c #8D8DDF", "1 c #8F90EF", "2 c #9D9EED", "3 c #A6A6E8", " -#$&%%%%%&&&&%%%&&&$#- ", " =$*,:133333333333333|}>%$= ", " -&,}22122222322233333333[>%- ", " =&,}111111|2|21111|22322332,&= ", " $,[1}1}1}}1}1111111[1|||<|||&$ ", "-%]}}}}}}}}}[[[}}}}}}[[[||||1:&-", "#,:_}:::}::[<((((((<[}}[[[[<[[,#", "%!:::::::_<(((((((((/<_:___[__]$", "&]]]]]]]://///(////////_^::___]%", "%]]]]]]^{{{/{{/{/{)''-{''''''''''''{')]~~~~$", "%,>,!>)-'-'-''''''';''''')!!~~~$", "&,,$>>--;;-;;;;;;;;;);;;;->>>#!$", "&&&,$$;+;+;+;@;;.;;;;;;;;;%>,>>%", "%&&&$$++@+..@...;..@.@;@.;%,$%$%", "&&*&&%+++..@@@@@@@@@+@++@+%%%%%%", "&&&&%%+@+.@@+++@++@@@++++@&%%%$%", "%&&&&&+....+++++@+@+@+@@@@&%%%$$", "$%%&%&#.@..@+++++++++++@@#&&%$$$", "$%%%&*$....@+++++++++++@.$*&&%%$", "%%&&***#...@+++-++++++++#***&%%%", "&%&&***&...@+++++++++++@$&**&%%%", "&%%&****$.@@+++++++++++$&&*&&&&&", "$%%&&&&%&$#+@@+++++++#$%&&****&$", "#%%%%&%%$%$$#@.@@@+#$%%%%&*****#", "-%%%%%%$$$$%%%&%%&&&&%%&&&*****-", " $%%%&$$$$$$%$$%&&**&&%&******$ ", " =%%&&&$$$$$$$$%&&***%%&*****&= ", " -&&&&%$$$$$$$%%***&&&&****&- ", " =$&%%%$%$$$$%&&&&&&&&***$= ", " -#$%%%%$$$%%&&&&&&&%#- "}; fltk-1.4.3/test/pixmaps/yellow_bomb.xpm0000644000175000017500000000325115004135251020306 0ustar albrechtalbrecht/* XPM */ static const char * const yellow_bomb_xpm[] = { "32 32 32 1", " c #000100", ". c #393900", "+ c #2A4602", "@ c #434101", "# c #474900", "$ c #435B00", "% c #515116", "& c #5B5C20", "* c #676800", "= c #666635", "- c #7C7B50", "; c #848323", "> c #838442", ", c #8E9200", "' c #8A8A5F", ") c #A6A600", "! c #9A9B6D", "~ c #B2B102", "{ c #AFB132", "] c #BAB900", "^ c #C1C300", "/ c #C6C42C", "( c #CFD000", "_ c #C7C84F", ": c #CBCA40", "< c #CCCC67", "[ c #D7D984", "} c #E0E167", "| c #E0E07A", "1 c #E6E6A0", "2 c #EEEE88", "3 c #EDED97", " $,)]]]~]]]]^]]~]]^^),$ ", " +,(/}2111111111111113'>--_}_____]", "~::/:/_>=-=--=--=--=---->____<<)", "~:///:;=============>===={:{{{{)", "]^///:>%=.=.========&====>{:{{{,", "^^^]~{.=.==.=%%%&&&&&=&&&%/~{{{~", "]^^/))....=.%%=%%%%&%%%%%%/~~~~~", "^^^^/{.=...%@@@@%#%@%@%%%%]/~/~~", "^((^]~...%%@@@@.@@@@@@.@@@]]]~]]", "]^((]/..@@@%..@@@@@@@.@.@@]~~]~~", "~]]^]]@%@#@@...@@@@@@.@@@@^]~))~", ")~]]^^;@##@#@........@@@#;^^]~))", "~~]]^()#@##@@......@..@@@)((^]~)", "~]^^(((*####@..........@*(((^~~]", "]]^^(((^##@@@..........@)^^(^]]]", "/]]((((()##@..........@)(((((^]]", ")]~]((^^])*@@@@.....@*,]]^^((((~", ",]]]]]]~~~~,*@@#@@@*,]]]^^((((^,", "$~~]/]~)))~]]]]]^^(((^]]^(((((($", " ,]~]~~),))~~~~]]^((^^]]((((((, ", " +]]^^^])))))))~^^(((]]^((((((+ ", " $^^^]~)))))))]^(((^^](((((($ ", " +,(^]~)~))))~]^^^^^/^((({+ ", " $,,~]~)),)~^^(^(^^^/,$ "}; fltk-1.4.3/test/pixmaps/tile.xpm0000644000175000017500000002474015004135251016737 0ustar albrechtalbrecht/* XPM */ static const char * const tile_xpm[] = { "100 100 17 1", " c None", ". c #DCDCDC", "+ c #D9D9D9", "@ c #E4E4E4", "# c #DFDFDF", "$ c #CECECE", "% c #D2D2D2", "& c #C8C8C8", "* c #CACACA", "= c #C4C4C4", "- c #BEBEBE", "; c #D4D4D4", "> c #E8E8E8", ", c #D6D6D6", "' c #C6C6C6", ") c #B2B2B2", "! c #E2E2E2", ".+@.##$%%$$$&*=..%$*%-;*>,%$%#>,$,%%*%*.#*%++$;+,,.&&=-%%+.$,#,=;%#,@.+,%>,+=-++@@#%$.++#,--;.=*+,,>", "%%.&$@.#,*%*&'%%&$;,*%%,&%;%,#..;$$%';+.+,++.%.;+@@@$'.;'..;@.+$%)&!!,.!>+%@%-*%@>#.+&&+.+$%,++$$#++", ",.$&$+#+.%++$%,=$;$&'+.%%&-+++;%;;$%+%+;.#.+@!!..>#+$%;,$.+@,+.%-%%-%>#+.#+$%...%,!>>;$$$.%$+#+*++&*", ",$;;;..-*!;*.+%=*%;*%%=&$+$++,-%;+++++++++++#@@@>@#,++;$%;++#.+++%&*=#.+;%>@+,...++$>@#&%*%;.$=$##=;", "%#$,+$$%,.++.%%,'*%;,$=-$+@,%*$+%.#+%,.++%;.,#@@@>#+*,$%;,++..@#.,+@+.#.+%#+!.,%#>%,,+>#.%$!#%=%$$#+", "+*'%$)&,+,+,+*%,,$,+,*-&++$%%*%#@#%$;+.%,!.+;+!@+>..,%$,$;..#,@.$;%.##.#!#;;++#.+%!.,%,.@##>%,>%$,+,", ",,$$$%%%';+$%,$!,$,;;,..,&)%%+#!+..,++%%++#+#@+,##,;,%.%.+++.#;%+.,+#.,#+;#%.@,+#.+,#!,+.>#..,,++++.", ";=-;##%=$%,.$%%+;%%%$+.%&%%%,.,%++..+++;%;;.+#.+%..%;+,#+$%.;,....+.++.+,$$.#>.$+@&+#;.@@.%!@.#+@!,%", "-$$&+%.,#;;&$$,*$+%%.#*='$,,+.;,+,##...$%++%.,++%,..+;%,%,,%+,.,##.+%%+@,'%#.++,,,%++.>++.>#+#>>.%,%", ",!.;$$$#.;%'-'&*+++.$=*%;,++;;;.+;++,+++@@%++++..$..+%+&$.+*;,++.+;+*%+#+++...+;.%+##@.%@>#.!>#&%+=$", "...#%%,,;=-%$=%%@+.;==;=+#+%+*$#.%+%+@.++!,%,;;%..,,*,+'+,;;#.$%#%+%,.%&+#.$+@!%;,+##++#@!!#@@&%@..+", "+$=%%$#,$--$=$%+#,=%%,%;$;%.+.,,+!++#..++%;.%%$..,#;.+$#%$$#;.%;+..+,.%,%+,..@++..*+#,+.#>@#.+++!.+.", "..+'=;%$,+,%$*&%&=-;+#+%==..;,#,#.###@+$%,,$$;+@#.,;.*;.+&.#%*.>.,.#$'+.%%,,%##++;+,#*.@>#%%#@+%$@@.", "..;+.$%=$,##,,'=&$$%%++$$%,,;$;.,##.+#;++;#+;+.>..#$$%,%;,%+=$+#.!...+%,%++%;&+#$%.%#@,;+#.,#,+.+%;,", "%;+@++*$%%$+@,*&$$*&;%%.#,.$$,++#@@#.,+%.;%#+!#.,!#..'%;%+;%*%;+,!@..#,;.%%,+&,*$.,%@>!+;,###&;;#.;%", "$$;+.,.;%=$$$,+%+$,&$%,,.+=$%.,;##!#.#$%.+%,+.@.,#%*#%$$;+*.+,$%%@.+@..+,$%++$&%#+,.#,#@#.&$$++,+.,,", ",%+.+$.;&;%+,$,+,+%%**$+*$+,%+%,$%.%;@+%##;;;;#+##%*$%'*&++.;.+;.#+;#>++,+*%%%++,,.#;=@@.+,;$&;%;%$-", "%'.+,'*;;;#+;&$#$$,%*,$=%,+,,%%$%%%+%!@++#;++&+.,.;,&$-%,;,++%..#+;++$+#,++,=%%+++!#++..+;;,%,%=&+..", "%,;+%&$$+#%%++%;$&&%%%'%,,+++%,%;*.+%%>..+,+##+%+;=.&&,%$#.%;%!@,+,%,,+++.+.*%%;$.%+#!+&,;,;+,%+$=,$", "%#.&%,-;+$+.,++$*$%&=$,,;#,.,&;&.,+%++;%.+%,+!#.;%%&*,,%.$,;&#!.%%%%++,.%,;+,%.#.$;++;%;++#,$=.++,$=", ";%;%$,$%=%#.@,,$*%*=%;%%+%$.%&'+%$#.=,++&;$>#*..+,%+$+;,,#.;.@,%.+,+;,#++,$$+++.++,+#%%$%##.,++*$+;.", "$+%$;.,*$#+%.!..,%=*$&$;;%$%$+,$$%%%'++,+,.@#+.,$.,!;#;$,#,#++,%.%.,.+;.$%.,++%%$+,#%,+,$,.%.%$+.$,;", "-%@#..%$+;%+;,%.+,$$'$*+%%;,%$$%%+;;,&'%#.##...$#.!$'#>+&,+#,+$*+.;+#,%%;,.!+,+$$%+.+++*+..+,+%,#+.=", ";%;###+@!;+$$;,$.+.%$$%.%.$*%&&,.,,;+;$&$+.+..$+#+$%.!.%$%%+#*;;&,#++%,,+,;#++$$%++,%,%%++!.+@.;*#,*", "*%%+@%+#,...,$;,'$++,;#&,,&'=&'*+++.%$-=$$%!..#,%%++>+=#%;+,++,++.%..+$;.+,+$%%+,.;&,#+,*.++##@;%,%-", "%$%#,.++$+#+%%+$'%&.,;#+$&$&&%-;,$.!+=*&=*.#;#.,%,@@$;#.*%..,+,#@..+,$%@,,.&%$;,%%$%,+%+%+&,@.##.+**", "%*..+%.;+#,+.$$,;*$$%+;+%%$,%'%;%*%.;%+$=,%*$++,+>+'..,$%;!%$##@+#..$%.%;,,%$%%;==..$%%,+,++$;@.&+>#", "%@@%'+$+.%.#.=&,%%%$';%&%$+.%&.%**+=$+#%.%%';%*$>.&=..%$$*...+,.;.#%.#+.@$%%.,$-&,,,%;*#%;#$,+;#+#@.", "!@.;=,.;$@.;+.$''%%=.;=;+%*,..;=&%=$+,&,+%,+;%$;,.&!.+%$+#,+,#.;.,%,.,.>!$$;;%;%,,$*%;%+#;;+#%#>!+,.", "##+-..+,+...+%+;$&&,*&,%,;%%%*+,%*,%%%%=-.+;##%,$$,!+!+%!,%%+#,%+;+.+;.%%;$$=+%+;,;'$,;++++..>>#%%##", "#+%@@;++.++%,;+.%*%-$%%;%.@%*$%.,+;%++'%&;&.>%@++%$%.,%+%$###.+*+#.,%++'#%$%&$%*%$;%+.+,##++!.+#!!.%", ".-%##!@.%%$%;..;,+%$&%&%++.;+,+%%+;%;.++#$$@;#$.#%.=*$#,*+%$%+..+;;%++;;+!;$'%+'=%;;.##+.++.#+#.#.,.", "#@!#+#@.%+%$,++,,;;,+%*&%;+%%$=#+&$+**+#,+@..#.'$,#;,*,+!%%,%.#;%$%$&;,%%,.$%.%-$;;!@$%%..+.##!+,$.$", "..@>#@++;+;%%++..%;+!+%$;.;+'-%$+%,,=%.$+!+#@+%$>*-,%+..$=%%#.-=*%++$;%&%%&$.;%'%%.+%;.&,+#!!#+*;$*&", ">@%+.;%%#+$+*$++$;*.+%%%+,+%*&$&,+;',@=%+$#.%*..&''&.+#.;$&$;%&&.$=&$,$%=*+.&&,.+.+;,.;;%.#.++,+''&.", "!+..$&+%$;.,++%,%%%,#,+.%+%$&,$*.+&.+$+%$.@&&+#%-=,,#;%%.#.$&%&+.%=','*$++.%%%.+.+%;++%,,#+,*.;%..@@", "$;+%,.&=-;++@..$$,%+!!%%.%$;$;;==%#.$$$$##;++#+$=$...;%*+%+.,%%$&$*%$==,#$&$$+,++,%;%++;%+%-$++.+!@%", ".%;++.-*$%%;+.+$+;..++...,;*+%;%%.!$;+,++%+.+%;.;,,.;+%$,&&.#%&'-&%,=-,+%&&,+#+;;+,.+#+++,'%.;.##+$#", "...#%%%*=%+$+,+....+,+.;!++;$$%,.+,+$,++#+#>+.$++.$#++$%%$%+*&+,%=%==+%'=%%+.,.&%%+%#.%%,%%%.;++%%;&", "%+.+%+*+&;$%$$.+.!#;#+%=&#@,;$..%#;++=$,.#!#+..+#,,%$&&+;;,,$-+#;+-=$$&$%++,,$$%%+%.%$,*$%%+$%;=$,*%", ".%;!.$$%#,+=$$%,!#@#;;+.%*=+#.,,.+%+.$+++%%,%.#>.;+$;$&++%'$,++.+%+,,=$'+++,*%,;+*;,%$,%+&*%++&-;%$$", "%++;+.%+$$%%$$%,+#.%.@.%;$++*>#+,;.&$@.!#='&@+@@..*$,%%+%$%$%#;+,;#%%$;+,+%$%$%++&%&;;%;$&$*&;;%;,$%", "%+=$#+,%&''++,.+$#.!+%%+;*%.!++*%+.',.%;!;.#.;#@+%%$;..%-%%*,;+,,%$$$.!+'$%%%$;+%%+.+++*+;$%;%,%;,;$", "*$$,,;;$$$$++#.$+%.@%;..%+.;#+&,.+*.;..$&,!.;+;..*%;,%%+%*'*&%!.'*$%$$'..++%,;$%%++;&+,%%%$%,,..++&&", "'&$,,+*%+%%..+;#.+#$%+.+.,+;%$.%+*$++,.%++#@#$'$.!%%;$-%%+$$-%+$,.+;&)'%;.!#,%%%++,%$%';,$%%.+%,#+&+", "'%,%*$%%%,,..;;..,+.+,%+,+,,*,#+&%%#.#.!.;@!%%...%.&=$+&&%,%#%*,;*;*=&'$;+.##,,+.$+,*-'%%+,;.;$'%%,,", ".+,$--&$,+$&..#+%,%,$!+%++,+.%+%%$+%!#!##+++*$,@!#%-$+'%.$-+%%%&%$-**=&$%%.;%+#.;$%.$;+%,%,;;%;*$%;=", ",;&===*;%*,=,#+##%).*%>#%+$#,*=.+%$+.$#.$+@%;*%+#..#+=+@#&$-*,..'-*;-$$;$=';,++#@%%$+@+%%%$$,+&&+;$#", ";'=$+$;;)%=,%+..%+#,,%&$+#,.;$$.,+#;#+,$%##;;;%&+;#$&+.$;%%-&;.;&;-;$$=$*-$,.,;;.#!.,.,$%,,,%&*;%;..", "*)=)&%.#'-&,+%%#;;+>.$,+.*%#+!,,&,@;,,,.@=%&';,+.,;+.>.;&%=+*,+&,%;*;%%'-$++%.%,.%%+&$;%%,%.%=.=*%%*", ".&&=-%%+.$,#,=;%#,@.+,%>,+=-++@@#%$.++#,--;.=*+,,>.+@.##$%%$$$&*=..%$*%-;*>,%$%#>,$,%%*%*.#*%++$;+,,", "@@$'.;'..;@.+$%)&!!,.!>+%@%-*%@>#.+&&+.+$%,++$$#++%%.&$@.#,*%*&'%%&$;,*%%,&%;%,#..;$$%';+.+,++.%.;+@", "#+$%;,$.+@,+.%-%%-%>#+.#+$%...%,!>>;$$$.%$+#+*++&*,.$&$+#+.%++$%,=$;$&'+.%%&-+++;%;;$%+%+;.#.+@!!..>", "#,++;$%;++#.+++%&*=#.+;%>@+,...++$>@#&%*%;.$=$##=;,$;;;..-*!;*.+%=*%;*%%=&$+$++,-%;+++++++++++#@@@>@", "#+*,$%;,++..@#.,+@+.#.+%#+!.,%#>%,,+>#.%$!#%=%$$#+%#$,+$$%,.++.%%,'*%;,$=-$+@,%*$+%.#+%,.++%;.,#@@@>", "..,%$,$;..#,@.$;%.##.#!#;;++#.+%!.,%,.@##>%,>%$,+,+*'%$)&,+,+,+*%,,$,+,*-&++$%%*%#@#%$;+.%,!.+;+!@+>", ",;,%.%.+++.#;%+.,+#.,#+;#%.@,+#.+,#!,+.>#..,,++++.,,$$$%%%';+$%,$!,$,;;,..,&)%%+#!+..,++%%++#+#@+,##", ".%;+,#+$%.;,....+.++.+,$$.#>.$+@&+#;.@@.%!@.#+@!,%;=-;##%=$%,.$%%+;%%%$+.%&%%%,.,%++..+++;%;;.+#.+%.", "..+;%,%,,%+,.,##.+%%+@,'%#.++,,,%++.>++.>#+#>>.%,%-$$&+%.,#;;&$$,*$+%%.#*='$,,+.;,+,##...$%++%.,++%,", "..+%+&$.+*;,++.+;+*%+#+++...+;.%+##@.%@>#.!>#&%+=$,!.;$$$#.;%'-'&*+++.$=*%;,++;;;.+;++,+++@@%++++..$", ",,*,+'+,;;#.$%#%+%,.%&+#.$+@!%;,+##++#@!!#@@&%@..+...#%%,,;=-%$=%%@+.;==;=+#+%+*$#.%+%+@.++!,%,;;%..", "#;.+$#%$$#;.%;+..+,.%,%+,..@++..*+#,+.#>@#.+++!.+.+$=%%$#,$--$=$%+#,=%%,%;$;%.+.,,+!++#..++%;.%%$..,", ",;.*;.+&.#%*.>.,.#$'+.%%,,%##++;+,#*.@>#%%#@+%$@@...+'=;%$,+,%$*&%&=-;+#+%==..;,#,#.###@+$%,,$$;+@#.", "#$$%,%;,%+=$+#.!...+%,%++%;&+#$%.%#@,;+#.,#,+.+%;,..;+.$%=$,##,,'=&$$%%++$$%,,;$;.,##.+#;++;#+;+.>..", "#..'%;%+;%*%;+,!@..#,;.%%,+&,*$.,%@>!+;,###&;;#.;%%;+@++*$%%$+@,*&$$*&;%%.#,.$$,++#@@#.,+%.;%#+!#.,!", "%*#%$$;+*.+,$%%@.+@..+,$%++$&%#+,.#,#@#.&$$++,+.,,$$;+.,.;%=$$$,+%+$,&$%,,.+=$%.,;##!#.#$%.+%,+.@.,#", "%*$%'*&++.;.+;.#+;#>++,+*%%%++,,.#;=@@.+,;$&;%;%$-,%+.+$.;&;%+,$,+,+%%**$+*$+,%+%,$%.%;@+%##;;;;#+##", ";,&$-%,;,++%..#+;++$+#,++,=%%+++!#++..+;;,%,%=&+..%'.+,'*;;;#+;&$#$$,%*,$=%,+,,%%$%%%+%!@++#;++&+.,.", "=.&&,%$#.%;%!@,+,%,,+++.+.*%%;$.%+#!+&,;,;+,%+$=,$%,;+%&$$+#%%++%;$&&%%%'%,,+++%,%;*.+%%>..+,+##+%+;", "%&*,,%.$,;&#!.%%%%++,.%,;+,%.#.$;++;%;++#,$=.++,$=%#.&%,-;+$+.,++$*$%&=$,,;#,.,&;&.,+%++;%.+%,+!#.;%", "%+$+;,,#.;.@,%.+,+;,#++,$$+++.++,+#%%$%##.,++*$+;.;%;%$,$%=%#.@,,$*%*=%;%%+%$.%&'+%$#.=,++&;$>#*..+,", ",!;#;$,#,#++,%.%.,.+;.$%.,++%%$+,#%,+,$,.%.%$+.$,;$+%$;.,*$#+%.!..,%=*$&$;;%$%$+,$$%%%'++,+,.@#+.,$.", "!$'#>+&,+#,+$*+.;+#,%%;,.!+,+$$%+.+++*+..+,+%,#+.=-%@#..%$+;%+;,%.+,$$'$*+%%;,%$$%%+;;,&'%#.##...$#.", "$%.!.%$%%+#*;;&,#++%,,+,;#++$$%++,%,%%++!.+@.;*#,*;%;###+@!;+$$;,$.+.%$$%.%.$*%&&,.,,;+;$&$+.+..$+#+", "++>+=#%;+,++,++.%..+$;.+,+$%%+,.;&,#+,*.++##@;%,%-*%%+@%+#,...,$;,'$++,;#&,,&'=&'*+++.%$-=$$%!..#,%%", "@@$;#.*%..,+,#@..+,$%@,,.&%$;,%%$%,+%+%+&,@.##.+**%$%#,.++$+#+%%+$'%&.,;#+$&$&&%-;,$.!+=*&=*.#;#.,%,", "+'..,$%;!%$##@+#..$%.%;,,%$%%;==..$%%,+,++$;@.&+>#%*..+%.;+#,+.$$,;*$$%+;+%%$,%'%;%*%.;%+$=,%*$++,+>", "&=..%$$*...+,.;.#%.#+.@$%%.,$-&,,,%;*#%;#$,+;#+#@.%@@%'+$+.%.#.=&,%%%$';%&%$+.%&.%**+=$+#%.%%';%*$>.", "&!.+%$+#,+,#.;.,%,.,.>!$$;;%;%,,$*%;%+#;;+#%#>!+,.!@.;=,.;$@.;+.$''%%=.;=;+%*,..;=&%=$+,&,+%,+;%$;,.", ",!+!+%!,%%+#,%+;+.+;.%%;$$=+%+;,;'$,;++++..>>#%%####+-..+,+...+%+;$&&,*&,%,;%%%*+,%*,%%%%=-.+;##%,$$", "$%.,%+%$###.+*+#.,%++'#%$%&$%*%$;%+.+,##++!.+#!!.%#+%@@;++.++%,;+.%*%-$%%;%.@%*$%.,+;%++'%&;&.>%@++%", ".=*$#,*+%$%+..+;;%++;;+!;$'%+'=%;;.##+.++.#+#.#.,..-%##!@.%%$%;..;,+%$&%&%++.;+,+%%+;%;.++#$$@;#$.#%", "#;,*,+!%%,%.#;%$%$&;,%%,.$%.%-$;;!@$%%..+.##!+,$.$#@!#+#@.%+%$,++,,;;,+%*&%;+%%$=#+&$+**+#,+@..#.'$,", "-,%+..$=%%#.-=*%++$;%&%%&$.;%'%%.+%;.&,+#!!#+*;$*&..@>#@++;+;%%++..%;+!+%$;.;+'-%$+%,,=%.$+!+#@+%$>*", "'&.+#.;$&$;%&&.$=&$,$%=*+.&&,.+.+;,.;;%.#.++,+''&.>@%+.;%%#+$+*$++$;*.+%%%+,+%*&$&,+;',@=%+$#.%*..&'", ",,#;%%.#.$&%&+.%=','*$++.%%%.+.+%;++%,,#+,*.;%..@@!+..$&+%$;.,++%,%%%,#,+.%+%$&,$*.+&.+$+%$.@&&+#%-=", "...;%*+%+.,%%$&$*%$==,#$&$$+,++,%;%++;%+%-$++.+!@%$;+%,.&=-;++@..$$,%+!!%%.%$;$;;==%#.$$$$##;++#+$=$", ",.;+%$,&&.#%&'-&%,=-,+%&&,+#+;;+,.+#+++,'%.;.##+$#.%;++.-*$%%;+.+$+;..++...,;*+%;%%.!$;+,++%+.+%;.;,", "$#++$%%$%+*&+,%=%==+%'=%%+.,.&%%+%#.%%,%%%.;++%%;&...#%%%*=%+$+,+....+,+.;!++;$$%,.+,+$,++#+#>+.$++.", ",%$&&+;;,,$-+#;+-=$$&$%++,,$$%%+%.%$,*$%%+$%;=$,*%%+.+%+*+&;$%$$.+.!#;#+%=&#@,;$..%#;++=$,.#!#+..+#,", "+$;$&++%'$,++.+%+,,=$'+++,*%,;+*;,%$,%+&*%++&-;%$$.%;!.$$%#,+=$$%,!#@#;;+.%*=+#.,,.+%+.$+++%%,%.#>.;", "*$,%%+%$%$%#;+,;#%%$;+,+%$%$%++&%&;;%;$&$*&;;%;,$%%++;+.%+$$%%$$%,+#.%.@.%;$++*>#+,;.&$@.!#='&@+@@..", "%$;..%-%%*,;+,,%$$$.!+'$%%%$;+%%+.+++*+;$%;%,%;,;$%+=$#+,%&''++,.+$#.!+%%+;*%.!++*%+.',.%;!;.#.;#@+%", "%;,%%+%*'*&%!.'*$%$$'..++%,;$%%++;&+,%%%$%,,..++&&*$$,,;;$$$$++#.$+%.@%;..%+.;#+&,.+*.;..$&,!.;+;..*", "%%;$-%%+$$-%+$,.+;&)'%;.!#,%%%++,%$%';,$%%.+%,#+&+'&$,,+*%+%%..+;#.+#$%+.+.,+;%$.%+*$++,.%++#@#$'$.!", ".&=$+&&%,%#%*,;*;*=&'$;+.##,,+.$+,*-'%%+,;.;$'%%,,'%,%*$%%%,,..;;..,+.+,%+,+,,*,#+&%%#.#.!.;@!%%...%", "%-$+'%.$-+%%%&%$-**=&$%%.;%+#.;$%.$;+%,%,;;%;*$%;=.+,$--&$,+$&..#+%,%,$!+%++,+.%+%%$+%!#!##+++*$,@!#", ".#+=+@#&$-*,..'-*;-$$;$=';,++#@%%$+@+%%%$$,+&&+;$#,;&===*;%*,=,#+##%).*%>#%+$#,*=.+%$+.$#.$+@%;*%+#.", "#$&+.$;%%-&;.;&;-;$$=$*-$,.,;;.#!.,.,$%,,,%&*;%;..;'=$+$;;)%=,%+..%+#,,%&$+#,.;$$.,+#;#+,$%##;;;%&+;", ";+.>.;&%=+*,+&,%;*;%%'-$++%.%,.%%+&$;%%,%.%=.=*%%**)=)&%.#'-&,+%%#;;+>.$,+.*%#+!,,&,@;,,,.@=%&';,+.,"}; fltk-1.4.3/test/iconize.cxx0000644000175000017500000000306415004135251015753 0ustar albrechtalbrecht// // Iconize test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include void iconize_cb(Fl_Widget *, void *v) { Fl_Window *w = (Fl_Window *)v; w->iconize(); } void show_cb(Fl_Widget *, void *v) { Fl_Window *w = (Fl_Window *)v; w->show(); } void hide_cb(Fl_Widget *, void *v) { Fl_Window *w = (Fl_Window *)v; w->hide(); } void window_cb(Fl_Widget*, void*) { exit(0); } int main(int argc, char **argv) { Fl_Window mainw(200,200); mainw.end(); mainw.show(argc,argv); Fl_Window control(120,120); Fl_Button hide_button(0,0,120,30,"hide()"); hide_button.callback(hide_cb, &mainw); Fl_Button iconize_button(0,30,120,30,"iconize()"); iconize_button.callback(iconize_cb, &mainw); Fl_Button show_button(0,60,120,30,"show()"); show_button.callback(show_cb, &mainw); Fl_Button show_button2(0,90,120,30,"show this"); show_button2.callback(show_cb, &control); // Fl_Box box(FL_NO_BOX,0,60,120,30,"Also try running\nwith -i switch"); control.end(); control.show(); control.callback(window_cb); return Fl::run(); } fltk-1.4.3/test/glpuzzle.cxx0000644000175000017500000007673615004135251016207 0ustar albrechtalbrecht// // OpenGL puzzle demo for the Fast Light Tool Kit (FLTK). // // This is a GLUT demo program to demonstrate fltk's GLUT emulation. // Search for "fltk" to find all the changes // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Convenience options 'n' and ' ' and command line switch '-n' added for FLTK // this block added for fltk's distribution so it will compile w/o OpenGL: #include #if !HAVE_GL || !HAVE_GL_GLU_H #include #include int main(int, char**) { fl_alert("This demo does not work without GL and GLU"); return 1; } #else // end of added block #include #include #include #include #include #include #include // changed for fltk #include // added for fltk #include "trackball.c" // changed from trackball.h for fltk #define WIDTH 4 #define HEIGHT 5 #define PIECES 10 #define OFFSETX -2.0f #define OFFSETY -2.5f #define OFFSETZ -0.5f typedef char Config[HEIGHT][WIDTH]; struct puzzle { struct puzzle *backptr; struct puzzle *solnptr; Config pieces; struct puzzle *next; unsigned hashvalue; }; #define HASHSIZE 10691 struct puzzlelist { struct puzzle *puzzle; struct puzzlelist *next; }; static char convert[PIECES + 1] = {0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4}; static unsigned char colors[PIECES + 1][3] = { {0, 0, 0}, {255, 255, 127}, {255, 255, 127}, {255, 255, 127}, {255, 255, 127}, {255, 127, 255}, {255, 127, 255}, {255, 127, 255}, {255, 127, 255}, {255, 127, 127}, {255, 255, 255}, }; void changeState(void); void animate(int); static struct puzzle *hashtable[HASHSIZE]; static struct puzzle *startPuzzle; static struct puzzlelist *puzzles; static struct puzzlelist *lastentry; int curX, curY, visible; #define MOVE_SPEED 0.2f static unsigned char movingPiece; static float move_x, move_y; static float curquat[4]; static int doubleBuffer = 1; static int depth = 1; static char xsize[PIECES + 1] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2}; static char ysize[PIECES + 1] = {0, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2}; static float zsize[PIECES + 1] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.6f}; static Config startConfig = { {8, 10, 10, 7}, {8, 10, 10, 7}, {6, 9, 9, 5}, {6, 4, 3, 5}, {2, 0, 0, 1} }; static Config thePuzzle = { {8, 10, 10, 7}, {8, 10, 10, 7}, {6, 9, 9, 5}, {6, 4, 3, 5}, {2, 0, 0, 1} }; static int xadds[4] = {-1, 0, 1, 0}; static int yadds[4] = {0, -1, 0, 1}; static long W = 400, H = 300; static GLint viewport[4]; #define srandom srand #define random() (rand() >> 2) unsigned hash(Config config) { int i, j, value; value = 0; for (i = 0; i < HEIGHT; i++) { for (j = 0; j < WIDTH; j++) { value = value + convert[(int)config[i][j]]; value *= 6; } } return (value); } int solution(Config config) { if (config[4][1] == 10 && config[4][2] == 10) return (1); return (0); } float boxcoords[][3] = { {0.2f, 0.2f, 0.9f}, {0.8f, 0.2f, 0.9f}, {0.8f, 0.8f, 0.9f}, {0.2f, 0.8f, 0.9f}, {0.2f, 0.1f, 0.8f}, {0.8f, 0.1f, 0.8f}, {0.9f, 0.2f, 0.8f}, {0.9f, 0.8f, 0.8f}, {0.8f, 0.9f, 0.8f}, {0.2f, 0.9f, 0.8f}, {0.1f, 0.8f, 0.8f}, {0.1f, 0.2f, 0.8f}, {0.2f, 0.1f, 0.2f}, {0.8f, 0.1f, 0.2f}, {0.9f, 0.2f, 0.2f}, {0.9f, 0.8f, 0.2f}, {0.8f, 0.9f, 0.2f}, {0.2f, 0.9f, 0.2f}, {0.1f, 0.8f, 0.2f}, {0.1f, 0.2f, 0.2f}, {0.2f, 0.2f, 0.1f}, {0.8f, 0.2f, 0.1f}, {0.8f, 0.8f, 0.1f}, {0.2f, 0.8f, 0.1f}, }; float boxnormals[][3] = { {0, 0, 1}, /* 0 */ {0, 1, 0}, {1, 0, 0}, {0, 0, -1}, {0, -1, 0}, {-1, 0, 0}, {0.7071f, 0.7071f, 0.0000f}, /* 6 */ {0.7071f, -0.7071f, 0.0000f}, {-0.7071f, 0.7071f, 0.0000f}, {-0.7071f, -0.7071f, 0.0000f}, {0.7071f, 0.0000f, 0.7071f}, /* 10 */ {0.7071f, 0.0000f, -0.7071f}, {-0.7071f, 0.0000f, 0.7071f}, {-0.7071f, 0.0000f, -0.7071f}, {0.0000f, 0.7071f, 0.7071f}, /* 14 */ {0.0000f, 0.7071f, -0.7071f}, {0.0000f, -0.7071f, 0.7071f}, {0.0000f, -0.7071f, -0.7071f}, {0.5774f, 0.5774f, 0.5774f}, /* 18 */ {0.5774f, 0.5774f, -0.5774f}, {0.5774f, -0.5774f, 0.5774f}, {0.5774f, -0.5774f, -0.5774f}, {-0.5774f, 0.5774f, 0.5774f}, {-0.5774f, 0.5774f, -0.5774f}, {-0.5774f, -0.5774f, 0.5774f}, {-0.5774f, -0.5774f, -0.5774f}, }; int boxfaces[][4] = { {0, 1, 2, 3}, /* 0 */ {9, 8, 16, 17}, {6, 14, 15, 7}, {20, 23, 22, 21}, {12, 13, 5, 4}, {19, 11, 10, 18}, {7, 15, 16, 8}, /* 6 */ {13, 14, 6, 5}, {18, 10, 9, 17}, {19, 12, 4, 11}, {1, 6, 7, 2}, /* 10 */ {14, 21, 22, 15}, {11, 0, 3, 10}, {20, 19, 18, 23}, {3, 2, 8, 9}, /* 14 */ {17, 16, 22, 23}, {4, 5, 1, 0}, {20, 21, 13, 12}, {2, 7, 8, -1}, /* 18 */ {16, 15, 22, -1}, {5, 6, 1, -1}, {13, 21, 14, -1}, {10, 3, 9, -1}, {18, 17, 23, -1}, {11, 4, 0, -1}, {20, 12, 19, -1}, }; #define NBOXFACES (sizeof(boxfaces)/sizeof(boxfaces[0])) /* Draw a box. Bevel as desired. */ void drawBox(int piece, float xoff, float yoff) { int xlen, ylen; int i, k; float x, y, z; float zlen; float *v; xlen = xsize[piece]; ylen = ysize[piece]; zlen = zsize[piece]; glColor3ubv(colors[piece]); glBegin(GL_QUADS); for (i = 0; i < 18; i++) { glNormal3fv(boxnormals[i]); for (k = 0; k < 4; k++) { if (boxfaces[i][k] == -1) continue; v = boxcoords[boxfaces[i][k]]; x = v[0] + OFFSETX; if (v[0] > 0.5) x += xlen - 1; y = v[1] + OFFSETY; if (v[1] > 0.5) y += ylen - 1; z = v[2] + OFFSETZ; if (v[2] > 0.5) z += zlen - 1; glVertex3f(xoff + x, yoff + y, z); } } glEnd(); glBegin(GL_TRIANGLES); for (i = 18; i < int(NBOXFACES); i++) { glNormal3fv(boxnormals[i]); for (k = 0; k < 3; k++) { if (boxfaces[i][k] == -1) continue; v = boxcoords[boxfaces[i][k]]; x = v[0] + OFFSETX; if (v[0] > 0.5) x += xlen - 1; y = v[1] + OFFSETY; if (v[1] > 0.5) y += ylen - 1; z = v[2] + OFFSETZ; if (v[2] > 0.5) z += zlen - 1; glVertex3f(xoff + x, yoff + y, z); } } glEnd(); } float containercoords[][3] = { {-0.1f, -0.1f, 1.0f}, {-0.1f, -0.1f, -0.1f}, {4.1f, -0.1f, -0.1f}, {4.1f, -0.1f, 1.0f}, {1.0f, -0.1f, 0.6f}, /* 4 */ {3.0f, -0.1f, 0.6f}, {1.0f, -0.1f, 0.0f}, {3.0f, -0.1f, 0.0f}, {1.0f, 0.0f, 0.0f}, /* 8 */ {3.0f, 0.0f, 0.0f}, {3.0f, 0.0f, 0.6f}, {1.0f, 0.0f, 0.6f}, {0.0f, 0.0f, 1.0f}, /* 12 */ {4.0f, 0.0f, 1.0f}, {4.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 5.0f, 0.0f}, /* 16 */ {0.0f, 5.0f, 1.0f}, {4.0f, 5.0f, 1.0f}, {4.0f, 5.0f, 0.0f}, {-0.1f, 5.1f, -0.1f}, /* 20 */ {4.1f, 5.1f, -0.1f}, {4.1f, 5.1f, 1.0f}, {-0.1f, 5.1f, 1.0f}, }; float containernormals[][3] = { {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, -1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {1, 0, 0}, {1, 0, 0}, {1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, -1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, }; int containerfaces[][4] = { {1, 6, 4, 0}, {0, 4, 5, 3}, {1, 2, 7, 6}, {7, 2, 3, 5}, {16, 19, 18, 17}, {23, 22, 21, 20}, {12, 11, 8, 15}, {10, 13, 14, 9}, {15, 16, 17, 12}, {2, 21, 22, 3}, {6, 8, 11, 4}, {1, 0, 23, 20}, {14, 13, 18, 19}, {9, 7, 5, 10}, {12, 13, 10, 11}, {1, 20, 21, 2}, {4, 11, 10, 5}, {15, 8, 19, 16}, {19, 8, 9, 14}, {8, 6, 7, 9}, {0, 3, 13, 12}, {13, 3, 22, 18}, {18, 22, 23, 17}, {17, 23, 0, 12}, }; #define NCONTFACES (sizeof(containerfaces)/sizeof(containerfaces[0])) /* Draw the container */ void drawContainer(void) { int i, k; float *v; /* Y is reversed here because the model has it reversed */ /* Arbitrary bright wood-like color */ glColor3ub(209, 103, 23); glBegin(GL_QUADS); for (i = 0; i < int(NCONTFACES); i++) { v = containernormals[i]; glNormal3f(v[0], -v[1], v[2]); for (k = 3; k >= 0; k--) { v = containercoords[containerfaces[i][k]]; glVertex3f(v[0] + OFFSETX, -(v[1] + OFFSETY), v[2] + OFFSETZ); } } glEnd(); } void drawAll(void) { int i, j; int piece; char done[PIECES + 1]; float m[4][4]; build_rotmatrix(m, curquat); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, -10); glMultMatrixf(&(m[0][0])); glRotatef(180, 0, 0, 1); if (depth) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } else { glClear(GL_COLOR_BUFFER_BIT); } for (i = 1; i <= PIECES; i++) { done[i] = 0; } glLoadName(0); drawContainer(); for (i = 0; i < HEIGHT; i++) { for (j = 0; j < WIDTH; j++) { piece = thePuzzle[i][j]; if (piece == 0) continue; if (done[piece]) continue; done[piece] = 1; glLoadName(piece); if (piece == movingPiece) { drawBox(piece, move_x, move_y); } else { drawBox(piece, float(j), float(i)); } } } } void redraw(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45, viewport[2]*1.0/viewport[3], 0.1, 100.0); drawAll(); if (doubleBuffer) glutSwapBuffers(); else glFinish(); } void solidifyChain(struct puzzle *puzzle) { int i; char buf[256]; i = 0; while (puzzle->backptr) { i++; puzzle->backptr->solnptr = puzzle; puzzle = puzzle->backptr; } snprintf(buf, 256, "%d moves to complete!", i); glutSetWindowTitle(buf); } int addConfig(Config config, struct puzzle *back) { unsigned hashvalue; struct puzzle *newpiece; struct puzzlelist *newlistentry; hashvalue = hash(config); newpiece = hashtable[hashvalue % HASHSIZE]; while (newpiece != NULL) { if (newpiece->hashvalue == hashvalue) { int i, j; for (i = 0; i < WIDTH; i++) { for (j = 0; j < HEIGHT; j++) { if (convert[(int)config[j][i]] != convert[(int)newpiece->pieces[j][i]]) goto nomatch; } } return 0; } nomatch: newpiece = newpiece->next; } newpiece = (struct puzzle *) malloc(sizeof(struct puzzle)); newpiece->next = hashtable[hashvalue % HASHSIZE]; newpiece->hashvalue = hashvalue; memcpy(newpiece->pieces, config, HEIGHT * WIDTH); newpiece->backptr = back; newpiece->solnptr = NULL; hashtable[hashvalue % HASHSIZE] = newpiece; newlistentry = (struct puzzlelist *) malloc(sizeof(struct puzzlelist)); newlistentry->puzzle = newpiece; newlistentry->next = NULL; if (lastentry) { lastentry->next = newlistentry; } else { puzzles = newlistentry; } lastentry = newlistentry; if (back == NULL) { startPuzzle = newpiece; } if (solution(config)) { solidifyChain(newpiece); return 1; } return 0; } /* Checks if a space can move */ int canmove0(Config pieces, int x, int y, int dir, Config newpieces) { char piece; int xadd, yadd; int l, m; xadd = xadds[dir]; yadd = yadds[dir]; if (x + xadd < 0 || x + xadd >= WIDTH || y + yadd < 0 || y + yadd >= HEIGHT) return 0; piece = pieces[y + yadd][x + xadd]; if (piece == 0) return 0; memcpy(newpieces, pieces, HEIGHT * WIDTH); for (l = 0; l < WIDTH; l++) { for (m = 0; m < HEIGHT; m++) { if (newpieces[m][l] == piece) newpieces[m][l] = 0; } } xadd = -xadd; yadd = -yadd; for (l = 0; l < WIDTH; l++) { for (m = 0; m < HEIGHT; m++) { if (pieces[m][l] == piece) { int newx, newy; newx = l + xadd; newy = m + yadd; if (newx < 0 || newx >= WIDTH || newy < 0 || newy >= HEIGHT) return 0; if (newpieces[newy][newx] != 0) return 0; newpieces[newy][newx] = piece; } } } return 1; } /* Checks if a piece can move */ int canmove(Config pieces, int x, int y, int dir, Config newpieces) { int xadd, yadd; xadd = xadds[dir]; yadd = yadds[dir]; if (x + xadd < 0 || x + xadd >= WIDTH || y + yadd < 0 || y + yadd >= HEIGHT) return 0; if (pieces[y + yadd][x + xadd] == pieces[y][x]) { return canmove(pieces, x + xadd, y + yadd, dir, newpieces); } if (pieces[y + yadd][x + xadd] != 0) return 0; return canmove0(pieces, x + xadd, y + yadd, (dir + 2) % 4, newpieces); } int generateNewConfigs(struct puzzle *puzzle) { int i, j, k; Config pieces; Config newpieces; memcpy(pieces, puzzle->pieces, HEIGHT * WIDTH); for (i = 0; i < WIDTH; i++) { for (j = 0; j < HEIGHT; j++) { if (pieces[j][i] == 0) { for (k = 0; k < 4; k++) { if (canmove0(pieces, i, j, k, newpieces)) { if (addConfig(newpieces, puzzle)) return 1; } } } } } return 0; } void freeSolutions(void) { struct puzzlelist *nextpuz; struct puzzle *puzzle, *next; int i; while (puzzles) { nextpuz = puzzles->next; free((char *) puzzles); puzzles = nextpuz; } lastentry = NULL; for (i = 0; i < HASHSIZE; i++) { puzzle = hashtable[i]; hashtable[i] = NULL; while (puzzle) { next = puzzle->next; free((char *) puzzle); puzzle = next; } } startPuzzle = NULL; } int continueSolving(void) { struct puzzle *nextpuz; int i, j; int movedPiece; int movedir; int fromx, fromy; int tox, toy; if (startPuzzle == NULL) return 0; if (startPuzzle->solnptr == NULL) { freeSolutions(); return 0; } nextpuz = startPuzzle->solnptr; movedPiece = 0; movedir = 0; for (i = 0; i < HEIGHT; i++) { for (j = 0; j < WIDTH; j++) { if (startPuzzle->pieces[i][j] != nextpuz->pieces[i][j]) { if (startPuzzle->pieces[i][j]) { movedPiece = startPuzzle->pieces[i][j]; fromx = j; fromy = i; if (i < HEIGHT - 1 && nextpuz->pieces[i + 1][j] == movedPiece) { movedir = 3; } else { movedir = 2; } goto found_piece; } else { movedPiece = nextpuz->pieces[i][j]; if (i < HEIGHT - 1 && startPuzzle->pieces[i + 1][j] == movedPiece) { fromx = j; fromy = i + 1; movedir = 1; } else { fromx = j + 1; fromy = i; movedir = 0; } goto found_piece; } } } } glutSetWindowTitle((char *)"What! No change?"); freeSolutions(); return 0; found_piece: if (!movingPiece) { movingPiece = movedPiece; move_x = float(fromx); move_y = float(fromy); } move_x += xadds[movedir] * MOVE_SPEED; move_y += yadds[movedir] * MOVE_SPEED; tox = fromx + xadds[movedir]; toy = fromy + yadds[movedir]; if (move_x > tox - MOVE_SPEED / 2 && move_x < tox + MOVE_SPEED / 2 && move_y > toy - MOVE_SPEED / 2 && move_y < toy + MOVE_SPEED / 2) { startPuzzle = nextpuz; movingPiece = 0; } memcpy(thePuzzle, startPuzzle->pieces, HEIGHT * WIDTH); changeState(); return 1; } int solvePuzzle(void) { struct puzzlelist *nextpuz; char buf[256]; int i; if (solution(thePuzzle)) { glutSetWindowTitle((char *)"Puzzle already solved!"); return 0; } addConfig(thePuzzle, NULL); i = 0; while (puzzles) { i++; if (generateNewConfigs(puzzles->puzzle)) break; nextpuz = puzzles->next; free((char *) puzzles); puzzles = nextpuz; } if (puzzles == NULL) { freeSolutions(); snprintf(buf, 256, "I can't solve it! (%d positions examined)", i); glutSetWindowTitle(buf); return 1; } return 1; } int selectPiece(int mousex, int mousey) { long hits; GLuint selectBuf[1024]; GLuint closest; GLuint dist; glSelectBuffer(1024, selectBuf); (void) glRenderMode(GL_SELECT); glInitNames(); /* Because LoadName() won't work with no names on the stack */ glPushName(0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPickMatrix(mousex, H - mousey, 4, 4, viewport); gluPerspective(45, viewport[2]*1.0/viewport[3], 0.1, 100.0); drawAll(); hits = glRenderMode(GL_RENDER); if (hits <= 0) { return 0; } closest = 0; dist = 0xFFFFFFFFU; //2147483647; while (hits) { if (selectBuf[(hits - 1) * 4 + 1] < dist) { dist = selectBuf[(hits - 1) * 4 + 1]; closest = selectBuf[(hits - 1) * 4 + 3]; } hits--; } return closest; } void nukePiece(int piece) { int i, j; for (i = 0; i < HEIGHT; i++) { for (j = 0; j < WIDTH; j++) { if (thePuzzle[i][j] == piece) { thePuzzle[i][j] = 0; } } } } void multMatrices(const GLfloat a[16], const GLfloat b[16], GLfloat r[16]) { int i, j; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { r[i * 4 + j] = a[i * 4 + 0] * b[0 * 4 + j] + a[i * 4 + 1] * b[1 * 4 + j] + a[i * 4 + 2] * b[2 * 4 + j] + a[i * 4 + 3] * b[3 * 4 + j]; } } } void makeIdentity(GLfloat m[16]) { m[0 + 4 * 0] = 1; m[0 + 4 * 1] = 0; m[0 + 4 * 2] = 0; m[0 + 4 * 3] = 0; m[1 + 4 * 0] = 0; m[1 + 4 * 1] = 1; m[1 + 4 * 2] = 0; m[1 + 4 * 3] = 0; m[2 + 4 * 0] = 0; m[2 + 4 * 1] = 0; m[2 + 4 * 2] = 1; m[2 + 4 * 3] = 0; m[3 + 4 * 0] = 0; m[3 + 4 * 1] = 0; m[3 + 4 * 2] = 0; m[3 + 4 * 3] = 1; } /* ** inverse = invert(src) */ int invertMatrix(const GLfloat src[16], GLfloat inverse[16]) { int i, j, k, swap; float t; GLfloat temp[4][4]; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { temp[i][j] = src[i * 4 + j]; } } makeIdentity(inverse); for (i = 0; i < 4; i++) { /* ** Look for largest element in column */ swap = i; for (j = i + 1; j < 4; j++) { if (fabs(temp[j][i]) > fabs(temp[i][i])) { swap = j; } } if (swap != i) { /* ** Swap rows. */ for (k = 0; k < 4; k++) { t = temp[i][k]; temp[i][k] = temp[swap][k]; temp[swap][k] = t; t = inverse[i * 4 + k]; inverse[i * 4 + k] = inverse[swap * 4 + k]; inverse[swap * 4 + k] = t; } } if (temp[i][i] == 0) { /* ** No non-zero pivot. The matrix is singular, which shouldn't ** happen. This means the user gave us a bad matrix. */ return 0; } t = temp[i][i]; for (k = 0; k < 4; k++) { temp[i][k] /= t; inverse[i * 4 + k] /= t; } for (j = 0; j < 4; j++) { if (j != i) { t = temp[j][i]; for (k = 0; k < 4; k++) { temp[j][k] -= temp[i][k] * t; inverse[j * 4 + k] -= inverse[i * 4 + k] * t; } } } } return 1; } /* ** This is a screwball function. What it does is the following: ** Given screen x and y coordinates, compute the corresponding object space ** x and y coordinates given that the object space z is 0.9 + OFFSETZ. ** Since the tops of (most) pieces are at z = 0.9 + OFFSETZ, we use that ** number. */ int computeCoords(int piece, int mousex, int mousey, GLfloat * selx, GLfloat * sely) { GLfloat modelMatrix[16]; GLfloat projMatrix[16]; GLfloat finalMatrix[16]; GLfloat in[4]; GLfloat a, b, c, d; GLfloat top, bot; GLfloat z; GLfloat w; GLfloat height; if (piece == 0) return 0; height = zsize[piece] - 0.1f + OFFSETZ; glGetFloatv(GL_PROJECTION_MATRIX, projMatrix); glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); multMatrices(modelMatrix, projMatrix, finalMatrix); if (!invertMatrix(finalMatrix, finalMatrix)) return 0; in[0] = (2.0f * (mousex - viewport[0]) / viewport[2]) - 1; in[1] = (2.0f * ((H - mousey) - viewport[1]) / viewport[3]) - 1; a = in[0] * finalMatrix[0 * 4 + 2] + in[1] * finalMatrix[1 * 4 + 2] + finalMatrix[3 * 4 + 2]; b = finalMatrix[2 * 4 + 2]; c = in[0] * finalMatrix[0 * 4 + 3] + in[1] * finalMatrix[1 * 4 + 3] + finalMatrix[3 * 4 + 3]; d = finalMatrix[2 * 4 + 3]; /* ** Ok, now we need to solve for z: ** (a + b z) / (c + d z) = height. ** ("height" is the height in object space we want to solve z for) ** ** ==> a + b z = height c + height d z ** bz - height d z = height c - a ** z = (height c - a) / (b - height d) */ top = height * c - a; bot = b - height * d; if (bot == 0.0) return 0; z = top / bot; /* ** Ok, no problem. ** Now we solve for x and y. We know that w = c + d z, so we compute it. */ w = c + d * z; /* ** Now for x and y: */ *selx = (in[0] * finalMatrix[0 * 4 + 0] + in[1] * finalMatrix[1 * 4 + 0] + z * finalMatrix[2 * 4 + 0] + finalMatrix[3 * 4 + 0]) / w - OFFSETX; *sely = (in[0] * finalMatrix[0 * 4 + 1] + in[1] * finalMatrix[1 * 4 + 1] + z * finalMatrix[2 * 4 + 1] + finalMatrix[3 * 4 + 1]) / w - OFFSETY; return 1; } static int selected; static int selectx, selecty; static float selstartx, selstarty; void grabPiece(int piece, float selx, float sely) { int hit; selectx = int(selx); selecty = int(sely); if (selectx < 0 || selecty < 0 || selectx >= WIDTH || selecty >= HEIGHT) { return; } hit = thePuzzle[selecty][selectx]; if (hit != piece) return; if (hit) { movingPiece = hit; while (selectx > 0 && thePuzzle[selecty][selectx - 1] == movingPiece) { selectx--; } while (selecty > 0 && thePuzzle[selecty - 1][selectx] == movingPiece) { selecty--; } move_x = float(selectx); move_y = float(selecty); selected = 1; selstartx = selx; selstarty = sely; } else { selected = 0; } changeState(); } void moveSelection(float selx, float sely) { float deltax, deltay; int dir; Config newpieces; if (!selected) return; deltax = selx - selstartx; deltay = sely - selstarty; if (fabs(deltax) > fabs(deltay)) { deltay = 0; if (deltax > 0) { if (deltax > 1) deltax = 1; dir = 2; } else { if (deltax < -1) deltax = -1; dir = 0; } } else { deltax = 0; if (deltay > 0) { if (deltay > 1) deltay = 1; dir = 3; } else { if (deltay < -1) deltay = -1; dir = 1; } } if (canmove(thePuzzle, selectx, selecty, dir, newpieces)) { move_x = deltax + selectx; move_y = deltay + selecty; if (deltax > 0.5) { memcpy(thePuzzle, newpieces, HEIGHT * WIDTH); selectx++; selstartx++; } else if (deltax < -0.5) { memcpy(thePuzzle, newpieces, HEIGHT * WIDTH); selectx--; selstartx--; } else if (deltay > 0.5) { memcpy(thePuzzle, newpieces, HEIGHT * WIDTH); selecty++; selstarty++; } else if (deltay < -0.5) { memcpy(thePuzzle, newpieces, HEIGHT * WIDTH); selecty--; selstarty--; } } else { if (deltay > 0 && thePuzzle[selecty][selectx] == 10 && selectx == 1 && selecty == 3) { /* Allow visual movement of solution piece outside of the box */ move_x = float(selectx); move_y = sely - selstarty + selecty; } else { move_x = float(selectx); move_y = float(selecty); } } } void dropSelection(void) { if (!selected) return; movingPiece = 0; selected = 0; changeState(); } static int left_mouse, middle_mouse; static int mousex, mousey; static int solving; static int spinning; static int enable_spinning = 1; static float lastquat[4]; static int sel_piece; static int timer_active = 0; // restart another rimer at the end of `animate` static int timer_pending = 0; // a timer is waiting to be triggered static int timer_delay = 13; // timeout in msec (13ms = 72 frames per second) static void Reshape(int width, int height) { W = width; H = height; glViewport(0, 0, (GLsizei)W, (GLsizei)H); glGetIntegerv(GL_VIEWPORT, viewport); } void toggleSolve(void) { if (solving) { freeSolutions(); solving = 0; glutChangeToMenuEntry(2, (char *)"Solve", 2); glutSetWindowTitle((char *)"glpuzzle"); movingPiece = 0; } else { glutChangeToMenuEntry(2, (char *)"Stop solving", 2); glutSetWindowTitle((char *)"Solving..."); if (solvePuzzle()) { solving = 1; } } changeState(); glutPostRedisplay(); } void reset_position(void) { spinning = 0; trackball(curquat, 0.0, 0.0, 0.0, 0.0); // reset position if (!timer_pending) { timer_pending = 1; glutTimerFunc(timer_delay, animate, 0); } } void reset(void) { reset_position(); if (solving) { freeSolutions(); solving = 0; glutChangeToMenuEntry(2, (char *)"Solve", 2); glutSetWindowTitle((char *)"glpuzzle"); movingPiece = 0; changeState(); } memcpy(thePuzzle, startConfig, HEIGHT * WIDTH); glutPostRedisplay(); } void keyboard(unsigned char c, int x, int y) { int piece; switch (c) { case 27: exit(0); break; case ' ': case 'n': case 'N': reset_position(); break; case 'D': case 'd': if (solving) { freeSolutions(); solving = 0; glutChangeToMenuEntry(2, (char *)"Solve", 2); glutSetWindowTitle((char *)"glpuzzle"); movingPiece = 0; changeState(); } piece = selectPiece(x, y); if (piece) { nukePiece(piece); } glutPostRedisplay(); break; case 'R': case 'r': reset(); break; case 'S': case 's': toggleSolve(); break; case 'b': case 'B': depth = 1 - depth; if (depth) { glEnable(GL_DEPTH_TEST); } else { glDisable(GL_DEPTH_TEST); } glutPostRedisplay(); break; default: break; } } void motion(int x, int y) { float selx, sely; if (middle_mouse && !left_mouse) { if (mousex != x || mousey != y) { trackball(lastquat, (2.0f*mousex - W) / W, (H - 2.0f*mousey) / H, (2.0f*x - W) / W, (H - 2.0f*y) / H); spinning = enable_spinning; // 1 = yes, 0 = disabled (commandline -n) } else { spinning = 0; } changeState(); } else { computeCoords(sel_piece, x, y, &selx, &sely); moveSelection(selx, sely); } mousex = x; mousey = y; glutPostRedisplay(); } void mouse(int b, int s, int x, int y) { float selx, sely; mousex = x; mousey = y; curX = x; curY = y; if (s == GLUT_DOWN) { switch (b) { case GLUT_LEFT_BUTTON: if (solving) { freeSolutions(); solving = 0; glutChangeToMenuEntry(2, (char *)"Solve", 2); glutSetWindowTitle((char *)"glpuzzle"); movingPiece = 0; } left_mouse = GL_TRUE; sel_piece = selectPiece(mousex, mousey); if (!sel_piece) { left_mouse = GL_FALSE; middle_mouse = GL_TRUE; // let it rotate object } else if (computeCoords(sel_piece, mousex, mousey, &selx, &sely)) { grabPiece(sel_piece, selx, sely); } glutPostRedisplay(); break; case GLUT_MIDDLE_BUTTON: middle_mouse = GL_TRUE; glutPostRedisplay(); break; } } else { if (left_mouse) { left_mouse = GL_FALSE; dropSelection(); glutPostRedisplay(); } else if (middle_mouse) { middle_mouse = GL_FALSE; glutPostRedisplay(); } } motion(x, y); } void animate(int) { timer_pending = 0; if (spinning) { add_quats(lastquat, curquat, curquat); } glutPostRedisplay(); if (solving) { if (!continueSolving()) { solving = 0; glutChangeToMenuEntry(2, (char *)"Solve", 2); glutSetWindowTitle((char *)"glpuzzle"); } } if ((!solving && !spinning) || !visible) { timer_active = 0; } if (timer_active && !timer_pending) { timer_pending = 1; glutTimerFunc(timer_delay, animate, 0); } } void changeState(void) { if (visible) { if (!solving && !spinning) { timer_active = 0; } else { timer_active = 1; if (!timer_pending) { timer_pending = 1; glutTimerFunc(timer_delay, animate, 0); } } } else { timer_active = 0; } } void init(void) { static float lmodel_ambient[] = {0.0, 0.0, 0.0, 0.0}; static float lmodel_twoside[] = {GL_FALSE}; static float lmodel_local[] = {GL_FALSE}; static float light0_ambient[] = {0.1f, 0.1f, 0.1f, 1.0f}; static float light0_diffuse[] = {1.0f, 1.0f, 1.0f, 0.0f}; static float light0_position[] = {0.8660254f, 0.5f, 1, 0}; static float light0_specular[] = {0.0, 0.0, 0.0, 0.0}; static float bevel_mat_ambient[] = {0.0, 0.0, 0.0, 1.0}; static float bevel_mat_shininess[] = {40.0}; static float bevel_mat_specular[] = {0.0, 0.0, 0.0, 0.0}; static float bevel_mat_diffuse[] = {1.0, 0.0, 0.0, 0.0}; glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glEnable(GL_DEPTH_TEST); glClearDepth(1.0); glClearColor(0.5, 0.5, 0.5, 0.0); glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular); glLightfv(GL_LIGHT0, GL_POSITION, light0_position); glEnable(GL_LIGHT0); glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local); glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glEnable(GL_LIGHTING); glMaterialfv(GL_FRONT, GL_AMBIENT, bevel_mat_ambient); glMaterialfv(GL_FRONT, GL_SHININESS, bevel_mat_shininess); glMaterialfv(GL_FRONT, GL_SPECULAR, bevel_mat_specular); glMaterialfv(GL_FRONT, GL_DIFFUSE, bevel_mat_diffuse); glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glEnable(GL_COLOR_MATERIAL); glShadeModel(GL_FLAT); trackball(curquat, 0.0, 0.0, 0.0, 0.0); srandom((unsigned int)time(NULL)); } static void Usage(void) { puts("Usage: puzzle [-s]"); puts(" -s: Run in single buffered mode"); exit(-1); } void visibility(int v) { if (v == GLUT_VISIBLE) { visible = 1; } else { visible = 0; } changeState(); } void menu(int choice) { switch(choice) { case 1: reset_position(); break; case 2: toggleSolve(); break; case 3: reset(); break; case 4: exit(0); break; } } int main(int argc, char **argv) { long i; Fl::use_high_res_GL(1); glutInit(&argc, argv); for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'n': enable_spinning = 0; // disable (sometimes annoying) spinning behaviour break; case 's': doubleBuffer = 0; break; default: Usage(); } } else { Usage(); } } glutInitWindowSize((int)W, (int)H); if (doubleBuffer) { glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE); } else { glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_SINGLE | GLUT_MULTISAMPLE); } glutCreateWindow("glpuzzle"); visible = 1; // added for fltk, bug in original program? init(); glGetIntegerv(GL_VIEWPORT, viewport); puts(""); puts("n Normal position - stop spinning"); puts("r Reset puzzle"); puts("s Solve puzzle (may take a few seconds to compute)"); puts("d Destroy a piece - makes the puzzle easier"); puts("b Toggles the depth buffer on and off"); puts(""); puts("Left mouse moves pieces"); puts("Middle mouse spins the puzzle"); puts("Right mouse has menu"); glutReshapeFunc(Reshape); glutDisplayFunc(redraw); glutKeyboardFunc(keyboard); glutMotionFunc(motion); glutMouseFunc(mouse); glutVisibilityFunc(visibility); glutCreateMenu(menu); glutAddMenuEntry("Normal pos", 1); glutAddMenuEntry("Solve", 2); glutAddMenuEntry("Reset", 3); glutAddMenuEntry("Quit", 4); glutAttachMenu(GLUT_RIGHT_BUTTON); glutMainLoop(); return 0; /* ANSI C requires main to return int. */ } #endif // added for fltk's distribution fltk-1.4.3/test/device.cxx0000644000175000017500000005417515004135251015563 0ustar albrechtalbrecht// // Device test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Roman Kantor and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pixmaps/porsche.xpm" #include "pixmaps/sorceress.xbm" class MyWidget: public Fl_Box{ protected: void draw() FL_OVERRIDE { Fl_Box::draw(); fl_color(FL_RED); fl_rectf(x()+5,y()+5,w()-10,h()-10); fl_push_clip(x()+6,y()+6,w()-12,h()-12); fl_color(FL_DARK_GREEN); fl_rectf(x()+5,y()+5,w()-10,h()-10); fl_pop_clip(); fl_color(FL_YELLOW); fl_rectf(x()+7,y()+7,w()-14,h()-14); fl_color(FL_BLUE); fl_rect(x()+8,y()+8,w()-16,h()-16); fl_push_clip(x()+25,y()+25,w()-50, h()-50); fl_color(FL_BLACK); fl_rect(x()+24,y()+24,w()-48,h()-48); fl_line(x()+27,y()+27,x()+w()-27,y()+h()-27); fl_line(x()+27,y()+h()-27,x()+w()-27,y()+27); //fl_rect(x()+30,y()+30,w()-60,h()-60); fl_pop_clip(); } public: MyWidget(int x, int y):Fl_Box(x,y,100,100, "Clipping and rect(f):\nYellow rect.framed\nby B-Y-G-R rect. 1 p.\nthick. Your printer may \nrender very thin lines\nsurrounding \"X\""){ align(FL_ALIGN_TOP); labelsize(10); } }; class MyWidget2: public Fl_Box { protected: void draw() FL_OVERRIDE { Fl_Box::draw(); int d; // fl_line_style(0); for(d=y()+5;d<48+y();d+=2){ fl_xyline(x()+5,d,x()+48); } fl_push_clip(x()+52,y()+5,45,43); for(d=y()+5;d<150+y();d+=3){ fl_line(x()+52,d,x()+92,d-40); } fl_pop_clip(); fl_line_style(FL_DASH); fl_xyline(x()+5,y()+55,x()+48); fl_line_style(FL_DOT); fl_xyline(x()+5,y()+58,x()+48); fl_line_style(FL_DASHDOT); fl_xyline(x()+5,y()+61,x()+48); fl_line_style(FL_DASHDOTDOT); fl_xyline(x()+5,y()+64,x()+48); fl_line_style(0,0,(char*)"\7\3\7\2"); fl_xyline(x()+5,y()+67,x()+48); fl_line_style(0); fl_line(x()+5,y()+72,x()+25,y()+95); fl_line(x()+8,y()+72,x()+28,y()+95,x()+31,y()+72); fl_color(FL_YELLOW); fl_polygon(x()+11, y()+72,x()+27,y()+91,x()+29,y()+72); fl_color(FL_RED); fl_loop(x()+11, y()+72,x()+27,y()+91,x()+29,y()+72); fl_color(FL_BLUE); //// fl_line_style(FL_SOLID, 6); fl_loop(x()+31, y()+12,x()+47,y()+31,x()+49,y()+12); fl_line_style(0); fl_color(200,0,200); fl_polygon(x()+35,y()+72,x()+33,y()+95,x()+48,y()+95,x()+43,y()+72); fl_color(FL_GREEN); fl_loop(x()+35,y()+72,x()+33,y()+95,x()+48,y()+95,x()+43,y()+72); fl_color(FL_BLUE); fl_yxline(x()+65,y()+63,y()+66); fl_color(FL_GREEN); fl_yxline(x()+66,y()+66,y()+63); fl_color(FL_BLUE); fl_rect(x()+80,y()+55,5,5); fl_color(FL_YELLOW); fl_rectf(x()+81,y()+56,3,3); fl_color(FL_BLACK); fl_point(x()+82,y()+57); fl_color(FL_BLUE); fl_rect(x()+56, y()+79, 24, 17); fl_color(FL_CYAN); fl_rectf(x()+57, y()+80, 22 , 15 ); fl_color(FL_RED); fl_arc(x()+57, y()+80, 22 ,15 ,40, 270); fl_color(FL_YELLOW); fl_pie(x()+58, y()+81, 20 ,13 ,40, 270); fl_line_style(0); fl_color(FL_BLACK); fl_point(x()+58,y()+58); fl_color(FL_RED); fl_yxline(x()+59,y()+58,y()+59); fl_color(FL_GREEN); fl_yxline(x()+60,y()+59,y()+58); fl_color(FL_BLACK); fl_xyline(x()+61,y()+58,x()+62); fl_color(FL_RED); fl_xyline(x()+62,y()+59,x()+61); fl_color(FL_GREEN); fl_yxline(x()+57,y()+58,y()+59,x()+58); fl_color(FL_BLUE); fl_xyline(x()+58,y()+60,x()+56,y()+58); fl_color(FL_RED); fl_xyline(x()+58,y()+61,x()+56,y()+63); fl_color(FL_GREEN); fl_yxline(x()+57,y()+63,y()+62,x()+58); fl_color(FL_BLUE); fl_line(x()+58,y()+63, x()+60, y()+65); fl_color(FL_BLACK); fl_line(x()+61,y()+65, x()+59, y()+63); fl_color(FL_BLACK); } public: MyWidget2(int x, int y):Fl_Box(x,y,100,100, "Integer primitives") { labelsize(10); align(FL_ALIGN_TOP); } }; class MyWidget3: public Fl_Box { protected: void draw() FL_OVERRIDE { Fl_Box::draw(); double d; // fl_line_style(0); fl_push_clip(x()+5,y()+5,45,43); for(d=y()+5;d<95+y();d+=1.63){ fl_begin_line(); fl_vertex(x()+5,d); fl_vertex(x()+48,d); fl_end_line(); } fl_pop_clip(); fl_push_clip(x()+52,y()+5,45,43); for(d=y()+5;d<150+y();d+=2.3052){ fl_begin_line(); fl_vertex(x()+52,d); fl_vertex(x()+92,d-43); fl_end_line(); } fl_pop_clip(); } public: MyWidget3(int x, int y):Fl_Box(x,y,100,100, "Sub-pixel drawing of\nlines 1.63 points apart\nOn the screen you\ncan see aliasing, the\nprinter should render\nthem properly") { labelsize(10); align(FL_ALIGN_TOP); } }; class MyWidget4: public Fl_Box{ protected: void draw() FL_OVERRIDE { Fl_Box::draw(); fl_push_matrix(); fl_translate(x(),y()); fl_scale(.75,.75); fl_line_style(FL_SOLID , 5); fl_begin_line(); fl_vertex(10, 160); fl_vertex(40, 160); fl_vertex(40, 190); fl_end_line(); fl_line_style(0); fl_color(FL_RED); fl_line_style(FL_SOLID | FL_CAP_FLAT |FL_JOIN_MITER , 5); fl_begin_line(); fl_vertex(10, 150); fl_vertex(50, 150); fl_vertex(50, 190); fl_end_line(); fl_line_style(0); fl_color(FL_GREEN); fl_line_style(FL_SOLID | FL_CAP_ROUND |FL_JOIN_ROUND , 5); fl_begin_line(); fl_vertex(10, 140); fl_vertex(60, 140); fl_vertex(60, 190); fl_end_line(); fl_line_style(0); fl_color(FL_BLUE); fl_line_style(FL_SOLID | FL_CAP_SQUARE |FL_JOIN_BEVEL , 5); fl_begin_line(); fl_vertex(10, 130); fl_vertex(70, 130); fl_vertex(70, 190); fl_end_line(); fl_line_style(0); fl_color(FL_BLACK); fl_line_style(FL_DASH , 5); fl_begin_line(); fl_vertex(10, 120); fl_vertex(80, 120); fl_vertex(80, 190); fl_end_line(); fl_line_style(0); fl_color(FL_RED); fl_line_style(FL_DASH |FL_CAP_FLAT , 5); fl_begin_line(); fl_vertex(10, 110); fl_vertex(90, 110); fl_vertex(90, 190); fl_end_line(); fl_line_style(0); fl_color(FL_GREEN); fl_line_style(FL_DASH |FL_CAP_ROUND , 5); fl_begin_line(); fl_vertex(10, 100); fl_vertex(100, 100); fl_vertex(100, 190); fl_end_line(); fl_line_style(0); fl_color(FL_BLUE); fl_line_style(FL_DASH |FL_CAP_SQUARE , 5); fl_begin_line(); fl_vertex(10, 90); fl_vertex(110, 90); fl_vertex(110, 190); fl_end_line(); fl_line_style(0); fl_color(FL_BLACK); fl_line_style(FL_DOT, 5); fl_begin_line(); fl_vertex(10, 80); fl_vertex(120, 80); fl_vertex(120, 190); fl_end_line(); fl_line_style(0); fl_color(FL_RED); fl_line_style(FL_DOT | FL_CAP_FLAT, 5); fl_begin_line(); fl_vertex(10, 70); fl_vertex(130, 70); fl_vertex(130, 190); fl_end_line(); fl_line_style(0); fl_color(FL_GREEN); fl_line_style(FL_DOT | FL_CAP_ROUND, 5); fl_begin_line(); fl_vertex(10, 60); fl_vertex(140, 60); fl_vertex(140, 190); fl_end_line(); fl_line_style(0); fl_color(FL_BLUE); fl_line_style(FL_DOT | FL_CAP_SQUARE, 5); fl_begin_line(); fl_vertex(10, 50); fl_vertex(150, 50); fl_vertex(150, 190); fl_end_line(); fl_line_style(0); fl_color(FL_BLACK); fl_line_style(FL_DASHDOT |FL_CAP_ROUND |FL_JOIN_ROUND , 5); fl_begin_line(); fl_vertex(10, 40); fl_vertex(160, 40); fl_vertex(160, 190); fl_end_line(); fl_line_style(0); fl_color(FL_RED); fl_line_style(FL_DASHDOTDOT |FL_CAP_SQUARE |FL_JOIN_BEVEL , 5); fl_begin_line(); fl_vertex(10, 30); fl_vertex(170, 30); fl_vertex(170, 190); fl_end_line(); fl_line_style(0); fl_color(FL_GREEN); fl_line_style(FL_DASHDOTDOT |FL_CAP_ROUND |FL_JOIN_ROUND , 5); fl_begin_line(); fl_vertex(10, 20); fl_vertex(180, 20); fl_vertex(180, 190); fl_end_line(); fl_line_style(0); fl_color(FL_BLUE); fl_line_style(0, 5, (char*)"\12\3\4\2\2\1"); fl_begin_line(); fl_vertex(10, 10); fl_vertex(190, 10); fl_vertex(190, 190); fl_end_line(); fl_line_style(0); fl_pop_matrix(); fl_color(FL_BLACK); } public: MyWidget4(int x, int y):Fl_Box(x,y+10,150,150, "Line styles"){ labelsize(10); align(FL_ALIGN_TOP); } }; class MyWidget5: public Fl_Box { protected: void draw() FL_OVERRIDE { Fl_Box::draw(); fl_push_matrix(); fl_translate(x(),y()); fl_push_matrix(); fl_mult_matrix(1,3,0,1,0,-20); fl_color(FL_GREEN); fl_begin_polygon(); fl_vertex(10,10); fl_vertex(100,-80); fl_vertex(100,-190); fl_end_polygon(); fl_color(FL_RED); fl_line_style(FL_DASHDOT, 7); fl_begin_loop(); fl_vertex(10,10); fl_vertex(100,-80); fl_vertex(100,-190); fl_end_loop(); fl_line_style(0); fl_color(FL_BLUE); fl_line_style(FL_SOLID, 3); fl_begin_loop(); fl_circle(60,-50,30); fl_end_loop(); fl_line_style(0); fl_pop_matrix(); fl_scale(1.8,1); fl_color(FL_YELLOW); fl_begin_polygon(); fl_arc(30,90,20,-45,200); fl_end_polygon(); fl_color(FL_BLACK); fl_line_style(FL_DASH, 3); fl_begin_line(); fl_arc(30,90,20,-45,200); fl_end_line(); fl_line_style(0); fl_translate(15,0); fl_scale(1.5,3); fl_begin_complex_polygon(); fl_vertex(30,70); fl_arc(45,55,10,200,90); fl_arc(55,45,8,-170,20); fl_vertex(60,40); fl_vertex(30,20); fl_vertex(40,5); fl_vertex(60,25); //fl_vertex(50,50); fl_curve(35,30,30,53,0,35,65,65); fl_gap(); fl_vertex(50,25); fl_vertex(40,10); fl_vertex(35,20); fl_end_complex_polygon(); fl_pop_matrix(); } public: MyWidget5(int x, int y):Fl_Box(x,y,230,250, "Complex (double) drawings:\nBlue ellipse may not be\ncorrectly transformed\ndue to non-orthogonal\ntransformation"){ labelsize(10); align(FL_ALIGN_TOP); } }; uchar *image; int width = 80; int height = 80; void make_image() { image = new uchar[4*width*height]; uchar *p = image; for (int y = 0; y < height; y++) { double Y = double(y)/(height-1); for (int x = 0; x < width; x++) { double X = double(x)/(width-1); *p++ = uchar(255*((1-X)*(1-Y))); // red in upper-left *p++ = uchar(255*((1-X)*Y)); // green in lower-left *p++ = uchar(255*(X*Y)); // blue in lower-right X -= 0.5; Y -= 0.5; int alpha = (int)(350 * sqrt(X * X + Y * Y)); if (alpha < 255) *p++ = uchar(alpha); // alpha transparency else *p++ = 255; Y += 0.5; } } } void close_tmp_win(Fl_Widget *win, void *data) { ((Fl_Shared_Image*)data)->release(); Fl::delete_widget(win); } Fl_Widget *target; const char *operation; void copy(Fl_Widget *, void *data) { if (strcmp(operation, "Fl_Image_Surface") == 0) { Fl_Image_Surface *rgb_surf; int W, H, decorated; if (target->as_window() && !target->parent()) { W = target->as_window()->decorated_w(); H = target->as_window()->decorated_h(); decorated = 1; } else { W = target->w(); H = target->h(); decorated = 0; } rgb_surf = new Fl_Image_Surface(W, H, 1); Fl_Surface_Device::push_current(rgb_surf); fl_color(FL_YELLOW);fl_rectf(0,0,W,H); if (decorated) rgb_surf->draw_decorated_window(target->as_window()); else rgb_surf->draw(target); Fl_Image *img = rgb_surf->image(); delete rgb_surf; Fl_Surface_Device::pop_current(); if (img) { Fl_Window* g2 = new Fl_Window(img->w()+10, img->h()+10, "Fl_Image_Surface"); g2->color(FL_YELLOW); Fl_Box *b = new Fl_Box(FL_NO_BOX,5,5,img->w(), img->h(),0); b->image(img); g2->end(); g2->callback(close_tmp_win, img); g2->show(); } return; } if (strcmp(operation, "Fl_Copy_Surface") == 0) { Fl_Copy_Surface *copy_surf; if (target->as_window() && !target->parent()) { copy_surf = new Fl_Copy_Surface(target->as_window()->decorated_w(), target->as_window()->decorated_h()); Fl_Surface_Device::push_current(copy_surf); copy_surf->draw_decorated_window(target->as_window(), 0, 0); } else { copy_surf = new Fl_Copy_Surface(target->w()+10, target->h()+20); Fl_Surface_Device::push_current(copy_surf); fl_color(FL_YELLOW);fl_rectf(0,0,copy_surf->w(), copy_surf->h()); copy_surf->draw(target, 5, 10); } delete copy_surf; Fl_Surface_Device::pop_current(); } if (strcmp(operation, "Fl_Printer") == 0 || strcmp(operation, "Fl_PostScript_File_Device") == 0 || strcmp(operation, "Fl_PDF_File_Surface") == 0) { Fl_Paged_Device *p; int err; char *err_message = NULL; if (strcmp(operation, "Fl_Printer") == 0) { p = new Fl_Printer(); err = p->begin_job(1, NULL, NULL, &err_message); } else if (strcmp(operation, "Fl_PDF_File_Surface") == 0) { p = new Fl_PDF_File_Surface(); err = ((Fl_PDF_File_Surface*)p)->begin_job("FLTK.pdf", &err_message); } else { p = new Fl_PostScript_File_Device(); err = ((Fl_PostScript_File_Device*)p)->start_job(1); } if (!err) { p->begin_page(); Fl_Window *win = target->as_window(); int target_w = win ? win->decorated_w() : target->w(); int target_h = win ? win->decorated_h() : target->h(); int w, h; p->printable_rect(&w, &h); float s = 1, s_aux = 1; if (target_w > w) s_aux = float(w) / target_w; if (target_h > h) s = float(h) / target_h; if (s_aux < s) s = s_aux; p->scale(s); p->printable_rect(&w, &h); p->origin(w/2, h/2); if (win) p->draw_decorated_window(win, - target_w/2, - target_h/2); else p->draw(target, - target_w/2, - target_h/2); p->end_page(); p->end_job(); } else if (err > 1 && err_message) {fl_alert("%s", err_message); delete[] err_message;} delete p; } if (strcmp(operation, "Fl_SVG_File_Surface") == 0) { Fl_Native_File_Chooser fnfc; fnfc.title("Save a .svg file"); fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); fnfc.filter("SVG\t*.svg\n"); fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | Fl_Native_File_Chooser::USE_FILTER_EXT); if (!fnfc.show() ) { FILE *svg = fl_fopen(fnfc.filename(), "w"); if (svg) { int ww, wh; if (target->as_window()) { ww = target->as_window()->decorated_w(); wh = target->as_window()->decorated_h(); } else { ww = target->w(); wh = target->h(); } Fl_SVG_File_Surface surface(ww, wh, svg); if (surface.file()) { if (target->as_window()) surface.draw_decorated_window(target->as_window()); else surface.draw(target); if (surface.close()) fl_message("Error while writing to SVG file %s", fnfc.filename()); } } } } if (strcmp(operation, "fl_capture_window()") == 0) { Fl_Window *win = target->as_window() ? target->as_window() : target->window(); int X = target->as_window() ? 0 : target->x(); int Y = target->as_window() ? 0 : target->y(); Fl_RGB_Image *img = fl_capture_window(win, X, Y, target->w(), target->h()); if (img) { Fl_Window* g2 = new Fl_Window(img->w()+10, img->h()+10, "fl_capture_window()"); g2->color(FL_YELLOW); Fl_Box *b = new Fl_Box(FL_NO_BOX,5,5,img->w(), img->h(),0); b->image(img); g2->end(); g2->callback(close_tmp_win, img); g2->show(); } } if (strcmp(operation, "Fl_Image_Surface::mask()") == 0) { Fl_Image_Surface *surf = new Fl_Image_Surface(target->w(), target->h(), 1); Fl_Surface_Device::push_current(surf); fl_color(FL_BLACK); fl_rectf(0, 0, target->w(), target->h()); fl_color(FL_WHITE); fl_pie(0, 0, target->w(), target->h(), 0, 360); if (target->top_window() == target) { fl_color(FL_BLACK); int mini = int((target->w() < target->h() ? target->w() : target->h()) * 0.66); fl_pie(target->w()/2 - mini/2, target->h()/2 - mini/2, mini, mini, 0, 360); fl_color(FL_WHITE); fl_font(FL_TIMES_BOLD, 120); int dx, dy, l, h; fl_text_extents("FLTK", dx, dy, l, h); fl_draw("FLTK", target->w()/2 - l/2, target->h()/2 + h/2); } Fl_RGB_Image *mask = surf->image(); fl_color(FL_YELLOW); fl_rectf(0, 0, target->w(), target->h()); Fl_Surface_Device::pop_current(); surf->mask(mask); delete mask; Fl_Surface_Device::push_current(surf); surf->draw(target, 0, 0); mask = surf->image(); Fl_Surface_Device::pop_current(); delete surf; Fl_Window *win = new Fl_Window(mask->w(), mask->h(), operation); Fl_Box *box = new Fl_Box(0, 0, mask->w(), mask->h()); box->bind_image(mask); win->end(); win->show(); } } class My_Button:public Fl_Button { protected: void draw() FL_OVERRIDE { if (type() == FL_HIDDEN_BUTTON) return; Fl_Color col = value() ? selection_color() : color(); draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col); fl_color(FL_WHITE); fl_line_style(FL_SOLID,5); fl_line(x()+15,y()+10,x()+w()-15,y()+h()-23); fl_line(x()+w()-15,y()+10,x()+15,y()+h()-23); fl_line_style(0); draw_label(); } public: My_Button(int x, int y, int w, int h, const char * label = 0):Fl_Button(x,y,w,h,label){} }; void target_cb(Fl_Widget* wid, void *data) { target = (Fl_Widget*)data; } void operation_cb(Fl_Widget* wid, void *data) { operation = wid->label(); } int main(int argc, char ** argv) { //Fl::scheme("plastic"); Fl_Window * w2 = new Fl_Window(500,568,"Graphics test"); Fl_Group *c2 =new Fl_Group(3, 56, 494, 514 ); new MyWidget(10,140+16); new MyWidget2(110,80+16); new MyWidget3(220,140+16); new MyWidget4(330,70+16); new MyWidget5(140,270+16); make_image(); Fl_RGB_Image *rgb = new Fl_RGB_Image(image, width, height, 4); My_Button b_rgb(10,245+16,100,100,"RGB with alpha"); b_rgb.image(rgb); My_Button b_pixmap(10,345+16,100,100,"Pixmap"); Fl_Pixmap *pixmap = new Fl_Pixmap(porsche_xpm); b_pixmap.image(pixmap); My_Button b_bitmap(10,445+16,100,100,"Bitmap"); b_bitmap.labelcolor(FL_GREEN); b_bitmap.image(new Fl_Bitmap(sorceress_bits,sorceress_width,sorceress_height)); new Fl_Clock(360,230+16,120,120); Fl_Return_Button * ret = new Fl_Return_Button (360, 360+16, 120,30, "Return"); ret->deactivate(); Fl_Button but1(360, 390+16, 30, 30, "@->|"); but1.labelcolor(FL_DARK3); Fl_Button but2(390, 390+16, 30, 30, "@UpArrow"); but2.labelcolor(FL_DARK3); Fl_Button but3(420, 390+16, 30, 30, "@DnArrow"); but3.labelcolor(FL_DARK3); Fl_Button but4(450, 390+16, 30, 30, "@+"); but4.labelcolor(FL_DARK3); Fl_Button but5(360, 425+16, 120, 30, "Hello, World"); but5.labelfont(FL_BOLD|FL_ITALIC); but5.labeltype(FL_SHADOW_LABEL); but5.box(FL_ROUND_UP_BOX); Fl_Button but6(360, 460+16, 120, 30, "Plastic"); but6.box(FL_PLASTIC_UP_BOX); Fl_Group *group; { Fl_Group* o = new Fl_Group(360, 495+16, 120, 40); group=o; o->box(FL_UP_BOX); { Fl_Group* o = new Fl_Group(365, 500+16, 110, 30); o->box(FL_THIN_UP_FRAME); { Fl_Round_Button* o = new Fl_Round_Button(365, 500+16, 40, 30, "rad"); o->value(1); } { Fl_Check_Button* o = new Fl_Check_Button(410, 500+16, 60, 30, "check"); o->value(1); } o->end(); } o->end(); o->deactivate(); } Fl_Box tx(120,492+16,230,50,"Background is not printed because\nencapsulating group, which we are\n printing, has not set the box type"); tx.box(FL_SHADOW_BOX); tx.labelsize(12); tx.hide(); c2->end(); Fl_Radio_Round_Button *rb; Fl_Window *w3 = new Fl_Window(2,5,w2->w()-10,73); w3->box(FL_DOWN_BOX); Fl_Group *g1 = new Fl_Group(0,0,w3->w(),w3->h()); rb = new Fl_Radio_Round_Button(5,4,150,12, "Fl_Image_Surface"); rb->set(); rb->callback(operation_cb, NULL); operation = rb->label(); rb->labelsize(12); rb = new Fl_Radio_Round_Button(170,4,150,12, "Fl_Copy_Surface"); rb->callback(operation_cb, NULL); rb->labelsize(12); rb = new Fl_Radio_Round_Button(5,17,150,12, "Fl_Printer"); rb->callback(operation_cb, NULL); rb->labelsize(12); rb = new Fl_Radio_Round_Button(170,17,150,12, "Fl_PostScript_File_Device"); rb->callback(operation_cb, NULL); rb->labelsize(12); rb = new Fl_Radio_Round_Button(5,30,150,12, "Fl_PDF_File_Surface"); rb->callback(operation_cb, NULL); rb->labelsize(12); rb = new Fl_Radio_Round_Button(170,30,150,12, "Fl_SVG_File_Surface"); rb->callback(operation_cb, NULL); rb->labelsize(12); rb = new Fl_Radio_Round_Button(5,43,150,12, "fl_capture_window()"); rb->callback(operation_cb, NULL); rb->labelsize(12); rb = new Fl_Radio_Round_Button(170,43,150,12, "Fl_Image_Surface::mask()"); rb->callback(operation_cb, NULL); rb->labelsize(12); g1->end(); Fl_Group *g2 = new Fl_Group(0,0,w3->w(),w3->h()); Fl_Box *box = new Fl_Box(FL_BORDER_BOX, 4, 55, 340, 16, NULL); box->color(FL_LIGHT3); rb = new Fl_Radio_Round_Button(5,57,140,12, "Decorated window"); rb->labelsize(12); rb->set(); rb->callback(target_cb, w2); target = w2; rb = new Fl_Radio_Round_Button(160,57,100,12, "Sub-window"); rb->labelsize(12); rb->callback(target_cb, w3); rb = new Fl_Radio_Round_Button(275,57,60,12, "Group"); rb->labelsize(12);rb->callback(target_cb, group); g2->end(); Fl_Button *b4 = new Fl_Button(380, (w3->h() - 25)/2, 100, 25, "GO"); b4->callback((Fl_Callback*)copy,NULL); w3->end(); w2->end(); Fl_RGB_Image *rgba_icon = new Fl_RGB_Image(pixmap); Fl_Window::default_icon(rgba_icon); // w2->icon(rgba_icon); delete rgba_icon; w2->show(argc, argv); Fl::run(); delete pixmap; delete b_bitmap.image(); delete rgb; return 0; } fltk-1.4.3/test/preferences.fl0000644000175000017500000003206115004135251016412 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 i18n_type 1 i18n_include {} i18n_conditional {} i18n_gnu_function gettext i18n_gnu_static_function gettext_noop header_name {.h} code_name {.cxx} comment {About test/preferences: The preferences app shows two features of FLTK and FLUID. The Fl_Preferences class is used as a storage for user settings between app launches. Fl_Preferences can store small amounts of arbitrary data in an .ini file format which can be retrieved again at the next app launch. The FLUID setup uses GNU gettext for internationalisation (i18n). FLUID finds the texts that need to be translated and writes them into .po files that can be processed by the GNU gettext tools. FLUID produces source code that will translate all text into the current locale when generating the UI. In this small example, 'getttext' is only emulated.} {in_source not_in_header } decl {\#include } {public local } decl {\#include } {public local } decl {\#include } {private local } decl {\#include } {private local } decl {\#include } {private local } decl {\#define _(text) gettext(text)} {private local } decl {int g_language = 0;} { comment {Current languages are: 0 = English 1 = German} private global } decl {const char *project = "fltk.org";} {private local } decl {const char *application = "test/preferences";} {private local } Function {gettext(const char *text)} { comment {This is a minimal implementation of the GNU gettext API for systems that don't have GNU libintl library.} open return_type {const char*} } { code {static const char* translation_table[][2] = { { "Alarm at:", "Wecken um:" }, { "Bread:", "Brot:" }, { "Breakfast:", "Frühstück:" }, { "Cancel", "Abbrechen" }, { "Copy", "Kopieren" }, { "Cut", "Ausschneiden" }, { "Drink:", "Getränk:" }, { "English", "Englisch" }, { "German", "Deutsch" }, { "Get Up:", "Aufstehen:" }, { "Language:", "Sprache:" }, { "My Preferences", "Meine Vorlieben" }, { "NY Times", "Der Spiegel" }, { "Newspaper:", "Tageszeitung:" }, { "OK", "OK" }, { "Paste", "Einfügen" }, { "Please restart the app to use your new language setting.", "Bitte starten Sie die App erneut um Ihre Spracheinstellung zu nutzen." }, { "Wear:", "Schuhwerk:" }, { "a.m.", "früh" }, { "bare foot", "barfuß" }, { "brush teeth", "Zähne putzen" }, { "coffee", "Kaffee" }, { "eggs", "Eier" }, { "flip flops", "Schlappen" }, { "juice", "Saft" }, { "left side", "linke Seite" }, { "min.", "Min." }, { "of the bed", "vom Bett" }, { "p.m.", "spät" }, { "right side", "rechte Seite" }, { "rye", "Roggen" }, { "sandals", "Sandalen" }, { "shave", "rasieren" }, { "shoes", "Schuhe" }, { "shower", "duschen" }, { "sourdough", "Sauerteig" }, { "tea", "Tee" }, { "wheat", "Weizen" }, { "white", "Weißbrot" }, { "with butter", "mit Butter" }, { "with milk", "mit Milch" }, }; int lang = g_language; int i, n = 41; const char *found = 0L; // As this is just a minimal demo, I did not implement binary search. for (i=0; i} } { MenuItem {} { label English xywh {20 20 100 20} } MenuItem {} { label German xywh {20 20 100 20} } } } code {readPrefs();} {} } Function {readLanguagePrefs()} { comment {Read the language setting before we create the UI.} open return_type void } { code {Fl_Preferences app( Fl_Preferences::USER_L, project, application ); app.get( "language", g_language, 0 );} {} } Function {readPrefs()} {open return_type void } { code {int boolValue; int intValue; char buffer[80]; double doubleValue; char path[ FL_PATH_MAX ]; Fl_Preferences::Root root = Fl_Preferences::filename(path, FL_PATH_MAX, Fl_Preferences::USER_L, project, application); if (root == Fl_Preferences::UNKNOWN_ROOT_TYPE) { printf("Location of future Preferences file not found.\\n"); } else { printf("Preferences file will be located at:\\n%s\\n", path); } Fl_Preferences app( Fl_Preferences::USER_L, project, application ); root = app.filename(path, FL_PATH_MAX); if (root == Fl_Preferences::UNKNOWN_ROOT_TYPE) { printf("Location of app Preferences file not found.\\n"); } else if (root == Fl_Preferences::MEMORY) { printf("App Preferences are memory mapped.\\n"); } else { printf("App Preferences file is actually located at:\\n%s\\n", path); } app.getUserdataPath( path, sizeof(path) ); if (path[0]) { printf("Preferences user data directory is located at:\\n%s\\n", path); } else { printf("Location of Preferences user data directory not found.\\n"); } wLanguage->value( g_language ); Fl_Preferences bed( app, "Bed" ); bed.get( "alarm", buffer, "8:00", 79 ); wAlarm->value( buffer ); bed.get( "ampm", intValue, 0 ); wAmPm->value( intValue ); bed.get( "wear", intValue, 1 ); wWear->value( intValue ); int side; bed.get( "side", side, 2 ); if ( side == 1 ) wLeft->value( 1 ); if ( side == 2 ) wRight->value( 1 ); int tasks; bed.get( "taskFlags", tasks, 0x05 ); if ( tasks & 0x01 ) wShower->value( 1 ); if ( tasks & 0x02 ) wShave->value( 1 ); if ( tasks & 0x04 ) wBrush->value( 1 ); Fl_Preferences eat( app, "Breakfast" ); eat.get( "drink", intValue, 1 ); wDrink->value( intValue ); eat.get( "wMilk", boolValue, 0 ); wMilk->value( boolValue ); eat.get( "bread", intValue, 0 ); wBread->value( intValue ); eat.get( "wButter", boolValue, 1 ); wButter->value( boolValue ); eat.get( "nEggs", intValue, 2 ); sprintf( buffer, "%d", intValue ); wEggs->value( buffer ); eat.get( "minutes", doubleValue, 3.2 ); wMinutes->value( doubleValue ); char *flexBuffer; eat.get( "newspaper", flexBuffer, gettext("NY Times") ); wPaper->value( flexBuffer ); if ( flexBuffer ) free( flexBuffer ); eat.get( "foo", buffer, "bar", 80 ); /** sample code only: Fl_Preferences prev( app, "PreviousStarts" ); { int i, n; prev.get( "n", n, 0 ); for ( i=0; ivalue() ); Fl_Preferences bed( app, "Bed" ); bed.set( "alarm", wAlarm->value() ); bed.set( "ampm", wAmPm->value() ); bed.set( "wear", wWear->value() ); int side = 0; if ( wLeft->value() ) side = 1; if ( wRight->value() ) side = 2; bed.set( "side", side ); int tasks = 0; if ( wShower->value() ) tasks |= 0x01; if ( wShave->value() ) tasks |= 0x02; if ( wBrush->value() ) tasks |= 0x04; bed.set( "taskFlags", tasks ); Fl_Preferences eat( app, "Breakfast" ); eat.set( "drink", wDrink->value() ); eat.set( "wMilk", wMilk->value() ); eat.set( "bread", wBread->value() ); eat.set( "wButter", wButter->value() ); eat.set( "nEggs", wEggs->value() ); eat.set( "minutes", wMinutes->value() ); eat.set( "newspaper", wPaper->value() ); eat.set( "foo", "bar\\nfly\\rBackslash: \\\\ and bell: \\007 and delete: \\177\\n" ); eat.set( Fl_Preferences::Name( 3 ), "Test3" ); /* sample: create a sub-sub-group */ Fl_Preferences eatMore( eat, "More" ); eatMore.set( "more", "stuff" ); /* all the following searches should return 1 */ int sum = 0; sum += app.groupExists( "Breakfast" ); /* find 'eat' relative to 'app' */ sum += app.groupExists( "Breakfast/More" ); /* find 'eat.eatMore' relative to 'app' */ sum += app.groupExists( "./Breakfast/More" ); /* find 'eat.eatMore' relative to Preferences */ sum += eat.groupExists( "More" ); /* find 'eatMore' relative to 'eat' */ sum += eat.groupExists( "./Breakfast/More" ); /* find 'eat.eatMore' relative to Preferences */ sum += eat.groupExists( "." ); /* find myself ('eat') */ sum += eat.groupExists( "./" ); /* find the topmost group ('app') */ if ( sum != 7 ) fl_message( "Assertion failed:\\nNot all group entries were found!" ); /* sample code only: */ // unsigned int hex = 0xefbeadde; // unsigned int size_of_bed = sizeof( bed ); // size of Fl_Preferences 'bed' // eat.set( "binFoo", (void*)&hex, sizeof( unsigned int ) ); // eat.set( "SizeOfBed", (int)size_of_bed ); // eat.set( "Prefs_Bed", (void*)&bed, sizeof( bed ) );} {} } fltk-1.4.3/test/gl_overlay.cxx0000644000175000017500000000676215004135251016466 0ustar albrechtalbrecht// // OpenGL overlay test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #if !HAVE_GL #include class shape_window : public Fl_Box { public: int sides; shape_window(int x,int y,int w,int h,const char *l=0) :Fl_Box(FL_DOWN_BOX,x,y,w,h,l){ label("This demo does\nnot work without GL"); } }; #else #include #include class shape_window : public Fl_Gl_Window { void draw() FL_OVERRIDE; void draw_overlay() FL_OVERRIDE; public: int sides; int overlay_sides; shape_window(int x,int y,int w,int h,const char *l=0); }; shape_window::shape_window(int x,int y,int w,int h,const char *l) : Fl_Gl_Window(x,y,w,h,l) { sides = overlay_sides = 3; } void shape_window::draw() { // the valid() property may be used to avoid reinitializing your // GL transformation for each redraw: if (!valid()) { valid(1); glLoadIdentity(); glViewport(0,0,pixel_w(),pixel_h()); } // draw an amazing but slow graphic: glClear(GL_COLOR_BUFFER_BIT); // for (int j=1; j<=1000; j++) { glBegin(GL_POLYGON); for (int j=0; jsides = int(((Fl_Slider *)o)->value()); sw->redraw(); } #if HAVE_GL void overlay_sides_cb(Fl_Widget *o, void *p) { shape_window *sw = (shape_window *)p; sw->overlay_sides = int(((Fl_Slider *)o)->value()); sw->redraw_overlay(); } #endif #include int main(int argc, char **argv) { Fl::use_high_res_GL(1); Fl_Window window(300, 370); shape_window sw(10, 75, window.w()-20, window.h()-90); //sw.mode(FL_RGB); window.resizable(&sw); Fl_Hor_Slider slider(60, 5, window.w()-70, 30, "Sides:"); slider.align(FL_ALIGN_LEFT); slider.callback(sides_cb,&sw); slider.value(sw.sides); slider.step(1); slider.bounds(3,40); Fl_Hor_Slider oslider(60, 40, window.w()-70, 30, "Overlay:"); oslider.align(FL_ALIGN_LEFT); #if HAVE_GL oslider.callback(overlay_sides_cb,&sw); oslider.value(sw.overlay_sides); #endif oslider.step(1); oslider.bounds(3,40); window.end(); window.show(argc,argv); #if HAVE_GL printf("Can do overlay = %d\n", sw.can_do_overlay()); sw.show(); sw.redraw_overlay(); #else sw.show(); #endif return Fl::run(); } fltk-1.4.3/test/grid_buttons.cxx0000644000175000017500000000411715004135251017016 0ustar albrechtalbrecht// // Fl_Grid demo program for the Fast Light Tool Kit (FLTK). // // Copyright 2021 by Albrecht Schlosser // Copyright 2022-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Q: How to achieve a spaced out layout? // https://groups.google.com/g/fltkgeneral/c/haet7hOQR0g // A: We use an Fl_Grid with 1 x 7 cells (5 buttons) as requested: // [New] [Options] [About] [Help] [Quit] #include #include #include #include int main(int argc, char **argv) { Fl_Double_Window *win = new Fl_Double_Window(460, 200, "Fl_Grid Row with 5 Buttons"); Fl_Grid *grid = new Fl_Grid(0, 0, win->w(), 50); grid->layout(1, 7, 10, 10); // create the buttons Fl_Button *b0 = new Fl_Button(0, 0, 80, 30, "New"); Fl_Button *b1 = new Fl_Button(0, 0, 80, 30, "Options"); Fl_Button *b3 = new Fl_Button(0, 0, 80, 30, "About"); Fl_Button *b4 = new Fl_Button(0, 0, 80, 30, "Help"); Fl_Button *b6 = new Fl_Button(0, 0, 80, 30, "Quit"); grid->end(); // assign buttons to grid positions grid->widget(b0, 0, 0); grid->widget(b1, 0, 1); grid->col_gap(1, 0); grid->widget(b3, 0, 3); grid->widget(b4, 0, 4); grid->col_gap(4, 0); grid->widget(b6, 0, 6); // set column weights for resizing (only empty columns resize) int weight[] = { 0, 0, 50, 0, 0, 50, 0 }; grid->col_weight(weight, 7); grid->end(); // grid->show_grid(1); // enable to display grid helper lines // add content ... Fl_Group *g1 = new Fl_Group(0, 50, win->w(), win->h() - 50); // add more widgets ... win->end(); win->resizable(g1); win->size_range(win->w(), 100); win->show(argc, argv); int ret = Fl::run(); delete win; // not necessary but useful to test for memory leaks return ret; } fltk-1.4.3/test/keyboard_ui.fl0000644000175000017500000004273015004135251016412 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} Function {make_window()} {open } { Fl_Window my_window {open xywh {448 339 495 215} type Double code0 {\#include "keyboard.h"} class MyWindow visible } { Fl_Output key_output { label {Fl::event_key():} xywh {15 20 170 30} labelsize 9 align 5 } Fl_Output text_output { label {Fl::event_text():} xywh {195 20 190 30} labelsize 9 align 5 } Fl_Button {} { label {Esc } user_data FL_Escape user_data_type {void*} callback key_cb xywh {15 70 20 20} labelsize 8 } Fl_Button {} { label F1 user_data {FL_F+1} user_data_type {void*} callback key_cb xywh {50 70 20 20} labelsize 10 } Fl_Button {} { label F2 user_data {FL_F+2} user_data_type {void*} callback key_cb xywh {70 70 20 20} labelsize 10 } Fl_Button {} { label F3 user_data {FL_F+3} user_data_type {void*} callback key_cb xywh {90 70 20 20} labelsize 10 } Fl_Button {} { label F4 user_data {FL_F+4} user_data_type {void*} callback key_cb xywh {110 70 20 20} labelsize 10 } Fl_Button {} { label F5 user_data {FL_F+5} user_data_type {void*} callback key_cb xywh {140 70 20 20} labelsize 10 } Fl_Button {} { label F6 user_data {FL_F+6} user_data_type {void*} callback key_cb xywh {160 70 20 20} labelsize 10 } Fl_Button {} { label F7 user_data {FL_F+7} user_data_type {void*} callback key_cb xywh {180 70 20 20} labelsize 10 } Fl_Button {} { label F8 user_data {FL_F+8} user_data_type {void*} callback key_cb xywh {200 70 20 20} labelsize 10 } Fl_Button {} { label F9 user_data {FL_F+9} user_data_type {void*} callback key_cb xywh {230 70 20 20} labelsize 10 } Fl_Button {} { label F10 user_data {FL_F+10} user_data_type {void*} callback key_cb xywh {250 70 20 20} labelsize 10 } Fl_Button {} { label F11 user_data {FL_F+11} user_data_type {void*} callback key_cb xywh {270 70 20 20} labelsize 10 } Fl_Button {} { label F12 user_data {FL_F+12} user_data_type {void*} callback key_cb xywh {290 70 20 20} labelsize 10 } Fl_Button {} { label {Print } user_data FL_Print user_data_type {void*} callback key_cb xywh {325 70 20 20} labelsize 8 } Fl_Button {} { label {Sclk } user_data FL_Scroll_Lock user_data_type {void*} callback key_cb xywh {345 70 20 20} labelsize 8 } Fl_Button {} { label {Paus } user_data FL_Pause user_data_type {void*} callback key_cb xywh {365 70 20 20} labelsize 8 } Fl_Button {} { label Help user_data FL_Help user_data_type {void*} callback key_cb xywh {400 70 20 20} labelsize 8 } Fl_Button {} { label {=} user_data {FL_KP+'='} user_data_type {void*} callback key_cb xywh {420 70 20 20} labelsize 10 } Fl_Dial roller_x { label {x:} callback wheel_cb xywh {440 70 20 20} box ROUND_UP_BOX selection_color 49 labelsize 9 align 5 step 0.1 } Fl_Dial roller_y { label {y:} callback wheel_cb xywh {460 70 20 20} box ROUND_UP_BOX selection_color 49 labelsize 9 align 5 step 0.1 } Fl_Button {} { label {`} callback key_cb xywh {15 100 20 20} labelsize 10 } Fl_Button {} { label 1 callback key_cb xywh {35 100 20 20} labelsize 10 } Fl_Button {} { label 2 callback key_cb xywh {55 100 20 20} labelsize 10 } Fl_Button {} { label 3 callback key_cb xywh {75 100 20 20} labelsize 10 } Fl_Button {} { label 4 callback key_cb xywh {95 100 20 20} labelsize 10 } Fl_Button {} { label 5 callback key_cb xywh {115 100 20 20} labelsize 10 } Fl_Button {} { label 6 callback key_cb xywh {135 100 20 20} labelsize 10 } Fl_Button {} { label 7 callback key_cb xywh {155 100 20 20} labelsize 10 } Fl_Button {} { label 8 callback key_cb xywh {175 100 20 20} labelsize 10 } Fl_Button {} { label 9 callback key_cb xywh {195 100 20 20} labelsize 10 } Fl_Button {} { label 0 callback key_cb xywh {215 100 20 20} labelsize 10 } Fl_Button {} { label {-} callback key_cb xywh {235 100 20 20} labelsize 10 } Fl_Button {} { label {=} callback key_cb xywh {255 100 20 20} labelsize 10 } Fl_Button {} { label Bksp user_data FL_BackSpace user_data_type {void*} callback key_cb xywh {275 100 35 20} labeltype SHADOW_LABEL labelsize 8 align 20 } Fl_Button {} { label {Ins } user_data FL_Insert user_data_type {void*} callback key_cb xywh {325 100 20 20} labelsize 8 } Fl_Button {} { label Home user_data FL_Home user_data_type {void*} callback key_cb xywh {345 100 20 20} labelsize 8 } Fl_Button {} { label {pgup } user_data FL_Page_Up user_data_type {void*} callback key_cb xywh {365 100 20 20} labelsize 8 } Fl_Button {} { label Num user_data FL_Num_Lock user_data_type {void*} callback key_cb xywh {400 100 20 20} labelsize 8 } Fl_Button {} { label {/} user_data {FL_KP+'/'} user_data_type {void*} callback key_cb xywh {420 100 20 20} labelsize 10 } Fl_Button {} { label {*} user_data {FL_KP+'*'} user_data_type {void*} callback key_cb xywh {440 100 20 20} labelsize 10 } Fl_Button {} { label {-} user_data {FL_KP+'-'} user_data_type {void*} callback key_cb xywh {460 100 20 20} labelsize 10 } Fl_Button {} { label Tab user_data FL_Tab user_data_type {void*} callback key_cb xywh {15 120 27 20} labelsize 8 align 20 } Fl_Button {} { label Q callback key_cb xywh {42 120 20 20} labelsize 10 } Fl_Button {} { label W callback key_cb xywh {62 120 20 20} labelsize 10 } Fl_Button {} { label E callback key_cb xywh {82 120 20 20} labelsize 10 } Fl_Button {} { label R callback key_cb xywh {102 120 20 20} labelsize 10 } Fl_Button {} { label T callback key_cb xywh {122 120 20 20} labelsize 10 } Fl_Button {} { label Y callback key_cb xywh {142 120 20 20} labelsize 10 } Fl_Button {} { label U callback key_cb xywh {162 120 20 20} labelsize 10 } Fl_Button {} { label I callback key_cb xywh {182 120 20 20} labelsize 10 } Fl_Button {} { label O callback key_cb xywh {202 120 20 20} labelsize 10 } Fl_Button {} { label P callback key_cb xywh {222 120 20 20} labelsize 10 } Fl_Button {} { label {[} callback key_cb xywh {242 120 20 20} labelsize 10 } Fl_Button {} { label {]} callback key_cb xywh {262 120 20 20} labelsize 10 } Fl_Button {} { label {\\} callback key_cb xywh {282 120 28 20} labelsize 10 align 20 } Fl_Button {} { label {Del } user_data FL_Delete user_data_type {void*} callback key_cb xywh {325 120 20 20} labelsize 8 } Fl_Button {} { label {End } user_data FL_End user_data_type {void*} callback key_cb xywh {345 120 20 20} labelsize 8 } Fl_Button {} { label {pgdn } user_data FL_Page_Down user_data_type {void*} callback key_cb xywh {365 120 20 20} labelsize 8 } Fl_Button {} { label 7 user_data {FL_KP+'7'} user_data_type {void*} callback key_cb xywh {400 120 20 20} labelsize 10 } Fl_Button {} { label 8 user_data {FL_KP+'8'} user_data_type {void*} callback key_cb xywh {420 120 20 20} labelsize 10 } Fl_Button {} { label 9 user_data {FL_KP+'9'} user_data_type {void*} callback key_cb xywh {440 120 20 20} labelsize 10 } Fl_Button {} { label {+} user_data {FL_KP+'+'} user_data_type {void*} callback key_cb xywh {460 120 20 40} labelsize 10 align 17 } Fl_Button {} { label Lock user_data FL_Caps_Lock user_data_type {void*} callback key_cb xywh {15 140 36 20} labelsize 8 align 20 } Fl_Button {} { label A callback key_cb xywh {51 140 20 20} labelsize 10 } Fl_Button {} { label S callback key_cb xywh {71 140 20 20} labelsize 10 } Fl_Button {} { label D callback key_cb xywh {91 140 20 20} labelsize 10 } Fl_Button {} { label F callback key_cb xywh {111 140 20 20} labelsize 10 } Fl_Button {} { label G callback key_cb xywh {131 140 20 20} labelsize 10 } Fl_Button {} { label H callback key_cb xywh {151 140 20 20} labelsize 10 } Fl_Button {} { label J callback key_cb xywh {171 140 20 20} labelsize 10 } Fl_Button {} { label K callback key_cb xywh {191 140 20 20} labelsize 10 } Fl_Button {} { label L callback key_cb xywh {211 140 20 20} labelsize 10 } Fl_Button {} { label {;} callback key_cb xywh {231 140 20 20} labelsize 10 } Fl_Button {} { label {'} callback key_cb xywh {251 140 20 20} labelsize 10 } Fl_Button {} { label Enter user_data FL_Enter user_data_type {void*} callback key_cb xywh {271 140 39 20} labelsize 8 align 20 } Fl_Button {} { label 4 user_data {FL_KP+'4'} user_data_type {void*} callback key_cb xywh {400 140 20 20} labelsize 10 } Fl_Button {} { label 5 user_data {FL_KP+'5'} user_data_type {void*} callback key_cb xywh {420 140 20 20} labelsize 10 } Fl_Button {} { label 6 user_data {FL_KP+'6'} user_data_type {void*} callback key_cb xywh {440 140 20 20} labelsize 10 } Fl_Button {} { label Shift user_data FL_Shift_L user_data_type {void*} callback key_cb xywh {15 160 45 20} labelsize 8 align 20 } Fl_Button {} { label Z callback key_cb xywh {60 160 20 20} labelsize 10 } Fl_Button {} { label X callback key_cb xywh {80 160 20 20} labelsize 10 } Fl_Button {} { label C callback key_cb xywh {100 160 20 20} labelsize 10 } Fl_Button {} { label V callback key_cb xywh {120 160 20 20} labelsize 10 } Fl_Button {} { label B callback key_cb xywh {140 160 20 20} labelsize 10 } Fl_Button {} { label N callback key_cb xywh {160 160 20 20} labelsize 10 } Fl_Button {} { label M callback key_cb xywh {180 160 20 20} labelsize 10 } Fl_Button {} { label {,} callback key_cb xywh {200 160 20 20} labelsize 10 } Fl_Button {} { label {.} callback key_cb xywh {220 160 20 20} labelsize 10 } Fl_Button {} { label {/} callback key_cb xywh {240 160 20 20} labelsize 10 } Fl_Button {} { label Shift user_data FL_Shift_R user_data_type {void*} callback key_cb xywh {260 160 50 20} labelsize 8 align 20 } Fl_Button {} { label {@8->} user_data FL_Up user_data_type {void*} callback key_cb xywh {345 160 20 20} labeltype SHADOW_LABEL labelsize 10 labelcolor 47 } Fl_Button {} { label 1 user_data {FL_KP+'1'} user_data_type {void*} callback key_cb xywh {400 160 20 20} labelsize 10 } Fl_Button {} { label 2 user_data {FL_KP+'2'} user_data_type {void*} callback key_cb xywh {420 160 20 20} labelsize 10 } Fl_Button {} { label 3 user_data {FL_KP+'3'} user_data_type {void*} callback key_cb xywh {440 160 20 20} labelsize 10 } Fl_Button {} { user_data FL_KP_Enter user_data_type {void*} callback key_cb xywh {460 160 20 40} } Fl_Button {} { label Ctrl user_data FL_Control_L user_data_type {void*} callback key_cb xywh {15 180 30 20} labelsize 8 align 20 } Fl_Button {} { label {Meta } user_data FL_Meta_L user_data_type {void*} callback key_cb xywh {45 180 30 20} labelsize 8 } Fl_Button {} { label {Alt } user_data FL_Alt_L user_data_type {void*} callback key_cb xywh {75 180 30 20} labelsize 8 } Fl_Button {} { user_data {' '} user_data_type {void*} callback key_cb xywh {105 180 85 20} labelsize 10 } Fl_Button {} { label {Alt } user_data FL_Alt_R user_data_type {void*} callback key_cb xywh {190 180 30 20} labelsize 8 } Fl_Button {} { label {Meta } user_data FL_Meta_R user_data_type {void*} callback key_cb xywh {220 180 30 20} labelsize 8 } Fl_Button {} { label {Menu } user_data FL_Menu user_data_type {void*} callback key_cb xywh {250 180 30 20} labelsize 8 } Fl_Button {} { label Ctrl user_data FL_Control_R user_data_type {void*} callback key_cb xywh {280 180 30 20} labelsize 8 align 20 } Fl_Button {} { label {@4->} user_data FL_Left user_data_type {void*} callback key_cb xywh {325 180 20 20} labeltype SHADOW_LABEL labelsize 10 labelcolor 47 } Fl_Button {} { label {@2->} user_data FL_Down user_data_type {void*} callback key_cb xywh {345 180 20 20} labeltype SHADOW_LABEL labelsize 10 labelcolor 47 } Fl_Button {} { label {@6->} user_data FL_Right user_data_type {void*} callback key_cb xywh {365 180 20 20} labeltype SHADOW_LABEL labelsize 10 labelcolor 47 } Fl_Button {} { label 0 user_data {FL_KP+'0'} user_data_type {void*} callback key_cb xywh {400 180 40 20} labelsize 10 align 20 } Fl_Button {} { label {.} user_data {FL_KP+'.'} user_data_type {void*} callback key_cb xywh {440 180 20 20} labelsize 10 } Fl_Box {} { label {Fl::event_state():} selected xywh {400 15 80 0} labelsize 9 align 5 } Fl_Button {} { label {shift } user_data FL_SHIFT user_data_type {void*} callback shift_cb xywh {400 15 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label {lock } user_data FL_CAPS_LOCK user_data_type {void*} callback shift_cb xywh {420 15 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label ctrl user_data FL_CTRL user_data_type {void*} callback shift_cb xywh {440 15 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label alt user_data FL_ALT user_data_type {void*} callback shift_cb xywh {460 15 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label num user_data FL_NUM_LOCK user_data_type {void*} callback shift_cb xywh {400 25 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label {?} user_data 0x20 user_data_type {void*} callback shift_cb xywh {420 25 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label {meta } user_data FL_META user_data_type {void*} callback shift_cb xywh {440 25 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label sclk user_data FL_SCROLL_LOCK user_data_type {void*} callback shift_cb xywh {460 25 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label b1 user_data FL_BUTTON1 user_data_type {void*} callback shift_cb xywh {400 35 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label b2 user_data FL_BUTTON2 user_data_type {void*} callback shift_cb xywh {420 35 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label b3 user_data FL_BUTTON3 user_data_type {void*} callback shift_cb xywh {440 35 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label bck user_data FL_BUTTON4 user_data_type {void*} callback shift_cb xywh {460 35 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label fwd user_data FL_BUTTON5 user_data_type {void*} callback shift_cb xywh {400 45 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label {?} user_data 0x2000 user_data_type {void*} callback shift_cb xywh {420 45 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label {?} user_data 0x4000 user_data_type {void*} callback shift_cb xywh {440 45 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } Fl_Button {} { label {?} user_data 0x8000 user_data_type {void*} callback shift_cb xywh {460 45 20 10} box THIN_UP_BOX selection_color 3 labelsize 8 } } } fltk-1.4.3/test/offscreen.cxx0000644000175000017500000001563415004135251016273 0ustar albrechtalbrecht// // Offscreen drawing test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* Standard headers */ #include #include // time() - used to seed rand() /* Fltk headers */ #include #include #include #include #include static Fl_Double_Window *main_window = 0; // constants to define the view etc. static const int offscreen_size = 1000; static const int win_size = 512; static const int first_useful_color = 56; static const int last_useful_color = 255; static const int num_iterations = 300; static const int max_line_width = 9; static const double delta_time = 0.1; /*****************************************************************************/ class oscr_box : public Fl_Box { public: oscr_box(int x, int y, int w, int h); void oscr_drawing(void); bool has_oscr() const { if (oscr) return true; return false; } private: void draw() FL_OVERRIDE; int handle(int event) FL_OVERRIDE; // Generate "random" values for the line display double random_val(int v) const { double dr = (double)(rand()) / (double)(RAND_MAX); // 0.0 to 1.0 dr = dr * (double)(v); // 0 to v return dr; } // The offscreen surface Fl_Offscreen oscr; // variables used to handle "dragging" of the view within the box int x1, y1; // drag start positions int xoff, yoff; // drag offsets int drag_state; // non-zero if drag is in progress int page_x, page_y; // top left of view area // Width and height of the offscreen surface int offsc_w, offsc_h; int iters; // Must be set on first pass! float scale; // current screen scaling factor value }; /*****************************************************************************/ oscr_box::oscr_box(int x, int y, int w, int h) : Fl_Box(x, y, w, h), // base box oscr(0), // offscreen is not set at start x1(0), y1(0), drag_state(0), // not dragging view page_x((offscreen_size - win_size) / 2), // roughly centred in view page_y((offscreen_size - win_size) / 2), offsc_w(0), offsc_h(0), // offscreen size - initially none iters(num_iterations + 1) { } // Constructor /*****************************************************************************/ void oscr_box::draw() { int wd = w(); int ht = h(); int xo = x(); int yo = y(); fl_color(fl_gray_ramp(19)); // a light grey background shade fl_rectf(xo, yo, wd, ht); // fill the box with this colour // then add the offscreen on top of the grey background if (has_oscr()) // offscreen exists { if (scale != Fl_Graphics_Driver::default_driver().scale()) { // the screen scaling factor has changed fl_rescale_offscreen(oscr); scale = Fl_Graphics_Driver::default_driver().scale(); } fl_copy_offscreen(xo, yo, wd, ht, oscr, page_x, page_y); } else // create offscreen { // some hosts may need a valid window context to base the offscreen on... main_window->make_current(); offsc_w = offscreen_size; offsc_h = offscreen_size; oscr = fl_create_offscreen(offsc_w, offsc_h); scale = Fl_Graphics_Driver::default_driver().scale(); } } // draw method /*****************************************************************************/ int oscr_box::handle(int ev) { int ret = Fl_Box::handle(ev); // handle dragging of visible page area - if a valid context exists if (has_oscr()) { switch (ev) { case FL_ENTER: main_window->cursor(FL_CURSOR_MOVE); ret = 1; break; case FL_LEAVE: main_window->cursor(FL_CURSOR_DEFAULT); ret = 1; break; case FL_PUSH: x1 = Fl::event_x_root(); y1 = Fl::event_y_root(); drag_state = 1; // drag ret = 1; break; case FL_DRAG: if (drag_state == 1) // dragging page { int x2 = Fl::event_x_root(); int y2 = Fl::event_y_root(); xoff = x1 - x2; yoff = y1 - y2; x1 = x2; y1 = y2; page_x += xoff; page_y += yoff; // check the page bounds if (page_x < -w()) { page_x = -w(); } else if (page_x > offsc_w) { page_x = offsc_w; } if (page_y < -h()) { page_y = -h(); } else if (page_y > offsc_h) { page_y = offsc_h; } redraw(); } ret = 1; break; case FL_RELEASE: drag_state = 0; ret = 1; break; default: break; } } return ret; } // handle /*****************************************************************************/ void oscr_box::oscr_drawing(void) { Fl_Color col; static int icol = first_useful_color; static int ox = (offscreen_size / 2); static int oy = (offscreen_size / 2); if (!has_oscr()) { return; // no valid offscreen, nothing to do here } fl_begin_offscreen(oscr); /* Open the offscreen context for drawing */ { if (iters > num_iterations) // clear the offscreen and start afresh { fl_color(FL_WHITE); fl_rectf(0, 0, offsc_w, offsc_h); iters = 0; } iters++; icol++; if (icol > last_useful_color) { icol = first_useful_color; } col = static_cast(icol); fl_color(col); // set the colour double drx = random_val(offsc_w); double dry = random_val(offsc_h); double drt = random_val(max_line_width); int ex = static_cast(drx); int ey = static_cast(dry); fl_line_style(FL_SOLID, static_cast(drt)); fl_line(ox, oy, ex, ey); ox = ex; oy = ey; } fl_line_style(FL_SOLID, 0); fl_end_offscreen(); // close the offscreen context redraw(); } // oscr_drawing /*****************************************************************************/ static oscr_box *os_box = 0; // a widget to view the offscreen with /*****************************************************************************/ static void oscr_anim(void *) { os_box->oscr_drawing(); // if the offscreen exists, draw something Fl::repeat_timeout(delta_time, oscr_anim); } // oscr_anim /*****************************************************************************/ int main(int argc, char **argv) { int dim1 = win_size; main_window = new Fl_Double_Window(dim1, dim1, "Offscreen demo"); main_window->begin(); dim1 -= 10; os_box = new oscr_box(5, 5, dim1, dim1); main_window->end(); main_window->resizable(os_box); main_window->show(argc, argv); srand((unsigned int)time(NULL)); // seed the random sequence generator Fl::add_timeout(delta_time, oscr_anim); return Fl::run(); } // main fltk-1.4.3/test/grid_dialog.cxx0000644000175000017500000001231315004135251016554 0ustar albrechtalbrecht// // Fl_Grid based dialog window for the Fast Light Tool Kit (FLTK). // // Copyright 2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // This demo program builds a flexible layout of a dialog similar // to fl_ask(), fl_choice(), and others. // // For buttons we use an Fl_Grid with 2 rows and columns: // - Cell (0, 0) (III) holds an icon (top left cell) // - Cell (0, 1) holds the message text; spans columns // - Cell (1, n) holds buttons (2 <= n <= ) // - Column 1 (XX) is the resizable column; not used for buttons // - Column 2+ is used for buttons // _________________________________________________ // | | // | III Some message text ... ... ... ... ... ... | // | III more message text ... ... ... ... ... ... | // | III more message text ... ... ... ... ... ... | // | more message text ... ... ... ... ... ... | // | more message text ... ... ... ... ... ... | // | XX +––––––––+ +––––+ | // | XX [more buttons ...] | Cancel | | OK | | // | XX +––––––––+ +––––+ | // |_________________________________________________| #include #include #include #include #include static const int ROWS = 2; static const int BUTTONS = 4; // default = 4, use 1 to 5 to test static const int COLS = BUTTONS + 2; static const int BUTTON_H = 25; static const int ICON_W = 60; static const int ICON_H = 70; static const int MARGIN = 10; static const int GAP = 8; // Button labels (left to right) static const char *labels[5] = { "Quit", "Copy", "Cancel", "OK", "More ..." }; static const char *tooltips[5] = { "Quit this program", "Copy the message text to the clipboard", "Cancel - does nothing", "OK - does nothing", "More buttons could be added here" }; // button widths (left to right) to avoid font calculations static const int button_w[5] = { 50, 50, 70, 40, 100}; static int col_weights[] = { 0, 100, 0, 0, 0, 0, 0 }; static int row_weights[] = { 100, 0, 0, 0, 0, 0, 0 }; static const char *message_text = "This is a long message in an Fl_Grid based dialog " "that may wrap over more than one line. " "Resize the window to see how it (un)wraps."; Fl_Box *message_box = 0; // global only to simplify the code // Common button callback void button_cb(Fl_Widget *w, void *v) { int val = fl_int(v); printf("Button %d: '%s'\n", val, w->label()); switch(val) { case 0: // Quit w->window()->hide(); break; case 1: { // Copy const char *text = message_box->label(); const int len = (int)strlen(text); Fl::copy(text, len, 1); } printf("Message copied to clipboard.\n"); break; default: break; } fflush(stdout); } int main(int argc, char **argv) { int min_w = ICON_W + 2 * MARGIN + (BUTTONS + 1) * GAP; int min_h = ICON_H + 10 + 2 * MARGIN + GAP + BUTTON_H; for (int i = 0; i < BUTTONS; i++) { min_w += button_w[i]; } Fl_Double_Window *win = new Fl_Double_Window(min_w, min_h, "Fl_Grid Based Dialog"); Fl_Grid *grid = new Fl_Grid(0, 0, win->w(), win->h()); grid->layout(ROWS, COLS, MARGIN, GAP); grid->color(FL_WHITE); grid->tooltip("Resize the window to see this dialog \"in action\""); // Child 0: Fl_Box for the "icon" or image (fixed size) Fl_Box *icon = new Fl_Box(0, 0, ICON_W, ICON_H, "ICON"); grid->widget(icon, 0, 0, 1, 1, FL_GRID_TOP); icon->box(FL_THIN_UP_BOX); icon->color(0xddffff00); icon->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE|FL_ALIGN_CLIP); icon->tooltip("This could also be a full Fl_Image or subclass thereof"); // Child 1: the message box message_box = new Fl_Box(0, 0, 0, 0); grid->widget(message_box, 0, 1, 1, BUTTONS + 1, FL_GRID_FILL); message_box->label(message_text); message_box->align(FL_ALIGN_TOP|FL_ALIGN_INSIDE|FL_ALIGN_WRAP); message_box->tooltip("The text in this box can be copied to the clipboard"); // Children 2++: the buttons (left to right for tab navigation order) for (int i = 0; i < BUTTONS; i++) { Fl_Button *b = new Fl_Button(0, 0, button_w[i], BUTTON_H, labels[i]); grid->widget(b, 1, i + 2); b->callback(button_cb, fl_voidptr(i)); b->tooltip(tooltips[i]); } grid->end(); // set row and column weights for resizing grid->row_weight(row_weights, ROWS); grid->col_weight(col_weights, COLS); // Set environment variable "FLTK_GRID_DEBUG=1" or uncomment this line: // grid->show_grid(1); // enable to display grid helper lines win->end(); win->resizable(grid); win->size_range(min_w, min_h, 3 * min_w, min_h + 50); win->show(argc, argv); int ret = Fl::run(); delete win; // not necessary but useful to test for memory leaks return ret; } fltk-1.4.3/test/pixmap_browser.cxx0000644000175000017500000001103315004135251017347 0ustar albrechtalbrecht// // A shared image test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include #include // setlocale().. #include #include #include #include Fl_Box *b; Fl_Double_Window *w; Fl_Shared_Image *img; static char name[1024]; void cb_forced_redraw(void *) { Fl_Window *win = Fl::first_window(); while (win) { if (!win->menu_window()) win->redraw(); win = Fl::next_window(win); } if (Fl::first_window()) Fl::repeat_timeout(1./10, cb_forced_redraw); } void load_file(const char *n) { if (img) { ((Fl_Shared_Image*)b->image())->release(); img = 0L; } if (fl_filename_isdir(n)) { b->label("@fileopen"); // show a generic folder b->labelsize(64); b->labelcolor(FL_LIGHT2); b->image(0); b->redraw(); return; } Fl_Shared_Image *img2 = Fl_Shared_Image::get(n); if (!img2) { b->label("@filenew"); // show an empty document b->labelsize(64); b->labelcolor(FL_LIGHT2); b->image(0); b->redraw(); return; } img = img2; b->labelsize(14); b->labelcolor(FL_FOREGROUND_COLOR); b->image(img); img->scale(b->w(), b->h()); b->label(NULL); b->redraw(); } void file_cb(const char *n) { if (!strcmp(name,n)) return; load_file(n); strcpy(name,n); w->label(name); } void button_cb(Fl_Widget *,void *) { fl_file_chooser_callback(file_cb); const char *fname = fl_file_chooser("Image file?","*.{bm,bmp,gif,ico,jpg,pbm,pgm,png,ppm,xbm,xpm" #ifdef FLTK_USE_SVG ",svg,svgz" #endif // FLTK_USE_SVG "}", name); puts(fname ? fname : "(null)"); fflush(stdout); fl_file_chooser_callback(0); } void print_cb(Fl_Widget *widget, void *) { Fl_Printer printer; int width, height; if (printer.start_job(1)) return; printer.start_page(); printer.printable_rect(&width, &height); float fw = widget->window()->decorated_w() / float(width); float fh = widget->window()->decorated_h() / float(height); if (fh > fw) fw = fh; printer.scale(1/fw); printer.print_window(widget->window()); printer.end_page(); printer.end_job(); } void svg_cb(Fl_Widget *widget, void *) { Fl_Native_File_Chooser fnfc; fnfc.title("Pick a .svg file"); fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); fnfc.filter("SVG\t*.svg\n"); fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | Fl_Native_File_Chooser::USE_FILTER_EXT); if (fnfc.show() ) return; FILE *svg = fl_fopen(fnfc.filename(), "w"); Fl_SVG_File_Surface surf(widget->window()->decorated_w(), widget->window()->decorated_h(), svg); surf.draw_decorated_window(widget->window()); surf.close(); } int dvisual = 0; int animate = 1; int arg(int, char **argv, int &i) { if (argv[i][1] == '8') {dvisual = 1; i++; return 1;} if (argv[i][1] == 'a') {animate = 1; i++; return 1;} return 0; } int main(int argc, char **argv) { int i = 1; setlocale(LC_ALL, ""); // enable multilanguage errors in file chooser fl_register_images(); Fl::args_to_utf8(argc, argv); // enable multilanguage commandlines on Windows Fl::args(argc, argv, i, arg); // parse commandline if (animate) Fl_GIF_Image::animate = true; // create animated shared .GIF images (e.g. file chooser) Fl_Double_Window window(400,450); ::w = &window; Fl_Box b(10,45,380,380); ::b = &b; b.box(FL_THIN_DOWN_BOX); b.align(FL_ALIGN_INSIDE|FL_ALIGN_CENTER|FL_ALIGN_CLIP); Fl_Button button(150,5,100,30,"load"); button.callback(button_cb); if (!dvisual) Fl::visual(FL_RGB); if (argv[1]) load_file(argv[1]); window.resizable(b); Fl_Button print(300,425,50,25,"Print"); print.callback(print_cb); Fl_Button svg(190,425,100,25,"save as SVG"); svg.callback(svg_cb); window.show(argc,argv); if (animate) Fl::add_timeout(1./10, cb_forced_redraw); // force periodic redraw return Fl::run(); } fltk-1.4.3/test/CubeViewUI.fl0000644000175000017500000000456415004135251016067 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} class CubeViewUI {open } { Function {CubeViewUI()} {open } { Fl_Window mainWindow { label CubeView open private xywh {494 321 415 405} type Double box UP_BOX labelsize 12 resizable visible } { Fl_Group {} {open xywh {5 3 374 399} } { Fl_Group VChange {open xywh {5 100 37 192} } { Fl_Roller vrot { label {V Rot} callback {cube->v_angle(((Fl_Roller *)o)->value()); cube->redraw();} xywh {5 100 17 186} labeltype NO_LABEL labelsize 12 align 128 minimum -180 maximum 180 step 1 code0 {\#include } } Fl_Slider ypan { label {V Pan} callback {cube->pany(((Fl_Slider *)o)->value()); cube->redraw();} xywh {25 100 17 186} type {Vert Knob} selection_color 136 labeltype NO_LABEL labelsize 12 align 0 minimum -25 maximum 25 step 0.1 } } Fl_Group HChange {open xywh {120 362 190 40} } { Fl_Slider xpan { label {H Pan} callback {cube->panx(((Fl_Slider *)o)->value()); cube->redraw();} xywh {122 364 186 17} type {Horz Knob} selection_color 136 labeltype NO_LABEL labelsize 12 align 16 minimum 25 maximum -25 step 0.1 } Fl_Roller hrot { label {H Rotation} callback {cube->h_angle(((Fl_Roller *)o)->value()); cube->redraw();} selected xywh {122 383 186 17} type Horizontal labeltype NO_LABEL labelsize 12 align 8 minimum -180 maximum 180 step 1 } } Fl_Group MainView {open xywh {46 27 333 333} box DOWN_BOX resizable } { Fl_Box cube { label {This is the cube_view} xywh {48 29 329 329} align 16 resizable code0 {\#include "CubeView.h"} class CubeView } } Fl_Value_Slider zoom { label Zoom callback {cube->size=((Fl_Value_Slider *)o)->value(); cube->redraw();} xywh {106 3 227 19} type {Horz Knob} selection_color 136 labelfont 1 labelsize 12 align 4 minimum 1 maximum 50 step 0.1 value 10 textfont 1 } } } } Function {show(int argc, char **argv)} {open } { code {mainWindow->show(argc, argv);} {} } } fltk-1.4.3/test/unittest_scrollbarsize.cxx0000644000175000017500000002525415004135251021135 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include #include #include #include #include #include #include #include // // Test new 1.3.x global vs. local scrollbar sizing // class Ut_Table : public Fl_Table { // Handle drawing table's cells // Fl_Table calls this function to draw each visible cell in the table. // It's up to us to use FLTK's drawing functions to draw the cells the way we want. // void draw_cell(TableContext context, int ROW=0, int COL=0, int X=0, int Y=0, int W=0, int H=0) FL_OVERRIDE { static char s[10]; switch ( context ) { case CONTEXT_STARTPAGE: // before page is drawn.. fl_font(FL_HELVETICA, 8); // set font for drawing operations return; case CONTEXT_CELL: // Draw data in cells snprintf(s, 10, "%c", 'A'+ROW+COL); fl_push_clip(X,Y,W,H); // Draw cell bg fl_color(FL_WHITE); fl_rectf(X,Y,W,H); // Draw cell data fl_color(FL_GRAY0); fl_draw(s, X,Y,W,H, FL_ALIGN_CENTER); // Draw box border fl_color(color()); fl_rect(X,Y,W,H); fl_pop_clip(); return; default: return; } } public: // Constructor // Make our data array, and initialize the table options. // Ut_Table(int X, int Y, int W, int H, const char *L=0) : Fl_Table(X,Y,W,H,L) { // Rows rows(13); // how many rows row_height_all(10); // default height of rows // Cols cols(13); // how many columns col_width_all(10); // default width of columns end(); // end the Fl_Table group } ~Ut_Table() { } }; static const char *phonetics[] = { "Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliet", "Kilo", "Lima", "Mike", "November", "Oscar", "Papa", "Quebec", "Romeo", "Sierra", "Tango", "Uniform", "Victor", "Whiskey", "X-ray", "Yankee", "Zulu", NULL }; class Ut_Scrollbar_Size_Test : public Fl_Group { Fl_Browser *brow_a, *brow_b, *brow_c; Fl_Tree *tree_a, *tree_b, *tree_c; Ut_Table *table_a,*table_b,*table_c; Fl_Text_Display *text_a, *text_b, *text_c; Fl_Terminal *term_a, *term_b, *term_c; Fl_Browser *makebrowser(int X,int Y,int W,int H,const char*L=0) { Fl_Browser *b = new Fl_Browser(X,Y,W,H,L); b->type(FL_MULTI_BROWSER); b->labelsize(10); b->textsize(10); b->align(FL_ALIGN_TOP); for (int t=0; phonetics[t]; t++ ) { b->add(phonetics[t]); if ( phonetics[t][0] == 'C' ) b->add("Long entry will show h-bar"); } return(b); } Fl_Tree *maketree(int X,int Y,int W,int H,const char*L=0) { Fl_Tree *b = new Fl_Tree(X,Y,W,H,L); b->labelsize(10); b->item_labelsize(10); b->type(FL_TREE_SELECT_MULTI); b->align(FL_ALIGN_TOP); for (int t=0; phonetics[t]; t++ ) { b->add(phonetics[t]); if ( phonetics[t][0] == 'C' ) b->add("Long entry will show h-bar"); } return(b); } Ut_Table *maketable(int X,int Y,int W,int H,const char*L=0) { Ut_Table *mta = new Ut_Table(X,Y,W,H,L); mta->labelsize(10); mta->align(FL_ALIGN_TOP); mta->end(); return(mta); } Fl_Text_Display *maketextdisplay(int X,int Y,int W,int H,const char*L=0) { Fl_Text_Display *dpy = new Fl_Text_Display(X,Y,W,H,L); Fl_Text_Buffer *buf = new Fl_Text_Buffer(); dpy->labelsize(10); dpy->textsize(10); dpy->buffer(buf); for (int t=0; phonetics[t]; t++ ) { buf->printf("%s\n", phonetics[t]); if ( phonetics[t][0] == 'C' ) buf->printf("Long entry will show h-bar\n"); } return(dpy); } Fl_Terminal *maketerm(int X,int Y,int W,int H,const char*L=0) { Fl_Terminal *term = new Fl_Terminal(X,Y,W,H,L); term->labelsize(8); term->textsize(8); term->end(); term->display_columns(40); // force wider than normal to show hscroll term->printf("Long entry will show h-bar\n"); return(term); } void slide_cb2(Fl_Value_Slider *in) { const char *label = in->label(); int val = int(in->value()); //fprintf(stderr, "VAL='%d'\n",val); if ( strcmp(label,"A: Scroll Size") == 0 ) { brow_a->scrollbar_size(val); tree_a->scrollbar_size(val); table_a->scrollbar_size(val); text_a->scrollbar_size(val); term_a->scrollbar_size(val); } else { Fl::scrollbar_size(val); } in->window()->redraw(); } static void slide_cb(Fl_Widget *w, void *data) { Ut_Scrollbar_Size_Test *o = (Ut_Scrollbar_Size_Test*)data; o->slide_cb2((Fl_Value_Slider*)w); } public: static Fl_Widget *create() { return(new Ut_Scrollbar_Size_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H)); } // CTOR Ut_Scrollbar_Size_Test(int X, int Y, int W, int H) : Fl_Group(X,Y,W,H) { begin(); // _____________ _______________ // |_____________| |_______________| // --- ----- <-- tgrpy // brow_a brow_b brow_c ↕ 14 ↑ // ---------- ---------- ---------- --- | <-- browy // | | | | | | ↑ browh | // | | | | | | ↓ | // ---------- ---------- ---------- --- tgrph // ↑ | // tree_a tree_b tree_c ↓ 20 | // ---------- ---------- ---------- --- | <-- treey // | | | | | | ↑ treeh | // | | | | | | ↓ | // ---------- ---------- ---------- --- | // ↑ | // table_a table_b table_c ↓ 20 | // ---------- ---------- ---------- --- | <-- tabley // | | | | | | ↑ tableh | // | | | | | | ↓ | // ---------- ---------- ---------- --- | // ↑ | // term_a term_b term_c ↓ 20 | // ---------- ---------- ---------- --- | <-- termy // | | | | | | ↑ termh | // | | | | | | ↓ ↓ // ---------- ---------- ---------- --- ------ // etc.. int tgrpy = Y+30; int tgrph = H-30; int ysep = 20; // y separation between widgets int browy = tgrpy+14; int browh = tgrph/5 - 20; // 5: number of widgets vertically int treey = browy + browh + ysep; int treeh = browh; int tabley = treey + treeh + ysep; int tableh = browh; int texty = tabley + tableh + ysep; int texth = browh; int termy = texty + texth + ysep; // int termh = texth; // unused but left because it's documented above brow_a = makebrowser(X+ 10,browy,100,browh,"Browser A"); brow_b = makebrowser(X+120,browy,100,browh,"Browser B"); brow_c = makebrowser(X+230,browy,100,browh,"Browser C"); tree_a = maketree(X+ 10,treey,100,treeh,"Tree A"); tree_b = maketree(X+120,treey,100,treeh,"Tree B"); tree_c = maketree(X+230,treey,100,treeh,"Tree C"); table_a = maketable(X+ 10,tabley,100,tableh,"Table A"); table_b = maketable(X+120,tabley,100,tableh,"Table B"); table_c = maketable(X+230,tabley,100,tableh,"Table C"); text_a = maketextdisplay(X+ 10,texty,100,texth,"Text Display A"); text_b = maketextdisplay(X+120,texty,100,texth,"Text Display B"); text_c = maketextdisplay(X+230,texty,100,texth,"Text Display C"); term_a = maketerm(X+ 10,termy,100,texth,"Term A"); term_b = maketerm(X+120,termy,100,texth,"Term B"); term_c = maketerm(X+230,termy,100,texth,"Term C"); Fl_Value_Slider *slide_glob = new Fl_Value_Slider(X+100,Y,100,18,"Global Scroll Size"); slide_glob->value(16); slide_glob->type(FL_HORIZONTAL); slide_glob->align(FL_ALIGN_LEFT); slide_glob->range(0.0, 30.0); slide_glob->step(1.0); slide_glob->callback(slide_cb, (void*)this); slide_glob->labelsize(12); Fl_Value_Slider *slide_browa = new Fl_Value_Slider(X+350,Y,100,18,"A: Scroll Size"); slide_browa->value(0); slide_browa->type(FL_HORIZONTAL); slide_browa->align(FL_ALIGN_LEFT); slide_browa->range(0.0, 30.0); slide_browa->step(1.0); slide_browa->callback(slide_cb, (void*)this); slide_browa->labelsize(12); int msgbox_x = brow_c->x() + brow_c->w() + 20; int msgbox_y = tgrpy; int msgbox_w = W-(msgbox_x-X); int msgbox_h = tgrph; Fl_Box *msgbox = new Fl_Box(msgbox_x,msgbox_y,msgbox_w,msgbox_h); msgbox->label("\nVerify global scrollbar sizing and per-widget scrollbar sizing. " "Scrollbar's size should change interactively as size sliders are changed. " "Changing 'Global Scroll Size' should affect all scrollbars AS LONG AS the " "'A: Scroll Size' slider is 0. Otherwise its value takes precedence " "for all the 'A' group widgets."); msgbox->labelsize(12); msgbox->align(FL_ALIGN_INSIDE|FL_ALIGN_CENTER|FL_ALIGN_LEFT|FL_ALIGN_WRAP); msgbox->box(FL_FLAT_BOX); msgbox->color(53); // 90% gray end(); } }; UnitTest scrollbarsize(UT_TEST_SCROLLBARSIZE, "Scrollbar Size", Ut_Scrollbar_Size_Test::create); fltk-1.4.3/test/unittest_points.cxx0000644000175000017500000002415515004135251017572 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include #include #include #if HAVE_GL #include #endif // //------- test the point drawing capabilities of this implementation ---------- // class Ut_Native_Point_Test : public Fl_Window { public: Ut_Native_Point_Test(int x, int y, int w, int h) : Fl_Window(x, y, w, h) { end(); } void draw() FL_OVERRIDE { int i; fl_color(FL_WHITE); fl_rectf(0, 0, 10, 10); fl_color(FL_BLACK); for (i=0; i<10; i++) { fl_point(i, 0); fl_point(i, 9); } for (i=0; i<10; i++) { fl_point(0, i); fl_point(9, i); } } }; #if HAVE_GL class Ut_GL_Point_Test : public Fl_Gl_Window { public: Ut_GL_Point_Test(int x, int y, int w, int h) : Fl_Gl_Window(x, y, w, h) { box(FL_FLAT_BOX); end(); } void draw() FL_OVERRIDE { Fl_Gl_Window::draw_begin(); Fl_Window::draw(); int a = -24, b = 5-9, i, j; // Test 1a: pixel size fl_color(FL_WHITE); fl_rectf(a+24, b+9-5, 10, 10); fl_color(FL_BLACK); for (i=0; i<8; i++) for (j=0; j<8; j++) if ((i+j)&1) fl_point(a+i+24+1, b+j+9-5+1); // Test 2a: pixel color for (int n=0; n<3; n++) { static Fl_Color lut[3] = { FL_RED, FL_GREEN, FL_BLUE }; int yy = b+9-5+24 + 16*n; fl_color(FL_WHITE); fl_rectf(a+24, yy, 10, 10); fl_color(lut[n]); for (i=0; i<8; i++) for (j=0; j<8; j++) fl_point(a+i+24+1, yy+j+1); } // Test 3a: pixel alignment inside windows (drawing happens in PointTestWin) int xx = a+24, yy = b+2*24+2*16+9-5; fl_color(FL_RED); for (i=0; i<10; i++) { fl_point(xx-1, yy+i); fl_point(xx+10, yy+i); } fl_color(FL_BLACK); for (i=0; i<10; i++) { fl_point(xx+i, yy); fl_point(xx+i, yy+9); } for (i=0; i<10; i++) { fl_point(xx, yy+i); fl_point(xx+9, yy+i); } fl_color(FL_WHITE); for (i=0; i<8; i++) for (j=0; j<8; j++) fl_point(xx+i+1, yy+j+1); // Test 4a: check pixel clipping xx = a+24; yy = b+3*24+2*16+9-5; fl_push_clip(xx+1, yy+1, 9, 9); fl_color(FL_RED); for (i=0; i<10; i++) { fl_point(xx+i, yy); fl_point(xx+i, yy+9); } for (i=0; i<10; i++) { fl_point(xx, yy+i); fl_point(xx+9, yy+i); } fl_color(FL_BLACK); for (i=1; i<9; i++) { fl_point(xx+i, yy+1); fl_point(xx+i, yy+8); } for (i=1; i<9; i++) { fl_point(xx+1, yy+i); fl_point(xx+8, yy+i); } fl_color(FL_WHITE); for (i=1; i<7; i++) for (j=1; j<7; j++) fl_point(xx+i+1, yy+j+1); fl_pop_clip(); Fl_Gl_Window::draw_end(); } }; #endif class Ut_Point_Test : public Fl_Group { Ut_Native_Point_Test *align_test_win; #if HAVE_GL Ut_GL_Point_Test *gl_test_win; #endif public: static Fl_Widget *create() { return new Ut_Point_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); // 520x365, resizable } Ut_Point_Test(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { label("Testing the fl_point call."); align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_WRAP); box(FL_BORDER_BOX); int a = x+16, b = y+34; Fl_Box *t = new Fl_Box(a, b-24, 80, 18, "native"); t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); t = new Fl_Box(a, b, 18, 18, "1"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing pixel size and antialiasing.\n\n" // Description: "This draws a checker board of black points on a white background.\n\n" // Things to look out for: "Black and white points should be the same size of one unit (1 pixel in regular mode, 2x2 pixels in hidpi mode)." "If black points are smaller than white in hidpi mode, point size must be increased.\n\n" "Points should not be blurry. Antialiasing should be switched of and the point coordinates should be centered on the pixel(s).\n\n" "If parts of the white border are missing, the size of fl_rect should be adjusted." ); t = new Fl_Box(a, b+24, 18, 18, "2"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing pixels color.\n\n" // Description: "This draws three squares in red, green, and blue.\n\n" // Things to look out for: "If the order of colors is different, the byte order when writing into the pixel buffer should be fixed." ); t = new Fl_Box(a, b+2*24+2*16, 18, 18, "3"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing pixels alignment in windows.\n\n" // Description: "This draws a black frame around a white square.\n\n" // Things to look out for: "If parts of the black frame are clipped by the window and not visible, pixel offsets must be adjusted." ); align_test_win = new Ut_Native_Point_Test(a+24, b+2*24+2*16+9-5, 10, 10); t = new Fl_Box(a, b+3*24+2*16, 18, 18, "4"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing pixels clipping.\n\n" // Description: "This draws a black frame around a white square.\n\n" // Things to look out for: "If red pixels are visible or black pixels are missing, graphics clipping is misaligned." ); a+=100; #if HAVE_GL t = new Fl_Box(a, b-24, 80, 18, "OpenGL"); t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); t = new Fl_Box(a, b, 26, 18, "1a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing pixel size and antialiasing.\n\n" // Description: "This draws a checker board of black points on a white background.\n\n" // Things to look out for: "Black and white points should be the same size of one unit (1 pixel in regular mode, 2x2 pixels in hidpi mode)." "If black points are smaller than white in hidpi mode, point size must be increased.\n\n" "Points should not be blurry. Antialiasing should be switched of and the point coordinates should be centered on the pixel(s).\n\n" "If parts of the white border are missing, the size of fl_rect should be adjusted." ); t = new Fl_Box(a, b+24, 26, 18, "2a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing pixels color.\n\n" // Description: "This draws three squares in red, green, and blue.\n\n" // Things to look out for: "If the order of colors is different, the color component order when writing into the pixel buffer should be fixed." ); t = new Fl_Box(a, b+2*24+2*16, 26, 18, "3a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing pixels alignment in windows.\n\n" // Description: "This draws a black frame around a white square, extending to both sides.\n\n" // Things to look out for: "If parts of the black frame are clipped by the window and not visible, pixel offsets must be adjusted horizontally.\n\n" "If the horizontal lines are misaligned, vertical pixel offset should be adjusted." ); t = new Fl_Box(a, b+3*24+2*16, 26, 18, "4a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing pixels clipping.\n\n" // Description: "This draws a black frame around a white square. The square is slightly smaller.\n\n" // Things to look out for: "If red pixels are visible or black pixels are missing, graphics clipping is misaligned." ); gl_test_win = new Ut_GL_Point_Test(a+24+8, b+9-5, 10, 4*24+2*16); #endif t = new Fl_Box(x+w-1,y+h-1, 1, 1); resizable(t); } void draw() FL_OVERRIDE { Fl_Group::draw(); int a = x()+16, b = y()+34, i, j; // Test 1: pixel size fl_color(FL_WHITE); fl_rectf(a+24, b+9-5, 10, 10); fl_color(FL_BLACK); for (i=0; i<8; i++) for (j=0; j<8; j++) if ((i+j)&1) fl_point(a+i+24+1, b+j+9-5+1); // Test 2: pixel color for (int n=0; n<3; n++) { static Fl_Color lut[3] = { FL_RED, FL_GREEN, FL_BLUE }; int yy = b+9-5+24 + 16*n; fl_color(FL_WHITE); fl_rectf(a+24, yy, 10, 10); fl_color(lut[n]); for (i=0; i<8; i++) for (j=0; j<8; j++) fl_point(a+i+24+1, yy+j+1); } // Test 3: pixel alignment inside windows (drawing happens in PointTestWin) // Test 4: check pixel clipping int xx = a+24, yy = b+3*24+2*16+9-5; fl_push_clip(xx, yy, 10, 10); fl_color(FL_RED); for (i=-1; i<11; i++) { fl_point(xx+i, yy-1); fl_point(xx+i, yy+10); } for (i=-1; i<11; i++) { fl_point(xx-1, yy+i); fl_point(xx+10, yy+i); } fl_color(FL_BLACK); for (i=0; i<10; i++) { fl_point(xx+i, yy); fl_point(xx+i, yy+9); } for (i=0; i<10; i++) { fl_point(xx, yy+i); fl_point(xx+9, yy+i); } fl_color(FL_WHITE); for (i=0; i<8; i++) for (j=0; j<8; j++) fl_point(xx+i+1, yy+j+1); fl_pop_clip(); // Test 3a: pixel alignment inside the OpenGL window #if HAVE_GL xx = a+24+108; yy = b+2*24+2*16+9-5; fl_color(FL_BLACK); for (i=-4; i<14; i++) { fl_point(xx+i, yy); fl_point(xx+i, yy+9); } #endif } }; UnitTest points(UT_TEST_POINTS, "Drawing Points", Ut_Point_Test::create); fltk-1.4.3/test/table.cxx0000644000175000017500000004024515004135251015404 0ustar albrechtalbrecht// // exercisetablerow -- Exercise all aspects of the Fl_Table_Row widget // #include #include #include #include #include #include #include #include #include #include #include #include // atoi #define TERMINAL_HEIGHT 120 // Globals Fl_Terminal *G_tty = 0; // Simple demonstration class to derive from Fl_Table_Row class DemoTable : public Fl_Table_Row { private: Fl_Color cell_bgcolor; // color of cell's bg color Fl_Color cell_fgcolor; // color of cell's fg color bool show_callbacks; // set to show callback msgs protected: void draw_cell(TableContext context, // table cell drawing int R=0, int C=0, int X=0, int Y=0, int W=0, int H=0) FL_OVERRIDE; static void event_callback(Fl_Widget*, void*); void event_callback2(); // callback for table events public: DemoTable(int x, int y, int w, int h, const char *l=0) : Fl_Table_Row(x,y,w,h,l) { cell_bgcolor = FL_WHITE; cell_fgcolor = FL_BLACK; show_callbacks = false; callback(&event_callback, (void*)this); end(); } ~DemoTable() { } Fl_Color GetCellFGColor() const { return(cell_fgcolor); } Fl_Color GetCellBGColor() const { return(cell_bgcolor); } void SetCellFGColor(Fl_Color val) { cell_fgcolor = val; } void SetCellBGColor(Fl_Color val) { cell_bgcolor = val; } void ShowCallbacks(bool val) { show_callbacks = val; } }; // Handle drawing all cells in table void DemoTable::draw_cell(TableContext context, int R, int C, int X, int Y, int W, int H) { static char s[40]; snprintf(s, 40, "%d/%d", R, C); // text for each cell switch ( context ) { case CONTEXT_STARTPAGE: fl_font(FL_HELVETICA, 16); return; case CONTEXT_COL_HEADER: fl_push_clip(X, Y, W, H); { fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, col_header_color()); fl_color(FL_BLACK); fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER); } fl_pop_clip(); return; case CONTEXT_ROW_HEADER: fl_push_clip(X, Y, W, H); { fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, row_header_color()); fl_color(FL_BLACK); fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER); } fl_pop_clip(); return; case CONTEXT_CELL: { fl_push_clip(X, Y, W, H); { // BG COLOR fl_color( row_selected(R) ? selection_color() : cell_bgcolor); fl_rectf(X, Y, W, H); // TEXT fl_color(cell_fgcolor); fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER); // BORDER fl_color(color()); fl_rect(X, Y, W, H); } fl_pop_clip(); return; } case CONTEXT_TABLE: G_tty->printf("TABLE CONTEXT CALLED\n"); return; case CONTEXT_ENDPAGE: case CONTEXT_RC_RESIZE: case CONTEXT_NONE: return; } } // Callback whenever someone clicks on different parts of the table void DemoTable::event_callback(Fl_Widget*, void *data) { DemoTable *o = (DemoTable*)data; o->event_callback2(); } void DemoTable::event_callback2() { int R = callback_row(), C = callback_col(); TableContext context = callback_context(); const char *name = label() ? label() : "?"; if ( show_callbacks ) G_tty->printf("'%s' callback: Row=%d Col=%d Context=%d Event=%d InteractiveResize? %d\n", name, R, C, (int)context, (int)Fl::event(), (int)is_interactive_resize()); } // GLOBAL TABLE WIDGET static DemoTable *G_table = 0; void setrows_cb(Fl_Widget*, void *data) { Fl_Input *in = (Fl_Input*)data; int rows = atoi(in->value()); if ( rows < 0 ) rows = 0; G_table->rows(rows); } void setcols_cb(Fl_Widget*, void *data) { Fl_Input *in = (Fl_Input*)data; int cols = atoi(in->value()); if ( cols < 0 ) cols = 0; G_table->cols(cols); } void setrowheader_cb(Fl_Widget*, void *data) { Fl_Check_Button *check = (Fl_Check_Button*)data; G_table->row_header(check->value()); } void setcolheader_cb(Fl_Widget*, void *data) { Fl_Check_Button *check = (Fl_Check_Button*)data; G_table->col_header(check->value()); } void setrowresize_cb(Fl_Widget*, void *data) { Fl_Check_Button *check = (Fl_Check_Button*)data; G_table->row_resize(check->value()); } void setcolresize_cb(Fl_Widget*, void *data) { Fl_Check_Button *check = (Fl_Check_Button*)data; G_table->col_resize(check->value()); } void setpositionrow_cb(Fl_Widget *w, void *data) { Fl_Input *in = (Fl_Input*)data; int toprow = atoi(in->value()); if ( toprow < 0 || toprow >= G_table->rows() ) { fl_alert("Must be in range 0 thru #rows"); } else { G_table->row_position(toprow); } } void setpositioncol_cb(Fl_Widget *w, void *data) { Fl_Input *in = (Fl_Input*)data; int leftcol = atoi(in->value()); if ( leftcol < 0 || leftcol >= G_table->cols() ) { fl_alert("Must be in range 0 thru #cols"); } else { G_table->col_position(leftcol); } } void setrowheaderwidth_cb(Fl_Widget *w, void *data) { Fl_Input *in = (Fl_Input*)data; int val = atoi(in->value()); if ( val < 1 ) { val = 1; in->value("1"); } G_table->row_header_width(val); } void setcolheaderheight_cb(Fl_Widget *w, void *data) { Fl_Input *in = (Fl_Input*)data; int val = atoi(in->value()); if ( val < 1 ) { val = 1; in->value("1"); } G_table->col_header_height(val); } void setrowheadercolor_cb(Fl_Widget *w, void *data) { Fl_Input *in = (Fl_Input*)data; int val = atoi(in->value()); if ( val < 0 ) { fl_alert("Must be a color >0"); } else { G_table->row_header_color(Fl_Color(val)); } } void setcolheadercolor_cb(Fl_Widget *w, void *data) { Fl_Input *in = (Fl_Input*)data; int val = atoi(in->value()); if ( val < 0 ) { fl_alert("Must be a color >0"); } else { G_table->col_header_color(Fl_Color(val)); } } void setrowheightall_cb(Fl_Widget *w, void *data) { Fl_Input *in = (Fl_Input*)data; int val = atoi(in->value()); if ( val < 0 ) { val = 0; in->value("0"); } G_table->row_height_all(val); } void setcolwidthall_cb(Fl_Widget *w, void *data) { Fl_Input *in = (Fl_Input*)data; int val = atoi(in->value()); if ( val < 0 ) { val = 0; in->value("0"); } G_table->col_width_all(val); } void settablecolor_cb(Fl_Widget *w, void *data) { Fl_Input *in = (Fl_Input*)data; int val = atoi(in->value()); if ( val < 0 ) { fl_alert("Must be a color >0"); } else { G_table->color(Fl_Color(val)); } G_table->redraw(); } void setcellfgcolor_cb(Fl_Widget *w, void *data) { Fl_Input *in = (Fl_Input*)data; int val = atoi(in->value()); if ( val < 0 ) { fl_alert("Must be a color >0"); } else { G_table->SetCellFGColor(Fl_Color(val)); } G_table->redraw(); } void setcellbgcolor_cb(Fl_Widget *w, void *data) { Fl_Input *in = (Fl_Input*)data; int val = atoi(in->value()); if ( val < 0 ) { fl_alert("Must be a color >0"); } else { G_table->SetCellBGColor(Fl_Color(val)); } G_table->redraw(); } char *itoa(int val) { static char s[80]; snprintf(s, 80, "%d", val); return(s); } void tablebox_choice_cb(Fl_Widget *w, void *data) { G_table->table_box((Fl_Boxtype)(fl_intptr_t)data); G_table->redraw(); } void widgetbox_choice_cb(Fl_Widget *w, void *data) { G_table->box((Fl_Boxtype)(fl_intptr_t)data); G_table->resize(G_table->x(), G_table->y(), G_table->w(), G_table->h()); } void type_choice_cb(Fl_Widget *w, void *data) { G_table->type((Fl_Table_Row::TableRowSelectMode)(fl_intptr_t)data); } Fl_Menu_Item tablebox_choices[] = { {"No Box", 0, tablebox_choice_cb, (void*)FL_NO_BOX }, {"Flat Box", 0, tablebox_choice_cb, (void*)FL_FLAT_BOX }, {"Up Box", 0, tablebox_choice_cb, (void*)FL_UP_BOX }, {"Down Box", 0, tablebox_choice_cb, (void*)FL_DOWN_BOX }, {"Up Frame", 0, tablebox_choice_cb, (void*)FL_UP_FRAME }, {"Down Frame", 0, tablebox_choice_cb, (void*)FL_DOWN_FRAME }, {"Thin Up Box", 0, tablebox_choice_cb, (void*)FL_THIN_UP_BOX }, {"Thin Down Box", 0, tablebox_choice_cb, (void*)FL_THIN_DOWN_BOX }, {"Thin Up Frame", 0, tablebox_choice_cb, (void*)FL_THIN_UP_FRAME }, {"Thin Down Frame",0, tablebox_choice_cb, (void*)FL_THIN_DOWN_FRAME }, {"Engraved Box", 0, tablebox_choice_cb, (void*)FL_ENGRAVED_BOX }, {"Embossed Box", 0, tablebox_choice_cb, (void*)FL_EMBOSSED_BOX }, {"Engraved Frame", 0, tablebox_choice_cb, (void*)FL_ENGRAVED_FRAME }, {"Embossed Frame", 0, tablebox_choice_cb, (void*)FL_EMBOSSED_FRAME }, {"Border Box", 0, tablebox_choice_cb, (void*)FL_BORDER_BOX }, {"Shadow Box", 0, tablebox_choice_cb, (void*)FL_SHADOW_BOX }, {"Border Frame", 0, tablebox_choice_cb, (void*)FL_BORDER_FRAME }, {0} }; Fl_Menu_Item widgetbox_choices[] = { {"No Box", 0, widgetbox_choice_cb, (void*)FL_NO_BOX }, //{"Flat Box", 0, widgetbox_choice_cb, (void*)FL_FLAT_BOX }, //{"Up Box", 0, widgetbox_choice_cb, (void*)FL_UP_BOX }, //{"Down Box", 0, widgetbox_choice_cb, (void*)FL_DOWN_BOX }, {"Up Frame", 0, widgetbox_choice_cb, (void*)FL_UP_FRAME }, {"Down Frame", 0, widgetbox_choice_cb, (void*)FL_DOWN_FRAME }, //{"Thin Up Box", 0, widgetbox_choice_cb, (void*)FL_THIN_UP_BOX }, //{"Thin Down Box", 0, widgetbox_choice_cb, (void*)FL_THIN_DOWN_BOX }, {"Thin Up Frame", 0, widgetbox_choice_cb, (void*)FL_THIN_UP_FRAME }, {"Thin Down Frame",0, widgetbox_choice_cb, (void*)FL_THIN_DOWN_FRAME }, //{"Engraved Box", 0, widgetbox_choice_cb, (void*)FL_ENGRAVED_BOX }, //{"Embossed Box", 0, widgetbox_choice_cb, (void*)FL_EMBOSSED_BOX }, {"Engraved Frame", 0, widgetbox_choice_cb, (void*)FL_ENGRAVED_FRAME }, {"Embossed Frame", 0, widgetbox_choice_cb, (void*)FL_EMBOSSED_FRAME }, //{"Border Box", 0, widgetbox_choice_cb, (void*)FL_BORDER_BOX }, //{"Shadow Box", 0, widgetbox_choice_cb, (void*)FL_SHADOW_BOX }, {"Border Frame", 0, widgetbox_choice_cb, (void*)FL_BORDER_FRAME }, {0} }; Fl_Menu_Item type_choices[] = { {"SelectNone", 0, type_choice_cb, (void*)Fl_Table_Row::SELECT_NONE }, {"SelectSingle", 0, type_choice_cb, (void*)Fl_Table_Row::SELECT_SINGLE }, {"SelectMulti", 0, type_choice_cb, (void*)Fl_Table_Row::SELECT_MULTI }, {0} }; int main(int argc, char **argv) { Fl_Window win(900, 730+TERMINAL_HEIGHT); G_tty = new Fl_Terminal(0,730,win.w(),TERMINAL_HEIGHT); G_table = new DemoTable(20, 20, 860, 460, "Demo"); G_table->selection_color(FL_YELLOW); G_table->when(FL_WHEN_RELEASE|FL_WHEN_CHANGED); G_table->table_box(FL_NO_BOX); G_table->col_resize_min(4); G_table->row_resize_min(4); // ROWS G_table->row_header(1); G_table->row_header_width(60); G_table->row_resize(1); G_table->rows(500); G_table->row_height_all(20); // COLS G_table->cols(500); G_table->col_header(1); G_table->col_header_height(25); G_table->col_resize(1); G_table->col_width_all(80); // After initialization, show table's callbacks G_table->ShowCallbacks(true); // Add children to window win.begin(); // ROW Fl_Input setrows(150, 500, 120, 25, "Rows"); setrows.labelsize(12); setrows.value(itoa(G_table->rows())); setrows.callback(setrows_cb, (void*)&setrows); setrows.when(FL_WHEN_RELEASE); Fl_Input rowheightall(400, 500, 120, 25, "Row Height"); rowheightall.labelsize(12); rowheightall.value(itoa(G_table->row_height(0))); rowheightall.callback(setrowheightall_cb, (void*)&rowheightall); rowheightall.when(FL_WHEN_RELEASE); Fl_Input positionrow(650, 500, 120, 25, "Row Position"); positionrow.labelsize(12); positionrow.value("1"); positionrow.callback(setpositionrow_cb, (void*)&positionrow); positionrow.when(FL_WHEN_RELEASE); // COL Fl_Input setcols(150, 530, 120, 25, "Cols"); setcols.labelsize(12); setcols.value(itoa(G_table->cols())); setcols.callback(setcols_cb, (void*)&setcols); setcols.when(FL_WHEN_RELEASE); Fl_Input colwidthall(400, 530, 120, 25, "Col Width"); colwidthall.labelsize(12); colwidthall.value(itoa(G_table->col_width(0))); colwidthall.callback(setcolwidthall_cb, (void*)&colwidthall); colwidthall.when(FL_WHEN_RELEASE); Fl_Input positioncol(650, 530, 120, 25, "Col Position"); positioncol.labelsize(12); positioncol.value("1"); positioncol.callback(setpositioncol_cb, (void*)&positioncol); positioncol.when(FL_WHEN_RELEASE); // ROW HEADER Fl_Input rowheaderwidth(150, 570, 120, 25, "Row Header Width"); rowheaderwidth.labelsize(12); rowheaderwidth.value(itoa(G_table->row_header_width())); rowheaderwidth.callback(setrowheaderwidth_cb, (void*)&rowheaderwidth); rowheaderwidth.when(FL_WHEN_RELEASE); Fl_Input rowheadercolor(400, 570, 120, 25, "Row Header Color"); rowheadercolor.labelsize(12); rowheadercolor.value(itoa((int)G_table->row_header_color())); rowheadercolor.callback(setrowheadercolor_cb, (void*)&rowheadercolor); rowheadercolor.when(FL_WHEN_RELEASE); Fl_Check_Button rowheader(550, 570, 120, 25, "Row Headers?"); rowheader.labelsize(12); rowheader.callback(setrowheader_cb, (void*)&rowheader); rowheader.value(G_table->row_header() ? 1 : 0); Fl_Check_Button rowresize(700, 570, 120, 25, "Row Resize?"); rowresize.labelsize(12); rowresize.callback(setrowresize_cb, (void*)&rowresize); rowresize.value(G_table->row_resize() ? 1 : 0); // COL HEADER Fl_Input colheaderheight(150, 600, 120, 25, "Col Header Height"); colheaderheight.labelsize(12); colheaderheight.value(itoa(G_table->col_header_height())); colheaderheight.callback(setcolheaderheight_cb, (void*)&colheaderheight); colheaderheight.when(FL_WHEN_RELEASE); Fl_Input colheadercolor(400, 600, 120, 25, "Col Header Color"); colheadercolor.labelsize(12); colheadercolor.value(itoa((int)G_table->col_header_color())); colheadercolor.callback(setcolheadercolor_cb, (void*)&colheadercolor); colheadercolor.when(FL_WHEN_RELEASE); Fl_Check_Button colheader(550, 600, 120, 25, "Col Headers?"); colheader.labelsize(12); colheader.callback(setcolheader_cb, (void*)&colheader); colheader.value(G_table->col_header() ? 1 : 0); Fl_Check_Button colresize(700, 600, 120, 25, "Col Resize?"); colresize.labelsize(12); colresize.callback(setcolresize_cb, (void*)&colresize); colresize.value(G_table->col_resize() ? 1 : 0); Fl_Choice tablebox(150, 640, 120, 25, "Table Box"); tablebox.labelsize(12); tablebox.textsize(12); tablebox.menu(tablebox_choices); tablebox.value(0); Fl_Choice widgetbox(150, 670, 120, 25, "Widget Box"); widgetbox.labelsize(12); widgetbox.textsize(12); widgetbox.menu(widgetbox_choices); widgetbox.value(2); // down frame Fl_Input tablecolor(400, 640, 120, 25, "Table Color"); tablecolor.labelsize(12); tablecolor.value(itoa((int)G_table->color())); tablecolor.callback(settablecolor_cb, (void*)&tablecolor); tablecolor.when(FL_WHEN_RELEASE); Fl_Input cellbgcolor(400, 670, 120, 25, "Cell BG Color"); cellbgcolor.labelsize(12); cellbgcolor.value(itoa((int)G_table->GetCellBGColor())); cellbgcolor.callback(setcellbgcolor_cb, (void*)&cellbgcolor); cellbgcolor.when(FL_WHEN_RELEASE); Fl_Input cellfgcolor(400, 700, 120, 25, "Cell FG Color"); cellfgcolor.labelsize(12); cellfgcolor.value(itoa((int)G_table->GetCellFGColor())); cellfgcolor.callback(setcellfgcolor_cb, (void*)&cellfgcolor); cellfgcolor.when(FL_WHEN_RELEASE); Fl_Choice type(650, 640, 120, 25, "Type"); type.labelsize(12); type.textsize(12); type.menu(type_choices); type.value(2); win.end(); win.resizable(*G_table); win.show(argc, argv); return(Fl::run()); } fltk-1.4.3/test/flex_demo.cxx0000644000175000017500000001014715004135251016255 0ustar albrechtalbrecht// // Fl_Flex demo program for the Fast Light Tool Kit (FLTK). // // Copyright 2020 by Karsten Pedersen // Copyright 2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #define DEBUG_GROUP (0) void debug_group(Fl_Group *g) { #if (DEBUG_GROUP) printf("\nFl_Group (%p) has %d children:\n", g, g->children()); for (int i = 0; i < g->children(); i++) { Fl_Widget *c = g->child(i); printf(" child %2d: hidden = %-5s, (x,y,w,h) = (%3d, %3d, %3d, %3d), label = '%s'\n", i, c->visible() ? "false" : "true", c->x(), c->y(), c->w(), c->h(), c->label() ? c->label() : "(null)"); } #endif } // debug_group Fl_Button *create_button(const char *caption) { Fl_Button *rtn = new Fl_Button(0, 0, 120, 30, caption); rtn->color(fl_rgb_color(225, 225, 225)); return rtn; } void toggle_cb(Fl_Widget *w, void *v) { static Fl_Box *b = 0; Fl_Widget *o = (Fl_Widget *)v; Fl_Flex *flex = (Fl_Flex *)o->parent(); if (o->visible()) { o->hide(); w->label("show OK button"); flex->child(1)->hide(); // hide Box } else { o->show(); w->label("hide OK button"); flex->child(1)->show(); // show Box } flex->layout(); debug_group(flex); // Yet another test: modify the first (top) Fl_Flex widget flex = (Fl_Flex *)(flex->parent()->child(0)); Fl_Group::current(0); if (!b) { b = new Fl_Box(0, 0, 0, 0, "Box3"); flex->insert(*b, flex->children() - 1); } else { delete b; b = 0; } flex->layout(); debug_group(flex); } Fl_Flex *create_row() { Fl_Flex *row = new Fl_Flex(Fl_Flex::ROW); { Fl_Button *toggle = create_button("hide OK button"); toggle->tooltip("hide() or show() OK button"); Fl_Box *box2 = new Fl_Box(0, 0, 120, 10, "Box2"); Fl_Button * okay = create_button("OK"); new Fl_Input(0, 0, 120, 10, ""); toggle->callback(toggle_cb, okay); Fl_Flex *col2 = new Fl_Flex(Fl_Flex::COLUMN); { create_button("Top2"); create_button("Bottom2"); col2->end(); col2->margin(0, 5); col2->box(FL_FLAT_BOX); col2->color(fl_rgb_color(255, 128, 128)); } row->fixed(box2, 50); row->fixed(col2, 100); row->end(); // TEST row->box(FL_DOWN_BOX); row->color(FL_GREEN); } return row; } int main(int argc, char **argv) { Fl_Window *window = new Fl_Double_Window(100, 100, "Simple GUI Example"); Fl_Flex *col = new Fl_Flex(5, 5, 90, 90, Fl_Flex::COLUMN); Fl_Flex *row1 = new Fl_Flex(Fl_Flex::ROW); row1->color(FL_YELLOW); row1->box(FL_FLAT_BOX); create_button("Cancel"); new Fl_Box(0, 0, 120, 10, "Box1"); create_button("OK"); new Fl_Input(0, 0, 120, 10, ""); Fl_Flex *col1 = new Fl_Flex(Fl_Flex::COLUMN); create_button("Top1"); create_button("Bottom1"); col1->box(FL_FLAT_BOX); col1->color(fl_rgb_color(255, 128, 128)); col1->margin(5, 5); col1->end(); row1->end(); col->fixed(create_row(), 90); // sets height of created (anonymous) row #2 create_button("Something1"); // "row" #3 Fl_Flex *row4 = new Fl_Flex(Fl_Flex::ROW); Fl_Button *cancel = create_button("Cancel"); Fl_Button *ok = create_button("OK"); new Fl_Input(0, 0, 120, 10, ""); row4->fixed(cancel, 100); row4->fixed(ok, 100); row4->end(); create_button("Something2"); // "row" #5 col->fixed(row4, 30); col->margin(6, 10, 6, 10); col->gap(6); col->end(); window->resizable(col); window->color(fl_rgb_color(160, 180, 240)); window->box(FL_FLAT_BOX); window->end(); window->size_range(550, 330); window->resize(0, 0, 640, 480); window->show(argc, argv); int ret = Fl::run(); delete window; // not necessary but useful to test for memory leaks return ret; } fltk-1.4.3/test/sudoku.ico0000644000175000017500000000137615004135251015601 0ustar albrechtalbrecht ( @fltk-1.4.3/test/contrast.cxx0000644000175000017500000003625015004135251016153 0ustar albrechtalbrecht// // Contrast function test program for the Fast Light Tool Kit (FLTK). // // Copyright 2022-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Note: this test and demo program is work in progress. It is published // because it is helpful but it needs some more work to be "perfect" ;-) // AlbrechtS #include #include #include #include #include #include #include #include #include #include #include #include #include // program version const char *version = "0.9.1"; // prototypes and forward declarations static void button_cb(Fl_Widget *w, void *v); static Fl_Color calc_contrast(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs); // class Button class Button : public Fl_Button { char lbuf[20]; // private label buffer Fl_Color ocol_; // "original" (label) color int idx_; // button index (0 - 255) public: Button(int X, int Y, int W, int H, int n) : Fl_Button(X, Y, W, H, "") { idx_ = n; box(FL_THIN_DOWN_BOX); label(lbuf); callback(button_cb); color((Fl_Color)n); sprintf(lbuf, "%03d", n); set_labelcolor(n); labelsize(15); labelfont(FL_HELVETICA); } void set_labelcolor(Fl_Color col) { ocol_ = col; labelcolor(calc_contrast(col, color(), labelsize())); } Fl_Color ocol() { return ocol_; } int idx() { return idx_; } void draw() FL_OVERRIDE { draw_box(); // draw small filled rectangle with "original" color fl_color(ocol_); fl_rectf(x() + 5, y() + 5, 10, h() - 10); // measure and draw label int lw = 0, lh = 0; fl_font(labelfont(), labelsize()); fl_measure(lbuf, lw, lh); fl_color(labelcolor()); fl_draw(lbuf, x() + 15 + (w() - lw - 15) / 2, y() + h() - (h() - lh) / 2 - lh/4); fl_color(FL_BLACK); } }; // class Button // global variables Fl_Terminal *term = 0; double g_lfg; // perceived lightness of foreground color double g_lbg; // perceived lightness of background color double g_lcref; // calculated contrast reference (CIELAB, L*a*b*) int g_selected = -1; // selected button: -1 = none, 0 - 255 = valid button Fl_Fontsize g_fs = 15; // fontsize for button labels int g_level = 0; // *init* fl_contrast_level (sensitivity) int g_algo = FL_CONTRAST_CIELAB; // contrast algorithm: 0 = none, 1 = legacy (1.3.x), 2 = CIELAB, 3 = custom const char *alch = ""; // algorithm as char: "LEGACY", "CIELAB" , or "CUSTOM" Fl_Color lcolor = FL_BLACK; // label color, set by slider callback Button *buttons[256]; // array of color buttons Fl_Value_Slider *sliders[6]; // array of sliders (gray, red, green, blue, level, fontsize) Fl_Output *color_out = 0; // color output (RRGGBB) // Custom contrast algorithm: currently a dummy function (returns fg). // This may be used to define a "better" contrast function in user code static Fl_Color custom_contrast(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int) { return fg; } /* Local function to calculate the contrast and store it in some global variables for display purposes and logging. This function is a wrapper around fl_contrast() in this demo program. */ static Fl_Color calc_contrast(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs) { // Compute and set global *perceived* lightness L* (Lstar) and contrast for display g_lfg = fl_lightness(fg); g_lbg = fl_lightness(bg); g_lcref = g_lfg - g_lbg; // perceived contrast (light on dark = positive) switch (g_algo) { case FL_CONTRAST_NONE: // 0 = none (return fg) case FL_CONTRAST_LEGACY: // 1 = legacy (FLTK 1.3.x) case FL_CONTRAST_CIELAB: // 2 = CIELAB (L*a*b*) case FL_CONTRAST_CUSTOM: // 3 = Custom return fl_contrast(fg, bg, fs); default: break; } return fg; } // set all button label colors and adjust fontsize (labelsize) static void update_labels() { for (int i = 0; i < 256; i++) { buttons[i]->set_labelcolor(lcolor); buttons[i]->labelsize(g_fs); } } static void button_cb(Fl_Widget *w, void *v) { Button *b = (Button *)w; g_selected = b->idx(); // selected button index Fl_Color ocol = Fl::get_color(b->ocol()); // button's "original" label color (RGB0) Fl_Color fg = Fl::get_color(b->labelcolor()); // button's label color (RGB0) Fl_Color bg = Fl::get_color(b->color()); // button's background color (RGB0) calc_contrast(ocol, bg, g_fs); // calculate values to be displayed const char *color = ""; // calculated label color (text) if (fg == ocol) color = "fg"; else if (fg == 0xffffff00) color = "WHITE"; else if (fg == 0x0) color = "BLACK"; term->printf("[%s] fg: %06x, bg: %06x, lfg: %6.2f, lbg: %6.2f, lc: %7.2f, %s => %-5s", b->label(), ocol >> 8, bg >> 8, g_lfg, g_lbg, g_lcref, alch, color); if (g_algo == FL_CONTRAST_LEGACY || g_algo == FL_CONTRAST_CIELAB) term->printf(" (level = %3d)\n", g_level); else term->printf("\n"); } void lf_cb(Fl_Widget *w, void *v) { term->printf("\n"); } // callback for color (gray and R, G, B) sliders void color_slider_cb(Fl_Widget *w, void *v) { int n = fl_int(v); // slider type: 0 = gray, 1 = color unsigned int r, g, b; if (n == 0) { // gray slider int val = (int)sliders[0]->value(); lcolor = fl_rgb_color(val, val, val); // set gray value sliders[1]->value(val); // set r/g/b values as well sliders[2]->value(val); sliders[3]->value(val); r = g = b = val; } else { // any color slider r = (unsigned int)sliders[1]->value(); g = (unsigned int)sliders[2]->value(); b = (unsigned int)sliders[3]->value(); lcolor = fl_rgb_color(r, g, b); // set color value } // update button label colors update_labels(); // output label color char color_buf[10]; sprintf(color_buf, "%02X %02X %02X", r, g, b); color_out->value(color_buf); w->window()->redraw(); } // callback for "level" and "fontsize" sliders void slider_cb(Fl_Widget *w, void *v) { int n = fl_int(v); // slider type: 1 = level, 2 = fontsize switch (n) { case 1: // fl_contrast_level() g_level = (int)sliders[n + 3]->value(); fl_contrast_level(g_level); // set/store current contrast level break; case 2: // 2nd slider: fontsize (labelsize) g_fs = (int)sliders[n + 3]->value(); break; default: break; } // update button label colors update_labels(); w->window()->redraw(); } // callback for the "random color" button void rc_cb(Fl_Widget *w, void *v) { static bool first = true; unsigned int r, g, b; if (first) { // Seed the random number generator... srand((unsigned int)time(NULL)); first = false; r = g = b = 0; // initialize with black } else { r = rand() % 256; g = rand() % 256; b = rand() % 256; } sliders[1] -> value(r); sliders[2] -> value(g); sliders[3] -> value(b); // update button label colors lcolor = fl_rgb_color(r, g, b); // set color value update_labels(); // output label color char color_buf[10]; sprintf(color_buf, "%02X %02X %02X", r, g, b); color_out->value(color_buf); w->window()->redraw(); } // callback for contrast algorithm (radio buttons) void algo_cb(Fl_Widget *w, void *v) { int val = fl_int(v); g_algo = val; switch(val) { case FL_CONTRAST_LEGACY: alch = "LEGACY"; fl_contrast_mode(val); break; // legacy 1.3.x case FL_CONTRAST_CIELAB: alch = "CIELAB"; fl_contrast_mode(val); break; // CIELAB L*a*b* case FL_CONTRAST_CUSTOM: alch = "CUSTOM"; fl_contrast_mode(val); break; // custom case FL_CONTRAST_NONE: default: alch = "none "; fl_contrast_mode(FL_CONTRAST_NONE); break; } g_level = fl_contrast_level(); // get current contrast level (per mode) sliders[4]->value(g_level); // set level slider value update_labels(); // update all button labels // print selected button's attributes if (g_selected >= 0) { button_cb(buttons[g_selected], (void *)0); } if (w) w->window()->redraw(); } // color chooser callback void color_cb(Fl_Widget *w, void *v) { Fl_Color_Chooser *cc = (Fl_Color_Chooser *)w; int r = (int)(cc->r() * 255); int g = (int)(cc->g() * 255); int b = (int)(cc->b() * 255); Fl_Color c = fl_rgb_color(r, g, b); Button *bt = buttons[255]; // last button bt->color(c); bt->set_labelcolor(lcolor); bt->redraw(); } // =============================================================== // ====================== main() program ====================== // =============================================================== int main(int argc, char **argv) { const int bw = 58; const int bh = 30; int cw = 16 * bw + 10; int ch = 16 * bh + 10; int ww = cw + 10; int wh = 16 * bh + 135 + 10 + 170 /* terminal */ + 10; Fl_Double_Window window(ww, wh, "fl_contrast test"); int n = 0; Button **b = buttons; for (int y = 0; y < 16; y++) { for (int x = 0; x < 16; x++) { *b = new Button(x * bw + 10, y * bh + 10, bw, bh, n); (*b)->set_labelcolor(n); b++; n++; } } // sliders for label color (gray, red, green, blue) const int sx = 10 + bw; const int sw = 5 * bw; const int sh = 25; int sy = ch + 10; Fl_Hor_Value_Slider *gray = new Fl_Hor_Value_Slider(sx, sy, sw, sh, "gray"); gray->color(0xdddddd00); gray->textsize(13); gray->align(FL_ALIGN_LEFT); gray->value(0); gray->bounds(0, 255); gray->step(1); gray->callback(color_slider_cb, (void *)0); sy += sh + 10; Fl_Hor_Value_Slider *red = new Fl_Hor_Value_Slider(sx, sy, sw, sh, "red"); red->color(FL_RED); red->textcolor(FL_WHITE); red->textsize(13); red->align(FL_ALIGN_LEFT); red->value(0); red->bounds(0, 255); red->step(1); red->callback(color_slider_cb, (void *)1); sy += sh + 5; Fl_Hor_Value_Slider *green = new Fl_Hor_Value_Slider(sx, sy, sw, sh, "green"); green->color(FL_GREEN); green->textsize(13); green->align(FL_ALIGN_LEFT); green->value(0); green->bounds(0, 255); green->step(1); green->callback(color_slider_cb, (void *)1); sy += sh + 5; Fl_Hor_Value_Slider *blue = new Fl_Hor_Value_Slider(sx, sy, sw, sh, "blue"); blue->color(FL_BLUE); blue->textcolor(FL_WHITE); blue->textsize(13); blue->align(FL_ALIGN_LEFT); blue->value(0); blue->bounds(0, 255); blue->step(1); blue->callback(color_slider_cb, (void *)1); sliders[0] = gray; sliders[1] = red; sliders[2] = green; sliders[3] = blue; // contrast algorithm selection group int cgx = 10 + 6*bw + 10; int cgy = ch + 30; int cgw = 90; int cgh = 100; int abh = 25; Fl_Group *cg = new Fl_Group(cgx, cgy, cgw, cgh, "fl_contrast:"); cg->align(FL_ALIGN_TOP); cg->box(FL_FRAME); Fl_Radio_Round_Button *anon = new Fl_Radio_Round_Button(cgx, cgy, cgw, abh, "none"); Fl_Radio_Round_Button *aleg = new Fl_Radio_Round_Button(cgx, cgy + 25, cgw, abh, "LEGACY"); Fl_Radio_Round_Button *acie = new Fl_Radio_Round_Button(cgx, cgy + 50, cgw, abh, "CIELAB"); Fl_Radio_Round_Button *aapc = new Fl_Radio_Round_Button(cgx, cgy + 75, cgw, abh, "CUSTOM"); acie->value(1); anon->callback(algo_cb, (void *)0); aleg->callback(algo_cb, (void *)1); acie->callback(algo_cb, (void *)2); aapc->callback(algo_cb, (void *)3); cg->end(); color_out = new Fl_Output(10 + 10 * bw, ch + 10, 100, 30, "label color:"); color_out->align(FL_ALIGN_LEFT); color_out->textfont(FL_COURIER); color_out->textsize(16); color_out->value("00 00 00"); // light blue "level" slider Fl_Hor_Value_Slider *s_level = new Fl_Hor_Value_Slider(10 + 9 * bw, red->y(), 3 * bw - 15, sh, "level"); s_level->color(231); s_level->textcolor(224); s_level->textsize(13); s_level->align(FL_ALIGN_LEFT); s_level->step(1); s_level->bounds(0, 100); s_level->value(g_level); s_level->callback(slider_cb, (void *)1); s_level->tooltip("set contrast sensitivity level (0-100), default: 50"); // labelsize slider Fl_Hor_Value_Slider *s_fs = new Fl_Hor_Value_Slider(10 + 9 * bw, green->y(), 3 * bw - 15, sh, "labelsize"); s_fs->color(231); s_fs->textcolor(224); s_fs->textsize(13); s_fs->align(FL_ALIGN_LEFT); s_fs->step(1); s_fs->bounds(8, 24); s_fs->value(15); s_fs->callback(slider_cb, (void *)2); s_fs->tooltip("set label/text fontsize"); sliders[4] = s_level; sliders[5] = s_fs; // line feed (LF) button Fl_Button *lf = new Fl_Button(10 + 8 * bw, blue->y(), bw, sh, "LF"); lf->tooltip("Click to output a linefeed to the log."); lf->callback(lf_cb); // random color (R) button Fl_Button *rc = new Fl_Button(10 + 8 * bw + lf->w() + 2, blue->y(), bw*3/4, sh, "&RC"); rc->tooltip("Click to select a random text color."); rc->callback(rc_cb); // color chooser for field #255 int ccx = 10 + 12 * bw; int ccy = ch + 10; int ccw = 4 * bw; int cch = 120; Fl_Color_Chooser *color_chooser = new Fl_Color_Chooser(ccx, ccy, ccw, cch); color_chooser->callback(color_cb); color_chooser->label("bg color [255] @->"); color_chooser->rgb(1, 1, 1); color_chooser->mode(1); // byte mode color_chooser->align(FL_ALIGN_LEFT_BOTTOM); // set contrast mode and level, update button label colors fl_contrast_mode(g_algo); fl_contrast_function(custom_contrast); // dummy contrast function algo_cb(acie, fl_voidptr(2)); // Fl_Terminal for output int ttx = 10; int tty = color_chooser->y() + cch + 10; int ttw = window.w() - 20; int tth = window.h() - tty - 10; term = new Fl_Terminal(ttx, tty, ttw, tth); term->color(FL_WHITE); term->textfgcolor(FL_BLACK); term->textsize(13); term->printf("FLTK %d.%d.%d fl_contrast() test program with different contrast algorithms, version %s\n", FL_MAJOR_VERSION, FL_MINOR_VERSION, FL_PATCH_VERSION, version); term->printf(" - Select a foreground (text) color with the gray or red/green/blue sliders (displayed inside each field).\n"); term->printf(" - Select an arbitrary background color for field #255 with the color chooser.\n"); term->printf(" - Select a colored field (by clicking on it) to display its attributes.\n"); term->printf(" - Select the contrast algorithm by clicking on the radio buttons.\n"); term->printf(" - Tune the contrast algorithm with the light blue \"level\" slider (default: %d).\n", fl_contrast_level()); term->printf(" - Select a random foreground (text) color by clicking the RC button\n"); window.resizable(term); window.end(); window.show(argc, argv); rc_cb(rc, 0); // update button labels - must be called after show() return Fl::run(); } fltk-1.4.3/test/boxtype.cxx0000644000175000017500000001416215004135251016006 0ustar albrechtalbrecht// // Boxtype test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2015 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include int N = 0; #define W 200 #define H 50 #define ROWS 14 // Note: Run the program with command line '-s abc' to view boxtypes // with scheme 'abc'. // class BoxGroup - minimal class to enable visible box size debugging // // Set the following static variables to 0 (default) to disable // or 1 to enable the given feature. // // If you enable the 'outline' variable, then a red frame should be drawn // around each box, and it should ideally be fully visible. // // The white background is optional (otherwise you see the window background). // // Set BOTH variables = 0 to show the default image for the FLTK manual. // // Note: As of FLTK 1.3.3 (probably since FLTK 1.0/1.1) there are some // shadows 'leaking' outside their widget bounding boxes (x,y,w,h). // Is this intentional? static const int outline = 0; // draw 1-px red frame around all boxes static const int box_bg = 0; // draw white background inside all boxes static const int inactive = 0; // deactivate boxes and use green background class BoxGroup : public Fl_Group { public: BoxGroup(int x, int y, int w, int h) : Fl_Group(x,y,w,h) {} void draw() FL_OVERRIDE { draw_box(); if (outline + box_bg) { // outline or box_bg or both Fl_Widget*const* a = array(); for (int i=children(); i--;) { Fl_Widget& o = **a++; if (outline) { fl_color(FL_RED); fl_rect(o.x()-1,o.y()-1,o.w()+2,o.h()+2); } if (box_bg) { fl_color(FL_WHITE); fl_rectf(o.x(),o.y(),o.w(),o.h()); } fl_color(FL_BLACK); } } // outline or box_bg or both Fl_Group::draw_children(); } // draw() }; // class BoxGroup Fl_Double_Window *window; void bt(const char *name, Fl_Boxtype type, int square=0) { int x = N%4; int y = N/4; N++; x = x*W+10; y = y*H+10; Fl_Button *b = new Fl_Button(x,y,square ? H-20 : W-20,H-20,name); b->box(type); b->labelsize(11); if (inactive) { b->color(FL_GREEN); b->deactivate(); } if (square) b->align(FL_ALIGN_RIGHT); } int main(int argc, char ** argv) { window = new Fl_Double_Window(4*W,ROWS*H); window->box(FL_FLAT_BOX); #if 0 // this code uses the command line arguments to set arbitrary color schemes Fl::args(argc, argv); Fl::get_system_colors(); #elif 0 // this code uses a single color to define a scheme Fl::args(argc, argv); Fl::get_system_colors(); Fl::background(113,113,198); #else // this code uses the nice bright blue background to show box vs. frame types Fl::args(argc, argv); Fl::get_system_colors(); window->color(fl_rgb_color(51, 173, 255)); // light blue (#33adff) #endif // TEST: set box shadow width and max. border radius (should be commented out) // Fl::box_border_radius_max(5); // default: 15 (see documentation) // Fl::box_shadow_width(6); // default: 3 (see documentation) // set window title to show active scheme Fl::scheme(Fl::scheme()); // init scheme char title[100]; snprintf(title, 100,"FLTK boxtypes: scheme = '%s'",Fl::scheme()?Fl::scheme():"none"); window->label(title); // create special container group for box size debugging BoxGroup *bg = new BoxGroup(0,0,window->w(),window->h()); bg->box(FL_NO_BOX); // create demo boxes bt("FL_NO_BOX",FL_NO_BOX); bt("FL_FLAT_BOX",FL_FLAT_BOX); N += 2; // go to start of next row to line up boxes & frames bt("FL_UP_BOX",FL_UP_BOX); bt("FL_DOWN_BOX",FL_DOWN_BOX); bt("FL_UP_FRAME",FL_UP_FRAME); bt("FL_DOWN_FRAME",FL_DOWN_FRAME); bt("FL_THIN_UP_BOX",FL_THIN_UP_BOX); bt("FL_THIN_DOWN_BOX",FL_THIN_DOWN_BOX); bt("FL_THIN_UP_FRAME",FL_THIN_UP_FRAME); bt("FL_THIN_DOWN_FRAME",FL_THIN_DOWN_FRAME); bt("FL_ENGRAVED_BOX",FL_ENGRAVED_BOX); bt("FL_EMBOSSED_BOX",FL_EMBOSSED_BOX); bt("FL_ENGRAVED_FRAME",FL_ENGRAVED_FRAME); bt("FL_EMBOSSED_FRAME",FL_EMBOSSED_FRAME); bt("FL_BORDER_BOX",FL_BORDER_BOX); bt("FL_SHADOW_BOX",FL_SHADOW_BOX); bt("FL_BORDER_FRAME",FL_BORDER_FRAME); bt("FL_SHADOW_FRAME",FL_SHADOW_FRAME); bt("FL_ROUNDED_BOX",FL_ROUNDED_BOX); bt("FL_RSHADOW_BOX",FL_RSHADOW_BOX); bt("FL_ROUNDED_FRAME",FL_ROUNDED_FRAME); bt("FL_RFLAT_BOX",FL_RFLAT_BOX); bt("FL_OVAL_BOX",FL_OVAL_BOX); bt("FL_OSHADOW_BOX",FL_OSHADOW_BOX); bt("FL_OVAL_FRAME",FL_OVAL_FRAME); bt("FL_OFLAT_BOX",FL_OFLAT_BOX); bt("FL_ROUND_UP_BOX",FL_ROUND_UP_BOX); bt("FL_ROUND_DOWN_BOX",FL_ROUND_DOWN_BOX); bt("FL_DIAMOND_UP_BOX",FL_DIAMOND_UP_BOX); bt("FL_DIAMOND_DOWN_BOX",FL_DIAMOND_DOWN_BOX); bt("FL_PLASTIC_UP_BOX",FL_PLASTIC_UP_BOX); bt("FL_PLASTIC_DOWN_BOX",FL_PLASTIC_DOWN_BOX); bt("FL_PLASTIC_UP_FRAME",FL_PLASTIC_UP_FRAME); bt("FL_PLASTIC_DOWN_FRAME",FL_PLASTIC_DOWN_FRAME); bt("FL_PLASTIC_THIN_UP_BOX",FL_PLASTIC_THIN_UP_BOX); bt("FL_PLASTIC_THIN_DOWN_BOX",FL_PLASTIC_THIN_DOWN_BOX); N += 2; bt("FL_PLASTIC_ROUND_UP_BOX",FL_PLASTIC_ROUND_UP_BOX); bt("FL_PLASTIC_ROUND_DOWN_BOX",FL_PLASTIC_ROUND_DOWN_BOX); N += 2; bt("FL_GTK_UP_BOX",FL_GTK_UP_BOX); bt("FL_GTK_DOWN_BOX",FL_GTK_DOWN_BOX); bt("FL_GTK_UP_FRAME",FL_GTK_UP_FRAME); bt("FL_GTK_DOWN_FRAME",FL_GTK_DOWN_FRAME); bt("FL_GTK_THIN_UP_BOX",FL_GTK_THIN_UP_BOX); bt("FL_GTK_THIN_DOWN_BOX",FL_GTK_THIN_DOWN_BOX); bt("FL_GTK_THIN_UP_FRAME",FL_GTK_THIN_UP_FRAME); bt("FL_GTK_THIN_DOWN_FRAME",FL_GTK_THIN_DOWN_FRAME); bt("FL_GTK_ROUND_UP_BOX",FL_GTK_ROUND_UP_BOX); bt("FL_GTK_ROUND_DOWN_BOX",FL_GTK_ROUND_DOWN_BOX); bg->end(); window->resizable(window); Fl_Scheme_Choice scheme_choice(610, 10, 150, 30, "Scheme:"); window->end(); window->show(); return Fl::run(); } fltk-1.4.3/test/buttons.cxx0000644000175000017500000000512315004135251016007 0ustar albrechtalbrecht// // Another button test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include int main(int argc, char **argv) { Fl_Window *window = new Fl_Window(420, 170); Fl_Button *b1 = new Fl_Button(10, 10, 130, 30, "Fl_Button"); b1->tooltip("Fl_Button"); Fl_Button *b2 = new Fl_Return_Button(150, 10, 160, 30, "Fl_Return_Button"); b2->tooltip("Fl_Return_Button"); Fl_Button *b3 = new Fl_Repeat_Button(10, 50, 130, 30, "Fl_Repeat_Button"); b3->tooltip("Fl_Repeat_Button"); Fl_Button *b4 = new Fl_Round_Button(150, 50, 160, 30, "Fl_Round_Button"); b4->tooltip("Fl_Round_Button"); Fl_Button *b5 = new Fl_Light_Button(10, 90, 130, 30, "Fl_Light_Button"); b5->tooltip("Fl_Light_Button"); Fl_Button *b6 = new Fl_Check_Button(150, 90, 160, 30, "Fl_Check_Button"); b6->tooltip("Fl_Check_Button"); Fl_Group *keypad = new Fl_Group(320, 10, 90, 120); Fl_Button *kp[11]; kp[7] = new Fl_Button(320, 10, 30, 30, "7"); kp[8] = new Fl_Button(350, 10, 30, 30, "8"); kp[9] = new Fl_Button(380, 10, 30, 30, "9"); kp[4] = new Fl_Button(320, 40, 30, 30, "4"); kp[5] = new Fl_Button(350, 40, 30, 30, "5"); kp[6] = new Fl_Button(380, 40, 30, 30, "6"); kp[1] = new Fl_Button(320, 70, 30, 30, "1"); kp[2] = new Fl_Button(350, 70, 30, 30, "2"); kp[3] = new Fl_Button(380, 70, 30, 30, "3"); kp[0] = new Fl_Button(320, 100, 60, 30, "0"); kp[10] = new Fl_Button(380, 100, 30, 30, "."); for (int i=0; i<11; i++) { kp[i]->compact(1); kp[i]->selection_color(FL_SELECTION_COLOR); } keypad->end(); // Add a scheme choice widget for easier testing. Position the widget at // the right window border so the menu popup doesn't cover the check boxes etc. Fl_Scheme_Choice *scheme_choice = new Fl_Scheme_Choice(180, 130, 130, 30, "Active FLTK Scheme:"); scheme_choice->tooltip("Fl_Scheme_Choice"); window->end(); window->resizable(window); window->size_range(320, 130); window->show(argc, argv); return Fl::run(); } fltk-1.4.3/test/keyboard.h0000644000175000017500000000141115004135251015532 0ustar albrechtalbrecht// // Keyboard/event test header for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef keyboard_h # define keyboard_h # include # include # include class MyWindow : public Fl_Window { int handle(int) FL_OVERRIDE; public: MyWindow(int w, int h, const char *t=0L) : Fl_Window( w, h, t ) { } }; #endif // !keyboard_h fltk-1.4.3/test/threads.h0000644000175000017500000000441215004135251015370 0ustar albrechtalbrecht// // Simple threading API for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Inline classes to provide portable support for threads and mutexes. // // FLTK does not use this (it has an internal mutex implementation // that is used if Fl::lock() is called). This header file's only // purpose is so we can write portable demo programs. It may be useful // or an inspiration to people who want to try writing multithreaded // programs themselves. // // FLTK has no multithreaded support unless the main thread calls Fl::lock(). // This main thread is the only thread allowed to call Fl::run() or Fl::wait(). // From then on FLTK will be locked except when the main thread is actually // waiting for events from the user. Other threads must call Fl::lock() and // Fl::unlock() to surround calls to FLTK (such as to change widgets or // redraw them). #ifndef Threads_H # define Threads_H # ifdef HAVE_PTHREAD_H // Use POSIX threading... # include typedef pthread_t Fl_Thread; extern "C" { typedef void *(Fl_Thread_Func)(void *); } static int fl_create_thread(Fl_Thread& t, Fl_Thread_Func* f, void* p) { return pthread_create((pthread_t*)&t, 0, f, p); } # elif defined(_WIN32) && !defined(__WATCOMC__) // Use Windows threading... # include # include typedef unsigned long Fl_Thread; extern "C" { typedef void *(__cdecl Fl_Thread_Func)(void *); } static int fl_create_thread(Fl_Thread& t, Fl_Thread_Func* f, void* p) { return t = (Fl_Thread)_beginthread((void( __cdecl * )( void * ))f, 0, p); } # elif defined(__WATCOMC__) # include typedef unsigned long Fl_Thread; extern "C" { typedef void *(__cdecl Fl_Thread_Func)(void *); } static int fl_create_thread(Fl_Thread& t, Fl_Thread_Func* f, void* p) { return t = (Fl_Thread)_beginthread((void(* )( void * ))f, 32000, p); } # endif // !HAVE_PTHREAD_H #endif // !Threads_h fltk-1.4.3/test/unittest_complex_shapes.cxx0000644000175000017500000002760315004135251021271 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include #include #include #include #include #include #if HAVE_GL #include #endif // // --- test drawing circles and arcs ------ // class Ut_Complex_Shapes_Test; void draw_complex(Ut_Complex_Shapes_Test *p); #if HAVE_GL class Ut_GL_Complex_Shapes_Test : public Fl_Gl_Window { public: Ut_GL_Complex_Shapes_Test(int x, int y, int w, int h) : Fl_Gl_Window(x, y, w, h) { box(FL_FLAT_BOX); end(); } void draw() FL_OVERRIDE { draw_begin(); Fl_Window::draw(); draw_complex((Ut_Complex_Shapes_Test*)parent()); draw_end(); } }; #endif class Ut_Native_Complex_Shapes_Test : public Fl_Window { public: Ut_Native_Complex_Shapes_Test(int x, int y, int w, int h) : Fl_Window(x, y, w, h) { box(FL_FLAT_BOX); end(); } void draw() FL_OVERRIDE { Fl_Window::draw(); draw_complex((Ut_Complex_Shapes_Test*)parent()); } }; // //------- test the compelx shape drawing capabilities of this implementation ---------- // class Ut_Complex_Shapes_Test : public Fl_Group { Ut_Native_Complex_Shapes_Test* native_test_window; #if HAVE_GL Ut_GL_Complex_Shapes_Test* gl_test_window; #endif static void update_cb(Fl_Widget*, void *v) { Ut_Complex_Shapes_Test* This = (Ut_Complex_Shapes_Test*)v; This->native_test_window->redraw(); #if HAVE_GL This->gl_test_window->redraw(); #endif } public: Fl_Hor_Value_Slider* scale; Fl_Dial* rotate; Fl_Positioner* position; void set_transformation() { fl_translate(position->xvalue(), position->yvalue()); fl_rotate(-rotate->value()); fl_scale(scale->value(), scale->value()); } static Fl_Widget* create() { return new Ut_Complex_Shapes_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } Ut_Complex_Shapes_Test(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { label("Testing complex shape drawing."); align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_WRAP); box(FL_BORDER_BOX); int a = x+16, b = y+34; Fl_Box *t = new Fl_Box(a, b-24, 80, 18, "native"); t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); native_test_window = new Ut_Native_Complex_Shapes_Test(a+23, b-1, 200, 200); t = new Fl_Box(a, b, 18, 18, "1"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing complex drawing with transformations.\n\n" // Description: "Draw a point pattern, an open line, a closed line, and a covenx polygon.\n\n" // Things to look out for: "Use the controls at the bottom right to scale, rotate, and move the patterns." ); b+=44; t = new Fl_Box(a, b, 18, 18, "2"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing complex polygons.\n\n" // Description: "Draw polygons at different leves of complexity. " "All polygons should be within the blue boundaries\n\n" // Things to look out for: "1: a convex polygon\n" "2: a non-convex polygon\n" "3: two polygons in a single operation\n" "4: a polygon with a square hole in it" ); b+=44; t = new Fl_Box(a, b, 18, 18, "3"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing complex polygons with arcs.\n\n" // Description: "Draw polygons with an arc section. " "All polygons should be within the blue boundaries\n\n" // Things to look out for: "1: a polygon with a camel hump\n" "2: a polygon with a camel dip" ); #if HAVE_GL a = x+16+250, b = y+34; t = new Fl_Box(a, b-24, 80, 18, "OpenGL"); t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); gl_test_window = new Ut_GL_Complex_Shapes_Test(a+31, b-1, 200, 200); t = new Fl_Box(a, b, 26, 18, "1a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing complex drawing with transformations.\n\n" // Description: "Draw a point pattern, an open line, a closed line, and a convex polygon.\n\n" // Things to look out for: "Use the controls at the bottom right to scale, rotate, and move the patterns." ); b+=44; t = new Fl_Box(a, b, 28, 18, "2a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing complex polygons.\n\n" // Description: "Draw polygons at different leves of complexity. " "All polygons should be within the blue boundaries\n\n" // Things to look out for: "1: a convex polygon\n" "2: a non-convex polygon\n" "3: two polygons in a single operation\n" "4: a polygon with a square hole in it" ); b+=44; t = new Fl_Box(a, b, 28, 18, "3a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing complex polygons with arcs.\n\n" // Description: "Draw polygons with an arc section. " "All polygons should be within the blue boundaries\n\n" // Things to look out for: "1: a polygon with a camel hump\n" "2: a polygon with a camel dip" ); #endif a = UT_TESTAREA_X+UT_TESTAREA_W-250; b = UT_TESTAREA_Y+UT_TESTAREA_H-50; scale = new Fl_Hor_Value_Slider(a, b+10, 120, 20, "Scale:"); scale->align(FL_ALIGN_TOP_LEFT); scale->range(0.8, 1.2); scale->value(1.0); scale->callback(update_cb, this); rotate = new Fl_Dial(a+140, b, 40, 40, "Rotate:"); rotate->align(FL_ALIGN_TOP_LEFT); rotate->angles(0, 360); rotate->range(-180.0, 180.0); rotate->value(0.0); rotate->callback(update_cb, this); position = new Fl_Positioner(a+200, b, 40, 40, "Offset:"); position->align(FL_ALIGN_TOP_LEFT); position->xbounds(-10, 10); position->ybounds(-10, 10); position->value(0.0, 0.0); position->callback(update_cb, this); t = new Fl_Box(a-1, b-1, 1, 1); resizable(t); } }; void convex_shape(int w, int h) { fl_vertex(-w/2, -h); fl_vertex(w/2, -h); fl_vertex(w, 0); fl_vertex(w, h); fl_vertex(0, h); fl_vertex(-w, h/2); fl_vertex(-w, -h/2); } void complex_shape(int w, int h) { fl_vertex(-w/2, -h); fl_vertex(0, -h/2); fl_vertex(w/2, -h); fl_vertex(w, 0); fl_vertex(w, h); fl_vertex(0, h); fl_vertex(-w, h/2); fl_vertex(-w/2, 0); fl_vertex(-w, -h/2); } void two_complex_shapes(int w, int h) { fl_vertex(-w/2, -h); fl_vertex(w/2, -h); fl_vertex(w, 0); fl_vertex(w, h-3); fl_gap(); fl_vertex(w-3, h); fl_vertex(0, h); fl_vertex(-w, h/2); fl_vertex(-w, -h/2); } void complex_shape_with_hole(int w, int h) { int w2 = w/3, h2 = h/3; // clockwise fl_vertex(-w/2, -h); fl_vertex(w/2, -h); fl_vertex(w, 0); fl_vertex(w, h); fl_vertex(0, h); fl_vertex(-w, h/2); fl_vertex(-w, -h/2); fl_gap(); // counterclockwise fl_vertex(-w2, -h2); fl_vertex(-w2, h2); fl_vertex( w2, h2); fl_vertex( w2, -h2); } void draw_complex(Ut_Complex_Shapes_Test *p) { int a = 0, b = 0, dx = 20, dy = 20, w = 10, h = 10; int w2 = w/3, h2 = h/3; // ---- 1: draw a random shape fl_color(FL_BLACK); // -- points fl_push_matrix(); fl_translate(a+dx, b+dy); p->set_transformation(); fl_begin_points(); convex_shape(w, h); fl_end_points(); fl_pop_matrix(); // -- lines fl_push_matrix(); fl_translate(a+dx+50, b+dy); p->set_transformation(); fl_begin_line(); convex_shape(w, h); fl_end_line(); fl_pop_matrix(); // -- line loop fl_push_matrix(); fl_translate(a+dx+100, b+dy); p->set_transformation(); fl_begin_loop(); convex_shape(w, h); fl_end_loop(); fl_pop_matrix(); // -- polygon fl_push_matrix(); fl_translate(a+dx+150, b+dy); p->set_transformation(); fl_begin_polygon(); convex_shape(w, h); fl_end_polygon(); fl_pop_matrix(); // ---- 2: draw a complex shape b += 44; // -- covex polygon drawn in complex mode fl_push_matrix(); fl_translate(a+dx, b+dy); p->set_transformation(); fl_color(FL_DARK2); fl_begin_complex_polygon(); convex_shape(w, h); fl_end_complex_polygon(); fl_color(FL_BLUE); fl_begin_loop(); convex_shape(w, h); fl_end_loop(); fl_pop_matrix(); // -- non-convex polygon drawn in complex mode fl_push_matrix(); fl_translate(a+dx+50, b+dy); p->set_transformation(); fl_color(FL_DARK2); fl_begin_complex_polygon(); complex_shape(w, h); fl_end_complex_polygon(); fl_color(FL_BLUE); fl_begin_loop(); complex_shape(w, h); fl_end_loop(); fl_pop_matrix(); // -- two part polygon with gap fl_push_matrix(); fl_translate(a+dx+100, b+dy); p->set_transformation(); fl_color(FL_DARK2); fl_begin_complex_polygon(); two_complex_shapes(w, h); fl_end_complex_polygon(); fl_color(FL_BLUE); fl_begin_loop(); fl_vertex(-w/2, -h); fl_vertex(w/2, -h); fl_vertex(w, 0); fl_vertex(w, h-3); fl_end_loop(); fl_begin_loop(); fl_vertex(w-3, h); fl_vertex(0, h); fl_vertex(-w, h/2); fl_vertex(-w, -h/2); fl_end_loop(); fl_pop_matrix(); // -- polygon with a hole fl_push_matrix(); fl_translate(a+dx+150, b+dy); p->set_transformation(); fl_color(FL_DARK2); fl_begin_complex_polygon(); complex_shape_with_hole(w, h); fl_end_complex_polygon(); fl_color(FL_BLUE); fl_begin_loop(); fl_vertex(-w/2, -h); fl_vertex(w/2, -h); fl_vertex(w, 0); fl_vertex(w, h); fl_vertex(0, h); fl_vertex(-w, h/2); fl_vertex(-w, -h/2); fl_end_loop(); fl_begin_loop(); fl_vertex(-w2, -h2); fl_vertex(-w2, h2); fl_vertex( w2, h2); fl_vertex( w2, -h2); fl_end_loop(); fl_pop_matrix(); // ---- 3: draw polygons with arcs b += 44; // -- a rectangle with a camel hump fl_push_matrix(); fl_translate(a+dx, b+dy); p->set_transformation(); fl_color(FL_DARK2); fl_begin_complex_polygon(); fl_vertex(-w, 0); fl_arc(0, 0, w-3, 180.0, 0.0); fl_vertex(w, 0); fl_vertex(w, h); fl_vertex(-w, h); fl_end_complex_polygon(); fl_color(FL_BLUE); fl_begin_loop(); fl_vertex(-w, 0); fl_arc(0, 0, w-3, 180.0, 0.0); fl_vertex(w, 0); fl_vertex(w, h); fl_vertex(-w, h); fl_end_loop(); fl_pop_matrix(); // -- a rectangle with a camel dip fl_push_matrix(); fl_translate(a+dx+50, b+dy); p->set_transformation(); fl_color(FL_DARK2); fl_begin_complex_polygon(); fl_vertex(-w, 0); fl_arc(0, 0, w-3, 180.0, 360.0); fl_vertex(w, 0); fl_vertex(w, h); fl_vertex(-w, h); fl_end_complex_polygon(); fl_color(FL_BLUE); fl_begin_loop(); fl_vertex(-w, 0); fl_arc(0, 0, w-3, 180.0, 360.0); fl_vertex(w, 0); fl_vertex(w, h); fl_vertex(-w, h); fl_end_loop(); fl_pop_matrix(); // -- a rectangle with a bezier curve top fl_push_matrix(); fl_translate(a+dx+100, b+dy); p->set_transformation(); fl_color(FL_DARK2); fl_begin_complex_polygon(); fl_vertex(-w, 0); fl_curve(-w+3, 0, 0, -h, 0, h, w-3, 0); fl_vertex(w, 0); fl_vertex(w, h); fl_vertex(-w, h); fl_end_complex_polygon(); fl_color(FL_BLUE); fl_begin_loop(); fl_vertex(-w, 0); fl_curve(-w+3, 0, 0, -h, 0, h, w-3, 0); fl_vertex(w, 0); fl_vertex(w, h); fl_vertex(-w, h); fl_end_loop(); fl_pop_matrix(); } UnitTest complex_shapes(UT_TEST_COMPLEX_SHAPES, "Complex Shapes", Ut_Complex_Shapes_Test::create); fltk-1.4.3/test/unittest_about.cxx0000644000175000017500000000466315004135251017372 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include // //------- Introduction to FLTK drawing test ------- // class Ut_About_View : public Fl_Help_View { public: static Fl_Widget *create() { return new Ut_About_View(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } Ut_About_View(int x, int y, int w, int h) : Fl_Help_View(x, y, w, h) { value( "

About Unit Testing...

\n" "The Unit Testing application can be used to verify correct graphics rendering " "on the current platform. The core developer team uses this program to make sure that the " "FLTK user experience is identical on all supported graphics systems." "

The UI Designer

\n" "

Designing a good user interface is an art. Widgets must be selected and carefully positioned " "to create a consistent look and feel for the user. Text must fit into given boxes and graphic " "elements must be correctly aligned. A good UI library will give consistent results on any " "supported platform and render all graphics in the way the UI designer intended.

\n" "

FLTK supports a large collection of platforms and graphics drivers. This unit testing " "application contains modules which will test rendering and alignment for most " "FLTK core graphics functions.

\n" "

The Developer

\n" "

Unittest is also a great help when implementing new graphics drivers. The tests are sorted " "in the same order in which a new graphics driver could be implemented. Most tests rely " "on the previous test to function correctly, so sticking to the given order is a good idea.

\n" "

Conventions

\n" "

Two layers of graphics are drawn for most tests. The lower layer contains " "red and green pixels. The upper layer contains black pixels. The test is rendered correctly " "if all red pixels are covered, but none of the green pixels. The top graphics layer can be " "switched on and off.

" ""); } }; UnitTest about(UT_TEST_ABOUT, "About...", Ut_About_View::create); fltk-1.4.3/test/resize-example4b.cxx0000644000175000017500000000645115004135251017476 0ustar albrechtalbrecht// // Resize example for use in the Fast Light Tool Kit (FLTK) documentation. // // See Article #415: How does resizing work? // https://www.fltk.org/articles.php?L415 // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "resize-arrows.h" #include // window, complex and arrow dimensions int TLx = 35, TRx = 320, TLw = 260, Ww = 620; int TLy = 35, LGy = 100, TLh = 65, LGh = 80, LAh = 35, Wh = 200; Fl_Double_Window *window = 0; class Complex : public Fl_Group { public: Complex(int X, int Y, int W, int H, const char *T = 0); Fl_Box *m_button1, *m_input1, *m_button2, *m_input2; }; Complex::Complex(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->box(FL_UP_BOX); Fl_Group *LG = new Fl_Group(X + 10, Y + 10, 120, 45); LG->box(FL_UP_BOX); m_button1 = new Fl_Box(X + 20, Y + 20, 40, 25, "btn"); m_button1->box(FL_UP_BOX); m_input1 = new Fl_Box(X + 70, Y + 20, 50, 25, "input"); m_input1->box(FL_UP_BOX); m_input1->color(FL_YELLOW); LG->resizable(m_input1); LG->end(); Fl_Group *RG = new Fl_Group(X + 130, Y + 10, 120, 45); RG->box(FL_UP_BOX); m_button2 = new Fl_Box(X + 140, Y + 20, 40, 25, "btn"); m_button2->box(FL_UP_BOX); m_input2 = new Fl_Box(X + 190, Y + 20, 50, 25, "input"); m_input2->box(FL_UP_BOX); m_input2->color(FL_YELLOW); RG->resizable(m_input2); RG->end(); this->end(); } class Resizables : public Fl_Group { public: Resizables(int X, int Y, int W, int H, const char *T = 0); Complex *TL, *TR; // topleft, topright Harrow *LA, *RA; // left arrow, right arrow }; Resizables::Resizables(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { TL = new Complex(X + TLx, Y + TLy, TLw, TLh, "Original"); TL->align(FL_ALIGN_TOP_LEFT); TR = new Complex(X + TRx, Y + TLy, TLw, TLh, "Horizonally Resized"); TR->align(FL_ALIGN_TOP_LEFT); Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); LG->box(FL_NO_BOX); LG->color(FL_WHITE); LA = new Harrow(TL->m_input2->x(), LG->y(), TL->m_input2->w(), LAh, "Initial\nwidth"); LG->resizable(LA); LG->end(); Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); RG->box(FL_NO_BOX); RG->color(FL_WHITE); Fl_Group *RG0 = new Fl_Group(X + TRx, Y + LGy, TLw / 2, LGh); RG0->box(FL_NO_BOX); RG0->color(FL_WHITE); RG0->end(); Fl_Group *RG1 = new Fl_Group(X + TRx + TLw / 2, Y + LGy, TLw / 2, LGh); RG1->box(FL_NO_BOX); RG1->color(FL_WHITE); RA = new Harrow(TR->m_input2->x(), RG1->y(), TR->m_input2->w(), LAh, "Resized\nwidth"); RG1->resizable(RA); RG1->end(); RG->end(); this->resizable(TR); this->end(); } int main(int argc, char **argv) { window = new Fl_Double_Window(Ww, Wh, "resize-example4b"); window->color(FL_WHITE); Resizables *resizables = new Resizables(0, 0, Ww, Wh); window->end(); window->resizable(resizables); window->size_range(Ww, Wh); window->show(argc, argv); window->size(Ww + 90, Wh); return Fl::run(); } fltk-1.4.3/test/resize-example2.cxx0000644000175000017500000001103115004135251017320 0ustar albrechtalbrecht// // Resize example for use in the Fast Light Tool Kit (FLTK) documentation. // // See Article #415: How does resizing work? // https://www.fltk.org/articles.php?L415 // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "resize-arrows.h" #include // inner box dimensions int Ax = 0, Bx = 35, Cx = 70, Dx = 105, Nx = 140, Aw = 35, Rw = 70, Mw = 140; int Ay = 0, Ey = 35, Gy = 70, Iy = 105, My = 140, Ah = 35, Rh = 70, Nh = 175; // resize box and arrow group dimensions int TLx = 35, TRx = 245, TGx = 420, TLw = 175, TGw = 140, TAw = 35; int TLy = 35, BLy = 245, LGy = 420, TLh = 175, LGh = 105, LAh = 35; // window dimensions int Ww = 560, Wh = 525; Fl_Double_Window *window; class Resizebox : public Fl_Group { public: Resizebox(int X, int Y, int W, int H, const char *T); Fl_Box *m_box; }; Resizebox::Resizebox(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->align(FL_ALIGN_TOP_LEFT); this->box(FL_UP_BOX); Fl_Box *b; b = new Fl_Box(FL_FRAME_BOX, X + Ax, Y + Ay, Aw, Ah, "A"); b->color(14); b = new Fl_Box(FL_FRAME_BOX, X + Bx, Y + Ay, Aw, Ah, "B"); b->color(9); b = new Fl_Box(FL_FRAME_BOX, X + Cx, Y + Ay, Aw, Ah, "C"); b->color(10); b = new Fl_Box(FL_FRAME_BOX, X + Dx, Y + Ay, Aw, Ah, "D"); b->color(11); b = new Fl_Box(FL_FRAME_BOX, X + Ax, Y + Ey, Aw, Ah, "E"); b->color(9); b = new Fl_Box(FL_FRAME_BOX, X + Bx, Y + Ey, Rw, Rh, "R"); b->color(3); b->label("resizable"); m_box = b; b = new Fl_Box(FL_FRAME_BOX, X + Dx, Y + Ey, Aw, Ah, "F"); b->color(12); b = new Fl_Box(FL_FRAME_BOX, X + Ax, Y + Gy, Aw, Ah, "G"); b->color(10); b = new Fl_Box(FL_FRAME_BOX, X + Dx, Y + Gy, Aw, Ah, "H"); b->color(13); b = new Fl_Box(FL_FRAME_BOX, X + Ax, Y + Iy, Aw, Ah, "I"); b->color(11); b = new Fl_Box(FL_FRAME_BOX, X + Bx, Y + Iy, Aw, Ah, "J"); b->color(12); b = new Fl_Box(FL_FRAME_BOX, X + Cx, Y + Iy, Aw, Ah, "K"); b->color(13); b = new Fl_Box(FL_FRAME_BOX, X + Dx, Y + Iy, Aw, Ah, "L"); b->color(14); b = new Fl_Box(FL_FRAME_BOX, X + Ax, Y + My, Mw, Ah, "M"); b->color(12); b = new Fl_Box(FL_FRAME_BOX, X + Nx, Y + Ay, Aw, Nh, "N"); b->color(13); this->end(); this->resizable(m_box); } class Resizables : public Fl_Group { public: Resizables(int X, int Y, int W, int H, const char *T = 0); Resizebox *TL, *TR, *BL, *BR; // topleft, topright, bottomleft, bottomright Harrow *LA, *RA; // left arrow, right arrow Varrow *TA, *BA; // top arrow, bottom arrow }; Resizables::Resizables(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->box(FL_UP_BOX); this->color(FL_WHITE); TL = new Resizebox(X + TLx, Y + TLy, TLw, TLh, "Original Size"); TL->resizable(0); TR = new Resizebox(X + TRx, Y + TLy, TLw, TLh, "Horizontally Resized"); BL = new Resizebox(X + TLx, Y + BLy, TLw, TLh, "Vertically Resized"); BR = new Resizebox(X + TRx, Y + BLy, TLw, TLh, "Horizontally and Vertically Resized"); Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); LG->box(FL_NO_BOX); LG->color(FL_WHITE); LA = new Harrow(BL->m_box->x(), LG->y(), BL->m_box->w(), LAh, "Initial\nwidth"); LG->resizable(LA); LG->end(); Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); RG->box(FL_NO_BOX); RG->color(FL_WHITE); RA = new Harrow(BR->m_box->x(), LG->y(), BL->m_box->w(), LAh, "Resized\nwidth"); RG->resizable(RA); RG->end(); Fl_Group *TG = new Fl_Group(X + TGx, Y + TLy, TGw, TLh); TG->box(FL_NO_BOX); TG->color(FL_WHITE); TA = new Varrow(TG->x(), TR->m_box->y(), TAw, TR->m_box->h(), "Initial\nheight"); TG->resizable(TA); TG->end(); Fl_Group *BG = new Fl_Group(X + TGx, Y + BLy, TGw, TLh); BG->box(FL_NO_BOX); BG->color(FL_WHITE); BA = new Varrow(BG->x(), BR->m_box->y(), TAw, BR->m_box->h(), "Resized\nheight"); BG->resizable(BA); BG->end(); this->resizable(BR); this->end(); } int main(int argc, char **argv) { window = new Fl_Double_Window(Ww, Wh, "resize-example2"); window->color(FL_WHITE); Resizables *resizables = new Resizables(0, 0, Ww, Wh); window->end(); window->resizable(resizables); window->size_range(Ww, Wh); window->show(argc, argv); window->size(Ww + 140, Wh + 35); return Fl::run(); } fltk-1.4.3/test/fonts.cxx0000644000175000017500000002210315004135251015437 0ustar albrechtalbrecht// // Font demo program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include #include Fl_Double_Window *form; Fl_Tile *tile; Fl_Window *vector_font_editor = 0; class FontDisplay : public Fl_Widget { void draw() FL_OVERRIDE; public: int font, size; FontDisplay(Fl_Boxtype B, int X, int Y, int W, int H, const char* L = 0) : Fl_Widget(X,Y,W,H,L) {box(B); font = 0; size = 14;} }; void FontDisplay::draw() { draw_box(); fl_font((Fl_Font)font, size); fl_color(FL_BLACK); fl_draw(label(), x()+3, y()+3, w()-6, h()-6, align()); } FontDisplay *textobj; Fl_Hold_Browser *fontobj, *sizeobj; int **sizes; int *numsizes; int pickedsize = 14; void font_cb(Fl_Widget *, long) { int fn = fontobj->value(); if (!fn) return; fn--; textobj->font = fn; sizeobj->clear(); int n = numsizes[fn]; int *s = sizes[fn]; if (!n) { // no sizes } else if (s[0] == 0) { // many sizes; int j = 1; for (int i = 1; i<64 || iadd(buf); } sizeobj->value(pickedsize); } else { // some sizes int w = 0; for (int i = 0; i < n; i++) { if (s[i]<=pickedsize) w = i; char buf[20]; snprintf(buf, 20,"@b%d",s[i]); sizeobj->add(buf); } sizeobj->value(w+1); } textobj->redraw(); } void size_cb(Fl_Widget *, long) { int i = sizeobj->value(); if (!i) return; const char *c = sizeobj->text(i); while (*c < '0' || *c > '9') c++; pickedsize = atoi(c); textobj->size = pickedsize; textobj->redraw(); } char label[0x1000]; unsigned char current_char = 'A'; unsigned char vec[255][128] = { { 0 } }; class LetterBox : public Fl_Group { public: LetterBox(int x, int y, int w, int h, const char *l) : Fl_Group(x, y, w, h, l) { } void draw() FL_OVERRIDE { draw_box(); fl_push_clip(x(), y(), w(), h()); draw_label(x(), y()-5, w(), h()-16, FL_ALIGN_CENTER); fl_color(FL_BLUE); fl_line_style(FL_SOLID|FL_CAP_ROUND|FL_JOIN_ROUND, 10); bool rendering = false; unsigned char *fd = vec[current_char]; double px, py; for (;;) { unsigned char cmd = *fd++; if (cmd==0) { if (rendering) { fl_end_line(); rendering = false; } break; } else if (cmd>63) { if (cmd=='\100' && rendering) { fl_end_line(); rendering = false; } } else { if (!rendering) { fl_begin_line(); rendering = true; } int vx = (cmd & '\70')>>3; int vy = (cmd & '\07'); px = (vx*16+8+10); py = (vy*32+16+10); fl_vertex(px, py); } } fl_line_style(FL_SOLID, 1); draw_children(); fl_pop_clip(); } }; void add_point_cb(Fl_Widget *w, void *d) { unsigned char *fd = vec[current_char]; while (*fd) fd++; *fd = (fl_uchar)(d); w->parent()->redraw(); } void add_gap_cb(Fl_Widget *w, void *d) { unsigned char *fd = vec[current_char]; while (*fd) fd++; *fd = '\100'; w->parent()->redraw(); } void clear_cb(Fl_Widget *w, void *d) { unsigned char *fd = vec[current_char]; memset(fd, 0, 128); w->parent()->redraw(); } void prev_cb(Fl_Widget *w, void *d) { current_char--; char b[2] = { (char)current_char, 0 }; w->parent()->child(0)->copy_label(b); w->parent()->child(0)->redraw(); } void next_cb(Fl_Widget *w, void *d) { current_char++; char b[2] = { (char)current_char, 0 }; w->parent()->child(0)->copy_label(b); w->parent()->child(0)->redraw(); } void back_cb(Fl_Widget *w, void *d) { unsigned char *fd = vec[current_char]; if (*fd==0) return; while (*fd) fd++; *(--fd) = 0; w->parent()->child(0)->redraw(); } void save_cb(Fl_Widget *w, void *d) { const char *filename = fl_file_chooser("Save font as:", 0, 0); if (!filename) return; FILE *f = fopen(filename, "wb"); if (!f) { fl_alert("can't open file for writing"); return; } fprintf(f, "\nstatic const char *font_data[128] = {\n "); for (int i=0; i<128; i++) { unsigned char *fd = vec[i]; if (i>=32 && i<127) fprintf(f, "/*%c*/", i); else fprintf(f, "/*%02X*/", i); if (*fd==0) { fprintf(f, "0"); } else { fprintf(f, "\""); for (;;) { unsigned char c = *fd++; if (c==0) break; fprintf(f, "\\%02o", c); } fprintf(f, "\""); } if (i<127) fprintf(f, ", "); if ((i&3)==3)fprintf(f, "\n "); } fprintf(f, "};\n\n"); fclose(f); } Fl_Window *create_editor() { Fl_Window *win = new Fl_Double_Window(400,400); LetterBox *c = new LetterBox(10, 10, 128, 256, "A"); //c->labelfont(FL_COURIER); c->align(FL_ALIGN_CENTER); c->labelsize(200); c->labelcolor(FL_DARK3); c->box(FL_DOWN_BOX); Fl_Button *b; int i, j; for (i=0; i<8; i++) { for (j=0; j<8; j++) { b = new Fl_Button(i*16+8-5+10, j*32+16-5+10, 10, 10); b->box(FL_OVAL_BOX); b->callback(add_point_cb, (void*)(fl_intptr_t)(i*8+j)); } } c->end(); b = new Fl_Button(10, 290, 70, 20, "Gap"); b->callback(add_gap_cb); b = new Fl_Button(90, 290, 70, 20, "Clear"); b->callback(clear_cb); b = new Fl_Button(10, 315, 70, 20, "<-"); b->callback(prev_cb); b->shortcut(FL_Left); b = new Fl_Button(90, 315, 70, 20, "->"); b->callback(next_cb); b->shortcut(FL_Right); b = new Fl_Button(10, 340, 70, 20, "Back"); b->callback(back_cb); b = new Fl_Button(90, 340, 70, 20, "Save"); b->callback(save_cb); b->shortcut(FL_COMMAND+'s'); return win; } class Ut_Main_Window : public Fl_Double_Window { public: Ut_Main_Window(int w, int h, const char *l=0) : Fl_Double_Window(w, h, l) { } int handle(int event) FL_OVERRIDE { if (event==FL_KEYBOARD && Fl::event_key()==FL_F+1) { if (!vector_font_editor) vector_font_editor = create_editor(); vector_font_editor->show(); return 1; } else { return Fl_Double_Window::handle(event); } } }; void create_the_forms() { // create the sample string int n = 0; strcpy(label, "Hello, world!\n"); int i = (int)strlen(label); ulong c; for (c = ' '+1; c < 127; c++) { if (!(c&0x1f)) label[i++] = '\n'; if (c == '@') label[i++] = '@'; label[i++] = (char)c; } label[i++] = '\n'; for (c = 0xA1; c < 0x600; c += 9) { if (!(++n&(0x1f))) label[i++]='\n'; i += fl_utf8encode((unsigned int)c, label + i); } label[i] = 0; // create the basic layout form = new Ut_Main_Window(550,370); tile = new Fl_Tile(0, 0, 550, 370); Fl_Group *textgroup = new Fl_Group(0, 0, 550, 185); textgroup->box(FL_FLAT_BOX); textobj = new FontDisplay(FL_FRAME_BOX,10,10,530,170,label); textobj->align(FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP); textobj->color(9,47); textgroup->resizable(textobj); textgroup->end(); Fl_Group *fontgroup = new Fl_Group(0, 185, 550, 185); fontgroup->box(FL_FLAT_BOX); fontobj = new Fl_Hold_Browser(10, 190, 390, 170); fontobj->box(FL_FRAME_BOX); fontobj->color(53,3); fontobj->callback(font_cb); sizeobj = new Fl_Hold_Browser(410, 190, 130, 170); sizeobj->box(FL_FRAME_BOX); sizeobj->color(53,3); sizeobj->callback(size_cb); fontgroup->resizable(fontobj); fontgroup->end(); tile->end(); form->resizable(tile); form->end(); } int main(int argc, char **argv) { Fl::scheme(NULL); Fl::args_to_utf8(argc, argv); // for MSYS2/MinGW Fl::args(argc, argv); Fl::get_system_colors(); create_the_forms(); // For the Unicode test, get all fonts... //#ifdef __APPLE__ int i = 0; //#else // int i = fl_choice("Which fonts:","-*","iso8859","All"); //#endif int k = Fl::set_fonts(i ? (i>1 ? "*" : 0) : "-*"); sizes = new int*[k]; numsizes = new int[k]; for (i = 0; i < k; i++) { int t; const char *name = Fl::get_font_name((Fl_Font)i,&t); char buffer[128]; #if 1 if (t) { char *p = buffer; if (t & FL_BOLD) {*p++ = '@'; *p++ = 'b';} if (t & FL_ITALIC) {*p++ = '@'; *p++ = 'i';} *p++ = '@'; *p++ = '.'; // Suppress subsequent formatting - some MS fonts have '@' in their name strcpy(p,name); name = buffer; } #else // this is neat, but really slow on some X servers: sprintf(buffer, "@F%d@.%s", i, name); name = buffer; #endif fontobj->add(name); int *s; int n = Fl::get_font_sizes((Fl_Font)i, s); numsizes[i] = n; if (n) { sizes[i] = new int[n]; for (int j=0; jvalue(1); font_cb(fontobj,0); form->show(argc,argv); return Fl::run(); } fltk-1.4.3/test/fracviewer.h0000644000175000017500000000663515004135251016104 0ustar albrechtalbrecht/* * fracviewer.h [from agviewer.h (version 1.0)] * * AGV: a glut viewer. Routines for viewing a 3d scene w/ glut * * The two view movement modes are POLAR and FLYING. Both move the eye, NOT * THE OBJECT. You can never be upside down or twisted (roll) in either mode. * * A nice addition would be an examiner type trackball mode where you are * moving the object and so could see it from any angle. Also less restricted * flying and polar modes (fly upside down, do rolls, etc.). * * Controls for Polar are just left and middle buttons -- for flying it's * those plus 0-9 number keys and +/- for speed adjustment. * * See agv_example.c and agviewer.c for more info. Probably want to make * a copy of these and then edit for each program. This isn't meant to be * a library, just something to graft onto your own programs. * * I welcome any feedback or improved versions. * * Philip Winston - 4/11/95 * pwinston@hmc.edu * http://www.cs.hmc.edu/people/pwinston */ /* * Call agvInit() with glut's current window set to the window in * which you want to run the viewer. Right after creating it is fine. It * will remember that window for possible later use (see below) and * registers mouse, motion, and keyboard handlers for that window (see below). * * allowidle is 1 or 0 depnding on whether you will let AGV install * and uninstall an idle function. 0 means you will not let it (because * you will be having your own idle function). In this case it is your * responsibility to put a statement like: * * if (agvMoving) * agvMove(); * * at the end of your idle function, to let AGV update the viewpoint if it * is moving. * * If allowidle is 1 it means AGV will install its own idle which * will update the viewpoint as needed and send glutPostRedisplay() to the * window which was current when agvInit() was called. * * agvSetIdleAllow changes this value so you can let AGV install its idle * when your idle isn't installed. * */ void agvInit(int allowidle); void agvSetAllowIdle(int allowidle); /* * Set which movement mode you are in. */ typedef enum { FLYING, POLAR } MovementType; void agvSwitchMoveMode(int move); /* * agvViewTransform basically does the appropriate gluLookAt() for the * current position. So call it in your display on the projection matrix */ void agvViewTransform(void); /* * agvMoving will be set by AGV according to whether it needs you to call * agvMove() at the end of your idle function. You only need these if * you aren't allowing AGV to do its own idle. * (Don't change the value of agvMoving) */ extern int agvMoving; void agvMove(void); /* * These are the routines AGV registers to deal with mouse and keyboard input. * Keyboard input only matters in flying mode, and then only to set speed. * Mouse input only uses left two buttons in both modes. * These are all registered with agvInit(), but you could register * something else which called these, or reregister these as needed */ void agvHandleButton(int button, int state, int x, int y); void agvHandleMotion(int x, int y); void agvHandleKeys(unsigned char key, int x, int y); /* * Just an extra routine which makes an x-y-z axes (about 10x10x10) * which is nice for aligning things and debugging. Pass it an available * displaylist number. */ void agvMakeAxesList(int displaylist); void ncrossprod(float v1[3], float v2[3], float cp[3]); fltk-1.4.3/test/desktop/0000755000175000017500000000000015004135251015235 5ustar albrechtalbrechtfltk-1.4.3/test/desktop/blocks-128.png0000644000175000017500000003755115004135251017543 0ustar albrechtalbrechtPNG  IHDR9Q]bKGDC pHYs  tIME76?;tEXtComment̖ IDATxy$U}UU]ܾ;00&%,!%j$;Pb4i q!Q,LdDKD l vfar; ¹6 ; 7 R lt[K`j/ܿC[n)TI?ogkGM|2 gvHD b-$]xoq'kKо&p~Sokְag4o0|osyNd4-s5t| VYvҦI[vKxw8yl 2H e=!~,V𪳿I'>p|98>I4K!/~UUI(:QEd#Zts -wM o}KJy!_&H)4k31%7Ox/ { KM (l?A.0cEczz`-$. q׵v;r3z3.gD_y?W/y8!'*xT|+43#SOG,_19MjYvߘGvЎQ1-sFէtAL{3,"~ i%x{5JVirU~6F)jFk@vg~ntKdsW#`&~teZκ fZ%czt~ƃkb"ej~@7Da"KfOxmap&%X;gP8Tz= Pe_~Mt&& gZ|3x`CfrЉ9yn@r y\@*)qk MOeNN`, ,8)v1y+cncXK J'I<>TOe+Tkߩrw`,Pp"<+nPUɤZ}09$yl&h4H;y| 'N8Sn_%i39i7=.d-#P7"yx<64'WfNW"!(lv@Gsx ']J* 'Cyq'M%7]׶eǭcgVzӤow~vYi;rtɔhI6G{m=r拂:s ` e{ ǯ%H`6t;Z}_~Yկ|VLm#4:]yoD,NQj8fQX)ph=GHJҼE~|n*>(Q޴fIBI$l4lP*=Hq7빦gy@1=7<['1 xi )Ut:AD(JΝbiKվDW(#j*>ib&2hv":ͥk(W[=cjVLv#ۀuCZ3`Á /X^Np_=-`IIzX/}ۇ]`ɒ3Ɍ1q՞Oa|!?A?C,N >_;4-#ӣ'Ԍͤ> [Kz+No-Jn\"i7Sg`rJ0IGqV0R*%= 6$UWlzTM؄~*ۘ*[pŻl V1hġ68Gz ~w|ؖpZw6S|W<~2/}$=nz%~*X< ?fq.pN"loW9㫥>g,obXRMǷ`~NӃ|wlhc/puɄ e)/Ծh< `0Aѹv,XD[Dz̶Ш3X()P] Nfbl>+lB m0w>ryO& qrLC;7 HP6Cӥ 0jI[ If2k %mJEd"\Ęvy:w ̼ccex$qSEh4diwބ3O؎.?ذKF~rCG.}ρw$ҫťx*QEIǃc_o,|w=Z#UXi%vHkf+#-[w<,Xtr[3Y{hj4tv..7Wgzr Pov,&xGR|;~(kk$-IN$-ZO~.xNCZ%t&0itD" {$#%w=2gbJpbM_n<?dժUz=jcבi躎/{<)AJ>P+ZF&q\C:Ok{=cD啡2&><-Vdb jkQL{8H폆;0]xHmZMx} =Ky^ '/>X*WxR:TǍ@廢t3DE߅jp^| 7[NScl}8`V_(pz }jJ@3=:]Ƕ[Akrcݖ#VV1<=Z~&*q7>w7L, zv-@be0 ݖTR! ~w7~;r{gd|A-KЃ8 ]ۅH< \t`~8߃w;O-NP)@1ONwE %jNSesg2 S4ztRSEq2zxM<7NZn 2>kOv>VƂtbt?ҍgs|{ PB#"Qҩ@aA H$nPg3MP&:<ɵT*dib H?ݗ4<0! -XuAHe):;߬X4}cJp|.Rgz>)FƳ* N͖MjL8Z*:-5[ 9Z<@w0ڙ3gPjlg:s 7gܮ3]*6邇VŶG%j!//"1gM0?EQC +1? cp0v{<,5"i`.%X0봐pn. nyp\!Bp [?7``s  yh-S!66^b?2Ƣ_ I:Ψf˿ Ob?=Mef``dӧC`xrA~~(7ߛ[&hӼxub!:BzZlơ8M"\WHI/@{ :/ vh׀͏H^8IB7a-0U9|ߊB_}Ւ/][7UXnMNbP28rt!\rwwQO &*){0XB 6==̊O@9ZLlf3s:?7O_2)Abz -^P7 ڧuuZh5.NnMډA0?T\0OE"1S] ծbqkb6\vx +W]KS:m"~قf9OhxaBZÓ"*?+L_AEHLkշh:M:jW%ҋA S^upG3csuM}$:6?+|IPFD!QkP`EzR%%!%n^BșRy.~܉(}^$Z(RZrAf vA*pJ?|攎vGI4-:J\h5ĚKppn266>94BJ&4[O* +.&c R6MEZS<ж9xttic) 8l [`U"^(&LE1Hwp#8eO$UbLQNo-۟y3 7$8Eʦ{b*U\ i`S2)طD Pc(İ Ja["FC_RnqֽJhu b1+ Uc0|8`qA$s0x"nHN3 -~Qfc!S T}X͵cY>AQar|<&1EkH}AXL ;^!ø'I?jЬ 1ɰ+12V91H?C894%Sla >/Ve iGj%.+EFES>۶c uW ‚BNdqtmq!,ڷ=wt560e}gNf 0"/&N(S:j,ƺT m% ɅLo5W1(y_`\vN :bϗV̭SZY\gRIb5 fUC B6vo$@Eƒ[[xh7G; \a/HC~-]\9}!N[QL` 6p!~đM^D~$VH*s6X[q+rk^Nx|`bt:$IdYf=_C(ݑ A>sQYt8pk樷?&nÉ'Ą $I۶ypӣ|(=xG>ys"XT, b7F~_輚.CNVm *bh4?u. SOHVmw$K1jm*% 9"YXXlv9eq~xu{xGcҤcph۶F4M,ˤ Y$Y&zszOIDATQ*ARm]v|A!7Q)՚gJuBжz[C(Idaz<5}8zHJ{DG9[|rJTIlz=dbA4%aEAcY-lM"b{{~ZC dHKP ;Z' \4H)\B0t4 apŶm\G}#kxG>^ LIaqoBbs#-(Q"(zH$B:\#nEnk}}w2w^ߍ}>v:0Q/  -q 46[ [ [ahDQ\iTU @Q0x:<9X(Pɛ#e$V,MvL'"}J+(W躎,hq˲h4I:Pshx|)`hl3X+<'y $/A4Eד }.Fk+ʐ>HuKh$ŽaTZy[}ySؾijd9l$m}~aÌj3R`xI0%asx;7 u bxۗ}z'^ s]<ҙW@&}2n^0HXø-k2Ex[ ݵc%`P2?%,n۶_os# } oqo0A"W$ZXRCVFiJQ%C$vR?3>\]5WI'Hd%Gnצۭtem[Z;0*JjnGiyXèt;F4m$RcX|jW&'C!TP o,oV5f|KJHXq:ZH &'^GIu\ J$ H|t(#|~5վF@\` BO͐xv9)HI `>v5~Ʋ!J^ɩ8Jtۀ㯋Jt[J ~诧flf,+^Do|H]D#­ wK\@Zv>HAb%mm;HUx6dǿì>u0m d BKԼe "Ȳ;.XZ2YhV;_χ"X^sG4YњEApSjLaf;{y  .dOx ƊW͍\P? Q 5y~^kgpJ֧!O/ 1ؗ6gt|;j`+-dBD&TI7࡟zG%{>LkJRG*$(p=gONni\T'9Ǵ.̶b7 CSaAۓ6X2f֎3 't0FwElхt6M (P: c, C pLNОoWmDe|i/=}@m:JZi-2r׫Ie:x!w/'8}lpO$ڌ,Nt?K#b]YShU ͆1Ym=nV tN0 (LL,Siڳ m-mX36-HY:-'1XۍBw>}>6R`'G)]v-MOu#Z(%A, #@SQ ^S"J ىqA[^%_B_쏈k4pl\aji> ~8>im5x{@ng,< r)j]z-N(Lx>z4y˪L8TvH;I{)Rؒյ<յ<^"=m(Q7#R!;|_ vh4 Gյccٱ1lDe[!OQS)v=_$lVN{Y{0y ,G@d/aK ֩/aK RYGZO0]!JTJP׀5`a|i=C Qnn.R <$ ֭y 9*#, fЮXi!1=<\4Hw^0UG=?' ܎#AI3x%3x/ୈE62Kc%gMcF80\Sp8"$qTF2{>.Cſ@x#@/ Pa.*"w2;/7Wܶ#Xxu4KYV.&yv7G-)b[8߃+Ih?99a`1Ҁ=ܲxO$G8A 3t7HN,4 ǕQ0XJ>儉ʞ Fg{DU;`Ӑwov"޲}.":Iy1F a)u-±nM{$ HHΧ=efɤt&zo4f4ר#oy_ʃ˧b~EF+xIiRgf[}:=t{ro#!jă/8ݯ]MnbLuFԑcG\nN(ق_Z~2DW_˟?Kr|*5?WȠ>7eRȹzr, i <_WhW|哝}GӍwI3{D'ѡjePCH,E|2Y>ge}; r/ ɑv' \:'$v5*I=a\?5[yWF֝ӽK,T'{.G4 mv-NJu#,yߙ-Wm`1v|" v]:|nK,C:=^/ca*َt|Xjm(9/ЇdG='mNF$9gUCg|'6 yޤHGAʂ1SC!A-|lcBagBam3LxN,8cBVRH~m2y1\G:>]!/0(*l9T-kII~/_LO&2^c_5&gv/]nlQ,z.U&;sb1rNǻ?ڝ];x?McBUPMF]0HE E Qc1p?qP&sdۃ*.w^u M&5?7/JX(hּTwS6PjUd XAQ_ڡ"!D|#DצA$W!SY.'w5p KB[\?)?B"jG&9LH#[/e(g:ZN AD\ۢ x feWaڔ ZXMڤPiH3 YhBm 7jXhTi-D}AЏt|<̀d+ cmeSm-!,L@QpYJ71侪 ";bpSI69* ڲCmSs7i`@bkn g6Xi2N '|nhGy=!v]0c6 IzK(EP.Wtź. #Jz"T:wH'9"¬ VXNN"V/aK~Tw5ς"q3AIr{r` .*` JWriLM[J  #Ml\V xԳe; spAAa2Quf+,z,+['w~\]i򙣼ۤC+$X1_ p+&TR!F #Jx K+x?~ZsD6cz=$K@(rH@$B[SQc1z>N2sHG4B#}J_r[[X+QAC%LsPp뿍J : k*~ .=(~ Jh sDrsl/:Mt>둳YCa5&VLY9"=J{.Ι), )0.42R`;;=~?7.3?;K9Oykֲn.y3<`P-/{W_;_GC"grjlIXlqHmh4ԍ6syJŝ<3MWe9)cO6zfLzI 5Wq xocQhXprj|U'ٹn㙬J7y&ƆE(HE,gGQ@?8NNZ[ 76U7d3h^_7wl~![o5+z-c$e"Ahÿn2vrj ۶vvINe5c1fO}6D)W,آ#Dzm3U(SD) V\稣u >-HPe9,QvoHNH$(F%OBjjtp 8>VlQ/)Ut>!Qf'LqgǢܵka+2^fSq \-q.ݮ޺RیHF[=znc{hjz ϵDXGβ[>5cY||T# ioN:Ps3tl|w_R$J"xj5#@|PNq.HIz fծ@~~(FQf,Ѫ( ]CAf/xw5$JaUցxBr>q!aoÎ~K|!AiHJ(]$N腵EokhTUxb a 6MCV0d2IBu] J1(z|l"gA` 39IA^VwlodYX1YvvQg-F1X&8d =>^݃=+DUn$=\&an>'F,}xNҎ}ǟėrt:!@E!!8·0ExMӈœȒ֛&q 9>soG(/$hY&H=A, R.%Gw2$C!F Io 6|'m8cjh4Vqh6}\Z5lD|.Ib(#߃ ňar_ ;Dx*jȲ Nu'Eu%:2cb&L!dz~;wa98h/)ϝ]Rj{EfE:!?Y"+[g]p!'qםlQw=m 4J:@=Z8N0vyzxw vLSbIENDB`fltk-1.4.3/test/desktop/sudoku-32.png0000644000175000017500000000044715004135251017504 0ustar albrechtalbrechtPNG  IHDR szzbKGD pHYs  tIME$*ZCIDATX _ bm#RϏ "& z07޽j<5ʪ{z>kp\-$| ePz3hpp,,E#`ʚ&;IA$l[dVG_2n`Y$a@+K(gIENDB`fltk-1.4.3/test/desktop/checkers.desktop0000644000175000017500000000023415004135251020416 0ustar albrechtalbrecht[Desktop Entry] Name=Checkers Comment=Checkers Game TryExec=checkers Exec=checkers Icon=checkers Terminal=false Type=Application Categories=Game;BoardGame; fltk-1.4.3/test/desktop/blocks.desktop0000644000175000017500000000024115004135251020102 0ustar albrechtalbrecht[Desktop Entry] Name=Block Attack! Comment=Block Attack! Game TryExec=blocks Exec=blocks Icon=blocks Terminal=false Type=Application Categories=Game;BlocksGame; fltk-1.4.3/test/desktop/blocks-32.png0000644000175000017500000000350015004135251017440 0ustar albrechtalbrechtPNG  IHDR }JbbKGDC pHYs  tIME86'gtEXtComment̖IDATXõ[pWrnI38Mြh v 4v@^?g%sF@ pJ ya*>s0J. L#LJ q8h8c>zzI?, Ό[#~K;=WHɗyhaV57aÐOrh+46aDߺ<~xo`0ȫKT@V70|t ?j IC1\2iKh<ǴAHR 0"%#I+G6nLP|'r&1<Smm^<'$}X[ƖcaH]]-/8 ^RHXĢbocx xTR\8I?3HPQidJjʡ!}veٟ +b, Bu?A;cs9O\N21f)ܰ|z`;қ֑t=$U& H9t;|f=1?\H wJ`%&d@H /cux>dZ!Ғ##p-a1\T<%k>ȃ?SqW8 s&[Adҽ8QmKs'QUid:vEGIu_'HdRD6Ãο+b1:rM06|EDM "ۀ(KeZL \2,K񍏺=qNJ$rMTb$GFwὫͬ@cv=7׭cN>ؾ<$mئ.hqD[oKY"~*C0IT )ժRjKTɊ(P9 j2v1c&c}p V]GW3~\p~I/l ..!g:]ɍPJ844Ä"zJ w8^C ju}ٯ>l"<&+W_##qia6۱ Ö;:^j(3iVF,i*G{=#8 ~`0bA?765@P~gPapx0\XA`ΝcYveed2uv^mmnIJ(}?ŋTOOOUU_ވFM.IVdB&gg=m6HWW-ˊ/ Â`}}['Uʗꊢi L&+ {<yt6=>ѣㅅ?poB$Y%n'Y㸼Q~p0Ldy~ml?Yb___w [t8tZ64,qAKKZ[P//oLL,}s*D1T(9]]~YV.paA&M>ϋS$pbaZ @Eű*Uvo`PMk>ߌBqpD" Br}}[ B\OOϕ+.wvs3gi)jMQL tu~²,J2ɲn8AuuI4:)BK˟b=;33?1L0L􇦦?F*9Ve% nvoK$R*UQ8.//'I"[?)HMVJO*>staa/&T*\hT)"n6^}{Byhtكe0MS|~$B:\ل/GQD[۠-8~ei[wy<{Ndz PBe>r6A AD2)5h4R\β~S+fhmmbpi8t||YB%ͪT'M57_ ~&AY, IJf낂AFF-ճTyyhaaRn_XRRܻ6Of3nX:HEȹx) @Kaű;wnz[TJV/"-1T fnH}&%d2 @2L&[:#K$,2%}ki *//9D";Z-`0_p!։kIENDB`fltk-1.4.3/test/desktop/checkers-128.png0000644000175000017500000005614715004135251020057 0ustar albrechtalbrechtPNG  IHDRL\ pHYs6[tIME'($ IDATxڜ}wUsNߝe7@BH(b@@: " *`'(H  BMh !ғM6۲o݄|^̹={yNyo\@ b$`\(qAB@.H8#K$q vA{`\)qAXUt "H0F\Qi$rȸ`ą:60'FHH O*q+EJނ.FD " } }Ub3G _lbC~Ν_l;0 INI޴1D`# _Ml(:)ǷEʰN_:fjby:FopX#- 8"^_@<_T3&;{iKόΨ'pM{F_D$!KbѠJh]6zl9#2PT"@H0`B1^LWT]{sQd;O?4ZiHɀ:X`BJ P:u1ܻXP(3wݹ߾D2 "  %ͩ'»c{|sS/~! D\',# A1 iouۯTxW]Uw=ty(`FdW2.8:UZleO /Nľ=!N%?{^}GW]5 !=t:W_]о``,,tVBh hشe˜y>)/{`0r|`$/M2oxO`G̘dvB O3kn &>uf4”KKKL ?޹3}ק]]ɼ.Y ayO>`dt]~׮}U7I7*/O`nr69^!IkJ:]_\3Sp w(e{ ˉ, o/puMMO0ujc[[OVxj0ke~74~vi!-|_.[gB7yUUW|Hp+'b>p"^/< G*)go)YE&uW 1MZPREɨ8nRqIMu6+V,'P8 !d~Bh*%ށ/]Z;sf!PX$P6Ӄ5ɟoPm YV,9;:;&4NiXX5Wjjm s~ !8T/ -lY;y€QmZ—/I2A[7wr**fљӴj6䅧"/ XweTvĖ-m.c䢗^:PWj.koUR݈֭{61/ʁc4pJm;vtT|^ǻtgάBh\-O nL8x+&[ZR{&>qS6 آE>߱æU3͘YC/;jGڶm`С=tԦ=0ՖaIX2X(!0eP_PRDsfGRٌ[W7=IQB|h͇\N9VLVX[/-A}}[]f10vl=D"a#FWJˁ#^+6is\宊rO}}Aq1&O*..m2@-9FFaa:[eῶ&cl^@Y j55j͘VJr~m挦H$,nqh~@ ~uN'ppR:?o$KҌ>ZP3lsٽFWA#~nJDѨMχ?C?Z7cxVgCB@;#F:c%cYg+~pd+32޵%e&1^$MPsX4T]aLJF-(}m+ >qˮε\Uv^ϘmM"ƍmG/.lx=꫞֟k,P8FA{as!<8ouyM͍Mj}~{G\@a!Hr qޓiH&S===L~^^^UUUMm : D_eyii뭩)..A%6U6 uttvwwcq+6559]NγM0C6-.PWWWOOO"$|"%=Z`f[:tw ׏y嚋ZFd,9di'G FPdx,zuPehӦZ](;G*H;Ncqv0ߠbuUvڤĆ m|6 G&^|ʡpE(B,ɒ$K/7"4kŠ ZZ~Í@8['2Tdd$m k,HqcZ1]w-诩^x{rz hǐd8 S[pnܪǗ}5b̺u=W_hrǦF[x;@4yT;th]0A vnM|cK9auzKHQCzF{#pUPL@0Y7 R8ryܿ}{oWTh @p@Z`2Y(2&+ʳwcm@*qZH" -NDK*f!'N,,J2y@éib|'ϨuX]< =^΂ [brh(; E6uYl݆4yYkY#[GnOW~ j@P!6NLۺ嶊IS-~pzE>c0j|N ^dpo3^ym۪U&M*N.Yɧ4=o2eY6v^WWg 1'^cU^]9Ms@Q cuzJ^r_~C>(!yLWΛ?s܊–LEѵg`K{%[k2 7l3'*{-_Sz855=3gL'.<é7A`֬}O _FYcLYh1 o/[:ӲPnHT Bck۶ 44T,^pPdb!xGgZm_o_nt"0CBP{d~C׾V ʿ±tYu^zC˖RIX Tkk:]3\lV,_^WSxJҥ-^xLs `ڴSx‘jZtw'3#U~"6<MdxXQ[9J-jjP\ #CE7nM 9KJ}Ay1tl{{d"K{~;@%FENvrEYYpB`kpMM f3tGGG8y*BG&l+[䮫s|K/-V{cw3'@1f5Hmm#Lԩ~OoOG'K.VY5ꀒ' #.n]˼T2ZQyK)I;>;=~E>(L&z/0N ;.\0jy[[{ɟBcp8˫&/'Z1c1w?>z@W[9a_|q[uM.,L%ɜNarxfΞd"=wn`ֿْ%8匟e38C g–(voL?_>cLNUm0$ M^ꫦĆpu۹/<܋G#[צAYhh|s~sVΜ5Cz??RvⓅŋ]K= aFՃs[7(n8ޟ6ww i%[IW]yWG5QUUo5thtY'͚^z_Q\|iIcsl&P3kj:f[c ~xsqו>с {i8r-lŘ'aMs?;.m3_|.iSτE=鍏|Q]Y96~`9'2i`ՑÛ'o䲑N˗~֘ld=~K]y-5>8PW[8yRi6=3Z|"rhUI O'䉕W r/ww pmę%Ш bе/ ^ߢmG(;{)5լ8nݱi`@i@-̳EM ; H?;cN)—#}Z,VUH`yq #(.VpH8茯#^!]"^4ͰLMjKJyَs5_rON9yɫ߆ہ 0` j[jaKG$0A\|p\p8?zә DFIp{6fA<-)h9K$uu>"#%h)17{ ͱoWBP02H)4Ɋ1ō"3A2D1r@Eys"he  ѥqrH`>~b@/tia2 _K_sd /]>{7>)0iU.-;&E~e-Q'V^yC}! R43Cr>ą.\x¾};w?!y.Y>QXi0gmC?oEUJ":=H@VLr/AU\pY|eߺ5յWq_33#Nj削I7 IXT\;v9\^}mOnV=ǒnEu :|mhx /p/]^1dnן(4蓰0oO8M8F_L^xvù YL3+oK?s{\LevgEvį+1[s 6ƒO>%UU'o8N<@zt 2ksbOyl'4a._z35pM3xӷ0/ص^TR:xI賙ޖX"p'{Yn_ \0sBqnw=6V^}_x6 Vxm{z瞷fvɤ' IDATZ0w%~`l?ַ>[nt?vB0t0w'WV$7|=,K_m./XX^Ӡ''~` pwX,<)‹[ٹbolٱ{rBUǜzB=0 fQ+KH ȁnhh:T<O7?Ƶl$=#iM #7@[RC{BCc?2鮻"XG9%ެoFum3~`'vp_PG:=޲3pƦK,W{%)x"f29mg).uJ -?i &N{vx}n> (dEoKaXN>Վ9eɴ{"U- \]]{SieݺCfr{{;Yjɬ@0nR)`͚pX)g5*?#I NNg3D"zʆF9ǔ̟_[PZ=oaCc%鮮тCMp6 .MƤms82RT!~c?:|{u8Rޞ_4M^koOw$Gz0%%wcnH10?$? Scogϋlww}}inƳϾ&1F93#L Un9X_'UWG3aUAQ7^umŒyuuX. L Ml Dx?{]ծbw@6#W=$K8Ī$"FC]2ڇ$wcV^x@QGQ㎿'yo.@L&$I IМm;KJ];OWŦNYR~dB* LQ"IM;~ݙu<'>_Y--H&* {/گ̡Cݙ4Cw /~V5IKփ^+LU4&Oöm}>_<ػg@Gϻt)S44%gR$;Eh@DsD"w:qp0ɻ_cK:D"tcÿE/ 2SL1a1&F+8wO*>t(w߾>귿Ѽ\N:d첿n۩~LVZLHKV̛yZwD~[ϯ; 3I6~1L%i!lLZ@^RՃW_5gtu>@0'y; Mq$RIIɠc -YKLʿwOlZ]U1mTӄwpWvXZ}IiJ fn̺7q4l5U[svͪ5^{ ,Bƒ/]2CuWĨmfNۧ`̯d|M?I%\.*+d9aXS.ęGAb{}_?PohuuT*\PFDOn!YYU$urcB !CF?emڔnk9KOzo\r1L= mQ}6bD?d"se;Kv74#cV_>[V[UzE57~JԯFR[K;]Ml>j&9qN!;_䀤6 >y|=d"2/Tf(F~4VMA\ֈ_]btW_[P[]dR[o gF@կ0 U ̡Q$$bTa*u(޾m9̀ b-:׵aأ40k-.1]'fO=1 TjI**,9Ы'dJHrsFBu@ ׅ:7oMCFF0Yw!y4  $LꐵZl[#Ltߞd,>J9gԜ.&r|g,иtXKcX鈫r=3!Z,̦=GqN1avV rYUH8qA%^ ^zPSxlռݚ^]\WӋp&pnơ/1q-وēbInQw{eY6S } Q]MIEN`vbO6; {hbe4fؚ @/;٧[\t0iR|BØAVGG< [U=&W(g@7qu:ms[Pi1_&N!/Hי'ڏ, E}uG}OMTFz5FVv=ۻGI}>B&GnY / q#`QRV2$@:ǡ6rv.qA/;T&\&=TA`!1aSn5=7=TUĔ٬#"AHзpj!6ؑHHNJ"dr'@?iIe&;,i*pE8RMfTC9X_nU+$bzBYbsl9KI01DrȾ̳@pَ AAp3!K3U+$'0[ᮦGF8 3b'[ӶL{ Ȅ6Xl4BL); }fԲ.aMng(#8l=MH\oojezľ}2W_{ 9!ZETh넠{雔xdI0šeBS^*! ?<8@'d ndUZ[%Ԕa:v@Id[sGed`o<7    ߫-g׬NPKwEro-qn cp8?utLI9>1y?> S?@9Nc2%u|Jn/>:wgN`0p7f"yL#BD`m*p=_dK܁=08hz2k nwM=z^|vf]= i?`(8sNK%v-G9Z;vKmQ?"8 b`Bh5OJ ش`@xѳ' hVS≳Y\ouc-I}.310 Sv2b%픜%8vgUNBI!Dv`2 +t RX L.T+ê/ }jEtw#pxҙM$".o*` 4 M8*( Sϐd&28DxCLdOs}`<FȄ6 Z"YC]^`C;yX4rҩp:T LhSX(aF*z12F?UnK@isH'$f;GqN&058xx 1%f.8z# ! 1Ka]zc.&8j|Bsuѧ d"A&ghxd4,`$0WoBU"#&T!*ILJ(<ϗ3:NصEFazC7 qؓw(2`$8\$E Ǵ ^.mp.g,@@vvH#$H%~r*9 .4IAXФ,DV0bT\ПHk2ٌWj+*}yyUU܇$whhX4lB\!Ή+$\W1z HXau=Ag;OfTGO9ˎB8X ,G {[[$ƭJ2d<.T0tX6헝5e@@m'cbLH^d]]x_:SH(O 8'Fn򊒁`ApI$1.#mv"#zƙDCᦦ`Ar[ϗKǁp>_@,XV̺`0455 Ι$ɲS/%19tghL܅qԉ @@$9N]Ht|n[_ a%W9}9s渜N~9n!)Y;ƯdC yTyI$P0ĠB7` N+5ˣQayc(+1$ e3 s!D"XCx+b,yK;nzGtuu564(ZICCCtpI>܉) 9uM-^,;x8s:X<ɲC( SHosldmh>0؟H$JKK,%Sa HLNj@l0ENp&[\TduDžCIKQ;jJ H\(&GFY`Mpxo{@l4F4xYȗMga 5NN/{z[Vc]t2Ƞ.١K6_Ԙ()2x,Hjoo/ Ѿp@_$>$9֒jL{*Tje%.lg}} &B*1,1f`0h2]kE M< %s`;v"zP }pp I:(H|l&x̑@ 7NgN8Q(Lod4`b^a25/Gd}]ߡFF8l\pX'ŌꟘPD*e E Dӡޞv@!e@@~!;L>Dj[)',#Obawͦ}&Fc"X4Qd chȌ"f$T 8@ 9 B0ZZD qR GFқ7oՌIDAT.8? ]nkNF$bSC/$1UbL"HYNΤڽ3{>3< f$2d ^YYG |!o8B@0 >$# 5553a<" VzH  p)8KAo (,*҈ fH@aSFHnPb$(^ 4 YYY)KWct`B4I#g9Bq\,@Йj* dNB 655i :L&&گjiI\B"!9E&Q0\%޺[1̘A_S=3 pP!9X'N+ | 5+,_$@Fҋ<8Ea(8q"l abdb&$d%f.&?I`0 @[UN& #aӀ^ȶ)JSpp1?bg$ $ȅcOs!PGT*ѡO#Zoe^OTYA9 :}˔8 ; J fW^`; }jkKhiOCCЯ~x\jD<iokJ$X"\R^Q9w\Irqx=]g@dwv:J3Ky55&Lw+?bݧufz'0( ܤ#DBHpLpb6b^_v;svwuݾ͏>3N:譯[U=>olnJ/󏌜R|_I30Z?OD.8uAp:VVVZnG81O|xQ'0PF*iK\Eh_<QTx4@ݮj@SLX{z=%-4%h c?n@ (5N҂0Q) '΁#+-eM}~zr;͍cl/{k*RX*ɖ ,wd{=q!h8xPYS.|WZ3lEĻZ3̗B0Ù+>^ %;{R~q*35q mO!2ķR%cR%y:4g4S30&ڪAOć8!P*T*$))Q.$Zg@)+;ΦSYk6ec"I8xJwmo-t+JZOwd9fP U`)"E?o?&twZd4u5ݎfS-)CȼY@٦]+|2띵9%p 8H*%9)(1a8#t0Crr8sXW"8Ӌ›iG,*‘,_9)OҭbVkMdXi졗2Y%=܃hq$@e.pq~^0L +Bx|!ɀEh4ǧ' $ks)"H}TYU{BzҎU@*jVelZD`pKaSlˁ4d68fRqF3k\wJbדggf*^#.DZE"!9E@.擆S4LP,"(extt3=bR˞=o 9d)qI3ZL;'' |ШE<A EYDZ ^oM#& E)B pkˈ6IAIHJs/+e.RJhV s` _6DØ-r;w"MӔRrCd7fFӒ #!hŽVi{;7n\ RcWkeG ݻ-N8|ilԗ*R,*o !$Y[۾9Pu9&)FQ>e*GOH) {^7vvEO=OQ-4gOiuۭF1*Ύ t]7L =<)pY8AY1+I9͟پm QzxJ), } \yw:%tMߋonm4MJQ܍Dd6Ob (#LuÝ;(8!V0azi0.G`KJ`:E ߋ3̹kjd fvܝ?8;_`Awt!!1MEIHESv~y^4eh{//.fA!S,ђeɅ>ij k_;w/πO1dx^c`L^8Gα*(ks[\cqS,)Ec3N1o|qvt4h<رȟ{xkEOBQ_- £㪣M\4|`,ũydq<lyBNT@X ɨf8,!0F.83xNS+ !+x󍸜fM XjfߕDFBgٲ@fD^P3S-Q:Ptw\v-Ki3#1XqGBN(=zR:5QԆE__[_/ƱL\`i߶pxX:6!. S% X[[K2]jA?[&aX:6}][.)ppee/ʥ;q|VuA UDoLB9u+-WjZlϏ(ҁL1l5ܗNk q ss'ȵy(_  h𚅠MlmZ) d;N8xyq3-!:ȮOI Wh}Uw0Bx7 g,g7Pu!ojU>bphypq 굫Q3!!6Mw*9z͂F86͵MG=ː 2sg.fc ` NQ[R|R;$@L( / AD ﳭ*9X/òkM)2t0I\>M V?`3ļD&GY|v嶋1 G]ɬ< x v7ux|ltv9Jebq}}֭[KCw ǮJ)JŶ흝Ng)`qu]W!0 n?S/7~6sQۍe2m3$/~c=m]X_dycPG/ ?d^ϽyB۶%'_suO8xլ1,{?2c? aH%↌Z{֟Ry6KF>QX.\xp'CAaEeYe-H7]K#kqT7;Ѩzы]P=aNե!swn놑V 8J:"վi[SZn@΁?c9H5JӬ&iH6AJDhwJ F<G D$>QV*x$߈,3g|j?_LBO(9w8S%-ΫAӠq㓫1D7}z8P*PuttJnsU28c4~.ٗ ƶee@8!rkvi"eh;Kr1AH+_n1ɺ{: 唧)=(OH5A$!0?=۹E"{SѠ?` ]q~@>â89Jxg:cnADggg ٻdH2*r^B~PyΑ 5`mM{{f)PBEtn!o޹=eVmGBNgb`o?l.3Ӹ&*E^v\.{w흞`\AA rc.(ںZ{Cw@MtU)SK/’'HcَHi7Z2X#&JJ$y4'vi=\7S&O0T[5(R8ȕko 0zRi}}#UJiP9 @gPrCCSAnR)Oϼ=@'R _>iSՊFJME]vTCDk_(}[;Rj"x4ђyÞ+:]ʦDR(\n S.5Ţ|"7͞lkBT!eFۙCЁ-xؐ%"`+lfe?^ Xs 'c1`7_d{+|WMqAєJ=!Bވ׿Ƕ'Ա+n,["G'~MJn+G]7`D_&b,Y |5B@u-jPʚ7&iVSyɷ1d@؈RiׇMݷa~Z%X,="JE@:p ]#CHyY<מּ+clLq$@9lcPMRUxkT_^vl kkϽs,kۡ8´*eI'b59; 8g?JQ(fw.Dq4n> 9 q)$W_:0}[8<0)Uzz~xp8OuM74X(6:2*T2T/SLƐ&p/BH6H{{g|XpBթWWTd ed,T*P8׹0 q abik}ԭEǮ4 7X:h<:;;;:>\l.؅Nkms}$d(e4>J"{ tQ-QIENDB`fltk-1.4.3/test/desktop/sudoku.desktop0000644000175000017500000000023115004135251020136 0ustar albrechtalbrecht[Desktop Entry] Name=Sudoku Comment=Suduku Number Game TryExec=sudoku Exec=sudoku Icon=sudoku Terminal=false Type=Application Categories=Game;LogicGame; fltk-1.4.3/test/desktop/sudoku-128.png0000644000175000017500000001456215004135251017575 0ustar albrechtalbrechtPNG  IHDR;[ 9IDATx]y\M(I@Q끊EQ (UcQzj QX}kjh- IfwsP,߿};כ޼y3%&&^|GTT84'@W(O01 C)8ϙ3 ̖6۷oi Ç)vڑ>Ĕ/^ tkI,a͵ZP((KKKiK"hڏr8vXÆ Zl˖-D=ZJ&M[]{=z(m JfyO0aRIŃbQQQܺ0eC5q<**JDד>z r+JLɓpψ)k֬a"<}wرz]F @DFhӦ 8##I&F.d 9/cƌa+E3>@0j(Tc>|=v1)z@oPPVB@w% ŋtr@~~~ƍZ4::QaYGGyNNNtΎTIV|"JV yyy Oe2񩈎E8dFS]\\BݧO7jllluuH$cnݺ Gv#wH$zO0I!R۷oσ۲eD",Ő>}" 0 fP^/PgxEE%=#F@# k׮m׮CagkkKD.\ O=oDGG34))}3Sm0 #w2$3F * Z*^0|[III&`…t#sL۷,3t( uu_ =jW:^J*d|Hh0`VtCb8߻w+fb I}4N< D"ÂR@}I^#2|ڑ ڵkW}tttvv6s[jE^ QPPArrr޽)2ppppttq< ՕGiiizFa?#T*wEzjvlt|@PqmS\.j4FOVHm=S$)pAr4 Y1ðSl-5 spp7oO?ԡCH#&NE^^^V˵*++)_FǩS:uDUXXX^=kkk:i 8@\̄ϟD"N=]n~uoD9s8//-Z\~̝;j5)S!SG KZӎ  j*xEFFwJy-_9ʩÝzoΛv/2AZP||;w4i2fSt###e˖Ç 666(E$~GM8{lw(Ae7dRXX8p@=WΜ9RΞ=LaPrZMp{{{ba+2Z]v999T*2W\0޽T眜XPLɦMBo߾|%/55M!bqII ?80l߾}ƍcUVV8nkkcwsN0Dwe޺uk\ԩSBXQ.Qbҥp-8h @rr2 8Hrt`(VۧObֹ8wؑNq]PgJI=^zٷ(X~AzȲ̓_6lKVfpa?tc7$ðÇBc0 +<2W\!fCFs%NI!"ccc̻6lXVVT*  ǏI&"RnpvҳuR)ד~NNбcGŲ6mZzlMBR.\`7o+zVd2P>kd?dӑOz*h֮]RtkDH$uK„{{{7m4AN2Bϝ;Ǜ b>yI}{ȑ@OOO3LTUWWLJ[`tiPvvv۶m###g/bΝ! ؠ^P v?x =nK6l=H gyl+&Ğ vܩT*߿ω'h7| )U+L<988͍=֭[5zuX,v`ќ9]&Ùݻwb O:3Gtibeii) @c Ƿmۆ D8{,@&P0dDo`Ւ%K!7hЀN .h{/ݺuCFG r7 [6% ǥ={d)It#J`CRImn߾ef3f4_Ν;֮]KL+L]}#ׯ_K.gϞ!=oD?%={h' l2uff&?S(O믿Mꃃ鄄Hڼysތ?f͚5k֜aL.s"::/5{RR҇>ߐ{0 t-պ܉mn̈?V7n[[ۦM2oEEE;w$jcccԁ4i~-F+O<K 9HHH(// l'LYOVc.zsѢEr޽c8\K7of. (&&իf(ބ͛3mT#q w0x/ lb격j$R)ݢ3/^d~~qKjKKK=zt)Sb vڥyk|VtΝ;Q|ϤIڷoO#ˉx6 9rQhϿFBqZ_,deeT۷oׯ_m۶ĻuEKJJ7mԫWϏ?ð/RR gR+ŋuZh2 w\Izj̄̀M 1FTRJSŋȓ6vX xʕ+ѣG"5/뀻w 6Mklٲ Jxi''N:P3ZңhH%`cS)aRlРA;v9 y,I[rZ"ٳtS"t*  W'zIN eHqFNnܸj* ϻB(..:ujTT˓79RٳgB͛||P(owwwBtx~~~Zv֬Y-[dCׯ_???ǧ񊊊%K@vZlU-xBNFѣ}z"^zfiii*WĵkaЋ_bbb닎 c>< n!h4/ ƍ׳gO7o~z~߾}QwؑFsxHXXP8p1cXnqM`j>|XVYYzj tHHHM:G٬rZ3m4swrGl4bWfffzwqqjРAτ?yB777NrAu0?DFtL?[ Zd^IENDB`fltk-1.4.3/test/glut_test.cxx0000644000175000017500000001151515004135251016325 0ustar albrechtalbrecht// // GLUT test program for the Fast Light Tool Kit (FLTK). // // Provided by Brian Schack (STR #3458, see "big.cxx"). // Copyright 2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Thanks to the original author Brian Schack for this test program. // This program has been extended to test several GLUT functions with // (1) a valid and (2) an invalid (destroyed) GLUT window. // The test program opens two GLUT windows, runs the tests, prints // diagnostics on stdout, and exits immediately. This is intended. // To compile (examples with different GLUT implementations) // as of Apr 03, 2018 provided Brian Schack, slightly modified // // macOS GLUT: // g++ -o glut_test glut_test.cxx -framework OpenGL -framework GLUT // // FreeGLUT (on macOS, with Macport's FreeGLUT): // g++ -o glut_test glut_test.cxx -framework OpenGL -I/opt/local/include -L/opt/local/lib -lglut // // FLTK // fltk-config --use-gl --compile glut_test.cxx // Enable one of the following two #include's depending on the GLUT implementation // #include // GLUT and FreeGLUT version #include // FLTK version #include // Empty callback functions for testing. void displayFunc() {} void reshapeFunc(int w, int h) {} void keyboardFunc(unsigned char key, int x, int y) {} void mouseFunc(int b, int state, int x, int y) {} void motionFunc(int x, int y) {} void passiveMotionFunc(int x, int y) {} void entryFunc(int s) {} void visibilityFunc(int s) {} void idleFunc() {} void timerFunc(int value) {} void menuStateFunc(int state) {} void menuStatusFunc(int status, int x, int y) {} void specialFunc(int key, int x, int y) {} void overlayDisplayFunc() {} int main(int argc, char **argv) { glutInit(&argc, argv); // Create 2 windows. int win1 = glutCreateWindow("Window 1"); int win2 = glutCreateWindow("Window 2"); printf("Window 1 created, number = %d\n", win1); printf("Window 2 created, number = %d\n", win2); // Run tests twice, with (1) a valid and (2) an invalid current window for (int i = 0; i < 2; i++) { // Find out which window is current. int current = glutGetWindow(); printf("Window %d is current\n", current); // Ask GLUT to redisplay things. glutPostRedisplay(); // Set window title glutSetWindowTitle((char *)"Non-existent"); // Set icon title glutSetIconTitle((char *)"Non-existent"); // Position window glutPositionWindow(10, 20); // Reshape window glutReshapeWindow(100, 200); // Pop window glutPopWindow(); // Iconify window glutIconifyWindow(); // Show window glutShowWindow(); // Hide window glutHideWindow(); // Go to full screen mode glutFullScreen(); // Set the cursor glutSetCursor(GLUT_CURSOR_INFO); // Establish an overlay glutEstablishOverlay(); // Remove overlay glutRemoveOverlay(); // Choose a layer glutUseLayer(GLUT_NORMAL); glutUseLayer(GLUT_OVERLAY); // Post display on a layer glutPostOverlayRedisplay(); // Show overlay glutShowOverlay(); // Hide overlay glutHideOverlay(); // Attach a menu glutAttachMenu(0); // Detach a menu glutDetachMenu(0); // Specify callbacks glutDisplayFunc(displayFunc); glutReshapeFunc(reshapeFunc); glutKeyboardFunc(keyboardFunc); glutMouseFunc(mouseFunc); glutMotionFunc(motionFunc); glutPassiveMotionFunc(passiveMotionFunc); glutEntryFunc(entryFunc); glutVisibilityFunc(visibilityFunc); glutIdleFunc(idleFunc); glutTimerFunc(1000, timerFunc, 42); glutMenuStateFunc(menuStateFunc); glutMenuStatusFunc(menuStatusFunc); glutSpecialFunc(specialFunc); glutOverlayDisplayFunc(overlayDisplayFunc); // Swap buffers glutSwapBuffers(); // GLUT gets printf("GLUT_WINDOW_X = %d\n", glutGet(GLUT_WINDOW_X)); printf("GLUT_WINDOW_Y = %d\n", glutGet(GLUT_WINDOW_Y)); printf("GLUT_WINDOW_WIDTH = %d\n", glutGet(GLUT_WINDOW_WIDTH)); printf("GLUT_WINDOW_HEIGHT = %d\n", glutGet(GLUT_WINDOW_HEIGHT)); printf("GLUT_WINDOW_PARENT = %d\n", glutGet(GLUT_WINDOW_PARENT)); // GLUT layer gets printf("GLUT_OVERLAY_POSSIBLE = %d\n", glutLayerGet(GLUT_OVERLAY_POSSIBLE)); printf("GLUT_NORMAL_DAMAGED = %d\n", glutLayerGet(GLUT_NORMAL_DAMAGED)); // Destroy the current window - this sets glut_window to NULL printf("Destroy the current window (%d)\n\n", glutGetWindow()); glutDestroyWindow(current); } // loop with current window printf("All tests done, exiting.\n"); return 0; } fltk-1.4.3/test/sudoku.cxx0000644000175000017500000011121015004135251015616 0ustar albrechtalbrecht// // Sudoku game using the Fast Light Tool Kit (FLTK). // // Copyright 2005-2018 by Michael Sweet. // Copyright 2019-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pixmaps/sudoku.xbm" // Audio headers... #include #ifndef _WIN32 # include #endif // !_WIN32 #if defined __APPLE__ && !defined(FLTK_USE_X11) # define USE_MACOS 1 #endif #ifdef HAVE_ALSA_ASOUNDLIB_H # define ALSA_PCM_NEW_HW_PARAMS_API # include #endif // HAVE_ALSA_ASOUNDLIB_H #ifdef __APPLE__ # include #endif // __APPLE__ #ifdef _WIN32 # include #endif // _WIN32 // // Default sizes... // #define GROUP_SIZE 160 #define CELL_SIZE 50 #define CELL_OFFSET 5 #ifdef USE_MACOS # define MENU_OFFSET 0 #else # define MENU_OFFSET 25 #endif // USE_MACOS // Sound class for Sudoku... // // There are MANY ways to implement sound in a FLTK application. // The approach we are using here is to conditionally compile OS- // specific code into the application - CoreAudio for MacOS X, the // standard Win32 API stuff for Windows, ALSA or X11 for Linux, and // X11 for all others. We have to support ALSA on Linux because the // current Xorg releases no longer support XBell() or the PC speaker. // // There are several good cross-platform audio libraries we could also // use, such as OpenAL, PortAudio, and SDL, however they were not chosen // for this application because of our limited use of sound. // // Many thanks to Ian MacArthur who provided sample code that led to // the CoreAudio implementation you see here! class SudokuSound { // Private, OS-specific data... #ifdef __APPLE__ AudioDeviceID device; # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 AudioDeviceIOProcID audio_proc_id; # endif AudioStreamBasicDescription format; short *data; int remaining; static OSStatus audio_cb(AudioDeviceID device, const AudioTimeStamp *current_time, const AudioBufferList *data_in, const AudioTimeStamp *time_in, AudioBufferList *data_out, const AudioTimeStamp *time_out, void *client_data); #elif defined(_WIN32) HWAVEOUT device; HGLOBAL header_handle; LPWAVEHDR header_ptr; HGLOBAL data_handle; LPSTR data_ptr; #else # ifdef HAVE_ALSA_ASOUNDLIB_H snd_pcm_t *handle; # endif // HAVE_ALSA_ASOUNDLIB_H #endif // __APPLE__ // Common data... static int frequencies[9]; static short *sample_data[9]; static int sample_size; public: SudokuSound(); ~SudokuSound(); void play(char note); }; typedef unsigned int State; typedef State GameState[81]; // Sudoku cell class... class SudokuCell : public Fl_Widget { int row_; int col_; bool readonly_; int value_; int hint_map_; public: SudokuCell(int row, int col, int X, int Y, int W, int H); int row() { return row_; } int col() { return col_; } void draw() FL_OVERRIDE; int handle(int event) FL_OVERRIDE; void readonly(bool r) { readonly_ = r; redraw(); } bool readonly() const { return readonly_; } void set_hint(int n) { hint_map_ |= (1<>1) | (value_<<12) | (readonly_<<9); } void state(State s) { hint_map_ = (s & 0x000001ff) << 1; readonly_ = (s & 0x00000200) >> 9; value_ = (s & 0x0000f000) >> 12; if (readonly_) color(FL_GRAY); else color(FL_LIGHT3); redraw(); } }; // Sudoku window class... class Sudoku : public Fl_Double_Window { Fl_Sys_Menu_Bar *menubar_; Fl_Group *grid_; time_t seed_; char grid_values_[9][9]; SudokuCell *grid_cells_[9][9]; Fl_Group *grid_groups_[3][3]; int difficulty_; SudokuSound *sound_; GameState undo_stack[64]; int undo_head_, undo_tail_, redo_head_; static void check_cb(Fl_Widget *widget, void *); static void close_cb(Fl_Widget *widget, void *); static void diff_cb(Fl_Widget *widget, void *d); static void update_helpers_cb(Fl_Widget *, void *); static void help_cb(Fl_Widget *, void *); static void mute_cb(Fl_Widget *widget, void *); static void new_cb(Fl_Widget *widget, void *); static void reset_cb(Fl_Widget *widget, void *); static void restart_cb(Fl_Widget *widget, void *); void set_title(); static void solve_cb(Fl_Widget *widget, void *); static Fl_Help_Dialog *help_dialog_; static Fl_Preferences prefs_; public: Sudoku(); ~Sudoku(); void check_game(bool highlight = true); void load_game(); void new_game(time_t seed); int next_value(SudokuCell *c); void resize(int X, int Y, int W, int H) FL_OVERRIDE; void save_game(); void solve_game(); void update_helpers(); void clear_hints_for(int row, int col, int val); void save_state(GameState &s); void load_state(GameState &s); void undo(); void redo(); void clear_undo(); void undo_checkpoint(); }; Sudoku *sudoku = NULL; // Sound class globals... int SudokuSound::frequencies[9] = { 880, // A(5) 988, // B(5) 1046, // C(5) 1174, // D(5) 1318, // E(5) 1396, // F(5) 1568, // G(5) 1760, // H (A6) 1976 // I (B6) }; short *SudokuSound::sample_data[9] = { 0 }; int SudokuSound::sample_size = 0; // Initialize the SudokuSound class SudokuSound::SudokuSound() { sample_size = 0; #ifdef __APPLE__ remaining = 0; UInt32 size = sizeof(device); if (AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, (void *)&device) != noErr) return; size = sizeof(format); if (AudioDeviceGetProperty(device, 0, false, kAudioDevicePropertyStreamFormat, &size, &format) != noErr) return; // Set up a format we like... format.mSampleRate = 44100.0; // 44.1kHz format.mChannelsPerFrame = 2; // stereo if (AudioDeviceSetProperty(device, NULL, 0, false, kAudioDevicePropertyStreamFormat, sizeof(format), &format) != noErr) return; // Check we got linear pcm - what to do if we did not ??? if (format.mFormatID != kAudioFormatLinearPCM) return; // Attach the callback and start the device # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (AudioDeviceCreateIOProcID(device, audio_cb, (void *)this, &audio_proc_id) != noErr) return; AudioDeviceStart(device, audio_proc_id); # else if (AudioDeviceAddIOProc(device, audio_cb, (void *)this) != noErr) return; AudioDeviceStart(device, audio_cb); # endif sample_size = (int)format.mSampleRate / 20; #elif defined(_WIN32) WAVEFORMATEX format; memset(&format, 0, sizeof(format)); format.cbSize = sizeof(format); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = 2; format.nSamplesPerSec = 44100; format.nAvgBytesPerSec = 44100 * 4; format.nBlockAlign = 4; format.wBitsPerSample = 16; data_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, format.nSamplesPerSec / 5); if (!data_handle) return; data_ptr = (LPSTR)GlobalLock(data_handle); header_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR)); if (!header_handle) return; header_ptr = (WAVEHDR *)GlobalLock(header_handle); header_ptr->lpData = data_ptr; header_ptr->dwBufferLength = format.nSamplesPerSec / 5; header_ptr->dwFlags = 0; header_ptr->dwLoops = 0; if (waveOutOpen(&device, WAVE_MAPPER, &format, 0, 0, WAVE_ALLOWSYNC) != MMSYSERR_NOERROR) return; waveOutPrepareHeader(device, header_ptr, sizeof(WAVEHDR)); sample_size = 44100 / 20; #else # ifdef HAVE_ALSA_ASOUNDLIB_H handle = NULL; if (snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0) >= 0) { // Initialize PCM sound stuff... snd_pcm_hw_params_t *params; snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle, params); snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16); snd_pcm_hw_params_set_channels(handle, params, 2); unsigned rate = 44100; int dir; snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir); snd_pcm_uframes_t period = (int)rate / 4; snd_pcm_hw_params_set_period_size_near(handle, params, &period, &dir); sample_size = rate / 20; if (snd_pcm_hw_params(handle, params) < 0) { sample_size = 0; snd_pcm_close(handle); handle = NULL; } } # endif // HAVE_ALSA_ASOUNDLIB_H #endif // __APPLE__ if (sample_size) { // Make each of the notes using a combination of sine and sawtooth waves int attack = sample_size / 10; int decay = 4 * sample_size / 5; for (int i = 0; i < 9; i ++) { sample_data[i] = new short[2 * sample_size]; short *sample_ptr = sample_data[i]; for (int j = 0; j < sample_size; j ++, sample_ptr += 2) { double theta = 0.05 * frequencies[i] * j / sample_size; double val = 0.5 * sin(2.0 * M_PI * theta) + theta - (int)theta - 0.5; if (j < attack) { *sample_ptr = (int)(32767 * val * j / attack); } else if (j > decay) { *sample_ptr = (int)(32767 * val * (sample_size - j + decay) / sample_size); } else *sample_ptr = (int)(32767 * val); sample_ptr[1] = *sample_ptr; } } } } // Cleanup the SudokuSound class SudokuSound::~SudokuSound() { #ifdef __APPLE__ if (sample_size) { # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 AudioDeviceStop(device, audio_proc_id); AudioDeviceDestroyIOProcID(device, audio_proc_id); # else AudioDeviceStop(device, audio_cb); AudioDeviceRemoveIOProc(device, audio_cb); # endif } #elif defined(_WIN32) if (sample_size) { waveOutClose(device); GlobalUnlock(header_handle); GlobalFree(header_handle); GlobalUnlock(data_handle); GlobalFree(data_handle); } #else # ifdef HAVE_ALSA_ASOUNDLIB_H if (handle) { snd_pcm_drain(handle); snd_pcm_close(handle); } # endif // HAVE_ALSA_ASOUNDLIB_H #endif // __APPLE__ if (sample_size) { for (int i = 0; i < 9; i ++) { delete[] sample_data[i]; } } } #ifdef __APPLE__ // Callback function for writing audio data... OSStatus SudokuSound::audio_cb(AudioDeviceID device, const AudioTimeStamp *current_time, const AudioBufferList *data_in, const AudioTimeStamp *time_in, AudioBufferList *data_out, const AudioTimeStamp *time_out, void *client_data) { SudokuSound *ss = (SudokuSound *)client_data; int count; float *buffer; if (!ss->remaining) return noErr; for (count = data_out->mBuffers[0].mDataByteSize / sizeof(float), buffer = (float*) data_out->mBuffers[0].mData; ss->remaining > 0 && count > 0; count --, ss->data ++, ss->remaining --) { *buffer++ = *(ss->data) / 32767.0; } while (count > 0) { *buffer++ = 0.0; count --; } return noErr; } #endif // __APPLE__ #define NOTE_DURATION 50 // Play a note for ms... void SudokuSound::play(char note) { Fl::check(); #ifdef __APPLE__ // Point to the next note... data = sample_data[note - 'A']; remaining = sample_size * 2; // Wait for the sound to complete... usleep(NOTE_DURATION*1000); #elif defined(_WIN32) if (sample_size) { memcpy(data_ptr, sample_data[note - 'A'], sample_size * 4); waveOutWrite(device, header_ptr, sizeof(WAVEHDR)); Sleep(NOTE_DURATION); } else Beep(frequencies[note - 'A'], NOTE_DURATION); #elif defined(FLTK_USE_X11) # ifdef HAVE_ALSA_ASOUNDLIB_H if (handle) { // Use ALSA to play the sound... if (snd_pcm_writei(handle, sample_data[note - 'A'], sample_size) < 0) { snd_pcm_prepare(handle); snd_pcm_writei(handle, sample_data[note - 'A'], sample_size); } usleep(NOTE_DURATION*1000); return; } # endif // HAVE_ALSA_ASOUNDLIB_H // Just use standard X11 stuff... XKeyboardState state; XKeyboardControl control; // Get original pitch and duration... XGetKeyboardControl(fl_display, &state); // Sound a tone for the given note... control.bell_percent = 100; control.bell_pitch = frequencies[note - 'A']; control.bell_duration = NOTE_DURATION; XChangeKeyboardControl(fl_display, KBBellPercent | KBBellPitch | KBBellDuration, &control); XBell(fl_display, 100); XFlush(fl_display); // Restore original pitch and duration... control.bell_percent = state.bell_percent; control.bell_pitch = state.bell_pitch; control.bell_duration = state.bell_duration; XChangeKeyboardControl(fl_display, KBBellPercent | KBBellPitch | KBBellDuration, &control); #endif // __APPLE__ } // Create a cell widget SudokuCell::SudokuCell(int row, int col, int X, int Y, int W, int H) : Fl_Widget(X, Y, W, H, 0), row_(row), col_(col) { value(0); } // Draw cell void SudokuCell::draw() { static Fl_Align align[9] = { FL_ALIGN_TOP_LEFT, FL_ALIGN_TOP, FL_ALIGN_TOP_RIGHT, FL_ALIGN_LEFT, 0, FL_ALIGN_RIGHT, FL_ALIGN_BOTTOM_LEFT, FL_ALIGN_BOTTOM, FL_ALIGN_BOTTOM_RIGHT, }; // Draw the cell box... if (readonly()) fl_draw_box(FL_UP_BOX, x(), y(), w(), h(), color()); else fl_draw_box(FL_DOWN_BOX, x(), y(), w(), h(), color()); // Draw the cell background... if (Fl::focus() == this) { Fl_Color c = fl_color_average(FL_SELECTION_COLOR, color(), 0.5f); fl_color(c); fl_rectf(x() + 4, y() + 4, w() - 8, h() - 8); fl_color(fl_contrast(labelcolor(), c)); } else fl_color(labelcolor()); // Draw the cell value... char s[2]; s[1] = '\0'; if (value_) { s[0] = value_ + '0'; fl_font(FL_HELVETICA_BOLD, h() - 10); fl_draw(s, x(), y(), w(), h(), FL_ALIGN_CENTER); } else { fl_font(FL_HELVETICA_BOLD, h() / 5); for (int i = 1; i <= 9; i ++) { if (hint_set(i)) { s[0] = i + '0'; fl_draw(s, x() + 5, y() + 5, w() - 10, h() - 10, align[i-1]); } } } } // Handle events in cell int SudokuCell::handle(int event) { switch (event) { case FL_FOCUS : Fl::focus(this); redraw(); return 1; case FL_UNFOCUS : redraw(); return 1; case FL_PUSH : if (!readonly() && Fl::event_inside(this)) { if (Fl::event_clicks()) { // 2+ clicks increments/sets value if (value()) { if (value() < 9) value(value() + 1); else value(1); } else value(sudoku->next_value(this)); } // TODO: add this to the undo process Fl::focus(this); redraw(); return 1; } break; case FL_KEYDOWN : if (Fl::event_state() & FL_CTRL) break; int key = Fl::event_key() - '0'; if (key < 0 || key > 9) key = Fl::event_key() - FL_KP - '0'; if (key > 0 && key <= 9) { if (readonly()) { fl_beep(FL_BEEP_ERROR); return 1; } if (Fl::event_state() & (FL_SHIFT | FL_CAPS_LOCK)) { if (hint_set(key)) { clear_hint(key); } else { set_hint(key); } sudoku->undo_checkpoint(); redraw(); } else { value(key); sudoku->clear_hints_for(row(), col(), key); sudoku->undo_checkpoint(); do_callback(); } return 1; } else if (key == 0 || Fl::event_key() == FL_BackSpace || Fl::event_key() == FL_Delete) { if (readonly()) { fl_beep(FL_BEEP_ERROR); return 1; } if (Fl::event_state() & (FL_SHIFT | FL_CAPS_LOCK)) { clear_hints(); sudoku->undo_checkpoint(); } else { value(0); do_callback(); sudoku->undo_checkpoint(); } return 1; } break; } return Fl_Widget::handle(event); } // Sudoku class globals... Fl_Help_Dialog *Sudoku::help_dialog_ = (Fl_Help_Dialog *)0; Fl_Preferences Sudoku::prefs_(Fl_Preferences::USER_L, "fltk.org", "sudoku"); static void undo_cb(Fl_Widget*, void*) { sudoku->undo(); } static void redo_cb(Fl_Widget*, void*) { sudoku->redo(); } // Create a Sudoku game window... Sudoku::Sudoku() : Fl_Double_Window(GROUP_SIZE * 3, GROUP_SIZE * 3 + MENU_OFFSET, "Sudoku"), undo_head_(0), undo_tail_(0), redo_head_(0) { int j, k; Fl_Group *g; SudokuCell *cell; static Fl_Menu_Item items[] = { { "&Game", 0, 0, 0, FL_SUBMENU }, { "&New Game", FL_COMMAND | 'n', new_cb, 0, FL_MENU_DIVIDER }, { "&Check Game", FL_COMMAND | 'c', check_cb, 0, 0 }, { "&Restart Game", FL_COMMAND | 'r', restart_cb, 0, 0 }, { "&Solve Game", FL_COMMAND | 's', solve_cb, 0, FL_MENU_DIVIDER }, { "&Update Helpers", 0, update_helpers_cb, 0, 0 }, { "&Mute Sound", FL_COMMAND | 'm', mute_cb, 0, FL_MENU_TOGGLE | FL_MENU_DIVIDER }, #ifndef USE_MACOS { "&Quit", FL_COMMAND | 'q', close_cb, 0, 0 }, #endif { 0 }, { "&Edit", 0, 0, 0, FL_SUBMENU }, { "&Undo", FL_COMMAND | 'z', undo_cb }, { "&Redo", FL_COMMAND | 'Z', redo_cb }, { 0 }, { "&Difficulty", 0, 0, 0, FL_SUBMENU }, { "&Easy", 0, diff_cb, (void *)"0", FL_MENU_RADIO }, { "&Medium", 0, diff_cb, (void *)"1", FL_MENU_RADIO }, { "&Hard", 0, diff_cb, (void *)"2", FL_MENU_RADIO }, { "&Impossible", 0, diff_cb, (void *)"3", FL_MENU_RADIO }, { 0 }, #ifndef USE_MACOS { "&Help", 0, 0, 0, FL_SUBMENU }, { "&About Sudoku", FL_F + 1, help_cb, 0, 0 }, { 0 }, #endif { 0 } }; // Setup sound output... prefs_.get("mute_sound", j, 0); if (j) { // Mute sound? sound_ = NULL; items[6].flags |= FL_MENU_VALUE; } else sound_ = new SudokuSound(); // Menubar... prefs_.get("difficulty", difficulty_, 0); if (difficulty_ < 0 || difficulty_ > 3) difficulty_ = 0; items[10 + difficulty_].flags |= FL_MENU_VALUE; menubar_ = new Fl_Sys_Menu_Bar(0, 0, 3 * GROUP_SIZE, 25); menubar_->menu(items); #ifdef USE_MACOS menubar_->about(help_cb, NULL); #endif // Create the grids... grid_ = new Fl_Group(0, MENU_OFFSET, 3 * GROUP_SIZE, 3 * GROUP_SIZE); for (j = 0; j < 3; j ++) for (k = 0; k < 3; k ++) { g = new Fl_Group(k * GROUP_SIZE, j * GROUP_SIZE + MENU_OFFSET, GROUP_SIZE, GROUP_SIZE); g->box(FL_BORDER_BOX); if ((int)(j == 1) ^ (int)(k == 1)) g->color(FL_DARK3); else g->color(FL_DARK2); g->end(); grid_groups_[j][k] = g; } for (j = 0; j < 9; j ++) for (k = 0; k < 9; k ++) { cell = new SudokuCell(j, k, k * CELL_SIZE + CELL_OFFSET + (k / 3) * (GROUP_SIZE - 3 * CELL_SIZE), j * CELL_SIZE + CELL_OFFSET + MENU_OFFSET + (j / 3) * (GROUP_SIZE - 3 * CELL_SIZE), CELL_SIZE, CELL_SIZE); cell->callback(reset_cb); grid_cells_[j][k] = cell; } // Set icon for window Fl_Bitmap bm(sudoku_bits, sudoku_width, sudoku_height); Fl_Image_Surface surf(sudoku_width, sudoku_height, 1); Fl_Surface_Device::push_current(&surf); fl_color(FL_WHITE); fl_rectf(0, 0, sudoku_width, sudoku_height); fl_color(FL_BLACK); bm.draw(0, 0); Fl_Surface_Device::pop_current(); icon(surf.image()); // Catch window close events... callback(close_cb); // Make the window resizable... resizable(grid_); size_range(3 * GROUP_SIZE, 3 * GROUP_SIZE + MENU_OFFSET, 0, 0, 5, 5, 1); // Restore the previous window dimensions... int X, Y, W, H; if (prefs_.get("x", X, -1)) { prefs_.get("y", Y, -1); prefs_.get("width", W, 3 * GROUP_SIZE); prefs_.get("height", H, 3 * GROUP_SIZE + MENU_OFFSET); resize(X, Y, W, H); } set_title(); clear_undo(); } // Destroy the sudoku window... Sudoku::~Sudoku() { if (sound_) delete sound_; } // Check for a solution to the game... void Sudoku::check_cb(Fl_Widget *widget, void *) { sudoku->check_game(); } // Check if the user has correctly solved the game... void Sudoku::check_game(bool highlight) { bool empty = false; bool correct = true; int j, k, m; // Check the game for right/wrong answers... for (j = 0; j < 9; j ++) for (k = 0; k < 9; k ++) { SudokuCell *cell = grid_cells_[j][k]; int val = cell->value(); if (cell->readonly()) continue; if (!val) empty = true; else { for (m = 0; m < 9; m ++) if ((j != m && grid_cells_[m][k]->value() == val) || (k != m && grid_cells_[j][m]->value() == val)) break; if (m < 9) { if (highlight) { cell->color(FL_YELLOW); cell->redraw(); } correct = false; } else if (highlight) { cell->color(FL_LIGHT3); cell->redraw(); } } } // Check subgrids for duplicate numbers... for (j = 0; j < 9; j += 3) for (k = 0; k < 9; k += 3) for (int jj = 0; jj < 3; jj ++) for (int kk = 0; kk < 3; kk ++) { SudokuCell *cell = grid_cells_[j + jj][k + kk]; int val = cell->value(); if (cell->readonly() || !val) continue; int jjj; for (jjj = 0; jjj < 3; jjj ++) { int kkk; for (kkk = 0; kkk < 3; kkk ++) if (jj != jjj && kk != kkk && grid_cells_[j + jjj][k + kkk]->value() == val) break; if (kkk < 3) break; } if (jjj < 3) { if (highlight) { cell->color(FL_YELLOW); cell->redraw(); } correct = false; } } if (!empty && correct) { // Success! for (j = 0; j < 9; j ++) { for (k = 0; k < 9; k ++) { SudokuCell *cell = grid_cells_[j][k]; cell->color(FL_GREEN); cell->readonly(1); } if (sound_) sound_->play('A' + grid_cells_[j][8]->value() - 1); } } } // Close the window, saving the game first... void Sudoku::close_cb(Fl_Widget *widget, void *) { sudoku->save_game(); sudoku->hide(); if (help_dialog_) help_dialog_->hide(); } // Set the level of difficulty... void Sudoku::diff_cb(Fl_Widget *widget, void *d) { int diff = atoi((char *)d); if (diff != sudoku->difficulty_) { sudoku->difficulty_ = diff; sudoku->new_cb(widget, NULL); sudoku->set_title(); if (diff > 1) { // Display a message about the higher difficulty levels for the // Sudoku zealots of the world... int val; prefs_.get("difficulty_warning", val, 0); if (!val) { prefs_.set("difficulty_warning", 1); fl_alert("Note: 'Hard' and 'Impossible' puzzles may have more than " "one possible solution.\n" "This is not an error or bug."); } } prefs_.set("difficulty", sudoku->difficulty_); } } // Update the little marker numbers in all cells void Sudoku::update_helpers_cb(Fl_Widget *widget, void *) { sudoku->update_helpers(); } void Sudoku::update_helpers() { int j, k, m; // First we delete any entries that the user may have made for (j = 0; j < 9; j ++) { for (k = 0; k < 9; k ++) { SudokuCell *cell = grid_cells_[j][k]; cell->clear_hints(); } } // Now go through all cells and find out, what we can not be for (j = 0; j < 81; j ++) { char taken[10] = { 0 }; // Find our destination cell int row = j / 9; int col = j % 9; SudokuCell *dst_cell = grid_cells_[row][col]; if (dst_cell->value()) continue; // Find all values already taken in this row for (k = 0; k < 9; k ++) { SudokuCell *cell = grid_cells_[row][k]; int v = cell->value(); if (v) taken[v] = 1; } // Find all values already taken in this column for (k = 0; k < 9; k ++) { SudokuCell *cell = grid_cells_[k][col]; int v = cell->value(); if (v) taken[v] = 1; } // Now find all values already taken in this square int ro = (row / 3) * 3; int co = (col / 3) * 3; for (k = 0; k < 3; k ++) { for (m = 0; m < 3; m ++) { SudokuCell *cell = grid_cells_[ro + k][co + m]; int v = cell->value(); if (v) taken[v] = 1; } } // transfer our findings to the markers for (m = 1; m <= 9; m ++) { if (!taken[m]) dst_cell->set_hint(m); } } undo_checkpoint(); } void Sudoku::clear_hints_for(int row, int col, int val) { int i, j; // clear row for (i = 0; i < 9; ++i) grid_cells_[row][i]->clear_hint(val); // clear column for (i = 0; i < 9; ++i) grid_cells_[i][col]->clear_hint(val); // clear block row = (row / 3) * 3; col = (col / 3) * 3; for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) grid_cells_[row+i][col+j]->clear_hint(val); } // Show the on-line help... void Sudoku::help_cb(Fl_Widget *, void *) { if (!help_dialog_) { help_dialog_ = new Fl_Help_Dialog(); help_dialog_->value( "\n" "\n" "Sudoku Help\n" "\n" "\n" "

About the Game

\n" "

Sudoku (pronounced soo-dough-coo with the emphasis on the\n" "first syllable) is a simple number-based puzzle/game played on a\n" "9x9 grid that is divided into 3x3 subgrids. The goal is to enter\n" "a number from 1 to 9 in each cell so that each number appears\n" "only once in each column and row. In addition, each 3x3 subgrid\n" "may only contain one of each number.

\n" "

This version of the puzzle is copyright 2005-2010 by Michael R\n" "Sweet.

\n" "

Note: The 'Hard' and 'Impossible' difficulty\n" "levels generate Sudoku puzzles with multiple possible solutions.\n" "While some purists insist that these cannot be called 'Sudoku'\n" "puzzles, the author (me) has personally solved many such puzzles\n" "in published/printed Sudoku books and finds them far more\n" "interesting than the simple single solution variety. If you don't\n" "like it, don't play with the difficulty set to 'High' or\n" "'Impossible'.

\n" "

How to Play the Game

\n" "

At the start of a new game, Sudoku fills in a random selection\n" "of cells for you - the number of cells depends on the difficulty\n" "level you use. Click in any of the empty cells or use the arrow\n" "keys to highlight individual cells and press a number from 1 to 9\n" "to fill in the cell. To clear a cell, press 0, Delete, or\n" "Backspace. When you have successfully completed all subgrids, the\n" "entire puzzle is highlighted in green until you start a new\n" "game.

\n" "

As you work to complete the puzzle, you can display possible\n" "solutions inside each cell by holding the Shift key and pressing\n" "each number in turn. Repeat the process to remove individual\n" "numbers, or press a number without the Shift key to replace them\n" "with the actual number to use.

\n" "\n" ); } help_dialog_->show(); } // Load the game from saved preferences... void Sudoku::load_game() { // Load the current values and state of each grid... memset(grid_values_, 0, sizeof(grid_values_)); bool solved = true; for (int j = 0; j < 9; j ++) for (int k = 0; k < 9; k ++) { char name[255]; int val; SudokuCell *cell = grid_cells_[j][k]; snprintf(name, sizeof(name), "value%d.%d", j, k); if (!prefs_.get(name, val, 0)) { j = 9; grid_values_[0][0] = 0; break; } grid_values_[j][k] = val; snprintf(name, sizeof(name), "state%d.%d", j, k); prefs_.get(name, val, 0); cell->value(val); snprintf(name, sizeof(name), "readonly%d.%d", j, k); prefs_.get(name, val, 0); cell->readonly(val != 0); if (val) cell->color(FL_GRAY); else { cell->color(FL_LIGHT3); solved = false; } snprintf(name, sizeof(name), "hint%d.%d", j, k); prefs_.get(name, val, 0); cell->set_hint_map(val); } // If we didn't load any values or the last game was solved, then // create a new game automatically... if (solved || !grid_values_[0][0]) new_game(time(NULL)); else check_game(false); clear_undo(); } // Mute/unmute sound... void Sudoku::mute_cb(Fl_Widget *widget, void *) { if (sudoku->sound_) { delete sudoku->sound_; sudoku->sound_ = NULL; prefs_.set("mute_sound", 1); } else { sudoku->sound_ = new SudokuSound(); prefs_.set("mute_sound", 0); } } // Create a new game... void Sudoku::new_cb(Fl_Widget *widget, void *) { if (sudoku->grid_cells_[0][0]->color() != FL_GREEN) { if (!fl_choice("Are you sure you want to change the difficulty level and " "discard the current game?", "Keep Current Game", "Start New Game", NULL)) return; } sudoku->new_game(time(NULL)); } // Create a new game... void Sudoku::new_game(time_t seed) { int j, k, m, n, t, count; // Generate a new (valid) Sudoku grid... seed_ = seed; srand((unsigned int)seed); memset(grid_values_, 0, sizeof(grid_values_)); for (j = 0; j < 9; j += 3) { for (k = 0; k < 9; k += 3) { for (t = 1; t <= 9; t ++) { for (count = 0; count < 20; count ++) { m = j + (rand() % 3); n = k + (rand() % 3); if (!grid_values_[m][n]) { int mm; for (mm = 0; mm < m; mm ++) if (grid_values_[mm][n] == t) break; if (mm < m) continue; int nn; for (nn = 0; nn < n; nn ++) if (grid_values_[m][nn] == t) break; if (nn < n) continue; grid_values_[m][n] = t; break; } } if (count == 20) { // Unable to find a valid puzzle so far, so start over... k = 9; j = -3; memset(grid_values_, 0, sizeof(grid_values_)); } } } } // Start by making all cells editable SudokuCell *cell; for (j = 0; j < 9; j ++) for (k = 0; k < 9; k ++) { cell = grid_cells_[j][k]; cell->value(0); cell->readonly(0); cell->color(FL_LIGHT3); cell->clear_hints(); } // Show N cells... count = 11 * (5 - difficulty_); int numbers[9]; for (j = 0; j < 9; j ++) numbers[j] = j + 1; while (count > 0) { for (j = 0; j < 20; j ++) { k = rand() % 9; m = rand() % 9; t = numbers[k]; numbers[k] = numbers[m]; numbers[m] = t; } for (j = 0; count > 0 && j < 9; j ++) { t = numbers[j]; for (k = 0; count > 0 && k < 9; k ++) { cell = grid_cells_[j][k]; if (grid_values_[j][k] == t && !cell->readonly()) { cell->value(grid_values_[j][k]); cell->readonly(1); cell->color(FL_GRAY); count --; break; } } } } clear_undo(); } // Return the next available value for a cell... int Sudoku::next_value(SudokuCell *c) { int j = 0, k = 0, m = 0, n = 0; for (j = 0; j < 9; j ++) { for (k = 0; k < 9; k ++) if (grid_cells_[j][k] == c) break; if (k < 9) break; } if (j == 9) return 1; j -= j % 3; k -= k % 3; int numbers[9]; memset(numbers, 0, sizeof(numbers)); for (m = 0; m < 3; m ++) for (n = 0; n < 3; n ++) { c = grid_cells_[j + m][k + n]; if (c->value()) numbers[c->value() - 1] = 1; } for (j = 0; j < 9; j ++) if (!numbers[j]) return j + 1; return 1; } // Reset widget color to gray... void Sudoku::reset_cb(Fl_Widget *widget, void *) { widget->color(FL_LIGHT3); widget->redraw(); ((Sudoku *)(widget->window()))->check_game(false); } // Resize the window... void Sudoku::resize(int X, int Y, int W, int H) { // Resize the window... Fl_Double_Window::resize(X, Y, W, H); // Save the new window geometry... prefs_.set("x", X); prefs_.set("y", Y); prefs_.set("width", W); prefs_.set("height", H); } // Restart game from beginning... void Sudoku::restart_cb(Fl_Widget *widget, void *) { bool solved = true; for (int j = 0; j < 9; j ++) for (int k = 0; k < 9; k ++) { SudokuCell *cell = sudoku->grid_cells_[j][k]; cell->clear_hints(); if (!cell->readonly()) { solved = false; int v = cell->value(); cell->value(0); cell->color(FL_LIGHT3); if (v && sudoku->sound_) sudoku->sound_->play('A' + v - 1); } } if (solved) sudoku->new_game(sudoku->seed_); else sudoku->clear_undo(); } // Save the current game state... void Sudoku::save_game() { // Save the current values and state of each grid... for (int j = 0; j < 9; j ++) for (int k = 0; k < 9; k ++) { char name[255]; SudokuCell *cell = grid_cells_[j][k]; snprintf(name, sizeof(name), "value%d.%d", j, k); prefs_.set(name, grid_values_[j][k]); snprintf(name, sizeof(name), "state%d.%d", j, k); prefs_.set(name, cell->value()); snprintf(name, sizeof(name), "readonly%d.%d", j, k); prefs_.set(name, cell->readonly()); for (int m = 0; m < 8; m ++) { snprintf(name, sizeof(name), "hint%d.%d", j, k); prefs_.set(name, cell->get_hint_map()); } } } void Sudoku::save_state(GameState &s) { for (int j = 0; j < 9; j ++) { for (int k = 0; k < 9; k ++) { s[j*9+k] = grid_cells_[j][k]->state(); } } } void Sudoku::load_state(GameState &s) { for (int j = 0; j < 9; j ++) { for (int k = 0; k < 9; k ++) { grid_cells_[j][k]->state(s[j*9+k]); } } } void Sudoku::undo() { if (undo_head_ != undo_tail_) { undo_head_ = ((undo_head_-1) & 63); load_state(undo_stack[undo_head_]); redraw(); } else { fl_beep(FL_BEEP_ERROR); } } void Sudoku::redo() { if (undo_head_ != redo_head_) { undo_head_ = ((undo_head_+1) & 63); load_state(undo_stack[undo_head_]); redraw(); } else { fl_beep(FL_BEEP_ERROR); } } void Sudoku::clear_undo() { undo_head_ = undo_tail_ = redo_head_ = 0; save_state(undo_stack[undo_head_]); } void Sudoku::undo_checkpoint() { if (undo_head_ == redo_head_) { redo_head_ = ((redo_head_+1) & 63); } undo_head_ = ((undo_head_+1) & 63); if (undo_head_ == undo_tail_) { undo_tail_ = ((undo_tail_+1) & 63); } save_state(undo_stack[undo_head_]); } // Set title of window... void Sudoku::set_title() { static const char * const titles[] = { "Sudoku - Easy", "Sudoku - Medium", "Sudoku - Hard", "Sudoku - Impossible" }; label(titles[difficulty_]); } // Solve the puzzle... void Sudoku::solve_cb(Fl_Widget *widget, void *) { sudoku->solve_game(); } // Solve the puzzle... void Sudoku::solve_game() { int j, k; for (j = 0; j < 9; j ++) { for (k = 0; k < 9; k ++) { SudokuCell *cell = grid_cells_[j][k]; cell->value(grid_values_[j][k]); cell->readonly(1); cell->color(FL_GRAY); } if (sound_) sound_->play('A' + grid_cells_[j][8]->value() - 1); } undo_checkpoint(); } // Main entry for game... int main(int argc, char *argv[]) { Sudoku s; sudoku = &s; // Show the game... s.show(argc, argv); // Load the previous game... s.load_game(); // Run until the user quits... return (Fl::run()); } fltk-1.4.3/test/CMakeLists.txt0000644000175000017500000003406515004135251016334 0ustar albrechtalbrecht# # CMakeLists.txt used to build test and demo apps by the CMake build system # # Copyright 2004-2025 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # ####################################################################### include(../CMake/FLTK-Functions.cmake) include(../CMake/fl_create_example.cmake) set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/../bin/test) set(TESTFILE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../data) # create data and binary directory to copy scripts and data files file(MAKE_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) file(MAKE_DIRECTORY ${TESTFILE_PATH}) ####################################################################### # Define additional example programs for testing, for instance: # set(extra_tests issue-276 str-1895) # Use the source file test/'name'.cxx for each additional program. # These test programs will be built with image and GL libraries. # Leave the variable 'extra_tests' empty to disable extra test programs. set(extra_tests) ####################################################################### # audio libs for test apps if(WIN32) set(AUDIOLIBS winmm) elseif(APPLE) set(AUDIOLIBS "-framework CoreAudio") elseif(HAVE_ALSA_ASOUNDLIB_H) find_library(LIB_asound asound) if(LIB_asound) set(AUDIOLIBS ${LIB_asound}) endif(LIB_asound) mark_as_advanced (LIB_asound) endif(WIN32) ####################################################################### # Define standard libraries for those OpenGL demos that can be built # w/o OpenGL as well. These demos show an alternate GUI or a warning # when built w/o OpenGL. # # Note: use "${GLDEMO_LIBS}" for their library parameter # or "${GLDEMO_SHARED}" to build with shared FLTK libraries if(OPENGL_FOUND) set(GLDEMO_LIBS fltk::gl) if(MSVC) set(GLDEMO_SHARED fltk::fltk-shared) else() set(GLDEMO_SHARED fltk::gl-shared) endif() else() set(GLDEMO_LIBS fltk::fltk) set(GLDEMO_SHARED fltk::fltk-shared) endif() # Similar approach for the 'forms' demo (shared lib not supported) if(FLTK_BUILD_FORMS) set(FORMS_LIBS fltk::forms) else() set(FORMS_LIBS fltk::fltk) endif() ####################################################################### fl_create_example(adjuster adjuster.cxx fltk::fltk) fl_create_example(arc arc.cxx fltk::fltk) fl_create_example(animated animated.cxx fltk::fltk) fl_create_example(ask ask.cxx fltk::fltk) fl_create_example(bitmap bitmap.cxx fltk::fltk) fl_create_example(boxtype boxtype.cxx fltk::fltk) fl_create_example(browser browser.cxx fltk::fltk) fl_create_example(button button.cxx fltk::fltk) fl_create_example(buttons buttons.cxx fltk::fltk) # Cairo demo, built with and w/o Cairo (libcairo is linked implicitly - or not at all) fl_create_example(cairo_test cairo_test.cxx fltk::fltk) fl_create_example(clipboard clipboard.cxx fltk::images) fl_create_example(clock clock.cxx fltk::fltk) fl_create_example(colbrowser colbrowser.cxx fltk::fltk) fl_create_example(color_chooser color_chooser.cxx fltk::fltk) fl_create_example(contrast contrast.cxx fltk::fltk) fl_create_example(coordinates coordinates.cxx fltk::fltk) fl_create_example(cursor cursor.cxx fltk::fltk) fl_create_example(curve curve.cxx fltk::fltk) fl_create_example(demo demo.cxx fltk::fltk) fl_create_example(device device.cxx fltk::images) fl_create_example(doublebuffer doublebuffer.cxx fltk::fltk) fl_create_example(editor "editor.cxx;editor.plist" fltk::fltk) fl_create_example(fast_slow fast_slow.fl fltk::fltk) fl_create_example(file_chooser file_chooser.cxx fltk::images) fl_create_example(flex_demo flex_demo.cxx fltk::fltk) fl_create_example(flex_login flex_login.cxx fltk::fltk) fl_create_example(fltk-versions fltk-versions.cxx fltk::fltk) fl_create_example(fonts fonts.cxx fltk::fltk) fl_create_example(forms forms.cxx "${FORMS_LIBS}") fl_create_example(fullscreen fullscreen.cxx "${GLDEMO_LIBS}") fl_create_example(grid_alignment grid_alignment.cxx fltk::fltk) fl_create_example(grid_buttons grid_buttons.cxx fltk::fltk) fl_create_example(grid_dialog grid_dialog.cxx fltk::fltk) fl_create_example(grid_login grid_login.cxx fltk::fltk) fl_create_example(handle_events handle_events.cxx "${GLDEMO_LIBS}") fl_create_example(handle_keys handle_keys.cxx fltk::fltk) fl_create_example(hello hello.cxx fltk::fltk) fl_create_example(help_dialog help_dialog.cxx fltk::images) fl_create_example(icon icon.cxx fltk::fltk) fl_create_example(iconize iconize.cxx fltk::fltk) fl_create_example(image image.cxx fltk::fltk) fl_create_example(inactive inactive.fl fltk::fltk) fl_create_example(input input.cxx fltk::fltk) fl_create_example(input_choice input_choice.cxx fltk::fltk) fl_create_example(keyboard "keyboard.cxx;keyboard_ui.fl" fltk::fltk) fl_create_example(label label.cxx fltk::fltk) fl_create_example(line_style line_style.cxx fltk::fltk) fl_create_example(line_style_docs line_style_docs.cxx fltk::fltk) fl_create_example(list_visuals list_visuals.cxx fltk::fltk) fl_create_example(mandelbrot "mandelbrot_ui.fl;mandelbrot.cxx" fltk::fltk) fl_create_example(menubar menubar.cxx fltk::fltk) fl_create_example(message message.cxx fltk::fltk) fl_create_example(minimum minimum.cxx fltk::fltk) fl_create_example(native-filechooser native-filechooser.cxx fltk::images) fl_create_example(navigation navigation.cxx fltk::fltk) fl_create_example(output output.cxx fltk::fltk) fl_create_example(overlay overlay.cxx fltk::fltk) fl_create_example(pack pack.cxx fltk::fltk) fl_create_example(pixmap pixmap.cxx fltk::images) fl_create_example(pixmap_browser pixmap_browser.cxx fltk::images) fl_create_example(preferences preferences.fl fltk::fltk) fl_create_example(offscreen offscreen.cxx fltk::fltk) fl_create_example(radio radio.fl fltk::fltk) fl_create_example(resize resize.fl fltk::fltk) fl_create_example(resizebox resizebox.cxx fltk::fltk) fl_create_example(resize-example1 "resize-example1.cxx;resize-arrows.cxx" fltk::fltk) fl_create_example(resize-example2 "resize-example2.cxx;resize-arrows.cxx" fltk::fltk) fl_create_example(resize-example3a "resize-example3a.cxx;resize-arrows.cxx" fltk::fltk) fl_create_example(resize-example3b "resize-example3b.cxx;resize-arrows.cxx" fltk::fltk) fl_create_example(resize-example3c "resize-example3c.cxx;resize-arrows.cxx" fltk::fltk) fl_create_example(resize-example4a "resize-example4a.cxx;resize-arrows.cxx" fltk::fltk) fl_create_example(resize-example4b "resize-example4b.cxx;resize-arrows.cxx" fltk::fltk) fl_create_example(resize-example5a "resize-example5a.cxx;resize-arrows.cxx" fltk::fltk) fl_create_example(resize-example5b "resize-example5b.cxx;resize-arrows.cxx" fltk::fltk) fl_create_example(resize-example5c "resize-example5c.cxx;resize-arrows.cxx" fltk::fltk) fl_create_example(rotated_text rotated_text.cxx fltk::fltk) fl_create_example(scroll scroll.cxx fltk::fltk) fl_create_example(subwindow subwindow.cxx fltk::fltk) fl_create_example(symbols symbols.cxx fltk::fltk) fl_create_example(tabs tabs.fl fltk::fltk) fl_create_example(table table.cxx fltk::fltk) fl_create_example(terminal terminal.fl fltk::fltk) fl_create_example(threads threads.cxx fltk::fltk) fl_create_example(tile tile.cxx fltk::fltk) fl_create_example(tiled_image tiled_image.cxx fltk::fltk) fl_create_example(tree tree.fl fltk::fltk) fl_create_example(twowin twowin.cxx fltk::fltk) fl_create_example(utf8 utf8.cxx fltk::fltk) fl_create_example(valuators valuators.fl fltk::fltk) fl_create_example(windowfocus windowfocus.cxx fltk::fltk) fl_create_example(wizard wizard.cxx fltk::fltk) # games if(NOT FLTK_BUILD_SHARED_LIBS) fl_create_example(blocks "blocks.cxx;blocks.plist;blocks.icns" "fltk::fltk;${AUDIOLIBS}") fl_create_example(checkers "checkers.cxx;checkers_pieces.fl;checkers.icns" fltk::images) fl_create_example(sudoku "sudoku.cxx;sudoku.plist;sudoku.icns;sudoku.rc" "fltk::images;${AUDIOLIBS}") endif() # unittests uses multiple source files and can be built with or w/o OpenGL and "shared" SET (UNITTEST_SRCS unittests.cxx unittests.h unittest_about.cxx unittest_points.cxx unittest_core.cxx unittest_complex_shapes.cxx unittest_fast_shapes.cxx unittest_circles.cxx unittest_text.cxx unittest_unicode.cxx unittest_symbol.cxx unittest_images.cxx unittest_viewport.cxx unittest_scrollbarsize.cxx unittest_schemes.cxx unittest_terminal.cxx ) fl_create_example(unittests "${UNITTEST_SRCS}" "${GLDEMO_LIBS}") # Create additional test programs (used by developers for testing) if(extra_tests) foreach(name ${extra_tests}) fl_create_example(${name} ${name}.cxx "fltk::images;${GLDEMO_LIBS}") endforeach() endif() # OpenGL demos. These programs can't be built w/o OpenGL if(OPENGL_FOUND) fl_create_example(CubeView "CubeMain.cxx;CubeView.cxx;CubeViewUI.fl" "${GLDEMO_LIBS}") fl_create_example(cube cube.cxx "${GLDEMO_LIBS}") fl_create_example(fractals "fractals.cxx;fracviewer.cxx" "${GLDEMO_LIBS}") fl_create_example(glut_test glut_test.cxx "${GLDEMO_LIBS}") if(NOT FLTK_BUILD_SHARED_LIBS) fl_create_example(glpuzzle glpuzzle.cxx "${GLDEMO_LIBS}") endif() fl_create_example(gl_overlay gl_overlay.cxx "${GLDEMO_LIBS}") fl_create_example(shape shape.cxx "${GLDEMO_LIBS}") endif(OPENGL_FOUND) # Test FLTK headers for variable shadowing [-Wshadow] (STR 2728) # # The following test program is added only for GNU or Clang compilers which # are known to support the '-Wshadow' compiler flag. We could also implement # a compile test but using GNU and Clang appears to be sufficient. # # Note 1: usage of `file(GLOB ...)` is discouraged by CMake documentation because # it doesn't trigger rebuilding when new header files are added. However, this # is better than nothing. # # Note 2: a better way to generate the header file might be with a custom command # to be able to generate proper dependencies but this is left for later... # # Note 3: this test program is only included in CMake builds and was inspired # by STR 2728: "Add test program to test for shadowed variables (-Wshadow)". # Its sole purpose is to issue compilation warnings during build time if # variables are shadowed in public headers. set(_compilers GNU Clang AppleClang) if(CMAKE_CXX_COMPILER_ID IN_LIST _compilers) set(include_all "${CMAKE_CURRENT_BINARY_DIR}/include_all.h") file(WRITE ${include_all} "/* DO NOT EDIT - this file is created by CMake */\n") file(GLOB all_headers "${FLTK_SOURCE_DIR}/FL/*.[hH]") foreach(hd ${all_headers}) get_filename_component(hd "${hd}" NAME) # skip headers that must not be included directly and fl_config.h if it exists string(REGEX MATCH "^(mac|win32|x11|wayland|fl_config|gl[a-z_0-9]*)\.[hH]$" skip "${hd}") if(skip STREQUAL "") file(APPEND ${include_all} "#include \n") endif() endforeach() if(FLTK_USE_GL) file(GLOB all_headers "${FLTK_SOURCE_DIR}/FL/gl*.[hH]") foreach(hd ${all_headers}) get_filename_component(hd "${hd}" NAME) file(APPEND ${include_all} "#include \n") endforeach() endif(FLTK_USE_GL) file(APPEND ${include_all} "/* End of generated file */\n") # now add the 'shadow_variables' target and set the compiler flag fl_create_example(shadow_variables shadow_variables.cxx fltk::fltk) set_target_properties(shadow_variables PROPERTIES COMPILE_FLAGS -Wshadow) endif() # GNU or Clang (-Wshadow test) unset(_compilers) # Build some of the demo programs linked against the shared FLTK lib(s). if(FLTK_BUILD_SHARED_LIBS) if(MSVC) # MS Visual C++ aka. Visual Studio # We need to link with fl_call_main.c which is available as an object # library 'call_main' when built with MSVC (see main CMakeLists.txt). fl_create_example(hello-shared hello.cxx "call_main;fltk::fltk-shared") fl_create_example(pixmap_browser-shared pixmap_browser.cxx "call_main;fltk::fltk-shared") fl_create_example(unittests-shared "${UNITTEST_SRCS}" "call_main;${GLDEMO_SHARED}") # Games fl_create_example(blocks-shared "blocks.cxx;blocks.plist;blocks.icns" "call_main;fltk::fltk-shared;${AUDIOLIBS}") fl_create_example(checkers-shared "checkers.cxx;checkers_pieces.fl;checkers.icns" "call_main;fltk::fltk-shared") fl_create_example(sudoku-shared "sudoku.cxx;sudoku.plist;sudoku.icns;sudoku.rc" "call_main;fltk::fltk-shared;${AUDIOLIBS}") if(OPENGL_FOUND) fl_create_example(glpuzzle-shared glpuzzle.cxx "call_main;${GLDEMO_SHARED}") fl_create_example(shape-shared shape.cxx "call_main;${GLDEMO_SHARED}") endif(OPENGL_FOUND) else() # not MSVC fl_create_example(cairo_test-shared cairo_test.cxx fltk::fltk-shared) fl_create_example(hello-shared hello.cxx fltk::fltk-shared) fl_create_example(pixmap_browser-shared pixmap_browser.cxx fltk::images-shared) fl_create_example(unittests-shared "${UNITTEST_SRCS}" "${GLDEMO_SHARED}") # Games fl_create_example(blocks-shared "blocks.cxx;blocks.plist;blocks.icns" "fltk::fltk-shared;${AUDIOLIBS}") fl_create_example(checkers-shared "checkers.cxx;checkers_pieces.fl;checkers.icns" fltk::images-shared) fl_create_example(sudoku-shared "sudoku.cxx;sudoku.plist;sudoku.icns;sudoku.rc" "fltk::images-shared;${AUDIOLIBS}") if(OPENGL_FOUND) fl_create_example(glpuzzle-shared glpuzzle.cxx "${GLDEMO_SHARED}") fl_create_example(shape-shared shape.cxx "${GLDEMO_SHARED}") endif(OPENGL_FOUND) endif(MSVC) # (not MSVC) endif(FLTK_BUILD_SHARED_LIBS) ##################################################### # We need some support files for the demo programs ##################################################### # copy the required test files file(COPY demo.menu rgb.txt browser.cxx editor.cxx valuators.fl help_dialog.html DESTINATION ${TESTFILE_PATH} ) # copy the image directory for help_dialog.html file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/images DESTINATION ${TESTFILE_PATH} ) # The main test program 'demo' needs additional hints and configurations. # Note: CMake defines "CMAKE_INTDIR" which is the build type folder (e.g. "Debug") # for multi config builds (MSVC, Xcode) target_compile_definitions (demo PRIVATE GENERATED_BY_CMAKE) fltk-1.4.3/test/utf8.cxx0000644000175000017500000004376615004135251015216 0ustar albrechtalbrecht// // UTF-8 test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // // Font chooser widget for the Fast Light Tool Kit(FLTK). // #define DEF_SIZE 16 // default value for the font size picker static Fl_Double_Window *fnt_chooser_win; static Fl_Hold_Browser *fontobj; static Fl_Hold_Browser *sizeobj; static Fl_Value_Output *fnt_cnt; static Fl_Button *refresh_btn; static Fl_Button *choose_btn; static Fl_Output *fix_prop; static Fl_Check_Button *own_face; static int **sizes = NULL; static int *numsizes = NULL; static int pickedsize = DEF_SIZE; static char label[1000]; static Fl_Double_Window *main_win; static Fl_Scroll *thescroll; static Fl_Font extra_font; static int font_count = 0; static int first_free = 0; static void cb_exit(Fl_Button*, void*) { if(fnt_chooser_win) fnt_chooser_win->hide(); if(main_win) main_win->hide(); } /* cb_exit */ /* Class for displaying sample fonts. */ class FontDisplay : public Fl_Widget { void draw(void) FL_OVERRIDE; public: int font, size; int test_fixed_pitch(void); FontDisplay(Fl_Boxtype B, int X, int Y, int W, int H, const char *L = 0) : Fl_Widget(X, Y, W, H, L) { box(B); font = 0; size = DEF_SIZE; } }; /* Draw the sample text. */ void FontDisplay::draw(void) { draw_box(); fl_font((Fl_Font)font, size); fl_color(FL_BLACK); fl_draw(label(), x() + 3, y() + 3, w() - 6, h() - 6, align()); } int FontDisplay::test_fixed_pitch(void) { int w1, w2; int h1, h2; w1 = w2 = 0; h1 = h2 = 0; fl_font((Fl_Font)font, size); fl_measure("MHMHWWMHMHMHM###WWX__--HUW", w1, h1, 0); fl_measure("iiiiiiiiiiiiiiiiiiiiiiiiii", w2, h2, 0); if (w1 == w2) return 1; // exact match - fixed pitch // Is the font "nearly" fixed pitch? If it is within 5%, say it is... double f1 = (double)w1; double f2 = (double)w2; double delta = fabs(f1 - f2) * 5.0; if (delta <= f1) return 2; // nearly fixed pitch... return 0; // NOT fixed pitch } static FontDisplay *textobj; static void size_cb(Fl_Widget *, long) { int size_idx = sizeobj->value(); if (!size_idx) return; const char *c = sizeobj->text(size_idx); while (*c < '0' || *c > '9') c++; // find the first numeric char pickedsize = atoi(c); // convert the number string to a value // Now set the font view to the selected size and redraw it. textobj->size = pickedsize; textobj->redraw(); } static void font_cb(Fl_Widget *, long) { int font_idx = fontobj->value() + first_free; if (!font_idx) return; font_idx--; textobj->font = font_idx; sizeobj->clear(); int size_count = numsizes[font_idx-first_free]; int *size_array = sizes[font_idx-first_free]; if (!size_count) { // no preferred sizes - probably TT fonts etc... } else if (size_array[0] == 0) { // many sizes, probably a scaleable font with preferred sizes int j = 1; for (int i = 1; i <= 64 || i < size_array[size_count - 1]; i++) { char buf[16]; if (j < size_count && i == size_array[j]) { snprintf(buf, 16, "@b%d", i); j++; } else snprintf(buf, 16, "%d", i); sizeobj->add(buf); } sizeobj->value(pickedsize); } else { // some sizes, probably a font with a few fixed sizes available int w = 0; for (int i = 0; i < size_count; i++) { // find the nearest available size to the current picked size if (size_array[i] <= pickedsize) w = i; char buf[16]; snprintf(buf, 16, "@b%d", size_array[i]); sizeobj->add(buf); } sizeobj->value(w + 1); } size_cb(sizeobj, 0); // force selection of nearest valid size, then redraw // Now check to see if the font looks like a fixed pitch font or not... int looks_fixed = textobj->test_fixed_pitch(); if(looks_fixed) { if (looks_fixed > 1) fix_prop->value("near"); else fix_prop->value("fixed"); } else { fix_prop->value("prop"); } } static void choose_cb(Fl_Widget *, long) { int font_idx = fontobj->value() + first_free; if (!font_idx) { puts("No font chosen"); } else { int font_type; font_idx -= 1; const char *name = Fl::get_font_name((Fl_Font)font_idx, &font_type); printf("idx %d\nUser name :%s:\n", font_idx, name); printf("FLTK name :%s:\n", Fl::get_font((Fl_Font)font_idx)); Fl::set_font(extra_font, (Fl_Font)font_idx); // Fl::set_font(extra_font, Fl::get_font((Fl_Font)font_idx)); } int size_idx = sizeobj->value(); if (!size_idx) { puts("No size selected"); } else { const char *c = sizeobj->text(size_idx); while (*c < '0' || *c > '9') c++; // find the first numeric char int pickedsize = atoi(c); // convert the number string to a value printf("size %d\n\n", pickedsize); } fflush(stdout); main_win->redraw(); } static void refresh_cb(Fl_Widget *, long) { main_win->redraw(); } static void own_face_cb(Fl_Widget *, void *) { int font_idx; int cursor_restore = 0; static int i_was = -1; // used to keep track of where we were in the list... if (i_was < 0) { // not been here before i_was = 1; } else { i_was = fontobj->topline(); // record which was the topmost visible line fontobj->clear(); // Populating the font widget can be slower than an old dog with three legs // on a bad day, show a wait cursor fnt_chooser_win->cursor(FL_CURSOR_WAIT); cursor_restore = 1; } // Populate the font list with the names of the fonts found for (font_idx = first_free; font_idx < font_count; font_idx++) { int font_type; const char *name = Fl::get_font_name((Fl_Font)font_idx, &font_type); char buffer[128]; if(own_face->value() == 0) { char *p = buffer; // if the font is BOLD, set the bold attribute in the list if (font_type & FL_BOLD) { *p++ = '@'; *p++ = 'b'; } if (font_type & FL_ITALIC) { // ditto for italic fonts *p++ = '@'; *p++ = 'i'; } // Suppress subsequent formatting - some MS fonts have '@' in their name *p++ = '@'; *p++ = '.'; strcpy(p, name); } else { // Show font in its own face // this is neat, but really slow on some systems: // uses each font to display its own name snprintf (buffer, sizeof(buffer), "@F%d@.%s", font_idx, name); } fontobj->add(buffer); } // now put the browser position back the way it was... more or less fontobj->topline(i_was); // restore the cursor if(cursor_restore) fnt_chooser_win->cursor(FL_CURSOR_DEFAULT); } static void create_font_widget() { // Create the font sample label strcpy(label, "Font Sample\n"); int i = 12; // strlen(label); int n = 0; ulong c; for (c = ' '+1; c < 127; c++) { if (!(c&0x1f)) label[i++]='\n'; if (c == '@') label[i++] = '@'; label[i++] = (char)c; } label[i++] = '\n'; for (c = 0xA1; c < 0x600; c += 9) { if (!(++n&(0x1f))) label[i++]='\n'; i += fl_utf8encode((unsigned int)c, label + i); } label[i] = 0; // Create the window layout fnt_chooser_win = new Fl_Double_Window(380, 420, "Font Selector"); { Fl_Tile *tile = new Fl_Tile(0, 0, 380, 420); { Fl_Group *textgroup = new Fl_Group(0, 0, 380, 105); { textobj = new FontDisplay(FL_FRAME_BOX, 10, 10, 360, 90, label); textobj->align(FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP); textobj->color(53, 3); textgroup->box(FL_FLAT_BOX); textgroup->resizable(textobj); textgroup->end(); } Fl_Group *fontgroup = new Fl_Group(0, 105, 380, 315); { fontobj = new Fl_Hold_Browser(10, 110, 290, 270); fontobj->box(FL_FRAME_BOX); fontobj->color(53, 3); fontobj->callback(font_cb); fnt_chooser_win->resizable(fontobj); sizeobj = new Fl_Hold_Browser(310, 110, 60, 270); sizeobj->box(FL_FRAME_BOX); sizeobj->color(53, 3); sizeobj->callback(size_cb); // Create the status bar Fl_Group *stat_bar = new Fl_Group (10, 385, 380, 30); { fnt_cnt = new Fl_Value_Output(10, 390, 40, 20); fnt_cnt->label("fonts"); fnt_cnt->align(FL_ALIGN_RIGHT); fix_prop = new Fl_Output(100, 390, 40, 20); fix_prop->color(FL_BACKGROUND_COLOR); fix_prop->value("prop"); fix_prop->clear_visible_focus(); own_face = new Fl_Check_Button(150, 390, 40, 20, "Self"); own_face->value(0); own_face->type(FL_TOGGLE_BUTTON); own_face->clear_visible_focus(); own_face->callback(own_face_cb); own_face->tooltip("Display font names in their own face"); Fl_Box * dummy = new Fl_Box(220, 390, 1, 1); choose_btn = new Fl_Button(240, 385, 60, 30); choose_btn->label("Select"); choose_btn->callback(choose_cb); refresh_btn = new Fl_Button(310, 385, 60, 30); refresh_btn->label("Refresh"); refresh_btn->callback(refresh_cb); stat_bar->resizable (dummy); stat_bar->end(); } fontgroup->box(FL_FLAT_BOX); fontgroup->resizable(fontobj); fontgroup->end(); } tile->end(); } fnt_chooser_win->resizable(tile); fnt_chooser_win->end(); fnt_chooser_win->callback((Fl_Callback*)cb_exit); } } int make_font_chooser(void) { int font_idx; // create the widget frame create_font_widget(); // Load the system's available fonts #if defined(FLTK_USE_X11) && !defined(FLTK_USE_CAIRO) // ask for everything that claims to be iso10646 compatible font_count = Fl::set_fonts("-*-*-*-*-*-*-*-*-*-*-*-*-iso10646-1"); #else // ask for everything font_count = Fl::set_fonts("*"); #endif // allocate space for the sizes and numsizes array, now we know how many // entries it needs sizes = new int*[font_count]; numsizes = new int[font_count]; // Populate the font list with the names of the fonts found first_free = FL_FREE_FONT; for (font_idx = first_free; font_idx < font_count; font_idx++) { // Find out how many sizes are supported for each font face int *size_array; int size_count = Fl::get_font_sizes((Fl_Font)font_idx, size_array); numsizes[font_idx-first_free] = size_count; // if the font has multiple sizes, populate the 2-D sizes array if (size_count) { sizes[font_idx-first_free] = new int[size_count]; for (int j = 0; j < size_count; j++) sizes[font_idx-first_free][j] = size_array[j]; } } // end of font list filling loop // Call this once to get the font browser loaded up own_face_cb(NULL, 0); fontobj->value(1); // optional hard-coded font for testing - do not use! // fontobj->textfont(261); font_cb(fontobj, 0); fnt_cnt->value(font_count); return font_count; } // make_font_chooser /* End of Font Chooser Widget code */ /* Unicode Font display widget */ void box_cb(Fl_Widget* o, void*) { thescroll->box(((Fl_Button*)o)->value() ? FL_DOWN_FRAME : FL_NO_BOX); thescroll->redraw(); } class right_left_input : public Fl_Input { public: right_left_input (int x, int y, int w, int h) : Fl_Input(x, y, w, h) {} void draw() FL_OVERRIDE { if (type() == FL_HIDDEN_INPUT) return; Fl_Boxtype b = box(); if (damage() & FL_DAMAGE_ALL) draw_box(b, color()); drawtext(x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b), w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b)); } void drawtext(int X, int Y, int W, int H) { fl_color(textcolor()); fl_font(textfont(), textsize()); fl_rtl_draw(value(), (int)strlen(value()), X + W, Y + fl_height() - fl_descent()); } }; void i7_cb(Fl_Widget *w, void *d) { int i = 0; char nb[] = "01234567"; Fl_Input *i7 = (Fl_Input*)w; Fl_Input *i8 = (Fl_Input*)d; static char buf[1024]; const char *ptr = i7->value(); while (ptr && *ptr) { if (*ptr < ' ' || *ptr > 126) { buf[i++] = '\\'; buf[i++] = nb[((*ptr >> 6) & 0x3)]; buf[i++] = nb[((*ptr >> 3) & 0x7)]; buf[i++] = nb[(*ptr & 0x7)]; } else { if (*ptr == '\\') buf[i++] = '\\'; buf[i++] = *ptr; } ptr++; } buf[i] = 0; i8->value(buf); } class UCharDropBox : public Fl_Output { public: UCharDropBox(int x, int y, int w, int h, const char *label=0) : Fl_Output(x, y, w, h, label) { } int handle(int event) FL_OVERRIDE { switch (event) { case FL_DND_ENTER: return 1; case FL_DND_DRAG: return 1; case FL_DND_RELEASE: return 1; case FL_PASTE: { static const char lut[] = "0123456789abcdef"; const char *t = Fl::event_text(); int i, n; unsigned int ucode = fl_utf8decode(t, t+Fl::event_length(), &n); if (n==0) { value(""); return 1; } char buffer[200], *d = buffer; for (i=0; i>4)&0x0f]; *d++ = lut[t[i]&0x0f]; } *d++ = ' '; *d++ = '0'; *d++ = 'x'; *d++ = lut[(ucode>>20)&0x0f]; *d++ = lut[(ucode>>16)&0x0f]; *d++ = lut[(ucode>>12)&0x0f]; *d++ = lut[(ucode>>8)&0x0f]; *d++ = lut[(ucode>>4)&0x0f]; *d++ = lut[ucode&0x0f]; *d++ = 0; value(buffer); } return 1; } return Fl_Output::handle(event); } }; int main(int argc, char** argv) { const char *latin1 = // "ABCabcàèéïßîöüã123" "\x41\x42\x43\x61\x62\x63\xe0\xe8\xe9\xef\xdf\xee\xf6\xfc\xe3\x31\x32\x33"; const char *emoji = // grinning face with smiling eyes, thumbs up "\360\237\230\204\360\237\221\215end"; // NOTE: FLTK does not currently support modifiers like skin tones // or ZWJs (zero width joiners) char *utf8 = (char*) malloc((strlen(latin1)+4) * 5 + 1); int l = fl_utf8froma(utf8, (unsigned int)strlen(latin1) * 5 + 1, latin1, (unsigned int)strlen(latin1)); utf8[l] = '\0'; strcat(utf8, emoji); l = (int)strlen(utf8); make_font_chooser(); extra_font = FL_TIMES_BOLD_ITALIC; /* setup the extra font */ Fl::set_font(extra_font, #ifdef _WIN32 " Microsoft Sans Serif" #elif defined(__APPLE__) "Monaco" #else "-*-*-*-*-*-*-*-*-*-*-*-*-iso10646-1" #endif ); main_win = new Fl_Double_Window (200 + 5*75, 400, "Unicode Display Test"); main_win->begin(); Fl_Input i1(5, 5, 190, 25); i1.value(utf8); Fl_Scroll scroll(200,0,5 * 75,400); int off = 2; int end_list = 0x10000 / 16; if (argc > 1) { off = (int)strtoul(argv[1], NULL, 0); end_list = off + 0x10000; off /= 16; end_list /= 16; } argc = 1; for (int y = off; y < end_list; y++) { int o = 0; char bu[25]; // index label char buf[16 * 6]; // utf8 text int i = 16 * y; for (int x = 0; x < 16; x++) { int l; l = fl_utf8encode(i, buf + o); if (l < 1) l = 1; o += l; i++; } buf[o] = '\0'; snprintf(bu, sizeof(bu), "0x%06X", y * 16); Fl_Input *b = new Fl_Input(200,(y-off)*25,80,25); b->textfont(FL_COURIER); b->value(bu); b = new Fl_Input(280,(y-off)*25,380,25); b->textfont(extra_font); b->value(buf); } scroll.end(); main_win->resizable(scroll); thescroll = &scroll; char *utf8l = (char*) malloc(strlen(utf8) * 3 + 1); Fl_Input i2(5, 35, 190, 25); l = fl_utf_tolower((const unsigned char*)utf8, l, utf8l); utf8l[l] = '\0'; i2.value(utf8l); char *utf8u = (char*) malloc(strlen(utf8l) * 3 + 1); Fl_Input i3(5, 65, 190, 25); l = fl_utf_toupper((const unsigned char*)utf8l, l, utf8u); utf8u[l] = '\0'; i3.value(utf8u); // free strings that are no longer used free(utf8u); free(utf8l); free(utf8); const char *ltr_txt = "\\->e\xCC\x82=\xC3\xAA"; Fl_Input i4(5, 90, 190, 25); i4.value(ltr_txt); i4.textfont(extra_font); wchar_t r_to_l_txt[] = {/*8238,*/ 1610, 1608, 1606, 1604, 1603, 1608, 1583, 0}; char abuf[40]; // l = fl_unicode2utf(r_to_l_txt, 8, abuf); l = fl_utf8fromwc(abuf, 40, r_to_l_txt, 8); abuf[l] = 0; right_left_input i5(5, 115, 190, 50); i5.textfont(extra_font); i5.textsize(30); i5.value(abuf); Fl_Input i7(5, 230, 190, 25); Fl_Input i8(5, 260, 190, 25); i7.callback(i7_cb, &i8); i7.textsize(20); i7.value(abuf); i7.when(FL_WHEN_CHANGED); wchar_t r_to_l_txt1[] = { /*8238,*/ 1610, 0x20, 1608, 0x20, 1606, 0x20, 1604, 0x20, 1603, 0x20, 1608, 0x20, 1583, 0}; // l = fl_unicode2utf(r_to_l_txt1, 14, abuf); l = fl_utf8fromwc(abuf, 40, r_to_l_txt1, 14); abuf[l] = 0; right_left_input i6(5, 175, 190, 50); i6.textfont(extra_font); i6.textsize(30); i6.value(abuf); // Now try Greg Ercolano's Japanese test sequence // SOME JAPANESE UTF-8 TEXT const char *utfstr = "\xe4\xbd\x95\xe3\x82\x82\xe8\xa1" "\x8c\xe3\x82\x8b\xe3\x80\x82"; UCharDropBox db(5, 300, 190, 30); db.textsize(16); db.value("unichar drop box"); Fl_Output o9(5, 330, 190, 45); o9.textfont(extra_font); o9.textsize(30); o9.value(utfstr); main_win->end(); main_win->callback((Fl_Callback*)cb_exit); fl_set_status(0, 370, 100, 30); main_win->show(argc,argv); fnt_chooser_win->show(); int ret = Fl::run(); // Free up the sizes arrays we allocated if(numsizes) {delete [] numsizes;} if(sizes) {delete [] sizes;} return ret; } fltk-1.4.3/test/fullscreen.cxx0000644000175000017500000002304515004135251016456 0ustar albrechtalbrecht// // // Copyright 1998-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // Fullscreen test program for the Fast Light Tool Kit (FLTK). // // This demo shows how to do many of the window manipulations that // are popular on SGI programs, even though X does not really like // them. You can toggle the border on/off, change the visual to // switch between single/double buffer, and make the window take // over the screen. // // Normally the program makes a single window with a child GL window. // This simulates a program where the 3D display is surrounded by // control knobs. Running the program with an argument will // make it make a seperate GL window from the controls window. This // simulates a (older?) style program where the graphics display is // a different window than the controls. // // This program reports how many times it redraws the window to // stdout, so you can see how much time it is wasting. It appears // to be impossible to prevent X from sending redundant resize // events, so there are extra redraws. But the way I have the // code arranged here seems to be keeping that to a minimu. // // Apparently unavoidable bugs: // // Turning the border on causes an unnecessary redraw. // // Turning off full screen when the border is on causes an unnecessary // resize and redraw when the program turns the border on. // // If it is a separate window, turning double buffering on and off // will cause the window to raise, deiconize, and possibly move. You // can avoid this by making the Fl_Gl_Window a child of a normal // window. #include #include #include #include #include #include #include #include #include #include #include #if HAVE_GL #include #include class shape_window : public Fl_Gl_Window { void draw() FL_OVERRIDE; public: int sides; shape_window(int x,int y,int w,int h,const char *l=0); }; shape_window::shape_window(int x,int y,int w,int h,const char *l) : Fl_Gl_Window(x,y,w,h,l) { sides = 3; } void shape_window::draw() { // fprintf(stderr, "drawing size %d %d\n", w(), h()); if (!valid()) { valid(1); // fprintf(stderr, "init\n"); glLoadIdentity(); glViewport(0,0,pixel_w(),pixel_h()); } glClear(GL_COLOR_BUFFER_BIT); glColor3f(.5f, .6f, .7f); glBegin(GL_POLYGON); for (int j = 0; j < sides; j ++) { double ang = j*2*M_PI/sides; glVertex3f((GLfloat)cos(ang), (GLfloat)sin(ang), 0); } glEnd(); } #else #include class shape_window : public Fl_Window { void draw() FL_OVERRIDE; public: int sides; shape_window(int x,int y,int w,int h,const char *l=0); }; shape_window::shape_window(int x,int y,int w,int h,const char *l) : Fl_Window(x,y,w,h,l) { sides = 3; } void shape_window::draw() { fl_color(0); fl_rectf(0,0,w(),h()); fl_font(0,20); fl_color(7); fl_draw("This requires GL",0,0,w(),h(),FL_ALIGN_CENTER); } #endif class fullscreen_window : public Fl_Single_Window { public: fullscreen_window(int W, int H, const char *t=0) : Fl_Single_Window(W, H, t) {} void resize(int x, int y, int w, int h) FL_OVERRIDE; Fl_Toggle_Light_Button *border_button; Fl_Toggle_Light_Button *maximize_button; Fl_Toggle_Light_Button *fullscreen_button; Fl_Toggle_Light_Button *allscreens_button; }; void after_resize(fullscreen_window *win) { if (win->maximize_active()) win->maximize_button->set(); else win->maximize_button->clear(); win->maximize_button->redraw(); if (win->fullscreen_active()) win->fullscreen_button->set(); else win->fullscreen_button->clear(); win->fullscreen_button->redraw(); } void fullscreen_window::resize(int x, int y, int w, int h) { Fl_Single_Window::resize(x,y,w,h); Fl::add_timeout(0, (Fl_Timeout_Handler)after_resize, this); } void sides_cb(Fl_Widget *o, void *p) { shape_window *sw = (shape_window *)p; sw->sides = int(((Fl_Slider *)o)->value()); sw->redraw(); } #if HAVE_GL void double_cb(Fl_Widget *o, void *p) { shape_window *sw = (shape_window *)p; int d = ((Fl_Button *)o)->value(); sw->mode(d ? Fl_Mode(FL_DOUBLE|FL_RGB) : FL_RGB); } #else void double_cb(Fl_Widget *, void *) {} #endif void border_cb(Fl_Button *b, Fl_Window *w) { int d = b->value(); w->border(d); // border change may have been refused (e.g. with fullscreen window) if ((int)w->border() != d) b->value(w->border()); } void maximize_cb(Fl_Button *b, Fl_Window *w) { if (w->fullscreen_active()) { b->value(1 - b->value()); return; } if (w->maximize_active()) { w->un_maximize(); } else { w->maximize(); } } void fullscreen_cb(Fl_Button *b, Fl_Window *w) { if (w->maximize_active()) { b->value(1 - b->value()); return; } if (b->value()) { w->fullscreen(); } else { w->fullscreen_off(); } } void allscreens_cb(Fl_Widget *o, void *p) { Fl_Window *w = (Fl_Window *)p; int d = ((Fl_Button *)o)->value(); if (d) { int top, bottom, left, right; int top_y, bottom_y, left_x, right_x; int sx, sy, sw, sh; top = bottom = left = right = 0; Fl::screen_xywh(sx, sy, sw, sh, 0); top_y = sy; bottom_y = sy + sh; left_x = sx; right_x = sx + sw; for (int i = 1;i < Fl::screen_count();i++) { Fl::screen_xywh(sx, sy, sw, sh, i); if (sy < top_y) { top = i; top_y = sy; } if ((sy + sh) > bottom_y) { bottom = i; bottom_y = sy + sh; } if (sx < left_x) { left = i; left_x = sx; } if ((sx + sw) > right_x) { right = i; right_x = sx + sw; } } w->fullscreen_screens(top, bottom, left, right); } else { w->fullscreen_screens(-1, -1, -1, -1); } } void update_screeninfo(Fl_Widget *b, void *p) { Fl_Browser *browser = (Fl_Browser *)p; int x, y, w, h; char line[128]; browser->clear(); snprintf(line, sizeof(line), "Main screen work area: %dx%d@%d,%d", Fl::w(), Fl::h(), Fl::x(), Fl::y()); browser->add(line); Fl::screen_work_area(x, y, w, h); snprintf(line, sizeof(line), "Mouse screen work area: %dx%d@%d,%d", w, h, x, y); browser->add(line); for (int n = 0; n < Fl::screen_count(); n++) { int x, y, w, h; float dpih, dpiv; Fl::screen_xywh(x, y, w, h, n); Fl::screen_dpi(dpih, dpiv, n); snprintf(line, sizeof(line), "Screen %d: %dx%d@%d,%d DPI:%.1fx%.1f scale:%.2f", n, w, h, x, y, dpih, dpiv, Fl::screen_scale(n)); browser->add(line); Fl::screen_work_area(x, y, w, h, n); snprintf(line, sizeof(line), "Work area %d: %dx%d@%d,%d", n, w, h, x, y); browser->add(line); } } #include void exit_cb(Fl_Widget *, void *) { exit(0); } #define NUMB 9 int twowindow = 0; int initfull = 0; int arg(int, char **argv, int &i) { if (argv[i][1] == '2') {twowindow = 1; i++; return 1;} if (argv[i][1] == 'f') {initfull = 1; i++; return 1;} return 0; } int main(int argc, char **argv) { Fl::use_high_res_GL(1); int i=0; if (Fl::args(argc,argv,i,arg) < argc) Fl::fatal("Options are:\n -2 = 2 windows\n -f = startup fullscreen\n%s",Fl::help); fullscreen_window window(460,400+30*NUMB); window.end(); shape_window sw(10,10,window.w()-20,window.h()-30*NUMB-120); sw.set_visible(); // necessary because sw is not a child of window #if HAVE_GL sw.mode(FL_RGB); #endif Fl_Window *w; if (twowindow) { // make its own window sw.resizable(&sw); w = &sw; window.set_modal(); // makes controls stay on top when fullscreen pushed argc--; sw.show(); } else { // otherwise make a subwindow window.add(sw); window.resizable(&sw); w = &window; } window.begin(); int y = window.h()-30*NUMB-105; Fl_Hor_Slider slider(50,y,window.w()-60,30,"Sides:"); slider.align(FL_ALIGN_LEFT); slider.callback(sides_cb,&sw); slider.value(sw.sides); slider.step(1); slider.bounds(3,40); y+=30; Fl_Toggle_Light_Button b1(50,y,window.w()-60,30,"Double Buffered"); b1.callback(double_cb,&sw); y+=30; Fl_Input i1(50,y,window.w()-60,30, "Input"); y+=30; window.border_button = new Fl_Toggle_Light_Button(50,y,window.w()-60,30,"Border"); window.border_button->callback((Fl_Callback*)border_cb,w); window.border_button->set(); y+=30; window.fullscreen_button = new Fl_Toggle_Light_Button(50,y,window.w()-60,30,"FullScreen"); window.fullscreen_button->callback((Fl_Callback*)fullscreen_cb,w); y+=30; window.maximize_button = new Fl_Toggle_Light_Button(50,y,window.w()-60,30,"Maximize"); window.maximize_button->callback((Fl_Callback*)maximize_cb,w); y+=30; window.allscreens_button = new Fl_Toggle_Light_Button(50,y,window.w()-60,30,"All Screens"); window.allscreens_button->callback(allscreens_cb,w); y+=30; Fl_Button eb(50,y,window.w()-60,30,"Exit"); eb.callback(exit_cb); y+=30; Fl_Browser *browser = new Fl_Browser(50,y,window.w()-60,100); update_screeninfo(0, browser); y+=100; Fl_Button update(50,y,window.w()-60,30,"Update"); update.callback(update_screeninfo, browser); y+=30; if (initfull) {window.fullscreen_button->set(); window.fullscreen_button->do_callback();} window.end(); window.show(argc,argv); return Fl::run(); } fltk-1.4.3/test/trackball.h0000644000175000017500000000625415004135251015703 0ustar albrechtalbrecht/* * (c) Copyright 1993, 1994, Silicon Graphics, Inc. * ALL RIGHTS RESERVED * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the above * copyright notice appear in all copies and that both the copyright notice * and this permission notice appear in supporting documentation, and that * the name of Silicon Graphics, Inc. not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. * * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. * * US Government Users Restricted Rights * Use, duplication, or disclosure by the Government is subject to * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph * (c)(1)(ii) of the Rights in Technical Data and Computer Software * clause at DFARS 252.227-7013 and/or in similar or successor * clauses in the FAR or the DOD or NASA FAR Supplement. * Unpublished-- rights reserved under the copyright laws of the * United States. Contractor/manufacturer is Silicon Graphics, * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. * * OpenGL(TM) is a trademark of Silicon Graphics, Inc. */ /* * trackball.h * A virtual trackball implementation * Written by Gavin Bell for Silicon Graphics, November 1988. */ /* * Pass the x and y coordinates of the last and current positions of * the mouse, scaled so they are from (-1.0 ... 1.0). * * The resulting rotation is returned as a quaternion rotation in the * first paramater. */ void trackball(float q[4], float p1x, float p1y, float p2x, float p2y); /* * Given two quaternions, add them together to get a third quaternion. * Adding quaternions to get a compound rotation is analagous to adding * translations to get a compound translation. When incrementally * adding rotations, the first argument here should be the new * rotation, the second and third the total rotation (which will be * over-written with the resulting new total rotation). */ void add_quats(float *q1, float *q2, float *dest); /* * A useful function, builds a rotation matrix in Matrix based on * given quaternion. */ void build_rotmatrix(float m[4][4], float q[4]); /* * This function computes a quaternion based on an axis (defined by * the given vector) and an angle about which to rotate. The angle is * expressed in radians. The result is put into the third argument. */ void axis_to_quat(float a[3], float phi, float q[4]); fltk-1.4.3/test/unittest_circles.cxx0000644000175000017500000001512215004135251017674 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include #include #include #include #if HAVE_GL #include #endif // // --- test drawing circles and arcs ------ // void arc(int xi, int yi, int w, int h, double a1, double a2) { if (a2<=a1) return; double rx = w/2.0; double ry = h/2.0; double x = xi + rx + 0.5; double y = yi + ry + 0.5; double circ = M_PI*0.5*(rx+ry); int i, segs = int(circ * (a2-a1) / 100); if (segs<3) segs = 3; a1 = a1/180*M_PI; a2 = a2/180*M_PI; double step = (a2-a1)/segs; int nx = int(x + cos(a1)*rx); int ny = int(y - sin(a1)*ry); fl_point(nx, ny); for (i=segs; i>0; i--) { a1 += step; nx = int(x + cos(a1)*rx); ny = int(y - sin(a1)*ry); fl_point(nx, ny); } } void draw_circles() { int a = 0, b = 0, w=40, h=40; // ---- 1: draw a circle and a filled circle fl_color(FL_RED); arc(a+1, b+1, w-2, h-2, 0.0, 360.0); fl_color(FL_GREEN); arc(a, b, w, h, 0.0, 360.0); arc(a+2, b+2, w-4, h-4, 0.0, 360.0); fl_color(FL_BLACK); fl_arc(a+1, b+1, w-1, h-1, 0.0, 360.0); // ---- fl_color(FL_RED); arc(a+1+50, b+1, w-2, h-2, 0.0, 360.0); fl_color(FL_GREEN); arc(a+50, b, w, h, 0.0, 360.0); fl_color(FL_BLACK); fl_pie(a+1+50, b+1, w-1, h-1, 0.0, 360.0); b+=44; // ---- 2: draw arcs and pies fl_color(FL_RED); // arc(a-5, b-5, w+10, h+10, 45.0, 315.0); arc(a+1, b+1, w-2, h-2, 45.0, 315.0); // arc(a+5, b+5, w-10, h-10, 45.0, 315.0); // arc(a+10, b+10, w-20, h-20, 45.0, 315.0); fl_color(FL_GREEN); arc(a, b, w, h, 45.0, 315.0); arc(a+2, b+2, w-4, h-4, 45.0, 315.0); fl_color(FL_BLACK); // fl_arc(a-5, b-5, w+10, h+10, 45.0, 315.0); fl_arc(a+1, b+1, w-1, h-1, 45.0, 315.0); // fl_arc(a+5, b+5, w-10, h-10, 45.0, 315.0); // fl_arc(a+10, b+10, w-20, h-20, 45.0, 315.0); fl_color(FL_RED); // ---- arc(a+1+50, b+1, w-2, h-2, 45.0, 315.0); fl_line(a+50+20, b+20, a+50+20+14, b+20-14); fl_line(a+50+20, b+20, a+50+20+14, b+20+14); fl_color(FL_GREEN); arc(a+50, b, w, h, 45.0, 315.0); fl_line(a+50+21, b+20, a+50+21+14, b+20-14); fl_line(a+50+21, b+20, a+50+21+14, b+20+14); fl_color(FL_BLACK); fl_pie(a+1+50, b+1, w-1, h-1, 45.0, 315.0); } #if HAVE_GL class Ut_GL_Circle_Test : public Fl_Gl_Window { public: Ut_GL_Circle_Test(int x, int y, int w, int h) : Fl_Gl_Window(x, y, w, h) { box(FL_FLAT_BOX); } void draw() FL_OVERRIDE { draw_begin(); Fl_Window::draw(); draw_circles(); draw_end(); } }; #endif class Ut_Native_Circle_Test : public Fl_Window { public: Ut_Native_Circle_Test(int x, int y, int w, int h) : Fl_Window(x, y, w, h) { box(FL_FLAT_BOX); end(); } void draw() FL_OVERRIDE { Fl_Window::draw(); draw_circles(); } }; // //------- test the circle drawing capabilities of this implementation ---------- // class Ut_Circle_Test : public Fl_Group { public: static Fl_Widget *create() { return new Ut_Circle_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } Ut_Circle_Test(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { label("Testing fast circle, arc, and pie drawing\n\n" "No red lines should be visible. " "The green outlines should not be overwritten by circle drawings."); align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_WRAP); box(FL_BORDER_BOX); int a = x+16, b = y+34; Fl_Box* t = new Fl_Box(a, b-24, 80, 18, "native"); t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); /* NativeCircleTest *nr = */ new Ut_Native_Circle_Test(a+23, b-1, 200, 200); t = new Fl_Box(a, b, 18, 18, "1"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing circle alignment.\n\n" // Description: "This draws a black circle and a black disc, surrounded by a green frame.\n\n" // Things to look out for: "If green pixels are missing, circle drawing must be adjusted (see fl_arc, fl_pie).\n\n" "If red pixels are showing, line width or aligment may be off." ); b+=44; t = new Fl_Box(a, b, 18, 18, "2"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing arc and pie drawing.\n\n" // Description: "This draws a black frame, surrounded on the inside and outside by a green frame.\n\n" // Things to look out for: "If green pixels are missing or red pixels are showing, rectangular frame drawing schould be adjusted (see fl_rect).\n\n" "If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted." ); #if HAVE_GL a = x+16+250, b = y+34; t = new Fl_Box(a, b-24, 80, 18, "OpenGL"); t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); /* GLCircleTest *glr = */ new Ut_GL_Circle_Test(a+31, b-1, 200, 200); t = new Fl_Box(a, b, 26, 18, "1a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing circle alignment.\n\n" // Description: "This draws a black circle and a black disc, surrounded by a green frame.\n\n" // Things to look out for: "If green pixels are missing, circle drawing must be adjusted (see fl_arc, fl_pie).\n\n" "If red pixels are showing, line width or aligment may be off." ); b+=44; t = new Fl_Box(a, b, 26, 18, "2a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing arc and pie drawing.\n\n" // Description: "This draws a black frame, surrounded on the inside and outside by a green frame.\n\n" // Things to look out for: "If green pixels are missing or red pixels are showing, rectangular frame drawing schould be adjusted (see fl_rect).\n\n" "If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted." ); #endif t = new Fl_Box(x+w-1,y+h-1, 1, 1); resizable(t); } }; UnitTest circle(UT_TEST_CIRCLES, "Circles and Arcs", Ut_Circle_Test::create); fltk-1.4.3/test/unittest_terminal.cxx0000644000175000017500000001042215004135251020061 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include #include #include // //------- test the Fl_Terminal drawing capabilities ---------- // class Ut_Terminal_Test : public Fl_Group { Fl_Terminal *tty1; Fl_Terminal *tty2; void ansi_test_pattern(Fl_Terminal *tty) { tty->append("\033[30mBlack Courier 14\033[0m Normal text\n" "\033[31mRed Courier 14\033[0m Normal text\n" "\033[32mGreen Courier 14\033[0m Normal text\n" "\033[33mYellow Courier 14\033[0m Normal text\n" "\033[34mBlue Courier 14\033[0m Normal text\n" "\033[35mMagenta Courier 14\033[0m Normal text\n" "\033[36mCyan Courier 14\033[0m Normal text\n" "\033[37mWhite Courier 14\033[0m Normal text\n" "\033[1;30mBright Black Courier 14\033[0m Normal text\n" "\033[1;31mBright Red Courier 14\033[0m Normal text\n" "\033[1;32mBright Green Courier 14\033[0m Normal text\n" "\033[1;33mBright Yellow Courier 14\033[0m Normal text\n" "\033[1;34mBright Blue Courier 14\033[0m Normal text\n" "\033[1;35mBright Magenta Courier 14\033[0m Normal text\n" "\033[1;36mBright Cyan Courier 14\033[0m Normal text\n" "\033[1;37mBright White Courier 14\033[0m Normal text\n" "\n" "\033[31mRed\033[32mGreen\033[33mYellow\033[34mBlue\033[35mMagenta\033[36mCyan\033[37mWhite\033[0m - " "\033[31mX\033[32mX\033[33mX\033[34mX\033[35mX\033[36mX\033[37mX\033[0m\n" "\033[1;31mRed\033[1;32mGreen\033[1;33mYellow\033[34mBlue\033[35mMagenta\033[36mCyan\033[1;37mWhite\033[1;0m - " "\033[1;31mX\033[1;32mX\033[1;33mX\033[1;34mX\033[1;35mX\033[1;36mX\033[1;37mX\033[0m\n"); } void gray_test_pattern(Fl_Terminal *tty) { tty->append("Grayscale Test Pattern\n" "--------------------------\n" "\033[38;2;255;255;255m 100% white Courier 14\n" // ESC xterm codes for setting r;g;b colors "\033[38;2;230;230;230m 90% white Courier 14\n" "\033[38;2;205;205;205m 80% white Courier 14\n" "\033[38;2;179;179;179m 70% white Courier 14\n" "\033[38;2;154;154;154m 60% white Courier 14\n" "\033[38;2;128;128;128m 50% white Courier 14\n" "\033[38;2;102;102;102m 40% white Courier 14\n" "\033[38;2;77;77;77m" " 30% white Courier 14\n" "\033[38;2;51;51;51m" " 20% white Courier 14\n" "\033[38;2;26;26;26m" " 10% white Courier 14\n" "\033[38;2;0;0;0m" " 0% white Courier 14\n" "\033[0m"); } static void date_timer_cb(void *data) { Fl_Terminal *tty = (Fl_Terminal*)data; time_t lt = time(NULL); tty->printf("The time and date is now: %s", ctime(<)); Fl::repeat_timeout(3.0, date_timer_cb, data); } public: static Fl_Widget *create() { return new Ut_Terminal_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } Ut_Terminal_Test(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { int tty_h = (int)(h/2.25+.5); int tty_y1 = y+(tty_h*0)+20; int tty_y2 = y+(tty_h*1)+40; // TTY1 tty1 = new Fl_Terminal(x, tty_y1, w, tty_h,"Tty 1: Colors"); ansi_test_pattern(tty1); Fl::add_timeout(0.5, date_timer_cb, (void*)tty1); // TTY2 tty2 = new Fl_Terminal(x, tty_y2, w, tty_h,"Tty 2: Grayscale"); gray_test_pattern(tty2); Fl::add_timeout(0.5, date_timer_cb, (void*)tty2); end(); } }; UnitTest simple_terminal(UT_TEST_SIMPLE_TERMINAL, "Terminal", Ut_Terminal_Test::create); fltk-1.4.3/test/icon.cxx0000644000175000017500000000347415004135251015250 0ustar albrechtalbrecht// // Window icon test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include static Fl_Double_Window *win; void choice_cb(Fl_Widget *, void *v) { Fl_Color c = (Fl_Color)fl_uint(v); if ( c != 0 ) { // choice was "Red", "Green".. static uchar buffer[32*32*3]; // static: issue #296 Fl_RGB_Image rgbicon(buffer, 32, 32, 3); rgbicon.color_average(c, 0.0); win->icon(&rgbicon); // once assigned, 'rgbicon' can go out of scope } else { // choice was "None".. win->icon((Fl_RGB_Image*)0); // reset window icon } } Fl_Menu_Item choices[] = { {"None", 0, choice_cb, fl_voidptr(0)}, {"Red", 0, choice_cb, fl_voidptr(FL_RED)}, {"Green", 0, choice_cb, fl_voidptr(FL_GREEN)}, {"Blue", 0, choice_cb, fl_voidptr(FL_BLUE)}, {0} }; int main(int argc, char **argv) { Fl_Double_Window window(400,300, "FLTK Window Icon Test"); win = &window; Fl_Choice choice(120,100,200,25,"Window icon:"); choice.menu(choices); choice.callback(choice_cb); choice.when(FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED); choice.tooltip("Sets the application icon for window manager. " "Affects e.g. titlebar, toolbar, Dock, Alt-Tab.."); window.end(); window.show(argc,argv); choice.do_callback(); // make default take effect return Fl::run(); } fltk-1.4.3/test/unittest_schemes.cxx0000644000175000017500000003117415004135251017704 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // Nods to Edmanuel Torres for the widget layout (STR#2672) // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include // needed by Edmanuel's test layout #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class Ut_Schemes_Test : public Fl_Group { Fl_Scheme_Choice *scheme_choice_; static void activate_subwin(Fl_Widget *w, void *data) { Fl_Window *win = (Fl_Window *)data; Fl_Light_Button *b = (Fl_Light_Button *)w; int active = b->value(); if (active) b->label("active"); else b->label("inactive"); // Documentation of deactivate() states: "Currently you cannot deactivate Fl_Window widgets". // However, it seems to work in this case. AlbrechtS, FLTK 1.4, July 2022 #if (1) if (active) win->activate(); else win->deactivate(); #else // alternative: deactivate all widgets (works definitely) for (int i = 0; i < win->children(); i++) { Fl_Widget *o = win->child(i); if (active) o->activate(); else o->deactivate(); } #endif } // activate_subwin() public: static Fl_Widget *create() { return new Ut_Schemes_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } Ut_Schemes_Test(int X,int Y,int W,int H) : Fl_Group(X,Y,W,H) { scheme_choice_ = new Fl_Scheme_Choice(X+125,Y,140,25,"FLTK Scheme"); scheme_choice_->labelfont(FL_HELVETICA_BOLD); Fl_Light_Button *active = new Fl_Light_Button(X + 300, Y, 100, 25, "active"); active->value(1); active->selection_color(FL_RED); active->align(FL_ALIGN_CENTER); Fl_Window *subwin = new Fl_Window(X,Y+30,W,H-30); active->callback(activate_subwin, subwin); subwin->begin(); { // Pasted from Edmanuel's gleam test app { Fl_Button* o = new Fl_Button(10, 9, 90, 25, "button"); o->box(FL_UP_BOX); o->color((Fl_Color)101); o->tooltip("selection_color() = default"); o->labelfont(5); } // Fl_Button* o { Fl_Button* o = new Fl_Button(10, 36, 90, 25, "button"); o->box(FL_UP_BOX); o->color((Fl_Color)179); o->selection_color(o->color()); o->tooltip("selection_color() = color()"); o->labelfont(4); o->labelcolor(FL_BACKGROUND2_COLOR); } // Fl_Button* o { Fl_Button* o = new Fl_Button(10, 63, 90, 25, "button"); o->box(FL_UP_BOX); o->color((Fl_Color)91); o->selection_color(fl_lighter(o->color())); o->tooltip("selection_color() = fl_lighter(color())"); } // Fl_Button* o { Fl_Button* o = new Fl_Button(10, 90, 90, 25, "button"); o->box(FL_UP_BOX); o->color(FL_INACTIVE_COLOR); o->selection_color(fl_darker(o->color())); o->tooltip("selection_color() = fl_darker(color())"); o->labelcolor(FL_BACKGROUND2_COLOR); } // Fl_Button* o { Fl_Tabs* o = new Fl_Tabs(10, 120, 320, 215); o->color(FL_DARK1); o->selection_color(FL_DARK1); { Fl_Group* o = new Fl_Group(14, 141, 310, 190, "tab1"); //o->box(FL_THIN_UP_BOX); o->color(FL_DARK1); o->selection_color((Fl_Color)23); o->hide(); { Fl_Clock* o = new Fl_Clock(24, 166, 130, 130); o->box(FL_THIN_UP_BOX); o->color((Fl_Color)12); o->selection_color(FL_BACKGROUND2_COLOR); o->labelcolor(FL_BACKGROUND2_COLOR); o->tooltip("Fl_Clock with thin up box"); } // Fl_Clock* o { new Fl_Progress(22, 306, 290, 20); } // Fl_Progress* o { Fl_Clock* o = new Fl_Clock(179, 166, 130, 130); o->box(FL_THIN_DOWN_BOX); o->color((Fl_Color)26); o->tooltip("Fl_Clock with thin down box"); } // Fl_Clock* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(15, 140, 310, 190, "tab2"); //o->box(FL_THIN_UP_BOX); o->color(FL_DARK1); { Fl_Slider* o = new Fl_Slider(20, 161, 25, 155); o->box(FL_DOWN_BOX); o->tooltip("Fl_Slider with down box"); } // Fl_Slider* o { Fl_Scrollbar* o = new Fl_Scrollbar(50, 161, 25, 155); o->value(0, 50, 1, 100); o->box(FL_DOWN_BOX); o->tooltip("Fl_Scrollbar with down box"); } // Fl_Scrollbar* o { Fl_Value_Slider* o = new Fl_Value_Slider(115, 161, 25, 155); o->box(FL_DOWN_BOX); } // Fl_Value_Slider* o { Fl_Value_Output* o = new Fl_Value_Output(240, 265, 75, 25); o->box(FL_DOWN_BOX); o->tooltip("Fl_Value_Output with down box"); } // Fl_Value_Output* o { Fl_Adjuster* o = new Fl_Adjuster(185, 210, 100, 25); o->tooltip("Fl_Adjuster"); } // Fl_Adjuster* o { Fl_Counter* o = new Fl_Counter(185, 180, 100, 25); o->box(FL_DOWN_BOX); o->tooltip("Fl_Counter with down box"); } // Fl_Counter* o { Fl_Roller* o = new Fl_Roller(85, 161, 25, 155); o->box(FL_UP_BOX); o->tooltip("Fl_Roller with up box"); } // Fl_Roller* o { Fl_Value_Input* o = new Fl_Value_Input(155, 265, 75, 25); o->box(FL_DOWN_BOX); o->tooltip("Fl_Value_Input with down box"); } // Fl_Value_Input* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(15, 140, 310, 190, "tab3"); //o->box(FL_THIN_UP_BOX); o->color(FL_DARK1); o->hide(); { Fl_Input* o = new Fl_Input(40, 230, 120, 25); o->box(FL_DOWN_BOX); o->tooltip("Fl_Input with down box"); } // Fl_Input* o { Fl_Output* o = new Fl_Output(40, 260, 120, 25); o->box(FL_DOWN_BOX); o->tooltip("Fl_Output with down box"); } // Fl_Output* o { Fl_Text_Editor* o = new Fl_Text_Editor(180, 160, 125, 55); o->box(FL_DOWN_FRAME); o->color((Fl_Color)80); o->tooltip("Fl_Text_Editor with down frame"); o->textsize(8); o->buffer(new Fl_Text_Buffer()); o->buffer()->text("Text editor"); } // Fl_Text_Editor* o { Fl_Text_Display* o = new Fl_Text_Display(180, 230, 125, 55); o->box(FL_DOWN_FRAME); o->color((Fl_Color)12); o->tooltip("Fl_Text_Display with down frame"); o->textsize(8); o->buffer(new Fl_Text_Buffer()); o->buffer()->text("Text display"); } // Fl_Text_Display* o { Fl_File_Input* o = new Fl_File_Input(40, 290, 265, 30); o->box(FL_DOWN_BOX); o->tooltip("Fl_File_Input with down box"); } // Fl_File_Input* o o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(15, 140, 310, 190, "tab4"); // o->box(FL_THIN_UP_BOX); o->color(FL_DARK1); o->hide(); { Fl_Radio_Round_Button* o = new Fl_Radio_Round_Button(40, 160, 120, 25, "Choice 1"); o->tooltip("Fl_Radio_Round_Button (default)"); // don't set selection color (use default selection color) o->value(1); // selected } // Fl_Radio_Round_Button* o { Fl_Radio_Round_Button* o = new Fl_Radio_Round_Button(40, 190, 120, 25, "Choice 2"); o->tooltip("Fl_Radio_Round_Button (red)"); o->selection_color(FL_RED); } // Fl_Radio_Round_Button* o { Fl_Radio_Round_Button* o = new Fl_Radio_Round_Button(40, 220, 120, 25, "Choice 3"); o->tooltip("Fl_Radio_Round_Button (green)"); o->selection_color(fl_darker(FL_GREEN)); } // Fl_Radio_Round_Button* o { Fl_Radio_Round_Button* o = new Fl_Radio_Round_Button(40, 250, 120, 25, "Choice 4"); o->tooltip("Fl_Radio_Round_Button (blue)"); o->selection_color(FL_BLUE); } // Fl_Radio_Round_Button* o o->end(); } // Fl_Group* o o->end(); } // Fl_Tabs* o { Fl_Box* o = new Fl_Box(341, 10, 80, 50, "thin box\ndown1"); o->box(FL_THIN_DOWN_BOX); o->color((Fl_Color)20); o->labelsize(10); } // Fl_Box* o { Fl_Box* o = new Fl_Box(430, 10, 80, 50, "thin box\nup1"); o->box(FL_THIN_UP_BOX); o->color(FL_SELECTION_COLOR); o->labelcolor((Fl_Color)6); o->labelsize(10); } // Fl_Box* o { Fl_Box* o = new Fl_Box(341, 71, 80, 44, "thin box\ndown2"); o->box(FL_THIN_DOWN_BOX); o->color((Fl_Color)190); o->labelsize(10); } // Fl_Box* o { Fl_Box* o = new Fl_Box(430, 71, 80, 44, "thin box\nup2"); o->box(FL_THIN_UP_BOX); o->color((Fl_Color)96); o->labelcolor(FL_BACKGROUND2_COLOR); o->labelsize(10); } // Fl_Box* o { Fl_Box* o = new Fl_Box(341, 127, 80, 50, "box down3"); o->box(FL_DOWN_BOX); o->color((Fl_Color)3); o->labelsize(10); } // Fl_Box* o { Fl_Box* o = new Fl_Box(430, 127, 80, 50, "box up3"); o->box(FL_UP_BOX); o->color((Fl_Color)104); o->labelcolor((Fl_Color)3); o->labelsize(10); } // Fl_Box* o { Fl_Box* o = new Fl_Box(341, 189, 80, 50, "box down4"); o->box(FL_DOWN_BOX); o->color((Fl_Color)42); o->labelcolor(FL_DARK_RED); o->labelsize(10); } // Fl_Box* o { Fl_Box* o = new Fl_Box(430, 189, 80, 50, "box up4"); o->box(FL_UP_BOX); o->color((Fl_Color)30); o->labelcolor((Fl_Color)26); o->labelsize(10); } // Fl_Box* o { Fl_Box* o = new Fl_Box(341, 251, 80, 82, "box down5"); o->box(FL_DOWN_BOX); o->color((Fl_Color)19); o->labelcolor((Fl_Color)4); o->labelsize(10); } // Fl_Box* o { Fl_Box* o = new Fl_Box(430, 251, 80, 82, "box up5"); o->box(FL_UP_BOX); o->color(FL_FOREGROUND_COLOR); o->labelcolor(FL_BACKGROUND2_COLOR); o->labelsize(10); } // Fl_Box* o { Fl_Light_Button* o = new Fl_Light_Button(110, 10, 105, 25, "Light"); o->box(FL_DOWN_BOX); o->color(FL_BACKGROUND2_COLOR); o->selection_color((Fl_Color)30); o->selection_color((Fl_Color)FL_RED); o->tooltip("Fl_Light_Button with down box"); } // Fl_Light_Button* o { Fl_Check_Button* o = new Fl_Check_Button(110, 37, 105, 25, "Check"); o->box(FL_DOWN_FRAME); o->down_box(FL_DOWN_BOX); o->color(FL_DARK1); o->selection_color(fl_darker(FL_GREEN)); o->tooltip("Fl_Check_Button with down frame"); } // Fl_Check_Button* o { Fl_Input* o = new Fl_Input(220, 10, 100, 25); o->box(FL_DOWN_BOX); o->color((Fl_Color)23); o->tooltip("Fl_Input with down box"); } // Fl_Input* o { Fl_Adjuster* o = new Fl_Adjuster(110, 65, 80, 43); o->box(FL_UP_BOX); o->color(FL_INACTIVE_COLOR); o->selection_color(FL_BACKGROUND2_COLOR); o->labelcolor((Fl_Color)55); o->tooltip("Fl_Adjuster with up box"); } // Fl_Adjuster* o { Fl_Text_Editor* o = new Fl_Text_Editor(220, 40, 100, 25); o->box(FL_DOWN_FRAME); o->color((Fl_Color)19); o->selection_color(FL_DARK1); o->buffer(new Fl_Text_Buffer); o->tooltip("Fl_Text_Editor with down frame"); } // Fl_Text_Editor* o { Fl_Text_Editor* o = new Fl_Text_Editor(220, 70, 100, 25); o->box(FL_UP_FRAME); o->color((Fl_Color)19); o->selection_color(FL_DARK1); o->buffer(new Fl_Text_Buffer); o->tooltip("Fl_Text_Editor with up frame"); } // Fl_Text_Editor* o } subwin->end(); subwin->resizable(subwin); subwin->show(); } }; UnitTest schemestest(UT_TEST_SCHEMES, "Schemes Test", Ut_Schemes_Test::create); fltk-1.4.3/test/unittest_text.cxx0000644000175000017500000000736715004135251017250 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include #include #include // // --- fl_text_extents() tests ----------------------------------------------- static void cb_base_bt(Fl_Widget *bt, void*) { bt->parent()->redraw(); } // class Ut_Text_Extents_Test : public Fl_Group { Fl_Check_Button *base_bt; void draw_text_and_boxes(const char *txt, int X, int Y) { int wm = 0, hm = 0, wt = 0, ht = 0; int dx, dy; // measure text so we can draw the baseline first fl_measure(txt, wm, hm, 0); fl_text_extents(txt, dx, dy, wt, ht); // Draw a baseline before the boxes if (base_bt->value()) { fl_color(FL_BLUE); fl_line((X - 20), Y, (X + wt + 20), Y); } // Then we draw the bounding boxes (fl_measure and fl_text_extents) // draw fl_measure() typographical bounding box int desc = fl_descent(); fl_color(FL_RED); fl_rect(X, Y-hm+desc, wm, hm); // draw fl_text_extents() glyph bounding box fl_color(FL_GREEN); fl_rect(X+dx, Y+dy, wt, ht); // Then we draw the text to show how it fits inside each of the two boxes fl_color(FL_BLACK); fl_draw(txt, X, Y); } public: static Fl_Widget *create() { return new Ut_Text_Extents_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } Ut_Text_Extents_Test(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { base_bt = new Fl_Check_Button(x + w - 150, 50, 130, 20, "Show Baseline"); base_bt->box(FL_FLAT_BOX); base_bt->down_box(FL_DOWN_BOX); base_bt->callback(cb_base_bt); Fl_Box *dummy = new Fl_Box ((x + w - 4), (y + h - 4), 2, 2); resizable(dummy); end(); } void draw(void) FL_OVERRIDE { int x0 = x(); // origin is current window position for Fl_Box int y0 = y(); int w0 = w(); int h0 = h(); fl_push_clip(x0, y0, w0, h0); // reset local clipping { // set the background colour - slightly off-white to enhance the green bounding box fl_color(fl_gray_ramp(FL_NUM_GRAY - 3)); fl_rectf(x0, y0, w0, h0); Fl_Group::draw(); fl_font(FL_HELVETICA, 30); int xx = x0+55; int yy = y0+40; draw_text_and_boxes("!abcdeABCDE\"#A", xx, yy); yy += 50; // mixed string draw_text_and_boxes("oacs", xx, yy); xx += 100; // small glyphs draw_text_and_boxes("qjgIPT", xx, yy); yy += 50; xx -= 100; // glyphs with descenders draw_text_and_boxes("````````", xx, yy); yy += 50; // high small glyphs draw_text_and_boxes("--------", xx, yy); yy += 50; // mid small glyphs draw_text_and_boxes("________", xx, yy); yy += 50; // low small glyphs fl_font(FL_HELVETICA, 14); fl_color(FL_RED); fl_draw("fl_measure bounding box in RED", xx, yy); yy += 20; fl_color(FL_GREEN); fl_draw("fl_text_extents bounding box in GREEN", xx, yy); fl_color(FL_BLACK); xx = x0 + 10; yy += 30; fl_draw("NOTE: On systems with text anti-aliasing (e.g. macOS Quartz)", xx, yy); w0 = h0 = 0; fl_measure("NOTE: ", w0, h0, 0); xx += w0; yy += h0; fl_draw("text may leak slightly outside the fl_text_extents()", xx, yy); } fl_pop_clip(); // remove the local clip } }; UnitTest textExtents(UT_TEST_TEXT, "Rendering Text", Ut_Text_Extents_Test::create); fltk-1.4.3/test/rotated_text.cxx0000644000175000017500000001304015004135251017014 0ustar albrechtalbrecht// // Label test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #ifndef M_PI #define M_PI 3.141592654 #endif Fl_Toggle_Button *leftb,*rightb,*clipb; //Fl_Box *text; Fl_Input *input; Fl_Hor_Value_Slider *fonts; Fl_Hor_Value_Slider *sizes; Fl_Hor_Value_Slider *angles; Fl_Double_Window *window; //code taken from fl_engraved_label.cxx class Rotated_Label_Box : public Fl_Widget{ protected: void draw() FL_OVERRIDE { draw_box(); fl_font(labelfont(), labelsize()); fl_color(labelcolor()); int dx(0),dy(0); if(rt_align&FL_ALIGN_CLIP)fl_push_clip(x(),y(),w(),h()); else fl_push_no_clip(); fl_measure(rt_text,dx,dy); if(rt_align&FL_ALIGN_LEFT){ dx=dy=0; }else if(rt_align&FL_ALIGN_RIGHT){ dy=(int)(-sin(M_PI*(double)(rt_angle+180)/180.)*(double)dx); dx=(int)(cos(M_PI*(double)(rt_angle+180)/180.)*(double)dx); }else{ dy=(int)(sin(M_PI*(double)rt_angle/180.)*(double)dx); dx=(int)(-cos(M_PI*(double)rt_angle/180.)*(double)dx); dx/=2;dy/=2; } if(labeltype()==FL_SHADOW_LABEL)shadow_label(x()+w()/2+dx,y()+h()/2+dy); else if(labeltype()==FL_ENGRAVED_LABEL)engraved_label(x()+w()/2+dx,y()+h()/2+dy); else if(labeltype()==FL_EMBOSSED_LABEL)embossed_label(x()+w()/2+dx,y()+h()/2+dy); else{ fl_draw(rt_angle,rt_text,x()+w()/2+dx,y()+h()/2+dy); } fl_pop_clip(); draw_label(); } void innards(int X, int Y, int data[][3], int n){ for (int i = 0; i < n; i++) { fl_color((Fl_Color)(i < n-1 ? data[i][2] : labelcolor())); fl_draw(rt_angle,rt_text, X+data[i][0], Y+data[i][1]); } } void shadow_label(int X, int Y){ static int data[2][3] = {{2,2,FL_DARK3},{0,0,0}}; innards(X, Y, data, 2); } void engraved_label(int X, int Y){ static int data[7][3] = { {1,0,FL_LIGHT3},{1,1,FL_LIGHT3},{0,1,FL_LIGHT3}, {-1,0,FL_DARK3},{-1,-1,FL_DARK3},{0,-1,FL_DARK3}, {0,0,0}}; innards(X, Y, data, 7); } void embossed_label(int X, int Y){ static int data[7][3] = { {-1,0,FL_LIGHT3},{-1,-1,FL_LIGHT3},{0,-1,FL_LIGHT3}, {1,0,FL_DARK3},{1,1,FL_DARK3},{0,1,FL_DARK3}, {0,0,0}}; innards(X, Y, data, 7); } public: Rotated_Label_Box(int X, int Y, int W, int H, const char*L=0): Fl_Widget(X,Y,W,H,L),rt_angle(0),rt_align((Fl_Align)0) { rt_text=input->value(); } int rt_angle; const char* rt_text; Fl_Align rt_align; }*text; void button_cb(Fl_Widget *,void *) { int i = 0; if (leftb->value()) i |= FL_ALIGN_LEFT; if (rightb->value()) i |= FL_ALIGN_RIGHT; if (clipb->value()) i |= FL_ALIGN_CLIP; text->rt_align=(Fl_Align)i; window->redraw(); } void font_cb(Fl_Widget *,void *) { text->labelfont(int(fonts->value())); window->redraw(); } void size_cb(Fl_Widget *,void *) { text->labelsize(int(sizes->value())); window->redraw(); } void angle_cb(Fl_Widget *,void *) { text->rt_angle=(int)angles->value(); window->redraw(); } void input_cb(Fl_Widget *,void *) { text->rt_text=input->value(); window->redraw(); } void normal_cb(Fl_Widget *,void *) { text->labeltype(FL_NORMAL_LABEL); window->redraw(); } void shadow_cb(Fl_Widget *,void *) { text->labeltype(FL_SHADOW_LABEL); window->redraw(); } void embossed_cb(Fl_Widget *,void *) { text->labeltype(FL_EMBOSSED_LABEL); window->redraw(); } void engraved_cb(Fl_Widget *,void *) { text->labeltype(FL_ENGRAVED_LABEL); window->redraw(); } Fl_Menu_Item choices[] = { {"FL_NORMAL_LABEL",0,normal_cb}, {"FL_SHADOW_LABEL",0,shadow_cb}, {"FL_ENGRAVED_LABEL",0,engraved_cb}, {"FL_EMBOSSED_LABEL",0,embossed_cb}, {0}}; int main(int argc, char **argv) { window = new Fl_Double_Window(400,425); angles= new Fl_Hor_Value_Slider(50,400,350,25,"Angle:"); angles->align(FL_ALIGN_LEFT); angles->bounds(-360,360); angles->step(1); angles->value(0); angles->callback(angle_cb); input = new Fl_Input(50,375,350,25); input->static_value("Rotate Me!!!"); input->when(FL_WHEN_CHANGED); input->callback(input_cb); sizes= new Fl_Hor_Value_Slider(50,350,350,25,"Size:"); sizes->align(FL_ALIGN_LEFT); sizes->bounds(1,64); sizes->step(1); sizes->value(14); sizes->callback(size_cb); fonts=new Fl_Hor_Value_Slider(50,325,350,25,"Font:"); fonts->align(FL_ALIGN_LEFT); fonts->bounds(0,15); fonts->step(1); fonts->value(0); fonts->callback(font_cb); Fl_Group *g = new Fl_Group(50,300,350,25); leftb = new Fl_Toggle_Button(50,300,50,25,"left"); leftb->callback(button_cb); rightb = new Fl_Toggle_Button(100,300,50,25,"right"); rightb->callback(button_cb); clipb = new Fl_Toggle_Button(350,300,50,25,"clip"); clipb->callback(button_cb); g->resizable(rightb); g->end(); Fl_Choice *c = new Fl_Choice(50,275,200,25); c->menu(choices); text= new Rotated_Label_Box(100,75,200,100,"Widget with rotated text"); text->box(FL_FRAME_BOX); text->align(FL_ALIGN_BOTTOM); window->resizable(text); window->end(); window->show(argc,argv); return Fl::run(); } fltk-1.4.3/test/resize-example1.cxx0000644000175000017500000001064015004135251017324 0ustar albrechtalbrecht// // Resize example for use in the Fast Light Tool Kit (FLTK) documentation. // // See Article #415: How does resizing work? // https://www.fltk.org/articles.php?L415 // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "resize-arrows.h" #include Fl_Double_Window *window; // inner box dimensions int Ax = 0, Bx = 35, Cx = 70, Dx = 105, Nx = 140, Aw = 35, Rw = 70, Mw = 140; int Ay = 0, Ey = 35, Gy = 70, Iy = 105, My = 140, Ah = 35, Rh = 70, Nh = 175; // resize box and arrow group dimensions int TLx = 35, TRx = 245, TGx = 420, TLw = 175, TGw = 140, TAw = 35; int TLy = 35, BLy = 245, LGy = 420, TLh = 175, LGh = 105, LAh = 35; // window dimensions int Ww = 560, Wh = 525; class Resizebox : public Fl_Group { public: Resizebox(int X, int Y, int W, int H, const char *T); }; Resizebox::Resizebox(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->align(FL_ALIGN_TOP_LEFT); this->box(FL_UP_BOX); Fl_Box *b; b = new Fl_Box(FL_FRAME_BOX, X + Ax, Y + Ay, Aw, Ah, "A"); b->color(14); b = new Fl_Box(FL_FRAME_BOX, X + Bx, Y + Ay, Aw, Ah, "B"); b->color(9); b = new Fl_Box(FL_FRAME_BOX, X + Cx, Y + Ay, Aw, Ah, "C"); b->color(10); b = new Fl_Box(FL_FRAME_BOX, X + Dx, Y + Ay, Aw, Ah, "D"); b->color(11); b = new Fl_Box(FL_FRAME_BOX, X + Ax, Y + Ey, Aw, Ah, "E"); b->color(9); b = new Fl_Box(FL_FRAME_BOX, X + Bx, Y + Ey, Rw, Rh, " "); b->color(8); b = new Fl_Box(FL_FRAME_BOX, X + Dx, Y + Ey, Aw, Ah, "F"); b->color(12); b = new Fl_Box(FL_FRAME_BOX, X + Ax, Y + Gy, Aw, Ah, "G"); b->color(10); b = new Fl_Box(FL_FRAME_BOX, X + Dx, Y + Gy, Aw, Ah, "H"); b->color(13); b = new Fl_Box(FL_FRAME_BOX, X + Ax, Y + Iy, Aw, Ah, "I"); b->color(11); b = new Fl_Box(FL_FRAME_BOX, X + Bx, Y + Iy, Aw, Ah, "J"); b->color(12); b = new Fl_Box(FL_FRAME_BOX, X + Cx, Y + Iy, Aw, Ah, "K"); b->color(13); b = new Fl_Box(FL_FRAME_BOX, X + Dx, Y + Iy, Aw, Ah, "L"); b->color(14); b = new Fl_Box(FL_FRAME_BOX, X + Ax, Y + My, Mw, Ah, "M"); b->color(12); b = new Fl_Box(FL_FRAME_BOX, X + Nx, Y + Ay, Aw, Nh, "N"); b->color(13); this->end(); this->resizable(this); } class Resizables : public Fl_Group { public: Resizables(int X, int Y, int W, int H, const char *T = 0); Resizebox *TL, *TR, *BL, *BR; // topleft, topright, bottomleft, bottomright Harrow *LA, *RA; // left arrow, right arrow Varrow *TA, *BA; // top arrow, bottom arrow }; Resizables::Resizables(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->box(FL_UP_BOX); this->color(FL_WHITE); TL = new Resizebox(X + TLx, Y + TLy, TLw, TLh, "Original Size"); TL->resizable(0); TR = new Resizebox(X + TRx, Y + TLy, TLw, TLh, "Horizontally Resized"); BL = new Resizebox(X + TLx, Y + BLy, TLw, TLh, "Vertically Resized"); BR = new Resizebox(X + TRx, Y + BLy, TLw, TLh, "Horizontally and Vertically Resized"); Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); LG->box(FL_NO_BOX); LG->color(FL_WHITE); LA = new Harrow(LG->x(), LG->y(), LG->w(), LAh, "Initial\nwidth"); LG->resizable(LA); LG->end(); Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); RG->box(FL_NO_BOX); RG->color(FL_WHITE); RA = new Harrow(RG->x(), RG->y(), RG->w(), LAh, "Resized\nwidth"); RG->resizable(RA); RG->end(); Fl_Group *TG = new Fl_Group(X + TGx, Y + TLy, TGw, TLh); TG->box(FL_NO_BOX); TG->color(FL_WHITE); TA = new Varrow(X + TGx, Y + TLy, TAw, TLh, "Initial\nheight"); TG->resizable(TA); TG->end(); Fl_Group *BG = new Fl_Group(X + TGx, Y + BLy, TGw, TLh); BG->box(FL_NO_BOX); BG->color(FL_WHITE); BA = new Varrow(X + TGx, Y + BLy, TAw, TLh, "Resized\nheight"); BG->resizable(BA); BG->end(); this->resizable(BR); this->end(); } int main(int argc, char **argv) { window = new Fl_Double_Window(Ww, Wh, "resize-example1"); window->color(FL_WHITE); Resizables *resizables = new Resizables(0, 0, Ww, Wh); window->end(); window->resizable(resizables); window->size_range(Ww, Wh); window->show(argc, argv); window->size(Ww + 140, Wh + 35); return Fl::run(); } fltk-1.4.3/test/tiled_image.cxx0000644000175000017500000000406415004135251016557 0ustar albrechtalbrecht// // Fl_Tiled_Image test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include "pixmaps/tile.xpm" Fl_Button *b; Fl_Double_Window *w; void button_cb(Fl_Widget *,void *) { w->hide(); } #include #include "list_visuals.cxx" int visid = -1; int arg(int argc, char **argv, int &i) { if (argv[i][1] == 'v') { if (i+1 >= argc) return 0; visid = atoi(argv[i+1]); i += 2; return 2; } return 0; } int main(int argc, char **argv) { int i = 1; Fl::args(argc,argv,i,arg); #ifdef FLTK_USE_X11 if (visid >= 0) { fl_open_display(); XVisualInfo templt; int num; templt.visualid = visid; fl_visual = XGetVisualInfo(fl_display, VisualIDMask, &templt, &num); if (!fl_visual) { fprintf(stderr, "No visual with id %d, use one of:\n",visid); list_visuals(); exit(1); } fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen), fl_visual->visual, AllocNone); fl_xpixel(FL_BLACK); // make sure black is allocated in overlay visuals } else { Fl::visual(FL_RGB); } #endif Fl_Double_Window window(400,400); ::w = &window; Fl_Group group(0,0,400,400); group.image(new Fl_Tiled_Image(new Fl_Pixmap((const char * const *)tile_xpm))); group.align(FL_ALIGN_INSIDE); Fl_Button b(340,365,50,25,"Close"); ::b = &b; b.callback(button_cb); group.end(); window.resizable(group); window.end(); window.show(argc, argv); return Fl::run(); } fltk-1.4.3/test/help_dialog.cxx0000644000175000017500000000335615004135251016566 0ustar albrechtalbrecht// // Fl_Help_Dialog test program. // // Copyright 1999-2010 by Easy Software Products. // Copyright 2011-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // main() - Display the help GUI... // // // Include necessary headers... // #include #include #include /* FL_PATH_MAX */ #include /* Fl::first_window(), etc */ #include /* strcpy(), etc */ static void cb_refresh(void *d) { // trigger a redraw of the window to see animated GIF's if (Fl::first_window()) Fl::first_window()->redraw(); Fl::repeat_timeout(1./10, cb_refresh, d); } // // 'main()' - Display the help GUI... // int // O - Exit status main(int argc, // I - Number of command-line arguments char *argv[]) // I - Command-line arguments { Fl_GIF_Image::animate = true; // create animated shared .GIF images Fl_Help_Dialog *help = new Fl_Help_Dialog; int i; Fl::args_to_utf8(argc, argv); // for MSYS2/MinGW if (!Fl::args(argc, argv, i)) Fl::fatal(Fl::help); const char *fname = (i < argc) ? argv[i] : "help_dialog.html"; help->load(fname); // TODO: add error check (when load() returns int instead of void) help->show(1, argv); Fl::add_timeout(1./10, cb_refresh, help); // to animate GIF's Fl::run(); delete help; return 0; } fltk-1.4.3/test/blocks.cxx0000644000175000017500000006734015004135251015577 0ustar albrechtalbrecht// // "Block Attack!" scrolling blocks game using the Fast Light Tool Kit (FLTK). // // Copyright © 2006-2021 by Michael Sweet. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Audio headers... #include #ifndef _WIN32 # include # include // gettimeofday() #endif // !_WIN32 #ifdef HAVE_ALSA_ASOUNDLIB_H # define ALSA_PCM_NEW_HW_PARAMS_API # include #endif // HAVE_ALSA_ASOUNDLIB_H #ifdef __APPLE__ # include #endif // __APPLE__ #ifdef _WIN32 # include #endif // _WIN32 #define BLOCK_COLS 25 #define BLOCK_ROWS 15 #define BLOCK_SIZE 32 #define BLOCK_BLAST 100 // These factors are used to fine-tune the game when these events // occur by multiplying the timer interval with the given factor: // // (a) enter the next game level // (b) click on a "normal block", destroy this one and adjacent blocks // (c) click on a "bomb", destroy all blocks of the same color #define LEVEL_FACTOR 0.900f // was: 0.95 #define NORMAL_FACTOR 0.999f #define BOMB_FACTOR 0.995f // Set this to 1 to debug the timer callback (should be 0) #define DEBUG_TIMER 0 #include "pixmaps/blast.xpm" Fl_Pixmap blast_pixmap(blast_xpm); #include "pixmaps/red.xpm" Fl_Pixmap red_pixmap(red_xpm); #include "pixmaps/red_bomb.xpm" Fl_Pixmap red_bomb_pixmap(red_bomb_xpm); #include "pixmaps/green.xpm" Fl_Pixmap green_pixmap(green_xpm); #include "pixmaps/green_bomb.xpm" Fl_Pixmap green_bomb_pixmap(green_bomb_xpm); #include "pixmaps/blue.xpm" Fl_Pixmap blue_pixmap(blue_xpm); #include "pixmaps/blue_bomb.xpm" Fl_Pixmap blue_bomb_pixmap(blue_bomb_xpm); #include "pixmaps/yellow.xpm" Fl_Pixmap yellow_pixmap(yellow_xpm); #include "pixmaps/yellow_bomb.xpm" Fl_Pixmap yellow_bomb_pixmap(yellow_bomb_xpm); #include "pixmaps/cyan.xpm" Fl_Pixmap cyan_pixmap(cyan_xpm); #include "pixmaps/cyan_bomb.xpm" Fl_Pixmap cyan_bomb_pixmap(cyan_bomb_xpm); #include "pixmaps/magenta.xpm" Fl_Pixmap magenta_pixmap(magenta_xpm); #include "pixmaps/magenta_bomb.xpm" Fl_Pixmap magenta_bomb_pixmap(magenta_bomb_xpm); #include "pixmaps/gray.xpm" Fl_Pixmap gray_pixmap(gray_xpm); #include "pixmaps/gray_bomb.xpm" Fl_Pixmap gray_bomb_pixmap(gray_bomb_xpm); Fl_Pixmap *normal_pixmaps[] = { &red_pixmap, &green_pixmap, &blue_pixmap, &yellow_pixmap, &cyan_pixmap, &magenta_pixmap, &gray_pixmap }; Fl_Pixmap *bomb_pixmaps[] = { &red_bomb_pixmap, &green_bomb_pixmap, &blue_bomb_pixmap, &yellow_bomb_pixmap, &cyan_bomb_pixmap, &magenta_bomb_pixmap, &gray_bomb_pixmap }; const unsigned char screen_bits[] = { 0xff, 0x55, 0xff, 0xaa, 0xff, 0x55, 0xff, 0xaa }; Fl_Bitmap screen_bitmap(screen_bits, 8, 8); Fl_Tiled_Image screen_tile(&screen_bitmap); // Sound class... // // There are MANY ways to implement sound in a FLTK application. // The approach we are using here is to conditionally compile OS- // specific code into the application - CoreAudio for MacOS X, the // standard Win32 API stuff for Windows, ALSA or X11 for Linux, and // X11 for all others. We have to support ALSA on Linux because the // current Xorg releases no longer support XBell() or the PC speaker. // // There are several good cross-platform audio libraries we could also // use, such as OpenAL, PortAudio, and SDL, however they were not chosen // for this application because of our limited use of sound. // // Many thanks to Ian MacArthur who provided sample code that led to // the CoreAudio implementation you see here! class BlockSound { // Private, OS-specific data... #ifdef __APPLE__ AudioDeviceID device; #ifndef MAC_OS_X_VERSION_10_5 #define MAC_OS_X_VERSION_10_5 1050 #endif # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 AudioDeviceIOProcID audio_proc_id; # endif AudioStreamBasicDescription format; short *data; int remaining; static OSStatus audio_cb(AudioDeviceID device, const AudioTimeStamp *current_time, const AudioBufferList *data_in, const AudioTimeStamp *time_in, AudioBufferList *data_out, const AudioTimeStamp *time_out, void *client_data); #elif defined(_WIN32) HWAVEOUT device; HGLOBAL header_handle; LPWAVEHDR header_ptr; HGLOBAL data_handle; LPSTR data_ptr; #else # ifdef HAVE_ALSA_ASOUNDLIB_H snd_pcm_t *handle; # endif // HAVE_ALSA_ASOUNDLIB_H #endif // __APPLE__ public: // Common data... static short *sample_data; static int sample_size; BlockSound(); ~BlockSound(); void play_explosion(float duration); }; // Sound class globals... short *BlockSound::sample_data = NULL; int BlockSound::sample_size = 0; // Initialize the BlockSound class BlockSound::BlockSound() { sample_size = 0; #ifdef __APPLE__ remaining = 0; UInt32 size = sizeof(device); if (AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, (void *)&device) != noErr) return; size = sizeof(format); if (AudioDeviceGetProperty(device, 0, false, kAudioDevicePropertyStreamFormat, &size, &format) != noErr) return; // Set up a format we like... format.mSampleRate = 44100.0; // 44.1kHz format.mChannelsPerFrame = 2; // stereo if (AudioDeviceSetProperty(device, NULL, 0, false, kAudioDevicePropertyStreamFormat, sizeof(format), &format) != noErr) return; // Check we got linear pcm - what to do if we did not ??? if (format.mFormatID != kAudioFormatLinearPCM) return; // Attach the callback and start the device # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (AudioDeviceCreateIOProcID(device, audio_cb, (void *)this, &audio_proc_id) != noErr) return; AudioDeviceStart(device, audio_proc_id); # else if (AudioDeviceAddIOProc(device, audio_cb, (void *)this) != noErr) return; AudioDeviceStart(device, audio_cb); # endif sample_size = (int)format.mSampleRate; #elif defined(_WIN32) WAVEFORMATEX format; memset(&format, 0, sizeof(format)); format.cbSize = sizeof(format); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = 2; format.nSamplesPerSec = 44100; format.nAvgBytesPerSec = 44100 * 4; format.nBlockAlign = 4; format.wBitsPerSample = 16; data_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, format.nSamplesPerSec * 4); if (!data_handle) return; data_ptr = (LPSTR)GlobalLock(data_handle); header_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR)); if (!header_handle) return; header_ptr = (WAVEHDR *)GlobalLock(header_handle); header_ptr->lpData = data_ptr; header_ptr->dwFlags = 0; header_ptr->dwLoops = 0; if (waveOutOpen(&device, WAVE_MAPPER, &format, 0, 0, WAVE_ALLOWSYNC) != MMSYSERR_NOERROR) return; sample_size = format.nSamplesPerSec; #else # ifdef HAVE_ALSA_ASOUNDLIB_H handle = NULL; if (snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0) >= 0) { // Initialize PCM sound stuff... snd_pcm_hw_params_t *params; snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle, params); snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16); snd_pcm_hw_params_set_channels(handle, params, 2); unsigned rate = 44100; int dir; snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir); snd_pcm_uframes_t period = (int)rate; snd_pcm_hw_params_set_period_size_near(handle, params, &period, &dir); sample_size = rate; if (snd_pcm_hw_params(handle, params) < 0) { sample_size = 0; snd_pcm_close(handle); handle = NULL; } } # endif // HAVE_ALSA_ASOUNDLIB_H #endif // __APPLE__ if (sample_size) { // Make an explosion sound by passing white noise through a low pass // filter with a decreasing frequency... sample_data = new short[2 * sample_size]; short *sample_ptr = sample_data; int max_sample = 2 * sample_size - 2; *sample_ptr++ = 0; *sample_ptr++ = 0; for (int j = max_sample; j > 0; j --, sample_ptr ++) { float freq = (float)j / (float)max_sample; float volume = float(32767.0 * (0.5 * sqrt(freq) + 0.5)); float sample = float(0.0001 * ((rand() % 20001) - 10000)); *sample_ptr = (int)(volume * freq * sample + (1.0 - freq) * sample_ptr[-2]); } } } // Cleanup the BlockSound class BlockSound::~BlockSound() { #ifdef __APPLE__ if (sample_size) { # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 AudioDeviceStop(device, audio_proc_id); AudioDeviceDestroyIOProcID(device, audio_proc_id); # else AudioDeviceStop(device, audio_cb); AudioDeviceRemoveIOProc(device, audio_cb); # endif } #elif defined(_WIN32) if (sample_size) { waveOutClose(device); GlobalUnlock(header_handle); GlobalFree(header_handle); GlobalUnlock(data_handle); GlobalFree(data_handle); } #else # ifdef HAVE_ALSA_ASOUNDLIB_H if (handle) { snd_pcm_drain(handle); snd_pcm_close(handle); } # endif // HAVE_ALSA_ASOUNDLIB_H #endif // __APPLE__ if (sample_size) { delete[] sample_data; } } #ifdef __APPLE__ // Callback function for writing audio data... OSStatus BlockSound::audio_cb(AudioDeviceID device, const AudioTimeStamp *current_time, const AudioBufferList *data_in, const AudioTimeStamp *time_in, AudioBufferList *data_out, const AudioTimeStamp *time_out, void *client_data) { BlockSound *ss = (BlockSound *)client_data; int count; float *buffer; if (!ss->remaining) return noErr; for (count = data_out->mBuffers[0].mDataByteSize / sizeof(float), buffer = (float*) data_out->mBuffers[0].mData; ss->remaining > 0 && count > 0; count --, ss->data ++, ss->remaining --) { *buffer++ = *(ss->data) / 32767.0; } while (count > 0) { *buffer++ = 0.0; count --; } return noErr; } #endif // __APPLE__ // Play a note for the given amount of time... void BlockSound::play_explosion(float duration) { Fl::check(); if (duration <= 0.0) return; #if defined(__APPLE__) || defined(_WIN32) || defined(HAVE_ALSA_ASOUNDLIB_H) if (duration > 1.0) duration = 1.0; int samples = (int)(duration * sample_size); short *sample_ptr = sample_data + 2 * (sample_size - samples); #endif // __APPLE__ || _WIN32 || HAVE_ALSA_ASOUNDLIB_H #ifdef __APPLE__ // Point to the next note... data = sample_ptr; remaining = samples * 2; #elif defined(_WIN32) if (sample_size) { memcpy(data_ptr, sample_ptr, samples * 4); header_ptr->dwBufferLength = samples * 4; waveOutPrepareHeader(device, header_ptr, sizeof(WAVEHDR)); waveOutWrite(device, header_ptr, sizeof(WAVEHDR)); } else Beep(440, (int)(1000.0 * duration)); #elif defined(HAVE_ALSA_ASOUNDLIB_H) if (handle) { // Use ALSA to play the sound... if (snd_pcm_writei(handle, sample_ptr, samples) < 0) { snd_pcm_prepare(handle); snd_pcm_writei(handle, sample_ptr, samples); } return; } #endif // __APPLE__ } class BlockWindow : public Fl_Double_Window { public: struct Block { int color; bool bomb; float y; }; struct Column { int num_blocks; Block blocks[BLOCK_ROWS]; float x; }; private: int frames_, frames_per_second_; time_t frame_time_; bool show_fps_; Fl_Button *help_button_, *play_button_; int num_columns_; Column columns_[BLOCK_COLS]; int count_; bool help_; int high_score_; float interval_; int level_; int num_colors_; int opened_columns_; bool paused_; static Fl_Preferences prefs_; int score_; BlockSound *sound_; char title_[255]; int title_y_; void _BlockWindow(); int bomb(int color); int click(int col, int row); static void help_cb(Fl_Widget *wi, BlockWindow *bw); void init(); static void play_cb(Fl_Widget *wi, BlockWindow *bw); static void timeout_cb(BlockWindow *bw); public: BlockWindow(int X, int Y, int W, int H, const char *L = 0); BlockWindow(int W, int H, const char *L = 0); ~BlockWindow(); void draw() FL_OVERRIDE; int handle(int event) FL_OVERRIDE; void new_game(); int score() { return (score_); } void up_level(); }; Fl_Preferences BlockWindow::prefs_(Fl_Preferences::USER_L, "fltk.org", "blocks"); int main(int argc, char *argv[]) { Fl::scheme("plastic"); Fl::visible_focus(0); BlockWindow *bw = new BlockWindow(BLOCK_COLS * BLOCK_SIZE, BLOCK_ROWS * BLOCK_SIZE + 20, "Block Attack!"); bw->show(argc, argv); return (Fl::run()); } // Create a block window at the specified position BlockWindow::BlockWindow(int X, int Y, int W, int H, const char *L) : Fl_Double_Window(X, Y, W, H, L) { _BlockWindow(); } // Create a block window BlockWindow::BlockWindow(int W, int H, const char *L) : Fl_Double_Window(W, H, L) { _BlockWindow(); } // Delete a block window BlockWindow::~BlockWindow() { Fl::remove_timeout((Fl_Timeout_Handler)timeout_cb, (void *)this); } // Initialize a block window... void BlockWindow::_BlockWindow() { init(); help_button_ = new Fl_Button(0, 0, 20, 20, "?"); help_button_->callback((Fl_Callback *)help_cb, this); help_button_->shortcut('?'); play_button_ = new Fl_Button(80, (h() - 80) / 2, 80, 80, "@>"); play_button_->callback((Fl_Callback *)play_cb, this); play_button_->labelsize(44); play_button_->shortcut(' '); sound_ = new BlockSound(); prefs_.get("high_score", high_score_, 0); Fl::add_timeout(0.01666666, (Fl_Timeout_Handler)timeout_cb, (void *)this); } // Bomb all blocks of a given color and return the number of affected blocks int BlockWindow::bomb(int color) { int j, k; int count; Block *b; Column *c; if (color >= BLOCK_BLAST) return (0); for (j = num_columns_, c = columns_, count = 1; j > 0; j --, c ++) for (k = c->num_blocks, b = c->blocks; k > 0; k --, b ++) if (b->color == color) { b->color = -color; count ++; } return (count); } // Tag all blocks connected to the clicked block and return the number // of affected blocks int BlockWindow::click(int col, int row) { Block *b; Column *c; int count, color; c = columns_ + col; b = c->blocks + row; color = b->color; if (color < 0 || color >= BLOCK_BLAST) return (0); // Find the bottom block... while (row > 0 && b[-1].color == color) { row --; b --; } count = 0; while (row < c->num_blocks && b->color == color) { b->color = -color; if (col > 0 && row < c[-1].num_blocks && c[-1].blocks[row].color == color) { count += click(col - 1, row); } if (col < (num_columns_ - 1) && row < c[1].num_blocks && c[1].blocks[row].color == color) { count += click(col + 1, row); } count ++; row ++; b ++; } return (count); } // Draw the block window... void BlockWindow::draw() { int j, k, xx, yy; Block *b; Column *c; // Draw the blocks... fl_color(FL_BLACK); fl_rectf(0, 0, w(), h()); // Draw the blocks... for (j = num_columns_, c = columns_; j > 0; j --, c ++) for (k = c->num_blocks, b = c->blocks; k > 0; k --, b ++) { xx = w() - (int)c->x; yy = h() - BLOCK_SIZE - (int)b->y; if (b->color >= BLOCK_BLAST) { b->color ++; blast_pixmap.draw(xx, yy); } else if (b->color < 0) { if (b->bomb) bomb_pixmaps[-b->color - 1]->draw(xx, yy); else normal_pixmaps[-b->color - 1]->draw(xx, yy); } else { if (b->bomb) bomb_pixmaps[b->color - 1]->draw(xx, yy); else normal_pixmaps[b->color - 1]->draw(xx, yy); } } if (interval_ < 0.0 || paused_) { fl_color(FL_BLACK); screen_tile.draw(0, 0, w(), h(), 0, 0); } // Redraw the widgets... play_button_->redraw(); help_button_->redraw(); draw_children(); // Draw any paused/game over/new game message... if ((paused_ || interval_ < 0.0) && play_button_->w() == 80) { const char *s; if (help_) { s = "Click on adjacent blocks of the same color. Clear all blocks " "before they reach the left side."; fl_font(FL_HELVETICA_BOLD, 24); fl_color(FL_BLACK); fl_draw(s, 171, 3, w() - 250, h() - 6, (Fl_Align)(FL_ALIGN_WRAP | FL_ALIGN_LEFT)); fl_color(FL_YELLOW); fl_draw(s, 168, 0, w() - 250, h(), (Fl_Align)(FL_ALIGN_WRAP | FL_ALIGN_LEFT)); } else { if (interval_ < 0.0) { #ifdef DEBUG // Show sample waveform... short *sample_ptr; for (i = 0; i < 2; i++) { fl_color(FL_RED + i); fl_begin_line(); for (j = 0, sample_ptr = sound_->sample_data + i; j < sound_->sample_size; j ++, sample_ptr += 2) fl_vertex(j * w() / sound_->sample_size, *sample_ptr * h() / 4 / 65534 + h() / 2); fl_end_line(); } #endif // DEBUG if (num_columns_ && (time(NULL) & 7) < 4) s = "Game Over"; else s = "Block Attack!\nby Michael R Sweet"; } else s = "Paused"; fl_font(FL_HELVETICA_BOLD, 32); fl_color(FL_BLACK); fl_draw(s, 6, 6, w() - 6, h() - 6, FL_ALIGN_CENTER); fl_color(FL_YELLOW); fl_draw(s, 0, 0, w(), h(), FL_ALIGN_CENTER); } } time_t curtime = time(NULL); frames_ ++; if (curtime > frame_time_) { frames_per_second_ = (frames_per_second_ + 3 * frames_ / int(curtime - frame_time_)) / 4; frames_ = 0; frame_time_ = curtime; } // Draw the scores and level... char s[255]; snprintf(s, sizeof(s), " Score: %d", score_); fl_color(FL_WHITE); fl_font(FL_HELVETICA, 14); fl_draw(s, 40, 0, w() - 40, 20, FL_ALIGN_LEFT); snprintf(s, sizeof(s), "High Score: %d ", high_score_); fl_draw(s, 0, 0, w(), 20, FL_ALIGN_RIGHT); if (level_ > 1 || title_y_ <= 0) { snprintf(s, sizeof(s), "Level: %d ", level_); fl_draw(s, 0, 0, w(), 20, FL_ALIGN_CENTER); } if (show_fps_) { snprintf(s, sizeof(s), "FPS: %d ", frames_per_second_); fl_draw(s, 0, h() - 20, w(), 20, FL_ALIGN_LEFT); } if (title_y_ > 0 && interval_ > 0.0) { int sz = 14 + title_y_ * 86 / h(); fl_font(FL_HELVETICA_BOLD, sz); fl_color(FL_YELLOW); fl_draw(title_, 0, title_y_, w(), sz, FL_ALIGN_CENTER); } } // Handle mouse clicks, etc. int BlockWindow::handle(int event) { int j, k, mx, my, count; Block *b; Column *c; if (Fl_Double_Window::handle(event)) return (1); else if (interval_ < 0.0 || paused_) return (0); switch (event) { case FL_KEYBOARD: // '+': raise level if (Fl::event_text() && !Fl::event_state(FL_CTRL | FL_ALT | FL_META) && !strcmp(Fl::event_text(), "+")) { up_level(); return (1); } // ALT + SHIFT + 'H': clear highscore if (Fl::event_text() && (Fl::event_state() & (FL_ALT | FL_SHIFT)) == (FL_ALT | FL_SHIFT) && !strcmp(Fl::event_text(), "H")) { high_score_ = score_; prefs_.set("high_score", high_score_); return (1); } // 'f': toggle showing frames-per-second if (Fl::event_text() && !strcmp(Fl::event_text(), "f")) { show_fps_ = !show_fps_; } break; case FL_PUSH: mx = w() - Fl::event_x() + BLOCK_SIZE; my = h() - Fl::event_y(); count = 0; b = 0; for (j = 0, c = columns_; !count && j < num_columns_; j ++, c ++) for (k = 0, b = c->blocks; k < c->num_blocks; k ++, b ++) if (mx >= c->x && mx < (c->x + BLOCK_SIZE) && my >= b->y && my < (b->y + BLOCK_SIZE)) { if (b->bomb) count = bomb(b->color); else count = click(j, k); break; } if (count < 2) { for (j = 0, c = columns_; j < num_columns_; j ++, c ++) for (k = 0, b = c->blocks; k < c->num_blocks; k ++, b ++) if (b->color < 0) b->color = -b->color; } else { count --; if (b->bomb) { sound_->play_explosion(float(0.19 + 0.005 * count)); interval_ *= BOMB_FACTOR; score_ += count; } else { sound_->play_explosion(float(0.09 + 0.005 * count)); interval_ *= NORMAL_FACTOR; score_ += count * count; } if (score_ > high_score_) { high_score_ = score_; prefs_.set("high_score", high_score_); } for (j = 0, c = columns_; j < num_columns_; j ++, c ++) for (k = 0, b = c->blocks; k < c->num_blocks; k ++, b ++) if (b->color < 0) b->color = BLOCK_BLAST; } return (1); default: break; } return (0); } // Toggle the on-line help... void BlockWindow::help_cb(Fl_Widget *, BlockWindow *bw) { bw->paused_ = bw->help_ = !bw->help_; bw->play_button_->label("@>"); bw->redraw(); } // Initialize the block window... void BlockWindow::init() { frames_ = 0; frames_per_second_ = 0; frame_time_ = time(NULL); show_fps_ = false; count_ = 0; help_ = false; interval_ = -1.0; level_ = 1; num_colors_ = 3; num_columns_ = 0; paused_ = false; score_ = 0; title_[0] = '\0'; title_y_ = 0; } // Start a new game... void BlockWindow::new_game() { // Seed the random number generator... srand((unsigned int)time(NULL)); init(); interval_ = 0.01666666666f; opened_columns_ = 0; strcpy(title_, "Level: 1"); title_y_ = h(); redraw(); } // Play/pause... void BlockWindow::play_cb(Fl_Widget *wi, BlockWindow *bw) { if (bw->interval_ < 0) bw->new_game(); else bw->paused_ = !bw->paused_; if (bw->paused_) wi->label("@>"); else { wi->label("@-2||"); bw->help_ = false; } } void BlockWindow::up_level() { interval_ *= LEVEL_FACTOR; opened_columns_ = 0; if (num_colors_ < 7) num_colors_ ++; level_ ++; snprintf(title_, sizeof(title_), "Level: %d", level_); title_y_ = h(); } // Animate the game... void BlockWindow::timeout_cb(BlockWindow *bw) { int i, j; Block *b; Column *c; float lastx, lasty; #if DEBUG_TIMER static double lasttime; static double delta_sum; static double interval; double curtime; static int ntime = 0; static int level = 0; #if !defined(_WIN32) { struct timeval atime; gettimeofday(&atime, NULL); curtime = atime.tv_sec % 60 + 0.000001 * atime.tv_usec; } #else // (_WIN32) { SYSTEMTIME atime; GetLocalTime(&atime); curtime = atime.wSecond + 0.001 * atime.wMilliseconds; } #endif // (_WIN32) // platform independent part of timer debugging code if (bw->interval_ > 0) { // game is active if (bw->level_ != level) { if (ntime > 0) { printf("*** average delta time = %9.6f, n =%4d, level %d, interval %f\n", delta_sum / ntime, ntime, level, interval); fflush(stdout); } delta_sum = 0; // reset average ntime = 0; interval = bw->interval_; } double delta = curtime - lasttime; if (delta < 0) delta += 60; printf("%9.6f (%+f - %f = %9.6f), level: %d\n", curtime, delta, interval, delta - interval, level); fflush(stdout); interval = bw->interval_; level = bw->level_; delta = delta - interval; delta_sum += delta > 0 ? delta : -delta; // abs(delta) ntime++; } else { // waiting ... // printf("[OFF] %6.2f\n", curtime); // fflush(stdout); } lasttime = curtime; #endif // DEBUG_TIMER // Update blocks that have been destroyed... for (i = 0, c = bw->columns_; i < bw->num_columns_; i ++, c ++) for (j = 0, b = c->blocks; j < c->num_blocks; j ++, b ++) if (b->color > (BLOCK_BLAST + 5)) { bw->redraw(); c->num_blocks --; if (j < c->num_blocks) { memmove(b, b + 1, (c->num_blocks - j) * sizeof(Block)); } j --; b --; if (!c->num_blocks) { bw->num_columns_ --; if (i < bw->num_columns_) { memmove(c, c + 1, (bw->num_columns_ - i) * sizeof(Column)); } i --; c --; j = c->num_blocks; } } // Let the rest of the blocks fall and/or move... for (i = bw->num_columns_, c = bw->columns_, lastx = c->x; i > 0; i--, c++) { if (c->x > lastx) { c->x -= 8; bw->redraw(); } lastx = c->x + BLOCK_SIZE; if (!bw->paused_ && bw->interval_ > 0.0) { bw->redraw(); c->x += 0.25; } for (j = c->num_blocks, b = c->blocks, lasty = 0; j > 0; j --, b ++) { if (b->y > lasty) { bw->redraw(); b->y -= 4; } lasty = b->y + BLOCK_SIZE; } } // Slide the title text as needed... if (bw->title_y_ > 0) { bw->redraw(); bw->title_y_ -= 2; } // Play the game... if (!bw->paused_ && bw->interval_ > 0.0) { bw->count_ --; if (bw->count_ <= 0) { bw->redraw(); bw->count_ = 4 * BLOCK_SIZE; if (bw->num_columns_ == BLOCK_COLS) { bw->interval_ = -1.0; bw->sound_->play_explosion(0.8f); bw->play_button_->label("@>"); } else { bw->opened_columns_ ++; if (bw->opened_columns_ > (2 * BLOCK_COLS)) { bw->up_level(); } c = bw->columns_; if (bw->num_columns_) { memmove(c + 1, c, bw->num_columns_ * sizeof(Column)); } bw->num_columns_ ++; c->x = 0; c->num_blocks = BLOCK_ROWS; for (j = 0, b = c->blocks; j < BLOCK_ROWS; j ++, b ++) { b->bomb = bw->num_colors_ > 3 && (rand() & 127) < bw->num_colors_; b->color = 1 + (rand() % bw->num_colors_); b->y = float(j * (BLOCK_SIZE + 8) + 24); } } } } else { bw->count_ --; if (bw->count_ <= 0) { bw->count_ = 40; bw->redraw(); } } // Update the play/pause button as needed... if ((bw->paused_ || bw->interval_< 0.0) && bw->play_button_->w() < 80) { int s = bw->play_button_->w() + 5; bw->play_button_->resize(s, (s - 20) * (bw->h() - s) / 120, s, s); bw->play_button_->labelsize(s / 2 + 4); bw->redraw(); } else if ((!bw->paused_ && bw->interval_ > 0.0) && bw->play_button_->w() > 20) { int s = bw->play_button_->w() - 2; bw->play_button_->resize(s, (s - 20) * (bw->h() - s) / 120, s, s); bw->play_button_->labelsize(s / 2 + 4); bw->redraw(); } if (bw->interval_ > 0.0) { Fl::repeat_timeout(bw->interval_, (Fl_Timeout_Handler)timeout_cb, (void *)bw); } else { Fl::repeat_timeout(0.1, (Fl_Timeout_Handler)timeout_cb, (void *)bw); } } fltk-1.4.3/test/menubar.cxx0000644000175000017500000002415215004135251015745 0ustar albrechtalbrecht// // Menubar test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if defined(__APPLE__) && !(defined(FLTK_USE_X11) || defined(FLTK_USE_WAYLAND)) # define HAS_MAC_APP_MENU 1 #endif #ifdef HAS_MAC_APP_MENU # include // for Fl_Mac_App_Menu #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #define TERMINAL_HEIGHT 120 // Set the macro below to 1 to test shortcuts usually used for screen scaling. // This should normally be set to 0, enable only for testing! // Note: screen scaling does not work with ctrl/+/-/0 if enabled (1)! #define OVERRIDE_SCALING_SHORTCUTS 0 // Globals Fl_Terminal *G_tty = 0; void window_cb(Fl_Widget* w, void*) { puts("window callback called"); // end of program, so stdout instead of G_tty ((Fl_Double_Window *)w)->hide(); } void test_cb(Fl_Widget* w, void*) { Fl_Menu_* mw = (Fl_Menu_*)w; const Fl_Menu_Item* m = mw->mvalue(); if (!m) G_tty->printf("NULL\n"); else if (m->shortcut()) G_tty->printf("%s - %s\n", m->label(), fl_shortcut_label(m->shortcut())); else G_tty->printf("%s\n", m->label()); } void quit_cb(Fl_Widget*, void*) {exit(0);} Fl_Menu_Item hugemenu[100]; Fl_Menu_Item menutable[] = { {"foo",0,0,0,FL_MENU_INACTIVE}, {"&File",0,0,0,FL_SUBMENU}, {"&Open", FL_ALT+'o', 0, 0, FL_MENU_INACTIVE}, {"&Close", 0, 0}, {"&Quit", FL_ALT+'q', quit_cb, 0, FL_MENU_DIVIDER}, #if (OVERRIDE_SCALING_SHORTCUTS) {"CTRL/0", FL_COMMAND+'0', 0}, {"CTRL/-", FL_COMMAND+'-', 0}, {"CTRL/+", FL_COMMAND+'+', 0}, {"CTRL/=", FL_COMMAND+'=', 0}, #endif {"shortcut",'a'}, {"shortcut",FL_SHIFT+'a'}, {"shortcut",FL_CTRL+'a'}, {"shortcut",FL_CTRL+FL_SHIFT+'a'}, {"shortcut",FL_ALT+'a'}, {"shortcut",FL_ALT+FL_SHIFT+'a'}, {"shortcut",FL_ALT+FL_CTRL+'a'}, {"shortcut",FL_ALT+FL_SHIFT+FL_CTRL+'a', 0,0, FL_MENU_DIVIDER}, {"shortcut",'\r'/*FL_Enter*/}, {"shortcut",FL_CTRL+FL_Enter, 0,0, FL_MENU_DIVIDER}, {"shortcut",FL_F+1}, {"shortcut",FL_SHIFT+FL_F+1}, {"shortcut",FL_CTRL+FL_F+1}, {"shortcut",FL_SHIFT+FL_CTRL+FL_F+1}, {"shortcut",FL_ALT+FL_F+1}, {"shortcut",FL_ALT+FL_SHIFT+FL_F+1}, {"shortcut",FL_ALT+FL_CTRL+FL_F+1}, {"shortcut",FL_ALT+FL_SHIFT+FL_CTRL+FL_F+1, 0,0, FL_MENU_DIVIDER}, {"&Submenus", FL_ALT+'S', 0, (void*)"Submenu1", FL_SUBMENU}, {"A very long menu item"}, {"&submenu",FL_CTRL+'S', 0, (void*)"submenu2", FL_SUBMENU}, {"item 1"}, {"item 2"}, {"item 3"}, {"item 4"}, {0}, {"after submenu"}, {0}, {0}, {"&Edit",FL_F+2,0,0,FL_SUBMENU}, {"Undo", FL_ALT+'z', 0}, {"Redo", FL_ALT+'r', 0, 0, FL_MENU_DIVIDER}, {"Cut", FL_ALT+'x', 0}, {"Copy", FL_ALT+'c', 0}, {"Paste", FL_ALT+'v', 0}, {"Inactive", FL_ALT+'d', 0, 0, FL_MENU_INACTIVE}, {"Clear", 0, 0, 0, FL_MENU_DIVIDER}, {"Invisible", FL_ALT+'e', 0, 0, FL_MENU_INVISIBLE}, {"Preferences", 0, 0}, {"Size", 0, 0}, {0}, {"&Checkbox",FL_F+3,0,0,FL_SUBMENU}, {"&Alpha", FL_F+2, 0, (void *)1, FL_MENU_TOGGLE}, {"&Beta", 0, 0, (void *)2, FL_MENU_TOGGLE}, {"&Gamma", 0, 0, (void *)3, FL_MENU_TOGGLE}, {"&Delta", 0, 0, (void *)4, FL_MENU_TOGGLE|FL_MENU_VALUE}, {"&Epsilon",0, 0, (void *)5, FL_MENU_TOGGLE}, {"&Pi", 0, 0, (void *)6, FL_MENU_TOGGLE}, {"&Mu", 0, 0, (void *)7, FL_MENU_TOGGLE|FL_MENU_DIVIDER}, {"Red", 0, 0, (void *)1, FL_MENU_TOGGLE, 0, 0, 0, 1}, {"Black", 0, 0, (void *)1, FL_MENU_TOGGLE|FL_MENU_DIVIDER}, {"00", 0, 0, (void *)1, FL_MENU_TOGGLE}, {"000", 0, 0, (void *)1, FL_MENU_TOGGLE}, {0}, {"&Radio",0,0,0,FL_SUBMENU}, {"&Alpha", 0, 0, (void *)1, FL_MENU_RADIO}, {"&Beta", 0, 0, (void *)2, FL_MENU_RADIO}, {"&Gamma", 0, 0, (void *)3, FL_MENU_RADIO}, {"&Delta", 0, 0, (void *)4, FL_MENU_RADIO|FL_MENU_VALUE}, {"&Epsilon",0, 0, (void *)5, FL_MENU_RADIO}, {"&Pi", 0, 0, (void *)6, FL_MENU_RADIO}, {"&Mu", 0, 0, (void *)7, FL_MENU_RADIO|FL_MENU_DIVIDER}, {"Red", 0, 0, (void *)1, FL_MENU_RADIO}, {"Black", 0, 0, (void *)1, FL_MENU_RADIO|FL_MENU_DIVIDER}, {"00", 0, 0, (void *)1, FL_MENU_RADIO}, {"000", 0, 0, (void *)1, FL_MENU_RADIO}, {0}, {"&Font",0,0,0,FL_SUBMENU /*, 0, FL_BOLD, 20*/}, {"Normal", 0, 0, 0, 0, 0, 0, 14}, {"Bold", 0, 0, 0, 0, 0, FL_BOLD, 14}, {"Italic", 0, 0, 0, 0, 0, FL_ITALIC, 14}, {"BoldItalic",0,0,0, 0, 0, FL_BOLD+FL_ITALIC, 14}, {"Small", 0, 0, 0, 0, 0, FL_BOLD+FL_ITALIC, 10}, {"Emboss", 0, 0, 0, 0, (uchar)FL_EMBOSSED_LABEL}, {"Engrave", 0, 0, 0, 0, (uchar)FL_ENGRAVED_LABEL}, {"Shadow", 0, 0, 0, 0, (uchar)FL_SHADOW_LABEL}, {"@->", 0, 0, 0, 0, (uchar)FL_SYMBOL_LABEL}, {0}, {"&International",0,0,0,FL_SUBMENU}, {"Sharp Ess",0x0000df}, {"A Umlaut",0x0000c4}, {"a Umlaut",0x0000e4}, {"Euro currency",FL_COMMAND+0x0020ac}, {"the &\xc3\xbc Umlaut"}, // ü {"the capital &\xc3\x9c"}, // Ü {"convert \xc2\xa5 to &\xc2\xa3"}, // Yen to GBP {"convert \xc2\xa5 to &\xe2\x82\xac"}, // Yen to Euro {"Hangul character Sios &\xe3\x85\x85"}, {"Hangul character Cieuc", 0x003148}, {0}, {"E&mpty",0,0,0,FL_SUBMENU}, {0}, {"&Inactive", 0, 0, 0, FL_MENU_INACTIVE|FL_SUBMENU}, {"A very long menu item"}, {"A very long menu item"}, {0}, {"Invisible",0, 0, 0, FL_MENU_INVISIBLE|FL_SUBMENU}, {"A very long menu item"}, {"A very long menu item"}, {0}, {"&Huge", 0, 0, (void*)hugemenu, FL_SUBMENU_POINTER}, {"button",FL_F+4, 0, 0, FL_MENU_TOGGLE}, {0} }; Fl_Menu_Item pulldown[] = { {"Red", FL_ALT+'r'}, {"Green", FL_ALT+'g'}, {"Blue", FL_ALT+'b'}, {"Strange", FL_ALT+'s', 0, 0, FL_MENU_INACTIVE}, {"&Charm", FL_ALT+'c'}, {"Truth", FL_ALT+'t'}, {"Beauty", FL_ALT+'b'}, {0} }; #ifdef HAS_MAC_APP_MENU Fl_Menu_Item menu_location[] = { {"Fl_Menu_Bar", 0, 0, 0, FL_MENU_VALUE}, {"Fl_Sys_Menu_Bar", }, {0} }; Fl_Sys_Menu_Bar* smenubar; void menu_location_cb(Fl_Widget* w, void* data) { Fl_Menu_Bar *menubar = (Fl_Menu_Bar*)data; if (((Fl_Choice*)w)->value() == 1) { // switch to system menu bar menubar->hide(); const Fl_Menu_Item *menu = menubar->menu(); smenubar = new Fl_Sys_Menu_Bar(0,0,0,30); smenubar->menu(menu); smenubar->callback(test_cb); } else { // switch to window menu bar menubar->copy(smenubar->menu()); delete smenubar; menubar->show(); } } #endif // HAS_MAC_APP_MENU void menu_linespacing_cb(Fl_Widget* w, void*) { Fl_Value_Slider *fvs = (Fl_Value_Slider*)w; int val = (int)fvs->value(); Fl::menu_linespacing(val); // takes effect when someone opens a new menu.. } #define WIDTH 700 Fl_Menu_* menus[4]; void about_cb(Fl_Widget*, void*) { fl_message("The menubar test app."); } int main(int argc, char **argv) { for (int i=0; i<99; i++) { char buf[100]; snprintf(buf, 100,"item %d",i); hugemenu[i].text = fl_strdup(buf); } Fl_Double_Window window(WIDTH,400+TERMINAL_HEIGHT); Fl_Scheme_Choice scheme_choice(300, 50, 100, 25, "&scheme"); G_tty = new Fl_Terminal(0,400,WIDTH,TERMINAL_HEIGHT); window.callback(window_cb); Fl_Menu_Bar menubar(0,0,WIDTH,30); menubar.menu(menutable); menubar.callback(test_cb); menus[0] = &menubar; Fl_Menu_Button mb1(100,100,120,25,"&menubutton"); mb1.menu(pulldown); mb1.tooltip("this is a menu button"); mb1.callback(test_cb); menus[1] = &mb1; Fl_Choice ch(300,100,80,25,"&choice:"); ch.menu(pulldown); ch.tooltip("this is a choice menu"); ch.callback(test_cb); menus[2] = &ch; Fl_Menu_Button mb(0,0,WIDTH,400,"&popup"); mb.type(Fl_Menu_Button::POPUP3); mb.menu(menutable); mb.remove(1); // delete the "File" submenu mb.callback(test_cb); menus[3] = &mb; Fl_Box b(200,200,200,100,"Press right button\nfor a pop-up menu"); window.resizable(&mb); window.size_range(300,400,0,400+TERMINAL_HEIGHT); #ifdef HAS_MAC_APP_MENU Fl_Choice ch2(500,100,150,25,"Use:"); ch2.menu(menu_location); ch2.callback(menu_location_cb, &menubar); ch2.value(1); menu_location_cb(&ch2, &menubar); #endif Fl_Value_Slider menu_linespacing_slider(500,150,150,20,"Fl::menu_linespacing()"); menu_linespacing_slider.tooltip("Changes the line spacing between all menu items"); menu_linespacing_slider.type(1); //menu_linespacing_slider.labelsize(14); menu_linespacing_slider.value(Fl::menu_linespacing()); menu_linespacing_slider.color((Fl_Color)46); menu_linespacing_slider.selection_color((Fl_Color)1); //menu_linespacing_slider.textsize(10); menu_linespacing_slider.align(Fl_Align(FL_ALIGN_LEFT)); menu_linespacing_slider.range(0.1, 50.0); menu_linespacing_slider.step(1.0); menu_linespacing_slider.callback(menu_linespacing_cb); window.end(); Fl_Sys_Menu_Bar::about(about_cb, NULL); #ifdef HAS_MAC_APP_MENU Fl_Menu_Item custom[] = { {"Preferences…", 0, test_cb, NULL, FL_MENU_DIVIDER}, {"Radio1", 0, test_cb, NULL, FL_MENU_RADIO | FL_MENU_VALUE}, {"Radio2", 0, test_cb, NULL, FL_MENU_RADIO | FL_MENU_DIVIDER}, {0} }; Fl_Mac_App_Menu::custom_application_menu_items(custom); //Fl_Sys_Menu_Bar::window_menu_style(Fl_Sys_Menu_Bar::no_window_menu); #endif window.show(argc, argv); return Fl::run(); } fltk-1.4.3/test/list_visuals.cxx0000644000175000017500000001255115004135251017035 0ustar albrechtalbrecht// // Visual list utility for the Fast Light Tool Kit (FLTK). // // List all the visuals on the screen, and dumps anything interesting // about them to stdout. // // Does not use FLTK under X11. // // This file may be #included in another program to make a function to // call to list the visuals. Fl.H must be included first to indicate this. // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef Fl_H # define NEED_MAIN 1 // when not included by another FLTK program #endif #include // for FLTK_USE_X11 #ifdef FLTK_USE_X11 #include #define HAVE_MULTIBUF 0 #ifdef NEED_MAIN #include #include #include #include #include Display *fl_display; int fl_screen; const char *dname; void fl_open_display() { fl_display = XOpenDisplay(dname); if (!fl_display) { fprintf(stderr,"Can't open display: %s\n",XDisplayName(dname)); exit(1); } fl_screen = DefaultScreen(fl_display); } #endif // NEED_MAIN const char *ClassNames[] = { "StaticGray ", "GrayScale ", "StaticColor", "PseudoColor", "TrueColor ", "DirectColor" }; // SERVER_OVERLAY_VISUALS property element: typedef struct _OverlayInfo { long overlay_visual; long transparent_type; long value; long layer; } OverlayInfo; #if HAVE_MULTIBUF #include #endif static void print_mask(XVisualInfo* p) { int n = 0; int what = 0; int print_anything = 0; char buf[20]; char *q = buf; *q = 0; int b; unsigned int m; for (b=32,m=0x80000000; ; b--,m>>=1) { int new_what = 0; if (p->red_mask&m) new_what = 'r'; else if (p->green_mask&m) new_what = 'g'; else if (p->blue_mask&m) new_what = 'b'; else new_what = '?'; if (new_what != what) { if (what && (what != '?' || print_anything)) { q += snprintf(q, sizeof(buf) - (q-buf), "%d%c", n, what); print_anything = 1; } what = new_what; n = 1; } else { n++; } if (!b) break; } printf("%7s", buf); } void list_visuals() { fl_open_display(); XVisualInfo vTemplate; int num; XVisualInfo *visualList = XGetVisualInfo(fl_display,0,&vTemplate,&num); XPixmapFormatValues *pfvlist; static int numpfv; pfvlist = XListPixmapFormats(fl_display, &numpfv); OverlayInfo *overlayInfo = 0; int numoverlayinfo = 0; Atom overlayVisualsAtom = XInternAtom(fl_display,"SERVER_OVERLAY_VISUALS",1); if (overlayVisualsAtom) { unsigned long sizeData, bytesLeft; Atom actualType; int actualFormat; if (!XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen), overlayVisualsAtom, 0L, 10000L, False, overlayVisualsAtom, &actualType, &actualFormat, &sizeData, &bytesLeft, (unsigned char **) &overlayInfo)) numoverlayinfo = int(sizeData/4); } #if HAVE_MULTIBUF int event_base, error_base; XmbufBufferInfo *mbuf, *sbuf; int nmbuf = 0, nsbuf = 0; if (XmbufQueryExtension(fl_display,&event_base, &error_base)) { XmbufGetScreenInfo(fl_display,RootWindow(fl_display,fl_screen), &nmbuf, &mbuf, &nsbuf, &sbuf); } #endif for (int i=0; i= pfvlist+numpfv) {pfv = 0; break;} // should not happen! if (pfv->depth == p->depth) break; } int j = pfv ? pfv->bits_per_pixel : 0; printf(" %2ld: %s %2d/%d", p->visualid, ClassNames[p->c_class], p->depth, j); if (j < 10) putchar(' '); print_mask(p); for (j=0; joverlay_visual == long(p->visualid)) { printf(" overlay("); if (o->transparent_type==1) printf("transparent pixel %ld, ",o->value); else if (o->transparent_type==2) printf("transparent mask %ld, ",o->value); else printf("opaque, "); printf("layer %ld)", o->layer); } } #if HAVE_MULTIBUF for (j=0; jvisualid == p->visualid) printf(" multibuffer(%d)", m->max_buffers); } for (j=0; jvisualid == p->visualid) printf(" stereo multibuffer(%d)", m->max_buffers); } #endif if (p->visualid==XVisualIDFromVisual(DefaultVisual(fl_display,fl_screen))) printf(" (default visual)"); putchar('\n'); } if ( overlayInfo ) { XFree(overlayInfo); overlayInfo = 0; } } #endif // FLTK_USE_X11 #ifdef NEED_MAIN # ifndef FLTK_USE_X11 # include # endif int main(int argc, char** argv) { # ifdef FLTK_USE_X11 if (argc == 1); else if (argc == 2 && argv[1][0]!='-') dname = argv[1]; else {fprintf(stderr,"usage: %s \n",argv[0]); exit(1);} list_visuals(); return 0; # else fl_alert("Currently, this program works only under X."); return 1; # endif // FLTK_USE_X11 } #endif // NEED_MAIN fltk-1.4.3/test/forms.cxx0000644000175000017500000001546215004135251015446 0ustar albrechtalbrecht// // Another forms demo for the Fast Light Tool Kit (FLTK). // // This is an XForms program with some changes for FLTK. // // This demo show the different boxtypes. Note that some // boxtypes are not appropriate for some objects // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include // FLTK: includes #ifdef FLTK_HAVE_FORMS // FLTK: defined in since FLTK 1.4.0 #include // changed for FLTK static int border = 1; // changed from FL_TRANSIENT for FLTK // (this is so the close box and Esc work to close the window) typedef struct { Fl_Boxtype val; const char *name; } VN_struct; static VN_struct btypes[] = { {FL_NO_BOX, "no box"}, {FL_UP_BOX, "up box"}, {FL_DOWN_BOX, "down box"}, {FL_BORDER_BOX, "border box"}, {FL_SHADOW_BOX, "shadow box"}, {FL_FLAT_BOX, "flat box"}, {FL_FRAME_BOX, "frame box"}, {FL_EMBOSSED_BOX, "embossed box"}, {FL_ROUNDED_BOX, "rounded box"}, {FL_RFLAT_BOX, "rflat box"}, {FL_RSHADOW_BOX, "rshadow box"}, // renamed for FLTK {FL_OVAL_BOX, "oval box"}, {FL_ROUNDED3D_UPBOX, "rounded3d upbox"}, {FL_ROUNDED3D_DOWNBOX, "rounded3d downbox"}, {FL_OVAL3D_UPBOX, "oval3d upbox"}, {FL_OVAL3D_DOWNBOX, "oval3d downbox"}, {FL_PLASTIC_UP_BOX, "plastic upbox"}, {FL_PLASTIC_DOWN_BOX, "plastic downbox"}, {FL_GTK_UP_BOX, "GTK up box"}, {FL_GTK_ROUND_UP_BOX, "GTK round up box"}, {FL_GLEAM_UP_BOX, "Gleam up box"}, /* sentinel */ {(Fl_Boxtype)(-1)} }; #include "pixmaps/sorceress.xbm" /*************** Callback **********************/ FL_FORM *form; Fl_Widget *tobj[18], *exitob, *btypeob, *modeob; void boxtype_cb(Fl_Widget *ob, long) { int i, req_bt = fl_get_choice(ob) - 1; static int lastbt = -1; if (lastbt != req_bt) { fl_freeze_form(form); fl_redraw_form(form); for (i = 0; i < 18; i++) fl_set_object_boxtype(tobj[i], btypes[req_bt].val); fl_unfreeze_form(form); lastbt = req_bt; fl_redraw_form(form); // added for FLTK } } void mode_cb(Fl_Widget *, long) { // empty } /*************** Creation Routines *********************/ void create_form_form(void) { Fl_Widget *obj; form = fl_bgn_form(FL_NO_BOX, 720, 520); obj = fl_add_box(FL_UP_BOX, 0, 0, 720, 520, ""); fl_set_object_color(obj, FL_BLUE, FL_COL1); obj = fl_add_box(FL_DOWN_BOX, 10, 90, 700, 420, ""); fl_set_object_color(obj, FL_COL1, FL_COL1); obj = fl_add_box(FL_DOWN_BOX, 10, 10, 700, 70, ""); fl_set_object_color(obj, FL_SLATEBLUE, FL_COL1); tobj[0] = obj = fl_add_box(FL_UP_BOX, 30, 110, 110, 110, "Box"); tobj[1] = obj = fl_add_text(FL_NORMAL_TEXT, 30, 240, 110, 30, "Text"); tobj[2] = obj = fl_add_bitmap(FL_NORMAL_BITMAP, 40, 280, 90, 80, "Bitmap"); fl_set_object_lcol(obj, FL_BLUE); tobj[3] = obj = fl_add_chart(FL_BAR_CHART, 160, 110, 160, 110, "Chart"); tobj[4] = obj = fl_add_clock(FL_ANALOG_CLOCK, 40, 390, 90, 90, "Clock"); // fl_set_object_dblbuffer(tobj[4],1); // removed for FLTK tobj[5] = obj = fl_add_button(FL_NORMAL_BUTTON, 340, 110, 120, 30, "Button"); tobj[6] = obj = fl_add_lightbutton(FL_PUSH_BUTTON, 340, 150, 120, 30, "Lightbutton"); tobj[7] = obj = fl_add_roundbutton(FL_PUSH_BUTTON, 340, 190, 120, 30, "Roundbutton"); tobj[8] = obj = fl_add_slider(FL_VERT_SLIDER, 160, 250, 40, 230, "Slider"); tobj[9] = obj = fl_add_valslider(FL_VERT_SLIDER, 220, 250, 40, 230, "Valslider"); tobj[10] = obj = fl_add_dial(FL_LINE_DIAL, 280, 250, 100, 100, "Dial"); tobj[11] = obj = fl_add_positioner(FL_NORMAL_POSITIONER, 280, 380, 150, 100, "Positioner"); tobj[12] = obj = fl_add_counter(FL_NORMAL_COUNTER, 480, 110, 210, 30, "Counter"); tobj[13] = obj = fl_add_input(FL_NORMAL_INPUT, 520, 170, 170, 30, "Input"); tobj[14] = obj = fl_add_menu(FL_PUSH_MENU, 400, 240, 100, 30, "Menu"); tobj[15] = obj = fl_add_choice(FL_NORMAL_CHOICE, 580, 250, 110, 30, "Choice"); tobj[16] = obj = fl_add_timer(FL_VALUE_TIMER, 580, 210, 110, 30, "Timer"); // fl_set_object_dblbuffer(tobj[16], 1); // removed for FLTK tobj[17] = obj = fl_add_browser(FL_NORMAL_BROWSER, 450, 300, 240, 180, "Browser"); exitob = obj = fl_add_button(FL_NORMAL_BUTTON, 590, 30, 100, 30, "Exit"); btypeob = obj = fl_add_choice(FL_NORMAL_CHOICE, 110, 30, 130, 30, "Boxtype"); fl_set_object_callback(obj, boxtype_cb, 0); modeob = obj = fl_add_choice(FL_NORMAL_CHOICE, 370, 30, 130, 30, "Graphics mode"); fl_set_object_callback(obj, mode_cb, 0); fl_end_form(); } /*---------------------------------------*/ void create_the_forms(void) { create_form_form(); } /*************** Main Routine ***********************/ const char *browserlines[] = { " ", "@C1@c@l@bObjects Demo", " ", "This demo shows you all", "objects that currently", "exist in the Forms Library.", " ", "You can change the boxtype", "of the different objects", "using the buttons at the top", "of the form. Note that some", "combinations might not", "look too good. Also realize", "that for all object classes", "many different types are", "available with different", "behaviour.", " ", "With this demo you can also", "see the effect of the drawing", "mode on the appearance of", "the objects.", 0 }; int main(int argc, char *argv[]) { FL_COLOR c = FL_BLACK; const char **p; VN_struct *vn; fl_initialize(&argc, argv, "FormDemo", 0, 0); create_the_forms (); fl_set_bitmap_data (tobj[2], sorceress_width, sorceress_height, sorceress_bits); fl_add_chart_value (tobj[3], 15, "item 1", c++); fl_add_chart_value (tobj[3], 5, "item 2", c++); fl_add_chart_value (tobj[3], -10, "item 3", c++); fl_add_chart_value (tobj[3], 25, "item 4", c++); fl_set_menu (tobj[14], "item 1|item 2|item 3|item 4|item 5"); fl_addto_choice (tobj[15], "item 1"); fl_addto_choice (tobj[15], "item 2"); fl_addto_choice (tobj[15], "item 3"); fl_addto_choice (tobj[15], "item 4"); fl_addto_choice (tobj[15], "item 5"); fl_set_timer (tobj[16], 1000.0); for (p = browserlines; *p; p++) fl_add_browser_line(tobj[17], *p); for (vn = btypes; vn->val >= 0; vn++) fl_addto_choice(btypeob, vn->name); fl_show_form(form, FL_PLACE_MOUSE, border, "Box types"); while (fl_do_forms() != exitob) ; return 0; } #else // (!FLTK_HAVE_FORMS) #include int main(int argc, char **argv) { fl_message_title("This program needs the Forms compatibility library"); fl_message( "Please configure FLTK with Forms enabled (--enable-forms)\n" "or the CMake option FLTK_BUILD_FORMS=ON."); return 0; } #endif // (FLTK_HAVE_FORMS) fltk-1.4.3/test/arc.cxx0000644000175000017500000000421715004135251015061 0ustar albrechtalbrecht// // Arc drawing test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2015 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include double args[6] = {140, 140, 50, 0, 360, 0}; const char* name[6] = {"X", "Y", "R", "start", "end", "rotate"}; class Drawing : public Fl_Widget { void draw() FL_OVERRIDE { fl_push_clip(x(),y(),w(),h()); fl_color(FL_DARK3); fl_rectf(x(),y(),w(),h()); fl_push_matrix(); if (args[5]) { fl_translate(x()+w()/2.0, y()+h()/2.0); fl_rotate(args[5]); fl_translate(-(x()+w()/2.0), -(y()+h()/2.0)); } fl_color(FL_WHITE); fl_translate(x(),y()); fl_begin_complex_polygon(); fl_arc(args[0],args[1],args[2],args[3],args[4]); fl_gap(); fl_arc(140,140,20,0,-360); fl_end_complex_polygon(); fl_color(FL_RED); fl_begin_line(); fl_arc(args[0],args[1],args[2],args[3],args[4]); fl_end_line(); fl_pop_matrix(); fl_pop_clip(); } public: Drawing(int X,int Y,int W,int H) : Fl_Widget(X,Y,W,H) {} }; Drawing *d; void slider_cb(Fl_Widget* o, void* v) { Fl_Slider* s = (Fl_Slider*)o; args[fl_intptr_t(v)] = s->value(); d->redraw(); } int main(int argc, char** argv) { Fl_Double_Window window(300,500); Drawing drawing(10,10,280,280); d = &drawing; int y = 300; for (int n = 0; n<6; n++) { Fl_Slider* s = new Fl_Hor_Value_Slider(50,y,240,25,name[n]); y += 25; if (n<3) {s->minimum(0); s->maximum(300);} else if (n==5) {s->minimum(0); s->maximum(360);} else {s->minimum(-360); s->maximum(360);} s->step(1); s->value(args[n]); s->align(FL_ALIGN_LEFT); s->callback(slider_cb, (void*)(fl_intptr_t)n); } window.end(); window.show(argc,argv); return Fl::run(); } fltk-1.4.3/test/demo.cxx0000644000175000017500000004613315004135251015243 0ustar albrechtalbrecht// // Main demo program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* General information on directory structure and file handling. The "classic" autotools/make system creates executables in their source folders, i.e. fluid/fluid, test/demo and test/xyz, resp.. The menu file is in folder test/, as is the main demo(.exe) program. In the following text and directory lists all test and demo executables are represented by "demo" and the fluid executable by "fluid", no matter what OS (under Windows: *.exe). The CMake build system generates all executables in the build tree and copies the supporting test data files to the build tree as well. This structure is different and needs to be handled separately in this program. Additionally, different OS platforms create different types of files, for instance "app bundles" on macOS. All this needs to be considered. The overall structure, relative to the FLTK source dir (fltk) and the build tree (build): (1) Autotools / Make: fltk/fluid fluid (../fluid/fluid) fltk/test demo, demo.menu, working directory, data files fltk/test/images images for help_dialog(.html) (2) CMake + make (e.g. Unix) build/bin fluid build/bin/test test and demo programs build/data demo.menu, working directory, data files build/data/images images for help_dialog(.html) (3) CMake + Visual Studio (TYPE == build type: Debug, Release, ...) build/bin/TYPE fluid build/bin/test/TYPE test and demo programs build/data demo.menu, working directory, data files build/data/images images for help_dialog(.html) (4) macOS The setup is similar to Windows and Linux: Makefiles: like (1) or (2) Xcode: like (3), i.e. similar to VS layout The built executable 'demo' can also be executed with the menu filename as commandline argument. In this case all the support (data) files are expected to be in the same directory as the menu file or relative paths as needed by the test programs, for instance help_dialog which needs help_dialog.html and related image files. */ #include #include #include #include #include #include #include #include #include // right click popup menu #include #include // tty #include #include #include // fl_alert() #include // fl_getcwd() // Define USE_MAC_OS for convenience (below). We use macOS specific features (bundles // and paths) if USE_MAC_OS is defined, otherwise we're using X11 (XQuartz) on macOS #if defined __APPLE__ && !defined(FLTK_USE_X11) #define USE_MAC_OS #include #endif #define FORM_W 350 #define FORM_H 440 #define TTY_W 780 #define TTY_H 200 /* The form description */ void doexit(Fl_Widget *, void *); void doback(Fl_Widget *, void *); void dobut(Fl_Widget *, long); Fl_Double_Window *form = 0; Fl_Group *demogrp = 0; Fl_Terminal *tty = 0; Fl_Scheme_Choice *scheme_choice = 0; Fl_Button *but[9]; Fl_Button *exit_button; // Allocate space to edit commands and arguments from demo.menu. // We "trust demo.menu" that strings don't overflow char cmdbuf[256]; // commandline w/o arguments char params[256]; // commandline arguments // Global path variables for all platforms and build systems // to avoid duplication and dynamic allocation char app_path [FL_PATH_MAX]; // directory of all demo binaries char fluid_path [FL_PATH_MAX]; // binary directory of fluid char options_path [FL_PATH_MAX]; // binary directory of fltk-options char data_path [FL_PATH_MAX]; // working directory of all demos char command [2 * FL_PATH_MAX + 40]; // command to be executed // platform specific suffix for executable files #ifdef _WIN32 const char *suffix = ".exe"; #elif defined USE_MAC_OS const char *suffix = ".app"; #else const char *suffix = ""; #endif // CMake defines the "build type" subdirectory for multi configuration // build setups like Visual Studio and Xcode #ifdef CMAKE_INTDIR const char *cmake_intdir = "/" CMAKE_INTDIR; #else const char *cmake_intdir = 0; #endif // debug output function void debug_var(const char *varname, const char *value) { tty->printf("%-10s = %s\n", varname, value); } // Show or hide the tty window. Generally this could be much simpler // but the extra space (10 px) at the bottom needs "special care" void show_tty(int val) { if (val) { tty->show(); // show debug terminal form->size_range(FORM_W, FORM_H + TTY_H/2, 0, 0); // allow resizing form->size(TTY_W + 20, FORM_H + TTY_H + 10); // demo + height for tty + space (10) tty->size(TTY_W, TTY_H); // force tty size } else { tty->hide(); // hide debug terminal form->size_range(FORM_W, FORM_H, FORM_W, FORM_H); // no resizing form->size(FORM_W, FORM_H); // normal demo size tty->resize(10, FORM_H - 1, FORM_W - 20, 1); // restore original position and size } form->init_sizes(); exit_button->take_focus(); } // Right click popup menu handler (1 = show, 0 = hide) void popup_menu_cb(Fl_Widget*, void *userdata) { show_tty(fl_int(userdata)); } void create_the_forms() { Fl_Widget *obj; Fl_Menu_Button *popup; form = new Fl_Double_Window(FORM_W, FORM_H, "FLTK Demonstration"); // Parent group for demo demogrp = new Fl_Group(0, 0, FORM_W, FORM_H - 1); // Top demo button obj = new Fl_Box(FL_FRAME_BOX, 10, 15, 330, 40, "FLTK Demonstration"); obj->color(FL_GRAY-4); obj->labelsize(24); obj->labelfont(FL_BOLD); obj->labeltype(FL_ENGRAVED_LABEL); obj = new Fl_Box(FL_FRAME_BOX, 10, 65, 330, 330, 0); obj->color(FL_GRAY-8); scheme_choice = new Fl_Scheme_Choice(90, 405, 100, 25, "Scheme:"); scheme_choice->labelfont(FL_HELVETICA_BOLD); exit_button = new Fl_Button(280, 405, 60, 25, "Exit"); exit_button->callback(doexit); exit_button->take_focus(); obj = new Fl_Button(10, 15, 330, 380); obj->type(FL_HIDDEN_BUTTON); obj->callback(doback); obj->tooltip("Use right mouse button to show/hide debug terminal"); but[0] = new Fl_Button( 30, 85,90,90); but[1] = new Fl_Button(130, 85,90,90); but[2] = new Fl_Button(230, 85,90,90); but[3] = new Fl_Button( 30,185,90,90); but[4] = new Fl_Button(130,185,90,90); but[5] = new Fl_Button(230,185,90,90); but[6] = new Fl_Button( 30,285,90,90); but[7] = new Fl_Button(130,285,90,90); but[8] = new Fl_Button(230,285,90,90); for (int i=0; i<9; i++) { but[i]->align(FL_ALIGN_WRAP); but[i]->callback(dobut, i); } // Right click popup menu (inside demogrp) popup = new Fl_Menu_Button(0,0,FORM_W,FORM_H); popup->box(FL_NO_BOX); popup->type(Fl_Menu_Button::POPUP3); // pop menu on right-click popup->add("Show debug terminal", 0, popup_menu_cb, (void*)1); popup->add("Hide debug terminal", 0, popup_menu_cb, (void*)0); // The resizable box of 'demogrp' ensures that the demo form is not resized // if the user resizes the window while the debug terminal (tty) is shown obj = new Fl_Box(FORM_W - 1, 0, 1, FORM_H); obj->box(FL_NO_BOX); demogrp->resizable(obj); demogrp->end(); // Small debug terminal window parented to window, not demogrp // To show/hide debug terminal, use demo's right-click menu // tty = new Fl_Terminal(10, FORM_H - 1, FORM_W - 20, 1); tty->history_lines(50); tty->display_rows(2); // make display at least 2 rows high, even if not seen tty->display_columns(100); // make display at least 100 cols wide, even if not seen tty->ansi(true); tty->hide(); tty->textsize(12); // End window form->end(); form->resizable(tty); // Note: do not set size_range() before show() or window can't be made resizable // later (macOS and Windows only, works on Linux though) // form->size_range(FORM_W, FORM_H, FORM_W, FORM_H); } /* Maintaining and building up the menus. */ typedef struct { char name[64]; int numb; char iname[9][64]; char icommand[9][64]; } MENU; #define MAXMENU 32 MENU menus[MAXMENU]; int mennumb = 0; /* Return the number of a given menu name. */ int find_menu(const char* nnn) { int i; for (i=0; ihide(); for (i=0; ishow(); but[bn]->label(menus[men].iname[i]); if (menus[men].icommand[i][0] != '@') but[bn]->tooltip(menus[men].icommand[i]); else but[bn]->tooltip(0); } if (stack[stsize]!=nnn) strcpy(stack[stsize],nnn); stsize++; } /* Pop a menu */ void pop_menu() { if (stsize<=1) return; stsize -= 2; push_menu(stack[stsize]); } /* The callback Routines */ /* Handle a button push */ void dobut(Fl_Widget *, long arg) { int men = find_menu(stack[stsize-1]); int n = menus[men].numb; int bn = but2numb( (int) arg, n-1); // menu ? if (menus[men].icommand[bn][0] == '@') { push_menu(menus[men].icommand[bn]); return; } // not a menu: run test/demo/fluid executable // find and separate "command" and "params" // skip leading spaces in command char *start_command = menus[men].icommand[bn]; while (*start_command == ' ') ++start_command; strcpy(cmdbuf, start_command); // here still full command w/params // find the space between the command and parameters if one exists char *start_params = strchr(cmdbuf, ' '); if (start_params) { *start_params = '\0'; // terminate command start_params++; // skip space strcpy(params, start_params); // copy parameters } else { params[0] = '\0'; // empty string } // select application path: either app_path or fluid_path const char *path = app_path; if (!strncmp(cmdbuf, "fluid", 5)) path = fluid_path; else if (!strncmp(cmdbuf, "fltk-options", 5)) path = options_path; // format commandline with optional parameters #if defined(USE_MAC_OS) // macOS if (params[0]) { // we assume that we have only one argument which is a filename in 'data_path' snprintf(command, sizeof(command), "open '%s/%s%s' --args '%s/%s'", path, cmdbuf, suffix, data_path, params); } else { snprintf(command, sizeof(command), "open '%s/%s%s'", path, cmdbuf, suffix); } #else // other platforms if (params[0]) snprintf(command, sizeof(command), "%s/%s%s %s", path, cmdbuf, suffix, params); else snprintf(command, sizeof(command), "%s/%s%s", path, cmdbuf, suffix); #endif // finally, execute program (the system specific part) #ifdef _WIN32 STARTUPINFO suInfo; // Process startup information PROCESS_INFORMATION prInfo; // Process information memset(&suInfo, 0, sizeof(suInfo)); suInfo.cb = sizeof(suInfo); debug_var("Command", command); BOOL stat = CreateProcess(NULL, command, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &suInfo, &prInfo); if (!stat) { DWORD err = GetLastError(); fl_alert("Error starting process, error #%lu\n'%s'", err, command); } #elif defined USE_MAC_OS debug_var("Command", command); system(command); #else // other platforms (Unix, Linux, X11, and XQuartz on macOS) strcat(command, " &"); // run in background debug_var("Command", command); if (system(command) == -1) { fl_alert("Could not start program, errno = %d\n'%s'", errno, command); } #endif // _WIN32 } void doback(Fl_Widget *, void *) {pop_menu();} void doexit(Fl_Widget *, void *) {exit(0);} /* Load the menu file. Returns whether successful. */ int load_the_menu(const char * const menu) { FILE *fin = 0; char line[256], mname[64],iname[64],cname[64]; int i, j; fin = fl_fopen(menu, "r"); if (fin == NULL) return 0; for (;;) { if (fgets(line,256,fin) == NULL) break; // remove all carriage returns that Cygwin may have inserted char *s = line, *d = line; for (;;++d) { while (*s=='\r') s++; *d = *s++; if (!*d) break; } // interpret the line j = 0; i = 0; while (line[i] == ' ' || line[i] == '\t') i++; if (line[i] == '\n') continue; if (line[i] == '#') continue; while (line[i] != ':' && line[i] != '\n') mname[j++] = line[i++]; mname[j] = '\0'; if (line[i] == ':') i++; j = 0; while (line[i] != ':' && line[i] != '\n') { if (line[i] == '\\') { i++; if (line[i] == 'n') iname[j++] = '\n'; else iname[j++] = line[i]; i++; } else iname[j++] = line[i++]; } iname[j] = '\0'; if (line[i] == ':') i++; j = 0; while (line[i] != ':' && line[i] != '\n') cname[j++] = line[i++]; cname[j] = '\0'; addto_menu(mname,iname,cname); } fclose(fin); return 1; } // Fix '\' in Windows paths (convert to '/') and cut off filename (optional, default) void fix_path(char *path, int strip_filename = 1) { if (!path[0]) return; #ifdef _WIN32 // convert '\' to '/' char *p = path; while (*p) { if (*p == '\\') *p = '/'; p++; } #endif // _WIN32 if (strip_filename) { char *pos = strrchr(path, '/'); if (pos) *pos = 0; } } int main(int argc, char **argv) { fl_putenv("FLTK_DOCDIR=../documentation/html"); // used by fluid char menu[FL_PATH_MAX]; // construct app_path for all executable files fl_filename_absolute(app_path, sizeof(app_path), argv[0]); #if defined(USE_MAC_OS) char *q = strstr(app_path, "/Contents/MacOS/"); if (q) *q = 0; #endif fix_path(app_path); // fluid's path is relative to app_path: // - "../fluid" for autoconf/make builds // - ".." (parent directory) for single configuration CMake builds // - "../../$CMAKE_INTDIR" for multi-config (Visual Studio or Xcode) CMake builds strcpy(fluid_path, app_path); strcpy(options_path, app_path); if (cmake_intdir) { fix_path(fluid_path); // remove intermediate (build type) folder, e.g. "/Debug" fix_path(options_path); } fix_path(fluid_path); // remove folder name ("test") fix_path(options_path); #if !defined(GENERATED_BY_CMAKE) strcat(fluid_path, "/fluid"); strcat(options_path, "/fltk-options"); #else // CMake: potentially Visual Studio or Xcode (multi config) if (cmake_intdir) { strcat(fluid_path, cmake_intdir); // append e.g. "/Debug" strcat(options_path, cmake_intdir); } #endif // GENERATED_BY_CMAKE // construct data_path for the menu file and all resources (data files) // CMake: replace "/bin/test/*" with "/data" // autotools: use app_path directly strcpy(data_path, app_path); #if defined(GENERATED_BY_CMAKE) { char *pos = strstr(data_path, "/bin/test"); if (pos) strcpy(pos, "/data"); } #endif // GENERATED_BY_CMAKE // Construct the menu file name, optionally overridden by command args. // Use data_path and append "/.menu" const char *fn = fl_filename_name(argv[0]); strcpy(menu, data_path); strcat(menu, "/"); strcat(menu, fn); fl_filename_setext(menu, sizeof(menu), ".menu"); // parse commandline int i = 0; Fl::args_to_utf8(argc, argv); // for MSYS2/MinGW if (!Fl::args(argc, argv, i) || i < argc-1) Fl::fatal("Usage: %s \n%s", argv[0], Fl::help); if (i < argc) { // override menu file *and* data path ! fl_filename_absolute(menu, sizeof(menu), (const char *)argv[i]); strcpy(data_path, menu); fix_path(data_path); } // set current work directory to 'data_path' if (fl_chdir(data_path) == -1) { /* ignore */ } // Create forms first // tty needs to exist before we can print debug msgs // create_the_forms(); { char cwd[1024]; fl_getcwd(cwd, sizeof(cwd)); fix_path(cwd, 0); debug_var("app_path", app_path); debug_var("fluid_path", fluid_path); debug_var("options_path", options_path); debug_var("data_path", data_path); debug_var("menu file", menu); debug_var("cwd", cwd); tty->printf("\n"); } if (!load_the_menu(menu)) Fl::fatal("Can't open menu file '%s'", menu); push_menu("@main"); form->show(argc, argv); // set size_range() after show() so the window can be resizable (Win + macOS) form->size_range(FORM_W, FORM_H, FORM_W, FORM_H); #if (0) // DEBUG (remove after testing) { const char *const *scheme_names = Fl_Scheme_Choice::scheme_names(); int ni = 0; while (scheme_names[ni]) { printf("scheme[%2d] = '%s'\n", ni, scheme_names[ni]); ni++; } } #endif // End of debug and test statements Fl::run(); return 0; } fltk-1.4.3/test/inactive.fl0000644000175000017500000000631415004135251015715 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} Function {} {open } { Fl_Window {} {open xywh {462 303 420 369} type Double resizable visible } { Fl_Group the_group { label {activate()/deactivate() called on this Fl_Group} open xywh {25 25 375 295} box ENGRAVED_FRAME align 17 resizable } { Fl_Button {} { label button xywh {50 50 105 20} } Fl_Light_Button {} { label {light button} xywh {50 75 105 20} value 1 align 16 } Fl_Group {} {open xywh {50 100 105 20} } { Fl_Button {} { label On selected xywh {50 100 52 20} type Radio value 1 compact 1 } Fl_Button {} { label Off selected xywh {102 100 53 20} type Radio compact 1 } } Fl_Group {} { label {Child group} open xywh {50 150 105 105} box DOWN_FRAME } { Fl_Check_Button {} { label red xywh {54 192 97 20} type Radio down_box DIAMOND_DOWN_BOX selection_color 1 labelcolor 1 } Fl_Check_Button {} { label green xywh {54 212 97 20} type Radio down_box DIAMOND_DOWN_BOX selection_color 2 labelcolor 2 } Fl_Check_Button {} { label blue xywh {54 232 97 20} type Radio down_box DIAMOND_DOWN_BOX selection_color 4 labelcolor 4 } Fl_Check_Button {} { label check xywh {54 152 97 20} down_box DOWN_BOX } Fl_Round_Button {} { label round xywh {54 172 97 20} down_box ROUND_DOWN_BOX } } Fl_Slider {} { label Fl_Slider xywh {165 50 24 205} value 0.5 } Fl_Input {} { xywh {195 50 195 30} code0 {o->static_value("Fl_Input");} } Fl_Menu_Button {} { label menu open xywh {245 90 130 30} } { MenuItem {} { label item xywh {0 0 100 20} } MenuItem {} { label item xywh {10 10 100 20} } MenuItem {} { label item xywh {20 20 100 20} } MenuItem {} { label item xywh {30 30 100 20} } MenuItem {} { label item xywh {40 40 100 20} } } Fl_Value_Output {} { label {value:} xywh {245 130 130 30} maximum 10000 step 1 textfont 5 textsize 24 textcolor 4 } Fl_Box {} { label Fl_Box xywh {245 170 140 50} box EMBOSSED_FRAME labeltype SHADOW_LABEL labelfont 3 labelsize 38 } Fl_Scrollbar {} { label scrollbar xywh {40 274 180 20} type Horizontal } Fl_Roller {} { label roller xywh {235 230 25 65} } Fl_Dial {} { label dial xywh {275 235 50 50} } Fl_Clock {} { label clock xywh {335 235 50 50} } } Fl_Button {} { label active callback {the_group->activate();} xywh {25 330 185 25} type Radio value 1 } Fl_Button {} { label inactive callback {the_group->deactivate();} xywh {220 330 180 25} type Radio } } } fltk-1.4.3/test/resize-example3a.cxx0000644000175000017500000000717115004135251017474 0ustar albrechtalbrecht// // Resize example for use in the Fast Light Tool Kit (FLTK) documentation. // // See Article #415: How does resizing work? // https://www.fltk.org/articles.php?L415 // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "resize-arrows.h" #include #include // resize dialog and arrow dimensions int TLx = 35, TRx = 270, TGx = 470, TLw = 200, TGw = 120, TAw = 35; int TLy = 35, BLy = 160, LGy = 250, TLh = 90, LGh = 90, LAh = 35; // window dimensions int Ww = 590, Wh = 340; Fl_Double_Window *window; class ResizeDialog : public Fl_Group { public: ResizeDialog(int X, int Y, int W, int H, const char *T = 0); Fl_Box *m_icon; Fl_Box *m_message; Fl_Button *m_button; }; ResizeDialog::ResizeDialog(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->align(FL_ALIGN_TOP_LEFT); this->box(FL_UP_BOX); m_icon = new Fl_Box(X + 10, Y + 10, 30, 30, "!"); m_icon->box(FL_DOWN_BOX); m_icon->color(FL_YELLOW); m_message = new Fl_Box(X + 50, Y + 10, 140, 30, "Out of Memory"); m_message->box(FL_DOWN_BOX); m_button = new Fl_Button(X + 140, Y + 50, 50, 30, "Darn!"); this->end(); this->resizable(m_icon); } class Resizables : public Fl_Group { public: Resizables(int X, int Y, int W, int H, const char *T = 0); ResizeDialog *TL, *TR, *BL, *BR; // topleft, topright, bottomleft, bottomright Harrow *LA, *RA; // left arrow, right arrow Varrow *TA, *BA; // top arrow, bottom arrow }; Resizables::Resizables(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->box(FL_UP_BOX); this->color(FL_WHITE); TL = new ResizeDialog(X + TLx, Y + TLy, TLw, TLh, "Original Size"); TL->resizable(0); TR = new ResizeDialog(X + TRx, Y + TLy, TLw, TLh, "Horizontally Resized"); BL = new ResizeDialog(X + TLx, Y + BLy, TLw, TLh, "Vertically Resized"); BR = new ResizeDialog(X + TRx, Y + BLy, TLw, TLh, "Horizontally and Vertically Resized"); Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); LG->box(FL_NO_BOX); LG->color(FL_WHITE); LA = new Harrow(BL->m_icon->x(), LG->y(), BL->m_icon->w(), LAh, "Initial\nwidth"); LG->resizable(LA); LG->end(); Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); RG->box(FL_NO_BOX); RG->color(FL_WHITE); RA = new Harrow(BR->m_icon->x(), LG->y(), BL->m_icon->w(), LAh, "Resized\nwidth"); RG->resizable(RA); RG->end(); Fl_Group *TG = new Fl_Group(X + TGx, Y + TLy, TGw, TLh); TG->box(FL_NO_BOX); TG->color(FL_WHITE); TA = new Varrow(TG->x(), TR->m_icon->y(), TAw, TR->m_icon->h(), "Initial\nheight"); TG->resizable(TA); TG->end(); Fl_Group *BG = new Fl_Group(X + TGx, Y + BLy, TGw, TLh); BG->box(FL_NO_BOX); BG->color(FL_WHITE); BA = new Varrow(BG->x(), BR->m_icon->y(), TAw, BR->m_icon->h(), "Resized\nheight"); BG->resizable(BA); BG->end(); this->resizable(BR); this->end(); } int main(int argc, char **argv) { window = new Fl_Double_Window(Ww, Wh, "resize-example3a"); window->color(FL_WHITE); Resizables *resizables = new Resizables(0, 0, Ww, Wh); window->end(); window->resizable(resizables); window->size_range(Ww, Wh); window->show(argc, argv); window->size(Ww + 50, Wh + 35); Fl::visible_focus(0); // suppress focus box return Fl::run(); } fltk-1.4.3/test/unittests.h0000644000175000017500000002053115004135251016000 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef UNITTESTS_H #define UNITTESTS_H 1 #include #include #include class Fl_Terminal; // WINDOW/WIDGET SIZES const int UT_MAINWIN_W = 700; // main window w() const int UT_MAINWIN_H = 600; // main window h() const int UT_BROWSER_X = 10; // browser x() const int UT_BROWSER_Y = 25; // browser y() const int UT_BROWSER_W = 150; // browser w() const int UT_BROWSER_H = (UT_MAINWIN_H-35); // browser h() const int UT_TESTAREA_X = (UT_BROWSER_W + 20); // test area x() const int UT_TESTAREA_Y = 25; // test area y() const int UT_TESTAREA_W = (UT_MAINWIN_W - UT_BROWSER_W - 30); // test area w() const int UT_TESTAREA_H = UT_BROWSER_H; // test area h() typedef void (*UnitTestCallback)(const char*, class Fl_Group*); extern class Ut_Main_Window* mainwin; extern class Fl_Hold_Browser* browser; enum { UT_TEST_ABOUT = 0, UT_TEST_POINTS, UT_TEST_FAST_SHAPES, UT_TEST_CIRCLES, UT_TEST_COMPLEX_SHAPES, UT_TEST_TEXT, UT_TEST_UNICODE, UT_TEST_SYBOL, UT_TEST_IMAGES, UT_TEST_VIEWPORT, UT_TEST_SCROLLBARSIZE, UT_TEST_SCHEMES, UT_TEST_SIMPLE_TERMINAL, UT_TEST_CORE }; // This class helps to automatically register a new test with the unittest app. // Please see the examples on how this is used. class UnitTest { public: UnitTest(int index, const char *label, Fl_Widget* (*create)()); ~UnitTest(); const char* label(); void create(); void show(); void hide(); static int num_tests() { return num_tests_; } static UnitTest* test(int i) { return test_list_[i]; } private: char* label_; Fl_Widget* (*create_)(); Fl_Widget* widget_; static void add(int index, UnitTest* t); static int num_tests_; static UnitTest* test_list_[]; }; // The following classes and macros implement a subset of the Google Test API // without creating any external dependencies. // // There is nothing to initialise or set up. Just by including these classes, // we can create tests anywhere inside the app by simply writing: // // TEST(Math, Addition) { // EXPECT_EQ(3+3, 6); // return true; // } // TEST(Math, Multiplication) { // EXPECT_EQ(3*3, 9); // return true; // } // RUN_ALL_TESTS(); // // The test suite must only be run once. typedef bool (*Ut_Test_Call)(); /** Implement a single test which can in turn contain many EXPECT_* macros. Ut_Test classes are automatically created using the TEST(suite_name, test_name) macro. Tests with identical suite names are grouped into a single suite. */ class Ut_Test { friend class Ut_Suite; const char *name_; Ut_Test_Call call_; bool failed_; bool done_; public: Ut_Test(const char *suitename, const char *testname, Ut_Test_Call call); bool run(const char *suite); void print_failed(const char *suite); }; /** Implement test registry and the grouping of tests into a suite. This class holds a number of static elements that register an arbitrary number of tests and groups them into suites via the TEST() macro. */ class Ut_Suite { static Ut_Suite **suite_list_; static int suite_list_size_; static int num_tests_; static int num_passed_; static int num_failed_; Ut_Test **test_list_; int test_list_size_; const char *name_; bool done_; Ut_Suite(const char *name); public: void add(Ut_Test *test); int size() { return test_list_size_; } int run(); void print_suite_epilog(); void print_failed(); static Ut_Suite *locate(const char *name); static int run_all_tests(); static bool run_next_test(); static void printf(const char *format, ...); static void log_bool(const char *file, int line, const char *cond, bool result, bool expected); static void log_string(const char *file, int line, const char *cond, const char *result, const char *expected); static void log_int(const char *file, int line, const char *cond, int result, const char *expected); static void print_prolog(); static void print_epilog(); static void color(int); static int failed() { return num_failed_; } static const char *red; static const char *green; static const char *normal; static Fl_Terminal *tty; }; #define UT_CONCAT_(prefix, suffix) prefix##suffix #define UT_CONCAT(prefix, suffix) UT_CONCAT_(prefix, suffix) /** Create a test function and register it with the test suites. \param[in] SUITE naming of the test suite for grouping \param[in] CASE name this test */ #define TEST(SUITE, CASE) \ static bool UT_CONCAT(test_call_, __LINE__)(); \ Ut_Test UT_CONCAT(test__, __LINE__)(#SUITE, #CASE, UT_CONCAT(test_call_, __LINE__)); \ static bool UT_CONCAT(test_call_, __LINE__)() /** Create a test case where the result is expected to be a boolena with the value true */ #define EXPECT_TRUE(COND) \ bool UT_CONCAT(cond, __LINE__) = COND; \ if (UT_CONCAT(cond, __LINE__) != true) { \ Ut_Suite::log_bool(__FILE__, __LINE__, #COND, UT_CONCAT(cond, __LINE__), true); \ return false; \ } /** Create a test case for string comparison. NULL is ok for both arguments. */ #define EXPECT_STREQ(A, B) \ const char *UT_CONCAT(a, __LINE__) = A; \ const char *UT_CONCAT(b, __LINE__) = B; \ if ( (UT_CONCAT(a, __LINE__)==NULL && UT_CONCAT(b, __LINE__)!=NULL) \ || (UT_CONCAT(a, __LINE__)!=NULL && UT_CONCAT(b, __LINE__)==NULL) \ || (UT_CONCAT(b, __LINE__)!=NULL && strcmp(UT_CONCAT(a, __LINE__), UT_CONCAT(b, __LINE__))!=0) ) { \ Ut_Suite::log_string(__FILE__, __LINE__, #A, UT_CONCAT(a, __LINE__), #B); \ return false; \ } /** Create a test case for integer comparison. */ #define EXPECT_EQ(A, B) \ int UT_CONCAT(a, __LINE__) = A; \ int UT_CONCAT(b, __LINE__) = B; \ if (UT_CONCAT(a, __LINE__) != UT_CONCAT(b, __LINE__)) { \ Ut_Suite::log_int(__FILE__, __LINE__, #A, UT_CONCAT(a, __LINE__), #B); \ return false; \ } /** Create a test case for integer comparison. */ #define EXPECT_NE(A, B) \ int UT_CONCAT(a, __LINE__) = A; \ int UT_CONCAT(b, __LINE__) = B; \ if (UT_CONCAT(a, __LINE__) == UT_CONCAT(b, __LINE__)) { \ Ut_Suite::log_int(__FILE__, __LINE__, #A, UT_CONCAT(a, __LINE__), #B); \ return false; \ } /** Create a test case for integer comparison. */ #define EXPECT_LT(A, B) \ int UT_CONCAT(a, __LINE__) = A; \ int UT_CONCAT(b, __LINE__) = B; \ if (UT_CONCAT(a, __LINE__) >= UT_CONCAT(b, __LINE__)) { \ Ut_Suite::log_int(__FILE__, __LINE__, #A, UT_CONCAT(a, __LINE__), #B); \ return false; \ } /** Create a test case for integer comparison. */ #define EXPECT_LE(A, B) \ int UT_CONCAT(a, __LINE__) = A; \ int UT_CONCAT(b, __LINE__) = B; \ if (UT_CONCAT(a, __LINE__) > UT_CONCAT(b, __LINE__)) { \ Ut_Suite::log_int(__FILE__, __LINE__, #A, UT_CONCAT(a, __LINE__), #B); \ return false; \ } /** Create a test case for integer comparison. */ #define EXPECT_GT(A, B) \ int UT_CONCAT(a, __LINE__) = A; \ int UT_CONCAT(b, __LINE__) = B; \ if (UT_CONCAT(a, __LINE__) <= UT_CONCAT(b, __LINE__)) { \ Ut_Suite::log_int(__FILE__, __LINE__, #A, UT_CONCAT(a, __LINE__), #B); \ return false; \ } /** Create a test case for integer comparison. */ #define EXPECT_GE(A, B) \ int UT_CONCAT(a, __LINE__) = A; \ int UT_CONCAT(b, __LINE__) = B; \ if (UT_CONCAT(a, __LINE__) < UT_CONCAT(b, __LINE__)) { \ Ut_Suite::log_int(__FILE__, __LINE__, #A, UT_CONCAT(a, __LINE__), #B); \ return false; \ } /** Run all registered suits and their tests, and return the number of failed tests. */ #define RUN_ALL_TESTS() \ Ut_Suite::run_all_tests() // The main window needs an additional drawing feature in order to support // the viewport alignment test. class Ut_Main_Window : public Fl_Double_Window { public: Ut_Main_Window(int w, int h, const char *l=0L); void draw_alignment_indicators(); void draw() FL_OVERRIDE; void test_alignment(int v); private: int draw_alignment_test_; }; #endif fltk-1.4.3/test/fast_slow.fl0000644000175000017500000000230515004135251016110 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} Function {} {open } { Fl_Window {} {open selected xywh {397 202 318 443} type Double resizable visible } { Fl_Slider control { label {move this} callback {fast->value(o->value()); if (!Fl::pushed()) slow->value(o->value());} xywh {90 200 30 200} code0 {o->when(FL_WHEN_CHANGED|FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED);} } Fl_Slider fast { label {fast redraw} xywh {140 200 30 200} code0 {o->set_output();} } Fl_Slider slow { label {slow redraw} xywh {190 200 30 200} code0 {o->set_output();} } Fl_Box {} { label {The left slider has changed( FL_WHEN_CHANGED | FL_WHEN_RELEASE | FL_WHEN_NOT_CHANGED) so it produces a callback on both drag and release mouse events. The middle slider (representing a widget with low overhead) is changed on every mouse movement. The right slider (representing a widget with high overhead) is only updated when the mouse is released, by checking if Fl::pushed() is zero.} xywh {10 10 300 180} box DOWN_BOX color 53 selection_color 47 labelfont 4 labelsize 12 align 148 } } } fltk-1.4.3/test/resize-example4a.cxx0000644000175000017500000000566215004135251017500 0ustar albrechtalbrecht// // Resize example for use in the Fast Light Tool Kit (FLTK) documentation. // // See Article #415: How does resizing work? // https://www.fltk.org/articles.php?L415 // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "resize-arrows.h" #include // window, simplex and arrow dimensions int TLx = 35, TRx = 320, TLw = 260, Ww = 620; int TLy = 35, LGy = 100, TLh = 65, LGh = 70, LAh = 35, Wh = 200; Fl_Double_Window *window = 0; class Simplex : public Fl_Group { public: Simplex(int X, int Y, int W, int H, const char *T = 0); Fl_Box *m_button1, *m_input1, *m_button2, *m_input2; }; Simplex::Simplex(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->box(FL_UP_BOX); Fl_Group *group = new Fl_Group(X + 10, Y + 10, 240, 45); group->box(FL_NO_BOX); m_button1 = new Fl_Box(X + 20, Y + 20, 40, 25, "btn"); m_button1->box(FL_UP_BOX); m_input1 = new Fl_Box(X + 70, Y + 20, 50, 25, "input"); m_input1->box(FL_UP_BOX); m_button2 = new Fl_Box(X + 140, Y + 20, 40, 25, "btn"); m_button2->box(FL_UP_BOX); m_input2 = new Fl_Box(X + 190, Y + 20, 50, 25, "input"); m_input2->box(FL_UP_BOX); m_input2->color(FL_YELLOW); group->resizable(m_input2); group->end(); this->resizable(group); this->end(); } class Resizables : public Fl_Group { public: Resizables(int X, int Y, int W, int H, const char *T = 0); Simplex *TL, *TR; // top left, top right Harrow *LA, *RA; // left arrow, right arrow }; Resizables::Resizables(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { TL = new Simplex(X + TLx, Y + TLy, TLw, TLh, "Original"); TL->align(FL_ALIGN_TOP_LEFT); TR = new Simplex(X + TRx, Y + TLy, TLw, TLh, "Horizonally Resized"); TR->align(FL_ALIGN_TOP_LEFT); Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); LG->box(FL_NO_BOX); LG->color(FL_WHITE); LA = new Harrow(TL->m_input2->x(), LG->y(), TL->m_input2->w(), LAh, "Initial\nwidth"); LG->resizable(LA); LG->end(); Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); RG->box(FL_NO_BOX); RG->color(FL_WHITE); RA = new Harrow(TR->m_input2->x(), RG->y(), TR->m_input2->w(), LAh, "Resized\nwidth"); RG->resizable(RA); RG->end(); this->resizable(TR); this->end(); } int main(int argc, char **argv) { window = new Fl_Double_Window(Ww, Wh, "resize-example4a"); window->color(FL_WHITE); Resizables *resizables = new Resizables(0, 0, Ww, Wh); window->end(); window->resizable(resizables); window->size_range(Ww, Wh); window->show(argc, argv); window->size(Ww + 90, Wh); return Fl::run(); } fltk-1.4.3/test/clock.cxx0000644000175000017500000000313515004135251015405 0ustar albrechtalbrecht// // Clock test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include const int dev_test = 0; // 1 = enable non-standard colors and no-shadow tests // close all windows when the user closes one of the windows void close_cb(Fl_Widget *w, void *v) { Fl_Window *win = Fl::first_window(); while (win) { win->hide(); win = Fl::first_window(); } return; } int main(int argc, char **argv) { Fl_Double_Window window(220,220,"Fl_Clock"); window.callback(close_cb); Fl_Clock c1(0,0,220,220); // c1.color(2,1); window.resizable(c1); window.end(); Fl_Double_Window window2(220,220,"Fl_Round_Clock"); window2.callback(close_cb); Fl_Round_Clock c2(0,0,220,220); if (dev_test) { c2.color(FL_YELLOW,FL_RED); // set background and hands colors, resp. c2.shadow(0); // disable shadows of the hands } window2.resizable(c2); window2.end(); // my machine had a clock* Xresource set for another program, so // I don't want the class to be "clock": window.xclass("Fl_Clock"); window2.xclass("Fl_Clock"); window.show(argc,argv); window2.show(); return Fl::run(); } fltk-1.4.3/test/handle_events.cxx0000644000175000017500000000660415004135251017135 0ustar albrechtalbrecht// // Event test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Build: fltk-config --compile handle_events.cxx #include #include #include #include #include #include // define WINDOW_TYPE as either "Fl_Gl_Window" or "Fl_Double_Window" #define WINDOW_TYPE Fl_Double_Window // Class to handle events class app : public WINDOW_TYPE { protected: int handle(int) FL_OVERRIDE; public: // storage for the last event int eventnum, ex, ey; const char *eventname; app(int X, int Y, int W, int H, const char *L = 0) : WINDOW_TYPE(X, Y, W, H, L) { eventname = NULL; eventnum = 0; } // evaluates and prints the current event void print_event(int ev) { eventnum++; ex = Fl::event_x(); ey = Fl::event_y(); int screen_num = Fl_Window::screen_num(); #if defined(FL_API_VERSION) && FL_API_VERSION >= 10400 int scale = int(Fl::screen_scale(screen_num) * 100. + 0.5); #else int scale = 100; #endif eventname = fl_eventnames[ev]; fprintf(stderr, "[%3d, win(%d,%d,%d,%d), screen %d, scale %3d%%] %-18.18s at (%4d, %4d)", eventnum, x(), y(), w(), h(), screen_num, scale, eventname, ex, ey); eventnum %= 999; } }; // Event handling int app::handle(int ev) { print_event(ev); // common for all events int res = WINDOW_TYPE::handle(ev); int buttons = Fl::event_buttons() >> 24; // bits: 1=left, 2=middle, 4=right button switch (ev) { case FL_PUSH: fprintf(stderr, ", button %d down, buttons = 0x%x", Fl::event_button(), buttons); res = 1; break; case FL_RELEASE: fprintf(stderr, ", button %d up, buttons = 0x%x", Fl::event_button(), buttons); res = 1; break; case FL_MOUSEWHEEL: fprintf(stderr, ", dx = %d, dy = %d", Fl::event_dx(), Fl::event_dy()); res = 1; break; case FL_ENTER: case FL_LEAVE: res = 1; break; case FL_MOVE: case FL_DRAG: fprintf(stderr, ", mouse buttons = 0x%x", buttons); res = 1; break; case FL_KEYBOARD: if (Fl::event_text()[0] >= 'a' && Fl::event_text()[0] <= 'z') { fprintf(stderr, ", Text = '%s'", Fl::event_text()); res = 1; } else { // "ignore" everything else fprintf(stderr, ", ignored '%s'", Fl::event_text()); } break; case FL_KEYUP: res = 1; break; case FL_FOCUS: case FL_UNFOCUS: res = 1; break; default: break; } fprintf(stderr, "\n"); fflush(stderr); return res; } /* end of handle() method */ // Quit button callback (closes the window) void quit_cb(Fl_Button *b, void *) { b->window()->hide(); } // main program int main(int argc, char **argv) { app *win = new app(10, 10, 240, 240); Fl_Button *quit = new Fl_Button(90, 100, 60, 40, "Quit"); quit->box(FL_THIN_UP_BOX); quit->callback((Fl_Callback *)quit_cb); win->end(); win->resizable(win); win->show(argc, argv); return Fl::run(); } fltk-1.4.3/test/fracviewer.cxx0000644000175000017500000003435115004135251016453 0ustar albrechtalbrecht/* * fractviewer.cxx [from agviewer.c (version 1.0)] * * AGV: a glut viewer. Routines for viewing a 3d scene w/ glut * * See agv_example.c and agviewer.h comments within for more info. * * I welcome any feedback or improved versions! * * Philip Winston - 4/11/95 * pwinston@hmc.edu * http://www.cs.hmc.edu/people/pwinston */ #include #if HAVE_GL && HAVE_GL_GLU_H # include # include # include # include # include # include # include # if !defined(_WIN32) # include # endif // !_WIN32 # include "fracviewer.h" /* Some files do not define M_PI... */ #ifndef M_PI #define M_PI 3.14159265 #endif /***************************************************************/ /************************** SETTINGS ***************************/ /***************************************************************/ /* Initial polar movement settings */ #define INIT_POLAR_AZ 0.0f #define INIT_POLAR_EL 30.0f #define INIT_DIST 4.0f #define INIT_AZ_SPIN 0.5f #define INIT_EL_SPIN 0.0f /* Initial flying movement settings */ #define INIT_EX 0.0f #define INIT_EY -2.0f #define INIT_EZ -2.0f #define INIT_MOVE 0.01f #define MINMOVE 0.001f /* Start in this mode */ #define INIT_MODE POLAR /* Controls: */ /* map 0-9 to an EyeMove value when number key is hit in FLYING mode */ #define SPEEDFUNCTION(x) ((x)*(x)*0.001f) /* Multiply EyeMove by (1+-MOVEFRACTION) when +/- hit in FLYING mode */ #define MOVEFRACTION 0.25f /* What to multiply number of pixels mouse moved by to get rotation amount */ #define EL_SENS 0.5f #define AZ_SENS 0.5f /* What to multiply number of pixels mouse moved by for movement amounts */ #define DIST_SENS 0.01f #define E_SENS 0.01f /* Minimum spin to allow in polar (lower forced to zero) */ #define MIN_AZSPIN 0.1f #define MIN_ELSPIN 0.1f /* Factors used in computing dAz and dEl (which determine AzSpin, ElSpin) */ #define SLOW_DAZ 0.90f #define SLOW_DEL 0.90f #define PREV_DAZ 0.80f #define PREV_DEL 0.80f #define CUR_DAZ 0.20f #define CUR_DEL 0.20f /***************************************************************/ /************************** GLOBALS ****************************/ /***************************************************************/ int MoveMode = INIT_MODE; /* FLYING or POLAR mode? */ GLfloat Ex = INIT_EX, /* flying parameters */ Ey = INIT_EY, Ez = INIT_EZ, EyeMove = INIT_MOVE, EyeDist = INIT_DIST, /* polar params */ AzSpin = INIT_AZ_SPIN, ElSpin = INIT_EL_SPIN, EyeAz = INIT_POLAR_AZ, /* used by both */ EyeEl = INIT_POLAR_EL; int agvMoving; /* Currently moving? */ int downx, downy, /* for tracking mouse position */ lastx, lasty, downb = -1; /* and button status */ GLfloat downDist, downEl, downAz, /* for saving state of things */ downEx, downEy, downEz, /* when button is pressed */ downEyeMove; GLfloat dAz, dEl, lastAz, lastEl; /* to calculate spinning w/ polar motion */ int AdjustingAzEl = 0; int AllowIdle, RedisplayWindow; /* If AllowIdle is 1 it means AGV will install its own idle which * will update the viewpoint as needed and send glutPostRedisplay() to the * window RedisplayWindow which was set in agvInit(). AllowIdle of 0 * means AGV won't install an idle funciton, and something like * "if (agvMoving) agvMove()" should exist at the end of the running * idle function. */ #define MAX(x,y) (((x) > (y)) ? (x) : (y)) #define TORAD(x) ((M_PI/180.0)*(x)) #define TODEG(x) ((180.0/M_PI)*(x)) /***************************************************************/ /************************ PROTOTYPES ***************************/ /***************************************************************/ /* * these are functions meant for internal use only * the other prototypes are in agviewer.h */ void PolarLookFrom(GLfloat dist, GLfloat elevation, GLfloat azimuth); void FlyLookFrom(GLfloat x, GLfloat y, GLfloat z, GLfloat az, GLfloat el); int ConstrainEl(void); void MoveOn(int v); void SetMove(float newmove); static void normalize(GLfloat v[3]); void ncrossprod(float v1[3], float v2[3], float cp[3]); /***************************************************************/ /************************ agvInit ******************************/ /***************************************************************/ void agvInit(int window) { glutMouseFunc(agvHandleButton); glutMotionFunc(agvHandleMotion); glutKeyboardFunc(agvHandleKeys); RedisplayWindow = glutGetWindow(); agvSetAllowIdle(window); } /***************************************************************/ /************************ VIEWPOINT STUFF **********************/ /***************************************************************/ /* * viewing transformation modified from page 90 of red book */ void PolarLookFrom(GLfloat dist, GLfloat elevation, GLfloat azimuth) { glTranslatef(0, 0, -dist); glRotatef(elevation, 1, 0, 0); glRotatef(azimuth, 0, 1, 0); } /* * I took the idea of tracking eye position in absolute * coords and direction looking in Polar form from denis */ void FlyLookFrom(GLfloat x, GLfloat y, GLfloat z, GLfloat az, GLfloat el) { float lookat[3], perp[3], up[3]; lookat[0] = GLfloat(sin(TORAD(az))*cos(TORAD(el))); lookat[1] = GLfloat(sin(TORAD(el))); lookat[2] = GLfloat(-cos(TORAD(az))*cos(TORAD(el))); normalize(lookat); perp[0] = lookat[2]; perp[1] = 0; perp[2] = -lookat[0]; normalize(perp); ncrossprod(lookat, perp, up); gluLookAt(x, y, z, x+lookat[0], y+lookat[1], z+lookat[2], up[0], up[1], up[2]); } /* * Call viewing transformation based on movement mode */ void agvViewTransform(void) { switch (MoveMode) { case FLYING: FlyLookFrom(Ex, Ey, Ez, EyeAz, EyeEl); break; case POLAR: PolarLookFrom(EyeDist, EyeEl, EyeAz); break; } } /* * keep them vertical; I think this makes a lot of things easier, * but maybe it wouldn't be too hard to adapt things to let you go * upside down */ int ConstrainEl(void) { if (EyeEl <= -90) { EyeEl = -89.99f; return 1; } else if (EyeEl >= 90) { EyeEl = 89.99f; return 1; } return 0; } /* * Idle Function - moves eyeposition */ void agvMove(void) { switch (MoveMode) { case FLYING: Ex += GLfloat(EyeMove*sin(TORAD(EyeAz))*cos(TORAD(EyeEl))); Ey += GLfloat(EyeMove*sin(TORAD(EyeEl))); Ez -= GLfloat(EyeMove*cos(TORAD(EyeAz))*cos(TORAD(EyeEl))); break; case POLAR: EyeEl += ElSpin; EyeAz += AzSpin; if (ConstrainEl()) { /* weird spin thing to make things look */ ElSpin = -ElSpin; /* look better when you are kept from going */ /* upside down while spinning - Isn't great */ if (fabs(ElSpin) > fabs(AzSpin)) AzSpin = GLfloat(fabs(ElSpin) * ((AzSpin > 0.0f) ? 1.0f : -1.0f)); } break; } if (AdjustingAzEl) { dAz *= SLOW_DAZ; dEl *= SLOW_DEL; } if (AllowIdle) { glutSetWindow(RedisplayWindow); glutPostRedisplay(); } } /* * Don't install agvMove as idle unless we will be updating the view * and we've been given a RedisplayWindow */ void MoveOn(int v) { if (v && ((MoveMode == FLYING && EyeMove != 0) || (MoveMode == POLAR && (AzSpin != 0 || ElSpin != 0 || AdjustingAzEl)))) { agvMoving = 1; if (AllowIdle) glutIdleFunc(agvMove); } else { agvMoving = 0; if (AllowIdle) glutIdleFunc(NULL); } } /* * set new redisplay window. If <= 0 it means we are not to install * an idle function and will rely on whoever does install one to * put statement like "if (agvMoving) agvMove();" at end of it */ void agvSetAllowIdle(int allowidle) { if ((AllowIdle = allowidle)) MoveOn(1); } /* * when moving to flying we stay in the same spot, moving to polar we * reset since we have to be looking at the origin (though a pivot from * current position to look at origin might be cooler) */ void agvSwitchMoveMode(int move) { switch (move) { case FLYING: if (MoveMode == FLYING) return; Ex = GLfloat(-EyeDist*sin(TORAD(EyeAz))*cos(TORAD(EyeEl))); Ey = GLfloat( EyeDist*sin(TORAD(EyeEl))); Ez = GLfloat( EyeDist*(cos(TORAD(EyeAz))*cos(TORAD(EyeEl)))); EyeEl = -EyeEl; EyeMove = INIT_MOVE; break; case POLAR: EyeDist = INIT_DIST; EyeAz = INIT_POLAR_AZ; EyeEl = INIT_POLAR_EL; AzSpin = INIT_AZ_SPIN; ElSpin = INIT_EL_SPIN; break; } MoveMode = move; MoveOn(1); glutPostRedisplay(); } /***************************************************************/ /******************* MOUSE HANDLING ***********************/ /***************************************************************/ void agvHandleButton(int button, int state, int x, int y) { // deal with mouse wheel events, that fltk sends as buttons 3 or 4 //if (button > GLUT_RIGHT_BUTTON)return; if ((state == GLUT_DOWN) && ((button == 3) || (button == 4))) { // attempt to process scrollwheel as zoom in/out float deltay = 0.25; if (button == 3) { deltay = (-0.25); } downb = -1; downDist = EyeDist; downEx = Ex; downEy = Ey; downEz = Ez; downEyeMove = EyeMove; EyeMove = 0; EyeDist = downDist + deltay; Ex = GLfloat(downEx - E_SENS*deltay*sin(TORAD(EyeAz))*cos(TORAD(EyeEl))); Ey = GLfloat(downEy - E_SENS*deltay*sin(TORAD(EyeEl))); Ez = GLfloat(downEz + E_SENS*deltay*cos(TORAD(EyeAz))*cos(TORAD(EyeEl))); EyeMove = downEyeMove; glutPostRedisplay(); return; } else if (button > GLUT_RIGHT_BUTTON)return; // ignore any other button... if (state == GLUT_DOWN && downb == -1) { lastx = downx = x; lasty = downy = y; downb = button; switch (button) { case GLUT_LEFT_BUTTON: lastEl = downEl = EyeEl; lastAz = downAz = EyeAz; AzSpin = ElSpin = dAz = dEl = 0; AdjustingAzEl = 1; MoveOn(1); break; case GLUT_MIDDLE_BUTTON: downDist = EyeDist; downEx = Ex; downEy = Ey; downEz = Ez; downEyeMove = EyeMove; EyeMove = 0; } } else if (state == GLUT_UP && button == downb) { downb = -1; switch (button) { case GLUT_LEFT_BUTTON: if (MoveMode != FLYING) { AzSpin = -dAz; if (AzSpin < MIN_AZSPIN && AzSpin > -MIN_AZSPIN) AzSpin = 0; ElSpin = -dEl; if (ElSpin < MIN_ELSPIN && ElSpin > -MIN_ELSPIN) ElSpin = 0; } AdjustingAzEl = 0; MoveOn(1); break; case GLUT_MIDDLE_BUTTON: EyeMove = downEyeMove; } } } /* * change EyeEl and EyeAz and position when mouse is moved w/ button down */ void agvHandleMotion(int x, int y) { int deltax = x - downx, deltay = y - downy; switch (downb) { case GLUT_LEFT_BUTTON: EyeEl = GLfloat(downEl + EL_SENS * deltay); ConstrainEl(); EyeAz = GLfloat(downAz + AZ_SENS * deltax); dAz = GLfloat(PREV_DAZ*dAz + CUR_DAZ*(lastAz - EyeAz)); dEl = GLfloat(PREV_DEL*dEl + CUR_DEL*(lastEl - EyeEl)); lastAz = EyeAz; lastEl = EyeEl; break; case GLUT_MIDDLE_BUTTON: EyeDist = GLfloat(downDist + DIST_SENS*deltay); Ex = GLfloat(downEx - E_SENS*deltay*sin(TORAD(EyeAz))*cos(TORAD(EyeEl))); Ey = GLfloat(downEy - E_SENS*deltay*sin(TORAD(EyeEl))); Ez = GLfloat(downEz + E_SENS*deltay*cos(TORAD(EyeAz))*cos(TORAD(EyeEl))); break; } glutPostRedisplay(); } /***************************************************************/ /********************* KEYBOARD HANDLING ***********************/ /***************************************************************/ /* * set EyeMove (current speed) for FLYING mode */ void SetMove(float newmove) { if (newmove > MINMOVE) { EyeMove = newmove; MoveOn(1); } else { EyeMove = 0; MoveOn(0); } } /* * 0->9 set speed, +/- adjust current speed -- in FLYING mode */ void agvHandleKeys(unsigned char key, int, int) { if (MoveMode != FLYING) return; if (key >= '0' && key <= '9') SetMove(SPEEDFUNCTION((key-'0'))); else switch(key) { case '+': if (EyeMove == 0) SetMove(MINMOVE); else SetMove(EyeMove *= (1 + MOVEFRACTION)); break; case '-': SetMove(EyeMove *= (1 - MOVEFRACTION)); break; } } /***************************************************************/ /*********************** VECTOR STUFF **************************/ /***************************************************************/ /* normalizes v */ static void normalize(GLfloat v[3]) { GLfloat d = sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); if (d == 0) fprintf(stderr, "Zero length vector in normalize\n"); else { v[0] /= d; v[1] /= d; v[2] /= d; } } /* calculates a normalized crossproduct to v1, v2 */ void ncrossprod(float v1[3], float v2[3], float cp[3]) { cp[0] = v1[1]*v2[2] - v1[2]*v2[1]; cp[1] = v1[2]*v2[0] - v1[0]*v2[2]; cp[2] = v1[0]*v2[1] - v1[1]*v2[0]; normalize(cp); } /***************************************************************/ /**************************** AXES *****************************/ /***************************************************************/ /* draw axes -- was helpful to debug/design things */ void agvMakeAxesList(int displaylistnum) { int i,j; GLfloat axes_ambuse[] = { 0.5, 0.0, 0.0, 1.0 }; GLfloat trans = -10; glNewList(displaylistnum, GL_COMPILE); glPushAttrib(GL_LIGHTING_BIT); glMatrixMode(GL_MODELVIEW); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, axes_ambuse); glBegin(GL_LINES); glVertex3f(15, 0, 0); glVertex3f(-15, 0, 0); glVertex3f(0, 15, 0); glVertex3f(0, -15, 0); glVertex3f(0, 0, 15); glVertex3f(0, 0, -15); glEnd(); for (i = 0; i < 3; i++) { glPushMatrix(); glTranslatef(trans*(i==0), trans*(i==1), trans*(i==2)); for (j = 0; j < 21; j++) { // glutSolidCube(0.1); glTranslatef(i==0, i==1, i==2); } glPopMatrix(); } glPopAttrib(); glEndList(); } #endif // HAVE_GL && HAVE_GL_GLU_H fltk-1.4.3/test/fltk-versions.cxx0000644000175000017500000001107515004135251017122 0ustar albrechtalbrecht// // Library version test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // This program is work in progress and may not be "perfect". #include #include #include #include #include #include #include static const int ww = 640, mw = 750; // initial, max. window width static const int wh = 200, mh = 300; // initial, max. window height // Function to determine the platform (system and backend). // Note: the display must have been opened before this is called. // Returns a string describing the system/platform and backend. static const char *get_platform() { #if defined(_WIN32) return "Windows"; #elif defined(FLTK_USE_X11) || defined(FLTK_USE_WAYLAND) # if defined(FLTK_USE_X11) if (fl_x11_display()) return "Unix/Linux (X11)"; # endif # if defined(FLTK_USE_WAYLAND) if (fl_wl_display()) return "Unix/Linux (Wayland)"; # endif return "X11 or Wayland (backend unknown or display not opened)"; #elif defined(__APPLE__) return "macOS (native)"; #endif return "platform unknown, unsupported, or display not opened"; } // set box attributes and optionally set a background color (debug mode) static void set_attributes(Fl_Widget *w, Fl_Color col) { w->labelfont(FL_COURIER); w->labelsize(16); w->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); #if (0) // 1 = debug: set a background color for a box (widget) w->box(FL_FLAT_BOX); w->color(col); #endif } static char version[9][80]; static Fl_Box *box[9]; // Optional: uncomment next line to disable wayland backend // FL_EXPORT bool fl_disable_wayland = true; int main(int argc, char **argv) { int versions = 0; fl_open_display(); const char *platform = get_platform(); printf("System/platform = %s\n", platform); // Version comparison results (Unicode check marks in comments are experimental) const char *YES = "OK"; // "🗹"; // "✓"; const char *NO = "FAIL"; // "🗷"; // "❌"; sprintf(version[versions++], "FL_VERSION = %6.4f", FL_VERSION); sprintf(version[versions++], "Fl::version() = %6.4f", Fl::version()); sprintf(version[versions++], "%s", (FL_VERSION == Fl::version()) ? YES : NO); sprintf(version[versions++], "FL_API_VERSION = %6d", FL_API_VERSION); sprintf(version[versions++], "Fl::api_version() = %6d", Fl::api_version()); sprintf(version[versions++], "%s", (FL_API_VERSION == Fl::api_version()) ? YES : NO); sprintf(version[versions++], "FL_ABI_VERSION = %6d", FL_ABI_VERSION); sprintf(version[versions++], "Fl::abi_version() = %6d", Fl::abi_version()); sprintf(version[versions++], "%s", (FL_ABI_VERSION == Fl::abi_version()) ? YES : NO); for (int i = 0; i < versions; i++) { if (i % 3 == 1) // 2nd line followed by check mark or text printf("%s ", version[i]); else // 1st and 3rd line printf("%s\n", version[i]); } fflush(stdout); #ifdef FL_ABI_VERSION if (FL_ABI_VERSION != Fl::abi_version()) { printf("*** FLTK ABI version mismatch: headers = %d, lib = %d ***\n", FL_ABI_VERSION, Fl::abi_version()); fflush(stdout); fl_message("*** FLTK ABI version mismatch: headers = %d, lib = %d ***", FL_ABI_VERSION, Fl::abi_version()); } #endif Fl_Window *window = new Fl_Window(ww, wh); Fl_Grid *grid = new Fl_Grid(0, 0, ww, wh); grid->layout(4, 3, 20, 5); Fl_Box *title = new Fl_Box(0, 0, 0, 0, platform); set_attributes(title, FL_YELLOW); title->labelfont(FL_HELVETICA_BOLD); grid->widget(title, 0, 0, 1, 3); grid->row_height(0, 40); title->labelsize(20); for (int i = 0; i < 3; i += 1) { box[3 * i ] = new Fl_Box(0, 0, 270, 0, version[3 * i]); box[3 * i + 1] = new Fl_Box(0, 0, 270, 0, version[3 * i + 1]); box[3 * i + 2] = new Fl_Box(0, 0, 40, 0, version[3 * i + 2]); grid->widget(box[3 * i], i + 1, 0); grid->widget(box[3 * i + 1], i + 1, 1); grid->widget(box[3 * i + 2], i + 1, 2); grid->row_height(i + 1, 30); } for (int i = 0; i < 9; i++) set_attributes(box[i], FL_GREEN); window->end(); window->resizable(grid); window->size_range(ww, wh, mw, mh); window->show(argc, argv); return Fl::run(); } fltk-1.4.3/test/trackball.c0000644000175000017500000002055215004135251015673 0ustar albrechtalbrecht/* * (c) Copyright 1993, 1994, Silicon Graphics, Inc. * ALL RIGHTS RESERVED * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the above * copyright notice appear in all copies and that both the copyright notice * and this permission notice appear in supporting documentation, and that * the name of Silicon Graphics, Inc. not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. * * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. * * US Government Users Restricted Rights * Use, duplication, or disclosure by the Government is subject to * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph * (c)(1)(ii) of the Rights in Technical Data and Computer Software * clause at DFARS 252.227-7013 and/or in similar or successor * clauses in the FAR or the DOD or NASA FAR Supplement. * Unpublished-- rights reserved under the copyright laws of the * United States. Contractor/manufacturer is Silicon Graphics, * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. * * OpenGL(TM) is a trademark of Silicon Graphics, Inc. */ /* * Trackball code: * * Implementation of a virtual trackball. * Implemented by Gavin Bell, lots of ideas from Thant Tessman and * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. * * Vector manip code: * * Original code from: * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli * * Much mucking with by: * Gavin Bell */ #include #include "trackball.h" /* * This size should really be based on the distance from the center of * rotation to the point on the object underneath the mouse. That * point would then track the mouse as closely as possible. This is a * simple example, though, so that is left as an Exercise for the * Programmer. */ #define TRACKBALLSIZE (0.8f) /* * Local function prototypes (not defined in trackball.h) */ static float tb_project_to_sphere(float, float, float); static void normalize_quat(float [4]); static float max_velocity = 0.1f; void vzero(float *v) { v[0] = 0.0; v[1] = 0.0; v[2] = 0.0; } void vset(float *v, float x, float y, float z) { v[0] = x; v[1] = y; v[2] = z; } void vsub(const float *src1, const float *src2, float *dst) { dst[0] = src1[0] - src2[0]; dst[1] = src1[1] - src2[1]; dst[2] = src1[2] - src2[2]; } void vcopy(const float *v1, float *v2) { int i; for (i = 0 ; i < 3 ; i++) v2[i] = v1[i]; } void vcross(const float *v1, const float *v2, float *cross) { float temp[3]; temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); vcopy(temp, cross); } float vlength(const float *v) { return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); } void vscale(float *v, float div) { v[0] *= div; v[1] *= div; v[2] *= div; } void vnormal(float *v) { vscale(v,1.0f/vlength(v)); } float vdot(const float *v1, const float *v2) { return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; } void vadd(const float *src1, const float *src2, float *dst) { dst[0] = src1[0] + src2[0]; dst[1] = src1[1] + src2[1]; dst[2] = src1[2] + src2[2]; } /* * Ok, simulate a track-ball. Project the points onto the virtual * trackball, then figure out the axis of rotation, which is the cross * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) * Note: This is a deformed trackball-- is a trackball in the center, * but is deformed into a hyperbolic sheet of rotation away from the * center. This particular function was chosen after trying out * several variations. * * It is assumed that the arguments to this routine are in the range * (-1.0 ... 1.0) */ void trackball(float q[4], float p1x, float p1y, float p2x, float p2y) { float a[3]; /* Axis of rotation */ float phi; /* how much to rotate about axis */ float p1[3], p2[3], d[3]; float t; if (p1x == p2x && p1y == p2y) { /* Zero rotation */ vzero(q); q[3] = 1.0; return; } /* * First, figure out z-coordinates for projection of P1 and P2 to * deformed sphere */ vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y)); vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y)); /* * Now, we want the cross product of P1 and P2 */ vcross(p2,p1,a); /* * Figure out how much to rotate around that axis. */ vsub(p1,p2,d); t = vlength(d) / (2.0f*TRACKBALLSIZE); /* * Avoid problems with out-of-control values... */ if (t > max_velocity) t = max_velocity; if (t < -max_velocity) t = -max_velocity; phi = float(2.0 * asin(t)); axis_to_quat(a,phi,q); } /* * Given an axis and angle, compute quaternion. */ void axis_to_quat(float a[3], float phi, float q[4]) { vnormal(a); vcopy(a,q); vscale(q,sinf(phi/2.0f)); q[3] = cosf(phi/2.0f); } /* * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet * if we are away from the center of the sphere. */ static float tb_project_to_sphere(float r, float x, float y) { float d, t, z; d = sqrtf(x*x + y*y); if (d < r * 0.70710678118654752440) { /* Inside sphere */ z = sqrtf(r*r - d*d); } else { /* On hyperbola */ t = float(r / 1.41421356237309504880); z = t*t / d; } return z; } /* * Given two rotations, e1 and e2, expressed as quaternion rotations, * figure out the equivalent single rotation and stuff it into dest. * * This routine also normalizes the result every RENORMCOUNT times it is * called, to keep error from creeping in. * * NOTE: This routine is written so that q1 or q2 may be the same * as dest (or each other). */ #define RENORMCOUNT 97 void add_quats(float q1[4], float q2[4], float dest[4]) { static int count=0; float t1[4], t2[4], t3[4]; float tf[4]; vcopy(q1,t1); vscale(t1,q2[3]); vcopy(q2,t2); vscale(t2,q1[3]); vcross(q2,q1,t3); vadd(t1,t2,tf); vadd(t3,tf,tf); tf[3] = q1[3] * q2[3] - vdot(q1,q2); dest[0] = tf[0]; dest[1] = tf[1]; dest[2] = tf[2]; dest[3] = tf[3]; if (++count > RENORMCOUNT) { count = 0; normalize_quat(dest); } } /* * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 * If they don't add up to 1.0, dividing by their magnitued will * renormalize them. * * Note: See the following for more information on quaternions: * * - Shoemake, K., Animating rotation with quaternion curves, Computer * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. * - Pletinckx, D., Quaternion calculus as a basic tool in computer * graphics, The Visual Computer 5, 2-13, 1989. */ static void normalize_quat(float q[4]) { int i; float mag; mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); for (i = 0; i < 4; i++) q[i] /= mag; } /* * Build a rotation matrix, given a quaternion rotation. * */ void build_rotmatrix(float m[4][4], float q[4]) { m[0][0] = 1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]); m[0][1] = 2.0f * (q[0] * q[1] - q[2] * q[3]); m[0][2] = 2.0f * (q[2] * q[0] + q[1] * q[3]); m[0][3] = 0.0f; m[1][0] = 2.0f * (q[0] * q[1] + q[2] * q[3]); m[1][1]= 1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]); m[1][2] = 2.0f * (q[1] * q[2] - q[0] * q[3]); m[1][3] = 0.0f; m[2][0] = 2.0f * (q[2] * q[0] - q[1] * q[3]); m[2][1] = 2.0f * (q[1] * q[2] + q[0] * q[3]); m[2][2] = 1.0f - 2.0f * (q[1] * q[1] + q[0] * q[0]); m[2][3] = 0.0f; m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 1.0; } fltk-1.4.3/test/unittest_fast_shapes.cxx0000644000175000017500000003422515004135251020555 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "unittests.h" #include #include #include // fl_text_extents() #if HAVE_GL #include #endif #if 0 // not testing yet: void fl_line(int x, int y, int x1, int y1) void fl_line(int x, int y, int x1, int y1, int x2, int y2) Draw one or two lines between the given points. void fl_loop(int x, int y, int x1, int y1, int x2, int y2) void fl_loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) Outline a 3 or 4-sided polygon with lines. void fl_polygon(int x, int y, int x1, int y1, int x2, int y2) void fl_polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) Draw vertical and horizontal lines. A vertical line is drawn first, then a horizontal, then a vertical. #endif // // --- test drawing shapes that are not transformed by the drawing matrix ------ // void draw_fast_shapes() { int a = 0, b = 0, i; // 1: draw a filled rectangle (fl_rectf) fl_color(FL_GREEN); for (i=0; i<=40; i++) { fl_point(a+i, b); fl_point(a+i, b+20); } for (i=0; i<=20; i++) { fl_point(a, b+i); fl_point(a+40, b+i); } fl_color(FL_RED); for (i=1; i<=39; i++) { fl_point(a+i, b+1); fl_point(a+i, b+19); } for (i=1; i<=19; i++) { fl_point(a+1, b+i); fl_point(a+39, b+i); } fl_color(FL_BLACK); fl_rectf(a+1, b+1, 39, 19); // 2: draw a one units wide frame b+=24; fl_color(FL_GREEN); for (i=0; i<=40; i++) { fl_point(a+i, b); fl_point(a+i, b+20); } for (i=0; i<=20; i++) { fl_point(a, b+i); fl_point(a+40, b+i); } fl_color(FL_GREEN); for (i=2; i<=38; i++) { fl_point(a+i, b+2); fl_point(a+i, b+18); } for (i=2; i<=18; i++) { fl_point(a+2, b+i); fl_point(a+38, b+i); } fl_color(FL_RED); for (i=1; i<=39; i++) { fl_point(a+i, b+1); fl_point(a+i, b+19); } for (i=1; i<=19; i++) { fl_point(a+1, b+i); fl_point(a+39, b+i); } fl_color(FL_BLACK); fl_rect(a+1, b+1, 39, 19); // 3: draw a three units wide frame b+=24; fl_color(FL_GREEN); fl_rect(a, b, 41, 21); fl_rect(a+4, b+4, 33, 13); fl_color(FL_RED); fl_rect(a+1, b+1, 39, 19); fl_rect(a+3, b+3, 35, 15); fl_color(FL_BLACK); fl_line_style(FL_SOLID, 3); fl_rect(a+2, b+2, 37, 17); fl_line_style(FL_SOLID, 1); // 4: draw fl_xyline b+=24; fl_color(FL_GREEN); fl_rect(a, b+8, 41, 3); // single line fl_rect(a+45, b, 41, 3); // horizontal, then vertical line fl_rect(a+83, b, 3, 21); fl_rect(a+90, b, 21, 3); // horizontal, vertical, horizontal line fl_rect(a+109, b, 3, 21); fl_rect(a+109, b+18, 21, 3); fl_color(FL_RED); fl_rectf(a+1, b+9, 39, 1); // single line fl_rectf(a+46, b+1, 39, 1); // two lines fl_rectf(a+84, b+1, 1, 19); fl_rectf(a+91, b+1, 20, 1); // three lines fl_rectf(a+110, b+1, 1, 19); fl_rectf(a+110, b+19, 19, 1); // three lines fl_color(FL_BLACK); fl_xyline(a+1, b+9, a+39); fl_xyline(a+46, b+1, a+84, b+19); fl_xyline(a+91, b+1, a+110, b+19, a+128); b+=24; fl_color(FL_GREEN); fl_rect(a, b+7, 41, 5); // single line fl_rect(a+45, b, 41, 5); // horizontal, then vertical line fl_rect(a+81, b, 5, 21); fl_rect(a+90, b, 22, 5); // horizontal, vertical, horizontal line fl_rect(a+108, b, 5, 21); fl_rect(a+108, b+16, 22, 5); fl_color(FL_RED); fl_rectf(a+1, b+8, 39, 3); // single line fl_rectf(a+46, b+1, 39, 3); // two lines fl_rectf(a+82, b+1, 3, 19); fl_rectf(a+91, b+1, 20, 3); // three lines fl_rectf(a+109, b+1, 3, 19); fl_rectf(a+109, b+17, 20, 3); // three lines fl_color(FL_BLACK); fl_line_style(FL_SOLID, 3); fl_xyline(a+1, b+9, a+39); fl_xyline(a+46, b+2, a+83, b+19); fl_xyline(a+91, b+2, a+110, b+18, a+128); fl_line_style(FL_SOLID, 1); // 5: draw fl_xyline b+=24; fl_color(FL_GREEN); fl_rect(a+9, b, 3, 21); // single line fl_rect(a+45, b, 3, 21); // horizontal, then vertical line fl_rect(a+45, b+18, 41, 3); fl_rect(a+90, b, 3, 11); // horizontal, vertical, horizontal line fl_rect(a+90, b+9, 40, 3); fl_rect(a+127, b+9, 3, 12); fl_color(FL_RED); fl_rectf(a+10, b+1, 1, 19); // single line fl_rectf(a+46, b+1, 1, 19); // two lines fl_rectf(a+46, b+19, 39, 1); fl_rectf(a+91, b+1, 1, 10); // three lines fl_rectf(a+91, b+10, 38, 1); fl_rectf(a+128, b+10, 1, 10); // three lines fl_color(FL_BLACK); fl_yxline(a+10, b+1, b+19); fl_yxline(a+46, b+1, b+19, a+84); fl_yxline(a+91, b+1, b+10, a+128, b+19); b+=24; fl_color(FL_GREEN); fl_rect(a+8, b, 5, 21); // single line fl_rect(a+45, b, 5, 21); // horizontal, then vertical line fl_rect(a+45, b+16, 41, 5); fl_rect(a+90, b, 5, 11); // horizontal, vertical, horizontal line fl_rect(a+90, b+8, 40, 5); fl_rect(a+125, b+8, 5, 13); fl_color(FL_RED); fl_rectf(a+9, b+1, 3, 19); // single line fl_rectf(a+46, b+1, 3, 19); // two lines fl_rectf(a+46, b+17, 39, 3); fl_rectf(a+91, b+1, 3, 10); // three lines fl_rectf(a+91, b+9, 38, 3); fl_rectf(a+126, b+9, 3, 11); // three lines fl_color(FL_BLACK); fl_line_style(FL_SOLID, 3); fl_yxline(a+10, b+1, b+19); fl_yxline(a+47, b+1, b+18, a+84); fl_yxline(a+92, b+1, b+10, a+127, b+19); fl_line_style(FL_SOLID, 1); // 6: fast diagonal lines b+=24; fl_color(FL_GREEN); fl_point(a, b); fl_point(a+1, b); fl_point(a, b+1); fl_point(a+20, b+20); fl_point(a+19, b+20); fl_point(a+20, b+19); fl_color(FL_RED); fl_point(a+1, b+1); fl_point(a+19, b+19); fl_color(FL_BLACK); fl_line(a+1, b+1, a+19, b+19); fl_color(FL_GREEN); fl_point(a+25+1, b); fl_point(a+25, b+1); fl_point(a+25+4, b); fl_point(a+25, b+4); fl_point(a+25+20, b+19); fl_point(a+25+19, b+20); fl_point(a+25+16, b+20); fl_point(a+25+20, b+16); fl_color(FL_RED); fl_point(a+25+2, b+2); fl_point(a+25+18, b+18); fl_color(FL_BLACK); fl_line_style(FL_SOLID, 5); fl_line(a+25+1, b+1, a+25+19, b+19); fl_line(a+50+1, b+1, a+50+20, b+20, a+50+39, b+1); fl_line_style(FL_SOLID, 1); } #if HAVE_GL class Ut_GL_Rect_Test : public Fl_Gl_Window { public: Ut_GL_Rect_Test(int x, int y, int w, int h) : Fl_Gl_Window(x, y, w, h) { box(FL_FLAT_BOX); } void draw() FL_OVERRIDE { draw_begin(); fl_color(color()); fl_rectf(0, 0, w(), h()); draw_fast_shapes(); draw_end(); } }; #endif class Ut_Native_Rect_Test : public Fl_Window { public: Ut_Native_Rect_Test(int x, int y, int w, int h) : Fl_Window(x, y, w, h) { box(FL_FLAT_BOX); end(); } void draw() FL_OVERRIDE { Fl_Window::draw(); draw_fast_shapes(); } }; class Ut_Rect_Test : public Fl_Group { // 520 x 365 public: static Fl_Widget *create() { return new Ut_Rect_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } Ut_Rect_Test(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { label("Testing FLTK fast shape calls.\n" "These calls draw horizontal and vertical lines, frames, and rectangles.\n\n" "No red pixels should be visible. " "If you see bright red lines, or if parts of the green frames are hidden, " "drawing alignment is off."); align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_WRAP); box(FL_BORDER_BOX); int a = x+16, b = y+34; Fl_Box *t = new Fl_Box(a, b-24, 80, 18, "native"); t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); /* NativeRectTest *nr = */ new Ut_Native_Rect_Test(a+23, b-1, 200, 200); t = new Fl_Box(a, b, 18, 18, "1"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing filled rectangle alignment.\n\n" // Description: "This draws a black rectangle, surrounded by a green frame.\n\n" // Things to look out for: "If green pixels are missing, filled rectangles draw too big (see fl_rectf).\n\n" "If red pixels are showing, filled rectangles are drawn too small." ); b+=24; t = new Fl_Box(a, b, 18, 18, "2"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing rectangle frame alignment.\n\n" // Description: "This draws a black frame, surrounded on the inside and outside by a green frame.\n\n" // Things to look out for: "If green pixels are missing or red pixels are showing, rectangular frame drawing schould be adjusted (see fl_rect).\n\n" "If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted." ); b+=24; t = new Fl_Box(a, b, 18, 18, "3"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing scaled frame alignment.\n\n" // Description: "This draws a 3 units wide black frame, surrounded on the inside and outside by a green frame.\n\n" // Things to look out for: "If green pixels are missing or red pixels are showing, line width schould be adjusted (see fl_line_style).\n\n" "If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted." ); b+=24; t = new Fl_Box(a, b, 18, 18, "4"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing fl_xyline.\n\n" // Description: "This draws 3 versions of fl_xyline surronded with a green outline.\n\n" // Things to look out for: "If green pixels are missing or red pixels are showing, fl_xyline must be adjusted." ); b+=48; t = new Fl_Box(a, b, 18, 18, "5"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing fl_yxline.\n\n" // Description: "This draws 3 versions of fl_yxline surronded with a green outline.\n\n" // Things to look out for: "If green pixels are missing or red pixels are showing, fl_yxline must be adjusted." ); b+=48; t = new Fl_Box(a, b, 18, 18, "6"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing fl_line(int...).\n\n" // Description: "This draws 2 lines at differnet widths, and one connected line.\n\n" // Things to look out for: "Green and red pixels mark the beginning and end of single lines." "The line caps should be flat, the joints should be of type \"miter\"." ); #if HAVE_GL a = x+16+250, b = y+34; t = new Fl_Box(a, b-24, 80, 18, "OpenGL"); t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); /*GLRectTest *glr = */ new Ut_GL_Rect_Test(a+31, b-1, 200, 200); t = new Fl_Box(a, b, 26, 18, "1a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing filled rectangle alignment.\n\n" // Description: "This draws a black rectangle, surrounded by a green frame.\n\n" // Things to look out for: "If green pixels are missing, filled rectangles draw too big (see fl_rectf).\n\n" "If red pixels are showing, filled rectangles are drawn too small." ); b+=24; t = new Fl_Box(a, b, 26, 18, "2a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing rectangle frame alignment.\n\n" // Description: "This draws a black frame, surrounded on the inside and outside by a green frame.\n\n" // Things to look out for: "If green pixels are missing or red pixels are showing, rectangular frame drawing schould be adjusted (see fl_rect).\n\n" "If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted." ); b+=24; t = new Fl_Box(a, b, 26, 18, "3a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing scaled frame alignment.\n\n" // Description: "This draws a 3 units wide black frame, surrounded on the inside and outside by a green frame.\n\n" // Things to look out for: "If green pixels are missing or red pixels are showing, line width schould be adjusted (see fl_line_style).\n\n" "If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted." ); b+=24; t = new Fl_Box(a, b, 26, 18, "4a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing fl_xyline.\n\n" // Description: "This draws 3 versions of fl_xyline surronded with a green outline.\n\n" // Things to look out for: "If green pixels are missing or red pixels are showing, fl_xyline must be adjusted." ); b+=48; t = new Fl_Box(a, b, 26, 18, "5a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing fl_yxline.\n\n" // Description: "This draws 3 versions of fl_yxline surronded with a green outline.\n\n" // Things to look out for: "If green pixels are missing or red pixels are showing, fl_yxline must be adjusted." ); b+=48; t = new Fl_Box(a, b, 26, 18, "6a"); t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW); t->tooltip(// Title: "Testing fl_line(int...).\n\n" // Description: "This draws 2 lines at differnet widths, and one connected line.\n\n" // Things to look out for: "Green and red pixels mark the beginning and end of single lines." "The line caps should be flat, the joints should be of type \"miter\"." ); #endif t = new Fl_Box(x+w-1,y+h-1, 1, 1); resizable(t); } }; UnitTest rects(UT_TEST_FAST_SHAPES, "Fast Shapes", Ut_Rect_Test::create); fltk-1.4.3/test/mandelbrot.cxx0000644000175000017500000002236115004135251016443 0ustar albrechtalbrecht// // Mandelbrot set demo for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "mandelbrot_ui.h" #include #include #include #include #include const unsigned int palette[] = { 0xCC0000, 0xCA0002, 0xC90004, 0xC70006, 0xC60008, 0xC4000A, 0xC3000C, 0xC1000E, 0xBF0010, 0xBE0012, 0xBC0014, 0xBB0016, 0xB90018, 0xB8001A, 0xB6001B, 0xB4001D, 0xB3001F, 0xB10021, 0xB00023, 0xAE0025, 0xAD0027, 0xAB0029, 0xA9002B, 0xA8002D, 0xA6002F, 0xA50031, 0xA30033, 0xA20035, 0xA00037, 0x9E0039, 0x9D003B, 0x9B003D, 0x9A003F, 0x980041, 0x970043, 0x950045, 0x940047, 0x920049, 0x90004B, 0x8F004D, 0x8D004E, 0x8C0050, 0x8A0052, 0x890054, 0x870056, 0x850058, 0x84005A, 0x82005C, 0x81005E, 0x7F0060, 0x7E0062, 0x7C0064, 0x7A0066, 0x790068, 0x77006A, 0x76006C, 0x74006E, 0x730070, 0x710072, 0x6F0074, 0x6E0076, 0x6C0078, 0x6B007A, 0x69007C, 0x68007E, 0x660080, 0x640081, 0x630083, 0x610085, 0x600087, 0x5E0089, 0x5D008B, 0x5B008D, 0x59008F, 0x580091, 0x560093, 0x550095, 0x530097, 0x520099, 0x50009B, 0x4E009D, 0x4D009F, 0x4B00A1, 0x4A00A3, 0x4800A5, 0x4700A7, 0x4500A9, 0x4300AB, 0x4200AD, 0x4000AF, 0x3F00B1, 0x3D00B3, 0x3C00B4, 0x3A00B6, 0x3800B8, 0x3700BA, 0x3500BC, 0x3400BE, 0x3200C0, 0x3100C2, 0x2F00C4, 0x2E00C6, 0x2C00C8, 0x2A00CA, 0x2900CC, 0x2700CE, 0x2600D0, 0x2400D2, 0x2300D4, 0x2100D6, 0x1F00D8, 0x1E00DA, 0x1C00DC, 0x1B00DE, 0x1900E0, 0x1800E2, 0x1600E4, 0x1400E6, 0x1300E7, 0x1100E9, 0x1000EB, 0x0E00ED, 0x0D00EF, 0x0B00F1, 0x0900F3, 0x0800F5, 0x0600F7, 0x0500F9, 0x0300FB, 0x0200FD, 0x0000FF, 0x0202FD, 0x0404FB, 0x0606F9, 0x0808F7, 0x0A0AF5, 0x0C0CF3, 0x0E0EF1, 0x1010EF, 0x1212ED, 0x1414EB, 0x1616E9, 0x1818E7, 0x1A1AE6, 0x1B1BE4, 0x1D1DE2, 0x1F1FE0, 0x2121DE, 0x2323DC, 0x2525DA, 0x2727D8, 0x2929D6, 0x2B2BD4, 0x2D2DD2, 0x2F2FD0, 0x3131CE, 0x3333CC, 0x3535CA, 0x3737C8, 0x3939C6, 0x3B3BC4, 0x3D3DC2, 0x3F3FC0, 0x4141BE, 0x4343BC, 0x4545BA, 0x4747B8, 0x4949B6, 0x4B4BB4, 0x4D4DB3, 0x4E4EB1, 0x5050AF, 0x5252AD, 0x5454AB, 0x5656A9, 0x5858A7, 0x5A5AA5, 0x5C5CA3, 0x5E5EA1, 0x60609F, 0x62629D, 0x64649B, 0x666699, 0x686897, 0x6A6A95, 0x6C6C93, 0x6E6E91, 0x70708F, 0x72728D, 0x74748B, 0x767689, 0x787887, 0x7A7A85, 0x7C7C83, 0x7E7E81, 0x808080, 0x81817E, 0x83837C, 0x85857A, 0x878778, 0x898976, 0x8B8B74, 0x8D8D72, 0x8F8F70, 0x91916E, 0x93936C, 0x95956A, 0x979768, 0x999966, 0x9B9B64, 0x9D9D62, 0x9F9F60, 0xA1A15E, 0xA3A35C, 0xA5A55A, 0xA7A758, 0xA9A956, 0xABAB54, 0xADAD52, 0xAFAF50, 0xB1B14E, 0xB3B34D, 0xB4B44B, 0xB6B649, 0xB8B847, 0xBABA45, 0xBCBC43, 0xBEBE41, 0xC0C03F, 0xC2C23D, 0xC4C43B, 0xC6C639, 0xC8C837, 0xCACA35, 0xCCCC33, 0xCECE31, 0xD0D02F, 0xD2D22D, 0xD4D42B, 0xD6D629, 0xD8D827, 0xDADA25, 0xDCDC23, 0xDEDE21, 0xE0E01F, 0xE2E21D, 0xE4E41B, 0xE6E61A, 0xE7E718, 0xE9E916, 0xEBEB14, 0xEFEF10, 0xF3F30C, 0xF7F708, 0xFBFB04, 0xFFFF00 }; const size_t palette_size = sizeof(palette)/sizeof(palette[0]); void get_color(float t, uchar& r, uchar& g, uchar& b) { int index = (int)((1-t) * palette_size); Fl_Color c = palette[index % palette_size] << 8; Fl::get_color(c, r, g, b); } Drawing_Window mbrot; Drawing_Window jbrot; void idle(void*) { if (!mbrot.d->idle() && !(jbrot.d && jbrot.d->idle())) Fl::remove_idle(idle); } void set_idle() { Fl::add_idle(idle); } static void window_callback(Fl_Widget*, void*) {exit(0);} static void print(Fl_Widget *o, void *data) { Fl_Printer printer; Fl_Window *win = o->window(); if(!win->visible()) return; win->make_current(); uchar *image_data = fl_read_image(NULL, 0, 0, win->w(), win->h(), 0); if( printer.start_job(1) ) return; if( printer.start_page() ) return; printer.scale(.7f,.7f); fl_draw_image(image_data, 0,0, win->w(), win->h()); printer.end_page(); delete image_data; printer.end_job(); } static void toggle_color(Fl_Widget *o, void *data) { mbrot.d->use_colors = !mbrot.d->use_colors; mbrot.d->new_buffer(); if(jbrot.d) { jbrot.d->use_colors = mbrot.d->use_colors; jbrot.d->new_buffer(); } } int main(int argc, char **argv) { mbrot.make_window(); mbrot.window->begin(); Fl_Button* o = new Fl_Button(0, 0, 0, 0, NULL); o->callback(print,NULL); o->shortcut(FL_CTRL+'p'); o = new Fl_Button(0, 0, 0, 0, NULL); o->callback(toggle_color,NULL); o->shortcut(FL_CTRL+'m'); mbrot.window->end(); mbrot.d->X = -.75; mbrot.d->scale = 2.5; mbrot.update_label(); int i = 0; if (Fl::args(argc,argv,i) < argc) Fl::fatal(Fl::help); Fl::visual(FL_RGB); mbrot.window->callback(window_callback); mbrot.window->show(argc,argv); Fl::run(); return 0; } void Drawing_Window::update_label() { char buffer[128]; snprintf(buffer, 128, "%+.10f", d->X); x_input->value(buffer); snprintf(buffer, 128, "%+.10f", d->Y); y_input->value(buffer); snprintf(buffer, 128, "%.2g", d->scale); w_input->value(buffer); } void Drawing_Area::draw() { if (!dx) { dx = Fl::box_dx(box()); dy = Fl::box_dy(box()); dw = Fl::box_dw(box()); dh = Fl::box_dh(box()); W -= dw; H -= dh; } draw_box(); drawn = 0; set_idle(); } int Drawing_Area::idle() { if (!window()->visible()) return 0; if (drawn < nextline) { window()->make_current(); int yy = drawn+y()+dy; if (yy >= sy && yy <= sy+sh) erase_box(); if (use_colors) fl_draw_image(buffer+drawn*W*3, x()+dx, yy, W, 1, 3); else fl_draw_image_mono(buffer+drawn*W, x()+dx, yy, W, 1, 1, W); drawn++; return 1; } int linebytes = use_colors ? W*3 : W; if (nextline < H) { if (!buffer) buffer = new uchar[linebytes*H]; double yy = Y+(H/2-nextline)*scale/W; double yi = yy; if (julia) yy = jY; uchar *p = buffer+nextline*linebytes; for (int xi = 0; xi < W; xi++) { double xx = X+(xi-W/2)*scale/W; double wx = xx; double wy = yi; if (julia) xx = jX; for (int i=0; ; i++) { if (i >= iterations) { *p = 0; if (use_colors) { *(p+1) = 0; *(p+2) = 0; } break; } double t = wx*wx - wy*wy + xx; wy = 2*wx*wy + yy; wx = t; if (wx*wx + wy*wy > 4) { wx = t = 1-double(i)/(1<<10); if (t <= 0) t = 0; else for (i=brightness; i--;) t*=wx; if (use_colors) { get_color((float)t, *p, *(p+1), *(p+2)); } else { *p = 255 - int(254*t); } break; } } p += use_colors ? 3 : 1; } nextline++; return nextline <= H; } return 0; } void Drawing_Area::erase_box() { window()->make_current(); fl_overlay_clear(); } int Drawing_Area::handle(int event) { static int ix, iy; static int dragged; static int button; int x2,y2; switch (event) { case FL_PUSH: erase_box(); ix = Fl::event_x(); if (ix=x()+w()) ix=x()+w()-1; iy = Fl::event_y(); if (iy=y()+h()) iy=y()+h()-1; dragged = 0; button = Fl::event_button(); return 1; case FL_DRAG: dragged = 1; erase_box(); x2 = Fl::event_x(); if (x2=x()+w()) x2=x()+w()-1; y2 = Fl::event_y(); if (y2=y()+h()) y2=y()+h()-1; if (button != 1) {ix = x2; iy = y2; return 1;} if (ix < x2) {sx = ix; sw = x2-ix;} else {sx = x2; sw = ix-x2;} if (iy < y2) {sy = iy; sh = y2-iy;} else {sy = y2; sh = iy-y2;} window()->make_current(); fl_overlay_rect(sx,sy,sw,sh); return 1; case FL_RELEASE: if (button == 1) { erase_box(); if (dragged && sw > 3 && sh > 3) { X = X + (sx+sw/2-x()-W/2)*scale/W; Y = Y + (-sy-sh/2+y()+H/2)*scale/W; scale = sw*scale/W; } else if (!dragged) { scale = 2*scale; if (julia) { if (scale >= 4) { scale = 4; X = Y = 0; } } else { if (scale >= 2.5) { scale = 2.5; X = -.75; Y = 0; } } } else return 1; ((Drawing_Window*)(user_data()))->update_label(); new_display(); } else if (!julia) { if (!jbrot.d) { jbrot.make_window(); jbrot.d->julia = 1; jbrot.d->X = 0; jbrot.d->Y = 0; jbrot.d->scale = 4; jbrot.d->use_colors = mbrot.d->use_colors; jbrot.update_label(); } jbrot.d->jX = X + (ix-x()-W/2)*scale/W; jbrot.d->jY = Y + (H/2-iy+y())*scale/W; static char s[128]; snprintf(s, 128, "Julia %.7f %.7f",jbrot.d->jX,jbrot.d->jY); jbrot.window->label(s); jbrot.window->show(); jbrot.d->new_display(); } return 1; } return 0; } void Drawing_Area::new_display() { drawn = nextline = 0; set_idle(); } void Drawing_Area::new_buffer() { if (buffer) {delete[] buffer; buffer = 0; new_display();} } void Drawing_Area::resize(int XX,int YY,int WW,int HH) { if (WW != w() || HH != h()) { W = WW - dw; H = HH - dh; if (buffer) {delete[] buffer; buffer = 0; new_display();} } Fl_Box::resize(XX,YY,WW,HH); } fltk-1.4.3/test/images/0000755000175000017500000000000015004135251015031 5ustar albrechtalbrechtfltk-1.4.3/test/images/fltk_animated3.gif0000644000175000017500000016621215004135251020415 0ustar albrechtalbrechtGIF89a/<*%/3&9>DIOVJdP]lW ^}su! j,,S87Zde66|22cmony!!w55@ALLedkkͰ !)(Y[Z200J%%2;<vu z#T4Q#dSO-QAvYוn楖f&™bֆ[o}9GgHicr Fi n욚f*WB yX m޴OG" ϊZ ňk.bƉ)Ś),m,kV$Z(}w빔k9Rr+%L, l>`6x؏2vxy´ɈTRԲ@k1u LXvu#,/,pΌJDgLmEQ.IG@EaՕk~)7ؔ +chGqN~(Bwm4F?+SJVP6Suܵ((λK^cg /2x6s&ynKZ='8sԋ~[8P#^ _o}yx/6Kr1m8: FHIJ؄a,Ir`v[B#'~5ꇼ'9YK嚵y`胔>r78dѡմ p!<d8 `+V/x1=nq)!03~9gcj44 NĆjt3RLߚv+~YD'wKMd^ȸ2Oe,(7F .;ĮVgۍZ>0mAP uLq|\ I;f;#W?46d(j/KR>_iAvB0P`f3(|:H I]CЌϤ&LibwbD3)H,c9:$̈Xp\Ĥ$䣧iF#&ih.MaBeE C:A™khQ`]BټNwcY)W s%DPn`g TC6ZR`+.efnA s=}kZK-@bJCM>HM'P~.j=WYHBjI5+lZi\ PȝqD1WIp-<]ŅZwr i5r RwcbS-D;,gѪdJ7f? `bsIwI|&ۉ+3/ wC P,0٧jTf%*W%R["uATr ,J,DCeZN<6cgJyhJcmZJ 2"`-|:鹞;*Y*0{z4ԨAh]lV'7lO3"}Քڮjrɗ,Еdɦש9,` s(0ʞ1S[ie!1Yf~WxZ M0j)U&63/(.+gڪvIqɗ%jqʢoJ,@+qQPZ18 j:h=krXׇ )9dS#/;`zwיyl~%$`9뙴Ț NKp4H-WqW2OS~:X2SX2<®t[jKsI8`kj ,0AazJΫ)0D0>SuRʱXeKy2@8)/3,6zi y {XY U S}*˃ "`+[zڞN۬TXT-ި7HKE^;oJV!-T}aXC6J i9$0' #X̏x^[60p=K+Ҳ!jܾŊ:JjPATqwU%6{Ib)A`PzrI &#1B̃iʂY6 ]SLvϗl`&mʢL''pL/:ʞLK;BsKg0:UX  k K -`|8By4lv6u{v5(Q10;,˅I0`AK5湧 ƚj e̦qJ He1k;rUwåk auuflMה`6p`:WgC>sKm<'r S ,}:/"oy%ሤK+0MZr9\c[BckɘuȘlFViu(p:'?9'C0C6ʃi?!SP+I=m~z|w  NwA:Z(2h'@ ļu9*&``c#`:$* u]d\,"L0A|gWMIc(E1@ٵ$G~a[~|9ھ(RiCfiFg|CT002ˍ 2`?ݳ)&0 P&ɩ:{*R{04B0 (~zPޛUL4ԱzJ`8:%p'B;.Q1d.M,@ѹL-`Cσ:&@%#[tˊĊp!04. C%_X2ӊ}O}lJݴ(ǥ=UTK#4÷1ؚfuOڭa6Zcbdp gq]2H<̡8,p3eW %Z_~VsL)|$rKT^8 xK-.5uoՇ׭ /m<#>)W(Tni,Τp(5~?=iz:"p w 1n%lЍ4~֨>(ȶ2B0&ug'֗0鮻ʉ`v8]^N틘n^&pxНmU{YK.dOb/@] f w/nhr2k#4C9N<_?>.홙L*QnKUt#7.+[mWCb:?^oc6hskni*/v0e 5pI(%$Qi9LQ 6}`&31s,6cg-oPPg8"!  !% ...9? 8 BKKT T^dh*rs-,*xuu-xx[^Z8&(7FPfkgƙ'@Ġ 23ȘAP 7j޼cD`0h#B"bQ )4%M>)Tpլ[|Kh`4vNgOaLkPTibk[;':w8 A ֺjTjd% _,aD8hE 5$dyL.3!X4M4SdX @`h^vЀtT8 ?u5\ܸᒘ,ZuCyw|S^ 5`̔A>M8EQP"CHlTJX 6I8ͦTiE sn6܂  a)dT‚*,z躇 qknX-Κsz iR&-Z( 0/Y1h#$$0*DE6KJGVF QBR(lBZ@LT^nC `*c29:Кq 㲐kfLH0Ѐ d2D `ӿ,;$k_D&Z٩h0w3ącTE+dG+AM$-2ռƆP`A ]C$b4p 92YDHdNP s w8] ] Dch}kY: x, ChXUc}BHn,R㡏-^xy18?/)3I^$E֔í%jQۈx[A[EzRz£g_$`k.fXW*f\[y_}u/8ri\PED CD,MBS9||o+^x Nfz'+œdgkA &20C+#yNrF`=) |3aM1タqMςVP21nAxrbBMnB<\7 Ѣh n7@)x1Ł0pۘ1q sc: Y+(1[l J4V§U[j Hf.q\Z]uL5hC[``RHeQkJ Lf#gD%ЀeIS&dWN0x' ˥ vf$^.?4{0kEW29HH0}A HzQu#` :U >\lKK]+~;P K Om(Qժn[[T<8m4P֨s#3֞q*)KE.v@O:qbFf>qLݓC;~Q]uZagTY9Sjibm9 @!DlLwȳ<ȊV%=ݏ ys7C CP˂Ce(w[R>@f,}`Kh*n]ڎDT pBNO֪X bG!L|R؊^ حEF/#$x-/nP4pV}JEybs(D L.HƦ4 4P@LL)+K` K@Nܾcn P@8ʯ*/?L Efm.t. VP[o3bb ) /]*A0l>P`N-^@!y#&m̈́-!.K#TMIZ6  d0"g5Rr\ P6Ѕ~ A ,Df+K@oSVB±y!T`s8,7"?/R:DTAy !A8 2 r4$Trx~ 00.@P: $Pda.1:Q6zuhr&''ױL2;ɚ>Yt,7vk:@> 24r4?*3@P35qŒP 5RI,)]԰#% #I˅2/tѱK0DŽi0ZxْJFn'{ ^" f v),89} G^B Sر:B? s0h@L238 83>Es>Ms5\+4Dsj~,NtA%Ī0 -<80R(m%/X MNe\e;+81I RX'|HG}x+A.ʌT 4>3e2'2,;G@d> 48K}-z tRCq6Ǽ8g*eWYOEFi4\`2)=sQ'$$a~4373/HS4rTP+ JQ,UuU3>=NjKFE+'<2P`5lΖ$>Y B+$D3dA~4ApH-u\?=e3@zqא@o'Ȓ6)Jo^ 5ʨө3UhliQǴ$z5aP@k,;/ub_#:BM,FP= `>|P6OOHuo[J\Rf!OIsnVDT)P<(|vxKc=8J40tmjtIw^CmivL1*BU;OYC?8h]TMZMrA'gFA3 \1U^*r*55r AHx5QkfYUF;b5#ؙ+MN +{ mH~q9~/s@FXn˲E.rT smp ׇ3DTJyخ@-#7!uN:g9 /2Y2x?̄_ i3tצ#uڎwnyMrqOZ++9' \pϷEm^Z}M%:{4NQ=$$@aY2S[$GNENG3J9[ '+p5BhV}XUpaqlͲg#/KI%|y%5MӞXgAmYZ&QG2/y>:G&䷍5l'z9˷^m㹵Nd1?^'Yr-{j'@;Q dnaqbϲ}fΞh?Zא9ǐ*@gw#Q!!so[d7Ćl홭Q2aDK<[Wﶺ9q^bOШU?5C +ŷ\rA,mg||}v&Y[^mq*n[ '[˵ܺS\qgЯs!['@sqA!I5*q{ P[Z:mq"\J!˱d1 {{qfl/עW!|m:U 4gV=}uB;1a a&=QZDnc=PvCCֆ:hJp\D=ծ@1ە5 }ng]ɑɹYP<%.@|Ss+/$}B8sوI5 hy 9OH[1^]y}d%>gͩD}JA=|[s p~=ya>~EX%H!~X9r5^aaT|~MQTJ2:X^bfjnrvzzͱqeaE-PA$"-.-$ 1. JfEq!WRA YekB6B.2+"J~_ ۧu%O"p O _?/{m7ٖ[7>n$sEj#)GQm֌K2,LHpUA,f!9ACjbE5s&'㶎 9rIrԑKK̶n=C3f0O|^A&^ Dc5F^g$>szҦ5՜C3t2+,RM:73gW|ʗ\A"JTsINcÏ$S,^BmXj>X^=w'Ϭ];Ae!إfVt^DtkEFZzAUoQEM'Uu䇊}(ZQRZ0[hZ)| Jc=S"[zEoO WY6z` "jfI$-Ww 7s):H~xXZ8̑\s6##hdEWfA~wù ]C'u (ܟuU(` #`MGR+{NlTݹ{dF܀Ga5Jګ(5u‹͚2ˠ$2&ieКH!%Z)9Zݘ3B1R7ulB非e+%&UY _z+җ7Y7^3;BlXi쟮 LqVwz"`{+Y\d,-oj[%F*۲V'|AZYڼهHIH^zkmZaUߠ_fwc+gnׂVWʷWַWYmu֛:19qkk߬gZ bgx|㇞~s˳/,sg/tl"8/ߡFjFpŸ51g[ 71L$ޖ4a`f:o40: }KaYGL[h82 1saJ7Ll/\َHBaP!KdHo#X/*/b1x@M:k#um|#Fҍ1yDoE,`ZXC2Pe4sEᑄO$ kUq1RGKEPSXd1E/ƘA kԠ(˳8XXb8pmK7p3*Ŧt;/<'Qы1zZR*NJ9]=l݋٢A&\{8t['FZْܹId©0l'6[ rK.,H5h+Og2)kvyn'Q;S`NAh,GFRc],PsfK4 Yy& &iv']AY^Z"8j'؀}_:1.aL \`>5X)<6sMJK+EvJpa C|DXz2Ěk7#Kb`Oƍ1F&V1F+ZF wq]xbbfxVL%k$( BkS%}tq'Hr1WR FJ+RI-&`8CnaGb.a$_](/f*K %CS+GI,Ŏ$RN>l>QvĴG Q B^i 1(#v#0 0צf KRYQ;ټ@%6ؿ3*kpT2KUH&dn1x{5~s^5q}Lpۉ2݀\NepR`^JmTR;8Jd S)eP,ckOsx6)qJP.lڲE\׮tGr% F`oF4XIYӞ~`IKQd t5(A' k#Xmj$/mds]h?"F3`I4Wdv<#2l4Aoj؛'ǀ8> U!lyl#$ #@PX< 4SG}`8AgN 9%މӸ4Yʳim*S!`5~bRڜ>9 \9%u5Ȝ p>zF}|1`$n]]W\{KE@$rK+%l,5o#%gLl6'W۱zp ZntUGDw{{{+XAW/ŗU|(WtCccKh,iWHWBzJ2 x))- 43'u)p{a҂0|'blp 6WS$nsua]QZ$ -io7!JvNk05s" YCyX1ch*1^*D{@(bC98RUyU>|< Ad[ʄOE TJ<\Usڛ=^SȺ$h0P_%D0S87S& +Ow(<ivVӪH{ p +JHT. ҀyºW~ P &B[Zfh4KA fzj |ǛP jмJ*Z,Phx8Vs$pzd;‰ٹ# G8u*`RvWO Կ#-69I;Z OQ``̛J< [L-ǶA`4'"l]Vag wʸT|8 H-E)F\Z`j l |;ɔ|ɕ Y[ JKl4G`izul/P4>x|zُ/+lP9(Q>0R~Qn Y`˄۴U}ա ڢ= M |Zdϫk0%s- PT}8D0,(Ĵ̥HnĄ Cț r>bz@eWCh }V,4r[̯N %.9p۾s>ծJOYeg뀮?sE=,>K4g:=g٢nՓ,條0h@̘zW@dkFFn}D\DhȀ8%GTQK`mnޜ}I.ޮΩ8I9=srDǮ4C@|ֿH:_pj^C*,Ѳ㚤YB& ؛Uc 9W,C M꛽՞C/`iI OY,Kz&/}8\N&] čĊKMޘ|@G xoBN\:O/o޷Wv4YC_%+ P0IPp.N)bxXCp0|Ba86Z-h^ ad:  %%+!&/)/#!@>AKMJ ?@`nv~r sxpb\ MKI:7=ݭ0K-WtShQ293Ϣ ={0Qɿa!)B)t/a"E*&nzEɺ~M4$[.fdOqC1ōW9r1O`'uHqVTeN#DXlLB>aA1MfoX5@[!벅U9lM=!"C  WWD=bNӌ2hRE1"'W.(}dW1A:-?:ѻu=]tuNgR`ZGðX5֦F@9 <-@1S: :Aj|H6t<]z ƽ=ní$::4b1(ըƋ`vt~+DZ;€E KCp,[O+ P29L1qy~3B=r|Z)F df|u9E$F5aB gֈжUacH1ť6ԷN<Ԣo>s#Od'lW=iIӞC2CA&XoýGqcfimC=T92bt[2|Sk_8GAqF!L7WC:/T;Tي?!2 Ħ@n? h=LrB§OZHդBAfW^9SELtꐧAtHE'/rT:0zq"% u`& {7iUΐ뱑ktyc'PT(UެEMmq?_[r#ӆt/ 5[.-L1$V-̞=u "Aj{Z:յJ9#iCzthrYR lER 4ToQ  bEiN3!g`鿡haἕVWEχWqL הj@4tM[G8:xp$+YS4fU1jUoi`ӳzY}_юsT\5(î6Ӽq.n-l4=26=-5CzM\b܅z5-ow+Z৑%qKti*6}nWՀ֡u`ZCy4,WC[yUm5+PM7;=iZn&_"Q mr趣/AJ] '&=i׹0O#bg73_ruEfgS7e! 9,.jpH,Ȥrl:Fl)zdXRmZV*E_aKB|{O''6ulurYdttlsoyf|kK !D%,N3(Xs|jwzL))-0-'{ (3M3,$T~jZ✻䔓Wf}B-*/12*J̨Gj a#S9Ij}"2q9Qc=e.Z1DU&@aG0 $̺1_}vfP8ґGA+Zτ?Xf8n8p8p]weGj5GP4F XMvF4stoiΝ, F=)$2>PmZB&Uf8I-F+_m #֧&QthQHսhh2((ōx/~sI_3}\,ܑCFu#[CQI:E4{QȠap E[vfSbLX4wgi\}YV(|E3R !B 3@frZa0o-FGf@(D4&,T^_T 8T^9[n (mY0!;±fmqq)`B /Ђ&dSǔ`nEdlTtdp q֐VrO yVEğ HkWʖhnWG'ldڣ[i&gpH%QI9930¥P_1Vh]2aD,BHiAfv+@jlf)A324ۧ%V]z [<$T;^RC+@2 8 S)0,hB - %ؐqUֵWbg%H6iz>+RS!vH5z9`pi 'OUM5 0kghWL|WOJ W4 ,hb;Ĉ[EsDL|fnG^ r?F ]LM2܂T眄.vS`kOjam[,B)J+@yPWߠmE6g;[vXDWV5 yѫ/,5~5]-^º&@LHtj-6 CsNBU0 ( N<xƀǰT(L|b>]gҙ9KS`wԯ^ D:rU[SaФ$e@V4 7-Fk B?S_5ʢV+q$J H4 .H VEІ4&4`^ IZ0I\ 嬎Q%+0_emjcwI>8K!tt!S>З`@Qe<"$` %G[_6w1U8HKd ل`"q^PHHRxGӔ/($ odG('Jq-kOivhHSԠ+] [6.,jaEfpъwlЙ1AIr>_ oUuvd8]-HJl$1Nb gن&MiQy\8_Ί6 #M~ð ջ)p0o  DX)ߵ|nA˽PaM;@~W2P*_B~|^jX}ITWI 0[y S ^%*{7XئAn2諦m`HxלNVzUI<#yjkءIS֒SVS/iCЪ ;wmgnʨz_!杗-w3wqwK:)SJSziI$Ygw7K:UIw`y˃۲ڰIPCihI`(qq寭U%pwwhwc9JZb.K٭* { z9()tZY3'٦H7評 Ȱ3+Y~JEI:gP[ϺY0jIfhYJ+艪-{z 0!j KZUKXQihJ P7[N*0BpbK)ۡwh؇&IW {I;7a99@NZ;*ۿ \; [7{ ~ڧQ/pzʃ׊)%Z!J˺.ܺqA9>hk ;)g D̲,`K<L}JA7C^[YB̏L(̆YüIK‰ƒB0!B<} mT {e;jLS˵ޚEpakvܧy<:~EЪY]ȨSO|pOuv?Z$%xO_pz_W_ɟO__ w_r?FV_/s9 Ï?ɟԿt?/?/_GMPJ@A! ,/pfpH,Ȣdl6ɨtJZ$6z-Ex3`篕 ݋-0n4 +$:w{Ϭ[9iN;j ^41i҉/3mtM|TD]m['^"]zlL gYdlpSWzEJ5[|xD"a@q[RTS2Q߅2J#R_ 0Es?redU.NKl#MCFM8$M+%MMiVq!ܘcfXf!a%YFe865b^|9iөu%(lhJh~)وiG4JLJ%iA4қPZ}tg$ew$xyb"NHRʢ'Dz֙(wrPK,vbJtBۜIxwOn^J~3+v'ڶ\يs4xB7 TI^Z ,\)YeaJ۝+JkE < KZnr0PP튭 A(&O?SCDӬ (Mx ֹfJ4ōtݛRlW9]/&A4xMs37o[&J*We͹" m oD.z q835jxjFg<r .{,oPjrί3nsF%fuի u q  ar 3Ȃ2Jõ)9VBz8m  "!xk hB`&"$D6PIv|865*tFL%#Q#ܘkr< 6DlXVޭ["C@  t1 mh5  P@ƪ.si$z @̥x[[W.A H|qD=EM+Јt7K3a0NT$`F#:WeeӬ29ie1%X񠿔_MY Xrʁh>ˀr&-!Hl WQB*-whhĊЧ5&՚6MEm{Lh%*u!p`TFQfP~FMJc=X^ 9dUQj񏓟V(_,i iZ^JR9V Xfl>(ħoƚ\yyqKx~!.p2"**orZ %;ׯsɩu ӛ2&*6kfƠ6brY"h<ĵrppW|z"kN^m̏ǍıCl2(m{'{)u/ͷGwF! ,/i@pH,Ȥrl:JZجvt3pC&0Az}l|yh><999>>>;=<<sM wzz|{}}>=JRyυ=Ӫ v͢Dp5ܯF=) v @S)n- ˞9T<zYe)#iS ;aGw !BPR ÚF^ÊCɌHUqCQk(  (v_Pa +ٶq93m`@XP<0ⵎق"r.(Y9sH#]upEie1`-``EL+67TcIim䊡v Yg;qa;"RL\>SAyFFZ_0 |BGPf>mqUw MSFUwHWEhZ0B(`GB(7~B_zD &⨐MB4tD&,wCU: ،3 h0vj @",TLw#v&V$HhHOrz J-DK6ڍ C(weBe^3,Փ*@'*ՎfrSj"ϊJjAX>'pi"Ѥ2/lM$;'.VqBFmޯbİJH~:L8슏/R`NGj.Q,,愬C5`+群ŕH8sHPʴ_߭#vPx"5u:d.eLJW!{0(#,B2h`0Hbg@#/xD@@RdIsӋ678 &K!MԾOc# )N/FLh)I!|> `ImPRNhjSs&xb/CQ:^5;ԭ E*f;—!Fxaqfnت +>G YA6;72%$07Ih"YbJ4.T0~dfq:ʢDf!b٪ݻb"\j2%x! U*i:{ I4Xi\33uʢEgF 뉣*K&is.98C>Njrh)&7 cKMI сGՃ젒pf4T %5l&`aDW"Tּ>I2 PXcG0F47O 6אdehSOI;(nF1 tS@4%Yp)A/`i$E,,XCWqSZg˱V4y&2t.tՠf/Nw#6=]_U>~a?NA^d`л5nTTB+jQ 6}Nw͑*flG*+d F5L h\O̶!9~ioa$#Xĝ]Xk̼V$Ef7%O1׳4t+N~mX $Nw e3>B*AN#HKDH-5%#sOJ[/fj=c#F5\3ځ>BW;asIw:>u#˔ EjXM*f腜"|;3nC d׭V,pE>,OvJ`{kY_ .@rM\"guѽcU.~sS|- I|_'x}ܥpYa\&՚ɷrj^B_]Vߦ:ϕGA|l"[q.x|9Nzq~fCxYfR`0'Ϗ YQ[lz{-@'8t8,_/:}9]ï&]-cKp<a2l_0;z+Wk&z#p pgdnvirsse~$|Ƈ&W70vi`3{x;gPR`W$AwdrxeRzJ烞YgwUVF9y\(:' ;K!T!(9qBJdJ`Aط:<dda0(sGJH`z6gOzt[Xpޖt8W;Հ=EqT`wJ~8 KRffh~v Gu~(O@WGL`SW\fvc8687Xp`ƆF" t'h8qޘX(8G|A! 6,.j@pH,Ȥrl:ωt:}L҇ zxL.ɓQ:'-_L|is%  gK%,0234131101/3/-3-/--.--***)))IGKR24554H ",\Hq]hHl ]BH &>ɇ Х[Ν8Pz@n0 N҂TѡՈ/$ꪸ+ƯWɑ*;hXʶG0Φ]ٓп@8)N1ǪZM*E X ł\$nmۺ}Res k3N{{G,E g0 x*j*ZY+GE&]dhWeAsնۂ w(!vX( XSTT1u͢U QWEHf ClvS:V~'#'W# (4 S 4Pr9`DeG Wq61r$^i$AаpCL&M7_|ͨG9#`>9bS BJY.jE%]gE顖 VjU*t"eèkjD'֪W؉`*z&BF2V`/^ "x#5챧m⊸U}ښJ( ᪜s 8 $(RC ,`B D3ҕV9P+5|qk=|;#aeCn8DZA'B) B'U"0B9̳8pA'"F' OG-5TmuT,kAk23,bbwqpMAEjm>PBw $d3 lE$^83'7@C T@`@5Aui:6Nyt&<ĸ__Qog9/ -4kA S?B@9p=o9%tpKFt S:0_= q6XFnp$#iߔ84d!/H $(!S+  80F@)1w6 lL!, 8QÄе.O)C~|QƌYEH4y"$YB!h,TMO K! 0!x8u! a}S؁؈0?  P3ȍdtk"m ,#J&H_U H ]МӠ189Tx+0x.@vW.|'T3\6Dp <\U*P DpV0f/c7#B+XOy@n$bBTbl6!lGp$4&iuB rU,dWhhÉArWrdi\Y*W"s6}%pe .i@b{T67brtHFvJ|U**"pʂY+:!fDZD-gHW(Bp ay׼ !ħ2PCheP5%zj'Fb.,6"W3)ap:$]IWgLfc S306xoK|<>qKCEja3Fh/ՠMf"ڟG:Ӏ4YnʿBNQφ6B *rxQIYUdoqN Cؚs)T_^ /<h%D*qh2@,S,e8uDMT(3r4 Ш40[׽bs?] Lw!떜?Ŧ%a95USHI FXzB ((eh:t LW׻v]XbLcLpBݟ:|&hiLpE:l*U uD!\gG$3/]QW\olJ~1D&7:t+K9Y@# +G$Vd]QXR-TSՑ3-{{m%1wP1SL}B:[z'Yҥ$txQEVpQ33Ǣ)]JX,cSZH{ڗ-b] o: "|Y_:Ba(Lh'}Ӯ $ Yg;,(eqn' eO8o#:4g3kGf` oJfh \Gp.C'luYe9RXIWM' $ŧq|(b!r!|g1VOou}}|%69;8)5hsIULĴ&@!pH*'e@jhQSv7G7M4hAg* xr||$1 2 Tv*':Md =@XecXׅUw - l'HlC{}7{{?]II'a' ܕ B!q uqbr:N1OSH;ЁQPV$X*h dž+x7&Q}aSVp@Fc9`>sOT}F0 ;zd}e`G#H>AHMdjhi088ufUZ[P88 p fq$%d>cY>B.D DcJ` G;`zC5i\v*7~9"[ X=`+ *4c=ƙ#F3kx_hk :@0jOשؑ8dr *2[2,SY5M2.tRf<դ MfdyBUKzU0_\9,l*Mxp#9Mt9=e3SM-ƣ*#SN6@>*6%s[: ʠ_PHiZXET]j?dqRt@Z{r2@*jm YZfAՃ88 .pERS$Jds6v>;e}K*B )zTx݇w&h `ڝBi"H&&жaWq)tgJFsx) #FqdjkC0XvZdj~`~2V)r `pA1JjAEE0 k1EsJ*nĈT@ ڤ2Q> dWJ;XסU. Ft-s$Sr(ZjDCOIpWC)Gkٴab(T}9VoZ  6P~ h۪1xeӹt^l{2r h9p9ɋp:JĪFL Krv[3NȌ0O:}> g"9DĄ`Ի蘞䙶c˲9p \T^4=\xh b$p{FFBpdWvHkgBp} &r븏}D;=6ӻ&ui#@{[8/YDWKPƈG{2d鰴6XQi3iQCpH +0[A0;rRUNUNړ8W' *,%)_&DcwGJEP&:YzDG<*F1TH'ʲQ|oª;[Xl0񫀉XWecJ:,P1C0Jxy }~6Jl †j+vyȌ 9q[%ЏƲ!y+_ql:pw|Ǹ|1q^W%\[CgDD:^;66*: `sTgWZZ{^:}!naڨ2-Jb`^A^q޳`ݠ{}znN}}*7 @d<^:THG\ ^ݵ8?L@ޓ<^މN^Zr^#Wt!$DBY>`[ԊyI uK&6PΛNݩXY륖bRBꯞרmjn=eN,nڢ~9EJrNۓf4B?Ni9P[O}_6C`18Wz|Pe^Z-%F~vZᯎAZ)09@93^ ؏ V}gEPdFI Ho~cS`^Ju^ANm=-1孥^~ARp S|;Ⳝcc+vV}] O@~DCB6T_^@F!oFq.~2/5\^-ⴍ/ÁB'4>B}[n6NmPDuڙW:P"Yk4nT.k޳A6o箥~RpO*h$10. ĔZ=,,B5|o` n nNqbT,m*& *! 2901=?C?370QAG=R797(oq)#'z}  ǷJm2=4BQS"AUeZ"D/ĤDʲ-Ѻq͙NQdž,]voA,nDw =Cq<,YaCK!-4ӾJM}ڒTE_@dB~fƌF(Q7):7ۄq"/ ˕RBReT1LOThBjSLےl3:wЭt(6 $bϡGW 8sjQ1@}.'ȴǰ}ܘsevó;ͽj+8<˄ ϫ';|&BNFуP=X+R)i qk? |%GAI(#J:A% &Eo6@fi4 Cq :\-ogpˍ/@:˘69^4CH*Ҍ R## /(Ihf 0 $@D/U7_sR BF']H3dǗw*!TK.YKSl>$U65iqƉb [%Њ!W^>^+.^l6C/j\ܗ4@X>i5y-otƊc43F,,GLI%tShH-6=5IUR3aYeEW˯baɆjՔYv=ʑ0 ]B3CeeX栍LmmWCiA| pv7<ʍ^*NԱ(?sm&t8kD7.LI]\is裵eͧqچC)qwhF"w'*cGJ,q֧slb STE÷oA|=)] ~mnFz|/ 9s63XFGr(EvlQ3qS Eaڸk4ZD!4P(KO2J> DRpk |#vD'Ђ*Im|0Xa84)˾n啳nk|KIVp9#zf|bWS }M1)O\+o;n1´hvCLdgVnnli0aEtɸ.U*5#Z뮕{-Zwj}IV 2Z8Y7 -5Gu0imRlG\9}%]Gg ij* LL#qˆ+R65gzV(C}Xoi!^chغ5u[ޱ.6h 2fyͨ<.j[ٻ6wƬn d\6w}n}sv.'62Zv;xϺ1~8˜qɠ푯<ǯ! ?,.+jpH,Ȥrl:dJZTd2Z)UvBʃn|N'Nm~~$%$'%'('#'&'%" k    I uM',003338885530%(4432cCLpŰX ֚8q1ULA4a$ɐ!d :ĜysFXdz@ JtH`$#)ROi / ԨyŪVWn1p+] X삆IV|p⡮w5͑Ç>v0 ({I 2f(`kYE]40l)A +}DX\qՅrsQ֝Sw$w!NY=C?' %Z,_ylc]khLm$$͕qTVyוf!`vbigF*~zN-ezY4^ ,Ž}Xҟ,hD lupQśVr>a9g7mp5d ޭNgix;D5 Q ho9lpGL()rZ9X #Og*OhK?ɣ^TsC#U2`F~uۢF&BDjW2%nnu}q(K^<غ2  0t/3ȚK .NELߕ`oHEu؉I<\S`-Ԕ  hhm"Uw4O[ ZL@P,I*!J0EKi]V\ۂ*f$7:Ǟxn7^{ qHT? 1v~udžF1޶tA~AxY=O?3"nB H@b(08 [jF-{|LԀE/=JHP0\`\ a P:K槃"Q*p08fO/Ғ8LI c`Ld pt &E4h+kY +l` $RbaWA( `£ 3!ǍW" BbC$q* 1,` @!iHp,w9h)@vbAs:)n@'U H@m) ;,EW W -\Oe4?Z7 !x!JHpf(@Rs2iHDzg C; :-) SL=-qTE lPT.ҕT(FYq@V1o^ /0ۤPIFX1` үT$#yÙf ~|qZNw4Pu+2, *+$@T -Ba-qRc G*R\\7= k_;\Dv@)( &{ D,)YiOSҕiUcPVu.lov ^yGI nQ=*&&K"W0]krzR9:/05)mUb)iB˘ e^ K ?A bJpĤ-kdW00&@+"͘`a+uJ)Ѻ?$&! G^oLh`5R+b@ItˈLƠH2@xW(#$`qy.G#3 P5LrAvByŀZ[\/?t+JcآoDH+9zm2*ƠpCMƒLS]DVKRb v{vE"9u[^7pvUXp xËU|mJ;y>s\Pzኡ8@VyBPpX/7҇4-tpXUR<ҬGF֙C.pm6dV: k\*@a`chF}m qO8- nE}~MR]DLZ; E5`Cn)%oqiTSCV]陠 PPralHkώ;< :ve(6R!pQl:) /S+ A=dCZ+h?GGA zr U=hV;f'm6dHm&p`LvdB$"RV ae &\g\fsxx3xA7oEIlUbvPU"~I!.2""3~p_VGQwq7dV:c=b$8@rxM4`/HU}9x!}%t(Npo_RFU|bWp~"4x&:hgJ2g%pK'Gh[acmBhOh3_RXiKfw 5(&Dt \`Z&x`4aCj \4}:@t?%ԲR cyҀFX."P&9&zpD8iq $h-S8d/- r` (C=|QUrzi@6XeCx:ss)Caf$O*-Py^8&!(zs"'zHl7hFqBC{B/P8d "W8)ą^W HS\(A4#!%]6kD[q^R01~聑#&ǃO.z vc .e5m@VxwD|S($W)5(SjExv)P4yt^ qG|8g)2 'uӖv*o`gp avH(dh'daQ$%sulB`•eTjHL)$:AIW)k>pr9q3@[0؃z9z=P'`1q쩍?U,0dYu/Pg(Fm6W|Vjxe}%dIف\Y3- Yksyo8{ g%'&𷟭FUz 0ZPJju0y4\'@=)G}x'~ՊefTXYN)Ik}GPg@ <9L5Q TWuR V5]W jF@*pQ3YugQR |2Y5$3j ]9}?fqY[Ig'h@&ʃW$ 3#*$`蚮 `*Z+ v;&/]gF`Qb$}3"zegHhxdhHzʝÆ"DXDTT*Vڣ獋jq`ן 1)*e7UA jZ&0!UP 0@$j'xi0Múx <Kt ISEqD_EK"25`S tcy{ z dQ*_cLk-_% Rԡw3M酃M\vxwjNO i%aVŤQ A`0F~UUZFkp*qtb]IK>k5XD ` u꘴ G~AiezMfuhC@kg[%)Vt>S{tP홷(2"@jz߸ =[qۋV !^ ȴ5 5\P{rhzl`3gHGLjIPk]E]UJdQgr&` t2)0Sj{hʳ? # ڠH ͂ &=n;Dl\He\9CgR :\B"K  E [C;by{5.!.Q\ '@Z^Z)[=B,{WA, ֊I\ijͶ;-;oeJ< MHcjF!Q#:2˳ژ'w<y,*鸹J[3/.0"mi1iC3e?׿fK͂ Iyi ,6z\#2 p8{c}бQE8i6JK̛; >3\۵EXHB9PPLNSNI1ѣlea<*Y(z>CB 6t7:tC`PM.P/ɉ^oC(8k|ݐR24c/ :7VQsmwVsBWI0-*`(>鑾9zq雓9?9g(=kD4ҋ@Eykf٣Fau.)#;^\s#̝r⡝ N~ ޮ^˂0 0c:ēܝ^b!7{ͬ' n wMV ylZ&/:wltt/:8\wdaՍ^܎5.-> 04uÊKשo`: )rf"Op!QGIˠ/_)_?]| ^8-վ  # l(ɂ,r,4V٬o%5a2 TiJLἾݷ 3\<[~xE/"P2d?FCEoq?3,u0NS'^ۼ$oL]]!hoz_'dn.EO0T`˪XŤA BD: NE`]㬟pU,VRD2?Q^?6 @, z^|^[,<_W~  !" !"',/13-8">'#JRf^bRUWW[JD: ; 5o"2# 'GGEJZZ^[\ W\UVĭ1+xG_ BQB 9`$BFpJP(H"ƋNduMbu53W͚/Xɗ M( BϜ9{F虋Aֆ@]!u6$E% m9sНK 2צ rj/@ &  ϊFYxg&`EʫNQNL5j9פLah &T0k!mOm[ZzEtZrȠ#Y]S A ] y"\A B8Tӕ$Y2ZX`PTƢY*Jhf≗%tH"AZ+0( Z@"⍛o>xF8*;94E(cy.Atk ëeB{%c' J1D@䀄.KS.KKб#G5)z$I@=50O?sOB, L3C5XQD34$RJ-ŠM9崀tQG-4jc5 B,B`! QIX#!Q@a `ެ5l$bd3$&G J҅``LyXzW}=`.X6`8X (avBdn6^GZeծ#ב8`!/4deDv4s46ā:aeDGxiy_zW| 9kN6U )9r4XV [-o?G~-'a]bji֧bDs!"!"$7taUS^v$n}߆@_ vx P[A03'<[ծA"/ɑdɘ5_@p6„j0Ξ :'HEu,jH*ٻ~5*P#[W Cm`GAݠ= ˕H~@-D{`=4O2 b@\Kܝ4O hb vtu^MXpKmhgZ[/Z_mEecK!Sv&1a>Cުy6TSG<'F [';[鯧ͮgy80q#*oV{wiಾ^t.7SH[S{ *>ld4hvY~ݯr6 N/w߄Rel/M N XnaІ^I6oҨ8MTF 0e NM^, wZ. Hp bΌFpJ H/d ЧdpPFˌ & &lB-$Fr(!XyJOxRpb [)60xI ))qw$hoάзD|a+-N4Q-a6ppwڐwL#=PQZ, n Aq )VhDF6 _/ K"( (1ءTBnddB&rͺq:` !lbq 3"kZ>خUlD l Ԍ^ Y/,b!Q _0I #flpVF[r*jީ)x Е24r R?@2pb͈ķ~+.bgΆ&+p0͂jk6-nG޲ p) Pr /9 .:9 1!12EPn#iK#T!B͎iJy;38 bhbHs91-6M#rڬ7Mq7p 3yÅ(S\*V0aBp`,r2+O_ +vd)]AR4a!ڑJ㿯QE, 0Т [3`̘K7wqFo|Xb3j(N1 ÆK!2ʕc̈Fg1^xbF/R Mk[n۸mAE)kP )<_nģF_aO6W5 b8H؅*ve "e2h 1"h(Zj0 37ʶk+#q| >~`Fj`@, .킁>Pe J%^"eB(-kip $wWorx#x Mz Vh"&a{}mvҠhbk̝  ,lck-+hx:.JG@ % )Mce2mYh<$@v>ÓingĒ:D2ͤjjkY1v]@wX-4Og@àCu WJmTjahBL0B%rZKIyk%F-nq@\6"RJ j+]#v+Gi"J( k:,#gIK4̶ Zj@%Jkڊ]*`dy p\O| (E\l<Cv d0(ѻZ0(2%HĀS `.tr@4mprz{vkµX!BpғiTQ vp!\6!.ELŷ~@9ả^ cwŕ4&?$BPM@CƑ5 Z$,Z':87lhOkdj:M@&bq `pJ(YrGg&BS-1.!V%ؘ\S& ^H_OO ,udwǬ `0ZWg9Tl=B9(3)&_(6^Su`_Btv Ơhw*V9- L E8AYdq/~UrS;kDs]]g;MN`DA ""~*#d+m˕*<[Q# fDݣũ@8iP i}a F-ֱ,pK`ˬmm P ]?=6yj*(ώdgΠ1(xw nt]+?1p ezG>j+t,,PxHs'9F؄GU[fBvp{P/O$vPcG&G{'a8 ml؆0nQDBWr%rGtӘuR'4eEHa[uzOM: Y i  eg|]ЖX]%E#&\$@V؜7R.!&^Gj;uCkAߨoooe0 KKP (C DqCbǚqZ|`j51Wl˜mmm) n%PnR!:="'H5Q"Ó-j(`9YYVZe9ɞƙIQ$/XSYٚוH|f pԕ2& ðn]" %҈"$r.D(!2PXdLlLܲi8_8ZxzZ@zpB:&q:5W8jYZچn9uhr9v x )~(2&u<-{9kqeSgZ)~eb/P#z9fZ`  9}Ȩsi ij  g^"=43X`[,uBByg9jke׉<аз<嚒XJBEb|yY: rH+؁Jn s's*F [nY.ӵk$:`qekIRGz%HzZܰz [u[uؔI &طEj/QjSZ|441GkZW9+.d ^fs3b D3Lٗr:~Et}&6~|`i VuPz+ Kkb'#25VӮ*qZ+J$jFK[xc\ f )#5b&?pZI(`sLqLK3iKbZ?eȉDzͻ@paQr5VsU!|? 0h@)|q滠owrg}z! 1{N*,ɮ3 ~~TR!L%0kZ]\uܲc ,hlvq8 51rIA4\  ;b- VaTV TL|>8Xfiأ(fx귶|ˎ braOl<[c#*b̒$]ڛe+rF+d)P/PN| \kY\zL"!jϟI(գԀH&x|0L|Xݷ{kFT2[2W:WVZBW4NO\]bec jml ju4<|}sb ?  A@ tQF5TH[X?xil 7fl v񧡄j( :`X{u)$. bѪ2nfgenN'@(" ORpT =t\/ 5qe]r+\I%PD ER{g&^TF PTSKuW@W_k#U:\x)ܪ׭af.=n8VLlƽfKily* <yW =F5|taz p߼6$I^:Q5Vu VZiU:'+`v  VXbˬ<ʢlʴf/n%`ܮͶ(n# H-B  ?7QPlnMsl<p,s ^8#b$oWkʐDzAKde1{y^5䁧E\2D/Nk`96e(l]<&y *9y8: 40z#N\Y̧oZRӱEp#Òr|K*̺I=YW3`OU0XE6y1!0ŭx`r5ݹwA!` ވLdP&1$BB/GHG`oG07&I0@  +:\oYyeLD^ۣB/;ګ١+l Q^ B扑mm; H\TEɈP<tI\QpԕD ]D uhCZGpSt'Tx-;aA Nz!-u) @"!xCcnZS)E;bR!$NuSo3%")O\Y$I|g7D +Y3Ѓum bRAҲ,`qOVqE&kۏ0m,DN(e1[\v5gMpЎeiEcԊ&Ei4ؚF%(jRȃ%c*oJi&q5*7xˤ67~5CRwZpm ^ȍWs}%_TB<;ͨC SG 0!@ fj\a $礑u뼍w ,l4mbi=wOzP,DP`*".+K\׽f]Jz^LڷD~$S#[ܯh?En9a߮Aat HA'u{*ǛKsٗ_$=*H VTSX NM&`*d}Q!SxamN{8VXs&:43ëcY>N)Ld6DnۑGJ?9.Z%&-ɹtKoWk@U7Gs@d4fFPv'7x&"Ўwٶ"Nm3˒) !vɑЈs<0Ջ~7odY@`P|_ɺ;c) sݫK|OzQBzlK aM=r[3l Z9 "U̢>XLc4|on}sI?4-hݍ&{9юOS1G}LhX偪m sw1=b$U{ wJWzt3^8+],*^уb-"R#Y)o`mo9WMaÒb0ije~(זo׀%XLqH0~>/)xXMzyH>efgƜMF0rzBO(((Ǟ&s MK0.pMi nPp/ح`4ڒ,(" m/})  lxM;}RJ h - lbr PfHyl.B/v9/⌺ N ~lq(薃N0mhN mod}NbcĂ 1Q**o ĚDlryon-R )Lnn ]-F//99jmM.c o֑ P,p)RQ!]^2Qى +"MM% OppXq/3 qqfNM%WMQ&p.'r-SbR9Tq99fZ+P0##/-de+΂1|-s!+>a{" @4qM;5rA16d6ߧB*vC7SlFo.eTF4(4K}pVtJpߦ*,5l##G7sԳJ;3)0&LRoVg.So".i>"ĸ;!M3Nm{6sqMCTOQ%8t:m pFUU2iUL OFLq)/A3rM5H}>*ECORuZ!YtJTDGyQ4PWI[E 51[yX1HSeUIB*UY\ZULFMUl[![ `{:C"kIne5/O5^KUG0T5d5%[5DaP3 25.^1`O1R^UI +cjT4TdVƃdaVW/YQfo+f2дbQS*TCLj OB/om4iUDUjUoH,k'NUULpeܔlmk$AYCY3nVnoUSgOvoa6DGtI5fM0<7(^m3t_3wc5yig5[t1p)]RVxߵbS wQ.n|e<0B//b#6gvw}g{?6Im*ݑ7ws'nVgM Dd~#X]u]J7H5dB,$P| =rr ^5s86NwHa]s!8c񁛲ipl}K p{=2rۑYۖӉRfmXj龓iuxnXS5!H95$<2TYrZ#xUxL؁Xxs+vb/q6@vc<7cˎ-y.ebݴaHvғ1B0kQ唍uؘ^9Z3s>V ^s9 M֊U#9r{{vc|9_|EZoY9.Iטy<'yӄ'OXyYe\yj-y85Жәڙz:r嘖eBUؚ-PcТ]yFzgZն6NZTIz+1:Ԧғr.5Q-SUzO6tﵞ31w9mzT{[XY5znZ zŷ:;suLC÷oM5K::-ۢYٱq񭡘Euwhq6]xFw;fltk-1.4.3/test/images/Fl_Value_Output.png0000644000175000017500000000107515004135251020617 0ustar albrechtalbrechtPNG  IHDR2GbKGD pHYsHHFk> vpAg2IDAThߑ Jc1)vZǿ `ܟ3N\7aeYF†"z0wC0D_ 3jċ~FSr"9Z5*ɚ'yػyLHy<.6rVdQ`&Mz6Þ1o T?0s{yY;$^^)4&zR䗔Ҝ06ŵjډ$diX0Tu4Y#5=~Iޕvuc S0I[m8]nSZpvzi~%\e_}葥=" r" r" rYwU.dȡզ]t5ȡCJ) r",dMrT<ّ6c 42H)D@D@D@v##ǹw|ّ~-9ED4bp;oIENDB`fltk-1.4.3/test/images/fltk_animated2.gif0000644000175000017500000003051215004135251020405 0ustar albrechtalbrechtGIF89aFffggghhhiijj k k k l l l mmmnnnoooppqqssuuv!!v!!w##w##x$$x%%x%%y&&y''z((z**{++|11~11::>>@@AAAABBCCDDEEEEFFGGIIIIJJLLQQSSOfYY]]^^ffhhiijjmmgvMnnooppqqssssttuuuuvvwwxxyyxjxk}[}\~\~]]}q^^^__z]^^^___```jkkllmmmnnĻkĻlļlżmǽ_ǽ`ƽnȾ`ȾaƾnǾnǾoȿaȿbɿbɿcǿoǿpc`abbcccd&! NETSCAPE2.0!Created with GIMP! ,FH*\ȰÇ#JHŋ3jȱc${BIɓ(QH9RǂSXʜISf(2ATTR3䐂{JѣH&)5J#@UpJPTB(լ۷Dj ;b݋TkTnӭ`P6 U0D +EAp |yd_Z.}YsR P!G!inO'Mq5^tۿFʻppq", 9>nVQJ!wS q<拢/x ]UidTG~!b8GWTHR  VфEeaĉ(,%.֨&T!a/duXBSvHT 2AIbtU^f PWw\C!$AKEONESfXD\ ԙ)AWhIĜc99]AWZ5藊D&D7Yih}*QH*Q `xʜzẠ@NSmڤ F! 6Wg$tR;a[q+ ~%F&$ KKn[dދB%0CF˩#P /԰Uot$WlDdTASb0,3ѐ0xdeElrB>'TCCV4C8;JYh!Ȃ,h  Wڤ )_brV,b' "~ӓ%!ܲX. Bc^+_\AlD3iQ.l2 +ٍf%|/Sb S3Q{"dY*Pٷpa*1@wƒiکkٺKܦ[#.)+G#mȘV!(arfV~y4I;34@,]Mtֺ F*{!p27R3;hq z(N[u~:GV7zݠ`4 ~*y7v}AQxU~RQ Uu8D_GW1ȡR!V цEeaċ0(4( %6(&T!/dXBSwHT :AQbtU^d$g DhqADNeM]9UmA`Q)ԙl&`}VfSpV$'q]1 ilIY Tj]AL|eP(hJYi@dqXhPѨ@hQVXk>kDlDB(ȅTVlyBQBT \fUg$Ѳ}~_[T+ Y0RI/CC"ǝ7mPC5P`F\j#DP/Uot䱷 lȈTASb@eV*t$# ,A rDR%CJ*PLBp hPQ܁*WPAY@<%/{*² SR f4 [.fR).oAY>1sr< ;άS!RIf}8Ab ÇQ"DAY*Pٷpa*1@wƒiکkٺKܦ[#.)+G#mȘV!(arfV~y4I;34@,]Mtֺ F*{!p27R3;hq *,N[u~:GV7zݠ`4 ~*y7v}AQxU~RQ Q%8D_GW1ȡR!V цEeaċ0(4( %6(&T!/dXBSwHT :AQbtU^d$g DTqADNeM]9UmA`Q)ԙl&`}VfSpV$'q]1 i9 lIY Tj]AL|eP(hJYi@d! XhPѨ@hQVXk>kDlDB(ȅTVlyBQBT \ Xg$Ѳ}~_[T+ Y0RI/CCǝ7mPC5P` F\j#DP/Uot䱷 lÔTASb@eV*t$# ,A rDR%CJ*PLBp,hPQ܁*WPAY@<%/{*² ,SR fف, [.fR).oAY>1sr< ;άS!-If}8Ab ÇQ"DAY@+PIҐ1N=WWB\!Q2 -[b85at'd73xof7*[ }߃{p"oן[W&(9_?yө(=_qyl+:%]:ڳ];qs;-,d|0sS56l d}G&;{Ke<&NW]Fw |pL6H=WH 5[`,h;"dD .B|lH8 UE>y&T@V;XÉͅ 8RU6:;%dK]CD,H,Bn."An@Dc ̈^/2‰><dPH s! +@R%@ ( H&p1\P\U*SPY@Q<%-qeK' *RRbrA1 W*fR-kY>1orr< 9eΩR!2Rܑ |4Ab nVQJ!wS q<拢/x ]UidTG~!b8GWTHR  VфEeaĉ(,%.֨&T!a/duXBSvHT 2AIbtU^f PWw\C!$AKEONESfXD\ ԙ)AWh̜c99]AWZ5藊D&D7Yih}*QH*Q `xʜzẠ@NSmڤ F! 6Wg$tR;a[q+ ~%F&$ Kیn[dދB%0CF˩#P /԰Uot$WldTASb0,3ѐ0xdeElrB>'TCCV4C8;JYh!Ȃ,h  Wڤ )_brV,b' "~ӓ%!ܲX. Bc^+_\AlD3iQ.l2 +ٍf%|/Sb S3Q{"dY*Pٷpa*1@wƒiکkٺKܦ[#.)+G#mȘV!(_arfV~y4I;34@,]Mtֺ F*{!p27R3;hq ,N[u~:GV7zݠ`4 ~*y7v}AQxU~RQ U8D_GW1ȡR!V цEeaċ0(4( %6(&T!/dXBSwHT :AQbtU^d$g DhTs99U4Zi^tTYZel9EYlLdPh YћMYќtŀI'1} (eRDRRu} PhiNZ]Tm@d&UhPѨ@hQVX>kDlDB(ȅTVlyBQBT \1Tg$Ѳ~~_[T+ Y0RI/CC7mPC5P`F\j#DP/Uot䱷 lĔTASb@eV*t$# ,A rDR%CJ*`LBp-hPQ܁*WPAY@<%/{*² -SR f4 [.fR).oAY>1sr< ;άS!,RIf}8Ab ÇQ"DAY*Pٷp1a*1@wƒiکkٺKܦ[#.)+G#mȘV!(_arfV~y4I;34@,]Mtֺ F*{!p27R3;hq Lj)N[u~:GV7zݠ`4 ~*y7v}AQxU~RQ Ue8D_GW1ȡR!V цEeaċ0(4( %6(&T!/dXBSwHT :AQbtU^d$g DhT]r99U4Zi^tTYZel9EYlLdPh YћMYќtŀI'&} (eRDRRu} PhiNZ]Tm@da XhPѨ@hQVX>kDlDB(ȅTVlyBQBT \&Ug$Ѳ~~_[T+ Y0RI/CCb7mPC5P`YF\j#DP/Uot䱷 lȘTASb@eV*t$# ,A rDR%CJ*`LBpA#hPQ܁*WPAY@<%/{*² A"SR f4 [.fR).oAY>1sr< ;άS!,If}8Ab ÇQ"DAY*Pٷp`*1@wƒiکkٺKܦ[#.)+G#mȘV!(earfV~y4I;34@,]Mtֺ F*{!p27R3;hq &N[u~:GV7zݠ`4 ~*y7v}AQxU~RQ Q8D_GW1ȡR!V цEeaċ0(4( %6(&T!/dXBSwHT :AQbtU^d$g DSq99U4Zi^tTYZel9EYlLdPh YћMYќtŀI} (eRDRRu1Us`@ѣ9jNtiRN){9ŧUA@EVzjoJ*RJEYq`Q\zT @N 'SZA FQ &6p`F .~>DnQ>P.dFJJe KTx"dLB0C  lOPB]PV߆,A$aB(S+O)<@DC~2XbTRi!GbV.=P3'tRk@udS3TSV}C(2JǕ8͟ -Ӎ6\bDua|',pmSf0 [<%q"畋]u٧kW&(z_Kձ(]_yp+:Aۻݻq{[M_md|sS;m< G,Gi|k:f\0͊ާ,,X]FꧣᏀ |L87H=XH5[`<#eD .@8}l:2>z.TWCYCх 8T6Q;=EeS<^OvEVTArscY r&Z$` #F{I,NLml G =((8DpkdI`QDL**q*W9Ki2,O@C,URsDH'/%z_Z1 hiE{ h94Pr96q}S4 |\Qiwj- @:42OІ<!; '>]qI"K+:p҄vdh R:*I&Sei҉@MQbT"(:]GҊJQEOZ*P3yFpcRj׾J@;fltk-1.4.3/test/images/FL200.png0000644000175000017500000001216015004135251016262 0ustar albrechtalbrechtPNG  IHDRd1b8IzTXtRaw profile type exifxڭgc;sC{`?xte$54 "p\䪥&-v~}^sqWu"r(_k]9?og|?u&k1I6}__/ihW|]~w_H%J+3Qq}glĢRt|Hȷ?oA~s?"eyň/=cuDngw] - !O«?W㥾 O?xBやz8a&Kc3='(NߌۥpmwW,\r;O^i! L}bź50읫$nz$pY`b[✸.Ppu D̝YLH KH9k5YyLbQR*ը109T,8P)Kι{IEJ.b$kRs-VvM*hUզŖJM[kGי3VΑG2(mILyY6+-hbUn[ve׭~ȵ|ʩGO;jZHu5ZClX a5DC0 fK9lظ 1 b>O-\ sr~7-ӹy{2`=q1w?t ZI^J^VDdgs ny|J>UP՝Xװn>\~kyh1Fˎk\IYS%(Ǿ$!Rό-{{j ׀Fchw,n:3kOgHTc+U6;׳+~=Ulڑ5R\{3ux6F,aq9bYώC.Wz՝:)LW6d ۟U\fTA>IG;~vȳo!>3@MEہ"3ظyH6͞O `oy*h$9m~eTL aĢ!f>]3$h['ѝU dA\ G$mGK$P.ƭXjuZ04A+hPc4Mib\!SC^hU.K"ڈP||ohmX"q!/K#L:D?1%wL:h)NsgIs>-0j}8~vl3&y-A:(KVc~bL;3iVSRc禘q(}x6a K#)њPwYB˂zY1Jޝ08xArLICwHl^AM~T:+x LufbRwba¢1EyE aI|5wOҧr=?Nf2m`0W^o)ޘH |] Qa\(t0O-J̯5,-D_Ĩ%w>7Mٵfr׵Fdɽ:t}^Ʈ8cIq=MjLTWpiO#{[~ ̾%lp}L?otDfNuMsrC!Ef#'H peےtz!z(@|FO4-RB) e =B0˰5e`W7jͨaV=)Gc'Ugz=PX@YnߺwGoO=6p<7(_K85bDN2p0_*NU={O&!}v7GnJ7t nbslpy=*6+,#ݹ\zEznYQ}ݟyDjlOph ͣ;76g"zŧ>NO8hYHin?km'tW9Z*ggcJ$mqTloy6VzjjɎDMm=V",DJW~zEg3!ۄZPmëdJfṜ,KǝNƛ] MdJ f72:= "!v hLAIe#-ciͅsT)YO&"P[f㡐DvQޥ*紳j+ YЈFυZ{4lg~Rt87;,n-r3$d2FK—dO^_ ޭwO<<0I6$ *–ia9B+ZQz & 9ֻ-w~:H]%[ʗ<2)!9zY|}H2N{nOiiu1B\6,D[4mzj}X.rQD_R DY%EN{ twgOl]Xzrj0a?-Q0eR{1w:+?Ք8SҎt"Ͱ6Yӻ9c P7O0_CW;7{dP"P; DRyNefA2{pƮe2v"F6h`3.ˆ[`ƕRH˹ﭳ "'\ Ҟ3/Hn˨r=29?,>ẕT\z}WI_+zzKV'NQ* 0uҪ$xqK:UYFF$OiB hAe.|+}ϲ0W6د5D __ŊղQtBb'F+iw7kƽY:֖;f }0dQRBdKlK4B]GX![ಃ 7x=K" @;=\Qŗii,+ƾt8 _7 f.zLCl2|ɪIX/S&viIpeo2k7>x2vt:[BDMжq}zBJoV*3Ŏ+D)T᧴0_R-iLF,!g%bl;!s_wl7*^f|ľ َ=^qΓ*"B#,Ehy`9c=@xhl»!ePcxZ Qo{vx3x ƍ unLiCCPICC profilex}=H@_S~T,(␡:Yq*BZu0 4$).kŪ "%/)=B4mtLĢb**^х29IwܟWX ij0m MObyY%>'3ď\W<~sY!3'&VMx8j: )U[b_+\9 "Q@6"XH~KRU#J ~?ݭQq>F.P8N3p7*0Izm⺡){0dȦJ~B6 7[{뭾 I]oC`4G-ۿgrvBl#PLTEal!%y02yMOuv˙UtRNS@fbKGDH pHYs.#.#x?vtIME  /iYIDAThN@>}&=SMhkm;C3e2˗e X,b: (dzeSat) էMˑԳ[؀6,] 7l"+#B4#0"8L ȣh rWސo˧ Ѝ  EeXPBk݈ U;(ҵhDPG`HdFW!{Y=M#8fjAVHVa_HGO7$x1"m$tVPbqݜ]Sş1VJ3]f $6O!f J X)W忐z! [9Kt$H{XDBbXzuHCq! - DںQ Ys1{USObX,C_IENDB`fltk-1.4.3/test/images/fltk_animated.gif0000644000175000017500000034350315004135251020332 0ustar albrechtalbrechtGIF89a/?!*%/3&>D9IOVJdP]lW ^}su2y j%%2!!w !,,S)(00J22c87Z66|55;<<@AGIILLY[ZdeedmonkkͰ! NETSCAPE2.0!Created with GIMP! ?,/pH,Ȥrl:ШtJZجvxL.zn, wNd/|| ~caa `loqy{cehmm~jil O̟㪁gkp l%G_е[xρb7Deb44P۶S"\1ńwÛ8!Rdxc)O6hQ,5 p+J\u6#̴P3ku3~q:F)-i$xzVvYckVٴi94?C~|iv}DS{Uvu z#T4Q#dSO-QAvYוn楖f&™bֆ[o}9GgHicrFi R욚fZWB yX m޴OG" ϊZ (ňk.bƉ))Ś),m,kV$Z(}w빔ki^r[%L, lF`6x؏2vxy´ɈTRԲ@k1u LXvu#,/,pΌJDgLmEQ.IG@EaՕk~)7ؔ +chGqN~(Bwm4F?+SjVP6Suܵ((λK^cg /2x6s&ynKZ='8sԋ~[8P#^ _o}yx/6Kr1m8: FHIJ؄ġ,Ir`v[B#'~5ꇼ'9YK嚵y`胔>r78dѡմ p!<d8 `+V/x1=nq)!03~9gcj44 NĆjt3RLߚv+~YD'wKMd^ȸ2Oe,(7F .;ĮVgۍZ>0mAP uLq|\ I;f;#W?46d(j/KR>_iAvB0P`f3(|:@I]CЌϤ&LibwbD3)H,c9:$̈Xp\Ĥ$䣧YF#&ih.MaBeE C:A™khQ`]BټNwcY)W s%DPn`g TC6ZR`+.efnA s=}kZK-@bJCM>HM'P~.j=WYHBjI5+lZi\ PȝqD1WIp-<]ŅZwr i5r RwcbS-D;,gѪdJp);r=P=00zY;:),TT(92PiY2/,p馓AnT{UN~MP$ )w@4VFoٖpYYșʹٜ;З[)vyؙ=@0fiW?1P7p9ٞi760Y2yN얚[ u¥~YT2p9:8pbmHZ8ڡi90P"<`<z$w3$2뙣ٞI٠"Ew{HAh~8i: >7f? `bsIwI|&ۉ+;/ wCP4p8٧j+Tf%*W%R["uATr y44DCeZN<cgJyhJcmZz2`5|鹞;*Y20{z4ԨAh]lV'7lO0);"}Քڮjrɗ4Еdɦש4` s00ʞ9Sj[ie!1Yf~Wx(Z M0j1U&63/0.+gڪvIqɗ%jqʢoJ4p+qQZ98z j:h=krXׇ 19dS%/;`zwיyl~)2'`뙴Ț NK$p4H-WqW2OS~:X2SX2<®t[jKsI>`kj ,8AazJΫY10D0>SuRʱXeK0y:p8)/3,@zi y {XYU S}鑿*Y˃ `[zڞN۬$TXT-ި7HKE^;oJV!-T}aXCJ iY'0. %X̏^[0p=K+Ҳ!jܾŊ:Jj+ATqwU%6{Ib)A`PzrI ,#9B̃iʂY ]S Lvϗl&mʢLy.'pL7:ʞLK;BsKg0:UX  k K 5`|8By4lv6uv5(Q18;,˅8AK5Ȑ湧 ƚje̦qJ He1k;rUwåk@ auuflMה`p`:WgC>sKm<.r@S ,}:7oy%ሤK+0MZr9\c[BkɘuȘlFVi0p.?9'C0Cʃi?SP+I=m~z|w  NwA:Z(2h'@ ļu9*&``%`'* u]d\,"LK0A|gWMIc(E1@ٵ$G~a[~|9ھ0RiCfiFg|sT8P2ˍ:`?ݳ,PP,ɩ:{*RK{04B0 (~zPޛUL4ԱzJ8:)p'B;.Q1d.}4@ѹL-`sσ,p)#[tˊĊ $04. C%_X2ӊ}O}0<7bE/uIҡ5x͡4P cQ5?-J1Y>lJݴ0ǥ=UTK#4÷1ؚfuOڭa6Zcbdp gq]2H<̡843eW %Z_~VsL)ü$rKT^8 xK-.5uoՇ׭ $7m<#>)W(Tni4Τp(5~?=iz:p w 1n%lЍ4~֨>(ȶ2B0,ug'֗8鮻 `v8]^N틘n^,pxНmU{YK.dOb/@ f w/nhr2k#4C9N<_?>.홙L*QnKUt#7.+[mWCb:?^ocI6hskni*/v0e|m@PV.b,xUn|k5I3;dK !Pp!pqAPQQ@ !rs tt 5@@@U@积FM$Bx("i iH(:Zh:;fǧ'|\|CZZI~"8"C*k-\ 2e԰"9(GϞ |IB %jJ,]ɓ'H*+Zl ybXRaN*C&lԬnā\8s_pԬSe^'Q\үJ:\hf!5dHa"E;y# (D# Vvv'h p*V 9VZ+x,C J:׬eYFZ#v*Vlꈻk&#ч.[2FaBgps`O$9h`" @eg:&Zq v(_dr)'.P1Anha,t:+ xk{j eaq.jk ,! 蠨"c#$ڃ@(BJZ䤔8LL.YPML)'4Y`J 0*xnIdQrf[Bw^ Gp1`H+p'2pɁl-/!Rj`H@l=C3O͏ вE6I,Y^inBMTZ oِ6>lFI4QHaʘTS**WG{THVWze~l%ϋ"W^cȨdX0;JeُqMG\NPHX-O=oQpAceßbIWśG}b^K&.Gs> Bɦi&G4 v]cX aR.ZI G$[Nl\qU[5C_ymDaM Wv`iީ߰wSǃ֏9b'U&aWVX^W][ 4(dd57pL:=cqp&.?7C~e>@@ :UU *AzG7p`ؤ64"Rb5 }I_ԣ oiOF7iZ$p,q &ԾTL@܆b\4@x+#6 "-܁]!ȃ#, ܡ$ߠ*ʣA+aJs LV(! l M\HC8%q0ٵhfA.61 z6r1CyV@E`,AHHcDf"ls؏u'$ wV@He_ʠ15(dԯIEF2R1q5/<-'t1XQ.itkp*6:VL,x4@=8m)|X(kC5 Ő[ٜY 6Ѐ6 NrDZjyS f$X-B9"޲skE 1Pn~8/48qxu؝0&@v `xI ׼num Ĺ͘pԢJ|s|2SI).kYlཝ^b?ͿCc%Աysm`i -1ܝֻ5ғ<|W`?pf+O{ʙR (|̵?%>`[M: $25ybyH男m
V V``XXSS lJm ``7x㼏;Dh ,o4cf@2>X oD`%Шp PE~N" ِثzkzW p\1^'n By"Be%^8qQ 7ݏCs0 _ 0>RqjQ[BC4 hMW\VGׄ10F cv. dq۞@Pn<BJD0&ɑ&EpdЫd@؏k#`@HVd FrlBwqn-r (ҳ6(#w$~!. QOư,ytt&k4n"kx[(e(o(>2kC@VP?*Cr04OOPȥ (RR0 k"˻VH$O qyyFHR^olJrrإ(ӅodH2)$"(3jc23As3+*r*EJrJưsl6S16򅺳cQCz@ŐCh)b =SWyt\@$7ndNkSF;,2j($*2gF@34M>H4S3}B* :J TD p-ٲ'S lsўN]rnx$;:/E' ϪH6HmX{>GGyTfk@6`ɈS4>Ser&+1g4d4 t4Kys-kJLt'q̫T.ư8{%uE?>"֦LYl`*<Q!$Az23s3)HRr42O+ۇTP~,OUγ=-1Kt74-p b `Tcdt":m0:2@zt@0H'[>[@eGnq֊?[!'R6Jk3^4tɖ,i3e@hhG'Ȥ1 `&uuH)z h͆K 0/L@b/ɘ @le 3gd[e[`4u*[v r*GfCDu C"gŌ|oH1n36cED DrE@7:sߥio>M&ӌhA(Ƞk#v5oCڎuOԔ.-OX$d|R|)0sɶRW@ey[@RU@F`S9\w1PȰ;G~J5q%0!n2 (#BQ4LG`5` uLdtGW!X] l#KX`oLg{+Y%6eFֳF8D`>r-FE^؅]>`g@atшJ]#G5|7WpdCsR2#Y#c1dl;!VbW>64 Ċ YELvD11گ(YDz3>*M6phSRJhP]9#NIYjׁ3LX.gIe7KD5l5JԘ_9=-s=[th|X\E!SwyX fwˮ@D$ Zai1?"8ؓ=uǤ5>̄1ӸgaY-(yGNnը\ɵn&+ԩ~TTl6˲q*<8P]XyKf!Vv/]t"LD *C{ǚg}cy}+?:xMʪEqB+ co'STJyתT@"˷ 'M,ZYO2y1>ČQ[:2hCgq葥xAxfNz*.+Y '7\fV _^|9$,wtM=d#HYvX1%E#MMG2@r9wZ*05:B^vqU\p g[#DK;#%n$U9M՘Yف3ڴgȬgYPP;$#sY0v:̇%Z5&Yy]_ԏ:N%9?PGyC~{dȼg?PmpToJfΝ~(?ZւY 6 &"= gac)c^߹C[2S6=Zwֹ1 qP|TNu9uB+7\^+ifns6ZNp|jm{G#{ʧEpLJi,!&:eܘ]aC5"b/U^9$>J"<62*%6= 8E]%l!o-3{IiWuM;) :FV[˻7 Na¢SJf^= # 2Ҫ9ߴXɒ&L<ɑvBUk~QGN~;!s&FD ):Q/vh7k^1<)v ^L"Ash\Kn}6 ̶&J1tƞ:q4j[Cfr7?ͬOJ,i ]%vzOZWL\E\4Ȓ6Ъ6pMm :C1Y:Ђ׹ {5wC*"XmDƬfذd7vq䔳ѷM;YB_il]Q,!q]yJTzL9X])\H^(daעfLSRHa7_^/E(QT4Yzu D 7͈}Uيa[>'Jx]gld"5ؘކLB!QEpYG܊ٜHYVǥ@UaFBʖZU)mBf`7y!$TZth3c|u4G7_dZsl (ogۚen:mivP6gbJYe'+r7nywb喔.Wn`TN>y*p ]u(sXGoEREshHCU[Cnԓc iK"E&>ƌ_ %0iSb,b ( %-726rCN-{_PA! ?,/pH,Ȥrl:ШtJZجvxL.zn, wNd/|| ~caa `loqy{cehmm~jil O̟㪁gkp l%G_е[xρb7Deb44P۶S"\1ńwÛ8!Rdxc)O6hQ,5 p+J\u6#̴P3ku3~q:F)-i$xzVvYckVٴi94?C~|iv}DS{Uvu z#T4Q#dSO-QAvYוn楖f&™bֆ[o}9GgHicrFi R욚fZWB yX m޴OG" ϊZ (ňk.bƉ))Ś),m,kV$Z(}w빔ki^r[%L, lF`6x؏2vxy´ɈTRԲ@k1u LXvu#,/,pΌJDgLmEQ.IG@EaՕk~)7ؔ +chGqN~(Bwm4F?+SjVP6Suܵ((λK^cg /2x6s&ynKZ='8sԋ~[8P#^ _o}yx/6Kr1m8: FHIJ؄ġ,Ir`v[B#'~5ꇼ'9YK嚵y`胔>r78dѡմ p!<d8 `+V/x1=nq)!03~9gcj44 NĆjt3RLߚv+~YD'wKMd^ȸ2Oe,(7F .;ĮVgۍZ>0mAP uLq|\ I;f;#W?46d(j/KR>_iAvB0P`f3(|:@I]CЌϤ&LibwbD3)H,c9:$̈Xp\Ĥ$䣧YF#&ih.MaBeE C:A™khQ`]BټNwcY)W s%DPn`g TC6ZR`+.efnA s=}kZK-@bJCM>HM'P~.j=WYHBjI5+lZi\ PȝqD1WIp-<]ŅZwr i5r RwcbS-D;,gѪdJ40@8@DHJyX?Г;R>UyTI>==; @CyX)c#I\LgɆ@[h KGbJnT{UNH~M$@90@iDYH9R ;]ə;8p8PWy(4@ٙ;0PB%|FMA 5^iW?s*!rN$2N֗[ u¥~YT2P579<;^I0.09ə`Fu&ps3?7=g֢$}Tq^R[ytK(dtxS7&:Y٢-))'p[.49.nt5s>sF Ǵ7҆wHpd wAwHxIr%iH5`)+=.ڕ1J 4`҅` £> ٟ`3|*&b"w@jnHVvS4VBMn*+!y~efu~xr7(ٓL8 ` 7 iT,9#BDaea*0['17HDK'(G tXb($yOT' 89I'@pixYG(;˧h |-J%CFf/.7dJ5"7`W8VEbAZ1@Ä ؉xg,q0$&y7G 1{y[KŅKT)C7X 8лA;Mawe/+:8^QnMٽ qICYhq/lu皺wD@[pp78옛)DhQJZ g/#3u)96[rY0@aTKN E*:Z(hpw< .}ʢ1-h-s̰Ly2pUIvupn@͍K=ZtA tz4覥ytaa[{Ns{$gxlCfR1P<j98HCIB =L]NY&cG{]5/O h@0SEYńNo%!().5%ODVĻ |Yرнl%c^#g)9;q kVZk匱\X2ӊ9uh7\$ӵL€ 9JT'B]9Kܯ mv\GR} N,7:屆! Xzc V=1-fu 'C _mJgg)/#tsNE^QE5Ca@ԱK_8M={OnC8hqX=U~+o]3LeB#z:@jb5F/z@z;y`'RF+^\D0%-8uwdPBq!RaRr3saS4 ` v@v `@ @@@8xXR0%g'ZZ/b;M 9*j [i:@& `t݅ }]jb$8E/pUD0) fʕ=,GĖH28_TA6]ad]Pِ{d@YI$ ^t"B/3\Mg-|yMq Po_9b!d5)>B h,h.vQ:3R̚6MYOd B-[Z3nR/!rx.%/*ͅ~k3@=r X[(Ai1a %,?*֒mhV+TÊY,cP~Ѭ EOF`{c{%0pA Gr.8 a4!X }|p*jӌzV@ 1M sY`tuM͂.D5i'OJHgN@p'L*0TbU9j5 -ш<ˁ "쒠\EiI'sEV1]O"F4af SgV2 XQM4D'wS4TLe&}84P%(}$5W4K*q,2p`~La~D Ԁqb$u _5#d3jhkh4MN#gbdtP{R6q-QZyt<-ԡ6F1H*3Xǧd-x0g1$/f+a.w R -qEŰMPg6ζB 7rTi5@vZ1("쬲BSMi[â6*"]H6KèƈMFZ4{$i<d€>a C"pߌ  Z,*K2sMly-T(9+_CjcaQ3 pя$)NYy@B v*a%ಛno5@~]`֨d,c \k6ѲFegL@YuV F&peanK5ފk(XQt#,p15jcėZ(e& 5qj@A g'WӸq}'!93c h/1(ՈʔU[ )t.[7lO۔ N}nO!YTɁ%Ko18H5l׀Ɖyir#߀^knnp|0~sQ]YYw*dWGHY|csO?."'6H!BZ*rM4 Tˡ-m'VcP5;mv~ve#t^@⁼fZͫ{2Mf" ԝxoex TĦ6zk C`iO`*=Uhj\̀'E"j~}i ɖAn28&4Yd#zɥ^JFwj2H@TOeVl0h.`N唯4P*DNcHЉqP*!Z62,#p|1vB1hqPWj>KPE pIn@X1vllGK $&%H/yJ.fެ(8LVW:0f˱ )UTM1 a. j4R v`2g r* IbJ !?0ImKΈZ3V;$6((\nHY.dl(>`@o&e`j1CO'a,z"^ _ 22Dr{2IjR@PC1 ,"_PL(@Ხ|o./1.H`bd:S$]qP*a4r*Y@@W1hKQB4TOV `<6tlD-qdW:2A#K1No8d s9 b2AtFJt OBb@`Th:Fc\1pJH2L(pHQ,0?uMOwWm%"&&2(,v0JׄUr%[CQF3A{wd)"ce,*DO;OO7D<^%AH XXQ!Qa`(RWQ+US)!a@'([͘A&TPPbM94œ"(6YU_ =]E|k3Vh1K"?S@C?F"@9CmLC(/Er $.8K/WrW״9ߊf@FLphZUY{ÈaLa{4 !A" coǰ hS JueAV#FRV5oV;u /d_wu8R%l\Ppʪp'6YPyUOyX&b+"c-"fL0#U H`8.[JjvW{5t$?Vh ouh'mG,llPmH5k[mfxznO${B.L(Jn",V,A`{VV`!cZapO.v3 ivgzNj ycc6dբW]!#ǖ¤1LseNm5jNn7uUfq6#53y&E7jK`5 wGm2vpdlĺ$["J3(-Qn7&Bu${.ACu/dw_g|u_Xgc"rK0*[o2)rEĘfИ2xzs881f8w͹@8u)k/J'7WjhX%ckccykg؇mH679fNd^V/4vu gW8@O7v6 j+W2v2D"լKlo(#+FZQ–iœsۯ5y^nMM9TCWXM}Ѫ 2w`Ǫq+T-Xְ"wBV#Aص`5umIV;x|{wNC&9tr vcY$ןKF NJKtr/ƛ]9F^ɴB-49T(XAA`n9귬Ogڥ K3wzX xKU z#Yz8av֌CzWqcͤmJ{˚V^ڍiKj3l6s6G4j97Wyؙ Cz:tx9M8-Waͷ Ƭ7ɇ[-/ݺgBx02LFᜥt/[˙{]-A$yXwk魷wkM9WWtss8L/1؉7Y|;ϝVg[n(϶O*Z@uG!򖛹'HzɬׂqVY29ӴeDoꔱVm{dۚK4^Ö[ /Z) mp;%zs([AW0wy1{̎Dre}b1.g:,%mkQr[dMڂ>ܼO5m{rQ|ڡi{Z{=JrYemO"^;@:ܿߡ_IU;+'~tך0T͜@0bނ=B^lAdMդC152/t_ YR:׿AN蒮'QJzk 04% X:`YZ[\ 5~9n%)$&& .26:*&*FNJNn y!18P^arYQ)w n*c2KB>["R:':7&  y*QH] –z}æ MHe*)pӥB ,MAPJxT*رzK;J3f$~._¬J$Jl6e:}jB&X1c|4"'TUWHr5W̮^Qnv  ½֨@6۳G*hU<[kxq?Kdpr?;fnɣ2U7_J$$.VÎzLYI~?-}Ug}Z6XQII?7a\ތw䇅4j˭,YgIv9٦nJ*Eg#KD#t'XƸ%UwTd.!ɟ}B/yϒFdcS)h_]=hyTID`ZVY'JJg,XVeZJ(2,A! ?,/pH,Ȥrl:ШtJZجvxL.zn, wNd/|| ~caa `loqy{cehmm~jil O̟㪁gkp l%G_е[xρb7Deb44P۶S"\1ńwÛ8!Rdxc)O6hQ,5 p+J\u6#̴P3ku3~q:F)-i$xzVvYckVٴi94?C~|iv}DS{Uvu z#T4Q#dSO-QAvYוn楖f&™bֆ[o}9GgHicrFi R욚fZWB yX m޴OG" ϊZ (ňk.bƉ))Ś),m,kV$Z(}w빔ki^r[%L, lF`6x؏2vxy´ɈTRԲ@k1u LXvu#,/,pΌJDgLmEQ.IG@EaՕk~)7ؔ +chGqN~(Bwm4F?+SjVP6Suܵ((λK^cg /2x6s&ynKZ='8sԋ~[8P#^ _o}yx/6Kr1m8: FHIJ؄ġ,Ir`v[B#'~5ꇼ'9YK嚵y`胔>r78dѡմ p!<d8 `+V/x1=nq)!03~9gcj44 NĆjt3RLߚv+~YD'wKMd^ȸ2Oe,(7F .;ĮVgۍZ>0mAP uLq|\ I;f;#W?46d(j/KR>_iAvB0P`f3(|:@I]CЌϤ&LibwbD3)H,c9:$̈Xp\Ĥ$䣧YF#&ih.MaBeE C:A™khQ`]BټNwcY)W s%DPn`g TC6ZR`+.efnA s=}kZK-@bJCM>HM'P~.j=WYHBjI5+lZi\ PȝqD1WIp-<]ŅZwr i5r RwcbS-D;,gѪdJ2&К4phV:'m͖|I&QDQDoB z$w:=4z7NRUHAh~85 7: \9iٖ=';3Gi|eDS9c,gCږ!(&7 0RR[ =1Hqkyg$Wr Y6P;p7mɚ.Ȃ4|4'MgYz`cY#bbH2 LrzvS4VBMn)+y~efu~xr3P5\8칚ٚoY0V״P:oY36gp՛amF$6b!i4Ә^H:T֘Vew~7 d5ami4PoEV)]7:C=9'Q)4GJJ׷kऀ4 qw [8rXׇɝ#J;fq4-ڢp*|%JWXyz0)9֟?|c5D#)TF@WMrz~-qpZWe4+4uwT^Xydꮪ-  ?6Tfvڅ(i-Yd > K@Ԭ@CK %q-:EQn*ux_aZ70X0,Fnyi=뫡4M-DW|6:S3q⨏adEX߲zs^\F\ۙY51<pf)&CjUцj6J6.cd&G5Kk-$w%K'(G tXbW(FyOʝ'+cZ˲l8`pW{k9iЅi5dT;WT8)Y5g@I 7a` vhU$xt3_X{j 9p;p)P=j ;6P}`u4 W埩)oCa:L6: U@ nYƹ#Wu~؝ ,$1vH8:2V!c{CE=v63z>nM'J ÔYhkuJ9E$p%&뛖1Pв3ՔpMgdͣ2Fd3E}˸>qzUJ4HQNeҹhN {ki : ,({͓$";œY!1q]iG\mv[V?227X| F&ry"qa^?1}ԻXkeJSV| 3tM)DӢEg%78牙Dָ+WUbP4LXN3u*݅^+$,7`* X$(c>E%-q;d1>̦7~@d vwOx.aZ > ~Z?ߜn5ݦE$-)Md˞ɮu&۞9G[żۤQ (nREYjbK10-00 Nc)D&hQxjGbnv3~U# p8Fؖ :,D#0"]En j2$* b_{e^GU?\Ip/DϘ@N/[k1DQۜoAA抯X.~ń> 2L5 0v92)Ó$15} QYLW(Ȥ~@pLJ La0ꃱf]oWh(c@ON ? @ а P!Ʀ2&'$3"bBuUtBUvvWוմ6Ԣty5S3[(tH(I =IʽJ+ Lm---N.π~$a!D=RԨ@5*YҤ)J5,OX2f2X,[X*/c*iMeAdpkCMpGƅCr.J9(Ròe^g× S'>0`B> +l\[cM1: *RO(]]qdɥHҬ9r/%-35!G2m6$C+R\T(NHxK._œJ X% jײ5(@tҥ? 5Z)G و&M(jGea/Q9ftV?rюƨ <%Xmsh6-ح4T+ޘ8H $.A[ꨳcJ04j1PfثlH,#Hd)@s3HJӸ!\C'PǶ&*xtӪʧð:J؊K!bŇdl@1Bo#4i){3РoɛDI>*QK )x͈qΙ &a̪ |'8 سQE|EÆQFnj_iڗ0&jj+n0 kZXzՏ_.9lFY.b 2 *] 0H RyۃY3 m@tzuPG0m_RlWj^0aN"8ɜ+cPH9O6P3,e4`ހJ? 3T\+|Y(3ZFP*.RXGllS-7^'Lhl8Md$mmS:Q@Հd"h4wL\$oh Mr>idC,!sL$jɍ< k ؞("<$DSt §:l U`@ NvX$ojcgPNID\8PCv.U]ӤvXSBdtI؈h1rl[`6!`#%@'s5H唞79*2 ̥1-I` 4!t߅t(bEp(1W.vjJ`L?b TX+RZөƼFcPJ7\eWE4 4;[MNȈc]뾂ZVDlCR!ĥ\]dۻod2hЁWy%l4rnҰk0+*AS!,q {]wV:qzwwL,X;=el4k(I#]t!GFr,k׺Gckg,]qw/kXED P=UFH(Xlvѕ&y 慍b a[CM9-Q&POLuq,8mzZ$j 4be^*J#=Un$j:*eBx?LlzVBGIyk߄:IپBg]j\3p~"^*\%dN`ј`&7 vkETEq.kɻ!Oͳ:2m v}k\~} !6 V$/+m`}Y:3r Ҝ uB\%Ѡבs;;O d8x^"8 ^@Xӑuܮ9uh?қ{%Jv``Z.jfYdY{70'q-y/2t/h23=M2.VfZo}o@Dd m6RZ()/j䇙@<.(ΪINN)_dz) V*dWW/nN,fl pl^;P` + bY V c@ [ۺ2 Ft8s},+6گ)jhpa relKcB kO Ӽ4 I @Ƅ606 ȎW%ƇZULfLtϤf bx/܆c`anp@D,*,Lkʮ7ˎL> 搣F\Zh̜0b Q*Q M6**B~l 9 1 B}o ~n4_nŖ,͊ଵP.g3iqnj17礐Qj0 Қ+t>@.1@l1 IJR*D8g#6@ !3(ViOW2)pѤtOf2zx:hcP:" :F9W/+(4jBʡ $4,qyMTk,6Ibd,.ﱜj&]*'}XT AD Eju j颈R1l~GWM+!Ha/;VG/tݺ<]abaM".QD<_S_#,qU4`c8*`["ULV[\%mQc'uEK6> ޞYUP)`E[Hf_[Y[s2$C2P b)Xs= /M!iY4NĴdfvU&ǶLk-dnVSvP`\`JD 袁rOo5j,ueτqC>#WrGrOƴxIQS b<-|1K|n=^u6jw3vp0pàO{|gur4&mYxs!Fu} x16+:nMP׶ kz["MR`tIN0D7pvvcK3POd1޶9πHUK[Ks >Es9^hO0guUgɊ*D 3Y-\^5%|ҢyM؜M=UK^dX N[aʵjU`aP'29؃oxu5;t#.ywZ6Yk'paPsXu5y}IŠJ-?ZI)A[ӇquYX!fIf~6-uȡܸK뿾ƅQXis߸׾uOE^O7=wGuo>61~c( #>XޅvQ%ދU߉5_~Q۫^o??{?iܑwJSTI^_! ?,/pH,Ȥrl:ШtJZجvxL.zn, wNd/|| ~caa `loqy{cehmm~jil O̟㪁gkp l%G_е[xρb7Deb44P۶S"\1ńwÛ8!Rdxc)O6hQ,5 p+J\u6#̴P3ku3~q:F)-i$xzVvYckVٴi94?C~|iv}DS{Uvu z#T4Q#dSO-QAvYוn楖f&™bֆ[o}9GgHicrFi R욚fZWB yX m޴OG" ϊZ (ňk.bƉ))Ś),m,kV$Z(}w빔ki^r[%L, lF`6x؏2vxy´ɈTRԲ@k1u LXvu#,/,pΌJDgLmEQ.IG@EaՕk~)7ؔ +chGqN~(Bwm4F?+SjVP6Suܵ((λK^cg /2x6s&ynKZ='8sԋ~[8P#^ _o}yx/6Kr1m8: FHIJ؄ġ,Ir`v[B#'~5ꇼ'9YK嚵y`胔>r78dѡմ p!<d8 `+V/x1=nq)!03~9gcj44 NĆjt3RLߚv+~YD'wKMd^ȸ2Oe,(7F .;ĮVgۍZ>0mAP uLq|\ I;f;#W?46d(j/KR>_iAvB0P`f3(|:@I]CЌϤ&LibwbD3)H,c9:$̈Xp\Ĥ$䣧YF#&ih.MaBeE C:A™khQ`]BټNwcY)W s%DPn`g TC6ZR`+.efnA s=}kZK-@bJCM>HM'P~.j=WYHBjI5+lZi\ PȝqD1WIp-<]ŅZwr i5r RwcbS-D;,gѪdJB(R|ieKᅉ&Ӣ'g`IƘJBteigCɨ!0u!!K=!As^WX +0RX>:o5~J {d8Z)J6ۛτCǒٱ#e ӬJb}G tXbך(vyOԨYJ' ~6/"?0Jf|dt-3vMpdJ7?~䆣H`n8VEbAZ15KJ{!F s)wP+pkM)yT_38Z0 U@ nYyZr~釵iG9AQaS?Ɵ2J,;8ziuJR}ng3I^7=*XNo) 󓀧HySܶVwTy{Qfia$Ji'MgBB[Q9ۑTqArzUHaTKNehNNJrk 7d2?W6p65:u59s]W3now{!JXy짭| L;EZ{Ns{$gZ P|pwT2/K9M9`yË Dw7e'D`1ej~PNL.F齪{P8ru9kcb\žo\;Tj3YA8~ {c;rɫ׋%!>XSס~uOLlٶp27ye,G?+Mbd2/ 'W g+(V\KHyꨏ3V0v@}7pڔ'|T[ly{wR@(Rd;HqeZp9u\uՇŬwŁ(D2auǛ8c( f 2X;cղ]ASK[ԝ xe7uwXWO*Ȫ{BiDAMW5^ބx#:Lz_lAD[9ȾS ]fObh\̥ܬR[lG 3=iBvuW6'9hx;DXT Gn1w(= LXlfb T<_|# y[ggf/Gޯӗz齣X5UCTaj }bnDָwue~,֝=a#[cʩJtָ-5L-zX! a ZnSB@e%]MhPgj6 I %=!fE\ Ys5Yuvў9P!YnQҝ Sg!(b֣-0>K8a2rAQn*̍Ba.XaZ,xր`:%ΐF1ذ:0"]!J<{Bnث#TΒ\tMޝ5s,;8D+lwzHaa%uB邷AWf}֐u|%fyg+ח;jH dtI&P"U,V^@-셉nKtYY33Ү9lZ5lOYf[(<MBn.*f3P'}kA@AjTBH*5lh)+j?߁$]NBiꍐA2d4148t(Be:2 /N($º Vs,3+2n 'ShcBŊjl΁REIszVjKgeoƙ]Ť%SwW9&^}#~;BF4.C3鵹)kD;D3*Pu9ھffh5kjx$H6B MtMA`:#E,[hTEG:È,τh-GmF!Rp8 4#W{C6y43i)N^Q@W`gt|B ч{ Q9OeTļg9RzrӃ/fVg\6U{qs1 KE{ C!-"Ti:e7qg$k\3p K\ @M/`JEjj`57I"P O|6WM_X<#?J1!;hAZ@<-3\e6g 9V1Z-ӂS,L~"vʚDXkp T!.?J\IX%LIxbeZF7m<u0f@H4]r" /V7Ɉvӓ7ؾS= ADh).1jE VM+%iV94izJil5,sp<$'MzL='EMVY*U/*(Q+GZgMW;ynׅoVŵJO\$@NE@Vԕ[2(MirRb\ǒ.,tM8u7DCڠβTWo^y9]DPZц5i2FCV51Ot`ToŒqh=-YkcWyЉ|(R T$"Pd>zkClR Mj61*K]H oMX%B*ie4w-f"kkc{I$t!,Nbޑ }"Ѱ]ڳ`ނ146oF15NX\kb=YJкLaOrؾGҰT.wUPZ+bfi)V B2fndj53YD%B6ߜemh|0y$icepv^q)j\9qZJ&I8zYrkwVa-5gL46m h<_^tTYʽrS!{8zW\/&u!sRQx@-O*H\Ϲt6#%g_ק-h3ݽQq71TzOfnG(dYW.aW9dkwfosD)J=\ړ+A!|-=O= 7m.z: OO6!O LL Ѽdh ^_ؖ % . ,-k@Ap,&.JkN!(*$PV &N^R"H`j*Nۊ+DaH$PǤ0֚c!( 0KpuP YTҸO-ONpnklc0Ԝ)W|"*N:I‘*i *W*o0żPVtP" se{ƒ:an.L/: IZ͌P'ޏ[ q,㏑iVp,lڜ""dq0-̈@iպ-7 0Sp_$즀M"ڈQV (1K M! q͈!ϭ[g1$)"%qjr 8.c*HD@qE!ѧz2Q%Y, ".+R15Qso9"n&N}Ո-*u/N/2/ń.aFd/*1;Xt22.ֲh ݢR3=s3'z`.8(iH806!I&2/R/ܶF!79.8_P]QƦϘS?r/B{R.c8/-."ۇEID%oEr S5A8D" D2bn}0.,8CATCS>n]4")JB/r8`o5qLk|lD ͩ1'HT6,s .a ?K3[Tڠ!]2JD!QM6aqG2:(4tr=S7,fNCUNdAtP+$K`Hz4`Dm-gF&ecpD1HCH? K*& !4WL*VkƜC0e3DGu{SH+C1Zbɨ˺m"w:XnP+&wrǗm:;:O٬;XM=b:(Yd?ښږ:=;yK55?:ur=[MװG[WG6r7gv5[), {P1d 0Hc[_cqHCc_;ϛx;kCɣE|Z^;۾ 7Why۹0w[\hy=qw ܄:W- 3\7! ?,/pH,Ȥrl:ШtJZجvxL.zn, wNd/|| ~caa `loqy{cehmm~jil O̟㪁gkp l%G_е[xρb7Deb44P۶S"\1ńwÛ8!Rdxc)O6hQ,5 p+J\u6#̴P3ku3~q:F)-i$xzVvYckVٴi94?C~|iv}DS{Uvu z#T4Q#dSO-QAvYוn楖f&™bֆ[o}9GgHicrFi R욚fZWB yX m޴OG" ϊZ (ňk.bƉ))Ś),m,kV$Z(}w빔ki^r[%L, lF`6x؏2vxy´ɈTRԲ@k1u LXvu#,/,pΌJDgLmEQ.IG@EaՕk~)7ؔ +chGqN~(Bwm4F?+SjVP6Suܵ((λK^cg /2x6s&ynKZ='8sԋ~[8P#^ _o}yx/6Kr1m8: FHIJ؄ġ,Ir`v[B#'~5ꇼ'9YK嚵y`胔>r78dѡմ p!<d8 `+V/x1=nq)!03~9gcj44 NĆjt3RLߚv+~YD'wKMd^ȸ2Oe,(7F .;ĮVgۍZ>0mAP uLq|\ I;f;#W?46d(j/KR>_iAvB0P`f3(|:@I]CЌϤ&LibwbD3)H,c9:$̈Xp\Ĥ$䣧YF#&ih.MaBeE C:A™khQ`]BټNwcY)W s%DPn`g TC6ZR`+.efnA s=}kZK-@bJCM>HM'P~.j=WYHBjI5+lZi\ PȝqD1WIp-<]ŅZwr i5r RwcbS-D;,gѪdJqzUHaTKNehN:nkz|gB8S)l0* d3?C JtfG؜̱"^zD[[7~@d T[1.Iߌ:֤k Ӑj1]YXAB&Hqr,uў9KKʿ{2Q 3∕d!(b\֠@e X*wq MM‰{TBa.X!1 {ه ؀`:D&nnKذ:0"]l~&SS&Sfs=QnZy^/nl)[k1DRMZRC,.xkxE6.c Y 秞.pc=MGխpv9HsB.j屺maKTߌNW LȏP,s+6~ȘZマ}7TQ|E*L6$ pi`>/l~]+3r5;l溷dw2},^W4+<Աv Jp!n!x5t cR:QG!  /0]n^ֿ]#K/-rL ^XώoN~yj9sg"a^?^𙎗 #5 _gἿж.VDH-B-7.@:$DBD2擱`.TkX4]E@e}N @H 0 pG(Ibbh2B(B"33bt5UBՓֳBw7ss32rYR(:IHii a*ˋ܌ mN-Nn>o@qPP#-M ِeƚE+d芖6h*^.4fL& 11KY!I:h3Ʉ"JD2 (O1x.\p1L6ڵI:u#ϟ| ;T#)MvB%ÈJuiɉ{eN>q/b;j̲2/MB`$6#A)DfIK1dΡcU dz|2{8}>ɐK#}5k# ӉUk)gZp!ʗ#f=&]R-aVTצ*x 7{EAkbo)CƘѤ.X3,Rl[:#̻팡EPC챕2iC#>Cb(tmt'zc79,' B!MVMaTE nƍ3_@)BNb)KȚlr#B+B* -(6]?߽)iށU + "i얦 sbB1*}gJN r{ L\PjfN*St*Wnӕ}KF3I/f]m/m" B8>dXj[D!o&*{g>c#3# 8E,GO8*? %1_["2mOܮ^q&>G,[l63-{c&ܩ T9)Jl( ܣ\1+XLKqH-TIkbrj"%(5h;Dݬa-o8BCx#xV)4%bb8C$szᐤ!7d 9-Isڼi5fFni9?M(PY@B^*Z<LKG$q%H\ɐD]C6a$@*00p~F"Ry0_uSY ":eh*]IS9dROjF-4-MAQݒˆ`7erT)r0?a@Z=Hz\^Qug*)EUө1DU:2B:% ˲[+Uu*[-GTT@VV{H`etUZ*^J\OA椷R*cU 6[De]r-JJŰ314fF+dK>0fD{쫵61{9t5H AU"0rՅ ؓ%۶ekL ւYl;掳a'axkĸ B6vG_WfTVm^Ei_ 5Cz~SYRs9e62 &S&/g: Ӂ2A6gF֪~w$΅7*>#iҩ)VOqy(A8iUB~$η>#wQڛ@4ର+Ǯs~U+ /aJyMӺt >ߔƫi/\26 jTnEml'rT5Mr5reinc5-ٱ\nՊ!M,%HS S0K+o9k8-SVo7 Je-9Y/œ"kt*liu<ѣiM4 ~;x8eiuթ 3WWnx~c&GL9 .F2L~p0d`Y^SrpJmh=@ńt<ۻhWZ;~` =[YeU-1oY?bxRQ/[cQ>O9%@w+@84,'IY+vO (+vzJl|J֮+*ltn 4l점iq)J/>4O P A!dh>a͕kIr$װ.> "ydi6i* DmȌC0 1'DzP)"qQZ.qA MȤH5pg-=q,˺®"0rqxèp3b&m%dho0+L+2&21Sw`1Ͳ6+"OcD-wTRpv.phf zh5W5A 0q-8U 8&y2SoIހGg>yFz3=PPHګT26]pPNs='48s2+pm>1-;Tޑ@ 1 롐Џ_&* 2 ADTt-#0e =%Ts ozhiH3 %bA\4؏QLf0M oT6t 'Bn-T& SC[#4 I+6J8Ѐ3)Ѽ1@ Q!;$sצDo<@Bf IsLGIROOas|C? TR5Fs6RsRqqײX?U5O@ _M̫Kү`Q[MRW,Dr6XW4X L4Ii56-ߵ|ȏOJ D`DUP[d\?y 5oTI@0>0C9sD UP7\ aUT^KFa |.YW.^/Sg3h_UjAU)WeUia5fmQ! gVt6_~UUeԄ 趀(eem.i@}HQsqxG_@cXGtA{~4XpC_tVdGdwaM ay4xwϸ_ˀ!Y|-P`[ѲӉq}}ÐOby yZX-YôU6NfttyQ LbSTAP0:pxsvpÖdDgx5gVٟL399#9[͗ʫD-|G0W=Yˆ*868Y[j빟 xsy)yV $gx}zlcX4Ww5ZSts:ew[!ITd㏮n8at#ř~mZͪz;y)؋ڭ+Qk_ -Ԝ%dT^Q:tqo>9E[SZ`#&'oyA_{\U/Sk;aakԝa[cG۸)KPyx5e[iE/Ѻ{5q*g/u{VM;y \ҫ{fO3[;! ?,/pH,Ȥrl:ШtJZجvxL.zn, wNd/|| ~caa `loqy{cehmm~jil O̟㪁gkp l%G_е[xρb7Deb44P۶S"\1ńwÛ8!Rdxc)O6hQ,5 p+J\u6#̴P3ku3~q:F)-i$xzVvYckVٴi94?C~|iv}DS{Uvu z#T4Q#dSO-QAvYוn楖f&™bֆ[o}9GgHicrFi R욚fZWB yX m޴OG" ϊZ (ňk.bƉ))Ś),m,kV$Z(}w빔ki^r[%L, lF`6x؏2vxy´ɈTRԲ@k1u LXvu#,/,pΌJDgLmEQ.IG@EaՕk~)7ؔ +chGqN~(Bwm4F?+SjVP6Suܵ((λK^cg /2x6s&ynKZ='8sԋ~[8P#^ _o}yx/6Kr1m8: FHIJ؄ġ,Ir`v[B#'~5ꇼ'9YK嚵y`胔>r78dѡմ p!<d8 `+V/x1=nq)!03~9gcj44 NĆjt3RLߚv+~YD'wKMd^ȸ2Oe,(7F .;ĮVgۍZ>0mAP uLq|\ I;f;#W?46d(j/KR>_iAvB0P`f3(|:@I]CЌϤ&LibwbD3)H,c9:$̈Xp\Ĥ$䣧YF#&ih.MaBeE C:A™khQ`]BټNwcY)W s%DPn`g TC6ZR`+.efnA s=}kZK-@bJCM>HM'P~.j=WYHBjI5+lZi\ PȝqD1WIp-<]ŅZwr i5r RwcbS-D;,gѪdJmb2z6YzP#%Hpd wAwHx{Ir%uQ"5mum:e]'MgY_`cY#bH2 LrzvS4VBMn)+y~efu~"jOTj&`\y]i'VVvm5ZIcMmD"a!r@ @m(I:ACerie!1Yf~Wx( GM +r&+\ilcBsaOq}jf  HC0{נkՊxA!Wx~}"zr\0#d]F‰M\2C2;|#  JWMrz~0xםq=^+KC1TǗ)L}ɒ_\PכAEp%DQF=-'ș@ħ@JP"zc #Sn*ŗX ~؞JPYCJVEVɟ9JBteigCɨ!0u!!K=!As^WX + RX>:o%zp֏yiJweƢ#C=Ա#e &usD}G tXbǚ(vyO!ʞI䑝2/"?fs5i*J2JMxɆ<׏B rԠp3 yhU$xSV:on[rٳDp\;DQrFmTfk| ;pEZəZ/)y+at,tr}ׂmaKߌQmfitfx~~\7=>ëȘZ =}(TQ|E*L$ pih~6l~]+3r虳V|VD;1)KuxgÛjB-|&K@(.>Kw҃0&5u;rzAiֈWo]#{rLN_hώoyj9a(>%;a 񡎗#n+ ޯ\;km_UE@P\(Cr.dA%bbYi~ukLk !]!PpAp0q!QaAARRA᠓34a !t`u U @7pO.͌B ihʚkY9 K ] m 9nn8@B J`QH&MڔiN((ujS8%$HtU$_? 8Ǎ=dh^.[Nnؒ\:.Imf m`4cJ343c)Μ~&O׀ 2{e)Ҧ4hQTSz*GY |UkWI[ vhWWߤIf'1iAtlζЌ'ѢyngNz'U=7>}3ZGl)-Ĕ bĊI鵞`vU*,H[${4I1KwsZtoUvc6͊Θw->r*vc8<RG,Bk«:4⨻W/zAlH!28y5pP[ -'! JwN?1Q" Lpzl8ɪ %1CBH9HiH$Q:PB1kţD1I:YzG|`"C !ks7Q2Ѯ2R/aq%+OFAW-A7oOw P'HT-ױtb T&mscpȃ8[(͂\@-\WKXkO 0[ 5)Uzp*4p%/ L ep)ejK2VP91![4DaXjJs.JQ/1L>`R FDXݩTD0i4Ζ)Tq%mJR\^SލL~S:MC jC8G$.cUb1Fk$o<\9GC+|}DWRԶ0Ogh~F\A80̰ yJj(8=ךbc1/[ٲ[xPh 壘~w5~wAJG^͔8ˬJ7ٲV~ Mn8MB.!G!# en=݃7r aZE8 "_u*5t|b:ֺpFeI,FK[c[Me”1*\?ȓ8@H<Ƚ7#nE_ L$P4rc8R;c@P,aQis,.8Ug6@PvV/{cGӶU照ټ2*x pŠ?7r1QqLb$F" UnRYF[X#JdYqN6 VwDaę΃D{ӣ`R\ljCY\3mMs"%r9:tUNSIV2He!4̑+ډere\4|p UzJաaLb=Q\ٚy:9ѩY{!R@ZzlX~xrʪeXޕFdNL.ژD]*52P3:@5%CiJO6敉M3c7qn%+MEwA_oa9kxE-(D6X_s}I,d٩>'n8FwIsB/յMp*V~̖ 7IU&=bz XI2u{BɡUt-I1FkSl7b◾pDH_v&O: BUKËK%.8 εO;~q a-(~Ghac:QlAt*ker5d|cߘu:fU`N9NӛJF;a3φYl:؟z;S ˦mr(-\)>~ VQ4 V@Tan͆j b⌱b4";㨊<+ @mAmJrKpB2m,[7dp\n{ N.:sooWmH*,/Zb$5N™G9~opP/2bzIxN~.WD,4dο" vۼƹJldY0 0 9/; 2x q*xvJ fi kMt誦Ͳ-EbiU$0$F2ϪF1imWb ]Bhpˎ8D0n0 jH ml,oXtg!0fj qJxQn A` &%Qrp n<'3 *+&pPy#QXILB>QZp%Q2K񿤉st2D%}ՠJ떰P#1Er$$e+~CRG$D&(D/Y^!\A,*O®C$aR+ 3$ Ojxp!?!!kHGpr=R/?2O$RDoEq؄Rj |'JP8DiJI/RGs4SNԨ cھږi0F<&oc::·-A l0 ;}0#ҔB@|"/SYZ*œA6 DKDdNR͚J(A*Ѝ 59EbΤ!bT+WAo<BRs/'ݳ .c<`dR#AEbE!{0QL׬WKO1 ¨O ۲i;E^M?ƅZJ4]X"۠ԠtFy&-, t!GcM g:H8=R!DY̔n1б9uP_ |i tR,m1}1WM DzV #k;MEtDE97YFDVa"$@g4'ga]B#sXbZE1fQc#LȮ?STu[5:D=U!y2ys=5M\3XLJc=-n-y,}FV'j?$dVkG0d4J^et56Ul3>XivZ #SgWϚ[Vp #u@ov^ m^aCH'YrrȈ5o?W6tgt2^+NP/gMV1r:CVE>9-uZ <ܨ6uT4UQt)Kygp5w?V!Wb(NC}2qk7qk9\]TzlnQLuD9sC EJ[6mW~pv^%uzvV/wN}x_u@o:sw~+k}=:HN =!JȄqw-Y xvu z#T4Q#dSO-QAvYוn楖f&™bֆ[o}9GgHicrFi R욚fZWB yX m޴OG" ϊZ (ňk.bƉ))Ś),m,kV$Z(}w빔ki^r[%L, lF`6x؏2vxy´ɈTRԲ@k1u LXvu#,/,pΌJDgLmEQ.IG@EaՕk~)7ؔ +chGqN~(Bwm4F?+SjVP6Suܵ((λK^cg /2x6s&ynKZ='8sԋ~[8P#^ _o}yx/6Kr1m8: FHIJ؄ġ,Ir`v[B#'~5ꇼ'9YK嚵y`胔>r78dѡմ p!<d8 `+V/x1=nq)!03~9gcj44 NĆjt3RLߚv+~YD'wKMd^ȸ2Oe,(7F .;ĮVgۍZ>0mAP uLq|\ I;f;#W?46d(j/KR>_iAvB0P`f3(|:@I]CЌϤ&LibwbD3)H,c9:$̈Xp\Ĥ$䣧YF#&ih.MaBeE C:A™khQ`]BټNwcY)W s%DPn`g TC6ZR`+.efnA s=}kZK-@bJCM>HM'P~.j=WYHBjI5+lZi\ PȝqD1WIp-<]ŅZwr i5r RwcbS-D;,gѪdJqzUHaTK@Nȩ7[jhLhvOp{@C.g'}&CI?&@&/d|tv<ַ5ɾ YiX-k$4N bW#qP$*ž~-x7V|g5L3 C$N5^Jfg\w_ RV[X"bup蛘#d++{QZ$#Sҷ0s`v.dWwc2}sCԉ〧{~#7-{ZИi믇'~K$:.<;>VlIq UCTau dQ2"}0wq ߘ nyq:yrm=l .,c JtfGH }"^zı[[7~@d T[!k EJ7ڙřS1X^YXAB&8Qs pZ(m)l۱dW'sN<%ZbKq}5+PJnuKeڹ ^QB*cY*ļBa6]5X1[K' `:Dnna=[''.jZźN&`~&L,T*ז==GUD]a,5)[k1Dya&nA;Y֊"P.jO8R5޶03yl4__<)T6͎>,tЮ7PxaKTZbhb%ʩΤpGI,6(Ux_/!c%Џ A !ZG8D2[l&mرOB[KH#_dZ2$)T3g8&$;9YmJ7,ᆎ#]:hfAwoѩ'4 "*4IT2c,{"RJY+{In(Jɍ2tQfdgt^FsPMZm"g3RsI/5e 6Tz6Y$ /`>&ZdB… 'I\.69#!f*Anvب kDLd#͛<ϼy\-[f`0LFfǪ9M;0ADP0BC0PzFb'h!<[I_dq$D/T!X' ף2kdBnb (s H)3ځ* VCr3s >61(ޜM{F*JhSfDj)XQd~BPTH[@ZL̪ğ 1$YW<ٺ8 OrDNS,ZaI;tVB)S2 WSg{:ي4 %B +S57^0g ` $'Pׄ}aCcAD.U 9 /ú}S SÑe<łQL"6S3x@jJ*-؈y,_d-BVL5la%+Y/ P1Og F/add o.m*B:qi™2$;1]JF3>umr"T*5,׶1 L$ v;[">A{<36jc eim޻Ç1x5M u]FxME3g_/ F(8B8@fadsEJYv2HO05I8&HtK3n1\Eπua>X8V%z9?ZjԮ_ӘpD"@X;8:ö炗R9#p$#3L&ѭcAFt6SJP (2 AysP =CsozsmlK$nwP4ߟWNPC 2nD9F^]$GrQTC}2|ǯ~mASns?37AFbQlHW|Fs;agQqv`\8PDK;E?䲎k΀UIL=ZaurkWNyYS)h$6lKQya*u*wl{;wlN!j"z%ni rXBft`J֧3rMS,yUT6}} A?x{n2B [،<6pَIyuĝqc<͸Xۀ5\m]"S*݂5l@`#!tb{HN͓v)urwVzGYJþ*Jt)f=P._!h`.pRHLDp+ڮhh.gZ.yEa I(k&_lнjJG h "$h]^+Le|P|/[*ʰx 0kOٞ /pmJ4$ 3ŮۈnԒPgSl+V,>PA5Ps@UJ6 +NqU tѢivaj w10Q|Q`mֆ&L30*I,B#ͺժo DLM@HQ oyuZv l /~/q ѽlJ JBG܋> OPcD,#Mgi ߄^PrMkd&ir+8Ql %I‚1f$o$'.0@n.c}sN3u,߰k%]Jgq޲>K*(6yQ  1C ޶2ɑQR@34`2Pi@frur1#l UR=/s݊)1R^PEZO2A2V$=k dq s&k26+}4# c4(s0!"z^>[S*sm3S3p A%&_q"TB'tm&[N ήQK5;'@RLGx,ߠwkA%NtLjOK%UtU3V>*}59S$u3SG  ;4XFUBT3sOi>](PuPWE'i:O/shO@9rMs<1тHYMg5QQOoIV)\`P5V#tQatި ԏ~Tp~+2ԔG_:Fl^2N`n(RZ%a3PO#qvj6 u-\#OpoπIr = AeY625粯\NlyluUo?AWkHLi+l@/UG 㕙LvRvO3kVILeV6lV"154VmiVI?qo*n-f h *,G3UoqYvpb6O&`wol振Pcfɐ&6+aRo93v$_c b3߰WoO4L{5vwv4$w3Whv 7 C]NwW/y3:wLKykMtQ%I^G3fHve7vM2L_mr7rKd47R膔v m/M^3A ^o o-k9^^lvQ_m-w˰sw|m_ƺ2@v:_nCi{jES ΆXv/ut_։ycL@Ux5w󷷞8igoiO8MS,o^pNXq|got7=8h%bg︠|W9uRwoudSNje:ktkuh660Yuks|#5n (5߂ՏW1u?dW-l^ǏX L V x5ky3s@GIJpsTj 8]8T++v-.yuph{9H?9z#cY ͋ScQy1ӷZWZVy׆8ք[В3yW>,yc%q-8CZA3#z#i QGXyMC٘Ų*iQy^W-S*ru.J76109tKg7oױWX9oY9#9 `:77z;LF%ZM@uwڒꅧ-![g9$=ۙ]8ZIuxWЮ閦ٙ@6 ;,4Bu|em9mRw{N;gz95zK9%u%kaMXxq%K|FAvK[YAx]Td; dUcYs{t[?c ;As7)++{=\zXP! n]m:ɲmRit {{S xH[yw|:5AӲuzXĩkt:Yj7y+Eն'ܡ-;SS;\T= 3=ĜC9(r:OzWYMg8Njn˚uL]BJ-mX 8'Y\;;wǭ{ԁ]pMٿֿ]Orه=e=۷R>ŝ޻4 j鐨]5ޙ\߅t-7po+>3:~sݵGݙUS1o_x^g}ٽSڭVi]奙M>~= >=I>! ?,/pH,Ȥrl:ШtJZجvxL.zn, wNd/|| ~caa `loqy{cehmm~jil O̟㪁gkp l%G_е[xρb7Deb44P۶S"\1ńwÛ8!Rdxc)O6hQ,5 p+J\u6#̴P3ku3~q:F)-i$xzVvYckVٴi94?C~|iv}DS{Uvu z#T4Q#dSO-QAvYוn楖f&™bֆ[o}9GgHicrFi R욚fZWB yX m޴OG" ϊZ (ňk.bƉ))Ś),m,kV$Z(}w빔ki^r[%L, lF`6x؏2vxy´ɈTRԲ@k1u LXvu#,/,pΌJDgLmEQ.IG@EaՕk~)7ؔ +chGqN~(Bwm4F?+SjVP6Suܵ((λK^cg /2x6s&ynKZ='8sԋ~[8P#^ _o}yx/6Kr1m8: FHIJ؄ġ,Ir`v[B#'~5ꇼ'9YK嚵y`胔>r78dѡմ p!<d8 `+V/x1=nq)!03~9gcj44 NĆjt3RLߚv+~YD'wKMd^ȸ2Oe,(7F .;ĮVgۍZ>0mAP uLq|\ I;f;#W?46d(j/KR>_iAvB0P`f3(|:@I]CЌϤ&LibwbD3)H,c9:$̈Xp\Ĥ$䣧YF#&ih.MaBeE C:A™khQ`]BټNwcY)W s%DPn`g TC6ZR`+.efnA s=}kZK-@bJCM>HM'P~.j=WYHBjI5+lZi\ PȝqD1WIp-<]ŅZwr i5r RwcbS-D;,gѪdJ]%kXY^|5 Ȑ˧ \Œh ,i Њ/4R*}h_fPCJGPTބ|Pi,6/%Q279m0P‰Y0l0 m$-N=|\ʌ%-<]۞aHȣ6\Gq|q'UaxΒSEiF`J,;fi}Ftb8~ʯϲ]|N_ ˦ =Ҡ:N%0\хֱY!f!EQ5.WSatw;FMg jm>)WI,CK\1@}G UNS5HqfA |0:ݵ h֪F.g'} P3gڈ|:1t5#vv6abZ쯺:`з|kP՛K^n ܵ4il~EЭFr/bC E \J,g ,P\̕1. AC34Iwet(0]ѧKu4|O~kr mY8-\FvT8pDIM9Wi[`)ݞ@'e-ox(۵!oX2^7ܙ(=*qQuD&(ϗypJqO<){-0TɼE[Y\ps톔٥a[s" "ѧ-څ~t~ì|N 7)l{Wi'ܚM(|(N.Vݼij)Qq UQw D(ݘ40̳޵(mwޱBpv6->邾yJZ9Dl2'x7pгmIT.pݞ \Yd@aG%qqU&+qN+&1ޱ3>^pmUDesfPO`E %! kZj%l#))).~I UM1_ޤ+L1~y;г! #2)@ 3S?};L4@vA5="ڡuzOv#}y* 2+^&kѳ=l+LJ_F|4 M9F>V D% 2f.@˦Kљ":kީ߫94z,N@1   BujGH|D,uEr/{0onPq. q эlr22&gS''GsttU&ֆf7wFw&XxaaAYAa:aZHHE%h ii*J]gl 1<} FE$ Ss9"]2S'Rv*I)YprrV-XnƯpΐBƈ e& JM6-F`@BnNX:,a"iZ3M~ vqBHs%ұ |fT)*oJJU5Xq\s-\v5#a< `ѢHn*ڶlܼ@Q}eJĤU1#㢡X8 {4cT3 LՉqH21_qmP~& ! fqPn&zk!QBs0n,wڑ" La+Hˢz?!=GnH6,p,130Nj$6%3t-@^dm`^XAphj탧,͛o)lj&ïa'r-1ƨ 1bO. 1; ~$#o1Xbr`e1-gR 4`$&f )6M5ͺ{S!g; C -`f.PUwN+cD#_qUd=}dTgŧ&p2@YuZ&nA>%'Ob00mIЦe]hxv V@!p![N[Hh>p-"&) Ł#jy0CIsk\{L `MDqVt3 R@+nY"IE/vq"@HF1c<ŘFgD0)ؚF<)NPB>epœ/8gPBe>LLq3c>!6=c.2+ #*%,d DDLd^{#G8@ iC|cV2=mᄅ2A ^9Z.Ke$C089n8xxꓵ+l%։Dz28e{prڃCS+<$pn}HTjhB d F=hCuPd EYEmh V1n<9@<19X</pLb$J;; uQovXĢobHڇԈ>k< Ojz.ʡ2-f6p%| ;zQZw5N9 QI?,ޱ/MP={dlس,/nb0_XW\N&Il&i#7⪺H.!U$ IpnApgV $LB( "$/JDǬrŁ0 `4`N0 OP P  TvtzAnk6Be6)oQfк1c!/2:oĀ)PQ[`kHV`^V_UVk5Vc5X3+9p 44״MsDYUY uG}T#SJl؈pu6/Tѵ꒺lU*hIlo#Q3F|ˢZM֔X*046Z)p)Z-6N 6[T πPRIISQ$fThH4U Kji^L5_Upnk-M VDDZnQ/v2v+DVJ?fL6Pq! ]HR.fbA?Q9/gs2[MԦk||pM&`Ŝ,%D*pmBkE(<줸v26.7c6 I[K5U o\ՠ[Puz`A5??pd|iyL=A>@RiE58kj#y8ͰV>ANBZs ]k[ڐ~ ARՐAf9OxĊx!,h;9X5q<8Z6{ +6||OPEWc7j}WUH*~Q,Tl?ku'9u،77ʬ얞OqbӬwiMr@ʮVɹOP,33t}}'9X^xol?v[wo,ߗx *́0OpMzid{ƒ?@s#p|mY(.ݎx쀉-^8?tw1sfۘf؈30;7S6!&$֑ҊKT{%Qsu%Ϛt}363LوVjlxKWHUbq1 HY؂EMGt9h;,y>%0XOMM;:KaksU7:pg12*Z'qYzW< +NjRf w͸;fWؗѤZ )[Q3qc5h+19irzDD9+>(s=Lck-sɚ̉hCnQY%AFyӔ % xjE+8O ..k|z> v}3{Y:ؗ0 lK34}3ߔdәNzK|j+6,Pk@()"+#k{ݍ¹qhۉ _hmi/$:&׬8|DtU[M9 p}L6پ3V[-tuڭY̹eDxb RyZJw7\ȅ\+=\+A<LY;1;i@Aj+:bzDF;l<IcCw[ڢMC{._;UC+G܊UW eٚZ<|Z̏4%{52眥-z&32D=ϓyʛ=D\sM;򬹤 Qp<͸G2ӫհQ%LuUݻ)D:;x+| tF| V[<爦ϜԇY$|ى%.iRՋC;M9Kx;{;s=w7yOQ{+&X`U=}+AhӱzS|9zo:GۮMʮ3כ`FTXM޹Xx|!> q88Ir w='G>=hүғի>^zCQպŵbZuDa\7ɉYa$[+w9Xjgc4ޫ/ʢ>ޘz; FY ՞ׯei@82`M<=A1[)w߭~ݛ. !(,|B)j6`;D"L>ɇa~9nW|Z'~!~1zqmAh PX q%!}zq`hA2"&ɹɱ   BJ{uAnITZRjv"yv#Ų YsI&5 bzܚgQH[eӴi8%m)rA )rNbLAŒ9gZd٨Q)%Z cp/M '֯k񞷃#"Ÿ"#}r+g*#*`u[io̳N YC>\^MU!:x7 )L'tELl"Y{`֠f V \YaE+67dWQK2⊜l6]$c|s EQYdդo6Ԙa^$r]#:g_nSg7djZQI=WGL*e)EiJsyW8ڡѓB\j)sz똴骥*~!"+g~&jB*ur$VujdtzXntg&H:k؅djB蹋Tߴ:ܣDӱ;S|kQJmVȯkI}!:/RЮ0㜳;! ?,/pH,Ȥrl:ШtJZجvxL.zn, wNd/|| ~caa `loqy{cehmm~jil O̟㪁gkp l%G_е[xρb7Deb44P۶S"\1ńwÛ8!Rdxc)O6hQ,5 p+J\u6#̴P3ku3~q:F)-i$xzVvYckVٴi94?C~|iv}DS{Uvu z#T4Q#dSO-QAvYוn楖f&™bֆ[o}9GgHicrFi R욚fZWB yX m޴OG" ϊZ (ňk.bƉ))Ś),m,kV$Z(}w빔ki^r[%L, lF`6x؏2vxy´ɈTRԲ@k1u LXvu#,/,pΌJDgLmEQ.IG@EaՕk~)7ؔ +chGqN~(Bwm4F?+SjVP6Suܵ((λK^cg /2x6s&ynKZ='8sԋ~[8P#^ _o}yx/6Kr1m8: FHIJ؄ġ,Ir`v[B#'~5ꇼ'9YK嚵y`胔>r78dѡմ p!<d8 `+V/x1=nq)!03~9gcj44 NĆjt3RLߚv+~YD'wKMd^ȸ2Oe,(7F .;ĮVgۍZ>0mAP uLq|\ I;f;#W?46d(j/KR>_iAvB0P`f3(|:@I]CЌϤ&LibwbD3)H,c9:$̈Xp\Ĥ$䣧YF#&ih.MaBeE C:A™khQ`]BټNwcY)W s%DPn`g TC6ZR`+.efnA s=}kZK-@bJCM>HM'P~.j=WYHBjI5+lZi\ PȝqD1WIp-<]ŅZwr i5r RwcbS-D;,gѪdJ`Y)]9fh>=m^`)ttY80<;З~:;8'G2qA[h F$++# #P@eupRivMbUx#z;~oD_rͪbCpiڷ#J% $voyЁZO9*J7B[CcI4 F~ Hַp׬U0Ҵ'M\B>`CG%QӗyƽCuʭ~] ?2^gj~Jفكy2-YD.PwDU4YʹrܜCG>[]Gdh"{Y=?2WE`v-'3r5N}̰;`b^?qDC=ΐq`74Γ6Aڌ亶'Kۇx*@;D?>*`n BXBv6-e2ltUjl>叝Tf()pfj쎘4Ia%DznXH~kl%]D,B_vɅKjͫ?; S%PeOhogOd?D\ADdƃ)/2$0?heJ%Ex%&nGm(K.@ ;"S̔w[KLr`XYZ97pޙGE73=b@8jK zŜNJo 4qu4u! /O@~D0<.5ஜ]@ }=qwT.<&ϙ9Q\.J #]R>x[t9zngX0poA!QbBBQARrRsSAaATAu A6 6dEEWC`Q!;,+m"<\" <}gHh(~H^龈ߨ$Hx8&4xc-M5;tP(E=i0!B BF2F.tSLORp*`%@\0u4 )klٳh l[ 2ULqaǨK7B}GwoI[!q7pɎ,߾r5-MnNp":zS kAJ !!DTbr2|yTXꙀl[Ai@ )0!-;֌ohD3 (ֆ: V׳cͪkn[=KHW$JA>O[50ַ3|$; $r? 9Z-LI5RVaZM q  V&az;Q+Nɔc 48c/)kG ! zc COf[06!\ !QQI6;sN,Ol0^)6E( @MDc8|3AE2οk T2!C:kb!*&{&^"L/`K,?= Ͽ?%IBIM4g:mQTӉ[X'Y$`rF)eP,$Lm , L`$~ၨ RM È1;XL0s2#%E K\%bEmEB׾}-C B@Jt =DZ6# $9ޣ}zSEek#aS͋U xUP2H苌_ H08o-STə'`Wܠsr18JuM`)=Q@kBw2*ºӰQI{_8lWcl%Fa(r}knK'>BPH $/uJ] \0bP!ЭX1b>N@VW"ڬq .q$ o r2!r g@"'"%f"36#;Z#?ZCL:QhHEn]A*"Q5&l|@!X#oc Kq *n$^ 2!rj@"#""1#9,=#Ar$Er$rPLPt 8Z&_p(2Ѹ,-@@f1 v:qRԮ1ױE2@$ R5+,o+#,[s6+Rrn"r#R-7$C2$2ΡF@%A(J& '[|nD;DXzH41|Ss!+r6k6r"w7A#--{ABP29-X/D`Ң.otS`̱Zrrm1O$xE䰁(/K# 'Ov(kzuropY$@*s5c3cJa6m7"u7A-R~:'9+CM0 Q6ѕMDDU0|Vom$Jdh4L(ڔ0T*2jM!I/ 16tSϵ5,wsTTA^KGRʅLThU*6]p5&!fWiDc"l'@dXt* Y% bLZձQS*ed˧2.YA6T+5uJ35eS]q]MU^SA}a8BUGL24h&&`DKT;0!OO@H"bDn6imqFEkOm5R*+fo56]kSEU7Ap7TsTyKQqh_!h v/fs߾t`B0_"ɺmk%u:ɚ)nw=+ֱ>|6@n#pEuwHYwWzyGw7w{WW7|D|7}9}9r .JD7`#aSa]b%tpLB|45F#RmȸZ7?M$T֖v(hPHJXeS^ cfj؆EAr0{bʚ/6n^ɴLh/tM--XZN4X)k5R\4X4nGVzWd DTaɇekZXVX]eak&[pX~n\""U5e,aIr7Wefa[ħ; 1Q!e4 )VB˾| Ls9KX{/jXrوD h~U9cuV_CQN0YyjM؀ND)4!#erPF@%%ҤW3$ ᘗyy8jRYkgz~NS_cU!A7~C%1(xr<ɛ9kbnQVMRq(EUT5qanq@@Z'OB礸͡#V֢F:7i:ڣgL'0iS6PfF"RZLhptHx|8M2-bzzœBއE~ne_7Wa銐k~=)NQXOnuxiyQ'ɴyMf@{Z[ Nr5D[N23/),::Wm`3[DJY#EdtqZF]*T8uĻM\F5e0D rrj¡jBlh#4ZϪ:{0?ZgVGK|БlerM{G%HZ*0BNHzg~x-t{Vsy?iZn -fPKH Ӟ oy(~o|L9ۢ80/ȣ6H KD=~ʳ} ;]{NH.\*T_/M!bRq-)\tCP yBNZNg[ е{aOj7NeŕDm٘8.z-4/-ZMe$=N|=Mɀ G#;NL<xg&u̠^\Ɵ嫤: Cۡ\W[y=Z^X99N&y ]<|ةy,5}/r Mǥ^~ȹAm5غ[a4otOx,O>=Ը/͏/(wq>Q\$C!޺~94~> W=}^w̟zau-t+A}1n3[qe#޳tq{ߧK^cƥfL=͑抔N|3sއY+g2ߪ:i!󍜊|SksNLIލ8pe~iw|/Mt~}O#>݄>y!HD(dr|.:bv81 av|n=/  %@FJNRVZ^bfBΩiiMA- > B5%5BY~~yy  -626^#"6jz :)Ɏ*1ͦ߆~jesc֨Iرd7A,^Ԧ(iā )BsuM pf=v[)XJ 4 aP2=Κv1##ؤUM$U$׮IX t*Ek廴\3 ٟDŐsT1UEeJG_"^(?]v[q<7b[,_9L138ZZkm޾'53F̤.1ܩN'hП=t0AbOZ5,Ŋi[VA_6Gv2y7I]R_3VGvF8 |@ %EISW+XP| .#yIm5dKQ ÆQ8u%~]OdYGq%w,w!aEbs"f^{1o8%k8Ei)EWavb^y_ A|&_D=NGm~@xMp9袮zT9H9`COm5yawJ,|~W+% :-DN)^haһd yD%Vۯv(Fzpvu z#T4Q#dSO-QAvYוn楖f&™bֆ[o}9GgHicrFi R욚fZWB yX m޴OG" ϊZ (ňk.bƉ))Ś),m,kV$Z(}w빔ki^r[%L, lF`6x؏2vxy´ɈTRԲ@k1u LXvu#,/,pΌJDgLmEQ.IG@EaՕk~)7ؔ +chGqN~(Bwm4F?+SjVP6Suܵ((λK^cg /2x6s&ynKZ='8sԋ~[8P#^ _o}yx/6Kr1m8: FHIJ؄ġ,Ir`v[B#'~5ꇼ'9YK嚵y`胔>r78dѡմ p!<d8 `+V/x1=nq)!03~9gcj44 NĆjt3RLߚv+~YD'wKMd^ȸ2Oe,(7F .;ĮVgۍZ>0mAP uLq|\ I;f;#W?46d(j/KR>_iAvB0P`f3(|:@I]CЌϤ&LibwbD3)H,c9:$̈Xp\Ĥ$䣧YF#&ih.MaBeE C:A™khQ`]BټNwcY)W s%DPn`g TC6ZR`+.efnA s=}kZK-@bJCM>HM'P~.j=WYHBjI5+lZi\ PȝqD1WIp-<]ŅZwr i5r RwcbS-D;,gѪdJp虞;py.UvWB+`&iS4`=pzI <:z:Y"z6@$j(99./02/p8z+p RW+(CjpŔp:Zٞ[ ;%9&s~iS/06rzp ʠ=uj )ZzI#*%3.J6:ʣ=z\h*Щ*&0yr( .rb` \DWFX>ŖsYjWtJȚ:zTzʡ !ꚩ٢-ښ,ڨ,+5:3:*ꩠ*ʤפH i5̊rzJ.;wɗf %#FkZYJӚyZi9@ٚ67[/+ʮz#hAS7-Щj_ b~:x:*ĺI.`4p|lL6gp9l,r)j>Pڱ 9WӚ+뙅0+:'Zڢ3,`몮7ʮ-!7ʴL+&LʤN @yڵ^%S=Vjm ^ jY˱Uʠj:XKI&i%ꚭy{;, B[>J+й !æCp@ ZU: ;`z;;g$:9 K۪˺ɪꙘi/K&4‹+>[AKLHI'{L )*Vz.'0g|42;+*Hlw"{$j;ٲzi9:J0L{- X6KKMk~eK` ڧڱ]̱u;J+0-?}C{=G-<,a)'hCii֭%޹xE$*b5Rf`ׄ?^|c(gz1+.[7C"6hoM- ۀ>LЇLJS+ ,N+/ ^՘W9 &GcQK-9ҌOSn> )$IDx7Kw8~< n͵δ#V7,D z!䖃&DEa Lj\cF(|FΜ=5Z)ur얦cKL\|ߡe8gy%4a%rw,/n#̭5?"KxXP -Jݝ-M/u^x1aB$Ђ(bw)i`vX?{8Ãz_!ll"7$n(gH `ؐG!K늬/ =9!9b 4d:֨qM)l?J$Z`˂̆#1*j #$BbAFZx@ $8ʖ4!C6lCy xT&gUl}D{X;ߞՓ\pko{ &>1ʰB@\<cZ9!|q Ax.Dh;dw59p|Vx^TWn6;e G Ȝm$Ca[^8㝃+@^wS9y!AX"=$To7XO{d9ܲ8 LEԗqhSe0)B#A[p0o4J U3C@Qb*E t`ni [LU# ilP8~4mp ټMi)2֣6zg,cyI jPV8l/K_W p#neNHKuihCzjt Q6em7E+f ם*b$!W1&$7blk8H:S*q䌨{[ z+1J`/X8t!iZ.`ua& ƩYTF)GFpͱAq1t)Hm6oZ9'>iC. O'ǷI5$1BFdfOxSIH @MȀ`k h@ 8O2 S fL)0̄uCa,6c*D6I,X8oq`"o! 1/y1*TQU q-"`oN A['6hk, \ Wq/8X~8h&ecS&"Q霍H"D[?&ɥjiz X41$+S`,8rleACնVS.;aMc㶼]a+i\s imu:L1R/ СR@J& G!כȘF֑ -{@O -0&u .ڧ5 fJ8P^Ă{p<:&ƪqD" h. ^v0u@cEG ;Xᑍ IgBđr"D$yWq+@~x(Z[^.(k5 4U,s/L;CAxFrc62ԜqŨ3֙.^6M:TaL2&ue:eɫ$ns el?54=rz U Z5+#!T9}d·3ǎXv/]t 4mv\!Fg[>!ۋV}X}_/ A;,6G]G+}0@ F zw \{l:yH`'>yFCJ'p8Jޗ @GJ !9'z"j~W}3dJXL̲dȎl0vאاO͖mgO-boދyDO!j*򺨋r:^JF-, &JGZ f6#||n ` 1.O/df:yFjLۂ+&xi4|Pb.a-Ḁ̏,MOn d3X) BzHҎs1V@ GD䮊8I-n@P1=&ļh;CH#^+HCOȴ AVqUB $Xt* K!`/{0N|J ю!.rM^PZ 6P2E[0pr&NNB n,cFMRBNcCP*/MQƑVl p =6^ & .!1Kd /2.2##1p}$D2T4'B^ zH* M*{rȐp*SCZ#P#:@:3;3K43F3KJ4Ss5!5]63H5g4oS  .R/X@,,aDeN|Dk-ߒ"$A.R[B`/-PP09I`/*Ab2Q#SCr&J& @e`"ATAc`AtAt`@B)4VA1 'H*2+JD%`0=r!. 3:A+v- # F2/2<.$rT?]R0bxed`X̡X?-sL-shNJazըXJJ.,p!3 pu#w4zOif$0IM~EF3'[j1CVƖ0D@BpV{0X*D],dXYUYa1P ODB/[,Ð9un Rf$p:۰uTRS>R#2@(M BClbCbA ccpO3+OC lh/beEe[mȵn URy4LTZ$C$@QOi#aRV`e_eKM/;`OBOul'6YX/Mtڶ6"doM>DfdR@tp_`x(!1f].g5%(^gFsnRF7GDME\uƱ6wwlq75!c@Ag7M@oFoIT7D W/oe G-#Uqs6g}]1Uؠ*I^tNޗ![ ރs7uϢnvm m1VI@Dž(8 yxIVX:xXqFԢWz]96p\!Տy g2.r rU ri @/}E!!X OaZ8j"`DO6ymMm=x9vc7fuBč"E~M#/y-k2qwqY]թ ╉Yù$*Y32 76Z[UY*=ƣ` :=솲:a<睩K@pb+ ã0zgVRw{yqcLF`zB`o*GNJpN0^/ =:t1j'6 :SR:XZYYӚa8ԭW`B9tB1TzR`=*ɢƀ6@W`G8GyW:{/:۳y(ZiG^%u/ #/Ej 7qZ [4@|UBDueJAǯ{րΪ}Q#0WU;0;t&}3Q%yϲCX+6 ԶMٶsYw;qrp a1XDXJpp[=|}:o_X;0<ŴrWǾT,N<ٓ3O 4)dr8\G4\d B\̹  {{Q{[.Hg2牾ŪH;͐B+. Эp3ȆZ+}d+J4ܢ0|ymM~y{Ssv˛RS_]Aއ[r%/aMf=)  (ZȃE E6>|8- ) = ]dO>4<ǕFfax<]=Uh;~=w{ݓd۵#X:縁n<)+MJ:K835!)M_ؼ[[η#@qMw|ط ¥Zx~Z)>VmzwQɇHWS~ݝݝd2['̕ss߲,"CGؓ:wo%y/}Ay; H&aM֐%]-jۅO<ٜ[f(w[2ֽ9q;7g^:˿@̓Xˋ=/ޝ>$o~d,zcr"}"oQ7UEK.qƽ[ߑ)xi_m'][}J6_Mt H/B  BP Qp.`EXöxl :n  w}$*.26:>:|mE-9%! qr2t.<>02H’2ʚ>,} er*4a"=]WJUa]eYmqqMNmu} A+JNN)+ cv~ AQHq2K߯bŠ;%eaiVEjb|&۶5#rY埘5 ˩00FAiM zkiD颥t)Si-@00⓲f/RyVڴiɜ!Y*R̾`SM;J=Ez/ʻdE_Ne$kH.1(1{Gj>eS[)SwͿ;:GXDΌB\ܧfgX&bb5ڴ4B]#톦o{ \:~9:s>}PP6u`Wa]L>FU7 zP{H |y15 '&_]_.`)dNl0 cV:4ޅGa7WKv$G41b'3VU#60c(ᰔK!gȜ{s5jf"u&micuIyb% lmhhal%p-wg. @;&n¡VaWaiF NZEZGaԗQWnzʣd &Xt2+FJ*QY{3kǢ4Ҿ}YK*.d`\bH0=@MdkQ$֤d gn1?;0!Y#~lW/Gq`9NK?"6 BtZzbʖXrj&82Z{mgKrp_gr bB:yup2bؠ%r.nDPMm]:8 L.'2B/NSGFcLXGef7Z<3}7~4q0waފ3:zƛ Ќ##;F>l1z!5@.xi\{tľ(qlM7.c Aȷ|YeHH[1J07FGrC4U܄Y0%XƿdS 33i6TP&6->u}l6&hR^愼9nȡ_<+ Ag=}^rhԖ-}C03y2TUZ4(W)F{M7)Ғ"L?ownpB dSuRUӯ4&)}sn@R7z\:gQmXA҉ҫ:Gc5[pJβjˬԠW͙R%o[aɽU!FG 69i(U='"1=&xK'ajuC(Zw'yK9f23%q-)YR֜]h?afhZO.q0[ɯa=/S]6q0%/fϱ]$UZ^۾׶FG;{nxkpkl:xmK DZ0OG"8*|Ϻ KlϿ0VL3ob"vw#'3{G r·MUk[$c9Ϊ}u,-'x>Fgl ٺo1a*_rβa\_Vs3F;fltk-1.4.3/test/images/tiny.png0000644000175000017500000000025215004135251016521 0ustar albrechtalbrechtPNG  IHDR! FPLTE"UĢ pHYsHHFk> vpAg! u$5IDATc??F0i0yC0x<;@e[I. ZIENDB`fltk-1.4.3/test/images/Fl_Value_Input.png0000644000175000017500000000103415004135251020411 0ustar albrechtalbrechtPNG  IHDR2$ bKGD pHYsHHFk> vpAg2=IDAThQr ׎G ye #include // resize dialog and arrow dimensions int TLx = 35, TRx = 270, TGx = 470, TLw = 200, TGw = 120, TAw = 35; int TLy = 35, BLy = 160, LGy = 250, TLh = 90, LGh = 90, LAh = 35; // window dimensions int Ww = 590, Wh = 340; Fl_Double_Window *window; class ResizeDialog : public Fl_Group { public: ResizeDialog(int X, int Y, int W, int H, const char *T = 0); Fl_Box *m_icon; Fl_Box *m_message; Fl_Button *m_button; }; ResizeDialog::ResizeDialog(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->align(FL_ALIGN_TOP_LEFT); this->box(FL_UP_BOX); m_icon = new Fl_Box(X + 10, Y + 10, 30, 30, "!"); m_icon->box(FL_DOWN_BOX); m_message = new Fl_Box(X + 50, Y + 10, 140, 30, "Out of Memory"); m_message->box(FL_DOWN_BOX); m_message->color(FL_YELLOW); Fl_Group *group = new Fl_Group(X + 50, Y + 50, 140, 30); Fl_Box *b = new Fl_Box(X + 50, Y + 50, 90, 30, "R"); b->box(FL_UP_BOX); // b->color(FL_YELLOW); m_button = new Fl_Button(X + 140, Y + 50, 50, 30, "Darn!"); group->resizable(b); group->end(); this->end(); this->resizable(m_message); } class Resizables : public Fl_Group { public: Resizables(int X, int Y, int W, int H, const char *T = 0); ResizeDialog *TL, *TR, *BL, *BR; // topleft, topright, bottomleft, bottomright Harrow *LA, *RA; // left arrow, right arrow Varrow *TA, *BA; // top arrow, bottom arrow }; Resizables::Resizables(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->box(FL_UP_BOX); this->color(FL_WHITE); TL = new ResizeDialog(X + TLx, Y + TLy, TLw, TLh, "Original Size"); TL->resizable(0); TR = new ResizeDialog(X + TRx, Y + TLy, TLw, TLh, "Horizontally Resized"); BL = new ResizeDialog(X + TLx, Y + BLy, TLw, TLh, "Vertically Resized"); BR = new ResizeDialog(X + TRx, Y + BLy, TLw, TLh, "Horizontally and Vertically Resized"); Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); LG->box(FL_NO_BOX); LG->color(FL_WHITE); LA = new Harrow(BL->m_message->x(), LG->y(), BL->m_message->w(), LAh, "Initial\nwidth"); LG->resizable(LA); LG->end(); Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); RG->box(FL_NO_BOX); RG->color(FL_WHITE); RA = new Harrow(BR->m_message->x(), LG->y(), BL->m_message->w(), LAh, "Resized\nwidth"); RG->resizable(RA); RG->end(); Fl_Group *TG = new Fl_Group(X + TGx, Y + TLy, TGw, TLh); TG->box(FL_NO_BOX); TG->color(FL_WHITE); TA = new Varrow(TG->x(), TR->m_message->y(), TAw, TR->m_message->h(), "Initial\nheight"); TG->resizable(TA); TG->end(); Fl_Group *BG = new Fl_Group(X + TGx, Y + BLy, TGw, TLh); BG->box(FL_NO_BOX); BG->color(FL_WHITE); BA = new Varrow(BG->x(), BR->m_message->y(), TAw, BR->m_message->h(), "Resized\nheight"); BG->resizable(BA); BG->end(); this->resizable(BR); this->end(); } int main(int argc, char **argv) { window = new Fl_Double_Window(Ww, Wh, "resize-example3c"); window->color(FL_WHITE); Resizables *resizables = new Resizables(0, 0, Ww, Wh); window->end(); window->resizable(resizables); window->size_range(Ww, Wh); window->show(argc, argv); window->size(Ww + 50, Wh + 35); Fl::visible_focus(0); // suppress focus box return Fl::run(); } fltk-1.4.3/test/minimum.cxx0000644000175000017500000000426115004135251015766 0ustar albrechtalbrecht// // Minimal update test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // This is a test of the minimal update code. The right slider has a // label that extends outside its border, and the minimal update // assumes this does not happen. Thus there is *supposed* to be // display errors when you move the right-most or any other slider. // If you *don't* see these errors, then the minimal update is // broken!!! // // I cannot emphasize how important it is to test this and make sure // any changes have not broken the minimal update. These sort of bugs // are extremely hard to fix and must be detected right away! // // The reason it is important to fix this is that otherwise you will // swiftly end up with a toolkit that thinks it has to draw the window // 20 times each time the display changes. I don't care how fast the // machine is, this is an insane waste of resources, and should be // stopped! // #include #include #include #include #include #include int main(int argc, char **argv) { Fl_Double_Window *window = new Fl_Double_Window(400,320,argv[0]); window->resizable(*(new Fl_Box(FL_ENGRAVED_FRAME,10,10,300,300, "MINIMUM UPDATE TEST\n" "\n" "The slider on the right purposely\n" "draws outside its boundaries.\n" "Moving it should leave old copies\n" "of the label. These copies should\n" "*not* be erased by any actions\n" "other than hiding and showing\n" "of that portion of the window\n" "or changing the button that\n" "intersects them."))); Fl_Slider *s; s = new Fl_Slider(320,10,20,300,"Too_Big_Label"); s->align(0); new Fl_Button(20,270,100,30,"Button"); new Fl_Return_Button(200,270,100,30,"Button"); window->show(argc, argv); return Fl::run(); } fltk-1.4.3/test/hello.cxx0000644000175000017500000000156515004135251015422 0ustar albrechtalbrecht// // Hello, World! program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include int main(int argc, char **argv) { Fl_Window *window = new Fl_Window(340, 180); Fl_Box *box = new Fl_Box(20, 40, 300, 100, "Hello, World!"); box->box(FL_UP_BOX); box->labelfont(FL_BOLD + FL_ITALIC); box->labelsize(36); box->labeltype(FL_SHADOW_LABEL); window->end(); window->show(argc, argv); return Fl::run(); } fltk-1.4.3/test/fractals.cxx0000644000175000017500000005441115004135251016114 0ustar albrechtalbrecht// // Fractal drawing demo for the Fast Light Tool Kit (FLTK). // // This is a GLUT demo program, with modifications to // demonstrate how to add FLTK controls to a GLUT program. The GLUT // code is unchanged except for the end (search for FLTK to find changes). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if !HAVE_GL || !HAVE_GL_GLU_H #include #include int main(int, char**) { fl_alert("This demo does not work without GL and GLU"); return 1; } #else /* * To compile: cc -o fractals fractals.c -lGL -lGLU -lX11 -lglut -lXmu -lm * * Usage: fractals * * Homework 6, Part 2: fractal mountains and fractal trees * (Pretty Late) * * Draws fractal mountains and trees -- and an island of mountains in water * (I tried having trees on the island but it didn't work too well.) * * Two viewer modes: polar and flying (both restrained to y>0 for up vector). * Keyboard 0->9 and +/- control speed when flying. * * Only keyboard commands are 0-9 and +/- for speed in flying mode. * * Fog would make the island look much better, but I couldn't get it to work * correctly. Would line up on -z axis not from eye. * * Philip Winston - 3/4/95 * pwinston@hmc.edu * http://www.cs.hmc.edu/people/pwinston * */ #include #include #include #include #include #include /* ULONG_MAX is defined here */ #include /* FLT_MAX is atleast defined here */ #include /* for random seed */ #include "fracviewer.h" #if defined(_WIN32) # define drand48() (((float) rand())/((float) RAND_MAX)) # define srand48(x) (srand((x))) #elif defined __APPLE__ # define drand48() (((float) rand())/((float) RAND_MAX)) # define srand48(x) (srand((x))) #endif typedef enum { NOTALLOWED, MOUNTAIN, TREE, ISLAND, BIGMTN, STEM, LEAF, MOUNTAIN_MAT, WATER_MAT, LEAF_MAT, TREE_MAT, STEMANDLEAVES, AXES } DisplayLists; // Note: MAXLEVEL is the highest level, range is 0..MAXLEVEL #define MAXLEVEL 8 int Rebuild = 1, /* Rebuild display list in next display? */ fractal = TREE, /* What fractal are we building */ Level = 4; /* levels of recursion for fractals */ int DrawAxes = 0; /***************************************************************/ /************************* VECTOR JUNK *************************/ /***************************************************************/ /* print vertex to stderr */ void printvert(float v[3]) { fprintf(stderr, "(%f, %f, %f)\n", v[0], v[1], v[2]); } #if 0 // removed for FL, it is in fracviewer.c /* normalizes v */ void normalize(GLfloat v[3]) { GLfloat d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); if (d == 0) fprintf(stderr, "Zero length vector in normalize\n"); else v[0] /= d; v[1] /= d; v[2] /= d; } /* calculates a normalized crossproduct to v1, v2 */ void ncrossprod(float v1[3], float v2[3], float cp[3]) { cp[0] = v1[1]*v2[2] - v1[2]*v2[1]; cp[1] = v1[2]*v2[0] - v1[0]*v2[2]; cp[2] = v1[0]*v2[1] - v1[1]*v2[0]; normalize(cp); } #endif /* calculates normal to the triangle designated by v1, v2, v3 */ void triagnormal(float v1[3], float v2[3], float v3[3], float norm[3]) { float vec1[3], vec2[3]; vec1[0] = v3[0] - v1[0]; vec2[0] = v2[0] - v1[0]; vec1[1] = v3[1] - v1[1]; vec2[1] = v2[1] - v1[1]; vec1[2] = v3[2] - v1[2]; vec2[2] = v2[2] - v1[2]; ncrossprod(vec2, vec1, norm); } float xzlength(float v1[3], float v2[3]) { return sqrtf((v1[0] - v2[0])*(v1[0] - v2[0]) + (v1[2] - v2[2])*(v1[2] - v2[2])); } float xzslope(float v1[3], float v2[3]) { return ((v1[0] != v2[0]) ? ((v1[2] - v2[2]) / (v1[0] - v2[0])) : FLT_MAX); } /***************************************************************/ /************************ MOUNTAIN STUFF ***********************/ /***************************************************************/ GLfloat DispFactor[MAXLEVEL + 1]; /* Array of what to multiply random number by for a given level to get midpoint displacement */ GLfloat DispBias[MAXLEVEL + 1]; /* Array of what to add to random number before multiplying it by DispFactor */ #define NUMRANDS 191 float RandTable[NUMRANDS]; /* hash table of random numbers so we can raise the same midpoints by the same amount */ /* The following are for permitting an edge of a moutain to be */ /* pegged so it won't be displaced up or down. This makes it */ /* easier to setup scenes and makes a single moutain look better */ GLfloat Verts[3][3], /* Vertices of outside edges of mountain */ Slopes[3]; /* Slopes between these outside edges */ int Pegged[3]; /* Is this edge pegged or not */ /* * Comes up with a new table of random numbers [0,1) */ void InitRandTable(unsigned int seed) { int i; srand48((long) seed); for (i = 0; i < NUMRANDS; i++) RandTable[i] = drand48() - 0.5f; } /* calculate midpoint and displace it if required */ void Midpoint(GLfloat mid[3], GLfloat v1[3], GLfloat v2[3], int edge, int level) { unsigned hash; mid[0] = (v1[0] + v2[0]) / 2; mid[1] = (v1[1] + v2[1]) / 2; mid[2] = (v1[2] + v2[2]) / 2; if (!Pegged[edge] || (fabs(xzslope(Verts[edge], mid) - Slopes[edge]) > 0.00001)) { srand48((int)((v1[0]+v2[0])*23344)); hash = unsigned(drand48() * 7334334); srand48((int)((v2[2]+v1[2])*43433)); hash = (unsigned)(drand48() * 634344 + hash) % NUMRANDS; mid[1] += ((RandTable[hash] + DispBias[level]) * DispFactor[level]); } } /* * Recursive moutain drawing routine -- from lecture with addition of * allowing an edge to be pegged. This function requires the above * globals to be set, as well as the Level global for fractal level */ static float cutoff = -1; void FMR(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int level) { if (level == Level) { GLfloat norm[3]; if (v1[1] <= cutoff && v2[1]<=cutoff && v3[1]<=cutoff) return; triagnormal(v1, v2, v3, norm); glNormal3fv(norm); glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v3); } else { GLfloat m1[3], m2[3], m3[3]; Midpoint(m1, v1, v2, 0, level); Midpoint(m2, v2, v3, 1, level); Midpoint(m3, v3, v1, 2, level); FMR(v1, m1, m3, level + 1); FMR(m1, v2, m2, level + 1); FMR(m3, m2, v3, level + 1); FMR(m1, m2, m3, level + 1); } } /* * sets up lookup tables and calls recursive mountain function */ void FractalMountain(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int pegged[3]) { GLfloat lengths[MAXLEVEL + 1]; GLfloat fraction[8] = { 0.3f, 0.3f, 0.4f, 0.2f, 0.3f, 0.2f, 0.4f, 0.4f }; GLfloat bias[8] = { 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f }; int i; float avglen = (xzlength(v1, v2) + xzlength(v2, v3) + xzlength(v3, v1) / 3); for (i = 0; i < 3; i++) { Verts[0][i] = v1[i]; /* set mountain vertex globals */ Verts[1][i] = v2[i]; Verts[2][i] = v3[i]; Pegged[i] = pegged[i]; } Slopes[0] = xzslope(Verts[0], Verts[1]); /* set edge slope globals */ Slopes[1] = xzslope(Verts[1], Verts[2]); Slopes[2] = xzslope(Verts[2], Verts[0]); lengths[0] = avglen; for (i = 1; i < Level; i++) { lengths[i] = lengths[i-1]/2; /* compute edge length for each level */ } for (i = 0; i < Level; i++) { /* DispFactor and DispBias arrays */ DispFactor[i] = (lengths[i] * ((i <= 7) ? fraction[i] : fraction[7])); DispBias[i] = ((i <= 7) ? bias[i] : bias[7]); } glBegin(GL_TRIANGLES); FMR(v1, v2, v3, 0); /* issues no GL but vertex calls */ glEnd(); } /* * draw a mountain and build the display list */ void CreateMountain(void) { GLfloat v1[3] = { 0, 0, -1 }, v2[3] = { -1, 0, 1 }, v3[3] = { 1, 0, 1 }; int pegged[3] = { 1, 1, 1 }; glNewList(MOUNTAIN, GL_COMPILE); glPushAttrib(GL_LIGHTING_BIT); glCallList(MOUNTAIN_MAT); FractalMountain(v1, v2, v3, pegged); glPopAttrib(); glEndList(); } /* * new random numbers to make a different moutain */ void NewMountain(void) { InitRandTable((unsigned int)time(NULL)); } /***************************************************************/ /***************************** TREE ****************************/ /***************************************************************/ long TreeSeed; /* for srand48 - remember so we can build "same tree" at a different level */ /* * recursive tree drawing thing, fleshed out from class notes pseudocode */ void FractalTree(int level, long level_seed) { if (level == Level) { glPushMatrix(); glRotatef(drand48()*180, 0, 1, 0); glCallList(STEMANDLEAVES); glPopMatrix(); } else { glCallList(STEM); glPushMatrix(); glRotatef(drand48()*180.0f, 0.0f, 1.0f, 0.0f); glTranslatef(0.0f, 1.0f, 0.0f); glScalef(0.7f, 0.7f, 0.7f); srand48(level_seed+1); glPushMatrix(); glRotatef(110.0f + drand48()*40.0f, 0.0f, 1.0f, 0.0f); glRotatef( 30.0f + drand48()*20.0f, 0.0f, 0.0f, 1.0f); FractalTree(level + 1, level_seed+4); glPopMatrix(); srand48(level_seed+2); glPushMatrix(); glRotatef(-130.0f + drand48()*40.0f, 0.0f, 1.0f, 0.0f); glRotatef( 30.0f + drand48()*20.0f, 0.0f, 0.0f, 1.0f); FractalTree(level + 1, level_seed+5); glPopMatrix(); srand48(level_seed+3); glPushMatrix(); glRotatef(-20.0f + drand48()*40.0f, 0.0f, 1.0f, 0.0f); glRotatef( 30.0f + drand48()*20.0f, 0.0f, 0.0f, 1.0f); FractalTree(level + 1, level_seed+6); glPopMatrix(); glPopMatrix(); } } /* * Create display lists for a leaf, a set of leaves, and a stem */ void CreateTreeLists(void) { GLUquadricObj *cylquad = gluNewQuadric(); int i; glNewList(STEM, GL_COMPILE); glPushMatrix(); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); gluCylinder(cylquad, 0.1, 0.08, 1, 10, 2 ); glPopMatrix(); glEndList(); glNewList(LEAF, GL_COMPILE); /* I think this was jeff allen's leaf idea */ glBegin(GL_TRIANGLES); glNormal3f(-0.1f, 0.00f, 0.25f); /* not normalized */ glVertex3f( 0.0f, 0.00f, 0.00f); glVertex3f(0.25f, 0.25f, 0.10f); glVertex3f(0.00f, 0.50f, 0.00f); glNormal3f( 0.10f, 0.00f, 0.25f); glVertex3f( 0.00f, 0.00f, 0.00f); glVertex3f( 0.00f, 0.50f, 0.00f); glVertex3f(-0.25f, 0.25f, 0.10f); glEnd(); glEndList(); glNewList(STEMANDLEAVES, GL_COMPILE); glPushMatrix(); glPushAttrib(GL_LIGHTING_BIT); glCallList(STEM); glCallList(LEAF_MAT); for(i = 0; i < 3; i++) { glTranslatef(0.0f, 0.333f, 0.0f); glRotatef(90.0f, 0.0f, 1.0f, 0.0f); glPushMatrix(); glRotatef( 0.0f, 0.0f, 1.0f, 0.0f); glRotatef(50.0f, 1.0f, 0.0f, 0.0f); glCallList(LEAF); glPopMatrix(); glPushMatrix(); glRotatef(180.0f, 0.0f, 1.0f, 0.0f); glRotatef( 60.0f, 1.0f, 0.0f, 0.0f); glCallList(LEAF); glPopMatrix(); } glPopAttrib(); glPopMatrix(); glEndList(); gluDeleteQuadric(cylquad); } /* * draw and build display list for tree */ void CreateTree(void) { srand48(TreeSeed); glNewList(TREE, GL_COMPILE); glPushMatrix(); glPushAttrib(GL_LIGHTING_BIT); glCallList(TREE_MAT); glTranslatef(0, -1, 0); FractalTree(0, TreeSeed); glPopAttrib(); glPopMatrix(); glEndList(); } /* * new seed for a new tree (groan) */ void NewTree(void) { TreeSeed = long(time(NULL)); // use time() as random seed } /***************************************************************/ /*********************** FRACTAL PLANET ************************/ /***************************************************************/ void CreateIsland(void) { cutoff = .06f; CreateMountain(); cutoff = -1; glNewList(ISLAND, GL_COMPILE); glPushAttrib(GL_LIGHTING_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glCallList(WATER_MAT); glBegin(GL_QUADS); glNormal3f( 0.0f, 1.00f, 0.0f); glVertex3f( 10.0f, 0.01f, 10.0f); glVertex3f( 10.0f, 0.01f, -10.0f); glVertex3f(-10.0f, 0.01f, -10.0f); glVertex3f(-10.0f, 0.01f, 10.0f); glEnd(); glPushMatrix(); glTranslatef(0.0f, -0.1f, 0.0f); glCallList(MOUNTAIN); glPopMatrix(); glPushMatrix(); glRotatef(135.0f, 0.0f, 1.0f, 0.0f); glTranslatef(0.2f, -0.15f, -0.4f); glCallList(MOUNTAIN); glPopMatrix(); glPushMatrix(); glRotatef(-60.0f, 0.0f, 1.0f, 0.0f); glTranslatef(0.7f, -0.07f, 0.5f); glCallList(MOUNTAIN); glPopMatrix(); glPushMatrix(); glRotatef(-175.0f, 0.0f, 1.0f, 0.0f); glTranslatef(-0.7f, -0.05f, -0.5f); glCallList(MOUNTAIN); glPopMatrix(); glPushMatrix(); glRotatef(165.0f, 0.0f, 1.0f, 0.0f); glTranslatef(-0.9f, -0.12f, 0.0f); glCallList(MOUNTAIN); glPopMatrix(); glPopMatrix(); glPopAttrib(); glEndList(); } void NewFractals(void) { NewMountain(); NewTree(); } void Create(int fract) { switch(fract) { case MOUNTAIN: CreateMountain(); break; case TREE: CreateTree(); break; case ISLAND: CreateIsland(); break; } } /***************************************************************/ /**************************** OPENGL ***************************/ /***************************************************************/ void SetupMaterials(void) { GLfloat mtn_ambuse[] = { 0.426f, 0.256f, 0.108f, 1.0f }; GLfloat mtn_specular[] = { 0.394f, 0.272f, 0.167f, 1.0f }; GLfloat mtn_shininess[] = { 10.0f }; GLfloat water_ambuse[] = { 0.0f, 0.1f, 0.5f, 1.0f }; GLfloat water_specular[] = { 0.0f, 0.1f, 0.5f, 1.0f }; GLfloat water_shininess[] = { 10.0f }; GLfloat tree_ambuse[] = { 0.4f, 0.25f, 0.1f, 1.0f }; GLfloat tree_specular[] = { 0.0f, 0.00f, 0.0f, 1.0f }; GLfloat tree_shininess[] = { 0.0f }; GLfloat leaf_ambuse[] = { 0.0f, 0.8f, 0.0f, 1.0f }; GLfloat leaf_specular[] = { 0.0f, 0.8f, 0.0f, 1.0f }; GLfloat leaf_shininess[] = { 10.0f }; glNewList(MOUNTAIN_MAT, GL_COMPILE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mtn_ambuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mtn_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mtn_shininess); glEndList(); glNewList(WATER_MAT, GL_COMPILE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, water_ambuse); glMaterialfv(GL_FRONT, GL_SPECULAR, water_specular); glMaterialfv(GL_FRONT, GL_SHININESS, water_shininess); glEndList(); glNewList(TREE_MAT, GL_COMPILE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tree_ambuse); glMaterialfv(GL_FRONT, GL_SPECULAR, tree_specular); glMaterialfv(GL_FRONT, GL_SHININESS, tree_shininess); glEndList(); glNewList(LEAF_MAT, GL_COMPILE); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, leaf_ambuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, leaf_specular); glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, leaf_shininess); glEndList(); } void myGLInit(void) { GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat light_position[] = { 0.0f, 0.3f, 0.3f, 0.0f }; GLfloat lmodel_ambient[] = { 0.4f, 0.4f, 0.4f, 1.0f }; glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); #if 0 glEnable(GL_CULL_FACE); glCullFace(GL_BACK); #endif glShadeModel(GL_SMOOTH); #if 0 glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #endif SetupMaterials(); CreateTreeLists(); glFlush(); } /***************************************************************/ /************************ GLUT STUFF ***************************/ /***************************************************************/ int winwidth = 1; int winheight = 1; void reshape(int w, int h) { glViewport(0,0,w,h); winwidth = w; winheight = h; } void display(void) { time_t curtime; char buf[255]; static time_t fpstime = 0; static int fpscount = 0; static int fps = 0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLdouble)winwidth/winheight, 0.01, 100); agvViewTransform(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if (Rebuild) { Create(fractal); Rebuild = 0; } glCallList(fractal); if (DrawAxes) glCallList(AXES); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, winwidth, 0.0, winheight); snprintf(buf, sizeof(buf), "FPS=%d", fps); glColor3f(1.0f, 1.0f, 1.0f); gl_font(FL_HELVETICA, 12); gl_draw(buf, 10, 10); // // Use glFinish() instead of glFlush() to avoid getting many frames // ahead of the display (problem with some Linux OpenGL implementations...) // glFinish(); // Update frames-per-second fpscount ++; curtime = time(NULL); if ((curtime - fpstime) >= 2) { fps = (fps + fpscount / int(curtime - fpstime)) / 2; fpstime = curtime; fpscount = 0; } } void visible(int v) { if (v == GLUT_VISIBLE) agvSetAllowIdle(1); else { glutIdleFunc(NULL); agvSetAllowIdle(0); } } void menuuse(int v) { if (v == GLUT_MENU_NOT_IN_USE) agvSetAllowIdle(1); else { glutIdleFunc(NULL); agvSetAllowIdle(0); } } /***************************************************************/ /******************* MENU SETUP & HANDLING *********************/ /***************************************************************/ typedef enum { MENU_QUIT, MENU_RAND, MENU_MOVE, MENU_AXES } MenuChoices; void setlevel(int value) { Level = value; Rebuild = 1; glutPostRedisplay(); } void choosefract(int value) { fractal = value; Rebuild = 1; glutPostRedisplay(); } void handlemenu(int value) { switch (value) { case MENU_QUIT: exit(0); break; case MENU_RAND: NewFractals(); Rebuild = 1; glutPostRedisplay(); break; case MENU_AXES: DrawAxes = !DrawAxes; glutPostRedisplay(); break; } } void MenuInit(void) { int submenu3, submenu2, submenu1; submenu1 = glutCreateMenu(setlevel); glutAddMenuEntry("0", 0); glutAddMenuEntry("1", 1); glutAddMenuEntry("2", 2); glutAddMenuEntry("3", 3); glutAddMenuEntry("4", 4); glutAddMenuEntry("5", 5); glutAddMenuEntry("6", 6); glutAddMenuEntry("7", 7); glutAddMenuEntry("8", 8); submenu2 = glutCreateMenu(choosefract); glutAddMenuEntry("Moutain", MOUNTAIN); glutAddMenuEntry("Tree", TREE); glutAddMenuEntry("Island", ISLAND); submenu3 = glutCreateMenu(agvSwitchMoveMode); glutAddMenuEntry("Flying", FLYING); glutAddMenuEntry("Polar", POLAR); glutCreateMenu(handlemenu); glutAddSubMenu((char *)"Level", submenu1); glutAddSubMenu((char *)"Fractal", submenu2); glutAddSubMenu((char *)"Movement", submenu3); glutAddMenuEntry("New Fractal", MENU_RAND); glutAddMenuEntry("Toggle Axes", MENU_AXES); glutAddMenuEntry("Quit", MENU_QUIT); glutAttachMenu(GLUT_RIGHT_BUTTON); } /***************************************************************/ /**************************** MAIN *****************************/ /***************************************************************/ // FLTK-style callbacks to Glut menu callback translators: void setlevel(Fl_Widget*, void *value) {setlevel(fl_int(value));} void choosefract(Fl_Widget*, void *value) {choosefract(fl_int(value));} void handlemenu(Fl_Widget*, void *value) {handlemenu(fl_int(value));} #include #include #include int main(int argc, char** argv) { Fl::use_high_res_GL(1); // glutInit(&argc, argv); // this line removed for FLTK // create FLTK window: Fl_Window window(512+20, 512+100); window.resizable(window); // create a bunch of buttons: Fl_Group *g = new Fl_Group(110,50,400-110,30,"Level:"); g->align(FL_ALIGN_LEFT); g->begin(); Fl_Button *b; b = new Fl_Button(110,50,30,30,"0"); b->callback(setlevel,(void*)0); b = new Fl_Button(140,50,30,30,"1"); b->callback(setlevel,(void*)1); b = new Fl_Button(170,50,30,30,"2"); b->callback(setlevel,(void*)2); b = new Fl_Button(200,50,30,30,"3"); b->callback(setlevel,(void*)3); b = new Fl_Button(230,50,30,30,"4"); b->callback(setlevel,(void*)4); b = new Fl_Button(260,50,30,30,"5"); b->callback(setlevel,(void*)5); b = new Fl_Button(290,50,30,30,"6"); b->callback(setlevel,(void*)6); b = new Fl_Button(320,50,30,30,"7"); b->callback(setlevel,(void*)7); b = new Fl_Button(350,50,30,30,"8"); b->callback(setlevel,(void*)8); g->end(); b = new Fl_Button(400,50,100,30,"New Fractal"); b->callback(handlemenu,(void*)MENU_RAND); b = new Fl_Button( 10,10,100,30,"Mountain"); b->callback(choosefract,(void*)MOUNTAIN); b = new Fl_Button(110,10,100,30,"Tree"); b->callback(choosefract,(void*)TREE); b = new Fl_Button(210,10,100,30,"Island"); b->callback(choosefract,(void*)ISLAND); b = new Fl_Button(400,10,100,30,"Quit"); b->callback(handlemenu,(void*)MENU_QUIT); window.show(argc,argv); // glut will die unless parent window visible window.begin(); // this will cause Glut window to be a child glutInitWindowSize(512, 512); glutInitWindowPosition(10,90); // place it inside parent window glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE); glutCreateWindow("Fractal Planet?"); window.end(); window.resizable(glut_window); agvInit(1); /* 1 cause we don't have our own idle */ glutReshapeFunc(reshape); glutDisplayFunc(display); glutVisibilityFunc(visible); glutMenuStateFunc(menuuse); NewFractals(); agvMakeAxesList(AXES); myGLInit(); MenuInit(); glutMainLoop(); // you could use Fl::run() instead return 0; } #endif fltk-1.4.3/test/label.cxx0000644000175000017500000001454715004135251015402 0ustar albrechtalbrecht// // Label test program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include "pixmaps/blast.xpm" Fl_Toggle_Button *imageb, *imageovertextb, *imagenexttotextb, *imagebackdropb; Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*clipb,*wrapb; Fl_Box *text; Fl_Input *input; Fl_Hor_Value_Slider *fonts; Fl_Hor_Value_Slider *sizes; Fl_Hor_Value_Slider *h_margin, *v_margin, *img_spacing; Fl_Double_Window *window; Fl_Pixmap *img; void button_cb(Fl_Widget *,void *) { int i = 0; if (leftb->value()) i |= FL_ALIGN_LEFT; if (rightb->value()) i |= FL_ALIGN_RIGHT; if (topb->value()) i |= FL_ALIGN_TOP; if (bottomb->value()) i |= FL_ALIGN_BOTTOM; if (insideb->value()) i |= FL_ALIGN_INSIDE; if (clipb->value()) i |= FL_ALIGN_CLIP; if (wrapb->value()) i |= FL_ALIGN_WRAP; if (imageovertextb->value()) i |= FL_ALIGN_TEXT_OVER_IMAGE; if (imagenexttotextb->value()) i |= FL_ALIGN_IMAGE_NEXT_TO_TEXT; if (imagebackdropb->value()) i |= FL_ALIGN_IMAGE_BACKDROP; text->align(i); window->redraw(); } void image_cb(Fl_Widget *,void *) { if (imageb->value()) text->image(img); else text->image(0); window->redraw(); } void font_cb(Fl_Widget *,void *) { text->labelfont(int(fonts->value())); window->redraw(); } void h_margin_cb(Fl_Widget *,void *) { text->horizontal_label_margin(int(h_margin->value())); window->redraw(); } void v_margin_cb(Fl_Widget *,void *) { text->vertical_label_margin(int(v_margin->value())); window->redraw(); } void spacing_cb(Fl_Widget *,void *) { text->label_image_spacing(int(img_spacing->value())); window->redraw(); } void size_cb(Fl_Widget *,void *) { text->labelsize(int(sizes->value())); window->redraw(); } void input_cb(Fl_Widget *,void *) { text->label(input->value()); window->redraw(); } void normal_cb(Fl_Widget *,void *) { text->labeltype(FL_NORMAL_LABEL); window->redraw(); } void symbol_cb(Fl_Widget *,void *) { text->labeltype(FL_SYMBOL_LABEL); if (input->value()[0] != '@') { input->static_value("@->"); text->label("@->"); } window->redraw(); } void shadow_cb(Fl_Widget *,void *) { text->labeltype(FL_SHADOW_LABEL); window->redraw(); } void embossed_cb(Fl_Widget *,void *) { text->labeltype(FL_EMBOSSED_LABEL); window->redraw(); } void engraved_cb(Fl_Widget *,void *) { text->labeltype(FL_ENGRAVED_LABEL); window->redraw(); } Fl_Menu_Item choices[] = { {"FL_NORMAL_LABEL",0,normal_cb}, {"FL_SYMBOL_LABEL",0,symbol_cb}, {"FL_SHADOW_LABEL",0,shadow_cb}, {"FL_ENGRAVED_LABEL",0,engraved_cb}, {"FL_EMBOSSED_LABEL",0,embossed_cb}, {0}}; int main(int argc, char **argv) { img = new Fl_Pixmap(blast_xpm); window = new Fl_Double_Window(440,495); input = new Fl_Input(70,435,350,25,"Label:"); input->static_value("The quick brown fox jumped over the lazy dog."); input->when(FL_WHEN_CHANGED); input->callback(input_cb); input->tooltip("label text"); sizes= new Fl_Hor_Value_Slider(70,350,350,25,"Size:"); sizes->align(FL_ALIGN_LEFT); sizes->bounds(1,64); sizes->step(1); sizes->value(14); sizes->callback(size_cb); fonts=new Fl_Hor_Value_Slider(70,325,350,25,"Font:"); fonts->align(FL_ALIGN_LEFT); fonts->bounds(0,15); fonts->step(1); fonts->value(0); fonts->callback(font_cb); Fl_Box *margin = new Fl_Box(0, 380, 70, 25, "Margins"); margin->box(FL_FLAT_BOX); margin->align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE); h_margin = new Fl_Hor_Value_Slider(70+50,380,125,25,"Hor:"); h_margin->align(FL_ALIGN_LEFT); h_margin->bounds(-25,25); h_margin->step(1); h_margin->value(0); h_margin->callback(h_margin_cb); v_margin = new Fl_Hor_Value_Slider(70+175+50,380,125,25,"Vert:"); v_margin->align(FL_ALIGN_LEFT); v_margin->bounds(-25,25); v_margin->step(1); v_margin->value(0); v_margin->callback(v_margin_cb); img_spacing = new Fl_Hor_Value_Slider(70+50,405,125,25,"Image:"); img_spacing->align(FL_ALIGN_LEFT); img_spacing->bounds(0,50); img_spacing->step(1); img_spacing->value(0); img_spacing->callback(spacing_cb); Fl_Group *g = new Fl_Group(70,275,350,50); imageb = new Fl_Toggle_Button(70,275,50,25,"image"); imageb->callback(image_cb); imageb->tooltip("show image"); imageovertextb = new Fl_Toggle_Button(120,275,50,25,"T o I"); imageovertextb->callback(button_cb); imageovertextb->tooltip("FL_ALIGN_TEXT_OVER_IMAGE"); imagenexttotextb = new Fl_Toggle_Button(170,275,50,25,"I | T"); imagenexttotextb->callback(button_cb); imagenexttotextb->tooltip("FL_ALIGN_IMAGE_NEXT_TO_TEXT"); imagebackdropb = new Fl_Toggle_Button(220,275,50,25,"back"); imagebackdropb->callback(button_cb); imagebackdropb->tooltip("FL_ALIGN_IMAGE_BACKDROP"); leftb = new Fl_Toggle_Button(70,300,50,25,"left"); leftb->callback(button_cb); leftb->tooltip("FL_ALIGN_LEFT"); rightb = new Fl_Toggle_Button(120,300,50,25,"right"); rightb->callback(button_cb); rightb->tooltip("FL_ALIGN_RIGHT"); topb = new Fl_Toggle_Button(170,300,50,25,"top"); topb->callback(button_cb); topb->tooltip("FL_ALIGN_TOP"); bottomb = new Fl_Toggle_Button(220,300,50,25,"bottom"); bottomb->callback(button_cb); bottomb->tooltip("FL_ALIGN_BOTTOM"); insideb = new Fl_Toggle_Button(270,300,50,25,"inside"); insideb->callback(button_cb); insideb->tooltip("FL_ALIGN_INSIDE"); wrapb = new Fl_Toggle_Button(320,300,50,25,"wrap"); wrapb->callback(button_cb); wrapb->tooltip("FL_ALIGN_WRAP"); clipb = new Fl_Toggle_Button(370,300,50,25,"clip"); clipb->callback(button_cb); clipb->tooltip("FL_ALIGN_CLIP"); g->resizable(insideb); g->end(); Fl_Choice *c = new Fl_Choice(70,250,200,25); c->menu(choices); text = new Fl_Box(FL_FRAME_BOX,120,75,200,100,input->value()); text->align(FL_ALIGN_CENTER); window->resizable(text); window->end(); window->show(argc,argv); return Fl::run(); } fltk-1.4.3/test/unittest_unicode.cxx0000644000175000017500000001025515004135251017700 0ustar albrechtalbrecht// // Unit tests for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // FLTK DEVS: utf-8 encoding must be enabled to edit this file. #include "unittests.h" #include #include #include #include #include #include #include static const char *utf8_box_test = "╳╳ ██ ▏▏┏━━┓ ╔══╗ ╔═╦═╗ ██████\n" "╳╳ ██ ▏▏┃ ┃ ║ ║ ╠═╬═╣ ██ ██\n" "╳╳ ██ ▏▏┗━━┛ ╚══╝ ╚═╩═╝ ██████\n" "\n" "underbar: ______\n" " overbar: ‾‾‾‾‾‾\n" "\n" "underbar/overbar alternate:\n" "\n" "___‾‾‾___‾‾‾___‾‾‾___‾‾‾___\n" "‾‾‾___‾‾‾___‾‾‾___‾‾‾___‾‾‾\n"; static const char *helptext = "In this test, ideally the box's lines should all be touching " "without white space between. Underbar and overbars should both " "be visible and not touching. All the above should be unaffected " "by different font sizes and font settings."; class Ut_Unicode_Box_Test : public Fl_Group { Fl_Text_Buffer *textbuffer; Fl_Text_Display *textdisplay; Fl_Multiline_Input *multilineinput; Fl_Choice *font_choice; Fl_Hor_Value_Slider *fontsize_slider; // Font choice callback void font_choice_cb2() { switch ( font_choice->value() ) { case 0: textdisplay->textfont(FL_COURIER); break; case 1: textdisplay->textfont(FL_SCREEN); break; } parent()->redraw(); } static void foant_choice_cb(Fl_Widget*, void *userdata) { Ut_Unicode_Box_Test *o = (Ut_Unicode_Box_Test*)userdata; o->font_choice_cb2(); } // Slider callback - apply new font size to widgets void font_size_slider_cb2() { // Get font size from slider value, apply to widgets int fontsize = (int)fontsize_slider->value(); textdisplay->textsize(fontsize); multilineinput->textsize(fontsize); multilineinput->insert_position(0); // keep scrolled to top parent()->redraw(); } static void font_size_slider_cb(Fl_Widget*, void *userdata) { Ut_Unicode_Box_Test *o = (Ut_Unicode_Box_Test*)userdata; o->font_size_slider_cb2(); } public: static Fl_Widget *create() { return new Ut_Unicode_Box_Test(UT_TESTAREA_X, UT_TESTAREA_Y, UT_TESTAREA_W, UT_TESTAREA_H); } Ut_Unicode_Box_Test(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { // Fl_Text_Display textbuffer = new Fl_Text_Buffer(); textbuffer->text(utf8_box_test); textdisplay = new Fl_Text_Display(x+5, y+20, 250, 250, "Fl_Text_Display"); textdisplay->textfont(FL_COURIER); textdisplay->buffer(textbuffer); textdisplay->tooltip(helptext); // Fl_Multiline_Input multilineinput = new Fl_Multiline_Input(x+250+15, y+20, 250, 250, "Fl_Multiline_Input"); multilineinput->align(FL_ALIGN_CENTER|FL_ALIGN_TOP); multilineinput->textfont(FL_COURIER); multilineinput->value(utf8_box_test); multilineinput->tooltip(helptext); // Font choice // Fonts must be fixed width to work correctly.. font_choice = new Fl_Choice(x+150, y+h-80, 200, 25, "Font face"); font_choice->add("FL_COURIER"); font_choice->add("FL_SCREEN"); font_choice->value(0); font_choice->callback(foant_choice_cb, (Fl_Widget*)this); // Font size slider fontsize_slider = new Fl_Hor_Value_Slider(x+150, y+h-50, 200, 25, "Font size"); fontsize_slider->align(FL_ALIGN_LEFT); fontsize_slider->range(1.0, 50.0); fontsize_slider->step(1.0); fontsize_slider->value(14.0); fontsize_slider->callback(font_size_slider_cb, (Fl_Widget*)this); end(); } }; UnitTest unicode_font_test(UT_TEST_UNICODE, "Unicode Boxes", Ut_Unicode_Box_Test::create); fltk-1.4.3/test/resize-example5b.cxx0000644000175000017500000000673415004135251017503 0ustar albrechtalbrecht// // Resize example for use in the Fast Light Tool Kit (FLTK) documentation. // // See Article #415: How does resizing work? // https://www.fltk.org/articles.php?L415 // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "resize-arrows.h" #include // window, simplex and arrow dimensions int TLx = 35, TRx = 320, TLw = 260, Ww = 620; int TLy = 35, LGy = 125, TLh = 90, LGh = 70, LAh = 35, Wh = 200; Fl_Double_Window *window = 0; class Simplex : public Fl_Group { public: Simplex(int X, int Y, int W, int H, const char *T = 0); Fl_Box *m_boxA, *m_boxB, *m_boxC, *m_boxI; Fl_Group *m_group, *m_groupL, *m_groupR; }; Simplex::Simplex(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { this->box(FL_UP_BOX); m_group = new Fl_Group(X + 10, Y + 10, 240, 70); m_group->box(FL_UP_BOX); m_groupL = new Fl_Group(X + 10, Y + 15, 145, 35, "AB group"); m_groupL->align(FL_ALIGN_BOTTOM_LEFT); m_groupL->box(FL_UP_BOX); m_groupL->color(FL_RED); m_groupL->labelcolor(FL_RED); m_boxA = new Fl_Box(X + 20, Y + 20, 80, 25, "A"); m_boxA->box(FL_UP_BOX); m_boxA->color(FL_YELLOW); m_boxB = new Fl_Box(X + 110, Y + 20, 40, 25, "B"); m_boxB->box(FL_UP_BOX); m_groupL->resizable(m_boxA); m_groupL->end(); m_groupR = new Fl_Group(X + 155, Y + 15, 95, 35, "C group"); m_groupR->align(FL_ALIGN_BOTTOM_RIGHT); m_groupR->box(FL_UP_BOX); m_groupR->color(FL_BLUE); m_groupR->labelcolor(FL_BLUE); m_boxC = new Fl_Box(X + 160, Y + 20, 80, 25, "C"); m_boxC->box(FL_UP_BOX); m_boxC->color(FL_YELLOW); m_groupR->resizable(m_boxC); m_groupR->end(); int d = 20; m_boxI = new Fl_Box(X + 155 - d, Y + 55, 2 * d, 10); m_boxI->box(FL_UP_BOX); m_boxI->color(FL_YELLOW); m_group->resizable(m_boxI); m_group->end(); this->resizable(m_group); this->end(); } class Resizables : public Fl_Group { public: Resizables(int X, int Y, int W, int H, const char *T = 0); Simplex *TL, *TR; // top left, top right Harrow *LA, *RA; // left arrow, right arrow }; Resizables::Resizables(int X, int Y, int W, int H, const char *T) : Fl_Group(X, Y, W, H, T) { TL = new Simplex(X + TLx, Y + TLy, TLw, TLh, "Original"); TL->align(FL_ALIGN_TOP_LEFT); TR = new Simplex(X + TRx, Y + TLy, TLw, TLh, "Horizontally Resized"); TR->align(FL_ALIGN_TOP_LEFT); Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); LG->box(FL_NO_BOX); LG->color(FL_WHITE); LA = new Harrow(TL->m_boxI->x(), LG->y(), TL->m_boxI->w(), LAh, "Initial\nwidth"); LG->resizable(LA); LG->end(); Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); RG->box(FL_NO_BOX); RG->color(FL_WHITE); RA = new Harrow(TR->m_boxI->x(), RG->y(), TR->m_boxI->w(), LAh, "Resized\nwidth"); RG->resizable(RA); RG->end(); this->resizable(TR); this->end(); } int main(int argc, char **argv) { window = new Fl_Double_Window(Ww, Wh, "resize-example5b"); window->color(FL_WHITE); Resizables *resizables = new Resizables(0, 0, Ww, Wh); window->end(); window->resizable(resizables); window->size_range(Ww, Wh); window->show(argc, argv); window->size(Ww + 90, Wh); return Fl::run(); } fltk-1.4.3/test/threads.cxx0000644000175000017500000001051215004135251015741 0ustar albrechtalbrecht// // Threading example program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if defined(HAVE_PTHREAD) || defined(_WIN32) # include # include # include # include # include # include "threads.h" # include # include Fl_Thread prime_thread; Fl_Browser *browser1, *browser2; Fl_Value_Output *value1, *value2; int start2 = 3; void magic_number_cb(void *p) { Fl_Value_Output *w = (Fl_Value_Output*)p; w->labelcolor(FL_RED); w->redraw_label(); } extern "C" void* prime_func(void* p) { Fl_Browser* browser = (Fl_Browser*) p; Fl_Value_Output *value; int n; int step; char proud = 0; if (browser == browser2) { n = start2; start2 += 2; step = 12; value = value2; } else { n = 3; step = 2; value = value1; } // very simple prime number calculator ! // // The return at the end of this function can never be reached and thus // will generate a warning with some compilers, however we need to have // a return statement or other compilers will complain there is no return // statement. To avoid warnings on all compilers, we fool the smart ones // into beleiving that there is a chance that we reach the end by testing // n>=0, knowing that logically, n will never be negative in this context. if (n>=0) for (;;) { int pp; int hn = (int)sqrt((double)n); for (pp=3; pp<=hn; pp+=2) if ( n%pp == 0 ) break; if (pp >= hn) { char s[128]; snprintf(s, 128, "%d", n); // Obtain a lock before we access the browser widget... Fl::lock(); browser->add(s); browser->bottomline(browser->size()); if (n > value->value()) value->value(n); n += step; // Release the lock... Fl::unlock(); // Send a message to the main thread, at which point it will // process any pending redraws for our browser widget. The // message we pass here isn't used for anything, so we could also // just pass NULL. Fl::awake(p); if (n>10000 && !proud) { proud = 1; Fl::awake(magic_number_cb, value); } } else { // This should not be necessary since "n" and "step" are local variables, // however it appears that at least MacOS X has some threading issues // that cause semi-random corruption of the (stack) variables. Fl::lock(); n += step; Fl::unlock(); } } return 0L; } int main(int argc, char **argv) { Fl_Double_Window* w = new Fl_Double_Window(200, 200, "Single Thread"); browser1 = new Fl_Browser(0, 0, 200, 175); w->resizable(browser1); value1 = new Fl_Value_Output(100, 175, 200, 25, "Max Prime:"); w->end(); w->show(argc, argv); w = new Fl_Double_Window(200, 200, "Six Threads"); browser2 = new Fl_Browser(0, 0, 200, 175); w->resizable(browser2); value2 = new Fl_Value_Output(100, 175, 200, 25, "Max Prime:"); w->end(); w->show(); browser1->add("Prime numbers:"); browser2->add("Prime numbers:"); // Enable multi-thread support by locking from the main // thread. Fl::wait() and Fl::run() call Fl::unlock() and // Fl::lock() as needed to release control to the child threads // when it is safe to do so... Fl::lock(); // Start threads... // One thread displaying in one browser fl_create_thread(prime_thread, prime_func, browser1); // Several threads displaying in another browser fl_create_thread(prime_thread, prime_func, browser2); fl_create_thread(prime_thread, prime_func, browser2); fl_create_thread(prime_thread, prime_func, browser2); fl_create_thread(prime_thread, prime_func, browser2); fl_create_thread(prime_thread, prime_func, browser2); fl_create_thread(prime_thread, prime_func, browser2); Fl::run(); return 0; } #else # include int main() { fl_alert("Sorry, threading not supported on this platform!"); } #endif // HAVE_PTHREAD || _WIN32 fltk-1.4.3/test/grid_alignment.cxx0000644000175000017500000001342015004135251017273 0ustar albrechtalbrecht// // Fl_Grid demo program for the Fast Light Tool Kit (FLTK). // // Copyright 2021 by Albrecht Schlosser // Copyright 2022-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // This program tests several different alignment features of Fl_Grid. // #include #include #include #include #include #include // Test function to change the layout (executed by timer callback) #define TEST_RELAYOUT (0) #define TEST_REMOVE_NOTIFY (0) #if (TEST_RELAYOUT) void relayout_cb(void *v) { Fl_Grid *grid = (Fl_Grid *)v; grid->layout(5, 5, 8, 4); grid->margin(10, 20, 30, 40); grid->layout(); grid->redraw(); } #endif #if TEST_REMOVE_NOTIFY void remove_cb(void *v) { static int n = 10; n--; Fl_Grid *grid = (Fl_Grid *)v; #if (0) // test 1: remove() the widget -- leaks memory (!) grid->remove(n); #else // test 2: delete the widget -- no leak delete grid->child(0); #endif if (n > 0) Fl::repeat_timeout(0.3, remove_cb, v); } #endif int main(int argc, char **argv) { Fl_Grid::Cell *c; Fl_Box *b; Fl_Double_Window *win = new Fl_Double_Window(440, 350, "Fl_Grid Alignment Test"); Fl_Grid *grid = new Fl_Grid(10, 10, 420, 330); grid->layout(7, 7, 8, 4); // cols, rows, margin, gap grid->box(FL_FLAT_BOX); grid->color(FL_WHITE); // add boxes (top and bottom rows) for (int col = 0; col < 7; col++) { grid->col_width(col, 50); b = new Fl_Box(0, 0, 20, 20); // variable size if (col == 5) { b->size(4, 20); // reduce width grid->col_width(col, 4); // new min. width grid->col_weight(col, 0); // no hor. resizing } b->box(FL_FLAT_BOX); b->color(FL_BLUE); grid->widget(b, 0, col); if (col == 5) b = new Fl_Box(0, 0, 4, 20); // variable size else b = new Fl_Box(0, 0, 20, 20); // variable size b->box(FL_FLAT_BOX); b->color(FL_RED); grid->widget(b, 6, col); } // add boxes (left and right columns) grid->row_height(0, 40); grid->row_height(6, 40); for (int row = 1; row < 6; row++) { grid->row_height(row, 40); b = new Fl_Box(0, 0, 20, 20); // fixed size, see alignment below b->box(FL_FLAT_BOX); b->color(FL_RED); switch(row) { case 1: grid->widget(b, row, 0, FL_GRID_FILL); break; case 2: grid->widget(b, row, 0, FL_ALIGN_CENTER); break; case 3: grid->widget(b, row, 0, FL_ALIGN_BOTTOM_RIGHT); break; case 4: grid->widget(b, row, 0, FL_ALIGN_BOTTOM_RIGHT); break; case 5: grid->widget(b, row, 0, FL_ALIGN_TOP_RIGHT); break; default: break; } b = new Fl_Box(0, 0, 20, 20); b->box(FL_FLAT_BOX); b->color(FL_GREEN); c = grid->widget(b, row, 6, FL_ALIGN_CENTER); } // two more boxes to demonstrate widget alignment inside the cell for (int row = 4; row < 6; row++) { b = new Fl_Box(0, 0, 20, 20); // fixed size, see alignment below b->box(FL_FLAT_BOX); b->color(FL_MAGENTA); c = grid->widget(b, row, 1); // default alignment: FL_GRID_FILL if (row == 4) c->align(FL_ALIGN_BOTTOM_LEFT); // alignment uses widget size if (row == 5) c->align(FL_ALIGN_TOP_LEFT); // alignment uses widget size } // one vertical box (line), spanning 5 rows b = new Fl_Box(0, 0, 2, 2); // extends vertically b->box(FL_FLAT_BOX); b->color(FL_BLACK); grid->widget(b, 1, 5, 5, 1, FL_GRID_VERTICAL | FL_ALIGN_RIGHT); // add a textbox with label or title, spanning 5 cells, centered b = new Fl_Box(0, 0, 1, 1); // variable size b->label("Hello, Fl_Grid !"); b->labelfont(FL_BOLD + FL_ITALIC); b->labelsize(30); b->labeltype(FL_SHADOW_LABEL); grid->widget(b, 1, 1, 1, 5); // rowspan = 1, colspan = 5 // add a footer textbox, spanning 3 cells, right aligned b = new Fl_Box(0, 0, 1, 10); // variable size b->label("FLTK/test/grid_alignment.cxx"); b->labelfont(FL_COURIER); b->labelsize(11); b->align(FL_ALIGN_INSIDE | FL_ALIGN_RIGHT); grid->widget(b, 5, 2, 1, 3, FL_GRID_HORIZONTAL | FL_ALIGN_BOTTOM); // input widgets with fixed size and alignment inside the cell Fl_Input *i1 = new Fl_Input(0, 0, 100, 30, "Username:"); c = grid->widget(i1, 2, 3, 1, 2); // widget, col, row, colspan, rowspan c->align(FL_GRID_HORIZONTAL); // widget alignment in cell Fl_Input *i2 = new Fl_Input(0, 0, 100, 30, "Password:"); c = grid->widget(i2, 3, 3, 1, 2); // widget, col, row, colspan, rowspan c->align(FL_GRID_HORIZONTAL); // widget alignment in cell // the login button spans 2 columns Fl_Button *bt = new Fl_Button(0, 0, 10, 30, "Login"); grid->widget(bt, 4, 3, 1, 2, FL_GRID_HORIZONTAL); // widget, col, row, colspan, rowspan, alignment grid->row_weight(1, 90); grid->row_weight(2, 0); grid->row_weight(3, 0); grid->row_weight(4, 0); grid->col_weight(0, 30); grid->col_weight(4, 90); grid->row_gap(5, 12); grid->end(); grid->layout(); grid->debug(0); // grid->show_grid(1); // enable to display grid helper lines win->end(); win->resizable(grid); win->size_range(440, 350); win->show(argc, argv); #if (TEST_RELAYOUT) Fl::add_timeout(5.0, relayout_cb, grid); #endif #if (TEST_REMOVE_NOTIFY) Fl::add_timeout(3.0, remove_cb, grid); #endif // return Fl::run(); int ret = Fl::run(); grid->clear_layout(); delete win; return ret; } fltk-1.4.3/test/checkers.cxx0000644000175000017500000011230115004135251016075 0ustar albrechtalbrecht// // Checkers game for the Fast Light Tool Kit (FLTK). // // Hours of fun: the FLTK checkers game! // Based on a very old algorithm, but it still works! // // Copyright 1998-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // const char* copyright = "Checkers game\n" "Copyright (C) 1997-2010 Bill Spitzak spitzak@@d2.com\n" "Original Pascal code:\n" "Copyright 1978, Oregon Minicomputer Software, Inc.\n" "2340 SW Canyon Road, Portland, Oregon 97201\n" "Written by Steve Poulsen 18-Jan-79\n" "\n" "This program is free software; you can redistribute it and/or modify " "it under the terms of the GNU General Public License as published by " "the Free Software Foundation; either version 2 of the License, or " "(at your option) any later version.\n" "\n" "This program is distributed in the hope that it will be useful, " "but WITHOUT ANY WARRANTY; without even the implied warranty of " "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU Library General Public " "License along with this library; if not, write to the Free Software " "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 " "USA."; // Define FLTK to get the fltk interface // Define VT100 to get the VT100 interface // Define both to get a program that takes a -t switch #define FLTK //#define VT100 #undef check #include #include #include #include #include #ifdef VT100 #include // toupper #endif //////////////////////////////////////////////////////////////// // The algorithim: int maxevaluate=2500; // max number of moves to examine on a turn int maxnodes = 2500; // maximum number of nodes in search tree int maxply = 20; // maximum depth to look ahead char forcejumps = 1; // is forced jumps rule in effect? // scoring parameters: (all divided by 5 from original code) // some signs seem to be backwards, marked them with (-) in comment const int spiece = 800; // value of a piece const int sking = 1200; // value of a king const int sadvan = 160; // value of mypieces/theirpieces-1 // const int smobil = ? // moves *enemy* can make w/o being jumped const int sallpin = 80; // mobil == 0 const int sdeny = 10; // moves enemy can make that will be jumped const int spin = 32; // enemy pieces that have no move except jumped const int sthreat = -10; // enemy pieces we can jump if not moved (-) const int sgrad = 1; // score of piece positions const int sback = 10; // back row occupied so enemy can't make king const int smoc2 = 200; // more mobility, more center const int smoc3 = -8; // less mobility, less center const int smoc4 = -80; // more mobility, less center const int smode2 = -14; // less mobility, less denied const int smode3 = -40; // more mobility, more denied (-) const int sdemmo = -20; // more denied, more moves (-) const int scent = 10; // pieces in center const int skcent = 100; // kings in center const int depthpenalty=4; // guess const int noise=2; // values less or eq to this apart are eq // const int sattackking = 4; // not used // const int sattackpiece = 3; struct node { node *father; node *son; // best son node *brother; // next brother short int value; // value of this board position to player making move unsigned char from,to; // the move to reach this board long int jump; // bit map of locations jumped unsigned char mobil; unsigned char deny; unsigned char pin; unsigned char threat; short int gradient; unsigned who:1; // 0 = black's move, 1 = white's move unsigned king:1; // 1 = move causes piece to be kinged unsigned back:1; unsigned moc2:1; unsigned moc3:1; unsigned moc4:1; unsigned mode2:1; unsigned mode3:1; unsigned demmo:1; }; int nodes; // count of nodes /* Board positions: Border positions: WHITE 00 01 02 03 04 05 06 07 08 04 XX XX XX XX 09 10 11 12 XX XX XX XX 13 14 15 16 17 13 XX XX XX XX 18 19 20 21 XX XX XX XX 22 23 24 25 26 22 XX XX XX XX 27 28 29 30 XX XX XX XX 31 32 33 34 36 31 XX XX XX XX 36 37 38 39 XX XX XX XX 40 BLACK 40 41 42 43 44 */ typedef char piece; // Piece values so that BLACK and WHITE are bit flags: #define EMPTY 0 #define BLACK 1 #define WHITE 2 #define KING 4 #define BLACKKING 5 #define WHITEKING 6 #define BLUE 8 const piece flip[9] = { EMPTY, WHITE, BLACK, 0, 0, WHITEKING, BLACKKING, 0, BLUE}; const int offset[9][4] = { // legal move directions {0,0,0,0}, {-5,-4,0,0}, {4,5,0,0}, {0,0,0,0}, {0,0,0,0}, {4,5,-4,-5}, {4,5,-4,-5}, {0,0,0,0}, {0,0,0,0} }; piece b[45]; // current board position being considered int evaluated; // number of moves evaluated this turn char centralsquares[45]; char is_protected[45]; piece flipboard[45]; // swapped if enemy is black piece *tb; // pointer to real or swapped board #define FRIEND BLACK #define FRIENDKING BLACKKING #define ENEMY WHITE #define ENEMYKING WHITEKING char check(int target,int direction) { // see if enemy at target can be jumped from direction by our piece int dst = target-direction; if (tb[dst]) return(0); int src = target+direction; if (tb[src] == FRIENDKING); else if (direction < 0 || tb[src] != FRIEND) return(0); piece aa = tb[target]; piece bb = tb[src]; tb[target] = EMPTY; tb[src] = EMPTY; int safe = ( (tb[src-4]&FRIEND && tb[src-8]&ENEMY) || (tb[src-5]&FRIEND && tb[src-10]&ENEMY) || (tb[dst-4]&ENEMY && !tb[dst+4]) || (tb[dst-5]&ENEMY && !tb[dst+5]) || (tb[src+4]&FRIEND && tb[src+8]==ENEMYKING) || (tb[src+5]&FRIEND && tb[src+10]==ENEMYKING) || (tb[dst+4]==ENEMYKING && !tb[dst-4]) || (tb[dst+5]==ENEMYKING && !tb[dst-5])); tb[target] = aa; tb[src] = bb; return(safe); } int deniedmoves,undeniedmoves; void analyzemove(int direction,int src) { int target = src+direction; if (!tb[target]) { if (!tb[target+direction]) is_protected[target] = 1; piece a = tb[src]; tb[src] = EMPTY; if (check(target,4) || check(target,5) || check(target,-4) || check(target,-5) || (tb[src+4]&ENEMY && check(src+4,4)) || (tb[src+5]&ENEMY && check(src+5,5)) || (tb[src-4]&ENEMY && check(src-4,-4)) || (tb[src-5]&ENEMY && check(src-5,-5))) deniedmoves++; else undeniedmoves++; tb[src] = a; } } void evaluateboard(node *n,int print) { if (!n->who) tb = b; // move was black's else { for (int i=0; i<45; i++) flipboard[44-i] = flip[(int)b[i]]; tb = flipboard; } memset(is_protected,0,sizeof(is_protected)); int friendpieces = 0; int enemypieces = 0; int friendkings = 0; int enemykings = 0; int friendkcent = 0; int friendcent = 0; int enemykcent = 0; int enemycent = 0; n->mobil = n->deny = n->pin = n->threat = 0; int i; for (i=5; i<40; i++) switch(tb[i]) { case ENEMYKING: enemykings++; enemykcent += centralsquares[i]; deniedmoves = 0; undeniedmoves = 0; if (i>8) { analyzemove(-4,i); analyzemove(-5,i); } goto J1; case ENEMY: deniedmoves = 0; undeniedmoves = 0; J1: enemypieces++; enemycent += centralsquares[i]; if (i<36) { analyzemove(4,i); analyzemove(5,i); } if (deniedmoves && !undeniedmoves) n->pin++; n->deny += deniedmoves; n->mobil += undeniedmoves; break; case FRIENDKING: friendkings++; friendkcent += centralsquares[i]; if (tb[i+4]&ENEMY && !tb[i+8] && !(tb[i+4]==ENEMYKING && !tb[i-4])) n->threat++; if (tb[i+5]&ENEMY && !tb[i+10] && !(tb[i+5]==ENEMYKING && !tb[i-5])) n->threat++; case FRIEND: friendpieces++; friendcent += centralsquares[i]; if (tb[i-4]&ENEMY && !tb[i-8] && tb[i+4]) n->threat++; if (tb[i-5]&ENEMY && !tb[i-10] && tb[i+5]) n->threat++; break; } int gradient[40]; for (i=4; i<9; i++) gradient[i] = tb[i] ? 0 : 32; int total = 0; for (i=9; i<40; i++) { int x = (gradient[i-4]+gradient[i-5])/2; if (tb[i]==FRIEND) total += x; gradient[i] = (tb[i]&FRIEND || (!tb[i] && !is_protected[i])) ? x : 0; } n->gradient = total; n->back = tb[39]==FRIEND && tb[37]==FRIEND && !enemykings; node* f = n->father; n->moc2 = f->mobil>n->mobil && friendcent>enemycent; n->moc3 = f->mobil<=n->mobil && friendcentmoc4 = f->mobil>n->mobil && friendcentmode2 = f->mobil<=n->mobil && n->denydeny; n->mode3 = f->mobil>n->mobil && n->deny>f->deny; n->demmo = n->deny>f->deny && f->deny+f->mobil>n->deny+n->mobil; total = spiece * (friendpieces - enemypieces) + (sking-spiece) * (friendkings - enemykings) + // mobil? sdeny * (n->deny - f->deny) + spin * (n->pin - f->pin) + sthreat * (n->threat - f->threat) + sgrad * (n->gradient - f->gradient) + sback * (n->back - f->back) + smoc2 * (n->moc2 - f->moc2) + smoc3 * (n->moc3 - f->moc3) + smoc4 * (n->moc4 - f->moc4) + smode2 * (n->mode2 - f->mode2) + smode3 * (n->mode3 - f->mode3) + sdemmo * (n->demmo - f->demmo) + scent * (friendcent - enemycent) + (skcent-scent) * (friendkcent - enemykcent); if (!n->mobil) total += sallpin; if (!enemypieces) total = 30000; else if (friendpieces > enemypieces) total += (sadvan*friendpieces)/enemypieces-sadvan; else total -= (sadvan*enemypieces)/friendpieces-sadvan; if (print) { printf("\tParent\tNew\tScore\n"); printf("pieces\t%d\t%d\t%d\n",enemypieces,friendpieces, spiece*(friendpieces-enemypieces)); printf("kings\t%d\t%d\t%d\n",enemykings,friendkings, (sking-spiece)*(friendkings-enemykings)); printf("mobil\t%d\t%d\n",f->mobil,n->mobil); printf("deny\t%d\t%d\t%d\n",f->deny,n->deny,sdeny*(n->deny-f->deny)); printf("pin\t%d\t%d\t%d\n",f->pin,n->pin,spin*(n->pin-f->pin)); printf("threat\t%d\t%d\t%d\n",f->threat,n->threat,sthreat*(n->threat-f->threat)); printf("grad\t%d\t%d\t%d\n",f->gradient,n->gradient,sgrad*(n->gradient-f->gradient)); printf("back\t%d\t%d\t%d\n",f->back,n->back,sback*(n->back-f->back)); printf("moc2\t%d\t%d\t%d\n",f->moc2,n->moc2,smoc2*(n->moc2-f->moc2)); printf("moc3\t%d\t%d\t%d\n",f->moc3,n->moc3,smoc3*(n->moc3-f->moc3)); printf("moc4\t%d\t%d\t%d\n",f->moc4,n->moc4,smoc4*(n->moc4-f->moc4)); printf("mode2\t%d\t%d\t%d\n",f->mode2,n->mode2,smode2*(n->mode2-f->mode2)); printf("mode3\t%d\t%d\t%d\n",f->mode3,n->mode3,smode3*(n->mode3-f->mode3)); printf("demmo\t%d\t%d\t%d\n",f->demmo,n->demmo,sdemmo*(n->demmo-f->demmo)); printf("cent\t%d\t%d\t%dn",enemycent,friendcent,scent*(friendcent-enemycent)); printf("kcent\t%d\t%d\t%d\n",enemykcent,friendkcent,skcent*(friendkcent-enemykcent)); printf("total:\t\t\t%d\n",total); } else { n->value = total; evaluated++; } } // end of evaluateboard // --------------------- Tree management ----------------- node *freelist; node *newnode(void) { node *n; if (freelist) { n = freelist; freelist = n->brother; } else n = (node *)malloc(sizeof(node)); memset(n,0,sizeof(node)); nodes++; return(n); } void extract(node *n) { node* i = n->father; if (i) { node* j = i->son; if (j==n) i->son = n->brother; else while (j) { i = j; j = j->brother; if (j==n) {i->brother = n->brother; break;} } } n->brother = 0; } void killnode(node *x) { if (!x) return; node *y; for (y = x; ; y = y->brother) { nodes--; killnode(y->son); y->son = 0; if (!y->brother) break; } y->brother = freelist; freelist = x; } int seed; // current random number void insert(node *n) { int val = n->value; node **pp; for (pp = &(n->father->son); *pp; pp = &((*pp)->brother)) { int val1 = (*pp)->value; if (abs(val-val1) <= noise) { seed = (seed*13077+5051)%0100000; if ((seed & 070) >= 060) break; } else if (val > val1) break; } n->brother = *pp; *pp = n; } // -------------------------------------------------------------- void movepiece(node* f, int i, node* jnode) { static char jumphappened; for (int k=0; k<4; k++) { int direction = offset[(int)b[i]][k]; if (!direction) break; int j = i+direction; if (b[j] == EMPTY) { if (!jnode && (!forcejumps || !f->son || !f->son->jump)) { node* n = newnode(); n->father = f; n->who = !f->who; n->from = i; n->to = j; piece oldpiece = b[i]; b[i] = EMPTY; if (!(oldpiece&KING) && n->who ? (j>=36) : (j<=8)) { n->king = 1; b[j] = oldpiece|KING; } else b[j] = oldpiece; evaluateboard(n,0); insert(n); b[i] = oldpiece; b[j] = EMPTY; } } else if (((b[j]^b[i])&(WHITE|BLACK))==(WHITE|BLACK) && !b[j+direction]) { if (forcejumps && f->son && !f->son->jump) { killnode(f->son); f->son = 0; } int jumploc = j; j += direction; node* n = newnode(); n->father = f; n->who = !f->who; n->from = i; n->to = j; n->jump = (1<<(jumploc-10)); piece oldpiece = b[i]; b[i] = EMPTY; if (!(oldpiece&KING) && n->who ? (j>=36) : (j<=8)) { n->king = 1; b[j] = oldpiece|KING; } else b[j] = oldpiece; if (jnode) { n->from = jnode->from; n->jump |= jnode->jump; n->king |= jnode->king; } piece jumpedpiece = b[jumploc]; b[jumploc] = EMPTY; jumphappened = 0; movepiece(f,j,n); if (forcejumps && jumphappened) killnode(n); else {evaluateboard(n,0); insert(n);} b[i] = oldpiece; b[j] = EMPTY; b[jumploc] = jumpedpiece; jumphappened = 1; } } } void expandnode(node *f) { if (f->son || f->value > 28000) return; // already done piece turn = f->who ? BLACK : WHITE; for (int i=5; i<40; i++) if (b[i]&turn) movepiece(f,i,0); if (f->son) { f->value = -f->son->value; if (f->brother) f->value -= depthpenalty; } else f->value = 30000; } void makemove(node *n) { b[n->to] = b[n->from]; if (n->king) b[n->to] |= KING; b[n->from] = EMPTY; if (n->jump) for(int i=0; i<32; i++) { if (n->jump & (1< maxnodes-(maxply*10) || evaluated > maxevaluate) return(0); expandnode(f); if (!f->son) return(1); piece oldboard[45]; memmove(oldboard,b,sizeof(b)); node* n = f->son; if (!n->jump && n->brother) {if (level<1) return(1); level--;} int i; node* sons[32]; for (i=0; (sons[i++] = n); n = n->brother) {/*empty*/} int ret = 1; for (i=0; ret && (n = sons[i++]);) { makemove(n); ret = fullexpand(n,level); memmove(b,oldboard,sizeof(b)); extract(n); insert(n); } f->value = -f->son->value; return(ret); } int descend(node *f) { static int depth; if (didabort() || nodes > maxnodes || depth >= maxply) return(0); if (f->son) { node* n = f->son; makemove(n); depth++; int ret = descend(n); depth--; extract(n); insert(n); f->value = -f->son->value; return(ret); } else {expandnode(f); return(1);} } char debug; node *calcmove(node *root) { // return best move after root expandnode(root); if (!root->son) return(0); // no move due to loss if (debug) printf("calcmove() initial nodes = %d\n",nodes); evaluated = 0; if (root->son->brother) { int x; for (x = 1; abs(root->value)<28000 && fullexpand(root,x); x++); piece saveboard[45]; memmove(saveboard,b,sizeof(b)); while (abs(root->value)<28000) { x = descend(root); memmove(b,saveboard,sizeof(b)); if (!x) break; } } if (debug) printf(" evaluated %d, nodes = %d\n", evaluated, nodes); return(root->son); } // the actual game state ---------------- node *root,*undoroot; piece jumpboards[24][45]; // saved boards for undoing jumps int nextjump; char user; // 0 = black, 1 = white char playing; char autoplay; void newgame(void) { int n; for (n=0; n<5; n++) b[n] = BLUE; for (n=5; n<18; n++) b[n] = WHITE; for (n=18; n<27; n++) b[n] = EMPTY; for (n=27; n<40; n++) b[n] = BLACK; for (n=40; n<45; n++) b[n] = BLUE; b[13] = b[22] = b[31] = BLUE; centralsquares[15] = centralsquares[16] = centralsquares[19] = centralsquares[20] = centralsquares[24] = centralsquares[25] = centralsquares[28] = centralsquares[29] = 1; // set up initial search tree: nextjump = 0; killnode(undoroot); undoroot = root = newnode(); // make it white's move, so first move is black: root->who = 1; user = 0; playing = 1; } void domove(node* move) { if (move->jump) memmove(jumpboards[nextjump++],b,sizeof(b)); makemove(move); extract(move); killnode(root->son); root->son = move; root = move; if (debug) evaluateboard(move,1); } node* undomove() { node *n = root; if (n == undoroot) return 0; // no more undo possible if (n->jump) memmove(b,jumpboards[--nextjump],sizeof(b)); else { b[n->from] = b[n->to]; if (n->king) b[n->from] &= (WHITE|BLACK); b[n->to] = EMPTY; } root = n->father; killnode(n); root->son = 0; root->value = 0; // prevent it from thinking game is over playing = 1; if (root == undoroot) user = 0; return n; } const char _usermoves[] = "B1D1F1H1A2C2E2G2??B3D3F3H3A4C4E4G4??B5D5F5H5A6C6E6G6??B7D7F7H7A8C8E8G8??"; // #define usermoves(x,y) _usermoves[2*((x)-5)+(y)-1] // Note: the macro above would cause out-of-bounds access to _usermoves[]. // The *workaround* chosen here is to check bounds and return '?' instead. // Note also that this is NOT a proper solution of the underlying problem, // but it removes access to undefined memory. `Address Sanitizer` finds this // issue and terminates the program whereas `valgrind` doesn't find it. // // Test scenario: The issue happens when you try to drag a piece when another // one *must* jump, according to the rules. // // Just in case someone feels inclined to find and fix the real issue: // Example (script from using VT100 mode, which does NOT crash): // Black's move? E6 F5 // Black moves from E6 to F5 (+20). // White moves from D3 to E4 (+14). // Black's move? G6 H5 <-- try this in GUI mode w/o the fix below // Valid moves are: // F5 D3 - Black jumps from F5 to D3, E4 removed (-14). // // Hint for further debugging: enable the printf/fflush statements below and // set a breakpoint inside the `if` condition below in a debugger. Then take // a look at the stack trace when the breakpoint is hit. Good luck! ;-) // Albrecht. int usermoves(int x, int y) { int idx = 2 * (x - 5) + y - 1; if (idx < 0 || idx > (int)sizeof(_usermoves) - 1) { // out of bounds // printf("usermoves(%3d, %3d): index = %3d is out of bounds, returning '?'\n", x, y, idx); // fflush(stdout); return '?'; } return _usermoves[idx]; } #ifdef VT100 void dumpnode(node *n, int help) { int x = n->from; int y = n->to; if (help) printf("%c%c %c%c\t- ", usermoves(x,1),usermoves(x,2), usermoves(y,1),usermoves(y,2)); printf("%s %ss from %c%c to %c%c", n->who ? "White" : "Black", n->jump ? "jump" : "move", usermoves(x,1),usermoves(x,2), usermoves(y,1),usermoves(y,2)); if (n->jump) { for (int i=0; i<32; i++) if (n->jump & (1<value); } #endif // VT100 int abortflag; //////////////////////////////////////////////////////////////// // VT100 Interface: #ifdef VT100 void positioncursor(int i) { printf("\033[%d;%dH", usermoves(i,2)-'0'+1, 2*(usermoves(i,1)-'A')+1); } void outpiecename(piece n) { printf(n&BLACK ? "\033[1;7m" : "\033[1m"); putchar(" BW??BW??"[n]); putchar(" BW??KK??"[n]); printf("\033[0m"); } void VT100board(void) { printf("\033<\033[H\033[J\033[10r"); int l = 0; puts(" A B C D E F G H"); for (int i=0; i<4; i++) { int j = 9*i+5; int k; for (k=0; k<4; k++) { printf("\033[7m \033[0m"); outpiecename(b[j+k]); } l++; printf("%d\n",l); j += 4; for (k=0; k<4; k++) { outpiecename(b[j+k]); printf("\033[7m \033[0m"); } l++; printf("%d\n",l); } } void VT100move(node *n, int) { if (!n) return; printf("\0337"); positioncursor(n->from); outpiecename(b[n->from]); positioncursor(n->to); outpiecename(b[n->to]); if (n->jump) for(int i=0; i<32; i++) { if (n->jump & (1< static void sigint(...) { abortflag = 1; signal(SIGINT,sigint); } void fixexit(int x) { printf("\0337\033[r\0338"); exit(x); } // Returns a son, or 0 if no move specified, or root to cause "help" node *getusermove(void) { int i,j; node *t; char line[100],*m1,*m2; if (playing) printf("\033[1m%s's move?\033[0m ",root->who ? "Black" : "White"); else printf("\033[1mCommand?\033[0m "); abortflag = 0; if (!fgets(line, sizeof(line), stdin)) { putchar('\n'); if (feof(stdin)) fixexit(0); return 0; } for (m1 = line; *m1 && *m1<=' '; m1++); if (!*m1) return(0); m2 = m1+1; if (*m2) m2++; for (; *m2 && *m2<'0'; m2++); if (playing && m1[1]>='0' && m1[1]<='9') { i = decode(m1); j = decode(m2); if (i && j) for (t = root->son; t; t = t->brother) if (t->from == i && t->to == j) return(t); puts("Valid moves are:"); m1[0] = 'L'; } switch(toupper(m1[0])) { case 0: return(0); case 'A': if (playing) autoplay = 1; return(root); case 'C': puts(copyright); break; case 'D': debug = !debug; printf("Debug is now %s.", debug ? "on" : "off"); break; case 'F': forcejumps = !forcejumps; printf("Forced jumps rule is now %s.",forcejumps ? "on" : "off"); killnode(root->son); root->son = 0; return(0); case 'L': expandnode(root); if (playing) for (t = root->son; t; t = t->brother) dumpnode(t,1); break; case 'M': return(playing ? root : 0); case 'N': newgame(); VT100board(); return(0); case 'P': printf("I expect the following moves:\n"); for (t = root->son; t; t = t->son) dumpnode(t,0); break; case 'Q': fixexit(0); case 'R': VT100board(); break; case 'S': user = !user; return(root); case 'U': VT100move(undomove(),1); VT100move(undomove(),1); return(0); case '+': maxevaluate = maxnodes = 2*maxevaluate; goto J2; case '-': if (maxevaluate > 1) maxevaluate = maxnodes = maxevaluate/2; J2: printf("Moves evaluated set to %d.",maxevaluate); break; default: puts( "A(utoplay)\n" "C(opyright)\n" "D(ebug on/off)\n" "F(orce jumps rule on/off)\n" "L(ist legal moves)\n" "M(ake a move for me)\n" "N(ew game)\n" "P(redict next few moves)\n" "Q(uit)\n" "R(edraw screen)\n" "S(witch sides)\n" "U(ndo)\n" "+ - smarter\n" "- - stupider"); expandnode(root); for (t = root->son; t; t = t->brother) dumpnode(t,1); } return(0); } int VT100main() { signal(SIGINT,sigint); VT100board(); for (;;) { if (playing) { expandnode(root); if (!root->son) { printf("%s has no move. Game over.",root->who ? "Black" : "White"); playing = autoplay = 0; } } node* move; if (playing && (autoplay || root->who == user)) { move = calcmove(root); if (move->value <= -30000) { printf("%s resigns.", move->who ? "White" : "Black"); move = 0; playing = autoplay = 0; } } else { move = getusermove(); if (move == root) move = calcmove(root); } if (move) { dumpnode(move,0); domove(move); VT100move(move,0); } } } #endif //////////////////////////////////////////////////////////////// // fltk interface: #ifdef FLTK #include #include #include #include #include #include //---------------------------------------------------------------- // Checkers pieces with built in transparency/drop shadows #include "checkers_pieces.h" Fl_PNG_Image *png[4]; void make_pieces() { if (png[0]) return; int which = 0; png[which++] = new Fl_PNG_Image(NULL, (const unsigned char *)pixmaps_black_checker_png, sizeof(pixmaps_black_checker_png)); png[which++] = new Fl_PNG_Image(NULL, (const unsigned char *)pixmaps_white_checker_png, sizeof(pixmaps_white_checker_png)); png[which++] = new Fl_PNG_Image(NULL, (const unsigned char *)pixmaps_black_checker_king_png, sizeof(pixmaps_black_checker_king_png)); png[which++] = new Fl_PNG_Image(NULL, (const unsigned char *)pixmaps_white_checker_king_png, sizeof(pixmaps_white_checker_king_png)); for (int i = 0; i < which; i++) png[i]->scale(png[i]->data_w()/2, png[i]->data_h()/2); } #define ISIZE 62 // old: 56 void draw_piece(int which, int x, int y) { if (!fl_not_clipped(x,y,ISIZE,ISIZE)) return; switch (which) { case BLACK: which = 0; break; case WHITE: which = 1; break; case BLACKKING: which = 2; break; case WHITEKING: which = 3; break; default: return; } png[which]->draw(x,y); } //---------------------------------------------------------------- class Board : public Fl_Double_Window { void draw() FL_OVERRIDE; int handle(int) FL_OVERRIDE; public: void drag_piece(int, int, int); void drop_piece(int); void animate(node* move, int backwards); void computer_move(int); Board(int w, int h) : Fl_Double_Window(w,h,"FLTK Checkers") {color(15);} }; #define BOXSIZE 52 #define BORDER 4 #define BOARDSIZE (8*BOXSIZE+BORDER) #define BMOFFSET 3 static int erase_this; // real location of dragging piece, don't draw it static int dragging; // piece being dragged static int dragx; // where it is static int dragy; static int showlegal; // show legal moves int squarex(int i) {return (usermoves(i,1)-'A')*BOXSIZE+BMOFFSET;} int squarey(int i) {return (usermoves(i,2)-'1')*BOXSIZE+BMOFFSET;} void Board::draw() { make_pieces(); // -- draw the board itself fl_draw_box(box(),0,0,w(),h(),color()); // -- draw all dark tiles fl_color((Fl_Color)10 /*107*/); int x; for (x=0; x<8; x++) for (int y=0; y<8; y++) { if (!((x^y)&1)) fl_rectf(BORDER+x*BOXSIZE, BORDER+y*BOXSIZE, BOXSIZE-BORDER, BOXSIZE-BORDER); } // -- draw outlines around the fileds fl_color(FL_DARK3); for (x=0; x<9; x++) { fl_rectf(x*BOXSIZE,0,BORDER,h()); fl_rectf(0,x*BOXSIZE,w(),BORDER); } for (int j = 5; j < 40; j++) if (j != erase_this) { draw_piece(b[j], squarex(j), squarey(j)); } if (showlegal) { fl_color(FL_WHITE); node* n; for (n = root->son; n; n = showlegal==2 ? n->son : n->brother) { int x1 = squarex(n->from)+BOXSIZE/2-5; int y1 = squarey(n->from)+BOXSIZE/2-5; int x2 = squarex(n->to)+BOXSIZE/2-5; int y2 = squarey(n->to)+BOXSIZE/2-5; fl_line(x1,y1,x2,y2); fl_push_matrix(); fl_mult_matrix(x2-x1,y2-y1,y1-y2,x2-x1,x2,y2); fl_begin_polygon(); fl_vertex(0,0); fl_vertex(-.3, .1); fl_vertex(-.3, -.1); fl_end_polygon(); fl_pop_matrix(); } int num = 1; fl_color(FL_BLACK); fl_font(FL_BOLD,10); for (n = root->son; n; n = showlegal==2 ? n->son : n->brother) { int x1 = squarex(n->from)+BOXSIZE/2-5; int y1 = squarey(n->from)+BOXSIZE/2-5; int x2 = squarex(n->to)+BOXSIZE/2-5; int y2 = squarey(n->to)+BOXSIZE/2-5; char buf[20]; snprintf(buf, 20,"%d",num); fl_draw(buf, x1+int((x2-x1)*.85)-3, y1+int((y2-y1)*.85)+5); num++; } } if (dragging) draw_piece(dragging, dragx, dragy); } // drag the piece on square i to dx dy, or undo drag if i is zero: void Board::drag_piece(int j, int dx, int dy) { dy = (dy&-2) | (dx&1); // make halftone shadows line up if (j != erase_this) drop_piece(erase_this); // should not happen if (!erase_this) { // pick up old piece dragx = squarex(j); dragy = squarey(j); erase_this = j; dragging = b[j]; } if (dx != dragx || dy != dragy) { damage(FL_DAMAGE_ALL, dragx, dragy, ISIZE, ISIZE); damage(FL_DAMAGE_ALL, dx, dy, ISIZE, ISIZE); } dragx = dx; dragy = dy; } // drop currently dragged piece on square i void Board::drop_piece(int j) { if (!erase_this) return; // should not happen! erase_this = 0; dragging = 0; int x = squarex(j); int y = squarey(j); if (x != dragx || y != dragy) { damage(4, dragx, dragy, ISIZE, ISIZE); damage(4, x, y, ISIZE, ISIZE); } } // show move (call this *before* the move, *after* undo): void Board::animate(node* move, int backwards) { if (showlegal) {showlegal = 0; redraw();} if (!move) return; int f = move->from; int t = move->to; if (backwards) {int x = f; f = t; t = x;} int x1 = squarex(f); int y1 = squarey(f); int x2 = squarex(t); int y2 = squarey(t); const int STEPS=35; for (int j=0; jfrom,x,y); Fl::flush(); Fl::wait(0.01); } drop_piece(t); if (move->jump) redraw(); } int busy; // causes pop-up abort menu void Board::computer_move(int help) { if (!playing) return; cursor(FL_CURSOR_WAIT); Fl::flush(); busy = 1; abortflag = 0; node* move = calcmove(root); busy = 0; if (move) { if (!help && move->value <= -30000) { fl_message("%s resigns", move->who ? "White" : "Black"); playing = autoplay = 0; cursor(FL_CURSOR_DEFAULT); return; } animate(move,0); domove(move); } expandnode(root); if (!root->son) { fl_message("%s has no move", root->who ? "Black" : "White"); playing = autoplay = 0; } if (!autoplay) cursor(FL_CURSOR_DEFAULT); } extern Fl_Menu_Item menu[]; extern Fl_Menu_Item busymenu[]; int Board::handle(int e) { if (busy) { const Fl_Menu_Item* m; switch(e) { case FL_PUSH: m = busymenu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0); if (m) m->do_callback(this, (void*)m); return 1; case FL_SHORTCUT: m = busymenu->test_shortcut(); if (m) {m->do_callback(this, (void*)m); return 1;} return 0; default: return 0; } } node *t, *n; static int deltax, deltay; int dist; const Fl_Menu_Item* m; switch (e) { case FL_PUSH: if (Fl::event_button() > 1) { m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0); if (m) m->do_callback(this, (void*)m); return 1; } if (playing) { expandnode(root); for (t = root->son; t; t = t->brother) { int x = squarex(t->from); int y = squarey(t->from); if (Fl::event_inside(x,y,BOXSIZE,BOXSIZE)) { deltax = Fl::event_x()-x; deltay = Fl::event_y()-y; drag_piece(t->from,x,y); return 1; } } } return 0; case FL_SHORTCUT: m = menu->test_shortcut(); if (m) {m->do_callback(this, (void*)m); return 1;} return 0; case FL_DRAG: drag_piece(erase_this, Fl::event_x()-deltax, Fl::event_y()-deltay); return 1; case FL_RELEASE: // find the closest legal move he dropped it on: dist = 50*50; n = 0; for (t = root->son; t; t = t->brother) if (t->from==erase_this) { int d1 = Fl::event_x()-deltax-squarex(t->to); int d = d1*d1; d1 = Fl::event_y()-deltay-squarey(t->to); d += d1*d1; if (d < dist) {dist = d; n = t;} } if (!n) {drop_piece(erase_this); return 1;} // none found drop_piece(n->to); domove(n); if (showlegal) {showlegal = 0; redraw();} if (n->jump) redraw(); computer_move(0); return 1; default: return 0; } } void quit_cb(Fl_Widget*, void*) {exit(0);} int FLTKmain(int argc, char** argv) { Fl::visual(FL_DOUBLE|FL_INDEX); Board b(BOARDSIZE,BOARDSIZE); b.color(FL_BACKGROUND_COLOR); b.callback(quit_cb); b.show(argc,argv); return Fl::run(); } void autoplay_cb(Fl_Widget*bp, void*) { if (autoplay) {autoplay = 0; return;} if (!playing) return; Board* b = (Board*)bp; autoplay = 1; while (autoplay) {b->computer_move(0); b->computer_move(0);} } #include Fl_Window *copyright_window; void copyright_cb(Fl_Widget*, void*) { if (!copyright_window) { copyright_window = new Fl_Window(400,270,"Copyright"); copyright_window->color(FL_WHITE); Fl_Box *b = new Fl_Box(20,0,380,270,copyright); b->labelsize(10); b->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP); copyright_window->end(); } copyright_window->hotspot(copyright_window); copyright_window->set_non_modal(); copyright_window->show(); } void debug_cb(Fl_Widget*, void*v) { debug = !debug; ((Fl_Menu_Item*)v)->flags = debug ? FL_MENU_TOGGLE|FL_MENU_VALUE : FL_MENU_TOGGLE; } void forced_cb(Fl_Widget*b, void*v) { forcejumps = !forcejumps; ((Fl_Menu_Item*)v)->flags = forcejumps ? FL_MENU_TOGGLE|FL_MENU_VALUE : FL_MENU_TOGGLE; killnode(root->son); root->son = 0; if (showlegal) {expandnode(root); b->redraw();} } void move_cb(Fl_Widget*pb, void*) { Board* b = (Board*)pb; if (playing) b->computer_move(1); if (playing) b->computer_move(0); } void newgame_cb(Fl_Widget*b, void*) { showlegal = 0; newgame(); b->redraw(); } void legal_cb(Fl_Widget*pb, void*) { if (showlegal == 1) {showlegal = 0; ((Board*)pb)->redraw(); return;} if (!playing) return; expandnode(root); showlegal = 1; ((Board*)pb)->redraw(); } void predict_cb(Fl_Widget*pb, void*) { if (showlegal == 2) {showlegal = 0; ((Board*)pb)->redraw(); return;} if (playing) expandnode(root); showlegal = 2; ((Board*)pb)->redraw(); } void switch_cb(Fl_Widget*pb, void*) { user = !user; ((Board*)pb)->computer_move(0); } void undo_cb(Fl_Widget*pb, void*) { Board* b = (Board*)pb; b->animate(undomove(),1); b->animate(undomove(),1); } //-------------------------- #include #include Fl_Window *intel_window; Fl_Value_Output *intel_output; void intel_slider_cb(Fl_Widget*w, void*) { double v = ((Fl_Slider*)w)->value(); int n = int(v*v); intel_output->value(n); maxevaluate = maxnodes = n; } void intel_cb(Fl_Widget*, void*) { if (!intel_window) { intel_window = new Fl_Window(200,25,"Checkers Intelligence"); Fl_Slider* s = new Fl_Slider(60,0,140,25); s->type(FL_HOR_NICE_SLIDER); s->minimum(1); s->maximum(500); s->value(50); s->callback(intel_slider_cb); intel_output = new Fl_Value_Output(0,0,60,25); intel_output->value(maxevaluate); intel_window->resizable(s); } intel_window->hotspot(intel_window); intel_window->set_non_modal(); intel_window->show(); } //--------------------------- void stop_cb(Fl_Widget*, void*) {abortflag = 1;} void continue_cb(Fl_Widget*, void*) {} Fl_Menu_Item menu[] = { {"Autoplay", 'a', autoplay_cb}, {"Legal moves", 'l', legal_cb}, {"Move for me", 'm', move_cb}, {"New game", 'n', newgame_cb}, {"Predict", 'p', predict_cb}, {"Switch sides", 's', switch_cb}, {"Undo", 'u', undo_cb, 0, FL_MENU_DIVIDER}, {"Forced jumps rule", 'f', forced_cb, 0, FL_MENU_TOGGLE|FL_MENU_VALUE}, {"Debug", 'd', debug_cb, (void *)"d", FL_MENU_TOGGLE}, {"Intelligence...", 'i', intel_cb, 0, FL_MENU_DIVIDER}, {"Copyright", 'c', copyright_cb}, {"Quit", 'q', quit_cb}, {0}}; Fl_Menu_Item busymenu[] = { {"Stop", '.', stop_cb}, {"Autoplay", 'a', autoplay_cb}, {"Continue", 0, continue_cb}, {"Debug", 'd', debug_cb, (void *)"d", FL_MENU_TOGGLE}, {"Intelligence...", 'i', intel_cb}, {"Copyright", 'c', copyright_cb}, {"Quit", 'q', quit_cb}, {0}}; #endif //////////////////////////////////////////////////////////////// // parts shared by both interface: #ifdef FLTK #ifdef VT100 #define BOTH #endif #endif #ifdef BOTH int terminal; int arg(int, char **argv, int &i) { if (argv[i][1] == 't') {terminal = 1; i++; return 1;} return 0; } #endif int didabort(void) { #ifdef FLTK #ifdef BOTH if (!terminal) #endif Fl::check(); #endif if (abortflag) { autoplay = 0; abortflag = 0; return 1; } return(0); } int main(int argc, char **argv) { seed = (int)time(0); newgame(); #ifdef BOTH fl_register_images(); int i = 1; if (Fl::args(argc, argv, i, arg) < argc) { fprintf(stderr," -t : use VT100 display\n", Fl::help); exit(1); } if (!fl_getenv("DISPLAY")) terminal = 1; if (!terminal) #endif #ifdef FLTK return FLTKmain(argc,argv); #endif #ifdef VT100 return VT100main(); #endif } fltk-1.4.3/test/checkers_pieces.fl0000644000175000017500000000173415004135251017233 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0401 header_name {.h} code_name {.cxx} comment {// // Checkers images for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // } {in_source in_header } data pixmaps_black_checker_png {public local filename {pixmaps/black_checker.png} } data pixmaps_white_checker_png {selected public local filename {pixmaps/white_checker.png} } data pixmaps_black_checker_king_png {public local filename {pixmaps/black_checker_king.png} } data pixmaps_white_checker_king_png {public local filename {pixmaps/white_checker_king.png} } fltk-1.4.3/config.sub0000755000175000017500000010541215004135251014573 0ustar albrechtalbrecht#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-10-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 \ | or1k | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or1k-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: fltk-1.4.3/config.guess0000755000175000017500000013135515004135251015135 0ustar albrechtalbrecht#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-11-29' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry to config-patches@gnu.org. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; or1k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: fltk-1.4.3/fltk.spec0000644000175000017500000000620415004146477014437 0ustar albrechtalbrecht# # RPM spec file for FLTK. # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # %define version 1.4.3 %define release 1 %define prefix /usr Summary: Fast Light Tool Kit (FLTK) Name: fltk Version: %{version} Release: %{release} License: LGPL Group: System Environment/Libraries Source: https://github.com/fltk/fltk/releases/download/release-1.4.3/fltk-1.4.3-source.tar.gz URL: https://www.fltk.org/ Packager: FLTK Developer # use BuildRoot so as not to disturb the version already installed BuildRoot: /var/tmp/fltk-%{PACKAGE_VERSION} %description The Fast Light Tool Kit ("FLTK") is a cross-platform C++ GUI toolkit for UNIX(r)/Linux(r) (X11), Microsoft(r) Windows(r), and macOS(r). FLTK provides modern GUI functionality without bloat and supports 3D graphics via OpenGL(r) and its built-in GLUT emulation. %package devel Summary: FLTK Development Environment Group: Development/Libraries %description devel Install fltk-devel if you need to develop FLTK applications. You'll need to install the fltk package if you plan to run dynamically linked applications. %package games Summary: FLTK Games Group: Games %description games Install fltk-games to play Block Attack!, Checkers, or Sudoku on your computer. %prep %setup %build CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix} --mandir=%{_mandir} --enable-largefile --enable-shared --enable-threads --enable-xft --enable-xinerama # If we got this far, all prerequisite libraries must be here. make %install # these lines just make sure the directory structure in the # RPM_BUILD_ROOT exists rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT make -e DESTDIR=$RPM_BUILD_ROOT install install-desktop %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %dir %{prefix}/lib %{prefix}/lib/libfltk*.so.* %files devel %defattr(-,root,root) %dir %{prefix}/bin %{prefix}/bin/fltk-config %{prefix}/bin/fltk-options %{prefix}/bin/fluid %dir %{prefix}/include/FL %{prefix}/include/FL/* %{prefix}/include/Fl %dir %{prefix}/lib %{prefix}/lib/libfltk*.so %{prefix}/lib/libfltk*.a %dir %{_mandir} %{_mandir}/cat1/* %{_mandir}/cat3/* %{_mandir}/man1/* %{_mandir}/man3/* %dir %{prefix}/share/doc/fltk %{prefix}/share/doc/fltk/* %dir %{prefix}/share/applications %{prefix}/share/applications/* %dir %{prefix}/share/icons %{prefix}/share/icons/hicolor/*/apps/fluid.png %dir %{prefix}/share/mimelnk %{prefix}/share/mimelnk/* %files games %dir %{prefix}/bin %{prefix}/bin/blocks %{prefix}/bin/checkers %{prefix}/bin/sudoku %dir %{_mandir} %{_mandir}/cat6/* %{_mandir}/man6/* %dir %{prefix}/share/applications %{prefix}/share/applications/* %dir %{prefix}/share/icons %{prefix}/share/icons/hicolor/*/apps/blocks.png %{prefix}/share/icons/hicolor/*/apps/checkers.png %{prefix}/share/icons/hicolor/*/apps/sudoku.png fltk-1.4.3/configh.in0000644000175000017500000001321015004135251014547 0ustar albrechtalbrecht/* * Configuration file for the Fast Light Tool Kit (FLTK). * * Copyright 1998-2024 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * Note: configure syntax vs. CMake syntax in source files (examples): * * configh.in configh.cmake.in * --------------------- ---------------------------- * [#]define HAVE_GL 0 [#]cmakedefine01 HAVE_GL * [#]undef HAVE_SNPRINTF [#]cmakedefine HAVE_SNPRINTF 1 * * The former defines the given macro either as 0 or 1, * the latter either does not define the macro or defines it as 1. */ /* * Always include the public build configuration header */ #include /* * Where to find files... */ #define FLTK_DATADIR "" #define FLTK_DOCDIR "" /* * BORDER_WIDTH: * * Thickness of FL_UP_BOX and FL_DOWN_BOX. Current 1,2, and 3 are * supported. * * 3 is the historic FLTK look. * 2 is the default and looks like Microsoft Windows, KDE, and Qt. * 1 is a plausible future evolution... * * Note that this may be simulated at runtime by redefining the boxtypes * using Fl::set_boxtype(). */ #define BORDER_WIDTH 2 /* * HAVE_GL: * * Do you have OpenGL? Set this to 0 if you don't have or plan to use * OpenGL, and FLTK will be smaller. */ #define HAVE_GL 0 /* * HAVE_GL_GLU_H: * * Do you have the OpenGL Utility Library header file? * (many broken Mesa RPMs do not...) */ #define HAVE_GL_GLU_H 0 /* * HAVE_GLXGETPROCADDRESSARB: * * Do you have the OpenGL glXGetProcAddressARB() function? */ #undef HAVE_GLXGETPROCADDRESSARB /* * USE_COLORMAP: * * Setting this to zero will save a good deal of code (especially for * fl_draw_image), but FLTK will only work on TrueColor visuals. */ #define USE_COLORMAP 1 /* * HAVE_XINERAMA * * Do we have the Xinerama library to support multi-head displays? */ #define HAVE_XINERAMA 0 /* * USE_XFT * * Use the Xft library to draw anti-aliased text. */ #define USE_XFT 0 /* * USE_PANGO * * Use the pango library to draw UTF-8 text. */ #define USE_PANGO 0 /* * HAVE_XFIXES: * * Do we have the X fixes extension? */ #define HAVE_XFIXES 0 /* * HAVE_XCURSOR: * * Do we have the X cursor library? */ #define HAVE_XCURSOR 0 /* * HAVE_XRENDER: * * Do we have the X render library? */ #define HAVE_XRENDER 0 /* * HAVE_X11_XREGION_H: * * Do we have the X11 Xregion.h header file ? */ #define HAVE_X11_XREGION_H 0 /* * HAVE_GL_OVERLAY: * * It is possible your GL has an overlay even if X does not. If so, * set this to 1. */ #define HAVE_GL_OVERLAY 0 /* * WORDS_BIGENDIAN: * * Byte order of your machine: 1 = big-endian, 0 = little-endian. */ #ifdef __APPLE__ #include #else #define WORDS_BIGENDIAN 0 #endif /* * U16, U32, U64: * * Types used by fl_draw_image. One of U32 or U64 must be defined. * U16 is optional but FLTK will work better with it! */ #undef U16 #undef U32 #undef U64 /* * HAVE_DIRENT_H, HAVE_SYS_NDIR_H, HAVE_SYS_DIR_H, HAVE_NDIR_H, * HAVE_SCANDIR, HAVE_SCANDIR_POSIX: * * Where is (used only by fl_file_chooser and scandir). */ #undef HAVE_DIRENT_H #undef HAVE_SYS_NDIR_H #undef HAVE_SYS_DIR_H #undef HAVE_NDIR_H #undef HAVE_SCANDIR #undef HAVE_SCANDIR_POSIX /* * Possibly missing sprintf-style functions: */ #undef HAVE_VSNPRINTF #undef HAVE_SNPRINTF /* * String functions and headers... */ #undef HAVE_STRINGS_H #undef HAVE_STRCASECMP #undef HAVE_STRLCAT #undef HAVE_STRLCPY /* * Do we have POSIX locale support? */ #undef HAVE_LOCALE_H #undef HAVE_LOCALECONV /* * HAVE_SYS_SELECT_H: * * Whether or not select() call has its own header file. */ #define HAVE_SYS_SELECT_H 0 /* * HAVE_SYS_STDTYPES_H: * * Whether or not we have the header file. */ #undef HAVE_SYS_STDTYPES_H /* * USE_POLL: * * Use the poll() call provided on Linux and Irix instead of select() */ #define USE_POLL 0 /* * HAVE_SETENV: * * Whether or not POSIX setenv() is available from stdlib.h. */ #define HAVE_SETENV 0 /* * HAVE_TRUNC: * * Whether or not POSIX trunc() is available from math.h. */ #define HAVE_TRUNC 0 /* * Do we have various image libraries? */ #undef HAVE_LIBPNG #undef HAVE_LIBZ #undef HAVE_LIBJPEG /* * Which header file do we include for libpng? * ifdef HAVE_PNG_H : * else : * There is no other choice. */ #undef HAVE_PNG_H /* * Do we have the png_xyz() functions? */ #undef HAVE_PNG_GET_VALID #undef HAVE_PNG_SET_TRNS_TO_ALPHA /* * Do we have POSIX threading? */ #undef HAVE_PTHREAD #undef HAVE_PTHREAD_H /* * Do we have PTHREAD_MUTEX_RECURSIVE? */ #undef HAVE_PTHREAD_MUTEX_RECURSIVE /* * Do we have the ALSA library? */ #undef HAVE_ALSA_ASOUNDLIB_H /* * Do we have the long long type? */ #undef HAVE_LONG_LONG #ifdef HAVE_LONG_LONG # define FLTK_LLFMT "%lld" # define FLTK_LLCAST (long long) #else # define FLTK_LLFMT "%ld" # define FLTK_LLCAST (long) #endif /* HAVE_LONG_LONG */ /* * Do we have the dlsym() function and header? */ #define HAVE_DLFCN_H 0 #define HAVE_DLSYM 0 /* * Do we want print support? */ #undef FL_NO_PRINT_SUPPORT /* * Do we use GDI+ to get antialiased graphics? */ #ifdef _WIN32 #define USE_GDIPLUS 0 #endif /* * Do we want filename handling and a filechooser? * *FIXME* FL_CFG_NO_FILESYSTEM_SUPPORT not yet implemented in configure ! */ #undef FL_CFG_NO_FILESYSTEM_SUPPORT fltk-1.4.3/fltk.list.in0000644000175000017500000005171215004135251015055 0ustar albrechtalbrecht# # EPM product list file for the Fast Light Tool Kit (FLTK). # # (EPM can be found at https://www.msweet.org/epm/) # # Copyright 1998-2023 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # %product Fast Light Tool Kit (FLTK) %copyright 1998-2023 by Bill Spitzak and others. %vendor FLTK Development Team %license COPYING %readme README.txt %version @FLTK_VERSION@ %description The Fast Light Tool Kit ("FLTK") is a cross-platform C++ GUI %description toolkit for UNIX(r)/Linux(r) (X11), Microsoft(r) Windows(r), %description and macOS(r). FLTK provides modern GUI functionality without %description bloat and supports 3D graphics via OpenGL(r) and its built-in %description GLUT emulation. $prefix=@prefix@ $exec_prefix=@exec_prefix@ $bindir=@bindir@ $datarootdir=@datarootdir@ $datadir=@datadir@ $includedir=@includedir@ $libdir=@libdir@ $mandir=@mandir@ $docdir=${datadir}/doc/fltk $CAT1EXT=@CAT1EXT@ $CAT3EXT=@CAT3EXT@ $CAT6EXT=@CAT6EXT@ $DSONAME=@DSONAME@ $FLDSONAME=@FLDSONAME@ $FLLIBNAME=@FLLIBNAME@ $GLDSONAME=@GLDSONAME@ $GLLIBNAME=@GLLIBNAME@ $FLUID=@FLUID@ $FLTK_OPTIONS=@FLTK_OPTIONS@ $JPEG=@JPEG@ $PNG=@PNG@ $ZLIB=@ZLIB@ %if DSONAME %system aix f 0555 root sys $libdir/libfltk_s.a src/libfltk_s.a nostrip() %system hpux f 0555 root sys $libdir/libfltk.sl.@FL_DSO_VERSION@ src/libfltk.sl.@FL_DSO_VERSION@ nostrip() %system darwin f 0555 root sys $libdir/libfltk.@FL_DSO_VERSION@.dylib src/libfltk.@FL_DSO_VERSION@.dylib nostrip() %system !aix !darwin !hpux f 0555 root sys $libdir/libfltk.so.@FL_DSO_VERSION@ src/libfltk.so.@FL_DSO_VERSION@ nostrip() %system all %system aix f 0555 root sys $libdir/libfltk_forms_s.a src/libfltk_forms_s.a nostrip() %system hpux f 0555 root sys $libdir/libfltk_forms.sl.@FL_DSO_VERSION@ src/libfltk_forms.sl.@FL_DSO_VERSION@ nostrip() %system darwin f 0555 root sys $libdir/libfltk_forms.@FL_DSO_VERSION@.dylib src/libfltk_forms.@FL_DSO_VERSION@.dylib nostrip() %system !aix !darwin !hpux f 0555 root sys $libdir/libfltk_forms.so.@FL_DSO_VERSION@ src/libfltk_forms.so.@FL_DSO_VERSION@ nostrip() %system all %system aix f 0555 root sys $libdir/libfltk_images_s.a src/libfltk_images_s.a nostrip() %system hpux f 0555 root sys $libdir/libfltk_images.sl.@FL_DSO_VERSION@ src/libfltk_images.sl.@FL_DSO_VERSION@ nostrip() %system darwin f 0555 root sys $libdir/libfltk_images.@FL_DSO_VERSION@.dylib src/libfltk_images.@FL_DSO_VERSION@.dylib nostrip() %system !aix !darwin !hpux f 0555 root sys $libdir/libfltk_images.so.@FL_DSO_VERSION@ src/libfltk_images.so.@FL_DSO_VERSION@ nostrip() %system all %endif %if GLDSONAME %system aix f 0555 root sys $libdir/libfltk_gl_s.a src/libfltk_gl_s.a nostrip() %system hpux f 0555 root sys $libdir/libfltk_gl.sl.@FL_DSO_VERSION@ src/libfltk_gl.sl.@FL_DSO_VERSION@ nostrip() %system darwin f 0555 root sys $libdir/libfltk_gl.@FL_DSO_VERSION@.dylib src/libfltk_gl.@FL_DSO_VERSION@.dylib nostrip() %system !aix !darwin !hpux f 0555 root sys $libdir/libfltk_gl.so.@FL_DSO_VERSION@ src/libfltk_gl.so.@FL_DSO_VERSION@ nostrip() %system all %endif %subpackage devel %description FLTK Development Environment %description Install fltk-devel if you need to develop FLTK applications. %description You'll need to install the fltk package if you plan to run %description dynamically linked applications. %system darwin d 0555 root sys /Applications/fluid.app - d 0555 root sys /Applications/fluid.app/Contents - f 0444 root sys /Applications/fluid.app/Contents/Info.plist fluid/fluid.app/Contents/Info.plist d 0555 root sys /Applications/fluid.app/Contents/MacOS - l 0555 root sys /Applications/fluid.app/Contents/MacOS/fluid $bindir/fluid d 0555 root sys /Applications/fluid.app/Contents/Resources - f 0444 root sys /Applications/fluid.app/Contents/Resources/fluid.icns fluid/fluid.app/Contents/Resources/fluid.icns %postinstall $bindir/fltk-config --post $bindir/fluid %postremove /bin/rm -rf /Applications/fluid.app d 0555 root sys /Applications/fltk-options.app - d 0555 root sys /Applications/fltk-options.app/Contents - f 0444 root sys /Applications/fltk-options.app/Contents/Info.plist fltk-options/fltk-options.app/Contents/Info.plist d 0555 root sys /Applications/fltk-options.app/Contents/MacOS - l 0555 root sys /Applications/fltk-options.app/Contents/MacOS/fltk-options $bindir/fltk-options d 0555 root sys /Applications/fltk-options.app/Contents/Resources - f 0444 root sys /Applications/fltk-options.app/Contents/Resources/fltk-options.icns fltk-options/fltk-options.app/Contents/Resources/fltk-options.icns %postinstall $bindir/fltk-config --post $bindir/fltk-options %postremove /bin/rm -rf /Applications/fltk-options.app %system !darwin f 0444 root sys /usr/share/applications/fluid.desktop fluid/fluid.desktop f 0444 root sys /usr/share/icons/hicolor/16x16/apps/fluid.png fluid/icons/fluid-16.png f 0444 root sys /usr/share/icons/hicolor/32x32/apps/fluid.png fluid/icons/fluid-32.png f 0444 root sys /usr/share/icons/hicolor/48x48/apps/fluid.png fluid/icons/fluid-48.png f 0444 root sys /usr/share/icons/hicolor/64x64/apps/fluid.png fluid/icons/fluid-64.png f 0444 root sys /usr/share/icons/hicolor/128x128/apps/fluid.png fluid/icons/fluid-128.png f 0444 root sys /usr/share/mimelnk/application/x-fluid.desktop fluid/fluid.desktop f 0444 root sys /usr/share/applications/fltk-options.desktop fltk-options/fltk-options.desktop f 0444 root sys /usr/share/icons/hicolor/16x16/apps/fltk-options.png fltk-options/icons/fltk-options-16.png f 0444 root sys /usr/share/icons/hicolor/32x32/apps/fltk-options.png fltk-options/icons/fltk-options-32.png f 0444 root sys /usr/share/icons/hicolor/48x48/apps/fltk-options.png fltk-options/icons/fltk-options-48.png f 0444 root sys /usr/share/icons/hicolor/64x64/apps/fltk-options.png fltk-options/icons/fltk-options-64.png f 0444 root sys /usr/share/icons/hicolor/128x128/apps/fltk-options.png fltk-options/icons/fltk-options-128.png f 0444 root sys /usr/share/mimelnk/application/x-fltk-options.desktop fltk-options/fltk-options.desktop %system all # Applications f 0555 root sys $bindir/fluid fluid/$FLUID f 0555 root sys $bindir/fltk-options fltk-options/$FLTK_OPTIONS f 0555 root sys $bindir/fltk-config fltk-config # Man pages f 0444 root sys $mandir/cat1/fluid.$CAT1EXT documentation/src/fluid.$CAT1EXT f 0444 root sys $mandir/cat1/fltk-options.$CAT1EXT documentation/src/fltk-options.$CAT1EXT f 0444 root sys $mandir/cat1/fltk-config.$CAT1EXT documentation/src/fltk-config.$CAT1EXT f 0444 root sys $mandir/cat3/fltk.$CAT3EXT documentation/src/fltk.$CAT3EXT f 0444 root sys $mandir/man1/fluid.1 documentation/src/fluid.man f 0444 root sys $mandir/man1/fltk-options.1 documentation/src/fltk-options.man f 0444 root sys $mandir/man1/fltk-config.1 documentation/src/fltk-config.man f 0444 root sys $mandir/man3/fltk.3 documentation/src/fltk.man # Library files f 0444 root sys $libdir/libfltk.a lib/libfltk.a f 0444 root sys $libdir/libfltk_forms.a lib/libfltk_forms.a f 0444 root sys $libdir/libfltk_images.a lib/libfltk_images.a %if GLLIBNAME f 0444 root sys $libdir/libfltk_gl.a lib/libfltk_gl.a %endif %if JPEG f 0444 root sys $libdir/libfltk_jpeg.a lib/libfltk_jpeg.a %endif %if PNG f 0444 root sys $libdir/libfltk_png.a lib/libfltk_png.a %endif %if ZLIB f 0444 root sys $libdir/libfltk_z.a lib/libfltk_z.a %endif %if DSONAME %system hpux l 0000 root sys $libdir/libfltk.sl libfltk.sl.@FL_DSO_VERSION@ %system darwin l 0000 root sys $libdir/libfltk.dylib libfltk.@FL_DSO_VERSION@.dylib %system !aix !darwin !hpux l 0000 root sys $libdir/libfltk.so libfltk.so.@FL_DSO_VERSION@ %system all %system hpux l 0000 root sys $libdir/libfltk_forms.sl libfltk_forms.sl.@FL_DSO_VERSION@ %system darwin l 0000 root sys $libdir/libfltk_forms.dylib libfltk_forms.@FL_DSO_VERSION@.dylib %system !aix !darwin !hpux l 0000 root sys $libdir/libfltk_forms.so libfltk_forms.so.@FL_DSO_VERSION@ %system all %system hpux l 0000 root sys $libdir/libfltk_images.sl libfltk_images.sl.@FL_DSO_VERSION@ %system darwin l 0000 root sys $libdir/libfltk_images.dylib libfltk_images.@FL_DSO_VERSION@.dylib %system !aix !darwin !hpux l 0000 root sys $libdir/libfltk_images.so libfltk_images.so.@FL_DSO_VERSION@ %system all %endif %if GLDSONAME %system hpux l 0000 root sys $libdir/libfltk_gl.sl libfltk_gl.sl.@FL_DSO_VERSION@ %system darwin l 0000 root sys $libdir/libfltk_gl.dylib libfltk_gl.@FL_DSO_VERSION@.dylib %system !aix !darwin !hpux l 0000 root sys $libdir/libfltk_gl.so libfltk_gl.so.@FL_DSO_VERSION@ %system all %endif # Header files f 0444 root sys $includedir/FL/ FL/*.[hH] %if JPEG f 0444 root sys $includedir/FL/images/jconfig.h jpeg/jconfig.h f 0444 root sys $includedir/FL/images/jerror.h jpeg/jerror.h f 0444 root sys $includedir/FL/images/jmorecfg.h jpeg/jmorecfg.h f 0444 root sys $includedir/FL/images/jpeglib.h jpeg/jpeglib.h %endif %if PNG f 0444 root sys $includedir/FL/images/png.h png/png.h f 0444 root sys $includedir/FL/images/pngconf.h png/pngconf.h f 0444 root sys $includedir/FL/images/pnglibconf.h png/pnglibconf.h %endif %if ZLIB f 0444 root sys $includedir/FL/images/zconf.h zlib/zconf.h f 0444 root sys $includedir/FL/images/zlib.h zlib/zlib.h f 0444 root sys $includedir/FL/images/zutil.h zlib/zutil.h %endif %system !darwin # Symlinks to handle common case problems... l 0000 root sys $includedir/Fl FL l 0000 root sys $includedir/FL/Enumerations.h Enumerations.H l 0000 root sys $includedir/FL/Fl.h Fl.H l 0000 root sys $includedir/FL/Fl_Adjuster.h Fl_Adjuster.H l 0000 root sys $includedir/FL/Fl_Bitmap.h Fl_Bitmap.H l 0000 root sys $includedir/FL/Fl_BMP_Image.h Fl_BMP_Image.H l 0000 root sys $includedir/FL/Fl_Box.h Fl_Box.H l 0000 root sys $includedir/FL/Fl_Browser.h Fl_Browser.H l 0000 root sys $includedir/FL/Fl_Browser_.h Fl_Browser_.H l 0000 root sys $includedir/FL/Fl_Button.h Fl_Button.H l 0000 root sys $includedir/FL/Fl_Cairo.h Fl_Cairo.H l 0000 root sys $includedir/FL/Fl_Cairo_Window.h Fl_Cairo_Window.H l 0000 root sys $includedir/FL/Fl_Chart.h Fl_Chart.H l 0000 root sys $includedir/FL/Fl_Check_Browser.h Fl_Check_Browser.H l 0000 root sys $includedir/FL/Fl_Check_Button.h Fl_Check_Button.H l 0000 root sys $includedir/FL/Fl_Choice.h Fl_Choice.H l 0000 root sys $includedir/FL/Fl_Clock.h Fl_Clock.H l 0000 root sys $includedir/FL/Fl_Color_Chooser.h Fl_Color_Chooser.H l 0000 root sys $includedir/FL/Fl_Counter.h Fl_Counter.H l 0000 root sys $includedir/FL/Fl_Device.h Fl_Device.H l 0000 root sys $includedir/FL/Fl_Dial.h Fl_Dial.H l 0000 root sys $includedir/FL/Fl_Double_Window.h Fl_Double_Window.H l 0000 root sys $includedir/FL/Fl_Export.h Fl_Export.H l 0000 root sys $includedir/FL/Fl_File_Browser.h Fl_File_Browser.H l 0000 root sys $includedir/FL/Fl_File_Chooser.h Fl_File_Chooser.H l 0000 root sys $includedir/FL/Fl_File_Icon.h Fl_File_Icon.H l 0000 root sys $includedir/FL/Fl_Fill_Dial.h Fl_Fill_Dial.H l 0000 root sys $includedir/FL/Fl_Fill_Slider.h Fl_Fill_Slider.H l 0000 root sys $includedir/FL/Fl_Float_Input.h Fl_Float_Input.H l 0000 root sys $includedir/FL/Fl_FormsBitmap.h Fl_FormsBitmap.H l 0000 root sys $includedir/FL/Fl_FormsPixmap.h Fl_FormsPixmap.H l 0000 root sys $includedir/FL/Fl_Free.h Fl_Free.H l 0000 root sys $includedir/FL/Fl_GIF_Image.h Fl_GIF_Image.H l 0000 root sys $includedir/FL/Fl_Gl_Window.h Fl_Gl_Window.H l 0000 root sys $includedir/FL/Fl_Group.h Fl_Group.H l 0000 root sys $includedir/FL/Fl_Help_Dialog.h Fl_Help_Dialog.H l 0000 root sys $includedir/FL/Fl_Help_View.h Fl_Help_View.H l 0000 root sys $includedir/FL/Fl_Hold_Browser.h Fl_Hold_Browser.H l 0000 root sys $includedir/FL/Fl_Hor_Fill_Slider.h Fl_Hor_Fill_Slider.H l 0000 root sys $includedir/FL/Fl_Hor_Nice_Slider.h Fl_Hor_Nice_Slider.H l 0000 root sys $includedir/FL/Fl_Hor_Slider.h Fl_Hor_Slider.H l 0000 root sys $includedir/FL/Fl_Hor_Value_Slider.h Fl_Hor_Value_Slider.H l 0000 root sys $includedir/FL/Fl_Image.h Fl_Image.H l 0000 root sys $includedir/FL/Fl_JPEG_Image.h Fl_JPEG_Image.H l 0000 root sys $includedir/FL/Fl_Input.h Fl_Input.H l 0000 root sys $includedir/FL/Fl_Input_.h Fl_Input_.H l 0000 root sys $includedir/FL/Fl_Input_Choice.h Fl_Input_Choice.H l 0000 root sys $includedir/FL/Fl_Int_Input.h Fl_Int_Input.H l 0000 root sys $includedir/FL/Fl_Light_Button.h Fl_Light_Button.H l 0000 root sys $includedir/FL/Fl_Line_Dial.h Fl_Line_Dial.H l 0000 root sys $includedir/FL/Fl_Menu.h Fl_Menu.H l 0000 root sys $includedir/FL/Fl_Menu_.h Fl_Menu_.H l 0000 root sys $includedir/FL/Fl_Menu_Bar.h Fl_Menu_Bar.H l 0000 root sys $includedir/FL/Fl_Menu_Button.h Fl_Menu_Button.H l 0000 root sys $includedir/FL/Fl_Menu_Item.h Fl_Menu_Item.H l 0000 root sys $includedir/FL/Fl_Menu_Window.h Fl_Menu_Window.H l 0000 root sys $includedir/FL/Fl_Multi_Browser.h Fl_Multi_Browser.H l 0000 root sys $includedir/FL/Fl_Multi_Label.h Fl_Multi_Label.H l 0000 root sys $includedir/FL/Fl_Multiline_Input.h Fl_Multiline_Input.H l 0000 root sys $includedir/FL/Fl_Multiline_Output.h Fl_Multiline_Output.H l 0000 root sys $includedir/FL/Fl_Native_File_Chooser.h Fl_Native_File_Chooser.H l 0000 root sys $includedir/FL/Fl_Nice_Slider.h Fl_Nice_Slider.H l 0000 root sys $includedir/FL/Fl_Object.h Fl_Object.H l 0000 root sys $includedir/FL/Fl_Output.h Fl_Output.H l 0000 root sys $includedir/FL/Fl_Overlay_Window.h Fl_Overlay_Window.H l 0000 root sys $includedir/FL/Fl_Pack.h Fl_Pack.H l 0000 root sys $includedir/FL/Fl_Paged_Device.h Fl_Paged_Device.H l 0000 root sys $includedir/FL/Fl_Pixmap.h Fl_Pixmap.H l 0000 root sys $includedir/FL/Fl_Plugin.h Fl_Plugin.H l 0000 root sys $includedir/FL/Fl_PNG_Image.h Fl_PNG_Image.H l 0000 root sys $includedir/FL/Fl_PNM_Image.h Fl_PNM_Image.H l 0000 root sys $includedir/FL/Fl_Positioner.h Fl_Positioner.H l 0000 root sys $includedir/FL/Fl_PostScript.h Fl_PostScript.H l 0000 root sys $includedir/FL/Fl_Preferences.h Fl_Preferences.H l 0000 root sys $includedir/FL/Fl_Printer.h Fl_Printer.H l 0000 root sys $includedir/FL/Fl_Progress.h Fl_Progress.H l 0000 root sys $includedir/FL/Fl_Radio_Button.h Fl_Radio_Button.H l 0000 root sys $includedir/FL/Fl_Radio_Light_Button.h Fl_Radio_Light_Button.H l 0000 root sys $includedir/FL/Fl_Radio_Round_Button.h Fl_Radio_Round_Button.H l 0000 root sys $includedir/FL/Fl_Repeat_Button.h Fl_Repeat_Button.H l 0000 root sys $includedir/FL/Fl_Return_Button.h Fl_Return_Button.H l 0000 root sys $includedir/FL/Fl_Roller.h Fl_Roller.H l 0000 root sys $includedir/FL/Fl_Round_Button.h Fl_Round_Button.H l 0000 root sys $includedir/FL/Fl_Round_Clock.h Fl_Round_Clock.H l 0000 root sys $includedir/FL/Fl_Scroll.h Fl_Scroll.H l 0000 root sys $includedir/FL/Fl_Scrollbar.h Fl_Scrollbar.H l 0000 root sys $includedir/FL/Fl_Secret_Input.h Fl_Secret_Input.H l 0000 root sys $includedir/FL/Fl_Select_Browser.h Fl_Select_Browser.H l 0000 root sys $includedir/FL/Fl_Shared_Image.h Fl_Shared_Image.H l 0000 root sys $includedir/FL/Fl_Simple_Counter.h Fl_Simple_Counter.H l 0000 root sys $includedir/FL/Fl_Single_Window.h Fl_Single_Window.H l 0000 root sys $includedir/FL/Fl_Slider.h Fl_Slider.H l 0000 root sys $includedir/FL/Fl_Spinner.h Fl_Spinner.H l 0000 root sys $includedir/FL/Fl_Sys_Menu_Bar.h Fl_Sys_Menu_Bar.H l 0000 root sys $includedir/FL/Fl_Table.h Fl_Table.H l 0000 root sys $includedir/FL/Fl_Table_Row.h Fl_Table_Row.H l 0000 root sys $includedir/FL/Fl_Tabs.h Fl_Tabs.H l 0000 root sys $includedir/FL/Fl_Text_Buffer.h Fl_Text_Buffer.H l 0000 root sys $includedir/FL/Fl_Text_Display.h Fl_Text_Display.H l 0000 root sys $includedir/FL/Fl_Text_Editor.h Fl_Text_Editor.H l 0000 root sys $includedir/FL/Fl_Tile.h Fl_Tile.H l 0000 root sys $includedir/FL/Fl_Tiled_Image.h Fl_Tiled_Image.H l 0000 root sys $includedir/FL/Fl_Timer.h Fl_Timer.H l 0000 root sys $includedir/FL/Fl_Toggle_Button.h Fl_Toggle_Button.H l 0000 root sys $includedir/FL/Fl_Toggle_Light_Button.h Fl_Toggle_Light_Button.H l 0000 root sys $includedir/FL/Fl_Toggle_Round_Button.h Fl_Toggle_Round_Button.H l 0000 root sys $includedir/FL/Fl_Tooltip.h Fl_Tooltip.H l 0000 root sys $includedir/FL/Fl_Tree.h Fl_Tree.H l 0000 root sys $includedir/FL/Fl_Tree_Item.h Fl_Tree_Item.H l 0000 root sys $includedir/FL/Fl_Tree_Item_Array.h Fl_Tree_Item_Array.H l 0000 root sys $includedir/FL/Fl_Tree_Prefs.h Fl_Tree_Prefs.H l 0000 root sys $includedir/FL/Fl_Valuator.h Fl_Valuator.H l 0000 root sys $includedir/FL/Fl_Value_Input.h Fl_Value_Input.H l 0000 root sys $includedir/FL/Fl_Value_Output.h Fl_Value_Output.H l 0000 root sys $includedir/FL/Fl_Value_Slider.h Fl_Value_Slider.H l 0000 root sys $includedir/FL/Fl_Widget.h Fl_Widget.H l 0000 root sys $includedir/FL/Fl_Window.h Fl_Window.H l 0000 root sys $includedir/FL/Fl_Wizard.h Fl_Wizard.H l 0000 root sys $includedir/FL/Fl_XBM_Image.h Fl_XBM_Image.H l 0000 root sys $includedir/FL/Fl_XPM_Image.h Fl_XPM_Image.H l 0000 root sys $includedir/FL/filename.h filename.H l 0000 root sys $includedir/FL/fl_ask.h fl_ask.H l 0000 root sys $includedir/FL/fl_draw.h fl_draw.H l 0000 root sys $includedir/FL/fl_message.h fl_message.H l 0000 root sys $includedir/FL/fl_show_colormap.h fl_show_colormap.H l 0000 root sys $includedir/FL/fl_show_input.h fl_show_input.H l 0000 root sys $includedir/FL/forms.h forms.H l 0000 root sys $includedir/FL/gl_draw.h gl_draw.H l 0000 root sys $includedir/FL/glut.h glut.H l 0000 root sys $includedir/FL/mac.h mac.H l 0000 root sys $includedir/FL/platform.h platform.H l 0000 root sys $includedir/FL/win32.h win32.H l 0000 root sys $includedir/FL/x.h x.H %system all # Documentation d 0555 root sys $docdir - f 0444 root sys $docdir/ documentation/html/*.gif f 0444 root sys $docdir/ documentation/html/*.html f 0444 root sys $docdir/ documentation/html/*.jpg f 0444 root sys $docdir/COPYING COPYING f 0444 root sys $docdir/CHANGES.txt CHANGES.txt # Examples d 0555 root sys $docdir/examples f 0444 root sys $docdir/examples/config.h config.h f 0444 root sys $docdir/examples/ test/*.cxx f 0444 root sys $docdir/examples/ test/*.fl f 0444 root sys $docdir/examples/ test/*.h %subpackage games %description FLTK Games %description Install fltk-games to play Block Attack!, checkers, or Sudoku on your computer. %system darwin d 0555 root sys /Applications/blocks.app - d 0555 root sys /Applications/blocks.app/Contents - f 0444 root sys /Applications/blocks.app/Contents/Info.plist test/blocks.app/Contents/Info.plist d 0555 root sys /Applications/blocks.app/Contents/MacOS - f 0555 root sys /Applications/blocks.app/Contents/MacOS/blocks test/blocks d 0555 root sys /Applications/blocks.app/Contents/Resources - f 0444 root sys /Applications/blocks.app/Contents/Resources/blocks.icns test/blocks.app/Contents/Resources/blocks.icns %postremove /bin/rm -rf /Applications/blocks.app d 0555 root sys /Applications/checkers.app - d 0555 root sys /Applications/checkers.app/Contents - f 0444 root sys /Applications/checkers.app/Contents/Info.plist test/checkers.app/Contents/Info.plist d 0555 root sys /Applications/checkers.app/Contents/MacOS - f 0555 root sys /Applications/checkers.app/Contents/MacOS/checkers test/checkers d 0555 root sys /Applications/checkers.app/Contents/Resources - f 0444 root sys /Applications/checkers.app/Contents/Resources/checkers.icns test/checkers.app/Contents/Resources/checkers.icns %postremove /bin/rm -rf /Applications/checkers.app d 0555 root sys /Applications/sudoku.app - d 0555 root sys /Applications/sudoku.app/Contents - f 0444 root sys /Applications/sudoku.app/Contents/Info.plist test/sudoku.app/Contents/Info.plist d 0555 root sys /Applications/sudoku.app/Contents/MacOS - f 0555 root sys /Applications/sudoku.app/Contents/MacOS/sudoku test/sudoku d 0555 root sys /Applications/sudoku.app/Contents/Resources - f 0444 root sys /Applications/sudoku.app/Contents/Resources/sudoku.icns test/sudoku.app/Contents/Resources/sudoku.icns %postremove /bin/rm -rf /Applications/sudoku.app %system !darwin f 0555 root sys $bindir/blocks test/blocks f 0444 root sys /usr/share/applications/blocks.desktop test/desktop/blocks.desktop f 0444 root sys /usr/share/icons/hicolor/32x32/apps/blocks.png test/desktop/blocks-32.png f 0444 root sys /usr/share/icons/hicolor/128x128/apps/blocks.png test/desktop/blocks-128.png f 0555 root sys $bindir/checkers test/checkers f 0444 root sys /usr/share/applications/checkers.desktop test/desktop/checkers.desktop f 0444 root sys /usr/share/icons/hicolor/32x32/apps/checkers.png test/desktop/checkers-32.png f 0444 root sys /usr/share/icons/hicolor/128x128/apps/checkers.png test/desktop/checkers-128.png f 0555 root sys $bindir/sudoku test/sudoku f 0444 root sys /usr/share/applications/sudoku.desktop test/desktop/sudoku.desktop f 0444 root sys /usr/share/icons/hicolor/32x32/apps/sudoku.png test/desktop/sudoku-32.png f 0444 root sys /usr/share/icons/hicolor/128x128/apps/sudoku.png test/desktop/sudoku-128.png %system all f 0444 root sys $mandir/cat6/blocks.$CAT6EXT documentation/src/blocks.$CAT6EXT f 0444 root sys $mandir/cat6/checkers.$CAT6EXT documentation/src/checkers.$CAT6EXT f 0444 root sys $mandir/cat6/sudoku.$CAT6EXT documentation/src/sudoku.$CAT6EXT f 0444 root sys $mandir/man6/blocks.6 documentation/src/blocks.man f 0444 root sys $mandir/man6/checkers.6 documentation/src/checkers.man f 0444 root sys $mandir/man6/sudoku.6 documentation/src/sudoku.man fltk-1.4.3/zlib/0000755000175000017500000000000015004135251013545 5ustar albrechtalbrechtfltk-1.4.3/zlib/gzclose.c0000644000175000017500000000123415004135251015357 0ustar albrechtalbrecht/* gzclose.c -- zlib gzclose() function * Copyright (C) 2004, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" /* gzclose() is in a separate file so that it is linked in only if it is used. That way the other gzclose functions can be used instead to avoid linking in unneeded compression or decompression routines. */ int ZEXPORT gzclose(gzFile file) { #ifndef NO_GZCOMPRESS gz_statep state; if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); #else return gzclose_r(file); #endif } fltk-1.4.3/zlib/makedepend0000644000175000017500000000225015004135251015564 0ustar albrechtalbrecht# DO NOT DELETE THIS LINE -- make depend depends on it. adler32.o: zconf.h adler32.o: zlib.h adler32.o: zutil.h compress.o: zconf.h compress.o: zlib.h crc32.o: crc32.h crc32.o: zconf.h crc32.o: zlib.h crc32.o: zutil.h deflate.o: deflate.h deflate.o: zconf.h deflate.o: zlib.h deflate.o: zutil.h gzclose.o: gzguts.h gzclose.o: zconf.h gzclose.o: zlib.h gzlib.o: gzguts.h gzlib.o: zconf.h gzlib.o: zlib.h gzread.o: gzguts.h gzread.o: zconf.h gzread.o: zlib.h gzwrite.o: gzguts.h gzwrite.o: zconf.h gzwrite.o: zlib.h infback.o: inffast.h infback.o: inffixed.h infback.o: inflate.h infback.o: inftrees.h infback.o: zconf.h infback.o: zlib.h infback.o: zutil.h inffast.o: inffast.h inffast.o: inflate.h inffast.o: inftrees.h inffast.o: zconf.h inffast.o: zlib.h inffast.o: zutil.h inflate.o: inffast.h inflate.o: inffixed.h inflate.o: inflate.h inflate.o: inftrees.h inflate.o: zconf.h inflate.o: zlib.h inflate.o: zutil.h inftrees.o: inftrees.h inftrees.o: zconf.h inftrees.o: zlib.h inftrees.o: zutil.h trees.o: deflate.h trees.o: trees.h trees.o: zconf.h trees.o: zlib.h trees.o: zutil.h uncompr.o: zconf.h uncompr.o: zlib.h zutil.o: gzguts.h zutil.o: zconf.h zutil.o: zlib.h zutil.o: zutil.h fltk-1.4.3/zlib/zutil.c0000644000175000017500000001601315004135251015061 0ustar albrechtalbrecht/* zutil.c -- target dependent utility functions for the compression library * Copyright (C) 1995-2017 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" #ifndef Z_SOLO # include "gzguts.h" #endif z_const char * const z_errmsg[10] = { (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ (z_const char *)"stream end", /* Z_STREAM_END 1 */ (z_const char *)"", /* Z_OK 0 */ (z_const char *)"file error", /* Z_ERRNO (-1) */ (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ (z_const char *)"" }; const char * ZEXPORT zlibVersion(void) { return ZLIB_VERSION; } uLong ZEXPORT zlibCompileFlags(void) { uLong flags; flags = 0; switch ((int)(sizeof(uInt))) { case 2: break; case 4: flags += 1; break; case 8: flags += 2; break; default: flags += 3; } switch ((int)(sizeof(uLong))) { case 2: break; case 4: flags += 1 << 2; break; case 8: flags += 2 << 2; break; default: flags += 3 << 2; } switch ((int)(sizeof(voidpf))) { case 2: break; case 4: flags += 1 << 4; break; case 8: flags += 2 << 4; break; default: flags += 3 << 4; } switch ((int)(sizeof(z_off_t))) { case 2: break; case 4: flags += 1 << 6; break; case 8: flags += 2 << 6; break; default: flags += 3 << 6; } #ifdef ZLIB_DEBUG flags += 1 << 8; #endif /* #if defined(ASMV) || defined(ASMINF) flags += 1 << 9; #endif */ #ifdef ZLIB_WINAPI flags += 1 << 10; #endif #ifdef BUILDFIXED flags += 1 << 12; #endif #ifdef DYNAMIC_CRC_TABLE flags += 1 << 13; #endif #ifdef NO_GZCOMPRESS flags += 1L << 16; #endif #ifdef NO_GZIP flags += 1L << 17; #endif #ifdef PKZIP_BUG_WORKAROUND flags += 1L << 20; #endif #ifdef FASTEST flags += 1L << 21; #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifdef NO_vsnprintf flags += 1L << 25; # ifdef HAS_vsprintf_void flags += 1L << 26; # endif # else # ifdef HAS_vsnprintf_void flags += 1L << 26; # endif # endif #else flags += 1L << 24; # ifdef NO_snprintf flags += 1L << 25; # ifdef HAS_sprintf_void flags += 1L << 26; # endif # else # ifdef HAS_snprintf_void flags += 1L << 26; # endif # endif #endif return flags; } #ifdef ZLIB_DEBUG #include # ifndef verbose # define verbose 0 # endif int ZLIB_INTERNAL z_verbose = verbose; void ZLIB_INTERNAL z_error(char *m) { fprintf(stderr, "%s\n", m); exit(1); } #endif /* exported to allow conversion of error code to string for compress() and * uncompress() */ const char * ZEXPORT zError(int err) { return ERR_MSG(err); } #if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 /* The older Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. */ int errno = 0; #endif #ifndef HAVE_MEMCPY void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) { if (len == 0) return; do { *dest++ = *source++; /* ??? to be unrolled */ } while (--len != 0); } int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) { uInt j; for (j = 0; j < len; j++) { if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; } return 0; } void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ } while (--len != 0); } #endif #ifndef Z_SOLO #ifdef SYS16BIT #ifdef __TURBOC__ /* Turbo C in 16-bit mode */ # define MY_ZCALLOC /* Turbo C malloc() does not allow dynamic allocation of 64K bytes * and farmalloc(64K) returns a pointer with an offset of 8, so we * must fix the pointer. Warning: the pointer must be put back to its * original form in order to free it, use zcfree(). */ #define MAX_PTR 10 /* 10*64K = 640K */ local int next_ptr = 0; typedef struct ptr_table_s { voidpf org_ptr; voidpf new_ptr; } ptr_table; local ptr_table table[MAX_PTR]; /* This table is used to remember the original form of pointers * to large buffers (64K). Such pointers are normalized with a zero offset. * Since MSDOS is not a preemptive multitasking OS, this table is not * protected from concurrent access. This hack doesn't work anyway on * a protected system like OS/2. Use Microsoft C instead. */ voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { voidpf buf; ulg bsize = (ulg)items*size; (void)opaque; /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ if (bsize < 65520L) { buf = farmalloc(bsize); if (*(ush*)&buf != 0) return buf; } else { buf = farmalloc(bsize + 16L); } if (buf == NULL || next_ptr >= MAX_PTR) return NULL; table[next_ptr].org_ptr = buf; /* Normalize the pointer to seg:0 */ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; *(ush*)&buf = 0; table[next_ptr++].new_ptr = buf; return buf; } void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { int n; (void)opaque; if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; } /* Find the original pointer */ for (n = 0; n < next_ptr; n++) { if (ptr != table[n].new_ptr) continue; farfree(table[n].org_ptr); while (++n < next_ptr) { table[n-1] = table[n]; } next_ptr--; return; } Assert(0, "zcfree: ptr not found"); } #endif /* __TURBOC__ */ #ifdef M_I86 /* Microsoft C in 16-bit mode */ # define MY_ZCALLOC #if (!defined(_MSC_VER) || (_MSC_VER <= 600)) # define _halloc halloc # define _hfree hfree #endif voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) { (void)opaque; return _halloc((long)items, size); } void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; _hfree(ptr); } #endif /* M_I86 */ #endif /* SYS16BIT */ #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC extern voidp malloc(uInt size); extern voidp calloc(uInt items, uInt size); extern void free(voidpf ptr); #endif voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { (void)opaque; return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; free(ptr); } #endif /* MY_ZCALLOC */ #endif /* !Z_SOLO */ fltk-1.4.3/zlib/inffast.c0000644000175000017500000003117415004135251015351 0ustar albrechtalbrecht/* inffast.c -- fast decoding * Copyright (C) 1995-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" #ifdef ASMINF # pragma message("Assembler code may have bugs -- use at your own risk") #else /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is available, an end-of-block is encountered, or a data error is encountered. When large enough input and output buffers are supplied to inflate(), for example, a 16K input buffer and a 64K output buffer, more than 95% of the inflate execution time is spent in this routine. Entry assumptions: state->mode == LEN strm->avail_in >= 6 strm->avail_out >= 258 start >= strm->avail_out state->bits < 8 On return, state->mode is one of: LEN -- ran out of enough output space or enough available input TYPE -- reached end of block code, inflate() to interpret next block BAD -- error in block data Notes: - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, and 13 bits for the distance extra. This totals 48 bits, or six bytes. Therefore if strm->avail_in >= 6, then there is enough input to avoid checking for available input while decoding. - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) { struct inflate_state FAR *state; z_const unsigned char FAR *in; /* local strm->next_in */ z_const unsigned char FAR *last; /* have enough input while in < last */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ #ifdef INFLATE_STRICT unsigned dmax; /* maximum distance from zlib header */ #endif unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ unsigned long hold; /* local strm->hold */ unsigned bits; /* local strm->bits */ code const FAR *lcode; /* local strm->lencode */ code const FAR *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ code const *here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ unsigned char FAR *from; /* where to copy match from */ /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; in = strm->next_in; last = in + (strm->avail_in - 5); out = strm->next_out; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT dmax = state->dmax; #endif wsize = state->wsize; whave = state->whave; wnext = state->wnext; window = state->window; hold = state->hold; bits = state->bits; lcode = state->lencode; dcode = state->distcode; lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { if (bits < 15) { hold += (unsigned long)(*in++) << bits; bits += 8; hold += (unsigned long)(*in++) << bits; bits += 8; } here = lcode + (hold & lmask); dolen: op = (unsigned)(here->bits); hold >>= op; bits -= op; op = (unsigned)(here->op); if (op == 0) { /* literal */ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here->val)); *out++ = (unsigned char)(here->val); } else if (op & 16) { /* length base */ len = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); hold >>= op; bits -= op; } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { hold += (unsigned long)(*in++) << bits; bits += 8; hold += (unsigned long)(*in++) << bits; bits += 8; } here = dcode + (hold & dmask); dodist: op = (unsigned)(here->bits); hold >>= op; bits -= op; op = (unsigned)(here->op); if (op & 16) { /* distance base */ dist = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; } } dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT if (dist > dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif hold >>= op; bits -= op; Tracevv((stderr, "inflate: distance %u\n", dist)); op = (unsigned)(out - beg); /* max distance in output */ if (dist > op) { /* see if copy from window */ op = dist - op; /* distance back in window */ if (op > whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { *out++ = 0; } while (--len); continue; } len -= op - whave; do { *out++ = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { *out++ = *from++; } while (--len); continue; } #endif } from = window; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } else if (wnext < op) { /* wrap around window */ from += wsize + wnext - op; op -= wnext; if (op < len) { /* some from end of window */ len -= op; do { *out++ = *from++; } while (--op); from = window; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } } else { /* contiguous in window */ from += wnext - op; if (op < len) { /* some from window */ len -= op; do { *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { *out++ = *from++; *out++ = *from++; *out++ = *from++; len -= 3; } if (len) { *out++ = *from++; if (len > 1) *out++ = *from++; } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ *out++ = *from++; *out++ = *from++; *out++ = *from++; len -= 3; } while (len > 2); if (len) { *out++ = *from++; if (len > 1) *out++ = *from++; } } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode + here->val + (hold & ((1U << op) - 1)); goto dodist; } else { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } } else if ((op & 64) == 0) { /* 2nd level length code */ here = lcode + here->val + (hold & ((1U << op) - 1)); goto dolen; } else if (op & 32) { /* end-of-block */ Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } else { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } } while (in < last && out < end); /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ len = bits >> 3; in -= len; bits -= len << 3; hold &= (1U << bits) - 1; /* update state and return */ strm->next_in = in; strm->next_out = out; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); state->hold = hold; state->bits = bits; return; } /* inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - Using bit fields for code structure - Different op definition to avoid & for extra bits (do & for table bits) - Three separate decoding do-loops for direct, window, and wnext == 0 - Special case for distance > 1 copies to do overlapped load and store copy - Explicit branch predictions (based on measured branch probabilities) - Deferring match copy and interspersed it with decoding subsequent codes - Swapping literal/length else - Swapping window/direct else - Larger unrolled copy loops (three is about right) - Moving len -= 3 statement into middle of loop */ #endif /* !ASMINF */ fltk-1.4.3/zlib/gzlib.c0000644000175000017500000003761615004135251015035 0ustar albrechtalbrecht/* gzlib.c -- zlib functions common to reading and writing gzip files * Copyright (C) 2004-2024 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" #if defined(_WIN32) && !defined(__BORLANDC__) # define LSEEK _lseeki64 #else #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 # define LSEEK lseek64 #else # define LSEEK lseek #endif #endif #if defined UNDER_CE /* Map the Windows error number in ERROR to a locale-dependent error message string and return a pointer to it. Typically, the values for ERROR come from GetLastError. The string pointed to shall not be modified by the application, but may be overwritten by a subsequent call to gz_strwinerror The gz_strwinerror function does not change the current setting of GetLastError. */ char ZLIB_INTERNAL *gz_strwinerror(DWORD error) { static char buf[1024]; wchar_t *msgbuf; DWORD lasterr = GetLastError(); DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error, 0, /* Default language */ (LPVOID)&msgbuf, 0, NULL); if (chars != 0) { /* If there is an \r\n appended, zap it. */ if (chars >= 2 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { chars -= 2; msgbuf[chars] = 0; } if (chars > sizeof (buf) - 1) { chars = sizeof (buf) - 1; msgbuf[chars] = 0; } wcstombs(buf, msgbuf, chars + 1); LocalFree(msgbuf); } else { sprintf(buf, "unknown win32 error (%ld)", error); } SetLastError(lasterr); return buf; } #endif /* UNDER_CE */ /* Reset gzip file state */ local void gz_reset(gz_statep state) { state->x.have = 0; /* no output data available */ if (state->mode == GZ_READ) { /* for reading ... */ state->eof = 0; /* not at end of file */ state->past = 0; /* have not read past end yet */ state->how = LOOK; /* look for gzip header */ } else /* for writing ... */ state->reset = 0; /* no deflateReset pending */ state->seek = 0; /* no seek request pending */ gz_error(state, Z_OK, NULL); /* clear error */ state->x.pos = 0; /* no uncompressed data yet */ state->strm.avail_in = 0; /* no input data yet */ } /* Open a gzip file either by name or file descriptor. */ local gzFile gz_open(const void *path, int fd, const char *mode) { gz_statep state; z_size_t len; int oflag; #ifdef O_CLOEXEC int cloexec = 0; #endif #ifdef O_EXCL int exclusive = 0; #endif /* check input */ if (path == NULL) return NULL; /* allocate gzFile structure to return */ state = (gz_statep)malloc(sizeof(gz_state)); if (state == NULL) return NULL; state->size = 0; /* no buffers allocated yet */ state->want = GZBUFSIZE; /* requested buffer size */ state->msg = NULL; /* no error message yet */ /* interpret mode */ state->mode = GZ_NONE; state->level = Z_DEFAULT_COMPRESSION; state->strategy = Z_DEFAULT_STRATEGY; state->direct = 0; while (*mode) { if (*mode >= '0' && *mode <= '9') state->level = *mode - '0'; else switch (*mode) { case 'r': state->mode = GZ_READ; break; #ifndef NO_GZCOMPRESS case 'w': state->mode = GZ_WRITE; break; case 'a': state->mode = GZ_APPEND; break; #endif case '+': /* can't read and write at the same time */ free(state); return NULL; case 'b': /* ignore -- will request binary anyway */ break; #ifdef O_CLOEXEC case 'e': cloexec = 1; break; #endif #ifdef O_EXCL case 'x': exclusive = 1; break; #endif case 'f': state->strategy = Z_FILTERED; break; case 'h': state->strategy = Z_HUFFMAN_ONLY; break; case 'R': state->strategy = Z_RLE; break; case 'F': state->strategy = Z_FIXED; break; case 'T': state->direct = 1; break; default: /* could consider as an error, but just ignore */ ; } mode++; } /* must provide an "r", "w", or "a" */ if (state->mode == GZ_NONE) { free(state); return NULL; } /* can't force transparent read */ if (state->mode == GZ_READ) { if (state->direct) { free(state); return NULL; } state->direct = 1; /* for empty file */ } /* save the path name for error messages */ #ifdef WIDECHAR if (fd == -2) { len = wcstombs(NULL, path, 0); if (len == (z_size_t)-1) len = 0; } else #endif len = strlen((const char *)path); state->path = (char *)malloc(len + 1); if (state->path == NULL) { free(state); return NULL; } #ifdef WIDECHAR if (fd == -2) if (len) wcstombs(state->path, path, len + 1); else *(state->path) = 0; else #endif #if !defined(NO_snprintf) && !defined(NO_vsnprintf) (void)snprintf(state->path, len + 1, "%s", (const char *)path); #else strcpy(state->path, path); #endif /* compute the flags for open() */ oflag = #ifdef O_LARGEFILE O_LARGEFILE | #endif #ifdef O_BINARY O_BINARY | #endif #ifdef O_CLOEXEC (cloexec ? O_CLOEXEC : 0) | #endif (state->mode == GZ_READ ? O_RDONLY : (O_WRONLY | O_CREAT | #ifdef O_EXCL (exclusive ? O_EXCL : 0) | #endif (state->mode == GZ_WRITE ? O_TRUNC : O_APPEND))); /* open the file with the appropriate flags (or just use fd) */ state->fd = fd > -1 ? fd : ( #ifdef WIDECHAR fd == -2 ? _wopen(path, oflag, 0666) : #endif open((const char *)path, oflag, 0666)); if (state->fd == -1) { free(state->path); free(state); return NULL; } if (state->mode == GZ_APPEND) { LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ state->mode = GZ_WRITE; /* simplify later checks */ } /* save the current position for rewinding (only if reading) */ if (state->mode == GZ_READ) { state->start = LSEEK(state->fd, 0, SEEK_CUR); if (state->start == -1) state->start = 0; } /* initialize stream */ gz_reset(state); /* return stream */ return (gzFile)state; } /* -- see zlib.h -- */ gzFile ZEXPORT gzopen(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ gzFile ZEXPORT gzopen64(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ gzFile ZEXPORT gzdopen(int fd, const char *mode) { char *path; /* identifier for error messages */ gzFile gz; if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) return NULL; #if !defined(NO_snprintf) && !defined(NO_vsnprintf) (void)snprintf(path, 7 + 3 * sizeof(int), "", fd); #else sprintf(path, "", fd); /* for debugging */ #endif gz = gz_open(path, fd, mode); free(path); return gz; } /* -- see zlib.h -- */ #ifdef WIDECHAR gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) { return gz_open(path, -2, mode); } #endif /* -- see zlib.h -- */ int ZEXPORT gzbuffer(gzFile file, unsigned size) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* make sure we haven't already allocated memory */ if (state->size != 0) return -1; /* check and set requested size */ if ((size << 1) < size) return -1; /* need to be able to double it */ if (size < 8) size = 8; /* needed to behave well with flushing */ state->want = size; return 0; } /* -- see zlib.h -- */ int ZEXPORT gzrewind(gzFile file) { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* back up and start over */ if (LSEEK(state->fd, state->start, SEEK_SET) == -1) return -1; gz_reset(state); return 0; } /* -- see zlib.h -- */ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { unsigned n; z_off64_t ret; gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* check that there's no error */ if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; /* can only seek from start or relative to current position */ if (whence != SEEK_SET && whence != SEEK_CUR) return -1; /* normalize offset to a SEEK_CUR specification */ if (whence == SEEK_SET) offset -= state->x.pos; else if (state->seek) offset += state->skip; state->seek = 0; /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && state->x.pos + offset >= 0) { ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR); if (ret == -1) return -1; state->x.have = 0; state->eof = 0; state->past = 0; state->seek = 0; gz_error(state, Z_OK, NULL); state->strm.avail_in = 0; state->x.pos += offset; return state->x.pos; } /* calculate skip amount, rewinding if needed for back seek when reading */ if (offset < 0) { if (state->mode != GZ_READ) /* writing -- can't go backwards */ return -1; offset += state->x.pos; if (offset < 0) /* before start of file! */ return -1; if (gzrewind(file) == -1) /* rewind, then skip to offset */ return -1; } /* if reading, skip what's in output buffer (one less gzgetc() check) */ if (state->mode == GZ_READ) { n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? (unsigned)offset : state->x.have; state->x.have -= n; state->x.next += n; state->x.pos += n; offset -= n; } /* request skip (if not zero) */ if (offset) { state->seek = 1; state->skip = offset; } return state->x.pos + offset; } /* -- see zlib.h -- */ z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) { z_off64_t ret; ret = gzseek64(file, (z_off64_t)offset, whence); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ z_off64_t ZEXPORT gztell64(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* return position */ return state->x.pos + (state->seek ? state->skip : 0); } /* -- see zlib.h -- */ z_off_t ZEXPORT gztell(gzFile file) { z_off64_t ret; ret = gztell64(file); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ z_off64_t ZEXPORT gzoffset64(gzFile file) { z_off64_t offset; gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* compute and return effective offset in file */ offset = LSEEK(state->fd, 0, SEEK_CUR); if (offset == -1) return -1; if (state->mode == GZ_READ) /* reading */ offset -= state->strm.avail_in; /* don't count buffered input */ return offset; } /* -- see zlib.h -- */ z_off_t ZEXPORT gzoffset(gzFile file) { z_off64_t ret; ret = gzoffset64(file); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ int ZEXPORT gzeof(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return 0; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return 0; /* return end-of-file state */ return state->mode == GZ_READ ? state->past : 0; } /* -- see zlib.h -- */ const char * ZEXPORT gzerror(gzFile file, int *errnum) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return NULL; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return NULL; /* return error information */ if (errnum != NULL) *errnum = state->err; return state->err == Z_MEM_ERROR ? "out of memory" : (state->msg == NULL ? "" : state->msg); } /* -- see zlib.h -- */ void ZEXPORT gzclearerr(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return; /* clear error and end-of-file */ if (state->mode == GZ_READ) { state->eof = 0; state->past = 0; } gz_error(state, Z_OK, NULL); } /* Create an error message in allocated memory and set state->err and state->msg accordingly. Free any previous error message already there. Do not try to free or allocate space if the error is Z_MEM_ERROR (out of memory). Simply save the error message as a static string. If there is an allocation failure constructing the error message, then convert the error to out of memory. */ void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) { /* free previously allocated message and clear */ if (state->msg != NULL) { if (state->err != Z_MEM_ERROR) free(state->msg); state->msg = NULL; } /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ if (err != Z_OK && err != Z_BUF_ERROR) state->x.have = 0; /* set error code, and if no message, then done */ state->err = err; if (msg == NULL) return; /* for an out of memory error, return literal string when requested */ if (err == Z_MEM_ERROR) return; /* construct error message with path */ if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { state->err = Z_MEM_ERROR; return; } #if !defined(NO_snprintf) && !defined(NO_vsnprintf) (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, "%s%s%s", state->path, ": ", msg); #else strcpy(state->msg, state->path); strcat(state->msg, ": "); strcat(state->msg, msg); #endif } /* portably return maximum value for an int (when limits.h presumed not available) -- we need to do this to cover cases where 2's complement not used, since C standard permits 1's complement and sign-bit representations, otherwise we could just use ((unsigned)-1) >> 1 */ unsigned ZLIB_INTERNAL gz_intmax(void) { #ifdef INT_MAX return INT_MAX; #else unsigned p = 1, q; do { q = p; p <<= 1; p++; } while (p > q); return q >> 1; #endif } fltk-1.4.3/zlib/zlib.h0000644000175000017500000027524615004135251014676 0ustar albrechtalbrecht/* zlib.h -- interface of the 'zlib' general purpose compression library version 1.3.1, January 22nd, 2024 Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef ZLIB_H #define ZLIB_H #include "zconf.h" #ifdef __cplusplus extern "C" { #endif #define ZLIB_VERSION "1.3.1" #define ZLIB_VERNUM 0x1310 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 3 #define ZLIB_VER_REVISION 1 #define ZLIB_VER_SUBREVISION 0 /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms will be added later and will have the same stream interface. Compression can be done in a single step if the buffers are large enough, or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. The compressed data format used by default by the in-memory functions is the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped around a deflate stream, which is itself documented in RFC 1951. The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. This library can optionally read and write gzip and raw deflate streams in memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- file compression on file systems, has a larger header than zlib to maintain directory information, and uses a different, slower check method than zlib. The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in the case of corrupted input. */ typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size); typedef void (*free_func)(voidpf opaque, voidpf address); struct internal_state; typedef struct z_stream_s { z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total number of input bytes read so far */ Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total number of bytes output so far */ z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: binary or text for deflate, or the decoding state for inflate */ uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* gzip header information passed to and from zlib routines. See RFC 1952 for more details on the meanings of these fields. */ typedef struct gz_header_s { int text; /* true if compressed data believed to be text */ uLong time; /* modification time */ int xflags; /* extra flags (not used when writing a gzip file) */ int os; /* operating system */ Bytef *extra; /* pointer to extra field or Z_NULL if none */ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ uInt extra_max; /* space at extra (only when reading header) */ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ uInt name_max; /* space at name (only when reading header) */ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ uInt comm_max; /* space at comment (only when reading header) */ int hcrc; /* true if there was or will be a header crc */ int done; /* true when done reading gzip header (not used when writing a gzip file) */ } gz_header; typedef gz_header FAR *gz_headerp; /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The opaque value provided by the application will be passed as the first parameter for calls of zalloc and zfree. This can be useful for custom memory management. The compression library attaches no meaning to the opaque value. zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be thread safe. In that case, zlib is thread-safe. When zalloc and zfree are Z_NULL on entry to the initialization function, they are set to internal routines that use the standard library functions malloc() and free(). On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers returned by zalloc for objects of exactly 65536 bytes *must* have their offset normalized to zero. The default allocation function provided by this library ensures this (see zutil.c). To reduce memory requirements and avoid any allocation of 64K objects, at the expense of compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use by the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 #define Z_BLOCK 5 #define Z_TREES 6 /* Allowed flush values; see deflate() and inflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative values * are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_RLE 3 #define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 /* Possible values of the data_type field for deflate() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ /* basic functions */ ZEXTERN const char * ZEXPORT zlibVersion(void); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions. total_in, total_out, adler, and msg are initialized. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level, or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - Generate more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary. Some output may be provided even if flush is zero. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. See deflatePending(), which can be used if desired to determine whether or not there is more output in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to maximize compression. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular avail_in is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. This completes the current deflate block and follows it with an empty stored block that is three bits plus filler bits to the next byte, followed by four bytes (00 00 ff ff). If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the output buffer, but the output is not aligned to a byte boundary. All of the input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output in order for the decompressor to finish the block before the empty fixed codes block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to seven bits of the current block are held to be written as the next byte after the next deflate block is completed. In this case, the decompressor may not be provided enough bits at this point in order to complete decompression of the data provided so far to the compressor. It may need to wait for the next block to be emitted. This is for advanced applications that need to control the emission of deflate blocks. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out is greater than six when the flush marker begins, in order to avoid repeated flush markers upon calling deflate() again when avail_out == 0. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd. Z_FINISH can be used in the first deflate call after deflateInit if all the compression is to be done in a single step. In order to complete in one call, avail_out must be at least the value returned by deflateBound (see below). Then deflate is guaranteed to return Z_STREAM_END. If not enough output space is provided, deflate will not return Z_STREAM_END, and it must be called again as described above. deflate() sets strm->adler to the Adler-32 checksum of all input read so far (that is, total_in bytes). If a gzip stream is being generated, then strm->adler will be the CRC-32 checksum of the input read so far. (See deflateInit2 below.) deflate() may update strm->data_type if it can make a good guess about the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was Z_NULL or the state was inadvertently written over by the application), or Z_BUF_ERROR if no progress is possible (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and deflate() can be called again with more input and more output space to continue compressing. */ ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded). In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* ZEXTERN int ZEXPORT inflateInit(z_streamp strm); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. In the current version of inflate, the provided input is not read or consumed. The allocation of a sliding window will be deferred to the first call of inflate (if the decompression does not complete on the first call). If zalloc and zfree are set to Z_NULL, inflateInit updates them to use default allocation functions. total_in, total_out, adler, and msg are initialized. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit does not perform any decompression. Actual decompression will be done by inflate(). So next_in, and avail_in, next_out, and avail_out are unused and unchanged. The current implementation of inflateInit() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. inflate performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), then next_in and avail_in are updated accordingly, and processing will resume at this point for the next call of inflate(). - Generate more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. If the caller of inflate() does not provide both available input and available output space, it is possible that there will be no progress made. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much output as possible to the output buffer. Z_BLOCK requests that inflate() stop if and when it gets to the next deflate block boundary. When decoding the zlib or gzip format, this will cause inflate() to return immediately after the header and before the first block. When doing a raw inflate, inflate() will go ahead and process the first block, and will return when it gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. To assist in this, on return inflate() always sets strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or decoding the complete header up to just before the first byte of the deflate stream. The end-of-block will not be indicated until all of the uncompressed data from that block has been written to strm->next_out. The number of unused bits may in general be greater than seven, except when bit 7 of data_type is set, in which case the number of unused bits will be less than eight. data_type is set as noted here every time inflate() returns for all flush options, and so can be used to determine the amount of currently consumed input in bits. The Z_TREES option behaves as Z_BLOCK does, but it also returns when the end of each deflate block header is reached, before any actual data in that block is decoded. This allows the caller to determine the length of the deflate block header for later use in random access within a deflate block. 256 is added to the value of strm->data_type when inflate() returns immediately after reaching the end of the deflate block header. inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all of the uncompressed data for the operation to complete. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The use of Z_FINISH is not required to perform an inflation in one step. However it may be used to inform inflate that a faster approach can be used for the single inflate() call. Z_FINISH also informs inflate to not maintain a sliding window if the stream completes, which reduces inflate's memory footprint. If the stream does not complete, either because not all of the stream is provided or not enough output space is provided, then a sliding window will be allocated and inflate() can be called again to continue the operation as if Z_NO_FLUSH had been used. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the first call. So the effects of the flush parameter in this implementation are on the return value of inflate() as noted below, when inflate() returns early when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of memory for a sliding window when Z_FINISH is used. If a preset dictionary is needed after this call (see inflateSetDictionary below), inflate sets strm->adler to the Adler-32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed Adler-32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip header is not retained unless inflateGetHeader() is used. When processing gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output produced so far. The CRC-32 is checked against the gzip trailer, as is the uncompressed length, modulo 2^32. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check value, in which case strm->msg points to a string with a more specific error), Z_STREAM_ERROR if the stream structure was inconsistent (for example next_in or next_out was Z_NULL, or the state was inadvertently written over by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no progress was possible or if there was not enough room in the output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial recovery of the data is to be attempted. */ ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state was inconsistent. */ /* Advanced functions */ /* The following functions are needed only in some special applications. */ /* ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy); This is another version of deflateInit with more compression options. The fields zalloc, zfree and opaque must be initialized before by the caller. The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. Larger values of this parameter result in better compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. For the current implementation of deflate(), a windowBits value of 8 (a window size of 256 bytes) is not supported. As a result, a request for 8 will result in 9 (a 512-byte window). In that case, providing 8 to inflateInit2() will result in an error when the zlib header with 9 is checked against the initialization of inflate(). The remedy is to not use 8 with deflateInit2() with this initialization, or at least in that case use 9 with inflateInit2(). windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data with no zlib header or trailer, and will not compute a check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no header crc, and the operating system will be set to the appropriate value, if the operating system was determined at compile time. If a gzip stream is being written, strm->adler is a CRC-32 instead of an Adler-32. For raw deflate or gzip encoding, a request for a 256-byte window is rejected as invalid, since only the zlib header provides a means of transmitting the window size to the decompressor. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory for optimal speed. The default value is 8. See zconf.h for total memory usage as a function of windowBits and memLevel. The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no string match), or Z_RLE to limit match distances to one (run-length encoding). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of Z_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit2 does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. When using the zlib format, this function must be called immediately after deflateInit, deflateInit2 or deflateReset, and before any call of deflate. When doing raw deflate, this function must be called either before any call of deflate, or immediately after the completion of a deflate block, i.e. after all input has been consumed and all output has been delivered when using any of the flush options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The compressor and decompressor must use exactly the same dictionary (see inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size provided in deflateInit or deflateInit2. Thus the strings most likely to be useful should be put at the end of the dictionary, not at the front. In addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine which dictionary has been used by the compressor. (The Adler-32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the Adler-32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream or if not at a block boundary for raw deflate). deflateSetDictionary does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary, uInt *dictLength); /* Returns the sliding dictionary being maintained by deflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If deflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. Similarly, if dictLength is Z_NULL, then it is not set. deflateGetDictionary() may return a length less than the window size, even when more than the window size in input has been provided. It may return up to 258 bytes less in that case, due to how zlib's implementation of deflate manages the sliding window and lookahead for matches, where matches can be up to 258 bytes long. If the application needs the last window-size bytes of input, then that would need to be saved by the application outside of zlib. deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. */ ZEXTERN int ZEXPORT deflateCopy(z_streamp dest, z_streamp source); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal compression state which can be quite large, so this strategy is slow and can consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT deflateReset(z_streamp strm); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate the internal compression state. The stream will leave the compression level and any other attributes that may have been set unchanged. total_in, total_out, adler, and msg are initialized. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT deflateParams(z_streamp strm, int level, int strategy); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression approach (which is a function of the level) or the strategy is changed, and if there have been any deflate() calls since the state was initialized or reset, then the input available so far is compressed with the old level and strategy using deflate(strm, Z_BLOCK). There are three approaches for the compression levels 0, 1..3, and 4..9 respectively. The new level and strategy will take effect at the next call of deflate(). If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does not have enough output space to complete, then the parameter change will not take effect. In this case, deflateParams() can be called again with the same parameters and more output space to try again. In order to assure a change in the parameters on the first try, the deflate stream should be flushed using deflate() with Z_BLOCK or other flush request until strm.avail_out is not zero, before calling deflateParams(). Then no more input data should be provided before the deflateParams() call. If this is done, the old level and strategy will be applied to the data compressed before deflateParams(), and the new level and strategy will be applied to the data compressed after deflateParams(). deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if there was not enough output space to complete the compression of the available input data before a change in the strategy or approach. Note that in the case of a Z_BUF_ERROR, the parameters are not changed. A return value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be retried with more output space. */ ZEXTERN int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for searching for the best matching string, and even then only by the most fanatic optimizer trying to squeeze out the last compressed bit for their specific input data. Read the deflate.c source code for the meaning of the max_lazy, good_length, nice_length, and max_chain parameters. deflateTune() can be called after deflateInit() or deflateInit2(), and returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be called before deflate(). If that first deflate() call is provided the sourceLen input bytes, an output buffer allocated to the size returned by deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed to return Z_STREAM_END. Note that it is possible for the compressed size to be larger than the value returned by deflateBound() if flush options other than Z_FINISH or Z_NO_FLUSH are used. */ ZEXTERN int ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits); /* deflatePending() returns the number of bytes and bits of output that have been generated, but not yet provided in the available output. The bytes not provided would be due to the available output space having being consumed. The number of bits of output not provided are between 0 and 7, where they await more bits to join them in order to fill out a full byte. If pending or bits are Z_NULL, then those values are not set. deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflatePrime(z_streamp strm, int bits, int value); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits leftover from a previous deflate stream when appending to it. As such, this function can only be used for raw deflate, and must be used before the first deflate() call after a deflateInit2() or deflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the output. deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called after deflateInit2() or deflateReset() and before the first call of deflate(). The text, time, os, extra field, name, and comment information in the provided gz_header structure are written to the gzip header (xflag is ignored -- the extra flags are set according to the compression level). The caller must assure that, if not Z_NULL, name and comment are terminated with a zero byte, and that if extra is not Z_NULL, that extra_len bytes are available there. If hcrc is true, a gzip header crc is included. Note that the current versions of the command-line version of gzip (up through version 1.3.x) do not support header crc's, and will report that it is a "multi-part gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, the time set to zero, and os set to the current operating system, with no extra, name, or comment fields. The gzip header is returned to the default state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateInit2(z_streamp strm, int windowBits); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. The default value is 15 if inflateInit is used instead. windowBits must be greater than or equal to the windowBits value provided to deflateInit2() while compressing, or it must be equal to 15 if deflateInit2() was not used. If a compressed stream with a larger window size is given as input, inflate() will return with the error code Z_DATA_ERROR instead of trying to allocate a larger window. windowBits can also be zero to request that inflate use the window size in the zlib header of the compressed stream. windowBits can also be -8..-15 for raw inflate. In this case, -windowBits determines the window size. inflate() will then process raw deflate data, not looking for a zlib or gzip header, not generating a check value, and not looking for any check values for comparison at the end of the stream. This is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is recommended that a check value such as an Adler-32 or a CRC-32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. windowBits can also be greater than 15 for optional gzip decoding. Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see below), inflate() will *not* automatically decode concatenated gzip members. inflate() will return Z_STREAM_END at the end of the gzip member. The state would need to be reset to continue decoding a subsequent gzip member. This *must* be done if there is more data after a gzip member, in order for the decompression to be compliant with the gzip standard (RFC 1952). inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit2 does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit2() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the Adler-32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called at any time to set the dictionary. If the provided dictionary is smaller than the window and there is already data in the window, then the provided dictionary will amend what's there. The application must insure that the dictionary that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary, uInt *dictLength); /* Returns the sliding dictionary being maintained by inflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If inflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. Similarly, if dictLength is Z_NULL, then it is not set. inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. */ ZEXTERN int ZEXPORT inflateSync(z_streamp strm); /* Skips invalid compressed data until a possible full flush point (see above for the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. inflateSync searches for a 00 00 FF FF pattern in the compressed data. All full flush points have this pattern, but not all occurrences of this pattern are full flush points. inflateSync returns Z_OK if a possible full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the success case, the application may save the current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, z_streamp source); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when randomly accessing a large stream. The first pass through the stream can periodically record the inflate state, allowing restarting inflate at those points when randomly accessing the stream. inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT inflateReset(z_streamp strm); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. total_in, total_out, adler, and msg are initialized. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT inflateReset2(z_streamp strm, int windowBits); /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted the same as it is for inflateInit2. If the window size is changed, then the memory allocated for the window is freed, and the window will be reallocated by inflate() if needed. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if the windowBits parameter is invalid. */ ZEXTERN int ZEXPORT inflatePrime(z_streamp strm, int bits, int value); /* This function inserts bits in the inflate input stream. The intent is that this function is used to start inflating at a bit position in the middle of a byte. The provided bits will be used before any bytes are used from next_in. This function should only be used with raw inflate, and should be used before the first inflate() call after inflateInit2() or inflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the input. If bits is negative, then the input stream bit buffer is emptied. Then inflatePrime() can be called again to put bits in the buffer. This is used to clear out bits leftover after feeding inflate a block description prior to feeding inflate codes. inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN long ZEXPORT inflateMark(z_streamp strm); /* This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the return value down 16 bits. If the upper value is -1 and the lower value is zero, then inflate() is currently decoding information outside of a block. If the upper value is -1 and the lower value is non-zero, then inflate is in the middle of a stored block, with the lower value equaling the number of bytes from the input remaining to copy. If the upper value is not -1, then it is the number of bits back from the current bit position in the input of the code (literal or length/distance pair) currently being processed. In that case the lower value is the number of bytes already emitted for that code. A code is being processed if inflate is waiting for more input to complete decoding of the code, or if it has completed decoding but is waiting for more output space to write the literal or match data. inflateMark() is used to mark locations in the input data for random access, which may be at bit positions, and to note those cases where the output of a code may span boundaries of random access blocks. The current location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. inflateMark returns the value noted above, or -65536 if the provided source stream state was inconsistent. */ ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after inflateInit2() or inflateReset(), and before the first call of inflate(). As inflate() processes the gzip stream, head->done is zero until the header is completed, at which time head->done is set to one. If a zlib stream is being decoded, then head->done is set to -1 to indicate that there will be no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be used to force inflate() to return immediately after header processing is complete and before any actual data is decompressed. The text, time, xflags, and os fields are filled in with the gzip header contents. hcrc is set to true if there is a header CRC. (The header CRC was valid if done is set to one.) If extra is not Z_NULL, then extra_max contains the maximum number of bytes to write to extra. Once done is true, extra_len contains the actual extra field length, and extra contains the extra field, or that field truncated if extra_max is less than extra_len. If name is not Z_NULL, then up to name_max characters are written there, terminated with a zero unless the length is greater than name_max. If comment is not Z_NULL, then up to comm_max characters are written there, terminated with a zero unless the length is greater than comm_max. When any of extra, name, or comment are not Z_NULL and the respective field is not present in the header, then that field is set to Z_NULL to signal its absence. This allows the use of deflateSetHeader() with the returned structure to duplicate the header. However if those fields are set to allocated memory, then the application will need to save those pointers elsewhere so that they can be eventually freed. If inflateGetHeader is not used, then the header information is simply discarded. The header is always checked for validity, including the header CRC if present. inflateReset() will reset the process to discard the header information. The application would need to call inflateGetHeader() again to retrieve the header from the next gzip stream. inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits, unsigned char FAR *window); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized before the call. If zalloc and zfree are Z_NULL, then the default library- derived memory allocation routines are used. windowBits is the base two logarithm of the window size, in the range 8..15. window is a caller supplied buffer of that size. Except for special applications where it is assured that deflate was used with small window sizes, windowBits must be 15 and a 32K byte window must be supplied to be able to decompress general deflate streams. See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ typedef unsigned (*in_func)(void FAR *, z_const unsigned char FAR * FAR *); typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned); ZEXTERN int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc); /* inflateBack() does a raw inflate with a single call using a call-back interface for input and output. This is potentially more efficient than inflate() for file i/o applications, in that it avoids copying between the output and the sliding window by simply making the window itself the output buffer. inflate() can be faster on modern CPUs when used with large buffers. inflateBack() trusts the application to not change the output buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. inflateBack() may then be used multiple times to inflate a complete, raw deflate stream with each call. inflateBackEnd() is then called to free the allocated state. A raw deflate stream is one with no zlib or gzip header or trailer. This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only the raw deflate stream to decompress. This is different from the default behavior of inflate(), which expects a zlib header and trailer around the deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those routines until it reads a complete deflate stream and writes out all of the uncompressed data, or until it encounters an error. The function's parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If there is no input available, in() must return zero -- buf is ignored in that case -- and inflateBack() will return a buffer error. inflateBack() will call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() should return zero on success, or non-zero on failure. If out() returns non-zero, inflateBack() will return with an error. Neither in() nor out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). For convenience, inflateBack() can be provided input on the first call by setting strm->next_in and strm->avail_in. If that input is exhausted, then in() will be called. Therefore strm->next_in must be initialized before calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in must also be initialized, and then if strm->avail_in is not zero, input will initially be taken from strm->next_in[0 .. strm->avail_in - 1]. The in_desc and out_desc parameters of inflateBack() is passed as the first parameter of in() and out() respectively when they are called. These descriptors can be optionally used to pass any information that the caller- supplied in() and out() functions need to do their job. On return, inflateBack() will set strm->next_in and strm->avail_in to pass back any unused input that was provided by the last in() call. The return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR if in() or out() returned an error, Z_DATA_ERROR if there was a format error in the deflate stream (in which case strm->msg is set to indicate the nature of the error), or Z_STREAM_ERROR if the stream was not properly initialized. In the case of Z_BUF_ERROR, an input or output error can be distinguished using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm); /* All memory allocated by inflateBackInit() is freed. inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream state was inconsistent. */ ZEXTERN uLong ZEXPORT zlibCompileFlags(void); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: 1.0: size of uInt 3.2: size of uLong 5.4: size of voidpf (pointer) 7.6: size of z_off_t Compiler, assembler, and debug options: 8: ZLIB_DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) One-time table building (smaller code, but not thread-safe if true): 12: BUILDFIXED -- build static block decoding tables when needed 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed 14,15: 0 (reserved) Library content (indicates missing functionality): 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking deflate code when not needed) 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect and decode gzip streams (to avoid linking crc code) 18-19: 0 (reserved) Operation variations (changes in library functionality): 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate 21: FASTEST -- deflate algorithm with only one, lowest compression level 22,23: 0 (reserved) The sprintf variant used by gzprintf (zero is best): 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! 26: 0 = returns value, 1 = void -- 1 means inferred string length returned Remainder: 27-31: 0 (reserved) */ #ifndef Z_SOLO /* utility functions */ /* The following utility functions are implemented on top of the basic stream-oriented functions. To simplify the interface, some default options are assumed (compression level and memory usage, standard memory allocation functions). The source code of these utility functions can be modified if you need special options. */ ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed data. compress() is equivalent to compress2() with a level parameter of Z_DEFAULT_COMPRESSION. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed data. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the uncompressed data. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In the case where there is not enough room, uncompress() will fill the output buffer with the uncompressed data up to that point. */ ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source, uLong *sourceLen); /* Same as uncompress, except that sourceLen is a pointer, where the length of the source is *sourceLen. On return, *sourceLen is the number of source bytes consumed. */ /* gzip file access functions */ /* This library supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio, using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. */ typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode); Open the gzip (.gz) file at path for reading and decompressing, or compressing and writing. The mode parameter is as in fopen ("rb" or "wb") but can also include a compression level ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of deflateInit2 for more information about the strategy parameter.) 'T' will request transparent writing or appending with no compression and not using the gzip format. "a" can be used instead of "w" to request that the gzip stream that will be written be appended to the file. "+" will result in an error, since reading and writing to the same gzip file is not supported. The addition of "x" when writing will create the file exclusively, which fails if the file already exists. On systems that support it, the addition of "e" when reading or writing will set the flag to close the file on an execve() call. These functions, as well as gzip, will read and decode a sequence of gzip streams in a file. The append function of gzopen() can be used to create such a file. (Also see gzflush() for another way to do this.) When appending, gzopen does not test whether the file begins with a gzip stream, nor does it look for the end of the gzip streams to begin appending. gzopen will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this case gzread will directly read from the file without decompression. When reading, this will be detected automatically by looking for the magic two- byte gzip header. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). errno can be checked to determine if the reason gzopen failed was that the file could not be opened. */ ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode); /* Associate a gzFile with the file descriptor fd. File descriptors are obtained from calls like open, dup, creat, pipe or fileno (if the file has been previously opened with fopen). The mode parameter is as in gzopen. The next call of gzclose on the returned gzFile will also close the file descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since gzdopen does not close fd if it fails. If you are using fileno() to get the file descriptor from a FILE *, then you will have to use dup() to avoid double-close()ing the file descriptor. Both gzclose() and fclose() will close the associated file descriptor, so they need to have different file descriptors. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided), or if fd is -1. The file descriptor is not used until the next gz* read, write, seek, or close operation, so gzdopen will not detect if fd is invalid (unless fd is -1). */ ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size); /* Set the internal buffer size used by this library's functions for file to size. The default buffer size is 8192 bytes. This function must be called after gzopen() or gzdopen(), and before any other calls that read or write the file. The buffer memory allocation is always deferred to the first read or write. Three times that size in buffer space is allocated. A larger buffer size of, for example, 64K or 128K bytes will noticeably increase the speed of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). gzbuffer() returns 0 on success, or -1 on failure, such as being called too late. */ ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy); /* Dynamically update the compression level and strategy for file. See the description of deflateInit2 for the meaning of these parameters. Previously provided data is flushed before applying the parameter changes. gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not opened for writing, Z_ERRNO if there is an error writing the flushed data, or Z_MEM_ERROR if there is a memory allocation error. */ ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); /* Read and decompress up to len uncompressed bytes from file into buf. If the input file is not in gzip format, gzread copies the given number of bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue to read, looking for another gzip stream. Any number of gzip streams may be concatenated in the input file, and will all be decompressed by gzread(). If something other than a gzip stream is encountered after a gzip stream, that remaining trailing garbage is ignored (and no error is returned). gzread can be used to read a gzip file that is being concurrently written. Upon reaching the end of the input, gzread will return with the available data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then gzclearerr can be used to clear the end of file indicator in order to permit gzread to be tried again. Z_OK indicates that a gzip stream was completed on the last gzread. Z_BUF_ERROR indicates that the input file ended in the middle of a gzip stream. Note that gzread does not return -1 in the event of an incomplete gzip stream. This error is deferred until gzclose(), which will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip stream. Alternatively, gzerror can be used before gzclose to detect this case. gzread returns the number of uncompressed bytes actually read, less than len for end of file, or -1 for error. If len is too large to fit in an int, then nothing is read, -1 is returned, and the error state is set to Z_STREAM_ERROR. */ ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file); /* Read and decompress up to nitems items of size size from file into buf, otherwise operating as gzread() does. This duplicates the interface of stdio's fread(), with size_t request and return types. If the library defines size_t, then z_size_t is identical to size_t. If not, then z_size_t is an unsigned integer type that can contain a pointer. gzfread() returns the number of full items read of size size, or zero if the end of the file was reached and a full item could not be read, or if there was an error. gzerror() must be consulted if zero is returned in order to determine if there was an error. If the multiplication of size and nitems overflows, i.e. the product does not fit in a z_size_t, then nothing is read, zero is returned, and the error state is set to Z_STREAM_ERROR. In the event that the end of file is reached and only a partial item is available at the end, i.e. the remaining uncompressed data length is not a multiple of size, then the final partial item is nevertheless read into buf and the end-of-file flag is set. The length of the partial item read is not provided, but could be inferred from the result of gztell(). This behavior is the same as the behavior of fread() implementations in common libraries, but it prevents the direct use of gzfread() to read a concurrently written file, resetting and retrying on end-of-file, when size is not 1. */ ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len); /* Compress and write the len uncompressed bytes at buf to file. gzwrite returns the number of uncompressed bytes written or 0 in case of error. */ ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems, gzFile file); /* Compress and write nitems items of size size from buf to file, duplicating the interface of stdio's fwrite(), with size_t request and return types. If the library defines size_t, then z_size_t is identical to size_t. If not, then z_size_t is an unsigned integer type that can contain a pointer. gzfwrite() returns the number of full items written of size size, or zero if there was an error. If the multiplication of size and nitems overflows, i.e. the product does not fit in a z_size_t, then nothing is written, zero is returned, and the error state is set to Z_STREAM_ERROR. */ ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...); /* Convert, format, compress, and write the arguments (...) to file under control of the string format, as in fprintf. gzprintf returns the number of uncompressed bytes actually written, or a negative zlib error code in case of error. The number of uncompressed bytes written is limited to 8191, or one less than the buffer size given to gzbuffer(). The caller should assure that this limit is not exceeded. If it is exceeded, then gzprintf() will return an error (0) with nothing written. In this case, there may also be a buffer overflow with unpredictable consequences, which is possible only if zlib was compiled with the insecure functions sprintf() or vsprintf(), because the secure snprintf() or vsnprintf() functions were not available. This can be determined using zlibCompileFlags(). */ ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s); /* Compress and write the given null-terminated string s to file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. */ ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); /* Read and decompress bytes from file into buf, until len-1 characters are read, or until a newline character is read and transferred to buf, or an end-of-file condition is encountered. If any characters are read or if len is one, the string is terminated with a null character. If no characters are read due to an end-of-file or len is less than one, then the buffer is left untouched. gzgets returns buf which is a null-terminated string, or it returns NULL for end-of-file or in case of error. If there was an error, the contents at buf are indeterminate. */ ZEXTERN int ZEXPORT gzputc(gzFile file, int c); /* Compress and write c, converted to an unsigned char, into file. gzputc returns the value that was written, or -1 in case of error. */ ZEXTERN int ZEXPORT gzgetc(gzFile file); /* Read and decompress one byte from file. gzgetc returns this byte or -1 in case of end of file or error. This is implemented as a macro for speed. As such, it does not do all of the checking the other functions do. I.e. it does not check to see if file is NULL, nor whether the structure file points to has been clobbered or not. */ ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); /* Push c back onto the stream for file to be read as the first character on the next read. At least one character of push-back is always allowed. gzungetc() returns the character pushed, or -1 on failure. gzungetc() will fail if c is -1, and may fail if a character has been pushed but not read yet. If gzungetc is used immediately after gzopen or gzdopen, at least the output buffer size of pushed characters is allowed. (See gzbuffer above.) The pushed character will be discarded if the stream is repositioned with gzseek() or gzrewind(). */ ZEXTERN int ZEXPORT gzflush(gzFile file, int flush); /* Flush all pending output to file. The parameter flush is as in the deflate() function. The return value is the zlib error number (see function gzerror below). gzflush is only permitted when writing. If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such concatenated gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. */ /* ZEXTERN z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence); Set the starting position to offset relative to whence for the next gzread or gzwrite on file. The offset represents a number of bytes in the uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new starting position. gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ ZEXTERN int ZEXPORT gzrewind(gzFile file); /* Rewind file. This function is supported only for reading. gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). */ /* ZEXTERN z_off_t ZEXPORT gztell(gzFile file); Return the starting position for the next gzread or gzwrite on file. This position represents a number of bytes in the uncompressed data stream, and is zero when starting, even if appending or reading a gzip stream from the middle of a file using gzdopen(). gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ /* ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file); Return the current compressed (actual) read or write offset of file. This offset includes the count of bytes that precede the gzip stream, for example when appending or when using gzdopen() for reading. When reading, the offset does not include as yet unused buffered input. This information can be used for a progress indicator. On error, gzoffset() returns -1. */ ZEXTERN int ZEXPORT gzeof(gzFile file); /* Return true (1) if the end-of-file indicator for file has been set while reading, false (0) otherwise. Note that the end-of-file indicator is set only if the read tried to go past the end of the input, but came up short. Therefore, just like feof(), gzeof() may return false even if there is no more data to read, in the event that the last read request was for the exact number of bytes remaining in the input file. This will happen if the input file size is an exact multiple of the buffer size. If gzeof() returns true, then the read functions will return no more data, unless the end-of-file indicator is reset by gzclearerr() and the input file has grown since the previous end of file was detected. */ ZEXTERN int ZEXPORT gzdirect(gzFile file); /* Return true (1) if file is being copied directly while reading, or false (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. If gzdirect() is used immediately after gzopen() or gzdopen() it will cause buffers to be allocated to allow reading the file to determine if it is a gzip file. Therefore if gzbuffer() is used, it should be called before gzdirect(). When writing, gzdirect() returns true (1) if transparent writing was requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: gzdirect() is not needed when writing. Transparent writing must be explicitly requested, so the application already knows the answer. When linking statically, using gzdirect() will include all of the zlib code for gzip file reading and decompression, which may not be desired.) */ ZEXTERN int ZEXPORT gzclose(gzFile file); /* Flush all pending output for file, if necessary, close file and deallocate the (de)compression state. Note that once file is closed, you cannot call gzerror with file, since its structures have been deallocated. gzclose must not be called more than once on the same file, just as free must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the last read ended in the middle of a gzip stream, or Z_OK on success. */ ZEXTERN int ZEXPORT gzclose_r(gzFile file); ZEXTERN int ZEXPORT gzclose_w(gzFile file); /* Same as gzclose(), but gzclose_r() is only for use when reading, and gzclose_w() is only for use when writing or appending. The advantage to using these instead of gzclose() is that they avoid linking in zlib compression or decompression code that is not used when only reading or only writing respectively. If gzclose() is used, then both compression and decompression code will be included the application when linking to a static zlib library. */ ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum); /* Return the error message for the last error which occurred on file. errnum is set to zlib error number. If an error occurred in the file system and not in the compression library, errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. The application must not modify the returned string. Future calls to this function may invalidate the previously returned string. If file is closed, then the string previously returned by gzerror will no longer be available. gzerror() should be used to distinguish errors from end-of-file for those functions above that do not distinguish those cases in their return values. */ ZEXTERN void ZEXPORT gzclearerr(gzFile file); /* Clear the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip file that is being written concurrently. */ #endif /* !Z_SOLO */ /* checksum functions */ /* These functions are not related to compression but are exported anyway because they might be useful in applications using the compression library. */ ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. An Adler-32 value is in the range of a 32-bit unsigned integer. If buf is Z_NULL, this function returns the required initial value for the checksum. An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed much faster. Usage example: uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); */ ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len); /* Same as adler32(), but with a size_t length. */ /* ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note that the z_off_t type (like off_t) is a signed integer. If len2 is negative, the result has no meaning or utility. */ ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. If buf is Z_NULL, this function returns the required initial value for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); */ ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf, z_size_t len); /* Same as crc32(), but with a size_t length. */ /* ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and len2. len2 must be non-negative. */ /* ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); Return the operator corresponding to length len2, to be used with crc32_combine_op(). len2 must be non-negative. */ ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); /* Give the same result as crc32_combine(), using op in place of len2. op is is generated from len2 by crc32_combine_gen(). This will be faster than crc32_combine() if the generated op is used more than once. */ /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size); ZEXTERN int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size); ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size); ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size); ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size); #ifdef Z_PREFIX_SET # define fltk_z_deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) # define fltk_z_inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) # define fltk_z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) # define fltk_z_inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ (int)sizeof(z_stream)) # define fltk_z_inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, (int)sizeof(z_stream)) #else # define deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) # define inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) # define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) # define inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ (int)sizeof(z_stream)) # define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, (int)sizeof(z_stream)) #endif #ifndef Z_SOLO /* gzgetc() macro and its supporting function and exposed data structure. Note * that the real internal state is much larger than the exposed structure. * This abbreviated structure exposes just enough for the gzgetc() macro. The * user should not mess with these exposed elements, since their names or * behavior could change in the future, perhaps even capriciously. They can * only be used by the gzgetc() macro. You have been warned. */ struct gzFile_s { unsigned have; unsigned char *next; z_off64_t pos; }; ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef fltk_z_gzgetc # define fltk_z_gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #else # define gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if * both are true, the application gets the *64 functions, and the regular * functions are changed to 64 bits) -- in case these are set on systems * without large file support, _LFS64_LARGEFILE must also be true */ #ifdef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); #endif #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) # ifdef Z_PREFIX_SET # define fltk_z_gzopen fltk_z_gzopen64 # define fltk_z_gzseek fltk_z_gzseek64 # define fltk_z_gztell fltk_z_gztell64 # define fltk_z_gzoffset fltk_z_gzoffset64 # define fltk_z_adler32_combine fltk_z_adler32_combine64 # define fltk_z_crc32_combine fltk_z_crc32_combine64 # define fltk_z_crc32_combine_gen fltk_z_crc32_combine_gen64 # else # define gzopen gzopen64 # define gzseek gzseek64 # define gztell gztell64 # define gzoffset gzoffset64 # define adler32_combine adler32_combine64 # define crc32_combine crc32_combine64 # define crc32_combine_gen crc32_combine_gen64 # endif # ifndef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); ZEXTERN z_off_t ZEXPORT gztell64(gzFile); ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); # endif #else ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int); ZEXTERN z_off_t ZEXPORT gztell(gzFile); ZEXTERN z_off_t ZEXPORT gzoffset(gzFile); ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); #endif #else /* Z_SOLO */ ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); #endif /* !Z_SOLO */ /* undocumented functions */ ZEXTERN const char * ZEXPORT zError(int); ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void); ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int); ZEXTERN int ZEXPORT inflateValidate(z_streamp, int); ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp); ZEXTERN int ZEXPORT inflateResetKeep(z_streamp); ZEXTERN int ZEXPORT deflateResetKeep(z_streamp); #if defined(_WIN32) && !defined(Z_SOLO) ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode); #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO ZEXTERN int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va); # endif #endif #ifdef __cplusplus } #endif #endif /* ZLIB_H */ fltk-1.4.3/zlib/deflate.c0000644000175000017500000023750315004135251015327 0ustar albrechtalbrecht/* deflate.c -- compress data using the deflation algorithm * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process depends on being able to identify portions * of the input text which are identical to earlier input (within a * sliding window trailing behind the input currently being processed). * * The most straightforward technique turns out to be the fastest for * most input files: try all possible matches and select the longest. * The key feature of this algorithm is that insertions into the string * dictionary are very simple and thus fast, and deletions are avoided * completely. Insertions are performed at each input character, whereas * string matches are performed only when the previous match ends. So it * is preferable to spend more time in matches to allow very fast string * insertions and avoid deletions. The matching algorithm for small * strings is inspired from that of Rabin & Karp. A brute force approach * is used to find longer strings when a small match has been found. * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze * (by Leonid Broukhis). * A previous version of this file used a more sophisticated algorithm * (by Fiala and Greene) which is guaranteed to run in linear amortized * time, but has a larger average cost, uses more memory and is patented. * However the F&G algorithm may be faster for some highly redundant * files if the parameter max_chain_length (described below) is too large. * * ACKNOWLEDGEMENTS * * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and * I found it in 'freeze' written by Leonid Broukhis. * Thanks to many people for bug reports and testing. * * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". * Available in http://tools.ietf.org/html/rfc1951 * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. * * Fiala,E.R., and Greene,D.H. * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 * */ /* @(#) $Id$ */ #include "deflate.h" const char deflate_copyright[] = " deflate 1.3.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ finish_started, /* finish started, need only more output at next deflate */ finish_done /* finish done, accept no more input or output */ } block_state; typedef block_state (*compress_func)(deflate_state *s, int flush); /* Compression function. Returns the block state after the call. */ local block_state deflate_stored(deflate_state *s, int flush); local block_state deflate_fast(deflate_state *s, int flush); #ifndef FASTEST local block_state deflate_slow(deflate_state *s, int flush); #endif local block_state deflate_rle(deflate_state *s, int flush); local block_state deflate_huff(deflate_state *s, int flush); /* =========================================================================== * Local data */ #define NIL 0 /* Tail of hash chains */ #ifndef TOO_FAR # define TOO_FAR 4096 #endif /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ /* Values for max_lazy_match, good_match and max_chain_length, depending on * the desired pack level (0..9). The values given below have been tuned to * exclude worst case performance for pathological files. Better values may be * found for specific files. */ typedef struct config_s { ush good_length; /* reduce lazy search above this match length */ ush max_lazy; /* do not perform lazy search above this match length */ ush nice_length; /* quit search above this match length */ ush max_chain; compress_func func; } config; #ifdef FASTEST local const config configuration_table[2] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ #else local const config configuration_table[10] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ /* 2 */ {4, 5, 16, 8, deflate_fast}, /* 3 */ {4, 6, 32, 32, deflate_fast}, /* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ /* 5 */ {8, 16, 32, 32, deflate_slow}, /* 6 */ {8, 16, 128, 128, deflate_slow}, /* 7 */ {8, 32, 128, 256, deflate_slow}, /* 8 */ {32, 128, 258, 1024, deflate_slow}, /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ #endif /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. */ /* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ #define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to UPDATE_HASH are made with consecutive input * characters, so that a running hash key can be computed from the previous * key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== * Insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. * IN assertion: all calls to INSERT_STRING are made with consecutive input * characters and the first MIN_MATCH bytes of str are valid (except for * the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #else #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #endif /* =========================================================================== * Initialize the hash table (avoiding 64K overflow for 16 bit systems). * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ do { \ s->head[s->hash_size - 1] = NIL; \ zmemzero((Bytef *)s->head, \ (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \ } while (0) /* =========================================================================== * Slide the hash table when sliding the window down (could be avoided with 32 * bit values at the expense of memory usage). We slide even when level == 0 to * keep the hash table consistent if we switch back to level > 0 later. */ #if defined(__has_feature) # if __has_feature(memory_sanitizer) __attribute__((no_sanitize("memory"))) # endif #endif local void slide_hash(deflate_state *s) { unsigned n, m; Posf *p; uInt wsize = s->w_size; n = s->hash_size; p = &s->head[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m - wsize : NIL); } while (--n); n = wsize; #ifndef FASTEST p = &s->prev[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m - wsize : NIL); /* If n is not on any hash chain, prev[n] is garbage but * its value will never be used. */ } while (--n); #endif } /* =========================================================================== * Read a new buffer from the current input stream, update the adler32 * and total number of bytes read. All deflate() input goes through * this function so some applications may wish to modify it to avoid * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ local unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size) { unsigned len = strm->avail_in; if (len > size) len = size; if (len == 0) return 0; strm->avail_in -= len; zmemcpy(buf, strm->next_in, len); if (strm->state->wrap == 1) { strm->adler = adler32(strm->adler, buf, len); } #ifdef GZIP else if (strm->state->wrap == 2) { strm->adler = crc32(strm->adler, buf, len); } #endif strm->next_in += len; strm->total_in += len; return len; } /* =========================================================================== * Fill the window when the lookahead becomes insufficient. * Updates strstart and lookahead. * * IN assertion: lookahead < MIN_LOOKAHEAD * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD * At least one byte has been read, or avail_in == 0; reads are * performed for at least two bytes (required for the zip translate_eol * option -- not supported here). */ local void fill_window(deflate_state *s) { unsigned n; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); do { more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); /* Deal with !@#$% 64K limit: */ if (sizeof(int) <= 2) { if (more == 0 && s->strstart == 0 && s->lookahead == 0) { more = wsize; } else if (more == (unsigned)(-1)) { /* Very unlikely, but possible on 16 bit machine if * strstart == 0 && lookahead == 1 (input done a byte at time) */ more--; } } /* If the window is almost full and there is insufficient lookahead, * move the upper half to the lower one to make room in the upper half. */ if (s->strstart >= wsize + MAX_DIST(s)) { zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; if (s->insert > s->strstart) s->insert = s->strstart; slide_hash(s); more += wsize; } if (s->strm->avail_in == 0) break; /* If there was no sliding: * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && * more == window_size - lookahead - strstart * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) * => more >= window_size - 2*WSIZE + 2 * In the BIG_MEM or MMAP case (not yet supported), * window_size == input_size + MIN_LOOKAHEAD && * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. * Otherwise, window_size == 2*WSIZE so more >= 2. * If there was sliding, more >= WSIZE. So in all cases, more >= 2. */ Assert(more >= 2, "more < 2"); n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); s->lookahead += n; /* Initialize the hash value now that we have some input: */ if (s->lookahead + s->insert >= MIN_MATCH) { uInt str = s->strstart - s->insert; s->ins_h = s->window[str]; UPDATE_HASH(s, s->ins_h, s->window[str + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif while (s->insert) { UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); #ifndef FASTEST s->prev[str & s->w_mask] = s->head[s->ins_h]; #endif s->head[s->ins_h] = (Pos)str; str++; s->insert--; if (s->lookahead + s->insert < MIN_MATCH) break; } } /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. */ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); /* If the WIN_INIT bytes after the end of the current data have never been * written, then zero those bytes in order to avoid memory check reports of * the use of uninitialized (or uninitialised as Julian writes) bytes by * the longest match routines. Update the high water mark for the next * time through here. WIN_INIT is set to MAX_MATCH since the longest match * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. */ if (s->high_water < s->window_size) { ulg curr = s->strstart + (ulg)(s->lookahead); ulg init; if (s->high_water < curr) { /* Previous high water mark below current data -- zero WIN_INIT * bytes or up to end of window, whichever is less. */ init = s->window_size - curr; if (init > WIN_INIT) init = WIN_INIT; zmemzero(s->window + curr, (unsigned)init); s->high_water = curr + init; } else if (s->high_water < (ulg)curr + WIN_INIT) { /* High water mark at or above current data, but below current data * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up * to end of window, whichever is less. */ init = (ulg)curr + WIN_INIT - s->high_water; if (init > s->window_size - s->high_water) init = s->window_size - s->high_water; zmemzero(s->window + s->high_water, (unsigned)init); s->high_water += init; } } Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, "not enough room for search"); } /* ========================================================================= */ int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size) { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size) { deflate_state *s; int wrap = 1; static const char my_version[] = ZLIB_VERSION; if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { return Z_VERSION_ERROR; } if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; if (strm->zalloc == (alloc_func)0) { #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; #endif } if (strm->zfree == (free_func)0) #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zfree = zcfree; #endif #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; if (windowBits < -15) return Z_STREAM_ERROR; windowBits = -windowBits; } #ifdef GZIP else if (windowBits > 15) { wrap = 2; /* write gzip wrapper instead */ windowBits -= 16; } #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state FAR *)s; s->strm = strm; s->status = INIT_STATE; /* to pass state test in deflateReset() */ s->wrap = wrap; s->gzhead = Z_NULL; s->w_bits = (uInt)windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; s->hash_bits = (uInt)memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH); s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); s->high_water = 0; /* nothing written to s->window yet */ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ /* We overlay pending_buf and sym_buf. This works since the average size * for length/distance pairs over any compressed block is assured to be 31 * bits or less. * * Analysis: The longest fixed codes are a length code of 8 bits plus 5 * extra bits, for lengths 131 to 257. The longest fixed distance codes are * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest * possible fixed-codes length/distance pair is then 31 bits total. * * sym_buf starts one-fourth of the way into pending_buf. So there are * three bytes in sym_buf for every four bytes in pending_buf. Each symbol * in sym_buf is three bytes -- two for the distance and one for the * literal/length. As each symbol is consumed, the pointer to the next * sym_buf value to read moves forward three bytes. From that symbol, up to * 31 bits are written to pending_buf. The closest the written pending_buf * bits gets to the next sym_buf symbol to read is just before the last * code is written. At that time, 31*(n - 2) bits have been written, just * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1 * symbols are written.) The closest the writing gets to what is unread is * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and * can range from 128 to 32768. * * Therefore, at a minimum, there are 142 bits of space between what is * written and what is read in the overlain buffers, so the symbols cannot * be overwritten by the compressed data. That space is actually 139 bits, * due to the three-bit fixed-code block header. * * That covers the case where either Z_FIXED is specified, forcing fixed * codes, or when the use of fixed codes is chosen, because that choice * results in a smaller compressed block than dynamic codes. That latter * condition then assures that the above analysis also covers all dynamic * blocks. A dynamic-code block will only be chosen to be emitted if it has * fewer bits than a fixed-code block would for the same set of symbols. * Therefore its average symbol length is assured to be less than 31. So * the compressed data for a dynamic block also cannot overwrite the * symbols from which it is being constructed. */ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, LIT_BUFS); s->pending_buf_size = (ulg)s->lit_bufsize * 4; if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { s->status = FINISH_STATE; strm->msg = ERR_MSG(Z_MEM_ERROR); deflateEnd (strm); return Z_MEM_ERROR; } #ifdef LIT_MEM s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1)); s->l_buf = s->pending_buf + (s->lit_bufsize << 2); s->sym_end = s->lit_bufsize - 1; #else s->sym_buf = s->pending_buf + s->lit_bufsize; s->sym_end = (s->lit_bufsize - 1) * 3; #endif /* We avoid equality with lit_bufsize*3 because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to * 64K-1 bytes. */ s->level = level; s->strategy = strategy; s->method = (Byte)method; return deflateReset(strm); } /* ========================================================================= * Check for a valid deflate stream state. Return 0 if ok, 1 if not. */ local int deflateStateCheck(z_streamp strm) { deflate_state *s; if (strm == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) return 1; s = strm->state; if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && #ifdef GZIP s->status != GZIP_STATE && #endif s->status != EXTRA_STATE && s->status != NAME_STATE && s->status != COMMENT_STATE && s->status != HCRC_STATE && s->status != BUSY_STATE && s->status != FINISH_STATE)) return 1; return 0; } /* ========================================================================= */ int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength) { deflate_state *s; uInt str, n; int wrap; unsigned avail; z_const unsigned char *next; if (deflateStateCheck(strm) || dictionary == Z_NULL) return Z_STREAM_ERROR; s = strm->state; wrap = s->wrap; if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) return Z_STREAM_ERROR; /* when using zlib wrappers, compute Adler-32 for provided dictionary */ if (wrap == 1) strm->adler = adler32(strm->adler, dictionary, dictLength); s->wrap = 0; /* avoid computing Adler-32 in read_buf */ /* if dictionary would fill window, just replace the history */ if (dictLength >= s->w_size) { if (wrap == 0) { /* already empty otherwise */ CLEAR_HASH(s); s->strstart = 0; s->block_start = 0L; s->insert = 0; } dictionary += dictLength - s->w_size; /* use the tail */ dictLength = s->w_size; } /* insert dictionary into window and hash */ avail = strm->avail_in; next = strm->next_in; strm->avail_in = dictLength; strm->next_in = (z_const Bytef *)dictionary; fill_window(s); while (s->lookahead >= MIN_MATCH) { str = s->strstart; n = s->lookahead - (MIN_MATCH-1); do { UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); #ifndef FASTEST s->prev[str & s->w_mask] = s->head[s->ins_h]; #endif s->head[s->ins_h] = (Pos)str; str++; } while (--n); s->strstart = str; s->lookahead = MIN_MATCH-1; fill_window(s); } s->strstart += s->lookahead; s->block_start = (long)s->strstart; s->insert = s->lookahead; s->lookahead = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; strm->next_in = next; strm->avail_in = avail; s->wrap = wrap; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary, uInt *dictLength) { deflate_state *s; uInt len; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; len = s->strstart + s->lookahead; if (len > s->w_size) len = s->w_size; if (dictionary != Z_NULL && len) zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); if (dictLength != Z_NULL) *dictLength = len; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateResetKeep(z_streamp strm) { deflate_state *s; if (deflateStateCheck(strm)) { return Z_STREAM_ERROR; } strm->total_in = strm->total_out = 0; strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ strm->data_type = Z_UNKNOWN; s = (deflate_state *)strm->state; s->pending = 0; s->pending_out = s->pending_buf; if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } s->status = #ifdef GZIP s->wrap == 2 ? GZIP_STATE : #endif INIT_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif adler32(0L, Z_NULL, 0); s->last_flush = -2; _tr_init(s); return Z_OK; } /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ local void lm_init(deflate_state *s) { s->window_size = (ulg)2L*s->w_size; CLEAR_HASH(s); /* Set the default configuration parameters: */ s->max_lazy_match = configuration_table[s->level].max_lazy; s->good_match = configuration_table[s->level].good_length; s->nice_match = configuration_table[s->level].nice_length; s->max_chain_length = configuration_table[s->level].max_chain; s->strstart = 0; s->block_start = 0L; s->lookahead = 0; s->insert = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; } /* ========================================================================= */ int ZEXPORT deflateReset(z_streamp strm) { int ret; ret = deflateResetKeep(strm); if (ret == Z_OK) lm_init(strm->state); return ret; } /* ========================================================================= */ int ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head) { if (deflateStateCheck(strm) || strm->state->wrap != 2) return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits) { if (deflateStateCheck(strm)) return Z_STREAM_ERROR; if (pending != Z_NULL) *pending = strm->state->pending; if (bits != Z_NULL) *bits = strm->state->bi_valid; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) { deflate_state *s; int put; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; #ifdef LIT_MEM if (bits < 0 || bits > 16 || (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; #else if (bits < 0 || bits > 16 || s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; #endif do { put = Buf_size - s->bi_valid; if (put > bits) put = bits; s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); s->bi_valid += put; _tr_flush_bits(s); value >>= put; bits -= put; } while (bits); return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) { deflate_state *s; compress_func func; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && s->last_flush != -2) { /* Flush the last buffer: */ int err = deflate(strm, Z_BLOCK); if (err == Z_STREAM_ERROR) return err; if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead) return Z_BUF_ERROR; } if (s->level != level) { if (s->level == 0 && s->matches != 0) { if (s->matches == 1) slide_hash(s); else CLEAR_HASH(s); s->matches = 0; } s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; s->nice_match = configuration_table[level].nice_length; s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain) { deflate_state *s; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; s->good_match = (uInt)good_length; s->max_lazy_match = (uInt)max_lazy; s->nice_match = nice_length; s->max_chain_length = (uInt)max_chain; return Z_OK; } /* ========================================================================= * For the default windowBits of 15 and memLevel of 8, this function returns a * close to exact, as well as small, upper bound on the compressed size. This * is an expansion of ~0.03%, plus a small constant. * * For any setting other than those defaults for windowBits and memLevel, one * of two worst case bounds is returned. This is at most an expansion of ~4% or * ~13%, plus a small constant. * * Both the 0.03% and 4% derive from the overhead of stored blocks. The first * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second * is for stored blocks of 127 bytes (the worst case memLevel == 1). The * expansion results from five bytes of header for each stored block. * * The larger expansion of 13% results from a window size less than or equal to * the symbols buffer size (windowBits <= memLevel + 7). In that case some of * the data being compressed may have slid out of the sliding window, impeding * a stored block from being emitted. Then the only choice is a fixed or * dynamic block, where a fixed block limits the maximum expansion to 9 bits * per 8-bit byte, plus 10 bits for every block. The smallest block size for * which this can occur is 255 (memLevel == 2). * * Shifts are used to approximate divisions, for speed. */ uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) { deflate_state *s; uLong fixedlen, storelen, wraplen; /* upper bound for fixed blocks with 9-bit literals and length 255 (memLevel == 2, which is the lowest that may not use stored blocks) -- ~13% overhead plus a small constant */ fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) + (sourceLen >> 9) + 4; /* upper bound for stored blocks with length 127 (memLevel == 1) -- ~4% overhead plus a small constant */ storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) + (sourceLen >> 11) + 7; /* if can't get parameters, return larger bound plus a zlib wrapper */ if (deflateStateCheck(strm)) return (fixedlen > storelen ? fixedlen : storelen) + 6; /* compute wrapper length */ s = strm->state; switch (s->wrap) { case 0: /* raw deflate */ wraplen = 0; break; case 1: /* zlib wrapper */ wraplen = 6 + (s->strstart ? 4 : 0); break; #ifdef GZIP case 2: /* gzip wrapper */ wraplen = 18; if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ Bytef *str; if (s->gzhead->extra != Z_NULL) wraplen += 2 + s->gzhead->extra_len; str = s->gzhead->name; if (str != Z_NULL) do { wraplen++; } while (*str++); str = s->gzhead->comment; if (str != Z_NULL) do { wraplen++; } while (*str++); if (s->gzhead->hcrc) wraplen += 2; } break; #endif default: /* for compiler happiness */ wraplen = 6; } /* if not default parameters, return one of the conservative bounds */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) + wraplen; /* default settings: return tight bound for that case -- ~0.03% overhead plus a small constant */ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen; } /* ========================================================================= * Put a short in the pending buffer. The 16-bit value is put in MSB order. * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ local void putShortMSB(deflate_state *s, uInt b) { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } /* ========================================================================= * Flush as much pending output as possible. All deflate() output, except for * some deflate_stored() output, goes through this function so some * applications may wish to modify it to avoid allocating a large * strm->next_out buffer and copying into it. (See also read_buf()). */ local void flush_pending(z_streamp strm) { unsigned len; deflate_state *s = strm->state; _tr_flush_bits(s); len = s->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; zmemcpy(strm->next_out, s->pending_out, len); strm->next_out += len; s->pending_out += len; strm->total_out += len; strm->avail_out -= len; s->pending -= len; if (s->pending == 0) { s->pending_out = s->pending_buf; } } /* =========================================================================== * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. */ #define HCRC_UPDATE(beg) \ do { \ if (s->gzhead->hcrc && s->pending > (beg)) \ strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ s->pending - (beg)); \ } while (0) /* ========================================================================= */ int ZEXPORT deflate(z_streamp strm, int flush) { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || (strm->avail_in != 0 && strm->next_in == Z_NULL) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); old_flush = s->last_flush; s->last_flush = flush; /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); if (strm->avail_out == 0) { /* Since avail_out is 0, deflate will be called again with * more output space, but possibly with both pending and * avail_in equal to zero. There won't be anything to do, * but this is not an error situation so make sure we * return OK instead of BUF_ERROR at next call of deflate: */ s->last_flush = -1; return Z_OK; } /* Make sure there is something to do and avoid duplicate consecutive * flushes. For repeated and useless calls with Z_FINISH, we keep * returning Z_STREAM_END instead of Z_BUF_ERROR. */ } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && flush != Z_FINISH) { ERR_RETURN(strm, Z_BUF_ERROR); } /* User must not provide more input after the first FINISH: */ if (s->status == FINISH_STATE && strm->avail_in != 0) { ERR_RETURN(strm, Z_BUF_ERROR); } /* Write the header */ if (s->status == INIT_STATE && s->wrap == 0) s->status = BUSY_STATE; if (s->status == INIT_STATE) { /* zlib header */ uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8; uInt level_flags; if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) level_flags = 0; else if (s->level < 6) level_flags = 1; else if (s->level == 6) level_flags = 2; else level_flags = 3; header |= (level_flags << 6); if (s->strstart != 0) header |= PRESET_DICT; header += 31 - (header % 31); putShortMSB(s, header); /* Save the adler32 of the preset dictionary: */ if (s->strstart != 0) { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } strm->adler = adler32(0L, Z_NULL, 0); s->status = BUSY_STATE; /* Compression must start with an empty pending buffer */ flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } } #ifdef GZIP if (s->status == GZIP_STATE) { /* gzip header */ strm->adler = crc32(0L, Z_NULL, 0); put_byte(s, 31); put_byte(s, 139); put_byte(s, 8); if (s->gzhead == Z_NULL) { put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, OS_CODE); s->status = BUSY_STATE; /* Compression must start with an empty pending buffer */ flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } } else { put_byte(s, (s->gzhead->text ? 1 : 0) + (s->gzhead->hcrc ? 2 : 0) + (s->gzhead->extra == Z_NULL ? 0 : 4) + (s->gzhead->name == Z_NULL ? 0 : 8) + (s->gzhead->comment == Z_NULL ? 0 : 16) ); put_byte(s, (Byte)(s->gzhead->time & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, s->gzhead->os & 0xff); if (s->gzhead->extra != Z_NULL) { put_byte(s, s->gzhead->extra_len & 0xff); put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); } if (s->gzhead->hcrc) strm->adler = crc32(strm->adler, s->pending_buf, s->pending); s->gzindex = 0; s->status = EXTRA_STATE; } } if (s->status == EXTRA_STATE) { if (s->gzhead->extra != Z_NULL) { ulg beg = s->pending; /* start of bytes to update crc */ uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; while (s->pending + left > s->pending_buf_size) { uInt copy = s->pending_buf_size - s->pending; zmemcpy(s->pending_buf + s->pending, s->gzhead->extra + s->gzindex, copy); s->pending = s->pending_buf_size; HCRC_UPDATE(beg); s->gzindex += copy; flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } beg = 0; left -= copy; } zmemcpy(s->pending_buf + s->pending, s->gzhead->extra + s->gzindex, left); s->pending += left; HCRC_UPDATE(beg); s->gzindex = 0; } s->status = NAME_STATE; } if (s->status == NAME_STATE) { if (s->gzhead->name != Z_NULL) { ulg beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { HCRC_UPDATE(beg); flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } beg = 0; } val = s->gzhead->name[s->gzindex++]; put_byte(s, val); } while (val != 0); HCRC_UPDATE(beg); s->gzindex = 0; } s->status = COMMENT_STATE; } if (s->status == COMMENT_STATE) { if (s->gzhead->comment != Z_NULL) { ulg beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { HCRC_UPDATE(beg); flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } beg = 0; } val = s->gzhead->comment[s->gzindex++]; put_byte(s, val); } while (val != 0); HCRC_UPDATE(beg); } s->status = HCRC_STATE; } if (s->status == HCRC_STATE) { if (s->gzhead->hcrc) { if (s->pending + 2 > s->pending_buf_size) { flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } } put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); strm->adler = crc32(0L, Z_NULL, 0); } s->status = BUSY_STATE; /* Compression must start with an empty pending buffer */ flush_pending(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; } } #endif /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; bstate = s->level == 0 ? deflate_stored(s, flush) : s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : s->strategy == Z_RLE ? deflate_rle(s, flush) : (*(configuration_table[s->level].func))(s, flush); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; } if (bstate == need_more || bstate == finish_started) { if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ } return Z_OK; /* If flush != Z_NO_FLUSH && avail_out == 0, the next call * of deflate should use the same flush parameter to make sure * that the flush is complete. So we don't have to output an * empty block here, this will be done at next call. This also * ensures that for a very small output buffer, we emit at most * one empty block. */ } if (bstate == block_done) { if (flush == Z_PARTIAL_FLUSH) { _tr_align(s); } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ _tr_stored_block(s, (char*)0, 0L, 0); /* For a full flush, this empty block will be recognized * as a special marker by inflate_sync(). */ if (flush == Z_FULL_FLUSH) { CLEAR_HASH(s); /* forget history */ if (s->lookahead == 0) { s->strstart = 0; s->block_start = 0L; s->insert = 0; } } } flush_pending(strm); if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ return Z_OK; } } } if (flush != Z_FINISH) return Z_OK; if (s->wrap <= 0) return Z_STREAM_END; /* Write the trailer */ #ifdef GZIP if (s->wrap == 2) { put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); put_byte(s, (Byte)(strm->total_in & 0xff)); put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); } else #endif { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } flush_pending(strm); /* If avail_out is zero, the application will call deflate again * to flush the rest. */ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ return s->pending != 0 ? Z_OK : Z_STREAM_END; } /* ========================================================================= */ int ZEXPORT deflateEnd(z_streamp strm) { int status; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; status = strm->state->status; /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); TRY_FREE(strm, strm->state->head); TRY_FREE(strm, strm->state->prev); TRY_FREE(strm, strm->state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; } /* ========================================================================= * Copy the source state to the destination state. * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) { #ifdef MAXSEG_64K (void)dest; (void)source; return Z_STREAM_ERROR; #else deflate_state *ds; deflate_state *ss; if (deflateStateCheck(source) || dest == Z_NULL) { return Z_STREAM_ERROR; } ss = source->state; zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state FAR *) ds; zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, LIT_BUFS); if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { deflateEnd (dest); return Z_MEM_ERROR; } /* following zmemcpy do not work for 16-bit MSDOS */ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); zmemcpy(ds->pending_buf, ss->pending_buf, ds->lit_bufsize * LIT_BUFS); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); #ifdef LIT_MEM ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1)); ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2); #else ds->sym_buf = ds->pending_buf + ds->lit_bufsize; #endif ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; ds->bl_desc.dyn_tree = ds->bl_tree; return Z_OK; #endif /* MAXSEG_64K */ } #ifndef FASTEST /* =========================================================================== * Set match_start to the longest match starting at the given string and * return its length. Matches shorter or equal to prev_length are discarded, * in which case the result is equal to prev_length and match_start is * garbage. * IN assertions: cur_match is the head of the hash chain for the current * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ local uInt longest_match(deflate_state *s, IPos cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ int best_len = (int)s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0. */ Posf *prev = s->prev; uInt wmask = s->w_mask; #ifdef UNALIGNED_OK /* Compare two bytes at a time. Note: this is not always beneficial. * Try with and without -DUNALIGNED_OK to check. */ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; register ush scan_start = *(ushf*)scan; register ush scan_end = *(ushf*)(scan + best_len - 1); #else register Bytef *strend = s->window + s->strstart + MAX_MATCH; register Byte scan_end1 = scan[best_len - 1]; register Byte scan_end = scan[best_len]; #endif /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); /* Do not waste too much time if we already have a good match: */ if (s->prev_length >= s->good_match) { chain_length >>= 2; } /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Skip to next match if the match length cannot increase * or if the match length is less than 2. Note that the checks below * for insufficient lookahead only occur occasionally for performance * reasons. Therefore uninitialized memory will be accessed, and * conditional jumps will be made that depend on those values. * However the length of the match is limited to the lookahead, so * the output of deflate is not affected by the uninitialized values. */ #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ if (*(ushf*)(match + best_len - 1) != scan_end || *(ushf*)match != scan_start) continue; /* It is not necessary to compare scan[2] and match[2] since they are * always equal when the other bytes match, given that the hash keys * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at * strstart + 3, + 5, up to strstart + 257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) && *(ushf*)(scan += 2) == *(ushf*)(match += 2) && *(ushf*)(scan += 2) == *(ushf*)(match += 2) && *(ushf*)(scan += 2) == *(ushf*)(match += 2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ /* Here, scan <= window + strstart + 257 */ Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); if (*scan == *match) scan++; len = (MAX_MATCH - 1) - (int)(strend - scan); scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ if (match[best_len] != scan_end || match[best_len - 1] != scan_end1 || *match != *scan || *++match != scan[1]) continue; /* The check at best_len - 1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match++; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; #endif /* UNALIGNED_OK */ if (len > best_len) { s->match_start = cur_match; best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK scan_end = *(ushf*)(scan + best_len - 1); #else scan_end1 = scan[best_len - 1]; scan_end = scan[best_len]; #endif } } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } #else /* FASTEST */ /* --------------------------------------------------------------------------- * Optimized version for FASTEST only */ local uInt longest_match(deflate_state *s, IPos cur_match) { register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ register Bytef *strend = s->window + s->strstart + MAX_MATCH; /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead"); Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Return failure if the match length is less than 2: */ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; /* The check at best_len - 1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match += 2; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart + 258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); if (len < MIN_MATCH) return MIN_MATCH - 1; s->match_start = cur_match; return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; } #endif /* FASTEST */ #ifdef ZLIB_DEBUG #define EQUAL 0 /* result of memcmp for equal strings */ /* =========================================================================== * Check that the match at match_start is indeed a match. */ local void check_match(deflate_state *s, IPos start, IPos match, int length) { /* check that the match is indeed a match */ Bytef *back = s->window + (int)match, *here = s->window + start; IPos len = length; if (match == (IPos)-1) { /* match starts one byte before the current window -- just compare the subsequent length-1 bytes */ back++; here++; len--; } if (zmemcmp(back, here, len) != EQUAL) { fprintf(stderr, " start %u, match %d, length %d\n", start, (int)match, length); do { fprintf(stderr, "(%02x %02x)", *back++, *here++); } while (--len != 0); z_error("invalid match"); } if (z_verbose > 1) { fprintf(stderr,"\\[%d,%d]", start - match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } #else # define check_match(s, start, match, length) #endif /* ZLIB_DEBUG */ /* =========================================================================== * Flush the current block, with given end-of-file flag. * IN assertion: strstart is set to the end of the current match. */ #define FLUSH_BLOCK_ONLY(s, last) { \ _tr_flush_block(s, (s->block_start >= 0L ? \ (charf *)&s->window[(unsigned)s->block_start] : \ (charf *)Z_NULL), \ (ulg)((long)s->strstart - s->block_start), \ (last)); \ s->block_start = s->strstart; \ flush_pending(s->strm); \ Tracev((stderr,"[FLUSH]")); \ } /* Same but force premature exit if necessary. */ #define FLUSH_BLOCK(s, last) { \ FLUSH_BLOCK_ONLY(s, last); \ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ } /* Maximum stored block length in deflate format (not including header). */ #define MAX_STORED 65535 /* Minimum of a and b. */ #define MIN(a, b) ((a) > (b) ? (b) : (a)) /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. * * In case deflateParams() is used to later switch to a non-zero compression * level, s->matches (otherwise unused when storing) keeps track of the number * of hash table slides to perform. If s->matches is 1, then one hash table * slide will be done when switching. If s->matches is 2, the maximum value * allowed here, then the hash table will be cleared, since two or more slides * is the same as a clear. * * deflate_stored() is written to minimize the number of times an input byte is * copied. It is most efficient with large input and output buffers, which * maximizes the opportunities to have a single copy from next_in to next_out. */ local block_state deflate_stored(deflate_state *s, int flush) { /* Smallest worthy block size when not flushing or finishing. By default * this is 32K. This can be as small as 507 bytes for memLevel == 1. For * large input and output buffers, the stored block size will be larger. */ unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); /* Copy as many min_block or larger stored blocks directly to next_out as * possible. If flushing, copy the remaining available input to next_out as * stored blocks, if there is enough space. */ unsigned len, left, have, last = 0; unsigned used = s->strm->avail_in; do { /* Set len to the maximum size block that we can copy directly with the * available input data and output space. Set left to how much of that * would be copied from what's left in the window. */ len = MAX_STORED; /* maximum deflate stored block length */ have = (s->bi_valid + 42) >> 3; /* number of header bytes */ if (s->strm->avail_out < have) /* need room for header */ break; /* maximum stored block length that will fit in avail_out: */ have = s->strm->avail_out - have; left = s->strstart - s->block_start; /* bytes left in window */ if (len > (ulg)left + s->strm->avail_in) len = left + s->strm->avail_in; /* limit len to the input */ if (len > have) len = have; /* limit len to the output */ /* If the stored block would be less than min_block in length, or if * unable to copy all of the available input when flushing, then try * copying to the window and the pending buffer instead. Also don't * write an empty block when flushing -- deflate() does that. */ if (len < min_block && ((len == 0 && flush != Z_FINISH) || flush == Z_NO_FLUSH || len != left + s->strm->avail_in)) break; /* Make a dummy stored block in pending to get the header bytes, * including any pending bits. This also updates the debugging counts. */ last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; _tr_stored_block(s, (char *)0, 0L, last); /* Replace the lengths in the dummy stored block with len. */ s->pending_buf[s->pending - 4] = len; s->pending_buf[s->pending - 3] = len >> 8; s->pending_buf[s->pending - 2] = ~len; s->pending_buf[s->pending - 1] = ~len >> 8; /* Write the stored block header bytes. */ flush_pending(s->strm); #ifdef ZLIB_DEBUG /* Update debugging counts for the data about to be copied. */ s->compressed_len += len << 3; s->bits_sent += len << 3; #endif /* Copy uncompressed bytes from the window to next_out. */ if (left) { if (left > len) left = len; zmemcpy(s->strm->next_out, s->window + s->block_start, left); s->strm->next_out += left; s->strm->avail_out -= left; s->strm->total_out += left; s->block_start += left; len -= left; } /* Copy uncompressed bytes directly from next_in to next_out, updating * the check value. */ if (len) { read_buf(s->strm, s->strm->next_out, len); s->strm->next_out += len; s->strm->avail_out -= len; s->strm->total_out += len; } } while (last == 0); /* Update the sliding window with the last s->w_size bytes of the copied * data, or append all of the copied data to the existing window if less * than s->w_size bytes were copied. Also update the number of bytes to * insert in the hash tables, in the event that deflateParams() switches to * a non-zero compression level. */ used -= s->strm->avail_in; /* number of input bytes directly copied */ if (used) { /* If any input was used, then no unused input remains in the window, * therefore s->block_start == s->strstart. */ if (used >= s->w_size) { /* supplant the previous history */ s->matches = 2; /* clear hash */ zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); s->strstart = s->w_size; s->insert = s->strstart; } else { if (s->window_size - s->strstart <= used) { /* Slide the window down. */ s->strstart -= s->w_size; zmemcpy(s->window, s->window + s->w_size, s->strstart); if (s->matches < 2) s->matches++; /* add a pending slide_hash() */ if (s->insert > s->strstart) s->insert = s->strstart; } zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); s->strstart += used; s->insert += MIN(used, s->w_size - s->insert); } s->block_start = s->strstart; } if (s->high_water < s->strstart) s->high_water = s->strstart; /* If the last block was written to next_out, then done. */ if (last) return finish_done; /* If flushing and all input has been consumed, then done. */ if (flush != Z_NO_FLUSH && flush != Z_FINISH && s->strm->avail_in == 0 && (long)s->strstart == s->block_start) return block_done; /* Fill the window with any remaining input. */ have = s->window_size - s->strstart; if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { /* Slide the window down. */ s->block_start -= s->w_size; s->strstart -= s->w_size; zmemcpy(s->window, s->window + s->w_size, s->strstart); if (s->matches < 2) s->matches++; /* add a pending slide_hash() */ have += s->w_size; /* more space now */ if (s->insert > s->strstart) s->insert = s->strstart; } if (have > s->strm->avail_in) have = s->strm->avail_in; if (have) { read_buf(s->strm, s->window + s->strstart, have); s->strstart += have; s->insert += MIN(have, s->w_size - s->insert); } if (s->high_water < s->strstart) s->high_water = s->strstart; /* There was not enough avail_out to write a complete worthy or flushed * stored block to next_out. Write a stored block to pending instead, if we * have enough input for a worthy block, or if flushing and there is enough * room for the remaining input as a stored block in the pending buffer. */ have = (s->bi_valid + 42) >> 3; /* number of header bytes */ /* maximum stored block length that will fit in pending: */ have = MIN(s->pending_buf_size - have, MAX_STORED); min_block = MIN(have, s->w_size); left = s->strstart - s->block_start; if (left >= min_block || ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && s->strm->avail_in == 0 && left <= have)) { len = MIN(left, have); last = flush == Z_FINISH && s->strm->avail_in == 0 && len == left ? 1 : 0; _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); s->block_start += len; flush_pending(s->strm); } /* We've done all we can with the available input and output. */ return last ? finish_started : need_more; } /* =========================================================================== * Compress as much as possible from the input stream, return the current * block state. * This function does not perform lazy evaluation of matches and inserts * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ local block_state deflate_fast(deflate_state *s, int flush) { IPos hash_head; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. * At this point we have always match_length < MIN_MATCH */ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ } if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->match_start, s->match_length); _tr_tally_dist(s, s->strstart - s->match_start, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ #ifndef FASTEST if (s->match_length <= s->max_insert_length && s->lookahead >= MIN_MATCH) { s->match_length--; /* string at strstart already in table */ do { s->strstart++; INSERT_STRING(s, s->strstart, hash_head); /* strstart never exceeds WSIZE-MAX_MATCH, so there are * always MIN_MATCH bytes ahead. */ } while (--s->match_length != 0); s->strstart++; } else #endif { s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ } } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } #ifndef FASTEST /* =========================================================================== * Same as above, but achieves better compression. We use a lazy * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ local block_state deflate_slow(deflate_state *s, int flush) { IPos hash_head; /* head of hash chain */ int bflush; /* set if current block must be flushed */ /* Process the input block. */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart + 2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. */ s->prev_length = s->match_length, s->prev_match = s->match_start; s->match_length = MIN_MATCH-1; if (hash_head != NIL && s->prev_length < s->max_lazy_match && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ if (s->match_length <= 5 && (s->strategy == Z_FILTERED #if TOO_FAR <= 32767 || (s->match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR) #endif )) { /* If prev_match is also MIN_MATCH, match_start is garbage * but we will ignore the current match anyway. */ s->match_length = MIN_MATCH-1; } } /* If there was a match at the previous step and the current * match is not better, output the previous match: */ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ check_match(s, s->strstart - 1, s->prev_match, s->prev_length); _tr_tally_dist(s, s->strstart - 1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. * strstart - 1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ s->lookahead -= s->prev_length - 1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { INSERT_STRING(s, s->strstart, hash_head); } } while (--s->prev_length != 0); s->match_available = 0; s->match_length = MIN_MATCH-1; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } else if (s->match_available) { /* If there was no match at the previous position, output a * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ Tracevv((stderr,"%c", s->window[s->strstart - 1])); _tr_tally_lit(s, s->window[s->strstart - 1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } s->strstart++; s->lookahead--; if (s->strm->avail_out == 0) return need_more; } else { /* There is no previous match to compare with, wait for * the next step to decide. */ s->match_available = 1; s->strstart++; s->lookahead--; } } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { Tracevv((stderr,"%c", s->window[s->strstart - 1])); _tr_tally_lit(s, s->window[s->strstart - 1], bflush); s->match_available = 0; } s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } #endif /* FASTEST */ /* =========================================================================== * For Z_RLE, simply look for runs of bytes, generate matches only of distance * one. Do not maintain a hash table. (It will be regenerated if this run of * deflate switches away from Z_RLE.) */ local block_state deflate_rle(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ uInt prev; /* byte at distance one to match */ Bytef *scan, *strend; /* scan goes up to strend for length of run */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the longest run, plus one for the unrolled loop. */ if (s->lookahead <= MAX_MATCH) { fill_window(s); if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* See how many times the previous byte repeats */ s->match_length = 0; if (s->lookahead >= MIN_MATCH && s->strstart > 0) { scan = s->window + s->strstart - 1; prev = *scan; if (prev == *++scan && prev == *++scan && prev == *++scan) { strend = s->window + s->strstart + MAX_MATCH; do { } while (prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); s->match_length = MAX_MATCH - (uInt)(strend - scan); if (s->match_length > s->lookahead) s->match_length = s->lookahead; } Assert(scan <= s->window + (uInt)(s->window_size - 1), "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->strstart - 1, s->match_length); _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; s->strstart += s->match_length; s->match_length = 0; } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } /* =========================================================================== * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. * (It will be regenerated if this run of deflate switches away from Huffman.) */ local block_state deflate_huff(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we have a literal to write. */ if (s->lookahead == 0) { fill_window(s); if (s->lookahead == 0) { if (flush == Z_NO_FLUSH) return need_more; break; /* flush the current block */ } } /* Output a literal byte */ s->match_length = 0; Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit(s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->sym_next) FLUSH_BLOCK(s, 0); return block_done; } fltk-1.4.3/zlib/ChangeLog0000644000175000017500000024263415004135251015332 0ustar albrechtalbrecht ChangeLog file for zlib Changes in 1.3 (18 Aug 2023) - Remove K&R function definitions and zlib2ansi - Fix bug in deflateBound() for level 0 and memLevel 9 - Fix bug when gzungetc() is used immediately after gzopen() - Fix bug when using gzflush() with a very small buffer - Fix crash when gzsetparams() attempted for transparent write - Fix test/example.c to work with FORCE_STORED - Rewrite of zran in examples (see zran.c version history) - Fix minizip to allow it to open an empty zip file - Fix reading disk number start on zip64 files in minizip - Fix logic error in minizip argument processing - Add minizip testing to Makefile - Read multiple bytes instead of byte-by-byte in minizip unzip.c - Add memory sanitizer to configure (--memory) - Various portability improvements - Various documentation improvements - Various spelling and typo corrections Changes in 1.2.13 (13 Oct 2022) - Fix configure issue that discarded provided CC definition - Correct incorrect inputs provided to the CRC functions - Repair prototypes and exporting of new CRC functions - Fix inflateBack to detect invalid input with distances too far - Have infback() deliver all of the available output up to any error - Fix a bug when getting a gzip header extra field with inflate() - Fix bug in block type selection when Z_FIXED used - Tighten deflateBound bounds - Remove deleted assembler code references - Various portability and appearance improvements Changes in 1.2.12 (27 Mar 2022) - Cygwin does not have _wopen(), so do not create gzopen_w() there - Permit a deflateParams() parameter change as soon as possible - Limit hash table inserts after switch from stored deflate - Fix bug when window full in deflate_stored() - Fix CLEAR_HASH macro to be usable as a single statement - Avoid a conversion error in gzseek when off_t type too small - Have Makefile return non-zero error code on test failure - Avoid some conversion warnings in gzread.c and gzwrite.c - Update use of errno for newer Windows CE versions - Small speedup to inflate [psumbera] - Return an error if the gzputs string length can't fit in an int - Add address checking in clang to -w option of configure - Don't compute check value for raw inflate if asked to validate - Handle case where inflateSync used when header never processed - Avoid the use of ptrdiff_t - Avoid an undefined behavior of memcpy() in gzappend() - Avoid undefined behaviors of memcpy() in gz*printf() - Avoid an undefined behavior of memcpy() in _tr_stored_block() - Make the names in functions declarations identical to definitions - Remove old assembler code in which bugs have manifested - Fix deflateEnd() to not report an error at start of raw deflate - Add legal disclaimer to README - Emphasize the need to continue decompressing gzip members - Correct the initialization requirements for deflateInit2() - Fix a bug that can crash deflate on some input when using Z_FIXED - Assure that the number of bits for deflatePrime() is valid - Use a structure to make globals in enough.c evident - Use a macro for the printf format of big_t in enough.c - Clean up code style in enough.c, update version - Use inline function instead of macro for index in enough.c - Clarify that prefix codes are counted in enough.c - Show all the codes for the maximum tables size in enough.c - Add gznorm.c example, which normalizes gzip files - Fix the zran.c example to work on a multiple-member gzip file - Add tables for crc32_combine(), to speed it up by a factor of 200 - Add crc32_combine_gen() and crc32_combine_op() for fast combines - Speed up software CRC-32 computation by a factor of 1.5 to 3 - Use atomic test and set, if available, for dynamic CRC tables - Don't bother computing check value after successful inflateSync() - Correct comment in crc32.c - Add use of the ARMv8 crc32 instructions when requested - Use ARM crc32 instructions if the ARM architecture has them - Explicitly note that the 32-bit check values are 32 bits - Avoid adding empty gzip member after gzflush with Z_FINISH - Fix memory leak on error in gzlog.c - Fix error in comment on the polynomial representation of a byte - Clarify gz* function interfaces, referring to parameter names - Change macro name in inflate.c to avoid collision in VxWorks - Correct typo in blast.c - Improve portability of contrib/minizip - Fix indentation in minizip's zip.c - Replace black/white with allow/block. (theresa-m) - minizip warning fix if MAXU32 already defined. (gvollant) - Fix unztell64() in minizip to work past 4GB. (Daniël Hörchner) - Clean up minizip to reduce warnings for testing - Add fallthrough comments for gcc - Eliminate use of ULL constants - Separate out address sanitizing from warnings in configure - Remove destructive aspects of make distclean - Check for cc masquerading as gcc or clang in configure - Fix crc32.c to compile local functions only if used Changes in 1.2.11 (15 Jan 2017) - Fix deflate stored bug when pulling last block from window - Permit immediate deflateParams changes before any deflate input Changes in 1.2.10 (2 Jan 2017) - Avoid warnings on snprintf() return value - Fix bug in deflate_stored() for zero-length input - Fix bug in gzwrite.c that produced corrupt gzip files - Remove files to be installed before copying them in Makefile.in - Add warnings when compiling with assembler code Changes in 1.2.9 (31 Dec 2016) - Fix contrib/minizip to permit unzipping with desktop API [Zouzou] - Improve contrib/blast to return unused bytes - Assure that gzoffset() is correct when appending - Improve compress() and uncompress() to support large lengths - Fix bug in test/example.c where error code not saved - Remedy Coverity warning [Randers-Pehrson] - Improve speed of gzprintf() in transparent mode - Fix inflateInit2() bug when windowBits is 16 or 32 - Change DEBUG macro to ZLIB_DEBUG - Avoid uninitialized access by gzclose_w() - Allow building zlib outside of the source directory - Fix bug that accepted invalid zlib header when windowBits is zero - Fix gzseek() problem on MinGW due to buggy _lseeki64 there - Loop on write() calls in gzwrite.c in case of non-blocking I/O - Add --warn (-w) option to ./configure for more compiler warnings - Reject a window size of 256 bytes if not using the zlib wrapper - Fix bug when level 0 used with Z_HUFFMAN or Z_RLE - Add --debug (-d) option to ./configure to define ZLIB_DEBUG - Fix bugs in creating a very large gzip header - Add uncompress2() function, which returns the input size used - Assure that deflateParams() will not switch functions mid-block - Dramatically speed up deflation for level 0 (storing) - Add gzfread(), duplicating the interface of fread() - Add gzfwrite(), duplicating the interface of fwrite() - Add deflateGetDictionary() function - Use snprintf() for later versions of Microsoft C - Fix *Init macros to use z_ prefix when requested - Replace as400 with os400 for OS/400 support [Monnerat] - Add crc32_z() and adler32_z() functions with size_t lengths - Update Visual Studio project files [AraHaan] Changes in 1.2.8 (28 Apr 2013) - Update contrib/minizip/iowin32.c for Windows RT [Vollant] - Do not force Z_CONST for C++ - Clean up contrib/vstudio [Roß] - Correct spelling error in zlib.h - Fix mixed line endings in contrib/vstudio Changes in 1.2.7.3 (13 Apr 2013) - Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc Changes in 1.2.7.2 (13 Apr 2013) - Change check for a four-byte type back to hexadecimal - Fix typo in win32/Makefile.msc - Add casts in gzwrite.c for pointer differences Changes in 1.2.7.1 (24 Mar 2013) - Replace use of unsafe string functions with snprintf if available - Avoid including stddef.h on Windows for Z_SOLO compile [Niessink] - Fix gzgetc undefine when Z_PREFIX set [Turk] - Eliminate use of mktemp in Makefile (not always available) - Fix bug in 'F' mode for gzopen() - Add inflateGetDictionary() function - Correct comment in deflate.h - Use _snprintf for snprintf in Microsoft C - On Darwin, only use /usr/bin/libtool if libtool is not Apple - Delete "--version" file if created by "ar --version" [Richard G.] - Fix configure check for veracity of compiler error return codes - Fix CMake compilation of static lib for MSVC2010 x64 - Remove unused variable in infback9.c - Fix argument checks in gzlog_compress() and gzlog_write() - Clean up the usage of z_const and respect const usage within zlib - Clean up examples/gzlog.[ch] comparisons of different types - Avoid shift equal to bits in type (caused endless loop) - Fix uninitialized value bug in gzputc() introduced by const patches - Fix memory allocation error in examples/zran.c [Nor] - Fix bug where gzopen(), gzclose() would write an empty file - Fix bug in gzclose() when gzwrite() runs out of memory - Check for input buffer malloc failure in examples/gzappend.c - Add note to contrib/blast to use binary mode in stdio - Fix comparisons of differently signed integers in contrib/blast - Check for invalid code length codes in contrib/puff - Fix serious but very rare decompression bug in inftrees.c - Update inflateBack() comments, since inflate() can be faster - Use underscored I/O function names for WINAPI_FAMILY - Add _tr_flush_bits to the external symbols prefixed by --zprefix - Add contrib/vstudio/vc10 pre-build step for static only - Quote --version-script argument in CMakeLists.txt - Don't specify --version-script on Apple platforms in CMakeLists.txt - Fix casting error in contrib/testzlib/testzlib.c - Fix types in contrib/minizip to match result of get_crc_table() - Simplify contrib/vstudio/vc10 with 'd' suffix - Add TOP support to win32/Makefile.msc - Support i686 and amd64 assembler builds in CMakeLists.txt - Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h - Add vc11 and vc12 build files to contrib/vstudio - Add gzvprintf() as an undocumented function in zlib - Fix configure for Sun shell - Remove runtime check in configure for four-byte integer type - Add casts and consts to ease user conversion to C++ - Add man pages for minizip and miniunzip - In Makefile uninstall, don't rm if preceding cd fails - Do not return Z_BUF_ERROR if deflateParam() has nothing to write Changes in 1.2.7 (2 May 2012) - Replace use of memmove() with a simple copy for portability - Test for existence of strerror - Restore gzgetc_ for backward compatibility with 1.2.6 - Fix build with non-GNU make on Solaris - Require gcc 4.0 or later on Mac OS X to use the hidden attribute - Include unistd.h for Watcom C - Use __WATCOMC__ instead of __WATCOM__ - Do not use the visibility attribute if NO_VIZ defined - Improve the detection of no hidden visibility attribute - Avoid using __int64 for gcc or solo compilation - Cast to char * in gzprintf to avoid warnings [Zinser] - Fix make_vms.com for VAX [Zinser] - Don't use library or built-in byte swaps - Simplify test and use of gcc hidden attribute - Fix bug in gzclose_w() when gzwrite() fails to allocate memory - Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen() - Fix bug in test/minigzip.c for configure --solo - Fix contrib/vstudio project link errors [Mohanathas] - Add ability to choose the builder in make_vms.com [Schweda] - Add DESTDIR support to mingw32 win32/Makefile.gcc - Fix comments in win32/Makefile.gcc for proper usage - Allow overriding the default install locations for cmake - Generate and install the pkg-config file with cmake - Build both a static and a shared version of zlib with cmake - Include version symbols for cmake builds - If using cmake with MSVC, add the source directory to the includes - Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta] - Move obsolete emx makefile to old [Truta] - Allow the use of -Wundef when compiling or using zlib - Avoid the use of the -u option with mktemp - Improve inflate() documentation on the use of Z_FINISH - Recognize clang as gcc - Add gzopen_w() in Windows for wide character path names - Rename zconf.h in CMakeLists.txt to move it out of the way - Add source directory in CMakeLists.txt for building examples - Look in build directory for zlib.pc in CMakeLists.txt - Remove gzflags from zlibvc.def in vc9 and vc10 - Fix contrib/minizip compilation in the MinGW environment - Update ./configure for Solaris, support --64 [Mooney] - Remove -R. from Solaris shared build (possible security issue) - Avoid race condition for parallel make (-j) running example - Fix type mismatch between get_crc_table() and crc_table - Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler] - Fix the path to zlib.map in CMakeLists.txt - Force the native libtool in Mac OS X to avoid GNU libtool [Beebe] - Add instructions to win32/Makefile.gcc for shared install [Torri] Changes in 1.2.6.1 (12 Feb 2012) - Avoid the use of the Objective-C reserved name "id" - Include io.h in gzguts.h for Microsoft compilers - Fix problem with ./configure --prefix and gzgetc macro - Include gz_header definition when compiling zlib solo - Put gzflags() functionality back in zutil.c - Avoid library header include in crc32.c for Z_SOLO - Use name in GCC_CLASSIC as C compiler for coverage testing, if set - Minor cleanup in contrib/minizip/zip.c [Vollant] - Update make_vms.com [Zinser] - Remove unnecessary gzgetc_ function - Use optimized byte swap operations for Microsoft and GNU [Snyder] - Fix minor typo in zlib.h comments [Rzesniowiecki] Changes in 1.2.6 (29 Jan 2012) - Update the Pascal interface in contrib/pascal - Fix function numbers for gzgetc_ in zlibvc.def files - Fix configure.ac for contrib/minizip [Schiffer] - Fix large-entry detection in minizip on 64-bit systems [Schiffer] - Have ./configure use the compiler return code for error indication - Fix CMakeLists.txt for cross compilation [McClure] - Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes] - Fix compilation of contrib/minizip on FreeBSD [Marquez] - Correct suggested usages in win32/Makefile.msc [Shachar, Horvath] - Include io.h for Turbo C / Borland C on all platforms [Truta] - Make version explicit in contrib/minizip/configure.ac [Bosmans] - Avoid warning for no encryption in contrib/minizip/zip.c [Vollant] - Minor cleanup up contrib/minizip/unzip.c [Vollant] - Fix bug when compiling minizip with C++ [Vollant] - Protect for long name and extra fields in contrib/minizip [Vollant] - Avoid some warnings in contrib/minizip [Vollant] - Add -I../.. -L../.. to CFLAGS for minizip and miniunzip - Add missing libs to minizip linker command - Add support for VPATH builds in contrib/minizip - Add an --enable-demos option to contrib/minizip/configure - Add the generation of configure.log by ./configure - Exit when required parameters not provided to win32/Makefile.gcc - Have gzputc return the character written instead of the argument - Use the -m option on ldconfig for BSD systems [Tobias] - Correct in zlib.map when deflateResetKeep was added Changes in 1.2.5.3 (15 Jan 2012) - Restore gzgetc function for binary compatibility - Do not use _lseeki64 under Borland C++ [Truta] - Update win32/Makefile.msc to build test/*.c [Truta] - Remove old/visualc6 given CMakefile and other alternatives - Update AS400 build files and documentation [Monnerat] - Update win32/Makefile.gcc to build test/*.c [Truta] - Permit stronger flushes after Z_BLOCK flushes - Avoid extraneous empty blocks when doing empty flushes - Permit Z_NULL arguments to deflatePending - Allow deflatePrime() to insert bits in the middle of a stream - Remove second empty static block for Z_PARTIAL_FLUSH - Write out all of the available bits when using Z_BLOCK - Insert the first two strings in the hash table after a flush Changes in 1.2.5.2 (17 Dec 2011) - fix ld error: unable to find version dependency 'ZLIB_1.2.5' - use relative symlinks for shared libs - Avoid searching past window for Z_RLE strategy - Assure that high-water mark initialization is always applied in deflate - Add assertions to fill_window() in deflate.c to match comments - Update python link in README - Correct spelling error in gzread.c - Fix bug in gzgets() for a concatenated empty gzip stream - Correct error in comment for gz_make() - Change gzread() and related to ignore junk after gzip streams - Allow gzread() and related to continue after gzclearerr() - Allow gzrewind() and gzseek() after a premature end-of-file - Simplify gzseek() now that raw after gzip is ignored - Change gzgetc() to a macro for speed (~40% speedup in testing) - Fix gzclose() to return the actual error last encountered - Always add large file support for windows - Include zconf.h for windows large file support - Include zconf.h.cmakein for windows large file support - Update zconf.h.cmakein on make distclean - Merge vestigial vsnprintf determination from zutil.h to gzguts.h - Clarify how gzopen() appends in zlib.h comments - Correct documentation of gzdirect() since junk at end now ignored - Add a transparent write mode to gzopen() when 'T' is in the mode - Update python link in zlib man page - Get inffixed.h and MAKEFIXED result to match - Add a ./config --solo option to make zlib subset with no library use - Add undocumented inflateResetKeep() function for CAB file decoding - Add --cover option to ./configure for gcc coverage testing - Add #define ZLIB_CONST option to use const in the z_stream interface - Add comment to gzdopen() in zlib.h to use dup() when using fileno() - Note behavior of uncompress() to provide as much data as it can - Add files in contrib/minizip to aid in building libminizip - Split off AR options in Makefile.in and configure - Change ON macro to Z_ARG to avoid application conflicts - Facilitate compilation with Borland C++ for pragmas and vsnprintf - Include io.h for Turbo C / Borland C++ - Move example.c and minigzip.c to test/ - Simplify incomplete code table filling in inflate_table() - Remove code from inflate.c and infback.c that is impossible to execute - Test the inflate code with full coverage - Allow deflateSetDictionary, inflateSetDictionary at any time (in raw) - Add deflateResetKeep and fix inflateResetKeep to retain dictionary - Fix gzwrite.c to accommodate reduced memory zlib compilation - Have inflate() with Z_FINISH avoid the allocation of a window - Do not set strm->adler when doing raw inflate - Fix gzeof() to behave just like feof() when read is not past end of file - Fix bug in gzread.c when end-of-file is reached - Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF - Document gzread() capability to read concurrently written files - Remove hard-coding of resource compiler in CMakeLists.txt [Blammo] Changes in 1.2.5.1 (10 Sep 2011) - Update FAQ entry on shared builds (#13) - Avoid symbolic argument to chmod in Makefile.in - Fix bug and add consts in contrib/puff [Oberhumer] - Update contrib/puff/zeros.raw test file to have all block types - Add full coverage test for puff in contrib/puff/Makefile - Fix static-only-build install in Makefile.in - Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno] - Add libz.a dependency to shared in Makefile.in for parallel builds - Spell out "number" (instead of "nb") in zlib.h for total_in, total_out - Replace $(...) with `...` in configure for non-bash sh [Bowler] - Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen] - Add solaris* to Linux* in configure to allow gcc use [Groffen] - Add *bsd* to Linux* case in configure [Bar-Lev] - Add inffast.obj to dependencies in win32/Makefile.msc - Correct spelling error in deflate.h [Kohler] - Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc - Add test to configure for GNU C looking for gcc in output of $cc -v - Add zlib.pc generation to win32/Makefile.gcc [Weigelt] - Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not - Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense - Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser) - Make stronger test in zconf.h to include unistd.h for LFS - Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack] - Fix zlib.h LFS support when Z_PREFIX used - Add updated as400 support (removed from old) [Monnerat] - Avoid deflate sensitivity to volatile input data - Avoid division in adler32_combine for NO_DIVIDE - Clarify the use of Z_FINISH with deflateBound() amount of space - Set binary for output file in puff.c - Use u4 type for crc_table to avoid conversion warnings - Apply casts in zlib.h to avoid conversion warnings - Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] - Improve inflateSync() documentation to note indeterminacy - Add deflatePending() function to return the amount of pending output - Correct the spelling of "specification" in FAQ [Randers-Pehrson] - Add a check in configure for stdarg.h, use for gzprintf() - Check that pointers fit in ints when gzprint() compiled old style - Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] - Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] - Add debug records in assembler code [Londer] - Update RFC references to use http://tools.ietf.org/html/... [Li] - Add --archs option, use of libtool to configure for Mac OS X [Borstel] Changes in 1.2.5 (19 Apr 2010) - Disable visibility attribute in win32/Makefile.gcc [Bar-Lev] - Default to libdir as sharedlibdir in configure [Nieder] - Update copyright dates on modified source files - Update trees.c to be able to generate modified trees.h - Exit configure for MinGW, suggesting win32/Makefile.gcc - Check for NULL path in gz_open [Homurlu] Changes in 1.2.4.5 (18 Apr 2010) - Set sharedlibdir in configure [Torok] - Set LDFLAGS in Makefile.in [Bar-Lev] - Avoid mkdir objs race condition in Makefile.in [Bowler] - Add ZLIB_INTERNAL in front of internal inter-module functions and arrays - Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C - Don't use hidden attribute when it is a warning generator (e.g. Solaris) Changes in 1.2.4.4 (18 Apr 2010) - Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok] - Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty - Try to use bash or ksh regardless of functionality of /bin/sh - Fix configure incompatibility with NetBSD sh - Remove attempt to run under bash or ksh since have better NetBSD fix - Fix win32/Makefile.gcc for MinGW [Bar-Lev] - Add diagnostic messages when using CROSS_PREFIX in configure - Added --sharedlibdir option to configure [Weigelt] - Use hidden visibility attribute when available [Frysinger] Changes in 1.2.4.3 (10 Apr 2010) - Only use CROSS_PREFIX in configure for ar and ranlib if they exist - Use CROSS_PREFIX for nm [Bar-Lev] - Assume _LARGEFILE64_SOURCE defined is equivalent to true - Avoid use of undefined symbols in #if with && and || - Make *64 prototypes in gzguts.h consistent with functions - Add -shared load option for MinGW in configure [Bowler] - Move z_off64_t to public interface, use instead of off64_t - Remove ! from shell test in configure (not portable to Solaris) - Change +0 macro tests to -0 for possibly increased portability Changes in 1.2.4.2 (9 Apr 2010) - Add consistent carriage returns to readme.txt's in masmx86 and masmx64 - Really provide prototypes for *64 functions when building without LFS - Only define unlink() in minigzip.c if unistd.h not included - Update README to point to contrib/vstudio project files - Move projects/vc6 to old/ and remove projects/ - Include stdlib.h in minigzip.c for setmode() definition under WinCE - Clean up assembler builds in win32/Makefile.msc [Rowe] - Include sys/types.h for Microsoft for off_t definition - Fix memory leak on error in gz_open() - Symbolize nm as $NM in configure [Weigelt] - Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt] - Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined - Fix bug in gzeof() to take into account unused input data - Avoid initialization of structures with variables in puff.c - Updated win32/README-WIN32.txt [Rowe] Changes in 1.2.4.1 (28 Mar 2010) - Remove the use of [a-z] constructs for sed in configure [gentoo 310225] - Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech] - Restore "for debugging" comment on sprintf() in gzlib.c - Remove fdopen for MVS from gzguts.h - Put new README-WIN32.txt in win32 [Rowe] - Add check for shell to configure and invoke another shell if needed - Fix big fat stinking bug in gzseek() on uncompressed files - Remove vestigial F_OPEN64 define in zutil.h - Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE - Avoid errors on non-LFS systems when applications define LFS macros - Set EXE to ".exe" in configure for MINGW [Kahle] - Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill] - Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev] - Add DLL install in win32/makefile.gcc [Bar-Lev] - Allow Linux* or linux* from uname in configure [Bar-Lev] - Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev] - Add cross-compilation prefixes to configure [Bar-Lev] - Match type exactly in gz_load() invocation in gzread.c - Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func - Provide prototypes for *64 functions when building zlib without LFS - Don't use -lc when linking shared library on MinGW - Remove errno.h check in configure and vestigial errno code in zutil.h Changes in 1.2.4 (14 Mar 2010) - Fix VER3 extraction in configure for no fourth subversion - Update zlib.3, add docs to Makefile.in to make .pdf out of it - Add zlib.3.pdf to distribution - Don't set error code in gzerror() if passed pointer is NULL - Apply destination directory fixes to CMakeLists.txt [Lowman] - Move #cmakedefine's to a new zconf.in.cmakein - Restore zconf.h for builds that don't use configure or cmake - Add distclean to dummy Makefile for convenience - Update and improve INDEX, README, and FAQ - Update CMakeLists.txt for the return of zconf.h [Lowman] - Update contrib/vstudio/vc9 and vc10 [Vollant] - Change libz.dll.a back to libzdll.a in win32/Makefile.gcc - Apply license and readme changes to contrib/asm686 [Raiter] - Check file name lengths and add -c option in minigzip.c [Li] - Update contrib/amd64 and contrib/masmx86/ [Vollant] - Avoid use of "eof" parameter in trees.c to not shadow library variable - Update make_vms.com for removal of zlibdefs.h [Zinser] - Update assembler code and vstudio projects in contrib [Vollant] - Remove outdated assembler code contrib/masm686 and contrib/asm586 - Remove old vc7 and vc8 from contrib/vstudio - Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe] - Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open() - Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant] - Remove *64 functions from win32/zlib.def (they're not 64-bit yet) - Fix bug in void-returning vsprintf() case in gzwrite.c - Fix name change from inflate.h in contrib/inflate86/inffas86.c - Check if temporary file exists before removing in make_vms.com [Zinser] - Fix make install and uninstall for --static option - Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta] - Update readme.txt in contrib/masmx64 and masmx86 to assemble Changes in 1.2.3.9 (21 Feb 2010) - Expunge gzio.c - Move as400 build information to old - Fix updates in contrib/minizip and contrib/vstudio - Add const to vsnprintf test in configure to avoid warnings [Weigelt] - Delete zconf.h (made by configure) [Weigelt] - Change zconf.in.h to zconf.h.in per convention [Weigelt] - Check for NULL buf in gzgets() - Return empty string for gzgets() with len == 1 (like fgets()) - Fix description of gzgets() in zlib.h for end-of-file, NULL return - Update minizip to 1.1 [Vollant] - Avoid MSVC loss of data warnings in gzread.c, gzwrite.c - Note in zlib.h that gzerror() should be used to distinguish from EOF - Remove use of snprintf() from gzlib.c - Fix bug in gzseek() - Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant] - Fix zconf.h generation in CMakeLists.txt [Lowman] - Improve comments in zconf.h where modified by configure Changes in 1.2.3.8 (13 Feb 2010) - Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer] - Use z_off64_t in gz_zero() and gz_skip() to match state->skip - Avoid comparison problem when sizeof(int) == sizeof(z_off64_t) - Revert to Makefile.in from 1.2.3.6 (live with the clutter) - Fix missing error return in gzflush(), add zlib.h note - Add *64 functions to zlib.map [Levin] - Fix signed/unsigned comparison in gz_comp() - Use SFLAGS when testing shared linking in configure - Add --64 option to ./configure to use -m64 with gcc - Fix ./configure --help to correctly name options - Have make fail if a test fails [Levin] - Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson] - Remove assembler object files from contrib Changes in 1.2.3.7 (24 Jan 2010) - Always gzopen() with O_LARGEFILE if available - Fix gzdirect() to work immediately after gzopen() or gzdopen() - Make gzdirect() more precise when the state changes while reading - Improve zlib.h documentation in many places - Catch memory allocation failure in gz_open() - Complete close operation if seek forward in gzclose_w() fails - Return Z_ERRNO from gzclose_r() if close() fails - Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL - Return zero for gzwrite() errors to match zlib.h description - Return -1 on gzputs() error to match zlib.h description - Add zconf.in.h to allow recovery from configure modification [Weigelt] - Fix static library permissions in Makefile.in [Weigelt] - Avoid warnings in configure tests that hide functionality [Weigelt] - Add *BSD and DragonFly to Linux case in configure [gentoo 123571] - Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212] - Avoid access of uninitialized data for first inflateReset2 call [Gomes] - Keep object files in subdirectories to reduce the clutter somewhat - Remove default Makefile and zlibdefs.h, add dummy Makefile - Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_ - Remove zlibdefs.h completely -- modify zconf.h instead Changes in 1.2.3.6 (17 Jan 2010) - Avoid void * arithmetic in gzread.c and gzwrite.c - Make compilers happier with const char * for gz_error message - Avoid unused parameter warning in inflate.c - Avoid signed-unsigned comparison warning in inflate.c - Indent #pragma's for traditional C - Fix usage of strwinerror() in glib.c, change to gz_strwinerror() - Correct email address in configure for system options - Update make_vms.com and add make_vms.com to contrib/minizip [Zinser] - Update zlib.map [Brown] - Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok] - Apply various fixes to CMakeLists.txt [Lowman] - Add checks on len in gzread() and gzwrite() - Add error message for no more room for gzungetc() - Remove zlib version check in gzwrite() - Defer compression of gzprintf() result until need to - Use snprintf() in gzdopen() if available - Remove USE_MMAP configuration determination (only used by minigzip) - Remove examples/pigz.c (available separately) - Update examples/gun.c to 1.6 Changes in 1.2.3.5 (8 Jan 2010) - Add space after #if in zutil.h for some compilers - Fix relatively harmless bug in deflate_fast() [Exarevsky] - Fix same problem in deflate_slow() - Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown] - Add deflate_rle() for faster Z_RLE strategy run-length encoding - Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding - Change name of "write" variable in inffast.c to avoid library collisions - Fix premature EOF from gzread() in gzio.c [Brown] - Use zlib header window size if windowBits is 0 in inflateInit2() - Remove compressBound() call in deflate.c to avoid linking compress.o - Replace use of errno in gz* with functions, support WinCE [Alves] - Provide alternative to perror() in minigzip.c for WinCE [Alves] - Don't use _vsnprintf on later versions of MSVC [Lowman] - Add CMake build script and input file [Lowman] - Update contrib/minizip to 1.1 [Svensson, Vollant] - Moved nintendods directory from contrib to root - Replace gzio.c with a new set of routines with the same functionality - Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above - Update contrib/minizip to 1.1b - Change gzeof() to return 0 on error instead of -1 to agree with zlib.h Changes in 1.2.3.4 (21 Dec 2009) - Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility - Update comments in configure and Makefile.in for default --shared - Fix test -z's in configure [Marquess] - Build examplesh and minigzipsh when not testing - Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h - Import LDFLAGS from the environment in configure - Fix configure to populate SFLAGS with discovered CFLAGS options - Adapt make_vms.com to the new Makefile.in [Zinser] - Add zlib2ansi script for C++ compilation [Marquess] - Add _FILE_OFFSET_BITS=64 test to make test (when applicable) - Add AMD64 assembler code for longest match to contrib [Teterin] - Include options from $SFLAGS when doing $LDSHARED - Simplify 64-bit file support by introducing z_off64_t type - Make shared object files in objs directory to work around old Sun cc - Use only three-part version number for Darwin shared compiles - Add rc option to ar in Makefile.in for when ./configure not run - Add -WI,-rpath,. to LDFLAGS for OSF 1 V4* - Set LD_LIBRARYN32_PATH for SGI IRIX shared compile - Protect against _FILE_OFFSET_BITS being defined when compiling zlib - Rename Makefile.in targets allstatic to static and allshared to shared - Fix static and shared Makefile.in targets to be independent - Correct error return bug in gz_open() by setting state [Brown] - Put spaces before ;;'s in configure for better sh compatibility - Add pigz.c (parallel implementation of gzip) to examples/ - Correct constant in crc32.c to UL [Leventhal] - Reject negative lengths in crc32_combine() - Add inflateReset2() function to work like inflateEnd()/inflateInit2() - Include sys/types.h for _LARGEFILE64_SOURCE [Brown] - Correct typo in doc/algorithm.txt [Janik] - Fix bug in adler32_combine() [Zhu] - Catch missing-end-of-block-code error in all inflates and in puff Assures that random input to inflate eventually results in an error - Added enough.c (calculation of ENOUGH for inftrees.h) to examples/ - Update ENOUGH and its usage to reflect discovered bounds - Fix gzerror() error report on empty input file [Brown] - Add ush casts in trees.c to avoid pedantic runtime errors - Fix typo in zlib.h uncompress() description [Reiss] - Correct inflate() comments with regard to automatic header detection - Remove deprecation comment on Z_PARTIAL_FLUSH (it stays) - Put new version of gzlog (2.0) in examples with interruption recovery - Add puff compile option to permit invalid distance-too-far streams - Add puff TEST command options, ability to read piped input - Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but _LARGEFILE64_SOURCE not defined - Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart - Fix deflateSetDictionary() to use all 32K for output consistency - Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h) - Clear bytes after deflate lookahead to avoid use of uninitialized data - Change a limit in inftrees.c to be more transparent to Coverity Prevent - Update win32/zlib.def with exported symbols from zlib.h - Correct spelling errors in zlib.h [Willem, Sobrado] - Allow Z_BLOCK for deflate() to force a new block - Allow negative bits in inflatePrime() to delete existing bit buffer - Add Z_TREES flush option to inflate() to return at end of trees - Add inflateMark() to return current state information for random access - Add Makefile for NintendoDS to contrib [Costa] - Add -w in configure compile tests to avoid spurious warnings [Beucler] - Fix typos in zlib.h comments for deflateSetDictionary() - Fix EOF detection in transparent gzread() [Maier] Changes in 1.2.3.3 (2 October 2006) - Make --shared the default for configure, add a --static option - Add compile option to permit invalid distance-too-far streams - Add inflateUndermine() function which is required to enable above - Remove use of "this" variable name for C++ compatibility [Marquess] - Add testing of shared library in make test, if shared library built - Use ftello() and fseeko() if available instead of ftell() and fseek() - Provide two versions of all functions that use the z_off_t type for binary compatibility -- a normal version and a 64-bit offset version, per the Large File Support Extension when _LARGEFILE64_SOURCE is defined; use the 64-bit versions by default when _FILE_OFFSET_BITS is defined to be 64 - Add a --uname= option to configure to perhaps help with cross-compiling Changes in 1.2.3.2 (3 September 2006) - Turn off silly Borland warnings [Hay] - Use off64_t and define _LARGEFILE64_SOURCE when present - Fix missing dependency on inffixed.h in Makefile.in - Rig configure --shared to build both shared and static [Teredesai, Truta] - Remove zconf.in.h and instead create a new zlibdefs.h file - Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant] - Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt] Changes in 1.2.3.1 (16 August 2006) - Add watcom directory with OpenWatcom make files [Daniel] - Remove #undef of FAR in zconf.in.h for MVS [Fedtke] - Update make_vms.com [Zinser] - Use -fPIC for shared build in configure [Teredesai, Nicholson] - Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen] - Use fdopen() (not _fdopen()) for Interix in zutil.h [Bäck] - Add some FAQ entries about the contrib directory - Update the MVS question in the FAQ - Avoid extraneous reads after EOF in gzio.c [Brown] - Correct spelling of "successfully" in gzio.c [Randers-Pehrson] - Add comments to zlib.h about gzerror() usage [Brown] - Set extra flags in gzip header in gzopen() like deflate() does - Make configure options more compatible with double-dash conventions [Weigelt] - Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen] - Fix uninstall target in Makefile.in [Truta] - Add pkgconfig support [Weigelt] - Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt] - Replace set_data_type() with a more accurate detect_data_type() in trees.c, according to the txtvsbin.txt document [Truta] - Swap the order of #include and #include "zlib.h" in gzio.c, example.c and minigzip.c [Truta] - Shut up annoying VS2005 warnings about standard C deprecation [Rowe, Truta] (where?) - Fix target "clean" from win32/Makefile.bor [Truta] - Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe] - Update zlib www home address in win32/DLL_FAQ.txt [Truta] - Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove] - Enable browse info in the "Debug" and "ASM Debug" configurations in the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta] - Add pkgconfig support [Weigelt] - Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h, for use in win32/zlib1.rc [Polushin, Rowe, Truta] - Add a document that explains the new text detection scheme to doc/txtvsbin.txt [Truta] - Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta] - Move algorithm.txt into doc/ [Truta] - Synchronize FAQ with website - Fix compressBound(), was low for some pathological cases [Fearnley] - Take into account wrapper variations in deflateBound() - Set examples/zpipe.c input and output to binary mode for Windows - Update examples/zlib_how.html with new zpipe.c (also web site) - Fix some warnings in examples/gzlog.c and examples/zran.c (it seems that gcc became pickier in 4.0) - Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain un-versioned, the patch adds versioning only for symbols introduced in zlib-1.2.0 or later. It also declares as local those symbols which are not designed to be exported." [Levin] - Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure - Do not initialize global static by default in trees.c, add a response NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess] - Don't use strerror() in gzio.c under WinCE [Yakimov] - Don't use errno.h in zutil.h under WinCE [Yakimov] - Move arguments for AR to its usage to allow replacing ar [Marot] - Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson] - Improve inflateInit() and inflateInit2() documentation - Fix structure size comment in inflate.h - Change configure help option from --h* to --help [Santos] Changes in 1.2.3 (18 July 2005) - Apply security vulnerability fixes to contrib/infback9 as well - Clean up some text files (carriage returns, trailing space) - Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] Changes in 1.2.2.4 (11 July 2005) - Add inflatePrime() function for starting inflation at bit boundary - Avoid some Visual C warnings in deflate.c - Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit compile - Fix some spelling errors in comments [Betts] - Correct inflateInit2() error return documentation in zlib.h - Add zran.c example of compressed data random access to examples directory, shows use of inflatePrime() - Fix cast for assignments to strm->state in inflate.c and infback.c - Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] - Move declarations of gf2 functions to right place in crc32.c [Oberhumer] - Add cast in trees.c t avoid a warning [Oberhumer] - Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] - Update make_vms.com [Zinser] - Initialize state->write in inflateReset() since copied in inflate_fast() - Be more strict on incomplete code sets in inflate_table() and increase ENOUGH and MAXD -- this repairs a possible security vulnerability for invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for discovering the vulnerability and providing test cases - Add ia64 support to configure for HP-UX [Smith] - Add error return to gzread() for format or i/o error [Levin] - Use malloc.h for OS/2 [Necasek] Changes in 1.2.2.3 (27 May 2005) - Replace 1U constants in inflate.c and inftrees.c for 64-bit compile - Typecast fread() return values in gzio.c [Vollant] - Remove trailing space in minigzip.c outmode (VC++ can't deal with it) - Fix crc check bug in gzread() after gzungetc() [Heiner] - Add the deflateTune() function to adjust internal compression parameters - Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) - Remove an incorrect assertion in examples/zpipe.c - Add C++ wrapper in infback9.h [Donais] - Fix bug in inflateCopy() when decoding fixed codes - Note in zlib.h how much deflateSetDictionary() actually uses - Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) - Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] - Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] - Add gzdirect() function to indicate transparent reads - Update contrib/minizip [Vollant] - Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] - Add casts in crc32.c to avoid warnings [Oberhumer] - Add contrib/masmx64 [Vollant] - Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] Changes in 1.2.2.2 (30 December 2004) - Replace structure assignments in deflate.c and inflate.c with zmemcpy to avoid implicit memcpy calls (portability for no-library compilation) - Increase sprintf() buffer size in gzdopen() to allow for large numbers - Add INFLATE_STRICT to check distances against zlib header - Improve WinCE errno handling and comments [Chang] - Remove comment about no gzip header processing in FAQ - Add Z_FIXED strategy option to deflateInit2() to force fixed trees - Add updated make_vms.com [Coghlan], update README - Create a new "examples" directory, move gzappend.c there, add zpipe.c, fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html - Add FAQ entry and comments in deflate.c on uninitialized memory access - Add Solaris 9 make options in configure [Gilbert] - Allow strerror() usage in gzio.c for STDC - Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] - Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] - Use z_off_t for adler32_combine() and crc32_combine() lengths - Make adler32() much faster for small len - Use OS_CODE in deflate() default gzip header Changes in 1.2.2.1 (31 October 2004) - Allow inflateSetDictionary() call for raw inflate - Fix inflate header crc check bug for file names and comments - Add deflateSetHeader() and gz_header structure for custom gzip headers - Add inflateGetheader() to retrieve gzip headers - Add crc32_combine() and adler32_combine() functions - Add alloc_func, free_func, in_func, out_func to Z_PREFIX list - Use zstreamp consistently in zlib.h (inflate_back functions) - Remove GUNZIP condition from definition of inflate_mode in inflate.h and in contrib/inflate86/inffast.S [Truta, Anderson] - Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] - Update projects/README.projects and projects/visualc6 [Truta] - Update win32/DLL_FAQ.txt [Truta] - Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] - Deprecate Z_ASCII; use Z_TEXT instead [Truta] - Use a new algorithm for setting strm->data_type in trees.c [Truta] - Do not define an exit() prototype in zutil.c unless DEBUG defined - Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] - Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() - Fix Darwin build version identification [Peterson] Changes in 1.2.2 (3 October 2004) - Update zlib.h comments on gzip in-memory processing - Set adler to 1 in inflateReset() to support Java test suite [Walles] - Add contrib/dotzlib [Ravn] - Update win32/DLL_FAQ.txt [Truta] - Update contrib/minizip [Vollant] - Move contrib/visual-basic.txt to old/ [Truta] - Fix assembler builds in projects/visualc6/ [Truta] Changes in 1.2.1.2 (9 September 2004) - Update INDEX file - Fix trees.c to update strm->data_type (no one ever noticed!) - Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] - Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) - Add limited multitasking protection to DYNAMIC_CRC_TABLE - Add NO_vsnprintf for VMS in zutil.h [Mozilla] - Don't declare strerror() under VMS [Mozilla] - Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize - Update contrib/ada [Anisimkov] - Update contrib/minizip [Vollant] - Fix configure to not hardcode directories for Darwin [Peterson] - Fix gzio.c to not return error on empty files [Brown] - Fix indentation; update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas [Truta] - Update mkasm.bat in contrib/masmx86 [Truta] - Update contrib/untgz [Truta] - Add projects/README.projects [Truta] - Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] - Update win32/DLL_FAQ.txt [Truta] - Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] - Remove an unnecessary assignment to curr in inftrees.c [Truta] - Add OS/2 to exe builds in configure [Poltorak] - Remove err dummy parameter in zlib.h [Kientzle] Changes in 1.2.1.1 (9 January 2004) - Update email address in README - Several FAQ updates - Fix a big fat bug in inftrees.c that prevented decoding valid dynamic blocks with only literals and no distance codes -- Thanks to "Hot Emu" for the bug report and sample file - Add a note to puff.c on no distance codes case Changes in 1.2.1 (17 November 2003) - Remove a tab in contrib/gzappend/gzappend.c - Update some interfaces in contrib for new zlib functions - Update zlib version number in some contrib entries - Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] - Support shared libraries on Hurd and KFreeBSD [Brown] - Fix error in NO_DIVIDE option of adler32.c Changes in 1.2.0.8 (4 November 2003) - Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas - Add experimental NO_DIVIDE #define in adler32.c - Possibly faster on some processors (let me know if it is) - Correct Z_BLOCK to not return on first inflate call if no wrap - Fix strm->data_type on inflate() return to correctly indicate EOB - Add deflatePrime() function for appending in the middle of a byte - Add contrib/gzappend for an example of appending to a stream - Update win32/DLL_FAQ.txt [Truta] - Delete Turbo C comment in README [Truta] - Improve some indentation in zconf.h [Truta] - Fix infinite loop on bad input in configure script [Church] - Fix gzeof() for concatenated gzip files [Johnson] - Add example to contrib/visual-basic.txt [Michael B.] - Add -p to mkdir's in Makefile.in [vda] - Fix configure to properly detect presence or lack of printf functions - Add AS400 support [Monnerat] - Add a little Cygwin support [Wilson] Changes in 1.2.0.7 (21 September 2003) - Correct some debug formats in contrib/infback9 - Cast a type in a debug statement in trees.c - Change search and replace delimiter in configure from % to # [Beebe] - Update contrib/untgz to 0.2 with various fixes [Truta] - Add build support for Amiga [Nikl] - Remove some directories in old that have been updated to 1.2 - Add dylib building for Mac OS X in configure and Makefile.in - Remove old distribution stuff from Makefile - Update README to point to DLL_FAQ.txt, and add comment on Mac OS X - Update links in README Changes in 1.2.0.6 (13 September 2003) - Minor FAQ updates - Update contrib/minizip to 1.00 [Vollant] - Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] - Update POSTINC comment for 68060 [Nikl] - Add contrib/infback9 with deflate64 decoding (unsupported) - For MVS define NO_vsnprintf and undefine FAR [van Burik] - Add pragma for fdopen on MVS [van Burik] Changes in 1.2.0.5 (8 September 2003) - Add OF to inflateBackEnd() declaration in zlib.h - Remember start when using gzdopen in the middle of a file - Use internal off_t counters in gz* functions to properly handle seeks - Perform more rigorous check for distance-too-far in inffast.c - Add Z_BLOCK flush option to return from inflate at block boundary - Set strm->data_type on return from inflate - Indicate bits unused, if at block boundary, and if in last block - Replace size_t with ptrdiff_t in crc32.c, and check for correct size - Add condition so old NO_DEFLATE define still works for compatibility - FAQ update regarding the Windows DLL [Truta] - INDEX update: add qnx entry, remove aix entry [Truta] - Install zlib.3 into mandir [Wilson] - Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] - Adapt the zlib interface to the new DLL convention guidelines [Truta] - Introduce ZLIB_WINAPI macro to allow the export of functions using the WINAPI calling convention, for Visual Basic [Vollant, Truta] - Update msdos and win32 scripts and makefiles [Truta] - Export symbols by name, not by ordinal, in win32/zlib.def [Truta] - Add contrib/ada [Anisimkov] - Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] - Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] - Add contrib/masm686 [Truta] - Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm [Truta, Vollant] - Update contrib/delphi; rename to contrib/pascal; add example [Truta] - Remove contrib/delphi2; add a new contrib/delphi [Truta] - Avoid inclusion of the nonstandard in contrib/iostream, and fix some method prototypes [Truta] - Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip [Truta] - Avoid the use of backslash (\) in contrib/minizip [Vollant] - Fix file time handling in contrib/untgz; update makefiles [Truta] - Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines [Vollant] - Remove contrib/vstudio/vc15_16 [Vollant] - Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] - Update README.contrib [Truta] - Invert the assignment order of match_head and s->prev[...] in INSERT_STRING [Truta] - Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings [Truta] - Compare function pointers with 0, not with NULL or Z_NULL [Truta] - Fix prototype of syncsearch in inflate.c [Truta] - Introduce ASMINF macro to be enabled when using an ASM implementation of inflate_fast [Truta] - Change NO_DEFLATE to NO_GZCOMPRESS [Truta] - Modify test_gzio in example.c to take a single file name as a parameter [Truta] - Exit the example.c program if gzopen fails [Truta] - Add type casts around strlen in example.c [Truta] - Remove casting to sizeof in minigzip.c; give a proper type to the variable compared with SUFFIX_LEN [Truta] - Update definitions of STDC and STDC99 in zconf.h [Truta] - Synchronize zconf.h with the new Windows DLL interface [Truta] - Use SYS16BIT instead of __32BIT__ to distinguish between 16- and 32-bit platforms [Truta] - Use far memory allocators in small 16-bit memory models for Turbo C [Truta] - Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in zlibCompileFlags [Truta] - Cygwin has vsnprintf [Wilson] - In Windows16, OS_CODE is 0, as in MSDOS [Truta] - In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] Changes in 1.2.0.4 (10 August 2003) - Minor FAQ updates - Be more strict when checking inflateInit2's windowBits parameter - Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well - Add gzip wrapper option to deflateInit2 using windowBits - Add updated QNX rule in configure and qnx directory [Bonnefoy] - Make inflate distance-too-far checks more rigorous - Clean up FAR usage in inflate - Add casting to sizeof() in gzio.c and minigzip.c Changes in 1.2.0.3 (19 July 2003) - Fix silly error in gzungetc() implementation [Vollant] - Update contrib/minizip and contrib/vstudio [Vollant] - Fix printf format in example.c - Correct cdecl support in zconf.in.h [Anisimkov] - Minor FAQ updates Changes in 1.2.0.2 (13 July 2003) - Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons - Attempt to avoid warnings in crc32.c for pointer-int conversion - Add AIX to configure, remove aix directory [Bakker] - Add some casts to minigzip.c - Improve checking after insecure sprintf() or vsprintf() calls - Remove #elif's from crc32.c - Change leave label to inf_leave in inflate.c and infback.c to avoid library conflicts - Remove inflate gzip decoding by default--only enable gzip decoding by special request for stricter backward compatibility - Add zlibCompileFlags() function to return compilation information - More typecasting in deflate.c to avoid warnings - Remove leading underscore from _Capital #defines [Truta] - Fix configure to link shared library when testing - Add some Windows CE target adjustments [Mai] - Remove #define ZLIB_DLL in zconf.h [Vollant] - Add zlib.3 [Rodgers] - Update RFC URL in deflate.c and algorithm.txt [Mai] - Add zlib_dll_FAQ.txt to contrib [Truta] - Add UL to some constants [Truta] - Update minizip and vstudio [Vollant] - Remove vestigial NEED_DUMMY_RETURN from zconf.in.h - Expand use of NO_DUMMY_DECL to avoid all dummy structures - Added iostream3 to contrib [Schwardt] - Replace rewind() with fseek() for WinCE [Truta] - Improve setting of zlib format compression level flags - Report 0 for huffman and rle strategies and for level == 0 or 1 - Report 2 only for level == 6 - Only deal with 64K limit when necessary at compile time [Truta] - Allow TOO_FAR check to be turned off at compile time [Truta] - Add gzclearerr() function [Souza] - Add gzungetc() function Changes in 1.2.0.1 (17 March 2003) - Add Z_RLE strategy for run-length encoding [Truta] - When Z_RLE requested, restrict matches to distance one - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE - Correct FASTEST compilation to allow level == 0 - Clean up what gets compiled for FASTEST - Incorporate changes to zconf.in.h [Vollant] - Refine detection of Turbo C need for dummy returns - Refine ZLIB_DLL compilation - Include additional header file on VMS for off_t typedef - Try to use _vsnprintf where it supplants vsprintf [Vollant] - Add some casts in inffast.c - Enhance comments in zlib.h on what happens if gzprintf() tries to write more than 4095 bytes before compression - Remove unused state from inflateBackEnd() - Remove exit(0) from minigzip.c, example.c - Get rid of all those darn tabs - Add "check" target to Makefile.in that does the same thing as "test" - Add "mostlyclean" and "maintainer-clean" targets to Makefile.in - Update contrib/inflate86 [Anderson] - Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] - Add msdos and win32 directories with makefiles [Truta] - More additions and improvements to the FAQ Changes in 1.2.0 (9 March 2003) - New and improved inflate code - About 20% faster - Does not allocate 32K window unless and until needed - Automatically detects and decompresses gzip streams - Raw inflate no longer needs an extra dummy byte at end - Added inflateBack functions using a callback interface--even faster than inflate, useful for file utilities (gzip, zip) - Added inflateCopy() function to record state for random access on externally generated deflate streams (e.g. in gzip files) - More readable code (I hope) - New and improved crc32() - About 50% faster, thanks to suggestions from Rodney Brown - Add deflateBound() and compressBound() functions - Fix memory leak in deflateInit2() - Permit setting dictionary for raw deflate (for parallel deflate) - Fix const declaration for gzwrite() - Check for some malloc() failures in gzio.c - Fix bug in gzopen() on single-byte file 0x1f - Fix bug in gzread() on concatenated file with 0x1f at end of buffer and next buffer doesn't start with 0x8b - Fix uncompress() to return Z_DATA_ERROR on truncated input - Free memory at end of example.c - Remove MAX #define in trees.c (conflicted with some libraries) - Fix static const's in deflate.c, gzio.c, and zutil.[ch] - Declare malloc() and free() in gzio.c if STDC not defined - Use malloc() instead of calloc() in zutil.c if int big enough - Define STDC for AIX - Add aix/ with approach for compiling shared library on AIX - Add HP-UX support for shared libraries in configure - Add OpenUNIX support for shared libraries in configure - Use $cc instead of gcc to build shared library - Make prefix directory if needed when installing - Correct Macintosh avoidance of typedef Byte in zconf.h - Correct Turbo C memory allocation when under Linux - Use libz.a instead of -lz in Makefile (assure use of compiled library) - Update configure to check for snprintf or vsnprintf functions and their return value, warn during make if using an insecure function - Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that is lost when library is used--resolution is to build new zconf.h - Documentation improvements (in zlib.h): - Document raw deflate and inflate - Update RFCs URL - Point out that zlib and gzip formats are different - Note that Z_BUF_ERROR is not fatal - Document string limit for gzprintf() and possible buffer overflow - Note requirement on avail_out when flushing - Note permitted values of flush parameter of inflate() - Add some FAQs (and even answers) to the FAQ - Add contrib/inflate86/ for x86 faster inflate - Add contrib/blast/ for PKWare Data Compression Library decompression - Add contrib/puff/ simple inflate for deflate format description Changes in 1.1.4 (11 March 2002) - ZFREE was repeated on same allocation on some error conditions This creates a security problem described in http://www.zlib.org/advisory-2002-03-11.txt - Returned incorrect error (Z_MEM_ERROR) on some invalid data - Avoid accesses before window for invalid distances with inflate window less than 32K - force windowBits > 8 to avoid a bug in the encoder for a window size of 256 bytes. (A complete fix will be available in 1.1.5) Changes in 1.1.3 (9 July 1998) - fix "an inflate input buffer bug that shows up on rare but persistent occasions" (Mark) - fix gzread and gztell for concatenated .gz files (Didier Le Botlan) - fix gzseek(..., SEEK_SET) in write mode - fix crc check after a gzeek (Frank Faubert) - fix miniunzip when the last entry in a zip file is itself a zip file (J Lillge) - add contrib/asm586 and contrib/asm686 (Brian Raiter) See http://www.muppetlabs.com/~breadbox/software/assembly.html - add support for Delphi 3 in contrib/delphi (Bob Dellaca) - add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) - do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) - use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) - added a FAQ file - Support gzdopen on Mac with Metrowerks (Jason Linhart) - Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) - define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) - avoid some warnings with Borland C (Tom Tanner) - fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) - emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) - allow several arguments to configure (Tim Mooney, Frodo Looijaard) - use libdir and includedir in Makefile.in (Tim Mooney) - support shared libraries on OSF1 V4 (Tim Mooney) - remove so_locations in "make clean" (Tim Mooney) - fix maketree.c compilation error (Glenn, Mark) - Python interface to zlib now in Python 1.5 (Jeremy Hylton) - new Makefile.riscos (Rich Walker) - initialize static descriptors in trees.c for embedded targets (Nick Smith) - use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) - add the OS/2 files in Makefile.in too (Andrew Zabolotny) - fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) - fix maketree.c to allow clean compilation of inffixed.h (Mark) - fix parameter check in deflateCopy (Gunther Nikl) - cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) - Many portability patches by Christian Spieler: . zutil.c, zutil.h: added "const" for zmem* . Make_vms.com: fixed some typos . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists . msdos/Makefile.msc: remove "default rtl link library" info from obj files . msdos/Makefile.*: use model-dependent name for the built zlib library . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) - use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) - replace __far with _far for better portability (Christian Spieler, Tom Lane) - fix test for errno.h in configure (Tim Newsham) Changes in 1.1.2 (19 March 98) - added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) See http://www.winimage.com/zLibDll/unzip.html - preinitialize the inflate tables for fixed codes, to make the code completely thread safe (Mark) - some simplifications and slight speed-up to the inflate code (Mark) - fix gzeof on non-compressed files (Allan Schrum) - add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) - use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) - added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) - add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) - do not wrap extern "C" around system includes (Tom Lane) - mention zlib binding for TCL in README (Andreas Kupries) - added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) - allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) - allow "configure --prefix $HOME" (Tim Mooney) - remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) - move Makefile.sas to amiga/Makefile.sas Changes in 1.1.1 (27 Feb 98) - fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) - remove block truncation heuristic which had very marginal effect for zlib (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the compression ratio on some files. This also allows inlining _tr_tally for matches in deflate_slow - added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) Changes in 1.1.0 (24 Feb 98) - do not return STREAM_END prematurely in inflate (John Bowler) - revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) - compile with -DFASTEST to get compression code optimized for speed only - in minigzip, try mmap'ing the input file first (Miguel Albrecht) - increase size of I/O buffers in minigzip.c and gzio.c (not a big gain on Sun but significant on HP) - add a pointer to experimental unzip library in README (Gilles Vollant) - initialize variable gcc in configure (Chris Herborth) Changes in 1.0.9 (17 Feb 1998) - added gzputs and gzgets functions - do not clear eof flag in gzseek (Mark Diekhans) - fix gzseek for files in transparent mode (Mark Diekhans) - do not assume that vsprintf returns the number of bytes written (Jens Krinke) - replace EXPORT with ZEXPORT to avoid conflict with other programs - added compress2 in zconf.h, zlib.def, zlib.dnt - new asm code from Gilles Vollant in contrib/asm386 - simplify the inflate code (Mark): . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() . ZALLOC the length list in inflate_trees_fixed() instead of using stack . ZALLOC the value area for huft_build() instead of using stack . Simplify Z_FINISH check in inflate() - Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 - in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) - in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with the declaration of FAR (Gilles Vollant) - install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) - read_buf buf parameter of type Bytef* instead of charf* - zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) - do not redeclare unlink in minigzip.c for WIN32 (John Bowler) - fix check for presence of directories in "make install" (Ian Willis) Changes in 1.0.8 (27 Jan 1998) - fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) - fix gzgetc and gzputc for big endian systems (Markus Oberhumer) - added compress2() to allow setting the compression level - include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) - use constant arrays for the static trees in trees.c instead of computing them at run time (thanks to Ken Raeburn for this suggestion). To create trees.h, compile with GEN_TREES_H and run "make test" - check return code of example in "make test" and display result - pass minigzip command line options to file_compress - simplifying code of inflateSync to avoid gcc 2.8 bug - support CC="gcc -Wall" in configure -s (QingLong) - avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) - fix test for shared library support to avoid compiler warnings - zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) - check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) - do not use fdopen for Metrowerks on Mac (Brad Pettit)) - add checks for gzputc and gzputc in example.c - avoid warnings in gzio.c and deflate.c (Andreas Kleinert) - use const for the CRC table (Ken Raeburn) - fixed "make uninstall" for shared libraries - use Tracev instead of Trace in infblock.c - in example.c use correct compressed length for test_sync - suppress +vnocompatwarnings in configure for HPUX (not always supported) Changes in 1.0.7 (20 Jan 1998) - fix gzseek which was broken in write mode - return error for gzseek to negative absolute position - fix configure for Linux (Chun-Chung Chen) - increase stack space for MSC (Tim Wegner) - get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) - define EXPORTVA for gzprintf (Gilles Vollant) - added man page zlib.3 (Rick Rodgers) - for contrib/untgz, fix makedir() and improve Makefile - check gzseek in write mode in example.c - allocate extra buffer for seeks only if gzseek is actually called - avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) - add inflateSyncPoint in zconf.h - fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def Changes in 1.0.6 (19 Jan 1998) - add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) - Fix a deflate bug occurring only with compression level 0 (thanks to Andy Buckler for finding this one) - In minigzip, pass transparently also the first byte for .Z files - return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() - check Z_FINISH in inflate (thanks to Marc Schluper) - Implement deflateCopy (thanks to Adam Costello) - make static libraries by default in configure, add --shared option - move MSDOS or Windows specific files to directory msdos - suppress the notion of partial flush to simplify the interface (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) - suppress history buffer provided by application to simplify the interface (this feature was not implemented anyway in 1.0.4) - next_in and avail_in must be initialized before calling inflateInit or inflateInit2 - add EXPORT in all exported functions (for Windows DLL) - added Makefile.nt (thanks to Stephen Williams) - added the unsupported "contrib" directory: contrib/asm386/ by Gilles Vollant 386 asm code replacing longest_match() contrib/iostream/ by Kevin Ruland A C++ I/O streams interface to the zlib gz* functions contrib/iostream2/ by Tyge Løvset Another C++ I/O streams interface contrib/untgz/ by "Pedro A. Aranda Guti\irrez" A very simple tar.gz file extractor using zlib contrib/visual-basic.txt by Carlos Rios How to use compress(), uncompress() and the gz* functions from VB - pass params -f (filtered data), -h (huffman only), -1 to -9 (compression level) in minigzip (thanks to Tom Lane) - use const for rommable constants in deflate - added test for gzseek and gztell in example.c - add undocumented function inflateSyncPoint() (hack for Paul Mackerras) - add undocumented function zError to convert error code to string (for Tim Smithers) - Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code - Use default memcpy for Symantec MSDOS compiler - Add EXPORT keyword for check_func (needed for Windows DLL) - add current directory to LD_LIBRARY_PATH for "make test" - create also a link for libz.so.1 - added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) - use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) - added -soname for Linux in configure (Chun-Chung Chen, - assign numbers to the exported functions in zlib.def (for Windows DLL) - add advice in zlib.h for best usage of deflateSetDictionary - work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) - allow compilation with ANSI keywords only enabled for TurboC in large model - avoid "versionString"[0] (Borland bug) - add NEED_DUMMY_RETURN for Borland - use variable z_verbose for tracing in debug mode (L. Peter Deutsch) - allow compilation with CC - defined STDC for OS/2 (David Charlap) - limit external names to 8 chars for MVS (Thomas Lund) - in minigzip.c, use static buffers only for 16-bit systems - fix suffix check for "minigzip -d foo.gz" - do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) - use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) - added makelcc.bat for lcc-win32 (Tom St Denis) - in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) - Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion - check for unistd.h in configure (for off_t) - remove useless check parameter in inflate_blocks_free - avoid useless assignment of s->check to itself in inflate_blocks_new - do not flush twice in gzclose (thanks to Ken Raeburn) - rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h - use NO_ERRNO_H instead of enumeration of operating systems with errno.h - work around buggy fclose on pipes for HP/UX - support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) - fix configure if CC is already equal to gcc Changes in 1.0.5 (3 Jan 98) - Fix inflate to terminate gracefully when fed corrupted or invalid data - Use const for rommable constants in inflate - Eliminate memory leaks on error conditions in inflate - Removed some vestigial code in inflate - Update web address in README Changes in 1.0.4 (24 Jul 96) - In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF bit, so the decompressor could decompress all the correct data but went on to attempt decompressing extra garbage data. This affected minigzip too - zlibVersion and gzerror return const char* (needed for DLL) - port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) - use z_error only for DEBUG (avoid problem with DLLs) Changes in 1.0.3 (2 Jul 96) - use z_streamp instead of z_stream *, which is now a far pointer in MSDOS small and medium models; this makes the library incompatible with previous versions for these models. (No effect in large model or on other systems.) - return OK instead of BUF_ERROR if previous deflate call returned with avail_out as zero but there is nothing to do - added memcmp for non STDC compilers - define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) - define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) - better check for 16-bit mode MSC (avoids problem with Symantec) Changes in 1.0.2 (23 May 96) - added Windows DLL support - added a function zlibVersion (for the DLL support) - fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) - Bytef is define's instead of typedef'd only for Borland C - avoid reading uninitialized memory in example.c - mention in README that the zlib format is now RFC1950 - updated Makefile.dj2 - added algorithm.doc Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] - fix array overlay in deflate.c which sometimes caused bad compressed data - fix inflate bug with empty stored block - fix MSDOS medium model which was broken in 0.99 - fix deflateParams() which could generate bad compressed data - Bytef is define'd instead of typedef'ed (work around Borland bug) - added an INDEX file - new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) - speed up adler32 for modern machines without auto-increment - added -ansi for IRIX in configure - static_init_done in trees.c is an int - define unlink as delete for VMS - fix configure for QNX - add configure branch for SCO and HPUX - avoid many warnings (unused variables, dead assignments, etc...) - no fdopen for BeOS - fix the Watcom fix for 32 bit mode (define FAR as empty) - removed redefinition of Byte for MKWERKS - work around an MWKERKS bug (incorrect merge of all .h files) Changes in 0.99 (27 Jan 96) - allow preset dictionary shared between compressor and decompressor - allow compression level 0 (no compression) - add deflateParams in zlib.h: allow dynamic change of compression level and compression strategy - test large buffers and deflateParams in example.c - add optional "configure" to build zlib as a shared library - suppress Makefile.qnx, use configure instead - fixed deflate for 64-bit systems (detected on Cray) - fixed inflate_blocks for 64-bit systems (detected on Alpha) - declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) - always return Z_BUF_ERROR when deflate() has nothing to do - deflateInit and inflateInit are now macros to allow version checking - prefix all global functions and types with z_ with -DZ_PREFIX - make falloc completely reentrant (inftrees.c) - fixed very unlikely race condition in ct_static_init - free in reverse order of allocation to help memory manager - use zlib-1.0/* instead of zlib/* inside the tar.gz - make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion -Wstrict-prototypes -Wmissing-prototypes" - allow gzread on concatenated .gz files - deflateEnd now returns Z_DATA_ERROR if it was premature - deflate is finally (?) fully deterministic (no matches beyond end of input) - Document Z_SYNC_FLUSH - add uninstall in Makefile - Check for __cpluplus in zlib.h - Better test in ct_align for partial flush - avoid harmless warnings for Borland C++ - initialize hash_head in deflate.c - avoid warning on fdopen (gzio.c) for HP cc -Aa - include stdlib.h for STDC compilers - include errno.h for Cray - ignore error if ranlib doesn't exist - call ranlib twice for NeXTSTEP - use exec_prefix instead of prefix for libz.a - renamed ct_* as _tr_* to avoid conflict with applications - clear z->msg in inflateInit2 before any error return - initialize opaque in example.c, gzio.c, deflate.c and inflate.c - fixed typo in zconf.h (_GNUC__ => __GNUC__) - check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) - fix typo in Make_vms.com (f$trnlnm -> f$getsyi) - in fcalloc, normalize pointer if size > 65520 bytes - don't use special fcalloc for 32 bit Borland C++ - use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc. - use Z_BINARY instead of BINARY - document that gzclose after gzdopen will close the file - allow "a" as mode in gzopen - fix error checking in gzread - allow skipping .gz extra-field on pipes - added reference to Perl interface in README - put the crc table in FAR data (I dislike more and more the medium model :) - added get_crc_table - added a dimension to all arrays (Borland C can't count) - workaround Borland C bug in declaration of inflate_codes_new & inflate_fast - guard against multiple inclusion of *.h (for precompiled header on Mac) - Watcom C pretends to be Microsoft C small model even in 32 bit mode - don't use unsized arrays to avoid silly warnings by Visual C++: warning C4746: 'inflate_mask' : unsized array treated as '__far' (what's wrong with far data in far model?) - define enum out of inflate_blocks_state to allow compilation with C++ Changes in 0.95 (16 Aug 95) - fix MSDOS small and medium model (now easier to adapt to any compiler) - inlined send_bits - fix the final (:-) bug for deflate with flush (output was correct but not completely flushed in rare occasions) - default window size is same for compression and decompression (it's now sufficient to set MAX_WBITS in zconf.h) - voidp -> voidpf and voidnp -> voidp (for consistency with other typedefs and because voidnp was not near in large model) Changes in 0.94 (13 Aug 95) - support MSDOS medium model - fix deflate with flush (could sometimes generate bad output) - fix deflateReset (zlib header was incorrectly suppressed) - added support for VMS - allow a compression level in gzopen() - gzflush now calls fflush - For deflate with flush, flush even if no more input is provided - rename libgz.a as libz.a - avoid complex expression in infcodes.c triggering Turbo C bug - work around a problem with gcc on Alpha (in INSERT_STRING) - don't use inline functions (problem with some gcc versions) - allow renaming of Byte, uInt, etc... with #define - avoid warning about (unused) pointer before start of array in deflate.c - avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c - avoid reserved word 'new' in trees.c Changes in 0.93 (25 June 95) - temporarily disable inline functions - make deflate deterministic - give enough lookahead for PARTIAL_FLUSH - Set binary mode for stdin/stdout in minigzip.c for OS/2 - don't even use signed char in inflate (not portable enough) - fix inflate memory leak for segmented architectures Changes in 0.92 (3 May 95) - don't assume that char is signed (problem on SGI) - Clear bit buffer when starting a stored block - no memcpy on Pyramid - suppressed inftest.c - optimized fill_window, put longest_match inline for gcc - optimized inflate on stored blocks - untabify all sources to simplify patches Changes in 0.91 (2 May 95) - Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h - Document the memory requirements in zconf.h - added "make install" - fix sync search logic in inflateSync - deflate(Z_FULL_FLUSH) now works even if output buffer too short - after inflateSync, don't scare people with just "lo world" - added support for DJGPP Changes in 0.9 (1 May 95) - don't assume that zalloc clears the allocated memory (the TurboC bug was Mark's bug after all :) - let again gzread copy uncompressed data unchanged (was working in 0.71) - deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented - added a test of inflateSync in example.c - moved MAX_WBITS to zconf.h because users might want to change that - document explicitly that zalloc(64K) on MSDOS must return a normalized pointer (zero offset) - added Makefiles for Microsoft C, Turbo C, Borland C++ - faster crc32() Changes in 0.8 (29 April 95) - added fast inflate (inffast.c) - deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this is incompatible with previous versions of zlib which returned Z_OK - work around a TurboC compiler bug (bad code for b << 0, see infutil.h) (actually that was not a compiler bug, see 0.81 above) - gzread no longer reads one extra byte in certain cases - In gzio destroy(), don't reference a freed structure - avoid many warnings for MSDOS - avoid the ERROR symbol which is used by MS Windows Changes in 0.71 (14 April 95) - Fixed more MSDOS compilation problems :( There is still a bug with TurboC large model Changes in 0.7 (14 April 95) - Added full inflate support - Simplified the crc32() interface. The pre- and post-conditioning (one's complement) is now done inside crc32(). WARNING: this is incompatible with previous versions; see zlib.h for the new usage Changes in 0.61 (12 April 95) - workaround for a bug in TurboC. example and minigzip now work on MSDOS Changes in 0.6 (11 April 95) - added minigzip.c - added gzdopen to reopen a file descriptor as gzFile - added transparent reading of non-gziped files in gzread - fixed bug in gzread (don't read crc as data) - fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose) - don't allocate big arrays in the stack (for MSDOS) - fix some MSDOS compilation problems Changes in 0.5: - do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but not yet Z_FULL_FLUSH - support decompression but only in a single step (forced Z_FINISH) - added opaque object for zalloc and zfree - added deflateReset and inflateReset - added a variable zlib_version for consistency checking - renamed the 'filter' parameter of deflateInit2 as 'strategy' Added Z_FILTERED and Z_HUFFMAN_ONLY constants Changes in 0.4: - avoid "zip" everywhere, use zlib instead of ziplib - suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush if compression method == 8 - added adler32 and crc32 - renamed deflateOptions as deflateInit2, call one or the other but not both - added the method parameter for deflateInit2 - added inflateInit2 - simplified considerably deflateInit and inflateInit by not supporting user-provided history buffer. This is supported only in deflateInit2 and inflateInit2 Changes in 0.3: - prefix all macro names with Z_ - use Z_FINISH instead of deflateEnd to finish compression - added Z_HUFFMAN_ONLY - added gzerror() fltk-1.4.3/zlib/FAQ0000644000175000017500000004014215004135251014100 0ustar albrechtalbrecht Frequently Asked Questions about zlib If your question is not there, please check the zlib home page http://zlib.net/ which may have more recent information. The latest zlib FAQ is at http://zlib.net/zlib_faq.html 1. Is zlib Y2K-compliant? Yes. zlib doesn't handle dates. 2. Where can I get a Windows DLL version? The zlib sources can be compiled without change to produce a DLL. See the file win32/DLL_FAQ.txt in the zlib distribution. 3. Where can I get a Visual Basic interface to zlib? See * http://marknelson.us/1997/01/01/zlib-engine/ * win32/DLL_FAQ.txt in the zlib distribution 4. compress() returns Z_BUF_ERROR. Make sure that before the call of compress(), the length of the compressed buffer is equal to the available size of the compressed buffer and not zero. For Visual Basic, check that this parameter is passed by reference ("as any"), not by value ("as long"). 5. deflate() or inflate() returns Z_BUF_ERROR. Before making the call, make sure that avail_in and avail_out are not zero. When setting the parameter flush equal to Z_FINISH, also make sure that avail_out is big enough to allow processing all pending input. Note that a Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be made with more input or output space. A Z_BUF_ERROR may in fact be unavoidable depending on how the functions are used, since it is not possible to tell whether or not there is more output pending when strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a heavily annotated example. 6. Where's the zlib documentation (man pages, etc.)? It's in zlib.h . Examples of zlib usage are in the files test/example.c and test/minigzip.c, with more in examples/ . 7. Why don't you use GNU autoconf or libtool or ...? Because we would like to keep zlib as a very small and simple package. zlib is rather portable and doesn't need much configuration. 8. I found a bug in zlib. Most of the time, such problems are due to an incorrect usage of zlib. Please try to reproduce the problem with a small program and send the corresponding source to us at zlib@gzip.org . Do not send multi-megabyte data files without prior agreement. 9. Why do I get "undefined reference to gzputc"? If "make test" produces something like example.o(.text+0x154): undefined reference to `gzputc' check that you don't have old files libz.* in /usr/lib, /usr/local/lib or /usr/X11R6/lib. Remove any old versions, then do "make install". 10. I need a Delphi interface to zlib. See the contrib/delphi directory in the zlib distribution. 11. Can zlib handle .zip archives? Not by itself, no. See the directory contrib/minizip in the zlib distribution. 12. Can zlib handle .Z files? No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt the code of uncompress on your own. 13. How can I make a Unix shared library? By default a shared (and a static) library is built for Unix. So: make distclean ./configure make 14. How do I install a shared zlib library on Unix? After the above, then: make install However, many flavors of Unix come with a shared zlib already installed. Before going to the trouble of compiling a shared version of zlib and trying to install it, you may want to check if it's already there! If you can #include , it's there. The -lz option will probably link to it. You can check the version at the top of zlib.h or with the ZLIB_VERSION symbol defined in zlib.h . 15. I have a question about OttoPDF. We are not the authors of OttoPDF. The real author is on the OttoPDF web site: Joel Hainley, jhainley@myndkryme.com. 16. Can zlib decode Flate data in an Adobe PDF file? Yes. See http://www.pdflib.com/ . To modify PDF forms, see http://sourceforge.net/projects/acroformtool/ . 17. Why am I getting this "register_frame_info not found" error on Solaris? After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib generates an error such as: ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: symbol __register_frame_info: referenced symbol not found The symbol __register_frame_info is not part of zlib, it is generated by the C compiler (cc or gcc). You must recompile applications using zlib which have this problem. This problem is specific to Solaris. See http://www.sunfreeware.com for Solaris versions of zlib and applications using zlib. 18. Why does gzip give an error on a file I make with compress/deflate? The compress and deflate functions produce data in the zlib format, which is different and incompatible with the gzip format. The gz* functions in zlib on the other hand use the gzip format. Both the zlib and gzip formats use the same compressed data format internally, but have different headers and trailers around the compressed data. 19. Ok, so why are there two different formats? The gzip format was designed to retain the directory information about a single file, such as the name and last modification date. The zlib format on the other hand was designed for in-memory and communication channel applications, and has a much more compact header and trailer and uses a faster integrity check than gzip. 20. Well that's nice, but how do I make a gzip file in memory? You can request that deflate write the gzip format instead of the zlib format using deflateInit2(). You can also request that inflate decode the gzip format using inflateInit2(). Read zlib.h for more details. 21. Is zlib thread-safe? Yes. However any library routines that zlib uses and any application- provided memory allocation routines must also be thread-safe. zlib's gz* functions use stdio library routines, and most of zlib's functions use the library memory allocation routines by default. zlib's *Init* functions allow for the application to provide custom memory allocation routines. Of course, you should only operate on any given zlib or gzip stream from a single thread at a time. 22. Can I use zlib in my commercial application? Yes. Please read the license in zlib.h. 23. Is zlib under the GNU license? No. Please read the license in zlib.h. 24. The license says that altered source versions must be "plainly marked". So what exactly do I need to do to meet that requirement? You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In particular, the final version number needs to be changed to "f", and an identification string should be appended to ZLIB_VERSION. Version numbers x.x.x.f are reserved for modifications to zlib by others than the zlib maintainers. For example, if the version of the base zlib you are altering is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also update the version strings in deflate.c and inftrees.c. For altered source distributions, you should also note the origin and nature of the changes in zlib.h, as well as in ChangeLog and README, along with the dates of the alterations. The origin should include at least your name (or your company's name), and an email address to contact for help or issues with the library. Note that distributing a compiled zlib library along with zlib.h and zconf.h is also a source distribution, and so you should change ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes in zlib.h as you would for a full source distribution. 25. Will zlib work on a big-endian or little-endian architecture, and can I exchange compressed data between them? Yes and yes. 26. Will zlib work on a 64-bit machine? Yes. It has been tested on 64-bit machines, and has no dependence on any data types being limited to 32-bits in length. If you have any difficulties, please provide a complete problem report to zlib@gzip.org 27. Will zlib decompress data from the PKWare Data Compression Library? No. The PKWare DCL uses a completely different compressed data format than does PKZIP and zlib. However, you can look in zlib's contrib/blast directory for a possible solution to your problem. 28. Can I access data randomly in a compressed stream? No, not without some preparation. If when compressing you periodically use Z_FULL_FLUSH, carefully write all the pending data at those points, and keep an index of those locations, then you can start decompression at those points. You have to be careful to not use Z_FULL_FLUSH too often, since it can significantly degrade compression. Alternatively, you can scan a deflate stream once to generate an index, and then use that index for random access. See examples/zran.c . 29. Does zlib work on MVS, OS/390, CICS, etc.? It has in the past, but we have not heard of any recent evidence. There were working ports of zlib 1.1.4 to MVS, but those links no longer work. If you know of recent, successful applications of zlib on these operating systems, please let us know. Thanks. 30. Is there some simpler, easier to read version of inflate I can look at to understand the deflate format? First off, you should read RFC 1951. Second, yes. Look in zlib's contrib/puff directory. 31. Does zlib infringe on any patents? As far as we know, no. In fact, that was originally the whole point behind zlib. Look here for some more information: http://www.gzip.org/#faq11 32. Can zlib work with greater than 4 GB of data? Yes. inflate() and deflate() will process any amount of data correctly. Each call of inflate() or deflate() is limited to input and output chunks of the maximum value that can be stored in the compiler's "unsigned int" type, but there is no limit to the number of chunks. Note however that the strm.total_in and strm_total_out counters may be limited to 4 GB. These counters are provided as a convenience and are not used internally by inflate() or deflate(). The application can easily set up its own counters updated after each call of inflate() or deflate() to count beyond 4 GB. compress() and uncompress() may be limited to 4 GB, since they operate in a single call. gzseek() and gztell() may be limited to 4 GB depending on how zlib is compiled. See the zlibCompileFlags() function in zlib.h. The word "may" appears several times above since there is a 4 GB limit only if the compiler's "long" type is 32 bits. If the compiler's "long" type is 64 bits, then the limit is 16 exabytes. 33. Does zlib have any security vulnerabilities? The only one that we are aware of is potentially in gzprintf(). If zlib is compiled to use sprintf() or vsprintf(), then there is no protection against a buffer overflow of an 8K string space (or other value as set by gzbuffer()), other than the caller of gzprintf() assuring that the output will not exceed 8K. On the other hand, if zlib is compiled to use snprintf() or vsnprintf(), which should normally be the case, then there is no vulnerability. The ./configure script will display warnings if an insecure variation of sprintf() will be used by gzprintf(). Also the zlibCompileFlags() function will return information on what variant of sprintf() is used by gzprintf(). If you don't have snprintf() or vsnprintf() and would like one, you can find a portable implementation here: http://www.ijs.si/software/snprintf/ Note that you should be using the most recent version of zlib. Versions 1.1.3 and before were subject to a double-free vulnerability, and versions 1.2.1 and 1.2.2 were subject to an access exception when decompressing invalid compressed data. 34. Is there a Java version of zlib? Probably what you want is to use zlib in Java. zlib is already included as part of the Java SDK in the java.util.zip package. If you really want a version of zlib written in the Java language, look on the zlib home page for links: http://zlib.net/ . 35. I get this or that compiler or source-code scanner warning when I crank it up to maximally-pedantic. Can't you guys write proper code? Many years ago, we gave up attempting to avoid warnings on every compiler in the universe. It just got to be a waste of time, and some compilers were downright silly as well as contradicted each other. So now, we simply make sure that the code always works. 36. Valgrind (or some similar memory access checker) says that deflate is performing a conditional jump that depends on an uninitialized value. Isn't that a bug? No. That is intentional for performance reasons, and the output of deflate is not affected. This only started showing up recently since zlib 1.2.x uses malloc() by default for allocations, whereas earlier versions used calloc(), which zeros out the allocated memory. Even though the code was correct, versions 1.2.4 and later was changed to not stimulate these checkers. 37. Will zlib read the (insert any ancient or arcane format here) compressed data format? Probably not. Look in the comp.compression FAQ for pointers to various formats and associated software. 38. How can I encrypt/decrypt zip files with zlib? zlib doesn't support encryption. The original PKZIP encryption is very weak and can be broken with freely available programs. To get strong encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib compression. For PKZIP compatible "encryption", look at http://www.info-zip.org/ 39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? "gzip" is the gzip format, and "deflate" is the zlib format. They should probably have called the second one "zlib" instead to avoid confusion with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 correctly points to the zlib specification in RFC 1950 for the "deflate" transfer encoding, there have been reports of servers and browsers that incorrectly produce or expect raw deflate data per the deflate specification in RFC 1951, most notably Microsoft. So even though the "deflate" transfer encoding using the zlib format would be the more efficient approach (and in fact exactly what the zlib format was designed for), using the "gzip" transfer encoding is probably more reliable due to an unfortunate choice of name on the part of the HTTP 1.1 authors. Bottom line: use the gzip format for HTTP 1.1 encoding. 40. Does zlib support the new "Deflate64" format introduced by PKWare? No. PKWare has apparently decided to keep that format proprietary, since they have not documented it as they have previous compression formats. In any case, the compression improvements are so modest compared to other more modern approaches, that it's not worth the effort to implement. 41. I'm having a problem with the zip functions in zlib, can you help? There are no zip functions in zlib. You are probably using minizip by Giles Vollant, which is found in the contrib directory of zlib. It is not part of zlib. In fact none of the stuff in contrib is part of zlib. The files in there are not supported by the zlib authors. You need to contact the authors of the respective contribution for help. 42. The match.asm code in contrib is under the GNU General Public License. Since it's part of zlib, doesn't that mean that all of zlib falls under the GNU GPL? No. The files in contrib are not part of zlib. They were contributed by other authors and are provided as a convenience to the user within the zlib distribution. Each item in contrib has its own license. 43. Is zlib subject to export controls? What is its ECCN? zlib is not subject to export controls, and so is classified as EAR99. 44. Can you please sign these lengthy legal documents and fax them back to us so that we can use your software in our product? No. Go away. Shoo. fltk-1.4.3/zlib/inftrees.c0000644000175000017500000003134015004135251015531 0ustar albrechtalbrecht/* inftrees.c -- generate Huffman trees for efficient decoding * Copyright (C) 1995-2024 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #define MAXBITS 15 const char inflate_copyright[] = " inflate 1.3.1 Copyright 1995-2024 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* Build a set of tables to decode the provided canonical Huffman code. The code lengths are lens[0..codes-1]. The result starts at *table, whose indices are 0..2^bits-1. work is a writable array of at least lens shorts, which is used as a work area. type is the type of code to be generated, CODES, LENS, or DISTS. On return, zero is success, -1 is an invalid code, and +1 means that ENOUGH isn't enough. table on return points to the next available entry's address. bits is the requested root table index bits, and on return it is the actual root table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work) { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ unsigned root; /* number of index bits for root table */ unsigned curr; /* number of index bits for current table */ unsigned drop; /* code bits to drop for sub-table */ int left; /* number of prefix codes available */ unsigned used; /* code entries in table used */ unsigned huff; /* Huffman code */ unsigned incr; /* for incrementing code, index */ unsigned fill; /* index for replicating entries */ unsigned low; /* low bits for current root entry */ unsigned mask; /* mask for low root bits */ code here; /* table entry for duplication */ code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ unsigned match; /* use base and extra for symbol >= match */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0}; static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64}; /* Process a set of code lengths to create a canonical Huffman code. The code lengths are lens[0..codes-1]. Each length corresponds to the symbols 0..codes-1. The Huffman code is generated by first sorting the symbols by length from short to long, and retaining the symbol order for codes with equal lengths. Then the code starts with all zero bits for the first code of the shortest length, and the codes are integer increments for the same length, and zeros are appended as the length increases. For the deflate format, these bits are stored backwards from their more natural integer increment ordering, and so when the decoding tables are built in the large loop below, the integer codes are incremented backwards. This routine assumes, but does not check, that all of the entries in lens[] are in the range 0..MAXBITS. The caller must assure this. 1..MAXBITS is interpreted as that code length. zero means that that symbol does not occur in this code. The codes are sorted by computing a count of codes for each length, creating from that a table of starting indices for each length in the sorted table, and then entering the symbols in order in the sorted table. The sorted table is work[], with that space being provided by the caller. The length counts are used for other purposes as well, i.e. finding the minimum and maximum length codes, determining if there are any codes at all, checking for a valid set of lengths, and looking ahead at length counts to determine sub-table sizes when building the decoding tables. */ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ for (len = 0; len <= MAXBITS; len++) count[len] = 0; for (sym = 0; sym < codes; sym++) count[lens[sym]]++; /* bound code lengths, force root to be within code lengths */ root = *bits; for (max = MAXBITS; max >= 1; max--) if (count[max] != 0) break; if (root > max) root = max; if (max == 0) { /* no symbols to code at all */ here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)1; here.val = (unsigned short)0; *(*table)++ = here; /* make a table to force an error */ *(*table)++ = here; *bits = 1; return 0; /* no symbols, but wait for decoding to report error */ } for (min = 1; min < max; min++) if (count[min] != 0) break; if (root < min) root = min; /* check for an over-subscribed or incomplete set of lengths */ left = 1; for (len = 1; len <= MAXBITS; len++) { left <<= 1; left -= count[len]; if (left < 0) return -1; /* over-subscribed */ } if (left > 0 && (type == CODES || max != 1)) return -1; /* incomplete set */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + count[len]; /* sort symbols by length, by symbol order within each length */ for (sym = 0; sym < codes; sym++) if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; /* Create and fill in decoding tables. In this loop, the table being filled is at next and has curr index bits. The code being used is huff with length len. That code is converted to an index by dropping drop bits off of the bottom. For codes where len is less than drop + curr, those top drop + curr - len bits are incremented through all values to fill the table with replicated entries. root is the number of index bits for the root table. When len exceeds root, sub-tables are created pointed to by the root entry with an index of the low root bits of huff. This is saved in low to check for when a new sub-table should be started. drop is zero when the root table is being filled, and drop is root when sub-tables are being filled. When a new sub-table is needed, it is necessary to look ahead in the code lengths to determine what size sub-table is needed. The length counts are used for this, and so count[] is decremented as codes are entered in the tables. used keeps track of how many table entries have been allocated from the provided *table space. It is checked for LENS and DIST tables against the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in the initial root table size constants. See the comments in inftrees.h for more information. sym increments through all symbols, and the loop terminates when all codes of length max, i.e. all codes, have been processed. This routine permits incomplete codes, so another loop after this one fills in the rest of the decoding tables with invalid code markers. */ /* set up for code type */ switch (type) { case CODES: base = extra = work; /* dummy value--not used */ match = 20; break; case LENS: base = lbase; extra = lext; match = 257; break; default: /* DISTS */ base = dbase; extra = dext; match = 0; } /* initialize state for loop */ huff = 0; /* starting code */ sym = 0; /* starting code symbol */ len = min; /* starting code length */ next = *table; /* current table to fill in */ curr = root; /* current table index bits */ drop = 0; /* current bits to drop from code for index */ low = (unsigned)(-1); /* trigger new sub-table when len > root */ used = 1U << root; /* use root table entries */ mask = used - 1; /* mask for comparing low */ /* check available table space */ if ((type == LENS && used > ENOUGH_LENS) || (type == DISTS && used > ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); if (work[sym] + 1U < match) { here.op = (unsigned char)0; here.val = work[sym]; } else if (work[sym] >= match) { here.op = (unsigned char)(extra[work[sym] - match]); here.val = base[work[sym] - match]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ here.val = 0; } /* replicate for those indices with low len bits equal to huff */ incr = 1U << (len - drop); fill = 1U << curr; min = fill; /* save offset to next table */ do { fill -= incr; next[(huff >> drop) + fill] = here; } while (fill != 0); /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; /* go to next symbol, update count, len */ sym++; if (--(count[len]) == 0) { if (len == max) break; len = lens[work[sym]]; } /* create new sub-table if needed */ if (len > root && (huff & mask) != low) { /* if first time, transition to sub-tables */ if (drop == 0) drop = root; /* increment past last table */ next += min; /* here min is 1 << curr */ /* determine length of next table */ curr = len - drop; left = (int)(1 << curr); while (curr + drop < max) { left -= count[curr + drop]; if (left <= 0) break; curr++; left <<= 1; } /* check for enough space */ used += 1U << curr; if ((type == LENS && used > ENOUGH_LENS) || (type == DISTS && used > ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ low = huff & mask; (*table)[low].op = (unsigned char)curr; (*table)[low].bits = (unsigned char)root; (*table)[low].val = (unsigned short)(next - *table); } } /* fill in remaining table entry if code is incomplete (guaranteed to have at most one remaining entry, since if the code is incomplete, the maximum code length that was allowed to get this far is one bit) */ if (huff != 0) { here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)(len - drop); here.val = (unsigned short)0; next[huff] = here; } /* set return parameters */ *table += used; *bits = root; return 0; } fltk-1.4.3/zlib/compress.c0000644000175000017500000000506515004135251015552 0ustar albrechtalbrecht/* compress.c -- compress a memory buffer * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #define ZLIB_INTERNAL #include "zlib.h" /* =========================================================================== Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least 0.1% larger than sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ int ZEXPORT compress2(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level) { z_stream stream; int err; const uInt max = (uInt)-1; uLong left; left = *destLen; *destLen = 0; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; stream.opaque = (voidpf)0; err = deflateInit(&stream, level); if (err != Z_OK) return err; stream.next_out = dest; stream.avail_out = 0; stream.next_in = (z_const Bytef *)source; stream.avail_in = 0; do { if (stream.avail_out == 0) { stream.avail_out = left > (uLong)max ? max : (uInt)left; left -= stream.avail_out; } if (stream.avail_in == 0) { stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen; sourceLen -= stream.avail_in; } err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); } while (err == Z_OK); *destLen = stream.total_out; deflateEnd(&stream); return err == Z_STREAM_END ? Z_OK : err; } /* =========================================================================== */ int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) { return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); } /* =========================================================================== If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ uLong ZEXPORT compressBound(uLong sourceLen) { return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13; } fltk-1.4.3/zlib/README0000644000175000017500000001230515004135251014426 0ustar albrechtalbrechtZLIB DATA COMPRESSION LIBRARY zlib 1.3.1 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). All functions of the compression library are documented in the file zlib.h (volunteer to write man pages welcome, contact zlib@gzip.org). A usage example of the library is given in the file test/example.c which also tests that the library is working correctly. Another example is given in the file test/minigzip.c. The compression library itself is composed of all source files in the root directory. To compile all files and run the test program, follow the instructions given at the top of Makefile.in. In short "./configure; make test", and if that goes well, "make install" should work for most flavors of Unix. For Windows, use one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use make_vms.com. Questions about zlib should be sent to , or to Gilles Vollant for the Windows DLL version. The zlib home page is http://zlib.net/ . Before reporting a problem, please check this site to verify that you have the latest version of zlib; otherwise get the latest version and check whether the problem still exists or not. PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at https://marknelson.us/posts/1997/01/01/zlib-engine.html . The changes made in version 1.3.1 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . zlib is available in Java using the java.util.zip package. Follow the API Documentation link at: https://docs.oracle.com/search/?q=java.util.zip . A Perl interface to zlib and bzip2 written by Paul Marquess can be found at https://github.com/pmqs/IO-Compress . A Python interface to zlib written by A.M. Kuchling is available in Python 1.5 and later versions, see http://docs.python.org/library/zlib.html . zlib is built into tcl: http://wiki.tcl.tk/4610 . An experimental package to read and write files in .zip format, written on top of zlib by Gilles Vollant , is available in the contrib/minizip directory of zlib. Notes for some targets: - For Windows DLL versions, please see win32/DLL_FAQ.txt - For 64-bit Irix, deflate.c must be compiled without any optimization. With -O, one libpng test fails. The test works in 32 bit mode (with the -n32 compiler flag). The compiler bug has been reported to SGI. - zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works when compiled with cc. - On Digital Unix 4.0D (formerly OSF/1) on AlphaServer, the cc option -std1 is necessary to get gzprintf working correctly. This is done by configure. - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with other compilers. Use "make test" to check your compiler. - gzdopen is not supported on RISCOS or BEOS. - For PalmOs, see http://palmzlib.sourceforge.net/ Acknowledgments: The deflate format used by zlib was defined by Phil Katz. The deflate and zlib specifications were written by L. Peter Deutsch. Thanks to all the people who reported problems and suggested various improvements in zlib; they are too numerous to cite here. Copyright notice: (C) 1995-2024 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu If you use the zlib library in a product, we would appreciate *not* receiving lengthy legal documents to sign. The sources are provided for free but without warranty of any kind. The library has been entirely written by Jean-loup Gailly and Mark Adler; it does not include third-party code. We make all contributions to and distributions of this project solely in our personal capacity, and are not conveying any rights to any intellectual property of any third parties. If you redistribute modified sources, we would appreciate that you include in the file ChangeLog history information documenting your changes. Please read the FAQ for more information on the distribution of modified source versions. fltk-1.4.3/zlib/inftrees.h0000644000175000017500000000555015004135251015542 0ustar albrechtalbrecht/* inftrees.h -- header to use inftrees.c * Copyright (C) 1995-2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* Structure for decoding tables. Each entry provides either the information needed to do the operation requested by the code that indexed that table entry, or it provides a pointer to another table that indexes more bits of the code. op indicates whether the entry is a pointer to another table, a literal, a length or distance, an end-of-block, or an invalid code. For a table pointer, the low four bits of op is the number of index bits of that table. For a length or distance, the low four bits of op is the number of extra bits to get after the code. bits is the number of bits in this code or part of the code to drop off of the bit buffer. val is the actual byte to output in the case of a literal, the base length or distance, or the offset from the current table to the next table. Each entry is four bytes. */ typedef struct { unsigned char op; /* operation, extra bits, table bits */ unsigned char bits; /* bits in this part of the code */ unsigned short val; /* offset in table or code value */ } code; /* op values as set by inflate_table(): 00000000 - literal 0000tttt - table link, tttt != 0 is the number of table index bits 0001eeee - length or distance, eeee is the number of extra bits 01100000 - end of block 01000000 - invalid code */ /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program examples/enough.c found in the zlib distribution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns 852, and "enough 30 6 15" for distance codes returns 592. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ #define ENOUGH_LENS 852 #define ENOUGH_DISTS 592 #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) /* Type of code to build for inflate_table() */ typedef enum { CODES, LENS, DISTS } codetype; int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work); fltk-1.4.3/zlib/zlib.30000644000175000017500000001057415004135251014600 0ustar albrechtalbrecht.TH ZLIB 3 "22 Jan 2024" .SH NAME zlib \- compression/decompression library .SH SYNOPSIS [see .I zlib.h for full description] .SH DESCRIPTION The .I zlib library is a general purpose data compression library. The code is thread safe, assuming that the standard library functions used are thread safe, such as memory allocation routines. It provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms may be added later with the same stream interface. .LP Compression can be done in a single step if the buffers are large enough or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. .LP The library also supports reading and writing files in .IR gzip (1) (.gz) format with an interface similar to that of stdio. .LP The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in the case of corrupted input. .LP All functions of the compression library are documented in the file .IR zlib.h . The distribution source includes examples of use of the library in the files .I test/example.c and .IR test/minigzip.c, as well as other examples in the .IR examples/ directory. .LP Changes to this version are documented in the file .I ChangeLog that accompanies the source. .LP .I zlib is built in to many languages and operating systems, including but not limited to Java, Python, .NET, PHP, Perl, Ruby, Swift, and Go. .LP An experimental package to read and write files in the .zip format, written on top of .I zlib by Gilles Vollant (info@winimage.com), is available at: .IP http://www.winimage.com/zLibDll/minizip.html and also in the .I contrib/minizip directory of the main .I zlib source distribution. .SH "SEE ALSO" The .I zlib web site can be found at: .IP http://zlib.net/ .LP The data format used by the .I zlib library is described by RFC (Request for Comments) 1950 to 1952 in the files: .IP http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format) .br http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format) .br http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format) .LP Mark Nelson wrote an article about .I zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at: .IP http://marknelson.us/1997/01/01/zlib-engine/ .SH "REPORTING PROBLEMS" Before reporting a problem, please check the .I zlib web site to verify that you have the latest version of .IR zlib ; otherwise, obtain the latest version and see if the problem still exists. Please read the .I zlib FAQ at: .IP http://zlib.net/zlib_faq.html .LP before asking for help. Send questions and/or comments to zlib@gzip.org, or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). .SH AUTHORS AND LICENSE Version 1.3.1 .LP Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler .LP This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. .LP Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: .LP .nr step 1 1 .IP \n[step]. 3 The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. .IP \n+[step]. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. .IP \n+[step]. This notice may not be removed or altered from any source distribution. .LP Jean-loup Gailly Mark Adler .br jloup@gzip.org madler@alumni.caltech.edu .LP The deflate format used by .I zlib was defined by Phil Katz. The deflate and .I zlib specifications were written by L. Peter Deutsch. Thanks to all the people who reported problems and suggested various improvements in .IR zlib ; who are too numerous to cite here. .LP UNIX manual page by R. P. C. Rodgers, U.S. National Library of Medicine (rodgers@nlm.nih.gov). .\" end of man page fltk-1.4.3/zlib/gzguts.h0000644000175000017500000001502415004135251015243 0ustar albrechtalbrecht/* gzguts.h -- zlib internal header definitions for gz* operations * Copyright (C) 2004-2024 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #ifdef _LARGEFILE64_SOURCE # ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE 1 # endif # undef _FILE_OFFSET_BITS # undef _TIME_BITS #endif #ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL #endif #include #include "zlib.h" #ifdef STDC # include # include # include #endif #ifndef _POSIX_SOURCE # define _POSIX_SOURCE #endif #include #ifdef _WIN32 # include #endif #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) # include #endif #if defined(_WIN32) # define WIDECHAR #endif #ifdef WINAPI_FAMILY # define open _open # define read _read # define write _write # define close _close #endif #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif #if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #if defined(__CYGWIN__) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #ifndef HAVE_VSNPRINTF # ifdef MSDOS /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), but for now we just assume it doesn't. */ # define NO_vsnprintf # endif # ifdef __TURBOC__ # define NO_vsnprintf # endif # ifdef WIN32 /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ # if !defined(vsnprintf) && !defined(NO_vsnprintf) # if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) # define vsnprintf _vsnprintf # endif # endif # endif # ifdef __SASC # define NO_vsnprintf # endif # ifdef VMS # define NO_vsnprintf # endif # ifdef __OS400__ # define NO_vsnprintf # endif # ifdef __MVS__ # define NO_vsnprintf # endif #endif /* unlike snprintf (which is required in C99), _snprintf does not guarantee null termination of the result -- however this is only used in gzlib.c where the result is assured to fit in the space provided */ #if defined(_MSC_VER) && _MSC_VER < 1900 # define snprintf _snprintf #endif #ifndef local # define local static #endif /* since "static" is used to mean two completely different things in C, we define "local" for the non-static meaning of "static", for readability (compile with -Dlocal if your debugger can't find static symbols) */ /* gz* functions always use library allocation functions */ #ifndef STDC extern voidp malloc(uInt size); extern void free(voidpf ptr); #endif /* get errno and strerror definition */ #if defined UNDER_CE # include # define zstrerror() gz_strwinerror((DWORD)GetLastError()) #else # ifndef NO_STRERROR # include # define zstrerror() strerror(errno) # else # define zstrerror() "stdio error (consult errno)" # endif #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); #endif /* default memLevel */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default i/o buffer size -- double this for output when reading (this and twice this must be able to fit in an unsigned type) */ #define GZBUFSIZE 8192 /* gzip modes, also provide a little integrity check on the passed structure */ #define GZ_NONE 0 #define GZ_READ 7247 #define GZ_WRITE 31153 #define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ /* values for gz_state how */ #define LOOK 0 /* look for a gzip header */ #define COPY 1 /* copy input directly */ #define GZIP 2 /* decompress a gzip stream */ /* internal gzip file state data structure */ typedef struct { /* exposed contents for gzgetc() macro */ struct gzFile_s x; /* "x" for exposed */ /* x.have: number of bytes available at x.next */ /* x.next: next output data to deliver or write */ /* x.pos: current position in uncompressed data */ /* used for both reading and writing */ int mode; /* see gzip modes above */ int fd; /* file descriptor */ char *path; /* path or fd for error messages */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ unsigned char *in; /* input buffer (double-sized when writing) */ unsigned char *out; /* output buffer (double-sized when reading) */ int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ int how; /* 0: get header, 1: copy, 2: decompress */ z_off64_t start; /* where the gzip data started, for rewinding */ int eof; /* true if end of input file reached */ int past; /* true if read requested past end */ /* just for writing */ int level; /* compression level */ int strategy; /* compression strategy */ int reset; /* true if a reset is pending after a Z_FINISH */ /* seek request */ z_off64_t skip; /* amount to skip (already rewound if backwards) */ int seek; /* true if seek request pending */ /* error information */ int err; /* error code */ char *msg; /* error message */ /* zlib inflate or deflate stream */ z_stream strm; /* stream structure in-place (not a pointer) */ } gz_state; typedef gz_state FAR *gz_statep; /* shared functions */ void ZLIB_INTERNAL gz_error(gz_statep, int, const char *); #if defined UNDER_CE char ZLIB_INTERNAL *gz_strwinerror(DWORD error); #endif /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t value -- needed when comparing unsigned to z_off64_t, which is signed (possible z_off64_t types off_t, off64_t, and long are all signed) */ unsigned ZLIB_INTERNAL gz_intmax(void); #define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) fltk-1.4.3/zlib/Makefile0000644000175000017500000000416115004135251015207 0ustar albrechtalbrecht# # ZIP library makefile for the Fast Light Toolkit (FLTK). # # Copyright 1998-2023 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # include ../makeinclude # # Object files... # OBJS = adler32.o compress.o crc32.o uncompr.o deflate.o \ trees.o zutil.o inflate.o inftrees.o inffast.o \ gzclose.o gzlib.o gzread.o gzwrite.o infback.o LIBZ = ../lib/libfltk_z$(LIBEXT) # # Make all targets... # all: $(LIBZ) # # Clean all targets and object files... # clean: $(RM) $(OBJS) $(RM) $(LIBZ) # # Install everything... # install: $(LIBZ) echo "Installing libfltk_z$(LIBEXT) in $(libdir)..." -$(INSTALL_DIR) "$(DESTDIR)$(libdir)" $(INSTALL_LIB) $(LIBZ) "$(DESTDIR)$(libdir)" $(RANLIB) "$(DESTDIR)$(libdir)/libfltk_z$(LIBEXT)" echo "Installing zlib headers in $(includedir)/FL/images..." -$(INSTALL_DIR) "$(DESTDIR)$(includedir)/FL/images" $(INSTALL_DATA) zconf.h "$(DESTDIR)$(includedir)/FL/images" $(INSTALL_DATA) zlib.h "$(DESTDIR)$(includedir)/FL/images" $(INSTALL_DATA) zutil.h "$(DESTDIR)$(includedir)/FL/images" # # Uninstall everything... # uninstall: echo "Uninstalling libfltk_z$(LIBEXT) in $(libdir)..." $(RM) "$(libdir)/libfltk_z$(LIBEXT)" echo "Uninstalling zlib headers in $(includedir)/FL/images..." $(RM) "$(includedir)/FL/images/zconf.h" $(RM) "$(includedir)/FL/images/zlib.h" $(RM) "$(includedir)/FL/images/zutil.h" # # libfltk_z.a # $(LIBZ): $(OBJS) echo Archiving $@... $(RM) $@ $(LIBCOMMAND) $@ $(OBJS) $(RANLIB) $@ # # Make dependencies... # depend: $(OBJS:.o=.c) makedepend -Y -I.. -f makedepend -w 20 $(OBJS:.o=.c) echo "# DO NOT DELETE THIS LINE -- make depend depends on it." > makedepend.tmp echo "" >> makedepend.tmp grep '^[a-zA-Z]' makedepend | ( LC_ALL=C sort -u -f >> makedepend.tmp; ) mv makedepend.tmp makedepend include makedepend $(OBJS): ../makeinclude fltk-1.4.3/zlib/INDEX0000644000175000017500000000370415004135251014343 0ustar albrechtalbrechtCMakeLists.txt cmake build file ChangeLog history of changes FAQ Frequently Asked Questions about zlib INDEX this file Makefile dummy Makefile that tells you to ./configure Makefile.in template for Unix Makefile README guess what configure configure script for Unix make_vms.com makefile for VMS test/example.c zlib usages examples for build testing test/minigzip.c minimal gzip-like functionality for build testing test/infcover.c inf*.c code coverage for build coverage testing treebuild.xml XML description of source file dependencies zconf.h.cmakein zconf.h template for cmake zconf.h.in zconf.h template for configure zlib.3 Man page for zlib zlib.3.pdf Man page in PDF format zlib.map Linux symbol information zlib.pc.in Template for pkg-config descriptor zlib.pc.cmakein zlib.pc template for cmake zlib2ansi perl script to convert source files for C++ compilation amiga/ makefiles for Amiga SAS C as400/ makefiles for AS/400 doc/ documentation for formats and algorithms msdos/ makefiles for MSDOS nintendods/ makefile for Nintendo DS old/ makefiles for various architectures and zlib documentation files that have not yet been updated for zlib 1.2.x qnx/ makefiles for QNX watcom/ makefiles for OpenWatcom win32/ makefiles for Windows zlib public header files (required for library use): zconf.h zlib.h private source files used to build the zlib library: adler32.c compress.c crc32.c crc32.h deflate.c deflate.h gzclose.c gzguts.h gzlib.c gzread.c gzwrite.c infback.c inffast.c inffast.h inffixed.h inflate.c inflate.h inftrees.c inftrees.h trees.c trees.h uncompr.c zutil.c zutil.h source files for sample programs See examples/README.examples unsupported contributions by third parties See contrib/README.contrib fltk-1.4.3/zlib/zutil.h0000644000175000017500000001502515004135251015070 0ustar albrechtalbrecht/* zutil.h -- internal interface and configuration of the compression library * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id$ */ #ifndef ZUTIL_H #define ZUTIL_H #ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL #endif #include "zlib.h" #if defined(STDC) && !defined(Z_SOLO) # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) # include # endif # include # include #endif #ifndef local # define local static #endif /* since "static" is used to mean two completely different things in C, we define "local" for the non-static meaning of "static", for readability (compile with -Dlocal if your debugger can't find static symbols) */ typedef unsigned char uch; typedef uch FAR uchf; typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; #if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC) # include # if (ULONG_MAX == 0xffffffffffffffff) # define Z_U8 unsigned long # elif (ULLONG_MAX == 0xffffffffffffffff) # define Z_U8 unsigned long long # elif (UINT_MAX == 0xffffffffffffffff) # define Z_U8 unsigned # endif #endif extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)] #define ERR_RETURN(strm,err) \ return (strm->msg = ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif /* default windowBits for decompression. MAX_WBITS is for compression only */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default memLevel */ #define STORED_BLOCK 0 #define STATIC_TREES 1 #define DYN_TREES 2 /* The three kinds of block type */ #define MIN_MATCH 3 #define MAX_MATCH 258 /* The minimum and maximum match lengths */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ /* target dependencies */ #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 # ifndef Z_SOLO # if defined(__TURBOC__) || defined(__BORLANDC__) # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) /* Allow compilation with ANSI keywords only enabled */ void _Cdecl farfree( void *block ); void *_Cdecl farmalloc( unsigned long nbytes ); # else # include # endif # else /* MSC or DJGPP */ # include # endif # endif #endif #ifdef AMIGA # define OS_CODE 1 #endif #if defined(VAXC) || defined(VMS) # define OS_CODE 2 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif #ifdef __370__ # if __TARGET_LIB__ < 0x20000000 # define OS_CODE 4 # elif __TARGET_LIB__ < 0x40000000 # define OS_CODE 11 # else # define OS_CODE 8 # endif #endif #if defined(ATARI) || defined(atarist) # define OS_CODE 5 #endif #ifdef OS2 # define OS_CODE 6 # if defined(M_I86) && !defined(Z_SOLO) # include # endif #endif #if defined(MACOS) # define OS_CODE 7 #endif #ifdef __acorn # define OS_CODE 13 #endif #if defined(WIN32) && !defined(__CYGWIN__) # define OS_CODE 10 #endif #ifdef _BEOS_ # define OS_CODE 16 #endif #ifdef __TOS_OS400__ # define OS_CODE 18 #endif #ifdef __APPLE__ # define OS_CODE 19 #endif #if defined(__BORLANDC__) && !defined(MSDOS) #pragma warn -8004 #pragma warn -8008 #pragma warn -8066 #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_WIN32) && \ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); #endif /* common defaults */ #ifndef OS_CODE # define OS_CODE 3 /* assume Unix */ #endif #ifndef F_OPEN # define F_OPEN(name, mode) fopen((name), (mode)) #endif /* functions */ #if defined(pyr) || defined(Z_SOLO) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) /* Use our own functions for small and medium model with MSC <= 5.0. * You may have to use the same strategy for Borland C (untested). * The __SC__ check is for Symantec. */ # define NO_MEMCPY #endif #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) # define HAVE_MEMCPY #endif #ifdef HAVE_MEMCPY # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ # define zmemcpy _fmemcpy # define zmemcmp _fmemcmp # define zmemzero(dest, len) _fmemset(dest, 0, len) # else # define zmemcpy memcpy # define zmemcmp memcmp # define zmemzero(dest, len) memset(dest, 0, len) # endif #else void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len); int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len); void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len); #endif /* Diagnostic functions */ #ifdef ZLIB_DEBUG # include extern int ZLIB_INTERNAL z_verbose; extern void ZLIB_INTERNAL z_error(char *m); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} # define Tracevv(x) {if (z_verbose>1) fprintf x ;} # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} #else # define Assert(cond,msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) # define Tracec(c,x) # define Tracecv(c,x) #endif #ifndef Z_SOLO voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size); void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr); #endif #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} /* Reverse the bytes in a 32-bit value */ #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) #endif /* ZUTIL_H */ fltk-1.4.3/zlib/infback.c0000644000175000017500000005421515004135251015315 0ustar albrechtalbrecht/* infback.c -- inflate using a call-back interface * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* This code is largely copied from inflate.c. Normally either infback.o or inflate.o would be linked into an application--not both. The interface with inffast.c is retained so that optimized assembler-coded versions of inflate_fast() can be used with either inflate.c or infback.c. */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" /* strm provides memory allocation functions in zalloc and zfree, or Z_NULL to use the library memory allocation functions. windowBits is in the range 8..15, and window is a user-supplied window and output buffer that is 2**windowBits bytes. */ int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size) { struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL || window == Z_NULL || windowBits < 8 || windowBits > 15) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; #endif } if (strm->zfree == (free_func)0) #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zfree = zcfree; #endif state = (struct inflate_state FAR *)ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->dmax = 32768U; state->wbits = (uInt)windowBits; state->wsize = 1U << windowBits; state->window = window; state->wnext = 0; state->whave = 0; state->sane = 1; return Z_OK; } /* Return state with length and distance decoding tables and index sizes set to fixed code decoding. Normally this returns fixed tables from inffixed.h. If BUILDFIXED is defined, then instead this routine builds the tables the first time it's called, and returns those tables the first time and thereafter. This reduces the size of the code by about 2K bytes, in exchange for a little execution time. However, BUILDFIXED should not be used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ local void fixedtables(struct inflate_state FAR *state) { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { unsigned sym, bits; static code *next; /* literal/length table */ sym = 0; while (sym < 144) state->lens[sym++] = 8; while (sym < 256) state->lens[sym++] = 9; while (sym < 280) state->lens[sym++] = 7; while (sym < 288) state->lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); /* distance table */ sym = 0; while (sym < 32) state->lens[sym++] = 5; distfix = next; bits = 5; inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); /* do this just once */ virgin = 0; } #else /* !BUILDFIXED */ # include "inffixed.h" #endif /* BUILDFIXED */ state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; state->distbits = 5; } /* Macros for inflateBack(): */ /* Load returned state from inflate_fast() */ #define LOAD() \ do { \ put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ hold = state->hold; \ bits = state->bits; \ } while (0) /* Set state from registers for inflate_fast() */ #define RESTORE() \ do { \ strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = next; \ strm->avail_in = have; \ state->hold = hold; \ state->bits = bits; \ } while (0) /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Assure that some input is available. If input is requested, but denied, then return a Z_BUF_ERROR from inflateBack(). */ #define PULL() \ do { \ if (have == 0) { \ have = in(in_desc, &next); \ if (have == 0) { \ next = Z_NULL; \ ret = Z_BUF_ERROR; \ goto inf_leave; \ } \ } \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflateBack() with an error if there is no input available. */ #define PULLBYTE() \ do { \ PULL(); \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflateBack() with an error. */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* Assure that some output space is available, by writing out the window if it's full. If the write fails, return from inflateBack() with a Z_BUF_ERROR. */ #define ROOM() \ do { \ if (left == 0) { \ put = state->window; \ left = state->wsize; \ state->whave = left; \ if (out(out_desc, put, left)) { \ ret = Z_BUF_ERROR; \ goto inf_leave; \ } \ } \ } while (0) /* strm provides the memory allocation functions and window buffer on input, and provides information on the unused input on return. For Z_DATA_ERROR returns, strm will also provide an error message. in() and out() are the call-back input and output functions. When inflateBack() needs more input, it calls in(). When inflateBack() has filled the window with output, or when it completes with data in the window, it calls out() to write out the data. The application must not change the provided input until in() is called again or inflateBack() returns. The application must not change the window/output buffer until inflateBack() returns. in() and out() are called with a descriptor parameter provided in the inflateBack() call. This parameter can be a structure that provides the information required to do the read or write, as well as accumulated information on the input and output such as totals and check values. in() should return zero on failure. out() should return non-zero on failure. If either in() or out() fails, than inflateBack() returns a Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it was in() or out() that caused in the error. Otherwise, inflateBack() returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format error, or Z_MEM_ERROR if it could not allocate memory for the state. inflateBack() can also return Z_STREAM_ERROR if the input parameters are not correct, i.e. strm is Z_NULL or the state was not initialized. */ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc) { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char FAR *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; /* Check that the strm exists and that the state was initialized */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* Reset the state */ strm->msg = Z_NULL; state->mode = TYPE; state->last = 0; state->whave = 0; next = strm->next_in; have = next != Z_NULL ? strm->avail_in : 0; hold = 0; bits = 0; put = state->window; left = state->wsize; /* Inflate until end of block marked as last */ for (;;) switch (state->mode) { case TYPE: /* determine and dispatch block type */ if (state->last) { BYTEBITS(); state->mode = DONE; break; } NEEDBITS(3); state->last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); state->mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN; /* decode codes */ break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); state->mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); break; case STORED: /* get and verify stored block length */ BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } state->length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state->length)); INITBITS(); /* copy stored block from input to output */ while (state->length != 0) { copy = state->length; PULL(); ROOM(); if (copy > have) copy = have; if (copy > left) copy = left; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state->length -= copy; } Tracev((stderr, "inflate: stored end\n")); state->mode = TYPE; break; case TABLE: /* get dynamic table entries descriptor */ NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); /* get code length code lengths (not a typo) */ state->have = 0; while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); /* get length and distance code code lengths */ state->have = 0; while (state->have < state->nlen + state->ndist) { for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } len = (unsigned)(state->lens[state->have - 1]); copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state->mode == BAD) break; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { strm->msg = (char *)"invalid code -- missing end-of-block"; state->mode = BAD; break; } /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } state->distcode = (code const FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN; /* fallthrough */ case LEN: /* use inflate_fast() if we have enough input and output */ if (have >= 6 && left >= 258) { RESTORE(); if (state->whave < state->wsize) state->whave = state->wsize - left; inflate_fast(strm, state->wsize); LOAD(); break; } /* get a literal, length, or end-of-block code */ for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); state->length = (unsigned)here.val; /* process literal */ if (here.op == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); ROOM(); *put++ = (unsigned char)(state->length); left--; state->mode = LEN; break; } /* process end of block */ if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } /* invalid code */ if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } /* length code -- get extra bits, if any */ state->extra = (unsigned)(here.op) & 15; if (state->extra != 0) { NEEDBITS(state->extra); state->length += BITS(state->extra); DROPBITS(state->extra); } Tracevv((stderr, "inflate: length %u\n", state->length)); /* get distance code */ for (;;) { here = state->distcode[BITS(state->distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); if (here.op & 64) { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; /* get distance extra bits, if any */ state->extra = (unsigned)(here.op) & 15; if (state->extra != 0) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); } if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } Tracevv((stderr, "inflate: distance %u\n", state->offset)); /* copy match from window to output */ do { ROOM(); copy = state->wsize - state->offset; if (copy < left) { from = put + copy; copy = left - copy; } else { from = put - state->offset; copy = left; } if (copy > state->length) copy = state->length; state->length -= copy; left -= copy; do { *put++ = *from++; } while (--copy); } while (state->length != 0); break; case DONE: /* inflate stream terminated properly */ ret = Z_STREAM_END; goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; default: /* can't happen, but makes compilers happy */ ret = Z_STREAM_ERROR; goto inf_leave; } /* Write leftover output and return unused input */ inf_leave: if (left < state->wsize) { if (out(out_desc, state->window, state->wsize - left) && ret == Z_STREAM_END) ret = Z_BUF_ERROR; } strm->next_in = next; strm->avail_in = have; return ret; } int ZEXPORT inflateBackEnd(z_streamp strm) { if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } fltk-1.4.3/zlib/CMakeLists.txt0000644000175000017500000000377215004135251016316 0ustar albrechtalbrecht# # ZLIB library CMake configuration for the Fast Light Toolkit (FLTK). # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # # source files for zlib set(ZLIB_SRCS adler32.c compress.c crc32.c deflate.c gzclose.c gzlib.c gzread.c gzwrite.c inflate.c infback.c inftrees.c inffast.c trees.c uncompr.c zutil.c ) ####################################################################### # Suppress some Visual Studio compiler warnings set(msvc_warnings /wd4267 /wd4996) ####################################################################### # Build the static library ####################################################################### fl_add_library(fltk_z STATIC "${ZLIB_SRCS}") if(MSVC) target_compile_options(fltk_z PRIVATE ${msvc_warnings}) endif(MSVC) ####################################################################### # Build the shared library (optional) ####################################################################### if(FLTK_BUILD_SHARED_LIBS) # ensure to export all symbols for Windows DLL's set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) fl_add_library(fltk_z SHARED "${ZLIB_SRCS}") if(MSVC) target_compile_options(fltk_z-shared PRIVATE ${msvc_warnings}) endif(MSVC) endif(FLTK_BUILD_SHARED_LIBS) set(FLTK_LIBRARIES ${FLTK_LIBRARIES} PARENT_SCOPE) set(FLTK_LIBRARIES_SHARED ${FLTK_LIBRARIES_SHARED} PARENT_SCOPE) ####################################################################### # Install the library headers ####################################################################### install(FILES zconf.h zlib.h zutil.h DESTINATION ${FLTK_INCLUDEDIR}/FL/images ) fltk-1.4.3/zlib/adler32.c0000644000175000017500000001154415004135251015152 0ustar albrechtalbrecht/* adler32.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" #define BASE 65521U /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); /* use NO_DIVIDE if your processor does not do division in hardware -- try it both ways to see which is faster */ #ifdef NO_DIVIDE /* note that this assumes BASE is 65521, where 65536 % 65521 == 15 (thank you to John Reiser for pointing this out) */ # define CHOP(a) \ do { \ unsigned long tmp = a >> 16; \ a &= 0xffffUL; \ a += (tmp << 4) - tmp; \ } while (0) # define MOD28(a) \ do { \ CHOP(a); \ if (a >= BASE) a -= BASE; \ } while (0) # define MOD(a) \ do { \ CHOP(a); \ MOD28(a); \ } while (0) # define MOD63(a) \ do { /* this assumes a is not negative */ \ z_off64_t tmp = a >> 32; \ a &= 0xffffffffL; \ a += (tmp << 8) - (tmp << 5) + tmp; \ tmp = a >> 16; \ a &= 0xffffL; \ a += (tmp << 4) - tmp; \ tmp = a >> 16; \ a &= 0xffffL; \ a += (tmp << 4) - tmp; \ if (a >= BASE) a -= BASE; \ } while (0) #else # define MOD(a) a %= BASE # define MOD28(a) a %= BASE # define MOD63(a) a %= BASE #endif /* ========================================================================= */ uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) { unsigned long sum2; unsigned n; /* split Adler-32 into component sums */ sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; /* in case user likes doing a byte at a time, keep it fast */ if (len == 1) { adler += buf[0]; if (adler >= BASE) adler -= BASE; sum2 += adler; if (sum2 >= BASE) sum2 -= BASE; return adler | (sum2 << 16); } /* initial Adler-32 value (deferred check for len == 1 speed) */ if (buf == Z_NULL) return 1L; /* in case short lengths are provided, keep it somewhat fast */ if (len < 16) { while (len--) { adler += *buf++; sum2 += adler; } if (adler >= BASE) adler -= BASE; MOD28(sum2); /* only added so many BASE's */ return adler | (sum2 << 16); } /* do length NMAX blocks -- requires just one modulo operation */ while (len >= NMAX) { len -= NMAX; n = NMAX / 16; /* NMAX is divisible by 16 */ do { DO16(buf); /* 16 sums unrolled */ buf += 16; } while (--n); MOD(adler); MOD(sum2); } /* do remaining bytes (less than NMAX, still just one modulo) */ if (len) { /* avoid modulos if none remaining */ while (len >= 16) { len -= 16; DO16(buf); buf += 16; } while (len--) { adler += *buf++; sum2 += adler; } MOD(adler); MOD(sum2); } /* return recombined sums */ return adler | (sum2 << 16); } /* ========================================================================= */ uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) { return adler32_z(adler, buf, len); } /* ========================================================================= */ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) { unsigned long sum1; unsigned long sum2; unsigned rem; /* for negative len, return invalid adler32 as a clue for debugging */ if (len2 < 0) return 0xffffffffUL; /* the derivation of this formula is left as an exercise for the reader */ MOD63(len2); /* assumes len2 >= 0 */ rem = (unsigned)len2; sum1 = adler1 & 0xffff; sum2 = rem * sum1; MOD(sum2); sum1 += (adler2 & 0xffff) + BASE - 1; sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; if (sum1 >= BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE; if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); if (sum2 >= BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } /* ========================================================================= */ uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) { return adler32_combine_(adler1, adler2, len2); } uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) { return adler32_combine_(adler1, adler2, len2); } fltk-1.4.3/zlib/inflate.h0000644000175000017500000001503315004135251015342 0ustar albrechtalbrecht/* inflate.h -- internal inflate state definition * Copyright (C) 1995-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip decoding should be left enabled. */ #ifndef NO_GZIP # define GUNZIP #endif /* Possible inflate modes between inflate() calls */ typedef enum { HEAD = 16180, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ EXLEN, /* i: waiting for extra length (gzip) */ EXTRA, /* i: waiting for extra bytes (gzip) */ NAME, /* i: waiting for end of file name (gzip) */ COMMENT, /* i: waiting for end of comment (gzip) */ HCRC, /* i: waiting for header crc (gzip) */ DICTID, /* i: waiting for dictionary check value */ DICT, /* waiting for inflateSetDictionary() call */ TYPE, /* i: waiting for type bits, including last-flag bit */ TYPEDO, /* i: same, but skip check to exit inflate on new block */ STORED, /* i: waiting for stored size (length and complement) */ COPY_, /* i/o: same as COPY below, but only first time in */ COPY, /* i/o: waiting for input or output to copy stored block */ TABLE, /* i: waiting for dynamic block table lengths */ LENLENS, /* i: waiting for code length code lengths */ CODELENS, /* i: waiting for length/lit and distance code lengths */ LEN_, /* i: same as LEN below, but only first time in */ LEN, /* i: waiting for length/lit/eob code */ LENEXT, /* i: waiting for length extra bits */ DIST, /* i: waiting for distance code */ DISTEXT, /* i: waiting for distance extra bits */ MATCH, /* o: waiting for output space to copy string */ LIT, /* o: waiting for output space to write literal */ CHECK, /* i: waiting for 32-bit check value */ LENGTH, /* i: waiting for 32-bit length (gzip) */ DONE, /* finished check, done -- remain here until reset */ BAD, /* got a data error -- remain here until reset */ MEM, /* got an inflate() memory error -- remain here until reset */ SYNC /* looking for synchronization bytes to restart inflate() */ } inflate_mode; /* State transitions between above modes - (most modes can go to BAD or MEM on error -- not shown for clarity) Process header: HEAD -> (gzip) or (zlib) or (raw) (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> HCRC -> TYPE (zlib) -> DICTID or TYPE DICTID -> DICT -> TYPE (raw) -> TYPEDO Read deflate blocks: TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK STORED -> COPY_ -> COPY -> TYPE TABLE -> LENLENS -> CODELENS -> LEN_ LEN_ -> LEN Read deflate codes in fixed or dynamic block: LEN -> LENEXT or LIT or TYPE LENEXT -> DIST -> DISTEXT -> MATCH -> LEN LIT -> LEN Process trailer: CHECK -> LENGTH -> DONE */ /* State maintained between inflate() calls -- approximately 7K bytes, not including the allocated sliding window, which is up to 32K bytes. */ struct inflate_state { z_streamp strm; /* pointer back to this zlib stream */ inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip, bit 2 true to validate check value */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags, 0 if zlib, or -1 if raw or no header yet */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned long check; /* protected copy of check value */ unsigned long total; /* protected copy of output count */ gz_headerp head; /* where to save gzip header information */ /* sliding window */ unsigned wbits; /* log base 2 of requested window size */ unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if needed */ /* bit accumulator */ unsigned long hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ /* for string and stored block copying */ unsigned length; /* literal or length of data to copy */ unsigned offset; /* distance back to copy string from */ /* for table and code decoding */ unsigned extra; /* extra bits needed */ /* fixed and dynamic code tables */ code const FAR *lencode; /* starting table for length/literal codes */ code const FAR *distcode; /* starting table for distance codes */ unsigned lenbits; /* index bits for lencode */ unsigned distbits; /* index bits for distcode */ /* dynamic table building */ unsigned ncode; /* number of code length code lengths */ unsigned nlen; /* number of length code lengths */ unsigned ndist; /* number of distance code lengths */ unsigned have; /* number of code lengths in lens[] */ code FAR *next; /* next available space in codes[] */ unsigned short lens[320]; /* temporary storage for code lengths */ unsigned short work[288]; /* work area for code table building */ code codes[ENOUGH]; /* space for code tables */ int sane; /* if false, allow invalid distance too far */ int back; /* bits back of last unprocessed length/lit */ unsigned was; /* initial length of match */ }; fltk-1.4.3/zlib/gzwrite.c0000644000175000017500000004544515004135251015420 0ustar albrechtalbrecht/* gzwrite.c -- zlib functions for writing gzip files * Copyright (C) 2004-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" /* Initialize state for writing a gzip file. Mark initialization by setting state->size to non-zero. Return -1 on a memory allocation failure, or 0 on success. */ local int gz_init(gz_statep state) { int ret; z_streamp strm = &(state->strm); /* allocate input buffer (double size for gzprintf) */ state->in = (unsigned char *)malloc(state->want << 1); if (state->in == NULL) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } /* only need output buffer and deflate state if compressing */ if (!state->direct) { /* allocate output buffer */ state->out = (unsigned char *)malloc(state->want); if (state->out == NULL) { free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } /* allocate deflate memory, set up for gzip compression */ strm->zalloc = Z_NULL; strm->zfree = Z_NULL; strm->opaque = Z_NULL; ret = deflateInit2(strm, state->level, Z_DEFLATED, MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); if (ret != Z_OK) { free(state->out); free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } strm->next_in = NULL; } /* mark state as initialized */ state->size = state->want; /* initialize write buffer if compressing */ if (!state->direct) { strm->avail_out = state->size; strm->next_out = state->out; state->x.next = strm->next_out; } return 0; } /* Compress whatever is at avail_in and next_in and write to the output file. Return -1 if there is an error writing to the output file or if gz_init() fails to allocate memory, otherwise 0. flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, then the deflate() state is reset to start a new gzip stream. If gz->direct is true, then simply write to the output file without compressing, and ignore flush. */ local int gz_comp(gz_statep state, int flush) { int ret, writ; unsigned have, put, max = ((unsigned)-1 >> 2) + 1; z_streamp strm = &(state->strm); /* allocate memory if this is the first time through */ if (state->size == 0 && gz_init(state) == -1) return -1; /* write directly if requested */ if (state->direct) { while (strm->avail_in) { put = strm->avail_in > max ? max : strm->avail_in; writ = write(state->fd, strm->next_in, put); if (writ < 0) { gz_error(state, Z_ERRNO, zstrerror()); return -1; } strm->avail_in -= (unsigned)writ; strm->next_in += writ; } return 0; } /* check for a pending reset */ if (state->reset) { /* don't start a new gzip member unless there is data to write */ if (strm->avail_in == 0) return 0; deflateReset(strm); state->reset = 0; } /* run deflate() on provided input until it produces no more output */ ret = Z_OK; do { /* write out current buffer contents if full, or if flushing, but if doing Z_FINISH then don't write until we get to Z_STREAM_END */ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { while (strm->next_out > state->x.next) { put = strm->next_out - state->x.next > (int)max ? max : (unsigned)(strm->next_out - state->x.next); writ = write(state->fd, state->x.next, put); if (writ < 0) { gz_error(state, Z_ERRNO, zstrerror()); return -1; } state->x.next += writ; } if (strm->avail_out == 0) { strm->avail_out = state->size; strm->next_out = state->out; state->x.next = state->out; } } /* compress */ have = strm->avail_out; ret = deflate(strm, flush); if (ret == Z_STREAM_ERROR) { gz_error(state, Z_STREAM_ERROR, "internal error: deflate stream corrupt"); return -1; } have -= strm->avail_out; } while (have); /* if that completed a deflate stream, allow another to start */ if (flush == Z_FINISH) state->reset = 1; /* all done, no errors */ return 0; } /* Compress len zeros to output. Return -1 on a write error or memory allocation failure by gz_comp(), or 0 on success. */ local int gz_zero(gz_statep state, z_off64_t len) { int first; unsigned n; z_streamp strm = &(state->strm); /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return -1; /* compress len zeros (len guaranteed > 0) */ first = 1; while (len) { n = GT_OFF(state->size) || (z_off64_t)state->size > len ? (unsigned)len : state->size; if (first) { memset(state->in, 0, n); first = 0; } strm->avail_in = n; strm->next_in = state->in; state->x.pos += n; if (gz_comp(state, Z_NO_FLUSH) == -1) return -1; len -= n; } return 0; } /* Write len bytes from buf to file. Return the number of bytes written. If the returned value is less than len, then there was an error. */ local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) { z_size_t put = len; /* if len is zero, avoid unnecessary operations */ if (len == 0) return 0; /* allocate memory if this is the first time through */ if (state->size == 0 && gz_init(state) == -1) return 0; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return 0; } /* for small len, copy to input buffer, otherwise compress directly */ if (len < state->size) { /* copy to input buffer, compress when full */ do { unsigned have, copy; if (state->strm.avail_in == 0) state->strm.next_in = state->in; have = (unsigned)((state->strm.next_in + state->strm.avail_in) - state->in); copy = state->size - have; if (copy > len) copy = (unsigned)len; memcpy(state->in + have, buf, copy); state->strm.avail_in += copy; state->x.pos += copy; buf = (const char *)buf + copy; len -= copy; if (len && gz_comp(state, Z_NO_FLUSH) == -1) return 0; } while (len); } else { /* consume whatever's left in the input buffer */ if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* directly compress user buffer to file */ state->strm.next_in = (z_const Bytef *)buf; do { unsigned n = (unsigned)-1; if (n > len) n = (unsigned)len; state->strm.avail_in = n; state->x.pos += n; if (gz_comp(state, Z_NO_FLUSH) == -1) return 0; len -= n; } while (len); } /* input was all buffered or compressed */ return put; } /* -- see zlib.h -- */ int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) { gz_statep state; /* get internal structure */ if (file == NULL) return 0; state = (gz_statep)file; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids a flaw in the interface) */ if ((int)len < 0) { gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); return 0; } /* write len bytes from buf (the return value will fit in an int) */ return (int)gz_write(state, buf, len); } /* -- see zlib.h -- */ z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems, gzFile file) { z_size_t len; gz_statep state; /* get internal structure */ if (file == NULL) return 0; state = (gz_statep)file; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; /* compute bytes to read -- error on overflow */ len = nitems * size; if (size && len / size != nitems) { gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); return 0; } /* write len bytes to buf, return the number of full items written */ return len ? gz_write(state, buf, len) / size : 0; } /* -- see zlib.h -- */ int ZEXPORT gzputc(gzFile file, int c) { unsigned have; unsigned char buf[1]; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return -1; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return -1; } /* try writing to input buffer for speed (state->size == 0 if buffer not initialized) */ if (state->size) { if (strm->avail_in == 0) strm->next_in = state->in; have = (unsigned)((strm->next_in + strm->avail_in) - state->in); if (have < state->size) { state->in[have] = (unsigned char)c; strm->avail_in++; state->x.pos++; return c & 0xff; } } /* no room in buffer or not initialized, use gz_write() */ buf[0] = (unsigned char)c; if (gz_write(state, buf, 1) != 1) return -1; return c & 0xff; } /* -- see zlib.h -- */ int ZEXPORT gzputs(gzFile file, const char *s) { z_size_t len, put; gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return -1; /* write string */ len = strlen(s); if ((int)len < 0 || (unsigned)len != len) { gz_error(state, Z_STREAM_ERROR, "string length does not fit in int"); return -1; } put = gz_write(state, s, len); return put < len ? -1 : (int)len; } #if defined(STDC) || defined(Z_HAVE_STDARG_H) #include /* -- see zlib.h -- */ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { int len; unsigned left; char *next; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return Z_STREAM_ERROR; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) return state->err; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return state->err; } /* do the printf() into the input buffer, put length in len -- the input buffer is double-sized just for this function, so there is guaranteed to be state->size bytes available after the current contents */ if (strm->avail_in == 0) strm->next_in = state->in; next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); next[state->size - 1] = 0; #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void (void)vsprintf(next, format, va); for (len = 0; len < state->size; len++) if (next[len] == 0) break; # else len = vsprintf(next, format, va); # endif #else # ifdef HAS_vsnprintf_void (void)vsnprintf(next, state->size, format, va); len = strlen(next); # else len = vsnprintf(next, state->size, format, va); # endif #endif /* check that printf() results fit in buffer */ if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) return 0; /* update buffer and position, compress first half if past that */ strm->avail_in += (unsigned)len; state->x.pos += len; if (strm->avail_in >= state->size) { left = strm->avail_in - state->size; strm->avail_in = state->size; if (gz_comp(state, Z_NO_FLUSH) == -1) return state->err; memmove(state->in, state->in + state->size, left); strm->next_in = state->in; strm->avail_in = left; } return len; } int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) { va_list va; int ret; va_start(va, format); ret = gzvprintf(file, format, va); va_end(va); return ret; } #else /* !STDC && !Z_HAVE_STDARG_H */ /* -- see zlib.h -- */ int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20) { unsigned len, left; char *next; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that can really pass pointer in ints */ if (sizeof(int) != sizeof(void *)) return Z_STREAM_ERROR; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return Z_STREAM_ERROR; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) return state->error; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return state->error; } /* do the printf() into the input buffer, put length in len -- the input buffer is double-sized just for this function, so there is guaranteed to be state->size bytes available after the current contents */ if (strm->avail_in == 0) strm->next_in = state->in; next = (char *)(strm->next_in + strm->avail_in); next[state->size - 1] = 0; #ifdef NO_snprintf # ifdef HAS_sprintf_void sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); for (len = 0; len < size; len++) if (next[len] == 0) break; # else len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #else # ifdef HAS_snprintf_void snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); len = strlen(next); # else len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #endif /* check that printf() results fit in buffer */ if (len == 0 || len >= state->size || next[state->size - 1] != 0) return 0; /* update buffer and position, compress first half if past that */ strm->avail_in += len; state->x.pos += len; if (strm->avail_in >= state->size) { left = strm->avail_in - state->size; strm->avail_in = state->size; if (gz_comp(state, Z_NO_FLUSH) == -1) return state->err; memmove(state->in, state->in + state->size, left); strm->next_in = state->in; strm->avail_in = left; } return (int)len; } #endif /* -- see zlib.h -- */ int ZEXPORT gzflush(gzFile file, int flush) { gz_statep state; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return Z_STREAM_ERROR; /* check flush parameter */ if (flush < 0 || flush > Z_FINISH) return Z_STREAM_ERROR; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return state->err; } /* compress remaining data with requested flush */ (void)gz_comp(state, flush); return state->err; } /* -- see zlib.h -- */ int ZEXPORT gzsetparams(gzFile file, int level, int strategy) { gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct) return Z_STREAM_ERROR; /* if no change is requested, then do nothing */ if (level == state->level && strategy == state->strategy) return Z_OK; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return state->err; } /* change compression parameters for subsequent input */ if (state->size) { /* flush previous input with previous parameters before changing */ if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) return state->err; deflateParams(strm, level, strategy); } state->level = level; state->strategy = strategy; return Z_OK; } /* -- see zlib.h -- */ int ZEXPORT gzclose_w(gzFile file) { int ret = Z_OK; gz_statep state; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're writing */ if (state->mode != GZ_WRITE) return Z_STREAM_ERROR; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) ret = state->err; } /* flush, free memory, and close file */ if (gz_comp(state, Z_FINISH) == -1) ret = state->err; if (state->size) { if (!state->direct) { (void)deflateEnd(&(state->strm)); free(state->out); } free(state->in); } gz_error(state, Z_OK, NULL); free(state->path); if (close(state->fd) == -1) ret = Z_ERRNO; free(state); return ret; } fltk-1.4.3/zlib/inflate.c0000644000175000017500000015433715004135251015350 0ustar albrechtalbrecht/* inflate.c -- zlib decompression * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * Change history: * * 1.2.beta0 24 Nov 2002 * - First version -- complete rewrite of inflate to simplify code, avoid * creation of window when not needed, minimize use of window when it is * needed, make inffast.c even faster, implement gzip decoding, and to * improve code readability and style over the previous zlib inflate code * * 1.2.beta1 25 Nov 2002 * - Use pointers for available input and output checking in inffast.c * - Remove input and output counters in inffast.c * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 * - Remove unnecessary second byte pull from length extra in inffast.c * - Unroll direct copy to three copies per loop in inffast.c * * 1.2.beta2 4 Dec 2002 * - Change external routine names to reduce potential conflicts * - Correct filename to inffixed.h for fixed tables in inflate.c * - Make hbuf[] unsigned char to match parameter type in inflate.c * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) * to avoid negation problem on Alphas (64 bit) in inflate.c * * 1.2.beta3 22 Dec 2002 * - Add comments on state->bits assertion in inffast.c * - Add comments on op field in inftrees.h * - Fix bug in reuse of allocated window after inflateReset() * - Remove bit fields--back to byte structure for speed * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths * - Change post-increments to pre-increments in inflate_fast(), PPC biased? * - Add compile time option, POSTINC, to use post-increments instead (Intel?) * - Make MATCH copy in inflate() much faster for when inflate_fast() not used * - Use local copies of stream next and avail values, as well as local bit * buffer and bit count in inflate()--for speed when inflate_fast() not used * * 1.2.beta4 1 Jan 2003 * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings * - Move a comment on output buffer sizes from inffast.c to inflate.c * - Add comments in inffast.c to introduce the inflate_fast() routine * - Rearrange window copies in inflate_fast() for speed and simplification * - Unroll last copy for window match in inflate_fast() * - Use local copies of window variables in inflate_fast() for speed * - Pull out common wnext == 0 case for speed in inflate_fast() * - Make op and len in inflate_fast() unsigned for consistency * - Add FAR to lcode and dcode declarations in inflate_fast() * - Simplified bad distance check in inflate_fast() * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new * source file infback.c to provide a call-back interface to inflate for * programs like gzip and unzip -- uses window as output buffer to avoid * window copying * * 1.2.beta5 1 Jan 2003 * - Improved inflateBack() interface to allow the caller to provide initial * input in strm. * - Fixed stored blocks bug in inflateBack() * * 1.2.beta6 4 Jan 2003 * - Added comments in inffast.c on effectiveness of POSTINC * - Typecasting all around to reduce compiler warnings * - Changed loops from while (1) or do {} while (1) to for (;;), again to * make compilers happy * - Changed type of window in inflateBackInit() to unsigned char * * * 1.2.beta7 27 Jan 2003 * - Changed many types to unsigned or unsigned short to avoid warnings * - Added inflateCopy() function * * 1.2.0 9 Mar 2003 * - Changed inflateBack() interface to provide separate opaque descriptors * for the in() and out() functions * - Changed inflateBack() argument and in_func typedef to swap the length * and buffer address return values for the input function * - Check next_in and next_out for Z_NULL on entry to inflate() * * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" #ifdef MAKEFIXED # ifndef BUILDFIXED # define BUILDFIXED # endif #endif local int inflateStateCheck(z_streamp strm) { struct inflate_state FAR *state; if (strm == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) return 1; state = (struct inflate_state FAR *)strm->state; if (state == Z_NULL || state->strm != strm || state->mode < HEAD || state->mode > SYNC) return 1; return 0; } int ZEXPORT inflateResetKeep(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; if (state->wrap) /* to support ill-conceived Java test suite */ strm->adler = state->wrap & 1; state->mode = HEAD; state->last = 0; state->havedict = 0; state->flags = -1; state->dmax = 32768U; state->head = Z_NULL; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; state->sane = 1; state->back = -1; Tracev((stderr, "inflate: reset\n")); return Z_OK; } int ZEXPORT inflateReset(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; state->wsize = 0; state->whave = 0; state->wnext = 0; return inflateResetKeep(strm); } int ZEXPORT inflateReset2(z_streamp strm, int windowBits) { int wrap; struct inflate_state FAR *state; /* get the state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* extract wrap request from windowBits parameter */ if (windowBits < 0) { if (windowBits < -15) return Z_STREAM_ERROR; wrap = 0; windowBits = -windowBits; } else { wrap = (windowBits >> 4) + 5; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; #endif } /* set number of window bits, free window if different */ if (windowBits && (windowBits < 8 || windowBits > 15)) return Z_STREAM_ERROR; if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { ZFREE(strm, state->window); state->window = Z_NULL; } /* update state and reset the rest of it */ state->wrap = wrap; state->wbits = (unsigned)windowBits; return inflateReset(strm); } int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) { int ret; struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; #endif } if (strm->zfree == (free_func)0) #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zfree = zcfree; #endif state = (struct inflate_state FAR *) ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->strm = strm; state->window = Z_NULL; state->mode = HEAD; /* to pass state test in inflateReset2() */ ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); strm->state = Z_NULL; } return ret; } int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size) { return inflateInit2_(strm, DEF_WBITS, version, stream_size); } int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; if (bits == 0) return Z_OK; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; state->bits = 0; return Z_OK; } if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; state->hold += (unsigned)value << state->bits; state->bits += (uInt)bits; return Z_OK; } /* Return state with length and distance decoding tables and index sizes set to fixed code decoding. Normally this returns fixed tables from inffixed.h. If BUILDFIXED is defined, then instead this routine builds the tables the first time it's called, and returns those tables the first time and thereafter. This reduces the size of the code by about 2K bytes, in exchange for a little execution time. However, BUILDFIXED should not be used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ local void fixedtables(struct inflate_state FAR *state) { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { unsigned sym, bits; static code *next; /* literal/length table */ sym = 0; while (sym < 144) state->lens[sym++] = 8; while (sym < 256) state->lens[sym++] = 9; while (sym < 280) state->lens[sym++] = 7; while (sym < 288) state->lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); /* distance table */ sym = 0; while (sym < 32) state->lens[sym++] = 5; distfix = next; bits = 5; inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); /* do this just once */ virgin = 0; } #else /* !BUILDFIXED */ # include "inffixed.h" #endif /* BUILDFIXED */ state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; state->distbits = 5; } #ifdef MAKEFIXED #include /* Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also defines BUILDFIXED, so the tables are built on the fly. makefixed() writes those tables to stdout, which would be piped to inffixed.h. A small program can simply call makefixed to do this: void makefixed(void); int main(void) { makefixed(); return 0; } Then that can be linked with zlib built with MAKEFIXED defined and run: a.out > inffixed.h */ void makefixed(void) { unsigned low, size; struct inflate_state state; fixedtables(&state); puts(" /* inffixed.h -- table for decoding fixed codes"); puts(" * Generated automatically by makefixed()."); puts(" */"); puts(""); puts(" /* WARNING: this file should *not* be used by applications."); puts(" It is part of the implementation of this library and is"); puts(" subject to change. Applications should only use zlib.h."); puts(" */"); puts(""); size = 1U << 9; printf(" static const code lenfix[%u] = {", size); low = 0; for (;;) { if ((low % 7) == 0) printf("\n "); printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, state.lencode[low].bits, state.lencode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); size = 1U << 5; printf("\n static const code distfix[%u] = {", size); low = 0; for (;;) { if ((low % 6) == 0) printf("\n "); printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, state.distcode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); } #endif /* MAKEFIXED */ /* Update the window with the last wsize (normally 32K) bytes written before returning. If window does not exist yet, create it. This is only called when a window is already in use, or when output has been written during this inflate call, but the end of the deflate stream has not been reached yet. It is also called to create a window for dictionary data when a dictionary is loaded. Providing output buffers larger than 32K to inflate() should provide a speed advantage, since only the last 32K of output is copied to the sliding window upon return from inflate(), and since all distances after the first 32K of output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) { struct inflate_state FAR *state; unsigned dist; state = (struct inflate_state FAR *)strm->state; /* if it hasn't been done already, allocate space for the window */ if (state->window == Z_NULL) { state->window = (unsigned char FAR *) ZALLOC(strm, 1U << state->wbits, sizeof(unsigned char)); if (state->window == Z_NULL) return 1; } /* if window not in use yet, initialize */ if (state->wsize == 0) { state->wsize = 1U << state->wbits; state->wnext = 0; state->whave = 0; } /* copy state->wsize or less output bytes into the circular window */ if (copy >= state->wsize) { zmemcpy(state->window, end - state->wsize, state->wsize); state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; if (dist > copy) dist = copy; zmemcpy(state->window + state->wnext, end - copy, dist); copy -= dist; if (copy) { zmemcpy(state->window, end - copy, copy); state->wnext = copy; state->whave = state->wsize; } else { state->wnext += dist; if (state->wnext == state->wsize) state->wnext = 0; if (state->whave < state->wsize) state->whave += dist; } } return 0; } /* Macros for inflate(): */ /* check function to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP # define UPDATE_CHECK(check, buf, len) \ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) #else # define UPDATE_CHECK(check, buf, len) adler32(check, buf, len) #endif /* check macros for header crc */ #ifdef GUNZIP # define CRC2(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ check = crc32(check, hbuf, 2); \ } while (0) # define CRC4(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ hbuf[2] = (unsigned char)((word) >> 16); \ hbuf[3] = (unsigned char)((word) >> 24); \ check = crc32(check, hbuf, 4); \ } while (0) #endif /* Load registers with state in inflate() for speed */ #define LOAD() \ do { \ put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ hold = state->hold; \ bits = state->bits; \ } while (0) /* Restore state from registers in inflate() */ #define RESTORE() \ do { \ strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = next; \ strm->avail_in = have; \ state->hold = hold; \ state->bits = bits; \ } while (0) /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflate() if there is no input available. */ #define PULLBYTE() \ do { \ if (have == 0) goto inf_leave; \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflate(). */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is structured roughly as follows: for (;;) switch (state) { ... case STATEn: if (not enough input data or output space to make progress) return; ... make progress ... state = STATEm; break; ... } so when inflate() is called again, the same case is attempted again, and if the appropriate resources are provided, the machine proceeds to the next state. The NEEDBITS() macro is usually the way the state evaluates whether it can proceed or should return. NEEDBITS() does the return if the requested bits are not available. The typical use of the BITS macros is: NEEDBITS(n); ... do something with BITS(n) ... DROPBITS(n); where NEEDBITS(n) either returns from inflate() if there isn't enough input left to load n bits into the accumulator, or it continues. BITS(n) gives the low n bits in the accumulator. When done, DROPBITS(n) drops the low n bits off the accumulator. INITBITS() clears the accumulator and sets the number of available bits to zero. BYTEBITS() discards just enough bits to put the accumulator on a byte boundary. After BYTEBITS() and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return if there is no input available. The decoding of variable length codes uses PULLBYTE() directly in order to pull just enough bytes to decode the next code, and no more. Some states loop until they get enough input, making sure that enough state information is maintained to continue the loop where it left off if NEEDBITS() returns in the loop. For example, want, need, and keep would all have to actually be part of the saved state in case NEEDBITS() returns: case STATEw: while (want < need) { NEEDBITS(n); keep[want++] = BITS(n); DROPBITS(n); } state = STATEx; case STATEx: As shown above, if the next state is also the next case, then the break is omitted. A state may also return if there is not enough output space available to complete that state. Those states are copying stored data, writing a literal byte, and copying a matching string. When returning, a "goto inf_leave" is used to update the total counters, update the check value, and determine whether any progress has been made during that inflate() call in order to return the proper return code. Progress is defined as a change in either strm->avail_in or strm->avail_out. When there is a window, goto inf_leave will update the window with the last output written. If a goto inf_leave occurs in the middle of decompression and there is no window currently, goto inf_leave will create one and copy output to the window for the next call of inflate(). In this implementation, the flush parameter of inflate() only affects the return code (per zlib.h). inflate() always writes as much as possible to strm->next_out, given the space available and the provided input--the effect documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers the allocation of and copying into a sliding window until necessary, which provides the effect documented in zlib.h for Z_FINISH when the entire input stream available. So the only thing the flush parameter actually does is: when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it will return Z_BUF_ERROR if it has not reached the end of the stream. */ int ZEXPORT inflate(z_streamp strm, int flush) { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned in, out; /* save starting available input and output */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char FAR *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ #ifdef GUNZIP unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ #endif static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; if (inflateStateCheck(strm) || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ LOAD(); in = have; out = left; ret = Z_OK; for (;;) switch (state->mode) { case HEAD: if (state->wrap == 0) { state->mode = TYPEDO; break; } NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ if (state->wbits == 0) state->wbits = 15; state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); state->mode = FLAGS; break; } if (state->head != Z_NULL) state->head->done = -1; if (!(state->wrap & 1) || /* check if zlib header allowed */ #else if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { strm->msg = (char *)"incorrect header check"; state->mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } DROPBITS(4); len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; if (len > 15 || len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; } state->dmax = 1U << len; state->flags = 0; /* indicate zlib header */ Tracev((stderr, "inflate: zlib header ok\n")); strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = hold & 0x200 ? DICTID : TYPE; INITBITS(); break; #ifdef GUNZIP case FLAGS: NEEDBITS(16); state->flags = (int)(hold); if ((state->flags & 0xff) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } if (state->flags & 0xe000) { strm->msg = (char *)"unknown header flags set"; state->mode = BAD; break; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); if ((state->flags & 0x0200) && (state->wrap & 4)) CRC2(state->check, hold); INITBITS(); state->mode = TIME; /* fallthrough */ case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; if ((state->flags & 0x0200) && (state->wrap & 4)) CRC4(state->check, hold); INITBITS(); state->mode = OS; /* fallthrough */ case OS: NEEDBITS(16); if (state->head != Z_NULL) { state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } if ((state->flags & 0x0200) && (state->wrap & 4)) CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; /* fallthrough */ case EXLEN: if (state->flags & 0x0400) { NEEDBITS(16); state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; if ((state->flags & 0x0200) && (state->wrap & 4)) CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) state->head->extra = Z_NULL; state->mode = EXTRA; /* fallthrough */ case EXTRA: if (state->flags & 0x0400) { copy = state->length; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && state->head->extra != Z_NULL && (len = state->head->extra_len - state->length) < state->head->extra_max) { zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; state->length -= copy; } if (state->length) goto inf_leave; } state->length = 0; state->mode = NAME; /* fallthrough */ case NAME: if (state->flags & 0x0800) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) state->head->name[state->length++] = (Bytef)len; } while (len && copy < have); if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->name = Z_NULL; state->length = 0; state->mode = COMMENT; /* fallthrough */ case COMMENT: if (state->flags & 0x1000) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) state->head->comment[state->length++] = (Bytef)len; } while (len && copy < have); if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->comment = Z_NULL; state->mode = HCRC; /* fallthrough */ case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); if ((state->wrap & 4) && hold != (state->check & 0xffff)) { strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; } INITBITS(); } if (state->head != Z_NULL) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } strm->adler = state->check = crc32(0L, Z_NULL, 0); state->mode = TYPE; break; #endif case DICTID: NEEDBITS(32); strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; /* fallthrough */ case DICT: if (state->havedict == 0) { RESTORE(); return Z_NEED_DICT; } strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = TYPE; /* fallthrough */ case TYPE: if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; /* fallthrough */ case TYPEDO: if (state->last) { BYTEBITS(); state->mode = CHECK; break; } NEEDBITS(3); state->last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); state->mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN_; /* decode codes */ if (flush == Z_TREES) { DROPBITS(2); goto inf_leave; } break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); state->mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); break; case STORED: BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } state->length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state->length)); INITBITS(); state->mode = COPY_; if (flush == Z_TREES) goto inf_leave; /* fallthrough */ case COPY_: state->mode = COPY; /* fallthrough */ case COPY: copy = state->length; if (copy) { if (copy > have) copy = have; if (copy > left) copy = left; if (copy == 0) goto inf_leave; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state->length -= copy; break; } Tracev((stderr, "inflate: stored end\n")); state->mode = TYPE; break; case TABLE: NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); state->have = 0; state->mode = LENLENS; /* fallthrough */ case LENLENS: while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; state->lencode = (const code FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); state->have = 0; state->mode = CODELENS; /* fallthrough */ case CODELENS: while (state->have < state->nlen + state->ndist) { for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } len = state->lens[state->have - 1]; copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state->mode == BAD) break; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { strm->msg = (char *)"invalid code -- missing end-of-block"; state->mode = BAD; break; } /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; state->lencode = (const code FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } state->distcode = (const code FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN_; if (flush == Z_TREES) goto inf_leave; /* fallthrough */ case LEN_: state->mode = LEN; /* fallthrough */ case LEN: if (have >= 6 && left >= 258) { RESTORE(); inflate_fast(strm, out); LOAD(); if (state->mode == TYPE) state->back = -1; break; } state->back = 0; for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; state->length = (unsigned)here.val; if ((int)(here.op) == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); state->mode = LIT; break; } if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state->back = -1; state->mode = TYPE; break; } if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } state->extra = (unsigned)(here.op) & 15; state->mode = LENEXT; /* fallthrough */ case LENEXT: if (state->extra) { NEEDBITS(state->extra); state->length += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } Tracevv((stderr, "inflate: length %u\n", state->length)); state->was = state->length; state->mode = DIST; /* fallthrough */ case DIST: for (;;) { here = state->distcode[BITS(state->distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; if (here.op & 64) { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; state->extra = (unsigned)(here.op) & 15; state->mode = DISTEXT; /* fallthrough */ case DISTEXT: if (state->extra) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } #ifdef INFLATE_STRICT if (state->offset > state->dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; /* fallthrough */ case MATCH: if (left == 0) goto inf_leave; copy = out - left; if (state->offset > copy) { /* copy from window */ copy = state->offset - copy; if (copy > state->whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR Trace((stderr, "inflate.c too far\n")); copy -= state->whave; if (copy > state->length) copy = state->length; if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = 0; } while (--copy); if (state->length == 0) state->mode = LEN; break; #endif } if (copy > state->wnext) { copy -= state->wnext; from = state->window + (state->wsize - copy); } else from = state->window + (state->wnext - copy); if (copy > state->length) copy = state->length; } else { /* copy from output */ from = put - state->offset; copy = state->length; } if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = *from++; } while (--copy); if (state->length == 0) state->mode = LEN; break; case LIT: if (left == 0) goto inf_leave; *put++ = (unsigned char)(state->length); left--; state->mode = LEN; break; case CHECK: if (state->wrap) { NEEDBITS(32); out -= left; strm->total_out += out; state->total += out; if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE_CHECK(state->check, put - out, out); out = left; if ((state->wrap & 4) && ( #ifdef GUNZIP state->flags ? hold : #endif ZSWAP32(hold)) != state->check) { strm->msg = (char *)"incorrect data check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: check matches trailer\n")); } #ifdef GUNZIP state->mode = LENGTH; /* fallthrough */ case LENGTH: if (state->wrap && state->flags) { NEEDBITS(32); if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { strm->msg = (char *)"incorrect length check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: length matches trailer\n")); } #endif state->mode = DONE; /* fallthrough */ case DONE: ret = Z_STREAM_END; goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; case MEM: return Z_MEM_ERROR; case SYNC: /* fallthrough */ default: return Z_STREAM_ERROR; } /* Return from inflate(), updating the total counts and the check value. If there was no progress during the inflate() call, return a buffer error. Call updatewindow() to create and/or update the window state. Note: a memory error from inflate() is non-recoverable. */ inf_leave: RESTORE(); if (state->wsize || (out != strm->avail_out && state->mode < BAD && (state->mode < CHECK || flush != Z_FINISH))) if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { state->mode = MEM; return Z_MEM_ERROR; } in -= strm->avail_in; out -= strm->avail_out; strm->total_in += in; strm->total_out += out; state->total += out; if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE_CHECK(state->check, strm->next_out - out, out); strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) ret = Z_BUF_ERROR; return ret; } int ZEXPORT inflateEnd(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary, uInt *dictLength) { struct inflate_state FAR *state; /* check state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* copy dictionary */ if (state->whave && dictionary != Z_NULL) { zmemcpy(dictionary, state->window + state->wnext, state->whave - state->wnext); zmemcpy(dictionary + state->whave - state->wnext, state->window, state->wnext); } if (dictLength != Z_NULL) *dictLength = state->whave; return Z_OK; } int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength) { struct inflate_state FAR *state; unsigned long dictid; int ret; /* check state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; /* check for correct dictionary identifier */ if (state->mode == DICT) { dictid = adler32(0L, Z_NULL, 0); dictid = adler32(dictid, dictionary, dictLength); if (dictid != state->check) return Z_DATA_ERROR; } /* copy dictionary to window using updatewindow(), which will amend the existing dictionary if appropriate */ ret = updatewindow(strm, dictionary + dictLength, dictLength); if (ret) { state->mode = MEM; return Z_MEM_ERROR; } state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; } int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) { struct inflate_state FAR *state; /* check state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; /* save header structure */ state->head = head; head->done = 0; return Z_OK; } /* Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found or when out of input. When called, *have is the number of pattern bytes found in order so far, in 0..3. On return *have is updated to the new state. If on return *have equals four, then the pattern was found and the return value is how many bytes were read including the last byte of the pattern. If *have is less than four, then the pattern has not been found yet and the return value is len. In the latter case, syncsearch() can be called again with more data and the *have state. *have is initialized to zero for the first call. */ local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf, unsigned len) { unsigned got; unsigned next; got = *have; next = 0; while (next < len && got < 4) { if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) got++; else if (buf[next]) got = 0; else got = 4 - got; next++; } *have = got; return next; } int ZEXPORT inflateSync(z_streamp strm) { unsigned len; /* number of bytes to look at or looked at */ int flags; /* temporary to save header status */ unsigned long in, out; /* temporary to save total_in and total_out */ unsigned char buf[4]; /* to restore bit buffer to byte string */ struct inflate_state FAR *state; /* check parameters */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; /* if first time, start search in bit buffer */ if (state->mode != SYNC) { state->mode = SYNC; state->hold >>= state->bits & 7; state->bits -= state->bits & 7; len = 0; while (state->bits >= 8) { buf[len++] = (unsigned char)(state->hold); state->hold >>= 8; state->bits -= 8; } state->have = 0; syncsearch(&(state->have), buf, len); } /* search available input */ len = syncsearch(&(state->have), strm->next_in, strm->avail_in); strm->avail_in -= len; strm->next_in += len; strm->total_in += len; /* return no joy or set up to restart inflate() on a new block */ if (state->have != 4) return Z_DATA_ERROR; if (state->flags == -1) state->wrap = 0; /* if no header yet, treat as raw */ else state->wrap &= ~4; /* no point in computing a check value now */ flags = state->flags; in = strm->total_in; out = strm->total_out; inflateReset(strm); strm->total_in = in; strm->total_out = out; state->flags = flags; state->mode = TYPE; return Z_OK; } /* Returns true if inflate is currently at the end of a block generated by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored block. When decompressing, PPP checks that at the end of input packet, inflate is waiting for these length bytes. */ int ZEXPORT inflateSyncPoint(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; return state->mode == STORED && state->bits == 0; } int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) { struct inflate_state FAR *state; struct inflate_state FAR *copy; unsigned char FAR *window; unsigned wsize; /* check input */ if (inflateStateCheck(source) || dest == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)source->state; /* allocate space */ copy = (struct inflate_state FAR *) ZALLOC(source, 1, sizeof(struct inflate_state)); if (copy == Z_NULL) return Z_MEM_ERROR; window = Z_NULL; if (state->window != Z_NULL) { window = (unsigned char FAR *) ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); if (window == Z_NULL) { ZFREE(source, copy); return Z_MEM_ERROR; } } /* copy state */ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); copy->strm = dest; if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); copy->distcode = copy->codes + (state->distcode - state->codes); } copy->next = copy->codes + (state->next - state->codes); if (window != Z_NULL) { wsize = 1U << state->wbits; zmemcpy(window, state->window, wsize); } copy->window = window; dest->state = (struct internal_state FAR *)copy; return Z_OK; } int ZEXPORT inflateUndermine(z_streamp strm, int subvert) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR state->sane = !subvert; return Z_OK; #else (void)subvert; state->sane = 1; return Z_DATA_ERROR; #endif } int ZEXPORT inflateValidate(z_streamp strm, int check) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (check && state->wrap) state->wrap |= 4; else state->wrap &= ~4; return Z_OK; } long ZEXPORT inflateMark(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return -(1L << 16); state = (struct inflate_state FAR *)strm->state; return (long)(((unsigned long)((long)state->back)) << 16) + (state->mode == COPY ? state->length : (state->mode == MATCH ? state->was - state->length : 0)); } unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return (unsigned long)-1; state = (struct inflate_state FAR *)strm->state; return (unsigned long)(state->next - state->codes); } fltk-1.4.3/zlib/deflate.h0000644000175000017500000003333115004135251015325 0ustar albrechtalbrecht/* deflate.h -- internal compression state * Copyright (C) 1995-2024 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id$ */ #ifndef DEFLATE_H #define DEFLATE_H #include "zutil.h" /* define NO_GZIP when compiling if you want to disable gzip header and trailer creation by deflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip encoding should be left enabled. */ #ifndef NO_GZIP # define GZIP #endif /* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at the cost of a larger memory footprint */ /* #define LIT_MEM */ /* =========================================================================== * Internal compression state. */ #define LENGTH_CODES 29 /* number of length codes, not counting the special END_BLOCK code */ #define LITERALS 256 /* number of literal bytes 0..255 */ #define L_CODES (LITERALS+1+LENGTH_CODES) /* number of Literal or Length codes, including the END_BLOCK code */ #define D_CODES 30 /* number of distance codes */ #define BL_CODES 19 /* number of codes used to transfer the bit lengths */ #define HEAP_SIZE (2*L_CODES+1) /* maximum heap size */ #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ #define Buf_size 16 /* size of bit buffer in bi_buf */ #define INIT_STATE 42 /* zlib header -> BUSY_STATE */ #ifdef GZIP # define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ #endif #define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ #define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ #define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ #define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ #define BUSY_STATE 113 /* deflate -> FINISH_STATE */ #define FINISH_STATE 666 /* stream complete */ /* Stream status */ /* Data structure describing a single value and its code string. */ typedef struct ct_data_s { union { ush freq; /* frequency count */ ush code; /* bit string */ } fc; union { ush dad; /* father node in Huffman tree */ ush len; /* length of bit string */ } dl; } FAR ct_data; #define Freq fc.freq #define Code fc.code #define Dad dl.dad #define Len dl.len typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ const static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; typedef Pos FAR Posf; typedef unsigned IPos; /* A Pos is an index in the character window. We use short instead of int to * save space in the various tables. IPos is used only for parameter passing. */ typedef struct internal_state { z_streamp strm; /* pointer back to this zlib stream */ int status; /* as the name implies */ Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ ulg pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ ulg gzindex; /* where in extra, name, or comment */ Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ uInt w_size; /* LZ77 window size (32K by default) */ uInt w_bits; /* log2(w_size) (8..16) */ uInt w_mask; /* w_size - 1 */ Bytef *window; /* Sliding window. Input bytes are read into the second half of the window, * and move to the first half later to keep a dictionary of at least wSize * bytes. With this organization, matches are limited to a distance of * wSize-MAX_MATCH bytes, but this ensures that IO is always * performed with a length multiple of the block size. Also, it limits * the window size to 64K, which is quite useful on MSDOS. * To do: use the user input buffer as sliding window. */ ulg window_size; /* Actual size of window: 2*wSize, except when the user input buffer * is directly used as sliding window. */ Posf *prev; /* Link to older string with same hash index. To limit the size of this * array to 64K, this link is maintained only for the last 32K strings. * An index in this array is thus a window index modulo 32K. */ Posf *head; /* Heads of the hash chains or NIL. */ uInt ins_h; /* hash index of string to be inserted */ uInt hash_size; /* number of elements in hash table */ uInt hash_bits; /* log2(hash_size) */ uInt hash_mask; /* hash_size-1 */ uInt hash_shift; /* Number of bits by which ins_h must be shifted at each input * step. It must be such that after MIN_MATCH steps, the oldest * byte no longer takes part in the hash key, that is: * hash_shift * MIN_MATCH >= hash_bits */ long block_start; /* Window position at the beginning of the current output block. Gets * negative when the window is moved backwards. */ uInt match_length; /* length of best match */ IPos prev_match; /* previous match */ int match_available; /* set if previous match exists */ uInt strstart; /* start of string to insert */ uInt match_start; /* start of matching string */ uInt lookahead; /* number of valid bytes ahead in window */ uInt prev_length; /* Length of the best match at previous step. Matches not greater than this * are discarded. This is used in the lazy match evaluation. */ uInt max_chain_length; /* To speed up deflation, hash chains are never searched beyond this * length. A higher limit improves compression ratio but degrades the * speed. */ uInt max_lazy_match; /* Attempt to find a better match only when the current match is strictly * smaller than this value. This mechanism is used only for compression * levels >= 4. */ # define max_insert_length max_lazy_match /* Insert new strings in the hash table only if the match length is not * greater than this length. This saves time but degrades compression. * max_insert_length is used only for compression levels <= 3. */ int level; /* compression level (1..9) */ int strategy; /* favor or force Huffman coding*/ uInt good_match; /* Use a faster search when the previous match is longer than this */ int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ /* Didn't use ct_data typedef below to suppress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ struct tree_desc_s l_desc; /* desc. for literal tree */ struct tree_desc_s d_desc; /* desc. for distance tree */ struct tree_desc_s bl_desc; /* desc. for bit length tree */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ int heap_len; /* number of elements in the heap */ int heap_max; /* element of largest frequency */ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. * The same heap array is used to build all trees. */ uch depth[2*L_CODES+1]; /* Depth of each subtree used as tie breaker for trees of equal frequency */ #ifdef LIT_MEM # define LIT_BUFS 5 ushf *d_buf; /* buffer for distances */ uchf *l_buf; /* buffer for literals/lengths */ #else # define LIT_BUFS 4 uchf *sym_buf; /* buffer for distances and literals/lengths */ #endif uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for * limiting lit_bufsize to 64K: * - frequencies can be kept in 16 bit counters * - if compression is not successful for the first block, all input * data is still in the window so we can still emit a stored block even * when input comes from standard input. (This can also be done for * all blocks if lit_bufsize is not greater than 32K.) * - if compression is not successful for a file smaller than 64K, we can * even emit a stored file instead of a stored block (saving 5 bytes). * This is applicable only for zip (not gzip or zlib). * - creating new Huffman trees less frequently may not provide fast * adaptation to changes in the input data statistics. (Take for * example a binary file with poorly compressible code followed by * a highly compressible string table.) Smaller buffer sizes give * fast adaptation but have of course the overhead of transmitting * trees more frequently. * - I can't count above 4 */ uInt sym_next; /* running index in symbol buffer */ uInt sym_end; /* symbol table full when sym_next reaches this */ ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ uInt matches; /* number of string matches in current block */ uInt insert; /* bytes at end of window left to insert */ #ifdef ZLIB_DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif ush bi_buf; /* Output buffer. bits are inserted starting at the bottom (least * significant bits). */ int bi_valid; /* Number of valid bits in bi_buf. All bits above the last valid bit * are always zero. */ ulg high_water; /* High water mark offset in window for initialized bytes -- bytes above * this are set to zero in order to avoid memory check warnings when * longest match routines access bytes past the input. This is then * updated to the new high water mark. */ } FAR deflate_state; /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ #define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */ #define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) /* In order to simplify the code, particularly on 16 bit machines, match * distances are limited to MAX_DIST instead of WSIZE. */ #define WIN_INIT MAX_MATCH /* Number of bytes after end of data in window to initialize in order to avoid memory checker errors from longest match routines */ /* in trees.c */ void ZLIB_INTERNAL _tr_init(deflate_state *s); int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc); void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int last); void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s); void ZLIB_INTERNAL _tr_align(deflate_state *s); void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int last); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and * must not have side effects. _dist_code[256] and _dist_code[257] are never * used. */ #ifndef ZLIB_DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) extern uch ZLIB_INTERNAL _length_code[]; extern uch ZLIB_INTERNAL _dist_code[]; #else extern const uch ZLIB_INTERNAL _length_code[]; extern const uch ZLIB_INTERNAL _dist_code[]; #endif #ifdef LIT_MEM # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->d_buf[s->sym_next] = 0; \ s->l_buf[s->sym_next++] = cc; \ s->dyn_ltree[cc].Freq++; \ flush = (s->sym_next == s->sym_end); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (uch)(length); \ ush dist = (ush)(distance); \ s->d_buf[s->sym_next] = dist; \ s->l_buf[s->sym_next++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->sym_next == s->sym_end); \ } #else # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->sym_buf[s->sym_next++] = 0; \ s->sym_buf[s->sym_next++] = 0; \ s->sym_buf[s->sym_next++] = cc; \ s->dyn_ltree[cc].Freq++; \ flush = (s->sym_next == s->sym_end); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (uch)(length); \ ush dist = (ush)(distance); \ s->sym_buf[s->sym_next++] = (uch)dist; \ s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \ s->sym_buf[s->sym_next++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->sym_next == s->sym_end); \ } #endif #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ flush = _tr_tally(s, distance, length) #endif #endif /* DEFLATE_H */ fltk-1.4.3/zlib/trees.h0000644000175000017500000002043015004135251015037 0ustar albrechtalbrecht/* header created automatically with -DGEN_TREES_H */ local const ct_data static_ltree[L_CODES+2] = { {{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, {{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, {{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, {{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, {{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, {{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, {{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, {{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, {{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, {{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, {{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, {{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, {{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, {{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, {{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, {{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, {{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, {{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, {{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, {{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, {{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, {{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, {{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, {{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, {{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, {{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, {{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, {{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, {{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, {{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, {{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, {{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, {{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, {{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, {{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, {{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, {{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, {{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, {{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, {{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, {{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, {{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, {{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, {{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, {{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, {{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, {{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, {{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, {{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, {{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, {{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, {{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, {{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, {{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, {{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, {{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, {{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, {{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} }; local const ct_data static_dtree[D_CODES] = { {{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, {{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, {{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, {{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, {{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, {{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} }; const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 }; const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 }; local const int base_length[LENGTH_CODES] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 }; local const int base_dist[D_CODES] = { 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 }; fltk-1.4.3/zlib/inffixed.h0000644000175000017500000001427415004135251015522 0ustar albrechtalbrecht /* inffixed.h -- table for decoding fixed codes * Generated automatically by makefixed(). */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of this library and is subject to change. Applications should only use zlib.h. */ static const code lenfix[512] = { {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, {0,9,255} }; static const code distfix[32] = { {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, {22,5,193},{64,5,0} }; fltk-1.4.3/zlib/inffast.h0000644000175000017500000000064615004135251015356 0ustar albrechtalbrecht/* inffast.h -- header to use inffast.c * Copyright (C) 1995-2003, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start); fltk-1.4.3/zlib/crc32.h0000644000175000017500000220360515004135251014642 0ustar albrechtalbrecht/* crc32.h -- tables for rapid CRC calculation * Generated automatically by crc32.c */ local const z_crc_t FAR crc_table[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; #ifdef W #if W == 8 local const z_word_t FAR crc_big_table[] = { 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, 0x8def022d00000000}; #else /* W == 4 */ local const z_word_t FAR crc_big_table[] = { 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, 0x8def022d}; #endif #if N == 1 #if W == 8 local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, 0x264b06e6}, {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, 0x92364a30}, {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, 0xe4c4abcc}, {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, 0xca64c78c}, {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1}, {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed}, {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72}, {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, 0x8def022d00000000}, {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000, 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000, 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000, 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000, 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000, 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000, 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000, 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000, 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000, 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000, 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000, 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000, 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000, 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000, 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000, 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000, 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000, 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000, 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000, 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000, 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000, 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000, 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000, 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000, 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000, 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000, 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000, 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000, 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000, 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000, 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000, 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000, 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000, 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000, 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000, 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000, 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000, 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000, 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000, 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000, 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000, 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000, 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000, 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000, 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000, 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000, 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000, 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000, 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000, 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000, 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000, 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000, 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000, 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000, 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000, 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000, 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000, 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000, 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000, 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000, 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000, 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000, 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000, 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000, 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000, 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000, 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000, 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000, 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000, 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000, 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000, 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000, 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000, 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000, 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000, 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000, 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000, 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000, 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000, 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000, 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000, 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000, 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000, 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000, 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000, 0x72fd249300000000}, {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000, 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000, 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000, 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000, 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000, 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000, 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000, 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000, 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000, 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000, 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000, 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000, 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000, 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000, 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000, 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000, 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000, 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000, 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000, 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000, 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000, 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000, 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000, 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000, 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000, 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000, 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000, 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000, 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000, 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000, 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000, 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000, 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000, 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000, 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000, 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000, 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000, 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000, 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000, 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000, 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000, 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000, 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000, 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000, 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000, 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000, 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000, 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000, 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000, 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000, 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000, 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000, 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000, 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000, 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000, 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000, 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000, 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000, 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000, 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000, 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000, 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000, 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000, 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000, 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000, 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000, 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000, 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000, 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000, 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000, 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000, 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000, 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000, 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000, 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000, 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000, 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000, 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000, 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000, 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000, 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000, 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000, 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000, 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000, 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000, 0xed3498be00000000}, {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000, 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000, 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000, 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000, 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000, 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000, 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000, 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000, 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000, 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000, 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000, 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000, 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000, 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000, 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000, 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000, 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000, 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000, 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000, 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000, 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000, 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000, 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000, 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000, 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000, 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000, 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000, 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000, 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000, 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000, 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000, 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000, 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000, 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000, 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000, 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000, 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000, 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000, 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000, 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000, 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000, 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000, 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000, 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000, 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000, 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000, 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000, 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000, 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000, 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000, 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000, 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000, 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000, 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000, 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000, 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000, 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000, 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000, 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000, 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000, 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000, 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000, 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000, 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000, 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000, 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000, 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000, 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000, 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000, 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000, 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000, 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000, 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000, 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000, 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000, 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000, 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000, 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000, 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000, 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000, 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000, 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000, 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000, 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000, 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000, 0xf10605de00000000}, {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000, 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000, 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000, 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000, 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000, 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000, 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000, 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000, 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000, 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000, 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000, 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000, 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000, 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000, 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000, 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000, 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000, 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000, 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000, 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000, 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000, 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000, 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000, 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000, 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000, 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000, 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000, 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000, 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000, 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000, 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000, 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000, 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000, 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000, 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000, 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000, 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000, 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000, 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000, 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000, 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000, 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000, 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000, 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000, 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000, 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000, 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000, 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000, 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000, 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000, 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000, 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000, 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000, 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000, 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000, 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000, 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000, 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000, 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000, 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000, 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000, 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000, 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000, 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000, 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000, 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000, 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000, 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000, 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000, 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000, 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000, 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000, 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000, 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000, 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000, 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000, 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000, 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000, 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000, 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000, 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000, 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000, 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000, 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000, 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000, 0x8cc764ca00000000}, {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000, 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000, 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000, 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000, 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000, 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000, 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000, 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000, 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000, 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000, 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000, 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000, 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000, 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000, 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000, 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000, 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000, 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000, 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000, 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000, 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000, 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000, 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000, 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000, 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000, 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000, 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000, 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000, 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000, 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000, 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000, 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000, 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000, 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000, 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000, 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000, 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000, 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000, 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000, 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000, 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000, 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000, 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000, 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000, 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000, 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000, 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000, 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000, 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000, 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000, 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000, 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000, 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000, 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000, 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000, 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000, 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000, 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000, 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000, 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000, 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000, 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000, 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000, 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000, 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000, 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000, 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000, 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000, 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000, 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000, 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000, 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000, 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000, 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000, 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000, 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000, 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000, 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000, 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000, 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000, 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000, 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000, 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000, 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000, 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000, 0xccabc4e400000000}, {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000, 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000, 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000, 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000, 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000, 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000, 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000, 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000, 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000, 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000, 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000, 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000, 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000, 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000, 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000, 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000, 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000, 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000, 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000, 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000, 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000, 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000, 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000, 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000, 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000, 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000, 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000, 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000, 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000, 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000, 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000, 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000, 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000, 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000, 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000, 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000, 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000, 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000, 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000, 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000, 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000, 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000, 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000, 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000, 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000, 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000, 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000, 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000, 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000, 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000, 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000, 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000, 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000, 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000, 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000, 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000, 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000, 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000, 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000, 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000, 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000, 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000, 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000, 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000, 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000, 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000, 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000, 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000, 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000, 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000, 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000, 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000, 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000, 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000, 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000, 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000, 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000, 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000, 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000, 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000, 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000, 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000, 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000, 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000, 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000, 0x304a369200000000}, {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000, 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000, 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000, 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000, 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000, 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000, 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000, 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000, 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000, 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000, 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000, 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000, 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000, 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000, 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000, 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000, 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000, 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000, 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000, 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000, 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000, 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000, 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000, 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000, 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000, 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000, 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000, 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000, 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000, 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000, 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000, 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000, 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000, 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000, 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000, 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000, 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000, 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000, 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000, 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000, 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000, 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000, 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000, 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000, 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000, 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000, 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000, 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000, 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000, 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000, 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000, 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000, 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000, 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000, 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000, 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000, 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000, 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000, 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000, 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000, 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000, 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000, 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000, 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000, 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000, 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000, 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000, 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000, 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000, 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000, 0x6171384400000000, 0xff71928800000000, 0xe678578200000000, 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000, 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000, 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000, 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000, 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000, 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000, 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000, 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000, 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000, 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000, 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000, 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000, 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000, 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000, 0xe6064b2600000000}}; #else /* W == 4 */ local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1}, {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed}, {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72}, {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, 0x8def022d}, {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64, 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1, 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e, 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61, 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82, 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff, 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7, 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da, 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139, 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6, 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89, 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c, 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0, 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d, 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a, 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177, 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de, 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b, 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824, 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e, 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad, 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0, 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d, 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60, 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83, 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822, 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d, 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8, 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171, 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c, 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b, 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6, 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca, 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f, 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430, 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf, 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c, 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51, 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9, 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84, 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67, 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398, 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7, 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62, 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e, 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923, 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4, 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9, 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070, 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5, 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a, 0x72fd2493}, {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907, 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f, 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a, 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e, 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512, 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14, 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b, 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d, 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731, 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925, 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620, 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28, 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70, 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176, 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d, 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b, 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b, 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63, 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266, 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a, 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446, 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40, 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557, 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51, 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d, 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0, 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5, 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed, 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd, 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb, 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0, 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6, 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de, 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6, 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3, 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7, 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb, 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd, 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92, 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094, 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598, 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c, 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489, 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81, 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9, 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af, 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4, 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2, 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2, 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba, 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf, 0xed3498be}, {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f, 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d, 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0, 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42, 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95, 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2, 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a, 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d, 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea, 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748, 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5, 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27, 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b, 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac, 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4, 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3, 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44, 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6, 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b, 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329, 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe, 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9, 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1, 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6, 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921, 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555, 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8, 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a, 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd, 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a, 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2, 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5, 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2, 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330, 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad, 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f, 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8, 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef, 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc, 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb, 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c, 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e, 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03, 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1, 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6, 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1, 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9, 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e, 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409, 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb, 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966, 0xf10605de}}; #endif #endif #if N == 2 #if W == 8 local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, 0x0d7139d7}, {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, 0x1c53e98a}, {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, 0x3f88e851}, {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, 0x3dee8ca6}, {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, 0x36197165}, {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, 0x1a3b93aa}, {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, 0xe147d714}, {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, 0x494f0c4b}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000, 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000, 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000, 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000, 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000, 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000, 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000, 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000, 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000, 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000, 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000, 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000, 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000, 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000, 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000, 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000, 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000, 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000, 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000, 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000, 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000, 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000, 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000, 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000, 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000, 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000, 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000, 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000, 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000, 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000, 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000, 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000, 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000, 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000, 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000, 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000, 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000, 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000, 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000, 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000, 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000, 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000, 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000, 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000, 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000, 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000, 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000, 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000, 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000, 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000, 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000, 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000, 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000, 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000, 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000, 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000, 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000, 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000, 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000, 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000, 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000, 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000, 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000, 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000, 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000, 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000, 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000, 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000, 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000, 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000, 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000, 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000, 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000, 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000, 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000, 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000, 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000, 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000, 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000, 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000, 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000, 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000, 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000, 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000, 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000, 0x4b0c4f4900000000}, {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000, 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000, 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000, 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000, 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000, 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000, 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000, 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000, 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000, 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000, 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000, 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000, 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000, 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000, 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000, 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000, 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000, 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000, 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000, 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000, 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000, 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000, 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000, 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000, 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000, 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000, 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000, 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000, 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000, 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000, 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000, 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000, 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000, 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000, 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000, 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000, 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000, 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000, 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000, 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000, 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000, 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000, 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000, 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000, 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000, 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000, 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000, 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000, 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000, 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000, 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000, 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000, 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000, 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000, 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000, 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000, 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000, 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000, 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000, 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000, 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000, 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000, 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000, 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000, 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000, 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000, 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000, 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000, 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000, 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000, 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000, 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000, 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000, 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000, 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000, 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000, 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000, 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000, 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000, 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000, 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000, 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000, 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000, 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000, 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000, 0x14d747e100000000}, {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000, 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000, 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000, 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000, 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000, 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000, 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000, 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000, 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000, 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000, 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000, 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000, 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000, 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000, 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000, 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000, 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000, 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000, 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000, 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000, 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000, 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000, 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000, 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000, 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000, 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000, 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000, 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000, 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000, 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000, 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000, 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000, 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000, 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000, 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000, 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000, 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000, 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000, 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000, 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000, 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000, 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000, 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000, 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000, 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000, 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000, 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000, 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000, 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000, 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000, 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000, 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000, 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000, 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000, 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000, 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000, 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000, 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000, 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000, 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000, 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000, 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000, 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000, 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000, 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000, 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000, 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000, 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000, 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000, 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000, 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000, 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000, 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000, 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000, 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000, 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000, 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000, 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000, 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000, 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000, 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000, 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000, 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000, 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000, 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000, 0xaa933b1a00000000}, {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000, 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000, 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000, 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000, 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000, 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000, 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000, 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000, 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000, 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000, 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000, 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000, 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000, 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000, 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000, 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000, 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000, 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000, 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000, 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000, 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000, 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000, 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000, 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000, 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000, 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000, 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000, 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000, 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000, 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000, 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000, 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000, 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000, 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000, 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000, 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000, 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000, 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000, 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000, 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000, 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000, 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000, 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000, 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000, 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000, 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000, 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000, 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000, 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000, 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000, 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000, 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000, 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000, 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000, 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000, 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000, 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000, 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000, 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000, 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000, 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000, 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000, 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000, 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000, 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000, 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000, 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000, 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000, 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000, 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000, 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000, 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000, 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000, 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000, 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000, 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000, 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000, 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000, 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000, 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000, 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000, 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000, 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000, 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000, 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000, 0x6571193600000000}, {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000, 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000, 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000, 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000, 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000, 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000, 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000, 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000, 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000, 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000, 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000, 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000, 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000, 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000, 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000, 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000, 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000, 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000, 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000, 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000, 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000, 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000, 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000, 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000, 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000, 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000, 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000, 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000, 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000, 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000, 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000, 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000, 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000, 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000, 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000, 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000, 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000, 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000, 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000, 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000, 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000, 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000, 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000, 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000, 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000, 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000, 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000, 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000, 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000, 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000, 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000, 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000, 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000, 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000, 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000, 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000, 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000, 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000, 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000, 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000, 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000, 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000, 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000, 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000, 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000, 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000, 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000, 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000, 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000, 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000, 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000, 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000, 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000, 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000, 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000, 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000, 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000, 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000, 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000, 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000, 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000, 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000, 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000, 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000, 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000, 0xa68cee3d00000000}, {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000, 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000, 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000, 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000, 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000, 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000, 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000, 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000, 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000, 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000, 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000, 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000, 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000, 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000, 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000, 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000, 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000, 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000, 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000, 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000, 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000, 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000, 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000, 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000, 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000, 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000, 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000, 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000, 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000, 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000, 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000, 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000, 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000, 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000, 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000, 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000, 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000, 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000, 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000, 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000, 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000, 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000, 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000, 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000, 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000, 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000, 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000, 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000, 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000, 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000, 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000, 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000, 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000, 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000, 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000, 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000, 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000, 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000, 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000, 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000, 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000, 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000, 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000, 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000, 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000, 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000, 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000, 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000, 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000, 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000, 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000, 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000, 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000, 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000, 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000, 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000, 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000, 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000, 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000, 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000, 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000, 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000, 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000, 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000, 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000, 0x51e8883f00000000}, {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000, 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000, 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000, 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000, 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000, 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000, 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000, 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000, 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000, 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000, 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000, 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000, 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000, 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000, 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000, 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000, 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000, 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000, 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000, 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000, 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000, 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000, 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000, 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000, 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000, 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000, 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000, 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000, 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000, 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000, 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000, 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000, 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000, 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000, 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000, 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000, 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000, 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000, 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000, 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000, 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000, 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000, 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000, 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000, 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000, 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000, 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000, 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000, 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000, 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000, 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000, 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000, 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000, 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000, 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000, 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000, 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000, 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000, 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000, 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000, 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000, 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000, 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000, 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000, 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000, 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000, 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000, 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000, 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000, 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000, 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000, 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000, 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000, 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000, 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000, 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000, 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000, 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000, 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000, 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000, 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000, 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000, 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000, 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000, 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000, 0x8ae9531c00000000}, {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000, 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000, 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000, 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000, 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000, 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000, 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000, 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000, 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000, 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000, 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000, 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000, 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000, 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000, 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000, 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000, 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000, 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000, 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000, 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000, 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000, 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000, 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000, 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000, 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000, 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000, 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000, 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000, 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000, 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000, 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000, 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000, 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000, 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000, 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000, 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000, 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000, 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000, 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000, 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000, 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000, 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000, 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000, 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000, 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000, 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000, 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000, 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000, 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000, 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000, 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000, 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000, 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000, 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000, 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000, 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000, 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000, 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000, 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000, 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000, 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000, 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000, 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000, 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000, 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000, 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000, 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000, 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000, 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000, 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000, 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000, 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000, 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000, 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000, 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000, 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000, 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000, 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000, 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000, 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000, 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000, 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000, 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000, 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000, 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000, 0xd739710d00000000}}; #else /* W == 4 */ local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, 0x264b06e6}, {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, 0x92364a30}, {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, 0xe4c4abcc}, {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, 0xca64c78c}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5, 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d, 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf, 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027, 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050, 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098, 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb, 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173, 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104, 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c, 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e, 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6, 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358, 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390, 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312, 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da, 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd, 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335, 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387, 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de, 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9, 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261, 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283, 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b, 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c, 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c, 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e, 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6, 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1, 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619, 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b, 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653, 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785, 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d, 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf, 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757, 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720, 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8, 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593, 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b, 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c, 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4, 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506, 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe, 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428, 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0, 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462, 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa, 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd, 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445, 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7, 0x8cc764ca}, {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b, 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27, 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a, 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285, 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef, 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf, 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a, 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a, 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70, 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf, 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2, 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e, 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f, 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f, 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae, 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe, 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97, 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b, 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436, 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e, 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4, 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4, 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46, 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716, 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c, 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5, 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8, 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774, 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d, 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d, 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc, 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec, 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82, 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e, 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623, 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c, 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6, 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6, 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c, 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c, 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66, 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9, 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4, 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978, 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416, 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946, 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7, 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7, 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e, 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32, 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f, 0xccabc4e4}, {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4, 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895, 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50, 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656, 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154, 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906, 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258, 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a, 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08, 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e, 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb, 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa, 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44, 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316, 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0, 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2, 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7, 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6, 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73, 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba, 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8, 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea, 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b, 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29, 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b, 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e, 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb, 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a, 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef, 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd, 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b, 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019, 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3, 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2, 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417, 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11, 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13, 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241, 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b, 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09, 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b, 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d, 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8, 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9, 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003, 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851, 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7, 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5, 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190, 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1, 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134, 0x304a3692}, {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84, 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f, 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15, 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2, 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf, 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7, 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb, 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3, 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae, 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749, 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243, 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8, 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29, 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61, 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8, 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0, 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1, 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a, 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40, 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e, 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03, 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b, 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee, 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6, 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb, 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f, 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495, 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e, 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f, 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067, 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be, 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6, 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e, 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5, 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf, 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958, 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305, 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d, 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338, 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370, 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d, 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca, 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0, 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b, 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083, 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb, 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012, 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a, 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b, 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0, 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea, 0xe6064b26}}; #endif #endif #if N == 3 #if W == 8 local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, 0x09cd8551}, {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, 0x7bc97a0c}, {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, 0x7851a2ca}, {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, 0x566b6848}, {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, 0xd8ac6b35}, {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, 0xa140efa8}, {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, 0x917cd6a1}, {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, 0x18ba364e}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000, 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000, 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000, 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000, 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000, 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000, 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000, 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000, 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000, 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000, 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000, 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000, 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000, 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000, 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000, 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000, 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000, 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000, 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000, 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000, 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000, 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000, 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000, 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000, 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000, 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000, 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000, 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000, 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000, 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000, 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000, 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000, 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000, 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000, 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000, 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000, 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000, 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000, 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000, 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000, 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000, 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000, 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000, 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000, 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000, 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000, 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000, 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000, 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000, 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000, 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000, 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000, 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000, 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000, 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000, 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000, 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000, 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000, 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000, 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000, 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000, 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000, 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000, 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000, 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000, 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000, 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000, 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000, 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000, 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000, 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000, 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000, 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000, 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000, 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000, 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000, 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000, 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000, 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000, 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000, 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000, 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000, 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000, 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000, 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000, 0x4e36ba1800000000}, {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000, 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000, 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000, 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000, 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000, 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000, 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000, 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000, 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000, 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000, 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000, 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000, 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000, 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000, 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000, 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000, 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000, 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000, 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000, 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000, 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000, 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000, 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000, 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000, 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000, 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000, 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000, 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000, 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000, 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000, 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000, 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000, 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000, 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000, 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000, 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000, 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000, 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000, 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000, 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000, 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000, 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000, 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000, 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000, 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000, 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000, 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000, 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000, 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000, 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000, 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000, 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000, 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000, 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000, 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000, 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000, 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000, 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000, 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000, 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000, 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000, 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000, 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000, 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000, 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000, 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000, 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000, 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000, 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000, 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000, 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000, 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000, 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000, 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000, 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000, 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000, 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000, 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000, 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000, 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000, 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000, 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000, 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000, 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000, 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000, 0xa1d67c9100000000}, {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000, 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000, 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000, 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000, 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000, 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000, 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000, 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000, 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000, 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000, 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000, 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000, 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000, 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000, 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000, 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000, 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000, 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000, 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000, 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000, 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000, 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000, 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000, 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000, 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000, 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000, 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000, 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000, 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000, 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000, 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000, 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000, 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000, 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000, 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000, 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000, 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000, 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000, 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000, 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000, 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000, 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000, 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000, 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000, 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000, 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000, 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000, 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000, 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000, 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000, 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000, 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000, 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000, 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000, 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000, 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000, 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000, 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000, 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000, 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000, 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000, 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000, 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000, 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000, 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000, 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000, 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000, 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000, 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000, 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000, 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000, 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000, 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000, 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000, 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000, 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000, 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000, 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000, 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000, 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000, 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000, 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000, 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000, 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000, 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000, 0xa8ef40a100000000}, {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000, 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000, 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000, 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000, 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000, 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000, 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000, 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000, 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000, 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000, 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000, 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000, 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000, 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000, 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000, 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000, 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000, 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000, 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000, 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000, 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000, 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000, 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000, 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000, 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000, 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000, 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000, 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000, 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000, 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000, 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000, 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000, 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000, 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000, 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000, 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000, 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000, 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000, 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000, 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000, 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000, 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000, 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000, 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000, 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000, 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000, 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000, 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000, 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000, 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000, 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000, 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000, 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000, 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000, 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000, 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000, 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000, 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000, 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000, 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000, 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000, 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000, 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000, 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000, 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000, 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000, 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000, 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000, 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000, 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000, 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000, 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000, 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000, 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000, 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000, 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000, 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000, 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000, 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000, 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000, 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000, 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000, 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000, 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000, 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000, 0x356bacd800000000}, {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000, 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000, 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000, 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000, 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000, 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000, 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000, 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000, 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000, 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000, 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000, 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000, 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000, 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000, 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000, 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000, 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000, 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000, 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000, 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000, 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000, 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000, 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000, 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000, 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000, 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000, 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000, 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000, 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000, 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000, 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000, 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000, 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000, 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000, 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000, 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000, 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000, 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000, 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000, 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000, 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000, 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000, 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000, 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000, 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000, 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000, 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000, 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000, 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000, 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000, 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000, 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000, 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000, 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000, 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000, 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000, 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000, 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000, 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000, 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000, 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000, 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000, 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000, 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000, 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000, 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000, 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000, 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000, 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000, 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000, 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000, 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000, 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000, 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000, 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000, 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000, 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000, 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000, 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000, 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000, 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000, 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000, 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000, 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000, 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000, 0x48686b5600000000}, {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000, 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000, 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000, 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000, 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000, 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000, 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000, 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000, 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000, 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000, 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000, 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000, 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000, 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000, 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000, 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000, 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000, 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000, 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000, 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000, 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000, 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000, 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000, 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000, 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000, 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000, 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000, 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000, 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000, 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000, 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000, 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000, 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000, 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000, 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000, 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000, 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000, 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000, 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000, 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000, 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000, 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000, 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000, 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000, 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000, 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000, 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000, 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000, 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000, 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000, 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000, 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000, 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000, 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000, 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000, 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000, 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000, 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000, 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000, 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000, 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000, 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000, 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000, 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000, 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000, 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000, 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000, 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000, 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000, 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000, 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000, 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000, 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000, 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000, 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000, 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000, 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000, 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000, 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000, 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000, 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000, 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000, 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000, 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000, 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000, 0xcaa2517800000000}, {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000, 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000, 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000, 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000, 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000, 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000, 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000, 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000, 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000, 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000, 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000, 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000, 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000, 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000, 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000, 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000, 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000, 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000, 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000, 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000, 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000, 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000, 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000, 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000, 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000, 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000, 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000, 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000, 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000, 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000, 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000, 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000, 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000, 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000, 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000, 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000, 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000, 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000, 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000, 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000, 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000, 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000, 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000, 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000, 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000, 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000, 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000, 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000, 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000, 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000, 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000, 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000, 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000, 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000, 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000, 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000, 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000, 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000, 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000, 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000, 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000, 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000, 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000, 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000, 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000, 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000, 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000, 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000, 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000, 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000, 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000, 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000, 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000, 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000, 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000, 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000, 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000, 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000, 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000, 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000, 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000, 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000, 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000, 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000, 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000, 0x0c7ac97b00000000}, {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000, 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000, 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000, 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000, 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000, 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000, 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000, 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000, 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000, 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000, 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000, 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000, 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000, 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000, 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000, 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000, 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000, 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000, 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000, 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000, 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000, 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000, 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000, 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000, 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000, 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000, 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000, 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000, 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000, 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000, 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000, 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000, 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000, 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000, 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000, 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000, 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000, 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000, 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000, 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000, 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000, 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000, 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000, 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000, 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000, 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000, 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000, 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000, 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000, 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000, 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000, 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000, 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000, 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000, 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000, 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000, 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000, 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000, 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000, 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000, 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000, 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000, 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000, 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000, 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000, 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000, 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000, 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000, 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000, 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000, 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000, 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000, 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000, 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000, 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000, 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000, 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000, 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000, 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000, 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000, 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000, 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000, 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000, 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000, 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000, 0x5185cd0900000000}}; #else /* W == 4 */ local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, 0x36197165}, {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, 0x1a3b93aa}, {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, 0xe147d714}, {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, 0x494f0c4b}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d, 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac, 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8, 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95, 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817, 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d, 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac, 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6, 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564, 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39, 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d, 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac, 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de, 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594, 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b, 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01, 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f, 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de, 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba, 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65, 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7, 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad, 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de, 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294, 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716, 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71, 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15, 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4, 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca, 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280, 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f, 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15, 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9, 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748, 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c, 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971, 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3, 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9, 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196, 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc, 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e, 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03, 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67, 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296, 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a, 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170, 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af, 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5, 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb, 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a, 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e, 0x4b0c4f49}, {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09, 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc, 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e, 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc, 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934, 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2, 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b, 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad, 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155, 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187, 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65, 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390, 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e, 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378, 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889, 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f, 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0, 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145, 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7, 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a, 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2, 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924, 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2, 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514, 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec, 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709, 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb, 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e, 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1, 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227, 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6, 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030, 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0, 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55, 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7, 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165, 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d, 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b, 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c, 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a, 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362, 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0, 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52, 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7, 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237, 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1, 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020, 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6, 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719, 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec, 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e, 0x14d747e1}, {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0, 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b, 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652, 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437, 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514, 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265, 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de, 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af, 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c, 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9, 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0, 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b, 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6, 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7, 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734, 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045, 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8, 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303, 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a, 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9, 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea, 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b, 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6, 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7, 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4, 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6, 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f, 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054, 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9, 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8, 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b, 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a, 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441, 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a, 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3, 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6, 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5, 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94, 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9, 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288, 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab, 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce, 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7, 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c, 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527, 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256, 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5, 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4, 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39, 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2, 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db, 0xaa933b1a}, {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603, 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d, 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9, 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b, 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a, 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792, 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4, 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c, 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d, 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f, 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb, 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65, 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330, 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8, 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da, 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742, 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f, 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1, 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5, 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f, 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e, 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6, 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8, 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250, 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021, 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb, 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f, 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511, 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c, 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4, 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886, 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e, 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b, 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5, 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791, 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003, 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272, 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea, 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc, 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24, 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55, 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7, 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3, 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d, 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548, 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0, 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2, 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a, 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47, 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9, 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad, 0x65711936}}; #endif #endif #if N == 4 #if W == 8 local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a, 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe, 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b, 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656, 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd, 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d, 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7, 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47, 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac, 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691, 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404, 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0, 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4, 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424, 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5, 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65, 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67, 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3, 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626, 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9, 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222, 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2, 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a, 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a, 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1, 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2, 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077, 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3, 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1, 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621, 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0, 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60, 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0, 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64, 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1, 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc, 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027, 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7, 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9, 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79, 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292, 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af, 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a, 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee, 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e, 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe, 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f, 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff, 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd, 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29, 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc, 0xe3c45916}, {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344, 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59, 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e, 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463, 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98, 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d, 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3, 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656, 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad, 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0, 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397, 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a, 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2, 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357, 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8, 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d, 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696, 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b, 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc, 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0, 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b, 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be, 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811, 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384, 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f, 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955, 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362, 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f, 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94, 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701, 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe, 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b, 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1, 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc, 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b, 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986, 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d, 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8, 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4, 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371, 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a, 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87, 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0, 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad, 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527, 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2, 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d, 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998, 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73, 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e, 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59, 0xa7520488}, {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20, 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09, 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431, 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a, 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203, 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b, 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14, 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c, 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25, 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e, 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36, 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f, 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649, 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961, 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58, 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170, 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b, 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742, 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a, 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55, 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c, 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64, 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f, 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77, 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e, 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a, 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2, 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b, 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090, 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8, 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881, 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9, 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6, 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f, 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7, 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c, 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695, 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd, 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb, 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3, 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa, 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1, 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9, 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0, 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df, 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7, 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace, 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6, 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd, 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4, 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec, 0x3522e9e4}, {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1, 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86, 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b, 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669, 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7, 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352, 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03, 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6, 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38, 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a, 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7, 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80, 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7, 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522, 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d, 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8, 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103, 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54, 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9, 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0, 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e, 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb, 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1, 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624, 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea, 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a, 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37, 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360, 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab, 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e, 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741, 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4, 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334, 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63, 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de, 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c, 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942, 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7, 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131, 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4, 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a, 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758, 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5, 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2, 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32, 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7, 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8, 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d, 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6, 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1, 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c, 0x97411e28}, {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474, 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5, 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6, 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7, 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938, 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051, 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a, 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3, 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c, 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d, 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e, 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf, 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740, 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29, 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592, 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb, 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4, 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365, 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036, 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7, 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08, 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561, 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a, 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663, 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac, 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d, 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce, 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f, 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50, 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639, 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82, 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb, 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954, 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5, 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86, 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7, 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418, 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71, 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa, 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93, 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c, 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d, 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e, 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df, 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60, 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309, 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2, 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db, 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4, 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45, 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16, 0x93c7a00b}, {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45, 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb, 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d, 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696, 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf, 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb, 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028, 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c, 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65, 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be, 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038, 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6, 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15, 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11, 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d, 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19, 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05, 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b, 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d, 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c, 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35, 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31, 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068, 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c, 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25, 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a, 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac, 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22, 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e, 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a, 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36, 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32, 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84, 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a, 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c, 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057, 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e, 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a, 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc, 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8, 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1, 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a, 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec, 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62, 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4, 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0, 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc, 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8, 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4, 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a, 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc, 0xce5f968d}, {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de, 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b, 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d, 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680, 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4, 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d, 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde, 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97, 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3, 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e, 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678, 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d, 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723, 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a, 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0, 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9, 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85, 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770, 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56, 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a, 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e, 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67, 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785, 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc, 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788, 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90, 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6, 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843, 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f, 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336, 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac, 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5, 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68, 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d, 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb, 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36, 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72, 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b, 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b, 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402, 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446, 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb, 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed, 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418, 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95, 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc, 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946, 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f, 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233, 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6, 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0, 0x3e721277}, {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb, 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9, 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11, 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d, 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9, 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c, 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881, 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274, 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790, 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc, 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514, 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56, 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9, 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c, 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13, 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6, 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c, 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e, 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386, 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376, 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692, 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67, 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416, 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3, 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07, 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd, 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15, 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457, 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd, 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28, 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337, 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2, 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594, 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6, 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e, 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52, 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6, 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143, 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17, 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2, 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306, 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a, 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182, 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0, 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496, 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63, 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c, 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89, 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903, 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041, 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9, 0x1c65ace7}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000, 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000, 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000, 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000, 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000, 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000, 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000, 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000, 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000, 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000, 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000, 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000, 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000, 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000, 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000, 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000, 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000, 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000, 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000, 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000, 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000, 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000, 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000, 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000, 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000, 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000, 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000, 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000, 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000, 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000, 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000, 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000, 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000, 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000, 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000, 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000, 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000, 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000, 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000, 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000, 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000, 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000, 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000, 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000, 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000, 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000, 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000, 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000, 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000, 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000, 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000, 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000, 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000, 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000, 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000, 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000, 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000, 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000, 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000, 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000, 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000, 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000, 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000, 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000, 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000, 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000, 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000, 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000, 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000, 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000, 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000, 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000, 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000, 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000, 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000, 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000, 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000, 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000, 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000, 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000, 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000, 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000, 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000, 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000, 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000, 0xe7ac651c00000000}, {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000, 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000, 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000, 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000, 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000, 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000, 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000, 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000, 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000, 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000, 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000, 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000, 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000, 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000, 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000, 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000, 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000, 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000, 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000, 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000, 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000, 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000, 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000, 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000, 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000, 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000, 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000, 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000, 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000, 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000, 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000, 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000, 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000, 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000, 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000, 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000, 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000, 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000, 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000, 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000, 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000, 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000, 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000, 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000, 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000, 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000, 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000, 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000, 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000, 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000, 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000, 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000, 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000, 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000, 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000, 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000, 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000, 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000, 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000, 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000, 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000, 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000, 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000, 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000, 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000, 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000, 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000, 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000, 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000, 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000, 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000, 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000, 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000, 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000, 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000, 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000, 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000, 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000, 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000, 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000, 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000, 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000, 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000, 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000, 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000, 0x7712723e00000000}, {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000, 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000, 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000, 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000, 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000, 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000, 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000, 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000, 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000, 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000, 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000, 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000, 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000, 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000, 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000, 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000, 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000, 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000, 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000, 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000, 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000, 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000, 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000, 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000, 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000, 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000, 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000, 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000, 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000, 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000, 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000, 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000, 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000, 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000, 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000, 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000, 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000, 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000, 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000, 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000, 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000, 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000, 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000, 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000, 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000, 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000, 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000, 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000, 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000, 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000, 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000, 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000, 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000, 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000, 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000, 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000, 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000, 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000, 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000, 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000, 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000, 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000, 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000, 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000, 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000, 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000, 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000, 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000, 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000, 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000, 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000, 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000, 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000, 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000, 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000, 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000, 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000, 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000, 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000, 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000, 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000, 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000, 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000, 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000, 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000, 0x8d965fce00000000}, {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000, 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000, 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000, 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000, 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000, 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000, 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000, 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000, 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000, 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000, 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000, 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000, 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000, 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000, 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000, 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000, 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000, 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000, 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000, 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000, 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000, 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000, 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000, 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000, 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000, 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000, 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000, 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000, 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000, 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000, 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000, 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000, 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000, 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000, 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000, 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000, 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000, 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000, 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000, 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000, 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000, 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000, 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000, 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000, 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000, 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000, 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000, 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000, 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000, 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000, 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000, 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000, 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000, 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000, 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000, 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000, 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000, 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000, 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000, 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000, 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000, 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000, 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000, 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000, 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000, 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000, 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000, 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000, 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000, 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000, 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000, 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000, 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000, 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000, 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000, 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000, 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000, 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000, 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000, 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000, 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000, 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000, 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000, 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000, 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000, 0x0ba0c79300000000}, {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000, 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000, 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000, 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000, 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000, 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000, 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000, 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000, 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000, 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000, 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000, 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000, 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000, 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000, 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000, 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000, 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000, 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000, 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000, 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000, 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000, 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000, 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000, 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000, 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000, 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000, 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000, 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000, 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000, 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000, 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000, 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000, 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000, 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000, 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000, 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000, 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000, 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000, 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000, 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000, 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000, 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000, 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000, 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000, 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000, 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000, 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000, 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000, 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000, 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000, 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000, 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000, 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000, 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000, 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000, 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000, 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000, 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000, 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000, 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000, 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000, 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000, 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000, 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000, 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000, 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000, 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000, 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000, 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000, 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000, 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000, 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000, 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000, 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000, 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000, 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000, 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000, 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000, 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000, 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000, 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000, 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000, 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000, 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000, 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000, 0x281e419700000000}, {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000, 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000, 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000, 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000, 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000, 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000, 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000, 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000, 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000, 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000, 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000, 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000, 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000, 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000, 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000, 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000, 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000, 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000, 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000, 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000, 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000, 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000, 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000, 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000, 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000, 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000, 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000, 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000, 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000, 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000, 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000, 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000, 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000, 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000, 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000, 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000, 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000, 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000, 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000, 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000, 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000, 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000, 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000, 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000, 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000, 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000, 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000, 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000, 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000, 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000, 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000, 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000, 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000, 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000, 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000, 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000, 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000, 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000, 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000, 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000, 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000, 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000, 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000, 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000, 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000, 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000, 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000, 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000, 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000, 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000, 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000, 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000, 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000, 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000, 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000, 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000, 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000, 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000, 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000, 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000, 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000, 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000, 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000, 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000, 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000, 0xe4e9223500000000}, {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000, 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000, 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000, 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000, 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000, 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000, 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000, 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000, 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000, 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000, 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000, 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000, 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000, 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000, 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000, 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000, 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000, 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000, 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000, 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000, 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000, 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000, 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000, 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000, 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000, 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000, 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000, 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000, 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000, 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000, 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000, 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000, 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000, 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000, 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000, 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000, 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000, 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000, 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000, 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000, 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000, 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000, 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000, 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000, 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000, 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000, 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000, 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000, 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000, 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000, 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000, 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000, 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000, 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000, 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000, 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000, 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000, 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000, 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000, 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000, 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000, 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000, 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000, 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000, 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000, 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000, 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000, 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000, 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000, 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000, 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000, 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000, 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000, 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000, 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000, 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000, 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000, 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000, 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000, 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000, 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000, 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000, 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000, 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000, 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000, 0x880452a700000000}, {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000, 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000, 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000, 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000, 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000, 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000, 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000, 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000, 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000, 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000, 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000, 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000, 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000, 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000, 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000, 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000, 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000, 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000, 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000, 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000, 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000, 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000, 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000, 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000, 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000, 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000, 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000, 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000, 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000, 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000, 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000, 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000, 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000, 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000, 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000, 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000, 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000, 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000, 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000, 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000, 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000, 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000, 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000, 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000, 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000, 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000, 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000, 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000, 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000, 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000, 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000, 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000, 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000, 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000, 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000, 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000, 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000, 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000, 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000, 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000, 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000, 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000, 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000, 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000, 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000, 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000, 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000, 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000, 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000, 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000, 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000, 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000, 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000, 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000, 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000, 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000, 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000, 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000, 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000, 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000, 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000, 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000, 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000, 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000, 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000, 0x1659c4e300000000}}; #else /* W == 4 */ local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, 0x0d7139d7}, {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, 0x1c53e98a}, {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, 0x3f88e851}, {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, 0x3dee8ca6}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0, 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587, 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa, 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09, 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee, 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3, 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3, 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce, 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429, 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda, 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7, 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0, 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd, 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0, 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287, 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a, 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9, 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e, 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3, 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3, 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054, 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49, 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da, 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7, 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20, 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d, 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00, 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347, 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14, 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209, 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e, 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33, 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3, 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194, 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9, 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a, 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd, 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0, 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d, 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460, 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87, 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674, 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509, 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e, 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae, 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3, 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694, 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989, 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da, 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d, 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0, 0xa68cee3d}, {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19, 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae, 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb, 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a, 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55, 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1, 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c, 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8, 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7, 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936, 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453, 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4, 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941, 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5, 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93, 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17, 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e, 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89, 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec, 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0, 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf, 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b, 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b, 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f, 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0, 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e, 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b, 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc, 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5, 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261, 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637, 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3, 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57, 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0, 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85, 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454, 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b, 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f, 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423, 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7, 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8, 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739, 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c, 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb, 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f, 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b, 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd, 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59, 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070, 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7, 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2, 0x51e8883f}, {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a, 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276, 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed, 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55, 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b, 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8, 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320, 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413, 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd, 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75, 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee, 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312, 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca, 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9, 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad, 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e, 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504, 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8, 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63, 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353, 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d, 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be, 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae, 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d, 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943, 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7, 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c, 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390, 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a, 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239, 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d, 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e, 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c, 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0, 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b, 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93, 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d, 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e, 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c, 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f, 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1, 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579, 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2, 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e, 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c, 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f, 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b, 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158, 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2, 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e, 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5, 0x8ae9531c}, {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4, 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd, 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220, 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf, 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495, 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def, 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90, 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea, 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0, 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f, 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2, 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab, 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e, 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754, 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda, 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0, 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c, 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215, 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8, 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910, 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a, 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30, 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658, 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22, 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478, 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2, 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f, 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606, 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba, 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0, 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e, 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034, 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f, 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996, 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b, 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84, 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de, 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4, 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5, 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f, 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5, 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a, 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7, 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce, 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65, 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f, 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91, 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb, 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57, 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e, 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3, 0xd739710d}}; #endif #endif #if N == 5 #if W == 8 local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df, 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8, 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef, 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376, 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201, 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399, 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372, 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea, 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d, 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004, 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353, 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334, 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a, 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2, 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a, 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2, 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b, 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c, 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b, 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f, 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338, 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0, 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6, 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e, 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319, 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3, 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4, 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783, 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a, 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492, 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a, 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2, 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496, 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1, 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6, 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f, 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548, 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0, 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741, 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9, 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae, 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437, 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760, 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707, 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433, 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab, 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703, 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b, 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412, 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475, 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722, 0xe9947565}, {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5, 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22, 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c, 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed, 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d, 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1, 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e, 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32, 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142, 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93, 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d, 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a, 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58, 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14, 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81, 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd, 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab, 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c, 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72, 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f, 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff, 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3, 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30, 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c, 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c, 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558, 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146, 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581, 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7, 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab, 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e, 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272, 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838, 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff, 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1, 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330, 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840, 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c, 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb, 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7, 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7, 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616, 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208, 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf, 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85, 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9, 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c, 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10, 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76, 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1, 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf, 0xf7d05006}, {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b, 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774, 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58, 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a, 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb, 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952, 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e, 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7, 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746, 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14, 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338, 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907, 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777, 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de, 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064, 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd, 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951, 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e, 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42, 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b, 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a, 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3, 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904, 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad, 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c, 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d, 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861, 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e, 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2, 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b, 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1, 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78, 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f, 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40, 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c, 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e, 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf, 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166, 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d, 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4, 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805, 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157, 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b, 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644, 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43, 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea, 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850, 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9, 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165, 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a, 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676, 0xb2075b94}, {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf, 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61, 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be, 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd, 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3, 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063, 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105, 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5, 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb, 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8, 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07, 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9, 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5, 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515, 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4, 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014, 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7, 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269, 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6, 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af, 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1, 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111, 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d, 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad, 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3, 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75, 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa, 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74, 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7, 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477, 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6, 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176, 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af, 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71, 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae, 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd, 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3, 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073, 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0, 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400, 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e, 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d, 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2, 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c, 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5, 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505, 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4, 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004, 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7, 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279, 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6, 0xba50bcb9}, {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897, 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb, 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2, 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2, 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372, 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70, 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92, 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190, 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40, 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430, 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759, 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75, 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2, 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0, 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7, 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5, 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39, 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215, 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c, 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5, 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625, 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27, 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c, 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e, 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee, 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71, 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18, 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134, 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8, 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba, 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd, 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff, 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a, 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6, 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf, 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf, 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f, 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d, 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d, 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f, 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af, 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df, 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6, 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a, 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef, 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed, 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa, 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8, 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624, 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08, 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861, 0x808abcf4}, {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2, 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd, 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76, 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52, 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e, 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124, 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147, 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d, 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31, 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15, 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae, 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1, 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d, 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307, 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9, 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3, 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084, 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb, 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850, 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2, 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe, 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94, 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261, 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b, 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917, 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53, 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8, 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787, 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0, 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba, 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404, 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e, 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af, 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0, 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b, 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f, 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543, 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129, 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627, 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d, 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51, 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75, 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce, 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1, 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760, 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a, 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4, 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde, 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089, 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6, 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d, 0xefdb3f95}, {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8, 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7, 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945, 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9, 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652, 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc, 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a, 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4, 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f, 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3, 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51, 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e, 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c, 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362, 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11, 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff, 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7, 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8, 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a, 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690, 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b, 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5, 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05, 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb, 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740, 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f, 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded, 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2, 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa, 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714, 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67, 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89, 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7, 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8, 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a, 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6, 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d, 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3, 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9, 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57, 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc, 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540, 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2, 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd, 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93, 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d, 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e, 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0, 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8, 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7, 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75, 0x0e2fbf43}, {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc, 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a, 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3, 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7, 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b, 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154, 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3, 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc, 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330, 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264, 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd, 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b, 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a, 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175, 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275, 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a, 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234, 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2, 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b, 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a, 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6, 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189, 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b, 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204, 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8, 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226, 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff, 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219, 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167, 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258, 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158, 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267, 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c, 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da, 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003, 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157, 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b, 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4, 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179, 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246, 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a, 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de, 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107, 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1, 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba, 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285, 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185, 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba, 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4, 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322, 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb, 0xf4377108}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000, 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000, 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000, 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000, 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000, 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000, 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000, 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000, 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000, 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000, 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000, 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000, 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000, 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000, 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000, 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000, 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000, 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000, 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000, 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000, 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000, 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000, 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000, 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000, 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000, 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000, 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000, 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000, 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000, 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000, 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000, 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000, 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000, 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000, 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000, 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000, 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000, 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000, 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000, 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000, 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000, 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000, 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000, 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000, 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000, 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000, 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000, 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000, 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000, 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000, 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000, 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000, 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000, 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000, 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000, 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000, 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000, 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000, 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000, 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000, 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000, 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000, 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000, 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000, 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000, 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000, 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000, 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000, 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000, 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000, 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000, 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000, 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000, 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000, 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000, 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000, 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000, 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000, 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000, 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000, 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000, 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000, 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000, 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000, 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000, 0x087137f400000000}, {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000, 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000, 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000, 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000, 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000, 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000, 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000, 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000, 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000, 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000, 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000, 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000, 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000, 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000, 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000, 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000, 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000, 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000, 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000, 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000, 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000, 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000, 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000, 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000, 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000, 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000, 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000, 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000, 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000, 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000, 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000, 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000, 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000, 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000, 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000, 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000, 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000, 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000, 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000, 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000, 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000, 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000, 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000, 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000, 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000, 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000, 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000, 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000, 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000, 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000, 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000, 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000, 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000, 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000, 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000, 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000, 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000, 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000, 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000, 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000, 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000, 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000, 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000, 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000, 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000, 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000, 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000, 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000, 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000, 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000, 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000, 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000, 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000, 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000, 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000, 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000, 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000, 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000, 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000, 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000, 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000, 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000, 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000, 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000, 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000, 0x43bf2f0e00000000}, {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000, 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000, 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000, 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000, 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000, 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000, 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000, 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000, 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000, 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000, 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000, 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000, 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000, 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000, 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000, 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000, 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000, 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000, 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000, 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000, 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000, 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000, 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000, 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000, 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000, 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000, 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000, 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000, 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000, 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000, 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000, 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000, 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000, 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000, 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000, 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000, 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000, 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000, 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000, 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000, 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000, 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000, 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000, 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000, 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000, 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000, 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000, 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000, 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000, 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000, 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000, 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000, 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000, 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000, 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000, 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000, 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000, 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000, 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000, 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000, 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000, 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000, 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000, 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000, 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000, 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000, 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000, 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000, 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000, 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000, 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000, 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000, 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000, 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000, 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000, 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000, 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000, 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000, 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000, 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000, 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000, 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000, 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000, 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000, 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000, 0x953fdbef00000000}, {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000, 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000, 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000, 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000, 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000, 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000, 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000, 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000, 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000, 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000, 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000, 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000, 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000, 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000, 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000, 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000, 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000, 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000, 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000, 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000, 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000, 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000, 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000, 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000, 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000, 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000, 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000, 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000, 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000, 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000, 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000, 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000, 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000, 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000, 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000, 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000, 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000, 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000, 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000, 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000, 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000, 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000, 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000, 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000, 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000, 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000, 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000, 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000, 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000, 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000, 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000, 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000, 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000, 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000, 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000, 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000, 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000, 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000, 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000, 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000, 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000, 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000, 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000, 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000, 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000, 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000, 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000, 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000, 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000, 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000, 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000, 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000, 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000, 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000, 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000, 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000, 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000, 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000, 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000, 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000, 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000, 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000, 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000, 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000, 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000, 0xf4bc8a8000000000}, {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000, 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000, 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000, 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000, 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000, 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000, 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000, 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000, 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000, 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000, 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000, 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000, 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000, 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000, 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000, 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000, 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000, 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000, 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000, 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000, 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000, 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000, 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000, 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000, 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000, 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000, 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000, 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000, 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000, 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000, 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000, 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000, 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000, 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000, 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000, 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000, 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000, 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000, 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000, 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000, 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000, 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000, 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000, 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000, 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000, 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000, 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000, 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000, 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000, 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000, 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000, 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000, 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000, 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000, 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000, 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000, 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000, 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000, 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000, 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000, 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000, 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000, 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000, 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000, 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000, 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000, 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000, 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000, 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000, 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000, 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000, 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000, 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000, 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000, 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000, 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000, 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000, 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000, 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000, 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000, 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000, 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000, 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000, 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000, 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000, 0xb9bc50ba00000000}, {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000, 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000, 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000, 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000, 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000, 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000, 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000, 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000, 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000, 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000, 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000, 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000, 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000, 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000, 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000, 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000, 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000, 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000, 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000, 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000, 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000, 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000, 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000, 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000, 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000, 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000, 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000, 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000, 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000, 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000, 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000, 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000, 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000, 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000, 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000, 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000, 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000, 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000, 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000, 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000, 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000, 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000, 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000, 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000, 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000, 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000, 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000, 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000, 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000, 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000, 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000, 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000, 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000, 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000, 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000, 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000, 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000, 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000, 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000, 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000, 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000, 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000, 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000, 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000, 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000, 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000, 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000, 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000, 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000, 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000, 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000, 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000, 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000, 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000, 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000, 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000, 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000, 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000, 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000, 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000, 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000, 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000, 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000, 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000, 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000, 0x945b07b200000000}, {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000, 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000, 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000, 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000, 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000, 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000, 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000, 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000, 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000, 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000, 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000, 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000, 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000, 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000, 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000, 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000, 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000, 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000, 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000, 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000, 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000, 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000, 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000, 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000, 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000, 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000, 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000, 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000, 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000, 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000, 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000, 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000, 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000, 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000, 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000, 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000, 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000, 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000, 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000, 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000, 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000, 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000, 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000, 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000, 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000, 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000, 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000, 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000, 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000, 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000, 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000, 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000, 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000, 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000, 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000, 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000, 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000, 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000, 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000, 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000, 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000, 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000, 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000, 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000, 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000, 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000, 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000, 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000, 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000, 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000, 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000, 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000, 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000, 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000, 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000, 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000, 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000, 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000, 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000, 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000, 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000, 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000, 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000, 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000, 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000, 0x0650d0f700000000}, {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000, 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000, 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000, 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000, 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000, 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000, 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000, 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000, 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000, 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000, 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000, 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000, 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000, 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000, 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000, 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000, 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000, 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000, 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000, 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000, 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000, 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000, 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000, 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000, 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000, 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000, 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000, 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000, 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000, 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000, 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000, 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000, 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000, 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000, 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000, 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000, 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000, 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000, 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000, 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000, 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000, 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000, 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000, 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000, 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000, 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000, 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000, 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000, 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000, 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000, 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000, 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000, 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000, 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000, 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000, 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000, 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000, 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000, 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000, 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000, 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000, 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000, 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000, 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000, 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000, 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000, 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000, 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000, 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000, 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000, 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000, 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000, 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000, 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000, 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000, 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000, 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000, 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000, 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000, 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000, 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000, 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000, 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000, 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000, 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000, 0x657594e900000000}}; #else /* W == 4 */ local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, 0xd8ac6b35}, {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, 0xa140efa8}, {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, 0x917cd6a1}, {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, 0x18ba364e}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873, 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661, 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441, 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44, 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1, 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05, 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa, 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e, 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb, 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be, 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e, 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c, 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d, 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9, 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f, 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b, 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39, 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b, 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b, 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20, 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595, 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61, 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0, 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644, 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1, 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d, 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d, 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f, 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad, 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359, 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f, 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b, 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7, 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5, 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5, 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0, 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65, 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091, 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633, 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7, 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272, 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77, 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57, 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145, 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9, 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d, 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb, 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f, 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad, 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf, 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f, 0x4e36ba18}, {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b, 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8, 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19, 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4, 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239, 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd, 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258, 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc, 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41, 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c, 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d, 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e, 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba, 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e, 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8, 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c, 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f, 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c, 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d, 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d, 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0, 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014, 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc, 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628, 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5, 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941, 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0, 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53, 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880, 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264, 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92, 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776, 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8, 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b, 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea, 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837, 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca, 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e, 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211, 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5, 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08, 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5, 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934, 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7, 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049, 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad, 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b, 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf, 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c, 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f, 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e, 0xa1d67c91}, {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9, 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de, 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94, 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0, 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a, 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924, 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052, 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c, 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6, 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2, 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8, 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f, 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d, 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273, 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30, 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e, 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7, 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980, 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca, 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8, 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62, 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c, 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c, 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032, 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798, 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d, 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07, 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630, 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389, 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7, 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4, 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca, 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55, 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662, 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828, 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c, 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6, 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98, 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3, 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d, 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037, 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913, 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759, 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e, 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1, 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf, 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c, 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2, 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b, 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c, 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276, 0xa8ef40a1}, {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e, 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8, 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819, 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f, 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d, 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756, 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0, 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb, 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9, 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f, 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e, 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8, 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835, 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e, 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62, 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749, 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b, 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d, 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc, 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80, 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2, 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599, 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05, 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e, 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c, 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e, 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef, 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359, 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b, 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0, 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc, 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7, 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f, 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189, 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568, 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e, 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c, 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27, 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794, 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf, 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d, 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db, 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a, 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c, 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544, 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f, 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013, 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38, 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea, 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c, 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd, 0x356bacd8}}; #endif #endif #if N == 6 #if W == 8 local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370, 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d, 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69, 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426, 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3, 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f, 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c, 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490, 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155, 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a, 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e, 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603, 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349, 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5, 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50, 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc, 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b, 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76, 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862, 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9, 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c, 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0, 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937, 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b, 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e, 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e, 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a, 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357, 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0, 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c, 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9, 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165, 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766, 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b, 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f, 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030, 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5, 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59, 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63, 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf, 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a, 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845, 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51, 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c, 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f, 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3, 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46, 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea, 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d, 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60, 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74, 0x8568a0a8}, {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5, 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf, 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5, 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba, 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf, 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f, 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0, 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450, 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55, 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a, 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620, 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a, 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454, 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4, 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534, 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584, 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694, 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e, 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4, 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1, 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4, 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164, 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1, 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911, 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314, 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c, 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6, 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec, 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc, 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c, 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c, 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c, 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716, 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c, 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676, 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879, 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c, 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc, 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77, 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7, 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2, 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd, 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7, 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad, 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897, 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827, 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7, 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947, 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57, 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d, 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37, 0x0d907052}, {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d, 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89, 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31, 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81, 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e, 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0, 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f, 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291, 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e, 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e, 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936, 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2, 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13, 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d, 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f, 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1, 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a, 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae, 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516, 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f, 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20, 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe, 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28, 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6, 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419, 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5, 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d, 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889, 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412, 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c, 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e, 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0, 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02, 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986, 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e, 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e, 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221, 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf, 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913, 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d, 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622, 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592, 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a, 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae, 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c, 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82, 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20, 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe, 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025, 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1, 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719, 0xfd1a6c8a}, {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3, 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb, 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d, 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb, 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9, 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156, 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045, 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa, 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8, 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e, 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8, 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0, 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38, 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87, 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46, 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9, 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585, 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d, 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb, 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531, 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03, 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc, 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33, 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c, 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be, 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d, 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b, 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303, 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f, 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0, 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801, 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe, 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e, 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346, 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620, 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776, 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844, 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb, 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0, 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f, 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d, 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b, 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d, 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75, 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795, 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a, 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb, 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354, 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28, 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30, 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856, 0x7895f01a}, {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188, 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33, 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d, 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445, 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2, 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058, 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43, 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9, 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e, 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06, 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228, 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93, 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e, 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4, 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b, 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371, 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265, 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede, 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0, 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f, 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8, 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32, 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae, 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544, 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3, 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f, 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911, 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa, 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be, 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54, 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b, 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1, 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652, 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9, 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7, 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f, 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68, 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782, 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797, 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d, 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a, 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2, 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc, 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647, 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4, 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e, 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41, 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab, 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf, 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904, 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a, 0x9239b848}, {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad, 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0, 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40, 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b, 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d, 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b, 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb, 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d, 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b, 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0, 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840, 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d, 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b, 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d, 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6, 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0, 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580, 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd, 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d, 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b, 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d, 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b, 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6, 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0, 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6, 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c, 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c, 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461, 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841, 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317, 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac, 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa, 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7, 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba, 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a, 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161, 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777, 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21, 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a, 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc, 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da, 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1, 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01, 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c, 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241, 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917, 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac, 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa, 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da, 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397, 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537, 0xeb36d3cc}, {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b, 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059, 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251, 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d, 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9, 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c, 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41, 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4, 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10, 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c, 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54, 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476, 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8, 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d, 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92, 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307, 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad, 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f, 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87, 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17, 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3, 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46, 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197, 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02, 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6, 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e, 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96, 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4, 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e, 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b, 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934, 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1, 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7, 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5, 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd, 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1, 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475, 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0, 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155, 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0, 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304, 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348, 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140, 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862, 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14, 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181, 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e, 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab, 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01, 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523, 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b, 0x38e5f3c5}, {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06, 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad, 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509, 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba, 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414, 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3, 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733, 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994, 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a, 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889, 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d, 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386, 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621, 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886, 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e, 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389, 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f, 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294, 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30, 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3, 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d, 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba, 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a, 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad, 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03, 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2, 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306, 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad, 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b, 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc, 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914, 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3, 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435, 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e, 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a, 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589, 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27, 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080, 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21, 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586, 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28, 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b, 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f, 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94, 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12, 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5, 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d, 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba, 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c, 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7, 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103, 0x3d3101a2}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000, 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000, 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000, 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000, 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000, 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000, 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000, 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000, 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000, 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000, 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000, 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000, 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000, 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000, 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000, 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000, 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000, 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000, 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000, 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000, 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000, 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000, 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000, 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000, 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000, 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000, 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000, 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000, 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000, 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000, 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000, 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000, 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000, 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000, 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000, 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000, 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000, 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000, 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000, 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000, 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000, 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000, 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000, 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000, 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000, 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000, 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000, 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000, 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000, 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000, 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000, 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000, 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000, 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000, 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000, 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000, 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000, 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000, 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000, 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000, 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000, 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000, 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000, 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000, 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000, 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000, 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000, 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000, 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000, 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000, 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000, 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000, 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000, 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000, 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000, 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000, 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000, 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000, 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000, 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000, 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000, 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000, 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000, 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000, 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000, 0xa201313d00000000}, {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000, 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000, 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000, 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000, 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000, 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000, 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000, 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000, 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000, 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000, 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000, 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000, 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000, 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000, 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000, 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000, 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000, 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000, 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000, 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000, 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000, 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000, 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000, 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000, 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000, 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000, 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000, 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000, 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000, 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000, 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000, 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000, 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000, 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000, 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000, 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000, 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000, 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000, 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000, 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000, 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000, 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000, 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000, 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000, 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000, 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000, 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000, 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000, 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000, 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000, 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000, 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000, 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000, 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000, 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000, 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000, 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000, 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000, 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000, 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000, 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000, 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000, 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000, 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000, 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000, 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000, 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000, 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000, 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000, 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000, 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000, 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000, 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000, 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000, 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000, 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000, 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000, 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000, 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000, 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000, 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000, 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000, 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000, 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000, 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000, 0xc5f3e53800000000}, {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000, 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000, 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000, 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000, 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000, 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000, 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000, 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000, 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000, 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000, 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000, 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000, 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000, 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000, 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000, 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000, 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000, 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000, 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000, 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000, 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000, 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000, 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000, 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000, 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000, 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000, 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000, 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000, 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000, 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000, 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000, 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000, 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000, 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000, 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000, 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000, 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000, 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000, 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000, 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000, 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000, 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000, 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000, 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000, 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000, 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000, 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000, 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000, 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000, 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000, 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000, 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000, 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000, 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000, 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000, 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000, 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000, 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000, 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000, 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000, 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000, 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000, 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000, 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000, 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000, 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000, 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000, 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000, 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000, 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000, 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000, 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000, 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000, 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000, 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000, 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000, 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000, 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000, 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000, 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000, 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000, 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000, 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000, 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000, 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000, 0xccd336eb00000000}, {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000, 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000, 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000, 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000, 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000, 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000, 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000, 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000, 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000, 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000, 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000, 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000, 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000, 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000, 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000, 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000, 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000, 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000, 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000, 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000, 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000, 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000, 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000, 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000, 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000, 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000, 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000, 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000, 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000, 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000, 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000, 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000, 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000, 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000, 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000, 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000, 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000, 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000, 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000, 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000, 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000, 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000, 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000, 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000, 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000, 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000, 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000, 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000, 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000, 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000, 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000, 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000, 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000, 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000, 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000, 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000, 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000, 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000, 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000, 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000, 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000, 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000, 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000, 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000, 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000, 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000, 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000, 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000, 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000, 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000, 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000, 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000, 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000, 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000, 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000, 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000, 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000, 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000, 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000, 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000, 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000, 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000, 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000, 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000, 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000, 0x48b8399200000000}, {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000, 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000, 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000, 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000, 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000, 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000, 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000, 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000, 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000, 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000, 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000, 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000, 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000, 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000, 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000, 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000, 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000, 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000, 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000, 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000, 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000, 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000, 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000, 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000, 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000, 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000, 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000, 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000, 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000, 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000, 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000, 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000, 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000, 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000, 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000, 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000, 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000, 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000, 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000, 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000, 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000, 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000, 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000, 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000, 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000, 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000, 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000, 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000, 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000, 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000, 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000, 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000, 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000, 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000, 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000, 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000, 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000, 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000, 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000, 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000, 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000, 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000, 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000, 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000, 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000, 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000, 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000, 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000, 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000, 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000, 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000, 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000, 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000, 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000, 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000, 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000, 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000, 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000, 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000, 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000, 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000, 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000, 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000, 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000, 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000, 0x1af0957800000000}, {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000, 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000, 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000, 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000, 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000, 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000, 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000, 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000, 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000, 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000, 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000, 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000, 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000, 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000, 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000, 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000, 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000, 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000, 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000, 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000, 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000, 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000, 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000, 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000, 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000, 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000, 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000, 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000, 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000, 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000, 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000, 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000, 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000, 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000, 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000, 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000, 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000, 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000, 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000, 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000, 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000, 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000, 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000, 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000, 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000, 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000, 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000, 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000, 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000, 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000, 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000, 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000, 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000, 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000, 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000, 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000, 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000, 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000, 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000, 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000, 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000, 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000, 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000, 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000, 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000, 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000, 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000, 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000, 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000, 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000, 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000, 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000, 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000, 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000, 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000, 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000, 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000, 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000, 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000, 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000, 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000, 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000, 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000, 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000, 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000, 0x8a6c1afd00000000}, {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000, 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000, 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000, 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000, 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000, 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000, 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000, 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000, 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000, 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000, 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000, 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000, 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000, 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000, 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000, 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000, 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000, 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000, 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000, 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000, 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000, 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000, 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000, 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000, 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000, 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000, 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000, 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000, 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000, 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000, 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000, 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000, 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000, 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000, 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000, 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000, 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000, 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000, 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000, 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000, 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000, 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000, 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000, 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000, 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000, 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000, 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000, 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000, 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000, 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000, 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000, 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000, 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000, 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000, 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000, 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000, 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000, 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000, 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000, 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000, 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000, 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000, 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000, 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000, 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000, 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000, 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000, 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000, 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000, 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000, 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000, 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000, 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000, 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000, 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000, 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000, 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000, 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000, 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000, 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000, 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000, 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000, 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000, 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000, 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000, 0x5270900d00000000}, {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000, 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000, 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000, 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000, 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000, 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000, 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000, 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000, 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000, 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000, 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000, 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000, 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000, 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000, 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000, 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000, 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000, 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000, 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000, 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000, 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000, 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000, 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000, 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000, 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000, 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000, 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000, 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000, 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000, 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000, 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000, 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000, 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000, 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000, 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000, 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000, 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000, 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000, 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000, 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000, 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000, 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000, 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000, 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000, 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000, 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000, 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000, 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000, 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000, 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000, 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000, 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000, 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000, 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000, 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000, 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000, 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000, 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000, 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000, 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000, 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000, 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000, 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000, 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000, 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000, 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000, 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000, 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000, 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000, 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000, 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000, 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000, 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000, 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000, 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000, 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000, 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000, 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000, 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000, 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000, 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000, 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000, 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000, 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000, 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000, 0xa8a0688500000000}}; #else /* W == 4 */ local const z_crc_t FAR crc_braid_table[][256] = { {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, 0x09cd8551}, {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, 0x7bc97a0c}, {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, 0x7851a2ca}, {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, 0x566b6848}}; local const z_word_t FAR crc_braid_big_table[][256] = { {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912, 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba, 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3, 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30, 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e, 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3, 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73, 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe, 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0, 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643, 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a, 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082, 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4, 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279, 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735, 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8, 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad, 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05, 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c, 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718, 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46, 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb, 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc, 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41, 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f, 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad, 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4, 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c, 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779, 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4, 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8, 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235, 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7, 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f, 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476, 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195, 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb, 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46, 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622, 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af, 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1, 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12, 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b, 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3, 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51, 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc, 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90, 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d, 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708, 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0, 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9, 0x48686b56}, {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c, 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae, 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb, 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90, 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410, 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b, 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6, 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed, 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d, 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036, 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953, 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1, 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca, 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781, 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d, 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416, 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f, 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd, 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8, 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b, 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb, 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0, 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5, 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e, 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e, 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558, 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d, 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf, 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6, 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad, 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971, 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a, 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b, 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969, 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c, 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57, 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7, 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c, 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab, 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0, 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160, 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b, 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e, 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac, 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d, 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546, 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a, 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1, 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8, 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a, 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f, 0xcaa25178}, {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00, 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b, 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed, 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777, 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01, 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a, 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef, 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74, 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002, 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498, 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee, 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75, 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05, 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e, 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8, 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73, 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404, 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f, 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9, 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71, 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607, 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c, 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb, 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470, 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806, 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790, 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6, 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d, 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a, 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991, 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7, 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c, 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09, 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92, 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4, 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e, 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08, 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593, 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3, 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778, 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e, 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94, 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2, 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079, 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c, 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497, 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1, 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a, 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d, 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396, 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0, 0x0c7ac97b}, {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669, 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853, 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062, 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527, 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad, 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545, 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27, 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf, 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45, 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800, 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031, 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b, 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26, 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce, 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d, 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5, 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130, 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a, 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b, 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480, 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a, 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2, 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e, 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996, 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c, 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc, 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd, 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7, 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232, 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da, 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439, 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1, 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da, 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0, 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1, 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94, 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e, 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6, 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2, 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a, 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0, 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95, 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4, 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e, 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395, 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d, 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e, 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676, 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83, 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9, 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888, 0x5185cd09}}; #endif #endif #endif local const z_crc_t FAR x2n_table[] = { 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000, 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467, 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0, 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169, 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37, 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a, 0xc40ba6d0, 0xc4e22c3c}; fltk-1.4.3/zlib/crc32.c0000644000175000017500000007556515004135251014647 0ustar albrechtalbrecht/* crc32.c -- compute the CRC-32 of a data stream * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * This interleaved implementation of a CRC makes use of pipelined multiple * arithmetic-logic units, commonly found in modern CPU cores. It is due to * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution. */ /* @(#) $Id$ */ /* Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore protection on the static variables used to control the first-use generation of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should first call get_crc_table() to initialize the tables before allowing more than one thread to use crc32(). MAKECRCH can be #defined to write out crc32.h. A main() routine is also produced, so that this one source file can be compiled to an executable. */ #ifdef MAKECRCH # include # ifndef DYNAMIC_CRC_TABLE # define DYNAMIC_CRC_TABLE # endif /* !DYNAMIC_CRC_TABLE */ #endif /* MAKECRCH */ #include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */ /* A CRC of a message is computed on N braids of words in the message, where each word consists of W bytes (4 or 8). If N is 3, for example, then three running sparse CRCs are calculated respectively on each braid, at these indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ... This is done starting at a word boundary, and continues until as many blocks of N * W bytes as are available have been processed. The results are combined into a single CRC at the end. For this code, N must be in the range 1..6 and W must be 4 or 8. The upper limit on N can be increased if desired by adding more #if blocks, extending the patterns apparent in the code. In addition, crc32.h would need to be regenerated, if the maximum N value is increased. N and W are chosen empirically by benchmarking the execution time on a given processor. The choices for N and W below were based on testing on Intel Kaby Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64 Octeon II processors. The Intel, AMD, and ARM processors were all fastest with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4. They were all tested with either gcc or clang, all using the -O3 optimization level. Your mileage may vary. */ /* Define N */ #ifdef Z_TESTN # define N Z_TESTN #else # define N 5 #endif #if N < 1 || N > 6 # error N must be in 1..6 #endif /* z_crc_t must be at least 32 bits. z_word_t must be at least as long as z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and that bytes are eight bits. */ /* Define W and the associated z_word_t type. If W is not defined, then a braided calculation is not used, and the associated tables and code are not compiled. */ #ifdef Z_TESTW # if Z_TESTW-1 != -1 # define W Z_TESTW # endif #else # ifdef MAKECRCH # define W 8 /* required for MAKECRCH */ # else # if defined(__x86_64__) || defined(__aarch64__) # define W 8 # else # define W 4 # endif # endif #endif #ifdef W # if W == 8 && defined(Z_U8) typedef Z_U8 z_word_t; # elif defined(Z_U4) # undef W # define W 4 typedef Z_U4 z_word_t; # else # undef W # endif #endif /* If available, use the ARM processor CRC32 instruction. */ #if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8 # define ARMCRC32 #endif #if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) /* Swap the bytes in a z_word_t to convert between little and big endian. Any self-respecting compiler will optimize this to a single machine byte-swap instruction, if one is available. This assumes that word_t is either 32 bits or 64 bits. */ local z_word_t byte_swap(z_word_t word) { # if W == 8 return (word & 0xff00000000000000) >> 56 | (word & 0xff000000000000) >> 40 | (word & 0xff0000000000) >> 24 | (word & 0xff00000000) >> 8 | (word & 0xff000000) << 8 | (word & 0xff0000) << 24 | (word & 0xff00) << 40 | (word & 0xff) << 56; # else /* W == 4 */ return (word & 0xff000000) >> 24 | (word & 0xff0000) >> 8 | (word & 0xff00) << 8 | (word & 0xff) << 24; # endif } #endif #ifdef DYNAMIC_CRC_TABLE /* ========================================================================= * Table of powers of x for combining CRC-32s, filled in by make_crc_table() * below. */ local z_crc_t FAR x2n_table[32]; #else /* ========================================================================= * Tables for byte-wise and braided CRC-32 calculations, and a table of powers * of x for combining CRC-32s, all made by make_crc_table(). */ # include "crc32.h" #endif /* CRC polynomial. */ #define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ /* Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, reflected. For speed, this requires that a not be zero. */ local z_crc_t multmodp(z_crc_t a, z_crc_t b) { z_crc_t m, p; m = (z_crc_t)1 << 31; p = 0; for (;;) { if (a & m) { p ^= b; if ((a & (m - 1)) == 0) break; } m >>= 1; b = b & 1 ? (b >> 1) ^ POLY : b >> 1; } return p; } /* Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been initialized. */ local z_crc_t x2nmodp(z_off64_t n, unsigned k) { z_crc_t p; p = (z_crc_t)1 << 31; /* x^0 == 1 */ while (n) { if (n & 1) p = multmodp(x2n_table[k & 31], p); n >>= 1; k++; } return p; } #ifdef DYNAMIC_CRC_TABLE /* ========================================================================= * Build the tables for byte-wise and braided CRC-32 calculations, and a table * of powers of x for combining CRC-32s. */ local z_crc_t FAR crc_table[256]; #ifdef W local z_word_t FAR crc_big_table[256]; local z_crc_t FAR crc_braid_table[W][256]; local z_word_t FAR crc_braid_big_table[W][256]; local void braid(z_crc_t [][256], z_word_t [][256], int, int); #endif #ifdef MAKECRCH local void write_table(FILE *, const z_crc_t FAR *, int); local void write_table32hi(FILE *, const z_word_t FAR *, int); local void write_table64(FILE *, const z_word_t FAR *, int); #endif /* MAKECRCH */ /* Define a once() function depending on the availability of atomics. If this is compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in multiple threads, and if atomics are not available, then get_crc_table() must be called to initialize the tables and must return before any threads are allowed to compute or combine CRCs. */ /* Definition of once functionality. */ typedef struct once_s once_t; /* Check for the availability of atomics. */ #if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ !defined(__STDC_NO_ATOMICS__) #include /* Structure for once(), which must be initialized with ONCE_INIT. */ struct once_s { atomic_flag begun; atomic_int done; }; #define ONCE_INIT {ATOMIC_FLAG_INIT, 0} /* Run the provided init() function exactly once, even if multiple threads invoke once() at the same time. The state must be a once_t initialized with ONCE_INIT. */ local void once(once_t *state, void (*init)(void)) { if (!atomic_load(&state->done)) { if (atomic_flag_test_and_set(&state->begun)) while (!atomic_load(&state->done)) ; else { init(); atomic_store(&state->done, 1); } } } #else /* no atomics */ /* Structure for once(), which must be initialized with ONCE_INIT. */ struct once_s { volatile int begun; volatile int done; }; #define ONCE_INIT {0, 0} /* Test and set. Alas, not atomic, but tries to minimize the period of vulnerability. */ local int test_and_set(int volatile *flag) { int was; was = *flag; *flag = 1; return was; } /* Run the provided init() function once. This is not thread-safe. */ local void once(once_t *state, void (*init)(void)) { if (!state->done) { if (test_and_set(&state->begun)) while (!state->done) ; else { init(); state->done = 1; } } } #endif /* State for once(). */ local once_t made = ONCE_INIT; /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x (which is shifting right by one and adding x^32 mod p if the bit shifted out is a one). We start with the highest power (least significant bit) of q and repeat for all eight bits of q. The table is simply the CRC of all possible eight bit values. This is all the information needed to generate CRCs on data a byte at a time for all combinations of CRC register values and incoming bytes. */ local void make_crc_table(void) { unsigned i, j, n; z_crc_t p; /* initialize the CRC of bytes tables */ for (i = 0; i < 256; i++) { p = i; for (j = 0; j < 8; j++) p = p & 1 ? (p >> 1) ^ POLY : p >> 1; crc_table[i] = p; #ifdef W crc_big_table[i] = byte_swap(p); #endif } /* initialize the x^2^n mod p(x) table */ p = (z_crc_t)1 << 30; /* x^1 */ x2n_table[0] = p; for (n = 1; n < 32; n++) x2n_table[n] = p = multmodp(p, p); #ifdef W /* initialize the braiding tables -- needs x2n_table[] */ braid(crc_braid_table, crc_braid_big_table, N, W); #endif #ifdef MAKECRCH { /* The crc32.h header file contains tables for both 32-bit and 64-bit z_word_t's, and so requires a 64-bit type be available. In that case, z_word_t must be defined to be 64-bits. This code then also generates and writes out the tables for the case that z_word_t is 32 bits. */ #if !defined(W) || W != 8 # error Need a 64-bit integer type in order to generate crc32.h. #endif FILE *out; int k, n; z_crc_t ltl[8][256]; z_word_t big[8][256]; out = fopen("crc32.h", "w"); if (out == NULL) return; /* write out little-endian CRC table to crc32.h */ fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n" " * Generated automatically by crc32.c\n */\n" "\n" "local const z_crc_t FAR crc_table[] = {\n" " "); write_table(out, crc_table, 256); fprintf(out, "};\n"); /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */ fprintf(out, "\n" "#ifdef W\n" "\n" "#if W == 8\n" "\n" "local const z_word_t FAR crc_big_table[] = {\n" " "); write_table64(out, crc_big_table, 256); fprintf(out, "};\n"); /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */ fprintf(out, "\n" "#else /* W == 4 */\n" "\n" "local const z_word_t FAR crc_big_table[] = {\n" " "); write_table32hi(out, crc_big_table, 256); fprintf(out, "};\n" "\n" "#endif\n"); /* write out braid tables for each value of N */ for (n = 1; n <= 6; n++) { fprintf(out, "\n" "#if N == %d\n", n); /* compute braid tables for this N and 64-bit word_t */ braid(ltl, big, n, 8); /* write out braid tables for 64-bit z_word_t to crc32.h */ fprintf(out, "\n" "#if W == 8\n" "\n" "local const z_crc_t FAR crc_braid_table[][256] = {\n"); for (k = 0; k < 8; k++) { fprintf(out, " {"); write_table(out, ltl[k], 256); fprintf(out, "}%s", k < 7 ? ",\n" : ""); } fprintf(out, "};\n" "\n" "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); for (k = 0; k < 8; k++) { fprintf(out, " {"); write_table64(out, big[k], 256); fprintf(out, "}%s", k < 7 ? ",\n" : ""); } fprintf(out, "};\n"); /* compute braid tables for this N and 32-bit word_t */ braid(ltl, big, n, 4); /* write out braid tables for 32-bit z_word_t to crc32.h */ fprintf(out, "\n" "#else /* W == 4 */\n" "\n" "local const z_crc_t FAR crc_braid_table[][256] = {\n"); for (k = 0; k < 4; k++) { fprintf(out, " {"); write_table(out, ltl[k], 256); fprintf(out, "}%s", k < 3 ? ",\n" : ""); } fprintf(out, "};\n" "\n" "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); for (k = 0; k < 4; k++) { fprintf(out, " {"); write_table32hi(out, big[k], 256); fprintf(out, "}%s", k < 3 ? ",\n" : ""); } fprintf(out, "};\n" "\n" "#endif\n" "\n" "#endif\n"); } fprintf(out, "\n" "#endif\n"); /* write out zeros operator table to crc32.h */ fprintf(out, "\n" "local const z_crc_t FAR x2n_table[] = {\n" " "); write_table(out, x2n_table, 32); fprintf(out, "};\n"); fclose(out); } #endif /* MAKECRCH */ } #ifdef MAKECRCH /* Write the 32-bit values in table[0..k-1] to out, five per line in hexadecimal separated by commas. */ local void write_table(FILE *out, const z_crc_t FAR *table, int k) { int n; for (n = 0; n < k; n++) fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", (unsigned long)(table[n]), n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); } /* Write the high 32-bits of each value in table[0..k-1] to out, five per line in hexadecimal separated by commas. */ local void write_table32hi(FILE *out, const z_word_t FAR *table, int k) { int n; for (n = 0; n < k; n++) fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", (unsigned long)(table[n] >> 32), n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); } /* Write the 64-bit values in table[0..k-1] to out, three per line in hexadecimal separated by commas. This assumes that if there is a 64-bit type, then there is also a long long integer type, and it is at least 64 bits. If not, then the type cast and format string can be adjusted accordingly. */ local void write_table64(FILE *out, const z_word_t FAR *table, int k) { int n; for (n = 0; n < k; n++) fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ", (unsigned long long)(table[n]), n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", ")); } /* Actually do the deed. */ int main(void) { make_crc_table(); return 0; } #endif /* MAKECRCH */ #ifdef W /* Generate the little and big-endian braid tables for the given n and z_word_t size w. Each array must have room for w blocks of 256 elements. */ local void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) { int k; z_crc_t i, p, q; for (k = 0; k < w; k++) { p = x2nmodp((n * w + 3 - k) << 3, 0); ltl[k][0] = 0; big[w - 1 - k][0] = 0; for (i = 1; i < 256; i++) { ltl[k][i] = q = multmodp(i << 24, p); big[w - 1 - k][i] = byte_swap(q); } } } #endif #endif /* DYNAMIC_CRC_TABLE */ /* ========================================================================= * This function can be used by asm versions of crc32(), and to force the * generation of the CRC tables in a threaded application. */ const z_crc_t FAR * ZEXPORT get_crc_table(void) { #ifdef DYNAMIC_CRC_TABLE once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ return (const z_crc_t FAR *)crc_table; } /* ========================================================================= * Use ARM machine instructions if available. This will compute the CRC about * ten times faster than the braided calculation. This code does not check for * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will * only be defined if the compilation specifies an ARM processor architecture * that has the instructions. For example, compiling with -march=armv8.1-a or * -march=armv8-a+crc, or -march=native if the compile machine has the crc32 * instructions. */ #ifdef ARMCRC32 /* Constants empirically determined to maximize speed. These values are from measurements on a Cortex-A57. Your mileage may vary. */ #define Z_BATCH 3990 /* number of words in a batch */ #define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */ #define Z_BATCH_MIN 800 /* fewest words in a final batch */ unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, z_size_t len) { z_crc_t val; z_word_t crc1, crc2; const z_word_t *word; z_word_t val0, val1, val2; z_size_t last, last2, i; z_size_t num; /* Return initial CRC, if requested. */ if (buf == Z_NULL) return 0; #ifdef DYNAMIC_CRC_TABLE once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ /* Pre-condition the CRC */ crc = (~crc) & 0xffffffff; /* Compute the CRC up to a word boundary. */ while (len && ((z_size_t)buf & 7) != 0) { len--; val = *buf++; __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); } /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */ word = (z_word_t const *)buf; num = len >> 3; len &= 7; /* Do three interleaved CRCs to realize the throughput of one crc32x instruction per cycle. Each CRC is calculated on Z_BATCH words. The three CRCs are combined into a single CRC after each set of batches. */ while (num >= 3 * Z_BATCH) { crc1 = 0; crc2 = 0; for (i = 0; i < Z_BATCH; i++) { val0 = word[i]; val1 = word[i + Z_BATCH]; val2 = word[i + 2 * Z_BATCH]; __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); } word += 3 * Z_BATCH; num -= 3 * Z_BATCH; crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1; crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2; } /* Do one last smaller batch with the remaining words, if there are enough to pay for the combination of CRCs. */ last = num / 3; if (last >= Z_BATCH_MIN) { last2 = last << 1; crc1 = 0; crc2 = 0; for (i = 0; i < last; i++) { val0 = word[i]; val1 = word[i + last]; val2 = word[i + last2]; __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); } word += 3 * last; num -= 3 * last; val = x2nmodp(last, 6); crc = multmodp(val, crc) ^ crc1; crc = multmodp(val, crc) ^ crc2; } /* Compute the CRC on any remaining words. */ for (i = 0; i < num; i++) { val0 = word[i]; __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); } word += num; /* Complete the CRC on any remaining bytes. */ buf = (const unsigned char FAR *)word; while (len) { len--; val = *buf++; __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); } /* Return the CRC, post-conditioned. */ return crc ^ 0xffffffff; } #else #ifdef W /* Return the CRC of the W bytes in the word_t data, taking the least-significant byte of the word as the first byte of data, without any pre or post conditioning. This is used to combine the CRCs of each braid. */ local z_crc_t crc_word(z_word_t data) { int k; for (k = 0; k < W; k++) data = (data >> 8) ^ crc_table[data & 0xff]; return (z_crc_t)data; } local z_word_t crc_word_big(z_word_t data) { int k; for (k = 0; k < W; k++) data = (data << 8) ^ crc_big_table[(data >> ((W - 1) << 3)) & 0xff]; return data; } #endif /* ========================================================================= */ unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, z_size_t len) { /* Return initial CRC, if requested. */ if (buf == Z_NULL) return 0; #ifdef DYNAMIC_CRC_TABLE once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ /* Pre-condition the CRC */ crc = (~crc) & 0xffffffff; #ifdef W /* If provided enough bytes, do a braided CRC calculation. */ if (len >= N * W + W - 1) { z_size_t blks; z_word_t const *words; unsigned endian; int k; /* Compute the CRC up to a z_word_t boundary. */ while (len && ((z_size_t)buf & (W - 1)) != 0) { len--; crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; } /* Compute the CRC on as many N z_word_t blocks as are available. */ blks = len / (N * W); len -= blks * N * W; words = (z_word_t const *)buf; /* Do endian check at execution time instead of compile time, since ARM processors can change the endianness at execution time. If the compiler knows what the endianness will be, it can optimize out the check and the unused branch. */ endian = 1; if (*(unsigned char *)&endian) { /* Little endian. */ z_crc_t crc0; z_word_t word0; #if N > 1 z_crc_t crc1; z_word_t word1; #if N > 2 z_crc_t crc2; z_word_t word2; #if N > 3 z_crc_t crc3; z_word_t word3; #if N > 4 z_crc_t crc4; z_word_t word4; #if N > 5 z_crc_t crc5; z_word_t word5; #endif #endif #endif #endif #endif /* Initialize the CRC for each braid. */ crc0 = crc; #if N > 1 crc1 = 0; #if N > 2 crc2 = 0; #if N > 3 crc3 = 0; #if N > 4 crc4 = 0; #if N > 5 crc5 = 0; #endif #endif #endif #endif #endif /* Process the first blks-1 blocks, computing the CRCs on each braid independently. */ while (--blks) { /* Load the word for each braid into registers. */ word0 = crc0 ^ words[0]; #if N > 1 word1 = crc1 ^ words[1]; #if N > 2 word2 = crc2 ^ words[2]; #if N > 3 word3 = crc3 ^ words[3]; #if N > 4 word4 = crc4 ^ words[4]; #if N > 5 word5 = crc5 ^ words[5]; #endif #endif #endif #endif #endif words += N; /* Compute and update the CRC for each word. The loop should get unrolled. */ crc0 = crc_braid_table[0][word0 & 0xff]; #if N > 1 crc1 = crc_braid_table[0][word1 & 0xff]; #if N > 2 crc2 = crc_braid_table[0][word2 & 0xff]; #if N > 3 crc3 = crc_braid_table[0][word3 & 0xff]; #if N > 4 crc4 = crc_braid_table[0][word4 & 0xff]; #if N > 5 crc5 = crc_braid_table[0][word5 & 0xff]; #endif #endif #endif #endif #endif for (k = 1; k < W; k++) { crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff]; #if N > 1 crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff]; #if N > 2 crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff]; #if N > 3 crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff]; #if N > 4 crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff]; #if N > 5 crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff]; #endif #endif #endif #endif #endif } } /* Process the last block, combining the CRCs of the N braids at the same time. */ crc = crc_word(crc0 ^ words[0]); #if N > 1 crc = crc_word(crc1 ^ words[1] ^ crc); #if N > 2 crc = crc_word(crc2 ^ words[2] ^ crc); #if N > 3 crc = crc_word(crc3 ^ words[3] ^ crc); #if N > 4 crc = crc_word(crc4 ^ words[4] ^ crc); #if N > 5 crc = crc_word(crc5 ^ words[5] ^ crc); #endif #endif #endif #endif #endif words += N; } else { /* Big endian. */ z_word_t crc0, word0, comb; #if N > 1 z_word_t crc1, word1; #if N > 2 z_word_t crc2, word2; #if N > 3 z_word_t crc3, word3; #if N > 4 z_word_t crc4, word4; #if N > 5 z_word_t crc5, word5; #endif #endif #endif #endif #endif /* Initialize the CRC for each braid. */ crc0 = byte_swap(crc); #if N > 1 crc1 = 0; #if N > 2 crc2 = 0; #if N > 3 crc3 = 0; #if N > 4 crc4 = 0; #if N > 5 crc5 = 0; #endif #endif #endif #endif #endif /* Process the first blks-1 blocks, computing the CRCs on each braid independently. */ while (--blks) { /* Load the word for each braid into registers. */ word0 = crc0 ^ words[0]; #if N > 1 word1 = crc1 ^ words[1]; #if N > 2 word2 = crc2 ^ words[2]; #if N > 3 word3 = crc3 ^ words[3]; #if N > 4 word4 = crc4 ^ words[4]; #if N > 5 word5 = crc5 ^ words[5]; #endif #endif #endif #endif #endif words += N; /* Compute and update the CRC for each word. The loop should get unrolled. */ crc0 = crc_braid_big_table[0][word0 & 0xff]; #if N > 1 crc1 = crc_braid_big_table[0][word1 & 0xff]; #if N > 2 crc2 = crc_braid_big_table[0][word2 & 0xff]; #if N > 3 crc3 = crc_braid_big_table[0][word3 & 0xff]; #if N > 4 crc4 = crc_braid_big_table[0][word4 & 0xff]; #if N > 5 crc5 = crc_braid_big_table[0][word5 & 0xff]; #endif #endif #endif #endif #endif for (k = 1; k < W; k++) { crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff]; #if N > 1 crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff]; #if N > 2 crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff]; #if N > 3 crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff]; #if N > 4 crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff]; #if N > 5 crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff]; #endif #endif #endif #endif #endif } } /* Process the last block, combining the CRCs of the N braids at the same time. */ comb = crc_word_big(crc0 ^ words[0]); #if N > 1 comb = crc_word_big(crc1 ^ words[1] ^ comb); #if N > 2 comb = crc_word_big(crc2 ^ words[2] ^ comb); #if N > 3 comb = crc_word_big(crc3 ^ words[3] ^ comb); #if N > 4 comb = crc_word_big(crc4 ^ words[4] ^ comb); #if N > 5 comb = crc_word_big(crc5 ^ words[5] ^ comb); #endif #endif #endif #endif #endif words += N; crc = byte_swap(comb); } /* Update the pointer to the remaining bytes to process. */ buf = (unsigned char const *)words; } #endif /* W */ /* Complete the computation of the CRC on any remaining bytes. */ while (len >= 8) { len -= 8; crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; } while (len) { len--; crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; } /* Return the CRC, post-conditioned. */ return crc ^ 0xffffffff; } #endif /* ========================================================================= */ unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len) { return crc32_z(crc, buf, len); } /* ========================================================================= */ uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) { #ifdef DYNAMIC_CRC_TABLE once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff); } /* ========================================================================= */ uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) { return crc32_combine64(crc1, crc2, (z_off64_t)len2); } /* ========================================================================= */ uLong ZEXPORT crc32_combine_gen64(z_off64_t len2) { #ifdef DYNAMIC_CRC_TABLE once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ return x2nmodp(len2, 3); } /* ========================================================================= */ uLong ZEXPORT crc32_combine_gen(z_off_t len2) { return crc32_combine_gen64((z_off64_t)len2); } /* ========================================================================= */ uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op) { return multmodp(op, crc1) ^ (crc2 & 0xffffffff); } fltk-1.4.3/zlib/trees.c0000644000175000017500000011775115004135251015047 0ustar albrechtalbrecht/* trees.c -- output deflated data using Huffman coding * Copyright (C) 1995-2024 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process uses several Huffman trees. The more * common source values are represented by shorter bit sequences. * * Each code tree is stored in a compressed form which is itself * a Huffman encoding of the lengths of all the code strings (in * ascending order by source values). The actual code strings are * reconstructed from the lengths in the inflate process, as described * in the deflate specification. * * REFERENCES * * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc * * Storer, James A. * Data Compression: Methods and Theory, pp. 49-50. * Computer Science Press, 1988. ISBN 0-7167-8156-5. * * Sedgewick, R. * Algorithms, p290. * Addison-Wesley, 1983. ISBN 0-201-06672-6. */ /* @(#) $Id$ */ /* #define GEN_TREES_H */ #include "deflate.h" #ifdef ZLIB_DEBUG # include #endif /* =========================================================================== * Constants */ #define MAX_BL_BITS 7 /* Bit length codes must not exceed MAX_BL_BITS bits */ #define END_BLOCK 256 /* end of block literal code */ #define REP_3_6 16 /* repeat previous bit length 3-6 times (2 bits of repeat count) */ #define REPZ_3_10 17 /* repeat a zero length 3-10 times (3 bits of repeat count) */ #define REPZ_11_138 18 /* repeat a zero length 11-138 times (7 bits of repeat count) */ local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; local const int extra_dbits[D_CODES] /* extra bits for each distance code */ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; local const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; /* The lengths of the bit length codes are sent in order of decreasing * probability, to avoid transmitting the lengths for unused bit length codes. */ /* =========================================================================== * Local data. These are initialized only once. */ #define DIST_CODE_LEN 512 /* see definition of array dist_code below */ #if defined(GEN_TREES_H) || !defined(STDC) /* non ANSI compilers may not accept trees.h */ local ct_data static_ltree[L_CODES+2]; /* The static literal tree. Since the bit lengths are imposed, there is no * need for the L_CODES extra codes used during heap construction. However * The codes 286 and 287 are needed to build a canonical tree (see _tr_init * below). */ local ct_data static_dtree[D_CODES]; /* The static distance tree. (Actually a trivial tree since all codes use * 5 bits.) */ uch _dist_code[DIST_CODE_LEN]; /* Distance codes. The first 256 values correspond to the distances * 3 .. 258, the last 256 values correspond to the top 8 bits of * the 15 bit distances. */ uch _length_code[MAX_MATCH-MIN_MATCH+1]; /* length code for each normalized match length (0 == MIN_MATCH) */ local int base_length[LENGTH_CODES]; /* First normalized length for each code (0 = MIN_MATCH) */ local int base_dist[D_CODES]; /* First normalized distance for each code (0 = distance of 1) */ #else # include "trees.h" #endif /* GEN_TREES_H */ struct static_tree_desc_s { const ct_data *static_tree; /* static tree or NULL */ const intf *extra_bits; /* extra bits for each code or NULL */ int extra_base; /* base index for extra_bits */ int elems; /* max number of elements in the tree */ int max_length; /* max bit length for the codes */ }; #ifdef NO_INIT_GLOBAL_POINTERS # define TCONST #else # define TCONST const #endif local TCONST static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; local TCONST static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; local TCONST static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== * Output a short LSB first on the stream. * IN assertion: there is enough room in pendingBuf. */ #define put_short(s, w) { \ put_byte(s, (uch)((w) & 0xff)); \ put_byte(s, (uch)((ush)(w) >> 8)); \ } /* =========================================================================== * Reverse the first len bits of a code, using straightforward code (a faster * method would use a table) * IN assertion: 1 <= len <= 15 */ local unsigned bi_reverse(unsigned code, int len) { register unsigned res = 0; do { res |= code & 1; code >>= 1, res <<= 1; } while (--len > 0); return res >> 1; } /* =========================================================================== * Flush the bit buffer, keeping at most 7 bits in it. */ local void bi_flush(deflate_state *s) { if (s->bi_valid == 16) { put_short(s, s->bi_buf); s->bi_buf = 0; s->bi_valid = 0; } else if (s->bi_valid >= 8) { put_byte(s, (Byte)s->bi_buf); s->bi_buf >>= 8; s->bi_valid -= 8; } } /* =========================================================================== * Flush the bit buffer and align the output on a byte boundary */ local void bi_windup(deflate_state *s) { if (s->bi_valid > 8) { put_short(s, s->bi_buf); } else if (s->bi_valid > 0) { put_byte(s, (Byte)s->bi_buf); } s->bi_buf = 0; s->bi_valid = 0; #ifdef ZLIB_DEBUG s->bits_sent = (s->bits_sent + 7) & ~7; #endif } /* =========================================================================== * Generate the codes for a given tree and bit counts (which need not be * optimal). * IN assertion: the array bl_count contains the bit length statistics for * the given tree and the field len is set for all tree elements. * OUT assertion: the field code is set for all tree elements of non * zero code length. */ local void gen_codes(ct_data *tree, int max_code, ushf *bl_count) { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ unsigned code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ /* The distribution counts are first used to generate the code values * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { code = (code + bl_count[bits - 1]) << 1; next_code[bits] = (ush)code; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. */ Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1, "inconsistent bit counts"); Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); for (n = 0; n <= max_code; n++) { int len = tree[n].Len; if (len == 0) continue; /* Now reverse the bits */ tree[n].Code = (ush)bi_reverse(next_code[len]++, len); Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1)); } } #ifdef GEN_TREES_H local void gen_trees_header(void); #endif #ifndef ZLIB_DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ #else /* !ZLIB_DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } #endif /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ #ifdef ZLIB_DEBUG local void send_bits(deflate_state *s, int value, int length) { Tracevv((stderr," l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); s->bits_sent += (ulg)length; /* If not enough room in bi_buf, use (valid) bits from bi_buf and * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid)) * unused bits in value. */ if (s->bi_valid > (int)Buf_size - length) { s->bi_buf |= (ush)value << s->bi_valid; put_short(s, s->bi_buf); s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); s->bi_valid += length - Buf_size; } else { s->bi_buf |= (ush)value << s->bi_valid; s->bi_valid += length; } } #else /* !ZLIB_DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ int val = (int)value;\ s->bi_buf |= (ush)val << s->bi_valid;\ put_short(s, s->bi_buf);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ s->bi_valid += len - Buf_size;\ } else {\ s->bi_buf |= (ush)(value) << s->bi_valid;\ s->bi_valid += len;\ }\ } #endif /* ZLIB_DEBUG */ /* the arguments must not have side effects */ /* =========================================================================== * Initialize the various 'constant' tables. */ local void tr_static_init(void) { #if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ int bits; /* bit counter */ int length; /* length value */ int code; /* code value */ int dist; /* distance index */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ if (static_init_done) return; /* For some embedded targets, global variables are not initialized: */ #ifdef NO_INIT_GLOBAL_POINTERS static_l_desc.static_tree = static_ltree; static_l_desc.extra_bits = extra_lbits; static_d_desc.static_tree = static_dtree; static_d_desc.extra_bits = extra_dbits; static_bl_desc.extra_bits = extra_blbits; #endif /* Initialize the mapping length (0..255) -> length code (0..28) */ length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; for (n = 0; n < (1 << extra_lbits[code]); n++) { _length_code[length++] = (uch)code; } } Assert (length == 256, "tr_static_init: length != 256"); /* Note that the length 255 (match length 258) can be represented * in two different ways: code 284 + 5 bits or code 285, so we * overwrite length_code[255] to use the best encoding: */ _length_code[length - 1] = (uch)code; /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; for (n = 0; n < (1 << extra_dbits[code]); n++) { _dist_code[dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: dist != 256"); dist >>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { _dist_code[256 + dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: 256 + dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; n = 0; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; /* Codes 286 and 287 do not exist, but we must include them in the * tree construction to get a canonical Huffman tree (longest code * all ones) */ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); /* The static distance tree is trivial: */ for (n = 0; n < D_CODES; n++) { static_dtree[n].Len = 5; static_dtree[n].Code = bi_reverse((unsigned)n, 5); } static_init_done = 1; # ifdef GEN_TREES_H gen_trees_header(); # endif #endif /* defined(GEN_TREES_H) || !defined(STDC) */ } /* =========================================================================== * Generate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef ZLIB_DEBUG # include # endif # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ ((i) % (width) == (width) - 1 ? ",\n" : ", ")) void gen_trees_header(void) { FILE *header = fopen("trees.h", "w"); int i; Assert (header != NULL, "Can't open trees.h"); fprintf(header, "/* header created automatically with -DGEN_TREES_H */\n\n"); fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); for (i = 0; i < L_CODES+2; i++) { fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); } fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); } fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); for (i = 0; i < DIST_CODE_LEN; i++) { fprintf(header, "%2u%s", _dist_code[i], SEPARATOR(i, DIST_CODE_LEN-1, 20)); } fprintf(header, "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { fprintf(header, "%2u%s", _length_code[i], SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); } fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); for (i = 0; i < LENGTH_CODES; i++) { fprintf(header, "%1u%s", base_length[i], SEPARATOR(i, LENGTH_CODES-1, 20)); } fprintf(header, "local const int base_dist[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "%5u%s", base_dist[i], SEPARATOR(i, D_CODES-1, 10)); } fclose(header); } #endif /* GEN_TREES_H */ /* =========================================================================== * Initialize a new block. */ local void init_block(deflate_state *s) { int n; /* iterates over tree elements */ /* Initialize the trees. */ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; s->dyn_ltree[END_BLOCK].Freq = 1; s->opt_len = s->static_len = 0L; s->sym_next = s->matches = 0; } /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ void ZLIB_INTERNAL _tr_init(deflate_state *s) { tr_static_init(); s->l_desc.dyn_tree = s->dyn_ltree; s->l_desc.stat_desc = &static_l_desc; s->d_desc.dyn_tree = s->dyn_dtree; s->d_desc.stat_desc = &static_d_desc; s->bl_desc.dyn_tree = s->bl_tree; s->bl_desc.stat_desc = &static_bl_desc; s->bi_buf = 0; s->bi_valid = 0; #ifdef ZLIB_DEBUG s->compressed_len = 0L; s->bits_sent = 0L; #endif /* Initialize the first block of the first file: */ init_block(s); } #define SMALLEST 1 /* Index within the heap array of least frequent node in the Huffman tree */ /* =========================================================================== * Remove the smallest element from the heap and recreate the heap with * one less element. Updates heap and heap_len. */ #define pqremove(s, tree, top) \ {\ top = s->heap[SMALLEST]; \ s->heap[SMALLEST] = s->heap[s->heap_len--]; \ pqdownheap(s, tree, SMALLEST); \ } /* =========================================================================== * Compares to subtrees, using the tree depth as tie breaker when * the subtrees have equal frequency. This minimizes the worst case length. */ #define smaller(tree, n, m, depth) \ (tree[n].Freq < tree[m].Freq || \ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) /* =========================================================================== * Restore the heap property by moving down the tree starting at node k, * exchanging a node with the smallest of its two sons if necessary, stopping * when the heap property is re-established (each father smaller than its * two sons). */ local void pqdownheap(deflate_state *s, ct_data *tree, int k) { int v = s->heap[k]; int j = k << 1; /* left son of k */ while (j <= s->heap_len) { /* Set j to the smallest of the two sons: */ if (j < s->heap_len && smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ if (smaller(tree, v, s->heap[j], s->depth)) break; /* Exchange v with the smallest son */ s->heap[k] = s->heap[j]; k = j; /* And continue down the tree, setting j to the left son of k */ j <<= 1; } s->heap[k] = v; } /* =========================================================================== * Compute the optimal bit lengths for a tree and update the total bit length * for the current block. * IN assertion: the fields freq and dad are set, heap[heap_max] and * above are the tree nodes sorted by increasing frequency. * OUT assertions: the field len is set to the optimal bit length, the * array bl_count contains the frequencies for each bit length. * The length opt_len is updated; static_len is also updated if stree is * not null. */ local void gen_bitlen(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; const ct_data *stree = desc->stat_desc->static_tree; const intf *extra = desc->stat_desc->extra_bits; int base = desc->stat_desc->extra_base; int max_length = desc->stat_desc->max_length; int h; /* heap index */ int n, m; /* iterate over the tree elements */ int bits; /* bit length */ int xbits; /* extra bits */ ush f; /* frequency */ int overflow = 0; /* number of elements with bit length too large */ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; /* In a first pass, compute the optimal bit lengths (which may * overflow in the case of the bit length tree). */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ for (h = s->heap_max + 1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; tree[n].Len = (ush)bits; /* We overwrite tree[n].Dad which is no longer needed */ if (n > max_code) continue; /* not a leaf node */ s->bl_count[bits]++; xbits = 0; if (n >= base) xbits = extra[n - base]; f = tree[n].Freq; s->opt_len += (ulg)f * (unsigned)(bits + xbits); if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); } if (overflow == 0) return; Tracev((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ do { bits = max_length - 1; while (s->bl_count[bits] == 0) bits--; s->bl_count[bits]--; /* move one leaf down the tree */ s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] */ overflow -= 2; } while (overflow > 0); /* Now recompute all bit lengths, scanning in increasing frequency. * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all * lengths instead of fixing only the wrong ones. This idea is taken * from 'ar' written by Haruhiko Okumura.) */ for (bits = max_length; bits != 0; bits--) { n = s->bl_count[bits]; while (n != 0) { m = s->heap[--h]; if (m > max_code) continue; if ((unsigned) tree[m].Len != (unsigned) bits) { Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq; tree[m].Len = (ush)bits; } n--; } } } #ifdef DUMP_BL_TREE # include #endif /* =========================================================================== * Construct one Huffman tree and assigns the code bit strings and lengths. * Update the total bit length for the current block. * IN assertion: the field freq is set for all tree elements. * OUT assertions: the fields len and code are set to the optimal bit length * and corresponding code. The length opt_len is updated; static_len is * also updated if stree is not null. The field max_code is set. */ local void build_tree(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; const ct_data *stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; int n, m; /* iterate over heap elements */ int max_code = -1; /* largest code with non zero frequency */ int node; /* new node being created */ /* Construct the initial heap, with least frequent element in * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1]. * heap[0] is not used. */ s->heap_len = 0, s->heap_max = HEAP_SIZE; for (n = 0; n < elems; n++) { if (tree[n].Freq != 0) { s->heap[++(s->heap_len)] = max_code = n; s->depth[n] = 0; } else { tree[n].Len = 0; } } /* The pkzip format requires that at least one distance code exists, * and that at least one bit should be sent even if there is only one * possible code. So to avoid special checks later on we force at least * two codes of non zero frequency. */ while (s->heap_len < 2) { node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); tree[node].Freq = 1; s->depth[node] = 0; s->opt_len--; if (stree) s->static_len -= stree[node].Len; /* node is 0 or 1 so it does not have extra bits */ } desc->max_code = max_code; /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); /* Construct the Huffman tree by repeatedly combining the least two * frequent nodes. */ node = elems; /* next internal node of the tree */ do { pqremove(s, tree, n); /* n = node of least frequency */ m = s->heap[SMALLEST]; /* m = node of next least frequency */ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ s->heap[--(s->heap_max)] = m; /* Create a new node father of n and m */ tree[node].Freq = tree[n].Freq + tree[m].Freq; s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? s->depth[n] : s->depth[m]) + 1); tree[n].Dad = tree[m].Dad = (ush)node; #ifdef DUMP_BL_TREE if (tree == s->bl_tree) { fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); } #endif /* and insert the new node in the heap */ s->heap[SMALLEST] = node++; pqdownheap(s, tree, SMALLEST); } while (s->heap_len >= 2); s->heap[--(s->heap_max)] = s->heap[SMALLEST]; /* At this point, the fields freq and dad are set. We can now * generate the bit lengths. */ gen_bitlen(s, (tree_desc *)desc); /* The field len is now set, we can generate the bit codes */ gen_codes ((ct_data *)tree, max_code, s->bl_count); } /* =========================================================================== * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ local void scan_tree(deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; tree[max_code + 1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { s->bl_tree[curlen].Freq += count; } else if (curlen != 0) { if (curlen != prevlen) s->bl_tree[curlen].Freq++; s->bl_tree[REP_3_6].Freq++; } else if (count <= 10) { s->bl_tree[REPZ_3_10].Freq++; } else { s->bl_tree[REPZ_11_138].Freq++; } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ local void send_tree(deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ /* tree[max_code + 1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n + 1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { do { send_code(s, curlen, s->bl_tree); } while (--count != 0); } else if (curlen != 0) { if (curlen != prevlen) { send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2); } else if (count <= 10) { send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3); } else { send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ local int build_bl_tree(deflate_state *s) { int max_blindex; /* index of last bit length code of non zero freq */ /* Determine the bit length frequencies for literal and distance trees */ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); /* Build the bit length tree: */ build_tree(s, (tree_desc *)(&(s->bl_desc))); /* opt_len now includes the length of the tree representations, except the * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format * requires that at least 4 bit length codes be sent. (appnote.txt says * 3 but the actual value used is 4.) */ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); return max_blindex; } /* =========================================================================== * Send the header for a block using dynamic Huffman trees: the counts, the * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ local void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes) { int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ send_bits(s, dcodes - 1, 5); send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } /* =========================================================================== * Send a stored block */ void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int last) { send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */ bi_windup(s); /* align on byte boundary */ put_short(s, (ush)stored_len); put_short(s, (ush)~stored_len); if (stored_len) zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len); s->pending += stored_len; #ifdef ZLIB_DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; s->bits_sent += 2*16; s->bits_sent += stored_len << 3; #endif } /* =========================================================================== * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) */ void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s) { bi_flush(s); } /* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. */ void ZLIB_INTERNAL _tr_align(deflate_state *s) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef ZLIB_DEBUG s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); } /* =========================================================================== * Send the block data compressed using the given Huffman trees */ local void compress_block(deflate_state *s, const ct_data *ltree, const ct_data *dtree) { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ unsigned sx = 0; /* running index in symbol buffers */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ if (s->sym_next != 0) do { #ifdef LIT_MEM dist = s->d_buf[sx]; lc = s->l_buf[sx++]; #else dist = s->sym_buf[sx++] & 0xff; dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; lc = s->sym_buf[sx++]; #endif if (dist == 0) { send_code(s, lc, ltree); /* send a literal byte */ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { /* Here, lc is the match length - MIN_MATCH */ code = _length_code[lc]; send_code(s, code + LITERALS + 1, ltree); /* send length code */ extra = extra_lbits[code]; if (extra != 0) { lc -= base_length[code]; send_bits(s, lc, extra); /* send the extra length bits */ } dist--; /* dist is now the match distance - 1 */ code = d_code(dist); Assert (code < D_CODES, "bad d_code"); send_code(s, code, dtree); /* send the distance code */ extra = extra_dbits[code]; if (extra != 0) { dist -= (unsigned)base_dist[code]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ /* Check for no overlay of pending_buf on needed symbols */ #ifdef LIT_MEM Assert(s->pending < 2 * (s->lit_bufsize + sx), "pendingBuf overflow"); #else Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); #endif } while (sx < s->sym_next); send_code(s, END_BLOCK, ltree); } /* =========================================================================== * Check if the data type is TEXT or BINARY, using the following algorithm: * - TEXT if the two conditions below are satisfied: * a) There are no non-portable control characters belonging to the * "block list" (0..6, 14..25, 28..31). * b) There is at least one printable character belonging to the * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). * - BINARY otherwise. * - The following partially-portable control characters form a * "gray list" that is ignored in this detection algorithm: * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). * IN assertion: the fields Freq of dyn_ltree are set. */ local int detect_data_type(deflate_state *s) { /* block_mask is the bit mask of block-listed bytes * set bits 0..6, 14..25, and 28..31 * 0xf3ffc07f = binary 11110011111111111100000001111111 */ unsigned long block_mask = 0xf3ffc07fUL; int n; /* Check for non-textual ("block-listed") bytes. */ for (n = 0; n <= 31; n++, block_mask >>= 1) if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0)) return Z_BINARY; /* Check for textual ("allow-listed") bytes. */ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 || s->dyn_ltree[13].Freq != 0) return Z_TEXT; for (n = 32; n < LITERALS; n++) if (s->dyn_ltree[n].Freq != 0) return Z_TEXT; /* There are no "block-listed" or "allow-listed" bytes: * this stream either is empty or has tolerated ("gray-listed") bytes only. */ return Z_BINARY; } /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and write out the encoded block. */ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int last) { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex = 0; /* index of last bit length code of non zero freq */ /* Build the Huffman trees unless a stored block is forced */ if (s->level > 0) { /* Check if the file is binary or text */ if (s->strm->data_type == Z_UNKNOWN) s->strm->data_type = detect_data_type(s); /* Construct the literal and distance trees */ build_tree(s, (tree_desc *)(&(s->l_desc))); Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, s->static_len)); build_tree(s, (tree_desc *)(&(s->d_desc))); Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, s->static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ /* Build the bit length tree for the above two trees, and get the index * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute the block lengths in bytes. */ opt_lenb = (s->opt_len + 3 + 7) >> 3; static_lenb = (s->static_len + 3 + 7) >> 3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->sym_next / 3)); #ifndef FORCE_STATIC if (static_lenb <= opt_lenb || s->strategy == Z_FIXED) #endif opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ } #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else if (stored_len + 4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since * the last block flush, because compression would have been * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * transform a block into a stored block. */ _tr_stored_block(s, buf, stored_len, last); } else if (static_lenb == opt_lenb) { send_bits(s, (STATIC_TREES<<1) + last, 3); compress_block(s, (const ct_data *)static_ltree, (const ct_data *)static_dtree); #ifdef ZLIB_DEBUG s->compressed_len += 3 + s->static_len; #endif } else { send_bits(s, (DYN_TREES<<1) + last, 3); send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1, max_blindex + 1); compress_block(s, (const ct_data *)s->dyn_ltree, (const ct_data *)s->dyn_dtree); #ifdef ZLIB_DEBUG s->compressed_len += 3 + s->opt_len; #endif } Assert (s->compressed_len == s->bits_sent, "bad compressed size"); /* The above check is made mod 2^32, for files larger than 512 MB * and uLong implemented on 32 bits. */ init_block(s); if (last) { bi_windup(s); #ifdef ZLIB_DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3, s->compressed_len - 7*last)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) { #ifdef LIT_MEM s->d_buf[s->sym_next] = (ush)dist; s->l_buf[s->sym_next++] = (uch)lc; #else s->sym_buf[s->sym_next++] = (uch)dist; s->sym_buf[s->sym_next++] = (uch)(dist >> 8); s->sym_buf[s->sym_next++] = (uch)lc; #endif if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; } else { s->matches++; /* Here, lc is the match length - MIN_MATCH */ dist--; /* dist = match distance - 1 */ Assert((ush)dist < (ush)MAX_DIST(s) && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } return (s->sym_next == s->sym_end); } fltk-1.4.3/zlib/uncompr.c0000644000175000017500000000553715004135251015406 0ustar albrechtalbrecht/* uncompr.c -- decompress a memory buffer * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #define ZLIB_INTERNAL #include "zlib.h" /* =========================================================================== Decompresses the source buffer into the destination buffer. *sourceLen is the byte length of the source buffer. Upon entry, *destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, *destLen is the size of the decompressed data and *sourceLen is the number of source bytes consumed. Upon return, source + *sourceLen points to the first unused input byte. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted, including if the input data is an incomplete zlib stream. */ int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source, uLong *sourceLen) { z_stream stream; int err; const uInt max = (uInt)-1; uLong len, left; Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */ len = *sourceLen; if (*destLen) { left = *destLen; *destLen = 0; } else { left = 1; dest = buf; } stream.next_in = (z_const Bytef *)source; stream.avail_in = 0; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; stream.opaque = (voidpf)0; err = inflateInit(&stream); if (err != Z_OK) return err; stream.next_out = dest; stream.avail_out = 0; do { if (stream.avail_out == 0) { stream.avail_out = left > (uLong)max ? max : (uInt)left; left -= stream.avail_out; } if (stream.avail_in == 0) { stream.avail_in = len > (uLong)max ? max : (uInt)len; len -= stream.avail_in; } err = inflate(&stream, Z_NO_FLUSH); } while (err == Z_OK); *sourceLen -= len + stream.avail_in; if (dest != buf) *destLen = stream.total_out; else if (stream.total_out && err == Z_BUF_ERROR) left = 1; inflateEnd(&stream); return err == Z_STREAM_END ? Z_OK : err == Z_NEED_DICT ? Z_DATA_ERROR : err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR : err; } int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) { return uncompress2(dest, destLen, source, &sourceLen); } fltk-1.4.3/zlib/zconf.h0000644000175000017500000004254315004135251015045 0ustar albrechtalbrecht/* FLTK *************************************************************** */ /* FLTK Comments marked with FLTK show modifications for FLTK which */ /* FLTK should probably be preserved when zlib is upgraded. */ /* FLTK *************************************************************** */ /* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #ifndef ZCONF_H #define ZCONF_H /* FLTK: enable symbol prefixes, see README.bundled-libs.txt */ #define Z_PREFIX 1 #define z_errmsg fltk_z_errmsg #if ! (defined(_WIN32) || defined(WIN32)) /* FLTK */ # define HAVE_UNISTD_H /* FLTK */ #endif /* FLTK */ /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * Even better than compiling with -DZ_PREFIX would be to use configure to set * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET /* all linked symbols and init macros */ # define _dist_code fltk_z__dist_code # define _length_code fltk_z__length_code # define _tr_align fltk_z__tr_align # define _tr_flush_bits fltk_z__tr_flush_bits # define _tr_flush_block fltk_z__tr_flush_block # define _tr_init fltk_z__tr_init # define _tr_stored_block fltk_z__tr_stored_block # define _tr_tally fltk_z__tr_tally # define adler32 fltk_z_adler32 # define adler32_combine fltk_z_adler32_combine # define adler32_combine64 fltk_z_adler32_combine64 # define adler32_z fltk_z_adler32_z # ifndef Z_SOLO # define compress fltk_z_compress # define compress2 fltk_z_compress2 # define compressBound fltk_z_compressBound # endif # define crc32 fltk_z_crc32 # define crc32_combine fltk_z_crc32_combine # define crc32_combine64 fltk_z_crc32_combine64 # define crc32_combine_gen fltk_z_crc32_combine_gen # define crc32_combine_gen64 fltk_z_crc32_combine_gen64 # define crc32_combine_op fltk_z_crc32_combine_op # define crc32_z fltk_z_crc32_z # define deflate fltk_z_deflate # define deflateBound fltk_z_deflateBound # define deflateCopy fltk_z_deflateCopy # define deflateEnd fltk_z_deflateEnd # define deflateGetDictionary fltk_z_deflateGetDictionary # define deflateInit fltk_z_deflateInit # define deflateInit2 fltk_z_deflateInit2 # define deflateInit2_ fltk_z_deflateInit2_ # define deflateInit_ fltk_z_deflateInit_ # define deflateParams fltk_z_deflateParams # define deflatePending fltk_z_deflatePending # define deflatePrime fltk_z_deflatePrime # define deflateReset fltk_z_deflateReset # define deflateResetKeep fltk_z_deflateResetKeep # define deflateSetDictionary fltk_z_deflateSetDictionary # define deflateSetHeader fltk_z_deflateSetHeader # define deflateTune fltk_z_deflateTune # define deflate_copyright fltk_z_deflate_copyright # define get_crc_table fltk_z_get_crc_table # ifndef Z_SOLO # define gz_error fltk_z_gz_error # define gz_intmax fltk_z_gz_intmax # define gz_strwinerror fltk_z_gz_strwinerror # define gzbuffer fltk_z_gzbuffer # define gzclearerr fltk_z_gzclearerr # define gzclose fltk_z_gzclose # define gzclose_r fltk_z_gzclose_r # define gzclose_w fltk_z_gzclose_w # define gzdirect fltk_z_gzdirect # define gzdopen fltk_z_gzdopen # define gzeof fltk_z_gzeof # define gzerror fltk_z_gzerror # define gzflush fltk_z_gzflush # define gzfread fltk_z_gzfread # define gzfwrite fltk_z_gzfwrite # define gzgetc fltk_z_gzgetc # define gzgetc_ fltk_z_gzgetc_ # define gzgets fltk_z_gzgets # define gzoffset fltk_z_gzoffset # define gzoffset64 fltk_z_gzoffset64 # define gzopen fltk_z_gzopen # define gzopen64 fltk_z_gzopen64 # ifdef _WIN32 # define gzopen_w fltk_z_gzopen_w # endif # define gzprintf fltk_z_gzprintf # define gzputc fltk_z_gzputc # define gzputs fltk_z_gzputs # define gzread fltk_z_gzread # define gzrewind fltk_z_gzrewind # define gzseek fltk_z_gzseek # define gzseek64 fltk_z_gzseek64 # define gzsetparams fltk_z_gzsetparams # define gztell fltk_z_gztell # define gztell64 fltk_z_gztell64 # define gzungetc fltk_z_gzungetc # define gzvprintf fltk_z_gzvprintf # define gzwrite fltk_z_gzwrite # endif # define inflate fltk_z_inflate # define inflateBack fltk_z_inflateBack # define inflateBackEnd fltk_z_inflateBackEnd # define inflateBackInit fltk_z_inflateBackInit # define inflateBackInit_ fltk_z_inflateBackInit_ # define inflateCodesUsed fltk_z_inflateCodesUsed # define inflateCopy fltk_z_inflateCopy # define inflateEnd fltk_z_inflateEnd # define inflateGetDictionary fltk_z_inflateGetDictionary # define inflateGetHeader fltk_z_inflateGetHeader # define inflateInit fltk_z_inflateInit # define inflateInit2 fltk_z_inflateInit2 # define inflateInit2_ fltk_z_inflateInit2_ # define inflateInit_ fltk_z_inflateInit_ # define inflateMark fltk_z_inflateMark # define inflatePrime fltk_z_inflatePrime # define inflateReset fltk_z_inflateReset # define inflateReset2 fltk_z_inflateReset2 # define inflateResetKeep fltk_z_inflateResetKeep # define inflateSetDictionary fltk_z_inflateSetDictionary # define inflateSync fltk_z_inflateSync # define inflateSyncPoint fltk_z_inflateSyncPoint # define inflateUndermine fltk_z_inflateUndermine # define inflateValidate fltk_z_inflateValidate # define inflate_copyright fltk_z_inflate_copyright # define inflate_fast fltk_z_inflate_fast # define inflate_table fltk_z_inflate_table # ifndef Z_SOLO # define uncompress fltk_z_uncompress # define uncompress2 fltk_z_uncompress2 # endif # define zError fltk_z_zError # ifndef Z_SOLO # define zcalloc fltk_z_zcalloc # define zcfree fltk_z_zcfree # endif # define zlibCompileFlags fltk_z_zlibCompileFlags # define zlibVersion fltk_z_zlibVersion /* all zlib typedefs in zlib.h and zconf.h */ # define Byte fltk_z_Byte # define Bytef fltk_z_Bytef # define alloc_func fltk_z_alloc_func # define charf fltk_z_charf # define free_func fltk_z_free_func # ifndef Z_SOLO # define gzFile fltk_z_gzFile # endif # define gz_header fltk_z_gz_header # define gz_headerp fltk_z_gz_headerp # define in_func fltk_z_in_func # define intf fltk_z_intf # define out_func fltk_z_out_func # define uInt fltk_z_uInt # define uIntf fltk_z_uIntf # define uLong fltk_z_uLong # define uLongf fltk_z_uLongf # define voidp fltk_z_voidp # define voidpc fltk_z_voidpc # define voidpf fltk_z_voidpf /* all zlib structs in zlib.h and zconf.h */ # define gz_header_s fltk_z_gz_header_s # define internal_state fltk_z_internal_state #endif /* Z_PREFIX */ /* FLTK */ #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) # define OS2 #endif #if defined(_WINDOWS) && !defined(WINDOWS) # define WINDOWS #endif #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) # ifndef WIN32 # define WIN32 # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # ifndef SYS16BIT # define SYS16BIT # endif # endif #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #ifdef SYS16BIT # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #ifdef __STDC_VERSION__ # ifndef STDC # define STDC # endif # if __STDC_VERSION__ >= 199901L # ifndef STDC99 # define STDC99 # endif # endif #endif #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) # define STDC #endif #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) # define STDC #endif #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) # define STDC #endif #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) # define STDC #endif #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ # define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const /* note: need a more gentle solution here */ # endif #endif #if defined(ZLIB_CONST) && !defined(z_const) # define z_const const #else # define z_const #endif #ifdef Z_SOLO # ifdef _WIN64 typedef unsigned long long z_size_t; # else typedef unsigned long z_size_t; # endif #else # define z_longlong long long # if defined(NO_SIZE_T) typedef unsigned NO_SIZE_T z_size_t; # elif defined(STDC) # include typedef size_t z_size_t; # else typedef unsigned long z_size_t; # endif # undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #ifdef SYS16BIT # if defined(M_I86SM) || defined(M_I86MM) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR _far # else # define FAR far # endif # endif # if (defined(__SMALL__) || defined(__MEDIUM__)) /* Turbo C small or medium model */ # define SMALL_MEDIUM # ifdef __BORLANDC__ # define FAR _far # else # define FAR far # endif # endif #endif #if defined(WINDOWS) || defined(WIN32) /* If building or using zlib as a DLL, define ZLIB_DLL. * This is not mandatory, but it offers a little performance increase. */ # ifdef ZLIB_DLL # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) # ifdef ZLIB_INTERNAL # define ZEXTERN extern __declspec(dllexport) # else # define ZEXTERN extern __declspec(dllimport) # endif # endif # endif /* ZLIB_DLL */ /* If building or using zlib with the WINAPI/WINAPIV calling convention, * define ZLIB_WINAPI. * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 # define ZEXPORTVA WINAPIV # else # define ZEXPORTVA FAR CDECL # endif # endif #endif #if defined (__BEOS__) # ifdef ZLIB_DLL # ifdef ZLIB_INTERNAL # define ZEXPORT __declspec(dllexport) # define ZEXPORTVA __declspec(dllexport) # else # define ZEXPORT __declspec(dllimport) # define ZEXPORTVA __declspec(dllimport) # endif # endif #endif #ifndef ZEXTERN # define ZEXTERN extern #endif #ifndef ZEXPORT # define ZEXPORT #endif #ifndef ZEXPORTVA # define ZEXPORTVA #endif #ifndef FAR # define FAR #endif #if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void const *voidpc; typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte const *voidpc; typedef Byte FAR *voidpf; typedef Byte *voidp; #endif #if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) # include # if (UINT_MAX == 0xffffffffUL) # define Z_U4 unsigned # elif (ULONG_MAX == 0xffffffffUL) # define Z_U4 unsigned long # elif (USHRT_MAX == 0xffffffffUL) # define Z_U4 unsigned short # endif #endif #ifdef Z_U4 typedef Z_U4 z_crc_t; #else typedef unsigned long z_crc_t; #endif #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif #ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_STDARG_H #endif #ifdef STDC # ifndef Z_SOLO # include /* for off_t */ # endif #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO # include /* for va_list */ # endif #endif #ifdef _WIN32 # ifndef Z_SOLO # include /* for wchar_t */ # endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even * though the former does not conform to the LFS document), but considering * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ #if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif #ifndef Z_HAVE_UNISTD_H # ifdef __WATCOMC__ # define Z_HAVE_UNISTD_H # endif #endif #ifndef Z_HAVE_UNISTD_H # if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) # define Z_HAVE_UNISTD_H # endif #endif #ifndef Z_SOLO # if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ # endif # ifndef z_off_t # define z_off_t off_t # endif # endif #endif #if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 # define Z_LFS64 #endif #if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) # define Z_LARGE64 #endif #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) # define Z_WANT64 #endif #if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t # define z_off_t long #endif #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else # if defined(_WIN32) && !defined(__GNUC__) # define z_off64_t __int64 # else # define z_off64_t z_off_t # endif #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) #pragma map(deflateInit_,"DEIN") #pragma map(deflateInit2_,"DEIN2") #pragma map(deflateEnd,"DEEND") #pragma map(deflateBound,"DEBND") #pragma map(inflateInit_,"ININ") #pragma map(inflateInit2_,"ININ2") #pragma map(inflateEnd,"INEND") #pragma map(inflateSync,"INSY") #pragma map(inflateSetDictionary,"INSEDI") #pragma map(compressBound,"CMBND") #pragma map(inflate_table,"INTABL") #pragma map(inflate_fast,"INFA") #pragma map(inflate_copyright,"INCOPY") #endif #endif /* ZCONF_H */ fltk-1.4.3/zlib/gzread.c0000644000175000017500000004673715004135251015206 0ustar albrechtalbrecht/* gzread.c -- zlib functions for reading gzip files * Copyright (C) 2004-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from state->fd, and update state->eof, state->err, and state->msg as appropriate. This function needs to loop on read(), since read() is not guaranteed to read the number of bytes requested, depending on the type of descriptor. */ local int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *have) { int ret; unsigned get, max = ((unsigned)-1 >> 2) + 1; *have = 0; do { get = len - *have; if (get > max) get = max; ret = read(state->fd, buf + *have, get); if (ret <= 0) break; *have += (unsigned)ret; } while (*have < len); if (ret < 0) { gz_error(state, Z_ERRNO, zstrerror()); return -1; } if (ret == 0) state->eof = 1; return 0; } /* Load up input buffer and set eof flag if last data loaded -- return -1 on error, 0 otherwise. Note that the eof flag is set when the end of the input file is reached, even though there may be unused data in the buffer. Once that data has been used, no more attempts will be made to read the file. If strm->avail_in != 0, then the current data is moved to the beginning of the input buffer, and then the remainder of the buffer is loaded with the available data from the input file. */ local int gz_avail(gz_statep state) { unsigned got; z_streamp strm = &(state->strm); if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; if (state->eof == 0) { if (strm->avail_in) { /* copy what's there to the start */ unsigned char *p = state->in; unsigned const char *q = strm->next_in; unsigned n = strm->avail_in; do { *p++ = *q++; } while (--n); } if (gz_load(state, state->in + strm->avail_in, state->size - strm->avail_in, &got) == -1) return -1; strm->avail_in += got; strm->next_in = state->in; } return 0; } /* Look for gzip header, set up for inflate or copy. state->x.have must be 0. If this is the first time in, allocate required memory. state->how will be left unchanged if there is no more input data available, will be set to COPY if there is no gzip header and direct copying will be performed, or it will be set to GZIP for decompression. If direct copying, then leftover input data from the input buffer will be copied to the output buffer. In that case, all further file reads will be directly to either the output buffer or a user buffer. If decompressing, the inflate state will be initialized. gz_look() will return 0 on success or -1 on failure. */ local int gz_look(gz_statep state) { z_streamp strm = &(state->strm); /* allocate read buffers and inflate memory */ if (state->size == 0) { /* allocate buffers */ state->in = (unsigned char *)malloc(state->want); state->out = (unsigned char *)malloc(state->want << 1); if (state->in == NULL || state->out == NULL) { free(state->out); free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } state->size = state->want; /* allocate inflate memory */ state->strm.zalloc = Z_NULL; state->strm.zfree = Z_NULL; state->strm.opaque = Z_NULL; state->strm.avail_in = 0; state->strm.next_in = Z_NULL; if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ free(state->out); free(state->in); state->size = 0; gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } } /* get at least the magic bytes in the input buffer */ if (strm->avail_in < 2) { if (gz_avail(state) == -1) return -1; if (strm->avail_in == 0) return 0; } /* look for gzip magic bytes -- if there, do gzip decoding (note: there is a logical dilemma here when considering the case of a partially written gzip file, to wit, if a single 31 byte is written, then we cannot tell whether this is a single-byte file, or just a partially written gzip file -- for here we assume that if a gzip file is being written, then the header will be written in a single operation, so that reading a single byte is sufficient indication that it is not a gzip file) */ if (strm->avail_in > 1 && strm->next_in[0] == 31 && strm->next_in[1] == 139) { inflateReset(strm); state->how = GZIP; state->direct = 0; return 0; } /* no gzip header -- if we were decoding gzip before, then this is trailing garbage. Ignore the trailing garbage and finish. */ if (state->direct == 0) { strm->avail_in = 0; state->eof = 1; state->x.have = 0; return 0; } /* doing raw i/o, copy any leftover input to output -- this assumes that the output buffer is larger than the input buffer, which also assures space for gzungetc() */ state->x.next = state->out; memcpy(state->x.next, strm->next_in, strm->avail_in); state->x.have = strm->avail_in; strm->avail_in = 0; state->how = COPY; state->direct = 1; return 0; } /* Decompress from input to the provided next_out and avail_out in the state. On return, state->x.have and state->x.next point to the just decompressed data. If the gzip stream completes, state->how is reset to LOOK to look for the next gzip stream or raw data, once state->x.have is depleted. Returns 0 on success, -1 on failure. */ local int gz_decomp(gz_statep state) { int ret = Z_OK; unsigned had; z_streamp strm = &(state->strm); /* fill output buffer up to end of deflate stream */ had = strm->avail_out; do { /* get more input for inflate() */ if (strm->avail_in == 0 && gz_avail(state) == -1) return -1; if (strm->avail_in == 0) { gz_error(state, Z_BUF_ERROR, "unexpected end of file"); break; } /* decompress and handle errors */ ret = inflate(strm, Z_NO_FLUSH); if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { gz_error(state, Z_STREAM_ERROR, "internal error: inflate stream corrupt"); return -1; } if (ret == Z_MEM_ERROR) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ gz_error(state, Z_DATA_ERROR, strm->msg == NULL ? "compressed data error" : strm->msg); return -1; } } while (strm->avail_out && ret != Z_STREAM_END); /* update available output */ state->x.have = had - strm->avail_out; state->x.next = strm->next_out - state->x.have; /* if the gzip stream completed successfully, look for another */ if (ret == Z_STREAM_END) state->how = LOOK; /* good decompression */ return 0; } /* Fetch data and put it in the output buffer. Assumes state->x.have is 0. Data is either copied from the input file or decompressed from the input file depending on state->how. If state->how is LOOK, then a gzip header is looked for to determine whether to copy or decompress. Returns -1 on error, otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the end of the input file has been reached and all data has been processed. */ local int gz_fetch(gz_statep state) { z_streamp strm = &(state->strm); do { switch(state->how) { case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ if (gz_look(state) == -1) return -1; if (state->how == LOOK) return 0; break; case COPY: /* -> COPY */ if (gz_load(state, state->out, state->size << 1, &(state->x.have)) == -1) return -1; state->x.next = state->out; return 0; case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ strm->avail_out = state->size << 1; strm->next_out = state->out; if (gz_decomp(state) == -1) return -1; } } while (state->x.have == 0 && (!state->eof || strm->avail_in)); return 0; } /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ local int gz_skip(gz_statep state, z_off64_t len) { unsigned n; /* skip over len bytes or reach end-of-file, whichever comes first */ while (len) /* skip over whatever is in output buffer */ if (state->x.have) { n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? (unsigned)len : state->x.have; state->x.have -= n; state->x.next += n; state->x.pos += n; len -= n; } /* output buffer empty -- return if we're at the end of the input */ else if (state->eof && state->strm.avail_in == 0) break; /* need more data to skip -- load up output buffer */ else { /* get more output, looking for header if required */ if (gz_fetch(state) == -1) return -1; } return 0; } /* Read len bytes into buf from file, or less than len up to the end of the input. Return the number of bytes read. If zero is returned, either the end of file was reached, or there was an error. state->err must be consulted in that case to determine which. */ local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { z_size_t got; unsigned n; /* if len is zero, avoid unnecessary operations */ if (len == 0) return 0; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return 0; } /* get len bytes to buf, or less than len if at the end */ got = 0; do { /* set n to the maximum amount of len that fits in an unsigned int */ n = (unsigned)-1; if (n > len) n = (unsigned)len; /* first just try copying data from the output buffer */ if (state->x.have) { if (state->x.have < n) n = state->x.have; memcpy(buf, state->x.next, n); state->x.next += n; state->x.have -= n; } /* output buffer empty -- return if we're at the end of the input */ else if (state->eof && state->strm.avail_in == 0) { state->past = 1; /* tried to read past end */ break; } /* need output data -- for small len or new stream load up our output buffer */ else if (state->how == LOOK || n < (state->size << 1)) { /* get more output, looking for header if required */ if (gz_fetch(state) == -1) return 0; continue; /* no progress yet -- go back to copy above */ /* the copy above assures that we will leave with space in the output buffer, allowing at least one gzungetc() to succeed */ } /* large len -- read directly into user buffer */ else if (state->how == COPY) { /* read directly */ if (gz_load(state, (unsigned char *)buf, n, &n) == -1) return 0; } /* large len -- decompress directly into user buffer */ else { /* state->how == GZIP */ state->strm.avail_out = n; state->strm.next_out = (unsigned char *)buf; if (gz_decomp(state) == -1) return 0; n = state->x.have; state->x.have = 0; } /* update progress */ len -= n; buf = (char *)buf + n; got += n; state->x.pos += n; } while (len); /* return number of bytes read into user buffer */ return got; } /* -- see zlib.h -- */ int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids a flaw in the interface) */ if ((int)len < 0) { gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); return -1; } /* read len or fewer bytes to buf */ len = (unsigned)gz_read(state, buf, len); /* check for an error */ if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; /* return the number of bytes read (this is assured to fit in an int) */ return (int)len; } /* -- see zlib.h -- */ z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) { z_size_t len; gz_statep state; /* get internal structure */ if (file == NULL) return 0; state = (gz_statep)file; /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return 0; /* compute bytes to read -- error on overflow */ len = nitems * size; if (size && len / size != nitems) { gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); return 0; } /* read len or fewer bytes to buf, return the number of full items read */ return len ? gz_read(state, buf, len) / size : 0; } /* -- see zlib.h -- */ #ifdef Z_PREFIX_SET # undef fltk_z_gzgetc /* FLTK */ #else # undef gzgetc #endif int ZEXPORT gzgetc(gzFile file) { unsigned char buf[1]; gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* try output buffer (no need to check for skip request) */ if (state->x.have) { state->x.have--; state->x.pos++; return *(state->x.next)++; } /* nothing there -- try gz_read() */ return gz_read(state, buf, 1) < 1 ? -1 : buf[0]; } int ZEXPORT gzgetc_(gzFile file) { return gzgetc(file); } /* -- see zlib.h -- */ int ZEXPORT gzungetc(int c, gzFile file) { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* in case this was just opened, set up the input buffer */ if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) (void)gz_look(state); /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return -1; } /* can't push EOF */ if (c < 0) return -1; /* if output buffer empty, put byte at end (allows more pushing) */ if (state->x.have == 0) { state->x.have = 1; state->x.next = state->out + (state->size << 1) - 1; state->x.next[0] = (unsigned char)c; state->x.pos--; state->past = 0; return c; } /* if no room, give up (must have already done a gzungetc()) */ if (state->x.have == (state->size << 1)) { gz_error(state, Z_DATA_ERROR, "out of room to push characters"); return -1; } /* slide output data if needed and insert byte before existing data */ if (state->x.next == state->out) { unsigned char *src = state->out + state->x.have; unsigned char *dest = state->out + (state->size << 1); while (src > state->out) *--dest = *--src; state->x.next = dest; } state->x.have++; state->x.next--; state->x.next[0] = (unsigned char)c; state->x.pos--; state->past = 0; return c; } /* -- see zlib.h -- */ char * ZEXPORT gzgets(gzFile file, char *buf, int len) { unsigned left, n; char *str; unsigned char *eol; gz_statep state; /* check parameters and get internal structure */ if (file == NULL || buf == NULL || len < 1) return NULL; state = (gz_statep)file; /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return NULL; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return NULL; } /* copy output bytes up to new line or len - 1, whichever comes first -- append a terminating zero to the string (we don't check for a zero in the contents, let the user worry about that) */ str = buf; left = (unsigned)len - 1; if (left) do { /* assure that something is in the output buffer */ if (state->x.have == 0 && gz_fetch(state) == -1) return NULL; /* error */ if (state->x.have == 0) { /* end of file */ state->past = 1; /* read past end */ break; /* return what we have */ } /* look for end-of-line in current output buffer */ n = state->x.have > left ? left : state->x.have; eol = (unsigned char *)memchr(state->x.next, '\n', n); if (eol != NULL) n = (unsigned)(eol - state->x.next) + 1; /* copy through end-of-line, or remainder if not found */ memcpy(buf, state->x.next, n); state->x.have -= n; state->x.next += n; state->x.pos += n; left -= n; buf += n; } while (left && eol == NULL); /* return terminated string, or if nothing, end of file */ if (buf == str) return NULL; buf[0] = 0; return str; } /* -- see zlib.h -- */ int ZEXPORT gzdirect(gzFile file) { gz_statep state; /* get internal structure */ if (file == NULL) return 0; state = (gz_statep)file; /* if the state is not known, but we can find out, then do so (this is mainly for right after a gzopen() or gzdopen()) */ if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) (void)gz_look(state); /* return 1 if transparent, 0 if processing a gzip stream */ return state->direct; } /* -- see zlib.h -- */ int ZEXPORT gzclose_r(gzFile file) { int ret, err; gz_statep state; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're reading */ if (state->mode != GZ_READ) return Z_STREAM_ERROR; /* free memory and close file */ if (state->size) { inflateEnd(&(state->strm)); free(state->out); free(state->in); } err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; gz_error(state, Z_OK, NULL); free(state->path); ret = close(state->fd); free(state); return ret ? Z_ERRNO : err; } fltk-1.4.3/src/0000755000175000017500000000000015004135251013374 5ustar albrechtalbrechtfltk-1.4.3/src/Fl_Anim_GIF_Image.cxx0000644000175000017500000011123015004135251017212 0ustar albrechtalbrecht// // Fl_Anim_GIF_Image class for the Fast Light Tool Kit (FLTK). // // Copyright 2016-2023 by Christian Grabner . // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include // round() #include /** \class Fl_Anim_GIF_Image The Fl_Anim_GIF_Image class supports loading, caching, and drawing of animated Compuserve GIFSM images. The class loads all images contained in the file and animates them by cycling through them as defined by the delay times in the image file. The user must supply an FLTK widget as "container" in order to see the animation by specifying it in the constructor or later using the canvas() method. */ /*static*/ bool Fl_GIF_Image::animate = false; /////////////////////////////////////////////////////////////////////// // Internal helper classes/structs /////////////////////////////////////////////////////////////////////// class Fl_Anim_GIF_Image::FrameInfo { friend class Fl_Anim_GIF_Image; enum Transparency { T_NONE = 0xff, T_FULL = 0 }; struct RGBA_Color { uchar r, g, b, alpha; RGBA_Color(uchar r = 0, uchar g = 0, uchar b = 0, uchar a = T_NONE) : r(r), g(g), b(b), alpha(a) {} }; enum Dispose { DISPOSE_UNDEF = 0, DISPOSE_NOT = 1, DISPOSE_BACKGROUND = 2, DISPOSE_PREVIOUS = 3 }; struct GifFrame { GifFrame() : rgb(0), scalable(0), average_color(FL_BLACK), average_weight(-1), desaturated(false), x(0), y(0), w(0), h(0), delay(0), dispose(DISPOSE_UNDEF), transparent_color_index(-1) {} Fl_RGB_Image *rgb; // full frame image Fl_Shared_Image *scalable; // used for hardware-accelerated scaling Fl_Color average_color; // last average color float average_weight; // last average weight bool desaturated; // flag if frame is desaturated unsigned short x, y, w, h; // frame original dimensions double delay; // delay (already converted to ms) Dispose dispose; // disposal method int transparent_color_index; // needed for dispose() RGBA_Color transparent_color; // needed for dispose() }; FrameInfo(Fl_Anim_GIF_Image *anim) : anim(anim), valid(false), frames_size(0), frames(0), loop_count(1), loop(0), background_color_index(-1), canvas_w(0), canvas_h(0), desaturate(false), average_color(FL_BLACK), average_weight(-1), scaling((Fl_RGB_Scaling)0), debug_(0), optimize_mem(false), offscreen(0) {} ~FrameInfo(); void clear(); void copy(const FrameInfo& fi); double convert_delay(int d) const; int debug() const { return debug_; } bool load(const char *name, const unsigned char *data, size_t length); bool push_back_frame(const GifFrame &frame); void resize(int W, int H); void scale_frame(int frame); void set_frame(int frame); private: Fl_Anim_GIF_Image *anim; // a pointer to the Image (only needed for name()) bool valid; // flag if valid data int frames_size; // number of frames stored in 'frames' GifFrame *frames; // "vector" for frames int loop_count; // loop count from file int loop; // current loop count int background_color_index; // needed for dispose() RGBA_Color background_color; // needed for dispose() GifFrame frame; // current processed frame int canvas_w; // width of GIF from header int canvas_h; // height of GIF from header bool desaturate; // flag if frames should be desaturated Fl_Color average_color; // color for color_average() float average_weight; // weight for color_average (negative: none) Fl_RGB_Scaling scaling; // saved scaling method for scale_frame() int debug_; // Flag for debug outputs bool optimize_mem; // Flag to store frames in original dimensions uchar *offscreen; // internal "offscreen" buffer private: private: void dispose(int frame_); void on_frame_data(Fl_GIF_Image::GIF_FRAME &gf); void on_extension_data(Fl_GIF_Image::GIF_FRAME &gf); void set_to_background(int frame_); }; #define LOG(x) if (debug()) printf x #define DEBUG(x) if (debug() >= 2) printf x #ifndef LOG #define LOG(x) #endif #ifndef DEBUG #define DEBUG(x) #endif // // helper class FrameInfo implementation // Fl_Anim_GIF_Image::FrameInfo::~FrameInfo() { clear(); } void Fl_Anim_GIF_Image::FrameInfo::clear() { // release all allocated memory while (frames_size-- > 0) { if (frames[frames_size].scalable) frames[frames_size].scalable->release(); delete frames[frames_size].rgb; } delete[] offscreen; offscreen = 0; free(frames); frames = 0; frames_size = 0; } double Fl_Anim_GIF_Image::FrameInfo::convert_delay(int d) const { if (d <= 0) d = loop_count != 1 ? 10 : 0; return (double)d / 100; } void Fl_Anim_GIF_Image::FrameInfo::copy(const FrameInfo& fi) { // copy from source for (int i = 0; i < fi.frames_size; i++) { if (!push_back_frame(fi.frames[i])) { break; } double scale_factor_x = (double)canvas_w / (double)fi.canvas_w; double scale_factor_y = (double)canvas_h / (double)fi.canvas_h; if (fi.optimize_mem) { frames[i].x = (unsigned short)round(fi.frames[i].x * scale_factor_x); frames[i].y = (unsigned short)round(fi.frames[i].y * scale_factor_y); int new_w = (int)round(fi.frames[i].w * scale_factor_x); int new_h = (int)round(fi.frames[i].h * scale_factor_y); frames[i].w = new_w; frames[i].h = new_h; } // just copy data 1:1 now - scaling will be done adhoc when frame is displayed frames[i].rgb = (Fl_RGB_Image *)fi.frames[i].rgb->copy(); frames[i].scalable = 0; } optimize_mem = fi.optimize_mem; scaling = Fl_Image::RGB_scaling(); // save current scaling mode loop_count = fi.loop_count; // .. and the loop_count! } void Fl_Anim_GIF_Image::FrameInfo::dispose(int frame) { if (frame < 0) { return; } // dispose frame with index 'frame_' to offscreen buffer switch (frames[frame].dispose) { case DISPOSE_PREVIOUS: { // dispose to previous restores to first not DISPOSE_TO_PREVIOUS frame int prev(frame); while (prev > 0 && frames[prev].dispose == DISPOSE_PREVIOUS) prev--; if (prev == 0 && frames[prev].dispose == DISPOSE_PREVIOUS) { set_to_background(frame); return; } DEBUG((" dispose frame %d to previous frame %d\n", frame + 1, prev + 1)); // copy the previous image data.. uchar *dst = offscreen; int px = frames[prev].x; int py = frames[prev].y; int pw = frames[prev].w; int ph = frames[prev].h; const char *src = frames[prev].rgb->data()[0]; if (px == 0 && py == 0 && pw == canvas_w && ph == canvas_h) memcpy((char *)dst, (char *)src, canvas_w * canvas_h * 4); else { if ( px + pw > canvas_w ) pw = canvas_w - px; if ( py + ph > canvas_h ) ph = canvas_h - py; for (int y = 0; y < ph; y++) { memcpy(dst + ( y + py ) * canvas_w * 4 + px, src + y * frames[prev].w * 4, pw * 4); } } break; } case DISPOSE_BACKGROUND: DEBUG((" dispose frame %d to background\n", frame + 1)); set_to_background(frame); break; default: { // nothing to do (keep everything as is) break; } } } bool Fl_Anim_GIF_Image::FrameInfo::load(const char *name, const unsigned char *data, size_t length) { // decode using FLTK valid = false; anim->ld(0); if (data) { anim->Fl_GIF_Image::load(name, data, length, true); // calls on_frame_data() for each frame } else { anim->Fl_GIF_Image::load(name, true); // calls on_frame_data() for each frame } delete[] offscreen; offscreen = 0; return valid; } void Fl_Anim_GIF_Image::FrameInfo::on_extension_data(Fl_GIF_Image::GIF_FRAME &gf) { if (!gf.bptr) return; const uchar *ext = gf.bptr; if (memcmp(ext, "NETSCAPE2.0", 11) == 0) { const uchar *params = &ext[11]; loop_count = params[1] | (params[2] << 8); DEBUG(("netscape loop count: %u\n", loop_count)); } } void Fl_Anim_GIF_Image::FrameInfo::on_frame_data(Fl_GIF_Image::GIF_FRAME &gf) { if (!gf.bptr) return; int delay = gf.delay; if (delay <= 0) delay = -(delay + 1); LOG(("on_frame_data: frame #%d/%d, %dx%d at %d/%d, delay: %d, bkgd=%d/%d, trans=%d, dispose=%d\n", gf.ifrm + 1, -1, gf.w, gf.h, gf.x, gf.y, gf.delay, gf.bkgd, gf.clrs, gf.trans, gf.dispose)); if (!gf.ifrm) { // first frame, get width/height valid = true; // may be reset later from loading callback canvas_w = gf.width; canvas_h = gf.height; offscreen = new uchar[canvas_w * canvas_h * 4]; memset(offscreen, 0, canvas_w * canvas_h * 4); } if (!gf.ifrm) { // store background_color AFTER color table is set background_color_index = gf.clrs && gf.bkgd < gf.clrs ? gf.bkgd : -1; if (background_color_index >= 0) { background_color = RGBA_Color(gf.cpal[background_color_index].r, gf.cpal[background_color_index].g, gf.cpal[background_color_index].b); } } // process frame frame.x = gf.x; frame.y = gf.y; frame.w = gf.w; frame.h = gf.h; frame.delay = convert_delay(delay); frame.transparent_color_index = gf.trans && gf.trans < gf.clrs ? gf.trans : -1; frame.dispose = (Dispose)gf.dispose; if (frame.transparent_color_index >= 0) { frame.transparent_color = RGBA_Color(gf.cpal[frame.transparent_color_index].r, gf.cpal[frame.transparent_color_index].g, gf.cpal[frame.transparent_color_index].b); } DEBUG(("#%d %d/%d %dx%d delay: %d, dispose: %d transparent_color: %d\n", (int)frames_size + 1, frame.x, frame.y, frame.w, frame.h, gf.delay, gf.dispose, gf.trans)); // we know now everything we need about the frame.. dispose(frames_size - 1); // copy image data to offscreen const uchar *bits = gf.bptr; const uchar *endp = offscreen + canvas_w * canvas_h * 4; for (int y = frame.y; y < frame.y + frame.h; y++) { for (int x = frame.x; x < frame.x + frame.w; x++) { uchar c = *bits++; if (c == gf.trans) continue; uchar *buf = offscreen; buf += (y * canvas_w * 4 + (x * 4)); if (buf >= endp) continue; *buf++ = gf.cpal[c].r; *buf++ = gf.cpal[c].g; *buf++ = gf.cpal[c].b; *buf = T_NONE; } } // create RGB image from offscreen if (optimize_mem) { uchar *buf = new uchar[frame.w * frame.h * 4]; uchar *dest = buf; for (int y = frame.y; y < frame.y + frame.h; y++) { for (int x = frame.x; x < frame.x + frame.w; x++) { if (offscreen + y * canvas_w * 4 + x * 4 < endp) memcpy(dest, &offscreen[y * canvas_w * 4 + x * 4], 4); dest += 4; } } frame.rgb = new Fl_RGB_Image(buf, frame.w, frame.h, 4); } else { uchar *buf = new uchar[canvas_w * canvas_h * 4]; memcpy(buf, offscreen, canvas_w * canvas_h * 4); frame.rgb = new Fl_RGB_Image(buf, canvas_w, canvas_h, 4); } frame.rgb->alloc_array = 1; if (!push_back_frame(frame)) { valid = false; } } bool Fl_Anim_GIF_Image::FrameInfo::push_back_frame(const GifFrame &frame) { void *tmp = realloc(frames, sizeof(GifFrame) * (frames_size + 1)); if (!tmp) { return false; } frames = (GifFrame *)tmp; memcpy(&frames[frames_size], &frame, sizeof(GifFrame)); frames_size++; return true; } void Fl_Anim_GIF_Image::FrameInfo::resize(int W, int H) { double scale_factor_x = (double)W / (double)canvas_w; double scale_factor_y = (double)H / (double)canvas_h; for (int i=0; i < frames_size; i++) { if (optimize_mem) { frames[i].x = (unsigned short)round(frames[i].x * scale_factor_x); frames[i].y = (unsigned short)round(frames[i].y * scale_factor_y); int new_w = (int)round(frames[i].w * scale_factor_x); int new_h = (int)round(frames[i].h * scale_factor_y); frames[i].w = new_w; frames[i].h = new_h; } } canvas_w = W; canvas_h = H; } void Fl_Anim_GIF_Image::FrameInfo::scale_frame(int frame) { // Do the actual scaling after a resize if neccessary int new_w = optimize_mem ? frames[frame].w : canvas_w; int new_h = optimize_mem ? frames[frame].h : canvas_h; if (frames[frame].scalable && frames[frame].scalable->w() == new_w && frames[frame].scalable->h() == new_h) return; Fl_RGB_Scaling old_scaling = Fl_Image::RGB_scaling(); // save current scaling method Fl_Image::RGB_scaling(scaling); if (!frames[frame].scalable) { frames[frame].scalable = Fl_Shared_Image::get(frames[frame].rgb, 0); } frames[frame].scalable->scale(new_w, new_h, 0, 1); Fl_Image::RGB_scaling(old_scaling); // restore scaling method } void Fl_Anim_GIF_Image::FrameInfo::set_to_background(int frame) { // reset offscreen to background color int bg = background_color_index; int tp = frame >= 0 ? frames[frame].transparent_color_index : bg; DEBUG((" set_to_background [%d] tp = %d, bg = %d\n", frame, tp, bg)); RGBA_Color color = background_color; if (tp >= 0) color = frames[frame].transparent_color; if (tp >= 0 && bg >= 0) bg = tp; color.alpha = tp == bg ? T_FULL : tp < 0 ? T_FULL : T_NONE; DEBUG((" set to color %d/%d/%d alpha=%d\n", color.r, color.g, color.b, color.alpha)); for (uchar *p = offscreen + canvas_w * canvas_h * 4 - 4; p >= offscreen; p -= 4) memcpy(p, &color, 4); } void Fl_Anim_GIF_Image::FrameInfo::set_frame(int frame) { // scaling pending? scale_frame(frame); // color average pending? if (average_weight >= 0 && average_weight < 1 && ((average_color != frames[frame].average_color) || (average_weight != frames[frame].average_weight))) { frames[frame].rgb->color_average(average_color, average_weight); frames[frame].average_color = average_color; frames[frame].average_weight = average_weight; } // desaturate pending? if (desaturate && !frames[frame].desaturated) { frames[frame].rgb->desaturate(); frames[frame].desaturated = true; } } /////////////////////////////////////////////////////////////////////// // // Fl_Anim_GIF_Image // // An extension to Fl_GIF_Image. // /////////////////////////////////////////////////////////////////////// // // Fl_Anim_GIF_Image global variables // /*static*/ double Fl_Anim_GIF_Image::min_delay = 0.; /*static*/ bool Fl_Anim_GIF_Image::loop = true; #include #include #include #include #include // // class Fl_Anim_GIF_Image implementation // /** Load an animated GIF image from a file. This constructor creates an animated image from a GIF-formatted file. Optionally it applies the \ref canvas() method after successful load. If \ref DONT_START is not specified in the \p flags parameter it calls \ref start() after successful load. \param[in] filename path and name of GIF file in the file system \param[in] canvas a widget that will show and animate the GIF, or \c NULL \param[in] flags see \ref Flags for details, or 0 \note The GIF image must be decoupled from the canvas by calling `myGif->canvas(NULL);` before deleting the canvas. */ Fl_Anim_GIF_Image::Fl_Anim_GIF_Image(const char *filename, Fl_Widget *canvas /* = 0*/, unsigned short flags /* = 0 */) : Fl_GIF_Image(), name_(0), flags_(flags), canvas_(canvas), uncache_(false), valid_(false), frame_(-1), speed_(1.), fi_(new FrameInfo(this)) { fi_->debug_ = ((flags_ & LOG_FLAG) != 0) + 2 * ((flags_ & DEBUG_FLAG) != 0); fi_->optimize_mem = (flags_ & OPTIMIZE_MEMORY); valid_ = load(filename, NULL, 0); if (canvas_w() && canvas_h()) { if (!w() && !h()) { w(canvas_w()); h(canvas_h()); } } this->canvas(canvas, flags); if (!(flags & DONT_START)) start(); else frame_ = 0; } /** Load an animated GIF image from memory. This constructor creates an animated image from a GIF-formatted block in memory. Optionally it applies the \ref canvas() method after successful load. If \ref DONT_START is not specified in the \p flags parameter it calls \ref start() after successful load. \p imagename can be \c NULL. If a name is given, the image is added to the list of shared images and will be available by that name. \param[in] imagename a name given to this image or \c NULL \param[in] data pointer to the start of the GIF image in memory \param[in] length length of the GIF image in memory \param[in] canvas a widget that will show and animate the GIF, or \c NULL \param[in] flags see \ref Flags for details, or 0 \note The GIF image must be decoupled from the canvas by calling `myGif->canvas(NULL);` before deleting the canvas. */ Fl_Anim_GIF_Image::Fl_Anim_GIF_Image(const char* imagename, const unsigned char *data, const size_t length, Fl_Widget *canvas /* = 0 */, unsigned short flags /* = 0 */) : Fl_GIF_Image(), name_(0), flags_(flags), canvas_(canvas), uncache_(false), valid_(false), frame_(-1), speed_(1.), fi_(new FrameInfo(this)) { fi_->debug_ = ((flags_ & LOG_FLAG) != 0) + 2 * ((flags_ & DEBUG_FLAG) != 0); fi_->optimize_mem = (flags_ & OPTIMIZE_MEMORY); valid_ = load(imagename, data, length); if (canvas_w() && canvas_h()) { if (!w() && !h()) { w(canvas_w()); h(canvas_h()); } } this->canvas(canvas, flags); if (!(flags & DONT_START)) start(); else frame_ = 0; } /** Create an empty animated GIF image shell. */ Fl_Anim_GIF_Image::Fl_Anim_GIF_Image() : Fl_GIF_Image(), name_(0), flags_(0), canvas_(0), uncache_(false), valid_(false), frame_(-1), speed_(1.), fi_(new FrameInfo(this)) { } /** Release the image and all cached data. Also removes the animation timer. */ Fl_Anim_GIF_Image::~Fl_Anim_GIF_Image() /* override */ { Fl::remove_timeout(cb_animate, this); delete fi_; free(name_); } /** Link the image back to a widget for automated animation. This method sets current widget, that is used to display the frame images. The \p flags parameter specifies whether the canvas widget is resized to the animation dimensions and/or its \ref image() method will be used to set the current frame image during animation. \param[in] canvas a pointer to the widget that will show the animation \param[in] flags see \ref Flags \note The GIF image must be decoupled from the canvas by calling `myGif->canvas(NULL);` before deleting the canvas. */ void Fl_Anim_GIF_Image::canvas(Fl_Widget *canvas, unsigned short flags/* = 0*/) { if (canvas_) canvas_->image(0); canvas_ = canvas; if (canvas_ && !(flags & DONT_SET_AS_IMAGE)) canvas_->image(this); // set animation as image() of canvas if (canvas_ && !(flags & DONT_RESIZE_CANVAS)) canvas_->size(w(), h()); if (flags_ != flags) { flags_ = flags; fi_->debug_ = ((flags & LOG_FLAG) != 0) + 2 * ((flags & DEBUG_FLAG) != 0); } // Note: 'Start' flag is *NOT* used here, // but an already running animation is restarted. frame_ = -1; if (Fl::has_timeout(cb_animate, this)) { Fl::remove_timeout(cb_animate, this); next_frame(); } else if ( fi_->frames_size ) { set_frame(0); } } /** Gets the current widget, that is used to display the frame images. \return a pointer to a widget */ Fl_Widget *Fl_Anim_GIF_Image::canvas() const { return canvas_; } /** Return the width of the animation canvas. \return the width in pixel units */ int Fl_Anim_GIF_Image::canvas_w() const { return fi_->canvas_w; } /** Return the height of the animation canvas. \return the width in pixel units */ int Fl_Anim_GIF_Image::canvas_h() const { return fi_->canvas_h; } /*static*/ void Fl_Anim_GIF_Image::cb_animate(void *d) { Fl_Anim_GIF_Image *b = (Fl_Anim_GIF_Image *)d; b->next_frame(); } void Fl_Anim_GIF_Image::clear_frames() { fi_->clear(); valid_ = false; } /** Applies a color average to all frames. The color_average() method averages the colors in the image with the provided FLTK color value. \param[in] c blend color \param[in] i a value between 0.0 and 1.0 where 0 results in the blend color, and 1 returns the original image */ void Fl_Anim_GIF_Image::color_average(Fl_Color c, float i) /* override */ { if (i < 0) { // immediate mode i = -i; for (int f=0; f < frames(); f++) { fi_->frames[f].rgb->color_average(c, i); } return; } fi_->average_color = c; fi_->average_weight = i; // Do not call set_frame()! If this is called with an indexed color before // the display connection is open, it will possible average *this* frame // with a different RGB value than the following frames. // See Fl_Image::inactive(). // set_frame(); } /** Copy and resize the animation frames. The virtual copy() method makes a copy of the animated image and resizes all of its frame images to W x H using the current resize method. \param[in] W, H new size in FLTK pixel units \return the resized copy of the animation */ Fl_Image *Fl_Anim_GIF_Image::copy(int W, int H) const /* override */ { Fl_Anim_GIF_Image *copied = new Fl_Anim_GIF_Image(); // copy/resize the base image (Fl_Pixmap) // Note: this is not really necessary, if the draw() // method never calls the base class. if (fi_->frames_size) { Fl_Pixmap *gif = (Fl_Pixmap *)Fl_GIF_Image::copy(W, H); copied->Fl_GIF_Image::data(gif->data(), gif->count()); copied->alloc_data = gif->alloc_data; gif->alloc_data = 0; delete gif; } if (name_) copied->name_ = fl_strdup(name_); copied->flags_ = flags_; copied->frame_ = frame_; copied->speed_ = speed_; copied->w(W); copied->h(H); copied->fi_->canvas_w = W; copied->fi_->canvas_h = H; copied->fi_->copy(*fi_); // copy the meta data copied->uncache_ = uncache_; // copy 'inherits' frame uncache status copied->valid_ = valid_ && copied->fi_->frames_size == fi_->frames_size; copied->scale_frame(); // scale current frame now if (copied->valid_ && frame_ >= 0 && !Fl::has_timeout(cb_animate, copied)) copied->start(); // start if original also was started return copied; } int Fl_Anim_GIF_Image::debug() const { return fi_->debug(); } /** Return the delay of frame `[0-frames() -1]` in seconds. \param[in] frame index into frame list \return delay to next frame in seconds */ double Fl_Anim_GIF_Image::delay(int frame) const { if (frame >= 0 && frame < frames()) return fi_->frames[frame].delay; return 0.; } /** Set the delay of frame `[0-frames() -1]` in seconds. \param[in] frame index into frame list \param[in] delay to next frame in seconds */ void Fl_Anim_GIF_Image::delay(int frame, double delay) { if (frame >= 0 && frame < frames()) fi_->frames[frame].delay = delay; } /** Desaturate to all frames of the animation. */ void Fl_Anim_GIF_Image::desaturate() /* override */ { fi_->desaturate = true; set_frame(); } /** Draw the current frame of the animation. \param[in] x, y, w, h target rectangle \param[in] cx, cy source offset */ void Fl_Anim_GIF_Image::draw(int x, int y, int w, int h, int cx/* = 0*/, int cy/* = 0*/) /* override */ { if (this->image()) { if (fi_->optimize_mem) { int f0 = frame_; while (f0 > 0 && !(fi_->frames[f0].x == 0 && fi_->frames[f0].y == 0 && fi_->frames[f0].w == this->w() && fi_->frames[f0].h == this->h())) --f0; for (int f = f0; f <= frame_; f++) { if (f < frame_ && fi_->frames[f].dispose == FrameInfo::DISPOSE_PREVIOUS) continue; if (f < frame_ && fi_->frames[f].dispose == FrameInfo::DISPOSE_BACKGROUND) continue; Fl_RGB_Image *rgb = fi_->frames[f].rgb; if (rgb) { float s = Fl_Graphics_Driver::default_driver().scale(); rgb->scale(int(s*fi_->frames[f].w), int(s*fi_->frames[f].h), 0, 1); rgb->draw(int(x + s*fi_->frames[f].x), int(y + s*fi_->frames[f].y), w, h, cx, cy); } } } else { this->image()->scale(Fl_GIF_Image::w(), Fl_GIF_Image::h(), 0, 1); this->image()->draw(x, y, w, h, cx, cy); } } else { // Note: should the base class be called here? // If it is, then the copy() method must also // copy the base image! Fl_GIF_Image::draw(x, y, w, h, cx, cy); } } /** Return the current frame. \return the current frame index in the range for 0 to `frames()-1`. \return -1 if the image has no frames. */ int Fl_Anim_GIF_Image::frame() const { return frame_; } /** Set the current frame. \param[in] frame index into list of frames */ void Fl_Anim_GIF_Image::frame(int frame) { if (Fl::has_timeout(cb_animate, this)) { Fl::warning("Fl_Anim_GIF_Image::frame(%d): not idle!\n", frame); return; } if (frame >= 0 && frame < frames()) { set_frame(frame); } else { Fl::warning("Fl_Anim_GIF_Image::frame(%d): out of range!\n", frame); } } /** Get the number of frames in a GIF file or in a GIF compressed data block. The static frame_count() method is just a convenience method for getting the number of images (frames) stored in a GIF file. As this count is not readily available in the GIF header, the whole GIF file has be parsed (which is done here by using a temporary Fl_Anim_GIF_Image object for simplicity). So this call may be slow with large files. If \p imgdata is \c NULL, the image will be read from the file. Otherwise, it will be read from memory. \param[in] name path and name of GIF file in the file system, ignored when reading from memeory \param[in] imgdata pointer to the start of the GIF image in memory, or \c NULL to read from a file \param[in] imglength length of the GIF image in memory, or \c 0 \return the number of frames in the animation */ int Fl_Anim_GIF_Image::frame_count(const char *name, const unsigned char *imgdata /* = NULL */, size_t imglength /* = 0 */) { Fl_Anim_GIF_Image temp; temp.load(name, imgdata, imglength); int frames = temp.valid() ? temp.frames() : 0; return frames; } /** Return the frame position of a frame. Usefull only if loaded with 'optimize_mem' and the animation also has size optimized frames. \param[in] frame index into frame list \return x position in FLTK pixle units */ int Fl_Anim_GIF_Image::frame_x(int frame) const { if (frame >= 0 && frame < frames()) return fi_->frames[frame].x; return -1; } /** Return the frame position of a frame. Usefull only if loaded with 'optimize_mem' and the animation also has size optimized frames. \param[in] frame index into frame list \return y position in FLTK pixle units */ int Fl_Anim_GIF_Image::frame_y(int frame) const { if (frame >= 0 && frame < frames()) return fi_->frames[frame].y; return -1; } /** Return the frame dimensions of a frame. Usefull only if loaded with 'optimize_mem' and the animation also has size optimized frames. \param[in] frame index into frame list \return width in FLTK pixle units */ int Fl_Anim_GIF_Image::frame_w(int frame) const { if (frame >= 0 && frame < frames()) return fi_->frames[frame].w; return -1; } /** Return the frame dimensions of a frame. Usefull only if loaded with 'optimize_mem' and the animation also has size optimized frames. \param[in] frame index into frame list \return height in FLTK pixle units */ int Fl_Anim_GIF_Image::frame_h(int frame) const { if (frame >= 0 && frame < frames()) return fi_->frames[frame].h; return -1; } /** Use frame_uncache() to set or forbid frame image uncaching. If frame uncaching is set, frame images are not offscreen cached for re-use and will be re-created every time they are displayed. This saves a lot of memory on the expense of cpu usage and should be carefully considered. Per default frame caching will be done. \param[in] uncache true to disable caching */ void Fl_Anim_GIF_Image::frame_uncache(bool uncache) { uncache_ = uncache; } /** Return the active frame_uncache() setting. \return true if caching is disabled */ bool Fl_Anim_GIF_Image::frame_uncache() const { return uncache_; } /** Get the number of frames in the animation. \return the number of frames */ int Fl_Anim_GIF_Image::frames() const { return fi_->frames_size; } /** Return the current frame image. \return a pointer to the image or NULL if this is not an animation. */ Fl_Image *Fl_Anim_GIF_Image::image() const { return frame_ >= 0 && frame_ < frames() ? fi_->frames[frame_].rgb : 0; } /** Return the image of the given frame index. \param[in] frame_ index into list of frames \return image data or NULL if the frame number is not valid. */ Fl_Image *Fl_Anim_GIF_Image::image(int frame_) const { if (frame_ >= 0 && frame_ < frames()) return fi_->frames[frame_].rgb; return 0; } /** Check if this is a valid animation with more than one frame. The \c is_animated() method is just a convenience method for testing the valid flag and the frame count beeing greater 1. \return true if the animation is valid and has multiple frames. */ bool Fl_Anim_GIF_Image::is_animated() const { return valid_ && fi_->frames_size > 1; } /*static*/ bool Fl_GIF_Image::is_animated(const char *name) { return Fl_Anim_GIF_Image::frame_count(name) > 1; } /** Load an animation from a file or from a memory block. The load() method is either used from the constructor to load the image from the given file, or to re-load an existing animation from another file. \param[in] name path and name of GIF file in the file system, or the image name when reading from memory \param[in] imgdata pointer to the start of the GIF image in memory, or \c NULL to read from a file \param[in] imglength length of the GIF image in memory, or \c 0 \return true if the animation loaded correctly */ bool Fl_Anim_GIF_Image::load(const char *name, const unsigned char *imgdata /* =NULL */, size_t imglength /* =0 */) { DEBUG(("\nFl_Anim_GIF_Image::load '%s'\n", name)); clear_frames(); if (name_ != name) { if (name_) { ::free(name_); } if (name) { name_ = fl_strdup(name); } else { name_ = NULL; } } // as load() can be called multiple times // we have to replicate the actions of the pixmap destructor here uncache(); if (alloc_data) { for (int i = 0; i < count(); i ++) delete[] (char *)data()[i]; delete[] (char **)data(); } alloc_data = 0; w(0); h(0); if (name_ || imgdata) { fi_->load(name, imgdata, imglength); } frame_ = fi_->frames_size - 1; valid_ = fi_->valid; if (!valid_) { Fl::error("Fl_Anim_GIF_Image: %s has invalid format.\n", name_); ld(ERR_FORMAT); } return valid_; } // load /** Return the name of the played file as specified in the constructor. If read from a memory block, this returns the name of the animation. \return pointer to a C string */ const char *Fl_Anim_GIF_Image::name() const { return name_; } bool Fl_Anim_GIF_Image::next_frame() { int frame(frame_); frame++; if (frame >= fi_->frames_size) { fi_->loop++; if (Fl_Anim_GIF_Image::loop && fi_->loop_count > 0 && fi_->loop > fi_->loop_count) { DEBUG(("loop count %d reached - stopped!\n", fi_->loop_count)); stop(); } else frame = 0; } if (frame >= fi_->frames_size) return false; set_frame(frame); double delay = fi_->frames[frame].delay; if (min_delay && delay < min_delay) { DEBUG(("#%d: correct delay %f => %f\n", frame, delay, min_delay)); delay = min_delay; } if (is_animated() && delay > 0 && speed_ > 0) { // normal GIF has no delay delay /= speed_; Fl::add_timeout(delay, cb_animate, this); } return true; } /*virtual*/ void Fl_Anim_GIF_Image::on_frame_data(Fl_GIF_Image::GIF_FRAME &gf) { fi_->on_frame_data(gf); } /*virtual*/ void Fl_Anim_GIF_Image::on_extension_data(Fl_GIF_Image::GIF_FRAME &gf) { fi_->on_extension_data(gf); } /** Resizes the image to the specified size, replacing the current image. If \ref DONT_RESIZE_CANVAS is not set, the canvas widget will also be resized. \param[in] w, h new size of teh naimtion frames */ Fl_Anim_GIF_Image& Fl_Anim_GIF_Image::resize(int w, int h) { int W(w); int H(h); if (canvas_ && !W && !H) { W = canvas_->w(); H = canvas_->h(); } if (!W || !H || ((W == this->w() && H == this->h()))) { return *this; } fi_->resize(W, H); scale_frame(); // scale current frame now this->w(fi_->canvas_w); this->h(fi_->canvas_h); if (canvas_ && !(flags_ & DONT_RESIZE_CANVAS)) { canvas_->size(this->w(), this->h()); } return *this; } /** Resizes the image to the specified size, replacing the current image. If \ref DONT_RESIZE_CANVAS is not set, the canvas widget will also be resized. \param[in] scale rescale factor in relation to current size */ Fl_Anim_GIF_Image& Fl_Anim_GIF_Image::resize(double scale) { return resize((int)round((double)w() * scale), (int)round((double)h() * scale)); } void Fl_Anim_GIF_Image::scale_frame() { int i(frame_); if (i < 0) return; fi_->scale_frame(i); } void Fl_Anim_GIF_Image::set_frame() { int i(frame_); if (i < 0) return; fi_->set_frame(i); } void Fl_Anim_GIF_Image::set_frame(int frame) { // int last_frame = frame_; frame_ = frame; // NOTE: uncaching decreases performance, but saves a lot of memory if (uncache_ && this->image()) this->image()->uncache(); fi_->set_frame(frame_); Fl_Widget* cv = canvas(); if (cv) { Fl_Group* parent = cv->parent(); bool no_bg = (cv->box() == FL_NO_BOX); bool outside = (!(cv->align() & FL_ALIGN_INSIDE) && !((cv->align() & FL_ALIGN_POSITION_MASK)==FL_ALIGN_CENTER)); // bool dispose = (fi_->frames[last_frame].dispose == FrameInfo::DISPOSE_BACKGROUND) // || (fi_->frames[last_frame].dispose == FrameInfo::DISPOSE_PREVIOUS); if (parent && (no_bg || outside)) parent->redraw(); else cv->redraw(); // Note: the code below did not animate labels with a pixmap outside of the canvas // canvas()->parent() && // (frame_ == 0 || (last_frame >= 0 && (fi_->frames[last_frame].dispose == FrameInfo::DISPOSE_BACKGROUND || // fi_->frames[last_frame].dispose == FrameInfo::DISPOSE_PREVIOUS))) && // (canvas()->box() == FL_NO_BOX || (canvas()->align() && !(canvas()->align() & FL_ALIGN_INSIDE))) ? // canvas()->parent()->redraw() : canvas()->redraw(); } } /** Get the animation speed factor. \return the current speed factor */ double Fl_Anim_GIF_Image::speed() const { return speed_; } /** Set the animation speed factor. The speed() method changes the playing speed to \p speed x original speed. E.g. to play at half speed call it with 0.5, for double speed with 2. \param[in] speed floating point speed factor */ void Fl_Anim_GIF_Image::speed(double speed) { speed_ = speed; } /** The start() method (re-)starts the playing of the frames. \return true if the animation has frames */ bool Fl_Anim_GIF_Image::start() { Fl::remove_timeout(cb_animate, this); if (fi_->frames_size) { next_frame(); } return fi_->frames_size != 0; } /** The stop() method stops the playing of the frames. \return true if the animation has frames */ bool Fl_Anim_GIF_Image::stop() { Fl::remove_timeout(cb_animate, this); return fi_->frames_size != 0; } /** Show the next frame if the animation is stopped. \return true if the animation has frames */ bool Fl_Anim_GIF_Image::next() { if (fi_->frames_size && !(Fl::has_timeout(cb_animate, this))) { int f = frame() + 1; if (f >= frames()) f = 0; frame(f); } return fi_->frames_size != 0; } /** Uncache all cached image data now. Re-implemented from Fl_Pixmap. */ void Fl_Anim_GIF_Image::uncache() /* override */ { Fl_GIF_Image::uncache(); for (int i=0; i < fi_->frames_size; i++) { if (fi_->frames[i].rgb) fi_->frames[i].rgb->uncache(); } } /** Check if animation is valid. \return true if the class has successfully loaded and the image has at least one frame. */ bool Fl_Anim_GIF_Image::valid() const { return valid_; } fltk-1.4.3/src/Fl_Image_Surface.cxx0000644000175000017500000003311115004135251017232 0ustar albrechtalbrecht// // Draw-to-image code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include // necessary for FL_EXPORT fl_*_offscreen() #include // realloc() /** Constructor with optional high resolution. \param w,h Width and height of the resulting image. The value of the \p high_res parameter controls whether \p w and \p h are interpreted as pixels or FLTK units. \param high_res If zero, the created image surface is sized at \p w x \p h pixels. If non-zero, the pixel size of the created image surface depends on the value of the display scale factor (see Fl::screen_scale(int)): the resulting image has the same number of pixels as an area of the display of size \p w x \p h expressed in FLTK units. \param off If not null, the image surface is constructed around a pre-existing Fl_Offscreen. The caller is responsible for both construction and destruction of this Fl_Offscreen object. Is mostly intended for internal use by FLTK. \version 1.3.4 (1.3.3 without the \p highres parameter) */ Fl_Image_Surface::Fl_Image_Surface(int w, int h, int high_res, Fl_Offscreen off) : Fl_Widget_Surface(NULL) { platform_surface = Fl_Image_Surface_Driver::newImageSurfaceDriver(w, h, high_res, off); platform_surface->image_surface_ = this; driver(platform_surface->driver()); } /** The destructor. */ Fl_Image_Surface::~Fl_Image_Surface() { if (is_current()) platform_surface->end_current(); delete platform_surface; } void Fl_Image_Surface::origin(int x, int y) {platform_surface->origin(x, y);} void Fl_Image_Surface::origin(int *x, int *y) { if (platform_surface) platform_surface->origin(x, y); } void Fl_Image_Surface::set_current() { if (platform_surface) platform_surface->set_current(); } bool Fl_Image_Surface::is_current() { return surface() == platform_surface; } void Fl_Image_Surface::translate(int x, int y) { if (platform_surface) platform_surface->translate(x, y); } void Fl_Image_Surface::untranslate() { if (platform_surface) platform_surface->untranslate(); } /** Returns the Fl_Offscreen object associated to the image surface. The returned Fl_Offscreen object is deleted when the Fl_Image_Surface object is deleted, unless the Fl_Image_Surface was constructed with non-null Fl_Offscreen argument. */ Fl_Offscreen Fl_Image_Surface::offscreen() { return platform_surface ? platform_surface->offscreen : (Fl_Offscreen)0; } int Fl_Image_Surface::printable_rect(int *w, int *h) {return platform_surface->printable_rect(w, h);} /** \cond DriverDev \addtogroup DriverDeveloper \{ */ int Fl_Image_Surface_Driver::printable_rect(int *w, int *h) { *w = width; *h = height; return 0; } // used by the Windows and X11(no Cairo) platforms void Fl_Image_Surface_Driver::copy_with_mask(Fl_RGB_Image* mask, uchar *dib_dst, uchar *dib_src, int line_size, bool bottom_to_top) { int w = mask->data_w(), h = mask->data_h(); for (int i = 0; i < h; i++) { const uchar* alpha = (const uchar*)mask->array + (bottom_to_top ? (h-i-1) : i) * w; uchar *src = dib_src + i * line_size; uchar *dst = dib_dst + i * line_size; for (int j = 0; j < w; j++) { // mix src and dst into dst weighted by mask pixel's value uchar u = *alpha++, v = 255 - u; *dst = ((*dst) * v + (*src) * u)/255; dst++; src++; *dst = ((*dst) * v + (*src) * u)/255; dst++; src++; *dst = ((*dst) * v + (*src) * u)/255; dst++; src++; } } } Fl_RGB_Image *Fl_Image_Surface_Driver::RGB3_to_RGB1(const Fl_RGB_Image *rgb3, int W, int H) { bool need_copy = false; if (W != rgb3->data_w() || H != rgb3->data_h()) { rgb3 = (Fl_RGB_Image*)rgb3->copy(W, H); need_copy = true; } uchar *data = new uchar[W * H]; int i, j, ld = rgb3->ld(); if (!ld) ld = 3 * W; uchar *p = data; for (i = 0; i < H; i++) { const uchar* alpha = rgb3->array + i * ld; for (j = 0; j < W; j++) { *p++ = (*alpha + *(alpha+1) + *(alpha+2)) / 3; alpha += 3; } } Fl_RGB_Image *rgb1 = new Fl_RGB_Image(data, W, H, 1); rgb1->alloc_array = 1; if (need_copy) delete rgb3; return rgb1; } /** \} \endcond */ /** Returns a depth-3 image made of all drawings sent to the Fl_Image_Surface object. The returned object contains its own copy of the RGB data; the caller is responsible for deleting it. \see Fl_Image_Surface::mask(Fl_RGB_Image*) */ Fl_RGB_Image *Fl_Image_Surface::image() { bool need_push = (Fl_Surface_Device::surface() != platform_surface); if (need_push) Fl_Surface_Device::push_current(platform_surface); Fl_RGB_Image *img = platform_surface->image(); if (need_push) Fl_Surface_Device::pop_current(); img->scale(platform_surface->width, platform_surface->height, 1, 1); return img; } /** Returns a possibly high resolution image made of all drawings sent to the Fl_Image_Surface object. The Fl_Image_Surface object should have been constructed with Fl_Image_Surface(W, H, 1). The returned Fl_Shared_Image object is scaled to a size of WxH FLTK units and may have a pixel size larger than these values. The returned object should be deallocated with Fl_Shared_Image::release() after use. \deprecated Use image() instead. \version 1.4 (1.3.4 for MacOS platform only) */ Fl_Shared_Image* Fl_Image_Surface::highres_image() { if (!platform_surface) return NULL; Fl_Shared_Image *s_img = Fl_Shared_Image::get(image()); int width, height; platform_surface->printable_rect(&width, &height); s_img->scale(width, height, 1, 1); return s_img; } // Allows to delete the Fl_Image_Surface object while keeping its underlying Fl_Offscreen Fl_Offscreen Fl_Image_Surface::get_offscreen_before_delete_() { Fl_Offscreen keep = platform_surface->offscreen; platform_surface->offscreen = 0; return keep; } /** Adapts the Fl_Image_Surface object to the new value of the GUI scale factor. The Fl_Image_Surface object must not be the current drawing surface. This function is useful only for an object constructed with non-zero \p high_res parameter. \version 1.4 */ void Fl_Image_Surface::rescale() { Fl_RGB_Image *rgb = image(); int w, h; printable_rect(&w, &h); delete platform_surface; platform_surface = Fl_Image_Surface_Driver::newImageSurfaceDriver(w, h, 1, 0); Fl_Surface_Device::push_current(this); rgb->draw(0,0); Fl_Surface_Device::pop_current(); delete rgb; } /** Defines a mask applied to drawings made after use of this function. The mask is an Fl_RGB_Image made of a white scene drawn on a solid black background; the drawable part of the image surface is reduced to the white areas of the mask after this member function gets called. If necessary, the \p mask image is internally replaced by a copy resized to the surface's pixel size. Overall, the image returned by Fl_Image_Surface::image() contains all drawings made until the mask() method assigned a mask, at which point subsequent drawing operations to the image surface were passed through the white areas of the mask. On some platforms, shades of gray in the mask image control the blending of foreground and background pixels; mask pixels closer in color to white produce image pixels closer to the image surface pixel, those closer to black produce image pixels closer to what the image surface pixel was before the call to mask(). The mask is easily constructed using an Fl_Image_Surface object, drawing white areas on a black background there, and calling Fl_Image_Surface::image(). \param mask A depth-3 image determining the drawable areas of the image surface. The \p mask object is not used after return from this member function. \note - The image surface must not be the current drawing surface when this function gets called. - The mask can have any size but is best when it has the size of the image surface. - It's possible to use several masks in succession on the same image surface provided member function Fl_Image_Surface::image() is called between successive calls to Fl_Image_Surface::mask(const Fl_RGB_Image*). Example of procedure to construct a masked image: \code int W = …, H = …; // width and height of the image under construction Fl_Image_Surface *surf = new Fl_Image_Surface(W, H, 1); // first, construct the mask Fl_Surface_Device::push_current(surf); fl_color(FL_BLACK); // draw a black background fl_rectf(0, 0, W, H); fl_color(FL_WHITE); // next, draw in white what the mask should not filter out fl_pie(0, 0, W, H, 0, 360); // here, an ellipse with axes lengths WxH Fl_RGB_Image *mask = surf->image(); // get the mask // second, draw the image background fl_color(FL_YELLOW); // here, draw a yellow background fl_rectf(0, 0, W, H); // third, apply the mask Fl_Surface_Device::pop_current(); surf->mask(mask); delete mask; // the mask image can be safely deleted at this point Fl_Surface_Device::push_current(surf); // fourth, draw the image foreground, part of which will be filtered out by the mask surf->draw(widget, 0, 0); // here the foreground is a drawn widget // fifth, get the final result, masked_image, as a depth-3 Fl_RGB_Image Fl_RGB_Image *masked_image = surf->image(); // Only the part of the foreground, here a drawn widget, that has not been // filtered out by the mask, here the white ellipse, is in masked_image; // the background, here solid yellow, shows up in the remaining areas of masked_image. Fl_Surface_Device::pop_current(); delete surf; \endcode \since 1.4.0 */ void Fl_Image_Surface::mask(const Fl_RGB_Image *mask) { platform_surface->mask(mask); } // implementation of the fl_XXX_offscreen() functions static Fl_Image_Surface **offscreen_api_surface = NULL; static int count_offscreens = 0; static int find_slot(void) { // return an available slot to memorize an Fl_Image_Surface object static int max = 0; for (int num = 0; num < count_offscreens; num++) { if (!offscreen_api_surface[num]) return num; } if (count_offscreens >= max) { max += 20; offscreen_api_surface = (Fl_Image_Surface**)realloc(offscreen_api_surface, max * sizeof(void *)); } return count_offscreens++; } /** \addtogroup fl_drawings @{ */ /** Creation of an offscreen graphics buffer. \param w,h width and height in FLTK units of the buffer. \return the created graphics buffer. The pixel size of the created graphics buffer is equal to the number of pixels in an area of the screen containing the current window sized at \p w,h FLTK units. This pixel size varies with the value of the scale factor of this screen. \note Work with the fl_XXX_offscreen() functions is equivalent to work with an Fl_Image_Surface object, as follows :
Fl_Offscreen-based approachFl_Image_Surface-based approach
Fl_Offscreen off = fl_create_offscreen(w, h)Fl_Image_Surface *surface = new Fl_Image_Surface(w, h, 1)
fl_begin_offscreen(off)Fl_Surface_Device::push_current(surface)
fl_end_offscreen()Fl_Surface_Device::pop_current()
fl_copy_offscreen(x,y,w,h, off, sx,sy)fl_copy_offscreen(x,y,w,h, surface->offscreen(), sx,sy)
fl_rescale_offscreen(off)surface->rescale()
fl_delete_offscreen(off)delete surface
*/ Fl_Offscreen fl_create_offscreen(int w, int h) { int rank = find_slot(); offscreen_api_surface[rank] = new Fl_Image_Surface(w, h, 1/*high_res*/); return offscreen_api_surface[rank]->offscreen(); } /** Deletion of an offscreen graphics buffer. \param ctx the buffer to be deleted. \note The \p ctx argument must have been created by fl_create_offscreen(). */ void fl_delete_offscreen(Fl_Offscreen ctx) { if (!ctx) return; for (int i = 0; i < count_offscreens; i++) { if (offscreen_api_surface[i] && offscreen_api_surface[i]->offscreen() == ctx) { delete offscreen_api_surface[i]; offscreen_api_surface[i] = NULL; return; } } } /** Send all subsequent drawing commands to this offscreen buffer. \param ctx the offscreen buffer. \note The \p ctx argument must have been created by fl_create_offscreen(). */ void fl_begin_offscreen(Fl_Offscreen ctx) { for (int i = 0; i < count_offscreens; i++) { if (offscreen_api_surface[i] && offscreen_api_surface[i]->offscreen() == ctx) { Fl_Surface_Device::push_current(offscreen_api_surface[i]); return; } } } /** Quit sending drawing commands to the current offscreen buffer. */ void fl_end_offscreen() { Fl_Surface_Device::pop_current(); } /** Adapts an offscreen buffer to a changed value of the scale factor. The \p ctx argument must have been created by fl_create_offscreen() and the calling context must not be between fl_begin_offscreen() and fl_end_offscreen(). The graphical content of the offscreen is preserved. The current scale factor value is given by Fl_Graphics_Driver::default_driver().scale(). \version 1.4 */ void fl_rescale_offscreen(Fl_Offscreen &ctx) { int i; for (i = 0; i < count_offscreens; i++) { if (offscreen_api_surface[i] && offscreen_api_surface[i]->offscreen() == ctx) { break; } } if (i >= count_offscreens) return; offscreen_api_surface[i]->rescale(); ctx = offscreen_api_surface[i]->offscreen(); } /** @} */ fltk-1.4.3/src/Fl_Scheme_Choice.cxx0000644000175000017500000000715715004135251017231 0ustar albrechtalbrecht// // Scheme Choice widget for the Fast Light Tool Kit (FLTK). // // Copyright 2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include /** The constructor initializes the Fl_Scheme_Choice object with all known schemes. \param[in] X,Y Widget coordinates \param[in] W,H Widget size (width, height) \param[in] L Widget label (default: NULL, no label) */ Fl_Scheme_Choice::Fl_Scheme_Choice(int X, int Y, int W, int H, const char *L) : Fl_Choice(X, Y, W, H, L) { const char * const *names = Fl_Scheme::names(); // Add all known schemes in the order defined by the list of scheme names while (*names) { add(*names); names++; } callback(scheme_cb_); // internal callback init_value(); // set choice value to current scheme } /** Public method to initialize the value of the Fl_Scheme_Choice widget. Normally you don't need to call this unless you change the current scheme by calling Fl::scheme(const char *). The Fl_Scheme_Choice widget does this automatically when the widget is shown (when receiving the FL_SHOW event) which should always be after Fl_Window::show(argc, argv) which may set the current scheme by interpreting the commandline. \since 1.4.0 */ void Fl_Scheme_Choice::init_value() { const char *current = Fl::scheme(); value(0); if (!current) return; const char * const * names = Fl_Scheme::names(); int i = 0; while (names[i]) { if (!strcmp(current, names[i])) { value(i); break; } i++; } } // init_value() /** Internal Fl_Scheme_Choice callback function (protected). You don't need to set a callback for this widget. The default callback changes the scheme (Fl::scheme()) and redraws all open windows. You may override the callback if changing the scheme shall redraw other windows or don't redraw the window at all. \param[in] w The Fl_Scheme_Choice widget */ void Fl_Scheme_Choice::scheme_cb_(Fl_Widget *w, void *) { Fl_Choice *c = reinterpret_cast(w); // set the new scheme only if the scheme was changed const char *new_scheme = c->text(c->value()); if (!Fl::is_scheme(new_scheme)) { Fl::scheme(new_scheme); } } /** \brief Handle FLTK events. This widget uses FL_SHOW and some other events to initialize its value() according to the current scheme. All events are also handled by the base class Fl_Choice. \param[in] event \return 1 if the event was used, 0 otherwise \internal Usually the FL_SHOW event is used to initialize the value, and this should in most cases be sufficient. However, if the scheme is changed after show() the widget doesn't "know" this and can't update itself. Therefore the enter and push events are also used to update the displayed value. In the future we will be able to register a callback that will be triggered when the scheme is changed. This will make the special handling of FL_PUSH and FL_ENTER obsolete, but FL_SHOW is still required. */ int Fl_Scheme_Choice::handle(int event) { int ret = 0; switch (event) { case FL_SHOW: case FL_PUSH: case FL_ENTER: init_value(); ret = 1; break; default: break; } ret |= Fl_Choice::handle(event); return ret; } fltk-1.4.3/src/scandir_posix.c0000644000175000017500000001670415004135251016415 0ustar albrechtalbrecht/* * This implementation of 'scandir()' is intended to be POSIX.1-2008 compliant. * A POSIX.1-1990 compliant system is required as minimum base. * Note: * The 'const' declarations were removed to match FLTK 1.3 wrapper (STR #2931) * * Copyright (c) 2013 by Michael Baeuerle * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php * * It is required that 'SIZE_MAX' is at least 'INT_MAX'. * Don't use a C++ compiler to build this module. * * The build system must define 'HAVE_PTHREAD' and link against a potentially * required library to switch this implementation into thread-safe mode. * The POSIX.1c-1995 extension is required if 'HAVE_PTHREAD' is defined. * * Note: * In theory, a system that provides threads should also provide 'readdir_r()', * a thread-safe version of 'readdir()'. In reality this is not always the case. * In addition there may be a race condition that can lead to a buffer overflow: * http://womble.decadent.org.uk/readdir_r-advisory.html */ #include #if defined(FLTK_USE_X11) && !defined(HAVE_SCANDIR) #ifndef HAVE_PTHREAD /* Switch system headers into POSIX.1-1990 mode */ # define _POSIX_SOURCE #else /* HAVE_PTHREAD */ /* Switch system headers into POSIX.1c-1995 mode */ # define _POSIX_C_SOURCE 199506L #endif /* HAVE_PTHREAD */ #include /* XPG2 require this for '*dir()' functions */ #include #include #include /* For 'malloc()', 'realloc()' and 'qsort()' */ #include /* For 'offsetof()', 'NULL' and 'size_t' */ #include /* For 'INT_MAX' */ #include /* For 'memcpy()' */ #include "flstring.h" /* For 'fl_snprintf()' */ #if defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_H) # include #endif /* HAVE_PTHREAD */ /* ========================================================================== */ /* At startup allocate memory for this number of result array elements */ #define ENTRIES_MIN (size_t) 32 /* ========================================================================== */ #ifdef HAVE_PTHREAD static pthread_mutex_t scandir_mutex = PTHREAD_MUTEX_INITIALIZER; #endif /* HAVE_PTHREAD */ /* ========================================================================== */ /* * This function reads the next entry from the directory referenced by 'dirp', * allocates a buffer for the entry and copies it into this buffer. * A pointer to this buffer is written to 'entryp' and the size of the buffer * is written to 'len'. * Success and a NULL pointer is returned for 'entryp' if there are no more * entries in the directory. * On success zero is returned and the caller is responsible for 'free()'ing * the buffer after use. * On error the return value is nonzero, 'entryp' and 'len' are invalid. * * Should be declared as 'static inline' if the compiler supports that. */ static int readentry(DIR *dirp, struct dirent **entryp, size_t *len) { int result = -1; struct dirent *e; #ifdef HAVE_PTHREAD if (!pthread_mutex_lock(&scandir_mutex)) { /* Ensure that there is no code path that bypasses the '_unlock()' call! */ #endif /* HAVE_PTHREAD */ errno = 0; e = readdir(dirp); if (NULL == e) { if (!errno) { /* No more entries in directory */ *entryp = NULL; *len = 0; result = 0; } } else { /* Entry found, allocate local buffer */ *len = offsetof(struct dirent, d_name) + strlen(e->d_name) + (size_t) 1; *entryp = (struct dirent *) malloc(*len); if (NULL != *entryp) { memcpy((void *) *entryp, (void *) e, *len); /* Force NUL termination at end of buffer */ ((char *) *entryp)[*len - (size_t) 1] = 0; result = 0; } } #ifdef HAVE_PTHREAD /* * In a multithreading environment the system's dirent buffer may be shared * between all threads. Therefore the mutex must stay locked until we have * copied the data to our thread local buffer. */ pthread_mutex_unlock(&scandir_mutex); } #endif /* HAVE_PTHREAD */ return result; } /* * This could use some docs. * * Returns -1 on error, errmsg returns error string (if non-NULL) */ int fl_scandir(const char *dir, struct dirent ***namelist, int (*sel)(struct dirent *), int (*compar)(struct dirent **, struct dirent **), char *errmsg, int errmsg_sz) { int result = -1; DIR *dirp; size_t len, num = 0, max = ENTRIES_MIN; struct dirent *entryp, **entries, **p; if (errmsg && errmsg_sz>0) errmsg[0] = '\0'; entries = (struct dirent **) malloc(sizeof(*entries) * max); if (NULL == entries) { if (errmsg) fl_snprintf(errmsg, errmsg_sz, "out of memory"); return -1; } /* Open directory 'dir' (and verify that it really is a directory) */ dirp = opendir(dir); if (NULL == dirp) { if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno)); // XXX: This would be a thread safe alternative to the above, but commented // out because we can get either GNU or POSIX versions on linux, // which AFAICT are incompatible: GNU doesn't guarantee errmsg is used // at all, whereas POSIX /only/ fills buffer. The two calls are not really // compatible but have the same name and different return values.. wtf? // // if (errmsg && errmsg_sz > 0) { // strerror_r(errno, errmsg, errmsg_sz); // thread safe. Might be GNU, might be POSIX // errmsg[errmsg_sz-1] = '\0'; // force null term b/c XSI does not specify // } return -1; } /* Read next directory entry */ while (!readentry(dirp, &entryp, &len)) { if (NULL == entryp) { /* EOD => Return number of directory entries */ result = (int) num; break; } /* Apply select function if there is one provided */ if (NULL != sel) { if (!sel(entryp)) continue; } entries[num++] = entryp; if (num >= max) { /* Allocate exponentially increasing sized memory chunks */ if (INT_MAX / 2 >= (int) max) { max *= (size_t) 2; } else { errno = ENOMEM; break; } p = (struct dirent **) realloc((void *)entries, sizeof(*entries)*max); if (NULL != p) { entries = p; } else break; } } closedir(dirp); /* * A standard compliant 'closedir()' is allowed to fail with 'EINTR', * but the state of the directory structure is undefined in this case. * Therefore we ignore the return value because we can't call 'closedir()' * again and must hope that the system has released all resources. */ /* Sort entries in array if there is a compare function provided */ if (NULL != compar) { qsort((void *) entries, num, sizeof(*entries), (int (*)(const void *, const void *)) compar); } *namelist = entries; /* Check for error */ if (-1 == result) { /* Free all memory we have allocated */ while (num--) { free(entries[num]); } free(entries); } return result; } #else /* defined(FLTK_USE_X11) && !defined(HAVE_SCANDIR) */ /* avoid (gcc) compiler warning [-Wpedantic] "ISO C forbids an empty translation unit" */ typedef int dummy; #endif /* defined(FLTK_USE_X11) && !defined(HAVE_SCANDIR) */ fltk-1.4.3/src/Fl_ICO_Image.cxx0000644000175000017500000001204315004135251016255 0ustar albrechtalbrecht// // Fl_ICO_Image class for the Fast Light Tool Kit (FLTK). // // Copyright 2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please report all bugs and problems on the following page: // // https://www.fltk.org/str.php // // // Include necessary header files... // #include #include "config.h" #include "Fl_Image_Reader.h" #include #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) # include #endif /** Loads the named icon image from the given .ico filename or from memory \param filename Name of a .ico file, or of the in-memory image \param id When id is -1 (default), the highest-resolution icon is loaded; when id ≥ 0, load the icon with this ID; when id = -2, load all IconDirEntry structures but no image. \param data NULL, or in-memory icon data \param datasize Size in bytes of the \p data byte array (used when \p data is not NULL) */ Fl_ICO_Image::Fl_ICO_Image(const char *filename, int id, const unsigned char *data, const size_t datasize) : Fl_BMP_Image(0,0), idcount_(0), icondirentry_(0) { Fl_Image_Reader rdr; int r; w(0); h(0); d(0); ld(0); alloc_array = 0; array = 0; if (data) { r = rdr.open(filename, data, datasize); } else { r = rdr.open(filename); } if (r == -1) { ld(ERR_FILE_ACCESS); } else { load_ico_(rdr, id); } } /** Destructor */ Fl_ICO_Image::~Fl_ICO_Image() { delete[] icondirentry_; } /* This method attempts to load the biggest image resource available inside a .ICO file (Windows Icon format). */ void Fl_ICO_Image::load_ico_(Fl_Image_Reader &rdr, int id) { int pickedID = -1; // Check file header (ICONDIR, 6 bytes) if (rdr.read_word() != 0 || rdr.read_word() != 1) { Fl::error("Fl_ICO_Image: %s is not an ICO file.\n", rdr.name()); ld(ERR_FORMAT); return; } idcount_ = rdr.read_word(); if (idcount() == 0) { Fl::error("Fl_ICO_Image: %s - no image resources found\n", rdr.name()); ld(ERR_FORMAT); return; } // read entries (IconDirEntry, 16 bytes each) icondirentry_ = new IconDirEntry[idcount()]; for (int i = 0; i < idcount(); ++i) { icondirentry_[i].bWidth = (int)rdr.read_byte(); icondirentry_[i].bHeight = (int)rdr.read_byte(); icondirentry_[i].bColorCount = (int)rdr.read_byte(); icondirentry_[i].bReserved = (int)rdr.read_byte(); icondirentry_[i].wPlanes = (int)rdr.read_word(); icondirentry_[i].wBitCount = (int)rdr.read_word(); icondirentry_[i].dwBytesInRes = (int)rdr.read_dword(); icondirentry_[i].dwImageOffset = (int)rdr.read_dword(); if (icondirentry_[i].bWidth == 0) icondirentry_[i].bWidth = 256; if (icondirentry_[i].bHeight == 0) icondirentry_[i].bHeight = 256; } if (id <= -2) return; if (!icondirentry_ || idcount() < 1 || id >= idcount()) { ld(ERR_FORMAT); return; } if (id == -1) { // pick icon with highest resolution + highest bitcount int highestRes = 0, bitcount = 0; for (int i = 0; i < idcount(); ++i) { int res = icondirentry_[i].bWidth * icondirentry_[i].bHeight; if (res > highestRes || (res == highestRes && icondirentry_[i].wBitCount > bitcount)) { highestRes = res; bitcount = icondirentry_[i].wBitCount; pickedID = i; } } } else { pickedID = id; } if (pickedID < 0 || icondirentry_[pickedID].bWidth <= 0 || icondirentry_[pickedID].bHeight <= 0 || icondirentry_[pickedID].dwImageOffset <= 0|| icondirentry_[pickedID].dwBytesInRes <= 0) { ld(ERR_FORMAT); return; } rdr.seek(icondirentry_[pickedID].dwImageOffset); // Check for a PNG image resource uchar b[8]; for (int i=0; i<8; ++i) b[i] = rdr.read_byte(); if (b[0]==0x89 && b[1]=='P' && b[2]=='N' && b[3]=='G' && b[4]=='\r' && b[5]=='\n' && b[6]==0x1A && b[7]=='\n') { #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) Fl_PNG_Image *png = new Fl_PNG_Image(rdr.name(), icondirentry_[pickedID].dwImageOffset); int loaded = png ? png->fail() : ERR_FILE_ACCESS; if (loaded < 0) { w(0); h(0); d(0); ld(loaded); if (png) delete png; return; } w(png->w()); h(png->h()); d(png->d()); // take over pointer of Fl_PNG_Image's array array = png->array; alloc_array = 1; png->array = NULL; png->alloc_array = 0; delete png; return; #else Fl::error("Fl_ICO_Image: %s - cannot decode PNG resource (no libpng support)!\n", rdr.name()); w(0); h(0); d(0); ld(ERR_FORMAT); return; #endif } // Bitmap resource w(icondirentry_[pickedID].bWidth); h(icondirentry_[pickedID].bHeight); d(4); if (((size_t)w()) * h() * d() > max_size()) { Fl::warning("ICO file \"%s\" is too large!\n", rdr.name()); w(0); h(0); d(0); ld(ERR_FORMAT); return; } rdr.seek(icondirentry_[pickedID].dwImageOffset); load_bmp_(rdr, h(), w()); } fltk-1.4.3/src/Fl_Single_Window.cxx0000644000175000017500000000175615004135251017322 0ustar albrechtalbrecht// // Single-buffered window for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // A window with a single-buffered context // // This is provided for systems where the base class is double // buffered. You can turn it off using this subclass in case // your display looks better without it. #include void Fl_Single_Window::show() { Fl_Window::show(); } Fl_Single_Window::Fl_Single_Window(int W, int H, const char *l) : Fl_Window(W,H,l) { } Fl_Single_Window::Fl_Single_Window(int X, int Y, int W, int H, const char *l) : Fl_Window(X,Y,W,H,l) { } fltk-1.4.3/src/Fl_Menu_.cxx0000644000175000017500000005115615004135251015614 0ustar albrechtalbrecht// // Common menu code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // This is a base class for all items that have a menu: // Fl_Menu_Bar, Fl_Menu_Button, Fl_Choice // This provides storage for a menu item, functions to add/modify/delete // items, and a call for when the user picks a menu item. // More code in Fl_Menu_add.cxx #include #include #include "flstring.h" #include #include #define SAFE_STRCAT(s) { len += (int) strlen(s); if ( len >= namelen ) { *name='\0'; return(-2); } else strcat(name,(s)); } /** Get the menu 'pathname' for the specified menuitem. If finditem==NULL, mvalue() is used (the most recently picked menuitem). \b Example: \code Fl_Menu_Bar *menubar = 0; void my_menu_callback(Fl_Widget*,void*) { char name[80]; if ( menubar->item_pathname(name, sizeof(name)-1) == 0 ) { // recently picked item if ( strcmp(name, "File/&Open") == 0 ) { .. } // open invoked if ( strcmp(name, "File/&Save") == 0 ) { .. } // save invoked if ( strcmp(name, "Edit/&Copy") == 0 ) { .. } // copy invoked } } int main() { [..] menubar = new Fl_Menu_Bar(..); menubar->add("File/&Open", 0, my_menu_callback); menubar->add("File/&Save", 0, my_menu_callback); menubar->add("Edit/&Copy", 0, my_menu_callback); [..] } \endcode \returns - 0 : OK (name has menuitem's pathname) - -1 : item not found (name="") - -2 : 'name' not large enough (name="") \see find_item() */ int Fl_Menu_::item_pathname(char *name, int namelen, const Fl_Menu_Item *finditem) const { name[0] = '\0'; return item_pathname_(name, namelen, finditem, menu_); } // INTERNAL: Descend into a specific menu hierarchy int Fl_Menu_::item_pathname_(char *name, int namelen, const Fl_Menu_Item *finditem, const Fl_Menu_Item *menu) const { int len = 0; int level = 0; finditem = finditem ? finditem : mvalue(); menu = menu ? menu : this->menu(); for ( int t=0; tsubmenu()) { // submenu? descend if (m->flags & FL_SUBMENU_POINTER) { // SUBMENU POINTER? Recurse to descend int slen = (int)strlen(name); const Fl_Menu_Item *submenu = (const Fl_Menu_Item*)m->user_data(); if (m->label()) { if (*name) SAFE_STRCAT("/"); SAFE_STRCAT(m->label()); } if (item_pathname_(name, len, finditem, submenu) == 0) return 0; name[slen] = 0; // continue from where we were } else { // REGULAR SUBMENU? DESCEND ++level; if (*name) SAFE_STRCAT("/"); if (m->label()) SAFE_STRCAT(m->label()); if (m == finditem) return(0); // found? done. } } else { if (m->label()) { // menu item? if ( m == finditem ) { // found? tack on itemname, done. SAFE_STRCAT("/"); SAFE_STRCAT(m->label()); return(0); } } else { // end of submenu? pop if ( --level < 0 ) { *name = '\0'; return -1; } char *ss = strrchr(name, '/'); if ( ss ) { *ss = 0; len = (int) strlen(name); } // "File/Edit" -> "File" else { name[0] = '\0'; len = 0; } // "File" -> "" continue; } } } *name = '\0'; return(-1); // item not found } /** Find the menu item for a given menu \p pathname, such as "Edit/Copy". This method finds a menu item in the menu array, also traversing submenus, but not submenu pointers (FL_SUBMENU_POINTER). To get the menu item's index, use find_index(const char*) \b Example: \code Fl_Menu_Bar *menubar = new Fl_Menu_Bar(..); menubar->add("File/&Open"); menubar->add("File/&Save"); menubar->add("Edit/&Copy"); // [..] Fl_Menu_Item *item; if ( ( item = (Fl_Menu_Item*)menubar->find_item("File/&Open") ) != NULL ) { item->labelcolor(FL_RED); } if ( ( item = (Fl_Menu_Item*)menubar->find_item("Edit/&Copy") ) != NULL ) { item->labelcolor(FL_GREEN); } \endcode \param pathname The path and name of the menu item \returns The item found, or NULL if not found \see find_index(const char*), find_item(Fl_Callback*), item_pathname() */ const Fl_Menu_Item * Fl_Menu_::find_item(const char *pathname) { int i = find_index(pathname); return( (i==-1) ? 0 : (const Fl_Menu_Item*)(menu_+i)); } /** Find the index into the menu array for a given \p item. A way to convert a menu item pointer into an index. Does \b not handle items that are in submenu pointers (FL_SUBMENU_POINTER). -1 is returned if the item is not in this menu or is part of an FL_SUBMENU_POINTER submenu. Current implementation is fast and not expensive. \code // Convert an index-to-item int index = 12; const Fl_Menu_Item *item = mymenu->menu() + index; // Convert an item-to-index int index = mymenu->find_index(item); if ( index == -1 ) { ..error.. } \endcode \param[in] item The item to be found \returns The index of the item, or -1 if not found. \see menu() */ int Fl_Menu_::find_index(const Fl_Menu_Item *item) const { Fl_Menu_Item *max = menu_+size(); if (item=max) return(-1); return (int) (item-menu_); } /** Find the index into the menu array for a given callback \p cb. This method finds a menu item's index position, also traversing submenus, but \b not submenu pointers (FL_SUBMENU_POINTER). This is useful if an application uses internationalisation and a menu item can not be found using its label. This search is also much faster. \param cb Find the first item with this callback \returns The index of the item with the specific callback, or -1 if not found \see find_index(const char*) */ int Fl_Menu_::find_index(Fl_Callback *cb) const { for ( int t=0; t < size(); t++ ) if (menu_[t].callback_==cb) return(t); return(-1); } /** Find the menu item index for a given menu \p pathname, such as "Edit/Copy". This method finds a menu item's index position for the given menu pathname, also traversing submenus, but \b not submenu pointers (FL_SUBMENU_POINTER). To get the menu item pointer for a pathname, use find_item() \param[in] pathname The path and name of the menu item to find \returns The index of the matching item, or -1 if not found. \see item_pathname() */ int Fl_Menu_::find_index(const char *pathname) const { char menupath[1024] = ""; // File/Export for ( int t=0; t < size(); t++ ) { Fl_Menu_Item *m = menu_ + t; if (m->flags&FL_SUBMENU) { // IT'S A SUBMENU // we do not support searches through FL_SUBMENU_POINTER links if (menupath[0]) strlcat(menupath, "/", sizeof(menupath)); strlcat(menupath, m->label(), sizeof(menupath)); if (!strcmp(menupath, pathname)) return(t); } else { if (!m->label()) { // END OF SUBMENU? Pop back one level. char *ss = strrchr(menupath, '/'); if ( ss ) *ss = 0; else menupath[0] = '\0'; continue; } // IT'S A MENU ITEM char itempath[1024]; // eg. Edit/Copy strcpy(itempath, menupath); if (itempath[0]) strlcat(itempath, "/", sizeof(itempath)); strlcat(itempath, m->label(), sizeof(itempath)); if (!strcmp(itempath, pathname)) return(t); } } return(-1); } /** Find the menu item for the given callback \p cb. This method finds a menu item in a menu array, also traversing submenus, but not submenu pointers. This is useful if an application uses internationalisation and a menu item can not be found using its label. This search is also much faster. \param[in] cb find the first item with this callback \returns The item found, or NULL if not found \see find_item(const char*) */ const Fl_Menu_Item * Fl_Menu_::find_item(Fl_Callback *cb) { for ( int t=0; t < size(); t++ ) { const Fl_Menu_Item *m = menu_ + t; if (m->callback_==cb) { return m; } } return (const Fl_Menu_Item *)0; } /** Find the menu item for the given user data \p v. \param[in] v find the first item with this user data \returns The item found, or NULL if not found \see find_item(const char*) */ const Fl_Menu_Item* Fl_Menu_::find_item_with_user_data(void *v) { for ( int t=0; t < size(); t++ ) { const Fl_Menu_Item *m = menu_ + t; if (m->user_data_==v) { return m; } } return (const Fl_Menu_Item *)NULL; } /** Find the menu item for the given user argument \p v. \param[in] v find the first item with this user argument \returns The item found, or NULL if not found \see find_item(const char*) */ const Fl_Menu_Item* Fl_Menu_::find_item_with_argument(long v) { for ( int t=0; t < size(); t++ ) { const Fl_Menu_Item *m = menu_ + t; if (m->argument()==v) { return m; } } return (const Fl_Menu_Item *)NULL; } /** Set the value of a menu to the menu item \c m. The \e value of the menu is the index into the menu() of the last item chosen by the user or -1. It is \c -1 initially (if no item has been chosen) or if the chosen menu item is part of a submenu addressed by an FL_SUBMENU_POINTER. \note All menu items are located in a contiguous array of Fl_Menu_Item's unless an item has the FL_SUBMENU_POINTER flag which redirects the submenu to an independent submenu array. This submenu array is not counted in the size() of the menu, and menu items in this submenu can't return a valid index into the \b main menu. Therefore menu items that are located in such a submenu return -1 when value() is called. This may be changed in a future version. The menu item can be any menu item, even one in a detached submenu (see note about FL_SUBMENU_POINTER above). \param[in] m Pointer to any menu item. \return Whether the new value is different than the old one. \retval 0 The value didn't change. \retval 1 The value was changed. \see int value(int) \see int value() \see const Fl_Menu_Item *mvalue() */ int Fl_Menu_::value(const Fl_Menu_Item* m) { clear_changed(); if (value_ != m) { prev_value_ = value_; value_ = m; return 1; } return 0; } /** Return the index into the menu() of the last item chosen by the user. The \e value of the menu is the index into the menu() of the last item chosen by the user or -1. It is \c -1 initially (if no item has been chosen) or if the chosen menu item is part of a submenu addressed by an FL_SUBMENU_POINTER. \note All menu items are located in a contiguous array of Fl_Menu_Item's unless an item has the FL_SUBMENU_POINTER flag which redirects the submenu to an independent submenu array. This submenu array is not counted in the size() of the menu, and menu items in this submenu can't return a valid index into the \b main menu. Therefore menu items that are located in such a submenu return -1 when value() is called. This may be changed in a future version. You can use mvalue() instead to retrieve the last picked menu item directly. \returns Index of the last chosen menu item or -1 (see description). \see const Fl_Menu_Item *mvalue() */ int Fl_Menu_::value() const { if (!value_) return -1; if (menu() && value_ >= menu() && value_ < menu() + size()) return (int)(value_ - menu_); return -1; } /** When user picks a menu item, call this. It will do the callback. Unfortunately this also casts away const for the checkboxes, but this was necessary so non-checkbox menus can really be declared 'const'. \param[in] v The menu item that was picked by the user. \returns The same Fl_Menu_Item* that was set (\c v). */ const Fl_Menu_Item* Fl_Menu_::picked(const Fl_Menu_Item* v) { if (v) { if (v->radio()) { if (!v->value()) { // they are turning on a radio item set_changed(); setonly((Fl_Menu_Item*)v); } redraw(); } else if (v->flags & FL_MENU_TOGGLE) { set_changed(); ((Fl_Menu_Item*)v)->flags ^= FL_MENU_VALUE; redraw(); } else if (v != value_) { // normal item set_changed(); } prev_value_ = value_; value_ = v; if (when()&(FL_WHEN_CHANGED|FL_WHEN_RELEASE)) { if (changed() || when()&FL_WHEN_NOT_CHANGED) { if (value_ && value_->callback_) value_->do_callback((Fl_Widget*)this); else do_callback(); } } } return v; } /* Scans an array of Fl_Menu_Item's that begins at start, searching for item. Returns NULL if item is not found. If item is present, returns start, unless item belongs to an FL_SUBMENU_POINTER-adressed array of items, in which case the first item of this array is returned. */ static Fl_Menu_Item *first_submenu_item(Fl_Menu_Item *item, Fl_Menu_Item *start) { Fl_Menu_Item* m = start; int nest = 0; // will indicate submenu nesting depth while (1) { // loop over all menu items if (!m->text) { // m is a null item if (!nest) return NULL; // item was not found nest--; // m marks the end of a submenu -> decrement submenu nesting depth } else { // a true item if (m == item) return start; // item is found, return menu start item if (m->flags & FL_SUBMENU_POINTER) { // scan the detached submenu which begins at m->user_data() Fl_Menu_Item *first = first_submenu_item(item, (Fl_Menu_Item*)m->user_data()); if (first) return first; // if item was found in the submenu, return } else if (m->flags & FL_SUBMENU) { // a direct submenu nest++; // increment submenu nesting depth } } m++; // step to next menu item } } /** Turns the radio item "on" for the menu item and turns "off" adjacent radio items of the same group. */ void Fl_Menu_::setonly(Fl_Menu_Item* item) { // find the first item of the (sub)menu containing item Fl_Menu_Item* first = first_submenu_item(item, menu_); if (!first) return; // item does not belong to our menu item->flags |= FL_MENU_RADIO | FL_MENU_VALUE; Fl_Menu_Item* j; for (j = item; ; ) { // go down if (j->flags & FL_MENU_DIVIDER) break; // stop on divider lines j++; if (!j->text || !j->radio()) break; // stop after group j->clear(); } for (j = item-1; j>=first; j--) { // go up //DEBUG printf("GO UP: WORKING ON: item='%s', flags=%x\n", j->text, j->flags); if (!j->text || (j->flags&FL_MENU_DIVIDER) || !j->radio()) break; j->clear(); } } /** Turns the radio item "on" for the menu item and turns "off" adjacent radio items set. \note This method is dangerous if radio items are first in the menu. Make sure that \p first is set ciorrectly or use Fl_Menu_::setonly(Fl_Menu_Item*) instead. \param[in] first start of menu array or NULL (default) if the radio group is not the first item */ void Fl_Menu_Item::setonly(Fl_Menu_Item const* first) { flags |= FL_MENU_RADIO | FL_MENU_VALUE; Fl_Menu_Item* j; for (j = this; ; ) { // go down if (j->flags & FL_MENU_DIVIDER) break; // stop on divider lines j++; if (!j->text || !j->radio()) break; // stop after group j->clear(); } if (this != first) for (j = this-1; ; j--) { // go up if (!j->text || (j->flags&FL_MENU_DIVIDER) || !j->radio()) break; j->clear(); if (j == first) break; } } /** Creates a new Fl_Menu_ widget using the given position, size, and label string. menu() is initialized to null. */ Fl_Menu_::Fl_Menu_(int X,int Y,int W,int H,const char* l) : Fl_Widget(X,Y,W,H,l), menu_(NULL), value_(NULL), prev_value_(NULL), alloc(0), down_box_(FL_NO_BOX), menu_box_(FL_NO_BOX), textfont_(FL_HELVETICA), textsize_(FL_NORMAL_SIZE), textcolor_(FL_FOREGROUND_COLOR) { set_flag(SHORTCUT_LABEL); box(FL_UP_BOX); when(FL_WHEN_RELEASE_ALWAYS); selection_color(FL_SELECTION_COLOR); } /** This returns the number of Fl_Menu_Item structures that make up the menu, correctly counting submenus. This includes the "terminator" item at the end. To copy a menu array you need to copy size()*sizeof(Fl_Menu_Item) bytes. If the menu is NULL this returns zero (an empty menu will return 1). */ int Fl_Menu_::size() const { if (!menu_) return 0; return menu_->size(); } /** Sets the menu array pointer directly. If the old menu is private it is deleted. NULL is allowed and acts the same as a zero-length menu. If you try to modify the array (with add(), replace(), or remove()) a private copy is automatically done. */ void Fl_Menu_::menu(const Fl_Menu_Item* m) { clear(); prev_value_ = NULL; value_ = menu_ = (Fl_Menu_Item*)m; } // this version is ok with new Fl_Menu_add code with fl_menu_array_owner: /** Sets the menu array pointer with a copy of m that will be automatically deleted. If userdata \p ud is not NULL, then all user data pointers are changed in the menus as well. See void Fl_Menu_::menu(const Fl_Menu_Item* m). */ void Fl_Menu_::copy(const Fl_Menu_Item* m, void* ud) { unsigned int n = m->size(); Fl_Menu_Item* newMenu = new Fl_Menu_Item[n]; memcpy(newMenu, m, n*sizeof(Fl_Menu_Item)); menu(newMenu); alloc = 1; // make destructor free array, but not strings // for convenience, provide way to change all the user data pointers: if (ud) for (; n--;) { if (newMenu->callback_) newMenu->user_data_ = ud; newMenu++; } } Fl_Menu_::~Fl_Menu_() { clear(); } // Fl_Menu::add() uses this to indicate the owner of the dynamically- // expanding array. We must not free this array: Fl_Menu_* fl_menu_array_owner = 0; /** Same as menu(NULL), set the array pointer to null, indicating a zero-length menu. Menus must not be cleared during a callback to the same menu. */ void Fl_Menu_::clear() { if (alloc) { if (alloc > 1) { // See GitHub issue #875: we can't release "everything" // for several reasons. Maybe we can do better if we create // a new menu system based on Fl_Widget in 1.5.0 or later. // Fl_Image's and Fl_Multi_Label's and their linked objects // can't be released automatically. However, we must take care // not to free() images or Fl_Multi_Label's because they can // either be static or are allocated by operator new. for (int i = size(); i--;) { if (!menu_[i].text) continue; switch(menu_[i].labeltype_) { case _FL_IMAGE_LABEL: break; case _FL_MULTI_LABEL: break; default: free((void*)menu_[i].text); break; } } } if (this == fl_menu_array_owner) fl_menu_array_owner = 0; else delete[] menu_; alloc = 0; } menu_ = 0; value_ = prev_value_ = 0; } /** Clears the specified submenu pointed to by \p index of all menu items. This method is useful for clearing a submenu so that it can be re-populated with new items. Example: a "File/Recent Files/..." submenu that shows the last few files that have been opened. The specified \p index must point to a submenu. The submenu is cleared with remove(). If the menu array was directly set with menu(x), then copy() is done to make a private array. \warning Since this method can change the internal menu array, any menu item pointers or indices the application may have cached can become stale, and should be recalculated/refreshed. \b Example: \code int index = menubar->find_index("File/Recent"); // get index of "File/Recent" submenu if ( index != -1 ) menubar->clear_submenu(index); // clear the submenu menubar->add("File/Recent/Aaa"); menubar->add("File/Recent/Bbb"); [..] \endcode \param index The index of the submenu to be cleared \returns 0 on success, -1 if the index is out of range or not a submenu \see remove(int) */ int Fl_Menu_::clear_submenu(int index) { if ( index < 0 || index >= size() ) return(-1); if ( ! (menu_[index].flags & FL_SUBMENU) ) return(-1); ++index; // advance to first item in submenu while ( index < size() ) { // keep remove()ing top item until end is reached if ( menu_[index].text == 0 ) break; // end of this submenu? done remove(index); // remove items/submenus } return(0); } fltk-1.4.3/src/d1.xbm0000644000175000017500000000042615004135251014412 0ustar albrechtalbrecht#define d1_width 16 #define d1_height 16 static unsigned char d1_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00, 0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; fltk-1.4.3/src/Fl_Window_fullscreen.cxx0000644000175000017500000000516615004135251020242 0ustar albrechtalbrecht// // Fullscreen window support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Window_Driver.H" void Fl_Window::border(int b) { if (b) { if (border()) return; clear_flag(NOBORDER); } else { if (!border()) return; set_flag(NOBORDER); } pWindowDriver->use_border(); } /* Note: The previous implementation toggled border(). With this new implementation this is not necessary. Additionally, if we do that, the application may lose focus when switching out of fullscreen mode with some window managers. Besides, the API does not say that the FLTK border state should be toggled; it only says that the borders should not be *visible*. */ void Fl_Window::fullscreen() { if (!is_resizable()) return; if (!maximize_active()) { no_fullscreen_x = x(); no_fullscreen_y = y(); no_fullscreen_w = w(); no_fullscreen_h = h(); } if (shown() && !(flags() & Fl_Widget::FULLSCREEN)) { pWindowDriver->fullscreen_on(); } else { set_flag(FULLSCREEN); } } void Fl_Window::fullscreen_off(int X,int Y,int W,int H) { if (shown() && (flags() & Fl_Widget::FULLSCREEN)) { pWindowDriver->fullscreen_off(X, Y, W, H); } else { clear_flag(FULLSCREEN); } if (!maximize_active()) no_fullscreen_x = no_fullscreen_y = no_fullscreen_w = no_fullscreen_h = 0; } void Fl_Window::fullscreen_off() { if (!no_fullscreen_x && !no_fullscreen_y) { // Window was initially created fullscreen - default to current monitor no_fullscreen_x = x(); no_fullscreen_y = y(); } fullscreen_off(no_fullscreen_x, no_fullscreen_y, no_fullscreen_w, no_fullscreen_h); } void Fl_Window::fullscreen_screens(int top, int bottom, int left, int right) { if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) { fullscreen_screen_top = -1; fullscreen_screen_bottom = -1; fullscreen_screen_left = -1; fullscreen_screen_right = -1; pWindowDriver->fullscreen_screens(false); } else { fullscreen_screen_top = top; fullscreen_screen_bottom = bottom; fullscreen_screen_left = left; fullscreen_screen_right = right; pWindowDriver->fullscreen_screens(true); } if (shown() && fullscreen_active()) pWindowDriver->fullscreen_on(); } fltk-1.4.3/src/utf8_internal.h0000644000175000017500000000213515004135251016330 0ustar albrechtalbrecht/* * Internal UTF-8 header file for the Fast Light Tool Kit (FLTK). * * Copyright 1998-2016 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* ---------------- Note to editors: ---------------- This file may only contain common, platform-independent function declarations used internally in FLTK. It may be #included everywhere in source files in the library, but not in public header files. */ #ifndef _SRC__FL_UTF8_H #define _SRC__FL_UTF8_H # ifdef __cplusplus extern "C" { # endif unsigned short XUtf8IsNonSpacing( unsigned int ucs); unsigned short XUtf8IsRightToLeft( unsigned int ucs); int XUtf8Tolower( int ucs); int XUtf8Toupper( int ucs); # ifdef __cplusplus } # endif #endif /* _SRC__FL_UTF8_H */ fltk-1.4.3/src/Fl_Tooltip.cxx0000644000175000017500000003060015004135251016172 0ustar albrechtalbrecht// // Tooltip source file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include "Fl_System_Driver.H" #include "Fl_Window_Driver.H" #include "Fl_Screen_Driver.H" #include float Fl_Tooltip::delay_ = 1.0f; float Fl_Tooltip::hidedelay_ = 12.0f; float Fl_Tooltip::hoverdelay_ = 0.2f; Fl_Color Fl_Tooltip::color_ = fl_color_cube(FL_NUM_RED - 1, FL_NUM_GREEN - 1, FL_NUM_BLUE - 2); Fl_Color Fl_Tooltip::textcolor_ = FL_BLACK; Fl_Font Fl_Tooltip::font_ = FL_HELVETICA; Fl_Fontsize Fl_Tooltip::size_ = -1; int Fl_Tooltip::margin_width_ = 3; int Fl_Tooltip::margin_height_ = 3; int Fl_Tooltip::wrap_width_ = 400; const int Fl_Tooltip::draw_symbols_ = 1; static const char* tip; static void tooltip_hide_timeout(void*); /** This widget creates a tooltip box window, with no caption. */ class Fl_TooltipBox : public Fl_Menu_Window { public: /** Creates the box window */ Fl_TooltipBox() : Fl_Menu_Window(0, 0) { set_override(); set_tooltip_window(); Fl_Window_Driver::driver(this)->set_popup_window(); end(); } void draw() FL_OVERRIDE; void layout(); /** Shows the tooltip windows only if a tooltip text is available. */ void show() FL_OVERRIDE { if (!tip) return; Fl_Menu_Window::show(); } int handle(int e) FL_OVERRIDE { if (e == FL_PUSH || e == FL_KEYDOWN) { hide(); Fl::remove_timeout(tooltip_hide_timeout); return 1; } return Fl_Menu_Window::handle(e); } }; Fl_Widget* Fl_Tooltip::widget_ = 0; static Fl_TooltipBox *window = 0; static int currentTooltipY, currentTooltipH; Fl_Window *Fl_Tooltip::current_window(void) { return (Fl_Window*)window; } void Fl_TooltipBox::layout() { fl_font(Fl_Tooltip::font(), Fl_Tooltip::size()); int ww = Fl_Tooltip::wrap_width(); int hh = 0; fl_measure(tip, ww, hh, Fl_Tooltip::draw_symbols_); ww += (Fl_Tooltip::margin_width() * 2); hh += (Fl_Tooltip::margin_height() * 2); // find position on the screen of the widget: int ox = Fl::event_x_root(), oy; if (currentTooltipH > 30) { oy = Fl::event_y_root()+13; } else { oy = currentTooltipY + currentTooltipH+2; for (Fl_Widget* p = Fl_Tooltip::current(); p; p = p->window()) { oy += p->y(); } } if (Fl::screen_driver()->screen_boundaries_known()) { int scr_x, scr_y, scr_w, scr_h; Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); if (ox+ww > scr_x+scr_w) ox = scr_x+scr_w - ww; if (ox < scr_x) ox = scr_x; if (currentTooltipH > 30) { if (oy+hh > scr_y+scr_h) oy -= 23+hh; } else { if (oy+hh > scr_y+scr_h) oy -= (4+hh+currentTooltipH); } if (oy < scr_y) oy = scr_y; } resize(ox, oy, ww, hh); } void Fl_TooltipBox::draw() { draw_box(FL_BORDER_BOX, 0, 0, w(), h(), Fl_Tooltip::color()); fl_color(Fl_Tooltip::textcolor()); fl_font(Fl_Tooltip::font(), Fl_Tooltip::size()); int X = Fl_Tooltip::margin_width(); int Y = Fl_Tooltip::margin_height(); int W = w() - (Fl_Tooltip::margin_width()*2); int H = h() - (Fl_Tooltip::margin_height()*2); fl_draw(tip, X, Y, W, H, Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_WRAP), 0, Fl_Tooltip::draw_symbols_); } static char recent_tooltip; static void recent_timeout(void*) { #ifdef DEBUG puts("recent_timeout();"); #endif // DEBUG recent_tooltip = 0; } static char recursion; // Is top level window iconified? static int top_win_iconified_() { Fl_Widget *w = Fl_Tooltip::current(); if ( !w ) return 0; Fl_Window *topwin = w->top_window(); if ( !topwin ) return 0; return !topwin->visible() ? 1 : 0; } static void tooltip_hide_timeout(void*) { if (window) window->hide(); recent_tooltip = 0; } static void tooltip_timeout(void*) { #ifdef DEBUG puts("tooltip_timeout();"); #endif // DEBUG if (recursion) return; recursion = 1; if (!top_win_iconified_()) { // no tooltip if top win iconified (STR #3157) if (!tip || !*tip) { if (window) window->hide(); Fl::remove_timeout(tooltip_hide_timeout); } else { int condition = 1; // bugfix: no need to refactor if (Fl::system_driver()->use_tooltip_timeout_condition()) condition = (Fl::grab() == NULL); if ( condition ) { if (!window) window = new Fl_TooltipBox; // this cast bypasses the normal Fl_Window label() code: ((Fl_Widget *) window)->label(tip); window->layout(); window->redraw(); // printf("tooltip_timeout: Showing window %p with tooltip \"%s\"...\n", // window, tip ? tip : "(null)"); window->show(); Fl::add_timeout(Fl_Tooltip::hidedelay(), tooltip_hide_timeout); } } } Fl::remove_timeout(recent_timeout); recent_tooltip = 1; recursion = 0; } /** This method is called when the mouse pointer enters a widget.

If this widget or one of its parents has a tooltip, enter it. This will do nothing if this is the current widget (even if the mouse moved out so an exit() was done and then moved back in). If no tooltip can be found do Fl_Tooltip::exit_(). If you don't want this behavior (for instance if you want the tooltip to reappear when the mouse moves back in) call the fancier enter_area() below. */ void Fl_Tooltip::enter_(Fl_Widget* w) { #ifdef DEBUG printf("Fl_Tooltip::enter_(w=%p)\n", w); printf(" window=%p\n", window); #endif // DEBUG if (w && w->as_window() && ((Fl_Window*)w)->tooltip_window()) { // Fix STR #2650: if there's no better place for a tooltip window, don't move it. int oldx = w->x(); int oldy = w->y(); ((Fl_TooltipBox*)w)->layout(); if (w->x() == oldx && w->y() == oldy) return; } // find the enclosing group with a tooltip: Fl_Widget* tw = w; for (;;) { if (!tw) {exit_(0); return;} if (tw == widget_) return; if (tw->tooltip()) break; tw = tw->parent(); } enter_area(w, 0, 0, w->w(), w->h(), tw->tooltip()); } /** Sets the current widget target. Acts as though enter(widget) was done but does not pop up a tooltip. This is useful to prevent a tooltip from reappearing when a modal overlapping window is deleted. FLTK does this automatically when you click the mouse button. */ void Fl_Tooltip::current(Fl_Widget* w) { #ifdef DEBUG printf("Fl_Tooltip::current(w=%p)\n", w); #endif // DEBUG exit_(0); // find the enclosing group with a tooltip: Fl_Widget* tw = w; for (;;) { if (!tw) return; if (tw->tooltip()) break; tw = tw->parent(); } // act just like Fl_Tooltip::enter_() except we can remember a zero: widget_ = w; } // Hide any visible tooltip. /** This method is called when the mouse pointer leaves a widget. */ void Fl_Tooltip::exit_(Fl_Widget *w) { #ifdef DEBUG printf("Fl_Tooltip::exit_(w=%p)\n", w); printf(" widget=%p, window=%p\n", widget_, window); #endif // DEBUG if (!widget_ || (w && w == window)) return; widget_ = 0; Fl::remove_timeout(tooltip_timeout); Fl::remove_timeout(recent_timeout); if (window && window->visible()) { window->hide(); Fl::remove_timeout(tooltip_hide_timeout); } if (recent_tooltip) { if (Fl::event_state() & FL_BUTTONS) recent_tooltip = 0; else Fl::add_timeout(Fl_Tooltip::hoverdelay(), recent_timeout); } } // Get ready to display a tooltip. The widget and the xywh box inside // it define an area the tooltip is for, this along with the current // mouse position places the tooltip (the mouse is assumed to point // inside or near the box). /** You may be able to use this to provide tooltips for internal pieces of your widget. Call this after setting Fl::belowmouse() to your widget (because that calls the above enter() method). Then figure out what thing the mouse is pointing at, and call this with the widget (this pointer is used to remove the tooltip if the widget is deleted or hidden, and to locate the tooltip), the rectangle surrounding the area, relative to the top-left corner of the widget (used to calculate where to put the tooltip), and the text of the tooltip (which must be a pointer to static data as it is not copied). */ void Fl_Tooltip::enter_area(Fl_Widget* wid, int x,int y,int w,int h, const char* t) { (void)x; (void)w; #ifdef DEBUG printf("Fl_Tooltip::enter_area(wid=%p, x=%d, y=%d, w=%d, h=%d, t=\"%s\")\n", wid, x, y, w, h, t ? t : "(null)"); printf(" recursion=%d, window=%p\n", recursion, window); #endif // DEBUG if (recursion) return; if (!t || !*t || !enabled()) { exit_(0); return; } // do nothing if it is the same: if (wid==widget_ /*&& x==X && y==currentTooltipY && w==W && h==currentTooltipH*/ && t==tip) return; Fl::remove_timeout(tooltip_timeout); Fl::remove_timeout(recent_timeout); // remember it: widget_ = wid; currentTooltipY = y; currentTooltipH = h; tip = t; // popup the tooltip immediately if it was recently up: if (recent_tooltip) { if (window) { window->hide(); Fl::remove_timeout(tooltip_hide_timeout); } Fl::add_timeout(Fl_Tooltip::hoverdelay(), tooltip_timeout); } else if (Fl_Tooltip::delay() < .1) { // possible fix for the Windows titlebar, it seems to want the // window to be destroyed, moving it messes up the parenting: if (Fl::system_driver()->use_recent_tooltip_fix() && window && window->visible()) { window->hide(); Fl::remove_timeout(tooltip_hide_timeout); } tooltip_timeout(0); } else { if (window && window->visible()) { window->hide(); Fl::remove_timeout(tooltip_hide_timeout); } Fl::add_timeout(Fl_Tooltip::delay(), tooltip_timeout); } #ifdef DEBUG printf(" tip=\"%s\", window->shown()=%d\n", tip ? tip : "(null)", window ? window->shown() : 0); #endif // DEBUG } void Fl_Tooltip::set_enter_exit_once_() { static char beenhere = 0; if (!beenhere) { beenhere = 1; Fl_Tooltip::enter = Fl_Tooltip::enter_; Fl_Tooltip::exit = Fl_Tooltip::exit_; } } /** Sets the current tooltip text. Sets a string of text to display in a popup tooltip window when the user hovers the mouse over the widget. The string is not copied, so make sure any formatted string is stored in a static, global, or allocated buffer. If you want a copy made and managed for you, use the copy_tooltip() method, which will manage the tooltip string automatically. If no tooltip is set, the tooltip of the parent is inherited. Setting a tooltip for a group and setting no tooltip for a child will show the group's tooltip instead. To avoid this behavior, you can set the child's tooltip to an empty string (""). \param[in] text New tooltip text (no copy is made) \see copy_tooltip(const char*), tooltip() */ void Fl_Widget::tooltip(const char *text) { Fl_Tooltip::set_enter_exit_once_(); if (flags() & COPIED_TOOLTIP) { // reassigning a copied tooltip remains the same copied tooltip if (tooltip_ == text) return; free((void*)(tooltip_)); // free maintained copy clear_flag(COPIED_TOOLTIP); // disable copy flag (WE don't make copies) } tooltip_ = text; } /** Sets the current tooltip text. Unlike tooltip(), this method allocates a copy of the tooltip string instead of using the original string pointer. The internal copy will automatically be freed whenever you assign a new tooltip or when the widget is destroyed. If no tooltip is set, the tooltip of the parent is inherited. Setting a tooltip for a group and setting no tooltip for a child will show the group's tooltip instead. To avoid this behavior, you can set the child's tooltip to an empty string (""). \param[in] text New tooltip text (an internal copy is made and managed) \see tooltip(const char*), tooltip() */ void Fl_Widget::copy_tooltip(const char *text) { Fl_Tooltip::set_enter_exit_once_(); if (flags() & COPIED_TOOLTIP) free((void *)(tooltip_)); if (text) { set_flag(COPIED_TOOLTIP); tooltip_ = fl_strdup(text); } else { clear_flag(COPIED_TOOLTIP); tooltip_ = (char *)0; } } fltk-1.4.3/src/makedepend0000644000175000017500000062222715004135251015427 0ustar albrechtalbrecht# DO NOT DELETE THIS LINE -- make depend depends on it. drivers/Cairo/Fl_Cairo_Graphics_Driver.o: ../config.h drivers/Cairo/Fl_Cairo_Graphics_Driver.o: ../FL/fl_config.h drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Enumerations.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Fl.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/fl_attr.h drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Fl_Bitmap.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/fl_config.h drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Fl_Device.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/fl_draw.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Fl_Export.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Fl_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Fl_Image.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Fl_Pixmap.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Fl_Plugin.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Fl_Preferences.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Fl_RGB_Image.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/fl_types.h drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/Fl_Widget.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: ../FL/platform_types.h drivers/OpenGL/Fl_OpenGL_Display_Device.o: drivers/OpenGL/Fl_OpenGL_Display_Device.H drivers/OpenGL/Fl_OpenGL_Display_Device.o: drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../config.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Enumerations.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/fl_attr.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Bitmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Cairo.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/fl_casts.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/fl_config.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Device.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/fl_draw.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Export.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Gl_Window.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Pixmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Plugin.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Preferences.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_RGB_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/fl_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/fl_utf8.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Widget.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/Fl_Window.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/gl.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/math.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: ../FL/platform_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.o: drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../config.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Enumerations.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/fl_attr.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Bitmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Cairo.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/fl_casts.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/fl_config.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Device.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/fl_draw.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Export.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Gl_Window.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Pixmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Plugin.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Preferences.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_RGB_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/fl_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/fl_utf8.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Widget.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/Fl_Window.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/gl.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: ../FL/platform_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.o: drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../config.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Enumerations.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/fl_attr.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Bitmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Cairo.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/fl_casts.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/fl_config.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Device.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/fl_draw.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Export.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Gl_Window.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Pixmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Plugin.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Preferences.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_RGB_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/fl_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/fl_utf8.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Widget.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/Fl_Window.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/gl.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: ../FL/platform_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.o: drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../config.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Enumerations.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/fl_attr.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Bitmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Cairo.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/fl_casts.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/fl_config.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Device.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/fl_draw.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Export.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Gl_Window.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Pixmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Plugin.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Preferences.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_RGB_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/fl_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/fl_utf8.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Widget.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/Fl_Window.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/gl.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: ../FL/platform_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.o: drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../config.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Enumerations.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/fl_attr.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Bitmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Cairo.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/fl_casts.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/fl_config.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Device.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/fl_draw.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Export.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Gl_Window.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Pixmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Plugin.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Preferences.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_RGB_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/fl_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/fl_utf8.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Widget.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/Fl_Window.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/gl.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/math.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: ../FL/platform_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.o: drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Enumerations.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Fl.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/fl_attr.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Fl_Bitmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/fl_config.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Fl_Device.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/fl_draw.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Fl_Export.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Fl_Graphics_Driver.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Fl_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Fl_Pixmap.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Fl_Plugin.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Fl_Preferences.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Fl_RGB_Image.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/fl_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/Fl_Widget.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/gl.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/math.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: ../FL/platform_types.h drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.o: drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../config.h drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Enumerations.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/filename.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/fl_ask.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/fl_attr.h drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Bitmap.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Box.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Button.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Cairo.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/fl_casts.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Check_Button.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Choice.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/fl_config.h drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Device.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Double_Window.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/fl_draw.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Export.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Group.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Image.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Input.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Input_.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Int_Input.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Light_Button.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Menu_.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Menu_Item.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Multi_Label.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Paged_Device.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Pixmap.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Plugin.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_PostScript.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Preferences.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Printer.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Progress.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Repeat_Button.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Return_Button.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Round_Button.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Spinner.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/fl_string_functions.h drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/fl_types.h drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/fl_utf8.h drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Widget.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Widget_Surface.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/Fl_Window.H drivers/Posix/Fl_Posix_Printer_Driver.o: ../FL/platform_types.h drivers/Posix/Fl_Posix_Printer_Driver.o: ../src/flstring.h drivers/Posix/Fl_Posix_Printer_Driver.o: ../src/print_panel.cxx drivers/Posix/Fl_Posix_Printer_Driver.o: drivers/Posix/Fl_Posix_System_Driver.H drivers/Posix/Fl_Posix_Printer_Driver.o: drivers/PostScript/Fl_PostScript_Graphics_Driver.H drivers/Posix/Fl_Posix_Printer_Driver.o: Fl_System_Driver.H drivers/Posix/Fl_Posix_Printer_Driver.o: print_panel.h drivers/Posix/Fl_Posix_System_Driver.o: ../config.h drivers/Posix/Fl_Posix_System_Driver.o: ../FL/Enumerations.H drivers/Posix/Fl_Posix_System_Driver.o: ../FL/filename.H drivers/Posix/Fl_Posix_System_Driver.o: ../FL/Fl.H drivers/Posix/Fl_Posix_System_Driver.o: ../FL/fl_attr.h drivers/Posix/Fl_Posix_System_Driver.o: ../FL/Fl_Cairo.H drivers/Posix/Fl_Posix_System_Driver.o: ../FL/fl_casts.H drivers/Posix/Fl_Posix_System_Driver.o: ../FL/fl_config.h drivers/Posix/Fl_Posix_System_Driver.o: ../FL/Fl_Export.H drivers/Posix/Fl_Posix_System_Driver.o: ../FL/Fl_File_Icon.H drivers/Posix/Fl_Posix_System_Driver.o: ../FL/Fl_Preferences.H drivers/Posix/Fl_Posix_System_Driver.o: ../FL/fl_string_functions.h drivers/Posix/Fl_Posix_System_Driver.o: ../FL/fl_types.h drivers/Posix/Fl_Posix_System_Driver.o: ../FL/fl_utf8.h drivers/Posix/Fl_Posix_System_Driver.o: ../FL/platform_types.h drivers/Posix/Fl_Posix_System_Driver.o: drivers/Posix/Fl_Posix_System_Driver.H drivers/Posix/Fl_Posix_System_Driver.o: flstring.h drivers/Posix/Fl_Posix_System_Driver.o: Fl_System_Driver.H drivers/PostScript/Fl_PostScript.o: ../config.h drivers/PostScript/Fl_PostScript.o: ../FL/Enumerations.H drivers/PostScript/Fl_PostScript.o: ../FL/filename.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl.H drivers/PostScript/Fl_PostScript.o: ../FL/fl_ask.H drivers/PostScript/Fl_PostScript.o: ../FL/fl_attr.h drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Bitmap.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Box.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Browser.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Button.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Cairo.H drivers/PostScript/Fl_PostScript.o: ../FL/fl_callback_macros.H drivers/PostScript/Fl_PostScript.o: ../FL/fl_casts.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Check_Button.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Choice.H drivers/PostScript/Fl_PostScript.o: ../FL/fl_config.h drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Device.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Double_Window.H drivers/PostScript/Fl_PostScript.o: ../FL/fl_draw.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Export.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_File_Browser.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_File_Chooser.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_File_Icon.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_File_Input.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Group.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Image.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Image_Surface.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Input.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Input_.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Light_Button.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Menu_.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Menu_Button.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Menu_Item.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Multi_Label.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Native_File_Chooser.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Paged_Device.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_PDF_File_Surface.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Plugin.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_PostScript.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Preferences.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Return_Button.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Shared_Image.H drivers/PostScript/Fl_PostScript.o: ../FL/fl_string_functions.h drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Tile.H drivers/PostScript/Fl_PostScript.o: ../FL/fl_types.h drivers/PostScript/Fl_PostScript.o: ../FL/fl_utf8.h drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Widget.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Widget_Surface.H drivers/PostScript/Fl_PostScript.o: ../FL/Fl_Window.H drivers/PostScript/Fl_PostScript.o: ../FL/platform.H drivers/PostScript/Fl_PostScript.o: ../FL/platform_types.h drivers/PostScript/Fl_PostScript.o: ../FL/x11.H drivers/PostScript/Fl_PostScript.o: drivers/PostScript/Fl_PostScript_Graphics_Driver.H drivers/PostScript/Fl_PostScript.o: Fl_System_Driver.H drivers/PostScript/Fl_PostScript_image.o: ../config.h drivers/PostScript/Fl_PostScript_image.o: ../FL/Enumerations.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl.H drivers/PostScript/Fl_PostScript_image.o: ../FL/fl_attr.h drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Bitmap.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Cairo.H drivers/PostScript/Fl_PostScript_image.o: ../FL/fl_casts.H drivers/PostScript/Fl_PostScript_image.o: ../FL/fl_config.h drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Device.H drivers/PostScript/Fl_PostScript_image.o: ../FL/fl_draw.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Export.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Group.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Image.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Paged_Device.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Pixmap.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Plugin.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_PostScript.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Preferences.H drivers/PostScript/Fl_PostScript_image.o: ../FL/fl_types.h drivers/PostScript/Fl_PostScript_image.o: ../FL/fl_utf8.h drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Widget.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Widget_Surface.H drivers/PostScript/Fl_PostScript_image.o: ../FL/Fl_Window.H drivers/PostScript/Fl_PostScript_image.o: ../FL/platform_types.h drivers/PostScript/Fl_PostScript_image.o: drivers/PostScript/Fl_PostScript_Graphics_Driver.H drivers/SVG/Fl_SVG_File_Surface.o: ../config.h drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Enumerations.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/filename.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/fl_attr.h drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Bitmap.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Cairo.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/fl_casts.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/fl_config.h drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Device.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/fl_draw.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Export.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Graphics_Driver.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Group.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Image.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Pixmap.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Plugin.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Preferences.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_RGB_Image.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/fl_string_functions.h drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_SVG_File_Surface.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/fl_types.h drivers/SVG/Fl_SVG_File_Surface.o: ../FL/fl_utf8.h drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Widget.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Widget_Surface.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/Fl_Window.H drivers/SVG/Fl_SVG_File_Surface.o: ../FL/math.h drivers/SVG/Fl_SVG_File_Surface.o: ../FL/platform_types.h drivers/SVG/Fl_SVG_File_Surface.o: Fl_System_Driver.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../config.h drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Enumerations.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/fl_attr.h drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Bitmap.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Cairo.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/fl_casts.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/fl_config.h drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Device.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/fl_draw.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Export.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Graphics_Driver.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Group.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Image.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Pixmap.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Plugin.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Preferences.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Rect.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_RGB_Image.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Scrollbar.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Slider.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Text_Buffer.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Text_Display.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Text_Editor.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/fl_types.h drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/fl_utf8.h drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Valuator.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/Fl_Widget.H drivers/Unix/Fl_Unix_Screen_Driver.o: ../FL/platform_types.h drivers/Unix/Fl_Unix_Screen_Driver.o: drivers/Unix/Fl_Unix_Screen_Driver.H drivers/Unix/Fl_Unix_Screen_Driver.o: Fl_Screen_Driver.H drivers/Unix/Fl_Unix_System_Driver.o: ../config.h drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Enumerations.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/filename.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/fl_attr.h drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Bitmap.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Browser.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Cairo.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/fl_casts.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/fl_config.h drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Device.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/fl_draw.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Export.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_File_Browser.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_File_Icon.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Graphics_Driver.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Group.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Image.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Pixmap.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Plugin.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Preferences.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Rect.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_RGB_Image.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Scrollbar.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Slider.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/fl_string_functions.h drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Text_Buffer.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Text_Display.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Text_Editor.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/fl_types.h drivers/Unix/Fl_Unix_System_Driver.o: ../FL/fl_utf8.h drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Valuator.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/Fl_Widget.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/platform.H drivers/Unix/Fl_Unix_System_Driver.o: ../FL/platform_types.h drivers/Unix/Fl_Unix_System_Driver.o: ../FL/x11.H drivers/Unix/Fl_Unix_System_Driver.o: drivers/Posix/Fl_Posix_System_Driver.H drivers/Unix/Fl_Unix_System_Driver.o: drivers/Unix/Fl_Unix_Screen_Driver.H drivers/Unix/Fl_Unix_System_Driver.o: drivers/Unix/Fl_Unix_System_Driver.H drivers/Unix/Fl_Unix_System_Driver.o: flstring.h drivers/Unix/Fl_Unix_System_Driver.o: Fl_Screen_Driver.H drivers/Unix/Fl_Unix_System_Driver.o: Fl_String.H drivers/Unix/Fl_Unix_System_Driver.o: Fl_System_Driver.H drivers/Unix/Fl_Unix_System_Driver.o: Fl_Timeout.h drivers/X11/Fl_X11_Gl_Window_Driver.o: ../config.h drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Enumerations.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/fl_attr.h drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Bitmap.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Cairo.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/fl_casts.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/fl_config.h drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Device.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/fl_draw.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Export.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Gl_Window.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Graphics_Driver.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Group.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Image.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Pixmap.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Plugin.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Preferences.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Rect.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_RGB_Image.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Scrollbar.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Slider.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Text_Buffer.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Text_Display.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Text_Editor.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/fl_types.h drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/fl_utf8.h drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Valuator.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Widget.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/Fl_Window.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/gl.h drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/platform.H drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/platform_types.h drivers/X11/Fl_X11_Gl_Window_Driver.o: ../FL/x11.H drivers/X11/Fl_X11_Gl_Window_Driver.o: drivers/X11/Fl_X11_Gl_Window_Driver.H drivers/X11/Fl_X11_Gl_Window_Driver.o: Fl_Gl_Choice.H drivers/X11/Fl_X11_Gl_Window_Driver.o: Fl_Gl_Window_Driver.H drivers/X11/Fl_X11_Gl_Window_Driver.o: Fl_Screen_Driver.H drivers/X11/fl_X11_platform_init.o: ../config.h drivers/X11/fl_X11_platform_init.o: ../FL/Enumerations.H drivers/X11/fl_X11_platform_init.o: ../FL/filename.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl.H drivers/X11/fl_X11_platform_init.o: ../FL/fl_attr.h drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Bitmap.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Cairo.H drivers/X11/fl_X11_platform_init.o: ../FL/fl_casts.H drivers/X11/fl_X11_platform_init.o: ../FL/fl_config.h drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Copy_Surface.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Device.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Double_Window.H drivers/X11/fl_X11_platform_init.o: ../FL/fl_draw.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Export.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Graphics_Driver.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Group.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Image.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Image_Surface.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Overlay_Window.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Pixmap.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Plugin.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Preferences.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Rect.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_RGB_Image.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Scrollbar.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Shared_Image.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Slider.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Text_Buffer.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Text_Display.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Text_Editor.H drivers/X11/fl_X11_platform_init.o: ../FL/fl_types.h drivers/X11/fl_X11_platform_init.o: ../FL/fl_utf8.h drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Valuator.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Widget.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Widget_Surface.H drivers/X11/fl_X11_platform_init.o: ../FL/Fl_Window.H drivers/X11/fl_X11_platform_init.o: ../FL/platform.H drivers/X11/fl_X11_platform_init.o: ../FL/platform_types.h drivers/X11/fl_X11_platform_init.o: ../FL/x11.H drivers/X11/fl_X11_platform_init.o: drivers/Posix/Fl_Posix_System_Driver.H drivers/X11/fl_X11_platform_init.o: drivers/Unix/Fl_Unix_Screen_Driver.H drivers/X11/fl_X11_platform_init.o: drivers/Unix/Fl_Unix_System_Driver.H drivers/X11/fl_X11_platform_init.o: drivers/X11/Fl_X11_Screen_Driver.H drivers/X11/fl_X11_platform_init.o: drivers/X11/Fl_X11_Window_Driver.H drivers/X11/fl_X11_platform_init.o: drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H drivers/X11/fl_X11_platform_init.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/X11/fl_X11_platform_init.o: drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H drivers/X11/fl_X11_platform_init.o: Fl_Screen_Driver.H drivers/X11/fl_X11_platform_init.o: Fl_System_Driver.H drivers/X11/fl_X11_platform_init.o: Fl_Window_Driver.H drivers/X11/Fl_X11_Screen_Driver.o: ../config.h drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Enumerations.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/filename.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/fl_ask.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/fl_attr.h drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Bitmap.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Box.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Cairo.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/fl_casts.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/fl_config.h drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Device.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Double_Window.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/fl_draw.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Export.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Graphics_Driver.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Group.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Image.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Image_Surface.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Overlay_Window.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Pixmap.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Plugin.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Preferences.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Rect.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_RGB_Image.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Scrollbar.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Shared_Image.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Slider.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/fl_string_functions.h drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Text_Buffer.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Text_Display.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Text_Editor.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Tooltip.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/fl_types.h drivers/X11/Fl_X11_Screen_Driver.o: ../FL/fl_utf8.h drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Valuator.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Widget.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Widget_Surface.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/Fl_Window.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/platform.H drivers/X11/Fl_X11_Screen_Driver.o: ../FL/platform_types.h drivers/X11/Fl_X11_Screen_Driver.o: ../FL/x11.H drivers/X11/Fl_X11_Screen_Driver.o: drivers/Posix/Fl_Posix_System_Driver.H drivers/X11/Fl_X11_Screen_Driver.o: drivers/Unix/Fl_Unix_Screen_Driver.H drivers/X11/Fl_X11_Screen_Driver.o: drivers/X11/Fl_X11_Screen_Driver.H drivers/X11/Fl_X11_Screen_Driver.o: drivers/X11/Fl_X11_Window_Driver.H drivers/X11/Fl_X11_Screen_Driver.o: flstring.h drivers/X11/Fl_X11_Screen_Driver.o: Fl_Screen_Driver.H drivers/X11/Fl_X11_Screen_Driver.o: Fl_System_Driver.H drivers/X11/Fl_X11_Screen_Driver.o: Fl_Timeout.h drivers/X11/Fl_X11_Screen_Driver.o: Fl_Window_Driver.H drivers/X11/Fl_X11_Window_Driver.o: ../config.h drivers/X11/Fl_X11_Window_Driver.o: ../FL/Enumerations.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/fl_ask.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/fl_attr.h drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Bitmap.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Cairo.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/fl_casts.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/fl_config.h drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Device.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Double_Window.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/fl_draw.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Export.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Graphics_Driver.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Group.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Image.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Image_Surface.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Overlay_Window.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Pixmap.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Plugin.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Preferences.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Rect.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_RGB_Image.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Scrollbar.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Shared_Image.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Slider.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Text_Buffer.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Text_Display.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Text_Editor.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Tooltip.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/fl_types.h drivers/X11/Fl_X11_Window_Driver.o: ../FL/fl_utf8.h drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Valuator.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Widget.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Widget_Surface.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/Fl_Window.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/platform.H drivers/X11/Fl_X11_Window_Driver.o: ../FL/platform_types.h drivers/X11/Fl_X11_Window_Driver.o: ../FL/x11.H drivers/X11/Fl_X11_Window_Driver.o: drivers/Unix/Fl_Unix_Screen_Driver.H drivers/X11/Fl_X11_Window_Driver.o: drivers/X11/Fl_X11_Screen_Driver.H drivers/X11/Fl_X11_Window_Driver.o: drivers/X11/Fl_X11_Window_Driver.H drivers/X11/Fl_X11_Window_Driver.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/X11/Fl_X11_Window_Driver.o: Fl_Screen_Driver.H drivers/X11/Fl_X11_Window_Driver.o: Fl_Window_Driver.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../config.h drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Enumerations.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/fl_attr.h drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Bitmap.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Cairo.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/fl_casts.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/fl_config.h drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Copy_Surface.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Device.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/fl_draw.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Export.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Group.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Image.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Image_Surface.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Pixmap.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Plugin.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Preferences.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Rect.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_RGB_Image.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Scrollbar.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Shared_Image.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Slider.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Text_Buffer.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Text_Display.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Text_Editor.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/fl_types.h drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/fl_utf8.h drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Valuator.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Widget.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Widget_Surface.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/Fl_Window.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/platform.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/platform_types.h drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: ../FL/x11.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: drivers/Unix/Fl_Unix_Screen_Driver.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: drivers/X11/Fl_X11_Screen_Driver.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.o: Fl_Screen_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../config.h drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Enumerations.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Fl.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/fl_attr.h drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Fl_Bitmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/fl_config.h drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Fl_Device.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/fl_draw.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Fl_Export.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Fl_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Fl_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Fl_Pixmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Fl_Plugin.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Fl_Preferences.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Fl_RGB_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/fl_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/Fl_Widget.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/platform.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/platform_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver.o: ../FL/x11.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: drivers/Xlib/Fl_Font.H drivers/Xlib/Fl_Xlib_Graphics_Driver.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Enumerations.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Fl.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/fl_attr.h drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Fl_Bitmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/fl_config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Fl_Device.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/fl_draw.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Fl_Export.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Fl_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Fl_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Fl_Pixmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Fl_Plugin.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Fl_Preferences.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Fl_RGB_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/fl_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/Fl_Widget.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/platform.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/platform_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: ../FL/x11.H drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Enumerations.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/fl_attr.h drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl_Bitmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl_Cairo.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/fl_casts.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/fl_config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl_Device.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/fl_draw.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl_Export.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl_Pixmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl_Plugin.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl_Preferences.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl_RGB_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/fl_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/fl_utf8.h drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/Fl_Widget.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/platform.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/platform_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: ../FL/x11.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_color.o: Fl_XColor.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Enumerations.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/fl_attr.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl_Bitmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl_Cairo.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/fl_casts.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/fl_config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl_Device.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/fl_draw.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl_Export.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl_Pixmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl_Plugin.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl_Preferences.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl_RGB_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/fl_string_functions.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/fl_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/fl_utf8.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/Fl_Widget.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/platform.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/platform_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: ../FL/x11.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: drivers/Xlib/Fl_Font.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.o: flstring.h drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Enumerations.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/fl_attr.h drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Bitmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Cairo.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/fl_casts.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/fl_config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Device.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Double_Window.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/fl_draw.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Export.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Group.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Image_Surface.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Overlay_Window.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Pixmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Plugin.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Preferences.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Rect.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_RGB_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Scrollbar.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Shared_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Slider.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/fl_string_functions.h drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Text_Buffer.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Text_Display.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Text_Editor.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Tiled_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/fl_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/fl_utf8.h drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Valuator.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Widget.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Widget_Surface.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/Fl_Window.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/platform.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/platform_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: ../FL/x11.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: drivers/Unix/Fl_Unix_Screen_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: drivers/X11/Fl_X11_Screen_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: drivers/X11/Fl_X11_Window_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: flstring.h drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: Fl_Screen_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: Fl_Window_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_image.o: Fl_XColor.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Enumerations.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/fl_attr.h drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl_Bitmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl_Cairo.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/fl_casts.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/fl_config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl_Device.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/fl_draw.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl_Export.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl_Pixmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl_Plugin.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl_Preferences.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl_RGB_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/fl_string_functions.h drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/fl_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/fl_utf8.h drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/Fl_Widget.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/platform.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/platform_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: ../FL/x11.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.o: flstring.h drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Enumerations.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/fl_attr.h drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl_Bitmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl_Cairo.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/fl_casts.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/fl_config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl_Device.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/fl_draw.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl_Export.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl_Pixmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl_Plugin.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl_Preferences.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl_RGB_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/fl_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/fl_utf8.h drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/Fl_Widget.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/platform.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/platform_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: ../FL/x11.H drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Enumerations.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Fl.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/fl_attr.h drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Fl_Bitmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/fl_config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Fl_Device.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/fl_draw.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Fl_Export.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Fl_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Fl_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Fl_Pixmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Fl_Plugin.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Fl_Preferences.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Fl_RGB_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/fl_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/Fl_Widget.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/math.h drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/platform.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/platform_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: ../FL/x11.H drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../config.h drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Enumerations.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/fl_attr.h drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Bitmap.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Cairo.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/fl_casts.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/fl_config.h drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Device.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/fl_draw.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Export.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Group.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Image.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Image_Surface.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Pixmap.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Plugin.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Preferences.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Rect.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_RGB_Image.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Scrollbar.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Shared_Image.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Slider.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Text_Buffer.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Text_Display.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Text_Editor.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/fl_types.h drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/fl_utf8.h drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Valuator.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Widget.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Widget_Surface.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/Fl_Window.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/platform.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/platform_types.h drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: ../FL/x11.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.o: Fl_Screen_Driver.H filename_absolute.o: ../config.h filename_absolute.o: ../FL/Enumerations.H filename_absolute.o: ../FL/filename.H filename_absolute.o: ../FL/Fl.H filename_absolute.o: ../FL/fl_attr.h filename_absolute.o: ../FL/Fl_Cairo.H filename_absolute.o: ../FL/fl_casts.H filename_absolute.o: ../FL/fl_config.h filename_absolute.o: ../FL/Fl_Export.H filename_absolute.o: ../FL/Fl_Preferences.H filename_absolute.o: ../FL/fl_string_functions.h filename_absolute.o: ../FL/fl_types.h filename_absolute.o: ../FL/fl_utf8.h filename_absolute.o: ../FL/platform_types.h filename_absolute.o: flstring.h filename_absolute.o: Fl_System_Driver.H filename_expand.o: ../FL/Enumerations.H filename_expand.o: ../FL/filename.H filename_expand.o: ../FL/Fl.H filename_expand.o: ../FL/fl_attr.h filename_expand.o: ../FL/Fl_Cairo.H filename_expand.o: ../FL/fl_casts.H filename_expand.o: ../FL/fl_config.h filename_expand.o: ../FL/Fl_Export.H filename_expand.o: ../FL/Fl_Preferences.H filename_expand.o: ../FL/fl_types.h filename_expand.o: ../FL/fl_utf8.h filename_expand.o: ../FL/platform_types.h filename_expand.o: Fl_System_Driver.H filename_ext.o: ../FL/Enumerations.H filename_ext.o: ../FL/filename.H filename_ext.o: ../FL/Fl.H filename_ext.o: ../FL/fl_attr.h filename_ext.o: ../FL/Fl_Cairo.H filename_ext.o: ../FL/fl_casts.H filename_ext.o: ../FL/fl_config.h filename_ext.o: ../FL/Fl_Export.H filename_ext.o: ../FL/Fl_Preferences.H filename_ext.o: ../FL/fl_types.h filename_ext.o: ../FL/fl_utf8.h filename_ext.o: ../FL/platform_types.h filename_ext.o: Fl_System_Driver.H filename_isdir.o: ../config.h filename_isdir.o: ../FL/Enumerations.H filename_isdir.o: ../FL/filename.H filename_isdir.o: ../FL/Fl.H filename_isdir.o: ../FL/fl_attr.h filename_isdir.o: ../FL/Fl_Cairo.H filename_isdir.o: ../FL/fl_casts.H filename_isdir.o: ../FL/fl_config.h filename_isdir.o: ../FL/Fl_Export.H filename_isdir.o: ../FL/Fl_Preferences.H filename_isdir.o: ../FL/fl_string_functions.h filename_isdir.o: ../FL/fl_types.h filename_isdir.o: ../FL/fl_utf8.h filename_isdir.o: ../FL/platform_types.h filename_isdir.o: flstring.h filename_isdir.o: Fl_System_Driver.H filename_list.o: ../config.h filename_list.o: ../FL/Enumerations.H filename_list.o: ../FL/filename.H filename_list.o: ../FL/Fl.H filename_list.o: ../FL/fl_attr.h filename_list.o: ../FL/Fl_Cairo.H filename_list.o: ../FL/fl_casts.H filename_list.o: ../FL/fl_config.h filename_list.o: ../FL/Fl_Export.H filename_list.o: ../FL/Fl_Preferences.H filename_list.o: ../FL/fl_string_functions.h filename_list.o: ../FL/fl_types.h filename_list.o: ../FL/fl_utf8.h filename_list.o: ../FL/platform_types.h filename_list.o: flstring.h filename_list.o: Fl_System_Driver.H filename_match.o: ../FL/filename.H filename_match.o: ../FL/fl_config.h filename_match.o: ../FL/Fl_Export.H filename_match.o: ../FL/platform_types.h filename_setext.o: ../config.h filename_setext.o: ../FL/filename.H filename_setext.o: ../FL/fl_config.h filename_setext.o: ../FL/Fl_Export.H filename_setext.o: ../FL/fl_string_functions.h filename_setext.o: ../FL/platform_types.h filename_setext.o: flstring.h Fl.o: ../config.h Fl.o: ../FL/Enumerations.H Fl.o: ../FL/filename.H Fl.o: ../FL/Fl.H Fl.o: ../FL/fl_attr.h Fl.o: ../FL/Fl_Bitmap.H Fl.o: ../FL/Fl_Cairo.H Fl.o: ../FL/fl_casts.H Fl.o: ../FL/fl_config.h Fl.o: ../FL/Fl_Device.H Fl.o: ../FL/Fl_Double_Window.H Fl.o: ../FL/fl_draw.H Fl.o: ../FL/Fl_Export.H Fl.o: ../FL/Fl_Graphics_Driver.H Fl.o: ../FL/Fl_Group.H Fl.o: ../FL/Fl_Image.H Fl.o: ../FL/Fl_Overlay_Window.H Fl.o: ../FL/Fl_Pixmap.H Fl.o: ../FL/Fl_Plugin.H Fl.o: ../FL/Fl_Preferences.H Fl.o: ../FL/Fl_Rect.H Fl.o: ../FL/Fl_RGB_Image.H Fl.o: ../FL/Fl_Scrollbar.H Fl.o: ../FL/Fl_Slider.H Fl.o: ../FL/fl_string_functions.h Fl.o: ../FL/Fl_Text_Buffer.H Fl.o: ../FL/Fl_Text_Display.H Fl.o: ../FL/Fl_Text_Editor.H Fl.o: ../FL/Fl_Tooltip.H Fl.o: ../FL/fl_types.h Fl.o: ../FL/fl_utf8.h Fl.o: ../FL/Fl_Valuator.H Fl.o: ../FL/Fl_Widget.H Fl.o: ../FL/Fl_Window.H Fl.o: ../FL/platform.H Fl.o: ../FL/platform_types.h Fl.o: ../FL/x11.H Fl.o: flstring.h Fl.o: Fl_Screen_Driver.H Fl.o: Fl_System_Driver.H Fl.o: Fl_Timeout.h Fl.o: Fl_Window_Driver.H flstring.o: ../config.h flstring.o: ../FL/fl_config.h flstring.o: ../FL/Fl_Export.H flstring.o: ../FL/fl_string_functions.h flstring.o: flstring.h Fl_abort.o: ../FL/Enumerations.H Fl_abort.o: ../FL/filename.H Fl_abort.o: ../FL/Fl.H Fl_abort.o: ../FL/fl_attr.h Fl_abort.o: ../FL/Fl_Cairo.H Fl_abort.o: ../FL/fl_casts.H Fl_abort.o: ../FL/fl_config.h Fl_abort.o: ../FL/Fl_Export.H Fl_abort.o: ../FL/Fl_Preferences.H Fl_abort.o: ../FL/fl_types.h Fl_abort.o: ../FL/fl_utf8.h Fl_abort.o: ../FL/platform_types.h Fl_abort.o: Fl_System_Driver.H Fl_add_idle.o: ../FL/Enumerations.H Fl_add_idle.o: ../FL/Fl.H Fl_add_idle.o: ../FL/fl_attr.h Fl_add_idle.o: ../FL/Fl_Cairo.H Fl_add_idle.o: ../FL/fl_casts.H Fl_add_idle.o: ../FL/fl_config.h Fl_add_idle.o: ../FL/Fl_Export.H Fl_add_idle.o: ../FL/fl_types.h Fl_add_idle.o: ../FL/fl_utf8.h Fl_add_idle.o: ../FL/platform_types.h Fl_Adjuster.o: ../FL/Enumerations.H Fl_Adjuster.o: ../FL/Fl.H Fl_Adjuster.o: ../FL/Fl_Adjuster.H Fl_Adjuster.o: ../FL/fl_attr.h Fl_Adjuster.o: ../FL/Fl_Bitmap.H Fl_Adjuster.o: ../FL/Fl_Cairo.H Fl_Adjuster.o: ../FL/fl_casts.H Fl_Adjuster.o: ../FL/fl_config.h Fl_Adjuster.o: ../FL/fl_draw.H Fl_Adjuster.o: ../FL/Fl_Export.H Fl_Adjuster.o: ../FL/Fl_Image.H Fl_Adjuster.o: ../FL/fl_types.h Fl_Adjuster.o: ../FL/fl_utf8.h Fl_Adjuster.o: ../FL/Fl_Valuator.H Fl_Adjuster.o: ../FL/Fl_Widget.H Fl_Adjuster.o: ../FL/platform_types.h Fl_Adjuster.o: fastarrow.h Fl_Adjuster.o: mediumarrow.h Fl_Adjuster.o: slowarrow.h Fl_Anim_GIF_Image.o: ../FL/Enumerations.H Fl_Anim_GIF_Image.o: ../FL/Fl.H Fl_Anim_GIF_Image.o: ../FL/Fl_Anim_GIF_Image.H Fl_Anim_GIF_Image.o: ../FL/fl_attr.h Fl_Anim_GIF_Image.o: ../FL/Fl_Bitmap.H Fl_Anim_GIF_Image.o: ../FL/Fl_Cairo.H Fl_Anim_GIF_Image.o: ../FL/fl_casts.H Fl_Anim_GIF_Image.o: ../FL/fl_config.h Fl_Anim_GIF_Image.o: ../FL/Fl_Device.H Fl_Anim_GIF_Image.o: ../FL/Fl_Export.H Fl_Anim_GIF_Image.o: ../FL/Fl_GIF_Image.H Fl_Anim_GIF_Image.o: ../FL/Fl_Graphics_Driver.H Fl_Anim_GIF_Image.o: ../FL/Fl_Group.H Fl_Anim_GIF_Image.o: ../FL/Fl_Image.H Fl_Anim_GIF_Image.o: ../FL/Fl_Pixmap.H Fl_Anim_GIF_Image.o: ../FL/Fl_Plugin.H Fl_Anim_GIF_Image.o: ../FL/Fl_Preferences.H Fl_Anim_GIF_Image.o: ../FL/Fl_RGB_Image.H Fl_Anim_GIF_Image.o: ../FL/Fl_Shared_Image.H Fl_Anim_GIF_Image.o: ../FL/fl_string_functions.h Fl_Anim_GIF_Image.o: ../FL/fl_types.h Fl_Anim_GIF_Image.o: ../FL/fl_utf8.h Fl_Anim_GIF_Image.o: ../FL/Fl_Widget.H Fl_Anim_GIF_Image.o: ../FL/platform_types.h fl_arc.o: ../FL/fl_draw.H fl_arc.o: ../FL/math.h Fl_arg.o: ../FL/Enumerations.H Fl_arg.o: ../FL/filename.H Fl_arg.o: ../FL/Fl.H Fl_arg.o: ../FL/fl_attr.h Fl_arg.o: ../FL/Fl_Bitmap.H Fl_arg.o: ../FL/Fl_Cairo.H Fl_arg.o: ../FL/fl_casts.H Fl_arg.o: ../FL/fl_config.h Fl_arg.o: ../FL/Fl_Device.H Fl_arg.o: ../FL/Fl_Double_Window.H Fl_arg.o: ../FL/fl_draw.H Fl_arg.o: ../FL/Fl_Export.H Fl_arg.o: ../FL/Fl_Graphics_Driver.H Fl_arg.o: ../FL/Fl_Group.H Fl_arg.o: ../FL/Fl_Image.H Fl_arg.o: ../FL/Fl_Overlay_Window.H Fl_arg.o: ../FL/Fl_Pixmap.H Fl_arg.o: ../FL/Fl_Plugin.H Fl_arg.o: ../FL/Fl_Preferences.H Fl_arg.o: ../FL/Fl_Rect.H Fl_arg.o: ../FL/Fl_RGB_Image.H Fl_arg.o: ../FL/Fl_Scrollbar.H Fl_arg.o: ../FL/Fl_Slider.H Fl_arg.o: ../FL/Fl_Text_Buffer.H Fl_arg.o: ../FL/Fl_Text_Display.H Fl_arg.o: ../FL/Fl_Text_Editor.H Fl_arg.o: ../FL/Fl_Tooltip.H Fl_arg.o: ../FL/fl_types.h Fl_arg.o: ../FL/fl_utf8.h Fl_arg.o: ../FL/Fl_Valuator.H Fl_arg.o: ../FL/Fl_Widget.H Fl_arg.o: ../FL/Fl_Window.H Fl_arg.o: ../FL/platform_types.h Fl_arg.o: Fl_Screen_Driver.H Fl_arg.o: Fl_System_Driver.H Fl_arg.o: Fl_Window_Driver.H fl_ask.o: ../config.h fl_ask.o: ../FL/Enumerations.H fl_ask.o: ../FL/Fl.H fl_ask.o: ../FL/fl_ask.H fl_ask.o: ../FL/fl_attr.h fl_ask.o: ../FL/Fl_Bitmap.H fl_ask.o: ../FL/Fl_Box.H fl_ask.o: ../FL/Fl_Cairo.H fl_ask.o: ../FL/fl_casts.H fl_ask.o: ../FL/fl_config.h fl_ask.o: ../FL/Fl_Device.H fl_ask.o: ../FL/fl_draw.H fl_ask.o: ../FL/Fl_Export.H fl_ask.o: ../FL/Fl_Graphics_Driver.H fl_ask.o: ../FL/Fl_Group.H fl_ask.o: ../FL/Fl_Image.H fl_ask.o: ../FL/Fl_Input_.H fl_ask.o: ../FL/Fl_Pixmap.H fl_ask.o: ../FL/Fl_Plugin.H fl_ask.o: ../FL/Fl_Preferences.H fl_ask.o: ../FL/Fl_Rect.H fl_ask.o: ../FL/Fl_RGB_Image.H fl_ask.o: ../FL/Fl_Scrollbar.H fl_ask.o: ../FL/Fl_Slider.H fl_ask.o: ../FL/fl_string_functions.h fl_ask.o: ../FL/Fl_Text_Buffer.H fl_ask.o: ../FL/Fl_Text_Display.H fl_ask.o: ../FL/Fl_Text_Editor.H fl_ask.o: ../FL/fl_types.h fl_ask.o: ../FL/fl_utf8.h fl_ask.o: ../FL/Fl_Valuator.H fl_ask.o: ../FL/Fl_Widget.H fl_ask.o: ../FL/Fl_Window.H fl_ask.o: ../FL/platform_types.h fl_ask.o: flstring.h fl_ask.o: Fl_Message.h fl_ask.o: Fl_Screen_Driver.H Fl_Bitmap.o: ../FL/Enumerations.H Fl_Bitmap.o: ../FL/Fl.H Fl_Bitmap.o: ../FL/fl_attr.h Fl_Bitmap.o: ../FL/Fl_Bitmap.H Fl_Bitmap.o: ../FL/Fl_Cairo.H Fl_Bitmap.o: ../FL/fl_casts.H Fl_Bitmap.o: ../FL/fl_config.h Fl_Bitmap.o: ../FL/fl_draw.H Fl_Bitmap.o: ../FL/Fl_Export.H Fl_Bitmap.o: ../FL/Fl_Image.H Fl_Bitmap.o: ../FL/Fl_Menu_Item.H Fl_Bitmap.o: ../FL/Fl_Multi_Label.H Fl_Bitmap.o: ../FL/fl_types.h Fl_Bitmap.o: ../FL/fl_utf8.h Fl_Bitmap.o: ../FL/Fl_Widget.H Fl_Bitmap.o: ../FL/platform_types.h Fl_BMP_Image.o: ../FL/Enumerations.H Fl_BMP_Image.o: ../FL/Fl.H Fl_BMP_Image.o: ../FL/fl_attr.h Fl_BMP_Image.o: ../FL/Fl_BMP_Image.H Fl_BMP_Image.o: ../FL/Fl_Cairo.H Fl_BMP_Image.o: ../FL/fl_casts.H Fl_BMP_Image.o: ../FL/fl_config.h Fl_BMP_Image.o: ../FL/Fl_Export.H Fl_BMP_Image.o: ../FL/Fl_Image.H Fl_BMP_Image.o: ../FL/fl_types.h Fl_BMP_Image.o: ../FL/fl_utf8.h Fl_BMP_Image.o: ../FL/platform_types.h Fl_BMP_Image.o: Fl_Image_Reader.h Fl_Box.o: ../FL/Fl.H Fl_Box.o: ../FL/Fl_Box.H Fl_Box.o: ../FL/Fl_Widget.H fl_boxtype.o: ../config.h fl_boxtype.o: ../FL/Enumerations.H fl_boxtype.o: ../FL/Fl.H fl_boxtype.o: ../FL/fl_attr.h fl_boxtype.o: ../FL/Fl_Cairo.H fl_boxtype.o: ../FL/fl_casts.H fl_boxtype.o: ../FL/fl_config.h fl_boxtype.o: ../FL/fl_draw.H fl_boxtype.o: ../FL/Fl_Export.H fl_boxtype.o: ../FL/fl_types.h fl_boxtype.o: ../FL/fl_utf8.h fl_boxtype.o: ../FL/Fl_Widget.H fl_boxtype.o: ../FL/platform_types.h Fl_Browser.o: ../config.h Fl_Browser.o: ../FL/Enumerations.H Fl_Browser.o: ../FL/Fl.H Fl_Browser.o: ../FL/fl_attr.h Fl_Browser.o: ../FL/Fl_Browser.H Fl_Browser.o: ../FL/Fl_Browser_.H Fl_Browser.o: ../FL/Fl_Cairo.H Fl_Browser.o: ../FL/fl_casts.H Fl_Browser.o: ../FL/fl_config.h Fl_Browser.o: ../FL/fl_draw.H Fl_Browser.o: ../FL/Fl_Export.H Fl_Browser.o: ../FL/Fl_Group.H Fl_Browser.o: ../FL/Fl_Hold_Browser.H Fl_Browser.o: ../FL/Fl_Image.H Fl_Browser.o: ../FL/Fl_Multi_Browser.H Fl_Browser.o: ../FL/Fl_Scrollbar.H Fl_Browser.o: ../FL/Fl_Select_Browser.H Fl_Browser.o: ../FL/Fl_Slider.H Fl_Browser.o: ../FL/fl_string_functions.h Fl_Browser.o: ../FL/fl_types.h Fl_Browser.o: ../FL/fl_utf8.h Fl_Browser.o: ../FL/Fl_Valuator.H Fl_Browser.o: ../FL/Fl_Widget.H Fl_Browser.o: ../FL/platform_types.h Fl_Browser.o: flstring.h Fl_Browser_.o: ../FL/Enumerations.H Fl_Browser_.o: ../FL/Fl.H Fl_Browser_.o: ../FL/fl_attr.h Fl_Browser_.o: ../FL/Fl_Browser_.H Fl_Browser_.o: ../FL/Fl_Cairo.H Fl_Browser_.o: ../FL/fl_casts.H Fl_Browser_.o: ../FL/fl_config.h Fl_Browser_.o: ../FL/fl_draw.H Fl_Browser_.o: ../FL/Fl_Export.H Fl_Browser_.o: ../FL/Fl_Group.H Fl_Browser_.o: ../FL/Fl_Scrollbar.H Fl_Browser_.o: ../FL/Fl_Slider.H Fl_Browser_.o: ../FL/fl_types.h Fl_Browser_.o: ../FL/fl_utf8.h Fl_Browser_.o: ../FL/Fl_Valuator.H Fl_Browser_.o: ../FL/Fl_Widget.H Fl_Browser_.o: ../FL/platform_types.h Fl_Browser_load.o: ../FL/Enumerations.H Fl_Browser_load.o: ../FL/Fl.H Fl_Browser_load.o: ../FL/fl_attr.h Fl_Browser_load.o: ../FL/Fl_Browser.H Fl_Browser_load.o: ../FL/Fl_Browser_.H Fl_Browser_load.o: ../FL/Fl_Cairo.H Fl_Browser_load.o: ../FL/fl_casts.H Fl_Browser_load.o: ../FL/fl_config.h Fl_Browser_load.o: ../FL/Fl_Export.H Fl_Browser_load.o: ../FL/Fl_Group.H Fl_Browser_load.o: ../FL/Fl_Image.H Fl_Browser_load.o: ../FL/Fl_Scrollbar.H Fl_Browser_load.o: ../FL/Fl_Slider.H Fl_Browser_load.o: ../FL/fl_types.h Fl_Browser_load.o: ../FL/fl_utf8.h Fl_Browser_load.o: ../FL/Fl_Valuator.H Fl_Browser_load.o: ../FL/Fl_Widget.H Fl_Browser_load.o: ../FL/platform_types.h Fl_Button.o: ../FL/Enumerations.H Fl_Button.o: ../FL/Fl.H Fl_Button.o: ../FL/fl_attr.h Fl_Button.o: ../FL/Fl_Bitmap.H Fl_Button.o: ../FL/Fl_Button.H Fl_Button.o: ../FL/Fl_Cairo.H Fl_Button.o: ../FL/fl_casts.H Fl_Button.o: ../FL/fl_config.h Fl_Button.o: ../FL/fl_draw.H Fl_Button.o: ../FL/Fl_Export.H Fl_Button.o: ../FL/Fl_Group.H Fl_Button.o: ../FL/Fl_Image.H Fl_Button.o: ../FL/Fl_Radio_Button.H Fl_Button.o: ../FL/Fl_Toggle_Button.H Fl_Button.o: ../FL/fl_types.h Fl_Button.o: ../FL/fl_utf8.h Fl_Button.o: ../FL/Fl_Widget.H Fl_Button.o: ../FL/Fl_Window.H Fl_Button.o: ../FL/platform_types.h Fl_Cairo.o: ../FL/Enumerations.H Fl_Cairo.o: ../FL/Fl.H Fl_Cairo.o: ../FL/fl_attr.h Fl_Cairo.o: ../FL/Fl_Bitmap.H Fl_Cairo.o: ../FL/Fl_Cairo.H Fl_Cairo.o: ../FL/fl_casts.H Fl_Cairo.o: ../FL/fl_config.h Fl_Cairo.o: ../FL/Fl_Export.H Fl_Cairo.o: ../FL/Fl_Group.H Fl_Cairo.o: ../FL/Fl_Image.H Fl_Cairo.o: ../FL/fl_types.h Fl_Cairo.o: ../FL/fl_utf8.h Fl_Cairo.o: ../FL/Fl_Widget.H Fl_Cairo.o: ../FL/Fl_Window.H Fl_Cairo.o: ../FL/platform.H Fl_Cairo.o: ../FL/platform_types.h Fl_Cairo.o: ../FL/x11.H Fl_Chart.o: ../config.h Fl_Chart.o: ../FL/Enumerations.H Fl_Chart.o: ../FL/Fl.H Fl_Chart.o: ../FL/fl_attr.h Fl_Chart.o: ../FL/Fl_Cairo.H Fl_Chart.o: ../FL/fl_casts.H Fl_Chart.o: ../FL/Fl_Chart.H Fl_Chart.o: ../FL/fl_config.h Fl_Chart.o: ../FL/fl_draw.H Fl_Chart.o: ../FL/Fl_Export.H Fl_Chart.o: ../FL/fl_string_functions.h Fl_Chart.o: ../FL/fl_types.h Fl_Chart.o: ../FL/fl_utf8.h Fl_Chart.o: ../FL/Fl_Widget.H Fl_Chart.o: ../FL/math.h Fl_Chart.o: ../FL/platform_types.h Fl_Chart.o: flstring.h Fl_Check_Browser.o: ../config.h Fl_Check_Browser.o: ../FL/Enumerations.H Fl_Check_Browser.o: ../FL/Fl.H Fl_Check_Browser.o: ../FL/fl_attr.h Fl_Check_Browser.o: ../FL/Fl_Browser_.H Fl_Check_Browser.o: ../FL/Fl_Cairo.H Fl_Check_Browser.o: ../FL/fl_casts.H Fl_Check_Browser.o: ../FL/Fl_Check_Browser.H Fl_Check_Browser.o: ../FL/fl_config.h Fl_Check_Browser.o: ../FL/fl_draw.H Fl_Check_Browser.o: ../FL/Fl_Export.H Fl_Check_Browser.o: ../FL/Fl_Group.H Fl_Check_Browser.o: ../FL/Fl_Scrollbar.H Fl_Check_Browser.o: ../FL/Fl_Slider.H Fl_Check_Browser.o: ../FL/fl_string_functions.h Fl_Check_Browser.o: ../FL/fl_types.h Fl_Check_Browser.o: ../FL/fl_utf8.h Fl_Check_Browser.o: ../FL/Fl_Valuator.H Fl_Check_Browser.o: ../FL/Fl_Widget.H Fl_Check_Browser.o: ../FL/platform_types.h Fl_Check_Browser.o: flstring.h Fl_Check_Button.o: ../FL/Enumerations.H Fl_Check_Button.o: ../FL/Fl.H Fl_Check_Button.o: ../FL/fl_attr.h Fl_Check_Button.o: ../FL/Fl_Button.H Fl_Check_Button.o: ../FL/Fl_Cairo.H Fl_Check_Button.o: ../FL/fl_casts.H Fl_Check_Button.o: ../FL/Fl_Check_Button.H Fl_Check_Button.o: ../FL/fl_config.h Fl_Check_Button.o: ../FL/Fl_Export.H Fl_Check_Button.o: ../FL/Fl_Light_Button.H Fl_Check_Button.o: ../FL/fl_types.h Fl_Check_Button.o: ../FL/fl_utf8.h Fl_Check_Button.o: ../FL/platform_types.h Fl_Choice.o: ../config.h Fl_Choice.o: ../FL/Enumerations.H Fl_Choice.o: ../FL/Fl.H Fl_Choice.o: ../FL/fl_attr.h Fl_Choice.o: ../FL/Fl_Cairo.H Fl_Choice.o: ../FL/fl_casts.H Fl_Choice.o: ../FL/Fl_Choice.H Fl_Choice.o: ../FL/fl_config.h Fl_Choice.o: ../FL/fl_draw.H Fl_Choice.o: ../FL/Fl_Export.H Fl_Choice.o: ../FL/Fl_Image.H Fl_Choice.o: ../FL/Fl_Menu_.H Fl_Choice.o: ../FL/Fl_Menu_Item.H Fl_Choice.o: ../FL/Fl_Multi_Label.H Fl_Choice.o: ../FL/fl_string_functions.h Fl_Choice.o: ../FL/fl_types.h Fl_Choice.o: ../FL/fl_utf8.h Fl_Choice.o: ../FL/Fl_Widget.H Fl_Choice.o: ../FL/platform_types.h Fl_Choice.o: flstring.h Fl_Clock.o: ../FL/Enumerations.H Fl_Clock.o: ../FL/filename.H Fl_Clock.o: ../FL/Fl.H Fl_Clock.o: ../FL/fl_attr.h Fl_Clock.o: ../FL/Fl_Cairo.H Fl_Clock.o: ../FL/fl_casts.H Fl_Clock.o: ../FL/Fl_Clock.H Fl_Clock.o: ../FL/fl_config.h Fl_Clock.o: ../FL/fl_draw.H Fl_Clock.o: ../FL/Fl_Export.H Fl_Clock.o: ../FL/Fl_Preferences.H Fl_Clock.o: ../FL/Fl_Round_Clock.H Fl_Clock.o: ../FL/fl_types.h Fl_Clock.o: ../FL/fl_utf8.h Fl_Clock.o: ../FL/Fl_Widget.H Fl_Clock.o: ../FL/platform_types.h Fl_Clock.o: Fl_System_Driver.H fl_color.o: ../FL/Enumerations.H fl_color.o: ../FL/Fl.H fl_color.o: ../FL/fl_attr.h fl_color.o: ../FL/Fl_Bitmap.H fl_color.o: ../FL/Fl_Cairo.H fl_color.o: ../FL/fl_casts.H fl_color.o: ../FL/fl_config.h fl_color.o: ../FL/Fl_Device.H fl_color.o: ../FL/Fl_Export.H fl_color.o: ../FL/Fl_Graphics_Driver.H fl_color.o: ../FL/Fl_Image.H fl_color.o: ../FL/Fl_Pixmap.H fl_color.o: ../FL/Fl_Plugin.H fl_color.o: ../FL/Fl_Preferences.H fl_color.o: ../FL/Fl_RGB_Image.H fl_color.o: ../FL/fl_types.h fl_color.o: ../FL/fl_utf8.h fl_color.o: ../FL/Fl_Widget.H fl_color.o: ../FL/platform_types.h fl_color.o: fl_cmap.h Fl_Color_Chooser.o: ../FL/Enumerations.H Fl_Color_Chooser.o: ../FL/Fl.H Fl_Color_Chooser.o: ../FL/fl_attr.h Fl_Color_Chooser.o: ../FL/Fl_Bitmap.H Fl_Color_Chooser.o: ../FL/Fl_Box.H Fl_Color_Chooser.o: ../FL/Fl_Button.H Fl_Color_Chooser.o: ../FL/Fl_Cairo.H Fl_Color_Chooser.o: ../FL/fl_casts.H Fl_Color_Chooser.o: ../FL/Fl_Choice.H Fl_Color_Chooser.o: ../FL/Fl_Color_Chooser.H Fl_Color_Chooser.o: ../FL/fl_config.h Fl_Color_Chooser.o: ../FL/fl_draw.H Fl_Color_Chooser.o: ../FL/Fl_Export.H Fl_Color_Chooser.o: ../FL/Fl_Group.H Fl_Color_Chooser.o: ../FL/Fl_Image.H Fl_Color_Chooser.o: ../FL/Fl_Input.H Fl_Color_Chooser.o: ../FL/Fl_Input_.H Fl_Color_Chooser.o: ../FL/Fl_Menu_.H Fl_Color_Chooser.o: ../FL/Fl_Menu_Item.H Fl_Color_Chooser.o: ../FL/Fl_Multi_Label.H Fl_Color_Chooser.o: ../FL/Fl_Return_Button.H Fl_Color_Chooser.o: ../FL/fl_types.h Fl_Color_Chooser.o: ../FL/fl_utf8.h Fl_Color_Chooser.o: ../FL/Fl_Valuator.H Fl_Color_Chooser.o: ../FL/Fl_Value_Input.H Fl_Color_Chooser.o: ../FL/Fl_Widget.H Fl_Color_Chooser.o: ../FL/Fl_Window.H Fl_Color_Chooser.o: ../FL/math.h Fl_Color_Chooser.o: ../FL/platform_types.h Fl_compose.o: ../FL/Enumerations.H Fl_compose.o: ../FL/Fl.H Fl_compose.o: ../FL/fl_attr.h Fl_compose.o: ../FL/Fl_Bitmap.H Fl_compose.o: ../FL/Fl_Cairo.H Fl_compose.o: ../FL/fl_casts.H Fl_compose.o: ../FL/fl_config.h Fl_compose.o: ../FL/Fl_Device.H Fl_compose.o: ../FL/fl_draw.H Fl_compose.o: ../FL/Fl_Export.H Fl_compose.o: ../FL/Fl_Graphics_Driver.H Fl_compose.o: ../FL/Fl_Group.H Fl_compose.o: ../FL/Fl_Image.H Fl_compose.o: ../FL/Fl_Pixmap.H Fl_compose.o: ../FL/Fl_Plugin.H Fl_compose.o: ../FL/Fl_Preferences.H Fl_compose.o: ../FL/Fl_Rect.H Fl_compose.o: ../FL/Fl_RGB_Image.H Fl_compose.o: ../FL/Fl_Scrollbar.H Fl_compose.o: ../FL/Fl_Slider.H Fl_compose.o: ../FL/Fl_Text_Buffer.H Fl_compose.o: ../FL/Fl_Text_Display.H Fl_compose.o: ../FL/Fl_Text_Editor.H Fl_compose.o: ../FL/fl_types.h Fl_compose.o: ../FL/fl_utf8.h Fl_compose.o: ../FL/Fl_Valuator.H Fl_compose.o: ../FL/Fl_Widget.H Fl_compose.o: ../FL/platform_types.h Fl_compose.o: Fl_Screen_Driver.H fl_contrast.o: ../FL/Enumerations.H fl_contrast.o: ../FL/Fl.H fl_contrast.o: ../FL/fl_attr.h fl_contrast.o: ../FL/Fl_Cairo.H fl_contrast.o: ../FL/fl_casts.H fl_contrast.o: ../FL/fl_config.h fl_contrast.o: ../FL/Fl_Export.H fl_contrast.o: ../FL/fl_types.h fl_contrast.o: ../FL/fl_utf8.h fl_contrast.o: ../FL/platform_types.h Fl_Copy_Surface.o: ../FL/Enumerations.H Fl_Copy_Surface.o: ../FL/Fl.H Fl_Copy_Surface.o: ../FL/fl_attr.h Fl_Copy_Surface.o: ../FL/Fl_Bitmap.H Fl_Copy_Surface.o: ../FL/Fl_Cairo.H Fl_Copy_Surface.o: ../FL/fl_casts.H Fl_Copy_Surface.o: ../FL/fl_config.h Fl_Copy_Surface.o: ../FL/Fl_Copy_Surface.H Fl_Copy_Surface.o: ../FL/Fl_Device.H Fl_Copy_Surface.o: ../FL/Fl_Export.H Fl_Copy_Surface.o: ../FL/Fl_Group.H Fl_Copy_Surface.o: ../FL/Fl_Image.H Fl_Copy_Surface.o: ../FL/Fl_Plugin.H Fl_Copy_Surface.o: ../FL/Fl_Preferences.H Fl_Copy_Surface.o: ../FL/fl_types.h Fl_Copy_Surface.o: ../FL/fl_utf8.h Fl_Copy_Surface.o: ../FL/Fl_Widget.H Fl_Copy_Surface.o: ../FL/Fl_Widget_Surface.H Fl_Copy_Surface.o: ../FL/Fl_Window.H Fl_Copy_Surface.o: ../FL/platform_types.h Fl_Counter.o: ../FL/Enumerations.H Fl_Counter.o: ../FL/Fl.H Fl_Counter.o: ../FL/fl_attr.h Fl_Counter.o: ../FL/Fl_Cairo.H Fl_Counter.o: ../FL/fl_casts.H Fl_Counter.o: ../FL/fl_config.h Fl_Counter.o: ../FL/Fl_Counter.H Fl_Counter.o: ../FL/fl_draw.H Fl_Counter.o: ../FL/Fl_Export.H Fl_Counter.o: ../FL/Fl_Simple_Counter.H Fl_Counter.o: ../FL/fl_types.h Fl_Counter.o: ../FL/fl_utf8.h Fl_Counter.o: ../FL/Fl_Valuator.H Fl_Counter.o: ../FL/platform_types.h fl_cursor.o: ../FL/Enumerations.H fl_cursor.o: ../FL/Fl.H fl_cursor.o: ../FL/fl_attr.h fl_cursor.o: ../FL/Fl_Bitmap.H fl_cursor.o: ../FL/Fl_Cairo.H fl_cursor.o: ../FL/fl_casts.H fl_cursor.o: ../FL/fl_config.h fl_cursor.o: ../FL/Fl_Double_Window.H fl_cursor.o: ../FL/fl_draw.H fl_cursor.o: ../FL/Fl_Export.H fl_cursor.o: ../FL/Fl_Group.H fl_cursor.o: ../FL/Fl_Image.H fl_cursor.o: ../FL/Fl_Overlay_Window.H fl_cursor.o: ../FL/Fl_Pixmap.H fl_cursor.o: ../FL/Fl_RGB_Image.H fl_cursor.o: ../FL/fl_types.h fl_cursor.o: ../FL/fl_utf8.h fl_cursor.o: ../FL/Fl_Widget.H fl_cursor.o: ../FL/Fl_Window.H fl_cursor.o: ../FL/platform.H fl_cursor.o: ../FL/platform_types.h fl_cursor.o: ../FL/x11.H fl_cursor.o: fl_cursor_help.xpm fl_cursor.o: fl_cursor_nesw.xpm fl_cursor.o: fl_cursor_none.xpm fl_cursor.o: fl_cursor_nwse.xpm fl_cursor.o: fl_cursor_wait.xpm fl_cursor.o: Fl_Window_Driver.H fl_curve.o: ../FL/fl_draw.H Fl_Device.o: ../config.h Fl_Device.o: ../FL/Enumerations.H Fl_Device.o: ../FL/Fl.H Fl_Device.o: ../FL/fl_attr.h Fl_Device.o: ../FL/Fl_Bitmap.H Fl_Device.o: ../FL/Fl_Cairo.H Fl_Device.o: ../FL/fl_casts.H Fl_Device.o: ../FL/fl_config.h Fl_Device.o: ../FL/Fl_Device.H Fl_Device.o: ../FL/Fl_Export.H Fl_Device.o: ../FL/Fl_Graphics_Driver.H Fl_Device.o: ../FL/Fl_Group.H Fl_Device.o: ../FL/Fl_Image.H Fl_Device.o: ../FL/Fl_Paged_Device.H Fl_Device.o: ../FL/Fl_PDF_File_Surface.H Fl_Device.o: ../FL/Fl_Pixmap.H Fl_Device.o: ../FL/Fl_Plugin.H Fl_Device.o: ../FL/Fl_Preferences.H Fl_Device.o: ../FL/Fl_RGB_Image.H Fl_Device.o: ../FL/fl_types.h Fl_Device.o: ../FL/fl_utf8.h Fl_Device.o: ../FL/Fl_Widget.H Fl_Device.o: ../FL/Fl_Widget_Surface.H Fl_Device.o: ../FL/Fl_Window.H Fl_Device.o: ../FL/platform_types.h Fl_Dial.o: ../FL/Enumerations.H Fl_Dial.o: ../FL/Fl.H Fl_Dial.o: ../FL/fl_attr.h Fl_Dial.o: ../FL/Fl_Cairo.H Fl_Dial.o: ../FL/fl_casts.H Fl_Dial.o: ../FL/fl_config.h Fl_Dial.o: ../FL/Fl_Dial.H Fl_Dial.o: ../FL/fl_draw.H Fl_Dial.o: ../FL/Fl_Export.H Fl_Dial.o: ../FL/Fl_Fill_Dial.H Fl_Dial.o: ../FL/Fl_Line_Dial.H Fl_Dial.o: ../FL/fl_types.h Fl_Dial.o: ../FL/fl_utf8.h Fl_Dial.o: ../FL/Fl_Valuator.H Fl_Dial.o: ../FL/math.h Fl_Dial.o: ../FL/platform_types.h fl_diamond_box.o: ../FL/Enumerations.H fl_diamond_box.o: ../FL/Fl.H fl_diamond_box.o: ../FL/fl_attr.h fl_diamond_box.o: ../FL/Fl_Cairo.H fl_diamond_box.o: ../FL/fl_casts.H fl_diamond_box.o: ../FL/fl_config.h fl_diamond_box.o: ../FL/fl_draw.H fl_diamond_box.o: ../FL/Fl_Export.H fl_diamond_box.o: ../FL/fl_types.h fl_diamond_box.o: ../FL/fl_utf8.h fl_diamond_box.o: ../FL/platform_types.h Fl_display.o: ../FL/Enumerations.H Fl_display.o: ../FL/Fl.H Fl_display.o: ../FL/fl_attr.h Fl_display.o: ../FL/Fl_Bitmap.H Fl_display.o: ../FL/Fl_Cairo.H Fl_display.o: ../FL/fl_casts.H Fl_display.o: ../FL/fl_config.h Fl_display.o: ../FL/Fl_Device.H Fl_display.o: ../FL/fl_draw.H Fl_display.o: ../FL/Fl_Export.H Fl_display.o: ../FL/Fl_Graphics_Driver.H Fl_display.o: ../FL/Fl_Group.H Fl_display.o: ../FL/Fl_Image.H Fl_display.o: ../FL/Fl_Pixmap.H Fl_display.o: ../FL/Fl_Plugin.H Fl_display.o: ../FL/Fl_Preferences.H Fl_display.o: ../FL/Fl_Rect.H Fl_display.o: ../FL/Fl_RGB_Image.H Fl_display.o: ../FL/Fl_Scrollbar.H Fl_display.o: ../FL/Fl_Slider.H Fl_display.o: ../FL/Fl_Text_Buffer.H Fl_display.o: ../FL/Fl_Text_Display.H Fl_display.o: ../FL/Fl_Text_Editor.H Fl_display.o: ../FL/fl_types.h Fl_display.o: ../FL/fl_utf8.h Fl_display.o: ../FL/Fl_Valuator.H Fl_display.o: ../FL/Fl_Widget.H Fl_display.o: ../FL/platform_types.h Fl_display.o: Fl_Screen_Driver.H fl_dnd_x.o: ../config.h fl_dnd_x.o: ../FL/Enumerations.H fl_dnd_x.o: ../FL/Fl.H fl_dnd_x.o: ../FL/fl_attr.h fl_dnd_x.o: ../FL/Fl_Bitmap.H fl_dnd_x.o: ../FL/Fl_Cairo.H fl_dnd_x.o: ../FL/fl_casts.H fl_dnd_x.o: ../FL/fl_config.h fl_dnd_x.o: ../FL/Fl_Device.H fl_dnd_x.o: ../FL/Fl_Double_Window.H fl_dnd_x.o: ../FL/fl_draw.H fl_dnd_x.o: ../FL/Fl_Export.H fl_dnd_x.o: ../FL/Fl_Graphics_Driver.H fl_dnd_x.o: ../FL/Fl_Group.H fl_dnd_x.o: ../FL/Fl_Image.H fl_dnd_x.o: ../FL/Fl_Overlay_Window.H fl_dnd_x.o: ../FL/Fl_Pixmap.H fl_dnd_x.o: ../FL/Fl_Plugin.H fl_dnd_x.o: ../FL/Fl_Preferences.H fl_dnd_x.o: ../FL/Fl_Rect.H fl_dnd_x.o: ../FL/Fl_RGB_Image.H fl_dnd_x.o: ../FL/Fl_Scrollbar.H fl_dnd_x.o: ../FL/Fl_Slider.H fl_dnd_x.o: ../FL/fl_string_functions.h fl_dnd_x.o: ../FL/Fl_Text_Buffer.H fl_dnd_x.o: ../FL/Fl_Text_Display.H fl_dnd_x.o: ../FL/Fl_Text_Editor.H fl_dnd_x.o: ../FL/fl_types.h fl_dnd_x.o: ../FL/fl_utf8.h fl_dnd_x.o: ../FL/Fl_Valuator.H fl_dnd_x.o: ../FL/Fl_Widget.H fl_dnd_x.o: ../FL/Fl_Window.H fl_dnd_x.o: ../FL/platform.H fl_dnd_x.o: ../FL/platform_types.h fl_dnd_x.o: ../FL/x11.H fl_dnd_x.o: drivers/Unix/Fl_Unix_Screen_Driver.H fl_dnd_x.o: drivers/X11/Fl_X11_Screen_Driver.H fl_dnd_x.o: flstring.h fl_dnd_x.o: Fl_Screen_Driver.H fl_dnd_x.o: Fl_Window_Driver.H Fl_Double_Window.o: ../FL/Enumerations.H Fl_Double_Window.o: ../FL/Fl.H Fl_Double_Window.o: ../FL/fl_attr.h Fl_Double_Window.o: ../FL/Fl_Bitmap.H Fl_Double_Window.o: ../FL/Fl_Cairo.H Fl_Double_Window.o: ../FL/fl_casts.H Fl_Double_Window.o: ../FL/fl_config.h Fl_Double_Window.o: ../FL/Fl_Double_Window.H Fl_Double_Window.o: ../FL/fl_draw.H Fl_Double_Window.o: ../FL/Fl_Export.H Fl_Double_Window.o: ../FL/Fl_Group.H Fl_Double_Window.o: ../FL/Fl_Image.H Fl_Double_Window.o: ../FL/Fl_Overlay_Window.H Fl_Double_Window.o: ../FL/fl_types.h Fl_Double_Window.o: ../FL/fl_utf8.h Fl_Double_Window.o: ../FL/Fl_Widget.H Fl_Double_Window.o: ../FL/Fl_Window.H Fl_Double_Window.o: ../FL/platform.H Fl_Double_Window.o: ../FL/platform_types.h Fl_Double_Window.o: ../FL/x11.H Fl_Double_Window.o: Fl_Window_Driver.H fl_draw.o: ../config.h fl_draw.o: ../FL/Enumerations.H fl_draw.o: ../FL/Fl.H fl_draw.o: ../FL/fl_attr.h fl_draw.o: ../FL/Fl_Cairo.H fl_draw.o: ../FL/fl_casts.H fl_draw.o: ../FL/fl_config.h fl_draw.o: ../FL/fl_draw.H fl_draw.o: ../FL/Fl_Export.H fl_draw.o: ../FL/Fl_Image.H fl_draw.o: ../FL/fl_string_functions.h fl_draw.o: ../FL/fl_types.h fl_draw.o: ../FL/fl_utf8.h fl_draw.o: ../FL/Fl_Widget.H fl_draw.o: ../FL/platform.H fl_draw.o: ../FL/platform_types.h fl_draw.o: ../FL/x11.H fl_draw.o: flstring.h fl_draw.o: fl_oxy.h fl_draw_arrow.o: ../FL/Enumerations.H fl_draw_arrow.o: ../FL/Fl.H fl_draw_arrow.o: ../FL/fl_attr.h fl_draw_arrow.o: ../FL/Fl_Cairo.H fl_draw_arrow.o: ../FL/fl_casts.H fl_draw_arrow.o: ../FL/fl_config.h fl_draw_arrow.o: ../FL/fl_draw.H fl_draw_arrow.o: ../FL/Fl_Export.H fl_draw_arrow.o: ../FL/fl_types.h fl_draw_arrow.o: ../FL/fl_utf8.h fl_draw_arrow.o: ../FL/platform_types.h fl_draw_arrow.o: fl_oxy.h fl_draw_pixmap.o: ../config.h fl_draw_pixmap.o: ../FL/Enumerations.H fl_draw_pixmap.o: ../FL/filename.H fl_draw_pixmap.o: ../FL/Fl.H fl_draw_pixmap.o: ../FL/fl_attr.h fl_draw_pixmap.o: ../FL/Fl_Cairo.H fl_draw_pixmap.o: ../FL/fl_casts.H fl_draw_pixmap.o: ../FL/fl_config.h fl_draw_pixmap.o: ../FL/fl_draw.H fl_draw_pixmap.o: ../FL/Fl_Export.H fl_draw_pixmap.o: ../FL/Fl_Preferences.H fl_draw_pixmap.o: ../FL/fl_string_functions.h fl_draw_pixmap.o: ../FL/fl_types.h fl_draw_pixmap.o: ../FL/fl_utf8.h fl_draw_pixmap.o: ../FL/platform.H fl_draw_pixmap.o: ../FL/platform_types.h fl_draw_pixmap.o: ../FL/x11.H fl_draw_pixmap.o: flstring.h fl_draw_pixmap.o: Fl_System_Driver.H fl_encoding_latin1.o: ../config.h fl_encoding_latin1.o: ../FL/Enumerations.H fl_encoding_latin1.o: ../FL/filename.H fl_encoding_latin1.o: ../FL/Fl.H fl_encoding_latin1.o: ../FL/fl_attr.h fl_encoding_latin1.o: ../FL/Fl_Cairo.H fl_encoding_latin1.o: ../FL/fl_casts.H fl_encoding_latin1.o: ../FL/fl_config.h fl_encoding_latin1.o: ../FL/fl_draw.H fl_encoding_latin1.o: ../FL/Fl_Export.H fl_encoding_latin1.o: ../FL/Fl_Preferences.H fl_encoding_latin1.o: ../FL/fl_string_functions.h fl_encoding_latin1.o: ../FL/fl_types.h fl_encoding_latin1.o: ../FL/fl_utf8.h fl_encoding_latin1.o: ../FL/platform_types.h fl_encoding_latin1.o: flstring.h fl_encoding_latin1.o: Fl_System_Driver.H fl_encoding_mac_roman.o: ../config.h fl_encoding_mac_roman.o: ../FL/Enumerations.H fl_encoding_mac_roman.o: ../FL/filename.H fl_encoding_mac_roman.o: ../FL/Fl.H fl_encoding_mac_roman.o: ../FL/fl_attr.h fl_encoding_mac_roman.o: ../FL/Fl_Cairo.H fl_encoding_mac_roman.o: ../FL/fl_casts.H fl_encoding_mac_roman.o: ../FL/fl_config.h fl_encoding_mac_roman.o: ../FL/fl_draw.H fl_encoding_mac_roman.o: ../FL/Fl_Export.H fl_encoding_mac_roman.o: ../FL/Fl_Preferences.H fl_encoding_mac_roman.o: ../FL/fl_string_functions.h fl_encoding_mac_roman.o: ../FL/fl_types.h fl_encoding_mac_roman.o: ../FL/fl_utf8.h fl_encoding_mac_roman.o: ../FL/platform_types.h fl_encoding_mac_roman.o: flstring.h fl_encoding_mac_roman.o: Fl_System_Driver.H fl_engraved_label.o: ../FL/Enumerations.H fl_engraved_label.o: ../FL/Fl.H fl_engraved_label.o: ../FL/fl_attr.h fl_engraved_label.o: ../FL/Fl_Cairo.H fl_engraved_label.o: ../FL/fl_casts.H fl_engraved_label.o: ../FL/fl_config.h fl_engraved_label.o: ../FL/fl_draw.H fl_engraved_label.o: ../FL/Fl_Export.H fl_engraved_label.o: ../FL/fl_types.h fl_engraved_label.o: ../FL/fl_utf8.h fl_engraved_label.o: ../FL/Fl_Widget.H fl_engraved_label.o: ../FL/platform_types.h Fl_File_Browser.o: ../config.h Fl_File_Browser.o: ../FL/Enumerations.H Fl_File_Browser.o: ../FL/filename.H Fl_File_Browser.o: ../FL/Fl.H Fl_File_Browser.o: ../FL/fl_attr.h Fl_File_Browser.o: ../FL/Fl_Browser.H Fl_File_Browser.o: ../FL/Fl_Cairo.H Fl_File_Browser.o: ../FL/fl_casts.H Fl_File_Browser.o: ../FL/fl_config.h Fl_File_Browser.o: ../FL/fl_draw.H Fl_File_Browser.o: ../FL/Fl_Export.H Fl_File_Browser.o: ../FL/Fl_File_Browser.H Fl_File_Browser.o: ../FL/Fl_File_Icon.H Fl_File_Browser.o: ../FL/Fl_Image.H Fl_File_Browser.o: ../FL/Fl_Preferences.H Fl_File_Browser.o: ../FL/fl_string_functions.h Fl_File_Browser.o: ../FL/fl_types.h Fl_File_Browser.o: ../FL/fl_utf8.h Fl_File_Browser.o: ../FL/Fl_Widget.H Fl_File_Browser.o: ../FL/platform_types.h Fl_File_Browser.o: flstring.h Fl_File_Browser.o: Fl_System_Driver.H Fl_File_Chooser.o: ../FL/Enumerations.H Fl_File_Chooser.o: ../FL/filename.H Fl_File_Chooser.o: ../FL/Fl.H Fl_File_Chooser.o: ../FL/fl_ask.H Fl_File_Chooser.o: ../FL/fl_attr.h Fl_File_Chooser.o: ../FL/Fl_Bitmap.H Fl_File_Chooser.o: ../FL/Fl_Box.H Fl_File_Chooser.o: ../FL/Fl_Browser.H Fl_File_Chooser.o: ../FL/Fl_Button.H Fl_File_Chooser.o: ../FL/Fl_Cairo.H Fl_File_Chooser.o: ../FL/fl_casts.H Fl_File_Chooser.o: ../FL/Fl_Check_Button.H Fl_File_Chooser.o: ../FL/Fl_Choice.H Fl_File_Chooser.o: ../FL/fl_config.h Fl_File_Chooser.o: ../FL/Fl_Double_Window.H Fl_File_Chooser.o: ../FL/fl_draw.H Fl_File_Chooser.o: ../FL/Fl_Export.H Fl_File_Chooser.o: ../FL/Fl_File_Browser.H Fl_File_Chooser.o: ../FL/Fl_File_Chooser.H Fl_File_Chooser.o: ../FL/Fl_File_Icon.H Fl_File_Chooser.o: ../FL/Fl_File_Input.H Fl_File_Chooser.o: ../FL/Fl_Group.H Fl_File_Chooser.o: ../FL/Fl_Image.H Fl_File_Chooser.o: ../FL/Fl_Input.H Fl_File_Chooser.o: ../FL/Fl_Input_.H Fl_File_Chooser.o: ../FL/Fl_Light_Button.H Fl_File_Chooser.o: ../FL/Fl_Menu_.H Fl_File_Chooser.o: ../FL/Fl_Menu_Button.H Fl_File_Chooser.o: ../FL/Fl_Menu_Item.H Fl_File_Chooser.o: ../FL/Fl_Multi_Label.H Fl_File_Chooser.o: ../FL/Fl_Preferences.H Fl_File_Chooser.o: ../FL/Fl_Return_Button.H Fl_File_Chooser.o: ../FL/Fl_Tile.H Fl_File_Chooser.o: ../FL/fl_types.h Fl_File_Chooser.o: ../FL/fl_utf8.h Fl_File_Chooser.o: ../FL/Fl_Widget.H Fl_File_Chooser.o: ../FL/Fl_Window.H Fl_File_Chooser.o: ../FL/platform_types.h Fl_File_Chooser2.o: ../config.h Fl_File_Chooser2.o: ../FL/Enumerations.H Fl_File_Chooser2.o: ../FL/filename.H Fl_File_Chooser2.o: ../FL/Fl.H Fl_File_Chooser2.o: ../FL/fl_ask.H Fl_File_Chooser2.o: ../FL/fl_attr.h Fl_File_Chooser2.o: ../FL/Fl_Box.H Fl_File_Chooser2.o: ../FL/Fl_Browser.H Fl_File_Chooser2.o: ../FL/Fl_Button.H Fl_File_Chooser2.o: ../FL/Fl_Cairo.H Fl_File_Chooser2.o: ../FL/fl_casts.H Fl_File_Chooser2.o: ../FL/Fl_Check_Button.H Fl_File_Chooser2.o: ../FL/Fl_Choice.H Fl_File_Chooser2.o: ../FL/fl_config.h Fl_File_Chooser2.o: ../FL/Fl_Double_Window.H Fl_File_Chooser2.o: ../FL/fl_draw.H Fl_File_Chooser2.o: ../FL/Fl_Export.H Fl_File_Chooser2.o: ../FL/Fl_File_Browser.H Fl_File_Chooser2.o: ../FL/Fl_File_Chooser.H Fl_File_Chooser2.o: ../FL/Fl_File_Icon.H Fl_File_Chooser2.o: ../FL/Fl_File_Input.H Fl_File_Chooser2.o: ../FL/Fl_Group.H Fl_File_Chooser2.o: ../FL/Fl_Image.H Fl_File_Chooser2.o: ../FL/Fl_Input.H Fl_File_Chooser2.o: ../FL/Fl_Input_.H Fl_File_Chooser2.o: ../FL/Fl_Light_Button.H Fl_File_Chooser2.o: ../FL/Fl_Menu_.H Fl_File_Chooser2.o: ../FL/Fl_Menu_Button.H Fl_File_Chooser2.o: ../FL/Fl_Menu_Item.H Fl_File_Chooser2.o: ../FL/Fl_Multi_Label.H Fl_File_Chooser2.o: ../FL/Fl_Preferences.H Fl_File_Chooser2.o: ../FL/Fl_Return_Button.H Fl_File_Chooser2.o: ../FL/Fl_Shared_Image.H Fl_File_Chooser2.o: ../FL/fl_string_functions.h Fl_File_Chooser2.o: ../FL/Fl_Tile.H Fl_File_Chooser2.o: ../FL/fl_types.h Fl_File_Chooser2.o: ../FL/fl_utf8.h Fl_File_Chooser2.o: ../FL/Fl_Widget.H Fl_File_Chooser2.o: ../FL/Fl_Window.H Fl_File_Chooser2.o: ../FL/platform.H Fl_File_Chooser2.o: ../FL/platform_types.h Fl_File_Chooser2.o: ../FL/x11.H Fl_File_Chooser2.o: flstring.h Fl_File_Chooser2.o: Fl_System_Driver.H fl_file_dir.o: ../config.h fl_file_dir.o: ../FL/Enumerations.H fl_file_dir.o: ../FL/filename.H fl_file_dir.o: ../FL/Fl.H fl_file_dir.o: ../FL/fl_ask.H fl_file_dir.o: ../FL/fl_attr.h fl_file_dir.o: ../FL/Fl_Box.H fl_file_dir.o: ../FL/Fl_Browser.H fl_file_dir.o: ../FL/Fl_Button.H fl_file_dir.o: ../FL/Fl_Cairo.H fl_file_dir.o: ../FL/fl_casts.H fl_file_dir.o: ../FL/Fl_Check_Button.H fl_file_dir.o: ../FL/Fl_Choice.H fl_file_dir.o: ../FL/fl_config.h fl_file_dir.o: ../FL/Fl_Double_Window.H fl_file_dir.o: ../FL/Fl_Export.H fl_file_dir.o: ../FL/Fl_File_Browser.H fl_file_dir.o: ../FL/Fl_File_Chooser.H fl_file_dir.o: ../FL/Fl_File_Icon.H fl_file_dir.o: ../FL/Fl_File_Input.H fl_file_dir.o: ../FL/Fl_Group.H fl_file_dir.o: ../FL/Fl_Image.H fl_file_dir.o: ../FL/Fl_Input.H fl_file_dir.o: ../FL/Fl_Input_.H fl_file_dir.o: ../FL/Fl_Light_Button.H fl_file_dir.o: ../FL/Fl_Menu_.H fl_file_dir.o: ../FL/Fl_Menu_Button.H fl_file_dir.o: ../FL/Fl_Menu_Item.H fl_file_dir.o: ../FL/Fl_Multi_Label.H fl_file_dir.o: ../FL/Fl_Preferences.H fl_file_dir.o: ../FL/Fl_Return_Button.H fl_file_dir.o: ../FL/fl_string_functions.h fl_file_dir.o: ../FL/Fl_Tile.H fl_file_dir.o: ../FL/fl_types.h fl_file_dir.o: ../FL/fl_utf8.h fl_file_dir.o: ../FL/Fl_Widget.H fl_file_dir.o: ../FL/Fl_Window.H fl_file_dir.o: ../FL/platform_types.h fl_file_dir.o: flstring.h Fl_File_Icon.o: ../config.h Fl_File_Icon.o: ../FL/Enumerations.H Fl_File_Icon.o: ../FL/filename.H Fl_File_Icon.o: ../FL/Fl.H Fl_File_Icon.o: ../FL/fl_attr.h Fl_File_Icon.o: ../FL/Fl_Cairo.H Fl_File_Icon.o: ../FL/fl_casts.H Fl_File_Icon.o: ../FL/fl_config.h Fl_File_Icon.o: ../FL/fl_draw.H Fl_File_Icon.o: ../FL/Fl_Export.H Fl_File_Icon.o: ../FL/Fl_File_Icon.H Fl_File_Icon.o: ../FL/Fl_Preferences.H Fl_File_Icon.o: ../FL/fl_string_functions.h Fl_File_Icon.o: ../FL/fl_types.h Fl_File_Icon.o: ../FL/fl_utf8.h Fl_File_Icon.o: ../FL/Fl_Widget.H Fl_File_Icon.o: ../FL/platform_types.h Fl_File_Icon.o: flstring.h Fl_File_Icon.o: Fl_System_Driver.H Fl_File_Icon2.o: ../config.h Fl_File_Icon2.o: ../FL/filename.H Fl_File_Icon2.o: ../FL/Fl.H Fl_File_Icon2.o: ../FL/fl_config.h Fl_File_Icon2.o: ../FL/fl_draw.H Fl_File_Icon2.o: ../FL/Fl_Export.H Fl_File_Icon2.o: ../FL/Fl_File_Icon.H Fl_File_Icon2.o: ../FL/Fl_Image.H Fl_File_Icon2.o: ../FL/Fl_Shared_Image.H Fl_File_Icon2.o: ../FL/fl_string_functions.h Fl_File_Icon2.o: ../FL/fl_utf8.h Fl_File_Icon2.o: ../FL/Fl_Widget.H Fl_File_Icon2.o: ../FL/math.h Fl_File_Icon2.o: ../FL/platform_types.h Fl_File_Icon2.o: flstring.h Fl_File_Input.o: ../config.h Fl_File_Input.o: ../FL/Enumerations.H Fl_File_Input.o: ../FL/filename.H Fl_File_Input.o: ../FL/Fl.H Fl_File_Input.o: ../FL/fl_attr.h Fl_File_Input.o: ../FL/Fl_Bitmap.H Fl_File_Input.o: ../FL/Fl_Cairo.H Fl_File_Input.o: ../FL/fl_casts.H Fl_File_Input.o: ../FL/fl_config.h Fl_File_Input.o: ../FL/fl_draw.H Fl_File_Input.o: ../FL/Fl_Export.H Fl_File_Input.o: ../FL/Fl_File_Input.H Fl_File_Input.o: ../FL/Fl_Group.H Fl_File_Input.o: ../FL/Fl_Image.H Fl_File_Input.o: ../FL/Fl_Input.H Fl_File_Input.o: ../FL/Fl_Input_.H Fl_File_Input.o: ../FL/Fl_Preferences.H Fl_File_Input.o: ../FL/fl_string_functions.h Fl_File_Input.o: ../FL/fl_types.h Fl_File_Input.o: ../FL/fl_utf8.h Fl_File_Input.o: ../FL/Fl_Widget.H Fl_File_Input.o: ../FL/Fl_Window.H Fl_File_Input.o: ../FL/platform_types.h Fl_File_Input.o: flstring.h Fl_File_Input.o: Fl_System_Driver.H Fl_Flex.o: ../FL/Fl_Flex.H Fl_Flex.o: ../FL/Fl_Group.H fl_font.o: ../config.h fl_font.o: ../FL/Enumerations.H fl_font.o: ../FL/Fl.H fl_font.o: ../FL/fl_attr.h fl_font.o: ../FL/Fl_Bitmap.H fl_font.o: ../FL/Fl_Cairo.H fl_font.o: ../FL/fl_casts.H fl_font.o: ../FL/fl_config.h fl_font.o: ../FL/Fl_Device.H fl_font.o: ../FL/fl_draw.H fl_font.o: ../FL/Fl_Export.H fl_font.o: ../FL/Fl_Graphics_Driver.H fl_font.o: ../FL/Fl_Group.H fl_font.o: ../FL/Fl_Image.H fl_font.o: ../FL/Fl_Pixmap.H fl_font.o: ../FL/Fl_Plugin.H fl_font.o: ../FL/Fl_Preferences.H fl_font.o: ../FL/Fl_Rect.H fl_font.o: ../FL/Fl_RGB_Image.H fl_font.o: ../FL/Fl_Scrollbar.H fl_font.o: ../FL/Fl_Slider.H fl_font.o: ../FL/fl_string_functions.h fl_font.o: ../FL/Fl_Text_Buffer.H fl_font.o: ../FL/Fl_Text_Display.H fl_font.o: ../FL/Fl_Text_Editor.H fl_font.o: ../FL/fl_types.h fl_font.o: ../FL/fl_utf8.h fl_font.o: ../FL/Fl_Valuator.H fl_font.o: ../FL/Fl_Widget.H fl_font.o: ../FL/platform_types.h fl_font.o: flstring.h fl_font.o: Fl_Screen_Driver.H Fl_get_key.o: ../config.h Fl_get_key.o: ../FL/Enumerations.H Fl_get_key.o: ../FL/Fl.H Fl_get_key.o: ../FL/fl_attr.h Fl_get_key.o: ../FL/Fl_Bitmap.H Fl_get_key.o: ../FL/Fl_Cairo.H Fl_get_key.o: ../FL/fl_casts.H Fl_get_key.o: ../FL/fl_config.h Fl_get_key.o: ../FL/Fl_Device.H Fl_get_key.o: ../FL/fl_draw.H Fl_get_key.o: ../FL/Fl_Export.H Fl_get_key.o: ../FL/Fl_Graphics_Driver.H Fl_get_key.o: ../FL/Fl_Group.H Fl_get_key.o: ../FL/Fl_Image.H Fl_get_key.o: ../FL/Fl_Pixmap.H Fl_get_key.o: ../FL/Fl_Plugin.H Fl_get_key.o: ../FL/Fl_Preferences.H Fl_get_key.o: ../FL/Fl_Rect.H Fl_get_key.o: ../FL/Fl_RGB_Image.H Fl_get_key.o: ../FL/Fl_Scrollbar.H Fl_get_key.o: ../FL/Fl_Slider.H Fl_get_key.o: ../FL/Fl_Text_Buffer.H Fl_get_key.o: ../FL/Fl_Text_Display.H Fl_get_key.o: ../FL/Fl_Text_Editor.H Fl_get_key.o: ../FL/fl_types.h Fl_get_key.o: ../FL/fl_utf8.h Fl_get_key.o: ../FL/Fl_Valuator.H Fl_get_key.o: ../FL/Fl_Widget.H Fl_get_key.o: ../FL/platform.H Fl_get_key.o: ../FL/platform_types.h Fl_get_key.o: ../FL/x11.H Fl_get_key.o: drivers/Unix/Fl_Unix_Screen_Driver.H Fl_get_key.o: drivers/X11/Fl_X11_Screen_Driver.H Fl_get_key.o: Fl_Screen_Driver.H Fl_get_system_colors.o: ../config.h Fl_get_system_colors.o: ../FL/Enumerations.H Fl_get_system_colors.o: ../FL/filename.H Fl_get_system_colors.o: ../FL/Fl.H Fl_get_system_colors.o: ../FL/fl_attr.h Fl_get_system_colors.o: ../FL/Fl_Bitmap.H Fl_get_system_colors.o: ../FL/Fl_Cairo.H Fl_get_system_colors.o: ../FL/fl_casts.H Fl_get_system_colors.o: ../FL/fl_config.h Fl_get_system_colors.o: ../FL/Fl_Device.H Fl_get_system_colors.o: ../FL/fl_draw.H Fl_get_system_colors.o: ../FL/Fl_Export.H Fl_get_system_colors.o: ../FL/Fl_Graphics_Driver.H Fl_get_system_colors.o: ../FL/Fl_Group.H Fl_get_system_colors.o: ../FL/Fl_Image.H Fl_get_system_colors.o: ../FL/Fl_Pixmap.H Fl_get_system_colors.o: ../FL/Fl_Plugin.H Fl_get_system_colors.o: ../FL/Fl_Preferences.H Fl_get_system_colors.o: ../FL/Fl_Rect.H Fl_get_system_colors.o: ../FL/Fl_RGB_Image.H Fl_get_system_colors.o: ../FL/Fl_Scrollbar.H Fl_get_system_colors.o: ../FL/Fl_Slider.H Fl_get_system_colors.o: ../FL/fl_string_functions.h Fl_get_system_colors.o: ../FL/Fl_Text_Buffer.H Fl_get_system_colors.o: ../FL/Fl_Text_Display.H Fl_get_system_colors.o: ../FL/Fl_Text_Editor.H Fl_get_system_colors.o: ../FL/Fl_Tiled_Image.H Fl_get_system_colors.o: ../FL/fl_types.h Fl_get_system_colors.o: ../FL/fl_utf8.h Fl_get_system_colors.o: ../FL/Fl_Valuator.H Fl_get_system_colors.o: ../FL/Fl_Widget.H Fl_get_system_colors.o: ../FL/math.h Fl_get_system_colors.o: ../FL/platform.H Fl_get_system_colors.o: ../FL/platform_types.h Fl_get_system_colors.o: ../FL/x11.H Fl_get_system_colors.o: flstring.h Fl_get_system_colors.o: Fl_Screen_Driver.H Fl_get_system_colors.o: Fl_System_Driver.H Fl_get_system_colors.o: tile.xpm Fl_GIF_Image.o: ../config.h Fl_GIF_Image.o: ../FL/Enumerations.H Fl_GIF_Image.o: ../FL/Fl.H Fl_GIF_Image.o: ../FL/fl_attr.h Fl_GIF_Image.o: ../FL/Fl_Cairo.H Fl_GIF_Image.o: ../FL/fl_casts.H Fl_GIF_Image.o: ../FL/fl_config.h Fl_GIF_Image.o: ../FL/Fl_Export.H Fl_GIF_Image.o: ../FL/Fl_GIF_Image.H Fl_GIF_Image.o: ../FL/Fl_Image.H Fl_GIF_Image.o: ../FL/Fl_Pixmap.H Fl_GIF_Image.o: ../FL/fl_string_functions.h Fl_GIF_Image.o: ../FL/fl_types.h Fl_GIF_Image.o: ../FL/fl_utf8.h Fl_GIF_Image.o: ../FL/platform_types.h Fl_GIF_Image.o: flstring.h Fl_GIF_Image.o: Fl_Image_Reader.h fl_gleam.o: ../FL/Enumerations.H fl_gleam.o: ../FL/Fl.H fl_gleam.o: ../FL/fl_attr.h fl_gleam.o: ../FL/Fl_Cairo.H fl_gleam.o: ../FL/fl_casts.H fl_gleam.o: ../FL/fl_config.h fl_gleam.o: ../FL/fl_draw.H fl_gleam.o: ../FL/Fl_Export.H fl_gleam.o: ../FL/fl_types.h fl_gleam.o: ../FL/fl_utf8.h fl_gleam.o: ../FL/platform_types.h Fl_Gl_Choice.o: ../config.h Fl_Gl_Choice.o: ../FL/Enumerations.H Fl_Gl_Choice.o: ../FL/Fl.H Fl_Gl_Choice.o: ../FL/fl_attr.h Fl_Gl_Choice.o: ../FL/Fl_Cairo.H Fl_Gl_Choice.o: ../FL/fl_casts.H Fl_Gl_Choice.o: ../FL/fl_config.h Fl_Gl_Choice.o: ../FL/Fl_Export.H Fl_Gl_Choice.o: ../FL/Fl_Gl_Window.H Fl_Gl_Choice.o: ../FL/fl_types.h Fl_Gl_Choice.o: ../FL/fl_utf8.h Fl_Gl_Choice.o: ../FL/Fl_Window.H Fl_Gl_Choice.o: ../FL/gl.h Fl_Gl_Choice.o: ../FL/gl_draw.H Fl_Gl_Choice.o: ../FL/platform_types.h Fl_Gl_Choice.o: Fl_Gl_Choice.H Fl_Gl_Choice.o: Fl_Gl_Window_Driver.H Fl_Gl_Device_Plugin.o: ../config.h Fl_Gl_Device_Plugin.o: ../FL/Enumerations.H Fl_Gl_Device_Plugin.o: ../FL/fl_attr.h Fl_Gl_Device_Plugin.o: ../FL/fl_config.h Fl_Gl_Device_Plugin.o: ../FL/Fl_Device.H Fl_Gl_Device_Plugin.o: ../FL/Fl_Export.H Fl_Gl_Device_Plugin.o: ../FL/Fl_Gl_Window.H Fl_Gl_Device_Plugin.o: ../FL/Fl_Image.H Fl_Gl_Device_Plugin.o: ../FL/Fl_Plugin.H Fl_Gl_Device_Plugin.o: ../FL/Fl_Preferences.H Fl_Gl_Device_Plugin.o: ../FL/Fl_RGB_Image.H Fl_Gl_Device_Plugin.o: ../FL/fl_types.h Fl_Gl_Device_Plugin.o: ../FL/Fl_Window.H Fl_Gl_Device_Plugin.o: ../FL/gl.h Fl_Gl_Device_Plugin.o: ../FL/platform_types.h Fl_Gl_Device_Plugin.o: Fl_Gl_Window_Driver.H Fl_Gl_Overlay.o: ../config.h Fl_Gl_Overlay.o: ../FL/Enumerations.H Fl_Gl_Overlay.o: ../FL/Fl.H Fl_Gl_Overlay.o: ../FL/fl_attr.h Fl_Gl_Overlay.o: ../FL/Fl_Cairo.H Fl_Gl_Overlay.o: ../FL/fl_casts.H Fl_Gl_Overlay.o: ../FL/fl_config.h Fl_Gl_Overlay.o: ../FL/Fl_Export.H Fl_Gl_Overlay.o: ../FL/Fl_Gl_Window.H Fl_Gl_Overlay.o: ../FL/fl_types.h Fl_Gl_Overlay.o: ../FL/fl_utf8.h Fl_Gl_Overlay.o: ../FL/Fl_Window.H Fl_Gl_Overlay.o: ../FL/gl.h Fl_Gl_Overlay.o: ../FL/platform_types.h Fl_Gl_Overlay.o: Fl_Gl_Window_Driver.H Fl_Gl_Window.o: ../config.h Fl_Gl_Window.o: ../FL/Enumerations.H Fl_Gl_Window.o: ../FL/Fl.H Fl_Gl_Window.o: ../FL/fl_attr.h Fl_Gl_Window.o: ../FL/Fl_Bitmap.H Fl_Gl_Window.o: ../FL/Fl_Cairo.H Fl_Gl_Window.o: ../FL/fl_casts.H Fl_Gl_Window.o: ../FL/fl_config.h Fl_Gl_Window.o: ../FL/Fl_Device.H Fl_Gl_Window.o: ../FL/Fl_Double_Window.H Fl_Gl_Window.o: ../FL/fl_draw.H Fl_Gl_Window.o: ../FL/Fl_Export.H Fl_Gl_Window.o: ../FL/Fl_Gl_Window.H Fl_Gl_Window.o: ../FL/Fl_Graphics_Driver.H Fl_Gl_Window.o: ../FL/Fl_Group.H Fl_Gl_Window.o: ../FL/Fl_Image.H Fl_Gl_Window.o: ../FL/Fl_Overlay_Window.H Fl_Gl_Window.o: ../FL/Fl_Pixmap.H Fl_Gl_Window.o: ../FL/Fl_Plugin.H Fl_Gl_Window.o: ../FL/Fl_Preferences.H Fl_Gl_Window.o: ../FL/Fl_RGB_Image.H Fl_Gl_Window.o: ../FL/fl_types.h Fl_Gl_Window.o: ../FL/fl_utf8.h Fl_Gl_Window.o: ../FL/Fl_Widget.H Fl_Gl_Window.o: ../FL/Fl_Window.H Fl_Gl_Window.o: ../FL/gl.h Fl_Gl_Window.o: ../FL/platform_types.h Fl_Gl_Window.o: drivers/OpenGL/Fl_OpenGL_Display_Device.H Fl_Gl_Window.o: drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H Fl_Gl_Window.o: Fl_Gl_Window_Driver.H Fl_Gl_Window.o: Fl_Window_Driver.H Fl_grab.o: ../FL/Enumerations.H Fl_grab.o: ../FL/Fl.H Fl_grab.o: ../FL/fl_attr.h Fl_grab.o: ../FL/Fl_Bitmap.H Fl_grab.o: ../FL/Fl_Cairo.H Fl_grab.o: ../FL/fl_casts.H Fl_grab.o: ../FL/fl_config.h Fl_grab.o: ../FL/Fl_Device.H Fl_grab.o: ../FL/fl_draw.H Fl_grab.o: ../FL/Fl_Export.H Fl_grab.o: ../FL/Fl_Graphics_Driver.H Fl_grab.o: ../FL/Fl_Group.H Fl_grab.o: ../FL/Fl_Image.H Fl_grab.o: ../FL/Fl_Pixmap.H Fl_grab.o: ../FL/Fl_Plugin.H Fl_grab.o: ../FL/Fl_Preferences.H Fl_grab.o: ../FL/Fl_Rect.H Fl_grab.o: ../FL/Fl_RGB_Image.H Fl_grab.o: ../FL/Fl_Scrollbar.H Fl_grab.o: ../FL/Fl_Slider.H Fl_grab.o: ../FL/Fl_Text_Buffer.H Fl_grab.o: ../FL/Fl_Text_Display.H Fl_grab.o: ../FL/Fl_Text_Editor.H Fl_grab.o: ../FL/fl_types.h Fl_grab.o: ../FL/fl_utf8.h Fl_grab.o: ../FL/Fl_Valuator.H Fl_grab.o: ../FL/Fl_Widget.H Fl_grab.o: ../FL/platform_types.h Fl_grab.o: Fl_Screen_Driver.H Fl_Graphics_Driver.o: ../config.h Fl_Graphics_Driver.o: ../FL/Enumerations.H Fl_Graphics_Driver.o: ../FL/Fl.H Fl_Graphics_Driver.o: ../FL/fl_attr.h Fl_Graphics_Driver.o: ../FL/Fl_Bitmap.H Fl_Graphics_Driver.o: ../FL/Fl_Cairo.H Fl_Graphics_Driver.o: ../FL/fl_casts.H Fl_Graphics_Driver.o: ../FL/fl_config.h Fl_Graphics_Driver.o: ../FL/Fl_Device.H Fl_Graphics_Driver.o: ../FL/fl_draw.H Fl_Graphics_Driver.o: ../FL/Fl_Export.H Fl_Graphics_Driver.o: ../FL/Fl_Graphics_Driver.H Fl_Graphics_Driver.o: ../FL/Fl_Group.H Fl_Graphics_Driver.o: ../FL/Fl_Image.H Fl_Graphics_Driver.o: ../FL/Fl_Image_Surface.H Fl_Graphics_Driver.o: ../FL/Fl_Pixmap.H Fl_Graphics_Driver.o: ../FL/Fl_Plugin.H Fl_Graphics_Driver.o: ../FL/Fl_Preferences.H Fl_Graphics_Driver.o: ../FL/Fl_Rect.H Fl_Graphics_Driver.o: ../FL/Fl_RGB_Image.H Fl_Graphics_Driver.o: ../FL/Fl_Scrollbar.H Fl_Graphics_Driver.o: ../FL/Fl_Shared_Image.H Fl_Graphics_Driver.o: ../FL/Fl_Slider.H Fl_Graphics_Driver.o: ../FL/Fl_Text_Buffer.H Fl_Graphics_Driver.o: ../FL/Fl_Text_Display.H Fl_Graphics_Driver.o: ../FL/Fl_Text_Editor.H Fl_Graphics_Driver.o: ../FL/fl_types.h Fl_Graphics_Driver.o: ../FL/fl_utf8.h Fl_Graphics_Driver.o: ../FL/Fl_Valuator.H Fl_Graphics_Driver.o: ../FL/Fl_Widget.H Fl_Graphics_Driver.o: ../FL/Fl_Widget_Surface.H Fl_Graphics_Driver.o: ../FL/Fl_Window.H Fl_Graphics_Driver.o: ../FL/math.h Fl_Graphics_Driver.o: ../FL/platform.H Fl_Graphics_Driver.o: ../FL/platform_types.h Fl_Graphics_Driver.o: ../FL/x11.H Fl_Graphics_Driver.o: Fl_Screen_Driver.H Fl_Grid.o: ../FL/fl_draw.H Fl_Grid.o: ../FL/Fl_Grid.H Fl_Grid.o: ../FL/Fl_Group.H Fl_Grid.o: ../FL/Fl_Rect.H Fl_Grid.o: ../FL/Fl_Widget.H Fl_Group.o: ../FL/Enumerations.H Fl_Group.o: ../FL/Fl.H Fl_Group.o: ../FL/fl_attr.h Fl_Group.o: ../FL/Fl_Bitmap.H Fl_Group.o: ../FL/Fl_Cairo.H Fl_Group.o: ../FL/fl_casts.H Fl_Group.o: ../FL/fl_config.h Fl_Group.o: ../FL/Fl_Double_Window.H Fl_Group.o: ../FL/fl_draw.H Fl_Group.o: ../FL/Fl_Export.H Fl_Group.o: ../FL/Fl_Group.H Fl_Group.o: ../FL/Fl_Image.H Fl_Group.o: ../FL/Fl_Overlay_Window.H Fl_Group.o: ../FL/Fl_Rect.H Fl_Group.o: ../FL/fl_types.h Fl_Group.o: ../FL/fl_utf8.h Fl_Group.o: ../FL/Fl_Widget.H Fl_Group.o: ../FL/Fl_Window.H Fl_Group.o: ../FL/platform_types.h Fl_Group.o: Fl_Window_Driver.H fl_gtk.o: ../FL/Enumerations.H fl_gtk.o: ../FL/Fl.H fl_gtk.o: ../FL/fl_attr.h fl_gtk.o: ../FL/Fl_Cairo.H fl_gtk.o: ../FL/fl_casts.H fl_gtk.o: ../FL/fl_config.h fl_gtk.o: ../FL/fl_draw.H fl_gtk.o: ../FL/Fl_Export.H fl_gtk.o: ../FL/fl_types.h fl_gtk.o: ../FL/fl_utf8.h fl_gtk.o: ../FL/platform_types.h Fl_Help_Dialog.o: ../config.h Fl_Help_Dialog.o: ../FL/Enumerations.H Fl_Help_Dialog.o: ../FL/filename.H Fl_Help_Dialog.o: ../FL/Fl.H Fl_Help_Dialog.o: ../FL/fl_ask.H Fl_Help_Dialog.o: ../FL/fl_attr.h Fl_Help_Dialog.o: ../FL/Fl_Bitmap.H Fl_Help_Dialog.o: ../FL/Fl_Box.H Fl_Help_Dialog.o: ../FL/Fl_Button.H Fl_Help_Dialog.o: ../FL/Fl_Cairo.H Fl_Help_Dialog.o: ../FL/fl_casts.H Fl_Help_Dialog.o: ../FL/fl_config.h Fl_Help_Dialog.o: ../FL/Fl_Device.H Fl_Help_Dialog.o: ../FL/Fl_Double_Window.H Fl_Help_Dialog.o: ../FL/fl_draw.H Fl_Help_Dialog.o: ../FL/Fl_Export.H Fl_Help_Dialog.o: ../FL/Fl_Graphics_Driver.H Fl_Help_Dialog.o: ../FL/Fl_Group.H Fl_Help_Dialog.o: ../FL/Fl_Help_Dialog.H Fl_Help_Dialog.o: ../FL/Fl_Help_View.H Fl_Help_Dialog.o: ../FL/Fl_Image.H Fl_Help_Dialog.o: ../FL/Fl_Input.H Fl_Help_Dialog.o: ../FL/Fl_Input_.H Fl_Help_Dialog.o: ../FL/Fl_Pixmap.H Fl_Help_Dialog.o: ../FL/Fl_Plugin.H Fl_Help_Dialog.o: ../FL/Fl_Preferences.H Fl_Help_Dialog.o: ../FL/Fl_Rect.H Fl_Help_Dialog.o: ../FL/Fl_RGB_Image.H Fl_Help_Dialog.o: ../FL/Fl_Scrollbar.H Fl_Help_Dialog.o: ../FL/Fl_Shared_Image.H Fl_Help_Dialog.o: ../FL/Fl_Slider.H Fl_Help_Dialog.o: ../FL/fl_string_functions.h Fl_Help_Dialog.o: ../FL/fl_types.h Fl_Help_Dialog.o: ../FL/fl_utf8.h Fl_Help_Dialog.o: ../FL/Fl_Valuator.H Fl_Help_Dialog.o: ../FL/Fl_Widget.H Fl_Help_Dialog.o: ../FL/Fl_Window.H Fl_Help_Dialog.o: ../FL/platform_types.h Fl_Help_Dialog.o: flstring.h Fl_Help_View.o: ../config.h Fl_Help_View.o: ../FL/Enumerations.H Fl_Help_View.o: ../FL/filename.H Fl_Help_View.o: ../FL/Fl.H Fl_Help_View.o: ../FL/fl_attr.h Fl_Help_View.o: ../FL/Fl_Bitmap.H Fl_Help_View.o: ../FL/Fl_Cairo.H Fl_Help_View.o: ../FL/fl_casts.H Fl_Help_View.o: ../FL/fl_config.h Fl_Help_View.o: ../FL/Fl_Device.H Fl_Help_View.o: ../FL/fl_draw.H Fl_Help_View.o: ../FL/Fl_Export.H Fl_Help_View.o: ../FL/Fl_Graphics_Driver.H Fl_Help_View.o: ../FL/Fl_Group.H Fl_Help_View.o: ../FL/Fl_Help_View.H Fl_Help_View.o: ../FL/Fl_Image.H Fl_Help_View.o: ../FL/Fl_Menu_Item.H Fl_Help_View.o: ../FL/Fl_Multi_Label.H Fl_Help_View.o: ../FL/Fl_Pixmap.H Fl_Help_View.o: ../FL/Fl_Plugin.H Fl_Help_View.o: ../FL/Fl_Preferences.H Fl_Help_View.o: ../FL/Fl_Rect.H Fl_Help_View.o: ../FL/Fl_RGB_Image.H Fl_Help_View.o: ../FL/Fl_Scrollbar.H Fl_Help_View.o: ../FL/Fl_Shared_Image.H Fl_Help_View.o: ../FL/Fl_Slider.H Fl_Help_View.o: ../FL/fl_string_functions.h Fl_Help_View.o: ../FL/fl_types.h Fl_Help_View.o: ../FL/fl_utf8.h Fl_Help_View.o: ../FL/Fl_Valuator.H Fl_Help_View.o: ../FL/Fl_Widget.H Fl_Help_View.o: ../FL/Fl_Window.H Fl_Help_View.o: ../FL/platform_types.h Fl_Help_View.o: flstring.h Fl_Help_View.o: Fl_Int_Vector.H Fl_Help_View.o: Fl_String.H Fl_ICO_Image.o: ../config.h Fl_ICO_Image.o: ../FL/Enumerations.H Fl_ICO_Image.o: ../FL/Fl.H Fl_ICO_Image.o: ../FL/fl_attr.h Fl_ICO_Image.o: ../FL/Fl_BMP_Image.H Fl_ICO_Image.o: ../FL/Fl_Cairo.H Fl_ICO_Image.o: ../FL/fl_casts.H Fl_ICO_Image.o: ../FL/fl_config.h Fl_ICO_Image.o: ../FL/Fl_Export.H Fl_ICO_Image.o: ../FL/Fl_ICO_Image.H Fl_ICO_Image.o: ../FL/Fl_Image.H Fl_ICO_Image.o: ../FL/Fl_PNG_Image.H Fl_ICO_Image.o: ../FL/fl_types.h Fl_ICO_Image.o: ../FL/fl_utf8.h Fl_ICO_Image.o: ../FL/platform_types.h Fl_ICO_Image.o: Fl_Image_Reader.h Fl_Image.o: ../config.h Fl_Image.o: ../FL/Enumerations.H Fl_Image.o: ../FL/Fl.H Fl_Image.o: ../FL/fl_attr.h Fl_Image.o: ../FL/Fl_Cairo.H Fl_Image.o: ../FL/fl_casts.H Fl_Image.o: ../FL/fl_config.h Fl_Image.o: ../FL/fl_draw.H Fl_Image.o: ../FL/Fl_Export.H Fl_Image.o: ../FL/Fl_Image.H Fl_Image.o: ../FL/Fl_Menu_Item.H Fl_Image.o: ../FL/Fl_Multi_Label.H Fl_Image.o: ../FL/fl_string_functions.h Fl_Image.o: ../FL/fl_types.h Fl_Image.o: ../FL/fl_utf8.h Fl_Image.o: ../FL/Fl_Widget.H Fl_Image.o: ../FL/platform_types.h Fl_Image.o: flstring.h fl_images_core.o: ../config.h fl_images_core.o: ../FL/Enumerations.H fl_images_core.o: ../FL/Fl.H fl_images_core.o: ../FL/Fl_Anim_GIF_Image.H fl_images_core.o: ../FL/fl_attr.h fl_images_core.o: ../FL/Fl_BMP_Image.H fl_images_core.o: ../FL/fl_config.h fl_images_core.o: ../FL/Fl_Export.H fl_images_core.o: ../FL/Fl_GIF_Image.H fl_images_core.o: ../FL/Fl_ICO_Image.H fl_images_core.o: ../FL/Fl_Image.H fl_images_core.o: ../FL/Fl_JPEG_Image.H fl_images_core.o: ../FL/Fl_Pixmap.H fl_images_core.o: ../FL/Fl_PNG_Image.H fl_images_core.o: ../FL/Fl_PNM_Image.H fl_images_core.o: ../FL/Fl_Shared_Image.H fl_images_core.o: ../FL/fl_string_functions.h fl_images_core.o: ../FL/Fl_SVG_Image.H fl_images_core.o: ../FL/fl_types.h fl_images_core.o: ../FL/fl_utf8.h fl_images_core.o: ../FL/Fl_Widget.H fl_images_core.o: ../FL/platform_types.h fl_images_core.o: flstring.h Fl_Image_Reader.o: ../FL/Fl_Export.H Fl_Image_Reader.o: ../FL/fl_string_functions.h Fl_Image_Reader.o: ../FL/fl_utf8.h Fl_Image_Reader.o: Fl_Image_Reader.h Fl_Image_Surface.o: ../FL/Enumerations.H Fl_Image_Surface.o: ../FL/Fl.H Fl_Image_Surface.o: ../FL/fl_attr.h Fl_Image_Surface.o: ../FL/Fl_Bitmap.H Fl_Image_Surface.o: ../FL/Fl_Cairo.H Fl_Image_Surface.o: ../FL/fl_casts.H Fl_Image_Surface.o: ../FL/fl_config.h Fl_Image_Surface.o: ../FL/Fl_Device.H Fl_Image_Surface.o: ../FL/fl_draw.H Fl_Image_Surface.o: ../FL/Fl_Export.H Fl_Image_Surface.o: ../FL/Fl_Group.H Fl_Image_Surface.o: ../FL/Fl_Image.H Fl_Image_Surface.o: ../FL/Fl_Image_Surface.H Fl_Image_Surface.o: ../FL/Fl_Plugin.H Fl_Image_Surface.o: ../FL/Fl_Preferences.H Fl_Image_Surface.o: ../FL/Fl_Shared_Image.H Fl_Image_Surface.o: ../FL/fl_types.h Fl_Image_Surface.o: ../FL/fl_utf8.h Fl_Image_Surface.o: ../FL/Fl_Widget.H Fl_Image_Surface.o: ../FL/Fl_Widget_Surface.H Fl_Image_Surface.o: ../FL/Fl_Window.H Fl_Image_Surface.o: ../FL/platform_types.h Fl_Input.o: ../config.h Fl_Input.o: ../FL/Enumerations.H Fl_Input.o: ../FL/filename.H Fl_Input.o: ../FL/Fl.H Fl_Input.o: ../FL/fl_ask.H Fl_Input.o: ../FL/fl_attr.h Fl_Input.o: ../FL/Fl_Bitmap.H Fl_Input.o: ../FL/Fl_Cairo.H Fl_Input.o: ../FL/fl_casts.H Fl_Input.o: ../FL/fl_config.h Fl_Input.o: ../FL/Fl_Device.H Fl_Input.o: ../FL/fl_draw.H Fl_Input.o: ../FL/Fl_Export.H Fl_Input.o: ../FL/Fl_Float_Input.H Fl_Input.o: ../FL/Fl_Graphics_Driver.H Fl_Input.o: ../FL/Fl_Group.H Fl_Input.o: ../FL/Fl_Image.H Fl_Input.o: ../FL/Fl_Input.H Fl_Input.o: ../FL/Fl_Input_.H Fl_Input.o: ../FL/Fl_Int_Input.H Fl_Input.o: ../FL/Fl_Menu_Item.H Fl_Input.o: ../FL/Fl_Multiline_Input.H Fl_Input.o: ../FL/Fl_Multiline_Output.H Fl_Input.o: ../FL/Fl_Multi_Label.H Fl_Input.o: ../FL/Fl_Output.H Fl_Input.o: ../FL/Fl_Pixmap.H Fl_Input.o: ../FL/Fl_Plugin.H Fl_Input.o: ../FL/Fl_Preferences.H Fl_Input.o: ../FL/Fl_Rect.H Fl_Input.o: ../FL/Fl_RGB_Image.H Fl_Input.o: ../FL/Fl_Scrollbar.H Fl_Input.o: ../FL/Fl_Secret_Input.H Fl_Input.o: ../FL/Fl_Slider.H Fl_Input.o: ../FL/fl_string_functions.h Fl_Input.o: ../FL/Fl_Text_Buffer.H Fl_Input.o: ../FL/Fl_Text_Display.H Fl_Input.o: ../FL/Fl_Text_Editor.H Fl_Input.o: ../FL/fl_types.h Fl_Input.o: ../FL/fl_utf8.h Fl_Input.o: ../FL/Fl_Valuator.H Fl_Input.o: ../FL/Fl_Widget.H Fl_Input.o: ../FL/Fl_Window.H Fl_Input.o: ../FL/platform.H Fl_Input.o: ../FL/platform_types.h Fl_Input.o: ../FL/x11.H Fl_Input.o: flstring.h Fl_Input.o: Fl_Screen_Driver.H Fl_Input.o: Fl_System_Driver.H Fl_Input_.o: ../config.h Fl_Input_.o: ../FL/Enumerations.H Fl_Input_.o: ../FL/Fl.H Fl_Input_.o: ../FL/fl_ask.H Fl_Input_.o: ../FL/fl_attr.h Fl_Input_.o: ../FL/Fl_Bitmap.H Fl_Input_.o: ../FL/Fl_Cairo.H Fl_Input_.o: ../FL/fl_casts.H Fl_Input_.o: ../FL/fl_config.h Fl_Input_.o: ../FL/Fl_Device.H Fl_Input_.o: ../FL/fl_draw.H Fl_Input_.o: ../FL/Fl_Export.H Fl_Input_.o: ../FL/Fl_Graphics_Driver.H Fl_Input_.o: ../FL/Fl_Group.H Fl_Input_.o: ../FL/Fl_Image.H Fl_Input_.o: ../FL/Fl_Input_.H Fl_Input_.o: ../FL/Fl_Pixmap.H Fl_Input_.o: ../FL/Fl_Plugin.H Fl_Input_.o: ../FL/Fl_Preferences.H Fl_Input_.o: ../FL/Fl_Rect.H Fl_Input_.o: ../FL/Fl_RGB_Image.H Fl_Input_.o: ../FL/Fl_Scrollbar.H Fl_Input_.o: ../FL/Fl_Slider.H Fl_Input_.o: ../FL/fl_string_functions.h Fl_Input_.o: ../FL/Fl_Text_Buffer.H Fl_Input_.o: ../FL/Fl_Text_Display.H Fl_Input_.o: ../FL/Fl_Text_Editor.H Fl_Input_.o: ../FL/fl_types.h Fl_Input_.o: ../FL/fl_utf8.h Fl_Input_.o: ../FL/Fl_Valuator.H Fl_Input_.o: ../FL/Fl_Widget.H Fl_Input_.o: ../FL/Fl_Window.H Fl_Input_.o: ../FL/platform_types.h Fl_Input_.o: flstring.h Fl_Input_.o: Fl_Screen_Driver.H Fl_Input_Choice.o: ../FL/Enumerations.H Fl_Input_Choice.o: ../FL/Fl.H Fl_Input_Choice.o: ../FL/fl_attr.h Fl_Input_Choice.o: ../FL/Fl_Cairo.H Fl_Input_Choice.o: ../FL/fl_casts.H Fl_Input_Choice.o: ../FL/fl_config.h Fl_Input_Choice.o: ../FL/fl_draw.H Fl_Input_Choice.o: ../FL/Fl_Export.H Fl_Input_Choice.o: ../FL/Fl_Group.H Fl_Input_Choice.o: ../FL/Fl_Image.H Fl_Input_Choice.o: ../FL/Fl_Input.H Fl_Input_Choice.o: ../FL/Fl_Input_.H Fl_Input_Choice.o: ../FL/Fl_Input_Choice.H Fl_Input_Choice.o: ../FL/Fl_Menu_.H Fl_Input_Choice.o: ../FL/Fl_Menu_Button.H Fl_Input_Choice.o: ../FL/Fl_Menu_Item.H Fl_Input_Choice.o: ../FL/Fl_Multi_Label.H Fl_Input_Choice.o: ../FL/fl_types.h Fl_Input_Choice.o: ../FL/fl_utf8.h Fl_Input_Choice.o: ../FL/Fl_Widget.H Fl_Input_Choice.o: ../FL/platform_types.h Fl_Int_Vector.o: ../FL/Fl_Export.H Fl_Int_Vector.o: Fl_Int_Vector.H Fl_JPEG_Image.o: ../config.h Fl_JPEG_Image.o: ../FL/Enumerations.H Fl_JPEG_Image.o: ../FL/Fl.H Fl_JPEG_Image.o: ../FL/fl_attr.h Fl_JPEG_Image.o: ../FL/Fl_Cairo.H Fl_JPEG_Image.o: ../FL/fl_casts.H Fl_JPEG_Image.o: ../FL/fl_config.h Fl_JPEG_Image.o: ../FL/Fl_Export.H Fl_JPEG_Image.o: ../FL/Fl_Image.H Fl_JPEG_Image.o: ../FL/Fl_JPEG_Image.H Fl_JPEG_Image.o: ../FL/Fl_Shared_Image.H Fl_JPEG_Image.o: ../FL/fl_types.h Fl_JPEG_Image.o: ../FL/fl_utf8.h Fl_JPEG_Image.o: ../FL/platform_types.h fl_labeltype.o: ../FL/Enumerations.H fl_labeltype.o: ../FL/Fl.H fl_labeltype.o: ../FL/fl_attr.h fl_labeltype.o: ../FL/Fl_Cairo.H fl_labeltype.o: ../FL/fl_casts.H fl_labeltype.o: ../FL/fl_config.h fl_labeltype.o: ../FL/fl_draw.H fl_labeltype.o: ../FL/Fl_Export.H fl_labeltype.o: ../FL/Fl_Group.H fl_labeltype.o: ../FL/Fl_Image.H fl_labeltype.o: ../FL/Fl_Input_.H fl_labeltype.o: ../FL/fl_types.h fl_labeltype.o: ../FL/fl_utf8.h fl_labeltype.o: ../FL/Fl_Widget.H fl_labeltype.o: ../FL/platform_types.h Fl_Light_Button.o: ../config.h Fl_Light_Button.o: ../FL/Enumerations.H Fl_Light_Button.o: ../FL/Fl.H Fl_Light_Button.o: ../FL/fl_attr.h Fl_Light_Button.o: ../FL/Fl_Button.H Fl_Light_Button.o: ../FL/Fl_Cairo.H Fl_Light_Button.o: ../FL/fl_casts.H Fl_Light_Button.o: ../FL/fl_config.h Fl_Light_Button.o: ../FL/fl_draw.H Fl_Light_Button.o: ../FL/Fl_Export.H Fl_Light_Button.o: ../FL/Fl_Light_Button.H Fl_Light_Button.o: ../FL/Fl_Radio_Light_Button.H Fl_Light_Button.o: ../FL/fl_string_functions.h Fl_Light_Button.o: ../FL/fl_types.h Fl_Light_Button.o: ../FL/fl_utf8.h Fl_Light_Button.o: ../FL/platform_types.h Fl_Light_Button.o: flstring.h Fl_lock.o: ../config.h Fl_lock.o: ../FL/Enumerations.H Fl_lock.o: ../FL/filename.H Fl_lock.o: ../FL/Fl.H Fl_lock.o: ../FL/fl_attr.h Fl_lock.o: ../FL/Fl_Cairo.H Fl_lock.o: ../FL/fl_casts.H Fl_lock.o: ../FL/fl_config.h Fl_lock.o: ../FL/Fl_Export.H Fl_lock.o: ../FL/Fl_Preferences.H Fl_lock.o: ../FL/fl_types.h Fl_lock.o: ../FL/fl_utf8.h Fl_lock.o: ../FL/platform_types.h Fl_lock.o: Fl_System_Driver.H Fl_Menu.o: ../config.h Fl_Menu.o: ../FL/Enumerations.H Fl_Menu.o: ../FL/Fl.H Fl_Menu.o: ../FL/fl_attr.h Fl_Menu.o: ../FL/Fl_Bitmap.H Fl_Menu.o: ../FL/Fl_Cairo.H Fl_Menu.o: ../FL/fl_casts.H Fl_Menu.o: ../FL/fl_config.h Fl_Menu.o: ../FL/Fl_Device.H Fl_Menu.o: ../FL/Fl_Double_Window.H Fl_Menu.o: ../FL/fl_draw.H Fl_Menu.o: ../FL/Fl_Export.H Fl_Menu.o: ../FL/Fl_Graphics_Driver.H Fl_Menu.o: ../FL/Fl_Group.H Fl_Menu.o: ../FL/Fl_Image.H Fl_Menu.o: ../FL/Fl_Menu_.H Fl_Menu.o: ../FL/Fl_Menu_Item.H Fl_Menu.o: ../FL/Fl_Menu_Window.H Fl_Menu.o: ../FL/Fl_Multi_Label.H Fl_Menu.o: ../FL/Fl_Overlay_Window.H Fl_Menu.o: ../FL/Fl_Pixmap.H Fl_Menu.o: ../FL/Fl_Plugin.H Fl_Menu.o: ../FL/Fl_Preferences.H Fl_Menu.o: ../FL/Fl_Rect.H Fl_Menu.o: ../FL/Fl_RGB_Image.H Fl_Menu.o: ../FL/Fl_Scrollbar.H Fl_Menu.o: ../FL/Fl_Single_Window.H Fl_Menu.o: ../FL/Fl_Slider.H Fl_Menu.o: ../FL/fl_string_functions.h Fl_Menu.o: ../FL/Fl_Text_Buffer.H Fl_Menu.o: ../FL/Fl_Text_Display.H Fl_Menu.o: ../FL/Fl_Text_Editor.H Fl_Menu.o: ../FL/fl_types.h Fl_Menu.o: ../FL/fl_utf8.h Fl_Menu.o: ../FL/Fl_Valuator.H Fl_Menu.o: ../FL/Fl_Widget.H Fl_Menu.o: ../FL/Fl_Window.H Fl_Menu.o: ../FL/platform_types.h Fl_Menu.o: flstring.h Fl_Menu.o: Fl_Screen_Driver.H Fl_Menu.o: Fl_Window_Driver.H Fl_Menu_.o: ../config.h Fl_Menu_.o: ../FL/Enumerations.H Fl_Menu_.o: ../FL/Fl.H Fl_Menu_.o: ../FL/fl_attr.h Fl_Menu_.o: ../FL/Fl_Cairo.H Fl_Menu_.o: ../FL/fl_casts.H Fl_Menu_.o: ../FL/fl_config.h Fl_Menu_.o: ../FL/Fl_Export.H Fl_Menu_.o: ../FL/Fl_Image.H Fl_Menu_.o: ../FL/Fl_Menu_.H Fl_Menu_.o: ../FL/Fl_Menu_Item.H Fl_Menu_.o: ../FL/Fl_Multi_Label.H Fl_Menu_.o: ../FL/fl_string_functions.h Fl_Menu_.o: ../FL/fl_types.h Fl_Menu_.o: ../FL/fl_utf8.h Fl_Menu_.o: ../FL/Fl_Widget.H Fl_Menu_.o: ../FL/platform_types.h Fl_Menu_.o: flstring.h Fl_Menu_add.o: ../config.h Fl_Menu_add.o: ../FL/Enumerations.H Fl_Menu_add.o: ../FL/Fl.H Fl_Menu_add.o: ../FL/fl_attr.h Fl_Menu_add.o: ../FL/fl_config.h Fl_Menu_add.o: ../FL/Fl_Export.H Fl_Menu_add.o: ../FL/Fl_Image.H Fl_Menu_add.o: ../FL/Fl_Menu_.H Fl_Menu_add.o: ../FL/Fl_Menu_Item.H Fl_Menu_add.o: ../FL/Fl_Multi_Label.H Fl_Menu_add.o: ../FL/fl_string_functions.h Fl_Menu_add.o: ../FL/fl_types.h Fl_Menu_add.o: ../FL/Fl_Widget.H Fl_Menu_add.o: ../FL/platform_types.h Fl_Menu_add.o: flstring.h Fl_Menu_Bar.o: ../FL/Enumerations.H Fl_Menu_Bar.o: ../FL/Fl.H Fl_Menu_Bar.o: ../FL/fl_attr.h Fl_Menu_Bar.o: ../FL/Fl_Cairo.H Fl_Menu_Bar.o: ../FL/fl_casts.H Fl_Menu_Bar.o: ../FL/fl_config.h Fl_Menu_Bar.o: ../FL/fl_draw.H Fl_Menu_Bar.o: ../FL/Fl_Export.H Fl_Menu_Bar.o: ../FL/Fl_Image.H Fl_Menu_Bar.o: ../FL/Fl_Menu_.H Fl_Menu_Bar.o: ../FL/Fl_Menu_Bar.H Fl_Menu_Bar.o: ../FL/Fl_Menu_Item.H Fl_Menu_Bar.o: ../FL/Fl_Multi_Label.H Fl_Menu_Bar.o: ../FL/fl_types.h Fl_Menu_Bar.o: ../FL/fl_utf8.h Fl_Menu_Bar.o: ../FL/Fl_Widget.H Fl_Menu_Bar.o: ../FL/platform_types.h Fl_Menu_Button.o: ../FL/Enumerations.H Fl_Menu_Button.o: ../FL/Fl.H Fl_Menu_Button.o: ../FL/fl_attr.h Fl_Menu_Button.o: ../FL/Fl_Cairo.H Fl_Menu_Button.o: ../FL/fl_casts.H Fl_Menu_Button.o: ../FL/fl_config.h Fl_Menu_Button.o: ../FL/fl_draw.H Fl_Menu_Button.o: ../FL/Fl_Export.H Fl_Menu_Button.o: ../FL/Fl_Image.H Fl_Menu_Button.o: ../FL/Fl_Menu_.H Fl_Menu_Button.o: ../FL/Fl_Menu_Button.H Fl_Menu_Button.o: ../FL/Fl_Menu_Item.H Fl_Menu_Button.o: ../FL/Fl_Multi_Label.H Fl_Menu_Button.o: ../FL/Fl_Rect.H Fl_Menu_Button.o: ../FL/fl_types.h Fl_Menu_Button.o: ../FL/fl_utf8.h Fl_Menu_Button.o: ../FL/Fl_Widget.H Fl_Menu_Button.o: ../FL/platform_types.h Fl_Menu_global.o: ../FL/Enumerations.H Fl_Menu_global.o: ../FL/Fl.H Fl_Menu_global.o: ../FL/fl_attr.h Fl_Menu_global.o: ../FL/Fl_Cairo.H Fl_Menu_global.o: ../FL/fl_casts.H Fl_Menu_global.o: ../FL/fl_config.h Fl_Menu_global.o: ../FL/Fl_Export.H Fl_Menu_global.o: ../FL/Fl_Image.H Fl_Menu_global.o: ../FL/Fl_Menu_.H Fl_Menu_global.o: ../FL/Fl_Menu_Item.H Fl_Menu_global.o: ../FL/Fl_Multi_Label.H Fl_Menu_global.o: ../FL/fl_types.h Fl_Menu_global.o: ../FL/fl_utf8.h Fl_Menu_global.o: ../FL/Fl_Widget.H Fl_Menu_global.o: ../FL/platform_types.h Fl_Menu_Window.o: ../FL/Enumerations.H Fl_Menu_Window.o: ../FL/Fl.H Fl_Menu_Window.o: ../FL/fl_attr.h Fl_Menu_Window.o: ../FL/Fl_Bitmap.H Fl_Menu_Window.o: ../FL/Fl_Cairo.H Fl_Menu_Window.o: ../FL/fl_casts.H Fl_Menu_Window.o: ../FL/fl_config.h Fl_Menu_Window.o: ../FL/Fl_Double_Window.H Fl_Menu_Window.o: ../FL/Fl_Export.H Fl_Menu_Window.o: ../FL/Fl_Group.H Fl_Menu_Window.o: ../FL/Fl_Image.H Fl_Menu_Window.o: ../FL/Fl_Menu_Window.H Fl_Menu_Window.o: ../FL/Fl_Overlay_Window.H Fl_Menu_Window.o: ../FL/Fl_Single_Window.H Fl_Menu_Window.o: ../FL/fl_types.h Fl_Menu_Window.o: ../FL/fl_utf8.h Fl_Menu_Window.o: ../FL/Fl_Widget.H Fl_Menu_Window.o: ../FL/Fl_Window.H Fl_Menu_Window.o: ../FL/platform_types.h Fl_Menu_Window.o: Fl_Window_Driver.H Fl_Message.o: ../config.h Fl_Message.o: ../FL/Enumerations.H Fl_Message.o: ../FL/Fl.H Fl_Message.o: ../FL/fl_ask.H Fl_Message.o: ../FL/fl_attr.h Fl_Message.o: ../FL/Fl_Bitmap.H Fl_Message.o: ../FL/Fl_Box.H Fl_Message.o: ../FL/Fl_Button.H Fl_Message.o: ../FL/Fl_Cairo.H Fl_Message.o: ../FL/fl_casts.H Fl_Message.o: ../FL/fl_config.h Fl_Message.o: ../FL/fl_draw.H Fl_Message.o: ../FL/Fl_Export.H Fl_Message.o: ../FL/Fl_Group.H Fl_Message.o: ../FL/Fl_Image.H Fl_Message.o: ../FL/Fl_Input.H Fl_Message.o: ../FL/Fl_Input_.H Fl_Message.o: ../FL/Fl_Return_Button.H Fl_Message.o: ../FL/Fl_Secret_Input.H Fl_Message.o: ../FL/fl_string_functions.h Fl_Message.o: ../FL/fl_types.h Fl_Message.o: ../FL/fl_utf8.h Fl_Message.o: ../FL/Fl_Widget.H Fl_Message.o: ../FL/Fl_Window.H Fl_Message.o: ../FL/platform_types.h Fl_Message.o: flstring.h Fl_Message.o: Fl_Message.h Fl_Multi_Label.o: ../FL/Enumerations.H Fl_Multi_Label.o: ../FL/Fl.H Fl_Multi_Label.o: ../FL/fl_attr.h Fl_Multi_Label.o: ../FL/Fl_Cairo.H Fl_Multi_Label.o: ../FL/fl_casts.H Fl_Multi_Label.o: ../FL/fl_config.h Fl_Multi_Label.o: ../FL/Fl_Export.H Fl_Multi_Label.o: ../FL/Fl_Image.H Fl_Multi_Label.o: ../FL/Fl_Menu_Item.H Fl_Multi_Label.o: ../FL/Fl_Multi_Label.H Fl_Multi_Label.o: ../FL/fl_types.h Fl_Multi_Label.o: ../FL/fl_utf8.h Fl_Multi_Label.o: ../FL/Fl_Widget.H Fl_Multi_Label.o: ../FL/platform_types.h Fl_Native_File_Chooser.o: ../FL/Enumerations.H Fl_Native_File_Chooser.o: ../FL/filename.H Fl_Native_File_Chooser.o: ../FL/Fl.H Fl_Native_File_Chooser.o: ../FL/fl_ask.H Fl_Native_File_Chooser.o: ../FL/fl_attr.h Fl_Native_File_Chooser.o: ../FL/Fl_Box.H Fl_Native_File_Chooser.o: ../FL/Fl_Browser.H Fl_Native_File_Chooser.o: ../FL/Fl_Button.H Fl_Native_File_Chooser.o: ../FL/Fl_Cairo.H Fl_Native_File_Chooser.o: ../FL/fl_casts.H Fl_Native_File_Chooser.o: ../FL/Fl_Check_Button.H Fl_Native_File_Chooser.o: ../FL/Fl_Choice.H Fl_Native_File_Chooser.o: ../FL/fl_config.h Fl_Native_File_Chooser.o: ../FL/Fl_Double_Window.H Fl_Native_File_Chooser.o: ../FL/Fl_Export.H Fl_Native_File_Chooser.o: ../FL/Fl_File_Browser.H Fl_Native_File_Chooser.o: ../FL/Fl_File_Chooser.H Fl_Native_File_Chooser.o: ../FL/Fl_File_Icon.H Fl_Native_File_Chooser.o: ../FL/Fl_File_Input.H Fl_Native_File_Chooser.o: ../FL/Fl_Group.H Fl_Native_File_Chooser.o: ../FL/Fl_Image.H Fl_Native_File_Chooser.o: ../FL/Fl_Input.H Fl_Native_File_Chooser.o: ../FL/Fl_Input_.H Fl_Native_File_Chooser.o: ../FL/Fl_Light_Button.H Fl_Native_File_Chooser.o: ../FL/Fl_Menu_.H Fl_Native_File_Chooser.o: ../FL/Fl_Menu_Button.H Fl_Native_File_Chooser.o: ../FL/Fl_Menu_Item.H Fl_Native_File_Chooser.o: ../FL/Fl_Multi_Label.H Fl_Native_File_Chooser.o: ../FL/Fl_Native_File_Chooser.H Fl_Native_File_Chooser.o: ../FL/Fl_Preferences.H Fl_Native_File_Chooser.o: ../FL/Fl_Return_Button.H Fl_Native_File_Chooser.o: ../FL/Fl_Tile.H Fl_Native_File_Chooser.o: ../FL/fl_types.h Fl_Native_File_Chooser.o: ../FL/fl_utf8.h Fl_Native_File_Chooser.o: ../FL/Fl_Widget.H Fl_Native_File_Chooser.o: ../FL/Fl_Window.H Fl_Native_File_Chooser.o: ../FL/platform_types.h Fl_Native_File_Chooser_FLTK.o: ../FL/Enumerations.H Fl_Native_File_Chooser_FLTK.o: ../FL/filename.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl.H Fl_Native_File_Chooser_FLTK.o: ../FL/fl_ask.H Fl_Native_File_Chooser_FLTK.o: ../FL/fl_attr.h Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Box.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Browser.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Button.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Cairo.H Fl_Native_File_Chooser_FLTK.o: ../FL/fl_casts.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Check_Button.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Choice.H Fl_Native_File_Chooser_FLTK.o: ../FL/fl_config.h Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Double_Window.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Export.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_File_Browser.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_File_Chooser.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_File_Icon.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_File_Input.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Group.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Image.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Input.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Input_.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Light_Button.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Menu_.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Menu_Button.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Menu_Item.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Multi_Label.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Native_File_Chooser.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Preferences.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Return_Button.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Tile.H Fl_Native_File_Chooser_FLTK.o: ../FL/fl_types.h Fl_Native_File_Chooser_FLTK.o: ../FL/fl_utf8.h Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Widget.H Fl_Native_File_Chooser_FLTK.o: ../FL/Fl_Window.H Fl_Native_File_Chooser_FLTK.o: ../FL/platform_types.h Fl_Native_File_Chooser_GTK.o: ../config.h Fl_Native_File_Chooser_GTK.o: ../FL/Enumerations.H Fl_Native_File_Chooser_GTK.o: ../FL/filename.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl.H Fl_Native_File_Chooser_GTK.o: ../FL/fl_ask.H Fl_Native_File_Chooser_GTK.o: ../FL/fl_attr.h Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Bitmap.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Box.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Browser.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Button.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Cairo.H Fl_Native_File_Chooser_GTK.o: ../FL/fl_casts.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Check_Button.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Choice.H Fl_Native_File_Chooser_GTK.o: ../FL/fl_config.h Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Device.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Double_Window.H Fl_Native_File_Chooser_GTK.o: ../FL/fl_draw.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Export.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_File_Browser.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_File_Chooser.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_File_Icon.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_File_Input.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Graphics_Driver.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Group.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Image.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Image_Surface.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Input.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Input_.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Light_Button.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Menu_.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Menu_Button.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Menu_Item.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Multi_Label.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Native_File_Chooser.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Overlay_Window.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Pixmap.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Plugin.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Preferences.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Rect.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Return_Button.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_RGB_Image.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Scrollbar.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Shared_Image.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Slider.H Fl_Native_File_Chooser_GTK.o: ../FL/fl_string_functions.h Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Text_Buffer.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Text_Display.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Text_Editor.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Tile.H Fl_Native_File_Chooser_GTK.o: ../FL/fl_types.h Fl_Native_File_Chooser_GTK.o: ../FL/fl_utf8.h Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Valuator.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Widget.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Widget_Surface.H Fl_Native_File_Chooser_GTK.o: ../FL/Fl_Window.H Fl_Native_File_Chooser_GTK.o: ../FL/platform.H Fl_Native_File_Chooser_GTK.o: ../FL/platform_types.h Fl_Native_File_Chooser_GTK.o: ../FL/x11.H Fl_Native_File_Chooser_GTK.o: drivers/Posix/Fl_Posix_System_Driver.H Fl_Native_File_Chooser_GTK.o: drivers/Unix/Fl_Unix_Screen_Driver.H Fl_Native_File_Chooser_GTK.o: Fl_Native_File_Chooser_Kdialog.H Fl_Native_File_Chooser_GTK.o: Fl_Native_File_Chooser_Zenity.H Fl_Native_File_Chooser_GTK.o: Fl_Screen_Driver.H Fl_Native_File_Chooser_GTK.o: Fl_String.H Fl_Native_File_Chooser_GTK.o: Fl_System_Driver.H Fl_Native_File_Chooser_GTK.o: Fl_Window_Driver.H Fl_Native_File_Chooser_Kdialog.o: ../config.h Fl_Native_File_Chooser_Kdialog.o: ../FL/Enumerations.H Fl_Native_File_Chooser_Kdialog.o: ../FL/filename.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl.H Fl_Native_File_Chooser_Kdialog.o: ../FL/fl_ask.H Fl_Native_File_Chooser_Kdialog.o: ../FL/fl_attr.h Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Bitmap.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Box.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Browser.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Button.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Cairo.H Fl_Native_File_Chooser_Kdialog.o: ../FL/fl_casts.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Check_Button.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Choice.H Fl_Native_File_Chooser_Kdialog.o: ../FL/fl_config.h Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Device.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Double_Window.H Fl_Native_File_Chooser_Kdialog.o: ../FL/fl_draw.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Export.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_File_Browser.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_File_Chooser.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_File_Icon.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_File_Input.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Graphics_Driver.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Group.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Image.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Input.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Input_.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Light_Button.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Menu_.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Menu_Button.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Menu_Item.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Multi_Label.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Native_File_Chooser.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Overlay_Window.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Pixmap.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Plugin.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Preferences.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Rect.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Return_Button.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_RGB_Image.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Scrollbar.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Slider.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Text_Buffer.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Text_Display.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Text_Editor.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Tile.H Fl_Native_File_Chooser_Kdialog.o: ../FL/fl_types.h Fl_Native_File_Chooser_Kdialog.o: ../FL/fl_utf8.h Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Valuator.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Widget.H Fl_Native_File_Chooser_Kdialog.o: ../FL/Fl_Window.H Fl_Native_File_Chooser_Kdialog.o: ../FL/platform_types.h Fl_Native_File_Chooser_Kdialog.o: drivers/Unix/Fl_Unix_Screen_Driver.H Fl_Native_File_Chooser_Kdialog.o: Fl_Native_File_Chooser_Kdialog.H Fl_Native_File_Chooser_Kdialog.o: Fl_Screen_Driver.H Fl_Native_File_Chooser_Kdialog.o: Fl_String.H Fl_Native_File_Chooser_Kdialog.o: Fl_System_Driver.H Fl_Native_File_Chooser_Kdialog.o: Fl_Window_Driver.H Fl_Native_File_Chooser_Zenity.o: ../config.h Fl_Native_File_Chooser_Zenity.o: ../FL/Enumerations.H Fl_Native_File_Chooser_Zenity.o: ../FL/filename.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl.H Fl_Native_File_Chooser_Zenity.o: ../FL/fl_ask.H Fl_Native_File_Chooser_Zenity.o: ../FL/fl_attr.h Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Box.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Browser.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Button.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Cairo.H Fl_Native_File_Chooser_Zenity.o: ../FL/fl_casts.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Check_Button.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Choice.H Fl_Native_File_Chooser_Zenity.o: ../FL/fl_config.h Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Double_Window.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Export.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_File_Browser.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_File_Chooser.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_File_Icon.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_File_Input.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Group.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Image.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Input.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Input_.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Light_Button.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Menu_.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Menu_Button.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Menu_Item.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Multi_Label.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Native_File_Chooser.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Preferences.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Return_Button.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Tile.H Fl_Native_File_Chooser_Zenity.o: ../FL/fl_types.h Fl_Native_File_Chooser_Zenity.o: ../FL/fl_utf8.h Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Widget.H Fl_Native_File_Chooser_Zenity.o: ../FL/Fl_Window.H Fl_Native_File_Chooser_Zenity.o: ../FL/platform_types.h Fl_Native_File_Chooser_Zenity.o: Fl_Native_File_Chooser_Kdialog.H Fl_Native_File_Chooser_Zenity.o: Fl_Native_File_Chooser_Zenity.H Fl_Native_File_Chooser_Zenity.o: Fl_String.H fl_open_uri.o: ../config.h fl_open_uri.o: ../FL/Enumerations.H fl_open_uri.o: ../FL/filename.H fl_open_uri.o: ../FL/Fl.H fl_open_uri.o: ../FL/fl_attr.h fl_open_uri.o: ../FL/Fl_Cairo.H fl_open_uri.o: ../FL/fl_casts.H fl_open_uri.o: ../FL/fl_config.h fl_open_uri.o: ../FL/Fl_Export.H fl_open_uri.o: ../FL/Fl_Preferences.H fl_open_uri.o: ../FL/fl_string_functions.h fl_open_uri.o: ../FL/fl_types.h fl_open_uri.o: ../FL/fl_utf8.h fl_open_uri.o: ../FL/platform_types.h fl_open_uri.o: flstring.h fl_open_uri.o: Fl_System_Driver.H fl_oval_box.o: ../FL/Enumerations.H fl_oval_box.o: ../FL/Fl.H fl_oval_box.o: ../FL/fl_attr.h fl_oval_box.o: ../FL/Fl_Cairo.H fl_oval_box.o: ../FL/fl_casts.H fl_oval_box.o: ../FL/fl_config.h fl_oval_box.o: ../FL/fl_draw.H fl_oval_box.o: ../FL/Fl_Export.H fl_oval_box.o: ../FL/fl_types.h fl_oval_box.o: ../FL/fl_utf8.h fl_oval_box.o: ../FL/platform_types.h fl_overlay.o: ../FL/Enumerations.H fl_overlay.o: ../FL/Fl.H fl_overlay.o: ../FL/fl_attr.h fl_overlay.o: ../FL/Fl_Bitmap.H fl_overlay.o: ../FL/Fl_Cairo.H fl_overlay.o: ../FL/fl_casts.H fl_overlay.o: ../FL/fl_config.h fl_overlay.o: ../FL/Fl_Device.H fl_overlay.o: ../FL/fl_draw.H fl_overlay.o: ../FL/Fl_Export.H fl_overlay.o: ../FL/Fl_Graphics_Driver.H fl_overlay.o: ../FL/Fl_Group.H fl_overlay.o: ../FL/Fl_Image.H fl_overlay.o: ../FL/Fl_Pixmap.H fl_overlay.o: ../FL/Fl_Plugin.H fl_overlay.o: ../FL/Fl_Preferences.H fl_overlay.o: ../FL/Fl_Rect.H fl_overlay.o: ../FL/Fl_RGB_Image.H fl_overlay.o: ../FL/Fl_Scrollbar.H fl_overlay.o: ../FL/Fl_Slider.H fl_overlay.o: ../FL/Fl_Text_Buffer.H fl_overlay.o: ../FL/Fl_Text_Display.H fl_overlay.o: ../FL/Fl_Text_Editor.H fl_overlay.o: ../FL/fl_types.h fl_overlay.o: ../FL/fl_utf8.h fl_overlay.o: ../FL/Fl_Valuator.H fl_overlay.o: ../FL/Fl_Widget.H fl_overlay.o: ../FL/platform.H fl_overlay.o: ../FL/platform_types.h fl_overlay.o: ../FL/x11.H fl_overlay.o: Fl_Screen_Driver.H Fl_Overlay_Window.o: ../FL/Enumerations.H Fl_Overlay_Window.o: ../FL/Fl.H Fl_Overlay_Window.o: ../FL/fl_attr.h Fl_Overlay_Window.o: ../FL/Fl_Bitmap.H Fl_Overlay_Window.o: ../FL/Fl_Cairo.H Fl_Overlay_Window.o: ../FL/fl_casts.H Fl_Overlay_Window.o: ../FL/fl_config.h Fl_Overlay_Window.o: ../FL/Fl_Double_Window.H Fl_Overlay_Window.o: ../FL/Fl_Export.H Fl_Overlay_Window.o: ../FL/Fl_Group.H Fl_Overlay_Window.o: ../FL/Fl_Image.H Fl_Overlay_Window.o: ../FL/Fl_Overlay_Window.H Fl_Overlay_Window.o: ../FL/fl_types.h Fl_Overlay_Window.o: ../FL/fl_utf8.h Fl_Overlay_Window.o: ../FL/Fl_Widget.H Fl_Overlay_Window.o: ../FL/Fl_Window.H Fl_Overlay_Window.o: ../FL/platform_types.h Fl_Overlay_Window.o: Fl_Window_Driver.H Fl_own_colormap.o: ../FL/Enumerations.H Fl_own_colormap.o: ../FL/Fl.H Fl_own_colormap.o: ../FL/fl_attr.h Fl_own_colormap.o: ../FL/Fl_Bitmap.H Fl_own_colormap.o: ../FL/Fl_Cairo.H Fl_own_colormap.o: ../FL/fl_casts.H Fl_own_colormap.o: ../FL/fl_config.h Fl_own_colormap.o: ../FL/Fl_Device.H Fl_own_colormap.o: ../FL/fl_draw.H Fl_own_colormap.o: ../FL/Fl_Export.H Fl_own_colormap.o: ../FL/Fl_Graphics_Driver.H Fl_own_colormap.o: ../FL/Fl_Group.H Fl_own_colormap.o: ../FL/Fl_Image.H Fl_own_colormap.o: ../FL/Fl_Pixmap.H Fl_own_colormap.o: ../FL/Fl_Plugin.H Fl_own_colormap.o: ../FL/Fl_Preferences.H Fl_own_colormap.o: ../FL/Fl_Rect.H Fl_own_colormap.o: ../FL/Fl_RGB_Image.H Fl_own_colormap.o: ../FL/Fl_Scrollbar.H Fl_own_colormap.o: ../FL/Fl_Slider.H Fl_own_colormap.o: ../FL/Fl_Text_Buffer.H Fl_own_colormap.o: ../FL/Fl_Text_Display.H Fl_own_colormap.o: ../FL/Fl_Text_Editor.H Fl_own_colormap.o: ../FL/fl_types.h Fl_own_colormap.o: ../FL/fl_utf8.h Fl_own_colormap.o: ../FL/Fl_Valuator.H Fl_own_colormap.o: ../FL/Fl_Widget.H Fl_own_colormap.o: ../FL/platform_types.h Fl_own_colormap.o: Fl_Screen_Driver.H fl_oxy.o: ../FL/Enumerations.H fl_oxy.o: ../FL/Fl.H fl_oxy.o: ../FL/fl_attr.h fl_oxy.o: ../FL/Fl_Cairo.H fl_oxy.o: ../FL/fl_casts.H fl_oxy.o: ../FL/fl_config.h fl_oxy.o: ../FL/fl_draw.H fl_oxy.o: ../FL/Fl_Export.H fl_oxy.o: ../FL/Fl_Rect.H fl_oxy.o: ../FL/fl_types.h fl_oxy.o: ../FL/fl_utf8.h fl_oxy.o: ../FL/Fl_Widget.H fl_oxy.o: ../FL/platform_types.h fl_oxy.o: fl_oxy.h Fl_Pack.o: ../FL/Enumerations.H Fl_Pack.o: ../FL/Fl.H Fl_Pack.o: ../FL/fl_attr.h Fl_Pack.o: ../FL/Fl_Cairo.H Fl_Pack.o: ../FL/fl_casts.H Fl_Pack.o: ../FL/fl_config.h Fl_Pack.o: ../FL/fl_draw.H Fl_Pack.o: ../FL/Fl_Export.H Fl_Pack.o: ../FL/Fl_Group.H Fl_Pack.o: ../FL/Fl_Pack.H Fl_Pack.o: ../FL/fl_types.h Fl_Pack.o: ../FL/fl_utf8.h Fl_Pack.o: ../FL/platform_types.h Fl_Paged_Device.o: ../FL/Enumerations.H Fl_Paged_Device.o: ../FL/Fl.H Fl_Paged_Device.o: ../FL/fl_attr.h Fl_Paged_Device.o: ../FL/Fl_Bitmap.H Fl_Paged_Device.o: ../FL/Fl_Cairo.H Fl_Paged_Device.o: ../FL/fl_casts.H Fl_Paged_Device.o: ../FL/fl_config.h Fl_Paged_Device.o: ../FL/Fl_Device.H Fl_Paged_Device.o: ../FL/fl_draw.H Fl_Paged_Device.o: ../FL/Fl_Export.H Fl_Paged_Device.o: ../FL/Fl_Group.H Fl_Paged_Device.o: ../FL/Fl_Image.H Fl_Paged_Device.o: ../FL/Fl_Paged_Device.H Fl_Paged_Device.o: ../FL/Fl_Plugin.H Fl_Paged_Device.o: ../FL/Fl_Preferences.H Fl_Paged_Device.o: ../FL/fl_types.h Fl_Paged_Device.o: ../FL/fl_utf8.h Fl_Paged_Device.o: ../FL/Fl_Widget.H Fl_Paged_Device.o: ../FL/Fl_Widget_Surface.H Fl_Paged_Device.o: ../FL/Fl_Window.H Fl_Paged_Device.o: ../FL/platform_types.h Fl_Pixmap.o: ../config.h Fl_Pixmap.o: ../FL/Enumerations.H Fl_Pixmap.o: ../FL/Fl.H Fl_Pixmap.o: ../FL/fl_attr.h Fl_Pixmap.o: ../FL/Fl_Cairo.H Fl_Pixmap.o: ../FL/fl_casts.H Fl_Pixmap.o: ../FL/fl_config.h Fl_Pixmap.o: ../FL/fl_draw.H Fl_Pixmap.o: ../FL/Fl_Export.H Fl_Pixmap.o: ../FL/Fl_Image.H Fl_Pixmap.o: ../FL/Fl_Menu_Item.H Fl_Pixmap.o: ../FL/Fl_Multi_Label.H Fl_Pixmap.o: ../FL/Fl_Pixmap.H Fl_Pixmap.o: ../FL/fl_string_functions.h Fl_Pixmap.o: ../FL/fl_types.h Fl_Pixmap.o: ../FL/fl_utf8.h Fl_Pixmap.o: ../FL/Fl_Widget.H Fl_Pixmap.o: ../FL/platform.H Fl_Pixmap.o: ../FL/platform_types.h Fl_Pixmap.o: ../FL/x11.H Fl_Pixmap.o: flstring.h fl_plastic.o: ../config.h fl_plastic.o: ../FL/Enumerations.H fl_plastic.o: ../FL/Fl.H fl_plastic.o: ../FL/fl_attr.h fl_plastic.o: ../FL/Fl_Cairo.H fl_plastic.o: ../FL/fl_casts.H fl_plastic.o: ../FL/fl_config.h fl_plastic.o: ../FL/fl_draw.H fl_plastic.o: ../FL/Fl_Export.H fl_plastic.o: ../FL/fl_string_functions.h fl_plastic.o: ../FL/fl_types.h fl_plastic.o: ../FL/fl_utf8.h fl_plastic.o: ../FL/platform_types.h fl_plastic.o: flstring.h Fl_PNG_Image.o: ../config.h Fl_PNG_Image.o: ../FL/Enumerations.H Fl_PNG_Image.o: ../FL/filename.H Fl_PNG_Image.o: ../FL/Fl.H Fl_PNG_Image.o: ../FL/fl_attr.h Fl_PNG_Image.o: ../FL/Fl_Cairo.H Fl_PNG_Image.o: ../FL/fl_casts.H Fl_PNG_Image.o: ../FL/fl_config.h Fl_PNG_Image.o: ../FL/Fl_Export.H Fl_PNG_Image.o: ../FL/Fl_Image.H Fl_PNG_Image.o: ../FL/Fl_PNG_Image.H Fl_PNG_Image.o: ../FL/Fl_Preferences.H Fl_PNG_Image.o: ../FL/Fl_Shared_Image.H Fl_PNG_Image.o: ../FL/fl_types.h Fl_PNG_Image.o: ../FL/fl_utf8.h Fl_PNG_Image.o: ../FL/platform_types.h Fl_PNG_Image.o: Fl_System_Driver.H Fl_PNM_Image.o: ../config.h Fl_PNM_Image.o: ../FL/Enumerations.H Fl_PNM_Image.o: ../FL/Fl.H Fl_PNM_Image.o: ../FL/fl_attr.h Fl_PNM_Image.o: ../FL/Fl_Cairo.H Fl_PNM_Image.o: ../FL/fl_casts.H Fl_PNM_Image.o: ../FL/fl_config.h Fl_PNM_Image.o: ../FL/Fl_Export.H Fl_PNM_Image.o: ../FL/Fl_Image.H Fl_PNM_Image.o: ../FL/Fl_PNM_Image.H Fl_PNM_Image.o: ../FL/fl_string_functions.h Fl_PNM_Image.o: ../FL/fl_types.h Fl_PNM_Image.o: ../FL/fl_utf8.h Fl_PNM_Image.o: ../FL/platform_types.h Fl_PNM_Image.o: flstring.h Fl_Positioner.o: ../FL/Enumerations.H Fl_Positioner.o: ../FL/Fl.H Fl_Positioner.o: ../FL/fl_attr.h Fl_Positioner.o: ../FL/Fl_Cairo.H Fl_Positioner.o: ../FL/fl_casts.H Fl_Positioner.o: ../FL/fl_config.h Fl_Positioner.o: ../FL/fl_draw.H Fl_Positioner.o: ../FL/Fl_Export.H Fl_Positioner.o: ../FL/Fl_Positioner.H Fl_Positioner.o: ../FL/fl_types.h Fl_Positioner.o: ../FL/fl_utf8.h Fl_Positioner.o: ../FL/Fl_Widget.H Fl_Positioner.o: ../FL/platform_types.h Fl_Preferences.o: ../config.h Fl_Preferences.o: ../FL/Enumerations.H Fl_Preferences.o: ../FL/filename.H Fl_Preferences.o: ../FL/Fl.H Fl_Preferences.o: ../FL/fl_attr.h Fl_Preferences.o: ../FL/Fl_Cairo.H Fl_Preferences.o: ../FL/fl_casts.H Fl_Preferences.o: ../FL/fl_config.h Fl_Preferences.o: ../FL/Fl_Export.H Fl_Preferences.o: ../FL/Fl_Plugin.H Fl_Preferences.o: ../FL/Fl_Preferences.H Fl_Preferences.o: ../FL/fl_string_functions.h Fl_Preferences.o: ../FL/fl_types.h Fl_Preferences.o: ../FL/fl_utf8.h Fl_Preferences.o: ../FL/platform_types.h Fl_Preferences.o: flstring.h Fl_Preferences.o: Fl_System_Driver.H Fl_Printer.o: ../config.h Fl_Printer.o: ../FL/Enumerations.H Fl_Printer.o: ../FL/Fl.H Fl_Printer.o: ../FL/fl_attr.h Fl_Printer.o: ../FL/Fl_Bitmap.H Fl_Printer.o: ../FL/Fl_Cairo.H Fl_Printer.o: ../FL/fl_casts.H Fl_Printer.o: ../FL/fl_config.h Fl_Printer.o: ../FL/Fl_Device.H Fl_Printer.o: ../FL/Fl_Export.H Fl_Printer.o: ../FL/Fl_Group.H Fl_Printer.o: ../FL/Fl_Image.H Fl_Printer.o: ../FL/Fl_Paged_Device.H Fl_Printer.o: ../FL/Fl_Plugin.H Fl_Printer.o: ../FL/Fl_Preferences.H Fl_Printer.o: ../FL/Fl_Printer.H Fl_Printer.o: ../FL/fl_types.h Fl_Printer.o: ../FL/fl_utf8.h Fl_Printer.o: ../FL/Fl_Widget.H Fl_Printer.o: ../FL/Fl_Widget_Surface.H Fl_Printer.o: ../FL/Fl_Window.H Fl_Printer.o: ../FL/platform_types.h Fl_Progress.o: ../FL/Enumerations.H Fl_Progress.o: ../FL/Fl.H Fl_Progress.o: ../FL/fl_attr.h Fl_Progress.o: ../FL/Fl_Cairo.H Fl_Progress.o: ../FL/fl_casts.H Fl_Progress.o: ../FL/fl_config.h Fl_Progress.o: ../FL/fl_draw.H Fl_Progress.o: ../FL/Fl_Export.H Fl_Progress.o: ../FL/Fl_Progress.H Fl_Progress.o: ../FL/fl_types.h Fl_Progress.o: ../FL/fl_utf8.h Fl_Progress.o: ../FL/Fl_Widget.H Fl_Progress.o: ../FL/platform_types.h fl_read_image.o: ../FL/Enumerations.H fl_read_image.o: ../FL/Fl.H fl_read_image.o: ../FL/fl_attr.h fl_read_image.o: ../FL/Fl_Bitmap.H fl_read_image.o: ../FL/Fl_Cairo.H fl_read_image.o: ../FL/fl_casts.H fl_read_image.o: ../FL/fl_config.h fl_read_image.o: ../FL/Fl_Device.H fl_read_image.o: ../FL/fl_draw.H fl_read_image.o: ../FL/Fl_Export.H fl_read_image.o: ../FL/Fl_Graphics_Driver.H fl_read_image.o: ../FL/Fl_Group.H fl_read_image.o: ../FL/Fl_Image.H fl_read_image.o: ../FL/Fl_Pixmap.H fl_read_image.o: ../FL/Fl_Plugin.H fl_read_image.o: ../FL/Fl_Preferences.H fl_read_image.o: ../FL/Fl_Rect.H fl_read_image.o: ../FL/Fl_RGB_Image.H fl_read_image.o: ../FL/Fl_Scrollbar.H fl_read_image.o: ../FL/Fl_Slider.H fl_read_image.o: ../FL/Fl_Text_Buffer.H fl_read_image.o: ../FL/Fl_Text_Display.H fl_read_image.o: ../FL/Fl_Text_Editor.H fl_read_image.o: ../FL/fl_types.h fl_read_image.o: ../FL/fl_utf8.h fl_read_image.o: ../FL/Fl_Valuator.H fl_read_image.o: ../FL/Fl_Widget.H fl_read_image.o: ../FL/platform.H fl_read_image.o: ../FL/platform_types.h fl_read_image.o: ../FL/x11.H fl_read_image.o: Fl_Screen_Driver.H fl_rect.o: ../FL/Enumerations.H fl_rect.o: ../FL/Fl.H fl_rect.o: ../FL/fl_attr.h fl_rect.o: ../FL/Fl_Bitmap.H fl_rect.o: ../FL/fl_config.h fl_rect.o: ../FL/Fl_Device.H fl_rect.o: ../FL/Fl_Export.H fl_rect.o: ../FL/Fl_Graphics_Driver.H fl_rect.o: ../FL/Fl_Image.H fl_rect.o: ../FL/Fl_Pixmap.H fl_rect.o: ../FL/Fl_Plugin.H fl_rect.o: ../FL/Fl_Preferences.H fl_rect.o: ../FL/Fl_RGB_Image.H fl_rect.o: ../FL/fl_types.h fl_rect.o: ../FL/Fl_Widget.H fl_rect.o: ../FL/platform.H fl_rect.o: ../FL/platform_types.h fl_rect.o: ../FL/x11.H Fl_Repeat_Button.o: ../FL/Enumerations.H Fl_Repeat_Button.o: ../FL/Fl.H Fl_Repeat_Button.o: ../FL/fl_attr.h Fl_Repeat_Button.o: ../FL/Fl_Button.H Fl_Repeat_Button.o: ../FL/Fl_Cairo.H Fl_Repeat_Button.o: ../FL/fl_casts.H Fl_Repeat_Button.o: ../FL/fl_config.h Fl_Repeat_Button.o: ../FL/Fl_Export.H Fl_Repeat_Button.o: ../FL/Fl_Repeat_Button.H Fl_Repeat_Button.o: ../FL/fl_types.h Fl_Repeat_Button.o: ../FL/fl_utf8.h Fl_Repeat_Button.o: ../FL/platform_types.h Fl_Return_Button.o: ../FL/Enumerations.H Fl_Return_Button.o: ../FL/Fl.H Fl_Return_Button.o: ../FL/fl_attr.h Fl_Return_Button.o: ../FL/Fl_Button.H Fl_Return_Button.o: ../FL/Fl_Cairo.H Fl_Return_Button.o: ../FL/fl_casts.H Fl_Return_Button.o: ../FL/fl_config.h Fl_Return_Button.o: ../FL/fl_draw.H Fl_Return_Button.o: ../FL/Fl_Export.H Fl_Return_Button.o: ../FL/Fl_Return_Button.H Fl_Return_Button.o: ../FL/fl_types.h Fl_Return_Button.o: ../FL/fl_utf8.h Fl_Return_Button.o: ../FL/platform_types.h Fl_Roller.o: ../FL/Enumerations.H Fl_Roller.o: ../FL/Fl.H Fl_Roller.o: ../FL/fl_attr.h Fl_Roller.o: ../FL/Fl_Cairo.H Fl_Roller.o: ../FL/fl_casts.H Fl_Roller.o: ../FL/fl_config.h Fl_Roller.o: ../FL/fl_draw.H Fl_Roller.o: ../FL/Fl_Export.H Fl_Roller.o: ../FL/Fl_Roller.H Fl_Roller.o: ../FL/fl_types.h Fl_Roller.o: ../FL/fl_utf8.h Fl_Roller.o: ../FL/Fl_Valuator.H Fl_Roller.o: ../FL/platform_types.h fl_rounded_box.o: ../FL/Enumerations.H fl_rounded_box.o: ../FL/Fl.H fl_rounded_box.o: ../FL/fl_attr.h fl_rounded_box.o: ../FL/Fl_Cairo.H fl_rounded_box.o: ../FL/fl_casts.H fl_rounded_box.o: ../FL/fl_config.h fl_rounded_box.o: ../FL/fl_draw.H fl_rounded_box.o: ../FL/Fl_Export.H fl_rounded_box.o: ../FL/fl_types.h fl_rounded_box.o: ../FL/fl_utf8.h fl_rounded_box.o: ../FL/platform_types.h fl_round_box.o: ../FL/Enumerations.H fl_round_box.o: ../FL/Fl.H fl_round_box.o: ../FL/fl_attr.h fl_round_box.o: ../FL/Fl_Cairo.H fl_round_box.o: ../FL/fl_casts.H fl_round_box.o: ../FL/fl_config.h fl_round_box.o: ../FL/fl_draw.H fl_round_box.o: ../FL/Fl_Export.H fl_round_box.o: ../FL/fl_types.h fl_round_box.o: ../FL/fl_utf8.h fl_round_box.o: ../FL/platform_types.h Fl_Round_Button.o: ../FL/Enumerations.H Fl_Round_Button.o: ../FL/Fl.H Fl_Round_Button.o: ../FL/fl_attr.h Fl_Round_Button.o: ../FL/Fl_Button.H Fl_Round_Button.o: ../FL/Fl_Cairo.H Fl_Round_Button.o: ../FL/fl_casts.H Fl_Round_Button.o: ../FL/fl_config.h Fl_Round_Button.o: ../FL/Fl_Export.H Fl_Round_Button.o: ../FL/Fl_Light_Button.H Fl_Round_Button.o: ../FL/Fl_Radio_Round_Button.H Fl_Round_Button.o: ../FL/Fl_Round_Button.H Fl_Round_Button.o: ../FL/fl_types.h Fl_Round_Button.o: ../FL/fl_utf8.h Fl_Round_Button.o: ../FL/platform_types.h Fl_Scheme.o: ../FL/Enumerations.H Fl_Scheme.o: ../FL/Fl.H Fl_Scheme.o: ../FL/fl_attr.h Fl_Scheme.o: ../FL/Fl_Bitmap.H Fl_Scheme.o: ../FL/Fl_Cairo.H Fl_Scheme.o: ../FL/fl_casts.H Fl_Scheme.o: ../FL/fl_config.h Fl_Scheme.o: ../FL/Fl_Export.H Fl_Scheme.o: ../FL/Fl_Group.H Fl_Scheme.o: ../FL/Fl_Image.H Fl_Scheme.o: ../FL/Fl_Scheme.H Fl_Scheme.o: ../FL/fl_string_functions.h Fl_Scheme.o: ../FL/fl_types.h Fl_Scheme.o: ../FL/fl_utf8.h Fl_Scheme.o: ../FL/Fl_Widget.H Fl_Scheme.o: ../FL/Fl_Window.H Fl_Scheme.o: ../FL/platform_types.h Fl_Scheme_Choice.o: ../FL/Enumerations.H Fl_Scheme_Choice.o: ../FL/Fl.H Fl_Scheme_Choice.o: ../FL/fl_attr.h Fl_Scheme_Choice.o: ../FL/Fl_Bitmap.H Fl_Scheme_Choice.o: ../FL/Fl_Cairo.H Fl_Scheme_Choice.o: ../FL/fl_casts.H Fl_Scheme_Choice.o: ../FL/Fl_Choice.H Fl_Scheme_Choice.o: ../FL/fl_config.h Fl_Scheme_Choice.o: ../FL/Fl_Export.H Fl_Scheme_Choice.o: ../FL/Fl_Group.H Fl_Scheme_Choice.o: ../FL/Fl_Image.H Fl_Scheme_Choice.o: ../FL/Fl_Menu_.H Fl_Scheme_Choice.o: ../FL/Fl_Menu_Item.H Fl_Scheme_Choice.o: ../FL/Fl_Multi_Label.H Fl_Scheme_Choice.o: ../FL/Fl_Scheme.H Fl_Scheme_Choice.o: ../FL/Fl_Scheme_Choice.H Fl_Scheme_Choice.o: ../FL/fl_types.h Fl_Scheme_Choice.o: ../FL/fl_utf8.h Fl_Scheme_Choice.o: ../FL/Fl_Widget.H Fl_Scheme_Choice.o: ../FL/Fl_Window.H Fl_Scheme_Choice.o: ../FL/platform_types.h Fl_Screen_Driver.o: ../FL/Enumerations.H Fl_Screen_Driver.o: ../FL/Fl.H Fl_Screen_Driver.o: ../FL/fl_attr.h Fl_Screen_Driver.o: ../FL/Fl_Bitmap.H Fl_Screen_Driver.o: ../FL/Fl_Box.H Fl_Screen_Driver.o: ../FL/Fl_Cairo.H Fl_Screen_Driver.o: ../FL/fl_casts.H Fl_Screen_Driver.o: ../FL/fl_config.h Fl_Screen_Driver.o: ../FL/Fl_Device.H Fl_Screen_Driver.o: ../FL/Fl_Double_Window.H Fl_Screen_Driver.o: ../FL/fl_draw.H Fl_Screen_Driver.o: ../FL/Fl_Export.H Fl_Screen_Driver.o: ../FL/Fl_Graphics_Driver.H Fl_Screen_Driver.o: ../FL/Fl_Group.H Fl_Screen_Driver.o: ../FL/Fl_Image.H Fl_Screen_Driver.o: ../FL/Fl_Image_Surface.H Fl_Screen_Driver.o: ../FL/Fl_Input.H Fl_Screen_Driver.o: ../FL/Fl_Input_.H Fl_Screen_Driver.o: ../FL/Fl_Overlay_Window.H Fl_Screen_Driver.o: ../FL/Fl_Pixmap.H Fl_Screen_Driver.o: ../FL/Fl_Plugin.H Fl_Screen_Driver.o: ../FL/Fl_Preferences.H Fl_Screen_Driver.o: ../FL/Fl_Rect.H Fl_Screen_Driver.o: ../FL/Fl_RGB_Image.H Fl_Screen_Driver.o: ../FL/Fl_Scrollbar.H Fl_Screen_Driver.o: ../FL/Fl_Shared_Image.H Fl_Screen_Driver.o: ../FL/Fl_Slider.H Fl_Screen_Driver.o: ../FL/Fl_Text_Buffer.H Fl_Screen_Driver.o: ../FL/Fl_Text_Display.H Fl_Screen_Driver.o: ../FL/Fl_Text_Editor.H Fl_Screen_Driver.o: ../FL/Fl_Tooltip.H Fl_Screen_Driver.o: ../FL/fl_types.h Fl_Screen_Driver.o: ../FL/fl_utf8.h Fl_Screen_Driver.o: ../FL/Fl_Valuator.H Fl_Screen_Driver.o: ../FL/Fl_Widget.H Fl_Screen_Driver.o: ../FL/Fl_Widget_Surface.H Fl_Screen_Driver.o: ../FL/Fl_Window.H Fl_Screen_Driver.o: ../FL/platform.H Fl_Screen_Driver.o: ../FL/platform_types.h Fl_Screen_Driver.o: ../FL/x11.H Fl_Screen_Driver.o: Fl_Screen_Driver.H Fl_Screen_Driver.o: Fl_Window_Driver.H Fl_Scroll.o: ../FL/Enumerations.H Fl_Scroll.o: ../FL/Fl.H Fl_Scroll.o: ../FL/fl_attr.h Fl_Scroll.o: ../FL/Fl_Cairo.H Fl_Scroll.o: ../FL/fl_casts.H Fl_Scroll.o: ../FL/fl_config.h Fl_Scroll.o: ../FL/fl_draw.H Fl_Scroll.o: ../FL/Fl_Export.H Fl_Scroll.o: ../FL/Fl_Group.H Fl_Scroll.o: ../FL/Fl_Image.H Fl_Scroll.o: ../FL/Fl_Scroll.H Fl_Scroll.o: ../FL/Fl_Scrollbar.H Fl_Scroll.o: ../FL/Fl_Slider.H Fl_Scroll.o: ../FL/Fl_Tiled_Image.H Fl_Scroll.o: ../FL/fl_types.h Fl_Scroll.o: ../FL/fl_utf8.h Fl_Scroll.o: ../FL/Fl_Valuator.H Fl_Scroll.o: ../FL/Fl_Widget.H Fl_Scroll.o: ../FL/platform_types.h Fl_Scrollbar.o: ../config.h Fl_Scrollbar.o: ../FL/Enumerations.H Fl_Scrollbar.o: ../FL/Fl.H Fl_Scrollbar.o: ../FL/fl_attr.h Fl_Scrollbar.o: ../FL/Fl_Cairo.H Fl_Scrollbar.o: ../FL/fl_casts.H Fl_Scrollbar.o: ../FL/fl_config.h Fl_Scrollbar.o: ../FL/fl_draw.H Fl_Scrollbar.o: ../FL/Fl_Export.H Fl_Scrollbar.o: ../FL/Fl_Scrollbar.H Fl_Scrollbar.o: ../FL/Fl_Slider.H Fl_Scrollbar.o: ../FL/fl_string_functions.h Fl_Scrollbar.o: ../FL/fl_types.h Fl_Scrollbar.o: ../FL/fl_utf8.h Fl_Scrollbar.o: ../FL/Fl_Valuator.H Fl_Scrollbar.o: ../FL/platform_types.h Fl_Scrollbar.o: flstring.h fl_scroll_area.o: ../FL/Enumerations.H fl_scroll_area.o: ../FL/Fl.H fl_scroll_area.o: ../FL/fl_attr.h fl_scroll_area.o: ../FL/Fl_Bitmap.H fl_scroll_area.o: ../FL/Fl_Cairo.H fl_scroll_area.o: ../FL/fl_casts.H fl_scroll_area.o: ../FL/fl_config.h fl_scroll_area.o: ../FL/Fl_Double_Window.H fl_scroll_area.o: ../FL/fl_draw.H fl_scroll_area.o: ../FL/Fl_Export.H fl_scroll_area.o: ../FL/Fl_Group.H fl_scroll_area.o: ../FL/Fl_Image.H fl_scroll_area.o: ../FL/Fl_Overlay_Window.H fl_scroll_area.o: ../FL/fl_types.h fl_scroll_area.o: ../FL/fl_utf8.h fl_scroll_area.o: ../FL/Fl_Widget.H fl_scroll_area.o: ../FL/Fl_Window.H fl_scroll_area.o: ../FL/platform_types.h fl_scroll_area.o: Fl_Window_Driver.H fl_set_font.o: ../config.h fl_set_font.o: ../FL/Enumerations.H fl_set_font.o: ../FL/Fl.H fl_set_font.o: ../FL/fl_attr.h fl_set_font.o: ../FL/Fl_Bitmap.H fl_set_font.o: ../FL/Fl_Cairo.H fl_set_font.o: ../FL/fl_casts.H fl_set_font.o: ../FL/fl_config.h fl_set_font.o: ../FL/Fl_Device.H fl_set_font.o: ../FL/fl_draw.H fl_set_font.o: ../FL/Fl_Export.H fl_set_font.o: ../FL/Fl_Graphics_Driver.H fl_set_font.o: ../FL/Fl_Group.H fl_set_font.o: ../FL/Fl_Image.H fl_set_font.o: ../FL/Fl_Pixmap.H fl_set_font.o: ../FL/Fl_Plugin.H fl_set_font.o: ../FL/Fl_Preferences.H fl_set_font.o: ../FL/Fl_Rect.H fl_set_font.o: ../FL/Fl_RGB_Image.H fl_set_font.o: ../FL/Fl_Scrollbar.H fl_set_font.o: ../FL/Fl_Slider.H fl_set_font.o: ../FL/fl_string_functions.h fl_set_font.o: ../FL/Fl_Text_Buffer.H fl_set_font.o: ../FL/Fl_Text_Display.H fl_set_font.o: ../FL/Fl_Text_Editor.H fl_set_font.o: ../FL/fl_types.h fl_set_font.o: ../FL/fl_utf8.h fl_set_font.o: ../FL/Fl_Valuator.H fl_set_font.o: ../FL/Fl_Widget.H fl_set_font.o: ../FL/platform.H fl_set_font.o: ../FL/platform_types.h fl_set_font.o: ../FL/x11.H fl_set_font.o: flstring.h fl_set_font.o: Fl_Screen_Driver.H fl_shadow_box.o: ../FL/Enumerations.H fl_shadow_box.o: ../FL/Fl.H fl_shadow_box.o: ../FL/fl_attr.h fl_shadow_box.o: ../FL/Fl_Cairo.H fl_shadow_box.o: ../FL/fl_casts.H fl_shadow_box.o: ../FL/fl_config.h fl_shadow_box.o: ../FL/fl_draw.H fl_shadow_box.o: ../FL/Fl_Export.H fl_shadow_box.o: ../FL/fl_types.h fl_shadow_box.o: ../FL/fl_utf8.h fl_shadow_box.o: ../FL/platform_types.h Fl_Shared_Image.o: ../config.h Fl_Shared_Image.o: ../FL/Enumerations.H Fl_Shared_Image.o: ../FL/Fl.H Fl_Shared_Image.o: ../FL/fl_attr.h Fl_Shared_Image.o: ../FL/Fl_Bitmap.H Fl_Shared_Image.o: ../FL/Fl_Cairo.H Fl_Shared_Image.o: ../FL/fl_casts.H Fl_Shared_Image.o: ../FL/fl_config.h Fl_Shared_Image.o: ../FL/fl_draw.H Fl_Shared_Image.o: ../FL/Fl_Export.H Fl_Shared_Image.o: ../FL/Fl_Image.H Fl_Shared_Image.o: ../FL/Fl_Pixmap.H Fl_Shared_Image.o: ../FL/Fl_Preferences.H Fl_Shared_Image.o: ../FL/Fl_Shared_Image.H Fl_Shared_Image.o: ../FL/fl_string_functions.h Fl_Shared_Image.o: ../FL/fl_types.h Fl_Shared_Image.o: ../FL/fl_utf8.h Fl_Shared_Image.o: ../FL/Fl_Widget.H Fl_Shared_Image.o: ../FL/Fl_XBM_Image.H Fl_Shared_Image.o: ../FL/Fl_XPM_Image.H Fl_Shared_Image.o: ../FL/platform_types.h Fl_Shared_Image.o: flstring.h fl_shortcut.o: ../config.h fl_shortcut.o: ../FL/Enumerations.H fl_shortcut.o: ../FL/filename.H fl_shortcut.o: ../FL/Fl.H fl_shortcut.o: ../FL/fl_attr.h fl_shortcut.o: ../FL/Fl_Bitmap.H fl_shortcut.o: ../FL/Fl_Button.H fl_shortcut.o: ../FL/Fl_Cairo.H fl_shortcut.o: ../FL/fl_casts.H fl_shortcut.o: ../FL/fl_config.h fl_shortcut.o: ../FL/Fl_Device.H fl_shortcut.o: ../FL/fl_draw.H fl_shortcut.o: ../FL/Fl_Export.H fl_shortcut.o: ../FL/Fl_Graphics_Driver.H fl_shortcut.o: ../FL/Fl_Group.H fl_shortcut.o: ../FL/Fl_Image.H fl_shortcut.o: ../FL/Fl_Pixmap.H fl_shortcut.o: ../FL/Fl_Plugin.H fl_shortcut.o: ../FL/Fl_Preferences.H fl_shortcut.o: ../FL/Fl_Rect.H fl_shortcut.o: ../FL/Fl_RGB_Image.H fl_shortcut.o: ../FL/Fl_Scrollbar.H fl_shortcut.o: ../FL/Fl_Slider.H fl_shortcut.o: ../FL/fl_string_functions.h fl_shortcut.o: ../FL/Fl_Text_Buffer.H fl_shortcut.o: ../FL/Fl_Text_Display.H fl_shortcut.o: ../FL/Fl_Text_Editor.H fl_shortcut.o: ../FL/fl_types.h fl_shortcut.o: ../FL/fl_utf8.h fl_shortcut.o: ../FL/Fl_Valuator.H fl_shortcut.o: ../FL/Fl_Widget.H fl_shortcut.o: ../FL/platform_types.h fl_shortcut.o: flstring.h fl_shortcut.o: Fl_Screen_Driver.H fl_shortcut.o: Fl_System_Driver.H Fl_Shortcut_Button.o: ../config.h Fl_Shortcut_Button.o: ../FL/Enumerations.H Fl_Shortcut_Button.o: ../FL/filename.H Fl_Shortcut_Button.o: ../FL/Fl.H Fl_Shortcut_Button.o: ../FL/fl_attr.h Fl_Shortcut_Button.o: ../FL/Fl_Button.H Fl_Shortcut_Button.o: ../FL/Fl_Cairo.H Fl_Shortcut_Button.o: ../FL/fl_casts.H Fl_Shortcut_Button.o: ../FL/fl_config.h Fl_Shortcut_Button.o: ../FL/fl_draw.H Fl_Shortcut_Button.o: ../FL/Fl_Export.H Fl_Shortcut_Button.o: ../FL/Fl_Preferences.H Fl_Shortcut_Button.o: ../FL/Fl_Shortcut_Button.H Fl_Shortcut_Button.o: ../FL/fl_string_functions.h Fl_Shortcut_Button.o: ../FL/fl_types.h Fl_Shortcut_Button.o: ../FL/fl_utf8.h Fl_Shortcut_Button.o: ../FL/Fl_Widget.H Fl_Shortcut_Button.o: ../FL/platform_types.h Fl_Shortcut_Button.o: flstring.h Fl_Shortcut_Button.o: Fl_System_Driver.H fl_show_colormap.o: ../config.h fl_show_colormap.o: ../FL/Enumerations.H fl_show_colormap.o: ../FL/Fl.H fl_show_colormap.o: ../FL/fl_attr.h fl_show_colormap.o: ../FL/Fl_Cairo.H fl_show_colormap.o: ../FL/fl_casts.H fl_show_colormap.o: ../FL/fl_config.h fl_show_colormap.o: ../FL/fl_draw.H fl_show_colormap.o: ../FL/Fl_Export.H fl_show_colormap.o: ../FL/fl_show_colormap.H fl_show_colormap.o: ../FL/Fl_Single_Window.H fl_show_colormap.o: ../FL/fl_types.h fl_show_colormap.o: ../FL/fl_utf8.h fl_show_colormap.o: ../FL/Fl_Window.H fl_show_colormap.o: ../FL/platform_types.h Fl_Single_Window.o: ../FL/Fl_Single_Window.H Fl_Single_Window.o: ../FL/Fl_Window.H Fl_Slider.o: ../config.h Fl_Slider.o: ../FL/Enumerations.H Fl_Slider.o: ../FL/Fl.H Fl_Slider.o: ../FL/fl_attr.h Fl_Slider.o: ../FL/Fl_Cairo.H Fl_Slider.o: ../FL/fl_casts.H Fl_Slider.o: ../FL/fl_config.h Fl_Slider.o: ../FL/fl_draw.H Fl_Slider.o: ../FL/Fl_Export.H Fl_Slider.o: ../FL/Fl_Fill_Slider.H Fl_Slider.o: ../FL/Fl_Hor_Fill_Slider.H Fl_Slider.o: ../FL/Fl_Hor_Nice_Slider.H Fl_Slider.o: ../FL/Fl_Hor_Slider.H Fl_Slider.o: ../FL/Fl_Nice_Slider.H Fl_Slider.o: ../FL/Fl_Slider.H Fl_Slider.o: ../FL/fl_string_functions.h Fl_Slider.o: ../FL/fl_types.h Fl_Slider.o: ../FL/fl_utf8.h Fl_Slider.o: ../FL/Fl_Valuator.H Fl_Slider.o: ../FL/platform_types.h Fl_Slider.o: flstring.h Fl_Spinner.o: ../FL/Enumerations.H Fl_Spinner.o: ../FL/Fl.H Fl_Spinner.o: ../FL/Fl_Button.H Fl_Spinner.o: ../FL/fl_draw.H Fl_Spinner.o: ../FL/Fl_Group.H Fl_Spinner.o: ../FL/Fl_Input.H Fl_Spinner.o: ../FL/Fl_Input_.H Fl_Spinner.o: ../FL/Fl_Rect.H Fl_Spinner.o: ../FL/Fl_Repeat_Button.H Fl_Spinner.o: ../FL/Fl_Spinner.H Fl_Spinner.o: ../FL/Fl_Widget.H Fl_String.o: ../FL/Fl_Export.H Fl_String.o: Fl_String.H fl_string_functions.o: ../FL/Enumerations.H fl_string_functions.o: ../FL/filename.H fl_string_functions.o: ../FL/Fl.H fl_string_functions.o: ../FL/fl_attr.h fl_string_functions.o: ../FL/Fl_Cairo.H fl_string_functions.o: ../FL/fl_casts.H fl_string_functions.o: ../FL/fl_config.h fl_string_functions.o: ../FL/Fl_Export.H fl_string_functions.o: ../FL/Fl_Preferences.H fl_string_functions.o: ../FL/fl_string_functions.h fl_string_functions.o: ../FL/fl_types.h fl_string_functions.o: ../FL/fl_utf8.h fl_string_functions.o: ../FL/platform_types.h fl_string_functions.o: Fl_System_Driver.H Fl_SVG_Image.o: ../config.h Fl_SVG_Image.o: ../FL/Enumerations.H Fl_SVG_Image.o: ../FL/filename.H Fl_SVG_Image.o: ../FL/Fl.H Fl_SVG_Image.o: ../FL/fl_attr.h Fl_SVG_Image.o: ../FL/Fl_Bitmap.H Fl_SVG_Image.o: ../FL/Fl_Cairo.H Fl_SVG_Image.o: ../FL/fl_casts.H Fl_SVG_Image.o: ../FL/fl_config.h Fl_SVG_Image.o: ../FL/Fl_Device.H Fl_SVG_Image.o: ../FL/fl_draw.H Fl_SVG_Image.o: ../FL/Fl_Export.H Fl_SVG_Image.o: ../FL/Fl_Graphics_Driver.H Fl_SVG_Image.o: ../FL/Fl_Group.H Fl_SVG_Image.o: ../FL/Fl_Image.H Fl_SVG_Image.o: ../FL/Fl_Pixmap.H Fl_SVG_Image.o: ../FL/Fl_Plugin.H Fl_SVG_Image.o: ../FL/Fl_Preferences.H Fl_SVG_Image.o: ../FL/Fl_Rect.H Fl_SVG_Image.o: ../FL/Fl_RGB_Image.H Fl_SVG_Image.o: ../FL/Fl_Scrollbar.H Fl_SVG_Image.o: ../FL/Fl_Shared_Image.H Fl_SVG_Image.o: ../FL/Fl_Slider.H Fl_SVG_Image.o: ../FL/fl_string_functions.h Fl_SVG_Image.o: ../FL/Fl_SVG_Image.H Fl_SVG_Image.o: ../FL/Fl_Text_Buffer.H Fl_SVG_Image.o: ../FL/Fl_Text_Display.H Fl_SVG_Image.o: ../FL/Fl_Text_Editor.H Fl_SVG_Image.o: ../FL/fl_types.h Fl_SVG_Image.o: ../FL/fl_utf8.h Fl_SVG_Image.o: ../FL/Fl_Valuator.H Fl_SVG_Image.o: ../FL/Fl_Widget.H Fl_SVG_Image.o: ../FL/platform_types.h Fl_SVG_Image.o: ../nanosvg/nanosvg.h Fl_SVG_Image.o: ../nanosvg/nanosvgrast.h Fl_SVG_Image.o: Fl_Screen_Driver.H Fl_SVG_Image.o: Fl_System_Driver.H fl_symbols.o: ../config.h fl_symbols.o: ../FL/Enumerations.H fl_symbols.o: ../FL/Fl.H fl_symbols.o: ../FL/fl_attr.h fl_symbols.o: ../FL/Fl_Cairo.H fl_symbols.o: ../FL/fl_casts.H fl_symbols.o: ../FL/fl_config.h fl_symbols.o: ../FL/fl_draw.H fl_symbols.o: ../FL/Fl_Export.H fl_symbols.o: ../FL/fl_string_functions.h fl_symbols.o: ../FL/fl_types.h fl_symbols.o: ../FL/fl_utf8.h fl_symbols.o: ../FL/math.h fl_symbols.o: ../FL/platform_types.h fl_symbols.o: flstring.h Fl_System_Driver.o: ../config.h Fl_System_Driver.o: ../FL/Enumerations.H Fl_System_Driver.o: ../FL/filename.H Fl_System_Driver.o: ../FL/Fl.H Fl_System_Driver.o: ../FL/fl_attr.h Fl_System_Driver.o: ../FL/Fl_Cairo.H Fl_System_Driver.o: ../FL/fl_casts.H Fl_System_Driver.o: ../FL/fl_config.h Fl_System_Driver.o: ../FL/Fl_Export.H Fl_System_Driver.o: ../FL/Fl_File_Icon.H Fl_System_Driver.o: ../FL/Fl_Preferences.H Fl_System_Driver.o: ../FL/fl_string_functions.h Fl_System_Driver.o: ../FL/fl_types.h Fl_System_Driver.o: ../FL/fl_utf8.h Fl_System_Driver.o: ../FL/platform_types.h Fl_System_Driver.o: flstring.h Fl_System_Driver.o: Fl_System_Driver.H Fl_System_Driver.o: Fl_Timeout.h Fl_Sys_Menu_Bar.o: ../config.h Fl_Sys_Menu_Bar.o: ../FL/Enumerations.H Fl_Sys_Menu_Bar.o: ../FL/filename.H Fl_Sys_Menu_Bar.o: ../FL/Fl.H Fl_Sys_Menu_Bar.o: ../FL/fl_attr.h Fl_Sys_Menu_Bar.o: ../FL/Fl_Cairo.H Fl_Sys_Menu_Bar.o: ../FL/fl_casts.H Fl_Sys_Menu_Bar.o: ../FL/fl_config.h Fl_Sys_Menu_Bar.o: ../FL/Fl_Export.H Fl_Sys_Menu_Bar.o: ../FL/Fl_Image.H Fl_Sys_Menu_Bar.o: ../FL/Fl_Menu_.H Fl_Sys_Menu_Bar.o: ../FL/Fl_Menu_Bar.H Fl_Sys_Menu_Bar.o: ../FL/Fl_Menu_Item.H Fl_Sys_Menu_Bar.o: ../FL/Fl_Multi_Label.H Fl_Sys_Menu_Bar.o: ../FL/Fl_Preferences.H Fl_Sys_Menu_Bar.o: ../FL/Fl_Sys_Menu_Bar.H Fl_Sys_Menu_Bar.o: ../FL/fl_types.h Fl_Sys_Menu_Bar.o: ../FL/fl_utf8.h Fl_Sys_Menu_Bar.o: ../FL/Fl_Widget.H Fl_Sys_Menu_Bar.o: ../FL/platform.H Fl_Sys_Menu_Bar.o: ../FL/platform_types.h Fl_Sys_Menu_Bar.o: ../FL/x11.H Fl_Sys_Menu_Bar.o: Fl_System_Driver.H Fl_Sys_Menu_Bar.o: Fl_Sys_Menu_Bar_Driver.H Fl_Table.o: ../FL/Enumerations.H Fl_Table.o: ../FL/Fl.H Fl_Table.o: ../FL/fl_attr.h Fl_Table.o: ../FL/Fl_Cairo.H Fl_Table.o: ../FL/fl_casts.H Fl_Table.o: ../FL/fl_config.h Fl_Table.o: ../FL/fl_draw.H Fl_Table.o: ../FL/Fl_Export.H Fl_Table.o: ../FL/Fl_Group.H Fl_Table.o: ../FL/Fl_Scroll.H Fl_Table.o: ../FL/Fl_Scrollbar.H Fl_Table.o: ../FL/Fl_Slider.H Fl_Table.o: ../FL/Fl_Table.H Fl_Table.o: ../FL/fl_types.h Fl_Table.o: ../FL/fl_utf8.h Fl_Table.o: ../FL/Fl_Valuator.H Fl_Table.o: ../FL/Fl_Widget.H Fl_Table.o: ../FL/platform_types.h Fl_Table.o: Fl_Int_Vector.H Fl_Table_Row.o: ../FL/Enumerations.H Fl_Table_Row.o: ../FL/Fl.H Fl_Table_Row.o: ../FL/fl_attr.h Fl_Table_Row.o: ../FL/Fl_Cairo.H Fl_Table_Row.o: ../FL/fl_casts.H Fl_Table_Row.o: ../FL/fl_config.h Fl_Table_Row.o: ../FL/fl_draw.H Fl_Table_Row.o: ../FL/Fl_Export.H Fl_Table_Row.o: ../FL/Fl_Group.H Fl_Table_Row.o: ../FL/Fl_Scroll.H Fl_Table_Row.o: ../FL/Fl_Scrollbar.H Fl_Table_Row.o: ../FL/Fl_Slider.H Fl_Table_Row.o: ../FL/Fl_Table.H Fl_Table_Row.o: ../FL/Fl_Table_Row.H Fl_Table_Row.o: ../FL/fl_types.h Fl_Table_Row.o: ../FL/fl_utf8.h Fl_Table_Row.o: ../FL/Fl_Valuator.H Fl_Table_Row.o: ../FL/Fl_Widget.H Fl_Table_Row.o: ../FL/platform_types.h Fl_Tabs.o: ../FL/Enumerations.H Fl_Tabs.o: ../FL/Fl.H Fl_Tabs.o: ../FL/fl_attr.h Fl_Tabs.o: ../FL/Fl_Bitmap.H Fl_Tabs.o: ../FL/Fl_Cairo.H Fl_Tabs.o: ../FL/fl_casts.H Fl_Tabs.o: ../FL/fl_config.h Fl_Tabs.o: ../FL/fl_draw.H Fl_Tabs.o: ../FL/Fl_Export.H Fl_Tabs.o: ../FL/Fl_Group.H Fl_Tabs.o: ../FL/Fl_Image.H Fl_Tabs.o: ../FL/Fl_Menu_Item.H Fl_Tabs.o: ../FL/Fl_Multi_Label.H Fl_Tabs.o: ../FL/Fl_Tabs.H Fl_Tabs.o: ../FL/Fl_Tooltip.H Fl_Tabs.o: ../FL/fl_types.h Fl_Tabs.o: ../FL/fl_utf8.h Fl_Tabs.o: ../FL/Fl_Widget.H Fl_Tabs.o: ../FL/Fl_Window.H Fl_Tabs.o: ../FL/platform_types.h Fl_Terminal.o: ../FL/Enumerations.H Fl_Terminal.o: ../FL/Fl.H Fl_Terminal.o: ../FL/fl_attr.h Fl_Terminal.o: ../FL/Fl_Bitmap.H Fl_Terminal.o: ../FL/Fl_Cairo.H Fl_Terminal.o: ../FL/fl_casts.H Fl_Terminal.o: ../FL/fl_config.h Fl_Terminal.o: ../FL/fl_draw.H Fl_Terminal.o: ../FL/Fl_Export.H Fl_Terminal.o: ../FL/Fl_Group.H Fl_Terminal.o: ../FL/Fl_Image.H Fl_Terminal.o: ../FL/Fl_Rect.H Fl_Terminal.o: ../FL/Fl_Scrollbar.H Fl_Terminal.o: ../FL/Fl_Slider.H Fl_Terminal.o: ../FL/fl_string_functions.h Fl_Terminal.o: ../FL/Fl_Terminal.H Fl_Terminal.o: ../FL/fl_types.h Fl_Terminal.o: ../FL/fl_utf8.h Fl_Terminal.o: ../FL/Fl_Valuator.H Fl_Terminal.o: ../FL/Fl_Widget.H Fl_Terminal.o: ../FL/Fl_Window.H Fl_Terminal.o: ../FL/platform_types.h Fl_Terminal.o: Fl_String.H Fl_Text_Buffer.o: ../config.h Fl_Text_Buffer.o: ../FL/Enumerations.H Fl_Text_Buffer.o: ../FL/Fl.H Fl_Text_Buffer.o: ../FL/fl_ask.H Fl_Text_Buffer.o: ../FL/fl_attr.h Fl_Text_Buffer.o: ../FL/Fl_Cairo.H Fl_Text_Buffer.o: ../FL/fl_casts.H Fl_Text_Buffer.o: ../FL/fl_config.h Fl_Text_Buffer.o: ../FL/Fl_Export.H Fl_Text_Buffer.o: ../FL/fl_string_functions.h Fl_Text_Buffer.o: ../FL/Fl_Text_Buffer.H Fl_Text_Buffer.o: ../FL/fl_types.h Fl_Text_Buffer.o: ../FL/fl_utf8.h Fl_Text_Buffer.o: ../FL/platform_types.h Fl_Text_Buffer.o: flstring.h Fl_Text_Display.o: ../config.h Fl_Text_Display.o: ../FL/Enumerations.H Fl_Text_Display.o: ../FL/Fl.H Fl_Text_Display.o: ../FL/fl_attr.h Fl_Text_Display.o: ../FL/Fl_Bitmap.H Fl_Text_Display.o: ../FL/Fl_Cairo.H Fl_Text_Display.o: ../FL/fl_casts.H Fl_Text_Display.o: ../FL/fl_config.h Fl_Text_Display.o: ../FL/Fl_Device.H Fl_Text_Display.o: ../FL/fl_draw.H Fl_Text_Display.o: ../FL/Fl_Export.H Fl_Text_Display.o: ../FL/Fl_Graphics_Driver.H Fl_Text_Display.o: ../FL/Fl_Group.H Fl_Text_Display.o: ../FL/Fl_Image.H Fl_Text_Display.o: ../FL/Fl_Input.H Fl_Text_Display.o: ../FL/Fl_Input_.H Fl_Text_Display.o: ../FL/Fl_Menu_Item.H Fl_Text_Display.o: ../FL/Fl_Multi_Label.H Fl_Text_Display.o: ../FL/Fl_Pixmap.H Fl_Text_Display.o: ../FL/Fl_Plugin.H Fl_Text_Display.o: ../FL/Fl_Preferences.H Fl_Text_Display.o: ../FL/Fl_Rect.H Fl_Text_Display.o: ../FL/Fl_RGB_Image.H Fl_Text_Display.o: ../FL/Fl_Scrollbar.H Fl_Text_Display.o: ../FL/Fl_Slider.H Fl_Text_Display.o: ../FL/fl_string_functions.h Fl_Text_Display.o: ../FL/Fl_Text_Buffer.H Fl_Text_Display.o: ../FL/Fl_Text_Display.H Fl_Text_Display.o: ../FL/Fl_Text_Editor.H Fl_Text_Display.o: ../FL/fl_types.h Fl_Text_Display.o: ../FL/fl_utf8.h Fl_Text_Display.o: ../FL/Fl_Valuator.H Fl_Text_Display.o: ../FL/Fl_Widget.H Fl_Text_Display.o: ../FL/Fl_Window.H Fl_Text_Display.o: ../FL/platform.H Fl_Text_Display.o: ../FL/platform_types.h Fl_Text_Display.o: ../FL/x11.H Fl_Text_Display.o: flstring.h Fl_Text_Display.o: Fl_Screen_Driver.H Fl_Text_Editor.o: ../config.h Fl_Text_Editor.o: ../FL/Enumerations.H Fl_Text_Editor.o: ../FL/Fl.H Fl_Text_Editor.o: ../FL/fl_ask.H Fl_Text_Editor.o: ../FL/fl_attr.h Fl_Text_Editor.o: ../FL/Fl_Bitmap.H Fl_Text_Editor.o: ../FL/Fl_Cairo.H Fl_Text_Editor.o: ../FL/fl_casts.H Fl_Text_Editor.o: ../FL/fl_config.h Fl_Text_Editor.o: ../FL/Fl_Device.H Fl_Text_Editor.o: ../FL/fl_draw.H Fl_Text_Editor.o: ../FL/Fl_Export.H Fl_Text_Editor.o: ../FL/Fl_Graphics_Driver.H Fl_Text_Editor.o: ../FL/Fl_Group.H Fl_Text_Editor.o: ../FL/Fl_Image.H Fl_Text_Editor.o: ../FL/Fl_Pixmap.H Fl_Text_Editor.o: ../FL/Fl_Plugin.H Fl_Text_Editor.o: ../FL/Fl_Preferences.H Fl_Text_Editor.o: ../FL/Fl_Rect.H Fl_Text_Editor.o: ../FL/Fl_RGB_Image.H Fl_Text_Editor.o: ../FL/Fl_Scrollbar.H Fl_Text_Editor.o: ../FL/Fl_Slider.H Fl_Text_Editor.o: ../FL/fl_string_functions.h Fl_Text_Editor.o: ../FL/Fl_Text_Buffer.H Fl_Text_Editor.o: ../FL/Fl_Text_Display.H Fl_Text_Editor.o: ../FL/Fl_Text_Editor.H Fl_Text_Editor.o: ../FL/fl_types.h Fl_Text_Editor.o: ../FL/fl_utf8.h Fl_Text_Editor.o: ../FL/Fl_Valuator.H Fl_Text_Editor.o: ../FL/Fl_Widget.H Fl_Text_Editor.o: ../FL/Fl_Window.H Fl_Text_Editor.o: ../FL/platform_types.h Fl_Text_Editor.o: flstring.h Fl_Text_Editor.o: Fl_Screen_Driver.H Fl_Tile.o: ../FL/Enumerations.H Fl_Tile.o: ../FL/Fl.H Fl_Tile.o: ../FL/fl_attr.h Fl_Tile.o: ../FL/Fl_Bitmap.H Fl_Tile.o: ../FL/Fl_Cairo.H Fl_Tile.o: ../FL/fl_casts.H Fl_Tile.o: ../FL/fl_config.h Fl_Tile.o: ../FL/Fl_Export.H Fl_Tile.o: ../FL/Fl_Group.H Fl_Tile.o: ../FL/Fl_Image.H Fl_Tile.o: ../FL/Fl_Rect.H Fl_Tile.o: ../FL/Fl_Tile.H Fl_Tile.o: ../FL/fl_types.h Fl_Tile.o: ../FL/fl_utf8.h Fl_Tile.o: ../FL/Fl_Widget.H Fl_Tile.o: ../FL/Fl_Window.H Fl_Tile.o: ../FL/platform_types.h Fl_Tiled_Image.o: ../FL/Enumerations.H Fl_Tiled_Image.o: ../FL/Fl.H Fl_Tiled_Image.o: ../FL/fl_attr.h Fl_Tiled_Image.o: ../FL/Fl_Bitmap.H Fl_Tiled_Image.o: ../FL/Fl_Cairo.H Fl_Tiled_Image.o: ../FL/fl_casts.H Fl_Tiled_Image.o: ../FL/fl_config.h Fl_Tiled_Image.o: ../FL/fl_draw.H Fl_Tiled_Image.o: ../FL/Fl_Export.H Fl_Tiled_Image.o: ../FL/Fl_Group.H Fl_Tiled_Image.o: ../FL/Fl_Image.H Fl_Tiled_Image.o: ../FL/Fl_Tiled_Image.H Fl_Tiled_Image.o: ../FL/fl_types.h Fl_Tiled_Image.o: ../FL/fl_utf8.h Fl_Tiled_Image.o: ../FL/Fl_Widget.H Fl_Tiled_Image.o: ../FL/Fl_Window.H Fl_Tiled_Image.o: ../FL/platform_types.h Fl_Timeout.o: ../config.h Fl_Timeout.o: ../FL/Enumerations.H Fl_Timeout.o: ../FL/filename.H Fl_Timeout.o: ../FL/Fl.H Fl_Timeout.o: ../FL/fl_attr.h Fl_Timeout.o: ../FL/Fl_Cairo.H Fl_Timeout.o: ../FL/fl_casts.H Fl_Timeout.o: ../FL/fl_config.h Fl_Timeout.o: ../FL/Fl_Export.H Fl_Timeout.o: ../FL/Fl_Preferences.H Fl_Timeout.o: ../FL/fl_types.h Fl_Timeout.o: ../FL/fl_utf8.h Fl_Timeout.o: ../FL/platform_types.h Fl_Timeout.o: Fl_System_Driver.H Fl_Timeout.o: Fl_Timeout.h Fl_Tooltip.o: ../FL/Enumerations.H Fl_Tooltip.o: ../FL/filename.H Fl_Tooltip.o: ../FL/Fl.H Fl_Tooltip.o: ../FL/fl_attr.h Fl_Tooltip.o: ../FL/Fl_Bitmap.H Fl_Tooltip.o: ../FL/Fl_Cairo.H Fl_Tooltip.o: ../FL/fl_casts.H Fl_Tooltip.o: ../FL/fl_config.h Fl_Tooltip.o: ../FL/Fl_Device.H Fl_Tooltip.o: ../FL/Fl_Double_Window.H Fl_Tooltip.o: ../FL/fl_draw.H Fl_Tooltip.o: ../FL/Fl_Export.H Fl_Tooltip.o: ../FL/Fl_Graphics_Driver.H Fl_Tooltip.o: ../FL/Fl_Group.H Fl_Tooltip.o: ../FL/Fl_Image.H Fl_Tooltip.o: ../FL/Fl_Menu_Window.H Fl_Tooltip.o: ../FL/Fl_Overlay_Window.H Fl_Tooltip.o: ../FL/Fl_Pixmap.H Fl_Tooltip.o: ../FL/Fl_Plugin.H Fl_Tooltip.o: ../FL/Fl_Preferences.H Fl_Tooltip.o: ../FL/Fl_Rect.H Fl_Tooltip.o: ../FL/Fl_RGB_Image.H Fl_Tooltip.o: ../FL/Fl_Scrollbar.H Fl_Tooltip.o: ../FL/Fl_Single_Window.H Fl_Tooltip.o: ../FL/Fl_Slider.H Fl_Tooltip.o: ../FL/fl_string_functions.h Fl_Tooltip.o: ../FL/Fl_Text_Buffer.H Fl_Tooltip.o: ../FL/Fl_Text_Display.H Fl_Tooltip.o: ../FL/Fl_Text_Editor.H Fl_Tooltip.o: ../FL/Fl_Tooltip.H Fl_Tooltip.o: ../FL/fl_types.h Fl_Tooltip.o: ../FL/fl_utf8.h Fl_Tooltip.o: ../FL/Fl_Valuator.H Fl_Tooltip.o: ../FL/Fl_Widget.H Fl_Tooltip.o: ../FL/Fl_Window.H Fl_Tooltip.o: ../FL/platform_types.h Fl_Tooltip.o: Fl_Screen_Driver.H Fl_Tooltip.o: Fl_System_Driver.H Fl_Tooltip.o: Fl_Window_Driver.H Fl_Tree.o: ../FL/Enumerations.H Fl_Tree.o: ../FL/Fl.H Fl_Tree.o: ../FL/fl_attr.h Fl_Tree.o: ../FL/Fl_Cairo.H Fl_Tree.o: ../FL/fl_casts.H Fl_Tree.o: ../FL/fl_config.h Fl_Tree.o: ../FL/fl_draw.H Fl_Tree.o: ../FL/Fl_Export.H Fl_Tree.o: ../FL/Fl_Group.H Fl_Tree.o: ../FL/Fl_Image.H Fl_Tree.o: ../FL/Fl_Preferences.H Fl_Tree.o: ../FL/Fl_Scrollbar.H Fl_Tree.o: ../FL/Fl_Slider.H Fl_Tree.o: ../FL/fl_string_functions.h Fl_Tree.o: ../FL/Fl_Tree.H Fl_Tree.o: ../FL/Fl_Tree_Item.H Fl_Tree.o: ../FL/Fl_Tree_Item_Array.H Fl_Tree.o: ../FL/Fl_Tree_Prefs.H Fl_Tree.o: ../FL/fl_types.h Fl_Tree.o: ../FL/fl_utf8.h Fl_Tree.o: ../FL/Fl_Valuator.H Fl_Tree.o: ../FL/Fl_Widget.H Fl_Tree.o: ../FL/platform_types.h Fl_Tree_Item.o: ../FL/Enumerations.H Fl_Tree_Item.o: ../FL/filename.H Fl_Tree_Item.o: ../FL/Fl.H Fl_Tree_Item.o: ../FL/fl_attr.h Fl_Tree_Item.o: ../FL/Fl_Cairo.H Fl_Tree_Item.o: ../FL/fl_casts.H Fl_Tree_Item.o: ../FL/fl_config.h Fl_Tree_Item.o: ../FL/fl_draw.H Fl_Tree_Item.o: ../FL/Fl_Export.H Fl_Tree_Item.o: ../FL/Fl_Group.H Fl_Tree_Item.o: ../FL/Fl_Image.H Fl_Tree_Item.o: ../FL/Fl_Preferences.H Fl_Tree_Item.o: ../FL/Fl_Scrollbar.H Fl_Tree_Item.o: ../FL/Fl_Slider.H Fl_Tree_Item.o: ../FL/fl_string_functions.h Fl_Tree_Item.o: ../FL/Fl_Tree.H Fl_Tree_Item.o: ../FL/Fl_Tree_Item.H Fl_Tree_Item.o: ../FL/Fl_Tree_Item_Array.H Fl_Tree_Item.o: ../FL/Fl_Tree_Prefs.H Fl_Tree_Item.o: ../FL/fl_types.h Fl_Tree_Item.o: ../FL/fl_utf8.h Fl_Tree_Item.o: ../FL/Fl_Valuator.H Fl_Tree_Item.o: ../FL/Fl_Widget.H Fl_Tree_Item.o: ../FL/platform_types.h Fl_Tree_Item.o: Fl_System_Driver.H Fl_Tree_Item_Array.o: ../FL/Enumerations.H Fl_Tree_Item_Array.o: ../FL/Fl.H Fl_Tree_Item_Array.o: ../FL/fl_attr.h Fl_Tree_Item_Array.o: ../FL/Fl_Cairo.H Fl_Tree_Item_Array.o: ../FL/fl_casts.H Fl_Tree_Item_Array.o: ../FL/fl_config.h Fl_Tree_Item_Array.o: ../FL/fl_draw.H Fl_Tree_Item_Array.o: ../FL/Fl_Export.H Fl_Tree_Item_Array.o: ../FL/Fl_Image.H Fl_Tree_Item_Array.o: ../FL/Fl_Tree_Item.H Fl_Tree_Item_Array.o: ../FL/Fl_Tree_Item_Array.H Fl_Tree_Item_Array.o: ../FL/Fl_Tree_Prefs.H Fl_Tree_Item_Array.o: ../FL/fl_types.h Fl_Tree_Item_Array.o: ../FL/fl_utf8.h Fl_Tree_Item_Array.o: ../FL/Fl_Widget.H Fl_Tree_Item_Array.o: ../FL/platform_types.h Fl_Tree_Prefs.o: ../config.h Fl_Tree_Prefs.o: ../FL/Enumerations.H Fl_Tree_Prefs.o: ../FL/filename.H Fl_Tree_Prefs.o: ../FL/Fl.H Fl_Tree_Prefs.o: ../FL/fl_attr.h Fl_Tree_Prefs.o: ../FL/Fl_Cairo.H Fl_Tree_Prefs.o: ../FL/fl_casts.H Fl_Tree_Prefs.o: ../FL/fl_config.h Fl_Tree_Prefs.o: ../FL/fl_draw.H Fl_Tree_Prefs.o: ../FL/Fl_Export.H Fl_Tree_Prefs.o: ../FL/Fl_Image.H Fl_Tree_Prefs.o: ../FL/Fl_Preferences.H Fl_Tree_Prefs.o: ../FL/Fl_Tree_Prefs.H Fl_Tree_Prefs.o: ../FL/fl_types.h Fl_Tree_Prefs.o: ../FL/fl_utf8.h Fl_Tree_Prefs.o: ../FL/Fl_Widget.H Fl_Tree_Prefs.o: ../FL/platform_types.h Fl_Tree_Prefs.o: Fl_System_Driver.H fl_utf8.o: ../FL/Enumerations.H fl_utf8.o: ../FL/filename.H fl_utf8.o: ../FL/Fl.H fl_utf8.o: ../FL/fl_attr.h fl_utf8.o: ../FL/Fl_Cairo.H fl_utf8.o: ../FL/fl_casts.H fl_utf8.o: ../FL/fl_config.h fl_utf8.o: ../FL/Fl_Export.H fl_utf8.o: ../FL/Fl_Preferences.H fl_utf8.o: ../FL/fl_types.h fl_utf8.o: ../FL/fl_utf8.h fl_utf8.o: ../FL/platform_types.h fl_utf8.o: Fl_System_Driver.H fl_utf8.o: utf8_internal.h fl_utf8.o: xutf8/mk_wcwidth.c Fl_Valuator.o: ../config.h Fl_Valuator.o: ../FL/Enumerations.H Fl_Valuator.o: ../FL/Fl.H Fl_Valuator.o: ../FL/fl_attr.h Fl_Valuator.o: ../FL/Fl_Cairo.H Fl_Valuator.o: ../FL/fl_casts.H Fl_Valuator.o: ../FL/fl_config.h Fl_Valuator.o: ../FL/Fl_Export.H Fl_Valuator.o: ../FL/fl_string_functions.h Fl_Valuator.o: ../FL/fl_types.h Fl_Valuator.o: ../FL/fl_utf8.h Fl_Valuator.o: ../FL/Fl_Valuator.H Fl_Valuator.o: ../FL/Fl_Widget.H Fl_Valuator.o: ../FL/math.h Fl_Valuator.o: ../FL/platform_types.h Fl_Valuator.o: flstring.h Fl_Value_Input.o: ../FL/Enumerations.H Fl_Value_Input.o: ../FL/Fl.H Fl_Value_Input.o: ../FL/fl_attr.h Fl_Value_Input.o: ../FL/Fl_Cairo.H Fl_Value_Input.o: ../FL/fl_casts.H Fl_Value_Input.o: ../FL/fl_config.h Fl_Value_Input.o: ../FL/Fl_Export.H Fl_Value_Input.o: ../FL/Fl_Group.H Fl_Value_Input.o: ../FL/Fl_Input.H Fl_Value_Input.o: ../FL/Fl_Input_.H Fl_Value_Input.o: ../FL/fl_types.h Fl_Value_Input.o: ../FL/fl_utf8.h Fl_Value_Input.o: ../FL/Fl_Valuator.H Fl_Value_Input.o: ../FL/Fl_Value_Input.H Fl_Value_Input.o: ../FL/math.h Fl_Value_Input.o: ../FL/platform_types.h Fl_Value_Output.o: ../FL/Enumerations.H Fl_Value_Output.o: ../FL/Fl.H Fl_Value_Output.o: ../FL/fl_attr.h Fl_Value_Output.o: ../FL/Fl_Cairo.H Fl_Value_Output.o: ../FL/fl_casts.H Fl_Value_Output.o: ../FL/fl_config.h Fl_Value_Output.o: ../FL/fl_draw.H Fl_Value_Output.o: ../FL/Fl_Export.H Fl_Value_Output.o: ../FL/fl_types.h Fl_Value_Output.o: ../FL/fl_utf8.h Fl_Value_Output.o: ../FL/Fl_Valuator.H Fl_Value_Output.o: ../FL/Fl_Value_Output.H Fl_Value_Output.o: ../FL/platform_types.h Fl_Value_Slider.o: ../FL/Enumerations.H Fl_Value_Slider.o: ../FL/Fl.H Fl_Value_Slider.o: ../FL/fl_attr.h Fl_Value_Slider.o: ../FL/Fl_Cairo.H Fl_Value_Slider.o: ../FL/fl_casts.H Fl_Value_Slider.o: ../FL/fl_config.h Fl_Value_Slider.o: ../FL/fl_draw.H Fl_Value_Slider.o: ../FL/Fl_Export.H Fl_Value_Slider.o: ../FL/Fl_Hor_Value_Slider.H Fl_Value_Slider.o: ../FL/Fl_Slider.H Fl_Value_Slider.o: ../FL/fl_types.h Fl_Value_Slider.o: ../FL/fl_utf8.h Fl_Value_Slider.o: ../FL/Fl_Valuator.H Fl_Value_Slider.o: ../FL/Fl_Value_Slider.H Fl_Value_Slider.o: ../FL/platform_types.h fl_vertex.o: ../FL/Enumerations.H fl_vertex.o: ../FL/Fl.H fl_vertex.o: ../FL/fl_attr.h fl_vertex.o: ../FL/Fl_Bitmap.H fl_vertex.o: ../FL/Fl_Cairo.H fl_vertex.o: ../FL/fl_casts.H fl_vertex.o: ../FL/fl_config.h fl_vertex.o: ../FL/Fl_Device.H fl_vertex.o: ../FL/Fl_Export.H fl_vertex.o: ../FL/Fl_Graphics_Driver.H fl_vertex.o: ../FL/Fl_Image.H fl_vertex.o: ../FL/Fl_Pixmap.H fl_vertex.o: ../FL/Fl_Plugin.H fl_vertex.o: ../FL/Fl_Preferences.H fl_vertex.o: ../FL/Fl_RGB_Image.H fl_vertex.o: ../FL/fl_types.h fl_vertex.o: ../FL/fl_utf8.h fl_vertex.o: ../FL/Fl_Widget.H fl_vertex.o: ../FL/math.h fl_vertex.o: ../FL/platform_types.h Fl_visual.o: ../FL/Enumerations.H Fl_visual.o: ../FL/Fl.H Fl_visual.o: ../FL/fl_attr.h Fl_visual.o: ../FL/Fl_Bitmap.H Fl_visual.o: ../FL/Fl_Cairo.H Fl_visual.o: ../FL/fl_casts.H Fl_visual.o: ../FL/fl_config.h Fl_visual.o: ../FL/Fl_Device.H Fl_visual.o: ../FL/fl_draw.H Fl_visual.o: ../FL/Fl_Export.H Fl_visual.o: ../FL/Fl_Graphics_Driver.H Fl_visual.o: ../FL/Fl_Group.H Fl_visual.o: ../FL/Fl_Image.H Fl_visual.o: ../FL/Fl_Pixmap.H Fl_visual.o: ../FL/Fl_Plugin.H Fl_visual.o: ../FL/Fl_Preferences.H Fl_visual.o: ../FL/Fl_Rect.H Fl_visual.o: ../FL/Fl_RGB_Image.H Fl_visual.o: ../FL/Fl_Scrollbar.H Fl_visual.o: ../FL/Fl_Slider.H Fl_visual.o: ../FL/Fl_Text_Buffer.H Fl_visual.o: ../FL/Fl_Text_Display.H Fl_visual.o: ../FL/Fl_Text_Editor.H Fl_visual.o: ../FL/fl_types.h Fl_visual.o: ../FL/fl_utf8.h Fl_visual.o: ../FL/Fl_Valuator.H Fl_visual.o: ../FL/Fl_Widget.H Fl_visual.o: ../FL/platform_types.h Fl_visual.o: Fl_Screen_Driver.H Fl_Widget.o: ../config.h Fl_Widget.o: ../FL/Enumerations.H Fl_Widget.o: ../FL/Fl.H Fl_Widget.o: ../FL/fl_attr.h Fl_Widget.o: ../FL/Fl_Cairo.H Fl_Widget.o: ../FL/fl_casts.H Fl_Widget.o: ../FL/fl_config.h Fl_Widget.o: ../FL/fl_draw.H Fl_Widget.o: ../FL/Fl_Export.H Fl_Widget.o: ../FL/Fl_Group.H Fl_Widget.o: ../FL/fl_string_functions.h Fl_Widget.o: ../FL/Fl_Tooltip.H Fl_Widget.o: ../FL/fl_types.h Fl_Widget.o: ../FL/fl_utf8.h Fl_Widget.o: ../FL/Fl_Widget.H Fl_Widget.o: ../FL/platform_types.h Fl_Widget.o: flstring.h Fl_Widget_Surface.o: ../FL/Enumerations.H Fl_Widget_Surface.o: ../FL/Fl.H Fl_Widget_Surface.o: ../FL/fl_attr.h Fl_Widget_Surface.o: ../FL/Fl_Bitmap.H Fl_Widget_Surface.o: ../FL/Fl_Cairo.H Fl_Widget_Surface.o: ../FL/fl_casts.H Fl_Widget_Surface.o: ../FL/fl_config.h Fl_Widget_Surface.o: ../FL/Fl_Device.H Fl_Widget_Surface.o: ../FL/Fl_Double_Window.H Fl_Widget_Surface.o: ../FL/fl_draw.H Fl_Widget_Surface.o: ../FL/Fl_Export.H Fl_Widget_Surface.o: ../FL/Fl_Graphics_Driver.H Fl_Widget_Surface.o: ../FL/Fl_Group.H Fl_Widget_Surface.o: ../FL/Fl_Image.H Fl_Widget_Surface.o: ../FL/Fl_Overlay_Window.H Fl_Widget_Surface.o: ../FL/Fl_Pixmap.H Fl_Widget_Surface.o: ../FL/Fl_Plugin.H Fl_Widget_Surface.o: ../FL/Fl_Preferences.H Fl_Widget_Surface.o: ../FL/Fl_Rect.H Fl_Widget_Surface.o: ../FL/Fl_RGB_Image.H Fl_Widget_Surface.o: ../FL/Fl_Scrollbar.H Fl_Widget_Surface.o: ../FL/Fl_Slider.H Fl_Widget_Surface.o: ../FL/Fl_Text_Buffer.H Fl_Widget_Surface.o: ../FL/Fl_Text_Display.H Fl_Widget_Surface.o: ../FL/Fl_Text_Editor.H Fl_Widget_Surface.o: ../FL/fl_types.h Fl_Widget_Surface.o: ../FL/fl_utf8.h Fl_Widget_Surface.o: ../FL/Fl_Valuator.H Fl_Widget_Surface.o: ../FL/Fl_Widget.H Fl_Widget_Surface.o: ../FL/Fl_Widget_Surface.H Fl_Widget_Surface.o: ../FL/Fl_Window.H Fl_Widget_Surface.o: ../FL/platform.H Fl_Widget_Surface.o: ../FL/platform_types.h Fl_Widget_Surface.o: ../FL/x11.H Fl_Widget_Surface.o: Fl_Screen_Driver.H Fl_Widget_Surface.o: Fl_Window_Driver.H Fl_Window.o: ../config.h Fl_Window.o: ../FL/Enumerations.H Fl_Window.o: ../FL/Fl.H Fl_Window.o: ../FL/fl_attr.h Fl_Window.o: ../FL/Fl_Bitmap.H Fl_Window.o: ../FL/Fl_Cairo.H Fl_Window.o: ../FL/fl_casts.H Fl_Window.o: ../FL/fl_config.h Fl_Window.o: ../FL/Fl_Device.H Fl_Window.o: ../FL/Fl_Double_Window.H Fl_Window.o: ../FL/fl_draw.H Fl_Window.o: ../FL/Fl_Export.H Fl_Window.o: ../FL/Fl_Graphics_Driver.H Fl_Window.o: ../FL/Fl_Group.H Fl_Window.o: ../FL/Fl_Image.H Fl_Window.o: ../FL/Fl_Overlay_Window.H Fl_Window.o: ../FL/Fl_Pixmap.H Fl_Window.o: ../FL/Fl_Plugin.H Fl_Window.o: ../FL/Fl_Preferences.H Fl_Window.o: ../FL/Fl_Rect.H Fl_Window.o: ../FL/Fl_RGB_Image.H Fl_Window.o: ../FL/Fl_Scrollbar.H Fl_Window.o: ../FL/Fl_Slider.H Fl_Window.o: ../FL/fl_string_functions.h Fl_Window.o: ../FL/Fl_Text_Buffer.H Fl_Window.o: ../FL/Fl_Text_Display.H Fl_Window.o: ../FL/Fl_Text_Editor.H Fl_Window.o: ../FL/Fl_Tooltip.H Fl_Window.o: ../FL/fl_types.h Fl_Window.o: ../FL/fl_utf8.h Fl_Window.o: ../FL/Fl_Valuator.H Fl_Window.o: ../FL/Fl_Widget.H Fl_Window.o: ../FL/Fl_Window.H Fl_Window.o: ../FL/platform.H Fl_Window.o: ../FL/platform_types.h Fl_Window.o: ../FL/x11.H Fl_Window.o: flstring.h Fl_Window.o: Fl_Screen_Driver.H Fl_Window.o: Fl_Window_Driver.H Fl_Window_Driver.o: ../FL/Enumerations.H Fl_Window_Driver.o: ../FL/Fl.H Fl_Window_Driver.o: ../FL/fl_attr.h Fl_Window_Driver.o: ../FL/Fl_Bitmap.H Fl_Window_Driver.o: ../FL/Fl_Cairo.H Fl_Window_Driver.o: ../FL/fl_casts.H Fl_Window_Driver.o: ../FL/fl_config.h Fl_Window_Driver.o: ../FL/Fl_Device.H Fl_Window_Driver.o: ../FL/Fl_Double_Window.H Fl_Window_Driver.o: ../FL/fl_draw.H Fl_Window_Driver.o: ../FL/Fl_Export.H Fl_Window_Driver.o: ../FL/Fl_Graphics_Driver.H Fl_Window_Driver.o: ../FL/Fl_Group.H Fl_Window_Driver.o: ../FL/Fl_Image.H Fl_Window_Driver.o: ../FL/Fl_Image_Surface.H Fl_Window_Driver.o: ../FL/Fl_Overlay_Window.H Fl_Window_Driver.o: ../FL/Fl_Pixmap.H Fl_Window_Driver.o: ../FL/Fl_Plugin.H Fl_Window_Driver.o: ../FL/Fl_Preferences.H Fl_Window_Driver.o: ../FL/Fl_Rect.H Fl_Window_Driver.o: ../FL/Fl_RGB_Image.H Fl_Window_Driver.o: ../FL/Fl_Scrollbar.H Fl_Window_Driver.o: ../FL/Fl_Shared_Image.H Fl_Window_Driver.o: ../FL/Fl_Slider.H Fl_Window_Driver.o: ../FL/Fl_Text_Buffer.H Fl_Window_Driver.o: ../FL/Fl_Text_Display.H Fl_Window_Driver.o: ../FL/Fl_Text_Editor.H Fl_Window_Driver.o: ../FL/fl_types.h Fl_Window_Driver.o: ../FL/fl_utf8.h Fl_Window_Driver.o: ../FL/Fl_Valuator.H Fl_Window_Driver.o: ../FL/Fl_Widget.H Fl_Window_Driver.o: ../FL/Fl_Widget_Surface.H Fl_Window_Driver.o: ../FL/Fl_Window.H Fl_Window_Driver.o: ../FL/platform.H Fl_Window_Driver.o: ../FL/platform_types.h Fl_Window_Driver.o: ../FL/x11.H Fl_Window_Driver.o: Fl_Screen_Driver.H Fl_Window_Driver.o: Fl_Window_Driver.H Fl_Window_fullscreen.o: ../FL/Enumerations.H Fl_Window_fullscreen.o: ../FL/Fl.H Fl_Window_fullscreen.o: ../FL/fl_attr.h Fl_Window_fullscreen.o: ../FL/Fl_Bitmap.H Fl_Window_fullscreen.o: ../FL/Fl_Cairo.H Fl_Window_fullscreen.o: ../FL/fl_casts.H Fl_Window_fullscreen.o: ../FL/fl_config.h Fl_Window_fullscreen.o: ../FL/Fl_Double_Window.H Fl_Window_fullscreen.o: ../FL/Fl_Export.H Fl_Window_fullscreen.o: ../FL/Fl_Group.H Fl_Window_fullscreen.o: ../FL/Fl_Image.H Fl_Window_fullscreen.o: ../FL/Fl_Overlay_Window.H Fl_Window_fullscreen.o: ../FL/fl_types.h Fl_Window_fullscreen.o: ../FL/fl_utf8.h Fl_Window_fullscreen.o: ../FL/Fl_Widget.H Fl_Window_fullscreen.o: ../FL/Fl_Window.H Fl_Window_fullscreen.o: ../FL/platform_types.h Fl_Window_fullscreen.o: Fl_Window_Driver.H Fl_Window_hotspot.o: ../FL/Enumerations.H Fl_Window_hotspot.o: ../FL/Fl.H Fl_Window_hotspot.o: ../FL/fl_attr.h Fl_Window_hotspot.o: ../FL/Fl_Bitmap.H Fl_Window_hotspot.o: ../FL/Fl_Cairo.H Fl_Window_hotspot.o: ../FL/fl_casts.H Fl_Window_hotspot.o: ../FL/fl_config.h Fl_Window_hotspot.o: ../FL/Fl_Double_Window.H Fl_Window_hotspot.o: ../FL/Fl_Export.H Fl_Window_hotspot.o: ../FL/Fl_Group.H Fl_Window_hotspot.o: ../FL/Fl_Image.H Fl_Window_hotspot.o: ../FL/Fl_Overlay_Window.H Fl_Window_hotspot.o: ../FL/fl_types.h Fl_Window_hotspot.o: ../FL/fl_utf8.h Fl_Window_hotspot.o: ../FL/Fl_Widget.H Fl_Window_hotspot.o: ../FL/Fl_Window.H Fl_Window_hotspot.o: ../FL/platform_types.h Fl_Window_hotspot.o: Fl_Window_Driver.H Fl_Window_iconize.o: ../FL/Enumerations.H Fl_Window_iconize.o: ../FL/Fl.H Fl_Window_iconize.o: ../FL/fl_attr.h Fl_Window_iconize.o: ../FL/Fl_Bitmap.H Fl_Window_iconize.o: ../FL/Fl_Cairo.H Fl_Window_iconize.o: ../FL/fl_casts.H Fl_Window_iconize.o: ../FL/fl_config.h Fl_Window_iconize.o: ../FL/Fl_Double_Window.H Fl_Window_iconize.o: ../FL/Fl_Export.H Fl_Window_iconize.o: ../FL/Fl_Group.H Fl_Window_iconize.o: ../FL/Fl_Image.H Fl_Window_iconize.o: ../FL/Fl_Overlay_Window.H Fl_Window_iconize.o: ../FL/fl_types.h Fl_Window_iconize.o: ../FL/fl_utf8.h Fl_Window_iconize.o: ../FL/Fl_Widget.H Fl_Window_iconize.o: ../FL/Fl_Window.H Fl_Window_iconize.o: ../FL/platform_types.h Fl_Window_iconize.o: Fl_Window_Driver.H Fl_Wizard.o: ../FL/Enumerations.H Fl_Wizard.o: ../FL/Fl.H Fl_Wizard.o: ../FL/fl_attr.h Fl_Wizard.o: ../FL/Fl_Bitmap.H Fl_Wizard.o: ../FL/Fl_Cairo.H Fl_Wizard.o: ../FL/fl_casts.H Fl_Wizard.o: ../FL/fl_config.h Fl_Wizard.o: ../FL/fl_draw.H Fl_Wizard.o: ../FL/Fl_Export.H Fl_Wizard.o: ../FL/Fl_Group.H Fl_Wizard.o: ../FL/Fl_Image.H Fl_Wizard.o: ../FL/fl_types.h Fl_Wizard.o: ../FL/fl_utf8.h Fl_Wizard.o: ../FL/Fl_Widget.H Fl_Wizard.o: ../FL/Fl_Window.H Fl_Wizard.o: ../FL/Fl_Wizard.H Fl_Wizard.o: ../FL/platform_types.h fl_write_png.o: ../config.h fl_write_png.o: ../FL/fl_config.h fl_write_png.o: ../FL/Fl_Export.H fl_write_png.o: ../FL/Fl_Image.H fl_write_png.o: ../FL/Fl_PNG_Image.H fl_write_png.o: ../FL/Fl_RGB_Image.H fl_write_png.o: ../FL/fl_string_functions.h fl_write_png.o: ../FL/fl_utf8.h Fl_x.o: ../config.h Fl_x.o: ../FL/Enumerations.H Fl_x.o: ../FL/filename.H Fl_x.o: ../FL/Fl.H Fl_x.o: ../FL/fl_ask.H Fl_x.o: ../FL/fl_attr.h Fl_x.o: ../FL/Fl_Bitmap.H Fl_x.o: ../FL/Fl_Cairo.H Fl_x.o: ../FL/fl_casts.H Fl_x.o: ../FL/fl_config.h Fl_x.o: ../FL/Fl_Device.H Fl_x.o: ../FL/Fl_Double_Window.H Fl_x.o: ../FL/fl_draw.H Fl_x.o: ../FL/Fl_Export.H Fl_x.o: ../FL/Fl_Graphics_Driver.H Fl_x.o: ../FL/Fl_Group.H Fl_x.o: ../FL/Fl_Image.H Fl_x.o: ../FL/Fl_Overlay_Window.H Fl_x.o: ../FL/Fl_Paged_Device.H Fl_x.o: ../FL/Fl_Pixmap.H Fl_x.o: ../FL/Fl_Plugin.H Fl_x.o: ../FL/Fl_Preferences.H Fl_x.o: ../FL/Fl_Rect.H Fl_x.o: ../FL/Fl_RGB_Image.H Fl_x.o: ../FL/Fl_Scrollbar.H Fl_x.o: ../FL/Fl_Shared_Image.H Fl_x.o: ../FL/Fl_Slider.H Fl_x.o: ../FL/fl_string_functions.h Fl_x.o: ../FL/Fl_Text_Buffer.H Fl_x.o: ../FL/Fl_Text_Display.H Fl_x.o: ../FL/Fl_Text_Editor.H Fl_x.o: ../FL/Fl_Tooltip.H Fl_x.o: ../FL/fl_types.h Fl_x.o: ../FL/fl_utf8.h Fl_x.o: ../FL/Fl_Valuator.H Fl_x.o: ../FL/Fl_Widget.H Fl_x.o: ../FL/Fl_Widget_Surface.H Fl_x.o: ../FL/Fl_Window.H Fl_x.o: ../FL/platform.H Fl_x.o: ../FL/platform_types.h Fl_x.o: ../FL/x11.H Fl_x.o: drivers/Posix/Fl_Posix_System_Driver.H Fl_x.o: drivers/Unix/Fl_Unix_Screen_Driver.H Fl_x.o: drivers/Unix/Fl_Unix_System_Driver.H Fl_x.o: drivers/X11/Fl_X11_Screen_Driver.H Fl_x.o: drivers/X11/Fl_X11_Window_Driver.H Fl_x.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H Fl_x.o: flstring.h Fl_x.o: Fl_Screen_Driver.H Fl_x.o: Fl_System_Driver.H Fl_x.o: Fl_Window_Driver.H Fl_x.o: print_button.h Fl_x.o: Xutf8.h Fl_XBM_Image.o: ../config.h Fl_XBM_Image.o: ../FL/Enumerations.H Fl_XBM_Image.o: ../FL/Fl.H Fl_XBM_Image.o: ../FL/fl_attr.h Fl_XBM_Image.o: ../FL/Fl_Bitmap.H Fl_XBM_Image.o: ../FL/Fl_Cairo.H Fl_XBM_Image.o: ../FL/fl_casts.H Fl_XBM_Image.o: ../FL/fl_config.h Fl_XBM_Image.o: ../FL/Fl_Export.H Fl_XBM_Image.o: ../FL/Fl_Image.H Fl_XBM_Image.o: ../FL/fl_string_functions.h Fl_XBM_Image.o: ../FL/fl_types.h Fl_XBM_Image.o: ../FL/fl_utf8.h Fl_XBM_Image.o: ../FL/Fl_Widget.H Fl_XBM_Image.o: ../FL/Fl_XBM_Image.H Fl_XBM_Image.o: ../FL/platform_types.h Fl_XBM_Image.o: flstring.h Fl_XPM_Image.o: ../config.h Fl_XPM_Image.o: ../FL/Enumerations.H Fl_XPM_Image.o: ../FL/Fl.H Fl_XPM_Image.o: ../FL/fl_attr.h Fl_XPM_Image.o: ../FL/Fl_Cairo.H Fl_XPM_Image.o: ../FL/fl_casts.H Fl_XPM_Image.o: ../FL/fl_config.h Fl_XPM_Image.o: ../FL/Fl_Export.H Fl_XPM_Image.o: ../FL/Fl_Image.H Fl_XPM_Image.o: ../FL/Fl_Pixmap.H Fl_XPM_Image.o: ../FL/fl_string_functions.h Fl_XPM_Image.o: ../FL/fl_types.h Fl_XPM_Image.o: ../FL/fl_utf8.h Fl_XPM_Image.o: ../FL/Fl_XPM_Image.H Fl_XPM_Image.o: ../FL/platform_types.h Fl_XPM_Image.o: flstring.h forms_bitmap.o: ../FL/Enumerations.H forms_bitmap.o: ../FL/filename.H forms_bitmap.o: ../FL/Fl.H forms_bitmap.o: ../FL/fl_ask.H forms_bitmap.o: ../FL/fl_attr.h forms_bitmap.o: ../FL/Fl_Bitmap.H forms_bitmap.o: ../FL/Fl_Box.H forms_bitmap.o: ../FL/Fl_Browser.H forms_bitmap.o: ../FL/Fl_Button.H forms_bitmap.o: ../FL/Fl_Cairo.H forms_bitmap.o: ../FL/fl_casts.H forms_bitmap.o: ../FL/Fl_Chart.H forms_bitmap.o: ../FL/Fl_Check_Button.H forms_bitmap.o: ../FL/Fl_Choice.H forms_bitmap.o: ../FL/Fl_Clock.H forms_bitmap.o: ../FL/fl_config.h forms_bitmap.o: ../FL/Fl_Counter.H forms_bitmap.o: ../FL/Fl_Device.H forms_bitmap.o: ../FL/Fl_Dial.H forms_bitmap.o: ../FL/Fl_Double_Window.H forms_bitmap.o: ../FL/fl_draw.H forms_bitmap.o: ../FL/Fl_Export.H forms_bitmap.o: ../FL/Fl_File_Browser.H forms_bitmap.o: ../FL/Fl_File_Chooser.H forms_bitmap.o: ../FL/Fl_File_Icon.H forms_bitmap.o: ../FL/Fl_File_Input.H forms_bitmap.o: ../FL/Fl_FormsBitmap.H forms_bitmap.o: ../FL/Fl_FormsPixmap.H forms_bitmap.o: ../FL/Fl_Free.H forms_bitmap.o: ../FL/Fl_Graphics_Driver.H forms_bitmap.o: ../FL/Fl_Group.H forms_bitmap.o: ../FL/Fl_Image.H forms_bitmap.o: ../FL/Fl_Input.H forms_bitmap.o: ../FL/Fl_Input_.H forms_bitmap.o: ../FL/Fl_Light_Button.H forms_bitmap.o: ../FL/Fl_Menu_.H forms_bitmap.o: ../FL/Fl_Menu_Button.H forms_bitmap.o: ../FL/Fl_Menu_Item.H forms_bitmap.o: ../FL/Fl_Multi_Label.H forms_bitmap.o: ../FL/Fl_Pixmap.H forms_bitmap.o: ../FL/Fl_Plugin.H forms_bitmap.o: ../FL/Fl_Positioner.H forms_bitmap.o: ../FL/Fl_Preferences.H forms_bitmap.o: ../FL/Fl_Rect.H forms_bitmap.o: ../FL/Fl_Return_Button.H forms_bitmap.o: ../FL/Fl_RGB_Image.H forms_bitmap.o: ../FL/Fl_Round_Button.H forms_bitmap.o: ../FL/fl_show_colormap.H forms_bitmap.o: ../FL/Fl_Slider.H forms_bitmap.o: ../FL/Fl_Tile.H forms_bitmap.o: ../FL/Fl_Timer.H forms_bitmap.o: ../FL/fl_types.h forms_bitmap.o: ../FL/fl_utf8.h forms_bitmap.o: ../FL/Fl_Valuator.H forms_bitmap.o: ../FL/Fl_Value_Slider.H forms_bitmap.o: ../FL/Fl_Widget.H forms_bitmap.o: ../FL/Fl_Window.H forms_bitmap.o: ../FL/forms.H forms_bitmap.o: ../FL/platform_types.h forms_compatibility.o: ../FL/Enumerations.H forms_compatibility.o: ../FL/filename.H forms_compatibility.o: ../FL/Fl.H forms_compatibility.o: ../FL/fl_ask.H forms_compatibility.o: ../FL/fl_attr.h forms_compatibility.o: ../FL/Fl_Bitmap.H forms_compatibility.o: ../FL/Fl_Box.H forms_compatibility.o: ../FL/Fl_Browser.H forms_compatibility.o: ../FL/Fl_Button.H forms_compatibility.o: ../FL/Fl_Cairo.H forms_compatibility.o: ../FL/fl_casts.H forms_compatibility.o: ../FL/Fl_Chart.H forms_compatibility.o: ../FL/Fl_Check_Button.H forms_compatibility.o: ../FL/Fl_Choice.H forms_compatibility.o: ../FL/Fl_Clock.H forms_compatibility.o: ../FL/fl_config.h forms_compatibility.o: ../FL/Fl_Counter.H forms_compatibility.o: ../FL/Fl_Device.H forms_compatibility.o: ../FL/Fl_Dial.H forms_compatibility.o: ../FL/Fl_Double_Window.H forms_compatibility.o: ../FL/fl_draw.H forms_compatibility.o: ../FL/Fl_Export.H forms_compatibility.o: ../FL/Fl_File_Browser.H forms_compatibility.o: ../FL/Fl_File_Chooser.H forms_compatibility.o: ../FL/Fl_File_Icon.H forms_compatibility.o: ../FL/Fl_File_Input.H forms_compatibility.o: ../FL/Fl_FormsBitmap.H forms_compatibility.o: ../FL/Fl_FormsPixmap.H forms_compatibility.o: ../FL/Fl_Free.H forms_compatibility.o: ../FL/Fl_Graphics_Driver.H forms_compatibility.o: ../FL/Fl_Group.H forms_compatibility.o: ../FL/Fl_Image.H forms_compatibility.o: ../FL/Fl_Input.H forms_compatibility.o: ../FL/Fl_Input_.H forms_compatibility.o: ../FL/Fl_Light_Button.H forms_compatibility.o: ../FL/Fl_Menu_.H forms_compatibility.o: ../FL/Fl_Menu_Button.H forms_compatibility.o: ../FL/Fl_Menu_Item.H forms_compatibility.o: ../FL/Fl_Multi_Label.H forms_compatibility.o: ../FL/Fl_Pixmap.H forms_compatibility.o: ../FL/Fl_Plugin.H forms_compatibility.o: ../FL/Fl_Positioner.H forms_compatibility.o: ../FL/Fl_Preferences.H forms_compatibility.o: ../FL/Fl_Rect.H forms_compatibility.o: ../FL/Fl_Repeat_Button.H forms_compatibility.o: ../FL/Fl_Return_Button.H forms_compatibility.o: ../FL/Fl_RGB_Image.H forms_compatibility.o: ../FL/Fl_Round_Button.H forms_compatibility.o: ../FL/fl_show_colormap.H forms_compatibility.o: ../FL/Fl_Slider.H forms_compatibility.o: ../FL/Fl_Tile.H forms_compatibility.o: ../FL/Fl_Timer.H forms_compatibility.o: ../FL/fl_types.h forms_compatibility.o: ../FL/fl_utf8.h forms_compatibility.o: ../FL/Fl_Valuator.H forms_compatibility.o: ../FL/Fl_Value_Slider.H forms_compatibility.o: ../FL/Fl_Widget.H forms_compatibility.o: ../FL/Fl_Window.H forms_compatibility.o: ../FL/forms.H forms_compatibility.o: ../FL/platform_types.h forms_free.o: ../FL/Enumerations.H forms_free.o: ../FL/Fl.H forms_free.o: ../FL/fl_attr.h forms_free.o: ../FL/Fl_Cairo.H forms_free.o: ../FL/fl_casts.H forms_free.o: ../FL/fl_config.h forms_free.o: ../FL/Fl_Export.H forms_free.o: ../FL/Fl_Free.H forms_free.o: ../FL/fl_types.h forms_free.o: ../FL/fl_utf8.h forms_free.o: ../FL/Fl_Widget.H forms_free.o: ../FL/platform_types.h forms_fselect.o: ../config.h forms_fselect.o: ../FL/Enumerations.H forms_fselect.o: ../FL/filename.H forms_fselect.o: ../FL/Fl.H forms_fselect.o: ../FL/fl_ask.H forms_fselect.o: ../FL/fl_attr.h forms_fselect.o: ../FL/Fl_Bitmap.H forms_fselect.o: ../FL/Fl_Box.H forms_fselect.o: ../FL/Fl_Browser.H forms_fselect.o: ../FL/Fl_Button.H forms_fselect.o: ../FL/Fl_Cairo.H forms_fselect.o: ../FL/fl_casts.H forms_fselect.o: ../FL/Fl_Chart.H forms_fselect.o: ../FL/Fl_Check_Button.H forms_fselect.o: ../FL/Fl_Choice.H forms_fselect.o: ../FL/Fl_Clock.H forms_fselect.o: ../FL/fl_config.h forms_fselect.o: ../FL/Fl_Counter.H forms_fselect.o: ../FL/Fl_Device.H forms_fselect.o: ../FL/Fl_Dial.H forms_fselect.o: ../FL/Fl_Double_Window.H forms_fselect.o: ../FL/fl_draw.H forms_fselect.o: ../FL/Fl_Export.H forms_fselect.o: ../FL/Fl_File_Browser.H forms_fselect.o: ../FL/Fl_File_Chooser.H forms_fselect.o: ../FL/Fl_File_Icon.H forms_fselect.o: ../FL/Fl_File_Input.H forms_fselect.o: ../FL/Fl_FormsBitmap.H forms_fselect.o: ../FL/Fl_FormsPixmap.H forms_fselect.o: ../FL/Fl_Free.H forms_fselect.o: ../FL/Fl_Graphics_Driver.H forms_fselect.o: ../FL/Fl_Group.H forms_fselect.o: ../FL/Fl_Image.H forms_fselect.o: ../FL/Fl_Input.H forms_fselect.o: ../FL/Fl_Input_.H forms_fselect.o: ../FL/Fl_Light_Button.H forms_fselect.o: ../FL/Fl_Menu_.H forms_fselect.o: ../FL/Fl_Menu_Button.H forms_fselect.o: ../FL/Fl_Menu_Item.H forms_fselect.o: ../FL/Fl_Multi_Label.H forms_fselect.o: ../FL/Fl_Pixmap.H forms_fselect.o: ../FL/Fl_Plugin.H forms_fselect.o: ../FL/Fl_Positioner.H forms_fselect.o: ../FL/Fl_Preferences.H forms_fselect.o: ../FL/Fl_Rect.H forms_fselect.o: ../FL/Fl_Return_Button.H forms_fselect.o: ../FL/Fl_RGB_Image.H forms_fselect.o: ../FL/Fl_Round_Button.H forms_fselect.o: ../FL/fl_show_colormap.H forms_fselect.o: ../FL/Fl_Slider.H forms_fselect.o: ../FL/fl_string_functions.h forms_fselect.o: ../FL/Fl_Tile.H forms_fselect.o: ../FL/Fl_Timer.H forms_fselect.o: ../FL/fl_types.h forms_fselect.o: ../FL/fl_utf8.h forms_fselect.o: ../FL/Fl_Valuator.H forms_fselect.o: ../FL/Fl_Value_Slider.H forms_fselect.o: ../FL/Fl_Widget.H forms_fselect.o: ../FL/Fl_Window.H forms_fselect.o: ../FL/forms.H forms_fselect.o: ../FL/platform_types.h forms_fselect.o: flstring.h forms_pixmap.o: ../FL/Enumerations.H forms_pixmap.o: ../FL/filename.H forms_pixmap.o: ../FL/Fl.H forms_pixmap.o: ../FL/fl_ask.H forms_pixmap.o: ../FL/fl_attr.h forms_pixmap.o: ../FL/Fl_Bitmap.H forms_pixmap.o: ../FL/Fl_Box.H forms_pixmap.o: ../FL/Fl_Browser.H forms_pixmap.o: ../FL/Fl_Button.H forms_pixmap.o: ../FL/Fl_Cairo.H forms_pixmap.o: ../FL/fl_casts.H forms_pixmap.o: ../FL/Fl_Chart.H forms_pixmap.o: ../FL/Fl_Check_Button.H forms_pixmap.o: ../FL/Fl_Choice.H forms_pixmap.o: ../FL/Fl_Clock.H forms_pixmap.o: ../FL/fl_config.h forms_pixmap.o: ../FL/Fl_Counter.H forms_pixmap.o: ../FL/Fl_Device.H forms_pixmap.o: ../FL/Fl_Dial.H forms_pixmap.o: ../FL/Fl_Double_Window.H forms_pixmap.o: ../FL/fl_draw.H forms_pixmap.o: ../FL/Fl_Export.H forms_pixmap.o: ../FL/Fl_File_Browser.H forms_pixmap.o: ../FL/Fl_File_Chooser.H forms_pixmap.o: ../FL/Fl_File_Icon.H forms_pixmap.o: ../FL/Fl_File_Input.H forms_pixmap.o: ../FL/Fl_FormsBitmap.H forms_pixmap.o: ../FL/Fl_FormsPixmap.H forms_pixmap.o: ../FL/Fl_Free.H forms_pixmap.o: ../FL/Fl_Graphics_Driver.H forms_pixmap.o: ../FL/Fl_Group.H forms_pixmap.o: ../FL/Fl_Image.H forms_pixmap.o: ../FL/Fl_Input.H forms_pixmap.o: ../FL/Fl_Input_.H forms_pixmap.o: ../FL/Fl_Light_Button.H forms_pixmap.o: ../FL/Fl_Menu_.H forms_pixmap.o: ../FL/Fl_Menu_Button.H forms_pixmap.o: ../FL/Fl_Menu_Item.H forms_pixmap.o: ../FL/Fl_Multi_Label.H forms_pixmap.o: ../FL/Fl_Pixmap.H forms_pixmap.o: ../FL/Fl_Plugin.H forms_pixmap.o: ../FL/Fl_Positioner.H forms_pixmap.o: ../FL/Fl_Preferences.H forms_pixmap.o: ../FL/Fl_Rect.H forms_pixmap.o: ../FL/Fl_Return_Button.H forms_pixmap.o: ../FL/Fl_RGB_Image.H forms_pixmap.o: ../FL/Fl_Round_Button.H forms_pixmap.o: ../FL/fl_show_colormap.H forms_pixmap.o: ../FL/Fl_Slider.H forms_pixmap.o: ../FL/Fl_Tile.H forms_pixmap.o: ../FL/Fl_Timer.H forms_pixmap.o: ../FL/fl_types.h forms_pixmap.o: ../FL/fl_utf8.h forms_pixmap.o: ../FL/Fl_Valuator.H forms_pixmap.o: ../FL/Fl_Value_Slider.H forms_pixmap.o: ../FL/Fl_Widget.H forms_pixmap.o: ../FL/Fl_Window.H forms_pixmap.o: ../FL/forms.H forms_pixmap.o: ../FL/platform_types.h forms_timer.o: ../FL/Enumerations.H forms_timer.o: ../FL/filename.H forms_timer.o: ../FL/Fl.H forms_timer.o: ../FL/fl_ask.H forms_timer.o: ../FL/fl_attr.h forms_timer.o: ../FL/Fl_Bitmap.H forms_timer.o: ../FL/Fl_Box.H forms_timer.o: ../FL/Fl_Browser.H forms_timer.o: ../FL/Fl_Button.H forms_timer.o: ../FL/Fl_Cairo.H forms_timer.o: ../FL/fl_casts.H forms_timer.o: ../FL/Fl_Chart.H forms_timer.o: ../FL/Fl_Check_Button.H forms_timer.o: ../FL/Fl_Choice.H forms_timer.o: ../FL/Fl_Clock.H forms_timer.o: ../FL/fl_config.h forms_timer.o: ../FL/Fl_Counter.H forms_timer.o: ../FL/Fl_Device.H forms_timer.o: ../FL/Fl_Dial.H forms_timer.o: ../FL/Fl_Double_Window.H forms_timer.o: ../FL/fl_draw.H forms_timer.o: ../FL/Fl_Export.H forms_timer.o: ../FL/Fl_File_Browser.H forms_timer.o: ../FL/Fl_File_Chooser.H forms_timer.o: ../FL/Fl_File_Icon.H forms_timer.o: ../FL/Fl_File_Input.H forms_timer.o: ../FL/Fl_FormsBitmap.H forms_timer.o: ../FL/Fl_FormsPixmap.H forms_timer.o: ../FL/Fl_Free.H forms_timer.o: ../FL/Fl_Graphics_Driver.H forms_timer.o: ../FL/Fl_Group.H forms_timer.o: ../FL/Fl_Image.H forms_timer.o: ../FL/Fl_Input.H forms_timer.o: ../FL/Fl_Input_.H forms_timer.o: ../FL/Fl_Light_Button.H forms_timer.o: ../FL/Fl_Menu_.H forms_timer.o: ../FL/Fl_Menu_Button.H forms_timer.o: ../FL/Fl_Menu_Item.H forms_timer.o: ../FL/Fl_Multi_Label.H forms_timer.o: ../FL/Fl_Pixmap.H forms_timer.o: ../FL/Fl_Plugin.H forms_timer.o: ../FL/Fl_Positioner.H forms_timer.o: ../FL/Fl_Preferences.H forms_timer.o: ../FL/Fl_Rect.H forms_timer.o: ../FL/Fl_Return_Button.H forms_timer.o: ../FL/Fl_RGB_Image.H forms_timer.o: ../FL/Fl_Round_Button.H forms_timer.o: ../FL/fl_show_colormap.H forms_timer.o: ../FL/Fl_Slider.H forms_timer.o: ../FL/Fl_Tile.H forms_timer.o: ../FL/Fl_Timer.H forms_timer.o: ../FL/fl_types.h forms_timer.o: ../FL/fl_utf8.h forms_timer.o: ../FL/Fl_Valuator.H forms_timer.o: ../FL/Fl_Value_Slider.H forms_timer.o: ../FL/Fl_Widget.H forms_timer.o: ../FL/Fl_Window.H forms_timer.o: ../FL/forms.H forms_timer.o: ../FL/platform_types.h forms_timer.o: Fl_System_Driver.H freeglut_geometry.o: ../FL/Fl.H freeglut_geometry.o: ../FL/Fl_Gl_Window.H freeglut_geometry.o: ../FL/Fl_Window.H freeglut_geometry.o: ../FL/gl.h freeglut_geometry.o: ../FL/glut.H freeglut_geometry.o: ../FL/math.h freeglut_stroke_mono_roman.o: ../FL/Fl.H freeglut_stroke_mono_roman.o: ../FL/Fl_Gl_Window.H freeglut_stroke_mono_roman.o: ../FL/Fl_Window.H freeglut_stroke_mono_roman.o: ../FL/gl.h freeglut_stroke_mono_roman.o: ../FL/glut.H freeglut_stroke_roman.o: ../FL/Fl.H freeglut_stroke_roman.o: ../FL/Fl_Gl_Window.H freeglut_stroke_roman.o: ../FL/Fl_Window.H freeglut_stroke_roman.o: ../FL/gl.h freeglut_stroke_roman.o: ../FL/glut.H freeglut_teapot.o: ../FL/Fl.H freeglut_teapot.o: ../FL/Fl_Gl_Window.H freeglut_teapot.o: ../FL/Fl_Window.H freeglut_teapot.o: ../FL/gl.h freeglut_teapot.o: ../FL/glut.H freeglut_teapot.o: freeglut_teapot_data.h glut_compatibility.o: ../config.h glut_compatibility.o: ../FL/Enumerations.H glut_compatibility.o: ../FL/Fl.H glut_compatibility.o: ../FL/fl_attr.h glut_compatibility.o: ../FL/Fl_Bitmap.H glut_compatibility.o: ../FL/Fl_Cairo.H glut_compatibility.o: ../FL/fl_casts.H glut_compatibility.o: ../FL/fl_config.h glut_compatibility.o: ../FL/Fl_Device.H glut_compatibility.o: ../FL/fl_draw.H glut_compatibility.o: ../FL/Fl_Export.H glut_compatibility.o: ../FL/Fl_Gl_Window.H glut_compatibility.o: ../FL/Fl_Graphics_Driver.H glut_compatibility.o: ../FL/Fl_Group.H glut_compatibility.o: ../FL/Fl_Image.H glut_compatibility.o: ../FL/Fl_Menu_Item.H glut_compatibility.o: ../FL/Fl_Multi_Label.H glut_compatibility.o: ../FL/Fl_Pixmap.H glut_compatibility.o: ../FL/Fl_Plugin.H glut_compatibility.o: ../FL/Fl_Preferences.H glut_compatibility.o: ../FL/Fl_Rect.H glut_compatibility.o: ../FL/Fl_RGB_Image.H glut_compatibility.o: ../FL/Fl_Scrollbar.H glut_compatibility.o: ../FL/Fl_Slider.H glut_compatibility.o: ../FL/fl_string_functions.h glut_compatibility.o: ../FL/Fl_Text_Buffer.H glut_compatibility.o: ../FL/Fl_Text_Display.H glut_compatibility.o: ../FL/Fl_Text_Editor.H glut_compatibility.o: ../FL/fl_types.h glut_compatibility.o: ../FL/fl_utf8.h glut_compatibility.o: ../FL/Fl_Valuator.H glut_compatibility.o: ../FL/Fl_Widget.H glut_compatibility.o: ../FL/Fl_Window.H glut_compatibility.o: ../FL/gl.h glut_compatibility.o: ../FL/glut.H glut_compatibility.o: ../FL/platform_types.h glut_compatibility.o: flstring.h glut_compatibility.o: Fl_Gl_Window_Driver.H glut_compatibility.o: Fl_Screen_Driver.H glut_font.o: ../config.h glut_font.o: ../FL/Fl.H glut_font.o: ../FL/fl_config.h glut_font.o: ../FL/Fl_Gl_Window.H glut_font.o: ../FL/Fl_Window.H glut_font.o: ../FL/gl.h glut_font.o: ../FL/glut.H gl_draw.o: ../config.h gl_draw.o: ../FL/Enumerations.H gl_draw.o: ../FL/Fl.H gl_draw.o: ../FL/fl_attr.h gl_draw.o: ../FL/Fl_Bitmap.H gl_draw.o: ../FL/Fl_Cairo.H gl_draw.o: ../FL/fl_casts.H gl_draw.o: ../FL/fl_config.h gl_draw.o: ../FL/Fl_Device.H gl_draw.o: ../FL/fl_draw.H gl_draw.o: ../FL/Fl_Export.H gl_draw.o: ../FL/Fl_Gl_Window.H gl_draw.o: ../FL/Fl_Group.H gl_draw.o: ../FL/Fl_Image.H gl_draw.o: ../FL/Fl_Image_Surface.H gl_draw.o: ../FL/Fl_Plugin.H gl_draw.o: ../FL/Fl_Preferences.H gl_draw.o: ../FL/Fl_Shared_Image.H gl_draw.o: ../FL/fl_types.h gl_draw.o: ../FL/fl_utf8.h gl_draw.o: ../FL/Fl_Widget.H gl_draw.o: ../FL/Fl_Widget_Surface.H gl_draw.o: ../FL/Fl_Window.H gl_draw.o: ../FL/gl.h gl_draw.o: ../FL/glu.h gl_draw.o: ../FL/glut.H gl_draw.o: ../FL/gl_draw.H gl_draw.o: ../FL/math.h gl_draw.o: ../FL/platform_types.h gl_draw.o: Fl_Gl_Window_Driver.H gl_start.o: ../config.h gl_start.o: ../FL/Enumerations.H gl_start.o: ../FL/Fl.H gl_start.o: ../FL/fl_attr.h gl_start.o: ../FL/Fl_Bitmap.H gl_start.o: ../FL/Fl_Cairo.H gl_start.o: ../FL/fl_casts.H gl_start.o: ../FL/fl_config.h gl_start.o: ../FL/fl_draw.H gl_start.o: ../FL/Fl_Export.H gl_start.o: ../FL/Fl_Gl_Window.H gl_start.o: ../FL/Fl_Group.H gl_start.o: ../FL/Fl_Image.H gl_start.o: ../FL/fl_types.h gl_start.o: ../FL/fl_utf8.h gl_start.o: ../FL/Fl_Widget.H gl_start.o: ../FL/Fl_Window.H gl_start.o: ../FL/gl.h gl_start.o: ../FL/platform_types.h gl_start.o: Fl_Gl_Window_Driver.H nanosvg.o: ../config.h nanosvg.o: ../FL/fl_config.h nanosvg.o: ../nanosvg/nanosvg.h nanosvg.o: ../nanosvg/nanosvgrast.h numericsort.o: ../FL/filename.H numericsort.o: ../FL/fl_config.h numericsort.o: ../FL/Fl_Export.H numericsort.o: ../FL/fl_utf8.h numericsort.o: ../FL/platform_types.h print_button.o: ../FL/Enumerations.H print_button.o: ../FL/Fl.H print_button.o: ../FL/fl_attr.h print_button.o: ../FL/Fl_Bitmap.H print_button.o: ../FL/Fl_Cairo.H print_button.o: ../FL/fl_casts.H print_button.o: ../FL/fl_config.h print_button.o: ../FL/Fl_Copy_Surface.H print_button.o: ../FL/Fl_Device.H print_button.o: ../FL/fl_draw.H print_button.o: ../FL/Fl_Export.H print_button.o: ../FL/Fl_Group.H print_button.o: ../FL/Fl_Image.H print_button.o: ../FL/Fl_Paged_Device.H print_button.o: ../FL/Fl_Plugin.H print_button.o: ../FL/Fl_PostScript.H print_button.o: ../FL/Fl_Preferences.H print_button.o: ../FL/Fl_Printer.H print_button.o: ../FL/fl_types.h print_button.o: ../FL/fl_utf8.h print_button.o: ../FL/Fl_Widget.H print_button.o: ../FL/Fl_Widget_Surface.H print_button.o: ../FL/Fl_Window.H print_button.o: ../FL/platform_types.h print_button.o: print_button.h scandir_posix.o: ../config.h scandir_posix.o: ../FL/fl_config.h screen_xywh.o: ../config.h screen_xywh.o: ../FL/Enumerations.H screen_xywh.o: ../FL/Fl.H screen_xywh.o: ../FL/fl_attr.h screen_xywh.o: ../FL/Fl_Bitmap.H screen_xywh.o: ../FL/Fl_Cairo.H screen_xywh.o: ../FL/fl_casts.H screen_xywh.o: ../FL/fl_config.h screen_xywh.o: ../FL/Fl_Device.H screen_xywh.o: ../FL/fl_draw.H screen_xywh.o: ../FL/Fl_Export.H screen_xywh.o: ../FL/Fl_Graphics_Driver.H screen_xywh.o: ../FL/Fl_Group.H screen_xywh.o: ../FL/Fl_Image.H screen_xywh.o: ../FL/Fl_Pixmap.H screen_xywh.o: ../FL/Fl_Plugin.H screen_xywh.o: ../FL/Fl_Preferences.H screen_xywh.o: ../FL/Fl_Rect.H screen_xywh.o: ../FL/Fl_RGB_Image.H screen_xywh.o: ../FL/Fl_Scrollbar.H screen_xywh.o: ../FL/Fl_Slider.H screen_xywh.o: ../FL/Fl_Text_Buffer.H screen_xywh.o: ../FL/Fl_Text_Display.H screen_xywh.o: ../FL/Fl_Text_Editor.H screen_xywh.o: ../FL/fl_types.h screen_xywh.o: ../FL/fl_utf8.h screen_xywh.o: ../FL/Fl_Valuator.H screen_xywh.o: ../FL/Fl_Widget.H screen_xywh.o: ../FL/platform.H screen_xywh.o: ../FL/platform_types.h screen_xywh.o: ../FL/x11.H screen_xywh.o: Fl_Screen_Driver.H vsnprintf.o: ../config.h vsnprintf.o: ../FL/fl_config.h vsnprintf.o: ../FL/Fl_Export.H vsnprintf.o: ../FL/fl_string_functions.h vsnprintf.o: flstring.h xutf8/case.o: utf8_internal.h xutf8/case.o: xutf8/headers/case.h xutf8/is_right2left.o: utf8_internal.h xutf8/is_spacing.o: utf8_internal.h xutf8/is_spacing.o: xutf8/headers/spacing.h xutf8/keysym2Ucs.o: ../FL/Fl_Export.H xutf8/keysym2Ucs.o: Xutf8.h xutf8/keysym2Ucs.o: xutf8/imKStoUCS.c xutf8/keysym2Ucs.o: xutf8/Ximint.h xutf8/keysym2Ucs.o: xutf8/Xlibint.h fltk-1.4.3/src/fl_cursor_help.xpm0000644000175000017500000000135315004135251017132 0ustar albrechtalbrecht/* XPM */ static const char * const fl_cursor_help_xpm[] = { "16 27 9 1", " c None", ". c #FFFFFF", "+ c #DBDBDB", "@ c #242424", "# c #000000", "$ c #494949", "% c #6D6D6D", "& c #929292", "* c #B6B6B6", " ", ". ", ".+ ", ".@+ ", ".#@+ ", ".##@. ", ".###@. ", ".####@. ", ".#####$. ", ".######$. ", ".#######$. ", ".#####@@@%. ", ".#####+..... ", ".##$%#%. ", ".#$..@#. ", ".$. .&#%. ", ".. .##. .... ", ". .&#.+%$%&. ", " ...*#@##%.", " ++.*#@.", " .%#$.", " .%#@. ", " .##+ ", " .++. ", " +##. ", " +##. ", " .... "}; fltk-1.4.3/src/Fl_Text_Editor.cxx0000644000175000017500000007232215004135251017001 0ustar albrechtalbrecht// // Copyright 2001-2023 by Bill Spitzak and others. // // Original code Copyright Mark Edel. Permission to distribute under // the LGPL for the FLTK library granted by Mark Edel. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "flstring.h" #include #include #include #include #include "Fl_Screen_Driver.H" #include /* Keyboard Control Matrix key\modifier plain Ctrl Alt Meta left 1/1 13/9 0/13 0/9 right 2/2 14/10 0/14 0/10 up 3/19 21/7 0/15 0/17 down 4/20 22/8 0/16 0/18 home 9/5 17/0 0/0 0/0 end 10/6 18/0 0/0 0/0 page up 11/7 23/0 0/11 0/0 page down 12/8 24/0 0/12 0/0 (FLTK action / OS X action) (adding the shift key extends the selection, all other combinations are no-op) 0: no-op 1: move cursor to the left, at line beginning wrap to end of prev line, at doc start no-op 2: move cursor to the right, at line end move to beginning of the next line, at doc end no-op 3: move cursor up, at doc top no-op 4: move cursor down, at doc bottom no-op 5: scroll display to top of text (cursor unchanged) 6: scroll display to end of text (cursor unchanged) 7: scroll text down one page (cursor unchanged) 8: scroll text up one page (cursor unchanged) 9: move cursor to beginning of line 10: move cursor to end of line 11: move cursor up one page and scroll down 12: move cursor down one page and scroll up 13: move to the beginning of the word or the previous word 14: move to the end of the word or the next word 15: if start of line: start of prev line, else start of this line 16: if end of line: end of next line, else end of this line 17: move cursor to the beginning of the document 18: move cursor to the end of the document 19: move cursor up, at doc top: home, at doc start: no-op) 20: move cursor down, at doc bot: end, at doc end: no-op) 21: scroll text down one line (cursor unchanged) 22: scroll text up one line (cursor unchanged) 23: move cursor to the beginning of the top of the screen 24: move cursor to the beginning of the bottom of the window */ /** The constructor creates a new text editor widget.*/ Fl_Text_Editor::Fl_Text_Editor(int X, int Y, int W, int H, const char* l) : Fl_Text_Display(X, Y, W, H, l) { mCursorOn = 1; insert_mode_ = 1; key_bindings = 0; set_flag(MAC_USE_ACCENTS_MENU); set_flag(NEEDS_KEYBOARD); // handle the default key bindings add_default_key_bindings(&key_bindings); // handle everything else default_key_function(kf_default); } #ifndef FL_DOXYGEN Fl_Text_Editor::Key_Binding* Fl_Text_Editor::global_key_bindings = 0; #endif // These are the default key bindings every widget should start with static struct { int key; int state; Fl_Text_Editor::Key_Func func; } default_key_bindings[] = { { FL_Escape, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_ignore }, { FL_Enter, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_enter }, { FL_KP_Enter, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_enter }, { FL_BackSpace, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_backspace }, { FL_Insert, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_insert }, { FL_Delete, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_delete }, { FL_Home, 0, Fl_Text_Editor::kf_move }, { FL_End, 0, Fl_Text_Editor::kf_move }, { FL_Left, 0, Fl_Text_Editor::kf_move }, { FL_Up, 0, Fl_Text_Editor::kf_move }, { FL_Right, 0, Fl_Text_Editor::kf_move }, { FL_Down, 0, Fl_Text_Editor::kf_move }, { FL_Page_Up, 0, Fl_Text_Editor::kf_move }, { FL_Page_Down, 0, Fl_Text_Editor::kf_move }, { FL_Home, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, { FL_End, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, { FL_Left, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, { FL_Up, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, { FL_Right, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, { FL_Down, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, { FL_Page_Up, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, { FL_Page_Down, FL_SHIFT, Fl_Text_Editor::kf_shift_move }, { FL_Home, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, { FL_End, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, { FL_Left, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, { FL_Up, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, { FL_Right, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, { FL_Down, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, { FL_Page_Up, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, { FL_Page_Down, FL_CTRL, Fl_Text_Editor::kf_ctrl_move }, { FL_Home, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, { FL_End, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, { FL_Left, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, { FL_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, { FL_Right, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, { FL_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, { FL_Page_Up, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, { FL_Page_Down, FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_c_s_move }, //{ FL_Clear, 0, Fl_Text_Editor::delete_to_eol }, { 'z', FL_CTRL, Fl_Text_Editor::kf_undo }, { 'z', FL_CTRL|FL_SHIFT, Fl_Text_Editor::kf_redo }, // Windows screen driver also defines Ctrl-Y { '/', FL_CTRL, Fl_Text_Editor::kf_undo }, // Emacs { '?', FL_CTRL, Fl_Text_Editor::kf_redo }, // Emacs { 'x', FL_CTRL, Fl_Text_Editor::kf_cut }, { FL_Delete, FL_SHIFT, Fl_Text_Editor::kf_cut }, { 'c', FL_CTRL, Fl_Text_Editor::kf_copy }, { FL_Insert, FL_CTRL, Fl_Text_Editor::kf_copy }, { 'v', FL_CTRL, Fl_Text_Editor::kf_paste }, { FL_Insert, FL_SHIFT, Fl_Text_Editor::kf_paste }, { 'a', FL_CTRL, Fl_Text_Editor::kf_select_all }, { 0, 0, 0 } }; /** Adds all of the default editor key bindings to the specified key binding list.*/ void Fl_Text_Editor::add_default_key_bindings(Key_Binding** list) { for (int i = 0; default_key_bindings[i].key; i++) { add_key_binding(default_key_bindings[i].key, default_key_bindings[i].state, default_key_bindings[i].func, list); } Key_Binding *extra_key_bindings = Fl::screen_driver()->text_editor_extra_key_bindings; if (extra_key_bindings) { // add platform-specific key bindings, if any for (int i = 0; extra_key_bindings[i].key; i++) { add_key_binding(extra_key_bindings[i].key, extra_key_bindings[i].state, extra_key_bindings[i].function, list); } } } /** Returns the function associated with a key binding.*/ Fl_Text_Editor::Key_Func Fl_Text_Editor::bound_key_function(int key, int state, Key_Binding* list) const { Key_Binding* cur; for (cur = list; cur; cur = cur->next) if (cur->key == key) if (cur->state == FL_TEXT_EDITOR_ANY_STATE || cur->state == state) break; if (!cur) return 0; return cur->function; } /** Removes all of the key bindings associated with the text editor or list.*/ void Fl_Text_Editor::remove_all_key_bindings(Key_Binding** list) { Key_Binding *cur, *next; for (cur = *list; cur; cur = next) { next = cur->next; delete cur; } *list = 0; } /** Removes the key binding associated with the key \p key of state \p state from the Key_Binding list \p list. This can be used in derived classes to remove global key bindings by using the global (static) Key_Binding list Fl_Text_Editor::global_key_bindings. */ void Fl_Text_Editor::remove_key_binding(int key, int state, Key_Binding** list) { Key_Binding *cur, *last = 0; for (cur = *list; cur; last = cur, cur = cur->next) if (cur->key == key && cur->state == state) break; if (!cur) return; if (last) last->next = cur->next; else *list = cur->next; delete cur; } /** Adds a \p key of state \p state with the function \p function to an arbitrary key binding list \p list. This can be used in derived classes to add global key bindings by using the global (static) Key_Binding list Fl_Text_Editor::global_key_bindings. */ void Fl_Text_Editor::add_key_binding(int key, int state, Key_Func function, Key_Binding** list) { Key_Binding* kb = new Key_Binding; kb->key = key; kb->state = state; kb->function = function; kb->next = *list; *list = kb; } //////////////////////////////////////////////////////////////// static void kill_selection(Fl_Text_Editor* e) { if (e->buffer()->selected()) { e->insert_position(e->buffer()->primary_selection()->start()); e->buffer()->remove_selection(); } } /** Inserts the text associated with key \p 'c' in editor \p 'e'. Honors the current selection and insert/overstrike mode. */ int Fl_Text_Editor::kf_default(int c, Fl_Text_Editor* e) { // FIXME: this function is a mess! Fix this! if (!c || (!(c > 0 && c < 127 && isprint(c)) && c != '\t')) return 0; char s[2] = "\0"; s[0] = (char)c; kill_selection(e); if (e->insert_mode()) e->insert(s); else e->overstrike(s); e->show_insert_position(); e->set_changed(); if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED); return 1; } /** Ignores the key \p 'c' in editor \p 'e'. This method can be used as a keyboard binding to disable a key that might otherwise be handled or entered as text. An example would be disabling FL_Escape, so that it isn't added to the buffer when invoked by the user. */ int Fl_Text_Editor::kf_ignore(int, Fl_Text_Editor*) { return 0; // don't handle } /** Does a backspace for key \p 'c' in the current buffer of editor \p 'e'. Any current selection is deleted. Otherwise, the character left is deleted and the cursor moved. The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_backspace(int, Fl_Text_Editor* e) { if (!e->buffer()->selected() && e->move_left()) { int p1 = e->insert_position(); int p2 = e->buffer()->next_char(p1); e->buffer()->select(p1, p2); } kill_selection(e); e->show_insert_position(); e->set_changed(); if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED); return 1; } /** Inserts a newline for key \p 'c' at the current cursor position in editor \p 'e'. The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_enter(int, Fl_Text_Editor* e) { kill_selection(e); e->insert("\n"); e->show_insert_position(); e->set_changed(); if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED); return 1; } extern int fl_text_drag_prepare(int pos, int key, Fl_Text_Display* d); extern void fl_text_drag_me(int pos, Fl_Text_Display* d); /** Moves the text cursor in the direction indicated by key \p 'c' in editor \p 'e'. Supported values for 'c' are currently: \code FL_Home -- moves the cursor to the beginning of the current line FL_End -- moves the cursor to the end of the current line FL_Left -- moves the cursor left one character FL_Right -- moves the cursor right one character FL_Up -- moves the cursor up one line FL_Down -- moves the cursor down one line FL_Page_Up -- moves the cursor up one page FL_Page_Down -- moves the cursor down one page \endcode */ int Fl_Text_Editor::kf_move(int c, Fl_Text_Editor* e) { int i; int selected = e->buffer()->selected(); if (!selected) e->dragPos = e->insert_position(); e->buffer()->unselect(); Fl::copy("", 0, 0); switch (c) { case FL_Home: e->insert_position(e->line_start(e->insert_position())); break; case FL_End: e->insert_position(e->line_end(e->insert_position(), false)); break; case FL_Left: e->move_left(); break; case FL_Right: e->move_right(); break; case FL_Up: e->move_up(); break; case FL_Down: e->move_down(); break; case FL_Page_Up: for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_up(); break; case FL_Page_Down: for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_down(); break; } e->show_insert_position(); return 1; } /** Extends the current selection in the direction of key \p 'c' in editor \p 'e'. \see kf_move() */ int Fl_Text_Editor::kf_shift_move(int c, Fl_Text_Editor* e) { fl_text_drag_prepare(-1, c, e); kf_move(c, e); fl_text_drag_me(e->insert_position(), e); char *copy = e->buffer()->selection_text(); if (copy) { Fl::copy(copy, (int) strlen(copy), 0); free(copy); } return 1; } /** Moves the current text cursor in the direction indicated by control key \p 'c' in editor \p 'e'. Supported values for 'c' are currently: \code FL_Home -- moves the cursor to the beginning of the document FL_End -- moves the cursor to the end of the document FL_Left -- moves the cursor left one word FL_Right -- moves the cursor right one word FL_Up -- scrolls up one line, without moving cursor FL_Down -- scrolls down one line, without moving cursor FL_Page_Up -- moves the cursor to the beginning of the top line on the current page FL_Page_Down -- moves the cursor to the beginning of the last line on the current page \endcode */ int Fl_Text_Editor::kf_ctrl_move(int c, Fl_Text_Editor* e) { if (!e->buffer()->selected()) e->dragPos = e->insert_position(); if (c != FL_Up && c != FL_Down) { e->buffer()->unselect(); Fl::copy("", 0, 0); e->show_insert_position(); } switch (c) { case FL_Home: e->insert_position(0); e->scroll(0, 0); break; case FL_End: e->insert_position(e->buffer()->length()); e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0); break; case FL_Left: e->previous_word(); break; case FL_Right: e->next_word(); break; case FL_Up: e->scroll(e->mTopLineNum-1, e->mHorizOffset); break; case FL_Down: e->scroll(e->mTopLineNum+1, e->mHorizOffset); break; case FL_Page_Up: e->insert_position(e->mLineStarts[0]); break; case FL_Page_Down: e->insert_position(e->mLineStarts[e->mNVisibleLines-2]); break; } return 1; } /** Moves the current text cursor in the direction indicated by meta key \p 'c' in editor \p 'e'. Supported values for 'c' are currently: \code FL_Up -- moves cursor to the beginning of the current document FL_Down -- moves cursor to the end of the current document FL_Left -- moves the cursor to the beginning of the current line FL_Right -- moves the cursor to the end of the current line \endcode */ int Fl_Text_Editor::kf_meta_move(int c, Fl_Text_Editor* e) { if (!e->buffer()->selected()) e->dragPos = e->insert_position(); if (c != FL_Up && c != FL_Down) { e->buffer()->unselect(); Fl::copy("", 0, 0); e->show_insert_position(); } switch (c) { case FL_Up: // top of buffer e->insert_position(0); e->scroll(0, 0); break; case FL_Down: // end of buffer e->insert_position(e->buffer()->length()); e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0); break; case FL_Left: // beginning of line kf_move(FL_Home, e); break; case FL_Right: // end of line kf_move(FL_End, e); break; } return 1; } /** Extends the current selection in the direction indicated by meta key \p 'c' in editor \p 'e'. \see kf_meta_move(). */ int Fl_Text_Editor::kf_m_s_move(int c, Fl_Text_Editor* e) { fl_text_drag_prepare(-1, c, e); kf_meta_move(c, e); fl_text_drag_me(e->insert_position(), e); return 1; } /** Extends the current selection in the direction indicated by control key \p 'c' in editor \p 'e'. \see kf_ctrl_move(). */ int Fl_Text_Editor::kf_c_s_move(int c, Fl_Text_Editor* e) { fl_text_drag_prepare(-1, c, e); kf_ctrl_move(c, e); fl_text_drag_me(e->insert_position(), e); return 1; } /** Moves the text cursor to the beginning of the current line in editor \p 'e'. Same as kf_move(FL_Home, e). The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_home(int, Fl_Text_Editor* e) { return kf_move(FL_Home, e); } /** Moves the text cursor to the end of the current line in editor \p 'e'. Same as kf_move(FL_End, e). The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_end(int, Fl_Text_Editor* e) { return kf_move(FL_End, e); } /** Moves the text cursor one character to the left in editor \p 'e'. Same as kf_move(FL_Left, e). The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_left(int, Fl_Text_Editor* e) { return kf_move(FL_Left, e); } /** Moves the text cursor one line up for editor \p 'e'. Same as kf_move(FL_Up, e). The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_up(int, Fl_Text_Editor* e) { return kf_move(FL_Up, e); } /** Moves the text cursor one character to the right for editor \p 'e'. Same as kf_move(FL_Right, e). The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_right(int, Fl_Text_Editor* e) { return kf_move(FL_Right, e); } /** Moves the text cursor one line down for editor \p 'e'. Same as kf_move(FL_Down, e). The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_down(int, Fl_Text_Editor* e) { return kf_move(FL_Down, e); } /** Moves the text cursor up one page for editor \p 'e'. Same as kf_move(FL_Page_Up, e). The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_page_up(int, Fl_Text_Editor* e) { return kf_move(FL_Page_Up, e); } /** Moves the text cursor down one page for editor \p 'e'. Same as kf_move(FL_Page_Down, e). The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_page_down(int, Fl_Text_Editor* e) { return kf_move(FL_Page_Down, e); } /** Toggles the insert mode for editor \p 'e'. The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_insert(int, Fl_Text_Editor* e) { e->insert_mode(e->insert_mode() ? 0 : 1); return 1; } /** Does a delete of selected text or the current character in the current buffer of editor \p 'e'. The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_delete(int, Fl_Text_Editor* e) { if (!e->buffer()->selected()) { int p1 = e->insert_position(); int p2 = e->buffer()->next_char(p1); e->buffer()->select(p1, p2); } kill_selection(e); e->show_insert_position(); e->set_changed(); if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED); return 1; } /** Does a copy of selected text or the current character in the current buffer of editor \p 'e'. The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_copy(int, Fl_Text_Editor* e) { if (!e->buffer()->selected()) return 1; const char *copy = e->buffer()->selection_text(); if (*copy) Fl::copy(copy, (int) strlen(copy), 1); free((void*)copy); e->show_insert_position(); return 1; } /** Does a cut of selected text in the current buffer of editor \p 'e'. The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_cut(int c, Fl_Text_Editor* e) { kf_copy(c, e); kill_selection(e); e->set_changed(); if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED); return 1; } /** Does a paste of selected text in the current buffer of editor \p 'e'. Any current selection is replaced with the pasted content. The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_paste(int, Fl_Text_Editor* e) { kill_selection(e); Fl::paste(*e, 1); e->show_insert_position(); e->set_changed(); if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED); return 1; } /** Selects all text in the current buffer in editor \p 'e'. The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_select_all(int, Fl_Text_Editor* e) { e->buffer()->select(0, e->buffer()->length()); const char *copy = e->buffer()->selection_text(); if (*copy) Fl::copy(copy, (int) strlen(copy), 0); free((void*)copy); return 1; } /** Undo last edit in the current buffer of editor \p 'e'. Also deselects previous selection. The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_undo(int , Fl_Text_Editor* e) { e->buffer()->unselect(); Fl::copy("", 0, 0); int crsr = e->insert_position(); int ret = e->buffer()->undo(&crsr); e->insert_position(crsr); e->show_insert_position(); e->set_changed(); if (e->when()&FL_WHEN_CHANGED) e->do_callback(); return ret; } /** Redo last undo action. Also deselects previous selection. The key value \p 'c' is currently unused. */ int Fl_Text_Editor::kf_redo(int , Fl_Text_Editor* e) { e->buffer()->unselect(); Fl::copy("", 0, 0); int crsr = e->insert_position(); int ret = e->buffer()->redo(&crsr); e->insert_position(crsr); e->show_insert_position(); e->set_changed(); if (e->when()&FL_WHEN_CHANGED) e->do_callback(); return ret; } /** Handles a key press in the editor */ int Fl_Text_Editor::handle_key() { // Call FLTK's rules to try to turn this into a printing character. // This uses the right-hand ctrl key as a "compose prefix" and returns // the changes that should be made to the text, as a number of // bytes to delete and a string to insert: int del = 0; if (Fl::compose(del)) { if (del) { // del is a number of bytes int dp = insert_position() - del; if ( dp < 0 ) dp = 0; buffer()->select(dp, insert_position()); } kill_selection(this); if (Fl::event_length()) { if (insert_mode()) insert(Fl::event_text()); else overstrike(Fl::event_text()); } if (Fl::screen_driver()->has_marked_text() && Fl::compose_state) { int pos = this->insert_position(); this->buffer()->select(pos - Fl::compose_state, pos); } show_insert_position(); set_changed(); if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED); return 1; } int key = Fl::event_key(), state = Fl::event_state(), c = Fl::event_text()[0]; state &= FL_SHIFT|FL_CTRL|FL_ALT|FL_META; // only care about these states Key_Func f; f = bound_key_function(key, state, global_key_bindings); if (!f) f = bound_key_function(key, state, key_bindings); if (f == kf_undo || f == kf_redo) { // never propagate undo and redo up to another widget if (!f(key, this)) fl_beep(); return 1; } else if (f){ return f(key, this); } if (default_key_function_ && !state) return default_key_function_(c, this); return 0; } /** does or does not a callback according to changed() and when() settings */ void Fl_Text_Editor::maybe_do_callback(Fl_Callback_Reason reason) { // printf("Fl_Text_Editor::maybe_do_callback()\n"); // printf("changed()=%d, when()=%x\n", changed(), when()); if (changed() || (when()&FL_WHEN_NOT_CHANGED)) do_callback(reason); } int Fl_Text_Editor::handle(int event) { static int dndCursorPos; if (!buffer()) return 0; switch (event) { case FL_FOCUS: show_cursor(mCursorOn); // redraws the cursor if (buffer()->selected()) redraw(); // Redraw selections... Fl::focus(this); return 1; case FL_UNFOCUS: show_cursor(mCursorOn); // redraws the cursor if (Fl::screen_driver()->has_marked_text() && buffer()->selected() && Fl::compose_state) { int pos = insert_position(); buffer()->select(pos, pos); fl_reset_spot(); } if (buffer()->selected()) redraw(); // Redraw selections... // FALLTHROUGH case FL_HIDE: if (when() & FL_WHEN_RELEASE) maybe_do_callback(FL_REASON_LOST_FOCUS); return 1; case FL_KEYBOARD: if (active_r() && window() && this == Fl::belowmouse()) window()->cursor(FL_CURSOR_NONE); return handle_key(); case FL_PASTE: if (!Fl::event_text()) { fl_beep(); return 1; } buffer()->remove_selection(); if (insert_mode()) insert(Fl::event_text()); else overstrike(Fl::event_text()); show_insert_position(); set_changed(); if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED); return 1; case FL_ENTER: // MRS: Windows only? Need to test! // case FL_MOVE: show_cursor(mCursorOn); return 1; case FL_PUSH: if (Fl::event_button() == 2) { // don't let the text_display see this event if (Fl_Group::handle(event)) return 1; dragType = DRAG_NONE; if(buffer()->selected()) { buffer()->unselect(); } int pos = xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS); insert_position(pos); Fl::paste(*this, 0); Fl::focus(this); set_changed(); if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED); return 1; } if (Fl::event_button() == FL_RIGHT_MOUSE) { if (active_r() && window()) { if (Fl::event_inside(text_area.x, text_area.y, text_area.w, text_area.h)) window()->cursor(FL_CURSOR_INSERT); else window()->cursor(FL_CURSOR_DEFAULT); } if (Fl::focus() != this) { Fl::focus(this); handle(FL_FOCUS); } switch (handle_rmb(0)) { case 1: kf_cut(0, this); break; case 2: kf_copy(0, this); break; case 3: kf_paste(0, this); break; } return 1; } break; case FL_SHORTCUT: if (!(shortcut() ? Fl::test_shortcut(shortcut()) : test_shortcut())) return 0; if (Fl::visible_focus() && handle(FL_FOCUS)) { Fl::focus(this); return 1; } break; // Handle drag'n'drop attempt by the user. This is a simplified // implementation which allows dnd operations onto the scroll bars. case FL_DND_ENTER: // save the current cursor position if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); show_cursor(mCursorOn); dndCursorPos = insert_position(); /* fall through */ case FL_DND_DRAG: // show a temporary insertion cursor insert_position(xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS)); return 1; case FL_DND_LEAVE: // restore original cursor insert_position(dndCursorPos); return 1; case FL_DND_RELEASE: // keep insertion cursor and wait for the FL_PASTE event if (!dragging) buffer()->unselect(); // FL_PASTE must not destroy current selection if drag comes from outside return 1; } return Fl_Text_Display::handle(event); } /** Enables or disables Tab key focus navigation. When disabled (default), tab characters are inserted into Fl_Text_Editor. Only the mouse can change focus. This behavior is desireable when Fl_Text_Editor is used, e.g. in a source code editor. When enabled, Tab navigates focus to the next widget, and Shift-Tab navigates focus to the previous widget. This behavior is desireable when Fl_Text_Editor is used e.g. in a database input form. Currently, this method is implemented as a convenience method that adjusts the key bindings for the Tab key. This implementation detail may change in the future. Know that changing the editor's key bindings for Tab and Shift-Tab may affect tab navigation. \param [in] val If \p val is 0, Tab inserts a tab character (default).
If \p val is 1, Tab navigates widget focus. \see tab_nav(), Fl::OPTION_ARROW_FOCUS. \version 1.3.4 ABI feature */ void Fl_Text_Editor::tab_nav(int val) { if ( val ) add_key_binding(FL_Tab, 0, kf_ignore); else remove_key_binding(FL_Tab, 0); } /** Check if Tab focus navigation is enabled. If disabled (default), hitting Tab inserts a tab character into the editor buffer. If enabled, hitting Tab navigates focus to the next widget, and Shift-Tab navigates focus to the previous widget. \returns if Tab inserts tab characters or moves the focus \retval 0 Tab inserts tab characters (default) \retval 1 Tab navigation is enabled. \see tab_nav(int), Fl::OPTION_ARROW_FOCUS. \version 1.3.4 ABI feature */ int Fl_Text_Editor::tab_nav() const { return (bound_key_function(FL_Tab,0)==kf_ignore) ? 1 : 0; } fltk-1.4.3/src/Fl_Valuator.cxx0000644000175000017500000001364715004135251016351 0ustar albrechtalbrecht// // Valuator widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Base class for sliders and all other one-value "knobs" #include #include #include #include #include "flstring.h" Fl_Valuator::Fl_Valuator(int X, int Y, int W, int H, const char* L) /** Creates a new Fl_Valuator widget using the given position, size, and label string. The default boxtype is FL_NO_BOX. */ : Fl_Widget(X,Y,W,H,L) { align(FL_ALIGN_BOTTOM); when(FL_WHEN_CHANGED); value_ = 0; previous_value_ = 1; min = 0; max = 1; A = 0.0; B = 1; } const double epsilon = 4.66e-10; /** See double Fl_Valuator::step() const */ void Fl_Valuator::step(double s) { if (s < 0) s = -s; A = rint(s); B = 1; while (fabs(s-A/B) > epsilon && B<=(0x7fffffff/10)) {B *= 10; A = rint(s*B);} } /** Sets the step value to 1.0 / 10digits. Precision \p digits is limited to 0...9 to avoid internal overflow errors. Values outside this range are clamped. \note For negative values of \p digits the step value is set to \p A = 1.0 and \p B = 1, i.e. 1.0/1 = 1. */ void Fl_Valuator::precision(int digits) { if (digits > 9) digits = 9; else if (digits < 0) digits = 0; A = 1.0; for (B = 1; digits--;) B *= 10; } /** Asks for partial redraw */ void Fl_Valuator::value_damage() {damage(FL_DAMAGE_EXPOSE);} // by default do partial-redraw /** Sets the current value. The new value is \e not clamped or otherwise changed before storing it. Use clamp() or round() to modify the value before calling value(). The widget is redrawn if the new value is different than the current one. The initial value is zero. changed() will return true if the user has moved the slider, but it will be turned off by value(x) and just before doing a callback (the callback can turn it back on if desired). */ int Fl_Valuator::value(double v) { clear_changed(); if (v == value_) return 0; value_ = v; value_damage(); return 1; } /** Clamps the value, but accepts v if the previous value is not already out of range */ double Fl_Valuator::softclamp(double v) { int which = (min<=max); double p = previous_value_; if ((vmax)==which && p!=max && (p>max)!=which) return max; else return v; } // inline void Fl_Valuator::handle_push() {previous_value_ = value_;} /** Called during a drag operation, after an FL_WHEN_CHANGED event is received and before the callback. */ void Fl_Valuator::handle_drag(double v) { if (v != value_) { value_ = v; value_damage(); set_changed(); if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED); } } /** Called after an FL_WHEN_RELEASE event is received and before the callback. */ void Fl_Valuator::handle_release() { if (when()&FL_WHEN_RELEASE) { // insure changed() is off even if no callback is done. It may have // been turned on by the drag, and then the slider returned to it's // initial position: clear_changed(); // now do the callback only if slider in new position or always is on: if (value_ != previous_value_ || when() & FL_WHEN_NOT_CHANGED) { do_callback(FL_REASON_RELEASED); } } } /** Round the passed value to the nearest step increment. Does nothing if step is zero. */ double Fl_Valuator::round(double v) { if (A) return rint(v*B/A)*A/B; else return v; } /** Clamps the passed value to the valuator range.*/ double Fl_Valuator::clamp(double v) { if ((vmax)==(min<=max)) return max; else return v; } /** Adds n times the step value to the passed value. If step was set to zero it uses fabs(maximum() - minimum()) / 100. */ double Fl_Valuator::increment(double v, int n) { if (!A) return v+n*(max-min)/100; if (min > max) n = -n; return (rint(v*B/A)+n)*A/B; } /** Uses internal rules to format the fields numerical value into the character array pointed to by the passed parameter. The actual format used depends on the current step value. If the step value has been set to zero then a \%g format is used. If the step value is non-zero, then a \%.*f format is used, where the precision is calculated to show sufficient digits for the current step value. An integer step value, such as 1 or 1.0, gives a precision of 0, so the formatted value will appear as an integer. This method is used by the Fl_Valuator_... group of widgets to format the current value into a text string. The return value is the length of the formatted text. The formatted value is written into \p buffer. \p buffer should have space for at least 128 bytes. You may override this function to create your own text formatting. */ int Fl_Valuator::format(char* buffer) { double v = value(); // MRS: THIS IS A HACK - RECOMMEND ADDING BUFFER SIZE ARGUMENT if (!A || !B) return snprintf(buffer, 128, "%g", v); // Figure out how many digits are required to correctly format the // value. int i, c = 0; char temp[32]; // output a number with many digits after the decimal point. This // seems to be needed to get high precission snprintf(temp, sizeof(temp), "%.12f", A/B); // strip all trailing 0's for (i=(int) strlen(temp)-1; i>0; i--) { if (temp[i]!='0') break; } // count digits until we find the decimal point (or comma or whatever // letter is set in the current locale) for (; i>0; i--, c++) { if (!isdigit(temp[i])) break; } // MRS: THIS IS A HACK - RECOMMEND ADDING BUFFER SIZE ARGUMENT return snprintf(buffer, 128, "%.*f", c, v); } fltk-1.4.3/src/Fl_Menu_Window.cxx0000644000175000017500000000217315004135251016777 0ustar albrechtalbrecht// // Menu window code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // This is the window type used by Fl_Menu to make the pop-ups. // It draws in the overlay planes if possible. // Also here is the implementation of the mouse & keyboard grab, // which are used so that clicks outside the program's windows // can be used to dismiss the menus. #include #include "Fl_Window_Driver.H" /** Destroys the window and all of its children.*/ Fl_Menu_Window::~Fl_Menu_Window() { hide(); } Fl_Menu_Window::Fl_Menu_Window(int W, int H, const char *l) : Fl_Single_Window(W,H,l) { image(0); } Fl_Menu_Window::Fl_Menu_Window(int X, int Y, int W, int H, const char *l) : Fl_Single_Window(X,Y,W,H,l) { image(0); } fltk-1.4.3/src/Fl_Help_View.cxx0000644000175000017500000032000415004135251016422 0ustar albrechtalbrecht// // Fl_Help_View widget for the Fast Light Tool Kit (FLTK). // // Copyright 1997-2010 by Easy Software Products. // Image support by Matthias Melcher, Copyright 2000-2009. // // Buffer management (HV_Edit_Buffer) and more by AlbrechtS and others. // Copyright 2011-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // Fl_Help_View::add_block() - Add a text block to the list. // Fl_Help_View::add_link() - Add a new link to the list. // Fl_Help_View::add_target() - Add a new target to the list. // Fl_Help_View::compare_targets() - Compare two targets. // Fl_Help_View::do_align() - Compute the alignment for a line in a block. // Fl_Help_View::draw() - Draw the Fl_Help_View widget. // Fl_Help_View::format() - Format the help text. // Fl_Help_View::format_table() - Format a table... // Fl_Help_View::free_data() - Free memory used for the document. // Fl_Help_View::get_align() - Get an alignment attribute. // Fl_Help_View::get_attr() - Get an attribute value from the string. // Fl_Help_View::get_color() - Get an alignment attribute. // Fl_Help_View::handle() - Handle events in the widget. // Fl_Help_View::Fl_Help_View() - Build a Fl_Help_View widget. // Fl_Help_View::~Fl_Help_View() - Destroy a Fl_Help_View widget. // Fl_Help_View::load() - Load the specified file. // Fl_Help_View::resize() - Resize the help widget. // Fl_Help_View::topline() - Set the top line to the named target. // Fl_Help_View::topline() - Set the top line by number. // Fl_Help_View::value() - Set the help text directly. // scrollbar_callback() - A callback for the scrollbar. // // // Include necessary header files... // #include #include #include #include #include #include "Fl_Int_Vector.H" #include "Fl_String.H" #include #include #include #include // fl_open_uri() #include // fl_strdup() #include "flstring.h" #include #include #include #define MAX_COLUMNS 200 // // Typedef the C API sort function type the only way I know how... // extern "C" { typedef int (*compare_func_t)(const void *, const void *); } // // Local functions... // static int quote_char(const char *); static void scrollbar_callback(Fl_Widget *s, void *); static void hscrollbar_callback(Fl_Widget *s, void *); // This function skips 'n' bytes *within* a string, i.e. it checks // for a NUL byte as string terminator. // If a NUL byte is found before 'n' bytes have been scanned it returns // a pointer to the end of the string (the NUL byte). // This avoids pure pointer arithmetic that would potentially overrun // the end of the string (buffer), see GitHub Issue #1196. // // Note: this should be rewritten and improved in FLTK 1.5.0 or later // by using std::string etc.. static char *skip_bytes(const char *p, int n) { for (int i = 0; i < n; ++i) { if (*p == '\0') break; ++p; } return const_cast(p); } // // global flag for image loading (see get_image). // static char initial_load = 0; // // Broken image... // static const char * const broken_xpm[] = { "16 24 4 1", "@ c #000000", " c #ffffff", "+ c none", "x c #ff0000", // pixels "@@@@@@@+++++++++", "@ @++++++++++", "@ @+++++++++++", "@ @++@++++++++", "@ @@+++++++++", "@ @+++@+++++", "@ @++@@++++@", "@ xxx @@ @++@@", "@ xxx xx@@ @", "@ xxx xxx @", "@ xxxxxx @", "@ xxxx @", "@ xxxxxx @", "@ xxx xxx @", "@ xxx xxx @", "@ xxx xxx @", "@ @", "@ @", "@ @", "@ @", "@ @", "@ @", "@ @", "@@@@@@@@@@@@@@@@", NULL }; static Fl_Pixmap broken_image(broken_xpm); /** [this text may be customized at run-time] */ const char *Fl_Help_View::copy_menu_text = "Copy"; static Fl_Menu_Item rmb_menu[] = { { NULL, 0, NULL, (void*)1 }, // Copy { NULL } }; // // Simple margin stack for Fl_Help_View::format()... // struct fl_margins { int depth_; int margins_[100]; fl_margins() { clear(); } int clear() { // puts("fl_margins::clear()"); depth_ = 0; return margins_[0] = 4; } int current() { return margins_[depth_]; } int pop() { // printf("fl_margins::pop(): depth_=%d, xx=%d\n", depth_, // depth_ > 0 ? margins_[depth_ - 1] : 4); if (depth_ > 0) { depth_ --; return margins_[depth_]; } else return 4; } int push(int indent) { int xx; xx = margins_[depth_] + indent; // printf("fl_margins::push(indent=%d): depth_=%d, xx=%d\n", indent, // depth_ + 1, xx); if (depth_ < 99) { depth_ ++; margins_[depth_] = xx; } return xx; } }; // // All the stuff needed to implement text selection in Fl_Help_View // /* matt: * We are trying to keep binary compatibility with previous versions * of FLTK. This means that we are limited to adding static variables * only to not enlarge the Fl_Help_View class. Lucky for us, only one * text can be selected system wide, so we can remember the selection * in a single set of variables. * * Still to do: * - &word; style characters mess up our count inside a word boundary * - we can only select words, no individual characters * - no dragging of the selection into another widget * - selection must be cleared if another widget get focus! * - write a comment for every new function */ /* The following functions are also used to draw stuff and should be replaced with local copies that are much faster when merely counting: fl_color(Fl_Color); fl_rectf(int, int, int, int); fl_push_clip(int, int, int, int); fl_xyline(int, int, int); fl_rect() fl_line() img->draw() */ // We don't put the offscreen buffer in the help view class because // we'd need to include platform.H in the header... static Fl_Offscreen fl_help_view_buffer; int Fl_Help_View::selection_first_ = 0; int Fl_Help_View::selection_last_ = 0; int Fl_Help_View::selection_push_first_ = 0; int Fl_Help_View::selection_push_last_ = 0; int Fl_Help_View::selection_drag_first_ = 0; int Fl_Help_View::selection_drag_last_ = 0; int Fl_Help_View::selected_ = 0; int Fl_Help_View::draw_mode_ = 0; int Fl_Help_View::mouse_x_ = 0; int Fl_Help_View::mouse_y_ = 0; int Fl_Help_View::current_pos_ = 0; Fl_Help_View *Fl_Help_View::current_view_ = 0L; Fl_Color Fl_Help_View::hv_selection_color_; Fl_Color Fl_Help_View::hv_selection_text_color_; /* * This function must be optimized for speed! */ void Fl_Help_View::hv_draw(const char *t, int x, int y, int entity_extra_length) { if (selected_ && current_view_==this && current_pos_=selection_first_) { Fl_Color c = fl_color(); fl_color(hv_selection_color_); int w = (int)fl_width(t); if (current_pos_+(int)strlen(t)=x && mouse_x_=y-fl_height()+fl_descent()&&mouse_y_<=y+fl_descent()) { int f = (int) current_pos_; int l = (int) (f+strlen(t)); // use 'quote_char' to calculate the true length of the HTML string if (draw_mode_==1) { selection_push_first_ = f; selection_push_last_ = l; } else { selection_drag_first_ = f; selection_drag_last_ = l + entity_extra_length; } } } } } // [Internal class HV_Edit_Buffer] // Debug: set to 1 for basic debugging, 2 for more, 0 for none #define DEBUG_EDIT_BUFFER 0 #if (DEBUG_EDIT_BUFFER > 1) #define DEBUG_FUNCTION(L,F) \ printf("\n========\n [%d] --- %s\n========\n", L, F); \ fflush(stdout); #else #define DEBUG_FUNCTION(L,F) #endif /* Note: Don't use Doxygen docs for this internal class. Internal class to manage the Fl_Help_View edit buffer. This is a subclass of Fl_String since FLTK 1.4.0. This class is for internal use in this file. Its sole purpose is to allow buffer management to avoid buffer overflows in stack variables used to edit strings for formatting and drawing (STR #3275). */ class HV_Edit_Buffer : public Fl_String { public: // use default constructor and destructor, none defined here // append a Unicode character (Code Point) to the string void add(int ucs); // case insensitive comparison of buffer contents with a string int cmp(const char *str) { return !strcasecmp(c_str(), str); } // string width of the entire buffer contents int width() { return (int)fl_width(c_str()); } #if (DEBUG_EDIT_BUFFER) void print(const char *text = ""); #endif }; /* Append one Unicode character (code point) to the buffer. The Unicode character \p ucs is converted to UTF-8 and appended to the buffer. \param[in] ucs Unicode character (code point) to be added */ void HV_Edit_Buffer::add(int ucs) { int len; char cbuf[6]; len = fl_utf8encode((unsigned int)ucs, cbuf); if (len < 1) len = 1; append(cbuf, len); } // add(int ucs) /* Print the edit buffer (Debug only). */ #if (DEBUG_EDIT_BUFFER) void HV_Edit_Buffer::print(const char *text) { printf("HV_Edit_Buffer::print(%s), capacity=%d, size=%d\n", text, capacity(), size()); printf(" \"%s\"\n", c_str() && size() ? c_str() : ""); fflush(stdout); } // print() #endif // [End of internal class HV_Edit_Buffer] /** Adds a text block to the list. */ Fl_Help_Block * // O - Pointer to new block Fl_Help_View::add_block(const char *s, // I - Pointer to start of block text int xx, // I - X position of block int yy, // I - Y position of block int ww, // I - Right margin of block int hh, // I - Height of block unsigned char border) // I - Draw border? { Fl_Help_Block *temp; // New block // printf("add_block(s = %p, xx = %d, yy = %d, ww = %d, hh = %d, border = %d)\n", // s, xx, yy, ww, hh, border); if (nblocks_ >= ablocks_) { ablocks_ += 16; if (ablocks_ == 16) blocks_ = (Fl_Help_Block *)malloc(sizeof(Fl_Help_Block) * ablocks_); else blocks_ = (Fl_Help_Block *)realloc(blocks_, sizeof(Fl_Help_Block) * ablocks_); } temp = blocks_ + nblocks_; memset(temp, 0, sizeof(Fl_Help_Block)); temp->start = s; temp->end = s; temp->x = xx; temp->y = yy; temp->w = ww; temp->h = hh; temp->border = border; temp->bgcolor = bgcolor_; nblocks_ ++; return (temp); } /** Adds a new link to the list. */ void Fl_Help_View::add_link(const char *n, // I - Name of link int xx, // I - X position of link int yy, // I - Y position of link int ww, // I - Width of link text int hh) // I - Height of link text { Fl_Help_Link *temp; // New link char *target; // Pointer to target name if (nlinks_ >= alinks_) { alinks_ += 16; if (alinks_ == 16) links_ = (Fl_Help_Link *)malloc(sizeof(Fl_Help_Link) * alinks_); else links_ = (Fl_Help_Link *)realloc(links_, sizeof(Fl_Help_Link) * alinks_); } temp = links_ + nlinks_; temp->x = xx; temp->y = yy; temp->w = xx + ww; temp->h = yy + hh; strlcpy(temp->filename, n, sizeof(temp->filename)); if ((target = strrchr(temp->filename, '#')) != NULL) { *target++ = '\0'; strlcpy(temp->name, target, sizeof(temp->name)); } else temp->name[0] = '\0'; nlinks_ ++; } /** Adds a new target to the list. */ void Fl_Help_View::add_target(const char *n, // I - Name of target int yy) // I - Y position of target { Fl_Help_Target *temp; // New target if (ntargets_ >= atargets_) { atargets_ += 16; if (atargets_ == 16) targets_ = (Fl_Help_Target *)malloc(sizeof(Fl_Help_Target) * atargets_); else targets_ = (Fl_Help_Target *)realloc(targets_, sizeof(Fl_Help_Target) * atargets_); } temp = targets_ + ntargets_; temp->y = yy; strlcpy(temp->name, n, sizeof(temp->name)); ntargets_ ++; } /** Compares two targets.*/ int // O - Result of comparison Fl_Help_View::compare_targets(const Fl_Help_Target *t0, // I - First target const Fl_Help_Target *t1) // I - Second target { return (strcasecmp(t0->name, t1->name)); } /** Computes the alignment for a line in a block.*/ int // O - New line Fl_Help_View::do_align(Fl_Help_Block *block, // I - Block to add to int line, // I - Current line int xx, // I - Current X position int a, // I - Current alignment int &l) // IO - Starting link { int offset; // Alignment offset switch (a) { case RIGHT : // Right align offset = block->w - xx; break; case CENTER : // Center offset = (block->w - xx) / 2; break; default : // Left align offset = 0; break; } block->line[line] = block->x + offset; if (line < 31) line ++; while (l < nlinks_) { links_[l].x += offset; links_[l].w += offset; l ++; } return (line); } /** Draws the Fl_Help_View widget. */ void Fl_Help_View::draw() { int i; // Looping var const Fl_Help_Block *block; // Pointer to current block const char *ptr, // Pointer to text in block *attrs; // Pointer to start of element attributes HV_Edit_Buffer buf; // Text buffer char attr[1024]; // Attribute buffer int xx, yy, ww, hh; // Current positions and sizes int line; // Current line Fl_Font font; Fl_Fontsize fsize; // Current font and size Fl_Color fcolor; // current font color int head, pre, // Flags for text needspace; // Do we need whitespace? Fl_Boxtype b = box() ? box() : FL_DOWN_BOX; // Box to draw... int underline, // Underline text? xtra_ww; // Extra width for underlined space between words DEBUG_FUNCTION(__LINE__,__FUNCTION__); // Draw the scrollbar(s) and box first... ww = w(); hh = h(); i = 0; draw_box(b, x(), y(), ww, hh, bgcolor_); if ( hscrollbar_.visible() || scrollbar_.visible() ) { int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size(); int hor_vis = hscrollbar_.visible(); int ver_vis = scrollbar_.visible(); // Scrollbar corner int scorn_x = x() + ww - (ver_vis?scrollsize:0) - Fl::box_dw(b) + Fl::box_dx(b); int scorn_y = y() + hh - (hor_vis?scrollsize:0) - Fl::box_dh(b) + Fl::box_dy(b); if ( hor_vis ) { if ( hscrollbar_.h() != scrollsize ) { // scrollsize changed? hscrollbar_.resize(x(), scorn_y, scorn_x - x(), scrollsize); init_sizes(); } draw_child(hscrollbar_); hh -= scrollsize; } if ( ver_vis ) { if ( scrollbar_.w() != scrollsize ) { // scrollsize changed? scrollbar_.resize(scorn_x, y(), scrollsize, scorn_y - y()); init_sizes(); } draw_child(scrollbar_); ww -= scrollsize; } if ( hor_vis && ver_vis ) { // Both scrollbars visible? Draw little gray box in corner fl_color(FL_GRAY); fl_rectf(scorn_x, scorn_y, scrollsize, scrollsize); } } if (!value_) return; if (current_view_ == this && selected_) { hv_selection_color_ = FL_SELECTION_COLOR; hv_selection_text_color_ = fl_contrast(textcolor_, FL_SELECTION_COLOR); } current_pos_ = 0; // Clip the drawing to the inside of the box... fl_push_clip(x() + Fl::box_dx(b), y() + Fl::box_dy(b), ww - Fl::box_dw(b), hh - Fl::box_dh(b)); fl_color(textcolor_); // Draw all visible blocks... for (i = 0, block = blocks_; i < nblocks_; i ++, block ++) if ((block->y + block->h) >= topline_ && block->y < (topline_ + h())) { line = 0; xx = block->line[line]; yy = block->y - topline_; hh = 0; pre = 0; head = 0; needspace = 0; underline = 0; initfont(font, fsize, fcolor); // byte length difference between html entity (encoded by &...;) and // UTF-8 encoding of same character int entity_extra_length = 0; for (ptr = block->start, buf.clear(); ptr < block->end;) { if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0) { if (!head && !pre) { // Check width... ww = buf.width(); if (needspace && xx > block->x) xx += (int)fl_width(' '); if ((xx + ww) > block->w) { if (line < 31) line ++; xx = block->line[line]; yy += hh; hh = 0; } hv_draw(buf.c_str(), xx + x() - leftline_, yy + y(), entity_extra_length); buf.clear(); entity_extra_length = 0; if (underline) { xtra_ww = isspace((*ptr)&255)?(int)fl_width(' '):0; fl_xyline(xx + x() - leftline_, yy + y() + 1, xx + x() - leftline_ + ww + xtra_ww); } current_pos_ = (int) (ptr-value_); xx += ww; if ((fsize + 2) > hh) hh = fsize + 2; needspace = 0; } else if (pre) { while (isspace((*ptr)&255)) { if (*ptr == '\n') { hv_draw(buf.c_str(), xx + x() - leftline_, yy + y()); if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1, xx + x() - leftline_ + buf.width()); buf.clear(); current_pos_ = (int) (ptr-value_); if (line < 31) line ++; xx = block->line[line]; yy += hh; hh = fsize + 2; } else if (*ptr == '\t') { // Do tabs every 8 columns... buf += ' '; // add at least one space while (buf.size() & 7) buf += ' '; } else { buf += ' '; } if ((fsize + 2) > hh) hh = fsize + 2; ptr ++; } if (buf.size() > 0) { hv_draw(buf.c_str(), xx + x() - leftline_, yy + y()); ww = buf.width(); buf.clear(); if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1, xx + x() - leftline_ + ww); xx += ww; current_pos_ = (int) (ptr-value_); } needspace = 0; } else { buf.clear(); while (isspace((*ptr)&255)) ptr ++; current_pos_ = (int) (ptr-value_); } } if (*ptr == '<') { ptr ++; if (strncmp(ptr, "!--", 3) == 0) { // Comment... ptr += 3; if ((ptr = strstr(ptr, "-->")) != NULL) { ptr += 3; continue; } else break; } while (*ptr && *ptr != '>' && !isspace((*ptr)&255)) buf += *ptr++; attrs = ptr; while (*ptr && *ptr != '>') ptr ++; if (*ptr == '>') ptr ++; // end of command reached, set the supposed start of printed eord here current_pos_ = (int) (ptr-value_); if (buf.cmp("HEAD")) head = 1; else if (buf.cmp("BR")) { if (line < 31) line ++; xx = block->line[line]; yy += hh; hh = 0; } else if (buf.cmp("HR")) { fl_line(block->x + x(), yy + y(), block->w + x(), yy + y()); if (line < 31) line ++; xx = block->line[line]; yy += 2 * fsize;//hh; hh = 0; } else if (buf.cmp("CENTER") || buf.cmp("P") || buf.cmp("H1") || buf.cmp("H2") || buf.cmp("H3") || buf.cmp("H4") || buf.cmp("H5") || buf.cmp("H6") || buf.cmp("UL") || buf.cmp("OL") || buf.cmp("DL") || buf.cmp("LI") || buf.cmp("DD") || buf.cmp("DT") || buf.cmp("PRE")) { if (tolower(buf[0]) == 'h') { font = FL_HELVETICA_BOLD; fsize = textsize_ + '7' - buf[1]; } else if (buf.cmp("DT")) { font = textfont_ | FL_ITALIC; fsize = textsize_; } else if (buf.cmp("PRE")) { font = FL_COURIER; fsize = textsize_; pre = 1; } if (buf.cmp("LI")) { if (block->ol) { char buf[10]; snprintf(buf, sizeof(buf), "%d. ", block->ol_num); hv_draw(buf, xx - (int)fl_width(buf) + x() - leftline_, yy + y()); } else { // draw bullet (•) Unicode: U+2022, UTF-8 (hex): e2 80 a2 unsigned char bullet[4] = { 0xe2, 0x80, 0xa2, 0x00 }; hv_draw((char *)bullet, xx - fsize + x() - leftline_, yy + y()); } } pushfont(font, fsize); buf.clear(); } else if (buf.cmp("A") && get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL) { fl_color(linkcolor_); underline = 1; } else if (buf.cmp("/A")) { fl_color(textcolor_); underline = 0; } else if (buf.cmp("FONT")) { if (get_attr(attrs, "COLOR", attr, sizeof(attr)) != NULL) { textcolor_ = get_color(attr, textcolor_); } if (get_attr(attrs, "FACE", attr, sizeof(attr)) != NULL) { if (!strncasecmp(attr, "helvetica", 9) || !strncasecmp(attr, "arial", 5) || !strncasecmp(attr, "sans", 4)) font = FL_HELVETICA; else if (!strncasecmp(attr, "times", 5) || !strncasecmp(attr, "serif", 5)) font = FL_TIMES; else if (!strncasecmp(attr, "symbol", 6)) font = FL_SYMBOL; else font = FL_COURIER; } if (get_attr(attrs, "SIZE", attr, sizeof(attr)) != NULL) { if (isdigit(attr[0] & 255)) { // Absolute size fsize = (int)(textsize_ * pow(1.2, atof(attr) - 3.0)); } else { // Relative size fsize = (int)(fsize * pow(1.2, atof(attr) - 3.0)); } } pushfont(font, fsize); } else if (buf.cmp("/FONT")) { popfont(font, fsize, textcolor_); } else if (buf.cmp("U")) underline = 1; else if (buf.cmp("/U")) underline = 0; else if (buf.cmp("B") || buf.cmp("STRONG")) pushfont(font |= FL_BOLD, fsize); else if (buf.cmp("TD") || buf.cmp("TH")) { int tx, ty, tw, th; if (tolower(buf[1]) == 'h') pushfont(font |= FL_BOLD, fsize); else pushfont(font = textfont_, fsize); tx = block->x - 4 - leftline_; ty = block->y - topline_ - fsize - 3; tw = block->w - block->x + 7; th = block->h + fsize - 5; if (tx < 0) { tw += tx; tx = 0; } if (ty < 0) { th += ty; ty = 0; } tx += x(); ty += y(); if (block->bgcolor != bgcolor_) { fl_color(block->bgcolor); fl_rectf(tx, ty, tw, th); fl_color(textcolor_); } if (block->border) fl_rect(tx, ty, tw, th); } else if (buf.cmp("I") || buf.cmp("EM")) pushfont(font |= FL_ITALIC, fsize); else if (buf.cmp("CODE") || buf.cmp("TT")) pushfont(font = FL_COURIER, fsize); else if (buf.cmp("KBD")) pushfont(font = FL_COURIER_BOLD, fsize); else if (buf.cmp("VAR")) pushfont(font = FL_COURIER_ITALIC, fsize); else if (buf.cmp("/HEAD")) head = 0; else if (buf.cmp("/H1") || buf.cmp("/H2") || buf.cmp("/H3") || buf.cmp("/H4") || buf.cmp("/H5") || buf.cmp("/H6") || buf.cmp("/B") || buf.cmp("/STRONG") || buf.cmp("/I") || buf.cmp("/EM") || buf.cmp("/CODE") || buf.cmp("/TT") || buf.cmp("/KBD") || buf.cmp("/VAR")) popfont(font, fsize, fcolor); else if (buf.cmp("/PRE")) { popfont(font, fsize, fcolor); pre = 0; } else if (buf.cmp("IMG")) { Fl_Shared_Image *img = 0; int width, height; char wattr[8], hattr[8]; get_attr(attrs, "WIDTH", wattr, sizeof(wattr)); get_attr(attrs, "HEIGHT", hattr, sizeof(hattr)); width = get_length(wattr); height = get_length(hattr); if (get_attr(attrs, "SRC", attr, sizeof(attr))) { img = get_image(attr, width, height); if (!width) width = img->w(); if (!height) height = img->h(); } if (!width || !height) { if (get_attr(attrs, "ALT", attr, sizeof(attr)) == NULL) { strcpy(attr, "IMG"); } } ww = width; if (needspace && xx > block->x) xx += (int)fl_width(' '); if ((xx + ww) > block->w) { if (line < 31) line ++; xx = block->line[line]; yy += hh; hh = 0; } if (img) { img->draw(xx + x() - leftline_, yy + y() - fl_height() + fl_descent() + 2); } xx += ww; if ((height + 2) > hh) hh = height + 2; needspace = 0; } buf.clear(); } else if (*ptr == '\n' && pre) { hv_draw(buf.c_str(), xx + x() - leftline_, yy + y()); buf.clear(); if (line < 31) line ++; xx = block->line[line]; yy += hh; hh = fsize + 2; needspace = 0; ptr ++; current_pos_ = (int) (ptr-value_); } else if (isspace((*ptr)&255)) { if (pre) { if (*ptr == ' ') buf += ' '; else { // Do tabs every 8 columns... buf += ' '; // at least one space while (buf.size() & 7) buf += ' '; } } ptr ++; if (!pre) current_pos_ = (int) (ptr-value_); needspace = 1; } else if (*ptr == '&') // process html entity { ptr ++; int qch = quote_char(ptr); if (qch < 0) buf += '&'; else { int utf8l = buf.size(); buf.add(qch); utf8l = buf.size() - utf8l; // length of added UTF-8 text const char *oldptr = ptr; ptr = strchr(ptr, ';') + 1; entity_extra_length += int(ptr - (oldptr-1)) - utf8l; // extra length between html entity and UTF-8 } if ((fsize + 2) > hh) hh = fsize + 2; } else { buf += *ptr++; if ((fsize + 2) > hh) hh = fsize + 2; } } if (buf.size() > 0 && !pre && !head) { ww = buf.width(); if (needspace && xx > block->x) xx += (int)fl_width(' '); if ((xx + ww) > block->w) { if (line < 31) line ++; xx = block->line[line]; yy += hh; hh = 0; } } if (buf.size() > 0 && !head) { hv_draw(buf.c_str(), xx + x() - leftline_, yy + y()); if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1, xx + x() - leftline_ + ww); current_pos_ = (int) (ptr-value_); } } fl_pop_clip(); } // draw() // In an html style text, set the character pointer p, skipping anything from a // leading '<' up to and including the closing '>'. If the end of the buffer is // reached, the function returns `end`. // No need to handle UTF-8 here. // // \param[in] p pointer to html text, UTF-8 characters possible // \param[in] end pointer to the end of the text (need nut be NUL) // \return new pointer to text after skipping over '<...>' blocks, or `end` // if NUL was found or a '<...>' block was not closed. static const char *vanilla(const char *p, const char *end) { if (*p == '\0' || p >= end) return end; for (;;) { if (*p != '<') { return p; } else { while (*p && p < end && *p != '>') p++; } p++; if (*p == '\0' || p >= end) return end; } } /** Finds the specified string \p s at starting position \p p. The argument \p p and the return value are offsets in Fl_Help_View::value(), counting from 0. If \p p is out of range, 0 is used. The string comparison is simple but honors some special cases: - the specified string \p s must be in UTF-8 encoding - HTML tags in value() are filtered (not compared as such, they never match) - HTML entities like '\<' or '\&x#20ac;' are converted to Unicode (UTF-8) - ASCII characters (7-bit, \< 0x80) are compared case insensitive - every newline (LF, '\\n') in value() is treated like a single space - all other strings are compared as-is (byte by byte) \param[in] s search string in UTF-8 encoding \param[in] p starting position for search (0,...), Default = 0 \return the matching position or -1 if not found */ int // O - Matching position or -1 if not found Fl_Help_View::find(const char *s, // I - String to find int p) // I - Starting position { int i, // Looping var c; // Current character Fl_Help_Block *b; // Current block const char *bp, // Block matching pointer *bs, // Start of current comparison *sp; // Search string pointer DEBUG_FUNCTION(__LINE__,__FUNCTION__); // Range check input and value... if (!s || !value_) return -1; if (p < 0 || p >= (int)strlen(value_)) p = 0; // Look for the string... for (i = nblocks_, b = blocks_; i > 0; i--, b++) { if (b->end < (value_ + p)) continue; if (b->start < (value_ + p)) bp = value_ + p; else bp = b->start; bp = vanilla(bp, b->end); if (bp == b->end) continue; for (sp = s, bs = bp; *sp && *bp && bp < b->end; ) { bool is_html_entity = false; if (*bp == '&') { // decode HTML entity... if ((c = quote_char(bp + 1)) < 0) { c = '&'; } else { const char *entity_end = strchr(bp + 1, ';'); if (entity_end) { is_html_entity = true; // c contains the unicode character bp = entity_end; } else { c = '&'; } } } else { c = *bp; } if (c == '\n') c = ' '; // treat newline as a single space // *FIXME* *UTF-8* (A.S. 02/14/2016) // At this point c may be an arbitrary Unicode Code Point corresponding // to a quoted character (see above), i.e. it _can_ be a multi byte // UTF-8 sequence and must be compared with the corresponding // multi byte string in (*sp)... // For instance: "€" == 0x20ac -> 0xe2 0x82 0xac (UTF-8: 3 bytes). // Hint: use fl_utf8encode() [see below] int utf_len = 1; if (c > 0x20 && c < 0x80 && tolower(*sp) == tolower(c)) { // Check for ASCII case insensitive match. //printf("%ld text match %c/%c\n", bp-value_, *sp, c); sp++; bp = vanilla(bp+1, b->end); } else if (is_html_entity && fl_utf8decode(sp, NULL, &utf_len) == (unsigned int)c ) { // Check if a < entity ini html matches a UTF-8 character in the // search string. //printf("%ld unicode match 0x%02X 0x%02X\n", bp-value_, *sp, c); sp += utf_len; bp = vanilla(bp+1, b->end); } else if (*sp == c) { // Check if UTF-8 bytes in html and the search string match. //printf("%ld binary match %c/%c\n", bp-value_, *sp, c); sp++; bp = vanilla(bp+1, b->end); } else { // No match, so reset to start of search... . //printf("reset search (%c/%c)\n", *sp, c); sp = s; bp = bs = vanilla(bs+1, b->end); } } if (!*sp) { // Found a match! topline(b->y - b->h); return int(bs - value_); } } // No match! return (-1); } /** Formats the help text. */ void Fl_Help_View::format() { int i; // Looping var int done; // Are we done yet? Fl_Help_Block *block, // Current block *cell; // Current table cell int cells[MAX_COLUMNS], // Cells in the current row... row; // Current table row (block number) const char *ptr, // Pointer into block *start, // Pointer to start of element *attrs; // Pointer to start of element attributes HV_Edit_Buffer buf; // Text buffer char attr[1024], // Attribute buffer wattr[1024], // Width attribute buffer hattr[1024], // Height attribute buffer linkdest[1024]; // Link destination int xx, yy, ww, hh; // Size of current text fragment int line; // Current line in block int links; // Links for current line Fl_Font font; Fl_Fontsize fsize; // Current font and size Fl_Color fcolor; // Current font color unsigned char border; // Draw border? int talign, // Current alignment newalign, // New alignment head, // In the section? pre, //

 text?
                needspace;      // Do we need whitespace?
  int           table_width,    // Width of table
                table_offset;   // Offset of table
  int           column,         // Current table column number
                columns[MAX_COLUMNS];
                                // Column widths
  Fl_Color      tc, rc;         // Table/row background color
  Fl_Boxtype    b = box() ? box() : FL_DOWN_BOX;
                                // Box to draw...
  fl_margins    margins;        // Left margin stack...
  Fl_Int_Vector OL_num;         // if nonnegative, in OL mode and this is the item number

  OL_num.push_back(-1);

  DEBUG_FUNCTION(__LINE__,__FUNCTION__);

  // Reset document width...
  int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
  hsize_ = w() - scrollsize - Fl::box_dw(b);

  done = 0;
  while (!done)
  {
    // Reset state variables...
    done       = 1;
    nblocks_   = 0;
    nlinks_    = 0;
    ntargets_  = 0;
    size_      = 0;
    bgcolor_   = color();
    textcolor_ = textcolor();
    linkcolor_ = fl_contrast(FL_BLUE, color());

    tc = rc = bgcolor_;

    strcpy(title_, "Untitled");

    if (!value_)
      return;

    // Setup for formatting...
    initfont(font, fsize, fcolor);

    line         = 0;
    links        = 0;
    xx           = margins.clear();
    yy           = fsize + 2;
    ww           = 0;
    column       = 0;
    border       = 0;
    hh           = 0;
    block        = add_block(value_, xx, yy, hsize_, 0);
    row          = 0;
    head         = 0;
    pre          = 0;
    talign       = LEFT;
    newalign     = LEFT;
    needspace    = 0;
    linkdest[0]  = '\0';
    table_offset = 0;

    // Html text character loop
    for (ptr = value_, buf.clear(); *ptr;)
    {
      // End of word?
      if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0)
      {
        // Get width of word parsed so far...
        ww = buf.width();

        if (!head && !pre)
        {
          // Check width...
          if (ww > hsize_) {
            hsize_ = ww;
            done   = 0;
            break;
          }

          if (needspace && xx > block->x)
            ww += (int)fl_width(' ');

  //        printf("line = %d, xx = %d, ww = %d, block->x = %d, block->w = %d\n",
  //           line, xx, ww, block->x, block->w);

          if ((xx + ww) > block->w)
          {
            line     = do_align(block, line, xx, newalign, links);
            xx       = block->x;
            yy       += hh;
            block->h += hh;
            hh       = 0;
          }

          if (linkdest[0])
            add_link(linkdest, xx, yy - fsize, ww, fsize);

          xx += ww;
          if ((fsize + 2) > hh)
            hh = fsize + 2;

          needspace = 0;
        }
        else if (pre)
        {
          // Add a link as needed...
          if (linkdest[0])
            add_link(linkdest, xx, yy - hh, ww, hh);

          xx += ww;
          if ((fsize + 2) > hh)
            hh = fsize + 2;

          // Handle preformatted text...
          while (isspace((*ptr)&255))
          {
            if (*ptr == '\n')
            {
              if (xx > hsize_) break;

              line     = do_align(block, line, xx, newalign, links);
              xx       = block->x;
              yy       += hh;
              block->h += hh;
              hh       = fsize + 2;
            }
            else
              xx += (int)fl_width(' ');

            if ((fsize + 2) > hh)
              hh = fsize + 2;

            ptr ++;
          }

          if (xx > hsize_) {
            hsize_ = xx;
            done   = 0;
            break;
          }

          needspace = 0;
        }
        else
        {
          // Handle normal text or stuff in the  section...
          while (isspace((*ptr)&255))
            ptr ++;
        }

        buf.clear();
      }

      if (*ptr == '<')
      {
        // Handle html tags..
        start = ptr;
        ptr ++;

        if (strncmp(ptr, "!--", 3) == 0)
        {
          // Comment...
          ptr += 3;
          if ((ptr = strstr(ptr, "-->")) != NULL)
          {
            ptr += 3;
            continue;
          }
          else
            break;
        }

        while (*ptr && *ptr != '>' && !isspace((*ptr)&255))
          buf += *ptr++;

        attrs = ptr;
        while (*ptr && *ptr != '>')
          ptr ++;

        if (*ptr == '>')
          ptr ++;

        if (buf.cmp("HEAD"))
          head = 1;
        else if (buf.cmp("/HEAD"))
          head = 0;
        else if (buf.cmp("TITLE"))
        {
          // Copy the title in the document...
          char *st;
          for (st = title_;
               *ptr != '<' && *ptr && st < (title_ + sizeof(title_) - 1);
               *st++ = *ptr++) {/*empty*/}

          *st = '\0';
          buf.clear();
        }
        else if (buf.cmp("A"))
        {
          if (get_attr(attrs, "NAME", attr, sizeof(attr)) != NULL)
            add_target(attr, yy - fsize - 2);

          if (get_attr(attrs, "HREF", attr, sizeof(attr)) != NULL)
            strlcpy(linkdest, attr, sizeof(linkdest));
        }
        else if (buf.cmp("/A"))
          linkdest[0] = '\0';
        else if (buf.cmp("BODY"))
        {
          bgcolor_   = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)),
                                 color());
          textcolor_ = get_color(get_attr(attrs, "TEXT", attr, sizeof(attr)),
                                 textcolor());
          linkcolor_ = get_color(get_attr(attrs, "LINK", attr, sizeof(attr)),
                                 fl_contrast(FL_BLUE, color()));
        }
        else if (buf.cmp("BR"))
        {
          line     = do_align(block, line, xx, newalign, links);
          xx       = block->x;
          block->h += hh;
          yy       += hh;
          hh       = 0;
        }
        else if (buf.cmp("CENTER") ||
                 buf.cmp("P") ||
                 buf.cmp("H1") ||
                 buf.cmp("H2") ||
                 buf.cmp("H3") ||
                 buf.cmp("H4") ||
                 buf.cmp("H5") ||
                 buf.cmp("H6") ||
                 buf.cmp("UL") ||
                 buf.cmp("OL") ||
                 buf.cmp("DL") ||
                 buf.cmp("LI") ||
                 buf.cmp("DD") ||
                 buf.cmp("DT") ||
                 buf.cmp("HR") ||
                 buf.cmp("PRE") ||
                 buf.cmp("TABLE"))
        {
          block->end = start;
          line       = do_align(block, line, xx, newalign, links);
          newalign   = buf.cmp("CENTER") ? CENTER : LEFT;
          xx         = block->x;
          block->h   += hh;

          if (buf.cmp("OL")) {
            int ol_num = 1;
            if (get_attr(attrs, "START", attr, sizeof(attr)) != NULL) {
              errno = 0;
              char *endptr = 0;
              ol_num = (int)strtol(attr, &endptr, 10);
              if (errno || endptr == attr || ol_num < 0)
                ol_num = 1;
            }
            OL_num.push_back(ol_num);
          }
          else if (buf.cmp("UL"))
            OL_num.push_back(-1);

          if (buf.cmp("UL") ||
              buf.cmp("OL") ||
              buf.cmp("DL"))
          {
            block->h += fsize + 2;
            xx       = margins.push(4 * fsize);
          }
          else if (buf.cmp("TABLE"))
          {
            if (get_attr(attrs, "BORDER", attr, sizeof(attr)))
              border = (uchar)atoi(attr);
            else
              border = 0;

            tc = rc = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), bgcolor_);

            block->h += fsize + 2;

            format_table(&table_width, columns, start);

            if ((xx + table_width) > hsize_) {
#ifdef DEBUG
              printf("xx=%d, table_width=%d, hsize_=%d\n", xx, table_width,
                     hsize_);
#endif // DEBUG
              hsize_ = xx + table_width;
              done   = 0;
              break;
            }

            switch (get_align(attrs, talign))
            {
              default :
                  table_offset = 0;
                  break;

              case CENTER :
                  table_offset = (hsize_ - table_width) / 2 - textsize_;
                  break;

              case RIGHT :
                  table_offset = hsize_ - table_width - textsize_;
                  break;
            }

            column = 0;
          }

          if (tolower(buf[0]) == 'h' && isdigit(buf[1]))
          {
            font  = FL_HELVETICA_BOLD;
            fsize = textsize_ + '7' - buf[1];
          }
          else if (buf.cmp("DT"))
          {
            font  = textfont_ | FL_ITALIC;
            fsize = textsize_;
          }
          else if (buf.cmp("PRE"))
          {
            font  = FL_COURIER;
            fsize = textsize_;
            pre   = 1;
          }
          else
          {
            font  = textfont_;
            fsize = textsize_;
          }

          pushfont(font, fsize);

          yy = block->y + block->h;
          hh = 0;

          if ((tolower(buf[0]) == 'h' && isdigit(buf[1])) ||
              buf.cmp("DD") ||
              buf.cmp("DT") ||
              buf.cmp("P"))
            yy += fsize + 2;
          else if (buf.cmp("HR"))
          {
            hh += 2 * fsize;
            yy += fsize;
          }

          if (row)
            block = add_block(start, xx, yy, block->w, 0);
          else
            block = add_block(start, xx, yy, hsize_, 0);

          if (buf.cmp("LI")) {
            block->ol = 0;
            if (OL_num.size() && OL_num.back()>=0) {
              block->ol = 1;
              block->ol_num = (int)OL_num.back();
              int nnum = OL_num.pop_back() + 1;
              OL_num.push_back(nnum);
            }
          }

          needspace = 0;
          line      = 0;

          if (buf.cmp("CENTER"))
            newalign = talign = CENTER;
          else
            newalign = get_align(attrs, talign);
        }
        else if (buf.cmp("/CENTER") ||
                 buf.cmp("/P") ||
                 buf.cmp("/H1") ||
                 buf.cmp("/H2") ||
                 buf.cmp("/H3") ||
                 buf.cmp("/H4") ||
                 buf.cmp("/H5") ||
                 buf.cmp("/H6") ||
                 buf.cmp("/PRE") ||
                 buf.cmp("/UL") ||
                 buf.cmp("/OL") ||
                 buf.cmp("/DL") ||
                 buf.cmp("/TABLE"))
        {
          line       = do_align(block, line, xx, newalign, links);
          xx         = block->x;
          block->end = ptr;

          if (buf.cmp("/OL") ||
              buf.cmp("/UL")) {
            if (OL_num.size()) OL_num.pop_back();
          }

          if (buf.cmp("/UL") ||
              buf.cmp("/OL") ||
              buf.cmp("/DL"))
          {
            xx       = margins.pop();
            block->h += fsize + 2;
          }
          else if (buf.cmp("/TABLE"))
          {
            block->h += fsize + 2;
            xx       = margins.current();
          }
          else if (buf.cmp("/PRE"))
          {
            pre = 0;
            hh  = 0;
          }
          else if (buf.cmp("/CENTER"))
            talign = LEFT;

          popfont(font, fsize, fcolor);

          //#if defined(__GNUC__)
          //#warning FIXME this isspace & 255 test will probably not work on a utf8 stream... And we use it everywhere!
          //#endif /*__GNUC__*/
          while (isspace((*ptr)&255))
            ptr ++;

          block->h += hh;
          yy       += hh;

          if (tolower(buf[2]) == 'l')
            yy += fsize + 2;

          if (row)
            block = add_block(ptr, xx, yy, block->w, 0);
          else
            block = add_block(ptr, xx, yy, hsize_, 0);

          needspace = 0;
          hh        = 0;
          line      = 0;
          newalign  = talign;
        }
        else if (buf.cmp("TR"))
        {
          block->end = start;
          line       = do_align(block, line, xx, newalign, links);
          xx         = block->x;
          block->h   += hh;

          if (row)
          {
            yy = blocks_[row].y + blocks_[row].h;

            for (cell = blocks_ + row + 1; cell <= block; cell ++)
              if ((cell->y + cell->h) > yy)
                yy = cell->y + cell->h;

            block = blocks_ + row;

            block->h = yy - block->y + 2;

            for (i = 0; i < column; i ++)
              if (cells[i])
              {
                cell = blocks_ + cells[i];
                cell->h = block->h;
              }
          }

          memset(cells, 0, sizeof(cells));

          yy        = block->y + block->h - 4;
          hh        = 0;
          block     = add_block(start, xx, yy, hsize_, 0);
          row       = (int) (block - blocks_);
          needspace = 0;
          column    = 0;
          line      = 0;

          rc = get_color(get_attr(attrs, "BGCOLOR", attr, sizeof(attr)), tc);
        }
        else if (buf.cmp("/TR") && row)
        {
          line       = do_align(block, line, xx, newalign, links);
          block->end = start;
          block->h   += hh;
          talign     = LEFT;

          xx = blocks_[row].x;
          yy = blocks_[row].y + blocks_[row].h;

          for (cell = blocks_ + row + 1; cell <= block; cell ++)
            if ((cell->y + cell->h) > yy)
              yy = cell->y + cell->h;

          block = blocks_ + row;

          block->h = yy - block->y + 2;

          for (i = 0; i < column; i ++)
            if (cells[i])
            {
              cell = blocks_ + cells[i];
              cell->h = block->h;
            }

          yy        = block->y + block->h /*- 4*/;
          block     = add_block(start, xx, yy, hsize_, 0);
          needspace = 0;
          row       = 0;
          line      = 0;
        }
        else if ((buf.cmp("TD") ||
                  buf.cmp("TH")) && row)
        {
          int   colspan;                // COLSPAN attribute


          line       = do_align(block, line, xx, newalign, links);
          block->end = start;
          block->h   += hh;

          if (buf.cmp("TH"))
            font = textfont_ | FL_BOLD;
          else
            font = textfont_;

          fsize = textsize_;

          xx = blocks_[row].x + fsize + 3 + table_offset;
          for (i = 0; i < column; i ++)
            xx += columns[i] + 6;

          margins.push(xx - margins.current());

          if (get_attr(attrs, "COLSPAN", attr, sizeof(attr)) != NULL)
            colspan = atoi(attr);
          else
            colspan = 1;

          for (i = 0, ww = -6; i < colspan; i ++)
            ww += columns[column + i] + 6;

          if (block->end == block->start && nblocks_ > 1)
          {
            nblocks_ --;
            block --;
          }

          pushfont(font, fsize);

          yy        = blocks_[row].y;
          hh        = 0;
          block     = add_block(start, xx, yy, xx + ww, 0, border);
          needspace = 0;
          line      = 0;
          newalign  = get_align(attrs, tolower(buf[1]) == 'h' ? CENTER : LEFT);
          talign    = newalign;

          cells[column] = (int) (block - blocks_);

          column += colspan;

          block->bgcolor = get_color(get_attr(attrs, "BGCOLOR", attr,
                                              sizeof(attr)), rc);
        }
        else if ((buf.cmp("/TD") ||
                  buf.cmp("/TH")) && row)
        {
          line = do_align(block, line, xx, newalign, links);
          popfont(font, fsize, fcolor);
          xx = margins.pop();
          talign = LEFT;
        }
        else if (buf.cmp("FONT"))
        {
          if (get_attr(attrs, "FACE", attr, sizeof(attr)) != NULL) {
            if (!strncasecmp(attr, "helvetica", 9) ||
                !strncasecmp(attr, "arial", 5) ||
                !strncasecmp(attr, "sans", 4)) font = FL_HELVETICA;
            else if (!strncasecmp(attr, "times", 5) ||
                     !strncasecmp(attr, "serif", 5)) font = FL_TIMES;
            else if (!strncasecmp(attr, "symbol", 6)) font = FL_SYMBOL;
            else font = FL_COURIER;
          }

          if (get_attr(attrs, "SIZE", attr, sizeof(attr)) != NULL) {
            if (isdigit(attr[0] & 255)) {
              // Absolute size
              fsize = (int)(textsize_ * pow(1.2, atoi(attr) - 3.0));
            } else {
              // Relative size
              fsize = (int)(fsize * pow(1.2, atoi(attr)));
            }
          }

          pushfont(font, fsize);
        }
        else if (buf.cmp("/FONT"))
          popfont(font, fsize, fcolor);
        else if (buf.cmp("B") ||
                 buf.cmp("STRONG"))
          pushfont(font |= FL_BOLD, fsize);
        else if (buf.cmp("I") ||
                 buf.cmp("EM"))
          pushfont(font |= FL_ITALIC, fsize);
        else if (buf.cmp("CODE") ||
                 buf.cmp("TT"))
          pushfont(font = FL_COURIER, fsize);
        else if (buf.cmp("KBD"))
          pushfont(font = FL_COURIER_BOLD, fsize);
        else if (buf.cmp("VAR"))
          pushfont(font = FL_COURIER_ITALIC, fsize);
        else if (buf.cmp("/B") ||
                 buf.cmp("/STRONG") ||
                 buf.cmp("/I") ||
                 buf.cmp("/EM") ||
                 buf.cmp("/CODE") ||
                 buf.cmp("/TT") ||
                 buf.cmp("/KBD") ||
                 buf.cmp("/VAR"))
          popfont(font, fsize, fcolor);
        else if (buf.cmp("IMG"))
        {
          Fl_Shared_Image       *img = 0;
          int           width;
          int           height;


          get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
          get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
          width  = get_length(wattr);
          height = get_length(hattr);

          if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
            img    = get_image(attr, width, height);
            width  = img->w();
            height = img->h();
          }

          ww = width;

          if (ww > hsize_) {
            hsize_ = ww;
            done   = 0;
            break;
          }

          if (needspace && xx > block->x)
            ww += (int)fl_width(' ');

          if ((xx + ww) > block->w)
          {
            line     = do_align(block, line, xx, newalign, links);
            xx       = block->x;
            yy       += hh;
            block->h += hh;
            hh       = 0;
          }

          if (linkdest[0])
            add_link(linkdest, xx, yy-fsize, ww, height);

          xx += ww;
          if ((height + 2) > hh)
            hh = height + 2;

          needspace = 0;
        }
        buf.clear();
      }
      else if (*ptr == '\n' && pre)
      {
        if (linkdest[0])
          add_link(linkdest, xx, yy - hh, ww, hh);

        if (xx > hsize_) {
          hsize_ = xx;
          done   = 0;
          break;
        }

        line      = do_align(block, line, xx, newalign, links);
        xx        = block->x;
        yy        += hh;
        block->h  += hh;
        needspace = 0;
        ptr ++;
      }
      else if (isspace((*ptr)&255))
      {
        needspace = 1;
        if ( pre ) {
          xx += (int)fl_width(' ');
        }
        ptr ++;
      }
      else if (*ptr == '&')
      {
        // Handle html '&' codes, eg. "&"
        ptr ++;

        int qch = quote_char(ptr);

        if (qch < 0)
          buf += '&';
        else {
          buf.add(qch);
          ptr = strchr(ptr, ';') + 1;
        }

        if ((fsize + 2) > hh)
          hh = fsize + 2;
      }
      else
      {
        buf += *ptr++;

        if ((fsize + 2) > hh)
          hh = fsize + 2;
      }
    }

    if (buf.size() > 0 && !head)
    {
      ww = buf.width();

  //    printf("line = %d, xx = %d, ww = %d, block->x = %d, block->w = %d\n",
  //       line, xx, ww, block->x, block->w);

      if (ww > hsize_) {
        hsize_ = ww;
        done   = 0;
        break;
      }

      if (needspace && xx > block->x)
        ww += (int)fl_width(' ');

      if ((xx + ww) > block->w)
      {
        line     = do_align(block, line, xx, newalign, links);
        xx       = block->x;
        yy       += hh;
        block->h += hh;
        hh       = 0;
      }

      if (linkdest[0])
        add_link(linkdest, xx, yy - fsize, ww, fsize);

      xx += ww;
    }

    do_align(block, line, xx, newalign, links);

    block->end = ptr;
    size_      = yy + hh;
  }

//  printf("margins.depth_=%d\n", margins.depth_);

  if (ntargets_ > 1)
    qsort(targets_, ntargets_, sizeof(Fl_Help_Target),
          (compare_func_t)compare_targets);

  int dx = Fl::box_dw(b) - Fl::box_dx(b);
  int dy = Fl::box_dh(b) - Fl::box_dy(b);
  int ss = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
  int dw = Fl::box_dw(b) + ss;
  int dh = Fl::box_dh(b);

  if (hsize_ > (w() - dw)) {
    hscrollbar_.show();

    dh += ss;

    if (size_ < (h() - dh)) {
      scrollbar_.hide();
      hscrollbar_.resize(x() + Fl::box_dx(b), y() + h() - ss - dy,
                         w() - Fl::box_dw(b), ss);
    } else {
      scrollbar_.show();
      scrollbar_.resize(x() + w() - ss - dx, y() + Fl::box_dy(b),
                        ss, h() - ss - Fl::box_dh(b));
      hscrollbar_.resize(x() + Fl::box_dx(b), y() + h() - ss - dy,
                         w() - ss - Fl::box_dw(b), ss);
    }
  } else {
    hscrollbar_.hide();

    if (size_ < (h() - dh)) scrollbar_.hide();
    else {
      scrollbar_.resize(x() + w() - ss - dx, y() + Fl::box_dy(b),
                        ss, h() - Fl::box_dh(b));
      scrollbar_.show();
    }
  }

  // Reset scrolling if it needs to be...
  if (scrollbar_.visible()) {
    int temph = h() - Fl::box_dh(b);
    if (hscrollbar_.visible()) temph -= ss;
    if ((topline_ + temph) > size_) topline(size_ - temph);
    else topline(topline_);
  } else topline(0);

  if (hscrollbar_.visible()) {
    int tempw = w() - ss - Fl::box_dw(b);
    if ((leftline_ + tempw) > hsize_) leftline(hsize_ - tempw);
    else leftline(leftline_);
  } else leftline(0);
}


/** Formats a table */
void
Fl_Help_View::format_table(int        *table_width,     // O - Total table width
                           int        *columns,         // O - Column widths
                           const char *table)           // I - Pointer to start of table
{
  int           column,                                 // Current column
                num_columns,                            // Number of columns
                colspan,                                // COLSPAN attribute
                width,                                  // Current width
                temp_width,                             // Temporary width
                max_width,                              // Maximum width
                incell,                                 // In a table cell?
                pre,                                    // 
 text?
                needspace;                              // Need whitespace?
  HV_Edit_Buffer buf;                                   // Text buffer
  char          attr[1024],                             // Other attribute
                wattr[1024],                            // WIDTH attribute
                hattr[1024];                            // HEIGHT attribute
  const char    *ptr,                                   // Pointer into table
                *attrs,                                 // Pointer to attributes
                *start;                                 // Start of element
  int           minwidths[MAX_COLUMNS];                 // Minimum widths for each column
  Fl_Font       font;
  Fl_Fontsize   fsize;                                  // Current font and size
  Fl_Color      fcolor;                                 // Currrent font color

  DEBUG_FUNCTION(__LINE__,__FUNCTION__);

  // Clear widths...
  *table_width = 0;
  for (column = 0; column < MAX_COLUMNS; column ++)
  {
    columns[column]   = 0;
    minwidths[column] = 0;
  }

  num_columns = 0;
  colspan     = 0;
  max_width   = 0;
  pre         = 0;
  needspace   = 0;
  fstack_.top(font, fsize, fcolor);

  // Scan the table...
  for (ptr = table, column = -1, width = 0, incell = 0; *ptr;)
  {
    if ((*ptr == '<' || isspace((*ptr)&255)) && buf.size() > 0 && incell)
    {
      // Check width...
      if (needspace)
      {
        buf += ' ';
        needspace = 0;
      }

      temp_width = buf.width();
      buf.clear();

      if (temp_width > minwidths[column])
        minwidths[column] = temp_width;

      width += temp_width;

      if (width > max_width)
        max_width = width;
    }

    if (*ptr == '<')
    {
      start = ptr;

      for (buf.clear(), ptr ++; *ptr && *ptr != '>' && !isspace((*ptr)&255);)
        buf += *ptr++;

      attrs = ptr;
      while (*ptr && *ptr != '>')
        ptr ++;

      if (*ptr == '>')
        ptr ++;

      if (buf.cmp("BR") ||
          buf.cmp("HR"))
      {
        width     = 0;
        needspace = 0;
      }
      else if (buf.cmp("TABLE") && start > table)
        break;
      else if (buf.cmp("CENTER") ||
               buf.cmp("P") ||
               buf.cmp("H1") ||
               buf.cmp("H2") ||
               buf.cmp("H3") ||
               buf.cmp("H4") ||
               buf.cmp("H5") ||
               buf.cmp("H6") ||
               buf.cmp("UL") ||
               buf.cmp("OL") ||
               buf.cmp("DL") ||
               buf.cmp("LI") ||
               buf.cmp("DD") ||
               buf.cmp("DT") ||
               buf.cmp("PRE"))
      {
        width     = 0;
        needspace = 0;

        if (tolower(buf[0]) == 'h' && isdigit(buf[1]))
        {
          font  = FL_HELVETICA_BOLD;
          fsize = textsize_ + '7' - buf[1];
        }
        else if (buf.cmp("DT"))
        {
          font  = textfont_ | FL_ITALIC;
          fsize = textsize_;
        }
        else if (buf.cmp("PRE"))
        {
          font  = FL_COURIER;
          fsize = textsize_;
          pre   = 1;
        }
        else if (buf.cmp("LI"))
        {
          width  += 4 * fsize;
          font   = textfont_;
          fsize  = textsize_;
        }
        else
        {
          font  = textfont_;
          fsize = textsize_;
        }

        pushfont(font, fsize);
      }
      else if (buf.cmp("/CENTER") ||
               buf.cmp("/P") ||
               buf.cmp("/H1") ||
               buf.cmp("/H2") ||
               buf.cmp("/H3") ||
               buf.cmp("/H4") ||
               buf.cmp("/H5") ||
               buf.cmp("/H6") ||
               buf.cmp("/PRE") ||
               buf.cmp("/UL") ||
               buf.cmp("/OL") ||
               buf.cmp("/DL"))
      {
        width     = 0;
        needspace = 0;

        popfont(font, fsize, fcolor);
      }
      else if (buf.cmp("TR") || buf.cmp("/TR") ||
               buf.cmp("/TABLE"))
      {
//        printf("%s column = %d, colspan = %d, num_columns = %d\n",
//             buf.c_str(), column, colspan, num_columns);

        if (column >= 0)
        {
          // This is a hack to support COLSPAN...
          max_width /= colspan;

          while (colspan > 0)
          {
            if (max_width > columns[column])
              columns[column] = max_width;

            column ++;
            colspan --;
          }
        }

        if (buf.cmp("/TABLE"))
          break;

        needspace = 0;
        column    = -1;
        width     = 0;
        max_width = 0;
        incell    = 0;
      }
      else if (buf.cmp("TD") ||
               buf.cmp("TH"))
      {
//        printf("BEFORE column = %d, colspan = %d, num_columns = %d\n",
//             column, colspan, num_columns);

        if (column >= 0)
        {
          // This is a hack to support COLSPAN...
          max_width /= colspan;

          while (colspan > 0)
          {
            if (max_width > columns[column])
              columns[column] = max_width;

            column ++;
            colspan --;
          }
        }
        else
          column ++;

        if (get_attr(attrs, "COLSPAN", attr, sizeof(attr)) != NULL)
          colspan = atoi(attr);
        else
          colspan = 1;

//        printf("AFTER column = %d, colspan = %d, num_columns = %d\n",
//             column, colspan, num_columns);

        if ((column + colspan) >= num_columns)
          num_columns = column + colspan;

        needspace = 0;
        width     = 0;
        incell    = 1;

        if (buf.cmp("TH"))
          font = textfont_ | FL_BOLD;
        else
          font = textfont_;

        fsize = textsize_;

        pushfont(font, fsize);

        if (get_attr(attrs, "WIDTH", attr, sizeof(attr)) != NULL)
          max_width = get_length(attr);
        else
          max_width = 0;

//        printf("max_width = %d\n", max_width);
      }
      else if (buf.cmp("/TD") ||
               buf.cmp("/TH"))
      {
        incell = 0;
        popfont(font, fsize, fcolor);
      }
      else if (buf.cmp("B") ||
               buf.cmp("STRONG"))
        pushfont(font |= FL_BOLD, fsize);
      else if (buf.cmp("I") ||
               buf.cmp("EM"))
        pushfont(font |= FL_ITALIC, fsize);
      else if (buf.cmp("CODE") ||
               buf.cmp("TT"))
        pushfont(font = FL_COURIER, fsize);
      else if (buf.cmp("KBD"))
        pushfont(font = FL_COURIER_BOLD, fsize);
      else if (buf.cmp("VAR"))
        pushfont(font = FL_COURIER_ITALIC, fsize);
      else if (buf.cmp("/B") ||
               buf.cmp("/STRONG") ||
               buf.cmp("/I") ||
               buf.cmp("/EM") ||
               buf.cmp("/CODE") ||
               buf.cmp("/TT") ||
               buf.cmp("/KBD") ||
               buf.cmp("/VAR"))
        popfont(font, fsize, fcolor);
      else if (buf.cmp("IMG") && incell)
      {
        Fl_Shared_Image *img = 0;
        int             iwidth, iheight;


        get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
        get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
        iwidth  = get_length(wattr);
        iheight = get_length(hattr);

        if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
          img     = get_image(attr, iwidth, iheight);
          iwidth  = img->w();
          iheight = img->h();
        }

        if (iwidth > minwidths[column])
          minwidths[column] = iwidth;

        width += iwidth;
        if (needspace)
          width += (int)fl_width(' ');

        if (width > max_width)
          max_width = width;

        needspace = 0;
      }
      buf.clear();
    }
    else if (*ptr == '\n' && pre)
    {
      width     = 0;
      needspace = 0;
      ptr ++;
    }
    else if (isspace((*ptr)&255))
    {
      needspace = 1;

      ptr ++;
    }
    else if (*ptr == '&' )
    {
      ptr ++;

      int qch = quote_char(ptr);

      if (qch < 0)
        buf += '&';
      else {
        buf.add(qch);
        ptr = strchr(ptr, ';') + 1;
      }
    }
    else
    {
      buf += *ptr++;
    }
  }

  // Now that we have scanned the entire table, adjust the table and
  // cell widths to fit on the screen...
  if (get_attr(table + 6, "WIDTH", attr, sizeof(attr)))
    *table_width = get_length(attr);
  else
    *table_width = 0;

#ifdef DEBUG
  printf("num_columns = %d, table_width = %d\n", num_columns, *table_width);
#endif // DEBUG

  if (num_columns == 0)
    return;

  // Add up the widths...
  for (column = 0, width = 0; column < num_columns; column ++)
    width += columns[column];

#ifdef DEBUG
  printf("width = %d, w() = %d\n", width, w());
  for (column = 0; column < num_columns; column ++)
    printf("    columns[%d] = %d, minwidths[%d] = %d\n", column, columns[column],
           column, minwidths[column]);
#endif // DEBUG

  // Adjust the width if needed...
  int scale_width = *table_width;

  int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
  if (scale_width == 0) {
    if (width > (hsize_ - scrollsize)) scale_width = hsize_ - scrollsize;
    else scale_width = width;
  }

  if (width < scale_width) {
#ifdef DEBUG
    printf("Scaling table up to %d from %d...\n", scale_width, width);
#endif // DEBUG

    *table_width = 0;

    scale_width = (scale_width - width) / num_columns;

#ifdef DEBUG
    printf("adjusted scale_width = %d\n", scale_width);
#endif // DEBUG

    for (column = 0; column < num_columns; column ++) {
      columns[column] += scale_width;

      (*table_width) += columns[column];
    }
  }
  else if (width > scale_width) {
#ifdef DEBUG
    printf("Scaling table down to %d from %d...\n", scale_width, width);
#endif // DEBUG

    for (column = 0; column < num_columns; column ++) {
      width       -= minwidths[column];
      scale_width -= minwidths[column];
    }

#ifdef DEBUG
    printf("adjusted width = %d, scale_width = %d\n", width, scale_width);
#endif // DEBUG

    if (width > 0) {
      for (column = 0; column < num_columns; column ++) {
        columns[column] -= minwidths[column];
        columns[column] = scale_width * columns[column] / width;
        columns[column] += minwidths[column];
      }
    }

    *table_width = 0;
    for (column = 0; column < num_columns; column ++) {
      (*table_width) += columns[column];
    }
  }
  else if (*table_width == 0)
    *table_width = width;

#ifdef DEBUG
  printf("FINAL table_width = %d\n", *table_width);
  for (column = 0; column < num_columns; column ++)
    printf("    columns[%d] = %d\n", column, columns[column]);
#endif // DEBUG
}


/** Frees memory used for the document. */
void
Fl_Help_View::free_data() {
  // Release all images...
  if (value_) {
    const char  *ptr,           // Pointer into block
                *attrs;         // Pointer to start of element attributes
    HV_Edit_Buffer buf;         // Text buffer
    char        attr[1024],     // Attribute buffer
                wattr[1024],    // Width attribute buffer
                hattr[1024];    // Height attribute buffer

    DEBUG_FUNCTION(__LINE__,__FUNCTION__);

    for (ptr = value_; *ptr;)
    {
      if (*ptr == '<')
      {
        ptr ++;

        if (strncmp(ptr, "!--", 3) == 0)
        {
          // Comment...
          ptr += 3;
          if ((ptr = strstr(ptr, "-->")) != NULL)
          {
            ptr += 3;
            continue;
          }
          else
            break;
        }

        buf.clear();

        while (*ptr && *ptr != '>' && !isspace((*ptr)&255))
          buf += *ptr++;

        attrs = ptr;
        while (*ptr && *ptr != '>')
          ptr ++;

        if (*ptr == '>')
          ptr ++;

        if (buf.cmp("IMG"))
        {
          Fl_Shared_Image       *img;
          int           width;
          int           height;

          get_attr(attrs, "WIDTH", wattr, sizeof(wattr));
          get_attr(attrs, "HEIGHT", hattr, sizeof(hattr));
          width  = get_length(wattr);
          height = get_length(hattr);

          if (get_attr(attrs, "SRC", attr, sizeof(attr))) {
            // Get and release the image to free it from memory...
            img = get_image(attr, width, height);
            if ((void*)img != &broken_image) {
              img->release();
            }
          }
        }
      }
      else
        ptr ++;
    }

    free((void *)value_);
    value_ = 0;
  }

  // Free all of the arrays...
  if (nblocks_) {
    free(blocks_);

    ablocks_ = 0;
    nblocks_ = 0;
    blocks_  = 0;
  }

  if (nlinks_) {
    free(links_);

    alinks_ = 0;
    nlinks_ = 0;
    links_  = 0;
  }

  if (ntargets_) {
    free(targets_);

    atargets_ = 0;
    ntargets_ = 0;
    targets_  = 0;
  }
} // free_data()

/** Gets an alignment attribute. */
int                                     // O - Alignment
Fl_Help_View::get_align(const char *p,  // I - Pointer to start of attrs
                        int        a)   // I - Default alignment
{
  char  buf[255];                       // Alignment value


  if (get_attr(p, "ALIGN", buf, sizeof(buf)) == NULL)
    return (a);

  if (strcasecmp(buf, "CENTER") == 0)
    return (CENTER);
  else if (strcasecmp(buf, "RIGHT") == 0)
    return (RIGHT);
  else
    return (LEFT);
}


/** Gets an attribute value from the string. */
const char *                                    // O - Pointer to buf or NULL
Fl_Help_View::get_attr(const char *p,           // I - Pointer to start of attributes
                      const char *n,            // I - Name of attribute
                      char       *buf,          // O - Buffer for attribute value
                      int        bufsize)       // I - Size of buffer
{
  char  name[255],                              // Name from string
        *ptr,                                   // Pointer into name or value
        quote;                                  // Quote


  buf[0] = '\0';

  while (*p && *p != '>')
  {
    while (isspace((*p)&255))
      p ++;

    if (*p == '>' || !*p)
      return (NULL);

    for (ptr = name; *p && !isspace((*p)&255) && *p != '=' && *p != '>';)
      if (ptr < (name + sizeof(name) - 1))
        *ptr++ = *p++;
      else
        p ++;

    *ptr = '\0';

    if (isspace((*p)&255) || !*p || *p == '>')
      buf[0] = '\0';
    else
    {
      if (*p == '=')
        p ++;

      for (ptr = buf; *p && !isspace((*p)&255) && *p != '>';)
        if (*p == '\'' || *p == '\"')
        {
          quote = *p++;

          while (*p && *p != quote)
            if ((ptr - buf + 1) < bufsize)
              *ptr++ = *p++;
            else
              p ++;

          if (*p == quote)
            p ++;
        }
        else if ((ptr - buf + 1) < bufsize)
          *ptr++ = *p++;
        else
          p ++;

      *ptr = '\0';
    }

    if (strcasecmp(n, name) == 0)
      return (buf);
    else
      buf[0] = '\0';

    if (*p == '>')
      return (NULL);
  }

  return (NULL);
}


/** Gets a color attribute. */
Fl_Color                                // O - Color value
Fl_Help_View::get_color(const char *n,  // I - Color name
                        Fl_Color   c)   // I - Default color value
{
  int   i;                              // Looping var
  int   rgb, r, g, b;                   // RGB values
  static const struct {                 // Color name table
    const char *name;
    int r, g, b;
  }     colors[] = {
    { "black",          0x00, 0x00, 0x00 },
    { "red",            0xff, 0x00, 0x00 },
    { "green",          0x00, 0x80, 0x00 },
    { "yellow",         0xff, 0xff, 0x00 },
    { "blue",           0x00, 0x00, 0xff },
    { "magenta",        0xff, 0x00, 0xff },
    { "fuchsia",        0xff, 0x00, 0xff },
    { "cyan",           0x00, 0xff, 0xff },
    { "aqua",           0x00, 0xff, 0xff },
    { "white",          0xff, 0xff, 0xff },
    { "gray",           0x80, 0x80, 0x80 },
    { "grey",           0x80, 0x80, 0x80 },
    { "lime",           0x00, 0xff, 0x00 },
    { "maroon",         0x80, 0x00, 0x00 },
    { "navy",           0x00, 0x00, 0x80 },
    { "olive",          0x80, 0x80, 0x00 },
    { "purple",         0x80, 0x00, 0x80 },
    { "silver",         0xc0, 0xc0, 0xc0 },
    { "teal",           0x00, 0x80, 0x80 }
  };


  if (!n || !n[0]) return c;

  if (n[0] == '#') {
    // Do hex color lookup
    rgb = (int)strtol(n + 1, NULL, 16);

    if (strlen(n) > 4) {
      r = rgb >> 16;
      g = (rgb >> 8) & 255;
      b = rgb & 255;
    } else {
      r = (rgb >> 8) * 17;
      g = ((rgb >> 4) & 15) * 17;
      b = (rgb & 15) * 17;
    }
    return (fl_rgb_color((uchar)r, (uchar)g, (uchar)b));
  } else {
    for (i = 0; i < (int)(sizeof(colors) / sizeof(colors[0])); i ++)
      if (!strcasecmp(n, colors[i].name)) {
        return fl_rgb_color(colors[i].r, colors[i].g, colors[i].b);
      }
    return c;
  }
}


/** Gets an inline image.

  The image reference count is maintained accordingly, such that
  the image can be released exactly once when the document is closed.

  \return a pointer to a cached Fl_Shared_Image, if the image can be loaded,
          otherwise a pointer to an internal Fl_Pixmap (broken_image).

  \todo Fl_Help_View::get_image() returns a pointer to the internal
  Fl_Pixmap broken_image, but this is _not_ compatible with the
  return type Fl_Shared_Image (release() must not be called).
*/

/* Implementation note: (A.S. Apr 05, 2009)

  Fl_Help_View::get_image() uses a static global flag (initial_load)
  to determine, if it is called from the initial loading of a document
  (load() or value()), or from resize() or draw().

  A better solution would be to manage all loaded images in an own
  structure like Fl_Help_Target (Fl_Help_Image ?) to avoid using this
  global flag, but this would break the ABI !

  This should be fixed in FLTK 1.3 !


  If initial_load is true, then Fl_Shared_Image::get() is called to
  load the image, and the reference count of the shared image is
  increased by one.

  If initial_load is false, then Fl_Shared_Image::find() is called to
  load the image, and the image is released immediately. This avoids
  increasing the reference count when calling get_image() from draw()
  or resize().

  Calling Fl_Shared_Image::find() instead of Fl_Shared_Image::get() avoids
  doing unnecessary i/o for "broken images" within each resize/redraw.

  Each image must be released exactly once in the destructor or before
  a new document is loaded: see free_data().
*/

Fl_Shared_Image *
Fl_Help_View::get_image(const char *name, int W, int H) {
  const char    *localname;             // Local filename
  char          dir[FL_PATH_MAX];       // Current directory
  char          temp[3 * FL_PATH_MAX],  // Temporary filename
                *tempptr;               // Pointer into temporary name
  Fl_Shared_Image *ip;                  // Image pointer...

  // See if the image can be found...
  if (strchr(directory_, ':') != NULL && strchr(name, ':') == NULL) {
    if (name[0] == '/') {
      strlcpy(temp, directory_, sizeof(temp));
      // the following search (strchr) will always succeed, see condition above!
      tempptr = skip_bytes(strchr(temp, ':'), 3);
      if ((tempptr = strrchr(tempptr, '/')) != NULL) {
        strlcpy(tempptr, name, sizeof(temp) - (tempptr - temp));
      } else {
        strlcat(temp, name, sizeof(temp));
      }
    } else {
      snprintf(temp, sizeof(temp), "%s/%s", directory_, name);
    }

    if (link_) localname = (*link_)(this, temp);
    else localname = temp;
  } else if (name[0] != '/' && strchr(name, ':') == NULL) {
    if (directory_[0]) snprintf(temp, sizeof(temp), "%s/%s", directory_, name);
    else {
      fl_getcwd(dir, sizeof(dir));
      snprintf(temp, sizeof(temp), "file:%s/%s", dir, name);
    }

    if (link_) localname = (*link_)(this, temp);
    else localname = temp;
  } else if (link_) localname = (*link_)(this, name);
  else localname = name;

  if (!localname) return 0;

  if (strncmp(localname, "file:", 5) == 0) localname += 5;

  if (initial_load) {
    if ((ip = Fl_Shared_Image::get(localname, W, H)) == NULL) {
      ip = (Fl_Shared_Image *)&broken_image;
    }
  } else { // draw or resize
    if ((ip = Fl_Shared_Image::find(localname, W, H)) == NULL) {
      ip = (Fl_Shared_Image *)&broken_image;
    } else {
      ip->release();
    }
  }

  return ip;
}


/** Gets a length value, either absolute or %. */
int
Fl_Help_View::get_length(const char *l) {       // I - Value
  int   val;                                    // Integer value

  if (!l[0]) return 0;

  val = atoi(l);
  if (l[strlen(l) - 1] == '%') {
    if (val > 100) val = 100;
    else if (val < 0) val = 0;

    int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size();
    val = val * (hsize_ - scrollsize) / 100;
  }

  return val;
}


Fl_Help_Link *Fl_Help_View::find_link(int xx, int yy)
{
  int           i;
  Fl_Help_Link  *linkp;
  for (i = nlinks_, linkp = links_; i > 0; i --, linkp ++) {
    if (xx >= linkp->x && xx < linkp->w &&
        yy >= linkp->y && yy < linkp->h)
      break;
  }
  return i ? linkp : 0L;
}

void Fl_Help_View::follow_link(Fl_Help_Link *linkp)
{
  char          target[32];     // Current target

  clear_selection();

  strlcpy(target, linkp->name, sizeof(target));

  set_changed();

  if (strcmp(linkp->filename, filename_) != 0 && linkp->filename[0])
  {
    char        dir[FL_PATH_MAX];       // Current directory
    char        temp[3 * FL_PATH_MAX],  // Temporary filename
               *tempptr;                // Pointer into temporary filename


    if (strchr(directory_, ':') != NULL &&
        strchr(linkp->filename, ':') == NULL)
    {
      if (linkp->filename[0] == '/')
      {
        strlcpy(temp, directory_, sizeof(temp));
        // the following search (strchr) will always succeed, see condition above!
        tempptr = skip_bytes(strchr(temp, ':'), 3);
        if ((tempptr = strrchr(tempptr, '/')) != NULL) {
          strlcpy(tempptr, linkp->filename, sizeof(temp) - (tempptr - temp));
        } else {
          strlcat(temp, linkp->filename, sizeof(temp));
        }
      }
      else
        snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename);
    }
    else if (linkp->filename[0] != '/' && strchr(linkp->filename, ':') == NULL)
    {
      if (directory_[0])
        snprintf(temp, sizeof(temp), "%s/%s", directory_, linkp->filename);
      else
      {
          fl_getcwd(dir, sizeof(dir));
        snprintf(temp, sizeof(temp), "file:%s/%s", dir, linkp->filename);
      }
    }
    else
      strlcpy(temp, linkp->filename, sizeof(temp));

    if (linkp->name[0])
      snprintf(temp + strlen(temp), sizeof(temp) - strlen(temp), "#%s",
               linkp->name);

    load(temp);
  }
  else if (target[0])
    topline(target);
  else
    topline(0);

  leftline(0);
}

/** Removes the current text selection. */
void Fl_Help_View::clear_selection()
{
  if (current_view_==this)
    clear_global_selection();
}
/** Selects all the text in the view. */
void Fl_Help_View::select_all()
{
  clear_global_selection();
  if (!value_) return;
  current_view_ = this;
  selection_drag_last_ = selection_last_ = (int) strlen(value_);
  selected_ = 1;
}

void Fl_Help_View::clear_global_selection()
{
  if (selected_) redraw();
  selection_push_first_ = selection_push_last_ = 0;
  selection_drag_first_ = selection_drag_last_ = 0;
  selection_first_ = selection_last_ = 0;
  selected_ = 0;
}

char Fl_Help_View::begin_selection()
{
  clear_global_selection();

  if (!fl_help_view_buffer) fl_help_view_buffer = fl_create_offscreen(1, 1);

  mouse_x_ = Fl::event_x();
  mouse_y_ = Fl::event_y();
  draw_mode_ = 1;

    current_view_ = this;
    fl_begin_offscreen(fl_help_view_buffer);
    draw();
    fl_end_offscreen();

  draw_mode_ = 0;

  if (selection_push_last_) return 1;
  else return 0;
}

char Fl_Help_View::extend_selection()
{
  if (Fl::event_is_click())
    return 0;

  // Give this widget the focus during the selection process. This will
  // deselect other text selection and make sure, we receive the Copy
  // keyboard shortcut.
  if (Fl::focus()!=this)
    Fl::focus(this);

//  printf("old selection_first_=%d, selection_last_=%d\n",
//         selection_first_, selection_last_);

  int sf = selection_first_, sl = selection_last_;

  selected_ = 1;
  mouse_x_ = Fl::event_x();
  mouse_y_ = Fl::event_y();
  draw_mode_ = 2;

    fl_begin_offscreen(fl_help_view_buffer);
    draw();
    fl_end_offscreen();

  draw_mode_ = 0;

  if (selection_push_first_ < selection_drag_first_) {
    selection_first_ = selection_push_first_;
  } else {
    selection_first_ = selection_drag_first_;
  }

  if (selection_push_last_ > selection_drag_last_) {
    selection_last_ = selection_push_last_;
  } else {
    selection_last_ = selection_drag_last_;
  }

//  printf("new selection_first_=%d, selection_last_=%d\n",
//         selection_first_, selection_last_);

  if (sf!=selection_first_ || sl!=selection_last_) {
//    puts("REDRAW!!!\n");
    return 1;
  } else {
//    puts("");
    return 0;
  }
}

// convert a command with up to four letters into an unsigned int
static unsigned int command(const char *cmd)
{
  unsigned int ret = (tolower(cmd[0])<<24);
  char c = cmd[1];
  if (c=='>' || c==' ' || c==0) return ret;
  ret |= (tolower(c)<<16);
  c = cmd[2];
  if (c=='>' || c==' ' || c==0) return ret;
  ret |= (tolower(c)<<8);
  c = cmd[3];
  if (c=='>' || c==' ' || c==0) return ret;
  ret |= tolower(c);
  c = cmd[4];
  if (c=='>' || c==' ' || c==0) return ret;
  return 0;
}

#define CMD(a, b, c, d) ((a<<24)|(b<<16)|(c<<8)|d)

void Fl_Help_View::end_selection(int clipboard)
{
  if (!selected_ || current_view_!=this)
    return;
  // convert the select part of our html text into some kind of somewhat readable UTF-8
  // and store it in the selection buffer
  int p = 0;
  char pre = 0;
  int len = (int) strlen(value_);
  char *txt = (char*)malloc(len+1), *d = txt;
  const char *s = value_, *cmd, *src;
  for (;;) {
    int c = (*s++) & 0xff;
    if (c==0) break;
    if (c=='<') { // begin of some html command. Skip until we find a '>'
      cmd = s;
      for (;;) {
        c = (*s++) & 0xff;
        if (c==0 || c=='>') break;
      }
      if (c==0) break;
      // do something with this command... .
      // The replacement string must not be longer than the command
      // itself plus '<' and '>'
      src = 0;
      switch (command(cmd)) {
        case CMD('p','r','e', 0 ): pre = 1; break;
        case CMD('/','p','r','e'): pre = 0; break;
        case CMD('t','d', 0 , 0 ):
        case CMD('p', 0 , 0 , 0 ):
        case CMD('/','p', 0 , 0 ):
        case CMD('b','r', 0 , 0 ): src = "\n"; break;
        case CMD('l','i', 0 , 0 ): src = "\n * "; break;
        case CMD('/','h','1', 0 ):
        case CMD('/','h','2', 0 ):
        case CMD('/','h','3', 0 ):
        case CMD('/','h','4', 0 ):
        case CMD('/','h','5', 0 ):
        case CMD('/','h','6', 0 ): src = "\n\n"; break;
        case CMD('t','r', 0 , 0 ):
        case CMD('h','1', 0 , 0 ):
        case CMD('h','2', 0 , 0 ):
        case CMD('h','3', 0 , 0 ):
        case CMD('h','4', 0 , 0 ):
        case CMD('h','5', 0 , 0 ):
        case CMD('h','6', 0 , 0 ): src = "\n\n"; break;
        case CMD('d','t', 0 , 0 ): src = "\n "; break;
        case CMD('d','d', 0 , 0 ): src = "\n - "; break;
      }
      int n = (int) (s-value_);
      if (src && n>selection_first_ && n<=selection_last_) {
        while (*src) {
          *d++ = *src++;
        }
        c = src[-1] & 0xff;
        p = isspace(c) ? ' ' : c;
      }
      continue;
    }
    const char *s2 = s;
    if (c=='&') { // special characters (HTML entities)
      int xx = quote_char(s);
      if (xx >= 0) {
        c = xx;
        for (;;) {
          char cc = *s++;
          if (!cc || cc==';') break;
        }
      }
    }
    int n = (int) (s2-value_);
    if (n>selection_first_ && n<=selection_last_) {
      if (!pre && c < 256 && isspace(c)) c = ' ';
      if (p != ' ' || c != ' ') {
        if (s2 != s) { // c was an HTML entity
          d += fl_utf8encode(c, d);
        }
        else *d++ = c;
      }
      p = c;
    }
    if (n>selection_last_) break; // stop parsing html after end of selection
  }
  *d = 0;
  Fl::copy(txt, (int) strlen(txt), clipboard);
  // printf("copy [%s]\n", txt);
  free(txt);
}

/**
 \brief Check if the user selected text in this view.
 \return 1 if text is selected, 0 if no text is selected
 */
int Fl_Help_View::text_selected() {
  if (current_view_==this)
    return selected_;
  else
    return 0;
}

/**
 \brief If text is selected in this view, copy it to a clipboard.
 \param[in] clipboard for x11 only, 0=selection buffer, 1=clipboard, 2=both
 \return 1 if text is selected, 0 if no text is selected
 */
int Fl_Help_View::copy(int clipboard) {
  if (text_selected()) {
    end_selection(clipboard);
    return 1;
  } else {
    return 0;
  }
}

/** Handles events in the widget. */
int                             // O - 1 if we handled it, 0 otherwise
Fl_Help_View::handle(int event) // I - Event to handle
{
  static Fl_Help_Link *linkp;   // currently clicked link

  int xx = Fl::event_x() - x() + leftline_;
  int yy = Fl::event_y() - y() + topline_;

  switch (event)
  {
    case FL_FOCUS:
      redraw();
      return 1;
    case FL_UNFOCUS:
      clear_selection();
      redraw();
      return 1;
    case FL_ENTER :
      Fl_Group::handle(event);
      return 1;
    case FL_LEAVE :
      fl_cursor(FL_CURSOR_DEFAULT);
      break;
    case FL_MOVE:
      if (find_link(xx, yy)) fl_cursor(FL_CURSOR_HAND);
      else fl_cursor(FL_CURSOR_DEFAULT);
      return 1;
    case FL_PUSH:
      if (Fl::event_button() == FL_RIGHT_MOUSE) {
        rmb_menu[0].label(copy_menu_text);
        if (text_selected())
          rmb_menu[0].activate();
        else
          rmb_menu[0].deactivate();
        fl_cursor(FL_CURSOR_DEFAULT);
        const Fl_Menu_Item *mi = rmb_menu->popup(Fl::event_x(), Fl::event_y());
        if (mi) switch (mi->argument()) {
          case 1:
            copy();
            break;
        }
      }
      if (Fl_Group::handle(event)) return 1;
      linkp = find_link(xx, yy);
      if (linkp) {
        fl_cursor(FL_CURSOR_HAND);
        return 1;
      }
      if (begin_selection()) {
        fl_cursor(FL_CURSOR_INSERT);
        return 1;
      }
      fl_cursor(FL_CURSOR_DEFAULT);
      return 1;
    case FL_DRAG:
      if (linkp) {
        if (Fl::event_is_click()) {
          fl_cursor(FL_CURSOR_HAND);
        } else {
          fl_cursor(FL_CURSOR_DEFAULT); // should be "FL_CURSOR_CANCEL" if we had it
        }
        return 1;
      }
      if (current_view_==this && selection_push_last_) {
        if (extend_selection()) redraw();
        fl_cursor(FL_CURSOR_INSERT);
        return 1;
      }
      fl_cursor(FL_CURSOR_DEFAULT);
      return 1;
    case FL_RELEASE:
      if (linkp) {
        if (Fl::event_is_click()) {
          follow_link(linkp);
        }
        fl_cursor(FL_CURSOR_DEFAULT);
        linkp = 0;
        return 1;
      }
      if (current_view_==this && selection_push_last_) {
        end_selection();
        return 1;
      }
      return 1;
    case FL_SHORTCUT: {
      int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT|FL_SHIFT);
      if ( mods == FL_COMMAND) {
        switch ( Fl::event_key() ) {
          case 'a': select_all(); redraw(); return 1;
          case 'c':
          case 'x': end_selection(1); return 1;
        }
      }
      break; }
  }
  return (Fl_Group::handle(event));
}

/**
  The constructor creates the Fl_Help_View widget at the specified
  position and size.
*/
Fl_Help_View::Fl_Help_View(int        xx,       // I - Left position
                           int        yy,       // I - Top position
                           int        ww,       // I - Width in pixels
                           int        hh,       // I - Height in pixels
                           const char *l)
    : Fl_Group(xx, yy, ww, hh, l),
      scrollbar_(xx + ww - Fl::scrollbar_size(), yy,
                 Fl::scrollbar_size(), hh - Fl::scrollbar_size()),
      hscrollbar_(xx, yy + hh - Fl::scrollbar_size(),
                  ww - Fl::scrollbar_size(), Fl::scrollbar_size())
{
  color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR);

  title_[0]     = '\0';
  defcolor_     = FL_FOREGROUND_COLOR;
  bgcolor_      = FL_BACKGROUND_COLOR;
  textcolor_    = FL_FOREGROUND_COLOR;
  linkcolor_    = FL_SELECTION_COLOR;
  textfont_     = FL_TIMES;
  textsize_     = 12;
  value_        = NULL;

  ablocks_      = 0;
  nblocks_      = 0;
  blocks_       = (Fl_Help_Block *)0;

  link_         = (Fl_Help_Func *)0;

  alinks_       = 0;
  nlinks_       = 0;
  links_        = (Fl_Help_Link *)0;

  atargets_     = 0;
  ntargets_     = 0;
  targets_      = (Fl_Help_Target *)0;

  directory_[0] = '\0';
  filename_[0]  = '\0';

  topline_      = 0;
  leftline_     = 0;
  size_         = 0;
  hsize_        = 0;
  scrollbar_size_ = 0;

  scrollbar_.value(0, hh, 0, 1);
  scrollbar_.step(8.0);
  scrollbar_.show();
  scrollbar_.callback(scrollbar_callback);

  hscrollbar_.value(0, ww, 0, 1);
  hscrollbar_.step(8.0);
  hscrollbar_.show();
  hscrollbar_.callback(hscrollbar_callback);
  hscrollbar_.type(FL_HORIZONTAL);
  end();

  resize(xx, yy, ww, hh);
}


/** Destroys the Fl_Help_View widget.

  The destructor destroys the widget and frees all memory that has been
  allocated for the current document.
*/
Fl_Help_View::~Fl_Help_View()
{
  clear_selection();
  free_data();
}


/** Loads the specified file.

 This method loads the specified file or URL. The filename may end in a
 \c \#name style target.

 If the URL starts with \a ftp, \a http, \a https, \a ipp, \a mailto, or
 \a news, followed by a colon, FLTK will use fl_open_uri() to show the
 requested page in an external browser.

 In all other cases, the URL is interpreted as a filename. The file is read and
 displayed in this browser. Note that Windows style backslashes are not
 supported in the file name.

 \param[in] f filename or URL

 \return 0 on success, -1 on error

 \see fl_open_uri()
*/
int Fl_Help_View::load(const char *f)
{
  FILE          *fp;            // File to read from
  long          len;            // Length of file
  char          *target;        // Target in file
  char          *slash;         // Directory separator
  const char    *localname;     // Local filename
  char          error[2 * FL_PATH_MAX]; // Error buffer
  char          newname[FL_PATH_MAX];   // New filename buffer

  // printf("load(%s)\n",f); fflush(stdout);

  if (strncmp(f, "ftp:", 4) == 0 ||
      strncmp(f, "http:", 5) == 0 ||
      strncmp(f, "https:", 6) == 0 ||
      strncmp(f, "ipp:", 4) == 0 ||
      strncmp(f, "mailto:", 7) == 0 ||
      strncmp(f, "news:", 5) == 0)
  {
    char urimsg[FL_PATH_MAX];
    if ( fl_open_uri(f, urimsg, sizeof(urimsg)) == 0 ) {
      clear_selection();

      strlcpy(newname, f, sizeof(newname));
      if ((target = strrchr(newname, '#')) != NULL)
        *target++ = '\0';

      if (link_)
        localname = (*link_)(this, newname);
      else
        localname = filename_;

      if (!localname)
        return (0);

      free_data();

      strlcpy(filename_, newname, sizeof(filename_));
      strlcpy(directory_, newname, sizeof(directory_));

      // Note: We do not support Windows backslashes, since they are illegal
      //       in URLs...
      if ((slash = strrchr(directory_, '/')) == NULL)
        directory_[0] = '\0';
      else if (slash > directory_ && slash[-1] != '/')
        *slash = '\0';

      snprintf(error, sizeof(error),
               "Error"
               "

Error

" "

Unable to follow the link \"%s\" - " "%s.

", f, urimsg); value(error); return -1; } else { return 0; } } clear_selection(); strlcpy(newname, f, sizeof(newname)); if ((target = strrchr(newname, '#')) != NULL) *target++ = '\0'; if (link_) localname = (*link_)(this, newname); else localname = filename_; if (!localname) return -1; free_data(); strlcpy(filename_, newname, sizeof(filename_)); strlcpy(directory_, newname, sizeof(directory_)); // Note: We do not support Windows backslashes, since they are illegal // in URLs... if ((slash = strrchr(directory_, '/')) == NULL) directory_[0] = '\0'; else if (slash > directory_ && slash[-1] != '/') *slash = '\0'; if (strncmp(localname, "file:", 5) == 0) localname += 5; // Adjust for local filename... int ret = 0; if ((fp = fl_fopen(localname, "rb")) != NULL) { fseek(fp, 0, SEEK_END); len = ftell(fp); rewind(fp); value_ = (const char *)calloc(len + 1, 1); if (fread((void *)value_, 1, len, fp)==0) { /* use default 0 */ } fclose(fp); } else { snprintf(error, sizeof(error), "Error" "

Error

" "

Unable to follow the link \"%s\" - " "%s.

", localname, strerror(errno)); value_ = fl_strdup(error); ret = -1; } initial_load = 1; format(); initial_load = 0; if (target) topline(target); else topline(0); return ret; } /** Resizes the help widget. */ void Fl_Help_View::resize(int xx, // I - New left position int yy, // I - New top position int ww, // I - New width int hh) // I - New height { Fl_Boxtype b = box() ? box() : FL_DOWN_BOX; // Box to draw... Fl_Widget::resize(xx, yy, ww, hh); int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size(); scrollbar_.resize(x() + w() - scrollsize - Fl::box_dw(b) + Fl::box_dx(b), y() + Fl::box_dy(b), scrollsize, h() - scrollsize - Fl::box_dh(b)); hscrollbar_.resize(x() + Fl::box_dx(b), y() + h() - scrollsize - Fl::box_dh(b) + Fl::box_dy(b), w() - scrollsize - Fl::box_dw(b), scrollsize); format(); } /** Scrolls the text to the indicated position, given a named destination. \param[in] n target name */ void Fl_Help_View::topline(const char *n) // I - Target name { Fl_Help_Target key, // Target name key *target; // Pointer to matching target if (ntargets_ == 0) return; strlcpy(key.name, n, sizeof(key.name)); target = (Fl_Help_Target *)bsearch(&key, targets_, ntargets_, sizeof(Fl_Help_Target), (compare_func_t)compare_targets); if (target != NULL) topline(target->y); } /** Scrolls the text to the indicated position, given a pixel line. If the given pixel value \p top is out of range, then the text is scrolled to the top or bottom of the document, resp. \param[in] top top line number in pixels (0 = start of document) */ void Fl_Help_View::topline(int top) // I - Top line number { if (!value_) return; int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size(); if (size_ < (h() - scrollsize) || top < 0) top = 0; else if (top > size_) top = size_; topline_ = top; scrollbar_.value(topline_, h() - scrollsize, 0, size_); do_callback(FL_REASON_DRAGGED); redraw(); } /** Scrolls the text to the indicated position, given a pixel column. If the given pixel value \p left is out of range, then the text is scrolled to the left or right side of the document, resp. \param[in] left left column number in pixels (0 = left side) */ void Fl_Help_View::leftline(int left) // I - Left position { if (!value_) return; int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size(); if (hsize_ < (w() - scrollsize) || left < 0) left = 0; else if (left > hsize_) left = hsize_; leftline_ = left; hscrollbar_.value(leftline_, w() - scrollsize, 0, hsize_); redraw(); } /** Sets the current help text buffer to the string provided and reformats the text. The provided character string \p val is copied internally and will be freed when value() is called again, or when the widget is destroyed. If \p val is NULL, then the widget is cleared. */ void Fl_Help_View::value(const char *val) // I - Text to view { clear_selection(); free_data(); set_changed(); if (!val) return; value_ = fl_strdup(val); initial_load = 1; format(); initial_load = 0; topline(0); leftline(0); } /* Returns the Unicode Code Point associated with a quoted character (aka "HTML Entity"). Possible encoding formats: - &name; named entity - &#nn..; numeric (decimal) Unicode Code Point - &#xnn..; numeric (hexadecimal) Unicode Code Point - &#Xnn..; numeric (hexadecimal) Unicode Code Point 'nn..' = decimal or hexadecimal number, resp. Contents of the table names[] below: All printable ASCII (32-126) and ISO-8859-1 (160-255) characters are encoded with the same value in Unicode. Special characters outside the range [0-255] are encoded with their Unicode Code Point as hexadecimal constants. Example: - Euro sign: (Unicode) U+20ac = (hex) 0x20ac Note: Converted to correct Unicode values and tested (compared with the display of Firefox). AlbrechtS, 14 Feb. 2016. Note to devs: if you add or remove items to/from this list, please update the documentation in FL/Fl_Help_View.H. */ static int // O - Code or -1 on error quote_char(const char *p) { // I - Quoted string int i; // Looping var static const struct { const char *name; int namelen; int code; } *nameptr, // Pointer into name array names[] = { // Quoting names { "Aacute;", 7, 193 }, { "aacute;", 7, 225 }, { "Acirc;", 6, 194 }, { "acirc;", 6, 226 }, { "acute;", 6, 180 }, { "AElig;", 6, 198 }, { "aelig;", 6, 230 }, { "Agrave;", 7, 192 }, { "agrave;", 7, 224 }, { "amp;", 4, '&' }, { "Aring;", 6, 197 }, { "aring;", 6, 229 }, { "Atilde;", 7, 195 }, { "atilde;", 7, 227 }, { "Auml;", 5, 196 }, { "auml;", 5, 228 }, { "brvbar;", 7, 166 }, { "bull;", 5, 0x2022 }, { "Ccedil;", 7, 199 }, { "ccedil;", 7, 231 }, { "cedil;", 6, 184 }, { "cent;", 5, 162 }, { "copy;", 5, 169 }, { "curren;", 7, 164 }, { "dagger;", 7, 0x2020 }, { "deg;", 4, 176 }, { "divide;", 7, 247 }, { "Eacute;", 7, 201 }, { "eacute;", 7, 233 }, { "Ecirc;", 6, 202 }, { "ecirc;", 6, 234 }, { "Egrave;", 7, 200 }, { "egrave;", 7, 232 }, { "ETH;", 4, 208 }, { "eth;", 4, 240 }, { "Euml;", 5, 203 }, { "euml;", 5, 235 }, { "euro;", 5, 0x20ac }, { "frac12;", 7, 189 }, { "frac14;", 7, 188 }, { "frac34;", 7, 190 }, { "gt;", 3, '>' }, { "Iacute;", 7, 205 }, { "iacute;", 7, 237 }, { "Icirc;", 6, 206 }, { "icirc;", 6, 238 }, { "iexcl;", 6, 161 }, { "Igrave;", 7, 204 }, { "igrave;", 7, 236 }, { "iquest;", 7, 191 }, { "Iuml;", 5, 207 }, { "iuml;", 5, 239 }, { "laquo;", 6, 171 }, { "lt;", 3, '<' }, { "macr;", 5, 175 }, { "micro;", 6, 181 }, { "middot;", 7, 183 }, { "nbsp;", 5, ' ' }, { "ndash;", 6, 0x2013 }, { "not;", 4, 172 }, { "Ntilde;", 7, 209 }, { "ntilde;", 7, 241 }, { "Oacute;", 7, 211 }, { "oacute;", 7, 243 }, { "Ocirc;", 6, 212 }, { "ocirc;", 6, 244 }, { "Ograve;", 7, 210 }, { "ograve;", 7, 242 }, { "ordf;", 5, 170 }, { "ordm;", 5, 186 }, { "Oslash;", 7, 216 }, { "oslash;", 7, 248 }, { "Otilde;", 7, 213 }, { "otilde;", 7, 245 }, { "Ouml;", 5, 214 }, { "ouml;", 5, 246 }, { "para;", 5, 182 }, { "permil;", 7, 0x2030 }, { "plusmn;", 7, 177 }, { "pound;", 6, 163 }, { "quot;", 5, '\"' }, { "raquo;", 6, 187 }, { "reg;", 4, 174 }, { "sect;", 5, 167 }, { "shy;", 4, 173 }, { "sup1;", 5, 185 }, { "sup2;", 5, 178 }, { "sup3;", 5, 179 }, { "szlig;", 6, 223 }, { "THORN;", 6, 222 }, { "thorn;", 6, 254 }, { "times;", 6, 215 }, { "trade;", 6, 0x2122 }, { "Uacute;", 7, 218 }, { "uacute;", 7, 250 }, { "Ucirc;", 6, 219 }, { "ucirc;", 6, 251 }, { "Ugrave;", 7, 217 }, { "ugrave;", 7, 249 }, { "uml;", 4, 168 }, { "Uuml;", 5, 220 }, { "uuml;", 5, 252 }, { "Yacute;", 7, 221 }, { "yacute;", 7, 253 }, { "yen;", 4, 165 }, { "Yuml;", 5, 0x0178 }, { "yuml;", 5, 255 } }; if (!strchr(p, ';')) return -1; if (*p == '#') { if (*(p+1) == 'x' || *(p+1) == 'X') return (int)strtol(p+2, NULL, 16); else return atoi(p+1); } for (i = (int)(sizeof(names) / sizeof(names[0])), nameptr = names; i > 0; i --, nameptr ++) if (strncmp(p, nameptr->name, nameptr->namelen) == 0) return nameptr->code; return -1; } /** The vertical scrollbar callback. */ static void scrollbar_callback(Fl_Widget *s, void *) { ((Fl_Help_View *)(s->parent()))->topline(int(((Fl_Scrollbar*)s)->value())); } /** The horizontal scrollbar callback. */ static void hscrollbar_callback(Fl_Widget *s, void *) { ((Fl_Help_View *)(s->parent()))->leftline(int(((Fl_Scrollbar*)s)->value())); } fltk-1.4.3/src/Fl_get_key.cxx0000644000175000017500000000272415004135251016175 0ustar albrechtalbrecht// // Keyboard state routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if !defined(FL_DOXYGEN) // Return the current state of a key. This is the X version. I identify // keys (mostly) by the X keysym. So this turns the keysym into a keycode // and looks it up in the X key bit vector, which Fl_x.cxx keeps track of. #include #include "drivers/X11/Fl_X11_Screen_Driver.H" #include // for fl_display extern char fl_key_vector[32]; // in Fl_x.cxx int Fl_X11_Screen_Driver::event_key(int k) { if (k > FL_Button && k <= FL_Button+8) return Fl::event_state(8<<(k-FL_Button)); int i; # ifdef __sgi // get some missing PC keyboard keys: if (k == FL_Meta_L) i = 147; else if (k == FL_Meta_R) i = 148; else if (k == FL_Menu) i = 149; else # endif i = XKeysymToKeycode(fl_display, k); if (i==0) return 0; return fl_key_vector[i/8] & (1 << (i%8)); } int Fl_X11_Screen_Driver::get_key(int k) { fl_open_display(); XQueryKeymap(fl_display, fl_key_vector); return event_key(k); } #endif // FL_DOXYGEN fltk-1.4.3/src/Fl_Repeat_Button.cxx0000644000175000017500000000267015004135251017321 0ustar albrechtalbrecht// // Repeat button widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #define INITIALREPEAT .5 #define REPEAT .1 void Fl_Repeat_Button::repeat_callback(void *v) { Fl_Button *b = (Fl_Button*)v; Fl::add_timeout(REPEAT,repeat_callback,b); b->do_callback(FL_REASON_RESELECTED); } int Fl_Repeat_Button::handle(int event) { int newval; switch (event) { case FL_HIDE: case FL_DEACTIVATE: case FL_RELEASE: newval = 0; goto J1; case FL_PUSH: case FL_DRAG: if (Fl::visible_focus()) Fl::focus(this); newval = Fl::event_inside(this); J1: if (!active()) newval = 0; if (value(newval)) { if (newval) { Fl::add_timeout(INITIALREPEAT,repeat_callback,this); do_callback(FL_REASON_SELECTED); } else { Fl::remove_timeout(repeat_callback,this); } } return 1; default: return Fl_Button::handle(event); } } Fl_Repeat_Button::Fl_Repeat_Button(int X,int Y,int W,int H,const char *l) : Fl_Button(X,Y,W,H,l) { } fltk-1.4.3/src/Fl_PNG_Image.cxx0000644000175000017500000001660215004135251016274 0ustar albrechtalbrecht// // Fl_PNG_Image routines. // // Copyright 1997-2012 by Easy Software Products. // Image support by Matthias Melcher, Copyright 2000-2009. // // Copyright 2013-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // Fl_PNG_Image::Fl_PNG_Image() - Load a PNG image file. // // // Include necessary header files... // #include #include #include "Fl_System_Driver.H" #include #include #include #include #include #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) extern "C" { # include # ifdef HAVE_PNG_H # include # else # include # endif // HAVE_PNG_H } typedef struct { png_structp pp; const unsigned char *current; const unsigned char *last; } fl_png_memory; extern "C" { static void png_read_data_from_mem( png_structp png_ptr, //pointer to our data png_bytep data, // where to copy the image data for libpng computing png_size_t length) // length of data to copy { fl_png_memory *png_mem_data = (fl_png_memory*)png_get_io_ptr(png_ptr); // get the pointer to our struct if (png_mem_data->current + length > png_mem_data->last) { png_error(png_mem_data->pp, "Invalid attempt to read row data"); return; } /* copy data from image buffer */ memcpy (data, png_mem_data->current, length); /* advance in the memory data */ png_mem_data->current += length; } } // extern "C" #endif // HAVE_LIBPNG && HAVE_LIBZ /** The constructor loads the named PNG image from the given png filename. The destructor frees all memory and server resources that are used by the image. Use Fl_Image::fail() to check if Fl_PNG_Image failed to load. fail() returns ERR_FILE_ACCESS if the file could not be opened or read, ERR_FORMAT if the PNG format could not be decoded, and ERR_NO_IMAGE if the image could not be loaded for another reason. \param[in] filename Name of PNG file to read */ Fl_PNG_Image::Fl_PNG_Image (const char *filename): Fl_RGB_Image(0,0,0) { load_png_(filename, 0, NULL, 0); } // private c'tor used by Fl_ICO_Image // \param offset Offset to seek for the begin of PNG data inside a .ICO file Fl_PNG_Image::Fl_PNG_Image (const char *filename, int offset): Fl_RGB_Image(0,0,0) { load_png_(filename, offset, NULL, 0); } /** \brief Constructor that reads a PNG image from memory. Construct an image from a block of memory inside the application. Fluid offers "binary Data" chunks as a great way to add image data into the C++ source code. name_png can be NULL. If a name is given, the image is added to the list of shared images (see: Fl_Shared_Image) and will be available by that name. \param name_png A name given to this image or NULL \param buffer Pointer to the start of the PNG image in memory \param maxsize Size in bytes of the memory buffer containing the PNG image */ Fl_PNG_Image::Fl_PNG_Image ( const char *name_png, const unsigned char *buffer, int maxsize): Fl_RGB_Image(0,0,0) { load_png_(name_png, 0, buffer, maxsize); } void Fl_PNG_Image::load_png_(const char *name_png, int offset, const unsigned char *buffer_png, int maxsize) { #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) int i; // Looping var int channels; // Number of color channels png_structp pp; // PNG read pointer png_infop info = 0; // PNG info pointers png_bytep *rows; // PNG row pointers fl_png_memory png_mem_data; int from_memory = (buffer_png != NULL); // true if reading image from memory // Note: The file pointer fp must not be an automatic (stack) variable // to avoid potential clobbering by setjmp/longjmp (gcc: [-Wclobbered]). // Hence the actual 'fp' is allocated with operator new. FILE** fp = new FILE*; // always allocate file pointer *fp = NULL; if (!from_memory) { if ((*fp = fl_fopen(name_png, "rb")) == NULL) { ld(ERR_FILE_ACCESS); delete fp; return; } if (offset > 0 && fseek(*fp, (long)offset, SEEK_SET) == -1) { fclose(*fp); ld(ERR_FORMAT); delete fp; return; } } const char *display_name = (name_png ? name_png : "In-memory PNG data"); // Setup the PNG data structures... pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (pp) info = png_create_info_struct(pp); if (!pp || !info) { if (pp) png_destroy_read_struct(&pp, NULL, NULL); if (!from_memory) fclose(*fp); Fl::warning("Cannot allocate memory to read PNG file or data \"%s\".\n", display_name); w(0); h(0); d(0); ld(ERR_FORMAT); delete fp; return; } if (setjmp(png_jmpbuf(pp))) { png_destroy_read_struct(&pp, &info, NULL); if (!from_memory) fclose(*fp); Fl::warning("PNG file or data \"%s\" is too large or contains errors!\n", display_name); w(0); h(0); d(0); ld(ERR_FORMAT); delete fp; return; } if (from_memory) { png_mem_data.current = buffer_png; png_mem_data.last = buffer_png + maxsize; png_mem_data.pp = pp; // Initialize the function pointer to the PNG read "engine"... png_set_read_fn (pp, (png_voidp) &png_mem_data, png_read_data_from_mem); } else { png_init_io(pp, *fp); // Initialize the PNG file read "engine"... } // Get the image dimensions and convert to grayscale or RGB... png_read_info(pp, info); if (png_get_color_type(pp, info) == PNG_COLOR_TYPE_PALETTE) png_set_expand(pp); if (png_get_color_type(pp, info) & PNG_COLOR_MASK_COLOR) channels = 3; else channels = 1; int num_trans = 0; png_get_tRNS(pp, info, 0, &num_trans, 0); if ((png_get_color_type(pp, info) & PNG_COLOR_MASK_ALPHA) || (num_trans != 0)) channels ++; w((int)(png_get_image_width(pp, info))); h((int)(png_get_image_height(pp, info))); d(channels); if (png_get_bit_depth(pp, info) < 8) { png_set_packing(pp); png_set_expand(pp); } else if (png_get_bit_depth(pp, info) == 16) png_set_strip_16(pp); # if defined(HAVE_PNG_GET_VALID) && defined(HAVE_PNG_SET_TRNS_TO_ALPHA) // Handle transparency... if (png_get_valid(pp, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(pp); # endif // HAVE_PNG_GET_VALID && HAVE_PNG_SET_TRNS_TO_ALPHA if (((size_t)w()) * h() * d() > max_size() ) longjmp(png_jmpbuf(pp), 1); array = new uchar[w() * h() * d()]; alloc_array = 1; // Allocate pointers... rows = new png_bytep[h()]; for (i = 0; i < h(); i ++) rows[i] = (png_bytep)(array + i * w() * d()); // Read the image, handling interlacing as needed... for (i = png_set_interlace_handling(pp); i > 0; i --) png_read_rows(pp, rows, NULL, h()); if (channels == 4) Fl::system_driver()->png_extra_rgba_processing((uchar*)array, w(), h()); // Free memory and return... delete[] rows; png_read_end(pp, info); png_destroy_read_struct(&pp, &info, NULL); if (from_memory) { if (w() && h() && name_png) { Fl_Shared_Image *si = new Fl_Shared_Image(name_png, this); si->add(); } } else { fclose(*fp); } delete fp; #endif // HAVE_LIBPNG && HAVE_LIBZ } fltk-1.4.3/src/fl_dnd_win32.cxx0000644000175000017500000004333515004135251016400 0ustar albrechtalbrecht// // Drag & Drop code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Note: this file contains platform specific code and will therefore // not be processed by doxygen (see Doxyfile.in). // This file contains Windows-specific code for FLTK which is always linked // in. Search other files for "_WIN32" or filenames ending in _win32.cxx // for other system-specific code. #include #include #include #include "Fl_Window_Driver.H" #include #include "drivers/WinAPI/Fl_WinAPI_Screen_Driver.H" #include "flstring.h" #include #include #include #include #include #if defined(__CYGWIN__) #include #include #endif extern char *fl_selection_buffer[2]; extern int fl_selection_length[2]; extern int fl_selection_buffer_length[2]; extern char fl_i_own_selection[2]; extern char *fl_locale2utf8(const char *s, UINT codepage = 0); extern unsigned int fl_codepage; Fl_Window *fl_dnd_target_window = 0; #include #include #include /** subclass the IDropTarget to receive data from DnD operations */ class FLDropTarget : public IDropTarget { DWORD m_cRefCount; // for "statistics" only (issue #569) DWORD lastEffect; int px, py; public: FLDropTarget() : m_cRefCount(0) { } // initialize virtual ~FLDropTarget() { } HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID *ppvObject ) FL_OVERRIDE { if (IID_IUnknown==riid || IID_IDropTarget==riid) { *ppvObject=this; ((LPUNKNOWN)*ppvObject)->AddRef(); return S_OK; } *ppvObject = NULL; return E_NOINTERFACE; } ULONG STDMETHODCALLTYPE AddRef() FL_OVERRIDE { return ++m_cRefCount; } ULONG STDMETHODCALLTYPE Release() FL_OVERRIDE { long nTemp; nTemp = --m_cRefCount; // this is a static object, do not 'delete this' (issue #569) return nTemp; } HRESULT STDMETHODCALLTYPE DragEnter( IDataObject *pDataObj, DWORD /*grfKeyState*/, POINTL pt, DWORD *pdwEffect) FL_OVERRIDE { if( !pDataObj ) return E_INVALIDARG; // set e_modifiers here from grfKeyState, set e_x and e_root_x // check if FLTK handles this drag and return if it can't (i.e. BMP drag without filename) POINT ppt; Fl::e_x_root = ppt.x = pt.x; Fl::e_y_root = ppt.y = pt.y; HWND hWnd = WindowFromPoint( ppt ); Fl_Window *target = fl_find( hWnd ); if (target) { float s = Fl::screen_driver()->scale(Fl_Window_Driver::driver(target)->screen_num()); Fl::e_x_root = int(Fl::e_x_root / s); Fl::e_y_root = int(Fl::e_y_root / s); Fl::e_x = Fl::e_x_root-target->x(); Fl::e_y = Fl::e_y_root-target->y(); } fl_dnd_target_window = target; px = pt.x; py = pt.y; if (fillCurrentDragData(pDataObj)) { // FLTK has no mechanism yet for the different drop effects, so we allow move and copy if ( target && Fl::handle( FL_DND_ENTER, target ) ) *pdwEffect = DROPEFFECT_MOVE|DROPEFFECT_COPY; //|DROPEFFECT_LINK; else *pdwEffect = DROPEFFECT_NONE; } else { *pdwEffect = DROPEFFECT_NONE; } lastEffect = *pdwEffect; return S_OK; } HRESULT STDMETHODCALLTYPE DragOver( DWORD /*grfKeyState*/, POINTL pt, DWORD *pdwEffect) FL_OVERRIDE { if ( px==pt.x && py==pt.y ) { *pdwEffect = lastEffect; return S_OK; } if ( !fl_dnd_target_window ) { *pdwEffect = lastEffect = DROPEFFECT_NONE; return S_OK; } // set e_modifiers here from grfKeyState, set e_x and e_root_x Fl::e_x_root = pt.x; Fl::e_y_root = pt.y; if (fl_dnd_target_window) { float s = Fl::screen_driver()->scale(Fl_Window_Driver::driver(fl_dnd_target_window)->screen_num()); Fl::e_x_root = int(Fl::e_x_root /s); Fl::e_y_root = int(Fl::e_y_root /s); Fl::e_x = Fl::e_x_root-fl_dnd_target_window->x(); Fl::e_y = Fl::e_y_root-fl_dnd_target_window->y(); } if (fillCurrentDragData(0)) { // Fl_Group will change DND_DRAG into DND_ENTER and DND_LEAVE if needed if ( Fl::handle( FL_DND_DRAG, fl_dnd_target_window ) ) *pdwEffect = DROPEFFECT_MOVE|DROPEFFECT_COPY; //|DROPEFFECT_LINK; else *pdwEffect = DROPEFFECT_NONE; } else { *pdwEffect = DROPEFFECT_NONE; } px = pt.x; py = pt.y; lastEffect = *pdwEffect; // show insert position if dnd'ing in the same window/process (STR #3209) Fl::flush(); return S_OK; } HRESULT STDMETHODCALLTYPE DragLeave() FL_OVERRIDE { if ( fl_dnd_target_window && fillCurrentDragData(0)) { Fl::handle( FL_DND_LEAVE, fl_dnd_target_window ); fl_dnd_target_window = 0; clearCurrentDragData(); } return S_OK; } HRESULT STDMETHODCALLTYPE Drop( IDataObject *data, DWORD /*grfKeyState*/, POINTL pt, DWORD* /*pdwEffect*/) FL_OVERRIDE { if ( !fl_dnd_target_window ) return S_OK; Fl_Window *target = fl_dnd_target_window; fl_dnd_target_window = 0; Fl::e_x_root = pt.x; Fl::e_y_root = pt.y; float s = Fl::screen_driver()->scale(Fl_Window_Driver::driver(target)->screen_num()); Fl::e_x_root = int(Fl::e_x_root / s); Fl::e_y_root = int(Fl::e_y_root / s); if (target) { Fl::e_x = Fl::e_x_root-target->x(); Fl::e_y = Fl::e_y_root-target->y(); } // tell FLTK that the user released an object on this widget if ( !Fl::handle( FL_DND_RELEASE, target ) ) return S_OK; Fl_Widget *w = target; while (w->parent()) w = w->window(); HWND hwnd = fl_xid( (Fl_Window*)w ); if (fillCurrentDragData(data)) { int old_event = Fl::e_number; char *a, *b; a = b = currDragData; while (*a) { // strip the CRLF pairs if (*a == '\r' && a[1] == '\n') a++; else *b++ = *a++; } *b = 0; Fl::e_text = currDragData; Fl::e_length = (int) (b - currDragData); Fl::belowmouse()->handle(Fl::e_number = FL_PASTE); // e_text will be invalid after this call Fl::e_number = old_event; SetForegroundWindow( hwnd ); clearCurrentDragData(); return S_OK; } return S_OK; } private: static IDataObject *currDragRef; static char *currDragData; static int currDragSize; static char currDragResult; static void clearCurrentDragData() { currDragRef = 0; if (currDragData) free(currDragData); currDragData = 0; currDragSize = 0; currDragResult = 0; } static char fillCurrentDragData(IDataObject *data) { // shortcut through this whole procedure if there is no fresh data if (!data) return currDragResult; // shortcut through this whole procedure if this is still the same drag event // (* this is safe, because 'currDragRef' is cleared on Leave and Drop events) if (data==currDragRef) return currDragResult; // clear currDrag* for a new drag event clearCurrentDragData(); currDragRef = data; // fill currDrag* with UTF-8 data, if available FORMATETC fmt = { 0 }; STGMEDIUM medium = { 0 }; fmt.tymed = TYMED_HGLOBAL; fmt.dwAspect = DVASPECT_CONTENT; fmt.lindex = -1; fmt.cfFormat = CF_UNICODETEXT; // if it is UNICODE text, return a UTF-8-converted copy of it if ( data->GetData( &fmt, &medium )==S_OK ) { void *stuff = GlobalLock( medium.hGlobal ); unsigned srclen = 0; const wchar_t *wstuff = (const wchar_t *)stuff; while (*wstuff++) srclen++; wstuff = (const wchar_t *)stuff; unsigned utf8len = fl_utf8fromwc(NULL, 0, wstuff, srclen); currDragSize = utf8len; currDragData = (char*)malloc(utf8len + 1); fl_utf8fromwc(currDragData, currDragSize+1, wstuff, srclen+1); // include null-byte GlobalUnlock( medium.hGlobal ); ReleaseStgMedium( &medium ); currDragResult = 1; return currDragResult; } fmt.cfFormat = CF_TEXT; // if it is CP1252 text, return a UTF-8-converted copy of it if ( data->GetData( &fmt, &medium )==S_OK ) { int len; char *p, *q, *last; unsigned u; void *stuff = GlobalLock( medium.hGlobal ); currDragData = (char*)malloc(3 * strlen((char*)stuff) + 10); p = (char*)stuff; last = p + strlen(p); q = currDragData; while (p < last) { u = fl_utf8decode(p, last, &len); p += len; len = fl_utf8encode(u, q); q += len; } *q = 0; currDragSize = (int) (q - currDragData); currDragData = (char*)realloc(currDragData, currDragSize + 1); GlobalUnlock( medium.hGlobal ); ReleaseStgMedium( &medium ); currDragResult = 1; return currDragResult; } // else fill currDrag* with filenames, if possible memset(&fmt, 0, sizeof(fmt)); fmt.tymed = TYMED_HGLOBAL; fmt.dwAspect = DVASPECT_CONTENT; fmt.lindex = -1; fmt.cfFormat = CF_HDROP; // if it is a pathname list, send an FL_PASTE with a \n separated list of filepaths if ( data->GetData( &fmt, &medium )==S_OK ) { HDROP hdrop = (HDROP)medium.hGlobal; int i, n, nn = 0, nf = DragQueryFileW( hdrop, (UINT)-1, 0, 0 ); for ( i=0; ihandle(FL_DROP); // free( Fl::e_text ); ReleaseStgMedium( &medium ); currDragResult = 1; return currDragResult; } currDragResult = 0; return currDragResult; } } flDropTarget; IDropTarget *flIDropTarget = &flDropTarget; IDataObject *FLDropTarget::currDragRef = 0; char *FLDropTarget::currDragData = 0; int FLDropTarget::currDragSize = 0; char FLDropTarget::currDragResult = 0; /** this class is needed to allow FLTK apps to be a DnD source */ class FLDropSource : public IDropSource { DWORD m_cRefCount; public: FLDropSource() { m_cRefCount = 0; } virtual ~FLDropSource() { } HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID *ppvObject ) FL_OVERRIDE { if (IID_IUnknown==riid || IID_IDropSource==riid) { *ppvObject=this; ((LPUNKNOWN)*ppvObject)->AddRef(); return S_OK; } *ppvObject = NULL; return E_NOINTERFACE; } ULONG STDMETHODCALLTYPE AddRef() FL_OVERRIDE { return ++m_cRefCount; } ULONG STDMETHODCALLTYPE Release() FL_OVERRIDE { long nTemp; nTemp = --m_cRefCount; if(nTemp==0) delete this; return nTemp; } STDMETHODIMP GiveFeedback( DWORD ) FL_OVERRIDE { return DRAGDROP_S_USEDEFAULTCURSORS; } STDMETHODIMP QueryContinueDrag( BOOL esc, DWORD keyState ) FL_OVERRIDE { if ( esc ) return DRAGDROP_S_CANCEL; if ( !(keyState & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON)) ) return DRAGDROP_S_DROP; return S_OK; } }; class FLEnum : public IEnumFORMATETC { public: int n; LONG m_lRefCount; ULONG __stdcall AddRef(void) FL_OVERRIDE { return InterlockedIncrement(&m_lRefCount); } ULONG __stdcall Release(void) FL_OVERRIDE { LONG count = InterlockedDecrement(&m_lRefCount); if(count == 0) { delete this; return 0; } else { return count; } } HRESULT __stdcall QueryInterface(REFIID iid, void **ppvObject) FL_OVERRIDE { if(iid == IID_IEnumFORMATETC || iid == IID_IUnknown) { AddRef(); *ppvObject = this; return S_OK; } else { *ppvObject = 0; return E_NOINTERFACE; } } HRESULT __stdcall Next(ULONG celt, FORMATETC * rgelt, ULONG *pceltFetched) FL_OVERRIDE { if (n > 0) return S_FALSE; for (ULONG i = 0; i < celt; i++) { n++; rgelt->cfFormat = CF_HDROP; rgelt->dwAspect = DVASPECT_CONTENT; rgelt->lindex = -1; rgelt->ptd = NULL; rgelt->tymed = TYMED_HGLOBAL; } if (pceltFetched) *pceltFetched = celt; return S_OK; } HRESULT __stdcall Skip(ULONG celt) FL_OVERRIDE { n += celt; return (n == 0) ? S_OK : S_FALSE; } HRESULT __stdcall Reset(void) FL_OVERRIDE { n = 0; return S_OK; } HRESULT __stdcall Clone(IEnumFORMATETC **ppenum) FL_OVERRIDE { *ppenum = new FLEnum(); return S_OK; } FLEnum(void) { m_lRefCount = 1; n = 0; } virtual ~FLEnum(void) { n = 0; } }; /** This is the actual object that FLTK can drop somewhere. The implementation is minimal, but it should work with all decent Win32 drop targets */ class FLDataObject : public IDataObject { DWORD m_cRefCount; //FLEnum *m_EnumF; public: FLDataObject() { m_cRefCount = 1; }// m_EnumF = new FLEnum();} virtual ~FLDataObject() { } HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID *ppvObject ) FL_OVERRIDE { if (IID_IUnknown==riid || IID_IDataObject==riid) { *ppvObject=this; ((LPUNKNOWN)*ppvObject)->AddRef(); return S_OK; } *ppvObject = NULL; return E_NOINTERFACE; } ULONG STDMETHODCALLTYPE AddRef() FL_OVERRIDE { return ++m_cRefCount; } ULONG STDMETHODCALLTYPE Release() FL_OVERRIDE { long nTemp; nTemp = --m_cRefCount; if(nTemp==0) delete this; return nTemp; } // GetData currently allows UNICODE text through Global Memory only HRESULT STDMETHODCALLTYPE GetData( FORMATETC *pformatetcIn, STGMEDIUM *pmedium ) FL_OVERRIDE { if ((pformatetcIn->dwAspect & DVASPECT_CONTENT) && (pformatetcIn->tymed & TYMED_HGLOBAL) && (pformatetcIn->cfFormat == CF_UNICODETEXT)) { int utf16_len = fl_utf8toUtf16(fl_selection_buffer[0], fl_selection_length[0], 0, 0); HGLOBAL gh = GlobalAlloc( GHND, utf16_len * 2 + 2 ); char *pMem = (char*)GlobalLock( gh ); fl_utf8toUtf16(fl_selection_buffer[0], fl_selection_length[0], (unsigned short*)pMem, utf16_len + 1); // HGLOBAL gh = GlobalAlloc( GHND| GMEM_SHARE, // (fl_selection_length[0]+4) * sizeof(short) // + sizeof(DROPFILES)); // unsigned char *pMem = (unsigned char*)GlobalLock( gh ); // if (!pMem) { // GlobalFree(gh); // return DV_E_FORMATETC; // } // DROPFILES *df =(DROPFILES*) pMem; // int l; // df->pFiles = sizeof(DROPFILES); // df->pt.x = 0; // df->pt.y = 0; // df->fNC = FALSE; // for (int i = 0; i < fl_selection_length[0]; i++) { // if (fl_selection_buffer[0][i] == '\n') { // fl_selection_buffer[0][i] = '\0'; // } // } // // df->fWide = TRUE; // l = fl_utf2unicode((unsigned char*)fl_selection_buffer[0], // fl_selection_length[0], (wchar_t*)(((char*)pMem) // + sizeof(DROPFILES))); // // pMem[l * sizeof(WCHAR) + sizeof(DROPFILES)] = 0; // pMem[l * sizeof(WCHAR) + 1 + sizeof(DROPFILES)] = 0; // pMem[l * sizeof(WCHAR) + 2 + sizeof(DROPFILES)] = 0; // pMem[l * sizeof(WCHAR) + 3 + sizeof(DROPFILES)] = 0; pmedium->tymed = TYMED_HGLOBAL; pmedium->hGlobal = gh; pmedium->pUnkForRelease = NULL; GlobalUnlock( gh ); return S_OK; } return DV_E_FORMATETC; } HRESULT STDMETHODCALLTYPE QueryGetData( FORMATETC *pformatetc ) FL_OVERRIDE { if ((pformatetc->dwAspect & DVASPECT_CONTENT) && (pformatetc->tymed & TYMED_HGLOBAL) && (pformatetc->cfFormat == CF_UNICODETEXT)) return S_OK; return DV_E_FORMATETC; } // HRESULT STDMETHODCALLTYPE EnumFormatEtc( DWORD dir, IEnumFORMATETC** ppenumFormatEtc) { // *ppenumFormatEtc = m_EnumF; // return S_OK; // } // all the following methods are not really needed for a DnD object HRESULT STDMETHODCALLTYPE GetDataHere( FORMATETC* /*pformatetcIn*/, STGMEDIUM* /*pmedium*/) FL_OVERRIDE { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc( FORMATETC* /*in*/, FORMATETC* /*out*/) FL_OVERRIDE { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE SetData( FORMATETC* /*pformatetc*/, STGMEDIUM* /*pmedium*/, BOOL /*fRelease*/) FL_OVERRIDE { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE EnumFormatEtc( DWORD /*dir*/, IEnumFORMATETC** /*ppenumFormatEtc*/) FL_OVERRIDE { return E_NOTIMPL; } // HRESULT STDMETHODCALLTYPE EnumFormatEtc( DWORD dir, IEnumFORMATETC** ppenumFormatEtc) FL_OVERRIDE {*ppenumFormatEtc = m_EnumF; return S_OK;} HRESULT STDMETHODCALLTYPE DAdvise( FORMATETC* /*pformatetc*/, DWORD /*advf*/, IAdviseSink* /*pAdvSink*/, DWORD* /*pdwConnection*/) FL_OVERRIDE { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE DUnadvise( DWORD /*dwConnection*/) FL_OVERRIDE { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE EnumDAdvise( IEnumSTATDATA** /*ppenumAdvise*/) FL_OVERRIDE { return E_NOTIMPL; } }; int Fl_WinAPI_Screen_Driver::dnd(int unused) { DWORD dropEffect; ReleaseCapture(); FLDataObject *fdo = new FLDataObject; fdo->AddRef(); FLDropSource *fds = new FLDropSource; fds->AddRef(); HRESULT ret = DoDragDrop( fdo, fds, DROPEFFECT_MOVE|DROPEFFECT_LINK|DROPEFFECT_COPY, &dropEffect ); fdo->Release(); fds->Release(); Fl_Widget *w = Fl::pushed(); if ( w ) { int old_event = Fl::e_number; w->handle(Fl::e_number = FL_RELEASE); Fl::e_number = old_event; Fl::pushed( 0 ); } if ( ret==DRAGDROP_S_DROP ) return 1; // or DD_S_CANCEL return 0; } fltk-1.4.3/src/Fl_Native_File_Chooser_MAC.mm0000644000175000017500000006516015004135251020707 0ustar albrechtalbrecht// // FLTK native OS file chooser widget for macOS // // Copyright 2004 Greg Ercolano. // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // TODO: // o When doing 'open file', only dir is preset, not filename. // Possibly 'preset_file' could be used to select the filename. // #include #include // for fl_mac_os_version #include #include #include #include #define MAXFILTERS 80 #import #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0 # import #endif #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9 const NSInteger NSModalResponseOK = NSFileHandlingPanelOKButton; #endif #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 const NSUInteger NSControlSizeRegular = NSRegularControlSize; #endif class Fl_Quartz_Native_File_Chooser_Driver : public Fl_Native_File_Chooser_Driver { private: int _btype; // kind-of browser to show() int _options; // general options NSSavePanel *_panel; char **_pathnames; // array of pathnames int _tpathnames; // total pathnames char *_directory; // default pathname to use char *_title; // title for window char *_preset_file; // the 'save as' filename char *_filter; // user-side search filter, eg: // C Files\t*.[ch]\nText Files\t*.txt" char *_filt_names; // filter names (tab delimited) // eg. "C Files\tText Files" char *_filt_patt[MAXFILTERS]; // array of filter patterns, eg: // _filt_patt[0]="*.{cxx,h}" // _filt_patt[1]="*.txt" int _filt_total; // parse_filter() # of filters loaded int _filt_value; // index of the selected filter char *_errmsg; // error message // Private methods void errmsg(const char *msg); void clear_pathnames(); void set_single_pathname(const char *s); int get_saveas_basename(void); void clear_filters(); void parse_filter(const char *from); int post(); int runmodal(); public: Fl_Quartz_Native_File_Chooser_Driver(int val); ~Fl_Quartz_Native_File_Chooser_Driver(); void type(int t) FL_OVERRIDE; int type() const FL_OVERRIDE; void options(int o) FL_OVERRIDE; int options() const FL_OVERRIDE; int count() const FL_OVERRIDE; const char *filename() const FL_OVERRIDE; const char *filename(int i) const FL_OVERRIDE; void directory(const char *val) FL_OVERRIDE; const char *directory() const FL_OVERRIDE; void title(const char *t) FL_OVERRIDE; const char* title() const FL_OVERRIDE; const char *filter() const FL_OVERRIDE; void filter(const char *f) FL_OVERRIDE; int filters() const FL_OVERRIDE; void filter_value(int i) FL_OVERRIDE; int filter_value() const FL_OVERRIDE; void preset_file(const char*f) FL_OVERRIDE; const char* preset_file() const FL_OVERRIDE; const char *errmsg() const FL_OVERRIDE; int show() FL_OVERRIDE; }; Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { platform_fnfc = new Fl_Quartz_Native_File_Chooser_Driver(val); } // FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS void Fl_Quartz_Native_File_Chooser_Driver::clear_pathnames() { if ( _pathnames ) { while ( --_tpathnames >= 0 ) { _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]); } delete [] _pathnames; _pathnames = NULL; } _tpathnames = 0; } // SET A SINGLE PATHNAME void Fl_Quartz_Native_File_Chooser_Driver::set_single_pathname(const char *s) { clear_pathnames(); _pathnames = new char*[1]; _pathnames[0] = strnew(s); _tpathnames = 1; } // CONSTRUCTOR Fl_Quartz_Native_File_Chooser_Driver::Fl_Quartz_Native_File_Chooser_Driver(int val) : Fl_Native_File_Chooser_Driver(val) { _btype = val; _panel = NULL; _options = Fl_Native_File_Chooser::NO_OPTIONS; _pathnames = NULL; _tpathnames = 0; _title = NULL; _filter = NULL; _filt_names = NULL; memset(_filt_patt, 0, sizeof(char*) * MAXFILTERS); _filt_total = 0; _filt_value = 0; _directory = NULL; _preset_file = NULL; _errmsg = NULL; } // DESTRUCTOR Fl_Quartz_Native_File_Chooser_Driver::~Fl_Quartz_Native_File_Chooser_Driver() { // _opts // nothing to manage // _options // nothing to manage // _keepstate // nothing to manage // _tempitem // nothing to manage clear_pathnames(); _directory = strfree(_directory); _title = strfree(_title); _preset_file = strfree(_preset_file); _filter = strfree(_filter); //_filt_names // managed by clear_filters() //_filt_patt[i] // managed by clear_filters() //_filt_total // managed by clear_filters() clear_filters(); //_filt_value // nothing to manage _errmsg = strfree(_errmsg); } // GET TYPE OF BROWSER int Fl_Quartz_Native_File_Chooser_Driver::type() const { return(_btype); } // SET OPTIONS void Fl_Quartz_Native_File_Chooser_Driver::options(int val) { _options = val; } // GET OPTIONS int Fl_Quartz_Native_File_Chooser_Driver::options() const { return(_options); } // SHOW THE BROWSER WINDOW // Returns: // 0 - user picked a file // 1 - user cancelled // -1 - failed; errmsg() has reason // int Fl_Quartz_Native_File_Chooser_Driver::show() { // Make sure fltk interface updates before posting our dialog Fl::flush(); // POST BROWSER int err = post(); return(err); } // SET ERROR MESSAGE // Internal use only. // void Fl_Quartz_Native_File_Chooser_Driver::errmsg(const char *msg) { _errmsg = strfree(_errmsg); _errmsg = strnew(msg); } // RETURN ERROR MESSAGE const char *Fl_Quartz_Native_File_Chooser_Driver::errmsg() const { return(_errmsg ? _errmsg : "No error"); } // GET FILENAME const char* Fl_Quartz_Native_File_Chooser_Driver::filename() const { if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]); return(""); } // GET FILENAME FROM LIST OF FILENAMES const char* Fl_Quartz_Native_File_Chooser_Driver::filename(int i) const { if ( _pathnames && i < _tpathnames ) return(_pathnames[i]); return(""); } // GET TOTAL FILENAMES CHOSEN int Fl_Quartz_Native_File_Chooser_Driver::count() const { return(_tpathnames); } // PRESET PATHNAME // Value can be NULL for none. // void Fl_Quartz_Native_File_Chooser_Driver::directory(const char *val) { _directory = strfree(_directory); _directory = strnew(val); } // GET PRESET PATHNAME // Returned value can be NULL if none set. // const char* Fl_Quartz_Native_File_Chooser_Driver::directory() const { return(_directory); } // SET TITLE // Value can be NULL if no title desired. // void Fl_Quartz_Native_File_Chooser_Driver::title(const char *val) { _title = strfree(_title); _title = strnew(val); } // GET TITLE // Returned value can be NULL if none set. // const char *Fl_Quartz_Native_File_Chooser_Driver::title() const { return(_title); } // SET FILTER // Can be NULL if no filter needed // void Fl_Quartz_Native_File_Chooser_Driver::filter(const char *val) { _filter = strfree(_filter); _filter = strnew(val); // Parse filter user specified // IN: _filter = "C Files\t*.{cxx,h}\nText Files\t*.txt" // OUT: _filt_names = "C Files\tText Files" // _filt_patt[0] = "*.{cxx,h}" // _filt_patt[1] = "*.txt" // _filt_total = 2 // parse_filter(_filter); } // GET FILTER // Returned value can be NULL if none set. // const char *Fl_Quartz_Native_File_Chooser_Driver::filter() const { return(_filter); } // CLEAR ALL FILTERS // Internal use only. // void Fl_Quartz_Native_File_Chooser_Driver::clear_filters() { _filt_names = strfree(_filt_names); for (int i=0; i<_filt_total; i++) { _filt_patt[i] = strfree(_filt_patt[i]); } _filt_total = 0; } // PARSE USER'S FILTER SPEC // Parses user specified filter ('in'), // breaks out into _filt_patt[], _filt_names, and _filt_total. // // Handles: // IN: OUT:_filt_names OUT: _filt_patt // ------------------------------------ ------------------ --------------- // "*.{ma,mb}" "*.{ma,mb} Files" "*.{ma,mb}" // "*.[abc]" "*.[abc] Files" "*.[abc]" // "*.txt" "*.txt Files" "*.c" // "C Files\t*.[ch]" "C Files" "*.[ch]" // "C Files\t*.[ch]\nText Files\t*.cxx" "C Files" "*.[ch]" // // Parsing Mode: // IN:"C Files\t*.{cxx,h}" // ||||||| ||||||||| // mode: nnnnnnn wwwwwwwww // \_____/ \_______/ // Name Wildcard // void Fl_Quartz_Native_File_Chooser_Driver::parse_filter(const char *in) { clear_filters(); if ( ! in ) return; int has_name = strchr(in, '\t') ? 1 : 0; char mode = has_name ? 'n' : 'w'; // parse mode: n=title, w=wildcard char wildcard[1024] = ""; // parsed wildcard char name[1024] = ""; // Parse filter user specified for ( ; 1; in++ ) { //// DEBUG //// printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n", //// *in, mode, name, wildcard); switch (*in) { // FINISHED PARSING NAME? case '\t': if ( mode != 'n' ) goto regchar; mode = 'w'; break; // ESCAPE NEXT CHAR case '\\': ++in; goto regchar; // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS? case '\r': case '\n': case '\0': // TITLE // If user didn't specify a name, make one // if ( name[0] == '\0' ) { snprintf(name, sizeof(name), "%.*s Files", (int)sizeof(name)-10, wildcard); } // APPEND NEW FILTER TO LIST if ( wildcard[0] ) { // Add to filtername list // Tab delimit if more than one. We later break // tab delimited string into CFArray with // CFStringCreateArrayBySeparatingStrings() // if ( _filt_total ) { _filt_names = strapp(_filt_names, "\t"); } _filt_names = strapp(_filt_names, name); // Add filter to the pattern array _filt_patt[_filt_total++] = strnew(wildcard); } // RESET wildcard[0] = name[0] = '\0'; mode = strchr(in, '\t') ? 'n' : 'w'; // DONE? if ( *in == '\0' ) return; // done else continue; // not done yet, more filters // Parse all other chars default: // handle all non-special chars regchar: // handle regular char switch ( mode ) { case 'n': chrcat(name, *in); continue; case 'w': chrcat(wildcard, *in); continue; } break; } } //NOTREACHED } // SET PRESET FILE // Value can be NULL for none. // void Fl_Quartz_Native_File_Chooser_Driver::preset_file(const char* val) { _preset_file = strfree(_preset_file); _preset_file = strnew(val); } // PRESET FILE // Returned value can be NULL if none set. // const char* Fl_Quartz_Native_File_Chooser_Driver::preset_file() const { return(_preset_file); } void Fl_Quartz_Native_File_Chooser_Driver::filter_value(int val) { _filt_value = val; } int Fl_Quartz_Native_File_Chooser_Driver::filter_value() const { return(_filt_value); } int Fl_Quartz_Native_File_Chooser_Driver::filters() const { return(_filt_total); } #define UNLIKELYPREFIX "___fl_very_unlikely_prefix_" int Fl_Quartz_Native_File_Chooser_Driver::get_saveas_basename(void) { char *q = fl_strdup( [[[_panel URL] path] UTF8String] ); if ( !(_options & Fl_Native_File_Chooser::SAVEAS_CONFIRM) ) { const char *d = [[[[_panel URL] path] stringByDeletingLastPathComponent] UTF8String]; int l = (int)strlen(d) + 1; if (strcmp(d, "/") == 0) l = 1; int lu = strlen(UNLIKELYPREFIX); // Remove UNLIKELYPREFIX between directory and filename parts if (memcmp(q+l, UNLIKELYPREFIX, lu) == 0) memmove(q + l, q + l + lu, strlen(q + l + lu) + 1); } set_single_pathname( q ); free(q); return 0; } // SET THE TYPE OF BROWSER void Fl_Quartz_Native_File_Chooser_Driver::type(int val) { _btype = val; } /* Input filter= "C files\t*.{c,h}\nText files\t*.txt\n" patterns[0] = "*.{c,h}" patterns[1] = "*.txt" count = 2 Return: "C files (*.{c,h})\nText files (*.txt)\n" */ static char *prepareMacFilter(int count, const char *filter, char **patterns) { int rank = 0, l = 0; for (int i = 0; i < count; i++) { l += strlen(patterns[i]) + 3; } const char *p = filter; const int t_size = (int)strlen(p) + l + 1; char *q; q = new char[t_size]; const char *r, *s; char *t; t = q; do { // copy to t what is in filter removing what is between \t and \n, if any r = strchr(p, '\n'); if (!r) r = p + strlen(p); s = strchr(p, '\t'); if (s && s < r) { memcpy(q, p, s - p); q += s - p; if (rank < count) { snprintf(q, t_size-(q-t), " (%s)", patterns[rank]); q += strlen(q); } } else { memcpy(q, p, r - p); q += r - p; } rank++; *(q++) = '\n'; if (*r) p = r + 1; else p = r; } while(*p); *q = 0; return t; } @interface FLopenDelegate : NSObject #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 #endif { NSPopUpButton *nspopup; char **filter_pattern; } - (FLopenDelegate*)setPopup:(NSPopUpButton*)popup filter_pattern:(char**)pattern; - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename; - (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url; @end @implementation FLopenDelegate - (FLopenDelegate*)setPopup:(NSPopUpButton*)popup filter_pattern:(char**)pattern { nspopup = popup; filter_pattern = pattern; return self; } - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename { if ( [nspopup indexOfSelectedItem] == [nspopup numberOfItems] - 1) return YES; BOOL isdir = NO; [[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isdir]; if (isdir) return YES; if ( fl_filename_match([filename fileSystemRepresentation], filter_pattern[([nspopup indexOfSelectedItem])]) ) return YES; return NO; } - (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url { return [self panel:sender shouldShowFilename:[url path]]; } @end @interface FLsaveDelegate : NSObject #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 #endif { NSSavePanel *dialog; BOOL saveas_confirm; } - (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag; - (void)control_allowed_types:(const char *)p; - (void)changedPopup:(id)sender; - (void)panel:(NSSavePanel*)p; - (void)option:(BOOL)o; @end @implementation FLsaveDelegate - (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag { if ( !okFlag || saveas_confirm ) return filename; // User has clicked save, and no overwrite confirmation should occur. // To get the latter, we need to change the name we return (hence the prefix): return [@ UNLIKELYPREFIX stringByAppendingString:filename]; } - (void)control_allowed_types:(const char *)p { NSString *ext = [NSString stringWithUTF8String:p]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0 if (@available(macOS 11.0, *)) { UTType *type = [UTType typeWithFilenameExtension:ext]; // 11.0 + framework UniformTypeIdentifiers [dialog setAllowedContentTypes:[NSArray arrayWithObject:type]]; // 11.0 } else #endif if (fl_mac_os_version >= 100900) { [dialog performSelector:@selector(setAllowedFileTypes:) withObject:[NSArray arrayWithObject:ext]]; } } - (void)changedPopup:(id)sender // runs when the save panel popup menu changes output file type // correspondingly changes the extension of the output file name { if (fl_mac_os_version < 100600) return; // because of setNameFieldStringValue and nameFieldStringValue char *s = fl_strdup([[(NSPopUpButton*)sender titleOfSelectedItem] UTF8String]); if (!s) return; char *p = strchr(s, '('); if (!p) p = s; p = strchr(p, '.'); if (!p) {free(s); return;} p++; while (*p == ' ') p++; if (!p || *p == '{') {free(s); return;} char *q = p+1; while (*q != ' ' && *q != ')' && *q != 0) q++; *q = 0; NSString *ns = [NSString stringWithFormat:@"%@.%@", [[dialog performSelector:@selector(nameFieldStringValue)] stringByDeletingPathExtension], [NSString stringWithUTF8String:p]]; [self control_allowed_types:p]; free(s); [dialog performSelector:@selector(setNameFieldStringValue:) withObject:ns]; } - (void)panel:(NSSavePanel*)p { dialog = p; } - (void) option:(BOOL)o { saveas_confirm = o; } @end @interface FLHiddenFilesAction : NSObject { @public NSSavePanel *panel; NSButton *button; } - (void)action; @end @implementation FLHiddenFilesAction - (void)action { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 if (fl_mac_os_version >= 100600) { [panel setShowsHiddenFiles:[button intValue]]; // 10.6 } #endif } @end static NSPopUpButton *createPopupAccessory(NSSavePanel *panel, const char *filter, const char *title, int rank) { NSPopUpButton *popup = nil; NSRect rectview = NSMakeRect(5, 5, 350, filter ? 60 : 30); NSView *view = [[[NSView alloc] initWithFrame:rectview] autorelease]; NSRect rectbox = NSMakeRect(0, 3, 140, 20 ); // the "Show hidden files" button NSRect hidden_files_rect = {{150, 0}, {80, 30}}; if (filter) hidden_files_rect.origin.y = 35; NSButton *hidden_files = [[[NSButton alloc] initWithFrame:hidden_files_rect] autorelease]; [hidden_files setButtonType: #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 NSButtonTypeSwitch #else NSSwitchButton #endif ]; [hidden_files setTitle:[NSString stringWithUTF8String:Fl_File_Chooser::hidden_label]]; [hidden_files sizeToFit]; [hidden_files setIntValue:0]; [view addSubview:hidden_files]; static FLHiddenFilesAction *target = [[FLHiddenFilesAction alloc] init]; // never released target->panel = panel; target->button = hidden_files; [hidden_files setAction:@selector(action)]; [hidden_files setTarget:target]; if (filter) { NSBox *box = [[[NSBox alloc] initWithFrame:rectbox] autorelease]; NSRect rectpop = NSMakeRect(105, 0, 246, 30 ); popup = [[[NSPopUpButton alloc ] initWithFrame:rectpop pullsDown:NO] autorelease]; [view addSubview:box]; [view addSubview:popup]; NSString *nstitle = [[NSString alloc] initWithUTF8String:title]; [box setTitle:nstitle]; [box setTitlePosition:NSBelowTop]; [nstitle release]; NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSize]]; [box setTitleFont:font]; [box sizeToFit]; // horizontally move box to fit the locale-dependent width of its title NSRect r=[box frame]; r.origin.x = rectpop.origin.x - r.size.width; r.origin.y = rectpop.origin.y + (rectpop.size.height - r.size.height) / 2; [box setFrame:r]; CFStringRef tab = CFSTR("\n"); CFStringRef tmp_cfs; tmp_cfs = CFStringCreateWithCString(NULL, filter, kCFStringEncodingUTF8); CFArrayRef array = CFStringCreateArrayBySeparatingStrings(NULL, tmp_cfs, tab); CFRelease(tmp_cfs); CFRelease(tab); [popup addItemsWithTitles:(NSArray*)array]; NSMenuItem *item = [popup itemWithTitle:@""]; if (item) [popup removeItemWithTitle:@""]; CFRelease(array); [popup selectItemAtIndex:rank]; } [panel setAccessoryView:view]; return popup; } int Fl_Quartz_Native_File_Chooser_Driver::runmodal() { NSString *dir = nil; NSString *fname = nil; NSString *preset = nil; NSInteger retval; if (_preset_file) { preset = [[NSString alloc] initWithUTF8String:_preset_file]; if (strchr(_preset_file, '/') != NULL) { dir = [[NSString alloc] initWithString:[preset stringByDeletingLastPathComponent]]; } fname = [preset lastPathComponent]; } if (_directory && !dir) dir = [[NSString alloc] initWithUTF8String:_directory]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 && defined(__BLOCKS__) if (fl_mac_os_version >= 100600) { bool usepath = false; NSString *path = nil; if (dir && fname && [_panel isKindOfClass:[NSOpenPanel class]]) { // STR #3406: If both dir + fname specified, combine and pass to setDirectoryURL path = [[NSString alloc] initWithFormat:@"%@/%@", dir, fname]; // dir+fname -> path // See if full path to file exists // If dir exists but fname doesn't, avoid using setDirectoryURL, // otherwise NSSavePanel falls back to showing user's Documents dir. // if ( [[NSFileManager defaultManager] fileExistsAtPath:path] ) usepath = true; } if (usepath) { // Set only if full path exists [_panel setDirectoryURL:[NSURL fileURLWithPath:path]]; // 10.6 } else { // didn't setDirectoryURL to full path? Set dir + fname separately.. if (dir) [_panel setDirectoryURL:[NSURL fileURLWithPath:dir]]; // 10.6 if (fname) [_panel setNameFieldStringValue:fname]; // 10.6 } [path release]; if ([NSApp mainWindow]) { __block NSInteger complete = -1; [_panel beginSheetModalForWindow:[NSApp mainWindow] completionHandler:^(NSInteger returnCode) { complete = returnCode; // this block runs after OK or Cancel was triggered in file dialog }]; // 10.6 this message returns immediately and begins the file dialog as a sheet while (complete == -1) Fl::wait(100); // loop until end of file dialog retval = complete; } else { retval = [_panel runModal]; } } else #endif { // the deprecation warning can be ignored because runs only for macOS < 10.6 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" retval = [_panel runModalForDirectory:dir file:fname]; // deprecated in 10.6 #pragma clang diagnostic pop } [dir release]; [preset release]; return (retval == NSModalResponseOK ? 1 : 0); } // POST BROWSER // Internal use only. // Assumes '_opts' has been initialized. // // Returns: // 0 - user picked a file // 1 - user cancelled // -1 - failed; errmsg() has reason // int Fl_Quartz_Native_File_Chooser_Driver::post() { // INITIALIZE BROWSER if ( _filt_total == 0 ) { // Make sure they match _filt_value = 0; // TBD: move to someplace more logical? } fl_open_display(); NSAutoreleasePool *localPool; localPool = [[NSAutoreleasePool alloc] init]; switch (_btype) { case Fl_Native_File_Chooser::BROWSE_FILE: case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: case Fl_Native_File_Chooser::BROWSE_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: _panel = [NSOpenPanel openPanel]; break; case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: _panel = [NSSavePanel savePanel]; break; } BOOL is_open_panel = [_panel isKindOfClass:[NSOpenPanel class]]; if (_title) { SEL title_or_message = (is_open_panel && fl_mac_os_version >= 101200) ? @selector(setMessage:) : @selector(setTitle:); [_panel performSelector:title_or_message withObject:[NSString stringWithUTF8String:_title]]; } switch (_btype) { case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: [(NSOpenPanel*)_panel setAllowsMultipleSelection:YES]; break; case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: [(NSOpenPanel*)_panel setAllowsMultipleSelection:YES]; /* FALLTHROUGH */ case Fl_Native_File_Chooser::BROWSE_DIRECTORY: [(NSOpenPanel*)_panel setCanChooseDirectories:YES]; break; case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: [_panel setCanCreateDirectories:YES]; break; } // SHOW THE DIALOG NSWindow *key = [NSApp keyWindow]; NSPopUpButton *popup = nil; if ( is_open_panel ) { if (_filt_total) { char *t = prepareMacFilter(_filt_total, _filter, _filt_patt); popup = createPopupAccessory(_panel, t, Fl_File_Chooser::show_label, 0); delete[] t; [[popup menu] addItem:[NSMenuItem separatorItem]]; [popup addItemWithTitle:[NSString stringWithUTF8String:Fl_File_Chooser::all_files_label]]; [popup setAction:@selector(validateVisibleColumns)]; [popup setTarget:(NSObject*)_panel]; FLopenDelegate *openDelegate = [[[FLopenDelegate alloc] init] autorelease]; [openDelegate setPopup:popup filter_pattern:_filt_patt]; [_panel setDelegate:openDelegate]; } else createPopupAccessory(_panel, NULL, Fl_File_Chooser::show_label, 0); } else { FLsaveDelegate *saveDelegate = [[[FLsaveDelegate alloc] init] autorelease]; [_panel setAllowsOtherFileTypes:YES]; [_panel setDelegate:saveDelegate]; [saveDelegate option:(_options & Fl_Native_File_Chooser::SAVEAS_CONFIRM)]; if (_filt_total) { if (_filt_value >= _filt_total) _filt_value = _filt_total - 1; char *t = prepareMacFilter(_filt_total, _filter, _filt_patt); popup = createPopupAccessory(_panel, t, [[_panel nameFieldLabel] UTF8String], _filt_value); delete[] t; if (_options & Fl_Native_File_Chooser::USE_FILTER_EXT) { [popup setAction:@selector(changedPopup:)]; [popup setTarget:saveDelegate]; [saveDelegate panel:(NSSavePanel*)_panel]; if (fl_mac_os_version >= 100900) { char *p = _filt_patt[_filt_value]; char *q = strchr(p, '.'); if(!q) q = p-1; do q++; while (*q==' ' || *q=='{'); p = fl_strdup(q); q = strchr(p, ','); if (q) *q = 0; [saveDelegate control_allowed_types:p]; free(p); } } [_panel setCanSelectHiddenExtension:YES]; [_panel setExtensionHidden:NO]; } else createPopupAccessory(_panel, NULL, Fl_File_Chooser::show_label, 0); } int retval = runmodal(); if (_filt_total) { _filt_value = (int)[popup indexOfSelectedItem]; } if ( retval == 1 ) { if (is_open_panel) { clear_pathnames(); NSArray *array = [(NSOpenPanel*)_panel URLs]; _tpathnames = (int)[array count]; _pathnames = new char*[_tpathnames]; for(int i = 0; i < _tpathnames; i++) { _pathnames[i] = strnew([[(NSURL*)[array objectAtIndex:i] path] UTF8String]); } } else get_saveas_basename(); } [key makeKeyWindow]; [localPool release]; return (retval == 1 ? 0 : 1); } fltk-1.4.3/src/Fl_Sys_Menu_Bar_Driver.H0000644000175000017500000000472015004135251017772 0ustar albrechtalbrecht// // system menu bar widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef Fl_Sys_Menu_Bar_Driver_H #define Fl_Sys_Menu_Bar_Driver_H #if !defined(FL_DOXYGEN) #include class Fl_Sys_Menu_Bar_Driver { friend class Fl_Sys_Menu_Bar; public: static Fl_Sys_Menu_Bar::window_menu_style_enum window_menu_style_; static Fl_Sys_Menu_Bar_Driver *driver_; // to be assigned with a unique object of this class or of a derived class Fl_Sys_Menu_Bar *bar; Fl_Sys_Menu_Bar_Driver(); virtual ~Fl_Sys_Menu_Bar_Driver(); virtual void update() {} virtual void draw() { bar->Fl_Menu_Bar::draw();} virtual void about(Fl_Callback *, void *) {} virtual int add(const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) { return bar->Fl_Menu_Bar::add(label, shortcut, cb, user_data, flags); } virtual int add(const char* str) { return bar->Fl_Menu_Bar::add(str); } virtual int insert(int index, const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) { return bar->Fl_Menu_Bar::insert(index, label, shortcut, cb, user_data, flags); } virtual void menu(const Fl_Menu_Item *m) { bar->Fl_Menu_Bar::menu(m); } virtual void shortcut(int i, int s) { bar->Fl_Menu_Bar::shortcut(i, s); } virtual void setonly(Fl_Menu_Item *item) { bar->Fl_Menu_Bar::setonly(item); } virtual void clear() { bar->Fl_Menu_Bar::clear(); } virtual int clear_submenu(int index) { return bar->Fl_Menu_Bar::clear_submenu(index);} virtual void remove(int index) { bar->Fl_Menu_Bar::remove(index); } virtual void replace(int index, const char *name) { bar->Fl_Menu_Bar::replace(index, name); } virtual void mode(int i, int fl) { bar->Fl_Menu_Bar::mode(i, fl); } virtual void create_window_menu() {} virtual void play_menu(const Fl_Menu_Item *) {} static Fl_Sys_Menu_Bar::window_menu_style_enum window_menu_style() { return window_menu_style_; } static void window_menu_style(Fl_Sys_Menu_Bar::window_menu_style_enum style) { window_menu_style_ = style; } }; #endif // !defined(FL_DOXYGEN) #endif // Fl_Sys_Menu_Bar_Driver_H fltk-1.4.3/src/fl_draw_arrow.cxx0000644000175000017500000001746115004135251016761 0ustar albrechtalbrecht// // Arrow drawing code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // These functions implement drawing of all "arrow like" GUI elements in scrollbars, // choice widgets, menus, etc. // Implementation of fl_draw_arrow(...) dependent on the active FLTK Scheme. #include #include #include #include "fl_oxy.h" // Debug mode: if you design a widget or want to check its layout, // then enable one or both flags of DEBUG_ARROW (below) so you can // see where the arrows (i.e. their bounding boxes) are positioned #ifndef DEBUG_ARROW #define DEBUG_ARROW (0) // 0 = off, 1 = green background, 2 = red frame, 3 = both #endif void debug_arrow(Fl_Rect r) { #if (DEBUG_ARROW & 1) fl_color(fl_lighter(FL_GREEN)); fl_rectf(r); #endif #if (DEBUG_ARROW & 2) fl_color(FL_RED); fl_line_style(FL_SOLID, 1); // work around X11 bug with default line width 0 fl_rect(r); fl_line_style(FL_SOLID, 0); // reset line style #endif } // debug_arrow // Calculate the applicable arrow size. // Imagine an arrow pointing to the right side: // - the calculated size s is the width of the arrow, // - the height of the arrow is 2 * s. // The calculation takes into account that we need one pixel padding at // all sides and that the available space doesn't need to be a square, // i.e. it's possible that r.w() != r.h(). static int arrow_size(Fl_Rect r, Fl_Orientation o, int num = 1) { int s, d1, d2; switch(o) { case FL_ORIENT_LEFT: case FL_ORIENT_RIGHT: d1 = (r.w() - 2) / num; d2 = (r.h() - 2) / 2; break; default: // up or down arrow d1 = (r.h() - 2) / num; d2 = (r.w() - 2) / 2; break; } s = d1 < d2 ? d1 : d2; if (s < 2) s = 2; else if (s > 6) s = 6; return s; } // Draw a "Single Arrow" in an arbitrary direction (0°, 90°, 180°, 270°). // This is the basic arrow drawing function for all "standard" widgets. // It is used in Fl_Scrollbars and similar and in all combinations, for // instance when "Double Arrows" or other combinations are needed. static int fl_draw_arrow_single(Fl_Rect r, Fl_Orientation o, Fl_Color col, int d = -1) { int x1, y1; // Revert gtk+ specific "chevron style" arrow drawing: see GitHub Issue #1117. // - gtk_chevron == true : use gtk+ specific ("chevron style") arrows // - gtk_chevron == false : use standard ("triangle") arrows // // Note 1: the "chevron style" was initially copied from Fl_Scrollbar and // then used in all "arrow" drawings, e.g. in Fl_Menu to unify arrow // appearance across all widgets and per scheme. This was probably // too much as mentioned in GitHub Issue #1117. The consequence is to // set 'gtk_chevron' to false to prevent the "chevron style". // // Note 2: In the future we may use more specific arrow types if needed and // integrate arrow drawing in Fl_Scheme_* classes. static const bool gtk_chevron = false; // ... or: Fl::is_scheme("gtk+"); x1 = r.x(); y1 = r.y(); if (d < 0) d = arrow_size(r, o); fl_color(col); switch(o) { case FL_ORIENT_LEFT: x1 += (r.w()-d)/2 - 1; y1 += r.h()/2; if (gtk_chevron) fl_polygon(x1, y1, x1+d, y1-d, x1+d-1, y1, x1+d, y1+d); else fl_polygon(x1, y1, x1+d, y1-d, x1+d, y1+d); return 1; case FL_ORIENT_RIGHT: x1 += (r.w()-d)/2; y1 += r.h()/2; if (gtk_chevron) fl_polygon(x1, y1-d, x1+1, y1, x1, y1+d, x1+d, y1); else fl_polygon(x1, y1-d, x1, y1+d, x1+d, y1); return 1; case FL_ORIENT_UP: x1 += r.w()/2; y1 += (r.h()-d)/2 - 1; if (gtk_chevron) fl_polygon(x1, y1, x1+d, y1+d, x1, y1+d-1, x1-d, y1+d); else fl_polygon(x1, y1, x1+d, y1+d, x1-d, y1+d); return 1; case FL_ORIENT_DOWN: x1 += r.w()/2-d; y1 += (r.h()-d)/2; if (gtk_chevron) { fl_polygon(x1, y1, x1+d, y1+1, x1+d, y1+d); fl_polygon(x1+d, y1+1, x1+2*d, y1, x1+d, y1+d); } else { fl_polygon(x1, y1, x1+d, y1+d, x1+2*d, y1); } return 1; default: // orientation not handled: return error return 0; } return 0; } // fl_draw_arrow_single() // Draw a "Double Arrow" in an arbitrary direction (0°, 90°, 180°, 270°). // This is the basic arrow drawing function for all "standard" widgets. // It is used in Fl_Scrollbars and similar and in all combinations, for // instance when "Double Arrows" or other combinations are needed. static int fl_draw_arrow_double(Fl_Rect r, Fl_Orientation o, Fl_Color col) { int d = arrow_size(r, o, 2); int x1 = r.x(); int y1 = r.y(); int da = (d+1)/2; switch(o) { case FL_ORIENT_LEFT: case FL_ORIENT_RIGHT: r.x(x1 - da); fl_draw_arrow_single(r, o, col, d); r.x(x1 + da); return fl_draw_arrow_single(r, o, col, d); case FL_ORIENT_UP: case FL_ORIENT_DOWN: r.y(y1 - da); fl_draw_arrow_single(r, o, col, d); r.y(y1 + da); return fl_draw_arrow_single(r, o, col, d); default: // orientation not handled: return error return 0; } return 0; } // fl_draw_arrow_double() // Draw a "Choice Arrow". The direction and type is determined by the scheme. static int fl_draw_arrow_choice(Fl_Rect r, Fl_Color col) { int w1 = (r.w() - 4) / 3; if (w1 < 1) w1 = 1; int x1 = r.x() + (r.w() - 2 * w1 - 1) / 2; int y1 = r.y() + (r.h() - w1 - 1) / 2; if (Fl::is_scheme("gtk+") || Fl::is_scheme("gleam")) { // Show smaller up/down arrows ... int x1 = r.x() + (r.w() - 6)/2; int y1 = r.y() + r.h() / 2; fl_color(col); fl_polygon(x1, y1 - 2, x1 + 3, y1 - 5, x1 + 6, y1 - 2); fl_polygon(x1, y1 + 2, x1 + 3, y1 + 5, x1 + 6, y1 + 2); return 1; } else if (Fl::is_scheme("plastic")) { // Show larger up/down arrows... fl_color(col); fl_polygon(x1, y1 + 3, x1 + w1, y1 + w1 + 3, x1 + 2 * w1, y1 + 3); fl_polygon(x1, y1 + 1, x1 + w1, y1 - w1 + 1, x1 + 2 * w1, y1 + 1); return 1; } else { // none, default // single down arrow return fl_draw_arrow_single(r, FL_ORIENT_DOWN, col); } return 0; } // fl_draw_arrow_double() /** Draw an "arrow like" GUI element for the selected scheme. In the future this function should be integrated in Fl_Scheme as a virtual method, i.e. it would call a method like ... \code Fl_Scheme::current()->draw_arrow(r, t, o, col); \endcode \param[in] r bounding box \param[in] t arrow type \param[in] o orientation \param[in] col arrow color \since 1.4.0 */ void fl_draw_arrow(Fl_Rect r, Fl_Arrow_Type t, Fl_Orientation o, Fl_Color col) { int ret = 0; Fl_Color saved_color = fl_color(); debug_arrow(r); // special case: arrows for the "oxy" scheme if (Fl::is_scheme("oxy")) { oxy_arrow(r, t, o, col); return; } // implementation of all arrow types for other schemes switch(t) { case FL_ARROW_SINGLE: ret = fl_draw_arrow_single(r, o, col); break; case FL_ARROW_DOUBLE: ret = fl_draw_arrow_double(r, o, col); break; case FL_ARROW_CHOICE: ret = fl_draw_arrow_choice(r, col); break; default: // unknown arrow type ret = 0; break; } // draw an error flag (red rectangle with cross) if not successful if (!ret) { fl_color(FL_RED); fl_rectf(r); fl_color(FL_BLACK); fl_rect(r); fl_line(r.x(), r.y(), r.r(), r.b()); fl_line(r.x(), r.b(), r.r(), r.y()); } fl_color(saved_color); } // fl_draw_arrow() fltk-1.4.3/src/Fl_Gl_Choice.H0000644000175000017500000000332515004135251015745 0ustar albrechtalbrecht// // OpenGL definitions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Internal interface to set up OpenGL. // // A "Fl_Gl_Choice" is created from an OpenGL mode and holds information // necessary to create a window (on X) and to create an OpenGL "context" // (on both X and Win32). // // create_gl_context takes a window (necessary only on Win32) and an // Fl_Gl_Choice and returns a new OpenGL context. All contexts share // display lists with each other. // // On X another create_gl_context is provided to create it for any // X visual. // // set_gl_context makes the given OpenGL context current and makes // it draw into the passed window. It tracks the current one context // to avoid calling the context switching code when the same context // is used, though it is a mystery to me why the GLX/WGL libraries // don't do this themselves... // // delete_gl_context destroys the context. // // This code is used by Fl_Gl_Window, gl_start(), and gl_visual() #ifndef Fl_Gl_Choice_H #define Fl_Gl_Choice_H // Describes the platform-independent part of data needed to create a GLContext. class Fl_Gl_Choice { friend class Fl_Gl_Window_Driver; int mode; const int *alist; Fl_Gl_Choice *next; public: Fl_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : mode(m), alist(alistp), next(n) {} }; #endif // Fl_Gl_Choice_H fltk-1.4.3/src/Fl_Color_Chooser.cxx0000644000175000017500000005051415004135251017306 0ustar albrechtalbrecht// // Color chooser for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include // Besides being a useful object on it's own, the Fl_Color_Chooser was // an attempt to make a complex composite object that could be easily // imbedded into a user interface. If you wish to make complex objects // of your own, be sure to read this code. // The function fl_color_chooser() creates a window containing a color // chooser and a few buttons and current-color indicators. It is an // easier interface for simple programs that just need a color. // The "hue box" can be a circle or rectilinear. // You get a circle by defining this: #define CIRCLE 1 // And the "hue box" can auto-update when the value changes // you get this by defining this: #define UPDATE_HUE_BOX 1 /** This \e static method converts HSV colors to RGB colorspace. \param[in] H, S, V color components \param[out] R, G, B color components */ void Fl_Color_Chooser::hsv2rgb( double H, double S, double V, double& R, double& G, double& B) { if (S < 5.0e-6) { R = G = B = V; } else { int i = (int)H; double f = H - (float)i; double p1 = V*(1.0-S); double p2 = V*(1.0-S*f); double p3 = V*(1.0-S*(1.0-f)); switch (i) { case 0: R = V; G = p3; B = p1; break; case 1: R = p2; G = V; B = p1; break; case 2: R = p1; G = V; B = p3; break; case 3: R = p1; G = p2; B = V; break; case 4: R = p3; G = p1; B = V; break; case 5: R = V; G = p1; B = p2; break; } } } /** This \e static method converts RGB colors to HSV colorspace. \param[in] R, G, B color components \param[out] H, S, V color components */ void Fl_Color_Chooser::rgb2hsv( double R, double G, double B, double& H, double& S, double& V) { double maxv = R > G ? R : G; if (B > maxv) maxv = B; V = maxv; if (maxv>0) { double minv = R < G ? R : G; if (B < minv) minv = B; S = 1.0 - double(minv)/maxv; if (maxv > minv) { if (maxv == R) {H = (G-B)/double(maxv-minv); if (H<0) H += 6.0;} else if (maxv == G) H = 2.0+(B-R)/double(maxv-minv); else H = 4.0+(R-G)/double(maxv-minv); } } } /** Fl_Color_Chooser modes */ enum { M_RGB, /**< mode() of Fl_Color_Chooser showing RGB values */ M_BYTE, /**< mode() of Fl_Color_Chooser showing byte values */ M_HEX, /**< mode() of Fl_Color_Chooser showing hex values */ M_HSV /**< mode() of Fl_Color_Chooser showing HSV values */ }; static const Fl_Menu_Item mode_menu[] = { {"rgb"}, {"byte"}, {"hex"}, {"hsv"}, {0} }; #ifndef FL_DOXYGEN int Flcc_Value_Input::format(char* buf) { Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); if (c->mode() == M_HEX) return snprintf(buf, 5,"0x%02X", int(value())); else return Fl_Valuator::format(buf); } #endif // !FL_DOXYGEN void Fl_Color_Chooser::set_valuators() { switch (mode()) { case M_RGB: rvalue.range(0,1); rvalue.step(1,1000); rvalue.value(r_); gvalue.range(0,1); gvalue.step(1,1000); gvalue.value(g_); bvalue.range(0,1); bvalue.step(1,1000); bvalue.value(b_); break; case M_BYTE: /* FALLTHROUGH */ case M_HEX: rvalue.range(0,255); rvalue.step(1); rvalue.value(int(255*r_+.5)); gvalue.range(0,255); gvalue.step(1); gvalue.value(int(255*g_+.5)); bvalue.range(0,255); bvalue.step(1); bvalue.value(int(255*b_+.5)); break; case M_HSV: rvalue.range(0,6); rvalue.step(1,1000); rvalue.value(hue_); gvalue.range(0,1); gvalue.step(1,1000); gvalue.value(saturation_); bvalue.range(0,1); bvalue.step(1,1000); bvalue.value(value_); break; } } /** Sets the current rgb color values. Does not do the callback. Does not clamp (but out of range values will produce psychedelic effects in the hue selector). \param[in] R, G, B color components. \return 1 if a new rgb value was set, 0 if the rgb value was the previous one. */ int Fl_Color_Chooser::rgb(double R, double G, double B) { if (R == r_ && G == g_ && B == b_) return 0; r_ = R; g_ = G; b_ = B; double ph = hue_; double ps = saturation_; double pv = value_; rgb2hsv(R,G,B,hue_,saturation_,value_); set_valuators(); set_changed(); if (value_ != pv) { #ifdef UPDATE_HUE_BOX huebox.damage(FL_DAMAGE_SCROLL); #endif valuebox.damage(FL_DAMAGE_EXPOSE);} if (hue_ != ph || saturation_ != ps) { huebox.damage(FL_DAMAGE_EXPOSE); valuebox.damage(FL_DAMAGE_SCROLL); } return 1; } /** Set the hsv values. The passed values are clamped (or for hue, modulus 6 is used) to get legal values. Does not do the callback. \param[in] H, S, V color components. \return 1 if a new hsv value was set, 0 if the hsv value was the previous one. */ int Fl_Color_Chooser::hsv(double H, double S, double V) { H = fmod(H,6.0); if (H < 0.0) H += 6.0; if (S < 0.0) S = 0.0; else if (S > 1.0) S = 1.0; if (V < 0.0) V = 0.0; else if (V > 1.0) V = 1.0; if (H == hue_ && S == saturation_ && V == value_) return 0; double ph = hue_; double ps = saturation_; double pv = value_; hue_ = H; saturation_ = S; value_ = V; if (value_ != pv) { #ifdef UPDATE_HUE_BOX huebox.damage(FL_DAMAGE_SCROLL); #endif valuebox.damage(FL_DAMAGE_EXPOSE);} if (hue_ != ph || saturation_ != ps) { huebox.damage(FL_DAMAGE_EXPOSE); valuebox.damage(FL_DAMAGE_SCROLL); } hsv2rgb(H,S,V,r_,g_,b_); set_valuators(); set_changed(); return 1; } //////////////////////////////////////////////////////////////// static void tohs(double x, double y, double& h, double& s) { #ifdef CIRCLE x = 2*x-1; y = 1-2*y; s = sqrt(x*x+y*y); if (s > 1.0) s = 1.0; h = (3.0/M_PI)*atan2(y,x); if (h<0) h += 6.0; #else h = fmod(6.0*x,6.0); if (h < 0.0) h += 6.0; s = 1.0-y; if (s < 0.0) s = 0.0; else if (s > 1.0) s = 1.0; #endif } #ifndef FL_DOXYGEN int Flcc_HueBox::handle(int e) { static double ih, is; Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); switch (e) { case FL_PUSH: if (Fl::visible_focus()) { Fl::focus(this); redraw(); } ih = c->hue(); is = c->saturation(); case FL_DRAG: { double Xf, Yf, H, S; Xf = (Fl::event_x()-x()-Fl::box_dx(box()))/double(w()-Fl::box_dw(box())); Yf = (Fl::event_y()-y()-Fl::box_dy(box()))/double(h()-Fl::box_dh(box())); tohs(Xf, Yf, H, S); if (fabs(H-ih) < 3*6.0/w()) H = ih; if (fabs(S-is) < 3*1.0/h()) S = is; if (Fl::event_state(FL_CTRL)) H = ih; if (c->hsv(H, S, c->value())) c->do_callback(FL_REASON_DRAGGED); } return 1; case FL_FOCUS : /* FALLTHROUGH */ case FL_UNFOCUS : if (Fl::visible_focus()) { redraw(); return 1; } else return 1; case FL_KEYBOARD : return handle_key(Fl::event_key()); default: return 0; } } #endif // !FL_DOXYGEN static void generate_image(void* vv, int X, int Y, int W, uchar* buf) { Flcc_HueBox* v = (Flcc_HueBox*)vv; int iw = v->w()-Fl::box_dw(v->box()); double Yf = double(Y)/(v->h()-Fl::box_dh(v->box())); #ifdef UPDATE_HUE_BOX const double V = ((Fl_Color_Chooser*)(v->parent()))->value(); #else const double V = 1.0; #endif for (int x = X; x < X+W; x++) { double Xf = double(x)/iw; double H,S; tohs(Xf,Yf,H,S); double r=0, g=0, b=0; Fl_Color_Chooser::hsv2rgb(H,S,V,r,g,b); *buf++ = uchar(255*r+.5); *buf++ = uchar(255*g+.5); *buf++ = uchar(255*b+.5); } } #ifndef FL_DOXYGEN int Flcc_HueBox::handle_key(int key) { int w1 = w()-Fl::box_dw(box())-6; int h1 = h()-Fl::box_dh(box())-6; Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); #ifdef CIRCLE int X = int(.5*(cos(c->hue()*(M_PI/3.0))*c->saturation()+1) * w1); int Y = int(.5*(1-sin(c->hue()*(M_PI/3.0))*c->saturation()) * h1); #else int X = int(c->hue()/6.0*w1); int Y = int((1-c->saturation())*h1); #endif switch (key) { case FL_Up : Y -= 3; break; case FL_Down : Y += 3; break; case FL_Left : X -= 3; break; case FL_Right : X += 3; break; default : return 0; } double Xf, Yf, H, S; Xf = (double)X/(double)w1; Yf = (double)Y/(double)h1; tohs(Xf, Yf, H, S); if (c->hsv(H, S, c->value())) c->do_callback(FL_REASON_CHANGED); return 1; } #endif // !FL_DOXYGEN #ifndef FL_DOXYGEN void Flcc_HueBox::draw() { if (damage()&FL_DAMAGE_ALL) draw_box(); int x1 = x()+Fl::box_dx(box()); int yy1 = y()+Fl::box_dy(box()); int w1 = w()-Fl::box_dw(box()); int h1 = h()-Fl::box_dh(box()); if (w1>0 && h1>0) { if (damage() == FL_DAMAGE_EXPOSE) fl_push_clip(x1+px,yy1+py,6,6); fl_draw_image(generate_image, this, x1, yy1, w1, h1); if (damage() == FL_DAMAGE_EXPOSE) fl_pop_clip(); } Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); #ifdef CIRCLE int X = int(.5*(cos(c->hue()*(M_PI/3.0))*c->saturation()+1) * (w1-6)); int Y = int(.5*(1-sin(c->hue()*(M_PI/3.0))*c->saturation()) * (h1-6)); #else int X = int(c->hue()/6.0*(w1-6)); int Y = int((1-c->saturation())*(h1-6)); #endif if (X < 0) X = 0; else if (X > w1-6) X = w1-6; if (Y < 0) Y = 0; else if (Y > h1-6) Y = h1-6; // fl_color(c->value()>.75 ? FL_BLACK : FL_WHITE); if (w1>0 && h1>0) { fl_push_clip(x1,yy1,w1,h1); draw_box(FL_UP_BOX,x1+X,yy1+Y,6,6,Fl::focus() == this ? FL_FOREGROUND_COLOR : FL_GRAY); fl_pop_clip(); } px = X; py = Y; } #endif // !FL_DOXYGEN //////////////////////////////////////////////////////////////// #ifndef FL_DOXYGEN int Flcc_ValueBox::handle(int e) { static double iv; Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); switch (e) { case FL_PUSH: if (Fl::visible_focus()) { Fl::focus(this); redraw(); } iv = c->value(); case FL_DRAG: { double Yf; Yf = 1-(Fl::event_y()-y()-Fl::box_dy(box()))/double(h()-Fl::box_dh(box())); if (fabs(Yf-iv)<(3*1.0/h())) Yf = iv; if (c->hsv(c->hue(),c->saturation(),Yf)) c->do_callback(FL_REASON_DRAGGED); } return 1; case FL_FOCUS : /* FALLTHROUGH */ case FL_UNFOCUS : if (Fl::visible_focus()) { redraw(); return 1; } else return 1; case FL_KEYBOARD : return handle_key(Fl::event_key()); default: return 0; } } #endif // !FL_DOXYGEN static double tr, tg, tb; static void generate_vimage(void* vv, int X, int Y, int W, uchar* buf) { Flcc_ValueBox* v = (Flcc_ValueBox*)vv; double Yf = 255*(1.0-double(Y)/(v->h()-Fl::box_dh(v->box()))); uchar r = uchar(tr*Yf+.5); uchar g = uchar(tg*Yf+.5); uchar b = uchar(tb*Yf+.5); for (int x = X; x < X+W; x++) { *buf++ = r; *buf++ = g; *buf++ = b; } } #ifndef FL_DOXYGEN void Flcc_ValueBox::draw() { if (damage()&FL_DAMAGE_ALL) draw_box(); Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); c->hsv2rgb(c->hue(),c->saturation(),1.0,tr,tg,tb); int x1 = x()+Fl::box_dx(box()); int yy1 = y()+Fl::box_dy(box()); int w1 = w()-Fl::box_dw(box()); int h1 = h()-Fl::box_dh(box()); if (w1>0 && h1>0) { if (damage() == FL_DAMAGE_EXPOSE) fl_push_clip(x1,yy1+py,w1,6); fl_draw_image(generate_vimage, this, x1, yy1, w1, h1); if (damage() == FL_DAMAGE_EXPOSE) fl_pop_clip(); } int Y = int((1-c->value()) * (h1-6)); if (Y < 0) Y = 0; else if (Y > h1-6) Y = h1-6; draw_box(FL_UP_BOX,x1,yy1+Y,w1,6,Fl::focus() == this ? FL_FOREGROUND_COLOR : FL_GRAY); py = Y; } #endif // !FL_DOXYGEN #ifndef FL_DOXYGEN int Flcc_ValueBox::handle_key(int key) { int h1 = h()-Fl::box_dh(box())-6; Fl_Color_Chooser* c = (Fl_Color_Chooser*)parent(); int Y = int((1-c->value()) * h1); if (Y < 0) Y = 0; else if (Y > h1) Y = h1; switch (key) { case FL_Up : Y -= 3; break; case FL_Down : Y += 3; break; default : return 0; } double Yf; Yf = 1-((double)Y/(double)h1); if (c->hsv(c->hue(),c->saturation(),Yf)) c->do_callback(FL_REASON_CHANGED); return 1; } #endif // !FL_DOXYGEN //////////////////////////////////////////////////////////////// void Fl_Color_Chooser::rgb_cb(Fl_Widget* o, void*) { Fl_Color_Chooser* c = (Fl_Color_Chooser*)(o->parent()); // clamp input values to valid ranges (issue #749, part 1) double R = c->rvalue.clamp(c->rvalue.value()); double G = c->gvalue.clamp(c->gvalue.value()); double B = c->bvalue.clamp(c->bvalue.value()); // update input values if they were clamped (#749, part 2) c->rvalue.value(R); c->gvalue.value(G); c->bvalue.value(B); if (c->mode() == M_HSV) { if (c->hsv(R,G,B)) c->do_callback(FL_REASON_CHANGED); return; } if (c->mode() != M_RGB) { R = R/255; G = G/255; B = B/255; } if (c->rgb(R,G,B)) c->do_callback(FL_REASON_CHANGED); } void Fl_Color_Chooser::mode_cb(Fl_Widget* o, void*) { Fl_Color_Chooser* c = (Fl_Color_Chooser*)(o->parent()); // force them to redraw even if value is the same: c->rvalue.value(-1); c->gvalue.value(-1); c->bvalue.value(-1); c->set_valuators(); } void Fl_Color_Chooser::mode(int newMode) { choice.value(newMode); choice.do_callback(FL_REASON_RESELECTED); } // Small local helper function: // Copy hex color value ('RRGGBB') of Fl_Color_Chooser to clipboard. // Always returns 1 (event was used). static int copy_rgb(double r, double g, double b) { char buf[8]; int len; len = snprintf(buf, 8, "%02X%02X%02X", int(r * 255 + .5), int(g * 255 + .5), int(b * 255 + .5)); Fl::copy(buf, len, 1); // printf("copied '%s' to clipboard\n", buf); // Debug return 1; } /** Handles all events received by this widget. This specific handle() method processes the standard 'copy' function as seen in other input widgets. It copies the current color value to the clipboard as a string in RGB format ('RRGGBB'). This format is independent of the Fl_Color_Chooser display format setting. No other formats are supplied. The keyboard events handled are: - ctrl-c - ctrl-x - ctrl-Insert All other events are processed by the parent class \c Fl_Group. This enables the \b user to choose a color value, press \p ctrl-c to copy the value to the clipboard and paste it into a color selection widget in another application window or any other text input (e.g. a preferences dialog or an editor). \note Keyboard event handling by the current focus widget has priority, hence moving the focus to one of the buttons or selecting text in one of the input widgets effectively disables this special method. \param[in] e current event \returns 1 if event has been handled, 0 otherwise \see Fl_Group::handle(int) */ int Fl_Color_Chooser::handle(int e) { int mods = Fl::event_state() & (FL_META | FL_CTRL | FL_ALT); unsigned int shift = Fl::event_state() & FL_SHIFT; switch (e) { case FL_KEYBOARD: case FL_SHORTCUT: // ignore CTRL-SHIFT-C, CTRL-SHIFT-X and CTRL-SHIFT-Insert if (shift) return Fl_Group::handle(e); switch (Fl::event_key()) { case FL_Insert: if (mods == FL_CTRL) return copy_rgb(r_, g_, b_); break; case 'c': case 'x': if (mods == FL_COMMAND) return copy_rgb(r_, g_, b_); break; default: break; } default: break; } return Fl_Group::handle(e); } //////////////////////////////////////////////////////////////// /** Creates a new Fl_Color_Chooser widget using the given position, size, and label string. The recommended dimensions are 200x95. The color is initialized to black. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Color_Chooser::Fl_Color_Chooser(int X, int Y, int W, int H, const char* L) : Fl_Group(0,0,195,115,L), huebox(0,0,115,115), valuebox(115,0,20,115), choice(140,0,55,25), rvalue(140,30,55,25), gvalue(140,60,55,25), bvalue(140,90,55,25), resize_box(0,0,115,115) { end(); resizable(resize_box); resize(X,Y,W,H); r_ = g_ = b_ = 0; hue_ = 0.0; saturation_ = 0.0; value_ = 0.0; huebox.box(FL_DOWN_FRAME); valuebox.box(FL_DOWN_FRAME); choice.menu(mode_menu); set_valuators(); rvalue.callback(rgb_cb); gvalue.callback(rgb_cb); bvalue.callback(rgb_cb); choice.callback(mode_cb); choice.box(FL_THIN_UP_BOX); choice.textfont(FL_HELVETICA_BOLD_ITALIC); } //////////////////////////////////////////////////////////////// // fl_color_chooser(): #include #include #include class ColorChip : public Fl_Widget { void draw() FL_OVERRIDE; public: uchar r,g,b; ColorChip(int X, int Y, int W, int H) : Fl_Widget(X,Y,W,H) { box(FL_ENGRAVED_FRAME);} }; void ColorChip::draw() { if (damage()&FL_DAMAGE_ALL) draw_box(); fl_rectf(x()+Fl::box_dx(box()), y()+Fl::box_dy(box()), w()-Fl::box_dw(box()), h()-Fl::box_dh(box()),r,g,b); } static void chooser_cb(Fl_Widget* o, void* vv) { Fl_Color_Chooser* c = (Fl_Color_Chooser*)o; ColorChip* v = (ColorChip*)vv; v->r = uchar(255*c->r()+.5); v->g = uchar(255*c->g()+.5); v->b = uchar(255*c->b()+.5); v->damage(FL_DAMAGE_EXPOSE); } extern const char* fl_ok; extern const char* fl_cancel; // fl_color_chooser's callback for ok_button (below) // [in] o is a pointer to okay_button (below) // [in] p is a pointer to an int to receive the return value (1) // closes the fl_color_chooser window static void cc_ok_cb (Fl_Widget *o, void *p) { *((int *)p) = 1; // set return value o->window()->hide(); } // fl_color_chooser's callback for cancel_button and window close // [in] o is a pointer to cancel_button (below) _or_ the dialog window // [in] p is a pointer to an int to receive the return value (0) // closes the fl_color_chooser window static void cc_cancel_cb (Fl_Widget *o, void *p) { *((int *)p) = 0; // set return value if (o->window()) // cancel button o->window()->hide(); else // window close o->hide(); } /** \addtogroup group_comdlg @{ */ /** \brief Pops up a window to let the user pick an arbitrary RGB color. \note \#include \image html fl_color_chooser.jpg \image latex fl_color_chooser.jpg "fl_color_chooser" width=8cm \param[in] name Title label for the window \param[in,out] r, g, b Color components in the range 0.0 to 1.0. \param[in] cmode Optional mode for color chooser. See mode(int). Default -1 if none (rgb mode). \retval 1 if user confirms the selection \retval 0 if user cancels the dialog \relates Fl_Color_Chooser */ int fl_color_chooser(const char* name, double& r, double& g, double& b, int cmode) { int ret = 0; Fl_Window window(215,200,name); window.callback(cc_cancel_cb,&ret); Fl_Color_Chooser chooser(10, 10, 195, 115); ColorChip ok_color(10, 130, 95, 25); Fl_Return_Button ok_button(10, 165, 95, 25, fl_ok); ok_button.callback(cc_ok_cb,&ret); ColorChip cancel_color(110, 130, 95, 25); cancel_color.r = uchar(255*r+.5); ok_color.r = cancel_color.r; ok_color.g = cancel_color.g = uchar(255*g+.5); ok_color.b = cancel_color.b = uchar(255*b+.5); Fl_Button cancel_button(110, 165, 95, 25, fl_cancel); cancel_button.callback(cc_cancel_cb,&ret); window.resizable(chooser); chooser.rgb(r,g,b); chooser.callback(chooser_cb, &ok_color); if (cmode!=-1) chooser.mode(cmode); window.end(); window.set_modal(); window.hotspot(window); window.show(); while (window.shown()) Fl::wait(); if (ret) { // ok_button or Enter r = chooser.r(); g = chooser.g(); b = chooser.b(); } return ret; } /** \brief Pops up a window to let the user pick an arbitrary RGB color. \note \#include \image html fl_color_chooser.jpg \image latex fl_color_chooser.jpg "fl_color_chooser" width=8cm \param[in] name Title label for the window \param[in,out] r, g, b Color components in the range 0 to 255. \param[in] cmode Optional mode for color chooser. See mode(int). Default -1 if none (rgb mode). \retval 1 if user confirms the selection \retval 0 if user cancels the dialog \relates Fl_Color_Chooser */ int fl_color_chooser(const char* name, uchar& r, uchar& g, uchar& b, int cmode) { double dr = r/255.0; double dg = g/255.0; double db = b/255.0; if (fl_color_chooser(name,dr,dg,db,cmode)) { r = uchar(255*dr+.5); g = uchar(255*dg+.5); b = uchar(255*db+.5); return 1; } return 0; } /** @} */ fltk-1.4.3/src/freeglut_stroke_roman.cxx0000644000175000017500000014015015004135251020521 0ustar albrechtalbrecht/* * freeglut_stroke_roman.c * * freeglut Roman stroke font definition * * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. * Written by Pawel W. Olszta, * Creation date: Thu Dec 16 1999 * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* This file has been automatically generated by the genstroke utility. */ #include /* char: 0x20 */ static const Fl_Glut_StrokeStrip ch32st[] = { { 0, 0 } }; static const Fl_Glut_StrokeChar ch32 = {104.762f,0,ch32st}; /* char: 0x21 */ static const Fl_Glut_StrokeVertex ch33st0[] = { {13.3819f,100.0f}, {13.3819f,33.3333f} }; static const Fl_Glut_StrokeVertex ch33st1[] = { {13.3819f,9.5238f}, {8.62f,4.7619f}, {13.3819f,0.0f}, {18.1438f,4.7619f}, {13.3819f,9.5238f} }; static const Fl_Glut_StrokeStrip ch33st[] = { {2,ch33st0}, {5,ch33st1} }; static const Fl_Glut_StrokeChar ch33 = {26.6238f,2,ch33st}; /* char: 0x22 */ static const Fl_Glut_StrokeVertex ch34st0[] = { {4.02f,100.0f}, {4.02f,66.6667f} }; static const Fl_Glut_StrokeVertex ch34st1[] = { {42.1152f,100.0f}, {42.1152f,66.6667f} }; static const Fl_Glut_StrokeStrip ch34st[] = { {2,ch34st0}, {2,ch34st1} }; static const Fl_Glut_StrokeChar ch34 = {51.4352f,2,ch34st}; /* char: 0x23 */ static const Fl_Glut_StrokeVertex ch35st0[] = { {41.2952f,119.048f}, {7.9619f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch35st1[] = { {69.8667f,119.048f}, {36.5333f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch35st2[] = { {7.9619f,57.1429f}, {74.6286f,57.1429f} }; static const Fl_Glut_StrokeVertex ch35st3[] = { {3.2f,28.5714f}, {69.8667f,28.5714f} }; static const Fl_Glut_StrokeStrip ch35st[] = { {2,ch35st0}, {2,ch35st1}, {2,ch35st2}, {2,ch35st3} }; static const Fl_Glut_StrokeChar ch35 = {79.4886f,4,ch35st}; /* char: 0x24 */ static const Fl_Glut_StrokeVertex ch36st0[] = { {28.6295f,119.048f}, {28.6295f,-19.0476f} }; static const Fl_Glut_StrokeVertex ch36st1[] = { {47.6771f,119.048f}, {47.6771f,-19.0476f} }; static const Fl_Glut_StrokeVertex ch36st2[] = { {71.4867f,85.7143f}, {61.9629f,95.2381f}, {47.6771f,100.0f}, {28.6295f,100.0f}, {14.3438f,95.2381f}, {4.82f,85.7143f}, {4.82f,76.1905f}, {9.5819f,66.6667f}, {14.3438f,61.9048f}, {23.8676f,57.1429f}, {52.439f,47.619f}, {61.9629f,42.8571f}, {66.7248f,38.0952f}, {71.4867f,28.5714f}, {71.4867f,14.2857f}, {61.9629f,4.7619f}, {47.6771f,0.0f}, {28.6295f,0.0f}, {14.3438f,4.7619f}, {4.82f,14.2857f} }; static const Fl_Glut_StrokeStrip ch36st[] = { {2,ch36st0}, {2,ch36st1}, {20,ch36st2} }; static const Fl_Glut_StrokeChar ch36 = {76.2067f,3,ch36st}; /* char: 0x25 */ static const Fl_Glut_StrokeVertex ch37st0[] = { {92.0743f,100.0f}, {6.36f,0.0f} }; static const Fl_Glut_StrokeVertex ch37st1[] = { {30.1695f,100.0f}, {39.6933f,90.4762f}, {39.6933f,80.9524f}, {34.9314f,71.4286f}, {25.4076f,66.6667f}, {15.8838f,66.6667f}, {6.36f,76.1905f}, {6.36f,85.7143f}, {11.1219f,95.2381f}, {20.6457f,100.0f}, {30.1695f,100.0f}, {39.6933f,95.2381f}, {53.979f,90.4762f}, {68.2648f,90.4762f}, {82.5505f,95.2381f}, {92.0743f,100.0f} }; static const Fl_Glut_StrokeVertex ch37st2[] = { {73.0267f,33.3333f}, {63.5029f,28.5714f}, {58.741f,19.0476f}, {58.741f,9.5238f}, {68.2648f,0.0f}, {77.7886f,0.0f}, {87.3124f,4.7619f}, {92.0743f,14.2857f}, {92.0743f,23.8095f}, {82.5505f,33.3333f}, {73.0267f,33.3333f} }; static const Fl_Glut_StrokeStrip ch37st[] = { {2,ch37st0}, {16,ch37st1}, {11,ch37st2} }; static const Fl_Glut_StrokeChar ch37 = {96.5743f,3,ch37st}; /* char: 0x26 */ static const Fl_Glut_StrokeVertex ch38st0[] = { {101.218f,57.1429f}, {101.218f,61.9048f}, {96.4562f,66.6667f}, {91.6943f,66.6667f}, {86.9324f,61.9048f}, {82.1705f,52.381f}, {72.6467f,28.5714f}, {63.1229f,14.2857f}, {53.599f,4.7619f}, {44.0752f,0.0f}, {25.0276f,0.0f}, {15.5038f,4.7619f}, {10.7419f,9.5238f}, {5.98f,19.0476f}, {5.98f,28.5714f}, {10.7419f,38.0952f}, {15.5038f,42.8571f}, {48.8371f,61.9048f}, {53.599f,66.6667f}, {58.361f,76.1905f}, {58.361f,85.7143f}, {53.599f,95.2381f}, {44.0752f,100.0f}, {34.5514f,95.2381f}, {29.7895f,85.7143f}, {29.7895f,76.1905f}, {34.5514f,61.9048f}, {44.0752f,47.619f}, {67.8848f,14.2857f}, {77.4086f,4.7619f}, {86.9324f,0.0f}, {96.4562f,0.0f}, {101.218f,4.7619f}, {101.218f,9.5238f} }; static const Fl_Glut_StrokeStrip ch38st[] = { {34,ch38st0} }; static const Fl_Glut_StrokeChar ch38 = {101.758f,1,ch38st}; /* char: 0x27 */ static const Fl_Glut_StrokeVertex ch39st0[] = { {4.44f,100.0f}, {4.44f,66.6667f} }; static const Fl_Glut_StrokeStrip ch39st[] = { {2,ch39st0} }; static const Fl_Glut_StrokeChar ch39 = {13.62f,1,ch39st}; /* char: 0x28 */ static const Fl_Glut_StrokeVertex ch40st0[] = { {40.9133f,119.048f}, {31.3895f,109.524f}, {21.8657f,95.2381f}, {12.3419f,76.1905f}, {7.58f,52.381f}, {7.58f,33.3333f}, {12.3419f,9.5238f}, {21.8657f,-9.5238f}, {31.3895f,-23.8095f}, {40.9133f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch40st[] = { {10,ch40st0} }; static const Fl_Glut_StrokeChar ch40 = {47.1733f,1,ch40st}; /* char: 0x29 */ static const Fl_Glut_StrokeVertex ch41st0[] = { {5.28f,119.048f}, {14.8038f,109.524f}, {24.3276f,95.2381f}, {33.8514f,76.1905f}, {38.6133f,52.381f}, {38.6133f,33.3333f}, {33.8514f,9.5238f}, {24.3276f,-9.5238f}, {14.8038f,-23.8095f}, {5.28f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch41st[] = { {10,ch41st0} }; static const Fl_Glut_StrokeChar ch41 = {47.5333f,1,ch41st}; /* char: 0x2a */ static const Fl_Glut_StrokeVertex ch42st0[] = { {30.7695f,71.4286f}, {30.7695f,14.2857f} }; static const Fl_Glut_StrokeVertex ch42st1[] = { {6.96f,57.1429f}, {54.579f,28.5714f} }; static const Fl_Glut_StrokeVertex ch42st2[] = { {54.579f,57.1429f}, {6.96f,28.5714f} }; static const Fl_Glut_StrokeStrip ch42st[] = { {2,ch42st0}, {2,ch42st1}, {2,ch42st2} }; static const Fl_Glut_StrokeChar ch42 = {59.439f,3,ch42st}; /* char: 0x2b */ static const Fl_Glut_StrokeVertex ch43st0[] = { {48.8371f,85.7143f}, {48.8371f,0.0f} }; static const Fl_Glut_StrokeVertex ch43st1[] = { {5.98f,42.8571f}, {91.6943f,42.8571f} }; static const Fl_Glut_StrokeStrip ch43st[] = { {2,ch43st0}, {2,ch43st1} }; static const Fl_Glut_StrokeChar ch43 = {97.2543f,2,ch43st}; /* char: 0x2c */ static const Fl_Glut_StrokeVertex ch44st0[] = { {18.2838f,4.7619f}, {13.5219f,0.0f}, {8.76f,4.7619f}, {13.5219f,9.5238f}, {18.2838f,4.7619f}, {18.2838f,-4.7619f}, {13.5219f,-14.2857f}, {8.76f,-19.0476f} }; static const Fl_Glut_StrokeStrip ch44st[] = { {8,ch44st0} }; static const Fl_Glut_StrokeChar ch44 = {26.0638f,1,ch44st}; /* char: 0x2d */ static const Fl_Glut_StrokeVertex ch45st0[] = { {7.38f,42.8571f}, {93.0943f,42.8571f} }; static const Fl_Glut_StrokeStrip ch45st[] = { {2,ch45st0} }; static const Fl_Glut_StrokeChar ch45 = {100.754f,1,ch45st}; /* char: 0x2e */ static const Fl_Glut_StrokeVertex ch46st0[] = { {13.1019f,9.5238f}, {8.34f,4.7619f}, {13.1019f,0.0f}, {17.8638f,4.7619f}, {13.1019f,9.5238f} }; static const Fl_Glut_StrokeStrip ch46st[] = { {5,ch46st0} }; static const Fl_Glut_StrokeChar ch46 = {26.4838f,1,ch46st}; /* char: 0x2f */ static const Fl_Glut_StrokeVertex ch47st0[] = { {7.24f,-14.2857f}, {73.9067f,100.0f} }; static const Fl_Glut_StrokeStrip ch47st[] = { {2,ch47st0} }; static const Fl_Glut_StrokeChar ch47 = {82.1067f,1,ch47st}; /* char: 0x30 */ static const Fl_Glut_StrokeVertex ch48st0[] = { {33.5514f,100.0f}, {19.2657f,95.2381f}, {9.7419f,80.9524f}, {4.98f,57.1429f}, {4.98f,42.8571f}, {9.7419f,19.0476f}, {19.2657f,4.7619f}, {33.5514f,0.0f}, {43.0752f,0.0f}, {57.361f,4.7619f}, {66.8848f,19.0476f}, {71.6467f,42.8571f}, {71.6467f,57.1429f}, {66.8848f,80.9524f}, {57.361f,95.2381f}, {43.0752f,100.0f}, {33.5514f,100.0f} }; static const Fl_Glut_StrokeStrip ch48st[] = { {17,ch48st0} }; static const Fl_Glut_StrokeChar ch48 = {77.0667f,1,ch48st}; /* char: 0x31 */ static const Fl_Glut_StrokeVertex ch49st0[] = { {11.82f,80.9524f}, {21.3438f,85.7143f}, {35.6295f,100.0f}, {35.6295f,0.0f} }; static const Fl_Glut_StrokeStrip ch49st[] = { {4,ch49st0} }; static const Fl_Glut_StrokeChar ch49 = {66.5295f,1,ch49st}; /* char: 0x32 */ static const Fl_Glut_StrokeVertex ch50st0[] = { {10.1819f,76.1905f}, {10.1819f,80.9524f}, {14.9438f,90.4762f}, {19.7057f,95.2381f}, {29.2295f,100.0f}, {48.2771f,100.0f}, {57.801f,95.2381f}, {62.5629f,90.4762f}, {67.3248f,80.9524f}, {67.3248f,71.4286f}, {62.5629f,61.9048f}, {53.039f,47.619f}, {5.42f,0.0f}, {72.0867f,0.0f} }; static const Fl_Glut_StrokeStrip ch50st[] = { {14,ch50st0} }; static const Fl_Glut_StrokeChar ch50 = {77.6467f,1,ch50st}; /* char: 0x33 */ static const Fl_Glut_StrokeVertex ch51st0[] = { {14.5238f,100.0f}, {66.9048f,100.0f}, {38.3333f,61.9048f}, {52.619f,61.9048f}, {62.1429f,57.1429f}, {66.9048f,52.381f}, {71.6667f,38.0952f}, {71.6667f,28.5714f}, {66.9048f,14.2857f}, {57.381f,4.7619f}, {43.0952f,0.0f}, {28.8095f,0.0f}, {14.5238f,4.7619f}, {9.7619f,9.5238f}, {5.0f,19.0476f} }; static const Fl_Glut_StrokeStrip ch51st[] = { {15,ch51st0} }; static const Fl_Glut_StrokeChar ch51 = {77.0467f,1,ch51st}; /* char: 0x34 */ static const Fl_Glut_StrokeVertex ch52st0[] = { {51.499f,100.0f}, {3.88f,33.3333f}, {75.3086f,33.3333f} }; static const Fl_Glut_StrokeVertex ch52st1[] = { {51.499f,100.0f}, {51.499f,0.0f} }; static const Fl_Glut_StrokeStrip ch52st[] = { {3,ch52st0}, {2,ch52st1} }; static const Fl_Glut_StrokeChar ch52 = {80.1686f,2,ch52st}; /* char: 0x35 */ static const Fl_Glut_StrokeVertex ch53st0[] = { {62.0029f,100.0f}, {14.3838f,100.0f}, {9.6219f,57.1429f}, {14.3838f,61.9048f}, {28.6695f,66.6667f}, {42.9552f,66.6667f}, {57.241f,61.9048f}, {66.7648f,52.381f}, {71.5267f,38.0952f}, {71.5267f,28.5714f}, {66.7648f,14.2857f}, {57.241f,4.7619f}, {42.9552f,0.0f}, {28.6695f,0.0f}, {14.3838f,4.7619f}, {9.6219f,9.5238f}, {4.86f,19.0476f} }; static const Fl_Glut_StrokeStrip ch53st[] = { {17,ch53st0} }; static const Fl_Glut_StrokeChar ch53 = {77.6867f,1,ch53st}; /* char: 0x36 */ static const Fl_Glut_StrokeVertex ch54st0[] = { {62.7229f,85.7143f}, {57.961f,95.2381f}, {43.6752f,100.0f}, {34.1514f,100.0f}, {19.8657f,95.2381f}, {10.3419f,80.9524f}, {5.58f,57.1429f}, {5.58f,33.3333f}, {10.3419f,14.2857f}, {19.8657f,4.7619f}, {34.1514f,0.0f}, {38.9133f,0.0f}, {53.199f,4.7619f}, {62.7229f,14.2857f}, {67.4848f,28.5714f}, {67.4848f,33.3333f}, {62.7229f,47.619f}, {53.199f,57.1429f}, {38.9133f,61.9048f}, {34.1514f,61.9048f}, {19.8657f,57.1429f}, {10.3419f,47.619f}, {5.58f,33.3333f} }; static const Fl_Glut_StrokeStrip ch54st[] = { {23,ch54st0} }; static const Fl_Glut_StrokeChar ch54 = {73.8048f,1,ch54st}; /* char: 0x37 */ static const Fl_Glut_StrokeVertex ch55st0[] = { {72.2267f,100.0f}, {24.6076f,0.0f} }; static const Fl_Glut_StrokeVertex ch55st1[] = { {5.56f,100.0f}, {72.2267f,100.0f} }; static const Fl_Glut_StrokeStrip ch55st[] = { {2,ch55st0}, {2,ch55st1} }; static const Fl_Glut_StrokeChar ch55 = {77.2267f,2,ch55st}; /* char: 0x38 */ static const Fl_Glut_StrokeVertex ch56st0[] = { {29.4095f,100.0f}, {15.1238f,95.2381f}, {10.3619f,85.7143f}, {10.3619f,76.1905f}, {15.1238f,66.6667f}, {24.6476f,61.9048f}, {43.6952f,57.1429f}, {57.981f,52.381f}, {67.5048f,42.8571f}, {72.2667f,33.3333f}, {72.2667f,19.0476f}, {67.5048f,9.5238f}, {62.7429f,4.7619f}, {48.4571f,0.0f}, {29.4095f,0.0f}, {15.1238f,4.7619f}, {10.3619f,9.5238f}, {5.6f,19.0476f}, {5.6f,33.3333f}, {10.3619f,42.8571f}, {19.8857f,52.381f}, {34.1714f,57.1429f}, {53.219f,61.9048f}, {62.7429f,66.6667f}, {67.5048f,76.1905f}, {67.5048f,85.7143f}, {62.7429f,95.2381f}, {48.4571f,100.0f}, {29.4095f,100.0f} }; static const Fl_Glut_StrokeStrip ch56st[] = { {29,ch56st0} }; static const Fl_Glut_StrokeChar ch56 = {77.6667f,1,ch56st}; /* char: 0x39 */ static const Fl_Glut_StrokeVertex ch57st0[] = { {68.5048f,66.6667f}, {63.7429f,52.381f}, {54.219f,42.8571f}, {39.9333f,38.0952f}, {35.1714f,38.0952f}, {20.8857f,42.8571f}, {11.3619f,52.381f}, {6.6f,66.6667f}, {6.6f,71.4286f}, {11.3619f,85.7143f}, {20.8857f,95.2381f}, {35.1714f,100.0f}, {39.9333f,100.0f}, {54.219f,95.2381f}, {63.7429f,85.7143f}, {68.5048f,66.6667f}, {68.5048f,42.8571f}, {63.7429f,19.0476f}, {54.219f,4.7619f}, {39.9333f,0.0f}, {30.4095f,0.0f}, {16.1238f,4.7619f}, {11.3619f,14.2857f} }; static const Fl_Glut_StrokeStrip ch57st[] = { {23,ch57st0} }; static const Fl_Glut_StrokeChar ch57 = {74.0648f,1,ch57st}; /* char: 0x3a */ static const Fl_Glut_StrokeVertex ch58st0[] = { {14.0819f,66.6667f}, {9.32f,61.9048f}, {14.0819f,57.1429f}, {18.8438f,61.9048f}, {14.0819f,66.6667f} }; static const Fl_Glut_StrokeVertex ch58st1[] = { {14.0819f,9.5238f}, {9.32f,4.7619f}, {14.0819f,0.0f}, {18.8438f,4.7619f}, {14.0819f,9.5238f} }; static const Fl_Glut_StrokeStrip ch58st[] = { {5,ch58st0}, {5,ch58st1} }; static const Fl_Glut_StrokeChar ch58 = {26.2238f,2,ch58st}; /* char: 0x3b */ static const Fl_Glut_StrokeVertex ch59st0[] = { {12.9619f,66.6667f}, {8.2f,61.9048f}, {12.9619f,57.1429f}, {17.7238f,61.9048f}, {12.9619f,66.6667f} }; static const Fl_Glut_StrokeVertex ch59st1[] = { {17.7238f,4.7619f}, {12.9619f,0.0f}, {8.2f,4.7619f}, {12.9619f,9.5238f}, {17.7238f,4.7619f}, {17.7238f,-4.7619f}, {12.9619f,-14.2857f}, {8.2f,-19.0476f} }; static const Fl_Glut_StrokeStrip ch59st[] = { {5,ch59st0}, {8,ch59st1} }; static const Fl_Glut_StrokeChar ch59 = {26.3038f,2,ch59st}; /* char: 0x3c */ static const Fl_Glut_StrokeVertex ch60st0[] = { {79.2505f,85.7143f}, {3.06f,42.8571f}, {79.2505f,0.0f} }; static const Fl_Glut_StrokeStrip ch60st[] = { {3,ch60st0} }; static const Fl_Glut_StrokeChar ch60 = {81.6105f,1,ch60st}; /* char: 0x3d */ static const Fl_Glut_StrokeVertex ch61st0[] = { {5.7f,57.1429f}, {91.4143f,57.1429f} }; static const Fl_Glut_StrokeVertex ch61st1[] = { {5.7f,28.5714f}, {91.4143f,28.5714f} }; static const Fl_Glut_StrokeStrip ch61st[] = { {2,ch61st0}, {2,ch61st1} }; static const Fl_Glut_StrokeChar ch61 = {97.2543f,2,ch61st}; /* char: 0x3e */ static const Fl_Glut_StrokeVertex ch62st0[] = { {2.78f,85.7143f}, {78.9705f,42.8571f}, {2.78f,0.0f} }; static const Fl_Glut_StrokeStrip ch62st[] = { {3,ch62st0} }; static const Fl_Glut_StrokeChar ch62 = {81.6105f,1,ch62st}; /* char: 0x3f */ static const Fl_Glut_StrokeVertex ch63st0[] = { {8.42f,76.1905f}, {8.42f,80.9524f}, {13.1819f,90.4762f}, {17.9438f,95.2381f}, {27.4676f,100.0f}, {46.5152f,100.0f}, {56.039f,95.2381f}, {60.801f,90.4762f}, {65.5629f,80.9524f}, {65.5629f,71.4286f}, {60.801f,61.9048f}, {56.039f,57.1429f}, {36.9914f,47.619f}, {36.9914f,33.3333f} }; static const Fl_Glut_StrokeVertex ch63st1[] = { {36.9914f,9.5238f}, {32.2295f,4.7619f}, {36.9914f,0.0f}, {41.7533f,4.7619f}, {36.9914f,9.5238f} }; static const Fl_Glut_StrokeStrip ch63st[] = { {14,ch63st0}, {5,ch63st1} }; static const Fl_Glut_StrokeChar ch63 = {73.9029f,2,ch63st}; /* char: 0x40 */ static const Fl_Glut_StrokeVertex ch64st0[] = { {49.2171f,52.381f}, {39.6933f,57.1429f}, {30.1695f,57.1429f}, {25.4076f,47.619f}, {25.4076f,42.8571f}, {30.1695f,33.3333f}, {39.6933f,33.3333f}, {49.2171f,38.0952f} }; static const Fl_Glut_StrokeVertex ch64st1[] = { {49.2171f,57.1429f}, {49.2171f,38.0952f}, {53.979f,33.3333f}, {63.5029f,33.3333f}, {68.2648f,42.8571f}, {68.2648f,47.619f}, {63.5029f,61.9048f}, {53.979f,71.4286f}, {39.6933f,76.1905f}, {34.9314f,76.1905f}, {20.6457f,71.4286f}, {11.1219f,61.9048f}, {6.36f,47.619f}, {6.36f,42.8571f}, {11.1219f,28.5714f}, {20.6457f,19.0476f}, {34.9314f,14.2857f}, {39.6933f,14.2857f}, {53.979f,19.0476f} }; static const Fl_Glut_StrokeStrip ch64st[] = { {8,ch64st0}, {19,ch64st1} }; static const Fl_Glut_StrokeChar ch64 = {74.3648f,2,ch64st}; /* char: 0x41 */ static const Fl_Glut_StrokeVertex ch65st0[] = { {40.5952f,100.0f}, {2.5f,0.0f} }; static const Fl_Glut_StrokeVertex ch65st1[] = { {40.5952f,100.0f}, {78.6905f,0.0f} }; static const Fl_Glut_StrokeVertex ch65st2[] = { {16.7857f,33.3333f}, {64.4048f,33.3333f} }; static const Fl_Glut_StrokeStrip ch65st[] = { {2,ch65st0}, {2,ch65st1}, {2,ch65st2} }; static const Fl_Glut_StrokeChar ch65 = {80.4905f,3,ch65st}; /* char: 0x42 */ static const Fl_Glut_StrokeVertex ch66st0[] = { {11.42f,100.0f}, {11.42f,0.0f} }; static const Fl_Glut_StrokeVertex ch66st1[] = { {11.42f,100.0f}, {54.2771f,100.0f}, {68.5629f,95.2381f}, {73.3248f,90.4762f}, {78.0867f,80.9524f}, {78.0867f,71.4286f}, {73.3248f,61.9048f}, {68.5629f,57.1429f}, {54.2771f,52.381f} }; static const Fl_Glut_StrokeVertex ch66st2[] = { {11.42f,52.381f}, {54.2771f,52.381f}, {68.5629f,47.619f}, {73.3248f,42.8571f}, {78.0867f,33.3333f}, {78.0867f,19.0476f}, {73.3248f,9.5238f}, {68.5629f,4.7619f}, {54.2771f,0.0f}, {11.42f,0.0f} }; static const Fl_Glut_StrokeStrip ch66st[] = { {2,ch66st0}, {9,ch66st1}, {10,ch66st2} }; static const Fl_Glut_StrokeChar ch66 = {83.6267f,3,ch66st}; /* char: 0x43 */ static const Fl_Glut_StrokeVertex ch67st0[] = { {78.0886f,76.1905f}, {73.3267f,85.7143f}, {63.8029f,95.2381f}, {54.279f,100.0f}, {35.2314f,100.0f}, {25.7076f,95.2381f}, {16.1838f,85.7143f}, {11.4219f,76.1905f}, {6.66f,61.9048f}, {6.66f,38.0952f}, {11.4219f,23.8095f}, {16.1838f,14.2857f}, {25.7076f,4.7619f}, {35.2314f,0.0f}, {54.279f,0.0f}, {63.8029f,4.7619f}, {73.3267f,14.2857f}, {78.0886f,23.8095f} }; static const Fl_Glut_StrokeStrip ch67st[] = { {18,ch67st0} }; static const Fl_Glut_StrokeChar ch67 = {84.4886f,1,ch67st}; /* char: 0x44 */ static const Fl_Glut_StrokeVertex ch68st0[] = { {11.96f,100.0f}, {11.96f,0.0f} }; static const Fl_Glut_StrokeVertex ch68st1[] = { {11.96f,100.0f}, {45.2933f,100.0f}, {59.579f,95.2381f}, {69.1029f,85.7143f}, {73.8648f,76.1905f}, {78.6267f,61.9048f}, {78.6267f,38.0952f}, {73.8648f,23.8095f}, {69.1029f,14.2857f}, {59.579f,4.7619f}, {45.2933f,0.0f}, {11.96f,0.0f} }; static const Fl_Glut_StrokeStrip ch68st[] = { {2,ch68st0}, {12,ch68st1} }; static const Fl_Glut_StrokeChar ch68 = {85.2867f,2,ch68st}; /* char: 0x45 */ static const Fl_Glut_StrokeVertex ch69st0[] = { {11.42f,100.0f}, {11.42f,0.0f} }; static const Fl_Glut_StrokeVertex ch69st1[] = { {11.42f,100.0f}, {73.3248f,100.0f} }; static const Fl_Glut_StrokeVertex ch69st2[] = { {11.42f,52.381f}, {49.5152f,52.381f} }; static const Fl_Glut_StrokeVertex ch69st3[] = { {11.42f,0.0f}, {73.3248f,0.0f} }; static const Fl_Glut_StrokeStrip ch69st[] = { {2,ch69st0}, {2,ch69st1}, {2,ch69st2}, {2,ch69st3} }; static const Fl_Glut_StrokeChar ch69 = {78.1848f,4,ch69st}; /* char: 0x46 */ static const Fl_Glut_StrokeVertex ch70st0[] = { {11.42f,100.0f}, {11.42f,0.0f} }; static const Fl_Glut_StrokeVertex ch70st1[] = { {11.42f,100.0f}, {73.3248f,100.0f} }; static const Fl_Glut_StrokeVertex ch70st2[] = { {11.42f,52.381f}, {49.5152f,52.381f} }; static const Fl_Glut_StrokeStrip ch70st[] = { {2,ch70st0}, {2,ch70st1}, {2,ch70st2} }; static const Fl_Glut_StrokeChar ch70 = {78.7448f,3,ch70st}; /* char: 0x47 */ static const Fl_Glut_StrokeVertex ch71st0[] = { {78.4886f,76.1905f}, {73.7267f,85.7143f}, {64.2029f,95.2381f}, {54.679f,100.0f}, {35.6314f,100.0f}, {26.1076f,95.2381f}, {16.5838f,85.7143f}, {11.8219f,76.1905f}, {7.06f,61.9048f}, {7.06f,38.0952f}, {11.8219f,23.8095f}, {16.5838f,14.2857f}, {26.1076f,4.7619f}, {35.6314f,0.0f}, {54.679f,0.0f}, {64.2029f,4.7619f}, {73.7267f,14.2857f}, {78.4886f,23.8095f}, {78.4886f,38.0952f} }; static const Fl_Glut_StrokeVertex ch71st1[] = { {54.679f,38.0952f}, {78.4886f,38.0952f} }; static const Fl_Glut_StrokeStrip ch71st[] = { {19,ch71st0}, {2,ch71st1} }; static const Fl_Glut_StrokeChar ch71 = {89.7686f,2,ch71st}; /* char: 0x48 */ static const Fl_Glut_StrokeVertex ch72st0[] = { {11.42f,100.0f}, {11.42f,0.0f} }; static const Fl_Glut_StrokeVertex ch72st1[] = { {78.0867f,100.0f}, {78.0867f,0.0f} }; static const Fl_Glut_StrokeVertex ch72st2[] = { {11.42f,52.381f}, {78.0867f,52.381f} }; static const Fl_Glut_StrokeStrip ch72st[] = { {2,ch72st0}, {2,ch72st1}, {2,ch72st2} }; static const Fl_Glut_StrokeChar ch72 = {89.0867f,3,ch72st}; /* char: 0x49 */ static const Fl_Glut_StrokeVertex ch73st0[] = { {10.86f,100.0f}, {10.86f,0.0f} }; static const Fl_Glut_StrokeStrip ch73st[] = { {2,ch73st0} }; static const Fl_Glut_StrokeChar ch73 = {21.3f,1,ch73st}; /* char: 0x4a */ static const Fl_Glut_StrokeVertex ch74st0[] = { {50.119f,100.0f}, {50.119f,23.8095f}, {45.3571f,9.5238f}, {40.5952f,4.7619f}, {31.0714f,0.0f}, {21.5476f,0.0f}, {12.0238f,4.7619f}, {7.2619f,9.5238f}, {2.5f,23.8095f}, {2.5f,33.3333f} }; static const Fl_Glut_StrokeStrip ch74st[] = { {10,ch74st0} }; static const Fl_Glut_StrokeChar ch74 = {59.999f,1,ch74st}; /* char: 0x4b */ static const Fl_Glut_StrokeVertex ch75st0[] = { {11.28f,100.0f}, {11.28f,0.0f} }; static const Fl_Glut_StrokeVertex ch75st1[] = { {77.9467f,100.0f}, {11.28f,33.3333f} }; static const Fl_Glut_StrokeVertex ch75st2[] = { {35.0895f,57.1429f}, {77.9467f,0.0f} }; static const Fl_Glut_StrokeStrip ch75st[] = { {2,ch75st0}, {2,ch75st1}, {2,ch75st2} }; static const Fl_Glut_StrokeChar ch75 = {79.3267f,3,ch75st}; /* char: 0x4c */ static const Fl_Glut_StrokeVertex ch76st0[] = { {11.68f,100.0f}, {11.68f,0.0f} }; static const Fl_Glut_StrokeVertex ch76st1[] = { {11.68f,0.0f}, {68.8229f,0.0f} }; static const Fl_Glut_StrokeStrip ch76st[] = { {2,ch76st0}, {2,ch76st1} }; static const Fl_Glut_StrokeChar ch76 = {71.3229f,2,ch76st}; /* char: 0x4d */ static const Fl_Glut_StrokeVertex ch77st0[] = { {10.86f,100.0f}, {10.86f,0.0f} }; static const Fl_Glut_StrokeVertex ch77st1[] = { {10.86f,100.0f}, {48.9552f,0.0f} }; static const Fl_Glut_StrokeVertex ch77st2[] = { {87.0505f,100.0f}, {48.9552f,0.0f} }; static const Fl_Glut_StrokeVertex ch77st3[] = { {87.0505f,100.0f}, {87.0505f,0.0f} }; static const Fl_Glut_StrokeStrip ch77st[] = { {2,ch77st0}, {2,ch77st1}, {2,ch77st2}, {2,ch77st3} }; static const Fl_Glut_StrokeChar ch77 = {97.2105f,4,ch77st}; /* char: 0x4e */ static const Fl_Glut_StrokeVertex ch78st0[] = { {11.14f,100.0f}, {11.14f,0.0f} }; static const Fl_Glut_StrokeVertex ch78st1[] = { {11.14f,100.0f}, {77.8067f,0.0f} }; static const Fl_Glut_StrokeVertex ch78st2[] = { {77.8067f,100.0f}, {77.8067f,0.0f} }; static const Fl_Glut_StrokeStrip ch78st[] = { {2,ch78st0}, {2,ch78st1}, {2,ch78st2} }; static const Fl_Glut_StrokeChar ch78 = {88.8067f,3,ch78st}; /* char: 0x4f */ static const Fl_Glut_StrokeVertex ch79st0[] = { {34.8114f,100.0f}, {25.2876f,95.2381f}, {15.7638f,85.7143f}, {11.0019f,76.1905f}, {6.24f,61.9048f}, {6.24f,38.0952f}, {11.0019f,23.8095f}, {15.7638f,14.2857f}, {25.2876f,4.7619f}, {34.8114f,0.0f}, {53.859f,0.0f}, {63.3829f,4.7619f}, {72.9067f,14.2857f}, {77.6686f,23.8095f}, {82.4305f,38.0952f}, {82.4305f,61.9048f}, {77.6686f,76.1905f}, {72.9067f,85.7143f}, {63.3829f,95.2381f}, {53.859f,100.0f}, {34.8114f,100.0f} }; static const Fl_Glut_StrokeStrip ch79st[] = { {21,ch79st0} }; static const Fl_Glut_StrokeChar ch79 = {88.8305f,1,ch79st}; /* char: 0x50 */ static const Fl_Glut_StrokeVertex ch80st0[] = { {12.1f,100.0f}, {12.1f,0.0f} }; static const Fl_Glut_StrokeVertex ch80st1[] = { {12.1f,100.0f}, {54.9571f,100.0f}, {69.2429f,95.2381f}, {74.0048f,90.4762f}, {78.7667f,80.9524f}, {78.7667f,66.6667f}, {74.0048f,57.1429f}, {69.2429f,52.381f}, {54.9571f,47.619f}, {12.1f,47.619f} }; static const Fl_Glut_StrokeStrip ch80st[] = { {2,ch80st0}, {10,ch80st1} }; static const Fl_Glut_StrokeChar ch80 = {85.6667f,2,ch80st}; /* char: 0x51 */ static const Fl_Glut_StrokeVertex ch81st0[] = { {33.8714f,100.0f}, {24.3476f,95.2381f}, {14.8238f,85.7143f}, {10.0619f,76.1905f}, {5.3f,61.9048f}, {5.3f,38.0952f}, {10.0619f,23.8095f}, {14.8238f,14.2857f}, {24.3476f,4.7619f}, {33.8714f,0.0f}, {52.919f,0.0f}, {62.4429f,4.7619f}, {71.9667f,14.2857f}, {76.7286f,23.8095f}, {81.4905f,38.0952f}, {81.4905f,61.9048f}, {76.7286f,76.1905f}, {71.9667f,85.7143f}, {62.4429f,95.2381f}, {52.919f,100.0f}, {33.8714f,100.0f} }; static const Fl_Glut_StrokeVertex ch81st1[] = { {48.1571f,19.0476f}, {76.7286f,-9.5238f} }; static const Fl_Glut_StrokeStrip ch81st[] = { {21,ch81st0}, {2,ch81st1} }; static const Fl_Glut_StrokeChar ch81 = {88.0905f,2,ch81st}; /* char: 0x52 */ static const Fl_Glut_StrokeVertex ch82st0[] = { {11.68f,100.0f}, {11.68f,0.0f} }; static const Fl_Glut_StrokeVertex ch82st1[] = { {11.68f,100.0f}, {54.5371f,100.0f}, {68.8229f,95.2381f}, {73.5848f,90.4762f}, {78.3467f,80.9524f}, {78.3467f,71.4286f}, {73.5848f,61.9048f}, {68.8229f,57.1429f}, {54.5371f,52.381f}, {11.68f,52.381f} }; static const Fl_Glut_StrokeVertex ch82st2[] = { {45.0133f,52.381f}, {78.3467f,0.0f} }; static const Fl_Glut_StrokeStrip ch82st[] = { {2,ch82st0}, {10,ch82st1}, {2,ch82st2} }; static const Fl_Glut_StrokeChar ch82 = {82.3667f,3,ch82st}; /* char: 0x53 */ static const Fl_Glut_StrokeVertex ch83st0[] = { {74.6667f,85.7143f}, {65.1429f,95.2381f}, {50.8571f,100.0f}, {31.8095f,100.0f}, {17.5238f,95.2381f}, {8.0f,85.7143f}, {8.0f,76.1905f}, {12.7619f,66.6667f}, {17.5238f,61.9048f}, {27.0476f,57.1429f}, {55.619f,47.619f}, {65.1429f,42.8571f}, {69.9048f,38.0952f}, {74.6667f,28.5714f}, {74.6667f,14.2857f}, {65.1429f,4.7619f}, {50.8571f,0.0f}, {31.8095f,0.0f}, {17.5238f,4.7619f}, {8.0f,14.2857f} }; static const Fl_Glut_StrokeStrip ch83st[] = { {20,ch83st0} }; static const Fl_Glut_StrokeChar ch83 = {80.8267f,1,ch83st}; /* char: 0x54 */ static const Fl_Glut_StrokeVertex ch84st0[] = { {35.6933f,100.0f}, {35.6933f,0.0f} }; static const Fl_Glut_StrokeVertex ch84st1[] = { {2.36f,100.0f}, {69.0267f,100.0f} }; static const Fl_Glut_StrokeStrip ch84st[] = { {2,ch84st0}, {2,ch84st1} }; static const Fl_Glut_StrokeChar ch84 = {71.9467f,2,ch84st}; /* char: 0x55 */ static const Fl_Glut_StrokeVertex ch85st0[] = { {11.54f,100.0f}, {11.54f,28.5714f}, {16.3019f,14.2857f}, {25.8257f,4.7619f}, {40.1114f,0.0f}, {49.6352f,0.0f}, {63.921f,4.7619f}, {73.4448f,14.2857f}, {78.2067f,28.5714f}, {78.2067f,100.0f} }; static const Fl_Glut_StrokeStrip ch85st[] = { {10,ch85st0} }; static const Fl_Glut_StrokeChar ch85 = {89.4867f,1,ch85st}; /* char: 0x56 */ static const Fl_Glut_StrokeVertex ch86st0[] = { {2.36f,100.0f}, {40.4552f,0.0f} }; static const Fl_Glut_StrokeVertex ch86st1[] = { {78.5505f,100.0f}, {40.4552f,0.0f} }; static const Fl_Glut_StrokeStrip ch86st[] = { {2,ch86st0}, {2,ch86st1} }; static const Fl_Glut_StrokeChar ch86 = {81.6105f,2,ch86st}; /* char: 0x57 */ static const Fl_Glut_StrokeVertex ch87st0[] = { {2.22f,100.0f}, {26.0295f,0.0f} }; static const Fl_Glut_StrokeVertex ch87st1[] = { {49.839f,100.0f}, {26.0295f,0.0f} }; static const Fl_Glut_StrokeVertex ch87st2[] = { {49.839f,100.0f}, {73.6486f,0.0f} }; static const Fl_Glut_StrokeVertex ch87st3[] = { {97.4581f,100.0f}, {73.6486f,0.0f} }; static const Fl_Glut_StrokeStrip ch87st[] = { {2,ch87st0}, {2,ch87st1}, {2,ch87st2}, {2,ch87st3} }; static const Fl_Glut_StrokeChar ch87 = {100.518f,4,ch87st}; /* char: 0x58 */ static const Fl_Glut_StrokeVertex ch88st0[] = { {2.5f,100.0f}, {69.1667f,0.0f} }; static const Fl_Glut_StrokeVertex ch88st1[] = { {69.1667f,100.0f}, {2.5f,0.0f} }; static const Fl_Glut_StrokeStrip ch88st[] = { {2,ch88st0}, {2,ch88st1} }; static const Fl_Glut_StrokeChar ch88 = {72.3667f,2,ch88st}; /* char: 0x59 */ static const Fl_Glut_StrokeVertex ch89st0[] = { {1.52f,100.0f}, {39.6152f,52.381f}, {39.6152f,0.0f} }; static const Fl_Glut_StrokeVertex ch89st1[] = { {77.7105f,100.0f}, {39.6152f,52.381f} }; static const Fl_Glut_StrokeStrip ch89st[] = { {3,ch89st0}, {2,ch89st1} }; static const Fl_Glut_StrokeChar ch89 = {79.6505f,2,ch89st}; /* char: 0x5a */ static const Fl_Glut_StrokeVertex ch90st0[] = { {69.1667f,100.0f}, {2.5f,0.0f} }; static const Fl_Glut_StrokeVertex ch90st1[] = { {2.5f,100.0f}, {69.1667f,100.0f} }; static const Fl_Glut_StrokeVertex ch90st2[] = { {2.5f,0.0f}, {69.1667f,0.0f} }; static const Fl_Glut_StrokeStrip ch90st[] = { {2,ch90st0}, {2,ch90st1}, {2,ch90st2} }; static const Fl_Glut_StrokeChar ch90 = {73.7467f,3,ch90st}; /* char: 0x5b */ static const Fl_Glut_StrokeVertex ch91st0[] = { {7.78f,119.048f}, {7.78f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch91st1[] = { {12.5419f,119.048f}, {12.5419f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch91st2[] = { {7.78f,119.048f}, {41.1133f,119.048f} }; static const Fl_Glut_StrokeVertex ch91st3[] = { {7.78f,-33.3333f}, {41.1133f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch91st[] = { {2,ch91st0}, {2,ch91st1}, {2,ch91st2}, {2,ch91st3} }; static const Fl_Glut_StrokeChar ch91 = {46.1133f,4,ch91st}; /* char: 0x5c */ static const Fl_Glut_StrokeVertex ch92st0[] = { {5.84f,100.0f}, {72.5067f,-14.2857f} }; static const Fl_Glut_StrokeStrip ch92st[] = { {2,ch92st0} }; static const Fl_Glut_StrokeChar ch92 = {78.2067f,1,ch92st}; /* char: 0x5d */ static const Fl_Glut_StrokeVertex ch93st0[] = { {33.0114f,119.048f}, {33.0114f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch93st1[] = { {37.7733f,119.048f}, {37.7733f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch93st2[] = { {4.44f,119.048f}, {37.7733f,119.048f} }; static const Fl_Glut_StrokeVertex ch93st3[] = { {4.44f,-33.3333f}, {37.7733f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch93st[] = { {2,ch93st0}, {2,ch93st1}, {2,ch93st2}, {2,ch93st3} }; static const Fl_Glut_StrokeChar ch93 = {46.3933f,4,ch93st}; /* char: 0x5e */ static const Fl_Glut_StrokeVertex ch94st0[] = { {44.0752f,109.524f}, {5.98f,42.8571f} }; static const Fl_Glut_StrokeVertex ch94st1[] = { {44.0752f,109.524f}, {82.1705f,42.8571f} }; static const Fl_Glut_StrokeStrip ch94st[] = { {2,ch94st0}, {2,ch94st1} }; static const Fl_Glut_StrokeChar ch94 = {90.2305f,2,ch94st}; /* char: 0x5f */ static const Fl_Glut_StrokeVertex ch95st0[] = { {-1.1f,-33.3333f}, {103.662f,-33.3333f}, {103.662f,-28.5714f}, {-1.1f,-28.5714f}, {-1.1f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch95st[] = { {5,ch95st0} }; static const Fl_Glut_StrokeChar ch95 = {104.062f,1,ch95st}; /* char: 0x60 */ static const Fl_Glut_StrokeVertex ch96st0[] = { {33.0219f,100.0f}, {56.8314f,71.4286f} }; static const Fl_Glut_StrokeVertex ch96st1[] = { {33.0219f,100.0f}, {28.26f,95.2381f}, {56.8314f,71.4286f} }; static const Fl_Glut_StrokeStrip ch96st[] = { {2,ch96st0}, {3,ch96st1} }; static const Fl_Glut_StrokeChar ch96 = {83.5714f,2,ch96st}; /* char: 0x61 */ static const Fl_Glut_StrokeVertex ch97st0[] = { {63.8229f,66.6667f}, {63.8229f,0.0f} }; static const Fl_Glut_StrokeVertex ch97st1[] = { {63.8229f,52.381f}, {54.299f,61.9048f}, {44.7752f,66.6667f}, {30.4895f,66.6667f}, {20.9657f,61.9048f}, {11.4419f,52.381f}, {6.68f,38.0952f}, {6.68f,28.5714f}, {11.4419f,14.2857f}, {20.9657f,4.7619f}, {30.4895f,0.0f}, {44.7752f,0.0f}, {54.299f,4.7619f}, {63.8229f,14.2857f} }; static const Fl_Glut_StrokeStrip ch97st[] = { {2,ch97st0}, {14,ch97st1} }; static const Fl_Glut_StrokeChar ch97 = {66.6029f,2,ch97st}; /* char: 0x62 */ static const Fl_Glut_StrokeVertex ch98st0[] = { {8.76f,100.0f}, {8.76f,0.0f} }; static const Fl_Glut_StrokeVertex ch98st1[] = { {8.76f,52.381f}, {18.2838f,61.9048f}, {27.8076f,66.6667f}, {42.0933f,66.6667f}, {51.6171f,61.9048f}, {61.141f,52.381f}, {65.9029f,38.0952f}, {65.9029f,28.5714f}, {61.141f,14.2857f}, {51.6171f,4.7619f}, {42.0933f,0.0f}, {27.8076f,0.0f}, {18.2838f,4.7619f}, {8.76f,14.2857f} }; static const Fl_Glut_StrokeStrip ch98st[] = { {2,ch98st0}, {14,ch98st1} }; static const Fl_Glut_StrokeChar ch98 = {70.4629f,2,ch98st}; /* char: 0x63 */ static const Fl_Glut_StrokeVertex ch99st0[] = { {62.6629f,52.381f}, {53.139f,61.9048f}, {43.6152f,66.6667f}, {29.3295f,66.6667f}, {19.8057f,61.9048f}, {10.2819f,52.381f}, {5.52f,38.0952f}, {5.52f,28.5714f}, {10.2819f,14.2857f}, {19.8057f,4.7619f}, {29.3295f,0.0f}, {43.6152f,0.0f}, {53.139f,4.7619f}, {62.6629f,14.2857f} }; static const Fl_Glut_StrokeStrip ch99st[] = { {14,ch99st0} }; static const Fl_Glut_StrokeChar ch99 = {68.9229f,1,ch99st}; /* char: 0x64 */ static const Fl_Glut_StrokeVertex ch100st0[] = { {61.7829f,100.0f}, {61.7829f,0.0f} }; static const Fl_Glut_StrokeVertex ch100st1[] = { {61.7829f,52.381f}, {52.259f,61.9048f}, {42.7352f,66.6667f}, {28.4495f,66.6667f}, {18.9257f,61.9048f}, {9.4019f,52.381f}, {4.64f,38.0952f}, {4.64f,28.5714f}, {9.4019f,14.2857f}, {18.9257f,4.7619f}, {28.4495f,0.0f}, {42.7352f,0.0f}, {52.259f,4.7619f}, {61.7829f,14.2857f} }; static const Fl_Glut_StrokeStrip ch100st[] = { {2,ch100st0}, {14,ch100st1} }; static const Fl_Glut_StrokeChar ch100 = {70.2629f,2,ch100st}; /* char: 0x65 */ static const Fl_Glut_StrokeVertex ch101st0[] = { {5.72f,38.0952f}, {62.8629f,38.0952f}, {62.8629f,47.619f}, {58.101f,57.1429f}, {53.339f,61.9048f}, {43.8152f,66.6667f}, {29.5295f,66.6667f}, {20.0057f,61.9048f}, {10.4819f,52.381f}, {5.72f,38.0952f}, {5.72f,28.5714f}, {10.4819f,14.2857f}, {20.0057f,4.7619f}, {29.5295f,0.0f}, {43.8152f,0.0f}, {53.339f,4.7619f}, {62.8629f,14.2857f} }; static const Fl_Glut_StrokeStrip ch101st[] = { {17,ch101st0} }; static const Fl_Glut_StrokeChar ch101 = {68.5229f,1,ch101st}; /* char: 0x66 */ static const Fl_Glut_StrokeVertex ch102st0[] = { {38.7752f,100.0f}, {29.2514f,100.0f}, {19.7276f,95.2381f}, {14.9657f,80.9524f}, {14.9657f,0.0f} }; static const Fl_Glut_StrokeVertex ch102st1[] = { {0.68f,66.6667f}, {34.0133f,66.6667f} }; static const Fl_Glut_StrokeStrip ch102st[] = { {5,ch102st0}, {2,ch102st1} }; static const Fl_Glut_StrokeChar ch102 = {38.6552f,2,ch102st}; /* char: 0x67 */ static const Fl_Glut_StrokeVertex ch103st0[] = { {62.5029f,66.6667f}, {62.5029f,-9.5238f}, {57.741f,-23.8095f}, {52.979f,-28.5714f}, {43.4552f,-33.3333f}, {29.1695f,-33.3333f}, {19.6457f,-28.5714f} }; static const Fl_Glut_StrokeVertex ch103st1[] = { {62.5029f,52.381f}, {52.979f,61.9048f}, {43.4552f,66.6667f}, {29.1695f,66.6667f}, {19.6457f,61.9048f}, {10.1219f,52.381f}, {5.36f,38.0952f}, {5.36f,28.5714f}, {10.1219f,14.2857f}, {19.6457f,4.7619f}, {29.1695f,0.0f}, {43.4552f,0.0f}, {52.979f,4.7619f}, {62.5029f,14.2857f} }; static const Fl_Glut_StrokeStrip ch103st[] = { {7,ch103st0}, {14,ch103st1} }; static const Fl_Glut_StrokeChar ch103 = {70.9829f,2,ch103st}; /* char: 0x68 */ static const Fl_Glut_StrokeVertex ch104st0[] = { {9.6f,100.0f}, {9.6f,0.0f} }; static const Fl_Glut_StrokeVertex ch104st1[] = { {9.6f,47.619f}, {23.8857f,61.9048f}, {33.4095f,66.6667f}, {47.6952f,66.6667f}, {57.219f,61.9048f}, {61.981f,47.619f}, {61.981f,0.0f} }; static const Fl_Glut_StrokeStrip ch104st[] = { {2,ch104st0}, {7,ch104st1} }; static const Fl_Glut_StrokeChar ch104 = {71.021f,2,ch104st}; /* char: 0x69 */ static const Fl_Glut_StrokeVertex ch105st0[] = { {10.02f,100.0f}, {14.7819f,95.2381f}, {19.5438f,100.0f}, {14.7819f,104.762f}, {10.02f,100.0f} }; static const Fl_Glut_StrokeVertex ch105st1[] = { {14.7819f,66.6667f}, {14.7819f,0.0f} }; static const Fl_Glut_StrokeStrip ch105st[] = { {5,ch105st0}, {2,ch105st1} }; static const Fl_Glut_StrokeChar ch105 = {28.8638f,2,ch105st}; /* char: 0x6a */ static const Fl_Glut_StrokeVertex ch106st0[] = { {17.3876f,100.0f}, {22.1495f,95.2381f}, {26.9114f,100.0f}, {22.1495f,104.762f}, {17.3876f,100.0f} }; static const Fl_Glut_StrokeVertex ch106st1[] = { {22.1495f,66.6667f}, {22.1495f,-14.2857f}, {17.3876f,-28.5714f}, {7.8638f,-33.3333f}, {-1.66f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch106st[] = { {5,ch106st0}, {5,ch106st1} }; static const Fl_Glut_StrokeChar ch106 = {36.2314f,2,ch106st}; /* char: 0x6b */ static const Fl_Glut_StrokeVertex ch107st0[] = { {9.6f,100.0f}, {9.6f,0.0f} }; static const Fl_Glut_StrokeVertex ch107st1[] = { {57.219f,66.6667f}, {9.6f,19.0476f} }; static const Fl_Glut_StrokeVertex ch107st2[] = { {28.6476f,38.0952f}, {61.981f,0.0f} }; static const Fl_Glut_StrokeStrip ch107st[] = { {2,ch107st0}, {2,ch107st1}, {2,ch107st2} }; static const Fl_Glut_StrokeChar ch107 = {62.521f,3,ch107st}; /* char: 0x6c */ static const Fl_Glut_StrokeVertex ch108st0[] = { {10.02f,100.0f}, {10.02f,0.0f} }; static const Fl_Glut_StrokeStrip ch108st[] = { {2,ch108st0} }; static const Fl_Glut_StrokeChar ch108 = {19.34f,1,ch108st}; /* char: 0x6d */ static const Fl_Glut_StrokeVertex ch109st0[] = { {9.6f,66.6667f}, {9.6f,0.0f} }; static const Fl_Glut_StrokeVertex ch109st1[] = { {9.6f,47.619f}, {23.8857f,61.9048f}, {33.4095f,66.6667f}, {47.6952f,66.6667f}, {57.219f,61.9048f}, {61.981f,47.619f}, {61.981f,0.0f} }; static const Fl_Glut_StrokeVertex ch109st2[] = { {61.981f,47.619f}, {76.2667f,61.9048f}, {85.7905f,66.6667f}, {100.076f,66.6667f}, {109.6f,61.9048f}, {114.362f,47.619f}, {114.362f,0.0f} }; static const Fl_Glut_StrokeStrip ch109st[] = { {2,ch109st0}, {7,ch109st1}, {7,ch109st2} }; static const Fl_Glut_StrokeChar ch109 = {123.962f,3,ch109st}; /* char: 0x6e */ static const Fl_Glut_StrokeVertex ch110st0[] = { {9.18f,66.6667f}, {9.18f,0.0f} }; static const Fl_Glut_StrokeVertex ch110st1[] = { {9.18f,47.619f}, {23.4657f,61.9048f}, {32.9895f,66.6667f}, {47.2752f,66.6667f}, {56.799f,61.9048f}, {61.561f,47.619f}, {61.561f,0.0f} }; static const Fl_Glut_StrokeStrip ch110st[] = { {2,ch110st0}, {7,ch110st1} }; static const Fl_Glut_StrokeChar ch110 = {70.881f,2,ch110st}; /* char: 0x6f */ static const Fl_Glut_StrokeVertex ch111st0[] = { {28.7895f,66.6667f}, {19.2657f,61.9048f}, {9.7419f,52.381f}, {4.98f,38.0952f}, {4.98f,28.5714f}, {9.7419f,14.2857f}, {19.2657f,4.7619f}, {28.7895f,0.0f}, {43.0752f,0.0f}, {52.599f,4.7619f}, {62.1229f,14.2857f}, {66.8848f,28.5714f}, {66.8848f,38.0952f}, {62.1229f,52.381f}, {52.599f,61.9048f}, {43.0752f,66.6667f}, {28.7895f,66.6667f} }; static const Fl_Glut_StrokeStrip ch111st[] = { {17,ch111st0} }; static const Fl_Glut_StrokeChar ch111 = {71.7448f,1,ch111st}; /* char: 0x70 */ static const Fl_Glut_StrokeVertex ch112st0[] = { {9.46f,66.6667f}, {9.46f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch112st1[] = { {9.46f,52.381f}, {18.9838f,61.9048f}, {28.5076f,66.6667f}, {42.7933f,66.6667f}, {52.3171f,61.9048f}, {61.841f,52.381f}, {66.6029f,38.0952f}, {66.6029f,28.5714f}, {61.841f,14.2857f}, {52.3171f,4.7619f}, {42.7933f,0.0f}, {28.5076f,0.0f}, {18.9838f,4.7619f}, {9.46f,14.2857f} }; static const Fl_Glut_StrokeStrip ch112st[] = { {2,ch112st0}, {14,ch112st1} }; static const Fl_Glut_StrokeChar ch112 = {70.8029f,2,ch112st}; /* char: 0x71 */ static const Fl_Glut_StrokeVertex ch113st0[] = { {61.9829f,66.6667f}, {61.9829f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch113st1[] = { {61.9829f,52.381f}, {52.459f,61.9048f}, {42.9352f,66.6667f}, {28.6495f,66.6667f}, {19.1257f,61.9048f}, {9.6019f,52.381f}, {4.84f,38.0952f}, {4.84f,28.5714f}, {9.6019f,14.2857f}, {19.1257f,4.7619f}, {28.6495f,0.0f}, {42.9352f,0.0f}, {52.459f,4.7619f}, {61.9829f,14.2857f} }; static const Fl_Glut_StrokeStrip ch113st[] = { {2,ch113st0}, {14,ch113st1} }; static const Fl_Glut_StrokeChar ch113 = {70.7429f,2,ch113st}; /* char: 0x72 */ static const Fl_Glut_StrokeVertex ch114st0[] = { {9.46f,66.6667f}, {9.46f,0.0f} }; static const Fl_Glut_StrokeVertex ch114st1[] = { {9.46f,38.0952f}, {14.2219f,52.381f}, {23.7457f,61.9048f}, {33.2695f,66.6667f}, {47.5552f,66.6667f} }; static const Fl_Glut_StrokeStrip ch114st[] = { {2,ch114st0}, {5,ch114st1} }; static const Fl_Glut_StrokeChar ch114 = {49.4952f,2,ch114st}; /* char: 0x73 */ static const Fl_Glut_StrokeVertex ch115st0[] = { {57.081f,52.381f}, {52.319f,61.9048f}, {38.0333f,66.6667f}, {23.7476f,66.6667f}, {9.4619f,61.9048f}, {4.7f,52.381f}, {9.4619f,42.8571f}, {18.9857f,38.0952f}, {42.7952f,33.3333f}, {52.319f,28.5714f}, {57.081f,19.0476f}, {57.081f,14.2857f}, {52.319f,4.7619f}, {38.0333f,0.0f}, {23.7476f,0.0f}, {9.4619f,4.7619f}, {4.7f,14.2857f} }; static const Fl_Glut_StrokeStrip ch115st[] = { {17,ch115st0} }; static const Fl_Glut_StrokeChar ch115 = {62.321f,1,ch115st}; /* char: 0x74 */ static const Fl_Glut_StrokeVertex ch116st0[] = { {14.8257f,100.0f}, {14.8257f,19.0476f}, {19.5876f,4.7619f}, {29.1114f,0.0f}, {38.6352f,0.0f} }; static const Fl_Glut_StrokeVertex ch116st1[] = { {0.54f,66.6667f}, {33.8733f,66.6667f} }; static const Fl_Glut_StrokeStrip ch116st[] = { {5,ch116st0}, {2,ch116st1} }; static const Fl_Glut_StrokeChar ch116 = {39.3152f,2,ch116st}; /* char: 0x75 */ static const Fl_Glut_StrokeVertex ch117st0[] = { {9.46f,66.6667f}, {9.46f,19.0476f}, {14.2219f,4.7619f}, {23.7457f,0.0f}, {38.0314f,0.0f}, {47.5552f,4.7619f}, {61.841f,19.0476f} }; static const Fl_Glut_StrokeVertex ch117st1[] = { {61.841f,66.6667f}, {61.841f,0.0f} }; static const Fl_Glut_StrokeStrip ch117st[] = { {7,ch117st0}, {2,ch117st1} }; static const Fl_Glut_StrokeChar ch117 = {71.161f,2,ch117st}; /* char: 0x76 */ static const Fl_Glut_StrokeVertex ch118st0[] = { {1.8f,66.6667f}, {30.3714f,0.0f} }; static const Fl_Glut_StrokeVertex ch118st1[] = { {58.9429f,66.6667f}, {30.3714f,0.0f} }; static const Fl_Glut_StrokeStrip ch118st[] = { {2,ch118st0}, {2,ch118st1} }; static const Fl_Glut_StrokeChar ch118 = {60.6029f,2,ch118st}; /* char: 0x77 */ static const Fl_Glut_StrokeVertex ch119st0[] = { {2.5f,66.6667f}, {21.5476f,0.0f} }; static const Fl_Glut_StrokeVertex ch119st1[] = { {40.5952f,66.6667f}, {21.5476f,0.0f} }; static const Fl_Glut_StrokeVertex ch119st2[] = { {40.5952f,66.6667f}, {59.6429f,0.0f} }; static const Fl_Glut_StrokeVertex ch119st3[] = { {78.6905f,66.6667f}, {59.6429f,0.0f} }; static const Fl_Glut_StrokeStrip ch119st[] = { {2,ch119st0}, {2,ch119st1}, {2,ch119st2}, {2,ch119st3} }; static const Fl_Glut_StrokeChar ch119 = {80.4905f,4,ch119st}; /* char: 0x78 */ static const Fl_Glut_StrokeVertex ch120st0[] = { {1.66f,66.6667f}, {54.041f,0.0f} }; static const Fl_Glut_StrokeVertex ch120st1[] = { {54.041f,66.6667f}, {1.66f,0.0f} }; static const Fl_Glut_StrokeStrip ch120st[] = { {2,ch120st0}, {2,ch120st1} }; static const Fl_Glut_StrokeChar ch120 = {56.401f,2,ch120st}; /* char: 0x79 */ static const Fl_Glut_StrokeVertex ch121st0[] = { {6.5619f,66.6667f}, {35.1333f,0.0f} }; static const Fl_Glut_StrokeVertex ch121st1[] = { {63.7048f,66.6667f}, {35.1333f,0.0f}, {25.6095f,-19.0476f}, {16.0857f,-28.5714f}, {6.5619f,-33.3333f}, {1.8f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch121st[] = { {2,ch121st0}, {6,ch121st1} }; static const Fl_Glut_StrokeChar ch121 = {66.0648f,2,ch121st}; /* char: 0x7a */ static const Fl_Glut_StrokeVertex ch122st0[] = { {56.821f,66.6667f}, {4.44f,0.0f} }; static const Fl_Glut_StrokeVertex ch122st1[] = { {4.44f,66.6667f}, {56.821f,66.6667f} }; static const Fl_Glut_StrokeVertex ch122st2[] = { {4.44f,0.0f}, {56.821f,0.0f} }; static const Fl_Glut_StrokeStrip ch122st[] = { {2,ch122st0}, {2,ch122st1}, {2,ch122st2} }; static const Fl_Glut_StrokeChar ch122 = {61.821f,3,ch122st}; /* char: 0x7b */ static const Fl_Glut_StrokeVertex ch123st0[] = { {31.1895f,119.048f}, {21.6657f,114.286f}, {16.9038f,109.524f}, {12.1419f,100.0f}, {12.1419f,90.4762f}, {16.9038f,80.9524f}, {21.6657f,76.1905f}, {26.4276f,66.6667f}, {26.4276f,57.1429f}, {16.9038f,47.619f} }; static const Fl_Glut_StrokeVertex ch123st1[] = { {21.6657f,114.286f}, {16.9038f,104.762f}, {16.9038f,95.2381f}, {21.6657f,85.7143f}, {26.4276f,80.9524f}, {31.1895f,71.4286f}, {31.1895f,61.9048f}, {26.4276f,52.381f}, {7.38f,42.8571f}, {26.4276f,33.3333f}, {31.1895f,23.8095f}, {31.1895f,14.2857f}, {26.4276f,4.7619f}, {21.6657f,0.0f}, {16.9038f,-9.5238f}, {16.9038f,-19.0476f}, {21.6657f,-28.5714f} }; static const Fl_Glut_StrokeVertex ch123st2[] = { {16.9038f,38.0952f}, {26.4276f,28.5714f}, {26.4276f,19.0476f}, {21.6657f,9.5238f}, {16.9038f,4.7619f}, {12.1419f,-4.7619f}, {12.1419f,-14.2857f}, {16.9038f,-23.8095f}, {21.6657f,-28.5714f}, {31.1895f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch123st[] = { {10,ch123st0}, {17,ch123st1}, {10,ch123st2} }; static const Fl_Glut_StrokeChar ch123 = {41.6295f,3,ch123st}; /* char: 0x7c */ static const Fl_Glut_StrokeVertex ch124st0[] = { {11.54f,119.048f}, {11.54f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch124st[] = { {2,ch124st0} }; static const Fl_Glut_StrokeChar ch124 = {23.78f,1,ch124st}; /* char: 0x7d */ static const Fl_Glut_StrokeVertex ch125st0[] = { {9.18f,119.048f}, {18.7038f,114.286f}, {23.4657f,109.524f}, {28.2276f,100.0f}, {28.2276f,90.4762f}, {23.4657f,80.9524f}, {18.7038f,76.1905f}, {13.9419f,66.6667f}, {13.9419f,57.1429f}, {23.4657f,47.619f} }; static const Fl_Glut_StrokeVertex ch125st1[] = { {18.7038f,114.286f}, {23.4657f,104.762f}, {23.4657f,95.2381f}, {18.7038f,85.7143f}, {13.9419f,80.9524f}, {9.18f,71.4286f}, {9.18f,61.9048f}, {13.9419f,52.381f}, {32.9895f,42.8571f}, {13.9419f,33.3333f}, {9.18f,23.8095f}, {9.18f,14.2857f}, {13.9419f,4.7619f}, {18.7038f,0.0f}, {23.4657f,-9.5238f}, {23.4657f,-19.0476f}, {18.7038f,-28.5714f} }; static const Fl_Glut_StrokeVertex ch125st2[] = { {23.4657f,38.0952f}, {13.9419f,28.5714f}, {13.9419f,19.0476f}, {18.7038f,9.5238f}, {23.4657f,4.7619f}, {28.2276f,-4.7619f}, {28.2276f,-14.2857f}, {23.4657f,-23.8095f}, {18.7038f,-28.5714f}, {9.18f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch125st[] = { {10,ch125st0}, {17,ch125st1}, {10,ch125st2} }; static const Fl_Glut_StrokeChar ch125 = {41.4695f,3,ch125st}; /* char: 0x7e */ static const Fl_Glut_StrokeVertex ch126st0[] = { {2.92f,28.5714f}, {2.92f,38.0952f}, {7.6819f,52.381f}, {17.2057f,57.1429f}, {26.7295f,57.1429f}, {36.2533f,52.381f}, {55.301f,38.0952f}, {64.8248f,33.3333f}, {74.3486f,33.3333f}, {83.8724f,38.0952f}, {88.6343f,47.619f} }; static const Fl_Glut_StrokeVertex ch126st1[] = { {2.92f,38.0952f}, {7.6819f,47.619f}, {17.2057f,52.381f}, {26.7295f,52.381f}, {36.2533f,47.619f}, {55.301f,33.3333f}, {64.8248f,28.5714f}, {74.3486f,28.5714f}, {83.8724f,33.3333f}, {88.6343f,47.619f}, {88.6343f,57.1429f} }; static const Fl_Glut_StrokeStrip ch126st[] = { {11,ch126st0}, {11,ch126st1} }; static const Fl_Glut_StrokeChar ch126 = {91.2743f,2,ch126st}; /* char: 0x7f */ static const Fl_Glut_StrokeVertex ch127st0[] = { {52.381f,100.0f}, {14.2857f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch127st1[] = { {28.5714f,66.6667f}, {14.2857f,61.9048f}, {4.7619f,52.381f}, {0.0f,38.0952f}, {0.0f,23.8095f}, {4.7619f,14.2857f}, {14.2857f,4.7619f}, {28.5714f,0.0f}, {38.0952f,0.0f}, {52.381f,4.7619f}, {61.9048f,14.2857f}, {66.6667f,28.5714f}, {66.6667f,42.8571f}, {61.9048f,52.381f}, {52.381f,61.9048f}, {38.0952f,66.6667f}, {28.5714f,66.6667f} }; static const Fl_Glut_StrokeStrip ch127st[] = { {2,ch127st0}, {17,ch127st1} }; static const Fl_Glut_StrokeChar ch127 = {66.6667f,2,ch127st}; static const Fl_Glut_StrokeChar *chars[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &ch32, &ch33, &ch34, &ch35, &ch36, &ch37, &ch38, &ch39, &ch40, &ch41, &ch42, &ch43, &ch44, &ch45, &ch46, &ch47, &ch48, &ch49, &ch50, &ch51, &ch52, &ch53, &ch54, &ch55, &ch56, &ch57, &ch58, &ch59, &ch60, &ch61, &ch62, &ch63, &ch64, &ch65, &ch66, &ch67, &ch68, &ch69, &ch70, &ch71, &ch72, &ch73, &ch74, &ch75, &ch76, &ch77, &ch78, &ch79, &ch80, &ch81, &ch82, &ch83, &ch84, &ch85, &ch86, &ch87, &ch88, &ch89, &ch90, &ch91, &ch92, &ch93, &ch94, &ch95, &ch96, &ch97, &ch98, &ch99, &ch100, &ch101, &ch102, &ch103, &ch104, &ch105, &ch106, &ch107, &ch108, &ch109, &ch110, &ch111, &ch112, &ch113, &ch114, &ch115, &ch116, &ch117, &ch118, &ch119, &ch120, &ch121, &ch122, &ch123, &ch124, &ch125, &ch126, &ch127 }; Fl_Glut_StrokeFont glutStrokeRoman = {(char *)"Roman",128,152.381f,chars}; fltk-1.4.3/src/fl_show_colormap.cxx0000644000175000017500000000745015004135251017463 0ustar albrechtalbrecht// // Colormap color selection dialog for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #define BOXSIZE 14 #define BORDER 4 /** This widget creates a modal window for selecting a color from the colormap. Pretty much unchanged from Forms. */ class ColorMenu : public Fl_Window { Fl_Color initial; Fl_Color which, previous; int done; void drawbox(Fl_Color); void draw() FL_OVERRIDE; int handle(int) FL_OVERRIDE; public: ColorMenu(Fl_Color oldcol); Fl_Color run(); }; ColorMenu::ColorMenu(Fl_Color oldcol) : Fl_Window(BOXSIZE*8+1+2*BORDER, BOXSIZE*32+1+2*BORDER) { clear_border(); set_modal(); initial = which = oldcol; } void ColorMenu::drawbox(Fl_Color c) { if (c > 255) return; int X = (c%8)*BOXSIZE+BORDER; int Y = (c/8)*BOXSIZE+BORDER; #if BORDER_WIDTH < 3 if (c == which) fl_draw_box(FL_DOWN_BOX, X+1, Y+1, BOXSIZE-1, BOXSIZE-1, c); else fl_draw_box(FL_BORDER_BOX, X, Y, BOXSIZE+1, BOXSIZE+1, c); #else fl_draw_box(c == which ? FL_DOWN_BOX : FL_BORDER_BOX, X, Y, BOXSIZE+1, BOXSIZE+1, c); #endif } void ColorMenu::draw() { if (damage() != FL_DAMAGE_CHILD) { fl_draw_box(FL_UP_BOX,0,0,w(),h(),color()); for (int c = 0; c < 256; c++) drawbox((Fl_Color)c); } else { drawbox(previous); drawbox(which); } previous = which; } int ColorMenu::handle(int e) { Fl_Color c = which; switch (e) { case FL_PUSH: case FL_DRAG: { int X = (Fl::event_x_root() - x() - BORDER); if (X >= 0) X = X/BOXSIZE; int Y = (Fl::event_y_root() - y() - BORDER); if (Y >= 0) Y = Y/BOXSIZE; if (X >= 0 && X < 8 && Y >= 0 && Y < 32) c = 8*Y + X; else c = initial; } break; case FL_RELEASE: done = 1; return 1; case FL_KEYBOARD: switch (Fl::event_key()) { case FL_Up: if (c > 7) c -= 8; break; case FL_Down: if (c < 256-8) c += 8; break; case FL_Left: if (c > 0) c--; break; case FL_Right: if (c < 255) c++; break; case FL_Escape: which = initial; done = 1; return 1; case FL_KP_Enter: case FL_Enter: done = 1; return 1; default: return 0; } break; default: return 0; } if (c != which) { which = (Fl_Color)c; damage(FL_DAMAGE_CHILD); int bx = (c%8)*BOXSIZE+BORDER; int by = (c/8)*BOXSIZE+BORDER; int px = x(); int py = y(); int scr_x, scr_y, scr_w, scr_h; Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); if (px < scr_x) px = scr_x; if (px+bx+BOXSIZE+BORDER >= scr_x+scr_w) px = scr_x+scr_w-bx-BOXSIZE-BORDER; if (py < scr_y) py = scr_y; if (py+by+BOXSIZE+BORDER >= scr_y+scr_h) py = scr_y+scr_h-by-BOXSIZE-BORDER; if (px+bx < BORDER) px = BORDER-bx; if (py+by < BORDER) py = BORDER-by; position(px,py); } return 1; } extern char fl_override_redirect; // hack for menus #ifdef _MSC_VER #pragma optimize("a",off) // needed to get the done check to work #endif Fl_Color ColorMenu::run() { if (which > 255) { position(Fl::event_x_root()-w()/2, Fl::event_y_root()-y()/2); } else { position(Fl::event_x_root()-(initial%8)*BOXSIZE-BOXSIZE/2-BORDER, Fl::event_y_root()-(initial/8)*BOXSIZE-BOXSIZE/2-BORDER); } show(); Fl::grab(*this); done = 0; while (!done) Fl::wait(); Fl::grab(0); return which; } Fl_Color fl_show_colormap(Fl_Color oldcol) { ColorMenu m(oldcol); return m.run(); } fltk-1.4.3/src/fl_cursor_nwse.xpm0000644000175000017500000000141215004135251017152 0ustar albrechtalbrecht/* XPM */ static const char * const fl_cursor_nwse_xpm[] = { "15 15 28 1", " c None", ". c #FFFFFF", "+ c #000000", "@ c #767676", "# c #4E4E4E", "$ c #0C0C0C", "% c #494949", "& c #1B1B1B", "* c #4D4D4D", "= c #363636", "- c #646464", "; c #515151", "> c #242424", ", c #585858", "' c #545454", ") c #6A6A6A", "! c #797979", "~ c #444444", "{ c #2E2E2E", "] c #3B3B3B", "^ c #0A0A0A", "/ c #F7F7F7", "( c #595959", "_ c #6B6B6B", ": c #080808", "< c #FEFEFE", "[ c #FCFCFC", "} c #FDFDFD", ".......... ", ".++++++@. ", ".+++++#. ", ".++++$. ", ".+++++%. ", ".++&+++*. .", ".+=.-+++;. ..", ".>. .,+++'. .).", ".. .#+++,.!+.", ". .~+++{++.", " .]+++++.", " .^++++.", " /(+++++.", " /_::::::.", " <[[[[[[[[}"}; fltk-1.4.3/src/Fl_grab.cxx0000644000175000017500000000204615004135251015456 0ustar albrechtalbrecht// // Grab/release code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Screen_Driver.H" //////////////////////////////////////////////////////////////// // "Grab" is done while menu systems are up. This has several effects: // Events are all sent to the "grab window", which does not even // have to be displayed (and in the case of Fl_Menu.cxx it isn't). // The system is also told to "grab" events and send them to this app. // This also modifies how Fl_Window::show() works, on X it turns on // override_redirect, it does similar things on Windows. void Fl::grab(Fl_Window *win) { screen_driver()->grab(win); } fltk-1.4.3/src/Fl_Pack.cxx0000644000175000017500000001156115004135251015423 0ustar albrechtalbrecht// // Packing widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Based on code by Curtis Edwards // Group that compresses all its children together and resizes to surround // them on each redraw (only if box() is zero) // Bugs: ? #include #include #include /** Creates a new Fl_Pack widget using the given position, size, and label string. The default boxtype is FL_NO_BOX. The default type() is Fl_Pack::VERTICAL. The destructor also deletes all the children. This allows a whole tree to be deleted at once, without having to keep a pointer to all the children in the user code. A kludge has been done so the Fl_Pack and all of its children can be automatic (local) variables, but you must declare the Fl_Pack first, so that it is destroyed last. \param[in] X,Y X and Y coordinates (position) \param[in] W,H width and height, respectively \param[in] L label (optional) */ Fl_Pack::Fl_Pack(int X, int Y, int W, int H, const char *L) : Fl_Group(X, Y, W, H, L) { resizable(0); spacing_ = 0; // type(VERTICAL); // already set like this } void Fl_Pack::draw() { int tx = x()+Fl::box_dx(box()); int ty = y()+Fl::box_dy(box()); int tw = w()-Fl::box_dw(box()); int th = h()-Fl::box_dh(box()); int rw, rh; int current_position = horizontal() ? tx : ty; int maximum_position = current_position; uchar d = damage(); Fl_Widget*const* a = array(); if (horizontal()) { rw = -spacing_; rh = th; for (int i = children(); i--;) if (child(i)->visible()) { if (child(i) != this->resizable()) rw += child(i)->w(); rw += spacing_; } } else { rw = tw; rh = -spacing_; for (int i = children(); i--;) if (child(i)->visible()) { if (child(i) != this->resizable()) rh += child(i)->h(); rh += spacing_; } } for (int i = children(); i--;) { Fl_Widget* o = *a++; if (o->visible()) { int X,Y,W,H; if (horizontal()) { X = current_position; W = o->w(); Y = ty; H = th; } else { X = tx; W = tw; Y = current_position; H = o->h(); } // Last child, if resizable, takes all remaining room if(i == 0 && o == this->resizable()) { if(horizontal()) W = tw - rw; else H = th - rh; } if (spacing_ && current_position>maximum_position && box() && (X != o->x() || Y != o->y() || d&FL_DAMAGE_ALL)) { fl_color(color()); if (horizontal()) fl_rectf(maximum_position, ty, spacing_, th); else fl_rectf(tx, maximum_position, tw, spacing_); } if (X != o->x() || Y != o->y() || W != o->w() || H != o->h()) { o->resize(X,Y,W,H); // Clear all damage flags, but *set* FL_DAMAGE_ALL, even if the widget // may be clipped by the parent and needs no redraw. o->clear_damage(FL_DAMAGE_ALL); } if (d&FL_DAMAGE_ALL) { draw_child(*o); draw_outside_label(*o); } else { update_child(*o); } // Make sure that all damage flags are cleared. o->clear_damage(); // child's draw() can change it's size, so use new size: current_position += (horizontal() ? o->w() : o->h()); if (current_position > maximum_position) maximum_position = current_position; current_position += spacing_; } } if (horizontal()) { if (maximum_position < tx+tw && box()) { fl_color(color()); fl_rectf(maximum_position, ty, tx+tw-maximum_position, th); } tw = maximum_position-tx; } else { if (maximum_position < ty+th && box()) { fl_color(color()); fl_rectf(tx, maximum_position, tw, ty+th-maximum_position); } th = maximum_position-ty; } tw += Fl::box_dw(box()); if (tw <= 0) tw = 1; th += Fl::box_dh(box()); if (th <= 0) th = 1; if (tw != w() || th != h()) { Fl_Widget::resize(x(),y(),tw,th); Fl_Group *parent = this->parent(); if (parent) parent->init_sizes(); d = FL_DAMAGE_ALL; } if (d&FL_DAMAGE_ALL) { draw_box(); draw_label(); } } /** Override Fl_Group resize behavior. Resizing an Fl_Pack will not resize any of its children, but trigger a redraw, which in turn recalculates the dimensions of all children. \param[in] X, Y, W, H new position and size of the Fl_Pack widget */ void Fl_Pack::resize(int X, int Y, int W, int H) { Fl_Widget::resize(X, Y, W, H); redraw(); } fltk-1.4.3/src/filename_ext.cxx0000644000175000017500000000275415004135251016570 0ustar albrechtalbrecht// // Filename extension routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_System_Driver.H" #include /** Gets the extension of a filename. \code #include [..] const char *out; out = fl_filename_ext("/some/path/foo.txt"); // result: ".txt" out = fl_filename_ext("/some/path/foo"); // result: NULL \endcode \param[in] buf the filename to be parsed \return a pointer to the extension (including '.') if any or NULL otherwise */ const char *fl_filename_ext(const char *buf) { return Fl::system_driver()->filename_ext(buf); } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** Finds a filename extension. The default implementation assumes that the last `.` character separates the extension from the basename of a file. \see fl_filename_ext(const char*) */ const char *Fl_System_Driver::filename_ext(const char *buf) { const char *q = 0; const char *p = buf; for (p=buf; *p; p++) { if (*p == '/') q = 0; else if (*p == '.') q = p; } return q ? q : p; } /** \} \endcond */ fltk-1.4.3/src/Fl_Positioner.cxx0000644000175000017500000000750215004135251016700 0ustar albrechtalbrecht// // Positioner widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // The positioner widget from Forms, gives 2D input // Written by: Mark Overmars #include #include #include static double flinear(double val, double smin, double smax, double gmin, double gmax) { if (smin == smax) return gmax; else return gmin + (gmax - gmin) * (val - smin) / (smax - smin); } void Fl_Positioner::draw(int X, int Y, int W, int H) { int x1 = X + 4; int y1 = Y + 4; int w1 = W - 2 * 4; int h1 = H - 2 * 4; int xx = int(flinear(xvalue(), xmin, xmax, x1, x1+w1-1)+.5); int yy = int(flinear(yvalue(), ymin, ymax, y1, y1+h1-1)+.5); draw_box(box(), X, Y, W, H, color()); fl_color(selection_color()); fl_xyline(x1, yy, x1+w1); fl_yxline(xx, y1, y1+h1); } void Fl_Positioner::draw() { draw(x(), y(), w(), h()); draw_label(); } /** Returns the current position in x and y.*/ int Fl_Positioner::value(double X, double Y) { clear_changed(); if (X == xvalue_ && Y == yvalue_) return 0; xvalue_ = X; yvalue_ = Y; redraw(); return 1; } /** Sets the X axis coordinate.*/ int Fl_Positioner::xvalue(double X) { return(value(X, yvalue_)); } /** Sets the Y axis coordinate.*/ int Fl_Positioner::yvalue(double Y) { return(value(xvalue_, Y)); } int Fl_Positioner::handle(int event, int X, int Y, int W, int H) { switch (event) { case FL_PUSH: case FL_DRAG: case FL_RELEASE: { double x1 = X + 4; double y1 = Y + 4; double w1 = W - 2 * 4; double h1 = H - 2 * 4; double xx = flinear(Fl::event_x(), x1, x1+w1-1.0, xmin, xmax); if (xstep_) xx = int(xx/xstep_+0.5) * xstep_; if (xmin < xmax) { if (xx < xmin) xx = xmin; if (xx > xmax) xx = xmax; } else { if (xx > xmin) xx = xmin; if (xx < xmax) xx = xmax; } double yy = flinear(Fl::event_y(), y1, y1+h1-1.0, ymin, ymax); if (ystep_) yy = int(yy/ystep_+0.5) * ystep_; if (ymin < ymax) { if (yy < ymin) yy = ymin; if (yy > ymax) yy = ymax; } else { if (yy > ymin) yy = ymin; if (yy < ymax) yy = ymax; } if (xx != xvalue_ || yy != yvalue_) { xvalue_ = xx; yvalue_ = yy; set_changed(); redraw(); } } if (!(when() & FL_WHEN_CHANGED || (when() & FL_WHEN_RELEASE && event == FL_RELEASE))) return 1; if (changed() || when()&FL_WHEN_NOT_CHANGED) { Fl_Callback_Reason reason = changed() ? FL_REASON_CHANGED : FL_REASON_SELECTED; if (event == FL_RELEASE) { clear_changed(); reason = FL_REASON_RELEASED; } do_callback(reason); } return 1; default: return 0; } } int Fl_Positioner::handle(int e) { return handle(e, x(), y(), w(), h()); } /** Creates a new Fl_Positioner widget using the given position, size, and label string. The default boxtype is FL_NO_BOX. */ Fl_Positioner::Fl_Positioner(int X, int Y, int W, int H, const char* l) : Fl_Widget(X, Y, W, H, l) { box(FL_DOWN_BOX); selection_color(FL_RED); align(FL_ALIGN_BOTTOM); when(FL_WHEN_CHANGED); xmin = ymin = 0; xmax = ymax = 1; xvalue_ = yvalue_ = .5; xstep_ = ystep_ = 0; } /** Sets the X axis bounds.*/ void Fl_Positioner::xbounds(double a, double b) { if (a != xmin || b != xmax) { xmin = a; xmax = b; redraw(); } } /** Sets the Y axis bounds.*/ void Fl_Positioner::ybounds(double a, double b) { if (a != ymin || b != ymax) { ymin = a; ymax = b; redraw(); } } fltk-1.4.3/src/fl_shortcut.cxx0000644000175000017500000003466215004135251016467 0ustar albrechtalbrecht// // Shortcut support routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Code to test and parse fltk shortcut numbers. // // A shortcut is a keysym or'd with shift flags. In the simplest // sense a shortcut is matched if the shift state is exactly as // given and the key returning that keysym is pressed. // // To make it easier to match some things it is more complex: // // Only FL_META, FL_ALT, FL_SHIFT, and FL_CTRL must be "off". A // zero in the other shift flags indicates "don't care". // // It also checks against the first character of Fl::event_text(), // and zero for FL_SHIFT means "don't care". // This allows punctuation shortcuts like "#" to work (rather than // calling it "shift+3" on a US keyboard) #include #include #include #include #include "Fl_System_Driver.H" #include "Fl_Screen_Driver.H" #include #include #include #include "flstring.h" /** Tests the current event, which must be an FL_KEYBOARD or FL_SHORTCUT, against a shortcut value (described in Fl_Button). Not to be confused with Fl_Widget::test_shortcut(). \return non-zero if there is a match. */ int Fl::test_shortcut(unsigned int shortcut) { if (!shortcut) return 0; unsigned int v = shortcut & FL_KEY_MASK; if (((unsigned)fl_tolower(v))!=v) { shortcut |= FL_SHIFT; } int shift = Fl::event_state(); // see if any required shift flags are off: if ((shortcut&shift) != (shortcut&0x7fff0000)) return 0; // record shift flags that are wrong: int mismatch = (shortcut^shift)&0x7fff0000; // these three must always be correct: if (mismatch&(FL_META|FL_ALT|FL_CTRL)) return 0; unsigned int key = shortcut & FL_KEY_MASK; // if shift is also correct, check for exactly equal keysyms: if (!(mismatch&(FL_SHIFT)) && key == (unsigned)Fl::event_key()) return 1; // try matching utf8, ignore shift: unsigned int firstChar = fl_utf8decode(Fl::event_text(), Fl::event_text()+Fl::event_length(), 0); if ( ! (FL_CAPS_LOCK&shift) && key==firstChar) return 1; // kludge so that Ctrl+'_' works (as opposed to Ctrl+'^_'): if ((shift&FL_CTRL) && key >= 0x3f && key <= 0x5F && firstChar==(key^0x40)) return 1; // firstChar should be within a-z return 0; } /** Get a human-readable string from a shortcut value. Unparse a shortcut value as used by Fl_Button or Fl_Menu_Item into a human-readable string like "Alt+N". This only works if the shortcut is a character key or a numbered function key. If the shortcut is zero then an empty string is returned. The return value points at a static buffer that is overwritten with each call. \since FLTK 1.3.4 modifier key names can be localized, but key names can not yet be localized. This may be added to a future FLTK version. Modifier key names (human-readable shortcut names) can be defined with the following global const char * pointer variables: - fl_local_ctrl => name of FL_CTRL - fl_local_alt => name of FL_ALT - fl_local_shift => name of FL_SHIFT - fl_local_meta => name of FL_META \code fl_local_ctrl = "Strg"; // German for "Ctrl" fl_local_shift = "Umschalt"; // German for "Shift" \endcode \note Due to \b random static initialization order this should always be done from code in main() or called by main() as opposed to static initialization since the default strings in the FLTK library are set by static initializers. Otherwise this \b might result in the wrong order so FLTK's internal initialization overwrites your strings. The shortcut name will be constructed by adding all modifier names in the order defined above plus the name of the key. A '+' character is added to each modifier name unless it has a trailing '\' or a trailing '+'. Example: Ctrl+Alt+Shift+Meta+F12 The default values for modifier key names are as given above for all platforms except macOS. macOS uses graphical characters that represent the typical macOS modifier names in menus, e.g. cloverleaf, saucepan, etc. You may, however, redefine macOS modifier names as well. \param [in] shortcut the integer value containing the ASCII character or extended keystroke plus modifiers \return a pointer to a static buffer containing human readable text for the shortcut */ const char* fl_shortcut_label(unsigned int shortcut) { return fl_shortcut_label(shortcut, 0L); } /* This static function adds a modifier key name to a character buffer and returns the pointer behind the modifier name and a trailing '+' character. Exceptions: (1) Last character = '\' : remove it, done (don't add '+') (2) Last character = '+' : user added '+', don't add another one In case of buffer overflow the modifier key name is replaced with "..." if that fits or not added at all. This should rarely (never) happen. */ static char *add_modifier_key(char *p, const char *end, const char *name) { size_t ln = strlen(name); if (p+ln > end) { // string too long if (p+4 <= end) { // can replace with "..." ? strcpy(p,"..."); p += 3; } else return p; } else { strcpy(p,name); p += ln; } if (p[-1] == '\\') // remove (last) '\' character p--; else if (p[-1] == '+') // don't add another '+' character {/*empty*/} else // not a '\' or '+' *p++ = '+'; // add a '+' character return p; } /** Get a human-readable string from a shortcut value. \param [in] shortcut the integer value containing the ASCII character or extended keystroke plus modifiers \param [in] eom if this pointer is set, it will receive a pointer to the end of the modifier text \return a pointer to a static buffer containing human readable text for the shortcut \see fl_shortcut_label(unsigned int shortcut) */ const char* fl_shortcut_label(unsigned int shortcut, const char **eom) { static char buf[80]; char *p = buf; char *end = &buf[sizeof(buf)-20]; // account for key name (max. ~10 + x) if (eom) *eom = p; if (!shortcut) {*p = 0; return buf;} // fix upper case shortcuts unsigned int key = shortcut & FL_KEY_MASK; if (((unsigned)fl_tolower(key)) != key) { shortcut |= FL_SHIFT; } // Add modifier key names. // Note: if necessary we could change the order here depending on the platform. // However, as discussed in fltk.coredev, the order appears to be the // same on all platforms, with exceptions in _some_ Linux applications. if (shortcut & FL_CTRL) {p = add_modifier_key(p, end, fl_local_ctrl);} if (shortcut & FL_ALT) {p = add_modifier_key(p, end, fl_local_alt);} if (shortcut & FL_SHIFT) {p = add_modifier_key(p, end, fl_local_shift);} if (shortcut & FL_META) {p = add_modifier_key(p, end, fl_local_meta);} if (eom) *eom = p; // add key name return Fl::screen_driver()->shortcut_add_key_name(key, p, buf, eom); } /** Emulation of XForms named shortcuts. Converts ASCII shortcut specifications (eg. "^c") into the FLTK integer equivalent (eg. FL_CTRL+'c') These ASCII characters are used to specify the various keyboard modifier keys: \verbatim # - Alt + - Shift ^ - Control ! - Meta @ - Command (Ctrl on linux/win, Meta on OSX) \endverbatim These special characters can be combined to form chords of modifier keys. (See 'Remarks' below) After the optional modifier key prefixes listed above, one can either specify a single keyboard character to use as the shortcut, or a numeric sequence in hex, decimal or octal. Examples: \verbatim "c" -- Uses 'c' as the shortcut "#^c" -- Same as FL_ALT|FL_CTRL|'c' "#^!c" -- Same as FL_ALT|FL_CTRL|FL_META|'c' "@c" -- Same as FL_COMMAND|'c' (see FL_COMMAND for platform specific behavior) "0x63" -- Same as "c" (hex 63=='c') "99" -- Same as "c" (dec 99=='c') "0143" -- Same as "c" (octal 0143=='c') "^0x63" -- Same as (FL_CTRL|'c'), or (FL_CTRL|0x63) "^99" -- Same as (FL_CTRL|'c'), or (FL_CTRL|99) "^0143" -- Same as (FL_CTRL|'c'), or (FL_CTRL|0143) \endverbatim \remarks Due to XForms legacy, there are some odd things to consider when using the modifier characters. \remarks (1) You can use the special modifier keys for chords *only* if the modifiers are provided in this order: #, +, ^, !, \@. Other ordering can yield undefined results. \remarks So for instance, Ctrl-Alt-c must be specified as "#^c" (and not "^#c"), due to the above ordering rule. \remarks (2) If you want to make a shortcut that uses one of the special modifier characters (as the character being modified), then to avoid confusion, specify the numeric equivalent, e.g. \remarks \verbatim If you want.. Then use.. ----------------------------- ------------------------------ '#' as the shortcut.. "0x23" (instead of just "#"). '+' as the shortcut.. "0x2b" (instead of just "+"). '^' as the shortcut.. "0x5e" (instead of just "^"). Alt-+ as the shortcut.. "#0x2b" (instead of "#+"). Alt-^ as the shortcut.. "#0x5e" (instead of "#^"). ..etc.. \endverbatim \remarks As a general rule that's easy to remember, unless the shortcut key to be modified is a single alpha-numeric character [A-Z,a-z,0-9), it's probably best to use the numeric equivalents. \remarks Don't fix these silly legacy issues in a future release. Nobody is using this anymore. */ unsigned int fl_old_shortcut(const char* s) { if (!s || !*s) return 0; if (s[1]==0 && strchr("@!",s[0])) return (unsigned int)s[0]; // maintain legacy behavior for "!" and "@" unsigned int n = 0; if (*s == '#') {n |= FL_ALT; s++;} if (*s == '+') {n |= FL_SHIFT; s++;} if (*s == '^') {n |= FL_CTRL; s++;} if (*s == '!') {n |= FL_META; s++;} // added in 1.3.3 if (*s == '@') {n |= FL_COMMAND; s++;} // added in 1.3.3 if (*s && s[1]) return n | (int)strtol(s,0,0); // allow 0xf00 to get any key return n | *s; } // Tests for &x shortcuts in button labels: /** Returns the Unicode value of the '&x' shortcut in a given text. The given text \p t (usually a widget's label or a menu text) is searched for a '&x' shortcut label, and if found, the Unicode value (code point) of the '&x' shortcut is returned. \param t text or label to search for '&x' shortcut. \return Unicode (UCS-4) value of shortcut in \p t or 0. \note Internal use only. */ unsigned int Fl_Widget::label_shortcut(const char *t) { if (!t) return 0; for (;;) { if (*t==0) return 0; if (*t=='&') { unsigned int s = fl_utf8decode(t+1, 0, 0); if (s==0) return 0; else if (s==(unsigned int)'&') t++; else return s; } t++; } } /** Returns true if the given text \p t contains the entered '&x' shortcut. This method must only be called in handle() methods or callbacks after a keypress event (usually FL_KEYDOWN or FL_SHORTCUT). The given text \p t (usually a widget's label or menu text) is searched for a '&x' shortcut, and if found, this is compared with the entered key value. Fl::event_text() is used to get the entered key value. Fl::event_state() is used to get the Alt modifier, if \p require_alt is true. \param t text or label to search for '&x' shortcut. \param require_alt if true: match only if Alt key is pressed. \return true, if the entered text matches the '&x' shortcut in \p t false (0) otherwise. \note Useful when a widget's handle(int) method needs dedicated processing of FL_SHORTCUT. */ int Fl_Widget::test_shortcut(const char *t, const bool require_alt) { static int extra_test = Fl::system_driver()->need_test_shortcut_extra(); if (!t) return 0; // for menubars etc. shortcuts must work only if the Alt modifier is pressed if (require_alt && Fl::event_state(FL_ALT)==0) return 0; unsigned int c = fl_utf8decode(Fl::event_text(), Fl::event_text()+Fl::event_length(), 0); // this line makes underline shortcuts work the same way they do on Windows // and Linux. if (extra_test && c && Fl::event_state(FL_ALT)) c = Fl::event_key(); if (!c) return 0; unsigned int ls = label_shortcut(t); if (c == ls) return 1; // On macOS, we need to simulate the upper case keystroke as well if (extra_test && Fl::event_state(FL_ALT) && c<128 && isalpha(c) && (unsigned)toupper(c)==ls) return 1; return 0; } /** Returns true if the widget's label contains the entered '&x' shortcut. This method must only be called in handle() methods or callbacks after a keypress event (usually FL_KEYDOWN or FL_SHORTCUT). The widget's label is searched for a '&x' shortcut, and if found, this is compared with the entered key value. Fl::event_text() is used to get the entered key value. \return true, if the entered text matches the widget's'&x' shortcut, false (0) otherwise. \note Useful when a widget's handle(int) method needs dedicated processing of FL_SHORTCUT. */ int Fl_Widget::test_shortcut() { if (!(flags()&SHORTCUT_LABEL)) return 0; return test_shortcut(label()); } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ const char *Fl_Screen_Driver::shortcut_add_key_name(unsigned key, char *p, char *buf, const char **eom) { if (key >= FL_F && key <= FL_F_Last) { *p++ = 'F'; if (key > FL_F+9) *p++ = (char)((key-FL_F)/10+'0'); *p++ = (char)((key-FL_F)%10 + '0'); } else { // binary search the table for a match: int a = 0; int b = key_table_size; while (a < b) { int c = (a+b)/2; if (key_table[c].key == key) { if (p > buf) { strcpy(p, key_table[c].name); return buf; } else { const char *sp = key_table[c].name; if (eom) *eom = sp; return sp; } } if (key_table[c].key < key) a = c+1; else b = c; } if (key >= FL_KP && key <= FL_KP_Last) { // mark keypad keys with KP_ prefix strcpy(p,"KP_"); p += 3; *p++ = uchar(key & 127); } else { // if none found, use the keystroke as a match: p += fl_utf8encode(fl_toupper(key), p); } } *p = 0; return buf; } /** \} \endcond */ fltk-1.4.3/src/fl_utf8.cxx0000644000175000017500000013027615004135251015500 0ustar albrechtalbrecht// // Unicode to UTF-8 conversion functions. // // Author: Jean-Marc Lienher ( http://oksid.ch ) // Copyright 2000-2010 by O'ksi'D. // Copyright 2016-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_System_Driver.H" #include #include #include #include "utf8_internal.h" #include #include #include #undef fl_open /** \addtogroup fl_unicode @{ */ // *** NOTE : All functions are LIMITED to 24 bits Unicode values !!! *** // *** But only 16 bits are really used under Linux and win32 *** #define NBC 0xFFFF + 1 static int Toupper(int ucs) { int i; static unsigned short *table = NULL; if (!table) { table = (unsigned short*) malloc( sizeof(unsigned short) * (NBC)); for (i = 0; i < NBC; i++) { table[i] = (unsigned short) i; } for (i = 0; i < NBC; i++) { int l; l = XUtf8Tolower(i); if (l != i) table[l] = (unsigned short) i; } } if (ucs >= NBC || ucs < 0) return ucs; return table[ucs]; } /** Returns the byte length of the UTF-8 sequence with first byte \p c, or -1 if \p c is not valid. This function is helpful for finding faulty UTF-8 sequences. \see fl_utf8len1 */ int fl_utf8len(char c) { if (!(c & 0x80)) return 1; if (c & 0x40) { if (c & 0x20) { if (c & 0x10) { if (c & 0x08) { if (c & 0x04) { return 6; } return 5; } return 4; } return 3; } return 2; } return -1; } // fl_utf8len /** Returns the byte length of the UTF-8 sequence with first byte \p c, or 1 if \p c is not valid. This function can be used to scan faulty UTF-8 sequences, albeit ignoring invalid codes. \see fl_utf8len */ int fl_utf8len1(char c) { if (!(c & 0x80)) return 1; if (c & 0x40) { if (c & 0x20) { if (c & 0x10) { if (c & 0x08) { if (c & 0x04) { return 6; } return 5; } return 4; } return 3; } return 2; } return 1; } // fl_utf8len1 /** Return the length in bytes of a UTF-8 string. \param[in] text encoded in UTF-8 \param[in] len number of Unicode characters, -1 to test until the end of text \return number of bytes that make up the Unicode string \see fl_utf_nb_char(const unsigned char *buf, int len) */ int fl_utf8strlen(const char *text, int len) { if (len == -1) return (int)strlen(text); int i, n = 0; for (i=len; i>0; i--) { if (*text == 0) return n; // end of string int nc = fl_utf8len1(*text); n += nc; text += nc; } return n; } /** Returns the number of Unicode chars in the UTF-8 string. \see fl_utf8strlen(const char *text, int len) */ int fl_utf_nb_char( const unsigned char *buf, int len) { int i = 0; int nbc = 0; while (i < len) { int cl = fl_utf8len((buf+i)[0]); if (cl < 1) cl = 1; nbc++; i += cl; } return nbc; } /** UTF-8 aware strncasecmp - converts to lower case Unicode and tests. \param s1, s2 the UTF-8 strings to compare \param n the maximum number of UTF-8 characters to compare \return result of comparison \retval 0 if the strings are equal \retval >0 if s1 is greater than s2 \retval <0 if s1 is less than s2 */ int fl_utf_strncasecmp(const char *s1, const char *s2, int n) { int i; for (i = 0; i < n; i++) { int l1, l2; unsigned int u1, u2; if (*s1==0 && *s2==0) return 0; // all compared equal, return 0 u1 = fl_utf8decode(s1, 0, &l1); u2 = fl_utf8decode(s2, 0, &l2); int res = XUtf8Tolower(u1) - XUtf8Tolower(u2); if (res) return res; s1 += l1; s2 += l2; } return 0; } /** UTF-8 aware strcasecmp - converts to Unicode and tests. \return result of comparison \retval 0 if the strings are equal \retval 1 if s1 is greater than s2 \retval -1 if s1 is less than s2 */ int fl_utf_strcasecmp(const char *s1, const char *s2) { return fl_utf_strncasecmp(s1, s2, 0x7fffffff); } /** Returns the Unicode lower case value of \p ucs. */ int fl_tolower(unsigned int ucs) { return XUtf8Tolower(ucs); } /** Returns the Unicode upper case value of \p ucs. */ int fl_toupper(unsigned int ucs) { return Toupper(ucs); } /** Converts the string \p str to its lower case equivalent into buf. Warning: to be safe buf length must be at least 3 * len [for 16-bit Unicode] */ int fl_utf_tolower(const unsigned char *str, int len, char *buf) { int i; int l = 0; char *end = (char *)&str[len]; for (i = 0; i < len;) { int l1, l2; unsigned int u1; u1 = fl_utf8decode((const char*)(str + i), end, &l1); l2 = fl_utf8encode((unsigned int) XUtf8Tolower(u1), buf + l); if (l1 < 1) { i += 1; } else { i += l1; } if (l2 < 1) { l += 1; } else { l += l2; } } return l; } /** Converts the string \p str to its upper case equivalent into buf. Warning: to be safe buf length must be at least 3 * len [for 16-bit Unicode] */ int fl_utf_toupper(const unsigned char *str, int len, char *buf) { int i; int l = 0; char *end = (char *)&str[len]; for (i = 0; i < len;) { int l1, l2; unsigned int u1; u1 = fl_utf8decode((const char*)(str + i), end, &l1); l2 = fl_utf8encode((unsigned int) Toupper(u1), buf + l); if (l1 < 1) { i += 1; } else { i += l1; } if (l2 < 1) { l += 1; } else { l += l2; } } return l; } /** Returns true if the Unicode character \p ucs is non-spacing. Non-spacing characters in Unicode are typically combining marks like tilde (~), diaeresis (¨), or other marks that are added to a base character, for instance 'a' (base character) + '¨' (combining mark) = 'ä' (German Umlaut). - http://unicode.org/glossary/#base_character - http://unicode.org/glossary/#nonspacing_mark - http://unicode.org/glossary/#combining_character */ unsigned int fl_nonspacing(unsigned int ucs) { return (unsigned int) XUtf8IsNonSpacing(ucs); } /** Converts UTF-8 string \p s to a local multi-byte character string. */ char * fl_utf2mbcs(const char *s) { return Fl::system_driver()->utf2mbcs(s); } /** Cross-platform function to get environment variables with a UTF-8 encoded name or value. This function is especially useful on the Windows platform where non-ASCII environment variables are encoded as wide characters. The returned value of the variable is encoded in UTF-8 as well. On platforms other than Windows this function calls getenv directly. The return value is returned as-is. The return value is a pointer to an implementation defined buffer: - an internal buffer that is (re)allocated as needed (Windows) or - the string in the environment itself (Unix, Linux, MaOS) or - any other implementation (other platforms). This string must be considered read-only and must not be freed by the caller. If the resultant string is to be used later it must be copied to a safe place. The next call to fl_getenv() or any other environment changes may overwrite the string. \note This function is not thread-safe. \param[in] v the UTF-8 encoded environment variable \return the environment variable in UTF-8 encoding, or NULL in case of error. */ char *fl_getenv(const char* v) { return Fl::system_driver()->getenv(v); } /** Cross-platform function to write environment variables with a UTF-8 encoded name or value. This function is especially useful on the Windows platform where non-ASCII environment variables are encoded as wide characters. The given argument \p var must be encoded in UTF-8 in the form "name=value". The \p 'name' part must conform to platform dependent restrictions on environment variable names. The string given in \p var is copied and optionally converted to the required encoding for the platform. On platforms other than Windows this function calls putenv directly. The return value is zero on success and non-zero in case of error. The value in case of error is platform specific and returned as-is. \note The copied string is allocated on the heap and "lost" on some platforms, i.e. calling fl_putenv() to change environment variables frequently may cause memory leaks. There may be an option to avoid this in a future implementation. \note This function is not thread-safe. \param[in] var the UTF-8 encoded environment variable \p 'name=value' \return 0 on success, non-zero in case of error. */ int fl_putenv(const char* var) { return Fl::system_driver()->putenv(var); } /** Cross-platform function to open files with a UTF-8 encoded name. This function is especially useful on the Windows platform where the standard open() function fails with UTF-8 encoded non-ASCII filenames. \param[in] fname the UTF-8 encoded filename \param[in] oflags other arguments are as in the standard open() function \return a file descriptor upon successful completion, or -1 in case of error. \see fl_fopen(), fl_open_ext(), fl_close_fd(int fd). */ int fl_open(const char* fname, int oflags, ...) { int pmode; va_list ap; va_start(ap, oflags); pmode = va_arg (ap, int); va_end(ap); return Fl::system_driver()->open(fname, oflags, pmode); } /** Cross-platform function to close a file descriptor. \return 0 in case of success, or -1 in case of error. */ int fl_close_fd(int fd) { return Fl::system_driver()->close_fd(fd); } /** Cross-platform function to open files with a UTF-8 encoded name. In comparison with fl_open(), this function allows to control whether the file is opened in binary (a.k.a. untranslated) mode. This is especially useful on the Windows platform where files are by default opened in text (translated) mode. \param[in] fname the UTF-8 encoded filename \param[in] binary if non-zero, the file is to be accessed in binary (a.k.a. untranslated) mode. \param[in] oflags,... these arguments are as in the standard open() function. Setting \p oflags to zero opens the file for reading. \return a file descriptor upon successful completion, or -1 in case of error. */ int fl_open_ext(const char* fname, int binary, int oflags, ...) { int pmode; va_list ap; va_start(ap, oflags); pmode = va_arg (ap, int); va_end(ap); return Fl::system_driver()->open_ext(fname, binary, oflags, pmode); } /** Cross-platform function to open files with a UTF-8 encoded name. This function is especially useful on the Windows platform where the standard fopen() function fails with UTF-8 encoded non-ASCII filenames. \param f the UTF-8 encoded filename \param mode same as the second argument of the standard fopen() function \return a FILE pointer upon successful completion, or NULL in case of error. \sa fl_open(). */ FILE *fl_fopen(const char* f, const char *mode) { return Fl::system_driver()->fopen(f, mode); } /** Cross-platform function to run a system command with a UTF-8 encoded string. This function is especially useful on the Windows platform where non-ASCII program (file) names must be encoded as wide characters. On platforms other than Windows this function calls system() directly. \param[in] cmd the UTF-8 encoded command string \return the return value of _wsystem() on Windows or system() on other platforms. */ int fl_system(const char* cmd) { return Fl::system_driver()->system(cmd); } int fl_execvp(const char *file, char *const *argv) { return Fl::system_driver()->execvp(file, argv); } /** Cross-platform function to set a files mode() with a UTF-8 encoded name or value. This function is especially useful on the Windows platform where the standard chmod() function fails with UTF-8 encoded non-ASCII filenames. \param[in] f the UTF-8 encoded filename \param[in] mode the mode to set \return the return value of _wchmod() on Windows or chmod() on other platforms. */ int fl_chmod(const char* f, int mode) { return Fl::system_driver()->chmod(f, mode); } /** Cross-platform function to test a files access() with a UTF-8 encoded name or value. This function is especially useful on the Windows platform where the standard access() function fails with UTF-8 encoded non-ASCII filenames. Windows defines the mode values 0 for existence, 2 for writable, 4 for readable, and 6 of readable and writable. On other systems, the modes `X_OK`, `W_OK`, and `R_OK` are usually defined as 1, 2, and 4. Upon successful completion, the value 0 is returned on all platforms. \param[in] f the UTF-8 encoded filename \param[in] mode the mode to test \return the return value of _waccess() on Windows or access() on other platforms. */ int fl_access(const char* f, int mode) { return Fl::system_driver()->access(f, mode); } /** Cross-platform function to stat() a file using a UTF-8 encoded name or value. This function is especially useful on the Windows platform where the standard stat() function fails with UTF-8 encoded non-ASCII filenames. \param[in] f the UTF-8 encoded filename \param b the stat struct to populate \return the return value of _wstat() on Windows or stat() on other platforms. */ int fl_stat(const char* f, struct stat *b) { return Fl::system_driver()->flstat(f, b); } /** Cross-platform function to change the current working directory, given as a UTF-8 encoded string. This function is especially useful on the Windows platform where the standard _wchdir() function needs a \p path in UTF-16 encoding. The \p path is converted to a system specific encoding if necessary and the system specific \p chdir(converted_path) function is called. The function returns 0 on success and -1 on error. Depending on the platform, \p errno \b may be set if an error occurs. \note The possible errno values are platform specific. Refer to the documentation of the platform specific chdir() function. If the function is not implemented on a particular platform the default implementation returns -1 and \p errno is \b not set. If the \p path is \p NULL the function returns -1, but \p errno is \b not changed. This is a convenience feature of fl_chdir() as opposed to chdir(). \param[in] path the target directory for chdir (may be \p NULL) \return 0 if successful, -1 on error (errno may be set) */ int fl_chdir(const char* path) { if (!path) return -1; return Fl::system_driver()->chdir(path); } /** Cross-platform function to get the current working directory as a UTF-8 encoded value. This function is especially useful on the Windows platform where the standard _wgetcwd() function returns UTF-16 encoded non-ASCII filenames. If \p buf is \p NULL a buffer of size \p (len+1) is allocated, filled with the current working directory, and returned. In this case the buffer must be released by the caller with free() to prevent memory leaks. \param[in] buf the buffer to populate (may be NULL) \param[in] len the length of the buffer \return the CWD encoded as UTF-8 */ char *fl_getcwd(char *buf, int len) { if (buf == NULL) { buf = (char*)malloc(len + 1); } return Fl::system_driver()->getcwd(buf, len); } /** Cross-platform function to unlink() (that is, delete) a file using a UTF-8 encoded filename. This function is especially useful on the Windows platform where the standard function expects UTF-16 encoded non-ASCII filenames. \param fname the filename to unlink \return the return value of _wunlink() on Windows or unlink() on other platforms. */ int fl_unlink(const char* fname) { return Fl::system_driver()->unlink(fname); } /** Cross-platform function to create a directory with a UTF-8 encoded name. This function is especially useful on the Windows platform where the standard _wmkdir() function expects UTF-16 encoded non-ASCII filenames. \param[in] f the UTF-8 encoded filename \param[in] mode the mode of the directory \return the return value of _wmkdir() on Windows or mkdir() on other platforms. */ int fl_mkdir(const char* f, int mode) { return Fl::system_driver()->mkdir(f, mode); } /** Cross-platform function to remove a directory with a UTF-8 encoded name. This function is especially useful on the Windows platform where the standard _wrmdir() function expects UTF-16 encoded non-ASCII filenames. \param[in] f the UTF-8 encoded filename to remove \return the return value of _wrmdir() on Windows or rmdir() on other platforms. */ int fl_rmdir(const char* f) { return Fl::system_driver()->rmdir(f); } /** Cross-platform function to rename a filesystem object using UTF-8 encoded names. This function is especially useful on the Windows platform where the standard _wrename() function expects UTF-16 encoded non-ASCII filenames. \param[in] f the UTF-8 encoded filename to change \param[in] n the new UTF-8 encoded filename to set \return the return value of _wrename() on Windows or rename() on other platforms. */ int fl_rename(const char* f, const char *n) { return Fl::system_driver()->rename(f, n); } /** Cross-platform function to recursively create a path in the file system. This function creates a \p path in the file system by recursively creating all directories. \param[in] path a Unix style ('/' forward slashes) absolute or relative pathname \return 1 if the path was created, 0 if creating the path failed at some point */ char fl_make_path( const char *path ) { if (fl_access(path, 0)) { const char *s = strrchr( path, '/' ); if ( !s ) return 0; size_t len = (size_t) (s-path); char *p = (char*)malloc( len+1 ); memcpy( p, path, len ); p[len] = 0; fl_make_path( p ); free( p ); fl_mkdir(path, 0700); } return 1; } /** Cross-platform function to create a path for the file in the file system. This function strips the filename from the given \p path and creates a path in the file system by recursively creating all directories. */ void fl_make_path_for_file( const char *path ) { const char *s = strrchr( path, '/' ); if ( !s ) return; size_t len = (s-path); char *p = (char*)malloc( len+1 ); memcpy( p, path, len ); p[len] = 0; fl_make_path( p ); free( p ); } // fl_make_path_for_file() /** Set to 1 to turn bad UTF-8 bytes into ISO-8859-1. If this is zero they are instead turned into the Unicode REPLACEMENT CHARACTER, of value 0xfffd. If this is on fl_utf8decode() will correctly map most (perhaps all) human-readable text that is in ISO-8859-1. This may allow you to completely ignore character sets in your code because virtually everything is either ISO-8859-1 or UTF-8. */ #ifndef ERRORS_TO_ISO8859_1 # define ERRORS_TO_ISO8859_1 1 #endif /** Set to 1 to turn bad UTF-8 bytes in the 0x80-0x9f range into the Unicode index for Microsoft's CP1252 character set. You should also set ERRORS_TO_ISO8859_1. With this a huge amount of more available text (such as all web pages) are correctly converted to Unicode. */ #ifndef ERRORS_TO_CP1252 # define ERRORS_TO_CP1252 1 #endif /** A number of Unicode code points are in fact illegal and should not be produced by a UTF-8 converter. Turn this on will replace the bytes in those encodings with errors. If you do this then converting arbitrary 16-bit data to UTF-8 and then back is not an identity, which will probably break a lot of software. */ #ifndef STRICT_RFC3629 # define STRICT_RFC3629 0 #endif #if ERRORS_TO_CP1252 /* Codes 0x80..0x9f from the Microsoft CP1252 character set, translated to Unicode: */ static unsigned short cp1252[32] = { 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f, 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178 }; #endif /** Decode a single UTF-8 encoded character starting at \e p. The resulting Unicode value (in the range 0-0x10ffff) is returned, and \e len is set to the number of bytes in the UTF-8 encoding (adding \e len to \e p will point at the next character). If \p p points at an illegal UTF-8 encoding, including one that would go past \e end, or where a code uses more bytes than necessary, then *(unsigned char*)p is translated as though it is in the Microsoft CP1252 character set and \e len is set to 1. Treating errors this way allows this to decode almost any ISO-8859-1 or CP1252 text that has been mistakenly placed where UTF-8 is expected, and has proven very useful. If you want errors to be converted to error characters (as the standards recommend), adding a test to see if the length is unexpectedly 1 will work: \code if (*p & 0x80) { // what should be a multibyte encoding code = fl_utf8decode(p,end,&len); if (len<2) code = 0xFFFD; // Turn errors into REPLACEMENT CHARACTER } else { // handle the 1-byte UTF-8 encoding: code = *p; len = 1; } \endcode Direct testing for the 1-byte case (as shown above) will also speed up the scanning of strings where the majority of characters are ASCII. */ unsigned fl_utf8decode(const char* p, const char* end, int* len) { unsigned char c = *(const unsigned char*)p; if (c < 0x80) { if (len) *len = 1; return c; #if ERRORS_TO_CP1252 } else if (c < 0xa0) { if (len) *len = 1; return cp1252[c-0x80]; #endif } else if (c < 0xc2) { goto FAIL; } if ( (end && p+1 >= end) || (p[1]&0xc0) != 0x80) goto FAIL; if (c < 0xe0) { if (len) *len = 2; return ((p[0] & 0x1f) << 6) + ((p[1] & 0x3f)); } else if (c == 0xe0) { if (((const unsigned char*)p)[1] < 0xa0) goto FAIL; goto UTF8_3; #if STRICT_RFC3629 } else if (c == 0xed) { /* RFC 3629 says surrogate chars are illegal. */ if (((const unsigned char*)p)[1] >= 0xa0) goto FAIL; goto UTF8_3; } else if (c == 0xef) { /* 0xfffe and 0xffff are also illegal characters */ if (((const unsigned char*)p)[1]==0xbf && ((const unsigned char*)p)[2]>=0xbe) goto FAIL; goto UTF8_3; #endif } else if (c < 0xf0) { UTF8_3: if ( (end && p+2 >= end) || (p[2]&0xc0) != 0x80) goto FAIL; if (len) *len = 3; return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + ((p[2] & 0x3f)); } else if (c == 0xf0) { if (((const unsigned char*)p)[1] < 0x90) goto FAIL; goto UTF8_4; } else if (c < 0xf4) { UTF8_4: if ( (end && p+3 >= end) || (p[2]&0xc0) != 0x80 || (p[3]&0xc0) != 0x80) goto FAIL; if (len) *len = 4; #if STRICT_RFC3629 /* RFC 3629 says all codes ending in fffe or ffff are illegal: */ if ((p[1]&0xf)==0xf && ((const unsigned char*)p)[2] == 0xbf && ((const unsigned char*)p)[3] >= 0xbe) goto FAIL; #endif return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12) + ((p[2] & 0x3f) << 6) + ((p[3] & 0x3f)); } else if (c == 0xf4) { if (((const unsigned char*)p)[1] > 0x8f) goto FAIL; /* after 0x10ffff */ goto UTF8_4; } else { FAIL: if (len) *len = 1; #if ERRORS_TO_ISO8859_1 return c; #else return 0xfffd; /* Unicode REPLACEMENT CHARACTER */ #endif } } /** Move \p p forward until it points to the start of a UTF-8 character. If it already points at the start of one then it is returned unchanged. Any UTF-8 errors are treated as though each byte of the error is an individual character. \e start is the start of the string and is used to limit the backwards search for the start of a UTF-8 character. \e end is the end of the string and is assumed to be a break between characters. It is assumed to be greater than p. This function is for moving a pointer that was jumped to the middle of a string, such as when doing a binary search for a position. You should use either this or fl_utf8back() depending on which direction your algorithm can handle the pointer moving. Do not use this to scan strings, use fl_utf8decode() instead. */ const char* fl_utf8fwd(const char* p, const char* start, const char* end) { const char* a; int len; /* if we are not pointing at a continuation character, we are done: */ if ((*p&0xc0) != 0x80) return p; /* search backwards for a 0xc0 starting the character: */ for (a = p-1; ; --a) { if (a < start) return p; if (!(a[0]&0x80)) return p; if ((a[0]&0x40)) break; } fl_utf8decode(a,end,&len); a += len; if (a > p) return a; return p; } /** Move \p p backward until it points to the start of a UTF-8 character. If it already points at the start of one then it is returned unchanged. Any UTF-8 errors are treated as though each byte of the error is an individual character. \e start is the start of the string and is used to limit the backwards search for the start of a UTF-8 character. \e end is the end of the string and is assumed to be a break between characters. It is assumed to be greater than p. If you wish to decrement a UTF-8 pointer, pass p-1 to this. */ const char* fl_utf8back(const char* p, const char* start, const char* end) { const char* a; int len; /* if we are not pointing at a continuation character, we are done: */ if ((*p&0xc0) != 0x80) return p; /* search backwards for a 0xc0 starting the character: */ for (a = p-1; ; --a) { if (a < start) return p; if (!(a[0]&0x80)) return p; if ((a[0]&0x40)) break; } fl_utf8decode(a,end,&len); if (a+len > p) return a; return p; } /** Returns number of bytes that utf8encode() will use to encode the character \p ucs. */ int fl_utf8bytes(unsigned ucs) { if (ucs < 0x000080U) { return 1; } else if (ucs < 0x000800U) { return 2; } else if (ucs < 0x010000U) { return 3; } else if (ucs <= 0x10ffffU) { return 4; } else { return 3; /* length of the illegal character encoding */ } } /** Write the UTF-8 encoding of \e ucs into \e buf and return the number of bytes written. Up to 4 bytes may be written. If you know that \p ucs is less than 0x10000 then at most 3 bytes will be written. If you wish to speed this up, remember that anything less than 0x80 is written as a single byte. If ucs is greater than 0x10ffff this is an illegal character according to RFC 3629. These are converted as though they are 0xFFFD (REPLACEMENT CHARACTER). RFC 3629 also says many other values for \p ucs are illegal (in the range 0xd800 to 0xdfff, or ending with 0xfffe or 0xffff). However I encode these as though they are legal, so that utf8encode/fl_utf8decode will be the identity for all codes between 0 and 0x10ffff. */ int fl_utf8encode(unsigned ucs, char* buf) { if (ucs < 0x000080U) { buf[0] = ucs; return 1; } else if (ucs < 0x000800U) { buf[0] = 0xc0 | (ucs >> 6); buf[1] = 0x80 | (ucs & 0x3F); return 2; } else if (ucs < 0x010000U) { buf[0] = 0xe0 | (ucs >> 12); buf[1] = 0x80 | ((ucs >> 6) & 0x3F); buf[2] = 0x80 | (ucs & 0x3F); return 3; } else if (ucs <= 0x0010ffffU) { buf[0] = 0xf0 | (ucs >> 18); buf[1] = 0x80 | ((ucs >> 12) & 0x3F); buf[2] = 0x80 | ((ucs >> 6) & 0x3F); buf[3] = 0x80 | (ucs & 0x3F); return 4; } else { /* encode 0xfffd: */ buf[0] = (char)0xef; buf[1] = (char)0xbf; buf[2] = (char)0xbd; return 3; } } /** Convert a single 32-bit Unicode codepoint into an array of 16-bit characters. These are used by some system calls, especially on Windows. \p ucs is the value to convert. \p dst points at an array to write, and \p dstlen is the number of locations in this array. At most \p dstlen words will be written, and a 0 terminating word will be added if \p dstlen is large enough. Thus this function will never overwrite the buffer and will attempt return a zero-terminated string if space permits. If \p dstlen is zero then \p dst can be set to NULL and no data is written, but the length is returned. The return value is the number of 16-bit words that \e would be written to \p dst if it is large enough, not counting any terminating zero. If the return value is greater than \p dstlen it indicates truncation, you should then allocate a new array of size return+1 and call this again. Unicode characters in the range 0x10000 to 0x10ffff are converted to "surrogate pairs" which take two words each (in UTF-16 encoding). Typically, setting \p dstlen to 2 will ensure that any valid Unicode value can be converted, and setting \p dstlen to 3 or more will allow a NULL terminated sequence to be returned. */ unsigned fl_ucs_to_Utf16(const unsigned ucs, unsigned short *dst, const unsigned dstlen) { /* The rule for direct conversion from UCS to UTF16 is: * - if UCS > 0x0010FFFF then UCS is invalid * - if UCS >= 0xD800 && UCS <= 0xDFFF UCS is invalid * - if UCS <= 0x0000FFFF then U16 = UCS, len = 1 * - else * -- U16[0] = ((UCS - 0x00010000) >> 10) & 0x3FF + 0xD800 * -- U16[1] = (UCS & 0x3FF) + 0xDC00 * -- len = 2; */ unsigned count; /* Count of converted UTF16 cells */ unsigned short u16[4]; /* Alternate buffer if dst is not set */ unsigned short *out; /* points to the active buffer */ /* Ensure we have a valid buffer to write to */ if((!dstlen) || (!dst)) { out = u16; } else { out = dst; } /* Convert from UCS to UTF16 */ if((ucs > 0x0010FFFF) || /* UCS is too large */ ((ucs > 0xD7FF) && (ucs < 0xE000))) { /* UCS in invalid range */ out[0] = 0xFFFD; /* REPLACEMENT CHARACTER */ count = 1; } else if(ucs < 0x00010000) { out[0] = (unsigned short)ucs; count = 1; } else if(dstlen < 2) { /* dst is too small for the result */ out[0] = 0xFFFD; /* REPLACEMENT CHARACTER */ count = 2; } else { out[0] = (((ucs - 0x00010000) >> 10) & 0x3FF) + 0xD800; out[1] = (ucs & 0x3FF) + 0xDC00; count = 2; } /* NULL terminate the output, if there is space */ if(count < dstlen) { out[count] = 0; } return count; } /* fl_ucs_to_Utf16 */ /** Convert a UTF-8 sequence into an array of 16-bit characters. These are used by some system calls, especially on Windows. \p src points at the UTF-8, and \p srclen is the number of bytes to convert. \p dst points at an array to write, and \p dstlen is the number of locations in this array. At most \p dstlen-1 words will be written there, plus a 0 terminating word. Thus this function will never overwrite the buffer and will always return a zero-terminated string. If \p dstlen is zero then \p dst can be null and no data is written, but the length is returned. The return value is the number of 16-bit words that \e would be written to \p dst if it were long enough, not counting the terminating zero. If the return value is greater or equal to \p dstlen it indicates truncation, you can then allocate a new array of size return+1 and call this again. Errors in the UTF-8 are converted as though each byte in the erroneous string is in the Microsoft CP1252 encoding. This allows ISO-8859-1 text mistakenly identified as UTF-8 to be printed correctly. Unicode characters in the range 0x10000 to 0x10ffff are converted to "surrogate pairs" which take two words each (this is called UTF-16 encoding). */ unsigned fl_utf8toUtf16(const char* src, unsigned srclen, unsigned short* dst, unsigned dstlen) { const char* p = src; const char* e = src+srclen; unsigned count = 0; if (dstlen) for (;;) { if (p >= e) {dst[count] = 0; return count;} if (!(*p & 0x80)) { /* ascii */ dst[count] = *p++; } else { int len; unsigned ucs = fl_utf8decode(p,e,&len); p += len; if (ucs < 0x10000) { dst[count] = ucs; } else { /* make a surrogate pair: */ if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;} dst[count] = (((ucs-0x10000u)>>10)&0x3ff) | 0xd800; dst[++count] = (ucs&0x3ff) | 0xdc00; } } if (++count == dstlen) {dst[count-1] = 0; break;} } /* we filled dst, measure the rest: */ while (p < e) { if (!(*p & 0x80)) p++; else { int len; unsigned ucs = fl_utf8decode(p,e,&len); p += len; if (ucs >= 0x10000) ++count; } ++count; } return count; } /** Convert a UTF-8 sequence into an array of 1-byte characters. If the UTF-8 decodes to a character greater than 0xff then it is replaced with '?'. Errors in the UTF-8 sequence are converted as individual bytes, same as fl_utf8decode() does. This allows ISO-8859-1 text mistakenly identified as UTF-8 to be printed correctly (and possibly CP1252 on Windows). \p src points at the UTF-8 sequence, and \p srclen is the number of bytes to convert. Up to \p dstlen bytes are written to \p dst, including a null terminator. The return value is the number of bytes that would be written, not counting the null terminator. If greater or equal to \p dstlen then if you malloc a new array of size n+1 you will have the space needed for the entire string. If \p dstlen is zero then nothing is written and this call just measures the storage space needed. */ unsigned fl_utf8toa(const char* src, unsigned srclen, char* dst, unsigned dstlen) { const char* p = src; const char* e = src+srclen; unsigned count = 0; if (dstlen) for (;;) { unsigned char c; if (p >= e) {dst[count] = 0; return count;} c = *(const unsigned char*)p; if (c < 0xC2) { /* ascii or bad code */ dst[count] = c; p++; } else { int len; unsigned ucs = fl_utf8decode(p,e,&len); p += len; if (ucs < 0x100) dst[count] = ucs; else dst[count] = '?'; } if (++count >= dstlen) {dst[count-1] = 0; break;} } /* we filled dst, measure the rest: */ while (p < e) { if (!(*p & 0x80)) p++; else { int len; fl_utf8decode(p,e,&len); p += len; } ++count; } return count; } /** Convert an ISO-8859-1 (ie normal c-string) byte stream to UTF-8. It is possible this should convert Microsoft's CP1252 to UTF-8 instead. This would translate the codes in the range 0x80-0x9f to different characters. Currently it does not do this. Up to \p dstlen bytes are written to \p dst, including a null terminator. The return value is the number of bytes that would be written, not counting the null terminator. If greater or equal to \p dstlen then if you malloc a new array of size n+1 you will have the space needed for the entire string. If \p dstlen is zero then nothing is written and this call just measures the storage space needed. \p srclen is the number of bytes in \p src to convert. If the return value equals \p srclen then this indicates that no conversion is necessary, as only ASCII characters are in the string. */ unsigned fl_utf8froma(char* dst, unsigned dstlen, const char* src, unsigned srclen) { const char* p = src; const char* e = src+srclen; unsigned count = 0; if (dstlen) for (;;) { unsigned char ucs; if (p >= e) {dst[count] = 0; return count;} ucs = *(const unsigned char*)p++; if (ucs < 0x80U) { dst[count++] = ucs; if (count >= dstlen) {dst[count-1] = 0; break;} } else { /* 2 bytes (note that CP1252 translate could make 3 bytes!) */ if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;} dst[count++] = 0xc0 | (ucs >> 6); dst[count++] = 0x80 | (ucs & 0x3F); } } /* we filled dst, measure the rest: */ while (p < e) { unsigned char ucs = *(const unsigned char*)p++; if (ucs < 0x80U) { count++; } else { count += 2; } } return count; } /** Examines the first \p srclen bytes in \p src and returns a verdict on whether it is UTF-8 or not. - Returns 0 if there is any illegal UTF-8 sequences, using the same rules as fl_utf8decode(). Note that some UCS values considered illegal by RFC 3629, such as 0xffff, are considered legal by this. - Returns 1 if there are only single-byte characters (ie no bytes have the high bit set). This is legal UTF-8, but also indicates plain ASCII. It also returns 1 if \p srclen is zero. - Returns 2 if there are only characters less than 0x800. - Returns 3 if there are only characters less than 0x10000. - Returns 4 if there are characters in the 0x10000 to 0x10ffff range. Because there are many illegal sequences in UTF-8, it is almost impossible for a string in another encoding to be confused with UTF-8. This is very useful for transitioning Unix to UTF-8 filenames, you can simply test each filename with this to decide if it is UTF-8 or in the locale encoding. My hope is that if this is done we will be able to cleanly transition to a locale-less encoding. */ int fl_utf8test(const char* src, unsigned srclen) { int ret = 1; const char* p = src; const char* e = src+srclen; while (p < e) { if (*p & 0x80) { int len; fl_utf8decode(p,e,&len); if (len < 2) return 0; if (len > ret) ret = len; p += len; } else { p++; } } return ret; } /* forward declare mk_wcwidth() as static so the name is not visible. */ static int mk_wcwidth(unsigned int ucs); /* include the c source directly so its contents are only visible here */ #include "xutf8/mk_wcwidth.c" /** Wrapper to adapt Markus Kuhn's implementation of wcwidth() for FLTK. \param [in] ucs Unicode character value \returns width of character in columns See http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c for Markus Kuhn's original implementation of wcwidth() and wcswidth() (defined in IEEE Std 1002.1-2001) for Unicode. \b WARNING: this function returns widths for "raw" Unicode characters. It does not even try to map C1 control characters (0x80 to 0x9F) to CP1252, and C0/C1 control characters and DEL will return -1. You are advised to use fl_width(const char* src) instead. */ int fl_wcwidth_(unsigned int ucs) { return mk_wcwidth(ucs); } /** extended wrapper around fl_wcwidth_(unsigned int ucs) function. \param[in] src pointer to start of UTF-8 byte sequence \returns width of character in columns Depending on build options, this function may map C1 control characters (0x80 to 0x9f) to CP1252, and return the width of that character instead. This is not the same behaviour as fl_wcwidth_(unsigned int ucs) . Note that other control characters and DEL will still return -1, so if you want different behaviour, you need to test for those characters before calling fl_wcwidth(), and handle them separately. */ int fl_wcwidth(const char* src) { int len = fl_utf8len(*src); int ret = 0; unsigned int ucs = fl_utf8decode(src, src+len, &ret); int width = fl_wcwidth_(ucs); return width; } /** Converts a UTF-8 string into a wide character string. This function generates 32-bit wchar_t (e.g. "ucs4" as it were) except on Windows where it is equivalent to fl_utf8toUtf16 and returns UTF-16. \p src points at the UTF-8, and \p srclen is the number of bytes to convert. \p dst points at an array to write, and \p dstlen is the number of locations in this array. At most \p dstlen-1 wchar_t will be written there, plus a 0 terminating wchar_t. The return value is the number of wchar_t that \e would be written to \p dst if it were long enough, not counting the terminating zero. If the return value is greater or equal to \p dstlen it indicates truncation, you can then allocate a new array of size return+1 and call this again. Notice that sizeof(wchar_t) is 2 on Windows and is 4 on Linux and most other systems. Where wchar_t is 16 bits, Unicode characters in the range 0x10000 to 0x10ffff are converted to "surrogate pairs" which take two words each (this is called UTF-16 encoding). If wchar_t is 32 bits this rather nasty problem is avoided. Note that Windows includes Cygwin, i.e. compiled with Cygwin's POSIX layer (cygwin1.dll, --enable-cygwin), either native (GDI) or X11. */ unsigned fl_utf8towc(const char* src, unsigned srclen, wchar_t* dst, unsigned dstlen) { return Fl::system_driver()->utf8towc(src, srclen, dst, dstlen); } /** Turn "wide characters" as returned by some system calls (especially on Windows) into UTF-8. Up to \p dstlen bytes are written to \p dst, including a null terminator. The return value is the number of bytes that would be written, not counting the null terminator. If greater or equal to \p dstlen then if you malloc a new array of size n+1 you will have the space needed for the entire string. If \p dstlen is zero then nothing is written and this call just measures the storage space needed. \p srclen is the number of words in \p src to convert. On Windows this is not necessarily the number of characters, due to there possibly being "surrogate pairs" in the UTF-16 encoding used. On Unix wchar_t is 32 bits and each location is a character. On Unix if a \p src word is greater than 0x10ffff then this is an illegal character according to RFC 3629. These are converted as though they are 0xFFFD (REPLACEMENT CHARACTER). Characters in the range 0xd800 to 0xdfff, or ending with 0xfffe or 0xffff are also illegal according to RFC 3629. However I encode these as though they are legal, so that fl_utf8towc will return the original data. On Windows "surrogate pairs" are converted to a single character and UTF-8 encoded (as 4 bytes). Mismatched halves of surrogate pairs are converted as though they are individual characters. */ unsigned fl_utf8fromwc(char* dst, unsigned dstlen, const wchar_t* src, unsigned srclen) { return Fl::system_driver()->utf8fromwc(dst, dstlen, src, srclen); } /** Return true if the "locale" seems to indicate that UTF-8 encoding is used. If true the fl_utf8to_mb and fl_utf8from_mb don't do anything useful. It is highly recommended that you change your system so this does return true. On Windows this is done by setting the "codepage" to CP_UTF8. On Unix this is done by setting $LC_CTYPE to a string containing the letters "utf" or "UTF" in it, or by deleting all $LC* and $LANG environment variables. In the future it is likely that all non-Asian Unix systems will return true, due to the compatibility of UTF-8 with ISO-8859-1. */ int fl_utf8locale() { return Fl::system_driver()->utf8locale(); } /** Convert the UTF-8 used by FLTK to the locale-specific encoding used for filenames (and sometimes used for data in files). Unfortunately due to stupid design you will have to do this as needed for filenames. This is a bug on both Unix and Windows. Up to \p dstlen bytes are written to \p dst, including a null terminator. The return value is the number of bytes that would be written, not counting the null terminator. If greater or equal to \p dstlen then if you malloc a new array of size n+1 you will have the space needed for the entire string. If \p dstlen is zero then nothing is written and this call just measures the storage space needed. If fl_utf8locale() returns true then this does not change the data. */ unsigned fl_utf8to_mb(const char* src, unsigned srclen, char* dst, unsigned dstlen) { if (fl_utf8locale()) { /* identity transform: */ if (srclen < dstlen) { memcpy(dst, src, srclen); dst[srclen] = 0; } else { /* Buffer insufficent or buffer query */ } return srclen; } return Fl::system_driver()->utf8to_mb(src, srclen, dst, dstlen); } /** Convert a filename from the locale-specific multibyte encoding used by Windows to UTF-8 as used by FLTK. Up to \p dstlen bytes are written to \p dst, including a null terminator. The return value is the number of bytes that would be written, not counting the null terminator. If greater or equal to \p dstlen then if you malloc a new array of size n+1 you will have the space needed for the entire string. If \p dstlen is zero then nothing is written and this call just measures the storage space needed. On Unix or on Windows when a UTF-8 locale is in effect, this does not change the data. You may also want to check if fl_utf8test() returns non-zero, so that the filesystem can store filenames in UTF-8 encoding regardless of the locale. */ unsigned fl_utf8from_mb(char* dst, unsigned dstlen, const char* src, unsigned srclen) { if (fl_utf8locale()) { /* identity transform: */ if (srclen < dstlen) { memcpy(dst, src, srclen); dst[srclen] = 0; } else { /* Buffer insufficent or buffer query */ } return srclen; } return Fl::system_driver()->utf8from_mb(dst, dstlen, src, srclen); } /** @} */ fltk-1.4.3/src/fl_cmap.h0000644000175000017500000001451515004135251015154 0ustar albrechtalbrecht// // DO NOT EDIT THIS FILE ! // // This file must be generated by "util/cmap.cxx". // See instructions in this file. // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // 0x00000000, // 0 0xff000000, // 1 0x00ff0000, // 2 0xffff0000, // 3 0x0000ff00, // 4 0xff00ff00, // 5 0x00ffff00, // 6 0xffffff00, // 7 0x55555500, // 8 0xc6717100, // 9 0x71c67100, // 10 0x8e8e3800, // 11 0x7171c600, // 12 0x8e388e00, // 13 0x388e8e00, // 14 0x00008000, // 15 0xa8a89800, // 16 0xe8e8d800, // 17 0x68685800, // 18 0x98a8a800, // 19 0xd8e8e800, // 20 0x58686800, // 21 0x9c9ca800, // 22 0xdcdce800, // 23 0x5c5c6800, // 24 0x9ca89c00, // 25 0xdce8dc00, // 26 0x5c685c00, // 27 0x90909000, // 28 0xc0c0c000, // 29 0x50505000, // 30 0xa0a0a000, // 31 0x00000000, // 32 0x0d0d0d00, // 33 0x1a1a1a00, // 34 0x26262600, // 35 0x31313100, // 36 0x3d3d3d00, // 37 0x48484800, // 38 0x55555500, // 39 0x5f5f5f00, // 40 0x6a6a6a00, // 41 0x75757500, // 42 0x80808000, // 43 0x8a8a8a00, // 44 0x95959500, // 45 0xa0a0a000, // 46 0xaaaaaa00, // 47 0xb5b5b500, // 48 0xc0c0c000, // 49 0xcbcbcb00, // 50 0xd5d5d500, // 51 0xe0e0e000, // 52 0xeaeaea00, // 53 0xf5f5f500, // 54 0xffffff00, // 55 0x00000000, // 56 0x00240000, // 57 0x00480000, // 58 0x006d0000, // 59 0x00910000, // 60 0x00b60000, // 61 0x00da0000, // 62 0x00ff0000, // 63 0x3f000000, // 64 0x3f240000, // 65 0x3f480000, // 66 0x3f6d0000, // 67 0x3f910000, // 68 0x3fb60000, // 69 0x3fda0000, // 70 0x3fff0000, // 71 0x7f000000, // 72 0x7f240000, // 73 0x7f480000, // 74 0x7f6d0000, // 75 0x7f910000, // 76 0x7fb60000, // 77 0x7fda0000, // 78 0x7fff0000, // 79 0xbf000000, // 80 0xbf240000, // 81 0xbf480000, // 82 0xbf6d0000, // 83 0xbf910000, // 84 0xbfb60000, // 85 0xbfda0000, // 86 0xbfff0000, // 87 0xff000000, // 88 0xff240000, // 89 0xff480000, // 90 0xff6d0000, // 91 0xff910000, // 92 0xffb60000, // 93 0xffda0000, // 94 0xffff0000, // 95 0x00003f00, // 96 0x00243f00, // 97 0x00483f00, // 98 0x006d3f00, // 99 0x00913f00, // 100 0x00b63f00, // 101 0x00da3f00, // 102 0x00ff3f00, // 103 0x3f003f00, // 104 0x3f243f00, // 105 0x3f483f00, // 106 0x3f6d3f00, // 107 0x3f913f00, // 108 0x3fb63f00, // 109 0x3fda3f00, // 110 0x3fff3f00, // 111 0x7f003f00, // 112 0x7f243f00, // 113 0x7f483f00, // 114 0x7f6d3f00, // 115 0x7f913f00, // 116 0x7fb63f00, // 117 0x7fda3f00, // 118 0x7fff3f00, // 119 0xbf003f00, // 120 0xbf243f00, // 121 0xbf483f00, // 122 0xbf6d3f00, // 123 0xbf913f00, // 124 0xbfb63f00, // 125 0xbfda3f00, // 126 0xbfff3f00, // 127 0xff003f00, // 128 0xff243f00, // 129 0xff483f00, // 130 0xff6d3f00, // 131 0xff913f00, // 132 0xffb63f00, // 133 0xffda3f00, // 134 0xffff3f00, // 135 0x00007f00, // 136 0x00247f00, // 137 0x00487f00, // 138 0x006d7f00, // 139 0x00917f00, // 140 0x00b67f00, // 141 0x00da7f00, // 142 0x00ff7f00, // 143 0x3f007f00, // 144 0x3f247f00, // 145 0x3f487f00, // 146 0x3f6d7f00, // 147 0x3f917f00, // 148 0x3fb67f00, // 149 0x3fda7f00, // 150 0x3fff7f00, // 151 0x7f007f00, // 152 0x7f247f00, // 153 0x7f487f00, // 154 0x7f6d7f00, // 155 0x7f917f00, // 156 0x7fb67f00, // 157 0x7fda7f00, // 158 0x7fff7f00, // 159 0xbf007f00, // 160 0xbf247f00, // 161 0xbf487f00, // 162 0xbf6d7f00, // 163 0xbf917f00, // 164 0xbfb67f00, // 165 0xbfda7f00, // 166 0xbfff7f00, // 167 0xff007f00, // 168 0xff247f00, // 169 0xff487f00, // 170 0xff6d7f00, // 171 0xff917f00, // 172 0xffb67f00, // 173 0xffda7f00, // 174 0xffff7f00, // 175 0x0000bf00, // 176 0x0024bf00, // 177 0x0048bf00, // 178 0x006dbf00, // 179 0x0091bf00, // 180 0x00b6bf00, // 181 0x00dabf00, // 182 0x00ffbf00, // 183 0x3f00bf00, // 184 0x3f24bf00, // 185 0x3f48bf00, // 186 0x3f6dbf00, // 187 0x3f91bf00, // 188 0x3fb6bf00, // 189 0x3fdabf00, // 190 0x3fffbf00, // 191 0x7f00bf00, // 192 0x7f24bf00, // 193 0x7f48bf00, // 194 0x7f6dbf00, // 195 0x7f91bf00, // 196 0x7fb6bf00, // 197 0x7fdabf00, // 198 0x7fffbf00, // 199 0xbf00bf00, // 200 0xbf24bf00, // 201 0xbf48bf00, // 202 0xbf6dbf00, // 203 0xbf91bf00, // 204 0xbfb6bf00, // 205 0xbfdabf00, // 206 0xbfffbf00, // 207 0xff00bf00, // 208 0xff24bf00, // 209 0xff48bf00, // 210 0xff6dbf00, // 211 0xff91bf00, // 212 0xffb6bf00, // 213 0xffdabf00, // 214 0xffffbf00, // 215 0x0000ff00, // 216 0x0024ff00, // 217 0x0048ff00, // 218 0x006dff00, // 219 0x0091ff00, // 220 0x00b6ff00, // 221 0x00daff00, // 222 0x00ffff00, // 223 0x3f00ff00, // 224 0x3f24ff00, // 225 0x3f48ff00, // 226 0x3f6dff00, // 227 0x3f91ff00, // 228 0x3fb6ff00, // 229 0x3fdaff00, // 230 0x3fffff00, // 231 0x7f00ff00, // 232 0x7f24ff00, // 233 0x7f48ff00, // 234 0x7f6dff00, // 235 0x7f91ff00, // 236 0x7fb6ff00, // 237 0x7fdaff00, // 238 0x7fffff00, // 239 0xbf00ff00, // 240 0xbf24ff00, // 241 0xbf48ff00, // 242 0xbf6dff00, // 243 0xbf91ff00, // 244 0xbfb6ff00, // 245 0xbfdaff00, // 246 0xbfffff00, // 247 0xff00ff00, // 248 0xff24ff00, // 249 0xff48ff00, // 250 0xff6dff00, // 251 0xff91ff00, // 252 0xffb6ff00, // 253 0xffdaff00, // 254 0xffffff00 // 255 // // End of fl_cmap.h - generated by cmap.cxx // fltk-1.4.3/src/Fl_Input_.cxx0000644000175000017500000013055015004135251016003 0ustar albrechtalbrecht// // Common input widget routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2011 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include "Fl_Screen_Driver.H" #include #include #include #include #include "flstring.h" #include #include #define MAXBUF 1024 static int l_secret; extern void fl_draw(const char*, int, float, float); //////////////////////////////////////////////////////////////// // see: Fl_Text_Undo_Action class Fl_Input_Undo_Action { public: Fl_Input_Undo_Action() : undobuffer(NULL), undobufferlength(0), undoat(0), undocut(0), undoinsert(0), undoyankcut(0) { } ~Fl_Input_Undo_Action() { if (undobuffer) ::free(undobuffer); } char *undobuffer; int undobufferlength; int undoat; // points after insertion int undocut; // number of characters deleted there int undoinsert; // number of characters inserted int undoyankcut; // length of valid contents of buffer, even if undocut=0 /* Resize the undo buffer to match at least the requested size. */ void undobuffersize(int n) { if (n > undobufferlength) { undobufferlength = n + 128; undobuffer = (char *)realloc(undobuffer, undobufferlength); } } void clear() { undocut = undoinsert = 0; } }; // see: Fl_Text_Undo_Action_List class Fl_Input_Undo_Action_List { Fl_Input_Undo_Action** list_; int list_size_; int list_capacity_; public: Fl_Input_Undo_Action_List() : list_(NULL), list_size_(0), list_capacity_(0) { } ~Fl_Input_Undo_Action_List() { clear(); } int size() const { return list_size_; } void push(Fl_Input_Undo_Action* action) { if (list_size_ == list_capacity_) { list_capacity_ += 25; list_ = (Fl_Input_Undo_Action**)realloc(list_, list_capacity_ * sizeof(Fl_Input_Undo_Action*)); } list_[list_size_++] = action; } Fl_Input_Undo_Action* pop() { if (list_size_ > 0) return list_[--list_size_]; else return NULL; } void clear() { if (list_) { for (int i=0; i^X and \\nnn as necessary. The destination buffer is limited to \c MAXBUF (currently at 1024). All following text is truncated. \param [in] p pointer to source buffer \param [in] buf pointer to destination buffer \return pointer to the end of the destination buffer */ const char* Fl_Input_::expand(const char* p, char* buf) const { char* o = buf; char* e = buf+(MAXBUF-4); const char* lastspace = p; char* lastspace_out = o; int width_to_lastspace = 0; int word_count = 0; int word_wrap; // const char *pe = p + strlen(p); if (input_type()==FL_SECRET_INPUT) { while (o= 1) { l_secret = fl_utf8encode(Fl_Screen_Driver::secret_input_character, o); o += l_secret; } p++; } } else while (o= value_+size_ || isspace(*p & 255))) { word_wrap = w() - Fl::box_dw(box()) - 2; width_to_lastspace += (int)fl_width(lastspace_out, (int) (o-lastspace_out)); if (p > lastspace+1) { if (word_count && width_to_lastspace > word_wrap) { p = lastspace; o = lastspace_out; break; } word_count++; } lastspace = p; lastspace_out = o; } if (p >= value_+size_) break; int c = *p++ & 255; if (c < ' ' || c == 127) { if (c=='\n' && input_type()==FL_MULTILINE_INPUT) {p--; break;} if (c == '\t' && input_type()==FL_MULTILINE_INPUT) { for (c = fl_utf_nb_char((uchar*)buf, (int) (o-buf))%8; c<8 && o= 1) n += l_secret; p += l; } } else while (p= 1; p += fl_utf8len1(*p); } if (returnn) *returnn = n; return fl_width(buf, n); } //////////////////////////////////////////////////////////////// /** \internal Marks a range of characters for update. This call marks all characters from \p p to the end of the text buffer for update. At least these characters will be redrawn in the next update cycle. Characters from \p mu_p to end of widget are redrawn. If \p erase_cursor_only, small part at \p mu_p is redrawn. Right now minimal update just keeps unchanged characters from being erased, so they don't blink. \param [in] p start of update range */ void Fl_Input_::minimal_update(int p) { if (damage() & FL_DAMAGE_ALL) return; // don't waste time if it won't be done if (damage() & FL_DAMAGE_EXPOSE) { if (p < mu_p) mu_p = p; } else { mu_p = p; } damage(FL_DAMAGE_EXPOSE); erase_cursor_only = 0; } /** \internal Marks a range of characters for update. This call marks a text range for update. At least all characters from \p p to \p q will be redrawn in the next update cycle. \param [in] p start of update range \param [in] q end of update range */ void Fl_Input_::minimal_update(int p, int q) { if (q < p) p = q; minimal_update(p); } //////////////////////////////////////////////////////////////// /* Horizontal cursor position in pixels while moving up or down. */ double Fl_Input_::up_down_pos = 0; /* Flag to remember last cursor move. */ int Fl_Input_::was_up_down = 0; /** Sets the current font and font size. */ void Fl_Input_::setfont() const { fl_font(textfont(), textsize()); } /** Draws the text in the passed bounding box. If damage() & FL_DAMAGE_ALL is true, this assumes the area has already been erased to color(). Otherwise it does minimal update and erases the area itself. \param X, Y, W, H area that must be redrawn */ void Fl_Input_::drawtext(int X, int Y, int W, int H) { drawtext(X, Y, W, H, (Fl::focus()==this)); } /** Draws the text in the passed bounding box. This version of `drawtext` allows the user to control whether the widget is drawn as acitive, i.e. with the text cursor, or inactive. This is useful for compound widgets where the input should be shown as active when actually the container widget is the active one. A caller should not draw the widget with `active` set if another text widget may indeed be the active widget. \param X, Y, W, H area that must be redrawn \param draw_active if set, the cursor will be drawn, even if the widget is not active \see Fl_Input_::drawtext(int X, int Y, int W, int H) */ void Fl_Input_::drawtext(int X, int Y, int W, int H, bool draw_active) { int do_mu = !(damage()&FL_DAMAGE_ALL); if (!draw_active && !size()) { if (do_mu) { // we have to erase it if cursor was there draw_box(box(), X-Fl::box_dx(box()), Y-Fl::box_dy(box()), W+Fl::box_dw(box()), H+Fl::box_dh(box()), color()); } return; } int selstart, selend; if (!draw_active && /*Fl::selection_owner()!=this &&*/ Fl::pushed()!=this) selstart = selend = 0; else if (insert_position() <= mark()) { selstart = insert_position(); selend = mark(); } else { selend = insert_position(); selstart = mark(); } setfont(); const char *p, *e; char buf[MAXBUF]; // count how many lines and put the last one into the buffer: // And figure out where the cursor is: int height = fl_height(); int threshold = height/2; int lines; int curx, cury; for (p=value(), curx=cury=lines=0; ;) { e = expand(p, buf); if (insert_position() >= p-value() && insert_position() <= e-value()) { curx = int(expandpos(p, value()+insert_position(), buf, 0)+.5); if (draw_active && !was_up_down) up_down_pos = curx; cury = lines*height; int newscroll = xscroll_; if (curx > newscroll+W-threshold) { // figure out scrolling so there is space after the cursor: newscroll = curx+threshold-W; // figure out the furthest left we ever want to scroll: int ex = int(expandpos(p, e, buf, 0))+4-W; // use minimum of both amounts: if (ex < newscroll) newscroll = ex; } else if (curx < newscroll+threshold) { newscroll = curx-threshold; } if (newscroll < 0) newscroll = 0; if (newscroll != xscroll_) { xscroll_ = newscroll; mu_p = 0; erase_cursor_only = 0; } } lines++; if (e >= value_+size_) break; p = e+1; } // adjust the scrolling: if (input_type()==FL_MULTILINE_INPUT) { int newy = yscroll_; if (cury < newy) newy = cury; if (cury > newy+H-height) newy = cury-H+height; if (newy < -1) newy = -1; if (newy != yscroll_) {yscroll_ = newy; mu_p = 0; erase_cursor_only = 0;} } else { yscroll_ = -(H-height)/2; } fl_push_clip(X, Y, W, H); Fl_Color tc = active_r() ? textcolor() : fl_inactive(textcolor()); p = value(); // visit each line and draw it: int desc = height-fl_descent(); float xpos = (float)(X - xscroll_ + 1); int ypos = -yscroll_; int ypos_cur = 0; //fix issue #270 for (; ypos < H;) { // re-expand line unless it is the last one calculated above: if (lines>1) e = expand(p, buf); if (ypos <= -height) goto CONTINUE; // clipped off top if (do_mu) { // for minimal update: const char* pp = value()+mu_p; // pointer to where minimal update starts if (e < pp) goto CONTINUE2; // this line is before the changes if (readonly()) erase_cursor_only = 0; // this isn't the most efficient way if (erase_cursor_only && p > pp) goto CONTINUE2; // this line is after // calculate area to erase: float r = (float)(X+W); float xx; if (p >= pp) { xx = (float)X; if (erase_cursor_only) r = xpos+2; else if (readonly()) xx -= 3; } else { xx = xpos + (float)expandpos(p, pp, buf, 0); if (erase_cursor_only) r = xx+2; else if (readonly()) xx -= 3; } // clip to and erase it: fl_push_clip((int)xx-1-height/8, Y+ypos, (int)(r-xx+2+height/4), height); draw_box(box(), X-Fl::box_dx(box()), Y-Fl::box_dy(box()), W+Fl::box_dw(box()), H+Fl::box_dh(box()), color()); // it now draws entire line over it // this should not draw letters to left of erased area, but // that is nyi. } // Draw selection area if required: if (selstart < selend && selstart <= e-value() && selend > p-value()) { const char* pp = value()+selstart; float x1 = xpos; int offset1 = 0; if (pp > p) { fl_color(tc); x1 += (float)expandpos(p, pp, buf, &offset1); fl_draw(buf, offset1, xpos, (float)(Y+ypos+desc)); } pp = value()+selend; float x2 = (float)(X+W); int offset2; if (pp <= e) x2 = xpos + (float)expandpos(p, pp, buf, &offset2); else offset2 = (int) strlen(buf); if (Fl::screen_driver()->has_marked_text() && Fl::compose_state) { fl_color(textcolor()); } else { fl_color(selection_color()); fl_rectf((int)(x1+0.5), Y+ypos, (int)(x2-x1+0.5), height); fl_color(fl_contrast(textcolor(), selection_color())); } fl_draw(buf+offset1, offset2-offset1, x1, (float)(Y+ypos+desc)); if (Fl::screen_driver()->has_marked_text() && Fl::compose_state) { fl_color( fl_color_average(textcolor(), color(), 0.6f) ); float width = (float)fl_width(buf+offset1, offset2-offset1); fl_line((int)x1, Y+ypos+height-1, (int)(x1+width), Y+ypos+height-1); } if (pp < e) { fl_color(tc); fl_draw(buf+offset2, (int) strlen(buf+offset2), x2, (float)(Y+ypos+desc)); } } else { // draw unselected text fl_color(tc); fl_draw(buf, (int) strlen(buf), xpos, (float)(Y+ypos+desc)); } if (do_mu) fl_pop_clip(); CONTINUE2: // draw the cursor: if ( draw_active && ( (Fl::screen_driver()->has_marked_text() && Fl::compose_state) || selstart == selend ) && insert_position() >= p-value() && insert_position() <= e-value() ) { fl_color(cursor_color()); // cursor position may need to be recomputed (see STR #2486) curx = int(expandpos(p, value()+insert_position(), buf, 0)+.5); if (readonly()) { // Draw '^' caret cursor fl_line((int)(xpos+curx-2.5f), Y+ypos+height-1, (int)(xpos+curx+0.5f), Y+ypos+height-4, (int)(xpos+curx+3.5f), Y+ypos+height-1); } else { fl_rectf((int)(xpos+curx+0.5), Y+ypos, 2, height); } ypos_cur = ypos+height; //fix issue #270 } CONTINUE: ypos += height; if (e >= value_+size_) break; if (*e == '\n' || *e == ' ') e++; p = e; } // for minimal update, erase all lines below last one if necessary: if (input_type()==FL_MULTILINE_INPUT && do_mu && ypos 0 && !isword(index(i-1))) i--; while (i > 0 && isword(index(i-1))) i--; return i; } /** Finds the end of a line. This call calculates the end of a line based on the given index \p i. \param [in] i starting index for the search \return end of the line */ int Fl_Input_::line_end(int i) const { if (input_type() != FL_MULTILINE_INPUT) return size(); if (wrap()) { // go to the start of the paragraph: int j = i; while (j > 0 && index(j-1) != '\n') j--; // now measure lines until we get past i, end of that line is real eol: setfont(); for (const char* p=value()+j; ;) { char buf[MAXBUF]; p = expand(p, buf); int k = (int) (p-value()); if (k >= i) return k; p++; } } else { while (i < size() && index(i) != '\n') i++; return i; } } /** Finds the start of a line. This call calculates the start of a line based on the given index \p i. \param [in] i starting index for the search \return start of the line */ int Fl_Input_::line_start(int i) const { if (input_type() != FL_MULTILINE_INPUT) return 0; int j = i; while (j > 0 && index(j-1) != '\n') j--; if (wrap()) { // now measure lines until we get past i, start of that line is real eol: setfont(); for (const char* p=value()+j; ;) { char buf[MAXBUF]; const char* e = expand(p, buf); if ((int) (e-value()) >= i) return (int) (p-value()); p = e+1; } } else return j; } static int strict_word_start(const char *s, int i, int itype) { if (itype == FL_SECRET_INPUT) return 0; while (i > 0 && !isspace(s[i-1])) i--; return i; } static int strict_word_end(const char *s, int len, int i, int itype) { if (itype == FL_SECRET_INPUT) return len; while (i < len && !isspace(s[i])) i++; return i; } /** Handles mouse clicks and mouse moves. \todo Add comment and parameters */ void Fl_Input_::handle_mouse(int X, int Y, int /*W*/, int /*H*/, int drag) { was_up_down = 0; if (!size()) return; setfont(); const char *p, *e; char buf[MAXBUF]; int theline = (input_type()==FL_MULTILINE_INPUT) ? (Fl::event_y()-Y+yscroll_)/fl_height() : 0; int newpos = 0; for (p=value();; ) { e = expand(p, buf); theline--; if (theline < 0) break; if (e >= value_+size_) break; p = e+1; } const char *l, *r, *t; double f0 = Fl::event_x()-X+xscroll_; for (l = p, r = e; l 0) { f1 = X-xscroll_+expandpos(p, l + cw, buf, 0) - Fl::event_x(); if (f1 < f0) l = l+cw; } } newpos = (int) (l-value()); int newmark = drag ? mark() : newpos; if (Fl::event_clicks()) { if (newpos >= newmark) { if (newpos == newmark) { if (newpos < size()) newpos++; else newmark--; } if (Fl::event_clicks() > 1) { newpos = line_end(newpos); newmark = line_start(newmark); } else { newpos = strict_word_end(value(), size(), newpos, input_type()); newmark = strict_word_start(value(), newmark, input_type()); } } else { if (Fl::event_clicks() > 1) { newpos = line_start(newpos); newmark = line_end(newmark); } else { newpos = strict_word_start(value(), newpos, input_type()); newmark = strict_word_end(value(), size(), newmark, input_type()); } } // if the multiple click does not increase the selection, revert // to single-click behavior: if (!drag && (mark() > insert_position() ? (newmark >= insert_position() && newpos <= mark()) : (newmark >= mark() && newpos <= insert_position()))) { Fl::event_clicks(0); newmark = newpos = (int) (l-value()); } } insert_position(newpos, newmark); } /** Sets the index for the cursor and mark. The input widget maintains two pointers into the string. The \e position (\c p) is where the cursor is. The \e mark (\c m) is the other end of the selected text. If they are equal then there is no selection. Changing this does not affect the clipboard (use copy() to do that). Changing these values causes a redraw(). The new values are bounds checked. \param p index for the cursor position \param m index for the mark \return 0 if no positions changed \see position(int), position(), mark(int) */ int Fl_Input_::insert_position(int p, int m) { int is_same = 0; was_up_down = 0; if (p<0) p = 0; if (p>size()) p = size(); if (m<0) m = 0; if (m>size()) m = size(); if (p == m) is_same = 1; while (p < position_ && p > 0 && (size() - p) > 0 && (fl_utf8len((char)(value() + p)[0]) < 1)) { p--; } int ul = fl_utf8len((char)(value() + p)[0]); while (p < size() && p > position_ && ul < 0) { p++; ul = fl_utf8len((char)(value() + p)[0]); } while (m < mark_ && m > 0 && (size() - m) > 0 && (fl_utf8len((char)(value() + m)[0]) < 1)) { m--; } ul = fl_utf8len((char)(value() + m)[0]); while (m < size() && m > mark_ && ul < 0) { m++; ul = fl_utf8len((char)(value() + m)[0]); } if (is_same) m = p; if (p == position_ && m == mark_) return 0; //if (Fl::selection_owner() == this) Fl::selection_owner(0); if (p != m) { if (p != position_) minimal_update(position_, p); if (m != mark_) minimal_update(mark_, m); } else { // new position is a cursor if (position_ == mark_) { // old position was just a cursor if (Fl::focus() == this && !(damage()&FL_DAMAGE_EXPOSE)) { minimal_update(position_); erase_cursor_only = 1; } } else { // old position was a selection minimal_update(position_, mark_); } } position_ = p; mark_ = m; return 1; } /** Moves the cursor to the column given by \p up_down_pos. This function is helpful when implementing up and down cursor movement. It moves the cursor from the beginning of a line to the column indicated by the global variable \p up_down_pos in pixel units. \param [in] i index into the beginning of a line of text \param [in] keepmark if set, move only the cursor, but not the mark \return index to new cursor position */ int Fl_Input_::up_down_position(int i, int keepmark) { // unlike before, i must be at the start of the line already! setfont(); char buf[MAXBUF]; const char* p = value()+i; const char* e = expand(p, buf); const char *l, *r, *t; for (l = p, r = e; l e) {b = mark(); e = insert_position();} if (input_type() == FL_SECRET_INPUT) e = b; Fl::copy(value()+b, e-b, clipboard); return 1; } return 0; } #define MAXFLOATSIZE 40 /** Append text at the end. This function appends the string in \p t to the end of the text. It does not moves the new position or mark. \param [in] t text that will be appended \param [in] l length of text, or 0 if the string is terminated by \c nul. \param [in] keep_selection if this is 1, the current text selection will remain, if 0, the cursor will move to the end of the inserted text. \return 0 if no text was appended */ int Fl_Input_::append(const char* t, int l, char keep_selection) { int end = size(); int om = mark_, op = position_; int ret = replace(end, end, t, l); if (keep_selection) { insert_position(op, om); } return ret; } /** Deletes text from \p b to \p e and inserts the new string \p text. All changes to the text buffer go through this function. It deletes the region between \p b and \p e (either one may be less or equal to the other), and then inserts the string \p text at that point and moves the mark() and position() to the end of the insertion. Does the callback if when() & FL_WHEN_CHANGED and there is a change. Set \p b and \p e equal to not delete anything. Set \p text to \c NULL to not insert anything. \p ilen can be zero or strlen(text), which saves a tiny bit of time if you happen to already know the length of the insertion, or can be used to insert a portion of a string. If \p ilen is zero, strlen(text) is used instead. \p b and \p e are clamped to the 0..size() range, so it is safe to pass any values. \p b, \p e, and \p ilen are used as numbers of bytes (not characters), where \p b and \p e count from 0 to size() (end of buffer). If \p b and/or \p e don't point to a valid UTF-8 character boundary, they are adjusted to the previous (\p b) or the next (\p e) valid UTF-8 character boundary, resp.. If the current number of characters in the buffer minus deleted characters plus inserted characters in \p text would overflow the number of allowed characters (maximum_size()), then only the first characters of the string are inserted, so that maximum_size() is not exceeded. cut() and insert() are just inline functions that call replace(). \param [in] b beginning index of text to be deleted \param [in] e ending index of text to be deleted and insertion position \param [in] text string that will be inserted \param [in] ilen length of \p text or 0 for \c nul terminated strings \return 0 if nothing changed \note If \p text does not point to a valid UTF-8 character or includes invalid UTF-8 sequences, the text is inserted nevertheless (counting invalid UTF-8 bytes as one character each). */ int Fl_Input_::replace(int b, int e, const char* text, int ilen) { int ul, om, op; was_up_down = 0; if (b<0) b = 0; if (e<0) e = 0; if (b>size_) b = size_; if (e>size_) e = size_; if (e 0 && (size_ - b) > 0 && (fl_utf8len((value_ + b)[0]) < 1)) { b--; } ul = fl_utf8len((char)(value_ + e)[0]); while (e < size_ && e > 0 && ul < 0) { e++; ul = fl_utf8len((char)(value_ + e)[0]); } if (text && !ilen) ilen = (int) strlen(text); if (e<=b && !ilen) return 0; // don't clobber undo for a null operation // we must count UTF-8 *characters* to determine whether we can insert // the full text or only a part of it (and how much this would be) int nchars = 0; // characters in value() - deleted + inserted const char *p = value_; while (p < (char *)(value_+size_)) { if (p == (char *)(value_+b)) { // skip removed part p = (char *)(value_+e); if (p >= (char *)(value_+size_)) break; } int ulen = fl_utf8len(*p); if (ulen < 1) ulen = 1; // invalid UTF-8 character: count as 1 nchars++; p += ulen; } int nlen = 0; // length (in bytes) to be inserted p = text; while (p < (char *)(text+ilen) && nchars < maximum_size()) { int ulen = fl_utf8len(*p); if (ulen < 1) ulen = 1; // invalid UTF-8 character: count as 1 nchars++; p += ulen; nlen += ulen; } ilen = nlen; put_in_buffer(size_+ilen); if (e>b) { if (b == undo_->undoat) { undo_->undobuffersize(undo_->undocut+(e-b)); memcpy(undo_->undobuffer+undo_->undocut, value_+b, e-b); undo_->undocut += e-b; } else if (e == undo_->undoat && !undo_->undoinsert) { undo_->undobuffersize(undo_->undocut+(e-b)); memmove(undo_->undobuffer+(e-b), undo_->undobuffer, undo_->undocut); memcpy(undo_->undobuffer, value_+b, e-b); undo_->undocut += e-b; } else if (e == undo_->undoat && (e-b)undoinsert) { undo_->undoinsert -= e-b; } else { redo_list_->clear(); undo_list_->push(undo_); undo_ = new Fl_Input_Undo_Action(); undo_->undobuffersize(e-b); memcpy(undo_->undobuffer, value_+b, e-b); undo_->undocut = e-b; undo_->undoinsert = 0; } memmove(buffer+b, buffer+e, size_-e+1); size_ -= e-b; undo_->undoat = b; if (input_type() == FL_SECRET_INPUT) undo_->undoyankcut = 0; else undo_->undoyankcut = undo_->undocut; } if (ilen) { if (b == undo_->undoat) { undo_->undoinsert += ilen; } else { redo_list_->clear(); undo_list_->push(undo_); undo_ = new Fl_Input_Undo_Action(); undo_->undocut = 0; undo_->undoinsert = ilen; } memmove(buffer+b+ilen, buffer+b, size_-b+1); memcpy(buffer+b, text, ilen); size_ += ilen; } om = mark_; op = position_; mark_ = position_ = undo_->undoat = b+ilen; // Insertions into the word at the end of the line will cause it to // wrap to the next line, so we must indicate that the changes may start // right after the whitespace before the current word. This will // result in sub-optimal update when such wrapping does not happen // but it is too hard to figure out for now... if (wrap()) { // if there is a space in the pasted text, the whole line may have rewrapped int i; for (i=0; i 0 && !isspace(index(b) & 255) && index(b)!='\n') b--; else while (b > 0 && index(b)!='\n') b--; } // make sure we redraw the old selection or cursor: if (om < b) b = om; if (op < b) b = op; minimal_update(b); mark_ = position_ = undo_->undoat; set_changed(); if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED); return 1; } /** Apply the current undo/redo operation It's up to undo() and redo() to push and pop actions to and from the lists. \return 1 if the current action changed any text. \see undo(), redo() */ int Fl_Input_::apply_undo() { was_up_down = 0; if (!undo_->undocut && !undo_->undoinsert) return 0; int ilen = undo_->undocut; int xlen = undo_->undoinsert; int b = undo_->undoat-xlen; int b1 = b; minimal_update(position_); put_in_buffer(size_+ilen); if (ilen) { memmove(buffer+b+ilen, buffer+b, size_-b+1); memcpy(buffer+b, undo_->undobuffer, ilen); size_ += ilen; b += ilen; } if (xlen) { undo_->undobuffersize(xlen); memcpy(undo_->undobuffer, buffer+b, xlen); memmove(buffer+b, buffer+b+xlen, size_-xlen-b+1); size_ -= xlen; } undo_->undocut = xlen; if (xlen) undo_->undoyankcut = xlen; undo_->undoinsert = ilen; undo_->undoat = b; mark_ = b /* -ilen */; position_ = b; if (wrap()) while (b1 > 0 && index(b1)!='\n') b1--; minimal_update(b1); set_changed(); return 1; } /** Undoes previous changes to the text buffer. This call undoes a number of previous calls to replace(). \return non-zero if any change was made. */ int Fl_Input_::undo() { if (apply_undo() == 0) return 0; redo_list_->push(undo_); undo_ = undo_list_->pop(); if (!undo_) undo_ = new Fl_Input_Undo_Action(); if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED); return 1; } /** Check if the last operation can be undone. \return true if the widget can undo the last change */ bool Fl_Input_::can_undo() const { return (undo_->undocut || undo_->undoinsert); } /** Redo previous undo operation. This call reapplies previously executed undo operations. \return non-zero if any change was made. */ int Fl_Input_::redo() { Fl_Input_Undo_Action *redo_action = redo_list_->pop(); if (!redo_action) return 0; if (undo_->undocut || undo_->undoinsert) undo_list_->push(undo_); else delete undo_; undo_ = redo_action; int ret = apply_undo(); if (ret && (when()&FL_WHEN_CHANGED)) do_callback(FL_REASON_CHANGED); return ret; } /** Check if there is a redo action available. \return true if the widget can redo the last undo action */ bool Fl_Input_::can_redo() const { return (redo_list_->size() > 0); } /** Copies the \e yank buffer to the clipboard. This method copies all the previous contiguous cuts from the undo information to the clipboard. This function implements the \c ^K shortcut key. \return 0 if the operation did not change the clipboard \see copy(int), cut() */ int Fl_Input_::copy_cuts() { // put the yank buffer into the X clipboard if (!undo_->undoyankcut || input_type()==FL_SECRET_INPUT) return 0; Fl::copy(undo_->undobuffer, undo_->undoyankcut, 1); return 1; } /** \internal Checks the when() field and does a callback if indicated. */ void Fl_Input_::maybe_do_callback(Fl_Callback_Reason reason) { if (changed() || (when()&FL_WHEN_NOT_CHANGED)) { do_callback(reason); } } /** Handles all kinds of text field related events. This is called by derived classes. \todo Add comment and parameters */ int Fl_Input_::handletext(int event, int X, int Y, int W, int H) { switch (event) { case FL_ENTER: case FL_MOVE: if (active_r() && window()) window()->cursor(FL_CURSOR_INSERT); return 1; case FL_LEAVE: if (active_r() && window()) window()->cursor(FL_CURSOR_DEFAULT); return 1; case FL_FOCUS: fl_set_spot(textfont(), textsize(), x(), y(), w(), h(), window()); if (mark_ == position_) { minimal_update(size()+1); } else //if (Fl::selection_owner() != this) minimal_update(mark_, position_); return 1; case FL_UNFOCUS: if (active_r() && window()) window()->cursor(FL_CURSOR_DEFAULT); if (mark_ == position_) { if (!(damage()&FL_DAMAGE_EXPOSE)) {minimal_update(position_); erase_cursor_only = 1;} } else //if (Fl::selection_owner() != this) minimal_update(mark_, position_); // FALLTHROUGH case FL_HIDE: fl_reset_spot(); if (!readonly() && (when() & FL_WHEN_RELEASE)) maybe_do_callback(FL_REASON_LOST_FOCUS); return 1; case FL_PUSH: if (active_r() && window()) window()->cursor(FL_CURSOR_INSERT); handle_mouse(X, Y, W, H, Fl::event_state(FL_SHIFT)); if (Fl::focus() != this) { Fl::focus(this); handle(FL_FOCUS); } return 1; case FL_DRAG: handle_mouse(X, Y, W, H, 1); return 1; case FL_RELEASE: copy(0); return 1; case FL_PASTE: { // Don't allow pastes into readonly widgets... if (readonly()) { fl_beep(FL_BEEP_ERROR); return 1; } // See if we have anything to paste... if (!Fl::event_text() || !Fl::event_length()) return 1; // strip trailing control characters and spaces before pasting: const char* t = Fl::event_text(); const char* e = t+Fl::event_length(); if (input_type() != FL_MULTILINE_INPUT) while (e > t && isspace(*(e-1) & 255)) e--; if (!t || e <= t) return 1; // Int/float stuff will crash without this test if (input_type() == FL_INT_INPUT) { while (isspace(*t & 255) && t < e) t ++; const char *p = t; if (*p == '+' || *p == '-') p ++; if (strncmp(p, "0x", 2) == 0) { p += 2; while (isxdigit(*p & 255) && p < e) p ++; } else { while (isdigit(*p & 255) && p < e) p ++; } if (p < e) { fl_beep(FL_BEEP_ERROR); return 1; } else return replace(0, size(), t, (int) (e-t)); } else if (input_type() == FL_FLOAT_INPUT) { while (isspace(*t & 255) && t < e) t ++; const char *p = t; if (*p == '+' || *p == '-') p ++; while (isdigit(*p & 255) && p < e) p ++; if (*p == '.') { p ++; while (isdigit(*p & 255) && p < e) p ++; if (*p == 'e' || *p == 'E') { p ++; if (*p == '+' || *p == '-') p ++; while (isdigit(*p & 255) && p < e) p ++; } } if (p < e) { fl_beep(FL_BEEP_ERROR); return 1; } else return replace(0, size(), t, (int) (e-t)); } return replace(insert_position(), mark(), t, (int) (e-t));} case FL_SHORTCUT: if (!(shortcut() ? Fl::test_shortcut(shortcut()) : test_shortcut())) return 0; if (Fl::visible_focus() && handle(FL_FOCUS)) { Fl::focus(this); return 1; } // else fall through default: return 0; } } /*------------------------------*/ /** Creates a new Fl_Input_ widget. This function creates a new Fl_Input_ widget and adds it to the current Fl_Group. The value() is set to \c NULL. The default boxtype is \c FL_DOWN_BOX. \param X, Y, W, H the dimensions of the new widget \param l an optional label text */ Fl_Input_::Fl_Input_(int X, int Y, int W, int H, const char* l) : Fl_Widget(X, Y, W, H, l) { box(FL_DOWN_BOX); color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR); align(FL_ALIGN_LEFT); textsize_ = FL_NORMAL_SIZE; textfont_ = FL_HELVETICA; textcolor_ = FL_FOREGROUND_COLOR; cursor_color_ = FL_FOREGROUND_COLOR; // was FL_BLUE mark_ = position_ = size_ = 0; bufsize = 0; buffer = 0; value_ = ""; xscroll_ = yscroll_ = 0; maximum_size_ = 32767; shortcut_ = 0; undo_list_ = new Fl_Input_Undo_Action_List(); redo_list_ = new Fl_Input_Undo_Action_List(); undo_ = new Fl_Input_Undo_Action(); set_flag(SHORTCUT_LABEL); set_flag(MAC_USE_ACCENTS_MENU); set_flag(NEEDS_KEYBOARD); tab_nav(1); } /** Copies the value from a possibly static entry into the internal buffer. \param [in] len size of the current text */ void Fl_Input_::put_in_buffer(int len) { if (value_ == buffer && bufsize > len) { buffer[size_] = 0; return; } if (!bufsize) { if (len > size_) len += 9; // let a few characters insert before realloc bufsize = len+1; buffer = (char*)malloc(bufsize); } else if (bufsize <= len) { // we may need to move old value in case it points into buffer: int moveit = (value_ >= buffer && value_ < buffer+bufsize); // enlarge current buffer if (len > size_) { do {bufsize *= 2;} while (bufsize <= len); } else { bufsize = len+1; } // Note: the following code is equivalent to: // // if (moveit) value_ = value_ - buffer; // char* nbuffer = (char*)realloc(buffer, bufsize); // if (moveit) value_ = value_ + nbuffer; // buffer = nbuffer; // // We just optimized the pointer arithmetic for value_... // char* nbuffer = (char*)realloc(buffer, bufsize); if (moveit) value_ += (nbuffer-buffer); buffer = nbuffer; } memmove(buffer, value_, size_); buffer[size_] = 0; value_ = buffer; } /** Changes the widget text. This function changes the text and sets the mark and the point to the end of it. The string is \e not copied. If the user edits the string it is copied to the internal buffer then. This can save a great deal of time and memory if your program is rapidly changing the values of text fields, but this will only work if the passed string remains unchanged until either the Fl_Input is destroyed or value() is called again. You can use the \p len parameter to directly set the length if you know it already or want to put \c nul characters in the text. \param [in] str the new text \param [in] len the length of the new text \return non-zero if the new value is different than the current one */ int Fl_Input_::static_value(const char* str, int len) { clear_changed(); undo_->clear(); undo_list_->clear(); redo_list_->clear(); if (str == value_ && len == size_) return 0; if (len) { // non-empty new value: if (xscroll_ || yscroll_) { xscroll_ = yscroll_ = 0; minimal_update(0); } else { int i = 0; // find first different character: if (value_) { for (; i #include // Global parameters for box drawing algorithm: // // BW = box shadow width #define BW (Fl::box_shadow_width()) static void fl_shadow_frame(int x, int y, int w, int h, Fl_Color c) { fl_color(FL_DARK3); fl_rectf(x+BW, y+h-BW, w - BW, BW); fl_rectf(x+w-BW, y+BW, BW, h - BW); Fl::set_box_color(c); fl_rect(x,y,w-BW,h-BW); } static void fl_shadow_box(int x, int y, int w, int h, Fl_Color c) { Fl::set_box_color(c); fl_rectf(x,y,w-BW,h-BW); fl_shadow_frame(x,y,w,h,FL_GRAY0); } extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*, Fl_Box_Draw_Focus_F* =NULL); Fl_Boxtype fl_define_FL_SHADOW_BOX() { fl_internal_boxtype(_FL_SHADOW_FRAME, fl_shadow_frame); fl_internal_boxtype(_FL_SHADOW_BOX, fl_shadow_box); return _FL_SHADOW_BOX; } fltk-1.4.3/src/Fl_Chart.cxx0000644000175000017500000003352215004135251015607 0ustar albrechtalbrecht// // Fl_Chart widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include "flstring.h" #include // this function is in fl_boxtype.cxx: void fl_rectbound(int x, int y, int w, int h, Fl_Color color); static const double ARCINC = (2.0 * M_PI / 360.0); /** Draws a bar chart. \p x, \p y, \p w, \p h is the bounding box, \p entries the array of \p numb entries, and \p min and \p max the boundaries. \param[in] x, y, w, h Widget position and size \param[in] numb Number of values \param[in] entries Array of values \param[in] min Lower boundary \param[in] max Upper boundary \param[in] autosize Whether the chart autosizes \param[in] maxnumb Maximal number of entries \param[in] textcolor Text color */ void Fl_Chart::draw_barchart(int x, int y, int w, int h, int numb, FL_CHART_ENTRY entries[], double min, double max, int autosize, int maxnumb, Fl_Color textcolor) { double incr; int zeroh; double lh = fl_height(); if (max == min) incr = h; else incr = h / (max - min); if ((-min * incr) < lh) { incr = (h - lh + min * incr) / (max - min); zeroh = int(y + h - lh); } else { zeroh = (int)rint(y + h + min * incr); } int bwidth = (int)rint(w / double(autosize ? numb : maxnumb)); // Draw base line fl_color(textcolor); fl_line(x, zeroh, x + w, zeroh); if (min == 0.0 && max == 0.0) return; // Nothing else to draw int i; // Draw the bars for (i = 0; i < numb; i++) { int hh = (int)rint(entries[i].val * incr); if (hh < 0) fl_rectbound(x + i * bwidth, zeroh, bwidth + 1, -hh + 1, (Fl_Color)entries[i].col); else if (hh > 0) fl_rectbound(x + i * bwidth, zeroh - hh, bwidth + 1, hh + 1, (Fl_Color)entries[i].col); } // Draw the labels fl_color(textcolor); for (i = 0; i < numb; i++) fl_draw(entries[i].str, x + i * bwidth + bwidth / 2, zeroh, 0, 0, FL_ALIGN_TOP); } /** Draws a horizontal bar chart. \p x, \p y, \p w, \p h is the bounding box, \p entries the array of \p numb entries, and \p min and \p max the boundaries. \param[in] x, y, w, h Widget position and size \param[in] numb Number of values \param[in] entries Array of values \param[in] min Lower boundary \param[in] max Upper boundary \param[in] autosize Whether the chart autosizes \param[in] maxnumb Maximal number of entries \param[in] textcolor Text color */ void Fl_Chart::draw_horbarchart(int x, int y, int w, int h, int numb, FL_CHART_ENTRY entries[], double min, double max, int autosize, int maxnumb, Fl_Color textcolor) { int i; double lw = 0.0; // Maximal label width // Compute maximal label width for (i = 0; i < numb; i++) { double w1 = fl_width(entries[i].str); if (w1 > lw) lw = w1; } if (lw > 0.0) lw += 4.0; double incr; int zeroh; if (max == min) incr = w; else incr = w / (max - min); if ((-min * incr) < lw) { incr = (w - lw + min * incr) / (max - min); zeroh = x + (int)rint(lw); } else { zeroh = (int)rint(x - min * incr); } int bwidth = (int)rint(h / double(autosize ? numb : maxnumb)); // Draw base line fl_color(textcolor); fl_line(zeroh, y, zeroh, y + h); if (min == 0.0 && max == 0.0) return; // Nothing else to draw // Draw the bars for (i = 0; i < numb; i++) { int ww = (int)rint(entries[i].val * incr); if (ww > 0) fl_rectbound(zeroh, y + i * bwidth, ww + 1, bwidth + 1, (Fl_Color)entries[i].col); else if (ww < 0) fl_rectbound(zeroh + ww, y + i * bwidth, -ww + 1, bwidth + 1, (Fl_Color)entries[i].col); } // Draw the labels fl_color(textcolor); for (i = 0; i < numb; i++) fl_draw(entries[i].str, zeroh - 2, y + i * bwidth + bwidth / 2, 0, 0, FL_ALIGN_RIGHT); } /** Draws a line chart. \p x, \p y, \p w, \p h is the bounding box, \p entries the array of \p numb entries, and \p min and \p max the boundaries. \param[in] type Chart type \param[in] x, y, w, h Widget position and size \param[in] numb Number of values \param[in] entries Array of values \param[in] min Lower boundary \param[in] max Upper boundary \param[in] autosize Whether the chart autosizes \param[in] maxnumb Maximal number of entries \param[in] textcolor Text color */ void Fl_Chart::draw_linechart(int type, int x, int y, int w, int h, int numb, FL_CHART_ENTRY entries[], double min, double max, int autosize, int maxnumb, Fl_Color textcolor) { int i; double lh = fl_height(); double incr; if (max == min) incr = h - 2.0 * lh; else incr = (h - 2.0 * lh) / (max - min); int zeroh = (int)rint(y + h - lh + min * incr); double bwidth = w / double(autosize ? numb : maxnumb); // Draw the values for (i = 0; i < numb; i++) { int x0 = x + (int)rint((i - .5) * bwidth); int x1 = x + (int)rint((i + .5) * bwidth); int yy0 = i ? zeroh - (int)rint(entries[i - 1].val * incr) : 0; int yy1 = zeroh - (int)rint(entries[i].val * incr); if (type == FL_SPIKE_CHART) { fl_color((Fl_Color)entries[i].col); fl_line(x1, zeroh, x1, yy1); } else if (type == FL_LINE_CHART && i != 0) { fl_color((Fl_Color)entries[i - 1].col); fl_line(x0, yy0, x1, yy1); } else if (type == FL_FILLED_CHART && i != 0) { fl_color((Fl_Color)entries[i - 1].col); if ((entries[i - 1].val > 0.0) != (entries[i].val > 0.0)) { double ttt = entries[i - 1].val / (entries[i - 1].val - entries[i].val); int xt = x + (int)rint((i - .5 + ttt) * bwidth); fl_polygon(x0, zeroh, x0, yy0, xt, zeroh); fl_polygon(xt, zeroh, x1, yy1, x1, zeroh); } else { fl_polygon(x0, zeroh, x0, yy0, x1, yy1, x1, zeroh); } fl_color(textcolor); fl_line(x0, yy0, x1, yy1); } } // Draw base line fl_color(textcolor); fl_line(x, zeroh, x + w, zeroh); // Draw the labels for (i = 0; i < numb; i++) { fl_draw(entries[i].str, x + (int)rint((i + .5) * bwidth), zeroh - (int)rint(entries[i].val * incr), 0, 0, entries[i].val >= 0 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP); } } /** Draws a pie chart. \param[in] x,y,w,h bounding box \param[in] numb number of chart entries \param[in] entries array of chart entries \param[in] special special (?) \param[in] textcolor text color */ void Fl_Chart::draw_piechart(int x, int y, int w, int h, int numb, FL_CHART_ENTRY entries[], int special, Fl_Color textcolor) { int i; double xc, yc, rad; // center and radius double tot; // sum of values double incr; // increment in angle double curang; // current angle we are drawing double txc, tyc; // temporary center double lh = fl_height(); // compute center and radius double h_denom = (special ? 2.3 : 2.0); rad = (h - 2 * lh) / h_denom / 1.1; xc = x + w / 2.0; yc = y + h - 1.1 * rad - lh; // compute sum of values tot = 0.0; for (i = 0; i < numb; i++) { if (entries[i].val > 0.0) tot += entries[i].val; } if (tot == 0.0) return; incr = 360.0 / tot; // Draw the pie curang = 0.0; for (i = 0; i < numb; i++) { if (entries[i].val > 0.0) { txc = xc; tyc = yc; // Correct for special pies if (special && i == 0) { txc += 0.3 * rad * cos(ARCINC * (curang + 0.5 * incr * entries[i].val)); tyc -= 0.3 * rad * sin(ARCINC * (curang + 0.5 * incr * entries[i].val)); } fl_color((Fl_Color)entries[i].col); fl_begin_polygon(); fl_vertex(txc, tyc); fl_arc(txc, tyc, rad, curang, curang + incr * entries[i].val); fl_end_polygon(); fl_color(textcolor); fl_begin_loop(); fl_vertex(txc, tyc); fl_arc(txc, tyc, rad, curang, curang + incr * entries[i].val); fl_end_loop(); curang += 0.5 * incr * entries[i].val; // draw the label double xl = txc + 1.1 * rad * cos(ARCINC * curang); fl_draw(entries[i].str, (int)rint(xl), (int)rint(tyc - 1.1 * rad * sin(ARCINC * curang)), 0, 0, xl < txc ? FL_ALIGN_RIGHT : FL_ALIGN_LEFT); curang += 0.5 * incr * entries[i].val; } } } /** Draws the Fl_Chart widget. */ void Fl_Chart::draw() { draw_box(); Fl_Boxtype b = box(); int xx = x() + Fl::box_dx(b); int yy = y() + Fl::box_dy(b); int ww = w() - Fl::box_dw(b); int hh = h() - Fl::box_dh(b); fl_push_clip(xx, yy, ww, hh); ww--; hh--; // adjust for line thickness if (min >= max) { min = max = 0.0; for (int i = 0; i < numb; i++) { if (entries[i].val < min) min = entries[i].val; if (entries[i].val > max) max = entries[i].val; } } fl_font(textfont(), textsize()); switch (type()) { case FL_BAR_CHART: ww++; // makes the bars fill box correctly draw_barchart(xx, yy, ww, hh, numb, entries, min, max, autosize(), maxnumb, textcolor()); break; case FL_HORBAR_CHART: hh++; // makes the bars fill box correctly draw_horbarchart(xx, yy, ww, hh, numb, entries, min, max, autosize(), maxnumb, textcolor()); break; case FL_PIE_CHART: draw_piechart(xx, yy, ww, hh, numb, entries, 0, textcolor()); break; case FL_SPECIALPIE_CHART: draw_piechart(xx, yy, ww, hh, numb, entries, 1, textcolor()); break; default: draw_linechart(type(), xx, yy, ww, hh, numb, entries, min, max, autosize(), maxnumb, textcolor()); break; } draw_label(); fl_pop_clip(); } /** Create a new Fl_Chart widget using the given position, size and label string. The default boxstyle is \c FL_NO_BOX. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Chart::Fl_Chart(int X, int Y, int W, int H, const char *L) : Fl_Widget(X, Y, W, H, L) { box(FL_BORDER_BOX); align(FL_ALIGN_BOTTOM); numb = 0; maxnumb = 0; sizenumb = FL_CHART_MAX; autosize_ = 1; min = max = 0; textfont_ = FL_HELVETICA; textsize_ = 10; textcolor_ = FL_FOREGROUND_COLOR; entries = (FL_CHART_ENTRY *)calloc(sizeof(FL_CHART_ENTRY), FL_CHART_MAX + 1); } /** Destroys the Fl_Chart widget and all of its data. */ Fl_Chart::~Fl_Chart() { free(entries); } /** Removes all values from the chart. */ void Fl_Chart::clear() { numb = 0; min = max = 0; redraw(); } /** Adds the data value \p val with optional label \p str and color \p col to the chart. \param[in] val data value \param[in] str optional data label \param[in] col optional data color */ void Fl_Chart::add(double val, const char *str, unsigned col) { // Allocate more entries if required if (numb >= sizenumb) { sizenumb += FL_CHART_MAX; entries = (FL_CHART_ENTRY *)realloc(entries, sizeof(FL_CHART_ENTRY) * (sizenumb + 1)); } // Shift entries as needed if (numb >= maxnumb && maxnumb > 0) { memmove(entries, entries + 1, sizeof(FL_CHART_ENTRY) * (numb - 1)); numb--; } entries[numb].val = float(val); entries[numb].col = col; if (str) { strlcpy(entries[numb].str, str, FL_CHART_LABEL_MAX + 1); } else { entries[numb].str[0] = 0; } numb++; redraw(); } /** Inserts a data value \p val at the given position \p ind. Position 1 is the first data value. \param[in] ind insertion position \param[in] val data value \param[in] str optional data label \param[in] col optional data color */ void Fl_Chart::insert(int ind, double val, const char *str, unsigned col) { int i; if (ind < 1 || ind > numb + 1) return; // Allocate more entries if required if (numb >= sizenumb) { sizenumb += FL_CHART_MAX; entries = (FL_CHART_ENTRY *)realloc(entries, sizeof(FL_CHART_ENTRY) * (sizenumb + 1)); } // Shift entries as needed for (i = numb; i >= ind; i--) entries[i] = entries[i - 1]; if (numb < maxnumb || maxnumb == 0) numb++; // Fill in the new entry entries[ind - 1].val = float(val); entries[ind - 1].col = col; if (str) { strlcpy(entries[ind - 1].str, str, FL_CHART_LABEL_MAX + 1); } else { entries[ind - 1].str[0] = 0; } redraw(); } /** Replaces a data value \p val at the given position \p ind. Position 1 is the first data value. \param[in] ind insertion position \param[in] val data value \param[in] str optional data label \param[in] col optional data color */ void Fl_Chart::replace(int ind, double val, const char *str, unsigned col) { if (ind < 1 || ind > numb) return; entries[ind - 1].val = float(val); entries[ind - 1].col = col; if (str) { strlcpy(entries[ind - 1].str, str, FL_CHART_LABEL_MAX + 1); } else { entries[ind - 1].str[0] = 0; } redraw(); } /** Sets the lower and upper bounds of the chart values. \param[in] a, b are used to set lower, upper */ void Fl_Chart::bounds(double a, double b) { this->min = a; this->max = b; redraw(); } /** Sets the maximum number of data values for a chart. If you do not call this method then the chart will be allowed to grow to any size depending on available memory. \param[in] m maximum number of data values allowed. */ void Fl_Chart::maxsize(int m) { int i; // Fill in the new number if (m < 0) return; maxnumb = m; // Shift entries if required if (numb > maxnumb) { for (i = 0; i < maxnumb; i++) entries[i] = entries[i + numb - maxnumb]; numb = maxnumb; redraw(); } } fltk-1.4.3/src/Fl_Menu_add.cxx0000644000175000017500000004477615004135251016277 0ustar albrechtalbrecht// // Menu utilities for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Methods to alter the menu in an Fl_Menu_ widget. // These are for Forms emulation and for dynamically changing the // menus. They are in this source file so they are not linked in if // not used, which is what will happen if the program only uses // constant menu tables. // Not at all guaranteed to be Forms compatible, especially with any // string with a % sign in it! #include #include #include "flstring.h" #include #include // If the array is this, we will double-reallocate as necessary: static Fl_Menu_Item* local_array = 0; static int local_array_alloc = 0; // number allocated static int local_array_size = 0; // == size(local_array) extern Fl_Menu_* fl_menu_array_owner; // in Fl_Menu_.cxx // For historical reasons there are matching methods that work on a // user-allocated array of Fl_Menu_Item. These methods are quite // depreciated and should not be used. These old methods use the // above pointers to detect if the array belongs to an Fl_Menu_ // widget, and if so it reallocates as necessary. // Insert a single Fl_Menu_Item into an array of size at offset n, // if this is local_array it will be reallocated if needed. static Fl_Menu_Item* array_insert( Fl_Menu_Item* array, // array to modify int size, // size of array int n, // index of new insert position const char *text, // text of new item (copy is made) int flags // flags for new item ) { if (array == local_array && size >= local_array_alloc) { local_array_alloc = 2*size; Fl_Menu_Item* newarray = new Fl_Menu_Item[local_array_alloc]; memmove(newarray, array, size*sizeof(Fl_Menu_Item)); delete[] local_array; local_array = array = newarray; } // move all the later items: memmove(array+n+1, array+n, sizeof(Fl_Menu_Item)*(size-n)); // create the new item: Fl_Menu_Item* m = array+n; m->text = text ? fl_strdup(text) : 0; m->shortcut_ = 0; m->callback_ = 0; m->user_data_ = 0; m->flags = flags; m->labeltype_ = m->labelsize_ = m->labelcolor_ = 0; m->labelfont_ = FL_HELVETICA; return array; } // Comparison that does not care about deleted '&' signs: static int compare(const char* a, const char* b) { for (;;) { int n = *a-*b; if (n) { if (*a == '&') a++; else if (*b == '&') b++; else return n; } else if (*a) { a++; b++; } else { return 0; } } } /** Adds a menu item. The text is split at '/' characters to automatically produce submenus (actually a totally unnecessary feature as you can now add submenu titles directly by setting FL_SUBMENU in the flags). \returns the index into the menu() array, where the entry was added \see Fl_Menu_Item::insert(int, const char*, int, Fl_Callback*, void*, int) */ int Fl_Menu_Item::add( const char *mytext, int sc, Fl_Callback *cb, void *data, int myflags ) { return(insert(-1,mytext,sc,cb,data,myflags)); // -1: append } /** Inserts an item at position \p index. If \p index is -1, the item is added the same way as Fl_Menu_Item::add(). If 'mytext' contains any un-escaped front slashes (/), it's assumed a menu pathname is being specified, and the value of \p index will be ignored. In all other aspects, the behavior of insert() is the same as add(). \param[in] index insert new items here \param[in] mytext new label string, details see above \param[in] sc keyboard shortcut for new item \param[in] cb callback function for new item \param[in] data user data for new item \param[in] myflags menu flags as described in Fl_Menu_Item \returns the index into the menu() array, where the entry was added */ int Fl_Menu_Item::insert( int index, const char *mytext, int sc, Fl_Callback *cb, void *data, int myflags ) { Fl_Menu_Item *array = this; Fl_Menu_Item *m = this; const char *p; char *q; char buf[1024]; int msize = array==local_array ? local_array_size : array->size(); int flags1 = 0; const char* item; // split at slashes to make submenus: for (;;) { // leading slash makes us assume it is a filename: if (*mytext == '/') {item = mytext; break;} // leading underscore causes divider line: if (*mytext == '_') {mytext++; flags1 = FL_MENU_DIVIDER;} // copy to buf, changing \x to x: q = buf; for (p=mytext; *p && *p != '/'; *q++ = *p++) if (*p=='\\' && p[1]) p++; *q = 0; item = buf; if (*p != '/') break; /* not a menu title */ index = -1; /* any submenu specified overrides insert position */ mytext = p+1; /* point at item title */ /* find a matching menu title: */ for (; m->text; m = m->next()) if (m->flags&FL_SUBMENU && !compare(item, m->text)) break; if (!m->text) { /* create a new menu */ int n = (int)(m-array); /* index is not used if label contains a path */ array = array_insert(array, msize, n, item, FL_SUBMENU|flags1); msize++; array = array_insert(array, msize, n+1, 0, 0); msize++; m = array+n; } m++; /* go into the submenu */ flags1 = 0; } /* find a matching menu item: */ for (; m->text; m = m->next()) if (!(m->flags&FL_SUBMENU) && !compare(m->text,item)) break; if (!m->text) { /* add a new menu item */ int n = (index==-1) ? (int) (m-array) : index; array = array_insert(array, msize, n, item, myflags|flags1); msize++; if (myflags & FL_SUBMENU) { // add submenu delimiter array = array_insert(array, msize, n+1, 0, 0); msize++; } m = array+n; } /* fill it in */ m->shortcut_ = sc; m->callback_ = cb; m->user_data_ = data; m->flags = myflags|flags1; if (array == local_array) local_array_size = msize; return (int) (m-array); } /** Adds a new menu item. \param[in] label The text label for the menu item. \param[in] shortcut Optional keyboard shortcut that can be an int or string: (FL_CTRL+'a') or "^a". Default 0 if none. \param[in] callback Optional callback invoked when user clicks the item. Default 0 if none. \param[in] userdata Optional user data passed as an argument to the callback. Default 0 if none. \param[in] flags Optional flags that control the type of menu item; see below. Default is 0 for none. \returns The index into the menu() array, where the entry was added. \par Description If the menu array was directly set with menu(x), then copy() is done to make a private array. \par Since this method can change the internal menu array, any menu item pointers or indices the application may have cached can become stale, and should be recalculated/refreshed. \par A menu item's callback must not add() items to its parent menu during the callback. Due to backwards compatibility and historical restrictions we recommend to use either - static menu arrays that are not extended during runtime or - dynamic, extendable menu item arrays that are entirely created by using add() or insert(). This ensures that all menu arrays and strings are copied to internal storage and released when required. \note If you create menus from static Fl_Menu_Item arrays and add() or insert() more menu items later, then the menu array is copied to local storage but some local (static) strings may appear to "leak memory". This is a known issue and discouraged usage (see description above) but the impact on memory usage should typically be small. Detailed Description of Parameters \par label The menu item's label. This argument is required and must not be NULL. \par The characters "&", "/", "\", and "_" are treated as special characters in the label string. The "&" character specifies that the following character is an accelerator and will be underlined. The "\" character is used to escape the next character in the string. Labels starting with the "_" character cause a divider to be placed after that menu item. \par A label of the form "File/Quit" will create the submenu "File" with a menu item called "Quit". \par The label string is copied to new memory and can be freed. The other arguments (including the shortcut) are copied into the menu item unchanged. \par If an item exists already with that name then it is replaced with this new one. Otherwise this new one is added to the end of the correct menu or submenu. The return value is the offset into the array that the new entry was placed at. \par shortcut The keyboard shortcut for this menu item. \par This parameter is optional, and defaults to 0 to indicate no shortcut. \par The shortcut can either be a raw integer value (eg. FL_CTRL+'A') or a string (eg. "^c" or "^97"). \par Raw integer shortcuts can be a combination of keyboard chars (eg. 'A') and optional keyboard modifiers (see Fl::event_state(), e.g. FL_SHIFT, etc). In addition, FL_COMMAND can be used to denote FL_META under Mac OS X and FL_CTRL under other platforms. \par String shortcuts can be specified in one of two ways: \par \verbatim [#+^] e.g. "97", "^97", "+97", "#97" [#+^] e.g. "a", "^a", "+a", "#a" \endverbatim \par ..where \ is a decimal value representing an ASCII character (eg. 97 is the ascii code for 'a'), and the optional prefixes enhance the value that follows. Multiple prefixes must appear in the order below. \par \verbatim # - Alt + - Shift ^ - Control \endverbatim \par Internally, the text shortcuts are converted to integer values using fl_old_shortcut(const char*). \par callback The callback to invoke when this menu item is selected. \par This parameter is optional, and defaults to 0 for no callback. \par userdata The callback's 'user data' that is passed to the callback. \par This parameter is optional, and defaults to 0. \par flags These are bit flags to define what kind of menu item this is. \par This parameter is optional, and defaults to 0 to define a 'regular' menu item. \par These flags can be 'OR'ed together: \code FL_MENU_INACTIVE // Deactivate menu item (gray out) FL_MENU_TOGGLE // Item is a checkbox toggle (shows checkbox for on/off state) FL_MENU_VALUE // The on/off state for checkbox/radio buttons (if set, state is 'on') FL_MENU_RADIO // Item is a radio button (one checkbox of many can be on) FL_MENU_INVISIBLE // Item will not show up (shortcut will work) FL_SUBMENU_POINTER // Indicates user_data() is a pointer to another menu array FL_SUBMENU // This item is a submenu to other items FL_MENU_DIVIDER // Creates divider line below this item. Also ends a group of radio buttons. \endcode \par All other bits in \p 'flags' are reserved and must not be used. If FL_SUBMENU is set in an item's flags, then actually two items are added: - the first item is the menu item (submenu title), as expected, and - the second item is the submenu terminating item with the label and all other members set to 0. If you add submenus with the 'path' technique, then the corresponding submenu terminators (maybe more than one) are added as well. \todo Raw integer shortcut needs examples. Dependent on responses to https://www.fltk.org/newsgroups.php?gfltk.coredev+v:10086 and results of STR#2344 */ int Fl_Menu_::add(const char *label,int shortcut,Fl_Callback *callback,void *userdata,int flags) { return(insert(-1,label,shortcut,callback,userdata,flags)); // -1: append } /** Inserts a new menu item at the specified \p index position. If \p index is -1, the menu item is appended; same behavior as add(). To properly insert a menu item, \p label must be the name of the item (eg. "Quit"), and not a 'menu pathname' (eg. "File/Quit"). If a menu pathname is specified, the value of \p index is \em ignored, the new item's position defined by the pathname. For more details, see add(). Except for the \p index parameter, add() has more detailed information on parameters and behavior, and is functionally equivalent. \param[in] index The menu array's index position where the new item is inserted. If -1, behavior is the same as add(). \param[in] label The text label for the menu item. If the label is a menu pathname, \p index is ignored, and the pathname indicates the position of the new item. \param[in] shortcut Optional keyboard shortcut. Can be an int (FL_CTRL+'a') or a string ("^a"). Default is 0. \param[in] callback Optional callback invoked when user clicks the item. Default 0 if none. \param[in] userdata Optional user data passed as an argument to the callback. Default 0 if none. \param[in] flags Optional flags that control the type of menu item; see add() for more info. Default is 0 for none. \returns The index into the menu() array, where the entry was added. \see add() */ int Fl_Menu_::insert( int index, const char *label, int shortcut, Fl_Callback *callback, void *userdata, int flags ) { // make this widget own the local array: if (this != fl_menu_array_owner) { if (fl_menu_array_owner) { fl_menu_array_owner->menu_end(); } if (menu_) { // this already has a menu array, use it as the local one: delete[] local_array; if (!alloc) copy(menu_); // duplicate a user-provided static array // add to the menu's current array: local_array_alloc = local_array_size = size(); local_array = menu_; } else { // start with a blank array: alloc = 2; // indicates that the strings can be freed if (local_array) { menu_ = local_array; } else { local_array_alloc = 15; local_array = menu_ = new Fl_Menu_Item[local_array_alloc]; memset(local_array, 0, sizeof(Fl_Menu_Item) * local_array_alloc); } memset(menu_, 0, sizeof(Fl_Menu_Item)); local_array_size = 1; } fl_menu_array_owner = this; } int r = menu_->insert(index,label,shortcut,callback,userdata,flags); // if it rellocated array we must fix the pointer: int value_offset = (int) (value_-menu_); menu_ = local_array; // in case it reallocated it if (value_) value_ = menu_+value_offset; return r; } /** This is a Forms (and SGI GL library) compatible add function, it adds many menu items, with '|' separating the menu items, and tab separating the menu item names from an optional shortcut string. The passed string is split at any '|' characters and then add(s,0,0,0,0) is done with each section. This is often useful if you are just using the value, and is compatible with Forms and other GL programs. The section strings use the same special characters as described for the long version of add(). No items must be added to a menu during a callback to the same menu. \param str string containing multiple menu labels as described above \returns the index into the menu() array, where the entry was added */ int Fl_Menu_::add(const char *str) { char buf[1024]; int r = 0; while (*str) { int sc = 0; char *c; for (c = buf; c < (buf + sizeof(buf) - 2) && *str && *str != '|'; str++) { if (*str == '\t') {*c++ = 0; sc = fl_old_shortcut(str);} else *c++ = *str; } *c = 0; r = add(buf, sc, 0, 0, 0); if (*str) str++; } return r; } /** Changes the text of item \p i. This is the only way to get slash into an add()'ed menu item. If the menu array was directly set with menu(x) then copy() is done to make a private array. \param i index into menu array \param str new label for menu item at index i */ void Fl_Menu_::replace(int i, const char *str) { if (i<0 || i>=size()) return; if (!alloc) copy(menu_); if (alloc > 1) { free((void *)menu_[i].text); str = fl_strdup(str?str:""); } menu_[i].text = str; } /** Deletes item \p i from the menu. If the menu array was directly set with menu(x) then copy() is done to make a private array. No items must be removed from a menu during a callback to the same menu. \param i index into menu array */ void Fl_Menu_::remove(int i) { int n = size(); if (i<0 || i>=n) return; if (!alloc) copy(menu_); // find the next item, skipping submenus: Fl_Menu_Item* item = menu_+i; const Fl_Menu_Item* next_item = item->next(); // delete the text only if all items were created with add(): if (alloc > 1) { for (Fl_Menu_Item* m = item; m < next_item; m++) if (m->text) free((void*)(m->text)); } // MRS: "n" is the menu size(), which includes the trailing NULL entry... memmove(item, next_item, (menu_+n-next_item)*sizeof(Fl_Menu_Item)); } /** Finishes menu modifications and returns menu(). Call menu_end() after using add(), insert(), remove(), or any other methods that may change the menu array if you want to access the menu array anytime later with menu(). This should be called only once after the \b last menu modification for performance reasons. Does nothing if the menu array is already in a private location. Some methods like Fl_Menu_Button::popup() call this method before their menu is opened. \note After menu changes like add(), insert(), etc. menu() would return a pointer to a temporary internal menu array that may be relocated at unexpected times. This is due to performance considerations and may be changed w/o further notice. \since 1.4.0 \returns New Fl_Menu_Item array pointer. \see Fl_Menu_::menu() */ const Fl_Menu_Item *Fl_Menu_::menu_end() { if (menu_ == local_array && fl_menu_array_owner == this) { // copy the menu array to a private correctly-sized array: int value_offset = (int)(value_ - local_array); int n = local_array_size; Fl_Menu_Item* newMenu = menu_ = new Fl_Menu_Item[n]; memcpy(newMenu, local_array, n * sizeof(Fl_Menu_Item)); if (value_) value_ = newMenu + value_offset; fl_menu_array_owner = 0; } return menu_; } fltk-1.4.3/src/Fl_Grid.cxx0000644000175000017500000007675715004135251015454 0ustar albrechtalbrecht// // Fl_Grid widget for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2022 by Albrecht Schlosser. // Copyright 2022-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file src/Fl_Grid.cxx Implements the Fl_Grid container widget. \since 1.4.0 */ #include #include // private class Col for column management class Fl_Grid::Col { friend class Fl_Grid; int minw_; // minimal size (width) int w_; // calculated size (width) short weight_; // weight used to allocate extra space short gap_; // gap to the right of the column Col() { minw_ = 0; w_ = 0; weight_ = 50; gap_ = -1; } ~Col() {}; }; // private class Row for row management class Fl_Grid::Row { friend class Fl_Grid; Cell *cells_; // cells of this row int minh_; // minimal size (height) int h_; // calculated size (height) short weight_; // weight used to allocate extra space short gap_; // gap below the row (-1 = use default) Row() { cells_ = NULL; minh_ = 0; h_ = 0; weight_ = 50; gap_ = -1; } ~Row() { free_cells(); }; // Fl_Grid::Row::free_cells() - free all cells of a row void free_cells() { Cell *cel = cells_; while (cel) { Cell *next = cel->next(); delete cel; cel = next; } // free_cells() cells_ = 0; } // Fl_Grid::Row::remove_cell() - remove all cells of column col from the list of cells void remove_cell(int col) { // Cell *cel = cells_; Cell *prev = 0; while (cel) { Cell *next = cel->next(); if (cel->col() == col) { if (prev) { prev->next(next); } else { cells_ = next; } delete cel; return; } else { prev = cel; cel = next; } } // while (cel) } // Row::remove_cell(col) }; // class Row /** Create a new Fl_Grid widget. \todo More documentation of Fl_Grid constructor? */ Fl_Grid::Fl_Grid(int X, int Y, int W, int H, const char *L) : Fl_Group(X, Y, W, H, L) { init(); box(FL_FLAT_BOX); } // private: init vars void Fl_Grid::init() { rows_ = 0; cols_ = 0; margin_left_ = 0; margin_top_ = 0; margin_right_ = 0; margin_bottom_ = 0; gap_row_ = 0; gap_col_ = 0; Cols_ = 0; Rows_ = 0; old_size = Fl_Rect(0, 0, 0, 0); need_layout_ = false; // no need to calculate layout grid_color = (Fl_Color)0xbbeebb00; // light green draw_grid_ = false; // don't draw grid helper lines if (fl_getenv("FLTK_GRID_DEBUG")) draw_grid_ = true; } Fl_Grid::~Fl_Grid() { delete[] Cols_; delete[] Rows_; } /** Set the basic layout parameters of the Fl_Grid widget. You need to specify at least \p rows and \p cols to define a layout before you can add widgets to the grid. Parameters \p margin and \p gap are optional. You can call layout(int rows, int cols, int margin, int gap) again to change the layout but this is inefficient since all cells are reallocated if the layout changed. Calling this with the same values of \p rows and \p cols is fast and can be used to change \p margin and \p gap w/o reallocating the cells. \p margin sets all margins (left, top, right, bottom) to the same value. Negative values (e.g. -1) don't change the established margins. The default value set by the constructor is 0. \p gap sets row and column gaps to the same value. Negative values (e.g. -1) do not affect the established gaps. The default value set by the constructor is 0. After you added all widgets you must call layout() once without arguments to calculate the actual layout and to position and resize all widgets. \todo Document when and why to call layout() w/o args. See Fl_Flex::layout() \param[in] rows number of rows \param[in] cols number of columns \param[in] margin margin size inside the Fl_Grid's border \param[in] gap gap size between cells \see Fl_Grid::layout() */ void Fl_Grid::layout(int rows, int cols, int margin, int gap) { if (margin >= 0) margin_left_ = margin_top_ = margin_right_ = margin_bottom_ = margin; if (gap >= 0) gap_row_ = gap_col_ = gap; if (cols == cols_ && rows == rows_) // same size, nothing to do return; // release allocated memory if either rows <= 0 or cols <= 0 if (rows <= 0 || cols <= 0) { clear_layout(); return; } // allocate new cells, rows, and columns // Cell *new_cells = new Cell[rows * cols]; // reallocate and copy old columns if (cols != cols_) { Col *new_cols = new Col[cols]; for (int c = 0; c < cols; c++) { if (c < cols_) new_cols[c] = Cols_[c]; else break; } delete[] Cols_; Cols_ = new_cols; } // reallocate and copy old rows if (rows != rows_) { Row *new_rows = new Row[rows]; Row *row = Rows_; for (int r = 0; r < rows; r++, row++) { if (r < rows_) { new_rows[r] = *row; row->cells_ = 0; } else { break; } } delete[] Rows_; Rows_ = new_rows; } // store new layout and cells cols_ = cols; rows_ = rows; need_layout(1); } // layout(int, int, int, int) /** Draws the grid helper lines for design and debugging purposes. This method is protected so it can be modified in subclasses. */ void Fl_Grid::draw_grid() { int x0 = x() + Fl::box_dx(box()) + margin_left_; int y0 = y() + Fl::box_dy(box()) + margin_top_; int x1 = x() + w() - Fl::box_dx(box()) - margin_right_; int y1 = y() + h() - Fl::box_dy(box()) - margin_bottom_; fl_line_style(FL_SOLID, 1); fl_color(grid_color); // draw total layout frame fl_rect(x0, y0, x1 - x0, y1 - y0); // draw horizontal lines (gap = 0) or rectangles (gap > 0) for (int r = 0; r < rows_ - 1; r++) { int gap = Rows_[r].gap_ >= 0 ? Rows_[r].gap_ : gap_row_; y0 += Rows_[r].h_; if (gap == 0) { fl_xyline(x0, y0, x1); } else { fl_rectf(x0, y0, x1 - x0, gap); } y0 += gap; } // draw vertical lines (gap = 0) or rectangles (gap > 0) x0 = x() + Fl::box_dx(box()) + margin_left_; y0 = y() + Fl::box_dy(box()) + margin_top_; for (int c = 0; c < cols_ - 1; c++) { int gap = Cols_[c].gap_ >= 0 ? Cols_[c].gap_ : gap_col_; x0 += Cols_[c].w_; if (gap == 0) { fl_yxline(x0, y0, y1); } else { fl_rectf(x0, y0, gap, y1 - y0); } x0 += gap; } fl_line_style(FL_SOLID, 0); fl_color(FL_BLACK); } // Fl_Grid::draw_grid() /** Draws the Fl_Grid widget and all children. If the layout has been changed layout() is called before the widget is drawn so all children are arranged as designed. \see layout() \see need_layout() */ void Fl_Grid::draw() { if (need_layout()) layout(); if (damage() & ~FL_DAMAGE_CHILD) { // draw the entire widget draw_box(); if (draw_grid_) draw_grid(); draw_label(); } draw_children(); } // Fl_Grid::draw() /** Calculate the grid layout and resize and position all widgets. This is called automatically when the Fl_Grid is resized. You need to call it once after you added widgets or moved widgets between cells. Calling it once after all modifications are completed is enough. \todo Document when and why to call layout() w/o args. See Fl_Flex::layout() \see Fl_Grid::layout(int rows, int cols, int margin, int gap) */ void Fl_Grid::layout() { if (rows_ == 0 || cols_ == 0) // empty grid return; Row *row; Col *col; Cell *cel; // calculate the total available space w/o borders and margins int tw = w() - Fl::box_dw(box()) - margin_left_ - margin_right_; int th = h() - Fl::box_dh(box()) - margin_top_ - margin_bottom_; // initialize column widths and row heights col = Cols_; for (int c = 0; c < cols_; c++, col++) { col->w_ = col->minw_; } row = Rows_; for (int r = 0; r < rows_; r++, row++) { row->h_ = row->minh_; } // calculate minimal column widths and row heights (in one loop) row = Rows_; for (int r = 0; r < rows_; r++, row++) { col = Cols_; for (int c = 0; c < cols_; c++, col++) { cel = cell(r, c); if (cel) { Fl_Widget *wi = cel->widget_; if (wi && wi->visible()) { if (cel->colspan_ == 1 && cel->w_ > col->w_) col->w_ = cel->w_; if (cel->rowspan_ == 1 && cel->h_ > row->h_) row->h_ = cel->h_; } // widget } // colspan && rowspan } // cols } // rows // calculate total space occupied by rows and columns including gaps int tcwi = 0; // total column width incl. gaps int tcwe = 0; // total column weight int hcwe = 0; // highest column weight int icwe = 0; // index of column with highest weight int trhe = 0; // total row height incl. gaps int trwe = 0; // total row weight int hrwe = 0; // highest row weight int irwe = 0; // index of row with highest weight col = Cols_; for (int c = 0; c < cols_; c++, col++) { tcwi += col->w_; tcwe += col->weight_; if (c < cols_ - 1) tcwi += ((col->gap_ >= 0) ? col->gap_ : gap_col_); if (col->weight_ > hcwe) { hcwe = col->weight_; icwe = c; } } row = Rows_; for (int r = 0; r < rows_; r++, row++) { trhe += row->h_; trwe += row->weight_; if (r < rows_ - 1) trhe += ((row->gap_ >= 0) ? row->gap_ : gap_row_); if (row->weight_ > hrwe) { hrwe = row->weight_; irwe = r; } } // Add extra space to columns and rows to fill the entire grid, using relative weights. // Rounding differences are added to or subtracted from the col/row with the highest weight. int space = tw - tcwi; // additional space for columns int add_space = 0; // used for calculation int remaining = 0; // remaining space if (space > 0 && tcwe > 0) { remaining = space; col = Cols_; for (int c = 0; c < cols_; c++, col++) { if (col->weight_ > 0) { add_space = int(float(space * col->weight_) / tcwe + 0.5); col->w_ += add_space; remaining -= add_space; } } if (remaining != 0) Cols_[icwe].w_ += remaining; } space = th - trhe; // additional space for rows if (space > 0 && trwe > 0) { remaining = space; row = Rows_; for (int r = 0; r < rows_; r++, row++) { if (row->weight_ > 0) { add_space = int(float(space * row->weight_) / trwe + 0.5); row->h_ += add_space; remaining -= add_space; } } if (remaining != 0) Rows_[irwe].h_ += remaining; } // calculate and assign widget positions and sizes int x0, y0; // starting x/y positions y0 = y() + Fl::box_dy(box()) + margin_top_; row = Rows_; for (int r = 0; r < rows_; r++, row++) { x0 = x() + Fl::box_dx(box()) + margin_left_; col = Cols_; for (int c = 0; c < cols_; c++, col++) { int wx = x0; // widget's x int wy = y0; // widget's y cel = cell(r, c); if (cel) { Fl_Widget *wi = cel->widget_; if (wi && wi->visible()) { // calculate the cell's position and size, take cell spanning into account int ww = col->w_; int wh = row->h_; for (int i = 0; i < cel->colspan_ - 1; i++) { ww += (Cols_[c + i].gap_ >= 0) ? Cols_[c + i].gap_ : gap_col_; ww += Cols_[c + i + 1].w_; } for (int i = 0; i < cel->rowspan_ - 1; i++) { wh += (Rows_[r + i].gap_ >= 0) ? Rows_[r + i].gap_ : gap_row_; wh += Rows_[r + i + 1].h_; } // horizontal alignment: left + right => stretch Fl_Grid_Align ali = cel->align_; Fl_Grid_Align mask; mask = FL_GRID_LEFT | FL_GRID_RIGHT | FL_GRID_HORIZONTAL; if ((ali & mask) == 0) { wx += (ww - cel->w_) / 2; ww = cel->w_; } else if ((ali & mask) == FL_GRID_LEFT) { ww = cel->w_; } else if ((ali & mask) == FL_GRID_RIGHT) { wx += ww - cel->w_; ww = cel->w_; } // vertical alignment: top + bottom => stretch mask = FL_GRID_TOP | FL_GRID_BOTTOM | FL_GRID_VERTICAL; if ((ali & mask) == 0) { wy += (wh - cel->h_) / 2; wh = cel->h_; } else if ((ali & mask) == FL_GRID_TOP) { wh = cel->h_; } else if ((ali & mask) == FL_GRID_BOTTOM) { wy += wh - cel->h_; wh = cel->h_; } wi->resize(wx, wy, ww, wh); } // widget is visible } // cell x0 += (col->w_ + ((col->gap_ >= 0) ? col->gap_ : gap_col_)); } // cols y0 += ( row->h_ + ((row->gap_ >= 0) ? row->gap_ : gap_row_) ); } // rows need_layout(0); redraw(); } // layout() /** Fl_Group calls this method when a child widget is about to be removed. Make sure that the widget is also removed from our internal list of children. */ void Fl_Grid::on_remove(int index) { Fl_Widget *wi = child(index); Cell *c = cell(wi); // find the cell of this child if (c) { remove_cell(c->row_, c->col_); } } // private: add a new cell to the grid Fl_Grid::Cell *Fl_Grid::add_cell(int row, int col) { Cell *c = new Cell(row, col); Row *r = &Rows_[row]; Cell* cel = r->cells_; // "current" cell Cell* prev = 0; // "previous" cell while (cel) { // existing cells if (cel->col_ > col) { // found spot ... break; } prev = cel; cel = cel->next_; } // insertion point: prev => last cell or NULL, cel == next cell or NULL if (prev) prev->next_ = c; else r->cells_ = c; c->next_ = cel; need_layout(1); return c; } // private: remove a cell from the grid void Fl_Grid::remove_cell(int row, int col) { Row *r = &Rows_[row]; r->remove_cell(col); need_layout(1); } /** Recalculate the layout and position and resize all widgets. This method overrides Fl_Group::resize() and calculates all positions and sizes of its children according to its own rules. \param[in] X,Y new widget position \param[in] W,H new widget size */ void Fl_Grid::resize(int X, int Y, int W, int H) { old_size = Fl_Rect(x(), y(), w(), h()); Fl_Widget::resize(X, Y, W, H); layout(); } /** Reset the layout w/o removing widgets. Removes all cells and sets rows and cols to zero. Existing widgets are kept as children of the Fl_Group (base class) but are hidden. This method should be rarely used. You may want to call Fl_Grid::clear() to remove all widgets and reset the layout to zero rows and columns. You must call layout(int rows, int cols, ...) to set a new layout, allocate new cells, and assign widgets to new cells. \todo Fl_Grid::clear() needs to be implemented as documented above! */ void Fl_Grid::clear_layout() { delete[] Cols_; delete[] Rows_; init(); for (int i = 0; i < children(); i++) { child(i)->hide(); } need_layout(1); return; } /** Set all margins (left, top, right, bottom). All margins are measured in pixels inside the box borders. You need to specify at least one argument, all other arguments are optional. If you don't specify an argument or use a negative value (e.g. -1) then that particular margin is not affected. \param[in] left left margin \param[in] top top margin \param[in] right right margin \param[in] bottom bottom margin */ void Fl_Grid::margin(int left, int top, int right, int bottom) { if (left >= 0) margin_left_ = left; if (top >= 0) margin_top_ = top; if (right >= 0) margin_right_ = right; if (bottom >= 0) margin_bottom_ = bottom; need_layout(1); } /** Returns all outside margin sizes of the grid. All margin sizes are returned in the given arguments. If any argument is \p NULL the respective value is not returned. \param[out] left returns left margin if not \p NULL \param[out] top returns top margin if not \p NULL \param[out] right returns right margin if not \p NULL \param[out] bottom returns bottom margin if not \p NULL \return whether all margins are equal \retval 1 all margins have the same size \retval 0 at least one margin has a different size */ int Fl_Grid::margin(int *left, int *top, int *right, int *bottom) const { if (left) *left = margin_left_; if (top) *top = margin_top_; if (right) *right = margin_right_; if (bottom) *bottom = margin_bottom_; if (margin_left_ == margin_top_ && margin_top_ == margin_right_ && margin_right_ == margin_bottom_) return 1; return 0; } /** Set default gaps for rows and columns. All gaps are positioned below the rows and right of their columns. The bottom row and the right-most column don't have a gap, i.e. the gap sizes of these columns and rows are ignored. You can use a right or bottom margin instead. You have to specify at least one argument, \p col_gap is optional. If you don't specify an argument or use a negative value (e.g. -1) then that margin is not affected. You can also initialize the default gaps with layout(int, int, int, int). \param[in] row_gap default gap for all rows \param[in] col_gap default gap for all columns \see Fl_Grid::layout(int rows, int cols, int margin, int gap) */ void Fl_Grid::gap(int row_gap, int col_gap) { if (row_gap >= 0) gap_row_ = row_gap; if (col_gap >= 0) gap_col_ = col_gap; need_layout(1); } /** Get the default gaps for rows and columns. \param[out] row_gap pointer to int to receive column gap, may be NULL \param[out] col_gap pointer to int to receive column gap, may be NULL */ void Fl_Grid::gap(int *row_gap, int *col_gap) const { if (row_gap) *row_gap = gap_row_; if (col_gap) *col_gap = gap_col_; } /** Get the grid cell of row \p row and column \p col. Widgets and other attributes are organized in cells (Fl_Grid::Cell). This cell is an opaque structure (class) with some public methods. \b Don't assume anything about grid cell sizes and ordering in memory. These are implementation details that can be changed without notice. The validity of an Fl_Grid::Cell pointer is limited. It will definitely be invalidated when the overall grid layout is changed, for instance by calling layout(int, int). Adding new cells beyond the current layout limits will also invalidate cell pointers but this is not (yet) implemented. Attempts to assign widgets to out-of-bounds cells are currently ignored. The only well-defined usage of cell pointers is to set one or more properties like widget alignment of a cell after retrieving the cell pointer. Don't store cell pointers in your program for later reference. \param[in] row row index \param[in] col column index \returns pointer to cell \retval NULL if \p row or \p col is out of bounds or no widget was assigned */ Fl_Grid::Cell* Fl_Grid::cell(int row, int col) const { if (row < 0 || row >= rows_ || col < 0 || col >= cols_) return 0; Row *r = &Rows_[row]; Cell *cel = r->cells_; while (cel) { if (cel->col_ > col) return 0; if (cel->col_ == col) return cel; cel = cel->next_; } return 0; } /** Get the grid cell of widget \p widget. The pointer to the cell can be used for further assignment of properties like alignment etc. Hint: If you know the row and column index of the cell you should use Fl_Grid::cell(int row, int col) instead because it is \b much faster. Please see Fl_Grid::cell(int row, int col) for details and the validity of cell pointers. \param[in] widget widget whose cell is requested \retval NULL if \p widget is not assigned to a cell */ Fl_Grid::Cell* Fl_Grid::cell(Fl_Widget *widget) const { Row *row = Rows_; for (int r = 0; r < rows_; r++, row++) { Cell *cel = row->cells_; while (cel) { if (cel->widget_ == widget) return cel; cel = cel->next_; } } return 0; } /** Assign a widget to a grid cell and set its alignment. This short form sets row and column spanning attributes to (1, 1). For more information see Fl_Grid::widget(Fl_Widget *wi, int row, int col, int rowspan, int colspan, Fl_Grid_Align align) \param[in] wi widget to be assigned to the cell \param[in] row row \param[in] col column \param[in] align widget alignment inside the cell \return assigned cell \retval NULL if \p row or \p col is out of bounds \see Fl_Grid::widget(Fl_Widget *wi, int row, int col, int rowspan, int colspan, Fl_Grid_Align align) */ Fl_Grid::Cell *Fl_Grid::widget(Fl_Widget *wi, int row, int col, Fl_Grid_Align align) { return widget(wi, row, col, 1, 1, align); } /** Assign a widget to a grid cell and set cell spanning and alignment. Default alignment is \c FL_GRID_FILL which stretches the widget in horizontal and vertical directions to fill the whole cell(s) given by \p colspan and \p rowspan. You can use this method to move a widget from one cell to another; it is automatically removed from its old cell. If the new cell is already assigned to another widget that widget is deassigned but kept as a child of the group. Before you can assign a widget to a cell it must have been created as a child of the Fl_Grid widget (i.e. its Fl_Group). \param[in] wi widget to be assigned to the cell \param[in] row row \param[in] col column \param[in] rowspan vertical span in cells, default 1 \param[in] colspan horizontal span in cells, default 1 \param[in] align widget alignment inside the cell \return assigned cell \retval NULL if \p row or \p col is out of bounds or \p wi is not a child */ Fl_Grid::Cell *Fl_Grid::widget(Fl_Widget *wi, int row, int col, int rowspan, int colspan, Fl_Grid_Align align) { int child = Fl_Group::find(wi); // is this widget one of our children? if (child >= children()) { // fprintf(stderr, "Fl_Grid::widget(): can't assign widget %p to cell (%d, %d): not a child!\n", wi, row, col); return 0; } if (row < 0 || row > rows_) return 0; if (col < 0 || col > cols_) return 0; Cell *c = cell(row, col); if (!c) { c = add_cell(row, col); } // check if the widget is already assigned to another cell and deassign it if (c->widget_ != wi) { Cell *oc = cell(wi); // search cells for the same widget if (oc) { // if found: deassign and remove cell remove_cell(oc->row_, oc->col_); } } // assign the widget to this cell c->widget_ = wi; c->align_ = align; c->w_ = wi->w(); c->h_ = wi->h(); if (rowspan > 0) c->rowspan_ = rowspan; if (colspan > 0) c->colspan_ = colspan; need_layout(1); return c; } /** Set the minimal width of a column. Column widths are calculated by using the maximum of all widget widths in that column and the given column width. After calculating the width additional space is added when resizing according to the \c weight of the column. You can set one or more column widths in one call by using Fl_Grid::col_width(const int *value, size_t size). \param[in] col column number (counting from 0) \param[in] value minimal column width, must be \>= 0 \see Fl_Grid::col_width(const int *value, size_t size) */ void Fl_Grid::col_width(int col, int value) { if (col >= 0 && col < cols_) { if (Cols_[col].minw_ != value) { Cols_[col].minw_ = value; need_layout(1); } } } /** Set minimal widths of more than one column. The values are taken from the array \p value and assigned sequentially to columns, starting from column 0. If the array \p size is too large extraneous values are ignored. Negative values in the \p array are not assigned to their columns, i.e. the existing value for the corresponding column is not changed. Example: \code int widths[] = { 0, 0, 50, -1, -1, 50, 0 }; grid->col_width(widths, sizeof(width)/sizeof(width[0])); \endcode \param[in] value an array of column widths \param[in] size the size of the array (number of values) */ void Fl_Grid::col_width(const int *value, size_t size) { Col *c = Cols_; for (int i = 0; i < cols_; i++, value++, c++) { if (i >= (int)size) break; if (*value >= 0) c->minw_ = *value; } need_layout(1); } int Fl_Grid::col_width(int col) const { if (col >= 0 && col < cols_) return Cols_[col].minw_; return 0; } /** Set the weight of a column. Column and row weights are used to distribute additional space when the grid is resized beyond its defined (minimal) size. All weight values are relative and can be chosen freely. Suggested weights are in the range {0 .. 100}, 0 (zero) disables resizing of the column. How does it work? Whenever additional space (say: \c SPACE in pixels) is to be distributed to a set of columns the weights of all columns are added to a value \c SUM, then every single column width is increased by the value (in pseudo code): \code col.width += SPACE * col.weight / SUM \endcode Resulting pixel values are rounded to the next integer and rounding differences are added to or subtracted from the column with the highest weight. If more columns have the same weight one of them is chosen. \note If none of the columns considered for resizing have weights \> 0 then Fl_Grid assigns the remaining space to an arbitrary column or to all considered columns evenly. This is implementation defined and can be changed without notice. You can avoid this situation by designing your grid with sensible sizes and weights. \param[in] col column number (counting from 0) \param[in] value weight, must be \>= 0 */ void Fl_Grid::col_weight(int col, int value) { if (col >= 0 && col < cols_) Cols_[col].weight_ = value; need_layout(1); } /** Set the weight of more than one column. The values are taken from the array \p value and assigned sequentially to columns, starting from column 0. If the array \p size is too large extraneous values are ignored. Negative values in the \p array are not assigned to their columns, i.e. the existing value for the corresponding column is not changed. Example: \code int val[] = { 0, 0, 50, -1, -1, 50, 0 }; grid->col_weight(val, sizeof(val)/sizeof(val[0])); \endcode \param[in] value an array of column weights \param[in] size the size of the array (number of values) */ void Fl_Grid::col_weight(const int *value, size_t size) { Col *c = Cols_; for (int i = 0; i < cols_; i++, value++, c++) { if (i >= (int)size) break; if (*value >= 0) c->weight_ = *value; } need_layout(1); } int Fl_Grid::col_weight(int col) const { if (col >= 0 && col < cols_) return Cols_[col].weight_; return 0; } /** Set the gap of column \c col. Note that the gap is right of each column except the last one which is ignored. Use margin() for the right most column. \param[in] col column \param[in] value gap size after the column */ void Fl_Grid::col_gap(int col, int value) { if (col >= 0 && col < cols_) Cols_[col].gap_ = value; need_layout(1); } /** Set more than one column gaps at once. \see Fl_Grid::col_weight(const int *value, size_t size) for handling of the value array and \p size. */ void Fl_Grid::col_gap(const int *value, size_t size) { Col *c = Cols_; for (int i = 0; i < cols_; i++, value++, c++) { if (i >= (int)size) break; if (*value >= 0) c->gap_ = *value; } need_layout(1); } int Fl_Grid::col_gap(int col) const { if (col >= 0 && col < cols_) return Cols_[col].gap_; return 0; } /** Set the minimal row height of row \c row. \param[in] row row \param[in] value minimal height of the row */ void Fl_Grid::row_height(int row, int value) { if (row >= 0 && row < rows_) Rows_[row].minh_ = value; need_layout(1); } /** Set the minimal row height of more than one row. \param[in] value array of height values \param[in] size size of array \p value \see Fl_Grid::col_weight(const int *value, size_t size) for handling of the value array and \p size. */ void Fl_Grid::row_height(const int *value, size_t size) { Row *r = Rows_; for (int i = 0; i < rows_; i++, value++, r++) { if (i >= (int)size) break; if (*value >= 0) r->minh_ = *value; } need_layout(1); } int Fl_Grid::row_height(int row) const { if (row >= 0 && row < rows_) return Rows_[row].minh_; return 0; } /** Set the row weight of row \c row. \param[in] row row \param[in] value weight of the row */ void Fl_Grid::row_weight(int row, int value) { if (row >= 0 && row < rows_) Rows_[row].weight_ = value; need_layout(1); } /** Set the weight of more than one row. \param[in] value array of height values \param[in] size size of array \p value \see Fl_Grid::col_weight(const int *value, size_t size) for handling of the \p value array and \p size. */ void Fl_Grid::row_weight(const int *value, size_t size) { Row *r = Rows_; for (int i = 0; i < rows_; i++, value++, r++) { if (i >= (int)size) break; if (*value >= 0) r->weight_ = *value; } need_layout(1); } int Fl_Grid::row_weight(int row) const { if (row >= 0 && row < rows_) return Rows_[row].weight_; return 0; } /** Set the gap of row \c row. Note that the gap is below each row except the last one which is ignored. Use margin() for the bottom row. \param[in] row row \param[in] value gap size below the row */ void Fl_Grid::row_gap(int row, int value) { if (row >= 0 && row < rows_) Rows_[row].gap_ = value; need_layout(1); } /** Set more than one row gaps at once. \see Fl_Grid::col_weight(const int *value, size_t size) for handling of the value array and \p size. */ void Fl_Grid::row_gap(const int *value, size_t size) { Row *r = Rows_; for (int i = 0; i < rows_; i++, value++, r++) { if (i >= (int)size) break; if (*value >= 0) r->gap_ = *value; } need_layout(1); } int Fl_Grid::row_gap(int row) const { if (row >= 0 && row < rows_) return Rows_[row].gap_; return 0; } int Fl_Grid::computed_col_width(int col) const { return Cols_[col].w_; } int Fl_Grid::computed_row_height(int row) const { return Rows_[row].h_; } /** Output layout information of this Fl_Grid to stderr. Parameter \p level will be used to define the amount of output. - 0 = nothing - 127 = everything - other values not yet defined \note It is not yet defined which kind of values \p level will have, either a numerical value (127 = maximum, 0 = nothing) or a bit mask that determines what to output. \todo Add more information about cells and children. \todo Control output by using \p level. \param[in] level not yet used (0-127, default = 127) */ void Fl_Grid::debug(int level) { if (level <= 0) return; fprintf(stderr, "Fl_Grid::layout(%d, %d) at (%d, %d, %d, %d)\n", rows_, cols_, x(), y(), w(), h()); fprintf(stderr, " margins: (%2d, %2d, %2d, %2d)\n", margin_left_, margin_top_, margin_right_, margin_bottom_); fprintf(stderr, " gaps: (%2d, %2d)\n", gap_row_, gap_col_); Row *row = Rows_; for (int r = 0; r < rows_; r++, row++) { fprintf(stderr, "Row %2d: minh = %d, weight = %d, gap = %d, h = %d\n", r, row->minh_, row->weight_, row->gap_, row->h_); Cell *cel = row->cells_; while (cel) { fprintf(stderr, " Cell(%2d, %2d)\n", cel->row_, cel->col_); cel = cel->next_; } } fflush(stderr); // necessary for Windows } fltk-1.4.3/src/Fl_Menu.cxx0000644000175000017500000012067415004135251015457 0ustar albrechtalbrecht// // Menu code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Warning: this menu code is quite a mess! // This file contains code for implementing Fl_Menu_Item, and for // methods for bringing up popup menu hierarchies without using the // Fl_Menu_ widget. #include #include "Fl_Screen_Driver.H" #include "Fl_Window_Driver.H" #include #include #include #include #include "flstring.h" /** Size of the menu starting from this menu item. This method counts all menu items starting with \p this menu item, including all menu items in the same (sub)menu level, all nested submenus, \b and the terminating empty (0) menu item. It does \b not count menu items referred to by FL_SUBMENU_POINTER menu items (except the single menu item with FL_SUBMENU_POINTER). All menu items counted are consecutive in memory (one array). Example: \code schemechoice = new Fl_Choice(X+125,Y,140,25,"FLTK Scheme"); schemechoice->add("none"); schemechoice->add("plastic"); schemechoice->add("gtk+"); schemechoice->add("gleam"); printf("schemechoice->menu()->size() = %d\n", schemechoice->menu()->size()); \endcode Output: schemechoice->menu()->%size() = 5 */ int Fl_Menu_Item::size() const { const Fl_Menu_Item* m = this; int nest = 0; for (;;) { if (!m->text) { if (!nest) return (int) (m-this+1); nest--; } else if (m->flags & FL_SUBMENU) { nest++; } m++; } } // Advance a pointer to next visible or invisible item of a menu array, // skipping the contents of submenus. static const Fl_Menu_Item* next_visible_or_not(const Fl_Menu_Item* m) { int nest = 0; do { if (!m->text) { if (!nest) return m; nest--; } else if (m->flags&FL_SUBMENU) { nest++; } m++; } while (nest); return m; } /** Advance a pointer by n items through a menu array, skipping the contents of submenus and invisible items. There are two calls so that you can advance through const and non-const data. */ const Fl_Menu_Item* Fl_Menu_Item::next(int n) const { if (n < 0) return 0; // this is so selected==-1 returns NULL const Fl_Menu_Item* m = this; if (!m->visible()) n++; while (n) { m = next_visible_or_not(m); if (m->visible() || !m->text) n--; } return m; } // appearance of current menus are pulled from this parent widget: static const Fl_Menu_* button=0; //////////////////////////////////////////////////////////////// class menuwindow; // utility class covering both menuwindow and menutitle class window_with_items : public Fl_Menu_Window { protected: window_with_items(int X, int Y, int W, int H, const Fl_Menu_Item *m) : Fl_Menu_Window(X, Y, W, H, 0) { menu = m; set_menu_window(); Fl_Window_Driver::driver(this)->set_popup_window(); end(); set_modal(); clear_border(); } public: const Fl_Menu_Item* menu; virtual menuwindow* as_menuwindow() { return NULL; } }; // tiny window for title of menu: class menutitle : public window_with_items { void draw() FL_OVERRIDE; public: menutitle(int X, int Y, int W, int H, const Fl_Menu_Item*, bool menubar = false); bool in_menubar; }; // each vertical menu has one of these: class menuwindow : public window_with_items { friend class Fl_Window_Driver; friend struct Fl_Menu_Item; void draw() FL_OVERRIDE; void drawentry(const Fl_Menu_Item*, int i, int erase); int handle_part1(int); int handle_part2(int e, int ret); static Fl_Window *parent_; static int display_height_; public: menutitle* title; int handle(int) FL_OVERRIDE; int itemheight; // zero == menubar int numitems; int selected; int drawn_selected; // last redraw has this selected int shortcutWidth; menuwindow(const Fl_Menu_Item* m, int X, int Y, int W, int H, const Fl_Menu_Item* picked, const Fl_Menu_Item* title, int menubar = 0, int menubar_title = 0, int right_edge = 0); ~menuwindow(); void set_selected(int); int find_selected(int mx, int my); int titlex(int); void autoscroll(int); void position(int x, int y); int is_inside(int x, int y); menuwindow* as_menuwindow() FL_OVERRIDE { return this; } int menubartitle; menuwindow *origin; int offset_y; }; Fl_Window *menuwindow::parent_ = NULL; int menuwindow::display_height_ = 0; /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** The Fl_Window from which currently displayed popups originate. Optionally, gives also the height of the display containing this window */ Fl_Window *Fl_Window_Driver::menu_parent(int *display_height) { if (display_height) *display_height = menuwindow::display_height_; return menuwindow::parent_; } static menuwindow *to_menuwindow(Fl_Window *win) { if (!Fl_Window_Driver::driver(win)->popup_window() || !win->menu_window()) return NULL; return ((window_with_items*)win)->as_menuwindow(); } /** Accessor to the "origin" member variable of class menuwindow. Variable origin is not NULL when 2 menuwindow's occur, one being a submenu of the other; it links the menuwindow at right to the one at left. */ Fl_Window *Fl_Window_Driver::menu_leftorigin(Fl_Window *win) { menuwindow *mwin = to_menuwindow(win); return (mwin ? mwin->origin : NULL); } /** Accessor to the "title" member variable of class menuwindow */ Fl_Window *Fl_Window_Driver::menu_title(Fl_Window *win) { menuwindow *mwin = to_menuwindow(win); return (mwin ? mwin->title : NULL); } /** Accessor to the "itemheight" member variable of class menuwindow */ int Fl_Window_Driver::menu_itemheight(Fl_Window *win) { menuwindow *mwin = to_menuwindow(win); return (mwin ? mwin->itemheight : 0); } /** Accessor to the "menubartitle" member variable of class menuwindow */ int Fl_Window_Driver::menu_bartitle(Fl_Window *win) { menuwindow *mwin = to_menuwindow(win); return (mwin ? mwin->menubartitle : 0); } /** Accessor to the "selected" member variable of class menuwindow */ int Fl_Window_Driver::menu_selected(Fl_Window *win) { menuwindow *mwin = to_menuwindow(win); return (mwin ? mwin->selected : -1); } /** Accessor to the address of the offset_y member variable of class menuwindow */ int *Fl_Window_Driver::menu_offset_y(Fl_Window *win) { menuwindow *mwin = to_menuwindow(win); return (mwin ? &(mwin->offset_y) : NULL); } /** Returns whether win is a non-menubar menutitle */ bool Fl_Window_Driver::is_floating_title(Fl_Window *win) { if (!Fl_Window_Driver::driver(win)->popup_window() || !win->menu_window()) return false; Fl_Window *mwin = ((window_with_items*)win)->as_menuwindow(); return !mwin && !((menutitle*)win)->in_menubar; } /** Makes sure that the tall menu's selected item is visible in display */ void Fl_Window_Driver::scroll_to_selected_item(Fl_Window *win) { menuwindow *mwin = to_menuwindow(win); if (mwin && mwin->selected > 0) { mwin->autoscroll(mwin->selected); } } /** \} \endcond */ extern char fl_draw_shortcut; /** Measures width of label, including effect of & characters. Optionally, can get height if hp is not NULL. */ int Fl_Menu_Item::measure(int* hp, const Fl_Menu_* m) const { Fl_Label l; l.value = text; l.image = 0; l.deimage = 0; l.type = labeltype_; l.font = labelsize_ || labelfont_ ? labelfont_ : (m ? m->textfont() : FL_HELVETICA); l.size = labelsize_ ? labelsize_ : m ? m->textsize() : FL_NORMAL_SIZE; l.color = FL_FOREGROUND_COLOR; // this makes no difference? l.h_margin_ = l.v_margin_ = l.spacing = 0; fl_draw_shortcut = 1; int w = 0; int h = 0; l.measure(w, hp ? *hp : h); fl_draw_shortcut = 0; if (flags & (FL_MENU_TOGGLE|FL_MENU_RADIO)) w += FL_NORMAL_SIZE + 4; return w; } /** Draws the menu item in bounding box x,y,w,h, optionally selects the item. */ void Fl_Menu_Item::draw(int x, int y, int w, int h, const Fl_Menu_* m, int selected) const { Fl_Label l; l.value = text; l.image = 0; l.deimage = 0; l.type = labeltype_; l.font = labelsize_ || labelfont_ ? labelfont_ : (m ? m->textfont() : FL_HELVETICA); l.size = labelsize_ ? labelsize_ : m ? m->textsize() : FL_NORMAL_SIZE; l.color = labelcolor_ ? labelcolor_ : m ? m->textcolor() : int(FL_FOREGROUND_COLOR); l.h_margin_ = l.v_margin_ = l.spacing = 0; if (!active()) l.color = fl_inactive((Fl_Color)l.color); if (selected) { Fl_Color r = m ? m->selection_color() : FL_SELECTION_COLOR; Fl_Boxtype b = m && m->down_box() ? m->down_box() : FL_FLAT_BOX; l.color = fl_contrast((Fl_Color)labelcolor_, r); if (selected == 2) { // menu title fl_draw_box(b, x, y, w, h, r); x += 3; w -= 8; } else { fl_draw_box(b, x+1, y-(Fl::menu_linespacing()-2)/2, w-2, h+(Fl::menu_linespacing()-2), r); } } if (flags & (FL_MENU_TOGGLE|FL_MENU_RADIO)) { int d = (h - FL_NORMAL_SIZE + 1) / 2; int W = h - 2 * d; Fl_Color check_color = labelcolor_; if (Fl::is_scheme("gtk+")) check_color = FL_SELECTION_COLOR; check_color = fl_contrast(check_color, FL_BACKGROUND2_COLOR); if (flags & FL_MENU_RADIO) { fl_draw_box(FL_ROUND_DOWN_BOX, x+2, y+d, W, W, FL_BACKGROUND2_COLOR); if (value()) { int tW = (W - Fl::box_dw(FL_ROUND_DOWN_BOX)) / 2 + 1; if ((W - tW) & 1) tW++; // Make sure difference is even to center int td = (W - tW) / 2; fl_draw_radio(x + td + 1, y + d + td - 1, tW + 2, check_color); } // FL_MENU_RADIO && value() } else { // FL_MENU_TOGGLE && ! FL_MENU_RADIO fl_draw_box(FL_DOWN_BOX, x+2, y+d, W, W, FL_BACKGROUND2_COLOR); if (value()) { fl_draw_check(Fl_Rect(x+3, y+d+1, W-2, W-2), check_color); } } x += W + 3; w -= W + 3; } if (!fl_draw_shortcut) fl_draw_shortcut = 1; l.draw(x+3, y, w>6 ? w-6 : 0, h, FL_ALIGN_LEFT); fl_draw_shortcut = 0; } menutitle::menutitle(int X, int Y, int W, int H, const Fl_Menu_Item* L, bool inbar) : window_with_items(X, Y, W, H, L) { in_menubar = inbar; } menuwindow::menuwindow(const Fl_Menu_Item* m, int X, int Y, int Wp, int Hp, const Fl_Menu_Item* picked, const Fl_Menu_Item* t, int menubar, int menubar_title, int right_edge) : window_with_items(X, Y, Wp, Hp, m) { int scr_x, scr_y, scr_w, scr_h; int tx = X, ty = Y; menubartitle = menubar_title; origin = NULL; offset_y = 0; int n = (Wp > 0 ? Fl::screen_num(X, Y) : -1); Fl_Window_Driver::driver(this)->menu_window_area(scr_x, scr_y, scr_w, scr_h, n); if (!right_edge || right_edge > scr_x+scr_w) right_edge = scr_x+scr_w; if (m) m = m->first(); // find the first item that needs to be rendered drawn_selected = -1; if (button) { Fl_Boxtype b = button->menu_box(); if (b==FL_NO_BOX) b = button->box(); if (b==FL_NO_BOX) b = FL_FLAT_BOX; box(b); } else { box(FL_UP_BOX); } color(button && !Fl::scheme() ? button->color() : FL_GRAY); selected = -1; { int j = 0; if (m) for (const Fl_Menu_Item* m1=m; ; m1 = m1->next(), j++) { if (picked) { if (m1 == picked) {selected = j; picked = 0;} else if (m1 > picked) {selected = j-1; picked = 0; Wp = Hp = 0;} } if (!m1->text) break; } numitems = j;} if (menubar) { itemheight = 0; title = 0; return; } itemheight = 1; int hotKeysw = 0; int hotModsw = 0; int Wtitle = 0; int Htitle = 0; if (t) Wtitle = t->measure(&Htitle, button) + 12; int W = 0; if (m) for (; m->text; m = m->next()) { int hh; int w1 = m->measure(&hh, button); if (hh+Fl::menu_linespacing()>itemheight) itemheight = hh+Fl::menu_linespacing(); if (m->flags&(FL_SUBMENU|FL_SUBMENU_POINTER)) w1 += FL_NORMAL_SIZE; if (w1 > W) W = w1; // calculate the maximum width of all shortcuts if (m->shortcut_) { // s is a pointer to the UTF-8 string for the entire shortcut // k points only to the key part (minus the modifier keys) const char *k, *s = fl_shortcut_label(m->shortcut_, &k); if (fl_utf_nb_char((const unsigned char*)k, (int) strlen(k))<=4) { // a regular shortcut has a right-justified modifier followed by a left-justified key w1 = int(fl_width(s, (int) (k-s))); if (w1 > hotModsw) hotModsw = w1; w1 = int(fl_width(k))+4; if (w1 > hotKeysw) hotKeysw = w1; } else { // a shortcut with a long modifier is right-justified to the menu w1 = int(fl_width(s))+4; if (w1 > (hotModsw+hotKeysw)) { hotModsw = w1-hotKeysw; } } } } shortcutWidth = hotKeysw; if (selected >= 0 && !Wp) X -= W/2; int BW = Fl::box_dx(box()); W += hotKeysw+hotModsw+2*BW+7; if (Wp > W) W = Wp; if (Wtitle > W) W = Wtitle; if (X < scr_x) X = scr_x; // this change improves popup submenu positioning at right screen edge, // but it makes right_edge argument useless //if (X > scr_x+scr_w-W) X = right_edge-W; if (X > scr_x+scr_w-W) X = scr_x+scr_w-W; x(X); w(W); h((numitems ? itemheight*numitems-4 : 0)+2*BW+3); if (selected >= 0) { Y = Y+(Hp-itemheight)/2-selected*itemheight-BW; } else { Y = Y+Hp; // if the menu hits the bottom of the screen, we try to draw // it above the menubar instead. We will not adjust any menu // that has a selected item. if (Y+h()>scr_y+scr_h && Y-h()>=scr_y) { if (Hp>1) { // if we know the height of the Fl_Menu_, use it Y = Y-Hp-h(); } else if (t) { // assume that the menubar item height relates to the first // menuitem as well Y = Y-itemheight-h()-Fl::box_dh(box()); } else { // draw the menu to the right Y = Y-h()+itemheight+Fl::box_dy(box()); } if (t) { if (menubar_title) { Y = Y + Fl::menu_linespacing() - Fl::box_dw(button->box()); } else { Y += 2*Htitle+2*BW+3; } } } } if (m) y(Y); else {y(Y-2); w(1); h(1);} if (t) { if (menubar_title) { int dy = Fl::box_dy(button->box())+1; int ht = button->h()-dy*2; title = new menutitle(tx, ty-ht-dy, Wtitle, ht, t, true); } else { int dy = 2; int ht = Htitle+2*BW+3; title = new menutitle(X, Y-ht-dy, Wtitle, ht, t); } } else { title = 0; } } menuwindow::~menuwindow() { hide(); delete title; } void menuwindow::position(int X, int Y) { if (title) {title->position(X, title->y()+Y-y());} Fl_Menu_Window::position(X, Y); // x(X); y(Y); // don't wait for response from X } // scroll so item i is visible on screen void menuwindow::autoscroll(int n) { int scr_y, scr_h; int Y = y()+Fl::box_dx(box())+2+n*itemheight; int xx, ww; Fl_Window_Driver::driver(this)->menu_window_area(xx, scr_y, ww, scr_h, this->screen_num()); if (n==0 && Y <= scr_y + itemheight) { Y = scr_y - Y + 10; } else if (Y <= scr_y + itemheight) { Y = scr_y - Y + 10 + itemheight; } else { Y = Y+itemheight-scr_h-scr_y; if (Y < 0) return; Y = -Y-10; } Fl_Window_Driver::driver(this)->reposition_menu_window(x(), y()+Y); // y(y()+Y); // don't wait for response from X } //////////////////////////////////////////////////////////////// void menuwindow::drawentry(const Fl_Menu_Item* m, int n, int eraseit) { if (!m) return; // this happens if -1 is selected item and redrawn int BW = Fl::box_dx(box()); int xx = BW; int W = w(); int ww = W-2*BW-1; int yy = BW+1+n*itemheight+Fl::menu_linespacing()/2-2; int hh = itemheight - Fl::menu_linespacing(); if (eraseit && n != selected) { fl_push_clip(xx+1, yy-(Fl::menu_linespacing()-2)/2, ww-2, hh+(Fl::menu_linespacing()-2)); draw_box(box(), 0, 0, w(), h(), button ? button->color() : color()); fl_pop_clip(); } m->draw(xx, yy, ww, hh, button, n==selected); // the shortcuts and arrows assume fl_color() was left set by draw(): if (m->submenu()) { // calculate the bounding box of the submenu pointer (arrow) int sz = ((hh-2) & (-2)) + 1 ; // must be odd for better centering if (sz > 13) sz = 13; // limit arrow size int x1 = xx + ww - sz - 2; // left border int y1 = yy + (hh-sz)/2 + 1; // top border // draw an arrow whose style depends on the active scheme fl_draw_arrow(Fl_Rect(x1, y1, sz, sz), FL_ARROW_SINGLE, FL_ORIENT_RIGHT, fl_color()); } else if (m->shortcut_) { Fl_Font f = m->labelsize_ || m->labelfont_ ? (Fl_Font)m->labelfont_ : button ? button->textfont() : FL_HELVETICA; fl_font(f, m->labelsize_ ? m->labelsize_ : button ? button->textsize() : FL_NORMAL_SIZE); const char *k, *s = fl_shortcut_label(m->shortcut_, &k); if (fl_utf_nb_char((const unsigned char*)k, (int) strlen(k))<=4) { // right-align the modifiers and left-align the key char *buf = (char*)malloc(k-s+1); memcpy(buf, s, k-s); buf[k-s] = 0; fl_draw(buf, xx, yy, ww-shortcutWidth, hh, FL_ALIGN_RIGHT); fl_draw( k, xx+ww-shortcutWidth, yy, shortcutWidth, hh, FL_ALIGN_LEFT); free(buf); } else { // right-align to the menu fl_draw(s, xx, yy, ww-4, hh, FL_ALIGN_RIGHT); } } if (m->flags & FL_MENU_DIVIDER) { fl_color(FL_DARK3); fl_xyline(BW-1, yy+hh+(Fl::menu_linespacing()-2)/2, W-2*BW+2); fl_color(FL_LIGHT3); fl_xyline(BW-1, yy+hh+((Fl::menu_linespacing()-2)/2+1), W-2*BW+2); } } void menutitle::draw() { menu->draw(0, 0, w(), h(), button, 2); } void menuwindow::draw() { if (damage() != FL_DAMAGE_CHILD) { // complete redraw if ( box() != FL_FLAT_BOX && ( Fl::is_scheme( "gtk+" ) || Fl::is_scheme( "plastic") || Fl::is_scheme( "gleam" ) )) { // Draw a FL_FLAT_BOX to avoid on macOS the white corners of the menus fl_draw_box( FL_FLAT_BOX, 0, 0, w(), h(), button ? button->color() : color()); } fl_draw_box(box(), 0, 0, w(), h(), button ? button->color() : color()); if (menu) { const Fl_Menu_Item* m; int j; for (m=menu->first(), j=0; m->text; j++, m = m->next()) drawentry(m, j, 0); } } else { if (damage() & FL_DAMAGE_CHILD && selected!=drawn_selected) { // change selection drawentry(menu->next(drawn_selected), drawn_selected, 1); drawentry(menu->next(selected), selected, 1); } } drawn_selected = selected; } void menuwindow::set_selected(int n) { if (n != selected) {selected = n; damage(FL_DAMAGE_CHILD);} } //////////////////////////////////////////////////////////////// int menuwindow::find_selected(int mx, int my) { if (!menu || !menu->text) return -1; mx -= x(); my -= y(); if (my < 0 || my >= h()) return -1; if (!itemheight) { // menubar int xx = 3; int n = 0; const Fl_Menu_Item* m = menu->first(); for (; ; m = m->next(), n++) { if (!m->text) return -1; xx += m->measure(0, button) + 16; if (xx > mx) break; } return n; } if (mx < Fl::box_dx(box()) || mx >= w()) return -1; int n = (my-Fl::box_dx(box())-1)/itemheight; if (n < 0 || n>=numitems) return -1; return n; } // return horizontal position for item n in a menubar: int menuwindow::titlex(int n) { const Fl_Menu_Item* m; int xx = 3; for (m=menu->first(); n--; m = m->next()) xx += m->measure(0, button) + 16; return xx; } // return 1, if the given root coordinates are inside the window int menuwindow::is_inside(int mx, int my) { if ( mx < x_root() || mx >= x_root() + w() || my < y_root() || my >= y_root() + h()) { return 0; } if (itemheight == 0 && find_selected(mx, my) == -1) { // in the menubar but out from any menu header return 0; } return 1; } //////////////////////////////////////////////////////////////// // Fl_Menu_Item::popup(...) // Because Fl::grab() is done, all events go to one of the menu windows. // But the handle method needs to look at all of them to find out // what item the user is pointing at. And it needs a whole lot // of other state variables to determine what is going on with // the currently displayed menus. // So the main loop (handlemenu()) puts all the state in a structure // and puts a pointer to it in a static location, so the handle() // on menus can refer to it and alter it. The handle() method // changes variables in this state to indicate what item is // picked, but does not actually alter the display, instead the // main loop does that. This is because the X mapping and unmapping // of windows is slow, and we don't want to fall behind the events. // values for menustate.state: #define INITIAL_STATE 0 // no mouse up or down since popup() called #define PUSH_STATE 1 // mouse has been pushed on a normal item #define DONE_STATE 2 // exit the popup, the current item was picked #define MENU_PUSH_STATE 3 // mouse has been pushed on a menu title struct menustate { const Fl_Menu_Item* current_item; // what mouse is pointing at int menu_number; // which menu it is in int item_number; // which item in that menu, -1 if none menuwindow* p[20]; // pointers to menus int nummenus; int menubar; // if true p[0] is a menubar int state; menuwindow* fakemenu; // kludge for buttons in menubar int is_inside(int mx, int my); }; static menustate* p=0; // return 1 if the coordinates are inside any of the menuwindows int menustate::is_inside(int mx, int my) { int i; for (i=nummenus-1; i>=0; i--) { if (p[i]->is_inside(mx, my)) return 1; } return 0; } static inline void setitem(const Fl_Menu_Item* i, int m, int n) { p->current_item = i; p->menu_number = m; p->item_number = n; } static void setitem(int m, int n) { menustate &pp = *p; pp.current_item = (n >= 0) ? pp.p[m]->menu->next(n) : 0; pp.menu_number = m; pp.item_number = n; } static int forward(int menu) { // go to next item in menu menu if possible // `menu` is -1 if no item is currently selected, so use the first menu if (menu < 0) menu = 0; menustate &pp = *p; menuwindow &m = *(pp.p[menu]); int item = (menu == pp.menu_number) ? pp.item_number : m.selected; bool wrapped = false; do { while (++item < m.numitems) { const Fl_Menu_Item* m1 = m.menu->next(item); if (m1->activevisible()) {setitem(m1, menu, item); return 1;} } if (wrapped) break; item = -1; wrapped = true; } while (Fl::event_key() != FL_Down); return 0; } static int backward(int menu) { // previous item in menu menu if possible // `menu` is -1 if no item is currently selected, so use the first menu if (menu < 0) menu = 0; menustate &pp = *p; menuwindow &m = *(pp.p[menu]); int item = (menu == pp.menu_number) ? pp.item_number : m.selected; bool wrapped = false; do { while (--item >= 0) { const Fl_Menu_Item* m1 = m.menu->next(item); if (m1->activevisible()) {setitem(m1, menu, item); return 1;} } if (wrapped) break; item = m.numitems; wrapped = true; } while (Fl::event_key() != FL_Up); return 0; } int menuwindow::handle(int e) { /* In FLTK 1.3.4, the equivalent of handle_part2() is called for the Mac OS and X11 platforms and "svn blame" shows it is here to fix STR #449. But this STR is Mac OS-specific. So, it is unclear why handle_part2() is called also for X11. Furthermore, calling handle_part2() for X11 renders the fix for STR #2619 below necessary. If handle_part2() is not called under X11, then STR #2619 does not occur. need_menu_handle_part1_extra() activates this fix. FLTK 1.3.4 behavior: Fl::screen_driver()->need_menu_handle_part2() returns true on Mac + X11 Fl::screen_driver()->need_menu_handle_part1_extra() returns true on X11 Alternative behavior that seems equally correct: Fl::screen_driver()->need_menu_handle_part2() returns true on Mac need_menu_handle_part1_extra() does not exist Other alternative: Neither need_menu_handle_part2() nor need_menu_handle_part1_extra() exist --> the menuwindow code is entirely cross-platform and simpler. It makes a small difference with Mac OS when resizing a window with a menu on: the menu disappears after the end of the resize rather than at its beginning. Apple applications do close popups at the beginning of resizes. */ static int use_part2 = Fl::screen_driver()->need_menu_handle_part2(); int ret = handle_part1(e); if (use_part2) ret = handle_part2(e, ret); return ret; } int menuwindow::handle_part2(int e, int ret) { // This off-route takes care of the "detached menu" bug on OS X (STR #449). // Apple event handler requires that we hide all menu windows right // now, so that Carbon can continue undisturbed with handling window // manager events, like dragging the application window. menustate &pp = *p; if (pp.state == DONE_STATE) { hide(); if (pp.fakemenu) { pp.fakemenu->hide(); if (pp.fakemenu->title) pp.fakemenu->title->hide(); } int i = pp.nummenus; while (i>0) { menuwindow *mw = pp.p[--i]; if (mw) { mw->hide(); if (mw->title) mw->title->hide(); } } } return ret; } int menuwindow::handle_part1(int e) { menustate &pp = *p; switch (e) { case FL_KEYBOARD: switch (Fl::event_key()) { case FL_BackSpace: BACKTAB: backward(pp.menu_number); return 1; case FL_Up: if (pp.menubar && pp.menu_number == 0) { // Do nothing... } else if (backward(pp.menu_number)) { // Do nothing... } else if (pp.menubar && pp.menu_number==1) { setitem(0, pp.p[0]->selected); } return 1; case FL_Tab: if (Fl::event_shift()) goto BACKTAB; if (pp.menubar && pp.menu_number == 0) goto RIGHT; case FL_Down: if (pp.menu_number || !pp.menubar) { forward(pp.menu_number); } else if (pp.menu_number < pp.nummenus-1) { forward(pp.menu_number+1); } return 1; case FL_Right: RIGHT: if (pp.menubar && (pp.menu_number<=0 || (pp.menu_number == pp.nummenus-1))) forward(0); else if (pp.menu_number < pp.nummenus-1) forward(pp.menu_number+1); return 1; case FL_Left: if (pp.menubar && pp.menu_number<=1) backward(0); else if (pp.menu_number>0) setitem(pp.menu_number-1, pp.p[pp.menu_number-1]->selected); return 1; case FL_Enter: case FL_KP_Enter: case ' ': // if the current item is a submenu with no callback, // simulate FL_Right to enter the submenu if ( pp.current_item && (!pp.menubar || pp.menu_number > 0) && pp.current_item->activevisible() && pp.current_item->submenu() && !pp.current_item->callback_) { goto RIGHT; } // Ignore keypresses over inactive items, mark KEYBOARD event as used. if (pp.current_item && !pp.current_item->activevisible()) return 1; // Mark the menu 'done' which will trigger the callback pp.state = DONE_STATE; return 1; case FL_Escape: setitem(0, -1, 0); pp.state = DONE_STATE; return 1; } break; case FL_SHORTCUT: { for (int mymenu = pp.nummenus; mymenu--;) { menuwindow &mw = *(pp.p[mymenu]); int item; const Fl_Menu_Item* m = mw.menu->find_shortcut(&item); if (m) { setitem(m, mymenu, item); if (!m->submenu()) pp.state = DONE_STATE; return 1; } } } break; case FL_MOVE: { static int use_part1_extra = Fl::screen_driver()->need_menu_handle_part1_extra(); if (use_part1_extra && pp.state == DONE_STATE) { return 1; // Fix for STR #2619 } } /* FALLTHROUGH */ case FL_ENTER: case FL_PUSH: case FL_DRAG: { int mx = Fl::event_x_root(); int my = Fl::event_y_root(); int item=0; int mymenu = pp.nummenus-1; // Clicking or dragging outside menu cancels it... if ((!pp.menubar || mymenu) && !pp.is_inside(mx, my)) { setitem(0, -1, 0); if (e==FL_PUSH) pp.state = DONE_STATE; return 1; } for (mymenu = pp.nummenus-1; ; mymenu--) { item = pp.p[mymenu]->find_selected(mx, my); if (item >= 0) break; if (mymenu <= 0) { // buttons in menubars must be deselected if we move outside of them! if (pp.menu_number==-1 && e==FL_PUSH) { pp.state = DONE_STATE; return 1; } if (pp.current_item && pp.menu_number==0 && !pp.current_item->submenu()) { if (e==FL_PUSH) { pp.state = DONE_STATE; setitem(0, -1, 0); } return 1; } // all others can stay selected return 0; } } setitem(mymenu, item); if (e == FL_PUSH) { if (pp.current_item && pp.current_item->submenu() // this is a menu title && item != pp.p[mymenu]->selected // and it is not already on && !pp.current_item->callback_) // and it does not have a callback pp.state = MENU_PUSH_STATE; else pp.state = PUSH_STATE; } } return 1; case FL_RELEASE: // Mouse must either be held down/dragged some, or this must be // the second click (not the one that popped up the menu): if ( !Fl::event_is_click() || pp.state == PUSH_STATE || (pp.menubar && pp.current_item && !pp.current_item->submenu()) // button ) { #if 0 // makes the check/radio items leave the menu up const Fl_Menu_Item* m = pp.current_item; if (m && button && (m->flags & (FL_MENU_TOGGLE|FL_MENU_RADIO))) { ((Fl_Menu_*)button)->picked(m); pp.p[pp.menu_number]->redraw(); } else #endif // do nothing if they try to pick an inactive item, or a submenu with no callback if (!pp.current_item || (pp.current_item->activevisible() && (!pp.current_item->submenu() || pp.current_item->callback_ || (pp.menubar && pp.menu_number <= 0)))) pp.state = DONE_STATE; } return 1; } return Fl_Window::handle(e); } /** Pulldown() is similar to popup(), but a rectangle is provided to position the menu. The menu is made at least \p W wide, and the picked item \p initial_item is centered over the rectangle (like Fl_Choice uses). If \p initial_item is \p NULL or not found, the menu is aligned just below the rectangle (like a pulldown menu). The \p title and \p menubar arguments are used internally by the Fl_Menu_Bar widget. */ const Fl_Menu_Item* Fl_Menu_Item::pulldown( int X, int Y, int W, int H, const Fl_Menu_Item* initial_item, const Fl_Menu_* pbutton, const Fl_Menu_Item* title, int menubar) const { Fl_Group::current(0); // fix possible user error... // track the Fl_Menu_ widget to make sure we notice if it gets // deleted while the menu is open (STR #3503) Fl_Widget_Tracker wp((Fl_Widget *)pbutton); button = pbutton; if (pbutton && pbutton->window()) { menuwindow::parent_ = pbutton->top_window(); for (Fl_Window* w = pbutton->window(); w; w = w->window()) { X += w->x(); Y += w->y(); } } else { X += Fl::event_x_root()-Fl::event_x(); Y += Fl::event_y_root()-Fl::event_y(); menuwindow::parent_ = Fl::first_window(); } int XX, YY, WW; Fl::screen_xywh(XX, YY, WW, menuwindow::display_height_, menuwindow::parent_->screen_num()); menuwindow mw(this, X, Y, W, H, initial_item, title, menubar); Fl::grab(mw); // If we grab the mouse pointer, we should also make sure that it is visible. if (menuwindow::parent_) menuwindow::parent_->cursor(FL_CURSOR_DEFAULT); menustate pp; p = &pp; pp.p[0] = &mw; pp.nummenus = 1; pp.menubar = menubar; pp.state = INITIAL_STATE; pp.fakemenu = 0; // kludge for buttons in menubar // preselected item, pop up submenus if necessary: if (initial_item && mw.selected >= 0) { setitem(0, mw.selected); goto STARTUP; } pp.current_item = 0; pp.menu_number = 0; pp.item_number = -1; if (menubar) { // find the initial menu if (!mw.handle(FL_DRAG)) { Fl::grab(0); return 0; } } initial_item = pp.current_item; if (initial_item) { if (menubar && !initial_item->activevisible()) { // pointing at inactive item Fl::grab(0); return NULL; } goto STARTUP; } // the main loop: runs until p.state goes to DONE_STATE or the menu // widget is deleted (e.g. from a timer callback, see STR #3503): for (;;) { // make sure all the menus are shown: { for (int k = menubar; k < pp.nummenus; k++) { if (!pp.p[k]->shown()) { if (pp.p[k]->title) pp.p[k]->title->show(); pp.p[k]->show(); } } } // get events: { const Fl_Menu_Item* oldi = pp.current_item; Fl::wait(); if (pbutton && wp.deleted()) // menu widget has been deleted (STR #3503) break; if (pp.state == DONE_STATE) break; // done. if (pp.current_item == oldi) continue; } // only do rest if item changes: if(pp.fakemenu) {delete pp.fakemenu; pp.fakemenu = 0;} // turn off "menubar button" if (!pp.current_item) { // pointing at nothing // turn off selection in deepest menu, but don't erase other menus: pp.p[pp.nummenus-1]->set_selected(-1); continue; } if(pp.fakemenu) {delete pp.fakemenu; pp.fakemenu = 0;} initial_item = 0; // stop the startup code pp.p[pp.menu_number]->autoscroll(pp.item_number); STARTUP: menuwindow& cw = *pp.p[pp.menu_number]; const Fl_Menu_Item* m = pp.current_item; if (!m->activevisible()) { // pointing at inactive item cw.set_selected(-1); initial_item = 0; // turn off startup code continue; } cw.set_selected(pp.item_number); if (m==initial_item) initial_item=0; // stop the startup code if item found if (m->submenu()) { const Fl_Menu_Item* title = m; const Fl_Menu_Item* menutable; if (m->flags&FL_SUBMENU) menutable = m+1; else menutable = (Fl_Menu_Item*)(m)->user_data_; // figure out where new menu goes: int nX, nY; if (!pp.menu_number && pp.menubar) { // menu off a menubar: nX = cw.x() + cw.titlex(pp.item_number); nY = cw.y() + cw.h(); initial_item = 0; } else { nX = cw.x() + cw.w(); nY = cw.y() + pp.item_number * cw.itemheight; title = 0; } if (initial_item) { // bring up submenu containing initial item: menuwindow* n = new menuwindow(menutable,X,Y,W,H,initial_item,title,0,0,cw.x()); pp.p[pp.nummenus++] = n; if (pp.nummenus >= 2) pp.p[pp.nummenus-1]->origin = pp.p[pp.nummenus-2]; // move all earlier menus to line up with this new one: if (n->selected>=0) { int dy = n->y()-nY; int dx = n->x()-nX; int waX, waY, waW, waH; Fl_Window_Driver::driver(n)->menu_window_area(waX, waY, waW, waH, Fl::screen_num(X, Y)); for (int menu = 0; menu <= pp.menu_number; menu++) { menuwindow* tt = pp.p[menu]; int nx = tt->x()+dx; if (nx < waX) {nx = waX; dx = -tt->x() + waX;} int ny = tt->y()+dy; if (ny < waY) {ny = waY; dy = -tt->y() + waY;} tt->position(nx, ny); } setitem(pp.nummenus-1, n->selected); goto STARTUP; } } else if (pp.nummenus > pp.menu_number+1 && pp.p[pp.menu_number+1]->menu == menutable) { // the menu is already up: while (pp.nummenus > pp.menu_number+2) delete pp.p[--pp.nummenus]; pp.p[pp.nummenus-1]->set_selected(-1); } else { // delete all the old menus and create new one: while (pp.nummenus > pp.menu_number+1) delete pp.p[--pp.nummenus]; pp.p[pp.nummenus++]= new menuwindow(menutable, nX, nY, title?1:0, 0, 0, title, 0, menubar, (title ? 0 : cw.x()) ); if (pp.nummenus >= 2 && pp.p[pp.nummenus-2]->itemheight) { pp.p[pp.nummenus-1]->origin = pp.p[pp.nummenus-2]; } } } else { // !m->submenu(): while (pp.nummenus > pp.menu_number+1) delete pp.p[--pp.nummenus]; if (!pp.menu_number && pp.menubar) { // kludge so "menubar buttons" turn "on" by using menu title: pp.fakemenu = new menuwindow(0, cw.x()+cw.titlex(pp.item_number), cw.y()+cw.h(), 0, 0, 0, m, 0, 1); pp.fakemenu->title->show(); } } } const Fl_Menu_Item* m = (pbutton && wp.deleted()) ? NULL : pp.current_item; delete pp.fakemenu; while (pp.nummenus>1) delete pp.p[--pp.nummenus]; mw.hide(); Fl::grab(0); menuwindow::parent_ = NULL; return m; } /** This method is called by widgets that want to display menus. The menu stays up until the user picks an item or dismisses it. The selected item (or NULL if none) is returned. This does not do the callbacks or change the state of check or radio items. The menu is positioned so the cursor is centered over the item picked. This will work even if \p picked is in a submenu. If \p picked is zero or not in the menu item table the menu is positioned with the cursor in the top-left corner. \param[in] X,Y the position of the mouse cursor, relative to the window that got the most recent event (usually you can pass Fl::event_x() and Fl::event_y() unchanged here). \param[in] title a character string title for the menu. If non-zero a small box appears above the menu with the title in it. \param[in] picked if this pointer is not NULL, the popup menu will appear so that the picked menu is under the mouse pointer. \param[in] menu_button is a pointer to an Fl_Menu_ from which the color and boxtypes for the menu are pulled. If NULL then defaults are used. \return a pointer to the menu item selected by the user, or NULL */ const Fl_Menu_Item* Fl_Menu_Item::popup( int X, int Y, const char* title, const Fl_Menu_Item* picked, const Fl_Menu_* menu_button ) const { static Fl_Menu_Item dummy; // static so it is all zeros dummy.text = title; return pulldown(X, Y, 0, 0, picked, menu_button, title ? &dummy : 0); } static bool is_special_labeltype(uchar t) { return t == _FL_MULTI_LABEL || t == _FL_ICON_LABEL || t == _FL_IMAGE_LABEL; } /** Search only the top level menu for a shortcut. Either &x in the label or the shortcut fields are used. This tests the current event, which must be an FL_KEYBOARD or FL_SHORTCUT, against a shortcut value. \param ip returns the index of the item, if \p ip is not NULL. \param require_alt if true: match only if Alt key is pressed. \return found Fl_Menu_Item or NULL */ const Fl_Menu_Item* Fl_Menu_Item::find_shortcut(int* ip, const bool require_alt) const { const Fl_Menu_Item* m = this; if (m) for (int ii = 0; m->text; m = next_visible_or_not(m), ii++) { if (m->active()) { if (Fl::test_shortcut(m->shortcut_) || (!is_special_labeltype(m->labeltype_) && Fl_Widget::test_shortcut(m->text, require_alt)) || (m->labeltype_ == _FL_MULTI_LABEL && !is_special_labeltype(((Fl_Multi_Label*)m->text)->typea) && Fl_Widget::test_shortcut(((Fl_Multi_Label*)m->text)->labela, require_alt)) || (m->labeltype_ == _FL_MULTI_LABEL && !is_special_labeltype(((Fl_Multi_Label*)m->text)->typeb) && Fl_Widget::test_shortcut(((Fl_Multi_Label*)m->text)->labelb, require_alt))) { if (ip) *ip=ii; return m; } } } return 0; } // Recursive search of all submenus for anything with this key as a // shortcut. Only uses the shortcut field, ignores &x in the labels: /** This is designed to be called by a widgets handle() method in response to a FL_SHORTCUT event. If the current event matches one of the items shortcut, that item is returned. If the keystroke does not match any shortcuts then NULL is returned. This only matches the shortcut() fields, not the letters in the title preceeded by ' */ const Fl_Menu_Item* Fl_Menu_Item::test_shortcut() const { const Fl_Menu_Item* m = this; const Fl_Menu_Item* ret = 0; if (m) for (; m->text; m = next_visible_or_not(m)) { if (m->active()) { // return immediately any match of an item in top level menu: if (Fl::test_shortcut(m->shortcut_)) return m; // if (Fl_Widget::test_shortcut(m->text)) return m; // only return matches from lower menu if nothing found in top menu: if (!ret && m->submenu()) { const Fl_Menu_Item* s = (m->flags&FL_SUBMENU) ? m+1:(const Fl_Menu_Item*)m->user_data_; ret = s->test_shortcut(); } } } return ret; } fltk-1.4.3/src/Fl_Sys_Menu_Bar.cxx0000644000175000017500000002073315004135251017074 0ustar albrechtalbrecht// // system menu bar widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Sys_Menu_Bar_Driver.H" #include #include "Fl_System_Driver.H" Fl_Sys_Menu_Bar *fl_sys_menu_bar = 0; /** The constructor. On Mac OS X, all arguments are unused. On other platforms they are used as by Fl_Menu_Bar::Fl_Menu_Bar(). */ Fl_Sys_Menu_Bar::Fl_Sys_Menu_Bar(int x,int y,int w,int h,const char *l) : Fl_Menu_Bar(x,y,w,h,l) { if (driver()) { if (fl_sys_menu_bar) delete fl_sys_menu_bar; fl_sys_menu_bar = this; driver()->bar = this; // Remove macOS menubar from its parent Fl_Group so it's activated // by system menu shortcuts Fl_Group *p = parent(); if (p) p->remove(this); } } /** The destructor */ Fl_Sys_Menu_Bar::~Fl_Sys_Menu_Bar() { if (driver()) { fl_sys_menu_bar = 0; clear(); } } void Fl_Sys_Menu_Bar::update() { if (driver()) driver()->update(); } /** \brief create a system menu bar using the given list of menu structs \author Matthias Melcher \param m Zero-ending list of Fl_Menu_Item's */ void Fl_Sys_Menu_Bar::menu(const Fl_Menu_Item *m) { if (driver()) driver()->menu(m); else Fl_Menu_Bar::menu(m); } /** Changes the shortcut of item i to n. */ void Fl_Sys_Menu_Bar::shortcut (int i, int s) { if (driver()) driver()->shortcut(i, s); else Fl_Menu_Bar::shortcut(i, s); } /** Turns the radio item "on" for the menu item and turns "off" adjacent radio items of the same group.*/ void Fl_Sys_Menu_Bar::setonly (Fl_Menu_Item *item) { if (driver()) driver()->setonly(item); else Fl_Menu_Bar::setonly(item); } /** Sets the flags of item i \see Fl_Menu_::mode(int i, int fl) */ void Fl_Sys_Menu_Bar::mode (int i, int fl) { if (driver()) driver()->mode(i, fl); else Fl_Menu_Bar::mode(i, fl); } /** \brief Add a new menu item to the system menu bar. Add to the system menu bar a new menu item, with a title string, shortcut int, callback, argument to the callback, and flags. \param label - new menu item's label \param shortcut - new menu item's integer shortcut (can be 0 for none, or e.g. FL_ALT+'x') \param cb - callback to be invoked when item selected (can be 0 for none, in which case the menubar's callback() can be used instead) \param user_data - argument to the callback \param flags - item's flags, e.g. ::FL_MENU_TOGGLE, etc. \returns the index into the menu() array, where the entry was added \see Fl_Menu_::add(const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) */ int Fl_Sys_Menu_Bar::add(const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) { if (driver()) return driver()->add(label, shortcut, cb, user_data, flags); else return Fl_Menu_Bar::add(label, shortcut, cb, user_data, flags); } /** Forms-compatible procedure to add items to the system menu bar \returns the index into the menu() array, where the entry was added \see Fl_Menu_::add(const char* str) */ int Fl_Sys_Menu_Bar::add(const char* str) { return driver() ? driver()->add(str) : Fl_Menu_Bar::add(str); } /** \brief insert in the system menu bar a new menu item Insert in the system menu bar a new menu item, with a title string, shortcut int, callback, argument to the callback, and flags. \returns the index into the menu() array, where the entry was inserted \see Fl_Menu_::insert(int index, const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) */ int Fl_Sys_Menu_Bar::insert(int index, const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) { return driver() ? driver()->insert(index, label, shortcut, cb, user_data, flags) : Fl_Menu_Bar::insert(index, label, shortcut, cb, user_data, flags); } /** Set the Fl_Menu_Item array pointer to null, indicating a zero-length menu. \see Fl_Menu_::clear() */ void Fl_Sys_Menu_Bar::clear() { if (driver()) driver()->clear(); else Fl_Menu_Bar::clear(); } /** Clears the specified submenu pointed to by index of all menu items. \see Fl_Menu_::clear_submenu(int index) */ int Fl_Sys_Menu_Bar::clear_submenu(int index) { return driver() ? driver()->clear_submenu(index) : Fl_Menu_Bar::clear_submenu(index); } /** \brief remove an item from the system menu bar \param index the index of the item to remove */ void Fl_Sys_Menu_Bar::remove(int index) { if (driver()) driver()->remove(index); else Fl_Menu_Bar::remove(index); } /** \brief rename an item from the system menu bar \param index the index of the item to rename \param name the new item name as a UTF8 string */ void Fl_Sys_Menu_Bar::replace(int index, const char *name) { if (driver()) driver()->replace(index, name); else Fl_Menu_Bar::replace(index, name); } /** Attaches a callback to the "About myprog" item of the system application menu. This cross-platform function is effective only under the MacOS platform. \param cb a callback that will be called by "About myprog" menu item with NULL 1st argument. \param data a pointer transmitted as 2nd argument to the callback. */ void Fl_Sys_Menu_Bar::about(Fl_Callback *cb, void *data) { if (driver()) { fl_open_display(); // create the system menu, if needed driver()->about(cb, data); } } void Fl_Sys_Menu_Bar::draw() { if (driver()) driver()->draw(); else Fl_Menu_Bar::draw(); } /** Get the style of the Window menu in the system menu bar */ Fl_Sys_Menu_Bar::window_menu_style_enum Fl_Sys_Menu_Bar::window_menu_style() { return driver() ? Fl_Sys_Menu_Bar_Driver::window_menu_style() : no_window_menu; } /** Set the desired style of the Window menu in the system menu bar. This function, to be called before the first call to Fl_Window::show(), allows to control whether the system menu bar should contain a Window menu, and if yes, whether new windows should be displayed in tabbed form. These are the effects of various values for \p style : \li \c no_window_menu : don't add a Window menu to the system menu bar \li \c tabbing_mode_none : add a simple Window menu to the system menu bar \li \c tabbing_mode_automatic : the window menu also contains "Merge All Windows" to group all windows in a single tabbed display mode. This is the \b default Window menu style for FLTK apps. \li \c tabbing_mode_preferred : new windows are displayed in tabbed mode when first created The Window menu, if present, is entirely created and controlled by the FLTK library. Mac OS version 10.12 or later must be running for windows to be displayed in tabbed form. Under non MacOS platforms, this function does nothing. \version 1.4 */ void Fl_Sys_Menu_Bar::window_menu_style(Fl_Sys_Menu_Bar::window_menu_style_enum style) { if (driver()) Fl_Sys_Menu_Bar_Driver::window_menu_style(style); } /** Adds a Window menu, to the end of the system menu bar. FLTK apps typically don't need to call this function which is automatically called by the library the first time a window is shown. The default system menu bar contains a Window menu with a "Merge All Windows" item. Other Window menu styles can be obtained calling Fl_Sys_Menu_Bar::window_menu_style(window_menu_style_enum) before the first Fl_Window::show(). Alternatively, an app can call create_window_menu() after having populated the system menu bar, for example with menu(const Fl_Menu_Item *), and before the first Fl_Window::show(). This function does nothing on non MacOS platforms. \version 1.4 */ void Fl_Sys_Menu_Bar::create_window_menu() { if (driver()) { fl_open_display(); fl_sys_menu_bar->driver()->create_window_menu(); } } void Fl_Sys_Menu_Bar::play_menu(const Fl_Menu_Item *item) { Fl_Sys_Menu_Bar_Driver *dr = driver(); if (dr) dr->play_menu(item); else Fl_Menu_Bar::play_menu(item); } #if !defined(FL_DOXYGEN) Fl_Sys_Menu_Bar_Driver *Fl_Sys_Menu_Bar::driver() { return Fl::system_driver()->sys_menu_bar_driver(); } Fl_Sys_Menu_Bar_Driver *Fl_Sys_Menu_Bar_Driver::driver_ = 0; Fl_Sys_Menu_Bar_Driver::Fl_Sys_Menu_Bar_Driver() {bar = NULL;} Fl_Sys_Menu_Bar_Driver::~Fl_Sys_Menu_Bar_Driver() {} Fl_Sys_Menu_Bar::window_menu_style_enum Fl_Sys_Menu_Bar_Driver::window_menu_style_ = Fl_Sys_Menu_Bar::tabbing_mode_automatic; #endif // !defined(FL_DOXYGEN) fltk-1.4.3/src/fl_encoding_latin1.cxx0000644000175000017500000000320515004135251017637 0ustar albrechtalbrecht// // Convert Windows-1252 (Latin-1) encoded text to the local encoding. // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include "Fl_System_Driver.H" #include #include #include "flstring.h" /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** Default implementation of latin-to-local text conversion. The default implementation returns the original text. This method should be reimplemented by drivers for platforms that commonly use latin text encoding. \see fl_latin1_to_local(const char *, int) */ const char *Fl_System_Driver::latin1_to_local(const char *t, int) { return t; } /** Default implementation of local-to-latin text conversion. The default implementation returns the original text. This method should be reimplemented by drivers for platforms that commonly use latin text encoding. \see fl_local_to_latin1(const char *, int) */ const char *Fl_System_Driver::local_to_latin1(const char *t, int) { return t; } /** \} \endcond */ const char *fl_latin1_to_local(const char *t, int n) { return Fl::system_driver()->latin1_to_local(t, n); } const char *fl_local_to_latin1(const char *t, int n) { return Fl::system_driver()->local_to_latin1(t, n); } fltk-1.4.3/src/README-Fl_Terminal.txt0000644000175000017500000010627115004135251017273 0ustar albrechtalbrecht// vim: autoindent tabstop=8 shiftwidth=4 expandtab softtabstop=4 Fl_Terminal Design Document =========================== When I started this project, I identified the key concepts needed to implement Fl_Terminal: - Draw and manage multiline Unicode text in FLTK effectively, allowing per-character colors and attributes like underline, strikeout, background, etc. - An efficient screen buffer to handle the "scrollback history" and "screen display" concepts; the "history" being a scrollback history of text that scrolls up and off screen from the "display", and the "display" being where the action is: the cursor can be moved around and text scrolled up or down. - How the vertical scrollbar should provide the user with a way to scroll back into the scrollback history to allow the user to scroll back to view the "scrollback history", without stopping the "screen display" from operating - How to manage mouse selection for copy/paste - Escape code management to implement VT100 style / ANSI escape codes. ┌─────────────────────────────────────────┬──────────────────────────────┐ │ NOTE: Abbreviations "hist" and "disp" │ │ ├─────────────────────────────────────────┘ │ │ │ │ "history" may be abbreviated as "hist", and "display" as "disp" in │ │ both this text and the source code. 4 character names are used so │ │ they line up cleanly in the source, e.g. │ │ │ │ ring_cols = 0; ring_rows = 0; │ │ hist_cols = 0; ring_cols = 0; │ │ disp_cols = 0; ring_cols = 0; │ │ └─┬┘ └─┬┘ │ │ └────┴─── 4 characters │ │ │ └────────────────────────────────────────────────────────────────────────┘ So the of these concepts were able to fit into C++ class concepts well. Those classes being: Utf8Char ======== Each character on the screen is a "Utf8Char" which can manage the utf8 encoding of any character as one or more bytes. Also in that class is a byte for an attribute (underline, bold, etc), and two integers for fg/bg color. RingBuffer ========== The RingBuffer class keeps track of the buffer itself, a single array of Utf8Chars called "ring_chars", and some index numbers to keep track of how many rows are in the screen's history and display, named "hist_rows" and "disp_rows". The memory layout of the Utf8Char array is: ___________________ _ _ | | ʌ | | | | | | | H i s t o r y | | hist_rows | | | | | | |___________________| _v_ | | ʌ | | | | D i s p l a y | | disp_rows | | | |___________________| _v_ |<----------------->| ring_cols So it's basically a single continguous array of Utf8Char instances where any character can be accessed by index# using the formula: ring_chars[ (row*ring_cols)+col ] ..where 'row' is the desired row, 'col' is the desired column, and 'ring_cols' is how many columns "wide" the buffer is. Methods are used to give access the characters in the buffer. A key concept is to allow the starting point of the history and display to be moved around to implement 'text scrolling', such as when crlf at the screen bottom causes a 'scroll up'. This is simply an "index offset" integer applied to the hist and disp indexes when drawing the display, e.g. Offset is 0: 2 Offset now 2: ┌───────────────────┐ ──┐ ┌───────────────────┐ │ │ │ │ D i s p l a y │ │ │ └─> ├───────────────────┤ │ │ │ │ │ H i s t o r y │ │ │ │ │ │ H i s t o r y │ │ │ 2 │ │ ├───────────────────┤ ──┐ │ │ │ │ │ │ │ │ │ └─> ├───────────────────┤ │ D i s p l a y │ │ │ │ │ │ D i s p l a y │ │ │ │ │ └───────────────────┘ └───────────────────┘ Offset is 0: 4 Offset now 4: ┌───────────────────┐ ──┐ ┌───────────────────┐ │ │ │ │ │ │ │ │ │ D i s p l a y │ │ │ │ │ │ │ H i s t o r y │ └─> ├───────────────────┤ │ │ │ │ │ │ 4 │ │ ├───────────────────┤ ──┐ │ H i s t o r y │ │ │ │ │ │ │ │ │ │ │ │ D i s p l a y │ │ │ │ │ │ └─> ├───────────────────┤ │ │ │ D i s p l a y │ └───────────────────┘ └───────────────────┘ The effect of applying an offset trivially implements "text scrolling", so that no screen memory has to physically moved around, simply changing the single integer "offset" is enough. The text remains where it was, and the offset is simply incremented to scroll up. This also automatically makes it appear the top line in the display is 'scrolled up' into the last line of the scrollback history. If the offset exceeds the size of the ring buffer, it is simply wrapped back to the beginning of the buffer with a modulo: offset =% ring_rows; Indexes into the display and history are also modulo their respective rows, e.g. act_ring_index = (hist_rows + disp_row + offset - scrollbar_pos) % ring_rows; This way indexes for ranges can run beyond the bottom of the ring, and automatically wrap around the ring, e.g. Offset now 4: ┌───────────────────┐ 2 │ │ 3 │ D i s p l a y │ 4 │ │ <- act_disp_row(4) ├───────────────────┤ │ │ │ │ │ H i s t o r y │ │ │ │ │ │ │ ├───────────────────┤ 0 │ D i s p l a y │ 1 └───────────────────┘ <- ring_rows 2 : : 3 : : disp_row(5) -> 4 :...................: Here the "disp_row" is the desired offset into the display, but we need the actual index into the ring from the top, since that's the physical array. So some simple math calculates the row position based on the "offset", and the "hist" vs "disp" concepts: act_ring_index = (histrows // the display exists AFTER the history, so offset the hist_rows + offset // include the scroll 'offset' + disp_row // add the desired row relative to the top of the display (0..disp_rows) ) % ring_rows; // make sure the resulting index is within the ring buffer (0..ring_rows) An additional bit of math makes sure if a negative result occurs, that negative value works relative to the end of the ring, e.g. if (act_ring_index < 0) act_ring_index = ring_rows + act_ring_index; This guaratnees the act_ring_index is within the ring buffer's address space, with all offsets applied. The math that implements this can be found in the u8c_xxxx_row() methods, where "xxxx" is one of the concept regions "ring", "hist" or "disp": Utf8Char *u8c; u8c = u8c_ring_row(rrow); // address within ring, rrow can be 0..(ring_rows-1) u8c = u8c_hist_row(hrow); // address within hist, hrow can be 0..(hist_rows-1) u8c = u8c_disp_row(drow); // address within disp, drow can be 0..(disp_rows-1) The small bit of math is only involved whenever a new row address is needed, so in a display that's 80x25, to walk all the characters in the screen, the math above would only be called 25 times, once for each row, e.g. for ( int row=0; row └──────────────────┘ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ CASE 2: ENLARGE, ADDING LINES BELOW CURSOR ┌──────────────────┐ ┌──────────────────┐ 1│ Line 1 │ 1│ Line 1 │ 2│ Line 2 │ enlarge 2│ Line 2 │ 3│ Hello! │ 3│ Hello! │ 4│ ▒ │ 4│ ▒ │ └──────────────────┘ ──┐ 5│ │ │ 6│ │ └──────> └──────────────────┘ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ CASE 3: SHRINK, TRIMMING LINES BELOW CURSOR ┌──────────────────┐ ┌──────────────────┐ 1│ Line 1 │ 1│ Line 1 │ 2│ Line 2 │ 2│ Line 2 │ 3│ Hello! │ resize 3│ Hello! │ 4│ ▒ │ 4│ ▒ │ 5│ │ ╭────> └──────────────────┘ 6│ │ │ 5 ┐ Lines below cursor erased └──────────────────┘ ──╯ 6 ┘ (regardless of contents) ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ ┄ CASE 4: SHRINK, PUSH TO HISTORY: -2 Line 1 ┐_ moved into -1 Line 2 ┘ scrollback history ┌──────────────────┐ ┌──────────────────┐ 1│ Line 1 │ 1│ Hello! │ 2│ Line 2 │ resize 2│ ▒ │ 3│ Hello! │ ╭────> └──────────────────┘ 4│ ▒ │ │ └──────────────────┘ ──╯ These case numbers (CASE 1 tru 4) are referenced in the source code for Fl_Terminal::refit_disp_to_screen(void). OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD RING BUFFER DESCRIPTION ======================= The history and display are defined by row indexes into this buffer which are adjusted whenever the text display is 'scrolled' (e.g. by crlfs) The scrollbar is a secondary offset on top of that applied during drawing. the display. Here's what the variables managing the split ring buffer look like: RING BUFFER ─ ring_chars[] ─┬─>┌───────────────┐ ʌ [hist_srow] ──┘ │ │ ┊ │ │ ┊ │ H i s t o r y ┊ hist_rows_┊ │ │ ┊ │ │ ┊ │ │ ┊ │ │ v [hist_erow] ───>│ │ ─ [disp_srow] ───>├───────────────┤ ʌ │ │ ┊ │ │ disp_rows_┊ │ D i s p l a y │ ┊ │ │ ┊ │ │ v [ring_erow] ───>│ +│<── ring_bot_ ─ └───────────────┘ (last valid ptr address in ring) │<──────┬──────>│ ring_cols hist_cols disp_cols The concept here is the single ring buffer is split into two parts that can differ in height (rows) but not in width (cols). For instance, typically the history is many times larger than the display; a typical old school display might be 80x25, but the history might be 2000 lines. ring_row() handles the fact that 'row' might run off the end of the buffer, depending on where hist_srow starts. For instance, if the display has scrolled a few lines, the ring buffer arrangement might look like: RING BUFFER ring_chars[] ───>┌───────────────┐ │ D i s p l a y │ [disp_erow] ───>│ │ ├───────────────┤ [hist_srow] ───>│ │ │ │ │ H i s t o r y │ │ │ │ │ │ │ [hist_erow] ───>│ │ ├───────────────┤ [disp_srow] ───>│ │ │ D i s p l a y │ │ │ [ring_erow] ───>│ +│<── ring_bot_ └───────────────┘ (last valid ptr address in ring) Note how the display 'wraps around', straddling the end of the ring buffer. So trivially walking ring_chars[] from 'disp_srow' for 'disp_rows' would run off the end of memory for the ring buffer. Example: // BAD! for ( int row=disp_srow; rowdo_something(); // BAD! can run off end of array } } The function u8c_row() can access the Utf8Char* of each row more safely, ensuring that even if the 'row' index runs off the end of the array, u8c_row() handles wrapping it for you. So the safe way to walk the chars of the display can be done this way: // GOOD! for ( int row=disp_srow; rowdo_something(); // get/set the utf8 char } } Walking the history would be the same, just replace disp_xxxx with hist_xxxx. One can also use ring_row_normalize() to return an index# that can be directly used with ring_chars[], the value kept in range of the buffer. RING BUFFER "SCROLLING" ======================= A ring buffer is used to greatly simplify the act of 'scrolling', which happens a lot when large amounts of data come in, each CRLF triggering a "scroll" that moves the top line up into the history buffer. The history buffer can be quite large (1000's of lines), so it would suck if, on each line scroll, thousands of rows of Utf8Chars had to be physically moved in memory. Much easier to just adjust the srow/erow pointers, which simply affect how drawing is done, and where the display area is. This trivially handles scrolling by just adjusting some integers by 1. -- -- HOW SCROLLING UP ONE LINE IS DONE -- -- ring_chars[] ─┬─>┌───────────────┐ ─┐ ring_chars[] ──>┌─────────────────┐ [hist_srow] ──┘ │ │ │ │x x x x x x x x x│ <-- blanks │ │ └─> [hist_srow] ──>├─────────────────┤ │ H i s t │ │ │ │ │ │ │ │ │ │ H i s t │ │ │ │ │ │ │ │ │ [hist_erow] ───>│ │ │ │ [disp_srow] ───>├Line 1─────────┤ ─┐ [hist_erow] ──>│Line 1 │ │Line 2 │ └─> [disp_srow] ──>├Line 2───────────┤ │Line 3 │ │Line 3 │ │ │ │ │ │ D i s p │ │ D i s p │ │ │ │ │ [disp_erow][ring_erow] ───>│Line 24 +│ [ring_erow] ──>│Line 24 +│ └───────────────┘ └─────────────────┘ In the above, Line 1 has effectively "moved" into history because the disp_s/erow and hist_s/erow variables have just been incremented. During resize_display(), we need to preserve the display and history as much as possible when the ring buffer is enlarged/shrank; the hist_rows size should be maintained, and only display section changes size based on the FLTK window size. ===================== OLD ====================== OLD ====================== OLD ====================== Conventions used for the internals ================================== This is a large widget, and these are some breadcrumbs for anyone working on the internals of this class. > There is one utf8 char buffer, buff_chars[], the top part is the 'history buffer' (which the user can scroll back to see), and the 'display buffer' which is the 'active display'. > glob or global - refers to global buffer buff_chars[] > disp or display - refers to display buffer disp_chars[] > Abbreviations glob/disp/buff/hist used because 4 chars line up nicely > row/col variable names use a 'g' or 'd' prefix to convey 'g'lobal or 'd'isplay. > The 'Cursor' class uses row/col for the display (disp_chars[]) because the cursor is only ever inside the display. > The 'Selection' class uses row/col for the global buffer (buff_chars[]) because it can be in the 'history' or the 'display' > These concepts talk about the same thing: > global buffer == buff_chars[] == "history buffer" == hist == grow/gcol > display == disp_chars[] == "active display" == drow/dcol > There is no hist_chars[] because it's just the top half of buff_chars[] > There is no hist_height_ because it's the same as hist_max_ > There is no hist_width_ because it's the same as buff_width_. Fl_Terminal's Class Hierarchy ============================= class Fl_Terminal -- Derived from Fl_Group (to parent scrollbars, popup menus, etc) We mainly use the group's background to draw over in draw(). Within the terminal classes are the following private/protected classes that help with bookkeeping and operation of the terminal class: class Margin -- Handles the margins around the terminal drawing area class CharStyle -- The styling for the characters: single byte color + attribute (bold/inverse/etc) class Cursor -- The attributes of the cursor -- position, color, etc, and some simple movement logic class Utf8Char -- Visible screen buffer is an array of these, one per character class RingBuffer -- The ring buffer of Utf8Char's, with the "history" and "display" concept. class EscapeSeq -- A class to handle parsing Esc sequences, and keeping state info between chars Single chars go in, and when a complete esc sequence is parsed, the caller can find out all the integer values and command code easily to figure out what op to do. OVERALL DESIGN: To handle unicode, the terminal's visible display area is a linear array of pointers to instances of the 'Utf8Char' class, one instance per character. The arrangement of the array is much like the IBM PC's video memory, but instead of Char/Attrib byte pairs, the Utf8Char class handles the more complex per-character data and colors/attributes. The cursor x,y value can be quickly converted to an index into this buffer. Strings are printed into the buffer, again, similar to the IBM PC video memory; one character at a time into the Utf8Char class instances. When the screen redraws, it just walks this array, and calls fl_draw() to draw the text, one utf8 char at a time, with the colors/fonts/attributes from the Utf8Char class. As characters are added, Esc sequences are intercepted and parsed into the EscapeSeq class, which has a single instance for the terminal. For the scrollback history, as lines scrolls off the top of the active display area, the Utf8Char's are copied to the history buffer, and the active display's top line is simply rotated to the bottom line and cleared, allowing memory reuse of the Utf8Char's, to prevent memory churn for the display. The goal is to allow high volume output to the terminal with a minimum affect on realloc'ing memory. OPTIMIZATIONS Where possible, caching is used to prevent repeated calls to cpu expensive operations, such as anything to do with calculating unicode character width/height/etc. RingBuffer The ring buffer is split in two; the top part is the history, the bottom part is the "display area", where new text comes in, where the cursor can be positioned, and concepts like "scroll up" and "scroll down" all happen. The "history" is simply a linear buffer where lines pushed up from the display are moved into. Methods let one access the ring with index#s: - The entire ring buffer can be accessed with: for (int i=0; i #include #include #include #include #include "flstring.h" // // 'hexdigit()' - Convert a hex digit to an integer. // static int hexdigit(int x) { // I - Hex digit... if (isdigit(x)) return x-'0'; if (isupper(x)) return x-'A'+10; if (islower(x)) return x-'a'+10; return 20; } #define MAXSIZE 2048 #define INITIALLINES 256 /** The constructor loads the XPM image from the name filename. The destructor frees all memory and server resources that are used by the image. */ Fl_XPM_Image::Fl_XPM_Image(const char *name) : Fl_Pixmap((char *const*)0) { FILE *f; if ((f = fl_fopen(name, "rb")) == NULL) return; // read all the c-strings out of the file: char** new_data = new char *[INITIALLINES]; char** temp_data; int malloc_size = INITIALLINES; char buffer[MAXSIZE+20]; int i = 0; int W,H,ncolors,chars_per_pixel; while (fgets(buffer,MAXSIZE+20,f)) { if (buffer[0] != '\"') continue; char *myp = buffer; char *q = buffer+1; while (*q != '\"' && myp < buffer+MAXSIZE) { if (*q == '\\') switch (*++q) { case '\r': case '\n': if (!fgets(q,(int) (buffer+MAXSIZE+20-q),f)) { /* no problem if we hit EOF */ } break; case 0: break; case 'x': { q++; int n = 0; for (int x = 0; x < 2; x++) { int xd = hexdigit(*q); if (xd > 15) break; n = (n<<4)+xd; q++; } *myp++ = n; } break; default: { int c = *q++; if (c>='0' && c<='7') { c -= '0'; for (int x=0; x<2; x++) { int xd = hexdigit(*q); if (xd>7) break; c = (c<<3)+xd; q++; } } *myp++ = c; } break; } else { *myp++ = *q++; } } *myp++ = 0; if (i >= malloc_size) { temp_data = new char *[malloc_size + INITIALLINES]; memcpy(temp_data, new_data, sizeof(char *) * malloc_size); delete[] new_data; new_data = temp_data; malloc_size += INITIALLINES; } // first line has 4 ints: width, height, ncolors, chars_per_pixel // followed by color segment: // if ncolors < 0 this is FLTK (non standard) compressed colormap - all colors coded in single line of 4*ncolors bytes // otherwise - ncolor lines of at least chars_per_pixel bytes // followed by pic segment: H lines of at least chars_per_pixel*W bytes // next line: would have loved to use measure_pixmap, but it doesn't return all the data! if ((!i) && (sscanf(buffer,"%d%d%d%d", &W, &H, &ncolors, &chars_per_pixel) < 4)) goto bad_data; // first line else if ((i > (ncolors<0?1:ncolors)) && (myp-buffer-1 0) delete[] new_data[--i]; delete[] new_data; if (f) fclose(f); } fltk-1.4.3/src/forms_fselect.cxx0000644000175000017500000000331315004135251016753 0ustar albrechtalbrecht// // Forms file selection routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Emulate the Forms file chooser using the fltk file chooser. #include #include "flstring.h" static char fl_directory[FL_PATH_MAX]; static const char *fl_pattern; // assumed passed value is static static char fl_filename[FL_PATH_MAX]; char* fl_show_file_selector(const char *message,const char *dir, const char *pat,const char *fname) { if (dir && dir[0]) strlcpy(fl_directory,dir,sizeof(fl_directory)); if (pat && pat[0]) fl_pattern = pat; if (fname && fname[0]) strlcpy(fl_filename,fname,sizeof(fl_filename)); char *p = fl_directory+strlen(fl_directory); if (p > fl_directory && *(p-1)!='/' #ifdef _WIN32 && *(p-1)!='\\' && *(p-1)!=':' #endif ) *p++ = '/'; strlcpy(p,fl_filename,sizeof(fl_directory) - (p - fl_directory)); const char *q = fl_file_chooser(message,fl_pattern,fl_directory); if (!q) return 0; strlcpy(fl_directory, q, sizeof(fl_directory)); p = (char *)fl_filename_name(fl_directory); strlcpy(fl_filename, p, sizeof(fl_filename)); if (p > fl_directory+1) p--; *p = 0; return (char *)q; } char* fl_get_directory() {return fl_directory;} char* fl_get_pattern() {return (char *)fl_pattern;} char* fl_get_filename() {return fl_filename;} fltk-1.4.3/src/Fl_Copy_Surface.cxx0000644000175000017500000000372415004135251017131 0ustar albrechtalbrecht// // Copy-to-clipboard code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include /** the constructor \param w, h Width and height of the drawing surface in FLTK units */ Fl_Copy_Surface::Fl_Copy_Surface(int w, int h) : Fl_Widget_Surface(NULL) { platform_surface = Fl_Copy_Surface_Driver::newCopySurfaceDriver(w, h); if (platform_surface) driver(platform_surface->driver()); } /** the destructor */ Fl_Copy_Surface::~Fl_Copy_Surface() { delete platform_surface; } void Fl_Copy_Surface::origin(int x, int y) {platform_surface->origin(x, y);} void Fl_Copy_Surface::origin(int *x, int *y) { if (platform_surface) platform_surface->origin(x, y); } void Fl_Copy_Surface::set_current() { if (platform_surface) platform_surface->set_current(); } bool Fl_Copy_Surface::is_current() { return surface() == platform_surface; } void Fl_Copy_Surface::translate(int x, int y) { if (platform_surface) platform_surface->translate(x, y); } void Fl_Copy_Surface::untranslate() { if (platform_surface) platform_surface->untranslate(); } int Fl_Copy_Surface::w() {return platform_surface ? platform_surface->width : 0;} int Fl_Copy_Surface::h() {return platform_surface ? platform_surface->height : 0;} int Fl_Copy_Surface::printable_rect(int *w, int *h) { if (platform_surface) return platform_surface->printable_rect(w, h); else { *w = *h = 0; } return 1; } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ int Fl_Copy_Surface_Driver::printable_rect(int *w, int *h) { *w = width; *h = height; return 0; } /** \} \endcond */ fltk-1.4.3/src/Fl_own_colormap.cxx0000644000175000017500000000247715004135251017252 0ustar albrechtalbrecht// // Private colormap support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Using the default system colormap can be a bad idea on PseudoColor // visuals, since typically every application uses the default colormap and // you can run out of colormap entries easily. // // The solution is to always create a new colormap on PseudoColor displays // and copy the first 16 colors from the default colormap so that we won't // get huge color changes when switching windows. #include #include "Fl_Screen_Driver.H" /** \fn Fl::own_colormap() Makes FLTK use its
own colormap. This may make FLTK display better and will reduce conflicts with other programs that want lots of colors. However the colors may flash as you move the cursor between windows.

This does nothing if the current visual is not colormapped. */ void Fl::own_colormap() { Fl::screen_driver()->own_colormap(); } fltk-1.4.3/src/Fl_String.H0000644000175000017500000001022115004135251015370 0ustar albrechtalbrecht// // Basic Fl_String header for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _FL_Fl_String_H_ #define _FL_Fl_String_H_ /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** \file src/Fl_String.H Basic Fl_String class for FLTK. */ #include // See: https://en.cppreference.com/w/cpp/string/basic_string/basic_string /** Fl_String is the basic string class for FLTK. In this version Fl_String can be used to store strings, copy strings, move strings, and do basic string manipulation. Fl_String implements a subset of std::string with a couple of extensions. std::string should be a drop-in if we ever decide to allow templates and the std library. Fl_String always maintains a trailing \e nul byte, but can also contain \e nul bytes inside the string if the constructor Fl_String(const char *str, int size) is used. Assignment and copy constructors \b copy the string value such that the source string can be freed immediately after the assignment. c_str() and data() can be an empty string \c "", but never be \c NULL. The method size() returns the full string size, whether the string contains embedded \c nul bytes or not. The special method Fl_String::strlen() returns the length of the string up to the first \e nul. All methods of Fl_String work on a byte level. They are not UTF-8 aware, but may hold and manipulate UTF-8 strings if done with care. \since 1.4.0 */ class FL_EXPORT Fl_String { private: /* FLTK does no small string optimization. If the string is empty and capacity is not set, buffer_ will be NULL. */ char *buffer_; int size_; int capacity_; void init_(); void grow_(int n); void shrink_(int n); Fl_String &replace_(int at, int n_del, const char *src, int n_ins); protected: static const char NUL; public: static const int npos; // ---- Assignment Fl_String(); Fl_String(const Fl_String &str); Fl_String(const char *cstr); Fl_String(const char *str, int size); ~Fl_String(); Fl_String& operator=(const Fl_String &str); Fl_String& operator=(const char *cstr); Fl_String &assign(const Fl_String &str); Fl_String &assign(const char *cstr); Fl_String &assign(const char *str, int size); // ---- Element Access char at(int pos) const; char operator[](int n) const; char &operator[](int n); const char *data() const; char *data(); const char *c_str() const; // ---- Capacity bool empty() const; int size() const; void reserve(int n); int capacity() const; void shrink_to_fit(); // --- Operations void clear(); Fl_String &insert(int at, const char *src, int n_ins=npos); Fl_String &insert(int at, const Fl_String &src); Fl_String &erase(int at, int n_del); void push_back(char c); void pop_back(); Fl_String &append(const char *src, int n_ins=npos); Fl_String &append(const Fl_String &src); Fl_String &append(char c); Fl_String &operator+=(const char *src); Fl_String &operator+=(const Fl_String &src); Fl_String &operator+=(char c); int find(const Fl_String &needle, int start_pos=0) const; Fl_String &replace(int at, int n_del, const char *src, int n_ins=npos); Fl_String &replace(int at, int n_del, const Fl_String &src); Fl_String substr(int pos=0, int n=npos) const; void resize(int n); // --- Non Standard int strlen() const; void debug(const char *info = 0) const; void hexdump(const char *info = 0) const; }; // class Fl_String // ---- Non-member functions FL_EXPORT Fl_String operator+(const Fl_String& lhs, const Fl_String& rhs); FL_EXPORT Fl_String operator+(const Fl_String& lhs, const char* rhs); FL_EXPORT bool operator==(const Fl_String & lhs, const Fl_String & rhs); FL_EXPORT bool operator!=(const Fl_String & lhs, const Fl_String & rhs); /** \} \endcond */ #endif // _FL_Fl_String_H_ fltk-1.4.3/src/Fl_Multi_Label.cxx0000644000175000017500000001072715004135251016741 0ustar albrechtalbrecht// // Multi-label widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Allows two or more labels to be used on a widget (by having one of them // be one of these it allows an infinite number!) #include #include #include #include static void multi_labeltype( const Fl_Label* o, int x, int y, int w, int h, Fl_Align a) { Fl_Multi_Label* b = (Fl_Multi_Label*)(o->value); Fl_Label local = *o; local.value = b->labela; local.type = b->typea; int W = w; int H = h; local.measure(W, H); local.draw(x,y,w,h,a); if (a & FL_ALIGN_BOTTOM) h -= H; else if (a & FL_ALIGN_TOP) {y += H; h -= H;} else if (a & FL_ALIGN_RIGHT) w -= W; else if (a & FL_ALIGN_LEFT) {x += W; w -= W;} else {int d = (h+H)/2; y += d; h -= d;} local.value = b->labelb; local.type = b->typeb; local.draw(x,y,w,h,a); } // measurement is only correct for left-to-right appending... static void multi_measure(const Fl_Label* o, int& w, int& h) { Fl_Multi_Label* b = (Fl_Multi_Label*)(o->value); Fl_Label local = *o; local.value = b->labela; local.type = b->typea; local.measure(w,h); local.value = b->labelb; local.type = b->typeb; int W = 0; int H = 0; local.measure(W,H); w += W; if (H>h) h = H; } // used by FL_MULTI_LABEL to set up the internal table, see FL/Enumerations.H Fl_Labeltype fl_define_FL_MULTI_LABEL() { Fl::set_labeltype(_FL_MULTI_LABEL, multi_labeltype, multi_measure); return _FL_MULTI_LABEL; } /** Associate an Fl_Multi_Label with an Fl_Widget. This method uses Fl_Widget::label(Fl_Labeltype, const char *) internally to set the \e label of the widget, i.e. it stores a \e pointer to the Fl_Multi_Label object (\e this). An existing label that has been set using Fl_Widget::copy_label() will be released prior to the assignment of the new label. This sets the type of the widget's label to \_FL_MULTI_LABEL - note the leading underscore ('_'). There is no way to use a method like Fl_Widget::copy_label() that transfers ownership of the Fl_Multi_Label and its linked objects (images, text, and chained Fl_Multi_Label's) to the widget. The Fl_Multi_Label and all linked images, text labels, or chained Fl_Multi_Label objects must exist during the lifetime of the widget and will not be released when the widget is destroyed. \note The user's code is responsible for releasing the Fl_Multi_Label and all linked objects (images, text, chained Fl_Multi_Label's) after the widget has been deleted. This may cause memory leaks if Fl_Multi_Label is used and reassigned w/o releasing the objects assigned to it. */ void Fl_Multi_Label::label(Fl_Widget* o) { o->label(FL_MULTI_LABEL, (const char*)this); // calls fl_define_FL_MULTI_LABEL() } /** Associate an Fl_Multi_Label with an Fl_Menu_Item. This uses Fl_Menu_Item::label(Fl_Labeltype a, const char *b) internally to set the \e label and the label type of the menu item, i.e. it stores a \e pointer to the Fl_Multi_Label object (\e this). An existing label (pointer) will be overwritten. This sets the type of the menu item's label to \_FL_MULTI_LABEL - note the leading underscore ('_'). There is no way to use a method like Fl_Widget::copy_label() that transfers ownership of the Fl_Multi_Label and its linked objects (images, text, and chained Fl_Multi_Label's) to the menu item. The Fl_Multi_Label and all linked images, text labels, or chained Fl_Multi_Label objects must exist during the lifetime of the menu and will not be released when the menu item is destroyed. \note The user's code is responsible for releasing the Fl_Multi_Label and all linked objects (images, text, chained Fl_Multi_Label's) after the menu has been deleted. This may cause memory leaks if Fl_Multi_Label is used and reassigned w/o releasing the objects assigned to it. \deprecated since 1.4.0: please use Fl_Menu_Item::label(Fl_Multi_Label *) \see Fl_Menu_Item::label(Fl_Multi_Label *) */ void Fl_Multi_Label::label(Fl_Menu_Item* o) { o->label(FL_MULTI_LABEL, (const char*)this); // calls fl_define_FL_MULTI_LABEL() } fltk-1.4.3/src/Fl_Flex.cxx0000644000175000017500000002611515004135251015444 0ustar albrechtalbrecht// // Fl_Flex widget implementation for the Fast Light Tool Kit (FLTK). // // Copyright 2020 by Karsten Pedersen // Copyright 2022-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include // malloc, free, ... /** Construct a new Fl_Flex widget with the given position, size, and label. You can set \p type(Fl_Flex::HORIZONTAL) or \p type(Fl_Flex::VERTICAL). The default is \p type(Fl_Flex::VERTICAL). Alternate constructors let you specify the layout as Fl_Flex::HORIZONTAL or Fl_Flex::VERTICAL directly. Fl_Flex::ROW is an alias of Fl_Flex::HORIZONTAL and Fl_Flex::COLUMN is an alias of Fl_Flex::VERTICAL. \param[in] X,Y position \param[in] W,H size (width and height) \param[in] L label (optional) \see Fl_Flex::Fl_Flex(int direction) \see Fl_Flex::Fl_Flex(int w, int h, int direction) \see Fl_Flex::Fl_Flex(int x, int y, int w, int h, int direction) \see Fl_Flex::Fl_Flex(int x, int y, int w, int h, const char *L) */ Fl_Flex::Fl_Flex(int X, int Y, int W, int H, const char *L) : Fl_Group(X, Y, W, H, L) { init(); } // special Fl_Flex constructors w/o label (backwards compatible with original Fl_Flex widget) /** Construct a new Fl_Flex widget specifying its layout. Use Fl_Flex::HORIZONTAL (aka Fl_Flex::ROW) or Fl_Flex::VERTICAL (aka Fl_Flex::COLUMN) as the \p direction argument. This constructor sets the position and size to (0, 0, 0, 0) which is suitable for nested Fl_Flex widgets. Use one of the other constructors to set the desired position and size as well. \param[in] direction horizontal (row) or vertical (column) layout \see Fl_Flex::Fl_Flex(int w, int h, int direction) \see Fl_Flex::Fl_Flex(int x, int y, int w, int h, int direction) \see Fl_Flex::Fl_Flex(int x, int y, int w, int h, const char *L) */ Fl_Flex::Fl_Flex(int direction) : Fl_Group(0, 0, 0, 0, 0) { init(direction); } /** Construct a new Fl_Flex widget specifying its layout and size. Use Fl_Flex::HORIZONTAL (aka Fl_Flex::ROW) or Fl_Flex::VERTICAL (aka Fl_Flex::COLUMN) as the \p direction argument. This constructor sets the position to (x = 0, y = 0) which is suitable for nested Fl_Flex widgets. Use one of the other constructors to set the desired position as well. \param[in] w,h widget size \param[in] direction horizontal (row) or vertical (column) layout \see Fl_Flex::Fl_Flex(int direction) \see Fl_Flex::Fl_Flex(int x, int y, int w, int h, int direction) \see Fl_Flex::Fl_Flex(int x, int y, int w, int h, const char *L) */ Fl_Flex::Fl_Flex(int w, int h, int direction) : Fl_Group(0, 0, w, h, 0) { init(direction); } /** Construct a new Fl_Flex widget specifying its layout, position, and size. Use Fl_Flex::HORIZONTAL (aka Fl_Flex::ROW) or Fl_Flex::VERTICAL (aka Fl_Flex::COLUMN) as the \p direction argument. This constructor sets the position and size of the widget which is suitable for top level Fl_Flex widgets but does not set a widget label. Use Fl_Widget::label() to set one if desired. \param[in] x,y widget position \param[in] w,h widget size \param[in] direction horizontal (row) or vertical (column) layout \see Fl_Flex::Fl_Flex(int direction) \see Fl_Flex::Fl_Flex(int w, int h, int direction) \see Fl_Flex::Fl_Flex(int x, int y, int w, int h, const char *L) */ Fl_Flex::Fl_Flex(int x, int y, int w, int h, int direction) : Fl_Group(x, y, w, h, 0) { init(direction); } void Fl_Flex::init(int t) { margin_left_ = 0; // default margin size margin_top_ = 0; // default margin size margin_right_ = 0; // default margin size margin_bottom_ = 0; // default margin size gap_ = 0; // default gap size fixed_size_size_ = 0; // number of fixed size widgets fixed_size_alloc_ = 0; // allocated size of array of fixed size widgets fixed_size_ = NULL; // array of fixed size widgets need_layout_ = false; // no need to calculate layout yet type(HORIZONTAL); if (t == VERTICAL) type(VERTICAL); } Fl_Flex::~Fl_Flex() { if (fixed_size_) free(fixed_size_); } /* Fl_Group calls this method when a child widget is about to be removed. Make sure that the widget is also removed from our fixed list. */ void Fl_Flex::on_remove(int index) { fixed(child(index), 0); need_layout(1); } /** Draw the widget. This will finally calculate the layout of the widget and of all its children if necessary and draw the widget. Some changes of included children may require a new layout to be calculated. If this is the case the user may need to call layout() to make sure everything is calculated properly. \see layout() */ void Fl_Flex::draw() { if (need_layout()) layout(); Fl_Group::draw(); } /** Resize the container and calculate all child positions and sizes. \param[in] x,y position \param[in] w,h width and height */ void Fl_Flex::resize(int x, int y, int w, int h) { Fl_Widget::resize(x, y, w, h); layout(); } // resize() /** Calculates the layout of the widget and redraws it. If you change widgets in the Fl_Flex container you should call this method to force recalculation of child widget sizes and positions. This can be useful (necessary) if you hide(), show(), add() or remove() children. Call this method if you need to recalculate widget positions for usage in an algorithm that places widgets at certain positions or when you need to display (show) or hide one or more children depending on the current layout (for instance a side bar). This method also calls redraw() on the Fl_Flex widget. */ void Fl_Flex::layout() { const int nc = children(); int dx = Fl::box_dx(box()); int dy = Fl::box_dy(box()); int dw = Fl::box_dw(box()); int dh = Fl::box_dh(box()); // Calculate total space minus gaps int gaps = nc > 1 ? nc - 1 : 0; int hori = horizontal(); int space = hori ? (w() - dw - margin_left_ - margin_right_) : (h() - dh - margin_top_ - margin_bottom_); // set x and y (start) position, calculate widget sizes int xp = x() + dx + margin_left_; int yp = y() + dy + margin_top_; int hh = h() - dh - margin_top_ - margin_bottom_; // if horizontal: constant height of widgets int vw = w() - dw - margin_left_ - margin_right_; // if vertical: constant width of widgets int fw = nc; // number of flexible widgets // Precalculate remaining space that can be distributed for (int i = 0; i < nc; i++) { Fl_Widget *c = child(i); if (c->visible()) { if (fixed(c)) { space -= (hori ? c->w() : c->h()); fw--; } } else { // hidden widget fw--; gaps--; } } if (gaps > 0) space -= gaps * gap_; // Set children to shared width/height of remaining space int sp = 0; // width or height of flexible widget int rem = 0; // remainder (to be distributed evenly) if (fw > 0) { sp = space / fw; rem = space % fw; if (rem) // adjust space for first 'rem' widgets sp++; } for (int i = 0; i < nc; i++) { Fl_Widget *c = child(i); if (!c->visible()) continue; if (hori) { if (fixed(c)) { c->resize(xp, yp, c->w(), hh); } else { c->resize(xp, yp, sp, hh); if (--rem == 0) sp--; } xp += c->w() + gap_; } else { if (fixed(c)) { c->resize(xp, yp, vw, c->h()); } else { c->resize(xp, yp, vw, sp); if (--rem == 0) sp--; } yp += c->h() + gap_; } } need_layout(0); // layout done, no need to do it again when drawing redraw(); } /** Ends automatic child addition and resizes all children. This marks the Fl_Flex widget as changed (need_layout(1)) which forces the widget to calculate its layout depending on all children and whether they have been assigned fix sizes or not right before it is drawn. \see need_layout(int) \see draw() */ void Fl_Flex::end() { Fl_Group::end(); need_layout(1); } /** Set the horizontal or vertical size of a child widget. This sets either the width or height of a child widget, depending on the type() of the Fl_Flex container (Fl_Flex::HORIZONTAL or Fl_Flex::VERTICAL). The other dimension is set to the full width or height of the Fl_Flex widget minus border and margin sizes. This can be used to set a fixed widget width or height of children of Fl_Flex so they are not resized dynamically. If \p size is 0 (zero) or negative the widget size is reset to flexible size. \param[in] child widget to be affected \param[in] size width (Fl_Flex::HORIZONTAL) or height (Fl_Flex::VERTICAL) */ void Fl_Flex::fixed(Fl_Widget *child, int size) { if (size <= 0) size = 0; // find w in our fixed size list int idx = -1; for (int i = 0; i < fixed_size_size_; i++) { if (fixed_size_[i] == child) { idx = i; break; } } // remove from array, if we want the widget to be flexible, but an entry was found if (size == 0 && idx >= 0) { for (int i = idx; i < fixed_size_size_ - 1; i++) { fixed_size_[i] = fixed_size_[i+1]; } fixed_size_size_--; need_layout(1); return; } // if w is meant to be flexible and we didn't find it, we are done now if (size == 0) return; // if we have no entry yet, add to array of fixed size widgets if (idx == -1) { if (fixed_size_size_ == fixed_size_alloc_) { fixed_size_alloc_ = alloc_size(fixed_size_alloc_); fixed_size_ = (Fl_Widget **)realloc(fixed_size_, fixed_size_alloc_ * sizeof(Fl_Widget *)); } fixed_size_[fixed_size_size_] = child; fixed_size_size_++; } // if the child size is meant to be fixed, set its new size if (horizontal()) child->size(size, h()-margin_top_-margin_bottom_-Fl::box_dh(box())); else child->size(w()-margin_left_-margin_right_-Fl::box_dw(box()), size); need_layout(1); } /** Return whether the given widget has a fixed size or resizes dynamically. \param[in] w widget \return whether the widget has a fixed size \retval 1 the widget has a fixed size \retval 0 the widget resizes dynamically */ int Fl_Flex::fixed(Fl_Widget *w) const { for (int i = 0; i < fixed_size_size_; i++) { if (w == fixed_size_[i]) { return 1; } } return 0; } /** Return new size to be allocated for array of fixed size widgets. This method is called when the array of fixed size widgets needs to be expanded. The current \p size is provided (size can be 0). The default method adds 8 to the current size. This can be used in derived classes to change the allocation strategy. Note that this method only \p queries the new size which shall be allocated but does not allocate the memory. \param[in] size current size \return int new size (to be allocated) */ int Fl_Flex::alloc_size(int size) const { return size + 8; } fltk-1.4.3/src/forms_compatibility.cxx0000644000175000017500000001175315004135251020206 0ustar albrechtalbrecht// // Forms compatibility functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Forms library compatibility functions. // Many more functions are defined as inlines in forms.h! #include #include char fl_flip = 2; void fl_end_form() { while (Fl_Group::current()) Fl_Group::current()->forms_end(); } void Fl_Group::forms_end() { // set the dimensions of a group to surround contents const int nc = children(); if (nc && !w()) { Fl_Widget*const* a = array(); Fl_Widget* o = *a++; int rx = o->x(); int ry = o->y(); int rw = rx+o->w(); int rh = ry+o->h(); for (int i = nc - 1; i--;) { o = *a++; if (o->x() < rx) rx = o->x(); if (o->y() < ry) ry = o->y(); if (o->x() + o->w() > rw) rw = o->x() + o->w(); if (o->y() + o->h() > rh) rh = o->y() + o->h(); } x(rx); y(ry); w(rw-rx); h(rh-ry); } // flip all the children's coordinate systems: if (nc && fl_flip) { Fl_Widget* o = as_window() ? this : window(); int Y = o->h(); Fl_Widget*const* a = array(); for (int i = nc; i--;) { Fl_Widget* ow = *a++; int newy = Y - ow->y() - ow->h(); ow->y(newy); } } end(); } static int initargc; static char **initargv; void fl_initialize(int *argc, char **argv, const char *, FL_CMD_OPT *, int) { initargc = *argc; initargv = new char*[*argc+1]; int i,j; for (i=0; i<=*argc; i++) initargv[i] = argv[i]; for (i=j=1; i<*argc; ) { if (Fl::arg(*argc,argv,i)); else argv[j++] = argv[i++]; } argv[j] = 0; *argc = j; if (fl_flip==2) fl_flip = 0; } char fl_modal_next; // set by fl_freeze_forms() void fl_show_form(Fl_Window *f,int place,int b,const char *n) { f->label(n); if (!b) f->clear_border(); if (fl_modal_next || b==FL_TRANSIENT) {f->set_modal(); fl_modal_next = 0;} if (place & FL_PLACE_MOUSE) f->hotspot(f); if (place & FL_PLACE_CENTER) { int scr_x, scr_y, scr_w, scr_h; Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h); f->position(scr_x+(scr_w-f->w())/2, scr_y+(scr_h-f->h())/2); } if (place & FL_PLACE_FULLSCREEN) f->fullscreen(); if (place & (FL_PLACE_POSITION | FL_PLACE_GEOMETRY)) f->position( (f->x() < 0) ? Fl::w()-f->w()+f->x()-1 : f->x(), (f->y() < 0) ? Fl::h()-f->h()+f->y()-1 : f->y()); // if (place & FL_PLACE_ASPECT) { // this is not yet implemented // it can be done by setting size_range(). if (place == FL_PLACE_FREE || place == FL_PLACE_SIZE) f->free_position(); if (place == FL_PLACE_FREE || place & FL_FREE_SIZE) if (!f->resizable()) f->resizable(f); if (initargc) {f->show(initargc,initargv); initargc = 0;} else f->show(); } Fl_Widget *fl_do_forms(void) { Fl_Widget *obj; while (!(obj = Fl::readqueue())) if (!Fl::wait()) exit(0); return obj; } Fl_Widget *fl_check_forms() { Fl::check(); return Fl::readqueue(); } void fl_set_graphics_mode(int /*r*/,int /*d*/) {} #ifndef FL_DOXYGEN // FIXME: suppress doxygen warning void Fl_FormsText::draw() { draw_box(); align(align()|FL_ALIGN_INSIDE); // questionable method of compatibility draw_label(); } #endif // Create a forms button by selecting correct fltk subclass: #include #include Fl_Button *fl_add_button(uchar t,int x,int y,int w,int h,const char *l) { Fl_Button *b; switch (t) { case FL_RETURN_BUTTON: case FL_HIDDEN_RET_BUTTON: b = new Fl_Return_Button(x,y,w,h,l); break; case FL_TOUCH_BUTTON: b = new Fl_Repeat_Button(x,y,w,h,l); break; default: b = new Fl_Button(x,y,w,h,l); } switch (t) { case FL_TOGGLE_BUTTON: case FL_RADIO_BUTTON: b->type(t); break; case FL_HIDDEN_BUTTON: case FL_HIDDEN_RET_BUTTON: b->type(FL_HIDDEN_BUTTON); break; case FL_INOUT_BUTTON: b->when(FL_WHEN_CHANGED); break; } return b; } void fl_show_message(const char *q1,const char *q2,const char *q3) { fl_message("%s\n%s\n%s", q1?q1:"", q2?q2:"", q3?q3:""); } void fl_show_alert(const char *q1,const char *q2,const char *q3,int) { fl_alert("%s\n%s\n%s", q1?q1:"", q2?q2:"", q3?q3:""); } int fl_show_question(const char *q1,const char *q2,const char *q3) { return fl_choice("%s\n%s\n%s", "No", "Yes", 0L, q1?q1:"", q2?q2:"", q3?q3:""); } int fl_show_choice( const char *q1, const char *q2, const char *q3, int, // number of buttons, ignored const char *b0, const char *b1, const char *b2) { return fl_choice("%s\n%s\n%s", q1?q1:"", q2?q2:"", q3?q3:"", b0,b1,b2)+1; } char *fl_show_simple_input(const char *str1, const char *defstr) { const char *r = fl_input("%s", defstr, str1); return (char *)(r ? r : defstr); } fltk-1.4.3/src/Fl_Shortcut_Button.cxx0000644000175000017500000002040615004135251017711 0ustar albrechtalbrecht// // Shortcut Button code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include "Fl_System_Driver.H" #include "flstring.h" #include /** \class Fl_Shortcut_Button A button that allows the user to type a key combination to create shortcuts. After clicked once, the button catches the following keyboard events and records the pressed keys and all modifiers. It draws a text representation of the shortcut. The backspace key deletes the current shortcut. A second click on the button or moving focus makes the last shortcut permanent. The Shortcut button calls the user callback after every change if FL_WHEN_CHANGED is set, and when the button is no longer recording shortcuts if FL_WHEN_RELEASE is set. */ /** Construct a shortcut button. \param X, Y, W, H position and size of the button \param l label text when no shortcut is set */ Fl_Shortcut_Button::Fl_Shortcut_Button(int X,int Y,int W,int H, const char* l) : Fl_Button(X,Y,W,H,l), hot_(false), pre_hot_(false), default_set_(false), handle_default_button_(false), pre_esc_(0), default_shortcut_(0), shortcut_value(0) { box(FL_DOWN_BOX); selection_color(FL_SELECTION_COLOR); type(FL_TOGGLE_BUTTON); // suppress warning on unused private members. I keep these around in case // we decide to activate this API again without changing the ABI. (void)default_shortcut_; (void)default_set_; } /** Set the displayed shortcut. \param[in] shortcut encoded as key and modifier */ void Fl_Shortcut_Button::value(Fl_Shortcut shortcut) { shortcut_value = shortcut; clear_changed(); redraw(); } /** Return the user selected shortcut. \return shortcut encoded as key and modifier */ Fl_Shortcut Fl_Shortcut_Button::value() { return shortcut_value; } #if 0 // Default shortcut settings are disabled until successful review of the UI /* * Set the default shortcut. If set, and additional 'reverse' button apears that the user can click to reset the shortcut to some default value (including 0). \param[in] shortcut encoded as key and modifier */ void Fl_Shortcut_Button::default_value(Fl_Shortcut shortcut) { default_shortcut_ = shortcut; default_set_ = true; redraw(); } #endif #if 0 // Default shortcut settings are disabled until successful review of the UI /* * Return the default shortcut. \return shortcut encoded as key and modifier */ Fl_Shortcut Fl_Shortcut_Button::default_value() { return default_shortcut_; } #endif #if 0 // Default shortcut settings are disabled until successful review of the UI /* * No longer show the button to reverse to a default shortcut. */ void Fl_Shortcut_Button::default_clear() { default_set_ = false; redraw(); } #endif /** Draw the textual representation of the shortcut button. When the button can receive shortcut key events, it's "hot". A hot button is drawn in selection color. A cold button is drawn as a regular text box containing a human readable version of the shortcut key. */ void Fl_Shortcut_Button::draw() { Fl_Color col = hot_ ? selection_color() : color(); Fl_Boxtype b = box(); if (hot_) { if (down_box()) b = down_box(); else if ((b > FL_FLAT_BOX) && (b < FL_BORDER_BOX)) b = Fl_Boxtype(((int)b) ^ 1); } draw_box(b, col); draw_backdrop(); int X = x() + Fl::box_dx(box()); int Y = y() + Fl::box_dy(box()); int W = w() - Fl::box_dw(box()); int H = h() - Fl::box_dh(box()); Fl_Color textcol = fl_contrast(labelcolor(), col); if (!active_r()) textcol = fl_inactive(textcol); fl_color(textcol); fl_font(labelfont(), labelsize()); const char *text = label(); if (shortcut_value) text = fl_shortcut_label(shortcut_value); #if 0 if (default_set_) { fl_draw(text, X, Y, W-H, H, align() | FL_ALIGN_INSIDE); fl_draw_symbol("@-29undo", X+W-H, Y, H, H, textcol); } else { fl_draw(text, X, Y, W, H, align() | FL_ALIGN_INSIDE); } #else fl_draw(text, X, Y, W, H, align() | FL_ALIGN_INSIDE); #endif if (Fl::focus() == this) draw_focus(); } /** Call the callback if the user is interested. */ void Fl_Shortcut_Button::do_end_hot_callback() { if (when() & FL_WHEN_RELEASE) { do_callback(FL_REASON_RELEASED); } } /** Handle keystrokes to catch the user's shortcut. */ int Fl_Shortcut_Button::handle(int e) { static int alt_modifier_extra_handler = Fl::system_driver()->need_test_shortcut_extra(); #if 0 bool inside_default_button = false; if (default_set_ && ( (e == FL_PUSH) || (e == FL_DRAG) || (e == FL_RELEASE) ) ) { int X = x() + Fl::box_dx(box()); int W = w() - Fl::box_dw(box()); int H = h() - Fl::box_dh(box()); if (Fl::event_inside(this) && (Fl::event_x() > X+W-H)) inside_default_button = true; } if ((e == FL_PUSH) && default_set_ && inside_default_button) { if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); handle_default_button_ = true; return 1; } if (handle_default_button_) { if (e == FL_DRAG) return 1; if (e == FL_RELEASE) { if (inside_default_button && (shortcut_value != default_shortcut_)) { shortcut_value = default_shortcut_; set_changed(); redraw(); if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED); clear_changed(); } handle_default_button_ = false; return 1; } } #endif switch (e) { case FL_PUSH: if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); pre_hot_ = hot_; /* FALLTHROUGH */ case FL_DRAG: case FL_RELEASE: if (Fl::event_inside(this)) { hot_ = !pre_hot_; } else { hot_ = pre_hot_; } if ((e == FL_RELEASE) && pre_hot_ && !hot_) do_end_hot_callback(); redraw(); handle_default_button_ = false; return 1; case FL_UNFOCUS: if (hot_) do_end_hot_callback(); hot_ = false; handle_default_button_ = false; /* FALLTHROUGH */ case FL_FOCUS: redraw(); return 1; case FL_KEYBOARD: if (hot_) { // Note: we can't really handle non-Latin shortcuts in the Fl_Shortcut // type, so we don't handle them here either // Todo: use fl_utf_tolower and fl_utf_toupper int v = fl_utf8decode(Fl::event_text(), 0, 0); if (alt_modifier_extra_handler && Fl::event_state(FL_ALT)) { // MacOS returns special characters when the alt modifier is held down. // FLTK handles shortcuts as ASCII keys, so let's convert the keystroke. int c = Fl::event_key(); if ( (c>32) && (c<128) && (isalnum(c)) ) { v = c; if (Fl::event_state(FL_SHIFT)) { v = toupper(c); } } } if ( (v > 32 && v < 0x7f) || (v > 0xa0 && v <= 0xff) ) { if (isupper(v)) { v = tolower(v); v |= FL_SHIFT; } v = v | (Fl::event_state()&(FL_META|FL_ALT|FL_CTRL)); } else { v = (Fl::event_state() & (FL_META|FL_ALT|FL_CTRL|FL_SHIFT)) | Fl::event_key(); if (v == FL_Escape) { if (shortcut_value == FL_Escape) { v = pre_esc_; do_end_hot_callback(); hot_ = false; } else { pre_esc_ = shortcut_value; } } if ((v == FL_BackSpace) && shortcut_value) { v = 0; } } if (v != (int)shortcut_value) { shortcut_value = v; set_changed(); redraw(); if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED); clear_changed(); } return 1; } else { if ((Fl::event_key() == FL_Enter) || (strcmp(Fl::event_text(), " ") == 0)) { hot_ = true; redraw(); return 1; } } break; case FL_SHORTCUT: if (hot_) return 1; break; } return Fl_Button::handle(e); } fltk-1.4.3/src/Fl_Timeout.cxx0000644000175000017500000004330115004135251016170 0ustar albrechtalbrecht// // Timeout support functions for the Fast Light Tool Kit (FLTK). // // Author: Albrecht Schlosser // Copyright 2021-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Timeout.h" #include "Fl_System_Driver.H" #include #include // for trunc() #if !HAVE_TRUNC static inline double trunc(double x) { return x >= 0 ? floor(x) : ceil(x); } #endif // !HAVE_TRUNC /** \file Fl_Timeout.cxx */ // static class variables Fl_Timeout *Fl_Timeout::free_timeout = 0; Fl_Timeout *Fl_Timeout::first_timeout = 0; Fl_Timeout *Fl_Timeout::current_timeout = 0; #if FL_TIMEOUT_DEBUG static int num_timers = 0; // DEBUG #endif /** Set a time stamp at this point in time with optional signed offset in seconds. The time stamp is an opaque type and does not represent the time of day or some time and date in the calendar. It is used with Fl::seconds_between() and Fl::seconds_since() to measure elapsed time. \code Fl_Timestamp start = Fl::now(); // do something double s = Fl::seconds_since(start); printf("That operation took %g seconds\n", s); \endcode Depending on the system the resolution may be milliseconds or microseconds. Under certain conditions (particularly on Windows) the value in member `sec` may wrap around and does not represent a real time (maybe runtime of the system). Function seconds_since() below uses this to subtract two timestamps which is always a correct delta time with milliseconds or microseconds resolution. \param offset optional signed offset in seconds added to the current time \return this moment in time offset by \p offset as an opaque time stamp \todo Fl::system_driver()->gettime() was implemented for the Forms library and has a limited resolution (on Windows: milliseconds). On POSIX platforms it uses gettimeofday() with microsecond resolution. A new function could use a better resolution on Windows with its multimedia timers which requires a new dependency: winmm.lib (dll). This could be a future improvement, maybe set as a build option or generally (requires Win95 or 98?). \see Fl::seconds_since(Fl_Timestamp& then) \see Fl::seconds_between(Fl_Timestamp& back, Fl_Timestamp& further_back) \see Fl::ticks_since(Fl_Timestamp& then) \see Fl::ticks_between(Fl_Timestamp& back, Fl_Timestamp& further_back) */ Fl_Timestamp Fl::now(double offset) { Fl_Timestamp ts; time_t sec; int usec; Fl::system_driver()->gettime(&sec, &usec); ts.sec = sec; ts.usec = usec; if (offset) { sec = (time_t)trunc(offset); usec = int((offset - sec) * 1000000); ts.sec += sec; if (usec + ts.usec >= 1000000) { ts.sec++; ts.usec += (usec - 1000000); } else if (usec + ts.usec < 0) { ts.sec--; ts.usec += (usec + 1000000); } else ts.usec += usec; } return ts; // C++ will copy the result into the lvalue for us } /** Return the time in seconds between now and a previously taken time stamp. \param[in] then a previously taken time stamp \return elapsed seconds and fractions of a second \see Fl::seconds_between(Fl_Timestamp& back, Fl_Timestamp& further_back) \see Fl::now() \see Fl::distant_past() */ double Fl::seconds_since(Fl_Timestamp& then) { Fl_Timestamp ts_now = Fl::now(); return Fl::seconds_between(ts_now, then); } /** Return the time in seconds between two time stamps. \param[in] back a previously taken time stamp \param[in] further_back an even earlier time stamp \return elapsed seconds and fractions of a second \see Fl::seconds_since(Fl_Timestamp& then) \see Fl::now() */ double Fl::seconds_between(Fl_Timestamp& back, Fl_Timestamp& further_back) { return double((back.sec - further_back.sec) + (back.usec - further_back.usec) / 1000000.); } /** Return the time in ticks (60Hz) between now and a previously taken time stamp. Ticks are a convenient way to time animations 'per frame'. Even though modern computers use all kinds of screen refresh rates, 60Hz is a very good base for animation that is typically shown in user interface graphics. \param[in] then a previously taken time stamp \return elapsed ticks in 60th of a second \see Fl::ticks_between(Fl_Timestamp& back, Fl_Timestamp& further_back) \see Fl::now() */ long Fl::ticks_since(Fl_Timestamp& then) { Fl_Timestamp ts_now = Fl::now(); return Fl::ticks_between(ts_now, then); } /** Return the time in ticks (60Hz) between two time stamps. \param[in] back a previously taken time stamp \param[in] further_back an even earlier time stamp \return elapsed ticks in 60th of a second \see Fl::ticks_since(Fl_Timestamp& then) \see Fl::now() */ long Fl::ticks_between(Fl_Timestamp& back, Fl_Timestamp& further_back) { return long((back.sec-further_back.sec)*60 + (back.usec-further_back.usec)/16666); } // Returns 0 and initializes the "previous" timestamp when called for the first time. /* Return the elapsed time since the last call in seconds. The first call initializes the internal "previous" timestamp and returns 0. This must only be called from Fl_Timeout::elapse_timeouts(). Todo: remove static variable in this function: previous time should be maintained in the caller. Return: double Elapsed time since the last call */ static double elapsed_time() { static int first = 1; // initialization static Fl_Timestamp prev; // previous timestamp Fl_Timestamp now = Fl::now(); // current timestamp double elapsed = 0.0; if (first) { first = 0; } else { elapsed = Fl::seconds_between(now, prev); } prev = now; return elapsed; } /** Insert this timer entry into the active timer queue. The timer is inserted at the required position so the timer queue is always ordered by due time. */ void Fl_Timeout::insert() { Fl_Timeout **p = (Fl_Timeout **)&first_timeout; while (*p && (*p)->time <= time) { p = (Fl_Timeout **)&((*p)->next); } next = *p; *p = this; } /** Returns true if the timeout exists and has not been called yet. \param[in] cb Timer callback (must match) \param[in] data Callback user data (must match) \returns whether the timer was found in the queue \retval 0 not found \retval 1 found Implements: int Fl::has_timeout(Fl_Timeout_Handler cb, void *data) \see Fl::has_timeout(Fl_Timeout_Handler cb, void *data) */ int Fl_Timeout::has_timeout(Fl_Timeout_Handler cb, void *data) { for (Fl_Timeout *t = first_timeout; t; t = t->next) { if (t->callback == cb && t->data == data) return 1; } return 0; } /** Adds a one-shot timeout callback. The callback function \p cb will be called by Fl::wait() at \p time seconds after this function is called. \param[in] time delta time in seconds until the timer expires \param[in] cb callback function \param[in] data optional user data (default: \p NULL) Implements: void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *data) \see Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *data) */ void Fl_Timeout::add_timeout(double time, Fl_Timeout_Handler cb, void *data) { elapse_timeouts(); Fl_Timeout *t = get(time, cb, data); t->insert(); } /** Repeats a timeout callback from the expiration of the previous timeout, allowing for more accurate timing. \param[in] time delta time in seconds until the timer expires \param[in] cb callback function \param[in] data optional user data (default: \p NULL) Implements: void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data) \see Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data) */ void Fl_Timeout::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data) { elapse_timeouts(); Fl_Timeout *t = (Fl_Timeout *)get(time, cb, data); Fl_Timeout *cur = current_timeout; if (cur) { t->time += cur->time; // was: missed_timeout_by (always <= 0.0) if (t->time < 0.0) t->time = 0.001; // at least 1 ms } t->insert(); } /** Remove a timeout callback. This method removes all matching timeouts, not just the first one. This may change in the future. \param[in] cb Timer callback to be removed (must match) \param[in] data Wildcard if NULL, must match otherwise Implements: void Fl::remove_timeout(Fl_Timeout_Handler cb, void *data) \see Fl::remove_timeout(Fl_Timeout_Handler cb, void *data) */ void Fl_Timeout::remove_timeout(Fl_Timeout_Handler cb, void *data) { for (Fl_Timeout** p = &first_timeout; *p;) { Fl_Timeout* t = *p; if (t->callback == cb && (t->data == data || !data)) { *p = t->next; t->next = free_timeout; free_timeout = t; } else { p = &(t->next); } } } /** Remove the next matching timeout callback and return its \p data pointer. Implements: int Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return) \param[in] cb Timer callback to be removed (must match) \param[in] data Wildcard if NULL, must match otherwise \param[inout] data_return pointer to void * to receive the data value \return non-zero if a timer was found and removed \retval 0 no matching timer was found \retval 1 the last matching timeout was found and removed \retval N>1 a matching timeout was removed and there are\n (N - 1) matching timeouts pending For details \see Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return) */ int Fl_Timeout::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return) { int ret = 0; for (Fl_Timeout** p = &first_timeout; *p;) { // scan all timeouts Fl_Timeout* t = *p; if (t->callback == cb && (t->data == data || !data)) { // timeout matches ret++; if (ret == 1) { // first timeout: remove if (data_return) *data_return = t->data; *p = t->next; t->next = free_timeout; free_timeout = t; continue; } p = &(t->next); } // timeout matches else { // no match p = &(t->next); } } // scan all timeouts return ret; } /** Remove the timeout from the active timer queue and push it onto the stack of currently running callbacks. This becomes the current() timeout which can be used in Fl::repeat_timeout(). \see Fl_Timeout::current() */ void Fl_Timeout::make_current() { // printf("[%4d] Fl_Timeout::make_current(%p)\n", __LINE__, this); // remove the timer entry from the active timer queue for (Fl_Timeout** p = &first_timeout; *p;) { Fl_Timeout* t = *p; if (t == this) { *p = t->next; // push it to the current timer stack t->next = current_timeout; current_timeout = t; break; } else { p = &(t->next); } } } /** Remove the top-most timeout from the stack of currently running timeout callbacks and insert it into the list of free timers. Typical code in the library would look like: \code // The timeout \p Fl_Timeout *t has exired, run its callback t->make_current(); (t->callback)(t->data); t->release(); \endcode */ void Fl_Timeout::release() { Fl_Timeout *t = current_timeout; if (t) { // The first timer in the "current" list *should* be 'this' but we // check it to be sure. Issue an error message which should never appear. // If it would happen we'd remove the wrong timer from the current timer // list. This is not good but it doesn't really do harm. if (t != this) { Fl::error("*** Fl_Timeout::release() *** timer t (%p) != this (%p)\n", t, this); } // remove the timer from the list current_timeout = t->next; } // put the timer into the list of free timers next = free_timeout; free_timeout = this; } /** Returns the first (top-most) timeout from the current timeout stack. This returns a pointer to the timeout but does not remove it from the list of current timeouts. This should be the timeout that is currently executing its callback. \return Fl_Timeout* The current timeout whose callback is running. \retval NULL if no callback is currently running. */ Fl_Timeout *Fl_Timeout::current() { return current_timeout; } /** Get an Fl_Timeout instance for further handling. The timer object will be initialized with the input parameters as given by Fl::add_timeout() or Fl::repeat_timeout(). Fl_Timeout objects are maintained in three queues: - active timer queue - list (stack, i.e. LIFO) of currently executing timer callbacks - free timer entries. When the FLTK program is launched all queues are empty. Whenever a new timer object is required the get() method is called and a timer object is either found in the queue of free timer entries or a new timer object is created (operator new). Active timer entries are inserted into the "active timer queue" until they expire and their callback is called. Before the callback is called the timer entry is inserted into the list of current timers, i.e. it becomes the Fl_Timeout::current() timeout. This can be used in Fl::repeat_timeout() to find out if and how long the current timeout has been delayed. When a timer is no longer used it is popped from the \p current list and inserted into the "free timer" list so it can be reused later. Timer queue entries are never returned to the system, there's no garbage collection. The total number of timer objects is determined by the largest number of concurrently active timers. \param[in] time requested delta time \param[in] cb timer callback \param[in] data userdata for timer callback \return Fl_Timeout* Timer entry \see Fl::add_timeout(), Fl::repeat_timeout() */ Fl_Timeout *Fl_Timeout::get(double time, Fl_Timeout_Handler cb, void *data) { Fl_Timeout *t = (Fl_Timeout *)free_timeout; if (t) { free_timeout = t->next; t->next = 0; } else { t = new Fl_Timeout; #if FL_TIMEOUT_DEBUG num_timers++; // DEBUG: count allocated timers #endif } t->next = 0; t->skip = 1; // see do_timeouts() (issue #450) t->delay(time); t->callback = cb; t->data = data; return t; } /** Elapse all timers w/o calling their callbacks. All timer values are adjusted by the delta time since the last call. This method does \b NOT call timer callbacks if timers are expired. This must be called before new timers are added to the timer queue to make sure that the next timer decrement does not count down too much time. \see Fl_Timeout::do_timeouts() */ void Fl_Timeout::elapse_timeouts() { double elapsed = elapsed_time(); // printf("elapse_timeouts: elapsed = %9.6f\n", double(elapsed)/1000000.); if (elapsed > 0.0) { // active timers for (Fl_Timeout* t = first_timeout; t; t = t->next) { t->time -= elapsed; } // "current" timers, i.e. timers being serviced for (Fl_Timeout* t = current_timeout; t; t = t->next) { t->time -= elapsed; } } } /** Elapse timers and call their callbacks if any timers are expired. */ void Fl_Timeout::do_timeouts() { // Reset "skip" flag for existing timers (issue #450). // For timers inserted in timer callbacks 'skip' will be true (1) Fl_Timeout *t = first_timeout; while (t) { t->skip = 0; t = t->next; } if (first_timeout) { Fl_Timeout::elapse_timeouts(); while ((t = first_timeout)) { if (t->time > 0) break; // skip timers inserted during timeout handling (issue #450) while (t && t->skip) t = t->next; if (!t || t->time > 0) break; // make this timeout the "current" timeout t->make_current(); // now it is safe for the callback to do add_timeout: t->callback(t->data); // release the timer entry t->release(); // Elapse timers (again) because the callback may have used a // significant amount of time. This is optional though. Fl_Timeout::elapse_timeouts(); } } } /** Returns the delay in seconds until the next timer expires, limited by \p ttw. This function calculates the time to wait for the FLTK event queue processing, depending on the given value \p ttw. If at least one timer is active and its timeout value is smaller than \p ttw then this value is returned. Fl::wait() will wait no longer than until the next timer expires. If no timer is active this returns the input value \p ttw unchanged. If at least one timer is expired this returns 0.0 so the event processing does not wait. \param[in] ttw time to wait from Fl::wait() etc. (upper limit) \return delay until next timeout or 0.0 (see description) */ double Fl_Timeout::time_to_wait(double ttw) { Fl_Timeout *t = first_timeout; if (!t) return ttw; double tdelay = t->delay(); if (tdelay < 0.0) return 0.0; if (tdelay < ttw) return tdelay; return ttw; } // Write some statistics to stdout for debugging #if FL_TIMEOUT_DEBUG void Fl_Timeout::debug(int level) { printf("\nFl_Timeout::debug: number of allocated timers = %d\n", num_timers); int active = 0; Fl_Timeout *t = first_timeout; while (t) { active++; t = t->next; } int current = 0; t = current_timeout; while (t) { current++; t = t->next; } int free = 0; t = free_timeout; while (t) { free++; t = t->next; } printf("Fl_Timeout::debug: active: %d, current: %d, free: %d\n\n", active, current, free); t = first_timeout; int n = 0; while (t) { printf("Active timer %3d: time = %10.6f sec\n", n+1, t->delay()); t = t->next; n++; } } // Fl_Timeout::debug(int) #endif // FL_TIMEOUT_DEBUG fltk-1.4.3/src/fl_symbols.cxx0000644000175000017500000004514215004135251016277 0ustar albrechtalbrecht// // Symbol drawing code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // These are small graphics drawn by the normal label-drawing // code when the string starts with an '@' sign. // Adapted from original code written by: // Written by Mark Overmars // Version 2.1 a // Date: Oct 2, 1992 #include #include #include #include "flstring.h" typedef struct { const char *name; void (*drawit)(Fl_Color); char scalable; char notempty; } SYMBOL; #define MAXSYMBOL 211 /* Maximal number of symbols in table. Only half of them are used. Should be prime. */ static SYMBOL symbols[MAXSYMBOL]; /* The symbols */ static int symbnumb = -1; /* Their number */ static int find(const char *name) { // returns hash entry if it exists, or first empty slot: int pos = name[0] ? ( name[1] ? ( name[2] ? 71*name[0]+31*name[1]+name[2] : 31*name[0]+name[1] ) : name[0] ) : 0; pos %= MAXSYMBOL; int hh2 = name[0] ? ( (name[1]) ? 51*name[0]+3*name[1] : 3*name[0] ) : 1; hh2 %= MAXSYMBOL; if (!hh2) hh2 = 1; for (;;) { if (!symbols[pos].notempty) return pos; if (!strcmp(symbols[pos].name,name)) return pos; pos = (pos + hh2) % MAXSYMBOL; } } static void fl_init_symbols(void); /**************** The routines seen by the user *************************/ /** Adds a symbol to the system. \param[in] name name of symbol (without the "@") \param[in] drawit function to draw symbol \param[in] scalable set to 1 if \p drawit uses scalable vector drawing \returns 1 on success, 0 on failure */ int fl_add_symbol(const char *name, void (*drawit)(Fl_Color), int scalable) { fl_init_symbols(); int pos; if (symbnumb > MAXSYMBOL / 2) return 0; // table is full pos = find(name); symbols[pos].name = name; symbols[pos].drawit = drawit; symbols[pos].notempty = 1; symbols[pos].scalable = scalable; symbnumb++; return 1; } int fl_return_arrow(int x,int y,int w,int h); /** Draw the named symbol in the given rectangle using the given color \param[in] label name of symbol \param[in] x,y position of symbol \param[in] w,h size of symbol \param[in] col color of symbox \returns 1 on success, 0 on failure */ // provided for back compatibility: int fl_draw_symbol(const char *label,int x,int y,int w,int h,Fl_Color col) { const char *p = label; if (*p++ != '@') return 0; fl_init_symbols(); int equalscale = 0; if (*p == '#') {equalscale = 1; p++;} if (*p == '-' && p[1]>='1' && p[1]<='9') { int n = p[1]-'0'; x += n; y += n; w -= 2*n; h -= 2*n; p += 2; } else if (*p == '+' && p[1]>='1' && p[1]<='9') { int n = p[1]-'0'; x -= n; y -= n; w += 2*n; h += 2*n; p += 2; } if (w < 10) {x -= (10-w)/2; w = 10;} if (h < 10) {y -= (10-h)/2; h = 10;} w = (w-1)|1; h = (h-1)|1; char flip_x = 0, flip_y = 0; if (*p=='$') { flip_x = 1; p++; } if (*p=='%') { flip_y = 1; p++; } int rotangle; switch (*p++) { case '0': rotangle = 1000*(p[1]-'0') + 100*(p[2]-'0') + 10*(p[3]-'0'); p += 4; break; case '1': rotangle = 2250; break; case '2': rotangle = 2700; break; case '3': rotangle = 3150; break; case '4': rotangle = 1800; break; case '5': case '6': rotangle = 0; break; case '7': rotangle = 1350; break; case '8': rotangle = 900; break; case '9': rotangle = 450; break; default: rotangle = 0; p--; break; } int pos = find(p); if (!symbols[pos].notempty) return 0; if (symbols[pos].scalable == 3) { // kludge to detect return arrow fl_return_arrow(x,y,w,h); return 1; } fl_push_matrix(); fl_translate(x+w/2,y+h/2); if (symbols[pos].scalable) { if (equalscale) {if (wcan_fill_non_convex_polygon()) { // draw the arrow as a 7-vertex filled polygon BP; vv(-0.8,-0.4); vv(-0.8,0.4); vv(0.0,0.4); vv(0.0,0.8); vv(0.8,0.0); vv(0.0,-0.8); vv(0.0,-0.4); EP; } else { // draw the arrow as a rectangle plus a triangle BP; vv(-0.8,-0.4); vv(-0.8,0.4); vv(0.0,0.4); vv(0.0,-0.4); EP; BP; vv(0.0,0.8); vv(0.8,0.0); vv(0.0,-0.8); vv(0.0,-0.4); vv(0.0,0.4); EP; } set_outline_color(col); BC; vv(-0.8,-0.4); vv(-0.8,0.4); vv(0.0,0.4); vv(0.0,0.8); vv(0.8,0.0); vv(0.0,-0.8); vv(0.0,-0.4); EC; } static void draw_arrow1bar(Fl_Color col) { draw_arrow1(col); rectangle(.6,-.8,.9,.8,col); } static void draw_arrow2(Fl_Color col) { fl_color(col); BP; vv(-0.3,0.8); vv(0.50,0.0); vv(-0.3,-0.8); EP; set_outline_color(col); BC; vv(-0.3,0.8); vv(0.50,0.0); vv(-0.3,-0.8); EC; } static void draw_arrow3(Fl_Color col) { fl_color(col); BP; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EP; BP; vv(-0.7,0.8); vv(0.1,0.0); vv(-0.7,-0.8); EP; set_outline_color(col); BC; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EC; BC; vv(-0.7,0.8); vv(0.1,0.0); vv(-0.7,-0.8); EC; } static void draw_arrowbar(Fl_Color col) { fl_color(col); BP; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EP; BP; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EP; set_outline_color(col); BC; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EC; BC; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EC; } static void draw_arrowbox(Fl_Color col) { fl_color(col); BP; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EP; BC; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EC; set_outline_color(col); BC; vv(0.2,0.8); vv(0.6,0.8); vv(0.6,-0.8); vv(0.2,-0.8); EC; BC; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EC; } static void draw_bararrow(Fl_Color col) { fl_color(col); BP; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EP; BP; vv(-0.5,0.8); vv(-0.1,0.8); vv(-0.1,-0.8); vv(-0.5,-0.8); EP; set_outline_color(col); BC; vv(0.1,0.8); vv(0.9,0.0); vv(0.1,-0.8); EC; BC; vv(-0.5,0.8); vv(-0.1,0.8); vv(-0.1,-0.8); vv(-0.5,-0.8); EC; } static void draw_doublebar(Fl_Color col) { rectangle(-0.6,-0.8,-.1,.8,col); rectangle(.1,-0.8,.6,.8,col); } static void draw_arrow01(Fl_Color col) { fl_rotate(180); draw_arrow1(col); } static void draw_arrow02(Fl_Color col) { fl_rotate(180); draw_arrow2(col); } static void draw_arrow03(Fl_Color col) { fl_rotate(180); draw_arrow3(col); } static void draw_0arrowbar(Fl_Color col) { fl_rotate(180); draw_arrowbar(col); } static void draw_0arrowbox(Fl_Color col) { fl_rotate(180); draw_arrowbox(col); } static void draw_0bararrow(Fl_Color col) { fl_rotate(180); draw_bararrow(col); } static void draw_doublearrow(Fl_Color col) { fl_color(col); BP; vv(-0.35,-0.4); vv(-0.35,0.4); vv(0.35,0.4); vv(0.35,-0.4); EP; BP; vv(0.15,0.8); vv(0.95,0.0); vv(0.15,-0.8); EP; BP; vv(-0.15,0.8); vv(-0.95,0.0); vv(-0.15,-0.8); EP; set_outline_color(col); BC; vv(-0.15,0.4); vv(0.15,0.4); vv(0.15,0.8); vv(0.95,0.0); vv(0.15,-0.8); vv(0.15,-0.4); vv(-0.15,-0.4); vv(-0.15,-0.8); vv(-0.95,0.0); vv(-0.15,0.8); EC; } static void draw_arrow(Fl_Color col) { fl_color(col); BP; vv(0.65,0.1); vv(1.0,0.0); vv(0.65,-0.1); EP; BL; vv(-1.0,0.0); vv(0.65,0.0); EL; set_outline_color(col); BL; vv(-1.0,0.0); vv(0.65,0.0); EL; BC; vv(0.65,0.1); vv(1.0,0.0); vv(0.65,-0.1); EC; } static void draw_square(Fl_Color col) { rectangle(-1,-1,1,1,col); } static void draw_circle(Fl_Color col) { fl_color(col); BP; fl_circle(0,0,1); EP; set_outline_color(col); BC; fl_circle(0,0,1); EC; } static void draw_line(Fl_Color col) { fl_color(col); BL; vv(-1.0,0.0); vv(1.0,0.0); EL; } static void draw_plus(Fl_Color col) { fl_color(col); BP; vv(-0.9,-0.15); vv(-0.9,0.15); vv(0.9,0.15); vv(0.9,-0.15); EP; BP; vv(-0.15,-0.9); vv(-0.15,0.9); vv(0.15,0.9); vv(0.15,-0.9); EP; set_outline_color(col); BC; vv(-0.9,-0.15); vv(-0.9,0.15); vv(-0.15,0.15); vv(-0.15,0.9); vv(0.15,0.9); vv(0.15,0.15); vv(0.9,0.15); vv(0.9,-0.15); vv(0.15,-0.15); vv(0.15,-0.9); vv(-0.15,-0.9); vv(-0.15,-0.15); EC; } static void draw_uparrow(Fl_Color) { fl_color(FL_LIGHT3); BL; vv(-.8,.8); vv(-.8,-.8); vv(.8,0); EL; fl_color(FL_DARK3); BL; vv(-.8,.8); vv(.8, 0); EL; } static void draw_downarrow(Fl_Color) { fl_color(FL_DARK3); BL; vv(-.8,.8); vv(-.8,-.8); vv(.8,0); EL; fl_color(FL_LIGHT3); BL; vv(-.8,.8); vv(.8, 0); EL; } static void draw_menu(Fl_Color col) { rectangle(-0.65, 0.85, 0.65, -0.25, col); rectangle(-0.65, -0.6, 0.65, -1.0, col); } // Standard UI icons... static void draw_filenew(Fl_Color c) { fl_color(c); BCP; vv(-0.7, -1.0); vv(0.1, -1.0); vv(0.1, -0.4); vv(0.7, -0.4); vv(0.7, 1.0); vv(-0.7, 1.0); ECP; fl_color(fl_lighter(c)); BP; vv(0.1, -1.0); vv(0.1, -0.4); vv(0.7, -0.4); EP; fl_color(fl_darker(c)); BC; vv(-0.7, -1.0); vv(0.1, -1.0); vv(0.1, -0.4); vv(0.7, -0.4); vv(0.7, 1.0); vv(-0.7, 1.0); EC; BL; vv(0.1, -1.0); vv(0.7, -0.4); EL; } static void draw_fileopen(Fl_Color c) { fl_color(c); BP; vv(-1.0, -0.7); vv(-0.9, -0.8); vv(-0.4, -0.8); vv(-0.3, -0.7); vv(0.6, -0.7); vv(0.6, 0.7); vv(-1.0, 0.7); EP; fl_color(fl_darker(c)); BC; vv(-1.0, -0.7); vv(-0.9, -0.8); vv(-0.4, -0.8); vv(-0.3, -0.7); vv(0.6, -0.7); vv(0.6, 0.7); vv(-1.0, 0.7); EC; fl_color(fl_lighter(c)); BP; vv(-1.0, 0.7); vv(-0.6, -0.3); vv(1.0, -0.3); vv(0.6, 0.7); EP; fl_color(fl_darker(c)); BC; vv(-1.0, 0.7); vv(-0.6, -0.3); vv(1.0, -0.3); vv(0.6, 0.7); EC; } static void draw_filesave(Fl_Color c) { fl_color(c); BP; vv(-0.9, -1.0); vv(0.9, -1.0); vv(1.0, -0.9); vv(1.0, 0.9); vv(0.9, 1.0); vv(-0.9, 1.0); vv(-1.0, 0.9); vv(-1.0, -0.9); EP; fl_color(fl_lighter(c)); BP; vv(-0.7, -1.0); vv(0.7, -1.0); vv(0.7, -0.4); vv(-0.7, -0.4); EP; BP; vv(-0.7, 0.0); vv(0.7, 0.0); vv(0.7, 1.0); vv(-0.7, 1.0); EP; fl_color(c); BP; vv(-0.5, -0.9); vv(-0.3, -0.9); vv(-0.3, -0.5); vv(-0.5, -0.5); EP; fl_color(fl_darker(c)); BC; vv(-0.9, -1.0); vv(0.9, -1.0); vv(1.0, -0.9); vv(1.0, 0.9); vv(0.9, 1.0); vv(-0.9, 1.0); vv(-1.0, 0.9); vv(-1.0, -0.9); EC; } static void draw_filesaveas(Fl_Color c) { draw_filesave(c); fl_color(fl_color_average(c, FL_WHITE, 0.25f)); BP; vv(0.6, -0.8); vv(1.0, -0.4); vv(0.0, 0.6); vv(-0.4, 0.6); vv(-0.4, 0.2); EP; fl_color(fl_darker(c)); BC; vv(0.6, -0.8); vv(1.0, -0.4); vv(0.0, 0.6); vv(-0.4, 0.6); vv(-0.4, 0.2); EC; BP; vv(-0.1, 0.6); vv(-0.4, 0.6); vv(-0.4, 0.3); EP; } static void draw_fileprint(Fl_Color c) { fl_color(c); BP; vv(-0.8, 0.0); vv(0.8, 0.0); vv(1.0, 0.2); vv(1.0, 1.0); vv(-1.0, 1.0); vv(-1.0, 0.2); EP; fl_color(fl_color_average(c, FL_WHITE, 0.25f)); BP; vv(-0.6, 0.0); vv(-0.6, -1.0); vv(0.6, -1.0); vv(0.6, 0.0); EP; fl_color(fl_lighter(c)); BP; vv(-0.6, 0.6); vv(0.6, 0.6); vv(0.6, 1.0); vv(-0.6, 1.0); EP; fl_color(fl_darker(c)); BC; vv(-0.8, 0.0); vv(-0.6, 0.0); vv(-0.6, -1.0); vv(0.6, -1.0); vv(0.6, 0.0); vv(0.8, 0.0); vv(1.0, 0.2); vv(1.0, 1.0); vv(-1.0, 1.0); vv(-1.0, 0.2); EC; BC; vv(-0.6, 0.6); vv(0.6, 0.6); vv(0.6, 1.0); vv(-0.6, 1.0); EC; } static void draw_round_arrow(Fl_Color c, float da=5.0) { double a, r, dr1=0.005, dr2=0.015; int i, j; for (j=0; j<2; j++) { if (j&1) { fl_color(c); set_outline_color(c); BC; } else { fl_color(c); BCP; } vv(-0.1, 0.0); vv(-1.0, 0.0); vv(-1.0, 0.9); for (i=27, a=140.0, r=1.0; i>0; i--, a-=da, r-=dr1) { double ar = a/180.0 * M_PI; vv(cos(ar)*r, sin(ar)*r); } for (i=27; i>=0; a+=da, i--, r-=dr2) { double ar = a/180.0 * M_PI; vv(cos(ar)*r, sin(ar)*r); } if (j&1) { EC; } else { ECP; } } } static void draw_refresh(Fl_Color c) { draw_round_arrow(c); fl_rotate(180.0); draw_round_arrow(c); fl_rotate(-180.0); } static void draw_reload(Fl_Color c) { fl_rotate(-135.0); draw_round_arrow(c, 10); fl_rotate(135.0); } static void draw_undo(Fl_Color c) { fl_translate(0.0, 0.2); fl_scale(1.0, -1.0); draw_round_arrow(c, 6); fl_scale(1.0, -1.0); fl_translate(0.0, -0.2); } static void draw_redo(Fl_Color c) { fl_scale(-1.0, 1.0); draw_undo(c); fl_scale(-1.0, 1.0); } static void draw_open_box(Fl_Color col) { fl_color(col); BCP; vv(-1.0, -1.0); vv(-0.4, -1.0); vv(-0.4, -0.75); vv(-0.75, -0.75); vv(-0.75, 0.75); vv(0.75, 0.75); vv(0.75, 0.4); vv(1.0, 0.4); vv(1.0, 1.0); vv(-1.0, 1.0); ECP; set_outline_color(col); BC; vv(-1.0, -1.0); vv(-0.4, -1.0); vv(-0.4, -0.75); vv(-0.75, -0.75); vv(-0.75, 0.75); vv(0.75, 0.75); vv(0.75, 0.4); vv(1.0, 0.4); vv(1.0, 1.0); vv(-1.0, 1.0); EC; } static void draw_import(Fl_Color col) { fl_push_matrix(); fl_scale(-1.0, 1.0); draw_open_box(col); fl_scale(-1.0, 1.0); fl_translate(-0.8, -0.3); fl_rotate(45.0+90); draw_round_arrow(col, 3); fl_pop_matrix(); } static void draw_export(Fl_Color col) { draw_open_box(col); fl_push_matrix(); fl_translate(0.7, 0.1); fl_rotate(225.0); draw_round_arrow(col, 3); fl_pop_matrix(); } static void fl_init_symbols(void) { static char beenhere; if (beenhere) return; beenhere = 1; symbnumb = 0; fl_add_symbol("", draw_arrow1, 1); fl_add_symbol("->", draw_arrow1, 1); fl_add_symbol(">", draw_arrow2, 1); fl_add_symbol(">>", draw_arrow3, 1); fl_add_symbol(">|", draw_arrowbar, 1); fl_add_symbol(">[]", draw_arrowbox, 1); fl_add_symbol("|>", draw_bararrow, 1); fl_add_symbol("<-", draw_arrow01, 1); fl_add_symbol("<", draw_arrow02, 1); fl_add_symbol("<<", draw_arrow03, 1); fl_add_symbol("|<", draw_0arrowbar, 1); fl_add_symbol("[]<", draw_0arrowbox, 1); fl_add_symbol("<|", draw_0bararrow, 1); fl_add_symbol("<->", draw_doublearrow, 1); fl_add_symbol("-->", draw_arrow, 1); fl_add_symbol("+", draw_plus, 1); fl_add_symbol("->|", draw_arrow1bar, 1); fl_add_symbol("arrow", draw_arrow, 1); fl_add_symbol("returnarrow", 0, 3); fl_add_symbol("square", draw_square, 1); fl_add_symbol("circle", draw_circle, 1); fl_add_symbol("line", draw_line, 1); fl_add_symbol("plus", draw_plus, 1); fl_add_symbol("menu", draw_menu, 1); fl_add_symbol("UpArrow", draw_uparrow, 1); fl_add_symbol("DnArrow", draw_downarrow, 1); fl_add_symbol("||", draw_doublebar, 1); fl_add_symbol("search", draw_search, 1); fl_add_symbol("FLTK", draw_fltk, 1); fl_add_symbol("filenew", draw_filenew, 1); fl_add_symbol("fileopen", draw_fileopen, 1); fl_add_symbol("filesave", draw_filesave, 1); fl_add_symbol("filesaveas", draw_filesaveas, 1); fl_add_symbol("fileprint", draw_fileprint, 1); fl_add_symbol("refresh", draw_refresh, 1); fl_add_symbol("reload", draw_reload, 1); fl_add_symbol("undo", draw_undo, 1); fl_add_symbol("redo", draw_redo, 1); fl_add_symbol("import", draw_import, 1); fl_add_symbol("export", draw_export, 1); // fl_add_symbol("file", draw_file, 1); } fltk-1.4.3/src/Fl_get_key_mac.cxx0000644000175000017500000002707315004135251017021 0ustar albrechtalbrecht// // MacOS keyboard state routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Note: this file contains platform specific code and will therefore // not be processed by doxygen (see Doxyfile.in). // Return the current state of a key. Keys are named by fltk symbols, // which are actually X keysyms. So this has to translate to macOS // symbols. #include #include #include "drivers/Darwin/Fl_Darwin_System_Driver.H" #include "drivers/Cocoa/Fl_Cocoa_Screen_Driver.H" // The list of Mac OS virtual keycodes appears with OS 10.5 in // ...../Carbon.framework/Frameworks/HIToolbox.framework/Headers/Events.h #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 #include #else /* * These constants are the virtual keycodes defined originally in * Inside Mac Volume V, pg. V-191. They identify physical keys on a * keyboard. Those constants with "ANSI" in the name are labeled * according to the key position on an ANSI-standard US keyboard. * For example, kVK_ANSI_A indicates the virtual keycode for the key * with the letter 'A' in the US keyboard layout. Other keyboard * layouts may have the 'A' key label on a different physical key; * in this case, pressing 'A' will generate a different virtual * keycode. */ enum { kVK_ANSI_A = 0x00, kVK_ANSI_S = 0x01, kVK_ANSI_D = 0x02, kVK_ANSI_F = 0x03, kVK_ANSI_H = 0x04, kVK_ANSI_G = 0x05, kVK_ANSI_Z = 0x06, kVK_ANSI_X = 0x07, kVK_ANSI_C = 0x08, kVK_ANSI_V = 0x09, kVK_ANSI_B = 0x0B, kVK_ANSI_Q = 0x0C, kVK_ANSI_W = 0x0D, kVK_ANSI_E = 0x0E, kVK_ANSI_R = 0x0F, kVK_ANSI_Y = 0x10, kVK_ANSI_T = 0x11, kVK_ANSI_1 = 0x12, kVK_ANSI_2 = 0x13, kVK_ANSI_3 = 0x14, kVK_ANSI_4 = 0x15, kVK_ANSI_6 = 0x16, kVK_ANSI_5 = 0x17, kVK_ANSI_Equal = 0x18, kVK_ANSI_9 = 0x19, kVK_ANSI_7 = 0x1A, kVK_ANSI_Minus = 0x1B, kVK_ANSI_8 = 0x1C, kVK_ANSI_0 = 0x1D, kVK_ANSI_RightBracket = 0x1E, kVK_ANSI_O = 0x1F, kVK_ANSI_U = 0x20, kVK_ANSI_LeftBracket = 0x21, kVK_ANSI_I = 0x22, kVK_ANSI_P = 0x23, kVK_ANSI_L = 0x25, kVK_ANSI_J = 0x26, kVK_ANSI_Quote = 0x27, kVK_ANSI_K = 0x28, kVK_ANSI_Semicolon = 0x29, kVK_ANSI_Backslash = 0x2A, kVK_ANSI_Comma = 0x2B, kVK_ANSI_Slash = 0x2C, kVK_ANSI_N = 0x2D, kVK_ANSI_M = 0x2E, kVK_ANSI_Period = 0x2F, kVK_ANSI_Grave = 0x32, kVK_ANSI_KeypadDecimal = 0x41, kVK_ANSI_KeypadMultiply = 0x43, kVK_ANSI_KeypadPlus = 0x45, kVK_ANSI_KeypadClear = 0x47, kVK_ANSI_KeypadDivide = 0x4B, kVK_ANSI_KeypadEnter = 0x4C, kVK_ANSI_KeypadMinus = 0x4E, kVK_ANSI_KeypadEquals = 0x51, kVK_ANSI_Keypad0 = 0x52, kVK_ANSI_Keypad1 = 0x53, kVK_ANSI_Keypad2 = 0x54, kVK_ANSI_Keypad3 = 0x55, kVK_ANSI_Keypad4 = 0x56, kVK_ANSI_Keypad5 = 0x57, kVK_ANSI_Keypad6 = 0x58, kVK_ANSI_Keypad7 = 0x59, kVK_ANSI_Keypad8 = 0x5B, kVK_ANSI_Keypad9 = 0x5C }; /* keycodes for keys that are independent of keyboard layout*/ enum { kVK_Return = 0x24, kVK_Tab = 0x30, kVK_Space = 0x31, kVK_Delete = 0x33, kVK_Escape = 0x35, kVK_Command = 0x37, kVK_Shift = 0x38, kVK_CapsLock = 0x39, kVK_Option = 0x3A, kVK_Control = 0x3B, kVK_RightShift = 0x3C, kVK_RightOption = 0x3D, kVK_RightControl = 0x3E, kVK_Function = 0x3F, kVK_F17 = 0x40, kVK_VolumeUp = 0x48, kVK_VolumeDown = 0x49, kVK_Mute = 0x4A, kVK_F18 = 0x4F, kVK_F19 = 0x50, kVK_F20 = 0x5A, kVK_F5 = 0x60, kVK_F6 = 0x61, kVK_F7 = 0x62, kVK_F3 = 0x63, kVK_F8 = 0x64, kVK_F9 = 0x65, kVK_F11 = 0x67, kVK_F13 = 0x69, kVK_F16 = 0x6A, kVK_F14 = 0x6B, kVK_F10 = 0x6D, kVK_F12 = 0x6F, kVK_F15 = 0x71, kVK_Help = 0x72, kVK_Home = 0x73, kVK_PageUp = 0x74, kVK_ForwardDelete = 0x75, kVK_F4 = 0x76, kVK_End = 0x77, kVK_F2 = 0x78, kVK_PageDown = 0x79, kVK_F1 = 0x7A, kVK_LeftArrow = 0x7B, kVK_RightArrow = 0x7C, kVK_DownArrow = 0x7D, kVK_UpArrow = 0x7E }; /* ISO keyboards only*/ enum { kVK_ISO_Section = 0x0A }; /* JIS keyboards only*/ enum { kVK_JIS_Yen = 0x5D, kVK_JIS_Underscore = 0x5E, kVK_JIS_KeypadComma = 0x5F, kVK_JIS_Eisu = 0x66, kVK_JIS_Kana = 0x68 }; #endif // convert an FLTK (X) keysym to a MacOS symbol: // This table is in numeric order by FLTK symbol order for binary search. static const struct {unsigned short vk, fltk;} vktab[] = { { kVK_Space, ' ' }, { kVK_ANSI_Quote, '\'' }, { kVK_ANSI_Comma, ',' }, { kVK_ANSI_Minus, '-' }, { kVK_ANSI_Period, '.' }, { kVK_ANSI_Slash, '/' }, { kVK_ANSI_0, '0' }, { kVK_ANSI_1, '1' }, { kVK_ANSI_2, '2' }, { kVK_ANSI_3, '3' }, { kVK_ANSI_4, '4' }, { kVK_ANSI_5, '5' }, { kVK_ANSI_6, '6' }, { kVK_ANSI_7, '7' }, { kVK_ANSI_8, '8' }, { kVK_ANSI_9, '9' }, { kVK_ANSI_Semicolon, ';' }, { kVK_ANSI_Equal, '=' }, { kVK_ANSI_A, 'A' }, { kVK_ANSI_B, 'B' }, { kVK_ANSI_C, 'C' }, { kVK_ANSI_D, 'D' }, { kVK_ANSI_E, 'E' }, { kVK_ANSI_F, 'F' }, { kVK_ANSI_G, 'G' }, { kVK_ANSI_H, 'H' }, { kVK_ANSI_I, 'I' }, { kVK_ANSI_J, 'J' }, { kVK_ANSI_K, 'K' }, { kVK_ANSI_L, 'L' }, { kVK_ANSI_M, 'M' }, { kVK_ANSI_N, 'N' }, { kVK_ANSI_O, 'O' }, { kVK_ANSI_P, 'P' }, { kVK_ANSI_Q, 'Q' }, { kVK_ANSI_R, 'R' }, { kVK_ANSI_S, 'S' }, { kVK_ANSI_T, 'T' }, { kVK_ANSI_U, 'U' }, { kVK_ANSI_V, 'V' }, { kVK_ANSI_W, 'W' }, { kVK_ANSI_X, 'X' }, { kVK_ANSI_Y, 'Y' }, { kVK_ANSI_Z, 'Z' }, { kVK_ANSI_LeftBracket, '[' }, { kVK_ANSI_Backslash, '\\' }, { kVK_ANSI_RightBracket, ']' }, { kVK_ANSI_Grave, '`' }, { kVK_VolumeDown, FL_Volume_Down}, { kVK_Mute, FL_Volume_Mute}, { kVK_VolumeUp, FL_Volume_Up}, { kVK_Delete, FL_BackSpace }, { kVK_Tab, FL_Tab }, { kVK_ISO_Section, FL_Iso_Key }, { kVK_Return, FL_Enter }, /*{ 0x7F, FL_Pause }, { 0x7F, FL_Scroll_Lock },*/ { kVK_Escape, FL_Escape }, { kVK_JIS_Kana, FL_Kana}, { kVK_JIS_Eisu, FL_Eisu}, { kVK_JIS_Yen, FL_Yen}, { kVK_JIS_Underscore, FL_JIS_Underscore}, { kVK_Home, FL_Home }, { kVK_LeftArrow, FL_Left }, { kVK_UpArrow, FL_Up }, { kVK_RightArrow, FL_Right }, { kVK_DownArrow, FL_Down }, { kVK_PageUp, FL_Page_Up }, { kVK_PageDown, FL_Page_Down }, { kVK_End, FL_End }, /*{ 0x7F, FL_Print }, { 0x7F, FL_Insert },*/ { 0x6e, FL_Menu }, { kVK_Help, FL_Help }, { kVK_ANSI_KeypadClear, FL_Num_Lock }, { kVK_ANSI_KeypadEnter, FL_KP_Enter }, { kVK_ANSI_KeypadMultiply, FL_KP+'*' }, { kVK_ANSI_KeypadPlus, FL_KP+'+'}, { kVK_JIS_KeypadComma, FL_KP+',' }, { kVK_ANSI_KeypadMinus, FL_KP+'-' }, { kVK_ANSI_KeypadDecimal, FL_KP+'.' }, { kVK_ANSI_KeypadDivide, FL_KP+'/' }, { kVK_ANSI_Keypad0, FL_KP+'0' }, { kVK_ANSI_Keypad1, FL_KP+'1' }, { kVK_ANSI_Keypad2, FL_KP+'2' }, { kVK_ANSI_Keypad3, FL_KP+'3' }, { kVK_ANSI_Keypad4, FL_KP+'4' }, { kVK_ANSI_Keypad5, FL_KP+'5' }, { kVK_ANSI_Keypad6, FL_KP+'6' }, { kVK_ANSI_Keypad7, FL_KP+'7' }, { kVK_ANSI_Keypad8, FL_KP+'8' }, { kVK_ANSI_Keypad9, FL_KP+'9' }, { kVK_ANSI_KeypadEquals, FL_KP+'=' }, { kVK_F1, FL_F+1 }, { kVK_F2, FL_F+2 }, { kVK_F3, FL_F+3 }, { kVK_F4, FL_F+4 }, { kVK_F5, FL_F+5 }, { kVK_F6, FL_F+6 }, { kVK_F7, FL_F+7 }, { kVK_F8, FL_F+8 }, { kVK_F9, FL_F+9 }, { kVK_F10, FL_F+10 }, { kVK_F11, FL_F+11 }, { kVK_F12, FL_F+12 }, { kVK_F13, FL_F+13 }, { kVK_F14, FL_F+14 }, { kVK_F15, FL_F+15 }, { kVK_F16, FL_F+16 }, { kVK_F17, FL_F+17 }, { kVK_F18, FL_F+18 }, { kVK_F19, FL_F+19 }, { kVK_F20, FL_F+20 }, { kVK_Shift, FL_Shift_L }, { kVK_RightShift, FL_Shift_R }, { kVK_Control, FL_Control_L }, { kVK_RightControl, FL_Control_R }, { kVK_CapsLock, FL_Caps_Lock }, { kVK_Command, FL_Meta_L }, { 0x36, FL_Meta_R }, { kVK_Option, FL_Alt_L }, { kVK_RightOption, FL_Alt_R }, { kVK_ForwardDelete, FL_Delete } }; // Computes the macKeyLookUp table that transforms a Mac OS virtual keycode into an FLTK keysym unsigned short *Fl_Darwin_System_Driver::compute_macKeyLookUp() { static unsigned short macKeyLookUp[128]; memset(macKeyLookUp, 0, sizeof(macKeyLookUp)); for (unsigned i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) { macKeyLookUp[vktab[i].vk] = vktab[i].fltk; } return macKeyLookUp; } static int fltk2mac(int fltk) { int a = 0; int b = sizeof(vktab)/sizeof(*vktab); while (a < b) { int c = (a+b)/2; if (vktab[c].fltk == fltk) return vktab[c].vk; if (vktab[c].fltk < fltk) a = c+1; else b = c; } return vktab[a].vk; } //: returns true, if that key was pressed during the last event int Fl_Cocoa_Screen_Driver::event_key(int k) { return get_key(k); } //: returns true, if that key is pressed right now int Fl_Cocoa_Screen_Driver::get_key(int k) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (&CGEventSourceKeyState != NULL) { return (int)CGEventSourceKeyState(kCGEventSourceStateCombinedSessionState, fltk2mac(k) ); } else #endif { typedef UInt32 fl_KeyMap[4]; fl_KeyMap foo; // use the GetKeys Carbon function typedef void (*keymap_f)(fl_KeyMap); static keymap_f f = NULL; if (!f) f = ( keymap_f )Fl_Darwin_System_Driver::get_carbon_function("GetKeys"); (*f)(foo); #ifdef MAC_TEST_FOR_KEYCODES static int cnt = 0; if (cnt++>1024) { cnt = 0; printf("%08x %08x %08x %08x\n", (ulong*)(foo)[3], (ulong*)(foo)[2], (ulong*)(foo)[1], (ulong*)(foo)[0]); } #endif unsigned char *b = (unsigned char*)foo; // KP_Enter can be at different locations for Powerbooks vs. desktop Macs if (k==FL_KP_Enter) { return (((b[0x34>>3]>>(0x34&7))&1)||((b[0x4c>>3]>>(0x4c&7))&1)); } int i = fltk2mac(k); return (b[i>>3]>>(i&7))&1; } } fltk-1.4.3/src/Fl_Value_Output.cxx0000644000175000017500000000470415004135251017202 0ustar albrechtalbrecht// // Value output widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Fltk widget for drag-adjusting a floating point value. // This is much lighter than Fl_Value_Input because it has no text editor // If step() is zero then it can be used to display a floating-point value #include #include #include void Fl_Value_Output::draw() { Fl_Boxtype b = box() ? box() : FL_DOWN_BOX; int X = x()+Fl::box_dx(b); int Y = y()+Fl::box_dy(b); int W = w()-Fl::box_dw(b); int H = h()-Fl::box_dh(b); if (damage()&~FL_DAMAGE_CHILD) draw_box(b, color()); else { fl_color(color()); fl_rectf(X, Y, W, H); } char buf[128]; format(buf); fl_color(active_r() ? textcolor() : fl_inactive(textcolor())); fl_font(textfont(), textsize()); fl_draw(buf,X,Y,W,H,FL_ALIGN_LEFT); } int Fl_Value_Output::handle(int event) { if (!step()) return 0; double v; int delta; int mx = Fl::event_x(); static int ix, drag; switch (event) { case FL_PUSH: ix = mx; drag = Fl::event_button(); handle_push(); return 1; case FL_DRAG: delta = Fl::event_x()-ix; if (delta > 5) delta -= 5; else if (delta < -5) delta += 5; else delta = 0; switch (drag) { case 3: v = increment(previous_value(),delta*100); break; case 2: v = increment(previous_value(),delta*10); break; default:v = increment(previous_value(),delta); break; } v = round(v); handle_drag(soft()?softclamp(v):clamp(v));; return 1; case FL_RELEASE: handle_release(); return 1; case FL_ENTER : case FL_LEAVE : return 1; default: return 0; } } /** Creates a new Fl_Value_Output widget using the given position, size, and label string. The default boxtype is FL_NO_BOX.

Inherited destructor destroys the Valuator. */ Fl_Value_Output::Fl_Value_Output(int X, int Y, int W, int H,const char *l) : Fl_Valuator(X,Y,W,H,l) { box(FL_NO_BOX); align(FL_ALIGN_LEFT); textfont_ = FL_HELVETICA; textsize_ = FL_NORMAL_SIZE; textcolor_ = FL_FOREGROUND_COLOR; soft_ = 0; } fltk-1.4.3/src/forms_timer.cxx0000644000175000017500000000744515004135251016460 0ustar albrechtalbrecht// // Forms timer object for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Emulate the Forms Timer object // You don't want to use this if you just want a timeout, call // Fl::add_timeout directly! #include #include #include #include #include "Fl_System_Driver.H" #include #define FL_TIMER_BLINKRATE 0.2 void fl_gettime(long* sec, long* usec) { time_t tt_sec; int i_usec; Fl::system_driver()->gettime(&tt_sec, &i_usec); *sec = (long)tt_sec; *usec = i_usec; } void Fl_Timer::draw() { int tt; Fl_Color col; char str[32]; if (!on || delay>0.0) col = color(); else if ((int) (delay / FL_TIMER_BLINKRATE) % 2) col = color(); else col = selection_color(); draw_box(box(), col); if (type() == FL_VALUE_TIMER && delay>0.0) { double d = direction_ ? total-delay : delay; if (d < 60.0) snprintf(str, 32, "%.1f", d); else { tt = (int) ((d+0.05) / 60.0); snprintf(str, 32, "%d:%04.1f", tt, d - 60.0 * tt); } fl_font(labelfont(), labelsize()); fl_color(labelcolor()); fl_draw(str, x(), y(), w(), h(), FL_ALIGN_CENTER); } else draw_label(); } void Fl_Timer::stepcb(void* v) { ((Fl_Timer*)v)->step(); } void Fl_Timer::step() { if (!on) return; double lastdelay = delay; long sec, usec; fl_gettime(&sec, &usec); delay -= (double) (sec - lastsec) + (double) (usec - lastusec) / 1000000.0; lastsec = sec; lastusec = usec; if (lastdelay > 0.0 && delay <= 0.0) { if (type() == FL_HIDDEN_TIMER) { on = 0; delay = 0; } else { redraw(); Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this); } set_changed(); do_callback(); } else { if (type() == FL_VALUE_TIMER) redraw(); Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this); } } int Fl_Timer::handle(int event) { if (event == FL_RELEASE && delay <= 0) value(0.0); return 0; } /** Destroys the timer and removes the timeout. */ Fl_Timer::~Fl_Timer() { Fl::remove_timeout(stepcb, this); } /** Creates a new Fl_Timer widget using the given type, position, size, and label string. The type parameter can be any of the following symbolic constants: \li FL_NORMAL_TIMER - The timer just does the callback and displays the string "Timer" in the widget. \li FL_VALUE_TIMER - The timer does the callback and displays the current timer value in the widget. \li FL_HIDDEN_TIMER - The timer just does the callback and does not display anything. */ Fl_Timer::Fl_Timer(uchar t, int X, int Y, int W, int H, const char* l) : Fl_Widget(X, Y, W, H, l) { box(FL_DOWN_BOX); selection_color(FL_RED); delay = 0; on = 0; direction_ = 0; type(t); if (t == FL_HIDDEN_TIMER) clear_visible(); if (t == FL_VALUE_TIMER) align(FL_ALIGN_LEFT); } /** Sets the current timer value */ void Fl_Timer::value(double d) { delay = total = d; on = (d > 0.0); fl_gettime(&(lastsec), &(lastusec)); if (type() != FL_HIDDEN_TIMER) redraw(); Fl::remove_timeout(stepcb, this); if (on) Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this); } /** Gets or sets whether the timer is suspended.*/ void Fl_Timer::suspended(char d) { if (!d) { if (on) return; on = (delay > 0.0); fl_gettime(&(lastsec), &(lastusec)); if (on) Fl::add_timeout(FL_TIMER_BLINKRATE, stepcb, this); } else { if (!on) return; on = 0; Fl::remove_timeout(stepcb, this); } } fltk-1.4.3/src/Fl_Spinner.cxx0000644000175000017500000001324115004135251016160 0ustar albrechtalbrecht// // Spinner widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* \file Fl_Spinner widget . */ #include #include #include #include #include /* This widget is a combination of the input widget and repeat buttons. The user can either type into the input area or use the buttons to change the value. */ void Fl_Spinner::sb_cb(Fl_Widget *w, Fl_Spinner *sb) { double v; // New value if (w == &(sb->input_)) { // Something changed in the input field... v = atof(sb->input_.value()); if (v < sb->minimum_) { sb->value_ = sb->minimum_; sb->update(); } else if (v > sb->maximum_) { sb->value_ = sb->maximum_; sb->update(); } else sb->value_ = v; } else if (w == &(sb->up_button_)) { // Up button pressed... v = sb->value_ + sb->step_; if (v > sb->maximum_) { if (sb->wrap_) v = sb->minimum_; else v = sb->maximum_; } sb->value_ = v; sb->update(); } else if (w == &(sb->down_button_)) { // Down button pressed... v = sb->value_ - sb->step_; if (v < sb->minimum_) { if (sb->wrap_) v = sb->maximum_; else v = sb->minimum_; } sb->value_ = v; sb->update(); } sb->set_changed(); sb->do_callback(FL_REASON_CHANGED); } void Fl_Spinner::update() { char s[255]; // Value string if (format_[0] == '%' && format_[1] == '.' && format_[2] == '*') { // precision argument // this code block is a simplified version of // Fl_Valuator::format() and works well (but looks ugly) int c = 0; char temp[64], *sp = temp; snprintf(temp, 64, "%.12f", step_); while (*sp) sp++; sp--; while (sp > temp && *sp == '0') sp--; while (sp > temp && (*sp >= '0' && *sp <= '9')) { sp--; c++; } snprintf(s, sizeof(s), format_, c, value_); } else { snprintf(s, sizeof(s), format_, value_); } input_.value(s); } /** Creates a new Fl_Spinner widget using the given position, size, and label string. The inherited destructor destroys the widget and any value associated with it. */ Fl_Spinner::Fl_Spinner(int X, int Y, int W, int H, const char *L) : Fl_Group(X, Y, W, H, L), input_(X, Y, W - H / 2 - 2, H), up_button_(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2), down_button_(X + W - H / 2 - 2, Y + H - H / 2, H / 2 + 2, H / 2) { end(); value_ = 1.0; minimum_ = 1.0; maximum_ = 100.0; step_ = 1.0; wrap_ = 1; format_ = "%g"; align(FL_ALIGN_LEFT); input_.value("1"); input_.type(FL_INT_INPUT); input_.when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE); input_.callback((Fl_Callback *)sb_cb, this); up_button_.callback((Fl_Callback *)sb_cb, this); down_button_.callback((Fl_Callback *)sb_cb, this); } void Fl_Spinner::draw() { // let group draw itself; buttons are blank as they have no labels Fl_Group::draw(); // draw up/down arrows over the button's empty labels Fl_Color arrow_color = active_r() ? labelcolor() : fl_inactive(labelcolor()); Fl_Rect up(up_button_); up.inset(up_button_.box()); fl_draw_arrow(up, FL_ARROW_SINGLE, FL_ORIENT_UP, arrow_color); Fl_Rect down(down_button_); down.inset(down_button_.box()); fl_draw_arrow(down, FL_ARROW_SINGLE, FL_ORIENT_DOWN, arrow_color); } int Fl_Spinner::handle(int event) { switch (event) { case FL_KEYDOWN: case FL_SHORTCUT: if (Fl::event_key() == FL_Up) { up_button_.do_callback(FL_REASON_DRAGGED); return 1; } else if (Fl::event_key() == FL_Down) { down_button_.do_callback(FL_REASON_DRAGGED); return 1; } return 0; case FL_FOCUS: if (input_.take_focus()) return 1; return 0; } return Fl_Group::handle(event); } void Fl_Spinner::resize(int X, int Y, int W, int H) { Fl_Group::resize(X,Y,W,H); input_.resize(X, Y, W - H / 2 - 2, H); up_button_.resize(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2); down_button_.resize(X + W - H / 2 - 2, Y + H - H / 2, H / 2 + 2, H / 2); } /** Sets or returns the amount to change the value when the user clicks a button. Before setting step to a non-integer value, the spinner type() should be changed to floating point. \see double Fl_Spinner::step() const */ void Fl_Spinner::step(double s) { step_ = s; if (step_ != (int)step_) input_.type(FL_FLOAT_INPUT); else input_.type(FL_INT_INPUT); update(); } /** Sets the numeric representation in the input field. Valid values are FL_INT_INPUT and FL_FLOAT_INPUT. Also changes the format() template. Setting a new spinner type via a superclass pointer will not work. \note type() is not a virtual function. */ void Fl_Spinner::type(uchar v) { if (v == FL_FLOAT_INPUT) { format("%.*f"); } else { format("%.0f"); } input_.type(v); } /** Handles events of Fl_Spinner's embedded input widget. Works like Fl_Input::handle() but ignores FL_Up and FL_Down keys so they can be handled by the parent widget (Fl_Spinner). */ int Fl_Spinner::Fl_Spinner_Input::handle(int event) { if (event == FL_KEYBOARD) { const int key = Fl::event_key(); if (key == FL_Up || key == FL_Down) { Fl_Input::handle(FL_UNFOCUS); // sets and potentially clips the input value return 0; } } return Fl_Input::handle(event); } fltk-1.4.3/src/Fl_lock.cxx0000644000175000017500000001550515004135251015477 0ustar albrechtalbrecht// // Multi-threading support code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "Fl_System_Driver.H" #include /* From Bill: I would prefer that FLTK contain the minimal amount of extra stuff for doing threads. There are other portable thread wrapper libraries out there and FLTK should not be providing another. This file is an attempt to make minimal additions and make them self-contained in this source file. From Mike: Starting with 1.1.8, we now have a callback so that you can process awake() messages as they come in. The API: Fl::lock() - recursive lock. You must call this before the first call to Fl::wait()/run() to initialize the thread system. The lock is locked all the time except when Fl::wait() is waiting for events. Fl::unlock() - release the recursive lock. Fl::awake(void*) - Causes Fl::wait() to return (with the lock locked) even if there are no events ready. Fl::awake(void (*cb)(void *), void*) - Call a function in the main thread from within another thread of execution. Fl::thread_message() - returns an argument sent to an Fl::awake() call, or returns NULL if none. WARNING: the current implementation only has a one-entry queue and only returns the most recent value! */ #ifndef FL_DOXYGEN Fl_Awake_Handler *Fl::awake_ring_; void **Fl::awake_data_; int Fl::awake_ring_size_; int Fl::awake_ring_head_; int Fl::awake_ring_tail_; #endif static const int AWAKE_RING_SIZE = 1024; /** Adds an awake handler for use in awake(). */ int Fl::add_awake_handler_(Fl_Awake_Handler func, void *data) { int ret = 0; Fl::system_driver()->lock_ring(); if (!awake_ring_) { awake_ring_size_ = AWAKE_RING_SIZE; awake_ring_ = (Fl_Awake_Handler*)malloc(awake_ring_size_*sizeof(Fl_Awake_Handler)); awake_data_ = (void**)malloc(awake_ring_size_*sizeof(void*)); // explicitly initialize the head and tail indices awake_ring_head_= awake_ring_tail_ = 0; } // The next head index we will want (not the current index): // We use this to check if the ring-buffer is full or not // (and to update awake_ring_head_ if we do use the current index.) int next_head = awake_ring_head_ + 1; if (next_head >= awake_ring_size_) { next_head = 0; } // check that the ring buffer is not full, and that it exists if ((!awake_ring_) || (next_head == awake_ring_tail_)) { // ring is non-existent or full. Return -1 as an error indicator. ret = -1; } else { awake_ring_[awake_ring_head_] = func; awake_data_[awake_ring_head_] = data; awake_ring_head_ = next_head; } Fl::system_driver()->unlock_ring(); return ret; } /** Gets the last stored awake handler for use in awake(). */ int Fl::get_awake_handler_(Fl_Awake_Handler &func, void *&data) { int ret = 0; Fl::system_driver()->lock_ring(); if ((!awake_ring_) || (awake_ring_head_ == awake_ring_tail_)) { ret = -1; } else { func = awake_ring_[awake_ring_tail_]; data = awake_data_[awake_ring_tail_]; ++awake_ring_tail_; if (awake_ring_tail_ >= awake_ring_size_) { awake_ring_tail_ = 0; } } Fl::system_driver()->unlock_ring(); return ret; } /** Let the main thread know an update is pending and have it call a specific function. Registers a function that will be called by the main thread during the next message handling cycle. Returns 0 if the callback function was registered, and -1 if registration failed. Over a thousand awake callbacks can be registered simultaneously. \see Fl::awake(void* message=0) */ int Fl::awake(Fl_Awake_Handler func, void *data) { int ret = add_awake_handler_(func, data); Fl::awake(); return ret; } /** \fn int Fl::lock() The lock() method blocks the current thread until it can safely access FLTK widgets and data. Child threads should call this method prior to updating any widgets or accessing data. The main thread must call lock() to initialize the threading support in FLTK. lock() will return non-zero if threading is not available on the platform. Child threads must call unlock() when they are done accessing FLTK. When the wait() method is waiting for input or timeouts, child threads are given access to FLTK. Similarly, when the main thread needs to do processing, it will wait until all child threads have called unlock() before processing additional data. \return 0 if threading is available on the platform; non-zero otherwise. See also: \ref advanced_multithreading */ /** \fn void Fl::unlock() The unlock() method releases the lock that was set using the lock() method. Child threads should call this method as soon as they are finished accessing FLTK. See also: \ref advanced_multithreading */ /** \fn void Fl::awake(void* msg) Sends a message pointer to the main thread, causing any pending Fl::wait() call to terminate so that the main thread can retrieve the message and any pending redraws can be processed. Multiple calls to Fl::awake() will queue multiple pointers for the main thread to process, up to a system-defined (typically several thousand) depth. The default message handler saves the last message which can be accessed using the Fl::thread_message() function. In the context of a threaded application, a call to Fl::awake() with no argument will trigger event loop handling in the main thread. Since it is not possible to call Fl::flush() from a subsidiary thread, Fl::awake() is the best (and only, really) substitute. It's \e not necessary to wrap calls to any form of Fl::awake() by Fl::lock() and Fl::unlock(). Nevertheless, the early, single call to Fl::lock() used to initialize threading support is necessary. Function Fl::awake() in all its forms is typically called by worker threads, but it can be used safely by the main thread too, as a means to break the event loop. \see \ref advanced_multithreading */ void Fl::awake(void *v) { Fl::system_driver()->awake(v); } void* Fl::thread_message() { return Fl::system_driver()->thread_message(); } int Fl::lock() { return Fl::system_driver()->lock(); } void Fl::unlock() { Fl::system_driver()->unlock(); } #ifndef FL_DOXYGEN bool Fl_System_Driver::awake_ring_empty() { Fl::system_driver()->lock_ring(); bool retval = (Fl::awake_ring_head_ == Fl::awake_ring_tail_); Fl::system_driver()->unlock_ring(); return retval; } #endif // FL_DOXYGEN fltk-1.4.3/src/Fl_Widget_Surface.cxx0000644000175000017500000001675415004135251017451 0ustar albrechtalbrecht// // Drivers code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include "Fl_Window_Driver.H" #include "Fl_Screen_Driver.H" /** The constructor. \param d can be nul. */ Fl_Widget_Surface::Fl_Widget_Surface(Fl_Graphics_Driver *d) : Fl_Surface_Device(d) { x_offset = 0; y_offset = 0; } /** \brief Draws the widget on the drawing surface. The widget's position on the surface is determined by the last call to origin() and by the optional delta_x and delta_y arguments. Its dimensions are in points unless there was a previous call to scale(). \param[in] widget Any FLTK widget (e.g., standard, custom, window). \param[in] delta_x,delta_y Optional horizontal and vertical offsets for positioning the widget top left relatively to the current origin of graphics. */ void Fl_Widget_Surface::draw(Fl_Widget* widget, int delta_x, int delta_y) { int old_x, old_y, new_x, new_y, is_window; if ( ! widget->visible() ) return; bool need_push = !is_current(); if (need_push) Fl_Surface_Device::push_current(this); is_window = (widget->as_window() != NULL); uchar old_damage = widget->damage(); widget->damage(FL_DAMAGE_ALL); // set origin to the desired top-left position of the widget origin(&old_x, &old_y); new_x = old_x + delta_x; new_y = old_y + delta_y; if (!is_window) { new_x -= widget->x(); new_y -= widget->y(); } if (new_x != old_x || new_y != old_y) { translate(new_x - old_x, new_y - old_y ); } // if widget is a window, clip all drawings to the window area if (is_window) { fl_push_clip(0, 0, widget->w(), widget->h()); } // we do some trickery to recognize OpenGL windows and draw them via a plugin int drawn_by_plugin = 0; if (widget->as_gl_window()) { Fl_Device_Plugin *plugin = Fl_Device_Plugin::opengl_plugin(); if (plugin) { drawn_by_plugin = plugin->print(widget); } } if (!drawn_by_plugin) { widget->draw(); Fl_Overlay_Window *over = (is_window ? widget->as_window()->as_overlay_window() : NULL); if (over) over->draw_overlay(); } if (is_window) fl_pop_clip(); // find subwindows of widget and print them traverse(widget); // reset origin to where it was if (new_x != old_x || new_y != old_y) { untranslate(); } if ((old_damage & FL_DAMAGE_CHILD) == 0) widget->clear_damage(old_damage); else widget->damage(FL_DAMAGE_ALL); if (need_push) Fl_Surface_Device::pop_current(); } void Fl_Widget_Surface::traverse(Fl_Widget *widget) { Fl_Group *g = widget->as_group(); if (!g) return; int n = g->children(); for (int i = 0; i < n; i++) { Fl_Widget *c = g->child(i); if ( !c->visible() ) continue; if ( c->as_window() ) { draw(c, c->x(), c->y()); } else traverse(c); } } /** Translates the current graphics origin accounting for the current rotation. Each translate() call must be matched by an untranslate() call. Successive translate() calls add up their effects. */ void Fl_Widget_Surface::translate(int x, int y) { } /** Undoes the effect of a previous translate() call. */ void Fl_Widget_Surface::untranslate() { } /** \brief Computes the coordinates of the current origin of graphics functions. \param[out] x,y If non-null, *x and *y are set to the horizontal and vertical coordinates of the graphics origin. */ void Fl_Widget_Surface::origin(int *x, int *y) { if (x) *x = x_offset; if (y) *y = y_offset; } /** \brief Sets the position of the origin of graphics in the drawable part of the drawing surface. Arguments should be expressed relatively to the result of a previous printable_rect() call. That is, printable_rect(&w, &h); origin(w/2, 0); sets the graphics origin at the top center of the drawable area. Successive origin() calls don't combine their effects. Origin() calls are not affected by rotate() calls (for classes derived from Fl_Paged_Device). \param[in] x,y Horizontal and vertical positions in the drawing surface of the desired origin of graphics. */ void Fl_Widget_Surface::origin(int x, int y) { x_offset = x; y_offset = y; } /** Draws a rectangular part of an on-screen window. \param win The window from where to capture. Can be an Fl_Gl_Window. Sub-windows that intersect the rectangle are also captured. \param x The rectangle left \param y The rectangle top \param w The rectangle width \param h The rectangle height \param delta_x,delta_y Optional horizontal and vertical offsets from current graphics origin where to draw the top left of the captured rectangle. */ void Fl_Widget_Surface::print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x, int delta_y) { if (!win->shown()) return; bool need_push = !Fl_Display_Device::display_device()->is_current(); if (need_push) Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); Fl_Window *save_front = Fl::first_window(); win->show(); Fl::check(); Fl_Window_Driver::driver(win)->flush(); // makes the window current Fl_RGB_Image *img = Fl_Screen_Driver::traverse_to_gl_subwindows(win, x, y, w, h, NULL); if (img) img->scale(w, h, 1, 1); if (save_front != win) save_front->show(); if (need_push) Fl_Surface_Device::pop_current(); if (img) { need_push = !is_current(); if (need_push) Fl_Surface_Device::push_current(this); img->draw(delta_x, delta_y); if (need_push) Fl_Surface_Device::pop_current(); delete img; } } /** Computes the width and height of the drawable area of the drawing surface. Values are in the same unit as that used by FLTK drawing functions and are unchanged by calls to origin(). If the object is derived from class Fl_Paged_Device, values account for the user-selected paper type and print orientation and are changed by scale() calls. \return 0 if OK, non-zero if any error */ int Fl_Widget_Surface::printable_rect(int *w, int *h) {return 1;} /** Draws a window with its title bar and frame if any. \p win_offset_x and \p win_offset_y are optional coordinates of where to position the window top left. Equivalent to draw() if \p win is a subwindow or has no border. Use Fl_Window::decorated_w() and Fl_Window::decorated_h() to get the size of the framed window. */ void Fl_Widget_Surface::draw_decorated_window(Fl_Window *win, int win_offset_x, int win_offset_y) { Fl_RGB_Image *top=0, *left=0, *bottom=0, *right=0; if (win->shown() && win->border() && !win->parent()) { Fl_Window_Driver::driver(win)->capture_titlebar_and_borders(top, left, bottom, right); } bool need_push = !is_current(); if (need_push) Fl_Surface_Device::push_current(this); int wsides = left ? left->w() : 0; int toph = top ? top->h() : 0; if (top) { top->draw(win_offset_x, win_offset_y); delete top; } if (left) { left->draw(win_offset_x, win_offset_y + toph); delete left; } if (right) { right->draw(win_offset_x + wsides + win->w(), win_offset_y + toph); delete right; } if (bottom) { bottom->draw(win_offset_x, win_offset_y + toph + win->h()); delete bottom; } this->draw(win, win_offset_x + wsides, win_offset_y + toph); if (need_push) Fl_Surface_Device::pop_current(); } fltk-1.4.3/src/Fl_Group.cxx0000644000175000017500000007604015004135251015644 0ustar albrechtalbrecht// // Group widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Fl_Group is the basic container type in FLTK. Other container types // (classes) are usually subclasses of Fl_Group. // Fl_Window itself is a subclass of this, and most of the event // handling is designed so windows themselves work correctly. #include #include "Fl_Window_Driver.H" #include #include #include // malloc etc. Fl_Group* Fl_Group::current_; // Hack: A single child is stored in the pointer to the array, while // multiple children are stored in an allocated array: /** Returns a pointer to the array of children. \note This pointer is only valid until the next time a child is added or removed. */ Fl_Widget*const* Fl_Group::array() const { return children_ <= 1 ? &child1_ : array_; } /** Searches the child array for the widget and returns the index. Returns children() if the widget is NULL or not found. */ int Fl_Group::find(const Fl_Widget* o) const { Fl_Widget*const* a = array(); int i; for (i=0; i < children_; i++) if (*a++ == o) break; return i; } // Some (* which? *) compilers / toolchains can't export the static // class member: current_, so these methods can't be inlined... /** Sets the current group so you can build the widget tree by just constructing the widgets. begin() is automatically called by the constructor for Fl_Group (and thus for Fl_Window as well). begin() is exactly the same as current(this). Don't forget to end() the group or window! */ void Fl_Group::begin() {current_ = this;} /** Exactly the same as current(this->parent()). Any new widgets added to the widget tree will be added to the parent of the group. */ void Fl_Group::end() {current_ = parent();} /** Returns the currently active group. The Fl_Widget constructor automatically does current()->add(widget) if this is not null. To prevent new widgets from being added to a group, call Fl_Group::current(0). */ Fl_Group *Fl_Group::current() {return current_;} /** Sets the current group. \see Fl_Group::current() */ void Fl_Group::current(Fl_Group *g) {current_ = g;} extern Fl_Widget* fl_oldfocus; // set by Fl::focus // For back-compatibility, we must adjust all events sent to child // windows so they are relative to that window. static int send(Fl_Widget* o, int event) { if (!o->as_window()) return o->handle(event); switch ( event ) { case FL_DND_ENTER: /* FALLTHROUGH */ case FL_DND_DRAG: // figure out correct type of event: event = (o->contains(Fl::belowmouse())) ? FL_DND_DRAG : FL_DND_ENTER; } int save_x = Fl::e_x; Fl::e_x -= o->x(); int save_y = Fl::e_y; Fl::e_y -= o->y(); int ret = o->handle(event); Fl::e_y = save_y; Fl::e_x = save_x; switch ( event ) { case FL_ENTER: /* FALLTHROUGH */ case FL_DND_ENTER: // Successful completion of FL_ENTER means the widget is now the // belowmouse widget, but only call Fl::belowmouse if the child // widget did not do so: if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o); break; } return ret; } // translate the current keystroke into up/down/left/right for navigation: static int navkey() { // The app may want these for hotkeys, check key state if (Fl::event_state(FL_CTRL | FL_ALT | FL_META)) return 0; switch (Fl::event_key()) { case 0: // not an FL_KEYBOARD/FL_SHORTCUT event break; case FL_Tab: if (!Fl::event_state(FL_SHIFT)) return FL_Right; return FL_Left; case FL_Right: return FL_Right; case FL_Left: return FL_Left; case FL_Up: return FL_Up; case FL_Down: return FL_Down; } return 0; } int Fl_Group::handle(int event) { Fl_Widget*const* a = array(); int i; Fl_Widget* o; switch (event) { case FL_FOCUS: switch (navkey()) { default: if (savedfocus_ && savedfocus_->take_focus()) return 1; case FL_Right: case FL_Down: for (i = children(); i--;) if ((*a++)->take_focus()) return 1; break; case FL_Left: case FL_Up: for (i = children(); i--;) if (a[i]->take_focus()) return 1; break; } return 0; case FL_UNFOCUS: savedfocus_ = fl_oldfocus; return 0; case FL_KEYBOARD: return navigation(navkey()); case FL_SHORTCUT: for (i = children(); i--;) { o = a[i]; if (o->takesevents() && Fl::event_inside(o) && send(o,FL_SHORTCUT)) return 1; } for (i = children(); i--;) { o = a[i]; if (o->takesevents() && !Fl::event_inside(o) && send(o,FL_SHORTCUT)) return 1; } if ((Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter)) return navigation(FL_Down); return 0; case FL_ENTER: case FL_MOVE: for (i = children(); i--;) { o = a[i]; if (o->visible() && Fl::event_inside(o)) { if (o->contains(Fl::belowmouse())) { return send(o,FL_MOVE); } else { Fl::belowmouse(o); if (send(o,FL_ENTER)) return 1; } } } Fl::belowmouse(this); return 1; case FL_DND_ENTER: case FL_DND_DRAG: for (i = children(); i--;) { o = a[i]; if (o->takesevents() && Fl::event_inside(o)) { if (o->contains(Fl::belowmouse())) { return send(o,FL_DND_DRAG); } else if (send(o,FL_DND_ENTER)) { if (!o->contains(Fl::belowmouse())) Fl::belowmouse(o); return 1; } } } Fl::belowmouse(this); return 0; case FL_PUSH: for (i = children(); i--;) { o = a[i]; if (o->takesevents() && Fl::event_inside(o)) { Fl_Widget_Tracker wp(o); if (send(o,FL_PUSH)) { if (Fl::pushed() && wp.exists() && !o->contains(Fl::pushed())) Fl::pushed(o); return 1; } } } return 0; case FL_RELEASE: case FL_DRAG: o = Fl::pushed(); if (o == this) return 0; else if (o) send(o,event); else { for (i = children(); i--;) { o = a[i]; if (o->takesevents() && Fl::event_inside(o)) { if (send(o,event)) return 1; } } } return 0; case FL_MOUSEWHEEL: for (i = children(); i--;) { o = a[i]; if (o->takesevents() && Fl::event_inside(o) && send(o,FL_MOUSEWHEEL)) return 1; } for (i = children(); i--;) { o = a[i]; if (o->takesevents() && !Fl::event_inside(o) && send(o,FL_MOUSEWHEEL)) return 1; } return 0; case FL_DEACTIVATE: case FL_ACTIVATE: for (i = children(); i--;) { o = *a++; if (o->active()) o->handle(event); } return 1; case FL_SHOW: case FL_HIDE: for (i = children(); i--;) { o = *a++; if (event == FL_HIDE && o == Fl::focus()) { // Give up input focus... int old_event = Fl::e_number; o->handle(Fl::e_number = FL_UNFOCUS); Fl::e_number = old_event; Fl::focus(0); } if (o->visible()) o->handle(event); } return 1; default: // For all other events, try to give to each child, starting at focus: for (i = 0; i < children(); i ++) if (Fl::focus_ == a[i]) break; if (i >= children()) i = 0; if (children()) { for (int j = i;;) { if (a[j]->takesevents()) if (send(a[j], event)) return 1; j++; if (j >= children()) j = 0; if (j == i) break; } } return 0; } } // try to move the focus in response to a keystroke: int Fl_Group::navigation(int key) { if (children() <= 1) return 0; int i; for (i = 0; ; i++) { if (i >= children_) return 0; if (array_[i]->contains(Fl::focus())) break; } Fl_Widget *previous = array_[i]; for (;;) { switch (key) { case FL_Right: case FL_Down: i++; if (i >= children_) { if (parent()) return 0; i = 0; } break; case FL_Left: case FL_Up: if (i) i--; else { if (parent()) return 0; i = children_-1; } break; default: return 0; } Fl_Widget* o = array_[i]; if (o == previous) return 0; switch (key) { case FL_Down: case FL_Up: // for up/down, the widgets have to overlap horizontally: if (o->x() >= previous->x()+previous->w() || o->x()+o->w() <= previous->x()) continue; } if (o->take_focus()) return 1; } } //////////////////////////////////////////////////////////////// Fl_Group::Fl_Group(int X,int Y,int W,int H,const char *l) : Fl_Widget(X,Y,W,H,l) { align(FL_ALIGN_TOP); children_ = 0; array_ = 0; savedfocus_ = 0; resizable_ = this; bounds_ = 0; // this is allocated when first resize() is done sizes_ = 0; // see bounds_ (FLTK 1.3 compatibility) // Subclasses may want to construct child objects as part of their // constructor, so make sure they are add()'d to this object. // But you must end() the object! begin(); } /** Deletes all child widgets from memory recursively. This method differs from the remove() method in that it affects all child widgets and deletes them from memory. The resizable() widget of the Fl_Group is set to the Fl_Group itself. \internal If the Fl_Group widget contains the Fl::focus() or the Fl::pushed() widget these are set to sensible values (other widgets or the Fl_Group widget itself). \see Fl_Group::remove(int), Fl_Group::delete_child(int), Fl_Group::~Fl_Group() */ void Fl_Group::clear() { savedfocus_ = 0; resizable_ = this; init_sizes(); // we must change the Fl::pushed() widget, if it is one of // the group's children. Otherwise fl_fix_focus() would send lots // of events to children that are about to be deleted anyway. Fl_Widget *pushed = Fl::pushed(); // save pushed() widget if (contains(pushed)) pushed = this; // set it to be the group, if it's a child Fl::pushed(this); // for fl_fix_focus etc. // Implementation note (AlbrechtS, Nov. 01, 2022): // For some obscure reason the order of all children had been // reversed in FLTK 1.3.x so the first child would be deleted // first but this is no longer done since FLTK 1.4.0. // Reasoning: // (1) it is supposedly better to remove children in the // order "last in, first out" // (2) it would not be compatible with the new subclass // notification feature Fl_Group::on_remove(). // See git commit a918292547cfb154 or earlier for removed code. // End of implementation note. // Okay, now it is safe to destroy the children. Children are // removed and deleted in the order from last child to first // child which is much faster than the other way around and // should be the "natural order" (last in, first out). while (children_) { // delete all children int idx = children_-1; // last child's index Fl_Widget* w = child(idx); // last child widget if (w->parent()==this) { // should always be true if (children_>2) { // optimized removal w->parent_ = 0; // reset child's parent on_remove(idx); children_--; // update counter } else { // slow removal remove(idx); } delete w; // delete the child } else { // should never happen remove(idx); // remove it anyway } } if (pushed != this) Fl::pushed(pushed); // reset pushed() widget } /** The destructor also deletes all the children. This allows a whole tree to be deleted at once, without having to keep a pointer to all the children in the user code. It is allowed that the Fl_Group and all of its children are automatic (local) variables, but you must declare the Fl_Group \e first, so that it is destroyed last. If you add static or automatic (local) variables to an Fl_Group, then it is your responsibility to remove (or delete) all such static or automatic child widgets \e \b before destroying the group - otherwise the group will attempt to call delete operator on them leading to undefined behavior! */ Fl_Group::~Fl_Group() { if (current_ == this) end(); clear(); } /** Allow derived groups to act when a widget is added as a child. Widgets derived from Fl_Group may store additional data for their children. Overriding this method will allow derived classes to generate these data structures just before the child is added. This method usually returns the same index that was given in the parameters. By setting a new index, the position of other widgets in the child pointer array can be preserved (e.g. Fl_Scroll keeps its scroll bars as the last two children). By returning -1, Fl_Group::insert will not add the child to array_. This is not recommended, but Fl_Table does something similar to forward children to a hidden group. \param candidate the candidate will be added to the child array_ after this method returns. \param index add the child at this position in the array_ \return index to position the child as planned \return a new index to force the child to a different position \return -1 to keep the group from adding the candidate */ int Fl_Group::on_insert(Fl_Widget *candidate, int index) { (void)candidate; return index; } /** Allow derived groups to act when a widget is moved within the group. Widgets derived from Fl_Group may store additional data for their children. Overriding this method will allow derived classes to move these data structures just before the child itself is moved. This method usually returns the new index that was given in the parameters. By setting a different destination index, the position of other widgets in the child pointer array can be preserved. By returning -1, Fl_Group::insert will not move the child. \param oldIndex the current index of the child that will be moved \param newIndex the new index of the child \return \p newIndex to position the child as planned \return a different index to force the child to a different position \return -1 to keep the group from moving the child */ int Fl_Group::on_move(int oldIndex, int newIndex) { (void)oldIndex; return newIndex; } /** The widget is removed from its current group (if any) and then inserted into this group. It is put at index n - or at the end, if n >= children(). This can also be used to rearrange the widgets inside a group. */ void Fl_Group::insert(Fl_Widget &o, int index) { if (o.parent()) { Fl_Group* g = o.parent(); int n = g->find(o); if (g == this) { // avoid expensive remove() and add() if we just move a widget within the group index = on_move(n, index); if (index < 0) return; // don't move: requested by subclass if (index > children_) index = children_; if (index > n) index--; // compensate for removal and re-insertion if (index == n) return; // same position; this includes (children_ == 1) if (index > n) memmove(array_+n, array_+(n+1), (index-n) * sizeof(Fl_Widget*)); else memmove(array_+(index+1), array_+index, (n-index) * sizeof(Fl_Widget*)); array_[index] = &o; init_sizes(); return; } g->remove(n); } index = on_insert(&o, index); if (index == -1) return; o.parent_ = this; if (children_ == 0) { // use array pointer to point at single child child1_ = &o; } else if (children_ == 1) { // go from 1 to 2 children Fl_Widget* t = child1_; array_ = (Fl_Widget**)malloc(2*sizeof(Fl_Widget*)); if (index) {array_[0] = t; array_[1] = &o;} else {array_[0] = &o; array_[1] = t;} } else { if (!(children_ & (children_-1))) // double number of children array_ = (Fl_Widget**)realloc((void*)array_, 2*children_*sizeof(Fl_Widget*)); int j; for (j = children_; j > index; j--) array_[j] = array_[j-1]; array_[j] = &o; } children_++; init_sizes(); } /** The widget is removed from its current group (if any) and then added to the end of this group. */ void Fl_Group::add(Fl_Widget &o) {insert(o, children_);} /** Allow derived groups to act when a child widget is removed from the group. Widgets derived from Fl_Group may store additional data for their children. Overriding this method will allow derived classes to remove these data structures just before the child is removed. \param index remove the child at this position in the array_ */ void Fl_Group::on_remove(int index) { (void)index; } /** Removes the widget at \p index from the group but does not delete it. This method does nothing if \p index is out of bounds. This method differs from the clear() method in that it only affects a single widget and does not delete it from memory. \since FLTK 1.3.0 */ void Fl_Group::remove(int index) { if (index < 0 || index >= children_) return; on_remove(index); Fl_Widget &o = *child(index); if (&o == savedfocus_) savedfocus_ = 0; if (&o == resizable_) resizable_ = this; if (o.parent_ == this) { // this should always be true o.parent_ = 0; } // remove the widget from the group children_--; if (children_ == 1) { // go from 2 to 1 child Fl_Widget *t = array_[!index]; free((void*)array_); child1_ = t; } else if (children_ > 1) { // delete from array for (; index < children_; index++) array_[index] = array_[index+1]; } init_sizes(); } /** Removes a widget from the group but does not delete it. This method does nothing if the widget is not a child of the group. This method differs from the clear() method in that it only affects a single widget and does not delete it from memory. \note If you have the child's index anyway, use remove(int index) instead, because this doesn't need a child lookup in the group's table of children. This can be much faster, if there are lots of children. */ void Fl_Group::remove(Fl_Widget &o) { if (!children_) return; int i = find(o); if (i < children_) remove(i); } /** Removes the widget at \p index from the group and deletes it. This method does nothing if \p index is out of bounds. This method differs from the remove() method in that it deletes the widget from memory. Since this method is virtual it can be reimplemented in subclasses with additional requirements and consequences. See the documentation of subclasses. Many subclasses don't need to reimplement this method. \note This method \b may refuse to remove and delete the widget if it is an essential part of the Fl_Group, for instance a scrollbar in an Fl_Scroll group. In this case the widget is neither removed nor deleted. This method does not call init_sizes() or redraw(). This is left to user code if necessary. Returns 0 if the widget was removed and deleted. Return values \> 0 are reserved for use by FLTK core widgets. Return values \< 0 are free to be used by user defined widgets. \todo Reimplementation of Fl_Group::delete_child(int) in more FLTK subclasses. This is not yet complete. \param[in] index index of child to be removed \returns success (0) or error code \retval 0 success \retval 1 index out of range \retval 2 widget not allowed to be removed (see note) \retval >2 reserved for FLTK use \since FLTK 1.4.0 */ int Fl_Group::delete_child(int index) { if (index < 0 || index >= children_) return 1; Fl_Widget *w = child(index); remove(index); delete w; return 0; } /** Resets the internal array of widget sizes and positions. The Fl_Group widget keeps track of the original widget sizes and positions when resizing occurs so that if you resize a window back to its original size the widgets will be in the correct places. If you rearrange the widgets in your group, call this method to register the new arrangement with the Fl_Group that contains them. If you add or remove widgets, this will be done automatically. \note The internal array of widget sizes and positions will be allocated and filled when the next resize() occurs. For more information on the contents and structure of the bounds() array see bounds(). \see bounds() \see sizes() (deprecated) */ void Fl_Group::init_sizes() { delete[] bounds_; bounds_ = 0; delete[] sizes_; // FLTK 1.3 compatibility sizes_ = 0; // FLTK 1.3 compatibility } /** Returns the internal array of widget sizes and positions. If the bounds() array does not exist, it will be allocated and filled with the current widget sizes and positions. The bounds() array stores the initial positions of widgets as Fl_Rect's. The size of the array is children() + 2. - The first Fl_Rect is the group, - the second is the resizable (clipped to the group), - the rest are the children. This is a convenient order for the resize algorithm. If the group and/or the resizable() is a Fl_Window (or subclass) then the x() and y() coordinates of their respective Fl_Rect's are zero. \note You should never need to use this \e protected method directly, unless you have special needs to rearrange the children of a Fl_Group. Fl_Tile uses this to rearrange its widget positions. The returned array should be considered read-only. Do not change its contents. If you need to rearrange children in a group, do so by resizing the children and call init_sizes(). \#include \ if you want to access the bounds() array in your derived class. Fl_Rect.H is intentionally not included by Fl_Group.H to avoid unnecessary dependencies. \returns Array of Fl_Rect's with widget positions and sizes. The returned array is only valid until init_sizes() is called or widgets are added to or removed from the group. \see init_sizes() \since FLTK 1.4.0 \internal Notes to developers: - If you change this be sure to fix Fl_Tile which also uses this array! - Do not \#include Fl_Rect.H in Fl_Group.H because this would introduce lots of unnecessary dependencies on Fl_Rect.H. */ Fl_Rect* Fl_Group::bounds() { if (!bounds_) { Fl_Rect* p = bounds_ = new Fl_Rect[children_+2]; // first thing in bounds array is the group's size: if (as_window()) p[0] = Fl_Rect(w(),h()); // x = y = 0 else p[0] = Fl_Rect(this); // next is the resizable's size: int left = p->x(); // init to the group's position and size int top = p->y(); int right = p->r(); int bottom = p->b(); Fl_Widget* r = resizable(); if (r && r != this) { // then clip the resizable to it int t; t = r->x(); if (t > left) left = t; t +=r->w(); if (t < right) right = t; t = r->y(); if (t > top) top = t; t +=r->h(); if (t < bottom) bottom = t; } p[1] = Fl_Rect(left, top, right-left, bottom-top); // next is all the children's sizes: p += 2; Fl_Widget*const* a = array(); for (int i=children_; i--;) { *p++ = Fl_Rect(*a++); } } return bounds_; } /** Returns the internal array of widget sizes and positions. For backward compatibility with FLTK versions before 1.4. The sizes() array stores the initial positions of widgets as (left, right, top, bottom) quads. The first quad is the group, the second is the resizable (clipped to the group), and the rest are the children. If the group and/or the resizable() is a Fl_Window, then the first (left) and third (top) entries of their respective quads (x,y) are zero. \deprecated Deprecated since 1.4.0. Please use bounds() instead. \note This method will be removed in a future FLTK version (1.5.0 or higher). \returns Array of int's with widget positions and sizes. The returned array is only valid until init_sizes() is called or widgets are added to or removed from the group. \note Since FLTK 1.4.0 the returned array is a \b read-only and re-ordered copy of the internal bounds() array. Do not change its contents. If you need to rearrange children in a group, do so by resizing the children and call init_sizes(). \see bounds() */ int* Fl_Group::sizes() { if (sizes_) return sizes_; // allocate new sizes_ array and copy bounds_ over to sizes_ int* pi = sizes_ = new int[4*(children_+2)]; Fl_Rect *rb = bounds(); for (int i = 0; i < children_+2; i++, rb++) { *pi++ = rb->x(); *pi++ = rb->r(); *pi++ = rb->y(); *pi++ = rb->b(); } return sizes_; } /** Resizes the Fl_Group widget and all of its children. The Fl_Group widget first resizes itself, and then it moves and resizes all its children according to the rules documented for Fl_Group::resizable(Fl_Widget*) \sa Fl_Group::resizable(Fl_Widget*) \sa Fl_Group::resizable() \sa Fl_Widget::resize(int,int,int,int) */ void Fl_Group::resize(int X, int Y, int W, int H) { int dx = X - x(); int dy = Y - y(); int dw = W - w(); int dh = H - h(); Fl_Rect* p = bounds(); // save initial sizes and positions Fl_Widget::resize(X, Y, W, H); // make new xywh values visible for children // Part 1: no resizable() or both width and height didn't change, // just move the children. // This case covers also window rescaling where dw == dh == 0. if (!resizable() || (dw==0 && dh==0)) { // top window and subwindows must not change the position of their children if (as_window()) dx = dy = 0; // Check if there's anything to do, otherwise don't call resize(). // Note that subwindows require resize() even if their relative position // didn't change, at least on macOS, if it's a rescale. if (Fl_Window::is_a_rescale() || dx || dy) { Fl_Widget*const* a = array(); for (int i = children_; i--;) { Fl_Widget* o = *a++; o->resize(o->x() + dx, o->y() + dy, o->w(), o->h()); } } } // End of part 1 // Part 2: here we definitely have a resizable() widget, resize children else if (children_) { // get changes in size/position from the initial size: dx = X - p->x(); dw = W - p->w(); dy = Y - p->y(); dh = H - p->h(); if (as_window()) dx = dy = 0; p++; // Developer note: // The following code uses T = top, L = left, R = right, and B = bottom // widget bounds. T and L are equivalent to x() and y(), whereas // R = x() + w() and B = y() + h(), respectively, i.e. the next pixel // beyond the widget border. // RL, RR, RT, and RB are those values of the resizable widget. // get initial size of resizable(): int RL = p->x(); int RR = RL + p->w(); int RT = p->y(); int RB = RT + p->h(); p++; // resize children Fl_Widget*const* a = array(); for (int i = children_; i--; p++) { Fl_Widget* o = *a++; int L = p->x(); int R = L + p->w(); int T = p->y(); int B = T + p->h(); // widget resizing code from Francois Ostiguy (since FLTK 1.4.0) if (L >= RR) L += dw; else if (L > RL) L += dw * (L-RL) / (RR-RL); if (R >= RR) R += dw; else if (R > RL) R += dw * (R-RL) / (RR-RL); if (T >= RB) T += dh; else if (T > RT) T += dh * (T-RT) / (RB-RT); if (B >= RB) B += dh; else if (B > RT) B += dh * (B-RT) / (RB-RT); o->resize(L+dx, T+dy, R-L, B-T); } } // End of part 2: we have a resizable() widget } /** Draws all children of the group. This is useful, if you derived a widget from Fl_Group and want to draw a special border or background. You can call draw_children() from the derived draw() method after drawing the box, border, or background. */ void Fl_Group::draw_children() { Fl_Widget*const* a = array(); if (clip_children()) { fl_push_clip(x() + Fl::box_dx(box()), y() + Fl::box_dy(box()), w() - Fl::box_dw(box()), h() - Fl::box_dh(box())); } if (damage() & ~FL_DAMAGE_CHILD) { // redraw the entire thing: for (int i=children_; i--;) { Fl_Widget& o = **a++; draw_child(o); draw_outside_label(o); } } else { // only redraw the children that need it: for (int i=children_; i--;) update_child(**a++); } if (clip_children()) fl_pop_clip(); } void Fl_Group::draw() { if (damage() & ~FL_DAMAGE_CHILD) { // redraw the entire thing: draw_box(); draw_label(); } draw_children(); } /** Draws a child only if it needs it. This draws a child widget, if it is not clipped \em and if any damage() bits are set. The damage bits are cleared after drawing. \sa Fl_Group::draw_child(Fl_Widget& widget) const */ void Fl_Group::update_child(Fl_Widget& widget) const { if (widget.damage() && widget.visible() && widget.type() < FL_WINDOW && fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) { widget.draw(); widget.clear_damage(); } } /** Forces a child to redraw. This draws a child widget, if it is not clipped. The damage bits are cleared after drawing. */ void Fl_Group::draw_child(Fl_Widget& widget) const { if (widget.visible() && widget.type() < FL_WINDOW && fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) { // The following call clears all damage flags and then *sets* FL_DAMAGE_ALL widget.clear_damage(FL_DAMAGE_ALL); widget.draw(); widget.clear_damage(); } } /** Parents normally call this to draw outside labels of child widgets. */ void Fl_Group::draw_outside_label(const Fl_Widget& widget) const { if (!widget.visible()) return; // skip any labels that are inside the widget: if (!(widget.align()&15) || (widget.align() & FL_ALIGN_INSIDE)) return; // invent a box that is outside the widget: Fl_Align a = widget.align(); int X = widget.x(); int Y = widget.y(); int W = widget.w(); int H = widget.h(); int wx, wy; if (const_cast(this)->as_window()) { wx = wy = 0; } else { wx = x(); wy = y(); } if ( (a & FL_ALIGN_POSITION_MASK) == FL_ALIGN_LEFT_TOP ) { a = (a &(~FL_ALIGN_POSITION_MASK) ) | FL_ALIGN_TOP_RIGHT; X = wx; W = widget.x()-X-3; } else if ( (a & FL_ALIGN_POSITION_MASK) == FL_ALIGN_LEFT_BOTTOM ) { a = (a &(~FL_ALIGN_POSITION_MASK) ) | FL_ALIGN_BOTTOM_RIGHT; X = wx; W = widget.x()-X-3; } else if ( (a & FL_ALIGN_POSITION_MASK) == FL_ALIGN_RIGHT_TOP ) { a = (a &(~FL_ALIGN_POSITION_MASK) ) | FL_ALIGN_TOP_LEFT; X = X+W+3; W = wx+this->w()-X; } else if ( (a & FL_ALIGN_POSITION_MASK) == FL_ALIGN_RIGHT_BOTTOM ) { a = (a &(~FL_ALIGN_POSITION_MASK) ) | FL_ALIGN_BOTTOM_LEFT; X = X+W+3; W = wx+this->w()-X; } else if (a & FL_ALIGN_TOP) { a ^= FL_ALIGN_TOP; a |= FL_ALIGN_BOTTOM; Y = wy; H = widget.y()-Y; } else if (a & FL_ALIGN_BOTTOM) { a ^= FL_ALIGN_BOTTOM; a |= FL_ALIGN_TOP; Y = Y+H; H = wy+h()-Y; } else if (a & FL_ALIGN_LEFT) { a ^= FL_ALIGN_LEFT; a |= FL_ALIGN_RIGHT; X = wx; W = widget.x()-X-3; } else if (a & FL_ALIGN_RIGHT) { a ^= FL_ALIGN_RIGHT; a |= FL_ALIGN_LEFT; X = X+W+3; W = wx+this->w()-X; } widget.draw_label(X,Y,W,H,(Fl_Align)a); } fltk-1.4.3/src/fl_gtk.cxx0000644000175000017500000002245515004135251015376 0ustar albrechtalbrecht// // "GTK" drawing routines for the Fast Light Tool Kit (FLTK). // // These box types provide a GTK+ look, based on Red Hat's Bluecurve // theme... // // Copyright 2006-2010 by Michael Sweet. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Box drawing code for an obscure box type. // These box types are in separate files so they are not linked // in if not used. #include #include extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*, Fl_Box_Draw_Focus_F* =NULL); static void gtk_color(Fl_Color c) { Fl::set_box_color(c); } static void gtk_up_frame(int x, int y, int w, int h, Fl_Color c) { gtk_color(fl_color_average(FL_WHITE, c, 0.5)); fl_xyline(x + 2, y + 1, x + w - 3); fl_yxline(x + 1, y + 2, y + h - 3); gtk_color(fl_color_average(FL_BLACK, c, 0.5)); fl_begin_loop(); fl_vertex(x, y + 2); fl_vertex(x + 2, y); fl_vertex(x + w - 3, y); fl_vertex(x + w - 1, y + 2); fl_vertex(x + w - 1, y + h - 3); fl_vertex(x + w - 3, y + h - 1); fl_vertex(x + 2, y + h - 1); fl_vertex(x, y + h - 3); fl_end_loop(); } static void gtk_up_box(int x, int y, int w, int h, Fl_Color c) { gtk_up_frame(x, y, w, h, c); gtk_color(fl_color_average(FL_WHITE, c, 0.4f)); fl_xyline(x + 2, y + 2, x + w - 3); gtk_color(fl_color_average(FL_WHITE, c, 0.2f)); fl_xyline(x + 2, y + 3, x + w - 3); gtk_color(fl_color_average(FL_WHITE, c, 0.1f)); fl_xyline(x + 2, y + 4, x + w - 3); gtk_color(c); fl_rectf(x + 2, y + 5, w - 4, h - 7); gtk_color(fl_color_average(FL_BLACK, c, 0.025f)); fl_xyline(x + 2, y + h - 4, x + w - 3); gtk_color(fl_color_average(FL_BLACK, c, 0.05f)); fl_xyline(x + 2, y + h - 3, x + w - 3); gtk_color(fl_color_average(FL_BLACK, c, 0.1f)); fl_xyline(x + 2, y + h - 2, x + w - 3); fl_yxline(x + w - 2, y + 2, y + h - 3); } static void gtk_down_frame(int x, int y, int w, int h, Fl_Color c) { gtk_color(fl_color_average(FL_BLACK, c, 0.5)); fl_begin_loop(); fl_vertex(x, y + 2); fl_vertex(x + 2, y); fl_vertex(x + w - 3, y); fl_vertex(x + w - 1, y + 2); fl_vertex(x + w - 1, y + h - 3); fl_vertex(x + w - 3, y + h - 1); fl_vertex(x + 2, y + h - 1); fl_vertex(x, y + h - 3); fl_end_loop(); gtk_color(fl_color_average(FL_BLACK, c, 0.1f)); fl_xyline(x + 2, y + 1, x + w - 3); fl_yxline(x + 1, y + 2, y + h - 3); gtk_color(fl_color_average(FL_BLACK, c, 0.05f)); fl_yxline(x + 2, y + h - 2, y + 2, x + w - 2); } static void gtk_down_box(int x, int y, int w, int h, Fl_Color c) { gtk_down_frame(x, y, w, h, c); gtk_color(c); fl_rectf(x + 3, y + 3, w - 5, h - 4); fl_yxline(x + w - 2, y + 3, y + h - 3); } static void gtk_thin_up_frame(int x, int y, int w, int h, Fl_Color c) { gtk_color(fl_color_average(FL_WHITE, c, 0.6f)); fl_xyline(x + 1, y, x + w - 2); fl_yxline(x, y + 1, y + h - 2); gtk_color(fl_color_average(FL_BLACK, c, 0.4f)); fl_xyline(x + 1, y + h - 1, x + w - 2); fl_yxline(x + w - 1, y + 1, y + h - 2); } static void gtk_thin_up_box(int x, int y, int w, int h, Fl_Color c) { gtk_thin_up_frame(x, y, w, h, c); gtk_color(fl_color_average(FL_WHITE, c, 0.4f)); fl_xyline(x + 1, y + 1, x + w - 2); gtk_color(fl_color_average(FL_WHITE, c, 0.2f)); fl_xyline(x + 1, y + 2, x + w - 2); gtk_color(fl_color_average(FL_WHITE, c, 0.1f)); fl_xyline(x + 1, y + 3, x + w - 2); gtk_color(c); fl_rectf(x + 1, y + 4, w - 2, h - 8); gtk_color(fl_color_average(FL_BLACK, c, 0.025f)); fl_xyline(x + 1, y + h - 4, x + w - 2); gtk_color(fl_color_average(FL_BLACK, c, 0.05f)); fl_xyline(x + 1, y + h - 3, x + w - 2); gtk_color(fl_color_average(FL_BLACK, c, 0.1f)); fl_xyline(x + 1, y + h - 2, x + w - 2); } static void gtk_thin_down_frame(int x, int y, int w, int h, Fl_Color c) { gtk_color(fl_color_average(FL_BLACK, c, 0.4f)); fl_xyline(x + 1, y, x + w - 2); fl_yxline(x, y + 1, y + h - 2); gtk_color(fl_color_average(FL_WHITE, c, 0.6f)); fl_xyline(x + 1, y + h - 1, x + w - 2); fl_yxline(x + w - 1, y + 1, y + h - 2); } static void gtk_thin_down_box(int x, int y, int w, int h, Fl_Color c) { gtk_thin_down_frame(x, y, w, h, c); gtk_color(c); fl_rectf(x + 1, y + 1, w - 2, h - 2); } //------------------------ // new GTK+ style for round buttons #if 1 static void fl_arc_i(int x,int y,int w,int h,double a1,double a2) { fl_arc(x,y,w,h,a1,a2); } enum {UPPER_LEFT, LOWER_RIGHT, CLOSED, FILL}; static void draw(int which, int x,int y,int w,int h, int inset) { if (inset*2 >= w) inset = (w-1)/2; if (inset*2 >= h) inset = (h-1)/2; x += inset; y += inset; w -= 2*inset; h -= 2*inset; int d = w <= h ? w : h; if (d <= 1) return; void (*f)(int,int,int,int,double,double); f = (which==FILL) ? fl_pie : fl_arc_i; if (which >= CLOSED) { if (w == h) f(x, y, d, d, 0, 360); else { f(x+w-d, y, d, d, w<=h ? 0 : -90, w<=h ? 180 : 90); f(x, y+h-d, d, d, w<=h ? 180 : 90, w<=h ? 360 : 270); } } else if (which == UPPER_LEFT) { f(x+w-d, y, d, d, 45, w<=h ? 180 : 90); f(x, y+h-d, d, d, w<=h ? 180 : 90, 225); } else { // LOWER_RIGHT f(x, y+h-d, d, d, 225, w<=h ? 360 : 270); f(x+w-d, y, d, d, w<=h ? 360 : 270, 360+45); } if (which == FILL) { if (w < h) fl_rectf(x, y+d/2, w, h-(d&-2)); else if (w > h) fl_rectf(x+d/2, y, w-(d&-2), h); } else { if (w < h) { if (which != UPPER_LEFT) fl_yxline(x+w-1, y+d/2-1, y+h-d/2+1); if (which != LOWER_RIGHT) fl_yxline(x, y+d/2-1, y+h-d/2+1); } else if (w > h) { if (which != UPPER_LEFT) fl_xyline(x+d/2-1, y+h-1, x+w-d/2+1); if (which != LOWER_RIGHT) fl_xyline(x+d/2-1, y, x+w-d/2+1); } } } static void gtk_round_up_box(int x, int y, int w, int h, Fl_Color c) { gtk_color(c); draw(FILL, x, y, w, h, 2); gtk_color(fl_color_average(FL_BLACK, c, 0.025f)); draw(LOWER_RIGHT, x+1, y, w-2, h, 2); draw(LOWER_RIGHT, x, y, w, h, 3); gtk_color(fl_color_average(FL_BLACK, c, 0.05f)); draw(LOWER_RIGHT, x+1, y, w-2, h, 1); draw(LOWER_RIGHT, x, y, w, h, 2); gtk_color(fl_color_average(FL_BLACK, c, 0.1f)); draw(LOWER_RIGHT, x+1, y, w-2, h, 0); draw(LOWER_RIGHT, x, y, w, h, 1); gtk_color(fl_color_average(FL_WHITE, c, 0.1f)); draw(UPPER_LEFT, x, y, w, h, 4); draw(UPPER_LEFT, x+1, y, w-2, h, 3); gtk_color(fl_color_average(FL_WHITE, c, 0.2f)); draw(UPPER_LEFT, x, y, w, h, 3); draw(UPPER_LEFT, x+1, y, w-2, h, 2); gtk_color(fl_color_average(FL_WHITE, c, 0.4f)); draw(UPPER_LEFT, x, y, w, h, 2); draw(UPPER_LEFT, x+1, y, w-2, h, 1); gtk_color(fl_color_average(FL_WHITE, c, 0.5f)); draw(UPPER_LEFT, x, y, w, h, 1); draw(UPPER_LEFT, x+1, y, w-2, h, 0); gtk_color(fl_color_average(FL_BLACK, c, 0.5f)); draw(CLOSED, x, y, w, h, 0); } static void gtk_round_down_box(int x, int y, int w, int h, Fl_Color c) { gtk_color(c); draw(FILL, x, y, w, h, 2); gtk_color(fl_color_average(FL_WHITE, c, 0.1f)); draw(LOWER_RIGHT, x+1, y, w-2, h, 2); draw(LOWER_RIGHT, x, y, w, h, 3); gtk_color(fl_color_average(FL_WHITE, c, 0.2f)); draw(LOWER_RIGHT, x+1, y, w-2, h, 1); draw(LOWER_RIGHT, x, y, w, h, 2); gtk_color(fl_color_average(FL_WHITE, c, 0.5f)); draw(LOWER_RIGHT, x+1, y, w-2, h, 0); draw(LOWER_RIGHT, x, y, w, h, 1); gtk_color(fl_color_average(FL_BLACK, c, 0.05f)); draw(UPPER_LEFT, x, y, w, h, 2); draw(UPPER_LEFT, x+1, y, w-2, h, 1); gtk_color(fl_color_average(FL_BLACK, c, 0.1f)); draw(UPPER_LEFT, x, y, w, h, 1); draw(UPPER_LEFT, x+1, y, w-2, h, 0); gtk_color(fl_color_average(FL_BLACK, c, 0.5f)); draw(CLOSED, x, y, w, h, 0); } #else static void gtk_round_up_box(int x, int y, int w, int h, Fl_Color c) { gtk_color(c); fl_pie(x, y, w, h, 0.0, 360.0); gtk_color(fl_color_average(FL_WHITE, c, 0.5f)); fl_arc(x, y, w, h, 45.0, 180.0); gtk_color(fl_color_average(FL_WHITE, c, 0.25f)); fl_arc(x, y, w, h, 180.0, 405.0); gtk_color(fl_color_average(FL_BLACK, c, 0.5f)); fl_arc(x, y, w, h, 225.0, 360.0); } static void gtk_round_down_box(int x, int y, int w, int h, Fl_Color c) { gtk_color(c); fl_pie(x, y, w, h, 0.0, 360.0); gtk_color(fl_color_average(FL_BLACK, c, 0.2)); fl_arc(x + 1, y, w, h, 90.0, 210.0); gtk_color(fl_color_average(FL_BLACK, c, 0.6)); fl_arc(x, y, w, h, 0.0, 360.0); } #endif extern void fl_round_focus(Fl_Boxtype bt, int x, int y, int w, int h, Fl_Color fg, Fl_Color bg); Fl_Boxtype fl_define_FL_GTK_UP_BOX() { fl_internal_boxtype(_FL_GTK_UP_BOX, gtk_up_box); fl_internal_boxtype(_FL_GTK_DOWN_BOX, gtk_down_box); fl_internal_boxtype(_FL_GTK_UP_FRAME, gtk_up_frame); fl_internal_boxtype(_FL_GTK_DOWN_FRAME, gtk_down_frame); fl_internal_boxtype(_FL_GTK_THIN_UP_BOX, gtk_thin_up_box); fl_internal_boxtype(_FL_GTK_THIN_DOWN_BOX, gtk_thin_down_box); fl_internal_boxtype(_FL_GTK_THIN_UP_FRAME, gtk_thin_up_frame); fl_internal_boxtype(_FL_GTK_THIN_DOWN_FRAME, gtk_thin_down_frame); fl_internal_boxtype(_FL_GTK_ROUND_UP_BOX, gtk_round_up_box, fl_round_focus); fl_internal_boxtype(_FL_GTK_ROUND_DOWN_BOX, gtk_round_down_box, fl_round_focus); return _FL_GTK_UP_BOX; } fltk-1.4.3/src/filename_expand.cxx0000644000175000017500000000302015004135251017232 0ustar albrechtalbrecht// // Filename expansion routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_System_Driver.H" #include /** Expands a filename containing shell variables and tilde (~). Currently handles these variants: \code "~username" // if 'username' does not exist, result will be unchanged "~/file" "$VARNAME" // does NOT handle ${VARNAME} \endcode \b Examples: \code #include [..] putenv("TMPDIR=/var/tmp"); fl_filename_expand(out, sizeof(out), "~fred/.cshrc"); // out="/usr/fred/.cshrc" fl_filename_expand(out, sizeof(out), "~/.cshrc"); // out="/usr//.cshrc" fl_filename_expand(out, sizeof(out), "$TMPDIR/foo.txt"); // out="/var/tmp/foo.txt" \endcode \param[out] to resulting expanded filename \param[in] tolen size of the expanded filename buffer \param[in] from filename containing shell variables \return 0 if no change, non zero otherwise */ int fl_filename_expand(char *to,int tolen, const char *from) { return Fl::system_driver()->filename_expand(to, tolen, from); } fltk-1.4.3/src/Fl_Bitmap.cxx0000644000175000017500000001302615004135251015757 0ustar albrechtalbrecht// // Bitmap drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \fn Fl_Bitmap::Fl_Bitmap(const char *array, int W, int H) The constructors create a new bitmap from the specified bitmap data.*/ /** \fn Fl_Bitmap::Fl_Bitmap(const unsigned char *array, int W, int H) The constructors create a new bitmap from the specified bitmap data.*/ #include #include #include #include #include #include void Fl_Bitmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { fl_graphics_driver->draw_bitmap(this, XP, YP, WP, HP, cx, cy); } /** The constructors create a new bitmap from the specified bitmap data. If the provided array is too small to contain all the image data, the constructor will not generate the bitmap to avoid illegal memory read access and instead set \c data to NULL and \c ld to \c ERR_MEMORY_ACCESS. \param bits bitmap data, one pixel per bit, rows are rounded to the next byte \param bits_length length of the \p bits array in bytes \param W image width in pixels \param H image height in pixels \see Fl_Bitmap(const char *bits, int bits_length, int W, int H), Fl_Bitmap(const uchar *bits, int W, int H) */ Fl_Bitmap::Fl_Bitmap(const uchar *bits, int bits_length, int W, int H) : Fl_Image(W,H,0), array((const uchar *)bits), alloc_array(0), id_(0), cache_w_(0), cache_h_(0) { int rowBytes = (W+7)>>3; int min_length = rowBytes * H; if (bits_length >= min_length) { data((const char **)&array, 1); } else { array = NULL; data(NULL, 0); ld(ERR_MEMORY_ACCESS); } } /** The constructors create a new bitmap from the specified bitmap data. If the provided array is too small to contain all the image data, the constructor will not generate the bitmap to avoid illegal memory read access and instead set \c data to NULL and \c ld to \c ERR_MEMORY_ACCESS. \param bits bitmap data, one pixel per bit, rows are rounded to the next byte \param bits_length length of the \p bits array in bytes \param W image width in pixels \param H image height in pixels \see Fl_Bitmap(const uchar *bits, int bits_length, int W, int H), Fl_Bitmap(const char *bits, int W, int H) */ Fl_Bitmap::Fl_Bitmap(const char *bits, int bits_length, int W, int H) : Fl_Image(W,H,0), array((const uchar *)bits), alloc_array(0), id_(0), cache_w_(0), cache_h_(0) { int rowBytes = (W+7)>>3; int min_length = rowBytes * H; if (bits_length >= min_length) { data((const char **)&array, 1); } else { array = NULL; data(NULL, 0); ld(ERR_MEMORY_ACCESS); } } /** The destructor frees all memory and server resources that are used by the bitmap. */ Fl_Bitmap::~Fl_Bitmap() { uncache(); if (alloc_array) delete[] (uchar *)array; } void Fl_Bitmap::uncache() { if (id_) { fl_graphics_driver->delete_bitmask(id_); id_ = 0; } } void Fl_Bitmap::label(Fl_Widget* widget) { widget->image(this); } void Fl_Bitmap::label(Fl_Menu_Item* m) { m->label(FL_IMAGE_LABEL, (const char*)this); } Fl_Image *Fl_Bitmap::copy(int W, int H) const { Fl_Bitmap *new_image; // New RGB image uchar *new_array; // New array for image data // Optimize the simple copy where the width and height are the same... if (W == data_w() && H == data_h()) { new_array = new uchar [H * ((W + 7) / 8)]; memcpy(new_array, array, H * ((W + 7) / 8)); new_image = new Fl_Bitmap(new_array, W, H); new_image->alloc_array = 1; return new_image; } if (W <= 0 || H <= 0) return 0; // OK, need to resize the image data; allocate memory and uchar *new_ptr, // Pointer into new array new_bit, // Bit for new array old_bit; // Bit for old array const uchar *old_ptr; // Pointer into old array int sx, sy, // Source coordinates dx, dy, // Destination coordinates xerr, yerr, // X & Y errors xmod, ymod, // X & Y moduli xstep, ystep; // X & Y step increments // Figure out Bresenham step/modulus values... xmod = data_w() % W; xstep = data_w() / W; ymod = data_h() % H; ystep = data_h() / H; // Allocate memory for the new image... new_array = new uchar [H * ((W + 7) / 8)]; new_image = new Fl_Bitmap(new_array, W, H); new_image->alloc_array = 1; memset(new_array, 0, H * ((W + 7) / 8)); // Scale the image using a nearest-neighbor algorithm... for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) { for (dx = W, xerr = W, old_ptr = array + sy * ((data_w() + 7) / 8), sx = 0, new_bit = 1; dx > 0; dx --) { old_bit = (uchar)(1 << (sx & 7)); if (old_ptr[sx / 8] & old_bit) *new_ptr |= new_bit; if (new_bit < 128) new_bit <<= 1; else { new_bit = 1; new_ptr ++; } sx += xstep; xerr -= xmod; if (xerr <= 0) { xerr += W; sx ++; } } if (new_bit > 1) new_ptr ++; sy += ystep; yerr -= ymod; if (yerr <= 0) { yerr += H; sy ++; } } return new_image; } fltk-1.4.3/src/Fl_Message.cxx0000644000175000017500000004250515004135251016133 0ustar albrechtalbrecht// // Common dialog implementation for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** \file Fl_Message.cxx - Base class for common dialogs. This is the base class for all common FLTK dialog windows used in fl_message(), fl_ask(), fl_choice(), fl_input(), and fl_password(). \note Internal use only. This class may be changed as required without notice.\n This class is reserved for FLTK's internal usage in common dialogs in FLTK 1.4.x and later. The header file is "hidden" in the src/ folder and not installed with the public header files. \since 1.4.0 All common dialogs can be altered by changing the contents of some static class variables. This is done by accessor methods like fl_message_title() and others defined in FL/fl_ask.H. This is for backwards compatibility with FLTK 1.3.x and earlier. \note The documentation is only visible if the CMake option \c 'FLTK_INCLUDE_DRIVER_DOCS' is enabled. */ #include #include "flstring.h" #include #include "Fl_Message.h" // intentionally "hidden" in src/... #include "FL/fl_string_functions.h" // fl_strdup() #include #include #include #include #include #include #include #include #include #include // Fl_Message static variables const char *Fl_Message::message_title_default_; const char *Fl_Message::message_title_; const char *Fl_Message::message_icon_label_; Fl_Box *Fl_Message::message_icon_; char *Fl_Message::input_buffer_; int Fl_Message::input_size_; int Fl_Message::enable_hotspot_ = 1; int Fl_Message::form_x_ = 0; int Fl_Message::form_y_ = 0; int Fl_Message::form_position_ = 0; // 0 = not set, 1 = absolute, 2 = centered /** Fl_Message's internal button callback. This callback function is used when the user pushes a button, presses the \c Return key, or uses a valid shortcut for one of the buttons. The internal return value \p retval_ is set according to the button that was invoked (0, 1, 2) and \p window_closed_ is set to 0 (dialog closed by dialog button). Then the dialog window is closed (hidden). */ void Fl_Message::button_cb_(Fl_Widget *w, void *d) { Fl_Window *window = w->window(); Fl_Message *dialog = (Fl_Message *)window->user_data(); dialog->window_closed_ = 0; dialog->retval_ = fl_int(d); // button window->hide(); } // button_cb_() /** Fl_Message's internal window callback. This callback function is used internally when the dialog window is closed by the user with the window close button or by pressing \c Escape. The internal return value \p retval_ is set to 0 (i.e. button 0) and \p window_closed_ is set to -1 (Escape) or -2 (window close button). Then the dialog window is closed (hidden). */ void Fl_Message::window_cb_(Fl_Widget *w, void *d) { Fl_Window *window = (Fl_Window *)w; Fl_Message *dialog = (Fl_Message *)window->user_data(); if ((Fl::event() == FL_KEYBOARD || Fl::event() == FL_SHORTCUT) && (Fl::event_key() == FL_Escape)) dialog->window_closed_ = -1; else dialog->window_closed_ = -2; dialog->retval_ = 0; // either window or button 0 window->hide(); } // window_cb_() /** Fl_Message constructor. The constructor creates a default message window and sets the icon type to the given \p iconlabel which can be any character (or string). If fl_message_icon_label() has been called before this label is used instead and reset to NULL after the message window has been created. Message text box (Fl_Box), icon (Fl_Box), and an input (Fl_Input) widgets are created and initialized. Three buttons are created and arranged right to left in the message window. The second (middle) button is an Fl_Return_Button. The message window is set to modal() */ Fl_Message::Fl_Message(const char *iconlabel) : window_(0) , retval_(0) , window_closed_(0) { // Make sure that the dialog does not become the child of some current group. Fl_Group *previous_group = Fl_Group::current(); if (previous_group) Fl_Group::current(0); // create widgets window_ = new Fl_Window(400, 150, NULL); message_ = new Fl_Message_Box(60, 25, 340, 20); message_->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_WRAP); input_ = new Fl_Input(60, 37, 340, 23); input_->hide(); Fl_Box *icon_template = message_icon(); // use template for icon box icon_ = new Fl_Box(10, 10, 50, 50); icon_->box(icon_template->box()); icon_->labelfont(icon_template->labelfont()); icon_->labelsize(icon_template->labelsize()); icon_->color(icon_template->color()); icon_->labelcolor(icon_template->labelcolor()); icon_->image(icon_template->image()); icon_->align(icon_template->align()); if (message_icon_label_) { // fl_message_icon_label() has been called icon_->copy_label(message_icon_label_); message_icon_label_ = 0; } else if (icon_template->label()) { // sticky icon template label() has been set icon_->copy_label(icon_template->label()); } else { // default string (c'tor argument) icon_->label(iconlabel); } window_->end(); // don't add the buttons automatically // create the buttons (positions: right to left) // button 1 is a return button for (int b = 0, x = 310; b < 3; b++, x -= 100) { if (b == 1) { button_[b] = new Fl_Return_Button(x, 70, 90, 23); } else { button_[b] = new Fl_Button(x, 70, 90, 23); } button_[b]->align(FL_ALIGN_INSIDE | FL_ALIGN_WRAP); button_[b]->callback(button_cb_, fl_voidptr(b)); } // add the buttons left to right for tab navigation for (int b = 2; b >= 0; b--) { window_->add(button_[b]); } window_->begin(); window_->resizable(new Fl_Box(60, 10, 110 - 60, 27)); window_->end(); window_->callback(window_cb_, this); window_->set_modal(); // restore previous group Fl_Group::current(previous_group); } /** Resizes the form and widgets so that they hold everything that is asked of them. */ void Fl_Message::resizeform() { int i; int message_w, message_h; int text_height; int button_w[3], button_h[3]; int x, w, h, max_w, max_h; const int icon_size = 50; fl_font(message_->labelfont(), message_->labelsize()); message_w = message_h = 0; fl_measure(message_->label(), message_w, message_h); message_w += 10; message_h += 10; if (message_w < 340) message_w = 340; if (message_h < 30) message_h = 30; fl_font(button_[0]->labelfont(), button_[0]->labelsize()); memset(button_w, 0, sizeof(button_w)); memset(button_h, 0, sizeof(button_h)); for (max_h = 25, i = 0; i < 3; i++) if (button_[i]->visible()) { fl_measure(button_[i]->label(), button_w[i], button_h[i]); if (i == 1) button_w[1] += 20; // account for return button arrow button_w[i] += 30; button_h[i] += 10; if (button_h[i] > max_h) max_h = button_h[i]; } if (input_->visible()) text_height = message_h + 25; else text_height = message_h; max_w = message_w + 10 + icon_size; w = button_w[0] + button_w[1] + button_w[2] - 10; if (w > max_w) max_w = w; // if the button horizontally overlap the icon, make sure that they are drawn // below to icon by making the text part at least as tall as the icon. if (w > message_w && text_height < icon_size) { int pad_h = icon_size-text_height; message_h += pad_h; text_height += pad_h; } message_w = max_w - 10 - icon_size; w = max_w + 20; h = max_h + 30 + text_height; window_->size(w, h); window_->size_range(w, h, w, h); message_->resize(20 + icon_size, 10, message_w, message_h); icon_->resize(10, 10, icon_size, icon_size); icon_->labelsize(icon_size - 10); input_->resize(20 + icon_size, 10 + message_h, message_w, 25); for (x = w, i = 0; i < 3; i++) { if (button_w[i]) { x -= button_w[i]; button_[i]->resize(x, h - 10 - max_h, button_w[i] - 10, max_h); } } window_->init_sizes(); } /** Does all Fl_Message window internals for messages with and w/o an input field. This method finalizes the layout of the message window, arranges (shows or hides) the buttons and the optional text input widget, sets the message window title, pops up the window, and waits for user input. The message window is positioned according to the positioning options set before calling the message function. The private variables \p retval_ and \p window_closed_ are set depending on the user action (pushing a button or closing the window). \note The above mentioned variables must be evaluated before the event loop is called because they might be overwritten by another dialog. It is safe to evaluate the variables before the message function returns. \param[in] fmt printf style format used in the user function call \param[in] ap argument list provided by the user function call \param[in] b0 text of button 0 (right: usually the "cancel" button) \param[in] b1 text of button 1 (middle) \param[in] b2 text of button 2 (left) \returns return code \retval 0 for Escape, window close, or button 0 \retval 1 button 1 was pushed \retval 2 button 2 was pushed */ int Fl_Message::innards(const char *fmt, va_list ap, const char *b0, const char *b1, const char *b2) { Fl::pushed(0); // stop dragging (STR #2159) char buffer[1024]; if (!strcmp(fmt, "%s")) { message_->label(va_arg(ap, const char *)); } else { ::vsnprintf(buffer, sizeof(buffer) - 1, fmt, ap); message_->label(buffer); } message_->labelfont(fl_message_font_); if (fl_message_size_ == -1) message_->labelsize(FL_NORMAL_SIZE); else message_->labelsize(fl_message_size_); if (b0) { button_[0]->show(); button_[0]->label(b0); button_[1]->position(210, 70); } else { button_[0]->hide(); button_[1]->position(310, 70); } if (b1) { button_[1]->show(); button_[1]->label(b1); } else button_[1]->hide(); if (b2) { button_[2]->show(); button_[2]->label(b2); } else button_[2]->hide(); resizeform(); if (button_[1]->visible() && !input_->visible()) button_[1]->take_focus(); if (form_position_) { if (form_position_ == 2) { // centered form_x_ -= window_->w() / 2; form_y_ -= window_->h() / 2; } window_->position(form_x_, form_y_); form_x_ = form_y_ = form_position_ = 0; } else if (enable_hotspot_) window_->hotspot(b0 ? button_[0] : button_[1]); else window_->free_position(); if (b0 && Fl_Widget::label_shortcut(b0)) button_[0]->shortcut(0); // set the one-time window title, if defined and a specific title is not set if (!window_->label() && message_title_) { window_->copy_label(message_title_); message_title(0); // reset global message title (compat.) } // set default window title, if defined and a specific title is not set if (!window_->label() && message_title_default_) window_->copy_label(message_title_default_); // deactivate Fl::grab() because it is incompatible with modal windows Fl_Window *g = Fl::grab(); if (g) Fl::grab(0); Fl_Group *current_group = Fl_Group::current(); // make sure the dialog does not interfere with any active group Fl_Group::current(0); window_->show(); Fl_Group::current(current_group); while (window_->shown()) Fl::wait(); if (g) // regrab the previous popup menu, if there was one Fl::grab(g); return retval_; } /** Gets the default icon container (Fl_Box) used in common dialogs. Many common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), and fl_password() display an icon. You can use this method to get the icon box (Fl_Box) and modify the icon's box type, font, fontsize etc. \since FLTK 1.4.0 \note This method replaces the deprecated method fl_message_icon(). Note that this new method correctly returns an Fl_Box * pointer, whereas fl_message_icon() returns Fl_Widget *. The current icon default values are: - width and height: 50 (currently not changeable) - box(FL_THIN_UP_BOX) - labelfont(FL_TIMES_BOLD) - labelsize(34) - color(FL_WHITE) - labelcolor(FL_BLUE) These values may be changed in a future FLTK version (although this is not very likely to happen). If you change this then the changed values are used for subsequently started common dialogs. This is intended to change the icon layout for your application at startup time. It is not recommended to change the default values for each message. */ Fl_Box *Fl_Message::message_icon() { if (!Fl_Message::message_icon_) { // not yet initialized Fl_Group *current_group = Fl_Group::current(); Fl_Group::current(0); Fl_Box *o = Fl_Message::message_icon_ = new Fl_Box(10, 10, 50, 50); o->box(FL_THIN_UP_BOX); o->labelfont(FL_TIMES_BOLD); o->labelsize(34); o->color(FL_WHITE); o->labelcolor(FL_BLUE); Fl_Group::current(current_group); } return Fl_Message::message_icon_; } /** Does all Fl_Message window internals for messages with a text input field. \param[in] fmt printf style format used in the user function call \param[in] ap argument list provided by the user function call \param[in] defstr default string given by the user \param[in] type either FL_NORMAL_INPUT or FL_SECRET_INPUT (password) \param[in] maxchar max. number of allowed characters (not bytes) \param[in] str true: return type is string, false: internal buffer \returns pointer to string or NULL if cancel or escape were hit \see innards() */ const char *Fl_Message::input_innards(const char *fmt, va_list ap, const char *defstr, uchar type, int maxchar, bool str) { message_->position(60, 10); input_->type(type); input_->show(); input_->value(defstr); input_->take_focus(); if (maxchar > 0) input_->maximum_size(maxchar); int r = innards(fmt, ap, fl_cancel, fl_ok, 0); if (!r) return 0; if (input_->value()) { int size = input_->size() + 1; if (!str) { // need to store the value in pre-allocated buffer // The allocated input buffer starts with size 0 and is allocated // in multiples of 128 bytes >= size. If both the size and the pointer // are 0 (NULL) then realloc() allocates a /new/ buffer. if (size > input_size_) { size += 127; size &= ~127; input_buffer_ = (char *)realloc(input_buffer_, size); input_size_ = size; } // Store the input. Note that value() can contain null bytes, // so we use memcpy and add a terminating null byte as well. memcpy(input_buffer_, input_->value(), input_->size()); input_buffer_[input_->size()] = '\0'; return (input_buffer_); } else { // string version: return value() which will be copied return input_->value(); } } else return 0; } /** Sets the title of the dialog window used in many common dialogs. This window \p title will be used in the next call of one of the common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), fl_password(). The \p title string is copied internally, so that you can use a local variable or free the string immediately after this call. It applies only to the \b next call of one of the common dialogs and will be reset to an empty title (the default for all dialogs) after that call. \param[in] title window label, string copied internally */ void Fl_Message::message_title(const char *title) { if (message_title_) { free((void *)message_title_); message_title_ = 0; } if (title) message_title_ = fl_strdup(title); } /** Sets the default title of the dialog window used in many common dialogs. This window \p title will be used in all subsequent calls of one of the common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), fl_password(), unless a specific title has been set with fl_message_title(const char *title). The default is no title. You can override the default title for a single dialog with fl_message_title(const char *title). The \p title string is copied internally, so that you can use a local variable or free the string immediately after this call. \param[in] title default window label, string copied internally */ void Fl_Message::message_title_default(const char *title) { if (message_title_default_) { free((void *)message_title_default_); message_title_default_ = 0; } if (title) message_title_default_ = fl_strdup(title); } void Fl_Message::icon_label(const char *str) { message_icon_label_ = str; } // handle ctrl-c (command-c on macOS) to copy message text int Fl_Message_Box::handle(int e) { int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT); switch (e) { case FL_KEYBOARD: case FL_SHORTCUT: if (Fl::event_key() == 'c' && mods == FL_COMMAND) { Fl::copy(label(), int(strlen(label())), 1); return 1; } break; default: break; } return Fl_Box::handle(e); } /** \} \endcond */ fltk-1.4.3/src/Fl_Native_File_Chooser_FLTK.cxx0000644000175000017500000002141415004135251021232 0ustar albrechtalbrecht// // FLTK native file chooser widget wrapper for GTK's GtkFileChooserDialog // // Copyright 1998-2014 by Bill Spitzak and others. // Copyright 2012 IMM // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include #include #include #include #include Fl_Native_File_Chooser_FLTK_Driver::Fl_Native_File_Chooser_FLTK_Driver(int val) : Fl_Native_File_Chooser_Driver(val) { _btype = 0; _options = 0; _filter = NULL; _filtvalue = 0; _parsedfilt = NULL; _preset_file = NULL; _prevvalue = NULL; _directory = NULL; _errmsg = NULL; _file_chooser= NULL; if (val >= 0) { _file_chooser = new Fl_File_Chooser(NULL, NULL, 0, NULL); type(val); // do this after _file_chooser created } _nfilters = 0; } Fl_Native_File_Chooser_FLTK_Driver::~Fl_Native_File_Chooser_FLTK_Driver() { delete _file_chooser; _file_chooser = NULL; _filter = strfree(_filter); _parsedfilt = strfree(_parsedfilt); _preset_file = strfree(_preset_file); _prevvalue = strfree(_prevvalue); _directory = strfree(_directory); _errmsg = strfree(_errmsg); } // PRIVATE: SET ERROR MESSAGE void Fl_Native_File_Chooser_FLTK_Driver::errmsg(const char *msg) { _errmsg = strfree(_errmsg); _errmsg = strnew(msg); } // PRIVATE: translate Native types to Fl_File_Chooser types int Fl_Native_File_Chooser_FLTK_Driver::type_fl_file(int val) { switch (val) { case Fl_Native_File_Chooser::BROWSE_FILE: return(Fl_File_Chooser::SINGLE); case Fl_Native_File_Chooser::BROWSE_DIRECTORY: return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::DIRECTORY); case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: return(Fl_File_Chooser::MULTI); case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::MULTI); case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::CREATE); case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::MULTI | Fl_File_Chooser::CREATE); default: return(Fl_File_Chooser::SINGLE); } } void Fl_Native_File_Chooser_FLTK_Driver::type(int val) { _btype = val; _file_chooser->type(type_fl_file(val)); } int Fl_Native_File_Chooser_FLTK_Driver::type() const { return(_btype); } void Fl_Native_File_Chooser_FLTK_Driver::options(int val) { _options = val; } int Fl_Native_File_Chooser_FLTK_Driver::options() const { return(_options); } int Fl_Native_File_Chooser_FLTK_Driver::show() { // FILTER if ( _parsedfilt ) { _file_chooser->filter(_parsedfilt); } // FILTER VALUE // Set this /after/ setting the filter // _file_chooser->filter_value(_filtvalue); // DIRECTORY if ( _directory && _directory[0] ) { _file_chooser->directory(_directory); } else { _file_chooser->directory(_prevvalue); } // PRESET FILE if ( _preset_file ) { _file_chooser->value(_preset_file); } // OPTIONS: PREVIEW _file_chooser->preview( (options() & Fl_Native_File_Chooser::PREVIEW) ? 1 : 0); // OPTIONS: NEW FOLDER if ( options() & Fl_Native_File_Chooser::NEW_FOLDER ) _file_chooser->type(_file_chooser->type() | Fl_File_Chooser::CREATE); // on // SHOW _file_chooser->show(); // BLOCK WHILE BROWSER SHOWN while ( _file_chooser->shown() ) { Fl::wait(); } if ( _file_chooser->value() && _file_chooser->value()[0] ) { _prevvalue = strfree(_prevvalue); _prevvalue = strnew(_file_chooser->value()); _filtvalue = _file_chooser->filter_value(); // update filter value // HANDLE SHOWING 'SaveAs' CONFIRM if ( options() & Fl_Native_File_Chooser::SAVEAS_CONFIRM && type() == Fl_Native_File_Chooser::BROWSE_SAVE_FILE ) { struct stat buf; if ( fl_stat(_file_chooser->value(), &buf) != -1 ) { if ( buf.st_mode & S_IFREG ) { // Regular file + exists? if ( exist_dialog() == 0 ) { return(1); } } } } } if ( _file_chooser->count() ) return(0); else return(1); } const char *Fl_Native_File_Chooser_FLTK_Driver::errmsg() const { return(_errmsg ? _errmsg : "No error"); } const char* Fl_Native_File_Chooser_FLTK_Driver::filename() const { if ( _file_chooser->count() > 0 ) { return(_file_chooser->value()); } return(""); } const char* Fl_Native_File_Chooser_FLTK_Driver::filename(int i) const { if ( i < _file_chooser->count() ) return(_file_chooser->value(i+1)); // convert fltk 1 based to our 0 based return(""); } void Fl_Native_File_Chooser_FLTK_Driver::title(const char *val) { _file_chooser->label(val); } const char *Fl_Native_File_Chooser_FLTK_Driver::title() const { return(_file_chooser->label()); } void Fl_Native_File_Chooser_FLTK_Driver::filter(const char *val) { _filter = strfree(_filter); _filter = strnew(val); parse_filter(); } const char *Fl_Native_File_Chooser_FLTK_Driver::filter() const { return(_filter); } int Fl_Native_File_Chooser_FLTK_Driver::filters() const { return(_nfilters); } void Fl_Native_File_Chooser_FLTK_Driver::filter_value(int val) { _filtvalue = val; } int Fl_Native_File_Chooser_FLTK_Driver::filter_value() const { return _filtvalue; } int Fl_Native_File_Chooser_FLTK_Driver::count() const { return _file_chooser->count(); } void Fl_Native_File_Chooser_FLTK_Driver::directory(const char *val) { _directory = strfree(_directory); _directory = strnew(val); } const char *Fl_Native_File_Chooser_FLTK_Driver::directory() const { return _directory; } // PRIVATE: Convert our filter format to fltk's chooser format // FROM TO (FLTK) // ------------------------- -------------------------- // "*.cxx" "*.cxx Files(*.cxx)" // "C Files\t*.{cxx,h}" "C Files(*.{cxx,h})" // "C Files\t*.{cxx,h}\nText Files\t*.txt" "C Files(*.{cxx,h})\tText Files(*.txt)" // // Returns a modified version of the filter that the caller is responsible // for freeing with strfree(). // void Fl_Native_File_Chooser_FLTK_Driver::parse_filter() { _parsedfilt = strfree(_parsedfilt); // clear previous parsed filter (if any) _nfilters = 0; char *in = _filter; if ( !in ) return; int has_name = strchr(in, '\t') ? 1 : 0; char mode = has_name ? 'n' : 'w'; // parse mode: n=title, w=wildcard char wildcard[1024] = ""; // parsed wildcard char name[1024] = ""; // Parse filter user specified for ( ; 1; in++ ) { /*** DEBUG printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n", *in, mode, name, wildcard); ***/ switch (*in) { // FINISHED PARSING NAME? case '\t': if ( mode != 'n' ) goto regchar; mode = 'w'; break; // ESCAPE NEXT CHAR case '\\': ++in; goto regchar; // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS? case '\r': case '\n': case '\0': // APPEND NEW FILTER TO LIST if ( wildcard[0] ) { // OUT: "name(wild)\tname(wild)" char comp[2048]; snprintf(comp, 2048, "%s%.511s(%.511s)", ((_parsedfilt)?"\t":""), name, wildcard); _parsedfilt = strapp(_parsedfilt, comp); _nfilters++; //DEBUG printf("DEBUG: PARSED FILT NOW <%s>\n", _parsedfilt); } // RESET wildcard[0] = name[0] = '\0'; mode = strchr(in, '\t') ? 'n' : 'w'; // DONE? if ( *in == '\0' ) return; // done else continue; // not done yet, more filters // Parse all other chars default: // handle all non-special chars regchar: // handle regular char switch ( mode ) { case 'n': chrcat(name, *in); continue; case 'w': chrcat(wildcard, *in); continue; } break; } } //NOTREACHED } void Fl_Native_File_Chooser_FLTK_Driver::preset_file(const char* val) { _preset_file = strfree(_preset_file); _preset_file = strnew(val); } const char* Fl_Native_File_Chooser_FLTK_Driver::preset_file() const { return _preset_file; } int Fl_Native_File_Chooser_FLTK_Driver::exist_dialog() { return fl_choice("%s", fl_cancel, fl_ok, NULL, Fl_Native_File_Chooser::file_exists_message); } /** \} \endcond */ fltk-1.4.3/src/Fl_Widget.cxx0000644000175000017500000002730215004135251015770 0ustar albrechtalbrecht// // Base widget class for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include "flstring.h" //////////////////////////////////////////////////////////////// // for compatibility with Forms, all widgets without callbacks are // inserted into a "queue" when they are activated, and the forms // compatibility interaction functions (fl_do_events, etc.) will // read one widget at a time from this queue and return it: const int QUEUE_SIZE = 20; static Fl_Widget *obj_queue[QUEUE_SIZE]; static int obj_head, obj_tail; void Fl_Widget::default_callback(Fl_Widget *widget, void * /*v*/) { obj_queue[obj_head++] = widget; if (obj_head >= QUEUE_SIZE) obj_head = 0; if (obj_head == obj_tail) { obj_tail++; if (obj_tail >= QUEUE_SIZE) obj_tail = 0; } } /** Reads the default callback queue and returns the first widget. All Fl_Widgets that don't have a callback defined use the default callback \p static Fl_Widget::default_callback() that puts a pointer to the widget in a queue. This method reads the oldest widget out of this queue. The queue (FIFO) is limited (currently 20 items). If the queue overflows, the oldest entry (Fl_Widget *) is discarded. Relying on the default callback and reading the callback queue with Fl::readqueue() is not recommended. If you need a callback, you should set one with Fl_Widget::callback(Fl_Callback *cb, void *data) or one of its variants. \see Fl_Widget::callback() \see Fl_Widget::callback(Fl_Callback *cb, void *data) \see Fl_Widget::default_callback() */ Fl_Widget *Fl::readqueue() { if (obj_tail==obj_head) return 0; Fl_Widget *widget = obj_queue[obj_tail++]; if (obj_tail >= QUEUE_SIZE) obj_tail = 0; return widget; } /* This static internal function removes all pending callbacks for a specific widget from the default callback queue (Fl::readqueue()). It is only called from Fl_Widget's destructor if the widget doesn't have an own callback. Note: There's no need to have this in the Fl:: namespace. */ static void cleanup_readqueue(Fl_Widget *w) { if (obj_tail==obj_head) return; // Read the entire queue and copy over all valid entries. // The new head will be determined after the last copied entry. int old_head = obj_head; // save newest entry int entry = obj_tail; // oldest entry obj_head = obj_tail; // new queue start for (;;) { Fl_Widget *o = obj_queue[entry++]; if (entry >= QUEUE_SIZE) entry = 0; if (o != w) { // valid entry obj_queue[obj_head++] = o; if (obj_head >= QUEUE_SIZE) obj_head = 0; } // valid entry if (entry == old_head) break; } return; } //////////////////////////////////////////////////////////////// int Fl_Widget::handle(int) { return 0; } /** Default font size for widgets */ Fl_Fontsize FL_NORMAL_SIZE = 14; Fl_Widget::Fl_Widget(int X, int Y, int W, int H, const char* L) { x_ = X; y_ = Y; w_ = W; h_ = H; label_.value = L; label_.image = 0; label_.deimage = 0; label_.type = FL_NORMAL_LABEL; label_.font = FL_HELVETICA; label_.size = FL_NORMAL_SIZE; label_.color = FL_FOREGROUND_COLOR; label_.align_ = FL_ALIGN_CENTER; label_.h_margin_ = label_.v_margin_ = 0; label_.spacing = 0; tooltip_ = 0; callback_ = default_callback; user_data_ = 0; type_ = 0; flags_ = VISIBLE_FOCUS; damage_ = 0; box_ = FL_NO_BOX; color_ = FL_GRAY; color2_ = FL_GRAY; when_ = FL_WHEN_RELEASE; parent_ = 0; if (Fl_Group::current()) Fl_Group::current()->add(this); } void Fl_Widget::resize(int X, int Y, int W, int H) { x_ = X; y_ = Y; w_ = W; h_ = H; } // this is useful for parent widgets to call to resize children: int Fl_Widget::damage_resize(int X, int Y, int W, int H) { if (x() == X && y() == Y && w() == W && h() == H) return 0; resize(X, Y, W, H); redraw(); return 1; } int Fl_Widget::take_focus() { if (!takesevents()) return 0; if (!visible_focus()) return 0; if (!handle(FL_FOCUS)) return 0; // see if it wants it if (contains(Fl::focus())) return 1; // it called Fl::focus for us Fl::focus(this); return 1; } extern void fl_throw_focus(Fl_Widget*); // in Fl_x.cxx /** Destroys the widget, taking care of throwing focus before if any. Destruction removes the widget from any parent group! And groups when destroyed destroy all their children. This is convenient and fast. */ Fl_Widget::~Fl_Widget() { Fl::clear_widget_pointer(this); if (flags() & COPIED_LABEL) free((void *)(label_.value)); if (flags() & COPIED_TOOLTIP) free((void *)(tooltip_)); image(NULL); deimage(NULL); // remove from parent group if (parent_) parent_->remove(this); #ifdef DEBUG_DELETE if (parent_) { // this should never happen printf("*** Fl_Widget: parent_->remove(this) failed [%p,%p]\n",parent_,this); } #endif // DEBUG_DELETE parent_ = 0; // Don't throw focus to a parent widget. fl_throw_focus(this); // remove stale entries from default callback queue (Fl::readqueue()) if (callback_ == default_callback) cleanup_readqueue(this); if ( (flags_ & AUTO_DELETE_USER_DATA) && user_data_) delete (Fl_Callback_User_Data*)user_data_; } /** Draws a focus box for the widget at the given position and size. This method does nothing if - the global option Fl::visible_focus() or - the per-widget option visible_focus() is false (off). This means that Fl_Widget::draw_focus() or one of the more specialized methods can be called without checking these visible focus options. \note This method must only be called if the widget has the focus. This is not tested internally. The boxtype \p bt is used to calculate the inset so the focus box is drawn inside the box borders. The default focus box drawing color is black. The background color \p bg is used to determine a better visible color if necessary by using fl_contrast() with the given background color. \param[in] bt Boxtype that needs to be considered (frame width) \param[in] X,Y,W,H Bounding box \param[in] bg Background color \see Fl_Widget::draw_focus() \see Fl_Widget::draw_focus(Fl_Boxtype, int, int, int, int) const */ void Fl_Widget::draw_focus(Fl_Boxtype bt, int X, int Y, int W, int H, Fl_Color bg) const { if (!Fl::visible_focus()) return; if (!visible_focus()) return; fl_draw_box_focus(bt, X, Y, W, H, FL_BLACK, bg); } void Fl_Widget::activate() { if (!active()) { clear_flag(INACTIVE); if (active_r()) { redraw(); redraw_label(); handle(FL_ACTIVATE); if (inside(Fl::focus())) Fl::focus()->take_focus(); } } } void Fl_Widget::deactivate() { if (active_r()) { set_flag(INACTIVE); redraw(); redraw_label(); handle(FL_DEACTIVATE); fl_throw_focus(this); } else { set_flag(INACTIVE); } } int Fl_Widget::active_r() const { for (const Fl_Widget* o = this; o; o = o->parent()) if (!o->active()) return 0; return 1; } void Fl_Widget::show() { if (!visible()) { clear_flag(INVISIBLE); if (visible_r()) { redraw(); redraw_label(); handle(FL_SHOW); if (inside(Fl::focus())) Fl::focus()->take_focus(); } } } void Fl_Widget::hide() { if (visible_r()) { set_flag(INVISIBLE); for (Fl_Widget *p = parent(); p; p = p->parent()) if (p->box() || !p->parent()) {p->redraw(); break;} handle(FL_HIDE); fl_throw_focus(this); } else { set_flag(INVISIBLE); } } int Fl_Widget::visible_r() const { for (const Fl_Widget* o = this; o; o = o->parent()) if (!o->visible()) return 0; return 1; } // return true if widget is inside (or equal to) this: // Returns false for null widgets. int Fl_Widget::contains(const Fl_Widget *o) const { for (; o; o = o->parent_) if (o == this) return 1; return 0; } void Fl_Widget::label(const char *a) { if (flags() & COPIED_LABEL) { // reassigning a copied label remains the same copied label if (label_.value == a) return; free((void *)(label_.value)); clear_flag(COPIED_LABEL); } label_.value=a; redraw_label(); } void Fl_Widget::copy_label(const char *a) { // reassigning a copied label remains the same copied label if ((flags() & COPIED_LABEL) && (label_.value == a)) return; if (a) { label(fl_strdup(a)); set_flag(COPIED_LABEL); } else { label(0); } } void Fl_Widget::image(Fl_Image* img) { if (image_bound()) { if (label_.image && (label_.image != img)) { label_.image->release(); } bind_image(0); } label_.image = img; } void Fl_Widget::image(Fl_Image& img) { image(&img); } void Fl_Widget::bind_image(Fl_Image* img) { image(img); bind_image( (img != NULL) ); } void Fl_Widget::deimage(Fl_Image* img) { if (deimage_bound()) { if (label_.deimage && (label_.deimage != img)) { label_.deimage->release(); } bind_deimage(0); } label_.deimage = img; } void Fl_Widget::deimage(Fl_Image& img) { deimage(&img); } void Fl_Widget::bind_deimage(Fl_Image* img) { deimage(img); bind_deimage( (img != NULL) ); } /** Calls the widget callback function with arbitrary arguments. All overloads of do_callback() call this method. It does nothing if the widget's callback() is NULL. It clears the widget's \e changed flag \b after the callback was called unless the callback is the default callback. Hence it is not necessary to call clear_changed() after calling do_callback() in your own widget's handle() method. A \p reason must be set for widgets if different actions can trigger the same callback. \note It is legal to delete the widget in the callback (i.e. in user code), but you must not access the widget in the handle() method after calling do_callback() if the widget was deleted in the callback. We recommend to use Fl_Widget_Tracker to check whether the widget was deleted in the callback. \param[in] widget call the callback with \p widget as the first argument \param[in] arg use \p arg as the user data (second) argument \param[in] reason give a reason to why this callback was called, defaults to \ref FL_REASON_UNKNOWN \see default_callback() \see callback() \see class Fl_Widget_Tracker \see Fl::callback_reason() */ void Fl_Widget::do_callback(Fl_Widget *widget, void *arg, Fl_Callback_Reason reason) { Fl::callback_reason_ = reason; if (!callback_) return; Fl_Widget_Tracker wp(this); callback_(widget, arg); if (wp.deleted()) return; if (callback_ != default_callback) clear_changed(); } /* \brief Sets the user data for this widget. Sets the new user data (void *) argument that is passed to the callback function. \param[in] v new user data */ void Fl_Widget::user_data(void* v) { if ((flags_ & AUTO_DELETE_USER_DATA) && user_data_) delete (Fl_Callback_User_Data*)user_data_; clear_flag(AUTO_DELETE_USER_DATA); user_data_ = v; } /* \brief Sets the user data for this widget. Sets the new user data (void *) argument that is passed to the callback function. \param[in] v new user data \param[in] auto_free if set, the widget will free user data when destroyed; defaults to false */ void Fl_Widget::user_data(Fl_Callback_User_Data* v, bool auto_free) { user_data((void*)v); if (auto_free) set_flag(AUTO_DELETE_USER_DATA); } fltk-1.4.3/src/Fl_Browser_load.cxx0000644000175000017500000000303215004135251017161 0ustar albrechtalbrecht// // File loading routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include /** Clears the browser and reads the file, adding each line from the file to the browser. If the filename is NULL or a zero-length string then this just clears the browser. This returns zero if there was any error in opening or reading the file, in which case errno is set to the system error. The data() of each line is set to NULL. \param[in] filename The filename to load \returns 1 if OK, 0 on error (errno has reason) \see add() */ int Fl_Browser::load(const char *filename) { #define MAXFL_BLINE 1024 char newtext[MAXFL_BLINE]; int c; int i; clear(); if (!filename || !(filename[0])) return 1; FILE *fl = fl_fopen(filename,"r"); if (!fl) return 0; i = 0; do { c = getc(fl); if (c == '\n' || c <= 0 || i>=(MAXFL_BLINE-1)) { newtext[i] = 0; add(newtext); i = 0; } else { newtext[i++] = c; } } while (c >= 0); fclose(fl); return 1; } fltk-1.4.3/src/Fl_Native_File_Chooser_GTK.cxx0000644000175000017500000011514715004135251021126 0ustar albrechtalbrecht// // FLTK native file chooser widget wrapper for GTK's GtkFileChooserDialog // // Copyright 1998-2023 by Bill Spitzak and others. // Copyright 2012 IMM // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "Fl_Native_File_Chooser_Zenity.H" #include "Fl_Native_File_Chooser_Kdialog.H" #if HAVE_DLSYM && HAVE_DLFCN_H #include #include #include #include #include #include // for dlopen et al #include "drivers/Posix/Fl_Posix_System_Driver.H" #include "drivers/Unix/Fl_Unix_Screen_Driver.H" #include "Fl_Window_Driver.H" #include "Fl_Screen_Driver.H" /* --------------------- Type definitions from GLIB and GTK --------------------- */ /* all of this is from the public gnome API, so unlikely to change */ #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif typedef void* gpointer; typedef int gint; typedef unsigned int guint; typedef unsigned long gulong; typedef gint gboolean; typedef char gchar; typedef struct _GSList GSList; struct _GSList { gpointer data; GSList *next; }; #define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL) typedef struct _GtkWidget GtkWidget; typedef struct _GtkFileChooser GtkFileChooser; typedef struct _GtkDialog GtkDialog; typedef struct _GtkWindow GtkWindow; typedef struct _GtkFileFilter GtkFileFilter; typedef struct _GtkToggleButton GtkToggleButton; typedef struct _GdkPixbuf GdkPixbuf; typedef struct _GtkImage GtkImage; typedef struct _GtkTable GtkTable; typedef enum { GTK_FILE_FILTER_FILENAME = 1 << 0, GTK_FILE_FILTER_URI = 1 << 1, GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2, GTK_FILE_FILTER_MIME_TYPE = 1 << 3 } GtkFileFilterFlags; struct _GtkFileFilterInfo { GtkFileFilterFlags contains; const gchar *filename; const gchar *uri; const gchar *display_name; const gchar *mime_type; }; typedef struct _GtkFileFilterInfo GtkFileFilterInfo; typedef gboolean (*GtkFileFilterFunc) (const GtkFileFilterInfo *filter_info, gpointer data); typedef void (*GDestroyNotify)(gpointer data); typedef enum { GTK_FILE_CHOOSER_ACTION_OPEN, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER } GtkFileChooserAction; #define GTK_STOCK_CANCEL "gtk-cancel" #define GTK_STOCK_SAVE "gtk-save" #define GTK_STOCK_OPEN "gtk-open" const int GTK_RESPONSE_NONE = -1; const int GTK_RESPONSE_ACCEPT = -3; const int GTK_RESPONSE_DELETE_EVENT = -4; const int GTK_RESPONSE_CANCEL = -6; typedef void (*GCallback)(void); #define G_CALLBACK(f) ((GCallback) (f)) typedef int GConnectFlags; typedef struct _GClosure GClosure; typedef void (*GClosureNotify)(gpointer data, GClosure *closure); /* --------------------- End of Type definitions from GLIB and GTK --------------------- */ class Fl_GTK_Native_File_Chooser_Driver : public Fl_Native_File_Chooser_FLTK_Driver { friend class Fl_Native_File_Chooser; private: static int have_looked_for_GTK_libs; typedef struct _GtkFileFilterInfo GtkFileFilterInfo; struct pair { Fl_GTK_Native_File_Chooser_Driver* running; // the running Fl_GTK_File_Chooser const char *filter; // a filter string of the chooser pair(Fl_GTK_Native_File_Chooser_Driver* c, const char *f) { running = c; filter = fl_strdup(f); } ~pair() { free((char*)filter); } }; GtkWidget *gtkw_ptr; // used to hold a GtkWidget* without pulling GTK into everything... void *gtkw_slist; // used to hold a GLib GSList... unsigned gtkw_count; // number of files read back - if any mutable char *gtkw_filename; // last name we read back char *gtkw_title; // the title to be applied to the dialog const char *previous_filter; int fl_gtk_chooser_wrapper(); // method that wraps the GTK widget Fl_GTK_Native_File_Chooser_Driver(int val); ~Fl_GTK_Native_File_Chooser_Driver() FL_OVERRIDE; static int did_find_GTK_libs; static void probe_for_GTK_libs(void); void type(int) FL_OVERRIDE; int count() const FL_OVERRIDE; const char *filename() const FL_OVERRIDE; const char *filename(int i) const FL_OVERRIDE; void title(const char *) FL_OVERRIDE; const char* title() const FL_OVERRIDE; int show() FL_OVERRIDE; void changed_output_type(const char *filter); static int custom_gtk_filter_function(const GtkFileFilterInfo*, Fl_GTK_Native_File_Chooser_Driver::pair*); static void free_pair(pair *p); Fl_Preferences gtk_chooser_prefs; public: static gboolean want_preview; // state of "Preview" button }; gboolean Fl_GTK_Native_File_Chooser_Driver::want_preview = false; int Fl_GTK_Native_File_Chooser_Driver::did_find_GTK_libs = 0; /* These are the GTK/GLib methods we want to load, but not call by name...! */ // void g_free (gpointer mem); typedef void (*XX_g_free)(gpointer); static XX_g_free fl_g_free = NULL; // gpointer g_slist_nth_data (GSList *list, guint n); typedef gpointer (*XX_g_slist_nth_data) (GSList *, guint); static XX_g_slist_nth_data fl_g_slist_nth_data = NULL; // guint g_slist_length (GSList *list); typedef guint (*XX_g_slist_length) (GSList *); static XX_g_slist_length fl_g_slist_length = NULL; // void g_slist_free (GSList *list); typedef void (*XX_g_slist_free) (GSList *); static XX_g_slist_free fl_g_slist_free = NULL; // void gtk_widget_destroy (GtkWidget *widget); typedef void (*XX_gtk_widget_destroy) (GtkWidget *); static XX_gtk_widget_destroy fl_gtk_widget_destroy = NULL; // void gtk_file_chooser_set_select_multiple(GtkFileChooser *chooser, gboolean select_multiple); typedef void (*XX_gtk_file_chooser_set_select_multiple)(GtkFileChooser *, gboolean); static XX_gtk_file_chooser_set_select_multiple fl_gtk_file_chooser_set_select_multiple = NULL; // void gtk_file_chooser_set_do_overwrite_confirmation(GtkFileChooser *chooser, gboolean do_overwrite_confirmation); typedef void (*XX_gtk_file_chooser_set_do_overwrite_confirmation)(GtkFileChooser *, gboolean); static XX_gtk_file_chooser_set_do_overwrite_confirmation fl_gtk_file_chooser_set_do_overwrite_confirmation = NULL; // void gtk_file_chooser_set_current_name (GtkFileChooser *chooser, const gchar *name); typedef void (*XX_gtk_file_chooser_set_current_name)(GtkFileChooser *, const gchar *); static XX_gtk_file_chooser_set_current_name fl_gtk_file_chooser_set_current_name = NULL; // void gtk_file_chooser_set_current_folder (GtkFileChooser *chooser, const gchar *name); typedef void (*XX_gtk_file_chooser_set_current_folder)(GtkFileChooser *, const gchar *); static XX_gtk_file_chooser_set_current_folder fl_gtk_file_chooser_set_current_folder = NULL; // void gtk_file_chooser_set_create_folders (GtkFileChooser *chooser, gboolean create_folders); typedef void (*XX_gtk_file_chooser_set_create_folders) (GtkFileChooser *, gboolean); static XX_gtk_file_chooser_set_create_folders fl_gtk_file_chooser_set_create_folders = NULL; // gboolean gtk_file_chooser_get_select_multiple(GtkFileChooser *chooser); typedef gboolean (*XX_gtk_file_chooser_get_select_multiple)(GtkFileChooser *); static XX_gtk_file_chooser_get_select_multiple fl_gtk_file_chooser_get_select_multiple = NULL; // void gtk_widget_hide(GtkWidget *widget); typedef void (*XX_gtk_widget_hide)(GtkWidget *); static XX_gtk_widget_hide fl_gtk_widget_hide = NULL; // gchar * gtk_file_chooser_get_filename(GtkFileChooser *chooser); typedef gchar* (*XX_gtk_file_chooser_get_filename)(GtkFileChooser *); static XX_gtk_file_chooser_get_filename fl_gtk_file_chooser_get_filename = NULL; // GSList * gtk_file_chooser_get_filenames(GtkFileChooser *chooser); typedef GSList* (*XX_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); static XX_gtk_file_chooser_get_filenames fl_gtk_file_chooser_get_filenames = NULL; // gboolean gtk_main_iteration(void); typedef gboolean (*XX_gtk_main_iteration)(void); static XX_gtk_main_iteration fl_gtk_main_iteration = NULL; // gboolean gtk_events_pending(void); typedef gboolean (*XX_gtk_events_pending)(void); static XX_gtk_events_pending fl_gtk_events_pending = NULL; // GtkWidget * gtk_file_chooser_dialog_new(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...); typedef GtkWidget* (*XX_gtk_file_chooser_dialog_new)(const gchar *, GtkWindow *, GtkFileChooserAction, const gchar *, ...); static XX_gtk_file_chooser_dialog_new fl_gtk_file_chooser_dialog_new = NULL; // void gtk_file_chooser_add_filter(GtkFileChooser*, GtkFileFilter*); typedef void (*XX_gtk_file_chooser_add_filter)(GtkFileChooser*, GtkFileFilter*); static XX_gtk_file_chooser_add_filter fl_gtk_file_chooser_add_filter = NULL; // GtkFileFilter* gtk_file_chooser_get_filter(GtkFileChooser*); typedef GtkFileFilter* (*XX_gtk_file_chooser_get_filter)(GtkFileChooser*); static XX_gtk_file_chooser_get_filter fl_gtk_file_chooser_get_filter = NULL; // void gtk_file_chooser_set_filter(GtkFileChooser*, GtkFileFilter*); typedef void (*XX_gtk_file_chooser_set_filter)(GtkFileChooser*, GtkFileFilter*); static XX_gtk_file_chooser_set_filter fl_gtk_file_chooser_set_filter = NULL; // GtkFileFilter * gtk_file_filter_new(); typedef GtkFileFilter* (*XX_gtk_file_filter_new)(void); static XX_gtk_file_filter_new fl_gtk_file_filter_new = NULL; // void gtk_file_filter_add_pattern(GtkFileFilter*, const gchar*); typedef void (*XX_gtk_file_filter_add_pattern)(GtkFileFilter*, const gchar*); static XX_gtk_file_filter_add_pattern fl_gtk_file_filter_add_pattern = NULL; // void gtk_file_filter_add_custom(GtkFileFilter *filter, GtkFileFilterFlags needed, // GtkFileFilterFunc func, gpointer data, GDestroyNotify notify); typedef void (*XX_gtk_file_filter_add_custom)(GtkFileFilter *filter, GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, GDestroyNotify notify); static XX_gtk_file_filter_add_custom fl_gtk_file_filter_add_custom = NULL; // void gtk_file_filter_set_name(GtkFileFilter*, const gchar*); typedef void (*XX_gtk_file_filter_set_name)(GtkFileFilter*, const gchar*); static XX_gtk_file_filter_set_name fl_gtk_file_filter_set_name = NULL; // const gchar* gtk_file_filter_get_name(GtkFileFilter*); typedef const gchar* (*XX_gtk_file_filter_get_name)(GtkFileFilter*); static XX_gtk_file_filter_get_name fl_gtk_file_filter_get_name = NULL; // void gtk_file_chooser_set_extra_widget(GtkFileChooser *, GtkWidget *); typedef void (*XX_gtk_file_chooser_set_extra_widget)(GtkFileChooser *, GtkWidget *); static XX_gtk_file_chooser_set_extra_widget fl_gtk_file_chooser_set_extra_widget = NULL; // void gtk_widget_show_now(GtkWidget *); typedef void (*XX_gtk_widget_show_now)(GtkWidget *); static XX_gtk_widget_show_now fl_gtk_widget_show_now = NULL; // GtkWidget *gtk_check_button_new_with_label(const gchar *); typedef GtkWidget* (*XX_gtk_check_button_new_with_label)(const gchar *); static XX_gtk_check_button_new_with_label fl_gtk_check_button_new_with_label = NULL; // gulong g_signal_connect_data(gpointer, const gchar *, GCallback, gpointer, GClosureNotify, GConnectFlags); typedef gulong (*XX_g_signal_connect_data)(gpointer, const gchar *, GCallback, gpointer, GClosureNotify, GConnectFlags); static XX_g_signal_connect_data fl_g_signal_connect_data = NULL; // gboolean gtk_toggle_button_get_active(GtkToggleButton *); typedef gboolean (*XX_gtk_toggle_button_get_active)(GtkToggleButton*); static XX_gtk_toggle_button_get_active fl_gtk_toggle_button_get_active = NULL; // void gtk_file_chooser_set_show_hidden(GtkFileChooser *, gboolean); typedef void (*XX_gtk_file_chooser_set_show_hidden)(GtkFileChooser *, gboolean); static XX_gtk_file_chooser_set_show_hidden fl_gtk_file_chooser_set_show_hidden = NULL; // gboolean gtk_file_chooser_get_show_hidden(GtkFileChooser *); typedef gboolean (*XX_gtk_file_chooser_get_show_hidden)(GtkFileChooser *); static XX_gtk_file_chooser_get_show_hidden fl_gtk_file_chooser_get_show_hidden = NULL; // void gtk_toggle_button_set_active(GtkToggleButton *, gboolean); typedef void (*XX_gtk_toggle_button_set_active)(GtkToggleButton *, gboolean); static XX_gtk_toggle_button_set_active fl_gtk_toggle_button_set_active = NULL; // GtkWidget *gtk_check_button_new_with_label(const gchar *); typedef GtkWidget* (*XX_gtk_file_chooser_set_preview_widget_active)(GtkFileChooser*, gboolean); static XX_gtk_file_chooser_set_preview_widget_active fl_gtk_file_chooser_set_preview_widget_active = NULL; // GdkPixbuf* gtk_file_chooser_set_preview_widget(GtkFileChooser *, GtkWidget *); typedef GdkPixbuf* (*XX_gtk_file_chooser_set_preview_widget) (GtkFileChooser *gtkw_ptr, GtkWidget *preview); static XX_gtk_file_chooser_set_preview_widget fl_gtk_file_chooser_set_preview_widget = NULL; // char *gtk_file_chooser_get_preview_filename(GtkFileChooser*); // 2.4 typedef char* (*XX_gtk_file_chooser_get_preview_filename) (GtkFileChooser*); static XX_gtk_file_chooser_get_preview_filename fl_gtk_file_chooser_get_preview_filename = NULL; // GdkPixbuf *gdk_pixbuf_new_from_data(const uchar *,GdkColorspace, gboolean, int, int, int, int, void*, void*); typedef GdkPixbuf* (*XX_gdk_pixbuf_new_from_data)(const uchar *, int/*GdkColorspace*/, gboolean, int, int, int, int, void*, void*); static XX_gdk_pixbuf_new_from_data fl_gdk_pixbuf_new_from_data = NULL; // void gtk_image_set_from_pixbuf(GtkImage*, GdkPixbuf*); typedef GdkPixbuf* (*XX_gtk_image_set_from_pixbuf) (GtkImage*, GdkPixbuf*); static XX_gtk_image_set_from_pixbuf fl_gtk_image_set_from_pixbuf = NULL; // GtkWidget *gtk_image_new(); typedef GtkWidget* (*XX_gtk_image_new)(void); static XX_gtk_image_new fl_gtk_image_new = NULL; // GtkWidget *gtk_table_new(); typedef GtkTable* (*XX_gtk_table_new)(int, int, gboolean); static XX_gtk_table_new fl_gtk_table_new = NULL; // GtkWidget *gtk_table_new(); typedef void (*XX_gtk_widget_show_all)(GtkWidget*); static XX_gtk_widget_show_all fl_gtk_widget_show_all = NULL; // void gtk_table_attach_defaults() typedef void (*XX_gtk_table_attach_defaults)(GtkTable *, GtkWidget *, guint left_attach, guint right_attach, guint top_attach, guint bottom_attach); static XX_gtk_table_attach_defaults fl_gtk_table_attach_defaults = NULL; // GtkImage *gtk_file_chooser_get_preview_widget(GtkFileChooser*); typedef GtkImage*(*XX_gtk_file_chooser_get_preview_widget)(GtkFileChooser*); static XX_gtk_file_chooser_get_preview_widget fl_gtk_file_chooser_get_preview_widget = NULL; typedef void (*XX_gtk_widget_set_sensitive)(GtkWidget *, gboolean); static XX_gtk_widget_set_sensitive fl_gtk_widget_set_sensitive = NULL; typedef GtkWidget *(*XX_gtk_button_new_with_label)(const char*); XX_gtk_button_new_with_label fl_gtk_button_new_with_label = NULL; typedef GtkWidget *(*XX_gtk_widget_get_toplevel)(GtkWidget *); static XX_gtk_widget_get_toplevel fl_gtk_widget_get_toplevel = NULL; // void g_object_unref(gpointer); typedef void (*XX_g_object_unref)(void*); static XX_g_object_unref fl_g_object_unref = NULL; int Fl_GTK_Native_File_Chooser_Driver::have_looked_for_GTK_libs = 0; Fl_GTK_Native_File_Chooser_Driver::Fl_GTK_Native_File_Chooser_Driver(int val) : Fl_Native_File_Chooser_FLTK_Driver(-1), gtk_chooser_prefs(Fl_Preferences::USER, "fltk.org", "fltk/GTK-file-chooser") { gtkw_ptr = NULL; // used to hold a GtkWidget* gtkw_slist = NULL; // will hold the returned file names in a multi-selection... gtkw_count = 0; // How many items were selected? gtkw_filename = NULL; // holds the last name we read back in a single file selection... gtkw_title = NULL; // dialog title _btype = val; previous_filter = NULL; if (options() & Fl_Native_File_Chooser::PREVIEW) want_preview = true; else gtk_chooser_prefs.get("Preview", want_preview, 0); } Fl_GTK_Native_File_Chooser_Driver::~Fl_GTK_Native_File_Chooser_Driver() { // Should free up resources taken for... if(gtkw_ptr) { fl_gtk_widget_destroy (gtkw_ptr); gtkw_ptr = NULL; } if(gtkw_filename) { fl_g_free(gtkw_filename); gtkw_filename = NULL; } if(gtkw_slist) { GSList *iter = (GSList *)gtkw_slist; while(iter) { if(iter->data) fl_g_free(iter->data); iter = g_slist_next(iter); } fl_g_slist_free((GSList *)gtkw_slist); gtkw_slist = NULL; } gtkw_count = 0; // assume we have no files selected now gtkw_title = strfree(gtkw_title); if (!(options() & Fl_Native_File_Chooser::PREVIEW)) gtk_chooser_prefs.set("Preview", want_preview); } void Fl_GTK_Native_File_Chooser_Driver::type(int val) { _btype = val; } int Fl_GTK_Native_File_Chooser_Driver::count() const { return gtkw_count; } const char *Fl_GTK_Native_File_Chooser_Driver::filename() const { if(gtkw_ptr) { if(fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { return gtkw_filename; } else { GSList *iter = (GSList *)gtkw_slist; char *nm = (char *)iter->data; return nm; } } return(""); } const char *Fl_GTK_Native_File_Chooser_Driver::filename(int i) const { if(fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { return gtkw_filename; } else { if ((unsigned)i < gtkw_count) { GSList *iter = (GSList *)gtkw_slist; char *nm = (char *)fl_g_slist_nth_data(iter, i); return nm; } } return(""); } void Fl_GTK_Native_File_Chooser_Driver::title(const char *val) { strfree(gtkw_title); gtkw_title = strnew(val); } const char* Fl_GTK_Native_File_Chooser_Driver::title() const { return gtkw_title; } /* changes the extension of the outfile in the chooser according to newly selected filter */ void Fl_GTK_Native_File_Chooser_Driver::changed_output_type(const char *filter) { if ( !(options()&Fl_Native_File_Chooser::USE_FILTER_EXT) ) return; if (strchr(filter, '(') || strchr(filter, '{') || strchr(filter+1, '*') || strncmp(filter, "*.", 2)) return; const char *p = fl_gtk_file_chooser_get_filename((GtkFileChooser*)gtkw_ptr); if (!p) return; p = fl_filename_name(p); const char *q = strrchr(p, '.'); if (!q) q = p + strlen(p); char *r = new char[strlen(p) + strlen(filter)]; strcpy(r, p); strcpy(r + (q - p), filter + 1); fl_gtk_file_chooser_set_current_name((GtkFileChooser*)gtkw_ptr, r); delete[] r; } /* Filters files before display in chooser. Also used to detect when the filter just changed */ gboolean Fl_GTK_Native_File_Chooser_Driver::custom_gtk_filter_function(const GtkFileFilterInfo *info, Fl_GTK_Native_File_Chooser_Driver::pair* p) { if (p->running->previous_filter != p->filter) { p->running->changed_output_type(p->filter); p->running->previous_filter = p->filter; } return (gboolean)fl_filename_match(fl_filename_name(info->filename), p->filter); } void Fl_GTK_Native_File_Chooser_Driver::free_pair(Fl_GTK_Native_File_Chooser_Driver::pair *p) { delete p; } static void hidden_files_cb(GtkToggleButton *togglebutton, gpointer user_data) { gboolean state = fl_gtk_toggle_button_get_active(togglebutton); fl_gtk_file_chooser_set_show_hidden((GtkFileChooser*)user_data, state); } int Fl_GTK_Native_File_Chooser_Driver::show() { return fl_gtk_chooser_wrapper(); } static char *extract_dir_from_path(const char *path) { static char *dir = NULL; if (fl_filename_isdir(path)) { return (char*)path; } if (*path != '/') return NULL; if (dir) free(dir); dir = fl_strdup(path); do { char *p = strrchr(dir, '/'); if (p == dir) p++; *p = 0; } while (!fl_filename_isdir(dir)); return dir; } static void run_response_handler(GtkDialog *dialog, gint response_id, gpointer data) { gint *ri = (gint *)data; *ri = response_id; } // checks whether the file begins with up to 1000 UTF-8-encoded unicode characters // if yes, those characters are returned as a UTF-8 string (to be delete[]'d after use) // if no, NULL is returned static char *text_file_preview(const char *fname) { if (!strcmp(fl_filename_ext(fname), ".svg")) return NULL; if (!strcmp(fl_filename_ext(fname), ".xpm")) return NULL; FILE *in = fl_fopen(fname, "r"); if (!in) return NULL; char *text = new char[4011]; int len = fread(text, 1, 4010, in); fclose(in); text[len] = 0; if ((int)strlen(text) < len) text[0] = 0; // presence of null byte in file --> not text char *p = text; int count = 0; const char *end = text + strlen(text); while (p < end && count < 1000) { if (*p & 0x80) { // what should be a multibyte encoding fl_utf8decode(p, end, &len); if (len < 2) { // That's not genuine UTF-8 delete[] text; return NULL; } } else { len = 1; } p += len; count++; } *p = 0; if (text[0]==0) {delete[] text; text = NULL;} return text; } static void delete_rgb_image(uchar *pixels, Fl_RGB_Image *rgb) { delete rgb; } // Draws to an Fl_RGB_Image a preview of text and image files, // and uses it to fill the "preview" part of the GTK file chooser //static int preview_width = 175; static float preview_zoom = 1.; static GtkWidget *plus_button, *minus_button; static void update_preview_cb(GtkFileChooser *file_chooser, GtkImage* gtkimg) { gboolean have_preview = false; Fl_Shared_Image *img = NULL; char *preview_text = NULL; char *filename = NULL; fl_gtk_widget_set_sensitive(plus_button, false); fl_gtk_widget_set_sensitive(minus_button, false); if (Fl_GTK_Native_File_Chooser_Driver::want_preview) filename = fl_gtk_file_chooser_get_preview_filename(file_chooser); // 2.4 if (filename) { if (!fl_filename_isdir(filename)) { preview_text = text_file_preview(filename); if (!preview_text) { img = Fl_Shared_Image::get(filename); } } free(filename); } if (preview_text || (img && !img->fail())) { int width = preview_zoom * 175, height = preview_zoom * 225; // same size as Fl_File_Chooser's preview box if (preview_text) height = 225; if (img) { img->scale(width, height); width = img->w(), height = img->h(); } Fl_Image_Surface *surf = new Fl_Image_Surface(width, height); Fl_Surface_Device::push_current(surf); fl_color(FL_WHITE); fl_rectf(0, 0, width, height); if (img) img->draw(0, 0); else { fl_color(FL_BLACK); fl_font(FL_COURIER, FL_NORMAL_SIZE - 1); fl_draw(preview_text, 0, 0, width, height, FL_ALIGN_TOP|FL_ALIGN_LEFT, NULL, false); delete[] preview_text; } Fl_RGB_Image *rgb = surf->image(); Fl_Surface_Device::pop_current(); delete surf; GdkPixbuf *pixbuf = fl_gdk_pixbuf_new_from_data(rgb->array, 0/*GDK_COLORSPACE_RGB*/, rgb->d() == 4, 8, rgb->data_w(), rgb->data_h(), rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d(), (void*)&delete_rgb_image, rgb); if (pixbuf) { fl_gtk_image_set_from_pixbuf(gtkimg, pixbuf); fl_g_object_unref(pixbuf); if (preview_zoom < 4) fl_gtk_widget_set_sensitive(plus_button, true); if (preview_zoom > 1) fl_gtk_widget_set_sensitive(minus_button, true); have_preview = true; } } if (img) img->release(); fl_gtk_file_chooser_set_preview_widget_active(file_chooser, have_preview); //2.4 } static void preview_cb(GtkToggleButton *togglebutton, GtkFileChooser *chooser) { Fl_GTK_Native_File_Chooser_Driver::want_preview = fl_gtk_toggle_button_get_active(togglebutton); GtkImage *preview = fl_gtk_file_chooser_get_preview_widget(chooser); update_preview_cb(chooser, preview); } static void plus_cb(GtkWidget *togglebutton, GtkImage *preview) { preview_zoom *= 1.5; if (preview_zoom > 4) { preview_zoom = 4; } update_preview_cb((GtkFileChooser*)fl_gtk_widget_get_toplevel(togglebutton), preview); } static void minus_cb(GtkWidget *togglebutton, GtkImage *preview) { preview_zoom /= 1.5; if (preview_zoom < 1) { preview_zoom = 1; } update_preview_cb((GtkFileChooser*)fl_gtk_widget_get_toplevel(togglebutton), preview); } static int fnfc_dispatch(int /*event*/, Fl_Window* /*win*/) { return 0; } int Fl_GTK_Native_File_Chooser_Driver::fl_gtk_chooser_wrapper() { int result = 1; char *p; if(gtkw_ptr) { // discard the previous dialog widget fl_gtk_widget_destroy (gtkw_ptr); gtkw_ptr = NULL; } // set the dialog action type GtkFileChooserAction gtw_action_type; switch (_btype) { case Fl_Native_File_Chooser::BROWSE_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: gtw_action_type = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; break; case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: gtw_action_type = GTK_FILE_CHOOSER_ACTION_SAVE; break; case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: gtw_action_type = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER; break; case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: case Fl_Native_File_Chooser::BROWSE_FILE: default: gtw_action_type = GTK_FILE_CHOOSER_ACTION_OPEN; break; } // create a new dialog gtkw_ptr = fl_gtk_file_chooser_dialog_new (gtkw_title, NULL, /* parent_window */ gtw_action_type, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, gtw_action_type == GTK_FILE_CHOOSER_ACTION_SAVE || gtw_action_type == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); // did we create a valid dialog widget? if(!gtkw_ptr) { // fail return -1; } // set the dialog properties switch (_btype) { case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: fl_gtk_file_chooser_set_select_multiple((GtkFileChooser *)gtkw_ptr, TRUE); break; case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: if (_preset_file)fl_gtk_file_chooser_set_current_name ((GtkFileChooser *)gtkw_ptr, fl_filename_name(_preset_file)); /* FALLTHROUGH */ case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: fl_gtk_file_chooser_set_create_folders((GtkFileChooser *)gtkw_ptr, TRUE); fl_gtk_file_chooser_set_do_overwrite_confirmation ((GtkFileChooser *)gtkw_ptr, (_options & Fl_Native_File_Chooser::SAVEAS_CONFIRM)?TRUE:FALSE); break; case Fl_Native_File_Chooser::BROWSE_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_FILE: default: break; } if (_directory && _directory[0]) { p = extract_dir_from_path(_directory); if (p) fl_gtk_file_chooser_set_current_folder((GtkFileChooser *)gtkw_ptr, p); } else if (_preset_file) { p = extract_dir_from_path(_preset_file); if (p) fl_gtk_file_chooser_set_current_folder((GtkFileChooser *)gtkw_ptr, p); } GtkFileFilter **filter_tab = NULL; if (_parsedfilt) { filter_tab = new GtkFileFilter*[_nfilters]; char *filter = fl_strdup(_parsedfilt); p = strtok(filter, "\t"); int count = 0; while (p) { filter_tab[count] = fl_gtk_file_filter_new(); fl_gtk_file_filter_set_name(filter_tab[count], p); p = strchr(p, '(') + 1; char *q = strchr(p, ')'); *q = 0; fl_gtk_file_filter_add_custom(filter_tab[count], GTK_FILE_FILTER_FILENAME, (GtkFileFilterFunc)Fl_GTK_Native_File_Chooser_Driver::custom_gtk_filter_function, new Fl_GTK_Native_File_Chooser_Driver::pair(this, p), (GDestroyNotify)Fl_GTK_Native_File_Chooser_Driver::free_pair); fl_gtk_file_chooser_add_filter((GtkFileChooser *)gtkw_ptr, filter_tab[count]); p = strtok(NULL, "\t"); count++; } free(filter); fl_gtk_file_chooser_set_filter((GtkFileChooser *)gtkw_ptr, filter_tab[_filtvalue < _nfilters?_filtvalue:0]); previous_filter = NULL; if (gtw_action_type == GTK_FILE_CHOOSER_ACTION_OPEN) { GtkFileFilter* gfilter = fl_gtk_file_filter_new(); fl_gtk_file_filter_set_name(gfilter, Fl_File_Chooser::all_files_label); fl_gtk_file_filter_add_pattern(gfilter, "*"); fl_gtk_file_chooser_add_filter((GtkFileChooser *)gtkw_ptr, gfilter); } } // extra buttons "Show hidden" [+ "Preview" before it if fl_register_images() was called] GtkWidget *show_hidden_button = fl_gtk_check_button_new_with_label(Fl_File_Chooser::hidden_label); fl_g_signal_connect_data(show_hidden_button, "toggled", G_CALLBACK(hidden_files_cb), gtkw_ptr, NULL, (GConnectFlags) 0); GtkWidget *extra = show_hidden_button; if (Fl_Image::register_images_done) { GtkTable *table = fl_gtk_table_new(1, 4, true); GtkWidget *preview = fl_gtk_image_new(); fl_gtk_file_chooser_set_preview_widget((GtkFileChooser *)gtkw_ptr, preview); //2.4 fl_g_signal_connect_data((GtkFileChooser *)gtkw_ptr, "update-preview", G_CALLBACK(update_preview_cb), preview, NULL, (GConnectFlags)0); GtkWidget *preview_button = fl_gtk_check_button_new_with_label(Fl_File_Chooser::preview_label); fl_gtk_toggle_button_set_active((GtkToggleButton *)preview_button, want_preview); fl_g_signal_connect_data(preview_button, "toggled", G_CALLBACK(preview_cb), gtkw_ptr, NULL, (GConnectFlags) 0); fl_gtk_table_attach_defaults(table, preview_button, 0, 1, 0, 1); plus_button = fl_gtk_button_new_with_label("<--->"); fl_g_signal_connect_data(plus_button, "clicked", G_CALLBACK(plus_cb), preview, NULL, (GConnectFlags) 0); fl_gtk_table_attach_defaults(table, plus_button, 1,2, 0, 1); minus_button = fl_gtk_button_new_with_label(">---<"); fl_g_signal_connect_data(minus_button, "clicked", G_CALLBACK(minus_cb), preview, NULL, (GConnectFlags) 0); fl_gtk_table_attach_defaults(table, minus_button, 2,3, 0, 1); fl_gtk_table_attach_defaults(table, show_hidden_button, 3, 4, 0, 1); extra = (GtkWidget*)table; } fl_gtk_file_chooser_set_extra_widget((GtkFileChooser *)gtkw_ptr, extra); fl_gtk_widget_show_all(extra); fl_gtk_widget_show_now(gtkw_ptr); // map the GTK window on screen gboolean state = fl_gtk_file_chooser_get_show_hidden((GtkFileChooser *)gtkw_ptr); fl_gtk_toggle_button_set_active((GtkToggleButton *)show_hidden_button, state); Fl_Event_Dispatch old_dispatch = Fl::event_dispatch(); // prevent FLTK from processing any event Fl::event_dispatch(fnfc_dispatch); void *control = ((Fl_Unix_Screen_Driver*)Fl::screen_driver())->control_maximize_button(NULL); gint response_id = GTK_RESPONSE_NONE; fl_g_signal_connect_data(gtkw_ptr, "response", G_CALLBACK(run_response_handler), &response_id, NULL, (GConnectFlags) 0); while (response_id == GTK_RESPONSE_NONE) { // loop that shows the GTK dialog window fl_gtk_main_iteration(); // one iteration of the GTK event loop while (Fl::ready()) Fl::check(); // queued iterations of the FLTK event loop } if (response_id == GTK_RESPONSE_ACCEPT) { if (_parsedfilt) { GtkFileFilter *gfilter = fl_gtk_file_chooser_get_filter((GtkFileChooser *)gtkw_ptr); for (_filtvalue = 0; _filtvalue < _nfilters; _filtvalue++) { if (filter_tab[_filtvalue] == gfilter) break; } } // discard any filenames or lists from previous calls if(gtkw_filename) { fl_g_free(gtkw_filename); gtkw_filename = NULL; } if(gtkw_slist) { GSList *iter = (GSList *)gtkw_slist; while(iter) { if(iter->data) fl_g_free(iter->data); iter = g_slist_next(iter); } fl_g_slist_free((GSList *)gtkw_slist); gtkw_slist = NULL; } gtkw_count = 0; // assume we have no files selected now if(fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { gtkw_filename = fl_gtk_file_chooser_get_filename ((GtkFileChooser *)gtkw_ptr); if (gtkw_filename) { gtkw_count = 1; result = 0; //printf("single: %s\n", gtkw_filename); } } else { gtkw_slist = fl_gtk_file_chooser_get_filenames((GtkFileChooser *)gtkw_ptr); gtkw_count = fl_g_slist_length((GSList *)gtkw_slist); if(gtkw_count) result = 0; // puts("multiple"); // GSList *iter = (GSList *)gtkw_slist; // printf ("Selected %d files\n", gtkw_count); // while(iter) { // char *nm = (char *)iter->data; // printf("%s\n", nm); // iter = g_slist_next(iter); // } } } delete[] filter_tab; if ( response_id == GTK_RESPONSE_DELETE_EVENT) gtkw_ptr = NULL; else fl_gtk_widget_hide (gtkw_ptr); // I think this is analogous to doing an Fl::check() - we need this here to make sure // the GtkFileChooserDialog is removed from the display correctly while (fl_gtk_events_pending ()) fl_gtk_main_iteration (); Fl::event_dispatch(old_dispatch); if (control) ((Fl_Unix_Screen_Driver*)Fl::screen_driver())->control_maximize_button(control); return result; } // fl_gtk_chooser_wrapper // macro to help with the symbol loading boilerplate... # define GET_SYM(SSS, LLL) \ dlerror(); /* Clear any existing error */ \ fl_##SSS = (XX_##SSS)dlsym(LLL, #SSS); \ if ((pc_dl_error = dlerror()) != NULL) { \ fprintf(stderr, "%s\n", pc_dl_error); \ did_find_GTK_libs = 0; \ return; } /* * Use dlopen to see if we can load the gtk dynamic libraries that * will allow us to create a GtkFileChooserDialog() on the fly, * without linking to the GTK libs at compile time. */ void Fl_GTK_Native_File_Chooser_Driver::probe_for_GTK_libs(void) { void *ptr_gtk; if ( !Fl_Posix_System_Driver::probe_for_GTK(2, 4, &ptr_gtk)) { did_find_GTK_libs = 0; return; } void *ptr_glib = ptr_gtk; char *pc_dl_error; // used to report errors by the GET_SYM macro... // items we need from GLib GET_SYM(g_free, ptr_glib); GET_SYM(g_slist_nth_data, ptr_glib); GET_SYM(g_slist_length, ptr_glib); GET_SYM(g_slist_free, ptr_glib); // items we need from GTK GET_SYM(gtk_widget_destroy, ptr_gtk); GET_SYM(gtk_file_chooser_set_select_multiple, ptr_gtk); GET_SYM(gtk_file_chooser_set_do_overwrite_confirmation, ptr_gtk); GET_SYM(gtk_file_chooser_set_current_name, ptr_gtk); GET_SYM(gtk_file_chooser_set_current_folder, ptr_gtk); GET_SYM(gtk_file_chooser_set_create_folders, ptr_gtk); GET_SYM(gtk_file_chooser_get_select_multiple, ptr_gtk); GET_SYM(gtk_widget_hide, ptr_gtk); GET_SYM(gtk_file_chooser_get_filename, ptr_gtk); GET_SYM(gtk_file_chooser_get_filenames, ptr_gtk); GET_SYM(gtk_main_iteration, ptr_gtk); GET_SYM(gtk_events_pending, ptr_gtk); GET_SYM(gtk_file_chooser_dialog_new, ptr_gtk); GET_SYM(gtk_file_chooser_add_filter, ptr_gtk); GET_SYM(gtk_file_chooser_get_filter, ptr_gtk); GET_SYM(gtk_file_chooser_set_filter, ptr_gtk); GET_SYM(gtk_file_filter_new, ptr_gtk); GET_SYM(gtk_file_filter_add_pattern, ptr_gtk); GET_SYM(gtk_file_filter_add_custom, ptr_gtk); GET_SYM(gtk_file_filter_set_name, ptr_gtk); GET_SYM(gtk_file_filter_get_name, ptr_gtk); GET_SYM(gtk_file_chooser_set_extra_widget, ptr_gtk); GET_SYM(gtk_widget_show_now, ptr_gtk); GET_SYM(gtk_file_chooser_set_preview_widget_active, ptr_gtk); GET_SYM(gtk_file_chooser_set_preview_widget, ptr_gtk); GET_SYM(gtk_file_chooser_get_preview_widget, ptr_gtk); GET_SYM(gtk_widget_set_sensitive, ptr_gtk); GET_SYM(gtk_button_new_with_label, ptr_gtk); GET_SYM(gtk_widget_get_toplevel, ptr_gtk); GET_SYM(gtk_file_chooser_get_preview_filename, ptr_gtk); GET_SYM(gdk_pixbuf_new_from_data, ptr_gtk); GET_SYM(gtk_image_set_from_pixbuf, ptr_gtk); GET_SYM(gtk_image_new, ptr_gtk); GET_SYM(gtk_table_new, ptr_gtk); GET_SYM(gtk_widget_show_all, ptr_gtk); GET_SYM(gtk_table_attach_defaults, ptr_gtk); GET_SYM(g_object_unref, ptr_gtk); GET_SYM(gtk_check_button_new_with_label, ptr_gtk); GET_SYM(g_signal_connect_data, ptr_gtk); GET_SYM(gtk_toggle_button_get_active, ptr_gtk); GET_SYM(gtk_file_chooser_set_show_hidden, ptr_gtk); GET_SYM(gtk_file_chooser_get_show_hidden, ptr_gtk); GET_SYM(gtk_toggle_button_set_active, ptr_gtk); did_find_GTK_libs = 1; } // probe_for_GTK_libs #endif // HAVE_DLSYM && HAVE_DLFCN_H Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { // Use zenity if available at run-time even if using the KDE desktop, // because its portal integration means the KDE chooser will be used. // Else use kdialog if available at run-time and if using the KDE // desktop, else, use GTK dialog if available at run-time // otherwise, use FLTK file chooser. platform_fnfc = NULL; fl_open_display(); if (Fl::option(Fl::OPTION_FNFC_USES_ZENITY)&& val != BROWSE_MULTI_DIRECTORY) { if (!Fl_Zenity_Native_File_Chooser_Driver::have_looked_for_zenity) { // First Time here, try to find zenity FILE *pipe = popen("zenity --version 2> /dev/null", "r"); if (pipe) { char *p, line[100] = ""; p = fgets(line, sizeof(line), pipe); if (p && strlen(line) > 0) Fl_Zenity_Native_File_Chooser_Driver::did_find_zenity = true; pclose(pipe); } Fl_Zenity_Native_File_Chooser_Driver::have_looked_for_zenity = true; } // if we found zenity, we will use the Fl_Zenity_Native_File_Chooser_Driver if (Fl_Zenity_Native_File_Chooser_Driver::did_find_zenity) platform_fnfc = new Fl_Zenity_Native_File_Chooser_Driver(val); } if (!platform_fnfc && Fl::option(Fl::OPTION_FNFC_USES_KDIALOG) && val != BROWSE_MULTI_DIRECTORY) { if (!Fl_Kdialog_Native_File_Chooser_Driver::have_looked_for_kdialog) { // First Time here, try to find kdialog FILE *pipe = popen("kdialog -v 2> /dev/null", "r"); if (pipe) { char *p, line[100] = ""; p = fgets(line, sizeof(line), pipe); if (p && strlen(line) > 0) Fl_Kdialog_Native_File_Chooser_Driver::did_find_kdialog = true; pclose(pipe); } Fl_Kdialog_Native_File_Chooser_Driver::have_looked_for_kdialog = true; } // if we found kdialog, we will use the Fl_Kdialog_Native_File_Chooser_Driver if (Fl_Kdialog_Native_File_Chooser_Driver::did_find_kdialog) platform_fnfc = new Fl_Kdialog_Native_File_Chooser_Driver(val); } #if HAVE_DLSYM && HAVE_DLFCN_H if (!platform_fnfc) { if (Fl::option(Fl::OPTION_FNFC_USES_GTK)) { if ( Fl_GTK_Native_File_Chooser_Driver::have_looked_for_GTK_libs == 0) { // First Time here, try to find the GTK libs if they are installed Fl_GTK_Native_File_Chooser_Driver::probe_for_GTK_libs(); Fl_GTK_Native_File_Chooser_Driver::have_looked_for_GTK_libs = -1; } // if we found all the GTK functions we need, we will use the GtkFileChooserDialog if (Fl_GTK_Native_File_Chooser_Driver::did_find_GTK_libs) platform_fnfc = new Fl_GTK_Native_File_Chooser_Driver(val); } } #endif // HAVE_DLSYM && HAVE_DLFCN_H if (!platform_fnfc) platform_fnfc = new Fl_Native_File_Chooser_FLTK_Driver(val); } fltk-1.4.3/src/freeglut_teapot.cxx0000644000175000017500000001334515004135251017317 0ustar albrechtalbrecht/* * freeglut_teapot.c * * Teapot(tm) rendering code. * * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. * Written by Pawel W. Olszta, * Creation date: Fri Dec 24 1999 * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* * Original teapot code copyright follows: */ /* * (c) Copyright 1993, Silicon Graphics, Inc. * * ALL RIGHTS RESERVED * * Permission to use, copy, modify, and distribute this software * for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that * both the copyright notice and this permission notice appear in * supporting documentation, and that the name of Silicon * Graphics, Inc. not be used in advertising or publicity * pertaining to distribution of the software without specific, * written prior permission. * * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU * "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR * OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO * EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE * ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER, * INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE, * SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR * NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY * OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR * PERFORMANCE OF THIS SOFTWARE. * * US Government Users Restricted Rights * * Use, duplication, or disclosure by the Government is subject to * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph * (c)(1)(ii) of the Rights in Technical Data and Computer * Software clause at DFARS 252.227-7013 and/or in similar or * successor clauses in the FAR or the DOD or NASA FAR * Supplement. Unpublished-- rights reserved under the copyright * laws of the United States. Contractor/manufacturer is Silicon * Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA * 94039-7311. * * OpenGL(TM) is a trademark of Silicon Graphics, Inc. */ #include #include "freeglut_teapot_data.h" /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ static void fghTeapot( GLint grid, GLdouble scale, GLenum type ) { double p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3]; long i, j, k, l; glPushAttrib( GL_ENABLE_BIT | GL_EVAL_BIT ); glEnable( GL_AUTO_NORMAL ); glEnable( GL_NORMALIZE ); glEnable( GL_MAP2_VERTEX_3 ); glEnable( GL_MAP2_TEXTURE_COORD_2 ); glPushMatrix(); glRotated( 270.0, 1.0, 0.0, 0.0 ); glScaled( 0.5 * scale, 0.5 * scale, 0.5 * scale ); glTranslated( 0.0, 0.0, -1.5 ); for (i = 0; i < 10; i++) { for (j = 0; j < 4; j++) { for (k = 0; k < 4; k++) { for (l = 0; l < 3; l++) { p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l]; q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l]; if (l == 1) q[j][k][l] *= -1.0; if (i < 6) { r[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l]; if (l == 0) r[j][k][l] *= -1.0; s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l]; if (l == 0) s[j][k][l] *= -1.0; if (l == 1) s[j][k][l] *= -1.0; } } } } glMap2d(GL_MAP2_TEXTURE_COORD_2, 0.0, 1.0, 2, 2, 0.0, 1.0, 4, 2, &tex[0][0][0]); glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4, &p[0][0][0]); glMapGrid2d(grid, 0.0, 1.0, grid, 0.0, 1.0); glEvalMesh2(type, 0, grid, 0, grid); glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4, &q[0][0][0]); glEvalMesh2(type, 0, grid, 0, grid); if (i < 6) { glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4, &r[0][0][0]); glEvalMesh2(type, 0, grid, 0, grid); glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4, &s[0][0][0]); glEvalMesh2(type, 0, grid, 0, grid); } } glPopMatrix(); glPopAttrib(); } /* -- INTERFACE FUNCTIONS -------------------------------------------------- */ /* * Renders a beautiful wired teapot... */ void glutWireTeapot( GLdouble size ) { /* We will use the general teapot rendering code */ fghTeapot( 10, size, GL_LINE ); } /* * Renders a beautiful filled teapot... */ void glutSolidTeapot( GLdouble size ) { /* We will use the general teapot rendering code */ fghTeapot( 7, size, GL_FILL ); } /*** END OF FILE ***/ fltk-1.4.3/src/glut_font.cxx0000644000175000017500000001233115004135251016121 0ustar albrechtalbrecht// // GLUT font routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // The stroked text code was copied from FreeGLUT 2.4.0 which carries // the following notice: // // Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. // // (sort of) emulation of Glut's bitmap drawing functions, using FL's // font stuff. Not all the fonts match! #include #if HAVE_GL # include Fl_Glut_Bitmap_Font glutBitmap9By15 = {FL_SCREEN, 15}; Fl_Glut_Bitmap_Font glutBitmap8By13 = {FL_SCREEN, 13}; Fl_Glut_Bitmap_Font glutBitmapTimesRoman10 = {FL_TIMES, 10}; Fl_Glut_Bitmap_Font glutBitmapTimesRoman24 = {FL_TIMES, 24}; Fl_Glut_Bitmap_Font glutBitmapHelvetica10 = {FL_HELVETICA, 10}; Fl_Glut_Bitmap_Font glutBitmapHelvetica12 = {FL_HELVETICA, 12}; Fl_Glut_Bitmap_Font glutBitmapHelvetica18 = {FL_HELVETICA, 18}; void glutBitmapCharacter(void* font, int character) { gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size); char a[1]; a[0] = character; gl_draw(a,1); } int glutBitmapHeight(void* font) { gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size); return gl_height(); } int glutBitmapLength(void *font, const unsigned char *string) { gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size); const char *s = (const char*)string; return int(gl_width(s)+.5); } void glutBitmapString(void *font, const unsigned char *string) { gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size); const char *s = (const char*)string; gl_draw(s); } int glutBitmapWidth(void* font, int character) { gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size); return int(gl_width(character)+.5); } /* * Draw a stroke character */ void glutStrokeCharacter(void* fontID, int character) { const Fl_Glut_StrokeChar *schar; const Fl_Glut_StrokeStrip *strip; int i, j; Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID; if (character < 0 || character >= font->Quantity) return; schar = font->Characters[character]; if (!schar) return; strip = schar->Strips; for (i = 0; i < schar->Number; i++, strip++) { glBegin(GL_LINE_STRIP); for (j = 0; j < strip->Number; j++) glVertex2f(strip->Vertices[j].X, strip->Vertices[j].Y); glEnd(); } glTranslatef(schar->Right, 0.0, 0.0); } void glutStrokeString(void* fontID, const unsigned char *string) { unsigned char c; int i, j; float length = 0.0; Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID; if (!string || ! *string) return; /* * Step through the string, drawing each character. * A newline will simply translate the next character's insertion * point back to the start of the line and down one line. */ while ((c = *string++) != 0) { if (c < font->Quantity) { if (c == '\n') { glTranslatef(-length, -(float)(font->Height), 0.0); length = 0.0; } else { /* Not an EOL, draw the bitmap character */ const Fl_Glut_StrokeChar *schar = font->Characters[c]; if (schar) { const Fl_Glut_StrokeStrip *strip = schar->Strips; for (i = 0; i < schar->Number; i++, strip++) { glBegin(GL_LINE_STRIP); for (j = 0; j < strip->Number; j++) glVertex2f(strip->Vertices[j].X, strip->Vertices[j].Y); glEnd(); } length += schar->Right; glTranslatef(schar->Right, 0.0, 0.0); } } } } } /* * Return the width in pixels of a stroke character */ int glutStrokeWidth( void* fontID, int character ) { const Fl_Glut_StrokeChar *schar; Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID; if (character < 0 || character >= font->Quantity) return 0; schar = font->Characters[ character ]; return schar ? (int)(schar->Right + 0.5) : 0; } /* * Return the width of a string drawn using a stroke font */ int glutStrokeLength(void* fontID, const unsigned char* string) { unsigned char c; float length = 0.0; float this_line_length = 0.0; Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID; if (!string || ! *string) return 0; while ((c = *string++) != 0) { if (c < font->Quantity) { if (c == '\n') { /* EOL; reset the length of this line */ if (length < this_line_length) length = this_line_length; this_line_length = 0.0; } else { /* Not an EOL, increment the length of this line */ const Fl_Glut_StrokeChar *schar = font->Characters[c]; if (schar) this_line_length += schar->Right; } } } if (length < this_line_length) length = this_line_length; return (int)(length + 0.5); } /* * Returns the height of a stroke font */ GLfloat glutStrokeHeight(void* fontID) { Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID; return font->Height; } #endif // HAVE_GL fltk-1.4.3/src/Fl_add_idle.cxx0000644000175000017500000000577315004135251016302 0ustar albrechtalbrecht// // Idle routine support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Allows you to manage an arbitrary set of idle() callbacks. // Replaces the older set_idle() call (which is used to implement this) #include struct idle_cb { void (*cb)(void*); void* data; idle_cb *next; }; // the callbacks are stored linked in a ring. last points at the one // just called, first at the next to call. last->next == first. static idle_cb* first; static idle_cb* last; static idle_cb* freelist; // The function call_idle() // - removes the first idle callback from the front of the list (ring) // - adds it as the last entry and // - calls the idle callback. // The idle callback may remove itself from the list of idle callbacks // by calling Fl::remove_idle() static void call_idle() { idle_cb* p = first; last = p; first = p->next; p->cb(p->data); // this may call add_idle() or remove_idle()! } /** Adds a callback function that is called every time by Fl::wait() and also makes it act as though the timeout is zero (this makes Fl::wait() return immediately, so if it is in a loop it is called repeatedly, and thus the idle function is called repeatedly). The idle function can be used to get background processing done. You can have multiple idle callbacks. To remove an idle callback use Fl::remove_idle(). Fl::wait() and Fl::check() call idle callbacks, but Fl::ready() does not. The idle callback can call any FLTK functions, including Fl::wait(), Fl::check(), and Fl::ready(). FLTK will not recursively call the idle callback. */ void Fl::add_idle(Fl_Idle_Handler cb, void* data) { idle_cb* p = freelist; if (p) freelist = p->next; else p = new idle_cb; p->cb = cb; p->data = data; if (first) { last->next = p; last = p; p->next = first; } else { first = last = p; p->next = p; set_idle(call_idle); } } /** Returns true if the specified idle callback is currently installed. */ int Fl::has_idle(Fl_Idle_Handler cb, void* data) { idle_cb* p = first; if (!p) return 0; for (;; p = p->next) { if (p->cb == cb && p->data == data) return 1; if (p==last) return 0; } } /** Removes the specified idle callback, if it is installed. */ void Fl::remove_idle(Fl_Idle_Handler cb, void* data) { idle_cb* p = first; if (!p) return; idle_cb* l = last; for (;; p = p->next) { if (p->cb == cb && p->data == data) break; if (p==last) return; // not found l = p; } if (l == p) { // only one first = last = 0; set_idle(0); } else { last = l; first = l->next = p->next; } p->next = freelist; freelist = p; } fltk-1.4.3/src/fl_vertex.cxx0000644000175000017500000000675315004135251016131 0ustar albrechtalbrecht// // Portable drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file fl_vertex.cxx \brief Portable drawing code for drawing arbitrary shapes with simple 2D transformations. */ // Portable code for drawing arbitrary shapes with simple 2D transformations. // See also fl_arc.cxx // matt: the Quartz implementation purposely doesn't use the Quartz matrix // operations for reasons of compatibility and maintainability // ----------------------------------------------------------------------------- // all driver code is now in drivers/XXX/Fl_XXX_Graphics_Driver_xyz.cxx // ----------------------------------------------------------------------------- #include #include #include #include /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** see fl_push_matrix() */ void Fl_Graphics_Driver::push_matrix() { if (sptr==matrix_stack_size) Fl::error("fl_push_matrix(): matrix stack overflow."); else stack[sptr++] = m; } /** see fl_pop_matrix() */ void Fl_Graphics_Driver::pop_matrix() { if (sptr==0) Fl::error("fl_pop_matrix(): matrix stack underflow."); else m = stack[--sptr]; } /** see fl_load_identity() */ void Fl_Graphics_Driver::load_identity() { m = m0; } /** see fl_load_matrix() */ void Fl_Graphics_Driver::load_matrix(double a, double b, double c, double d, double x, double y) { m.a = a; m.b = b; m.c = c; m.d = d; m.x = x; m.y = y; } /** see fl_mult_matrix() */ void Fl_Graphics_Driver::mult_matrix(double a, double b, double c, double d, double x, double y) { matrix o; o.a = a*m.a + b*m.c; o.b = a*m.b + b*m.d; o.c = c*m.a + d*m.c; o.d = c*m.b + d*m.d; o.x = x*m.a + y*m.c + m.x; o.y = x*m.b + y*m.d + m.y; m = o; } /** see fl_rotate() */ void Fl_Graphics_Driver::rotate(double d) { if (d) { double s, c; if (d == 0) {s = 0; c = 1;} else if (d == 90) {s = 1; c = 0;} else if (d == 180) {s = 0; c = -1;} else if (d == 270 || d == -90) {s = -1; c = 0;} else {s = sin(d*M_PI/180); c = cos(d*M_PI/180);} mult_matrix(c,-s,s,c,0,0); } } /** see fl_translate() */ void Fl_Graphics_Driver::translate(double x,double y) { mult_matrix(1,0,0,1,x,y); } /** see fl_begin_points() */ void Fl_Graphics_Driver::begin_points() { n = 0; what = POINTS; } /** see fl_begin_line() */ void Fl_Graphics_Driver::begin_line() { n = 0; what = LINE; } /** see fl_begin_loop() */ void Fl_Graphics_Driver::begin_loop() { n = 0; what = LOOP; } /** see fl_begin_polygon() */ void Fl_Graphics_Driver::begin_polygon() { n = 0; what = POLYGON; } /** see fl_transform_x() */ double Fl_Graphics_Driver::transform_x(double x, double y) { return x*m.a + y*m.c + m.x; } /** see fl_transform_y() */ double Fl_Graphics_Driver::transform_y(double x, double y) { return x*m.b + y*m.d + m.y; } /** see fl_transform_dx() */ double Fl_Graphics_Driver::transform_dx(double x, double y) { return x*m.a + y*m.c; } /** see fl_transform_dy() */ double Fl_Graphics_Driver::transform_dy(double x, double y) { return x*m.b + y*m.d; } /** \} \endcond */ fltk-1.4.3/src/scandir_win32.c0000644000175000017500000001334715004135251016215 0ustar albrechtalbrecht/* * Windows scandir function for the Fast Light Tool Kit (FLTK). * * Copyright 1998-2023 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #ifndef __CYGWIN__ /* Emulation of POSIX scandir() call with error messages */ #include #include #include "flstring.h" #include #include /* Get error message string for last failed WIN32 operation * in 'errmsg' (if non-NULL), string size limited to errmsg_sz. * * NOTE: Copied from: fluid/ExternalCodeEditor_WIN32.cxx * * TODO: Verify works in different languages, with utf8 strings. * TODO: This should be made available globally to the FLTK internals, in case * other parts of FLTK need OS error messages.. */ static void get_ms_errmsg(char *errmsg, int errmsg_sz) { DWORD lastErr = GetLastError(); DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM; DWORD langid = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); LPWSTR mbuf = 0; DWORD msize = 0; /* Early exit if parent doesn't want an errmsg */ if (!errmsg || errmsg_sz <= 0 ) return; /* Get error message from Windows */ msize = FormatMessageW(flags, 0, lastErr, langid, (LPWSTR)&mbuf, 0, NULL); if ( msize == 0 ) { fl_snprintf(errmsg, errmsg_sz, "Error #%lu", (unsigned long)lastErr); } else { char *src; char *dst; /* convert message to UTF-8 */ fl_utf8fromwc(errmsg, errmsg_sz, mbuf, msize); /* Remove '\r's -- they screw up fl_alert()) */ src = dst = errmsg; for ( ; 1; src++ ) { if ( *src == '\0' ) { *dst = '\0'; break; } if ( *src != '\r' ) { *dst++ = *src; } } LocalFree(mbuf); /* Free the buffer allocated by the system */ } } /* * This could use some docs. * * Returns -1 on error, errmsg returns error string (if non-NULL) */ int fl_scandir(const char *dirname, struct dirent ***namelist, int (*select)(struct dirent *), int (*compar)(struct dirent **, struct dirent **), char *errmsg, int errmsg_sz) { int len; char *findIn, *d, is_dir = 0; WIN32_FIND_DATAW findw; HANDLE h; int nDir = 0, NDir = 0; struct dirent **dir = 0, *selectDir; unsigned long ret; if (errmsg && errmsg_sz>0) errmsg[0] = '\0'; len = (int) strlen(dirname); findIn = (char *)malloc((size_t)(len+10)); if (!findIn) { /* win32 malloc() docs: "malloc sets errno to ENOMEM if allocation fails" */ if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno)); return -1; } strcpy(findIn, dirname); for (d = findIn; *d; d++) if (*d == '/') *d = '\\'; if (len == 0) { strcpy(findIn, ".\\*"); } if ((len == 2) && (findIn[1] == ':') && isalpha(findIn[0])) { *d++ = '\\'; *d = 0; } if ((len == 1) && (d[-1] == '.')) { strcpy(findIn, ".\\*"); is_dir = 1; } if ((len > 0) && (d[-1] == '\\')) { *d++ = '*'; *d = 0; is_dir = 1; } if ((len > 1) && (d[-1] == '.') && (d[-2] == '\\')) { d[-1] = '*'; is_dir = 1; } { /* Create a block to limit the scope while we find the initial "wide" filename */ unsigned short *wbuf = NULL; unsigned wlen = fl_utf8toUtf16(findIn, (unsigned) strlen(findIn), NULL, 0); /* Pass NULL to query length */ wlen++; /* add a little extra for termination etc. */ wbuf = (unsigned short*)malloc(sizeof(unsigned short)*(wlen+2)); wlen = fl_utf8toUtf16(findIn, (unsigned) strlen(findIn), wbuf, wlen); /* actually convert the filename */ wbuf[wlen] = 0; /* NULL terminate the resultant string */ if (!is_dir) { /* this file may still be a directory that we need to list */ DWORD attr = GetFileAttributesW(wbuf); if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) ) { wbuf[wlen] = '\\'; wbuf[wlen+1] = '*'; wbuf[wlen+2] = 0; } } h = FindFirstFileW(wbuf, &findw); /* get a handle to the first filename in the search */ free(wbuf); /* release the "wide" buffer before the pointer goes out of scope */ } if (h == INVALID_HANDLE_VALUE) { free(findIn); ret = GetLastError(); if (ret != ERROR_NO_MORE_FILES) { nDir = -1; get_ms_errmsg(errmsg, errmsg_sz); /* return OS error msg */ } *namelist = dir; return nDir; } do { int l = (int) wcslen(findw.cFileName); int dstlen = l * 5 + 1; selectDir=(struct dirent*)malloc(sizeof(struct dirent)+dstlen); l = fl_utf8fromwc(selectDir->d_name, dstlen, findw.cFileName, l); selectDir->d_name[l] = 0; if (findw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* Append a trailing slash to directory names... */ strcat(selectDir->d_name, "/"); } if (!select || (*select)(selectDir)) { if (nDir==NDir) { struct dirent **tempDir = (struct dirent **)calloc(sizeof(struct dirent*), (size_t)(NDir+33)); if (NDir) memcpy(tempDir, dir, sizeof(struct dirent*)*NDir); if (dir) free(dir); dir = tempDir; NDir += 32; } dir[nDir] = selectDir; nDir++; dir[nDir] = 0; } else { free(selectDir); } } while (FindNextFileW(h, &findw)); ret = GetLastError(); if (ret != ERROR_NO_MORE_FILES) { /* don't return an error code, because the dir list may still be valid up to this point */ } FindClose(h); free (findIn); if (compar) qsort(dir, (size_t)nDir, sizeof(*dir), (int(*)(const void*, const void*))compar); *namelist = dir; return nDir; } #endif fltk-1.4.3/src/Fl_Native_File_Chooser_Kdialog.H0000644000175000017500000000367515004135251021442 0ustar albrechtalbrecht// // FLTK native file chooser widget : KDE version // // Copyright 2021-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_KDIALOG_NATIVE_FILE_CHOOSER_H #define FL_KDIALOG_NATIVE_FILE_CHOOSER_H 1 /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include #include "Fl_String.H" class Fl_Kdialog_Native_File_Chooser_Driver : public Fl_Native_File_Chooser_FLTK_Driver { friend class Fl_Native_File_Chooser; friend class Fl_Zenity_Native_File_Chooser_Driver; struct fnfc_pipe_struct { char *all_files; int fd; }; static void fnfc_fd_cb(int fd, fnfc_pipe_struct *data); char **_pathnames; int _tpathnames; char *_directory; char *_preset_file; char *_title; static bool did_find_kdialog; static bool have_looked_for_kdialog; Fl_Kdialog_Native_File_Chooser_Driver(int val); ~Fl_Kdialog_Native_File_Chooser_Driver(); int count() const FL_OVERRIDE; const char *filename() const FL_OVERRIDE; const char *filename(int i) const FL_OVERRIDE; virtual void build_command(Fl_String& command); int show() FL_OVERRIDE; char *parse_filter(const char *f); const char *filter() const FL_OVERRIDE; void filter(const char *f) FL_OVERRIDE; int filters() const FL_OVERRIDE; void preset_file(const char *val) FL_OVERRIDE; const char *preset_file() const FL_OVERRIDE; void directory(const char *val) FL_OVERRIDE; const char *directory() const FL_OVERRIDE; void title(const char *val) FL_OVERRIDE; const char *title() const FL_OVERRIDE; void shell_quote(Fl_String& s); }; /** \} \endcond */ #endif // FL_KDIALOG_NATIVE_FILE_CHOOSER_H fltk-1.4.3/src/Fl_Screen_Driver.H0000644000175000017500000002440115004135251016661 0ustar albrechtalbrecht// // All screen related calls in a driver style class. // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #ifndef FL_SCREEN_DRIVER_H #define FL_SCREEN_DRIVER_H #include #include // for Fl_Timeout_Handler #include // TODO: add text composition? // TODO: add Fl::display // TODO: add copy/paste, drag/drop? // TODO: get key/get mouse? // TODO: system colors/colormaps // TODO: system menu? // TODO: native filechooser // TODO: native message boxes // TODO: read screen to image // TODO: application shortcuts class Fl_Window; class Fl_RGB_Image; class Fl_Group; class Fl_Input; class Fl_System_Driver; /** A base class describing the interface between FLTK and screen-related operations. This class is only for internal use by the FLTK library. Each supported platform implements several of the virtual methods of this class. */ class Fl_Screen_Driver { protected: Fl_Screen_Driver(); virtual ~Fl_Screen_Driver(); static const int MAX_SCREENS = 16; int num_screens; static float fl_intersection(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2); public: static int keyboard_screen_scaling; // true means ctrl/+/-/0/ resize windows static char bg_set; static char bg2_set; static char fg_set; static Fl_System_Driver *system_driver; // These flags are useful after calling XParseGeometry(). They indicate which of its // arguments contain meaningful data upon return. static const int fl_NoValue; static const int fl_WidthValue; static const int fl_HeightValue; static const int fl_XValue; static const int fl_YValue; static const int fl_XNegative; static const int fl_YNegative; // Next 2 are used when transient scale windows are implemented as popups static Fl_Window *transient_scale_parent; static void del_transient_window(void *); // key_table and key_table_size are used in fl_shortcut to translate key names struct Keyname { unsigned int key; const char* name; } *key_table; int key_table_size; virtual float scale(int) { return 1; } virtual void scale(int /*n*/, float /*f*/) {} static Fl_Screen_Driver *newScreenDriver(); // implement to process the -display argument and support the DISPLAY env var virtual void display(const char *) { } // default implementation should be enough virtual int XParseGeometry(const char* string, int* x, int* y, unsigned int* width, unsigned int* height); // the default implementation is most probably enough virtual void own_colormap() {} // the default implementation of shortcut_add_key_name() is in src/fl_shortcut.cxx virtual const char *shortcut_add_key_name(unsigned key, char *p, char *buf, const char **); // whether a platform uses additional code in Fl_Menu::handle_part1(int e) virtual int need_menu_handle_part1_extra() {return 0;} // whether a platform uses additional code in Fl_Menu::handle(int e) virtual int need_menu_handle_part2() {return 0;} // implement functions telling whether a key is pressed virtual int event_key(int) {return 0;} virtual int get_key(int) {return 0;} virtual int visual(int flags); // --- screen configuration virtual void init() {} virtual int x() { return 0; } virtual int y() { return 0; } virtual int w() { return 800; } // default, FL_OVERRIDE in driver! virtual int h() { return 600; } // default, FL_OVERRIDE in driver! virtual int screen_count(); void screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my); virtual void screen_xywh(int &X, int &Y, int &W, int &H, int /*n*/) { X = 0; Y = 0; W = 800; H = 600; } void screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh); virtual bool screen_boundaries_known() { return true; } virtual int screen_num(int x, int y); virtual int screen_num(int x, int y, int w, int h); virtual void screen_dpi(float &h, float &v, int n = 0) { // FL_OVERRIDE in driver! h = 72; v = 72; (void)n; } void screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my); virtual void screen_work_area(int &X, int &Y, int &W, int &H, int n) { screen_xywh(X, Y, W, H, n); } // --- audible output virtual void beep(int) {} // --- global events virtual void flush() {} // must FL_OVERRIDE virtual void grab(Fl_Window *) {} // --- global colors /* the default implementation of parse_color() may be enough */ virtual int parse_color(const char *p, uchar &r, uchar &g, uchar &b); virtual void get_system_colors(); /* the default implementation of get_system_scheme() may be enough */ virtual const char *get_system_scheme(); static int secret_input_character; /* Implement to indicate whether complex text input may involve marked text. When it does, has_marked_text returns non zero. */ virtual int has_marked_text() const { return 0; } // implement so text-editing widgets support dead keys virtual int compose(int &del) { del = 0; return 0; } // default implementation may be enough virtual void compose_reset(); // implement to support drag-n-drop. use_selection = 1 means the GUI is welcome to display // the selected text during the D&D operation virtual int dnd(int use_selection = 0) { (void)use_selection; return 0; } // null means no platform-specific key bindings for Fl_Text_Editor Fl_Text_Editor::Key_Binding *text_editor_extra_key_bindings; // default implementation may be enough virtual int text_display_can_leak() const { return 0; } // if no keyboard is connected on a touch or pen device, the system on-screen keyboard is // requested virtual void request_keyboard() {} // we no longer need the on-screen keyboard; it's up to the system to hide it virtual void release_keyboard() {} /* Member function read_win_rectangle() supports public functions fl_read_image() and fl_capture_window() which capture pixel data from a window (or also from an offscreen buffer with fl_read_image). If 'may_capture_subwins' is true, an implementation may or may not capture also the content of subwindows embedded in 'win'. If subwindows were captured, *'did_capture_subwins' is returned set to true. If read_win_rectangle() is called with 'may_capture_subwins' set to true, 'did_capture_subwins' should be set before the call to the address of a boolean set to false. The implementation of this virtual function for the macOS platform has the capability of capturing subwindows when asked for. A platform may also use its read_win_rectangle() implementation to capture window decorations (e.g., title bar). In that case, it is called by Fl_XXX_Window_Driver::capture_titlebar_and_borders(). win is the window to capture from, or NULL to capture from the current offscreen */ virtual Fl_RGB_Image *read_win_rectangle(int /*X*/, int /*Y*/, int /*w*/, int /*h*/, Fl_Window *, bool may_capture_subwins = false, bool *did_capture_subwins = NULL) { (void)may_capture_subwins; (void)did_capture_subwins; return NULL; } static void write_image_inside(Fl_RGB_Image *to, Fl_RGB_Image *from, int to_x, int to_y); static Fl_RGB_Image *traverse_to_gl_subwindows(Fl_Group *g, int x, int y, int w, int h, Fl_RGB_Image *full_img); static size_t convert_crlf(char *s, size_t len); // optional platform-specific key handling for Fl_Input widget // the default implementation may be enough virtual int input_widget_handle_key(int key, unsigned mods, unsigned shift, Fl_Input *input); // implement to support Fl::get_mouse() virtual int get_mouse(int &/*x*/, int &/*y*/) { return 0; } // optional methods to enable/disable input methods for complex scripts virtual void enable_im() {} virtual void disable_im() {} // calls open_display_platform() and then does platform-independent work void open_display(); // implement to open access to the display virtual void open_display_platform() {} // optional method to close display access virtual void close_display() {} // compute dimensions of an Fl_Offscreen virtual void offscreen_size(Fl_Offscreen, int &/*width*/, int &/*height*/) {} void rescale_all_windows_from_screen(int screen, float f, float old_f); static void transient_scale_display(float f, int nscreen); // need export to fltk_gl.so because used in glut_compatibility.cxx static FL_EXPORT int scale_handler(int event); virtual void desktop_scale_factor() {} void use_startup_scale_factor(); enum APP_SCALING_CAPABILITY { NO_APP_SCALING = 0, ///< The platform does not support rescaling. SYSTEMWIDE_APP_SCALING, ///< The platform supports rescaling with the same factor for all screens. PER_SCREEN_APP_SCALING ///< The platform supports rescaling with one factor for each screen. }; /** Returns the platform's support for rescaling the application with ctrl/+/-/0 keys. */ virtual APP_SCALING_CAPABILITY rescalable() { return NO_APP_SCALING; } // supports Fl_Window::default_icons() virtual void default_icons(const Fl_RGB_Image *icons[], int count); // implement to support copy-to-clipboard virtual void copy(const char * /*stuff*/, int /*len*/, int /*clipboard*/, const char * /*type*/) {} // implement to support paste-from-clipboard virtual void paste(Fl_Widget &, int /*clipboard*/, const char * /*type*/) {} // implement to support paste-from-clipboard virtual int clipboard_contains(const char * /*type*/) {return 0;} // implement to support paste-from-clipboard virtual void clipboard_notify_change() {} // next 3 are related to Input Methods virtual void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win); virtual void reset_spot(); virtual void set_status(int X, int Y, int W, int H); virtual float base_scale(int numscreen); }; #endif // !FL_SCREEN_DRIVER_H /** \} \endcond */ fltk-1.4.3/src/Fl_visual.cxx0000644000175000017500000000334515004135251016051 0ustar albrechtalbrecht// // Visual support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Set the default visual according to passed switches: #include #include "Fl_Screen_Driver.H" /** \fn Fl::visual(int flags) Selects a visual so that your graphics are drawn correctly. This is only allowed before you call show() on any windows. This does nothing if the default visual satisfies the capabilities, or if no visual satisfies the capabilities, or on systems that don't have such brain-dead notions.

Only the following combinations do anything useful:

  • Fl::visual(FL_RGB)
    Full/true color (if there are several depths FLTK chooses the largest). Do this if you use fl_draw_image for much better (non-dithered) output.
     
  • Fl::visual(FL_RGB8)
    Full color with at least 24 bits of color. FL_RGB will always pick this if available, but if not it will happily return a less-than-24 bit deep visual. This call fails if 24 bits are not available.
     

This returns true if the system has the capabilities by default or FLTK succeeded in turning them on. Your program will still work even if this returns false (it just won't look as good). */ int Fl::visual(int flags) { return screen_driver()->visual(flags); } fltk-1.4.3/src/ns_mask.xbm0000644000175000017500000000052515004135251015541 0ustar albrechtalbrecht#define ns_mask_width 16 #define ns_mask_height 16 #define ns_mask_x_hot 8 #define ns_mask_y_hot 8 static unsigned char ns_mask_bits[] = { 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}; fltk-1.4.3/src/fl_arc.cxx0000644000175000017500000000516015004135251015350 0ustar albrechtalbrecht// // Arc functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file fl_arc.cxx \brief Utility functions for drawing arcs and circles. */ // Utility for drawing arcs and circles. They are added to // the current fl_begin/fl_vertex/fl_end path. // Incremental math implementation: #include #include // avoid problems with some platforms that don't // implement hypot. static double _fl_hypot(double x, double y) { return sqrt(x*x + y*y); } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** Draw an arc. The default implementation draws an arc using other calls into the graphics driver. There is no need to override the method unless the target platform supports drawing arcs directly. \see fl_arc(double x, double y, double r, double start, double end) */ void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end) { // draw start point accurately: double A = start*(M_PI/180); // Initial angle (radians) double X = r*cos(A); // Initial displacement, (X,Y) double Y = -r*sin(A); // from center to initial point fl_vertex(x+X,y+Y); // Insert initial point // Maximum arc length to approximate with chord with error <= 0.125 double epsilon; { double r1 = _fl_hypot(fl_transform_dx(r,0), // Horizontal "radius" fl_transform_dy(r,0)); double r2 = _fl_hypot(fl_transform_dx(0,r), // Vertical "radius" fl_transform_dy(0,r)); if (r1 > r2) r1 = r2; // r1 = minimum "radius" if (r1 < 2.) r1 = 2.; // radius for circa 9 chords/circle epsilon = 2*acos(1.0 - 0.125/r1); // Maximum arc angle } A = end*(M_PI/180) - A; // Displacement angle (radians) int i = int(ceil(fabs(A)/epsilon)); // Segments in approximation if (i) { epsilon = A/i; // Arc length for equal-size steps double cos_e = cos(epsilon); // Rotation coefficients double sin_e = sin(epsilon); do { double Xnew = cos_e*X + sin_e*Y; Y = -sin_e*X + cos_e*Y; fl_vertex(x + (X=Xnew), y + Y); } while (--i); } } /** \} \endcond */ fltk-1.4.3/src/Fl_Table.cxx0000644000175000017500000013211115004135251015567 0ustar albrechtalbrecht// // Fl_Table -- A table widget for the Fast Light Tool Kit (FLTK). // // Copyright 2002 by Greg Ercolano. // Copyright (c) 2004 O'ksi'D // Copyright 2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include // EXPERIMENTAL // We use either std::vector or the private class Fl_Int_Vector // depending on the build option FLTK_OPTION_STD or equivalent. // This option allows to use std::string and maybe std::vector // already in FLTK 1.4.x #if (!FLTK_USE_STD) #include "Fl_Int_Vector.H" // Note: MUST NOT be included in Fl_Table.H #endif #include #include // memcpy #include // fprintf #include // realloc/free /** Sets the vertical scroll position so 'row' is at the top, and causes the screen to redraw. */ void Fl_Table::row_position(int row) { if ( _row_position == row ) return; // OPTIMIZATION: no change? avoid redraw if ( row < 0 ) row = 0; else if ( row >= rows() ) row = rows() - 1; if ( table_h <= tih ) return; // don't scroll if table smaller than window double newtop = row_scroll_position(row); if ( newtop > vscrollbar->maximum() ) { newtop = vscrollbar->maximum(); } vscrollbar->Fl_Slider::value(newtop); table_scrolled(); redraw(); _row_position = row; // HACK: override what table_scrolled() came up with } /** Sets the horizontal scroll position so 'col' is at the left, and causes the screen to redraw. */ void Fl_Table::col_position(int col) { if ( _col_position == col ) return; // OPTIMIZATION: no change? avoid redraw if ( col < 0 ) col = 0; else if ( col >= cols() ) col = cols() - 1; if ( table_w <= tiw ) return; // don't scroll if table smaller than window double newleft = col_scroll_position(col); if ( newleft > hscrollbar->maximum() ) { newleft = hscrollbar->maximum(); } hscrollbar->Fl_Slider::value(newleft); table_scrolled(); redraw(); _col_position = col; // HACK: override what table_scrolled() came up with } /** Returns the scroll position (in pixels) of the specified 'row'. */ long Fl_Table::row_scroll_position(int row) { int startrow = 0; long scroll = 0; // OPTIMIZATION: // Attempt to use precomputed row scroll position // if ( toprow_scrollpos != -1 && row >= toprow ) { scroll = toprow_scrollpos; startrow = toprow; } for ( int t=startrow; t= leftcol ) { scroll = leftcol_scrollpos; startcol = leftcol; } for ( int t=startcol; t; // column widths in pixels _rowheights = new std::vector; // row heights in pixels #else _colwidths = new Fl_Int_Vector(); // column widths in pixels _rowheights = new Fl_Int_Vector(); // row heights in pixels #endif box(FL_THIN_DOWN_FRAME); vscrollbar = new Fl_Scrollbar(x()+w()-Fl::scrollbar_size(), y(), Fl::scrollbar_size(), h()-Fl::scrollbar_size()); vscrollbar->type(FL_VERTICAL); vscrollbar->callback(scroll_cb, (void*)this); hscrollbar = new Fl_Scrollbar(x(), y()+h()-Fl::scrollbar_size(), w(), Fl::scrollbar_size()); hscrollbar->type(FL_HORIZONTAL); hscrollbar->callback(scroll_cb, (void*)this); table = new Fl_Scroll(x(), y(), w(), h()); table->box(FL_NO_BOX); table->type(0); // don't show Fl_Scroll's scrollbars -- use our own table->hide(); // hide unless children are present table->end(); table_resized(); redraw(); Fl_Group::end(); // end the group's begin() table->begin(); // leave with fltk children getting added to the scroll } /** The destructor for Fl_Table. Destroys the table and its associated widgets. */ Fl_Table::~Fl_Table() { // The parent Fl_Group takes care of destroying scrollbars delete _colwidths; delete _rowheights; } /** Returns the current number of columns. This is equivalent to the size of the column widths vector. \returns Number of columns. */ int Fl_Table::col_size() { return int(_colwidths->size()); } /** Returns the current number of rows. This is equivalent to the size of the row heights vector. \returns Number of rows. */ int Fl_Table::row_size() { return int(_rowheights->size()); } /** Sets the height of the specified row in pixels, and the table is redrawn. callback() will be invoked with CONTEXT_RC_RESIZE if the row's height was actually changed, and when() is FL_WHEN_CHANGED. */ void Fl_Table::row_height(int row, int height) { if ( row < 0 ) return; if ( row < row_size() && (*_rowheights)[row] == height ) { return; // OPTIMIZATION: no change? avoid redraw } // Add row heights, even if none yet int now_size = row_size(); if (row >= now_size) { #if (FLTK_USE_STD) _rowheights->resize(row, height); #else _rowheights->size(row); while (now_size < row) (*_rowheights)[now_size++] = height; #endif // FLTK_USE_STD } (*_rowheights)[row] = height; table_resized(); if ( row <= botrow ) { // OPTIMIZATION: only redraw if onscreen or above screen redraw(); } // ROW RESIZE CALLBACK if ( Fl_Widget::callback() && when() & FL_WHEN_CHANGED ) { do_callback(CONTEXT_RC_RESIZE, row, 0); } } /** Sets the width of the specified column in pixels, and the table is redrawn. callback() will be invoked with CONTEXT_RC_RESIZE if the column's width was actually changed, and when() is FL_WHEN_CHANGED. */ void Fl_Table::col_width(int col, int width) { if ( col < 0 ) return; if ( col < col_size() && (*_colwidths)[col] == width ) { return; // OPTIMIZATION: no change? avoid redraw } // Add column widths, even if none yet int now_size = col_size(); if ( col >= now_size ) { #if (FLTK_USE_STD) _colwidths->resize(col+1, width); #else _colwidths->size(col+1); while (now_size < col) (*_colwidths)[now_size++] = width; #endif } (*_colwidths)[col] = width; table_resized(); if ( col <= rightcol ) { // OPTIMIZATION: only redraw if onscreen or to the left redraw(); } // COLUMN RESIZE CALLBACK if ( Fl_Widget::callback() && when() & FL_WHEN_CHANGED ) { do_callback(CONTEXT_RC_RESIZE, 0, col); } } /** Return specified row/col values R and C to within the table's current row/col limits. \returns 0 if no changes were made, or 1 if they were. */ int Fl_Table::row_col_clamp(TableContext context, int &R, int &C) { int clamped = 0; if ( R < 0 ) { R = 0; clamped = 1; } if ( C < 0 ) { C = 0; clamped = 1; } switch ( context ) { case CONTEXT_COL_HEADER: // Allow col headers to draw even if no rows if ( R >= _rows && R != 0 ) { R = _rows - 1; clamped = 1; } break; case CONTEXT_ROW_HEADER: // Allow row headers to draw even if no columns if ( C >= _cols && C != 0 ) { C = _cols - 1; clamped = 1; } break; case CONTEXT_CELL: default: // CLAMP R/C TO _rows/_cols if ( R >= _rows ) { R = _rows - 1; clamped = 1; } if ( C >= _cols ) { C = _cols - 1; clamped = 1; } break; } return(clamped); } /** Returns the (X,Y,W,H) bounding region for the specified 'context'. */ void Fl_Table::get_bounds(TableContext context, int &X, int &Y, int &W, int &H) { switch ( context ) { case CONTEXT_COL_HEADER: // Column header clipping. X = tox; Y = wiy; W = tow; H = col_header_height(); return; case CONTEXT_ROW_HEADER: // Row header clipping. X = wix; Y = toy; W = row_header_width(); H = toh; return; case CONTEXT_TABLE: // Table inner dimensions X = tix; Y = tiy; W = tiw; H = tih; return; // TODO: Add other contexts.. default: fprintf(stderr, "Fl_Table::get_bounds(): context %d unimplemented\n", (int)context); return; } //NOTREACHED } /** Find row/col for the recent mouse event. Returns the context, and the row/column values in R/C. Also returns 'resizeflag' if mouse is hovered over a resize boundary. */ Fl_Table::TableContext Fl_Table::cursor2rowcol(int &R, int &C, ResizeFlag &resizeflag) { // return values R = C = 0; resizeflag = RESIZE_NONE; // Row header? int X, Y, W, H; if ( row_header() ) { // Inside a row heading? get_bounds(CONTEXT_ROW_HEADER, X, Y, W, H); if ( Fl::event_inside(X, Y, W, H) ) { // Scan visible rows until found for ( R = toprow; R <= botrow; R++ ) { find_cell(CONTEXT_ROW_HEADER, R, 0, X, Y, W, H); if ( Fl::event_y() >= Y && Fl::event_y() < (Y+H) ) { // Found row? // If cursor over resize boundary, and resize enabled, // enable the appropriate resize flag. // if ( row_resize() ) { if ( Fl::event_y() <= (Y+3-0) ) { resizeflag = RESIZE_ROW_ABOVE; } if ( Fl::event_y() >= (Y+H-3) ) { resizeflag = RESIZE_ROW_BELOW; } } return(CONTEXT_ROW_HEADER); } } // Must be in row header dead zone return(CONTEXT_NONE); } } // Column header? if ( col_header() ) { // Inside a column heading? get_bounds(CONTEXT_COL_HEADER, X, Y, W, H); if ( Fl::event_inside(X, Y, W, H) ) { // Scan visible columns until found for ( C = leftcol; C <= rightcol; C++ ) { find_cell(CONTEXT_COL_HEADER, 0, C, X, Y, W, H); if ( Fl::event_x() >= X && Fl::event_x() < (X+W) ) { // Found column? // If cursor over resize boundary, and resize enabled, // enable the appropriate resize flag. // if ( col_resize() ) { if ( Fl::event_x() <= (X+3-0) ) { resizeflag = RESIZE_COL_LEFT; } if ( Fl::event_x() >= (X+W-3) ) { resizeflag = RESIZE_COL_RIGHT; } } return(CONTEXT_COL_HEADER); } } // Must be in column header dead zone return(CONTEXT_NONE); } } // Mouse somewhere in table? // Scan visible r/c's until we find it. // if ( Fl::event_inside(tox, toy, tow, toh) ) { for ( R = toprow; R <= botrow; R++ ) { find_cell(CONTEXT_CELL, R, C, X, Y, W, H); if ( Fl::event_y() < Y ) break; // OPT: thanks lars if ( Fl::event_y() >= (Y+H) ) continue; // OPT: " " for ( C = leftcol; C <= rightcol; C++ ) { find_cell(CONTEXT_CELL, R, C, X, Y, W, H); if ( Fl::event_inside(X, Y, W, H) ) { return(CONTEXT_CELL); // found it } } } // Must be in a dead zone of the table R = C = 0; return(CONTEXT_TABLE); } // Somewhere else return(CONTEXT_NONE); } /** Find a cell's X/Y/W/H region for the specified cell in row 'R', column 'C'. \returns - 0 -- on success, XYWH returns the region of the specified cell. - -1 -- if R or C are out of range, and X/Y/W/H will be set to zero. */ int Fl_Table::find_cell(TableContext context, int R, int C, int &X, int &Y, int &W, int &H) { if ( row_col_clamp(context, R, C) ) { // row or col out of range? error X=Y=W=H=0; return(-1); } X = (int)col_scroll_position(C) - hscrollbar->value() + tix; Y = (int)row_scroll_position(R) - vscrollbar->value() + tiy; W = col_width(C); H = row_height(R); switch ( context ) { case CONTEXT_COL_HEADER: Y = wiy; H = col_header_height(); return(0); case CONTEXT_ROW_HEADER: X = wix; W = row_header_width(); return(0); case CONTEXT_CELL: return(0); case CONTEXT_TABLE: return(0); // TODO -- HANDLE OTHER CONTEXTS default: fprintf(stderr, "Fl_Table::find_cell: unknown context %d\n", (int)context); return(-1); } //NOTREACHED } // Enable automatic scroll-selection void Fl_Table::_start_auto_drag() { if (_auto_drag) return; _auto_drag = 1; Fl::add_timeout(0.3, _auto_drag_cb2, this); } // Disable automatic scroll-selection void Fl_Table::_stop_auto_drag() { if (!_auto_drag) return; Fl::remove_timeout(_auto_drag_cb2, this); _auto_drag = 0; } void Fl_Table::_auto_drag_cb2(void *d) { ((Fl_Table*)d)->_auto_drag_cb(); } // Handle automatic scroll-selection if mouse selection dragged off table edge void Fl_Table::_auto_drag_cb() { int lx = Fl::e_x; int ly = Fl::e_y; if (_selecting == CONTEXT_COL_HEADER) { ly = y() + col_header_height(); } else if (_selecting == CONTEXT_ROW_HEADER) { lx = x() + row_header_width(); } if (lx > x() + w() - 20) { Fl::e_x = x() + w() - 20; if (hscrollbar->visible()) ((Fl_Slider*)hscrollbar)->value(hscrollbar->clamp(hscrollbar->value() + 30)); hscrollbar->do_callback(); _dragging_x = Fl::e_x - 30; } else if (lx < (x() + row_header_width())) { Fl::e_x = x() + row_header_width() + 1; if (hscrollbar->visible()) { ((Fl_Slider*)hscrollbar)->value(hscrollbar->clamp(hscrollbar->value() - 30)); } hscrollbar->do_callback(); _dragging_x = Fl::e_x + 30; } if (ly > y() + h() - 20) { Fl::e_y = y() + h() - 20; if (vscrollbar->visible()) { ((Fl_Slider*)vscrollbar)->value(vscrollbar->clamp(vscrollbar->value() + 30)); } vscrollbar->do_callback(); _dragging_y = Fl::e_y - 30; } else if (ly < (y() + col_header_height())) { Fl::e_y = y() + col_header_height() + 1; if (vscrollbar->visible()) { ((Fl_Slider*)vscrollbar)->value(vscrollbar->clamp(vscrollbar->value() - 30)); } vscrollbar->do_callback(); _dragging_y = Fl::e_y + 30; } _auto_drag = 2; handle(FL_DRAG); _auto_drag = 1; Fl::e_x = lx; Fl::e_y = ly; Fl::check(); Fl::flush(); if (Fl::event_buttons() && _auto_drag) { Fl::add_timeout(0.05, _auto_drag_cb2, this); } } /** Recalculate the dimensions of the table, and affect any children. Internally, Fl_Group::resize() and init_sizes() are called. */ void Fl_Table::recalc_dimensions() { // Recalc to* (Table Outer), ti* (Table Inner), wi* ( Widget Inner) wix = ( x() + Fl::box_dx(box())); tox = wix; tix = tox + Fl::box_dx(table->box()); wiy = ( y() + Fl::box_dy(box())); toy = wiy; tiy = toy + Fl::box_dy(table->box()); wiw = ( w() - Fl::box_dw(box())); tow = wiw; tiw = tow - Fl::box_dw(table->box()); wih = ( h() - Fl::box_dh(box())); toh = wih; tih = toh - Fl::box_dh(table->box()); // Trim window if headers enabled if ( col_header() ) { tiy += col_header_height(); toy += col_header_height(); tih -= col_header_height(); toh -= col_header_height(); } if ( row_header() ) { tix += row_header_width(); tox += row_header_width(); tiw -= row_header_width(); tow -= row_header_width(); } // Make scroll bars disappear if window large enough { // First pass: can hide via window size? int hidev = (table_h <= tih); int hideh = (table_w <= tiw); int scrollsize = _scrollbar_size ? _scrollbar_size : Fl::scrollbar_size(); // Second pass: Check for interference if ( !hideh && hidev ) { hidev = (( table_h - tih + scrollsize ) <= 0 ); } if ( !hidev && hideh ) { hideh = (( table_w - tiw + scrollsize ) <= 0 ); } // Determine scrollbar visibility, trim ti[xywh]/to[xywh] if ( hidev ) { vscrollbar->hide(); } else { vscrollbar->show(); tiw -= scrollsize; tow -= scrollsize; } if ( hideh ) { hscrollbar->hide(); } else { hscrollbar->show(); tih -= scrollsize; toh -= scrollsize; } } // Resize the child table table->resize(tox, toy, tow, toh); table->init_sizes(); } /** Recalculate internals after a scroll. Call this if table has been scrolled or resized. Does not handle redraw(). TODO: Assumes ti[xywh] has already been recalculated. */ void Fl_Table::table_scrolled() { // Find top row int y, row, voff = vscrollbar->value(); for ( row=y=0; row < _rows; row++ ) { y += row_height(row); if ( y > voff ) { y -= row_height(row); break; } } _row_position = toprow = ( row >= _rows ) ? (row - 1) : row; toprow_scrollpos = y; // OPTIMIZATION: save for later use // Find bottom row voff = vscrollbar->value() + tih; for ( ; row < _rows; row++ ) { y += row_height(row); if ( y >= voff ) { break; } } botrow = ( row >= _rows ) ? (row - 1) : row; // Left column int x, col, hoff = hscrollbar->value(); for ( col=x=0; col < _cols; col++ ) { x += col_width(col); if ( x > hoff ) { x -= col_width(col); break; } } _col_position = leftcol = ( col >= _cols ) ? (col - 1) : col; leftcol_scrollpos = x; // OPTIMIZATION: save for later use // Right column // Work with data left over from leftcol calculation // hoff = hscrollbar->value() + tiw; for ( ; col < _cols; col++ ) { x += col_width(col); if ( x >= hoff ) { break; } } rightcol = ( col >= _cols ) ? (col - 1) : col; // First tell children to scroll draw_cell(CONTEXT_RC_RESIZE, 0,0,0,0,0,0); } /** Call this if table was resized, to recalculate internal data. Calls recall_dimensions(), and recalculates scrollbar sizes. */ void Fl_Table::table_resized() { table_h = (int)row_scroll_position(rows()); table_w = (int)col_scroll_position(cols()); recalc_dimensions(); // Recalc scrollbar sizes // Clamp scrollbar value() after a resize. // Resize scrollbars to enforce a constant trough width after a window resize. // { // Vertical scrollbar float vscrolltab = ( table_h == 0 || tih > table_h ) ? 1 : (float)tih / table_h; float hscrolltab = ( table_w == 0 || tiw > table_w ) ? 1 : (float)tiw / table_w; int scrollsize = _scrollbar_size ? _scrollbar_size : Fl::scrollbar_size(); vscrollbar->bounds(0, table_h-tih); vscrollbar->precision(10); vscrollbar->slider_size(vscrolltab); vscrollbar->resize(wix+wiw-scrollsize, wiy, scrollsize, wih - ((hscrollbar->visible())?scrollsize:0)); vscrollbar->Fl_Valuator::value(vscrollbar->clamp(vscrollbar->value())); // Horizontal scrollbar hscrollbar->bounds(0, table_w-tiw); hscrollbar->precision(10); hscrollbar->slider_size(hscrolltab); hscrollbar->resize(wix, wiy+wih-scrollsize, wiw - ((vscrollbar->visible())?scrollsize:0), scrollsize); hscrollbar->Fl_Valuator::value(hscrollbar->clamp(hscrollbar->value())); } // Tell FLTK child widgets were resized Fl_Group::init_sizes(); // Recalc top/bot/left/right table_scrolled(); // DO *NOT* REDRAW -- LEAVE THIS UP TO THE CALLER // redraw(); } /** Callback for when someone moves a scrollbar. */ void Fl_Table::scroll_cb(Fl_Widget*w, void *data) { Fl_Table *o = (Fl_Table*)data; o->recalc_dimensions(); // recalc tix, tiy, etc. o->table_scrolled(); o->redraw(); } /** Sets the number of rows in the table, and the table is redrawn. */ void Fl_Table::rows(int val) { int oldrows = _rows; _rows = val; int default_h = row_size() > 0 ? _rowheights->back() : 25; int now_size = row_size(); #if (FLTK_USE_STD) if (now_size != val) _rowheights->resize(val, default_h); // enlarge or shrink as needed #else _rowheights->size(val); // enlarge or shrink as needed while (now_size < val) (*_rowheights)[now_size++] = default_h; // fill new #endif table_resized(); // OPTIMIZATION: redraw only if change is visible. if ( val >= oldrows && oldrows > botrow ) { // NO REDRAW } else { redraw(); } } /** Set the number of columns in the table and redraw. */ void Fl_Table::cols(int val) { _cols = val; int default_w = col_size() > 0 ? (*_colwidths)[col_size()-1] : 80; int now_size = col_size(); #if (FLTK_USE_STD) if (now_size != val) _colwidths->resize(val, default_w); // enlarge or shrink as needed #else _colwidths->size(val); // enlarge or shrink as needed while (now_size < val) (*_colwidths)[now_size++] = default_w; // fill new #endif table_resized(); redraw(); } /** Change mouse cursor to different type */ void Fl_Table::change_cursor(Fl_Cursor newcursor) { if ( newcursor != _last_cursor ) { fl_cursor(newcursor, FL_BLACK, FL_WHITE); _last_cursor = newcursor; } } /** Sets the damage zone to the specified row/col values. Calls redraw_range(). */ void Fl_Table::damage_zone(int r1, int c1, int r2, int c2, int r3, int c3) { int R1 = r1, C1 = c1; int R2 = r2, C2 = c2; if (r1 > R2) R2 = r1; if (r2 < R1) R1 = r2; if (r3 > R2) R2 = r3; if (r3 < R1) R1 = r3; if (c1 > C2) C2 = c1; if (c2 < C1) C1 = c2; if (c3 > C2) C2 = c3; if (c3 < C1) C1 = c3; if (R1 < 0) { if (R2 < 0) return; R1 = 0; } if (C1 < 0) { if (C2 < 0) return; C1 = 0; } if (R1 < toprow) R1 = toprow; if (R2 > botrow) R2 = botrow; if (C1 < leftcol) C1 = leftcol; if (C2 > rightcol) C2 = rightcol; redraw_range(R1, R2, C1, C2); } /** Moves the selection cursor a relative number of rows/columns specifed by R/C. R/C can be positive or negative, depending on the direction to move. A value of 0 for R or C prevents cursor movement on that axis. If shiftselect is set, the selection range is extended to the new cursor position. If clear, the cursor is simply moved, and any previous selection is cancelled. Used mainly by keyboard events (e.g. Fl_Right, FL_Home, FL_End..) to let the user keyboard navigate the selection cursor around. The scroll positions may be modified if the selection cursor traverses into cells off the screen's edge. Internal variables select_row/select_col and current_row/current_col are modified, among others. \code Examples: R=1, C=0 -- moves the selection cursor one row downward. R=5, C=0 -- moves the selection cursor 5 rows downward. R=-5, C=0 -- moves the cursor 5 rows upward. R=2, C=2 -- moves the cursor 2 rows down and 2 columns to the right. \endcode */ int Fl_Table::move_cursor(int R, int C, int shiftselect) { if (select_row == -1) R++; if (select_col == -1) C++; R += select_row; C += select_col; if (R < 0) R = 0; if (R >= rows()) R = rows() - 1; if (C < 0) C = 0; if (C >= cols()) C = cols() - 1; if (R == select_row && C == select_col) return 0; damage_zone(current_row, current_col, select_row, select_col, R, C); select_row = R; select_col = C; if (!shiftselect || !Fl::event_state(FL_SHIFT)) { current_row = R; current_col = C; } if (R < toprow + 1 || R > botrow - 1) row_position(R); if (C < leftcol + 1 || C > rightcol - 1) col_position(C); return 1; } /** Same as move_cursor(R,C,1); */ int Fl_Table::move_cursor(int R, int C) { return move_cursor(R,C,1); } //#define DEBUG 1 #ifdef DEBUG #include #define PRINTEVENT \ fprintf(stderr,"Table %s: ** Event: %s --\n", (label()?label():"none"), fl_eventnames[event]); #else #define PRINTEVENT #endif /** Handle FLTK events. */ int Fl_Table::handle(int event) { PRINTEVENT; int ret = Fl_Group::handle(event); // let FLTK group handle events first // Which row/column are we over? int R, C; // row/column being worked on ResizeFlag resizeflag; // which resizing area are we over? (0=none) TableContext context = cursor2rowcol(R, C, resizeflag); if (ret) { if (Fl::event_inside(hscrollbar) || Fl::event_inside(vscrollbar)) return 1; if ( context != CONTEXT_ROW_HEADER && // mouse not in row header (STR#2742) context != CONTEXT_COL_HEADER && // mouse not in col header (STR#2742) Fl::focus() != this && // we don't have focus? contains(Fl::focus())) { // focus is a child? return 1; } } // Make snapshots of realtime event states *before* we service user's cb, // which may do things like post popup menus that return with unexpected button states. int _event_button = Fl::event_button(); int _event_clicks = Fl::event_clicks(); int _event_x = Fl::event_x(); int _event_y = Fl::event_y(); int _event_key = Fl::event_key(); int _event_state = Fl::event_state(); Fl_Widget *_focus = Fl::focus(); switch ( event ) { case FL_PUSH: // Single left-click on table? do user's callback with CONTEXT_TABLE if (_event_button == 1 && !_event_clicks) { if (_focus == this) { take_focus(); do_callback(CONTEXT_TABLE, -1, -1); ret = 1; } damage_zone(current_row, current_col, select_row, select_col, R, C); if (context == CONTEXT_CELL) { current_row = select_row = R; current_col = select_col = C; _selecting = CONTEXT_CELL; } else { // Clear selection if not resizing row/col if ( !resizeflag ) { current_row = select_row = -1; current_col = select_col = -1; } } } // A click on table with user's callback defined? // Need this for eg. right click to pop up a menu // if ( Fl_Widget::callback() && // callback defined? resizeflag == RESIZE_NONE ) { // not resizing? do_callback(context, R, C); // do callback with context (cell, header, etc) } // Handle selection if handling a left-click // Use snapshot of _event_button we made before servicing user's cb's // to avoid checking realtime state of buttons which may have changed // during the user's callbacks. // switch ( context ) { case CONTEXT_CELL: // FL_PUSH on a cell? ret = 1; // express interest in FL_RELEASE break; case CONTEXT_NONE: // FL_PUSH on table corner? if ( _event_button == 1 && _event_x < x() + row_header_width()) { current_col = 0; select_col = cols() - 1; current_row = 0; select_row = rows() - 1; damage_zone(current_row, current_col, select_row, select_col); ret = 1; } break; case CONTEXT_COL_HEADER: // FL_PUSH on a column header? if ( _event_button == 1) { // Resizing? Handle it if ( resizeflag ) { // Start resize if left click on column border. // "ret=1" ensures we get drag events from now on. // (C-1) is used if mouse is over the left hand side // of cell, so we resize the next column on the left. // _resizing_col = ( resizeflag & RESIZE_COL_LEFT ) ? C-1 : C; _resizing_row = -1; _dragging_x = _event_x; ret = 1; } else { // Not resizing? Select the column if ( Fl::focus() != this && contains(Fl::focus()) ) return 0; // STR #3018 - item 1 current_col = select_col = C; current_row = 0; select_row = rows() - 1; _selecting = CONTEXT_COL_HEADER; damage_zone(current_row, current_col, select_row, select_col); ret = 1; } } break; case CONTEXT_ROW_HEADER: // FL_PUSH on a row header? if ( _event_button == 1 ) { // Resizing? Handle it if ( resizeflag ) { // Start resize if left mouse clicked on row border. // "ret = 1" ensures we get drag events from now on. // (R-1) is used if mouse is over the top of the cell, // so that we resize the row above. // _resizing_row = ( resizeflag & RESIZE_ROW_ABOVE ) ? R-1 : R; _resizing_col = -1; _dragging_y = _event_y; ret = 1; } else { // Not resizing? Select the row if ( Fl::focus() != this && contains(Fl::focus()) ) return 0; // STR #3018 - item 1 current_row = select_row = R; current_col = 0; select_col = cols() - 1; _selecting = CONTEXT_ROW_HEADER; damage_zone(current_row, current_col, select_row, select_col); ret = 1; } } break; default: ret = 0; // express disinterest break; } _last_row = R; break; case FL_DRAG: if (_auto_drag == 1) { ret = 1; break; } if ( _resizing_col > -1 ) { // Dragging column? // // Let user drag even /outside/ the row/col widget. // Don't allow column width smaller than 1. // Continue to show FL_CURSOR_WE at all times during drag. // int offset = _dragging_x - _event_x; int new_w = col_width(_resizing_col) - offset; if ( new_w < _col_resize_min ) new_w = _col_resize_min; col_width(_resizing_col, new_w); _dragging_x = _event_x; table_resized(); redraw(); change_cursor(FL_CURSOR_WE); ret = 1; if ( Fl_Widget::callback() && when() & FL_WHEN_CHANGED ) { do_callback(CONTEXT_RC_RESIZE, R, C); } } else if ( _resizing_row > -1 ) { // Dragging row? // // Let user drag even /outside/ the row/col widget. // Don't allow row width smaller than 1. // Continue to show FL_CURSOR_NS at all times during drag. // int offset = _dragging_y - _event_y; int new_h = row_height(_resizing_row) - offset; if ( new_h < _row_resize_min ) new_h = _row_resize_min; row_height(_resizing_row, new_h); _dragging_y = _event_y; table_resized(); redraw(); change_cursor(FL_CURSOR_NS); ret = 1; if ( Fl_Widget::callback() && when() & FL_WHEN_CHANGED ) { do_callback(CONTEXT_RC_RESIZE, R, C); } } else { if (_event_button == 1 && _selecting == CONTEXT_CELL && context == CONTEXT_CELL) { // Dragging a cell selection? if ( _event_clicks ) break; // STR #3018 - item 2 if (select_row != R || select_col != C) { damage_zone(current_row, current_col, select_row, select_col, R, C); } select_row = R; select_col = C; ret = 1; } else if (_event_button == 1 && _selecting == CONTEXT_ROW_HEADER && context & (CONTEXT_ROW_HEADER|CONTEXT_COL_HEADER|CONTEXT_CELL)) { if (select_row != R) { damage_zone(current_row, current_col, select_row, select_col, R, C); } select_row = R; ret = 1; } else if (_event_button == 1 && _selecting == CONTEXT_COL_HEADER && context & (CONTEXT_ROW_HEADER|CONTEXT_COL_HEADER|CONTEXT_CELL)) { if (select_col != C) { damage_zone(current_row, current_col, select_row, select_col, R, C); } select_col = C; ret = 1; } } // Enable autodrag if not resizing, and mouse has moved off table edge if ( _resizing_row < 0 && _resizing_col < 0 && _auto_drag == 0 && ( _event_x > x() + w() - 20 || _event_x < x() + row_header_width() || _event_y > y() + h() - 20 || _event_y < y() + col_header_height() ) ) { _start_auto_drag(); } break; case FL_RELEASE: _stop_auto_drag(); switch ( context ) { case CONTEXT_ROW_HEADER: // release on row header case CONTEXT_COL_HEADER: // release on col header case CONTEXT_CELL: // release on a cell case CONTEXT_TABLE: // release on dead zone if ( _resizing_col == -1 && // not resizing a column _resizing_row == -1 && // not resizing a row Fl_Widget::callback() && // callback defined when() & FL_WHEN_RELEASE && // on button release _last_row == R ) { // release on same row PUSHed? // Need this for eg. left clicking on a cell to select it do_callback(context, R, C); } break; default: break; } if ( _event_button == 1 ) { change_cursor(FL_CURSOR_DEFAULT); _resizing_col = -1; _resizing_row = -1; ret = 1; } break; case FL_MOVE: if ( context == CONTEXT_COL_HEADER && // in column header? resizeflag ) { // resize + near boundary? change_cursor(FL_CURSOR_WE); // show resize cursor } else if ( context == CONTEXT_ROW_HEADER && // in row header? resizeflag ) { // resize + near boundary? change_cursor(FL_CURSOR_NS); // show resize cursor } else { change_cursor(FL_CURSOR_DEFAULT); // normal cursor } ret = 1; break; case FL_ENTER: // See FLTK event docs on the FL_ENTER widget if (!ret) take_focus(); ret = 1; //FALLTHROUGH case FL_LEAVE: // We want to track the mouse if resizing is allowed. if ( resizeflag ) { ret = 1; } if ( event == FL_LEAVE ) { _stop_auto_drag(); change_cursor(FL_CURSOR_DEFAULT); } break; case FL_FOCUS: Fl::focus(this); //FALLTHROUGH case FL_UNFOCUS: _stop_auto_drag(); ret = 1; break; case FL_KEYBOARD: { ret = 0; int is_row = select_row; int is_col = select_col; switch(_event_key) { case FL_Home: ret = move_cursor(0, -1000000); break; case FL_End: ret = move_cursor(0, 1000000); break; case FL_Page_Up: ret = move_cursor(-(botrow - toprow - 1), 0); break; case FL_Page_Down: ret = move_cursor(botrow - toprow - 1 , 0); break; case FL_Left: ret = move_cursor(0, -1); break; case FL_Right: ret = move_cursor(0, 1); break; case FL_Up: ret = move_cursor(-1, 0); break; case FL_Down: ret = move_cursor(1, 0); break; case FL_Tab: if ( !tab_cell_nav() ) break; // not navigating cells? let fltk handle it (STR#2862) if ( _event_state & FL_SHIFT ) { ret = move_cursor(0, -1, 0); // shift-tab -> left } else { ret = move_cursor(0, 1, 0); // tab -> right } break; } if (ret && Fl::focus() != this) { do_callback(CONTEXT_TABLE, -1, -1); take_focus(); } //if (!ret && Fl_Widget::callback() && when() & FL_WHEN_NOT_CHANGED ) if ( Fl_Widget::callback() && ( ( !ret && when() & FL_WHEN_NOT_CHANGED ) || ( is_row!= select_row || is_col!= select_col ) ) ) { do_callback(CONTEXT_CELL, select_row, select_col); //damage_zone(current_row, current_col, select_row, select_col); ret = 1; } break; } default: change_cursor(FL_CURSOR_DEFAULT); break; } return(ret); } /** Handle resize events if user resizes parent window. This changes the size of Fl_Table, causing it to redraw. */ void Fl_Table::resize(int X, int Y, int W, int H) { // Tell group to resize, and recalc our own widget as well Fl_Group::resize(X, Y, W, H); table_resized(); redraw(); } // Draw a cell void Fl_Table::_redraw_cell(TableContext context, int r, int c) { if ( r < 0 || c < 0 ) return; int X,Y,W,H; find_cell(context, r, c, X, Y, W, H); // find positions of cell draw_cell(context, r, c, X, Y, W, H); // call users' function to draw it } /** See if the cell at row \p r and column \p c is selected. \returns 1 if the cell is selected, 0 if not. */ int Fl_Table::is_selected(int r, int c) { int s_left, s_right, s_top, s_bottom; if (select_col > current_col) { s_left = current_col; s_right = select_col; } else { s_right = current_col; s_left = select_col; } if (select_row > current_row) { s_top = current_row; s_bottom = select_row; } else { s_bottom = current_row; s_top = select_row; } if (r >= s_top && r <= s_bottom && c >= s_left && c <= s_right) { return 1; } return 0; } /** Gets the region of cells selected (highlighted). \param[in] row_top Returns the top row of selection area \param[in] col_left Returns the left column of selection area \param[in] row_bot Returns the bottom row of selection area \param[in] col_right Returns the right column of selection area */ void Fl_Table::get_selection(int& row_top, int& col_left, int& row_bot, int& col_right) { if (select_col > current_col) { col_left = current_col; col_right = select_col; } else { col_right = current_col; col_left = select_col; } if (select_row > current_row) { row_top = current_row; row_bot = select_row; } else { row_bot = current_row; row_top = select_row; } } /** Sets the region of cells to be selected (highlighted). So for instance, set_selection(0,0,0,0) selects the top/left cell in the table. And set_selection(0,0,1,1) selects the four cells in rows 0 and 1, column 0 and 1. To deselect all cells, use set_selection(-1,-1,-1,-1); \param[in] row_top Top row of selection area \param[in] col_left Left column of selection area \param[in] row_bot Bottom row of selection area \param[in] col_right Right column of selection area */ void Fl_Table::set_selection(int row_top, int col_left, int row_bot, int col_right) { damage_zone(current_row, current_col, select_row, select_col); current_col = col_left; current_row = row_top; select_col = col_right; select_row = row_bot; damage_zone(current_row, current_col, select_row, select_col); } /** Draws the entire Fl_Table. Lets fltk widgets draw themselves first, followed by the cells via calls to draw_cell(). */ void Fl_Table::draw() { int scrollsize = _scrollbar_size ? _scrollbar_size : Fl::scrollbar_size(); // Check if scrollbar size changed if ( ( vscrollbar && (scrollsize != vscrollbar->w()) ) || ( hscrollbar && (scrollsize != hscrollbar->h()) ) ) { // handle size change, min/max, table dim's, etc table_resized(); } draw_cell(CONTEXT_STARTPAGE, 0, 0, // let user's drawing routine tix, tiy, tiw, tih); // prep new page // Let fltk widgets draw themselves first. Do this after // draw_cell(CONTEXT_STARTPAGE) in case user moves widgets around. // Use window 'inner' clip to prevent drawing into table border. // (unfortunately this clips FLTK's border, so we must draw it explicitly below) // fl_push_clip(wix, wiy, wiw, wih); { Fl_Group::draw(); } fl_pop_clip(); // Explicitly draw border around widget, if any draw_box(box(), x(), y(), w(), h(), color()); // If Fl_Scroll 'table' is hidden, draw its box // Do this after Fl_Group::draw() so we draw over scrollbars // that leak around the border. // if ( ! table->visible() ) { if ( damage() & FL_DAMAGE_ALL || damage() & FL_DAMAGE_CHILD ) { draw_box(table->box(), tox, toy, tow, toh, table->color()); } } // Clip all further drawing to the inner widget dimensions fl_push_clip(wix, wiy, wiw, wih); { // Only redraw a few cells? if ( ! ( damage() & FL_DAMAGE_ALL ) && _redraw_leftcol != -1 ) { fl_push_clip(tix, tiy, tiw, tih); for ( int c = _redraw_leftcol; c <= _redraw_rightcol; c++ ) { for ( int r = _redraw_toprow; r <= _redraw_botrow; r++ ) { _redraw_cell(CONTEXT_CELL, r, c); } } fl_pop_clip(); } if ( damage() & FL_DAMAGE_ALL ) { int X,Y,W,H; // Draw row headers, if any if ( row_header() ) { get_bounds(CONTEXT_ROW_HEADER, X, Y, W, H); fl_push_clip(X,Y,W,H); for ( int r = toprow; r <= botrow; r++ ) { _redraw_cell(CONTEXT_ROW_HEADER, r, 0); } fl_pop_clip(); } // Draw column headers, if any if ( col_header() ) { get_bounds(CONTEXT_COL_HEADER, X, Y, W, H); fl_push_clip(X,Y,W,H); for ( int c = leftcol; c <= rightcol; c++ ) { _redraw_cell(CONTEXT_COL_HEADER, 0, c); } fl_pop_clip(); } // Draw all cells. // This includes cells partially obscured off edges of table. // No longer do this last; you might think it would be nice // to draw over dead zones, but on redraws it flickers. Avoid // drawing over deadzones; prevent deadzones by sizing columns. // fl_push_clip(tix, tiy, tiw, tih); { for ( int r = toprow; r <= botrow; r++ ) { for ( int c = leftcol; c <= rightcol; c++ ) { _redraw_cell(CONTEXT_CELL, r, c); } } } fl_pop_clip(); // Draw little rectangle in corner of headers if ( row_header() && col_header() ) { fl_rectf(wix, wiy, row_header_width(), col_header_height(), color()); } // Table has a boxtype? Close those few dead pixels if ( table->box() ) { if ( col_header() ) { fl_rectf(tox, wiy, Fl::box_dx(table->box()), col_header_height(), color()); } if ( row_header() ) { fl_rectf(wix, toy, row_header_width(), Fl::box_dx(table->box()), color()); } } // Table width smaller than window? Fill remainder with rectangle if ( table_w < tiw ) { fl_rectf(tix + table_w, tiy, tiw - table_w, tih, color()); // Col header? fill that too if ( col_header() ) { fl_rectf(tix + table_w, wiy, // get that corner just right.. (tiw - table_w + Fl::box_dw(table->box()) - Fl::box_dx(table->box())), col_header_height(), color()); } } // Table height smaller than window? Fill remainder with rectangle if ( table_h < tih ) { fl_rectf(tix, tiy + table_h, tiw, tih - table_h, color()); if ( row_header() ) { // NOTE: // Careful with that lower corner; don't use tih; when eg. // table->box(FL_THIN_UP_FRAME) and hscrollbar hidden, // leaves a row of dead pixels. // fl_rectf(wix, tiy + table_h, row_header_width(), (wiy+wih) - (tiy+table_h) - ( hscrollbar->visible() ? scrollsize : 0), color()); } } } // Both scrollbars? Draw little box in lower right if ( vscrollbar->visible() && hscrollbar->visible() ) { fl_rectf(vscrollbar->x(), hscrollbar->y(), vscrollbar->w(), hscrollbar->h(), color()); } draw_cell(CONTEXT_ENDPAGE, 0, 0, // let user's drawing tix, tiy, tiw, tih); // routines cleanup _redraw_leftcol = _redraw_rightcol = _redraw_toprow = _redraw_botrow = -1; } fl_pop_clip(); } /** Returns the current height of the specified row as a value in pixels. */ int Fl_Table::row_height(int row) { return((row < 0 || row >= row_size()) ? 0 : (*_rowheights)[row]); } /** Returns the current width of the specified column in pixels. */ int Fl_Table::col_width(int col) { return((col < 0 || col >= col_size()) ? 0 : (*_colwidths)[col]); } fltk-1.4.3/src/Fl_Choice.cxx0000644000175000017500000001536415004135251015744 0ustar albrechtalbrecht// // Choice widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include "flstring.h" // Emulates the Forms choice widget. This is almost exactly the same // as an Fl_Menu_Button. The only difference is the appearance of the // button: it draws the text of the current pick and a down-arrow. // The exact layout and the type of arrow can vary by FLTK scheme. // FIXME: all such variations should be implemented in the "scheme code", // hopefully in a future class derived from a base class Fl_Scheme or similar. // Albrecht void Fl_Choice::draw() { Fl_Boxtype btype = Fl::scheme() ? FL_UP_BOX // non-default uses up box : FL_DOWN_BOX; // default scheme uses down box int dx = Fl::box_dx(btype); int dy = Fl::box_dy(btype); // Arrow area int H = h() - 2 * dy; int W = 20; int X = x() + w() - W - dx; int Y = y() + dy; Fl_Rect ab(X, Y, W, H); // arrow box int active = active_r(); Fl_Color arrow_color = active ? labelcolor() : fl_inactive(labelcolor()); Fl_Color box_color = color(); // From "original" code: modify the box color *only* for the default scheme. // This is weird (why?). I believe we should either make sure that the text // color contrasts well when the text is rendered *or* we should do this for // *all* schemes. Anyway, adapting the old code... (Albrecht) if (!Fl::scheme()) { // default scheme only, see comment above if (fl_contrast(textcolor(), FL_BACKGROUND2_COLOR) == textcolor()) box_color = FL_BACKGROUND2_COLOR; else box_color = fl_lighter(color()); } // Draw the widget box draw_box(btype, box_color); // Arrow box or horizontal divider line, depending on the current scheme // Scheme: Box or divider line // ---------------------------------------- // Default (None): Arrow box (FL_UP_BOX) // gtk+, gleam, oxy: Divider line // else: Nothing (!) if (Fl::scheme()) { if (Fl::is_scheme("gtk+") || Fl::is_scheme("gleam") || Fl::is_scheme("oxy")) { // draw the divider int x1 = x() + w() - W - 2 * dx; int y1 = y() + dy; int y2 = y() + h() - dy; fl_color(fl_darker(color())); fl_yxline(x1, y1, y2); fl_color(fl_lighter(color())); fl_yxline(x1 + 1, y1, y2); } } else { // Default scheme ("None") // Draw arrow box draw_box(FL_UP_BOX, X, Y, W, H, color()); ab.inset(FL_UP_BOX); } // Draw choice arrow(s) fl_draw_arrow(ab, FL_ARROW_CHOICE, FL_ORIENT_NONE, arrow_color); W += 2 * dx; // Draw menu item's label if (mvalue()) { Fl_Menu_Item m = *mvalue(); if (active) m.activate(); else m.deactivate(); // Clip int xx = x() + dx, yy = y() + dy + 1, ww = w() - W, hh = H - 2; fl_push_clip(xx, yy, ww, hh); if (Fl::scheme()) { Fl_Label l; l.value = m.text; l.image = 0; l.deimage = 0; l.type = m.labeltype_; l.font = m.labelsize_ || m.labelfont_ ? m.labelfont_ : textfont(); l.size = m.labelsize_ ? m.labelsize_ : textsize(); l.color= m.labelcolor_ ? m.labelcolor_ : textcolor(); l.h_margin_ = l.v_margin_ = l.spacing = 0; if (!m.active()) l.color = fl_inactive((Fl_Color)l.color); fl_draw_shortcut = 2; // hack value to make '&' disappear l.draw(xx+3, yy, ww>6 ? ww-6 : 0, hh, FL_ALIGN_LEFT); fl_draw_shortcut = 0; if ( Fl::focus() == this ) draw_focus(box(), xx, yy, ww, hh); } else { fl_draw_shortcut = 2; // hack value to make '&' disappear m.draw(xx, yy, ww, hh, this, Fl::focus() == this); fl_draw_shortcut = 0; } fl_pop_clip(); } // Widget's label draw_label(); } /** Create a new Fl_Choice widget using the given position, size and label string. The default boxtype is \c FL_UP_BOX. The constructor sets menu() to NULL. See Fl_Menu_ for the methods to set or change the menu. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Choice::Fl_Choice(int X, int Y, int W, int H, const char *L) : Fl_Menu_(X,Y,W,H,L) { align(FL_ALIGN_LEFT); when(FL_WHEN_RELEASE); textfont(FL_HELVETICA); box(FL_UP_BOX); down_box(FL_BORDER_BOX); } /** Sets the currently selected value using a pointer to menu item. Changing the selected value causes a redraw(). \param[in] v pointer to menu item in the menu item array. \returns non-zero if the new value is different to the old one. */ int Fl_Choice::value(const Fl_Menu_Item *v) { if (!Fl_Menu_::value(v)) return 0; redraw(); return 1; } /** Sets the currently selected value using the index into the menu item array. Changing the selected value causes a redraw(). \param[in] v index of value in the menu item array. \returns non-zero if the new value is different to the old one. */ int Fl_Choice::value(int v) { if (v == -1) return value((const Fl_Menu_Item *)0); if (v < 0 || v >= (size() - 1)) return 0; if (!Fl_Menu_::value(v)) return 0; redraw(); return 1; } int Fl_Choice::handle(int e) { if (!menu() || !menu()->text) return 0; const Fl_Menu_Item* v; Fl_Widget_Tracker wp(this); switch (e) { case FL_ENTER: case FL_LEAVE: return 1; case FL_KEYBOARD: if (Fl::event_key() != ' ' || (Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) return 0; case FL_PUSH: if (Fl::visible_focus()) Fl::focus(this); J1: if (Fl::scheme() || fl_contrast(textcolor(), FL_BACKGROUND2_COLOR) != textcolor()) { v = menu()->pulldown(x(), y(), w(), h(), mvalue(), this); if (wp.deleted()) return 1; } else { // In order to preserve the old look-n-feel of "white" menus, // temporarily override the color() of this widget... Fl_Color c = color(); color(FL_BACKGROUND2_COLOR); v = menu()->pulldown(x(), y(), w(), h(), mvalue(), this); if (wp.deleted()) return 1; color(c); } if (!v || v->submenu()) return 1; if (v != mvalue()) redraw(); picked(v); return 1; case FL_SHORTCUT: if (Fl_Widget::test_shortcut()) goto J1; v = menu()->test_shortcut(); if (!v) return 0; if (v != mvalue()) redraw(); picked(v); return 1; case FL_FOCUS: case FL_UNFOCUS: if (Fl::visible_focus()) { redraw(); return 1; } else return 0; default: return 0; } } fltk-1.4.3/src/Fl_Gl_Window_Driver.H0000644000175000017500000001147215004135251017337 0ustar albrechtalbrecht// // Definition of class Fl_Gl_Window_Driver, and of its platform-specific derived classes // for the Fast Light Tool Kit (FLTK). // // Copyright 2016-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #ifndef Fl_Gl_Window_Driver_H #define Fl_Gl_Window_Driver_H #include #include // for GLint class Fl_Gl_Choice; class Fl_Font_Descriptor; /* The constructor of each Fl_Gl_Window object creates also an object from a platform-specific derived class from this class. */ class Fl_Gl_Window_Driver { protected: GLint current_prog; Fl_Gl_Window *pWindow; public: static Fl_Window* cached_window; static int nContext; static GLContext *context_list; static Fl_Gl_Choice *first; static int copy; static float gl_scale; static GLContext gl_start_context; Fl_Gl_Choice* g() {return pWindow->g;} void g(Fl_Gl_Choice *c) {pWindow->g = c;} int mode() {return pWindow->mode_;} void mode(int m) { pWindow->mode_ = m;} const int *alist() {return pWindow->alist;} void alist(const int *l) { pWindow->alist = l;} void* overlay() {return pWindow->overlay;} void draw_overlay() {pWindow->draw_overlay();} Fl_Gl_Window_Driver(Fl_Gl_Window *win) : pWindow(win) {current_prog=0;} virtual ~Fl_Gl_Window_Driver() {} static Fl_Gl_Window_Driver *newGlWindowDriver(Fl_Gl_Window *w); static Fl_Gl_Window_Driver *global(); virtual float pixels_per_unit() {return 1;} virtual void before_show(int&) {} virtual void after_show() {} virtual void invalidate(); virtual int mode_(int /*m*/, const int * /*a*/) {return 0;} virtual void make_current_before() {} virtual void make_current_after() {} virtual void swap_buffers() {} virtual void resize(int /*is_a_resize*/, int /*w*/, int /*h*/) {} virtual char swap_type(); virtual void swap_interval(int) { } virtual int swap_interval() const { return -1; } virtual int flush_begin(char&) {return 0;} virtual void gl_hide_before(void *&) {} // the default implementation may be enough static Fl_Gl_Choice *find_begin(int m, const int *alistp); static void add_context(GLContext ctx); static void del_context(GLContext ctx); // Return one of these structures for a given gl mode. // The second argument is a glX attribute list, and is used if mode is zero. // This is not supported on Win32: virtual Fl_Gl_Choice *find(int /*mode*/, const int * /*alistp*/) {return NULL;} virtual GLContext create_gl_context(Fl_Window*, const Fl_Gl_Choice*) {return 0;} virtual void set_gl_context(Fl_Window*, GLContext) {} virtual void delete_gl_context(GLContext) {} virtual void make_overlay(void* &o); virtual void hide_overlay() {} // the default implementation may be enough virtual void make_overlay_current() {} virtual void redraw_overlay() {} virtual int can_do_overlay() {return 0;} virtual void waitGL() {} // support for gl_finish() function virtual void gl_visual(Fl_Gl_Choice*); // support for Fl::gl_visual() function virtual void gl_start() {} // support for gl_start() function virtual void* GetProcAddress(const char *procName); // support for glutGetProcAddress() virtual void draw_string_legacy(const char* str, int n); // support for gl_draw() void draw_string_legacy_get_list(const char* str, int n); // support for gl_draw() static void draw_string_legacy_glut(const char* str, int n); // support for gl_draw() virtual void get_list(Fl_Font_Descriptor*, int) {} // support for gl_draw() without textures virtual void gl_bitmap_font(Fl_Font_Descriptor *) {} // support for gl_font() without textures virtual int overlay_color(Fl_Color) {return 0;} // support for gl_color() with HAVE_GL_OVERLAY static void draw_string_with_texture(const char* str, int n); // cross-platform // support for gl_draw(). The cross-platform version may be enough. virtual char *alpha_mask_for_string(const char *str, int n, int w, int h, Fl_Fontsize fs); virtual int genlistsize() { return 0; } // support for gl_draw() virtual Fl_Font_Descriptor** fontnum_to_fontdescriptor(int fnum); virtual Fl_RGB_Image* capture_gl_rectangle(int x, int y, int w, int h); static inline Fl_Gl_Window_Driver* driver(const Fl_Gl_Window *win) {return win->pGlWindowDriver;} // true means the platform uses glScissor() to make sure GL subwindows // don't leak outside their parent window virtual bool need_scissor() { return false; } virtual void switch_to_GL1(); virtual void switch_back(); }; #endif /* Fl_Gl_Window_Driver_H */ /** \} \endcond */ fltk-1.4.3/src/Fl_Scrollbar.cxx0000644000175000017500000001610115004135251016463 0ustar albrechtalbrecht// // Scroll bar widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include "flstring.h" #define INITIALREPEAT .5 #define REPEAT .05 void Fl_Scrollbar::increment_cb() { char inv = maximum()-ls) i = -ls; // err } break; case 6: // clicked into the box next to the slider on the right i = (int((maximum()-minimum())*slider_size()/(1.0-slider_size()))); if (inv) { if (i>ls) i = ls; } else { if (iincrement_cb(); Fl::add_timeout(REPEAT, timeout_cb, s); } int Fl_Scrollbar::handle(int event) { // area of scrollbar: int area; int X=x(); int Y=y(); int W=w(); int H=h(); // adjust slider area to be inside the arrow buttons: if (horizontal()) { if (W >= 3*H) {X += H; W -= 2*H;} } else { if (H >= 3*W) {Y += W; H -= 2*W;} } // which widget part is highlighted? int relx; int ww; if (horizontal()) { relx = Fl::event_x()-X; ww = W; } else { relx = Fl::event_y()-Y; ww = H; } if (relx < 0) area = 1; else if (relx >= ww) area = 2; else { int S = int(slider_size()*ww+.5); int T = (horizontal() ? H : W)/2+1; if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4; if (S < T) S = T; double val = (maximum()-minimum()) ? (value()-minimum())/(maximum()-minimum()) : 0.5; int sliderx; if (val >= 1.0) sliderx = ww-S; else if (val <= 0.0) sliderx = 0; else sliderx = int(val*(ww-S)+.5); if (Fl::event_button() == FL_MIDDLE_MOUSE) area = 8; else if (relx < sliderx) area = 5; else if (relx >= sliderx+S) area = 6; else area = 8; } switch (event) { case FL_ENTER: case FL_LEAVE: return 1; case FL_RELEASE: damage(FL_DAMAGE_ALL); if (pushed_) { Fl::remove_timeout(timeout_cb, this); pushed_ = 0; } handle_release(); return 1; case FL_PUSH: if (pushed_) return 1; if (area != 8) pushed_ = area; if (pushed_) { handle_push(); Fl::add_timeout(INITIALREPEAT, timeout_cb, this); increment_cb(); damage(FL_DAMAGE_ALL); return 1; } return Fl_Slider::handle(event, X,Y,W,H); case FL_DRAG: if (pushed_) return 1; return Fl_Slider::handle(event, X,Y,W,H); case FL_MOUSEWHEEL : if (horizontal()) { if (Fl::e_dx==0) return 0; int ls = maximum()>=minimum() ? linesize_ : -linesize_; handle_drag(clamp(value() + ls * Fl::e_dx)); return 1; } else { if (Fl::e_dy==0) return 0; int ls = maximum()>=minimum() ? linesize_ : -linesize_; handle_drag(clamp(value() + ls * Fl::e_dy)); return 1; } case FL_SHORTCUT: case FL_KEYBOARD: { int v = value(); int ls = maximum()>=minimum() ? linesize_ : -linesize_; if (horizontal()) { switch (Fl::event_key()) { case FL_Left: v -= ls; break; case FL_Right: v += ls; break; default: return 0; } } else { // vertical switch (Fl::event_key()) { case FL_Up: v -= ls; break; case FL_Down: v += ls; break; case FL_Page_Up: if (slider_size() >= 1.0) return 0; v -= int((maximum()-minimum())*slider_size()/(1.0-slider_size())); v += ls; break; case FL_Page_Down: if (slider_size() >= 1.0) return 0; v += int((maximum()-minimum())*slider_size()/(1.0-slider_size())); v -= ls; break; case FL_Home: v = int(minimum()); break; case FL_End: v = int(maximum()); break; default: return 0; } } v = int(clamp(v)); if (v != value()) { Fl_Slider::value(v); value_damage(); set_changed(); do_callback(FL_REASON_DRAGGED); } return 1;} } return 0; } void Fl_Scrollbar::draw() { if (damage() & FL_DAMAGE_ALL) draw_box(); int X = x() + Fl::box_dx(box()); int Y = y() + Fl::box_dy(box()); int W = w() - Fl::box_dw(box()); int H = h() - Fl::box_dh(box()); Fl_Rect ab; // arrow box int inset = 2; if (W < 8 || H < 8) inset = 1; if (horizontal()) { if (W < 3*H) { Fl_Slider::draw(X, Y, W, H); return; } Fl_Slider::draw(X+H, Y, W-2*H, H); if (damage()&FL_DAMAGE_ALL) { draw_box((pushed_==1) ? fl_down(slider()) : slider(), X, Y, H, H, selection_color()); draw_box((pushed_==2) ? fl_down(slider()) : slider(), X+W-H, Y, H, H, selection_color()); Fl_Color arrowcolor = active_r() ? labelcolor() : fl_inactive(labelcolor()); ab = Fl_Rect(X, Y, H, H); ab.inset(inset); fl_draw_arrow(ab, FL_ARROW_SINGLE, FL_ORIENT_LEFT, arrowcolor); // left arrow ab = Fl_Rect(X+W-H, Y, H, H); ab.inset(inset); fl_draw_arrow(ab, FL_ARROW_SINGLE, FL_ORIENT_RIGHT, arrowcolor); // right arrow } } else { // vertical if (H < 3*W) { Fl_Slider::draw(X, Y, W, H); return; } Fl_Slider::draw(X, Y+W, W, H-2*W); if (damage() & FL_DAMAGE_ALL) { draw_box((pushed_==1) ? fl_down(slider()) : slider(), X, Y, W, W, selection_color()); draw_box((pushed_==2) ? fl_down(slider()) : slider(), X, Y+H-W, W, W, selection_color()); Fl_Color arrowcolor = active_r() ? labelcolor() : fl_inactive(labelcolor()); ab = Fl_Rect(X, Y, W, W); ab.inset(inset); fl_draw_arrow(ab, FL_ARROW_SINGLE, FL_ORIENT_UP, arrowcolor); // up arrow ab = Fl_Rect(X, Y+H-W, W, W); ab.inset(inset); fl_draw_arrow(ab, FL_ARROW_SINGLE, FL_ORIENT_DOWN, arrowcolor); // down arrow } } } /** Creates a new Fl_Scrollbar widget with given position, size, and label. You need to do type(FL_HORIZONTAL) if you want a horizontal scrollbar. */ Fl_Scrollbar::Fl_Scrollbar(int X, int Y, int W, int H, const char* L) : Fl_Slider(X, Y, W, H, L) { box(FL_FLAT_BOX); color(FL_DARK2); slider(FL_UP_BOX); linesize_ = 16; pushed_ = 0; step(1); } /** Destroys the Scrollbar. */ Fl_Scrollbar::~Fl_Scrollbar() { if (pushed_) Fl::remove_timeout(timeout_cb, this); } fltk-1.4.3/src/freeglut_geometry.cxx0000644000175000017500000011472315004135251017660 0ustar albrechtalbrecht/* * freeglut_geometry.c * * Freeglut geometry rendering methods. * * Copyright (c) 1999-2010 Pawel W. Olszta. All Rights Reserved. * Written by Pawel W. Olszta, * Creation date: Fri Dec 3 1999 * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include /* * TODO BEFORE THE STABLE RELEASE: * * Following functions have been contributed by Andreas Umbach. * * glutWireCube() -- looks OK * glutSolidCube() -- OK * * Those functions have been implemented by John Fay. * * glutWireTorus() -- looks OK * glutSolidTorus() -- looks OK * glutWireDodecahedron() -- looks OK * glutSolidDodecahedron() -- looks OK * glutWireOctahedron() -- looks OK * glutSolidOctahedron() -- looks OK * glutWireTetrahedron() -- looks OK * glutSolidTetrahedron() -- looks OK * glutWireIcosahedron() -- looks OK * glutSolidIcosahedron() -- looks OK * * The Following functions have been updated by Nigel Stewart, based * on FreeGLUT 2.0.0 implementations: * * glutWireSphere() -- looks OK * glutSolidSphere() -- looks OK * glutWireCone() -- looks OK * glutSolidCone() -- looks OK */ /* -- INTERFACE FUNCTIONS -------------------------------------------------- */ /* * Draws a wireframed cube. Code contributed by Andreas Umbach */ void glutWireCube( GLdouble dSize ) { double size = dSize * 0.5; # define V(a,b,c) glVertex3d( a size, b size, c size ); # define N(a,b,c) glNormal3d( a, b, c ); /* PWO: I dared to convert the code to use macros... */ glBegin( GL_LINE_LOOP ); N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); glEnd(); glBegin( GL_LINE_LOOP ); N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); glEnd(); glBegin( GL_LINE_LOOP ); N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); glEnd(); glBegin( GL_LINE_LOOP ); N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); glEnd(); glBegin( GL_LINE_LOOP ); N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); glEnd(); glBegin( GL_LINE_LOOP ); N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd(); # undef V # undef N } /* * Draws a solid cube. Code contributed by Andreas Umbach */ void glutSolidCube( GLdouble dSize ) { double size = dSize * 0.5; # define V(a,b,c) glVertex3d( a size, b size, c size ); # define N(a,b,c) glNormal3d( a, b, c ); /* PWO: Again, I dared to convert the code to use macros... */ glBegin( GL_QUADS ); N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd(); # undef V # undef N } /* * Compute lookup table of cos and sin values forming a cirle * * Notes: * It is the responsibility of the caller to free these tables * The size of the table is (n+1) to form a connected loop * The last entry is exactly the same as the first * The sign of n can be flipped to get the reverse loop */ static void fghCircleTable(double **sint,double **cost,const int n) { int i; /* Table size, the sign of n flips the circle direction */ const int size = abs(n); /* Determine the angle between samples */ const double angle = 2*M_PI/(double)( ( n == 0 ) ? 1 : n ); /* Allocate memory for n samples, plus duplicate of first entry at the end */ *sint = (double *) calloc(sizeof(double), size+1); *cost = (double *) calloc(sizeof(double), size+1); /* Bail out if memory allocation fails, fgError never returns */ if (!(*sint) || !(*cost)) { if (*sint) free(*sint); if (*cost) free(*cost); return; } /* Compute cos and sin around the circle */ (*sint)[0] = 0.0; (*cost)[0] = 1.0; for (i=1; i0)?1:0]; r0 = 0.0; r1 = sint2[(stacks>0)?1:0]; glBegin(GL_TRIANGLE_FAN); glNormal3d(0,0,1); glVertex3d(0,0,radius); for (j=slices; j>=0; j--) { glNormal3d(cost1[j]*r1, sint1[j]*r1, z1 ); glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius); } glEnd(); /* Cover each stack with a quad strip, except the top and bottom stacks */ for( i=1; i 0 ) ? stacks : 1 ); const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 ); /* Scaling factors for vertex normals */ const double cosn = ( height / sqrt ( height * height + base * base )); const double sinn = ( base / sqrt ( height * height + base * base )); /* Pre-computed circle */ double *sint,*cost; fghCircleTable(&sint,&cost,-slices); /* Cover the circular base with a triangle fan... */ z0 = 0.0; z1 = zStep; r0 = base; r1 = r0 - rStep; glBegin(GL_TRIANGLE_FAN); glNormal3d(0.0,0.0,-1.0); glVertex3d(0.0,0.0, z0 ); for (j=0; j<=slices; j++) glVertex3d(cost[j]*r0, sint[j]*r0, z0); glEnd(); /* Cover each stack with a quad strip, except the top stack */ for( i=0; i 0 ) ? stacks : 1 ); const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 ); /* Scaling factors for vertex normals */ const double cosn = ( height / sqrt ( height * height + base * base )); const double sinn = ( base / sqrt ( height * height + base * base )); /* Pre-computed circle */ double *sint,*cost; fghCircleTable(&sint,&cost,-slices); /* Draw the stacks... */ for (i=0; i 0 ) ? stacks : 1 ); /* Pre-computed circle */ double *sint,*cost; fghCircleTable(&sint,&cost,-slices); /* Cover the base and top */ glBegin(GL_TRIANGLE_FAN); glNormal3d(0.0, 0.0, -1.0 ); glVertex3d(0.0, 0.0, 0.0 ); for (j=0; j<=slices; j++) glVertex3d(cost[j]*radius, sint[j]*radius, 0.0); glEnd(); glBegin(GL_TRIANGLE_FAN); glNormal3d(0.0, 0.0, 1.0 ); glVertex3d(0.0, 0.0, height); for (j=slices; j>=0; j--) glVertex3d(cost[j]*radius, sint[j]*radius, height); glEnd(); /* Do the stacks */ z0 = 0.0; z1 = zStep; for (i=1; i<=stacks; i++) { if (i==stacks) z1 = height; glBegin(GL_QUAD_STRIP); for (j=0; j<=slices; j++ ) { glNormal3d(cost[j], sint[j], 0.0 ); glVertex3d(cost[j]*radius, sint[j]*radius, z0 ); glVertex3d(cost[j]*radius, sint[j]*radius, z1 ); } glEnd(); z0 = z1; z1 += zStep; } /* Release sin and cos tables */ free(sint); free(cost); } /* * Draws a wire cylinder */ void glutWireCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks) { int i,j; /* Step in z and radius as stacks are drawn. */ double z = 0.0; const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 ); /* Pre-computed circle */ double *sint,*cost; fghCircleTable(&sint,&cost,-slices); /* Draw the stacks... */ for (i=0; i<=stacks; i++) { if (i==stacks) z = height; glBegin(GL_LINE_LOOP); for( j=0; j #include #include /** Creates a new Fl_Round_Button widget using the given position, size, and label string. \image html Fl_Round_Button.png \image latex Fl_Round_Button.png " Fl_Round_Button" width=4cm The Fl_Round_Button subclass displays the "ON" state by turning on a light, rather than drawing pushed in. The default box type is FL_NO_BOX, which draws the label w/o a box right of the checkmark. The shape of the "light" is set with down_box() and its default value is FL_ROUND_DOWN_BOX. The color of the light when on is controlled with selection_color(), which defaults to FL_FOREGROUND_COLOR (usually black). \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Round_Button::Fl_Round_Button(int X,int Y,int W,int H, const char *L) : Fl_Light_Button(X,Y,W,H,L) { box(FL_NO_BOX); down_box(FL_ROUND_DOWN_BOX); selection_color(FL_FOREGROUND_COLOR); } /** Creates a new Fl_Radio_Button widget using the given position, size, and label string. The button type() is set to FL_RADIO_BUTTON. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Radio_Round_Button::Fl_Radio_Round_Button(int X,int Y,int W,int H,const char *L) : Fl_Round_Button(X,Y,W,H,L) { type(FL_RADIO_BUTTON); } fltk-1.4.3/src/ew_mask.xbm0000644000175000017500000000052515004135251015534 0ustar albrechtalbrecht#define ew_mask_width 16 #define ew_mask_height 16 #define ew_mask_x_hot 8 #define ew_mask_y_hot 8 static unsigned char ew_mask_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; fltk-1.4.3/src/up.xbm0000644000175000017500000000042615004135251014532 0ustar albrechtalbrecht#define up_width 16 #define up_height 16 static unsigned char up_bits[] = { 0x00, 0x00, 0x78, 0x00, 0x84, 0x00, 0x02, 0x01, 0x31, 0xfe, 0x79, 0x80, 0xfd, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x31, 0x80, 0x01, 0x80, 0x01, 0x80, 0xff, 0xff, 0x00, 0x00}; fltk-1.4.3/src/fl_oxy.cxx0000644000175000017500000004130615004135251015424 0ustar albrechtalbrecht// // "Oxy" Scheme drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 2011 by Dmitrij K. aka "kdiman" // Copyright 2012-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please report all bugs and problems on the following page: // // https://www.fltk.org/str.php // #include #include #include #include "fl_oxy.h" // Note: // // Drawing on the X11 platform w/o Cairo can be asymmetric for some "arrows" #define GROFF 0.45f // gradients offset #ifndef DEBUG_OXY_ARROW #define DEBUG_OXY_ARROW 0 // 0 = off, 1 = cross at center position of arrows #endif // Draw a single arrow static void single_arrow(Fl_Rect bb, Fl_Orientation o, Fl_Color col) { int x1 = bb.x(); int y1 = bb.y(); int w1 = bb.w(); int h1 = bb.h(); float angle = int(o) * 45.0f; // calculate arrow size int dx = (w1 - 3) / 2; if (h1 < w1) dx = (h1 - 3) / 2; if (dx > 4) dx = 4; else if (dx < 2) dx = 2; // dx = (dx + 1) & (-2); // should be even ? not required int tx = x1 + w1/2; int ty = y1 + h1/2; const int lw = 2; // arrow line width: n+1 pixels (must be even) const int dw = 1; // half the line width fl_color(col); fl_line_style(FL_SOLID, 1); fl_push_matrix(); fl_translate(tx, ty); // move to center fl_rotate(angle); // rotate by given angle // DEBUG: Draw a two-colored cross at the center of the arrow box // This can be used to debug or adjust array alignment (centering) #if (DEBUG_OXY_ARROW) // draw a cross at the center int ll; // line length fl_color(FL_BLUE); // "horizontal" line ll = (o&2) ? h1/2 - 1 : w1/2 - 1; // line length fl_begin_line(); fl_vertex(-ll, 0); fl_vertex(ll, 0); fl_end_line(); fl_color(0x22882200); // "vertical" line ll = (o&2) ? w1/2 - 1 : h1/2 - 1; // line length fl_begin_line(); fl_vertex(0, -ll); fl_vertex(0, ll); fl_end_line(); fl_color(col); // back to original color #endif // Draw the "arrow", similar to '>' at the center of the box fl_begin_complex_polygon(); fl_vertex(-dx + dw, -dx); fl_vertex( 0 + dw, 0); fl_vertex(-dx + dw, dx); fl_vertex(-dx + dw + lw, dx); fl_vertex( 0 + dw + lw, 0); fl_vertex(-dx + dw + lw, -dx); fl_end_complex_polygon(); fl_pop_matrix(); fl_line_style(0); } /** Draw an "arrow" GUI element for the 'oxy' scheme. This draws one or two "arrows" depending on the arrow type \p t. \param[in] bb bounding box \param[in] t arrow type \param[in] o orientation \param[in] col arrow color */ void oxy_arrow(Fl_Rect bb, Fl_Arrow_Type t, Fl_Orientation o, Fl_Color col) { switch(t) { case FL_ARROW_DOUBLE: switch (int(o)) { case FL_ORIENT_DOWN: case FL_ORIENT_UP: bb.h(bb.h() - 4); // reduce size single_arrow(bb, o, col); bb.y(bb.y() + 4); // shift down single_arrow(bb, o, col); break; default: bb.w(bb.w() - 4); // reduce size single_arrow(bb, o, col); bb.x(bb.x() + 4); // shift right single_arrow(bb, o, col); break; } break; case FL_ARROW_CHOICE: bb.y(bb.y() - 1); // shift upwards bb.h(bb.h() - 4); // reduce height single_arrow(bb, FL_ORIENT_UP, col); bb.y(bb.y() + 6); // shift down single_arrow(bb, FL_ORIENT_DOWN, col); break; default: single_arrow(bb, o, col); break; } } // draw gradient from South to North static void _oxy_up_box_(int x, int y, int w, int h, Fl_Color bg) { float groff = GROFF; if (groff < 0.0) { groff = 0.0f; } float gradoffset = groff; float stepoffset = (1.0f / (float)h); int xw = x + w - 1; // from bottom to top for (int _y = y; _y < y + h; _y++) { fl_color(fl_color_average(bg, FL_WHITE, (gradoffset < 1.0f) ? gradoffset : 1.0f)); fl_xyline(x, _y, xw); gradoffset += stepoffset; } } // draw gradient from North to South static void _oxy_down_box_(int x, int y, int w, int h, Fl_Color bg) { float groff = GROFF; if (groff < 0.0) { groff = 0.0f; } float gradoffset = groff; float stepoffset = (1.0f / (float)h); int xw = x + w - 1; // from top to bottom for (int _y = y + h - 1; _y >= y; _y--) { fl_color(fl_color_average(bg, FL_WHITE, (gradoffset < 1.0f) ? gradoffset : 1.0f)); fl_xyline(x, _y, xw); gradoffset += stepoffset; } } // draw gradient for button up box static void _oxy_button_up_box_(int x, int y, int w, int h, Fl_Color bg) { int half_h = h / 2; float gradoffset = 0.15f; float stepoffset = (1.0f / (float)half_h); Fl_Color col = fl_color_average(bg, FL_WHITE, 0.5); int xw = x + w - 1; for (int _y = y; _y <= y + half_h; _y++) { fl_color(fl_color_average(col, FL_WHITE, (gradoffset < 1.0f) ? gradoffset : 1.0f)); fl_xyline(x, _y, xw); gradoffset += stepoffset; } gradoffset = 0.0f; col = bg; for (int _y = y + h - 1; _y >= y + half_h - 1; _y--) { fl_color(fl_color_average(col, FL_WHITE, (gradoffset < 1.0f) ? gradoffset : 1.0f)); fl_xyline(x, _y, xw); gradoffset += stepoffset; } } // draw gradient for button down box static void _oxy_button_down_box_(int x, int y, int w, int h, Fl_Color bg) { bg = fl_color_average(bg, FL_BLACK, 0.88f); int half_h = h / 2, xw = x + w - 1; float gradoffset = 0.15f, stepoffset = (1.0f / (float)half_h); Fl_Color col = fl_color_average(bg, FL_WHITE, 0.5); for (int _y = y; _y <= y + half_h; _y++) { fl_color(fl_color_average(col, FL_WHITE, (gradoffset < 1.0f) ? gradoffset : 1.0f)); fl_xyline(x, _y, xw); gradoffset += stepoffset; } gradoffset = 0.0f; col = bg; for (int _y = y + h - 1; _y >= y + half_h - 1; _y--) { fl_color(fl_color_average(col, FL_WHITE, (gradoffset < 1.0f) ? gradoffset : 1.0f)); fl_xyline(x, _y, xw); gradoffset += stepoffset; } } // draw rounded box static void _oxy_rounded_box_(int x, int y, int w, int h, Fl_Color bg) { fl_color(bg); if (w > h) { fl_pie(x, y, h, h, 90.0, 270.0); // right half of circle fl_rectf(x + h / 2, y, w - h + 1, h); // rectangle between left and right half-circle fl_pie(x + w - h, y, h, h, 0.0, 90.0); // top-left quarter of circle fl_pie(x + w - h, y, h, h, 270.0, 360.0); // bottom-left quarter of circle } else if (w == h) { fl_pie(x, y, w, w, 0.0, 360.0); } else { fl_pie(x, y, w, w, 0.0, 180.0); // top half of circle fl_rectf(x, y + w / 2, w, h - w + 1); // rectangle between top and bottom half-circle fl_pie(x, y + h - w, w, w, 180.0, 360.0); // bottom half of circle } } static Fl_Color oxy_color(Fl_Color col) { if (Fl::draw_box_active()) { return col; } else { return fl_inactive(col); } } static void oxy_draw(int x, int y, int w, int h, Fl_Color col, int typebox, bool is_shadow) { if (w < 1 || h < 1) return; int X, Y, W, H, X1, Y1; // draw bg if (typebox != _FL_OXY_UP_FRAME && typebox != _FL_OXY_DOWN_FRAME) { X = x + 1; Y = y + 1; W = w - 2; H = h - 2; switch (typebox) { case _FL_OXY_UP_BOX: { _oxy_up_box_(X, Y, W, H, oxy_color(col)); break; } case _FL_OXY_DOWN_BOX: { _oxy_down_box_(X, Y, W, H, oxy_color(col)); break; } case _FL_OXY_BUTTON_UP_BOX: { _oxy_button_up_box_(X, Y, W, H, oxy_color(col)); break; } case _FL_OXY_BUTTON_DOWN_BOX: { _oxy_button_down_box_(X, Y, W, H, oxy_color(col)); break; } case _FL_OXY_ROUND_UP_BOX: case _FL_OXY_ROUND_DOWN_BOX: _oxy_rounded_box_(x, y, w, h, oxy_color(fl_color_average(col, FL_WHITE, 0.82f))); break; default: { break; } } } Fl_Color leftline = col, topline = col, rightline = col, bottomline = col; if (typebox == _FL_OXY_ROUND_UP_BOX || typebox == _FL_OXY_ROUND_DOWN_BOX) { leftline = fl_color_average(col, FL_WHITE, 0.88f); leftline = topline = rightline = bottomline = fl_color_average(leftline, FL_BLACK, 0.97f); } else if (typebox == _FL_OXY_UP_BOX || typebox == _FL_OXY_UP_FRAME) { topline = fl_color_average(col, FL_BLACK, 0.95f); leftline = fl_color_average(col, FL_BLACK, 0.85f); rightline = leftline; bottomline = fl_color_average(col, FL_BLACK, 0.88f); } else if (typebox == _FL_OXY_DOWN_BOX || typebox == _FL_OXY_DOWN_FRAME) { topline = fl_color_average(col, FL_BLACK, 0.88f); leftline = fl_color_average(col, FL_BLACK, 0.85f); rightline = leftline; bottomline = fl_color_average(col, FL_BLACK, 0.95f); } else if (typebox == _FL_OXY_BUTTON_UP_BOX || typebox == _FL_OXY_BUTTON_DOWN_BOX) { topline = leftline = rightline = bottomline = fl_color_average(col, FL_BLACK, 0.85f); } // draw border if (typebox != _FL_OXY_ROUND_UP_BOX && typebox != _FL_OXY_ROUND_DOWN_BOX) { // bottom side fl_color(oxy_color(bottomline)); fl_line(x + 1, y + h - 1, x + w - 2, y + h - 1); // right side fl_color(oxy_color(rightline)); fl_line(x + w - 1, y + 1, x + w - 1, y + h - 2); // top side fl_color(oxy_color(topline)); fl_line(x + 1, y, x + w - 2, y); // left side fl_color(oxy_color(leftline)); fl_line(x, y + 1, x, y + h - 2); } // draw shadow if (is_shadow) { if (typebox == _FL_OXY_ROUND_UP_BOX) { topline = fl_color_average(col, FL_WHITE, 0.35f); bottomline = fl_color_average(col, FL_BLACK, 0.94f); } else if (typebox == _FL_OXY_ROUND_DOWN_BOX) { topline = fl_color_average(col, FL_BLACK, 0.94f); bottomline = fl_color_average(col, FL_WHITE, 0.35f); } else if (typebox == _FL_OXY_UP_BOX || typebox == _FL_OXY_UP_FRAME) { topline = fl_color_average(col, FL_WHITE, 0.35f); leftline = fl_color_average(col, FL_WHITE, 0.4f); rightline = leftline; bottomline = fl_color_average(col, FL_BLACK, 0.8f); } else if (typebox == _FL_OXY_DOWN_BOX || typebox == _FL_OXY_DOWN_FRAME) { topline = fl_color_average(col, FL_BLACK, 0.8f); leftline = fl_color_average(col, FL_BLACK, 0.94f); rightline = leftline; bottomline = fl_color_average(col, FL_WHITE, 0.35f); } int xw1 = x + w - 1; int xw2 = x + w - 2; int xw3 = x + w - 3; int yh2 = y + h - 2; int yh1 = y + h - 1; if (typebox == _FL_OXY_UP_BOX || typebox == _FL_OXY_UP_FRAME) { fl_color(oxy_color(topline)); X = x + 1; Y = y + 1; X1 = xw2; Y1 = y + 1; fl_line(X, Y, X1, Y1); // top line fl_color(oxy_color(leftline)); X = x + 1; Y = yh2; X1 = x + 1; Y1 = y + 2; fl_line(X, Y, X1, Y1); // left line fl_color(oxy_color(rightline)); X = xw2; Y = y + 2; X1 = xw2; Y1 = yh2; fl_line(X, Y, X1, Y1); // right line fl_color(oxy_color(bottomline)); X = xw2; Y = yh2; X1 = x + 1; Y1 = yh2; fl_line(X, Y, X1, Y1); // bottom line } else if (typebox == _FL_OXY_DOWN_BOX || typebox == _FL_OXY_DOWN_FRAME) { fl_color(oxy_color(topline)); X = x + 1; Y = y + 1; X1 = xw2; Y1 = y + 1; fl_line(X, Y, X1, Y1); // top line fl_color(oxy_color(leftline)); X = x + 1; Y = yh2; X1 = x + 1; Y1 = y + 2; fl_line(X, Y, X1, Y1); // left line fl_color(oxy_color(rightline)); X = xw2; Y = y + 2; X1 = xw2; Y1 = yh2; fl_line(X, Y, X1, Y1); // right line fl_color(oxy_color(bottomline)); X = xw3; Y = yh2; X1 = x + 2; Y1 = yh2; fl_line(X, Y, X1, Y1); // bottom line } else if (typebox == _FL_OXY_ROUND_UP_BOX || typebox == _FL_OXY_ROUND_DOWN_BOX) { int Radius, smooth; int r_offset2; // quarter of smooth and half of smooth if (w > h) { smooth = w; } else { smooth = h; } // correcting `smooth' if (smooth > 0 && (smooth * 3 > w || smooth * 3 > h)) { if (h < w) { smooth = h / 3; } else { smooth = w / 3; } } r_offset2 = smooth / 2; Radius = smooth * 3; if (Radius == 3) { Radius = 4; } fl_color(oxy_color(topline)); fl_line(x + 1, yh1 - smooth - r_offset2, x + 1, y + r_offset2 + smooth); // left side fl_arc(x + 1, y + 1, Radius, Radius, 90.0, 180.0); // left-top corner if (typebox == _FL_OXY_ROUND_DOWN_BOX) { fl_arc(x + 1, y + 1, Radius + 1, Radius + 1, 90.0, 180.0); } // left-top corner (DOWN_BOX) fl_line(x + smooth + r_offset2, y + 1, xw1 - smooth - r_offset2, y + 1); // top side fl_arc(xw1 - Radius, y + 1, Radius, Radius, 00.0, 90.0); // right-top corner if (typebox == _FL_OXY_ROUND_DOWN_BOX) { fl_arc(xw1 - Radius, y + 1, Radius + 1, Radius + 1, 00.0, 90.0); } // right-top corner (DOWN_BOX) fl_line(xw2, y + smooth + r_offset2, xw2, yh1 - smooth - r_offset2); // right side fl_arc(x + 1, yh1 - Radius, Radius, Radius, 180.0, 200.0); // left-bottom corner fl_arc(xw1 - Radius, yh1 - Radius, Radius, Radius, 340.0, 360.0); // right-bottom fl_color(oxy_color(bottomline)); fl_arc(x + 1, yh1 - Radius, Radius, Radius, 200.0, 270.0); // left-bottom corner if (typebox == _FL_OXY_ROUND_UP_BOX) { fl_arc(x + 1, yh1 - Radius, Radius + 1, Radius + 1, 200.0, 270.0); } // left-bottom corner (UP_BOX) fl_line(xw1 - smooth - r_offset2, yh2, x + smooth + r_offset2, yh2); // bottom side fl_arc(xw1 - Radius, yh1 - Radius, Radius, Radius, 270.0, 340.0); // right-bottom corner if (typebox == _FL_OXY_ROUND_UP_BOX) { fl_arc(xw1 - Radius, yh1 - Radius, Radius + 1, Radius + 1, 270.0, 340.0); } // right-bottom corner } } // end `if (is_shadow)' } // end `static void oxy_draw(...)' void button_up_box(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_BUTTON_UP_BOX, true); } void button_down_box(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_BUTTON_DOWN_BOX, true); } void up_box(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_UP_BOX, true); } void down_box(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_DOWN_BOX, true); } void thin_up_box(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_UP_BOX, false); } void thin_down_box(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_DOWN_BOX, false); } void up_frame(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_UP_FRAME, true); } void down_frame(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_DOWN_FRAME, true); } void thin_up_frame(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_UP_FRAME, false); } void thin_down_frame(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_DOWN_FRAME, false); } void round_up_box(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_ROUND_UP_BOX, true); } void round_down_box(int x, int y, int w, int h, Fl_Color col) { oxy_draw(x, y, w, h, col, _FL_OXY_ROUND_DOWN_BOX, true); } extern void fl_round_focus(Fl_Boxtype bt, int x, int y, int w, int h, Fl_Color fg, Fl_Color bg); extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*, Fl_Box_Draw_Focus_F* =NULL); Fl_Boxtype fl_define_FL_OXY_UP_BOX() { fl_internal_boxtype(_FL_OXY_UP_BOX, up_box); fl_internal_boxtype(_FL_OXY_DOWN_BOX, down_box); fl_internal_boxtype(_FL_OXY_UP_FRAME, up_frame); fl_internal_boxtype(_FL_OXY_DOWN_FRAME, down_frame); fl_internal_boxtype(_FL_OXY_THIN_UP_BOX, thin_up_box); fl_internal_boxtype(_FL_OXY_THIN_DOWN_BOX, thin_down_box); fl_internal_boxtype(_FL_OXY_THIN_UP_FRAME, thin_up_frame); fl_internal_boxtype(_FL_OXY_THIN_DOWN_FRAME, thin_down_frame); fl_internal_boxtype(_FL_OXY_ROUND_UP_BOX, round_up_box, fl_round_focus); fl_internal_boxtype(_FL_OXY_ROUND_DOWN_BOX, round_down_box, fl_round_focus); fl_internal_boxtype(_FL_OXY_BUTTON_UP_BOX, button_up_box); fl_internal_boxtype(_FL_OXY_BUTTON_DOWN_BOX, button_down_box); return _FL_OXY_UP_BOX; } fltk-1.4.3/src/Fl_Screen_Driver.cxx0000644000175000017500000007075515004135251017311 0ustar albrechtalbrecht// // All screen related calls in a driver style class. // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include "Fl_Screen_Driver.H" #include #include #include #include #include #include #include "Fl_Window_Driver.H" #include #include #include #include // for memchr // these are set by Fl::args() and override any system colors: from Fl_get_system_colors.cxx extern const char *fl_fg; extern const char *fl_bg; extern const char *fl_bg2; // end of extern additions workaround char Fl_Screen_Driver::bg_set = 0; char Fl_Screen_Driver::bg2_set = 0; char Fl_Screen_Driver::fg_set = 0; Fl_System_Driver *Fl_Screen_Driver::system_driver = NULL; const int Fl_Screen_Driver::fl_NoValue = 0x0000; const int Fl_Screen_Driver::fl_WidthValue = 0x0004; const int Fl_Screen_Driver::fl_HeightValue = 0x0008; const int Fl_Screen_Driver::fl_XValue = 0x0001; const int Fl_Screen_Driver::fl_YValue = 0x0002; const int Fl_Screen_Driver::fl_XNegative = 0x0010; const int Fl_Screen_Driver::fl_YNegative = 0x0020; // This default key table is used for all system drivers that don't define // and/or use their own table. It is defined here "static" and assigned // in the constructor to avoid static initialization race conditions. // // As of January 2022, the Windows and Wayland platforms use this table. // X11 does not use a key table at all; macOS has its own table. // Platforms that use their own key tables must assign them in their // constructors (which overwrites the pointer and size). static Fl_Screen_Driver::Keyname default_key_table[] = { {' ', "Space"}, {FL_BackSpace, "Backspace"}, {FL_Tab, "Tab"}, {0xff0b/*XK_Clear*/, "Clear"}, {FL_Enter, "Enter"}, // X says "Enter" {FL_Pause, "Pause"}, {FL_Scroll_Lock, "Scroll_Lock"}, {FL_Escape, "Escape"}, {FL_Home, "Home"}, {FL_Left, "Left"}, {FL_Up, "Up"}, {FL_Right, "Right"}, {FL_Down, "Down"}, {FL_Page_Up, "Page_Up"}, // X says "Prior" {FL_Page_Down, "Page_Down"}, // X says "Next" {FL_End, "End"}, {FL_Print, "Print"}, {FL_Insert, "Insert"}, {FL_Menu, "Menu"}, {FL_Num_Lock, "Num_Lock"}, {FL_KP_Enter, "KP_Enter"}, {FL_Shift_L, "Shift_L"}, {FL_Shift_R, "Shift_R"}, {FL_Control_L, "Control_L"}, {FL_Control_R, "Control_R"}, {FL_Caps_Lock, "Caps_Lock"}, {FL_Meta_L, "Meta_L"}, {FL_Meta_R, "Meta_R"}, {FL_Alt_L, "Alt_L"}, {FL_Alt_R, "Alt_R"}, {FL_Delete, "Delete"} }; int Fl_Screen_Driver::keyboard_screen_scaling = 1; Fl_Screen_Driver::Fl_Screen_Driver() : num_screens(-1), text_editor_extra_key_bindings(NULL) { // initialize default key table (used in fl_shortcut.cxx) key_table = default_key_table; key_table_size = sizeof(default_key_table)/sizeof(*default_key_table); } Fl_Screen_Driver::~Fl_Screen_Driver() { } int Fl_Screen_Driver::visual(int) { // blank return 1; } void Fl_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) { screen_xywh(X, Y, W, H, screen_num(mx, my)); } void Fl_Screen_Driver::screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my) { screen_work_area(X, Y, W, H, screen_num(mx, my)); } int Fl_Screen_Driver::screen_count() { if (num_screens < 0) init(); return num_screens ? num_screens : 1; } void Fl_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh) { screen_xywh(X, Y, W, H, screen_num(mx, my, mw, mh)); } int Fl_Screen_Driver::screen_num(int x, int y) { int screen = 0; if (num_screens < 0) init(); for (int i = 0; i < num_screens; i ++) { int sx, sy, sw, sh; screen_xywh(sx, sy, sw, sh, i); if ((x >= sx) && (x < (sx+sw)) && (y >= sy) && (y < (sy+sh))) { screen = i; break; } } return screen; } // Return the number of pixels common to the two rectangular areas float Fl_Screen_Driver::fl_intersection(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) { if(x1+w1 < x2 || x2+w2 < x1 || y1+h1 < y2 || y2+h2 < y1) return 0.; int int_left = x1 > x2 ? x1 : x2; int int_right = x1+w1 > x2+w2 ? x2+w2 : x1+w1; int int_top = y1 > y2 ? y1 : y2; int int_bottom = y1+h1 > y2+h2 ? y2+h2 : y1+h1; return (float)(int_right - int_left) * (int_bottom - int_top); } int Fl_Screen_Driver::screen_num(int x, int y, int w, int h) { int best_screen = 0; float best_intersection = 0.; if (num_screens < 0) init(); for (int i = 0; i < num_screens; i++) { int sx = 0, sy = 0, sw = 0, sh = 0; screen_xywh(sx, sy, sw, sh, i); float sintersection = fl_intersection(x, y, w, h, sx, sy, sw, sh); if (sintersection > best_intersection) { best_screen = i; best_intersection = sintersection; } } return best_screen; } static void getsyscolor(const char* arg, void (*func)(uchar,uchar,uchar)) { if (arg && *arg) { uchar r,g,b; if (!fl_parse_color(arg, r,g,b)) Fl::error("Unknown color: %s", arg); else func(r,g,b); } } static void set_selection_color(uchar r, uchar g, uchar b) { Fl::set_color(FL_SELECTION_COLOR,r,g,b); } void Fl_Screen_Driver::get_system_colors() { if (!bg2_set) getsyscolor(fl_bg2, Fl::background2); if (!fg_set) getsyscolor(fl_fg, Fl::foreground); if (!bg_set) getsyscolor(fl_bg, Fl::background); getsyscolor(0, set_selection_color); } const char *Fl_Screen_Driver::get_system_scheme() { return fl_getenv("FLTK_SCHEME"); } /** The bullet character used by default by Fl_Secret_Input */ int Fl_Screen_Driver::secret_input_character = 0x2022; void Fl_Screen_Driver::compose_reset() { Fl::compose_state = 0; } void Fl_Screen_Driver::write_image_inside(Fl_RGB_Image *to, Fl_RGB_Image *from, int to_x, int to_y) /* Copy the image "from" inside image "to" with its top-left angle at coordinates to_x, to_y. Image depths can differ between "to" and "from". */ { int to_ld = (to->ld() == 0? to->w() * to->d() : to->ld()); int from_ld = (from->ld() == 0? from->w() * from->d() : from->ld()); uchar *tobytes = (uchar*)to->array + to_y * to_ld + to_x * to->d(); const uchar *frombytes = from->array; int need_alpha = (from->d() == 3 && to->d() == 4); for (int i = 0; i < from->h(); i++) { if (from->d() == to->d()) memcpy(tobytes, frombytes, from->w() * from->d()); else { for (int j = 0; j < from->w(); j++) { memcpy(tobytes + j * to->d(), frombytes + j * from->d(), from->d()); if (need_alpha) *(tobytes + j * to->d() + 3) = 0xff; } } tobytes += to_ld; frombytes += from_ld; } } /* Captures rectangle x,y,w,h from a mapped window or GL window. All sub-GL-windows that intersect x,y,w,h, and their subwindows, are also captured. Arguments when this function is initially called: g: a window or GL window x,y,w,h: a rectangle in window g's coordinates full_img: NULL Arguments when this function recursively calls itself: g: an Fl_Group x,y,w,h: a rectangle in g's coordinates if g is a window, or in g's parent window coords if g is a group full_img: NULL, or a previously captured image that encompasses the x,y,w,h rectangle and that will be partially overwritten with the new capture Return value: An Fl_RGB_Image*, the depth of which is platform-dependent, containing the captured pixels, or NULL if capture failed. */ Fl_RGB_Image *Fl_Screen_Driver::traverse_to_gl_subwindows(Fl_Group *g, int x, int y, int w, int h, Fl_RGB_Image *full_img) { bool captured_subwin = false; if ( g->as_gl_window() ) { Fl_Device_Plugin *plugin = Fl_Device_Plugin::opengl_plugin(); if (!plugin) return full_img; full_img = plugin->rectangle_capture(g, x, y, w, h); } else if ( g->as_window() ) { full_img = Fl::screen_driver()->read_win_rectangle(x, y, w, h, g->as_window(), true, &captured_subwin); } if (!full_img) return NULL; float full_img_scale = (full_img && w > 0 ? float(full_img->data_w())/w : 1); int n = (captured_subwin ? 0 : g->children()); for (int i = 0; i < n; i++) { Fl_Widget *c = g->child(i); if ( !c->visible() || !c->as_group()) continue; if ( c->as_window() ) { int origin_x = x; // compute intersection of x,y,w,h and the c window if (x < c->x()) origin_x = c->x(); int origin_y = y; if (y < c->y()) origin_y = c->y(); int maxi = x + w; if (maxi > c->x() + c->w()) maxi = c->x() + c->w(); int width = maxi - origin_x; maxi = y + h; if (maxi > c->y() + c->h()) maxi = c->y() + c->h(); int height = maxi - origin_y; if (width > 0 && height > 0) { Fl_RGB_Image *img = traverse_to_gl_subwindows(c->as_window(), origin_x - c->x(), origin_y - c->y(), width, height, full_img); if (img == full_img) continue; write_image_inside(full_img, img, int((origin_x - x) * full_img_scale), int((origin_y - y) * full_img_scale)); delete img; } } else traverse_to_gl_subwindows(c->as_group(), x, y, w, h, full_img); } return full_img; } int Fl_Screen_Driver::input_widget_handle_key(int key, unsigned mods, unsigned shift, Fl_Input *input) { switch (key) { case FL_Delete: { int selected = (input->insert_position() != input->mark()) ? 1 : 0; if (mods==0 && shift && selected) return input->kf_copy_cut(); // Shift-Delete with selection (WP,NP,WOW,GE,KE,OF) if (mods==0 && shift && !selected) return input->kf_delete_char_right(); // Shift-Delete no selection (WP,NP,WOW,GE,KE,!OF) if (mods==0) return input->kf_delete_char_right(); // Delete (Standard) if (mods==FL_CTRL) return input->kf_delete_word_right(); // Ctrl-Delete (WP,!NP,WOW,GE,KE,!OF) return 0; // ignore other combos, pass to parent } case FL_Left: if (mods==0) return input->kf_move_char_left(); // Left (WP,NP,WOW,GE,KE,OF) if (mods==FL_CTRL) return input->kf_move_word_left(); // Ctrl-Left (WP,NP,WOW,GE,KE,!OF) if (mods==FL_META) return input->kf_move_char_left(); // Meta-Left (WP,NP,?WOW,GE,KE) return 0; // ignore other combos, pass to parent case FL_Right: if (mods==0) return input->kf_move_char_right(); // Right (WP,NP,WOW,GE,KE,OF) if (mods==FL_CTRL) return input->kf_move_word_right(); // Ctrl-Right (WP,NP,WOW,GE,KE,!OF) if (mods==FL_META) return input->kf_move_char_right(); // Meta-Right (WP,NP,?WOW,GE,KE,!OF) return 0; // ignore other combos, pass to parent case FL_Up: if (mods==0) return input->kf_lines_up(1); // Up (WP,NP,WOW,GE,KE,OF) if (mods==FL_CTRL) return input->kf_move_up_and_sol(); // Ctrl-Up (WP,!NP,WOW,GE,!KE,OF) return 0; // ignore other combos, pass to parent case FL_Down: if (mods==0) return input->kf_lines_down(1); // Dn (WP,NP,WOW,GE,KE,OF) if (mods==FL_CTRL) return input->kf_move_down_and_eol(); // Ctrl-Down (WP,!NP,WOW,GE,!KE,OF) return 0; // ignore other combos, pass to parent case FL_Page_Up: // Fl_Input has no scroll control, so instead we move the cursor by one page if (mods==0) return input->kf_page_up(); // PageUp (WP,NP,WOW,GE,KE) if (mods==FL_CTRL) return input->kf_page_up(); // Ctrl-PageUp (!WP,!NP,!WOW,!GE,KE,OF) if (mods==FL_ALT) return input->kf_page_up(); // Alt-PageUp (!WP,!NP,!WOW,!GE,KE,OF) return 0; // ignore other combos, pass to parent case FL_Page_Down: if (mods==0) return input->kf_page_down(); // PageDn (WP,NP,WOW,GE,KE) if (mods==FL_CTRL) return input->kf_page_down(); // Ctrl-PageDn (!WP,!NP,!WOW,!GE,KE,OF) if (mods==FL_ALT) return input->kf_page_down(); // Alt-PageDn (!WP,!NP,!WOW,!GE,KE,OF) return 0; // ignore other combos, pass to parent case FL_Home: if (mods==0) return input->kf_move_sol(); // Home (WP,NP,WOW,GE,KE,OF) if (mods==FL_CTRL) return input->kf_top(); // Ctrl-Home (WP,NP,WOW,GE,KE,OF) return 0; // ignore other combos, pass to parent case FL_End: if (mods==0) return input->kf_move_eol(); // End (WP,NP,WOW,GE,KE,OF) if (mods==FL_CTRL) return input->kf_bottom(); // Ctrl-End (WP,NP,WOW,GE,KE,OF) return 0; // ignore other combos, pass to parent case FL_BackSpace: if (mods==0) return input->kf_delete_char_left(); // Backspace (WP,NP,WOW,GE,KE,OF) if (mods==FL_CTRL) return input->kf_delete_word_left(); // Ctrl-Backspace (WP,!NP,WOW,GE,KE,!OF) return 0; // ignore other combos, pass to parent } return -1; } void Fl_Screen_Driver::rescale_all_windows_from_screen(int screen, float f, float old_f) { this->scale(screen, f); Fl_Graphics_Driver *d = Fl_Display_Device::display_device()->driver(); d->scale(f); int i = 0, count = 0; // count top-level windows, except transient scale-displaying window Fl_Window *win = Fl::first_window(); while (win) { if (!win->parent() && (Fl_Window_Driver::driver(win)->screen_num() == screen) && win->user_data() != &Fl_Screen_Driver::transient_scale_display) { count++; } win = Fl::next_window(win); } if (count == 0) return; Fl_Window **win_array = new Fl_Window*[count]; win = Fl::first_window(); // memorize all top-level windows while (win) { if (!win->parent() && (Fl_Window_Driver::driver(win)->screen_num() == screen) && win->user_data() != &Fl_Screen_Driver::transient_scale_display) { win_array[i++] = win; } win = Fl::next_window(win); } for (i = count - 1; i >= 0; i--) { // rescale all top-level windows, finishing with front one win = win_array[i]; Fl_Window_Driver::driver(win)->resize_after_scale_change(screen, old_f, f); win->wait_for_expose(); } delete[] win_array; } static Fl_Window *transient_scale_window = NULL; Fl_Window *Fl_Screen_Driver::transient_scale_parent = NULL; void Fl_Screen_Driver::del_transient_window(void *) { transient_scale_parent = NULL; delete (Fl_Image*)transient_scale_window->shape(); delete transient_scale_window; transient_scale_window = NULL; } void Fl_Screen_Driver::transient_scale_display(float f, int nscreen) { if (!Fl::option(Fl::OPTION_SHOW_SCALING)) return; // transiently show the new scaling value using a shaped window int w = 150; // draw a white rounded box on black background Fl_Screen_Driver *d = Fl::screen_driver(); float s = d->scale(nscreen); if (s > 3) s = 3; // limit the growth of the transient window Fl_Image_Surface *surf = new Fl_Image_Surface(int(w*s), int(w*s/2)); Fl_Surface_Device::push_current(surf); fl_color(FL_BLACK); fl_rectf(-1, -1, int(w*s)+2, int(w*s)+2); Fl_Box *b = new Fl_Box(FL_RFLAT_BOX, 0, 0, int(w*s), int(w*s/2), ""); b->color(FL_WHITE); surf->draw(b); delete b; Fl_RGB_Image* img = surf->image(); // img will be the window's shape Fl_Surface_Device::pop_current(); delete surf; //create a window shaped with the rounded box int X, Y, W, H; Fl::screen_xywh(X, Y, W, H, nscreen); w = int(w / (d->scale(nscreen)/s)); Fl_Window *win = new Fl_Window((X + W/2) -w/2, (Y + H/2) -w/4, w, w/2, 0); b = new Fl_Box(FL_FLAT_BOX, 0, 0, w, w/2, NULL); char str[10]; snprintf(str, 10, "%d %%", int(f * 100 + 0.5)); b->copy_label(str); b->labelfont(FL_TIMES_BOLD); b->labelsize(Fl_Fontsize(30 * s / d->scale(nscreen))); b->labelcolor(Fl_Tooltip::textcolor()); b->color(Fl_Tooltip::color()); win->end(); win->shape(img); win->user_data((void*)&transient_scale_display); // prevent this window from being rescaled later win->set_output(); win->set_non_modal(); Fl_Window_Driver::driver(win)->screen_num(nscreen); Fl_Window_Driver::driver(win)->force_position(1); if (transient_scale_window) { Fl::remove_timeout(del_transient_window); del_transient_window(NULL); } transient_scale_window = win; win->show(); // delete transient win after 1 sec Fl::add_timeout(1, del_transient_window, NULL); } // respond to Ctrl-'+' and Ctrl-'-' and Ctrl-'0' (Ctrl-'=' is same as Ctrl-'+') by rescaling all windows int Fl_Screen_Driver::scale_handler(int event) { if (!keyboard_screen_scaling) return 0; if ( event != FL_SHORTCUT || !Fl::event_command() ) return 0; enum {none, zoom_in, zoom_out, zoom_reset} zoom = none; if (Fl::test_shortcut(FL_COMMAND+'+')) zoom = zoom_in; else if (Fl::test_shortcut(FL_COMMAND+'-')) zoom = zoom_out; else if (Fl::test_shortcut(FL_COMMAND+'0')) zoom = zoom_reset; // Kludge to recognize shortcut FL_COMMAND+'+' without pressing SHIFT. if (Fl::option(Fl::OPTION_SIMPLE_ZOOM_SHORTCUT)) { if ((Fl::event_state() & (FL_META|FL_ALT|FL_CTRL|FL_SHIFT)) == FL_COMMAND) { // We use Ctrl + key '=|+' for instance on US, UK, and FR keyboards. // This works as expected on all keyboard layouts that have the '=' key in the // lower and the '+' key in the upper position on the same key. // This test would be "false positive" if a keyboard layout had the '=' key in // the lower and any other key than '+' in the upper position! if (Fl::event_key() == '=') zoom = zoom_in; // Note: Fl::event_key() is often incorrect under X11 *if* the selected keyboard // layout is *not* the primary one in the keyboard selection list, e.g. under Gnome. // The observation is that Fl::event_key() is erroneously derived from the primary // keyboard layout instead. This can be very confusing and I don't know why this // happens. Albrecht-S, Oct 2024, on Debian 12 (Bookworm aka Stable as of now). // Example: 0xfe51 ("dead_acute") is sent by the '=' key of the US layout if the // primary layout is German. This *would* be the correct key value for the German // keyboard layout but not for the US layout. // The following statement would work around this for this very special case but // this should IMHO not be done. A valid workaround by the user is to make the // *used* layout the first in the keyboard layout selection list! // else if (Fl::event_key() == 0xfe51) zoom = zoom_in; // dead_acute, see above } } if (zoom != none) { int i, count; if (Fl::grab()) return 0; // don't rescale when menu windows are on Fl_Widget *wid = Fl::focus(); if (!wid) return 0; Fl_Window *top = wid->top_window(); int screen = Fl_Window_Driver::driver(top)->screen_num(); Fl_Screen_Driver *screen_dr = Fl::screen_driver(); // don't rescale when any top window on same screen as // focus window is fullscreen or maximized top = Fl::first_window(); while (top) { if (!top->parent() && (Fl_Window_Driver::driver(top)->screen_num() == screen || screen_dr->rescalable() == SYSTEMWIDE_APP_SCALING)) { if (top->fullscreen_active() || top->maximize_active()) return 0; } top = Fl::next_window(top); } float initial_scale = screen_dr->base_scale(screen); #if defined(TEST_SCALING) // test scaling factors: lots of values from 0.3 to 8.0 static float scaling_values[] = { 0.30000, 0.33661, 0.37768, 0.42376, 0.47547, 0.50000, 0.53348, 0.59858, 0.67162, 0.75357, 0.84551, 0.94868, 1.00000, 1.06444, 1.19432, 1.34005, 1.50000, 1.68702, 1.89287, 2.00000, 2.12384, 7.0f/3, 2.38298, 8.0f/3, 3.00000, 10.0f/3, 3.75000, 4.00000, 13.0f/3, 14.0f/3, 5.00000, 16.0f/3, 17.0f/3, 6.00000, 7.00000, 8.00000}; #else // scaling factors for the standard GUI static float scaling_values[] = { 0.5f, 2.f/3, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 4.f/3, 1.5f, 1.7f, 2.0f, 2.4f, 3.0f}; #endif float f, old_f = screen_dr->scale(screen)/initial_scale; if (zoom == zoom_reset) f = 1; else { count = sizeof(scaling_values)/sizeof(float); for (i = 0; i < count; i++) { if (old_f >= scaling_values[i] - 1e-4 && (i+1 >= count || old_f < scaling_values[i+1] - 1e-4)) { break; } } if (zoom == zoom_out) i--; else i++; if (i < 0) i = 0; else if (i >= count) i = count - 1; f = scaling_values[i]; } if (f == old_f) return 1; if (screen_dr->rescalable() == SYSTEMWIDE_APP_SCALING) { float old_f = screen_dr->scale(0); for (int i = 0; i < Fl::screen_count(); i++) { screen_dr->rescale_all_windows_from_screen(i, f * initial_scale, old_f); } } else { screen_dr->rescale_all_windows_from_screen(screen, f * initial_scale, screen_dr->scale(screen)); } Fl_Screen_Driver::transient_scale_display(f, screen); Fl::handle(FL_ZOOM_EVENT, NULL); return 1; } return 0; } // use the startup time scaling value void Fl_Screen_Driver::use_startup_scale_factor() { char *p; int s_count = screen_count(); desktop_scale_factor(); if ((p = fl_getenv("FLTK_SCALING_FACTOR"))) { float factor = 1; sscanf(p, "%f", &factor); if (rescalable() == SYSTEMWIDE_APP_SCALING) { float new_val = factor * scale(0); for (int i = 0; i < s_count; i++) scale(i, new_val); } else { for (int i = 0; i < s_count; i++) scale(i, factor * scale(i)); } } } void Fl_Screen_Driver::open_display() { static bool been_here = false; if (!been_here) { been_here = true; open_display_platform(); // Memorize the most recently added handler. It may have been // added by open_display_platform() Fl_Event_Handler last_added = Fl::last_handler(); if (rescalable()) { use_startup_scale_factor(); if (keyboard_screen_scaling && rescalable()) { // Add scale_handler after memorized one in linked list // so it has less priority Fl::add_handler(Fl_Screen_Driver::scale_handler, last_added); } int mx, my; int ns = Fl::screen_driver()->get_mouse(mx, my); Fl_Graphics_Driver::default_driver().scale(scale(ns)); } } } // simulation of XParseColor: int Fl_Screen_Driver::parse_color(const char* p, uchar& r, uchar& g, uchar& b) { if (*p == '#') p++; size_t n = strlen(p); size_t m = n/3; const char *pattern = 0; switch(m) { case 1: pattern = "%1x%1x%1x"; break; case 2: pattern = "%2x%2x%2x"; break; case 3: pattern = "%3x%3x%3x"; break; case 4: pattern = "%4x%4x%4x"; break; default: return 0; } int R,G,B; if (sscanf(p,pattern,&R,&G,&B) != 3) return 0; switch(m) { case 1: R *= 0x11; G *= 0x11; B *= 0x11; break; case 3: R >>= 4; G >>= 4; B >>= 4; break; case 4: R >>= 8; G >>= 8; B >>= 8; break; } r = (uchar)R; g = (uchar)G; b = (uchar)B; return 1; } void Fl_Screen_Driver::default_icons(const Fl_RGB_Image *icons[], int count) {} /** see fl_set_spot() */ void Fl_Screen_Driver::set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) {} void Fl_Screen_Driver::set_status(int X, int Y, int W, int H) {} /** see fl_reset_spot() */ void Fl_Screen_Driver::reset_spot() {} /* the following function was stolen from the X sources as indicated. */ /* Copyright Massachusetts Institute of Technology 1985, 1986, 1987 */ /* $XConsortium: XParseGeom.c,v 11.18 91/02/21 17:23:05 rws Exp $ */ /* Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of M.I.T. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. M.I.T. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. */ /* XParseGeometry parses strings of the form "=x{+-}{+-}", where width, height, xoffset, and yoffset are unsigned integers. Example: "=80x24+300-49" The equal sign is optional. It returns a bitmask that indicates which of the four values were actually found in the string. For each value found, the corresponding argument is updated; for each value not found, the corresponding argument is left unchanged. */ static int ReadInteger(char* string, char** NextString) { int Result = 0; int Sign = 1; if (*string == '+') string++; else if (*string == '-') { string++; Sign = -1; } for (; (*string >= '0') && (*string <= '9'); string++) { Result = (Result * 10) + (*string - '0'); } *NextString = string; if (Sign >= 0) return (Result); else return (-Result); } int Fl_Screen_Driver::XParseGeometry(const char* string, int* x, int* y, unsigned int* width, unsigned int* height) { int mask = Fl_Screen_Driver::fl_NoValue; char *strind; unsigned int tempWidth = 0, tempHeight = 0; int tempX = 0, tempY = 0; char *nextCharacter; if ( (string == NULL) || (*string == '\0')) return(mask); if (*string == '=') string++; /* ignore possible '=' at beg of geometry spec */ strind = (char *)string; if (*strind != '+' && *strind != '-' && *strind != 'x') { tempWidth = ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return (0); strind = nextCharacter; mask |= fl_WidthValue; } if (*strind == 'x' || *strind == 'X') { strind++; tempHeight = ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return (0); strind = nextCharacter; mask |= fl_HeightValue; } if ((*strind == '+') || (*strind == '-')) { if (*strind == '-') { strind++; tempX = -ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return (0); strind = nextCharacter; mask |= fl_XNegative; } else { strind++; tempX = ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return(0); strind = nextCharacter; } mask |= fl_XValue; if ((*strind == '+') || (*strind == '-')) { if (*strind == '-') { strind++; tempY = -ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return(0); strind = nextCharacter; mask |= fl_YNegative; } else { strind++; tempY = ReadInteger(strind, &nextCharacter); if (strind == nextCharacter) return(0); strind = nextCharacter; } mask |= fl_YValue; } } /* If strind isn't at the end of the string the it's an invalid geometry specification. */ if (*strind != '\0') return (0); if (mask & fl_XValue) *x = tempX; if (mask & fl_YValue) *y = tempY; if (mask & fl_WidthValue) *width = tempWidth; if (mask & fl_HeightValue) *height = tempHeight; return (mask); } // turn '\r' characters into '\n' and "\r\n" sequences into '\n' // returns new length size_t Fl_Screen_Driver::convert_crlf(char *s, size_t len) { char *src = (char *)memchr(s, '\r', len); // find first `\r` in buffer if (src) { char *dst = src; char *end = s + len; while (src < end) { if (*src == '\r') { if (src + 1 < end && *(src + 1) == '\n') { src++; // skip '\r' continue; } else { *dst++ = '\n'; // replace single '\r' with '\n' } } else { *dst++ = *src; } src++; } return (dst - s); } return len; } float Fl_Screen_Driver::base_scale(int numscreen) { static float base = scale(numscreen); return base; } /** \} \endcond */ fltk-1.4.3/src/Fl_Adjuster.cxx0000644000175000017500000001147315004135251016330 0ustar albrechtalbrecht// // Adjuster widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2011 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include "fastarrow.h" static Fl_Bitmap fastarrow(fastarrow_bits, fastarrow_width, fastarrow_height); #include "mediumarrow.h" static Fl_Bitmap mediumarrow(mediumarrow_bits, mediumarrow_width, mediumarrow_height); #include "slowarrow.h" static Fl_Bitmap slowarrow(slowarrow_bits, slowarrow_width, slowarrow_height); // changing the value does not change the appearance: void Fl_Adjuster::value_damage() {} void Fl_Adjuster::draw() { int dx, dy, W, H; if (w()>=h()) { dx = W = w()/3; dy = 0; H = h(); } else { dx = 0; W = w(); dy = H = h()/3; } draw_box(drag==1?FL_DOWN_BOX:box(), x(), y()+2*dy, W, H, color()); draw_box(drag==2?FL_DOWN_BOX:box(), x()+dx, y()+dy, W, H, color()); draw_box(drag==3?FL_DOWN_BOX:box(), x()+2*dx, y(), W, H, color()); if (active_r()) fl_color(selection_color()); else fl_color(fl_inactive(selection_color())); fastarrow.draw(x()+(W-fastarrow_width)/2, y()+2*dy+(H-fastarrow_height)/2, W, H); mediumarrow.draw(x()+dx+(W-mediumarrow_width)/2, y()+dy+(H-mediumarrow_height)/2, W, H); slowarrow.draw(x()+2*dx+(W-slowarrow_width)/2, y()+(H-slowarrow_width)/2, W, H); if (Fl::focus() == this) draw_focus(); } int Fl_Adjuster::handle(int event) { double v; int delta; int mx = Fl::event_x(); // Fl_Widget_Tracker wp(this); switch (event) { case FL_PUSH: if (Fl::visible_focus()) Fl::focus(this); ix = mx; if (w()>=h()) drag = 3*(mx-x())/w() + 1; else drag = 3-3*(Fl::event_y()-y()-1)/h(); { Fl_Widget_Tracker wp(this); handle_push(); if (wp.deleted()) return 1; } redraw(); return 1; case FL_DRAG: if (w() >= h()) { delta = x()+(drag-1)*w()/3; // left edge of button if (mx < delta) delta = mx-delta; else if (mx > (delta+w()/3)) // right edge of button delta = mx-delta-w()/3; else delta = 0; } else { if (mx < x()) delta = mx-x(); else if (mx > (x()+w())) delta = mx-x()-w(); else delta = 0; } switch (drag) { case 3: v = increment(previous_value(), delta); break; case 2: v = increment(previous_value(), delta*10); break; default:v = increment(previous_value(), delta*100); break; } handle_drag(soft() ? softclamp(v) : clamp(v)); return 1; case FL_RELEASE: if (Fl::event_is_click()) { // detect click but no drag if (Fl::event_state()&0xF0000) delta = -10; else delta = 10; switch (drag) { case 3: v = increment(previous_value(), delta); break; case 2: v = increment(previous_value(), delta*10); break; default:v = increment(previous_value(), delta*100); break; } Fl_Widget_Tracker wp(this); handle_drag(soft() ? softclamp(v) : clamp(v)); if (wp.deleted()) return 1; } drag = 0; redraw(); handle_release(); return 1; case FL_KEYBOARD : switch (Fl::event_key()) { case FL_Up: if (w() > h()) return 0; handle_drag(clamp(increment(value(),-1))); return 1; case FL_Down: if (w() > h()) return 0; handle_drag(clamp(increment(value(),1))); return 1; case FL_Left: if (w() < h()) return 0; handle_drag(clamp(increment(value(),-1))); return 1; case FL_Right: if (w() < h()) return 0; handle_drag(clamp(increment(value(),1))); return 1; default: return 0; } // break not required because of switch... case FL_FOCUS: case FL_UNFOCUS: if (Fl::visible_focus()) { redraw(); return 1; } else return 0; case FL_ENTER : case FL_LEAVE : return 1; } return 0; } /** Creates a new Fl_Adjuster widget using the given position, size, and label string. It looks best if one of the dimensions is 3 times the other.

Inherited destructor destroys the Valuator. */ Fl_Adjuster::Fl_Adjuster(int X, int Y, int W, int H, const char* l) : Fl_Valuator(X, Y, W, H, l) { box(FL_UP_BOX); step(1, 10000); selection_color(FL_SELECTION_COLOR); drag = 0; soft_ = 1; } fltk-1.4.3/src/Fl_Printer.cxx0000644000175000017500000002023715004135251016170 0ustar albrechtalbrecht// // Encompasses platform-specific printing-support code and // PostScript output code for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #if defined(FL_NO_PRINT_SUPPORT) #include #include Fl_Printer::Fl_Printer(void) { printer = NULL; } Fl_Paged_Device* Fl_Printer::newPrinterDriver(void) { return NULL; } int Fl_Printer::begin_job(int pagecount, int *frompage, int *topage, char **perr_message) {return 2;} int Fl_Printer::begin_page(void) {return 1;} int Fl_Printer::printable_rect(int *w, int *h) {return 1;} void Fl_Printer::margins(int *left, int *top, int *right, int *bottom) {} void Fl_Printer::origin(int *x, int *y) {} void Fl_Printer::origin(int x, int y) {} void Fl_Printer::scale(float scale_x, float scale_y) {} void Fl_Printer::rotate(float angle) {} void Fl_Printer::translate(int x, int y) {} void Fl_Printer::untranslate(void) {} int Fl_Printer::end_page (void) {return 1;} void Fl_Printer::end_job (void) {} void Fl_Printer::set_current(void) {} void Fl_PostScript_File_Device::end_current(void) {} void Fl_PostScript_File_Device::set_current(void) {} bool Fl_Printer::is_current(void) {return false;} Fl_Printer::~Fl_Printer(void) {} const char *Fl_Printer::dialog_title = NULL; const char *Fl_Printer::dialog_printer = NULL; const char *Fl_Printer::dialog_range = NULL; const char *Fl_Printer::dialog_copies = NULL; const char *Fl_Printer::dialog_all = NULL; const char *Fl_Printer::dialog_pages = NULL; const char *Fl_Printer::dialog_from = NULL; const char *Fl_Printer::dialog_to = NULL; const char *Fl_Printer::dialog_properties = NULL; const char *Fl_Printer::dialog_copyNo = NULL; const char *Fl_Printer::dialog_print_button = NULL; const char *Fl_Printer::dialog_cancel_button = NULL; const char *Fl_Printer::dialog_print_to_file = NULL; const char *Fl_Printer::property_title = NULL; const char *Fl_Printer::property_pagesize = NULL; const char *Fl_Printer::property_mode = NULL; const char *Fl_Printer::property_use = NULL; const char *Fl_Printer::property_save = NULL; const char *Fl_Printer::property_cancel = NULL; Fl_PostScript_File_Device::Fl_PostScript_File_Device(void) {} int Fl_PostScript_File_Device::begin_job(int pagecount, int* from, int* to, char **perr_message) {return 2;} int Fl_PostScript_File_Device::begin_job(int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) {return 1;} int Fl_PostScript_File_Device::begin_job(FILE *ps_output, int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) {return 1;} int Fl_PostScript_File_Device::begin_page (void) {return 1;} int Fl_PostScript_File_Device::printable_rect(int *w, int *h) {return 1;} void Fl_PostScript_File_Device::margins(int *left, int *top, int *right, int *bottom) {} void Fl_PostScript_File_Device::origin(int *x, int *y) {} void Fl_PostScript_File_Device::origin(int x, int y) {} void Fl_PostScript_File_Device::scale (float scale_x, float scale_y) {} void Fl_PostScript_File_Device::rotate(float angle) {} void Fl_PostScript_File_Device::translate(int x, int y) {} void Fl_PostScript_File_Device::untranslate(void) {} int Fl_PostScript_File_Device::end_page (void) {return 1;} void Fl_PostScript_File_Device::end_job(void) {} FILE* Fl_PostScript_File_Device::file() {return NULL;} void Fl_PostScript_File_Device::close_command(Fl_PostScript_Close_Command cmd) {} Fl_PostScript_File_Device::~Fl_PostScript_File_Device(void) {} Fl_EPS_File_Surface::Fl_EPS_File_Surface(int width, int height, FILE *eps_output, Fl_Color background, Fl_PostScript_Close_Command closef) : Fl_Widget_Surface(NULL) {} Fl_EPS_File_Surface::~Fl_EPS_File_Surface() {} void Fl_EPS_File_Surface::origin(int, int) {} void Fl_EPS_File_Surface::origin(int*, int*) {} int Fl_EPS_File_Surface::printable_rect(int*, int*) {return 1;} void Fl_EPS_File_Surface::translate(int, int) {} void Fl_EPS_File_Surface::untranslate() {} FILE* Fl_EPS_File_Surface::file() {return NULL;} int Fl_EPS_File_Surface::close() {return 1;} Fl_PDF_File_Surface::Fl_PDF_File_Surface(void) {} int Fl_PDF_File_Surface::begin_job(const char* defaultfilename, char **perr) {return 2;} int Fl_PDF_File_Surface::begin_document(const char* pathname, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout, char **perr) {return 2;} Fl_PDF_File_Surface::~Fl_PDF_File_Surface(void) {} #else // print dialog customization strings /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_title = "Print"; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_printer = "Printer:"; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_range = "Print Range"; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_copies = "Copies"; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_all = "All"; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_pages = "Pages"; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_from = "From:"; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_to = "To:"; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_properties = "Properties..."; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_copyNo = "# Copies:"; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_print_button = "Print"; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_cancel_button = "Cancel"; /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_print_to_file = "Print To File"; /** [this text may be customized at run-time] */ const char *Fl_Printer::property_title = "Printer Properties"; /** [this text may be customized at run-time] */ const char *Fl_Printer::property_pagesize = "Page Size:"; /** [this text may be customized at run-time] */ const char *Fl_Printer::property_mode = "Output Mode:"; /** [this text may be customized at run-time] */ const char *Fl_Printer::property_use = "Use"; /** [this text may be customized at run-time] */ const char *Fl_Printer::property_save = "Save"; /** [this text may be customized at run-time] */ const char *Fl_Printer::property_cancel = "Cancel"; Fl_Printer::Fl_Printer(void) { printer = Fl_Printer::newPrinterDriver(); driver(printer->driver()); } int Fl_Printer::begin_job(int pagecount, int *frompage, int *topage, char **perr_message) { return printer->begin_job(pagecount, frompage, topage, perr_message); } int Fl_Printer::begin_page(void) { return printer->begin_page(); } int Fl_Printer::printable_rect(int *w, int *h) { return printer->printable_rect(w, h); } void Fl_Printer::margins(int *left, int *top, int *right, int *bottom) { printer->margins(left, top, right, bottom); } void Fl_Printer::origin(int *x, int *y) { printer->origin(x, y); } void Fl_Printer::origin(int x, int y) { printer->origin(x, y); } void Fl_Printer::scale(float scale_x, float scale_y) { printer->scale(scale_x, scale_y); } void Fl_Printer::rotate(float angle) { printer->rotate(angle); } void Fl_Printer::translate(int x, int y) { printer->translate(x, y); } void Fl_Printer::untranslate(void) { printer->untranslate(); } int Fl_Printer::end_page (void) { return printer->end_page(); } void Fl_Printer::end_job (void) { printer->end_job(); } void Fl_Printer::set_current(void) { printer->set_current(); } bool Fl_Printer::is_current() { return surface() == printer; } Fl_Printer::~Fl_Printer(void) { delete printer; } #endif // defined(FL_NO_PRINT_SUPPORT) fltk-1.4.3/src/filename_absolute.cxx0000644000175000017500000003317715004135251017611 0ustar albrechtalbrecht// // Filename expansion routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* expand a file name by prepending current directory, deleting . and .. (not really correct for symbolic links) between the prepended current directory. Use $PWD if it exists. Returns true if any changes were made. */ #include #include #include #include "Fl_System_Driver.H" #include #include "flstring.h" static inline int isdirsep(int c) {return c == '/';} /** Makes a filename absolute from a relative filename to the current working directory. \code #include [..] fl_chdir("/var/tmp"); fl_filename_absolute(out, sizeof(out), "foo.txt"); // out="/var/tmp/foo.txt" fl_filename_absolute(out, sizeof(out), "./foo.txt"); // out="/var/tmp/foo.txt" fl_filename_absolute(out, sizeof(out), "../log/messages"); // out="/var/log/messages" \endcode \param[out] to resulting absolute filename \param[in] tolen size of the absolute filename buffer \param[in] from relative filename \return 0 if no change, non zero otherwise */ int fl_filename_absolute(char *to, int tolen, const char *from) { char cwd_buf[FL_PATH_MAX]; // Current directory // get the current directory and return if we can't if (!fl_getcwd(cwd_buf, sizeof(cwd_buf))) { strlcpy(to, from, tolen); return 0; } return Fl::system_driver()->filename_absolute(to, tolen, from, cwd_buf); } /** Concatenate the absolute path `base` with `from` to form the new absolute path in `to`. \code #include char out[FL_PATH_MAX]; fl_filename_absolute(out, sizeof(out), "../foo.txt", "/var/tmp"); // out="/var/foo.txt" fl_filename_absolute(out, sizeof(out), "../local/bin", "/usr/bin"); // out="/usr/local/bin" \endcode \param[out] to resulting absolute filename \param[in] tolen size of the absolute filename buffer \param[in] from relative filename \param[in] base `from` is relative to this absolute file path \return 0 if no change, non zero otherwise */ int fl_filename_absolute(char *to, int tolen, const char *from, const char *base) { return Fl::system_driver()->filename_absolute(to, tolen, from, base); } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ int Fl_System_Driver::filename_absolute(char *to, int tolen, const char *from, const char *base) { if (isdirsep(*from) || *from == '|' || !base) { strlcpy(to, from, tolen); return 0; } char *a; char *temp = new char[tolen]; const char *start = from; strlcpy(temp, base, tolen); a = temp+strlen(temp); /* remove trailing '/' in current working directory */ if (isdirsep(*(a-1))) a--; /* remove intermediate . and .. names: */ while (*start == '.') { if (start[1]=='.' && (isdirsep(start[2]) || start[2]==0) ) { // found "..", remove the last directory segment form cwd char *b; for (b = a-1; b >= temp && !isdirsep(*b); b--) {/*empty*/} if (b < temp) break; a = b; if (start[2]==0) start += 2; // Skip to end of path else start += 3; // Skip over dir separator } else if (isdirsep(start[1])) { // found "./" in path, just skip it start += 2; } else if (!start[1]) { // found "." at end of path, just skip it start ++; break; } else break; } *a++ = '/'; strlcpy(a,start,tolen - (a - temp)); strlcpy(to, temp, tolen); delete[] temp; return 1; } /** \} \endcond */ /** Makes a filename relative to the current working directory. Return the \a from path made relative to the working directory, similar to C++17 `std::filesystem::path::lexically_relative`. This function can also be called with a fourth argument for a user supplied \a base directory path These conversions are purely lexical. They do not check that the paths exist, do not follow symlinks, and do not access the filesystem at all. Path arguments must be absolute (start at the root directory) and must not contain `.` or `..` segments, or double separators. A single trailing separator is ok. On Windows, path arguments must start with a drive name, e.g. `c:\`. Windows network paths and other special paths starting with a double separator are not supported (`\\cloud\drive\path`, `\\?\`, etc.) . Separators can be `\` and `/` and will be preserved. Newly created separators are alway the forward slash `/`. On Windows and macOS, the path segment tests are case insensitive. If the path can not be generated, \a from path is copied into the \a to buffer and 0 is returned. \code #include [..] fl_chdir("/var/tmp/somedir"); // set cwd to /var/tmp/somedir [..] char out[FL_PATH_MAX]; fl_filename_relative(out, sizeof(out), "/var/tmp/somedir/foo.txt"); // out="foo.txt", return=1 fl_filename_relative(out, sizeof(out), "/var/tmp/foo.txt"); // out="../foo.txt", return=1 fl_filename_relative(out, sizeof(out), "foo.txt"); // out="foo.txt", return=0 (no change) fl_filename_relative(out, sizeof(out), "./foo.txt"); // out="./foo.txt", return=0 (no change) fl_filename_relative(out, sizeof(out), "../foo.txt"); // out="../foo.txt", return=0 (no change) \endcode \param[out] to resulting relative filename \param[in] tolen size of the relative filename buffer \param[in] from absolute filename \return 0 if no change, non zero otherwise \see fl_filename_relative(char *to, int tolen, const char *from, const char *base) */ int fl_filename_relative(char *to, int tolen, const char *from) { char cwd_buf[FL_PATH_MAX]; // Current directory // get the current directory and return if we can't if (!fl_getcwd(cwd_buf, sizeof(cwd_buf))) { strlcpy(to, from, tolen); return 0; } return fl_filename_relative(to, tolen, from, cwd_buf); } /** Makes a filename relative to any other directory. \param[out] to resulting relative filepath \param[in] tolen size of the relative filename buffer \param[in] from absolute filepath \param[in] base generate filepath relative to this absolute filepath \return 0 if no change, non zero otherwise \see fl_filename_relative(char *to, int tolen, const char *from) */ int fl_filename_relative(char *to, int tolen, const char *from, const char *base) { return Fl::system_driver()->filename_relative(to, tolen, from, base); } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ int Fl_System_Driver::filename_relative(char *to, int tolen, const char *dest_dir, const char *base_dir) { // Find the relative path from base_dir to dest_dir. // Both paths must be absolute and well formed (contain no /../ and /./ segments). const char *base_i = base_dir; // iterator through the base directory string const char *base_s = base_dir; // pointer to the last dir separator found const char *dest_i = dest_dir; // iterator through the destination directory const char *dest_s = dest_dir; // pointer to the last dir separator found // return if any of the pointers is NULL if (!to || !dest_dir || !base_dir) { return 0; } // return if `base_dir` or `dest_dir` is not an absolute path if (!isdirsep(*base_dir) || !isdirsep(*dest_dir)) { strlcpy(to, dest_dir, tolen); return 0; } // compare both path names until we find a difference for (;;) { #ifndef __APPLE__ // case sensitive base_i++; dest_i++; char b = *base_i, d = *dest_i; #else // case insensitive base_i += fl_utf8len1(*base_i); int b = fl_tolower(fl_utf8decode(base_i, NULL, NULL)); dest_i += fl_utf8len1(*dest_i); int d = fl_tolower(fl_utf8decode(dest_i, NULL, NULL)); #endif int b0 = (b==0) || (isdirsep(b)); int d0 = (d==0) || (isdirsep(d)); if (b0 && d0) { base_s = base_i; dest_s = dest_i; } if (b==0 || d==0) break; if (b!=d) break; } // base_s and dest_s point at the last separator we found // base_i and dest_i point at the first character that differs // test for the exact same string and return "." if so if ( (base_i[0] == 0 || (isdirsep(base_i[0]) && base_i[1] == 0)) && (dest_i[0] == 0 || (isdirsep(dest_i[0]) && dest_i[1] == 0))) { strlcpy(to, ".", tolen); return 0; } // prepare the destination buffer to[0] = '\0'; to[tolen - 1] = '\0'; // count the directory segments remaining in `base_dir` int n_up = 0; for (;;) { char b = *base_s++; if (b==0) break; if (isdirsep(b) && *base_s) n_up++; } // now add a "previous dir" sequence for every following slash in the cwd if (n_up>0) strlcat(to, "..", tolen); for (; n_up>1; --n_up) strlcat(to, "/..", tolen); // finally add the differing path from "from" if (*dest_s) { if (n_up) strlcat(to, "/", tolen); strlcat(to, dest_s+1, tolen); } return 1; } /** \} \endcond */ // FIXME: '0 &&' => We can't do that in 1.4.x, enable this block in 1.5 or higher. // There would be too many naming conflicts with fluid's usage of these functions. #if (0 && FLTK_USE_STD) /** Return a new string that contains the name part of the filename. \param[in] filename file path and name \return the name part of a filename \see fl_filename_name(const char *filename) */ std::string fl_filename_name(const std::string &filename) { return std::string(fl_filename_name(filename.c_str())); } /** Return a new string that contains the path part of the filename. \param[in] filename file path and name \return the path part of a filename without the name \see fl_filename_name(const char *filename) */ std::string fl_filename_path(const std::string &filename) { const char *base = filename.c_str(); const char *name = fl_filename_name(base); if (name) { return std::string(base, (int)(name-base)); } else { return std::string(); } } /** Return a new string that contains the filename extension. \param[in] filename file path and name \return the filename extension including the prepending '.', or an empty string if the filename has no extension \see fl_filename_ext(const char *buf) */ std::string fl_filename_ext(const std::string &filename) { return std::string(fl_filename_ext(filename.c_str())); } /** Return a copy of the old filename with the new extension. \param[in] filename file path and name \param[in] new_extension new filename extension, starts with a '.' \return the new filename \see fl_filename_setext(char *to, int tolen, const char *ext) */ std::string fl_filename_setext(const std::string &filename, const std::string &new_extension) { char buffer[FL_PATH_MAX]; fl_strlcpy(buffer, filename.c_str(), FL_PATH_MAX); fl_filename_setext(buffer, FL_PATH_MAX, new_extension.c_str()); return std::string(buffer); } /** Expands a filename containing shell variables and tilde (~). \param[in] from file path and name \return the new, expanded filename \see fl_filename_expand(char *to, int tolen, const char *from) */ std::string fl_filename_expand(const std::string &from) { char buffer[FL_PATH_MAX]; fl_filename_expand(buffer, FL_PATH_MAX, from.c_str()); return std::string(buffer); } /** Makes a filename absolute from a filename relative to the current working directory. \param[in] from relative filename \return the new, absolute filename \see fl_filename_absolute(char *to, int tolen, const char *from) */ std::string fl_filename_absolute(const std::string &from) { char buffer[FL_PATH_MAX]; fl_filename_absolute(buffer, FL_PATH_MAX, from.c_str()); return std::string(buffer); } /** Append the relative filename `from` to the absolute filename `base` to form the new absolute path. \param[in] from relative filename \param[in] base `from` is relative to this absolute file path \return the new, absolute filename \see fl_filename_absolute(char *to, int tolen, const char *from, const char *base) */ std::string fl_filename_absolute(const std::string &from, const std::string &base) { char buffer[FL_PATH_MAX]; fl_filename_absolute(buffer, FL_PATH_MAX, from.c_str(), base.c_str()); return std::string(buffer); } /** Makes a filename relative to the current working directory. \param[in] from file path and name \return the new, relative filename \see fl_filename_relative(char *to, int tolen, const char *from) */ std::string fl_filename_relative(const std::string &from) { char buffer[FL_PATH_MAX]; fl_filename_relative(buffer, FL_PATH_MAX, from.c_str()); return std::string(buffer); } /** Makes a filename relative to any directory. \param[in] from file path and name \param[in] base relative to this absolute path \return the new, relative filename \see fl_filename_relative(char *to, int tolen, const char *from, const char *base) */ std::string fl_filename_relative(const std::string &from, const std::string &base) { char buffer[FL_PATH_MAX]; fl_filename_relative(buffer, FL_PATH_MAX, from.c_str(), base.c_str()); return std::string(buffer); } /** Cross-platform function to get the current working directory as a UTF-8 encoded value in an std::string. \return the CWD encoded as UTF-8 */ std::string fl_getcwd() { char buffer[FL_PATH_MAX]; fl_getcwd(buffer, FL_PATH_MAX); return std::string(buffer); } #endif // FLTK_USE_STD fltk-1.4.3/src/Fl_JPEG_Image.cxx0000644000175000017500000002452715004135251016402 0ustar albrechtalbrecht// // Fl_JPEG_Image routines. // // Copyright 1997-2011 by Easy Software Products. // Image support by Matthias Melcher, Copyright 2000-2009. // // Copyright 2013-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // Fl_JPEG_Image::Fl_JPEG_Image() - Load a JPEG image file. // // // Include necessary header files... // #include #include #include #include #include #include #include #include // Some releases of the Cygwin JPEG libraries don't have a correctly // updated header file for the INT32 data type; the following define // from Shane Hill seems to be a usable workaround... #if defined(__CYGWIN__) # define XMD_H #endif // __CYGWIN__ extern "C" { #ifdef HAVE_LIBJPEG # include #endif // HAVE_LIBJPEG } // // Custom JPEG error handling structure... // #ifdef HAVE_LIBJPEG struct fl_jpeg_error_mgr { jpeg_error_mgr pub_; // Destination manager... jmp_buf errhand_; // Error handler }; #endif // HAVE_LIBJPEG // // Error handler for JPEG files... // #ifdef HAVE_LIBJPEG extern "C" { static void fl_jpeg_error_handler(j_common_ptr dinfo) { // I - Decompressor info longjmp(((fl_jpeg_error_mgr *)(dinfo->err))->errhand_, 1); } static void fl_jpeg_output_handler(j_common_ptr) { // I - Decompressor info (not used) } } #endif // HAVE_LIBJPEG /** \brief The constructor loads the JPEG image from the given jpeg filename. The inherited destructor frees all memory and server resources that are used by the image. Use Fl_Image::fail() to check if Fl_JPEG_Image failed to load. fail() returns ERR_FILE_ACCESS if the file could not be opened or read, ERR_FORMAT if the JPEG format could not be decoded, and ERR_NO_IMAGE if the image could not be loaded for another reason. If the image has loaded correctly, w(), h(), and d() should return values greater than zero. \param[in] filename a full path and name pointing to a valid jpeg file. \see Fl_JPEG_Image::Fl_JPEG_Image(const char *imagename, const unsigned char *data) */ Fl_JPEG_Image::Fl_JPEG_Image(const char *filename) : Fl_RGB_Image(0,0,0) { load_jpg_(filename, 0L, 0L); } /** \brief The constructor loads the JPEG image from memory. Construct an image from a block of memory inside the application. Fluid offers "binary Data" chunks as a great way to add image data into the C++ source code. name_png can be NULL. If a name is given, the image is added to the list of shared images (see: Fl_Shared_Image) and will be available by that name. The inherited destructor frees all memory and server resources that are used by the image. Use Fl_Image::fail() to check if Fl_JPEG_Image failed to load. fail() returns ERR_FILE_ACCESS if the file could not be opened or read, ERR_FORMAT if the JPEG format could not be decoded, and ERR_NO_IMAGE if the image could not be loaded for another reason. If the image has loaded correctly, w(), h(), and d() should return values greater than zero. \param name A unique name or NULL \param data A pointer to the memory location of the JPEG image \param data_length optional length of \c data. This will protect memory outside of the \c data array from illegal read operations \see Fl_JPEG_Image::Fl_JPEG_Image(const char *filename) \see Fl_Shared_Image */ Fl_JPEG_Image::Fl_JPEG_Image(const char *name, const unsigned char *data, int data_length) : Fl_RGB_Image(0,0,0) { load_jpg_(0L, name, data, data_length); } // data source manager for reading jpegs from memory // init_source (j_decompress_ptr cinfo) // fill_input_buffer (j_decompress_ptr cinfo) // skip_input_data (j_decompress_ptr cinfo, long num_bytes) // resync_to_restart (j_decompress_ptr cinfo, int desired) // term_source (j_decompress_ptr cinfo) // JOCTET * next_output_byte; /* => next byte to write in buffer */ // size_t free_in_buffer; /* # of byte spaces remaining in buffer */ #ifdef HAVE_LIBJPEG typedef struct { struct jpeg_source_mgr pub; const unsigned char *data, *s; // JOCTET * buffer; /* start of buffer */ // boolean start_of_file; /* have we gotten any data yet? */ } my_source_mgr; typedef my_source_mgr *my_src_ptr; extern "C" { static void init_source(j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr)cinfo->src; src->s = src->data; } static boolean fill_input_buffer(j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr)cinfo->src; size_t nbytes = 4096; src->pub.next_input_byte = src->s; src->pub.bytes_in_buffer = nbytes; src->s += nbytes; return TRUE; } static void term_source(j_decompress_ptr cinfo) { } static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) { my_src_ptr src = (my_src_ptr)cinfo->src; if (num_bytes > 0) { while (num_bytes > (long)src->pub.bytes_in_buffer) { num_bytes -= (long)src->pub.bytes_in_buffer; fill_input_buffer(cinfo); } src->pub.next_input_byte += (size_t) num_bytes; src->pub.bytes_in_buffer -= (size_t) num_bytes; } } } // extern "C" static void jpeg_unprotected_mem_src(j_decompress_ptr cinfo, const unsigned char *data) { my_src_ptr src = (my_source_mgr*)malloc(sizeof(my_source_mgr)); cinfo->src = &(src->pub); src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; src->pub.term_source = term_source; src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ src->pub.next_input_byte = NULL; /* until buffer loaded */ src->data = data; src->s = data; } #endif // HAVE_LIBJPEG /* This method reads JPEG image data and creates an RGB or grayscale image. To avoid code duplication, we set filename if we want to read form a file or data to read from memory instead. Sharename can be set if the image is supposed to be added to the Fl_Shared_Image list. */ void Fl_JPEG_Image::load_jpg_(const char *filename, const char *sharename, const unsigned char *data, int data_length) { #ifdef HAVE_LIBJPEG jpeg_decompress_struct dinfo; // Decompressor info fl_jpeg_error_mgr jerr; // Error handler info JSAMPROW row; // Sample row pointer // The following variables are pointers allocating some private space that // is not reset by 'setjmp()'. At least under macOS, it's necessay to make // these variables volatile to avoid errors occurring when compiled with -O1 (issue #1207). volatile char* max_finish_decompress_err; // count errors and give up after a while volatile char* max_destroy_decompress_err; // to avoid recursion and deadlock // Note: The file pointer fp must not be an automatic (stack) variable // to avoid potential clobbering by setjmp/longjmp (gcc: [-Wclobbered]). // Hence the actual 'fp' is allocated with operator new. FILE** fp = new FILE*; // always allocate file pointer *fp = NULL; // Clear data... alloc_array = 0; array = (uchar *)0; // Open the image file if we read from the file system if (filename) { if ((*fp = fl_fopen(filename, "rb")) == NULL) { ld(ERR_FILE_ACCESS); delete fp; return; } } else { if (data==0L) { ld(ERR_FILE_ACCESS); delete fp; return; } } // Setup the decompressor info and read the header... dinfo.err = jpeg_std_error((jpeg_error_mgr *)&jerr); jerr.pub_.error_exit = fl_jpeg_error_handler; jerr.pub_.output_message = fl_jpeg_output_handler; // Setup error loop variables max_finish_decompress_err = (char*)malloc(1); // allocate space on the frame for error counters max_destroy_decompress_err = (char*)malloc(1); // otherwise, the variables are reset on the longjmp *max_finish_decompress_err=10; *max_destroy_decompress_err=10; if (setjmp(jerr.errhand_)) { // JPEG error handling... const char *name = ""; if (filename) name = filename; else if (sharename) name = sharename; Fl::warning("JPEG file \"%s\" is too large or contains errors!\n", name); // if any of the cleanup routines hits another error, we would end up // in a loop. So instead, we decrement max_err for some upper cleanup limit. if ( ((*max_finish_decompress_err)-- > 0) && array) jpeg_finish_decompress(&dinfo); if ( (*max_destroy_decompress_err)-- > 0) jpeg_destroy_decompress(&dinfo); if (*fp) fclose(*fp); w(0); h(0); d(0); if (array) { delete[] (uchar *)array; array = 0; alloc_array = 0; } free((void*)max_destroy_decompress_err); free((void*)max_finish_decompress_err); ld(ERR_FORMAT); delete fp; return; } jpeg_create_decompress(&dinfo); if (*fp) { jpeg_stdio_src(&dinfo, *fp); } else { if (data_length==-1) jpeg_unprotected_mem_src(&dinfo, data); else jpeg_mem_src(&dinfo, const_cast(data), (size_t)data_length); } jpeg_read_header(&dinfo, TRUE); dinfo.quantize_colors = (boolean)FALSE; dinfo.out_color_space = JCS_RGB; dinfo.out_color_components = 3; dinfo.output_components = 3; jpeg_calc_output_dimensions(&dinfo); w(dinfo.output_width); h(dinfo.output_height); d(dinfo.output_components); if (((size_t)w()) * h() * d() > max_size() ) longjmp(jerr.errhand_, 1); array = new uchar[w() * h() * d()]; alloc_array = 1; jpeg_start_decompress(&dinfo); while (dinfo.output_scanline < dinfo.output_height) { row = (JSAMPROW)(array + dinfo.output_scanline * dinfo.output_width * dinfo.output_components); jpeg_read_scanlines(&dinfo, &row, (JDIMENSION)1); } jpeg_finish_decompress(&dinfo); jpeg_destroy_decompress(&dinfo); free((void*)max_destroy_decompress_err); free((void*)max_finish_decompress_err); if (*fp) fclose(*fp); if (sharename && w() && h()) { Fl_Shared_Image *si = new Fl_Shared_Image(sharename, this); si->add(); } delete fp; #endif // HAVE_LIBJPEG } fltk-1.4.3/src/filename_setext.cxx0000644000175000017500000000235115004135251017275 0ustar albrechtalbrecht// // Filename extension routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Replace .ext with new extension #include #include "flstring.h" /** Replaces the extension in \p buf of max.
size \p buflen with the extension in \p ext.
If there's no '.' in \p buf, \p ext is appended.
If \p ext is NULL, behaves as if it were an empty string (""). \b Example \code #include [..] char buf[FL_PATH_MAX] = "/path/myfile.cxx"; fl_filename_setext(buf, sizeof(buf), ".txt"); // buf[] becomes "/path/myfile.txt" \endcode \return buf itself for calling convenience. */ char *fl_filename_setext(char *buf, int buflen, const char *ext) { char *q = (char *)fl_filename_ext(buf); if (ext) { strlcpy(q,ext,buflen - (q - buf)); } else *q = 0; return(buf); } fltk-1.4.3/src/nanosvg.cxx0000644000175000017500000000407715004135251015603 0ustar albrechtalbrecht// // Implementation of the nanosvg library for the Fast Light Tool Kit (FLTK). // // Copyright 2017-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // This code includes the header-only nanosvg library and builds a // separate object file comprised of the nanosvg library and nothing // else. Moved here from Fl_SVG_Image.cxx for better code separation. #include #if defined(FLTK_USE_SVG) || defined(FL_DOXYGEN) // GitHub Issue #937: "Support for HP-UX" (version 11.11, Dec. 2000) // // C90 does not provide roundf() but nanosvg.h uses it although // nanosvgrast.h has a replacement function: nsvg__roundf() // // Solution: use nsvg_roundf() instead. // Advantage: we don't need to check system macros. // // Note: using nsvg__roundf() in nanosvg.h should be applied upstream. // Once this is available we can remove this comment block and // the following 3-line "fix": #include // must be before #define below ! static float nsvg__roundf(float x); // prototype (see nanosvgrast.h) #define roundf nsvg__roundf // redefinition (#937) // End of GitHub Issue #937. Remove this entire block when upstream is patched. #if !defined(HAVE_LONG_LONG) static double strtoll(const char *str, char **endptr, int base) { return (double)strtol(str, endptr, base); } #endif #ifdef _MSC_VER #pragma warning (disable: 4244) // Switch off conversion warnings #endif #define NANOSVG_ALL_COLOR_KEYWORDS // include full list of color keywords #define NANOSVG_IMPLEMENTATION // use nanosvg.h implementation #define NANOSVGRAST_IMPLEMENTATION // use nanosvgrast.h implementation #include "../nanosvg/nanosvg.h" #include "../nanosvg/nanosvgrast.h" #endif // FLTK_USE_SVG fltk-1.4.3/src/Fl_Menu_Button.cxx0000644000175000017500000000701715004135251017005 0ustar albrechtalbrecht// // Menu button widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include Fl_Menu_Button* Fl_Menu_Button::pressed_menu_button_ = NULL; void Fl_Menu_Button::draw() { if (!box() || type()) return; // calculate position and size of virtual "arrow box" (choice button) int ah = h() - Fl::box_dh(box()); int aw = ah > 20 ? 20 : ah; // limit width: don't waste space for button int ax = x() + w() - Fl::box_dx(box()) - aw; int ay = y() + (h() - ah) / 2; // the remaining space is used to draw the label draw_box(pressed_menu_button_ == this ? fl_down(box()) : box(), color()); draw_label(x() + Fl::box_dx(box()), y(), w() - Fl::box_dw(box()) - aw, h()); if (Fl::focus() == this) draw_focus(); // draw the arrow (choice button) Fl_Color arrow_color = active_r() ? labelcolor() : fl_inactive(labelcolor()); fl_draw_arrow(Fl_Rect(ax, ay, aw, ah), FL_ARROW_SINGLE, FL_ORIENT_DOWN, arrow_color); } /** Act exactly as though the user clicked the button or typed the shortcut key. The menu appears, it waits for the user to pick an item, and if they pick one it sets value() and does the callback or sets changed() as described above. The menu item is returned or NULL if the user dismisses the menu. \note Since FLTK 1.4.0 Fl_Menu_::menu_end() is called before the menu pops up to make sure the menu array is located in private storage. \see Fl_Menu_::menu_end() */ const Fl_Menu_Item* Fl_Menu_Button::popup() { menu_end(); const Fl_Menu_Item* m; pressed_menu_button_ = this; redraw(); Fl_Widget_Tracker mb(this); if (!box() || type()) { m = menu()->popup(Fl::event_x(), Fl::event_y(), label(), mvalue(), this); } else { m = menu()->pulldown(x(), y(), w(), h(), 0, this); } picked(m); pressed_menu_button_ = 0; if (mb.exists()) redraw(); return m; } int Fl_Menu_Button::handle(int e) { if (!menu() || !menu()->text) return 0; switch (e) { case FL_ENTER: /* FALLTHROUGH */ case FL_LEAVE: return (box() && !type()) ? 1 : 0; case FL_PUSH: if (!box()) { if (Fl::event_button() != 3) return 0; } else if (type()) { if (!(type() & (1 << (Fl::event_button()-1)))) return 0; } if (Fl::visible_focus()) Fl::focus(this); popup(); return 1; case FL_KEYBOARD: if (!box()) return 0; if (Fl::event_key() == ' ' && !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) { popup(); return 1; } else return 0; case FL_SHORTCUT: if (Fl_Widget::test_shortcut()) {popup(); return 1;} return test_shortcut() != 0; case FL_FOCUS: /* FALLTHROUGH */ case FL_UNFOCUS: if (box() && Fl::visible_focus()) { redraw(); return 1; } default: return 0; } } /** Creates a new Fl_Menu_Button widget using the given position, size, and label string. The default boxtype is FL_UP_BOX.

The constructor sets menu() to NULL. See Fl_Menu_ for the methods to set or change the menu. */ Fl_Menu_Button::Fl_Menu_Button(int X,int Y,int W,int H,const char *l) : Fl_Menu_(X,Y,W,H,l) { down_box(FL_NO_BOX); } fltk-1.4.3/src/Fl_Scheme.cxx0000644000175000017500000001070515004135251015750 0ustar albrechtalbrecht// // Scheme implementation for the Fast Light Tool Kit (FLTK). // // Copyright 2022-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include // fl_strdup #include // malloc, realloc const char **Fl_Scheme::names_ = NULL; int Fl_Scheme::num_schemes_ = 0; int Fl_Scheme::alloc_size_ = 0; /** Return a list of all known scheme names. This list is only valid until a new scheme is added or one is removed. It is possible that scheme names are appended to the list during the runtime of the program but schemes can't be removed. Getting the list of known schemes can be useful to populate a menu of scheme choices to let the user select a scheme. You should process the names immediately and you should never store a pointer to the list or any individual name for later reference because the location of the list can be changed (reallocated) when schemes are added. The list of scheme names is nul-terminated. \note Currently (in FLTK 1.4.0) schemes can only be added to the list and not removed from the list. This may change in a later version. \return List of currently known scheme names. */ const char **Fl_Scheme::names() { if (names_) return names_; alloc_size_ = 8; names_ = (const char **)malloc(alloc_size_ * sizeof(const char *)); // FIXME: register "known" scheme names ... add_scheme_name("base"); add_scheme_name("plastic"); add_scheme_name("gtk+"); add_scheme_name("gleam"); add_scheme_name("oxy"); return names_; } /** Add a scheme name to the list of known schemes. This method is public in FLTK 1.4.0 because derived classes of Fl_Scheme are not yet implemented. Thus, users implementing their own schemes can use this method to add the scheme name to the list of known schemes which is for instance used in Fl_Scheme::names(). \note \b Attention! In a future version, when subclasses of Fl_Scheme will be implemented, this method will either be replaced by another \p protected method or it will no longer do anything (kept only for ABI reasons). The new scheme name must consist of valid ASCII characters as described below: - lowercase letters \p 'a' - \p 'z' - numbers \p '0' - \p '9' - any character in \p "$+_." (w/o the quotes). The name must not be longer than 12 ASCII characters (bytes). The new scheme name is added to the \b end of the \b unordered list. \note Call this method only once for each scheme name. If the returned value is \<= 0 you should check the scheme name. The given scheme \p name is copied and may be freed directly after the call to add_scheme_name(). \param[in] name New scheme name \returns The new number of schemes if the name was successfully added. This is the same as the index of the scheme + 1. \retval 0 Scheme \p name already exists \retval -1 Invalid character(s) in \p name \retval -2 The \p name is too long \since 1.4.0 */ int Fl_Scheme::add_scheme_name(const char *name) { static const char valid_chars[] = "$+_."; // test if the scheme name is valid int nlen = static_cast(strlen(name)); if (nlen > 12) return (-2); for (int i = 0; i < nlen; i++) { if ((name[i] >= 'a' && name[i] <= 'z') || (name[i] >= '0' && name[i] <= '9')) continue; if (!strchr(valid_chars, name[i])) return (-1); } // Test if the scheme name already exists. // We know already that it consists only of valid characters, // hence we can use the faster strcmp() for comparison. const char **s = names(); for (int i = 0; i < num_schemes_; i++) { if (strcmp(name, s[i]) == 0) return 0; } // The scheme name is OK, we can add it. Take care that we need // a null pointer at the end of the list. num_schemes_++; if (num_schemes_ + 1 > alloc_size_) { // overflow, extend the list alloc_size_ += 8; names_ = (const char **)realloc(names_, alloc_size_ * sizeof(const char *)); } names_[num_schemes_-1] = fl_strdup(name); names_[num_schemes_] = NULL; return num_schemes_; } fltk-1.4.3/src/Fl_File_Chooser.fl0000644000175000017500000003752115004135251016711 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0403 header_name {../FL/Fl_File_Chooser.H} code_name {.cxx} comment {// // Fl_File_Chooser dialog for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // ======================================================================= // DO NOT EDIT FL/Fl_File_Chooser.H and src/Fl_File_Chooser.cxx !!! // ======================================================================= // Please use fluid to change src/Fl_File_Chooser.fl interactively // and then use fluid to "write code" or edit and use fluid -c . // ======================================================================= // } {in_source in_header } decl {\#include } {private local } class FL_EXPORT Fl_File_Chooser {open } { decl {enum Type { SINGLE = 0, ///< Select a single, existing file. MULTI = 1, ///< Select one or more existing files. CREATE = 2, ///< When used alone, select a single, existing file or specify a new filename. ///< Can be combined with DIRECTORY (e.g. CREATE|DIRECTORY) to have the same ///< effect for directories. DIRECTORY = 4 ///< Select a single, existing directory. Can be combined with CREATE. };} { comment {\\enum Type Determines the type of file chooser presented to the user. } public local } decl {static Fl_Preferences *prefs_;} {private local } decl {void (*callback_)(Fl_File_Chooser*, void *);} {private local } decl {void *data_;} {private local } decl {char directory_[FL_PATH_MAX];} {private local } decl {char pattern_[FL_PATH_MAX];} {private local } decl {char preview_text_[2048];} {private local } decl {int type_;} {private local } decl {void favoritesButtonCB();} {private local } decl {void favoritesCB(Fl_Widget *w);} {private local } decl {void fileListCB();} {private local } decl {void fileNameCB();} {private local } decl {void newdir();} {private local } decl {static void previewCB(Fl_File_Chooser *fc);} {private local } decl {void showChoiceCB();} {private local } decl {void update_favorites();} {private local } decl {void update_preview();} {private local } Function {Fl_File_Chooser(const char *pathname, const char *pattern, int type_val, const char *title)} {open } { code {if (!prefs_) { prefs_ = new Fl_Preferences(Fl_Preferences::CORE_USER, "fltk.org", "filechooser"); }} {} code {Fl_Group *prev_current = Fl_Group::current();} {} Fl_Window window { label {Choose File} callback {fileName->value(""); fileList->deselect(); hide();} open selected private xywh {467 276 490 380} type Double resizable code0 {if (title) window->label(title);} modal visible } { Fl_Group {} {open private xywh {10 10 470 25} } { Fl_Choice showChoice { label {Show:} callback {showChoiceCB();} open private xywh {65 10 215 25} down_box BORDER_BOX labelfont 1 resizable code0 {showChoice->label(show_label);} } {} Fl_Menu_Button favoritesButton { label Favorites callback {favoritesButtonCB();} open private xywh {290 10 155 25} down_box BORDER_BOX align 20 code0 {favoritesButton->label(favorites_label);} } {} Fl_Button newButton { callback {newdir();} image {new.xbm} compress_image 0 xywh {455 10 25 25} labelsize 8 code0 {\#include } code1 {o->tooltip(new_directory_tooltip);} } } Fl_Tile {} { callback {update_preview();} open private xywh {10 45 470 225} resizable } { Fl_File_Browser fileList { callback {fileListCB();} private xywh {10 45 295 225} type Hold box DOWN_BOX hotspot code0 {\#include } } Fl_Box errorBox { label {dynamic error display} private xywh {10 45 295 225} box DOWN_BOX color 7 labelsize 18 labelcolor 1 align 149 hide } Fl_Box previewBox { label {?} private xywh {305 45 175 225} box DOWN_BOX labelsize 100 align 80 } } Fl_Group {} {open private xywh {10 275 470 95} } { Fl_Group {} {open private xywh {10 275 470 20} } { Fl_Check_Button previewButton { label Preview callback {preview(previewButton->value());} xywh {10 275 105 20} down_box DOWN_BOX shortcut 0x80070 value 1 code0 {previewButton->label(preview_label);} } Fl_Check_Button showHiddenButton { label {Show hidden files} callback {showHidden(showHiddenButton->value());} xywh {115 275 140 20} down_box DOWN_BOX code0 {showHiddenButton->label(hidden_label);} } Fl_Box {} { private xywh {255 275 225 20} resizable } } Fl_File_Input fileName { callback {fileNameCB();} private xywh {115 300 365 35} labelfont 1 when 8 resizable code0 {fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY_ALWAYS);} } Fl_Box {} { label {Filename:} private xywh {10 310 105 25} labelfont 1 align 24 code0 {o->label(filename_label);} } Fl_Group {} {open private xywh {10 345 470 25} } { Fl_Return_Button okButton { label OK callback {hide(); // Do any callback that is registered... if (callback_) (*callback_)(this, data_);} private xywh {313 345 85 25} code0 {\#include } code1 {okButton->label(fl_ok);} } Fl_Button cancelButton { label Cancel callback {fileName->value(""); fileList->deselect(); hide();} private xywh {408 345 72 25} code0 {o->label(fl_cancel);} } Fl_Box {} { private xywh {10 345 30 25} resizable } } } } Fl_Window favWindow { label {Manage Favorites} private xywh {0 0 355 150} type Double hide resizable code0 {favWindow->label(manage_favorites_label);} modal size_range {181 150 0 0} } { Fl_File_Browser favList { callback {favoritesCB(favList);} private xywh {10 10 300 95} type Hold resizable } Fl_Group {} {open xywh {320 10 25 95} } { Fl_Button favUpButton { label {@8>} callback {favoritesCB(favUpButton);} private xywh {320 10 25 25} } Fl_Button favDeleteButton { label X callback {favoritesCB(favDeleteButton);} private xywh {320 45 25 25} labelfont 1 resizable } Fl_Button favDownButton { label {@2>} callback {favoritesCB(favDownButton);} private xywh {320 80 25 25} } } Fl_Group {} {open xywh {10 113 335 29} } { Fl_Button favCancelButton { label Cancel callback {favWindow->hide();} private xywh {273 115 72 25} code0 {favCancelButton->label(fl_cancel);} } Fl_Return_Button favOkButton { label Save callback {favoritesCB(favOkButton);} private xywh {181 115 79 25} code0 {\#include } code1 {favOkButton->label(save_label);} } Fl_Box {} { xywh {10 115 161 25} resizable } } } code {callback_ = 0; data_ = 0; directory_[0] = 0; window->size_range(window->w(), window->h()); type(type_val); filter(pattern); update_favorites(); value(pathname); type(type_val); int e; prefs_->get("preview", e, 1); preview(e); Fl_Group::current(prev_current);} {} code {ext_group=(Fl_Widget*)0;} {} } Function {~Fl_File_Chooser()} {open } { code {Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this); if(ext_group)window->remove(ext_group); delete window; delete favWindow;} {} } Function {callback(void (*cb)(Fl_File_Chooser *, void *), void *d = 0)} {return_type void } { code {callback_ = cb; data_ = d;} {} } Function {color(Fl_Color c)} {} { code {fileList->color(c);} {} } Function {color()} {return_type Fl_Color } { code {return (fileList->color());} {} } decl {int count();} {public local } decl {void directory(const char *d);} {public local } Function {directory()} {return_type {char *} } { code {return directory_;} {} } decl {void filter(const char *p);} {public local } Function {filter()} {return_type {const char *} } { code {return (fileList->filter());} {} } Function {filter_value()} {return_type int } { code {return showChoice->value();} {} } Function {filter_value(int f)} {return_type void } { code {showChoice->value(f); showChoiceCB();} {} } Function {iconsize(uchar s)} {return_type void } { code {fileList->iconsize(s);} {} } Function {iconsize()} {return_type uchar } { code {return (fileList->iconsize());} {} } Function {label(const char *l)} {return_type void } { code {window->label(l);} {} } Function {label()} {return_type {const char *} } { code {return (window->label());} {} } Function {ok_label(const char *l)} {return_type void } { code {if (l) okButton->label(l); int w=0, h=0; okButton->measure_label(w, h); okButton->resize(cancelButton->x() - 50 - w, cancelButton->y(), w + 40, 25); okButton->parent()->init_sizes();} {} } Function {ok_label()} {return_type {const char *} } { code {return (okButton->label());} {} } decl {void preview(int e);} {public local } decl {int preview() const { return previewButton->value(); }} {public local } decl {void showHidden(int e);} {private local } decl {void remove_hidden_files();} {private local } decl {void rescan();} {public local } decl {void rescan_keep_filename();} {public local } decl {void show();} {public local } decl {void hide();} {public local } Function {shown()} {return_type int } { code {return window->shown();} {} } Function {textcolor(Fl_Color c)} {return_type void } { code {fileList->textcolor(c);} {} } Function {textcolor()} {return_type Fl_Color } { code {return (fileList->textcolor());} {} } Function {textfont(Fl_Font f)} {return_type void } { code {fileList->textfont(f);} {} } Function {textfont()} {return_type Fl_Font } { code {return (fileList->textfont());} {} } Function {textsize(Fl_Fontsize s)} {return_type void } { code {fileList->textsize(s);} {} } Function {textsize()} {return_type Fl_Fontsize } { code {return (fileList->textsize());} {} } Function {type(int t)} {return_type void } { code {type_ = t; if (t & MULTI) fileList->type(FL_MULTI_BROWSER); else fileList->type(FL_HOLD_BROWSER); if (t & CREATE) newButton->activate(); else newButton->deactivate(); if (t & DIRECTORY) fileList->filetype(Fl_File_Browser::DIRECTORIES); else fileList->filetype(Fl_File_Browser::FILES);} {} } Function {type()} {return_type int } { code {return (type_);} {} } Function {user_data() const} {return_type {void *} } { code {return (data_);} {} } Function {user_data(void *d)} {return_type void } { code {data_ = d;} {} } decl {const char *value(int f = 1);} {public local } decl {void value(const char *filename);} {public local } Function {visible()} {return_type int } { code {return window->visible();} {} } Function {position(int x, int y)} {return_type void } { code {window->position(x, y);} {} } Function {x() const} {return_type int } { code {return window->x();} {} } Function {y() const} {return_type int } { code {return window->y();} {} } Function {w() const} {return_type int } { code {return window->w();} {} } Function {h() const} {return_type int } { code {return window->h();} {} } Function {size(int w, int h)} {open return_type void } { code {window->size(w, h);} {} } Function {resize(int x, int y, int w, int h)} {open return_type void } { code {window->resize(x, y, w, h);} {} } decl {static const char *add_favorites_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *all_files_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *custom_filter_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *existing_file_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *favorites_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *filename_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *filesystems_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *manage_favorites_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *new_directory_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *new_directory_tooltip;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *preview_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *save_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *show_label;} { comment {[standard text may be customized at run-time]} public local } decl {static const char *hidden_label;} { comment {[standard text may be customized at run-time]} public local } decl {static Fl_File_Sort_F *sort;} { comment {the sort function that is used when loading the contents of a directory.} public local } decl {Fl_Widget* ext_group;} {private local } Function {add_extra(Fl_Widget* gr)} {open return_type {Fl_Widget*} } { code {Fl_Widget* ret=ext_group;} {} codeblock {if (gr==ext_group)} {open } { code {return ret;} {} } codeblock {if (ext_group)} {open } { code {int sh=ext_group->h()+4; Fl_Widget* svres=window->resizable(); window->resizable(NULL); window->size(window->w(),window->h()-sh); window->remove(ext_group); ext_group=NULL; window->resizable(svres);} {} } codeblock {if (gr)} {open } { code {int nh=window->h()+gr->h()+4; Fl_Widget* svres=window->resizable(); window->resizable(NULL); window->size(window->w(),nh); gr->position(2,okButton->y()+okButton->h()+2); window->add(gr); ext_group=gr; window->resizable(svres);} {} } code {return ret;} {} } Function {show_error_box(int val)} { comment {Show error box if val=1, hide if val=0} open protected return_type void } { code {if ( val ) { errorBox->color(fileList->color()); // inherit fileList's bg color errorBox->show(); fileList->hide(); } else { errorBox->hide(); fileList->show(); }} {} } } decl {FL_EXPORT char *fl_dir_chooser(const char *message,const char *fname,int relative=0);} {public local } decl {FL_EXPORT char *fl_file_chooser(const char *message,const char *pat,const char *fname,int relative=0);} {public local } decl {FL_EXPORT void fl_file_chooser_callback(void (*cb)(const char*));} {public local } decl {FL_EXPORT void fl_file_chooser_ok_label(const char*l);} {public local } fltk-1.4.3/src/Fl_Browser_.cxx0000644000175000017500000010524215004135251016327 0ustar albrechtalbrecht// // Base Browser widget class for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #define DISPLAY_SEARCH_BOTH_WAYS_AT_ONCE #include #include #include #include #include #include // This is the base class for browsers. To be useful it must be // subclassed and several virtual functions defined. The // Forms-compatible browser and the file chooser's browser are // subclassed off of this. // Yes, I know this should be a template... // This has been designed so that the subclass has complete control // over the storage of the data, although because next() and prev() // functions are used to index, it works best as a linked list or as a // large block of characters in which the line breaks must be searched // for. // A great deal of work has been done so that the "height" of a data // object does not need to be determined until it is drawn. This was // done for the file chooser, because the height requires doing stat() // to see if the file is a directory, which can be annoyingly slow // over the network. /* redraw bits: 1 = redraw children (the scrollbar) 2 = redraw one or two items 4 = redraw all items */ static void scrollbar_callback(Fl_Widget* s, void*) { ((Fl_Browser_*)(s->parent()))->vposition(int(((Fl_Scrollbar*)s)->value())); } static void hscrollbar_callback(Fl_Widget* s, void*) { ((Fl_Browser_*)(s->parent()))->hposition(int(((Fl_Scrollbar*)s)->value())); } // return where to draw the actual box: /** Returns the bounding box for the interior of the list's display window, inside the scrollbars. \param[out] X,Y,W,H The returned bounding box.\n (The original contents of these parameters are overwritten) */ void Fl_Browser_::bbox(int& X, int& Y, int& W, int& H) const { int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size(); Fl_Boxtype b = box() ? box() : FL_DOWN_BOX; X = x()+Fl::box_dx(b); Y = y()+Fl::box_dy(b); W = w()-Fl::box_dw(b); H = h()-Fl::box_dh(b); if (scrollbar.visible()) { W -= scrollsize; if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollsize; } if (W < 0) W = 0; if (hscrollbar.visible()) { H -= scrollsize; if (scrollbar.align() & FL_ALIGN_TOP) Y += scrollsize; } if (H < 0) H = 0; } /** This method returns the X position of the left edge of the list area after adjusting for the scrollbar and border, if any. \returns The X position of the left edge of the list, in pixels. \see Fl_Browser_::bbox() */ int Fl_Browser_::leftedge() const { int X, Y, W, H; bbox(X, Y, W, H); return X; } // The scrollbars may be moved again by draw(), since each one's size // depends on whether the other is visible or not. This skips over // Fl_Group::resize since it moves the scrollbars uselessly. /** Repositions and/or resizes the browser. \param[in] X,Y,W,H The new position and size for the browser, in pixels. */ void Fl_Browser_::resize(int X, int Y, int W, int H) { int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size(); Fl_Widget::resize(X, Y, W, H); // move the scrollbars so they can respond to events: bbox(X,Y,W,H); scrollbar.resize( scrollbar.align()&FL_ALIGN_LEFT ? X-scrollsize : X+W, Y, scrollsize, H); hscrollbar.resize( X, scrollbar.align()&FL_ALIGN_TOP ? Y-scrollsize : Y+H, W, scrollsize); max_width = 0; } // Cause minimal update to redraw the given item: /** This method should be called when the contents of \p item has changed, but not its height. \param[in] item The item that needs to be redrawn. \see redraw_lines(), redraw_line() */ void Fl_Browser_::redraw_line(void* item) { if (!redraw1 || redraw1 == item) {redraw1 = item; damage(FL_DAMAGE_EXPOSE);} else if (!redraw2 || redraw2 == item) {redraw2 = item; damage(FL_DAMAGE_EXPOSE);} else damage(FL_DAMAGE_SCROLL); } // Figure out top() based on position(): void Fl_Browser_::update_top() { if (!top_) top_ = item_first(); if (position_ != real_position_) { void* l; int ly; int yy = position_; // start from either head or current position, whichever is closer: if (!top_ || yy <= (real_position_/2)) { l = item_first(); ly = 0; } else { l = top_; ly = real_position_-offset_; } if (!l) { top_ = 0; offset_ = 0; real_position_ = 0; } else { int hh = item_quick_height(l) + linespacing(); // step through list until we find line containing this point: while (ly > yy) { void* l1 = item_prev(l); if (!l1) {ly = 0; break;} // hit the top l = l1; hh = item_quick_height(l) + linespacing(); ly -= hh; } while ((ly+hh) <= yy) { void* l1 = item_next(l); if (!l1) {yy = ly+hh-1; break;} l = l1; ly += hh; hh = item_quick_height(l) + linespacing(); } // top item must *really* be visible, use slow height: for (;;) { hh = item_height(l) + linespacing(); if ((ly+hh) > yy) break; // it is big enough to see // go up to top of previous item: void* l1 = item_prev(l); if (!l1) {ly = yy = 0; break;} // hit the top l = l1; yy = position_ = ly = ly-item_quick_height(l) + linespacing(); } // use it: top_ = l; offset_ = yy-ly; real_position_ = yy; } damage(FL_DAMAGE_SCROLL); } } // Change vposition(), top() will update when update_top() is called // (probably by draw() or handle()): /** Sets the vertical scroll position of the list to pixel position \p pos. The position is how many pixels of the list are scrolled off the top edge of the screen. Example: A position of '3' scrolls the top three pixels of the list off the top edge of the screen. \param[in] pos The vertical position (in pixels) to scroll the browser to. \see vposition(), hposition() */ void Fl_Browser_::vposition(int pos) { if (pos < 0) pos = 0; if (pos == position_) return; position_ = pos; if (pos != real_position_) redraw_lines(); } /** Sets the horizontal scroll position of the list to pixel position \p pos. The position is how many pixels of the list are scrolled off the left edge of the screen. Example: A position of '18' scrolls the left 18 pixels of the list off the left edge of the screen. \param[in] pos The horizontal position (in pixels) to scroll the browser to. \see vposition(), hposition() */ void Fl_Browser_::hposition(int pos) { if (pos < 0) pos = 0; if (pos == hposition_) return; hposition_ = pos; if (pos != real_hposition_) redraw_lines(); } // Tell whether item is currently displayed: /** Returns non-zero if \p item has been scrolled to a position where it is being displayed. Checks to see if the item's vertical position is within the top and bottom edges of the display window. This does NOT take into account the hide()/show() status of the widget or item. \param[in] item The item to check \returns 1 if visible, 0 if not visible. \see display(), displayed() */ int Fl_Browser_::displayed(void* item) const { int X, Y, W, H; bbox(X, Y, W, H); int yy = H+offset_; for (void* l = top_; l && yy > 0; l = item_next(l)) { if (l == item) return 1; yy -= item_height(l) + linespacing(); } return 0; } // Ensure this item is displayed: // Messy because we have no idea if it is before top or after bottom: /** Displays the \p item, scrolling the list as necessary. \param[in] item The item to be displayed. \see display(), displayed() */ void Fl_Browser_::display(void* item) { // First special case - want to display first item in the list? update_top(); if (item == item_first()) { vposition(0); return; } int X, Y, W, H, Yp; bbox(X, Y, W, H); void* l = top_; Y = Yp = -offset_; int h1; // 2nd special case - want to display item already displayed at top of browser? if (l == item) { vposition(real_position_+Y); return; } // scroll up a bit // 3rd special case - want to display item just above top of browser? void* lp = item_prev(l); if (lp == item) { vposition(real_position_+Y-item_quick_height(lp)-linespacing()); return; } #ifdef DISPLAY_SEARCH_BOTH_WAYS_AT_ONCE // search for item. We search both up and down the list at the same time, // this evens up the execution time for the two cases - the old way was // much slower for going up than for going down. while (l || lp) { if (l) { h1 = item_quick_height(l) + linespacing(); if (l == item) { if (Y <= H) { // it is visible or right at bottom Y = Y+h1-H; // find where bottom edge is if (Y > 0) vposition(real_position_+Y); // scroll down a bit } else { vposition(real_position_+Y-(H-h1)/2); // center it } return; } Y += h1; l = item_next(l); } if (lp) { h1 = item_quick_height(lp) + linespacing(); Yp -= h1; if (lp == item) { if ((Yp + h1) >= 0) vposition(real_position_+Yp); else vposition(real_position_+Yp-(H-h1)/2); return; } lp = item_prev(lp); } } #else // Old version went forwards and then backwards: // search forward for it: l = top_; for (; l; l = item_next(l)) { h1 = item_quick_height(l) + linespacing(); if (l == item) { if (Y <= H) { // it is visible or right at bottom Y = Y+h1-H; // find where bottom edge is if (Y > 0) position(real_position_+Y); // scroll down a bit } else { position(real_position_+Y-(H-h1)/2); // center it } return; } Y += h1; } // search backward for it, if found center it: l = lp; Y = -offset_; for (; l; l = item_prev(l)) { h1 = item_quick_height(l) + linespacing(); Y -= h1; if (l == item) { if ((Y + h1) >= 0) position(real_position_+Y); else position(real_position_+Y-(H-h1)/2); return; } } #endif } // redraw, has side effect of updating top and setting scrollbar: /** Draws the list within the normal widget bounding box. */ void Fl_Browser_::draw() { int drawsquare = 0; update_top(); int full_width_ = full_width(); int full_height_ = full_height(); int X, Y, W, H; bbox(X, Y, W, H); int dont_repeat = 0; J1: if (damage() & FL_DAMAGE_ALL) { // redraw the box if full redraw Fl_Boxtype b = box() ? box() : FL_DOWN_BOX; draw_box(b, x(), y(), w(), h(), color()); drawsquare = 1; } // see if scrollbar needs to be switched on/off: if ((has_scrollbar_ & VERTICAL) && ( (has_scrollbar_ & ALWAYS_ON) || position_ || full_height_ > H)) { if (!scrollbar.visible()) { scrollbar.set_visible(); drawsquare = 1; bbox(X, Y, W, H); } } else { top_ = item_first(); real_position_ = offset_ = 0; if (scrollbar.visible()) { scrollbar.clear_visible(); clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL)); } } if ((has_scrollbar_ & HORIZONTAL) && ( (has_scrollbar_ & ALWAYS_ON) || hposition_ || full_width_ > W)) { if (!hscrollbar.visible()) { hscrollbar.set_visible(); drawsquare = 1; bbox(X, Y, W, H); } } else { real_hposition_ = 0; if (hscrollbar.visible()) { hscrollbar.clear_visible(); clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL)); } } // Check the vertical scrollbar again, just in case it needs to be drawn // because the horizontal one is drawn. There should be a cleaner way // to do this besides copying the same code... if ((has_scrollbar_ & VERTICAL) && ( (has_scrollbar_ & ALWAYS_ON) || position_ || full_height_ > H)) { if (!scrollbar.visible()) { scrollbar.set_visible(); drawsquare = 1; bbox(X, Y, W, H); } } else { top_ = item_first(); real_position_ = offset_ = 0; if (scrollbar.visible()) { scrollbar.clear_visible(); clear_damage((uchar)(damage()|FL_DAMAGE_SCROLL)); } } bbox(X, Y, W, H); fl_push_clip(X, Y, W, H); // for each line, draw it if full redraw or scrolled. Erase background // if not a full redraw or if it is selected: void* l = top(); int yy = -offset_; for (; l && yy < H; l = item_next(l)) { int hh = item_height(l) + linespacing(); if (hh <= 0) continue; if ((damage()&(FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) || l == redraw1 || l == redraw2) { if (item_selected(l)) { fl_color(active_r() ? selection_color() : fl_inactive(selection_color())); fl_rectf(X, yy+Y, W, hh); } else if (!(damage()&FL_DAMAGE_ALL)) { fl_push_clip(X, yy+Y, W, hh); draw_box(box() ? box() : FL_DOWN_BOX, x(), y(), w(), h(), color()); fl_pop_clip(); } item_draw(l, X-hposition_, yy+Y, W+hposition_, hh); if (l == selection_ && Fl::focus() == this) { draw_box(FL_BORDER_FRAME, X, yy+Y, W, hh, color()); draw_focus(FL_NO_BOX, X, yy+Y, W+1, hh+1); } int ww = item_width(l); if (ww > max_width) {max_width = ww; max_width_item = l;} } yy += hh; } // erase the area below last line: if (!(damage()&FL_DAMAGE_ALL) && yy < H) { fl_push_clip(X, yy+Y, W, H-yy); draw_box(box() ? box() : FL_DOWN_BOX, x(), y(), w(), h(), color()); fl_pop_clip(); } fl_pop_clip(); fl_push_clip(x(),y(),w(),h()); // STR# 2886 redraw1 = redraw2 = 0; if (!dont_repeat) { dont_repeat = 1; // see if changes to full_height caused by calls to slow_height // caused scrollbar state to change, in which case we have to redraw: full_height_ = full_height(); full_width_ = full_width(); if ((has_scrollbar_ & VERTICAL) && ((has_scrollbar_ & ALWAYS_ON) || position_ || full_height_>H)) { if (!scrollbar.visible()) { damage(FL_DAMAGE_ALL); fl_pop_clip(); goto J1; } } else { if (scrollbar.visible()) { damage(FL_DAMAGE_ALL); fl_pop_clip(); goto J1; } } if ((has_scrollbar_ & HORIZONTAL) && ((has_scrollbar_ & ALWAYS_ON) || hposition_ || full_width_>W)) { if (!hscrollbar.visible()) { damage(FL_DAMAGE_ALL); fl_pop_clip(); goto J1; } } else { if (hscrollbar.visible()) { damage(FL_DAMAGE_ALL); fl_pop_clip(); goto J1; } } } // update the scrollbars and redraw them: int scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size(); int dy = top_ ? item_quick_height(top_) + linespacing() : 0; if (dy < 10) dy = 10; if (scrollbar.visible()) { scrollbar.damage_resize( scrollbar.align()&FL_ALIGN_LEFT ? X-scrollsize : X+W, Y, scrollsize, H); scrollbar.value(position_, H, 0, full_height_); scrollbar.linesize(dy); if (drawsquare) draw_child(scrollbar); else update_child(scrollbar); } if (hscrollbar.visible()) { hscrollbar.damage_resize( X, scrollbar.align()&FL_ALIGN_TOP ? Y-scrollsize : Y+H, W, scrollsize); hscrollbar.value(hposition_, W, 0, full_width_); hscrollbar.linesize(dy); if (drawsquare) draw_child(hscrollbar); else update_child(hscrollbar); } // draw that little square between the scrollbars: if (drawsquare && scrollbar.visible() && hscrollbar.visible()) { fl_color(parent()->color()); fl_rectf(scrollbar.x(), hscrollbar.y(), scrollsize, scrollsize); } real_hposition_ = hposition_; fl_pop_clip(); } // Quick way to delete and reset everything: /** This method should be called when the list data is completely replaced or cleared. It informs the Fl_Browser_ widget that any cached information it has concerning the items is invalid. This method does not clear the list, it just handles the follow up bookkeeping after the list has been cleared. */ void Fl_Browser_::new_list() { top_ = 0; position_ = real_position_ = 0; hposition_ = real_hposition_ = 0; selection_ = 0; offset_ = 0; max_width = 0; max_width_item = 0; redraw_lines(); } // Tell it that this item is going away, and that this must remove // all pointers to it: /** This method should be used when \p item is being deleted from the list. It allows the Fl_Browser_ to discard any cached data it has on the item. This method does not actually delete the item, but handles the follow up bookkeeping after the item has just been deleted. \param[in] item The item being deleted. */ void Fl_Browser_::deleting(void* item) { if (displayed(item)) { redraw_lines(); if (item == top_) { real_position_ -= offset_; offset_ = 0; top_ = item_next(item); if (!top_) top_ = item_prev(item); } } else { // we don't know where this item is, recalculate top... real_position_ = 0; offset_ = 0; top_ = 0; } if (item == selection_) selection_ = 0; if (item == max_width_item) {max_width_item = 0; max_width = 0;} } /** This method should be used when item \p a is being replaced by item \p b. It allows the Fl_Browser_ to update its cache data as needed, schedules a redraw for the item being changed, and tries to maintain the selection. This method does not actually replace the item, but handles the follow up bookkeeping after the item has just been replaced. \param[in] a Item being replaced \param[in] b Item to replace 'a' */ void Fl_Browser_::replacing(void* a, void* b) { redraw_line(a); if (a == selection_) selection_ = b; if (a == top_) top_ = b; if (a == max_width_item) {max_width_item = 0; max_width = 0;} } /** This method should be used when two items \p a and \p b are being swapped. It allows the Fl_Browser_ to update its cache data as needed, schedules a redraw for the two items, and tries to maintain the current selection. This method does not actually swap items, but handles the follow up bookkeeping after items have been swapped. \param[in] a,b Items being swapped. */ void Fl_Browser_::swapping(void* a, void* b) { redraw_line(a); redraw_line(b); if (a == selection_) selection_ = b; else if (b == selection_) selection_ = a; if (a == top_) top_ = b; else if (b == top_) top_ = a; } /** This method should be used when an item is in the process of being inserted into the list. It allows the Fl_Browser_ to update its cache data as needed, scheduling a redraw for the affected lines. This method does not actually insert items, but handles the follow up bookkeeping after items have been inserted. \param[in] a The starting item position \param[in] b The new item being inserted */ void Fl_Browser_::inserting(void* a, void* b) { if (displayed(a)) redraw_lines(); if (a == top_) top_ = b; } /** This method returns the item under mouse y position \p ypos. NULL is returned if no item is displayed at that position. \param[in] ypos The y position (eg. Fl::event_y()) to find an item under. \returns The item, or NULL if not found */ void* Fl_Browser_::find_item(int ypos) { update_top(); int X, Y, W, H; bbox(X, Y, W, H); int yy = Y-offset_; for (void *l = top_; l; l = item_next(l)) { int hh = item_height(l); if (hh <= 0) continue; yy += hh + linespacing(); if (ypos <= yy || yy>=(Y+H)) return l; } return 0; } /** Sets the selection state of \p item to \p val, and returns 1 if the state changed or 0 if it did not. If \p docallbacks is non-zero, select tries to call the callback function for the widget. \param[in] item The item whose selection state is to be changed \param[in] val The new selection state (1=select, 0=de-select) \param[in] docallbacks If non-zero, invokes widget callback if item changed.\n If 0, doesn't do callback (default). \returns 1 if state was changed, 0 if not. */ int Fl_Browser_::select(void* item, int val, int docallbacks) { if (type() == FL_MULTI_BROWSER) { if (selection_ != item) { if (selection_) redraw_line(selection_); selection_ = item; redraw_line(item); } if ((!val)==(!item_selected(item))) return 0; item_select(item, val); redraw_line(item); } else { if (val && selection_ == item) return 0; if (!val && selection_ != item) return 0; if (selection_) { item_select(selection_, 0); redraw_line(selection_); selection_ = 0; } if (val) { item_select(item, 1); selection_ = item; redraw_line(item); display(item); } } if (docallbacks) { set_changed(); do_callback(FL_REASON_CHANGED); } return 1; } /** Deselects all items in the list and returns 1 if the state changed or 0 if it did not. If the optional \p docallbacks parameter is non-zero, deselect tries to call the callback function for the widget. \param[in] docallbacks If non-zero, invokes widget callback if item changed.\n If 0, doesn't do callback (default). */ int Fl_Browser_::deselect(int docallbacks) { if (type() == FL_MULTI_BROWSER) { int change = 0; for (void* p = item_first(); p; p = item_next(p)) change |= select(p, 0, docallbacks); return change; } else { if (!selection_) return 0; item_select(selection_, 0); redraw_line(selection_); selection_ = 0; return 1; } } /** Selects \p item and returns 1 if the state changed or 0 if it did not. Any other items in the list are deselected. \param[in] item The \p item to select. \param[in] docallbacks If non-zero, invokes widget callback if item changed.\n If 0, doesn't do callback (default). */ int Fl_Browser_::select_only(void* item, int docallbacks) { if (!item) return deselect(docallbacks); int change = 0; Fl_Widget_Tracker wp(this); if (type() == FL_MULTI_BROWSER) { for (void* p = item_first(); p; p = item_next(p)) { if (p != item) change |= select(p, 0, docallbacks); if (wp.deleted()) return change; } } change |= select(item, 1, docallbacks); if (wp.deleted()) return change; display(item); return change; } /** Handles the \p event within the normal widget bounding box. \param[in] event The event to process. \returns 1 if event was processed, 0 if not. */ int Fl_Browser_::handle(int event) { // NOTE: // We use Fl_Widget_Tracker to test if the user has deleted // this widget in a callback. Callbacks can be called by: // - do_callback() // - select() // - select_only() // - deselect() // Thus we must test wp.deleted() after each of these calls, // unless we return directly after one of these. // If wp.deleted() is true, we return 1 because we used the event. Fl_Widget_Tracker wp(this); // must do shortcuts first or the scrollbar will get them... if (event == FL_ENTER || event == FL_LEAVE) return 1; if (event == FL_KEYBOARD && type() >= FL_HOLD_BROWSER) { void* l1 = selection_; void* l = l1; if (!l) l = top_; if (!l) l = item_first(); if (l) { if (type()==FL_HOLD_BROWSER) { switch (Fl::event_key()) { case FL_Down: while ((l = item_next(l))) { if (item_height(l)>0) {select_only(l, when()); break;} } return 1; case FL_Up: while ((l = item_prev(l))) { if (item_height(l)>0) { select_only(l, when()); break; // no need to test wp (return 1) } } return 1; } } else { switch (Fl::event_key()) { case FL_Enter: case FL_KP_Enter: select_only(l, when() & ~FL_WHEN_ENTER_KEY); if (wp.deleted()) return 1; if (when() & FL_WHEN_ENTER_KEY) { set_changed(); do_callback(FL_REASON_CHANGED); } return 1; case ' ': selection_ = l; select(l, !item_selected(l), when() & ~FL_WHEN_ENTER_KEY); return 1; case FL_Down: while ((l = item_next(l))) { if (Fl::event_state(FL_SHIFT|FL_CTRL)) select(l, l1 ? item_selected(l1) : 1, when()); if (wp.deleted()) return 1; if (item_height(l)>0) goto J1; } return 1; case FL_Up: while ((l = item_prev(l))) { if (Fl::event_state(FL_SHIFT|FL_CTRL)) select(l, l1 ? item_selected(l1) : 1, when()); if (wp.deleted()) return 1; if (item_height(l)>0) goto J1; } return 1; J1: if (selection_) redraw_line(selection_); selection_ = l; redraw_line(l); display(l); return 1; } } } } if (Fl_Group::handle(event)) return 1; if (wp.deleted()) return 1; int X, Y, W, H; bbox(X, Y, W, H); int my; // NOTE: // instead of: // change = select_only(find_item(my), when() & FL_WHEN_CHANGED) // we use the construct: // change = select_only(find_item(my), 0); // if (change && (when() & FL_WHEN_CHANGED)) { // set_changed(); // do_callback(); // } // See str #834 // The first form calls the callback *before* setting change. // The callback may execute an Fl::wait(), resulting in another // call of Fl_Browser_::handle() for the same widget. The sequence // of events can be an FL_PUSH followed by an FL_RELEASE. // This second call of Fl_Browser_::handle() may result in a - // somewhat unexpected - second concurrent invocation of the callback. static char change; static char whichway; static int py; switch (event) { case FL_PUSH: if (!Fl::event_inside(X, Y, W, H)) return 0; if (Fl::visible_focus()) { Fl::focus(this); redraw(); } my = py = Fl::event_y(); change = 0; if (type() == FL_NORMAL_BROWSER || !top_) ; else if (type() != FL_MULTI_BROWSER) { change = select_only(find_item(my), 0); if (wp.deleted()) return 1; if (change && (when() & FL_WHEN_CHANGED)) { set_changed(); do_callback(FL_REASON_CHANGED); if (wp.deleted()) return 1; } } else { void* l = find_item(my); whichway = 1; if (Fl::event_state(FL_COMMAND)) { // toggle selection: TOGGLE: if (l) { whichway = !item_selected(l); change = select(l, whichway, 0); if (wp.deleted()) return 1; if (change && (when() & FL_WHEN_CHANGED)) { set_changed(); do_callback(FL_REASON_CHANGED); if (wp.deleted()) return 1; } } } else if (Fl::event_state(FL_SHIFT)) { // extend selection: if (l == selection_) goto TOGGLE; // state of previous selection determines new value: whichway = l ? !item_selected(l) : 1; // see which of the new item or previous selection is earlier, // by searching from the previous forward for this one: int down; if (!l) down = 1; else {for (void* m = selection_; ; m = item_next(m)) { if (m == l) {down = 1; break;} if (!m) {down = 0; break;} }} if (down) { for (void* m = selection_; m != l; m = item_next(m)) { select(m, whichway, when() & FL_WHEN_CHANGED); if (wp.deleted()) return 1; } } else { void* e = selection_; for (void* m = item_next(l); m; m = item_next(m)) { select(m, whichway, when() & FL_WHEN_CHANGED); if (wp.deleted()) return 1; if (m == e) break; } } // do the clicked item last so the select box is around it: change = 1; if (l) select(l, whichway, when() & FL_WHEN_CHANGED); if (wp.deleted()) return 1; } else { // select only this item change = select_only(l, 0); if (wp.deleted()) return 1; if (change && (when() & FL_WHEN_CHANGED)) { set_changed(); do_callback(FL_REASON_CHANGED); if (wp.deleted()) return 1; } } } return 1; case FL_DRAG: // do the scrolling first: my = Fl::event_y(); if (my < Y && my < py) { int p = real_position_+my-Y; if (p<0) p = 0; vposition(p); } else if (my > (Y+H) && my > py) { int p = real_position_+my-(Y+H); int hh = full_height()-H; if (p > hh) p = hh; if (p<0) p = 0; vposition(p); } if (type() == FL_NORMAL_BROWSER || !top_) ; else if (type() == FL_MULTI_BROWSER) { void* l = find_item(my); void* t; void* b; // this will be the range to change if (my > py) { // go down t = selection_ ? item_next(selection_) : 0; b = l ? item_next(l) : 0; } else { // go up t = l; b = selection_; } for (; t && t != b; t = item_next(t)) { char change_t; change_t = select(t, whichway, 0); if (wp.deleted()) return 1; change |= change_t; if (change_t && (when() & FL_WHEN_CHANGED)) { set_changed(); do_callback(FL_REASON_CHANGED); if (wp.deleted()) return 1; } } if (l) selection_ = l; } else { void* l1 = selection_; void* l = (Fl::event_x()x()+w()) ? selection_ : find_item(my); change = (l != l1); select_only(l, when() & FL_WHEN_CHANGED); if (wp.deleted()) return 1; } py = my; return 1; case FL_RELEASE: if (type() == FL_SELECT_BROWSER) { void* t = selection_; deselect(); if (wp.deleted()) return 1; selection_ = t; } if (change) { set_changed(); if (when() & FL_WHEN_RELEASE) do_callback(FL_REASON_CHANGED); } else { if (when() & FL_WHEN_NOT_CHANGED) do_callback(FL_REASON_RESELECTED); } if (wp.deleted()) return 1; // double click calls the callback: (like Enter Key) if (Fl::event_clicks() && (when() & FL_WHEN_ENTER_KEY)) { set_changed(); do_callback(FL_REASON_CHANGED); } return 1; case FL_FOCUS: case FL_UNFOCUS: if (type() >= FL_HOLD_BROWSER && Fl::visible_focus()) { redraw(); return 1; } else return 0; } return 0; } /** The constructor makes an empty browser. \param[in] X,Y,W,H position and size. \param[in] L The label string, may be NULL. */ Fl_Browser_::Fl_Browser_(int X, int Y, int W, int H, const char* L) : Fl_Group(X, Y, W, H, L), linespacing_(0), scrollbar(0, 0, 0, 0, 0), // they will be resized by draw() hscrollbar(0, 0, 0, 0, 0) { box(FL_NO_BOX); align(FL_ALIGN_BOTTOM); position_ = real_position_ = 0; hposition_ = real_hposition_ = 0; offset_ = 0; top_ = 0; when(FL_WHEN_RELEASE_ALWAYS); selection_ = 0; color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR); scrollbar.callback(scrollbar_callback); //scrollbar.align(FL_ALIGN_LEFT|FL_ALIGN_BOTTOM); // back compatibility? hscrollbar.callback(hscrollbar_callback); hscrollbar.type(FL_HORIZONTAL); textfont_ = FL_HELVETICA; textsize_ = FL_NORMAL_SIZE; textcolor_ = FL_FOREGROUND_COLOR; has_scrollbar_ = BOTH; max_width = 0; max_width_item = 0; scrollbar_size_ = 0; redraw1 = redraw2 = 0; end(); } /** Sort the items in the browser based on \p flags. item_swap(void*, void*) and item_text(void*) must be implemented for this call. \param[in] flags FL_SORT_ASCENDING -- sort in ascending order\n FL_SORT_DESCENDING -- sort in descending order\n FL_SORT_CASEINSENSITIVE -- add this to sort case-insensitively\n Values other than the above will cause undefined behavior\n Other flags may appear in the future. */ void Fl_Browser_::sort(int flags) { // // Simple bubble sort - pure lazyness on my side. // int i, j, n = -1, desc = ((flags&FL_SORT_DESCENDING)==FL_SORT_DESCENDING); bool caseinsensitive = (flags&FL_SORT_CASEINSENSITIVE); void *a =item_first(), *b, *c; if (!a) return; while (a) { a = item_next(a); n++; } for (i=n; i>0; i--) { char swapped = 0; a = item_first(); b = item_next(a); for (j=0; j 0) || (!caseinsensitive && strcmp(ta, tb) > 0) ) { item_swap(a, b); swapped = 1; } } if (!c) break; b = c; a = item_prev(b); } if (!swapped) break; } } // Default versions of some of the virtual functions: /** This method may be provided by the subclass to return the height of the \p item, in pixels. Allow for two additional pixels for the list selection box. This method differs from item_height in that it is only called for selection and scrolling operations. The default implementation calls item_height. \param[in] item The item whose height to return. \returns The height, in pixels. */ int Fl_Browser_::item_quick_height(void* item) const { return item_height(item); } /** This method may be provided to return the average height of all items to be used for scrolling. The default implementation uses the height of the first item. \returns The average height of items, in pixels. */ int Fl_Browser_::incr_height() const { return item_quick_height(item_first()) + linespacing(); } /** This method may be provided by the subclass to indicate the full height of the item list, in pixels. The default implementation computes the full height from the item heights. Includes the items that are scrolled off screen. \returns The height of the entire list, in pixels. */ int Fl_Browser_::full_height() const { int t = 0; for (void* p = item_first(); p; p = item_next(p)) t += item_quick_height(p); return t; } /** This method may be provided by the subclass to indicate the full width of the item list, in pixels. The default implementation computes the full width from the item widths. \returns The maximum width of all the items, in pixels. */ int Fl_Browser_::full_width() const { return max_width; } /** This method must be implemented by the subclass if it supports multiple selections; sets the selection state to \p val for the \p item. Sets the selection state for \p item, where optional \p val is 1 (select, the default) or 0 (de-select). \param[in] item The item to be selected \param[in] val The optional selection state; 1=select, 0=de-select.\n The default is to select the item (1). */ void Fl_Browser_::item_select(void *item, int val) {} /** This method must be implemented by the subclass if it supports multiple selections; returns the selection state for \p item. The method should return 1 if \p item is selected, or 0 otherwise. \param[in] item The item to test. */ int Fl_Browser_::item_selected(void* item) const { return item==selection_ ? 1 : 0; } fltk-1.4.3/src/Fl_Int_Vector.cxx0000644000175000017500000000340515004135251016617 0ustar albrechtalbrecht// // An STL-ish vector without templates for the Fast Light Tool Kit (FLTK). // // Copyright 2002 by Greg Ercolano. // Copyright 2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include "Fl_Int_Vector.H" #include #include /** Make a copy of another array. Private: For use internally by the class's copy ctors only. */ void Fl_Int_Vector::copy(int *newarr, unsigned int newsize) { size(newsize); memcpy(arr_, newarr, newsize * sizeof(int)); } /** Destructor - frees the internal array and destroys the class. */ Fl_Int_Vector::~Fl_Int_Vector() { if (arr_) free(arr_); } /** Set the size of the array to \p count. Setting size to zero clears the array and frees any memory it used. Shrinking truncates the array and frees memory of truncated elements. Enlarging creates new elements that are zero in value. */ void Fl_Int_Vector::size(unsigned int count) { if (count == 0) { // zero? special case frees memory if (arr_) free(arr_); arr_ = 0; size_ = 0; return; } if (count > size_) { // array enlarged? realloc + init new vals to 0 arr_ = (int *)realloc(arr_, count * sizeof(int)); while ( size_ < count ) { arr_[size_++] = 0; } return; // leaves with size_ == count } // count <= size_? just truncate size_ = count; } /** \} \endcond */ fltk-1.4.3/src/Fl_Native_File_Chooser_WIN32.cxx0000644000175000017500000010464115004135251021300 0ustar albrechtalbrecht// // FLTK native OS file chooser widget // // Copyright 1998-2021 by Bill Spitzak and others. // Copyright 2004 Greg Ercolano. // API changes + filter improvements by Nathan Vander Wilt 2005 // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Any application to multi-folder implementation: // http://www.codeproject.com/dialog/selectfolder.asp // #ifndef FL_DOXYGEN // PREVENT DOXYGEN'S USE OF THIS FILE #include #include // malloc #include // snprintf #include #define FNFC_MAX_PATH 32768 // XXX: MAX_PATH under win32 is 260, too small for modern use #include // fl_strdup() #include "flstring.h" // fl_strlcpy()/cat() #include # include # include // OPENFILENAMEW, GetOpenFileName() # include // BROWSEINFOW, SHBrowseForFolder() # include // FL_EXPORT #include // fl_open_display class Fl_WinAPI_Native_File_Chooser_Driver : public Fl_Native_File_Chooser_Driver { private: int _btype; // kind-of browser to show() int _options; // general options OPENFILENAMEW *_ofn_ptr; // GetOpenFileName() & GetSaveFileName() struct BROWSEINFOW *_binf_ptr; // SHBrowseForFolder() struct WCHAR *_wpattern; // pattern buffer for filter char **_pathnames; // array of pathnames int _tpathnames; // total pathnames char *_directory; // default pathname to use char *_title; // title for window char *_filter; // user-side search filter char *_parsedfilt; // filter parsed for Windows dialog int _nfilters; // number of filters parse_filter counted char *_preset_file; // the file to preselect char *_errmsg; // error message // Private methods void errmsg(const char *msg); void clear_pathnames(); void set_single_pathname(const char *s); void add_pathname(const char *s); void ClearOFN(); void ClearBINF(); void Win2Unix(char *s); void Unix2Win(char *s); bool IsUnixPath(const char *s); int showfile(); int showdir(); void parse_filter(const char *); void clear_filters(); void add_filter(const char *, const char *); public: Fl_WinAPI_Native_File_Chooser_Driver(int val); ~Fl_WinAPI_Native_File_Chooser_Driver(); void type(int t) FL_OVERRIDE; int type() const FL_OVERRIDE; void options(int o) FL_OVERRIDE; int options() const FL_OVERRIDE; int count() const FL_OVERRIDE; const char *filename() const FL_OVERRIDE; const char *filename(int i) const FL_OVERRIDE; void directory(const char *val) FL_OVERRIDE; const char *directory() const FL_OVERRIDE; void title(const char *t) FL_OVERRIDE; const char* title() const FL_OVERRIDE; const char *filter() const FL_OVERRIDE; void filter(const char *f) FL_OVERRIDE; int filters() const FL_OVERRIDE; void filter_value(int i) FL_OVERRIDE; int filter_value() const FL_OVERRIDE; void preset_file(const char*f) FL_OVERRIDE; const char* preset_file() const FL_OVERRIDE; const char *errmsg() const FL_OVERRIDE; int show() FL_OVERRIDE; }; Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { platform_fnfc = new Fl_WinAPI_Native_File_Chooser_Driver(val); } static LPCWSTR utf8towchar(const char *in); static char *wchartoutf8(LPCWSTR in); #define LCURLY_CHR '{' #define RCURLY_CHR '}' #define LBRACKET_CHR '[' #define RBRACKET_CHR ']' // STATIC: Print Windows 'double-null' string (debug) #ifdef DEBUG #include static void dnullprint(char *wp) { if ( ! wp ) return; for ( int t=0; true; t++ ) { if ( wp[t] == '\0' && wp[t+1] == '\0' ) { printf("\\0\\0"); fflush(stdout); return; } else if ( wp[t] == '\0' ) { printf("\\0"); } else { printf("%c",wp[t]); } } } #endif // Return length of double-null string // Includes single nulls in count, excludes trailing double-null. // // 1234 567 // |||/\||| // IN: "one\0two\0\0" // OUT: 7 // static int dnulllen(const char *wp) { int len = 0; while ( ! ( *(wp+0) == 0 && *(wp+1) == 0 ) ) { ++wp; ++len; } return(len); } // STATIC: Append a string to another, leaving terminated with DOUBLE NULL. // Automatically handles extending length of string. // wp can be NULL (a new wp will be allocated and initialized). // string must be NULL terminated. // The pointer wp may be modified on return. // static void dnullcat(char*&wp, const char *string, int n = -1 ) { //DEBUG printf("DEBUG: dnullcat IN: <"); dnullprint(wp); printf(">\n"); size_t inlen = ( n < 0 ) ? strlen(string) : n; char *wp2 = 0; // used to point at end of last string if ( ! wp ) { wp = new char[inlen + 4]; *(wp+0) = '\0'; *(wp+1) = '\0'; wp2 = wp; // no "last string", point at begin of buffer } else { int wplen = dnulllen(wp); // Make copy of wp into larger buffer char *tmp = new char[wplen + inlen + 4]; memcpy(tmp, wp, wplen+2); // copy of wp plus doublenull delete[] wp; // delete old wp wp = tmp; // use new copy wp2 = wp + wplen + 1; // point at second null //DEBUG printf("DEBUG: dnullcat COPY: <"); dnullprint(wp); printf("> (wplen=%d)\n", wplen); } // *wp2 points at second null; the buffer is large enough to copy the string! strcpy(wp2, string); *(wp2+inlen+1) = '\0'; // Leave string double-null terminated //DEBUG printf("DEBUG: dnullcat OUT: <"); dnullprint(wp); printf(">\n\n"); } // CTOR Fl_WinAPI_Native_File_Chooser_Driver::Fl_WinAPI_Native_File_Chooser_Driver(int val) : Fl_Native_File_Chooser_Driver(val) { _btype = val; _options = Fl_Native_File_Chooser::NO_OPTIONS; _ofn_ptr = new OPENFILENAMEW; _binf_ptr = new BROWSEINFOW; _wpattern = 0; memset((void*)_ofn_ptr, 0, sizeof(OPENFILENAMEW)); _ofn_ptr->lStructSize = sizeof(OPENFILENAMEW); _ofn_ptr->hwndOwner = 0L; memset((void*)_binf_ptr, 0, sizeof(BROWSEINFOW)); _pathnames = NULL; _tpathnames = 0; _directory = NULL; _title = NULL; _filter = NULL; _parsedfilt = NULL; _nfilters = 0; _preset_file = NULL; _errmsg = NULL; } // DTOR Fl_WinAPI_Native_File_Chooser_Driver::~Fl_WinAPI_Native_File_Chooser_Driver() { //_pathnames // managed by clear_pathnames() //_tpathnames // managed by clear_pathnames() _directory = strfree(_directory); _title = strfree(_title); _filter = strfree(_filter); //_parsedfilt // managed by clear_filters() //_nfilters // managed by clear_filters() _preset_file = strfree(_preset_file); _errmsg = strfree(_errmsg); clear_filters(); clear_pathnames(); ClearOFN(); ClearBINF(); delete _binf_ptr; delete _ofn_ptr; if ( _wpattern ) delete[] _wpattern; } // SET TYPE OF BROWSER void Fl_WinAPI_Native_File_Chooser_Driver::type(int val) { _btype = val; } // GET TYPE OF BROWSER int Fl_WinAPI_Native_File_Chooser_Driver::type() const { return( _btype ); } // SET OPTIONS void Fl_WinAPI_Native_File_Chooser_Driver::options(int val) { _options = val; } // GET OPTIONS int Fl_WinAPI_Native_File_Chooser_Driver::options() const { return(_options); } // PRIVATE: SET ERROR MESSAGE void Fl_WinAPI_Native_File_Chooser_Driver::errmsg(const char *val) { _errmsg = strfree(_errmsg); _errmsg = strnew(val); } // FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS void Fl_WinAPI_Native_File_Chooser_Driver::clear_pathnames() { if ( _pathnames ) { while ( --_tpathnames >= 0 ) { _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]); } delete[] _pathnames; _pathnames = NULL; } _tpathnames = 0; } // SET A SINGLE PATHNAME void Fl_WinAPI_Native_File_Chooser_Driver::set_single_pathname(const char *s) { clear_pathnames(); _pathnames = new char*[1]; _pathnames[0] = strnew(s); _tpathnames = 1; } // ADD PATHNAME TO EXISTING ARRAY void Fl_WinAPI_Native_File_Chooser_Driver::add_pathname(const char *s) { if ( ! _pathnames ) { // Create first element in array ++_tpathnames; _pathnames = new char*[_tpathnames]; } else { // Grow array by 1 char **tmp = new char*[_tpathnames+1]; // create new buffer memcpy((void*)tmp, (void*)_pathnames, sizeof(char*)*_tpathnames); // copy old delete[] _pathnames; // delete old _pathnames = tmp; // use new ++_tpathnames; } _pathnames[_tpathnames-1] = strnew(s); } // FREE A PIDL (Pointer to IDentity List) static void FreePIDL(LPITEMIDLIST pidl) { IMalloc *imalloc = NULL; if ( SUCCEEDED(SHGetMalloc(&imalloc)) ) { imalloc->Free(pidl); imalloc->Release(); imalloc = NULL; } } // CLEAR MICROSOFT OFN (OPEN FILE NAME) CLASS void Fl_WinAPI_Native_File_Chooser_Driver::ClearOFN() { // Free any previously allocated lpstrFile before zeroing out _ofn_ptr if ( _ofn_ptr->lpstrFile ) { delete[] _ofn_ptr->lpstrFile; _ofn_ptr->lpstrFile = NULL; } if ( _ofn_ptr->lpstrInitialDir ) { delete[] (TCHAR*) _ofn_ptr->lpstrInitialDir; //msvc6 compilation fix _ofn_ptr->lpstrInitialDir = NULL; } _ofn_ptr->lpstrFilter = NULL; // (deleted elsewhere) int temp = _ofn_ptr->nFilterIndex; // keep the filter_value memset((void*)_ofn_ptr, 0, sizeof(OPENFILENAMEW)); _ofn_ptr->lStructSize = sizeof(OPENFILENAMEW); _ofn_ptr->nFilterIndex = temp; } // CLEAR MICROSOFT BINF (BROWSER INFO) CLASS void Fl_WinAPI_Native_File_Chooser_Driver::ClearBINF() { if ( _binf_ptr->pidlRoot ) { FreePIDL((ITEMIDLIST*)_binf_ptr->pidlRoot); _binf_ptr->pidlRoot = NULL; } memset((void*)_binf_ptr, 0, sizeof(BROWSEINFOW)); } // CONVERT WINDOWS BACKSLASHES TO UNIX FRONTSLASHES void Fl_WinAPI_Native_File_Chooser_Driver::Win2Unix(char *s) { while ( (s=strchr(s,'\\')) ) *s = '/'; } // CONVERT UNIX FRONTSLASHES TO WINDOWS BACKSLASHES void Fl_WinAPI_Native_File_Chooser_Driver::Unix2Win(char *s) { while ( (s=strchr(s,'/')) ) *s = '\\'; } // SEE IF PATH IS FRONT SLASH OR BACKSLASH STYLE // Use this to preserve path style after windows dialog appears. // If no slashes are specified, windows is assumed. // If a mix of both path styles is used, windows is assumed. // bool Fl_WinAPI_Native_File_Chooser_Driver::IsUnixPath(const char *s) { if ( !s ) return false; // NULL? if ( strchr(s, '\\') ) return false; // windows style? if ( strchr(s, '/') ) return true; // unix style? return false; // no slashes? assume native windows } // SAVE THE CURRENT WORKING DIRECTORY // Returns a malloc()ed copy of the cwd that can // later be freed with RestoreCWD(). May return 0 on error. // static char *SaveCWD() { char *thecwd = 0; DWORD thecwdsz = GetCurrentDirectory(0,0); if ( thecwdsz > 0 ) { thecwd = (char*)malloc(thecwdsz); if (GetCurrentDirectory(thecwdsz, thecwd) == 0 ) { free(thecwd); thecwd = 0; } } return thecwd; } // RESTORES THE CWD SAVED BY SaveCWD(), FREES STRING // Always returns NULL (string was freed). // static void RestoreCWD(char *thecwd) { if ( !thecwd ) return; SetCurrentDirectory(thecwd); free(thecwd); } // SHOW FILE BROWSER int Fl_WinAPI_Native_File_Chooser_Driver::showfile() { bool unixpath = IsUnixPath(_directory) || IsUnixPath(_preset_file); // caller uses unix paths? ClearOFN(); clear_pathnames(); size_t fsize = FNFC_MAX_PATH; _ofn_ptr->Flags |= OFN_NOVALIDATE; // prevent disabling of front slashes _ofn_ptr->Flags |= OFN_HIDEREADONLY; // hide goofy readonly flag // USE NEW BROWSER _ofn_ptr->Flags |= OFN_EXPLORER; // use newer explorer windows _ofn_ptr->Flags |= OFN_ENABLESIZING; // allow window to be resized (hey, why not?) _ofn_ptr->Flags |= OFN_NOCHANGEDIR; // XXX: docs say ineffective on XP/2K/NT, but set it anyway.. switch ( _btype ) { case Fl_Native_File_Chooser::BROWSE_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: abort(); // never happens: handled by showdir() case Fl_Native_File_Chooser::BROWSE_FILE: break; case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: _ofn_ptr->Flags |= OFN_ALLOWMULTISELECT; break; case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: if ( options() & Fl_Native_File_Chooser::SAVEAS_CONFIRM && type() == Fl_Native_File_Chooser::BROWSE_SAVE_FILE ) { _ofn_ptr->Flags |= OFN_OVERWRITEPROMPT; } break; } // SPACE FOR RETURNED FILENAME _ofn_ptr->lpstrFile = new WCHAR[fsize]; _ofn_ptr->nMaxFile = (DWORD)(fsize-1); _ofn_ptr->lpstrFile[0] = 0; _ofn_ptr->lpstrFile[1] = 0; // dnull // PARENT WINDOW _ofn_ptr->hwndOwner = GetForegroundWindow(); // DIALOG TITLE if (_title) { static WCHAR wtitle[200]; wcsncpy(wtitle, utf8towchar(_title), 200); wtitle[200-1] = 0; _ofn_ptr->lpstrTitle = wtitle; } else { _ofn_ptr->lpstrTitle = NULL; } // FILTER if (_parsedfilt != NULL) { // to convert a null-containing char string into a widechar string // NEW if ( !_wpattern ) _wpattern = new WCHAR[FNFC_MAX_PATH]; const char *p = _parsedfilt; while(*(p + strlen(p) + 1) != 0) p += strlen(p) + 1; p += strlen(p) + 2; MultiByteToWideChar(CP_UTF8, 0, _parsedfilt, (int) (p - _parsedfilt), _wpattern, FNFC_MAX_PATH); _ofn_ptr->lpstrFilter = _wpattern; } else { _ofn_ptr->lpstrFilter = NULL; } // PRESET FILE // If set, supercedes _directory. See KB Q86920 for details // XXX: this doesn't preselect the item in the listview.. why? // if ( _preset_file ) { // Temp copy of _dirname we can convert to windows path if needed char *winpath = fl_strdup(_preset_file); if ( unixpath ) Unix2Win(winpath); size_t len = strlen(winpath); if ( len >= _ofn_ptr->nMaxFile ) { char msg[80]; snprintf(msg, 80, "preset_file() filename is too long: %ld is >=%ld", (long)len, (long)fsize); errmsg(msg); return(-1); } wcscpy(_ofn_ptr->lpstrFile, utf8towchar(winpath)); len = wcslen(_ofn_ptr->lpstrFile); _ofn_ptr->lpstrFile[len+0] = 0; // multiselect needs dnull _ofn_ptr->lpstrFile[len+1] = 0; free(winpath); // free temp copy now that we have a new wchar //wprintf(L"lpstrFile is '%ls'\n", (WCHAR*)(_ofn_ptr->lpstrFile)); } // PRESET DIR // XXX: See KB Q86920 for doc bug: // http://support.microsoft.com/default.aspx?scid=kb;en-us;86920 // if ( _directory ) { // Temp copy of _dirname we can convert to windows path if needed char *winpath = fl_strdup(_directory); // Caller specified unix front slash path? // If so, convert to backslashes; windows native browser mishandles unix style paths. // We'll convert back to unix style when dialog completes. // if ( unixpath ) Unix2Win(winpath); // Make a wide char version of potentially utf8 string _ofn_ptr->lpstrInitialDir = new WCHAR[FNFC_MAX_PATH]; wcscpy((WCHAR *)_ofn_ptr->lpstrInitialDir, utf8towchar(winpath)); free(winpath); // free temp copy now that we have a new wchar //wprintf(L"lpstrInitialDir is '%ls'\n", (WCHAR*)(_ofn_ptr->lpstrInitialDir)); } // SAVE THE CURRENT DIRECTORY // See above warning (XXX) for OFN_NOCHANGEDIR // char *save_cwd = SaveCWD(); // must be freed with RestoreCWD() // OPEN THE DIALOG WINDOW int err; if ( _btype == Fl_Native_File_Chooser::BROWSE_SAVE_FILE ) { err = GetSaveFileNameW(_ofn_ptr); } else { err = GetOpenFileNameW(_ofn_ptr); } // GET EXTENDED ERROR int exterr = CommDlgExtendedError(); // RESTORE CURRENT DIRECTORY RestoreCWD(save_cwd); save_cwd = 0; // also frees save_cwd // ERROR OR CANCEL? if ( err == 0 ) { if ( exterr == 0 ) return(1); // user hit cancel // Otherwise, an error occurred.. char msg[80]; snprintf(msg, 80, "CommDlgExtendedError() code=%d", exterr); errmsg(msg); return(-1); } // PREPARE PATHNAMES FOR RETURN switch ( _btype ) { case Fl_Native_File_Chooser::BROWSE_FILE: case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: set_single_pathname(wchartoutf8(_ofn_ptr->lpstrFile)); if ( unixpath ) Win2Unix(_pathnames[_tpathnames-1]); // preserve unix style path break; case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: { // EXTRACT MULTIPLE FILENAMES const WCHAR *dirname = _ofn_ptr->lpstrFile; size_t dirlen = wcslen(dirname); if ( dirlen > 0 ) { // WALK STRING SEARCHING FOR 'DOUBLE-NULL' // eg. "/dir/name\0foo1\0foo2\0foo3\0\0" // char pathname[FNFC_MAX_PATH]; for ( const WCHAR *s = dirname + dirlen + 1; *s; s += (wcslen(s)+1)) { // ISSUE #206: replace strncpy/cat with fl_strlcpy/cat fl_strlcpy(pathname, wchartoutf8(dirname), FNFC_MAX_PATH); fl_strlcat(pathname, "\\", FNFC_MAX_PATH); fl_strlcat(pathname, wchartoutf8(s), FNFC_MAX_PATH); add_pathname(pathname); } } // XXX // Work around problem where pasted forward-slash pathname // into the file browser causes new "Explorer" interface // not to grok forward slashes, passing back as a 'filename'..! // if ( _tpathnames == 0 ) { add_pathname(wchartoutf8(dirname)); } // Caller specified unix path? Return unix paths if ( unixpath ) { for ( int t=0; t<_tpathnames; t++ ) { Win2Unix(_pathnames[t]); } } break; } case Fl_Native_File_Chooser::BROWSE_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: abort(); // never happens: handled by showdir() } return(0); } // Used by SHBrowseForFolder(), sets initial selected dir. // Ref: Usenet: microsoft.public.vc.mfc, Dec 8 2000, 1:38p David Lowndes // Subject: How to specify to select an initial folder .." // static int CALLBACK Dir_CB(HWND win, UINT msg, LPARAM param, LPARAM data) { switch (msg) { case BFFM_INITIALIZED: if (data) ::SendMessageW(win, BFFM_SETSELECTIONW, TRUE, data); break; case BFFM_SELCHANGED: TCHAR path[FNFC_MAX_PATH]; if ( SHGetPathFromIDList((ITEMIDLIST*)param, path) ) { ::SendMessage(win, BFFM_ENABLEOK, 0, 1); } else { // disable ok button if not a path ::SendMessage(win, BFFM_ENABLEOK, 0, 0); } break; case BFFM_VALIDATEFAILED: // we could pop up an annoying message here. // also needs set ulFlags |= BIF_VALIDATE break; default: break; } return(0); } // SHOW DIRECTORY BROWSER int Fl_WinAPI_Native_File_Chooser_Driver::showdir() { bool unixpath = IsUnixPath(_directory); // caller uses unix paths? // initialize OLE only once fl_open_display(); // init needed by BIF_USENEWUI ClearBINF(); clear_pathnames(); // PARENT WINDOW _binf_ptr->hwndOwner = GetForegroundWindow(); // DIALOG TITLE //_binf_ptr->lpszTitle = _title ? _title : NULL; if (_title) { static WCHAR wtitle[256]; wcsncpy(wtitle, utf8towchar(_title), 256); wtitle[255] = 0; _binf_ptr->lpszTitle = wtitle; } else { _binf_ptr->lpszTitle = NULL; } // FLAGS _binf_ptr->ulFlags = 0; // initialize // TBD: make sure matches to runtime system, if need be. //(what if _WIN32_IE doesn't match system? does the program not run?) // // TBD: match all 3 types of directories // // NOTE: *Don't* use BIF_SHAREABLE. It /disables/ mapped network shares // from being visible in BROWSE_DIRECTORY mode. Walter Garm's comments: // // --- Garms, Walter (GE EntSol, Security) wrote: // With your help I was able to solve the problem of the network drives. // For Version 6.0, at least, the BIF_SHAREABLE flag seems to have the // opposite sense: With BIF_SHAREABLE not set I see the mapped network // drives, and with BIF_SHAREABLE set I do not. // --- #if defined(BIF_NONEWFOLDERBUTTON) // Version 6.0 if ( _btype == Fl_Native_File_Chooser::BROWSE_DIRECTORY ) _binf_ptr->ulFlags |= BIF_NONEWFOLDERBUTTON; _binf_ptr->ulFlags |= BIF_USENEWUI | BIF_RETURNONLYFSDIRS; #elif defined(BIF_USENEWUI) // Version 5.0 if ( _btype == Fl_Native_File_Chooser::BROWSE_DIRECTORY ) _binf_ptr->ulFlags |= BIF_EDITBOX; else if ( _btype == Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY ) _binf_ptr->ulFlags |= BIF_USENEWUI; _binf_ptr->ulFlags |= BIF_RETURNONLYFSDIRS; #elif defined(BIF_EDITBOX) // Version 4.71 _binf_ptr->ulFlags |= BIF_RETURNONLYFSDIRS | BIF_EDITBOX; #else // Version Old _binf_ptr->ulFlags |= BIF_RETURNONLYFSDIRS; #endif // BUFFER //char displayname[FNFC_MAX_PATH]; WCHAR displayname[FNFC_MAX_PATH]; _binf_ptr->pszDisplayName = displayname; // PRESET DIR WCHAR presetname[FNFC_MAX_PATH]; if ( _directory ) { // Temp copy of _dirname we can convert to windows path if needed char *winpath = fl_strdup(_directory); // Caller specified unix front slash path? // If so, convert to backslashes; windows native browser mishandles unix style paths. // We'll convert back to unix style when dialog completes. // if ( unixpath ) Unix2Win(winpath); // Wide char version of potentially utf8 string wcsncpy(presetname, utf8towchar(winpath), FNFC_MAX_PATH); free(winpath); // free temp copy now that we have a new wchar presetname[FNFC_MAX_PATH-1] = 0; // dnull presetname[FNFC_MAX_PATH-2] = 0; _binf_ptr->lParam = (LPARAM)presetname; //wprintf(L"presetname is '%ls'\n", (WCHAR*)(presetname)); } else _binf_ptr->lParam = 0; _binf_ptr->lpfn = Dir_CB; // OPEN BROWSER LPITEMIDLIST pidl = SHBrowseForFolderW(_binf_ptr); // CANCEL? if ( pidl == NULL ) return(1); // GET THE PATHNAME(S) THE USER SELECTED // TBD: expand NetHood shortcuts from this PIDL?? // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shbrowseforfolder.asp WCHAR path[FNFC_MAX_PATH]; if ( SHGetPathFromIDListW(pidl, path) ) { add_pathname(wchartoutf8(path)); if ( unixpath ) Win2Unix(_pathnames[_tpathnames-1]); // preserve unix style path } FreePIDL(pidl); if ( !wcslen(path) ) return(1); // don't return empty pathnames return(0); } // RETURNS: // 0 - user picked a file // 1 - user cancelled // -1 - failed; errmsg() has reason // int Fl_WinAPI_Native_File_Chooser_Driver::show() { int retval; if ( _btype == Fl_Native_File_Chooser::BROWSE_DIRECTORY || _btype == Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY || _btype == Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY ) { retval = showdir(); } else { retval = showfile(); } // restore the correct state of mouse buttons and keyboard modifier keys (STR #3221) HWND h = GetForegroundWindow(); if (h) { WNDPROC windproc = (WNDPROC)GetWindowLongPtrW(h, GWLP_WNDPROC); CallWindowProc(windproc, h, WM_ACTIVATEAPP, 1, 0); } return retval; } // RETURN ERROR MESSAGE const char *Fl_WinAPI_Native_File_Chooser_Driver::errmsg() const { return(_errmsg ? _errmsg : "No error"); } // GET FILENAME const char* Fl_WinAPI_Native_File_Chooser_Driver::filename() const { if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]); return(""); } // GET FILENAME FROM LIST OF FILENAMES const char* Fl_WinAPI_Native_File_Chooser_Driver::filename(int i) const { if ( _pathnames && i < _tpathnames ) return(_pathnames[i]); return(""); } // GET TOTAL FILENAMES CHOSEN int Fl_WinAPI_Native_File_Chooser_Driver::count() const { return(_tpathnames); } // PRESET PATHNAME // Can be NULL if no preset is desired. // void Fl_WinAPI_Native_File_Chooser_Driver::directory(const char *val) { _directory = strfree(_directory); _directory = strnew(val); } // GET PRESET PATHNAME // Can return NULL if none set. // const char *Fl_WinAPI_Native_File_Chooser_Driver::directory() const { return(_directory); } // SET TITLE // Can be NULL if no title desired. // void Fl_WinAPI_Native_File_Chooser_Driver::title(const char *val) { _title = strfree(_title); _title = strnew(val); } // GET TITLE // Can return NULL if none set. // const char *Fl_WinAPI_Native_File_Chooser_Driver::title() const { return(_title); } // SET FILTER // Can be NULL if no filter needed // void Fl_WinAPI_Native_File_Chooser_Driver::filter(const char *val) { _filter = strfree(_filter); clear_filters(); if ( val ) { _filter = strnew(val); parse_filter(_filter); } add_filter("All Files", "*.*"); // always include 'all files' option #ifdef DEBUG dnullprint(_parsedfilt); #endif /*DEBUG*/ } // GET FILTER // Can return NULL if none set. // const char *Fl_WinAPI_Native_File_Chooser_Driver::filter() const { return(_filter); } // CLEAR FILTERS void Fl_WinAPI_Native_File_Chooser_Driver::clear_filters() { _nfilters = 0; _parsedfilt = strfree(_parsedfilt); } // ADD A FILTER void Fl_WinAPI_Native_File_Chooser_Driver::add_filter(const char *name_in, // name of filter (optional: can be null) const char *winfilter) { // windows style filter (eg. "*.cxx;*.h") // No name? Make one.. char name[1024]; if ( !name_in || name_in[0] == '\0' ) { snprintf(name, sizeof(name), "%.*s Files", int(sizeof(name)-10), winfilter); } else { if ((strlen(name_in)+strlen(winfilter)+3) < sizeof(name)) { snprintf(name, sizeof(name), "%s (%s)", name_in, winfilter); } else { snprintf(name, sizeof(name), "%.*s", int(sizeof(name))-1, name_in); } } dnullcat(_parsedfilt, name); dnullcat(_parsedfilt, winfilter); _nfilters++; //DEBUG printf("DEBUG: ADD FILTER name=<%s> winfilter=<%s>\n", name, winfilter); } // RETURN HOW MANY DIFFERENT FILTERS WERE SPECIFIED // In: "foo.[CH]" or "foo.{C,H}" // Out: 2 // static int count_filters(const char *filter) { int count = 0; char mode = 0; const char *in = filter; while (*in) { switch(*in) { case '\\': // escape next character ++in; if ( *in == 0 ) continue; // skip escape. EOL? done ++in; // skip escaped char continue; case LCURLY_CHR: // start "{aaa,bbb}" mode = *in; // set mode, parse over curly ++count; // at least +1 wildcard break; case RCURLY_CHR: // end "{aaa,bbb}" if ( mode == LCURLY_CHR ) // disable curly mode (if on) mode = 0; break; case LBRACKET_CHR: // start "[xyz]" mode = *in; // set mode, parse over bracket break; case RBRACKET_CHR: // end "[xyz]" if ( mode == LBRACKET_CHR ) // disable bracket mode (if on) mode = 0; break; default: // any other char switch (mode) { // handle {} or [] modes case LCURLY_CHR: // handle "{aaa,bbb}" if (*in==',' || *in=='|') // ',' and '|' adds filters ++count; break; case LBRACKET_CHR: // handle "[xyz]" ++count; // all chars in []'s add new filter break; } break; } ++in; // parse past char } return count > 0 ? count : 1; // return at least 1 } // Convert FLTK style pattern matches to windows 'double-null' pattern // Returns with the parsed double-null result in '_parsedfilt'. // // Handles: // IN OUT // ----------- ----------------------------- // *.{ma,mb} "*.{ma,mb} Files\0*.ma;*.mb\0\0" // *.[abc] "*.[abc] Files\0*.a;*.b;*.c\0\0" // *.txt "*.txt Files\0*.txt\0\0" // C Files\t*.[ch] "C Files\0*.c;*.h\0\0" // // Example: // IN: "*.{ma,mb}" // OUT: "*.ma;*.mb Files\0*.ma;*.mb\0All Files\0*.*\0\0" // --------------- --------- --------- --- // | | | | // Title Wildcards Title Wildcards // // Parsing Mode: // IN:"C Files\t*.{cxx,h}" // ||||||| ||||||||| // mode: nnnnnnn ww{{{{{{{ // \_____/ \_______/ // Name Wildcard // void Fl_WinAPI_Native_File_Chooser_Driver::parse_filter(const char *in) { clear_filters(); if ( ! in || in[0] == '\0' ) return; int has_name = strchr(in, '\t') ? 1 : 0; char mode = has_name ? 'n' : 'w'; // parse mode: n=name, w=wildcard // whatever input string is, our output won't be much longer in length.. // use double length just for safety. size_t slen = strlen(in); char *wildprefix = new char[(slen+1)*2]; wildprefix[0] = 0; char *comp = new char[(slen+1)*2]; comp[0] = 0; char *name = new char[(slen+1)*2]; name[0] = 0; // Init int nwildcards = 0; int maxfilters = count_filters(in) + 1; // count wildcard seps char **wildcards = new char*[maxfilters]; // parsed wildcards (can be several) int t; for ( t=0; t name=<%s> wildprefix=<%s> nwildcards=%d wildcards[n]=<%s>\n", // *in, mode, name, wildprefix, nwildcards, wildcards[nwildcards]); switch (*in) { case ',': case '|': if ( mode == LCURLY_CHR ) { // create new wildcard, copy in prefix strcat(wildcards[nwildcards++], wildprefix); continue; } else { goto regchar; } continue; // FINISHED PARSING A NAME? case '\t': if ( mode != 'n' ) goto regchar; // finish parsing name? switch to wildcard mode mode = 'w'; break; // ESCAPE NEXT CHAR case '\\': ++in; goto regchar; // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS? case '\r': case '\n': case '\0': { if ( mode == 'w' ) { // finished parsing wildcard? if ( nwildcards == 0 ) { strcpy(wildcards[nwildcards++], wildprefix); } // Append wildcards in Microsoft's "*.one;*.two" format comp[0] = 0; for ( t=0; t 0 ) { chrcat(wildcards[nwildcards-1], *in); } continue; case 'n': chrcat(name, *in); continue; case 'w': chrcat(wildprefix, *in); for ( t=0; tnFilterIndex = i + 1; } // RETURN VALUE OF 'CURRENTLY SELECTED FILTER' int Fl_WinAPI_Native_File_Chooser_Driver::filter_value() const { return(_ofn_ptr->nFilterIndex ? _ofn_ptr->nFilterIndex-1 : _nfilters+1); } // PRESET FILENAME FOR 'SAVE AS' CHOOSER void Fl_WinAPI_Native_File_Chooser_Driver::preset_file(const char* val) { _preset_file = strfree(_preset_file); _preset_file = strnew(val); } // GET PRESET FILENAME FOR 'SAVE AS' CHOOSER const char* Fl_WinAPI_Native_File_Chooser_Driver::preset_file() const { return(_preset_file); } int Fl_WinAPI_Native_File_Chooser_Driver::filters() const { return(_nfilters); } static char *wchartoutf8(LPCWSTR in) { static char *out = NULL; static int lchar = 0; if (in == NULL)return NULL; int utf8len = WideCharToMultiByte(CP_UTF8, 0, in, -1, NULL, 0, NULL, NULL); if (utf8len > lchar) { lchar = utf8len; out = (char *)realloc(out, lchar * sizeof(char)); } WideCharToMultiByte(CP_UTF8, 0, in, -1, out, utf8len, NULL, NULL); return out; } static LPCWSTR utf8towchar(const char *in) { static WCHAR *wout = NULL; static int lwout = 0; if (in == NULL)return NULL; int wlen = MultiByteToWideChar(CP_UTF8, 0, in, -1, NULL, 0); if (wlen > lwout) { lwout = wlen; wout = (WCHAR *)realloc(wout, lwout * sizeof(WCHAR)); } MultiByteToWideChar(CP_UTF8, 0, in, -1, wout, wlen); return wout; } #endif /* !FL_DOXYGEN */ fltk-1.4.3/src/forms_free.cxx0000644000175000017500000000535615004135251016260 0ustar albrechtalbrecht// // Forms free widget routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Emulation of the Forms "free" widget. // This emulation allows the free demo to run, and has allowed // me to port several other programs, but it is in no way // complete. #include #include void Fl_Free::step(void *v) { Fl_Free *f = (Fl_Free *)v; int old_event = Fl::e_number; f->handle(Fl::e_number == FL_STEP); Fl::e_number = old_event; Fl::add_timeout(.01,step,v); } /** Create a new Fl_Free widget with type, position, size, label and handler. \param[in] t type \param[in] X, Y, W, H position and size \param[in] L widget label \param[in] hdl handler function The constructor takes both the type and the handle function. The handle function should be declared as follows: \code int handle_function(Fl_Widget *w, int event, float event_x, float event_y, char key) \endcode This function is called from the handle() method in response to most events, and is called by the draw() method. The event argument contains the event type: \code // old event names for compatibility: #define FL_MOUSE FL_DRAG #define FL_DRAW 0 #define FL_STEP 9 #define FL_FREEMEM 12 #define FL_FREEZE FL_UNMAP #define FL_THAW FL_MAP \endcode */ Fl_Free::Fl_Free(uchar t,int X, int Y, int W, int H,const char *L, FL_HANDLEPTR hdl) : Fl_Widget(X,Y,W,H,L) { type(t); hfunc = hdl; if (t == FL_SLEEPING_FREE) set_flag(INACTIVE); if (t == FL_CONTINUOUS_FREE || t == FL_ALL_FREE) Fl::add_timeout(.01,step,this); } /** The destructor will call the handle function with the event FL_FREE_MEM. */ Fl_Free::~Fl_Free() { Fl::remove_timeout(step,this); hfunc(this,FL_FREEMEM,0,0,0); } void Fl_Free::draw() {hfunc(this,FL_DRAW,0,0,0);} int Fl_Free::handle(int e) { char key = Fl::event_key(); switch (e) { case FL_FOCUS: if (type()!=FL_INPUT_FREE && type()!=FL_ALL_FREE) return 0; break; case FL_PUSH: case FL_DRAG: case FL_RELEASE: key = 4-Fl::event_button(); break; case FL_SHORTCUT: return 0; } if (hfunc(this, e, float(Fl::event_x()), float(Fl::event_y()), key)) do_callback(); return 1; } fltk-1.4.3/src/fl_diamond_box.cxx0000644000175000017500000000554415004135251017074 0ustar albrechtalbrecht// // Diamond box code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2011 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Box drawing code for an obscure box type. // These box types are in separate files so they are not linked // in if not used. // The diamond box draws best if the area is square! #include #include extern const uchar* fl_gray_ramp(); static void fl_diamond_up_box(int x,int y,int w,int h,Fl_Color bgcolor) { w &= -2; h &= -2; int x1 = x+w/2; int y1 = y+h/2; Fl::set_box_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3); const uchar *g = fl_gray_ramp(); fl_color(g[(int)'W']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); fl_color(g[(int)'U']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); fl_color(g[(int)'S']); fl_line(x+3, y1, x1, y+3, x+w-3, y1); fl_color(g[(int)'P']); fl_line(x+3, y1, x1, y+h-3, x+w-3, y1); fl_color(g[(int)'N']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); fl_color(g[(int)'H']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); fl_color(g[(int)'A']); fl_loop(x, y1, x1, y, x+w, y1, x1, y+h); } static void fl_diamond_down_box(int x,int y,int w,int h,Fl_Color bgcolor) { w &= -2; h &= -2; int x1 = x+w/2; int y1 = y+h/2; const uchar *g = fl_gray_ramp(); fl_color(g[(int)'P']); fl_line(x+0, y1, x1, y+0, x+w-0, y1); fl_color(g[(int)'N']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); fl_color(g[(int)'H']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); fl_color(g[(int)'W']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); fl_color(g[(int)'U']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); fl_color(g[(int)'S']); fl_line(x+0, y1, x1, y+h-0, x+w-0, y1); Fl::set_box_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3); fl_color(g[(int)'A']); fl_loop(x+3, y1, x1, y+3, x+w-3, y1, x1, y+h-3); } void fl_diamond_focus(Fl_Boxtype bt, int x, int y, int w, int h, Fl_Color fg, Fl_Color bg) { w &= -2; h &= -2; x += Fl::box_dx(bt)+4; y += Fl::box_dy(bt)+4; w -= Fl::box_dw(bt)+8; h -= Fl::box_dh(bt)+8; int x1 = x+w/2; int y1 = y+h/2; Fl_Color savecolor = fl_color(); fl_color(fl_contrast(fg, bg)); fl_line_style(FL_DOT); fl_loop(x,y1, x1,y, x+w,y1, x1,y+h); fl_line_style(FL_SOLID); fl_color(savecolor); } extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*, Fl_Box_Draw_Focus_F* =NULL); Fl_Boxtype fl_define_FL_DIAMOND_BOX() { fl_internal_boxtype(_FL_DIAMOND_DOWN_BOX, fl_diamond_down_box, fl_diamond_focus); fl_internal_boxtype(_FL_DIAMOND_UP_BOX, fl_diamond_up_box, fl_diamond_focus); return _FL_DIAMOND_UP_BOX; } fltk-1.4.3/src/Fl_cocoa.mm0000644000175000017500000056042215004135251015445 0ustar albrechtalbrecht// // macOS-Cocoa specific code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // extern "C" { #include } #include #include #include #include "Fl_Window_Driver.H" #include "Fl_Screen_Driver.H" #include "Fl_Timeout.h" #include #include #include #include #include #include #include "drivers/Quartz/Fl_Quartz_Graphics_Driver.H" #include "drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H" #include "drivers/Cocoa/Fl_Cocoa_Screen_Driver.H" #include "drivers/Cocoa/Fl_Cocoa_Window_Driver.H" #include "drivers/Darwin/Fl_Darwin_System_Driver.H" #include "drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H" #include "print_button.h" #include #include #include #include #include #include #include #include #include #import #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_15_0 # import #endif // #define DEBUG_SELECT // UNCOMMENT FOR SELECT()/THREAD DEBUGGING #ifdef DEBUG_SELECT #include // testing #define DEBUGMSG(msg) if ( msg ) fprintf(stderr, msg); #define DEBUGPERRORMSG(msg) if ( msg ) perror(msg) #define DEBUGTEXT(txt) txt #else #define DEBUGMSG(msg) #define DEBUGPERRORMSG(msg) #define DEBUGTEXT(txt) NULL #endif /*DEBUG_SELECT*/ // external functions extern void fl_fix_focus(); extern int fl_send_system_handlers(void *e); // forward definition of functions in this file // converting cr lf converter function static void createAppleMenu(void); static void cocoaMouseHandler(NSEvent *theEvent); static void clipboard_check(void); static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y, int w, int h); static NSBitmapImageRep* rect_to_NSBitmapImageRep_subwins(Fl_Window *win, int x, int y, int w, int h, bool capture_subwins); static void drain_dropped_files_list(void); static NSPoint FLTKtoCocoa(Fl_Window *win, int x, int y, int H); static int get_window_frame_sizes(Fl_Window *win, int *pbx = NULL, int *pby = NULL); int fl_mac_os_version = Fl_Darwin_System_Driver::calc_mac_os_version(); // the version number of the running Mac OS X (e.g., 100604 for 10.6.4) // public variables void *fl_capture = 0; // (NSWindow*) we need this to compensate for a missing(?) mouse capture FLWindow *fl_window; // forward declarations of variables in this file static int main_screen_height; // height of menubar-containing screen used to convert between Cocoa and FLTK global screen coordinates // through_drawRect = YES means the drawRect: message was sent to the view, // thus the graphics context was prepared by the system static BOOL through_drawRect = NO; // through_Fl_X_flush = YES means Fl_Cocoa_Window_Driver::flush() was called static BOOL through_Fl_X_flush = NO; static BOOL views_use_CA = NO; // YES means views are layer-backed, as on macOS 10.14 when linked with SDK 10.14 static int im_enabled = -1; // OS version-dependent pasteboard type names. // Some, but not all, versions of the 10.6 SDK for PPC lack the 3 symbols below (PR #761) #if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6) || defined(__POWERPC__) # define NSPasteboardTypeTIFF @"public.tiff" # define NSPasteboardTypePDF @"com.adobe.pdf" # define NSPasteboardTypeString @"public.utf8-plain-text" #endif // the next 5 deprecation/availability warnings can be legitimately ignored #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" #pragma clang diagnostic ignored "-Wunguarded-availability" static NSString *TIFF_pasteboard_type = (fl_mac_os_version >= 100600 ? NSPasteboardTypeTIFF : NSTIFFPboardType); static NSString *PDF_pasteboard_type = (fl_mac_os_version >= 100600 ? NSPasteboardTypePDF : NSPDFPboardType); static NSString *PICT_pasteboard_type = (fl_mac_os_version >= 100600 ? @"com.apple.pict" : NSPICTPboardType); static NSString *UTF8_pasteboard_type = (fl_mac_os_version >= 100600 ? NSPasteboardTypeString : NSStringPboardType); static NSString *fl_filenames_pboard_type = #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 (fl_mac_os_version >= 101300 ? NSPasteboardTypeFileURL : NSFilenamesPboardType); #else NSFilenamesPboardType; #endif #pragma clang diagnostic pop static bool in_nsapp_run = false; // true during execution of [NSApp run] static NSMutableArray *dropped_files_list = nil; // list of files dropped at app launch typedef void (*open_cb_f_type)(const char *); static Fl_Window *starting_moved_window = NULL; // the moved window which brings its subwins with it enum { FLTKTimerEvent = 1, FLTKDataReadyEvent }; // Carbon functions and definitions typedef void *TSMDocumentID; extern "C" enum { kTSMDocumentEnabledInputSourcesPropertyTag = 'enis' // from Carbon/TextServices.h }; // Undocumented voodoo. Taken from Mozilla. static const int smEnableRomanKybdsOnly = -23; typedef TSMDocumentID (*TSMGetActiveDocument_type)(void); static TSMGetActiveDocument_type TSMGetActiveDocument; typedef OSStatus (*TSMSetDocumentProperty_type)(TSMDocumentID, OSType, UInt32, void*); static TSMSetDocumentProperty_type TSMSetDocumentProperty; typedef OSStatus (*TSMRemoveDocumentProperty_type)(TSMDocumentID, OSType); static TSMRemoveDocumentProperty_type TSMRemoveDocumentProperty; typedef CFArrayRef (*TISCreateInputSourceList_type)(CFDictionaryRef, Boolean); static TISCreateInputSourceList_type TISCreateInputSourceList; static CFStringRef kTISTypeKeyboardLayout; static CFStringRef kTISPropertyInputSourceType; typedef void (*KeyScript_type)(short); static KeyScript_type KeyScript; #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13 const NSInteger NSControlStateValueOn = NSOnState; const NSInteger NSControlStateValueOff = NSOffState; #endif #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 const NSUInteger NSEventModifierFlagCommand = NSCommandKeyMask; const NSUInteger NSEventModifierFlagOption = NSAlternateKeyMask; const NSUInteger NSEventModifierFlagControl = NSControlKeyMask; const NSUInteger NSEventModifierFlagShift = NSShiftKeyMask; const NSUInteger NSEventModifierFlagCapsLock = NSAlphaShiftKeyMask; const NSEventType NSEventTypeLeftMouseDown = NSLeftMouseDown; const NSEventType NSEventTypeRightMouseDown = NSRightMouseDown; const NSEventType NSEventTypeOtherMouseDown = NSOtherMouseDown; const NSEventType NSEventTypeLeftMouseUp = NSLeftMouseUp; const NSEventType NSEventTypeRightMouseUp = NSRightMouseUp; const NSEventType NSEventTypeOtherMouseUp = NSOtherMouseUp; const NSEventType NSEventTypeLeftMouseDragged = NSLeftMouseDragged; const NSEventType NSEventTypeRightMouseDragged = NSRightMouseDragged; const NSEventType NSEventTypeOtherMouseDragged = NSOtherMouseDragged; const NSEventType NSEventTypeMouseMoved = NSMouseMoved; const NSEventType NSEventTypeMouseEntered = NSMouseEntered; const NSEventType NSEventTypeMouseExited = NSMouseExited; const NSEventType NSEventTypeKeyUp = NSKeyUp; const NSEventType NSEventTypeApplicationDefined = NSApplicationDefined; const NSUInteger NSWindowStyleMaskResizable = NSResizableWindowMask; const NSUInteger NSWindowStyleMaskBorderless = NSBorderlessWindowMask; const NSUInteger NSWindowStyleMaskMiniaturizable = NSMiniaturizableWindowMask; const NSUInteger NSWindowStyleMaskClosable = NSClosableWindowMask; const NSUInteger NSWindowStyleMaskTitled = NSTitledWindowMask; # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 const NSUInteger NSWindowStyleMaskFullScreen = NSFullScreenWindowMask; # endif const NSUInteger NSEventMaskAny = NSAnyEventMask; const NSUInteger NSEventMaskSystemDefined = NSSystemDefinedMask; # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 const NSUInteger NSBitmapFormatAlphaFirst = NSAlphaFirstBitmapFormat; const NSUInteger NSBitmapFormatAlphaNonpremultiplied = NSAlphaNonpremultipliedBitmapFormat; # endif #endif /* * Mac keyboard lookup table */ static unsigned short* macKeyLookUp = NULL; /* * convert the current mouse chord into the FLTK modifier state */ static unsigned int mods_to_e_state( NSUInteger mods ) { unsigned int state = 0; if ( mods & NSEventModifierFlagCommand ) state |= FL_META; if ( mods & NSEventModifierFlagOption ) state |= FL_ALT; if ( mods & NSEventModifierFlagControl ) state |= FL_CTRL; if ( mods & NSEventModifierFlagShift ) state |= FL_SHIFT; if ( mods & NSEventModifierFlagCapsLock ) state |= FL_CAPS_LOCK; unsigned int ret = ( Fl::e_state & 0xff000000 ) | state; Fl::e_state = ret; //printf( "State 0x%08x (%04x)\n", Fl::e_state, mods ); return ret; } // these pointers are set by the Fl::lock() function: static void nothing() {} void (*fl_lock_function)() = nothing; void (*fl_unlock_function)() = nothing; // // Select interface -- how it's implemented: // When the user app configures one or more file descriptors to monitor // with Fl::add_fd(), we start a separate thread to select() the data, // sending a custom OSX 'FLTK data ready event' to the parent thread's // RunApplicationLoop(), so that it triggers the data ready callbacks // in the parent thread. -erco 04/04/04 // #define POLLIN 1 #define POLLOUT 4 #define POLLERR 8 // Class to handle select() 'data ready' class DataReady { struct FD { int fd; short events; void (*cb)(int, void*); void* arg; }; int nfds, fd_array_size; FD *fds; pthread_t tid; // select()'s thread id // Data that needs to be locked (all start with '_') pthread_mutex_t _datalock; // data lock fd_set _fdsets[3]; // r/w/x sets user wants to monitor int _maxfd; // max fd count to monitor int _cancelpipe[2]; // pipe used to help cancel thread public: DataReady() { nfds = 0; fd_array_size = 0; fds = 0; tid = 0; pthread_mutex_init(&_datalock, NULL); FD_ZERO(&_fdsets[0]); FD_ZERO(&_fdsets[1]); FD_ZERO(&_fdsets[2]); _cancelpipe[0] = _cancelpipe[1] = 0; _maxfd = -1; } ~DataReady() { CancelThread(DEBUGTEXT("DESTRUCTOR\n")); if (fds) { free(fds); fds = 0; } nfds = 0; } // Locks // The convention for locks: volatile vars start with '_', // and must be locked before use. Locked code is prefixed // with /*LOCK*/ to make painfully obvious esp. in debuggers. -erco // void DataLock() { pthread_mutex_lock(&_datalock); } void DataUnlock() { pthread_mutex_unlock(&_datalock); } // Accessors int IsThreadRunning() { return(tid ? 1 : 0); } int GetNfds() { return(nfds); } int GetCancelPipe(int ix) { return(_cancelpipe[ix]); } fd_set GetFdset(int ix) { return(_fdsets[ix]); } // Methods void AddFD(int n, int events, void (*cb)(int, void*), void *v); void RemoveFD(int n, int events); int CheckData(fd_set& r, fd_set& w, fd_set& x); void HandleData(fd_set& r, fd_set& w, fd_set& x); static void* DataReadyThread(void *self); void StartThread(void); void CancelThread(const char *reason); }; static DataReady dataready; void DataReady::AddFD(int n, int events, void (*cb)(int, void*), void *v) { RemoveFD(n, events); int i = nfds++; if (i >= fd_array_size) { fl_open_display(); // necessary for NSApp to be defined and the event loop to work FD *temp; fd_array_size = 2*fd_array_size+1; if (!fds) { temp = (FD*)malloc(fd_array_size*sizeof(FD)); } else { temp = (FD*)realloc(fds, fd_array_size*sizeof(FD)); } if (!temp) return; fds = temp; } fds[i].cb = cb; fds[i].arg = v; fds[i].fd = n; fds[i].events = events; DataLock(); /*LOCK*/ if (events & POLLIN) FD_SET(n, &_fdsets[0]); /*LOCK*/ if (events & POLLOUT) FD_SET(n, &_fdsets[1]); /*LOCK*/ if (events & POLLERR) FD_SET(n, &_fdsets[2]); /*LOCK*/ if (n > _maxfd) _maxfd = n; DataUnlock(); } // Remove an FD from the array void DataReady::RemoveFD(int n, int events) { int i,j; _maxfd = -1; // recalculate maxfd on the fly for (i=j=0; i _maxfd) _maxfd = fds[i].fd; // move it down in the array if necessary: if (jDataLock(); /*LOCK*/ int maxfd = self->_maxfd; /*LOCK*/ fd_set r = self->GetFdset(0); /*LOCK*/ fd_set w = self->GetFdset(1); /*LOCK*/ fd_set x = self->GetFdset(2); /*LOCK*/ int cancelpipe = self->GetCancelPipe(0); /*LOCK*/ if ( cancelpipe > maxfd ) maxfd = cancelpipe; /*LOCK*/ FD_SET(cancelpipe, &r); // add cancelpipe to fd's to watch /*LOCK*/ FD_SET(cancelpipe, &x); self->DataUnlock(); // timeval t = { 1000, 0 }; // 1000 seconds; timeval t = { 2, 0 }; // HACK: 2 secs prevents 'hanging' problem int ret = ::select(maxfd+1, &r, &w, &x, &t); pthread_testcancel(); // OSX 10.0.4 and older: needed for parent to cancel switch ( ret ) { case 0: // NO DATA continue; case -1: // ERROR { DEBUGPERRORMSG("CHILD THREAD: select() failed"); return(NULL); // error? exit thread } default: // DATA READY { if (FD_ISSET(cancelpipe, &r) || FD_ISSET(cancelpipe, &x)) // cancel? { return(NULL); } // just exit DEBUGMSG("CHILD THREAD: DATA IS READY\n"); NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init]; NSEvent *event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined location:NSMakePoint(0,0) modifierFlags:0 timestamp:0 windowNumber:0 context:NULL subtype:FLTKDataReadyEvent data1:0 data2:0]; [NSApp postEvent:event atStart:NO]; [localPool release]; return(NULL); // done with thread } } } } // START 'DATA READY' THREAD RUNNING, CREATE INTER-THREAD PIPE void DataReady::StartThread(void) { CancelThread(DEBUGTEXT("STARTING NEW THREAD\n")); DataLock(); /*LOCK*/ pipe(_cancelpipe); // pipe for sending cancel msg to thread DataUnlock(); DEBUGMSG("*** START THREAD\n"); pthread_create(&tid, NULL, DataReadyThread, (void*)this); } // CANCEL 'DATA READY' THREAD, CLOSE PIPE void DataReady::CancelThread(const char *reason) { if ( tid ) { DEBUGMSG("*** CANCEL THREAD: "); DEBUGMSG(reason); if ( pthread_cancel(tid) == 0 ) { // cancel first DataLock(); /*LOCK*/ write(_cancelpipe[1], "x", 1); // wake thread from select DataUnlock(); pthread_join(tid, NULL); // wait for thread to finish } tid = 0; DEBUGMSG("(JOINED) OK\n"); } // Close pipe if open DataLock(); /*LOCK*/ if ( _cancelpipe[0] ) { close(_cancelpipe[0]); _cancelpipe[0] = 0; } /*LOCK*/ if ( _cancelpipe[1] ) { close(_cancelpipe[1]); _cancelpipe[1] = 0; } DataUnlock(); } void Fl_Darwin_System_Driver::add_fd( int n, int events, void (*cb)(int, void*), void *v ) { dataready.AddFD(n, events, cb, v); } void Fl_Darwin_System_Driver::add_fd(int fd, void (*cb)(int, void*), void* v) { dataready.AddFD(fd, POLLIN, cb, v); } void Fl_Darwin_System_Driver::remove_fd(int n, int events) { dataready.RemoveFD(n, events); } void Fl_Darwin_System_Driver::remove_fd(int n) { dataready.RemoveFD(n, -1); } /* * Check if there is actually a message pending */ int Fl_Darwin_System_Driver::ready() { NSEvent *retval = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate dateWithTimeIntervalSinceNow:0] inMode:NSDefaultRunLoopMode dequeue:NO]; return retval != nil; } static void processFLTKEvent(void) { fl_lock_function(); dataready.CancelThread(DEBUGTEXT("DATA READY EVENT\n")); // CHILD THREAD TELLS US DATA READY // Check to see what's ready, and invoke user's cb's // fd_set r,w,x; switch(dataready.CheckData(r,w,x)) { case 0: // NO DATA break; case -1: // ERROR break; default: // DATA READY dataready.HandleData(r,w,x); break; } fl_unlock_function(); return; } /* * break the current event loop */ void Fl_Cocoa_Screen_Driver::breakMacEventLoop() { NSEvent *event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined location:NSMakePoint(0,0) modifierFlags:0 timestamp:0 windowNumber:0 context:NULL subtype:FLTKTimerEvent data1:0 data2:0]; [NSApp postEvent:event atStart:NO]; } @interface FLWindow : NSWindow { Fl_Window *w; } - (FLWindow*)initWithFl_W:(Fl_Window *)flw contentRect:(NSRect)rect styleMask:(NSUInteger)windowStyle; - (Fl_Window *)getFl_Window; - (void)recursivelySendToSubwindows:(SEL)sel applyToSelf:(BOOL)b; - (void)setSubwindowFrame; - (void)checkSubwindowFrame; - (void)waitForExpose; - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - (NSPoint)convertBaseToScreen:(NSPoint)aPoint; #endif - (NSBitmapImageRep*)rect_to_NSBitmapImageRep:(Fl_Rect*)r; - (void)makeKeyWindow; @end @interface FLView : NSView = MAC_OS_X_VERSION_10_5 , NSTextInputClient #endif #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 ,NSDraggingSource #endif > { BOOL in_key_event; // YES means keypress is being processed by handleEvent BOOL need_handle; // YES means Fl::handle(FL_KEYBOARD,) is needed after handleEvent processing NSInteger identifier; NSRange selectedRange; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 @public CGContextRef aux_bitmap; // all drawing to view goes there and is finally copied to the CALayer #endif } + (void)prepareEtext:(NSString*)aString; + (void)concatEtext:(NSString*)aString; - (BOOL)process_keydown:(NSEvent*)theEvent; - (id)initWithFrame:(NSRect)frameRect; - (void)drawRect:(NSRect)rect; - (BOOL)acceptsFirstResponder; - (BOOL)acceptsFirstMouse:(NSEvent*)theEvent; - (void)resetCursorRects; - (BOOL)performKeyEquivalent:(NSEvent*)theEvent; - (void)mouseUp:(NSEvent *)theEvent; - (void)rightMouseUp:(NSEvent *)theEvent; - (void)otherMouseUp:(NSEvent *)theEvent; - (void)mouseDown:(NSEvent *)theEvent; - (void)rightMouseDown:(NSEvent *)theEvent; - (void)otherMouseDown:(NSEvent *)theEvent; - (void)mouseMoved:(NSEvent *)theEvent; - (void)mouseEntered:(NSEvent *)theEvent; - (void)mouseExited:(NSEvent *)theEvent; - (void)mouseDragged:(NSEvent *)theEvent; - (void)rightMouseDragged:(NSEvent *)theEvent; - (void)otherMouseDragged:(NSEvent *)theEvent; - (void)scrollWheel:(NSEvent *)theEvent; - (void)magnifyWithEvent:(NSEvent *)theEvent; - (void)keyDown:(NSEvent *)theEvent; - (void)keyUp:(NSEvent *)theEvent; - (void)flagsChanged:(NSEvent *)theEvent; - (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender; - (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender; - (BOOL)performDragOperation:(id )sender; - (void)draggingExited:(id < NSDraggingInfo >)sender; - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal; #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange; - (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection replacementRange:(NSRange)replacementRange; - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange; - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange; - (NSInteger)windowLevel; #else - (void)updateTrackingAreas; #endif #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context; - (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation; #endif - (BOOL)did_view_resolution_change; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 - (void)create_aux_bitmap:(CGContextRef)gc retina:(BOOL)r; - (void)reset_aux_bitmap; #endif @end @implementation FLWindow - (void)close { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 if (views_use_CA) [(FLView*)[self contentView] reset_aux_bitmap]; #endif [[self standardWindowButton:NSWindowDocumentIconButton] setImage:nil]; [super close]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 while (fl_mac_os_version >= 100500) { NSArray *a = [[self contentView] trackingAreas]; if ([a count] == 0) break; NSTrackingArea *ta = (NSTrackingArea*)[a objectAtIndex:0]; [[self contentView] removeTrackingArea:ta]; } #endif // when a fullscreen window is closed, windowDidResize may be sent after the close message was sent // and before the FLWindow receives the final dealloc message w = NULL; } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - (NSPoint)convertBaseToScreen:(NSPoint)aPoint { if (fl_mac_os_version >= 100700) { NSRect r = [self convertRectToScreen:NSMakeRect(aPoint.x, aPoint.y, 0, 0)]; return r.origin; } else { // replaces return [super convertBaseToScreen:aPoint] that may trigger a compiler warning typedef NSPoint (*convertIMP)(id, SEL, NSPoint); static convertIMP addr = (convertIMP)[NSWindow instanceMethodForSelector:@selector(convertBaseToScreen:)]; return addr(self, @selector(convertBaseToScreen:), aPoint); } } #endif - (FLWindow*)initWithFl_W:(Fl_Window *)flw contentRect:(NSRect)rect styleMask:(NSUInteger)windowStyle { self = [super initWithContentRect:rect styleMask:windowStyle backing:NSBackingStoreBuffered defer:NO]; if (self) { w = flw; if (fl_mac_os_version >= 100700) { // replaces [self setRestorable:NO] that may trigger a compiler warning typedef void (*setIMP)(id, SEL, BOOL); static setIMP addr = (setIMP)[NSWindow instanceMethodForSelector:@selector(setRestorable:)]; addr(self, @selector(setRestorable:), NO); } } return self; } - (Fl_Window *)getFl_Window; { return w; } - (BOOL)canBecomeKeyWindow { if (Fl::modal_ && (Fl::modal_ != w)) return NO; // prevent the caption to be redrawn as active on click // when another modal window is currently the key win return !(!w || w->output() || w->tooltip_window() || w->menu_window() || w->parent()); } - (BOOL)canBecomeMainWindow { if (Fl::modal_ && (Fl::modal_ != w)) return NO; // prevent the caption to be redrawn as active on click // when another modal window is currently the key win return !(!w || w->tooltip_window() || w->menu_window() || w->parent()); } - (void)recursivelySendToSubwindows:(SEL)sel applyToSelf:(BOOL)b { if (b) [self performSelector:sel]; NSEnumerator *enumerator = [[self childWindows] objectEnumerator]; id child; while ((child = [enumerator nextObject]) != nil) { if ([child isKindOfClass:[FLWindow class]]) [child recursivelySendToSubwindows:sel applyToSelf:YES]; } } - (void)setSubwindowFrame { // have the cocoa position and size of a (sub)window follow its FLTK data Fl_Window *parent = w->window(); if (!w->visible_r()) return; NSPoint pt = FLTKtoCocoa(w, w->x(), w->y(), w->h()); float s = Fl::screen_driver()->scale(0); int bt = parent ? 0 : get_window_frame_sizes(w); NSRect rp = NSMakeRect(round(pt.x), round(pt.y), round(s * w->w()), round(s * w->h()) + bt); if (!NSEqualRects(rp, [self frame])) { [self setFrame:rp display:(views_use_CA ? NO : YES)]; } if (parent && ![self parentWindow]) { // useful when subwin is first shown, not when moved FLWindow *pxid = fl_xid(parent); [pxid addChildWindow:self ordered:NSWindowAbove]; // needs OS X 10.2 [self orderWindow:NSWindowAbove relativeTo:[pxid windowNumber]]; // necessary under 10.3 } } - (void)checkSubwindowFrame { if (!w->parent()) return; // make sure this subwindow doesn't leak out of its parent window Fl_Window *from = w, *parent; CGRect full = CGRectMake(0, 0, w->w(), w->h()); // full subwindow area CGRect srect = full; // will become new subwindow clip int fromx = 0, fromy = 0; while ((parent = from->window()) != NULL) { // loop over all parent windows fromx -= from->x(); // parent origin in subwindow's coordinates fromy -= from->y(); CGRect prect = CGRectMake(fromx, fromy, parent->w(), parent->h()); srect = CGRectIntersection(prect, srect); // area of subwindow inside its parent from = parent; } Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(w); CGRect *r = d->subRect(); CGRect current_clip = (r ? *r : full); // current subwindow clip if (!CGRectEqualToRect(srect, current_clip)) { // if new clip differs from current clip delete r; FLWindow *xid = fl_xid(w); FLView *view = (FLView*)[xid contentView]; if (CGRectEqualToRect(srect, full)) { r = NULL; } else { r = new CGRect(srect); if (r->size.width == 0 && r->size.height == 0) r->origin.x = r->origin.y = 0; } d->subRect(r); w->redraw(); if (fl_mac_os_version < 100900) { NSInteger parent_num = [fl_xid(w->window()) windowNumber]; [xid orderWindow:NSWindowBelow relativeTo:parent_num]; [xid orderWindow:NSWindowAbove relativeTo:parent_num]; } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 if (!views_use_CA || view->aux_bitmap) #endif [view display]; // subwindow needs redrawn } } -(void)waitForExpose { if ([self getFl_Window]->shown()) { // this makes freshly created windows appear on the screen, if they are not there already NSModalSession session = [NSApp beginModalSessionForWindow:self]; [NSApp runModalSession:session]; [NSApp endModalSession:session]; } } /* With Mac OS 10.11 the green window button makes window fullscreen (covers system menu bar and dock). When there are subwindows, they are by default constrained not to cover the menu bar (this is arguably a Mac OS bug). Overriding the constrainFrameRect:toScreen: method removes this constraint. */ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen { if ([self parentWindow]) return frameRect; // do not constrain subwindows return [super constrainFrameRect:frameRect toScreen:screen]; // will prevent a window from going above the menu bar } - (NSBitmapImageRep*)rect_to_NSBitmapImageRep:(Fl_Rect*)r { return rect_to_NSBitmapImageRep(w, r->x(), r->y(), r->w(), r->h()); } - (void)makeKeyWindow { // Necessary in this scenario at least: // transition of a subwindow-containing window from multiscreen-fullscreen mode to normal mode. if ([self canBecomeKeyWindow]) [super makeKeyWindow]; } @end @interface FLApplication : NSObject { } + (void)sendEvent:(NSEvent *)theEvent; @end /* * This function is the central event handler. * It reads events from the event queue using the given maximum time */ static int do_queued_events( double time = 0.0 ) { static int got_events; // not sure the static is necessary here got_events = 0; // Check for re-entrant condition if ( dataready.IsThreadRunning() ) { dataready.CancelThread(DEBUGTEXT("AVOID REENTRY\n")); } // Start thread to watch for data ready if ( dataready.GetNfds() ) { dataready.StartThread(); } // Elapse timeouts and calculate waiting time Fl_Timeout::elapse_timeouts(); time = Fl_Timeout::time_to_wait(time); fl_unlock_function(); NSEvent *event; while ( (event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate dateWithTimeIntervalSinceNow:time] inMode:NSDefaultRunLoopMode dequeue:YES]) != nil ) { got_events = 1; [FLApplication sendEvent:event]; // will then call [NSApplication sendevent:] time = 0; } fl_lock_function(); return got_events; } double Fl_Darwin_System_Driver::wait(double time_to_wait) { if (dropped_files_list) { // when the list of dropped files is not empty, open one and remove it from list drain_dropped_files_list(); } NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; time_to_wait = Fl_System_Driver::wait(time_to_wait); // the deprecation warnings can be ignored because they run only for macOS < 10.11 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" if (fl_mac_os_version < 101100) NSDisableScreenUpdates(); // deprecated 10.11 Fl::flush(); if (fl_mac_os_version < 101100) NSEnableScreenUpdates(); // deprecated 10.11 #pragma clang diagnostic pop if (Fl::idle) // 'idle' may have been set within flush() time_to_wait = 0.0; int retval = do_queued_events(time_to_wait); Fl_Cocoa_Window_Driver::q_release_context(); [pool release]; return retval; } static NSInteger max_normal_window_level(void) { Fl_X *x; NSInteger max_level; max_level = 0; for (x = Fl_X::first;x;x = x->next) { NSInteger level; FLWindow *cw = (FLWindow*)x->xid; Fl_Window *win = x->w; if (!win || !cw || ![cw isVisible]) continue; if (win->modal() || win->non_modal()) continue; level = [cw level]; if (level >= max_level) max_level = level; } return max_level; } // appropriate window level for modal windows static NSInteger modal_window_level(void) { NSInteger level; level = max_normal_window_level(); if (level < NSStatusWindowLevel) return NSStatusWindowLevel; // Need some room for non-modal windows level += 2; // We cannot exceed this if (level > CGShieldingWindowLevel()) return CGShieldingWindowLevel(); return level; } // appropriate window level for non-modal windows static NSInteger non_modal_window_level(void) { NSInteger level; level = max_normal_window_level(); if (level < NSFloatingWindowLevel) return NSFloatingWindowLevel; level += 1; if (level > CGShieldingWindowLevel()) return CGShieldingWindowLevel(); return level; } // makes sure modal and non-modal windows stay on top static void fixup_window_levels(void) { NSInteger modal_level, non_modal_level; Fl_X *x; FLWindow *prev_modal, *prev_non_modal; modal_level = modal_window_level(); non_modal_level = non_modal_window_level(); prev_modal = NULL; prev_non_modal = NULL; for (x = Fl_X::first;x;x = x->next) { FLWindow *cw = (FLWindow*)x->xid; Fl_Window *win = x->w; if (!win || !cw || ![cw isVisible]) continue; if (win->modal()) { if ([cw level] != modal_level) { [cw setLevel:modal_level]; // changing level puts then in front, so make sure the // stacking isn't messed up if (prev_modal != NULL) [cw orderWindow:NSWindowBelow relativeTo:[prev_modal windowNumber]]; } prev_modal = cw; } else if (win->non_modal()) { if ([cw level] != non_modal_level) { [cw setLevel:non_modal_level]; if (prev_non_modal != NULL) [cw orderWindow:NSWindowBelow relativeTo:[prev_non_modal windowNumber]]; } prev_non_modal = cw; } } } // updates Fl::e_x, Fl::e_y, Fl::e_x_root, and Fl::e_y_root static void update_e_xy_and_e_xy_root(NSWindow *nsw) { NSPoint pt; pt = [nsw mouseLocationOutsideOfEventStream]; float s = Fl::screen_driver()->scale(0); Fl::e_x = int(pt.x / s); Fl::e_y = int(([[nsw contentView] frame].size.height - pt.y)/s); pt = [NSEvent mouseLocation]; Fl::e_x_root = int(pt.x/s); Fl::e_y_root = int((main_screen_height - pt.y)/s); } /* * Cocoa Mousewheel handler */ static void cocoaMouseWheelHandler(NSEvent *theEvent) { // Handle the new "MightyMouse" mouse wheel events. Please, someone explain // to me why Apple changed the API on this even though the current API // supports two wheels just fine. Matthias, fl_lock_function(); Fl_Window *window = (Fl_Window*)[(FLWindow*)[theEvent window] getFl_Window]; Fl::first_window(window); // Under OSX, mousewheel deltas are floats, but fltk only supports ints. float s = Fl::screen_driver()->scale(0); float edx = [theEvent deltaX]; float edy = [theEvent deltaY]; int dx = roundf(edx / s); int dy = roundf(edy / s); // make sure that even small wheel movements count at least as one unit if (edx>0.0f) dx++; else if (edx<0.0f) dx--; if (edy>0.0f) dy++; else if (edy<0.0f) dy--; // allow both horizontal and vertical movements to be processed by the widget if (dx) { Fl::e_dx = -dx; Fl::e_dy = 0; Fl::handle( FL_MOUSEWHEEL, window ); } if (dy) { Fl::e_dx = 0; Fl::e_dy = -dy; Fl::handle( FL_MOUSEWHEEL, window ); } fl_unlock_function(); } /* * Cocoa Magnify Gesture Handler */ static void cocoaMagnifyHandler(NSEvent *theEvent) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 fl_lock_function(); Fl_Window *window = (Fl_Window*)[(FLWindow*)[theEvent window] getFl_Window]; if ( !window->shown() ) { fl_unlock_function(); return; } Fl::first_window(window); Fl::e_dy = [theEvent magnification]*1000; // 10.5.2 if ( Fl::e_dy) { NSPoint pos = [theEvent locationInWindow]; pos.y = window->h() - pos.y; NSUInteger mods = [theEvent modifierFlags]; mods_to_e_state( mods ); update_e_xy_and_e_xy_root([theEvent window]); Fl::handle( FL_ZOOM_GESTURE, window ); } fl_unlock_function(); #endif } /* * Cocoa Mouse Button Handler */ static void cocoaMouseHandler(NSEvent *theEvent) { static int keysym[] = { 0, FL_Button+1, FL_Button+3, FL_Button+2, FL_Button+4, FL_Button+5 }; static int px, py; fl_lock_function(); Fl_Window *window = (Fl_Window*)[(FLWindow*)[theEvent window] getFl_Window]; if (!window || !window->shown() ) { fl_unlock_function(); return; } NSPoint pos = [theEvent locationInWindow]; float s = Fl::screen_driver()->scale(0); pos.x /= s; pos.y /= s; pos.y = window->h() - pos.y; NSInteger btn = [theEvent buttonNumber] + 1; NSUInteger mods = [theEvent modifierFlags]; int sendEvent = 0; NSEventType etype = [theEvent type]; if (etype == NSEventTypeLeftMouseDown || etype == NSEventTypeRightMouseDown || etype == NSEventTypeOtherMouseDown) { if (btn == 1) Fl::e_state |= FL_BUTTON1; else if (btn == 3) Fl::e_state |= FL_BUTTON2; else if (btn == 2) Fl::e_state |= FL_BUTTON3; else if (btn == 4) Fl::e_state |= FL_BUTTON4; else if (btn == 5) Fl::e_state |= FL_BUTTON5; } else if (etype == NSEventTypeLeftMouseUp || etype == NSEventTypeRightMouseUp || etype == NSEventTypeOtherMouseUp) { if (btn == 1) Fl::e_state &= ~FL_BUTTON1; else if (btn == 3) Fl::e_state &= ~FL_BUTTON2; else if (btn == 2) Fl::e_state &= ~FL_BUTTON3; else if (btn == 4) Fl::e_state &= ~FL_BUTTON4; else if (btn == 5) Fl::e_state &= ~FL_BUTTON5; } switch ( etype ) { case NSEventTypeLeftMouseDown: case NSEventTypeRightMouseDown: case NSEventTypeOtherMouseDown: sendEvent = FL_PUSH; Fl::e_is_click = 1; px = (int)pos.x; py = (int)pos.y; if ([theEvent clickCount] > 1) Fl::e_clicks++; else Fl::e_clicks = 0; // fall through case NSEventTypeLeftMouseUp: case NSEventTypeRightMouseUp: case NSEventTypeOtherMouseUp: if ( !window ) break; if ( !sendEvent ) { sendEvent = FL_RELEASE; } Fl::e_keysym = keysym[ btn ]; // fall through case NSEventTypeMouseMoved: if ( !sendEvent ) { sendEvent = FL_MOVE; } // fall through case NSEventTypeLeftMouseDragged: case NSEventTypeRightMouseDragged: case NSEventTypeOtherMouseDragged: { if ( !sendEvent ) { sendEvent = FL_MOVE; // Fl::handle will convert into FL_DRAG if (fabs(pos.x-px)>5 || fabs(pos.y-py)>5) Fl::e_is_click = 0; } mods_to_e_state( mods ); update_e_xy_and_e_xy_root([theEvent window]); if (fl_mac_os_version < 100500) { // before 10.5, mouse moved events aren't sent to borderless windows such as tooltips Fl_Window *tooltip = Fl_Tooltip::current_window(); int inside = 0; if (tooltip && tooltip->shown() ) { // check if a tooltip window is currently opened // check if mouse is inside the tooltip inside = (Fl::event_x_root() >= tooltip->x() && Fl::event_x_root() < tooltip->x() + tooltip->w() && Fl::event_y_root() >= tooltip->y() && Fl::event_y_root() < tooltip->y() + tooltip->h() ); } // if inside, send event to tooltip window instead of background window if (inside) window = tooltip; } Fl::handle( sendEvent, window ); } break; case NSEventTypeMouseEntered : Fl::handle(FL_ENTER, window); break; case NSEventTypeMouseExited : Fl::handle(FL_LEAVE, window); break; default: break; } fl_unlock_function(); return; } @interface FLTextView : NSTextView // this subclass is only needed under OS X < 10.6 { BOOL isActive; } + (void)initialize; + (FLTextView*)singleInstance; - (void)insertText:(id)aString; - (void)doCommandBySelector:(SEL)aSelector; - (void)setActive:(BOOL)a; @end static FLTextView *fltextview_instance = nil; @implementation FLTextView + (void)initialize { NSRect rect={{0,0},{20,20}}; fltextview_instance = [[FLTextView alloc] initWithFrame:rect]; } + (FLTextView*)singleInstance { return fltextview_instance; } - (void)insertText:(id)aString { if (isActive) [[[NSApp keyWindow] contentView] insertText:aString]; } - (void)doCommandBySelector:(SEL)aSelector { [[[NSApp keyWindow] contentView] doCommandBySelector:aSelector]; } - (void)setActive:(BOOL)a { isActive = a; } @end @interface FLWindowDelegate : NSObject #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 #endif + (void)initialize; + (FLWindowDelegate*)singleInstance; - (void)windowDidMove:(NSNotification *)notif; - (void)view_did_resize:(NSNotification *)notif; - (void)windowDidResignKey:(NSNotification *)notif; - (void)windowDidBecomeKey:(NSNotification *)notif; - (void)windowDidBecomeMain:(NSNotification *)notif; - (void)windowDidDeminiaturize:(NSNotification *)notif; - (void)fl_windowMiniaturize:(NSNotification *)notif; - (void)windowDidMiniaturize:(NSNotification *)notif; - (void)windowWillEnterFullScreen:(NSNotification *)notif; - (void)windowWillExitFullScreen:(NSNotification *)notif; - (BOOL)windowShouldClose:(id)fl; - (void)anyWindowWillClose:(NSNotification *)notif; - (void)doNothing:(id)unused; - (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu; @end /* make subwindows re-appear after appl unhide or window deminiaturize (not necessary with 10.5 and above) */ static void orderfront_subwindows(FLWindow *xid) { NSArray *children = [xid childWindows]; // 10.2 NSEnumerator *enumerator = [children objectEnumerator]; id child; while ((child = [enumerator nextObject]) != nil) { // this undo-redo seems necessary under 10.3 [xid removeChildWindow:child]; [xid addChildWindow:child ordered:NSWindowAbove]; [child orderWindow:NSWindowAbove relativeTo:[xid windowNumber]]; orderfront_subwindows(child); } } @interface FLWindowDelegateBefore10_6 : FLWindowDelegate - (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client; @end @implementation FLWindowDelegateBefore10_6 - (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client { return [FLTextView singleInstance]; } @end @interface FLWindowDelegateBefore10_5 : FLWindowDelegateBefore10_6 -(void)windowDidDeminiaturize:(NSNotification *)notif; -(void)windowWillMiniaturize:(NSNotification *)notif; @end @implementation FLWindowDelegateBefore10_5 -(void)windowDidDeminiaturize:(NSNotification *)notif { [super windowDidDeminiaturize:notif]; fl_lock_function(); orderfront_subwindows([notif object]); fl_unlock_function(); } -(void)windowWillMiniaturize:(NSNotification *)notif { [super fl_windowMiniaturize:notif]; NSArray *children = [(NSWindow*)[notif object] childWindows]; // 10.2 NSEnumerator *enumerator = [children objectEnumerator]; id child; while ((child = [enumerator nextObject]) != nil) [child orderOut:self]; } @end // compute coordinates of the win top left in FLTK units static void CocoatoFLTK(Fl_Window *win, int &x, int &y) { NSPoint ori; FLWindow *nsw = fl_xid(win); ori = [nsw convertBaseToScreen:NSMakePoint(0, [[nsw contentView] frame].size.height)]; float s = Fl::screen_driver()->scale(0); x = (int)lround(ori.x / s); y = (int)lround((main_screen_height - ori.y) / s); while (win->parent()) {win = win->window(); x -= win->x(); y -= win->y();} } // return Cocoa coordinates of the point in window win at (x,y) FLTK units static NSPoint FLTKtoCocoa(Fl_Window *win, int x, int y, int H) { float s = Fl::screen_driver()->scale(0); while (win->parent()) {win = win->window(); x += win->x(); y += win->y();} return NSMakePoint(round(x * s), main_screen_height - round((y + H)*s)); } static FLWindowDelegate *flwindowdelegate_instance = nil; @implementation FLWindowDelegate + (void)initialize { if (self == [FLWindowDelegate self]) { if (fl_mac_os_version < 100500) flwindowdelegate_instance = [FLWindowDelegateBefore10_5 alloc]; else if (fl_mac_os_version < 100600) flwindowdelegate_instance = [FLWindowDelegateBefore10_6 alloc]; else flwindowdelegate_instance = [FLWindowDelegate alloc]; flwindowdelegate_instance = [flwindowdelegate_instance init]; } } + (FLWindowDelegate*)singleInstance { return flwindowdelegate_instance; } - (void)windowDidMove:(NSNotification *)notif { fl_lock_function(); FLWindow *nsw = (FLWindow*)[notif object]; Fl_Window *window = [nsw getFl_Window]; if (!window->parent()) starting_moved_window = window; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 FLView *view = (FLView*)[nsw contentView]; if (views_use_CA && [view did_view_resolution_change]) { if (window->as_gl_window() && Fl::use_high_res_GL()) [view setNeedsDisplay:YES]; // necessary with macOS ≥ 10.14.2; harmless before } #endif if (window == starting_moved_window) { // we update 'main_screen_height' here because it's wrong just after screen config changes main_screen_height = CGDisplayBounds(CGMainDisplayID()).size.height; int X, Y; CocoatoFLTK(window, X, Y); if (window->x() != X || window->y() != Y) { if (!Fl_Cocoa_Window_Driver::driver(window)->through_resize()) window->position(X, Y); else window->Fl_Widget::resize(X,Y,window->w(),window->h()); } update_e_xy_and_e_xy_root(nsw); // at least since MacOS 10.9: OS moves subwindows contained in a moved window // setSubwindowFrame is no longer necessary. if (fl_mac_os_version < 100900) [nsw recursivelySendToSubwindows:@selector(setSubwindowFrame) applyToSelf:NO]; if (window->parent()) [nsw recursivelySendToSubwindows:@selector(checkSubwindowFrame) applyToSelf:YES]; starting_moved_window = NULL; } if (!window->parent()) { int nscreen = Fl::screen_num(window->x(), window->y(), window->w(), window->h()); Fl_Window_Driver::driver(window)->screen_num(nscreen); } fl_unlock_function(); } /* This method is called whenever the view of an Fl_Window changes size. This can happen for various reasons: - the user resizes a desktop window (NSViewFrameDidChangeNotification) Fl_Cocoa_Window_Driver::driver(window)->through_resize() == 0 for the top level window Fl_Window::is_a_rescale() == 0 - the app scale is changed (the Cocoa size changes, but the FLTK size remains) Fl_Cocoa_Window_Driver::driver(window)->through_resize() == 1 Fl_Window::is_a_rescale() == 1 - a window is resized by application code: Fl_Window:resize() Fl_Cocoa_Window_Driver::driver(window)->through_resize() == 1 Fl_Window::is_a_rescale() == 0 Note that a top level window must be treated differently than a subwindow (an Fl_Window that is the child of another window). Also note, it's important to keep the logical FLTK coordinate system intact. Converting Cocoa coordinates into FLTK coordinates is not reliable because it loses precision if the screen scale is set to anything but 1:1. See also: Fl_Cocoa_Window_Driver::driver(window)->view_resized() avoid recursion Fl_Cocoa_Window_Driver::driver(window)->through_resize(); avoid recursion Fl_Cocoa_Window_Driver::driver(window)->changed_resolution(); tested OK */ - (void)view_did_resize:(NSNotification *)notif { if (![[notif object] isKindOfClass:[FLView class]]) return; FLView *view = (FLView*)[notif object]; FLWindow *nsw = (FLWindow*)[view window]; if (!nsw || ![nsw getFl_Window]) return; fl_lock_function(); Fl_Window *window = [nsw getFl_Window]; int X, Y, W, H; float s = Fl::screen_driver()->scale(window->screen_num()); if (Fl_Window::is_a_rescale()) { if (window->parent()) { X = window->x(); Y = window->y(); } else { // Recalculate the FLTK position from the current Cocoa position applying // the new scale, so the window stays at its current position after scaling. CocoatoFLTK(window, X, Y); } W = window->w(); H = window->h(); } else if (Fl_Cocoa_Window_Driver::driver(window)->through_resize()) { if (window->parent()) { X = window->x(); Y = window->y(); } else { // Recalculate the FLTK position from the current Cocoa position CocoatoFLTK(window, X, Y); } W = window->w(); H = window->h(); } else { CocoatoFLTK(window, X, Y); NSRect r = [view frame]; W = (int)lround(r.size.width/s); H = (int)lround(r.size.height/s); } Fl_Cocoa_Window_Driver::driver(window)->view_resized(1); if (Fl_Cocoa_Window_Driver::driver(window)->through_resize()) { if (window->as_gl_window()) { static Fl_Cocoa_Plugin *plugin = NULL; if (!plugin) { Fl_Plugin_Manager pm("fltk:cocoa"); plugin = (Fl_Cocoa_Plugin*)pm.plugin("gl.cocoa.fltk.org"); } // calls Fl_Gl_Window::resize() without including Fl_Gl_Window.H plugin->resize(window->as_gl_window(), X, Y, W, H); } else { Fl_Cocoa_Window_Driver::driver(window)->resize(X, Y, W, H); } } else window->resize(X, Y, W, H); Fl_Cocoa_Window_Driver::driver(window)->view_resized(0); update_e_xy_and_e_xy_root(nsw); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 if (views_use_CA && !window->as_gl_window()) { [view reset_aux_bitmap]; window->redraw(); } #endif if (!window->parent() && window->border() && Fl_Window_Driver::driver(window)->is_resizable()) { Fl_Cocoa_Window_Driver::driver(window)->is_maximized([nsw isZoomed] && !window->fullscreen_active()); } fl_unlock_function(); } - (void)windowDidResignKey:(NSNotification *)notif { fl_lock_function(); FLWindow *nsw = (FLWindow*)[notif object]; Fl_Window *window = [nsw getFl_Window]; /* Fullscreen windows obscure all other windows so we need to return to a "normal" level when the user switches to another window or another app */ if (window->fullscreen_active()) { [nsw setLevel:NSNormalWindowLevel]; fixup_window_levels(); } Fl::handle( FL_UNFOCUS, window); fl_unlock_function(); } - (void)windowDidBecomeKey:(NSNotification *)notif { fl_lock_function(); FLWindow *nsw = (FLWindow*)[notif object]; Fl_Window *w = [nsw getFl_Window]; /* Restore previous fullscreen level */ if (w->fullscreen_active() # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 && (fl_mac_os_version < 100700 || !(nsw.styleMask & NSWindowStyleMaskFullScreen)) #endif ) { [nsw setLevel:NSStatusWindowLevel]; fixup_window_levels(); } Fl::handle( FL_FOCUS, w); fl_unlock_function(); } - (void)windowDidBecomeMain:(NSNotification *)notif { fl_lock_function(); FLWindow *nsw = (FLWindow*)[notif object]; Fl_Window *window = [nsw getFl_Window]; Fl::first_window(window); if (!window->parent()) [nsw orderFront:nil]; update_e_xy_and_e_xy_root(nsw); if (fl_sys_menu_bar && Fl_MacOS_Sys_Menu_Bar_Driver::window_menu_style()) { // select the corresponding Window menu item int index = Fl_MacOS_Sys_Menu_Bar_Driver::driver()->first_window_menu_item; while (index > 0) { Fl_Menu_Item *item = Fl_MacOS_Sys_Menu_Bar_Driver::driver()->window_menu_items + index; if (!item->label()) break; if (item->user_data() == window) { if (!item->value()) { item->setonly(); fl_sys_menu_bar->update(); } break; } index++; } } fl_unlock_function(); } - (void)windowDidDeminiaturize:(NSNotification *)notif { fl_lock_function(); FLWindow *nsw = (FLWindow*)[notif object]; if ([nsw miniwindowImage]) { [nsw setMiniwindowImage:nil]; } Fl_Window *window = [nsw getFl_Window]; Fl::handle(FL_SHOW, window); // necessary when resolutions before miniaturization and after deminiaturization differ // or if GUI was resized while window was minimized [nsw recursivelySendToSubwindows:@selector(setSubwindowFrame) applyToSelf:YES]; update_e_xy_and_e_xy_root(nsw); Fl::flush(); // Process redraws set by FL_SHOW. fl_unlock_function(); } - (void)fl_windowMiniaturize:(NSNotification *)notif { // subwindows are not captured in system-built miniature window image fl_lock_function(); FLWindow *nsw = (FLWindow*)[notif object]; if ([[nsw childWindows] count]) { Fl_Window *window = [nsw getFl_Window]; // capture the window and its subwindows and use as miniature window image NSBitmapImageRep *bitmap = rect_to_NSBitmapImageRep_subwins(window, 0, 0, window->w(), window->h(), true); if (bitmap) { NSImage *img = [[[NSImage alloc] initWithSize:NSMakeSize([bitmap pixelsWide], [bitmap pixelsHigh])] autorelease]; [img addRepresentation:bitmap]; [bitmap release]; [nsw setMiniwindowImage:img]; } } fl_unlock_function(); } - (void)windowDidMiniaturize:(NSNotification *)notif { if (fl_mac_os_version >= 100500) [self fl_windowMiniaturize:notif]; fl_lock_function(); FLWindow *nsw = (FLWindow*)[notif object]; Fl_Window *window = [nsw getFl_Window]; Fl::handle(FL_HIDE, window); fl_unlock_function(); } - (void)windowWillEnterFullScreen:(NSNotification *)notif; { FLWindow *nsw = (FLWindow*)[notif object]; Fl_Window *window = [nsw getFl_Window]; window->_set_fullscreen(); } - (void)windowWillExitFullScreen:(NSNotification *)notif; { FLWindow *nsw = (FLWindow*)[notif object]; Fl_Window *window = [nsw getFl_Window]; window->_clear_fullscreen(); } - (BOOL)windowShouldClose:(id)fl { fl_lock_function(); Fl_Window *win = [(FLWindow *)fl getFl_Window]; if (win) Fl::handle(FL_CLOSE, win); // this might or might not close the window fl_unlock_function(); // the system doesn't need to send [fl close] because FLTK does it when needed return NO; } - (void)anyWindowWillClose:(NSNotification *)notif { fl_lock_function(); if ([[notif object] isKeyWindow]) { // If the closing window is the key window, // find a bordered top-level window to become the new key window Fl_Window *w = Fl::first_window(); while (w && (w->parent() || !w->border() || !w->visible())) { w = Fl::next_window(w); } if (w) { [fl_mac_xid(w) makeKeyWindow]; } } fl_unlock_function(); } - (void)doNothing:(id)unused { return; } - (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu { return NO; } @end @interface FLAppDelegate : NSObject #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 #endif { @public open_cb_f_type open_cb; TSMDocumentID currentDoc; } - (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app; - (void)applicationDidFinishLaunching:(NSNotification *)notification; - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender; - (void)applicationDidBecomeActive:(NSNotification *)notify; - (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification; - (void)applicationDidUpdate:(NSNotification *)aNotification; - (void)applicationWillResignActive:(NSNotification *)notify; - (void)applicationWillHide:(NSNotification *)notify; - (void)applicationWillUnhide:(NSNotification *)notify; - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename; @end @implementation FLAppDelegate - (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app { // Avoids macOS 14 warning message when app is launched from command line: // "WARNING: Secure coding is automatically enabled for restorable state! // However, not on all supported macOS versions of this application. // Opt-in to secure coding explicitly by implementing // NSApplicationDelegate.applicationSupportsSecureRestorableState:." return (fl_mac_os_version >= 140000); } - (void)applicationDidFinishLaunching:(NSNotification *)notification { if (fl_mac_os_version >= 101300 && [NSApp isRunning]) [NSApp stop:nil]; } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender { fl_lock_function(); while ( Fl_X::first ) { Fl_Window *win = Fl::first_window(); if (win->parent()) win = win->top_window(); Fl_Widget_Tracker wt(win); // track the window object Fl::handle(FL_CLOSE, win); if (wt.exists() && win->shown()) { // the user didn't close win break; } } fl_unlock_function(); if ( ! Fl::first_window() ) { Fl::program_should_quit(1); Fl_Cocoa_Screen_Driver::breakMacEventLoop(); // necessary when called through menu and in Fl::wait() } return NSTerminateCancel; } - (void)applicationDidBecomeActive:(NSNotification *)notify { fl_lock_function(); // update clipboard status clipboard_check(); /** * Cocoa organizes the Z depth of windows on a global priority. FLTK however * expects the window manager to organize Z level by application. The trickery * below will change Z order during activation and deactivation. */ fixup_window_levels(); fl_unlock_function(); } - (void)applicationDidChangeScreenParameters:(NSNotification *)unused { // react to changes in screen numbers and positions fl_lock_function(); main_screen_height = CGDisplayBounds(CGMainDisplayID()).size.height; Fl::call_screen_init(); Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL); fl_unlock_function(); } - (void)applicationDidUpdate:(NSNotification *)aNotification { if (im_enabled != -1) { TSMDocumentID newDoc; // It is extremely unclear when Cocoa decides to create/update // the input context, but debugging reveals that it is done // by NSApplication:updateWindows. So check if the input context // has shifted after each such run so that we can update our // input methods status. newDoc = TSMGetActiveDocument(); if (newDoc != currentDoc) { TSMDocumentID doc; doc = TSMGetActiveDocument(); if (im_enabled) TSMRemoveDocumentProperty(doc, kTSMDocumentEnabledInputSourcesPropertyTag); else { CFArrayRef inputSources; CFDictionaryRef filter; // FLΤΚ previously used TISCreateASCIICapableInputSourceList(), // which mostly hits the mark. But it excludes things like Greek // and Cyrillic keyboards. So let's be more explicit. filter = CFDictionaryCreate(NULL, (const void **)kTISPropertyInputSourceType, (const void **)kTISTypeKeyboardLayout, 1, NULL, NULL); inputSources = TISCreateInputSourceList(filter, false); CFRelease(filter); TSMSetDocumentProperty(doc, kTSMDocumentEnabledInputSourcesPropertyTag, sizeof(CFArrayRef), &inputSources); CFRelease(inputSources); } currentDoc = newDoc; } } } - (void)applicationWillResignActive:(NSNotification *)notify { fl_lock_function(); Fl_X *x; FLWindow *top = 0; // sort in all regular windows for (x = Fl_X::first;x;x = x->next) { FLWindow *cw = (FLWindow*)x->xid; Fl_Window *win = x->w; if (win && cw) { if (win->modal()) { } else if (win->non_modal()) { } else { if (!top) top = cw; } } } // now sort in all modals for (x = Fl_X::first;x;x = x->next) { FLWindow *cw = (FLWindow*)x->xid; Fl_Window *win = x->w; if (win && cw && [cw isVisible]) { if (win->modal()) { [cw setLevel:NSNormalWindowLevel]; if (top) [cw orderWindow:NSWindowAbove relativeTo:[top windowNumber]]; } } } // finally all non-modals for (x = Fl_X::first;x;x = x->next) { FLWindow *cw = (FLWindow*)x->xid; Fl_Window *win = x->w; if (win && cw && [cw isVisible]) { if (win->non_modal()) { [cw setLevel:NSNormalWindowLevel]; if (top) [cw orderWindow:NSWindowAbove relativeTo:[top windowNumber]]; } } } fl_unlock_function(); } - (void)applicationWillHide:(NSNotification *)notify { fl_lock_function(); Fl_X *x; for (x = Fl_X::first;x;x = x->next) { Fl_Window *window = x->w; if ( !window->parent() ) Fl::handle( FL_HIDE, window); } fl_unlock_function(); } - (void)applicationWillUnhide:(NSNotification *)notify { fl_lock_function(); for (Fl_X *x = Fl_X::first;x;x = x->next) { Fl_Window *w = x->w; if ( !w->parent() && ![(FLWindow*)x->xid isMiniaturized]) { Fl::handle(FL_SHOW, w); } } fl_unlock_function(); } - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { if (fl_mac_os_version < 101300) { // without the next two statements, the opening of the 1st window is delayed by several seconds // under 10.8 ≤ Mac OS < 10.13 when a file is dragged on the application icon Fl_Window *firstw = Fl::first_window(); if (firstw) firstw->wait_for_expose(); } else if (in_nsapp_run) { // memorize all dropped filenames if (!dropped_files_list) dropped_files_list = [[NSMutableArray alloc] initWithCapacity:1]; [dropped_files_list addObject:filename]; return YES; } if (open_cb) { fl_lock_function(); (*open_cb)([filename UTF8String]); Fl::flush(); // useful for AppleScript that does not break the event loop fl_unlock_function(); return YES; } return NO; } @end @interface FLAppDelegateBefore10_5 : FLAppDelegate - (void)applicationDidUnhide:(NSNotification *)notify; - (void)applicationDidUpdate:(NSNotification *)aNotification; @end @implementation FLAppDelegateBefore10_5 - (void)applicationDidUnhide:(NSNotification *)notify { // before 10.5, subwindows are lost when application is unhidden fl_lock_function(); for (Fl_X *x = Fl_X::first; x; x = x->next) { if (![(FLWindow*)x->xid parentWindow]) { orderfront_subwindows((FLWindow*)x->xid); } } fl_unlock_function(); } - (void)applicationDidUpdate:(NSNotification *)aNotification { } @end static void drain_dropped_files_list() { open_cb_f_type open_cb = ((FLAppDelegate*)[NSApp delegate])->open_cb; if (!open_cb) { [dropped_files_list removeAllObjects]; [dropped_files_list release]; dropped_files_list = nil; return; } NSString *s = (NSString*)[dropped_files_list objectAtIndex:0]; char *fname = fl_strdup([s UTF8String]); [dropped_files_list removeObjectAtIndex:0]; if ([dropped_files_list count] == 0) { [dropped_files_list release]; dropped_files_list = nil; } open_cb(fname); free(fname); } /* * Install an open documents event handler... */ void Fl_Darwin_System_Driver::open_callback(void (*cb)(const char *)) { fl_open_display(); ((FLAppDelegate*)[NSApp delegate])->open_cb = cb; } @implementation FLApplication + (void)sendEvent:(NSEvent *)theEvent { if (fl_send_system_handlers(theEvent)) return; NSEventType type = [theEvent type]; if (type == NSEventTypeLeftMouseDown) { fl_lock_function(); Fl_Window *grab = Fl::grab(); if (grab) { FLWindow *win = (FLWindow *)[theEvent window]; if ( [win isKindOfClass:[FLWindow class]] && grab != [win getFl_Window]) { // a click event out of a menu window, so we should close this menu // done here to catch also clicks on window title bar/resize box cocoaMouseHandler(theEvent); } } fl_unlock_function(); } else if (type == NSEventTypeApplicationDefined) { if ([theEvent subtype] == FLTKDataReadyEvent) { processFLTKEvent(); } return; } else if (type == NSEventTypeKeyUp) { // The default sendEvent turns key downs into performKeyEquivalent when // modifiers are down, but swallows the key up if the modifiers include // command. This one makes all modifiers consistent by always sending key ups. // FLView treats performKeyEquivalent to keyDown, but performKeyEquivalent is // still needed for the system menu. [[NSApp keyWindow] sendEvent:theEvent]; return; } [NSApp sendEvent:theEvent]; } @end /* Prototype of undocumented function needed to support Mac OS 10.2 or earlier extern "C" { OSErr CPSEnableForegroundOperation(ProcessSerialNumber*, UInt32, UInt32, UInt32, UInt32); } */ static BOOL is_bundled() { static int value = 2; if (value == 2) { value = 1; NSBundle *bundle = [NSBundle mainBundle]; if (bundle) { NSString *exe = [[bundle executablePath] stringByStandardizingPath]; NSString *bpath = [[bundle bundlePath] stringByStandardizingPath]; NSString *exe_dir = [exe stringByDeletingLastPathComponent]; //NSLog(@"exe=%@ bpath=%@ exe_dir=%@",exe, bpath, exe_dir); if ([bpath isEqualToString:exe] || [bpath isEqualToString:exe_dir]) value = 0; } else value = 0; } return value == 1; } static void foreground_and_activate() { if ( !is_bundled() ) { // only transform the application type for unbundled apps ProcessSerialNumber cur_psn = { 0, kCurrentProcess }; TransformProcessType(&cur_psn, kProcessTransformToForegroundApplication); // needs Mac OS 10.3 /* support of Mac OS 10.2 or earlier used this undocumented call instead err = CPSEnableForegroundOperation(&cur_psn, 0x03, 0x3C, 0x2C, 0x1103); */ } [NSApp activateIgnoringOtherApps:YES]; } // simpler way to activate application tested OK on MacOS 10.3 10.6 10.9 10.13 and 10.14 public beta void Fl_Cocoa_Screen_Driver::open_display_platform() { static char beenHereDoneThat = 0; if ( !beenHereDoneThat ) { beenHereDoneThat = 1; BOOL need_new_nsapp = (NSApp == nil); if (need_new_nsapp) [NSApplication sharedApplication]; NSAutoreleasePool *localPool; localPool = [[NSAutoreleasePool alloc] init]; // never released FLAppDelegate *delegate = (Fl_Darwin_System_Driver::calc_mac_os_version() < 100500 ? [FLAppDelegateBefore10_5 alloc] : [FLAppDelegate alloc]); [(NSApplication*)NSApp setDelegate:[delegate init]]; if (need_new_nsapp) { if (fl_mac_os_version >= 101300 && fl_mac_os_version < 140000 && is_bundled()) { [NSApp activateIgnoringOtherApps:YES]; in_nsapp_run = true; [NSApp run]; in_nsapp_run = false; } else { [NSApp finishLaunching]; // Unbundled app may require this so delegate receives applicationDidFinishLaunching: // even if doc states this is sent at the end of finishLaunching. if (!is_bundled()) [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:nil inMode:NSDefaultRunLoopMode dequeue:NO]; } } if (fl_mac_os_version < 140000) { // empty the event queue but keep system events for drag&drop of files at launch NSEvent *ign_event; do ign_event = [NSApp nextEventMatchingMask:(NSEventMaskAny & ~NSEventMaskSystemDefined) untilDate:[NSDate dateWithTimeIntervalSinceNow:0] inMode:NSDefaultRunLoopMode dequeue:YES]; while (ign_event); } if (![NSApp isActive]) foreground_and_activate(); if (![NSApp servicesMenu]) createAppleMenu(); else Fl_Sys_Menu_Bar::window_menu_style(Fl_Sys_Menu_Bar::no_window_menu); main_screen_height = CGDisplayBounds(CGMainDisplayID()).size.height; [[NSNotificationCenter defaultCenter] addObserver:[FLWindowDelegate singleInstance] selector:@selector(anyWindowWillClose:) name:NSWindowWillCloseNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:[FLWindowDelegate singleInstance] selector:@selector(view_did_resize:) name:NSViewFrameDidChangeNotification object:nil]; if (![NSThread isMultiThreaded]) { // With old OS X versions, it is necessary to create one thread for secondary pthreads to be // allowed to use cocoa, especially to create an NSAutoreleasePool. // We create a thread that does nothing so it completes very fast: [NSThread detachNewThreadSelector:@selector(doNothing:) toTarget:[FLWindowDelegate singleInstance] withObject:nil]; } (void)localPool; // silence warning } } // Force a "Roman" or "ASCII" keyboard, which both the Mozilla and // Safari people seem to think implies turning off advanced IME stuff // (see nsTSMManager::SyncKeyScript in Mozilla and enableSecureTextInput // in Safari/Webcore). Should be good enough for us then... static int input_method_startup() { static int retval = -1; // -1: not initialized, 0: not usable, 1: ready for use if (retval == -1) { fl_open_display(); if (fl_mac_os_version >= 100500) { // These symbols are no longer visible in Apple doc. // They do exist in Carbon.framework --> HIToolbox.framework --> TextServices.h TSMGetActiveDocument = (TSMGetActiveDocument_type)Fl_Darwin_System_Driver::get_carbon_function("TSMGetActiveDocument"); TSMSetDocumentProperty = (TSMSetDocumentProperty_type)Fl_Darwin_System_Driver::get_carbon_function("TSMSetDocumentProperty"); TSMRemoveDocumentProperty = (TSMRemoveDocumentProperty_type)Fl_Darwin_System_Driver::get_carbon_function("TSMRemoveDocumentProperty"); // These symbols are no longer visible in Apple doc. // They do exist in Carbon.framework --> HIToolbox.framework --> TextInputSources.h TISCreateInputSourceList = (TISCreateInputSourceList_type)Fl_Darwin_System_Driver::get_carbon_function("TISCreateInputSourceList"); kTISTypeKeyboardLayout = (CFStringRef)Fl_Darwin_System_Driver::get_carbon_function("kTISTypeKeyboardLayout"); kTISPropertyInputSourceType = (CFStringRef)Fl_Darwin_System_Driver::get_carbon_function("kTISPropertyInputSourceType"); retval = (TSMGetActiveDocument && TSMSetDocumentProperty && TSMRemoveDocumentProperty && TISCreateInputSourceList && kTISTypeKeyboardLayout && kTISPropertyInputSourceType ? 1 : 0); } else { KeyScript = (KeyScript_type)Fl_Darwin_System_Driver::get_carbon_function("KeyScript"); retval = (KeyScript? 1 : 0); } } return retval; } void Fl_Cocoa_Screen_Driver::enable_im() { if (!input_method_startup()) return; im_enabled = 1; if (fl_mac_os_version >= 100500) { ((FLAppDelegate*)[NSApp delegate])->currentDoc = NULL; [NSApp updateWindows]; // triggers [FLAppDelegate applicationDidUpdate] } else KeyScript(-7/*smKeyEnableKybds*/); } void Fl_Cocoa_Screen_Driver::disable_im() { if (!input_method_startup()) return; im_enabled = 0; if (fl_mac_os_version >= 100500) { ((FLAppDelegate*)[NSApp delegate])->currentDoc = NULL; [NSApp updateWindows]; // triggers [FLAppDelegate applicationDidUpdate] } else KeyScript(smEnableRomanKybdsOnly); } // Gets the border sizes and the titlebar height static int get_window_frame_sizes(Fl_Window *win, int *pbx, int *pby) { if (pbx) *pbx = 0; if (pby) *pby = 0; if (win && !win->border()) return 0; FLWindow *flw = fl_xid(win); if (flw) { return [flw frame].size.height - [[flw contentView] frame].size.height; } static int top = 0, left, bottom; if (!top) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSRect inside = { {20,20}, {100,100} }; NSRect outside = [NSWindow frameRectForContentRect:inside styleMask:NSWindowStyleMaskTitled]; left = int(outside.origin.x - inside.origin.x); bottom = int(outside.origin.y - inside.origin.y); top = int(outside.size.height - inside.size.height) - bottom; [pool release]; } if (pbx) *pbx = left; if (pby) *pby = bottom; return top; } void Fl_Cocoa_Window_Driver::decoration_sizes(int *top, int *left, int *right, int *bottom) { *top = get_window_frame_sizes(pWindow, left, bottom); *right = *left; } /* * smallest x coordinate in screen space of work area of menubar-containing display */ int Fl_Cocoa_Screen_Driver::x() { open_display(); return int([[[NSScreen screens] objectAtIndex:0] visibleFrame].origin.x) / scale(0); } /* * smallest y coordinate in screen space of work area of menubar-containing display */ int Fl_Cocoa_Screen_Driver::y() { open_display(); NSRect visible = [[[NSScreen screens] objectAtIndex:0] visibleFrame]; return int(main_screen_height - (visible.origin.y + visible.size.height)) / scale(0); } /* * width of work area of menubar-containing display */ int Fl_Cocoa_Screen_Driver::w() { open_display(); return int([[[NSScreen screens] objectAtIndex:0] visibleFrame].size.width) / scale(0); } /* * height of work area of menubar-containing display */ int Fl_Cocoa_Screen_Driver::h() { open_display(); return int([[[NSScreen screens] objectAtIndex:0] visibleFrame].size.height) / scale(0); } // computes the work area of the nth screen (screen #0 has the menubar) void Fl_Cocoa_Screen_Driver::screen_work_area(int &X, int &Y, int &W, int &H, int n) { if (num_screens < 0) init(); if (n < 0 || n >= num_screens) n = 0; open_display(); NSRect r = [[[NSScreen screens] objectAtIndex:n] visibleFrame]; X = int(r.origin.x) / scale(0); Y = (main_screen_height - int(r.origin.y + r.size.height)) / scale(0); W = int(r.size.width) / scale(0); H = int(r.size.height) / scale(0); } /* * get the current mouse pointer world coordinates */ int Fl_Cocoa_Screen_Driver::get_mouse(int &x, int &y) { open_display(); NSPoint pt = [NSEvent mouseLocation]; x = int(pt.x); y = int(main_screen_height - pt.y); return screen_num(x/scale(0), y/scale(0)); } static int fake_X_wm(Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) { int W, H, xoff, yoff, dx, dy; int ret = bx = by = bt = 0; if (w->border() && !w->parent()) { int minw, minh, maxw, maxh; w->get_size_range(&minw, &minh, &maxw, &maxh, NULL, NULL, NULL); if (maxw != minw || maxh != minh) { ret = 2; } else { ret = 1; } bt = get_window_frame_sizes(w, &bx, &by); } if (w->parent()) return 0; // The coordinates of the whole window, including non-client area xoff = bx; yoff = by + bt; dx = 2*bx; dy = 2*by + bt; float s = Fl::screen_driver()->scale(0); X = round(w->x()*s)-xoff; Y = round(w->y()*s)-yoff; W = w->w()*s+dx; H = w->h()*s+dy; // Proceed to positioning the window fully inside the screen, if possible // let's get a little elaborate here. Mac OS X puts a lot of stuff on the desk // that we want to avoid when positioning our window, namely the Dock and the // top menu bar (and even more stuff in 10.4 Tiger). So we will go through the // list of all available screens and find the one that this window is most // likely to go to, and then reposition it to fit withing the 'good' area. // Rect r; // find the screen, that the center of this window will fall into int R = X+W, B = Y+H; // right and bottom int cx = (X+R)/2, cy = (Y+B)/2; // center of window; NSScreen *gd = NULL; NSArray *a = [NSScreen screens]; int count = (int)[a count]; NSRect r; int i; for( i = 0; i < count; i++) { r = [[a objectAtIndex:i] frame]; r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( cx >= r.origin.x && cx <= r.origin.x + r.size.width && cy >= r.origin.y && cy <= r.origin.y + r.size.height) break; } if (i < count) gd = [a objectAtIndex:i]; // if the center doesn't fall on a screen, try the top left if (!gd) { for( i = 0; i < count; i++) { r = [[a objectAtIndex:i] frame]; r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( X >= r.origin.x && X <= r.origin.x + r.size.width && Y >= r.origin.y && Y <= r.origin.y + r.size.height) break; } if (i < count) gd = [a objectAtIndex:i]; } // if that doesn't fall on a screen, try the top right if (!gd) { for( i = 0; i < count; i++) { r = [[a objectAtIndex:i] frame]; r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( R >= r.origin.x && R <= r.origin.x + r.size.width && Y >= r.origin.y && Y <= r.origin.y + r.size.height) break; } if (i < count) gd = [a objectAtIndex:i]; } // if that doesn't fall on a screen, try the bottom left if (!gd) { for( i = 0; i < count; i++) { r = [[a objectAtIndex:i] frame]; r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( X >= r.origin.x && X <= r.origin.x + r.size.width && Y+H >= r.origin.y && Y+H <= r.origin.y + r.size.height) break; } if (i < count) gd = [a objectAtIndex:i]; } // last resort, try the bottom right if (!gd) { for( i = 0; i < count; i++) { r = [[a objectAtIndex:i] frame]; r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( R >= r.origin.x && R <= r.origin.x + r.size.width && Y+H >= r.origin.y && Y+H <= r.origin.y + r.size.height) break; } if (i < count) gd = [a objectAtIndex:i]; } // if we still have not found a screen, we will use the main // screen, the one that has the application menu bar. if (!gd) gd = [a objectAtIndex:0]; if (gd) { r = [gd visibleFrame]; r.origin.y = main_screen_height - (r.origin.y + r.size.height); // use FLTK's multiscreen coordinates if ( R > r.origin.x + r.size.width ) X -= int(R - (r.origin.x + r.size.width)); if ( B > r.size.height + r.origin.y ) Y -= int(B - (r.size.height + r.origin.y)); if ( X < r.origin.x ) X = int(r.origin.x); if ( Y < r.origin.y ) Y = int(r.origin.y); } // Return the client area's top left corner in (X,Y) X+=xoff; Y+=yoff; X /= s; Y /= s; return ret; } Fl_Window *fl_dnd_target_window = 0; static void q_set_window_title(NSWindow *nsw, const char * name, const char *mininame) { CFStringRef title = CFStringCreateWithCString(NULL, (name ? name : ""), kCFStringEncodingUTF8); if(!title) { // fallback when name contains malformed UTF-8 int l = (int)strlen(name); unsigned short* utf16 = new unsigned short[l + 1]; l = fl_utf8toUtf16(name, l, utf16, l + 1); title = CFStringCreateWithCharacters(NULL, utf16, l); delete[] utf16; } [nsw setTitle:(NSString*)title]; CFRelease(title); if (mininame && strlen(mininame)) { CFStringRef minititle = CFStringCreateWithCString(NULL, mininame, kCFStringEncodingUTF8); if (minititle) { [nsw setMiniwindowTitle:(NSString*)minititle]; CFRelease(minititle); } } } /** How FLTK handles Mac OS text input Let myview be the instance of the FLView class that has the keyboard focus. FLView is an FLTK-defined NSView subclass that implements the NSTextInputClient protocol to properly handle text input. It also implements the old NSTextInput protocol to run with OS <= 10.4. The few NSTextInput protocol methods that differ in signature from the NSTextInputClient protocol transmit the received message to the corresponding NSTextInputClient method. Keyboard input sends keyDown: and performKeyEquivalent: messages to myview. The latter occurs for keys such as ForwardDelete, arrows and F1, and when the Ctrl or Cmd modifiers are used. Other key presses send keyDown: messages. The keyDown: method calls [myview process_keydown:theEvent] that is equivalent to [[myview inputContext] handleEvent:theEvent], and triggers system processing of keyboard events. The performKeyEquivalent: method directly calls Fl::handle(FL_KEYBOARD, focus-window) when the Ctrl or Cmd modifiers are used. If not, it also calls [[myview inputContext] handleEvent:theEvent]. The performKeyEquivalent: method returns YES when the keystroke has been handled and NO otherwise, which allows shortcuts of the system menu to be processed. Three sorts of messages are then sent back by the system to myview: doCommandBySelector:, setMarkedText: and insertText:. All 3 messages eventually produce Fl::handle(FL_KEYBOARD, win) calls. The doCommandBySelector: message allows to process events such as new-line, forward and backward delete, arrows, escape, tab, F1. The message setMarkedText: is sent when marked text, that is, temporary text that gets replaced later by some other text, is inserted. This happens when a dead key is pressed, and also when entering complex scripts (e.g., Chinese). Fl_Cocoa_Screen_Driver::next_marked_length gives the byte length of marked text before the FL_KEYBOARD event is processed. Fl::compose_state gives this length after this processing. Message insertText: is sent to enter text in the focused widget. If there's marked text, Fl::compose_state is > 0, and this marked text gets replaced by the inserted text. If there's no marked text, the new text is inserted at the insertion point. When the character palette is used to enter text, the system sends an insertText: message to myview. The in_key_event field of the FLView class allows to differentiate keyboard from palette inputs. During processing of the handleEvent message, inserted and marked strings are concatenated in a single string inserted in a single FL_KEYBOARD event after return from handleEvent. The need_handle member variable of FLView allows to determine when setMarkedText or insertText strings have been sent during handleEvent processing and must trigger an FL_KEYBOARD event. Concatenating two insertText operations or an insertText followed by a setMarkedText is possible. In contrast, setMarkedText followed by insertText or by another setMarkedText isn't correct if concatenated in a single string. Thus, in such case, the setMarkedText and the next operation produce each an FL_KEYBOARD event. OS >= 10.7 contains a feature where pressing and holding certain keys opens a menu window that shows a list of possible accented variants of this key. The selectedRange field of the FLView class and the selectedRange, insertText: and setMarkedText: methods of the NSTextInputClient protocol are used to support this feature. The notion of selected text (!= marked text) is monitored by the selectedRange field. The -(NSRange)[FLView selectedRange] method is used to control whether an FLTK widget opens accented character windows by returning .location = NSNotFound to disable that, or returning the value of the selectedRange field to enable the feature. When selectedRange.location >= 0, the value of selectedRange.length is meaningful. 0 means no text is currently selected, > 0 means this number of characters before the insertion point are selected. The insertText: method does selectedRange = NSMakeRange(100, 0); to indicate no text is selected. The setMarkedText: method does selectedRange = NSMakeRange(100, newSelection.length); to indicate that this length of text is selected. With OS <= 10.5, the NSView class does not implement the inputContext message. [myview process_keydown:theEvent] is equivalent to [[FLTextInputContext singleInstance] handleEvent:theEvent]. Method +[FLTextInputContext singleInstance] returns an instance of class FLTextInputContext that possesses a handleEvent: method. The class FLTextView implements the so-called view's "field editor". This editor is an instance of the FLTextView class allocated by the -(id)[FLWindowDelegate windowWillReturnFieldEditor: toObject:] method. The -(BOOL)[FLTextInputContext handleEvent:] method emulates the missing 10.6 -(BOOL)[NSTextInputContext handleEvent:] by sending the interpretKeyEvents: message to the FLTextView object. The system sends back doCommandBySelector: and insertText: messages to the FLTextView object that are transmitted unchanged to myview to be processed as with OS >= 10.6. The system also sends setMarkedText: messages directly to myview. There is furthermore an oddity of dead key processing with OS <= 10.5. It occurs when a dead key followed by a non-accented key are pressed. Say, for example, that keys '^' followed by 'p' are pressed on a French or German keyboard. Resulting messages are: [myview setMarkedText:@"^"], [myview insertText:@"^"], [myview insertText:@"p"], [FLTextView insertText:@"^p"]. The 2nd '^' replaces the marked 1st one, followed by p^p. The resulting text in the widget is "^p^p" instead of the desired "^p". To avoid that, the FLTextView object is deactivated by the insertText: message and reactivated after the handleEvent: message has been processed. NSEvent's during a character composition sequence: - keyDown with deadkey -> [[theEvent characters] length] is 0 - keyUp -> [theEvent characters] contains the deadkey - keyDown with next key -> [theEvent characters] contains the composed character - keyUp -> [theEvent characters] contains the standard character */ static void cocoaKeyboardHandler(NSEvent *theEvent) { NSUInteger mods; // get the modifiers mods = [theEvent modifierFlags]; // get the key code UInt32 keyCode = 0, maskedKeyCode = 0; unsigned short sym = 0; keyCode = [theEvent keyCode]; // extended keyboards can also send sequences on key-up to generate Kanji etc. codes. // Some observed prefixes are 0x81 to 0x83, followed by an 8 bit keycode. // In this mode, there seem to be no key-down codes // printf("%08x %08x %08x\n", keyCode, mods, key); maskedKeyCode = keyCode & 0x7f; mods_to_e_state( mods ); // process modifier keys if (!macKeyLookUp) macKeyLookUp = Fl_Darwin_System_Driver::compute_macKeyLookUp(); sym = macKeyLookUp[maskedKeyCode]; if (sym < 0xff00) { // a "simple" key // find the result of this key without modifier NSString *sim = [theEvent charactersIgnoringModifiers]; UniChar one; CFStringGetCharacters((CFStringRef)sim, CFRangeMake(0, 1), &one); // charactersIgnoringModifiers doesn't ignore shift, remove it when it's on if(one >= 'A' && one <= 'Z') one += 32; if (one > 0 && one <= 0x7f && (sym<'0' || sym>'9') ) sym = one; } Fl::e_keysym = Fl::e_original_keysym = sym; /*NSLog(@"cocoaKeyboardHandler: keycode=%08x keysym=%08x mods=%08x symbol=%@ (%@)", keyCode, sym, mods, [theEvent characters], [theEvent charactersIgnoringModifiers]);*/ // If there is text associated with this key, it will be filled in later. Fl::e_length = 0; Fl::e_text = (char*)""; } @interface FLTextInputContext : NSObject // "emulates" NSTextInputContext before OS 10.6 + (void)initialize; + (FLTextInputContext*)singleInstance; -(BOOL)handleEvent:(NSEvent*)theEvent; @end static FLTextInputContext* fltextinputcontext_instance = nil; @implementation FLTextInputContext + (void)initialize { fltextinputcontext_instance = [[FLTextInputContext alloc] init]; } + (FLTextInputContext*)singleInstance { return fltextinputcontext_instance; } -(BOOL)handleEvent:(NSEvent*)theEvent { FLTextView *edit = [FLTextView singleInstance]; [edit setActive:YES]; [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; [edit setActive:YES]; return YES; } @end /* Implementation note for the support of layer-backed views. MacOS 10.14 Mojave changes the way all drawing to displays is performed: all NSView objects become layer-backed, that is, drawing is done by Core Animation to a CALayer object whose content is then displayed by the NSView. The global variable views_use_CA is set to YES when such change applies, that is, for apps running under 10.14 and linked to SDK 10.14. When views_use_CA is NO, views are not supposed to be layer-backed. Most drawing is done by [FLView drawRect:] which the system calls when a window is created or resized and when Fl_Window_Driver::flush() runs which sends the display message to the view. Within drawRect:, [[NSGraphicsContext currentContext] CGContext] gives a graphics context whose product ultimately appears on screen. But the full content of the view must be redrawn each time drawRect: runs, in contrast to pre-10.14 where drawings were added to the previous window content. That is why FLView maintains a bitmap (view->aux_bitmap) to which all drawing is directed. At the end of drawRect:, the content of view->aux_bitmap is copied to the window's graphics context. A problem arises to support drawing done outside Fl_Window_Driver::flush(), that is, after the app calls Fl_Window::make_current() at any time it wants. That situation is identified by the condition (views_use_CA && !through_drawRect). Fl_Window::make_current() thus calls [view setNeedsDisplay:YES] which instructs the system to run drawRect: at the next event loop. Later, when drawRect: runs, the content of aux_bitmap is copied to drawRect's graphics context. OpenGL windows remain processed under 10.14 as before. */ @implementation FLView - (BOOL)did_view_resolution_change { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if (fl_mac_os_version >= 100700) { // determine whether window is mapped to a retina display Fl_Window *window = [(FLWindow*)[self window] getFl_Window]; Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(window); bool previous = d->mapped_to_retina(); NSView *view = (!views_use_CA && window->parent() && !window->as_gl_window()) ? [fl_xid(window->top_window()) contentView] : self; if (view) { NSSize s = [view convertSizeToBacking:NSMakeSize(10, 10)]; // 10.7 d->mapped_to_retina( int(s.width + 0.5) > 10 ); } BOOL retval = (d->wait_for_expose_value == 0 && previous != d->mapped_to_retina()); if (retval) { d->changed_resolution(true); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 if (views_use_CA && !window->as_gl_window() ) { [self reset_aux_bitmap]; window->redraw(); } #endif } return retval; } #endif return NO; } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 - (void)create_aux_bitmap:(CGContextRef)gc retina:(BOOL)r { if (!gc || fl_mac_os_version >= 101600) { // bitmap context-related functions (e.g., CGBitmapContextGetBytesPerRow) can't be used here with macOS 11.0 "Big Sur" static CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB(); int W = [self frame].size.width, H = [self frame].size.height; if (r) { W *= 2; H *= 2; } aux_bitmap = CGBitmapContextCreate(NULL, W, H, 8, 0, cspace, kCGImageAlphaPremultipliedFirst|kCGBitmapByteOrder32Host); } else { aux_bitmap = CGBitmapContextCreate(NULL, CGBitmapContextGetWidth(gc), CGBitmapContextGetHeight(gc), CGBitmapContextGetBitsPerComponent(gc), CGBitmapContextGetBytesPerRow(gc), CGBitmapContextGetColorSpace(gc), CGBitmapContextGetBitmapInfo(gc)); } CGContextClearRect(aux_bitmap, CGRectMake(0, 0, CGBitmapContextGetWidth(aux_bitmap), CGBitmapContextGetHeight(aux_bitmap))); if (r) CGContextScaleCTM(aux_bitmap, 2, 2); } - (void)reset_aux_bitmap { CGContextRelease(aux_bitmap); aux_bitmap = NULL; } #endif - (BOOL)process_keydown:(NSEvent*)theEvent { id o = fl_mac_os_version >= 100600 ? [self performSelector:@selector(inputContext)] : [FLTextInputContext singleInstance]; return [o handleEvent:theEvent]; } - (id)initWithFrame:(NSRect)frameRect { static NSInteger counter = 0; self = [super initWithFrame:frameRect]; if (self) { in_key_event = NO; identifier = ++counter; } return self; } /* Used by all GL or non-GL windows. * Gets called when a window is created, resized, or moved between retina and non-retina displays. * For non-GL windows, also called by Fl_Window_Driver::flush() because of the display message sent to the view. */ - (void)drawRect:(NSRect)rect { FLWindow *cw = (FLWindow*)[self window]; Fl_Window *window = [cw getFl_Window]; if (!window) return; // may happen after closing full-screen window if (!Fl_X::flx(window)) return; // reported to happen with Gmsh (issue #434) fl_lock_function(); Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(window); if (!through_Fl_X_flush #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 && (!views_use_CA || !aux_bitmap) #endif ) { [self did_view_resolution_change]; if (d->wait_for_expose_value) { d->wait_for_expose_value = 0; if (window->as_gl_window() && views_use_CA && fl_mac_os_version < 101401) { // 1st drawing of layer-backed GL window window->size(window->w(), window->h()); // sends message [GLcontext update] } } Fl_X *i = Fl_X::flx(window); if ( i->region ) { Fl_Graphics_Driver::default_driver().XDestroyRegion(i->region); i->region = 0; } window->clear_damage(FL_DAMAGE_ALL); } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 CGContextRef destination = NULL; if (views_use_CA) { destination = [[NSGraphicsContext currentContext] CGContext]; if (!aux_bitmap && !window->as_gl_window()) [self create_aux_bitmap:destination retina:d->mapped_to_retina()]; } #endif through_drawRect = YES; if (window->damage()) d->Fl_Window_Driver::flush(); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 if (destination) { // can be NULL with gl_start/gl_finish if (fl_mac_os_version < 101600 && CGBitmapContextGetBytesPerRow(aux_bitmap) == CGBitmapContextGetBytesPerRow(destination)) { memcpy(CGBitmapContextGetData(destination), CGBitmapContextGetData(aux_bitmap), CGBitmapContextGetHeight(aux_bitmap) * CGBitmapContextGetBytesPerRow(aux_bitmap)); } else { CGImageRef img = CGBitmapContextCreateImage(aux_bitmap); CGContextDrawImage(destination, [self frame], img); CGImageRelease(img); } } #endif Fl_Cocoa_Window_Driver::q_release_context(); if (!through_Fl_X_flush) window->clear_damage(); through_drawRect = NO; fl_unlock_function(); } - (BOOL)acceptsFirstResponder { return [[self window] parentWindow] ? NO : YES; // 10.2 } - (BOOL)performKeyEquivalent:(NSEvent*)theEvent { //NSLog(@"performKeyEquivalent:"); fl_lock_function(); cocoaKeyboardHandler(theEvent); BOOL handled; NSUInteger mods = [theEvent modifierFlags]; Fl_Window *w = [(FLWindow*)[theEvent window] getFl_Window]; if ( (mods & NSEventModifierFlagControl) || (mods & NSEventModifierFlagCommand) ) { NSString *s = [theEvent characters]; if ( (mods & NSEventModifierFlagShift) && (mods & NSEventModifierFlagCommand) ) { s = [s uppercaseString]; // US keyboards return lowercase letter in s if cmd-shift-key is hit } [FLView prepareEtext:s]; Fl::compose_state = 0; handled = Fl::handle(FL_KEYBOARD, w); } else { in_key_event = YES; need_handle = NO; handled = [self process_keydown:theEvent]; if (need_handle) handled = Fl::handle(FL_KEYBOARD, w); in_key_event = NO; } fl_unlock_function(); return handled; } - (BOOL)acceptsFirstMouse:(NSEvent*)theEvent { Fl_Window *w = [(FLWindow*)[theEvent window] getFl_Window]; Fl_Window *first = Fl::first_window(); return (first == w || !first->modal()); } - (void)resetCursorRects { Fl_Window *w = [(FLWindow*)[self window] getFl_Window]; Fl_X *i = (w ? Fl_X::flx(w) : NULL); if (!i) return; // fix for STR #3128 // We have to have at least one cursor rect for invalidateCursorRectsForView // to work, hence the "else" clause. if (Fl_Cocoa_Window_Driver::driver(w)->cursor) [self addCursorRect:[self frame] cursor:Fl_Cocoa_Window_Driver::driver(w)->cursor]; else [self addCursorRect:[self frame] cursor:[NSCursor arrowCursor]]; } - (void)mouseUp:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } - (void)rightMouseUp:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } - (void)otherMouseUp:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } - (void)mouseDown:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } - (void)rightMouseDown:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } - (void)otherMouseDown:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } - (void)mouseMoved:(NSEvent *)theEvent { if (Fl::belowmouse()) cocoaMouseHandler(theEvent); } - (void)mouseEntered:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } - (void)mouseExited:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - (void)updateTrackingAreas { if (fl_mac_os_version >= 100500) { if (![[self window] parentWindow]) { while (true) { NSArray *a = [self trackingAreas]; // 10.5 if ([a count] == 0) break; NSTrackingArea *ta = (NSTrackingArea*)[a objectAtIndex:0]; [self removeTrackingArea:ta]; // 10.5 } NSTrackingArea *tracking = [[[NSTrackingArea alloc] // 10.5 initWithRect:[self frame] options:NSTrackingActiveAlways | NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved owner:self userInfo:nil] autorelease]; if (tracking) { [self addTrackingArea:tracking]; // 10.5 } } [super updateTrackingAreas]; } } #endif - (void)mouseDragged:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } - (void)rightMouseDragged:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } - (void)otherMouseDragged:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } - (void)scrollWheel:(NSEvent *)theEvent { cocoaMouseWheelHandler(theEvent); } - (void)magnifyWithEvent:(NSEvent *)theEvent { cocoaMagnifyHandler(theEvent); } - (void)keyDown:(NSEvent *)theEvent { //NSLog(@"keyDown:%@",[theEvent characters]); fl_lock_function(); Fl_Window *window = [(FLWindow*)[theEvent window] getFl_Window]; Fl::first_window(window); cocoaKeyboardHandler(theEvent); in_key_event = YES; Fl_Widget *f = Fl::focus(); if (f && f->as_gl_window()) { // ignore text input methods for GL windows need_handle = YES; [FLView prepareEtext:[theEvent characters]]; } else { need_handle = NO; [self process_keydown:theEvent]; } if (need_handle) Fl::handle(FL_KEYBOARD, window); in_key_event = NO; fl_unlock_function(); } - (void)keyUp:(NSEvent *)theEvent { //NSLog(@"keyUp:%@",[theEvent characters]); if (![[theEvent window] isKindOfClass:[FLWindow class]]) // issue #1170 return [super keyUp:theEvent]; fl_lock_function(); Fl_Window *window = (Fl_Window*)[(FLWindow*)[theEvent window] getFl_Window]; Fl::first_window(window); cocoaKeyboardHandler(theEvent); NSString *s = [theEvent characters]; if ([s length] >= 1) [FLView prepareEtext:[s substringToIndex:1]]; Fl::handle(FL_KEYUP,window); fl_unlock_function(); } #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10 typedef NSUInteger NSEventModifierFlags; #endif - (void)flagsChanged:(NSEvent *)theEvent { //NSLog(@"flagsChanged: "); fl_lock_function(); static NSEventModifierFlags prevMods = 0; NSEventModifierFlags mods = [theEvent modifierFlags]; Fl_Window *window = (Fl_Window*)[(FLWindow*)[theEvent window] getFl_Window]; NSEventModifierFlags tMods = prevMods ^ mods; int sendEvent = 0; if ( tMods ) { unsigned short keycode = [theEvent keyCode]; if (!macKeyLookUp) macKeyLookUp = Fl_Darwin_System_Driver::compute_macKeyLookUp(); Fl::e_keysym = Fl::e_original_keysym = macKeyLookUp[keycode & 0x7f]; if ( Fl::e_keysym ) sendEvent = ( prevMods)sender { fl_lock_function(); Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; update_e_xy_and_e_xy_root([self window]); fl_dnd_target_window = target; int ret = Fl::handle( FL_DND_ENTER, target ); Fl_Cocoa_Screen_Driver::breakMacEventLoop(); fl_unlock_function(); Fl::flush(); return ret ? NSDragOperationCopy : NSDragOperationNone; } - (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender { fl_lock_function(); Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; update_e_xy_and_e_xy_root([self window]); fl_dnd_target_window = target; int ret = Fl::handle( FL_DND_DRAG, target ); Fl_Cocoa_Screen_Driver::breakMacEventLoop(); fl_unlock_function(); // if the DND started in the same application, Fl::dnd() will not return until // the DND operation is finished. The call below causes the drop indicator // to be drawn correctly (a full event handling would be better...) Fl::flush(); return ret ? NSDragOperationCopy : NSDragOperationNone; } - (BOOL)performDragOperation:(id )sender { static char *DragData = NULL; fl_lock_function(); Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; if ( !Fl::handle( FL_DND_RELEASE, target ) ) { Fl_Cocoa_Screen_Driver::breakMacEventLoop(); fl_unlock_function(); return NO; } NSPasteboard *pboard; // NSDragOperation sourceDragMask; // sourceDragMask = [sender draggingSourceOperationMask]; pboard = [sender draggingPasteboard]; update_e_xy_and_e_xy_root([self window]); if (DragData) { free(DragData); DragData = NULL; } if ([[pboard types] containsObject:fl_filenames_pboard_type]) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 if (fl_mac_os_version >= 101300) { NSArray *a = [pboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:nil]; // 10.6 NSEnumerator *enumerator = [a objectEnumerator]; NSURL *url; while ((url = (NSURL*)[enumerator nextObject]) != nil) { const char *p = [url fileSystemRepresentation]; // 10.9 if (!DragData) { DragData = strdup(p); } else { int l = (int)strlen(DragData) + (int)strlen(p) + 2; char *drag2 = (char*)malloc(l); snprintf(drag2, l, "%s\n%s", DragData, p); free(DragData); DragData = drag2; } } } else #endif { CFArrayRef files = (CFArrayRef)[pboard propertyListForType:fl_filenames_pboard_type]; CFStringRef all = CFStringCreateByCombiningStrings(NULL, files, CFSTR("\n")); int l = (int)CFStringGetMaximumSizeForEncoding(CFStringGetLength(all), kCFStringEncodingUTF8); DragData = (char *)malloc(l + 1); CFStringGetCString(all, DragData, l + 1, kCFStringEncodingUTF8); CFRelease(all); } } else if ([[pboard types] containsObject:UTF8_pasteboard_type]) { NSData *data = [pboard dataForType:UTF8_pasteboard_type]; DragData = (char *)malloc([data length] + 1); [data getBytes:DragData length:[data length]]; DragData[([data length])] = 0; Fl_Screen_Driver::convert_crlf(DragData, strlen(DragData)); } else { Fl_Cocoa_Screen_Driver::breakMacEventLoop(); fl_unlock_function(); return NO; } Fl::e_text = DragData; Fl::e_length = (int)strlen(DragData); int old_event = Fl::e_number; Fl::belowmouse()->handle(Fl::e_number = FL_PASTE); Fl::e_number = old_event; if (DragData) { free(DragData); DragData = NULL; } Fl::e_text = NULL; Fl::e_length = 0; fl_dnd_target_window = NULL; Fl_Cocoa_Screen_Driver::breakMacEventLoop(); fl_unlock_function(); return YES; } - (void)draggingExited:(id < NSDraggingInfo >)sender { fl_lock_function(); if ( fl_dnd_target_window ) { Fl::handle( FL_DND_LEAVE, fl_dnd_target_window ); fl_dnd_target_window = 0; } fl_unlock_function(); } - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { return NSDragOperationGeneric; } + (void)prepareEtext:(NSString*)aString { // fills Fl::e_text with UTF-8 encoded aString using an adequate memory allocation static char *received_utf8 = NULL; static int lreceived = 0; char *p = (char*)[aString UTF8String]; int l = (int)strlen(p); if (l > 0) { if (lreceived == 0) { received_utf8 = (char*)malloc(l + 1); lreceived = l; } else if (l > lreceived) { received_utf8 = (char*)realloc(received_utf8, l + 1); lreceived = l; } strcpy(received_utf8, p); Fl::e_text = received_utf8; } Fl::e_length = l; } + (void)concatEtext:(NSString*)aString { // extends Fl::e_text with aString NSString *newstring = [[NSString stringWithUTF8String:Fl::e_text] stringByAppendingString:aString]; [FLView prepareEtext:newstring]; } - (void)doCommandBySelector:(SEL)aSelector { NSString *s = [[NSApp currentEvent] characters]; //NSLog(@"doCommandBySelector:%s text='%@'",sel_getName(aSelector), s); s = [s substringFromIndex:[s length] - 1]; [FLView prepareEtext:s]; // use the last character of the event; necessary for deadkey + Tab Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; Fl::handle(FL_KEYBOARD, target); } - (void)insertText:(id)aString { [self insertText:aString replacementRange:NSMakeRange(NSNotFound, 0)]; } - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { NSString *received; if ([aString isKindOfClass:[NSAttributedString class]]) { received = [(NSAttributedString*)aString string]; } else { received = (NSString*)aString; } /*NSLog(@"insertText='%@' l=%d Fl::compose_state=%d range=%d,%d", received,strlen([received UTF8String]),Fl::compose_state,replacementRange.location,replacementRange.length);*/ fl_lock_function(); Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 if (fl_mac_os_version >= 101400 && replacementRange.length > 0) { // occurs after a key was pressed and maintained and an auxiliary window appeared // prevents marking dead key from deactivation [[self inputContext] discardMarkedText]; } #endif while (replacementRange.length--) { // delete replacementRange.length characters before insertion point int saved_keysym = Fl::e_keysym; Fl::e_keysym = FL_BackSpace; Fl::handle(FL_KEYBOARD, target); Fl::e_keysym = saved_keysym; } if (in_key_event && Fl_Cocoa_Screen_Driver::next_marked_length && Fl::e_length) { // if setMarkedText + insertText is sent during handleEvent, text cannot be concatenated in single FL_KEYBOARD event Fl::handle(FL_KEYBOARD, target); Fl::e_length = 0; } if (in_key_event && Fl::e_length) [FLView concatEtext:received]; else [FLView prepareEtext:received]; Fl_Cocoa_Screen_Driver::next_marked_length = 0; // We can get called outside of key events (e.g., from the character palette, from CJK text input). BOOL palette = !(in_key_event || Fl::compose_state); if (palette) Fl::e_keysym = 0; // YES if key has text attached BOOL has_text_key = Fl::e_keysym <= '~' || Fl::e_keysym == FL_Iso_Key || (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last && Fl::e_keysym != FL_KP_Enter); // insertText sent during handleEvent of a key without text cannot be processed in a single FL_KEYBOARD event. // Occurs with deadkey followed by non-text key if (!in_key_event || !has_text_key) { Fl::handle(FL_KEYBOARD, target); Fl::e_length = 0; } else need_handle = YES; selectedRange = NSMakeRange(100, 0); // 100 is an arbitrary value // for some reason, with the palette, the window does not redraw until the next mouse move or button push // sending a 'redraw()' or 'awake()' does not solve the issue! if (palette) Fl::flush(); if (fl_mac_os_version < 100600) [[FLTextView singleInstance] setActive:NO]; fl_unlock_function(); } - (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection { [self setMarkedText:aString selectedRange:newSelection replacementRange:NSMakeRange(NSNotFound, 0)]; } - (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection replacementRange:(NSRange)replacementRange { NSString *received; if ([aString isKindOfClass:[NSAttributedString class]]) { received = [(NSAttributedString*)aString string]; } else { received = (NSString*)aString; } fl_lock_function(); /*NSLog(@"setMarkedText:%@ l=%d newSelection=%d,%d Fl::compose_state=%d replacement=%d,%d", received, strlen([received UTF8String]), newSelection.location, newSelection.length, Fl::compose_state, replacementRange.location, replacementRange.length);*/ Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; while (replacementRange.length--) { // delete replacementRange.length characters before insertion point Fl::e_keysym = FL_BackSpace; Fl::compose_state = 0; Fl_Cocoa_Screen_Driver::next_marked_length = 0; Fl::handle(FL_KEYBOARD, target); Fl::e_keysym = 'a'; // pretend a letter key was hit } if (in_key_event && Fl_Cocoa_Screen_Driver::next_marked_length && Fl::e_length) { // if setMarkedText + setMarkedText is sent during handleEvent, text cannot be concatenated in single FL_KEYBOARD event Fl::handle(FL_KEYBOARD, target); Fl::e_length = 0; } if (in_key_event && Fl::e_length) [FLView concatEtext:received]; else [FLView prepareEtext:received]; Fl_Cocoa_Screen_Driver::next_marked_length = (int)strlen([received UTF8String]); if (!in_key_event) Fl::handle( FL_KEYBOARD, target); else need_handle = YES; selectedRange = NSMakeRange(100, newSelection.length); fl_unlock_function(); } - (void)unmarkText { fl_lock_function(); Fl_Cocoa_Screen_Driver::reset_marked_text(); fl_unlock_function(); //NSLog(@"unmarkText"); } - (NSRange)selectedRange { Fl_Widget *w = Fl::focus(); if (w && w->use_accents_menu()) return selectedRange; return NSMakeRange(NSNotFound, 0); } - (NSRange)markedRange { //NSLog(@"markedRange=%d %d", Fl::compose_state > 0?0:NSNotFound, Fl::compose_state); return NSMakeRange(Fl::compose_state > 0?0:NSNotFound, Fl::compose_state); } - (BOOL)hasMarkedText { //NSLog(@"hasMarkedText %s", Fl::compose_state > 0?"YES":"NO"); return (Fl::compose_state > 0); } - (NSAttributedString *)attributedSubstringFromRange:(NSRange)aRange { return [self attributedSubstringForProposedRange:aRange actualRange:NULL]; } - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { //NSLog(@"attributedSubstringFromRange: %d %d",aRange.location,aRange.length); return nil; } - (NSArray *)validAttributesForMarkedText { return nil; } - (NSRect)firstRectForCharacterRange:(NSRange)aRange { return [self firstRectForCharacterRange:aRange actualRange:NULL]; } - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { //NSLog(@"firstRectForCharacterRange %d %d actualRange=%p",aRange.location, aRange.length,actualRange); NSRect glyphRect; fl_lock_function(); Fl_Widget *focus = Fl::focus(); Fl_Window *wfocus = [(FLWindow*)[self window] getFl_Window]; if (!focus) focus = wfocus; glyphRect.size.width = 0; int x, y, height; if (Fl_Cocoa_Screen_Driver::insertion_point_location(&x, &y, &height)) { glyphRect.origin.x = (CGFloat)x; glyphRect.origin.y = (CGFloat)y; } else { if (focus->as_window()) { glyphRect.origin.x = 0; glyphRect.origin.y = focus->h(); } else { glyphRect.origin.x = focus->x(); glyphRect.origin.y = focus->y() + focus->h(); } height = 12; } glyphRect.size.height = height; Fl_Window *win = focus->as_window(); if (!win) win = focus->window(); while (win != NULL && win != wfocus) { glyphRect.origin.x += win->x(); glyphRect.origin.y += win->y(); win = win->window(); } // Convert the rect to screen coordinates float s = Fl_Graphics_Driver::default_driver().scale(); glyphRect.origin.x *= s; glyphRect.origin.y *= s; glyphRect.origin.y = wfocus->h()*s - glyphRect.origin.y; glyphRect.origin = [(FLWindow*)[self window] convertBaseToScreen:glyphRect.origin]; glyphRect.size.height *= s; if (actualRange) *actualRange = aRange; fl_unlock_function(); return glyphRect; } - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint { return 0; } - (NSInteger)windowLevel { return [[self window] level]; } - ( #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 NSInteger #else long #endif )conversationIdentifier { return identifier; } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context { return NSDragOperationCopy; } - (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation { Fl_Widget *w = Fl::pushed(); if ( w ) { int old_event = Fl::e_number; w->handle(Fl::e_number = FL_RELEASE); Fl::e_number = old_event; Fl::pushed( 0 ); } } #endif @end /* * Initialize the given port for redraw and call the window's flush() to actually draw the content */ void Fl_Cocoa_Window_Driver::flush() { if (pWindow->as_gl_window()) { Fl_Window_Driver::flush(); } else { through_Fl_X_flush = YES; NSView *view = [fl_xid(pWindow) contentView]; if (views_use_CA) [view display]; else { [view setNeedsDisplay:YES]; [view displayIfNeededIgnoringOpacity]; } through_Fl_X_flush = NO; } } /* * go ahead, create that (sub)window */ void Fl_Cocoa_Window_Driver::makeWindow() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; Fl_Group::current(0); fl_open_display(); NSInteger winlevel = NSNormalWindowLevel; NSUInteger winstyle; Fl_Sys_Menu_Bar::create_window_menu(); // effective once at most Fl_Window* w = pWindow; if (w->parent()) { w->border(0); show_iconic(0); } if (w->border()) { winstyle = (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable); if (is_resizable()) winstyle |= NSWindowStyleMaskResizable; } else { winstyle = NSWindowStyleMaskBorderless; } if (show_iconic() && !w->parent()) { // prevent window from being out of work area when created iconized int sx, sy, sw, sh; Fl::screen_work_area (sx, sy, sw, sh, w->x(), w->y()); if (w->x() < sx) x(sx); if (w->y() < sy) y(sy); } int xp = w->x(); int yp = w->y(); int xwm = xp, ywm = yp, bt, bx, by; if (!fake_X_wm(w, xwm, ywm, bt, bx, by)) { // menu windows and tooltips if (w->modal()||w->tooltip_window()) { winlevel = modal_window_level(); } } if (w->modal()) { winstyle &= ~NSWindowStyleMaskMiniaturizable; winlevel = modal_window_level(); } else if (w->non_modal()) { winlevel = non_modal_window_level(); } if (force_position()) { if (!Fl::grab()) { xp = xwm; yp = ywm; x(xp);y(yp); } xp -= bx; yp -= by+bt; } Fl_X *x = new Fl_X; other_xid = 0; // room for doublebuffering image map. On OS X this is only used by overlay windows x->region = 0; subRect(0); gc = 0; mapped_to_retina(false); changed_resolution(false); NSRect crect; if (w->fullscreen_active() && fl_mac_os_version < 100700) { int top, bottom, left, right; int sx, sy, sw, sh, X, Y, W, H; top = fullscreen_screen_top(); bottom = fullscreen_screen_bottom(); left = fullscreen_screen_left(); right = fullscreen_screen_right(); if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) { top = Fl::screen_num(w->x(), w->y(), w->w(), w->h()); bottom = top; left = top; right = top; } Fl::screen_xywh(sx, sy, sw, sh, top); Y = sy; Fl::screen_xywh(sx, sy, sw, sh, bottom); H = sy + sh - Y; Fl::screen_xywh(sx, sy, sw, sh, left); X = sx; Fl::screen_xywh(sx, sy, sw, sh, right); W = sx + sw - X; w->resize(X, Y, W, H); winstyle = NSWindowStyleMaskBorderless; winlevel = NSStatusWindowLevel; } float s = Fl::screen_driver()->scale(0); crect.origin.x = round(s * w->x()); // correct origin set later for subwindows crect.origin.y = main_screen_height - round(s * (w->y() + w->h())); crect.size.width = int(s * w->w()); crect.size.height = int(s * w->h()); FLWindow *cw = [[FLWindow alloc] initWithFl_W:w contentRect:crect styleMask:winstyle]; [cw setFrameOrigin:crect.origin]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 if (fl_mac_os_version >= 101200) { if (!w->parent() && (winstyle & NSWindowStyleMaskTitled) && (winstyle & NSWindowStyleMaskResizable) && !w->modal() && !w->non_modal() && (Fl_MacOS_Sys_Menu_Bar_Driver::window_menu_style() > Fl_Sys_Menu_Bar::tabbing_mode_none)) { if (Fl_MacOS_Sys_Menu_Bar_Driver::window_menu_style() == Fl_Sys_Menu_Bar::tabbing_mode_preferred) [cw setTabbingMode:NSWindowTabbingModePreferred]; else [cw setTabbingMode:NSWindowTabbingModeAutomatic]; } else { [cw setTabbingMode:NSWindowTabbingModeDisallowed]; } } #endif if (!w->parent()) { [cw setHasShadow:YES]; [cw setAcceptsMouseMovedEvents:YES]; } if (w->shape()) { [cw setOpaque:NO]; // shaped windows must be non opaque [cw setBackgroundColor:[NSColor clearColor]]; // and with transparent background color } x->xid = (fl_uintptr_t)cw; x->w = w; flx(x); wait_for_expose_value = 1; if (!w->parent()) { x->next = Fl_X::first; Fl_X::first = x; } else if (Fl_X::first) { x->next = Fl_X::first->next; Fl_X::first->next = x; } else { x->next = NULL; Fl_X::first = x; } FLView *myview = [[FLView alloc] initWithFrame:crect]; [cw setContentView:myview]; [myview release]; [cw setLevel:winlevel]; q_set_window_title(cw, w->label(), w->iconlabel()); NSImage *icon = icon_image; // is a window or default icon present? if (!icon) icon = ((Fl_Cocoa_Screen_Driver*)Fl::screen_driver())->default_icon; if (icon && (winstyle & NSWindowStyleMaskTitled) && w->label() && strlen(w->label()) > 0) { [cw setRepresentedFilename:[NSString stringWithFormat:@"/%@", [cw title]]]; NSButton *icon_button = [cw standardWindowButton:NSWindowDocumentIconButton]; if (icon_button) { [icon setSize:[icon_button frame].size]; [icon_button setImage:icon]; } } if (!force_position()) { if (w->modal()) { [cw center]; } else if (w->non_modal()) { [cw center]; } else if (!w->fullscreen_active()) { static NSPoint delta = NSZeroPoint; delta = [cw cascadeTopLeftFromPoint:delta]; } crect = [cw frame]; // synchronize FLTK's and the system's window coordinates this->x(round(crect.origin.x/s)); this->y( round((main_screen_height - crect.origin.y)/s) - w->h() ); } if(w->menu_window()) { // make menu windows slightly transparent [cw setAlphaValue:0.97]; } // Install DnD handlers [myview registerForDraggedTypes:[NSArray arrayWithObjects:UTF8_pasteboard_type, fl_filenames_pboard_type, nil]]; if (pWindow->get_size_range(NULL, NULL, NULL, NULL, NULL, NULL, NULL)) size_range(); if ( w->border() || (!w->modal() && !w->tooltip_window()) ) { Fl_Tooltip::enter(0); } if (w->modal()) Fl::modal_ = w; w->set_visible(); if ( w->border() || (!w->modal() && !w->tooltip_window() && w->user_data() != &Fl_Screen_Driver::transient_scale_display) ) Fl::handle(FL_FOCUS, w); [cw setDelegate:[FLWindowDelegate singleInstance]]; if (show_iconic()) { show_iconic(0); w->handle(FL_SHOW); // create subwindows if any if (fl_mac_os_version < 101300) { // TODO: threshold may be smaller // draw the window and its subwindows before its icon is computed [cw recursivelySendToSubwindows:@selector(display) applyToSelf:YES]; } [cw miniaturize:nil]; } else if (w->parent()) { // a subwindow [cw setIgnoresMouseEvents:YES]; // needs OS X 10.2 // next 2 statements so a subwindow doesn't leak out of its parent window [cw setOpaque:NO]; [cw setBackgroundColor:[NSColor clearColor]]; // transparent background color starting_moved_window = w; [cw setSubwindowFrame]; starting_moved_window = NULL; // needed if top window was first displayed miniaturized FLWindow *pxid = fl_xid(w->top_window()); [pxid makeFirstResponder:[pxid contentView]]; } else { // a top-level window if ([cw canBecomeKeyWindow]) [cw makeKeyAndOrderFront:nil]; else [cw orderFront:nil]; if (w->fullscreen_active() && fl_mac_os_version >= 100700) { if (fullscreen_screen_top() >= 0) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 if (fl_mac_os_version >= 101200) cw.collectionBehavior |= NSWindowCollectionBehaviorFullScreenNone; #endif *no_fullscreen_x() = pWindow->x(); *no_fullscreen_y() = pWindow->y(); } fullscreen_on(); } } if (fl_sys_menu_bar && Fl_MacOS_Sys_Menu_Bar_Driver::window_menu_style() && !w->parent() && w->border() && !w->modal() && !w->non_modal()) { Fl_MacOS_Sys_Menu_Bar_Driver::driver()->new_window(w); } int old_event = Fl::e_number; w->handle(Fl::e_number = FL_SHOW); Fl::e_number = old_event; // if (w->modal()) { Fl::modal_ = w; fl_fix_focus(); } if (!w->parent()) [myview did_view_resolution_change]; // to set mapped_to_retina to its current state [pool release]; } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 static BOOL fullscreen_screen_border = NO; // YES means the multi-screened window had a border before #endif static NSUInteger calc_win_style(Fl_Window *win); void Fl_Cocoa_Window_Driver::fullscreen_on() { pWindow->_set_fullscreen(); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 bool has_border = pWindow->border(); if (fl_mac_os_version >= 100700 && fullscreen_screen_top() >= 0 && has_border) { fullscreen_screen_border = YES; has_border = false; } if (fl_mac_os_version >= 100700 && has_border) { NSWindow *nswin = fl_xid(pWindow); # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 if (fl_mac_os_version >= 101300) { NSWindow *active_tab = [[nswin tabGroup] selectedWindow]; if (active_tab) nswin = active_tab; } # endif if (fullscreen_screen_border) { // from "All Screens" fullscreen to single-screen fullscreen pWindow->_clear_fullscreen(); [nswin setLevel:NSNormalWindowLevel]; [nswin setStyleMask:calc_win_style(pWindow)]; //10.6 pWindow->_set_fullscreen(); } [nswin toggleFullScreen:nil]; } else # endif if (fl_mac_os_version >= 100600) { FLWindow *nswin = fl_xid(pWindow); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if (fl_mac_os_version >= 100700 && (nswin.styleMask & NSWindowStyleMaskFullScreen)) { // from single-screen fullscreen to "All Screens" fullscreen, with border #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 if (fl_mac_os_version >= 101200) { bool allscreens_on = (nswin.collectionBehavior & NSWindowCollectionBehaviorFullScreenNone); if (allscreens_on) nswin.collectionBehavior &= ~NSWindowCollectionBehaviorFullScreenNone; [nswin toggleFullScreen:nil]; if (allscreens_on) nswin.collectionBehavior |= NSWindowCollectionBehaviorFullScreenNone; } else #endif [nswin toggleFullScreen:nil]; if (*no_fullscreen_w() == 0) { *no_fullscreen_x() = x(); *no_fullscreen_y() = y(); *no_fullscreen_w() = w(); *no_fullscreen_h() = h(); } pWindow->_set_fullscreen(); } #endif [nswin setStyleMask:NSWindowStyleMaskBorderless]; // 10.6 if ([nswin isKeyWindow]) { if ([nswin level] != NSStatusWindowLevel) { [nswin setLevel:NSStatusWindowLevel]; fixup_window_levels(); } } else if([nswin level] != NSNormalWindowLevel) { [nswin setLevel:NSNormalWindowLevel]; fixup_window_levels(); } int sx, sy, sw, sh, X, Y, W, H; int top = fullscreen_screen_top(); int bottom = fullscreen_screen_bottom(); int left = fullscreen_screen_left(); int right = fullscreen_screen_right(); if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) { top = Fl::screen_num(x(), y(), w(), h()); bottom = top; left = top; right = top; } Fl::screen_xywh(sx, sy, sw, sh, top); Y = sy; Fl::screen_xywh(sx, sy, sw, sh, bottom); H = sy + sh - Y; Fl::screen_xywh(sx, sy, sw, sh, left); X = sx; Fl::screen_xywh(sx, sy, sw, sh, right); W = sx + sw - X; pWindow->resize(X, Y, W, H); } else #endif { // On OS X < 10.6, it is necessary to recreate the window. This is done with hide+show. pWindow->hide(); pWindow->show(); } Fl::handle(FL_FULLSCREEN, pWindow); } void Fl_Cocoa_Window_Driver::maximize() { if (border()) [fl_xid(pWindow) performZoom:nil]; else Fl_Window_Driver::maximize(); } void Fl_Cocoa_Window_Driver::un_maximize() { if (border()) [fl_xid(pWindow) performZoom:nil]; else Fl_Window_Driver::un_maximize(); } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 static NSUInteger calc_win_style(Fl_Window *win) { NSUInteger winstyle; if (win->border() && !win->fullscreen_active()) { winstyle = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable; if (Fl_Window_Driver::driver(win)->is_resizable()) winstyle |= NSWindowStyleMaskResizable; if (!win->modal()) winstyle |= NSWindowStyleMaskMiniaturizable; } else winstyle = NSWindowStyleMaskBorderless; return winstyle; } static void restore_window_title_and_icon(Fl_Window *pWindow, NSImage *icon) { FLWindow *nswin = fl_xid(pWindow); q_set_window_title(nswin, pWindow->label(), pWindow->iconlabel()); if (!icon) icon = ((Fl_Cocoa_Screen_Driver*)Fl::screen_driver())->default_icon; if (icon && ([nswin styleMask] & NSWindowStyleMaskTitled) && pWindow->label() && (strlen(pWindow->label()) > 0)) { NSButton *icon_button = [nswin standardWindowButton:NSWindowDocumentIconButton]; if (icon_button) { [icon setSize:[icon_button frame].size]; [icon_button setImage:icon]; } } } #endif void Fl_Cocoa_Window_Driver::fullscreen_off(int X, int Y, int W, int H) { NSWindow *nswin = fl_xid(pWindow); pWindow->_clear_fullscreen(); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if (fl_mac_os_version >= 100700 && ([nswin styleMask] & NSWindowStyleMaskFullScreen)) { # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 if (fl_mac_os_version >= 101300) { NSWindow *active_tab = [[nswin tabGroup] selectedWindow]; if (active_tab) nswin = active_tab; } # endif [nswin toggleFullScreen:nil]; pWindow->resize(*no_fullscreen_x(), *no_fullscreen_y(), *no_fullscreen_w(), *no_fullscreen_h()); } else # endif if (fl_mac_os_version >= 100600) { // Transition from multi-screen fullscreen mode to normal mode NSInteger level = NSNormalWindowLevel; if (pWindow->modal()) level = modal_window_level(); else if (pWindow->non_modal()) level = non_modal_window_level(); /* Hide (orderOut) and later show (orderFront) the window to avoid a crash that occurs in a very specific situation: the dock is at bottom and H is larger than the maximum value for the display. See "Crashing regression in MacOS code" in fltk.coredev. */ BOOL has_focus = [nswin isKeyWindow]; [nswin orderOut:nil]; [nswin setLevel:level]; [nswin setStyleMask:calc_win_style(pWindow)]; //10.6 restore_window_title_and_icon(pWindow, icon_image); pWindow->resize(X, Y, W, H); if (pWindow->maximize_active()) Fl_Window_Driver::maximize(); if (has_focus) [nswin makeKeyAndOrderFront:nil]; else [nswin orderFront:nil]; } else #endif { pWindow->hide(); pWindow->resize(X, Y, W, H); pWindow->show(); } Fl::handle(FL_FULLSCREEN, pWindow); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 fullscreen_screen_border = NO; #endif } void Fl_Cocoa_Window_Driver::fullscreen_screens(bool on_off) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 if (fl_mac_os_version >= 101200) { FLWindow *xid = fl_mac_xid(pWindow); if (on_off) xid.collectionBehavior |= NSWindowCollectionBehaviorFullScreenNone; else xid.collectionBehavior &= ~NSWindowCollectionBehaviorFullScreenNone; } #endif } void Fl_Cocoa_Window_Driver::use_border() { if (!shown() || pWindow->parent()) return; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 if (fl_mac_os_version >= 100600) { if (pWindow->fullscreen_active() || pWindow->maximize_active()) { // prevent changing border while window is fullscreen or maximized static bool active = false; if (!active) { active = true; bool b = !border(); pWindow->border(b); active = false; } return; } [fl_xid(pWindow) setStyleMask:calc_win_style(pWindow)]; // 10.6 if (border()) restore_window_title_and_icon(pWindow, icon_image); pWindow->redraw(); } else #endif Fl_Window_Driver::use_border(); } /* * Tell the OS what window sizes we want to allow */ void Fl_Cocoa_Window_Driver::size_range() { Fl_X *i = Fl_X::flx(pWindow); if (i && i->xid) { float s = Fl::screen_driver()->scale(0); int bt = get_window_frame_sizes(pWindow); int minw, minh, maxw, maxh; pWindow->get_size_range(&minw, &minh, &maxw, &maxh, NULL, NULL, NULL); NSSize minSize = NSMakeSize(int(minw * s +.5) , int(minh * s +.5) + bt); NSSize maxSize = NSMakeSize(maxw ? int(maxw * s + .5):32000, maxh ? int(maxh * s +.5) + bt:32000); [(FLWindow*)i->xid setMinSize:minSize]; [(FLWindow*)i->xid setMaxSize:maxSize]; } } void Fl_Cocoa_Window_Driver::wait_for_expose() { if (fl_mac_os_version < 101300) { [fl_xid(pWindow) recursivelySendToSubwindows:@selector(waitForExpose) applyToSelf:YES]; } else { Fl_Window_Driver::wait_for_expose(); } } /* * set the window title bar name */ void Fl_Cocoa_Window_Driver::label(const char *name, const char *mininame) { if (shown() || Fl_X::flx(pWindow)) { q_set_window_title(fl_xid(pWindow), name, mininame); if (fl_sys_menu_bar && Fl_Sys_Menu_Bar_Driver::window_menu_style()) Fl_MacOS_Sys_Menu_Bar_Driver::driver()->rename_window(pWindow); } } /* * make a window visible */ void Fl_Cocoa_Window_Driver::show() { Fl_X *top = NULL; if (parent()) top = Fl_X::flx(pWindow->top_window()); if (!shown() && (!parent() || (top && ![(FLWindow*)top->xid isMiniaturized]))) { makeWindow(); } else { if ( !parent() ) { Fl_X *i = Fl_X::flx(pWindow); if ([(FLWindow*)i->xid isMiniaturized]) { i->w->redraw(); [(FLWindow*)i->xid deminiaturize:nil]; } if (!fl_capture) { [(FLWindow*)i->xid makeKeyAndOrderFront:nil]; } } else pWindow->set_visible(); } } /* * resize a window */ void Fl_Cocoa_Window_Driver::resize(int X, int Y, int W, int H) { if (!pWindow->shown() && (X != x() || Y != y())) force_position(1); if (view_resized() || !visible_r()) { pWindow->Fl_Group::resize(X, Y, W, H); if (!pWindow->shown()) pWindow->init_sizes(); } else if (!through_resize()) { NSPoint pt = FLTKtoCocoa(pWindow, X, Y, H); FLWindow *xid = fl_xid(pWindow); through_resize(1); if (W != w() || H != h() || Fl_Window::is_a_rescale()) { NSRect r; float s = Fl::screen_driver()->scale(screen_num()); int bt = get_window_frame_sizes(pWindow); r.origin = pt; r.size.width = round(W*s); r.size.height = round(H*s) + bt; if (NSEqualRects(r, [xid frame])) { pWindow->Fl_Group::resize(X, Y, W, H); // runs rarely, e.g. with scaled down test/tabs pWindow->redraw(); } else { // First resize the logical FLTK coordinates for this and all children if (!Fl_Window::is_a_rescale()) pWindow->Fl_Group::resize(X, Y, W, H); // Next update the physical Cocoa view [xid setFrame:r display:YES]; [[xid contentView] displayIfNeededIgnoringOpacity]; // Finally tell the the group to render its contents if the code above // didn't already pWindow->redraw(); } } else { if (pWindow->parent()) starting_moved_window = pWindow; if (!NSEqualPoints([xid frame].origin, pt)) [xid setFrameOrigin:pt]; // set cocoa coords to FLTK position else { x(X); y(Y); } if (pWindow->parent()) starting_moved_window = NULL; } through_resize(0); } // make sure subwindow doesn't leak outside parent if (pWindow->parent()) [fl_xid(pWindow) checkSubwindowFrame]; } /* * make all drawing go into this window (called by subclass flush() impl.) This can be called in 3 different situations: 1) When a window is created, resized or moved between low/high resolution displays. macOS sends the drawRect: message to the window view after having prepared the current graphics context to draw to this view. The drawRect: method sets through_drawRect to YES and calls Fl_Window_Driver::flush(). Fl_Window_Driver::flush() calls Fl_Window::flush() that calls Fl_Window::make_current() that uses the graphics context of the window or the layer. The window's draw() function is then executed. 2) At each round of the FLTK event loop. Fl::flush() is called, that calls Fl_Cocoa_Window_Driver::flush() on each window that needs drawing. Fl_Cocoa_Window_Driver::flush() sets through_Fl_X_Flush to YES and marks the view as needing display. The view is sent the displayIfNeededIgnoringOpacity or display message which makes the OS send the view the drawRect: message. The program proceeds next as in 1) above. 3) An FLTK application can call Fl_Window::make_current() at any time before it draws to a window. This occurs for instance in the idle callback function of the mandelbrot test program. Variables through_Fl_X_flush and through_drawRect equal NO. Before 10.14: The window graphics context is obtained. Subsequent drawing requests go to the window. After 10.14: The layered view is marked as needing display. It will be sent the drawRect: message at the next event loop. Subsequent drawing operations, until drawRect: runs, are sent to view->aux_bitmap. CAUTION: it's not possible to call Fl::wait(), Fl::check() nor Fl::ready() while in the draw() function of a widget. Use an idle callback instead. */ void Fl_Cocoa_Window_Driver::make_current() { q_release_context(); Fl_X *i = Fl_X::flx(pWindow); //NSLog(@"region-count=%d damage=%u",i->region?i->region->count:0, pWindow->damage()); fl_window = (FLWindow*)i->xid; ((Fl_Quartz_Graphics_Driver&)Fl_Graphics_Driver::default_driver()).high_resolution( mapped_to_retina() ); if (pWindow->as_overlay_window() && other_xid && changed_resolution()) { destroy_double_buffer(); changed_resolution(false); } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 FLView *view = (FLView*)[fl_window contentView]; if (views_use_CA && !through_drawRect) { // detect direct calls from the app [view setNeedsDisplay:YES]; } if (views_use_CA && view->aux_bitmap) { gc = view->aux_bitmap; } else #endif { NSGraphicsContext *nsgc = (through_drawRect ? [NSGraphicsContext currentContext] : [NSGraphicsContext graphicsContextWithWindow:fl_window]); static SEL gc_sel = fl_mac_os_version >= 101000 ? @selector(CGContext) : @selector(graphicsPort); gc = (CGContextRef)[nsgc performSelector:gc_sel]; } Fl_Graphics_Driver::default_driver().gc(gc); #if defined(FLTK_HAVE_CAIROEXT) CGContextSaveGState(gc); // one extra level #endif CGContextSaveGState(gc); // native context // antialiasing must be deactivated because it applies to rectangles too // and escapes even clipping!!! // it gets activated when needed (e.g., draw text) CGContextSetShouldAntialias(gc, false); CGFloat hgt = [[fl_window contentView] frame].size.height; float s = Fl::screen_driver()->scale(0); CGContextTranslateCTM(gc, 0.5f*s, hgt-0.5f*s); CGContextScaleCTM(gc, 1.0f, -1.0f); // now 0,0 is top-left point of the window CGContextScaleCTM(gc, s, s); // apply current scaling factor // for subwindows, limit drawing to inside of parent window // half pixel offset is necessary for clipping as done by fl_cgrectmake_cocoa() if (subRect()) { CGContextClipToRect(gc, CGRectOffset(*(subRect()), -0.5, -0.5)); } // this is the context with origin at top left of (sub)window CGContextSaveGState(gc); fl_clip_region( 0 ); #ifdef FLTK_HAVE_CAIROEXT // update the cairo_t context if (Fl::cairo_autolink_context()) Fl::cairo_make_current(pWindow); #endif } // Give the Quartz context back to the system void Fl_Cocoa_Window_Driver::q_release_context(Fl_Cocoa_Window_Driver *x) { CGContextRef gc = (CGContextRef)Fl_Graphics_Driver::default_driver().gc(); if (x && x->shown() && x->gc != gc) return; if (!gc) return; CGContextRestoreGState(gc); // match the CGContextSaveGState's of make_current CGContextRestoreGState(gc); CGContextFlush(gc); Fl_Graphics_Driver::default_driver().gc(0); #if defined(FLTK_HAVE_CAIROEXT) CGContextRestoreGState(gc); #endif } static NSBitmapImageRep *pdf_to_nsbitmapimagerep(NSData *pdfdata) { NSImage *image = [[NSImage alloc] initWithData:pdfdata]; NSInteger width = [image size].width * 2; NSInteger height = [image size].height * 2; NSBitmapImageRep *bitmap = [NSBitmapImageRep alloc]; NSRect dest_r = NSMakeRect(0, 0, width, height); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 if (fl_mac_os_version >= 100900) { // This procedure is necessary because initWithFocusedViewRect is deprecated in macOS 10.14 // and because it produces a bitmap with floating point pixel values with macOS 11.x bitmap = [bitmap initWithBitmapDataPlanes:NULL pixelsWide:width pixelsHigh:height bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:0 bitsPerPixel:0]; NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init]; [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:bitmap]];// 10.4 [[NSColor clearColor] set]; NSRect r = NSMakeRect(0, 0, width, height); NSRectFill(r); [image drawInRect:dest_r]; // 10.9 [NSGraphicsContext restoreGraphicsState]; [localPool release]; } else #endif { [image lockFocus]; // the deprecation warning at 10.14 can be ignored because runs only for macOS < 10.9 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" bitmap = [bitmap initWithFocusedViewRect:dest_r]; #pragma clang diagnostic pop [image unlockFocus]; } [bitmap setSize:[image size]]; [image release]; return bitmap; } Fl_Quartz_Copy_Surface_Driver::~Fl_Quartz_Copy_Surface_Driver() { CGContextRestoreGState(gc); CGContextEndPage(gc); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (fl_mac_os_version >= 100500) CGPDFContextClose(gc); // needs 10.5, necessary with macOS 10.15 #endif CGContextRelease(gc); NSPasteboard *clip = [NSPasteboard generalPasteboard]; [clip declareTypes:[NSArray arrayWithObjects:PDF_pasteboard_type, TIFF_pasteboard_type, nil] owner:nil]; [clip setData:(NSData*)pdfdata forType:PDF_pasteboard_type]; //second, transform this PDF to a bitmap image and put it as tiff in clipboard with retina resolution NSBitmapImageRep *bitmap = pdf_to_nsbitmapimagerep((NSData*)pdfdata); CFRelease(pdfdata); [clip setData:[bitmap TIFFRepresentation] forType:TIFF_pasteboard_type]; [bitmap release]; delete driver(); } //////////////////////////////////////////////////////////////// // Copy & Paste fltk implementation. //////////////////////////////////////////////////////////////// // clipboard variables definitions : char *fl_selection_buffer[2] = {NULL, NULL}; int fl_selection_length[2] = {0, 0}; static int fl_selection_buffer_length[2]; extern void fl_trigger_clipboard_notify(int source); static void clipboard_check(void) { static NSInteger oldcount = -1; NSInteger newcount = [[NSPasteboard generalPasteboard] changeCount]; if (newcount == oldcount) return; oldcount = newcount; fl_trigger_clipboard_notify(1); } static void resize_selection_buffer(int len, int clipboard) { if (len <= fl_selection_buffer_length[clipboard]) return; delete[] fl_selection_buffer[clipboard]; fl_selection_buffer[clipboard] = new char[len+100]; fl_selection_buffer_length[clipboard] = len+100; } /* * create a selection * stuff: pointer to selected data * len: size of selected data * type: always "plain/text" for now */ void Fl_Cocoa_Screen_Driver::copy(const char *stuff, int len, int clipboard, const char *type) { if (!stuff || len<0) return; if (clipboard >= 2) clipboard = 1; // Only on X11 do multiple clipboards make sense. resize_selection_buffer(len+1, clipboard); memcpy(fl_selection_buffer[clipboard], stuff, len); fl_selection_buffer[clipboard][len] = 0; // needed for direct paste fl_selection_length[clipboard] = len; if (clipboard) { CFDataRef text = CFDataCreate(kCFAllocatorDefault, (UInt8*)fl_selection_buffer[1], len); if (text==NULL) return; // there was a pb creating the object, abort. NSPasteboard *clip = [NSPasteboard generalPasteboard]; [clip declareTypes:[NSArray arrayWithObject:UTF8_pasteboard_type] owner:nil]; [clip setData:(NSData*)text forType:UTF8_pasteboard_type]; CFRelease(text); } } static int get_plain_text_from_clipboard(int clipboard) { NSInteger length = 0; NSPasteboard *clip = [NSPasteboard generalPasteboard]; NSString *found = [clip availableTypeFromArray:[NSArray arrayWithObjects:UTF8_pasteboard_type, @"public.utf16-plain-text", @"com.apple.traditional-mac-plain-text", nil]]; if (found) { NSData *data = [clip dataForType:found]; if (data) { NSInteger len; char *aux_c = NULL; if (![found isEqualToString:UTF8_pasteboard_type]) { NSString *auxstring; auxstring = (NSString *)CFStringCreateWithBytes(NULL, (const UInt8*)[data bytes], [data length], ([found isEqualToString:@"public.utf16-plain-text"] ? kCFStringEncodingUnicode : kCFStringEncodingMacRoman), false); aux_c = fl_strdup([auxstring UTF8String]); [auxstring release]; len = strlen(aux_c) + 1; } else len = [data length] + 1; resize_selection_buffer((int)len, clipboard); if (![found isEqualToString:UTF8_pasteboard_type]) { strcpy(fl_selection_buffer[clipboard], aux_c); free(aux_c); } else { [data getBytes:fl_selection_buffer[clipboard] length:[data length]]; } fl_selection_buffer[clipboard][len - 1] = 0; length = Fl_Screen_Driver::convert_crlf(fl_selection_buffer[clipboard], len - 1); // turn all \r characters into \n: Fl::e_clipboard_type = Fl::clipboard_plain_text; } } return (int)length; } static Fl_RGB_Image* get_image_from_clipboard(Fl_Widget *receiver) { NSPasteboard *clip = [NSPasteboard generalPasteboard]; NSArray *present = [clip types]; // types in pasteboard in order of decreasing preference NSArray *possible = [NSArray arrayWithObjects:PDF_pasteboard_type, TIFF_pasteboard_type, PICT_pasteboard_type, nil]; NSString *found = nil; NSUInteger rank; for (NSUInteger i = 0; (!found) && i < [possible count]; i++) { for (rank = 0; rank < [present count]; rank++) { // find first of possible types present in pasteboard if ([[present objectAtIndex:rank] isEqualToString:[possible objectAtIndex:i]]) { found = [present objectAtIndex:rank]; break; } } } if (!found) return NULL; NSData *data = [clip dataForType:found]; if (!data) return NULL; NSBitmapImageRep *bitmap = nil; if ([found isEqualToString:TIFF_pasteboard_type]) { bitmap = [[NSBitmapImageRep alloc] initWithData:data]; } else if ([found isEqualToString:PDF_pasteboard_type] || [found isEqualToString:PICT_pasteboard_type]) { bitmap = pdf_to_nsbitmapimagerep(data); } if (!bitmap) return NULL; int bytesPerPixel((int)[bitmap bitsPerPixel]/8); int bpr((int)[bitmap bytesPerRow]); int hh((int)[bitmap pixelsHigh]); int ww((int)[bitmap pixelsWide]); uchar *imagedata = new uchar[bpr * hh]; memcpy(imagedata, [bitmap bitmapData], bpr * hh); Fl_RGB_Image *image = new Fl_RGB_Image(imagedata, ww, hh, bytesPerPixel, (bpr == ww * bytesPerPixel ? 0 : bpr) ); image->scale([bitmap size].width, [bitmap size].height); image->alloc_array = 1; [bitmap release]; Fl::e_clipboard_type = Fl::clipboard_image; return image; } // Call this when a "paste" operation happens: void Fl_Cocoa_Screen_Driver::paste(Fl_Widget &receiver, int clipboard, const char *type) { if (type[0] == 0) type = Fl::clipboard_plain_text; if (clipboard) { Fl::e_clipboard_type = ""; if (strcmp(type, Fl::clipboard_plain_text) == 0) { fl_selection_length[1] = get_plain_text_from_clipboard(1); } else if (strcmp(type, Fl::clipboard_image) == 0) { Fl::e_clipboard_data = get_image_from_clipboard(&receiver); if (Fl::e_clipboard_data) { int done = receiver.handle(FL_PASTE); Fl::e_clipboard_type = ""; if (done == 0) { delete (Fl_Image*)Fl::e_clipboard_data; Fl::e_clipboard_data = NULL; } } return; } else fl_selection_length[1] = 0; } Fl::e_text = fl_selection_buffer[clipboard]; Fl::e_length = fl_selection_length[clipboard]; if (!Fl::e_length) Fl::e_text = (char *)""; receiver.handle(FL_PASTE); } int Fl_Cocoa_Screen_Driver::clipboard_contains(const char *type) { NSString *found = nil; if (strcmp(type, Fl::clipboard_plain_text) == 0) { found = [[NSPasteboard generalPasteboard] availableTypeFromArray:[NSArray arrayWithObjects:UTF8_pasteboard_type, @"public.utf16-plain-text", @"com.apple.traditional-mac-plain-text", nil]]; } else if (strcmp(type, Fl::clipboard_image) == 0) { found = [[NSPasteboard generalPasteboard] availableTypeFromArray:[NSArray arrayWithObjects:TIFF_pasteboard_type, PDF_pasteboard_type, PICT_pasteboard_type, nil]]; } return found != nil; } void Fl_Cocoa_Window_Driver::destroy(FLWindow *xid) { [[xid parentWindow] removeChildWindow:xid]; // necessary until 10.6 at least if (fl_sys_menu_bar && Fl_Sys_Menu_Bar_Driver::window_menu_style()) Fl_MacOS_Sys_Menu_Bar_Driver::driver()->remove_window([xid getFl_Window]); [xid close]; } void Fl_Cocoa_Window_Driver::map() { FLWindow *xid = fl_xid(pWindow); if (pWindow && xid && ![xid parentWindow]) { // 10.2 // after a subwindow has been unmapped, it has lost its parent window and its frame may be wrong [xid setSubwindowFrame]; } if (cursor) { [cursor release]; cursor = NULL; } } void Fl_Cocoa_Window_Driver::unmap() { FLWindow *xid = fl_xid(pWindow); if (pWindow && xid) { if (parent()) [[xid parentWindow] removeChildWindow:xid]; // necessary with at least 10.5 [xid orderOut:nil]; } } void Fl_Cocoa_Window_Driver::iconize() { [fl_xid(pWindow) miniaturize:nil]; } static NSImage *CGBitmapContextToNSImage(CGContextRef c) // the returned NSImage is autoreleased { NSImage* image; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 if (fl_mac_os_version >= 100600) { CGImageRef cgimg = CGBitmapContextCreateImage(c); // requires 10.4 image = [[NSImage alloc] initWithCGImage:cgimg size:NSZeroSize]; // requires 10.6 CFRelease(cgimg); } else #endif { NSBitmapImageRep *imagerep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:CGBitmapContextGetWidth(c) pixelsHigh:CGBitmapContextGetHeight(c) bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:CGBitmapContextGetBytesPerRow(c) bitsPerPixel:CGBitmapContextGetBitsPerPixel(c)]; memcpy([imagerep bitmapData], CGBitmapContextGetData(c), [imagerep bytesPerRow] * [imagerep pixelsHigh]); image = [[NSImage alloc] initWithSize:NSMakeSize([imagerep pixelsWide], [imagerep pixelsHigh])]; [image addRepresentation:imagerep]; [imagerep release]; } return [image autorelease]; } int Fl_Cocoa_Window_Driver::set_cursor(Fl_Cursor c) { if (cursor) { [(NSCursor*)cursor release]; cursor = NULL; } switch (c) { case FL_CURSOR_ARROW: cursor = [NSCursor arrowCursor]; break; case FL_CURSOR_CROSS: cursor = [NSCursor crosshairCursor]; break; case FL_CURSOR_INSERT: cursor = [NSCursor IBeamCursor]; break; case FL_CURSOR_HAND: cursor = [NSCursor pointingHandCursor]; break; case FL_CURSOR_MOVE: cursor = [NSCursor openHandCursor]; break; case FL_CURSOR_NS: cursor = [NSCursor resizeUpDownCursor]; break; case FL_CURSOR_WE: cursor = [NSCursor resizeLeftRightCursor]; break; case FL_CURSOR_N: cursor = [NSCursor resizeUpCursor]; break; case FL_CURSOR_E: cursor = [NSCursor resizeRightCursor]; break; case FL_CURSOR_W: cursor = [NSCursor resizeLeftCursor]; break; case FL_CURSOR_S: cursor = [NSCursor resizeDownCursor]; break; default: return 0; } [(NSCursor*)cursor retain]; [fl_xid(pWindow) invalidateCursorRectsForView:[fl_xid(pWindow) contentView]]; return 1; } int Fl_Cocoa_Window_Driver::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { if (cursor) { [(NSCursor*)cursor release]; cursor = NULL; } if ((hotx < 0) || (hotx >= image->w())) return 0; if ((hoty < 0) || (hoty >= image->h())) return 0; // OS X >= 10.6 can create a NSImage from a CGImage, but we need to // support older versions, hence this pesky handling. NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:image->data_w() pixelsHigh:image->data_h() bitsPerSample:8 samplesPerPixel:image->d() hasAlpha:!(image->d() & 1) isPlanar:NO colorSpaceName:(image->d() <= 2 ? NSDeviceWhiteColorSpace : NSDeviceRGBColorSpace) bytesPerRow:(image->data_w() * image->d()) bitsPerPixel:(image->d()*8)]; // Alpha needs to be premultiplied for this format const uchar *i = (const uchar*)*image->data(); const int extra_data = image->ld() ? (image->ld() - image->data_w() * image->d()) : 0; unsigned char *o = [bitmap bitmapData]; for (int y = 0;y < image->data_h();y++) { if (!(image->d() & 1)) { for (int x = 0;x < image->data_w();x++) { unsigned int alpha; if (image->d() == 4) { alpha = i[3]; *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255); *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255); } alpha = i[1]; *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255); *o++ = alpha; i++; } } else { // No alpha, so we can just copy everything directly. int len = image->data_w() * image->d(); memcpy(o, i, len); o += len; i += len; } i += extra_data; } NSImage *nsimage = [[NSImage alloc] initWithSize:NSMakeSize(image->w(), image->h())]; [nsimage addRepresentation:bitmap]; cursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSMakePoint(hotx, hoty)]; [fl_xid(pWindow) invalidateCursorRectsForView:[fl_xid(pWindow) contentView]]; [bitmap release]; [nsimage release]; return 1; } @interface PrintWithTitlebarItem : NSMenuItem { } - (void) toggleCallback; @end @implementation PrintWithTitlebarItem - (void) toggleCallback { NSMenuItem *item = [self representedObject]; const char *title; if ([self state] == NSControlStateValueOn) { [self setState:NSControlStateValueOff]; title = Fl_Mac_App_Menu::print_no_titlebar; } else { [self setState:NSControlStateValueOn]; title = Fl_Mac_App_Menu::print; } [item setTitle:NSLocalizedString([NSString stringWithUTF8String:title], nil)]; } @end static PrintWithTitlebarItem *print_with_titlebar_item = NULL; @interface FLaboutItemTarget : NSObject { } - (BOOL)validateMenuItem:(NSMenuItem *)item; - (void)showPanel; - (void)printPanel; - (void)terminate:(id)sender; @end @implementation FLaboutItemTarget - (BOOL)validateMenuItem:(NSMenuItem *)item { // invalidate the Quit item of the application menu when running modal or when in native file chooser if ([[NSApp keyWindow] isKindOfClass:[NSSavePanel class]]) return NO; if (!Fl::modal() || [item action] != @selector(terminate:)) return YES; return NO; } - (void)showPanel { NSDictionary *options; options = [NSDictionary dictionaryWithObjectsAndKeys: [[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@" GUI with FLTK %d.%d", FL_MAJOR_VERSION, FL_MINOR_VERSION ]] autorelease], @"Credits", nil]; [NSApp orderFrontStandardAboutPanelWithOptions:options]; } - (void)printPanel { bool grab_decoration = ([print_with_titlebar_item state] == NSControlStateValueOn); fl_lock_function(); fl_print_or_copy_window(Fl::first_window(), grab_decoration, 1); fl_unlock_function(); } - (void)terminate:(id)sender { [NSApp terminate:sender]; } @end static void createAppleMenu(void) { static BOOL donethat = NO; if (donethat) return; donethat = YES; NSMenu *mainmenu, *services = nil, *appleMenu; NSMenuItem *menuItem; NSString *title; SEL infodictSEL = (fl_mac_os_version >= 100200 ? @selector(localizedInfoDictionary) : @selector(infoDictionary)); NSString *nsappname = [[[NSBundle mainBundle] performSelector:infodictSEL] objectForKey:@"CFBundleName"]; if (nsappname == nil) nsappname = [[NSProcessInfo processInfo] processName]; appleMenu = [[NSMenu alloc] initWithTitle:@""]; /* Add menu items */ title = [NSString stringWithFormat:NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::about],nil), nsappname]; menuItem = [appleMenu addItemWithTitle:title action:@selector(showPanel) keyEquivalent:@""]; FLaboutItemTarget *about = [[FLaboutItemTarget alloc] init]; [menuItem setTarget:about]; [appleMenu addItem:[NSMenuItem separatorItem]]; // Print front window title = NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::print], nil); if ([title length] > 0) { menuItem = [appleMenu addItemWithTitle:title action:@selector(printPanel) keyEquivalent:@""]; [menuItem setTarget:about]; [menuItem setEnabled:YES]; // Toggle "Print Window with titlebar" / "Print Window" title = NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::toggle_print_titlebar], nil); print_with_titlebar_item = [[PrintWithTitlebarItem alloc] initWithTitle:title action:@selector(toggleCallback) keyEquivalent:@""]; [appleMenu addItem:print_with_titlebar_item]; [print_with_titlebar_item setTarget:print_with_titlebar_item]; [print_with_titlebar_item setRepresentedObject:menuItem]; [print_with_titlebar_item setState:NSControlStateValueOn]; [print_with_titlebar_item setEnabled:YES]; [appleMenu addItem:[NSMenuItem separatorItem]]; } if (fl_mac_os_version >= 100400) { // services+hide+quit already in menu in OS 10.3 // Services Menu services = [[NSMenu alloc] initWithTitle:@""]; menuItem = [appleMenu addItemWithTitle:NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::services], nil) action:nil keyEquivalent:@""]; [appleMenu setSubmenu:services forItem:menuItem]; [appleMenu addItem:[NSMenuItem separatorItem]]; // Hide AppName title = [NSString stringWithFormat:NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::hide],nil), nsappname]; [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; // Hide Others menuItem = [appleMenu addItemWithTitle:NSLocalizedString( [NSString stringWithUTF8String:Fl_Mac_App_Menu::hide_others] , nil) action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; [menuItem setKeyEquivalentModifierMask:(NSEventModifierFlagOption|NSEventModifierFlagCommand)]; // Show All [appleMenu addItemWithTitle:NSLocalizedString( [NSString stringWithUTF8String:Fl_Mac_App_Menu::show], nil) action:@selector(unhideAllApplications:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; // Quit AppName title = [NSString stringWithFormat:NSLocalizedString( [NSString stringWithUTF8String:Fl_Mac_App_Menu::quit], nil), nsappname]; menuItem = [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; [menuItem setTarget:about]; } /* Put menu into the menubar */ menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; [menuItem setSubmenu:appleMenu]; mainmenu = [[NSMenu alloc] initWithTitle:@""]; [mainmenu addItem:menuItem]; if (fl_mac_os_version < 100600) { // [NSApp setAppleMenu:appleMenu]; // to avoid compiler warning raised by use of undocumented setAppleMenu : [NSApp performSelector:@selector(setAppleMenu:) withObject:appleMenu]; } [NSApp setMainMenu:mainmenu]; if (services) { [NSApp setServicesMenu:services]; [services release]; } [mainmenu release]; [appleMenu release]; [menuItem release]; Fl_MacOS_Sys_Menu_Bar_Driver::driver(); } void Fl_Cocoa_Window_Driver::set_key_window() { [fl_xid(pWindow) makeKeyWindow]; } static NSImage *imageFromText(const char *text, int *pwidth, int *pheight) { const char *p, *q; int width = 0, height, w2, ltext = (int)strlen(text); fl_font(FL_HELVETICA, 10); p = text; int nl = 0; while(nl < 100 && (q=strchr(p, '\n')) != NULL) { nl++; w2 = (int)fl_width(p, (int)(q - p)); if (w2 > width) width = w2; p = q + 1; } if (text[ ltext - 1] != '\n') { nl++; w2 = int(fl_width(p)); if (w2 > width) width = w2; } height = nl * fl_height() + 3; width += 6; Fl_Image_Surface *off = new Fl_Image_Surface(width, height, 1); Fl_Surface_Device::push_current(off); CGContextSetRGBFillColor( (CGContextRef)off->offscreen(), 0,0,0,0); fl_rectf(0,0,width,height); fl_color(FL_BLACK); p = text; fl_font(FL_HELVETICA, 10); int y = fl_height(); while(TRUE) { q = strchr(p, '\n'); if (q) { fl_draw(p, (int)(q - p), 3, y); } else { fl_draw(p, 3, y); break; } y += fl_height(); p = q + 1; } Fl_Surface_Device::pop_current(); NSImage* image = CGBitmapContextToNSImage( (CGContextRef)off->offscreen() ); delete off; *pwidth = width; *pheight = height; return image; } static NSImage *defaultDragImage(int *pwidth, int *pheight) { const int version_threshold = 100700; int width, height; if (fl_mac_os_version >= version_threshold) { width = 50; height = 40; } else { width = 16; height = 16; } Fl_Image_Surface *off = new Fl_Image_Surface(width, height, 1); Fl_Surface_Device::push_current(off); if (fl_mac_os_version >= version_threshold) { fl_font(FL_HELVETICA, 20); fl_color(FL_BLACK); char str[4]; // the "Delivery truck" Unicode character from "Apple Color Emoji" font int l = fl_utf8encode(0x1F69A, str); fl_draw(str, l, 1, 16); } else { // draw two squares CGContextSetRGBFillColor( (CGContextRef)off->offscreen(), 0,0,0,0); fl_rectf(0,0,width,height); CGContextSetRGBStrokeColor( (CGContextRef)off->offscreen(), 0,0,0,0.6); fl_rect(0,0,width,height); fl_rect(2,2,width-4,height-4); } Fl_Surface_Device::pop_current(); NSImage* image = CGBitmapContextToNSImage( (CGContextRef)off->offscreen() ); delete off; *pwidth = width; *pheight = height; return image; } int Fl_Cocoa_Screen_Driver::dnd(int use_selection) { CFDataRef text = CFDataCreate(kCFAllocatorDefault, (UInt8*)fl_selection_buffer[0], fl_selection_length[0]); if (text==NULL) return false; NSAutoreleasePool *localPool; localPool = [[NSAutoreleasePool alloc] init]; Fl_Widget *w = Fl::pushed(); Fl_Window *win = w->top_window(); FLView *myview = (FLView*)[fl_mac_xid(win) contentView]; NSEvent *theEvent = [NSApp currentEvent]; int width, height; NSImage *image; if (use_selection) { fl_selection_buffer[0][ fl_selection_length[0] ] = 0; image = imageFromText(fl_selection_buffer[0], &width, &height); } else { image = defaultDragImage(&width, &height); } NSPoint pt = [theEvent locationInWindow]; pt.x -= width/2; pt.y -= height/2; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if (fl_mac_os_version >= 100700) { NSPasteboardItem *pbItem = [[[NSPasteboardItem alloc] init] autorelease]; [pbItem setData:(NSData*)text forType:UTF8_pasteboard_type]; NSDraggingItem *dragItem = [[[NSDraggingItem alloc] initWithPasteboardWriter:pbItem] autorelease]; NSRect r = {pt, {CGFloat(width), CGFloat(height)}}; [dragItem setDraggingFrame:r contents:image]; [myview beginDraggingSessionWithItems:[NSArray arrayWithObject:dragItem] event:theEvent source:myview]; } else #endif { static NSSize offset={0,0}; // the 2 deprecation warnings can be ignored because this runs only for macOS < 10.7 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" // deprecated in 10.13 NSPasteboard *mypasteboard = [NSPasteboard pasteboardWithName:NSDragPboard]; [mypasteboard declareTypes:[NSArray arrayWithObject:UTF8_pasteboard_type] owner:nil]; [mypasteboard setData:(NSData*)text forType:UTF8_pasteboard_type]; [myview dragImage:image at:pt offset:offset // deprecated in 10.7 event:theEvent pasteboard:mypasteboard source:myview slideBack:YES]; #pragma clang diagnostic pop if ( w ) { int old_event = Fl::e_number; w->handle(Fl::e_number = FL_RELEASE); Fl::e_number = old_event; Fl::pushed( 0 ); } } CFRelease(text); [localPool release]; return true; } // rescales an NSBitmapImageRep (and also rewrites it with integer pixels) static NSBitmapImageRep *scale_nsbitmapimagerep(NSBitmapImageRep *img, float scale) { int w = (int)[img pixelsWide]; int h = (int)[img pixelsHigh]; long int scaled_w = lround(scale * w); long int scaled_h = lround(scale * h); NSBitmapImageRep *scaled = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:scaled_w pixelsHigh:scaled_h bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:scaled_w*4 bitsPerPixel:32]; NSDictionary *dict = [NSDictionary dictionaryWithObject:scaled forKey:NSGraphicsContextDestinationAttributeName]; NSGraphicsContext *oldgc = [NSGraphicsContext currentContext]; [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithAttributes:dict]]; [[NSColor clearColor] set]; NSRect r = NSMakeRect(0, 0, scaled_w, scaled_h); NSRectFill(r); [img drawInRect:r]; [NSGraphicsContext setCurrentContext:oldgc]; [img release]; return scaled; } static void write_bitmap_inside(NSBitmapImageRep *to, int to_width, NSBitmapImageRep *from, int to_x, int to_y) /* Copies in bitmap "to" the bitmap "from" with its top-left angle at coordinates to_x, to_y On retina displays both bitmaps have double width and height to_width is the width in screen units of "to". On retina, its pixel width is twice that. */ { const uchar *from_data = [from bitmapData]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (fl_mac_os_version >= 100400) { // 10.4 required by the bitmapFormat message if (([to bitmapFormat] & NSBitmapFormatAlphaFirst) && !([from bitmapFormat] & NSBitmapFormatAlphaFirst) ) { // "to" is ARGB and "from" is RGBA --> convert "from" to ARGB // it is enough to read "from" starting one byte earlier, because A is always 0xFF: // RGBARGBA becomes (A)RGBARGB from_data--; } else if ( !([to bitmapFormat] & NSBitmapFormatAlphaFirst) && ([from bitmapFormat] & NSBitmapFormatAlphaFirst) ) { // "from" is ARGB and "to" is RGBA --> convert "from" to RGBA // it is enough to offset reading by one byte because A is always 0xFF // so ARGBARGB becomes RGBARGB(A) as needed from_data++; } } #endif int to_w = (int)[to pixelsWide]; // pixel width of "to" int from_w = (int)[from pixelsWide]; // pixel width of "from" int from_h = (int)[from pixelsHigh]; // pixel height of "from" int to_depth = (int)[to samplesPerPixel]; int from_depth = (int)[from samplesPerPixel]; int depth = 0; if (to_depth > from_depth) depth = from_depth; else if (from_depth > to_depth) depth = to_depth; float factor = to_w / (float)to_width; // scaling factor is 1 for classic displays and 2 for retina to_x = factor*to_x; // transform offset from screen unit to pixels to_y = factor*to_y; // perform the copy uchar *tobytes = [to bitmapData] + to_y * to_w * to_depth + to_x * to_depth; const uchar *frombytes = from_data; for (int i = 0; i < from_h; i++) { if (depth == 0) { // depth is always 0 in case of RGBA <-> ARGB conversion if (i == 0 && from_data < [from bitmapData]) { memcpy(tobytes+1, frombytes+1, from_w * from_depth-1); // avoid reading before [from bitmapData] *tobytes = 0xFF; // set the very first A byte } else if (i == from_h - 1 && from_data > [from bitmapData]) { memcpy(tobytes, frombytes, from_w * from_depth - 1); // avoid reading after end of [from bitmapData] *(tobytes + from_w * from_depth - 1) = 0xFF; // set the very last A byte } else { memcpy(tobytes, frombytes, from_w * from_depth); } } else { for (int j = 0; j < from_w; j++) { memcpy(tobytes + j * to_depth, frombytes + j * from_depth, depth); } } tobytes += to_w * to_depth; frombytes += from_w * from_depth; } } static NSBitmapImageRep* GL_rect_to_nsbitmap(Fl_Window *win, int x, int y, int w, int h) // captures a rectangle from a GL window and returns it as an allocated NSBitmapImageRep // the capture has high res on retina { Fl_Device_Plugin *plugin = Fl_Device_Plugin::opengl_plugin(); if (!plugin) return nil; Fl_RGB_Image *img = plugin->rectangle_capture(win, x, y, w, h); NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:img->w() pixelsHigh:img->h() bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:4*img->w() bitsPerPixel:32]; if (img->d() == 4) memcpy([bitmap bitmapData], img->array, 4*img->data_w()*img->data_h()); else { memset([bitmap bitmapData], 0xFF, [bitmap bytesPerPlane]); const uchar *from = img->array; for (int r = 0; r < img->h(); r++) { uchar *to = [bitmap bitmapData] + r * [bitmap bytesPerRow]; for (int c = 0; c < img->w(); c++) { memcpy(to, from, 3); from += 3; to += 4; } } } delete img; return bitmap; } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 static NSBitmapImageRep* rect_to_NSBitmapImage_layer(Fl_Window *win, int x, int y, int w, int h) { // capture window data for layer-based views because initWithFocusedViewRect: does not work for them FLView *view = (FLView*)[fl_xid(win) contentView]; if (!view->aux_bitmap) return nil; CGImageRef cgimg = CGBitmapContextCreateImage(view->aux_bitmap); if (x || y || w != win->w() || h != win->h()) { float s = Fl::screen_driver()->scale(0); if (Fl_Cocoa_Window_Driver::driver(win)->mapped_to_retina()) s *= 2; CGRect rect = CGRectMake(x * s, y * s, w * s, h * s); CGImageRef cgimg2 = CGImageCreateWithImageInRect(cgimg, rect); CGImageRelease(cgimg); cgimg = cgimg2; } NSBitmapImageRep *bitmap = (cgimg ? [[NSBitmapImageRep alloc] initWithCGImage:cgimg/*10.5*/] : nil); CGImageRelease(cgimg); return bitmap; } #endif static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y, int w, int h) { NSBitmapImageRep *bitmap = nil; NSRect rect; float s = Fl_Graphics_Driver::default_driver().scale(); if (win->as_gl_window() && y >= 0) { bitmap = GL_rect_to_nsbitmap(win, x, y, w, h); } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 else if (views_use_CA) { bitmap = rect_to_NSBitmapImage_layer(win, x, y, w, h); } #endif else { NSView *winview = nil; if ( through_Fl_X_flush && Fl_Window::current() == win ) { rect = NSMakeRect(x - 0.5, y - 0.5, w, h); } else { winview = [fl_xid(win) contentView]; int view_h = [winview frame].size.height; rect = NSMakeRect(int(x*s), int(view_h-y*s-int(h*s)), int(w*s), int(h*s)); // lock focus to win's view #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (fl_mac_os_version >= 101100) { NSGraphicsContext *ctxt = [fl_xid(win) performSelector:@selector(graphicsContext)]; [ctxt saveGraphicsState]; // necessary under 10.11 } #endif [winview performSelector:@selector(lockFocus)]; } // The image depth is 3 until macOS 10.5 and 4 with 10.6 and above // the deprecation warning at 10.14 can be ignored because runs only for macOS < 10.14 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:rect]; #pragma clang diagnostic pop if ( !( through_Fl_X_flush && Fl_Window::current() == win) ) { [winview performSelector:@selector(unlockFocus)]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (fl_mac_os_version >= 101100) { NSGraphicsContext *ctxt = [fl_xid(win) performSelector:@selector(graphicsContext)]; [ctxt restoreGraphicsState]; } #endif } } return bitmap; } static NSBitmapImageRep* rect_to_NSBitmapImageRep_subwins(Fl_Window *win, int x, int y, int w, int h, bool capture_subwins) /* Captures a rectangle from a mapped window. On retina displays, the resulting bitmap has 2 pixels per screen unit. The returned value is to be released after use */ { Fl_Rect r(x, y, w, h); NSBitmapImageRep *bitmap = [fl_xid(win) rect_to_NSBitmapImageRep:&r]; if (!capture_subwins || !bitmap) return bitmap; // capture also subwindows NSArray *children = [fl_xid(win) childWindows]; // 10.2 NSEnumerator *enumerator = [children objectEnumerator]; id child; while ((child = [enumerator nextObject]) != nil) { if (![child isKindOfClass:[FLWindow class]]) continue; Fl_Window *sub = [(FLWindow*)child getFl_Window]; CGRect rsub = CGRectMake(sub->x(), win->h() -(sub->y()+sub->h()), sub->w(), sub->h()); CGRect clip = CGRectMake(x, win->h()-(y+h), w, h); clip = CGRectIntersection(rsub, clip); if (CGRectIsNull(clip)) continue; NSBitmapImageRep *childbitmap = rect_to_NSBitmapImageRep_subwins(sub, clip.origin.x - sub->x(), win->h() - clip.origin.y - sub->y() - clip.size.height, clip.size.width, clip.size.height, true); if (childbitmap) { // if bitmap is high res and childbitmap is not, childbitmap must be rescaled if (!win->as_gl_window() && Fl_Cocoa_Window_Driver::driver(win)->mapped_to_retina() && sub->as_gl_window() && !Fl::use_high_res_GL()) { childbitmap = scale_nsbitmapimagerep(childbitmap, 2); } float s = Fl_Graphics_Driver::default_driver().scale(); write_bitmap_inside(bitmap, w * s, childbitmap, (clip.origin.x - x) * s, (win->h() - clip.origin.y - clip.size.height - y) * s ); } [childbitmap release]; } return bitmap; } static void nsbitmapProviderReleaseData (void *info, const void *data, size_t size) { [(NSBitmapImageRep*)info release]; } CGImageRef Fl_Cocoa_Window_Driver::CGImage_from_window_rect(int x, int y, int w, int h, bool capture_subwins) /* Returns a capture of a rectangle of a mapped window as a CGImage. With retina displays, the returned image has twice the width and height. CFRelease the returned CGImageRef after use */ { CGImageRef img; NSBitmapImageRep *bitmap = rect_to_NSBitmapImageRep_subwins(pWindow, x, y, w, h, capture_subwins); if (fl_mac_os_version >= 100500) { img = (CGImageRef)[bitmap performSelector:@selector(CGImage)]; // requires Mac OS 10.5 CGImageRetain(img); [bitmap release]; } else { CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB(); CGDataProviderRef provider = CGDataProviderCreateWithData(bitmap, [bitmap bitmapData], [bitmap bytesPerRow] * [bitmap pixelsHigh], nsbitmapProviderReleaseData); img = CGImageCreate([bitmap pixelsWide], [bitmap pixelsHigh], 8, [bitmap bitsPerPixel], [bitmap bytesPerRow], cspace, ([bitmap bitsPerPixel] == 32 ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNone) , provider, NULL, false, kCGRenderingIntentDefault); CGColorSpaceRelease(cspace); CGDataProviderRelease(provider); } return img; } int Fl_Cocoa_Window_Driver::decorated_w() { if (!shown() || parent() || !border() || !visible()) return w(); int bx=0; get_window_frame_sizes(pWindow, &bx); return w() + 2 * bx; } int Fl_Cocoa_Window_Driver::decorated_h() { if (!shown() || parent() || !border() || !visible()) return h(); int bx = 0, by = 0; int bt = get_window_frame_sizes(pWindow, &bx, &by); float s = Fl::screen_driver()->scale(0); return h() + bt/s; } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_15_0 // Requires -weak_framework ScreenCaptureKit and used by FLTK for macOS ≥ 15.0 static CGImageRef capture_decorated_window_SCK(NSWindow *nswin) { if (@available(macOS 15.0, *)) { __block CGImageRef capture = NULL; __block BOOL capture_err = NO; void (^block_to_stop_main_loop)(void) = ^{ CFRunLoopStop(CFRunLoopGetMain()); }; // Fix for bug in ScreenCaptureKit that modifies a window's styleMask the first time // it captures a non-resizable window. We memorize each non-resizable window's styleMask, // and we restore modified styleMasks later, after the screen capture. NSMutableArray *xid_array = [NSMutableArray arrayWithCapacity:2]; NSMutableArray *mask_array = [NSMutableArray arrayWithCapacity:2]; Fl_Window *win = Fl::first_window(); while (win) { if (!win->parent() && win->border()) { FLWindow *xid = fl_mac_xid(win); if (xid && !([xid styleMask] & NSWindowStyleMaskResizable)) { [xid_array addObject:xid]; NSUInteger mask = [xid styleMask]; [mask_array addObject:[NSData dataWithBytes:&mask length:sizeof(NSUInteger)]]; } } win = Fl::next_window(win); } CGWindowID target_id = [nswin windowNumber]; NSRect r = [nswin frame]; int W = r.size.width, H = r.size.height; [SCShareableContent getCurrentProcessShareableContentWithCompletionHandler: // macOS 14.4 ^(SCShareableContent *shareableContent, NSError *error) { SCWindow *scwin = nil; if (!error) { NSEnumerator *enumerator = [[shareableContent windows] objectEnumerator]; while ((scwin = (SCWindow*)[enumerator nextObject]) != nil) { if ([scwin windowID] == target_id) { break; } } } if (!scwin) { capture_err = YES; dispatch_async(dispatch_get_main_queue(), block_to_stop_main_loop); return; } SCContentFilter *filter = [[[SCContentFilter alloc] initWithDesktopIndependentWindow:scwin] autorelease]; int s = (int)[filter pointPixelScale]; SCStreamConfiguration *config = [[[SCStreamConfiguration alloc] init] autorelease]; [config setIgnoreShadowsSingleWindow:YES]; [config setShowsCursor:NO]; [config setWidth:W*s]; [config setHeight:H*s]; [config setIncludeChildWindows:NO]; // macOS 14.2 [SCScreenshotManager captureImageWithFilter:filter configuration:config completionHandler:^(CGImageRef sampleBuffer, NSError *error) { if (error) capture_err = YES; else { capture = sampleBuffer; CGImageRetain(capture); } dispatch_async(dispatch_get_main_queue(), block_to_stop_main_loop); } ]; } ]; // run the main loop until the 1 or 2 blocks above have completed and have stopped the loop while (!capture_err && !capture) CFRunLoopRun(); if (capture_err) return NULL; // ScreenCaptureKit bug cont'd: restore modified styleMasks. for (int i = 0, count = [xid_array count]; i < count; i++) { NSUInteger mask; [(NSData*)[mask_array objectAtIndex:i] getBytes:&mask length:sizeof(NSUInteger)]; NSWindow *xid = (NSWindow*)[xid_array objectAtIndex:i]; if (mask != [xid styleMask]) [xid setStyleMask:mask]; } return capture; } else return NULL; } #endif //MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_15_0 CGImageRef Fl_Cocoa_Window_Driver::capture_decorated_window_10_5(NSWindow *nswin) { // usable with 10.5 and above CGImageRef img = NULL; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_15_0 if (fl_mac_os_version >= 150000) img = capture_decorated_window_SCK(nswin); else #endif { # if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_15_0 NSInteger win_id = [nswin windowNumber]; CFArrayRef array = CFArrayCreate(NULL, (const void**)&win_id, 1, NULL); img = CGWindowListCreateImageFromArray(CGRectNull, array, kCGWindowImageBoundsIgnoreFraming); // 10.5 CFRelease(array); # endif } #endif // >= MAC_OS_X_VERSION_10_5 return img; } static CGImageRef capture_window_titlebar(Fl_Window *win, Fl_Cocoa_Window_Driver *cocoa_dr) { CGImageRef img; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 if (fl_mac_os_version >= 100600) { // verified OK from 10.6 FLWindow *nswin = fl_xid(win); CGImageRef img_full = Fl_Cocoa_Window_Driver::capture_decorated_window_10_5(nswin); int bt = [nswin frame].size.height - [[nswin contentView] frame].size.height; int s = CGImageGetWidth(img_full) / [nswin frame].size.width; CGRect cgr = CGRectMake(0, 0, CGImageGetWidth(img_full), bt * s); img = CGImageCreateWithImageInRect(img_full, cgr); // 10.4 CGImageRelease(img_full); } else #endif { int w = win->w(), h = win->decorated_h() - win->h(); Fl_Graphics_Driver::default_driver().scale(1); img = cocoa_dr->CGImage_from_window_rect(0, -h, w, h, false); Fl_Graphics_Driver::default_driver().scale(Fl::screen_driver()->scale(win->screen_num())); } return img; } void Fl_Cocoa_Window_Driver::draw_titlebar_to_context(CGContextRef gc, int w, int h) { FLWindow *nswin = fl_xid(pWindow); if ([nswin canBecomeMainWindow]) [nswin makeMainWindow]; [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:nil inMode:NSDefaultRunLoopMode dequeue:NO]; CGImageRef img = capture_window_titlebar(pWindow, this); if (img) { CGContextSaveGState(gc); if (fl_mac_os_version < 100600) clip_to_rounded_corners(gc, w, h); CGContextDrawImage(gc, CGRectMake(0, 0, w, h), img); CGImageRelease(img); CGContextRestoreGState(gc); } } /* Returns the version of the running Mac OS as an int such as 100802 for 10.8.2, and also assigns that value to global fl_mac_os_version. N.B.: macOS "Big Sur" 11.0 can produce 2 different values for fl_mac_os_version: - when SDK 11.0 is used, fl_mac_os_version is set to 110000 (or bigger) - when SDK 10.15 or earlier is used, fl_mac_os_version is set to 101600 That is reported to facilitate life of apps that assumed majorVersion would remain equal to 10 and used only minorVersion to determine what is the running version of macOS. */ int Fl_Darwin_System_Driver::calc_mac_os_version() { if (fl_mac_os_version) return fl_mac_os_version; int M = 0, m = 0, b = 0; NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10 if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) { NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion]; M = (int)version.majorVersion; m = (int)version.minorVersion; b = (int)version.patchVersion; } else #endif { NSDictionary * sv = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]; const char *s = [[sv objectForKey:@"ProductVersion"] UTF8String]; sscanf(s, "%d.%d.%d", &M, &m, &b); } [localPool release]; fl_mac_os_version = M*10000 + m*100 + b; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14 if (fl_mac_os_version >= 101400) views_use_CA = YES; #endif return fl_mac_os_version; } /* Note: `prefs` can be NULL! */ char *Fl_Darwin_System_Driver::preference_rootnode(Fl_Preferences * /*prefs*/, Fl_Preferences::Root root, const char *vendor, const char *application) { static char *filename = 0L; // Allocate this only when we need it, but then keep it allocated. if (!filename) filename = (char*)::calloc(1, FL_PATH_MAX); switch (root&Fl_Preferences::ROOT_MASK) { case Fl_Preferences::SYSTEM: // This is safe, even on machines that use different languages strcpy(filename, "/Library/Preferences"); break; case Fl_Preferences::USER: { // Find the home directory, but return NULL if components were not found. // If we ever port this to iOS: NSHomeDirectory returns tha location of the app! const char *e = ::getenv("HOME"); // if $HOME does not exist, try NSHomeDirectory, the Mac way. NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init]; if ( (e==0L) || (e[0]==0) || (::access(e, F_OK)==-1) ) { NSString *nsHome = NSHomeDirectory(); if (nsHome) e = [nsHome UTF8String]; } // if NSHomeDirectory does not work, try getpwuid(), the Unix way. if ( (e==0L) || (e[0]==0) || (::access(e, F_OK)==-1) ) { struct passwd *pw = getpwuid(getuid()); e = pw->pw_dir; } snprintf(filename, FL_PATH_MAX, "%s/Library/Preferences", e); [localPool release]; break; } } // Make sure that the parameters are not NULL if ( (vendor==0L) || (vendor[0]==0) ) vendor = "unknown"; if ( (application==0L) || (application[0]==0) ) application = "unknown"; // Our C path names for preferences will be: // SYSTEM: "/Library/Preferences/$vendor/$application.prefs" // USER: "/Users/$user/Library/Preferences/$vendor/$application.prefs" snprintf(filename + strlen(filename), FL_PATH_MAX - strlen(filename), "/%s/%s.prefs", vendor, application); return filename; } Fl_Cocoa_Window_Driver::~Fl_Cocoa_Window_Driver() { if (shape_data_) { if (shape_data_->mask) { CGImageRelease(shape_data_->mask); } delete shape_data_; } [icon_image release]; } static NSImage* rgb_to_nsimage(const Fl_RGB_Image *rgb) { if (!rgb) return nil; int ld = rgb->ld(); if (!ld) ld = rgb->data_w() * rgb->d(); NSImage *win_icon = nil; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (fl_mac_os_version >= 101000) { NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:rgb->data_w() pixelsHigh:rgb->data_h() bitsPerSample:8 samplesPerPixel:rgb->d() hasAlpha:!(rgb->d() & 1) isPlanar:NO colorSpaceName:(rgb->d() <= 2 ? NSDeviceWhiteColorSpace : NSDeviceRGBColorSpace) bitmapFormat:NSBitmapFormatAlphaNonpremultiplied bytesPerRow:ld bitsPerPixel:rgb->d() * 8]; // 10.4 memcpy([bitmap bitmapData], rgb->array, rgb->data_h() * ld); win_icon = [[NSImage alloc] initWithSize:NSMakeSize(0, 0)]; [win_icon addRepresentation:bitmap]; [bitmap release]; } #endif return win_icon; } void Fl_Cocoa_Window_Driver::icons(const Fl_RGB_Image *icons[], int count) { [icon_image release]; icon_image = nil; if (count >= 1 && pWindow->border() && pWindow->label() && strlen(pWindow->label())) { ((Fl_RGB_Image*)icons[0])->normalize(); icon_image = rgb_to_nsimage(icons[0]); } } void Fl_Cocoa_Screen_Driver::default_icons(const Fl_RGB_Image *icons[], int count) { [default_icon release]; default_icon = nil; if (count >= 1) { default_icon = rgb_to_nsimage(icons[0]); } } fl_uintptr_t Fl_Cocoa_Window_Driver::os_id() { return [fl_xid(pWindow) windowNumber]; } // Deprecated in 1.4 - only for backward compatibility with 1.3 void Fl::insertion_point_location(int x, int y, int height) { Fl_Cocoa_Screen_Driver::insertion_point_location(x, y, height); } // Deprecated in 1.4 - only for backward compatibility with 1.3 void Fl::reset_marked_text() { Fl_Cocoa_Screen_Driver::reset_marked_text(); } fltk-1.4.3/src/Fl_Window_Driver.cxx0000644000175000017500000002070515004135251017327 0ustar albrechtalbrecht// // A base class for platform specific window handling code // for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include "Fl_Window_Driver.H" #include #include #include #include #include #include "Fl_Screen_Driver.H" extern void fl_throw_focus(Fl_Widget *o); /** Create a new Window Driver. This class must be derived into a new class that manages windows on the target platform. */ Fl_Window_Driver::Fl_Window_Driver(Fl_Window *win) : pWindow(win) { wait_for_expose_value = 0; other_xid = 0; screen_num_ = 0; } Fl_Window_Driver::~Fl_Window_Driver() { // empty } // accessors to Fl_Window private stuff int Fl_Window_Driver::force_position() {return pWindow->force_position(); } void Fl_Window_Driver::force_position(int c) { pWindow->force_position(c); } void Fl_Window_Driver::x(int X) {pWindow->x(X); } void Fl_Window_Driver::y(int Y) {pWindow->y(Y); } int Fl_Window_Driver::fullscreen_screen_top() {return pWindow->fullscreen_screen_top;} int Fl_Window_Driver::fullscreen_screen_bottom() {return pWindow->fullscreen_screen_bottom;} int Fl_Window_Driver::fullscreen_screen_left() {return pWindow->fullscreen_screen_left;} int Fl_Window_Driver::fullscreen_screen_right() {return pWindow->fullscreen_screen_right;} void Fl_Window_Driver::current(Fl_Window *c) {pWindow->current_ = c;} /** Draw the window content. A new driver can add code before or after drawing an individual window. */ void Fl_Window_Driver::draw() { pWindow->draw(); } /** Prepare this window for rendering. A new driver may prepare bitmaps and clipping areas for calls to the graphics driver. */ void Fl_Window_Driver::make_current() { } /** Make the window visible and raise it to the top. */ void Fl_Window_Driver::show() { } /** Change the window title. A new driver should provide an interface to change the title of the window in the title bar. */ void Fl_Window_Driver::label(const char *name, const char *mininame) {} void Fl_Window_Driver::take_focus() { // nothing to do } void Fl_Window_Driver::flush_double() { pWindow->Fl_Window::flush(); } void Fl_Window_Driver::flush_overlay() { pWindow->Fl_Window::flush(); } void Fl_Window_Driver::draw_begin() { // nothing to do } void Fl_Window_Driver::draw_end() { // nothing to do } void Fl_Window_Driver::destroy_double_buffer() { delete other_xid; other_xid = 0; } void Fl_Window_Driver::shape_pixmap_(Fl_Image* pixmap) { Fl_RGB_Image* rgba = new Fl_RGB_Image((Fl_Pixmap*)pixmap); shape_alpha_(rgba, 3); delete rgba; } void Fl_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) { top = left = bottom = right = NULL; } // This function is available for use by platform-specific, Fl_Window_Driver-derived classes int Fl_Window_Driver::hide_common() { pWindow->clear_visible(); if (!shown()) return 1; // remove from the list of windows: Fl_X* ip = Fl_X::flx(pWindow); Fl_X** pp = &Fl_X::first; for (; *pp != ip; pp = &(*pp)->next) if (!*pp) return 1; *pp = ip->next; pWindow->flx_ = 0; // recursively remove any subwindows: for (Fl_X *wi = Fl_X::first; wi;) { Fl_Window* W = wi->w; if (W->window() == pWindow) { W->hide(); W->set_visible(); wi = Fl_X::first; } else wi = wi->next; } if (pWindow == Fl::modal_) { // we are closing the modal window, find next one: Fl_Window* W; for (W = Fl::first_window(); W; W = Fl::next_window(W)) if (W->modal()) break; Fl::modal_ = W; } // Make sure no events are sent to this window: fl_throw_focus(pWindow); pWindow->handle(FL_HIDE); return 0; } void Fl_Window_Driver::use_border() { if (shown()) { pWindow->hide(); // hide and then show to reflect the new state of the window border pWindow->force_position(1); pWindow->show(); } } void Fl_Window_Driver::size_range() { // *FIXME* This should not be necessary! // pWindow->size_range_set = 1; } int Fl_Window_Driver::can_do_overlay() { return 0; } void Fl_Window_Driver::redraw_overlay() { ((Fl_Overlay_Window*)pWindow)->overlay_ = pWindow; pWindow->clear_damage((uchar)(pWindow->damage()|FL_DAMAGE_OVERLAY)); Fl::damage(FL_DAMAGE_CHILD); } void Fl_Window_Driver::flush() { pWindow->flush(); } int Fl_Window_Driver::set_cursor(Fl_Cursor) { return 0; } int Fl_Window_Driver::set_cursor(const Fl_RGB_Image*, int, int) { return 0; } void Fl_Window_Driver::wait_for_expose() { if (!shown()) return; Fl_X *i = Fl_X::flx(pWindow); while (!i || wait_for_expose_value) { Fl::wait(); } } int Fl_Window_Driver::screen_num() { if (pWindow->parent()) { screen_num_ = Fl_Window_Driver::driver(pWindow->top_window())->screen_num(); } return screen_num_ >= 0 ? screen_num_ : 0; } bool Fl_Window_Driver::is_a_rescale_ = false; void Fl_Window_Driver::resize_after_scale_change(int ns, float old_f, float new_f) { screen_num(ns); Fl_Graphics_Driver::default_driver().scale(new_f); int X = int(pWindow->x() * old_f / new_f), Y = int(pWindow->y() * old_f / new_f); int W, H; if (pWindow->fullscreen_active()) { W = int(pWindow->w() * old_f / new_f); H = int(pWindow->h() * old_f / new_f); } else { W = pWindow->w(); H = pWindow->h(); int sX, sY, sW, sH; Fl::screen_xywh(sX, sY, sW, sH, ns); // bounding box of new screen const int d = 5; // make sure new window centre is located in new screen if (X+W/2 < sX) X = sX-W/2+d; else if (X+W/2 > sX+sW-1) X = sX+sW-1-W/2-d; if (Y+H/2 < sY) Y = sY-H/2+d; else if (Y+H/2 > sY+sH-1) Y = sY+sH-1-H/2-d; } size_range(); // adjust the OS-level boundary size values for the window (#880) is_a_rescale_ = true; pWindow->resize(X, Y, W, H); is_a_rescale_ = false; } void Fl_Window_Driver::reposition_menu_window(int x, int y) { if (y != pWindow->y() || x != pWindow->x()) { int ns = pWindow->screen_num(); pWindow->Fl_Widget::position(x, y); Fl::check(); // the window move may erroneously change the window's screen number; reset it if (pWindow->screen_num() != ns) screen_num(ns); } } void Fl_Window_Driver::menu_window_area(int &X, int &Y, int &W, int &H, int nscreen) { int mx, my; Fl_Screen_Driver *scr_driver = Fl::screen_driver(); if (nscreen < 0) nscreen = scr_driver->get_mouse(mx, my); scr_driver->screen_work_area(X, Y, W, H, nscreen); } /** Returns the platform-specific reference of the given window, or NULL if that window isn't shown. \version 1.4.0 */ fl_uintptr_t Fl_Window_Driver::xid(const Fl_Window *win) { Fl_X *flx = win->flx_; return flx ? flx->xid : 0; } /** Returns a pointer to the Fl_Window corresponding to the platform-specific reference \p xid of a shown window. \version 1.4.0 */ Fl_Window *Fl_Window_Driver::find(fl_uintptr_t xid) { Fl_X *window; for (Fl_X **pp = &Fl_X::first; (window = *pp); pp = &window->next) { if (window->xid == xid) { if (window != Fl_X::first && !Fl::modal()) { // make this window be first to speed up searches // this is not done if modal is true to avoid messing up modal stack *pp = window->next; window->next = Fl_X::first; Fl_X::first = window; } return window->w; } } return 0; } void Fl_Window_Driver::maximize() { *no_fullscreen_x() = x(); *no_fullscreen_y() = y(); *no_fullscreen_w() = w(); *no_fullscreen_h() = h(); int X,Y,W,H; Fl::screen_work_area(X, Y, W, H, screen_num()); int width = decorated_w(); int height = decorated_h(); int dw = (width - w()); int dh = (height - h() - dw); bool need_hide_show = maximize_needs_hide(); if (need_hide_show) hide(); // pb may occur in subwindow without this pWindow->resize(X + dw/2, Y + dh + dw/2, W - dw, H - dh - dw); if (need_hide_show) show(); } void Fl_Window_Driver::un_maximize() { pWindow->resize(*no_fullscreen_x(), *no_fullscreen_y(), *no_fullscreen_w(), *no_fullscreen_h()); *no_fullscreen_x() = 0; *no_fullscreen_y() = 0; *no_fullscreen_w() = 0; *no_fullscreen_h() = 0; } /** \} \endcond */ fltk-1.4.3/src/Fl_Gl_Window.cxx0000644000175000017500000004647115004135251016446 0ustar albrechtalbrecht// // OpenGL window code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if HAVE_GL extern int fl_gl_load_plugin; #include #include #include "Fl_Gl_Window_Driver.H" #include "Fl_Window_Driver.H" #include #include #include "drivers/OpenGL/Fl_OpenGL_Display_Device.H" #include "drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H" #include # if (HAVE_DLSYM && HAVE_DLFCN_H) # include # endif // (HAVE_DLSYM && HAVE_DLFCN_H) # ifdef HAVE_GLXGETPROCADDRESSARB # define GLX_GLXEXT_LEGACY # include # endif // HAVE_GLXGETPROCADDRESSARB //////////////////////////////////////////////////////////////// // The symbol SWAP_TYPE defines what is in the back buffer after doing // a glXSwapBuffers(). // The OpenGl documentation says that the contents of the backbuffer // are "undefined" after glXSwapBuffers(). However, if we know what // is in the backbuffers then we can save a good deal of time. For // this reason you can define some symbols to describe what is left in // the back buffer. // Having not found any way to determine this from glx (or wgl) I have // resorted to letting the user specify it with an environment variable, // GL_SWAP_TYPE, it should be equal to one of these symbols: // contents of back buffer after glXSwapBuffers(): #define UNDEFINED 1 // anything #define SWAP 2 // former front buffer (same as unknown) #define COPY 3 // unchanged #define NODAMAGE 4 // unchanged even by X expose() events static char SWAP_TYPE = 0 ; // 0 = determine it from environment variable /** Returns non-zero if the hardware supports the given or current OpenGL mode. */ int Fl_Gl_Window::can_do(int a, const int *b) { return Fl_Gl_Window_Driver::global()->find(a,b) != 0; } void Fl_Gl_Window::show() { int need_after = 0; if (!shown()) { Fl_Window::default_size_range(); if (!g) { g = pGlWindowDriver->find(mode_,alist); if (!g && (mode_ & FL_DOUBLE) == FL_SINGLE) { g = pGlWindowDriver->find(mode_ | FL_DOUBLE,alist); if (g) mode_ |= FL_FAKE_SINGLE; } if (!g) { Fl::error("Insufficient GL support"); return; } } pGlWindowDriver->before_show(need_after); } Fl_Window::show(); if (need_after) pGlWindowDriver->after_show(); } /** The invalidate() method turns off valid() and is equivalent to calling value(0). */ void Fl_Gl_Window::invalidate() { valid(0); context_valid(0); pGlWindowDriver->invalidate(); } int Fl_Gl_Window::mode(int m, const int *a) { if (m == mode_ && a == alist) return 0; return pGlWindowDriver->mode_(m, a); } #define NON_LOCAL_CONTEXT 0x80000000 /** The make_current() method selects the OpenGL context for the widget. It is called automatically prior to the draw() method being called and can also be used to implement feedback and/or selection within the handle() method. */ void Fl_Gl_Window::make_current() { // puts("Fl_Gl_Window::make_current()"); // printf("make_current: context_=%p\n", context_); pGlWindowDriver->make_current_before(); if (!context_) { mode_ &= ~NON_LOCAL_CONTEXT; context_ = pGlWindowDriver->create_gl_context(this, g); valid(0); context_valid(0); } pGlWindowDriver->set_gl_context(this, context_); pGlWindowDriver->make_current_after(); if (mode_ & FL_FAKE_SINGLE) { glDrawBuffer(GL_FRONT); glReadBuffer(GL_FRONT); } current_ = this; } /** Sets the projection so 0,0 is in the lower left of the window and each pixel is 1 unit wide/tall. If you are drawing 2D images, your draw() method may want to call this if valid() is false. */ void Fl_Gl_Window::ortho() { // Alpha NT seems to have a broken OpenGL that does not like negative coords: #ifdef _M_ALPHA glLoadIdentity(); glViewport(0, 0, w(), h()); glOrtho(0, w(), 0, h(), -1, 1); #else GLint v[2]; glGetIntegerv(GL_MAX_VIEWPORT_DIMS, v); glLoadIdentity(); glViewport(pixel_w()-v[0], pixel_h()-v[1], v[0], v[1]); glOrtho(pixel_w()-v[0], pixel_w(), pixel_h()-v[1], pixel_h(), -1, 1); #endif } /** The swap_buffers() method swaps the back and front buffers. It is called automatically after the draw() method is called. */ void Fl_Gl_Window::swap_buffers() { pGlWindowDriver->swap_buffers(); } /** Sets the rate at which the GL windows swaps buffers. This method can be called after the OpenGL context was created, typically within the user overridden `Fl_Gl_Window::draw()` method that will be overridden by the user. \note This method depends highly on the underlying OpenGL contexts and driver implementation. Most driver seem to accept only 0 and 1 to swap buffer asynchronously or in sync with the vertical blank. \param[in] frames set the number of vertical frame blanks between OpenGL buffer swaps */ void Fl_Gl_Window::swap_interval(int frames) { pGlWindowDriver->swap_interval(frames); } /** Gets the rate at which the GL windows swaps buffers. This method can be called after the OpenGL context was created, typically within the user overridden `Fl_Gl_Window::draw()` method that will be overridden by the user. \note This method depends highly on the underlying OpenGL contexts and driver implementation. Some drivers return no information, most drivers don't support intervals with multiple frames and return only 0 or 1. \note Some drivers have the ability to set the swap interval but no way to query it, hence this method may return -1 even though the interval was set correctly. Conversely a return value greater zero does not guarantee that the driver actually honors the setting. \return an integer greater zero if vertical blanking is taken into account when swapping OpenGL buffers \return 0 if the vertical blanking is ignored \return -1 if the information can not be retrieved */ int Fl_Gl_Window::swap_interval() const { return pGlWindowDriver->swap_interval(); } void Fl_Gl_Window::flush() { if (!shown()) return; uchar save_valid = valid_f_ & 1; if (pGlWindowDriver->flush_begin(valid_f_) ) return; make_current(); if (mode_ & FL_DOUBLE) { glDrawBuffer(GL_BACK); if (!SWAP_TYPE) { SWAP_TYPE = pGlWindowDriver->swap_type(); const char* c = fl_getenv("GL_SWAP_TYPE"); if (c) { if (!strcmp(c,"COPY")) SWAP_TYPE = COPY; else if (!strcmp(c, "NODAMAGE")) SWAP_TYPE = NODAMAGE; else if (!strcmp(c, "SWAP")) SWAP_TYPE = SWAP; else SWAP_TYPE = UNDEFINED; } } if (SWAP_TYPE == NODAMAGE) { // don't draw if only overlay damage or expose events: if ((damage()&~(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE)) || !save_valid) draw(); swap_buffers(); } else if (SWAP_TYPE == COPY) { // don't draw if only the overlay is damaged: if (damage() != FL_DAMAGE_OVERLAY || !save_valid) draw(); swap_buffers(); } else if (SWAP_TYPE == SWAP){ damage(FL_DAMAGE_ALL); draw(); if (overlay == this) draw_overlay(); swap_buffers(); } else if (SWAP_TYPE == UNDEFINED){ // SWAP_TYPE == UNDEFINED // If we are faking the overlay, use CopyPixels to act like // SWAP_TYPE == COPY. Otherwise overlay redraw is way too slow. if (overlay == this) { // don't draw if only the overlay is damaged: if (damage1_ || damage() != FL_DAMAGE_OVERLAY || !save_valid) draw(); // we use a separate context for the copy because rasterpos must be 0 // and depth test needs to be off: static GLContext ortho_context = 0; static Fl_Gl_Window* ortho_window = 0; int orthoinit = !ortho_context; if (orthoinit) ortho_context = pGlWindowDriver->create_gl_context(this, g); pGlWindowDriver->set_gl_context(this, ortho_context); if (orthoinit || !save_valid || ortho_window != this) { glDisable(GL_DEPTH_TEST); glReadBuffer(GL_BACK); glDrawBuffer(GL_FRONT); glLoadIdentity(); glViewport(0, 0, pixel_w(), pixel_h()); glOrtho(0, pixel_w(), 0, pixel_h(), -1, 1); glRasterPos2i(0,0); ortho_window = this; } glCopyPixels(0,0,pixel_w(),pixel_h(),GL_COLOR); make_current(); // set current context back to draw overlay damage1_ = 0; } else { damage1_ = damage(); clear_damage(0xff); draw(); swap_buffers(); } } if (overlay==this && SWAP_TYPE != SWAP) { // fake overlay in front buffer glDrawBuffer(GL_FRONT); draw_overlay(); glDrawBuffer(GL_BACK); glFlush(); } } else { // single-buffered context is simpler: draw(); if (overlay == this) draw_overlay(); glFlush(); } valid(1); context_valid(1); } void Fl_Gl_Window::resize(int X,int Y,int W,int H) { // printf("Fl_Gl_Window::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H); // printf("current: x()=%d, y()=%d, w()=%d, h()=%d\n", x(), y(), w(), h()); int is_a_resize = (W != Fl_Widget::w() || H != Fl_Widget::h() || is_a_rescale()); if (is_a_resize) valid(0); pGlWindowDriver->resize(is_a_resize, W, H); Fl_Window::resize(X,Y,W,H); } /** Sets a pointer to the GLContext that this window is using. This is a system-dependent structure, but it is portable to copy the context from one window to another. You can also set it to NULL, which will force FLTK to recreate the context the next time make_current() is called, this is useful for getting around bugs in OpenGL implementations. If destroy_flag is true the context will be destroyed by fltk when the window is destroyed, or when the mode() is changed, or the next time context(x) is called. */ void Fl_Gl_Window::context(GLContext v, int destroy_flag) { if (context_ && !(mode_&NON_LOCAL_CONTEXT)) pGlWindowDriver->delete_gl_context(context_); context_ = v; if (destroy_flag) mode_ &= ~NON_LOCAL_CONTEXT; else mode_ |= NON_LOCAL_CONTEXT; } /** Hides the window and destroys the OpenGL context. */ void Fl_Gl_Window::hide() { context(0); pGlWindowDriver->gl_hide_before(overlay); Fl_Window::hide(); } /** The destructor removes the widget and destroys the OpenGL context associated with it. */ Fl_Gl_Window::~Fl_Gl_Window() { hide(); // delete overlay; this is done by ~Fl_Group delete pGlWindowDriver; } void Fl_Gl_Window::init() { pGlWindowDriver = Fl_Gl_Window_Driver::newGlWindowDriver(this); end(); // we probably don't want any children box(FL_NO_BOX); mode_ = FL_RGB | FL_DEPTH | FL_DOUBLE; alist = 0; context_ = 0; g = 0; overlay = 0; valid_f_ = 0; damage1_ = 0; #if 0 // This breaks resizing on Linux/X11 int H = h(); h(1); // Make sure we actually do something in resize()... resize(x(), y(), w(), H); #endif // 0 } /** You must implement this virtual function if you want to draw into the overlay. The overlay is cleared before this is called. You should draw anything that is not clear using OpenGL. You must use gl_color(i) to choose colors (it allocates them from the colormap using system-specific calls), and remember that you are in an indexed OpenGL mode and drawing anything other than flat-shaded will probably not work. Both this function and Fl_Gl_Window::draw() should check Fl_Gl_Window::valid() and set the same transformation. If you don't your code may not work on other systems. Depending on the OS, and on whether overlays are real or simulated, the OpenGL context may be the same or different between the overlay and main window. */ void Fl_Gl_Window::draw_overlay() {} /** Supports drawing to an Fl_Gl_Window with the FLTK 2D drawing API. \see \ref opengl_with_fltk_widgets */ void Fl_Gl_Window::draw_begin() { if (mode() & FL_OPENGL3) pGlWindowDriver->switch_to_GL1(); damage(FL_DAMAGE_ALL); // always redraw all GL widgets above the GL scene Fl_Surface_Device::push_current( Fl_OpenGL_Display_Device::display_device() ); Fl_OpenGL_Graphics_Driver *drv = (Fl_OpenGL_Graphics_Driver*)Fl_Surface_Device::surface()->driver(); drv->pixels_per_unit_ = pixels_per_unit(); if (!valid()) { glViewport(0, 0, pixel_w(), pixel_h()); valid(1); } glPushAttrib(GL_ALL_ATTRIB_BITS); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0, w(), h(), 0.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glEnable(GL_POINT_SMOOTH); glLineWidth((GLfloat)(drv->pixels_per_unit_*drv->line_width_)); glPointSize((GLfloat)(drv->pixels_per_unit_)); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); if (!pGlWindowDriver->need_scissor()) glDisable(GL_SCISSOR_TEST); } /** To be used as a match for a previous call to Fl_Gl_Window::draw_begin(). \see \ref opengl_with_fltk_widgets */ void Fl_Gl_Window::draw_end() { glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); // GL_ALL_ATTRIB_BITS Fl_Surface_Device::pop_current(); if (mode() & FL_OPENGL3) pGlWindowDriver->switch_back(); } /** Draws the Fl_Gl_Window. You \e \b must subclass Fl_Gl_Window and provide an implementation for draw(). You may also provide an implementation of draw_overlay() if you want to draw into the overlay planes. You can avoid reinitializing the viewport and lights and other things by checking valid() at the start of draw() and only doing the initialization if it is false. The draw() method can only use OpenGL calls. Do not attempt to call X, any of the functions in , or glX directly. Do not call gl_start() or gl_finish(). If double-buffering is enabled in the window, the back and front buffers are swapped after this function is completed. The following pseudo-code shows how to use "if (!valid())" to initialize the viewport: \code void mywindow::draw() { if (!valid()) { glViewport(0,0,pixel_w(),pixel_h()); glFrustum(...) or glOrtho(...) ...other initialization... } if (!context_valid()) { ...load textures, etc. ... } // clear screen glClearColor(...); glClear(...); ... draw your geometry here ... } \endcode Actual example code to clear screen to black and draw a 2D white "X": \code void mywindow::draw() { if (!valid()) { glLoadIdentity(); glViewport(0,0,pixel_w(),pixel_h()); glOrtho(-w(),w(),-h(),h(),-1,1); } // Clear screen glClear(GL_COLOR_BUFFER_BIT); // Draw white 'X' glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINE_STRIP); glVertex2f(w(), h()); glVertex2f(-w(),-h()); glEnd(); glBegin(GL_LINE_STRIP); glVertex2f(w(),-h()); glVertex2f(-w(), h()); glEnd(); } \endcode Regular FLTK widgets can be added as children to the Fl_Gl_Window. To correctly overlay the widgets, Fl_Gl_Window::draw() must be called after rendering the main scene. \code void mywindow::draw() { // draw 3d graphics scene Fl_Gl_Window::draw(); // -- or -- draw_begin(); Fl_Window::draw(); // other 2d drawing calls, overlays, etc. draw_end(); } \endcode */ void Fl_Gl_Window::draw() { draw_begin(); Fl_Window::draw(); draw_end(); } /** Handle some FLTK events as needed. */ int Fl_Gl_Window::handle(int event) { return Fl_Window::handle(event); } // don't remove me! this serves only to force linking of Fl_Gl_Device_Plugin.o int Fl_Gl_Window::gl_plugin_linkage() { return fl_gl_load_plugin; } /** The number of pixels per FLTK unit of length for the window. This method dynamically adjusts its value when the GUI is rescaled or when the window is moved to/from displays of distinct resolutions. This method is useful, e.g., to convert, in a window's handle() method, the FLTK units returned by Fl::event_x() and Fl::event_y() to the pixel units used by the OpenGL source code. \version 1.3.4 */ float Fl_Gl_Window::pixels_per_unit() { return pGlWindowDriver->pixels_per_unit(); } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ int Fl_Gl_Window_Driver::copy = COPY; Fl_Window* Fl_Gl_Window_Driver::cached_window = NULL; float Fl_Gl_Window_Driver::gl_scale = 1; // scaling factor between FLTK and GL drawing units: GL = FLTK * gl_scale // creates a unique, dummy Fl_Gl_Window_Driver object used when no Fl_Gl_Window is around // necessary to support gl_start()/gl_finish() Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::global() { static Fl_Gl_Window_Driver *gwd = newGlWindowDriver(NULL); return gwd; } void Fl_Gl_Window_Driver::invalidate() { if (pWindow->overlay) { ((Fl_Gl_Window*)pWindow->overlay)->valid(0); ((Fl_Gl_Window*)pWindow->overlay)->context_valid(0); } } char Fl_Gl_Window_Driver::swap_type() {return UNDEFINED;} void* Fl_Gl_Window_Driver::GetProcAddress(const char *procName) { #if defined(HAVE_GLXGETPROCADDRESSARB) return (void*)glXGetProcAddressARB((const GLubyte *)procName); #elif (HAVE_DLSYM && HAVE_DLFCN_H) # ifdef RTLD_DEFAULT void *rtld_default = RTLD_DEFAULT; # else static void *rtld_default = dlopen(0, RTLD_LAZY); # endif char symbol[1024]; snprintf(symbol, sizeof(symbol), "_%s", procName); return dlsym(rtld_default, symbol); #endif // HAVE_DLSYM return NULL; } Fl_Font_Descriptor** Fl_Gl_Window_Driver::fontnum_to_fontdescriptor(int fnum) { extern FL_EXPORT Fl_Fontdesc *fl_fonts; return &(fl_fonts[fnum].first); } /* Captures a rectangle of a Fl_Gl_Window and returns it as an RGB image. This is the platform-independent version. Some platforms may override it. */ Fl_RGB_Image* Fl_Gl_Window_Driver::capture_gl_rectangle(int x, int y, int w, int h) { Fl_Gl_Window *glw = pWindow; glw->flush(); // forces a GL redraw, necessary for the glpuzzle demo // Read OpenGL context pixels directly. // For extra safety, save & restore OpenGL states that are changed glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */ glPixelStorei(GL_PACK_ROW_LENGTH, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); // float s = glw->pixels_per_unit(); if (s != 1) { x = int(x * s); y = int(y * s); w = int(w * s); h = int(h * s); } // Read a block of pixels from the frame buffer int mByteWidth = w * 3; mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes uchar *baseAddress = new uchar[mByteWidth * h]; glReadPixels(x, glw->pixel_h() - (y+h), w, h, GL_RGB, GL_UNSIGNED_BYTE, baseAddress); glPopClientAttrib(); // GL gives a bottom-to-top image, convert it to top-to-bottom uchar *tmp = new uchar[mByteWidth]; uchar *p = baseAddress ; uchar *q = baseAddress + (h-1)*mByteWidth; for (int i = 0; i < h/2; i++, p += mByteWidth, q -= mByteWidth) { memcpy(tmp, p, mByteWidth); memcpy(p, q, mByteWidth); memcpy(q, tmp, mByteWidth); } delete[] tmp; Fl_RGB_Image *img = new Fl_RGB_Image(baseAddress, w, h, 3, mByteWidth); img->alloc_array = 1; return img; } /** \} \endcond */ #endif // HAVE_GL fltk-1.4.3/src/Fl_Window_iconize.cxx0000644000175000017500000000125315004135251017531 0ustar albrechtalbrecht// // Window minification code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Window_Driver.H" void Fl_Window::iconize() { if (!shown()) { show_next_window_iconic(1); show(); } else { pWindowDriver->iconize(); } } fltk-1.4.3/src/drivers/0000755000175000017500000000000015004135251015052 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/X11/0000755000175000017500000000000015004135251015423 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/X11/Fl_X11_Window_Driver.H0000644000175000017500000001054715004135251021377 0ustar albrechtalbrecht// // Definition of X11 window driver // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_X11_Window_Driver.H \brief Definition of X11 window driver. */ #ifndef FL_X11_WINDOW_DRIVER_H #define FL_X11_WINDOW_DRIVER_H #include "../../Fl_Window_Driver.H" #include #include // for Cursor #if FLTK_USE_CAIRO typedef struct _cairo cairo_t; #endif // FLTK_USE_CAIRO class Fl_Bitmap; /* Move everything here that manages the native window interface. There is one window driver for each Fl_Window. Window drivers manage window actions such as resizing, events, decoration, fullscreen modes, etc. . All drawing and rendering is managed by the Surface device and the associated graphics driver. - window specific event handling - window types and styles, depth, etc. - decorations ? where do we handle the interface between OpenGL/DirectX and Cocoa/Windows/Glx? */ class Fl_X11_Window_Driver : public Fl_Window_Driver { friend class Fl_X; friend int fl_handle(const XEvent&); private: struct icon_data { const void *legacy_icon; Fl_RGB_Image **icons; int count; } *icon_; struct shape_data_type { int lw_; ///< width of shape image int lh_; ///< height of shape image Fl_Image* shape_; ///< shape image Fl_Bitmap *effective_bitmap_; ///< auxiliary bitmap image } *shape_data_; #if USE_XFT // --- support for screen-specific scaling factors struct type_for_resize_window_between_screens { int screen; bool busy; }; static type_for_resize_window_between_screens data_for_resize_window_between_screens_; #endif // USE_XFT #if FLTK_USE_CAIRO cairo_t *cairo_; #endif // FLTK_USE_CAIRO bool decorated_win_size(int &w, int &h); void combine_mask(); void shape_bitmap_(Fl_Image* b); void shape_alpha_(Fl_Image* img, int offset) FL_OVERRIDE; void flush_double(int erase_overlay); void sendxjunk(); void activate_window(); public: Fl_X11_Window_Driver(Fl_Window*); ~Fl_X11_Window_Driver() FL_OVERRIDE; static inline Fl_X11_Window_Driver* driver(const Fl_Window *w) {return (Fl_X11_Window_Driver*)Fl_Window_Driver::driver(w);} #if USE_XFT static void resize_after_screen_change(void *data); #endif // USE_XFT // --- window data int decorated_w() FL_OVERRIDE; int decorated_h() FL_OVERRIDE; const Fl_Image* shape() FL_OVERRIDE; // --- window management void makeWindow() FL_OVERRIDE; void take_focus() FL_OVERRIDE; void flush_double() FL_OVERRIDE; void flush_overlay() FL_OVERRIDE; void draw_begin() FL_OVERRIDE; void make_current() FL_OVERRIDE; void show() FL_OVERRIDE; void resize(int X,int Y,int W,int H) FL_OVERRIDE; void label(const char *name, const char *mininame) FL_OVERRIDE; void hide() FL_OVERRIDE; void map() FL_OVERRIDE; void unmap() FL_OVERRIDE; void fullscreen_on() FL_OVERRIDE; void fullscreen_off(int X, int Y, int W, int H) FL_OVERRIDE; void maximize() FL_OVERRIDE; void un_maximize() FL_OVERRIDE; void use_border() FL_OVERRIDE; void size_range() FL_OVERRIDE; void iconize() FL_OVERRIDE; void decoration_sizes(int *top, int *left, int *right, int *bottom) FL_OVERRIDE; void show_with_args_begin() FL_OVERRIDE; void show_with_args_end(int argc, char **argv) FL_OVERRIDE; // --- window cursor stuff int set_cursor(Fl_Cursor) FL_OVERRIDE; int set_cursor(const Fl_RGB_Image*, int, int) FL_OVERRIDE; void shape(const Fl_Image* img) FL_OVERRIDE; void icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE; const void *icon() const FL_OVERRIDE; void icon(const void * ic) FL_OVERRIDE; void free_icons() FL_OVERRIDE; void set_icons(); // driver-internal support function void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) FL_OVERRIDE; int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data) FL_OVERRIDE; fl_uintptr_t os_id() FL_OVERRIDE; }; #endif // FL_X11_WINDOW_DRIVER_H fltk-1.4.3/src/drivers/X11/Fl_X11_Window_Driver.cxx0000644000175000017500000004404315004135251022010 0ustar albrechtalbrecht// // Definition of X11 window driver. // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_X11_Window_Driver.H" #include "Fl_X11_Screen_Driver.H" #if FLTK_USE_CAIRO # include # include "../Cairo/Fl_X11_Cairo_Graphics_Driver.H" #else # include "../Xlib/Fl_Xlib_Graphics_Driver.H" #endif // FLTK_USE_CAIRO #include #include #include #include #include #include #include #if HAVE_DLFCN_H #include #endif #define ShapeBounding 0 #define ShapeSet 0 Window fl_window; Fl_X11_Window_Driver::Fl_X11_Window_Driver(Fl_Window *win) : Fl_Window_Driver(win) { icon_ = new icon_data; shape_data_ = NULL; memset(icon_, 0, sizeof(icon_data)); #if USE_XFT screen_num_ = -1; #endif #if FLTK_USE_CAIRO cairo_ = NULL; #endif } Fl_X11_Window_Driver::~Fl_X11_Window_Driver() { if (shape_data_) { delete shape_data_->effective_bitmap_; delete shape_data_; } delete icon_; } // --- private bool Fl_X11_Window_Driver::decorated_win_size(int &w, int &h) { Fl_Window *win = pWindow; w = win->w(); h = win->h(); if (!win->shown() || win->parent() || !win->border() || !win->visible()) return false; Window root, parent, *children; unsigned n = 0; Status status = XQueryTree(fl_display, Fl_X::flx(win)->xid, &root, &parent, &children, &n); if (status != 0 && n) XFree(children); // when compiz is used, root and parent are the same window // and I don't know where to find the window decoration if (status == 0 || root == parent) return false; XWindowAttributes attributes; XGetWindowAttributes(fl_display, parent, &attributes); // sometimes, very wide window borders are reported // ignore them all: XWindowAttributes w_attributes; XGetWindowAttributes(fl_display, Fl_X::flx(win)->xid, &w_attributes); bool true_sides = false; if (attributes.width - w_attributes.width >= 20) { attributes.height -= (attributes.width - w_attributes.width); attributes.width = w_attributes.width; } else if (attributes.width > w_attributes.width) { true_sides = true; } int nscreen = screen_num(); float s = Fl::screen_driver()->scale(nscreen); w = attributes.width / s; h = attributes.height / s; return true_sides; } // --- window data int Fl_X11_Window_Driver::decorated_h() { int w, h; decorated_win_size(w, h); return h; } int Fl_X11_Window_Driver::decorated_w() { int w, h; bool true_sides = decorated_win_size(w, h); return true_sides ? w : this->w(); } void Fl_X11_Window_Driver::take_focus() { Fl_X *i = Fl_X::flx(pWindow); if (!Fl_X11_Screen_Driver::ewmh_supported()) { // Save and restore the current group because 'show()' sets it to NULL. // See issue #515: Fl::focus() changes Fl_Group::current() to null. Fl_Group *cg = Fl_Group::current(); // save current group pWindow->show(); // old WMs, XMapRaised Fl_Group::current(cg); // restore current group } else if (i) { // New WMs use the NETWM attribute: activate_window(); } } void Fl_X11_Window_Driver::draw_begin() { if (shape_data_) { int nscreen = screen_num(); float s = Fl::screen_driver()->scale(nscreen); if (( shape_data_->lw_ != int(s*w()) || shape_data_->lh_ != int(s*h()) ) && shape_data_->shape_) { // size of window has changed since last time combine_mask(); } } } void Fl_X11_Window_Driver::flush_double() { if (!shown()) return; flush_double(0); } void Fl_X11_Window_Driver::flush_double(int erase_overlay) { pWindow->make_current(); // make sure fl_gc is non-zero Fl_X *i = Fl_X::flx(pWindow); if (!other_xid) { other_xid = new Fl_Image_Surface(w(), h(), 1); #if FLTK_USE_CAIRO cairo_ = ((Fl_Cairo_Graphics_Driver*)other_xid->driver())->cr(); #endif pWindow->clear_damage(FL_DAMAGE_ALL); } #if FLTK_USE_CAIRO ((Fl_X11_Cairo_Graphics_Driver*)fl_graphics_driver)->set_cairo(cairo_); #endif if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { fl_clip_region(i->region); i->region = 0; fl_window = other_xid->offscreen(); # if defined(FLTK_HAVE_CAIROEXT) if (Fl::cairo_autolink_context()) Fl::cairo_make_current(pWindow); # endif draw(); fl_window = i->xid; } if (erase_overlay) fl_clip_region(0); int X = 0, Y = 0, W = 0, H = 0; fl_clip_box(0, 0, w(), h(), X, Y, W, H); if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid->offscreen(), X, Y); } void Fl_X11_Window_Driver::flush_overlay() { if (!shown()) return; int erase_overlay = (pWindow->damage()&FL_DAMAGE_OVERLAY) | (overlay() == pWindow); pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY)); flush_double(erase_overlay); if (overlay() == pWindow) { #if FLTK_USE_CAIRO float scale = fl_graphics_driver->scale(); int W = pWindow->w() * scale, H = pWindow->h() * scale; cairo_surface_t *s = cairo_xlib_surface_create(fl_display, Fl_X::flx(pWindow)->xid, fl_visual->visual, W, H); cairo_t *overlay_cairo = cairo_create(s); cairo_surface_destroy(s); cairo_save(overlay_cairo); ((Fl_X11_Cairo_Graphics_Driver*)fl_graphics_driver)->set_cairo(overlay_cairo); #endif pWindow->as_overlay_window()->draw_overlay(); #if FLTK_USE_CAIRO cairo_destroy(overlay_cairo); #endif } } void Fl_X11_Window_Driver::shape_bitmap_(Fl_Image* b) { shape_data_->shape_ = b; } void Fl_X11_Window_Driver::shape_alpha_(Fl_Image* img, int offset) { int i, j, d = img->d(), w = img->w(), h = img->h(), bytesperrow = (w+7)/8; unsigned u; uchar byte, onebit; // build an Fl_Bitmap covering the non-fully transparent/black part of the image const uchar* bits = new uchar[h*bytesperrow]; // to store the bitmap const uchar* alpha = (const uchar*)*img->data() + offset; // points to alpha value of rgba pixels for (i = 0; i < h; i++) { uchar *p = (uchar*)bits + i * bytesperrow; byte = 0; onebit = 1; for (j = 0; j < w; j++) { if (d == 3) { u = *alpha; u += *(alpha+1); u += *(alpha+2); } else u = *alpha; if (u > 0) { // if the pixel is not fully transparent/black byte |= onebit; // turn on the corresponding bit of the bitmap } onebit = onebit << 1; // move the single set bit one position to the left if (onebit == 0 || j == w-1) { onebit = 1; *p++ = byte; // store in bitmap one pack of bits byte = 0; } alpha += d; // point to alpha value of next pixel } } Fl_Bitmap* bitmap = new Fl_Bitmap(bits, w, h); bitmap->alloc_array = 1; shape_bitmap_(bitmap); shape_data_->effective_bitmap_ = bitmap; shape_data_->shape_ = img; } void Fl_X11_Window_Driver::shape(const Fl_Image* img) { if (shape_data_) { if (shape_data_->effective_bitmap_) { delete shape_data_->effective_bitmap_; } } else { shape_data_ = new shape_data_type; } memset(shape_data_, 0, sizeof(shape_data_type)); pWindow->border(false); int d = img->d(); if (d && img->count() >= 2) { shape_pixmap_((Fl_Image*)img); shape_data_->shape_ = (Fl_Image*)img; } else if (d == 0) shape_bitmap_((Fl_Image*)img); else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1); else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0); } void Fl_X11_Window_Driver::combine_mask() { typedef void (*XShapeCombineMask_type)(Display*, int, int, int, int, Pixmap, int); static XShapeCombineMask_type XShapeCombineMask_f = NULL; static int beenhere = 0; typedef Bool (*XShapeQueryExtension_type)(Display*, int*, int*); if (!beenhere) { beenhere = 1; #if HAVE_DLSYM && HAVE_DLFCN_H fl_open_display(); void *handle = dlopen(NULL, RTLD_LAZY); // search symbols in executable XShapeQueryExtension_type XShapeQueryExtension_f = (XShapeQueryExtension_type)dlsym(handle, "XShapeQueryExtension"); XShapeCombineMask_f = (XShapeCombineMask_type)dlsym(handle, "XShapeCombineMask"); // make sure that the X server has the SHAPE extension int error_base, shapeEventBase; if ( !( XShapeQueryExtension_f && XShapeCombineMask_f && XShapeQueryExtension_f(fl_display, &shapeEventBase, &error_base) ) ) XShapeCombineMask_f = NULL; #endif } if (!XShapeCombineMask_f) return; float s = Fl::screen_driver()->scale(screen_num()); shape_data_->lw_ = w()*s; shape_data_->lh_ = h()*s; Fl_Image* temp = shape_data_->effective_bitmap_ ? shape_data_->effective_bitmap_ : shape_data_->shape_; temp = temp->copy(shape_data_->lw_, shape_data_->lh_); Pixmap pbitmap = XCreateBitmapFromData(fl_display, fl_xid(pWindow), (const char*)*temp->data(), temp->w(), temp->h()); XShapeCombineMask_f(fl_display, fl_xid(pWindow), ShapeBounding, 0, 0, pbitmap, ShapeSet); if (pbitmap != None) XFreePixmap(fl_display, pbitmap); delete temp; } void Fl_X11_Window_Driver::icons(const Fl_RGB_Image *icons[], int count) { free_icons(); if (count > 0) { icon_->icons = new Fl_RGB_Image*[count]; icon_->count = count; // FIXME: Fl_RGB_Image lacks const modifiers on methods for (int i = 0;i < count;i++) { icon_->icons[i] = (Fl_RGB_Image*)((Fl_RGB_Image*)icons[i])->copy(); icon_->icons[i]->normalize(); } } if (Fl_X::flx(pWindow)) set_icons(); } const void *Fl_X11_Window_Driver::icon() const { return icon_->legacy_icon; } void Fl_X11_Window_Driver::icon(const void * ic) { free_icons(); icon_->legacy_icon = ic; } void Fl_X11_Window_Driver::free_icons() { int i; icon_->legacy_icon = 0L; if (icon_->icons) { for (i = 0;i < icon_->count;i++) delete icon_->icons[i]; delete [] icon_->icons; icon_->icons = 0L; } icon_->count = 0; } /* Returns images of the captures of the window title-bar, and the left, bottom and right window borders (or NULL if a particular border is absent). Returned images can be deleted after use. Their depth and size may be platform-dependent. The top and bottom images extend from left of the left border to right of the right border. This function exploits a feature of Fl_X11_Screen_Driver::read_win_rectangle() which, when called with negative 3rd argument, captures the window decoration. Other requirement to capture the window decoration: fl_window is the parent window of the top window */ void Fl_X11_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) { top = left = bottom = right = NULL; if (pWindow->decorated_h() == h()) return; Window from = fl_window; Window root, parent, *children, child_win, xid = fl_xid(pWindow); unsigned n = 0; int do_it; int wsides, htop, ww, hh; do_it = (XQueryTree(fl_display, xid, &root, &parent, &children, &n) != 0 && XTranslateCoordinates(fl_display, xid, parent, 0, 0, &wsides, &htop, &child_win) == True); if (n) XFree(children); if (!do_it) return; bool true_sides = Fl_X11_Window_Driver::decorated_win_size(ww, hh); float s = Fl::screen_driver()->scale(screen_num()); if (true_sides) { XWindowAttributes attributes; XGetWindowAttributes(fl_display, parent, &attributes); ww = attributes.width; hh = attributes.height; } else { ww *= s; hh *= s; } if (!true_sides) htop -= wsides; fl_window = parent; if (htop) { if (true_sides) { top = Fl::screen_driver()->read_win_rectangle(1, 1, -(ww-2), hh-2, pWindow); if (top) top->scale(decorated_w(), decorated_h(), 0, 1); } else { top = Fl::screen_driver()->read_win_rectangle(wsides, wsides, -(ww-1), htop, pWindow); if (top) top->scale(w(), htop / s, 0, 1); } } fl_window = from; } // make X drawing go into this window (called by subclass flush() impl.) void Fl_X11_Window_Driver::make_current() { if (!shown()) { fl_alert("Fl_Window::make_current(), but window is not shown()."); Fl::fatal("Fl_Window::make_current(), but window is not shown()."); } fl_window = fl_xid(pWindow); fl_graphics_driver->clip_region(0); #if FLTK_USE_CAIRO float scale = Fl::screen_scale(screen_num()); // get the screen scaling factor if (!pWindow->as_double_window()) { if (!cairo_) { int W = pWindow->w() * scale, H = pWindow->h() * scale; cairo_surface_t *s = cairo_xlib_surface_create(fl_display, fl_window, fl_visual->visual, W, H); cairo_ = cairo_create(s); cairo_surface_destroy(s); cairo_save(cairo_); } ((Fl_X11_Cairo_Graphics_Driver*)fl_graphics_driver)->set_cairo(cairo_); } fl_graphics_driver->scale(scale); #elif USE_XFT ((Fl_Xlib_Graphics_Driver*)fl_graphics_driver)->scale(Fl::screen_driver()->scale(screen_num())); #endif #ifdef FLTK_HAVE_CAIROEXT // update the cairo_t context if (Fl::cairo_autolink_context()) Fl::cairo_make_current(pWindow); #endif } void Fl_X11_Window_Driver::hide() { Fl_X* ip = Fl_X::flx(pWindow); if (hide_common()) return; if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region); # if USE_XFT && ! FLTK_USE_CAIRO Fl_Xlib_Graphics_Driver::destroy_xft_draw(ip->xid); screen_num_ = -1; # endif # if FLTK_USE_CAIRO if (cairo_ && !pWindow->as_double_window()) { cairo_destroy(cairo_); cairo_ = NULL; } # endif // this test makes sure ip->xid has not been destroyed already if (ip->xid) XDestroyWindow(fl_display, ip->xid); delete ip; } void Fl_X11_Window_Driver::map() { XMapWindow(fl_display, fl_xid(pWindow)); // extra map calls are harmless } void Fl_X11_Window_Driver::unmap() { XUnmapWindow(fl_display, fl_xid(pWindow)); } // Turning the border on/off by changing the motif_wm_hints property // works on Irix 4DWM. Does not appear to work for any other window // manager. Fullscreen still works on some window managers (fvwm is one) // because they allow the border to be placed off-screen. // Unfortunately most X window managers ignore changes to the border // and refuse to position the border off-screen, so attempting to make // the window full screen will lose the size of the border off the // bottom and right. void Fl_X11_Window_Driver::use_border() { if (shown()) sendxjunk(); } void Fl_X11_Window_Driver::size_range() { if (shown()) sendxjunk(); } void Fl_X11_Window_Driver::iconize() { XIconifyWindow(fl_display, fl_xid(pWindow), fl_screen); } void Fl_X11_Window_Driver::decoration_sizes(int *top, int *left, int *right, int *bottom) { // Ensure border is on screen; these values are generic enough // to work with many window managers, and are based on KDE defaults. *top = 20; *left = 4; *right = 4; *bottom = 8; } void Fl_X11_Window_Driver::show_with_args_begin() { // Get defaults for drag-n-drop and focus... const char *key = 0, *val; if (Fl::first_window()) key = Fl::first_window()->xclass(); if (!key) key = "fltk"; val = XGetDefault(fl_display, key, "dndTextOps"); if (val) Fl::dnd_text_ops(strcasecmp(val, "true") == 0 || strcasecmp(val, "on") == 0 || strcasecmp(val, "yes") == 0); val = XGetDefault(fl_display, key, "tooltips"); if (val) Fl_Tooltip::enable(strcasecmp(val, "true") == 0 || strcasecmp(val, "on") == 0 || strcasecmp(val, "yes") == 0); val = XGetDefault(fl_display, key, "visibleFocus"); if (val) Fl::visible_focus(strcasecmp(val, "true") == 0 || strcasecmp(val, "on") == 0 || strcasecmp(val, "yes") == 0); } void Fl_X11_Window_Driver::show_with_args_end(int argc, char **argv) { if (argc) { // set the command string, used by state-saving window managers: int j; int n=0; for (j=0; jscale(screen_num()); XCopyArea(fl_display, fl_window, fl_window, (GC)fl_graphics_driver->gc(), int(src_x*s), int(src_y*s), int(src_w*s), int(src_h*s), int(dest_x*s), int(dest_y*s)); // we have to sync the display and get the GraphicsExpose events! (sigh) for (;;) { XEvent e; XWindowEvent(fl_display, fl_window, ExposureMask, &e); if (e.type == NoExpose) break; // otherwise assume it is a GraphicsExpose event: draw_area(data, e.xexpose.x, e.xexpose.y, e.xexpose.width, e.xexpose.height); if (!e.xgraphicsexpose.count) break; } return 0; } void Fl_X11_Window_Driver::makeWindow() { Fl_X::make_xid(pWindow, fl_visual, fl_colormap); } const Fl_Image* Fl_X11_Window_Driver::shape() { return shape_data_ ? shape_data_->shape_ : NULL; } Fl_Window *fl_x11_find(Window xid) { return Fl_Window_Driver::find((fl_uintptr_t)xid); } Window fl_x11_xid(const Fl_Window *win) { return (Window)Fl_Window_Driver::xid(win); } #if USE_XFT Fl_X11_Window_Driver::type_for_resize_window_between_screens Fl_X11_Window_Driver::data_for_resize_window_between_screens_ = {0, false}; void Fl_X11_Window_Driver::resize_after_screen_change(void *data) { Fl_Window *win = (Fl_Window*)data; float f = Fl::screen_driver()->scale(data_for_resize_window_between_screens_.screen); Fl_Window_Driver::driver(win)->resize_after_scale_change(data_for_resize_window_between_screens_.screen, f, f); data_for_resize_window_between_screens_.busy = false; } #endif // USE_XFT fl_uintptr_t Fl_X11_Window_Driver::os_id() { return fl_xid(pWindow); } fltk-1.4.3/src/drivers/X11/Fl_X11_Screen_Driver.cxx0000644000175000017500000010565615004135251021770 0ustar albrechtalbrecht// // Definition of X11 Screen interface // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_X11_Screen_Driver.H" #include "Fl_X11_Window_Driver.H" #include "../Posix/Fl_Posix_System_Driver.H" #include #include #include #include #include #include #include #include #include "../../Fl_Timeout.h" #include "../../flstring.h" #if HAVE_XINERAMA # include #endif # include # ifdef __sgi # include # else # include # endif // __sgi #ifdef DEBUG # include #endif // DEBUG extern Atom fl_NET_WORKAREA; // these are set by Fl::args() and FL_OVERRIDE any system colors: from Fl_get_system_colors.cxx extern const char *fl_fg; extern const char *fl_bg; extern const char *fl_bg2; // end of extern additions workaround #if !USE_XFT extern char *fl_get_font_xfld(int fnum, int size); #endif XIM Fl_X11_Screen_Driver::xim_im = 0; XIC Fl_X11_Screen_Driver::xim_ic = 0; int Fl_X11_Screen_Driver::fl_spotf = -1; int Fl_X11_Screen_Driver::fl_spots = -1; XRectangle Fl_X11_Screen_Driver::fl_spot; char Fl_X11_Screen_Driver::fl_is_over_the_spot = 0; Window Fl_X11_Screen_Driver::xim_win = 0; Fl_X11_Screen_Driver::Fl_X11_Screen_Driver() : Fl_Unix_Screen_Driver() { // X11 screen driver does not use a key table key_table = NULL; key_table_size = 0; } void Fl_X11_Screen_Driver::display(const char *d) { if (!d) return; // Issue #937: // setenv() is available since POSIX.1-2001 // https://pubs.opengroup.org/onlinepubs/009604499/functions/setenv.html #if HAVE_SETENV setenv("DISPLAY", d, 1); #else // HAVE_SETENV // Use putenv() for old systems (similar to FLTK 1.3) static char e[1024]; strcpy(e, "DISPLAY="); strlcat(e, d, sizeof(e)); for (char *c = e + 8; *c != ':'; c++) { if (!*c) { strlcat(e,":0.0",sizeof(e)); break; } } putenv(e); #endif // HAVE_SETENV } void fl_x11_use_display(Display *d) { fl_display = d; } int Fl_X11_Screen_Driver::XParseGeometry(const char* string, int* x, int* y, unsigned int* width, unsigned int* height) { return ::XParseGeometry(string, x, y, width, height); } void Fl_X11_Screen_Driver::own_colormap() { fl_open_display(); #if USE_COLORMAP switch (fl_visual->c_class) { case GrayScale : case PseudoColor : case DirectColor : break; default: return; // don't do anything for non-colormapped visuals } int i; XColor colors[16]; // Get the first 16 colors from the default colormap... for (i = 0; i < 16; i ++) colors[i].pixel = i; XQueryColors(fl_display, fl_colormap, colors, 16); // Create a new colormap... fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen), fl_visual->visual, AllocNone); // Copy those first 16 colors to our own colormap: for (i = 0; i < 16; i ++) XAllocColor(fl_display, fl_colormap, colors + i); #endif // USE_COLORMAP } const char *Fl_X11_Screen_Driver::shortcut_add_key_name(unsigned key, char *p, char *buf, const char **eom) { const char* q; if (key == FL_Enter || key == '\r') q = "Enter"; // don't use Xlib's "Return": else if (key > 32 && key < 0x100) q = 0; else q = XKeysymToString(key); if (!q) { p += fl_utf8encode(fl_toupper(key), p); *p = 0; return buf; } if (p > buf) { strcpy(p,q); return buf; } else { if (eom) *eom = q; return q; } } static int test_visual(XVisualInfo& v, int flags) { if (v.screen != fl_screen) return 0; #if USE_COLORMAP if (!(flags & FL_INDEX)) { if (v.c_class != StaticColor && v.c_class != TrueColor) return 0; if (v.depth <= 8) return 0; // fltk will work better in colormap mode } if (flags & FL_RGB8) { if (v.depth < 24) return 0; } // for now, fltk does not like colormaps of more than 8 bits: if ((v.c_class&1) && v.depth > 8) return 0; #else // simpler if we can't use colormapped visuals at all: if (v.c_class != StaticColor && v.c_class != TrueColor) return 0; #endif return 1; } int Fl_X11_Screen_Driver::visual(int flags) { if (flags & FL_DOUBLE) return 0; open_display(); // always use default if possible: if (test_visual(*fl_visual, flags)) return 1; // get all the visuals: XVisualInfo vTemplate; int num; XVisualInfo *visualList = XGetVisualInfo(fl_display, 0, &vTemplate, &num); // find all matches, use the one with greatest depth: XVisualInfo *found = 0; for (int i=0; idepth < visualList[i].depth) found = &visualList[i]; } if (!found) {XFree((void*)visualList); return 0;} fl_visual = found; fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen), fl_visual->visual, AllocNone); return 1; } static int fl_workarea_xywh[4] = { -1, -1, -1, -1 }; void Fl_X11_Screen_Driver::init_workarea() { Atom actual; unsigned long count, remaining; int format; long *xywh = 0; /* If there are several screens, the _NET_WORKAREA property does not give the work area of the main screen, but that of all screens together. Therefore, we use this property only when there is a single screen, and fall back to the main screen full area when there are several screens. */ if (Fl::screen_count() > 1 || XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen), fl_NET_WORKAREA, 0, 4, False, XA_CARDINAL, &actual, &format, &count, &remaining, (unsigned char **)&xywh) || !xywh || !xywh[2] || !xywh[3]) { fl_workarea_xywh[0] = screens[0].x_org; fl_workarea_xywh[1] = screens[0].y_org; fl_workarea_xywh[2] = screens[0].width; fl_workarea_xywh[3] = screens[0].height; } else { fl_workarea_xywh[0] = xywh[0]; fl_workarea_xywh[1] = xywh[1]; fl_workarea_xywh[2] = xywh[2]; fl_workarea_xywh[3] = xywh[3]; } if ( xywh ) { XFree(xywh); xywh = 0; } } int Fl_X11_Screen_Driver::x() { if (!fl_display) open_display(); return fl_workarea_xywh[0] #if USE_XFT / screens[0].scale #endif ; } int Fl_X11_Screen_Driver::y() { if (!fl_display) open_display(); return fl_workarea_xywh[1] #if USE_XFT / screens[0].scale #endif ; } int Fl_X11_Screen_Driver::w() { if (!fl_display) open_display(); return fl_workarea_xywh[2] #if USE_XFT / screens[0].scale #endif ; } int Fl_X11_Screen_Driver::h() { if (!fl_display) open_display(); return fl_workarea_xywh[3] #if USE_XFT / screens[0].scale #endif ; } #define USE_XRANDR (HAVE_DLSYM && HAVE_DLFCN_H) // means attempt to dynamically load libXrandr.so #if USE_XRANDR #include typedef struct { int width, height; int mwidth, mheight; } XRRScreenSize; typedef XRRScreenSize* (*XRRSizes_type)(Display *dpy, int screen, int *nsizes); #endif // USE_XRANDR void Fl_X11_Screen_Driver::init() { if (!fl_display) open_display(); int dpi_by_randr = 0; float dpih = 0.0f, dpiv = 0.0f; #if USE_XRANDR static XRRSizes_type XRRSizes_f = NULL; if (!XRRSizes_f) { XRRSizes_f = (XRRSizes_type)Fl_Posix_System_Driver::dlopen_or_dlsym("libXrandr", "XRRSizes"); } if (XRRSizes_f) { int nscreens; XRRScreenSize *ssize = XRRSizes_f(fl_display, fl_screen, &nscreens); //for (int i=0; i 0) { // Note: XRRSizes() *may* return nscreens == 0, see docs int mm = ssize[0].mwidth; dpih = mm ? ssize[0].width*25.4f/mm : 0.0f; mm = ssize[0].mheight; dpiv = mm ? ssize[0].height*25.4f/mm : 0.0f; dpi_by_randr = 1; } } #endif // USE_XRANDR #if HAVE_XINERAMA if (XineramaIsActive(fl_display)) { XineramaScreenInfo *xsi = XineramaQueryScreens(fl_display, &num_screens); if (num_screens > MAX_SCREENS) num_screens = MAX_SCREENS; /* There's no way to use different DPI for different Xinerama screens. */ for (int i=0; i MAX_SCREENS) num_screens = MAX_SCREENS; for (int i=0; i= num_screens) n = 0; if (n == 0) { // for the main screen, these return the work area X = Fl::x(); Y = Fl::y(); W = Fl::w(); H = Fl::h(); } else { // for other screens, work area is full screen, screen_xywh(X, Y, W, H, n); } } void Fl_X11_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n) { if (num_screens < 0) init(); if ((n < 0) || (n >= num_screens)) n = 0; if (num_screens > 0) { #if USE_XFT float s = screens[n].scale; #else float s = 1; #endif X = screens[n].x_org / s; Y = screens[n].y_org / s; W = screens[n].width / s; H = screens[n].height / s; } } void Fl_X11_Screen_Driver::screen_dpi(float &h, float &v, int n) { if (num_screens < 0) init(); h = v = 0.0f; if (n >= 0 && n < num_screens) { h = dpi[n][0]; v = dpi[n][1]; } } // Implements fl_beep(). See documentation in src/fl_ask.cxx. void Fl_X11_Screen_Driver::beep(int type) { int vol; switch (type) { case FL_BEEP_ERROR : vol = 100; break; case FL_BEEP_DEFAULT : default : vol = 0; break; } if (!fl_display) open_display(); XBell(fl_display, vol); } void Fl_X11_Screen_Driver::flush() { if (fl_display) XFlush(fl_display); } extern void fl_fix_focus(); // in Fl.cxx void Fl_X11_Screen_Driver::grab(Fl_Window* win) { const char *p; static bool using_kde = ( p = getenv("XDG_CURRENT_DESKTOP") , (p && (strcmp(p, "KDE") == 0)) ); Fl_Window *fullscreen_win = NULL; for (Fl_Window *W = Fl::first_window(); W; W = Fl::next_window(W)) { if (W->fullscreen_active()) { fullscreen_win = W; break; } } if (win) { if (!Fl::grab()) { Window xid = fullscreen_win ? fl_xid(fullscreen_win) : fl_xid(Fl::first_window()); XGrabPointer(fl_display, xid, 1, ButtonPressMask|ButtonReleaseMask| ButtonMotionMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, 0, fl_event_time); if (!using_kde) { // grabbing tends to stick with KDE (#904) XGrabKeyboard(fl_display, xid, 1, GrabModeAsync, GrabModeAsync, fl_event_time); } } Fl::grab_ = win; // FIXME: Fl::grab_ "should be private", but we need // a way to *set* the variable from the driver! } else { if (Fl::grab()) { // We must keep the grab in the non-EWMH fullscreen case if (!fullscreen_win || ewmh_supported()) { XUngrabKeyboard(fl_display, fl_event_time); } XUngrabPointer(fl_display, fl_event_time); // this flush is done in case the picked menu item goes into // an infinite loop, so we don't leave the X server locked up: XFlush(fl_display); Fl::grab_ = 0; // FIXME: Fl::grab_ "should be private", but we need // a way to *set* the variable from the driver! fl_fix_focus(); } } } // Wrapper around XParseColor... int Fl_X11_Screen_Driver::parse_color(const char* p, uchar& r, uchar& g, uchar& b) { // before w open the display, we try interpreting this ourselves // "None" will ultimately always return 0 if ( (fl_ascii_strcasecmp(p, "none") == 0) || (fl_ascii_strcasecmp(p, "#transparent") == 0) ) return 0; // if it's #rgb, we can do that ourselves if (Fl_Screen_Driver::parse_color(p, r, g, b)) return 1; // it's neither "None" nor hex, so finally open the diplay and ask X11 XColor x; if (!fl_display) open_display(); if (XParseColor(fl_display, fl_colormap, p, &x)) { r = (uchar)(x.red>>8); g = (uchar)(x.green>>8); b = (uchar)(x.blue>>8); return 1; } else return 0; } // Read colors that KDE writes to the xrdb database. // XGetDefault does not do the expected thing: it does not like // periods in either word. Therefore it cannot match class.Text.background. // However *.Text.background is matched by pretending the program is "Text". // But this will also match *.background if there is no *.Text.background // entry, requiring users to put in both (unless they want the text fields // the same color as the windows). static void set_selection_color(uchar r, uchar g, uchar b) { Fl::set_color(FL_SELECTION_COLOR,r,g,b); } static void getsyscolor(const char *key1, const char* key2, const char *arg, const char *defarg, void (*func)(uchar,uchar,uchar)) { if (!arg) { arg = XGetDefault(fl_display, key1, key2); if (!arg) arg = defarg; } XColor x; if (!XParseColor(fl_display, fl_colormap, arg, &x)) Fl::error("Unknown color: %s", arg); else func(x.red>>8, x.green>>8, x.blue>>8); } void Fl_X11_Screen_Driver::get_system_colors() { open_display(); const char* key1 = 0; if (Fl::first_window()) key1 = Fl::first_window()->xclass(); if (!key1) key1 = "fltk"; if (!bg2_set) getsyscolor("Text","background", fl_bg2, "#ffffff", Fl::background2); if (!fg_set) getsyscolor(key1, "foreground", fl_fg, "#000000", Fl::foreground); if (!bg_set) getsyscolor(key1, "background", fl_bg, "#c0c0c0", Fl::background); getsyscolor("Text", "selectBackground", 0, "#000080", set_selection_color); } const char *Fl_X11_Screen_Driver::get_system_scheme() { const char *s = 0L; if ((s = fl_getenv("FLTK_SCHEME")) == NULL) { const char* key = 0; if (Fl::first_window()) key = Fl::first_window()->xclass(); if (!key) key = "fltk"; open_display(); s = XGetDefault(fl_display, key, "scheme"); } return s; } int Fl_X11_Screen_Driver::compose(int& del) { int condition; unsigned char ascii = (unsigned char)Fl::e_text[0]; condition = (Fl::e_state & (FL_ALT | FL_META | FL_CTRL)) && !(ascii & 128) ; if (condition) { del = 0; return 0;} // this stuff is to be treated as a function key del = Fl::compose_state; Fl::compose_state = 0; // Only insert non-control characters: if ( (!Fl::compose_state) && ! (ascii & ~31 && ascii!=127)) { return 0; } return 1; } void Fl_X11_Screen_Driver::compose_reset() { Fl::compose_state = 0; if (xim_ic) XmbResetIC(xim_ic); } int Fl_X11_Screen_Driver::text_display_can_leak() const { #if USE_XFT return 1; #else return 0; #endif } // // 'fl_subimage_offsets()' - Calculate subimage offsets for an axis static inline int fl_subimage_offsets(int a, int aw, int b, int bw, int &obw) { int off; int ob; if (b >= a) { ob = b; off = 0; } else { ob = a; off = a - b; } bw -= off; if (ob + bw <= a + aw) { obw = bw; } else { obw = (a + aw) - ob; } return off; } // this handler will catch and ignore exceptions during XGetImage // to avoid an application crash extern "C" { static int xgetimageerrhandler(Display *display, XErrorEvent *error) { return 0; } } // When capturing window decoration, w is negative and X,Y,w and h are in pixels; // otherwise X,Y,w and h are in FLTK units. // Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins) { XImage *image; // Captured image int i, maxindex; // Looping vars int x, y; // Current X & Y in image unsigned char *line, // Array to hold image row *line_ptr; // Pointer to current line image unsigned char *pixel; // Current color value XColor colors[4096]; // Colors from the colormap... unsigned char cvals[4096][3]; // Color values from the colormap... unsigned index_mask, index_shift, red_mask, red_shift, green_mask, green_shift, blue_mask, blue_shift; // // Under X11 we have the option of the XGetImage() interface or SGI's // ReadDisplay extension which does all of the really hard work for // us... // int allow_outside = w < 0; // negative w allows negative X or Y, that is, window frame if (w < 0) w = - w; Window xid = (win && !allow_outside ? fl_xid(win) : fl_window); float s = allow_outside ? 1 : Fl_Surface_Device::surface()->driver()->scale(); int Xs = Fl_Scalable_Graphics_Driver::floor(X, s); int Ys = Fl_Scalable_Graphics_Driver::floor(Y, s); int ws = Fl_Scalable_Graphics_Driver::floor(X+w, s) - Xs; int hs = Fl_Scalable_Graphics_Driver::floor(Y+h, s) - Ys; # ifdef __sgi if (XReadDisplayQueryExtension(fl_display, &i, &i)) { image = XReadDisplay(fl_display, xid, Xs, Ys, ws, hs, 0, NULL); } else # else image = 0; # endif // __sgi if (!image) { // fetch absolute coordinates int dx = 0, dy = 0, sx = 0, sy = 0, sw = 0, sh = 0; Window child_win; if (win) { XTranslateCoordinates(fl_display, xid, RootWindow(fl_display, fl_screen), Xs, Ys, &dx, &dy, &child_win); // screen dimensions int ns = Fl_Window_Driver::driver(win)->screen_num(); sx = screens[ns].x_org; sy = screens[ns].y_org; sw = screens[ns].width; sh = screens[ns].height; } #if ! HAVE_XRENDER if (win && !allow_outside && int(s) != s) { ws = (w+1) * s; // approximates what Fl_Graphics_Driver::cache_size() does hs = (h+1) * s; } #endif if (!allow_outside && win && Xs + ws > int(win->w()*s)) ws = win->w()*s - Xs; if (!allow_outside && win && Ys + hs > int(win->h()*s)) hs = win->h()*s - Ys; if (ws < 1) ws = 1; if (hs < 1) hs = 1; if (!win || (dx >= sx && dy >= sy && dx + ws <= sx+sw && dy + hs <= sy+sh) ) { // the image is fully contained, we can use the traditional method // however, if the window is obscured etc. the function will still fail. Make sure we // catch the error and continue, otherwise an exception will be thrown. XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler); image = XGetImage(fl_display, xid, Xs, Ys, ws, hs, AllPlanes, ZPixmap); XSetErrorHandler(old_handler); } else { // image is crossing borders, determine visible region int nw, nh, noffx, noffy; noffx = fl_subimage_offsets(sx, sw, dx, ws, nw); noffy = fl_subimage_offsets(sy, sh, dy, hs, nh); if (nw <= 0 || nh <= 0) return 0; // allocate the image int bpp = fl_visual->depth + ((fl_visual->depth / 8) % 2) * 8; char* buf = (char*)malloc((bpp / 8) * ws * hs); image = XCreateImage(fl_display, fl_visual->visual, fl_visual->depth, ZPixmap, 0, buf, ws, hs, bpp, 0); if (!image) { if (buf) free(buf); return 0; } XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler); XImage *subimg = XGetSubImage(fl_display, xid, Xs + noffx, Ys + noffy, nw, nh, AllPlanes, ZPixmap, image, noffx, noffy); XSetErrorHandler(old_handler); if (!subimg) { XDestroyImage(image); return 0; } } } if (!image) return 0; if (s != 1) { w = ws; h = hs; } #ifdef DEBUG printf("width = %d\n", image->width); printf("height = %d\n", image->height); printf("xoffset = %d\n", image->xoffset); printf("format = %d\n", image->format); printf("data = %p\n", image->data); printf("byte_order = %d\n", image->byte_order); printf("bitmap_unit = %d\n", image->bitmap_unit); printf("bitmap_bit_order = %d\n", image->bitmap_bit_order); printf("bitmap_pad = %d\n", image->bitmap_pad); printf("depth = %d\n", image->depth); printf("bytes_per_line = %d\n", image->bytes_per_line); printf("bits_per_pixel = %d\n", image->bits_per_pixel); printf("red_mask = %08x\n", image->red_mask); printf("green_mask = %08x\n", image->green_mask); printf("blue_mask = %08x\n", image->blue_mask); printf("map_entries = %d\n", fl_visual->visual->map_entries); #endif // DEBUG const int d = 3; // Depth of image uchar *p = NULL; // Allocate the image data array as needed... p = new uchar[w * h * d]; // Initialize the default colors/alpha in the whole image... memset(p, 0, w * h * d); // Check that we have valid mask/shift values... if (!image->red_mask && image->bits_per_pixel > 12) { // Greater than 12 bits must be TrueColor... image->red_mask = fl_visual->visual->red_mask; image->green_mask = fl_visual->visual->green_mask; image->blue_mask = fl_visual->visual->blue_mask; #ifdef DEBUG // Defined in Fl_Xlib_Graphics_Driver_color.cxx extern uchar fl_redmask, fl_greenmask, fl_bluemask; extern int fl_redshift, fl_greenshift, fl_blueshift; puts("\n---- UPDATED ----"); printf("fl_redmask = %08x\n", fl_redmask); printf("fl_redshift = %d\n", fl_redshift); printf("fl_greenmask = %08x\n", fl_greenmask); printf("fl_greenshift = %d\n", fl_greenshift); printf("fl_bluemask = %08x\n", fl_bluemask); printf("fl_blueshift = %d\n", fl_blueshift); printf("red_mask = %08x\n", image->red_mask); printf("green_mask = %08x\n", image->green_mask); printf("blue_mask = %08x\n", image->blue_mask); #endif // DEBUG } // Check if we have colormap image... if (!image->red_mask) { // Get the colormap entries for this window... maxindex = fl_visual->visual->map_entries; for (i = 0; i < maxindex; i ++) colors[i].pixel = i; XQueryColors(fl_display, fl_colormap, colors, maxindex); for (i = 0; i < maxindex; i ++) { cvals[i][0] = colors[i].red >> 8; cvals[i][1] = colors[i].green >> 8; cvals[i][2] = colors[i].blue >> 8; } // Read the pixels and output an RGB image... for (y = 0; y < image->height; y ++) { pixel = (unsigned char *)(image->data + y * image->bytes_per_line); line = p + y * w * d; switch (image->bits_per_pixel) { case 1 : for (x = image->width, line_ptr = line, index_mask = 128; x > 0; x --, line_ptr += d) { if (*pixel & index_mask) { line_ptr[0] = cvals[1][0]; line_ptr[1] = cvals[1][1]; line_ptr[2] = cvals[1][2]; } else { line_ptr[0] = cvals[0][0]; line_ptr[1] = cvals[0][1]; line_ptr[2] = cvals[0][2]; } if (index_mask > 1) { index_mask >>= 1; } else { index_mask = 128; pixel ++; } } break; case 2 : for (x = image->width, line_ptr = line, index_shift = 6; x > 0; x --, line_ptr += d) { i = (*pixel >> index_shift) & 3; line_ptr[0] = cvals[i][0]; line_ptr[1] = cvals[i][1]; line_ptr[2] = cvals[i][2]; if (index_shift > 0) { index_shift -= 2; } else { index_shift = 6; pixel ++; } } break; case 4 : for (x = image->width, line_ptr = line, index_shift = 4; x > 0; x --, line_ptr += d) { if (index_shift == 4) i = (*pixel >> 4) & 15; else i = *pixel & 15; line_ptr[0] = cvals[i][0]; line_ptr[1] = cvals[i][1]; line_ptr[2] = cvals[i][2]; if (index_shift > 0) { index_shift = 0; } else { index_shift = 4; pixel ++; } } break; case 8 : for (x = image->width, line_ptr = line; x > 0; x --, line_ptr += d, pixel ++) { line_ptr[0] = cvals[*pixel][0]; line_ptr[1] = cvals[*pixel][1]; line_ptr[2] = cvals[*pixel][2]; } break; case 12 : for (x = image->width, line_ptr = line, index_shift = 0; x > 0; x --, line_ptr += d) { if (index_shift == 0) { i = ((pixel[0] << 4) | (pixel[1] >> 4)) & 4095; } else { i = ((pixel[1] << 8) | pixel[2]) & 4095; } line_ptr[0] = cvals[i][0]; line_ptr[1] = cvals[i][1]; line_ptr[2] = cvals[i][2]; if (index_shift == 0) { index_shift = 4; } else { index_shift = 0; pixel += 3; } } break; } } } else { // RGB(A) image, so figure out the shifts & masks... red_mask = image->red_mask; red_shift = 0; while ((red_mask & 1) == 0) { red_mask >>= 1; red_shift ++; } green_mask = image->green_mask; green_shift = 0; while ((green_mask & 1) == 0) { green_mask >>= 1; green_shift ++; } blue_mask = image->blue_mask; blue_shift = 0; while ((blue_mask & 1) == 0) { blue_mask >>= 1; blue_shift ++; } // Read the pixels and output an RGB image... for (y = 0; y < image->height; y ++) { pixel = (unsigned char *)(image->data + y * image->bytes_per_line); line = p + y * w * d; switch (image->bits_per_pixel) { case 8 : for (x = image->width, line_ptr = line; x > 0; x --, line_ptr += d, pixel ++) { i = *pixel; line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; } break; case 12 : for (x = image->width, line_ptr = line, index_shift = 0; x > 0; x --, line_ptr += d) { if (index_shift == 0) { i = ((pixel[0] << 4) | (pixel[1] >> 4)) & 4095; } else { i = ((pixel[1] << 8) | pixel[2]) & 4095; } line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; if (index_shift == 0) { index_shift = 4; } else { index_shift = 0; pixel += 3; } } break; case 16 : if (image->byte_order == LSBFirst) { // Little-endian... for (x = image->width, line_ptr = line; x > 0; x --, line_ptr += d, pixel += 2) { i = (pixel[1] << 8) | pixel[0]; line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; } } else { // Big-endian... for (x = image->width, line_ptr = line; x > 0; x --, line_ptr += d, pixel += 2) { i = (pixel[0] << 8) | pixel[1]; line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; } } break; case 24 : if (image->byte_order == LSBFirst) { // Little-endian... for (x = image->width, line_ptr = line; x > 0; x --, line_ptr += d, pixel += 3) { i = (((pixel[2] << 8) | pixel[1]) << 8) | pixel[0]; line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; } } else { // Big-endian... for (x = image->width, line_ptr = line; x > 0; x --, line_ptr += d, pixel += 3) { i = (((pixel[0] << 8) | pixel[1]) << 8) | pixel[2]; line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; } } break; case 32 : if (image->byte_order == LSBFirst) { // Little-endian... for (x = image->width, line_ptr = line; x > 0; x --, line_ptr += d, pixel += 4) { i = (((((pixel[3] << 8) | pixel[2]) << 8) | pixel[1]) << 8) | pixel[0]; line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; } } else { // Big-endian... for (x = image->width, line_ptr = line; x > 0; x --, line_ptr += d, pixel += 4) { i = (((((pixel[0] << 8) | pixel[1]) << 8) | pixel[2]) << 8) | pixel[3]; line_ptr[0] = 255 * ((i >> red_shift) & red_mask) / red_mask; line_ptr[1] = 255 * ((i >> green_shift) & green_mask) / green_mask; line_ptr[2] = 255 * ((i >> blue_shift) & blue_mask) / blue_mask; } } break; } } } // Destroy the X image we've read and return the RGB(A) image... XDestroyImage(image); Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, d); rgb->alloc_array = 1; return rgb; } void Fl_X11_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &height) { int px, py; unsigned w, h, b, d; Window root; XGetGeometry(fl_display, (Pixmap)off, &root, &px, &py, &w, &h, &b, &d); width = (int)w; height = (int)h; } void Fl_X11_Screen_Driver::reset_spot(void) { fl_spot.x = -1; fl_spot.y = -1; //if (xim_ic) XUnsetICFocus(xim_ic); } void Fl_X11_Screen_Driver::set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) { int change = 0; XVaNestedList preedit_attr; static XFontSet fs = NULL; char **missing_list = NULL; int missing_count = 0; char *def_string = NULL; char *fnt = NULL; bool must_free_fnt = true; static XIC ic = NULL; if (!xim_ic || !fl_is_over_the_spot) return; if (Fl::focus()) { // handle case when text widget is inside subwindow Fl_Window *focuswin = Fl::focus()->window(); while (focuswin && focuswin->parent()) { X += focuswin->x(); Y += focuswin->y(); focuswin = focuswin->window(); } } // XSetICFocus(xim_ic); if (X != fl_spot.x || Y != fl_spot.y) { fl_spot.x = X; fl_spot.y = Y; fl_spot.height = H; fl_spot.width = W; change = 1; } if (font != fl_spotf || size != fl_spots) { fl_spotf = font; fl_spots = size; change = 1; if (fs) { XFreeFontSet(fl_display, fs); } #if USE_XFT fnt = NULL; // FIXME: missing XFT support here #else fnt = fl_get_font_xfld(font, size); #endif if (!fnt) { fnt = (char*)"-misc-fixed-*"; must_free_fnt = false; } fs = XCreateFontSet(fl_display, fnt, &missing_list, &missing_count, &def_string); if (missing_list) XFreeStringList(missing_list); } if (xim_ic != ic) { ic = xim_ic; change = 1; } if (fnt && must_free_fnt) free(fnt); if (!change) return; float s = Fl_Graphics_Driver::default_driver().scale(); XRectangle fl_spot_unscaled = { short(fl_spot.x * s), short(fl_spot.y * s), (unsigned short)(fl_spot.width * s), (unsigned short)(fl_spot.height * s) }; preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &fl_spot_unscaled, XNFontSet, fs, NULL); XSetICValues(xim_ic, XNPreeditAttributes, preedit_attr, NULL); XFree(preedit_attr); } #if USE_XFT //NOTICE: returns -1 if x,y is not in any screen int Fl_X11_Screen_Driver::screen_num_unscaled(int x, int y) { int screen = -1; if (num_screens < 0) init(); for (int i = 0; i < num_screens; i ++) { int sx = screens[i].x_org, sy = screens[i].y_org, sw = screens[i].width, sh = screens[i].height; if ((x >= sx) && (x < (sx+sw)) && (y >= sy) && (y < (sy+sh))) { screen = i; break; } } return screen; } // set the desktop's default scaling value void Fl_X11_Screen_Driver::desktop_scale_factor() { if (this->current_xft_dpi == 0.) { // Try getting the Xft.dpi resource value char *s = XGetDefault(fl_display, "Xft", "dpi"); if (s && sscanf(s, "%f", &(this->current_xft_dpi)) == 1) { float factor = this->current_xft_dpi / 96.; // checks to prevent potential crash (factor <= 0) or very large factors // and round nearly 1 or nearly 2 values (issue #1138) if (factor < 1.1) factor = 1; else if (factor > 1.8 && factor < 2.2) factor = 2; else if (factor > 10.0) factor = 10.0; for (int i = 0; i < screen_count(); i++) scale(i, factor); } } } #endif // USE_XFT fltk-1.4.3/src/drivers/X11/Fl_X11_Screen_Driver.H0000644000175000017500000001111215004135251021334 0ustar albrechtalbrecht// // Definition of X11 Screen interface // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_X11_Screen_Driver.H \brief Definition of X11 Screen interface */ #ifndef FL_X11_SCREEN_DRIVER_H #define FL_X11_SCREEN_DRIVER_H #include #include "../Unix/Fl_Unix_Screen_Driver.H" #include class Fl_Window; class Fl_X11_Screen_Driver : public Fl_Unix_Screen_Driver { friend class Fl_Screen_Driver; protected: typedef struct { short x_org; short y_org; short width; short height; #if USE_XFT float scale; #endif } FLScreenInfo; FLScreenInfo screens[MAX_SCREENS]; float dpi[MAX_SCREENS][2]; int get_mouse_unscaled(int &xx, int &yy); public: #if USE_XFT // scaling does not work without Xft float current_xft_dpi; // current value of the Xft.dpi X resource APP_SCALING_CAPABILITY rescalable() FL_OVERRIDE { return PER_SCREEN_APP_SCALING; } float scale(int n) FL_OVERRIDE {return screens[n].scale;} void scale(int n, float f) FL_OVERRIDE { screens[n].scale = f;} void desktop_scale_factor() FL_OVERRIDE; int screen_num_unscaled(int x, int y); #endif Fl_X11_Screen_Driver(); static int ewmh_supported(); static void copy_image(const unsigned char* data, int W, int H, int destination); // --- display management void display(const char *disp) FL_OVERRIDE; int XParseGeometry(const char*, int*, int*, unsigned int*, unsigned int*) FL_OVERRIDE; int poll_or_select_with_delay(double time_to_wait) FL_OVERRIDE; int poll_or_select() FL_OVERRIDE; void own_colormap() FL_OVERRIDE; const char *shortcut_add_key_name(unsigned key, char *p, char *buf, const char **) FL_OVERRIDE; int need_menu_handle_part1_extra() FL_OVERRIDE {return 1;} int need_menu_handle_part2() FL_OVERRIDE {return 1;} // these 2 are in Fl_get_key.cxx int event_key(int) FL_OVERRIDE; int get_key(int) FL_OVERRIDE; int visual(int flags) FL_OVERRIDE; // --- screen configuration void init_workarea(); void init() FL_OVERRIDE; int x() FL_OVERRIDE; int y() FL_OVERRIDE; int w() FL_OVERRIDE; int h() FL_OVERRIDE; void screen_xywh(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; void screen_dpi(float &h, float &v, int n=0) FL_OVERRIDE; void screen_work_area(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; // --- audible output void beep(int type) FL_OVERRIDE; // --- global events void flush() FL_OVERRIDE; void grab(Fl_Window* win) FL_OVERRIDE; // --- global colors int parse_color(const char* p, uchar& r, uchar& g, uchar& b) FL_OVERRIDE; void get_system_colors() FL_OVERRIDE; const char *get_system_scheme() FL_OVERRIDE; int dnd(int unused) FL_OVERRIDE; int compose(int &del) FL_OVERRIDE; void compose_reset() FL_OVERRIDE; int text_display_can_leak() const FL_OVERRIDE; Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins) FL_OVERRIDE; int get_mouse(int &x, int &y) FL_OVERRIDE; void open_display_platform() FL_OVERRIDE; void close_display() FL_OVERRIDE; // --- compute dimensions of an Fl_Offscreen void offscreen_size(Fl_Offscreen o, int &width, int &height) FL_OVERRIDE; void default_icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE; // this one is in Fl_x.cxx void copy(const char *stuff, int len, int clipboard, const char *type) FL_OVERRIDE; // this one is in Fl_x.cxx void paste(Fl_Widget &receiver, int clipboard, const char *type) FL_OVERRIDE; // this one is in Fl_x.cxx int clipboard_contains(const char *type) FL_OVERRIDE; // this one is in Fl_x.cxx void clipboard_notify_change() FL_OVERRIDE; // for support of input methods static char fl_is_over_the_spot; static XRectangle fl_spot; static int fl_spotf; static int fl_spots; static XIM xim_im; static XIC xim_ic; static Window xim_win; static void new_ic(); static void xim_activate(Window xid); static void xim_deactivate(void); static void init_xim(); void enable_im() FL_OVERRIDE; void disable_im() FL_OVERRIDE; void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) FL_OVERRIDE; void reset_spot() FL_OVERRIDE; void set_status(int X, int Y, int W, int H) FL_OVERRIDE; }; #endif // FL_X11_SCREEN_DRIVER_H fltk-1.4.3/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx0000644000175000017500000003110215004135251022422 0ustar albrechtalbrecht// // Class Fl_X11_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if HAVE_GL #include #include "../../Fl_Gl_Choice.H" #include "../../Fl_Screen_Driver.H" #include "Fl_X11_Gl_Window_Driver.H" #include #if ! USE_XFT # include "../Xlib/Fl_Font.H" #endif // Describes crap needed to create a GLContext. class Fl_X11_Gl_Choice : public Fl_Gl_Choice { friend class Fl_X11_Gl_Window_Driver; private: XVisualInfo *vis; /* the visual to use */ Colormap colormap; /* a colormap for that visual */ public: Fl_X11_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : Fl_Gl_Choice(m, alistp, n) { vis = NULL; colormap = 0; } }; #ifndef FLTK_USE_WAYLAND Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w) { return new Fl_X11_Gl_Window_Driver(w); } #endif void Fl_X11_Gl_Window_Driver::draw_string_legacy(const char* str, int n) { draw_string_legacy_get_list(str, n); } int Fl_X11_Gl_Window_Driver::genlistsize() { #if USE_XFT return 256; #else return 0x10000; #endif } void Fl_X11_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) { /* This method should ONLY be triggered if our GL font texture pile mechanism * is not working on this platform. This code might not reliably render glyphs * from higher codepoints. */ if (!fl_fontsize->listbase) { #if USE_XFT && !FLTK_USE_CAIRO /* Ideally, for XFT, we need a glXUseXftFont implementation here... But we * do not have such a thing. Instead, we try to find a legacy Xlib font that * matches the current XFT font and use that. * Ideally, we never come here - we hope the texture pile implementation * will work correctly so that XFT can render the face directly without the * need for this workaround. */ XFontStruct *font = fl_xfont.value(); int base = font->min_char_or_byte2; int count = font->max_char_or_byte2 - base + 1; fl_fontsize->listbase = glGenLists(genlistsize()); glXUseXFont(font->fid, base, count, fl_fontsize->listbase+base); #else /* Not using XFT to render text - the legacy Xlib fonts can usually be rendered * directly by using glXUseXFont mechanisms. */ fl_fontsize->listbase = glGenLists(genlistsize()); #endif // !USE_XFT } glListBase(fl_fontsize->listbase); } void Fl_X11_Gl_Window_Driver::get_list(Fl_Font_Descriptor *fd, int r) { # if USE_XFT /* We hope not to come here: We hope that any system using XFT will also * have sufficient GL capability to support our font texture pile mechansim, * allowing XFT to render the face directly. */ // Face already set by gl_bitmap_font in this case. (void)fd; (void)r; # else Fl_Xlib_Font_Descriptor *gl_fd = (Fl_Xlib_Font_Descriptor*)fd; if (gl_fd->glok[r]) return; gl_fd->glok[r] = 1; unsigned int ii = r * 0x400; for (int i = 0; i < 0x400; i++) { XFontStruct *font = NULL; unsigned short id; fl_XGetUtf8FontAndGlyph(gl_fd->font, ii, &font, &id); if (font) glXUseXFont(font->fid, id, 1, gl_fd->listbase+ii); ii++; } # endif } #if !USE_XFT Fl_Font_Descriptor** Fl_X11_Gl_Window_Driver::fontnum_to_fontdescriptor(int fnum) { Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts) + fnum; return &(s->first); } #endif Fl_Gl_Choice *Fl_X11_Gl_Window_Driver::find(int m, const int *alistp) { Fl_X11_Gl_Choice *g = (Fl_X11_Gl_Choice*)Fl_Gl_Window_Driver::find_begin(m, alistp); if (g) return g; const int *blist; int list[32]; if (alistp) blist = alistp; else { int n = 0; if (m & FL_INDEX) { list[n++] = GLX_BUFFER_SIZE; list[n++] = 8; // glut tries many sizes, but this should work... } else { list[n++] = GLX_RGBA; list[n++] = GLX_GREEN_SIZE; list[n++] = (m & FL_RGB8) ? 8 : 1; if (m & FL_ALPHA) { list[n++] = GLX_ALPHA_SIZE; list[n++] = (m & FL_RGB8) ? 8 : 1; } if (m & FL_ACCUM) { list[n++] = GLX_ACCUM_GREEN_SIZE; list[n++] = 1; if (m & FL_ALPHA) { list[n++] = GLX_ACCUM_ALPHA_SIZE; list[n++] = 1; } } } if (m & FL_DOUBLE) { list[n++] = GLX_DOUBLEBUFFER; } if (m & FL_DEPTH) { list[n++] = GLX_DEPTH_SIZE; list[n++] = 1; } if (m & FL_STENCIL) { list[n++] = GLX_STENCIL_SIZE; list[n++] = 1; } if (m & FL_STEREO) { list[n++] = GLX_STEREO; } # if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample) if (m & FL_MULTISAMPLE) { list[n++] = GLX_SAMPLES_SGIS; list[n++] = 4; // value Glut uses } # endif list[n] = 0; blist = list; } fl_open_display(); XVisualInfo *visp = glXChooseVisual(fl_display, fl_screen, (int *)blist); if (!visp) { # if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample) if (m&FL_MULTISAMPLE) return find(m&~FL_MULTISAMPLE, 0); # endif return 0; } g = new Fl_X11_Gl_Choice(m, alistp, first); first = g; g->vis = visp; if (/*MaxCmapsOfScreen(ScreenOfDisplay(fl_display,fl_screen))==1 && */ visp->visualid == fl_visual->visualid && !fl_getenv("MESA_PRIVATE_CMAP")) g->colormap = fl_colormap; else g->colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen), visp->visual, AllocNone); return g; } GLContext Fl_X11_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) { (void)window; GLContext shared_ctx = 0; if (context_list && nContext) shared_ctx = context_list[0]; // use OpenGL 1-style context creation GLContext ctx = glXCreateContext(fl_display, ((Fl_X11_Gl_Choice*)g)->vis, (GLXContext)shared_ctx, true); if (ctx) add_context(ctx); //glXMakeCurrent(fl_display, fl_xid(window), ctx);printf("%s\n", glGetString(GL_VERSION)); return ctx; } void Fl_X11_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) { GLContext current_context = glXGetCurrentContext(); if (context != current_context || w != cached_window) { cached_window = w; glXMakeCurrent(fl_display, fl_xid(w), (GLXContext)context); } } void Fl_X11_Gl_Window_Driver::delete_gl_context(GLContext context) { GLContext current_context = glXGetCurrentContext(); if (current_context == context) { cached_window = 0; glXMakeCurrent(fl_display, 0, 0); } glXDestroyContext(fl_display, (GLXContext)context); del_context(context); } void Fl_X11_Gl_Window_Driver::make_overlay_current() { glDrawBuffer(GL_FRONT); } void Fl_X11_Gl_Window_Driver::redraw_overlay() { pWindow->damage(FL_DAMAGE_OVERLAY); } void Fl_X11_Gl_Window_Driver::before_show(int&) { Fl_X11_Gl_Choice *g = (Fl_X11_Gl_Choice*)this->g(); Fl_X::make_xid(pWindow, g->vis, g->colormap); } float Fl_X11_Gl_Window_Driver::pixels_per_unit() { int ns = pWindow->screen_num(); return Fl::screen_driver()->scale(ns); } int Fl_X11_Gl_Window_Driver::mode_(int m, const int *a) { int oldmode = mode(); if (a) { // when the mode is set using the a array of system-dependent values, and if asking for double buffer, // the FL_DOUBLE flag must be set in the mode_ member variable const int *aa = a; while (*aa) { if (*(aa++) == GLX_DOUBLEBUFFER ) { m |= FL_DOUBLE; break; } } } Fl_X11_Gl_Choice* oldg = (Fl_X11_Gl_Choice*)g(); pWindow->context(0); mode(m); alist(a); if (pWindow->shown()) { g( find(m, a) ); // under X, if the visual changes we must make a new X window (yuck!): Fl_X11_Gl_Choice* g = (Fl_X11_Gl_Choice*)this->g(); if (!g || g->vis->visualid != oldg->vis->visualid || (oldmode^m)&FL_DOUBLE) { pWindow->hide(); pWindow->show(); } } else { g(0); } return 1; } void Fl_X11_Gl_Window_Driver::swap_buffers() { if (!fl_xid(pWindow)) // window not shown return; if (overlay()) { int wo = pWindow->pixel_w(), ho = pWindow->pixel_h(); GLint matrixmode; GLfloat pos[4]; glGetIntegerv(GL_MATRIX_MODE, &matrixmode); glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); // save original glRasterPos glMatrixMode(GL_PROJECTION); // save proj/model matrices glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glScalef(2.0f/wo, 2.0f/ho, 1.0f); glTranslatef(-wo/2.0f, -ho/2.0f, 0.0f); // set transform so 0,0 is bottom/left of Gl_Window glRasterPos2i(0,0); // set glRasterPos to bottom left corner { // Emulate overlay by doing copypixels glReadBuffer(GL_BACK); glDrawBuffer(GL_FRONT); glCopyPixels(0, 0, wo, ho, GL_COLOR); // copy GL_BACK to GL_FRONT } glPopMatrix(); // GL_MODELVIEW // restore model/proj matrices glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(matrixmode); glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos } else glXSwapBuffers(fl_display, fl_xid(pWindow)); } char Fl_X11_Gl_Window_Driver::swap_type() { return copy; } // Start of swap_interval implementation in the three possibel ways for X11 // -1 = not yet initialized, 0 = none found, 1 = GLX, 2 = MESA, 3 = SGI static signed char swap_interval_type = -1; typedef void (*Fl_GLX_Set_Swap_Iterval_Proc) (Display *dpy, GLXDrawable drawable, int interval); typedef int (*Fl_MESA_Set_Swap_Iterval_Proc) (unsigned int interval); typedef int (*Fl_MESA_Get_Swap_Iterval_Proc) (); typedef int (*Fl_SGI_Set_Swap_Iterval_Proc) (int interval); static union { Fl_GLX_Set_Swap_Iterval_Proc EXT; Fl_MESA_Set_Swap_Iterval_Proc MESA; Fl_SGI_Set_Swap_Iterval_Proc SGI; } fl_glXSwapInterval = { NULL }; static Fl_MESA_Get_Swap_Iterval_Proc fl_glXGetSwapIntervalMESA = NULL; static void init_swap_interval() { if (swap_interval_type != -1) return; int major = 1, minor = 0; glXQueryVersion(fl_display, &major, &minor); swap_interval_type = 0; const char *extensions = glXQueryExtensionsString(fl_display, fl_screen); if (strstr(extensions, "GLX_EXT_swap_control") && ((major > 1) || (minor >= 3))) { fl_glXSwapInterval.EXT = (Fl_GLX_Set_Swap_Iterval_Proc)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalEXT"); swap_interval_type = 1; } else if (strstr(extensions, "GLX_MESA_swap_control")) { fl_glXSwapInterval.MESA = (Fl_MESA_Set_Swap_Iterval_Proc)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalMESA"); fl_glXGetSwapIntervalMESA = (Fl_MESA_Get_Swap_Iterval_Proc)glXGetProcAddressARB((const GLubyte*)"glXGetSwapIntervalMESA"); swap_interval_type = 2; } else if (strstr(extensions, "GLX_SGI_swap_control")) { fl_glXSwapInterval.SGI = (Fl_SGI_Set_Swap_Iterval_Proc)glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalSGI"); swap_interval_type = 3; } } void Fl_X11_Gl_Window_Driver::swap_interval(int interval) { if (!fl_xid(pWindow)) return; if (swap_interval_type == -1) init_swap_interval(); switch (swap_interval_type) { case 1: if (fl_glXSwapInterval.EXT) fl_glXSwapInterval.EXT(fl_display, fl_xid(pWindow), interval); break; case 2: if (fl_glXSwapInterval.MESA) fl_glXSwapInterval.MESA((unsigned int)interval); break; case 3: if (fl_glXSwapInterval.SGI) fl_glXSwapInterval.SGI(interval); break; } } int Fl_X11_Gl_Window_Driver::swap_interval() const { if (!fl_xid(pWindow)) return -1; if (swap_interval_type == -1) init_swap_interval(); int interval = -1; switch (swap_interval_type) { case 1: { unsigned int val = 0; glXQueryDrawable(fl_display, fl_xid(pWindow), 0x20F1 /*GLX_SWAP_INTERVAL_EXT*/, &val); interval = (int)val; break; } case 2: if (fl_glXGetSwapIntervalMESA) interval = fl_glXGetSwapIntervalMESA(); break; case 3: // not available break; } return interval; } // end of swap_interval implementation void Fl_X11_Gl_Window_Driver::waitGL() { glXWaitGL(); } void Fl_X11_Gl_Window_Driver::gl_visual(Fl_Gl_Choice *c) { Fl_Gl_Window_Driver::gl_visual(c); fl_visual = ((Fl_X11_Gl_Choice*)c)->vis; fl_colormap = ((Fl_X11_Gl_Choice*)c)->colormap; } void Fl_X11_Gl_Window_Driver::gl_start() { glXWaitX(); } FL_EXPORT GLXContext fl_x11_glcontext(GLContext rc) { return (GLXContext)rc; } #endif // HAVE_GL fltk-1.4.3/src/drivers/X11/Fl_X11_Gl_Window_Driver.H0000644000175000017500000000406315004135251022015 0ustar albrechtalbrecht// // Class Fl_X11_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). // // Copyright 2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_X11_GL_WINDOW_DRIVER_H #define FL_X11_GL_WINDOW_DRIVER_H #include #if HAVE_GL #include #include "../../Fl_Gl_Window_Driver.H" class Fl_Gl_Choice; class Fl_X11_Gl_Window_Driver : public Fl_Gl_Window_Driver { friend Fl_Gl_Window_Driver* Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *); Fl_X11_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {} float pixels_per_unit() FL_OVERRIDE; void before_show(int& need_after) FL_OVERRIDE; int mode_(int m, const int *a) FL_OVERRIDE; void swap_buffers() FL_OVERRIDE; char swap_type() FL_OVERRIDE; void swap_interval(int) FL_OVERRIDE; int swap_interval() const FL_OVERRIDE; Fl_Gl_Choice *find(int m, const int *alistp) FL_OVERRIDE; GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) FL_OVERRIDE; void set_gl_context(Fl_Window* w, GLContext context) FL_OVERRIDE; void delete_gl_context(GLContext) FL_OVERRIDE; void make_overlay_current() FL_OVERRIDE; void redraw_overlay() FL_OVERRIDE; void waitGL() FL_OVERRIDE; void gl_visual(Fl_Gl_Choice*) FL_OVERRIDE; // support for Fl::gl_visual() void gl_start() FL_OVERRIDE; void draw_string_legacy(const char* str, int n) FL_OVERRIDE; void gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) FL_OVERRIDE; void get_list(Fl_Font_Descriptor *fd, int r) FL_OVERRIDE; int genlistsize() FL_OVERRIDE; #if !USE_XFT virtual Fl_Font_Descriptor** fontnum_to_fontdescriptor(int fnum) FL_OVERRIDE; #endif //static GLContext create_gl_context(XVisualInfo* vis); }; #endif // HAVE_GL #endif // FL_X11_GL_WINDOW_DRIVER_H fltk-1.4.3/src/drivers/X11/fl_X11_platform_init.cxx0000644000175000017500000000360215004135251022131 0ustar albrechtalbrecht// // X11-specific code to initialize wayland support. // // Copyright 2022-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "../Xlib/Fl_Xlib_Copy_Surface_Driver.H" #if FLTK_USE_CAIRO # include "../Cairo/Fl_X11_Cairo_Graphics_Driver.H" #else # include "../Xlib/Fl_Xlib_Graphics_Driver.H" #endif #include "Fl_X11_Screen_Driver.H" #include "../Unix/Fl_Unix_System_Driver.H" #include "Fl_X11_Window_Driver.H" #include "../Xlib/Fl_Xlib_Image_Surface_Driver.H" Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int h) { return new Fl_Xlib_Copy_Surface_Driver(w, h); } Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() { #if FLTK_USE_CAIRO return new Fl_X11_Cairo_Graphics_Driver(); #else return new Fl_Xlib_Graphics_Driver(); #endif } Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() { Fl_X11_Screen_Driver *d = new Fl_X11_Screen_Driver(); #if USE_XFT for (int i = 0; i < MAX_SCREENS; i++) d->screens[i].scale = 1; d->current_xft_dpi = 0.; // means the value of the Xft.dpi resource is still unknown #else secret_input_character = '*'; #endif return d; } Fl_System_Driver *Fl_System_Driver::newSystemDriver() { return new Fl_Unix_System_Driver(); } Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w) { return new Fl_X11_Window_Driver(w); } Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off) { return new Fl_Xlib_Image_Surface_Driver(w, h, high_res, off); } fltk-1.4.3/src/drivers/OpenGL/0000755000175000017500000000000015004135251016176 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.cxx0000644000175000017500000001600715004135251025223 0ustar albrechtalbrecht// // Portable drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_OpenGL_Graphics_Driver_vertex.cxx \brief Portable drawing code for drawing arbitrary shapes with simple 2D transformations, implemented for OpenGL. */ #include "Fl_OpenGL_Graphics_Driver.H" #include #include #include #include // OpenGL does not support rednering non-convex polygons. Calling // glBegin(GL_POLYGON); witha complex outline will create rather random // errors, often overwrinting gaps and holes. // // Defining SLOW_COMPLEX_POLY will activate a line-by-line drawing method // for complex polygons that is correct for FLTK, but also a lot slower. // // It's recommended that SLOW_COMPLEX_POLY is defined, but fl_begin_polygon() // is used instead of fl_begin_complex_polygon() whenever possible. //#undef SLOW_COMPLEX_POLY #define SLOW_COMPLEX_POLY #ifdef SLOW_COMPLEX_POLY # define GAP (1e9f) #endif // Event though there are faster versions of the functions in OpenGL, // we use the default FLTK implementation for compatibility in the // following functions. // void Fl_OpenGL_Graphics_Driver::push_matrix() // void Fl_OpenGL_Graphics_Driver::pop_matrix() // void Fl_OpenGL_Graphics_Driver::mult_matrix(double a, double b, double c, double d, double x, double y) // void Fl_OpenGL_Graphics_Driver::rotate(double d) // double Fl_OpenGL_Graphics_Driver::transform_x(double x, double y) // double Fl_OpenGL_Graphics_Driver::transform_y(double x, double y) // double Fl_OpenGL_Graphics_Driver::transform_dx(double x, double y) // double Fl_OpenGL_Graphics_Driver::transform_dy(double x, double y) void Fl_OpenGL_Graphics_Driver::begin_points() { n = 0; gap_ = 0; what = POINTS; glBegin(GL_POINTS); } void Fl_OpenGL_Graphics_Driver::end_points() { glEnd(); } void Fl_OpenGL_Graphics_Driver::begin_line() { n = 0; gap_ = 0; what = LINE; glBegin(GL_LINE_STRIP); } void Fl_OpenGL_Graphics_Driver::end_line() { glEnd(); } void Fl_OpenGL_Graphics_Driver::begin_loop() { n = 0; gap_ = 0; what = LOOP; glBegin(GL_LINE_LOOP); } void Fl_OpenGL_Graphics_Driver::end_loop() { glEnd(); } void Fl_OpenGL_Graphics_Driver::begin_polygon() { n = 0; gap_ = 0; what = POLYGON; glBegin(GL_POLYGON); } void Fl_OpenGL_Graphics_Driver::end_polygon() { glEnd(); } void Fl_OpenGL_Graphics_Driver::begin_complex_polygon() { n = 0; what = COMPLEX_POLYGON; #ifndef SLOW_COMPLEX_POLY glBegin(GL_POLYGON); #endif } void Fl_OpenGL_Graphics_Driver::gap() { #ifdef SLOW_COMPLEX_POLY // drop gaps at the start or gap after gap if (n==0 || n==gap_) // || pnVertex==pVertexGapStart) return; // create a loop XPOINT& p = xpoint[gap_]; transformed_vertex(p.x, p.y); transformed_vertex(GAP, 0.0); gap_ = n; #else glEnd(); glBegin(GL_POLYGON); #endif } #ifdef SLOW_COMPLEX_POLY // Draw a complex polygon line by line from the top to the bottom. void Fl_OpenGL_Graphics_Driver::end_complex_polygon() { int i, y; XPOINT *v0, *v1; // don't bother if no polygon is defined if (n < 2) return; // make sure that we always have a closed loop by appending the first // coordinate again as the alst coordinate gap(); // find the bounding box for this polygon v0 = xpoint; v0->y -= 0.1f; float xMin = v0->x, xMax = xMin; int yMin = (int)v0->y, yMax = yMin; for (i = 1; i < n; i++) { v0++; v0->y -= 0.1f; float v0x = v0->x; int v0y = (int)v0->y; if (v0x == GAP) continue; if (v0x <= xMin) xMin = v0x; if (v0x >= xMax) xMax = v0x; if (v0y <= yMin) yMin = v0y; if (v0y >= yMax) yMax = v0y; } int nNodes; float *nodeX = (float*)malloc((n-1)*sizeof(float)), swap; if (!nodeX) return; // loop through the rows of the image for (y = yMin; y <= yMax; y++) { // Build a list of all crossing points with this y axis v0 = xpoint + 0; v1 = xpoint + 1; nNodes = 0; for (i = 1; i < n; i++) { if (v1->x==GAP) { // skip the gap i++; v0++; v1++; v0++; v1++; continue; } if ( (v1->y < y && v0->y >= y) || (v0->y < y && v1->y >= y) ) { float dy = v0->y - v1->y; if (fabsf(dy)>.0001f) { nodeX[nNodes++] = v1->x + ((y - v1->y) / dy) * (v0->x - v1->x); } else { nodeX[nNodes++] = v1->x; } } v0++; v1++; } // sort the nodes, via a simple Bubble sort i = 0; while (i < nNodes-1) { if (nodeX[i] > nodeX[i+1]) { swap = nodeX[i]; nodeX[i] = nodeX[i+1]; nodeX[i+1] = swap; if (i) i--; } else { i++; } } // fill the pixels between node pairs // Using lines requires additional attention to the current line width and pattern // We are using glRectf instead // glBegin(GL_LINES); for (i = 0; i < nNodes; i += 2) { float x0 = nodeX[i]; if (x0 >= xMax) break; float x1 = nodeX[i+1]; if (x1 > xMin) { if (x0 < xMin) x0 = xMin; if (x1 > xMax) x1 = xMax; glRectf((GLfloat)(x0-0.25f), (GLfloat)(y), (GLfloat)(x1+0.25f), (GLfloat)(y+1.0f)); // glVertex2f((GLfloat)x0, (GLfloat)y); // glVertex2f((GLfloat)x1, (GLfloat)y); } } // glEnd(); } ::free(nodeX); } #else // FXIME: non-convex polygons are not supported yet // use gluTess* functions to do this; search for gluBeginPolygon void Fl_OpenGL_Graphics_Driver::end_complex_polygon() { glEnd(); } #endif // remove equal points from closed path void Fl_OpenGL_Graphics_Driver::fixloop() { } void Fl_OpenGL_Graphics_Driver::transformed_vertex(double xf, double yf) { #ifdef SLOW_COMPLEX_POLY if (what==COMPLEX_POLYGON) { Fl_Graphics_Driver::transformed_vertex(xf, yf); } else { glVertex2d(xf, yf); } #else glVertex2d(xf, yf); #endif } void Fl_OpenGL_Graphics_Driver::circle(double cx, double cy, double r) { double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a)); double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d)); double rMax; if (ry>rx) rMax = ry; else rMax = rx; // from http://slabode.exofire.net/circle_draw.shtml and many other places int num_segments = (int)(10 * sqrt(rMax))+1; double theta = 2 * M_PI / float(num_segments); double tangetial_factor = tan(theta); double radial_factor = cos(theta);//calculate the radial factor double x = r; //we start at angle = 0 double y = 0; glBegin(GL_LINE_LOOP); for(int ii = 0; ii < num_segments; ii++) { vertex(x + cx, y + cy); // output vertex double tx = -y; double ty = x; x += tx * tangetial_factor; y += ty * tangetial_factor; x *= radial_factor; y *= radial_factor; } glEnd(); } fltk-1.4.3/src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx0000644000175000017500000000163715004135251023442 0ustar albrechtalbrecht// // implementation of class Fl_OpenGL_Display_Device for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_OpenGL_Graphics_Driver.H" #include "Fl_OpenGL_Display_Device.H" Fl_OpenGL_Display_Device *Fl_OpenGL_Display_Device::display_device() { static Fl_OpenGL_Display_Device *display = new Fl_OpenGL_Display_Device(new Fl_OpenGL_Graphics_Driver()); return display; } Fl_OpenGL_Display_Device::Fl_OpenGL_Display_Device(Fl_OpenGL_Graphics_Driver *graphics_driver) : Fl_Surface_Device(graphics_driver) { } fltk-1.4.3/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.cxx0000644000175000017500000000156515004135251023631 0ustar albrechtalbrecht// // Rectangle drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Note: // This file doesn't contribute any code to the library. // It is kept as a placeholder for future usage. // This file is not compiled (as of Aug 2017) // // Fl_OpenGL_Graphics_Driver is implemented in several files // named Fl_OpenGL_Graphics_Driver_*.cxx. // This may be changed in the future. #include #include "Fl_OpenGL_Graphics_Driver.H" fltk-1.4.3/src/drivers/OpenGL/Fl_OpenGL_Display_Device.H0000644000175000017500000000155615004135251023027 0ustar albrechtalbrecht// // Definition of class Fl_OpenGL_Display_Device for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include class Fl_OpenGL_Graphics_Driver; /** OpenGL Surface. This surface is needed as an interface between GL windows and the GL graphics driver. */ class Fl_OpenGL_Display_Device : public Fl_Surface_Device { Fl_OpenGL_Display_Device(Fl_OpenGL_Graphics_Driver *graphics_driver); public: static Fl_OpenGL_Display_Device *display_device(); }; fltk-1.4.3/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.cxx0000644000175000017500000002424715004135251024650 0ustar albrechtalbrecht// // Rectangle drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_OpenGL_Graphics_Driver_rect.cxx \brief OpenGL specific line and polygon drawing with integer coordinates. */ #include #include "Fl_OpenGL_Graphics_Driver.H" #include #include #include #include #include // --- line and polygon drawing with integer coordinates void Fl_OpenGL_Graphics_Driver::point(int x, int y) { if (line_width_ == 1.0f) { glBegin(GL_POINTS); glVertex2f(x+0.5f, y+0.5f); glEnd(); } else { float offset = line_width_ / 2.0f; float xx = x+0.5f, yy = y+0.5f; glRectf(xx-offset, yy-offset, xx+offset, yy+offset); } } void Fl_OpenGL_Graphics_Driver::rect(int x, int y, int w, int h) { float offset = line_width_ / 2.0f; float xx = x+0.5f, yy = y+0.5f; float rr = x+w-0.5f, bb = y+h-0.5f; glRectf(xx-offset, yy-offset, rr+offset, yy+offset); glRectf(xx-offset, bb-offset, rr+offset, bb+offset); glRectf(xx-offset, yy-offset, xx+offset, bb+offset); glRectf(rr-offset, yy-offset, rr+offset, bb+offset); } void Fl_OpenGL_Graphics_Driver::rectf(int x, int y, int w, int h) { if (w<=0 || h<=0) return; glRectf((GLfloat)x, (GLfloat)y, (GLfloat)(x+w), (GLfloat)(y+h)); } void Fl_OpenGL_Graphics_Driver::line(int x, int y, int x1, int y1) { if (x==x1 && y==y1) return; if (x==x1) { yxline(x, y, y1); return; } if (y==y1) { xyline(x, y, x1); return; } float xx = x+0.5f, xx1 = x1+0.5f; float yy = y+0.5f, yy1 = y1+0.5f; if (line_width_==1.0f) { glBegin(GL_LINE_STRIP); glVertex2f(xx, yy); glVertex2f(xx1, yy1); glEnd(); } else { float dx = xx1-xx, dy = yy1-yy; float len = sqrtf(dx*dx+dy*dy); dx = dx/len*line_width_*0.5f; dy = dy/len*line_width_*0.5f; glBegin(GL_TRIANGLE_STRIP); glVertex2f(xx-dy, yy+dx); glVertex2f(xx+dy, yy-dx); glVertex2f(xx1-dy, yy1+dx); glVertex2f(xx1+dy, yy1-dx); glEnd(); } } void Fl_OpenGL_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { // TODO: no corner types (miter) yet line(x, y, x1, y1); line(x1, y1, x2, y2); } void Fl_OpenGL_Graphics_Driver::xyline(int x, int y, int x1) { float offset = line_width_ / 2.0f; float xx = (float)x, yy = y+0.5f, rr = x1+1.0f; glRectf(xx, yy-offset, rr, yy+offset); } void Fl_OpenGL_Graphics_Driver::xyline(int x, int y, int x1, int y2) { float offset = line_width_ / 2.0f; float xx = (float)x, yy = y+0.5f, rr = x1+0.5f, bb = y2+1.0f; glRectf(xx, yy-offset, rr+offset, yy+offset); glRectf(rr-offset, yy+offset, rr+offset, bb); } void Fl_OpenGL_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { float offset = line_width_ / 2.0f; float xx = (float)x, yy = y+0.5f, xx1 = x1+0.5f, rr = x3+1.0f, bb = y2+0.5f; glRectf(xx, yy-offset, xx1+offset, yy+offset); glRectf(xx1-offset, yy+offset, xx1+offset, bb+offset); glRectf(xx1+offset, bb-offset, rr, bb+offset); } void Fl_OpenGL_Graphics_Driver::yxline(int x, int y, int y1) { float offset = line_width_ / 2.0f; float xx = x+0.5f, yy = (float)y, bb = y1+1.0f; glRectf(xx-offset, yy, xx+offset, bb); } void Fl_OpenGL_Graphics_Driver::yxline(int x, int y, int y1, int x2) { float offset = line_width_ / 2.0f; float xx = x+0.5f, yy = (float)y, rr = x2+1.0f, bb = y1+0.5f; glRectf(xx-offset, yy, xx+offset, bb+offset); glRectf(xx+offset, bb-offset, rr, bb+offset); } void Fl_OpenGL_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { float offset = line_width_ / 2.0f; float xx = x+0.5f, yy = (float)y, yy1 = y1+0.5f, rr = x2+0.5f, bb = y3+1.0f; glRectf(xx-offset, yy, xx+offset, yy1+offset); glRectf(xx+offset, yy1-offset, rr+offset, yy1+offset); glRectf(rr-offset, yy1+offset, rr+offset, bb); } void Fl_OpenGL_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { glBegin(GL_LINE_LOOP); glVertex2i(x0, y0); glVertex2i(x1, y1); glVertex2i(x2, y2); glEnd(); } void Fl_OpenGL_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { glBegin(GL_LINE_LOOP); glVertex2i(x0, y0); glVertex2i(x1, y1); glVertex2i(x2, y2); glVertex2i(x3, y3); glEnd(); } void Fl_OpenGL_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { glBegin(GL_POLYGON); glVertex2i(x0, y0); glVertex2i(x1, y1); glVertex2i(x2, y2); glEnd(); } void Fl_OpenGL_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { glBegin(GL_POLYGON); glVertex2i(x0, y0); glVertex2i(x1, y1); glVertex2i(x2, y2); glVertex2i(x3, y3); glEnd(); } void Fl_OpenGL_Graphics_Driver::focus_rect(int x, int y, int w, int h) { float width = line_width_; int stipple = line_stipple_; line_style(FL_DOT, 1); glBegin(GL_LINE_LOOP); glVertex2f(x+0.5f, y+0.5f); glVertex2f(x+w+0.5f, y+0.5f); glVertex2f(x+w+0.5f, y+h+0.5f); glVertex2f(x+0.5f, y+h+0.5f); glEnd(); line_style(stipple, (int)width); } // ----------------------------------------------------------------------------- static int gl_min(int a, int b) { return (ab) ? a : b; } enum { kStateFull, // Region is the full window kStateRect, // Region is a rectangle kStateEmpty // Region is an empty space }; typedef struct Fl_Gl_Region { int x, y, w, h; int gl_x, gl_y, gl_w, gl_h; char state; void set(int inX, int inY, int inW, int inH) { if (inW<=0 || inH<=0) { state = kStateEmpty; x = inX; y = inY; w = 1; h = 1; // or 0? } else { x = inX; y = inY; w = inW; h = inH; state = kStateRect; } Fl_Gl_Window *win = Fl_Gl_Window::current()->as_gl_window(); if (win) { float scale = win->pixels_per_unit(); gl_x = int(x*scale); gl_y = int((win->h()-h-y+1)*scale); gl_w = int((w-1)*scale); gl_h = int((h-1)*scale); if (inX<=0 && inY<=0 && inX+inW>win->w() && inY+inH>=win->h()) { state = kStateFull; } } else { state = kStateFull; } } void set_full() { state = kStateFull; } void set_empty() { state = kStateEmpty; } void set_intersect(int inX, int inY, int inW, int inH, Fl_Gl_Region &g) { if (g.state==kStateFull) { set(inX, inY, inW, inH); } else if (g.state==kStateEmpty) { set_empty(); } else { int rx = gl_max(inX, g.x); int ry = gl_max(inY, g.y); int rr = gl_min(inX+inW, g.x+g.w); int rb = gl_max(inY+inH, g.y+g.h); set(rx, ry, rr-rx, rb-ry); } } void apply() { if (state==kStateFull) { glDisable(GL_SCISSOR_TEST); } else { glScissor(gl_x, gl_y, gl_w, gl_h); glEnable(GL_SCISSOR_TEST); } } } Fl_Gl_Region; static int gl_rstackptr = 0; static const int gl_region_stack_max = FL_REGION_STACK_SIZE - 1; static Fl_Gl_Region gl_rstack[FL_REGION_STACK_SIZE]; /* Intersect the given rect with the current rect, push the result on the stack, and apply the new clipping area. */ void Fl_OpenGL_Graphics_Driver::push_clip(int x, int y, int w, int h) { if (gl_rstackptr==gl_region_stack_max) { Fl::warning("Fl_OpenGL_Graphics_Driver::push_clip: clip stack overflow!\n"); return; } if (gl_rstackptr==0) { gl_rstack[gl_rstackptr].set(x, y, w, h); } else { gl_rstack[gl_rstackptr].set_intersect(x, y, w, h, gl_rstack[gl_rstackptr-1]); } gl_rstack[gl_rstackptr].apply(); gl_rstackptr++; } /* Remove the current clipping area and apply the previous one on the stack. */ void Fl_OpenGL_Graphics_Driver::pop_clip() { if (gl_rstackptr==0) { glDisable(GL_SCISSOR_TEST); Fl::warning("Fl_OpenGL_Graphics_Driver::pop_clip: clip stack underflow!\n"); return; } gl_rstackptr--; restore_clip(); } /* Push a full area onton the stack, so no clipping will take place. */ void Fl_OpenGL_Graphics_Driver::push_no_clip() { if (gl_rstackptr==gl_region_stack_max) { Fl::warning("Fl_OpenGL_Graphics_Driver::push_no_clip: clip stack overflow!\n"); return; } gl_rstack[gl_rstackptr].set_full(); gl_rstack[gl_rstackptr].apply(); gl_rstackptr++; } /* We don't know the format of clip regions of the default driver, so return NULL. */ Fl_Region Fl_OpenGL_Graphics_Driver::clip_region() { return NULL; } /* We don't know the format of clip regions of the default driver, so do the best we can. */ void Fl_OpenGL_Graphics_Driver::clip_region(Fl_Region r) { if (r==NULL) { glDisable(GL_SCISSOR_TEST); } else { restore_clip(); } } /* Apply the current clipping rect. */ void Fl_OpenGL_Graphics_Driver::restore_clip() { if (gl_rstackptr==0) { glDisable(GL_SCISSOR_TEST); } else { gl_rstack[gl_rstackptr-1].apply(); } } /* Does the rectangle intersect the current clip region? 0 = regions don't intersect, nothing to draw 1 = region is fully inside current clipping region 2 = region is partially inside current clipping region */ int Fl_OpenGL_Graphics_Driver::not_clipped(int x, int y, int w, int h) { if (gl_rstackptr==0) return 1; Fl_Gl_Region &g = gl_rstack[gl_rstackptr-1]; if (g.state==kStateFull) return 1; if (g.state==kStateEmpty) return 0; int r = x+w, b = y + h; int gr = g.x+g.w, gb = g.y+g.h; if (r<=g.x || x>=gr || b<=g.y || y>=gb) return 0; if (x>=g.x && y>=g.y && r<=gr && b<=gb) return 1; return 2; } /* Calculate the intersection of the given rect and the clipping area. Return 0 if the result did not change. */ int Fl_OpenGL_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) { X = x; Y = y; W = w; H = h; if (gl_rstackptr==0) return 0; Fl_Gl_Region &g = gl_rstack[gl_rstackptr-1]; if (g.state==kStateFull) return 0; int r = x+w, b = y + h; int gr = g.x+g.w, gb = g.y+g.h; X = gl_max(x, g.x); Y = gl_max(y, g.y); W = gl_min(r, gr) - X; H = gl_min(b, gb) - Y; return (x!=X || y!=Y || w!=W || h!=H); } fltk-1.4.3/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.cxx0000644000175000017500000002051415004135251024652 0ustar albrechtalbrecht// // Standard X11 font selection code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* This module implements a lowest-common-denominator font for OpenGL. It will always work, even if the main graphics library does not support rendering text into a texture buffer. The font is limited to a single face and ASCII characters. It is drawn using lines which makes it arbitrarily scalable. I am trying to keep font data really compact. */ #include #include "Fl_OpenGL_Graphics_Driver.H" #include #include #include #include #include // FIXME: check out FreeGlut: // FIXME: implement font-to-RGBA in the main graphics driver #if 0 /* |01234567| -+--------+ 0| |____ 1|++++++++|font 2|++++++++| 3|++++++++| 4|++++++++| 5|++++++++|____ 6| |descent 7| | -+--------+ */ static const char *font_data[128] = { /*00*/0, /*01*/0, /*02*/0, /*03*/0, /*04*/0, /*05*/0, /*06*/0, /*07*/0, /*08*/0, /*09*/0, /*0A*/0, /*0B*/0, /*0C*/0, /*0D*/0, /*0E*/0, /*0F*/0, /*10*/0, /*11*/0, /*12*/0, /*13*/0, /*14*/0, /*15*/0, /*16*/0, /*17*/0, /*18*/0, /*19*/0, /*1A*/0, /*1B*/0, /*1C*/0, /*1D*/0, /*1E*/0, /*1F*/0, /* */0, /* ! */"\31\34\100\35\36", /*"*/"\31\22\100\51\42", /*#*/"\31\15\100\61\45\100\12\72\100\04\64", /*$*/"\62\51\11\02\13\53\64\55\15\04\100\30\36", /*%*/"\21\11\02\13\23\32\21\100\15\51\100\34\43\53\64\55\45\34", /*&*/"\63\45\15\04\13\52\41\21\12\65", /*'*/"\31\22", /*(*/"\51\32\23\24\35\56", /*)*/"\21\42\53\54\45\26", /* * */"\31\33\15\100\33\55\100\02\33\62", /*+*/"\35\31\100\03\63", /*,*/"\35\45\36", /*-*/"\13\53", /*.*/"\35\36", /* / */"\51\15", /*0*/"\21\12\14\25\55\64\62\51\21\100\24\52", /*1*/"\22\41\45", /*2*/"\12\21\51\62\53\24\15\65", /*3*/"\12\21\51\62\53\64\55\25\14\100\53\33", /*4*/"\55\51\04\64", /*5*/"\14\25\55\64\53\13\21\61", /*6*/"\62\51\21\12\14\25\55\64\53\13", /*7*/"\11\61\33\25", /*8*/"\12\21\51\62\53\64\55\25\14\23\12\100\23\53", /*9*/"\14\25\55\64\62\51\21\12\23\63", /*:*/"\32\33\100\35\36", /*;*/"\32\33\100\25\35\26", /*<*/"\62\13\64", /*=*/"\12\62\100\14\64", /*>*/"\12\63\14", /*?*/"\12\21\51\62\43\34\35\100\36\37", /*@*/"\56\16\05\02\11\51\62\64\55\35\24\23\32\52\63", /*A*/"\05\31\65\100\14\54", /*B*/"\11\51\62\53\64\55\15\11\100\13\53", /*C*/"\62\51\11\02\04\15\55\64", /*D*/"\11\51\62\64\55\15\11", /*E*/"\61\11\15\65\100\13\53", /*F*/"\61\11\15\100\13\53", /*G*/"\62\51\11\02\04\15\55\64\63\33", /*H*/"\11\15\100\61\65\100\13\63", /*I*/"\21\41\100\25\45\100\35\31", /*J*/"\51\54\45\15\04", /*K*/"\11\15\100\14\61\100\65\33", /*L*/"\11\15\65", /*M*/"\05\01\35\61\65", /*N*/"\05\01\65\61", /*O*/"\02\11\51\62\64\55\15\04\02", /*P*/"\15\11\51\62\53\13", /*Q*/"\02\11\51\62\64\55\15\04\02\100\65\34", /*R*/"\15\11\51\62\53\13\100\33\65", /*S*/"\62\51\11\02\13\53\64\55\15\04", /*T*/"\01\61\100\31\35", /*U*/"\61\64\55\15\04\01", /*V*/"\01\35\61", /*W*/"\01\15\31\55\61", /*X*/"\01\65\100\05\61", /*Y*/"\01\33\35\100\33\61", /*Z*/"\01\61\05\65", /*[*/"\51\31\36\56", /*\*/"\21\55", /*]*/"\21\41\46\26", /*^*/"\13\31\53", /*_*/"\06\76", /*`*/"\31\42", /*a*/"\22\52\63\65\100\63\23\14\25\55\64", /*b*/"\11\15\100\14\25\55\64\63\52\22\13", /*c*/"\63\52\22\13\14\25\55\64", /*d*/"\61\65\100\64\55\25\14\13\22\52\63", /*e*/"\64\63\52\22\13\14\25\55\100\64\14", /*f*/"\35\32\41\51\100\22\52", /*g*/"\62\65\56\26\100\63\52\22\13\14\25\55\64", /*h*/"\11\15\100\65\63\52\22\13", /*i*/"\31\32\100\33\100\23\33\35\100\25\45", /*j*/"\31\32\100\33\35\26\16", /*k*/"\11\15\100\14\62\100\33\65", /*l*/"\31\34\45\55", /*m*/"\05\02\100\03\12\22\33\35\100\33\42\52\63\65", /*n*/"\12\15\100\13\22\52\63\65", /*o*/"\22\13\14\25\55\64\63\52\22", /*p*/"\16\12\100\13\22\52\63\64\55\25\14", /*q*/"\62\66\100\63\52\22\13\14\25\55\64", /*r*/"\22\25\100\23\32\42\53", /*s*/"\63\52\22\13\64\55\25\14", /*t*/"\31\34\45\55\100\22\42", /*u*/"\12\14\25\55\64\62\100\64\65", /*v*/"\62\35\02", /*w*/"\02\15\32\55\62", /*x*/"\62\15\100\65\12", /*y*/"\12\45\62\100\45\36\16", /*z*/"\12\62\15\65", /*{*/"\51\41\32\33\24\35\36\47\57\100\14\24", /*|*/"\31\37", /*}*/"\21\31\42\43\54\64\100\54\45\46\37\27", /*~*/"\12\21\31\42\52\61", /*7F*/0 }; void Fl_OpenGL_Graphics_Driver::font(Fl_Font face, Fl_Fontsize fsize) { Fl_Graphics_Driver::font(face, fsize); } double Fl_OpenGL_Graphics_Driver::width(const char *str, int n) { return size_*n*0.5; } int Fl_OpenGL_Graphics_Driver::descent() { return (int)(size_ - size_*0.8); } int Fl_OpenGL_Graphics_Driver::height() { return (int)(size_); } void Fl_OpenGL_Graphics_Driver::text_extents(const char *str, int n, int& dx, int& dy, int& w, int& h) { dx = 0; dy = descent(); w = (int)width(str, n); h = size_; } void Fl_OpenGL_Graphics_Driver::draw(const char *str, int n, int x, int y) { int i; for (i=0; i63) { if (cmd=='\100' && rendering) { glEnd(); glBegin(GL_POINTS); glVertex2f(px, py); glEnd(); rendering = 0; } } else { if (!rendering) { glBegin(GL_LINE_STRIP); rendering = 1; } int vx = (cmd & '\70')>>3; int vy = (cmd & '\07'); px = (int)(0.5+x+vx*size_*0.5/8.0); py = (int)(0.5+y+vy*size_/8.0-0.8*size_); glVertex2f(px, py); } } } x += size_*0.5; } } #elif 0 /* extern FL_EXPORT Fl_Glut_StrokeFont glutStrokeRoman; extern FL_EXPORT Fl_Glut_StrokeFont glutStrokeMonoRoman; # define GLUT_STROKE_ROMAN (&glutStrokeRoman) # define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) FL_EXPORT void glutStrokeCharacter(void *font, int character); FL_EXPORT GLfloat glutStrokeHeight(void *font); FL_EXPORT int glutStrokeLength(void *font, const unsigned char *string); FL_EXPORT void glutStrokeString(void *font, const unsigned char *string); FL_EXPORT int glutStrokeWidth(void *font, int character); */ #else // use gl_font()/gl_draw() to draw GL text void Fl_OpenGL_Graphics_Driver::font(Fl_Font face, Fl_Fontsize fsize) { Fl_Graphics_Driver::font(face, fsize); Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); gl_font(face, fsize); Fl_Surface_Device::pop_current(); } Fl_Font Fl_OpenGL_Graphics_Driver::font() { return Fl_Graphics_Driver::font(); } void Fl_OpenGL_Graphics_Driver::draw(const char *str, int n, float x, float y) { this->draw(str, n, int(x), int(y)); } void Fl_OpenGL_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {} void Fl_OpenGL_Graphics_Driver::draw(const char* str, int n, int x, int y) { Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); gl_draw(str, n, x, y); Fl_Surface_Device::pop_current(); } double Fl_OpenGL_Graphics_Driver::width(const char *str, int n) { Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); double w = fl_width(str, n); Fl_Surface_Device::pop_current(); return w; } double Fl_OpenGL_Graphics_Driver::width(unsigned int c) { return Fl_Graphics_Driver::width(c); } int Fl_OpenGL_Graphics_Driver::descent() { Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); int d = fl_descent(); Fl_Surface_Device::pop_current(); return d; } int Fl_OpenGL_Graphics_Driver::height() { Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); int h = fl_height(); Fl_Surface_Device::pop_current(); return h; } void Fl_OpenGL_Graphics_Driver::text_extents(const char *str, int n, int& dx, int& dy, int& w, int& h) { Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); fl_text_extents(str, n, dx, dy, w, h); Fl_Surface_Device::pop_current(); } #endif fltk-1.4.3/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.cxx0000644000175000017500000000406315004135251026054 0ustar albrechtalbrecht// // Line style code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_OpenGL_Graphics_Driver_line_style.cxx \brief Line style drawing utility hiding different platforms. */ #include #include "Fl_OpenGL_Graphics_Driver.H" #include #include #include #include #include // OpenGL implementation does not support custom patterns // OpenGL implementation does not support cap and join types void Fl_OpenGL_Graphics_Driver::line_style(int style, int width, char* dashes) { if (width<1) width = 1; line_width_ = (float)width; int stipple = style & 0x00ff; line_stipple_ = stipple; // int cap = style & 0x0f00; // int join = style & 0xf000; if (stipple==FL_SOLID) { glLineStipple(1, 0xFFFF); glDisable(GL_LINE_STIPPLE); } else { char enable = 1; switch (stipple & 0x00ff) { case FL_DASH: glLineStipple(GLint(pixels_per_unit_*line_width_), 0x0F0F); // ....****....**** break; case FL_DOT: glLineStipple(GLint(pixels_per_unit_*line_width_), 0x5555); // .*.*.*.*.*.*.*.* break; case FL_DASHDOT: glLineStipple(GLint(pixels_per_unit_*line_width_), 0x2727); // ..*..***..*..*** break; case FL_DASHDOTDOT: glLineStipple(GLint(pixels_per_unit_*line_width_), 0x5757); // .*.*.***.*.*.*** break; default: glLineStipple(1, 0xFFFF); enable = 0; } if (enable) glEnable(GL_LINE_STIPPLE); else glDisable(GL_LINE_STIPPLE); } glLineWidth( (GLfloat)(pixels_per_unit_ * line_width_) ); glPointSize( (GLfloat)(pixels_per_unit_) ); } fltk-1.4.3/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.cxx0000644000175000017500000000417415004135251024626 0ustar albrechtalbrecht// // Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_OpenGL_Graphics_Driver_arci.cxx \brief Utility functions for drawing circles using integers */ #include #include "Fl_OpenGL_Graphics_Driver.H" #include #include #include #include #include #define _USE_MATH_DEFINES #include void Fl_OpenGL_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) { if (w <= 0 || h <= 0) return; while (a2h) rMax = rx; else rMax = ry; int nSeg = (int)(10 * sqrt(rMax))+1; double incr = (a2-a1)/(double)nSeg; glBegin(GL_LINE_STRIP); for (int i=0; i<=nSeg; i++) { glVertex2d(cx+cos(a1)*rx, cy-sin(a1)*ry); a1 += incr; } glEnd(); } void Fl_OpenGL_Graphics_Driver::arc(double x, double y, double r, double start, double end) { Fl_Graphics_Driver::arc(x, y, r, start, end); } void Fl_OpenGL_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) { if (w <= 0 || h <= 0) return; while (a2h) rMax = rx; else rMax = ry; int nSeg = (int)(10 * sqrt(rMax))+1; double incr = (a2-a1)/(double)nSeg; glBegin(GL_TRIANGLE_FAN); glVertex2d(cx, cy); for (int i=0; i<=nSeg; i++) { glVertex2d(cx+cos(a1)*rx, cy-sin(a1)*ry); a1 += incr; } glEnd(); } fltk-1.4.3/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H0000644000175000017500000001005015004135251023203 0ustar albrechtalbrecht// // Definition of OpenGL graphics driver // for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_OpenGL_Graphics_Driver.H \brief Definition of OpenGL graphics driver. */ #ifndef FL_OPENGL_GRAPHICS_DRIVER_H #define FL_OPENGL_GRAPHICS_DRIVER_H #include #include /** \brief OpenGL specific graphics class. */ class Fl_OpenGL_Graphics_Driver : public Fl_Graphics_Driver { public: float pixels_per_unit_; float line_width_; int line_stipple_; Fl_OpenGL_Graphics_Driver() : pixels_per_unit_(1.0f), line_width_(1.0f), line_stipple_(FL_SOLID) { } // --- line and polygon drawing with integer coordinates void point(int x, int y) FL_OVERRIDE; void rect(int x, int y, int w, int h) FL_OVERRIDE; void rectf(int x, int y, int w, int h) FL_OVERRIDE; void line(int x, int y, int x1, int y1) FL_OVERRIDE; void line(int x, int y, int x1, int y1, int x2, int y2) FL_OVERRIDE; void xyline(int x, int y, int x1) FL_OVERRIDE; void xyline(int x, int y, int x1, int y2) FL_OVERRIDE; void xyline(int x, int y, int x1, int y2, int x3) FL_OVERRIDE; void yxline(int x, int y, int y1) FL_OVERRIDE; void yxline(int x, int y, int y1, int x2) FL_OVERRIDE; void yxline(int x, int y, int y1, int x2, int y3) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void focus_rect(int x, int y, int w, int h) FL_OVERRIDE; // ---- clipping void push_clip(int x, int y, int w, int h) FL_OVERRIDE; void pop_clip() FL_OVERRIDE; void push_no_clip() FL_OVERRIDE; Fl_Region clip_region() FL_OVERRIDE; void clip_region(Fl_Region r) FL_OVERRIDE; void restore_clip() FL_OVERRIDE; int not_clipped(int x, int y, int w, int h) FL_OVERRIDE; int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) FL_OVERRIDE; // ---- matrix transformed drawing void transformed_vertex(double xf, double yf) FL_OVERRIDE; void begin_points() FL_OVERRIDE; void end_points() FL_OVERRIDE; void begin_line() FL_OVERRIDE; void end_line() FL_OVERRIDE; void begin_loop() FL_OVERRIDE; void end_loop() FL_OVERRIDE; void begin_polygon() FL_OVERRIDE; void end_polygon() FL_OVERRIDE; void begin_complex_polygon() FL_OVERRIDE; void gap() FL_OVERRIDE; void end_complex_polygon() FL_OVERRIDE; void fixloop() FL_OVERRIDE; void circle(double x, double y, double r) FL_OVERRIDE; void arc(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void arc(double x, double y, double r, double start, double end) FL_OVERRIDE; void pie(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void line_style(int style, int width=0, char* dashes=0) FL_OVERRIDE; void color(Fl_Color c) FL_OVERRIDE; Fl_Color color() FL_OVERRIDE { return color_; } void color(uchar r, uchar g, uchar b) FL_OVERRIDE; // --- implementation is in Fl_OpenGL_Graphics_Driver_font.cxx void font(Fl_Font face, Fl_Fontsize fsize) FL_OVERRIDE; Fl_Font font() FL_OVERRIDE; void draw(const char *str, int n, int x, int y) FL_OVERRIDE; void draw(const char *str, int n, float x, float y) FL_OVERRIDE; void draw(int angle, const char *str, int n, int x, int y) FL_OVERRIDE; double width(const char *str, int n) FL_OVERRIDE; double width(unsigned int c) FL_OVERRIDE; void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h) FL_OVERRIDE; int height() FL_OVERRIDE; int descent() FL_OVERRIDE; }; #endif // FL_OPENGL_GRAPHICS_DRIVER_H fltk-1.4.3/src/drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.cxx0000644000175000017500000000247615004135251025031 0ustar albrechtalbrecht// // Color functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file fl_color.cxx \brief Color handling */ #include #include "Fl_OpenGL_Graphics_Driver.H" #include #include #include #include #include // Implementation of fl_color(i), fl_color(r,g,b). extern unsigned fl_cmap[256]; // defined in fl_color.cxx void Fl_OpenGL_Graphics_Driver::color(Fl_Color i) { if (i & 0xffffff00) { unsigned rgba = ((unsigned)i)^0x000000ff; Fl_Graphics_Driver::color(i); glColor4ub(rgba>>24, rgba>>16, rgba>>8, rgba); } else { unsigned rgba = ((unsigned)fl_cmap[i])^0x000000ff; Fl_Graphics_Driver::color(fl_cmap[i]); glColor4ub(rgba>>24, rgba>>16, rgba>>8, rgba); } } void Fl_OpenGL_Graphics_Driver::color(uchar r, uchar g, uchar b) { Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) ); glColor3ub(r,g,b); } fltk-1.4.3/src/drivers/SVG/0000755000175000017500000000000015004135251015511 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/SVG/Fl_SVG_File_Surface.cxx0000644000175000017500000011220515004135251021725 0ustar albrechtalbrecht// // Implementation of classes Fl_SVG_Graphics_Driver and Fl_SVG_File_Surface in the Fast Light Tool Kit (FLTK). // // Copyright 2020-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Complete implementation to draw into an SVG file using the standard FLTK drawing API. #include #include #ifdef FLTK_USE_SVG #include #include #include #include #include #include "../../Fl_System_Driver.H" #include #include #include #include #include #include #include extern "C" { #if defined(HAVE_LIBPNG) # ifdef HAVE_PNG_H # include # else # include # endif // HAVE_PNG_H #endif // HAVE_LIBPNG #ifdef HAVE_LIBJPEG # include #endif // HAVE_LIBJPEG } class Fl_SVG_Graphics_Driver : public Fl_Graphics_Driver { FILE *out_; int width_; int line_style_; const char *linecap_; const char *linejoin_; uchar red_, green_, blue_; char *dasharray_; // the dash array as SVG needs it char *user_dash_array_; // the dash array as FLTK needs it class Clip { public: int x, y, w, h; // the clip rectangle char Id[12]; // "none" or SVG Id of this clip rectangle Clip *prev; // previous in pile of clips }; Clip * clip_; // top of pile of clips int clip_count_; // to generate distinct SVG clip Ids char *last_rgb_name_; // NULL or SVG Id of last defined RGB image const char *family_; const char *bold_; const char *style_; public: Fl_SVG_Graphics_Driver(FILE*); ~Fl_SVG_Graphics_Driver(); FILE* file() {return out_;} protected: int clocale_printf(const char *format, ...); void rect(int x, int y, int w, int h) FL_OVERRIDE; void rectf(int x, int y, int w, int h) FL_OVERRIDE; virtual void compute_dasharray(float s, char *dashes=0); void line_style(int style, int width, char *dashes=0) FL_OVERRIDE; void line(int x1, int y1, int x2, int y2) FL_OVERRIDE; void line(int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void font_(int f, int s); void font(int f, int s) FL_OVERRIDE; Fl_Font font() FL_OVERRIDE; void draw(const char *str, int n, int x, int y) FL_OVERRIDE; void draw(const char*, int, float, float) FL_OVERRIDE; void draw(int, const char*, int, int, int) FL_OVERRIDE; void rtl_draw(const char *str, int n, int x, int y) FL_OVERRIDE; void color(uchar r, uchar g, uchar b) FL_OVERRIDE; void color(Fl_Color c) FL_OVERRIDE; Fl_Color color() FL_OVERRIDE; double width(const char*, int) FL_OVERRIDE; double width(unsigned int c) FL_OVERRIDE; void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h) FL_OVERRIDE; int height() FL_OVERRIDE; int descent() FL_OVERRIDE; void draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void define_rgb_png(Fl_RGB_Image *rgb, const char *name, int x, int y); void define_rgb_jpeg(Fl_RGB_Image *rgb, const char *name, int x, int y); void draw_pixmap(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_bitmap(Fl_Bitmap *bm,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l) FL_OVERRIDE; void draw_image(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h, int d) FL_OVERRIDE; void draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l) FL_OVERRIDE; void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h, int d) FL_OVERRIDE; void push_clip(int x, int y, int w, int h) FL_OVERRIDE; void push_no_clip() FL_OVERRIDE; void pop_clip() FL_OVERRIDE; int clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H) FL_OVERRIDE; int not_clipped(int x, int y, int w, int h) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void point(int x, int y) FL_OVERRIDE; void end_points() FL_OVERRIDE; void end_line() FL_OVERRIDE; void end_polygon() FL_OVERRIDE; void end_complex_polygon() FL_OVERRIDE; void circle(double x, double y,double r) FL_OVERRIDE; void arc(int x,int y,int w,int h,double a1,double a2) FL_OVERRIDE; void arc(double x, double y, double r, double start, double end) FL_OVERRIDE; void pie(int x,int y,int w,int h,double a1,double a2) FL_OVERRIDE; void arc_pie(char AorP, int x, int y, int w, int h, double a1, double a2); }; Fl_SVG_Graphics_Driver::Fl_SVG_Graphics_Driver(FILE *f) { out_ = f; width_ = 1; line_style_ = 0; linecap_ = "butt"; linejoin_ = "miter"; family_ = ""; bold_ = ""; style_ = ""; red_ = green_ = blue_ = 0; clip_count_ = 0; clip_ = NULL; user_dash_array_ = 0; dasharray_ = fl_strdup("none"); p_size = 0; last_rgb_name_ = NULL; } Fl_SVG_Graphics_Driver::~Fl_SVG_Graphics_Driver() { if (user_dash_array_) free(user_dash_array_); if (dasharray_) free(dasharray_); while (clip_){ Clip * c= clip_; clip_= clip_->prev; delete c; } if (last_rgb_name_) free(last_rgb_name_); } int Fl_SVG_Graphics_Driver::clocale_printf(const char *format, ...) { va_list args; va_start(args, format); int retval = Fl::system_driver()->clocale_vprintf(out_, format, args); va_end(args); return retval; } static int clocale_fprintf(FILE *f, const char *format, ...) { va_list args; va_start(args, format); int retval = Fl::system_driver()->clocale_vprintf(f, format, args); va_end(args); return retval; } void Fl_SVG_Graphics_Driver::rect(int x, int y, int w, int h) { fprintf(out_, "\n", x, y, w-1, h-1, red_, green_, blue_, width_, dasharray_, linecap_, linejoin_); } void Fl_SVG_Graphics_Driver::rectf(int x, int y, int w, int h) { clocale_fprintf(out_, "\n", x-.5, y-.5, w, h, red_, green_, blue_); } void Fl_SVG_Graphics_Driver::point(int x, int y) { rectf(x,y,1,1); } void Fl_SVG_Graphics_Driver::line(int x1, int y1, int x2, int y2) { fprintf(out_, "\n", x1,y1,x2,y2, red_, green_, blue_, width_, linecap_, linejoin_, dasharray_); } void Fl_SVG_Graphics_Driver::line(int x1, int y1, int x2, int y2, int x3, int y3) { fprintf(out_, "\n", x1, y1, x2, y2, x3, y3, red_, green_, blue_, width_, linecap_, linejoin_, dasharray_); } void Fl_SVG_Graphics_Driver::font_(int ft, int s) { Fl_Graphics_Driver::font(ft, s); int famnum = ft/4; if (famnum == 0) family_ = "Helvetica"; else if (famnum == 1) family_ = "Courier"; else family_ = "Times"; int modulo = ft % 4; int use_bold = modulo == 1 || modulo == 3; int use_italic = modulo >= 2; bold_ = ( use_bold ? " font-weight=\"bold\"" : "" ); style_ = ( use_italic ? " font-style=\"italic\"" : "" ); if (use_italic && famnum != 2) style_ = " font-style=\"oblique\""; } void Fl_SVG_Graphics_Driver::font(int ft, int s) { Fl_Display_Device::display_device()->driver()->font(ft, s); font_(ft, s); } Fl_Font Fl_SVG_Graphics_Driver::font() { return Fl_Graphics_Driver::font(); } void Fl_SVG_Graphics_Driver::compute_dasharray(float s, char *dashes) { if (user_dash_array_ && user_dash_array_ != dashes) {free(user_dash_array_); user_dash_array_ = NULL;} if (dashes && *dashes) { if (dasharray_) free(dasharray_); int array_len = int(10*strlen(dashes) + 1); dasharray_ = (char*)calloc(array_len, 1); for (char *p = dashes; *p; p++) { int c = snprintf(dasharray_+strlen(dasharray_), array_len, "%.3f,", (*p)/s); array_len -= c; } dasharray_[strlen(dasharray_) - 1] = 0; if (user_dash_array_ != dashes) user_dash_array_ = fl_strdup(dashes); return; } int dash_part = line_style_ & 0xFF; if (dash_part == FL_SOLID) { if (strcmp(dasharray_, "none")) { free(dasharray_); dasharray_ = fl_strdup("none"); } } else { int cap_part = (line_style_ & 0xF00); bool is_flat = (cap_part == FL_CAP_FLAT || cap_part == 0); float dot = (is_flat ? width_/s : width_*0.6f/s); float gap = (is_flat ? width_/s : width_*1.5f/s); float big = (is_flat ? 3*width_/s : width_*2.5f/s); if (dasharray_) free(dasharray_); dasharray_ = (char*)malloc(61); if (dash_part == FL_DOT) snprintf(dasharray_, 61, "%.3f,%.3f", dot, gap); else if (dash_part == FL_DASH) snprintf(dasharray_, 61, "%.3f,%.3f", big, gap); else if (dash_part == FL_DASHDOT) snprintf(dasharray_, 61, "%.3f,%.3f,%.3f,%.3f", big, gap, dot, gap); else snprintf(dasharray_, 61, "%.3f,%.3f,%.3f,%.3f,%.3f,%.3f", big, gap, dot, gap, dot, gap); } } void Fl_SVG_Graphics_Driver::line_style(int style, int width, char *dashes) { line_style_ = style; if (width == 0) width = 1; width_ = width; int cap_part = style & 0xF00; if (cap_part == FL_CAP_SQUARE) linecap_ = "square"; else if (cap_part == FL_CAP_ROUND) linecap_ = "round"; else linecap_ = "butt"; int join_part = style & 0xF000; if (join_part == FL_JOIN_BEVEL) linejoin_ = "bevel"; else if (join_part == FL_JOIN_MITER) linejoin_ = "miter"; else if (join_part == FL_JOIN_ROUND) linejoin_ = "round"; else linejoin_ = "miter"; compute_dasharray(1., dashes); } void Fl_SVG_Graphics_Driver::draw(const char *str, int n, int x, int y) { // Caution: Internet Explorer ignores the xml:space="preserve" attribute // work-around: replace all spaces by no-break space = U+00A0 = 0xC2-0xA0 (UTF-8) before sending to IE fprintf(out_, "", x, y, family_, bold_, style_, size(), red_, green_, blue_, (int)width(str, n)); for (int i = 0; i < n; i++) { if (str[i] == '&') fputs("&", out_); else if (str[i] == '<') fputs("<", out_); else if (str[i] == '>') fputs(">", out_); else fputc(str[i], out_); } fputs("\n", out_); } void Fl_SVG_Graphics_Driver::draw(const char* str, int n, float fx, float fy) { return draw(str, n, (int)fx, (int)fy); } void Fl_SVG_Graphics_Driver::draw(int angle, const char* str, int n, int x, int y) { fprintf(out_, "", x, y, -angle); draw(str, n, 0, 0); fputs("\n", out_); } void Fl_SVG_Graphics_Driver::rtl_draw(const char *str, int n, int x, int y) { int w = (int)width(str, n); draw(str, n, x - w, y); } void Fl_SVG_Graphics_Driver::color(Fl_Color c) { Fl_Graphics_Driver::color(c); Fl::get_color(c, red_, green_, blue_); } void Fl_SVG_Graphics_Driver::color(uchar r, uchar g, uchar b) { red_ = r; green_ = g; blue_ = b; } Fl_Color Fl_SVG_Graphics_Driver::color() { return Fl_Graphics_Driver::color(); } double Fl_SVG_Graphics_Driver::width(const char* str, int l) { return Fl_Display_Device::display_device()->driver()->width(str, l); } double Fl_SVG_Graphics_Driver::width(unsigned int c) { return Fl_Display_Device::display_device()->driver()->width(c); } void Fl_SVG_Graphics_Driver::text_extents(const char *c, int n, int& dx, int& dy, int& w, int& h) { Fl::first_window()->make_current(); // to get a valid drawing gc Fl_Display_Device::display_device()->driver()->text_extents(c, n, dx, dy, w, h); } int Fl_SVG_Graphics_Driver::height() { return Fl_Display_Device::display_device()->driver()->height(); } int Fl_SVG_Graphics_Driver::descent() { return Fl_Display_Device::display_device()->driver()->descent(); } Fl_SVG_File_Surface::Fl_SVG_File_Surface(int w, int h, FILE *f, int (*closef)(FILE*)) : Fl_Widget_Surface(new Fl_SVG_Graphics_Driver(f)) { closef_ = closef; Fl_Window *win = Fl::first_window(); float s = (win ? Fl::screen_scale(win->screen_num()) : 1); int sw = int(w * s), sh = int(h * s); fprintf(f, "\n" "\n" "\n", sw, sh, sw, sh); width_ = w; height_ = h; clocale_fprintf(f, "\n", s); fputs("\n", f); } Fl_SVG_File_Surface::~Fl_SVG_File_Surface() { if (driver()) close(); } FILE *Fl_SVG_File_Surface::file() { Fl_SVG_Graphics_Driver *driver = (Fl_SVG_Graphics_Driver*)this->driver(); return driver->file(); } int Fl_SVG_File_Surface::close() { Fl_SVG_Graphics_Driver *driver = (Fl_SVG_Graphics_Driver*)this->driver(); fputs("\n", driver->file()); int retval = (closef_ ? closef_(driver->file()) : fclose(driver->file())); delete driver; this->driver(NULL); return retval; } void Fl_SVG_File_Surface::translate(int x, int y) { Fl_SVG_Graphics_Driver *driver = (Fl_SVG_Graphics_Driver*)this->driver(); fprintf(driver->file(), "\n", x, y); } void Fl_SVG_File_Surface::untranslate() { Fl_SVG_Graphics_Driver *driver = (Fl_SVG_Graphics_Driver*)this->driver(); fputs("\n", driver->file()); } void Fl_SVG_File_Surface::origin(int x, int y) { Fl_SVG_Graphics_Driver *driver = (Fl_SVG_Graphics_Driver*)this->driver(); fprintf(driver->file(), "\n", x, y); Fl_Widget_Surface::origin(x, y); } int Fl_SVG_File_Surface::printable_rect(int *w, int *h) { *w = width_; *h = height_; return 0; } struct svg_base64_t { // holds data useful to perform base64-encoding of a stream of bytes FILE *svg; // where base64-encoded data is output int lline; // follows length of current line in svg file uchar buff[3]; // holds up to 3 bytes that still need encoding int lbuf; // # of valid bytes in buff }; // Performs base64 encoding of up to 3 bytes. // To be called successively with 3 consecutive bytes (l=3), // and possibly with l=1 or l=2 only at the end of the byte stream. // Always writes 4 printable characters to the output FILE. static void to_base64(uchar *p, int l, svg_base64_t *svg_base64) { static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; uchar B0 = *p++; uchar B1 = (l == 1 ? 0 : *p++); uchar B2 = (l <= 2 ? 0 : *p); fputc(base64_table[ B0 >> 2 ], svg_base64->svg); fputc(base64_table[ ((B0 & 0x3) << 4) + (B1 >> 4) ], svg_base64->svg); fputc( (l == 1 ? '=' : base64_table[ ((B1 & 0xF) << 2) + (B2 >> 6) ]), svg_base64->svg ); fputc( (l < 3 ? '=' : base64_table[ B2 & 0x3F ]), svg_base64->svg ); svg_base64->lline += 4; if (svg_base64->lline >= 80) { fputc('\n', svg_base64->svg); svg_base64->lline = 0; } } // Writes to the svg file, in base64-encoded form, a block of length bytes. // 1 or 2 bytes may remain unprocessed after return. // Returns the number of remaining unprocessed bytes. static size_t write_by_3(uchar *data, size_t length, svg_base64_t *svg_base64) { while (length >= 3) { to_base64(data, 3, svg_base64); data += 3; length -= 3; } return length; } #ifdef HAVE_LIBPNG // processes length bytes of the png stream under construction static void user_write_data(png_structp png_ptr, png_bytep data, png_size_t length) { svg_base64_t *svg_base64_data = (svg_base64_t*)png_get_io_ptr(png_ptr); if (svg_base64_data->lbuf == 1 && length >= 2) { svg_base64_data->buff[1] = *data++; length--; svg_base64_data->buff[2] = *data++; length--; write_by_3(svg_base64_data->buff, 3, svg_base64_data); } else if (svg_base64_data->lbuf == 2 && length >= 1) { svg_base64_data->buff[2] = *data++; length--; write_by_3(svg_base64_data->buff, 3, svg_base64_data); } size_t new_l = length; if (length >= 3) { new_l = write_by_3(data, length, svg_base64_data); } svg_base64_data->lbuf = (int)new_l; if (new_l) { memcpy(svg_base64_data->buff, data + length - new_l, new_l); } } // processes last bytes to be base64 encoded static void user_flush_data(png_structp png_ptr) { svg_base64_t *svg_base64_data = (svg_base64_t*)png_get_io_ptr(png_ptr); if (svg_base64_data->lbuf) to_base64(svg_base64_data->buff, svg_base64_data->lbuf, svg_base64_data); } /* How to define first the image data and next use it, possibly several times: */ /* Specify image data and draw it in one go: */ void Fl_SVG_Graphics_Driver::define_rgb_png(Fl_RGB_Image *rgb, const char *name, int x, int y) { png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) return; png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return; } if (name) { if (last_rgb_name_) free(last_rgb_name_); last_rgb_name_ = fl_strdup(name); } float f = rgb->data_w() > rgb->data_h() ? float(rgb->w()) / rgb->data_w(): float(rgb->h()) / rgb->data_h(); if (name) fprintf(out_, "data_w(), f*rgb->data_h()); // Transforms the image into a stream of bytes in PNG format, // base64-encode this byte stream, and outputs the result to the svg FILE. svg_base64_t svg_base64_data; svg_base64_data.svg = out_; svg_base64_data.lline = 0; svg_base64_data.lbuf = 0; // user_write_data is a function repetitively called by libpng which receives blocks of bytes. png_set_write_fn(png_ptr, &svg_base64_data, user_write_data, user_flush_data); int color_type; switch (rgb->d()) { case 1: color_type = PNG_COLOR_TYPE_GRAY; break; case 2: color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; case 3: color_type = PNG_COLOR_TYPE_RGB; break; case 4: default: color_type = PNG_COLOR_TYPE_RGB_ALPHA; } png_set_IHDR(png_ptr, info_ptr, rgb->data_w(), rgb->data_h(), 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); const uchar **row_pointers = new const uchar*[rgb->data_h()]; int ld = rgb->ld() ? rgb->ld() : rgb->d() * rgb->data_w(); for (int i=0; i < rgb->data_h(); i++) row_pointers[i] = (rgb->array + i*ld); png_set_rows(png_ptr, info_ptr, (png_bytepp)row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); png_write_end(png_ptr, NULL); user_flush_data(png_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); delete[] row_pointers; if (name) fputs("\"/>\n", out_); else fputs("\"/>\n", out_); } #endif // HAVE_LIBPNG #ifdef HAVE_LIBJPEG struct jpeg_client_data_struct { JOCTET JPEG_BUFFER[50000]; size_t size; svg_base64_t base64_data; }; static void init_destination(jpeg_compress_struct *cinfo) { jpeg_client_data_struct *client_data = (jpeg_client_data_struct*)(cinfo->client_data); cinfo->dest->next_output_byte = client_data->JPEG_BUFFER; cinfo->dest->free_in_buffer = client_data->size; } static size_t process_jpeg_chunk(jpeg_compress_struct *cinfo, size_t length) { jpeg_client_data_struct *client_data = (jpeg_client_data_struct*)(cinfo->client_data); JOCTET *data = client_data->JPEG_BUFFER; size_t new_l = length; if (length >= 3) { new_l = write_by_3(data, length, &client_data->base64_data); if (new_l) memmove(client_data->JPEG_BUFFER, data + length - new_l, new_l); } cinfo->dest->next_output_byte = client_data->JPEG_BUFFER + new_l; cinfo->dest->free_in_buffer = client_data->size - new_l; return new_l; } static boolean empty_output_buffer(jpeg_compress_struct *cinfo) { jpeg_client_data_struct *client_data = (jpeg_client_data_struct*)(cinfo->client_data); process_jpeg_chunk(cinfo, client_data->size); return TRUE; } static void term_destination(jpeg_compress_struct *cinfo) { jpeg_client_data_struct *client_data = (jpeg_client_data_struct*)(cinfo->client_data); size_t new_l = process_jpeg_chunk(cinfo, client_data->size - cinfo->dest->free_in_buffer); if (new_l) { to_base64(client_data->JPEG_BUFFER, (int)new_l, &client_data->base64_data); } } void Fl_SVG_Graphics_Driver::define_rgb_jpeg(Fl_RGB_Image *rgb, const char *name, int x, int y) { if (name) { if (last_rgb_name_) free(last_rgb_name_); last_rgb_name_ = fl_strdup(name); } float f = rgb->data_w() > rgb->data_h() ? float(rgb->w()) / rgb->data_w(): float(rgb->h()) / rgb->data_h(); if (name) fprintf(out_, "data_w(), f*rgb->data_h()); // Transforms the image into a stream of bytes in JPEG format, // base64-encode this byte stream, and outputs the result to the svg FILE. jpeg_compress_struct cinfo; jpeg_error_mgr jerr; jpeg_client_data_struct jpeg_client_data; jpeg_client_data.size = sizeof(jpeg_client_data.JPEG_BUFFER); cinfo.client_data = &jpeg_client_data; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_destination_mgr jpeg_mgr; jpeg_mgr.init_destination = init_destination; jpeg_mgr.empty_output_buffer = empty_output_buffer; jpeg_mgr.term_destination = term_destination; cinfo.dest = &jpeg_mgr; cinfo.image_width = rgb->data_w(); cinfo.image_height = rgb->data_h(); cinfo.input_components = rgb->d(); // 1 or 3 cinfo.in_color_space = rgb->d() == 3 ? JCS_RGB : JCS_GRAYSCALE; jpeg_set_defaults(&cinfo); jpeg_client_data.base64_data.svg = out_; jpeg_client_data.base64_data.lline = 0; jpeg_client_data.base64_data.lbuf = 0; jpeg_start_compress(&cinfo, TRUE); int ld = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d(); JSAMPROW row_pointer[1]; while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = (uchar*)rgb->array + ld*cinfo.next_scanline; jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); if (name) fputs("\"/>\n", out_); else fputs("\"/>\n", out_); } #endif // HAVE_LIBJPEG void Fl_SVG_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) { #if defined(HAVE_LIBPNG) char name[24]; bool need_clip = (cx || cy || WP != rgb->w() || HP != rgb->h()); void *p = (void*)*Fl_Graphics_Driver::id(rgb); if (p) snprintf(name, 24, "FLrgb%p", p); else name[0] = 0; if (!p || !last_rgb_name_ || strcmp(name, last_rgb_name_) != 0) { if (*name==0 && need_clip) push_clip(XP, YP, WP, HP); #if defined(HAVE_LIBJPEG) if (rgb->d() == 3 || rgb->d() == 1) define_rgb_jpeg(rgb, *name ? name : NULL, XP-cx, YP-cy); else #endif // HAVE_LIBJPEG define_rgb_png(rgb, *name ? name : NULL, XP-cx, YP-cy); if (*name==0 && need_clip) pop_clip(); } if (*name) { if (need_clip) push_clip(XP, YP, WP, HP); fprintf(out_, "\n", last_rgb_name_, XP-cx, YP-cy); if (need_clip) pop_clip(); } #endif // HAVE_LIBPNG } void Fl_SVG_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { #if defined(HAVE_LIBPNG) char name[24]; bool need_clip = (cx || cy || WP != pxm->w() || HP != pxm->h()); void *p = (void*)*Fl_Graphics_Driver::id(pxm); if (p) snprintf(name, 24, "FLpx%p", p); else name[0] = 0; if (!p || !last_rgb_name_ || strcmp(name, last_rgb_name_) != 0) { Fl_RGB_Image *rgb = new Fl_RGB_Image(pxm); if (*name==0 && need_clip) push_clip(XP, YP, WP, HP); define_rgb_png(rgb, *name ? name : NULL, XP-cx, YP-cy); if (*name==0 && need_clip) pop_clip(); delete rgb; } if (*name) { if (need_clip) push_clip(XP, YP, WP, HP); fprintf(out_, "\n", last_rgb_name_, XP-cx, YP-cy); if (need_clip) pop_clip(); } #endif // HAVE_LIBPNG } void Fl_SVG_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { #if defined(HAVE_LIBPNG) char name[45]; bool need_clip = (cx || cy || WP != bm->w() || HP != bm->h()); void *p = (void*)*Fl_Graphics_Driver::id(bm); if (p) snprintf(name, 45, "FLbm%p%X", p, fl_color()); else name[0] = 0; if (!p || !last_rgb_name_ || strcmp(name, last_rgb_name_) != 0) { uchar R, G, B; Fl::get_color(fl_color(), R, G, B); uchar *data = new uchar[bm->data_w() * bm->data_h() * 4]; memset(data, 0, bm->data_w() * bm->data_h() * 4); Fl_RGB_Image *rgb = new Fl_RGB_Image(data, bm->data_w(), bm->data_h(), 4); rgb->alloc_array = 1; int rowBytes = (bm->data_w()+7)>>3 ; for (int j = 0; j < bm->data_h(); j++) { const uchar *p = bm->array + j*rowBytes; for (int i = 0; i < rowBytes; i++) { uchar q = *p; int last = bm->data_w() - 8*i; if (last > 8) last = 8; for (int k=0; k < last; k++) { if (q&1) { uchar *r = (uchar*)rgb->array + j*bm->data_w()*4 + i*8*4 + k*4; *r++ = R; *r++ = G; *r++ = B; *r = ~0; } q >>= 1; } p++; } } if (*name==0 && need_clip) push_clip(XP, YP, WP, HP); define_rgb_png(rgb, *name ? name : NULL, XP-cx, YP-cy); if (*name==0 && need_clip) pop_clip(); delete rgb; } if (*name) { if (need_clip) push_clip(XP, YP, WP, HP); fprintf(out_, "\n", last_rgb_name_, XP-cx, YP-cy); if (need_clip) pop_clip(); } #endif // HAVE_LIBPNG } void Fl_SVG_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l) { if (d < 0) { fprintf(out_, "\n", x, y); x = -w; y = 0; buf -= (w-1)*abs(d); } if (l < 0) { fprintf(out_, "\n", x, y); x = 0; y = -h; buf -= (h-1)*abs(l); } Fl_RGB_Image *rgb = new Fl_RGB_Image(buf, w, h, abs(d), abs(l)); rgb->draw(x, y); delete rgb; if (d < 0) fprintf(out_, "\n"); if (l < 0) fprintf(out_, "\n"); } void Fl_SVG_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h, int d) { uchar *buf = new uchar[w*h*d]; for (int j = 0; j < h; j++) { cb(data, 0, j, w, buf + j*w*d); } draw_image(buf, x, y, w, h, d, 0); delete [] buf; } struct mono_image_data { const uchar *buf; int d; int l; }; static void mono_image_cb(mono_image_data* data, int x, int y, int w, uchar* buf) { for (int i = 0; i < w; i++) *buf++ = *(data->buf + y*data->l + (x++)*data->d); } void Fl_SVG_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l) { mono_image_data data; data.buf = buf; data.d = d; data.l = (l?l:w*d); draw_image((Fl_Draw_Image_Cb)mono_image_cb, (void*)&data, x, y, w, h, 1); } void Fl_SVG_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h, int d) { uchar *buf = new uchar[w*h*d]; for (int j = 0; j < h; j++) { cb(data, 0, j, w, buf + j*w*d); } draw_image_mono(buf, x, y, w, h, d, 0); delete[] buf; } void Fl_SVG_Graphics_Driver::push_clip(int x, int y, int w, int h) { Clip * c=new Clip(); clip_box(x,y,w,h,c->x,c->y,c->w,c->h); c->prev=clip_; snprintf(c->Id, sizeof(c->Id), "FLclip%d", clip_count_++); clip_=c; fprintf(out_, "\n", c->Id, clip_->x , clip_->y , clip_->w, clip_->h, c->Id); } void Fl_SVG_Graphics_Driver::push_no_clip() { Clip * c=clip_; while (c) { fprintf(out_, ""); c = c->prev; } c=new Clip(); c->prev=clip_; strcpy(c->Id, "none"); // mark of no_clip clip_=c; fprintf(out_, "\n"); } void Fl_SVG_Graphics_Driver::pop_clip() { Clip *c; bool was_no_clip = clip_ && (strcmp(clip_->Id, "none") == 0); fprintf(out_, ""); if (clip_) { c = clip_; clip_ = clip_->prev; delete c; } if (was_no_clip) { Clip *next = NULL; c=clip_; while (c) { Clip *c2 = new Clip(*c); c2->prev = next; next = c2; c = c->prev; } while (next) { fprintf(out_, "", next->Id); c = next->prev; delete next; next = c; } } fprintf(out_, "\n"); } int Fl_SVG_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H) { if (!clip_) { X = x; Y = y; W = w; H = h; return 0; } if (clip_->w < 0) { X = x; Y = y; W = w; H = h; return 1; } int ret = 0; if (x > (X=clip_->x)) {X=x; ret=1;} if (y > (Y=clip_->y)) {Y=y; ret=1;} if ((x+w) < (clip_->x+clip_->w)) { W=x+w-X; ret=1; }else W = clip_->x + clip_->w - X; if(W<0){ W=0; return 1; } if ((y+h) < (clip_->y+clip_->h)) { H=y+h-Y; ret=1; }else H = clip_->y + clip_->h - Y; if(H<0){ W=0; H=0; return 1; } return ret; } int Fl_SVG_Graphics_Driver::not_clipped(int x, int y, int w, int h) { if (!clip_) return 1; if (clip_->w < 0) return 1; int X = 0, Y = 0, W = 0, H = 0; clip_box(x, y, w, h, X, Y, W, H); if (W) return 1; return 0; } void Fl_SVG_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { fprintf(out_, "\n", x0, y0, x1, y1, x2, y2, red_, green_, blue_); } void Fl_SVG_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { fprintf(out_, "\n", x0, y0, x1, y1, x2, y2, x3, y3, red_, green_, blue_); } void Fl_SVG_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { fprintf(out_, "\n", x0, y0, x1, y1, x2, y2, x3, y3, red_, green_, blue_, width_, linejoin_, linecap_, dasharray_); } void Fl_SVG_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { fprintf(out_, "\n", x0, y0, x1, y1, x2, y2, red_, green_, blue_, width_, linejoin_, linecap_, dasharray_); } void Fl_SVG_Graphics_Driver::end_points() { for (int i=0; i\n", xpoint[i].x, xpoint[i].y, xpoint[i].x, xpoint[i].y, red_, green_, blue_, width_); } } void Fl_SVG_Graphics_Driver::end_line() { if (n < 2) { end_points(); return; } if (n<=1) return; clocale_printf("\n", red_, green_, blue_, width_, dasharray_, linecap_, linejoin_); } void Fl_SVG_Graphics_Driver::end_polygon() { fixloop(); if (n < 3) { end_line(); return; } if (n<=1) return; clocale_printf("\n", red_, green_, blue_); } void Fl_SVG_Graphics_Driver::circle(double x, double y, double r) { double xt = transform_x(x,y); double yt = transform_y(x,y); double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a)); double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d)); int llx = (int)rint(xt-rx); int w = (int)rint(xt+rx)-llx; int lly = (int)rint(yt-ry); int h = (int)rint(yt+ry)-lly; clocale_printf("\n", red_, green_, blue_); } void Fl_SVG_Graphics_Driver::end_complex_polygon() { gap(); if (n < 3) { end_line(); return; } if (n<=1) return; clocale_printf("\n", red_, green_, blue_); } void Fl_SVG_Graphics_Driver::arc(double x, double y, double r, double start, double end) { Fl_Graphics_Driver::arc(x, y, r, start, end); } void Fl_SVG_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) { arc_pie('A', x, y, w, h, a1, a2); } void Fl_SVG_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) { arc_pie('P', x, y, w, h, a1, a2); } void Fl_SVG_Graphics_Driver::arc_pie(char AorP, int x, int y, int w, int h, double a1, double a2) { // This implementation was constructed as follows: // - follow Fl_Quartz_Graphics_Driver::arc(int x,...). // which applies a translation, a scaling, and then calls // CGContextAddArc(gc_, 0, 0, 0.5, a1, a2, 1); // to draw an arc of a circle given its center, its radius, and starting and ending angles // - consider https://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes // which gives the equations that transform the center parameterization used by // CGContextAddArc() to the endpoint parameterization used by the "elliptical arc curve" command of SVG (A). if (w <= 0 || h <= 0) return; bool full = fabs(a1-a2) == 360; // case of full circle/disk a1 = (-a1)/180.0f*M_PI; a2 = (-a2)/180.0f*M_PI; float cx = x + 0.5f*w /*- 0.5f*/, cy = y + 0.5f*h - 0.5f; double r = (w!=h ? 0.5 : (w+h)*0.25f-0.5f); float stroke_width = float(width_); float sx, sy; if (w != h) { sx = float(w-1); sy = float(h-1); stroke_width /= ((sx+sy)/2); } else { sx = sy = float(2*r); stroke_width /= sx; } clocale_printf("\n", cx, cy, sx, sy); if (AorP == 'A') compute_dasharray((sx+sy)/2, user_dash_array_); if (full) { fprintf(out_, " M_PI ? 1 : 0; if (AorP == 'A') clocale_printf("\n\n", red_, green_, blue_); if (AorP == 'A') compute_dasharray(1., user_dash_array_); } #else Fl_SVG_File_Surface::Fl_SVG_File_Surface(int w, int h, FILE *f, int (*closef)(FILE*)) : Fl_Widget_Surface(NULL) { closef_ = NULL; width_ = height_ = 0; } Fl_SVG_File_Surface::~Fl_SVG_File_Surface() {} int Fl_SVG_File_Surface::close() {return 0;} FILE *Fl_SVG_File_Surface::file() {return NULL;} void Fl_SVG_File_Surface::origin(int x, int y) {} void Fl_SVG_File_Surface::translate(int x, int y) {} void Fl_SVG_File_Surface::untranslate() {} int Fl_SVG_File_Surface::printable_rect(int *w, int *h) {return 0;} #endif // FLTK_USE_SVG void Fl_SVG_File_Surface::origin(int *x, int *y) { Fl_Widget_Surface::origin(x, y);} fltk-1.4.3/src/drivers/WinAPI/0000755000175000017500000000000015004135251016141 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.H0000644000175000017500000001030715004135251022625 0ustar albrechtalbrecht// // Definition of Windows window driver // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_WinAPI_Window_Driver.H \brief Definition of Windows window driver. */ #ifndef FL_WINAPI_WINDOW_DRIVER_H #define FL_WINAPI_WINDOW_DRIVER_H #include "../../Fl_Window_Driver.H" #include /* Move everything here that manages the native window interface. There is one window driver for each Fl_Window. Window drivers manage window actions such as resizing, events, decoration, fullscreen modes, etc. . All drawing and rendering is managed by the Surface device and the associated graphics driver. - window specific event handling - window types and styles, depth, etc. - decorations ? where do we handle the interface between OpenGL/DirectX and Cocoa/Windows/Glx? */ class Fl_WinAPI_Window_Driver : public Fl_Window_Driver { struct icon_data { const void *legacy_icon; Fl_RGB_Image **icons; int count; HICON big_icon; HICON small_icon; }; struct shape_data_type { int lw_; ///< width of shape image int lh_; ///< height of shape image Fl_Image* shape_; ///< shape image Fl_Bitmap *effective_bitmap_; ///< auxiliary bitmap image } *shape_data_; private: void shape_bitmap_(Fl_Image* b); void shape_alpha_(Fl_Image* img, int offset) FL_OVERRIDE; public: Fl_WinAPI_Window_Driver(Fl_Window*); ~Fl_WinAPI_Window_Driver(); static inline Fl_WinAPI_Window_Driver* driver(const Fl_Window *w) {return (Fl_WinAPI_Window_Driver*)Fl_Window_Driver::driver(w);} HDC private_dc; // used for OpenGL RECT border_width_title_bar_height(int &bx, int &by, int &bt); struct icon_data *icon_; HCURSOR cursor; int custom_cursor; struct type_for_resize_window_between_screens { int screen; bool busy; }; static type_for_resize_window_between_screens data_for_resize_window_between_screens_; void set_minmax(LPMINMAXINFO minmax); int fake_X_wm(int &X, int &Y, int &bt, int &bx, int &by, DWORD style = 0, DWORD styleEx = 0); void make_fullscreen(int X, int Y, int W, int H); // --- window data int decorated_w() FL_OVERRIDE; int decorated_h() FL_OVERRIDE; const Fl_Image* shape() FL_OVERRIDE; // --- window management void makeWindow() FL_OVERRIDE; void size_range() FL_OVERRIDE { // currently nothing to do } void flush_double() FL_OVERRIDE; void flush_overlay() FL_OVERRIDE; void draw_begin() FL_OVERRIDE; void make_current() FL_OVERRIDE; void show() FL_OVERRIDE; void label(const char *name,const char *iname) FL_OVERRIDE; void resize(int X,int Y,int W,int H) FL_OVERRIDE; void hide() FL_OVERRIDE; void map() FL_OVERRIDE; void unmap() FL_OVERRIDE; void fullscreen_on() FL_OVERRIDE; void fullscreen_off(int X, int Y, int W, int H) FL_OVERRIDE; void maximize() FL_OVERRIDE; void un_maximize() FL_OVERRIDE; bool maximize_needs_hide() FL_OVERRIDE { return true; } void iconize() FL_OVERRIDE; void decoration_sizes(int *top, int *left, int *right, int *bottom) FL_OVERRIDE; // --- window cursor stuff int set_cursor(Fl_Cursor) FL_OVERRIDE; int set_cursor(const Fl_RGB_Image*, int, int) FL_OVERRIDE; void shape(const Fl_Image* img) FL_OVERRIDE; void icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE; const void *icon() const FL_OVERRIDE; void icon(const void * ic) FL_OVERRIDE; void free_icons() FL_OVERRIDE; void set_icons(); // driver-internal support function // this one is implemented in Fl_win32.cxx void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) FL_OVERRIDE; int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data) FL_OVERRIDE; static void resize_after_screen_change(void *data); }; #endif // FL_WINAPI_WINDOW_DRIVER_H fltk-1.4.3/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx0000644000175000017500000003637715004135251023433 0ustar albrechtalbrecht// // Printing support for Windows for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "../GDI/Fl_GDI_Graphics_Driver.H" #include #include #include #include #include #include #include #include // for fl_win32_xid() #include // fl_strdup() #include #include // DocumentProperties(), OpenPrinter(), ClosePrinter() extern HWND fl_window; /** Support for printing on the Windows platform */ class Fl_WinAPI_Printer_Driver : public Fl_Paged_Device { friend class Fl_Printer; protected: int abortPrint; PRINTDLG pd; HDC hPr; int prerr; int left_margin; int top_margin; void absolute_printable_rect(int *x, int *y, int *w, int *h); Fl_WinAPI_Printer_Driver(void); int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message = NULL) FL_OVERRIDE; int begin_page (void) FL_OVERRIDE; int printable_rect(int *w, int *h) FL_OVERRIDE; void margins(int *left, int *top, int *right, int *bottom) FL_OVERRIDE; void origin(int *x, int *y) FL_OVERRIDE; void origin(int x, int y) FL_OVERRIDE; void scale (float scale_x, float scale_y = 0.) FL_OVERRIDE; void rotate(float angle) FL_OVERRIDE; void translate(int x, int y) FL_OVERRIDE; void untranslate(void) FL_OVERRIDE; int end_page (void) FL_OVERRIDE; void end_job (void) FL_OVERRIDE; ~Fl_WinAPI_Printer_Driver(void); }; Fl_WinAPI_Printer_Driver::Fl_WinAPI_Printer_Driver(void) : Fl_Paged_Device() { hPr = NULL; driver(new Fl_GDI_Printer_Graphics_Driver); } Fl_Paged_Device* Fl_Printer::newPrinterDriver(void) { return new Fl_WinAPI_Printer_Driver(); } Fl_WinAPI_Printer_Driver::~Fl_WinAPI_Printer_Driver(void) { if (hPr) end_job(); delete driver(); } static void WIN_SetupPrinterDeviceContext(HDC prHDC) { if ( !prHDC ) return; fl_window = 0; SetGraphicsMode(prHDC, GM_ADVANCED); // to allow for rotations SetMapMode(prHDC, MM_ANISOTROPIC); SetTextAlign(prHDC, TA_BASELINE|TA_LEFT); SetBkMode(prHDC, TRANSPARENT); // this matches 720 logical units to the number of device units in 10 inches of paper // thus the logical unit is the point (= 1/72 inch) SetWindowExtEx(prHDC, 720, 720, NULL); SetViewportExtEx(prHDC, 10*GetDeviceCaps(prHDC, LOGPIXELSX), 10*GetDeviceCaps(prHDC, LOGPIXELSY), NULL); } class Fl_PDF_GDI_File_Surface : public Fl_WinAPI_Printer_Driver { private: static LPSTR pdf_printer_name_; public: char *doc_fname; Fl_PDF_GDI_File_Surface(); ~Fl_PDF_GDI_File_Surface() { if (doc_fname) free(doc_fname); } int begin_job(const char *defaultname, char **perr_message = NULL); int begin_job(int, int*, int *, char **) FL_OVERRIDE {return 1;} // don't use int begin_document(const char* outname, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout, char **perr_message); void end_job() FL_OVERRIDE; }; LPSTR Fl_PDF_GDI_File_Surface::pdf_printer_name_ = _strdup("Microsoft Print to PDF"); Fl_PDF_GDI_File_Surface::Fl_PDF_GDI_File_Surface() { driver(new Fl_GDI_Graphics_Driver()); doc_fname = NULL; } Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) { Fl_PDF_GDI_File_Surface *surf = new Fl_PDF_GDI_File_Surface(); *pfname = (const char**)&surf->doc_fname; return surf; } int Fl_PDF_File_Surface::begin_job(const char* defaultfilename, char **perr_message) { return ((Fl_PDF_GDI_File_Surface*)platform_surface_)->begin_job(defaultfilename, perr_message); } int Fl_PDF_File_Surface::begin_document(const char* defaultfilename, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout, char **perr_message) { return ((Fl_PDF_GDI_File_Surface*)platform_surface_)->begin_document(defaultfilename, format, layout, perr_message); } int Fl_PDF_GDI_File_Surface::begin_job(const char *defaultfname, char **perr_message) { int err = 0; abortPrint = FALSE; HANDLE hPr2; err = OpenPrinterA(pdf_printer_name_, &hPr2, NULL); if (err == 0) { if (perr_message) { int l = 240; *perr_message = new char[l]; snprintf(*perr_message, l, "Class Fl_PDF_File_Surface requires printer '%s' available in Windows 10+.", pdf_printer_name_); } return 1; } HWND hwndOwner = fl_win32_xid(Fl::first_window()); LONG count = DocumentPropertiesA(hwndOwner, hPr2, pdf_printer_name_, NULL, NULL, 0); if (count <= 0) { ClosePrinter(hPr2); return 1; } char *buffer = new char[count]; DEVMODEA *pDevMode = (DEVMODEA*)buffer; memset(buffer, 0, count); pDevMode->dmSize = (WORD)count; count = DocumentPropertiesA(hwndOwner, hPr2, pdf_printer_name_, pDevMode, NULL, DM_OUT_BUFFER | DM_IN_PROMPT); ClosePrinter(hPr2); if (count == IDCANCEL || count < 0) { delete[] buffer; return 1; } Fl_Native_File_Chooser fnfc; fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); fnfc.filter("PDF\t*.pdf\n"); if (defaultfname && strlen(defaultfname) > 0) fnfc.preset_file(defaultfname); fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM); if (fnfc.show() == 0) this->hPr = CreateDCA(NULL, pdf_printer_name_, NULL, pDevMode); delete[] buffer; if (!this->hPr) return 1; DOCINFOW di; wchar_t docName [256]; wchar_t outName [256]; fl_utf8towc("FLTK", 4, docName, 256); fl_utf8towc(fnfc.filename(), (unsigned int)strlen(fnfc.filename()), outName, 256); memset(&di, 0, sizeof(DOCINFOW)); di.cbSize = sizeof(DOCINFOW); di.lpszDocName = (LPCWSTR)docName; di.lpszOutput = (LPCWSTR)outName; err = StartDocW(this->hPr, &di); if (err <= 0) { DWORD dw = GetLastError(); DeleteDC(this->hPr); this->hPr = NULL; if (dw != ERROR_CANCELLED) { if (perr_message) { int l = 40; *perr_message = new char[l]; snprintf(*perr_message, l, "Error %lu in StartDoc() call", dw); } return 2; } return 1; } x_offset = 0; y_offset = 0; WIN_SetupPrinterDeviceContext(this->hPr); driver()->gc(this->hPr); doc_fname = fl_strdup(fnfc.filename()); return 0; } int Fl_PDF_GDI_File_Surface::begin_document(const char* outfname, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout, char **perr_message) { int err = 0; abortPrint = FALSE; DEVMODEA inDevMode; memset(&inDevMode, 0, sizeof(DEVMODEA)); inDevMode.dmSize = sizeof(DEVMODEA); inDevMode.dmOrientation = (layout == PORTRAIT ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE); inDevMode.dmPaperSize = (format == A4 ? DMPAPER_A4 : DMPAPER_LETTER); inDevMode.dmFields = DM_ORIENTATION | DM_PAPERSIZE ; this->hPr = CreateDCA(NULL, pdf_printer_name_, NULL, &inDevMode); if (!this->hPr) { if (perr_message) { int l = 150; *perr_message = new char[l]; snprintf(*perr_message, l, "Class Fl_PDF_File_Surface requires printer '%s'.", pdf_printer_name_); } return 2; } DOCINFOW di; wchar_t docName[256]; wchar_t outName[256]; fl_utf8towc("FLTK", 4, docName, 256); memset(&di, 0, sizeof(DOCINFOW)); di.cbSize = sizeof(DOCINFOW); di.lpszDocName = (LPCWSTR)docName; di.lpszOutput = (LPCWSTR)outName; fl_utf8towc(outfname, (unsigned int)strlen(outfname), outName, 256); err = StartDocW(hPr, &di); if (err <= 0) { DWORD dw = GetLastError(); DeleteDC(this->hPr); this->hPr = NULL; if (perr_message) { int l = 50; *perr_message = new char[l]; snprintf(*perr_message, l, "Error %lu in StartDoc() call", dw); } return 2; } x_offset = 0; y_offset = 0; WIN_SetupPrinterDeviceContext(this->hPr); driver()->gc(this->hPr); doc_fname = fl_strdup(outfname); return 0; } int Fl_WinAPI_Printer_Driver::begin_job (int pagecount, int *frompage, int *topage, char **perr_message) // returns 0 iff OK { if (pagecount == 0) pagecount = 10000; DOCINFO di; char docName [256]; int err = 0; abortPrint = FALSE; memset (&pd, 0, sizeof (PRINTDLG)); pd.lStructSize = sizeof (PRINTDLG); pd.hwndOwner = GetForegroundWindow(); pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE | PD_NOSELECTION; pd.nMinPage = 1; pd.nMaxPage = pagecount; BOOL b = PrintDlg (&pd); if (pd.hwndOwner) { // restore the correct state of mouse buttons and keyboard modifier keys (STR #3221) WNDPROC windproc = (WNDPROC)GetWindowLongPtrW(pd.hwndOwner, GWLP_WNDPROC); CallWindowProc(windproc, pd.hwndOwner, WM_ACTIVATEAPP, 1, 0); } if (b != 0) { hPr = pd.hDC; if (hPr != NULL) { strcpy (docName, "FLTK"); memset(&di, 0, sizeof(DOCINFO)); di.cbSize = sizeof (DOCINFO); di.lpszDocName = (LPCSTR) docName; prerr = StartDoc (hPr, &di); if (prerr < 1) { abortPrint = TRUE; DWORD dw = GetLastError(); err = (dw == ERROR_CANCELLED ? 1 : 2); if (perr_message && err == 2) { wchar_t *lpMsgBuf; DWORD retval = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &lpMsgBuf, 0, NULL); if (retval) { unsigned srclen = lstrlenW(lpMsgBuf); while (srclen > 0 && (lpMsgBuf[srclen-1] == '\n' || lpMsgBuf[srclen-1] == '\r')) srclen--; unsigned l = fl_utf8fromwc(NULL, 0, lpMsgBuf, srclen); *perr_message = new char[l+51]; snprintf(*perr_message, l+51, "begin_job() failed with error %lu: ", dw); fl_utf8fromwc(*perr_message + strlen(*perr_message), l+1, lpMsgBuf, srclen); LocalFree(lpMsgBuf); } } } } } else { err = 1; } if(!err) { if((pd.Flags & PD_PAGENUMS) != 0 ) { if (frompage) *frompage = pd.nFromPage; if (topage) *topage = pd.nToPage; } else { if (frompage) *frompage = 1; if (topage) *topage = pagecount; } x_offset = 0; y_offset = 0; WIN_SetupPrinterDeviceContext (hPr); driver()->gc(hPr); } return err; } void Fl_PDF_GDI_File_Surface::end_job(void) { if (hPr != NULL) { if (! abortPrint) { if (EndDoc (hPr) <= 0) { fl_message ("Error in EndDoc() call"); } DeleteDC (hPr); } hPr = NULL; } } void Fl_WinAPI_Printer_Driver::end_job (void) { if (hPr != NULL) { if (! abortPrint) { prerr = EndDoc (hPr); if (prerr < 0) { fl_alert ("EndDoc error %d", prerr); } } DeleteDC (hPr); if (pd.hDevMode != NULL) { GlobalFree (pd.hDevMode); } if (pd.hDevNames != NULL) { GlobalFree (pd.hDevNames); } } hPr = NULL; } void Fl_WinAPI_Printer_Driver::absolute_printable_rect(int *x, int *y, int *w, int *h) { POINT physPageSize; POINT pixelsPerInch; XFORM transform; if (hPr == NULL) return; HDC gc = (HDC)driver()->gc(); GetWorldTransform(gc, &transform); ModifyWorldTransform(gc, NULL, MWT_IDENTITY); SetWindowOrgEx(gc, 0, 0, NULL); physPageSize.x = GetDeviceCaps(hPr, HORZRES); physPageSize.y = GetDeviceCaps(hPr, VERTRES); DPtoLP(hPr, &physPageSize, 1); *w = physPageSize.x + 1; *h = physPageSize.y + 1; pixelsPerInch.x = GetDeviceCaps(hPr, LOGPIXELSX); pixelsPerInch.y = GetDeviceCaps(hPr, LOGPIXELSY); DPtoLP(hPr, &pixelsPerInch, 1); left_margin = (pixelsPerInch.x / 4); *w -= (pixelsPerInch.x / 2); top_margin = (pixelsPerInch.y / 4); *h -= (pixelsPerInch.y / 2); *x = left_margin; *y = top_margin; origin(x_offset, y_offset); SetWorldTransform(gc, &transform); } void Fl_WinAPI_Printer_Driver::margins(int *left, int *top, int *right, int *bottom) { int x = 0, y = 0, w = 0, h = 0; absolute_printable_rect(&x, &y, &w, &h); if (left) *left = x; if (top) *top = y; if (right) *right = x; if (bottom) *bottom = y; } int Fl_WinAPI_Printer_Driver::printable_rect(int *w, int *h) { int x, y; absolute_printable_rect(&x, &y, w, h); return 0; } int Fl_WinAPI_Printer_Driver::begin_page (void) { int rsult, w, h; rsult = 0; if (hPr != NULL) { Fl_Surface_Device::push_current(this); WIN_SetupPrinterDeviceContext (hPr); prerr = StartPage (hPr); if (prerr < 0) { Fl_Surface_Device::pop_current(); fl_alert ("StartPage error %d", prerr); rsult = 1; } printable_rect(&w, &h); origin(0, 0); fl_clip_region(0); } return rsult; } void Fl_WinAPI_Printer_Driver::origin (int deltax, int deltay) { SetWindowOrgEx( (HDC)driver()->gc(), - left_margin - deltax, - top_margin - deltay, NULL); x_offset = deltax; y_offset = deltay; } void Fl_WinAPI_Printer_Driver::scale (float scalex, float scaley) { if (scaley == 0.) scaley = scalex; int w, h; SetWindowExtEx((HDC)driver()->gc(), (int)(720 / scalex + 0.5), (int)(720 / scaley + 0.5), NULL); printable_rect(&w, &h); origin(0, 0); } void Fl_WinAPI_Printer_Driver::rotate (float rot_angle) { XFORM mat; float angle; angle = (float) - (rot_angle * M_PI / 180.); mat.eM11 = (float)cos(angle); mat.eM12 = (float)sin(angle); mat.eM21 = - mat.eM12; mat.eM22 = mat.eM11; mat.eDx = mat.eDy = 0; SetWorldTransform((HDC)driver()->gc(), &mat); } int Fl_WinAPI_Printer_Driver::end_page (void) { int rsult; rsult = 0; if (hPr != NULL) { Fl_Surface_Device::pop_current(); prerr = EndPage (hPr); if (prerr < 0) { abortPrint = TRUE; fl_alert ("EndPage error %d", prerr); rsult = 1; } else { // make sure rotation is not transferred to next page ModifyWorldTransform(hPr, NULL, MWT_IDENTITY); } } return rsult; } static int translate_stack_depth = 0; const int translate_stack_max = 5; static int translate_stack_x[translate_stack_max]; static int translate_stack_y[translate_stack_max]; static void do_translate(int x, int y, HDC gc) { XFORM tr; tr.eM11 = tr.eM22 = 1; tr.eM12 = tr.eM21 = 0; tr.eDx = (FLOAT) x; tr.eDy = (FLOAT) y; ModifyWorldTransform(gc, &tr, MWT_LEFTMULTIPLY); } void Fl_WinAPI_Printer_Driver::translate (int x, int y) { do_translate(x, y, (HDC)driver()->gc()); if (translate_stack_depth < translate_stack_max) { translate_stack_x[translate_stack_depth] = x; translate_stack_y[translate_stack_depth] = y; translate_stack_depth++; } } void Fl_WinAPI_Printer_Driver::untranslate (void) { if (translate_stack_depth > 0) { translate_stack_depth--; do_translate( - translate_stack_x[translate_stack_depth], - translate_stack_y[translate_stack_depth], (HDC)driver()->gc() ); } } void Fl_WinAPI_Printer_Driver::origin(int *x, int *y) { Fl_Paged_Device::origin(x, y); } fltk-1.4.3/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H0000644000175000017500000000706215004135251022601 0ustar albrechtalbrecht// // Windows screen interface for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_WinAPI_Screen_Driver.H \brief Definition of Windows screen interface. */ #ifndef FL_WINAPI_SCREEN_DRIVER_H #define FL_WINAPI_SCREEN_DRIVER_H #include "../../Fl_Screen_Driver.H" #include class Fl_Window; class Fl_WinAPI_Screen_Driver : public Fl_Screen_Driver { protected: RECT screens[MAX_SCREENS]; RECT work_area[MAX_SCREENS]; float scale_of_screen[MAX_SCREENS]; static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM); BOOL screen_cb(HMONITOR mon, HDC, LPRECT r); int get_mouse_unscaled(int &mx, int &my); public: float dpi[MAX_SCREENS][2]; enum APP_SCALING_CAPABILITY scaling_capability; void update_scaling_capability(); Fl_WinAPI_Screen_Driver(); // --- display management int visual(int flags) FL_OVERRIDE; // --- screen configuration void init() FL_OVERRIDE; int x() FL_OVERRIDE; int y() FL_OVERRIDE; int w() FL_OVERRIDE; int h() FL_OVERRIDE; void screen_xywh(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; void screen_xywh_unscaled(int &X, int &Y, int &W, int &H, int n); void screen_dpi(float &h, float &v, int n=0) FL_OVERRIDE; int screen_num_unscaled(int x, int y); void screen_work_area(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; // --- audible output void beep(int type) FL_OVERRIDE; // --- global events void flush() FL_OVERRIDE; void grab(Fl_Window* win) FL_OVERRIDE; // --- global colors void get_system_colors() FL_OVERRIDE; int dnd(int unused) FL_OVERRIDE; int compose(int &del) FL_OVERRIDE; Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins) FL_OVERRIDE; Fl_RGB_Image *read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win); int get_mouse(int &x, int &y) FL_OVERRIDE; void enable_im() FL_OVERRIDE; void disable_im() FL_OVERRIDE; void open_display_platform() FL_OVERRIDE; void offscreen_size(Fl_Offscreen off, int &width, int &height) FL_OVERRIDE; APP_SCALING_CAPABILITY rescalable() FL_OVERRIDE { return scaling_capability; } float scale(int n) FL_OVERRIDE { return scale_of_screen[n]; } void scale(int n, float f) FL_OVERRIDE { scale_of_screen[n] = f; } void desktop_scale_factor() FL_OVERRIDE; void default_icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE; // this one is implemented in Fl_win32.cxx void copy(const char *stuff, int len, int clipboard, const char *type) FL_OVERRIDE; // this one is implemented in Fl_win32.cxx void paste(Fl_Widget &receiver, int clipboard, const char *type) FL_OVERRIDE; // this one is implemented in Fl_win32.cxx int clipboard_contains(const char *type) FL_OVERRIDE; // this one is implemented in Fl_win32.cxx void clipboard_notify_change() FL_OVERRIDE; // this one is implemented in Fl_win32.cxx void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) FL_OVERRIDE; // these two are implemented in Fl_get_key_win32.cxx int event_key(int) FL_OVERRIDE; int get_key(int) FL_OVERRIDE; float base_scale(int numscreen) FL_OVERRIDE; }; #endif // FL_WINAPI_SCREEN_DRIVER_H fltk-1.4.3/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H0000644000175000017500000000442215004135251023250 0ustar albrechtalbrecht// // Class Fl_WinAPI_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_WINAPI_GL_WINDOW_DRIVER_H #define FL_WINAPI_GL_WINDOW_DRIVER_H #include #if HAVE_GL #include #include "../../Fl_Gl_Window_Driver.H" #include class Fl_WinAPI_Gl_Window_Driver : public Fl_Gl_Window_Driver { friend Fl_Gl_Window_Driver* Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *); Fl_WinAPI_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {} float pixels_per_unit() FL_OVERRIDE; int mode_(int m, const int *a) FL_OVERRIDE; void make_current_after() FL_OVERRIDE; void swap_buffers() FL_OVERRIDE; void swap_interval(int) FL_OVERRIDE; int swap_interval() const FL_OVERRIDE; void invalidate() FL_OVERRIDE {} int flush_begin(char& valid_f) FL_OVERRIDE; Fl_Gl_Choice *find(int m, const int *alistp) FL_OVERRIDE; GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) FL_OVERRIDE; GLContext do_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer); void set_gl_context(Fl_Window* w, GLContext context) FL_OVERRIDE; void delete_gl_context(GLContext) FL_OVERRIDE; void make_overlay_current() FL_OVERRIDE; void redraw_overlay() FL_OVERRIDE; void* GetProcAddress(const char *procName) FL_OVERRIDE; void draw_string_legacy(const char* str, int n) FL_OVERRIDE; void gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) FL_OVERRIDE; void get_list(Fl_Font_Descriptor *fd, int r) FL_OVERRIDE; int genlistsize() FL_OVERRIDE; void switch_to_GL1() FL_OVERRIDE; void switch_back() FL_OVERRIDE; #if HAVE_GL_OVERLAY void gl_hide_before(void *& overlay) FL_OVERRIDE; int can_do_overlay() FL_OVERRIDE; int overlay_color(Fl_Color i) FL_OVERRIDE; void make_overlay(void*&overlay) FL_OVERRIDE; #endif }; #endif // HAVE_GL #endif // FL_WINAPI_GL_WINDOW_DRIVER_H fltk-1.4.3/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx0000644000175000017500000003376615004135251023226 0ustar albrechtalbrecht// // Windows screen interface for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_WinAPI_Screen_Driver.H" #include "../GDI/Fl_Font.H" #include #include #include "../GDI/Fl_GDI_Graphics_Driver.H" #include #include #include // these are set by Fl::args() and override any system colors: from Fl_get_system_colors.cxx extern const char *fl_fg; extern const char *fl_bg; extern const char *fl_bg2; // end of extern additions workaround #if !defined(HMONITOR_DECLARED) && (_WIN32_WINNT < 0x0500) # define COMPILE_MULTIMON_STUBS # include #endif // !HMONITOR_DECLARED && _WIN32_WINNT < 0x0500 static Fl_Text_Editor::Key_Binding extra_bindings[] = { // Define Windows specific accelerators... { 'y', FL_CTRL, Fl_Text_Editor::kf_redo ,0}, { 0, 0, 0 ,0} }; Fl_WinAPI_Screen_Driver::Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() { text_editor_extra_key_bindings = extra_bindings; for (int i = 0; i < MAX_SCREENS; i++) scale_of_screen[i] = 1; scaling_capability = SYSTEMWIDE_APP_SCALING; } int Fl_WinAPI_Screen_Driver::visual(int flags) { fl_GetDC(0); if (flags & FL_DOUBLE) return 0; HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc(); if (!(flags & FL_INDEX) && GetDeviceCaps(gc,BITSPIXEL) <= 8) return 0; if ((flags & FL_RGB8) && GetDeviceCaps(gc,BITSPIXEL)<24) return 0; return 1; } // We go the much more difficult route of individually picking some multi-screen // functions from the USER32.DLL . If these functions are not available, we // will gracefully fall back to single monitor support. // // If we were to insist on the existence of "EnumDisplayMonitors" and // "GetMonitorInfoA", it would be impossible to use FLTK on Windows 2000 // before SP2 or earlier. // BOOL EnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM) typedef BOOL(WINAPI* fl_edm_func)(HDC, LPCRECT, MONITORENUMPROC, LPARAM); // BOOL GetMonitorInfo(HMONITOR, LPMONITORINFO) typedef BOOL(WINAPI* fl_gmi_func)(HMONITOR, LPMONITORINFO); static fl_gmi_func fl_gmi = NULL; // used to get a proc pointer for GetMonitorInfoA BOOL Fl_WinAPI_Screen_Driver::screen_cb(HMONITOR mon, HDC hdc, LPRECT r, LPARAM d) { Fl_WinAPI_Screen_Driver *drv = (Fl_WinAPI_Screen_Driver*)d; return drv->screen_cb(mon, hdc, r); } BOOL Fl_WinAPI_Screen_Driver::screen_cb(HMONITOR mon, HDC, LPRECT r) { if (num_screens >= MAX_SCREENS) return TRUE; MONITORINFOEX mi; mi.cbSize = sizeof(mi); // GetMonitorInfo(mon, &mi); // (but we use our self-acquired function pointer instead) if (fl_gmi(mon, &mi)) { screens[num_screens] = mi.rcMonitor; // If we also want to record the work area, we would also store mi.rcWork at this point work_area[num_screens] = mi.rcWork; num_screens++; } return TRUE; } void Fl_WinAPI_Screen_Driver::init() { open_display(); // Since not all versions of Windows include multiple monitor support, // we do a run-time check for the required functions... HMODULE hMod = GetModuleHandle("USER32.DLL"); if (hMod) { // check that EnumDisplayMonitors is available fl_edm_func fl_edm = (fl_edm_func)GetProcAddress(hMod, "EnumDisplayMonitors"); if (fl_edm) { // we have EnumDisplayMonitors - do we also have GetMonitorInfoA ? fl_gmi = (fl_gmi_func)GetProcAddress(hMod, "GetMonitorInfoA"); if (fl_gmi) { // We have GetMonitorInfoA, enumerate all the screens... // EnumDisplayMonitors(0,0,screen_cb,0); // (but we use our self-acquired function pointer instead) // NOTE: num_screens is incremented in screen_cb so we must first reset it here... num_screens = 0; fl_edm(0, 0, screen_cb, (LPARAM)this); return; } } } // If we get here, assume we have 1 monitor... num_screens = 1; screens[0].top = 0; screens[0].left = 0; screens[0].right = GetSystemMetrics(SM_CXSCREEN); screens[0].bottom = GetSystemMetrics(SM_CYSCREEN); work_area[0] = screens[0]; } void Fl_WinAPI_Screen_Driver::screen_work_area(int &X, int &Y, int &W, int &H, int n) { if (num_screens < 0) init(); if (n < 0 || n >= num_screens) n = 0; X = int(work_area[n].left/scale_of_screen[n]); Y = int(work_area[n].top/scale_of_screen[n]); W = int((work_area[n].right - work_area[n].left)/scale_of_screen[n]); H = int((work_area[n].bottom - work_area[n].top)/scale_of_screen[n]); } void Fl_WinAPI_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n) { if (num_screens < 0) init(); if ((n < 0) || (n >= num_screens)) n = 0; if (num_screens > 0) { X = int(screens[n].left/scale_of_screen[n]); Y = int(screens[n].top/scale_of_screen[n]); W = int((screens[n].right - screens[n].left)/scale_of_screen[n]); H = int((screens[n].bottom - screens[n].top)/scale_of_screen[n]); } else { /* Fallback if something is broken... */ X = 0; Y = 0; W = GetSystemMetrics(SM_CXSCREEN); H = GetSystemMetrics(SM_CYSCREEN); } } void Fl_WinAPI_Screen_Driver::screen_xywh_unscaled(int &X, int &Y, int &W, int &H, int n) { if (num_screens < 0) init(); if ((n < 0) || (n >= num_screens)) n = 0; X = screens[n].left; Y = screens[n].top; W = screens[n].right - screens[n].left; H = screens[n].bottom - screens[n].top; }; void Fl_WinAPI_Screen_Driver::screen_dpi(float &h, float &v, int n) { if (num_screens < 0) init(); h = v = 0.0f; if (n >= 0 && n < num_screens) { h = float(dpi[n][0]); v = float(dpi[n][1]); } } int Fl_WinAPI_Screen_Driver::x() { /*RECT r; SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); return r.left;*/ int X, Y, W, H; screen_work_area(X, Y, W, H, 0); return X; } int Fl_WinAPI_Screen_Driver::y() { /*RECT r; SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); return r.top;*/ int X, Y, W, H; screen_work_area(X, Y, W, H, 0); return Y; } int Fl_WinAPI_Screen_Driver::h() { /*RECT r; SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); return r.bottom - r.top;*/ int X, Y, W, H; screen_work_area(X, Y, W, H, 0); return H; } int Fl_WinAPI_Screen_Driver::w() { /*RECT r; SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); return r.right - r.left;*/ int X, Y, W, H; screen_work_area(X, Y, W, H, 0); return W; } // Implements fl_beep(). See documentation in src/fl_ask.cxx. void Fl_WinAPI_Screen_Driver::beep(int type) { switch (type) { case FL_BEEP_QUESTION : case FL_BEEP_PASSWORD : MessageBeep(MB_ICONQUESTION); break; case FL_BEEP_MESSAGE : MessageBeep(MB_ICONASTERISK); break; case FL_BEEP_NOTIFICATION : MessageBeep(MB_ICONASTERISK); break; case FL_BEEP_ERROR : MessageBeep(MB_ICONERROR); break; default : MessageBeep(0xFFFFFFFF); break; } } void Fl_WinAPI_Screen_Driver::flush() { GdiFlush(); } extern void fl_fix_focus(); // in Fl.cxx // We have to keep track of whether we have captured the mouse, since // Windows shows little respect for this... Grep for fl_capture to // see where and how this is used. extern HWND fl_capture; void Fl_WinAPI_Screen_Driver::grab(Fl_Window* win) { if (win) { if (!Fl::grab_) { SetActiveWindow(fl_capture = fl_xid(Fl::first_window())); SetCapture(fl_capture); } Fl::grab_ = win; } else { if (Fl::grab_) { fl_capture = 0; ReleaseCapture(); Fl::grab_ = 0; fl_fix_focus(); } } } static void set_selection_color(uchar r, uchar g, uchar b) { Fl::set_color(FL_SELECTION_COLOR,r,g,b); } static void getsyscolor(int what, const char* arg, void (*func)(uchar,uchar,uchar)) { if (arg) { uchar r,g,b; if (!fl_parse_color(arg, r,g,b)) Fl::error("Unknown color: %s", arg); else func(r,g,b); } else { DWORD x = GetSysColor(what); func(uchar(x&255), uchar(x>>8), uchar(x>>16)); } } void Fl_WinAPI_Screen_Driver::get_system_colors() { if (!bg2_set) getsyscolor(COLOR_WINDOW, fl_bg2,Fl::background2); if (!fg_set) getsyscolor(COLOR_WINDOWTEXT, fl_fg, Fl::foreground); if (!bg_set) getsyscolor(COLOR_BTNFACE, fl_bg, Fl::background); getsyscolor(COLOR_HIGHLIGHT, 0, set_selection_color); } int Fl_WinAPI_Screen_Driver::compose(int &del) { unsigned char ascii = (unsigned char)Fl::e_text[0]; /* WARNING: The [AltGr] key on international keyboards sets FL_CTRL. 2nd line in condition below asks [AltGr] key (a.k.a. VK_RMENU) not to be down. */ int condition = (Fl::e_state & (FL_ALT | FL_META | FL_CTRL)) && !(ascii & 128) && !( (Fl::e_state & FL_CTRL) && (GetAsyncKeyState(VK_RMENU) >> 15) ); if (condition) { // this stuff is to be treated as a function key del = 0; return 0; } del = Fl::compose_state; Fl::compose_state = 0; // Only insert non-control characters: if ( (!Fl::compose_state) && ! (ascii & ~31 && ascii!=127)) { return 0; } return 1; } Fl_RGB_Image * // O - image or NULL if failed Fl_WinAPI_Screen_Driver::read_win_rectangle( int X, // I - Left position int Y, // I - Top position int w, // I - Width of area to read int h, // I - Height of area to read Fl_Window *win, // I - window to capture from or NULL to capture from current offscreen bool may_capture_subwins, bool *did_capture_subwins) { float s = Fl_Surface_Device::surface()->driver()->scale(); int ws, hs; if (int(s) == s) { ws = w * int(s); hs = h * int(s);} else { ws = Fl_Scalable_Graphics_Driver::floor(X+w, s) - Fl_Scalable_Graphics_Driver::floor(X, s), hs = Fl_Scalable_Graphics_Driver::floor(Y+h, s) - Fl_Scalable_Graphics_Driver::floor(Y, s); if (ws < 1) ws = 1; if (hs < 1) hs = 1; } return read_win_rectangle_unscaled(Fl_Scalable_Graphics_Driver::floor(X, s), Fl_Scalable_Graphics_Driver::floor(Y, s), ws, hs, win); } Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win) { // Depth of image is always 3 here // Grab all of the pixels in the image... // Assure that we are not trying to read non-existing data. If it is so, the // function should still work, but the out-of-bounds part of the image is // untouched (initialized with the alpha value or 0 (black), resp.). int ww = w; // We need the original width for output data line size int shift_x = 0; // X target shift if X modified int shift_y = 0; // Y target shift if X modified if (X < 0) { shift_x = -X; w += X; X = 0; } if (Y < 0) { shift_y = -Y; h += Y; Y = 0; } if (h < 1 || w < 1) return 0; // nothing to copy // Allocate and initialize the image data array size_t arraySize = ((size_t)w * h) * 3; uchar *p = new uchar[arraySize]; memset(p, 0, arraySize); int line_size = ((3*w+3)/4) * 4; // each line is aligned on a DWORD (4 bytes) uchar *dib = new uchar[line_size*h]; // create temporary buffer to read DIB // fill in bitmap info for GetDIBits BITMAPINFO bi; bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biWidth = w; bi.bmiHeader.biHeight = -h; // negative => top-down DIB bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 24; // 24 bits RGB bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = 0; bi.bmiHeader.biXPelsPerMeter = 0; bi.bmiHeader.biYPelsPerMeter = 0; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; // copy bitmap from original DC (Window, Fl_Offscreen, ...) if (win && Fl_Window::current() != win) win->make_current(); HDC gc = (HDC)fl_graphics_driver->gc(); HDC hdc = CreateCompatibleDC(gc); HBITMAP hbm = CreateCompatibleBitmap(gc,w,h); int save_dc = SaveDC(hdc); // save context for cleanup SelectObject(hdc,hbm); // select bitmap BitBlt(hdc,0,0,w,h,gc,X,Y,SRCCOPY); // copy image section to DDB // copy RGB image data to the allocated DIB GetDIBits(hdc, hbm, 0, h, dib, (BITMAPINFO *)&bi, DIB_RGB_COLORS); // finally copy the image data to the user buffer for (int j = 0; jalloc_array = 1; return rgb; } void Fl_WinAPI_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &height) { BITMAP bitmap; if ( GetObject((HBITMAP)off, sizeof(BITMAP), &bitmap) ) { width = bitmap.bmWidth; height = bitmap.bmHeight; } } //NOTICE: returns -1 if x,y is not in any screen int Fl_WinAPI_Screen_Driver::screen_num_unscaled(int x, int y) { int screen = -1; if (num_screens < 0) init(); for (int i = 0; i < num_screens; i ++) { if (x >= screens[i].left && x < screens[i].right && y >= screens[i].top && y < screens[i].bottom) { screen = i; break; } } return screen; } float Fl_WinAPI_Screen_Driver::base_scale(int numscreen) { return float(dpi[numscreen][0] / 96.); } fltk-1.4.3/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx0000644000175000017500000011072315004135251023260 0ustar albrechtalbrecht// // Definition of Windows system driver for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "Fl_WinAPI_System_Driver.H" #include #include #include #include #include #include "../../Fl_String.H" #include "../../flstring.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // We must define _WIN32_IE at least to 0x0500 before inclusion of 'shlobj.h' to enable // the declaration of SHGFP_TYPE_CURRENT for some older versions of MinGW, notably // header versions 5.3.0 and earlier, whereas 5.4.2 seems to define _WIN32_IE as needed. #if !(defined _WIN32_IE) || (_WIN32_IE < 0x0500) # undef _WIN32_IE # define _WIN32_IE 0x0500 #endif /* _WIN32_WINNT checks */ #include // function pointer for the UuidCreate Function // RPC_STATUS RPC_ENTRY UuidCreate(UUID __RPC_FAR *Uuid); typedef RPC_STATUS (WINAPI *uuid_func)(UUID __RPC_FAR *Uuid); // Apparently Borland C++ defines DIRECTORY in , which // interferes with the Fl_File_Icon enumeration of the same name. # ifdef DIRECTORY # undef DIRECTORY # endif // DIRECTORY #ifdef __CYGWIN__ # include #endif // Optional helper function to debug Fl_WinAPI_System_Driver::home_directory_name() #ifndef DEBUG_HOME_DIRECTORY_NAME #define DEBUG_HOME_DIRECTORY_NAME 0 #endif #if DEBUG_HOME_DIRECTORY_NAME static void print_env(const char *ev) { const char *val = getenv(ev); printf("%-30.30s = \"%s\"\n", ev, val ? val : ""); fflush(stdout); } #endif // DEBUG_HOME_DIRECTORY_NAME static inline int isdirsep(char c) { return c == '/' || c == '\\'; } static wchar_t *mbwbuf = NULL; static wchar_t *wbuf = NULL; static wchar_t *wbuf1 = NULL; extern "C" { int fl_scandir(const char *dirname, struct dirent ***namelist, int (*select)(struct dirent *), int (*compar)(struct dirent **, struct dirent **), char *errmsg, int errmsg_len); } /* Convert UTF-8 string to Windows wide character encoding (UTF-16). This helper function is used throughout this file to convert UTF-8 strings to Windows specific UTF-16 encoding for filenames, paths, or other strings to be used by system functions. The input string can be a null-terminated string or its length can be provided by the optional argument 'lg'. If 'lg' is omitted or less than 0 (default = -1) the string length is determined with strlen(), otherwise 'lg' takes precedence. Zero (0) is a valid string length (an empty string). The argument 'wbuf' must have been initialized with NULL or a previous call to malloc() or realloc(). If the converted string doesn't fit into the allocated size of 'wbuf' or if 'wbuf' is NULL a new buffer is allocated with realloc(). Hence the pointer 'wbuf' can be shared among multiple calls to this function if it has been initialized with NULL (or malloc or realloc) before the first call. The return value is either the old value of 'wbuf' (if the string fits) or a pointer to the (re)allocated buffer. Pseudo doxygen docs (static function intentionally not documented): param[in] utf8 input string (UTF-8) param[in,out] wbuf in: pointer to output string buffer or NULL out: new string (the pointer may be changed) param[in] lg optional: input string length (default = -1) returns pointer to string buffer */ static wchar_t *utf8_to_wchar(const char *utf8, wchar_t *&wbuf, int lg = -1) { unsigned len = (lg >= 0) ? (unsigned)lg : (unsigned)strlen(utf8); unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 1; // Query length wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * wn); wn = fl_utf8toUtf16(utf8, len, (unsigned short *)wbuf, wn); // Convert string wbuf[wn] = 0; return wbuf; } /* Convert a Windows wide character (UTF-16) string to UTF-8 encoding. This helper function is used throughout this file to convert Windows wide character strings as returned by system functions to UTF-8 encoding for internal usage. The argument 'utf8' must have been initialized with NULL or a previous call to malloc() or realloc(). If the converted string doesn't fit into the allocated size of 'utf8' or if 'utf8' is NULL a new buffer is allocated with realloc(). Hence the pointer 'utf8' can be shared among multiple calls to this function if it has been initialized with NULL (or malloc or realloc) before the first call. Ideally every call to this function has its own static pointer though. The return value is either the old value of 'utf8' (if the string fits) or a pointer at the (re)allocated buffer. Pseudo doxygen docs (static function intentionally not documented): param[in] wstr input string (wide character, UTF-16) param[in,out] utf8 in: pointer to output string buffer out: new string (pointer may be changed) returns pointer to string buffer */ static char *wchar_to_utf8(const wchar_t *wstr, char *&utf8) { unsigned len = (unsigned)wcslen(wstr); unsigned wn = fl_utf8fromwc(NULL, 0, wstr, len) + 1; // query length utf8 = (char *)realloc(utf8, wn); wn = fl_utf8fromwc(utf8, wn, wstr, len); // convert string utf8[wn] = 0; return utf8; } void Fl_WinAPI_System_Driver::warning(const char *format, va_list args) { // Show nothing for warnings under Windows... } void Fl_WinAPI_System_Driver::error(const char *format, va_list args) { char buf[1024]; vsnprintf(buf, 1024, format, args); MessageBox(0, buf, "Error", MB_ICONEXCLAMATION | MB_SYSTEMMODAL); } void Fl_WinAPI_System_Driver::fatal(const char *format, va_list args) { char buf[1024]; vsnprintf(buf, 1024, format, args); MessageBox(0, buf, "Error", MB_ICONSTOP | MB_SYSTEMMODAL); ::exit(1); } char *Fl_WinAPI_System_Driver::utf2mbcs(const char *utf8) { static char *buf = NULL; if (!utf8) return NULL; unsigned len = (unsigned)strlen(utf8); unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 7; // Query length mbwbuf = (wchar_t *)realloc(mbwbuf, sizeof(wchar_t) * wn); len = fl_utf8toUtf16(utf8, len, (unsigned short *)mbwbuf, wn); // Convert string mbwbuf[len] = 0; buf = (char*)realloc(buf, len * 6 + 1); len = (unsigned)wcstombs(buf, mbwbuf, len * 6); buf[len] = 0; return buf; } char *Fl_WinAPI_System_Driver::getenv(const char *var) { static char *buf = NULL; wchar_t *ret = _wgetenv(utf8_to_wchar(var, wbuf)); if (!ret) return NULL; return wchar_to_utf8(ret, buf); } int Fl_WinAPI_System_Driver::putenv(const char *var) { unsigned len = (unsigned)strlen(var); unsigned wn = fl_utf8toUtf16(var, len, NULL, 0) + 1; // Query length wchar_t *wbuf = (wchar_t *)malloc(sizeof(wchar_t) * wn); wn = fl_utf8toUtf16(var, len, (unsigned short *)wbuf, wn); wbuf[wn] = 0; int ret = _wputenv(wbuf); free(wbuf); return ret; } int Fl_WinAPI_System_Driver::open(const char *fnam, int oflags, int pmode) { utf8_to_wchar(fnam, wbuf); if (pmode == -1) return _wopen(wbuf, oflags); else return _wopen(wbuf, oflags, pmode); } int Fl_WinAPI_System_Driver::open_ext(const char *fnam, int binary, int oflags, int pmode) { if (oflags == 0) oflags = _O_RDONLY; oflags |= (binary ? _O_BINARY : _O_TEXT); return this->open(fnam, oflags, pmode); } FILE *Fl_WinAPI_System_Driver::fopen(const char *fnam, const char *mode) { utf8_to_wchar(fnam, wbuf); utf8_to_wchar(mode, wbuf1); return _wfopen(wbuf, wbuf1); } int Fl_WinAPI_System_Driver::system(const char *cmd) { return _wsystem(utf8_to_wchar(cmd, wbuf)); } int Fl_WinAPI_System_Driver::execvp(const char *file, char *const *argv) { int n = 0; while (argv[n]) n++; // count args wchar_t **ar = (wchar_t **)calloc(sizeof(wchar_t *), n + 1); // convert arguments first; trailing NULL provided by calloc() for (int i = 0; i < n; i++) ar[i] = utf8_to_wchar(argv[i], ar[i]); // alloc and assign // convert executable file and execute it ... utf8_to_wchar(file, wbuf); _wexecvp(wbuf, ar); // STR #3040 // clean up (reached only if _wexecvp() failed) for (int i = 0; i < n; i++) free(ar[i]); free(ar); return -1; // STR #3040 } int Fl_WinAPI_System_Driver::chmod(const char *fnam, int mode) { return _wchmod(utf8_to_wchar(fnam, wbuf), mode); } int Fl_WinAPI_System_Driver::access(const char *fnam, int mode) { return _waccess(utf8_to_wchar(fnam, wbuf), mode); } int Fl_WinAPI_System_Driver::flstat(const char *fnam, struct stat *b) { // remove trailing '/' or '\' unsigned len = (unsigned)strlen(fnam); if (len > 0 && (fnam[len-1] == '/' || fnam[len-1] == '\\')) len--; // convert filename and execute _wstat() return _wstat(utf8_to_wchar(fnam, wbuf, len), (struct _stat *)b); } char *Fl_WinAPI_System_Driver::getcwd(char *buf, int len) { static wchar_t *wbuf = NULL; wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * (len + 1)); wchar_t *ret = _wgetcwd(wbuf, len); if (!ret) return NULL; unsigned dstlen = (unsigned)len; len = (int)wcslen(wbuf); dstlen = fl_utf8fromwc(buf, dstlen, wbuf, (unsigned)len); buf[dstlen] = 0; return buf; } int Fl_WinAPI_System_Driver::chdir(const char *path) { return _wchdir(utf8_to_wchar(path, wbuf)); } int Fl_WinAPI_System_Driver::unlink(const char *fnam) { return _wunlink(utf8_to_wchar(fnam, wbuf)); } int Fl_WinAPI_System_Driver::mkdir(const char *fnam, int mode) { return _wmkdir(utf8_to_wchar(fnam, wbuf)); } int Fl_WinAPI_System_Driver::rmdir(const char *fnam) { return _wrmdir(utf8_to_wchar(fnam, wbuf)); } int Fl_WinAPI_System_Driver::rename(const char *fnam, const char *newnam) { utf8_to_wchar(fnam, wbuf); utf8_to_wchar(newnam, wbuf1); return _wrename(wbuf, wbuf1); } // See Fl::args_to_utf8() int Fl_WinAPI_System_Driver::args_to_utf8(int argc, char ** &argv) { int i; // Convert the command line arguments to UTF-8 LPWSTR *wideArgv = CommandLineToArgvW(GetCommandLineW(), &argc); argv = (char **)malloc((argc + 1) * sizeof(char *)); for (i = 0; i < argc; i++) { // find the required size of the buffer int u8size = WideCharToMultiByte(CP_UTF8, // CodePage 0, // dwFlags wideArgv[i], // lpWideCharStr -1, // cchWideChar NULL, // lpMultiByteStr 0, // cbMultiByte NULL, // lpDefaultChar NULL); // lpUsedDefaultChar if (u8size > 0) { char *strbuf = (char*)::malloc(u8size); int ret = WideCharToMultiByte(CP_UTF8, // CodePage 0, // dwFlags wideArgv[i], // lpWideCharStr -1, // cchWideChar strbuf, // lpMultiByteStr u8size, // cbMultiByte NULL, // lpDefaultChar NULL); // lpUsedDefaultChar if (ret) { argv[i] = strbuf; } else { argv[i] = _strdup(""); ::free(strbuf); } } else { argv[i] = _strdup(""); } } argv[argc] = NULL; // required NULL pointer at end of list // Free the wide character string array LocalFree(wideArgv); // Note: the allocated memory or argv[] will not be free'd by the system // on exit. This does not constitute a memory leak. return argc; } // Two Windows-specific functions fl_utf8_to_locale() and fl_locale_to_utf8() // from file fl_utf8.cxx are put here for API compatibility static char *buf = NULL; static int buf_len = 0; static unsigned short *wbufa = NULL; unsigned int fl_codepage = 0; // FIXME: This should *maybe* return 'const char *' instead of 'char *' char *fl_utf8_to_locale(const char *s, int len, UINT codepage) { if (!s) return (char *)""; int l = 0; unsigned wn = fl_utf8toUtf16(s, len, NULL, 0); // Query length wn = wn * 2 + 1; if (wn >= (unsigned)buf_len) { buf_len = wn; buf = (char*) realloc(buf, buf_len); wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short)); } if (codepage < 1) codepage = fl_codepage; l = fl_utf8toUtf16(s, len, wbufa, wn); // Convert string wbufa[l] = 0; buf[l] = 0; l = WideCharToMultiByte(codepage, 0, (WCHAR*)wbufa, l, buf, buf_len, NULL, NULL); if (l < 0) l = 0; buf[l] = 0; return buf; } // FIXME: This should maybe return 'const char *' instead of 'char *' char *fl_locale_to_utf8(const char *s, int len, UINT codepage) { if (!s) return (char *)""; int l = 0; if (buf_len < len * 5 + 1) { buf_len = len * 5 + 1; buf = (char*) realloc(buf, buf_len); wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short)); } if (codepage < 1) codepage = fl_codepage; buf[l] = 0; l = MultiByteToWideChar(codepage, 0, s, len, (WCHAR*)wbufa, buf_len); if (l < 0) l = 0; wbufa[l] = 0; l = fl_utf8fromwc(buf, buf_len, (wchar_t*)wbufa, l); buf[l] = 0; return buf; } /////////////////////////////////// unsigned Fl_WinAPI_System_Driver::utf8towc(const char *src, unsigned srclen, wchar_t *dst, unsigned dstlen) { return fl_utf8toUtf16(src, srclen, (unsigned short*)dst, dstlen); } unsigned Fl_WinAPI_System_Driver::utf8fromwc(char *dst, unsigned dstlen, const wchar_t *src, unsigned srclen) { unsigned i = 0; unsigned count = 0; if (dstlen) for (;;) { unsigned ucs; if (i >= srclen) { dst[count] = 0; return count; } ucs = src[i++]; if (ucs < 0x80U) { dst[count++] = ucs; if (count >= dstlen) {dst[count-1] = 0; break;} } else if (ucs < 0x800U) { /* 2 bytes */ if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;} dst[count++] = 0xc0 | (ucs >> 6); dst[count++] = 0x80 | (ucs & 0x3F); } else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen && src[i] >= 0xdc00 && src[i] <= 0xdfff) { /* surrogate pair */ unsigned ucs2 = src[i++]; ucs = 0x10000U + ((ucs&0x3ff)<<10) + (ucs2&0x3ff); /* all surrogate pairs turn into 4-byte UTF-8 */ if (count+4 >= dstlen) {dst[count] = 0; count += 4; break;} dst[count++] = 0xf0 | (ucs >> 18); dst[count++] = 0x80 | ((ucs >> 12) & 0x3F); dst[count++] = 0x80 | ((ucs >> 6) & 0x3F); dst[count++] = 0x80 | (ucs & 0x3F); } else { /* all others are 3 bytes: */ if (count+3 >= dstlen) {dst[count] = 0; count += 3; break;} dst[count++] = 0xe0 | (ucs >> 12); dst[count++] = 0x80 | ((ucs >> 6) & 0x3F); dst[count++] = 0x80 | (ucs & 0x3F); } } /* we filled dst, measure the rest: */ while (i < srclen) { unsigned ucs = src[i++]; if (ucs < 0x80U) { count++; } else if (ucs < 0x800U) { /* 2 bytes */ count += 2; } else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen-1 && src[i+1] >= 0xdc00 && src[i+1] <= 0xdfff) { /* surrogate pair */ ++i; count += 4; } else { count += 3; } } return count; } int Fl_WinAPI_System_Driver::utf8locale() { static int ret = (GetACP() == CP_UTF8); return ret; } unsigned Fl_WinAPI_System_Driver::utf8to_mb(const char *src, unsigned srclen, char *dst, unsigned dstlen) { wchar_t lbuf[1024]; wchar_t *buf = lbuf; unsigned length = fl_utf8towc(src, srclen, buf, 1024); unsigned ret; if (length >= 1024) { buf = (wchar_t*)(malloc((length+1)*sizeof(wchar_t))); fl_utf8towc(src, srclen, buf, length+1); } if (dstlen) { // apparently this does not null-terminate, even though msdn documentation claims it does: ret = WideCharToMultiByte(GetACP(), 0, buf, length, dst, dstlen, 0, 0); dst[ret] = 0; } // if it overflows or measuring length, get the actual length: if (dstlen==0 || ret >= dstlen-1) ret = WideCharToMultiByte(GetACP(), 0, buf, length, 0, 0, 0, 0); if (buf != lbuf) free(buf); return ret; } unsigned Fl_WinAPI_System_Driver::utf8from_mb(char *dst, unsigned dstlen, const char *src, unsigned srclen) { wchar_t lbuf[1024]; wchar_t *buf = lbuf; unsigned length; unsigned ret; length = MultiByteToWideChar(GetACP(), 0, src, srclen, buf, 1024); if ((length == 0)&&(GetLastError()==ERROR_INSUFFICIENT_BUFFER)) { length = MultiByteToWideChar(GetACP(), 0, src, srclen, 0, 0); buf = (wchar_t*)(malloc(length*sizeof(wchar_t))); MultiByteToWideChar(GetACP(), 0, src, srclen, buf, length); } ret = fl_utf8fromwc(dst, dstlen, buf, length); if (buf != lbuf) free((void*)buf); return ret; } #if defined(_MSC_VER) && (_MSC_VER >= 1400 /*Visual Studio 2005*/) static _locale_t c_locale = NULL; #endif int Fl_WinAPI_System_Driver::clocale_vprintf(FILE *output, const char *format, va_list args) { #if defined(_MSC_VER) && (_MSC_VER >= 1400 /*Visual Studio 2005*/) if (!c_locale) c_locale = _create_locale(LC_NUMERIC, "C"); int retval = _vfprintf_l(output, format, c_locale, args); #else char *saved_locale = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); int retval = vfprintf(output, format, args); setlocale(LC_NUMERIC, saved_locale); #endif return retval; } int Fl_WinAPI_System_Driver::clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) { #if defined(_MSC_VER) && (_MSC_VER >= 1400 /*Visual Studio 2005*/) if (!c_locale) c_locale = _create_locale(LC_NUMERIC, "C"); int retval = _vsnprintf_l(output, output_size, format, c_locale, args); #else char *saved_locale = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); int retval = vsnprintf(output, output_size, format, args); setlocale(LC_NUMERIC, saved_locale); #endif return retval; } int Fl_WinAPI_System_Driver::clocale_vsscanf(const char *input, const char *format, va_list args) { char *saved_locale = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); int retval = vsscanf(input, format, args); setlocale(LC_NUMERIC, saved_locale); return retval; } int Fl_WinAPI_System_Driver::filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **), char *errmsg, int errmsg_sz) { // For Windows we have a special scandir implementation that uses // the Win32 "wide" functions for lookup, avoiding the code page mess // entirely. It also fixes up the trailing '/'. return fl_scandir(d, list, 0, sort, errmsg, errmsg_sz); } int Fl_WinAPI_System_Driver::filename_expand(char *to, int tolen, const char *from) { char *temp = new char[tolen]; strlcpy(temp,from, tolen); char *start = temp; char *end = temp+strlen(temp); int ret = 0; for (char *a=temp; a= tolen) end += tolen - (end+1-e+t); memmove(a+t, e, end+1-e); end = a+t+(end-e); *end = '\0'; memcpy(a, value, t); ret++; } else { a = e+1; if (*e == '\\') {*e = '/'; ret++;} // ha ha! } } strlcpy(to, start, tolen); delete[] temp; return ret; } int // O - 0 if no change, 1 if changed Fl_WinAPI_System_Driver::filename_relative(char *to, // O - Relative filename int tolen, // I - Size of "to" buffer const char *dest_dir, // I - Absolute filename const char *base_dir) // I - Find path relative to this path { // Find the relative path from base_dir to dest_dir. // Both paths must be absolute and well formed (contain no /../ and /./ segments). // return if any of the pointers is NULL if (!to || !dest_dir || !base_dir) { return 0; } // if there is a drive letter, make sure both paths use the same drive if ( (unsigned)base_dir[0] < 128 && isalpha(base_dir[0]) && base_dir[1] == ':' && (unsigned)dest_dir[0] < 128 && isalpha(dest_dir[0]) && dest_dir[1] == ':') { if (tolower(base_dir[0]) != tolower(dest_dir[0])) { strlcpy(to, dest_dir, tolen); return 0; } // same drive, so skip to the start of the path base_dir += 2; dest_dir += 2; } // return if `base_dir` or `dest_dir` is not an absolute path if (!isdirsep(*base_dir) || !isdirsep(*dest_dir)) { strlcpy(to, dest_dir, tolen); return 0; } const char *base_i = base_dir; // iterator through the base directory string const char *base_s = base_dir; // pointer to the last dir separator found const char *dest_i = dest_dir; // iterator through the destination directory const char *dest_s = dest_dir; // pointer to the last dir separator found // compare both path names until we find a difference for (;;) { #if 0 // case sensitive base_i++; dest_i++; char b = *base_i, d = *dest_i; #else // case insensitive base_i += fl_utf8len1(*base_i); int b = fl_tolower(fl_utf8decode(base_i, NULL, NULL)); dest_i += fl_utf8len1(*dest_i); int d = fl_tolower(fl_utf8decode(dest_i, NULL, NULL)); #endif int b0 = (b == 0) || (isdirsep(b)); int d0 = (d == 0) || (isdirsep(d)); if (b0 && d0) { base_s = base_i; dest_s = dest_i; } if (b == 0 || d == 0) break; if (b != d) break; } // base_s and dest_s point at the last separator we found // base_i and dest_i point at the first character that differs // test for the exact same string and return "." if so if ( (base_i[0] == 0 || (isdirsep(base_i[0]) && base_i[1] == 0)) && (dest_i[0] == 0 || (isdirsep(dest_i[0]) && dest_i[1] == 0))) { strlcpy(to, ".", tolen); return 0; } // prepare the destination buffer to[0] = '\0'; to[tolen - 1] = '\0'; // count the directory segments remaining in `base_dir` int n_up = 0; for (;;) { char b = *base_s++; if (b == 0) break; if (isdirsep(b) && *base_s) n_up++; } // now add a "previous dir" sequence for every following slash in the cwd if (n_up > 0) strlcat(to, "..", tolen); for (; n_up > 1; --n_up) strlcat(to, "/..", tolen); // finally add the differing path from "from" if (*dest_s) { if (n_up) strlcat(to, "/", tolen); strlcat(to, dest_s + 1, tolen); } return 1; } int Fl_WinAPI_System_Driver::filename_absolute(char *to, int tolen, const char *from, const char *base) { if (isdirsep(*from) || *from == '|' || from[1]==':' || !base) { strlcpy(to, from, tolen); return 0; } char *a; char *temp = new char[tolen]; const char *start = from; strlcpy(temp, base, tolen); for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha /* remove trailing '/' in current working directory */ if (isdirsep(*(a-1))) a--; /* remove intermediate . and .. names: */ while (*start == '.') { if (start[1]=='.' && (isdirsep(start[2]) || start[2]==0) ) { // found "..", remove the last directory segment form cwd char *b; for (b = a-1; b >= temp && !isdirsep(*b); b--) {/*empty*/} if (b < temp) break; a = b; if (start[2] == 0) start += 2; else start += 3; } else if (isdirsep(start[1])) { // found "./" in path, just skip it start += 2; } else if (!start[1]) { // found "." at end of path, just skip it start ++; break; } else break; } *a++ = '/'; strlcpy(a,start,tolen - (a - temp)); strlcpy(to, temp, tolen); delete[] temp; return 1; } int Fl_WinAPI_System_Driver::filename_isdir(const char *n) { char fn[4]; // used for drive letter only: "X:/" int length = (int)strlen(n); // Strip trailing slash from name... if (length > 0 && isdirsep(n[length - 1])) length --; if (length < 1) return 0; // This workaround brought to you by the fine folks at Microsoft! // (read lots of sarcasm in that...) if (length == 2 && isalpha(n[0]) && n[1] == ':') { // trailing '/' already "removed" // Always use "X:/" for drive letters fn[0] = n[0]; strcpy(fn + 1, ":/"); n = fn; length = 3; } // convert filename to wide chars using *length* utf8_to_wchar(n, wbuf, length); DWORD fa = GetFileAttributesW(wbuf); return (fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY); } int Fl_WinAPI_System_Driver::filename_isdir_quick(const char *n) { // Do a quick optimization for filenames with a trailing slash... if (*n && isdirsep(n[strlen(n) - 1])) return 1; return filename_isdir(n); } const char *Fl_WinAPI_System_Driver::filename_ext(const char *buf) { const char *q = 0; const char *p = buf; for (p = buf; *p; p++) { if (isdirsep(*p) ) q = 0; else if (*p == '.') q = p; } return q ? q : p; } int Fl_WinAPI_System_Driver::open_uri(const char *uri, char *msg, int msglen) { if (msg) snprintf(msg, msglen, "open %s", uri); return (int)(ShellExecute(HWND_DESKTOP, "open", uri, NULL, NULL, SW_SHOW) > (void *)32); } int Fl_WinAPI_System_Driver::file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon) { int num_files = 0; # ifdef __CYGWIN__ // // Cygwin provides an implementation of setmntent() to get the list // of available drives... // FILE *m = setmntent("/-not-used-", "r"); struct mntent *p; while ((p = getmntent (m)) != NULL) { browser->add(p->mnt_dir, icon); num_files ++; } endmntent(m); # else // // Normal Windows code uses drive bits... // DWORD drives; // Drive available bits drives = GetLogicalDrives(); for (int i = 'A'; i <= 'Z'; i ++, drives >>= 1) { if (drives & 1) { snprintf(filename, lname, "%c:/", i); if (i < 'C') // see also: GetDriveType and GetVolumeInformation in Windows browser->add(filename, icon); else browser->add(filename, icon); num_files ++; } } # endif // __CYGWIN__ return num_files; } int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory, char *filename, size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort, char *errmsg, int errmsg_sz) { strlcpy(filename, directory, name_size); int i = (int) (strlen(filename) - 1); if (i == 2 && filename[1] == ':' && (filename[2] == '/' || filename[2] == '\\')) filename[2] = '/'; else if (filename[i] != '/' && filename[i] != '\\') strlcat(filename, "/", name_size); return filename_list(filename, pfiles, sort, errmsg, errmsg_sz); } void Fl_WinAPI_System_Driver::newUUID(char *uuidBuffer) { // First try and use the win API function UuidCreate(), but if that is not // available, fall back to making something up from scratch. // We do not want to link against the Rpcrt4.dll, as we will rarely use it, // so we load the DLL dynamically, if it is available, and work from there. static HMODULE hMod = NULL; UUID ud; UUID *pu = &ud; int got_uuid = 0; if (!hMod) { // first time in? hMod = LoadLibrary("Rpcrt4.dll"); } if (hMod) { // do we have a usable handle to Rpcrt4.dll? uuid_func uuid_crt = (uuid_func)GetProcAddress(hMod, "UuidCreate"); if (uuid_crt != NULL) { RPC_STATUS rpc_res = uuid_crt(pu); if ( // is the return status OK for our needs? (rpc_res == RPC_S_OK) || // all is well (rpc_res == RPC_S_UUID_LOCAL_ONLY) || // only unique to this machine (rpc_res == RPC_S_UUID_NO_ADDRESS) // probably only locally unique ) { got_uuid = -1; snprintf(uuidBuffer, 36+1, "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", pu->Data1, pu->Data2, pu->Data3, pu->Data4[0], pu->Data4[1], pu->Data4[2], pu->Data4[3], pu->Data4[4], pu->Data4[5], pu->Data4[6], pu->Data4[7]); } } } if (got_uuid == 0) { // did not make a UUID - use fallback logic unsigned char b[16]; time_t t = time(0); // first 4 byte b[0] = (unsigned char)t; b[1] = (unsigned char)(t>>8); b[2] = (unsigned char)(t>>16); b[3] = (unsigned char)(t>>24); int r = rand(); // four more bytes b[4] = (unsigned char)r; b[5] = (unsigned char)(r>>8); b[6] = (unsigned char)(r>>16); b[7] = (unsigned char)(r>>24); // Now we try to find 4 more "random" bytes. We extract the // lower 4 bytes from the address of t - it is created on the // stack so *might* be in a different place each time... // This is now done via a union to make it compile OK on 64-bit systems. union { void *pv; unsigned char a[sizeof(void*)]; } v; v.pv = (void *)(&t); // NOTE: This assume that all WinXX systems are little-endian b[8] = v.a[0]; b[9] = v.a[1]; b[10] = v.a[2]; b[11] = v.a[3]; TCHAR name[MAX_COMPUTERNAME_LENGTH + 1]; // only used to make last four bytes DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1; // GetComputerName() does not depend on any extra libs, and returns something // analogous to gethostname() GetComputerName(name, &nSize); // use the first 4 TCHAR's of the name to create the last 4 bytes of our UUID for (int ii = 0; ii < 4; ii++) { b[12 + ii] = (unsigned char)name[ii]; } snprintf(uuidBuffer, 36+1, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]); } } /* Note: `prefs` can be NULL! */ char *Fl_WinAPI_System_Driver::preference_rootnode(Fl_Preferences * /*prefs*/, Fl_Preferences::Root root, const char *vendor, const char *application) { static char *filename = 0L; // make enough room for a UTF-16 pathname if (!filename) filename = (char*)::malloc(2 * FL_PATH_MAX); HRESULT res; // https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpathw int appdata = CSIDL_APPDATA; // assume user preferences if ((root & Fl_Preferences::ROOT_MASK) == Fl_Preferences::SYSTEM) appdata = CSIDL_COMMON_APPDATA; // use system preferences res = SHGetFolderPathW(NULL, // hwnd: Reserved! appdata, // csidl: User or common Application Data (Roaming) NULL, // hToken (unused) SHGFP_TYPE_CURRENT, // dwFlags: use current, potentially redirected path (LPWSTR)filename); // out: filename in Windows wide string encoding if (res != S_OK) { // don't write data into some arbitrary directory! Just return NULL. return 0L; } // convert the path from Windows wide character (UTF-16) to UTF-8 // FIXME: can this be simplified? Don't allocate/copy/move/free more than necessary! char *buf = NULL; wchar_to_utf8((wchar_t *)filename, buf); // allocates buf for conversion strcpy(filename, buf); free(buf); // Make sure that the parameters are not NULL if ( (vendor==0L) || (vendor[0]==0) ) vendor = "unknown"; if ( (application==0L) || (application[0]==0) ) application = "unknown"; // append vendor, application, and ".prefs", and convert '\' to '/' snprintf(filename + strlen(filename), FL_PATH_MAX - strlen(filename), "/%s/%s.prefs", vendor, application); for (char *s = filename; *s; s++) if (*s == '\\') *s = '/'; return filename; } void *Fl_WinAPI_System_Driver::load(const char *filename) { return LoadLibraryW(utf8_to_wchar(filename, wbuf)); } void Fl_WinAPI_System_Driver::png_extra_rgba_processing(unsigned char *ptr, int w, int h) { // Some Windows graphics drivers don't honor transparency when RGB == white // Convert RGB to 0 when alpha == 0... for (int i = w * h; i > 0; i --, ptr += 4) { if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0; } } const char *Fl_WinAPI_System_Driver::next_dir_sep(const char *start) { const char *p = strchr(start, '/'); if (!p) p = strchr(start, '\\'); return p; } int Fl_WinAPI_System_Driver::file_type(const char *filename) { int filetype; if (filename[strlen(filename) - 1] == '/') filetype = Fl_File_Icon::DIRECTORY; else if (filename_isdir(filename)) filetype = Fl_File_Icon::DIRECTORY; else filetype = Fl_File_Icon::PLAIN; return filetype; } // Note: the result is cached in a static variable const char *Fl_WinAPI_System_Driver::home_directory_name() { static Fl_String home; if (!home.empty()) return home.c_str(); #if (DEBUG_HOME_DIRECTORY_NAME) print_env("HOMEDRIVE"); print_env("HOMEPATH"); print_env("UserProfile"); print_env("HOME"); #endif // Implement various ways to retrieve the HOME path. // Note, from `man getenv`: // "The implementation of getenv() is not required to be reentrant. // The string pointed to by the return value of getenv() may be statically // allocated, and can be modified by a subsequent call to getenv()...". // Tests show that this is the case in some MinGW implementations. if (home.empty()) { const char *home_drive = getenv("HOMEDRIVE"); if (home_drive) { home = home_drive; // copy *before* calling getenv() again, see above const char *home_path = getenv("HOMEPATH"); if (home_path) { home.append(home_path); } else { home.clear(); // reset } // home_path } // home_drive } // empty() if (home.empty()) { const char *h = getenv("UserProfile"); if (h) home = h; } if (home.empty()) { const char *h = getenv("HOME"); if (h) home = h; } if (home.empty()) { home = "~/"; // last resort } // Make path canonical. for (int i = 0; i < home.size(); ++i) { if (home[i] == '\\') home[i] = '/'; } #if (DEBUG_HOME_DIRECTORY_NAME) printf("home_directory_name() returns \"%s\"\n", home.c_str()); fflush(stdout); #endif return home.c_str(); } void Fl_WinAPI_System_Driver::gettime(time_t *sec, int *usec) { struct _timeb t; _ftime(&t); *sec = t.time; *usec = t.millitm * 1000; } // // Code for lock support // // These pointers are in Fl_win32.cxx: extern void (*fl_lock_function)(); extern void (*fl_unlock_function)(); // The main thread's ID static DWORD main_thread; // Microsoft's version of a MUTEX... static CRITICAL_SECTION cs; static CRITICAL_SECTION *cs_ring; void Fl_WinAPI_System_Driver::unlock_ring() { LeaveCriticalSection(cs_ring); } void Fl_WinAPI_System_Driver::lock_ring() { if (!cs_ring) { cs_ring = (CRITICAL_SECTION*)malloc(sizeof(CRITICAL_SECTION)); InitializeCriticalSection(cs_ring); } EnterCriticalSection(cs_ring); } // // 'unlock_function()' - Release the lock. // static void unlock_function() { LeaveCriticalSection(&cs); } // // 'lock_function()' - Get the lock. // static void lock_function() { EnterCriticalSection(&cs); } int Fl_WinAPI_System_Driver::lock() { if (!main_thread) InitializeCriticalSection(&cs); lock_function(); if (!main_thread) { fl_lock_function = lock_function; fl_unlock_function = unlock_function; main_thread = GetCurrentThreadId(); } return 0; } void Fl_WinAPI_System_Driver::unlock() { unlock_function(); } void Fl_WinAPI_System_Driver::awake(void* msg) { PostThreadMessage( main_thread, fl_wake_msg, (WPARAM)msg, 0); } int Fl_WinAPI_System_Driver::close_fd(int fd) { return _close(fd); } fltk-1.4.3/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H0000644000175000017500000001312715004135251022645 0ustar albrechtalbrecht// // Windows system driver for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_WinAPI_System_Driver.H \brief Definition of Windows system driver. */ #ifndef FL_WINAPI_SYSTEM_DRIVER_H #define FL_WINAPI_SYSTEM_DRIVER_H #include "../../Fl_System_Driver.H" #include #include // strdup /* Move everything here that manages the system interface. There is exactly one system driver. - filename and pathname management - directory and file access - system time and system timer - multithreading - string management */ class Fl_WinAPI_System_Driver : public Fl_System_Driver { public: void warning(const char *format, va_list args) FL_OVERRIDE; void error(const char *format, va_list args) FL_OVERRIDE; void fatal(const char *format, va_list args) FL_OVERRIDE; char *utf2mbcs(const char *s) FL_OVERRIDE; char *getenv(const char *var) FL_OVERRIDE; int putenv(const char *var) FL_OVERRIDE; int open(const char *fnam, int oflags, int pmode) FL_OVERRIDE; int open_ext(const char *fnam, int binary, int oflags, int pmode) FL_OVERRIDE; FILE *fopen(const char *fnam, const char *mode) FL_OVERRIDE; int system(const char *cmd) FL_OVERRIDE; int execvp(const char *file, char *const *argv) FL_OVERRIDE; int chmod(const char *fnam, int mode) FL_OVERRIDE; int access(const char *fnam, int mode) FL_OVERRIDE; int flstat(const char *fnam, struct stat *b) FL_OVERRIDE; char *getcwd(char *b, int l) FL_OVERRIDE; int chdir(const char *path) FL_OVERRIDE; int unlink(const char *fnam) FL_OVERRIDE; int mkdir(const char *fnam, int mode) FL_OVERRIDE; int rmdir(const char *fnam) FL_OVERRIDE; int rename(const char *fnam, const char *newnam) FL_OVERRIDE; // Windows commandline argument conversion to UTF-8 int args_to_utf8(int argc, char ** &argv) FL_OVERRIDE; // Windows specific UTF-8 conversions unsigned utf8towc(const char *src, unsigned srclen, wchar_t* dst, unsigned dstlen) FL_OVERRIDE; unsigned utf8fromwc(char *dst, unsigned dstlen, const wchar_t* src, unsigned srclen) FL_OVERRIDE; int utf8locale() FL_OVERRIDE; unsigned utf8to_mb(const char *src, unsigned srclen, char *dst, unsigned dstlen) FL_OVERRIDE; unsigned utf8from_mb(char *dst, unsigned dstlen, const char *src, unsigned srclen) FL_OVERRIDE; int clocale_vprintf(FILE *output, const char *format, va_list args) FL_OVERRIDE; int clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) FL_OVERRIDE; int clocale_vsscanf(const char *input, const char *format, va_list args) FL_OVERRIDE; int filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **), char *errmsg=NULL, int errmsg_sz=0) FL_OVERRIDE; int filename_expand(char *to,int tolen, const char *from) FL_OVERRIDE; int filename_relative(char *to, int tolen, const char *from, const char *base) FL_OVERRIDE; int filename_absolute(char *to, int tolen, const char *from, const char *base) FL_OVERRIDE; int filename_isdir(const char *n) FL_OVERRIDE; int filename_isdir_quick(const char *n) FL_OVERRIDE; const char *filename_ext(const char *buf) FL_OVERRIDE; int open_uri(const char *uri, char *msg, int msglen) FL_OVERRIDE; int use_recent_tooltip_fix() FL_OVERRIDE {return 1;} int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon) FL_OVERRIDE; int file_browser_load_directory(const char *directory, char *filename, size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort, char *errmsg=NULL, int errmsg_sz=0) FL_OVERRIDE; void newUUID(char *uuidBuffer) FL_OVERRIDE; char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor, const char *application) FL_OVERRIDE; void *load(const char *filename) FL_OVERRIDE; void png_extra_rgba_processing(unsigned char *array, int w, int h) FL_OVERRIDE; const char *next_dir_sep(const char *start) FL_OVERRIDE; // these 3 are implemented in Fl_lock.cxx void awake(void*) FL_OVERRIDE; int lock() FL_OVERRIDE; void unlock() FL_OVERRIDE; // this one is implemented in Fl_win32.cxx void* thread_message() FL_OVERRIDE; int file_type(const char *filename) FL_OVERRIDE; const char *home_directory_name() FL_OVERRIDE; const char *filesystems_label() FL_OVERRIDE { return "My Computer"; } int backslash_as_slash() FL_OVERRIDE {return 1;} int colon_is_drive() FL_OVERRIDE {return 1;} int case_insensitive_filenames() FL_OVERRIDE {return 1;} // this one is implemented in Fl_win32.cxx const char *filename_name(const char *buf) FL_OVERRIDE; void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE; void add_fd(int fd, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE; void remove_fd(int, int when) FL_OVERRIDE; void remove_fd(int) FL_OVERRIDE; void gettime(time_t *sec, int *usec) FL_OVERRIDE; char* strdup(const char *s) FL_OVERRIDE { return ::_strdup(s); } void lock_ring() FL_OVERRIDE; void unlock_ring() FL_OVERRIDE; double wait(double time_to_wait) FL_OVERRIDE; int ready() FL_OVERRIDE; int close_fd(int fd) FL_OVERRIDE; }; #endif // FL_WINAPI_SYSTEM_DRIVER_H fltk-1.4.3/src/drivers/WinAPI/fl_WinAPI_platform_init.cxx0000644000175000017500000000551515004135251023372 0ustar albrechtalbrecht// // Windows-specific code to initialize Windows support. // // Copyright 2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "../GDI/Fl_GDI_Copy_Surface_Driver.H" #include "../GDI/Fl_GDI_Graphics_Driver.H" #include "Fl_WinAPI_Screen_Driver.H" #include "Fl_WinAPI_System_Driver.H" #include "Fl_WinAPI_Window_Driver.H" #include "../GDI/Fl_GDI_Image_Surface_Driver.H" Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int h) { return new Fl_GDI_Copy_Surface_Driver(w, h); } Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() { #if USE_GDIPLUS // Initialize GDI+. static Gdiplus::GdiplusStartupInput gdiplusStartupInput; if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_CLOSED) { Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_STARTUP; Gdiplus::Status ret = GdiplusStartup(&Fl_GDIplus_Graphics_Driver::gdiplus_token_, &gdiplusStartupInput, NULL); if (ret == 0) { // 0 is same as Gdiplus::Status::Ok, but old mingw64 barks at that Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_OPEN; } else { Fl::warning("GdiplusStartup failed with error code %d.", ret); Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_CLOSED; return new Fl_GDI_Graphics_Driver(); } } else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_OPEN) { // Fl::warning("GdiplusStartup() called, but driver is already open."); } else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_SHUTDOWN) { // Fl::warning("GdiplusStartup() called while driver is shutting down."); } else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_STARTUP) { // Fl::warning("GdiplusStartup() called recursively."); } Fl_Graphics_Driver *driver = new Fl_GDIplus_Graphics_Driver(); return driver; #else return new Fl_GDI_Graphics_Driver(); #endif } Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() { return new Fl_WinAPI_Screen_Driver(); } Fl_System_Driver *Fl_System_Driver::newSystemDriver() { return new Fl_WinAPI_System_Driver(); } Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w) { return new Fl_WinAPI_Window_Driver(w); } Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off) { return new Fl_GDI_Image_Surface_Driver(w, h, high_res, off); } fltk-1.4.3/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx0000644000175000017500000005777415004135251023263 0ustar albrechtalbrecht// // Definition of Windows window driver for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include #include "Fl_WinAPI_Window_Driver.H" #include "Fl_WinAPI_Screen_Driver.H" #include "../GDI/Fl_GDI_Graphics_Driver.H" #include #include #include // for ceil() #if USE_COLORMAP extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx #endif Fl_WinAPI_Window_Driver::Fl_WinAPI_Window_Driver(Fl_Window *win) : Fl_Window_Driver(win) { icon_ = new icon_data; shape_data_ = NULL; memset(icon_, 0, sizeof(icon_data)); cursor = NULL; screen_num_ = -1; } Fl_WinAPI_Window_Driver::~Fl_WinAPI_Window_Driver() { if (shape_data_) { delete shape_data_->effective_bitmap_; delete shape_data_; } delete icon_; } //FILE*LOG=fopen("log.log","w"); RECT // frame of the decorated window in screen coordinates Fl_WinAPI_Window_Driver::border_width_title_bar_height( int &bx, // left and right border width int &by, // bottom border height (=bx) int &bt // height of window title bar ) { Fl_Window *win = pWindow; RECT r = {0,0,0,0}; bx = by = bt = 0; if (win->shown() && !win->parent() && win->border() && win->visible()) { static HMODULE dwmapi_dll = LoadLibrary("dwmapi.dll"); typedef HRESULT (WINAPI* DwmGetWindowAttribute_type)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute); static DwmGetWindowAttribute_type DwmGetWindowAttribute = dwmapi_dll ? (DwmGetWindowAttribute_type)GetProcAddress(dwmapi_dll, "DwmGetWindowAttribute") : NULL; int need_r = 1; if (DwmGetWindowAttribute) { const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9; if ( DwmGetWindowAttribute(fl_xid(win), DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK ) { need_r = 0; } } if (need_r) { GetWindowRect(fl_xid(win), &r); } int width, height; RECT rc; GetClientRect(fl_xid(win), &rc); width = rc.right; height = rc.bottom; bx = (r.right - r.left - width)/2; if (bx < 1) bx = 1; by = bx; bt = r.bottom - r.top - height - 2 * by; } return r; } // --- window data int Fl_WinAPI_Window_Driver::decorated_w() { int bt, bx, by; float s = Fl::screen_driver()->scale(screen_num()); border_width_title_bar_height(bx, by, bt); int mini_bx = int(bx/s); if (mini_bx < 1) mini_bx = 1; return w() + 2 * mini_bx; } int Fl_WinAPI_Window_Driver::decorated_h() { int bt, bx, by; border_width_title_bar_height(bx, by, bt); float s = Fl::screen_driver()->scale(screen_num()); int mini_by = int(by / s); if (mini_by < 1) mini_by = 1; return h() + int((bt + by) / s) + mini_by; } // --- window management void Fl_WinAPI_Window_Driver::shape_bitmap_(Fl_Image* b) { shape_data_->shape_ = b; } void Fl_WinAPI_Window_Driver::shape_alpha_(Fl_Image* img, int offset) { int i, j, d = img->d(), w = img->w(), h = img->h(), bytesperrow = (w+7)/8; unsigned u; uchar byte, onebit; // build an Fl_Bitmap covering the non-fully transparent/black part of the image const uchar* bits = new uchar[h*bytesperrow]; // to store the bitmap const uchar* alpha = (const uchar*)*img->data() + offset; // points to alpha value of rgba pixels for (i = 0; i < h; i++) { uchar *p = (uchar*)bits + i * bytesperrow; byte = 0; onebit = 1; for (j = 0; j < w; j++) { if (d == 3) { u = *alpha; u += *(alpha+1); u += *(alpha+2); } else u = *alpha; if (u > 0) { // if the pixel is not fully transparent/black byte |= onebit; // turn on the corresponding bit of the bitmap } onebit = onebit << 1; // move the single set bit one position to the left if (onebit == 0 || j == w-1) { onebit = 1; *p++ = byte; // store in bitmap one pack of bits byte = 0; } alpha += d; // point to alpha value of next pixel } } Fl_Bitmap* bitmap = new Fl_Bitmap(bits, w, h); bitmap->alloc_array = 1; shape_bitmap_(bitmap); shape_data_->effective_bitmap_ = bitmap; shape_data_->shape_ = img; } void Fl_WinAPI_Window_Driver::shape(const Fl_Image* img) { if (shape_data_) { if (shape_data_->effective_bitmap_) { delete shape_data_->effective_bitmap_; } } else { shape_data_ = new shape_data_type; } memset(shape_data_, 0, sizeof(shape_data_type)); pWindow->border(false); int d = img->d(); if (d && img->count() >= 2) { shape_pixmap_((Fl_Image*)img); shape_data_->shape_ = (Fl_Image*)img; } else if (d == 0) shape_bitmap_((Fl_Image*)img); else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1); else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0); } static inline BYTE bit(int x) { return (BYTE)(1 << (x%8)); } static HRGN bitmap2region(Fl_Image* image) { HRGN hRgn = 0; /* Does this need to be dynamically determined, perhaps? */ const int ALLOC_UNIT = 100; DWORD maxRects = ALLOC_UNIT; RGNDATA* pData = (RGNDATA*)malloc(sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects)); pData->rdh.dwSize = sizeof(RGNDATAHEADER); pData->rdh.iType = RDH_RECTANGLES; pData->rdh.nCount = pData->rdh.nRgnSize = 0; SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); const int bytesPerLine = (image->w() + 7)/8; BYTE* p, *data = (BYTE*)*image->data(); for (int y = 0; y < image->h(); y++) { // each row, left to right for (int x = 0; x < image->w(); x++) { int x0 = x; while (x < image->w()) { p = data + x / 8; if (!((*p) & bit(x))) break; // transparent pixel x++; } if (x > x0) { RECT *pr; /* Add the pixels (x0, y) to (x, y+1) as a new rectangle * in the region */ if (pData->rdh.nCount >= maxRects) { maxRects += ALLOC_UNIT; pData = (RGNDATA*)realloc(pData, sizeof(RGNDATAHEADER) + (sizeof(RECT)*maxRects)); } pr = (RECT*)&pData->Buffer; SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1); if (x0 < pData->rdh.rcBound.left) pData->rdh.rcBound.left = x0; if (y < pData->rdh.rcBound.top) pData->rdh.rcBound.top = y; if (x > pData->rdh.rcBound.right) pData->rdh.rcBound.right = x; if (y+1 > pData->rdh.rcBound.bottom) pData->rdh.rcBound.bottom = y+1; pData->rdh.nCount++; /* On Windows98, ExtCreateRegion() may fail if the * number of rectangles is too large (ie: > * 4000). Therefore, we have to create the region by * multiple steps. */ if (pData->rdh.nCount == 2000) { HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT)*maxRects), pData); if (hRgn) { CombineRgn(hRgn, hRgn, h, RGN_OR); DeleteObject(h); } else hRgn = h; pData->rdh.nCount = 0; SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); } } } /* Go to next row */ data += bytesPerLine; } /* Create or extend the region with the remaining rectangles*/ HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT)*maxRects), pData); if (hRgn) { CombineRgn(hRgn, hRgn, h, RGN_OR); DeleteObject(h); } else hRgn = h; free(pData); // I've created the region so I can free this now, right? return hRgn; } void Fl_WinAPI_Window_Driver::draw_begin() { if (shape_data_) { float s = Fl::screen_driver()->scale(screen_num()); if ((shape_data_->lw_ != s*w() || shape_data_->lh_ != s*h()) && shape_data_->shape_) { // size of window has changed since last time shape_data_->lw_ = int(s * w()); shape_data_->lh_ = int(s * h()); Fl_Image* temp = shape_data_->effective_bitmap_ ? shape_data_->effective_bitmap_ : shape_data_->shape_; temp = temp->copy(shape_data_->lw_, shape_data_->lh_); HRGN region = bitmap2region(temp); SetWindowRgn(fl_xid(pWindow), region, TRUE); // the system deletes the region when it's no longer needed delete temp; } } } void Fl_WinAPI_Window_Driver::flush_double() { if (!shown()) return; pWindow->make_current(); // make sure fl_gc is non-zero Fl_X *i = Fl_X::flx(pWindow); if (!i) return; // window not yet created if (!other_xid) { other_xid = new Fl_Image_Surface(w(), h(), 1); pWindow->clear_damage(FL_DAMAGE_ALL); } if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { fl_clip_region(i->region); i->region = 0; #if 0 /* Short form that transiently changes the current Fl_Surface_Device */ Fl_Surface_Device::push_current(other_xid); fl_graphics_driver->clip_region( 0 ); draw(); Fl_Surface_Device::pop_current(); #else /* Alternative form that avoids changing the current Fl_Surface_Device. The code run in the window draw() method can call Fl_Surface_Device::surface() and conclude that it's drawing to the display, which is ultimately true for an Fl_Double_Window. */ HDC sgc = fl_gc; fl_gc = fl_makeDC((HBITMAP)other_xid->offscreen()); int savedc = SaveDC(fl_gc); fl_graphics_driver->gc(fl_gc); fl_graphics_driver->restore_clip(); // duplicate clip region into new gc # if defined(FLTK_HAVE_CAIROEXT) if (Fl::cairo_autolink_context()) Fl::cairo_make_current(pWindow); # endif draw(); RestoreDC(fl_gc, savedc); DeleteDC(fl_gc); fl_graphics_driver->gc(sgc); #endif } int X = 0, Y = 0, W = 0, H = 0; fl_clip_box(0, 0, w(), h(), X, Y, W, H); if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid->offscreen(), X, Y); } void Fl_WinAPI_Window_Driver::flush_overlay() { Fl_Overlay_Window *oWindow = pWindow->as_overlay_window(); if (!shown()) return; pWindow->make_current(); // make sure fl_gc is non-zero Fl_X *i = Fl_X::flx(pWindow); if (!i) return; // window not yet created int eraseoverlay = (pWindow->damage()&FL_DAMAGE_OVERLAY); pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY)); if (!other_xid) { other_xid = new Fl_Image_Surface(w(), h(), 1); pWindow->clear_damage(FL_DAMAGE_ALL); } if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { fl_clip_region(i->region); i->region = 0; Fl_Surface_Device::push_current(other_xid); fl_graphics_driver->clip_region(0); draw(); Fl_Surface_Device::pop_current(); } if (eraseoverlay) fl_clip_region(0); int X, Y, W, H; fl_clip_box(0, 0, w(), h(), X, Y, W, H); if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid->offscreen(), X, Y); if (overlay() == oWindow) oWindow->draw_overlay(); } void Fl_WinAPI_Window_Driver::icons(const Fl_RGB_Image *icons[], int count) { free_icons(); if (count > 0) { icon_->icons = new Fl_RGB_Image*[count]; icon_->count = count; // FIXME: Fl_RGB_Image lacks const modifiers on methods for (int i = 0;i < count;i++) { icon_->icons[i] = (Fl_RGB_Image*)((Fl_RGB_Image*)icons[i])->copy(); icon_->icons[i]->normalize(); } } if (Fl_X::flx(pWindow)) set_icons(); } const void *Fl_WinAPI_Window_Driver::icon() const { return icon_->legacy_icon; } void Fl_WinAPI_Window_Driver::icon(const void * ic) { free_icons(); icon_->legacy_icon = ic; } void Fl_WinAPI_Window_Driver::free_icons() { int i; icon_->legacy_icon = 0L; if (icon_->icons) { for (i = 0;i < icon_->count;i++) delete icon_->icons[i]; delete [] icon_->icons; icon_->icons = 0L; } icon_->count = 0; if (icon_->big_icon) DestroyIcon(icon_->big_icon); if (icon_->small_icon) DestroyIcon(icon_->small_icon); icon_->big_icon = NULL; icon_->small_icon = NULL; } void Fl_WinAPI_Window_Driver::make_current() { fl_GetDC(fl_xid(pWindow)); #if USE_COLORMAP // Windows maintains a hardware and software color palette; the // SelectPalette() call updates the current soft->hard mapping // for all drawing calls, so we must select it here before any // code does any drawing... fl_select_palette(); #endif // USE_COLORMAP fl_graphics_driver->clip_region(0); ((Fl_GDI_Graphics_Driver*)fl_graphics_driver)->scale(Fl::screen_driver()->scale(screen_num())); #if defined(FLTK_HAVE_CAIROEXT) if (Fl::cairo_autolink_context()) Fl::cairo_make_current(pWindow); #endif } void Fl_WinAPI_Window_Driver::label(const char *name,const char *iname) { if (shown() && !parent()) { if (!name) name = ""; size_t l = strlen(name); // WCHAR *lab = (WCHAR*) malloc((l + 1) * sizeof(short)); // l = fl_utf2unicode((unsigned char*)name, l, (wchar_t*)lab); unsigned wlen = fl_utf8toUtf16(name, (unsigned) l, NULL, 0); // Pass NULL to query length wlen++; unsigned short * lab = (unsigned short*)malloc(sizeof(unsigned short)*wlen); wlen = fl_utf8toUtf16(name, (unsigned) l, lab, wlen); lab[wlen] = 0; SetWindowTextW(fl_xid(pWindow), (WCHAR *)lab); free(lab); } } extern void fl_clipboard_notify_retarget(HWND wnd); extern void fl_update_clipboard(void); extern char fl_i_own_selection[2]; void Fl_WinAPI_Window_Driver::hide() { Fl_X* ip = Fl_X::flx(pWindow); // STR#3079: if there remains a window and a non-modal window, and the window is deleted, // the app remains running without any apparent window. // Bug mechanism: hiding an owner window unmaps the owned (non-modal) window(s) // but does not delete it(them) in FLTK. // Fix for it: // when hiding a window, build list of windows it owns, and do hide/show on them. int count = 0; Fl_Window *win, **doit = NULL; for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) { if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == (HWND)ip->xid) { count++; } } if (count) { doit = new Fl_Window*[count]; count = 0; for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) { if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == (HWND)ip->xid) { doit[count++] = win; } } } if (hide_common()) { delete[] doit; // note: `count` and `doit` may be NULL (see PR #241) return; } // Issue #569: undo RegisterDragDrop() RevokeDragDrop((HWND)ip->xid); fl_i_own_selection[1] = 0; // issue #1233 // make sure any custom icons get freed // icons(NULL, 0); // free_icons() is called by the Fl_Window destructor // this little trick keeps the current clipboard alive, even if we are about // to destroy the window that owns the selection. if (GetClipboardOwner() == (HWND)ip->xid) fl_update_clipboard(); // Make sure we unlink this window from the clipboard chain fl_clipboard_notify_retarget((HWND)ip->xid); // Send a message to myself so that I'll get out of the event loop... PostMessage((HWND)ip->xid, WM_APP, 0, 0); if (private_dc) fl_release_dc((HWND)ip->xid, private_dc); if ((HWND)ip->xid == fl_window && fl_graphics_driver->gc()) { fl_release_dc(fl_window, (HDC)fl_graphics_driver->gc()); fl_window = (HWND)-1; fl_graphics_driver->gc(0); # ifdef FLTK_HAVE_CAIROEXT if (Fl::cairo_autolink_context()) Fl::cairo_make_current((Fl_Window*) 0); # endif } if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region); // this little trickery seems to avoid the popup window stacking problem HWND p = GetForegroundWindow(); if (p==GetParent((HWND)ip->xid)) { ShowWindow((HWND)ip->xid, SW_HIDE); ShowWindow(p, SW_SHOWNA); } DestroyWindow((HWND)ip->xid); // end of fix for STR#3079 if (count) { int ii; for (ii = 0; ii < count; ii++) doit[ii]->hide(); for (ii = 0; ii < count; ii++) { if (ii != 0) doit[0]->show(); // Fix for STR#3165 doit[ii]->show(); } } delete[] doit; // note: `count` and `doit` may be NULL (see PR #241) // Try to stop the annoying "raise another program" behavior if (pWindow->non_modal() && Fl::first_window() && Fl::first_window()->shown()) Fl::first_window()->show(); delete ip; screen_num_ = -1; } void Fl_WinAPI_Window_Driver::map() { ShowWindow(fl_xid(pWindow), SW_RESTORE); // extra map calls are harmless } void Fl_WinAPI_Window_Driver::unmap() { ShowWindow(fl_xid(pWindow), SW_HIDE); } #if !defined(FL_DOXYGEN) // FIXME - silence Doxygen warning void Fl_WinAPI_Window_Driver::make_fullscreen(int X, int Y, int W, int H) { HWND xid = fl_xid(pWindow); int top, bottom, left, right; int sx, sy, sw, sh; top = fullscreen_screen_top(); bottom = fullscreen_screen_bottom(); left = fullscreen_screen_left(); right = fullscreen_screen_right(); if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) { top = screen_num(); bottom = top; left = top; right = top; } Fl_WinAPI_Screen_Driver *scr_dr = (Fl_WinAPI_Screen_Driver*)Fl::screen_driver(); scr_dr->screen_xywh_unscaled(sx, Y, sw, sh, top); scr_dr->screen_xywh_unscaled(sx, sy, sw, sh, bottom); H = sy + sh - Y; scr_dr->screen_xywh_unscaled(X, sy, sw, sh, left); scr_dr->screen_xywh_unscaled(sx, sy, sw, sh, right); W = sx + sw - X; DWORD flags = GetWindowLong(xid, GWL_STYLE); flags = flags & ~(WS_THICKFRAME|WS_CAPTION); SetWindowLong(xid, GWL_STYLE, flags); // SWP_NOSENDCHANGING is so that we can override size limits SetWindowPos(xid, HWND_TOP, X, Y, W, H, SWP_NOSENDCHANGING | SWP_FRAMECHANGED); } #endif // !defined(FL_DOXYGEN) // FIXME - silence Doxygen warning void Fl_WinAPI_Window_Driver::fullscreen_on() { pWindow->_set_fullscreen(); make_fullscreen(x(), y(), w(), h()); Fl::handle(FL_FULLSCREEN, pWindow); } void Fl_WinAPI_Window_Driver::fullscreen_off(int X, int Y, int W, int H) { pWindow->_clear_fullscreen(); DWORD style = GetWindowLong(fl_xid(pWindow), GWL_STYLE); if (pWindow->border()) style |= WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_CAPTION; // Remove the xid temporarily so that Fl_WinAPI_Window_Driver::fake_X_wm() behaves like it // does in Fl_WinAPI_Window_Driver::makeWindow(). HWND xid = fl_xid(pWindow); Fl_X::flx(pWindow)->xid = 0; int wx, wy, bt, bx, by; switch (fake_X_wm(wx, wy, bt, bx, by, style)) { case 0: break; case 1: style |= WS_CAPTION; break; case 2: /*if (border()) { style |= WS_THICKFRAME | WS_CAPTION; }*/ break; } Fl_X::flx(pWindow)->xid = (fl_uintptr_t)xid; SetWindowLong(fl_xid(pWindow), GWL_STYLE, style); if (!pWindow->maximize_active()) { // compute window position and size in scaled units float s = Fl::screen_driver()->scale(screen_num()); int scaledX = int(ceil(X*s)), scaledY= int(ceil(Y*s)), scaledW = int(ceil(W*s)), scaledH = int(ceil(H*s)); // Adjust for decorations (but not if that puts the decorations // outside the screen) if ((X != x()) || (Y != y())) { scaledX -= bx; scaledY -= by+bt; } scaledW += bx*2; scaledH += by*2+bt; SetWindowPos(fl_xid(pWindow), 0, scaledX, scaledY, scaledW, scaledH, SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); } else { int WX, WY, WW, WH; ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->screen_xywh_unscaled(WX, WY, WW, WH, screen_num()); SetWindowPos(fl_xid(pWindow), 0, WX, WY, WW, WH, SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); } Fl::handle(FL_FULLSCREEN, pWindow); } void Fl_WinAPI_Window_Driver::maximize() { if (!border()) return Fl_Window_Driver::maximize(); ShowWindow(fl_xid(pWindow), SW_SHOWMAXIMIZED); } void Fl_WinAPI_Window_Driver::un_maximize() { if (!border()) return Fl_Window_Driver::un_maximize(); ShowWindow(fl_xid(pWindow), SW_SHOWNORMAL); } void Fl_WinAPI_Window_Driver::iconize() { ShowWindow(fl_xid(pWindow), SW_SHOWMINNOACTIVE); } void Fl_WinAPI_Window_Driver::decoration_sizes(int *top, int *left, int *right, int *bottom) { int minw, minh, maxw, maxh, set; set = pWindow->get_size_range(&minw, &minh, &maxw, &maxh, NULL, NULL, NULL); if (set && (maxw != minw || maxh != minh)) { *left = *right = GetSystemMetrics(SM_CXSIZEFRAME); *top = *bottom = GetSystemMetrics(SM_CYSIZEFRAME); } else { *left = *right = GetSystemMetrics(SM_CXFIXEDFRAME); *top = *bottom = GetSystemMetrics(SM_CYFIXEDFRAME); } *top += GetSystemMetrics(SM_CYCAPTION); } int Fl_WinAPI_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data) { typedef int (WINAPI* fl_GetRandomRgn_func)(HDC, HRGN, INT); static fl_GetRandomRgn_func fl_GetRandomRgn = 0L; static char first_time = 1; // We will have to do some Region magic now, so let's see if the // required function is available (and it should be starting w/Win95) if (first_time) { HMODULE hMod = GetModuleHandle("GDI32.DLL"); if (hMod) { fl_GetRandomRgn = (fl_GetRandomRgn_func)GetProcAddress(hMod, "GetRandomRgn"); } first_time = 0; } float s = Fl::screen_driver()->scale(screen_num()); src_x = int(src_x * s); src_y = int(src_y * s); src_w = int(src_w * s); src_h = int(src_h * s); dest_x = int(dest_x * s); dest_y = int(dest_y * s); // Now check if the source scrolling area is fully visible. // If it is, we will do a quick scroll and just update the // newly exposed area. If it is not, we go the safe route and // re-render the full area instead. // Note 1: we could go and find the areas that are actually // obscured and recursively call fl_scroll for the newly found // rectangles. However, this practice would rely on the // elements of the undocumented Rgn structure. // Note 2: although this method should take care of most // multi-screen solutions, it will not solve issues scrolling // from a different resolution screen onto another. // Note 3: this has been tested with image maps, too. HDC gc = (HDC)fl_graphics_driver->gc(); if (fl_GetRandomRgn) { // get the DC region minus all overlapping windows HRGN sys_rgn = CreateRectRgn(0, 0, 0, 0); fl_GetRandomRgn(gc, sys_rgn, 4); // now get the source scrolling rectangle HRGN src_rgn = CreateRectRgn(src_x, src_y, src_x+src_w, src_y+src_h); POINT offset = { 0, 0 }; if (GetDCOrgEx(gc, &offset)) { OffsetRgn(src_rgn, offset.x, offset.y); } // see if all source pixels are available in the system region // Note: we could be a bit more merciful and subtract the // scroll destination region as well. HRGN dst_rgn = CreateRectRgn(0, 0, 0, 0); int r = CombineRgn(dst_rgn, src_rgn, sys_rgn, RGN_DIFF); DeleteObject(dst_rgn); DeleteObject(src_rgn); DeleteObject(sys_rgn); if (r != NULLREGION) { return 1; } } // Great, we can do an accelerated scroll instead of re-rendering BitBlt(gc, dest_x, dest_y, src_w, src_h, gc, src_x, src_y,SRCCOPY); return 0; } Fl_WinAPI_Window_Driver::type_for_resize_window_between_screens Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_ = {0, false}; void Fl_WinAPI_Window_Driver::resize_after_screen_change(void *data) { Fl_Window *win = (Fl_Window*)data; RECT r; GetClientRect(fl_xid(win), &r); float old_f = float(r.right)/win->w(); int ns = data_for_resize_window_between_screens_.screen; Fl_Window_Driver::driver(win)->resize_after_scale_change(ns, old_f, Fl::screen_driver()->scale(ns)); data_for_resize_window_between_screens_.busy = false; } const Fl_Image* Fl_WinAPI_Window_Driver::shape() { return shape_data_ ? shape_data_->shape_ : NULL; } HWND fl_win32_xid(const Fl_Window *win) { return (HWND)Fl_Window_Driver::xid(win); } Fl_Window *fl_win32_find(HWND xid) { return Fl_Window_Driver::find((fl_uintptr_t)xid); } fltk-1.4.3/src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx0000644000175000017500000003453115004135251023667 0ustar albrechtalbrecht// // Class Fl_WinAPI_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if HAVE_GL #include #include "../../Fl_Screen_Driver.H" #include #include "Fl_WinAPI_Gl_Window_Driver.H" #include "../../Fl_Gl_Choice.H" #include "Fl_WinAPI_Window_Driver.H" #include "../GDI/Fl_Font.H" extern void fl_save_dc(HWND, HDC); #ifndef GL_CURRENT_PROGRAM # define GL_CURRENT_PROGRAM 0x8B8D // from glew.h #endif // STR #3119: select pixel format with composition support // ... and no more than 32 color bits (8 bits/color) // Ref: PixelFormatDescriptor Object // https://msdn.microsoft.com/en-us/library/cc231189.aspx #if !defined(PFD_SUPPORT_COMPOSITION) # define PFD_SUPPORT_COMPOSITION (0x8000) #endif #define DEBUG_PFD (0) // 1 = PFD selection debug output, 0 = no debug output // Describes crap needed to create a GLContext. class Fl_WinAPI_Gl_Choice : public Fl_Gl_Choice { friend class Fl_WinAPI_Gl_Window_Driver; private: int pixelformat; // the visual to use PIXELFORMATDESCRIPTOR pfd; // some wgl calls need this thing public: Fl_WinAPI_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : Fl_Gl_Choice(m, alistp, n) { pixelformat = 0; } }; Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w) { return new Fl_WinAPI_Gl_Window_Driver(w); } Fl_Gl_Choice *Fl_WinAPI_Gl_Window_Driver::find(int m, const int *alistp) { Fl_WinAPI_Gl_Choice *g = (Fl_WinAPI_Gl_Choice*)Fl_Gl_Window_Driver::find_begin(m, alistp); if (g) return g; // Replacement for ChoosePixelFormat() that finds one with an overlay if possible: HDC gc = (HDC)(fl_graphics_driver ? fl_graphics_driver->gc() : 0); if (!gc) gc = fl_GetDC(0); int pixelformat = 0; PIXELFORMATDESCRIPTOR chosen_pfd; for (int i = 1; ; i++) { PIXELFORMATDESCRIPTOR pfd; if (!DescribePixelFormat(gc, i, sizeof(pfd), &pfd)) break; // continue if it does not satisfy our requirements: if (~pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL)) continue; if (pfd.iPixelType != ((m&FL_INDEX)?PFD_TYPE_COLORINDEX:PFD_TYPE_RGBA)) continue; if ((m & FL_ALPHA) && !pfd.cAlphaBits) continue; if ((m & FL_ACCUM) && !pfd.cAccumBits) continue; if ((!(m & FL_DOUBLE)) != (!(pfd.dwFlags & PFD_DOUBLEBUFFER))) continue; if ((!(m & FL_STEREO)) != (!(pfd.dwFlags & PFD_STEREO))) continue; if ((m & FL_DEPTH) && !pfd.cDepthBits) continue; if ((m & FL_STENCIL) && !pfd.cStencilBits) continue; #if DEBUG_PFD printf("pfd #%d supports composition: %s\n", i, (pfd.dwFlags & PFD_SUPPORT_COMPOSITION) ? "yes" : "no"); printf(" ... & PFD_GENERIC_FORMAT: %s\n", (pfd.dwFlags & PFD_GENERIC_FORMAT) ? "generic" : "accelerated"); printf(" ... Overlay Planes : %d\n", pfd.bReserved & 15); printf(" ... Color & Depth : %d, %d\n", pfd.cColorBits, pfd.cDepthBits); if (pixelformat) printf(" current pixelformat : %d\n", pixelformat); fflush(stdout); #endif // DEBUG_PFD // see if better than the one we have already: if (pixelformat) { // offering non-generic rendering is better (read: hardware acceleration) if (!(chosen_pfd.dwFlags & PFD_GENERIC_FORMAT) && (pfd.dwFlags & PFD_GENERIC_FORMAT)) continue; // offering overlay is better: else if (!(chosen_pfd.bReserved & 15) && (pfd.bReserved & 15)) {} // otherwise prefer a format that supports composition (STR #3119) else if ((chosen_pfd.dwFlags & PFD_SUPPORT_COMPOSITION) && !(pfd.dwFlags & PFD_SUPPORT_COMPOSITION)) continue; // otherwise more bit planes is better, but no more than 32 (8 bits per channel): else if (pfd.cColorBits > 32 || chosen_pfd.cColorBits > pfd.cColorBits) continue; else if (chosen_pfd.cDepthBits > pfd.cDepthBits) continue; } pixelformat = i; chosen_pfd = pfd; } #if DEBUG_PFD static int bb = 0; if (!bb) { bb = 1; printf("PFD_SUPPORT_COMPOSITION = 0x%x\n", PFD_SUPPORT_COMPOSITION); } printf("Chosen pixel format is %d\n", pixelformat); printf("Color bits = %d, Depth bits = %d\n", chosen_pfd.cColorBits, chosen_pfd.cDepthBits); printf("Pixel format supports composition: %s\n", (chosen_pfd.dwFlags & PFD_SUPPORT_COMPOSITION) ? "yes" : "no"); fflush(stdout); #endif // DEBUG_PFD if (!pixelformat) return 0; g = new Fl_WinAPI_Gl_Choice(m, alistp, first); first = g; g->pixelformat = pixelformat; g->pfd = chosen_pfd; return g; } GLContext Fl_WinAPI_Gl_Window_Driver::do_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) { Fl_X* i = Fl_X::flx(window); HDC hdc = Fl_WinAPI_Window_Driver::driver(window)->private_dc; if (!hdc) { hdc = Fl_WinAPI_Window_Driver::driver(window)->private_dc = GetDCEx((HWND)i->xid, 0, DCX_CACHE); fl_save_dc((HWND)i->xid, hdc); SetPixelFormat(hdc, ((Fl_WinAPI_Gl_Choice*)g)->pixelformat, (PIXELFORMATDESCRIPTOR*)(&((Fl_WinAPI_Gl_Choice*)g)->pfd)); # if USE_COLORMAP if (fl_palette) SelectPalette(hdc, fl_palette, FALSE); # endif } GLContext context = layer ? wglCreateLayerContext(hdc, layer) : wglCreateContext(hdc); if (context) { if (context_list && nContext) wglShareLists((HGLRC)context_list[0], (HGLRC)context); add_context(context); } return context; } GLContext Fl_WinAPI_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) { return do_create_gl_context(window, g, 0); } void Fl_WinAPI_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) { GLContext current_context = wglGetCurrentContext(); if (context != current_context || w != cached_window) { cached_window = w; wglMakeCurrent(Fl_WinAPI_Window_Driver::driver(w)->private_dc, (HGLRC)context); } } void Fl_WinAPI_Gl_Window_Driver::delete_gl_context(GLContext context) { GLContext current_context = wglGetCurrentContext(); if (current_context == context) { cached_window = 0; wglMakeCurrent(0, 0); } wglDeleteContext((HGLRC)context); del_context(context); } void Fl_WinAPI_Gl_Window_Driver::make_overlay_current() { #if HAVE_GL_OVERLAY if (overlay() != this) { set_gl_context(pWindow, (GLContext)overlay()); // if (fl_overlay_depth) // wglRealizeLayerPalette(Fl_X::flx(this)->private_dc, 1, TRUE); } else #endif glDrawBuffer(GL_FRONT); } void Fl_WinAPI_Gl_Window_Driver::redraw_overlay() { pWindow->damage(FL_DAMAGE_OVERLAY); } #if HAVE_GL_OVERLAY // Methods on Fl_Gl_Window_driver that create an overlay window. // Under win32 another GLX context is created to draw into the overlay // and it is stored in the "overlay" pointer. // If overlay hardware is unavailable, the overlay is // "faked" by drawing into the main layers. This is indicated by // setting overlay == this. //static COLORREF *palette; static int fl_overlay_depth = 0; void Fl_WinAPI_Gl_Window_Driver::gl_hide_before(void *& overlay) { if (overlay && overlay != pWindow) { delete_gl_context((GLContext)overlay); overlay = 0; } } void Fl_WinAPI_Gl_Window_Driver::make_overlay(void*&overlay) { if (overlay) return; GLContext context = do_create_gl_context(pWindow, g(), 1); if (!context) {overlay = pWindow; return;} // fake the overlay HDC hdc = Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc; overlay = context; LAYERPLANEDESCRIPTOR pfd; wglDescribeLayerPlane(hdc, g()->pixelformat, 1, sizeof(pfd), &pfd); if (!pfd.iPixelType) { ; // full-color overlay } else { fl_overlay_depth = pfd.cColorBits; // used by gl_color() if (fl_overlay_depth > 8) fl_overlay_depth = 8; COLORREF palette[256]; int n = (1<valid(0); return; } int Fl_WinAPI_Gl_Window_Driver::can_do_overlay() { if (!g()) { g( find(mode(), alist()) ); if (!g()) return 0; } return (g()->pfd.bReserved & 15) != 0; } int Fl_WinAPI_Gl_Window_Driver::overlay_color(Fl_Color i) { if (Fl_Xlib_Graphics_Driver::fl_overlay && fl_overlay_depth) { if (fl_overlay_depth < 8) { // only black & white produce the expected colors. This could // be improved by fixing the colormap set in Fl_Gl_Overlay.cxx int size = 1<= size-2) glIndexi(size-1); else glIndexi(i); } else { glIndexi(i ? i : FL_GRAY_RAMP); } return 1; } return 0; } #endif // HAVE_GL_OVERLAY float Fl_WinAPI_Gl_Window_Driver::pixels_per_unit() { int ns = Fl_Window_Driver::driver(pWindow)->screen_num(); return Fl::screen_driver()->scale(ns); } int Fl_WinAPI_Gl_Window_Driver::mode_(int m, const int *a) { int oldmode = mode(); pWindow->context(0); mode( m); alist(a); if (pWindow->shown()) { g( find(m, a) ); if (!g() || (oldmode^m)&(FL_DOUBLE|FL_STEREO)) { pWindow->hide(); pWindow->show(); } } else { g(0); } return 1; } void Fl_WinAPI_Gl_Window_Driver::make_current_after() { #if USE_COLORMAP if (fl_palette) { fl_GetDC(fl_xid(pWindow)); SelectPalette((HDC)fl_graphics_driver->gc(), fl_palette, FALSE); RealizePalette((HDC)fl_graphics_driver->gc()); } #endif // USE_COLORMAP } //#define HAVE_GL_OVERLAY 1 //test only void Fl_WinAPI_Gl_Window_Driver::swap_buffers() { # if HAVE_GL_OVERLAY // Do not swap the overlay, to match GLX: BOOL ret = wglSwapLayerBuffers(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc, WGL_SWAP_MAIN_PLANE); DWORD err = GetLastError(); # else SwapBuffers(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc); # endif } // Start of swap_interval implementation in the three possibel ways for X11 // -1 = not yet initialized, 0 = none found, 1 = GLX, 2 = MESA, 3 = SGI static signed char swap_interval_type = -1; typedef const char *(WINAPI *WGL_Get_Extension_String_Proc)(); typedef BOOL (WINAPI *WGL_Swap_Iterval_Proc)(int interval); typedef int (WINAPI *WGL_Get_Swap_Iterval_Proc)(); static WGL_Swap_Iterval_Proc wglSwapIntervalEXT = NULL; static WGL_Get_Swap_Iterval_Proc wglGetSwapIntervalEXT = NULL; static void init_swap_interval() { if (swap_interval_type != -1) return; swap_interval_type = 0; WGL_Get_Extension_String_Proc wglGetExtensionsStringEXT = NULL; wglGetExtensionsStringEXT = (WGL_Get_Extension_String_Proc)wglGetProcAddress("wglGetExtensionsStringEXT"); if (!wglGetExtensionsStringEXT) return; const char *extensions = wglGetExtensionsStringEXT(); if (extensions && strstr(extensions, "WGL_EXT_swap_control")) { wglSwapIntervalEXT = (WGL_Swap_Iterval_Proc)wglGetProcAddress("wglSwapIntervalEXT"); wglGetSwapIntervalEXT = (WGL_Get_Swap_Iterval_Proc)wglGetProcAddress("wglGetSwapIntervalEXT"); swap_interval_type = 1; } } void Fl_WinAPI_Gl_Window_Driver::swap_interval(int interval) { if (swap_interval_type == -1) init_swap_interval(); if (swap_interval_type == 1) { if (wglSwapIntervalEXT) wglSwapIntervalEXT(interval); } } int Fl_WinAPI_Gl_Window_Driver::swap_interval() const { if (swap_interval_type == -1) init_swap_interval(); int interval = -1; if (swap_interval_type == 1) { if (wglGetSwapIntervalEXT) interval = wglGetSwapIntervalEXT(); } return interval; } // end of swap_interval implementation #if HAVE_GL_OVERLAY #endif int Fl_WinAPI_Gl_Window_Driver::flush_begin(char& valid_f_) { #if HAVE_GL_OVERLAY char save_valid_f = valid_f_; // Draw into hardware overlay planes if they are damaged: if (overlay() && overlay() != pWindow && (pWindow->damage()&(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE) || !save_valid_f & 1)) { set_gl_context(pWindow, (GLContext)overlay()); if (fl_overlay_depth) wglRealizeLayerPalette(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc, 1, TRUE); glDisable(GL_SCISSOR_TEST); glClear(GL_COLOR_BUFFER_BIT); Fl_Xlib_Graphics_Driver::fl_overlay = 1; draw_overlay(); Fl_Xlib_Graphics_Driver::fl_overlay = 0; valid_f_ = save_valid_f; wglSwapLayerBuffers(Fl_WinAPI_Window_Driver::driver(pWindow)->private_dc, WGL_SWAP_OVERLAY1); // if only the overlay was damaged we are done, leave main layer alone: if (pWindow->damage() == FL_DAMAGE_OVERLAY) { return 1; } } #endif return 0; } void* Fl_WinAPI_Gl_Window_Driver::GetProcAddress(const char *procName) { return (void*)wglGetProcAddress((LPCSTR)procName); } void Fl_WinAPI_Gl_Window_Driver::draw_string_legacy(const char* str, int n) { draw_string_legacy_get_list(str, n); } int Fl_WinAPI_Gl_Window_Driver::genlistsize() { return 0x10000; } void Fl_WinAPI_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) { if (!fl_fontsize->listbase) { fl_fontsize->listbase = glGenLists(genlistsize()); } glListBase(fl_fontsize->listbase); } void Fl_WinAPI_Gl_Window_Driver::get_list(Fl_Font_Descriptor *fd, int r) { Fl_GDI_Font_Descriptor* gl_fd = (Fl_GDI_Font_Descriptor*)fd; if (gl_fd->glok[r]) return; gl_fd->glok[r] = 1; unsigned int ii = r * 0x400; HFONT oldFid = (HFONT)SelectObject((HDC)fl_graphics_driver->gc(), gl_fd->fid); wglUseFontBitmapsW((HDC)fl_graphics_driver->gc(), ii, 0x400, gl_fd->listbase+ii); SelectObject((HDC)fl_graphics_driver->gc(), oldFid); } typedef void (WINAPI *glUseProgram_type)(GLint); static glUseProgram_type glUseProgram_f = NULL; void Fl_WinAPI_Gl_Window_Driver::switch_to_GL1() { if (!glUseProgram_f) { glUseProgram_f = (glUseProgram_type)GetProcAddress("glUseProgram"); } glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_prog); if (current_prog) glUseProgram_f(0); } void Fl_WinAPI_Gl_Window_Driver::switch_back() { if (current_prog) glUseProgram_f((GLuint)current_prog); } FL_EXPORT HGLRC fl_win32_glcontext(GLContext rc) { return (HGLRC)rc; } #endif // HAVE_GL fltk-1.4.3/src/drivers/Darwin/0000755000175000017500000000000015004135251016276 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/Darwin/Fl_Darwin_System_Driver.cxx0000644000175000017500000003160515004135251023553 0ustar albrechtalbrecht// // Definition of Apple Darwin system driver. // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Darwin_System_Driver.H" #include "../Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H" #include #include #include #include #include #include #include "../../flstring.h" #include #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 #include #endif #include #include #include #include #include #include #include #include const char *Fl_Darwin_System_Driver::shift_name() { return "⇧\\"; // "\xe2\x87\xa7\\"; // U+21E7 (upwards white arrow) } const char *Fl_Darwin_System_Driver::meta_name() { return "⌘\\"; // "\xe2\x8c\x98\\"; // U+2318 (place of interest sign) } const char *Fl_Darwin_System_Driver::alt_name() { return "⌥\\"; // "\xe2\x8c\xa5\\"; // U+2325 (option key) } const char *Fl_Darwin_System_Driver::control_name() { return "⌃\\"; // "\xe2\x8c\x83\\"; // U+2303 (up arrowhead) } Fl_Darwin_System_Driver::Fl_Darwin_System_Driver() : Fl_Posix_System_Driver() { if (fl_mac_os_version == 0) fl_mac_os_version = calc_mac_os_version(); command_key = FL_META; control_key = FL_CTRL; } int Fl_Darwin_System_Driver::single_arg(const char *arg) { // The Finder application in MacOS X passes the "-psn_N_NNNNN" option to all apps. return (strncmp(arg, "psn_", 4) == 0); } int Fl_Darwin_System_Driver::arg_and_value(const char *name, const char *value) { // Xcode in MacOS X may pass "-NSDocumentRevisionsDebugMode YES" return strcmp(name, "NSDocumentRevisionsDebugMode") == 0; } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 static locale_t postscript_locale = NULL; #endif int Fl_Darwin_System_Driver::clocale_vprintf(FILE *output, const char *format, va_list args) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (fl_mac_os_version >= 100400) { if (!postscript_locale) postscript_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); return vfprintf_l(output, postscript_locale, format, args); } #endif char *saved_locale = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); int retval = vfprintf(output, format, args); setlocale(LC_NUMERIC, saved_locale); return retval; } int Fl_Darwin_System_Driver::clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (fl_mac_os_version >= 100400) { if (!postscript_locale) postscript_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); return vsnprintf_l(output, output_size, postscript_locale, format, args); } #endif char *saved_locale = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); int retval = vsnprintf(output, output_size, format, args); setlocale(LC_NUMERIC, saved_locale); return retval; } int Fl_Darwin_System_Driver::clocale_vsscanf(const char *input, const char *format, va_list args) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (fl_mac_os_version >= 100400) { if (!postscript_locale) postscript_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); return vsscanf_l(input, postscript_locale, format, args); } #endif char *saved_locale = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); int retval = vsscanf(input, format, args); setlocale(LC_NUMERIC, saved_locale); return retval; } /* Returns the address of a Carbon function after dynamically loading the Carbon library if needed. Supports old Mac OS X versions that may use a couple of Carbon calls: GetKeys used by OS X 10.3 or before (in Fl::get_key()) PMSessionPageSetupDialog and PMSessionPrintDialog used by 10.4 or before (in Fl_Printer::begin_job()) */ void *Fl_Darwin_System_Driver::get_carbon_function(const char *function_name) { static void *carbon = ::dlopen("/System/Library/Frameworks/Carbon.framework/Carbon", RTLD_LAZY); return (carbon ? dlsym(carbon, function_name) : NULL); } int Fl_Darwin_System_Driver::filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **), char *errmsg, int errmsg_sz) { int dirlen; char *dirloc; // Assume that locale encoding is no less dense than UTF-8 dirlen = (int)strlen(d); dirloc = (char *)d; # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 int n = scandir(dirloc, list, 0, (int(*)(const struct dirent**,const struct dirent**))sort); # else int n = scandir(dirloc, list, 0, (int(*)(const void*,const void*))sort); # endif if (n==-1) { if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno)); return -1; } // convert every filename to UTF-8, and append a '/' to all // filenames that are directories int i; char *fullname = (char*)malloc(dirlen+FL_PATH_MAX+3); // Add enough extra for two /'s and a nul // Use memcpy for speed since we already know the length of the string... memcpy(fullname, d, dirlen+1); char *name = fullname + dirlen; if (name!=fullname && name[-1]!='/') *name++ = '/'; for (i=0; id_name); newlen = len; dirent *newde = (dirent*)malloc(de->d_name - (char*)de + newlen + 2); // Add space for a / and a nul // Conversion to UTF-8 memcpy(newde, de, de->d_name - (char*)de); strcpy(newde->d_name, de->d_name); // Check if dir (checks done on "old" name as we need to interact with // the underlying OS) if (de->d_name[len-1]!='/' && len<=FL_PATH_MAX) { // Use memcpy for speed since we already know the length of the string... memcpy(name, de->d_name, len+1); if (fl_filename_isdir(fullname)) { char *dst = newde->d_name + newlen; *dst++ = '/'; *dst = 0; } } free(de); (*list)[i] = newde; } free(fullname); return n; } int Fl_Darwin_System_Driver::open_uri(const char *uri, char *msg, int msglen) { char *argv[3]; // Command-line arguments argv[0] = (char*)"open"; argv[1] = (char*)uri; argv[2] = (char*)0; if (msg) snprintf(msg, msglen, "open %s", uri); return run_program("/usr/bin/open", argv, msg, msglen) != 0; } int Fl_Darwin_System_Driver::file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon) { // MacOS X and Darwin use getfsstat() system call... int numfs; // Number of file systems struct statfs *fs; // Buffer for file system info int num_files = 0; // We always have the root filesystem. browser->add("/", icon); // Get the mounted filesystems... numfs = getfsstat(NULL, 0, MNT_NOWAIT); if (numfs > 0) { // We have file systems, get them... fs = new struct statfs[numfs]; getfsstat(fs, sizeof(struct statfs) * numfs, MNT_NOWAIT); // Add filesystems to the list... for (int i = 0; i < numfs; i ++) { // Ignore "/", "/dev", and "/.vol"... if (fs[i].f_mntonname[1] && strcmp(fs[i].f_mntonname, "/dev") && strcmp(fs[i].f_mntonname, "/.vol")) { snprintf(filename, lname, "%s/", fs[i].f_mntonname); browser->add(filename, icon); } num_files ++; } // Free the memory used for the file system info array... delete[] fs; } return num_files; } void Fl_Darwin_System_Driver::newUUID(char *uuidBuffer) { CFUUIDRef theUUID = CFUUIDCreate(NULL); CFUUIDBytes b = CFUUIDGetUUIDBytes(theUUID); snprintf(uuidBuffer, 36+1, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", b.byte0, b.byte1, b.byte2, b.byte3, b.byte4, b.byte5, b.byte6, b.byte7, b.byte8, b.byte9, b.byte10, b.byte11, b.byte12, b.byte13, b.byte14, b.byte15); CFRelease(theUUID); } /* * returns pointer to the filename, or null if name ends with ':' */ const char *Fl_Darwin_System_Driver::filename_name( const char *name ) { const char *p, *q; if (!name) return (0); for ( p = q = name ; *p ; ) { if ( ( p[0] == ':' ) && ( p[1] == ':' ) ) { q = p+2; p++; } else if (p[0] == '/') { q = p + 1; } p++; } return q; } // These function assume a western code page. If you need to support // scripts that are not part of this code page, you might want to // take a look at FLTK2, which uses utf8 for text encoding. // // By keeping these conversion tables in their own module, they will not // be statically linked (by a smart linker) unless actually used. // // On MS-Windows, nothing need to be converted. We simply return the // original pointer. // // Most X11 implementations seem to default to Latin-1 as a code since it // is a superset of ISO 8859-1, the original Western codepage on X11. // // Apple's OS X however renders text in MacRoman for western settings. The // lookup tables below will convert all common character codes and replace // unknown characters with an upside-down question mark. // This table converts Windows-1252/Latin 1 into MacRoman encoding static uchar latin2roman[128] = { 0xdb, 0xc0, 0xe2, 0xc4, 0xe3, 0xc9, 0xa0, 0xe0, 0xf6, 0xe4, 0xc0, 0xdc, 0xce, 0xc0, 0xc0, 0xc0, 0xc0, 0xd4, 0xd5, 0xd2, 0xd3, 0xa5, 0xd0, 0xd1, 0xf7, 0xaa, 0xc0, 0xdd, 0xcf, 0xc0, 0xc0, 0xd9, 0xca, 0xc1, 0xa2, 0xa3, 0xc0, 0xb4, 0xc0, 0xa4, 0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0xc0, 0xa8, 0xf8, 0xa1, 0xb1, 0xc0, 0xc0, 0xab, 0xb5, 0xa6, 0xe1, 0xfc, 0xc0, 0xbc, 0xc8, 0xc0, 0xc0, 0xc0, 0xc0, 0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, 0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec, 0xc0, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0xc0, 0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0xc0, 0xc0, 0xa7, 0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, 0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, 0xc0, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, 0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0xc0, 0xc0, 0xd8 }; // This table converts MacRoman into Windows-1252/Latin 1 static uchar roman2latin[128] = { 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, 0x86, 0xb0, 0xa2, 0xa3, 0xa7, 0x95, 0xb6, 0xdf, 0xae, 0xa9, 0x99, 0xb4, 0xa8, 0xbf, 0xc6, 0xd8, 0xbf, 0xb1, 0xbf, 0xbf, 0xa5, 0xb5, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xaa, 0xba, 0xbf, 0xe6, 0xf8, 0xbf, 0xa1, 0xac, 0xbf, 0x83, 0xbf, 0xbf, 0xab, 0xbb, 0x85, 0xa0, 0xc0, 0xc3, 0xd5, 0x8c, 0x9c, 0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xf7, 0xbf, 0xff, 0x9f, 0xbf, 0x80, 0x8b, 0x9b, 0xbf, 0xbf, 0x87, 0xb7, 0x82, 0x84, 0x89, 0xc2, 0xca, 0xc1, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4, 0xbf, 0xd2, 0xda, 0xdb, 0xd9, 0xbf, 0x88, 0x98, 0xaf, 0xbf, 0xbf, 0xbf, 0xb8, 0xbf, 0xbf, 0xbf }; static char *buf = 0; static int n_buf = 0; const char *Fl_Darwin_System_Driver::latin1_to_local(const char *t, int n) { if (n==-1) n = (int)strlen(t); if (n<=n_buf) { n_buf = (n + 257) & 0x7fffff00; if (buf) free(buf); buf = (char*)malloc(n_buf); } const uchar *src = (const uchar*)t; uchar *dst = (uchar*)buf; for ( ; n>0; n--) { uchar c = *src++; if (c>127) *dst = latin2roman[c-128]; else *dst = c; } //*dst = 0; // this would be wrong! return buf; } const char *Fl_Darwin_System_Driver::local_to_latin1(const char *t, int n) { if (n==-1) n = (int)strlen(t); if (n<=n_buf) { n_buf = (n + 257) & 0x7fffff00; if (buf) free(buf); buf = (char*)malloc(n_buf); } const uchar *src = (const uchar*)t; uchar *dst = (uchar*)buf; for ( ; n>0; n--) { uchar c = *src++; if (c>127) *dst++ = roman2latin[c-128]; else *dst++ = c; } //*dst = 0; // this would be wrong return buf; } // On Mac OS X, nothing need to be converted. We simply return the // original pointer. const char *Fl_Darwin_System_Driver::mac_roman_to_local(const char *t, int) { return t; } // On Mac OS X, nothing need to be converted. We simply return the // original pointer. const char *Fl_Darwin_System_Driver::local_to_mac_roman(const char *t, int) { return t; } Fl_Sys_Menu_Bar_Driver *Fl_Darwin_System_Driver::sys_menu_bar_driver() { return Fl_MacOS_Sys_Menu_Bar_Driver::driver(); } // Draw Mac-specific Fl_Tree open/close icons void Fl_Darwin_System_Driver::tree_draw_expando_button(int x, int y, bool state, bool active) { fl_color(active ? FL_FOREGROUND_COLOR : FL_INACTIVE_COLOR); if(state) fl_polygon(x + 3, y, x + 3, y + 11, x + 8, y + 5); // right arrow: ▶ else fl_polygon(x, y + 3, x + 11, y + 3, x + 5, y + 8); // down arrow: ▼ } int Fl_Darwin_System_Driver::tree_connector_style() { return FL_TREE_CONNECTOR_NONE; } fltk-1.4.3/src/drivers/Darwin/fl_macOS_platform_init.cxx0000644000175000017500000000275615004135251023446 0ustar albrechtalbrecht// // macOS-specific code to initialize macOS support. // // Copyright 2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "../Quartz/Fl_Quartz_Copy_Surface_Driver.H" #include "../Quartz/Fl_Quartz_Graphics_Driver.H" #include "../Cocoa/Fl_Cocoa_Screen_Driver.H" #include "../Darwin/Fl_Darwin_System_Driver.H" #include "../Cocoa/Fl_Cocoa_Window_Driver.H" #include "../Quartz/Fl_Quartz_Image_Surface_Driver.H" Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int h) { return new Fl_Quartz_Copy_Surface_Driver(w, h); } Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() { return new Fl_Quartz_Graphics_Driver(); } Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() { return new Fl_Cocoa_Screen_Driver(); } Fl_System_Driver *Fl_System_Driver::newSystemDriver() { return new Fl_Darwin_System_Driver(); } Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w) { return new Fl_Cocoa_Window_Driver(w); } Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off) { return new Fl_Quartz_Image_Surface_Driver(w, h, high_res, off); } fltk-1.4.3/src/drivers/Darwin/Fl_Darwin_System_Driver.H0000644000175000017500000000647315004135251023145 0ustar albrechtalbrecht// // Definition of Apple Darwin system driver // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Darwin_System_Driver.H \brief Definition of Apple Darwin system driver. */ #ifndef FL_DARWIN_SYSTEM_DRIVER_H #define FL_DARWIN_SYSTEM_DRIVER_H #include "../Posix/Fl_Posix_System_Driver.H" #include #include /* Move everything here that manages the system interface. There is exactly one system driver. - filename and pathname management - directory and file access - system time and system timer - multithreading */ class Fl_Darwin_System_Driver : public Fl_Posix_System_Driver { public: Fl_Darwin_System_Driver(); int single_arg(const char *arg) FL_OVERRIDE; int arg_and_value(const char *name, const char *value) FL_OVERRIDE; int clocale_vprintf(FILE *output, const char *format, va_list args) FL_OVERRIDE; int clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) FL_OVERRIDE; int clocale_vsscanf(const char *input, const char *format, va_list args) FL_OVERRIDE; static void *get_carbon_function(const char *name); static int calc_mac_os_version(); // computes the fl_mac_os_version global variable static unsigned short *compute_macKeyLookUp(); int filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **), char *errmsg=NULL, int errmsg_sz=0) FL_OVERRIDE; int open_uri(const char *uri, char *msg, int msglen) FL_OVERRIDE; int need_test_shortcut_extra() FL_OVERRIDE {return 1;} int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon) FL_OVERRIDE; void newUUID(char *uuidBuffer) FL_OVERRIDE; char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor, const char *application) FL_OVERRIDE; const char *local_to_latin1(const char *t, int n) FL_OVERRIDE; const char *latin1_to_local(const char *t, int n) FL_OVERRIDE; const char *local_to_mac_roman(const char *t, int n) FL_OVERRIDE; const char *mac_roman_to_local(const char *t, int n) FL_OVERRIDE; void tree_draw_expando_button(int x, int y, bool state, bool active) FL_OVERRIDE; int tree_connector_style() FL_OVERRIDE; const char *filename_name(const char *buf) FL_OVERRIDE; void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE; void add_fd(int fd, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE; void remove_fd(int, int when) FL_OVERRIDE; void remove_fd(int) FL_OVERRIDE; void open_callback(void (*)(const char *)) FL_OVERRIDE; const char *shift_name() FL_OVERRIDE; const char *meta_name() FL_OVERRIDE; const char *alt_name() FL_OVERRIDE; const char *control_name() FL_OVERRIDE; Fl_Sys_Menu_Bar_Driver *sys_menu_bar_driver() FL_OVERRIDE; double wait(double time_to_wait) FL_OVERRIDE; int ready() FL_OVERRIDE; }; #endif // FL_DARWIN_SYSTEM_DRIVER_H fltk-1.4.3/src/drivers/Posix/0000755000175000017500000000000015004135251016154 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx0000644000175000017500000003665715004135251023462 0ustar albrechtalbrecht// // PostScript priting support for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if !defined(FL_NO_PRINT_SUPPORT) #include #include "../PostScript/Fl_PostScript_Graphics_Driver.H" #include #include #include /** Support for printing on the Unix/Linux platform */ class Fl_Posix_Printer_Driver : public Fl_PostScript_File_Device { int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message=NULL) FL_OVERRIDE; }; #if HAVE_DLSYM && HAVE_DLFCN_H // GTK types #include // for dlopen et al #include // for mkstemp #include #include "Fl_Posix_System_Driver.H" #define GTK_PAPER_NAME_LETTER "na_letter" #define GTK_PAPER_NAME_LEGAL "na_legal" #define GTK_PAPER_NAME_A3 "iso_a3" #define GTK_PAPER_NAME_A5 "iso_a5" #define GTK_PAPER_NAME_JB5 "jis_b5" #define GTK_PAPER_NAME_TABLOID "na_ledger" #define GTK_PAPER_NAME_DLE "iso_dl" #define GTK_RESPONSE_NONE -1 #define GTK_RESPONSE_REJECT -2 #define GTK_RESPONSE_OK -5 #define GTK_RESPONSE_CANCEL -6 #define GTK_RESPONSE_DELETE_EVENT -4 #define GTK_PRINT_PAGES_RANGES 2 class Fl_GTK_Printer_Driver : public Fl_PostScript_File_Device { public: typedef int gboolean; typedef struct _GtkPrintUnixDialog GtkPrintUnixDialog; typedef struct _GtkDialog GtkDialog; typedef struct _GtkPrintSettings GtkPrintSettings; typedef struct _GtkPageSetup GtkPageSetup; enum GtkPageOrientation {GTK_PAGE_ORIENTATION_PORTRAIT, GTK_PAGE_ORIENTATION_LANDSCAPE}; typedef struct _GtkPaperSize GtkPaperSize; typedef struct _GtkPrinter GtkPrinter; typedef struct _GtkPrintJob GtkPrintJob; typedef struct _GtkWidget GtkWidget; struct GError; GtkPrintJob *pjob; // data shared between begin_job() and end_job() char tmpfilename[50]; // name of temporary PostScript file containing to-be-printed data int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message=NULL) FL_OVERRIDE; void end_job() FL_OVERRIDE; static bool probe_for_GTK(); static void *ptr_gtk; // points to the GTK dynamic lib or NULL typedef GtkPrintUnixDialog* (*gtk_print_unix_dialog_new_t)(const char*, void*); typedef int (*gtk_dialog_run_t)(GtkDialog*); typedef GtkPrintSettings *(*gtk_print_unix_dialog_get_settings_t)(GtkPrintUnixDialog*); typedef void (*gtk_print_unix_dialog_set_settings_t)(GtkPrintUnixDialog*, GtkPrintSettings*); typedef GtkPageSetup *(*gtk_print_unix_dialog_get_page_setup_t)(GtkPrintUnixDialog*); typedef GtkPageOrientation (*gtk_page_setup_get_orientation_t)(GtkPageSetup*); typedef GtkPaperSize* (*gtk_page_setup_get_paper_size_t)(GtkPageSetup*); typedef const char * (*gtk_paper_size_get_name_t)(GtkPaperSize*); typedef GtkPrinter * (*gtk_print_unix_dialog_get_selected_printer_t)(GtkPrintUnixDialog*); typedef int (*gtk_printer_accepts_ps_t)(GtkPrinter*); typedef int (*gtk_printer_is_active_t)(GtkPrinter*); typedef GtkPrintJob *(*gtk_print_job_new_t)(const char *, GtkPrinter *, GtkPrintSettings *, GtkPageSetup *); typedef void (*gtk_widget_hide_t)(GtkWidget*); typedef void (*gtk_widget_destroy_t)(GtkWidget*); typedef gboolean (*gtk_events_pending_t)(void); typedef void (*gtk_main_iteration_t)(void); typedef int (*gtk_print_job_set_source_file_t)(GtkPrintJob *job, const char *filename, GError **error); typedef void (*gtk_print_job_send_t)(GtkPrintJob *, void* , gboolean* , void* ); typedef void (*gtk_print_settings_set_t) (GtkPrintSettings *settings, const char *key, const char *value); typedef const char * (*gtk_print_settings_get_t) (GtkPrintSettings *settings, const char *key ); typedef int (*gtk_print_settings_get_print_pages_t)(GtkPrintSettings*); struct GtkPageRange { int start, end; }; typedef GtkPageRange* (*gtk_print_settings_get_page_ranges_t)(GtkPrintSettings*, int*); typedef void (*g_object_unref_t)(void* object); typedef struct _GClosure GClosure; typedef void (*GClosureNotify)(void* data, GClosure *closure); typedef void (*GCallback)(void); typedef void (*g_signal_connect_data_t)(void *,const char *, GCallback, void*, GClosureNotify, int); typedef void (*gtk_print_unix_dialog_set_embed_page_setup_t)(GtkPrintUnixDialog *dialog, gboolean embed); typedef void (*gtk_widget_show_now_t)(GtkPrintUnixDialog *dialog); typedef const char * (*gtk_check_version_t)(unsigned, unsigned, unsigned); }; // the CALL_GTK macro produces the source code to call a GTK function given its name // or to get a pointer to this function : // CALL_GTK(gtk_my_function) produces ((gtk_my_function_t)dlsym(ptr_gtk, "gtk_my_function")) #define CALL_GTK(NAME) ((NAME##_t)dlsym(ptr_gtk, #NAME)) void *Fl_GTK_Printer_Driver::ptr_gtk = NULL; // test wether GTK is available at run-time bool Fl_GTK_Printer_Driver::probe_for_GTK() { return Fl_Posix_System_Driver::probe_for_GTK(2, 10, &ptr_gtk); } static void run_response_handler(void *dialog, int response_id, void* data) { int *ri = (int *)data; *ri = response_id; } static int no_dispatch(int /*event*/, Fl_Window* /*win*/) { return 0; } int Fl_GTK_Printer_Driver::begin_job(int pagecount, int *firstpage, int *lastpage, char **perr_message) { enum Fl_Paged_Device::Page_Format format = Fl_Paged_Device::A4; enum Fl_Paged_Device::Page_Layout layout = Fl_Paged_Device::PORTRAIT ; GtkPrintUnixDialog *pdialog = CALL_GTK(gtk_print_unix_dialog_new)(Fl_Printer::dialog_title, NULL); //2.10 if (dlsym(ptr_gtk, "gtk_get_major_version") || !CALL_GTK(gtk_check_version)(2, 18, 0)) CALL_GTK(gtk_print_unix_dialog_set_embed_page_setup)(pdialog, true); //2.18 GtkPrintSettings *psettings = CALL_GTK(gtk_print_unix_dialog_get_settings)(pdialog); //2.10 CALL_GTK(gtk_print_settings_set)(psettings, "output-file-format", "ps"); //2.10 char line[FL_PATH_MAX + 20], cwd[FL_PATH_MAX]; snprintf(line, FL_PATH_MAX + 20, "file://%s/FLTK.ps", fl_getcwd(cwd, FL_PATH_MAX)); CALL_GTK(gtk_print_settings_set)(psettings, "output-uri", line); //2.10 CALL_GTK(gtk_print_unix_dialog_set_settings)(pdialog, psettings); //2.10 CALL_GTK(g_object_unref)(psettings); int response_id = GTK_RESPONSE_NONE; CALL_GTK(g_signal_connect_data)(pdialog, "response", GCallback(run_response_handler), &response_id, NULL, 0); gtk_events_pending_t fl_gtk_events_pending = CALL_GTK(gtk_events_pending); gtk_main_iteration_t fl_gtk_main_iteration = CALL_GTK(gtk_main_iteration); CALL_GTK(gtk_widget_show_now)(pdialog); // map the GTK window on screen Fl_Event_Dispatch old_dispatch = Fl::event_dispatch(); // prevent FLTK from processing any event Fl::event_dispatch(no_dispatch); while (response_id == GTK_RESPONSE_NONE) { // loop that shows the GTK dialog window fl_gtk_main_iteration(); // one iteration of the GTK event loop while (Fl::ready()) Fl::check(); // queued iterations of the FLTK event loop } if (response_id == GTK_RESPONSE_OK) { GtkPageSetup *psetup = CALL_GTK(gtk_print_unix_dialog_get_page_setup)(pdialog); //2.10 GtkPageOrientation orient = CALL_GTK(gtk_page_setup_get_orientation)(psetup); //2.10 if (orient == GTK_PAGE_ORIENTATION_LANDSCAPE) layout = Fl_Paged_Device::LANDSCAPE; GtkPaperSize* psize = CALL_GTK(gtk_page_setup_get_paper_size)(psetup); //2.10 const char *pname = CALL_GTK(gtk_paper_size_get_name)(psize); //2.10 if (strcmp(pname, GTK_PAPER_NAME_LETTER) == 0) format = Fl_Paged_Device::LETTER; else if (strcmp(pname, GTK_PAPER_NAME_LEGAL) == 0) format = Fl_Paged_Device::LEGAL; else if (strcmp(pname, GTK_PAPER_NAME_A3) == 0) format = Fl_Paged_Device::A3; else if (strcmp(pname, GTK_PAPER_NAME_A5) == 0) format = Fl_Paged_Device::A5; else if (strcmp(pname, GTK_PAPER_NAME_JB5) == 0) format = Fl_Paged_Device::B5; else if (strcmp(pname, GTK_PAPER_NAME_TABLOID) == 0) format = Fl_Paged_Device::TABLOID; else if (strcmp(pname, GTK_PAPER_NAME_DLE) == 0) format = Fl_Paged_Device::DLE; GtkPrinter *gprinter = CALL_GTK(gtk_print_unix_dialog_get_selected_printer)(pdialog); //2.10 psettings = CALL_GTK(gtk_print_unix_dialog_get_settings)(pdialog); //2.10 const char* p = CALL_GTK(gtk_print_settings_get)(psettings, "output-uri"); //2.10 bool printing_to_file = (p != NULL); if (printing_to_file) { p += 6; // skip "file://" prefix strcpy(line, p); int l = strlen(p); if (strcmp(p+l-4, "/.ps") == 0) { line[l-3] = 0; strcat(line, "FLTK.ps"); } } if (firstpage && lastpage) { *firstpage = 1; *lastpage = pagecount; if (CALL_GTK(gtk_print_settings_get_print_pages)(psettings) == GTK_PRINT_PAGES_RANGES) { // 2.10 int num_ranges; GtkPageRange *ranges = CALL_GTK(gtk_print_settings_get_page_ranges)(psettings, &num_ranges); //2.10 if (num_ranges > 0) { *firstpage = ranges[0].start + 1; *lastpage = ranges[0].end + 1; free(ranges); } } } response_id = GTK_RESPONSE_NONE; if (printing_to_file) { pjob = NULL; FILE *output = fopen(line, "w"); if (output) { Fl_PostScript_File_Device::begin_job(output, 0, format, layout); response_id = GTK_RESPONSE_OK; } else { response_id = GTK_RESPONSE_REJECT; if (perr_message) { *perr_message = new char[strlen(line)+50]; snprintf(*perr_message, strlen(line)+50, "Can't open output file %s", line); } } } else if ( CALL_GTK(gtk_printer_accepts_ps)(gprinter) && //2.10 CALL_GTK(gtk_printer_is_active)(gprinter) ) { // 2.10 strcpy(tmpfilename, "/tmp/FLTKprintjobXXXXXX"); int fd = mkstemp(tmpfilename); if (fd >= 0) { FILE *output = fdopen(fd, "w"); Fl_PostScript_File_Device::begin_job(output, 0, format, layout); pjob = CALL_GTK(gtk_print_job_new)("FLTK print job", gprinter, psettings, psetup); //2.10 response_id = GTK_RESPONSE_OK; } else { response_id = GTK_RESPONSE_REJECT; if (perr_message) { *perr_message = new char[strlen(tmpfilename)+50]; snprintf(*perr_message, strlen(tmpfilename)+50, "Can't create temporary file %s", tmpfilename); } } } CALL_GTK(g_object_unref)(psettings); } CALL_GTK(gtk_widget_hide)((GtkWidget*)pdialog); while (fl_gtk_events_pending()) fl_gtk_main_iteration(); CALL_GTK(gtk_widget_destroy)((GtkWidget*)pdialog); Fl::event_dispatch(old_dispatch); Fl_Window *first = Fl::first_window(); if (first) { Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); first->show(); while (Fl::ready()) Fl::check(); Fl_Surface_Device::pop_current(); } if (response_id == GTK_RESPONSE_OK) return 0; if (response_id == GTK_RESPONSE_CANCEL || response_id == GTK_RESPONSE_DELETE_EVENT) return 1; return 2; } static void pJobCompleteFunc(Fl_GTK_Printer_Driver::GtkPrintJob *print_job, Fl_GTK_Printer_Driver::gboolean *user_data, const Fl_GTK_Printer_Driver::GError *error) { *user_data = true; } static void pDestroyNotify(void* data) {} void Fl_GTK_Printer_Driver::end_job() { Fl_PostScript_File_Device::end_job(); Fl_PostScript_Graphics_Driver *psgd = driver(); fclose(psgd->output); if (!pjob) return; GError *gerr; gboolean gb = CALL_GTK(gtk_print_job_set_source_file)(pjob, tmpfilename, &gerr); //2.10 if (gb) { gb = false; CALL_GTK(gtk_print_job_send)(pjob, (void*)pJobCompleteFunc, &gb, (void*)pDestroyNotify); //2.10 gtk_main_iteration_t fl_gtk_main_iteration = CALL_GTK(gtk_main_iteration); while (!gb) { fl_gtk_main_iteration(); } } fl_unlink(tmpfilename); } #endif // HAVE_DLSYM && HAVE_DLFCN_H Fl_Paged_Device* Fl_Printer::newPrinterDriver(void) { #if HAVE_DLSYM && HAVE_DLFCN_H static bool gtk = ( Fl::option(Fl::OPTION_PRINTER_USES_GTK) ? Fl_GTK_Printer_Driver::probe_for_GTK() : false); if (gtk) return new Fl_GTK_Printer_Driver(); #endif return new Fl_Posix_Printer_Driver(); } /* Begins a print job. */ int Fl_Posix_Printer_Driver::begin_job(int pages, int *firstpage, int *lastpage, char **perr_message) { enum Fl_Paged_Device::Page_Format format; enum Fl_Paged_Device::Page_Layout layout; // first test version for print dialog if (!print_panel) make_print_panel(); printing_style style = print_load(); print_selection->deactivate(); print_all->setonly(); print_all->do_callback(); print_from->value("1"); { char tmp[10]; snprintf(tmp, sizeof(tmp), "%d", pages); print_to->value(tmp); } print_panel->show(); // this is modal while (print_panel->shown()) Fl::wait(); if (!print_start) // user clicked cancel return 1; // get options switch (print_page_size->value()) { case 0: format = Fl_Paged_Device::LETTER; break; case 2: format = Fl_Paged_Device::LEGAL; break; case 3: format = Fl_Paged_Device::EXECUTIVE; break; case 4: format = Fl_Paged_Device::A3; break; case 5: format = Fl_Paged_Device::A5; break; case 6: format = Fl_Paged_Device::B5; break; case 7: format = Fl_Paged_Device::ENVELOPE; break; case 8: format = Fl_Paged_Device::DLE; break; case 9: format = Fl_Paged_Device::TABLOID; break; default: format = Fl_Paged_Device::A4; } { // page range choice int from = 1, to = pages; if (print_pages->value()) { sscanf(print_from->value(), "%d", &from); sscanf(print_to->value(), "%d", &to); } if (from < 1) from = 1; if (to > pages) to = pages; if (to < from) to = from; if (firstpage) *firstpage = from; if (lastpage) *lastpage = to; if (pages > 0) pages = to - from + 1; } if (print_output_mode[0]->value()) layout = Fl_Paged_Device::PORTRAIT; else if (print_output_mode[1]->value()) layout = Fl_Paged_Device::LANDSCAPE; else if (print_output_mode[2]->value()) layout = Fl_Paged_Device::PORTRAIT; else layout = Fl_Paged_Device::LANDSCAPE; int print_pipe = print_choice->value(); // 0 = print to file, >0 = printer (pipe) const char *media = print_page_size->text(print_page_size->value()); const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); if (!print_pipe) printer = ""; if (!print_pipe) // fall back to file printing return Fl_PostScript_File_Device::begin_job (pages, format, layout); // Print: pipe the output into the lp command... char command[1024]; if (style == SystemV) snprintf(command, sizeof(command), "lp -s -d %s -n %d -t '%s' -o media=%s", printer, print_collate_button->value() ? 1 : (int)(print_copies->value() + 0.5), "FLTK", media); else snprintf(command, sizeof(command), "lpr -h -P%s -#%d -T FLTK ", printer, print_collate_button->value() ? 1 : (int)(print_copies->value() + 0.5)); Fl_PostScript_Graphics_Driver *ps = driver(); ps->output = popen(command, "w"); if (!ps->output) { if (perr_message) { *perr_message = new char[strlen(command) + 50]; snprintf(*perr_message, strlen(command) + 50, "could not run command: %s", command); } return 2; } ps->close_command(pclose); return ps->start_postscript(pages, format, layout); // start printing } #endif // !defined(FL_NO_PRINT_SUPPORT) fltk-1.4.3/src/drivers/Posix/Fl_Posix_System_Driver.H0000644000175000017500000000623315004135251022673 0ustar albrechtalbrecht// // Definition of POSIX system driver // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Posix_System_Driver.H \brief Definition of Posix system driver. */ #ifndef FL_POSIX_SYSTEM_DRIVER_H #define FL_POSIX_SYSTEM_DRIVER_H #include #include "../../Fl_System_Driver.H" #include #include #include #include /* Move everything here that manages the system interface. There is exactly one system driver. - filename and pathname management - directory and file access - system time and system timer - multithreading - string management */ class Fl_Posix_System_Driver : public Fl_System_Driver { protected: int run_program(const char *program, char **argv, char *msg, int msglen); public: int mkdir(const char* f, int mode) FL_OVERRIDE {return ::mkdir(f, mode);} int open(const char* f, int oflags, int pmode) FL_OVERRIDE { return pmode == -1 ? ::open(f, oflags) : ::open(f, oflags, pmode); } char *getenv(const char *v) FL_OVERRIDE { return ::getenv(v); } int putenv(const char *var) FL_OVERRIDE {return ::putenv(strdup(var));} int system(const char* cmd) FL_OVERRIDE {return ::system(cmd);} int execvp(const char *file, char *const *argv) FL_OVERRIDE {return ::execvp(file, argv);} int chmod(const char* f, int mode) FL_OVERRIDE {return ::chmod(f, mode);} int access(const char* f, int mode) FL_OVERRIDE { return ::access(f, mode);} int flstat(const char* f, struct stat *b) FL_OVERRIDE { return ::stat(f, b);} char *getcwd(char* b, int l) FL_OVERRIDE {return ::getcwd(b, l);} int chdir(const char* path) FL_OVERRIDE {return ::chdir(path);} int unlink(const char* f) FL_OVERRIDE {return ::unlink(f);} int rmdir(const char* f) FL_OVERRIDE {return ::rmdir(f);} int rename(const char* f, const char *n) FL_OVERRIDE {return ::rename(f, n);} const char *getpwnam(const char *login) FL_OVERRIDE; #if HAVE_DLFCN_H void *load(const char *filename) FL_OVERRIDE; #if HAVE_DLSYM static void *ptr_gtk; static bool probe_for_GTK(int major, int minor, void **ptr_gtk); #endif #endif static void *dlopen_or_dlsym(const char *lib_name, const char *func_name = NULL); // these 4 are implemented in Fl_lock.cxx void awake(void*) FL_OVERRIDE; int lock() FL_OVERRIDE; void unlock() FL_OVERRIDE; void* thread_message() FL_OVERRIDE; int file_type(const char *filename) FL_OVERRIDE; const char *home_directory_name() FL_OVERRIDE { return ::getenv("HOME"); } int dot_file_hidden() FL_OVERRIDE {return 1;} void gettime(time_t *sec, int *usec) FL_OVERRIDE; char* strdup(const char *s) FL_OVERRIDE {return ::strdup(s);} int close_fd(int fd) FL_OVERRIDE; #if defined(HAVE_PTHREAD) void lock_ring() FL_OVERRIDE; void unlock_ring() FL_OVERRIDE; #endif }; #endif // FL_POSIX_SYSTEM_DRIVER_H fltk-1.4.3/src/drivers/Posix/Fl_Posix_System_Driver.cxx0000644000175000017500000003252015004135251023304 0ustar albrechtalbrecht// // Definition of Posix system driver (used by the X11, Wayland and macOS platforms). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Posix_System_Driver.H" #include "../../flstring.h" #include #include #include #include #include #include #if HAVE_DLFCN_H # include #endif #include #include #include #include #include #include #include #include #include #include #include // // Define missing POSIX/XPG4 macros as needed... // #ifndef S_ISDIR # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #endif /* !S_ISDIR */ #if HAVE_DLFCN_H void *Fl_Posix_System_Driver::load(const char *filename) { return ::dlopen(filename, RTLD_LAZY); } #endif int Fl_Posix_System_Driver::file_type(const char *filename) { int filetype; struct stat fileinfo; // Information on file if (!::stat(filename, &fileinfo)) { if (S_ISDIR(fileinfo.st_mode)) filetype = Fl_File_Icon::DIRECTORY; # ifdef S_ISFIFO else if (S_ISFIFO(fileinfo.st_mode)) filetype = Fl_File_Icon::FIFO; # endif // S_ISFIFO # if defined(S_ISCHR) && defined(S_ISBLK) else if (S_ISCHR(fileinfo.st_mode) || S_ISBLK(fileinfo.st_mode)) filetype = Fl_File_Icon::DEVICE; # endif // S_ISCHR && S_ISBLK # ifdef S_ISLNK else if (S_ISLNK(fileinfo.st_mode)) filetype = Fl_File_Icon::LINK; # endif // S_ISLNK else filetype = Fl_File_Icon::PLAIN; } else filetype = Fl_File_Icon::PLAIN; return filetype; } const char *Fl_Posix_System_Driver::getpwnam(const char *login) { struct passwd *pwd; pwd = ::getpwnam(login); return pwd ? pwd->pw_dir : NULL; } void Fl_Posix_System_Driver::gettime(time_t *sec, int *usec) { struct timeval tv; gettimeofday(&tv, NULL); *sec = tv.tv_sec; *usec = tv.tv_usec; } // Run the specified program, returning 1 on success and 0 on failure int Fl_Posix_System_Driver::run_program(const char *program, char **argv, char *msg, int msglen) { pid_t pid; // Process ID of first child int status; // Exit status from first child sigset_t set, oldset; // Signal masks // Block SIGCHLD while we run the program... // // Note that I only use the POSIX signal APIs, however older operating // systems may either not support POSIX signals or have side effects. // IRIX, for example, provides three separate and incompatible signal // APIs, so it is possible that an application setting a signal handler // via signal() or sigset() will not have its SIGCHLD signals blocked... sigemptyset(&set); sigaddset(&set, SIGCHLD); sigprocmask(SIG_BLOCK, &set, &oldset); // Create child processes that actually run the program for us... if ((pid = fork()) == 0) { // First child comes here, fork a second child and exit... if (!fork()) { // Second child comes here, redirect stdin/out/err to /dev/null... close(0); ::open("/dev/null", O_RDONLY); close(1); ::open("/dev/null", O_WRONLY); close(2); ::open("/dev/null", O_WRONLY); // Detach from the current process group... setsid(); // Run the program... execv(program, argv); _exit(0); } else { // First child gets here, exit immediately... _exit(0); } } else if (pid < 0) { // Restore signal handling... sigprocmask(SIG_SETMASK, &oldset, NULL); // Return indicating failure... return 0; } // Wait for the first child to exit... while (waitpid(pid, &status, 0) < 0) { if (errno != EINTR) { // Someone else grabbed the child status... if (msg) snprintf(msg, msglen, "waitpid(%ld) failed: %s", (long)pid, strerror(errno)); // Restore signal handling... sigprocmask(SIG_SETMASK, &oldset, NULL); // Return indicating failure... return 0; } } // Restore signal handling... sigprocmask(SIG_SETMASK, &oldset, NULL); // Return indicating success... return 1; } #if HAVE_DLSYM && HAVE_DLFCN_H && !defined (__APPLE_CC__) static void* quadruple_dlopen(const char *libname) { char filename2[FL_PATH_MAX]; snprintf(filename2, FL_PATH_MAX, "%s.so", libname); void *ptr = dlopen(filename2, RTLD_LAZY | RTLD_GLOBAL); if (!ptr) { snprintf(filename2, FL_PATH_MAX, "%s.so.2", libname); ptr = dlopen(filename2, RTLD_LAZY | RTLD_GLOBAL); if (!ptr) { snprintf(filename2, FL_PATH_MAX, "%s.so.1", libname); ptr = dlopen(filename2, RTLD_LAZY | RTLD_GLOBAL); if (!ptr) { snprintf(filename2, FL_PATH_MAX, "%s.so.0", libname); ptr = dlopen(filename2, RTLD_LAZY | RTLD_GLOBAL); } } } return ptr; } #endif // HAVE_DLSYM && HAVE_DLFCN_H && !defined (__APPLE_CC__) /** Returns the run-time address of a function or of a shared library. \param lib_name shared library name (without its extension) or NULL to search the function in the running program \param func_name function name or NULL \return the address of the function (when func_name != NULL) or of the shared library, or NULL if not found. */ void *Fl_Posix_System_Driver::dlopen_or_dlsym(const char *lib_name, const char *func_name) { void *lib_address = NULL; #if HAVE_DLSYM && HAVE_DLFCN_H void *func_ptr = NULL; if (func_name) { #ifdef RTLD_DEFAULT func_ptr = dlsym(RTLD_DEFAULT, func_name); #else void *p = dlopen(NULL, RTLD_LAZY); func_ptr = dlsym(p, func_name); #endif if (func_ptr) return func_ptr; } #ifdef __APPLE_CC__ // allows using on Darwin + XQuartz + (homebrew or fink) if (lib_name) { char path[FL_PATH_MAX]; snprintf(path, FL_PATH_MAX, "/opt/X11/lib/%s.dylib", lib_name); lib_address = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); if (!lib_address) { snprintf(path, FL_PATH_MAX, "/opt/homebrew/lib/%s.dylib", lib_name); lib_address = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); if (!lib_address) { snprintf(path, FL_PATH_MAX, "/opt/sw/lib/%s.dylib", lib_name); lib_address = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); if (!lib_address) { snprintf(path, FL_PATH_MAX, "/sw/lib/%s.dylib", lib_name); lib_address = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); // the GTK2 shared lib has a new name under homebrew in macOS, try it: if (!lib_address && !strcmp(lib_name, "libgtk-x11-2.0")) { lib_address = dlopen("/opt/homebrew/lib/libgtkmacintegration-gtk2.dylib", RTLD_LAZY | RTLD_GLOBAL); } } } } } #else if (lib_name) lib_address = quadruple_dlopen(lib_name); #endif // __APPLE_CC__ if (func_name && lib_address) return ::dlsym(lib_address, func_name); #endif // HAVE_DLFCN_H return lib_address; } #if HAVE_DLSYM && HAVE_DLFCN_H void *Fl_Posix_System_Driver::ptr_gtk = NULL; bool Fl_Posix_System_Driver::probe_for_GTK(int major, int minor, void **p_ptr_gtk) { typedef int (*init_t)(int*, char***); init_t init_f = NULL; // was GTK previously loaded? if (Fl_Posix_System_Driver::ptr_gtk) { // yes, it was. *p_ptr_gtk = Fl_Posix_System_Driver::ptr_gtk; return true; } // Try first with GTK3 Fl_Posix_System_Driver::ptr_gtk = Fl_Posix_System_Driver::dlopen_or_dlsym("libgtk-3"); if (Fl_Posix_System_Driver::ptr_gtk) { #ifdef DEBUG puts("selected GTK-3\n"); #endif } else { // Try then with GTK2 Fl_Posix_System_Driver::ptr_gtk = Fl_Posix_System_Driver::dlopen_or_dlsym("libgtk-x11-2.0"); #ifdef DEBUG if (Fl_Posix_System_Driver::ptr_gtk) { puts("selected GTK-2\n"); } #endif } if (!Fl_Posix_System_Driver::ptr_gtk) { #ifdef DEBUG puts("Failure to load libgtk"); #endif return false; } init_f = (init_t)dlsym(Fl_Posix_System_Driver::ptr_gtk, "gtk_init_check"); if (!init_f) return false; *p_ptr_gtk = Fl_Posix_System_Driver::ptr_gtk; // The point here is that after running gtk_init_check, the calling program's current locale can be modified. // To avoid that, we memorize the calling program's current locale and restore the locale // before returning. char *before = NULL; // record in "before" the calling program's current locale char *p = setlocale(LC_ALL, NULL); if (p) before = fl_strdup(p); int ac = 0; if ( !init_f(&ac, NULL) ) { // may change the locale free(before); return false; } if (before) { setlocale(LC_ALL, before); // restore calling program's current locale free(before); } // now check if running version is high enough if (dlsym(Fl_Posix_System_Driver::ptr_gtk, "gtk_get_major_version") == NULL) { // YES indicates V 3 typedef const char* (*check_t)(int, int, int); check_t check_f = (check_t)dlsym(Fl_Posix_System_Driver::ptr_gtk, "gtk_check_version"); if (!check_f || check_f(major, minor, 0) ) return false; } return true; } #endif // HAVE_DLSYM && HAVE_DLFCN_H int Fl_Posix_System_Driver::close_fd(int fd) { return close(fd); } //////////////////////////////////////////////////////////////// // POSIX threading... #if defined(HAVE_PTHREAD) # include # include # include // Pipe for thread messaging via Fl::awake()... static int thread_filedes[2]; // Mutex and state information for Fl::lock() and Fl::unlock()... static pthread_mutex_t fltk_mutex; static pthread_t owner; static int counter; static void lock_function_init_std() { pthread_mutex_init(&fltk_mutex, NULL); } static void lock_function_std() { if (!counter || owner != pthread_self()) { pthread_mutex_lock(&fltk_mutex); owner = pthread_self(); } counter++; } static void unlock_function_std() { if (!--counter) pthread_mutex_unlock(&fltk_mutex); } # ifdef HAVE_PTHREAD_MUTEX_RECURSIVE static bool lock_function_init_rec() { pthread_mutexattr_t attrib; pthread_mutexattr_init(&attrib); if (pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE)) { pthread_mutexattr_destroy(&attrib); return true; } pthread_mutex_init(&fltk_mutex, &attrib); return false; } static void lock_function_rec() { pthread_mutex_lock(&fltk_mutex); } static void unlock_function_rec() { pthread_mutex_unlock(&fltk_mutex); } # endif // HAVE_PTHREAD_MUTEX_RECURSIVE void Fl_Posix_System_Driver::awake(void* msg) { if (thread_filedes[1]) { if (write(thread_filedes[1], &msg, sizeof(void*))==0) { /* ignore */ } } } static void* thread_message_; void* Fl_Posix_System_Driver::thread_message() { void* r = thread_message_; thread_message_ = 0; return r; } static void thread_awake_cb(int fd, void*) { if (read(fd, &thread_message_, sizeof(void*))==0) { /* This should never happen */ } Fl_Awake_Handler func; void *data; while (Fl::get_awake_handler_(func, data)==0) { (*func)(data); } } // These pointers are in Fl_x.cxx: extern void (*fl_lock_function)(); extern void (*fl_unlock_function)(); int Fl_Posix_System_Driver::lock() { if (!thread_filedes[1]) { // Initialize thread communication pipe to let threads awake FLTK // from Fl::wait() if (pipe(thread_filedes)==-1) { /* this should not happen */ } // Make the write side of the pipe non-blocking to avoid deadlock // conditions (STR #1537) fcntl(thread_filedes[1], F_SETFL, fcntl(thread_filedes[1], F_GETFL) | O_NONBLOCK); // Monitor the read side of the pipe so that messages sent via // Fl::awake() from a thread will "wake up" the main thread in // Fl::wait(). Fl::add_fd(thread_filedes[0], FL_READ, thread_awake_cb); // Set lock/unlock functions for this system, using a system-supplied // recursive mutex if supported... # ifdef HAVE_PTHREAD_MUTEX_RECURSIVE if (!lock_function_init_rec()) { fl_lock_function = lock_function_rec; fl_unlock_function = unlock_function_rec; } else { # endif // HAVE_PTHREAD_MUTEX_RECURSIVE lock_function_init_std(); fl_lock_function = lock_function_std; fl_unlock_function = unlock_function_std; # ifdef HAVE_PTHREAD_MUTEX_RECURSIVE } # endif // HAVE_PTHREAD_MUTEX_RECURSIVE } fl_lock_function(); return 0; } void Fl_Posix_System_Driver::unlock() { fl_unlock_function(); } // Mutex code for the awake ring buffer static pthread_mutex_t *ring_mutex; void Fl_Posix_System_Driver::unlock_ring() { pthread_mutex_unlock(ring_mutex); } void Fl_Posix_System_Driver::lock_ring() { if (!ring_mutex) { ring_mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t)); pthread_mutex_init(ring_mutex, NULL); } pthread_mutex_lock(ring_mutex); } #else // ! HAVE_PTHREAD void Fl_Posix_System_Driver::awake(void*) {} int Fl_Posix_System_Driver::lock() { return 1; } void Fl_Posix_System_Driver::unlock() {} void* Fl_Posix_System_Driver::thread_message() { return NULL; } //void lock_ring() {} //void unlock_ring() {} #endif // HAVE_PTHREAD fltk-1.4.3/src/drivers/Wayland/0000755000175000017500000000000015004135251016451 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx0000644000175000017500000021372215004135251024036 0ustar albrechtalbrecht// // Implementation of Wayland Screen interface // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Wayland_Screen_Driver.H" #include "Fl_Wayland_Window_Driver.H" #include "Fl_Wayland_Graphics_Driver.H" #include #include "../../../libdecor/build/fl_libdecor.h" #include "xdg-shell-client-protocol.h" #include "../Posix/Fl_Posix_System_Driver.H" #include #include #include #include #include #if FLTK_USE_STD # include typedef std::vector Fl_Int_Vector; #else # include "../../Fl_Int_Vector.H" #endif #include "../../print_button.h" #include #include #include #include #include #include "text-input-client-protocol.h" #include "gtk-shell-client-protocol.h" #include #include #include #include #include // for strerror() extern "C" { bool libdecor_get_cursor_settings(char **theme, int *size); bool fl_is_surface_from_GTK_titlebar (struct wl_surface *surface, struct libdecor_frame *frame, bool *using_GTK); } // set this to 1 for keyboard debug output, 0 for no debug output #define DEBUG_KEYBOARD 0 #define fl_max(a,b) ((a) > (b) ? (a) : (b)) #define fl_min(a,b) ((a) < (b) ? (a) : (b)) struct pointer_output { Fl_Wayland_Screen_Driver::output* output; struct wl_list link; }; /* Implementation note: - About CSD and SSD : * Mutter and Weston use CSD (client-side decoration) which means that libdecor.so draws all window titlebars and responds to resize, minimization and maximization events. * KWin uses SSD (server-side decoration) which means the OS draws titlebars according to its own rules and triggers resize, minimization and maximization events. - Function registry_handle_global() runs within fl_open_display() and sets public static variable Fl_Wayland_Screen_Driver::compositor to either Fl_Wayland_Screen_Driver::MUTTER, ::WESTON, or ::KWIN. - Specific operations for WESTON: * When a libdecor-framed window is minimized under Weston, the frame remains on display. To avoid that, function libdecor_frame_set_minimized() is modified so it turns off the frame's visibility, with function libdecor_frame_set_visibility(), when the window is minimized. That's implemented in file libdecor/build/fl_libdecor.c. The modified libdecor_frame_set_minimized() function, part of libdecor.so, needs access to variable Fl_Wayland_Screen_Driver::compositor, part of libfltk.a. This is achieved calling FLTK function fl_libdecor_using_weston() which returns whether the running compositor is Weston. This Weston bug has been corrected in Weston version 10. Thus, this special processing is not performed when Weston version is ≥ 10. - Support of Fl_Window::border(int) : FLTK uses libdecor_frame_set_visibility() to show or hide a toplevel window's frame. This doesn't work with KWin which uses Server-Side Decoration. In that case, FLTK hides and re-shows the window to toggle between presence and absence of a window's frame. */ static Fl_Int_Vector key_vector; // used by Fl_Wayland_Screen_Driver::event_key() static struct wl_surface *gtk_shell_surface = NULL; Fl_Wayland_Screen_Driver::compositor_name Fl_Wayland_Screen_Driver::compositor = Fl_Wayland_Screen_Driver::unspecified; extern "C" { bool fl_libdecor_using_weston(void) { return Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::WESTON; } } static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) { xdg_wm_base_pong(xdg_wm_base, serial); } static const struct xdg_wm_base_listener xdg_wm_base_listener = { .ping = xdg_wm_base_ping, }; // these are set by Fl::args() and override any system colors: from Fl_get_system_colors.cxx extern const char *fl_fg; extern const char *fl_bg; extern const char *fl_bg2; // end of extern additions workaround void Fl_Wayland_Screen_Driver::do_set_cursor( struct Fl_Wayland_Screen_Driver::seat *seat, struct wl_cursor *wl_cursor) { struct wl_cursor_image *image; struct wl_buffer *buffer; const int scale = seat->pointer_scale; if (!seat->cursor_theme || !seat->wl_pointer) return; if (!wl_cursor) wl_cursor = seat->default_cursor; image = wl_cursor->images[0]; buffer = wl_cursor_image_get_buffer(image); wl_pointer_set_cursor(seat->wl_pointer, seat->pointer_enter_serial, seat->cursor_surface, image->hotspot_x / scale, image->hotspot_y / scale); wl_surface_attach(seat->cursor_surface, buffer, 0, 0); wl_surface_set_buffer_scale(seat->cursor_surface, scale); wl_surface_damage_buffer(seat->cursor_surface, 0, 0, image->width, image->height); wl_surface_commit(seat->cursor_surface); } static uint32_t ptime; static uint32_t wld_event_time; static int px, py; static void set_event_xy(Fl_Window *win) { // turn off is_click if enough time or mouse movement has passed: if (abs(Fl::e_x_root-px)+abs(Fl::e_y_root-py) > 3 || wld_event_time >= ptime+1000) { Fl::e_is_click = 0; //fprintf(stderr, "Fl::e_is_click = 0\n"); } } // if this is same event as last && is_click, increment click count: static inline void checkdouble() { if (Fl::e_is_click == Fl::e_keysym) { Fl::e_clicks++; //fprintf(stderr, "Fl::e_clicks = %d\n", Fl::e_clicks); } else { Fl::e_clicks = 0; Fl::e_is_click = Fl::e_keysym; //fprintf(stderr, "Fl::e_is_click = %d\n", Fl::e_is_click); } px = Fl::e_x_root; py = Fl::e_y_root; ptime = wld_event_time; } struct wl_display *Fl_Wayland_Screen_Driver::wl_display = NULL; static Fl_Window *event_coords_from_surface(struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface); if (!win) return NULL; int delta_x = 0, delta_y = 0; while (win->parent()) { delta_x += win->x(); delta_y += win->y(); win = win->window(); } float f = Fl::screen_scale(win->screen_num()); Fl::e_x = wl_fixed_to_int(surface_x) / f + delta_x; Fl::e_x_root = Fl::e_x + win->x(); Fl::e_y = wl_fixed_to_int(surface_y) / f + delta_y; int *poffset = Fl_Window_Driver::menu_offset_y(win); if (poffset) Fl::e_y -= *poffset; Fl::e_y_root = Fl::e_y + win->y(); return win; } static void pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; Fl_Window *win = event_coords_from_surface(surface, surface_x, surface_y); static bool using_GTK = seat->gtk_shell && (gtk_shell1_get_version(seat->gtk_shell) >= GTK_SURFACE1_TITLEBAR_GESTURE_SINCE_VERSION); if (!win && using_GTK) { // check whether surface is the headerbar of a GTK-decorated window Fl_X *xp = Fl_X::first; while (xp && using_GTK) { // all mapped windows struct wld_window *xid = (struct wld_window*)xp->xid; if (xid->kind == Fl_Wayland_Window_Driver::DECORATED && fl_is_surface_from_GTK_titlebar(surface, xid->frame, &using_GTK)) { gtk_shell_surface = surface; break; } xp = xp->next; } } if (!win) return; // use custom cursor if present struct wl_cursor *cursor = fl_wl_xid(win)->custom_cursor ? fl_wl_xid(win)->custom_cursor->wl_cursor : NULL; Fl_Wayland_Screen_Driver::do_set_cursor(seat, cursor); seat->serial = serial; seat->pointer_enter_serial = serial; set_event_xy(win); Fl::handle(FL_ENTER, win); //fprintf(stderr, "pointer_enter window=%p\n", win); seat->pointer_focus = surface; } static void pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; if (seat->pointer_focus == surface) seat->pointer_focus = NULL; Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface); gtk_shell_surface = NULL; if (win) { Fl::belowmouse(0); set_event_xy(win); Fl::handle(FL_LEAVE, win->top_window()); } //fprintf(stderr, "pointer_leave surface=%p window=%p\n", surface, win); } static void pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; Fl_Window *win = event_coords_from_surface(seat->pointer_focus, surface_x, surface_y); if (!win) return; if (Fl::grab() && !Fl::grab()->menu_window() && Fl::grab() != win) { // If there's an active, non-menu grab() and the pointer is in a window other than // the grab(), make e_x_root too large to be in any window Fl::e_x_root = 1000000; } else if (Fl_Window_Driver::menu_parent(NULL) && // any kind of menu is active now, and !win->menu_window() && // we enter a non-menu window win != Fl_Window_Driver::menu_parent(NULL) // that's not the window below the menu ) { Fl::e_x_root = 1000000; // make it too large to be in any window } //fprintf(stderr, "FL_MOVE on win=%p to x:%dx%d root:%dx%d\n", win, Fl::e_x, Fl::e_y, Fl::e_x_root, Fl::e_y_root); wld_event_time = time; set_event_xy(win); Fl::handle(FL_MOVE, win); } //#include static void pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; if (gtk_shell_surface && state == WL_POINTER_BUTTON_STATE_PRESSED && button == BTN_MIDDLE) { struct gtk_surface1 *gtk_surface = gtk_shell1_get_gtk_surface(seat->gtk_shell,gtk_shell_surface); gtk_surface1_titlebar_gesture(gtk_surface, serial, seat->wl_seat, GTK_SURFACE1_GESTURE_MIDDLE_CLICK); gtk_surface1_release(gtk_surface); // very necessary return; } seat->serial = serial; int event = 0; Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(seat->pointer_focus); if (!win) return; win = win->top_window(); wld_event_time = time; int b = 0; // Fl::e_state &= ~FL_BUTTONS; // DO NOT reset the mouse button state! if (state == WL_POINTER_BUTTON_STATE_PRESSED) { if (button == BTN_LEFT) { Fl::e_state |= FL_BUTTON1; b = 1; } else if (button == BTN_RIGHT) { Fl::e_state |= FL_BUTTON3; b = 3; } else if (button == BTN_MIDDLE) { Fl::e_state |= FL_BUTTON2; b = 2; } else if (button == BTN_BACK) { Fl::e_state |= FL_BUTTON4; b = 4; } // ? else if (button == BTN_SIDE) { Fl::e_state |= FL_BUTTON4; b = 4; } // OK: Debian 12 else if (button == BTN_FORWARD) { Fl::e_state |= FL_BUTTON5; b = 5; } // ? else if (button == BTN_EXTRA) { Fl::e_state |= FL_BUTTON5; b = 5; } // OK: Debian 12 } else { // must be WL_POINTER_BUTTON_STATE_RELEASED if (button == BTN_LEFT) { Fl::e_state &= ~FL_BUTTON1; b = 1; } else if (button == BTN_RIGHT) { Fl::e_state &= ~FL_BUTTON3; b = 3; } else if (button == BTN_MIDDLE) { Fl::e_state &= ~FL_BUTTON2; b = 2; } else if (button == BTN_BACK) { Fl::e_state &= ~FL_BUTTON4; b = 4; } // ? else if (button == BTN_SIDE) { Fl::e_state &= ~FL_BUTTON4; b = 4; } // OK: Debian 12 else if (button == BTN_FORWARD) { Fl::e_state &= ~FL_BUTTON5; b = 5; } // ? else if (button == BTN_EXTRA) { Fl::e_state &= ~FL_BUTTON5; b = 5; } // OK: Debian 12 } Fl::e_keysym = FL_Button + b; Fl::e_dx = Fl::e_dy = 0; set_event_xy(win); if (state == WL_POINTER_BUTTON_STATE_PRESSED) { event = FL_PUSH; checkdouble(); } else if (state == WL_POINTER_BUTTON_STATE_RELEASED) { event = FL_RELEASE; } // fprintf(stderr, "%s %s\n", fl_eventnames[event], win->label() ? win->label():"[]"); Fl::handle(event, win); } static void pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(seat->pointer_focus); if (!win) return; wld_event_time = time; int delta = wl_fixed_to_int(value); if (abs(delta) >= 10) delta /= 10; // fprintf(stderr, "FL_MOUSEWHEEL: %c delta=%d\n", axis==WL_POINTER_AXIS_HORIZONTAL_SCROLL?'H':'V', delta); // allow both horizontal and vertical movements to be processed by the widget if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) { if (Fl::event_shift()) { // shift key pressed: send vertical mousewheel event Fl::e_dx = 0; Fl::e_dy = delta; } else { // shift key not pressed (normal behavior): send horizontal mousewheel event Fl::e_dx = delta; Fl::e_dy = 0; } Fl::handle(FL_MOUSEWHEEL, win->top_window()); } if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { if (Fl::event_shift()) { // shift key pressed: send horizontal mousewheel event Fl::e_dx = delta; Fl::e_dy = 0; } else {// shift key not pressed (normal behavior): send vertical mousewheel event Fl::e_dx = 0; Fl::e_dy = delta; } Fl::handle(FL_MOUSEWHEEL, win->top_window()); } } static struct wl_pointer_listener pointer_listener = { pointer_enter, pointer_leave, pointer_motion, pointer_button, pointer_axis }; static const char *proxy_tag = "FLTK for Wayland"; bool Fl_Wayland_Screen_Driver::own_output(struct wl_output *output) { return wl_proxy_get_tag((struct wl_proxy *)output) == &proxy_tag; } static void init_cursors(struct Fl_Wayland_Screen_Driver::seat *seat); static void try_update_cursor(struct Fl_Wayland_Screen_Driver::seat *seat) { if (wl_list_empty(&seat->pointer_outputs)) return; struct pointer_output *pointer_output; int scale = 1; wl_list_for_each(pointer_output, &seat->pointer_outputs, link) { scale = fl_max(scale, pointer_output->output->wld_scale); } if (scale != seat->pointer_scale) { seat->pointer_scale = scale; init_cursors(seat); Fl_Wayland_Screen_Driver::do_set_cursor(seat); } } static void output_scale(void *data, struct wl_output *wl_output, int32_t factor); static void cursor_surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { // Runs when the seat's cursor_surface enters a display struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; struct pointer_output *pointer_output; if (!Fl_Wayland_Screen_Driver::own_output(wl_output)) return; pointer_output = (struct pointer_output *)calloc(1, sizeof(struct pointer_output)); pointer_output->output = (Fl_Wayland_Screen_Driver::output *)wl_output_get_user_data(wl_output); //fprintf(stderr, "cursor_surface_enter: wl_output_get_user_data(%p)=%p\n", wl_output, pointer_output->output); wl_list_insert(&seat->pointer_outputs, &pointer_output->link); try_update_cursor(seat); Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)wl_output_get_user_data(wl_output); output_scale(output, wl_output, output->wld_scale); // rescale custom cursors // maintain custom or standard window cursor Fl_Window *win = Fl::first_window(); if (win) { Fl_Wayland_Window_Driver *driver = Fl_Wayland_Window_Driver::driver(win); struct wld_window *xid = fl_wl_xid(win); if (xid->custom_cursor) Fl_Wayland_Screen_Driver::do_set_cursor(seat, xid->custom_cursor->wl_cursor); else if (driver->cursor_default()) driver->set_cursor(driver->cursor_default()); else win->cursor(driver->standard_cursor()); } } static void cursor_surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; struct pointer_output *pointer_output, *tmp; wl_list_for_each_safe(pointer_output, tmp, &seat->pointer_outputs, link) { if (pointer_output->output->wl_output == wl_output) { wl_list_remove(&pointer_output->link); free(pointer_output); } } try_update_cursor(seat); // maintain custom window cursor Fl_Window *win = Fl::first_window(); if (win) { struct wld_window *xid = fl_wl_xid(win); if (xid->custom_cursor) Fl_Wayland_Screen_Driver::do_set_cursor(seat, xid->custom_cursor->wl_cursor); } } static struct wl_surface_listener cursor_surface_listener = { cursor_surface_enter, cursor_surface_leave, }; static void init_cursors(struct Fl_Wayland_Screen_Driver::seat *seat) { char *name; int size; struct wl_cursor_theme *theme; if (!libdecor_get_cursor_settings(&name, &size)) { name = NULL; size = 24; } size *= seat->pointer_scale; Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); theme = wl_cursor_theme_load(name, size, scr_driver->wl_shm); free(name); //struct wl_cursor_theme *old_theme = seat->cursor_theme; if (theme != NULL) { if (seat->cursor_theme) { // caution to destroy theme because Fl_Wayland_Window_Driver::set_cursor(Fl_Cursor) caches used cursors scr_driver->reset_cursor(); wl_cursor_theme_destroy(seat->cursor_theme); } seat->cursor_theme = theme; } if (seat->cursor_theme) { seat->default_cursor = scr_driver->xc_cursor[Fl_Wayland_Screen_Driver::arrow] = wl_cursor_theme_get_cursor(seat->cursor_theme, "left_ptr"); } if (!seat->cursor_surface) { seat->cursor_surface = wl_compositor_create_surface(scr_driver->wl_compositor); wl_surface_add_listener(seat->cursor_surface, &cursor_surface_listener, seat); } } static void wl_keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1); char *map_shm = (char*)mmap(NULL, size, PROT_READ, wl_keyboard_get_version(wl_keyboard) >= 7 ? MAP_PRIVATE : MAP_SHARED, fd, 0); assert(map_shm != MAP_FAILED); struct xkb_keymap *xkb_keymap = xkb_keymap_new_from_string(seat->xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); munmap(map_shm, size); close(fd); if (xkb_keymap) { struct xkb_state *xkb_state = xkb_state_new(xkb_keymap); xkb_keymap_unref(seat->xkb_keymap); if (seat->xkb_state) xkb_state_unref(seat->xkb_state); seat->xkb_keymap = xkb_keymap; seat->xkb_state = xkb_state; } } static int search_int_vector(Fl_Int_Vector& v, int val) { for (unsigned pos = 0; pos < v.size(); pos++) { if (v[pos] == val) return pos; } return -1; } static void remove_int_vector(Fl_Int_Vector& v, int val) { int pos = search_int_vector(v, val); if (pos < 0) return; #if FLTK_USE_STD v.erase(v.begin()+pos); #else int last = v.pop_back(); if (last != val) v[pos] = last; #endif } static int process_wld_key(struct xkb_state *xkb_state, uint32_t key, uint32_t *p_keycode, xkb_keysym_t *p_sym) { uint32_t keycode = key + 8; xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, keycode); if (sym == 0xfe20) sym = FL_Tab; if (sym >= 'A' && sym <= 'Z') sym += 32; // replace uppercase by lowercase letter int for_key_vector = sym; // for support of Fl::event_key(int) // special processing for number keys == keycodes 10-19 : if (keycode >= 10 && keycode <= 18) { for_key_vector = '1' + (keycode - 10); } else if (keycode == 19) { for_key_vector = '0'; } if (p_keycode) *p_keycode = keycode; if (p_sym) *p_sym = sym; return for_key_vector; } static uint32_t last_keydown_serial = 0; // serial of last keydown event static void wl_keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; //fprintf(stderr, "keyboard enter fl_win=%p; keys pressed are: ", Fl_Wayland_Window_Driver::surface_to_window(surface)); #if FLTK_USE_STD key_vector.clear(); #else key_vector.size(0); #endif // Replace wl_array_for_each(p, keys) rejected by C++ for (uint32_t *p = (uint32_t *)(keys)->data; (const char *) p < ((const char *) (keys)->data + (keys)->size); (p)++) { int for_key_vector = process_wld_key(seat->xkb_state, *p, NULL, NULL); //fprintf(stderr, "%d ", for_key_vector); if (search_int_vector(key_vector, for_key_vector) < 0) { key_vector.push_back(for_key_vector); } } //fprintf(stderr, "\n"); seat->keyboard_surface = surface; seat->keyboard_enter_serial = serial; last_keydown_serial = 0; Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface); if (win) { Fl::handle(FL_FOCUS, win); fl_wl_find(fl_wl_xid(win)); } } struct key_repeat_data_t { uint32_t serial; Fl_Window *window; }; #define KEY_REPEAT_DELAY 0.5 // sec #define KEY_REPEAT_INTERVAL 0.05 // sec static void key_repeat_timer_cb(key_repeat_data_t *key_repeat_data) { if (last_keydown_serial == key_repeat_data->serial) { Fl::handle(FL_KEYDOWN, key_repeat_data->window); Fl::add_timeout(KEY_REPEAT_INTERVAL, (Fl_Timeout_Handler)key_repeat_timer_cb, key_repeat_data); } else delete key_repeat_data; } int Fl_Wayland_Screen_Driver::next_marked_length = 0; int Fl_Wayland_Screen_Driver::has_marked_text() const { return 1; } int Fl_Wayland_Screen_Driver::insertion_point_x = 0; int Fl_Wayland_Screen_Driver::insertion_point_y = 0; int Fl_Wayland_Screen_Driver::insertion_point_width = 0; int Fl_Wayland_Screen_Driver::insertion_point_height = 0; bool Fl_Wayland_Screen_Driver::insertion_point_location_is_valid = false; static int previous_cursor_x = 0, previous_cursor_y = 0, previous_cursor_h = 0; static uint32_t commit_serial = 0; static char *current_pre_edit = NULL; static char *pending_pre_edit = NULL; static char *pending_commit = NULL; static void send_commit(struct zwp_text_input_v3 *zwp_text_input_v3) { zwp_text_input_v3_commit(zwp_text_input_v3); commit_serial++; } // inform TIM about location of the insertion point, and memorize this info. void Fl_Wayland_Screen_Driver::insertion_point_location(int x, int y, int height) { //printf("insertion_point_location %dx%d\n",x,y); Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); if (scr_driver->seat->text_input /*&& !current_pre_edit*/ && (x != previous_cursor_x || y != previous_cursor_y || height != previous_cursor_h)) { previous_cursor_x = x; previous_cursor_y = y; previous_cursor_h = height; if (Fl::focus()) { Fl_Widget *focuswin = Fl::focus()->window(); while (focuswin && focuswin->parent()) { x += focuswin->x(); y += focuswin->y(); focuswin = focuswin->window(); } } float s = fl_graphics_driver->scale(); insertion_point_location_is_valid = true; insertion_point_x = s*x; insertion_point_y = s*(y-height); insertion_point_width = s*5; insertion_point_height = s*height; if (zwp_text_input_v3_get_user_data(scr_driver->seat->text_input) ) { zwp_text_input_v3_set_cursor_rectangle(scr_driver->seat->text_input, insertion_point_x, insertion_point_y, insertion_point_width, insertion_point_height); send_commit(scr_driver->seat->text_input); } } } // computes window coordinates & size of insertion point bool Fl_Wayland_Screen_Driver::insertion_point_location(int *px, int *py, int *pwidth, int *pheight) { // return true if the current coordinates and size of the insertion point are available if ( ! insertion_point_location_is_valid ) return false; *px = insertion_point_x; *py = insertion_point_y; *pwidth = insertion_point_width; *pheight = insertion_point_height; return true; } int Fl_Wayland_Screen_Driver::compose(int& del) { unsigned char ascii = (unsigned char)Fl::e_text[0]; // letter+modifier key int condition = (Fl::e_state & (FL_ALT | FL_META | FL_CTRL)) && ascii < 128 ; // pressing modifier key // FL_Shift_L, FL_Shift_R, FL_Control_L, FL_Control_R, FL_Caps_Lock // FL_Meta_L, FL_Meta_R, FL_Alt_L, FL_Alt_R condition |= ((Fl::e_keysym >= FL_Shift_L && Fl::e_keysym <= FL_Alt_R) || Fl::e_keysym == FL_Alt_Gr); // FL_Home FL_Left FL_Up FL_Right FL_Down FL_Page_Up FL_Page_Down FL_End // FL_Print FL_Insert FL_Menu FL_Help and more condition |= (Fl::e_keysym >= FL_Home && Fl::e_keysym <= FL_Help); condition |= Fl::e_keysym == FL_Tab; //fprintf(stderr, "compose: condition=%d e_state=%x ascii=%d\n", condition, Fl::e_state, ascii); if (condition) { del = 0; return 0;} //fprintf(stderr, "compose: del=%d compose_state=%d next_marked_length=%d \n", del, Fl::compose_state, next_marked_length); del = Fl::compose_state; Fl::compose_state = next_marked_length; // no-underlined-text && (ascii non-printable || ascii == delete) if (ascii && (!Fl::compose_state) && (ascii <= 31 || ascii == 127)) { del = 0; return 0; } return 1; } void Fl_Wayland_Screen_Driver::compose_reset() { if (!Fl_Wayland_Screen_Driver::wl_registry) open_display(); Fl::compose_state = 0; next_marked_length = 0; if (seat->xkb_compose_state) xkb_compose_state_reset(seat->xkb_compose_state); } struct dead_key_struct { xkb_keysym_t keysym; // the keysym obtained when hitting a dead key const char *marked_text; // the temporary text to display for that dead key }; static dead_key_struct dead_keys[] = { {XKB_KEY_dead_grave, "`"}, {XKB_KEY_dead_acute, "´"}, {XKB_KEY_dead_circumflex, "^"}, {XKB_KEY_dead_tilde, "~"}, {XKB_KEY_dead_macron, "¯"}, {XKB_KEY_dead_breve, "˘"}, {XKB_KEY_dead_abovedot, "˙"}, {XKB_KEY_dead_diaeresis, "¨"}, {XKB_KEY_dead_abovering, "˚"}, {XKB_KEY_dead_doubleacute, "˝"}, {XKB_KEY_dead_caron, "ˇ"}, {XKB_KEY_dead_cedilla, "¸"}, {XKB_KEY_dead_ogonek, "˛"}, {XKB_KEY_dead_iota, "ι"}, {XKB_KEY_dead_doublegrave, " ̏"}, }; const int dead_key_count = sizeof(dead_keys)/sizeof(struct dead_key_struct); static void wl_keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; seat->serial = serial; static char buf[128]; uint32_t keycode; xkb_keysym_t sym; int for_key_vector = process_wld_key(seat->xkb_state, key, &keycode, &sym); #if (DEBUG_KEYBOARD) xkb_keysym_get_name(sym, buf, sizeof(buf)); const char *action = (state == WL_KEYBOARD_KEY_STATE_PRESSED ? "press" : "release"); fprintf(stderr, "wl_keyboard_key: key %s: sym: %-12s(%d) code:%u fl_win=%p, ", action, buf, sym, keycode, Fl_Wayland_Window_Driver::surface_to_window(seat->keyboard_surface)); #endif xkb_state_key_get_utf8(seat->xkb_state, keycode, buf, sizeof(buf)); #if (DEBUG_KEYBOARD) fprintf(stderr, "utf8: '%s' e_length=%d [%d]\n", buf, (int)strlen(buf), *buf); #endif Fl::e_keysym = Fl::e_original_keysym = for_key_vector; if (!(Fl::e_state & FL_NUM_LOCK) && sym >= XKB_KEY_KP_Home && sym <= XKB_KEY_KP_Delete) { // compute e_keysym and e_original_keysym for keypad number keys and '.|,' when NumLock is off static const int table[11] = {FL_Home /* 7 */, FL_Left /* 4 */, FL_Up /* 8 */, FL_Right /* 6 */, FL_Down /* 2 */, FL_Page_Up /* 9 */, FL_Page_Down /* 3 */, FL_End /* 1 */, 0xff0b /* 5 */, FL_Insert /* 0 */, FL_Delete /* .|, */}; static const int table_original[11] = {0xffb7 /* 7 */, 0xffb4 /* 4 */, 0xffb8 /* 8 */, 0xffb6 /* 6 */, 0xffb2 /* 2 */, 0xffb9 /* 9 */, 0xffb3 /* 3 */, 0xffb1 /* 1 */, 0xffb5 /* 5 */, 0xffb0 /* 0 */, 0xffac /* .|, */}; Fl::e_keysym = table[sym - XKB_KEY_KP_Home]; Fl::e_original_keysym = table_original[sym - XKB_KEY_KP_Home]; for_key_vector = Fl::e_original_keysym; } #if (DEBUG_KEYBOARD) fprintf(stderr, "wl_keyboard_key: e_keysym=%x e_original_keysym=%x\n", Fl::e_keysym, Fl::e_original_keysym); #endif if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { if (search_int_vector(key_vector, for_key_vector) < 0) { key_vector.push_back(for_key_vector); } } else { last_keydown_serial = 0; remove_int_vector(key_vector, for_key_vector); } Fl::e_text = buf; Fl::e_length = (int)strlen(buf); // Process dead keys and compose sequences : enum xkb_compose_status status = XKB_COMPOSE_NOTHING; // This part is useful only if the compositor doesn't support protocol text-input-unstable-v3 if (seat->xkb_compose_state && state == WL_KEYBOARD_KEY_STATE_PRESSED && !(sym >= FL_Shift_L && sym <= FL_Alt_R) && sym != XKB_KEY_ISO_Level3_Shift) { xkb_compose_state_feed(seat->xkb_compose_state, sym); status = xkb_compose_state_get_status(seat->xkb_compose_state); if (status == XKB_COMPOSE_COMPOSING) { if (Fl::e_length == 0) { // dead keys produce e_length = 0 int i; for (i = 0; i < dead_key_count; i++) { if (dead_keys[i].keysym == sym) break; } if (i < dead_key_count) strcpy(buf, dead_keys[i].marked_text); else buf[0] = 0; Fl::e_length = (int)strlen(buf); Fl::compose_state = 0; } Fl_Wayland_Screen_Driver::next_marked_length = Fl::e_length; } else if (status == XKB_COMPOSE_COMPOSED) { Fl::e_length = xkb_compose_state_get_utf8(seat->xkb_compose_state, buf, sizeof(buf)); Fl::compose_state = Fl_Wayland_Screen_Driver::next_marked_length; Fl_Wayland_Screen_Driver::next_marked_length = 0; } else if (status == XKB_COMPOSE_CANCELLED) { Fl::e_length = 0; Fl::compose_state = Fl_Wayland_Screen_Driver::next_marked_length; Fl_Wayland_Screen_Driver::next_marked_length = 0; } //fprintf(stderr, "xkb_compose_status=%d ctxt=%p state=%p l=%d[%s]\n", status, seat->xkb_context, seat->xkb_compose_state, Fl::e_length, buf); } // end of part used only without text-input-unstable-v3 wld_event_time = time; int event = (state == WL_KEYBOARD_KEY_STATE_PRESSED ? FL_KEYDOWN : FL_KEYUP); // Send event to focus-containing top window as defined by FLTK, // otherwise send it to Wayland-defined focus window Fl_Window *win = ( Fl::focus() ? Fl::focus()->top_window() : Fl_Wayland_Window_Driver::surface_to_window(seat->keyboard_surface) ); if (win) { set_event_xy(win); Fl::e_is_click = 0; Fl::handle(event, win); } if (event == FL_KEYDOWN && status == XKB_COMPOSE_NOTHING && !(sym >= FL_Shift_L && sym <= FL_Alt_R)) { // Handling of key repeats : // Use serial argument rather than time to detect repeated keys because // serial value changes at each key up or down in all tested OS and compositors, // whereas time value changes in Ubuntu24.04 KDE/Plasma 5.27.11 and Ubuntu22.04 KDE/Plasma 5.24.7 // but not in Debian-testing KDE/Plasma 5.27.10. // Unexplained difference in behaviors of KDE/Plasma compositor: // Consider KDE settings -> input -> keyboard -> when a key is held: repeat/do nothing. // This setting (repeat) has key-down wayland events repeated when key is held under Debian/KDE // but not under Ubuntu/KDE ! key_repeat_data_t *key_repeat_data = new key_repeat_data_t; key_repeat_data->serial = serial; key_repeat_data->window = win; last_keydown_serial = serial; Fl::add_timeout(KEY_REPEAT_DELAY, (Fl_Timeout_Handler)key_repeat_timer_cb, key_repeat_data); } } static void wl_keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; //fprintf(stderr, "keyboard leave fl_win=%p\n", Fl_Wayland_Window_Driver::surface_to_window(surface)); seat->keyboard_surface = NULL; last_keydown_serial = 0; Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface); if (!win && Fl::focus()) win = Fl::focus()->top_window(); if (win) Fl::handle(FL_UNFOCUS, win); #if FLTK_USE_STD key_vector.clear(); #else key_vector.size(0); #endif } static void wl_keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; xkb_state_update_mask(seat->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); Fl::e_state &= ~(FL_SHIFT+FL_CTRL+FL_ALT+FL_CAPS_LOCK+FL_NUM_LOCK); if (xkb_state_mod_name_is_active(seat->xkb_state, XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_DEPRESSED)) Fl::e_state |= FL_SHIFT; if (xkb_state_mod_name_is_active(seat->xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_DEPRESSED)) Fl::e_state |= FL_CTRL; if (xkb_state_mod_name_is_active(seat->xkb_state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_DEPRESSED)) Fl::e_state |= FL_ALT; if (xkb_state_mod_name_is_active(seat->xkb_state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED)) Fl::e_state |= FL_CAPS_LOCK; if (xkb_state_mod_name_is_active(seat->xkb_state, XKB_MOD_NAME_NUM, XKB_STATE_MODS_LOCKED)) Fl::e_state |= FL_NUM_LOCK; //fprintf(stderr, "mods_depressed=%u Fl::e_state=%X\n", mods_depressed, Fl::e_state); } static void wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay) { // wl_keyboard is version 3 under Debian, but that event isn't sent until version 4 } static const struct wl_keyboard_listener wl_keyboard_listener = { .keymap = wl_keyboard_keymap, .enter = wl_keyboard_enter, .leave = wl_keyboard_leave, .key = wl_keyboard_key, .modifiers = wl_keyboard_modifiers, .repeat_info = wl_keyboard_repeat_info, }; void text_input_enter(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, struct wl_surface *surface) { //puts("text_input_enter"); zwp_text_input_v3_set_user_data(zwp_text_input_v3, surface); zwp_text_input_v3_enable(zwp_text_input_v3); zwp_text_input_v3_set_content_type(zwp_text_input_v3, ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL); int x, y, width, height; if (Fl_Wayland_Screen_Driver::insertion_point_location(&x, &y, &width, &height)) { zwp_text_input_v3_set_cursor_rectangle(zwp_text_input_v3, x, y, width, height); } send_commit(zwp_text_input_v3); } void text_input_leave(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, struct wl_surface *surface) { //puts("text_input_leave"); zwp_text_input_v3_disable(zwp_text_input_v3); zwp_text_input_v3_set_user_data(zwp_text_input_v3, NULL); send_commit(zwp_text_input_v3); free(pending_pre_edit); pending_pre_edit = NULL; free(current_pre_edit); current_pre_edit = NULL; free(pending_commit); pending_commit = NULL; } static void send_text_to_fltk(const char *text, bool is_marked, struct wl_surface *current_surface) { //printf("send_text_to_fltk(%s, %d)\n",text,is_marked); Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(current_surface); Fl::e_text = text ? (char*)text : (char*)""; Fl::e_length = text ? (int)strlen(text) : 0; Fl::e_keysym = 'a'; // fake a simple key set_event_xy(win); Fl::e_is_click = 0; if (is_marked) { // goes to widget as marked text Fl_Wayland_Screen_Driver::next_marked_length = Fl::e_length; Fl::handle(FL_KEYDOWN, win); } else if (text) { Fl_Wayland_Screen_Driver::next_marked_length = 0; Fl::handle(FL_KEYDOWN, win); Fl::compose_state = 0; } else { Fl_Wayland_Screen_Driver::next_marked_length = 0; Fl::handle(FL_KEYDOWN, win); } } void text_input_preedit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, const char *text, int32_t cursor_begin, int32_t cursor_end) { //printf("text_input_preedit_string %s cursor_begin=%d cursor_end=%d\n",text, cursor_begin, cursor_end); free(pending_pre_edit); pending_pre_edit = text ? strdup(text) : NULL; } void text_input_commit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, const char *text) { //printf("text_input_commit_string %s\n",text); free(pending_commit); pending_commit = text ? strdup(text) : NULL; } void text_input_delete_surrounding_text(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, uint32_t before_length, uint32_t after_length) { fprintf(stderr, "delete_surrounding_text before=%d adfter=%d\n", before_length,after_length); } void text_input_done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3, uint32_t serial) { //puts("text_input_done"); struct wl_surface *current_surface = (struct wl_surface*)data; const bool bad_event = (serial != commit_serial); if ((pending_pre_edit == NULL && current_pre_edit == NULL) || (pending_pre_edit && current_pre_edit && strcmp(pending_pre_edit, current_pre_edit) == 0)) { free(pending_pre_edit); pending_pre_edit = NULL; } else { free(current_pre_edit); current_pre_edit = pending_pre_edit; pending_pre_edit = NULL; if (current_pre_edit) { send_text_to_fltk(current_pre_edit, !bad_event, current_surface); } else { send_text_to_fltk(NULL, false, current_surface); } } if (pending_commit) { send_text_to_fltk(pending_commit, false, current_surface); free(pending_commit); pending_commit = NULL; } } static const struct zwp_text_input_v3_listener text_input_listener = { .enter = text_input_enter, .leave = text_input_leave, .preedit_string = text_input_preedit_string, .commit_string = text_input_commit_string, .delete_surrounding_text = text_input_delete_surrounding_text, .done = text_input_done, }; void Fl_Wayland_Screen_Driver::enable_im() { if (text_input_base && !seat->text_input) { seat->text_input = zwp_text_input_manager_v3_get_text_input(text_input_base, seat->wl_seat); //printf("seat->text_input=%p\n",seat->text_input); zwp_text_input_v3_add_listener(seat->text_input, &text_input_listener, NULL); } } void Fl_Wayland_Screen_Driver::disable_im() { if (seat->text_input) { zwp_text_input_v3_disable(seat->text_input); zwp_text_input_v3_commit(seat->text_input); zwp_text_input_v3_destroy(seat->text_input); seat->text_input = NULL; free(pending_pre_edit); pending_pre_edit = NULL; free(current_pre_edit); current_pre_edit = NULL; free(pending_commit); pending_commit = NULL; } } static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !seat->wl_pointer) { seat->wl_pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); seat->pointer_scale = 1; init_cursors(seat); } else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer) { wl_pointer_release(seat->wl_pointer); seat->wl_pointer = NULL; } bool have_keyboard = seat->xkb_context && (capabilities & WL_SEAT_CAPABILITY_KEYBOARD); if (have_keyboard && seat->wl_keyboard == NULL) { seat->wl_keyboard = wl_seat_get_keyboard(wl_seat); wl_keyboard_add_listener(seat->wl_keyboard, &wl_keyboard_listener, seat); //fprintf(stderr, "wl_keyboard version=%d\n", wl_keyboard_get_version(seat->wl_keyboard)); } else if (!have_keyboard && seat->wl_keyboard != NULL) { wl_keyboard_release(seat->wl_keyboard); seat->wl_keyboard = NULL; } Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); scr_driver->enable_im(); } static void seat_name(void *data, struct wl_seat *wl_seat, const char *name) { struct Fl_Wayland_Screen_Driver::seat *seat = (struct Fl_Wayland_Screen_Driver::seat*)data; seat->name = strdup(name); } static struct wl_seat_listener seat_listener = { seat_capabilities, seat_name }; static void output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char *make, const char *model, int32_t transform) { //fprintf(stderr, "output_geometry: x=%d y=%d physical=%dx%d\n",x,y,physical_width,physical_height); Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)data; output->x = int(x); output->y = int(y); output->dpi = 96; // to elaborate } static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)data; output->width = int(width); output->height = int(height); //fprintf(stderr, "output_mode: [%p]=%dx%d\n",output->wl_output,width,height); } static void output_done(void *data, struct wl_output *wl_output) { // Runs at startup and when desktop scale factor is changed Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)data; //fprintf(stderr, "output_done output=%p\n",output); Fl_X *xp = Fl_X::first; while (xp) { // all mapped windows struct wld_window *win = (struct wld_window*)xp->xid; Fl_Window *W = win->fl_win; if (win->buffer || W->as_gl_window()) { if (W->as_gl_window()) { wl_surface_set_buffer_scale(win->wl_surface, output->wld_scale); Fl_Window_Driver::driver(W)->is_a_rescale(true); W->resize(W->x(), W->y(), W->w(), W->h()); Fl_Window_Driver::driver(W)->is_a_rescale(false); } else { Fl_Wayland_Graphics_Driver::buffer_release(win); } W->redraw(); Fl_Window_Driver::driver(W)->flush(); } xp = xp->next; } output->done = true; Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); if (scr_driver->seat) try_update_cursor(scr_driver->seat); scr_driver->init_workarea(); Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL); } static void output_scale(void *data, struct wl_output *wl_output, int32_t factor) { Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)data; output->wld_scale = factor; //fprintf(stderr,"output_scale: wl_output=%p factor=%d\n",wl_output, factor); // rescale cursors of windows that map here and have a custom cursor Fl_Window *win = Fl::first_window(); while (win) { struct wld_window *xid = fl_wl_xid(win); struct Fl_Wayland_Window_Driver::surface_output *s_output; // get 1st screen where window appears s_output = wl_container_of(xid->outputs.next, s_output, link); if (xid->custom_cursor && output == s_output->output) { Fl_Wayland_Window_Driver *driver = Fl_Wayland_Window_Driver::driver(win); driver->set_cursor_4args(xid->custom_cursor->rgb, xid->custom_cursor->hotx, xid->custom_cursor->hoty, false); }; win = Fl::next_window(win); } } static struct wl_output_listener output_listener = { output_geometry, output_mode, output_done, output_scale }; // Notice: adding use of unstable protocol "XDG output" would allow FLTK to be notified // in real time of changes to the relative location of multiple displays; // with the present code, that information is received at startup only. static void registry_handle_global(void *user_data, struct wl_registry *wl_registry, uint32_t id, const char *interface, uint32_t version) { //fprintf(stderr, "interface=%s version=%u\n", interface, version); Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); if (strcmp(interface, "wl_compositor") == 0) { if (version < 4) { Fl::fatal("wl_compositor version >= 4 required"); } scr_driver->wl_compositor = (struct wl_compositor*)wl_registry_bind(wl_registry, id, &wl_compositor_interface, 4); } else if (strcmp(interface, "wl_subcompositor") == 0) { scr_driver->wl_subcompositor = (struct wl_subcompositor*)wl_registry_bind(wl_registry, id, &wl_subcompositor_interface, 1); } else if (strcmp(interface, "wl_shm") == 0) { scr_driver->wl_shm = (struct wl_shm*)wl_registry_bind(wl_registry, id, &wl_shm_interface, 1); } else if (strcmp(interface, "wl_seat") == 0) { if (version < 3) { Fl::fatal("%s version 3 required but only version %i is available\n", interface, version); } if (!scr_driver->seat) scr_driver->seat = (struct Fl_Wayland_Screen_Driver::seat*)calloc(1, sizeof(struct Fl_Wayland_Screen_Driver::seat)); //fprintf(stderr, "registry_handle_global: seat=%p\n", scr_driver->seat); wl_list_init(&scr_driver->seat->pointer_outputs); scr_driver->seat->wl_seat = (wl_seat*)wl_registry_bind(wl_registry, id, &wl_seat_interface, 3); scr_driver->seat->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (scr_driver->seat->xkb_context) { const char *locale = getenv("LC_ALL"); if (!locale || !*locale) locale = getenv("LC_CTYPE"); if (!locale || !*locale) locale = getenv("LANG"); if (!locale || !*locale) locale = "C"; struct xkb_compose_table *table = xkb_compose_table_new_from_locale(scr_driver->seat->xkb_context, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); if (table) { scr_driver->seat->xkb_compose_state = xkb_compose_state_new(table, XKB_COMPOSE_STATE_NO_FLAGS); } } wl_seat_add_listener(scr_driver->seat->wl_seat, &seat_listener, scr_driver->seat); if (scr_driver->seat->data_device_manager) { scr_driver->seat->data_device = wl_data_device_manager_get_data_device(scr_driver->seat->data_device_manager, scr_driver->seat->wl_seat); wl_data_device_add_listener(scr_driver->seat->data_device, Fl_Wayland_Screen_Driver::p_data_device_listener, NULL); } } else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) { if (!scr_driver->seat) scr_driver->seat = (struct Fl_Wayland_Screen_Driver::seat*)calloc(1, sizeof(struct Fl_Wayland_Screen_Driver::seat)); scr_driver->seat->data_device_manager = (struct wl_data_device_manager*)wl_registry_bind(wl_registry, id, &wl_data_device_manager_interface, fl_min(version, 3)); if (scr_driver->seat->wl_seat) { scr_driver->seat->data_device = wl_data_device_manager_get_data_device(scr_driver->seat->data_device_manager, scr_driver->seat->wl_seat); wl_data_device_add_listener(scr_driver->seat->data_device, Fl_Wayland_Screen_Driver::p_data_device_listener, NULL); } //fprintf(stderr, "registry_handle_global: %s\n", interface); } else if (strcmp(interface, "wl_output") == 0) { if (version < 2) { Fl::fatal("%s version 2 required but only version %i is available\n", interface, version); } Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)calloc(1, sizeof *output); output->id = id; output->wld_scale = 1; #ifdef WL_OUTPUT_RELEASE_SINCE_VERSION const int used_version = WL_OUTPUT_RELEASE_SINCE_VERSION; #else const int used_version = 2; #endif output->wl_output = (struct wl_output*)wl_registry_bind(wl_registry, id, &wl_output_interface, fl_min(used_version, version)); output->gui_scale = 1.f; wl_proxy_set_tag((struct wl_proxy *) output->wl_output, &proxy_tag); wl_output_add_listener(output->wl_output, &output_listener, output); wl_list_insert(&(scr_driver->outputs), &output->link); scr_driver->screen_count_set( wl_list_length(&(scr_driver->outputs)) ); //fprintf(stderr, "wl_output: id=%d wl_output=%p screen_count()=%d\n", id, output->wl_output, Fl::screen_count()); } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { //fprintf(stderr, "registry_handle_global interface=%s\n", interface); scr_driver->xdg_wm_base = (struct xdg_wm_base *)wl_registry_bind(wl_registry, id, &xdg_wm_base_interface, 1); xdg_wm_base_add_listener(scr_driver->xdg_wm_base, &xdg_wm_base_listener, NULL); } else if (strcmp(interface, "gtk_shell1") == 0) { Fl_Wayland_Screen_Driver::compositor = Fl_Wayland_Screen_Driver::MUTTER; //fprintf(stderr, "Running the Mutter compositor\n"); scr_driver->seat->gtk_shell = (struct gtk_shell1*)wl_registry_bind(wl_registry, id, >k_shell1_interface, version); } else if (strcmp(interface, "weston_desktop_shell") == 0) { Fl_Wayland_Screen_Driver::compositor = Fl_Wayland_Screen_Driver::WESTON; //fprintf(stderr, "Running the Weston compositor\n"); } else if (strcmp(interface, "org_kde_plasma_shell") == 0) { Fl_Wayland_Screen_Driver::compositor = Fl_Wayland_Screen_Driver::KWIN; //fprintf(stderr, "Running the KWin compositor\n"); } else if (strncmp(interface, "zowl_mach_ipc", 13) == 0) { Fl_Wayland_Screen_Driver::compositor = Fl_Wayland_Screen_Driver::OWL; //fprintf(stderr, "Running the Owl compositor\n"); if (wl_list_length(&scr_driver->outputs) == 0) { Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)calloc(1, sizeof *output); output->id = 1; output->wld_scale = 1; output->gui_scale = 1.f; output->width = 1440; output->height = 900; output->done = true; wl_list_insert(&(scr_driver->outputs), &output->link); scr_driver->screen_count_set(1); } } else if (strcmp(interface, zwp_text_input_manager_v3_interface.name) == 0) { scr_driver->text_input_base = (struct zwp_text_input_manager_v3 *) wl_registry_bind(wl_registry, id, &zwp_text_input_manager_v3_interface, 1); //printf("scr_driver->text_input_base=%p version=%d\n",scr_driver->text_input_base,version); } } static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {//TODO to be tested Fl_Wayland_Screen_Driver::output *output, *tmp; //fprintf(stderr, "registry_handle_global_remove data=%p id=%u\n", data, name); Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); wl_list_for_each_safe(output, tmp, &(scr_driver->outputs), link) { // all screens if (output->id == name) { // the screen being removed again: Fl_X *xp = Fl_X::first; while (xp) { // all mapped windows struct wld_window *win = (struct wld_window*)xp->xid; struct Fl_Wayland_Window_Driver::surface_output *s_output; wl_list_for_each(s_output, &win->outputs, link) { if (output == s_output->output) { delete win->fl_win; goto again; } } xp = xp->next; } wl_list_remove(&output->link); scr_driver->screen_count_set( wl_list_length(&(scr_driver->outputs)) ); wl_output_destroy(output->wl_output); free(output); break; } } } static const struct wl_registry_listener registry_listener = { registry_handle_global, registry_handle_global_remove }; extern int fl_send_system_handlers(void *); static void wayland_socket_callback(int fd, struct wl_display *display) { if (fl_send_system_handlers(NULL)) return; struct pollfd fds = (struct pollfd) { fd, POLLIN, 0 }; do { if (wl_display_dispatch(display) == -1) { int err = wl_display_get_error(display); if (err == EPROTO) { const struct wl_interface *interface; int code = wl_display_get_protocol_error(display, &interface, NULL); Fl::fatal("Fatal error no %d in Wayland protocol: %s", code, interface->name); } else { Fl::fatal("Fatal error while communicating with the Wayland server: %s", strerror(errno)); } } } while (poll(&fds, 1, 0) > 0); } Fl_Wayland_Screen_Driver::Fl_Wayland_Screen_Driver() : Fl_Unix_Screen_Driver() { libdecor_context = NULL; seat = NULL; text_input_base = NULL; reset_cursor(); wl_registry = NULL; } static void sync_done(void *data, struct wl_callback *cb, uint32_t time) { // runs after all calls to registry_handle_global() *(struct wl_callback **)data = NULL; wl_callback_destroy(cb); // keep processing until output_done() has run for each screen Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); Fl_Wayland_Screen_Driver::output *output; wl_list_for_each(output, &scr_driver->outputs, link) { // each screen of the system while (!output->done) wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display); } } static const struct wl_callback_listener sync_listener = { sync_done }; static void do_atexit() { if (Fl_Wayland_Screen_Driver::wl_display) { wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); } } void Fl_Wayland_Screen_Driver::open_display_platform() { static bool beenHereDoneThat = false; if (beenHereDoneThat) return; beenHereDoneThat = true; if (!wl_display) { wl_display = wl_display_connect(NULL); if (!wl_display) { Fl::fatal("No Wayland connection\n"); } } //puts("Using Wayland backend"); wl_list_init(&outputs); wl_registry = wl_display_get_registry(wl_display); wl_registry_add_listener(wl_registry, ®istry_listener, NULL); struct wl_callback *registry_cb = wl_display_sync(wl_display); wl_callback_add_listener(registry_cb, &sync_listener, ®istry_cb); while (registry_cb) wl_display_dispatch(wl_display); Fl::add_fd(wl_display_get_fd(wl_display), FL_READ, (Fl_FD_Handler)wayland_socket_callback, wl_display); fl_create_print_window(); /* This is useful to avoid crash of the Wayland compositor after FLTK apps terminate in certain situations: - gnome-shell version < 44 (e.g. version 42.9) - focus set to "follow-mouse" See issue #821 for details. */ atexit(do_atexit); } void Fl_Wayland_Screen_Driver::close_display() { if (!Fl_Wayland_Screen_Driver::wl_display) return; wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); if (text_input_base) { disable_im(); zwp_text_input_manager_v3_destroy(text_input_base); text_input_base = NULL; } while (wl_list_length(&outputs) > 0) { Fl_Wayland_Screen_Driver::output *output; wl_list_for_each(output, &outputs, link) { wl_list_remove(&output->link); screen_count_set( wl_list_length(&outputs) ); if (output->wl_output) { #ifdef WL_OUTPUT_RELEASE_SINCE_VERSION if (wl_output_get_version(output->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION) wl_output_release(output->wl_output); else #endif wl_output_destroy(output->wl_output); } free(output); break; } } wl_subcompositor_destroy(wl_subcompositor); wl_subcompositor = NULL; wl_surface_destroy(seat->cursor_surface); seat->cursor_surface = NULL; if (seat->cursor_theme) { wl_cursor_theme_destroy(seat->cursor_theme); seat->cursor_theme = NULL; } wl_compositor_destroy(wl_compositor); wl_compositor = NULL; // wl_shm-related data if (Fl_Wayland_Graphics_Driver::current_pool) { struct Fl_Wayland_Graphics_Driver::wld_shm_pool_data *pool_data = (struct Fl_Wayland_Graphics_Driver::wld_shm_pool_data*) wl_shm_pool_get_user_data(Fl_Wayland_Graphics_Driver::current_pool); wl_shm_pool_destroy(Fl_Wayland_Graphics_Driver::current_pool); Fl_Wayland_Graphics_Driver::current_pool = NULL; /*int err = */munmap(pool_data->pool_memory, pool_data->pool_size); //printf("close_display munmap(%p)->%d\n", pool_data->pool_memory, err); free(pool_data); } wl_shm_destroy(wl_shm); wl_shm = NULL; if (seat->wl_keyboard) { if (seat->xkb_state) { xkb_state_unref(seat->xkb_state); seat->xkb_state = NULL; } if (seat->xkb_keymap) { xkb_keymap_unref(seat->xkb_keymap); seat->xkb_keymap = NULL; } wl_keyboard_destroy(seat->wl_keyboard); seat->wl_keyboard = NULL; } wl_pointer_destroy(seat->wl_pointer); seat->wl_pointer = NULL; if (seat->xkb_compose_state) { xkb_compose_state_unref(seat->xkb_compose_state); seat->xkb_compose_state = NULL; } if (seat->xkb_context) { xkb_context_unref(seat->xkb_context); seat->xkb_context = NULL; } if (seat->data_source) { wl_data_source_destroy(seat->data_source); seat->data_source = NULL; } wl_data_device_destroy(seat->data_device); seat->data_device = NULL; wl_data_device_manager_destroy(seat->data_device_manager); seat->data_device_manager = NULL; wl_seat_destroy(seat->wl_seat); seat->wl_seat = NULL; if (seat->name) free(seat->name); free(seat); seat = NULL; if (libdecor_context) { libdecor_unref(libdecor_context); libdecor_context = NULL; } xdg_wm_base_destroy(xdg_wm_base); xdg_wm_base = NULL; Fl_Wayland_Plugin *plugin = Fl_Wayland_Window_Driver::gl_plugin(); if (plugin) plugin->terminate(); Fl::remove_fd(wl_display_get_fd(Fl_Wayland_Screen_Driver::wl_display)); wl_registry_destroy(wl_registry); wl_registry = NULL; wl_display_disconnect(Fl_Wayland_Screen_Driver::wl_display); Fl_Wayland_Screen_Driver::wl_display = NULL; delete Fl_Display_Device::display_device()->driver(); delete Fl_Display_Device::display_device(); delete Fl::system_driver(); delete this; } static int workarea_xywh[4] = { -1, -1, -1, -1 }; void Fl_Wayland_Screen_Driver::init_workarea() { Fl_Wayland_Screen_Driver::output *output; wl_list_for_each(output, &outputs, link) { workarea_xywh[0] = output->x; // pixels workarea_xywh[1] = output->y; // pixels workarea_xywh[2] = output->width; // pixels workarea_xywh[3] = output->height; // pixels break; } } int Fl_Wayland_Screen_Driver::x() { if (!Fl_Wayland_Screen_Driver::wl_registry) open_display(); Fl_Wayland_Screen_Driver::output *output; wl_list_for_each(output, &outputs, link) { break; } return workarea_xywh[0] / (output->gui_scale * output->wld_scale); } int Fl_Wayland_Screen_Driver::y() { if (!Fl_Wayland_Screen_Driver::wl_registry) open_display(); Fl_Wayland_Screen_Driver::output *output; wl_list_for_each(output, &outputs, link) { break; } return workarea_xywh[1] / (output->gui_scale * output->wld_scale); } int Fl_Wayland_Screen_Driver::w() { if (!Fl_Wayland_Screen_Driver::wl_registry) open_display(); Fl_Wayland_Screen_Driver::output *output; wl_list_for_each(output, &outputs, link) { break; } return workarea_xywh[2] / (output->gui_scale * output->wld_scale); } int Fl_Wayland_Screen_Driver::h() { if (!Fl_Wayland_Screen_Driver::wl_registry) open_display(); Fl_Wayland_Screen_Driver::output *output; wl_list_for_each(output, &outputs, link) { break; } return workarea_xywh[3] / (output->gui_scale * output->wld_scale); } void Fl_Wayland_Screen_Driver::init() { if (!Fl_Wayland_Screen_Driver::wl_registry) open_display(); } void Fl_Wayland_Screen_Driver::screen_work_area(int &X, int &Y, int &W, int &H, int n) { if (num_screens < 0) init(); if (n < 0 || n >= num_screens) n = 0; if (n == 0) { // for the main screen, these return the work area X = Fl::x(); Y = Fl::y(); W = Fl::w(); H = Fl::h(); } else { // for other screens, work area is full screen, screen_xywh(X, Y, W, H, n); } } void Fl_Wayland_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n) { if (num_screens < 0) init(); if ((n < 0) || (n >= num_screens)) n = 0; if (num_screens > 0) { Fl_Wayland_Screen_Driver::output *output; int i = 0; wl_list_for_each(output, &outputs, link) { if (i++ == n) { // n'th screen of the system float s = output->gui_scale * output->wld_scale; X = output->x / s; Y = output->y / s; W = output->width / s; H = output->height / s; break; } } } } void Fl_Wayland_Screen_Driver::screen_dpi(float &h, float &v, int n) { if (num_screens < 0) init(); h = v = 0.0f; if (n >= 0 && n < num_screens) { Fl_Wayland_Screen_Driver::output *output; int i = 0; wl_list_for_each(output, &outputs, link) { if (i++ == n) { // n'th screen of the system h = output->dpi; v = output->dpi; break; } } } } // Implements fl_beep(). See documentation in src/fl_ask.cxx. void Fl_Wayland_Screen_Driver::beep(int type) { fprintf(stderr, "\007"); } void Fl_Wayland_Screen_Driver::flush() { if (Fl_Wayland_Screen_Driver::wl_display) { wl_display_flush(Fl_Wayland_Screen_Driver::wl_display); } } extern void fl_fix_focus(); // in Fl.cxx void Fl_Wayland_Screen_Driver::grab(Fl_Window* win) { if (win) { if (!Fl::grab()) { } Fl::grab_ = win; // FIXME: Fl::grab_ "should be private", but we need // a way to *set* the variable from the driver! } else { if (Fl::grab()) { // We must keep the grab in the non-EWMH fullscreen case Fl::grab_ = 0; // FIXME: Fl::grab_ "should be private", but we need // a way to *set* the variable from the driver! fl_fix_focus(); } } } static void set_selection_color(uchar r, uchar g, uchar b) { Fl::set_color(FL_SELECTION_COLOR,r,g,b); } static void getsyscolor(const char *key1, const char* key2, const char *arg, const char *defarg, void (*func)(uchar,uchar,uchar)) { uchar r, g, b; if (!arg) arg = defarg; if (!Fl::screen_driver()->parse_color(arg, r, g, b)) Fl::error("Unknown color: %s", arg); else func(r, g, b); } void Fl_Wayland_Screen_Driver::get_system_colors() { open_display(); const char* key1 = 0; if (Fl::first_window()) key1 = Fl::first_window()->xclass(); if (!key1) key1 = "fltk"; if (!bg2_set) getsyscolor("Text","background", fl_bg2, "#ffffff", Fl::background2); if (!fg_set) getsyscolor(key1, "foreground", fl_fg, "#000000", Fl::foreground); if (!bg_set) getsyscolor(key1, "background", fl_bg, "#c0c0c0", Fl::background); getsyscolor("Text", "selectBackground", 0, "#000080", set_selection_color); } Fl_RGB_Image *Fl_Wayland_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool ignore, bool *p_ignore) { struct wld_window* xid = win ? fl_wl_xid(win) : NULL; if (win && (!xid || !xid->buffer)) return NULL; struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer; if (win) buffer = &xid->buffer->draw_buffer; else { Fl_Image_Surface_Driver *dr = (Fl_Image_Surface_Driver*)Fl_Surface_Device::surface(); buffer = Fl_Wayland_Graphics_Driver::offscreen_buffer( dr->image_surface()->offscreen()); } float s = win ? Fl_Wayland_Window_Driver::driver(win)->wld_scale() * scale(win->screen_num()) : Fl_Surface_Device::surface()->driver()->scale(); int Xs, Ys, ws, hs; if (s == 1) { Xs = X; Ys = Y; ws = w; hs = h; } else { Xs = Fl_Scalable_Graphics_Driver::floor(X, s); Ys = Fl_Scalable_Graphics_Driver::floor(Y, s); ws = Fl_Scalable_Graphics_Driver::floor(X+w, s) - Xs; hs = Fl_Scalable_Graphics_Driver::floor(Y+h, s) - Ys; } if (ws == 0 || hs == 0) return NULL; uchar *data = new uchar[ws * hs * 3]; uchar *p = data, *q; for (int j = 0; j < hs; j++) { q = buffer->buffer + (j+Ys) * buffer->stride + 4 * Xs; for (int i = 0; i < ws; i++) { *p++ = *(q+2); // R *p++ = *(q+1); // G *p++ = *q; // B q += 4; } } Fl_RGB_Image *rgb = new Fl_RGB_Image(data, ws, hs, 3); rgb->alloc_array = 1; return rgb; } void Fl_Wayland_Screen_Driver::offscreen_size(Fl_Offscreen off_, int &width, int &height) { struct Fl_Wayland_Graphics_Driver::draw_buffer *off = Fl_Wayland_Graphics_Driver::offscreen_buffer(off_); width = off->width; height = off->data_size / off->stride; } float Fl_Wayland_Screen_Driver::scale(int n) { Fl_Wayland_Screen_Driver::output *output; int i = 0; wl_list_for_each(output, &outputs, link) { if (i++ == n) break; } return output->gui_scale; } void Fl_Wayland_Screen_Driver::scale(int n, float f) { Fl_Wayland_Screen_Driver::output *output; int i = 0; wl_list_for_each(output, &outputs, link) { if (i++ == n) { output->gui_scale = f; return; } } } void Fl_Wayland_Screen_Driver::set_cursor() { do_set_cursor(seat); } struct wl_cursor *Fl_Wayland_Screen_Driver::default_cursor() { return seat->default_cursor; } void Fl_Wayland_Screen_Driver::default_cursor(struct wl_cursor *cursor) { seat->default_cursor = cursor; do_set_cursor(seat); } struct wl_cursor *Fl_Wayland_Screen_Driver::cache_cursor(const char *cursor_name) { return wl_cursor_theme_get_cursor(seat->cursor_theme, cursor_name); } void Fl_Wayland_Screen_Driver::reset_cursor() { for (int i = 0; i < cursor_count; i++) xc_cursor[i] = NULL; } uint32_t Fl_Wayland_Screen_Driver::get_serial() { return seat->serial; } struct wl_seat*Fl_Wayland_Screen_Driver::get_wl_seat() { return seat->wl_seat; } char *Fl_Wayland_Screen_Driver::get_seat_name() { return seat->name; } struct xkb_keymap *Fl_Wayland_Screen_Driver::get_xkb_keymap() { return seat->xkb_keymap; } int Fl_Wayland_Screen_Driver::get_mouse(int &xx, int &yy) { open_display(); xx = Fl::e_x_root; yy = Fl::e_y_root; if (!seat->pointer_focus) return 0; Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(seat->pointer_focus); if (!win) return 0; int snum = Fl_Window_Driver::driver(win)->screen_num(); //printf("get_mouse(%dx%d)->%d\n", xx, yy, snum); return snum; } void Fl_Wayland_Screen_Driver::set_spot(int font, int height, int x, int y, int w, int h, Fl_Window *win) { Fl_Wayland_Screen_Driver::insertion_point_location(x, y, height); } void Fl_Wayland_Screen_Driver::reset_spot() { Fl::compose_state = 0; Fl_Wayland_Screen_Driver::next_marked_length = 0; Fl_Wayland_Screen_Driver::insertion_point_location_is_valid = false; } void Fl_Wayland_Screen_Driver::display(const char *d) { if (d && !wl_registry) { // if display was opened, it's too late if (wl_display) { // only the wl_display_connect() call was done, redo it because the target // Wayland compositor may be different wl_display_disconnect(wl_display); } wl_display = wl_display_connect(d); if (!wl_display) { fprintf(stderr, "Error: '%s' is not an active Wayland socket\n", d); exit(1); } } } void *Fl_Wayland_Screen_Driver::control_maximize_button(void *data) { // The code below aims at removing the calling window's fullscreen button // while dialog runs. Unfortunately, it doesn't work with some X11 window managers // (e.g., KDE, xfce) because the button goes away but doesn't come back, // so we move this code to a virtual member function. // Noticeably, this code works OK under Wayland. struct win_dims { Fl_Widget_Tracker *tracker; int minw, minh, maxw, maxh; struct win_dims *next; }; if (!data) { // this call turns each decorated window's maximize button off struct win_dims *first_dim = NULL; // consider all bordered, top-level FLTK windows Fl_Window *win = Fl::first_window(); while (win) { if (!win->parent() && win->border() && !( ((struct wld_window*)Fl_X::flx(win)->xid)->state & LIBDECOR_WINDOW_STATE_MAXIMIZED) ) { win_dims *dim = new win_dims; dim->tracker = new Fl_Widget_Tracker(win); win->get_size_range(&dim->minw, &dim->minh, &dim->maxw, &dim->maxh, NULL, NULL, NULL); //make win un-resizable win->size_range(win->w(), win->h(), win->w(), win->h()); dim->next = first_dim; first_dim = dim; } win = Fl::next_window(win); } return first_dim; } else { // this call returns each decorated window's maximize button to its previous state win_dims *first_dim = (win_dims *)data; while (first_dim) { win_dims *dim = first_dim; //give back win its resizing parameters if (dim->tracker->exists()) { Fl_Window *win = (Fl_Window*)dim->tracker->widget(); win->size_range(dim->minw, dim->minh, dim->maxw, dim->maxh); } first_dim = dim->next; delete dim->tracker; delete dim; } return NULL; } } int Fl_Wayland_Screen_Driver::poll_or_select_with_delay(double time_to_wait) { if (wl_display_dispatch_pending(wl_display) > 0) return 1; return Fl_Unix_Screen_Driver::poll_or_select_with_delay(time_to_wait); } // like Fl_Wayland_Screen_Driver::poll_or_select_with_delay(0.0) except no callbacks are done: int Fl_Wayland_Screen_Driver::poll_or_select() { int ret = wl_display_prepare_read(wl_display); if (ret == 0) wl_display_cancel_read(wl_display); else return 1; return Fl_Unix_Screen_Driver::poll_or_select(); } int Fl_Wayland_Screen_Driver::event_key(int k) { if (k >= 'A' && k <= 'Z') k += 32; return (search_int_vector(key_vector, k) >= 0); } int Fl_Wayland_Screen_Driver::get_key(int k) { return event_key(k); } float Fl_Wayland_Screen_Driver::base_scale(int numscreen) { const char *p; float factor = 1; if ((p = fl_getenv("FLTK_SCALING_FACTOR"))) { sscanf(p, "%f", &factor); } return factor; } struct wl_display *fl_wl_display() { return Fl_Wayland_Screen_Driver::wl_display; } fltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H0000644000175000017500000000376315004135251024077 0ustar albrechtalbrecht// // Class Fl_Wayland_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_WAYLAND_GL_WINDOW_DRIVER_H #define FL_WAYLAND_GL_WINDOW_DRIVER_H #include #if HAVE_GL #include "../../Fl_Gl_Window_Driver.H" #include #include #include class Fl_Wayland_Gl_Window_Driver : public Fl_Gl_Window_Driver { friend Fl_Gl_Window_Driver* Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *); friend class Fl_Wayland_Gl_Plugin; private: static EGLDisplay egl_display; struct wl_egl_window *egl_window; EGLSurface egl_surface; Fl_Wayland_Gl_Window_Driver(Fl_Gl_Window *win); float pixels_per_unit() FL_OVERRIDE; void make_current_before() FL_OVERRIDE; int mode_(int m, const int *a) FL_OVERRIDE; void swap_buffers() FL_OVERRIDE; void resize(int is_a_resize, int w, int h) FL_OVERRIDE; char swap_type() FL_OVERRIDE; void swap_interval(int) FL_OVERRIDE; int swap_interval() const FL_OVERRIDE; Fl_Gl_Choice *find(int m, const int *alistp) FL_OVERRIDE; GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) FL_OVERRIDE; void set_gl_context(Fl_Window* w, GLContext context) FL_OVERRIDE; void delete_gl_context(GLContext) FL_OVERRIDE; void make_overlay_current() FL_OVERRIDE; void redraw_overlay() FL_OVERRIDE; void gl_start() FL_OVERRIDE; void gl_visual(Fl_Gl_Choice *c) FL_OVERRIDE; void init(); public: //virtual bool need_scissor() { return true; } // CONTROL_LEAKING_SUB_GL_WINDOWS //void apply_scissor(); // CONTROL_LEAKING_SUB_GL_WINDOWS }; #endif // HAVE_GL #endif // FL_WAYLAND_GL_WINDOW_DRIVER_H fltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx0000644000175000017500000000357615004135251025205 0ustar albrechtalbrecht// // Copy-to-clipboard code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Wayland_Copy_Surface_Driver.H" #include #include "Fl_Wayland_Graphics_Driver.H" #include "Fl_Wayland_Screen_Driver.H" #include "Fl_Wayland_Window_Driver.H" Fl_Wayland_Copy_Surface_Driver::Fl_Wayland_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) { float os_scale = Fl_Graphics_Driver::default_driver().scale(); int d = 1; if (Fl::first_window()) { d = Fl_Wayland_Window_Driver::driver(Fl::first_window())->wld_scale(); } img_surf = new Fl_Image_Surface(int(w * os_scale) * d, int(h * os_scale) * d); driver(img_surf->driver()); driver()->scale(d * os_scale); } Fl_Wayland_Copy_Surface_Driver::~Fl_Wayland_Copy_Surface_Driver() { Fl_RGB_Image *rgb = img_surf->image(); Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); scr_driver->copy_image(rgb->array, rgb->data_w(), rgb->data_h()); delete rgb; delete img_surf; driver(NULL); } void Fl_Wayland_Copy_Surface_Driver::set_current() { Fl_Surface_Device::set_current(); Fl_Cairo_Graphics_Driver *dr = (Fl_Cairo_Graphics_Driver*)driver(); if (!dr->cr()) dr->set_cairo((cairo_t*)img_surf->offscreen()); } void Fl_Wayland_Copy_Surface_Driver::translate(int x, int y) { ((Fl_Wayland_Graphics_Driver*)driver())->ps_translate(x, y); } void Fl_Wayland_Copy_Surface_Driver::untranslate() { ((Fl_Wayland_Graphics_Driver*)driver())->ps_untranslate(); } fltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H0000644000175000017500000001531215004135251023416 0ustar albrechtalbrecht// // Definition of the Wayland Screen interface // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Wayland_Screen_Driver.H \brief Definition of Wayland Screen interface */ #ifndef FL_WAYLAND_SCREEN_DRIVER_H #define FL_WAYLAND_SCREEN_DRIVER_H #include "../Unix/Fl_Unix_Screen_Driver.H" #include class Fl_Window; class Fl_Wayland_Screen_Driver : public Fl_Unix_Screen_Driver { private: static int insertion_point_x; static int insertion_point_y; static int insertion_point_width; static int insertion_point_height; static bool insertion_point_location_is_valid; public: // type definitions typedef enum {unspecified, MUTTER, WESTON, KWIN, OWL} compositor_name; struct seat { struct wl_seat *wl_seat; struct wl_pointer *wl_pointer; struct wl_keyboard *wl_keyboard; uint32_t keyboard_enter_serial; struct wl_surface *keyboard_surface; struct wl_list pointer_outputs; struct wl_cursor_theme *cursor_theme; struct wl_cursor *default_cursor; struct wl_surface *cursor_surface; struct wl_surface *pointer_focus; int pointer_scale; uint32_t serial; uint32_t pointer_enter_serial; struct wl_data_device_manager *data_device_manager; struct wl_data_device *data_device; struct wl_data_source *data_source; struct xkb_state *xkb_state; struct xkb_context *xkb_context; struct xkb_keymap *xkb_keymap; struct xkb_compose_state *xkb_compose_state; char *name; struct zwp_text_input_v3 *text_input; struct gtk_shell1 *gtk_shell; }; struct output { // one record for each screen uint32_t id; int x, y; // logical position of screen int width; // in pixels int height; // in pixels float dpi; struct wl_output *wl_output; int wld_scale; // Wayland scale factor float gui_scale; // FLTK scale factor bool done; struct wl_list link; }; enum cursor_shapes {arrow = 0, wait, insert, hand, help, cross, move, north, south, west, east, north_south, west_east, south_west, south_east, north_east, north_west, nesw, nwse}; static const int cursor_count = nwse + 1; // nber of elements of 'enum cursor_shapes' // static member variables static FL_EXPORT struct wl_display *wl_display; static const struct wl_data_device_listener *p_data_device_listener; // next length of marked text after current marked text will have been replaced static int next_marked_length; static compositor_name compositor; // identifies the used Wayland compositor // static member functions static void insertion_point_location(int x, int y, int height); static bool insertion_point_location(int *px, int *py, int *pwidth, int *pheight); static bool own_output(struct wl_output *output); static void do_set_cursor(struct Fl_Wayland_Screen_Driver::seat *, struct wl_cursor *wl_cursor = NULL); // member variables struct wl_cursor *xc_cursor[cursor_count]; // one for each element of enum cursor_shapes struct wl_registry *wl_registry; struct wl_compositor *wl_compositor; struct wl_subcompositor *wl_subcompositor; struct wl_shm *wl_shm; struct seat *seat; struct wl_list outputs; // linked list of struct output records for all screens in system struct libdecor *libdecor_context; struct xdg_wm_base *xdg_wm_base; struct zwp_text_input_manager_v3 *text_input_base; // constructor Fl_Wayland_Screen_Driver(); // overridden functions from parent class Fl_Screen_Driver APP_SCALING_CAPABILITY rescalable() FL_OVERRIDE { return PER_SCREEN_APP_SCALING; } float scale(int n) FL_OVERRIDE; void scale(int n, float f) FL_OVERRIDE; // --- screen configuration void init() FL_OVERRIDE; int x() FL_OVERRIDE; int y() FL_OVERRIDE; int w() FL_OVERRIDE; int h() FL_OVERRIDE; void screen_xywh(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; void screen_dpi(float &h, float &v, int n=0) FL_OVERRIDE; void screen_work_area(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; // --- audible output void beep(int type) FL_OVERRIDE; // --- global events void flush() FL_OVERRIDE; void grab(Fl_Window* win) FL_OVERRIDE; // --- global colors void get_system_colors() FL_OVERRIDE; // this one is in fl_wayland_clipboard_dnd.cxx int dnd(int unused) FL_OVERRIDE; int compose(int &del) FL_OVERRIDE; void compose_reset() FL_OVERRIDE; Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins) FL_OVERRIDE; int get_mouse(int &x, int &y) FL_OVERRIDE; void open_display_platform() FL_OVERRIDE; void close_display() FL_OVERRIDE; void display(const char *d) FL_OVERRIDE; // --- compute dimensions of an Fl_Offscreen void offscreen_size(Fl_Offscreen o, int &width, int &height) FL_OVERRIDE; int has_marked_text() const FL_OVERRIDE; // --- clipboard operations // this one is in fl_wayland_clipboard_dnd.cxx void copy(const char *stuff, int len, int clipboard, const char *type) FL_OVERRIDE; // this one is in fl_wayland_clipboard_dnd.cxx void paste(Fl_Widget &receiver, int clipboard, const char *type) FL_OVERRIDE; // this one is in fl_wayland_clipboard_dnd.cxx int clipboard_contains(const char *type) FL_OVERRIDE; void set_spot(int font, int height, int x, int y, int w, int h, Fl_Window *win) FL_OVERRIDE; void reset_spot() FL_OVERRIDE; void *control_maximize_button(void *data) FL_OVERRIDE; int event_key(int k) FL_OVERRIDE; int get_key(int k) FL_OVERRIDE; void enable_im() FL_OVERRIDE; void disable_im() FL_OVERRIDE; bool screen_boundaries_known() FL_OVERRIDE { return false; } float base_scale(int numscreen) FL_OVERRIDE; // overridden functions from parent class Fl_Unix_Screen_Driver int poll_or_select_with_delay(double time_to_wait) FL_OVERRIDE; int poll_or_select() FL_OVERRIDE; // Wayland-specific member functions void screen_count_set(int count) {num_screens = count;} void reset_cursor(); // this one is in fl_wayland_clipboard_dnd.cxx void copy_image(const unsigned char* data, int W, int H); void init_workarea(); void set_cursor(); struct wl_cursor *default_cursor(); void default_cursor(struct wl_cursor *cursor); struct wl_cursor *cache_cursor(const char *cursor_name); uint32_t get_serial(); struct wl_seat *get_wl_seat(); char *get_seat_name(); struct xkb_keymap *get_xkb_keymap(); }; #endif // FL_WAYLAND_SCREEN_DRIVER_H fltk-1.4.3/src/drivers/Wayland/fl_wayland_platform_init.cxx0000644000175000017500000001033715004135251024250 0ustar albrechtalbrecht// // Wayland-specific code to initialize wayland support. // // Copyright 2022-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Wayland_Copy_Surface_Driver.H" #include "Fl_Wayland_Graphics_Driver.H" #include "Fl_Wayland_Screen_Driver.H" #include "../Unix/Fl_Unix_System_Driver.H" #include "Fl_Wayland_Window_Driver.H" #include "Fl_Wayland_Image_Surface_Driver.H" #ifdef FLTK_USE_X11 # include "../Xlib/Fl_Xlib_Copy_Surface_Driver.H" # include "../Cairo/Fl_X11_Cairo_Graphics_Driver.H" # include "../X11/Fl_X11_Screen_Driver.H" # include "../X11/Fl_X11_Window_Driver.H" # include "../Xlib/Fl_Xlib_Image_Surface_Driver.H" #endif #include #include #include #ifdef FLTK_USE_X11 static bool attempt_wayland() { if (Fl_Wayland_Screen_Driver::wl_display) return true; static bool first = true; static bool disable_wl = false; if (first) { // get the value if it exists and cache it void *sym = Fl_Posix_System_Driver::dlopen_or_dlsym(NULL, "fl_disable_wayland"); if (sym) { disable_wl = *(bool *)sym; // printf("fl_disable_wayland = %s\n", disable_wl ? "true" : "false"); } first = false; } if (disable_wl) return false; const char *backend = ::getenv("FLTK_BACKEND"); // fprintf(stderr, "FLTK_BACKEND='%s'\n", backend ? backend : ""); if (backend && strcmp(backend, "x11") == 0) { return false; } if (backend && strcmp(backend, "wayland") == 0) { Fl_Wayland_Screen_Driver::wl_display = wl_display_connect(NULL); if (!Fl_Wayland_Screen_Driver::wl_display) { fprintf(stderr, "Error: no Wayland connection available, FLTK_BACKEND='wayland'\n"); exit(1); } return true; } if (!backend) { // env var XDG_RUNTIME_DIR is required for Wayland const char *xdgrt = ::getenv("XDG_RUNTIME_DIR"); if (xdgrt) { // is a Wayland connection available ? Fl_Wayland_Screen_Driver::wl_display = wl_display_connect(NULL); if (Fl_Wayland_Screen_Driver::wl_display) { // Yes, use Wayland drivers // puts("using wayland"); return true; } } // no Wayland connection or environment variable XDG_RUNTIME_DIR not set, // falling back to X11 return false; } fprintf(stderr, "Error: unexpected value of FLTK_BACKEND: '%s'\n", backend); exit(1); return false; } #endif // FLTK_USE_X11 Fl_System_Driver *Fl_System_Driver::newSystemDriver() { return new Fl_Unix_System_Driver(); } Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() { #ifdef FLTK_USE_X11 if (!attempt_wayland()) return new Fl_X11_Cairo_Graphics_Driver(); #endif return new Fl_Wayland_Graphics_Driver(); } Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int h) { #ifdef FLTK_USE_X11 if (!Fl_Wayland_Screen_Driver::wl_display) return new Fl_Xlib_Copy_Surface_Driver(w, h); #endif return new Fl_Wayland_Copy_Surface_Driver(w, h); } Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() { if (!Fl_Screen_Driver::system_driver) Fl::system_driver(); #ifdef FLTK_USE_X11 if (attempt_wayland()) { return new Fl_Wayland_Screen_Driver(); } Fl_X11_Screen_Driver *d = new Fl_X11_Screen_Driver(); for (int i = 0; i < MAX_SCREENS; i++) d->screens[i].scale = 1; d->current_xft_dpi = 0.; // means the value of the Xft.dpi resource is still unknown return d; #else return new Fl_Wayland_Screen_Driver(); #endif } Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w) { #ifdef FLTK_USE_X11 if (!attempt_wayland()) return new Fl_X11_Window_Driver(w); #endif return new Fl_Wayland_Window_Driver(w); } Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off) { #ifdef FLTK_USE_X11 if (!attempt_wayland()) return new Fl_Xlib_Image_Surface_Driver(w, h, high_res, off); #endif return new Fl_Wayland_Image_Surface_Driver(w, h, high_res, off); } fltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx0000644000175000017500000003100215004135251024344 0ustar albrechtalbrecht// // Implementation of the Wayland graphics driver. // // Copyright 2021-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Wayland_Graphics_Driver.H" #include "Fl_Wayland_Screen_Driver.H" #include "Fl_Wayland_Window_Driver.H" #include #include #include // for close() #include #include // for strerror() #include extern "C" { # include "../../../libdecor/src/os-compatibility.h" // for libdecor_os_create_anonymous_file() } // used by create_shm_buffer and do_buffer_release struct wl_shm_pool *Fl_Wayland_Graphics_Driver::current_pool = NULL; static void do_buffer_release(struct Fl_Wayland_Graphics_Driver::wld_buffer *); static void buffer_release_listener(void *user_data, struct wl_buffer *wl_buffer) { struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer = (struct Fl_Wayland_Graphics_Driver::wld_buffer*)user_data; buffer->in_use = false; if (buffer->released) do_buffer_release(buffer); } static const struct wl_buffer_listener buffer_listener = { buffer_release_listener }; void Fl_Wayland_Graphics_Driver::create_shm_buffer(Fl_Wayland_Graphics_Driver::wld_buffer *buffer) { int width = buffer->draw_buffer.width; int stride = buffer->draw_buffer.stride; int height = buffer->draw_buffer.data_size / stride; const size_t default_pool_size = 10000000; // larger pools are possible if needed int chunk_offset = 0; // offset to start of available memory in pool struct wld_shm_pool_data *pool_data = current_pool ? // data record attached to current pool (struct wld_shm_pool_data *)wl_shm_pool_get_user_data(current_pool) : NULL; size_t pool_size = current_pool ? pool_data->pool_size : default_pool_size; // current pool size if (current_pool && !wl_list_empty(&pool_data->buffers)) { // last wld_buffer created from current pool struct wld_buffer *record = wl_container_of(pool_data->buffers.next, record, link); chunk_offset = ((char*)record->data - pool_data->pool_memory) + record->draw_buffer.data_size; } if (!current_pool || chunk_offset + buffer->draw_buffer.data_size > pool_size) { // if true, a new pool is needed if (current_pool && wl_list_empty(&pool_data->buffers)) { wl_shm_pool_destroy(current_pool); /*int err = */munmap(pool_data->pool_memory, pool_data->pool_size); // printf("create_shm_buffer munmap(%p)->%d\n", pool_data->pool_memory, err); free(pool_data); } chunk_offset = 0; pool_size = default_pool_size; if (buffer->draw_buffer.data_size > pool_size) pool_size = 2 * buffer->draw_buffer.data_size; // a larger pool is needed int fd = libdecor_os_create_anonymous_file(pool_size); if (fd < 0) { Fl::fatal("libdecor_os_create_anonymous_file failed: %s\n", strerror(errno)); } pool_data = (struct wld_shm_pool_data*)calloc(1, sizeof(struct wld_shm_pool_data)); pool_data->pool_memory = (char*)mmap(NULL, pool_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (pool_data->pool_memory == MAP_FAILED) { close(fd); Fl::fatal("mmap failed: %s\n", strerror(errno)); } Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); current_pool = wl_shm_create_pool(scr_driver->wl_shm, fd, (int32_t)pool_size); close(fd); // does not prevent the mmap'ed memory from being used //printf("wl_shm_create_pool %p size=%lu\n",pool_data->pool_memory , pool_size); pool_data->pool_size = pool_size; wl_list_init(&pool_data->buffers); wl_shm_pool_set_user_data(current_pool, pool_data); } buffer->wl_buffer = wl_shm_pool_create_buffer(current_pool, chunk_offset, width, height, stride, wld_format); wl_buffer_add_listener(buffer->wl_buffer, &buffer_listener, buffer); // add this buffer to head of list of current pool's buffers wl_list_insert(&pool_data->buffers, &buffer->link); buffer->shm_pool = current_pool; buffer->data = (void*)(pool_data->pool_memory + chunk_offset); //fprintf(stderr, "last=%p chunk_offset=%d ", pool_data->buffers.next, chunk_offset); //fprintf(stderr, "create_shm_buffer: %dx%d = %d\n", width, height, size); } struct Fl_Wayland_Graphics_Driver::wld_buffer * Fl_Wayland_Graphics_Driver::create_wld_buffer(int width, int height, bool with_shm) { struct wld_buffer *buffer = (struct wld_buffer*)calloc(1, sizeof(struct wld_buffer)); int stride = cairo_format_stride_for_width(cairo_format, width); cairo_init(&buffer->draw_buffer, width, height, stride, cairo_format); buffer->draw_buffer_needs_commit = true; if (with_shm) create_shm_buffer(buffer); return buffer; } // used to support both normal and progressive drawing and for top-level GL windows static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) { struct wld_window *window = (struct wld_window *)data; wl_callback_destroy(cb); window->frame_cb = NULL; if (window->buffer && window->buffer->draw_buffer_needs_commit) { Fl_Wayland_Graphics_Driver::buffer_commit(window); } } static const struct wl_callback_listener surface_frame_listener = { .done = surface_frame_done, }; const struct wl_callback_listener *Fl_Wayland_Graphics_Driver::p_surface_frame_listener = &surface_frame_listener; // copy pixels in region r from the Cairo surface to the Wayland buffer static void copy_region(struct wld_window *window, cairo_region_t *r) { struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer = window->buffer; float f = Fl::screen_scale(window->fl_win->screen_num()); int d = Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale(); int count = cairo_region_num_rectangles(r); cairo_rectangle_int_t rect; for (int i = 0; i < count; i++) { cairo_region_get_rectangle(r, i, &rect); int left = d * int(rect.x * f); int top = d * int(rect.y * f); int right = d * ceil((rect.x + rect.width) * f); if (right > d * int(window->fl_win->w() * f)) right = d * int(window->fl_win->w() * f); int width = right - left; int bottom = d * ceil((rect.y + rect.height) * f); if (bottom > d * int(window->fl_win->h() * f)) bottom = d * int(window->fl_win->h() * f); int height = bottom - top; int offset = top * buffer->draw_buffer.stride + 4 * left; int W4 = 4 * width; for (int l = 0; l < height; l++) { if (offset + W4 >= (int)buffer->draw_buffer.data_size) { W4 = buffer->draw_buffer.data_size - offset; if (W4 <= 0) break; } memcpy((uchar*)buffer->data + offset, buffer->draw_buffer.buffer + offset, W4); offset += buffer->draw_buffer.stride; } wl_surface_damage_buffer(window->wl_surface, left, top, width, height); } } void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window, cairo_region_t *r) { if (!window->buffer->wl_buffer) create_shm_buffer(window->buffer); cairo_surface_t *surf = cairo_get_target(window->buffer->draw_buffer.cairo_); cairo_surface_flush(surf); if (r) copy_region(window, r); else { memcpy(window->buffer->data, window->buffer->draw_buffer.buffer, window->buffer->draw_buffer.data_size); wl_surface_damage_buffer(window->wl_surface, 0, 0, 1000000, 1000000); } window->buffer->in_use = true; wl_surface_attach(window->wl_surface, window->buffer->wl_buffer, 0, 0); wl_surface_set_buffer_scale( window->wl_surface, Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale() ); if (!window->covered) { // see issue #878 window->frame_cb = wl_surface_frame(window->wl_surface); wl_callback_add_listener(window->frame_cb, p_surface_frame_listener, window); } wl_surface_commit(window->wl_surface); window->buffer->draw_buffer_needs_commit = false; } void Fl_Wayland_Graphics_Driver::cairo_init(struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer, int width, int height, int stride, cairo_format_t format) { buffer->data_size = stride * height; buffer->stride = stride; buffer->buffer = new uchar[buffer->data_size]; buffer->width = width; cairo_surface_t *surf = cairo_image_surface_create_for_data(buffer->buffer, format, width, height, stride); if (cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS) { Fl::fatal("Can't create Cairo surface with cairo_image_surface_create_for_data()\n"); return; } buffer->cairo_ = cairo_create(surf); cairo_status_t err; if ((err = cairo_status(buffer->cairo_)) != CAIRO_STATUS_SUCCESS) { Fl::fatal("Cairo error during cairo_create() %s\n", cairo_status_to_string(err)); return; } cairo_surface_destroy(surf); memset(buffer->buffer, 0, buffer->data_size); // useful for transparent windows cairo_set_source_rgba(buffer->cairo_, .0, .0, .0, 1.0); // Black default color cairo_save(buffer->cairo_); } // runs when buffer->in_use is false and buffer->released is true static void do_buffer_release(struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer) { struct wl_shm_pool *my_pool = buffer->shm_pool; if (buffer->wl_buffer) { struct Fl_Wayland_Graphics_Driver::wld_shm_pool_data *pool_data = (struct Fl_Wayland_Graphics_Driver::wld_shm_pool_data*) wl_shm_pool_get_user_data(my_pool); wl_buffer_destroy(buffer->wl_buffer); // remove wld_buffer from list of pool's buffers wl_list_remove(&buffer->link); if (wl_list_empty(&pool_data->buffers) && my_pool != Fl_Wayland_Graphics_Driver::current_pool) { // all buffers from pool are gone wl_shm_pool_destroy(my_pool); /*int err = */munmap(pool_data->pool_memory, pool_data->pool_size); //printf("do_buffer_release munmap(%p)->%d\n", pool_data->pool_memory, err); free(pool_data); } } free(buffer); } void Fl_Wayland_Graphics_Driver::buffer_release(struct wld_window *window) { if (window->buffer && !window->buffer->released) { window->buffer->released = true; if (window->frame_cb) { wl_callback_destroy(window->frame_cb); window->frame_cb = NULL; } delete[] window->buffer->draw_buffer.buffer; window->buffer->draw_buffer.buffer = NULL; cairo_destroy(window->buffer->draw_buffer.cairo_); if (!window->buffer->in_use) do_buffer_release(window->buffer); window->buffer = NULL; } } // this refers to the same memory layout for pixel data as does CAIRO_FORMAT_ARGB32 const uint32_t Fl_Wayland_Graphics_Driver::wld_format = WL_SHM_FORMAT_ARGB8888; void Fl_Wayland_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen src, int srcx, int srcy) { // draw portion srcx,srcy,w,h of osrc to position x,y (top-left) of // the graphics driver's surface cairo_matrix_t matrix; cairo_get_matrix(cairo_, &matrix); double s = matrix.xx; cairo_save(cairo_); cairo_rectangle(cairo_, x - 0.5, y - 0.5, w, h); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_clip(cairo_); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); cairo_surface_t *surf = cairo_get_target((cairo_t *)src); cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf); cairo_set_source(cairo_, pat); cairo_matrix_init_scale(&matrix, s, s); cairo_matrix_translate(&matrix, -(x - srcx), -(y - srcy)); cairo_pattern_set_matrix(pat, &matrix); cairo_paint(cairo_); cairo_pattern_destroy(pat); cairo_restore(cairo_); surface_needs_commit(); } const cairo_user_data_key_t Fl_Wayland_Graphics_Driver::key = {}; struct Fl_Wayland_Graphics_Driver::draw_buffer* Fl_Wayland_Graphics_Driver::offscreen_buffer(Fl_Offscreen offscreen) { return (struct draw_buffer*)cairo_get_user_data((cairo_t*)offscreen, &key); } Fl_Image_Surface *Fl_Wayland_Graphics_Driver::custom_offscreen(int w, int h, struct Fl_Wayland_Graphics_Driver::wld_buffer **p_off) { struct wld_buffer *off = create_wld_buffer(w, h); *p_off = off; cairo_set_user_data(off->draw_buffer.cairo_, &key, &off->draw_buffer, NULL); return new Fl_Image_Surface(w, h, 0, (Fl_Offscreen)off->draw_buffer.cairo_); } void Fl_Wayland_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height) { Fl_Graphics_Driver::cache_size(img, width, height); width *= wld_scale; height *= wld_scale; } fltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx0000644000175000017500000025715615004135251024077 0ustar albrechtalbrecht// // Implementation of the Wayland window driver. // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Wayland_Window_Driver.H" #include "Fl_Wayland_Screen_Driver.H" #include "Fl_Wayland_Graphics_Driver.H" #include #include #include "../../../libdecor/build/fl_libdecor.h" #include "xdg-shell-client-protocol.h" #include "gtk-shell-client-protocol.h" #include #include #include #include #include #include #include #include #include // for ceil() #include // for pid_t #include // for getpid() struct cursor_image { // as in wayland-cursor.c of the Wayland project source code struct wl_cursor_image image; struct wl_cursor_theme *theme; struct wl_buffer *buffer; int offset; /* data offset of this image in the shm pool */ }; extern "C" { # include "../../../libdecor/src/libdecor-plugin.h" uchar *fl_libdecor_titlebar_buffer(struct libdecor_frame *frame, int *w, int *h, int *stride); } #define fl_max(a,b) ((a) > (b) ? (a) : (b)) #define fl_min(a,b) ((a) < (b) ? (a) : (b)) #if !defined(FLTK_USE_X11) Window fl_window = 0; #endif struct wld_window *Fl_Wayland_Window_Driver::wld_window = NULL; bool Fl_Wayland_Window_Driver::new_popup = false; // to support tall menu buttons // A menutitle to be mapped later as the child of a menuwindow Fl_Window *Fl_Wayland_Window_Driver::previous_floatingtitle = NULL; Fl_Wayland_Window_Driver::Fl_Wayland_Window_Driver(Fl_Window *win) : Fl_Window_Driver(win) { shape_data_ = NULL; standard_cursor_ = FL_CURSOR_DEFAULT; in_handle_configure = false; screen_num_ = -1; gl_start_support_ = NULL; subRect_ = NULL; is_popup_window_ = false; can_expand_outside_parent_ = false; } void Fl_Wayland_Window_Driver::delete_cursor( struct Fl_Wayland_Window_Driver::custom_cursor *custom, bool delete_rgb) { struct wl_cursor *wl_cursor = custom->wl_cursor; struct cursor_image *new_image = (struct cursor_image*)wl_cursor->images[0]; struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen = (struct Fl_Wayland_Graphics_Driver::wld_buffer *) wl_buffer_get_user_data(new_image->buffer); struct wld_window fake_xid; memset(&fake_xid, 0, sizeof(fake_xid)); fake_xid.buffer = offscreen; Fl_Wayland_Graphics_Driver::buffer_release(&fake_xid); free(new_image); free(wl_cursor->images); free(wl_cursor->name); free(wl_cursor); Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); if (scr_driver->default_cursor() == wl_cursor) { scr_driver->default_cursor(scr_driver->xc_cursor[Fl_Wayland_Screen_Driver::arrow]); } if (delete_rgb) delete custom->rgb; delete custom; } Fl_Wayland_Window_Driver::~Fl_Wayland_Window_Driver() { if (shape_data_) { cairo_surface_t *surface; cairo_pattern_get_surface(shape_data_->mask_pattern_, &surface); uchar *data = cairo_image_surface_get_data(surface); cairo_pattern_destroy(shape_data_->mask_pattern_); delete[] data; delete shape_data_; } if (subRect_) delete subRect_; if (gl_start_support_) { // occurs only if gl_start/gl_finish was used gl_plugin()->destroy(gl_start_support_); } } void Fl_Wayland_Window_Driver::decorated_win_size(int &w, int &h) { Fl_Window *win = pWindow; w = win->w(); h = win->h(); if (!win->shown() || win->parent() || !win->border() || !win->visible()) return; int X, titlebar_height; libdecor_frame_translate_coordinate(fl_wl_xid(win)->frame, 0, 0, &X, &titlebar_height); //printf("titlebar_height=%d\n",titlebar_height); h = win->h() + ceil(titlebar_height / Fl::screen_scale(win->screen_num())); } int Fl_Wayland_Window_Driver::decorated_h() { int w, h; decorated_win_size(w, h); return h; } int Fl_Wayland_Window_Driver::decorated_w() { int w, h; decorated_win_size(w, h); return w; } struct xdg_toplevel *Fl_Wayland_Window_Driver::xdg_toplevel() { struct wld_window * w = fl_wl_xid(pWindow); struct xdg_toplevel *top = NULL; if (w->kind == DECORATED) top = libdecor_frame_get_xdg_toplevel(w->frame); else if (w->kind == UNFRAMED) top = w->xdg_toplevel; return top; } void Fl_Wayland_Window_Driver::take_focus() { struct wld_window *w = fl_wl_xid(pWindow); if (w) { Fl_Window *old_first = Fl::first_window(); struct wld_window *first_xid = (old_first ? fl_wl_xid(old_first->top_window()) : NULL); if (first_xid && first_xid != w && xdg_toplevel()) { // this will move the target window to the front Fl_Wayland_Window_Driver *top_dr = Fl_Wayland_Window_Driver::driver(old_first->top_window()); xdg_toplevel_set_parent(xdg_toplevel(), top_dr->xdg_toplevel()); // this will remove the parent-child relationship xdg_toplevel_set_parent(xdg_toplevel(), NULL); wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); } // this sets the first window fl_wl_find(w); } } void Fl_Wayland_Window_Driver::flush_overlay() { if (!shown()) return; Fl_Overlay_Window *oWindow = pWindow->as_overlay_window(); int erase_overlay = (pWindow->damage()&FL_DAMAGE_OVERLAY) | (overlay() == oWindow); pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY)); pWindow->make_current(); if (!other_xid) { other_xid = new Fl_Image_Surface(oWindow->w(), oWindow->h(), 1); oWindow->clear_damage(FL_DAMAGE_ALL); } if (oWindow->damage() & ~FL_DAMAGE_EXPOSE) { Fl_X *myi = Fl_X::flx(pWindow); fl_clip_region(myi->region); myi->region = 0; Fl_Surface_Device::push_current(other_xid); draw(); Fl_Surface_Device::pop_current(); } if (erase_overlay) fl_clip_region(0); if (other_xid) { struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer = Fl_Wayland_Graphics_Driver::offscreen_buffer(other_xid->offscreen()); struct wld_window *xid = fl_wl_xid(pWindow); struct Fl_Wayland_Graphics_Driver::wld_buffer *wbuffer = xid->buffer; if (wbuffer->draw_buffer.data_size != buffer->data_size) { fl_copy_offscreen(0, 0, oWindow->w(), oWindow->h(), other_xid->offscreen(), 0, 0); } else { memcpy(wbuffer->draw_buffer.buffer, buffer->buffer, wbuffer->draw_buffer.data_size); } } if (overlay() == oWindow) oWindow->draw_overlay(); } const Fl_Image* Fl_Wayland_Window_Driver::shape() { return shape_data_ ? shape_data_->shape_ : NULL; } void Fl_Wayland_Window_Driver::shape_bitmap_(Fl_Image* b) { shape_data_->mask_pattern_ = Fl_Cairo_Graphics_Driver::bitmap_to_pattern( (Fl_Bitmap*)b, true, NULL); shape_data_->shape_ = b; shape_data_->lw_ = b->data_w(); shape_data_->lh_ = b->data_h(); } void Fl_Wayland_Window_Driver::shape_alpha_(Fl_Image* img, int offset) { int i, j, d = img->d(), w = img->data_w(), h = img->data_h(); int bytesperrow = cairo_format_stride_for_width(CAIRO_FORMAT_A1, w); unsigned u; uchar byte, onebit; // build a CAIRO_FORMAT_A1 surface covering the non-fully transparent/black part of the image uchar* bits = new uchar[h*bytesperrow]; // to store the surface data const uchar* alpha = (const uchar*)*img->data() + offset; // points to alpha value of pixels for (i = 0; i < h; i++) { uchar *p = (uchar*)bits + i * bytesperrow; byte = 0; onebit = 1; for (j = 0; j < w; j++) { if (d == 3) { u = *alpha; u += *(alpha+1); u += *(alpha+2); } else u = *alpha; if (u > 0) { // if the pixel is not fully transparent/black byte |= onebit; // turn on the corresponding bit of the bitmap } onebit = onebit << 1; // move the single set bit one position to the left if (onebit == 0 || j == w-1) { onebit = 1; *p++ = ~byte; // store in bitmap one pack of bits, complemented byte = 0; } alpha += d; // point to alpha value of next img pixel } } cairo_surface_t *mask_surf = cairo_image_surface_create_for_data(bits, CAIRO_FORMAT_A1, w, h, bytesperrow); shape_data_->mask_pattern_ = cairo_pattern_create_for_surface(mask_surf); cairo_surface_destroy(mask_surf); shape_data_->shape_ = img; shape_data_->lw_ = w; shape_data_->lh_ = h; } void Fl_Wayland_Window_Driver::shape(const Fl_Image* img) { if (shape_data_) { if (shape_data_->mask_pattern_) { cairo_surface_t *surface; cairo_pattern_get_surface(shape_data_->mask_pattern_, &surface); uchar *data = cairo_image_surface_get_data(surface); cairo_pattern_destroy(shape_data_->mask_pattern_); delete[] data; } } else { shape_data_ = new shape_data_type; } memset(shape_data_, 0, sizeof(shape_data_type)); pWindow->border(false); int d = img->d(); if (d && img->count() >= 2) { shape_pixmap_((Fl_Image*)img); shape_data_->shape_ = (Fl_Image*)img; } else if (d == 0) shape_bitmap_((Fl_Image*)img); else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1); else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0); } void Fl_Wayland_Window_Driver::draw_end() { if (shape_data_ && shape_data_->mask_pattern_) { Fl_Wayland_Graphics_Driver *gr_dr = (Fl_Wayland_Graphics_Driver*)fl_graphics_driver; cairo_t *cr = gr_dr->cr(); cairo_matrix_t matrix; cairo_matrix_init_scale(&matrix, double(shape_data_->lw_) / (pWindow->w() + 1), double(shape_data_->lh_) / (pWindow->h() + 1) ); cairo_matrix_translate(&matrix, 1, 1); cairo_pattern_set_matrix(shape_data_->mask_pattern_, &matrix); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_mask(cr, shape_data_->mask_pattern_); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); } } /* Returns images of the captures of the window title-bar, and the left, bottom and right window borders (or NULL if a particular border is absent). Returned images can be deleted after use. Their depth and size may be platform-dependent. The top and bottom images extend from left of the left border to right of the right border. */ void Fl_Wayland_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) { top = left = bottom = right = NULL; if (pWindow->decorated_h() == h()) return; int htop = pWindow->decorated_h() - pWindow->h(); struct wld_window *wwin = fl_wl_xid(pWindow); int width, height, stride; uchar *cairo_data = fl_libdecor_titlebar_buffer(wwin->frame, &width, &height, &stride); if (!cairo_data) return; uchar *data = new uchar[width * height * 4]; uchar *p = data; for (int j = 0; j < height; j++) { uchar *q = cairo_data + j * stride; for (int i = 0; i < width; i++) { *p++ = *(q+2); // R *p++ = *(q+1); // G *p++ = *q; // B *p++ = *(q+3); // A q += 4; } } top = new Fl_RGB_Image(data, width, height, 4); top->alloc_array = 1; top->scale(pWindow->w(), htop); } // make drawing go into this window (called by subclass flush() impl.) void Fl_Wayland_Window_Driver::make_current() { if (!shown()) { static const char err_message[] = "Fl_Window::make_current(), but window is not shown()."; fl_alert(err_message); Fl::fatal(err_message); } struct wld_window *window = fl_wl_xid(pWindow); if (window->buffer) { ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->needs_commit_tag( &window->buffer->draw_buffer_needs_commit); } // to support progressive drawing if ( (!Fl_Wayland_Window_Driver::in_flush_) && window->buffer && (!window->frame_cb) && window->buffer->draw_buffer_needs_commit && (!wait_for_expose_value) ) { Fl_Wayland_Graphics_Driver::buffer_commit(window); } Fl_Wayland_Window_Driver::wld_window = window; fl_window = (Window)window; float f = Fl::screen_scale(pWindow->screen_num()); int wld_s = wld_scale(); if (!window->buffer) { window->buffer = Fl_Wayland_Graphics_Driver::create_wld_buffer( int(pWindow->w() * f) * wld_s, int(pWindow->h() * f) * wld_s, false); ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->needs_commit_tag( &window->buffer->draw_buffer_needs_commit); } ((Fl_Wayland_Graphics_Driver*)fl_graphics_driver)->set_cairo( window->buffer->draw_buffer.cairo_, f * wld_s); ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->wld_scale = wld_s; int *poffset = Fl_Window_Driver::menu_offset_y(pWindow); if (poffset) { // for tall menu windows under KWIN to offset drawing inside window cairo_translate(window->buffer->draw_buffer.cairo_, 0, *poffset); } cairo_rectangle_int_t *extents = subRect(); if (extents) { // make damage-to-buffer not to leak outside parent Fl_Region clip_region = fl_graphics_driver->XRectangleRegion(extents->x, extents->y, extents->width, extents->height); //printf("make_current: %dx%d %dx%d\n",extents->x, extents->y, extents->width, extents->height); Fl_X::flx(pWindow)->region = clip_region; } else fl_graphics_driver->clip_region(0); #ifdef FLTK_HAVE_CAIROEXT // update the cairo_t context if (Fl::cairo_autolink_context()) Fl::cairo_make_current(pWindow); #endif } void Fl_Wayland_Window_Driver::flush() { if (!pWindow->damage()) return; if (pWindow->as_gl_window()) { int W = pWindow->w(); int H = pWindow->h(); float scale = fl_graphics_driver->scale(); Fl_Wayland_Window_Driver::in_flush_ = true; Fl_Window_Driver::flush(); Fl_Wayland_Window_Driver::in_flush_ = false; gl_plugin()->do_swap(pWindow); // useful only for GL win with overlay if (scale != fl_graphics_driver->scale() || W != pWindow->w() || H != pWindow->h()) { gl_plugin()->invalidate(pWindow); } return; } struct wld_window *window = fl_wl_xid(pWindow); if (!window || !window->configured_width) return; Fl_X *ip = Fl_X::flx(pWindow); cairo_region_t* r = (cairo_region_t*)ip->region; if (!window->buffer || pWindow->as_overlay_window()) r = NULL; Fl_Wayland_Window_Driver::in_flush_ = true; Fl_Window_Driver::flush(); Fl_Wayland_Window_Driver::in_flush_ = false; if (!window->frame_cb) Fl_Wayland_Graphics_Driver::buffer_commit(window, r); } void Fl_Wayland_Window_Driver::show() { if (!shown()) { fl_open_display(); makeWindow(); } else { // Wayland itself gives no way to programmatically unminimize a minimized window Fl::handle(FL_SHOW, pWindow); } } static void popup_done(void *data, struct xdg_popup *xdg_popup); static void destroy_surface_caution_pointer_focus(struct wl_surface *surface, struct Fl_Wayland_Screen_Driver::seat *seat) { if (seat->pointer_focus == surface) seat->pointer_focus = NULL; if (seat->keyboard_surface == surface) seat->keyboard_surface = NULL; wl_surface_destroy(surface); } void Fl_Wayland_Window_Driver::hide() { if (pWindow == Fl_Screen_Driver::transient_scale_parent) { // Delete also the running transient scale window // because the transient is a popup and MUST be deleted // before its parent. Fl::remove_timeout(Fl_Screen_Driver::del_transient_window); Fl_Screen_Driver::del_transient_window(NULL); } Fl_X* ip = Fl_X::flx(pWindow); if (hide_common()) return; if (ip->region) { Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region); ip->region = 0; } screen_num_ = -1; struct wld_window *wld_win = (struct wld_window*)ip->xid; if (wld_win) { // this test makes sure ip->xid has not been destroyed already Fl_Wayland_Graphics_Driver::buffer_release(wld_win); if (wld_win->kind == SUBWINDOW && wld_win->subsurface) { wl_subsurface_destroy(wld_win->subsurface); wld_win->subsurface = NULL; } if (wld_win->kind == DECORATED) { libdecor_frame_unref(wld_win->frame); wld_win->frame = NULL; wld_win->xdg_surface = NULL; } else { if (wld_win->kind == POPUP && wld_win->xdg_popup) { popup_done(xdg_popup_get_user_data(wld_win->xdg_popup), wld_win->xdg_popup); wld_win->xdg_popup = NULL; } if (wld_win->kind == UNFRAMED && wld_win->xdg_toplevel) { xdg_toplevel_destroy(wld_win->xdg_toplevel); wld_win->xdg_toplevel = NULL; } if (wld_win->xdg_surface) { xdg_surface_destroy(wld_win->xdg_surface); wld_win->xdg_surface = NULL; } } if (wld_win->custom_cursor) delete_cursor(wld_win->custom_cursor); if (wld_win->wl_surface) { Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); destroy_surface_caution_pointer_focus(wld_win->wl_surface, scr_driver->seat); wld_win->wl_surface = NULL; } while (!wl_list_empty(&wld_win->outputs)) { // remove from screens where it belongs struct surface_output *s_output; s_output = wl_container_of(wld_win->outputs.next, s_output, link); wl_list_remove(&s_output->link); free(s_output); } if (Fl_Wayland_Window_Driver::wld_window == wld_win) { Fl_Wayland_Window_Driver::wld_window = NULL; } if (wld_win->frame_cb) wl_callback_destroy(wld_win->frame_cb); // useful for GL subwins free(wld_win); } delete ip; } void Fl_Wayland_Window_Driver::map() { Fl_X* ip = Fl_X::flx(pWindow); struct wld_window *wl_win = (struct wld_window*)ip->xid; if (wl_win->kind == SUBWINDOW && !wl_win->subsurface) { struct wld_window *parent = fl_wl_xid(pWindow->window()); if (parent) { Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); wl_win->subsurface = wl_subcompositor_get_subsurface(scr_driver->wl_subcompositor, wl_win->wl_surface, parent->wl_surface); float f = Fl::screen_scale(pWindow->top_window()->screen_num()); wl_subsurface_set_position(wl_win->subsurface, pWindow->x() * f, pWindow->y() * f); wl_subsurface_set_desync(wl_win->subsurface); // important wl_subsurface_place_above(wl_win->subsurface, parent->wl_surface); wl_win->configured_width = pWindow->w(); wl_win->configured_height = pWindow->h(); wait_for_expose_value = 0; pWindow->redraw(); } } } void Fl_Wayland_Window_Driver::unmap() { Fl_X* ip = Fl_X::flx(pWindow); struct wld_window *wl_win = (struct wld_window*)ip->xid; if (wl_win->kind == SUBWINDOW && wl_win->wl_surface) { wl_surface_attach(wl_win->wl_surface, NULL, 0, 0); Fl_Wayland_Graphics_Driver::buffer_release(wl_win); wl_subsurface_destroy(wl_win->subsurface); wl_win->subsurface = NULL; } } void Fl_Wayland_Window_Driver::size_range() { if (shown()) { Fl_X* ip = Fl_X::flx(pWindow); struct wld_window *wl_win = (struct wld_window*)ip->xid; float f = Fl::screen_scale(pWindow->screen_num()); int minw, minh, maxw, maxh; pWindow->get_size_range(&minw, &minh, &maxw, &maxh, NULL, NULL, NULL); if (wl_win->kind == DECORATED && wl_win->frame) { int X,Y,W,H; Fl::screen_work_area(X,Y,W,H, Fl::screen_num(x(),y(),w(),h())); if (maxw && maxw < W && maxh && maxh < H) { libdecor_frame_unset_capabilities(wl_win->frame, LIBDECOR_ACTION_FULLSCREEN); } else { libdecor_frame_set_capabilities(wl_win->frame, LIBDECOR_ACTION_FULLSCREEN); } if (maxw && maxh && (minw >= maxw || minh >= maxh)) { libdecor_frame_unset_capabilities(wl_win->frame, LIBDECOR_ACTION_RESIZE); } else { libdecor_frame_set_capabilities(wl_win->frame, LIBDECOR_ACTION_RESIZE); } libdecor_frame_set_min_content_size(wl_win->frame, minw*f, minh*f); libdecor_frame_set_max_content_size(wl_win->frame, maxw*f, maxh*f); if (xdg_toplevel()) { struct libdecor_state *state = libdecor_state_new(int(w() * f), int(h() * f)); libdecor_frame_commit(wl_win->frame, state, NULL); libdecor_state_free(state); } } else if (wl_win->kind == UNFRAMED && wl_win->xdg_toplevel) { xdg_toplevel_set_min_size(wl_win->xdg_toplevel, minw*f, minh*f); if (maxw && maxh) xdg_toplevel_set_max_size(wl_win->xdg_toplevel, maxw*f, maxh*f); } } } void Fl_Wayland_Window_Driver::iconize() { Fl_X* ip = Fl_X::flx(pWindow); struct wld_window *wl_win = (struct wld_window*)ip->xid; if (wl_win->kind == DECORATED) { libdecor_frame_set_minimized(wl_win->frame); Fl::handle(FL_HIDE, pWindow); } else if (wl_win->kind == UNFRAMED && wl_win->xdg_toplevel) xdg_toplevel_set_minimized(wl_win->xdg_toplevel); } void Fl_Wayland_Window_Driver::decoration_sizes(int *top, int *left, int *right, int *bottom) { struct wld_window *xid = (struct wld_window*)fl_xid(pWindow); if (xid && xid->kind == DECORATED) { libdecor_frame_translate_coordinate(xid->frame, 0, 0, left, top); *right = *left; *bottom = 0; } else { Fl_Window_Driver::decoration_sizes(top, left, right, bottom); } } int Fl_Wayland_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data) { struct wld_window * xid = fl_wl_xid(pWindow); struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer = xid->buffer; float s = wld_scale() * fl_graphics_driver->scale(); if (s != 1) { src_x = src_x * s; src_y = src_y * s; src_w = src_w * s; src_h = src_h * s; dest_x = dest_x * s; dest_y = dest_y * s; } if (src_x == dest_x) { // vertical scroll int i, to, step; if (src_y > dest_y) { i = 0; to = src_h; step = 1; } else { i = src_h - 1; to = -1; step = -1; } while (i != to) { memcpy( buffer->draw_buffer.buffer + (dest_y + i) * buffer->draw_buffer.stride + 4 * dest_x, buffer->draw_buffer.buffer + (src_y + i) * buffer->draw_buffer.stride + 4 * src_x, 4 * src_w); i += step; } } else { // horizontal scroll int i, to, step; if (src_x > dest_x) { i = 0; to = src_h; step = 1; } else { i = src_h - 1; to = -1; step = -1; } while (i != to) { memmove( buffer->draw_buffer.buffer + (src_y + i) * buffer->draw_buffer.stride + 4 * dest_x, buffer->draw_buffer.buffer + (src_y + i) * buffer->draw_buffer.stride + 4 * src_x, 4 * src_w); i += step; } } return 0; } static void handle_error(struct libdecor *libdecor_context, enum libdecor_error error, const char *message) { Fl::fatal("Caught error (%d): %s\n", error, message); } static struct libdecor_interface libdecor_iface = { .error = handle_error, }; void change_scale(Fl_Wayland_Screen_Driver::output *output, struct wld_window *window, float pre_scale) { Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win); if (!window->fl_win->parent()) { // for top-level, set its screen number when the 1st screen for this surface changes Fl_Wayland_Screen_Driver::output *running_output; Fl_Wayland_Screen_Driver *scr_dr = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); int i = 0; wl_list_for_each(running_output, &scr_dr->outputs, link) { // each screen of the system if (running_output == output) { // we've found our screen of the system win_driver->screen_num(i); break; } i++; } } float post_scale = Fl::screen_scale(win_driver->screen_num()) * output->wld_scale; //printf("pre_scale=%.1f post_scale=%.1f\n", pre_scale, post_scale); if (post_scale != pre_scale) { if (window->kind == Fl_Wayland_Window_Driver::POPUP) { Fl_Wayland_Graphics_Driver::buffer_release(window); window->fl_win->redraw(); } else { win_driver->is_a_rescale(true); window->fl_win->size(window->fl_win->w(), window->fl_win->h()); win_driver->is_a_rescale(false); } } if (window->fl_win->as_gl_window()) wl_surface_set_buffer_scale(window->wl_surface, output->wld_scale); } static void surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { struct wld_window *window = (struct wld_window*)data; if (!Fl_Wayland_Screen_Driver::own_output(wl_output)) return; Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)wl_output_get_user_data(wl_output); if (output == NULL) return; Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win); float pre_scale = Fl::screen_scale(win_driver->screen_num()) * win_driver->wld_scale(); bool list_was_empty = wl_list_empty(&window->outputs); struct Fl_Wayland_Window_Driver::surface_output *surface_output = (struct Fl_Wayland_Window_Driver::surface_output*)malloc( sizeof(struct Fl_Wayland_Window_Driver::surface_output)); surface_output->output = output; // add to end of the linked list of displays of this surface struct wl_list *e = &window->outputs; while (e->next != &window->outputs) e = e->next; // move e to end of linked list wl_list_insert(e, &surface_output->link); //printf("window %p enters screen id=%d length=%d\n", window->fl_win, output->id, wl_list_length(&window->outputs)); if (list_was_empty) { change_scale(output, window, pre_scale); } } static void surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) { if (!Fl_Wayland_Screen_Driver::own_output(wl_output)) return; struct wld_window *window = (struct wld_window*)data; Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)wl_output_get_user_data(wl_output); Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win); float pre_scale = Fl::screen_scale(win_driver->screen_num()) * win_driver->wld_scale(); struct Fl_Wayland_Window_Driver::surface_output *s_output; int count = 0; wl_list_for_each(s_output, &window->outputs, link) { count++; if (s_output->output == output) { wl_list_remove(&s_output->link); free(s_output); //printf("window %p leaves screen id=%d length=%d\n", window->fl_win, output->id, wl_list_length(&window->outputs)); break; } } if (count == 1 && !wl_list_empty(&window->outputs)) { s_output = wl_container_of(window->outputs.next, s_output, link); change_scale(s_output->output, window, pre_scale); } } static struct wl_surface_listener surface_listener = { surface_enter, surface_leave, }; Fl_Window *Fl_Wayland_Window_Driver::surface_to_window(struct wl_surface *surface) { if (surface) { if (wl_proxy_get_listener((struct wl_proxy *)surface) == &surface_listener) { return ((struct wld_window *)wl_surface_get_user_data(surface))->fl_win; } } return NULL; } static struct Fl_Wayland_Screen_Driver::output *screen_num_to_output(int num_screen) { Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); int i = 0; Fl_Wayland_Screen_Driver::output *output; wl_list_for_each(output, &(scr_driver->outputs), link) { // all screens of the system if (i++ == num_screen) return output; } return NULL; } #define LIBDECOR_MR131 1 // this means libdecor does not include MR!131 yet #ifdef LIBDECOR_MR131 /* === Beginning of hack that would become un-needed if libdecor accepted MR!131 === */ // true while the GUI is interactively resizing a decorated window static bool in_decorated_window_resizing = false; // libdecor's configure cb function for xdg_toplevel objects static void (*decor_xdg_toplevel_configure)(void*, struct xdg_toplevel *, int32_t, int32_t, struct wl_array *); static void fltk_xdg_toplevel_configure(void *user_data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states) { uint32_t *p; in_decorated_window_resizing = false; // Replace wl_array_for_each(p, states) rejected by C++ for (p = (uint32_t *)(states)->data; (const char *) p < ((const char *) (states)->data + (states)->size); (p)++) { if (*p == XDG_TOPLEVEL_STATE_RESIZING) { in_decorated_window_resizing = true; break; } } decor_xdg_toplevel_configure(user_data, xdg_toplevel, width, height, states); } struct wl_object { // copied from wayland-private.h const struct wl_interface *interface; const void *implementation; uint32_t id; }; // replace libdecor's toplevel configure cb by FLTK's static void use_FLTK_toplevel_configure_cb(struct libdecor_frame *frame) { struct wl_object *object = (struct wl_object *)libdecor_frame_get_xdg_toplevel(frame); static struct xdg_toplevel_listener *fltk_listener = NULL; if (!fltk_listener) { struct xdg_toplevel_listener *decor_listener = (struct xdg_toplevel_listener*) object->implementation; fltk_listener = (struct xdg_toplevel_listener*) malloc(sizeof(struct xdg_toplevel_listener)); // initialize FLTK's listener with libdecor's values *fltk_listener = *decor_listener; // memorize libdecor's toplevel configure cb decor_xdg_toplevel_configure = decor_listener->configure; // replace libdecor's toplevel configure cb by FLTK's fltk_listener->configure = fltk_xdg_toplevel_configure; } // replace the toplevel listener by a copy whose configure member is FLTK's object->implementation = fltk_listener; } /* === End of hack that would become un-needed if libdecor accepted MR!131 === */ #endif // LIBDECOR_MR131 // does win entirely cover its parent ? static void does_window_cover_parent(Fl_Window *win) { Fl_Window *parent = win->window(); fl_wl_xid(parent)->covered = (win->x() <= 0 && win->y() <= 0 && win->w() >= parent->w() && win->h() >= parent->h()); } // recursively explore all shown subwindows in a window and call f for each static void scan_subwindows(Fl_Group *g, void (*f)(Fl_Window *)) { for (int i = 0; i < g->children(); i++) { Fl_Widget *o = g->child(i); if (o->as_window()) { if (!o->as_window()->shown()) continue; f(o->as_window()); } if (o->as_group()) scan_subwindows(o->as_group(), f); } } static void handle_configure(struct libdecor_frame *frame, struct libdecor_configuration *configuration, void *user_data) { struct wld_window *window = (struct wld_window*)user_data; if (!window->wl_surface) return; int width, height; enum libdecor_window_state window_state; struct libdecor_state *state; Fl_Wayland_Window_Driver *driver = Fl_Wayland_Window_Driver::driver(window->fl_win); // true exactly for the 1st run of handle_configure() for this window bool is_1st_run = (window->xdg_surface == 0); // true exactly for the 2nd run of handle_configure() for this window bool is_2nd_run = (window->xdg_surface != 0 && driver->wait_for_expose_value); float f = Fl::screen_scale(window->fl_win->screen_num()); if (!window->xdg_surface) window->xdg_surface = libdecor_frame_get_xdg_surface(frame); #ifdef LIBDECOR_MR131 if (is_1st_run) use_FLTK_toplevel_configure_cb(frame); #endif struct wl_output *wl_output = NULL; if (window->fl_win->fullscreen_active()) { if (!(window->state & LIBDECOR_WINDOW_STATE_FULLSCREEN)) { if (Fl_Window_Driver::driver(window->fl_win)->force_position()) { struct Fl_Wayland_Screen_Driver::output *output = screen_num_to_output(window->fl_win->screen_num()); if (output) wl_output = output->wl_output; } libdecor_frame_set_fullscreen(window->frame, wl_output); } } else if (driver->show_iconic()) { libdecor_frame_set_minimized(window->frame); driver->show_iconic(0); } if (!libdecor_configuration_get_window_state(configuration, &window_state)) window_state = LIBDECOR_WINDOW_STATE_NONE; if ((window->state & LIBDECOR_WINDOW_STATE_FULLSCREEN) && !(window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN) && !window->fl_win->border()) { // necessary so Mutter correctly positions borderless window back from fullscreen window->fl_win->redraw(); } window->state = window_state; // Weston, KWin, and some versions of Mutter, on purpose, don't set the // window width x height when xdg_toplevel_configure runs twice // during resizable window creation // (see https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/6). // Consequently, libdecor_configuration_get_content_size() may return false twice. // In that case libdecor_frame_get_content_{width,height}() give the desired window size if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) { if (is_2nd_run) { width = libdecor_frame_get_content_width(frame); height = libdecor_frame_get_content_height(frame); if (!driver->is_resizable()) { libdecor_frame_set_min_content_size(frame, width, height); libdecor_frame_set_max_content_size(frame, width, height); } } else { width = height = 0; } } if (is_2nd_run && Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::MUTTER) { scan_subwindows(window->fl_win, does_window_cover_parent); // issue #878 } if (window->fl_win->fullscreen_active() && Fl_Window_Driver::driver(window->fl_win)->force_position()) { int X, Y, W, H; Fl::screen_xywh(X, Y, W, H, window->fl_win->screen_num()); width = W * f; height = H * f; } if (width == 0) { width = window->floating_width; height = window->floating_height; //fprintf(stderr,"handle_configure: using floating %dx%d\n",width,height); } #ifndef LIBDECOR_MR131 bool in_decorated_window_resizing = (window->state & LIBDECOR_WINDOW_STATE_RESIZING); #endif bool condition = in_decorated_window_resizing; if (condition) { // see issue #878 condition = (window->covered ? (window->buffer && window->buffer->in_use) : (window->frame_cb != NULL)); } if (condition) { // Skip resizing & redrawing. The last resize request won't be skipped because // LIBDECOR_WINDOW_STATE_RESIZING will be off or cb will be NULL then. return; } driver->in_handle_configure = true; window->fl_win->resize(0, 0, ceil(width / f), ceil(height / f)); driver->in_handle_configure = false; if (wl_output) window->fl_win->redraw(); window->configured_width = ceil(width / f); window->configured_height = ceil(height / f); if (is_2nd_run) driver->wait_for_expose_value = 0; //fprintf(stderr, "handle_configure fl_win=%p size:%dx%d state=%x wait_for_expose_value=%d is_2nd_run=%d\n", window->fl_win, width,height,window_state,driver->wait_for_expose_value, is_2nd_run); /* We would like to do FL_HIDE when window is minimized but : "There is no way to know if the surface is currently minimized, nor is there any way to unset minimization on this surface. If you are looking to throttle redrawing when minimized, please instead use the wl_surface.frame event" */ if (window_state & LIBDECOR_WINDOW_STATE_ACTIVE) { if (Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::WESTON) { // After click on titlebar, weston calls wl_keyboard_enter() for a // titlebar-related surface that FLTK can't identify, so we send FL_FOCUS here. Fl::handle(FL_FOCUS, window->fl_win); } if (!window->fl_win->border()) libdecor_frame_set_visibility(window->frame, false); else if (!libdecor_frame_is_visible(window->frame)) { libdecor_frame_set_visibility(window->frame, true); } } if (window->fl_win->border()) driver->is_maximized(window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED); if (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) state = libdecor_state_new(width, height); else state = libdecor_state_new(int(ceil(width/f)*f), int(ceil(height/f)*f)); libdecor_frame_commit(frame, state, configuration); if (libdecor_frame_is_floating(frame)) { // store floating dimensions window->floating_width = int(ceil(width/f)*f); window->floating_height = int(ceil(height/f)*f); //fprintf(stderr,"set floating_width+height %dx%d\n",width,height); } libdecor_state_free(state); driver->flush(); if (Fl_Wayland_Screen_Driver::compositor != Fl_Wayland_Screen_Driver::WESTON || !is_1st_run) { window->fl_win->clear_damage(); } } void Fl_Wayland_Window_Driver::wait_for_expose() { Fl_Window_Driver::wait_for_expose(); struct wld_window * xid = fl_wl_xid(pWindow); if (!xid) return; if (pWindow->fullscreen_active()) { if (xid->kind == DECORATED) { while (!(xid->state & LIBDECOR_WINDOW_STATE_FULLSCREEN) || !(xid->state & LIBDECOR_WINDOW_STATE_ACTIVE)) { wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display); } } else if (xid->kind == UNFRAMED) { wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); } } else if (xid->kind == DECORATED) { // necessary for the windowfocus demo program with recent Wayland versions if (!(xid->state & LIBDECOR_WINDOW_STATE_ACTIVE)) { wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display); } } } static void delayed_close(Fl_Window *win) { Fl::remove_check((Fl_Timeout_Handler)delayed_close, win); Fl::handle(FL_CLOSE, win); } static void handle_close(struct libdecor_frame *frame, void *user_data) { // runs when the close button of a window titlebar is pushed // or after "Quit" of the application menu // or after the Kill command of Sway Fl_Window* win = ((struct wld_window*)user_data)->fl_win; int X, Y; libdecor_frame_translate_coordinate(frame, 0, 0, &X, &Y); if (Y == 0) Fl::handle(FL_CLOSE, win); else { // the close window attempt is delayed because libdecor // uses the frame after return from this function Fl::add_check((Fl_Timeout_Handler)delayed_close, win); } } static void handle_commit(struct libdecor_frame *frame, void *user_data) { struct wld_window* wl_win = (struct wld_window*)user_data; if (wl_win->wl_surface) wl_surface_commit(wl_win->wl_surface); } static void handle_dismiss_popup(struct libdecor_frame *frame, const char *seat_name, void *user_data) { } static struct libdecor_frame_interface libdecor_frame_iface = { handle_configure, handle_close, handle_commit, handle_dismiss_popup, }; static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { // runs for borderless windows and popup (menu,tooltip) windows struct wld_window *window = (struct wld_window*)data; xdg_surface_ack_configure(xdg_surface, serial); //fprintf(stderr, "xdg_surface_configure: surface=%p\n", window->wl_surface); if (window->fl_win->w() != window->configured_width || window->fl_win->h() != window->configured_height) { if (window->buffer) { Fl_Wayland_Graphics_Driver::buffer_release(window); } } window->configured_width = window->fl_win->w(); window->configured_height = window->fl_win->h(); Fl_Window_Driver::driver(window->fl_win)->flush(); window->fl_win->clear_damage(); } static const struct xdg_surface_listener xdg_surface_listener = { .configure = xdg_surface_configure, }; static bool parse_states_fullscreen(struct wl_array *states) { uint32_t *p; // Replace wl_array_for_each(p, states) rejected by C++ for (p = (uint32_t *)(states)->data; (const char *) p < ((const char *) (states)->data + (states)->size); (p)++) { if (*p == XDG_TOPLEVEL_STATE_FULLSCREEN) return true; } return false; } static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states) { // runs for borderless top-level windows // under Weston: width & height are 0 during both calls, except if fullscreen struct wld_window *window = (struct wld_window*)data; //fprintf(stderr, "xdg_toplevel_configure: surface=%p size: %dx%d\n", window->wl_surface, width, height); if (window->fl_win->fullscreen_active() && !parse_states_fullscreen(states)) { struct wl_output *wl_output = NULL; if (Fl_Window_Driver::driver(window->fl_win)->force_position()) { struct Fl_Wayland_Screen_Driver::output *output = screen_num_to_output(window->fl_win->screen_num()); if (output) wl_output = output->wl_output; } xdg_toplevel_set_fullscreen(xdg_toplevel, wl_output); if (wl_output) { int X, Y; Fl::screen_xywh(X, Y, width, height, window->fl_win->screen_num()); } } if (window->configured_width) { Fl_Window_Driver::driver(window->fl_win)->wait_for_expose_value = 0; } float f = Fl::screen_scale(window->fl_win->screen_num()); if (width == 0 || height == 0) { width = window->fl_win->w() * f; height = window->fl_win->h() * f; } window->fl_win->size(ceil(width / f), ceil(height / f)); if (window->buffer && (ceil(width / f) != window->configured_width || ceil(height / f) != window->configured_height)) { Fl_Wayland_Graphics_Driver::buffer_release(window); } window->configured_width = ceil(width / f); window->configured_height = ceil(height / f); } static void xdg_toplevel_close(void *data, struct xdg_toplevel *toplevel) { } static const struct xdg_toplevel_listener xdg_toplevel_listener = { .configure = xdg_toplevel_configure, .close = xdg_toplevel_close, }; struct win_positioner { struct wld_window *window; int x, y; Fl_Window *child_popup; }; static void popup_configure(void *data, struct xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height) { struct win_positioner *win_pos = (struct win_positioner *)data; struct wld_window *window = win_pos->window; //printf("popup_configure %p asked:%dx%d got:%dx%d\n",window->fl_win, win_pos->x,win_pos->y, x,y); Fl_Window_Driver::driver(window->fl_win)->wait_for_expose_value = 0; int HH; Fl_Window_Driver::menu_parent(&HH); if (window->fl_win->h() > HH && y != win_pos->y) { // A menu taller than the display // Under KWin, height is set to the display height or less: we ignore that. window->state = (y - win_pos->y); // make selected item visible, if there's one Fl_Window_Driver::scroll_to_selected_item(window->fl_win); } } static struct xdg_popup *mem_grabbing_popup = NULL; static void popup_done(void *data, struct xdg_popup *xdg_popup) { struct win_positioner *win_pos = (struct win_positioner *)data; struct wld_window *window = win_pos->window; //fprintf(stderr, "popup_done: popup=%p data=%p xid=%p fl_win=%p\n", xdg_popup, data, window, window->fl_win); if (win_pos->child_popup) win_pos->child_popup->hide(); xdg_popup_destroy(xdg_popup); delete win_pos; // The sway compositor calls popup_done directly and hides the menu // when the app looses focus. // Thus, we hide the window so FLTK and Wayland are in matching states. window->xdg_popup = NULL; window->fl_win->hide(); if (mem_grabbing_popup == xdg_popup) { mem_grabbing_popup = NULL; } } static const struct xdg_popup_listener popup_listener = { .configure = popup_configure, .popup_done = popup_done, }; bool Fl_Wayland_Window_Driver::in_flush_ = false; static const char *get_prog_name() { pid_t pid = getpid(); char fname[100]; snprintf(fname, 100, "/proc/%u/cmdline", pid); FILE *in = fopen(fname, "r"); if (in) { static char line[200]; const char *p = fgets(line, sizeof(line), in); fclose(in); p = strrchr(line, '/'); if (!p) p = line; else p++; return p; } return "unknown"; } /* Implementation note about menu windows under Wayland. Wayland offers a way to position popup windows such as menu windows using constraints. Each popup is located relatively to a parent window which can be a popup itself and MUST overlap or at least touch this parent. Constraints determine how a popup is positioned relatively to a defined area (called the anchor rectangle) of its parent popup/window and what happens when this position would place the popup all or partly outside the display. In contrast, FLTK computes the adequate positions of menu windows in the display using knowledge about the display size and the location of the window in the display, and then maps them at these positions. These 2 logics are quite different because Wayland hides the position of windows inside the display, whereas FLTK uses the location of windows inside the display to position popups. Let's call "source window" the non-popup window above which all popups are mapped. The approach implemented here is two-fold. 1) If a menu window is not taller than the display, use Wayland constraints to position it. Wayland imposes that the first constructed popup must overlap or touch the source window. Other popups can be placed below, above, at right, or at left of a previous popup which allows them to expand outside the source window, while constraints can ensure they won't extend outside the display. 2) A menu window taller than the display is initially mapped with the constraint to begin at the top border of the display. This allows FLTK to know the distance between the source window and the display top. FLTK can later reposition the same tall popup, without the constraint not to go beyond the display top, at the exact position so that the desired series of menu items appear in the visible part of the tall popup. In case 1) above, the values that represent the display bounds are given very large values. That's done by member function Fl_Wayland_Window_Driver::menu_window_area(). Consequently, FLTK computes an initial layout of future popups relatively to the source window as if it was mapped on an infinitely large display. Then, the location of the first popup to be mapped is modified if necessary so it overlaps or touches the source window. Finally, other popups are located using Wayland logic below, above or to the right of previous popups. Wayland constraints mechanism also allows a popup tentatively placed below a previous one to be flipped above it if that prevents the popup from expanding beyond display limits. This is used to unfold menu bar menus below or above the menu bar. After each popup is created and scheduled for being mapped on display by function process_menu_or_tooltip(), makeWindow() calls Fl_Window::wait_for_expose() so its constrained position is known before computing the position of the next popup. This ensures each popup is correctly placed relatively to its parent. Groups of popups containing a menutitle, the associated menuwindow, and optionally a submenu window and that don't belong to an Fl_Menu_Bar are mapped in a different order: the menuwindow is mapped first, and the menutitle is mapped second above it as a child popup. Fl_Window_Driver::is_floating_title() detects when such a menutitle is created, static member variable previous_floatingtitle is assigned the value of this menutitle, and the menutitle is mapped only after the menuwindow has been mapped, as a child of it. This positions better the popup group in the display relatively to where the popup was created. In case 2) above, a tall popup is mapped with XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y which puts its top at the display top border. The Wayland system then calls the popup_configure() callback function with the x,y coordinates of the top left corner where the popup is mapped relatively to an anchor point in the source window. The difference between the asked window position and the effective position is stored in the state member variable of the tall popup's struct wld_window. This information allows FLTK to compute the distance between the source window top and the display top border. Function Fl_Wayland_Window_Driver::menu_window_area() sets the top of the display to a value such that function Fl_Wayland_Window_Driver::reposition_menu_window(), called by menuwindow::autoscroll(int n), ensures that menu item #n is visible. Static boolean member variable Fl_Wayland_Window_Driver::new_popup is useful to position tall menuwindows created by an Fl_Menu_Button or Fl_Choice. It is set to true when any menu popup is created. It is used each time menu_window_area() runs for a particular Fl_Menu_Button or Fl_Choice, and is reset to false after its first use. This allows menu_window_area() to give the top of the display an adequate value the first time and to keep this value next times it runs. Fl_Window_Driver::scroll_to_selected_item() scrolls the tall popup so its selected item, when there's one, is visible immediately after the tall popup is mapped on display. */ bool Fl_Wayland_Window_Driver::process_menu_or_tooltip(struct wld_window *new_window) { // a menu window or tooltip new_window->kind = Fl_Wayland_Window_Driver::POPUP; Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); if (Fl_Window_Driver::is_floating_title(pWindow)) { previous_floatingtitle = pWindow; return true; } new_window->xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, new_window->wl_surface); xdg_surface_add_listener(new_window->xdg_surface, &xdg_surface_listener, new_window); Fl_Wayland_Window_Driver::new_popup = true; Fl_Window *menu_origin = NULL; if (pWindow->menu_window()) { menu_origin = Fl_Window_Driver::menu_leftorigin(pWindow); if (!menu_origin && !previous_floatingtitle) menu_origin = Fl_Window_Driver::menu_title(pWindow); } Fl_Widget *target = (pWindow->tooltip_window() ? Fl_Tooltip::current() : NULL); if (pWindow->user_data() == &Fl_Screen_Driver::transient_scale_display && Fl_Screen_Driver::transient_scale_parent) { target = Fl_Screen_Driver::transient_scale_parent; } if (!target) target = Fl_Window_Driver::menu_parent(); if (!target) target = Fl::belowmouse(); if (!target) target = Fl::first_window(); Fl_Window *parent_win = target->top_window(); while (parent_win && parent_win->menu_window() && driver(parent_win)->popup_window()) { parent_win = Fl::next_window(parent_win); } Fl_Window *origin_win = (menu_origin ? menu_origin : parent_win); struct wld_window * parent_xid = fl_wl_xid(origin_win); struct xdg_surface *parent_xdg = parent_xid->xdg_surface; float f = Fl::screen_scale(parent_win->screen_num()); //fprintf(stderr, "menu parent_win=%p pos:%dx%d size:%dx%d\n", parent_win, pWindow->x(), pWindow->y(), pWindow->w(), pWindow->h()); //printf("window=%p menutitle=%p bartitle=%d leftorigin=%p y=%d\n", pWindow, Fl_Window_Driver::menu_title(pWindow), Fl_Window_Driver::menu_bartitle(pWindow), Fl_Window_Driver::menu_leftorigin(pWindow), pWindow->y()); struct xdg_positioner *positioner = xdg_wm_base_create_positioner(scr_driver->xdg_wm_base); //xdg_positioner_get_version(positioner) <== gives 1 under Debian and Sway int popup_x, popup_y; if (Fl_Window_Driver::menu_title(pWindow) && Fl_Window_Driver::menu_bartitle(pWindow)) { xdg_positioner_set_anchor_rect(positioner, 0, 0, Fl_Window_Driver::menu_title(pWindow)->w() * f, Fl_Window_Driver::menu_title(pWindow)->h() * f); popup_x = 0; popup_y = Fl_Window_Driver::menu_title(pWindow)->h() * f; } else { popup_x = pWindow->x() * f; popup_y = pWindow->y() * f; if (popup_x + pWindow->w() * f < 0) popup_x = - pWindow->w() * f; if (menu_origin) { popup_x -= menu_origin->x() * f; popup_y -= menu_origin->y() * f; } if (popup_x >= origin_win->w() * f) popup_x = origin_win->w() * f - 1; if (!Fl_Window_Driver::menu_title(pWindow) && !Fl_Window_Driver::menu_bartitle(pWindow) && !Fl_Window_Driver::menu_leftorigin(pWindow)) { // prevent first popup from going above the permissible source window popup_y = fl_max(popup_y, - pWindow->h() * f); } if (parent_xid->kind == Fl_Wayland_Window_Driver::DECORATED) libdecor_frame_translate_coordinate(parent_xid->frame, popup_x, popup_y, &popup_x, &popup_y); xdg_positioner_set_anchor_rect(positioner, popup_x, 0, 1, 1); popup_y++; } xdg_positioner_set_size(positioner, pWindow->w() * f , pWindow->h() * f ); xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_BOTTOM_LEFT); xdg_positioner_set_gravity(positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT); // prevent menuwindow from expanding beyond display limits int constraint = 0; if ( !(parent_win->fullscreen_active() && Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::MUTTER && ((!Fl_Window_Driver::menu_title(pWindow) && !Fl_Window_Driver::menu_leftorigin(pWindow)) || Fl_Window_Driver::menu_bartitle(pWindow))) ) { // Condition above is only to bypass Mutter bug for fullscreen windows (see #1061) constraint |= (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y); if (Fl_Window_Driver::menu_bartitle(pWindow) && !Fl_Window_Driver::menu_leftorigin(pWindow)) { constraint |= XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y; } xdg_positioner_set_constraint_adjustment(positioner, constraint); } if (!(Fl_Window_Driver::menu_title(pWindow) && Fl_Window_Driver::menu_bartitle(pWindow))) { xdg_positioner_set_offset(positioner, 0, popup_y); } new_window->xdg_popup = xdg_surface_get_popup(new_window->xdg_surface, parent_xdg, positioner); struct win_positioner *win_pos = new struct win_positioner; win_pos->window = new_window; win_pos->x = popup_x; win_pos->y = popup_y; win_pos->child_popup = NULL; //printf("create xdg_popup=%p data=%p xid=%p fl_win=%p\n",new_window->xdg_popup,win_pos,new_window,new_window->fl_win); xdg_positioner_destroy(positioner); xdg_popup_add_listener(new_window->xdg_popup, &popup_listener, win_pos); if (!mem_grabbing_popup) { mem_grabbing_popup = new_window->xdg_popup; //xdg_popup_grab(new_window->xdg_popup, scr_driver->get_wl_seat(), scr_driver->get_serial()); //libdecor_frame_popup_grab(parent_xid->frame, scr_driver->get_seat_name()); } wl_surface_commit(new_window->wl_surface); // put it on same screen as parent_win this->screen_num(parent_win->screen_num()); return false; } void Fl_Wayland_Window_Driver::makeWindow() { Fl_Group::current(0); // get rid of very common user bug: forgot end() struct wld_window *new_window; bool is_floatingtitle = false; wait_for_expose_value = 1; if (pWindow->parent() && !pWindow->window()) return; if (pWindow->parent() && !pWindow->window()->shown()) return; if (!pWindow->parent() && !popup_window()) { x(0); y(0); // toplevel, non-popup windows must have origin at 0,0 } new_window = (struct wld_window *)calloc(1, sizeof *new_window); new_window->fl_win = pWindow; wl_list_init(&new_window->outputs); Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); new_window->wl_surface = wl_compositor_create_surface(scr_driver->wl_compositor); //Fl::warning("makeWindow:%p wayland-scale=%d user-scale=%.2f\n", pWindow, new_window->scale, Fl::screen_scale(0)); wl_surface_add_listener(new_window->wl_surface, &surface_listener, new_window); if (!shape()) { // rectangular FLTK windows are opaque struct wl_region *opaque = wl_compositor_create_region(scr_driver->wl_compositor); wl_region_add(opaque, 0, 0, 1000000, 1000000); wl_surface_set_opaque_region(new_window->wl_surface, opaque); wl_region_destroy(opaque); } if (pWindow->user_data() == &Fl_Screen_Driver::transient_scale_display && Fl::first_window()) { // put transient scale win at center of top window by making it a tooltip of top Fl_Screen_Driver::transient_scale_parent = Fl::first_window(); pWindow->set_tooltip_window(); set_popup_window(); pWindow->position( (Fl_Screen_Driver::transient_scale_parent->w() - pWindow->w())/2 , (Fl_Screen_Driver::transient_scale_parent->h() - pWindow->h())/2); } if (popup_window()) { // a menu window or tooltip is_floatingtitle = process_menu_or_tooltip(new_window); } else if (pWindow->border() && !pWindow->parent() ) { // a decorated window new_window->kind = DECORATED; if (!scr_driver->libdecor_context) scr_driver->libdecor_context = libdecor_new(Fl_Wayland_Screen_Driver::wl_display, &libdecor_iface); new_window->frame = libdecor_decorate(scr_driver->libdecor_context, new_window->wl_surface, &libdecor_frame_iface, new_window); // appears in the Gnome desktop menu bar libdecor_frame_set_app_id(new_window->frame, get_prog_name()); libdecor_frame_set_title(new_window->frame, pWindow->label()?pWindow->label():""); if (!is_resizable()) { libdecor_frame_unset_capabilities(new_window->frame, LIBDECOR_ACTION_RESIZE); libdecor_frame_unset_capabilities(new_window->frame, LIBDECOR_ACTION_FULLSCREEN); } libdecor_frame_map(new_window->frame); float f = Fl::screen_scale(pWindow->screen_num()); new_window->floating_width = pWindow->w() * f; new_window->floating_height = pWindow->h() * f; } else if (pWindow->parent()) { // for subwindows (GL or non-GL) new_window->kind = SUBWINDOW; struct wld_window *parent = fl_wl_xid(pWindow->window()); new_window->subsurface = wl_subcompositor_get_subsurface(scr_driver->wl_subcompositor, new_window->wl_surface, parent->wl_surface); //fprintf(stderr, "makeWindow: subsurface=%p\n", new_window->subsurface); float f = Fl::screen_scale(pWindow->top_window()->screen_num()); wl_subsurface_set_position(new_window->subsurface, pWindow->x() * f, pWindow->y() * f); wl_subsurface_set_desync(new_window->subsurface); // important // Next 5 statements ensure the subsurface will be mapped because: // "The effect of adding a sub-surface becomes visible on the next time // the state of the parent surface is applied." new_window->configured_width = pWindow->w(); new_window->configured_height = pWindow->h(); if (!pWindow->as_gl_window()) { parent->fl_win->wait_for_expose(); wl_surface_commit(parent->wl_surface); } wait_for_expose_value = 0; pWindow->border(0); checkSubwindowFrame(); // make sure subwindow doesn't leak outside parent } else { // a window without decoration new_window->kind = UNFRAMED; new_window->xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, new_window->wl_surface); //fprintf(stderr, "makeWindow: xdg_wm_base_get_xdg_surface=%p\n", new_window->xdg_surface); xdg_surface_add_listener(new_window->xdg_surface, &xdg_surface_listener, new_window); new_window->xdg_toplevel = xdg_surface_get_toplevel(new_window->xdg_surface); xdg_toplevel_add_listener(new_window->xdg_toplevel, &xdg_toplevel_listener, new_window); if (pWindow->label()) xdg_toplevel_set_title(new_window->xdg_toplevel, pWindow->label()); wl_surface_commit(new_window->wl_surface); pWindow->border(0); } Fl_Window *old_first = Fl::first_window(); struct wld_window * first_xid = (old_first ? fl_wl_xid(old_first) : NULL); Fl_X *xp = new Fl_X; xp->xid = (fl_uintptr_t)new_window; other_xid = 0; xp->w = pWindow; flx(xp); xp->region = 0; if (!pWindow->parent()) { xp->next = Fl_X::first; Fl_X::first = xp; } else if (Fl_X::first) { xp->next = Fl_X::first->next; Fl_X::first->next = xp; } else { xp->next = NULL; Fl_X::first = xp; } if (pWindow->modal() || pWindow->non_modal()) { if (pWindow->modal()) Fl::modal_ = pWindow; if (new_window->kind == DECORATED && first_xid && first_xid->kind == DECORATED) { if (first_xid->frame) libdecor_frame_set_parent(new_window->frame, first_xid->frame); } else if (new_window->kind == UNFRAMED && new_window->xdg_toplevel && first_xid) { Fl_Wayland_Window_Driver *top_dr = Fl_Wayland_Window_Driver::driver(first_xid->fl_win); if (top_dr->xdg_toplevel()) xdg_toplevel_set_parent(new_window->xdg_toplevel, top_dr->xdg_toplevel()); } if (scr_driver->seat->gtk_shell && pWindow->modal() && (new_window->kind == DECORATED || new_window->kind == UNFRAMED)) { // Useful to position modal windows above their parent with "gnome-shell --version" ≤ 45.2, // useless but harmless with "gnome-shell --version" ≥ 46.0. struct gtk_surface1 *gtk_surface = gtk_shell1_get_gtk_surface(scr_driver->seat->gtk_shell, new_window->wl_surface); gtk_surface1_set_modal(gtk_surface); if (gtk_surface1_get_version(gtk_surface) >= GTK_SURFACE1_RELEASE_SINCE_VERSION) gtk_surface1_release(gtk_surface); // very necessary else gtk_surface1_destroy(gtk_surface); } } size_range(); pWindow->set_visible(); int old_event = Fl::e_number; pWindow->redraw(); pWindow->handle(Fl::e_number = FL_SHOW); // get child windows to appear Fl::e_number = old_event; if (pWindow->menu_window() && popup_window() && !is_floatingtitle) { // make sure each menu window is mapped with its constraints before mapping next popup pWindow->wait_for_expose(); if (previous_floatingtitle) { // a menuwindow with a menutitle //puts("previous_floatingtitle"); int HH; Fl_Window_Driver::menu_parent(&HH); if (pWindow->h() > HH) { // a tall menuwindow with a menutitle: don't create the menutitle at all // and undo what has been created/allocated before struct wld_window *xid = fl_wl_xid(previous_floatingtitle); destroy_surface_caution_pointer_focus(xid->wl_surface, scr_driver->seat); free(xid); Fl_Window_Driver::driver(previous_floatingtitle)->hide_common(); previous_floatingtitle = NULL; return; } // map the menutitle popup now as child of pWindow struct wld_window *xid = fl_wl_xid(previous_floatingtitle); xid->xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, xid->wl_surface); xdg_surface_add_listener(xid->xdg_surface, &xdg_surface_listener, xid); struct xdg_positioner *positioner = xdg_wm_base_create_positioner(scr_driver->xdg_wm_base); xdg_positioner_set_anchor_rect(positioner, 0, 0, 1, 1); int snum = Fl_Window_Driver::menu_parent()->screen_num(); float f = Fl::screen_scale(snum); // put it on same screen as parent menu Fl_Window_Driver::driver(previous_floatingtitle)->screen_num(snum); xdg_positioner_set_size(positioner, previous_floatingtitle->w() * f , previous_floatingtitle->h() * f ); xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT); xdg_positioner_set_gravity(positioner, XDG_POSITIONER_GRAVITY_TOP_RIGHT); xid->xdg_popup = xdg_surface_get_popup(xid->xdg_surface, new_window->xdg_surface, positioner); xdg_positioner_destroy(positioner); struct win_positioner *win_pos = new struct win_positioner; win_pos->window = xid; win_pos->x = 0; win_pos->y = 0; win_pos->child_popup = NULL; xdg_popup_add_listener(xid->xdg_popup, &popup_listener, win_pos); wl_surface_commit(xid->wl_surface); struct win_positioner *parent_win_pos = (struct win_positioner*)xdg_popup_get_user_data(new_window->xdg_popup); parent_win_pos->child_popup = previous_floatingtitle; previous_floatingtitle = NULL; } } } Fl_Wayland_Window_Driver::type_for_resize_window_between_screens Fl_Wayland_Window_Driver::data_for_resize_window_between_screens_ = {0, false}; void Fl_Wayland_Window_Driver::resize_after_screen_change(void *data) { Fl_Window *win = (Fl_Window*)data; float f = Fl::screen_driver()->scale(data_for_resize_window_between_screens_.screen); Fl_Window_Driver::driver(win)->resize_after_scale_change( data_for_resize_window_between_screens_.screen, f, f); data_for_resize_window_between_screens_.busy = false; } int Fl_Wayland_Window_Driver::set_cursor(Fl_Cursor c) { Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); struct wld_window *xid = (struct wld_window *)Fl_Window_Driver::xid(pWindow); if (!scr_driver->seat->cursor_theme) return 1; // Cursor names are the files of directory /usr/share/icons/XXXX/cursors/ // where XXXX is the name of the current 'cursor theme'. static struct cursor_file_struct { Fl_Cursor c; const char *fname; Fl_Wayland_Screen_Driver::cursor_shapes wld_c; } cursor_file_array[] = { {FL_CURSOR_ARROW, "left_ptr", Fl_Wayland_Screen_Driver::arrow }, {FL_CURSOR_CROSS, "cross", Fl_Wayland_Screen_Driver::cross }, {FL_CURSOR_WAIT, "watch", Fl_Wayland_Screen_Driver::wait }, {FL_CURSOR_INSERT, "xterm", Fl_Wayland_Screen_Driver::insert }, {FL_CURSOR_HAND, "hand1", Fl_Wayland_Screen_Driver::hand }, {FL_CURSOR_HELP, "help", Fl_Wayland_Screen_Driver::help }, {FL_CURSOR_MOVE, "move", Fl_Wayland_Screen_Driver::move }, {FL_CURSOR_N, "top_side", Fl_Wayland_Screen_Driver::north }, {FL_CURSOR_E, "right_side", Fl_Wayland_Screen_Driver::east }, {FL_CURSOR_W, "left_side", Fl_Wayland_Screen_Driver::west }, {FL_CURSOR_S, "bottom_side", Fl_Wayland_Screen_Driver::south }, {FL_CURSOR_NS, "sb_v_double_arrow", Fl_Wayland_Screen_Driver::north_south }, {FL_CURSOR_WE, "sb_h_double_arrow", Fl_Wayland_Screen_Driver::west_east }, {FL_CURSOR_SW, "bottom_left_corner", Fl_Wayland_Screen_Driver::south_west }, {FL_CURSOR_SE, "bottom_right_corner", Fl_Wayland_Screen_Driver::south_east }, {FL_CURSOR_NE, "top_right_corner", Fl_Wayland_Screen_Driver::north_east }, {FL_CURSOR_NW, "top_left_corner", Fl_Wayland_Screen_Driver::north_west }, {FL_CURSOR_NESW, "fd_double_arrow", Fl_Wayland_Screen_Driver::nesw }, {FL_CURSOR_NWSE, "bd_double_arrow", Fl_Wayland_Screen_Driver::nwse } }; int found = -1; for (unsigned i = 0; i < sizeof(cursor_file_array) / sizeof(struct cursor_file_struct); i++) { if (cursor_file_array[i].c == c) { found = cursor_file_array[i].wld_c; if (!scr_driver->xc_cursor[found]) scr_driver->xc_cursor[found] = scr_driver->cache_cursor(cursor_file_array[i].fname); if (scr_driver->xc_cursor[found]) { scr_driver->default_cursor(scr_driver->xc_cursor[found]); } break; } } if (found < 0 || !scr_driver->xc_cursor[found]) return 0; if (xid->custom_cursor) { delete_cursor(xid->custom_cursor); xid->custom_cursor = NULL; } standard_cursor_ = c; scr_driver->set_cursor(); return 1; } void Fl_Wayland_Window_Driver::use_border() { if (!shown() || pWindow->parent()) return; pWindow->wait_for_expose(); // useful for border(0) just after show() struct libdecor_frame *frame = fl_wl_xid(pWindow)->frame; if (frame && Fl_Wayland_Screen_Driver::compositor != Fl_Wayland_Screen_Driver::KWIN) { if (fl_wl_xid(pWindow)->kind == DECORATED) { libdecor_frame_set_visibility(frame, pWindow->border()); } else { pWindow->hide(); pWindow->show(); } pWindow->redraw(); } else { Fl_Window_Driver::use_border(); } } /* Change an existing window to fullscreen */ void Fl_Wayland_Window_Driver::fullscreen_on() { int top, bottom, left, right; top = fullscreen_screen_top(); bottom = fullscreen_screen_bottom(); left = fullscreen_screen_left(); right = fullscreen_screen_right(); if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) { top = screen_num(); bottom = top; left = top; right = top; } pWindow->wait_for_expose(); // make sure ->xdg_toplevel is initialized if (xdg_toplevel()) { xdg_toplevel_set_fullscreen(xdg_toplevel(), NULL); pWindow->_set_fullscreen(); Fl::handle(FL_FULLSCREEN, pWindow); } } void Fl_Wayland_Window_Driver::fullscreen_off(int X, int Y, int W, int H) { if (!border()) pWindow->resize(X, Y, W, H); xdg_toplevel_unset_fullscreen(xdg_toplevel()); pWindow->_clear_fullscreen(); Fl::handle(FL_FULLSCREEN, pWindow); } void Fl_Wayland_Window_Driver::label(const char *name, const char *iname) { if (shown() && !parent() && fl_wl_xid(pWindow)->kind == DECORATED) { if (!name) name = ""; if (!iname) iname = fl_filename_name(name); libdecor_frame_set_title(fl_wl_xid(pWindow)->frame, name); } } int Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *rgb, int hotx, int hoty) { int retval = set_cursor_4args(rgb, hotx, hoty, true); if (retval) { Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); struct wld_window *xid = (struct wld_window *)Fl_Window_Driver::xid(pWindow); Fl_Wayland_Screen_Driver::do_set_cursor(scr_driver->seat, xid->custom_cursor->wl_cursor); } return retval; } int Fl_Wayland_Window_Driver::set_cursor_4args(const Fl_RGB_Image *rgb, int hotx, int hoty, bool keep_copy) { if (keep_copy) { int ld = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d(); uchar *data = new uchar[ld * rgb->data_h()]; memcpy(data, rgb->array, ld * rgb->data_h()); Fl_RGB_Image *rgb2 = new Fl_RGB_Image(data, rgb->data_w(), rgb->data_h(), rgb->d(), rgb->ld()); rgb2->alloc_array = 1; rgb2->scale(rgb->w(), rgb->h(), 0, 1); rgb = rgb2; } // build a new wl_cursor and its image struct wld_window *xid = (struct wld_window *)Fl_Window_Driver::xid(pWindow); struct wl_cursor *new_cursor = (struct wl_cursor*)malloc(sizeof(struct wl_cursor)); struct cursor_image *new_image = (struct cursor_image*)calloc(1, sizeof(struct cursor_image)); int scale = wld_scale(); new_image->image.width = rgb->w() * scale; new_image->image.height = rgb->h() * scale; new_image->image.hotspot_x = hotx * scale; new_image->image.hotspot_y = hoty * scale; new_image->image.delay = 0; new_image->offset = 0; //create a Wayland buffer and have it used as an image of the new cursor struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen; Fl_Image_Surface *img_surf = Fl_Wayland_Graphics_Driver::custom_offscreen( new_image->image.width, new_image->image.height, &offscreen); new_image->buffer = offscreen->wl_buffer; wl_buffer_set_user_data(new_image->buffer, offscreen); new_cursor->image_count = 1; new_cursor->images = (struct wl_cursor_image**)malloc(sizeof(struct wl_cursor_image*)); new_cursor->images[0] = (struct wl_cursor_image*)new_image; new_cursor->name = strdup("custom cursor"); // draw the rgb image to the cursor's drawing buffer Fl_Surface_Device::push_current(img_surf); Fl_Wayland_Graphics_Driver *driver = (Fl_Wayland_Graphics_Driver*)img_surf->driver(); cairo_scale(driver->cr(), scale, scale); ((Fl_RGB_Image*)rgb)->draw(0, 0); Fl_Surface_Device::pop_current(); delete img_surf; memcpy(offscreen->data, offscreen->draw_buffer.buffer, offscreen->draw_buffer.data_size); // delete the previous custom cursor, if there was one, // and keep its Fl_RGB_Image if appropriate if (xid->custom_cursor) delete_cursor(xid->custom_cursor, keep_copy); //have this new cursor used xid->custom_cursor = new custom_cursor; xid->custom_cursor->wl_cursor = new_cursor; xid->custom_cursor->rgb = rgb; xid->custom_cursor->hotx = hotx; xid->custom_cursor->hoty = hoty; return 1; } struct xid_and_rect { struct wld_window *xid; Fl_Window *win; int X, Y, W, H; bool need_resize; }; static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) { struct xid_and_rect *xid_rect = (xid_and_rect *)data; wl_callback_destroy(cb); xid_rect->xid->frame_cb = NULL; if (xid_rect->need_resize) { xid_rect->win->Fl_Group::resize(xid_rect->X, xid_rect->Y, xid_rect->W, xid_rect->H); xid_rect->win->redraw(); } else { xid_rect->win->Fl_Widget::resize(xid_rect->X, xid_rect->Y, xid_rect->W, xid_rect->H); if (xid_rect->xid->buffer && xid_rect->xid->buffer->draw_buffer_needs_commit) { // for scenarios where the child window is moved and its parent is simultaneously modified Fl_Wayland_Graphics_Driver::buffer_commit(xid_rect->xid); } } delete xid_rect; } static const struct wl_callback_listener surface_frame_listener = { .done = surface_frame_done, }; void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) { static int depth = 0; struct wld_window *fl_win = fl_wl_xid(pWindow); if (fl_win && fl_win->kind == DECORATED && !xdg_toplevel()) { pWindow->wait_for_expose(); } int is_a_move = (X != x() || Y != y()); bool true_rescale = Fl_Window::is_a_rescale(); float f = Fl::screen_scale(pWindow->screen_num()); if (fl_win && fl_win->buffer) { int scale = wld_scale(); int stride = cairo_format_stride_for_width( Fl_Cairo_Graphics_Driver::cairo_format, int(W * f) * scale ); size_t bsize = stride * int(H * f) * scale; true_rescale = (bsize != fl_win->buffer->draw_buffer.data_size); } int is_a_resize = (W != w() || H != h() || true_rescale); if (is_a_move) force_position(1); else if (!is_a_resize && !is_a_move) return; depth++; if (shown() && !(parent() || popup_window())) { X = Y = 0; } Fl_Window *parent = this->parent() ? pWindow->window() : NULL; struct wld_window *parent_xid = parent ? fl_wl_xid(parent) : NULL; xid_and_rect *xid_rect = NULL; if (parent_xid && parent_xid->frame_cb && wl_proxy_get_listener((struct wl_proxy*)parent_xid->frame_cb) == &surface_frame_listener) { xid_rect = (xid_and_rect*)wl_callback_get_user_data(parent_xid->frame_cb); if (xid_rect->win != pWindow) xid_rect = NULL; } // When moving or resizing a non-GL subwindow independently from its parent, this condition // delays application of X,Y,W,H values until the compositor signals // it's ready for a new frame using the frame callback mechanism. if ((parent && parent->damage()) || depth > 1 || pWindow->as_gl_window() || !parent_xid || wait_for_expose_value || (parent_xid->frame_cb && !xid_rect)) { if (is_a_resize) { if (pWindow->parent()) { if (W < 1) W = 1; if (H < 1) H = 1; } pWindow->Fl_Group::resize(X,Y,W,H); //fprintf(stderr, "resize: win=%p to %dx%d\n", pWindow, W, H); if (shown()) {pWindow->redraw();} } else { x(X); y(Y); //fprintf(stderr, "move win=%p to %dx%d\n", pWindow, X, Y); } } if (shown()) { if (is_a_resize) { if (pWindow->as_overlay_window() && other_xid) { destroy_double_buffer(); } if (fl_win->kind == DECORATED) { // a decorated window if (fl_win->buffer) { Fl_Wayland_Graphics_Driver::buffer_release(fl_win); } fl_win->configured_width = W; fl_win->configured_height = H; if (!in_handle_configure && xdg_toplevel()) { if (Fl_Window::is_a_rescale()) size_range(); struct libdecor_state *state = libdecor_state_new(int(W * f), int(H * f)); // necessary only if resize is initiated by prog libdecor_frame_commit(fl_win->frame, state, NULL); libdecor_state_free(state); if (libdecor_frame_is_floating(fl_win->frame)) { fl_win->floating_width = int(W*f); fl_win->floating_height = int(H*f); } } } else if (fl_win->kind == SUBWINDOW && fl_win->subsurface) { // a subwindow wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f); if (!pWindow->as_gl_window()) Fl_Wayland_Graphics_Driver::buffer_release(fl_win); fl_win->configured_width = W; fl_win->configured_height = H; } else if (fl_win->xdg_surface) { // a window without border if (!pWindow->as_gl_window()) Fl_Wayland_Graphics_Driver::buffer_release(fl_win); fl_win->configured_width = W; fl_win->configured_height = H; W *= f; H *= f; if (!pWindow->fullscreen_active()) { xdg_toplevel_set_min_size(fl_win->xdg_toplevel, W, H); xdg_toplevel_set_max_size(fl_win->xdg_toplevel, W, H); } xdg_surface_set_window_geometry(fl_win->xdg_surface, 0, 0, W, H); //printf("xdg_surface_set_window_geometry: %dx%d\n",W, H); } } else { if (!in_handle_configure && xdg_toplevel()) { // Wayland doesn't seem to provide a reliable way for the app to set the // window position on screen. This is functional when the move is mouse-driven. Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); if (Fl::e_state == FL_BUTTON1) { xdg_toplevel_move(xdg_toplevel(), scr_driver->seat->wl_seat, scr_driver->seat->serial); Fl::pushed(NULL); Fl::e_state = 0; } } else if (pWindow->as_gl_window() && fl_win->kind == SUBWINDOW && fl_win->subsurface) { wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f); } } } if (fl_win && parent_xid) { if (pWindow->as_gl_window()) { if (fl_win->frame_cb) { wl_callback_destroy(fl_win->frame_cb); fl_win->frame_cb = NULL; } if (parent_xid->buffer) Fl_Wayland_Graphics_Driver::buffer_commit(parent_xid); } else { if (!(parent && parent->damage()) && !parent_xid->frame_cb) { // use the frame callback mechanism and memorize current X,Y,W,H values xid_rect = new xid_and_rect; xid_rect->xid = parent_xid; xid_rect->win = pWindow; parent_xid->frame_cb = wl_surface_frame(parent_xid->wl_surface); wl_callback_add_listener(parent_xid->frame_cb, &surface_frame_listener, xid_rect); xid_rect->X = X; xid_rect->Y = Y; xid_rect->W = W; xid_rect->H = H; xid_rect->need_resize = is_a_resize; wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f); wl_surface_commit(parent_xid->wl_surface); } else if (!xid_rect) { if (is_a_move && fl_win->subsurface) { wl_subsurface_set_position(fl_win->subsurface, X * f, Y * f); } wl_surface_commit(parent_xid->wl_surface); } } checkSubwindowFrame(); // make sure subwindow doesn't leak outside parent } depth--; } static void crect_intersect(cairo_rectangle_int_t *to, cairo_rectangle_int_t *with) { int x = fl_max(to->x, with->x); to->width = fl_min(to->x + to->width, with->x + with->width) - x; if (to->width < 0) to->width = 0; int y = fl_max(to->y, with->y); to->height = fl_min(to->y + to->height, with->y + with->height) - y; if (to->height < 0) to->height = 0; to->x = x; to->y = y; } static bool crect_equal(cairo_rectangle_int_t *to, cairo_rectangle_int_t *with) { return (to->x == with->x && to->y == with->y && to->width == with->width && to->height == with->height); } void Fl_Wayland_Window_Driver::checkSubwindowFrame() { if (!pWindow->parent() || can_expand_outside_parent_) return; // make sure this subwindow doesn't leak out of its parent window Fl_Window *from = pWindow, *parent; cairo_rectangle_int_t full = {0, 0, pWindow->w(), pWindow->h()}; // full subwindow area cairo_rectangle_int_t srect = full; // will become new subwindow clip int fromx = 0, fromy = 0; while ((parent = from->window()) != NULL) { // loop over all parent windows fromx -= from->x(); // parent origin in subwindow's coordinates fromy -= from->y(); cairo_rectangle_int_t prect = {fromx, fromy, parent->w(), parent->h()}; crect_intersect(&srect, &prect); // area of subwindow inside its parent from = parent; } cairo_rectangle_int_t *r = subRect(); // current subwindow clip cairo_rectangle_int_t current_clip = (r ? *r : full); if (!crect_equal(&srect, ¤t_clip)) { // if new clip differs from current clip if (crect_equal(&srect, &full)) r = NULL; else { r = &srect; if (r->width == 0 || r->height == 0) { r = NULL; } } subRect(r); } } void Fl_Wayland_Window_Driver::subRect(cairo_rectangle_int_t *r) { if (subRect_) delete subRect_; cairo_rectangle_int_t *r2 = NULL; if (r) { r2 = new cairo_rectangle_int_t; *r2 = *r; } subRect_ = r2; } void Fl_Wayland_Window_Driver::reposition_menu_window(int x, int y) { if (y == pWindow->y()) return; if (Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::KWIN) { // The KWin compositor refuses to position a popup such that it extends above // the top of the screen. Therefore, instead of sliding the popup window // on the display, we slide the drawing inside the fixed popup via // member variable offset_y of the menuwindow class, and we redraw the popup // content. It's also useful to make such tall popup window transparent. *Fl_Window_Driver::menu_offset_y(pWindow) += (y - pWindow->y()); struct wld_window *xid = fl_wl_xid(pWindow); wl_surface_set_opaque_region(xid->wl_surface, NULL); if (xid->buffer) memset(xid->buffer->draw_buffer.buffer, 0, xid->buffer->draw_buffer.data_size); //printf("offset_y=%d\n", *Fl_Window_Driver::menu_offset_y(pWindow)); this->y(y); pWindow->redraw(); return; } struct wld_window * xid_menu = fl_wl_xid(pWindow); //printf("reposition %dx%d[cur=%d] menu->state=%d\n", x, y, pWindow->y(), xid_menu->state); struct xdg_popup *old_popup = xid_menu->xdg_popup; struct xdg_surface *old_xdg = xid_menu->xdg_surface; struct wl_surface *old_surface = xid_menu->wl_surface; // menu_origin will be the parent of the processed menu window Fl_Window *menu_origin = Fl_Window_Driver::menu_title(pWindow); if (!menu_origin) menu_origin = Fl_Window_Driver::menu_leftorigin(pWindow); if (!menu_origin) menu_origin = Fl_Window_Driver::menu_parent(); if (Fl_Window_Driver::menu_title(pWindow) && !Fl_Window_Driver::menu_bartitle(pWindow) && !Fl_Window_Driver::menu_leftorigin(pWindow)) { // occurs with tall popup menu menu_origin = Fl_Window_Driver::menu_parent(); } // create a new popup at position (x,y) and display it above the current one Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); xid_menu->wl_surface = wl_compositor_create_surface(scr_driver->wl_compositor); wl_surface_add_listener(xid_menu->wl_surface, &surface_listener, xid_menu); xid_menu->xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, xid_menu->wl_surface); xdg_surface_add_listener(xid_menu->xdg_surface, &xdg_surface_listener, xid_menu); struct xdg_positioner *positioner = xdg_wm_base_create_positioner(scr_driver->xdg_wm_base); struct wld_window * parent_xid = fl_wl_xid(menu_origin); float f = Fl::screen_scale(Fl_Window_Driver::menu_parent()->screen_num()); int popup_x = x * f, popup_y = y * f + xid_menu->state; if (menu_origin->menu_window() && driver(menu_origin)->popup_window()) { popup_x -= menu_origin->x() * f; popup_y -= menu_origin->y() * f; } if (popup_x >= menu_origin->w() * f) popup_x = menu_origin->w() * f - 1; if (parent_xid->kind == DECORATED) { libdecor_frame_translate_coordinate(parent_xid->frame, popup_x, popup_y, &popup_x, &popup_y); } xdg_positioner_set_anchor_rect(positioner, popup_x, 0, 1, 1); xdg_positioner_set_size(positioner, pWindow->w() * f , pWindow->h() * f ); xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT); xdg_positioner_set_gravity(positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT); xdg_positioner_set_constraint_adjustment(positioner, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X); xdg_positioner_set_offset(positioner, 0, popup_y); xid_menu->xdg_popup = xdg_surface_get_popup(xid_menu->xdg_surface, parent_xid->xdg_surface, positioner); xdg_positioner_destroy(positioner); struct win_positioner *win_pos = new struct win_positioner; win_pos->window = xid_menu; win_pos->x = popup_x; win_pos->y = popup_y; win_pos->child_popup = NULL; xdg_popup_add_listener(xid_menu->xdg_popup, &popup_listener, win_pos); wl_surface_commit(xid_menu->wl_surface); wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); // necessary with sway // delete the previous popup struct win_positioner *old_win_pos = (struct win_positioner*)xdg_popup_get_user_data(old_popup); xdg_popup_destroy(old_popup); delete old_win_pos; xdg_surface_destroy(old_xdg); destroy_surface_caution_pointer_focus(old_surface, scr_driver->seat); this->y(y); } void Fl_Wayland_Window_Driver::menu_window_area(int &X, int &Y, int &W, int &H, int nscreen) { int HH; Fl_Window *parent = Fl_Window_Driver::menu_parent(&HH); if (parent) { if (pWindow->menu_window() && popup_window() && pWindow->h() > HH) { // tall menu: set top (Y) and bottom (Y+H) bounds relatively to reference window int ih = Fl_Window_Driver::menu_itemheight(pWindow); X = -50000; W = 1000000; H = HH - 2 * ih; Fl_Window *origin = Fl_Window_Driver::menu_leftorigin(pWindow); if (origin) { // has left parent int selected = fl_max(Fl_Window_Driver::menu_selected(origin), 0); Y = origin->y() + (selected + 0.5) * ih; } else if (!Fl_Window_Driver::menu_bartitle(pWindow)) { // tall menu button static int y_offset = 0; if (new_popup) { y_offset = pWindow->y()- ih; new_popup = false; } Y = 1.5 * ih + y_offset; } else { // has a menutitle Y = 1.5 * ih; } } else { // position the menu window by wayland constraints X = -50000; Y = -50000; W = 1000000; H = 1000000; } //printf("menu_window_area: %dx%d - %dx%d\n",X,Y,W,H); } else Fl_Window_Driver::menu_window_area(X, Y, W, H, nscreen); } int Fl_Wayland_Window_Driver::wld_scale() { Fl_X *flx = Fl_X::flx(pWindow); struct wld_window *xid = (flx ? (struct wld_window *)flx->xid : NULL); if (!xid || wl_list_empty(&xid->outputs)) { int scale = 1; Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); Fl_Wayland_Screen_Driver::output *output; wl_list_for_each(output, &(scr_driver->outputs), link) { scale = fl_max(scale, output->wld_scale); } return scale; } struct surface_output *s_output; s_output = wl_container_of(xid->outputs.next, s_output, link); return s_output->output->wld_scale; } FL_EXPORT struct wl_surface *fl_wl_surface(struct wld_window *xid) { return xid->wl_surface; } cairo_t *fl_wl_gc() { return ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->cr(); } Fl_Window *fl_wl_find(struct wld_window *xid) { return Fl_Window_Driver::find((fl_uintptr_t)xid); } struct wld_window *fl_wl_xid(const Fl_Window *win) { return (struct wld_window *)Fl_Window_Driver::xid(win); } struct wl_compositor *fl_wl_compositor() { Fl_Wayland_Screen_Driver *screen_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); return screen_driver->wl_compositor; } int fl_wl_buffer_scale(Fl_Window *window) { return Fl_Wayland_Window_Driver::driver(window)->wld_scale(); } Fl_Wayland_Plugin *Fl_Wayland_Window_Driver::gl_plugin() { static Fl_Wayland_Plugin *plugin = NULL; if (!plugin) { Fl_Plugin_Manager pm("wayland.fltk.org"); plugin = (Fl_Wayland_Plugin*)pm.plugin("gl.wayland.fltk.org"); } return plugin; } void Fl_Wayland_Window_Driver::maximize() { struct wld_window *xid = (struct wld_window *)Fl_X::flx(pWindow)->xid; if (xid->kind == DECORATED) libdecor_frame_set_maximized(xid->frame); else Fl_Window_Driver::maximize(); } void Fl_Wayland_Window_Driver::un_maximize() { struct wld_window *xid = (struct wld_window *)Fl_X::flx(pWindow)->xid; if (xid->kind == DECORATED) libdecor_frame_unset_maximized(xid->frame); else Fl_Window_Driver::un_maximize(); } fltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx0000644000175000017500000003677015004135251024516 0ustar albrechtalbrecht// // Class Fl_Wayland_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if HAVE_GL #include #include #include "../../Fl_Gl_Choice.H" #include "Fl_Wayland_Window_Driver.H" #include "Fl_Wayland_Graphics_Driver.H" #include "Fl_Wayland_Gl_Window_Driver.H" #ifdef FLTK_USE_X11 # include "../X11/Fl_X11_Gl_Window_Driver.H" #endif #include #include #include /* Implementation notes about OpenGL drawing on the Wayland platform * After eglCreateWindowSurface() with attributes {EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER, EGL_NONE}, eglQueryContext() reports that EGL_RENDER_BUFFER equals EGL_BACK_BUFFER. This experiment suggests that the platform only supports double-buffer drawing. Consequently, FL_DOUBLE is enforced in all Fl_Gl_Window::mode_ values under Wayland. * Commented out code marked with CONTROL_LEAKING_SUB_GL_WINDOWS aims to prevent sub GL windows from leaking out from their parent by making leaking parts fully transparent. This code is commented out because it requires the FL_ALPHA flag to be on which not all client applications do. */ // Describes crap needed to create a GLContext. class Fl_Wayland_Gl_Choice : public Fl_Gl_Choice { friend class Fl_Wayland_Gl_Window_Driver; private: EGLConfig egl_conf; public: Fl_Wayland_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : Fl_Gl_Choice(m, alistp, n) { egl_conf = 0; } }; struct gl_start_support { // to support use of gl_start / gl_finish struct wl_surface *surface; struct wl_subsurface *subsurface; struct wl_egl_window *egl_window; EGLSurface egl_surface; }; static EGLConfig wld_egl_conf = NULL; static EGLint swap_interval_ = 1; static EGLint max_swap_interval = 1000; static EGLint min_swap_interval = 0; EGLDisplay Fl_Wayland_Gl_Window_Driver::egl_display = EGL_NO_DISPLAY; Fl_Wayland_Gl_Window_Driver::Fl_Wayland_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) { if (egl_display == EGL_NO_DISPLAY) init(); egl_window = NULL; egl_surface = NULL; } Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w) { #ifdef FLTK_USE_X11 if (!Fl_Wayland_Screen_Driver::wl_display) return new Fl_X11_Gl_Window_Driver(w); #endif return new Fl_Wayland_Gl_Window_Driver(w); } void Fl_Wayland_Gl_Window_Driver::init() { EGLint major, minor; if (!fl_wl_display()) fl_open_display(); egl_display = eglGetDisplay((EGLNativeDisplayType) fl_wl_display()); if (egl_display == EGL_NO_DISPLAY) { Fl::fatal("Can't create egl display\n"); } if (eglInitialize(egl_display, &major, &minor) != EGL_TRUE) { Fl::fatal("Can't initialise egl display\n"); } //printf("EGL major: %d, minor %d\n", major, minor); //eglGetConfigs(egl_display, NULL, 0, &configs_count); //printf("EGL has %d configs\n", configs_count); eglBindAPI(EGL_OPENGL_API); } Fl_Gl_Choice *Fl_Wayland_Gl_Window_Driver::find(int m, const int *alistp) { m |= FL_DOUBLE; //if (pWindow->parent()) m |= FL_ALPHA; // CONTROL_LEAKING_SUB_GL_WINDOWS Fl_Wayland_Gl_Choice *g = (Fl_Wayland_Gl_Choice*)Fl_Gl_Window_Driver::find_begin( m, alistp); if (g) return g; EGLint n; EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_DEPTH_SIZE, 0, // set at 11 EGL_SAMPLE_BUFFERS, 0, // set at 13 EGL_STENCIL_SIZE, 0, // set at 15 EGL_ALPHA_SIZE, 0, // set at 17 EGL_NONE }; if (m & FL_DEPTH) config_attribs[11] = 1; if (m & FL_MULTISAMPLE) config_attribs[13] = 1; if (m & FL_STENCIL) config_attribs[15] = 1; if (m & FL_ALPHA) config_attribs[17] = (m & FL_RGB8) ? 8 : 1; g = new Fl_Wayland_Gl_Choice(m, alistp, first); eglChooseConfig(egl_display, config_attribs, &(g->egl_conf), 1, &n); if (n == 0 && (m & FL_MULTISAMPLE)) { config_attribs[13] = 0; eglChooseConfig(egl_display, config_attribs, &(g->egl_conf), 1, &n); } if (n == 0) { Fl::fatal("failed to choose an EGL config\n"); } eglGetConfigAttrib(egl_display, g->egl_conf, EGL_MAX_SWAP_INTERVAL, &max_swap_interval); eglGetConfigAttrib(egl_display, g->egl_conf, EGL_MIN_SWAP_INTERVAL, &min_swap_interval); first = g; return g; } GLContext Fl_Wayland_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) { GLContext shared_ctx = 0; if (context_list && nContext) shared_ctx = context_list[0]; static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; GLContext ctx = (GLContext)eglCreateContext(egl_display, ((Fl_Wayland_Gl_Choice*)g)->egl_conf, (shared_ctx ? (EGLContext)shared_ctx : EGL_NO_CONTEXT), context_attribs); //fprintf(stderr, "eglCreateContext=%p shared_ctx=%p\n", ctx, shared_ctx); if (ctx) { add_context(ctx); /* CONTROL_LEAKING_SUB_GL_WINDOWS if (egl_surface) { eglMakeCurrent(egl_display, egl_surface, egl_surface, (EGLContext)ctx); glClearColor(0., 0., 0., 1.); // set opaque black as starting background color apply_scissor(); }*/ } return ctx; } void Fl_Wayland_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) { struct wld_window *win = fl_wl_xid(w); if (!win) return; Fl_Wayland_Window_Driver *dr = Fl_Wayland_Window_Driver::driver(w); EGLSurface target_egl_surface = NULL; if (egl_surface) target_egl_surface = egl_surface; else if (dr->gl_start_support_) target_egl_surface = dr->gl_start_support_->egl_surface; if (!target_egl_surface) { // useful for gl_start() dr->gl_start_support_ = new struct gl_start_support; float s = Fl::screen_scale(w->screen_num()); Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); // the GL scene will be a transparent subsurface above the cairo-drawn surface dr->gl_start_support_->surface = wl_compositor_create_surface(scr_driver->wl_compositor); dr->gl_start_support_->subsurface = wl_subcompositor_get_subsurface( scr_driver->wl_subcompositor, dr->gl_start_support_->surface, win->wl_surface); wl_subsurface_set_position(dr->gl_start_support_->subsurface, w->x() * s, w->y() * s); wl_subsurface_place_above(dr->gl_start_support_->subsurface, win->wl_surface); dr->gl_start_support_->egl_window = wl_egl_window_create( dr->gl_start_support_->surface, w->w() * s, w->h() * s); target_egl_surface = dr->gl_start_support_->egl_surface = eglCreateWindowSurface( egl_display, wld_egl_conf, dr->gl_start_support_->egl_window, NULL); } GLContext current_context = eglGetCurrentContext(); if (context != current_context || w != cached_window) { cached_window = w; if (eglMakeCurrent(egl_display, target_egl_surface, target_egl_surface, (EGLContext)context)) { //fprintf(stderr, "EGLContext %p made current\n", context); } else { Fl::error("eglMakeCurrent() failed\n"); } } if (!(mode() & FL_ALPHA)) { // useful at least for Linux on MacBook hardware GLfloat vals[4]; glGetFloatv(GL_COLOR_CLEAR_VALUE, vals); if (vals[3] == 0.) glClearColor(vals[0], vals[1], vals[2], 1.); } } /* CONTROL_LEAKING_SUB_GL_WINDOWS void Fl_Wayland_Gl_Window_Driver::apply_scissor() { cairo_rectangle_int_t *extents = Fl_Wayland_Window_Driver::driver(pWindow)->subRect(); if (extents) { glDisable(GL_SCISSOR_TEST); GLdouble vals[4]; glGetDoublev(GL_COLOR_CLEAR_VALUE, vals); glClearColor(0., 0., 0., 0.); glClear(GL_COLOR_BUFFER_BIT); glClearColor(vals[0], vals[1], vals[2], vals[3]); float s = pWindow->pixels_per_unit(); glScissor(s*extents->x, s*extents->y, s*extents->width, s*extents->height); //printf("apply_scissor %dx%d %dx%d\n",extents->x, extents->y, extents->width, extents->height); glEnable(GL_SCISSOR_TEST); } }*/ void Fl_Wayland_Gl_Window_Driver::delete_gl_context(GLContext context) { GLContext current_context = eglGetCurrentContext(); if (current_context == context) { cached_window = 0; } if (current_context == (EGLContext)context) { eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } eglDestroyContext(egl_display, (EGLContext)context); eglDestroySurface(egl_display, egl_surface); egl_surface = NULL; wl_egl_window_destroy(egl_window); egl_window = NULL; del_context(context); } void Fl_Wayland_Gl_Window_Driver::make_overlay_current() { glDrawBuffer(GL_FRONT); } void Fl_Wayland_Gl_Window_Driver::redraw_overlay() { pWindow->redraw(); } void Fl_Wayland_Gl_Window_Driver::make_current_before() { if (!egl_window) { struct wld_window *win = fl_wl_xid(pWindow); struct wl_surface *surface = win->wl_surface; int W = pWindow->pixel_w(); int H = pWindow->pixel_h(); int scale = Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale(); egl_window = wl_egl_window_create(surface, (W/scale)*scale, (H/scale)*scale); if (egl_window == EGL_NO_SURFACE) { Fl::fatal("Can't create egl window with wl_egl_window_create()\n"); } Fl_Wayland_Gl_Choice *g = (Fl_Wayland_Gl_Choice*)this->g(); egl_surface = eglCreateWindowSurface(egl_display, g->egl_conf, egl_window, NULL); wl_surface_set_buffer_scale(surface, scale); if (mode() & FL_ALPHA) wl_surface_set_opaque_region(surface, NULL); // Tested apps: shape, glpuzzle, cube, fractals, gl_overlay, fullscreen, unittests, // OpenGL3-glut-test, OpenGL3test. // Tested wayland compositors: mutter, kde-plasma, weston, sway on FreeBSD. if (pWindow->parent()) win = fl_wl_xid(pWindow->top_window()); while (wl_list_empty(&win->outputs)) wl_display_dispatch(fl_wl_display()); } } float Fl_Wayland_Gl_Window_Driver::pixels_per_unit() { int ns = pWindow->screen_num(); int wld_scale = (pWindow->shown() ? Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale() : 1); return wld_scale * Fl::screen_driver()->scale(ns); } int Fl_Wayland_Gl_Window_Driver::mode_(int m, const int *a) { mode(m | FL_DOUBLE); return 1; } void Fl_Wayland_Gl_Window_Driver::swap_buffers() { if (overlay()) { static bool overlay_buffer = true; int wo = pWindow->pixel_w(), ho = pWindow->pixel_h(); GLint matrixmode; GLfloat pos[4]; glGetIntegerv(GL_MATRIX_MODE, &matrixmode); glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); // save original glRasterPos glMatrixMode(GL_PROJECTION); // save proj/model matrices glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glScalef(2.0f/wo, 2.0f/ho, 1.0f); glTranslatef(-wo/2.0f, -ho/2.0f, 0.0f); // set transform so 0,0 is bottom/left of window glRasterPos2i(0,0); // set glRasterPos to bottom left corner { // Emulate overlay by doing copypixels glReadBuffer(overlay_buffer?GL_BACK:GL_FRONT); glDrawBuffer(overlay_buffer?GL_FRONT:GL_BACK); overlay_buffer = ! overlay_buffer; glCopyPixels(0, 0, wo, ho, GL_COLOR); } glPopMatrix(); // GL_MODELVIEW // restore model/proj matrices glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(matrixmode); glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos if (!overlay_buffer) return; // don't call eglSwapBuffers until overlay has been drawn } if (egl_surface) { if (pWindow->parent()) { // issue #967 struct wld_window *xid = fl_wl_xid(pWindow); if (xid->frame_cb) return; xid->frame_cb = wl_surface_frame(xid->wl_surface); wl_callback_add_listener(xid->frame_cb, Fl_Wayland_Graphics_Driver::p_surface_frame_listener, xid); } eglSwapBuffers(Fl_Wayland_Gl_Window_Driver::egl_display, egl_surface); } } class Fl_Wayland_Gl_Plugin : public Fl_Wayland_Plugin { public: Fl_Wayland_Gl_Plugin() : Fl_Wayland_Plugin(name()) { } const char *name() FL_OVERRIDE { return "gl.wayland.fltk.org"; } void do_swap(Fl_Window *w) FL_OVERRIDE { Fl_Gl_Window_Driver *gldr = Fl_Gl_Window_Driver::driver(w->as_gl_window()); if (gldr->overlay() == w) gldr->swap_buffers(); } void invalidate(Fl_Window *w) FL_OVERRIDE { w->as_gl_window()->valid(0); } void terminate() FL_OVERRIDE { if (Fl_Wayland_Gl_Window_Driver::egl_display != EGL_NO_DISPLAY) { eglTerminate(Fl_Wayland_Gl_Window_Driver::egl_display); } } void destroy(struct gl_start_support *gl_start_support_) FL_OVERRIDE { eglDestroySurface(Fl_Wayland_Gl_Window_Driver::egl_display, gl_start_support_->egl_surface); wl_egl_window_destroy(gl_start_support_->egl_window); wl_subsurface_destroy(gl_start_support_->subsurface); wl_surface_destroy(gl_start_support_->surface); delete gl_start_support_; } }; static Fl_Wayland_Gl_Plugin Gl_Overlay_Plugin; /* CONTROL_LEAKING_SUB_GL_WINDOWS static void delayed_scissor(Fl_Wayland_Gl_Window_Driver *dr) { dr->apply_scissor(); }*/ void Fl_Wayland_Gl_Window_Driver::resize(int is_a_resize, int W, int H) { if (!egl_window) return; float f = Fl::screen_scale(pWindow->screen_num()); int s = Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale(); W = int(W * f) * s; // W, H must be multiples of int s H = int(H * f) * s; int W2, H2; wl_egl_window_get_attached_size(egl_window, &W2, &H2); if (W2 != W || H2 != H) { struct wld_window *xid = fl_wl_xid(pWindow); if (xid->kind == Fl_Wayland_Window_Driver::DECORATED && !xid->frame_cb) { xid->frame_cb = wl_surface_frame(xid->wl_surface); wl_callback_add_listener(xid->frame_cb, Fl_Wayland_Graphics_Driver::p_surface_frame_listener, xid); } wl_egl_window_resize(egl_window, W, H, 0, 0); } /* CONTROL_LEAKING_SUB_GL_WINDOWS if (Fl_Wayland_Window_Driver::driver(pWindow)->subRect()) { pWindow->redraw(); Fl::add_timeout(0.01, (Fl_Timeout_Handler)delayed_scissor, this); }*/ } char Fl_Wayland_Gl_Window_Driver::swap_type() { return copy; } void Fl_Wayland_Gl_Window_Driver::gl_visual(Fl_Gl_Choice *c) { Fl_Gl_Window_Driver::gl_visual(c); wld_egl_conf = ((Fl_Wayland_Gl_Choice*)c)->egl_conf; } void Fl_Wayland_Gl_Window_Driver::gl_start() { float f = Fl::screen_scale(Fl_Window::current()->screen_num()); int W = Fl_Window::current()->w() * f; int H = Fl_Window::current()->h() * f; int W2, H2; Fl_Wayland_Window_Driver *dr = Fl_Wayland_Window_Driver::driver(Fl_Window::current()); wl_egl_window_get_attached_size(dr->gl_start_support_->egl_window, &W2, &H2); if (W2 != W || H2 != H) { wl_egl_window_resize(dr->gl_start_support_->egl_window, W, H, 0, 0); } glClearColor(0., 0., 0., 0.); glClear(GL_COLOR_BUFFER_BIT); } void Fl_Wayland_Gl_Window_Driver::swap_interval(int interval) { if (interval < min_swap_interval) interval = min_swap_interval; if (interval > max_swap_interval) interval = max_swap_interval; if (egl_display && eglSwapInterval(egl_display, interval)) swap_interval_ = interval; // printf("swap_interval_=%d\n",swap_interval_); } int Fl_Wayland_Gl_Window_Driver::swap_interval() const { return swap_interval_; } FL_EXPORT EGLContext fl_wl_glcontext(GLContext rc) { return (EGLContext)rc; } #endif // HAVE_GL fltk-1.4.3/src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx0000644000175000017500000006306615004135251024174 0ustar albrechtalbrecht// // Wayland-specific code for clipboard and drag-n-drop support. // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #if !defined(FL_DOXYGEN) # include # include # include # include # include # include "Fl_Wayland_Screen_Driver.H" # include "Fl_Wayland_Window_Driver.H" # include "../Unix/Fl_Unix_System_Driver.H" # include "Fl_Wayland_Graphics_Driver.H" # include "../../flstring.h" // includes # include # include # include //////////////////////////////////////////////////////////////// // Code used for copy and paste and DnD into the program: static char *fl_selection_buffer[2]; static int fl_selection_length[2]; static const char * fl_selection_type[2]; static int fl_selection_buffer_length[2]; static char fl_i_own_selection[2] = {0,0}; static struct wl_data_offer *fl_selection_offer = NULL; static const char *fl_selection_offer_type = NULL; // The MIME type Wayland uses for text-containing clipboard: static const char wld_plain_text_clipboard[] = "text/plain;charset=utf-8"; int Fl_Wayland_Screen_Driver::clipboard_contains(const char *type) { return fl_selection_type[1] == type; } struct data_source_write_struct { size_t rest; char *from; }; void write_data_source_cb(FL_SOCKET fd, data_source_write_struct *data) { while (data->rest) { ssize_t n = write(fd, data->from, data->rest); if (n == -1) { if (errno == EAGAIN) return; Fl::error("write_data_source_cb: error while writing clipboard data\n"); break; } data->from += n; data->rest -= n; } Fl::remove_fd(fd, FL_WRITE); delete data; close(fd); } static void data_source_handle_send(void *data, struct wl_data_source *source, const char *mime_type, int fd) { fl_intptr_t rank = (fl_intptr_t)data; //fprintf(stderr, "data_source_handle_send: %s fd=%d l=%d\n", mime_type, fd, fl_selection_length[1]); if (((!strcmp(mime_type, wld_plain_text_clipboard) || !strcmp(mime_type, "text/plain")) && fl_selection_type[rank] == Fl::clipboard_plain_text) || (!strcmp(mime_type, "image/bmp") && fl_selection_type[rank] == Fl::clipboard_image) ) { data_source_write_struct *write_data = new data_source_write_struct; write_data->rest = fl_selection_length[rank]; write_data->from = fl_selection_buffer[rank]; Fl::add_fd(fd, FL_WRITE, (Fl_FD_Handler)write_data_source_cb, write_data); } else { //Fl::error("Destination client requested unsupported MIME type: %s\n", mime_type); close(fd); } } static Fl_Window *fl_dnd_target_window = 0; static wl_surface *fl_dnd_target_surface = 0; static bool doing_dnd = false; // true when DnD is in action static wl_surface *dnd_icon = NULL; // non null when DnD uses text as cursor static wl_cursor* save_cursor = NULL; // non null when DnD uses "dnd-copy" cursor static void data_source_handle_cancelled(void *data, struct wl_data_source *source) { // An application has replaced the clipboard contents or DnD finished wl_data_source_destroy(source); Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); if (scr_driver->seat->data_source == source) scr_driver->seat->data_source = NULL; doing_dnd = false; if (dnd_icon) { struct Fl_Wayland_Graphics_Driver::wld_buffer *off = (struct Fl_Wayland_Graphics_Driver::wld_buffer *) wl_surface_get_user_data(dnd_icon); struct wld_window fake_window; memset(&fake_window, 0, sizeof(fake_window)); fake_window.buffer = off; Fl_Wayland_Graphics_Driver::buffer_release(&fake_window); wl_surface_destroy(dnd_icon); dnd_icon = NULL; } fl_i_own_selection[1] = 0; if (data == 0) { // at end of DnD if (save_cursor) { scr_driver->default_cursor(save_cursor); scr_driver->set_cursor(); save_cursor = NULL; } if (fl_dnd_target_window) { Fl::handle(FL_RELEASE, fl_dnd_target_window); fl_dnd_target_window = 0; } Fl::pushed(0); } } static void data_source_handle_target(void *data, struct wl_data_source *source, const char *mime_type) { if (!Fl::pushed()) { data_source_handle_cancelled(data, source); return; } if (mime_type != NULL) { //printf("Destination would accept MIME type if dropped: %s\n", mime_type); } else { //printf("Destination would reject if dropped\n"); } } static uint32_t last_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; static void data_source_handle_action(void *data, struct wl_data_source *source, uint32_t dnd_action) { last_dnd_action = dnd_action; switch (dnd_action) { case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY: //printf("Destination would perform a copy action if dropped\n"); break; case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE: //printf("Destination would reject the drag if dropped\n"); break; } } static void data_source_handle_dnd_drop_performed(void *data, struct wl_data_source *source) { //printf("Drop performed\n"); } static void data_source_handle_dnd_finished(void *data, struct wl_data_source *source) { switch (last_dnd_action) { case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE: //printf("Destination has accepted the drop with a move action\n"); break; case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY: //printf("Destination has accepted the drop with a copy action\n"); break; } } static const struct wl_data_source_listener data_source_listener = { .target = data_source_handle_target, .send = data_source_handle_send, .cancelled = data_source_handle_cancelled, .dnd_drop_performed = data_source_handle_dnd_drop_performed, .dnd_finished = data_source_handle_dnd_finished, .action = data_source_handle_action, }; static struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen_from_text(const char *text, int scale) { const char *p, *q; int width = 0, height, w2, ltext = strlen(text); fl_font(FL_HELVETICA, 10 * scale); p = text; int nl = 0; while(nl < 20 && (q=strchr(p, '\n')) != NULL) { nl++; w2 = int(fl_width(p, q - p)); if (w2 > width) width = w2; p = q + 1; } if (nl < 20 && text[ ltext - 1] != '\n') { nl++; w2 = int(fl_width(p)); if (w2 > width) width = w2; } if (width > 300*scale) width = 300*scale; height = nl * fl_height() + 3; width += 6; width = ceil(width/float(scale)) * scale; // these must be multiples of scale height = ceil(height/float(scale)) * scale; struct Fl_Wayland_Graphics_Driver::wld_buffer *off; Fl_Image_Surface *surf = Fl_Wayland_Graphics_Driver::custom_offscreen( width, height, &off); Fl_Surface_Device::push_current(surf); p = text; fl_font(FL_HELVETICA, 10 * scale); int y = fl_height(); while (nl > 0) { q = strchr(p, '\n'); if (q) { fl_draw(p, q - p, 3, y); } else { fl_draw(p, 3, y); break; } y += fl_height(); p = q + 1; nl--; } Fl_Surface_Device::pop_current(); delete surf; cairo_surface_flush( cairo_get_target(off->draw_buffer.cairo_) ); memcpy(off->data, off->draw_buffer.buffer, off->draw_buffer.data_size); return off; } int Fl_Wayland_Screen_Driver::dnd(int use_selection) { Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); struct wl_data_source *source = wl_data_device_manager_create_data_source(scr_driver->seat->data_device_manager); // we transmit the adequate value of index in fl_selection_buffer[index] wl_data_source_add_listener(source, &data_source_listener, (void*)0); wl_data_source_offer(source, wld_plain_text_clipboard); wl_data_source_set_actions(source, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); struct Fl_Wayland_Graphics_Driver::wld_buffer *off = NULL; int s = 1; if (use_selection) { // use the text as dragging icon Fl_Widget *current = Fl::pushed() ? Fl::pushed() : Fl::first_window(); s = Fl_Wayland_Window_Driver::driver(current->top_window())->wld_scale(); off = (struct Fl_Wayland_Graphics_Driver::wld_buffer *)offscreen_from_text(fl_selection_buffer[0], s); dnd_icon = wl_compositor_create_surface(scr_driver->wl_compositor); } else dnd_icon = NULL; doing_dnd = true; wl_data_device_start_drag(scr_driver->seat->data_device, source, scr_driver->seat->pointer_focus, dnd_icon, scr_driver->seat->serial); if (use_selection) { wl_surface_attach(dnd_icon, off->wl_buffer, 0, 0); wl_surface_set_buffer_scale(dnd_icon, s); wl_surface_damage(dnd_icon, 0, 0, 10000, 10000); wl_surface_commit(dnd_icon); wl_surface_set_user_data(dnd_icon, off); } else { static struct wl_cursor *dnd_cursor = scr_driver->cache_cursor("dnd-copy"); if (dnd_cursor) { save_cursor = scr_driver->default_cursor(); scr_driver->default_cursor(dnd_cursor); scr_driver->set_cursor(); } else save_cursor = NULL; } return 1; } static void data_offer_handle_offer(void *data, struct wl_data_offer *offer, const char *mime_type) { // runs when app becomes active and lists possible clipboard types //fprintf(stderr, "Clipboard offer=%p supports MIME type: %s\n", offer, mime_type); if (strcmp(mime_type, "image/png") == 0) { fl_selection_type[1] = Fl::clipboard_image; fl_selection_offer_type = "image/png"; } else if (strcmp(mime_type, "image/bmp") == 0 && (!fl_selection_offer_type || strcmp(fl_selection_offer_type, "image/png"))) { fl_selection_type[1] = Fl::clipboard_image; fl_selection_offer_type = "image/bmp"; } else if (strcmp(mime_type, "text/uri-list") == 0 && !fl_selection_type[1]) { fl_selection_type[1] = Fl::clipboard_plain_text; fl_selection_offer_type = "text/uri-list"; } else if (strcmp(mime_type, wld_plain_text_clipboard) == 0 && !fl_selection_type[1]) { fl_selection_type[1] = Fl::clipboard_plain_text; fl_selection_offer_type = wld_plain_text_clipboard; } else if (strcmp(mime_type, "text/plain") == 0 && !fl_selection_type[1]) { fl_selection_type[1] = Fl::clipboard_plain_text; fl_selection_offer_type = "text/plain"; } else if (strcmp(mime_type, "UTF8_STRING") == 0 && !fl_selection_type[1]) { fl_selection_type[1] = Fl::clipboard_plain_text; fl_selection_offer_type = "text/plain"; } } static void data_offer_handle_source_actions(void *data, struct wl_data_offer *offer, uint32_t actions) { if (actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) { //printf("Drag supports the copy action\n"); } } static void data_offer_handle_action(void *data, struct wl_data_offer *offer, uint32_t dnd_action) { switch (dnd_action) { case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE: //printf("A move action would be performed if dropped\n"); break; case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY: //printf("A copy action would be performed if dropped\n"); break; case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE: //printf("The drag would be rejected if dropped\n"); break; } } static const struct wl_data_offer_listener data_offer_listener = { .offer = data_offer_handle_offer, .source_actions = data_offer_handle_source_actions, .action = data_offer_handle_action, }; static void data_device_handle_data_offer(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer) { // An application has created a new data source //fprintf(stderr, "data_device_handle_data_offer offer=%p\n", offer); fl_selection_type[1] = NULL; fl_selection_offer_type = NULL; wl_data_offer_add_listener(offer, &data_offer_listener, NULL); } static void data_device_handle_selection(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer) { // An application has set the clipboard contents. W //fprintf(stderr, "data_device_handle_selection\n"); if (fl_selection_offer) wl_data_offer_destroy(fl_selection_offer); fl_selection_offer = offer; //if (offer == NULL) fprintf(stderr, "Clipboard is empty\n"); } // Gets from the system the clipboard or dnd text and puts it in fl_selection_buffer[1] // which is enlarged if necessary. static void get_clipboard_or_dragged_text(struct wl_data_offer *offer) { int fds[2]; char *from; if (pipe(fds)) return; wl_data_offer_receive(offer, fl_selection_offer_type, fds[1]); close(fds[1]); wl_display_flush(Fl_Wayland_Screen_Driver::wl_display); // read in fl_selection_buffer char *to = fl_selection_buffer[1]; ssize_t rest = fl_selection_buffer_length[1]; while (rest) { ssize_t n = read(fds[0], to, rest); if (n <= 0) { close(fds[0]); fl_selection_length[1] = to - fl_selection_buffer[1]; fl_selection_buffer[1][ fl_selection_length[1] ] = 0; goto way_out; } n = Fl_Screen_Driver::convert_crlf(to, n); to += n; rest -= n; } // compute size of unread clipboard data rest = fl_selection_buffer_length[1]; while (true) { char buf[1000]; ssize_t n = read(fds[0], buf, sizeof(buf)); if (n <= 0) { close(fds[0]); break; } rest += n; } //fprintf(stderr, "get_clipboard_or_dragged_text: size=%ld\n", rest); // read full clipboard data if (pipe(fds)) goto way_out; wl_data_offer_receive(offer, fl_selection_offer_type, fds[1]); close(fds[1]); wl_display_flush(Fl_Wayland_Screen_Driver::wl_display); if (rest+1 > fl_selection_buffer_length[1]) { delete[] fl_selection_buffer[1]; fl_selection_buffer[1] = new char[rest+1000+1]; fl_selection_buffer_length[1] = rest+1000; } from = fl_selection_buffer[1]; while (true) { ssize_t n = read(fds[0], from, rest); if (n <= 0) { close(fds[0]); break; } n = Fl_Screen_Driver::convert_crlf(from, n); from += n; } fl_selection_length[1] = from - fl_selection_buffer[1]; fl_selection_buffer[1][fl_selection_length[1]] = 0; way_out: if (strcmp(fl_selection_offer_type, "text/uri-list") == 0) { fl_decode_uri(fl_selection_buffer[1]); // decode encoded bytes char *p = fl_selection_buffer[1]; while (*p) { // remove prefixes if (strncmp(p, "file://", 7) == 0) { memmove(p, p+7, strlen(p+7)+1); } p = strchr(p, '\n'); if (!p) break; if (*++p == 0) *(p-1) = 0; // remove last '\n' } fl_selection_length[1] = strlen(fl_selection_buffer[1]); } Fl::e_clipboard_type = Fl::clipboard_plain_text; } static struct wl_data_offer *current_drag_offer = NULL; static uint32_t fl_dnd_serial; static void data_device_handle_enter(void *data, struct wl_data_device *data_device, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *offer) { Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(surface); //printf("Drag entered our surface %p(win=%p) at %dx%d\n", surface, win, wl_fixed_to_int(x), wl_fixed_to_int(y)); if (win) { fl_dnd_target_surface = surface; float f = Fl::screen_scale(win->screen_num()); Fl::e_x = wl_fixed_to_int(x) / f; Fl::e_y = wl_fixed_to_int(y) / f; while (win->parent()) { Fl::e_x += win->x(); Fl::e_y += win->y(); win = win->window(); } fl_dnd_target_window = win; Fl::e_x_root = Fl::e_x + fl_dnd_target_window->x(); Fl::e_y_root = Fl::e_y + fl_dnd_target_window->y(); Fl::handle(FL_DND_ENTER, fl_dnd_target_window); current_drag_offer = offer; fl_dnd_serial = serial; } uint32_t supported_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; uint32_t preferred_action = supported_actions; wl_data_offer_set_actions(offer, supported_actions, preferred_action); } static void data_device_handle_motion(void *data, struct wl_data_device *data_device, uint32_t time, wl_fixed_t x, wl_fixed_t y) { if (!current_drag_offer) return; //printf("data_device_handle_motion fl_dnd_target_window=%p\n", fl_dnd_target_window); int ret = 0; if (fl_dnd_target_window) { float f = Fl::screen_scale(fl_dnd_target_window->screen_num()); Fl_Window *win = Fl_Wayland_Window_Driver::surface_to_window(fl_dnd_target_surface); Fl::e_x = wl_fixed_to_int(x) / f; Fl::e_y = wl_fixed_to_int(y) / f; while (win->parent()) { Fl::e_x += win->x(); Fl::e_y += win->y(); win = win->window(); } Fl::e_x_root = Fl::e_x + fl_dnd_target_window->x(); Fl::e_y_root = Fl::e_y + fl_dnd_target_window->y(); ret = Fl::handle(FL_DND_DRAG, fl_dnd_target_window); if (Fl::belowmouse()) Fl::belowmouse()->take_focus(); } uint32_t supported_actions = ret && (Fl::pushed() || !doing_dnd) ? WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY : WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; uint32_t preferred_action = supported_actions; wl_data_offer_set_actions(current_drag_offer, supported_actions, preferred_action); wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); if (ret && current_drag_offer) wl_data_offer_accept(current_drag_offer, fl_dnd_serial, "text/plain"); } static void data_device_handle_leave(void *data, struct wl_data_device *data_device) { //printf("Drag left our surface\n"); if (current_drag_offer) Fl::handle(FL_DND_LEAVE, fl_dnd_target_window); } static void data_device_handle_drop(void *data, struct wl_data_device *data_device) { if (!current_drag_offer) return; Fl::handle(FL_ENTER, fl_dnd_target_window); // useful to set the belowmouse widget int ret = Fl::handle(FL_DND_RELEASE, fl_dnd_target_window); //printf("data_device_handle_drop ret=%d doing_dnd=%d\n", ret, doing_dnd); if (!ret) { wl_data_offer_destroy(current_drag_offer); current_drag_offer = NULL; return; } if (doing_dnd) { Fl::e_text = fl_selection_buffer[0]; Fl::e_length = fl_selection_length[0]; } else { get_clipboard_or_dragged_text(current_drag_offer); Fl::e_text = fl_selection_buffer[1]; Fl::e_length = fl_selection_length[1]; } int old_event = Fl::e_number; Fl::belowmouse()->handle(Fl::e_number = FL_PASTE); Fl::e_number = old_event; wl_data_offer_finish(current_drag_offer); wl_data_offer_destroy(current_drag_offer); current_drag_offer = NULL; } static const struct wl_data_device_listener data_device_listener = { .data_offer = data_device_handle_data_offer, .enter = data_device_handle_enter, .leave = data_device_handle_leave, .motion = data_device_handle_motion, .drop = data_device_handle_drop, .selection = data_device_handle_selection, }; const struct wl_data_device_listener *Fl_Wayland_Screen_Driver::p_data_device_listener = &data_device_listener; // Reads from the clipboard an image which can be in image/bmp or image/png MIME type. // Returns 0 if OK, != 0 if error. static int get_clipboard_image() { int fds[2]; if (pipe(fds)) return 1; wl_data_offer_receive(fl_selection_offer, fl_selection_offer_type, fds[1]); close(fds[1]); wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); if (strcmp(fl_selection_offer_type, "image/png") == 0) { char tmp_fname[21]; Fl_Shared_Image *shared = 0; strcpy(tmp_fname, "/tmp/clipboardXXXXXX"); int fd = mkstemp(tmp_fname); if (fd == -1) return 1; while (true) { char buf[10000]; ssize_t n = read(fds[0], buf, sizeof(buf)); if (n <= 0) { close(fds[0]); close(fd); break; } n = write(fd, buf, n); } shared = Fl_Shared_Image::get(tmp_fname); fl_unlink(tmp_fname); if (!shared) return 1; int ld = shared->ld() ? shared->ld() : shared->w() * shared->d(); uchar *rgb = new uchar[shared->w() * shared->h() * shared->d()]; memcpy(rgb, shared->data()[0], ld * shared->h() ); Fl_RGB_Image *image = new Fl_RGB_Image(rgb, shared->w(), shared->h(), shared->d(), shared->ld()); shared->release(); image->alloc_array = 1; Fl::e_clipboard_data = (void*)image; } else { // process image/bmp uchar buf[54]; size_t rest = 1; char *bmp = NULL; ssize_t n = read(fds[0], buf, sizeof(buf)); // read size info of the BMP image if (n == sizeof(buf)) { int w, h; // size of the BMP image Fl_Unix_System_Driver::read_int(buf + 18, w); Fl_Unix_System_Driver::read_int(buf + 22, h); // the number of bytes per row of BMP image, rounded up to multiple of 4 int R = ((3*w+3)/4) * 4; bmp = new char[R * h + 54]; memcpy(bmp, buf, 54); char *from = bmp + 54; rest = R * h; while (rest) { ssize_t n = read(fds[0], from, rest); if (n <= 0) break; from += n; rest -= n; } //fprintf(stderr, "get_clipboard_image: image/bmp %dx%d rest=%lu\n", w,h,rest); } close(fds[0]); if (!rest) Fl::e_clipboard_data = Fl_Unix_System_Driver::own_bmp_to_RGB(bmp); delete[] bmp; if (rest) return 1; } Fl::e_clipboard_type = Fl::clipboard_image; return 0; } void Fl_Wayland_Screen_Driver::paste(Fl_Widget &receiver, int clipboard, const char *type) { if (clipboard != 1) return; if (fl_i_own_selection[1]) { // We already have it, do it quickly without compositor. if (type == Fl::clipboard_plain_text && fl_selection_type[1] == type) { Fl::e_text = fl_selection_buffer[1]; Fl::e_length = fl_selection_length[1]; if (!Fl::e_text) Fl::e_text = (char *)""; } else if (type == Fl::clipboard_image && fl_selection_type[1] == type) { Fl::e_clipboard_data = Fl_Unix_System_Driver::own_bmp_to_RGB(fl_selection_buffer[1]); Fl::e_clipboard_type = Fl::clipboard_image; } else return; receiver.handle(FL_PASTE); return; } // otherwise get the compositor to return it: if (!fl_selection_offer) return; if (type == Fl::clipboard_plain_text && clipboard_contains(Fl::clipboard_plain_text)) { get_clipboard_or_dragged_text(fl_selection_offer); Fl::e_text = fl_selection_buffer[1]; Fl::e_length = fl_selection_length[1]; receiver.handle(FL_PASTE); } else if (type == Fl::clipboard_image && clipboard_contains(Fl::clipboard_image)) { if (get_clipboard_image()) return; struct wld_window * xid = fl_wl_xid(receiver.top_window()); if (xid) { int s = Fl_Wayland_Window_Driver::driver(receiver.top_window())->wld_scale(); if ( s > 1) { Fl_RGB_Image *rgb = (Fl_RGB_Image*)Fl::e_clipboard_data; rgb->scale(rgb->data_w() / s, rgb->data_h() / s); } } int done = receiver.handle(FL_PASTE); Fl::e_clipboard_type = ""; if (done == 0) { delete (Fl_RGB_Image*)Fl::e_clipboard_data; Fl::e_clipboard_data = NULL; } } } void Fl_Wayland_Screen_Driver::copy(const char *stuff, int len, int clipboard, const char *type) { if (!stuff || len < 0) return; if (clipboard >= 2) clipboard = 1; // Only on X11 do multiple clipboards make sense. if (len+1 > fl_selection_buffer_length[clipboard]) { delete[] fl_selection_buffer[clipboard]; fl_selection_buffer[clipboard] = new char[len+100]; fl_selection_buffer_length[clipboard] = len+100; } memcpy(fl_selection_buffer[clipboard], stuff, len); fl_selection_buffer[clipboard][len] = 0; // needed for direct paste fl_selection_length[clipboard] = len; fl_i_own_selection[clipboard] = 1; fl_selection_type[clipboard] = Fl::clipboard_plain_text; if (clipboard == 1) { if (seat->data_source) wl_data_source_destroy(seat->data_source); seat->data_source = wl_data_device_manager_create_data_source(seat->data_device_manager); // we transmit the adequate value of index in fl_selection_buffer[index] wl_data_source_add_listener(seat->data_source, &data_source_listener, (void*)1); wl_data_source_offer(seat->data_source, wld_plain_text_clipboard); wl_data_device_set_selection(seat->data_device, seat->data_source, seat->keyboard_enter_serial); //fprintf(stderr, "wl_data_device_set_selection len=%d to %d\n", len, clipboard); } } // takes a raw RGB image and puts it in the copy/paste buffer void Fl_Wayland_Screen_Driver::copy_image(const unsigned char *data, int W, int H){ if (!data || W <= 0 || H <= 0) return; delete[] fl_selection_buffer[1]; fl_selection_buffer[1] = (char *)Fl_Unix_System_Driver::create_bmp(data,W,H,&fl_selection_length[1]); fl_selection_buffer_length[1] = fl_selection_length[1]; fl_i_own_selection[1] = 1; fl_selection_type[1] = Fl::clipboard_image; if (seat->data_source) wl_data_source_destroy(seat->data_source); seat->data_source = wl_data_device_manager_create_data_source(seat->data_device_manager); // we transmit the adequate value of index in fl_selection_buffer[index] wl_data_source_add_listener(seat->data_source, &data_source_listener, (void*)1); wl_data_source_offer(seat->data_source, "image/bmp"); wl_data_device_set_selection(seat->data_device, seat->data_source, seat->keyboard_enter_serial); //fprintf(stderr, "copy_image: len=%d\n", fl_selection_length[1]); } //////////////////////////////////////////////////////////////// // Code for tracking clipboard changes: // is that possible with Wayland ? //////////////////////////////////////////////////////////////// #endif // !defined(FL_DOXYGEN) fltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Window_Driver.H0000644000175000017500000001534115004135251023450 0ustar albrechtalbrecht// // Definition of Wayland window driver for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Wayland_Window_Driver.H \brief Definition of Wayland window driver. */ #ifndef FL_WAYLAND_WINDOW_DRIVER_H #define FL_WAYLAND_WINDOW_DRIVER_H #include "../../Fl_Window_Driver.H" #include #include "Fl_Wayland_Screen_Driver.H" #include "Fl_Wayland_Graphics_Driver.H" /* Move everything here that manages the native window interface. There is one window driver for each Fl_Window. Window drivers manage window actions such as resizing, events, decoration, fullscreen modes, etc. . All drawing and rendering is managed by the Surface device and the associated graphics driver. - window specific event handling - window types and styles, depth, etc. - decorations */ typedef struct _cairo_pattern cairo_pattern_t; typedef struct _cairo_rectangle_int cairo_rectangle_int_t; class Fl_Wayland_Plugin; class Fl_Wayland_Window_Driver : public Fl_Window_Driver { friend class Fl_Wayland_Gl_Window_Driver; private: struct shape_data_type { int lw_; ///< width of shape image int lh_; ///< height of shape image Fl_Image* shape_; ///< shape image cairo_pattern_t *mask_pattern_; } *shape_data_; bool can_expand_outside_parent_; // specially to allow window docking (#987) cairo_rectangle_int_t *subRect_; // makes sure subwindow remains inside its parent window static bool in_flush_; // useful for progressive window drawing Fl_Cursor standard_cursor_; // window's standard custom kind struct gl_start_support *gl_start_support_; // for support of gl_start/gl_finish bool is_popup_window_; public: inline Fl_Cursor standard_cursor() { return standard_cursor_; }; bool in_handle_configure; // distinguish OS and user window resize // --- support for screen-specific scaling factors struct type_for_resize_window_between_screens { int screen; bool busy; }; struct surface_output { // for linked list of displays where a surface maps struct Fl_Wayland_Screen_Driver::output *output; struct wl_list link; }; struct custom_cursor { struct wl_cursor *wl_cursor; const Fl_RGB_Image *rgb; int hotx, hoty; }; static void delete_cursor(struct custom_cursor *custom, bool delete_rgb = true); static type_for_resize_window_between_screens data_for_resize_window_between_screens_; void decorated_win_size(int &w, int &h); void shape_bitmap_(Fl_Image* b); void shape_alpha_(Fl_Image* img, int offset) FL_OVERRIDE; FL_EXPORT int wld_scale(); // used by class Fl_Wayland_Gl_Window_Driver cairo_rectangle_int_t *subRect() { return subRect_; } // getter void subRect(cairo_rectangle_int_t *r); // setter void checkSubwindowFrame(); enum kind {DECORATED, SUBWINDOW, POPUP, UNFRAMED}; struct xdg_toplevel *xdg_toplevel(); Fl_Wayland_Window_Driver(Fl_Window*); virtual ~Fl_Wayland_Window_Driver(); static struct wld_window *wld_window; static Fl_Window *surface_to_window(struct wl_surface *); static inline Fl_Wayland_Window_Driver* driver(const Fl_Window *w) { return (Fl_Wayland_Window_Driver*)Fl_Window_Driver::driver(w); } static void resize_after_screen_change(void *data); static Fl_Wayland_Plugin *gl_plugin(); // --- window data int decorated_w() FL_OVERRIDE; int decorated_h() FL_OVERRIDE; const Fl_Image* shape() FL_OVERRIDE; // --- window management void makeWindow() FL_OVERRIDE; void take_focus() FL_OVERRIDE; void flush() FL_OVERRIDE; void flush_overlay() FL_OVERRIDE; void draw_end() FL_OVERRIDE; void make_current() FL_OVERRIDE; void show() FL_OVERRIDE; void resize(int X,int Y,int W,int H) FL_OVERRIDE; void label(const char *name, const char *mininame) FL_OVERRIDE; void hide() FL_OVERRIDE; void map() FL_OVERRIDE; void unmap() FL_OVERRIDE; void fullscreen_on() FL_OVERRIDE; void fullscreen_off(int X, int Y, int W, int H) FL_OVERRIDE; void maximize() FL_OVERRIDE; void un_maximize() FL_OVERRIDE; void use_border() FL_OVERRIDE; void size_range() FL_OVERRIDE; void iconize() FL_OVERRIDE; void decoration_sizes(int *top, int *left, int *right, int *bottom) FL_OVERRIDE; // --- window cursor stuff int set_cursor(Fl_Cursor) FL_OVERRIDE; int set_cursor(const Fl_RGB_Image*, int, int) FL_OVERRIDE; int set_cursor_4args(const Fl_RGB_Image*, int, int, bool); void shape(const Fl_Image* img) FL_OVERRIDE; void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) FL_OVERRIDE; int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data) FL_OVERRIDE; void wait_for_expose() FL_OVERRIDE; // menu-related stuff void reposition_menu_window(int x, int y) FL_OVERRIDE; void menu_window_area(int &X, int &Y, int &W, int &H, int nscreen = -1) FL_OVERRIDE; static bool new_popup; // to support tall menu buttons bool process_menu_or_tooltip(struct wld_window *); static Fl_Window *previous_floatingtitle; // to support floating menuwindow w/ title void allow_expand_outside_parent() FL_OVERRIDE { can_expand_outside_parent_ = true; } }; struct wld_window { Fl_Window *fl_win; struct wl_list outputs; // linked list of displays where part or whole of window maps struct wl_surface *wl_surface; struct wl_callback *frame_cb; struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer; struct xdg_surface *xdg_surface; enum Fl_Wayland_Window_Driver::kind kind; union { // for each value of kind struct libdecor_frame *frame; struct wl_subsurface *subsurface; struct xdg_popup *xdg_popup; struct xdg_toplevel *xdg_toplevel; }; // non-null when using custom cursor struct Fl_Wayland_Window_Driver::custom_cursor *custom_cursor; int configured_width; int configured_height; int floating_width; int floating_height; int state; bool covered; // specially for Mutter and issue #878 }; class Fl_Wayland_Plugin : public Fl_Plugin { public: Fl_Wayland_Plugin(const char *pluginName) : Fl_Plugin(klass(), pluginName) { } virtual const char *klass() { return "wayland.fltk.org"; } virtual const char *name() = 0; virtual void do_swap(Fl_Window*) = 0; virtual void invalidate(Fl_Window*) = 0; virtual void terminate() = 0; virtual void destroy(struct gl_start_support *) = 0; }; #endif // FL_WAYLAND_WINDOW_DRIVER_H fltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H0000644000175000017500000000232015004135251024664 0ustar albrechtalbrecht// // Draw-to-image code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_WAYLAND_IMAGE_SURFACE_DRIVER_H #define FL_WAYLAND_IMAGE_SURFACE_DRIVER_H #include class Fl_Wayland_Image_Surface_Driver : public Fl_Image_Surface_Driver { void end_current() FL_OVERRIDE; struct wld_window *pre_window; public: Fl_Wayland_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off); ~Fl_Wayland_Image_Surface_Driver(); void mask(const Fl_RGB_Image *) FL_OVERRIDE; struct shape_data_type { double scale; cairo_pattern_t *mask_pattern_; cairo_t *bg_cr; } *shape_data_; void set_current() FL_OVERRIDE; void translate(int x, int y) FL_OVERRIDE; void untranslate() FL_OVERRIDE; Fl_RGB_Image *image() FL_OVERRIDE; }; #endif // FL_WAYLAND_IMAGE_SURFACE_DRIVER_H fltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H0000644000175000017500000000524215004135251023740 0ustar albrechtalbrecht// // Definition of class Fl_Wayland_Graphics_Driver. // // Copyright 2021-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Wayland_Graphics_Driver.H \brief Definition of Wayland graphics driver. */ #ifndef FL_WAYLAND_GRAPHICS_DRIVER_H #define FL_WAYLAND_GRAPHICS_DRIVER_H #include "../Cairo/Fl_Cairo_Graphics_Driver.H" #include // for uint32_t #include // for wl_list class Fl_Wayland_Graphics_Driver : public Fl_Cairo_Graphics_Driver { public: struct draw_buffer { unsigned char *buffer; cairo_t *cairo_; size_t data_size; // of wl_buffer and buffer int stride; int width; }; struct wld_buffer { struct draw_buffer draw_buffer; struct wl_list link; // links all buffers from the same wl_shm_pool struct wl_buffer *wl_buffer; void *data; struct wl_shm_pool *shm_pool; bool draw_buffer_needs_commit; bool in_use; // true while being committed bool released; // true after buffer_release() was called }; struct wld_shm_pool_data { // one record attached to each wl_shm_pool object char *pool_memory; // start of mmap'ed memory encapsulated by the wl_shm_pool size_t pool_size; // size of encapsulated memory struct wl_list buffers; // to list of fl_wld_buffer's from this pool }; static const uint32_t wld_format; static struct wl_shm_pool *current_pool; static FL_EXPORT const struct wl_callback_listener *p_surface_frame_listener; void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc, int srcx, int srcy) FL_OVERRIDE; void cache_size(Fl_Image *img, int &width, int &height) FL_OVERRIDE; static struct wld_buffer *create_wld_buffer(int width, int height, bool with_shm = true); static void create_shm_buffer(wld_buffer *buffer); static void buffer_release(struct wld_window *window); static void buffer_commit(struct wld_window *window, cairo_region_t *r = NULL); static void cairo_init(struct draw_buffer *buffer, int width, int height, int stride, cairo_format_t format); // used by class Fl_Wayland_Gl_Window_Driver static FL_EXPORT struct draw_buffer *offscreen_buffer(Fl_Offscreen); static const cairo_user_data_key_t key; static Fl_Image_Surface *custom_offscreen(int w, int h, struct wld_buffer **buffer); }; #endif // FL_WAYLAND_GRAPHICS_DRIVER_H fltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.H0000644000175000017500000000200215004135251024551 0ustar albrechtalbrecht// // Copy-to-clipboard code for the Fast Light Tool Kit (FLTK). // // Copyright 2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_WAYLAND_COPY_SURFACE_DRIVER_H #define FL_WAYLAND_COPY_SURFACE_DRIVER_H #include #include class Fl_Wayland_Copy_Surface_Driver : public Fl_Copy_Surface_Driver { friend class Fl_Copy_Surface_Driver; Fl_Image_Surface *img_surf; protected: Fl_Wayland_Copy_Surface_Driver(int w, int h); ~Fl_Wayland_Copy_Surface_Driver(); void set_current() FL_OVERRIDE; void translate(int x, int y) FL_OVERRIDE; void untranslate() FL_OVERRIDE; }; #endif // FL_WAYLAND_COPY_SURFACE_DRIVER_H fltk-1.4.3/src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx0000644000175000017500000001560215004135251025306 0ustar albrechtalbrecht// // Draw-to-image code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Wayland_Graphics_Driver.H" #include "Fl_Wayland_Window_Driver.H" #include "Fl_Wayland_Image_Surface_Driver.H" Fl_Wayland_Image_Surface_Driver::Fl_Wayland_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) { shape_data_ = NULL; float s = 1; int d = 1; if (!off) { fl_open_display(); if (Fl::first_window()) { d = Fl_Wayland_Window_Driver::driver(Fl::first_window())->wld_scale(); } s = Fl_Graphics_Driver::default_driver().scale(); if (d*s != 1 && high_res) { w = int(w * s) * d; h = int(h * s) * d; } struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ = (struct Fl_Wayland_Graphics_Driver::draw_buffer*)calloc(1, sizeof(struct Fl_Wayland_Graphics_Driver::draw_buffer)); Fl_Wayland_Graphics_Driver::cairo_init(off_, w, h, cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w), CAIRO_FORMAT_RGB24); offscreen = (Fl_Offscreen)off_->cairo_; cairo_set_user_data(off_->cairo_, &Fl_Wayland_Graphics_Driver::key, off_, NULL); if (d*s != 1 && high_res) cairo_scale((cairo_t*)offscreen, d*s, d*s); } driver(new Fl_Wayland_Graphics_Driver()); if (d*s != 1 && high_res) driver()->scale(d*s); } Fl_Wayland_Image_Surface_Driver::~Fl_Wayland_Image_Surface_Driver() { if (shape_data_) { cairo_surface_t *surf; cairo_pattern_get_surface(shape_data_->mask_pattern_, &surf); unsigned char *bits = cairo_image_surface_get_data(surf); cairo_pattern_destroy(shape_data_->mask_pattern_); delete[] bits; struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ = Fl_Wayland_Graphics_Driver::offscreen_buffer((Fl_Offscreen)shape_data_->bg_cr); delete[] off_->buffer; free(off_); cairo_destroy(shape_data_->bg_cr); free(shape_data_); } if (offscreen && !external_offscreen) { struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer = Fl_Wayland_Graphics_Driver::offscreen_buffer(offscreen); cairo_destroy((cairo_t *)offscreen); delete[] buffer->buffer; free(buffer); } delete driver(); } void Fl_Wayland_Image_Surface_Driver::set_current() { Fl_Surface_Device::set_current(); Fl_Cairo_Graphics_Driver *dr = (Fl_Cairo_Graphics_Driver*)driver(); if (!dr->cr()) dr->set_cairo((cairo_t*)offscreen); pre_window = Fl_Wayland_Window_Driver::wld_window; Fl_Wayland_Window_Driver::wld_window = NULL; fl_window = 0; } void Fl_Wayland_Image_Surface_Driver::end_current() { cairo_surface_t *surf = cairo_get_target((cairo_t*)offscreen); cairo_surface_flush(surf); Fl_Wayland_Window_Driver::wld_window = pre_window; fl_window = (Window)pre_window; Fl_Surface_Device::end_current(); } void Fl_Wayland_Image_Surface_Driver::translate(int x, int y) { ((Fl_Wayland_Graphics_Driver*)driver())->ps_translate(x, y); } void Fl_Wayland_Image_Surface_Driver::untranslate() { ((Fl_Wayland_Graphics_Driver*)driver())->ps_untranslate(); } Fl_RGB_Image* Fl_Wayland_Image_Surface_Driver::image() { if (shape_data_ && shape_data_->mask_pattern_) { // draw above the secondary offscreen the main offscreen masked by mask_pattern_ cairo_t *c = ((Fl_Cairo_Graphics_Driver*)driver())->cr(); cairo_pattern_t *paint_pattern = cairo_pattern_create_for_surface(cairo_get_target(c)); cairo_set_source(shape_data_->bg_cr, paint_pattern); cairo_mask(shape_data_->bg_cr, shape_data_->mask_pattern_); cairo_pattern_destroy(paint_pattern); // copy secondary offscreen to the main offscreen cairo_pattern_t *pat = cairo_pattern_create_for_surface(cairo_get_target(shape_data_->bg_cr)); cairo_scale(c, shape_data_->scale, shape_data_->scale); cairo_set_source(c, pat), cairo_paint(c); cairo_pattern_destroy(pat); // delete secondary offscreen cairo_surface_t *surf; cairo_pattern_get_surface(shape_data_->mask_pattern_, &surf); unsigned char *bits = cairo_image_surface_get_data(surf); cairo_pattern_destroy(shape_data_->mask_pattern_); delete[] bits; struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ = Fl_Wayland_Graphics_Driver::offscreen_buffer((Fl_Offscreen)shape_data_->bg_cr); delete[] off_->buffer; free(off_); cairo_destroy(shape_data_->bg_cr); free(shape_data_); shape_data_ = NULL; } // Convert depth-4 image in draw_buffer to a depth-3 image while exchanging R and B colors struct Fl_Wayland_Graphics_Driver::draw_buffer *off_buf = Fl_Wayland_Graphics_Driver::offscreen_buffer(offscreen); int height = int(off_buf->data_size / off_buf->stride); uchar *rgb = new uchar[off_buf->width * height * 3]; uchar *p = rgb; uchar *q; for (int j = 0; j < height; j++) { q = off_buf->buffer + j*off_buf->stride; for (int i = 0; i < off_buf->width; i++) { // exchange R and B colors, transmit G *p = *(q+2); *(p+1) = *(q+1); *(p+2) = *q; p += 3; q += 4; } } Fl_RGB_Image *image = new Fl_RGB_Image(rgb, off_buf->width, height, 3); image->alloc_array = 1; return image; } void Fl_Wayland_Image_Surface_Driver::mask(const Fl_RGB_Image *mask) { bool using_copy = false; shape_data_ = (struct shape_data_type*)calloc(1, sizeof(struct shape_data_type)); int W, H; struct Fl_Wayland_Graphics_Driver::draw_buffer *off_buf = Fl_Wayland_Graphics_Driver::offscreen_buffer(offscreen); W = off_buf->width; H = (int)(off_buf->data_size / off_buf->stride); if (W != mask->data_w() || H != mask->data_h()) { Fl_RGB_Image *copy = (Fl_RGB_Image*)mask->copy(W, H); mask = copy; using_copy = true; } shape_data_->mask_pattern_ = Fl_Cairo_Graphics_Driver::calc_cairo_mask(mask); //duplicate current offscreen content to new cairo_t* shape_data_->bg_cr int width, height; printable_rect(&width, &height); struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ = (struct Fl_Wayland_Graphics_Driver::draw_buffer*)calloc(1, sizeof(struct Fl_Wayland_Graphics_Driver::draw_buffer)); Fl_Wayland_Graphics_Driver::cairo_init(off_, W, H, cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, W), CAIRO_FORMAT_RGB24); cairo_set_user_data(off_->cairo_, &Fl_Wayland_Graphics_Driver::key, off_, NULL); shape_data_->bg_cr = off_->cairo_; memcpy(off_->buffer, off_buf->buffer, off_buf->data_size); shape_data_->scale = double(width) / W; if (using_copy) delete mask; } fltk-1.4.3/src/drivers/Quartz/0000755000175000017500000000000015004135251016340 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx0000644000175000017500000001407615004135251025070 0ustar albrechtalbrecht// // Draw-to-image code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "Fl_Quartz_Image_Surface_Driver.H" #include "Fl_Quartz_Graphics_Driver.H" #include "../Cocoa/Fl_Cocoa_Window_Driver.H" #include Fl_Quartz_Image_Surface_Driver::Fl_Quartz_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) { # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 mask_ = NULL; #endif int W = w, H = h; float s = 1; if (high_res) { s = Fl_Graphics_Driver::default_driver().scale(); Fl_Window *cw = Fl::first_window(); Fl_Cocoa_Window_Driver *dr = cw ? Fl_Cocoa_Window_Driver::driver(cw) : NULL; if (dr && dr->mapped_to_retina()) s *= 2; W *= s; H *= s; } CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); offscreen = off ? off : (Fl_Offscreen)CGBitmapContextCreate(calloc(W*H,4), W, H, 8, W*4, lut, kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(lut); driver(new Fl_Quartz_Graphics_Driver); CGContextTranslateCTM((CGContextRef)offscreen, 0.5*s, -0.5*s); // as when drawing to a window if (high_res) { CGContextScaleCTM((CGContextRef)offscreen, s, s); driver()->scale(s); } CGContextSetShouldAntialias((CGContextRef)offscreen, false); CGContextTranslateCTM((CGContextRef)offscreen, 0, height); CGContextScaleCTM((CGContextRef)offscreen, 1.0f, -1.0f); CGContextSaveGState((CGContextRef)offscreen); CGContextSetRGBFillColor((CGContextRef)offscreen, 1, 1, 1, 0); CGContextFillRect((CGContextRef)offscreen, CGRectMake(0,0,w,h)); } Fl_Quartz_Image_Surface_Driver::~Fl_Quartz_Image_Surface_Driver() { # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (mask_) { CGImageRelease(mask_); } #endif if (offscreen) CGContextRestoreGState((CGContextRef)offscreen); if (offscreen && !external_offscreen) { void *data = CGBitmapContextGetData((CGContextRef)offscreen); free(data); CGContextRelease((CGContextRef)offscreen); } delete driver(); } void Fl_Quartz_Image_Surface_Driver::set_current() { Fl_Surface_Device::set_current(); pre_window = fl_window; driver()->gc((CGContextRef)offscreen); fl_window = 0; ((Fl_Quartz_Graphics_Driver*)driver())->high_resolution( CGBitmapContextGetWidth((CGContextRef)offscreen) > (size_t)width ); # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (mask_) { int W, H; printable_rect(&W, &H); CGContextSaveGState((CGContextRef)offscreen); CGContextClipToMask((CGContextRef)offscreen, CGRectMake(0,0,W,H), mask_); // 10.4 CGContextSaveGState((CGContextRef)offscreen); } # endif } void Fl_Quartz_Image_Surface_Driver::translate(int x, int y) { CGContextRestoreGState((CGContextRef)offscreen); CGContextSaveGState((CGContextRef)offscreen); CGContextTranslateCTM((CGContextRef)offscreen, x, y); CGContextSaveGState((CGContextRef)offscreen); } void Fl_Quartz_Image_Surface_Driver::untranslate() { CGContextRestoreGState((CGContextRef)offscreen); } Fl_RGB_Image* Fl_Quartz_Image_Surface_Driver::image() { CGContextFlush((CGContextRef)offscreen); # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (mask_) { CGContextRestoreGState((CGContextRef)offscreen); CGImageRelease(mask_); mask_ = NULL; } #endif int W = (int)CGBitmapContextGetWidth((CGContextRef)offscreen); int H = (int)CGBitmapContextGetHeight((CGContextRef)offscreen); int bpr = (int)CGBitmapContextGetBytesPerRow((CGContextRef)offscreen); int bpp = (int)CGBitmapContextGetBitsPerPixel((CGContextRef)offscreen)/8; uchar *base = (uchar*)CGBitmapContextGetData((CGContextRef)offscreen); int idx, idy; uchar *pdst, *psrc; unsigned char *data = new uchar[W * H * 3]; for (idy = 0, pdst = data; idy < H; idy ++) { for (idx = 0, psrc = base + idy * bpr; idx < W; idx ++, psrc += bpp, pdst += 3) { pdst[0] = psrc[0]; // R pdst[1] = psrc[1]; // G pdst[2] = psrc[2]; // B } } Fl_RGB_Image *image = new Fl_RGB_Image(data, W, H); image->alloc_array = 1; return image; } void Fl_Quartz_Image_Surface_Driver::end_current() { # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (mask_) { CGContextRestoreGState((CGContextRef)offscreen); CGContextRestoreGState((CGContextRef)offscreen); } # endif fl_window = pre_window; Fl_Surface_Device::end_current(); } # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 static void MyProviderReleaseData (void *info, const void *data, size_t size) { delete[] (uchar*)data; } void Fl_Quartz_Image_Surface_Driver::mask(const Fl_RGB_Image *img) { if (!&CGContextClipToMask) return; int W = (int)CGBitmapContextGetWidth((CGContextRef)offscreen); int H = (int)CGBitmapContextGetHeight((CGContextRef)offscreen); bool using_copy = false; if (W != img->data_w() || H != img->data_h()) { Fl_RGB_Image *copy = (Fl_RGB_Image*)img->copy(W, H); img = copy; using_copy = true; } int i, d = img->d(), w = img->data_w(), h = img->data_h(); // reverse top and bottom and convert to gray scale if img->d() == 3 and complement bits int bytes_per_row = (img->ld() ? img->ld() : w * d); uchar *from = new uchar[w * h]; for ( i = 0; i < h; i++) { const uchar *p = img->array + bytes_per_row * i; const uchar *last = p + bytes_per_row; uchar *q = from + (h - 1 - i) * w; while (p < last) { unsigned u = *p++; u += *p++; u += *p++; *q++ = ~(u/3); } } CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, w * h, MyProviderReleaseData); mask_ = CGImageMaskCreate(w, h, 8, 8, w, provider, NULL, false); CFRelease(provider); if (using_copy) delete img; } #endif fltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx0000644000175000017500000001325415004135251024133 0ustar albrechtalbrecht// // Rectangle drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Quartz_Graphics_Driver.H" #include "../Darwin/Fl_Darwin_System_Driver.H" #include "../Cocoa/Fl_Cocoa_Screen_Driver.H" #include #include #include #if HAS_ATSU && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 Fl_Quartz_Graphics_Driver::pter_to_draw_member Fl_Quartz_Graphics_Driver::CoreText_or_ATSU_draw; Fl_Quartz_Graphics_Driver::pter_to_width_member Fl_Quartz_Graphics_Driver::CoreText_or_ATSU_width; int Fl_Quartz_Graphics_Driver::CoreText_or_ATSU = 0; void Fl_Quartz_Graphics_Driver::init_CoreText_or_ATSU() { if (Fl_Darwin_System_Driver::calc_mac_os_version() < 100500) { // before Mac OS 10.5, only ATSU is available CoreText_or_ATSU = use_ATSU; CoreText_or_ATSU_draw = &Fl_Quartz_Graphics_Driver::draw_ATSU; CoreText_or_ATSU_width = &Fl_Quartz_Graphics_Driver::width_ATSU; } else { CoreText_or_ATSU = use_CoreText; CoreText_or_ATSU_draw = &Fl_Quartz_Graphics_Driver::draw_CoreText; CoreText_or_ATSU_width = &Fl_Quartz_Graphics_Driver::width_CoreText; } } #endif void Fl_Quartz_Graphics_Driver::antialias(int state) { } int Fl_Quartz_Graphics_Driver::antialias() { return 1; } Fl_Quartz_Graphics_Driver::Fl_Quartz_Graphics_Driver() : Fl_Graphics_Driver(), gc_(NULL) { quartz_line_width_ = 1.f; quartz_line_cap_ = kCGLineCapButt; quartz_line_join_ = kCGLineJoinMiter; quartz_line_pattern = 0; quartz_line_pattern_size = 0; high_resolution_ = false; #if HAS_ATSU && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (!CoreText_or_ATSU) init_CoreText_or_ATSU(); #endif } char Fl_Quartz_Graphics_Driver::can_do_alpha_blending() { return 1; } static void bmProviderRelease (void *src, const void *data, size_t size) { CFIndex count = CFGetRetainCount(src); CFRelease(src); if(count == 1) free((void*)data); } /* Reference to the current CGContext For back-compatibility only. The preferred procedure to get this reference is Fl_Surface_Device::surface()->driver()->gc(). */ CGContextRef fl_gc = 0; void Fl_Quartz_Graphics_Driver::global_gc() { fl_gc = (CGContextRef)gc(); } CGContextRef fl_mac_gc() { return fl_gc; } void Fl_Quartz_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc, int srcx, int srcy) { // draw portion srcx,srcy,w,h of osrc to position x,y (top-left) of the graphics driver's surface CGContextRef src = (CGContextRef)osrc; void *data = CGBitmapContextGetData(src); int sw = (int)CGBitmapContextGetWidth(src); int sh = (int)CGBitmapContextGetHeight(src); CGImageRef img; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (fl_mac_os_version >= 100400) img = CGBitmapContextCreateImage(src); // requires 10.4 else #endif { CGImageAlphaInfo alpha = CGBitmapContextGetAlphaInfo(src); CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); // when output goes to a Quartz printercontext, release of the bitmap must be // delayed after the end of the printed page CFRetain(src); CGDataProviderRef src_bytes = CGDataProviderCreateWithData( src, data, sw*sh*4, bmProviderRelease); img = CGImageCreate( sw, sh, 8, 4*8, 4*sw, lut, alpha, src_bytes, 0L, false, kCGRenderingIntentDefault); CGDataProviderRelease(src_bytes); CGColorSpaceRelease(lut); } CGAffineTransform at = CGContextGetCTM(src); float s = at.a; draw_CGImage(img, x, y, w, h, srcx, srcy, sw/s, sh/s); CGImageRelease(img); } // so a CGRect matches exactly what is denoted x,y,w,h for clipping purposes CGRect Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(int x, int y, int w, int h) { return CGRectMake(x - 0.5, y - 0.5, w, h); } void Fl_Quartz_Graphics_Driver::add_rectangle_to_region(Fl_Region r_, int X, int Y, int W, int H) { struct flCocoaRegion *r = (struct flCocoaRegion*)r_; CGRect arg = Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(X, Y, W, H); int j; // don't add a rectangle totally inside the Fl_Region for(j = 0; j < r->count; j++) { if(CGRectContainsRect(r->rects[j], arg)) break; } if( j >= r->count) { r->rects = (CGRect*)realloc(r->rects, (++(r->count)) * sizeof(CGRect)); r->rects[r->count - 1] = arg; } } Fl_Region Fl_Quartz_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) { struct flCocoaRegion* R = (struct flCocoaRegion*)malloc(sizeof(struct flCocoaRegion)); R->count = 1; R->rects = (CGRect *)malloc(sizeof(CGRect)); *(R->rects) = Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(x, y, w, h); return R; } void Fl_Quartz_Graphics_Driver::XDestroyRegion(Fl_Region r_) { if (r_) { struct flCocoaRegion *r = (struct flCocoaRegion*)r_; free(r->rects); free(r); } } void Fl_Quartz_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height) { width *= 2 * scale(); height *= 2 * scale(); } float Fl_Quartz_Graphics_Driver::override_scale() { float s = scale(); if (s != 1.f && Fl_Display_Device::display_device()->is_current()) { CGContextScaleCTM(gc_, 1./s, 1./s); Fl_Graphics_Driver::scale(1); } return s; } void Fl_Quartz_Graphics_Driver::restore_scale(float s) { if (s != 1.f && Fl_Display_Device::display_device()->is_current()) { CGContextScaleCTM(gc_, s, s); Fl_Graphics_Driver::scale(s); } } fltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx0000644000175000017500000010116015004135251025153 0ustar albrechtalbrecht// // MacOS font selection routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* Implementation of support for two text drawing APIs: Core Text (current) and ATSU (legacy) The HAS_ATSU macro (defined in Fl_Quartz_Graphics_Driver.H) is true if and only if ATSU is available at compile time. The condition #if HAS_ATSU && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 is true if and only if both APIs are available at compile time. Depending on what MacOS SDK and what deployment target are used, the code can be compiled in 2 ways: 1) both APIs are available at compile time and which one is used is determined at runtime, or 2) only one API is available. When both APIs are compiled in, the choice of which one is used at runtime is done the first time the Fl_Quartz_Graphics_Driver constructor runs, and remains unchanged. Core Text is selected if the running Mac OS version is ≥ 10.5. The static function init_CoreText_or_ATSU() does this by setting the value of the class variable CoreText_or_ATSU to either use_CoreText or use_ATSU. If both APIs are available, several member functions come in groups of 3. For example, functions draw(), draw_CoreText() and draw_ATSU() are defined. The only task of draw() is to call either draw_CoreText() or draw_ATSU() depending on what API has been selected at program start. If the compilation condition authorizes a single API, one member function is defined instead of 3 in the other case. For example, a single draw() function is compiled, and contains the same code as what is called either draw_CoreText() or draw_ATSU() in the other case. The ADD_SUFFIX(name, suffix) macro is used so that each function has the short (e.g., draw) or long (e.g., draw_CoreText) name adequate for each compilation condition. The 2 most often used text functions are draw() and width(). Two pointers to member function are defined. Function init_CoreText_or_ATSU() assigns one with either draw_CoreText() or draw_ATSU(), and the other with either width_CoreText() or width_ATSU(). The draw() and width() functions only have to dereference one pointer to member function to call the adequate code. If the compilation condition authorizes a single text API, only the code related to this API (say, CoreText) is compiled whereas all code related to the other API (thus, ATSU) is excluded from compilation. Furthermore, none of the code to choose API at runtime and to select which member function is called is compiled. Consequently, no pointer to member function is used. The condition for both APIs to be compiled-in is - target i386 or ppc architectures and - use SDK ≥ 10.5 and < 10.11 and - set MacOS deployment target < 10.5 (through the -mmacosx-version-min= compilation option) */ #include "Fl_Quartz_Graphics_Driver.H" #include "Fl_Font.H" #include #include #include #include // for fl_utf8toUtf16() #include // fl_strdup() #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8 const NSUInteger kCTFontOrientationHorizontal = kCTFontHorizontalOrientation; #endif Fl_Fontdesc* fl_fonts = NULL; static CGAffineTransform font_mx = { 1, 0, 0, -1, 0, 0 }; static int fl_free_font = FL_FREE_FONT; #if HAS_ATSU && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 # define ADD_SUFFIX(name, suffix) name##suffix #else # define ADD_SUFFIX(name, suffix) name #endif #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 static CFMutableDictionaryRef attributes = NULL; static Fl_Fontdesc built_in_table_PS[] = { // PostScript font names preferred when Mac OS ≥ 10.5 {"ArialMT"}, {"Arial-BoldMT"}, {"Arial-ItalicMT"}, {"Arial-BoldItalicMT"}, {"Courier"}, {"Courier-Bold"}, {"Courier-Oblique"}, {"Courier-BoldOblique"}, {"TimesNewRomanPSMT"}, {"TimesNewRomanPS-BoldMT"}, {"TimesNewRomanPS-ItalicMT"}, {"TimesNewRomanPS-BoldItalicMT"}, {"Symbol"}, {"Monaco"}, {"AndaleMono"}, // there is no bold Monaco font on standard Mac {"ZapfDingbatsITC"} }; #endif #if HAS_ATSU static Fl_Fontdesc built_in_table_full[] = { // full font names used before 10.5 {"Arial"}, {"Arial Bold"}, {"Arial Italic"}, {"Arial Bold Italic"}, {"Courier"}, {"Courier Bold"}, {"Courier New Italic"}, {"Courier New Bold Italic"}, {"Times New Roman"}, {"Times New Roman Bold"}, {"Times New Roman Italic"}, {"Times New Roman Bold Italic"}, {"Symbol"}, {"Monaco"}, {"Andale Mono"}, // there is no bold Monaco font on standard Mac {"Webdings"} }; #endif // Bug: older versions calculated the value for *ap as a side effect of // making the name, and then forgot about it. To avoid having to change // the header files I decided to store this value in the last character // of the font name array. #define ENDOFBUFFER sizeof(fl_fonts->fontname)-1 // turn a stored font name into a pretty name: const char* Fl_Quartz_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) { if (!fl_fonts) fl_fonts = calc_fl_fonts(); Fl_Fontdesc *f = fl_fonts + fnum; if (!f->fontname[0]) { this->set_fontname_in_fontdesc(f); const char* thisFont = f->name; if (!thisFont || !*thisFont) {if (ap) *ap = 0; return "";} int type = 0; if (strstr(f->name, "Bold")) type |= FL_BOLD; if (strstr(f->name, "Italic") || strstr(f->name, "Oblique")) type |= FL_ITALIC; f->fontname[ENDOFBUFFER] = (char)type; } if (ap) *ap = f->fontname[ENDOFBUFFER]; return f->fontname; } int Fl_Quartz_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) { static int array[128]; if (!fl_fonts) fl_fonts = calc_fl_fonts(); Fl_Fontdesc *s = fl_fonts+fnum; if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 int cnt = 0; // ATS supports all font size array[0] = 0; sizep = array; cnt = 1; return cnt; } Fl_Quartz_Font_Descriptor::Fl_Quartz_Font_Descriptor(const char* name, Fl_Fontsize Size) : Fl_Font_Descriptor(name, Size) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 fontref = NULL; #endif #if HAS_ATSU layout = NULL; #endif Fl_Quartz_Graphics_Driver *driver = (Fl_Quartz_Graphics_Driver*)&Fl_Graphics_Driver::default_driver(); #if HAS_ATSU && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (Fl_Quartz_Graphics_Driver::CoreText_or_ATSU == Fl_Quartz_Graphics_Driver::use_ATSU) { driver->descriptor_init_ATSU(name, size, this); return; } driver->descriptor_init_CoreText(name, size, this); #else driver->descriptor_init(name, size, this); #endif } Fl_Quartz_Font_Descriptor::~Fl_Quartz_Font_Descriptor() { /* #if HAVE_GL // ++ todo: remove OpenGL font allocations // Delete list created by gl_draw(). This is not done by this code // as it will link in GL unnecessarily. There should be some kind // of "free" routine pointer, or a subclass? #endif */ if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (fontref) { CFRelease(fontref); for (unsigned i = 0; i < sizeof(width)/sizeof(float*); i++) { if (width[i]) free(width[i]); } } #endif #if HAS_ATSU if (layout) { ATSUDisposeTextLayout(layout); ATSUDisposeStyle(style); } #endif } static UniChar *utfWbuf = 0; static unsigned utfWlen = 0; static UniChar *mac_Utf8_to_Utf16(const char *txt, int len, int *new_len) { unsigned wlen = fl_utf8toUtf16(txt, len, (unsigned short*)utfWbuf, utfWlen); if (wlen >= utfWlen) { utfWlen = wlen + 100; if (utfWbuf) free(utfWbuf); utfWbuf = (UniChar*)malloc((utfWlen)*sizeof(UniChar)); wlen = fl_utf8toUtf16(txt, len, (unsigned short*)utfWbuf, utfWlen); } *new_len = wlen; return utfWbuf; } static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size) { if (!fl_fonts) fl_fonts = Fl_Graphics_Driver::default_driver().calc_fl_fonts(); Fl_Fontdesc* s = fl_fonts+fnum; if (!s->name) s = fl_fonts; // use 0 if fnum undefined Fl_Font_Descriptor* f; for (f = s->first; f; f = f->next) if (f->size == size) return f; f = new Fl_Quartz_Font_Descriptor(s->name, size); f->next = s->first; s->first = f; return f; } void Fl_Quartz_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) { if (fnum == -1) { Fl_Graphics_Driver::font(0, 0); return; } Fl_Graphics_Driver::font(fnum, size); font_descriptor( find(fnum, size) ); } Fl_Quartz_Font_Descriptor *Fl_Quartz_Graphics_Driver::valid_font_descriptor() { // avoid a crash if no font has been selected by user yet if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE); return (Fl_Quartz_Font_Descriptor*)font_descriptor(); } int Fl_Quartz_Graphics_Driver::height() { Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor(); return fl_fontsize->ascent + fl_fontsize->descent; } int Fl_Quartz_Graphics_Driver::descent() { Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor(); return fl_fontsize->descent + 1; } void Fl_Quartz_Graphics_Driver::draw(const char* str, int n, int x, int y) { draw(str, n, (float)x, y+0.5f); } void Fl_Quartz_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) { CGContextSaveGState(gc_); CGContextTranslateCTM(gc_, x, y); CGContextRotateCTM(gc_, - angle*(M_PI/180) ); draw(str, n, 0, 0); CGContextRestoreGState(gc_); } void Fl_Quartz_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) { int dx, dy, w, h; text_extents(c, n, dx, dy, w, h); draw(c, n, x - w - dx, y); } double Fl_Quartz_Graphics_Driver::width(const char* txt, int n) { int wc_len = n; UniChar *uniStr = mac_Utf8_to_Utf16(txt, n, &wc_len); return width(uniStr, wc_len); } double Fl_Quartz_Graphics_Driver::width(unsigned int wc) { UniChar utf16[3]; int l = 1; if (wc <= 0xFFFF) { *utf16 = wc; } else { l = (int)fl_ucs_to_Utf16(wc, utf16, 3); } return width(utf16, l); } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 static void set_fontname_CoreText(Fl_Fontdesc *f) { CFStringRef cfname = CFStringCreateWithCString(NULL, f->name, kCFStringEncodingUTF8); CTFontRef ctfont = cfname ? CTFontCreateWithName(cfname, 0, NULL) : NULL; if (cfname) { CFRelease(cfname); cfname = NULL; } if (ctfont) { cfname = CTFontCopyFullName(ctfont); CFRelease(ctfont); if (cfname) { CFStringGetCString(cfname, f->fontname, ENDOFBUFFER, kCFStringEncodingUTF8); CFRelease(cfname); } } if (!cfname) strlcpy(f->fontname, f->name, ENDOFBUFFER); } #endif void Fl_Quartz_Graphics_Driver::set_fontname_in_fontdesc(Fl_Fontdesc *f) { #if HAS_ATSU && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (CoreText_or_ATSU == use_ATSU) strlcpy(f->fontname, f->name, ENDOFBUFFER); else set_fontname_CoreText(f); #elif HAS_ATSU strlcpy(f->fontname, f->name, ENDOFBUFFER); #else set_fontname_CoreText(f); #endif } const char *Fl_Quartz_Graphics_Driver::font_name(int num) { if (!fl_fonts) fl_fonts = calc_fl_fonts(); return fl_fonts[num].name; } void Fl_Quartz_Graphics_Driver::font_name(int num, const char *name) { Fl_Fontdesc *s = fl_fonts + num; if (s->name) { if (!strcmp(s->name, name)) {s->name = name; return;} for (Fl_Font_Descriptor* f = s->first; f;) { Fl_Font_Descriptor* n = f->next; delete f; f = n; } s->first = 0; } s->name = name; s->fontname[0] = 0; s->first = 0; } Fl_Fontdesc* Fl_Quartz_Graphics_Driver::calc_fl_fonts(void) { #if HAS_ATSU && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (CoreText_or_ATSU == use_ATSU) return built_in_table_full; return built_in_table_PS; #elif HAS_ATSU return built_in_table_full; #else return built_in_table_PS; #endif } #if HAS_ATSU && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 void Fl_Quartz_Graphics_Driver::draw(const char *str, int n, float x, float y) { (this->*CoreText_or_ATSU_draw)(str, n, x, y); } double Fl_Quartz_Graphics_Driver::width(const UniChar* txt, int n) { return (this->*CoreText_or_ATSU_width)(txt, n); } Fl_Font Fl_Quartz_Graphics_Driver::set_fonts(const char* xstarname) { if (CoreText_or_ATSU == use_ATSU) return set_fonts_ATSU(xstarname); return set_fonts_CoreText(xstarname); } void Fl_Quartz_Graphics_Driver::text_extents(const char* txt, int n, int& dx, int& dy, int& w, int& h) { if (CoreText_or_ATSU == use_ATSU) { text_extents_ATSU(txt, n, dx, dy, w, h); return; } text_extents_CoreText(txt, n, dx, dy, w, h); } #endif /// CoreText-based code #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(descriptor_init, _CoreText)(const char* name, Fl_Fontsize size, Fl_Quartz_Font_Descriptor *d) { CFStringRef str = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8); d->fontref = CTFontCreateWithName(str, size, NULL); CGGlyph glyph[2]; const UniChar A[2]={'W','.'}; CTFontGetGlyphsForCharacters(d->fontref, A, glyph, 2); CGSize advances[2]; double w; CTFontGetAdvancesForGlyphs(d->fontref, kCTFontOrientationHorizontal, glyph, advances, 2); w = advances[0].width; if ( fabs(advances[0].width - advances[1].width) < 1E-2 ) {//this is a fixed-width font // slightly rescale fixed-width fonts so the character width has an integral value CFRelease(d->fontref); CGFloat fsize = size / ( w/floor(w + 0.5) ); d->fontref = CTFontCreateWithName(str, fsize, NULL); w = CTFontGetAdvancesForGlyphs(d->fontref, kCTFontOrientationHorizontal, glyph, NULL, 1); } CFRelease(str); d->ascent = (short)(CTFontGetAscent(d->fontref) + 0.5); d->descent = (short)(CTFontGetDescent(d->fontref) + 0.5); d->q_width = w + 0.5; for (unsigned i = 0; i < sizeof(d->width)/sizeof(float*); i++) d->width[i] = NULL; if (!attributes) { static CFNumberRef zero_ref; float zero = 0.; zero_ref = CFNumberCreate(NULL, kCFNumberFloat32Type, &zero); // deactivate kerning for all fonts, so that string width = sum of character widths // which allows fast fl_width() implementation. attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue (attributes, kCTKernAttributeName, zero_ref); } if (d->ascent == 0) { // this may happen with some third party fonts CFDictionarySetValue (attributes, kCTFontAttributeName, d->fontref); CFAttributedStringRef mastr = CFAttributedStringCreate(kCFAllocatorDefault, CFSTR("Wj"), attributes); CTLineRef ctline = CTLineCreateWithAttributedString(mastr); CFRelease(mastr); CGFloat fascent, fdescent; CTLineGetTypographicBounds(ctline, &fascent, &fdescent, NULL); CFRelease(ctline); d->ascent = (short)(fascent + 0.5); d->descent = (short)(fdescent + 0.5); } } // returns width of a pair of UniChar's in the surrogate range static CGFloat surrogate_width(const UniChar *txt, Fl_Quartz_Font_Descriptor *fl_fontsize) { CTFontRef font2 = fl_fontsize->fontref; bool must_release = false; CGGlyph glyphs[2]; bool b = CTFontGetGlyphsForCharacters(font2, txt, glyphs, 2); CGSize a; if(!b) { // the current font doesn't contain this char CFStringRef str = CFStringCreateWithCharactersNoCopy(NULL, txt, 2, kCFAllocatorNull); // find a font that contains it font2 = CTFontCreateForString(font2, str, CFRangeMake(0,2)); must_release = true; CFRelease(str); b = CTFontGetGlyphsForCharacters(font2, txt, glyphs, 2); } if (b) CTFontGetAdvancesForGlyphs(font2, kCTFontOrientationHorizontal, glyphs, &a, 1); else a.width = fl_fontsize->q_width; if(must_release) CFRelease(font2); return a.width; } static CGFloat variation_selector_width(CFStringRef str16, Fl_Quartz_Font_Descriptor *fl_fontsize) { CGFloat retval; CFDictionarySetValue(attributes, kCTFontAttributeName, fl_fontsize->fontref); CFAttributedStringRef mastr = CFAttributedStringCreate(kCFAllocatorDefault, str16, attributes); CTLineRef ctline = CTLineCreateWithAttributedString(mastr); CFRelease(mastr); retval = CTLineGetOffsetForStringIndex(ctline, 2, NULL); CFRelease(ctline); return retval; } double Fl_Quartz_Graphics_Driver::ADD_SUFFIX(width, _CoreText)(const UniChar* txt, int n) { double retval = 0; UniChar uni; int i; Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor(); for (i = 0; i < n; i++) { // loop over txt uni = txt[i]; if (uni >= 0xD800 && uni <= 0xDBFF) { // handles the surrogate range retval += surrogate_width(&txt[i], fl_fontsize); i++; // because a pair of UniChar's represent a single character continue; } if (i+1 < n && txt[i+1] >= 0xFE00 && txt[i+1] <= 0xFE0F) { // handles variation selectors CFStringRef substr = CFStringCreateWithCharacters(NULL, txt + i, 2); retval += variation_selector_width(substr, fl_fontsize); CFRelease(substr); i++; continue; } const int block = 0x10000 / (sizeof(fl_fontsize->width)/sizeof(float*)); // block size // r: index of the character block containing uni unsigned int r = uni >> 7; // change 7 if sizeof(width) is changed if (!fl_fontsize->width[r]) { // this character block has not been hit yet //fprintf(stderr,"r=%d size=%d name=%s\n",r,fl_fontsize->size,fl_fonts[fl_font()].name); // allocate memory to hold width of each character in the block fl_fontsize->width[r] = (float*) malloc(sizeof(float) * block); UniChar ii = r * block; CGSize advance_size; CGGlyph glyph; for (int j = 0; j < block; j++) { // loop over the block // ii spans all characters of this block bool b = CTFontGetGlyphsForCharacters(fl_fontsize->fontref, &ii, &glyph, 1); if (b) CTFontGetAdvancesForGlyphs(fl_fontsize->fontref, kCTFontOrientationHorizontal, &glyph, &advance_size, 1); else advance_size.width = -1e9; // calculate this later // the width of one character of this block of characters fl_fontsize->width[r][j] = advance_size.width; ii++; } } // sum the widths of all characters of txt double wdt = fl_fontsize->width[r][uni & (block-1)]; if (wdt == -1e9) { CGSize advance_size; CGGlyph glyph; CTFontRef font2 = fl_fontsize->fontref; bool must_release = false; bool b = CTFontGetGlyphsForCharacters(font2, &uni, &glyph, 1); if (!b) { // the current font doesn't contain this char CFStringRef str = CFStringCreateWithCharactersNoCopy(NULL, &uni, 1, kCFAllocatorNull); // find a font that contains it font2 = CTFontCreateForString(font2, str, CFRangeMake(0,1)); must_release = true; CFRelease(str); b = CTFontGetGlyphsForCharacters(font2, &uni, &glyph, 1); } if (b) CTFontGetAdvancesForGlyphs(font2, kCTFontOrientationHorizontal, &glyph, &advance_size, 1); else advance_size.width = 0.; // the width of the 'uni' character wdt = fl_fontsize->width[r][uni & (block-1)] = advance_size.width; if (must_release) CFRelease(font2); } retval += wdt; } return retval; } // text extent calculation void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(text_extents, _CoreText)(const char *str8, int n, int &dx, int &dy, int &w, int &h) { Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor(); UniChar *txt = mac_Utf8_to_Utf16(str8, n, &n); CFStringRef str16 = CFStringCreateWithCharactersNoCopy(NULL, txt, n, kCFAllocatorNull); CFDictionarySetValue (attributes, kCTFontAttributeName, fl_fontsize->fontref); CFAttributedStringRef mastr = CFAttributedStringCreate(kCFAllocatorDefault, str16, attributes); CFRelease(str16); CTLineRef ctline = CTLineCreateWithAttributedString(mastr); CFRelease(mastr); CGContextSetTextPosition(gc_, 0, 0); CGContextSetShouldAntialias(gc_, true); CGRect rect = CTLineGetImageBounds(ctline, gc_); CGContextSetShouldAntialias(gc_, false); CFRelease(ctline); dx = floor(rect.origin.x + 0.5); dy = floor(- rect.origin.y - rect.size.height + 0.5); w = rect.size.width + 0.5; h = rect.size.height + 0.5; } static CGColorRef flcolortocgcolor(Fl_Color i) { uchar r, g, b; Fl::get_color(i, r, g, b); CGFloat components[4] = {r/255.0f, g/255.0f, b/255.0f, 1.}; static CGColorSpaceRef cspace = NULL; if (cspace == NULL) { cspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); } return CGColorCreate(cspace, components); } void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(draw, _CoreText)(const char *str, int n, float x, float y) { Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor(); // convert to UTF-16 first UniChar *uniStr = mac_Utf8_to_Utf16(str, n, &n); CGContextRef gc = (CGContextRef)this->gc(); CFMutableStringRef str16 = CFStringCreateMutableWithExternalCharactersNoCopy(NULL, uniStr, n, n, kCFAllocatorNull); if (str16 == NULL) return; // shd not happen CGColorRef color = flcolortocgcolor(this->color()); CFDictionarySetValue (attributes, kCTFontAttributeName, fl_fontsize->fontref); CFDictionarySetValue (attributes, kCTForegroundColorAttributeName, color); CFAttributedStringRef mastr = CFAttributedStringCreate(kCFAllocatorDefault, str16, attributes); CFRelease(str16); CFRelease(color); CTLineRef ctline = CTLineCreateWithAttributedString(mastr); CFRelease(mastr); CGContextSetTextMatrix(gc, font_mx); CGContextSetTextPosition(gc, x, y); CGContextSetShouldAntialias(gc, true); CTLineDraw(ctline, gc); CGContextSetShouldAntialias(gc, false); CFRelease(ctline); } // Skip over bold/italic/oblique qualifiers part of PostScript font names // Example: // input: '-Regular_Light-Condensed' // return: '_Light-Condensed' // static char *skip(char *p, int& derived) { // 0 5 10 // | | | if (strncmp(p, "-BoldItalic", 11) == 0) { p += 11; derived = 3; } else if (strncmp(p, "-BoldOblique", 12) == 0) { p += 12; derived = 3; } else if (strncmp(p, "-Bold", 5) == 0) { p += 5; derived = 1; } else if (strncmp(p, "-Italic", 7) == 0) { p += 7; derived = 2; } else if (strncmp(p, "-Oblique", 8) == 0) { p += 8; derived = 2; } else if (strncmp(p, "-Regular", 8) == 0) { p += 8; } else if (strncmp(p, "-Roman", 6) == 0) { p += 6; } return p; } static int name_compare(const void *a, const void *b) { /* Compare PostScript font names. First compare font family names ignoring bold, italic and oblique qualifiers. When families are identical, order them according to regular, bold, italic, bolditalic. */ char *n1 = *(char**)a; char *n2 = *(char**)b; int derived1 = 0; int derived2 = 0; while (true) { if (*n1 == '-') n1 = skip(n1, derived1); if (*n2 == '-') n2 = skip(n2, derived2); if (*n1 < *n2) return -1; if (*n1 > *n2) return +1; if (*n1 == 0) { return derived1 - derived2; } n1++; n2++; } } Fl_Font Fl_Quartz_Graphics_Driver::ADD_SUFFIX(set_fonts, _CoreText)(const char* xstarname) { #pragma unused ( xstarname ) if (fl_free_font > FL_FREE_FONT) return (Fl_Font)fl_free_font; // if already called int value[1] = {1}; CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)kCTFontCollectionRemoveDuplicatesOption, (const void **)&value, 1, NULL, NULL); CTFontCollectionRef fcref = CTFontCollectionCreateFromAvailableFonts(dict); CFRelease(dict); CFArrayRef arrayref = CTFontCollectionCreateMatchingFontDescriptors(fcref); CFRelease(fcref); CFIndex count = CFArrayGetCount(arrayref); CFIndex i; char **tabfontnames = new char*[count]; for (i = 0; i < count; i++) { CTFontDescriptorRef fdesc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(arrayref, i); CTFontRef font = CTFontCreateWithFontDescriptor(fdesc, 0., NULL); CFStringRef cfname = CTFontCopyPostScriptName(font); CFRelease(font); CFDataRef cfdata = CFStringCreateExternalRepresentation(NULL, cfname, kCFStringEncodingUTF8, '?'); CFIndex l = CFDataGetLength(cfdata); tabfontnames[i] = (char*)malloc(l+1); // never free'ed memcpy(tabfontnames[i], CFDataGetBytePtr(cfdata), l); tabfontnames[i][l] = 0; CFRelease(cfdata); CFRelease(cfname); } CFRelease(arrayref); qsort(tabfontnames, count, sizeof(char*), name_compare); for (i = 0; i < count; i++) { Fl::set_font((Fl_Font)(fl_free_font++), tabfontnames[i]); } delete[] tabfontnames; return (Fl_Font)fl_free_font; } #endif // >= 10.5 /// ATSU-based code to support Mac OS < 10.5 #if HAS_ATSU void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(descriptor_init, _ATSU)(const char* name, Fl_Fontsize size, Fl_Quartz_Font_Descriptor *d) { OSStatus err; // fill our structure with a few default values d->ascent = size*3/4.; d->descent = size-d->ascent; d->q_width = size*2/3.; // now we allocate everything needed to render text in this font later // get us the default layout and style err = ATSUCreateTextLayout(&d->layout); UniChar mTxt[2] = { 65, 0 }; err = ATSUSetTextPointerLocation(d->layout, mTxt, kATSUFromTextBeginning, 1, 1); err = ATSUCreateStyle(&d->style); err = ATSUSetRunStyle(d->layout, d->style, kATSUFromTextBeginning, kATSUToTextEnd); // now set the actual font, size and attributes. We also set the font matrix to // render our font up-side-down, so when rendered through our inverted CGContext, // text will appear normal again. Fixed fsize = IntToFixed(size); ATSUFontID fontID; ATSUFindFontFromName(name, strlen(name), kFontFullName, kFontMacintoshPlatform, kFontNoScriptCode, kFontEnglishLanguage, &fontID); // draw the font upside-down... Compensate for fltk/OSX origin differences ATSUAttributeTag sTag[] = { kATSUFontTag, kATSUSizeTag, kATSUFontMatrixTag }; ByteCount sBytes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(CGAffineTransform) }; ATSUAttributeValuePtr sAttr[] = { &fontID, &fsize, &font_mx }; if (fontID != kATSUInvalidFontID) err = ATSUSetAttributes(d->style, 1, sTag, sBytes, sAttr); // set the font attribute err = ATSUSetAttributes(d->style, 2, sTag + 1, sBytes + 1, sAttr + 1); // then the size and matrix attributes // next, make sure that Quartz will only render at integer coordinates ATSLineLayoutOptions llo = kATSLineUseDeviceMetrics | kATSLineDisableAllLayoutOperations; ATSUAttributeTag aTag[] = { kATSULineLayoutOptionsTag }; ByteCount aBytes[] = { sizeof(ATSLineLayoutOptions) }; ATSUAttributeValuePtr aAttr[] = { &llo }; err = ATSUSetLineControls (d->layout, kATSUFromTextBeginning, 1, aTag, aBytes, aAttr); // now we are finally ready to measure some letter to get the bounding box Fixed bBefore, bAfter, bAscent, bDescent; err = ATSUGetUnjustifiedBounds(d->layout, kATSUFromTextBeginning, 1, &bBefore, &bAfter, &bAscent, &bDescent); // Requesting a certain height font on Mac does not guarantee that ascent+descent // equal the requested height. fl_height will reflect the actual height that we got. // The font "Apple Chancery" is a pretty extreme example of overlapping letters. float fa = -FixedToFloat(bAscent), fd = -FixedToFloat(bDescent); if (fa>0.0f && fd>0.0f) { //float f = Size/(fa+fd); d->ascent = int(fa); //int(fa*f+0.5f); d->descent = int(fd); //Size - ascent; } int w = FixedToInt(bAfter); if (w) d->q_width = FixedToInt(bAfter); // Now, by way of experiment, try enabling Transient Font Matching, this will // cause ATSU to find a suitable font to render any chars the current font can't do... ATSUSetTransientFontMatching (d->layout, true); } void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(draw, _ATSU)(const char *str, int n, float x, float y) { Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor(); // convert to UTF-16 first UniChar *uniStr = mac_Utf8_to_Utf16(str, n, &n); CGContextRef gc = (CGContextRef)this->gc(); OSStatus err; // now collect our ATSU resources ATSUTextLayout layout = fl_fontsize->layout; ByteCount iSize = sizeof(CGContextRef); ATSUAttributeTag iTag = kATSUCGContextTag; ATSUAttributeValuePtr iValuePtr=&gc; ATSUSetLayoutControls(layout, 1, &iTag, &iSize, &iValuePtr); err = ATSUSetTextPointerLocation(layout, uniStr, kATSUFromTextBeginning, n, n); CGContextSetShouldAntialias(gc, true); err = ATSUDrawText(layout, kATSUFromTextBeginning, n, FloatToFixed(x), FloatToFixed(y)); CGContextSetShouldAntialias(gc, false); } double Fl_Quartz_Graphics_Driver::ADD_SUFFIX(width, _ATSU)(const UniChar* txt, int n) { OSStatus err; Fixed bBefore, bAfter, bAscent, bDescent; ATSUTextLayout layout; ByteCount iSize; ATSUAttributeTag iTag; ATSUAttributeValuePtr iValuePtr; Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor(); // Here's my ATSU text measuring attempt... This seems to do the Right Thing // now collect our ATSU resources and measure our text string layout = fl_fontsize->layout; // activate the current GC iSize = sizeof(CGContextRef); iTag = kATSUCGContextTag; CGContextRef value = (CGContextRef)fl_graphics_driver->gc(); iValuePtr = &value; ATSUSetLayoutControls(layout, 1, &iTag, &iSize, &iValuePtr); // now measure the bounding box err = ATSUSetTextPointerLocation(layout, txt, kATSUFromTextBeginning, n, n); err = ATSUGetUnjustifiedBounds(layout, kATSUFromTextBeginning, n, &bBefore, &bAfter, &bAscent, &bDescent); // If err is OK then return length, else return 0. Or something... int len = FixedToInt(bAfter); return len; } void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(text_extents, _ATSU)(const char *str8, int n, int &dx, int &dy, int &w, int &h) { Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor(); UniChar *txt = mac_Utf8_to_Utf16(str8, n, &n); OSStatus err; ATSUTextLayout layout; ByteCount iSize; ATSUAttributeTag iTag; ATSUAttributeValuePtr iValuePtr; // Here's my ATSU text measuring attempt... This seems to do the Right Thing // now collect our ATSU resources and measure our text string layout = fl_fontsize->layout; // activate the current GC iSize = sizeof(CGContextRef); iTag = kATSUCGContextTag; CGContextRef value = (CGContextRef)gc(); iValuePtr = &value; ATSUSetLayoutControls(layout, 1, &iTag, &iSize, &iValuePtr); // now measure the bounding box err = ATSUSetTextPointerLocation(layout, txt, kATSUFromTextBeginning, n, n); Rect bbox; err = ATSUMeasureTextImage(layout, kATSUFromTextBeginning, n, 0, 0, &bbox); w = bbox.right - bbox.left; h = bbox.bottom - bbox.top; dx = bbox.left; dy = -bbox.bottom; //printf("r: %d l: %d t: %d b: %d w: %d h: %d\n", bbox.right, bbox.left, bbox.top, bbox.bottom, w, h); } Fl_Font Fl_Quartz_Graphics_Driver::ADD_SUFFIX(set_fonts, _ATSU)(const char* xstarname) { #pragma unused ( xstarname ) if (fl_free_font > FL_FREE_FONT) return (Fl_Font)fl_free_font; // if already called ItemCount oFontCount, oCountAgain; ATSUFontID *oFontIDs; // How many fonts? ATSUFontCount (&oFontCount); // now allocate space for them... oFontIDs = (ATSUFontID *)malloc((oFontCount+1) * sizeof(ATSUFontID)); ATSUGetFontIDs (oFontIDs, oFontCount, &oCountAgain); // Now oFontIDs should contain a list of all the available Unicode fonts // Iterate through the list to get each font name for (ItemCount idx = 0; idx < oFontCount; idx++) { // ByteCount actualLength = 0; // Ptr oName; // How to get the name - Apples docs say call this twice, once to get the length, then again // to get the actual name... // ATSUFindFontName (oFontIDs[idx], kFontFullName, kFontMacintoshPlatform, kFontRomanScript, kFontEnglishLanguage, // 0, NULL, &actualLength, NULL); // Now actualLength tells us the length of buffer we need // oName = (Ptr)malloc(actualLength + 8); // But who's got time for that nonsense? Let's just hard code a fixed buffer (urgh!) ByteCount actualLength = 511; char oName[512]; ATSUFindFontName (oFontIDs[idx], kFontFullName, kFontMacintoshPlatform, kFontRomanScript, kFontEnglishLanguage, actualLength, oName, &actualLength, &oCountAgain); // bounds check and terminate the returned name if(actualLength > 511) oName[511] = 0; else oName[actualLength] = 0; Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(oName)); // free(oName); } free(oFontIDs); return (Fl_Font)fl_free_font; } #endif // HAS_ATSU fltk-1.4.3/src/drivers/Quartz/Fl_Font.H0000644000175000017500000000245715004135251020010 0ustar albrechtalbrecht// // Font definitions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Two internal fltk data structures: // // Fl_Fontdesc: an entry into the fl_font() table. There is one of these // for each fltk font number. // #ifndef FL_FONT_ #define FL_FONT_ #include #include "Fl_Quartz_Graphics_Driver.H" #include class Fl_Quartz_Font_Descriptor : public Fl_Font_Descriptor { public: Fl_Quartz_Font_Descriptor(const char* fontname, Fl_Fontsize size); virtual FL_EXPORT ~Fl_Quartz_Font_Descriptor(); # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 CTFontRef fontref; // the unicode span is divided in 512 blocks of 128 characters float *width[512]; // array of arrays of character widths # endif # if HAS_ATSU ATSUTextLayout layout; ATSUStyle style; # endif short q_width; }; extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table #endif fltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_line_style.cxx0000644000175000017500000000534715004135251026366 0ustar albrechtalbrecht// // Line style code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include /** \file quartz_line_style.cxx \brief Line style drawing utility hiding different platforms. */ #include "Fl_Quartz_Graphics_Driver.H" void Fl_Quartz_Graphics_Driver::quartz_restore_line_style() { CGContextSetLineWidth(gc_, quartz_line_width_); CGContextSetLineCap(gc_, quartz_line_cap_); CGContextSetLineJoin(gc_, quartz_line_join_); CGContextSetLineDash(gc_, 0, quartz_line_pattern, quartz_line_pattern_size); } void Fl_Quartz_Graphics_Driver::line_style(int style, int width, char* dashes) { static CGLineCap Cap[4] = { kCGLineCapButt, kCGLineCapButt, kCGLineCapRound, kCGLineCapSquare }; static CGLineJoin Join[4] = { kCGLineJoinMiter, kCGLineJoinMiter, kCGLineJoinRound, kCGLineJoinBevel }; if (width<1) width = 1; quartz_line_width_ = (float)width; quartz_line_cap_ = Cap[(style>>8)&3]; // when printing kCGLineCapSquare seems better for solid lines if ( Fl_Surface_Device::surface() != Fl_Display_Device::display_device() && style == FL_SOLID && dashes == NULL ) { quartz_line_cap_ = kCGLineCapSquare; } quartz_line_join_ = Join[(style>>12)&3]; char *d = dashes; static CGFloat pattern[16]; if (d && *d) { CGFloat *pDst = pattern; while (*d) { *pDst++ = (float)*d++; } quartz_line_pattern = pattern; quartz_line_pattern_size = (int)(d-dashes); } else if (style & 0xff) { char dash, dot, gap; // adjust lengths to account for cap: if (style & 0x200) { dash = char(2*width); dot = 1; gap = char(2*width-1); } else { dash = char(3*width); dot = gap = char(width); } CGFloat *pDst = pattern; switch (style & 0xff) { case FL_DASH: *pDst++ = dash; *pDst++ = gap; break; case FL_DOT: *pDst++ = dot; *pDst++ = gap; break; case FL_DASHDOT: *pDst++ = dash; *pDst++ = gap; *pDst++ = dot; *pDst++ = gap; break; case FL_DASHDOTDOT: *pDst++ = dash; *pDst++ = gap; *pDst++ = dot; *pDst++ = gap; *pDst++ = dot; *pDst++ = gap; break; } quartz_line_pattern_size = (int)(pDst-pattern); quartz_line_pattern = pattern; } else { quartz_line_pattern = 0; quartz_line_pattern_size = 0; } quartz_restore_line_style(); } fltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H0000644000175000017500000000225015004135251024334 0ustar albrechtalbrecht// // Definition of Apple Quartz graphics driver // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef Fl_Quartz_Copy_Surface_Driver_H #define Fl_Quartz_Copy_Surface_Driver_H #include #include class Fl_Quartz_Copy_Surface_Driver : public Fl_Copy_Surface_Driver { friend class Fl_Copy_Surface_Driver; protected: CFMutableDataRef pdfdata; CGContextRef gc; static size_t MyPutBytes(void* info, const void* buffer, size_t count); Fl_Quartz_Copy_Surface_Driver(int w, int h); // implemented in Fl_cocoa.mm because uses Objective-c ~Fl_Quartz_Copy_Surface_Driver(); void set_current() FL_OVERRIDE; void translate(int x, int y) FL_OVERRIDE; void untranslate() FL_OVERRIDE; }; #endif /* Fl_Quartz_Copy_Surface_Driver_H */ fltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx0000644000175000017500000000423115004135251024750 0ustar albrechtalbrecht// // Copy-to-clipboard code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2019 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "Fl_Quartz_Graphics_Driver.H" #include "Fl_Quartz_Copy_Surface_Driver.H" #include "../Cocoa/Fl_Cocoa_Window_Driver.H" Fl_Quartz_Copy_Surface_Driver::Fl_Quartz_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) { driver(new Fl_Quartz_Printer_Graphics_Driver); pdfdata = CFDataCreateMutable(NULL, 0); CGDataConsumerRef myconsumer; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 if (&CGDataConsumerCreateWithCFData != NULL) { myconsumer = CGDataConsumerCreateWithCFData(pdfdata); // 10.4 } else #endif { static CGDataConsumerCallbacks callbacks = { Fl_Quartz_Copy_Surface_Driver::MyPutBytes, NULL }; myconsumer = CGDataConsumerCreate((void*) pdfdata, &callbacks); } float d = fl_graphics_driver->scale(); CGRect bounds = CGRectMake(0, 0, w * d, h * d); gc = CGPDFContextCreate(myconsumer, &bounds, NULL); CGDataConsumerRelease(myconsumer); if (gc) { CGContextBeginPage(gc, &bounds); CGContextScaleCTM(gc, d, -d); CGContextTranslateCTM(gc, 0.5, -h + 0.5); CGContextSaveGState(gc); } } void Fl_Quartz_Copy_Surface_Driver::set_current() { driver()->gc(gc); fl_window = (FLWindow*)1; Fl_Surface_Device::set_current(); } size_t Fl_Quartz_Copy_Surface_Driver::MyPutBytes(void* info, const void* buffer, size_t count) { CFDataAppendBytes ((CFMutableDataRef) info, (const UInt8 *)buffer, count); return count; } void Fl_Quartz_Copy_Surface_Driver::translate(int x, int y) { CGContextRestoreGState(gc); CGContextSaveGState(gc); CGContextTranslateCTM(gc, x, y); CGContextSaveGState(gc); } void Fl_Quartz_Copy_Surface_Driver::untranslate() { CGContextRestoreGState(gc); } fltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx0000644000175000017500000002727415004135251025157 0ustar albrechtalbrecht// // Rectangle drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include /** \file quartz_rect.cxx \brief Apple Quartz specific line and polygon drawing with integer coordinates. */ #include "Fl_Quartz_Graphics_Driver.H" // --- line and polygon drawing with integer coordinates void Fl_Quartz_Graphics_Driver::point(int x, int y) { CGContextFillRect(gc_, CGRectMake(x - 0.5, y - 0.5, 1, 1) ); } void Fl_Quartz_Graphics_Driver::rect(int x, int y, int w, int h) { if (w<=0 || h<=0) return; double offset = (quartz_line_width_ >= 2 ? quartz_line_width_/4 : 0); CGRect rect = CGRectMake(x - offset, y - offset, w-1, h-1); CGContextStrokeRect(gc_, rect); } void Fl_Quartz_Graphics_Driver::focus_rect(int x, int y, int w, int h) { CGContextSaveGState(gc_); float s = scale(); CGContextScaleCTM(gc_, 1/s, 1/s); CGFloat lw = (s >= 1 ? floor(s) : 1); CGContextSetLineWidth(gc_, lw); CGFloat dots[2] = {lw, lw}; CGContextSetLineDash(gc_, 0, dots, 2); CGContextStrokeRect(gc_, CGRectMake(x*s, y*s, (w-1)*s, (h-1)*s)); CGContextRestoreGState(gc_); } void Fl_Quartz_Graphics_Driver::rectf(int x, int y, int w, int h) { if (w<=0 || h<=0) return; CGRect rect = CGRectMake(x - 0.5, y - 0.5, w , h); CGContextFillRect(gc_, rect); } void Fl_Quartz_Graphics_Driver::line(int x, int y, int x1, int y1) { if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x1, y1); CGContextStrokePath(gc_); if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x1, y1); CGContextAddLineToPoint(gc_, x2, y2); CGContextStrokePath(gc_); if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1) { if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x1, y); CGContextStrokePath(gc_); if (high_resolution() || scale()>=2) { /* On retina displays, all xyline() and yxline() functions produce lines that are half-unit (or one pixel) too short at both ends. This is corrected by filling at both ends rectangles of size one unit by line-width. */ CGContextFillRect(gc_, CGRectMake(x-0.5 , y - quartz_line_width_/2, 1 , quartz_line_width_)); CGContextFillRect(gc_, CGRectMake(x1-0.5 , y - quartz_line_width_/2, 1 , quartz_line_width_)); } if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1, int y2) { if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x1, y); CGContextAddLineToPoint(gc_, x1, y2); CGContextStrokePath(gc_); if (high_resolution() || scale()>=2) { CGContextFillRect(gc_, CGRectMake(x-0.5, y - quartz_line_width_/2, 1 , quartz_line_width_)); CGContextFillRect(gc_, CGRectMake(x1 - quartz_line_width_/2, y2-0.5, quartz_line_width_, 1)); } if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x1, y); CGContextAddLineToPoint(gc_, x1, y2); CGContextAddLineToPoint(gc_, x3, y2); CGContextStrokePath(gc_); if (high_resolution() || scale()>=2) { CGContextFillRect(gc_, CGRectMake(x-0.5, y - quartz_line_width_/2, 1 , quartz_line_width_)); CGContextFillRect(gc_, CGRectMake(x3-0.5, y2 - quartz_line_width_/2, 1 , quartz_line_width_)); } if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1) { if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x, y1); CGContextStrokePath(gc_); if (high_resolution() || scale()>=2) { CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y-0.5, quartz_line_width_, 1)); CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y1-0.5, quartz_line_width_, 1)); } if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1, int x2) { if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x, y1); CGContextAddLineToPoint(gc_, x2, y1); CGContextStrokePath(gc_); if (high_resolution() || scale()>=2) { CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y-0.5, quartz_line_width_, 1)); CGContextFillRect(gc_, CGRectMake(x2-0.5, y1 - quartz_line_width_/2, 1 , quartz_line_width_)); } if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x, y1); CGContextAddLineToPoint(gc_, x2, y1); CGContextAddLineToPoint(gc_, x2, y3); CGContextStrokePath(gc_); if (high_resolution() || scale()>=2) { CGContextFillRect(gc_, CGRectMake(x - quartz_line_width_/2, y-0.5, quartz_line_width_, 1)); CGContextFillRect(gc_, CGRectMake(x2 - quartz_line_width_/2, y3-0.5, quartz_line_width_, 1)); } if (has_feature(PRINTER) || quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2) { if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x1, y1); CGContextAddLineToPoint(gc_, x2, y2); CGContextClosePath(gc_); CGContextStrokePath(gc_); if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x1, y1); CGContextAddLineToPoint(gc_, x2, y2); CGContextAddLineToPoint(gc_, x3, y3); CGContextClosePath(gc_); CGContextStrokePath(gc_); if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::overlay_rect(int x, int y, int w , int h) { float s = scale(); if (s < 2) s = 0; CGContextSetLineWidth(gc_, 0.05); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x+w-1 +s/8, y); CGContextAddLineToPoint(gc_, x+w-1 +s/8, y+h-1 -s/8); CGContextAddLineToPoint(gc_, x, y+h-1 -s/8); CGContextClosePath(gc_); CGContextStrokePath(gc_); CGContextSetLineWidth(gc_, quartz_line_width_); } void Fl_Quartz_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) { CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x1, y1); CGContextAddLineToPoint(gc_, x2, y2); CGContextClosePath(gc_); CGContextFillPath(gc_); CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, x, y); CGContextAddLineToPoint(gc_, x1, y1); CGContextAddLineToPoint(gc_, x2, y2); CGContextAddLineToPoint(gc_, x3, y3); CGContextClosePath(gc_); CGContextFillPath(gc_); CGContextSetShouldAntialias(gc_, false); } // --- clipping // intersects current and x,y,w,h rectangle and returns result as a new Fl_Region static Fl_Region intersect_region_and_rect(Fl_Region current_, int x,int y,int w, int h) { if (current_ == NULL) return Fl_Graphics_Driver::default_driver().XRectangleRegion(x,y,w,h); struct flCocoaRegion* current = (struct flCocoaRegion*)current_; CGRect r = Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(x, y, w, h); struct flCocoaRegion* outr = (struct flCocoaRegion*)malloc(sizeof(struct flCocoaRegion)); outr->count = current->count; outr->rects =(CGRect*)malloc(outr->count * sizeof(CGRect)); int j = 0; for(int i = 0; i < current->count; i++) { CGRect test = CGRectIntersection(current->rects[i], r); if (!CGRectIsEmpty(test)) outr->rects[j++] = test; } if (j) { outr->count = j; outr->rects = (CGRect*)realloc(outr->rects, outr->count * sizeof(CGRect)); } else { Fl_Graphics_Driver::default_driver().XDestroyRegion(outr); outr = (struct flCocoaRegion*)Fl_Graphics_Driver::default_driver().XRectangleRegion(0,0,0,0); } return outr; } void Fl_Quartz_Graphics_Driver::push_clip(int x, int y, int w, int h) { Fl_Region r; if (w > 0 && h > 0) { r = XRectangleRegion(x,y,w,h); Fl_Region current = rstack[rstackptr]; if (current) { XDestroyRegion(r); r = intersect_region_and_rect(current, x,y,w,h); } } else { // make empty clip region: r = XRectangleRegion(0,0,0,0); } if (rstackptr < region_stack_max) rstack[++rstackptr] = r; else Fl::warning("Fl_Quartz_Graphics_Driver::push_clip: clip stack overflow!\n"); restore_clip(); } int Fl_Quartz_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){ X = x; Y = y; W = w; H = h; struct flCocoaRegion* r = (struct flCocoaRegion*)rstack[rstackptr]; if (!r) return 0; CGRect arg = fl_cgrectmake_cocoa(x, y, w, h); CGRect u = CGRectMake(0,0,0,0); CGRect test; for (int i = 0; i < r->count; i++) { test = CGRectIntersection(r->rects[i], arg); if ( !CGRectIsEmpty(test) ) { if(CGRectIsEmpty(u)) u = test; else u = CGRectUnion(u, test); } } X = int(u.origin.x + 0.5); // reverse offset introduced by fl_cgrectmake_cocoa() Y = int(u.origin.y + 0.5); W = int(u.size.width + 0.5); // round to nearest integer H = int(u.size.height + 0.5); if (CGRectIsEmpty(u)) W = H = 0; return !CGRectEqualToRect(arg, u); } int Fl_Quartz_Graphics_Driver::not_clipped(int x, int y, int w, int h) { if (x+w <= 0 || y+h <= 0) return 0; struct flCocoaRegion* r = (struct flCocoaRegion*)rstack[rstackptr]; if (!r) return 1; CGRect arg = fl_cgrectmake_cocoa(x, y, w, h); for (int i = 0; i < r->count; i++) { CGRect test = CGRectIntersection(r->rects[i], arg); if (!CGRectIsEmpty(test)) return 1; } return 0; } void Fl_Quartz_Graphics_Driver::restore_clip() { fl_clip_state_number++; struct flCocoaRegion* r = (struct flCocoaRegion*)rstack[rstackptr]; if ( fl_window || gc_ ) { // clipping for a true window or an offscreen buffer if (gc_) { CGContextRestoreGState(gc_); CGContextSaveGState(gc_); } color(color()); quartz_restore_line_style(); if (r) { //apply program clip CGContextClipToRects(gc_, r->rects, r->count); } } } fltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_vertex.cxx0000644000175000017500000000542015004135251025524 0ustar albrechtalbrecht// // Portable drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file quartz_vertex.cxx \brief Portable drawing code for drawing arbitrary shapes with simple 2D transformations, implemented for OS X Quartz. */ #include "Fl_Quartz_Graphics_Driver.H" #include #include #include void Fl_Quartz_Graphics_Driver::end_points() { for (int i = 0; i < n; i++) { point(xpoint[i].x, xpoint[i].y); } } void Fl_Quartz_Graphics_Driver::end_line() { if (n < 2) { end_points(); return; } if (n<=1) return; CGContextSetShouldAntialias(gc_, true); CGContextMoveToPoint(gc_, xpoint[0].x, xpoint[0].y); for (int i=1; i #include class Fl_Quartz_Image_Surface_Driver : public Fl_Image_Surface_Driver { private: # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 CGImageRef mask_; void mask(const Fl_RGB_Image *) FL_OVERRIDE; #endif void end_current() FL_OVERRIDE; public: FLWindow *pre_window; Fl_Quartz_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off); ~Fl_Quartz_Image_Surface_Driver(); void set_current() FL_OVERRIDE; void translate(int x, int y) FL_OVERRIDE; void untranslate() FL_OVERRIDE; Fl_RGB_Image *image() FL_OVERRIDE; }; #endif // FL_QUARTZ_IMAGE_SURFACE_DRIVER_H fltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H0000644000175000017500000002026115004135251023514 0ustar albrechtalbrecht// // Definition of Apple Quartz graphics driver // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Quartz_Graphics_Driver.H \brief Definition of Apple Quartz graphics driver. */ #ifndef FL_QUARTZ_GRAPHICS_DRIVER_H #define FL_QUARTZ_GRAPHICS_DRIVER_H #include #include #include // condition for the ATSU API to be available at compile time #if ( (!defined(__LP64__) || !__LP64__) \ && MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_11 \ && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 \ ) #define HAS_ATSU 1 #else #define HAS_ATSU 0 #endif struct Fl_Fontdesc; class Fl_Quartz_Font_Descriptor; /** \brief The Mac OS X-specific graphics class. This class is implemented only on the Mac OS X platform. */ class Fl_Quartz_Graphics_Driver : public Fl_Graphics_Driver { friend class Fl_Cocoa_Printer_Driver; friend class Fl_Quartz_Font_Descriptor; protected: CGContextRef gc_; bool high_resolution_; float quartz_line_width_; CGLineCap quartz_line_cap_; CGLineJoin quartz_line_join_; CGFloat *quartz_line_pattern; int quartz_line_pattern_size; void cache_size(Fl_Image* img, int &width, int &height) FL_OVERRIDE; public: Fl_Quartz_Graphics_Driver(); int has_feature(driver_feature mask) FL_OVERRIDE { return mask & NATIVE; } void gc(void *ctxt) FL_OVERRIDE { gc_ = (CGContextRef)ctxt; global_gc(); } void *gc() FL_OVERRIDE {return gc_;} char can_do_alpha_blending() FL_OVERRIDE; // --- bitmap stuff static CGImageRef create_bitmask(int w, int h, const uchar *array); // NOT virtual void delete_bitmask(fl_uintptr_t bm) FL_OVERRIDE; void draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_bitmap(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) FL_OVERRIDE; void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) FL_OVERRIDE; void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) FL_OVERRIDE; void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) FL_OVERRIDE; void cache(Fl_Pixmap *img) FL_OVERRIDE; void cache(Fl_Bitmap *img) FL_OVERRIDE; void cache(Fl_RGB_Image *img) FL_OVERRIDE; void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) FL_OVERRIDE; void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) FL_OVERRIDE; void draw_CGImage(CGImageRef cgimg, int x, int y, int w, int h, int srcx, int srcy, int sw, int sh); static CGRect fl_cgrectmake_cocoa(int x, int y, int w, int h); void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h) FL_OVERRIDE; Fl_Region XRectangleRegion(int x, int y, int w, int h) FL_OVERRIDE; void XDestroyRegion(Fl_Region r) FL_OVERRIDE; void high_resolution(bool b) { high_resolution_ = b; } protected: void point(int x, int y) FL_OVERRIDE; void rect(int x, int y, int w, int h) FL_OVERRIDE; void focus_rect(int x, int y, int w, int h) FL_OVERRIDE; void rectf(int x, int y, int w, int h) FL_OVERRIDE; void line(int x, int y, int x1, int y1) FL_OVERRIDE; void line(int x, int y, int x1, int y1, int x2, int y2) FL_OVERRIDE; void xyline(int x, int y, int x1) FL_OVERRIDE; void xyline(int x, int y, int x1, int y2) FL_OVERRIDE; void xyline(int x, int y, int x1, int y2, int x3) FL_OVERRIDE; void yxline(int x, int y, int y1) FL_OVERRIDE; void yxline(int x, int y, int y1, int x2) FL_OVERRIDE; void yxline(int x, int y, int y1, int x2, int y3) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; // --- clipping void push_clip(int x, int y, int w, int h) FL_OVERRIDE; int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) FL_OVERRIDE; int not_clipped(int x, int y, int w, int h) FL_OVERRIDE; void restore_clip() FL_OVERRIDE; void end_points() FL_OVERRIDE; void end_line() FL_OVERRIDE; void end_polygon() FL_OVERRIDE; void end_complex_polygon() FL_OVERRIDE; void circle(double x, double y, double r) FL_OVERRIDE; void arc(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void pie(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void line_style(int style, int width=0, char* dashes=0) FL_OVERRIDE; void color(Fl_Color c) FL_OVERRIDE; Fl_Color color() FL_OVERRIDE { return color_; } void color(uchar r, uchar g, uchar b) FL_OVERRIDE; void draw(const char *str, int n, int x, int y) FL_OVERRIDE; void draw(const char *str, int n, float x, float y) FL_OVERRIDE; void draw(int angle, const char *str, int n, int x, int y) FL_OVERRIDE; double width(const UniChar* txt, int n); void rtl_draw(const char *str, int n, int x, int y) FL_OVERRIDE; void font(Fl_Font face, Fl_Fontsize fsize) FL_OVERRIDE; double width(const char *str, int n) FL_OVERRIDE; double width(unsigned int c) FL_OVERRIDE; int height() FL_OVERRIDE; int descent() FL_OVERRIDE; virtual bool high_resolution() { return high_resolution_; } void global_gc() FL_OVERRIDE; void quartz_restore_line_style(); inline Fl_Quartz_Font_Descriptor *valid_font_descriptor(); const char* get_font_name(Fl_Font fnum, int* ap) FL_OVERRIDE; int get_font_sizes(Fl_Font fnum, int*& sizep) FL_OVERRIDE; const char *font_name(int num) FL_OVERRIDE; void font_name(int num, const char *name) FL_OVERRIDE; Fl_Fontdesc* calc_fl_fonts(void) FL_OVERRIDE; void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h) FL_OVERRIDE; Fl_Font set_fonts(const char* xstarname) FL_OVERRIDE; void set_fontname_in_fontdesc(Fl_Fontdesc *f); void uncache_pixmap(fl_uintptr_t p) FL_OVERRIDE; #if HAS_ATSU && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 enum {use_CoreText = 1, use_ATSU}; static int CoreText_or_ATSU; static void init_CoreText_or_ATSU(); void draw_CoreText(const char *str, int n, float x, float y); double width_CoreText(const UniChar* txt, int n); void descriptor_init_CoreText(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d); void text_extents_CoreText(const char*, int n, int& dx, int& dy, int& w, int& h); Fl_Font set_fonts_CoreText(const char* xstarname); void draw_ATSU(const char *str, int n, float x, float y); double width_ATSU(const UniChar* txt, int n); void descriptor_init_ATSU(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d); void text_extents_ATSU(const char*, int n, int& dx, int& dy, int& w, int& h); Fl_Font set_fonts_ATSU(const char* xstarname); // define 2 kinds of pointers to member function typedef void (Fl_Quartz_Graphics_Driver::*pter_to_draw_member)(const char *str, int n, float x, float y); typedef double (Fl_Quartz_Graphics_Driver::*pter_to_width_member)(const UniChar *str, int n); static pter_to_draw_member CoreText_or_ATSU_draw; static pter_to_width_member CoreText_or_ATSU_width; #else void descriptor_init(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d); #endif void overlay_rect(int x, int y, int w , int h) FL_OVERRIDE; float override_scale() FL_OVERRIDE; void restore_scale(float) FL_OVERRIDE; void antialias(int state) FL_OVERRIDE; int antialias() FL_OVERRIDE; }; class Fl_Quartz_Printer_Graphics_Driver : public Fl_Quartz_Graphics_Driver { public: int has_feature(driver_feature mask) FL_OVERRIDE { return mask & (NATIVE | PRINTER); } }; #endif // FL_QUARTZ_GRAPHICS_DRIVER_H fltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_arci.cxx0000644000175000017500000000401315004135251025122 0ustar albrechtalbrecht// // Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Quartz_Graphics_Driver.H" #include /** \file quartz_arci.cxx \brief Utility functions for drawing circles using integers */ void Fl_Quartz_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) { if (w <= 0 || h <= 0) return; a1 = (-a1)/180.0f*M_PI; a2 = (-a2)/180.0f*M_PI; float cx = x + 0.5f*w - 0.5f, cy = y + 0.5f*h - 0.5f; CGContextSetShouldAntialias(gc_, true); if (w!=h) { CGContextSaveGState(gc_); CGContextTranslateCTM(gc_, cx, cy); CGContextScaleCTM(gc_, w-1.0f, h-1.0f); CGContextAddArc(gc_, 0, 0, 0.5, a1, a2, 1); CGContextRestoreGState(gc_); } else { float r = (w+h)*0.25f-0.5f; CGContextAddArc(gc_, cx, cy, r, a1, a2, 1); } CGContextStrokePath(gc_); CGContextSetShouldAntialias(gc_, false); } void Fl_Quartz_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) { if (w <= 0 || h <= 0) return; a1 = (-a1)/180.0f*M_PI; a2 = (-a2)/180.0f*M_PI; float cx = x + 0.5f*w - 0.5f, cy = y + 0.5f*h - 0.5f; CGContextSetShouldAntialias(gc_, true); if (w!=h) { CGContextSaveGState(gc_); CGContextTranslateCTM(gc_, cx, cy); CGContextScaleCTM(gc_, w, h); CGContextAddArc(gc_, 0, 0, 0.5, a1, a2, 1); CGContextAddLineToPoint(gc_, 0, 0); CGContextClosePath(gc_); CGContextRestoreGState(gc_); } else { float r = (w+h)*0.25f; CGContextAddArc(gc_, cx, cy, r, a1, a2, 1); CGContextAddLineToPoint(gc_, cx, cy); CGContextClosePath(gc_); } CGContextFillPath(gc_); CGContextSetShouldAntialias(gc_, false); } fltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx0000644000175000017500000002442115004135251025273 0ustar albrechtalbrecht// // MacOS image drawing code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Quartz_Graphics_Driver.H" #include #include #include #include #define MAXBUFFER 0x40000 // 256k static void dataReleaseCB(void *info, const void *data, size_t size) { delete[] (uchar *)data; } /* draw an image based on the input parameters buf: image source data X, Y: position (in buffer?!) W, H: size of picture (in pixel?) delta: distance from pixel to pixel in buf in bytes linedelta: distance from line to line in buf in bytes mono: if set, pixel is one byte - if zero, pixel is 3 byte cb: callback to copy image data into (RGB?) buffer buf: pointer to first byte in image source x, y: position in buffer w: width (in bytes?) dst: destination buffer userdata: ? */ static void innards(const uchar *buf, int X, int Y, int W, int H, int delta, int linedelta, int mono, Fl_Draw_Image_Cb cb, void* userdata, CGContextRef gc, Fl_Quartz_Graphics_Driver *driver) { if (!linedelta) linedelta = W*abs(delta); uchar *tmpBuf = 0; if (!cb) { if (delta < 0) buf -= (W-1)*(-delta); if (linedelta < 0) buf -= (H-1)*abs(linedelta); } const void *array = buf; if (cb || driver->has_feature(Fl_Quartz_Graphics_Driver::PRINTER)) { tmpBuf = new uchar[ H*W*abs(delta) ]; if (cb) { for (int i=0; idraw_CGImage(img, 0,0,W,H, 0,0,W,H); CGImageRelease(img); CGContextRestoreGState(gc); } } void Fl_Quartz_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ d &= ~FL_IMAGE_WITH_ALPHA; innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0,gc_,this); } void Fl_Quartz_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data,gc_,this); } void Fl_Quartz_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ innards(buf,x,y,w,h,d,l,1,0,0,gc_,this); } void Fl_Quartz_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { innards(0,x,y,w,h,d,0,1,cb,data,gc_,this); } void Fl_Quartz_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; if (!bm->array) { draw_empty(bm, XP, YP); return; } if (start_image(bm, XP,YP,WP,HP,cx,cy,X,Y,W,H)) return; if (!*id(bm)) cache(bm); if (*Fl_Graphics_Driver::id(bm) && gc_) { draw_CGImage((CGImageRef)*Fl_Graphics_Driver::id(bm), X,Y,W,H, cx, cy, bm->w(), bm->h()); } } void Fl_Quartz_Graphics_Driver::cache(Fl_RGB_Image *rgb) { CGColorSpaceRef lut = rgb->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); int ld = rgb->ld(); if (!ld) ld = rgb->data_w() * rgb->d(); CGDataProviderRef src; if ( has_feature(PRINTER) ) { // When printing or copying to clipboard, the data at rgb->array are used when // the PDF page is completed, that is, after return from this function. // At that stage, the rgb object has possibly been deleted. It is therefore necessary // to use a copy of rgb->array. The mask_ member of rgb // is used to avoid repeating the copy operation if rgb is drawn again. // The CGImage data provider deletes the copy at the latest of these two events: // deletion of rgb, and completion of the PDF page where rgb was drawn. size_t total = ld * rgb->data_h(); uchar *copy = new uchar[total]; memcpy(copy, rgb->array, total); src = CGDataProviderCreateWithData(NULL, copy, total, dataReleaseCB); *Fl_Graphics_Driver::mask(rgb) = 1; } else { // the CGImage data provider must not release the image data. src = CGDataProviderCreateWithData(NULL, rgb->array, ld * rgb->data_h(), NULL); } CGImageRef cgimg = CGImageCreate(rgb->data_w(), rgb->data_h(), 8, rgb->d()*8, ld, lut, (rgb->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, src, 0L, false, kCGRenderingIntentDefault); *Fl_Graphics_Driver::id(rgb) = (fl_uintptr_t)cgimg; CGColorSpaceRelease(lut); CGDataProviderRelease(src); } void Fl_Quartz_Graphics_Driver::draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; // Don't draw an empty image... if (!img->d() || !img->array) { Fl_Graphics_Driver::draw_empty(img, XP, YP); return; } if (start_image(img, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; } CGImageRef cgimg = (CGImageRef)*Fl_Graphics_Driver::id(img); if (cgimg && has_feature(PRINTER) && !*Fl_Graphics_Driver::mask(img)) { CGImageRelease(cgimg); *Fl_Graphics_Driver::id(img) = 0; cgimg = NULL; } if (!cgimg) { cache(img); cgimg = (CGImageRef)*Fl_Graphics_Driver::id(img); } if (cgimg && gc_) { draw_CGImage(cgimg, X,Y,W,H, cx,cy, img->w(), img->h()); } } void Fl_Quartz_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; if (!pxm->data() || !pxm->w()) { draw_empty(pxm, XP, YP); return; } if ( start_image(pxm, XP,YP,WP,HP,cx,cy,X,Y,W,H) ) return; if (!*id(pxm)) { cache(pxm); } CGImageRef cgimg = (CGImageRef)*Fl_Graphics_Driver::id(pxm); draw_CGImage(cgimg, X,Y,W,H, cx,cy, pxm->w(), pxm->h()); } CGImageRef Fl_Quartz_Graphics_Driver::create_bitmask(int w, int h, const uchar *array) { static uchar reverse[16] = /* Bit reversal lookup table */ { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee, 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff }; int rowBytes = (w+7)>>3 ; uchar *bmask = new uchar[rowBytes*h]; uchar *dst = bmask; const uchar *src = array; for ( int i=rowBytes*h; i>0; i--,src++ ) { *dst++ = ((reverse[*src & 0x0f] & 0xf0) | (reverse[(*src >> 4) & 0x0f] & 0x0f))^0xff; } CGDataProviderRef srcp = CGDataProviderCreateWithData( NULL, bmask, rowBytes*h, dataReleaseCB); CGImageRef id_ = CGImageMaskCreate( w, h, 1, 1, rowBytes, srcp, 0L, false); CGDataProviderRelease(srcp); return id_; } void Fl_Quartz_Graphics_Driver::delete_bitmask(fl_uintptr_t bm) { if (bm) CGImageRelease((CGImageRef)bm); } void Fl_Quartz_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) { if (id_) { CGImageRelease((CGImageRef)id_); id_ = 0; mask_ = 0; } } void Fl_Quartz_Graphics_Driver::cache(Fl_Bitmap *bm) { *Fl_Graphics_Driver::id(bm) = (fl_uintptr_t)create_bitmask(bm->data_w(), bm->data_h(), bm->array); } static void pmProviderRelease (void *ctxt, const void *data, size_t size) { CFRelease(ctxt); } void Fl_Quartz_Graphics_Driver::cache(Fl_Pixmap *img) { Fl_Image_Surface *surf = new Fl_Image_Surface(img->data_w(), img->data_h()); Fl_Surface_Device::push_current(surf); fl_draw_pixmap(img->data(), 0, 0, FL_BLACK); Fl_Surface_Device::pop_current(); CGContextRef src = (CGContextRef)Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surf); void *cgdata = CGBitmapContextGetData(src); int sw = (int)CGBitmapContextGetWidth(src); int sh = (int)CGBitmapContextGetHeight(src); CGImageAlphaInfo alpha = CGBitmapContextGetAlphaInfo(src); CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); CGDataProviderRef src_bytes = CGDataProviderCreateWithData(src, cgdata, sw*sh*4, pmProviderRelease); CGImageRef cgimg = CGImageCreate( sw, sh, 8, 4*8, 4*sw, lut, alpha, src_bytes, 0L, false, kCGRenderingIntentDefault); CGColorSpaceRelease(lut); CGDataProviderRelease(src_bytes); *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)cgimg; } void Fl_Quartz_Graphics_Driver::draw_CGImage(CGImageRef cgimg, int x, int y, int w, int h, int srcx, int srcy, int sw, int sh) { CGRect rect = CGRectMake(x, y, w, h); CGContextSaveGState(gc_); CGContextClipToRect(gc_, CGRectOffset(rect, -0.5, -0.5 )); // move graphics context to origin of vertically reversed image // The 0.5 here cancels the 0.5 offset present in Quartz graphics contexts. // Thus, image and surface pixels are in phase. CGContextTranslateCTM(gc_, rect.origin.x - srcx - 0.5, rect.origin.y - srcy + sh - 0.5); CGContextScaleCTM(gc_, 1, -1); CGContextDrawImage(gc_, CGRectMake(0, 0, sw, sh), cgimg); CGContextRestoreGState(gc_); } void Fl_Quartz_Graphics_Driver::uncache_pixmap(fl_uintptr_t pixmap_ref) { CGImageRelease((CGImageRef)pixmap_ref); } fltk-1.4.3/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_color.cxx0000644000175000017500000000416015004135251025325 0ustar albrechtalbrecht// // MacOS color functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // The fltk "colormap". This allows ui colors to be stored in 8-bit // locations, and provides a level of indirection so that global color // changes can be made. Not to be confused with the X colormap, which // I try to hide completely. // matt: Neither Quartz nor Quickdraw support colormaps in this implementation // matt: Quartz support done #include "Fl_Quartz_Graphics_Driver.H" #include #include #include #include extern unsigned fl_cmap[256]; // defined in fl_color.cxx void Fl_Quartz_Graphics_Driver::color(Fl_Color i) { Fl_Graphics_Driver::color(i); uchar r, g, b; float fa = 1.0f; if (i & 0xFFFFFF00) { // translate rgb colors into color index r = i>>24; g = i>>16; b = i>> 8; } else { // translate index into rgb: unsigned c = fl_cmap[i]; c = c ^ 0x000000ff; // trick to restore the color's correct alpha value r = c>>24; g = c>>16; b = c>> 8; uchar a = c & 0xff; //printf("i=%d rgb=%u,%u,%u a=%u\n",i,r,g,b,a); fa = a/255.0f; } if (!gc_) return; // no context yet? We will assign the color later. float fr = r/255.0f; float fg = g/255.0f; float fb = b/255.0f; CGContextSetRGBFillColor(gc_, fr, fg, fb, fa); CGContextSetRGBStrokeColor(gc_, fr, fg, fb, fa); } void Fl_Quartz_Graphics_Driver::color(uchar r, uchar g, uchar b) { Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) ); float fr = r/255.0f; float fg = g/255.0f; float fb = b/255.0f; if (!gc_) return; // no context yet? We will assign the color later. CGContextSetRGBFillColor(gc_, fr, fg, fb, 1.0f); CGContextSetRGBStrokeColor(gc_, fr, fg, fb, 1.0f); } fltk-1.4.3/src/drivers/Unix/0000755000175000017500000000000015004135251015775 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/Unix/Fl_Unix_Screen_Driver.cxx0000644000175000017500000000475715004135251022714 0ustar albrechtalbrecht// // Definition of the part of the Screen interface shared by X11/Wayland // // Copyright 2022-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "Fl_Unix_Screen_Driver.H" #if !USE_POLL fd_set Fl_Unix_Screen_Driver::fdsets[3]; #endif int Fl_Unix_Screen_Driver::maxfd = 0; int Fl_Unix_Screen_Driver::nfds = 0; Fl_Unix_Screen_Driver::FD *Fl_Unix_Screen_Driver::fd = NULL; // these pointers are set by the Fl::lock() function: static void nothing() {} void (*fl_lock_function)() = nothing; void (*fl_unlock_function)() = nothing; // This is never called with time_to_wait < 0.0: // It should return negative on error, 0 if nothing happens before // timeout, and >0 if any callbacks were done. int Fl_Unix_Screen_Driver::poll_or_select_with_delay(double time_to_wait) { # if !USE_POLL fd_set fdt[3]; fdt[0] = fdsets[0]; fdt[1] = fdsets[1]; fdt[2] = fdsets[2]; # endif int n; fl_unlock_function(); if (time_to_wait < 2147483.648) { # if USE_POLL n = ::poll(pollfds, nfds, int(time_to_wait*1000 + .5)); # else timeval t; t.tv_sec = int(time_to_wait); t.tv_usec = int(1000000 * (time_to_wait-t.tv_sec)); n = ::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],&t); # endif } else { # if USE_POLL n = ::poll(pollfds, nfds, -1); # else n = ::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],0); # endif } fl_lock_function(); if (n > 0) { for (int i=0; i #include "../../Fl_Screen_Driver.H" # if USE_POLL # include static pollfd *pollfds = 0; # else # if HAVE_SYS_SELECT_H # include # endif /* HAVE_SYS_SELECT_H */ // NetBSD before version 3.0 declares select() in "unistd.h" (#944): // https://man.netbsd.org/NetBSD-2.1/select.2 # if defined(__NetBSD__) # include // For '__NetBSD_Version__' definition # if defined(__NetBSD_Version__) && (__NetBSD_Version__ < 300000000) # include # include # include # endif // __NetBSD_Version__ # endif // __NetBSD__ # define POLLIN 1 # define POLLOUT 4 # define POLLERR 8 # endif /* USE_POLL */ class Fl_Unix_Screen_Driver : public Fl_Screen_Driver { public: # if !USE_POLL static fd_set fdsets[3]; # endif static int maxfd; static int nfds; static struct FD { # if !USE_POLL int fd; short events; # endif void (*cb)(int, void*); void* arg; } *fd; virtual int poll_or_select_with_delay(double time_to_wait); virtual int poll_or_select(); virtual void *control_maximize_button(void *) { return NULL; } }; #endif /* FL_UNIX_SCREEN_DRIVER_H */ fltk-1.4.3/src/drivers/Unix/Fl_Unix_System_Driver.H0000644000175000017500000000506315004135251022335 0ustar albrechtalbrecht// // Definition of Wayland system driver // for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_NIX_SYSTEM_DRIVER_H #define FL_NIX_SYSTEM_DRIVER_H #include "../Posix/Fl_Posix_System_Driver.H" class Fl_RGB_Image; class Fl_Unix_System_Driver : public Fl_Posix_System_Driver { public: int clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) FL_OVERRIDE; int clocale_vsscanf(const char *input, const char *format, va_list args) FL_OVERRIDE; int clocale_vprintf(FILE *output, const char *format, va_list args) FL_OVERRIDE; int filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **), char *errmsg=NULL, int errmsg_sz=0) FL_OVERRIDE; int open_uri(const char *uri, char *msg, int msglen) FL_OVERRIDE; int use_tooltip_timeout_condition() FL_OVERRIDE {return 1;} int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon) FL_OVERRIDE; void newUUID(char *uuidBuffer) FL_OVERRIDE; char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor, const char *application) FL_OVERRIDE; char *preference_memory_rootnode(const char *vendor, const char *application, char *buffer); char *preference_system_rootnode(const char *vendor, const char *application, char *buffer); char *preference_user_rootnode(const char *vendor, const char *application, char *buffer); int preferences_need_protection_check() FL_OVERRIDE {return 1;} int utf8locale() FL_OVERRIDE; const char *filename_name(const char *buf) FL_OVERRIDE; void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE; void add_fd(int fd, Fl_FD_Handler cb, void* = 0) FL_OVERRIDE; void remove_fd(int, int when) FL_OVERRIDE; void remove_fd(int) FL_OVERRIDE; double wait(double time_to_wait) FL_OVERRIDE; int ready() FL_OVERRIDE; static unsigned char *create_bmp(const unsigned char *data, int W, int H, int *return_size); static Fl_RGB_Image *own_bmp_to_RGB(char *bmp); static void read_int(uchar *c, int& i); }; #endif /* FL_NIX_SYSTEM_DRIVER_H */ fltk-1.4.3/src/drivers/Unix/Fl_Unix_System_Driver.cxx0000644000175000017500000006703215004135251022754 0ustar albrechtalbrecht// // Definition of Unix/Linux system driver // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_Unix_System_Driver.H" #include "Fl_Unix_Screen_Driver.H" #include #include // fl_strdup #include #include "../../flstring.h" #include "../../Fl_String.H" #include "../../Fl_Timeout.h" #include #include #include #include #include #include // strerror(errno) #include // errno #if HAVE_DLSYM && HAVE_DLFCN_H #include // for dlsym #endif #if defined(_AIX) extern "C" { # include # include // Older AIX versions don't expose this prototype int mntctl(int, int, char *); } #endif // _AIX #if defined(__NetBSD__) extern "C" { # include // For '__NetBSD_Version__' definition # if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 300000000) # include # include # if defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_H) # include # endif // HAVE_PTHREAD && HAVE_PTHREAD_H # ifdef HAVE_PTHREAD static pthread_mutex_t getvfsstat_mutex = PTHREAD_MUTEX_INITIALIZER; # endif // HAVE_PTHREAD/ # endif // __NetBSD_Version__ } #endif // __NetBSD__ #ifndef HAVE_SCANDIR extern "C" { int fl_scandir(const char *dirname, struct dirent ***namelist, int (*select)(struct dirent *), int (*compar)(struct dirent **, struct dirent **), char *errmsg, int errmsg_sz); } #endif #if defined(__linux__) && defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700 static locale_t c_locale = NULL; #endif int Fl_Unix_System_Driver::clocale_vprintf(FILE *output, const char *format, va_list args) { #if defined(__linux__) && defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700 if (!c_locale) c_locale = newlocale(LC_NUMERIC_MASK, "C", duplocale(LC_GLOBAL_LOCALE)); locale_t previous_locale = uselocale(c_locale); int retval = vfprintf(output, format, args); uselocale(previous_locale); #else char *saved_locale = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); int retval = vfprintf(output, format, args); setlocale(LC_NUMERIC, saved_locale); #endif return retval; } int Fl_Unix_System_Driver::clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) { #if defined(__linux__) && defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700 if (!c_locale) c_locale = newlocale(LC_NUMERIC_MASK, "C", duplocale(LC_GLOBAL_LOCALE)); locale_t previous_locale = uselocale(c_locale); int retval = vsnprintf(output, output_size, format, args); uselocale(previous_locale); #else char *saved_locale = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); int retval = vsnprintf(output, output_size, format, args); setlocale(LC_NUMERIC, saved_locale); #endif return retval; } int Fl_Unix_System_Driver::clocale_vsscanf(const char *input, const char *format, va_list args) { #if defined(__linux__) && defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700 if (!c_locale) c_locale = newlocale(LC_NUMERIC_MASK, "C", duplocale(LC_GLOBAL_LOCALE)); locale_t previous_locale = uselocale(c_locale); int retval = vsscanf(input, format, args); uselocale(previous_locale); #else char *saved_locale = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); #if defined(__hpux) // HP-UX 11.11 provides: // int vsscanf(char *s, const char *format, va_list ap); int retval = vsscanf((char*)input, format, args); #else // defined(__hpux) int retval = vsscanf(input, format, args); #endif // defined(__hpux) setlocale(LC_NUMERIC, saved_locale); #endif return retval; } // Find a program in the path... static char *path_find(const char *program, char *filename, int filesize) { const char *path; // Search path char *ptr, // Pointer into filename *end; // End of filename buffer if ((path = fl_getenv("PATH")) == NULL) path = "/bin:/usr/bin"; for (ptr = filename, end = filename + filesize - 1; *path; path ++) { if (*path == ':') { if (ptr > filename && ptr[-1] != '/' && ptr < end) *ptr++ = '/'; strlcpy(ptr, program, end - ptr + 1); if (!access(filename, X_OK)) return filename; ptr = filename; } else if (ptr < end) *ptr++ = *path; } if (ptr > filename) { if (ptr[-1] != '/' && ptr < end) *ptr++ = '/'; strlcpy(ptr, program, end - ptr + 1); if (!access(filename, X_OK)) return filename; } return 0; } int Fl_Unix_System_Driver::open_uri(const char *uri, char *msg, int msglen) { // Run any of several well-known commands to open the URI. // // We give preference to the Portland group's xdg-utils // programs which run the user's preferred web browser, etc. // based on the current desktop environment in use. We fall // back on older standards and then finally test popular programs // until we find one we can use. // // Note that we specifically do not support the MAILER and // BROWSER environment variables because we have no idea whether // we need to run the listed commands in a terminal program. char command[FL_PATH_MAX], // Command to run... *argv[4], // Command-line arguments remote[1024]; // Remote-mode command... const char * const *commands; // Array of commands to check... int i; static const char * const browsers[] = { "xdg-open", // Portland "htmlview", // Freedesktop.org "firefox", "mozilla", "netscape", "konqueror", // KDE "opera", "hotjava", // Solaris "mosaic", NULL }; static const char * const readers[] = { "xdg-email", // Portland "thunderbird", "mozilla", "netscape", "evolution", // GNOME "kmailservice", // KDE NULL }; static const char * const managers[] = { "xdg-open", // Portland "fm", // IRIX "dtaction", // CDE "nautilus", // GNOME "konqueror", // KDE NULL }; // Figure out which commands to check for... if (!strncmp(uri, "file://", 7)) commands = managers; else if (!strncmp(uri, "mailto:", 7) || !strncmp(uri, "news:", 5)) commands = readers; else commands = browsers; // Find the command to run... for (i = 0; commands[i]; i ++) if (path_find(commands[i], command, sizeof(command))) break; if (!commands[i]) { if (msg) { snprintf(msg, msglen, "No helper application found for \"%s\"", uri); } return 0; } // Handle command-specific arguments... argv[0] = (char *)commands[i]; if (!strcmp(commands[i], "firefox") || !strcmp(commands[i], "mozilla") || !strcmp(commands[i], "netscape") || !strcmp(commands[i], "thunderbird")) { // program -remote openURL(uri) snprintf(remote, sizeof(remote), "openURL(%s)", uri); argv[1] = (char *)"-remote"; argv[2] = remote; argv[3] = 0; } else if (!strcmp(commands[i], "dtaction")) { // dtaction open uri argv[1] = (char *)"open"; argv[2] = (char *)uri; argv[3] = 0; } else { // program uri argv[1] = (char *)uri; argv[2] = 0; } if (msg) { strlcpy(msg, argv[0], msglen); for (i = 1; argv[i]; i ++) { strlcat(msg, " ", msglen); strlcat(msg, argv[i], msglen); } } return run_program(command, argv, msg, msglen) != 0; } int Fl_Unix_System_Driver::file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon) { int num_files = 0; #if defined(_AIX) // AIX don't write the mounted filesystems to a file like '/etc/mnttab'. // But reading the list of mounted filesystems from the kernel is possible: // http://publib.boulder.ibm.com/infocenter/pseries/v5r3/topic/com.ibm.aix.basetechref/doc/basetrf1/mntctl.htm int res = -1, len; char *list = NULL, *name; // We always have the root filesystem browser->add("/", icon); num_files++; // Get the required buffer size for the vmount structures res = mntctl(MCTL_QUERY, sizeof(len), (char *) &len); if (!res) { // Allocate buffer ... list = (char *) malloc((size_t) len); if (NULL == list) { res = -1; } else { // ... and read vmount structures from kernel res = mntctl(MCTL_QUERY, len, list); if (0 >= res) { res = -1; } else { struct vmount *vp = (struct vmount *) list; for (int i = 0; i < res; ++i) { name = (char *) vp + vp->vmt_data[VMT_STUB].vmt_off; strlcpy(filename, name, lname); // Skip the already added root filesystem if (strcmp("/", filename) != 0) { strlcat(filename, "/", lname); browser->add(filename, icon); num_files++; } vp = (struct vmount *) ((char *) vp + vp->vmt_length); } } } } // Note: Executing 'free(NULL)' is allowed and simply do nothing free((void *) list); #elif defined(__NetBSD__) && defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 300000000) // NetBSD don't write the mounted filesystems to a file like '/etc/mnttab'. // Since NetBSD 3.0 the system call getvfsstat(2) has replaced getfsstat(2) // that is used by getmntinfo(3): // http://www.daemon-systems.org/man/getmntinfo.3.html int res = -1; struct statvfs *list; // We always have the root filesystem browser->add("/", icon); num_files++; # ifdef HAVE_PTHREAD // Lock mutex for thread safety if (!pthread_mutex_lock(&getvfsstat_mutex)) { # endif // HAVE_PTHREAD // Get list of statvfs structures res = getmntinfo(&list, ST_WAIT); if (0 < res) { for (int i = 0; i < res; ++i) { strlcpy(filename, list[i].f_mntonname, lname); // Skip the already added root filesystem if (strcmp("/", filename) != 0) { strlcat(filename, "/", lname); browser->add(filename, icon); num_files++; } } } else { res = -1; } # ifdef HAVE_PTHREAD pthread_mutex_unlock(&getvfsstat_mutex); } # endif // HAVE_PTHREAD #else // // UNIX code uses /etc/fstab or similar... // FILE *mtab; // /etc/mtab or /etc/mnttab file char line[FL_PATH_MAX]; // Input line // Every Unix has a root filesystem '/'. // This ensures that the user don't get an empty // window after requesting filesystem list. browser->add("/", icon); num_files ++; // // Open the file that contains a list of mounted filesystems... // // Note: this misses automounted filesystems on FreeBSD if absent from /etc/fstab // mtab = fopen("/etc/mnttab", "r"); // Fairly standard if (mtab == NULL) mtab = fopen("/etc/mtab", "r"); // More standard if (mtab == NULL) mtab = fopen("/etc/fstab", "r"); // Otherwise fallback to full list if (mtab == NULL) mtab = fopen("/etc/vfstab", "r"); // Alternate full list file if (mtab != NULL) { while (fgets(line, sizeof(line), mtab) != NULL) { if (line[0] == '#' || line[0] == '\n') continue; if (sscanf(line, "%*s%4095s", filename) != 1) continue; if (strcmp("/", filename) == 0) continue; // "/" was added before // Add a trailing slash (except for the root filesystem) strlcat(filename, "/", lname); // printf("Fl_File_Browser::load() - adding \"%s\" to list...\n", filename); browser->add(filename, icon); num_files ++; } fclose(mtab); } #endif // _AIX || ... return num_files; } void Fl_Unix_System_Driver::newUUID(char *uuidBuffer) { unsigned char b[16]; #if HAVE_DLSYM && HAVE_DLFCN_H typedef void (*gener_f_type)(uchar*); static bool looked_for_uuid_generate = false; static gener_f_type uuid_generate_f = NULL; if (!looked_for_uuid_generate) { looked_for_uuid_generate = true; uuid_generate_f = (gener_f_type)dlopen_or_dlsym("libuuid", "uuid_generate"); } if (uuid_generate_f) { uuid_generate_f(b); } else #endif { time_t t = time(0); // first 4 byte b[0] = (unsigned char)t; b[1] = (unsigned char)(t>>8); b[2] = (unsigned char)(t>>16); b[3] = (unsigned char)(t>>24); int r = rand(); // four more bytes b[4] = (unsigned char)r; b[5] = (unsigned char)(r>>8); b[6] = (unsigned char)(r>>16); b[7] = (unsigned char)(r>>24); unsigned long a = (unsigned long)&t; // four more bytes b[8] = (unsigned char)a; b[9] = (unsigned char)(a>>8); b[10] = (unsigned char)(a>>16); b[11] = (unsigned char)(a>>24); // Now we try to find 4 more "random" bytes. We extract the // lower 4 bytes from the address of t - it is created on the // stack so *might* be in a different place each time... // This is now done via a union to make it compile OK on 64-bit systems. union { void *pv; unsigned char a[sizeof(void*)]; } v; v.pv = (void *)(&t); // NOTE: May need to handle big- or little-endian systems here # if WORDS_BIGENDIAN b[8] = v.a[sizeof(void*) - 1]; b[9] = v.a[sizeof(void*) - 2]; b[10] = v.a[sizeof(void*) - 3]; b[11] = v.a[sizeof(void*) - 4]; # else // data ordered for a little-endian system b[8] = v.a[0]; b[9] = v.a[1]; b[10] = v.a[2]; b[11] = v.a[3]; # endif char name[80]; // last four bytes gethostname(name, 79); memcpy(b+12, name, 4); } snprintf(uuidBuffer, 36+1, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]); } /* Create a buffer that holds the absolute file path and name of the preferences file for the given root, vendor, and application name. Note: `prefs` can be NULL! */ char *Fl_Unix_System_Driver::preference_rootnode(Fl_Preferences * /*prefs*/, Fl_Preferences::Root root, const char *vendor, const char *application) { // Create a static buffer for our filename static char *buffer = 0L; if (!buffer) buffer = (char*)::calloc(1, FL_PATH_MAX); buffer[0] = '\0'; // Make sure that the parameters are not NULL if ( (vendor==NULL) || (vendor[0]==0) ) vendor = "unknown"; if ( (application==NULL) || (application[0]==0) ) application = "unknown"; // Dispatch to the various path creators for the requested root. char *prefs_path = NULL; int pref_type = root & Fl_Preferences::ROOT_MASK; switch (pref_type) { case Fl_Preferences::USER: prefs_path = preference_user_rootnode(vendor, application, buffer); break; case Fl_Preferences::SYSTEM: prefs_path = preference_system_rootnode(vendor, application, buffer); break; case Fl_Preferences::MEMORY: default: prefs_path = preference_memory_rootnode(vendor, application, buffer); break; } return prefs_path; } /* Memory based preferences are never saved to any file, so the path is just an empty string. */ char *Fl_Unix_System_Driver::preference_memory_rootnode( const char * /*vendor*/, const char * /*application*/, char *buffer) { buffer[0] = 0; return buffer; } /* The path and file name for system preferences on Unix type systems is `/etc/fltk/{vendor}/{application}.prefs`. */ char *Fl_Unix_System_Driver::preference_system_rootnode( const char *vendor, const char *application, char *buffer) { snprintf(buffer, FL_PATH_MAX, "/etc/fltk/%s/%s.prefs", vendor, application); return buffer; } /* The user path changed between FLTK 1.3 and 1.4. It is now calculated using XDG guidelines. It is `$XDG_CONFIG_HOME/{vendor}/{application}.prefs` if `$XDG_CONFIG_HOME` is set, and `$HOME/.config/{vendor}/{application}.prefs` if `$XDG_CONFIG_HOME` is not set or empty. For compatibility with 1.3 preferences, this function checks 1. Does the XDG based top level folder '{vendor}' exist? If yes, use it. 2. If not: does the old location $HOME/.fltk/{vendor} exist? If yes, use it. 3. If neither: fall back to (1.) and use the XDG based folder (create it and the prefs file below it). */ char *Fl_Unix_System_Driver::preference_user_rootnode( const char *vendor, const char *application, char *buffer) { // Find the path to the user's home directory. Fl_String home_path = getenv("HOME"); if (home_path.empty()) { struct passwd *pw = getpwuid(getuid()); if (pw) home_path = pw->pw_dir; } // 1: Generate the 1.4 path for this vendor and application. Fl_String prefs_path_14 = getenv("XDG_CONFIG_HOME"); if (prefs_path_14.empty()) { prefs_path_14 = home_path + "/.config"; } else { if (prefs_path_14[prefs_path_14.size()-1]!='/') prefs_path_14.append('/'); if (prefs_path_14.find("~/")==0) // starts with "~" prefs_path_14.replace(0, 1, home_path); int h_env = prefs_path_14.find("${HOME}"); if (h_env!=prefs_path_14.npos) prefs_path_14.replace(h_env, 7, home_path); h_env = prefs_path_14.find("$HOME/"); if (h_env!=prefs_path_14.npos) prefs_path_14.replace(h_env, 5, home_path); } if (prefs_path_14[prefs_path_14.size()-1]!='/') prefs_path_14.append('/'); prefs_path_14.append(vendor); // 2: If this base path does not exist, try the 1.3 path if (::access(prefs_path_14.c_str(), F_OK) == -1) { Fl_String prefs_path_13 = home_path + "/.fltk/" + vendor; if (::access(prefs_path_13.c_str(), F_OK) == 0) { prefs_path_13.append('/'); prefs_path_13.append(application); prefs_path_13.append(".prefs"); strlcpy(buffer, prefs_path_13.c_str(), FL_PATH_MAX); return buffer; } } // 3: neither path exists, return the 1.4 file path and name prefs_path_14.append('/'); prefs_path_14.append(application); prefs_path_14.append(".prefs"); strlcpy(buffer, prefs_path_14.c_str(), FL_PATH_MAX); return buffer; } // // Needs some docs // Returns -1 on error, errmsg will contain OS error if non-NULL. // int Fl_Unix_System_Driver::filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **), char *errmsg, int errmsg_sz) { int dirlen; char *dirloc; if (errmsg && errmsg_sz>0) errmsg[0] = '\0'; // Assume that locale encoding is no less dense than UTF-8 dirlen = strlen(d); dirloc = (char *)malloc(dirlen + 1); fl_utf8to_mb(d, dirlen, dirloc, dirlen + 1); #ifndef HAVE_SCANDIR // This version is when we define our own scandir. Note it updates errmsg on errors. int n = fl_scandir(dirloc, list, 0, sort, errmsg, errmsg_sz); #elif defined(HAVE_SCANDIR_POSIX) // POSIX (2008) defines the comparison function like this: int n = scandir(dirloc, list, 0, (int(*)(const dirent **, const dirent **))sort); #elif defined(__osf__) // OSF, DU 4.0x int n = scandir(dirloc, list, 0, (int(*)(dirent **, dirent **))sort); #elif defined(_AIX) // AIX is almost standard... int n = scandir(dirloc, list, 0, (int(*)(void*, void*))sort); #elif defined(__sgi) int n = scandir(dirloc, list, 0, sort); #else // The vast majority of UNIX systems want the sort function to have this // prototype, most likely so that it can be passed to qsort without any // changes: int n = scandir(dirloc, list, 0, (int(*)(const void*,const void*))sort); #endif free(dirloc); if (n==-1) { // Don't write to errmsg if FLTK's fl_scandir() already set it. // If OS's scandir() was used (HAVE_SCANDIR), we return its error in errmsg here.. #ifdef HAVE_SCANDIR if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno)); #endif return -1; } // convert every filename to UTF-8, and append a '/' to all // filenames that are directories int i; char *fullname = (char*)malloc(dirlen+FL_PATH_MAX+3); // Add enough extra for two /'s and a nul // Use memcpy for speed since we already know the length of the string... memcpy(fullname, d, dirlen+1); char *name = fullname + dirlen; if (name!=fullname && name[-1]!='/') *name++ = '/'; for (i=0; id_name); newlen = fl_utf8from_mb(NULL, 0, de->d_name, len); dirent *newde = (dirent*)malloc(de->d_name - (char*)de + newlen + 2); // Add space for a / and a nul // Conversion to UTF-8 memcpy(newde, de, de->d_name - (char*)de); fl_utf8from_mb(newde->d_name, newlen + 1, de->d_name, len); // Check if dir (checks done on "old" name as we need to interact with // the underlying OS) if (de->d_name[len-1]!='/' && len<=FL_PATH_MAX) { // Use memcpy for speed since we already know the length of the string... memcpy(name, de->d_name, len+1); if (fl_filename_isdir(fullname)) { char *dst = newde->d_name + newlen; *dst++ = '/'; *dst = 0; } } free(de); (*list)[i] = newde; } free(fullname); return n; } int Fl_Unix_System_Driver::utf8locale() { static int ret = 2; if (ret == 2) { char* s; ret = 1; /* assume UTF-8 if no locale */ if (((s = getenv("LC_CTYPE")) && *s) || ((s = getenv("LC_ALL")) && *s) || ((s = getenv("LANG")) && *s)) { ret = (strstr(s,"utf") || strstr(s,"UTF")); } } return ret; } // returns pointer to the filename, or null if name ends with '/' const char *Fl_Unix_System_Driver::filename_name(const char *name) { const char *p,*q; if (!name) return (0); for (p=q=name; *p;) if (*p++ == '/') q = p; return q; } static int fd_array_size = 0; void Fl_Unix_System_Driver::add_fd(int n, int events, void (*cb)(int, void*), void *v) { remove_fd(n,events); int i = Fl_Unix_Screen_Driver::nfds++; if (i >= fd_array_size) { Fl_Unix_Screen_Driver::FD *temp; fd_array_size = 2*fd_array_size+1; if (!Fl_Unix_Screen_Driver::fd) temp = (Fl_Unix_Screen_Driver::FD*)malloc(fd_array_size*sizeof(Fl_Unix_Screen_Driver::FD)); else temp = (Fl_Unix_Screen_Driver::FD*)realloc(Fl_Unix_Screen_Driver::fd, fd_array_size*sizeof(Fl_Unix_Screen_Driver::FD)); if (!temp) return; Fl_Unix_Screen_Driver::fd = temp; # if USE_POLL pollfd *tpoll; if (!pollfds) tpoll = (pollfd*)malloc(fd_array_size*sizeof(pollfd)); else tpoll = (pollfd*)realloc(pollfds, fd_array_size*sizeof(pollfd)); if (!tpoll) return; pollfds = tpoll; # endif } Fl_Unix_Screen_Driver::fd[i].cb = cb; Fl_Unix_Screen_Driver::fd[i].arg = v; # if USE_POLL pollfds[i].fd = n; pollfds[i].events = events; # else Fl_Unix_Screen_Driver::fd[i].fd = n; Fl_Unix_Screen_Driver::fd[i].events = events; if (events & POLLIN) FD_SET(n, &Fl_Unix_Screen_Driver::fdsets[0]); if (events & POLLOUT) FD_SET(n, &Fl_Unix_Screen_Driver::fdsets[1]); if (events & POLLERR) FD_SET(n, &Fl_Unix_Screen_Driver::fdsets[2]); if (n > Fl_Unix_Screen_Driver::maxfd) Fl_Unix_Screen_Driver::maxfd = n; # endif } void Fl_Unix_System_Driver::add_fd(int n, void (*cb)(int, void*), void* v) { add_fd(n, POLLIN, cb, v); } void Fl_Unix_System_Driver::remove_fd(int n, int events) { int i,j; # if !USE_POLL Fl_Unix_Screen_Driver::maxfd = -1; // recalculate maxfd on the fly # endif for (i=j=0; i Fl_Unix_Screen_Driver::maxfd) Fl_Unix_Screen_Driver::maxfd = Fl_Unix_Screen_Driver::fd[i].fd; # endif // move it down in the array if necessary: if (jpoll_or_select_with_delay(0.0); Fl::flush(); return ret; } else { // do flush first so that user sees the display: Fl::flush(); if (Fl::idle) // 'idle' may have been set within flush() time_to_wait = 0.0; else { Fl_Timeout::elapse_timeouts(); time_to_wait = Fl_Timeout::time_to_wait(time_to_wait); } return scr_dr->poll_or_select_with_delay(time_to_wait); } } int Fl_Unix_System_Driver::ready() { Fl_Unix_Screen_Driver *scr_dr = (Fl_Unix_Screen_Driver*)Fl::screen_driver(); Fl_Timeout::elapse_timeouts(); if (Fl_Timeout::time_to_wait(1.0) <= 0.0) return 1; return scr_dr->poll_or_select(); } static void write_short(unsigned char **cp, short i) { unsigned char *c = *cp; *c++ = i & 0xFF; i >>= 8; *c++ = i & 0xFF; *cp = c; } static void write_int(unsigned char **cp, int i) { unsigned char *c = *cp; *c++ = i & 0xFF; i >>= 8; *c++ = i & 0xFF; i >>= 8; *c++ = i & 0xFF; i >>= 8; *c++ = i & 0xFF; *cp = c; } unsigned char *Fl_Unix_System_Driver::create_bmp(const unsigned char *data, int W, int H, int *return_size) { int R = ((3*W+3)/4) * 4; // the number of bytes per row, rounded up to multiple of 4 int s=H*R; int fs=14+40+s; unsigned char *b=new unsigned char[fs]; unsigned char *c=b; // BMP header *c++='B'; *c++='M'; write_int(&c,fs); write_int(&c,0); write_int(&c,14+40); // DIB header: write_int(&c,40); write_int(&c,W); write_int(&c,H); write_short(&c,1); write_short(&c,24);//bits ber pixel write_int(&c,0);//RGB write_int(&c,s); write_int(&c,0);// horizontal resolution write_int(&c,0);// vertical resolution write_int(&c,0);//number of colors. 0 -> 1<= 0; i--) { char *s = bmp + i * R; for (int j = 0; j < w; j++) { *p++=s[2]; *p++=s[1]; *p++=s[0]; s+=3; } } Fl_RGB_Image *img = new Fl_RGB_Image(data, w, h, 3); img->alloc_array = 1; return img; } fltk-1.4.3/src/drivers/GDI/0000755000175000017500000000000015004135251015455 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H0000644000175000017500000000236215004135251022702 0ustar albrechtalbrecht// // Draw-to-image code for the Fast Light Tool Kit (FLTK). // // Copyright 2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_GDI_IMAGE_SURFACE_DRIVER_H #define FL_GDI_IMAGE_SURFACE_DRIVER_H #include #include #include class Fl_GDI_Image_Surface_Driver : public Fl_Image_Surface_Driver { void end_current() FL_OVERRIDE; public: HWND pre_window; int _savedc; void mask(const Fl_RGB_Image *) FL_OVERRIDE; struct shape_data_type { HBITMAP background; uchar *vBits; Fl_RGB_Image* mask; } *shape_data_; Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off); ~Fl_GDI_Image_Surface_Driver(); void set_current() FL_OVERRIDE; void translate(int x, int y) FL_OVERRIDE; void untranslate() FL_OVERRIDE; Fl_RGB_Image *image() FL_OVERRIDE; POINT origin; }; #endif // FL_GDI_IMAGE_SURFACE_DRIVER_H fltk-1.4.3/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx0000644000175000017500000005444015004135251023415 0ustar albrechtalbrecht// // Windows font utilities for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif /* We require Windows 2000 features such as GetGlyphIndices */ #if !defined(WINVER) || (WINVER < 0x0500) # ifdef WINVER # undef WINVER # endif # define WINVER 0x0500 #endif #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) # ifdef _WIN32_WINNT # undef _WIN32_WINNT # endif # define _WIN32_WINNT 0x0500 #endif // Select fonts from the FLTK font table. #include "Fl_GDI_Graphics_Driver.H" #include "../../flstring.h" #include #include #include #include "Fl_Font.H" #include #include #include // This function fills in the FLTK font table with all the fonts that // are found on the X server. It tries to place the fonts into families // and to sort them so the first 4 in a family are normal, bold, italic, // and bold italic. #include #ifdef __CYGWIN__ # include #endif // Bug: older versions calculated the value for *ap as a side effect of // making the name, and then forgot about it. To avoid having to change // the header files I decided to store this value in the last character // of the font name array. #define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 // turn a stored font name into a pretty name: const char* Fl_GDI_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) { Fl_Fontdesc *f = fl_fonts + fnum; if (!f->fontname[0]) { const char* p = f->name; if (!p || !*p) {if (ap) *ap = 0; return "";} int type; switch (*p) { case 'B': type = FL_BOLD; break; case 'I': type = FL_ITALIC; break; case 'P': type = FL_BOLD | FL_ITALIC; break; default: type = 0; break; } strlcpy(f->fontname, p+1, ENDOFBUFFER); if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER); if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER); f->fontname[ENDOFBUFFER] = (char)type; } if (ap) *ap = f->fontname[ENDOFBUFFER]; return f->fontname; } static int fl_free_font = FL_FREE_FONT; // helper function for `enumcbw()` to avoid code repetition // input: // ft: font "type", i.e. ' ', 'B', 'I', or 'P' // fn: font name whose first byte is overwritten and then stored static void set_font_name(const char ft, char *fn) { fn[0] = ft; Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(fn)); } // Callback for EnumFontFamiliesW(): // return 1 to continue, 0 to stop enumeration static int CALLBACK enumcbw(CONST LOGFONTW *lpelf, CONST TEXTMETRICW * /* lpntm */, DWORD /* FontType */, LPARAM p) { if (!p && lpelf->lfCharSet != ANSI_CHARSET) return 1; char *fn = NULL; // FLTK font name unsigned lw = (unsigned)wcslen(lpelf->lfFaceName); unsigned dstlen = fl_utf8fromwc(fn, 0, (wchar_t*)lpelf->lfFaceName, lw); // measure the string fn = (char*)malloc((size_t)dstlen + 2); // "?" + name + NUL if (!fn) return 1; fn[0] = ' '; dstlen = fl_utf8fromwc(fn+1, dstlen+1, (wchar_t*)lpelf->lfFaceName, lw); // convert the string fn[dstlen + 1] = 0; // skip if it is one of our built-in fonts for (int i = 0; i < FL_FREE_FONT; i++) { if (!strcmp(Fl::get_font_name((Fl_Font)i), fn+1)) { free(fn); return 1; } } set_font_name(' ', fn); if (lpelf->lfWeight <= 400) set_font_name('B', fn); set_font_name('I', fn); if (lpelf->lfWeight <= 400) set_font_name('P', fn); free(fn); return 1; } /* enumcbw */ Fl_Font Fl_GDI_Graphics_Driver::set_fonts(const char* xstarname) { HDC gc = (HDC)fl_graphics_driver->gc(); if (fl_free_font == FL_FREE_FONT) {// if not already been called if (!gc) gc = fl_GetDC(0); EnumFontFamiliesW(gc, NULL, (FONTENUMPROCW)enumcbw, xstarname != 0); } return (Fl_Font)fl_free_font; } static int nbSize; static int cyPerInch; static int sizes[128]; static int CALLBACK EnumSizeCbW(CONST LOGFONTW * /*lpelf*/, CONST TEXTMETRICW *lpntm, DWORD fontType, LPARAM /*p*/) { if ((fontType & RASTER_FONTTYPE) == 0) { sizes[0] = 0; nbSize = 1; // Scalable font return 0; } int add = lpntm->tmHeight - lpntm->tmInternalLeading; add = MulDiv(add, 72, cyPerInch); int start = 0; while ((start < nbSize) && (sizes[start] < add)) { start++; } if ((start < nbSize) && (sizes[start] == add)) { return 1; } for (int i=nbSize; i>start; i--) sizes[i] = sizes[i - 1]; sizes[start] = add; nbSize++; // Stop enum if buffer overflow return nbSize < 128; } int Fl_GDI_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) { nbSize = 0; Fl_Fontdesc *s = fl_fonts+fnum; if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 HDC gc = (HDC)fl_graphics_driver->gc(); if (!gc) gc = fl_GetDC(0); cyPerInch = GetDeviceCaps(gc, LOGPIXELSY); if (cyPerInch < 1) cyPerInch = 1; // int l = fl_utf_nb_char((unsigned char*)s->name+1, strlen(s->name+1)); // unsigned short *b = (unsigned short*) malloc((l + 1) * sizeof(short)); // fl_utf2unicode((unsigned char*)s->name+1, l, (wchar_t*)b); const char *nm = (const char*)s->name+1; size_t len = strlen(s->name+1); unsigned l = fl_utf8toUtf16(nm, (unsigned) len, NULL, 0); // Pass NULL to query length required unsigned short *b = (unsigned short*) malloc((l + 1) * sizeof(short)); l = fl_utf8toUtf16(nm, (unsigned) len, b, (l+1)); // Now do the conversion b[l] = 0; EnumFontFamiliesW(gc, (WCHAR*)b, (FONTENUMPROCW)EnumSizeCbW, 0); free(b); sizep = sizes; return nbSize; } const char *Fl_GDI_Graphics_Driver::font_name(int num) { return fl_fonts[num].name; } void Fl_GDI_Graphics_Driver::font_name(int num, const char *name) { Fl_Fontdesc *s = fl_fonts + num; if (s->name) { if (!strcmp(s->name, name)) {s->name = name; return;} for (Fl_Font_Descriptor* f = s->first; f;) { Fl_Font_Descriptor* n = f->next; delete f; f = n; } s->first = 0; } s->name = name; s->fontname[0] = 0; s->first = 0; } static int fl_angle_ = 0; // Unicode string buffer static unsigned short *wstr = NULL; static int wstr_len = 0; #ifndef FL_DOXYGEN Fl_GDI_Font_Descriptor::Fl_GDI_Font_Descriptor(const char* name, Fl_Fontsize fsize) : Fl_Font_Descriptor(name,fsize) { int weight = FW_NORMAL; int italic = 0; switch (*name++) { case 'I': italic = 1; break; case 'P': italic = 1; case 'B': weight = FW_BOLD; break; case ' ': break; default: name--; } int wn = fl_utf8toUtf16(name, (unsigned int)strlen(name), wstr, wstr_len); if (wn >= wstr_len) { wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1)); wstr_len = wn + 1; wn = fl_utf8toUtf16(name, (unsigned int)strlen(name), wstr, wstr_len); } fid = CreateFontW( -fsize, // negative makes it use "char size" 0, // logical average character width fl_angle_*10, // angle of escapement fl_angle_*10, // base-line orientation angle weight, italic, FALSE, // underline attribute flag FALSE, // strikeout attribute flag DEFAULT_CHARSET, // character set identifier OUT_DEFAULT_PRECIS, // output precision CLIP_DEFAULT_PRECIS,// clipping precision DEFAULT_QUALITY, // output quality DEFAULT_PITCH, // pitch and family (LPCWSTR)wstr // pointer to typeface name string ); angle = fl_angle_; HDC gc = (HDC)fl_graphics_driver->gc(); if (!gc) gc = fl_GetDC(0); SelectObject(gc, fid); GetTextMetrics(gc, &metr); // BOOL ret = GetCharWidthFloat(fl_gc, metr.tmFirstChar, metr.tmLastChar, font->width+metr.tmFirstChar); // ...would be the right call, but is not implemented into Window95! (WinNT?) //GetCharWidth(fl_gc, 0, 255, width); int i; memset(width, 0, 64 * sizeof(int*)); #if HAVE_GL for (i = 0; i < 64; i++) glok[i] = 0; #endif size = fsize; } Fl_GDI_Font_Descriptor::~Fl_GDI_Font_Descriptor() { #if HAVE_GL // Delete list created by gl_draw(). This is not done by this code // as it will link in GL unnecessarily. There should be some kind // of "free" routine pointer, or a subclass? #endif if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL); DeleteObject(fid); for (int i = 0; i < 64; i++) { if ( width[i] ) free(width[i]); } } //////////////////////////////////////////////////////////////// // WARNING: if you add to this table, you must redefine FL_FREE_FONT // in Enumerations.H & recompile!! static Fl_Fontdesc built_in_table[] = { {" Microsoft Sans Serif"}, {"BMicrosoft Sans Serif"}, {"IMicrosoft Sans Serif"}, {"PMicrosoft Sans Serif"}, {" Courier New"}, {"BCourier New"}, {"ICourier New"}, {"PCourier New"}, {" Times New Roman"}, {"BTimes New Roman"}, {"ITimes New Roman"}, {"PTimes New Roman"}, {" Symbol"}, {" Terminal"}, {"BTerminal"}, {" Wingdings"}, }; Fl_Fontdesc* fl_fonts = built_in_table; static Fl_GDI_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size, int angle) { Fl_Fontdesc* s = fl_fonts+fnum; if (!s->name) s = fl_fonts; // use 0 if fnum undefined Fl_GDI_Font_Descriptor* f; for (f = (Fl_GDI_Font_Descriptor*)s->first; f; f = (Fl_GDI_Font_Descriptor*)f->next) if (f->size == size && f->angle == angle) return f; f = new Fl_GDI_Font_Descriptor(s->name, size); f->next = s->first; s->first = f; return f; } //////////////////////////////////////////////////////////////// // Public interface: static void fl_font(Fl_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle) { if (fnum==-1) { // just make sure that we will load a new font next time fl_angle_ = 0; driver->Fl_Graphics_Driver::font(0, 0); return; } if (fnum == driver->Fl_Graphics_Driver::font() && size == ((Fl_GDI_Graphics_Driver*)driver)->size_unscaled() && angle == fl_angle_) return; fl_angle_ = angle; driver->Fl_Graphics_Driver::font(fnum, size); driver->font_descriptor( find(fnum, size, angle) ); } void Fl_GDI_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) { fl_font(this, fnum, size, 0); } int Fl_GDI_Graphics_Driver::height_unscaled() { Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor(); if (fl_fontsize) return (fl_fontsize->metr.tmAscent + fl_fontsize->metr.tmDescent); else return -1; } int Fl_GDI_Graphics_Driver::descent_unscaled() { Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor(); if (fl_fontsize) return fl_fontsize->metr.tmDescent; else return -1; } Fl_Fontsize Fl_GDI_Graphics_Driver::size_unscaled() { if (font_descriptor()) return size_; return -1; } double Fl_GDI_Graphics_Driver::width_unscaled(const char* c, int n) { int i = 0; if (!font_descriptor()) return -1.0; double w = 0.0; char *end = (char *)&c[n]; while (i < n) { unsigned int ucs; int l; ucs = fl_utf8decode((const char*)(c + i), end, &l); // if (l < 1) l = 1; i += l; if (!fl_nonspacing(ucs)) { w += width_unscaled(ucs); } } return w; } double Fl_GDI_Graphics_Driver::width_unscaled(unsigned int c) { Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor(); unsigned int r; SIZE s; // Special Case Handling of Unicode points over U+FFFF. // The logic (below) computes a lookup table for char widths // on-the-fly, but the table only covers codepoints up to // U+FFFF, which covers the basic multilingual plane, but // not any higher plane, or glyphs that require surrogate-pairs // to encode them in WinXX, which is UTF16. // This code assumes that these glyphs are rarely used and simply // measures them explicitly if they occur - This will be slow... if(c > 0x0000FFFF) { // UTF16 surrogate pair is needed if (!gc_) { // We have no valid gc, so nothing to measure - bail out return 0.0; } int cc; // cell count unsigned short u16[4]; // Array for UTF16 representation of c // Creates a UTF16 string from a UCS code point. cc = fl_ucs_to_Utf16(c, u16, 4); // Make sure the current font is selected before we make the measurement SelectObject(gc_, fl_fontsize->fid); // measure the glyph width GetTextExtentPoint32W(gc_, (WCHAR*)u16, cc, &s); return (double)s.cx; } // else - this falls through to the lookup-table for glyph widths // in the basic multilingual plane r = (c & 0xFC00) >> 10; if (!fl_fontsize->width[r]) { fl_fontsize->width[r] = (int*) malloc(sizeof(int) * 0x0400); for (int i = 0; i < 0x0400; i++) fl_fontsize->width[r][i] = -1; } else { if ( fl_fontsize->width[r][c&0x03FF] >= 0 ) { // already cached return (double) fl_fontsize->width[r][c & 0x03FF]; } } unsigned short ii = r * 0x400; // The following code makes a best effort attempt to obtain a valid fl_gc. // If no fl_gc is available at the time we call fl_width(), then we first // try to obtain a gc from the first fltk window. // If that is null then we attempt to obtain the gc from the current screen // using (GetDC(NULL)). // This should resolve STR #2086 HDC gc2 = gc_; HWND hWnd = 0; if (!gc2) { // We have no valid gc, try and obtain one // Use our first fltk window, or fallback to using the screen via GetDC(NULL) hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL; gc2 = GetDC(hWnd); } if (!gc2) Fl::fatal("Invalid graphic context: fl_width() failed because no valid HDC was found!"); SelectObject(gc2, fl_fontsize->fid); ii += c &0x03FF; GetTextExtentPoint32W(gc2, (WCHAR*)&ii, 1, &s); fl_fontsize->width[r][c&0x03FF] = s.cx; if (gc2 && gc2 != gc_) ReleaseDC(hWnd, gc2); return (double) fl_fontsize->width[r][c & 0x03FF]; } /* Add function pointer to allow us to access GetGlyphIndicesW on systems that have it, * without crashing on systems that do not. */ /* DWORD WINAPI GetGlyphIndicesW(HDC,LPCWSTR,int,LPWORD,DWORD) */ typedef DWORD (WINAPI* fl_GetGlyphIndices_func)(HDC,LPCWSTR,int,LPWORD,DWORD); static fl_GetGlyphIndices_func fl_GetGlyphIndices = NULL; // used to hold a proc pointer for GetGlyphIndicesW static int have_loaded_GetGlyphIndices = 0; // Set this non-zero once we have tried to load GetGlyphIndices // Function that tries to dynamically load GetGlyphIndicesW at runtime static void GetGlyphIndices_init() { // Since not all versions of Windows include GetGlyphIndicesW support, // we do a run-time check for the required function. HMODULE hMod = GetModuleHandle("GDI32.DLL"); if (hMod) { // check that GetGlyphIndicesW is available fl_GetGlyphIndices = (fl_GetGlyphIndices_func)GetProcAddress(hMod, "GetGlyphIndicesW"); } have_loaded_GetGlyphIndices = -1; // set this non-zero when we have attempted to load GetGlyphIndicesW } // GetGlyphIndices_init function static void on_printer_extents_update(int &dx, int &dy, int &w, int &h, HDC gc) // converts text extents from device coords to logical coords { POINT pt[3] = { {0, 0}, {dx, dy}, {dx+w, dy+h} }; DPtoLP(gc, pt, 3); w = pt[2].x - pt[1].x; h = pt[2].y - pt[1].y; dx = pt[1].x - pt[0].x; dy = pt[1].y - pt[0].y; } // if printer context, extents shd be converted to logical coords #define EXTENTS_UPDATE(x,y,w,h,gc) \ if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { \ on_printer_extents_update(x,y,w,h,gc); \ } // Function to determine the extent of the "inked" area of the glyphs in a string void Fl_GDI_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &w, int &h) { Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor(); if (!fl_fontsize) { // no valid font, nothing to measure w = 0; h = 0; dx = dy = 0; return; } static unsigned short *ext_buff = NULL; // UTF-16 converted version of input UTF-8 string static WORD *w_buff = NULL; // glyph indices array static unsigned wc_len = 0; // current string buffer dimensions static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; // identity mat for GetGlyphOutlineW GLYPHMETRICS metrics; int maxw = 0, maxh = 0, dh; int minx = 0, miny = -999999; unsigned len = 0, idx = 0; HWND hWnd = 0; HDC gc2 = gc_; // local copy of current gc - make a copy in case we change it... int has_surrogates; // will be set if the string contains surrogate pairs // Have we loaded the GetGlyphIndicesW function yet? if (have_loaded_GetGlyphIndices == 0) { GetGlyphIndices_init(); } // Do we have a usable GetGlyphIndices function? if(!fl_GetGlyphIndices) goto exit_error; // No GetGlyphIndices function, use fallback mechanism instead // The following code makes a best effort attempt to obtain a valid fl_gc. // See description in fl_width() above for an explanation. if (!gc2) { // We have no valid gc, try and obtain one // Use our first fltk window, or fallback to using the screen via GetDC(NULL) hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL; gc2 = GetDC(hWnd); } if (!gc2) goto exit_error; // no valid gc, attempt to use fallback measure // now convert the string to WCHAR and measure it len = fl_utf8toUtf16(c, n, ext_buff, wc_len); if(len >= wc_len) { if(ext_buff) {delete [] ext_buff;} if(w_buff) {delete [] w_buff;} wc_len = len + 64; ext_buff = new unsigned short[wc_len]; w_buff = new WORD[wc_len]; len = fl_utf8toUtf16(c, n, ext_buff, wc_len); } SelectObject(gc2, fl_fontsize->fid); // Are there surrogate-pairs in this string? If so GetGlyphIndicesW will fail // since it can only handle the BMP range. // We ideally want to use GetGlyphIndicesW, as it is the Right Thing, but it // only works for the BMP, so we leverage GetCharacterPlacementW instead, which // is not ideal, but works adequately well, and does handle surrogate pairs. has_surrogates = 0; for(unsigned ll = 0; ll < len; ll++) { if((ext_buff[ll] >= 0xD800) && (ext_buff[ll] < 0xE000)) { has_surrogates = -1; break; } } if (has_surrogates) { // GetGlyphIndices will not work - use GetCharacterPlacementW() instead GCP_RESULTSW gcp_res; memset(w_buff, 0, (sizeof(WORD) * wc_len)); memset(&gcp_res, 0, sizeof(GCP_RESULTSW)); gcp_res.lpGlyphs = (LPWSTR)w_buff; gcp_res.nGlyphs = wc_len; gcp_res.lStructSize = sizeof(gcp_res); DWORD dr = GetCharacterPlacementW(gc2, (WCHAR*)ext_buff, len, 0, &gcp_res, GCP_GLYPHSHAPE); if(dr) { len = gcp_res.nGlyphs; } else goto exit_error; } else { if (fl_GetGlyphIndices(gc_, (WCHAR*)ext_buff, len, w_buff, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR) { // some error occurred here - just return fl_measure values goto exit_error; } } // now we have the glyph array we measure each glyph in turn... for(idx = 0; idx < len; idx++){ if (GetGlyphOutlineW (gc2, w_buff[idx], GGO_METRICS | GGO_GLYPH_INDEX, &metrics, 0, NULL, &matrix) == GDI_ERROR) { goto exit_error; } maxw += metrics.gmCellIncX; if(idx == 0) minx = metrics.gmptGlyphOrigin.x; dh = metrics.gmBlackBoxY - metrics.gmptGlyphOrigin.y; if(dh > maxh) maxh = dh; if(miny < metrics.gmptGlyphOrigin.y) miny = metrics.gmptGlyphOrigin.y; } // for the last cell, we only want the bounding X-extent, not the glyphs increment step maxw = maxw - metrics.gmCellIncX + metrics.gmBlackBoxX + metrics.gmptGlyphOrigin.x; w = maxw - minx; h = maxh + miny; dx = minx; dy = -miny; EXTENTS_UPDATE(dx, dy, w, h, gc_); return; // normal exit exit_error: // some error here - just return fl_measure values w = (int)width(c, n); h = height_unscaled(); dx = 0; dy = descent_unscaled() - h; EXTENTS_UPDATE(dx, dy, w, h, gc_); return; } // fl_text_extents void Fl_GDI_Graphics_Driver::draw_unscaled(const char* str, int n, int x, int y) { COLORREF oldColor = SetTextColor(gc_, fl_RGB()); // avoid crash if no font has been set yet if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE); SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid); int wn = fl_utf8toUtf16(str, n, wstr, wstr_len); if(wn >= wstr_len) { wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1)); wstr_len = wn + 1; wn = fl_utf8toUtf16(str, n, wstr, wstr_len); } TextOutW(gc_, x, y, (WCHAR*)wstr, wn); SetTextColor(gc_, oldColor); // restore initial state } void Fl_GDI_Graphics_Driver::draw_unscaled(int angle, const char* str, int n, int x, int y) { fl_font(this, Fl_Graphics_Driver::font(), size_unscaled(), angle); int wn = 0; // count of UTF16 cells to render full string COLORREF oldColor = SetTextColor(gc_, fl_RGB()); SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid); wn = fl_utf8toUtf16(str, n, wstr, wstr_len); if(wn >= wstr_len) { // Array too small wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1)); wstr_len = wn + 1; wn = fl_utf8toUtf16(str, n, wstr, wstr_len); // respin the translation } TextOutW(gc_, x, y, (WCHAR*)wstr, wn); SetTextColor(gc_, oldColor); fl_font(this, Fl_Graphics_Driver::font(), size_unscaled(), 0); } void Fl_GDI_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int y) { int wn; wn = fl_utf8toUtf16(c, n, wstr, wstr_len); if(wn >= wstr_len) { wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1)); wstr_len = wn + 1; wn = fl_utf8toUtf16(c, n, wstr, wstr_len); } COLORREF oldColor = SetTextColor(gc_, fl_RGB()); SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid); #ifdef RTL_CHAR_BY_CHAR int i = 0; int lx = 0; while (i < wn) { // output char by char is very bad for Arabic but coherent with fl_width() lx = (int) width(wstr[i]); x -= lx; TextOutW(gc_, x, y, (WCHAR*)wstr + i, 1); if (fl_nonspacing(wstr[i])) { x += lx; } i++; } #else UINT old_align = SetTextAlign(gc_, TA_RIGHT | TA_RTLREADING); TextOutW(gc_, x, y - height_unscaled() + descent_unscaled(), (WCHAR*)wstr, wn); SetTextAlign(gc_, old_align); #endif SetTextColor(gc_, oldColor); } #endif fltk-1.4.3/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx0000644000175000017500000001460715004135251023765 0ustar albrechtalbrecht// // Portable drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_GDI_Graphics_Driver_vertex.cxx \brief Portable drawing code for drawing arbitrary shapes with simple 2D transformations, implemented for Windows GDI. */ #include "Fl_GDI_Graphics_Driver.H" #include #include #include void Fl_GDI_Graphics_Driver::end_points() { for (int i=0; i1) Polyline(gc_, long_point, n); } void Fl_GDI_Graphics_Driver::end_loop() { fixloop(); if (n>2) transformed_vertex0(float(long_point[0].x), float(long_point[0].y)); end_line(); } void Fl_GDI_Graphics_Driver::end_polygon() { fixloop(); if (n < 3) { end_line(); return; } if (n>2) { SelectObject(gc_, fl_brush()); Polygon(gc_, long_point, n); } } void Fl_GDI_Graphics_Driver::begin_complex_polygon() { Fl_Graphics_Driver::begin_complex_polygon(); numcount = 0; } void Fl_GDI_Graphics_Driver::gap() { while (n>gap_+2 && long_point[n-1].x == long_point[gap_].x && long_point[n-1].y == long_point[gap_].y) n--; if (n > gap_+2) { transformed_vertex0(float(long_point[gap_].x), float(long_point[gap_].y)); counts[numcount++] = n-gap_; gap_ = n; } else { n = gap_; } } void Fl_GDI_Graphics_Driver::end_complex_polygon() { gap(); if (n < 3) { end_line(); return; } if (n>2) { SelectObject(gc_, fl_brush()); PolyPolygon(gc_, long_point, counts, numcount); } } void Fl_GDI_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) { int llx = (int)rint(xt-rx); int w = (int)rint(xt+rx)-llx; int lly = (int)rint(yt-ry); int h = (int)rint(yt+ry)-lly; if (what==POLYGON) { SelectObject(gc_, fl_brush()); Pie(gc_, llx, lly, llx+w, lly+h, 0,0, 0,0); } else Arc(gc_, llx, lly, llx+w, lly+h, 0,0, 0,0); } #if USE_GDIPLUS void Fl_GDIplus_Graphics_Driver::transformed_vertex(double xf, double yf) { if (!active) return Fl_Scalable_Graphics_Driver::transformed_vertex(xf, yf); transformed_vertex0(float(xf) , float(yf) ); } void Fl_GDIplus_Graphics_Driver::vertex(double x,double y) { if (!active) return Fl_Scalable_Graphics_Driver::vertex(x, y); transformed_vertex0(float(x*m.a + y*m.c + m.x) , float(x*m.b + y*m.d + m.y) ); } void Fl_GDIplus_Graphics_Driver::end_points() { if (!active) return Fl_GDI_Graphics_Driver::end_points(); for (int i = 0; i < n; i++) point(long_point[i].x, long_point[i].y); } void Fl_GDIplus_Graphics_Driver::end_line() { if (!active) return Fl_GDI_Graphics_Driver::end_line(); if (n < 2) { end_points(); return; } if (n>1) { Gdiplus::GraphicsPath path; Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; for (int i = 0; i < n; i++) { gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y); } path.AddLines(gdi2_p, n); delete[] gdi2_p; Gdiplus::Graphics graphics_(gc_); graphics_.ScaleTransform(scale(), scale()); graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); pen_->SetColor(gdiplus_color_); graphics_.DrawPath(pen_, &path); } } void Fl_GDIplus_Graphics_Driver::end_loop() { if (!active) return Fl_GDI_Graphics_Driver::end_loop(); fixloop(); if (n >= 2) { Gdiplus::GraphicsPath path; Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; for (int i = 0; i < n; i++) { gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y); } path.AddLines(gdi2_p, n); path.CloseFigure(); delete[] gdi2_p; Gdiplus::Graphics graphics_(gc_); graphics_.ScaleTransform(scale(), scale()); graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); pen_->SetColor(gdiplus_color_); graphics_.DrawPath(pen_, &path); } } void Fl_GDIplus_Graphics_Driver::end_polygon() { if (!active) return Fl_GDI_Graphics_Driver::end_polygon(); fixloop(); if (n < 3) { end_line(); return; } if (n>2) { Gdiplus::GraphicsPath path; Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; for (int i = 0; i < n; i++) { gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y); } path.AddPolygon(gdi2_p, n); delete[] gdi2_p; path.CloseFigure(); Gdiplus::Graphics graphics_(gc_); graphics_.ScaleTransform(scale(), scale()); graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); brush_->SetColor(gdiplus_color_); graphics_.FillPath(brush_, &path); } } void Fl_GDIplus_Graphics_Driver::end_complex_polygon() { if (!active) return Fl_GDI_Graphics_Driver::end_complex_polygon(); gap(); if (n < 3) { end_line(); return; } if (n>2) { Gdiplus::GraphicsPath path; Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; for (int i = 0; i < n; i++) { gdi2_p[i] = Gdiplus::Point(long_point[i].x, long_point[i].y); } path.AddPolygon(gdi2_p, n); delete[] gdi2_p; path.CloseFigure(); Gdiplus::Graphics graphics_(gc_); graphics_.ScaleTransform(scale(), scale()); graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); brush_->SetColor(gdiplus_color_); graphics_.FillPath(brush_, &path); } } void Fl_GDIplus_Graphics_Driver::circle(double x, double y, double r) { if (!active) return Fl_Scalable_Graphics_Driver::circle(x, y, r); double xt = transform_x(x,y); double yt = transform_y(x,y); double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a)); double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d)); int llx = (int)rint(xt-rx); int w = (int)rint(xt+rx)-llx; int lly = (int)rint(yt-ry); int h = (int)rint(yt+ry)-lly; Gdiplus::Graphics graphics_(gc_); graphics_.ScaleTransform(scale(), scale()); graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); if (what==POLYGON) { brush_->SetColor(gdiplus_color_); graphics_.FillPie(brush_, llx, lly, w, h, 0, 360); } else { pen_->SetColor(gdiplus_color_); graphics_.DrawArc(pen_, llx, lly, w, h, 0, 360); } } #endif fltk-1.4.3/src/drivers/GDI/Fl_Font.H0000644000175000017500000000203615004135251017116 0ustar albrechtalbrecht// // Font definitions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Two internal fltk data structures: // // Fl_Fontdesc: an entry into the fl_font() table. There is one of these // for each fltk font number. // #ifndef FL_FONT_ #define FL_FONT_ #include class Fl_GDI_Font_Descriptor : public Fl_Font_Descriptor { public: HFONT fid; int *width[64]; TEXTMETRIC metr; int angle; FL_EXPORT Fl_GDI_Font_Descriptor(const char* fontname, Fl_Fontsize size); # if HAVE_GL char glok[64]; # endif // HAVE_GL virtual FL_EXPORT ~Fl_GDI_Font_Descriptor(); }; extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table #endif fltk-1.4.3/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx0000644000175000017500000001735115004135251023565 0ustar albrechtalbrecht// // MSWidnows' GDI color functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // The fltk "colormap". This allows ui colors to be stored in 8-bit // locations, and provides a level of indirection so that global color // changes can be made. Not to be confused with the X colormap, which // I try to hide completely. #include "Fl_GDI_Graphics_Driver.H" #include #include #include #include // FIXME: all the global functions in this file should probably be protected // members of the driver class. Starting with 1.4 we will allow multiple drivers // to co-exist, creating conflicts with multipe mapping. // FIXME: maybe we can forget about color mapping and assume RGB? // FIXME: ... but for now we still have it ... extern unsigned fl_cmap[256]; // defined in fl_color.cxx // Translations to win32 data structures: Fl_XMap fl_xmap[256]; Fl_XMap* fl_current_xmap; HPALETTE fl_palette; static HGDIOBJ tmppen=0; static HPEN savepen=0; void fl_cleanup_pens(void) { for (int i=0; i<256; i++) { if (fl_xmap[i].pen) DeleteObject(fl_xmap[i].pen); } } void fl_save_pen(void) { if(!tmppen) tmppen = CreatePen(PS_SOLID, 1, 0); savepen = (HPEN)SelectObject((HDC)fl_graphics_driver->gc(), tmppen); } void fl_restore_pen(void) { if (savepen) SelectObject((HDC)fl_graphics_driver->gc(), savepen); DeleteObject(tmppen); tmppen = 0; savepen = 0; } static void clear_xmap(Fl_XMap& xmap) { if (xmap.pen) { HDC gc = (HDC)fl_graphics_driver->gc(); HGDIOBJ tmppen = GetStockObject(BLACK_PEN); HGDIOBJ oldpen = SelectObject(gc, tmppen); // Push out the current pen of the gc if(oldpen != xmap.pen) SelectObject(gc, oldpen); // Put it back if it is not the one we are about to delete DeleteObject((HGDIOBJ)(xmap.pen)); xmap.pen = 0; xmap.brush = -1; } } static void set_xmap(Fl_XMap& xmap, COLORREF c, int lw) { xmap.rgb = c; if (xmap.pen) { HDC gc = (HDC)fl_graphics_driver->gc(); HGDIOBJ oldpen = SelectObject(gc,GetStockObject(BLACK_PEN)); // replace current pen with safe one if (oldpen != xmap.pen)SelectObject(gc,oldpen); // if old one not xmap.pen, need to put it back DeleteObject(xmap.pen); // delete pen } // xmap.pen = CreatePen(PS_SOLID, 1, xmap.rgb); // get a pen into xmap.pen LOGBRUSH penbrush = {BS_SOLID, xmap.rgb, 0}; xmap.pen = ExtCreatePen(PS_GEOMETRIC | PS_ENDCAP_FLAT | PS_JOIN_ROUND, lw, &penbrush, 0, 0); xmap.pwidth = lw; xmap.brush = -1; } void Fl_GDI_Graphics_Driver::color(Fl_Color i) { if (i & 0xffffff00) { unsigned rgb = (unsigned)i; color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8)); } else { Fl_Graphics_Driver::color(i); Fl_XMap &xmap = fl_xmap[i]; int tw = line_width_ ? line_width_ : int(scale()); if (!tw) tw = 1; if (!xmap.pen || xmap.pwidth != tw) { #if USE_COLORMAP if (fl_palette) { set_xmap(xmap, PALETTEINDEX(i), tw); } else { #endif unsigned c = fl_cmap[i]; set_xmap(xmap, RGB(uchar(c>>24), uchar(c>>16), uchar(c>>8)), tw); #if USE_COLORMAP } #endif } fl_current_xmap = ⟼ SelectObject(gc_, (HGDIOBJ)(xmap.pen)); } } void Fl_GDI_Graphics_Driver::color(uchar r, uchar g, uchar b) { static Fl_XMap xmap; COLORREF c = RGB(r,g,b); Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) ); int tw = line_width_ ? line_width_ : int(scale()); if (!tw) tw = 1; if (!xmap.pen || c != xmap.rgb || tw != xmap.pwidth) { clear_xmap(xmap); set_xmap(xmap, c, tw); } fl_current_xmap = ⟼ SelectObject(gc_, (HGDIOBJ)(xmap.pen)); } HBRUSH fl_brush() { return fl_brush_action(0); } HBRUSH fl_brush_action(int action) { Fl_XMap *xmap = fl_current_xmap; HDC gc = (HDC)fl_graphics_driver->gc(); // Wonko: we use some statistics to cache only a limited number // of brushes: #define FL_N_BRUSH 16 static struct Fl_Brush { HBRUSH brush; unsigned short usage; Fl_XMap* backref; } brushes[FL_N_BRUSH]; if (action) { SelectObject(gc, GetStockObject(BLACK_BRUSH)); // Load stock object for (int i=0; ibrush; // find the associated brush if (i != -1) { // if the brush was allready allocated if (brushes[i].brush == NULL) goto CREATE_BRUSH; if ( (++brushes[i].usage) > 32000 ) { // keep a usage statistic for (int j=0; j16000) brushes[j].usage -= 16000; else brushes[j].usage = 0; } } return brushes[i].brush; } else { int umin = 32000, imin = 0; for (i=0; ibrush = -1; } CREATE_BRUSH: brushes[i].brush = CreateSolidBrush(xmap->rgb); brushes[i].usage = 0; brushes[i].backref = xmap; xmap->brush = i; return brushes[i].brush; } void Fl_GDI_Graphics_Driver::free_color(Fl_Color i, int overlay) { if (overlay) return; // do something about GL overlay? clear_xmap(fl_xmap[i]); } void Fl_GDI_Graphics_Driver::set_color(Fl_Color i, unsigned c) { if (fl_cmap[i] != c) { clear_xmap(fl_xmap[i]); fl_cmap[i] = c; } } #if USE_COLORMAP // 'fl_select_palette()' - Make a color palette for 8-bit displays if necessary // Thanks to Michael Sweet @ Easy Software Products for this HPALETTE fl_select_palette(void) { static char beenhere; HDC gc = (HDC)fl_graphics_driver->gc(); if (!beenhere) { beenhere = 1; int nColors = GetDeviceCaps(gc, SIZEPALETTE); if (nColors <= 0 || nColors > 256) return NULL; // this will try to work on < 256 color screens, but will probably // come out quite badly. // I lamely try to get this variable-sized object allocated on stack: ulong foo[(sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY))/sizeof(ulong)+1]; LOGPALETTE *pPal = (LOGPALETTE*)foo; pPal->palVersion = 0x300; pPal->palNumEntries = nColors; // Build 256 colors from the standard FLTK colormap... for (int i = 0; i < nColors; i ++) { pPal->palPalEntry[i].peRed = (fl_cmap[i] >> 24) & 255; pPal->palPalEntry[i].peGreen = (fl_cmap[i] >> 16) & 255; pPal->palPalEntry[i].peBlue = (fl_cmap[i] >> 8) & 255; pPal->palPalEntry[i].peFlags = 0; }; // Create the palette: fl_palette = CreatePalette(pPal); } if (fl_palette) { SelectPalette(gc, fl_palette, FALSE); RealizePalette(gc); } return fl_palette; } #endif #if USE_GDIPLUS void Fl_GDIplus_Graphics_Driver::color(uchar r, uchar g, uchar b) { Fl_GDI_Graphics_Driver::color(r, g, b); gdiplus_color_.SetFromCOLORREF(fl_RGB()); } void Fl_GDIplus_Graphics_Driver::color(Fl_Color i) { Fl_GDI_Graphics_Driver::color(i); gdiplus_color_.SetFromCOLORREF(fl_RGB()); } #endif // USE_GDIPLUS fltk-1.4.3/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx0000644000175000017500000000637615004135251023216 0ustar albrechtalbrecht// // Copy-to-clipboard code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_GDI_Copy_Surface_Driver.H" #include #include "Fl_GDI_Graphics_Driver.H" #include "../WinAPI/Fl_WinAPI_Screen_Driver.H" #include #include Fl_GDI_Copy_Surface_Driver::Fl_GDI_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) { driver(Fl_Graphics_Driver::newMainGraphicsDriver()); oldgc = (HDC)Fl_Surface_Device::surface()->driver()->gc(); // exact computation of factor from screen units to EnhMetaFile units (0.01 mm) HDC hdc = GetDC(NULL); int hmm = GetDeviceCaps(hdc, HORZSIZE); int hdots = GetDeviceCaps(hdc, HORZRES); int vmm = GetDeviceCaps(hdc, VERTSIZE); int vdots = GetDeviceCaps(hdc, VERTRES); ReleaseDC(NULL, hdc); float factorw = (100.f * hmm) / hdots; float factorh = (100.f * vmm) / vdots; // Global display scaling factor: 1, 1.25, 1.5, 1.75, etc... float scaling = Fl_Graphics_Driver::default_driver().scale(); driver()->scale(scaling); RECT rect; rect.left = 0; rect.top = 0; rect.right = (LONG)((w*scaling) * factorw); rect.bottom = (LONG)((h*scaling) * factorh); gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL); if (gc != NULL) { SetTextAlign(gc, TA_BASELINE|TA_LEFT); SetBkMode(gc, TRANSPARENT); } } Fl_GDI_Copy_Surface_Driver::~Fl_GDI_Copy_Surface_Driver() { if (oldgc == (HDC)Fl_Surface_Device::surface()->driver()->gc()) oldgc = NULL; HENHMETAFILE hmf = CloseEnhMetaFile (gc); if ( hmf != NULL ) { if ( OpenClipboard (NULL) ){ EmptyClipboard (); // put first the vectorial form of the graphics in the clipboard SetClipboardData (CF_ENHMETAFILE, hmf); // then put a BITMAP version of the graphics in the clipboard float scaling = driver()->scale(); int W = Fl_Scalable_Graphics_Driver::floor(width, scaling), H = Fl_Scalable_Graphics_Driver::floor(height, scaling); RECT rect = {0, 0, W, H}; Fl_Image_Surface *surf = new Fl_Image_Surface(W, H); Fl_Surface_Device::push_current(surf); fl_color(FL_WHITE); // draw white background fl_rectf(0, 0, W, H); PlayEnhMetaFile((HDC)surf->driver()->gc(), hmf, &rect); // draw metafile to offscreen buffer SetClipboardData(CF_BITMAP, (HBITMAP)surf->offscreen()); Fl_Surface_Device::pop_current(); delete surf; CloseClipboard (); } DeleteEnhMetaFile(hmf); } DeleteDC(gc); Fl_Surface_Device::surface()->driver()->gc(oldgc); delete driver(); } void Fl_GDI_Copy_Surface_Driver::set_current() { driver()->gc(gc); fl_window = (HWND)1; Fl_Surface_Device::set_current(); } void Fl_GDI_Copy_Surface_Driver::translate(int x, int y) { ((Fl_GDI_Graphics_Driver*)driver())->translate_all(x, y); } void Fl_GDI_Copy_Surface_Driver::untranslate() { ((Fl_GDI_Graphics_Driver*)driver())->untranslate_all(); } fltk-1.4.3/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx0000644000175000017500000000740215004135251024612 0ustar albrechtalbrecht// // Line style code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_GDI_Graphics_Driver_line_style.cxx \brief Line style drawing utility for Windows (GDI) platform. */ #include #include #include #include "Fl_GDI_Graphics_Driver.H" void Fl_GDI_Graphics_Driver::line_style_unscaled(int style, int width, char* dashes) { // According to Bill, the "default" cap and join should be the // "fastest" mode supported for the platform. I don't know why // they should be different (same graphics cards, etc., right?) MRS static const DWORD Cap[4] = {PS_ENDCAP_FLAT, PS_ENDCAP_FLAT, PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE}; static const DWORD Join[4] = {PS_JOIN_ROUND, PS_JOIN_MITER, PS_JOIN_ROUND, PS_JOIN_BEVEL}; int s1 = PS_GEOMETRIC | Cap[(style>>8)&3] | Join[(style>>12)&3]; DWORD a[16]; int n = 0; if (dashes && dashes[0]) { s1 |= PS_USERSTYLE; for (n = 0; n < 16 && *dashes; n++) a[n] = *dashes++; } else { s1 |= style & 0xff; // allow them to pass any low 8 bits for style } if ((style || n) && !width) width = int(scale()); // fix cards that do nothing for 0? if (!width) width = 1; if (!fl_current_xmap) color(FL_BLACK); LOGBRUSH penbrush = {BS_SOLID,fl_RGB(),0}; // can this be fl_brush()? HPEN newpen = ExtCreatePen(s1, width, &penbrush, n, n ? a : 0); if (!newpen) { Fl::error("fl_line_style(): Could not create GDI pen object."); return; } HPEN oldpen = (HPEN)SelectObject(gc_, newpen); DeleteObject(oldpen); DeleteObject(fl_current_xmap->pen); fl_current_xmap->pen = newpen; #if FL_ABI_VERSION >= 10403 // Issue #1214 // empty #else is_solid_ = ((style & 0xff) == FL_SOLID && (!dashes || !*dashes)); #endif style_ = style; } #if USE_GDIPLUS void Fl_GDIplus_Graphics_Driver::line_style(int style, int width, char* dashes) { if (!active) return Fl_Scalable_Graphics_Driver::line_style(style, width, dashes); int gdi_width = (width ? width : 1); pen_->SetWidth(Gdiplus::REAL(gdi_width)); int standard_dash = style & 0x7; if (standard_dash == FL_DASH ) pen_->SetDashStyle(Gdiplus::DashStyleDash); else if (standard_dash == FL_DOT ) pen_->SetDashStyle(Gdiplus::DashStyleDot); else if (standard_dash == FL_DASHDOT ) pen_->SetDashStyle(Gdiplus::DashStyleDashDot); else if (standard_dash == FL_DASHDOTDOT ) pen_->SetDashStyle(Gdiplus::DashStyleDashDotDot); else if(!dashes || !*dashes) pen_->SetDashStyle(Gdiplus::DashStyleSolid); if (style & FL_CAP_ROUND ) { pen_->SetStartCap(Gdiplus::LineCapRound); pen_->SetEndCap(Gdiplus::LineCapRound); } else if (style & FL_CAP_SQUARE ) { pen_->SetStartCap(Gdiplus::LineCapSquare); pen_->SetEndCap(Gdiplus::LineCapSquare); } else { pen_->SetStartCap(Gdiplus::LineCapFlat); pen_->SetEndCap(Gdiplus::LineCapFlat); } if (style & FL_JOIN_MITER ) { pen_->SetLineJoin(Gdiplus::LineJoinMiter); } else if (style & FL_JOIN_BEVEL ) { pen_->SetLineJoin(Gdiplus::LineJoinBevel); } else { pen_->SetLineJoin(Gdiplus::LineJoinRound); } if (dashes && *dashes) { int n = 0; while (dashes[n]) n++; Gdiplus::REAL *gdi_dashes = new Gdiplus::REAL[n]; for (int i = 0; i < n; i++) gdi_dashes[i] = dashes[i]/float(gdi_width); pen_->SetDashPattern(gdi_dashes, n); delete[] gdi_dashes; } Fl_Scalable_Graphics_Driver::line_style(style, width, dashes); } #endif fltk-1.4.3/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.H0000644000175000017500000000173315004135251022573 0ustar albrechtalbrecht// // Copy-to-clipboard code for the Fast Light Tool Kit (FLTK). // // Copyright 2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_GDI_COPY_SURFACE_DRIVER_H #define FL_GDI_COPY_SURFACE_DRIVER_H #include #include class Fl_GDI_Copy_Surface_Driver : public Fl_Copy_Surface_Driver { friend class Fl_Copy_Surface_Driver; protected: HDC oldgc; HDC gc; Fl_GDI_Copy_Surface_Driver(int w, int h); ~Fl_GDI_Copy_Surface_Driver(); void set_current() FL_OVERRIDE; void translate(int x, int y) FL_OVERRIDE; void untranslate() FL_OVERRIDE; }; #endif // FL_GDI_COPY_SURFACE_DRIVER_H fltk-1.4.3/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx0000644000175000017500000002575615004135251023414 0ustar albrechtalbrecht// // Rectangle drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_GDI_Graphics_Driver_rect.cxx \brief Windows GDI specific line and polygon drawing with integer coordinates. */ #include #include #include #include #include #include "Fl_GDI_Graphics_Driver.H" // --- line and polygon drawing with integer coordinates void Fl_GDI_Graphics_Driver::point(int x, int y) { rectf(x, y, 1, 1); } void Fl_GDI_Graphics_Driver::overlay_rect(int x, int y, int w , int h) { // make pen have a one-pixel width line_style_unscaled( (color()==FL_WHITE?FL_SOLID:FL_DOT), 1, NULL); int right = this->floor(x+w-1), bottom = this->floor(y+h-1); x = this->floor(x); y = this->floor(y); MoveToEx(gc_, x, y, 0L); LineTo(gc_, right, y); LineTo(gc_, right, bottom); LineTo(gc_, x, bottom); LineTo(gc_, x, y); } void Fl_GDI_Graphics_Driver::focus_rect(int x, int y, int w, int h) { // Windows 95/98/ME do not implement the dotted line style, so draw // every other pixel around the focus area... w = floor(x+w-1) - floor(x) + 1; h = floor(y+h-1) - floor(y) + 1; x = floor(x); y = floor(y); int i=1, xx, yy; COLORREF c = fl_RGB(); for (xx = 0; xx < w; xx++, i++) if (i & 1) SetPixel(gc_, x+xx, y, c); for (yy = 0; yy < h; yy++, i++) if (i & 1) SetPixel(gc_, x+w, y+yy, c); for (xx = w; xx > 0; xx--, i++) if (i & 1) SetPixel(gc_, x+xx, y+h, c); for (yy = h; yy > 0; yy--, i++) if (i & 1) SetPixel(gc_, x, y+yy, c); } void Fl_GDI_Graphics_Driver::rect_unscaled(int x, int y, int w, int h) { if (is_solid_ && line_width_ > 1) { line_style_unscaled(FL_CAP_SQUARE, line_width_, 0); // see issue #1052 } MoveToEx(gc_, x, y, 0L); LineTo(gc_, x+w, y); if (is_solid_ && line_width_ <= 1) LineTo(gc_, x+w, y+h+1); // see issue #1052 LineTo(gc_, x+w, y+h); LineTo(gc_, x, y+h); LineTo(gc_, x, y); if (is_solid_ && line_width_ > 1) { line_style_unscaled(style_, line_width_, 0); } } void Fl_GDI_Graphics_Driver::rectf_unscaled(int x, int y, int w, int h) { RECT rect; rect.left = x; rect.top = y; rect.right = (x + w); rect.bottom = (y + h); FillRect(gc_, &rect, fl_brush()); } void Fl_GDI_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1) { MoveToEx(gc_, x, y, 0L); LineTo(gc_, x1, y1); SetPixel(gc_, x1, y1, fl_RGB()); } void Fl_GDI_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1, int x2, int y2) { MoveToEx(gc_, x, y, 0L); LineTo(gc_, x1, y1); LineTo(gc_, x2, y2); SetPixel(gc_, x2, y2, fl_RGB()); } void* Fl_GDI_Graphics_Driver::change_pen_width(int width) { // set the width of the pen, return previous pen LOGBRUSH penbrush = {BS_SOLID, fl_RGB(), 0}; HPEN newpen = ExtCreatePen(PS_GEOMETRIC | PS_ENDCAP_FLAT | PS_JOIN_ROUND, width, &penbrush, 0, 0); return SelectObject(gc_, newpen); } void Fl_GDI_Graphics_Driver::reset_pen_width(void *data) { DeleteObject(SelectObject(gc_, (HPEN)data)); } void Fl_GDI_Graphics_Driver::xyline_unscaled(int x, int y, int x1) { MoveToEx(gc_, x, y, 0L); LineTo(gc_, x1+1 , y); } void Fl_GDI_Graphics_Driver::yxline_unscaled(int x, int y, int y1) { MoveToEx(gc_, x, y, 0L); LineTo(gc_, x, y1+1); } void Fl_GDI_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2) { MoveToEx(gc_, x, y, 0L); LineTo(gc_, x1, y1); LineTo(gc_, x2, y2); LineTo(gc_, x, y); } void Fl_GDI_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { MoveToEx(gc_, x, y, 0L); LineTo(gc_, x1, y1); LineTo(gc_, x2, y2); LineTo(gc_, x3, y3); LineTo(gc_, x, y); } void Fl_GDI_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2) { POINT p[3]; p[0].x = x; p[0].y = y; p[1].x = x1; p[1].y = y1; p[2].x = x2; p[2].y = y2; SelectObject(gc_, fl_brush()); Polygon(gc_, p, 3); } void Fl_GDI_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { POINT p[4]; p[0].x = x; p[0].y = y; p[1].x = x1; p[1].y = y1; p[2].x = x2; p[2].y = y2; p[3].x = x3; p[3].y = y3; SelectObject(gc_, fl_brush()); Polygon(gc_, p, 4); } // --- clipping void Fl_GDI_Graphics_Driver::push_clip(int x, int y, int w, int h) { HRGN r; if (w > 0 && h > 0) { r = (HRGN)XRectangleRegion(x,y,w,h); HRGN current = (HRGN)rstack[rstackptr]; if (current) { CombineRgn(r,r,current,RGN_AND); } } else { // make empty clip region: r = CreateRectRgn(0,0,0,0); } if (rstackptr < region_stack_max) rstack[++rstackptr] = r; else Fl::warning("Fl_GDI_Graphics_Driver::push_clip: clip stack overflow!\n"); fl_restore_clip(); } int Fl_GDI_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){ X = x; Y = y; W = w; H = h; HRGN r = (HRGN)rstack[rstackptr]; if (!r) return 0; // The win32 API makes no distinction between partial and complete // intersection, so we have to check for partial intersection ourselves. // However, given that the regions may be composite, we have to do // some voodoo stuff... HRGN rr = (HRGN)XRectangleRegion(x,y,w,h); HRGN temp = CreateRectRgn(0,0,0,0); int ret; if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { // disjoint W = H = 0; ret = 2; } else if (EqualRgn(temp, rr)) { // complete ret = 0; } else { // partial intersection RECT rect; GetRgnBox(temp, &rect); if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // if print context, convert coords from device to logical POINT pt[2] = { {rect.left, rect.top}, {rect.right, rect.bottom} }; DPtoLP(gc_, pt, 2); X = pt[0].x; Y = pt[0].y; W = pt[1].x - X; H = pt[1].y - Y; } else { X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y; } ret = 1; } DeleteObject(temp); DeleteObject(rr); return ret; } int Fl_GDI_Graphics_Driver::not_clipped(int x, int y, int w, int h) { if (x+w <= 0 || y+h <= 0) return 0; HRGN r = (HRGN)rstack[rstackptr]; if (!r) return 1; RECT rect; if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // in case of print context, convert coords from logical to device POINT pt[2] = { {x, y}, {x + w, y + h} }; LPtoDP(gc_, pt, 2); rect.left = pt[0].x; rect.top = pt[0].y; rect.right = pt[1].x; rect.bottom = pt[1].y; } else { rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h; } return RectInRegion(r,&rect); } void Fl_GDI_Graphics_Driver::restore_clip() { fl_clip_state_number++; if (gc_) { HRGN r = NULL; if (rstack[rstackptr]) r = (HRGN)scale_clip(scale()); SelectClipRgn(gc_, (HRGN)rstack[rstackptr]); // if region is NULL, clip is automatically cleared if (r) unscale_clip(r); } } #if USE_GDIPLUS void Fl_GDIplus_Graphics_Driver::line(int x, int y, int x1, int y1) { if (!active) return Fl_Scalable_Graphics_Driver::line(x, y, x1, y1); bool AA = !(x == x1 || y == y1); Gdiplus::Graphics graphics_(gc_); graphics_.ScaleTransform(scale(), scale()); pen_->SetColor(gdiplus_color_); if (AA) graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); graphics_.DrawLine(pen_, x, y, x1, y1); } void Fl_GDIplus_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { if (!active) return Fl_Scalable_Graphics_Driver::line(x, y, x1, y1, x2, y2); line(x, y, x1, y1); line(x1, y1, x2, y2); } void Fl_GDIplus_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { if (!active) return Fl_Scalable_Graphics_Driver::loop(x0, y0, x1, y1, x2, y2); Gdiplus::GraphicsPath path; Gdiplus::Point gdi2_p[3] = {Gdiplus::Point(x0, y0), Gdiplus::Point(x1, y1), Gdiplus::Point(x2, y2)}; path.AddLines(gdi2_p, 3); path.CloseFigure(); Gdiplus::Graphics graphics_(gc_); graphics_.ScaleTransform(scale(), scale()); pen_->SetColor(gdiplus_color_); graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); graphics_.DrawPath(pen_, &path); } #define fl_min(a,b) (a < b ? a : b) #define fl_max(a,b) (a > b ? a : b) void Fl_GDIplus_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { if ( (x0 == x3 && x1 == x2 && y0 == y1 && y3 == y2) || (x0 == x1 && y1 == y2 && x2 == x3 && y3 == y0) ) { // rectangular loop int left = fl_min(x0, fl_min(x1, fl_min(x2, x3))); int right = fl_max(x0, fl_max(x1, fl_max(x2, x3))); int top = fl_min(y0, fl_min(y1, fl_min(y2, y3))); int bottom = fl_max(y0, fl_max(y1, fl_max(y2, y3))); rect(left, top, right-left+1, bottom-top+1); } else { if (!active) return Fl_Scalable_Graphics_Driver::loop(x0, y0, x1, y1, x2, y2, x3, y3); Gdiplus::GraphicsPath path; Gdiplus::PointF gdi2_p[4] = {Gdiplus::PointF(x0+1-line_width_/2.f, y0+1-line_width_/2.f), Gdiplus::PointF(x1+1-line_width_/2.f, y1+1-line_width_/2.f), Gdiplus::PointF(x2+1-line_width_/2.f, y2+1-line_width_/2.f), Gdiplus::PointF(x3+1-line_width_/2.f, y3+1-line_width_/2.f)}; path.AddLines(gdi2_p, 4); path.CloseFigure(); Gdiplus::Graphics graphics_(gc_); graphics_.ScaleTransform(scale(), scale()); pen_->SetColor(gdiplus_color_); graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); graphics_.DrawPath(pen_, &path); } } void Fl_GDIplus_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { if (!active) return Fl_Scalable_Graphics_Driver::polygon(x0, y0, x1, y1, x2, y2); Gdiplus::GraphicsPath path; path.AddLine(x0, y0, x1, y1); path.AddLine(x1, y1, x2, y2); path.CloseFigure(); Gdiplus::Graphics graphics_(gc_); graphics_.ScaleTransform(scale(), scale()); brush_->SetColor(gdiplus_color_); graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); graphics_.FillPath(brush_, &path); } void Fl_GDIplus_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { if ( (x0 == x3 && x1 == x2 && y0 == y1 && y3 == y2) || (x0 == x1 && y1 == y2 && x2 == x3 && y3 == y0) ) { int left = fl_min(x0, fl_min(x1, fl_min(x2, x3))); int right = fl_max(x0, fl_max(x1, fl_max(x2, x3))); int top = fl_min(y0, fl_min(y1, fl_min(y2, y3))); int bottom = fl_max(y0, fl_max(y1, fl_max(y2, y3))); rectf(left, top, right-left, bottom-top); } else { if (!active) return Fl_Scalable_Graphics_Driver::polygon(x0, y0, x1, y1, x2, y2, x3, y3); Gdiplus::GraphicsPath path; path.AddLine(x0, y0, x1, y1); path.AddLine(x1, y1, x2, y2); path.AddLine(x2, y2, x3, y3); path.CloseFigure(); Gdiplus::Graphics graphics_(gc_); graphics_.ScaleTransform(scale(), scale()); brush_->SetColor(gdiplus_color_); graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); graphics_.FillPath(brush_, &path); } } #endif fltk-1.4.3/src/drivers/GDI/Fl_GDI_Graphics_Driver.H0000644000175000017500000002511715004135251021753 0ustar albrechtalbrecht// // Definition of classes Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_GDI_Graphics_Driver.H \brief Definition of Windows GDI graphics driver. */ #ifndef FL_GDI_GRAPHICS_DRIVER_H #define FL_GDI_GRAPHICS_DRIVER_H #include #include #include #include #if USE_GDIPLUS # if defined(_MSC_VER) # include # else # include // for PROPID needed with gcc 4.9.0 but not with 4.9.3 # endif # include #endif /** \brief The Windows-specific graphics driver class. This class is implemented only on the Windows platform. */ class Fl_GDI_Graphics_Driver : public Fl_Scalable_Graphics_Driver { private: BOOL alpha_blend_(int x, int y, int w, int h, HDC src_gc, int srcx, int srcy, int srcw, int srch); int depth; // to support translation POINT *origins; // to support translation void set_current_() FL_OVERRIDE; void draw_fixed(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_fixed(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void make_unused_color_(unsigned char &r, unsigned char &g, unsigned char &b, int color_count, void **data) FL_OVERRIDE; protected: void draw_fixed(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void cache(Fl_RGB_Image *rgb) FL_OVERRIDE; HDC gc_; int numcount; int counts[20]; uchar *mask_bitmap_; uchar **mask_bitmap() FL_OVERRIDE {return &mask_bitmap_;} POINT *long_point; #if FL_ABI_VERSION >= 10403 // Issue #1214 // empty #else bool is_solid_; #endif int style_; public: Fl_GDI_Graphics_Driver(); ~Fl_GDI_Graphics_Driver() FL_OVERRIDE; int has_feature(driver_feature mask) FL_OVERRIDE { return mask & NATIVE; } char can_do_alpha_blending() FL_OVERRIDE; void gc(void *ctxt) FL_OVERRIDE { gc_ = (HDC)ctxt; global_gc(); } void *gc() FL_OVERRIDE {return gc_;} // --- bitmap stuff static HBITMAP create_bitmask(int w, int h, const uchar *array); // NOT virtual static HBITMAP calc_HBITMAP_mask(Fl_RGB_Image *mask); void delete_bitmask(fl_uintptr_t bm) FL_OVERRIDE; HBITMAP create_alphamask(int w, int h, int d, int ld, const uchar *array); void draw_unscaled(const char* str, int n, int x, int y) FL_OVERRIDE; void draw_unscaled(int angle, const char *str, int n, int x, int y) FL_OVERRIDE; void rtl_draw_unscaled(const char* str, int n, int x, int y) FL_OVERRIDE; void font_unscaled(Fl_Font face, Fl_Fontsize size) FL_OVERRIDE; void draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) FL_OVERRIDE; void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) FL_OVERRIDE; void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) FL_OVERRIDE; void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) FL_OVERRIDE; void cache(Fl_Pixmap *img) FL_OVERRIDE; void uncache_pixmap(fl_uintptr_t p) FL_OVERRIDE; void cache(Fl_Bitmap *img) FL_OVERRIDE; void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) FL_OVERRIDE; double width_unscaled(const char *str, int n) FL_OVERRIDE; double width_unscaled(unsigned int c) FL_OVERRIDE; void text_extents_unscaled(const char*, int n, int& dx, int& dy, int& w, int& h) FL_OVERRIDE; int height_unscaled() FL_OVERRIDE; int descent_unscaled() FL_OVERRIDE; Fl_Fontsize size_unscaled() FL_OVERRIDE; #if ! defined(FL_DOXYGEN) void copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy); #endif void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) FL_OVERRIDE; void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h) FL_OVERRIDE; Fl_Region XRectangleRegion(int x, int y, int w, int h) FL_OVERRIDE; void XDestroyRegion(Fl_Region r) FL_OVERRIDE; void translate_all(int x, int y); void untranslate_all(void); static HRGN scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr); void scale(float f) FL_OVERRIDE; float scale() {return Fl_Graphics_Driver::scale();} protected: void transformed_vertex0(float x, float y) FL_OVERRIDE; void fixloop() FL_OVERRIDE; void point(int x, int y) FL_OVERRIDE; void focus_rect(int x, int y, int w, int h) FL_OVERRIDE; void rect_unscaled(int x, int y, int w, int h) FL_OVERRIDE; void rectf_unscaled(int x, int y, int w, int h) FL_OVERRIDE; #if USE_COLORMAP void colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) FL_OVERRIDE; #endif void line_unscaled(int x, int y, int x1, int y1) FL_OVERRIDE; void line_unscaled(int x, int y, int x1, int y1, int x2, int y2) FL_OVERRIDE; void xyline_unscaled(int x, int y, int x1) FL_OVERRIDE; void yxline_unscaled(int x, int y, int y1) FL_OVERRIDE; void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; // --- clipping void push_clip(int x, int y, int w, int h) FL_OVERRIDE; int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) FL_OVERRIDE; int not_clipped(int x, int y, int w, int h) FL_OVERRIDE; void restore_clip() FL_OVERRIDE; Fl_Region scale_clip(float f) FL_OVERRIDE; // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx void begin_complex_polygon() FL_OVERRIDE; void end_points() FL_OVERRIDE; void end_line() FL_OVERRIDE; void end_loop() FL_OVERRIDE; void end_polygon() FL_OVERRIDE; void end_complex_polygon() FL_OVERRIDE; void gap() FL_OVERRIDE; void ellipse_unscaled(double xt, double yt, double rx, double ry) FL_OVERRIDE; void arc_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void pie_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void line_style_unscaled(int style, int width, char* dashes) FL_OVERRIDE; void color(Fl_Color c) FL_OVERRIDE; Fl_Color color() FL_OVERRIDE { return color_; } void color(uchar r, uchar g, uchar b) FL_OVERRIDE; void set_color(Fl_Color i, unsigned int c) FL_OVERRIDE; void free_color(Fl_Color i, int overlay) FL_OVERRIDE; Fl_Font set_fonts(const char *name) FL_OVERRIDE; int get_font_sizes(Fl_Font fnum, int*& sizep) FL_OVERRIDE; const char* get_font_name(Fl_Font fnum, int* ap) FL_OVERRIDE; const char *font_name(int num) FL_OVERRIDE; void font_name(int num, const char *name) FL_OVERRIDE; void global_gc() FL_OVERRIDE; void overlay_rect(int x, int y, int w , int h) FL_OVERRIDE; void cache_size(Fl_Image *img, int &width, int &height) FL_OVERRIDE; void* change_pen_width(int width) FL_OVERRIDE; void reset_pen_width(void *data) FL_OVERRIDE; }; /** The graphics driver used when printing on Windows. This class is implemented only on the Windows platform. It is extremely similar to Fl_GDI_Graphics_Driver. */ class Fl_GDI_Printer_Graphics_Driver : public Fl_GDI_Graphics_Driver { private: typedef BOOL (WINAPI* transparent_f_type) (HDC,int,int,int,int,HDC,int,int,int,int,UINT); transparent_f_type TransparentBlt(); public: int has_feature(driver_feature mask) FL_OVERRIDE { return mask & (NATIVE | PRINTER); } void draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy) FL_OVERRIDE; }; #if USE_GDIPLUS class Fl_GDIplus_Graphics_Driver : public Fl_GDI_Graphics_Driver { friend class Fl_Graphics_Driver; private: Gdiplus::Color gdiplus_color_; Gdiplus::Pen *pen_; Gdiplus::SolidBrush *brush_; // The code below ensures that a connection to GDIplus is only made once, and that the // matching connection shutdown is also done exactly once. enum { STATE_CLOSED = 0, // no connection, token is invalid STATE_STARTUP, // attempt to start up, avoid recursions for whatever reason STATE_OPEN, // connection was successful and the token is valid STATE_SHUTDOWN // shutting down the gdi connection, avoid possible recursion }; static int gdiplus_state_; // reflect the state of the GDIplus driver connection static ULONG_PTR gdiplus_token_; // the token that GDIplus gives to us public: Fl_GDIplus_Graphics_Driver(); virtual ~Fl_GDIplus_Graphics_Driver(); bool active; static void shutdown(void); void color(Fl_Color c) FL_OVERRIDE; Fl_Color color() FL_OVERRIDE { return color_; } void color(uchar r, uchar g, uchar b) FL_OVERRIDE; void line(int x, int y, int x1, int y1) FL_OVERRIDE; void line(int x, int y, int x1, int y1, int x2, int y2) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void line_style(int style, int width, char* dashes) FL_OVERRIDE; void arc_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void pie_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void draw_circle(int x, int y, int d, Fl_Color c) FL_OVERRIDE; void transformed_vertex(double xf, double yf) FL_OVERRIDE; void vertex(double x,double y) FL_OVERRIDE; void end_points() FL_OVERRIDE; void end_line() FL_OVERRIDE; void end_loop() FL_OVERRIDE; void end_polygon() FL_OVERRIDE; void end_complex_polygon() FL_OVERRIDE; void circle(double x, double y, double r) FL_OVERRIDE; void antialias(int state) FL_OVERRIDE; int antialias() FL_OVERRIDE; }; #endif // USE_GDIPLUS #endif // FL_GDI_GRAPHICS_DRIVER_H fltk-1.4.3/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx0000644000175000017500000006626515004135251023541 0ustar albrechtalbrecht// // Windows image drawing code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // I hope a simple and portable method of drawing color and monochrome // images. To keep this simple, only a single storage type is // supported: 8 bit unsigned data, byte order RGB, and pixels are // stored packed into rows with the origin at the top-left. It is // possible to alter the size of pixels with the "delta" argument, to // add alpha or other information per pixel. It is also possible to // change the origin and direction of the image data by messing with // the "delta" and "linedelta", making them negative, though this may // defeat some of the shortcuts in translating the image for X. // Unbelievably (since it conflicts with how most PC software works) // Micro$oft picked a bottom-up and BGR storage format for their // DIB images. I'm pretty certain there is a way around this, but // I can't find any other than the brute-force method of drawing // each line as a separate image. This may also need to be done // if the delta is any amount other than 1, 3, or 4. //////////////////////////////////////////////////////////////// #include #include "Fl_GDI_Graphics_Driver.H" #include "../WinAPI/Fl_WinAPI_System_Driver.H" #include #include #include #include #define MAXBUFFER 0x40000 // 256k void fl_release_dc(HWND, HDC); // from Fl_win32.cxx #if USE_COLORMAP // error-diffusion dither into the FLTK colormap static void dither(uchar* to, const uchar* from, int w, int delta) { static int ri, gi, bi, dir; int r=ri, g=gi, b=bi; int d, td; if (dir) { dir = 0; from = from+(w-1)*delta; to = to+(w-1); d = -delta; td = -1; } else { dir = 1; d = delta; td = 1; } for (; w--; from += d, to += td) { r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; int rr = r*FL_NUM_RED/256; r -= rr*255/(FL_NUM_RED-1); g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255; int gg = g*FL_NUM_GREEN/256; g -= gg*255/(FL_NUM_GREEN-1); b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255; int bb = b*FL_NUM_BLUE/256; b -= bb*255/(FL_NUM_BLUE-1); *to = uchar(FL_COLOR_CUBE+(bb*FL_NUM_RED+rr)*FL_NUM_GREEN+gg); } ri = r; gi = g; bi = b; } // error-diffusion dither into the FLTK colormap static void monodither(uchar* to, const uchar* from, int w, int delta) { static int ri,dir; int r=ri; int d, td; if (dir) { dir = 0; from = from+(w-1)*delta; to = to+(w-1); d = -delta; td = -1; } else { dir = 1; d = delta; td = 1; } for (; w--; from += d, to += td) { r += *from; if (r < 0) r = 0; else if (r>255) r = 255; int rr = r*FL_NUM_GRAY/256; r -= rr*255/(FL_NUM_GRAY-1); *to = uchar(FL_GRAY_RAMP+rr); } ri = r; } #endif // USE_COLORMAP static int fl_abs(int v) { return v<0 ? -v : v; } static void innards(const uchar *buf, int X, int Y, int W, int H, int delta, int linedelta, int depth, Fl_Draw_Image_Cb cb, void* userdata, HDC gc) { char indexed = 0; #if USE_COLORMAP indexed = (fl_palette != 0); #endif if (depth==0) depth = 3; if (indexed || !fl_can_do_alpha_blending()) depth = (depth-1)|1; if (!linedelta) linedelta = W*fl_abs(delta); int x = 0, y = 0, w = 0, h = 0; fl_clip_box(X, Y, W, H, x, y, w, h); if (w<=0 || h<=0) return; if (buf) buf += (x-X)*delta + (y-Y)*linedelta; // bmibuffer: BITMAPINFOHEADER + 256 colors (RGBQUAD) + 1 (rounding effects ?) static U32 bmibuffer[sizeof(BITMAPINFOHEADER)/4 + 257]; BITMAPINFO *bmi = (BITMAPINFO*)bmibuffer; if (!bmi->bmiHeader.biSize) { bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi->bmiHeader.biPlanes = 1; bmi->bmiHeader.biCompression = BI_RGB; bmi->bmiHeader.biXPelsPerMeter = 0; bmi->bmiHeader.biYPelsPerMeter = 0; bmi->bmiHeader.biClrUsed = 0; bmi->bmiHeader.biClrImportant = 0; } #if USE_COLORMAP if (indexed) { for (short i=0; i<256; i++) { *((short*)(bmi->bmiColors)+i) = i; } } else #endif if (depth<3) { RGBQUAD *bmi_colors = &(bmi->bmiColors[0]); // use pointer to suppress warning (STR #3199) for (int i=0; i<256; i++) { bmi_colors[i].rgbBlue = (uchar)i; // = bmi->bmiColors[i] bmi_colors[i].rgbGreen = (uchar)i; bmi_colors[i].rgbRed = (uchar)i; bmi_colors[i].rgbReserved = (uchar)0; // must be zero } } bmi->bmiHeader.biWidth = w; #if USE_COLORMAP bmi->bmiHeader.biBitCount = indexed ? 8 : depth*8; int pixelsize = indexed ? 1 : depth; #else bmi->bmiHeader.biBitCount = depth*8; int pixelsize = depth; #endif if (depth==2) { // special case: gray with alpha bmi->bmiHeader.biBitCount = 32; pixelsize = 4; } int linesize = (pixelsize*w+3)&~3; static U32* buffer; static long buffer_size; int blocking = h; { int size = linesize * h; // when printing, don't limit buffer size not to get a crash in StretchDIBits if (size > MAXBUFFER && !fl_graphics_driver->has_feature(Fl_Graphics_Driver::PRINTER)) { size = MAXBUFFER; blocking = MAXBUFFER / linesize; } if (size > buffer_size) { delete[] buffer; buffer_size = size; buffer = new U32[(size + 3) / 4]; } } bmi->bmiHeader.biHeight = blocking; static U32* line_buffer; if (!buf) { int size = W*delta; static int line_buf_size; if (size > line_buf_size) { delete[] line_buffer; line_buf_size = size; line_buffer = new U32[(size+3)/4]; } } for (int j=0; j>8; to[0] = gray; to[1] = gray; to[2] = gray; to[3] = a; } break; case 3: for (i=w; i--; from += delta, to += 3) { uchar r = from[0]; to[0] = from[2]; to[1] = from[1]; to[2] = r; } break; case 4: for (i=w; i--; from += delta, to += 4) { uchar a = from[3]; uchar r = from[0]; to[0] = (from[2]*a)>>8; to[1] = (from[1]*a)>>8; to[2] = (r*a)>>8; to[3] = from[3]; } break; } } } // for (k = 0; jhas_feature(Fl_Graphics_Driver::PRINTER)) { // if print context, device and logical units are not equal, so SetDIBitsToDevice // does not do the expected job, whereas StretchDIBits does it. StretchDIBits(gc, x, y+j-k, w, k, 0, 0, w, k, (LPSTR)((uchar*)buffer+(blocking-k)*linesize), bmi, #if USE_COLORMAP indexed ? DIB_PAL_COLORS : DIB_RGB_COLORS #else DIB_RGB_COLORS #endif , SRCCOPY ); delete[] buffer; buffer = NULL; buffer_size = 0; } else { SetDIBitsToDevice(gc, x, y+j-k, w, k, 0, 0, 0, k, (LPSTR)((uchar*)buffer+(blocking-k)*linesize), bmi, #if USE_COLORMAP indexed ? DIB_PAL_COLORS : DIB_RGB_COLORS #else DIB_RGB_COLORS #endif ); } } // for (int j=0; j-3),0,0, gc_); } } void Fl_GDI_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) { d ^= FL_IMAGE_WITH_ALPHA; innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data, gc_); } else { innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data, gc_); } } void Fl_GDI_Graphics_Driver::draw_image_mono_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){ if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) { d ^= FL_IMAGE_WITH_ALPHA; innards(buf,x,y,w,h,d,l,1,0,0, gc_); } else { innards(buf,x,y,w,h,d,l,1,0,0, gc_); } } void Fl_GDI_Graphics_Driver::draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) { d ^= FL_IMAGE_WITH_ALPHA; innards(0,x,y,w,h,d,0,1,cb,data, gc_); } else { innards(0,x,y,w,h,d,0,1,cb,data, gc_); } } #if USE_COLORMAP void Fl_GDI_Graphics_Driver::colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { // use the error diffusion dithering code to produce a much nicer block: if (fl_palette) { uchar c[3]; c[0] = r; c[1] = g; c[2] = b; innards(c, floor(x), floor(y), floor(x + w) - floor(x), floor(y + h) - floor(y), 0,0,0,0,0, (HDC)gc()); return; } Fl_Graphics_Driver::colored_rectf(x, y, w, h, r, g, b); } #endif // Create an N-bit bitmap for masking... HBITMAP Fl_GDI_Graphics_Driver::create_bitmask(int w, int h, const uchar *data) { // this won't work when the user changes display mode during run or // has two screens with different depths HBITMAP bm; static uchar hiNibble[16] = { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 }; static uchar loNibble[16] = { 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f }; HDC current_gc = (HDC)Fl_Surface_Device::surface()->driver()->gc(); int np = GetDeviceCaps(current_gc, PLANES); //: was always one on sample machines int bpp = GetDeviceCaps(current_gc, BITSPIXEL);//: 1,4,8,16,24,32 and more odd stuff? int Bpr = (bpp*w+7)/8; //: bytes per row int pad = Bpr&1, w1 = (w+7)/8, shr = ((w-1)&7)+1; if (bpp==4) shr = (shr+1)/2; uchar *newarray = new uchar[(Bpr+pad)*h]; uchar *dst = newarray; const uchar *src = data; for (int i=0; i0; j--) { uchar b = *src++; if (bpp==1) { *dst++ = (uchar)( hiNibble[b&15] ) | ( loNibble[(b>>4)&15] ); } else if (bpp==4) { for (int k=(j==1)?shr:4; k>0; k--) { *dst++ = (uchar)("\377\360\017\000"[b&3]); b = b >> 2; } } else { for (int k=(j==1)?shr:8; k>0; k--) { if (b&1) { *dst++=0; if (bpp>8) *dst++=0; if (bpp>16) *dst++=0; if (bpp>24) *dst++=0; } else { *dst++=0xff; if (bpp>8) *dst++=0xff; if (bpp>16) *dst++=0xff; if (bpp>24) *dst++=0xff; } b = b >> 1; } } } dst += pad; } bm = CreateBitmap(w, h, np, bpp, newarray); delete[] newarray; return bm; } void Fl_GDI_Graphics_Driver::delete_bitmask(fl_uintptr_t bm) { DeleteObject((HGDIOBJ)bm); } void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) { X = this->floor(X); Y = this->floor(Y); cache_size(bm, W, H); cx = this->floor(cx); cy = this->floor(cy); HDC tempdc = CreateCompatibleDC(gc_); int save = SaveDC(tempdc); SelectObject(tempdc, (HGDIOBJ)*Fl_Graphics_Driver::id(bm)); SelectObject(gc_, fl_brush()); // secret bitblt code found in old Windows reference manual: BitBlt(gc_, X, Y, W, H, tempdc, cx, cy, 0xE20746L); RestoreDC(tempdc, save); DeleteDC(tempdc); } Fl_GDI_Printer_Graphics_Driver::transparent_f_type Fl_GDI_Printer_Graphics_Driver::TransparentBlt() { HMODULE hMod; static transparent_f_type fpter = ( (hMod = LoadLibrary("MSIMG32.DLL")) ? (transparent_f_type)GetProcAddress(hMod, "TransparentBlt") : NULL ); return fpter; } void Fl_GDI_Printer_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; if (Fl_Graphics_Driver::start_image(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; } transparent_f_type fl_TransparentBlt = TransparentBlt(); if (!fl_TransparentBlt) { Fl_Graphics_Driver::draw_bitmap(bm, X, Y, W, H, cx, cy); return; } bool recache = false; if (*id(bm)) { int *pw, *ph; cache_w_h(bm, pw, ph); recache = (*pw != bm->data_w() || *ph != bm->data_h()); } if (recache || !*id(bm)) { bm->uncache(); cache(bm); } HDC tempdc; int save; // algorithm for bitmap output to Fl_GDI_Printer Fl_Color save_c = fl_color(); // save bitmap's desired color uchar r, g, b; Fl::get_color(save_c, r, g, b); r = 255-r; g = 255-g; b = 255-b; Fl_Color background = fl_rgb_color(r, g, b); // a color very different from the bitmap's Fl_Image_Surface *img_surf = new Fl_Image_Surface(bm->data_w(), bm->data_h()); Fl_Surface_Device::push_current(img_surf); fl_color(background); fl_rectf(0,0, bm->data_w(), bm->data_h()); // use this color as offscreen background fl_color(save_c); // back to bitmap's color HDC off_gc = (HDC)fl_graphics_driver->gc(); tempdc = CreateCompatibleDC(off_gc); save = SaveDC(tempdc); SelectObject(tempdc, (HGDIOBJ)*Fl_Graphics_Driver::id(bm)); SelectObject(off_gc, fl_brush()); // use bitmap's desired color BitBlt(off_gc, 0, 0, bm->data_w(), bm->data_h(), tempdc, 0, 0, 0xE20746L); // draw bitmap to offscreen Fl_Surface_Device::pop_current(); SelectObject(tempdc, (HGDIOBJ)img_surf->offscreen()); // use offscreen data // draw it to printer context with background color as transparent float scaleW = bm->data_w()/float(bm->w()); float scaleH = bm->data_h()/float(bm->h()); fl_TransparentBlt(gc_, X, Y, W, H, tempdc, int(cx * scaleW), int(cy * scaleH), int(W * scaleW), int(H * scaleH), RGB(r, g, b) ); delete img_surf; RestoreDC(tempdc, save); DeleteDC(tempdc); if (recache) bm->uncache(); } // Create a 1-bit mask used for alpha blending HBITMAP Fl_GDI_Graphics_Driver::create_alphamask(int w, int h, int d, int ld, const uchar *array) { HBITMAP bm; int bmw = (w + 7) / 8; uchar *bitmap = new uchar[bmw * h]; uchar *bitptr, bit; const uchar *dataptr; int x, y; static uchar dither[16][16] = { // Simple 16x16 Floyd dither { 0, 128, 32, 160, 8, 136, 40, 168, 2, 130, 34, 162, 10, 138, 42, 170 }, { 192, 64, 224, 96, 200, 72, 232, 104, 194, 66, 226, 98, 202, 74, 234, 106 }, { 48, 176, 16, 144, 56, 184, 24, 152, 50, 178, 18, 146, 58, 186, 26, 154 }, { 240, 112, 208, 80, 248, 120, 216, 88, 242, 114, 210, 82, 250, 122, 218, 90 }, { 12, 140, 44, 172, 4, 132, 36, 164, 14, 142, 46, 174, 6, 134, 38, 166 }, { 204, 76, 236, 108, 196, 68, 228, 100, 206, 78, 238, 110, 198, 70, 230, 102 }, { 60, 188, 28, 156, 52, 180, 20, 148, 62, 190, 30, 158, 54, 182, 22, 150 }, { 252, 124, 220, 92, 244, 116, 212, 84, 254, 126, 222, 94, 246, 118, 214, 86 }, { 3, 131, 35, 163, 11, 139, 43, 171, 1, 129, 33, 161, 9, 137, 41, 169 }, { 195, 67, 227, 99, 203, 75, 235, 107, 193, 65, 225, 97, 201, 73, 233, 105 }, { 51, 179, 19, 147, 59, 187, 27, 155, 49, 177, 17, 145, 57, 185, 25, 153 }, { 243, 115, 211, 83, 251, 123, 219, 91, 241, 113, 209, 81, 249, 121, 217, 89 }, { 15, 143, 47, 175, 7, 135, 39, 167, 13, 141, 45, 173, 5, 133, 37, 165 }, { 207, 79, 239, 111, 199, 71, 231, 103, 205, 77, 237, 109, 197, 69, 229, 101 }, { 63, 191, 31, 159, 55, 183, 23, 151, 61, 189, 29, 157, 53, 181, 21, 149 }, { 254, 127, 223, 95, 247, 119, 215, 87, 253, 125, 221, 93, 245, 117, 213, 85 } }; // Generate a 1-bit "screen door" alpha mask; not always pretty, but // definitely fast... In the future we may be able to support things // like the RENDER extension in XFree86, when available, to provide // true RGBA-blended rendering. See: // // http://www.xfree86.org/~keithp/render/protocol.html // // for more info on XRender... // memset(bitmap, 0, bmw * h); for (dataptr = array + d - 1, y = 0; y < h; y ++, dataptr += ld) for (bitptr = bitmap + y * bmw, bit = 1, x = 0; x < w; x ++, dataptr += d) { if (*dataptr > dither[x & 15][y & 15]) *bitptr |= bit; if (bit < 128) bit <<= 1; else { bit = 1; bitptr ++; } } bm = create_bitmask(w, h, bitmap); delete[] bitmap; return bm; } void Fl_GDI_Graphics_Driver::cache(Fl_RGB_Image *img) { Fl_Image_Surface *surface = new Fl_Image_Surface(img->data_w(), img->data_h()); Fl_Surface_Device::push_current(surface); if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) { fl_draw_image(img->array, 0, 0, img->data_w(), img->data_h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld()); } else { fl_draw_image(img->array, 0, 0, img->data_w(), img->data_h(), img->d(), img->ld()); if (img->d() == 2 || img->d() == 4) { *Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)create_alphamask(img->data_w(), img->data_h(), img->d(), img->ld(), img->array); } } Fl_Surface_Device::pop_current(); Fl_Offscreen offs = Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surface); int *pw, *ph; cache_w_h(img, pw, ph); *pw = img->data_w(); *ph = img->data_h(); *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)offs; } void Fl_GDI_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { X = this->floor(X); Y = this->floor(Y); cache_size(img, W, H); cx = this->floor(cx); cy = this->floor(cy); if (W + cx > img->data_w()) W = img->data_w() - cx; if (H + cy > img->data_h()) H = img->data_h() - cy; if (!*Fl_Graphics_Driver::id(img)) { cache(img); } if (*Fl_Graphics_Driver::mask(img)) { HDC new_gc = CreateCompatibleDC(gc_); int save = SaveDC(new_gc); SelectObject(new_gc, (void*)*Fl_Graphics_Driver::mask(img)); BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCAND); SelectObject(new_gc, (void*)*Fl_Graphics_Driver::id(img)); BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCPAINT); RestoreDC(new_gc,save); DeleteDC(new_gc); } else if (img->d()==2 || img->d()==4) { copy_offscreen_with_alpha(X, Y, W, H, (HBITMAP)*Fl_Graphics_Driver::id(img), cx, cy); } else { copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(img), cx, cy); } } void Fl_GDI_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) { if (Fl_Graphics_Driver::start_image(rgb, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) { return; } if ((rgb->d() % 2) == 0 && !fl_can_do_alpha_blending()) { Fl_Graphics_Driver::draw_rgb(rgb, XP, YP, WP, HP, cx, cy); return; } if (!*Fl_Graphics_Driver::id(rgb)) { cache(rgb); } push_clip(XP, YP, WP, HP); XP -= cx; YP -= cy; WP = rgb->w(); HP = rgb->h(); cache_size(rgb, WP, HP); HDC new_gc = CreateCompatibleDC(gc_); int save = SaveDC(new_gc); SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(rgb)); if ( (rgb->d() % 2) == 0 ) { alpha_blend_(this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h()); } else { SetStretchBltMode(gc_, (Fl_Image::scaling_algorithm() == FL_RGB_SCALING_BILINEAR ? HALFTONE : BLACKONWHITE)); StretchBlt(gc_, this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h(), SRCCOPY); } RestoreDC(new_gc, save); DeleteDC(new_gc); pop_clip(); } void Fl_GDI_Printer_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) { if (Fl_Graphics_Driver::start_image(rgb, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) { return; } XFORM old_tr, tr; GetWorldTransform(gc_, &old_tr); // storing old transform tr.eM11 = float(rgb->w())/float(rgb->data_w()); tr.eM22 = float(rgb->h())/float(rgb->data_h()); tr.eM12 = tr.eM21 = 0; tr.eDx = float(XP); tr.eDy = float(YP); ModifyWorldTransform(gc_, &tr, MWT_LEFTMULTIPLY); if (*id(rgb)) { int *pw, *ph; cache_w_h(rgb, pw, ph); if ( *pw != rgb->data_w() || *ph != rgb->data_h()) rgb->uncache(); } if (!*id(rgb)) cache(rgb); draw_fixed(rgb, 0, 0, int(WP / tr.eM11), int(HP / tr.eM22), int(cx / tr.eM11), int(cy / tr.eM22)); SetWorldTransform(gc_, &old_tr); } void Fl_GDI_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) { if (id_) { DeleteObject((HBITMAP)id_); id_ = 0; } if (mask_) { delete_bitmask(mask_); mask_ = 0; } } // 'fl_create_bitmap()' - Create a 1-bit bitmap for drawing... static HBITMAP fl_create_bitmap(int w, int h, const uchar *data) { // we need to pad the lines out to words & swap the bits // in each byte. int w1 = (w + 7) / 8; int w2 = ((w + 15) / 16) * 2; uchar* newarray = new uchar[w2*h]; const uchar* src = data; uchar* dest = newarray; HBITMAP bm; static uchar reverse[16] = /* Bit reversal lookup table */ { 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee, 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff }; for (int y = 0; y < h; y++) { for (int n = 0; n < w1; n++, src++) *dest++ = (uchar)((reverse[*src & 0x0f] & 0xf0) | (reverse[(*src >> 4) & 0x0f] & 0x0f)); dest += w2 - w1; } bm = CreateBitmap(w, h, 1, 1, newarray); delete[] newarray; return bm; } void Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm) { int *pw, *ph; cache_w_h(bm, pw, ph); *pw = bm->data_w(); *ph = bm->data_h(); *Fl_Graphics_Driver::id(bm) = (fl_uintptr_t)fl_create_bitmap(bm->data_w(), bm->data_h(), bm->array); } void Fl_GDI_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, int H, int cx, int cy) { X = this->floor(X); Y = this->floor(Y); cache_size(pxm, W, H); cx = this->floor(cx); cy = this->floor(cy); Fl_Region r2 = scale_clip(scale()); if (*Fl_Graphics_Driver::mask(pxm)) { HDC new_gc = CreateCompatibleDC(gc_); int save = SaveDC(new_gc); SelectObject(new_gc, (void*)*Fl_Graphics_Driver::mask(pxm)); BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCAND); SelectObject(new_gc, (void*)*Fl_Graphics_Driver::id(pxm)); BitBlt(gc_, X, Y, W, H, new_gc, cx, cy, SRCPAINT); RestoreDC(new_gc,save); DeleteDC(new_gc); } else { float s = scale(); Fl_Graphics_Driver::scale(1); copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(pxm), cx, cy); Fl_Graphics_Driver::scale(s); } unscale_clip(r2); } /* ===== Implementation note about how Fl_Pixmap objects get printed under Windows ===== Fl_Pixmap objects are printed with the print-specific Fl_GDI_Printer_Graphics_Driver which uses the TransparentBlt() system function that can scale the image and treat one of its colors as transparent. Fl_GDI_Printer_Graphics_Driver::draw_pixmap(Fl_Pixmap *,...) sets need_pixmap_bg_color, a static class variable, to 1 and recaches the image. This calls fl_convert_pixmap() that checks the value of need_pixmap_bg_color. When this value is not 0, fl_convert_pixmap runs in a way that memorizes the list of all colors in the pixmap, computes a color absent from this list, uses it for the transparent pixels of the pixmap and puts this color value in need_pixmap_bg_color. As a result, the transparent areas of the image are correcty handled by the printing operation. Variable need_pixmap_bg_color is ultimately reset to 0. Fl_GDI_Graphics_Driver::make_unused_color_() which does the color computation mentioned above is implemented in file src/fl_draw_pixmap.cxx */ void Fl_GDI_Printer_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; if (start_image(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; transparent_f_type fl_TransparentBlt = TransparentBlt(); if (fl_TransparentBlt) { need_pixmap_bg_color = 1; pxm->uncache(); cache(pxm); HDC new_gc = CreateCompatibleDC(gc_); int save = SaveDC(new_gc); SelectObject(new_gc, (void*)*Fl_Graphics_Driver::id(pxm)); // print all of offscreen but its parts in background color float scaleW = pxm->data_w()/float(pxm->w()); float scaleH = pxm->data_h()/float(pxm->h()); fl_TransparentBlt(gc_, X, Y, W, H, new_gc, int(cx * scaleW), int(cy * scaleH), int(W * scaleW), int(H * scaleH), need_pixmap_bg_color ); RestoreDC(new_gc,save); DeleteDC(new_gc); need_pixmap_bg_color = 0; } else { copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(pxm), cx, cy); } } // Makes an RGB triplet different from all the colors used in the pixmap // and computes Fl_Graphics_Driver::need_pixmap_bg_color from this triplet void Fl_GDI_Graphics_Driver::make_unused_color_(uchar &r, uchar &g, uchar &b, int color_count, void **data) { typedef struct { uchar r; uchar g; uchar b; } UsedColor; UsedColor *used_colors = *(UsedColor**)data; int i; r = 2; g = 3; b = 4; while (1) { for ( i=0; i= color_count) { free((void*)used_colors); *(UsedColor**)data = NULL; need_pixmap_bg_color = RGB(r, g, b); return; } if (r < 255) { r++; } else { r = 0; if (g < 255) { g++; } else { g = 0; b++; } } } } void Fl_GDI_Graphics_Driver::cache(Fl_Pixmap *img) { Fl_Image_Surface *surf = new Fl_Image_Surface(img->data_w(), img->data_h()); Fl_Surface_Device::push_current(surf); uchar **pbitmap = surf->driver()->mask_bitmap(); *pbitmap = (uchar*)1;// will instruct fl_draw_pixmap() to compute the image's mask fl_draw_pixmap(img->data(), 0, 0, FL_BLACK); uchar *bitmap = *pbitmap; if (bitmap) { *Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)create_bitmask(img->data_w(), img->data_h(), bitmap); delete[] bitmap; } *pbitmap = 0; Fl_Surface_Device::pop_current(); Fl_Offscreen id = Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surf); int *pw, *ph; cache_w_h(img, pw, ph); *pw = img->data_w(); *ph = img->data_h(); *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)id; } void Fl_GDI_Graphics_Driver::uncache_pixmap(fl_uintptr_t offscreen) { DeleteObject((HBITMAP)offscreen); } fltk-1.4.3/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx0000644000175000017500000002473615004135251022374 0ustar albrechtalbrecht// // Rectangle drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_GDI_Graphics_Driver.H" #include #include #include #include "../../Fl_Screen_Driver.H" #include "Fl_Font.H" #if USE_GDIPLUS Fl_GDIplus_Graphics_Driver::Fl_GDIplus_Graphics_Driver() : Fl_GDI_Graphics_Driver() { if (!fl_current_xmap) color(FL_BLACK); pen_ = new Gdiplus::Pen(gdiplus_color_, 1); pen_->SetLineJoin(Gdiplus::LineJoinRound); pen_->SetStartCap(Gdiplus::LineCapFlat); pen_->SetEndCap(Gdiplus::LineCapFlat); brush_ = new Gdiplus::SolidBrush(gdiplus_color_); active = true; } Fl_GDIplus_Graphics_Driver::~Fl_GDIplus_Graphics_Driver() { delete pen_; delete brush_; } void Fl_GDIplus_Graphics_Driver::antialias(int state) { active = state; } int Fl_GDIplus_Graphics_Driver::antialias() { return active; } void Fl_GDIplus_Graphics_Driver::draw_circle(int x, int y, int d, Fl_Color c) { Fl_Graphics_Driver::draw_circle(x, y, d, c); } int Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_CLOSED; ULONG_PTR Fl_GDIplus_Graphics_Driver::gdiplus_token_ = 0; void Fl_GDIplus_Graphics_Driver::shutdown() { if (gdiplus_state_ == STATE_OPEN) { gdiplus_state_ = STATE_SHUTDOWN; Gdiplus::GdiplusShutdown(Fl_GDIplus_Graphics_Driver::gdiplus_token_); gdiplus_token_ = 0; gdiplus_state_ = STATE_CLOSED; } else if (gdiplus_state_ == STATE_CLOSED) { // Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called, but driver is closed."); } else if (gdiplus_state_ == STATE_SHUTDOWN) { // Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called recursively."); } else if (gdiplus_state_ == STATE_STARTUP) { // Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called while driver is starting up."); } } #endif // Code used to switch output to an off-screen window. See macros in // win32.H which save the old state in local variables. typedef struct { BYTE a; BYTE b; BYTE c; BYTE d; } FL_BLENDFUNCTION; typedef BOOL (WINAPI* fl_alpha_blend_func) (HDC,int,int,int,int,HDC,int,int,int,int,FL_BLENDFUNCTION); static fl_alpha_blend_func fl_alpha_blend = NULL; static FL_BLENDFUNCTION blendfunc = { 0, 0, 255, 1}; /* Reference to the current device context For back-compatibility only. The preferred procedure to get this reference is Fl_Surface_Device::surface()->driver()->gc(). */ HDC fl_gc = 0; HDC fl_win32_gc() { return fl_gc; } Fl_GDI_Graphics_Driver::Fl_GDI_Graphics_Driver() { mask_bitmap_ = NULL; gc_ = NULL; long_point = NULL; depth = -1; origins = NULL; #if FL_ABI_VERSION >= 10403 // Issue #1214 // empty #else is_solid_ = true; #endif style_ = FL_SOLID; } Fl_GDI_Graphics_Driver::~Fl_GDI_Graphics_Driver() { if (long_point) free(long_point); delete[] origins; } void Fl_GDI_Graphics_Driver::global_gc() { fl_gc = (HDC)gc(); } /* * This function checks if the version of Windows that we * curently run on supports alpha blending for bitmap transfers * and finds the required function if so. */ char Fl_GDI_Graphics_Driver::can_do_alpha_blending() { static char been_here = 0; static char can_do = 0; // do this test only once if (been_here) return can_do; been_here = 1; // load the library that implements alpha blending HMODULE hMod = LoadLibrary("MSIMG32.DLL"); // give up if that doesn't exist (Win95?) if (!hMod) return 0; // now find the blending function inside that dll fl_alpha_blend = (fl_alpha_blend_func)GetProcAddress(hMod, "AlphaBlend"); // give up if we can't find it (Win95) if (!fl_alpha_blend) return 0; // we have the call, but does our display support alpha blending? // get the desktop's device context HDC dc = GetDC(0L); if (!dc) return 0; // check the device capabilities flags. However GetDeviceCaps // does not return anything useful, so we have to do it manually: HBITMAP bm = CreateCompatibleBitmap(dc, 1, 1); HDC new_gc = CreateCompatibleDC(dc); int save = SaveDC(new_gc); SelectObject(new_gc, bm); /*COLORREF set = */ SetPixel(new_gc, 0, 0, 0x01010101); BOOL alpha_ok = fl_alpha_blend(dc, 0, 0, 1, 1, new_gc, 0, 0, 1, 1, blendfunc); RestoreDC(new_gc, save); DeleteDC(new_gc); DeleteObject(bm); ReleaseDC(0L, dc); if (alpha_ok) can_do = 1; return can_do; } HDC fl_makeDC(HBITMAP bitmap) { HDC new_gc = CreateCompatibleDC((HDC)Fl_Graphics_Driver::default_driver().gc()); SetTextAlign(new_gc, TA_BASELINE|TA_LEFT); SetBkMode(new_gc, TRANSPARENT); #if USE_COLORMAP if (fl_palette) SelectPalette(new_gc, fl_palette, FALSE); #endif SelectObject(new_gc, bitmap); return new_gc; } void Fl_GDI_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy) { x = int(x * scale()); y = int(y * scale()); w = int(w * scale()); h = int(h * scale()); srcx = int(srcx * scale()); srcy = int(srcy * scale()); if (srcx < 0) {w += srcx; x -= srcx; srcx = 0;} if (srcy < 0) {h += srcy; y -= srcy; srcy = 0;} int off_width, off_height; Fl::screen_driver()->offscreen_size(bitmap, off_width, off_height); if (srcx + w >= off_width) {w = off_width - srcx;} if (srcy + h >= off_height) {h = off_height - srcy;} if (w <= 0 || h <= 0) return; HDC new_gc = CreateCompatibleDC(gc_); int save = SaveDC(new_gc); SelectObject(new_gc, (HBITMAP)bitmap); BitBlt(gc_, x, y, w, h, new_gc, srcx, srcy, SRCCOPY); RestoreDC(new_gc, save); DeleteDC(new_gc); } void Fl_GDI_Printer_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy) { Fl_Graphics_Driver::copy_offscreen(x, y, w, h, bitmap, srcx, srcy); } BOOL Fl_GDI_Graphics_Driver::alpha_blend_(int x, int y, int w, int h, HDC src_gc, int srcx, int srcy, int srcw, int srch) { return fl_alpha_blend(gc_, x, y, w, h, src_gc, srcx, srcy, srcw, srch, blendfunc); } #if ! defined(FL_DOXYGEN) void Fl_GDI_Graphics_Driver::copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) { HDC new_gc = CreateCompatibleDC(gc_); int save = SaveDC(new_gc); SelectObject(new_gc, bitmap); BOOL alpha_ok = 0; // first try to alpha blend if ( fl_can_do_alpha_blending() ) { alpha_ok = alpha_blend_(x, y, w, h, new_gc, srcx, srcy, w, h); } // if that failed (it shouldn't), still copy the bitmap over, but now alpha is 1 if (!alpha_ok) { BitBlt(gc_, x, y, w, h, new_gc, srcx, srcy, SRCCOPY); } RestoreDC(new_gc, save); DeleteDC(new_gc); } void Fl_GDI_Graphics_Driver::translate_all(int x, int y) { const int stack_height = 10; if (depth == -1) { origins = new POINT[stack_height]; depth = 0; } if (depth >= stack_height) { Fl::warning("Fl_Copy/Image_Surface: translate stack overflow!"); depth = stack_height - 1; } GetWindowOrgEx((HDC)gc(), origins+depth); SetWindowOrgEx((HDC)gc(), int(origins[depth].x - x*scale()), int(origins[depth].y - y*scale()), NULL); depth++; } void Fl_GDI_Graphics_Driver::untranslate_all() { if (depth > 0) depth--; SetWindowOrgEx((HDC)gc(), origins[depth].x, origins[depth].y, NULL); } #endif void Fl_GDI_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) { HRGN R = (HRGN)XRectangleRegion(X, Y, W, H); CombineRgn((HRGN)r, (HRGN)r, R, RGN_OR); XDestroyRegion(R); } void Fl_GDI_Graphics_Driver::transformed_vertex0(float x, float y) { if (!n || x != long_point[n-1].x || y != long_point[n-1].y) { if (n >= p_size) { p_size = long_point ? 2*p_size : 16; long_point = (POINT*)realloc((void*)long_point, p_size*sizeof(*long_point)); } long_point[n].x = LONG(x); long_point[n].y = LONG(y); n++; } } void Fl_GDI_Graphics_Driver::fixloop() { // remove equal points from closed path while (n>2 && long_point[n-1].x == long_point[0].x && long_point[n-1].y == long_point[0].y) n--; } Fl_Region Fl_GDI_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) { if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) return CreateRectRgn(x,y,x+w,y+h); // because rotation may apply, the rectangle becomes a polygon in device coords POINT pt[4] = { {x, y}, {x + w, y}, {x + w, y + h}, {x, y + h} }; LPtoDP((HDC)fl_graphics_driver->gc(), pt, 4); return CreatePolygonRgn(pt, 4, ALTERNATE); } void Fl_GDI_Graphics_Driver::XDestroyRegion(Fl_Region r) { DeleteObject((HRGN)r); } void Fl_GDI_Graphics_Driver::scale(float f) { if (f != scale()) { size_ = 0; Fl_Graphics_Driver::scale(f); color(FL_BLACK); line_style(FL_SOLID); // scale also default line width } } /* Rescale region r with factor f and returns the scaled region. Region r is returned unchanged if r is null or f is 1. */ HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr) { if (r && f != 1) { DWORD size = GetRegionData(r, 0, NULL); RGNDATA *pdata = (RGNDATA*)malloc(size); GetRegionData(r, size, pdata); POINT pt = {0, 0}; if (dr && dr->depth >= 1) { // account for translation GetWindowOrgEx((HDC)dr->gc(), &pt); pt.x = int(pt.x * (f - 1)); pt.y = int(pt.y * (f - 1)); } RECT *rects = (RECT*)&(pdata->Buffer); for (DWORD i = 0; i < pdata->rdh.nCount; i++) { int x = Fl_Scalable_Graphics_Driver::floor(rects[i].left, f) + pt.x; int y = Fl_Scalable_Graphics_Driver::floor(rects[i].top, f) + pt.y; RECT R2; R2.left = x; R2.top = y; R2.right = Fl_Scalable_Graphics_Driver::floor(rects[i].right, f) + pt.x - x + R2.left; R2.bottom = Fl_Scalable_Graphics_Driver::floor(rects[i].bottom, f) + pt.y - y + R2.top; rects[i] = R2; } r = ExtCreateRegion(NULL, size, pdata); free(pdata); } return r; } Fl_Region Fl_GDI_Graphics_Driver::scale_clip(float f) { HRGN r = (HRGN)rstack[rstackptr]; HRGN r2 = scale_region(r, f, this); return (r == r2 ? NULL : (rstack[rstackptr] = r2, r)); } void Fl_GDI_Graphics_Driver::set_current_() { restore_clip(); } void Fl_GDI_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height) { float s = scale(); width = (s == int(s) ? width * int(s) : floor(width+1)); height = (s == int(s) ? height * int(s) : floor(height+1)); cache_size_finalize(img, width, height); } fltk-1.4.3/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx0000644000175000017500000001257315004135251023322 0ustar albrechtalbrecht// // Draw-to-image code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "Fl_GDI_Graphics_Driver.H" #include "../WinAPI/Fl_WinAPI_Screen_Driver.H" #include "Fl_GDI_Image_Surface_Driver.H" #include #include #include Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) { Fl_Display_Device::display_device(); // make sure fl_graphics_driver was initialized float d = fl_graphics_driver->scale(); if (!off && d != 1 && high_res) { w = int(w*d); h = int(h*d); } HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc(); offscreen = off ? off : (Fl_Offscreen)CreateCompatibleBitmap( (gc ? gc : fl_GetDC(0) ) , w, h); if (!offscreen) offscreen = (Fl_Offscreen)CreateCompatibleBitmap(fl_GetDC(0), w, h); driver(Fl_Graphics_Driver::newMainGraphicsDriver()); if (d != 1 && high_res) ((Fl_GDI_Graphics_Driver*)driver())->scale(d); origin.x = origin.y = 0; shape_data_ = NULL; } Fl_GDI_Image_Surface_Driver::~Fl_GDI_Image_Surface_Driver() { if (shape_data_ && shape_data_->background) { DeleteObject(shape_data_->background); delete shape_data_->mask; free(shape_data_); } if (offscreen && !external_offscreen) DeleteObject((HBITMAP)offscreen); delete driver(); } void Fl_GDI_Image_Surface_Driver::set_current() { HDC gc = fl_makeDC((HBITMAP)offscreen); driver()->gc(gc); SetWindowOrgEx(gc, origin.x, origin.y, NULL); Fl_Surface_Device::set_current(); pre_window = fl_window; _savedc = SaveDC(gc); fl_window=(HWND)offscreen; } void Fl_GDI_Image_Surface_Driver::translate(int x, int y) { ((Fl_GDI_Graphics_Driver*)driver())->translate_all(x, y); } void Fl_GDI_Image_Surface_Driver::untranslate() { ((Fl_GDI_Graphics_Driver*)driver())->untranslate_all(); } Fl_RGB_Image* Fl_GDI_Image_Surface_Driver::image() { if (shape_data_ && shape_data_->background) { // get the offscreen size in pixels HDC gc = fl_makeDC((HBITMAP)offscreen); BITMAPINFO bmi; bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 0; bmi.bmiHeader.biSizeImage = 0; GetDIBits(gc, (HBITMAP)offscreen, 0, 0, NULL, &bmi, DIB_RGB_COLORS); int W = bmi.bmiHeader.biWidth; int H = bmi.bmiHeader.biHeight; int line_size = ((3*W+3)/4) * 4; // read bits of main offscreen uchar *dib_src = new uchar[line_size * H]; bmi.bmiHeader.biWidth = W; bmi.bmiHeader.biHeight = H; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biBitCount = 24; GetDIBits(gc, (HBITMAP)offscreen, 0, H, dib_src, &bmi, DIB_RGB_COLORS); // draw above the secondary offscreen the main offscreen masked by shape_data_->mask GdiFlush(); Fl_Image_Surface_Driver::copy_with_mask(shape_data_->mask, shape_data_->vBits, dib_src, ((3*W+3)/4) * 4, true); delete shape_data_->mask; delete[] dib_src; // write bits of main offscreen SetDIBits(gc, (HBITMAP)offscreen, 0, H, shape_data_->vBits, &bmi, DIB_RGB_COLORS); DeleteDC(gc); DeleteObject(shape_data_->background); shape_data_->background = NULL; free(shape_data_); shape_data_ = NULL; } Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle( 0, 0, width, height, 0); return image; } void Fl_GDI_Image_Surface_Driver::end_current() { HDC gc = (HDC)driver()->gc(); GetWindowOrgEx(gc, &origin); RestoreDC(gc, _savedc); DeleteDC(gc); fl_window = pre_window; Fl_Surface_Device::end_current(); } void Fl_GDI_Image_Surface_Driver::mask(const Fl_RGB_Image *mask) { shape_data_ = (struct shape_data_type*)calloc(1, sizeof(struct shape_data_type)); // get the offscreen size in pixels HDC gc = fl_makeDC((HBITMAP)offscreen); BITMAPINFO bmi; bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 0; bmi.bmiHeader.biSizeImage = 0; GetDIBits(gc, (HBITMAP)offscreen, 0, 0, NULL, &bmi, DIB_RGB_COLORS); int W = bmi.bmiHeader.biWidth; int H = bmi.bmiHeader.biHeight; shape_data_->mask = Fl_Image_Surface_Driver::RGB3_to_RGB1(mask, W, H); // duplicate current offscreen content to new offscreen int line_size = ((3*W+3)/4) * 4; uchar *dib = new uchar[line_size * H]; // create temporary buffer to read DIB bmi.bmiHeader.biWidth = W; bmi.bmiHeader.biHeight = H; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biBitCount = 24; GetDIBits(gc, (HBITMAP)offscreen, 0, H, dib, &bmi, DIB_RGB_COLORS); HDC background_gc = CreateCompatibleDC(gc); shape_data_->background = CreateDIBSection(background_gc, &bmi, DIB_RGB_COLORS, (void**)&shape_data_->vBits, NULL, 0); if (!shape_data_->background) { Fl::error("CreateDIBSection error=%lu", GetLastError()); } memcpy(shape_data_->vBits, dib, H * line_size); delete[] dib; DeleteDC(background_gc); DeleteDC(gc); } fltk-1.4.3/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx0000644000175000017500000000647615004135251023373 0ustar albrechtalbrecht// // Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_GDI_Graphics_Driver_arci.cxx \brief Utility functions for drawing circles using integers */ // "integer" circle drawing functions. These draw the limited // circle types provided by X and NT graphics. The advantage of // these is that small ones draw quite nicely (probably due to stored // hand-drawn bitmaps of small circles!) and may be implemented by // hardware and thus are fast. #include "Fl_GDI_Graphics_Driver.H" #include #include void Fl_GDI_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) { if (w <= 0 || h <= 0) return; w++; h++; int xa = int( x+w/2+int(w*cos(a1/180.0*M_PI)) ); int ya = int( y+h/2-int(h*sin(a1/180.0*M_PI)) ); int xb = int( x+w/2+int(w*cos(a2/180.0*M_PI)) ); int yb = int( y+h/2-int(h*sin(a2/180.0*M_PI)) ); if (fabs(a1 - a2) < 90) { if (xa == xb && ya == yb) SetPixel(gc_, xa, ya, fl_RGB()); else Arc(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb); } else Arc(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb); } void Fl_GDI_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1, double a2) { if (w <= 0 || h <= 0) return; if (a1 == a2) return; x++; y++; w--; h--; if (scale() >= 3) {x++; y++; w-=2; h-=2;} int xa = int( x+w/2+int(w*cos(a1/180.0*M_PI)) ); int ya = int( y+h/2-int(h*sin(a1/180.0*M_PI)) ); int xb = int( x+w/2+int(w*cos(a2/180.0*M_PI)) ); int yb = int( y+h/2-int(h*sin(a2/180.0*M_PI)) ); SelectObject(gc_, fl_brush()); if (fabs(a1 - a2) < 90) { if (xa == xb && ya == yb) { MoveToEx(gc_, int(x+w/2), int(y+h/2), 0L); LineTo(gc_, xa, ya); SetPixel(gc_, xa, ya, fl_RGB()); } else Pie(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb); } else Pie(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb); } #if USE_GDIPLUS void Fl_GDIplus_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) { if (w <= 0 || h <= 0) return; if (!active) return Fl_GDI_Graphics_Driver::arc_unscaled(x, y, w, h, a1, a2); Gdiplus::Graphics graphics_(gc_); pen_->SetColor(gdiplus_color_); Gdiplus::REAL oldw = pen_->GetWidth(); Gdiplus::REAL new_w = (line_width_ <= scale() ? 1 : line_width_) * scale(); pen_->SetWidth(new_w); graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); graphics_.DrawArc(pen_, x, y, w, h, Gdiplus::REAL(-a1), Gdiplus::REAL(a1-a2)); pen_->SetWidth(oldw); } void Fl_GDIplus_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1, double a2) { if (w <= 0 || h <= 0) return; if (!active) return Fl_GDI_Graphics_Driver::pie_unscaled(x, y, w, h, a1, a2); Gdiplus::Graphics graphics_(gc_); brush_->SetColor(gdiplus_color_); graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); graphics_.FillPie(brush_, x, y, w, h, Gdiplus::REAL(-a1), Gdiplus::REAL(a1-a2)); } #endif fltk-1.4.3/src/drivers/Cocoa/0000755000175000017500000000000015004135251016076 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H0000644000175000017500000000414015004135251023137 0ustar albrechtalbrecht// // Class Fl_Cocoa_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). // // Copyright 2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if HAVE_GL #include #include "../../Fl_Gl_Window_Driver.H" class Fl_Gl_Choice; #ifdef __OBJC__ @class NSOpenGLContext; #else class NSOpenGLContext; #endif class Fl_Cocoa_Gl_Window_Driver : public Fl_Gl_Window_Driver { NSOpenGLContext *gl1ctxt; // GL1 context in addition to GL3 context friend Fl_Gl_Window_Driver* Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *); Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win); float pixels_per_unit() FL_OVERRIDE; void before_show(int& need_after) FL_OVERRIDE; void after_show() FL_OVERRIDE; int mode_(int m, const int *a) FL_OVERRIDE; void make_current_before() FL_OVERRIDE; void swap_buffers() FL_OVERRIDE; void resize(int is_a_resize, int w, int h) FL_OVERRIDE; char swap_type() FL_OVERRIDE; void swap_interval(int) FL_OVERRIDE; int swap_interval() const FL_OVERRIDE; Fl_Gl_Choice *find(int m, const int *alistp) FL_OVERRIDE; GLContext create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) FL_OVERRIDE; void set_gl_context(Fl_Window* w, GLContext context) FL_OVERRIDE; void delete_gl_context(GLContext) FL_OVERRIDE; void make_overlay_current() FL_OVERRIDE; void redraw_overlay() FL_OVERRIDE; void gl_start() FL_OVERRIDE; char *alpha_mask_for_string(const char *str, int n, int w, int h, Fl_Fontsize fs) FL_OVERRIDE; Fl_RGB_Image* capture_gl_rectangle(int x, int y, int w, int h) FL_OVERRIDE; bool need_scissor() FL_OVERRIDE { return true; } void* GetProcAddress(const char *procName) FL_OVERRIDE; void apply_scissor(); void switch_to_GL1() FL_OVERRIDE; void switch_back() FL_OVERRIDE; }; #endif // HAVE_GL fltk-1.4.3/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx0000644000175000017500000004177015004135251023112 0ustar albrechtalbrecht// // Definition of Apple Cocoa Screen interface. // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Cocoa_Screen_Driver.H" #include "Fl_Cocoa_Window_Driver.H" #include "../Quartz/Fl_Font.H" #include #include #include #include #include #include #include extern "C" void NSBeep(void); extern void (*fl_lock_function)(); extern void (*fl_unlock_function)(); int Fl_Cocoa_Screen_Driver::next_marked_length = 0; // This key table is used for the Darwin system driver. It is defined here // "static" and assigned in the constructor to avoid static initialization // race conditions. It is used in fl_shortcut.cxx. // // This table must be in numeric order by fltk (X) keysym number: Fl_Screen_Driver::Keyname darwin_key_table[] = { // v - this column may contain UTF-8 characters {' ', "Space"}, {FL_BackSpace, "⌫"/*"\xe2\x8c\xab"*/}, // U+232B : erase to the left {FL_Tab, "⇥"/*"\xe2\x87\xa5"*/}, // U+21E5 rightwards arrow to bar {FL_Enter, "↩"/*"\xe2\x86\xa9"*/}, // U+21A9 leftwards arrow with hook {FL_Pause, "Pause"}, {FL_Scroll_Lock, "Scroll_Lock"}, {FL_Escape, "⎋"/*"\xe2\x8e\x8b"*/}, // U+238B : broken circle with northwest arrow {FL_Home, "↖"/*"\xe2\x86\x96"*/}, // U+2196 north west arrow {FL_Left, "←"/*"\xe2\x86\x90"*/}, // U+2190 leftwards arrow {FL_Up, "↑"/*"\xe2\x86\x91"*/}, // U+2191 upwards arrow {FL_Right, "→"/*"\xe2\x86\x92"*/}, // U+2192 rightwards arrow {FL_Down, "↓"/*"\xe2\x86\x93"*/}, // U+2193 downwards arrow {FL_Page_Up, "⇞"/*"\xe2\x87\x9e"*/}, // U+21DE upwards arrow with double stroke {FL_Page_Down, "⇟"/*"\xe2\x87\x9f"*/}, // U+21DF downwards arrow with double stroke {FL_End, "↘"/*"\xe2\x86\x98"*/}, // U+2198 south east arrow {FL_Print, "Print"}, {FL_Insert, "Insert"}, {FL_Menu, "Menu"}, {FL_Num_Lock, "Num_Lock"}, {FL_KP_Enter, "⌤"/*"\xe2\x8c\xa4"*/}, // U+2324 up arrow head between two horizontal bars {FL_Shift_L, "Shift_L"}, {FL_Shift_R, "Shift_R"}, {FL_Control_L, "Control_L"}, {FL_Control_R, "Control_R"}, {FL_Caps_Lock, "⇪"/*"\xe2\x87\xaa"*/}, // U+21EA upwards white arrow from bar {FL_Meta_L, "Meta_L"}, {FL_Meta_R, "Meta_R"}, {FL_Alt_L, "Alt_L"}, {FL_Alt_R, "Alt_R"}, {FL_Delete, "⌦"/*"\xe2\x8c\xa6"*/} // U+2326 : erase to the right }; static Fl_Text_Editor::Key_Binding extra_bindings[] = { // Define CMD+key accelerators... { 'z', FL_COMMAND, Fl_Text_Editor::kf_undo ,0}, { 'z', FL_COMMAND|FL_SHIFT, Fl_Text_Editor::kf_redo ,0}, { 'x', FL_COMMAND, Fl_Text_Editor::kf_cut ,0}, { 'c', FL_COMMAND, Fl_Text_Editor::kf_copy ,0}, { 'v', FL_COMMAND, Fl_Text_Editor::kf_paste ,0}, { 'a', FL_COMMAND, Fl_Text_Editor::kf_select_all ,0}, { FL_Left, FL_COMMAND, Fl_Text_Editor::kf_meta_move ,0}, { FL_Right, FL_COMMAND, Fl_Text_Editor::kf_meta_move ,0}, { FL_Up, FL_COMMAND, Fl_Text_Editor::kf_meta_move ,0}, { FL_Down, FL_COMMAND, Fl_Text_Editor::kf_meta_move ,0}, { FL_Left, FL_COMMAND|FL_SHIFT, Fl_Text_Editor::kf_m_s_move ,0}, { FL_Right, FL_COMMAND|FL_SHIFT, Fl_Text_Editor::kf_m_s_move ,0}, { FL_Up, FL_COMMAND|FL_SHIFT, Fl_Text_Editor::kf_m_s_move ,0}, { FL_Down, FL_COMMAND|FL_SHIFT, Fl_Text_Editor::kf_m_s_move ,0}, { 0, 0, 0 ,0} }; Fl_Cocoa_Screen_Driver::Fl_Cocoa_Screen_Driver() { text_editor_extra_key_bindings = extra_bindings; scale_ = 1.; default_icon = nil; // initialize key table key_table = darwin_key_table; key_table_size = sizeof(darwin_key_table)/sizeof(*darwin_key_table); } void Fl_Cocoa_Screen_Driver::init() { open_display(); CGDirectDisplayID displays[MAX_SCREENS]; CGDisplayCount count, i; CGRect r; CGGetActiveDisplayList(MAX_SCREENS, displays, &count); for( i = 0; i < count; i++) { r = CGDisplayBounds(displays[i]); screens[i].x = int(r.origin.x); screens[i].y = int(r.origin.y); screens[i].width = int(r.size.width); screens[i].height = int(r.size.height); //fprintf(stderr,"screen %d %dx%dx%dx%d\n",i,screens[i].x,screens[i].y,screens[i].width,screens[i].height); if (&CGDisplayScreenSize != NULL) { CGSize s = CGDisplayScreenSize(displays[i]); // from 10.3 dpi_h[i] = screens[i].width / (s.width/25.4); dpi_v[i] = screens[i].height / (s.height/25.4); } else { dpi_h[i] = dpi_v[i] = 75.; } } num_screens = count; } void Fl_Cocoa_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n) { if (num_screens < 0) init(); if ((n < 0) || (n >= num_screens)) n = 0; float s = scale(0); X = screens[n].x/s; Y = screens[n].y/s; W = screens[n].width/s; H = screens[n].height/s; } void Fl_Cocoa_Screen_Driver::screen_dpi(float &h, float &v, int n) { if (num_screens < 0) init(); h = v = 0.0f; if (n >= 0 && n < num_screens) { h = dpi_h[n]; v = dpi_v[n]; } } // Implements fl_beep(). See documentation in src/fl_ask.cxx. void Fl_Cocoa_Screen_Driver::beep(int type) { switch (type) { case FL_BEEP_DEFAULT : case FL_BEEP_ERROR : NSBeep(); break; default : break; } } extern void fl_fix_focus(); // in Fl.cxx extern void *fl_capture; void Fl_Cocoa_Screen_Driver::grab(Fl_Window* win) { if (win) { if (!Fl::grab_) { fl_capture = (FLWindow*)(Fl_X::flx(Fl::first_window())->xid); Fl_Cocoa_Window_Driver::driver(Fl::first_window())->set_key_window(); } Fl::grab_ = win; } else { if (Fl::grab_) { fl_capture = 0; Fl::grab_ = 0; fl_fix_focus(); } } } static void set_selection_color(uchar r, uchar g, uchar b) { Fl::set_color(FL_SELECTION_COLOR,r,g,b); } // MacOS X currently supports two color schemes - Blue and Graphite. // Since we aren't emulating the Aqua interface (even if Apple would // let us), we use some defaults that are similar to both. The // Fl::scheme("plastic") color/box scheme provides a usable Aqua-like // look-n-feel... void Fl_Cocoa_Screen_Driver::get_system_colors() { open_display(); Fl_Screen_Driver::get_system_colors(); if (!bg2_set) Fl::background2(0xff, 0xff, 0xff); if (!fg_set) Fl::foreground(0, 0, 0); if (!bg_set) Fl::background(0xd8, 0xd8, 0xd8); #if 0 // this would be the correct code, but it does not run on all versions // of OS X. Also, setting a bright selection color would require // some updates in Fl_Adjuster and Fl_Help_Browser OSStatus err; RGBColor c; err = GetThemeBrushAsColor(kThemeBrushPrimaryHighlightColor, 24, true, &c); if (err) set_selection_color(0x00, 0x00, 0x80); else set_selection_color(c.red, c.green, c.blue); #else set_selection_color(0x00, 0x00, 0x80); #endif } int Fl_Cocoa_Screen_Driver::has_marked_text() const { return 1; } int Fl_Cocoa_Screen_Driver::insertion_point_x = 0; int Fl_Cocoa_Screen_Driver::insertion_point_y = 0; int Fl_Cocoa_Screen_Driver::insertion_point_height = 0; bool Fl_Cocoa_Screen_Driver::insertion_point_location_is_valid = false; void Fl_Cocoa_Screen_Driver::reset_marked_text() { Fl::compose_state = 0; next_marked_length = 0; insertion_point_location_is_valid = false; } // computes window coordinates & height of insertion point int Fl_Cocoa_Screen_Driver::insertion_point_location(int *px, int *py, int *pheight) // return true if the current coordinates of the insertion point are available { if ( ! insertion_point_location_is_valid ) return false; *px = insertion_point_x; *py = insertion_point_y; *pheight = insertion_point_height; return true; } void Fl_Cocoa_Screen_Driver::insertion_point_location(int x, int y, int height) { insertion_point_location_is_valid = true; insertion_point_x = x; insertion_point_y = y; insertion_point_height = height; } int Fl_Cocoa_Screen_Driver::compose(int &del) { int condition; int has_text_key = Fl::compose_state || Fl::e_keysym <= '~' || Fl::e_keysym == FL_Iso_Key || Fl::e_keysym == FL_JIS_Underscore || Fl::e_keysym == FL_Yen || (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last && Fl::e_keysym != FL_KP_Enter); condition = Fl::e_state&(FL_META | FL_CTRL) || (Fl::e_keysym >= FL_Shift_L && Fl::e_keysym <= FL_Alt_R) || // called from flagsChanged !has_text_key ; if (condition) { del = 0; return 0;} // this stuff is to be treated as a function key del = Fl::compose_state; Fl::compose_state = next_marked_length; return 1; } int Fl_Cocoa_Screen_Driver::input_widget_handle_key(int key, unsigned mods, unsigned shift, Fl_Input *input) { switch (key) { case FL_Delete: { if (mods==0) return input->kf_delete_char_right(); // Delete (OSX-HIG,TE,SA,WOX) if (mods==FL_CTRL) return input->kf_delete_char_right(); // Ctrl-Delete (??? TE,!SA,!WOX) if (mods==FL_ALT) return input->kf_delete_word_right(); // Alt-Delete (OSX-HIG,TE,SA) return 0; // ignore other combos, pass to parent } case FL_Left: if (mods==0) return input->kf_move_char_left(); // Left (OSX-HIG) if (mods==FL_ALT) return input->kf_move_word_left(); // Alt-Left (OSX-HIG) if (mods==FL_META) return input->kf_move_sol(); // Meta-Left (OSX-HIG) if (mods==FL_CTRL) return input->kf_move_sol(); // Ctrl-Left (TE/SA) return 0; // ignore other combos, pass to parent case FL_Right: if (mods==0) return input->kf_move_char_right(); // Right (OSX-HIG) if (mods==FL_ALT) return input->kf_move_word_right(); // Alt-Right (OSX-HIG) if (mods==FL_META) return input->kf_move_eol(); // Meta-Right (OSX-HIG) if (mods==FL_CTRL) return input->kf_move_eol(); // Ctrl-Right (TE/SA) return 0; // ignore other combos, pass to parent case FL_Up: if (mods==0) return input->kf_lines_up(1); // Up (OSX-HIG) if (mods==FL_CTRL) return input->kf_page_up(); // Ctrl-Up (TE !HIG) if (mods==FL_ALT) return input->kf_move_up_and_sol(); // Alt-Up (OSX-HIG) if (mods==FL_META) return input->kf_top(); // Meta-Up (OSX-HIG) return 0; // ignore other combos, pass to parent case FL_Down: if (mods==0) return input->kf_lines_down(1); // Dn (OSX-HIG) if (mods==FL_CTRL) return input->kf_page_down(); // Ctrl-Dn (TE !HIG) if (mods==FL_ALT) return input->kf_move_down_and_eol(); // Alt-Dn (OSX-HIG) if (mods==FL_META) return input->kf_bottom(); // Meta-Dn (OSX-HIG) return 0; // ignore other combos, pass to parent case FL_Page_Up: // Fl_Input has no scroll control, so instead we move the cursor by one page // OSX-HIG recommends Alt increase one semantic unit, Meta next higher.. if (mods==0) return input->kf_page_up(); // PgUp (OSX-HIG) if (mods==FL_ALT) return input->kf_page_up(); // Alt-PageUp (OSX-HIG) if (mods==FL_META) return input->kf_top(); // Meta-PageUp (OSX-HIG,!TE) return 0; // ignore other combos, pass to parent case FL_Page_Down: // Fl_Input has no scroll control, so instead we move the cursor by one page // OSX-HIG recommends Alt increase one semantic unit, Meta next higher.. if (mods==0) return input->kf_page_down(); // PgDn (OSX-HIG) if (mods==FL_ALT) return input->kf_page_down(); // Alt-PageDn (OSX-HIG) if (mods==FL_META) return input->kf_bottom(); // Meta-PageDn (OSX-HIG,!TE) return 0; // ignore other combos, pass to parent case FL_Home: if (mods==0) return input->kf_top(); // Home (OSX-HIG) if (mods==FL_ALT) return input->kf_top(); // Alt-Home (???) return 0; // ignore other combos, pass to parent case FL_End: if (mods==0) return input->kf_bottom(); // End (OSX-HIG) if (mods==FL_ALT) return input->kf_bottom(); // Alt-End (???) return 0; // ignore other combos, pass to parent case FL_BackSpace: if (mods==0) return input->kf_delete_char_left(); // Backspace (OSX-HIG) if (mods==FL_CTRL) return input->kf_delete_char_left(); // Ctrl-Backspace (TE/SA) if (mods==FL_ALT) return input->kf_delete_word_left(); // Alt-Backspace (OSX-HIG) if (mods==FL_META) return input->kf_delete_sol(); // Meta-Backspace (OSX-HIG,!TE) return 0; // ignore other combos, pass to parent } return -1; } void Fl_Cocoa_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &height) { width = (int)CGBitmapContextGetWidth((CGContextRef)off); height = (int)CGBitmapContextGetHeight((CGContextRef)off); } Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *window, bool may_capture_subwins, bool *did_capture_subwins) { int bpp, bpr; uchar *base, *p; if (!window) { // read from offscreen buffer float s = 1; CGContextRef src = (CGContextRef)Fl_Surface_Device::surface()->driver()->gc(); // get bitmap context base = (uchar *)CGBitmapContextGetData(src); // get data if(!base) return NULL; int sw = (int)CGBitmapContextGetWidth(src); int sh = (int)CGBitmapContextGetHeight(src); if( (sw - X < w) || (sh - Y < h) ) return NULL; bpr = (int)CGBitmapContextGetBytesPerRow(src); bpp = (int)CGBitmapContextGetBitsPerPixel(src)/8; Fl_Image_Surface *imgs = (Fl_Image_Surface*)Fl_Surface_Device::surface(); int fltk_w, fltk_h; imgs->printable_rect(&fltk_w, &fltk_h); s = sw / float(fltk_w); X *= s; Y *= s; w *= s; h *= s; if (X + w > sw) w = sw - X; if (Y + h > sh) h = sh - Y; // Copy the image from the off-screen buffer to the memory buffer. int idx, idy; // Current X & Y in image uchar *pdst, *psrc; p = new uchar[w * h * 4]; for (idy = Y, pdst = p; idy < h + Y; idy ++) { for (idx = 0, psrc = base + idy * bpr + X * bpp; idx < w; idx ++, psrc += bpp, pdst += 4) { pdst[0] = psrc[0]; // R pdst[1] = psrc[1]; // G pdst[2] = psrc[2]; // B } } bpr = 0; } else { // read from window Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(window); CGImageRef cgimg = d->CGImage_from_window_rect(X, Y, w, h, may_capture_subwins); if (did_capture_subwins) *did_capture_subwins = may_capture_subwins; if (!cgimg) { return NULL; } w = (int)CGImageGetWidth(cgimg); h = (int)CGImageGetHeight(cgimg); Fl_Image_Surface *surf = new Fl_Image_Surface(w, h); Fl_Surface_Device::push_current(surf); ((Fl_Quartz_Graphics_Driver*)fl_graphics_driver)->draw_CGImage(cgimg, 0, 0, w, h, 0, 0, w, h); CGContextRef gc = (CGContextRef)fl_graphics_driver->gc(); w = (int)CGBitmapContextGetWidth(gc); h = (int)CGBitmapContextGetHeight(gc); bpr = (int)CGBitmapContextGetBytesPerRow(gc); bpp = (int)CGBitmapContextGetBitsPerPixel(gc)/8; base = (uchar*)CGBitmapContextGetData(gc); p = new uchar[bpr * h]; memcpy(p, base, bpr * h); Fl_Surface_Device::pop_current(); delete surf; CFRelease(cgimg); } Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, 4, bpr); rgb->alloc_array = 1; return rgb; } void Fl_Cocoa_Screen_Driver::set_spot(int /*font*/, int size, int X, int Y, int /*W*/, int /*H*/, Fl_Window* /*win*/) { Fl_Cocoa_Screen_Driver::insertion_point_location(X, Y, size); } void Fl_Cocoa_Screen_Driver::reset_spot() { Fl_Cocoa_Screen_Driver::reset_marked_text(); } fltk-1.4.3/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H0000644000175000017500000000746315004135251022500 0ustar albrechtalbrecht// // Definition of Apple Cocoa Screen interface // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Cocoa_Screen_Driver.H \brief Definition of Apple Cocoa Screen interface. */ #ifndef FL_COCOA_SCREEN_DRIVER_H #define FL_COCOA_SCREEN_DRIVER_H #include "../../Fl_Screen_Driver.H" /* Move everything here that manages the native screen interface. There is exactly one screen driver in the system. - screen configuration and sizes - multiple screens - native dialog boxes */ class Fl_Window; class Fl_Input; class Fl_RGB_Image; #ifdef __OBJC__ @class NSImage; #else class NSImage; #endif class Fl_Cocoa_Screen_Driver : public Fl_Screen_Driver { protected: struct XRectangle {int x, y, width, height;}; XRectangle screens[MAX_SCREENS]; float dpi_h[MAX_SCREENS]; float dpi_v[MAX_SCREENS]; static int insertion_point_x; static int insertion_point_y; static int insertion_point_height; static bool insertion_point_location_is_valid; public: NSImage *default_icon; Fl_Cocoa_Screen_Driver(); static int next_marked_length; // next length of marked text after current marked text will have been replaced static void breakMacEventLoop(); // --- display management // --- screen configuration void init() FL_OVERRIDE; int x() FL_OVERRIDE; int y() FL_OVERRIDE; int w() FL_OVERRIDE; int h() FL_OVERRIDE; void screen_xywh(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; void screen_dpi(float &h, float &v, int n=0) FL_OVERRIDE; // implemented in Fl_cocoa.mm because uses Objective-c void screen_work_area(int &X, int &Y, int &W, int &H, int n) FL_OVERRIDE; // --- audible output void beep(int type) FL_OVERRIDE; // --- global events void grab(Fl_Window* win) FL_OVERRIDE; // --- global colors void get_system_colors() FL_OVERRIDE; int has_marked_text() const FL_OVERRIDE; static void reset_marked_text(); static void insertion_point_location(int x, int y, int height); static int insertion_point_location(int *px, int *py, int *pheight); int dnd(int use_selection) FL_OVERRIDE; int compose(int &del) FL_OVERRIDE; int input_widget_handle_key(int key, unsigned mods, unsigned shift, Fl_Input *input) FL_OVERRIDE; int get_mouse(int &x, int &y) FL_OVERRIDE; void enable_im() FL_OVERRIDE; void disable_im() FL_OVERRIDE; void open_display_platform() FL_OVERRIDE; // --- compute dimensions of an Fl_Offscreen void offscreen_size(Fl_Offscreen o, int &width, int &height) FL_OVERRIDE; APP_SCALING_CAPABILITY rescalable() FL_OVERRIDE { return SYSTEMWIDE_APP_SCALING; } float scale(int /*nscreen*/) FL_OVERRIDE {return scale_;} void scale(int /*nscreen*/, float f) FL_OVERRIDE { scale_ = f;} Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins) FL_OVERRIDE; void default_icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE; void copy(const char *stuff, int len, int clipboard, const char *type) FL_OVERRIDE; void paste(Fl_Widget &receiver, int clipboard, const char *type) FL_OVERRIDE; int clipboard_contains(const char *type) FL_OVERRIDE; void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) FL_OVERRIDE; void reset_spot() FL_OVERRIDE; int need_menu_handle_part2() FL_OVERRIDE {return 1;} // these 2 are in Fl_get_key_mac.cxx int event_key(int) FL_OVERRIDE; int get_key(int) FL_OVERRIDE; private: float scale_; }; #endif // FL_COCOA_SCREEN_DRIVER_H fltk-1.4.3/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm0000644000175000017500000004521515004135251023123 0ustar albrechtalbrecht// // Mac OS X-specific printing support (objective-c++) for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "../../Fl_Window_Driver.H" #include "../../Fl_Screen_Driver.H" #include "../Quartz/Fl_Quartz_Graphics_Driver.H" #include "../Darwin/Fl_Darwin_System_Driver.H" #include #include "Fl_Cocoa_Window_Driver.H" #include #include #include #include #include #import typedef OSStatus (*PMSessionSetDocumentFormatGeneration_type)( PMPrintSession printSession, CFStringRef docFormat, CFArrayRef graphicsContextTypes, CFTypeRef options); typedef OSStatus (*PMSessionBeginDocumentNoDialog_type)( PMPrintSession printSession, PMPrintSettings printSettings, PMPageFormat pageFormat); typedef OSStatus (*PMSessionGetGraphicsContext_type)( PMPrintSession printSession, CFStringRef graphicsContextType, void ** graphicsContext); /** Support for printing on the Apple OS X platform */ class Fl_Cocoa_Printer_Driver : public Fl_Paged_Device { friend class Fl_Printer; protected: float scale_x; float scale_y; float angle; // rotation angle in radians PMPrintSession printSession; PMPageFormat pageFormat; PMPrintSettings printSettings; Fl_Cocoa_Printer_Driver(void); int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message = NULL) FL_OVERRIDE; int begin_page (void) FL_OVERRIDE; int printable_rect(int *w, int *h) FL_OVERRIDE; void margins(int *left, int *top, int *right, int *bottom) FL_OVERRIDE; void origin(int *x, int *y) FL_OVERRIDE; void origin(int x, int y) FL_OVERRIDE; void scale (float scale_x, float scale_y = 0.) FL_OVERRIDE; void rotate(float angle) FL_OVERRIDE; void translate(int x, int y) FL_OVERRIDE; void untranslate(void) FL_OVERRIDE; int end_page (void) FL_OVERRIDE; void end_job (void) FL_OVERRIDE; ~Fl_Cocoa_Printer_Driver(void); }; Fl_Cocoa_Printer_Driver::Fl_Cocoa_Printer_Driver(void) { x_offset = 0; y_offset = 0; scale_x = scale_y = 1.; driver(new Fl_Quartz_Printer_Graphics_Driver); } Fl_Paged_Device* Fl_Printer::newPrinterDriver(void) { return new Fl_Cocoa_Printer_Driver(); } Fl_Cocoa_Printer_Driver::~Fl_Cocoa_Printer_Driver(void) { delete driver(); } @interface print_panel_delegate : NSObject - (void)printPanelDidEnd:(NSPrintPanel *)printPanel returnCode:(NSInteger)returnCode contextInfo:(NSInteger *)contextInfo; @end @implementation print_panel_delegate - (void)printPanelDidEnd:(NSPrintPanel *)printPanel returnCode:(NSInteger)returnCode contextInfo:(NSInteger *)contextInfo { *contextInfo = returnCode; } @end int Fl_Cocoa_Printer_Driver::begin_job (int pagecount, int *frompage, int *topage, char **perr_message) //printing using a Quartz graphics context //returns 0 iff OK { OSStatus status = 0; fl_open_display(); Fl_Cocoa_Window_Driver::q_release_context(); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (fl_mac_os_version >= 100500) { NSPrintInfo *info = [NSPrintInfo sharedPrintInfo]; NSPrintPanel *panel = [NSPrintPanel printPanel]; //from 10.5 [panel setOptions:NSPrintPanelShowsCopies | NSPrintPanelShowsPageRange | NSPrintPanelShowsPageSetupAccessory | NSPrintPanelShowsOrientation | NSPrintPanelShowsPaperSize]; NSInteger retval = -1; Fl_Window *top = Fl::first_window(); NSWindow *main = (top ? (NSWindow*)fl_xid(top->top_window()) : nil); if (main) { [panel beginSheetWithPrintInfo:info modalForWindow:main delegate:[[[print_panel_delegate alloc] init] autorelease] didEndSelector:@selector(printPanelDidEnd:returnCode:contextInfo:) contextInfo:&retval]; while (retval < 0) Fl::wait(100); [main makeKeyAndOrderFront:nil]; } else retval = [panel runModalWithPrintInfo:info]; //from 10.5 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9 const NSInteger NSModalResponseOK = NSOKButton; #endif if (retval != NSModalResponseOK) return 1; printSession = (PMPrintSession)[info PMPrintSession];//from 10.5 pageFormat = (PMPageFormat)[info PMPageFormat];//from 10.5 printSettings = (PMPrintSettings)[info PMPrintSettings];//from 10.5 UInt32 from32, to32; PMGetFirstPage(printSettings, &from32); if (frompage) *frompage = (int)from32; PMGetLastPage(printSettings, &to32); if (topage) { *topage = (int)to32; if (*topage > pagecount && pagecount > 0) *topage = pagecount; } status = PMSessionBeginCGDocumentNoDialog(printSession, printSettings, pageFormat);//from 10.4 } else #endif { #if !defined(__LP64__) || !__LP64__ Boolean accepted; status = PMCreateSession(&printSession); if (status != noErr) return 1; status = PMCreatePageFormat(&pageFormat); status = PMSessionDefaultPageFormat(printSession, pageFormat); if (status != noErr) return 1; // get pointer to the PMSessionPageSetupDialog Carbon function typedef OSStatus (*dialog_f)(PMPrintSession, PMPageFormat, Boolean *); static dialog_f f = NULL; if (!f) f = (dialog_f)Fl_Darwin_System_Driver::get_carbon_function("PMSessionPageSetupDialog"); status = (*f)(printSession, pageFormat, &accepted); if (status != noErr || !accepted) { Fl::first_window()->show(); return 1; } status = PMCreatePrintSettings(&printSettings); if (status != noErr || printSettings == kPMNoPrintSettings) return 1; status = PMSessionDefaultPrintSettings (printSession, printSettings); if (status != noErr) return 1; PMSetPageRange(printSettings, 1, (UInt32)kPMPrintAllPages); // get pointer to the PMSessionPrintDialog Carbon function typedef OSStatus (*dialog_f2)(PMPrintSession, PMPrintSettings, PMPageFormat, Boolean *); static dialog_f2 f2 = NULL; if (!f2) f2 = (dialog_f2)Fl_Darwin_System_Driver::get_carbon_function("PMSessionPrintDialog"); status = (*f2)(printSession, printSettings, pageFormat, &accepted); if (!accepted) status = kPMCancel; if (status != noErr) { Fl::first_window()->show(); return 1; } UInt32 from32, to32; PMGetFirstPage(printSettings, &from32); if (frompage) *frompage = (int)from32; PMGetLastPage(printSettings, &to32); if (topage) *topage = (int)to32; if(topage && *topage > pagecount) *topage = pagecount; CFStringRef mystring[1]; mystring[0] = kPMGraphicsContextCoreGraphics; CFArrayRef array = CFArrayCreate(NULL, (const void **)mystring, 1, &kCFTypeArrayCallBacks); PMSessionSetDocumentFormatGeneration_type PMSessionSetDocumentFormatGeneration = (PMSessionSetDocumentFormatGeneration_type)Fl_Darwin_System_Driver::get_carbon_function("PMSessionSetDocumentFormatGeneration"); status = PMSessionSetDocumentFormatGeneration(printSession, kPMDocumentFormatDefault, array, NULL); CFRelease(array); PMSessionBeginDocumentNoDialog_type PMSessionBeginDocumentNoDialog = (PMSessionBeginDocumentNoDialog_type)Fl_Darwin_System_Driver::get_carbon_function("PMSessionBeginDocumentNoDialog"); status = PMSessionBeginDocumentNoDialog(printSession, printSettings, pageFormat); #endif //__LP64__ } if (status != noErr) { if (perr_message) { NSError *nserr = [NSError errorWithDomain:NSCocoaErrorDomain code:status userInfo:nil]; NSString *s = [nserr localizedDescription]; if (s) *perr_message = fl_strdup([s UTF8String]); } return 2; } y_offset = x_offset = 0; return 0; } void Fl_Cocoa_Printer_Driver::margins(int *left, int *top, int *right, int *bottom) { PMPaper paper; PMGetPageFormatPaper(pageFormat, &paper); PMOrientation orientation; PMGetOrientation(pageFormat, &orientation); PMPaperMargins margins; PMPaperGetMargins(paper, &margins); if(orientation == kPMPortrait) { if (left) *left = (int)(margins.left / scale_x + 0.5); if (top) *top = (int)(margins.top / scale_y + 0.5); if (right) *right = (int)(margins.right / scale_x + 0.5); if (bottom) *bottom = (int)(margins.bottom / scale_y + 0.5); } else { if (left) *left = (int)(margins.top / scale_x + 0.5); if (top) *top = (int)(margins.left / scale_y + 0.5); if (right) *right = (int)(margins.bottom / scale_x + 0.5); if (bottom) *bottom = (int)(margins.right / scale_y + 0.5); } } int Fl_Cocoa_Printer_Driver::printable_rect(int *w, int *h) //returns 0 iff OK { OSStatus status; PMRect pmRect; int x, y; status = PMGetAdjustedPageRect(pageFormat, &pmRect); if (status != noErr) return 1; x = (int)pmRect.left; y = (int)pmRect.top; *w = int((int)(pmRect.right - x) / scale_x + 1); *h = int((int)(pmRect.bottom - y) / scale_y + 1); return 0; } void Fl_Cocoa_Printer_Driver::origin(int x, int y) { x_offset = x; y_offset = y; CGContextRef gc = (CGContextRef)driver()->gc(); CGContextRestoreGState(gc); CGContextRestoreGState(gc); CGContextSaveGState(gc); CGContextScaleCTM(gc, scale_x, scale_y); CGContextTranslateCTM(gc, x, y); CGContextRotateCTM(gc, angle); CGContextSaveGState(gc); } void Fl_Cocoa_Printer_Driver::scale (float s_x, float s_y) { if (s_y == 0.) s_y = s_x; scale_x = s_x; scale_y = s_y; CGContextRef gc = (CGContextRef)driver()->gc(); CGContextRestoreGState(gc); CGContextRestoreGState(gc); CGContextSaveGState(gc); CGContextScaleCTM(gc, scale_x, scale_y); CGContextRotateCTM(gc, angle); x_offset = y_offset = 0; CGContextSaveGState(gc); } void Fl_Cocoa_Printer_Driver::rotate (float rot_angle) { angle = - rot_angle * M_PI / 180.; CGContextRef gc = (CGContextRef)driver()->gc(); CGContextRestoreGState(gc); CGContextRestoreGState(gc); CGContextSaveGState(gc); CGContextScaleCTM(gc, scale_x, scale_y); CGContextTranslateCTM(gc, x_offset, y_offset); CGContextRotateCTM(gc, angle); CGContextSaveGState(gc); } void Fl_Cocoa_Printer_Driver::translate(int x, int y) { CGContextRef gc = (CGContextRef)driver()->gc(); CGContextSaveGState(gc); CGContextTranslateCTM(gc, x, y ); CGContextSaveGState(gc); } void Fl_Cocoa_Printer_Driver::untranslate(void) { CGContextRef gc = (CGContextRef)driver()->gc(); CGContextRestoreGState(gc); CGContextRestoreGState(gc); } int Fl_Cocoa_Printer_Driver::begin_page (void) { OSStatus status = PMSessionBeginPageNoDialog(printSession, pageFormat, NULL); CGContextRef gc; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if ( &PMSessionGetCGGraphicsContext != NULL ) { status = PMSessionGetCGGraphicsContext(printSession, &gc); } else #endif { #if !defined(__LP64__) || !__LP64__ PMSessionGetGraphicsContext_type PMSessionGetGraphicsContext = (PMSessionGetGraphicsContext_type)Fl_Darwin_System_Driver::get_carbon_function("PMSessionGetGraphicsContext"); status = PMSessionGetGraphicsContext(printSession, NULL, (void **)&gc); #endif } driver()->gc(gc); Fl_Surface_Device::push_current(this); PMRect pmRect; float win_scale_x, win_scale_y; PMPaper paper; PMGetPageFormatPaper(pageFormat, &paper); PMPaperMargins margins; PMPaperGetMargins(paper, &margins); PMOrientation orientation; PMGetOrientation(pageFormat, &orientation); status = PMGetAdjustedPageRect(pageFormat, &pmRect); double h = pmRect.bottom - pmRect.top; x_offset = 0; y_offset = 0; angle = 0; scale_x = scale_y = 1; win_scale_x = win_scale_y = 1; if(orientation == kPMPortrait) CGContextTranslateCTM(gc, margins.left, margins.bottom + h); else CGContextTranslateCTM(gc, margins.top, margins.right + h); CGContextScaleCTM(gc, win_scale_x, - win_scale_y); ((Fl_Quartz_Graphics_Driver*)driver())->quartz_restore_line_style(); CGContextSetShouldAntialias(gc, false); CGContextSaveGState(gc); CGContextSaveGState(gc); fl_line_style(FL_SOLID); fl_window = (FLWindow*)1; // TODO: something better fl_clip_region(0); return status != noErr; } int Fl_Cocoa_Printer_Driver::end_page (void) { CGContextRef gc = (CGContextRef)driver()->gc(); CGContextFlush(gc); CGContextRestoreGState(gc); CGContextRestoreGState(gc); OSStatus status = PMSessionEndPageNoDialog(printSession); gc = NULL; Fl_Surface_Device::pop_current(); return status != noErr; } void Fl_Cocoa_Printer_Driver::end_job (void) { OSStatus status; status = PMSessionError(printSession); if (status != noErr) { fl_alert ("PM Session error %d", (int)status); } PMSessionEndDocumentNoDialog(printSession); #if !defined(__LP64__) || !__LP64__ if (fl_mac_os_version < 100500) { PMRelease(printSettings); PMRelease(pageFormat); PMRelease(printSession); } #endif Fl_Window *w = Fl::first_window(); if (w) w->show(); } void Fl_Cocoa_Printer_Driver::origin(int *x, int *y) { Fl_Paged_Device::origin(x, y); } class Fl_PDF_Cocoa_File_Surface : public Fl_Cocoa_Printer_Driver { public: char *doc_fname; Fl_PDF_Cocoa_File_Surface(); ~Fl_PDF_Cocoa_File_Surface() { if (doc_fname) free(doc_fname); } int begin_job(const char *defaultname, char **perr_message = NULL); int begin_job(int, int*, int *, char **) FL_OVERRIDE {return 1;} // don't use int begin_document(const char* outname, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout, char **perr_message); }; Fl_PDF_Cocoa_File_Surface::Fl_PDF_Cocoa_File_Surface() { driver(new Fl_Quartz_Graphics_Driver()); doc_fname = NULL; } int Fl_PDF_Cocoa_File_Surface::begin_job(const char* defaultfilename, char **perr_message) { OSStatus status = 0; if (fl_mac_os_version < 100900) return 1; Fl_Window *top = Fl::first_window(); NSWindow *main = (top ? (NSWindow*)fl_xid(top->top_window()) : nil); if (!main) return 1; Fl_Cocoa_Window_Driver::q_release_context(); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 && defined(__BLOCKS__) NSPDFInfo *pdf_info = [[NSPDFInfo alloc] init]; // 10.9 NSPDFPanel *pdf_panel = [NSPDFPanel panel]; // 10.9 char buf[FL_PATH_MAX]; strcpy(buf, defaultfilename); fl_filename_setext(buf, sizeof(buf), NULL); [pdf_panel setDefaultFileName:[NSString stringWithUTF8String:buf]]; [pdf_panel setOptions: NSPrintPanelShowsOrientation | NSPrintPanelShowsPaperSize]; NSInteger retval = -1; __block NSInteger complete = -1; [pdf_panel beginSheetWithPDFInfo:pdf_info modalForWindow:main completionHandler:^(NSInteger returnCode) { // this block runs after OK or Cancel was triggered in file dialog complete = returnCode; } ]; while (complete == -1) Fl::wait(100); // loop until end of file dialog retval = complete; [main makeKeyAndOrderFront:nil]; if (retval != NSModalResponseOK) return 1; NSURL *url = [pdf_info URL]; doc_fname = fl_strdup([url fileSystemRepresentation]); NSPrintInfo *pr_info = [NSPrintInfo sharedPrintInfo]; [pr_info takeSettingsFromPDFInfo:pdf_info]; [pdf_info release]; printSession = (PMPrintSession)[pr_info PMPrintSession]; printSettings = (PMPrintSettings)[pr_info PMPrintSettings]; pageFormat = (PMPageFormat)[pr_info PMPageFormat]; status = PMSessionBeginCGDocumentNoDialog(printSession, printSettings, pageFormat);//from 10.4 #endif if (status != noErr) { if (perr_message) { NSError *nserr = [NSError errorWithDomain:NSCocoaErrorDomain code:status userInfo:nil]; NSString *s = [nserr localizedDescription]; if (s) *perr_message = fl_strdup([s UTF8String]); } free(doc_fname); doc_fname = NULL; return 2; } y_offset = x_offset = 0; return 0; } int Fl_PDF_Cocoa_File_Surface::begin_document(const char* outfname, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout, char **perr_message) { OSStatus status = 0; fl_open_display(); if (fl_mac_os_version < 100900) return 1; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 NSPDFInfo *pdf_info = [[NSPDFInfo alloc] init]; // 10.9 doc_fname = fl_strdup(outfname); NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:doc_fname]]; [pdf_info setURL:url]; NSSize psize = {(CGFloat)Fl_Paged_Device::page_formats[format].width, (CGFloat)Fl_Paged_Device::page_formats[format].height}; [pdf_info setPaperSize:psize]; [pdf_info setOrientation:(layout == PORTRAIT ? NSPaperOrientationPortrait : NSPaperOrientationLandscape)]; NSPrintInfo *pr_info = [NSPrintInfo sharedPrintInfo]; [pr_info takeSettingsFromPDFInfo:pdf_info]; [pdf_info release]; printSession = (PMPrintSession)[pr_info PMPrintSession]; printSettings = (PMPrintSettings)[pr_info PMPrintSettings]; pageFormat = (PMPageFormat)[pr_info PMPageFormat]; status = PMSessionBeginCGDocumentNoDialog(printSession, printSettings, pageFormat);//from 10.4 #endif if (status != noErr) { if (perr_message) { NSError *nserr = [NSError errorWithDomain:NSCocoaErrorDomain code:status userInfo:nil]; NSString *s = [nserr localizedDescription]; if (s) *perr_message = fl_strdup([s UTF8String]); } free(doc_fname); doc_fname = NULL; return 2; } y_offset = x_offset = 0; return 0; } Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) { Fl_PDF_Cocoa_File_Surface *surf = new Fl_PDF_Cocoa_File_Surface(); *pfname = (const char**)&surf->doc_fname; return surf; } int Fl_PDF_File_Surface::begin_job(const char* defaultfilename, char **perr_message) { return ((Fl_PDF_Cocoa_File_Surface*)platform_surface_)->begin_job(defaultfilename, perr_message); } int Fl_PDF_File_Surface::begin_document(const char* defaultfilename, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout, char **perr_message) { return ((Fl_PDF_Cocoa_File_Surface*)platform_surface_)->begin_document(defaultfilename, format, layout, perr_message); } fltk-1.4.3/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx0000644000175000017500000002574115004135251023142 0ustar albrechtalbrecht// // Definition of Apple Cocoa window driver. // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Cocoa_Window_Driver.H" #include "../../Fl_Screen_Driver.H" #include "../Quartz/Fl_Quartz_Graphics_Driver.H" #include #include #include #include #include #include #include Fl_Cocoa_Window_Driver::Fl_Cocoa_Window_Driver(Fl_Window *win) : Fl_Window_Driver(win) { cursor = nil; window_flags_ = 0; icon_image = NULL; screen_num_ = 0; shape_data_ = NULL; } void Fl_Cocoa_Window_Driver::take_focus() { set_key_window(); } void Fl_Cocoa_Window_Driver::flush_overlay() { Fl_Overlay_Window *oWindow = pWindow->as_overlay_window(); int erase_overlay = (pWindow->damage()&FL_DAMAGE_OVERLAY) | (overlay() == oWindow); pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY)); if (!oWindow->shown()) return; pWindow->make_current(); // make sure fl_gc is non-zero if (!other_xid) { other_xid = new Fl_Image_Surface(oWindow->w(), oWindow->h(), 1); oWindow->clear_damage(FL_DAMAGE_ALL); } if (oWindow->damage() & ~FL_DAMAGE_EXPOSE) { Fl_X *myi = Fl_X::flx(pWindow); fl_clip_region(myi->region); myi->region = 0; Fl_Surface_Device::push_current(other_xid); draw(); Fl_Surface_Device::pop_current(); } if (erase_overlay) fl_clip_region(0); fl_copy_offscreen(0, 0, oWindow->w(), oWindow->h(), other_xid->offscreen(), 0, 0); if (overlay() == oWindow) oWindow->draw_overlay(); } void Fl_Cocoa_Window_Driver::draw_begin() { if (!Fl_Surface_Device::surface()->driver()->has_feature(Fl_Graphics_Driver::NATIVE)) return; CGContextRef my_gc = (CGContextRef)Fl_Surface_Device::surface()->driver()->gc(); if (shape_data_) { # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (shape_data_->mask && (&CGContextClipToMask != NULL)) { CGContextClipToMask(my_gc, CGRectMake(0,0,w(),h()), shape_data_->mask); // requires Mac OS 10.4 } CGContextSaveGState(my_gc); # endif } } void Fl_Cocoa_Window_Driver::draw_end() { // on OS X, windows have no frame. Before OS X 10.7, to resize a window, we drag the lower right // corner. This code draws a little ribbed triangle for dragging. if (fl_mac_os_version < 100700 && !parent() && is_resizable()) { int minw, minh, maxw, maxh, set; set = pWindow->get_size_range(&minw, &minh, &maxw, &maxh, NULL, NULL, NULL); if (!set || minh != maxh || minw != maxw) { int dx = Fl::box_dw(pWindow->box())-Fl::box_dx(pWindow->box()); int dy = Fl::box_dh(pWindow->box())-Fl::box_dy(pWindow->box()); if (dx<=0) dx = 1; if (dy<=0) dy = 1; int x1 = w()-dx-1, x2 = x1, y1 = h()-dx-1, y2 = y1; Fl_Color c[4] = { pWindow->color(), fl_color_average(pWindow->color(), FL_WHITE, 0.7f), fl_color_average(pWindow->color(), FL_BLACK, 0.6f), fl_color_average(pWindow->color(), FL_BLACK, 0.8f), }; int i; for (i=dx; i<12; i++) { fl_color(c[i&3]); fl_line(x1--, y1, x2, y2--); } } } # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (Fl_Surface_Device::surface()->driver()->has_feature(Fl_Graphics_Driver::NATIVE)) { CGContextRef my_gc = (CGContextRef)Fl_Surface_Device::surface()->driver()->gc(); if (shape_data_) CGContextRestoreGState(my_gc); } # endif } static void MyProviderReleaseData (void *info, const void *data, size_t size) { delete[] (uchar*)data; } // bitwise inversion of all 4-bit quantities static const unsigned char swapped[16] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}; static inline uchar swap_byte(const uchar b) { // reverse the order of bits of byte b: 1->8 becomes 8->1 return (swapped[b & 0xF] << 4) | swapped[b >> 4]; } void Fl_Cocoa_Window_Driver::shape_bitmap_(Fl_Image* b) { shape_data_->shape_ = b; if (b) { // complement mask bits and perform bitwise inversion of all bytes and also reverse top and bottom int bytes_per_row = (b->w() + 7)/8; uchar *from = new uchar[bytes_per_row * b->h()]; for (int i = 0; i < b->h(); i++) { uchar *p = (uchar*)(*b->data()) + bytes_per_row * i; uchar *last = p + bytes_per_row; uchar *q = from + (b->h() - 1 - i) * bytes_per_row; while (p < last) { *q++ = swap_byte(~*p++); } } CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, bytes_per_row * b->h(), MyProviderReleaseData); shape_data_->mask = CGImageMaskCreate(b->w(), b->h(), 1, 1, bytes_per_row, provider, NULL, false); CFRelease(provider); } } void Fl_Cocoa_Window_Driver::shape_alpha_(Fl_Image* img, int offset) { int i, d = img->d(), w = img->w(), h = img->h(); shape_data_->shape_ = img; if (shape_data_->shape_) { // reverse top and bottom and convert to gray scale if img->d() == 3 and complement bits int bytes_per_row = w * d; uchar *from = new uchar[w * h]; for ( i = 0; i < h; i++) { uchar *p = (uchar*)(*img->data()) + bytes_per_row * i + offset; uchar *last = p + bytes_per_row; uchar *q = from + (h - 1 - i) * w; while (p < last) { if (d == 3) { unsigned u = *p++; u += *p++; u += *p++; *q++ = ~(u/3); } else { *q++ = ~(*p); p += d; } } } CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, w * h, MyProviderReleaseData); shape_data_->mask = CGImageMaskCreate(w, h, 8, 8, w, provider, NULL, false); CFRelease(provider); } } void Fl_Cocoa_Window_Driver::shape(const Fl_Image* img) { # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 if (shape_data_) { if (shape_data_->mask) { CGImageRelease(shape_data_->mask); } } else { shape_data_ = new shape_data_type; } memset(shape_data_, 0, sizeof(shape_data_type)); int d = img->d(); if (d && img->count() >= 2) { shape_pixmap_((Fl_Image*)img); shape_data_->shape_ = (Fl_Image*)img; } else if (d == 0) shape_bitmap_((Fl_Image*)img); else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1); else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0); #endif pWindow->border(false); } void Fl_Cocoa_Window_Driver::hide() { Fl_X* ip = Fl_X::flx(pWindow); // MacOS X manages a single pointer per application. Make sure that hiding // a toplevel window will not leave us with some random pointer shape, or // worst case, an invisible pointer if (ip && !parent()) pWindow->cursor(FL_CURSOR_DEFAULT); if ( hide_common() ) return; q_release_context(this); if ( ip->xid == (fl_uintptr_t)fl_window ) fl_window = 0; if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region); destroy((FLWindow*)ip->xid); delete subRect(); delete ip; } int Fl_Cocoa_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data) { if ( (src_x < 0) || (src_y < 0) ) return 1; if ( (src_x+src_w > pWindow->w()) || (src_y+src_h > pWindow->h()) ) return 1; CGImageRef img = CGImage_from_window_rect(src_x, src_y, src_w, src_h); if (!img) return 1; // the current surface is generally the display, but is an Fl_Image_Surface when scrolling an Fl_Overlay_Window Fl_Quartz_Graphics_Driver *qgd = (Fl_Quartz_Graphics_Driver*)Fl_Surface_Device::surface()->driver(); float s = qgd->scale(); qgd->draw_CGImage(img, dest_x, dest_y, (int)lround(s*src_w), (int)lround(s*src_h), 0, 0, src_w, src_h); CFRelease(img); return 0; } static const unsigned mapped_mask = 1; static const unsigned changed_mask = 2; static const unsigned view_resized_mask = 4; static const unsigned through_resize_mask = 8; bool Fl_Cocoa_Window_Driver::mapped_to_retina() { return window_flags_ & mapped_mask; } void Fl_Cocoa_Window_Driver::mapped_to_retina(bool b) { if (b) window_flags_ |= mapped_mask; else window_flags_ &= ~mapped_mask; } bool Fl_Cocoa_Window_Driver::changed_resolution() { return window_flags_ & changed_mask; } void Fl_Cocoa_Window_Driver::changed_resolution(bool b) { if (b) window_flags_ |= changed_mask; else window_flags_ &= ~changed_mask; } bool Fl_Cocoa_Window_Driver::view_resized() { return window_flags_ & view_resized_mask; } void Fl_Cocoa_Window_Driver::view_resized(bool b) { if (b) window_flags_ |= view_resized_mask; else window_flags_ &= ~view_resized_mask; } bool Fl_Cocoa_Window_Driver::through_resize() { return window_flags_ & through_resize_mask; } void Fl_Cocoa_Window_Driver::through_resize(bool b) { if (b) window_flags_ |= through_resize_mask; else window_flags_ &= ~through_resize_mask; } // clip the graphics context to rounded corners void Fl_Cocoa_Window_Driver::clip_to_rounded_corners(CGContextRef gc, int w, int h) { const CGFloat radius = 7.5; CGContextMoveToPoint(gc, 0, 0); CGContextAddLineToPoint(gc, 0, h - radius); CGContextAddArcToPoint(gc, 0, h, radius, h, radius); CGContextAddLineToPoint(gc, w - radius, h); CGContextAddArcToPoint(gc, w, h, w, h - radius, radius); CGContextAddLineToPoint(gc, w, 0); CGContextClip(gc); } const Fl_Image* Fl_Cocoa_Window_Driver::shape() { return shape_data_ ? shape_data_->shape_ : NULL; } /* Returns images of the capture of the window title-bar. On the Mac OS platform, left, bottom and right are returned NULL; top is returned with depth 4. */ void Fl_Cocoa_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) { top = left = bottom = right = NULL; int htop, hleft, hright, hbottom; Fl_Cocoa_Window_Driver::decoration_sizes(&htop, &hleft, &hright, &hbottom); if (htop == 0) return; // when window is fullscreen CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB(); float s = Fl::screen_driver()->scale(screen_num()); int scaled_w = int(w() * s); const int factor = (mapped_to_retina() ? 2 : 1); int data_w = factor * scaled_w, data_h = factor * htop; uchar *rgba = new uchar[4 * data_w * data_h]; CGContextRef auxgc = CGBitmapContextCreate(rgba, data_w, data_h, 8, 4 * data_w, cspace, kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(cspace); CGContextClearRect(auxgc, CGRectMake(0,0,data_w,data_h)); CGContextScaleCTM(auxgc, factor, factor); draw_titlebar_to_context(auxgc, scaled_w, htop); top = new Fl_RGB_Image(rgba, data_w, data_h, 4); top->alloc_array = 1; top->scale(w(),htop, s <1 ? 0 : 1, 1); CGContextRelease(auxgc); } FLWindow *fl_mac_xid(const Fl_Window *win) { return (FLWindow*)Fl_Window_Driver::xid(win); } Fl_Window *fl_mac_find(FLWindow *xid) { return Fl_Window_Driver::find((fl_uintptr_t)xid); } fltk-1.4.3/src/drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H0000644000175000017500000000351215004135251023514 0ustar albrechtalbrecht// // Definition of class Fl_MacOS_Sys_Menu_Bar_Driver for the Fast Light Tool Kit (FLTK). // // Copyright 2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef Fl_MacOS_Sys_Menu_Bar_Driver_H #define Fl_MacOS_Sys_Menu_Bar_Driver_H #include "../../Fl_Sys_Menu_Bar_Driver.H" class Fl_MacOS_Sys_Menu_Bar_Driver : public Fl_Sys_Menu_Bar_Driver { public: Fl_Menu_Item *window_menu_items; int first_window_menu_item; Fl_MacOS_Sys_Menu_Bar_Driver(); virtual ~Fl_MacOS_Sys_Menu_Bar_Driver(); void update() FL_OVERRIDE; void draw() FL_OVERRIDE; void about(Fl_Callback *cb, void *data) FL_OVERRIDE; int add(const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) FL_OVERRIDE; int add(const char* str) FL_OVERRIDE; int insert(int index, const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) FL_OVERRIDE; void menu(const Fl_Menu_Item *m) FL_OVERRIDE; void shortcut (int i, int s) FL_OVERRIDE; void setonly (Fl_Menu_Item *item) FL_OVERRIDE; void clear() FL_OVERRIDE; int clear_submenu(int index) FL_OVERRIDE; void remove(int index) FL_OVERRIDE; void replace(int index, const char *name) FL_OVERRIDE; void mode(int i, int fl) FL_OVERRIDE; void create_window_menu() FL_OVERRIDE; void new_window(Fl_Window *win); void remove_window(Fl_Window *win); void rename_window(Fl_Window *win); static Fl_MacOS_Sys_Menu_Bar_Driver* driver(); void play_menu(const Fl_Menu_Item *) FL_OVERRIDE; }; #endif /* Fl_MacOS_Sys_Menu_Bar_Driver_H */ fltk-1.4.3/src/drivers/Cocoa/Fl_Cocoa_Window_Driver.H0000644000175000017500000001333315004135251022521 0ustar albrechtalbrecht// // Definition of Apple Cocoa window driver // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Cocoa_Window_Driver.H \brief Definition of Apple Cocoa window driver. */ #ifndef FL_COCOA_WINDOW_DRIVER_H #define FL_COCOA_WINDOW_DRIVER_H #include "../../Fl_Window_Driver.H" #include #include class Fl_Image; class Fl_Window; #ifdef __OBJC__ @class CALayer; @class NSCursor; @class NSImage; @class FLWindow; @class NSOpenGLContext; @class NSOpenGLPixelFormat; @class NSView; @class NSWindow; #else class CALayer; class NSCursor; class NSImage; class FLWindow; class NSOpenGLContext; class NSOpenGLPixelFormat; class NSView; class NSWindow; #endif // __OBJC__ /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /* Move everything here that manages the native window interface. There is one window driver for each Fl_Window. Window drivers manage window actions such as resizing, events, decoration, fullscreen modes, etc. . All drawing and rendering is managed by the Surface device and the associated graphics driver. - window specific event handling - window types and styles, depth, etc. - decorations ? where do we handle the interface between OpenGL/DirectX and Cocoa/Windows/Glx? */ /** \} \endcond */ class Fl_Cocoa_Window_Driver : public Fl_Window_Driver { private: struct shape_data_type { Fl_Image* shape_; ///< shape image CGImageRef mask; } *shape_data_; void shape_bitmap_(Fl_Image* b); void shape_alpha_(Fl_Image* img, int offset) FL_OVERRIDE; CGRect* subRect_; // makes sure subwindow remains inside its parent window // stores 3 binary flags: whether window is mapped to retina display; whether resolution just changed; // whether window's view received the [FLView view_did_resize] message unsigned window_flags_; public: Fl_Cocoa_Window_Driver(Fl_Window*); ~Fl_Cocoa_Window_Driver(); static inline Fl_Cocoa_Window_Driver* driver(const Fl_Window *w) {return (Fl_Cocoa_Window_Driver*)Fl_Window_Driver::driver(w);} CGContextRef gc; // graphics context NSCursor *cursor; static void q_release_context(Fl_Cocoa_Window_Driver *x = 0); // free all resources associated with gc static void clip_to_rounded_corners(CGContextRef gc, int w, int h); static CGImageRef capture_decorated_window_10_5(NSWindow *nswin); void set_key_window(); bool mapped_to_retina(); // is window mapped to retina display? void mapped_to_retina(bool); // sets whether window is mapped to retina display bool changed_resolution(); // did window just moved to display with another resolution? void changed_resolution(bool);// sets whether window just moved to display with another resolution bool view_resized(); // did window's view receive [FLView view_did_resize] message? void view_resized(bool b); // sets whether window's view received [FLView view_did_resize] message bool through_resize(); // did Fl_Window::resize() run already void through_resize(bool b); // set whether Fl_Window::resize() run already CGRect* subRect() { return subRect_; } // getter void subRect(CGRect *r) { subRect_ = r; } // setter static void destroy(FLWindow*); CGImageRef CGImage_from_window_rect(int x, int y, int w, int h, bool capture_subwins = true); // --- window data int decorated_w() FL_OVERRIDE; int decorated_h() FL_OVERRIDE; const Fl_Image* shape() FL_OVERRIDE; // --- window management void makeWindow() FL_OVERRIDE; void take_focus() FL_OVERRIDE; void flush() FL_OVERRIDE; void flush_overlay() FL_OVERRIDE; void draw_begin() FL_OVERRIDE; void draw_end() FL_OVERRIDE; void make_current() FL_OVERRIDE; void label(const char *name, const char *mininame) FL_OVERRIDE; void show() FL_OVERRIDE; void resize(int X,int Y,int W,int H) FL_OVERRIDE; void hide() FL_OVERRIDE; void map() FL_OVERRIDE; void unmap() FL_OVERRIDE; void fullscreen_on() FL_OVERRIDE; void fullscreen_off(int X, int Y, int W, int H) FL_OVERRIDE; void fullscreen_screens(bool on_off) FL_OVERRIDE; void maximize() FL_OVERRIDE; void un_maximize() FL_OVERRIDE; void use_border() FL_OVERRIDE; void size_range() FL_OVERRIDE; void iconize() FL_OVERRIDE; void decoration_sizes(int *top, int *left, int *right, int *bottom) FL_OVERRIDE; // --- window cursor stuff int set_cursor(Fl_Cursor) FL_OVERRIDE; int set_cursor(const Fl_RGB_Image*, int, int) FL_OVERRIDE; void shape(const Fl_Image* img) FL_OVERRIDE; // next 4 are in Fl_cocoa.mm because they use Objective-c void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right) FL_OVERRIDE; void wait_for_expose() FL_OVERRIDE; void draw_titlebar_to_context(CGContextRef gc, int w, int h); int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, void (*draw_area)(void*, int,int,int,int), void* data) FL_OVERRIDE; //icons void icons(const Fl_RGB_Image *icons[], int count) FL_OVERRIDE; NSImage *icon_image; fl_uintptr_t os_id() FL_OVERRIDE; }; class Fl_Cocoa_Plugin : public Fl_Plugin { public: Fl_Cocoa_Plugin(const char *pluginName) : Fl_Plugin(klass(), pluginName) { } virtual const char *klass() { return "fltk:cocoa"; } virtual const char *name() = 0; virtual void resize(Fl_Gl_Window *glw, int x, int y, int w, int h) = 0; }; #endif // FL_COCOA_WINDOW_DRIVER_H fltk-1.4.3/src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm0000644000175000017500000004613515004135251023373 0ustar albrechtalbrecht// // Class Fl_Cocoa_Gl_Window_Driver for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if HAVE_GL #include #include #include "../../Fl_Gl_Choice.H" #include "../../Fl_Screen_Driver.H" #include "Fl_Cocoa_Window_Driver.H" #include "Fl_Cocoa_Gl_Window_Driver.H" #include #include #include #include #import /* macOS offers only core contexts when using GL3. This forbids to draw FLTK widgets in a GL3-using NSOpenGLContext because these widgets are drawn with the GL1-based Fl_OpenGL_Graphics_Driver. The solution implemented here is to create an additional NSView and an associated additional NSOpenGLContext (gl1ctxt) placed above and sized as the GL3-based window, to set the new NSOpenGLContext non opaque and GL1-based, and to draw the FLTK widgets in the new view/GL1 context. */ // Describes crap needed to create a GLContext. class Fl_Cocoa_Gl_Choice : public Fl_Gl_Choice { friend class Fl_Cocoa_Gl_Window_Driver; private: NSOpenGLPixelFormat* pixelformat; public: Fl_Cocoa_Gl_Choice(int m, const int *alistp, Fl_Gl_Choice *n) : Fl_Gl_Choice(m, alistp, n) { pixelformat = NULL; } }; Fl_Cocoa_Gl_Window_Driver::Fl_Cocoa_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) { gl1ctxt = NULL; } Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w) { return new Fl_Cocoa_Gl_Window_Driver(w); } static NSOpenGLPixelFormat* mode_to_NSOpenGLPixelFormat(int m, const int *alistp) { NSOpenGLPixelFormatAttribute attribs[32]; int n = 0; // AGL-style code remains commented out for comparison if (!alistp) { if (m & FL_INDEX) { //list[n++] = AGL_BUFFER_SIZE; list[n++] = 8; } else { //list[n++] = AGL_RGBA; //list[n++] = AGL_GREEN_SIZE; //list[n++] = (m & FL_RGB8) ? 8 : 1; attribs[n++] = NSOpenGLPFAColorSize; attribs[n++] = (NSOpenGLPixelFormatAttribute)((m & FL_RGB8) ? 32 : 1); if (m & FL_ALPHA) { //list[n++] = AGL_ALPHA_SIZE; attribs[n++] = NSOpenGLPFAAlphaSize; attribs[n++] = (NSOpenGLPixelFormatAttribute)((m & FL_RGB8) ? 8 : 1); } if (m & FL_ACCUM) { //list[n++] = AGL_ACCUM_GREEN_SIZE; list[n++] = 1; attribs[n++] = NSOpenGLPFAAccumSize; attribs[n++] = (NSOpenGLPixelFormatAttribute)1; if (m & FL_ALPHA) { //list[n++] = AGL_ACCUM_ALPHA_SIZE; list[n++] = 1; } } } if (m & FL_DOUBLE) { //list[n++] = AGL_DOUBLEBUFFER; attribs[n++] = NSOpenGLPFADoubleBuffer; } if (m & FL_DEPTH) { //list[n++] = AGL_DEPTH_SIZE; list[n++] = 24; attribs[n++] = NSOpenGLPFADepthSize; attribs[n++] = (NSOpenGLPixelFormatAttribute)24; } if (m & FL_STENCIL) { //list[n++] = AGL_STENCIL_SIZE; list[n++] = 1; attribs[n++] = NSOpenGLPFAStencilSize; attribs[n++] = (NSOpenGLPixelFormatAttribute)1; } if (m & FL_STEREO) { //list[n++] = AGL_STEREO; attribs[n++] = 6/*NSOpenGLPFAStereo*/; } if ((m & FL_MULTISAMPLE) && fl_mac_os_version >= 100400) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 attribs[n++] = NSOpenGLPFAMultisample; // 10.4 #endif attribs[n++] = NSOpenGLPFASampleBuffers; attribs[n++] = (NSOpenGLPixelFormatAttribute)1; attribs[n++] = NSOpenGLPFASamples; attribs[n++] = (NSOpenGLPixelFormatAttribute)4; } #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 #define NSOpenGLPFAOpenGLProfile (NSOpenGLPixelFormatAttribute)99 #define kCGLPFAOpenGLProfile NSOpenGLPFAOpenGLProfile #define NSOpenGLProfileVersionLegacy (NSOpenGLPixelFormatAttribute)0x1000 #define NSOpenGLProfileVersion3_2Core (NSOpenGLPixelFormatAttribute)0x3200 #define kCGLOGLPVersion_Legacy NSOpenGLProfileVersionLegacy #endif if (fl_mac_os_version >= 100700) { attribs[n++] = NSOpenGLPFAOpenGLProfile; attribs[n++] = (m & FL_OPENGL3) ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy; } } else { while (alistp[n] && n < 30) { if (alistp[n] == kCGLPFAOpenGLProfile) { if (fl_mac_os_version < 100700) { if (alistp[n+1] != kCGLOGLPVersion_Legacy) return nil; n += 2; continue; } } attribs[n] = (NSOpenGLPixelFormatAttribute)alistp[n]; n++; } } attribs[n] = (NSOpenGLPixelFormatAttribute)0; NSOpenGLPixelFormat *pixform = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; /*GLint color,alpha,accum,depth; [pixform getValues:&color forAttribute:NSOpenGLPFAColorSize forVirtualScreen:0]; [pixform getValues:&alpha forAttribute:NSOpenGLPFAAlphaSize forVirtualScreen:0]; [pixform getValues:&accum forAttribute:NSOpenGLPFAAccumSize forVirtualScreen:0]; [pixform getValues:&depth forAttribute:NSOpenGLPFADepthSize forVirtualScreen:0]; NSLog(@"color=%d alpha=%d accum=%d depth=%d",color,alpha,accum,depth);*/ return pixform; } Fl_Gl_Choice *Fl_Cocoa_Gl_Window_Driver::find(int m, const int *alistp) { Fl::screen_driver()->open_display(); // useful when called through gl_start() Fl_Cocoa_Gl_Choice *g = (Fl_Cocoa_Gl_Choice*)Fl_Gl_Window_Driver::find_begin(m, alistp); if (g) return g; NSOpenGLPixelFormat* fmt = mode_to_NSOpenGLPixelFormat(m, alistp); if (!fmt) return 0; g = new Fl_Cocoa_Gl_Choice(m, alistp, first); first = g; g->pixelformat = fmt; return g; } #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 # define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity #endif static void remove_gl_context_opacity(NSOpenGLContext *ctx) { GLint gl_opacity; [ctx getValues:&gl_opacity forParameter:NSOpenGLContextParameterSurfaceOpacity]; if (gl_opacity != 0) { gl_opacity = 0; [ctx setValues:&gl_opacity forParameter:NSOpenGLContextParameterSurfaceOpacity]; } } static NSOpenGLContext *create_GLcontext_for_window( NSOpenGLPixelFormat *pixelformat, NSOpenGLContext *shared_ctx, Fl_Window *window) { NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:pixelformat shareContext:shared_ctx]; if (shared_ctx && !context) context = [[NSOpenGLContext alloc] initWithFormat:pixelformat shareContext:nil]; if (context) { NSView *view = [fl_xid(window) contentView]; if (view && fl_mac_os_version >= 100700) { //replaces [view setWantsBestResolutionOpenGLSurface:YES] without compiler warning typedef void (*bestResolutionIMP)(id, SEL, BOOL); static bestResolutionIMP addr = (bestResolutionIMP)[NSView instanceMethodForSelector:@selector(setWantsBestResolutionOpenGLSurface:)]; addr(view, @selector(setWantsBestResolutionOpenGLSurface:), Fl::use_high_res_GL() != 0); } [context setView:view]; if (Fl_Cocoa_Window_Driver::driver(window)->subRect()) { remove_gl_context_opacity(context); } } return context; } GLContext Fl_Cocoa_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g) { GLContext context, shared_ctx = 0; if (context_list && nContext) shared_ctx = context_list[0]; // resets the pile of string textures used to draw strings // necessary before the first context is created if (!shared_ctx) gl_texture_reset(); context = create_GLcontext_for_window(((Fl_Cocoa_Gl_Choice*)g)->pixelformat, (NSOpenGLContext*)shared_ctx, window); if (!context) return 0; add_context(context); [(NSOpenGLContext*)context makeCurrentContext]; glClearColor(0., 0., 0., 1.); apply_scissor(); return (context); } void Fl_Cocoa_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) { NSOpenGLContext *current_context = [NSOpenGLContext currentContext]; if (context != current_context || w != cached_window) { cached_window = w; [(NSOpenGLContext*)context makeCurrentContext]; } } void Fl_Cocoa_Gl_Window_Driver::delete_gl_context(GLContext context) { NSOpenGLContext *current_context = [NSOpenGLContext currentContext]; if (current_context == context) { cached_window = 0; [current_context clearDrawable]; } [(NSOpenGLContext*)context release]; del_context(context); if (gl1ctxt) { [[gl1ctxt view] release]; [gl1ctxt release]; gl1ctxt = 0; } } void Fl_Cocoa_Gl_Window_Driver::make_overlay_current() { // this is not very useful, but unfortunately, Apple decided // that front buffer drawing can no longer (OS X 10.4) be supported on their platforms. if (pWindow->shown()) pWindow->make_current(); } void Fl_Cocoa_Gl_Window_Driver::redraw_overlay() { pWindow->redraw(); } void Fl_Cocoa_Gl_Window_Driver::before_show(int& need_after) { need_after = 1; } void Fl_Cocoa_Gl_Window_Driver::after_show() { // Makes sure the GL context is created to avoid drawing twice the window when first shown pWindow->make_current(); if ((mode() & FL_OPENGL3) && !gl1ctxt) { // Create transparent GL1 scene above the GL3 scene to hold child widgets and/or text NSView *view = [fl_mac_xid(pWindow) contentView]; NSView *gl1view = [[NSView alloc] initWithFrame:[view frame]]; [gl1view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; static NSOpenGLContext *shared_gl1_ctxt = nil; static NSOpenGLPixelFormat *gl1pixelformat = mode_to_NSOpenGLPixelFormat( FL_RGB8 | FL_ALPHA | FL_SINGLE, NULL); gl1ctxt = [[NSOpenGLContext alloc] initWithFormat:gl1pixelformat shareContext:shared_gl1_ctxt]; if (!shared_gl1_ctxt) { shared_gl1_ctxt = gl1ctxt; [shared_gl1_ctxt retain]; } [view addSubview:gl1view]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if (fl_mac_os_version >= 100700 && Fl::use_high_res_GL()) { [gl1view setWantsBestResolutionOpenGLSurface:YES]; } #endif [gl1ctxt setView:gl1view]; remove_gl_context_opacity(gl1ctxt); } } float Fl_Cocoa_Gl_Window_Driver::pixels_per_unit() { int retina = (fl_mac_os_version >= 100700 && Fl::use_high_res_GL() && Fl_X::flx(pWindow) && Fl_Cocoa_Window_Driver::driver(pWindow)->mapped_to_retina()) ? 2 : 1; return retina * Fl_Graphics_Driver::default_driver().scale(); } int Fl_Cocoa_Gl_Window_Driver::mode_(int m, const int *a) { if (a) { // when the mode is set using the a array of system-dependent values, and if asking for double buffer, // the FL_DOUBLE flag must be set in the mode_ member variable const int *aa = a; while (*aa) { if (*(aa++) == kCGLPFADoubleBuffer ) { m |= FL_DOUBLE; break; } } } pWindow->context(0); mode( m); alist(a); if (pWindow->shown()) { g( find(m, a) ); pWindow->redraw(); } else { g(0); } return 1; } void Fl_Cocoa_Gl_Window_Driver::make_current_before() { // detect if the window was moved between low and high resolution displays Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(pWindow); if (d->changed_resolution()){ d->changed_resolution(false); pWindow->invalidate(); [(NSOpenGLContext*)pWindow->context() update]; } } void Fl_Cocoa_Gl_Window_Driver::swap_buffers() { if (overlay() != NULL) { // STR# 2944 [1] // Save matrixmode/proj/modelview/rasterpos before doing overlay. // int wo = pWindow->pixel_w(), ho = pWindow->pixel_h(); GLint matrixmode; GLfloat pos[4]; glGetIntegerv(GL_MATRIX_MODE, &matrixmode); glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); // save original glRasterPos glMatrixMode(GL_PROJECTION); // save proj/model matrices glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glScalef(2.0f/wo, 2.0f/ho, 1.0f); glTranslatef(-wo/2.0f, -ho/2.0f, 0.0f); // set transform so 0,0 is bottom/left of Gl_Window glRasterPos2i(0,0); // set glRasterPos to bottom left corner { // Emulate overlay by doing copypixels glReadBuffer(GL_BACK); glDrawBuffer(GL_FRONT); glCopyPixels(0, 0, wo, ho, GL_COLOR); // copy GL_BACK to GL_FRONT } glPopMatrix(); // GL_MODELVIEW // restore model/proj matrices glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(matrixmode); glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos } else { [(NSOpenGLContext*)pWindow->context() flushBuffer]; } } char Fl_Cocoa_Gl_Window_Driver::swap_type() {return copy;} #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 # define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval #endif void Fl_Cocoa_Gl_Window_Driver::swap_interval(int n) { GLint interval = (GLint)n; NSOpenGLContext* ctx = (NSOpenGLContext*)pWindow->context(); if (ctx) [ctx setValues:&interval forParameter:NSOpenGLContextParameterSwapInterval]; } int Fl_Cocoa_Gl_Window_Driver::swap_interval() const { GLint interval = (GLint)-1; NSOpenGLContext* ctx = (NSOpenGLContext*)pWindow->context(); if (ctx) [ctx getValues:&interval forParameter:NSOpenGLContextParameterSwapInterval]; return interval; } void Fl_Cocoa_Gl_Window_Driver::resize(int is_a_resize, int w, int h) { if (pWindow->shown()) apply_scissor(); [(NSOpenGLContext*)pWindow->context() update]; if (gl1ctxt) { [gl1ctxt update]; } } void Fl_Cocoa_Gl_Window_Driver::apply_scissor() { if (glIsEnabled(GL_SCISSOR_TEST)) glDisable(GL_SCISSOR_TEST); CGRect *extents = Fl_Cocoa_Window_Driver::driver(pWindow)->subRect(); if (extents) { remove_gl_context_opacity((NSOpenGLContext*)pWindow->context()); GLdouble vals[4]; glGetDoublev(GL_COLOR_CLEAR_VALUE, vals); glClearColor(0., 0., 0., 0.); glClear(GL_COLOR_BUFFER_BIT); glClearColor(vals[0], vals[1], vals[2], vals[3]); float s = pWindow->pixels_per_unit(); glScissor(s*extents->origin.x, s*extents->origin.y, s*extents->size.width, s*extents->size.height); //printf("apply_scissor %dx%d %dx%d\n",extents->x, extents->y, extents->width, extents->height); glEnable(GL_SCISSOR_TEST); } } /* Some old Apple hardware doesn't implement the GL_EXT_texture_rectangle extension. For it, draw_string_legacy_glut() is used to draw text. */ char *Fl_Cocoa_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, int w, int h, Fl_Fontsize fs) { // write str to a bitmap just big enough Fl_Image_Surface *surf = new Fl_Image_Surface(w, h); Fl_Font f=fl_font(); Fl_Surface_Device::push_current(surf); fl_color(FL_WHITE); fl_font(f, fs); fl_draw(str, n, 0, fl_height() - fl_descent()); // get the alpha channel only of the bitmap char *alpha_buf = new char[w*h], *r = alpha_buf, *q; q = (char*)CGBitmapContextGetData((CGContextRef)surf->offscreen()); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { *r++ = *(q+3); q += 4; } } Fl_Surface_Device::pop_current(); delete surf; return alpha_buf; } void Fl_Cocoa_Gl_Window_Driver::gl_start() { [(NSOpenGLContext*)gl_start_context update]; } // convert BGRA to RGB and also exchange top and bottom static uchar *convert_BGRA_to_RGB(uchar *baseAddress, int w, int h, int mByteWidth) { uchar *newimg = new uchar[3*w*h]; uchar *to = newimg; for (int i = h-1; i >= 0; i--) { uchar *from = baseAddress + i * mByteWidth; for (int j = 0; j < w; j++, from += 4) { #if defined(__ppc__) && __ppc__ memcpy(to, from + 1, 3); to += 3; #else *(to++) = *(from+2); *(to++) = *(from+1); *(to++) = *from; #endif } } delete[] baseAddress; return newimg; } static Fl_RGB_Image *cgimage_to_rgb4(CGImageRef img) { int w = (int)CGImageGetWidth(img); int h = (int)CGImageGetHeight(img); CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB(); uchar *rgba = new uchar[4 * w * h]; CGContextRef auxgc = CGBitmapContextCreate(rgba, w, h, 8, 4 * w, cspace, kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(cspace); CGContextDrawImage(auxgc, CGRectMake(0, 0, w, h), img); CGContextRelease(auxgc); Fl_RGB_Image *rgb = new Fl_RGB_Image(rgba, w, h, 4); rgb->alloc_array = 1; return rgb; } Fl_RGB_Image* Fl_Cocoa_Gl_Window_Driver::capture_gl_rectangle(int x, int y, int w, int h) { Fl_Gl_Window* glw = pWindow; float factor = glw->pixels_per_unit(); if (factor != 1) { w *= factor; h *= factor; x *= factor; y *= factor; } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (fl_mac_os_version >= 100500) { NSWindow *nswin = (NSWindow*)fl_mac_xid(pWindow); CGImageRef img_full = Fl_Cocoa_Window_Driver::capture_decorated_window_10_5(nswin); int bt = [nswin frame].size.height - [[nswin contentView] frame].size.height; bt *= (factor / Fl_Graphics_Driver::default_driver().scale()); CGRect cgr = CGRectMake(x, y + bt, w, h); // add vertical offset to bypass titlebar CGImageRef cgimg = CGImageCreateWithImageInRect(img_full, cgr); // 10.4 CGImageRelease(img_full); Fl_RGB_Image *rgb = cgimage_to_rgb4(cgimg); CGImageRelease(cgimg); return rgb; } #endif [(NSOpenGLContext*)glw->context() makeCurrentContext]; // to capture also the overlay and for directGL demo [(NSOpenGLContext*)glw->context() flushBuffer]; // Read OpenGL context pixels directly. // For extra safety, save & restore OpenGL states that are changed glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */ glPixelStorei(GL_PACK_ROW_LENGTH, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); // Read a block of pixels from the frame buffer int mByteWidth = w * 4; mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes uchar *baseAddress = new uchar[mByteWidth * h]; glReadPixels(x, glw->pixel_h() - (y+h), w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, baseAddress); glPopClientAttrib(); baseAddress = convert_BGRA_to_RGB(baseAddress, w, h, mByteWidth); Fl_RGB_Image *img = new Fl_RGB_Image(baseAddress, w, h, 3, 3 * w); img->alloc_array = 1; [(NSOpenGLContext*)glw->context() flushBuffer]; return img; } void* Fl_Cocoa_Gl_Window_Driver::GetProcAddress(const char *procName) { return dlsym(RTLD_DEFAULT, procName); } FL_EXPORT NSOpenGLContext *fl_mac_glcontext(GLContext rc) { return (NSOpenGLContext*)rc; } void Fl_Cocoa_Gl_Window_Driver::switch_to_GL1() { [gl1ctxt makeCurrentContext]; glClearColor(0., 0., 0., 0.); glClear(GL_COLOR_BUFFER_BIT); } void Fl_Cocoa_Gl_Window_Driver::switch_back() { glFlush(); [(NSOpenGLContext*)pWindow->context() makeCurrentContext]; } class Fl_Gl_Cocoa_Plugin : public Fl_Cocoa_Plugin { public: Fl_Gl_Cocoa_Plugin() : Fl_Cocoa_Plugin(name()) { } const char *name() FL_OVERRIDE { return "gl.cocoa.fltk.org"; } void resize(Fl_Gl_Window *glw, int x, int y, int w, int h) FL_OVERRIDE { glw->Fl_Gl_Window::resize(x, y, w, h); } }; static Fl_Gl_Cocoa_Plugin Gl_Cocoa_Plugin; #endif // HAVE_GL fltk-1.4.3/src/drivers/Xlib/0000755000175000017500000000000015004135251015750 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx0000644000175000017500000007571115004135251024323 0ustar albrechtalbrecht// // Image drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // I hope a simple and portable method of drawing color and monochrome // images. To keep this simple, only a single storage type is // supported: 8 bit unsigned data, byte order RGB, and pixels are // stored packed into rows with the origin at the top-left. It is // possible to alter the size of pixels with the "delta" argument, to // add alpha or other information per pixel. It is also possible to // change the origin and direction of the image data by messing with // the "delta" and "linedelta", making them negative, though this may // defeat some of the shortcuts in translating the image for X. // A list of assumptions made about the X display: // bits_per_pixel must be one of 8, 16, 24, 32. // scanline_pad must be a power of 2 and greater or equal to 8. // PseudoColor visuals must have 8 bits_per_pixel (although the depth // may be less than 8). This is the only limitation that affects any // modern X displays, you can't use 12 or 16 bit colormaps. // The mask bits in TrueColor visuals for each color are // contiguous and have at least one bit of each color. This // is not checked for. // For 24 and 32 bit visuals there must be at least 8 bits of each color. //////////////////////////////////////////////////////////////// #include #include "Fl_Xlib_Graphics_Driver.H" #include "../X11/Fl_X11_Screen_Driver.H" #include "../X11/Fl_X11_Window_Driver.H" # include # include # include # include # include # include "../../Fl_Screen_Driver.H" # include "../../Fl_XColor.H" # include "../../flstring.h" #if HAVE_XRENDER # include # if RENDER_MAJOR * 100 + RENDER_MAJOR < 10 # define RepeatPad 2 # endif #endif // HAVE_XRENDER static XImage xi; // template used to pass info to X static int bytes_per_pixel; static int scanline_add; static int scanline_mask; static void (*converter)(const uchar *from, uchar *to, int w, int delta); static void (*mono_converter)(const uchar *from, uchar *to, int w, int delta); static int dir; // direction-alternator static int ri,gi,bi; // saved error-diffusion value # if USE_COLORMAP //////////////////////////////////////////////////////////////// // 8-bit converter with error diffusion static void color8_converter(const uchar *from, uchar *to, int w, int delta) { int r=ri, g=gi, b=bi; int d, td; if (dir) { dir = 0; from = from+(w-1)*delta; to = to+(w-1); d = -delta; td = -1; } else { dir = 1; d = delta; td = 1; } for (; w--; from += d, to += td) { r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255; b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255; Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); Fl_XColor& xmap = fl_xmap[0][i]; if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);} r -= xmap.r; g -= xmap.g; b -= xmap.b; *to = uchar(xmap.pixel); } ri = r; gi = g; bi = b; } static void mono8_converter(const uchar *from, uchar *to, int w, int delta) { int r=ri, g=gi, b=bi; int d, td; if (dir) { dir = 0; from = from+(w-1)*delta; to = to+(w-1); d = -delta; td = -1; } else { dir = 1; d = delta; td = 1; } for (; w--; from += d, to += td) { r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; g += from[0]; if (g < 0) g = 0; else if (g>255) g = 255; b += from[0]; if (b < 0) b = 0; else if (b>255) b = 255; Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); Fl_XColor& xmap = fl_xmap[0][i]; if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);} r -= xmap.r; g -= xmap.g; b -= xmap.b; *to = uchar(xmap.pixel); } ri = r; gi = g; bi = b; } # endif //////////////////////////////////////////////////////////////// // 16 bit TrueColor converters with error diffusion // Cray computers have no 16-bit type, so we use character pointers // (which may be slow) # ifdef U16 # define OUTTYPE U16 # define OUTSIZE 1 # define OUTASSIGN(v) *t = v # else # define OUTTYPE uchar # define OUTSIZE 2 # define OUTASSIGN(v) int tt=v; t[0] = uchar(tt>>8); t[1] = uchar(tt) # endif static void color16_converter(const uchar *from, uchar *to, int w, int delta) { OUTTYPE *t = (OUTTYPE *)to; int d, td; if (dir) { dir = 0; from = from+(w-1)*delta; t = t+(w-1)*OUTSIZE; d = -delta; td = -OUTSIZE; } else { dir = 1; d = delta; td = OUTSIZE; } int r=ri, g=gi, b=bi; for (; w--; from += d, t += td) { r = (r&~fl_redmask) +from[0]; if (r>255) r = 255; g = (g&~fl_greenmask)+from[1]; if (g>255) g = 255; b = (b&~fl_bluemask) +from[2]; if (b>255) b = 255; OUTASSIGN(( ((r&fl_redmask)<> fl_extrashift); } ri = r; gi = g; bi = b; } static void mono16_converter(const uchar *from,uchar *to,int w, int delta) { OUTTYPE *t = (OUTTYPE *)to; int d, td; if (dir) { dir = 0; from = from+(w-1)*delta; t = t+(w-1)*OUTSIZE; d = -delta; td = -OUTSIZE; } else { dir = 1; d = delta; td = OUTSIZE; } uchar mask = fl_redmask & fl_greenmask & fl_bluemask; int r=ri; for (; w--; from += d, t += td) { r = (r&~mask) + *from; if (r > 255) r = 255; uchar m = r&mask; OUTASSIGN(( (m<> fl_extrashift); } ri = r; } // special-case the 5r6g5b layout used by XFree86: static void c565_converter(const uchar *from, uchar *to, int w, int delta) { OUTTYPE *t = (OUTTYPE *)to; int d, td; if (dir) { dir = 0; from = from+(w-1)*delta; t = t+(w-1)*OUTSIZE; d = -delta; td = -OUTSIZE; } else { dir = 1; d = delta; td = OUTSIZE; } int r=ri, g=gi, b=bi; for (; w--; from += d, t += td) { r = (r&7)+from[0]; if (r>255) r = 255; g = (g&3)+from[1]; if (g>255) g = 255; b = (b&7)+from[2]; if (b>255) b = 255; OUTASSIGN(((r&0xf8)<<8) + ((g&0xfc)<<3) + (b>>3)); } ri = r; gi = g; bi = b; } static void m565_converter(const uchar *from,uchar *to,int w, int delta) { OUTTYPE *t = (OUTTYPE *)to; int d, td; if (dir) { dir = 0; from = from+(w-1)*delta; t = t+(w-1)*OUTSIZE; d = -delta; td = -OUTSIZE; } else { dir = 1; d = delta; td = OUTSIZE; } int r=ri; for (; w--; from += d, t += td) { r = (r&7) + *from; if (r > 255) r = 255; OUTASSIGN((r>>3) * 0x841); } ri = r; } //////////////////////////////////////////////////////////////// // 24bit TrueColor converters: static void rgb_converter(const uchar *from, uchar *to, int w, int delta) { int d = delta-3; for (; w--; from += d) { *to++ = *from++; *to++ = *from++; *to++ = *from++; } } static void bgr_converter(const uchar *from, uchar *to, int w, int delta) { for (; w--; from += delta) { uchar r = from[0]; uchar g = from[1]; *to++ = from[2]; *to++ = g; *to++ = r; } } static void rrr_converter(const uchar *from, uchar *to, int w, int delta) { for (; w--; from += delta) { *to++ = *from; *to++ = *from; *to++ = *from; } } //////////////////////////////////////////////////////////////// // 32bit TrueColor converters on a 32 or 64-bit machine: # ifdef U64 # define STORETYPE U64 # if WORDS_BIGENDIAN # define INNARDS32(f) \ U64 *t = (U64*)to; \ int w1 = w/2; \ for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = (i<<32)|(f);} \ if (w&1) *t++ = (U64)(f)<<32; # else # define INNARDS32(f) \ U64 *t = (U64*)to; \ int w1 = w/2; \ for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = ((U64)(f)<<32)|i;} \ if (w&1) *t++ = (U64)(f); # endif # else # define STORETYPE U32 # define INNARDS32(f) \ U32 *t = (U32*)to; for (; w--; from += delta) *t++ = f # endif static void rgbx_converter(const uchar *from, uchar *to, int w, int delta) { INNARDS32((unsigned(from[0])<<24)+(from[1]<<16)+(from[2]<<8)); } static void xbgr_converter(const uchar *from, uchar *to, int w, int delta) { INNARDS32((from[0])+(from[1]<<8)+(from[2]<<16)); } static void xrgb_converter(const uchar *from, uchar *to, int w, int delta) { INNARDS32((from[0]<<16)+(from[1]<<8)+(from[2])); } static void argb_premul_converter(const uchar *from, uchar *to, int w, int delta) { INNARDS32((unsigned(from[3]) << 24) + (((from[0] * from[3]) / 255) << 16) + (((from[1] * from[3]) / 255) << 8) + ((from[2] * from[3]) / 255)); } static void depth2_to_argb_premul_converter(const uchar *from, uchar *to, int w, int delta) { INNARDS32((unsigned(from[1]) << 24) + (((from[0] * from[1]) / 255) << 16) + (((from[0] * from[1]) / 255) << 8) + ((from[0] * from[1]) / 255)); } static void bgrx_converter(const uchar *from, uchar *to, int w, int delta) { INNARDS32((from[0]<<8)+(from[1]<<16)+(unsigned(from[2])<<24)); } static void rrrx_converter(const uchar *from, uchar *to, int w, int delta) { INNARDS32(unsigned(*from) * 0x1010100U); } static void xrrr_converter(const uchar *from, uchar *to, int w, int delta) { INNARDS32(*from * 0x10101U); } static void color32_converter(const uchar *from, uchar *to, int w, int delta) { INNARDS32( (from[0]<depth == fl_visual->depth) break; xi.format = ZPixmap; xi.byte_order = ImageByteOrder(fl_display); //i.bitmap_unit = 8; //i.bitmap_bit_order = MSBFirst; //i.bitmap_pad = 8; xi.depth = fl_visual->depth; xi.bits_per_pixel = pfv->bits_per_pixel; if (xi.bits_per_pixel & 7) bytes_per_pixel = 0; // produce fatal error else bytes_per_pixel = xi.bits_per_pixel/8; unsigned int n = pfv->scanline_pad/8; if (pfv->scanline_pad & 7 || (n&(n-1))) Fl::fatal("Can't do scanline_pad of %d",pfv->scanline_pad); if (n < sizeof(STORETYPE)) n = sizeof(STORETYPE); scanline_add = n-1; scanline_mask = -n; # if USE_COLORMAP if (bytes_per_pixel == 1) { converter = color8_converter; mono_converter = mono8_converter; return; } if (!fl_visual->red_mask) Fl::fatal("Can't do %d bits_per_pixel colormap",xi.bits_per_pixel); # endif // otherwise it is a TrueColor visual: int rs = fl_redshift; int gs = fl_greenshift; int bs = fl_blueshift; switch (bytes_per_pixel) { case 2: // All 16-bit TrueColor visuals are supported on any machine with // 24 or more bits per integer. # ifdef U16 xi.byte_order = WORDS_BIGENDIAN; # else xi.byte_order = 1; # endif if (rs == 11 && gs == 6 && bs == 0 && fl_extrashift == 3) { converter = c565_converter; mono_converter = m565_converter; } else { converter = color16_converter; mono_converter = mono16_converter; } break; case 3: if (xi.byte_order) {rs = 16-rs; gs = 16-gs; bs = 16-bs;} if (rs == 0 && gs == 8 && bs == 16) { converter = rgb_converter; mono_converter = rrr_converter; } else if (rs == 16 && gs == 8 && bs == 0) { converter = bgr_converter; mono_converter = rrr_converter; } else { Fl::fatal("Can't do arbitrary 24bit color"); } break; case 4: if ((xi.byte_order!=0) != WORDS_BIGENDIAN) {rs = 24-rs; gs = 24-gs; bs = 24-bs;} if (rs == 0 && gs == 8 && bs == 16) { converter = xbgr_converter; mono_converter = xrrr_converter; } else if (rs == 24 && gs == 16 && bs == 8) { converter = rgbx_converter; mono_converter = rrrx_converter; } else if (rs == 8 && gs == 16 && bs == 24) { converter = bgrx_converter; mono_converter = rrrx_converter; } else if (rs == 16 && gs == 8 && bs == 0) { converter = xrgb_converter; mono_converter = xrrr_converter; } else { xi.byte_order = WORDS_BIGENDIAN; converter = color32_converter; mono_converter = mono32_converter; } break; default: Fl::fatal("Can't do %d bits_per_pixel",xi.bits_per_pixel); } } # define MAXBUFFER 0x40000 // 256k static void innards(const uchar *buf, int X, int Y, int W, int H, int delta, int linedelta, int mono, Fl_Draw_Image_Cb cb, void* userdata, const bool alpha, GC gc) { if (!linedelta) linedelta = W*abs(delta); int dx = 0, dy = 0, w = 0, h = 0; fl_clip_box(X, Y, W, H, dx, dy, w, h); if (w<=0 || h<=0) return; dx -= X; dy -= Y; if (!bytes_per_pixel) figure_out_visual(); const unsigned oldbpp = bytes_per_pixel; static GC gc32 = None; xi.width = w; xi.height = h; void (*conv)(const uchar *from, uchar *to, int w, int delta) = converter; if (mono) conv = mono_converter; if (alpha) { // This flag states the destination format is ARGB32 (big-endian), pre-multiplied. bytes_per_pixel = 4; conv = (mono ? depth2_to_argb_premul_converter : argb_premul_converter); xi.depth = 32; xi.bits_per_pixel = 32; // Do we need a new GC? if (fl_visual->depth != 32) { if (gc32 == None) gc32 = XCreateGC(fl_display, fl_window, 0, NULL); gc = gc32; } } // See if the data is already in the right format. Unfortunately // some 32-bit x servers (XFree86) care about the unknown 8 bits // and they must be zero. I can't confirm this for user-supplied // data, so the 32-bit shortcut is disabled... // This can set bytes_per_line negative if image is bottom-to-top // I tested it on Linux, but it may fail on other Xlib implementations: if (buf && ( # if 0 // set this to 1 to allow 32-bit shortcut delta == 4 && # if WORDS_BIGENDIAN conv == rgbx_converter # else conv == xbgr_converter # endif || # endif conv == rgb_converter && delta==3 ) && !(linedelta&scanline_add)) { xi.data = (char *)(buf+delta*dx+linedelta*dy); xi.bytes_per_line = linedelta; } else { int linesize = ((w*bytes_per_pixel+scanline_add)&scanline_mask)/sizeof(STORETYPE); int blocking = h; static STORETYPE *buffer; // our storage, always word aligned static long buffer_size; {int size = linesize*h; if (size > MAXBUFFER) { size = MAXBUFFER; blocking = MAXBUFFER/linesize; } if (size > buffer_size) { delete[] buffer; buffer_size = size; buffer = new STORETYPE[size]; }} xi.data = (char *)buffer; xi.bytes_per_line = linesize*sizeof(STORETYPE); if (buf) { buf += delta*dx+linedelta*dy; for (int j=0; jdepth; xi.bits_per_pixel = oldbpp * 8; } } void Fl_Xlib_Graphics_Driver::draw_image_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){ const bool alpha = !!(abs(d) & FL_IMAGE_WITH_ALPHA); if (alpha) d ^= FL_IMAGE_WITH_ALPHA; const int mono = (d>-3 && d<3); innards(buf,x+floor(offset_x_),y+floor(offset_y_),w,h,d,l,mono,0,0,alpha,gc_); } void Fl_Xlib_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { const bool alpha = !!(abs(d) & FL_IMAGE_WITH_ALPHA); if (alpha) d ^= FL_IMAGE_WITH_ALPHA; const int mono = (d>-3 && d<3); innards(0,x+floor(offset_x_),y+floor(offset_y_),w,h,d,0,mono,cb,data,alpha,gc_); } void Fl_Xlib_Graphics_Driver::draw_image_mono_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){ innards(buf,x+floor(offset_x_),y+floor(offset_y_),w,h,d,l,1,0,0,0,gc_); } void Fl_Xlib_Graphics_Driver::draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int x, int y, int w, int h,int d) { innards(0,x+floor(offset_x_),y+floor(offset_y_),w,h,d,0,1,cb,data,0,gc_); } void Fl_Xlib_Graphics_Driver::colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { if (fl_visual->depth > 16) { Fl_Graphics_Driver::colored_rectf(x, y, w, h, r, g, b); } else { uchar c[3]; c[0] = r; c[1] = g; c[2] = b; innards(c, floor(x), floor(y), floor(x + w) - floor(x), floor(y + h) - floor(y), 0,0,0,0,0,0, (GC)gc()); } } unsigned long Fl_Xlib_Graphics_Driver::create_bitmask(int w, int h, const uchar *data) { return XCreateBitmapFromData(fl_display, fl_window, (const char *)data, (w+7)&-8, h); } void Fl_Xlib_Graphics_Driver::delete_bitmask(fl_uintptr_t bm) { XFreePixmap(fl_display, (unsigned long)bm); } void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) { X = floor(X)+floor(offset_x_); Y = floor(Y)+floor(offset_y_); cache_size(bm, W, H); cx *= scale(); cy *= scale(); XSetStipple(fl_display, gc_, *Fl_Graphics_Driver::id(bm)); int ox = X-cx; if (ox < 0) ox += bm->w()*scale(); int oy = Y-cy; if (oy < 0) oy += bm->h()*scale(); XSetTSOrigin(fl_display, gc_, ox, oy); XSetFillStyle(fl_display, gc_, FillStippled); XFillRectangle(fl_display, fl_window, gc_, X, Y, W, H); XSetFillStyle(fl_display, gc_, FillSolid); } // Composite an image with alpha on systems that don't have accelerated // alpha compositing... static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { if (cx < 0) { W += cx; X -= cx; cx = 0; } if (cy < 0) { H += cy; Y -= cy; cy = 0; } if (W + cx > img->data_w()) W = img->data_w() - cx; if (H + cy > img->data_h()) H = img->data_h() - cy; // don't attempt to read outside the window/offscreen buffer limits Window root_return; int x_return, y_return; unsigned int winW, winH; unsigned int border_width_return; unsigned int depth_return; XGetGeometry(fl_display, fl_window, &root_return, &x_return, &y_return, &winW, &winH, &border_width_return, &depth_return); if (X+W > (int)winW) W = (int)winW-X; if (Y+H > (int)winH) H = (int)winH-Y; if (W <= 0 || H <= 0) return; int ld = img->ld(); if (ld == 0) ld = img->data_w() * img->d(); uchar *srcptr = (uchar*)img->array + cy * ld + cx * img->d(); uchar *dst = fl_read_image(NULL, X, Y, W, H, 0); if (!dst) { fl_draw_image(srcptr, X, Y, W, H, img->d(), ld); return; } int srcskip = ld - img->d() * W; uchar *dstptr = dst; uchar srcr, srcg, srcb; // source color components uchar dstr, dstg, dstb; // destination color components unsigned int srca, dsta; // source alpha and inverse source alpha if (img->d() == 2) { // Composite grayscale + alpha over RGB... for (int y = H; y > 0; y--, srcptr+=srcskip) for (int x = W; x > 0; x--) { srcg = *srcptr++; srca = *srcptr++; if (srca == 255) { // special case "copy" *dstptr++ = srcg; *dstptr++ = srcg; *dstptr++ = srcg; } else if (srca == 0) { // special case "ignore" dstptr += 3; } else { // common case "blend" srca += srca>>7; // multiply by 1.004 to compensate integer rounding error dstr = dstptr[0]; dstg = dstptr[1]; dstb = dstptr[2]; dsta = 256 - srca; unsigned int srcg_pm = srcg * srca; // premultiply once *dstptr++ = (srcg_pm + dstr * dsta) >> 8; *dstptr++ = (srcg_pm + dstg * dsta) >> 8; *dstptr++ = (srcg_pm + dstb * dsta) >> 8; } } } else { // Composite RGBA over RGB... for (int y = H; y > 0; y--, srcptr+=srcskip) for (int x = W; x > 0; x--) { srcr = *srcptr++; srcg = *srcptr++; srcb = *srcptr++; srca = *srcptr++; if (srca == 255) { // special case "copy" *dstptr++ = srcr; *dstptr++ = srcg; *dstptr++ = srcb; } else if (srca == 0) { // special case "ignore" dstptr += 3; } else { // common case "blend" srca += srca>>7; // multiply by 1.004 to compensate integer rounding error dstr = dstptr[0]; dstg = dstptr[1]; dstb = dstptr[2]; dsta = 256 - srca; *dstptr++ = (srcr * srca + dstr * dsta) >> 8; *dstptr++ = (srcg * srca + dstg * dsta) >> 8; *dstptr++ = (srcb * srca + dstb * dsta) >> 8; } } } fl_draw_image(dst, X, Y, W, H, 3, 0); delete[] dst; } void Fl_Xlib_Graphics_Driver::cache(Fl_RGB_Image *img) { Fl_Image_Surface *surface; int depth = img->d(); if (depth == 1 || depth == 3) { surface = new Fl_Image_Surface(img->data_w(), img->data_h()); } else if (fl_can_do_alpha_blending()) { Pixmap pixmap = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), img->data_w(), img->data_h(), 32); surface = new Fl_Image_Surface(img->data_w(), img->data_h(), 0, (Fl_Offscreen)pixmap); depth |= FL_IMAGE_WITH_ALPHA; } else { *Fl_Graphics_Driver::id(img) = 0; return; } Fl_Surface_Device::push_current(surface); fl_draw_image(img->array, 0, 0, img->data_w(), img->data_h(), depth, img->ld()); Fl_Surface_Device::pop_current(); Fl_Offscreen off = Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surface); int *pw, *ph; cache_w_h(img, pw, ph); *pw = img->data_w(); *ph = img->data_h(); *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)off; } void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { X = floor(X)+floor(offset_x_); Y = floor(Y)+floor(offset_y_); cache_size(img, W, H); cx *= scale(); cy *= scale(); if (img->d() == 1 || img->d() == 3) { XCopyArea(fl_display, *Fl_Graphics_Driver::id(img), fl_window, gc_, cx, cy, W, H, X, Y); return; } // Composite image with alpha manually each time... push_no_clip(); float s = scale(); Fl_Graphics_Driver::scale(1); int ox = offset_x_, oy = offset_y_; offset_x_ = offset_y_ = 0; Fl_X11_Screen_Driver *d = (Fl_X11_Screen_Driver*)Fl::screen_driver(); int nscreen = Fl_Window_Driver::driver(Fl_Window::current())->screen_num(); float keep = d->scale(nscreen); d->scale(nscreen, 1); alpha_blend(img, X, Y, W, H, cx, cy); d->scale(nscreen, keep); Fl_Graphics_Driver::scale(s); offset_x_ = ox; offset_y_ = oy; pop_clip(); } #if HAVE_XRENDER void Fl_Xlib_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) { if (!fl_can_do_alpha_blending()) { Fl_Graphics_Driver::draw_rgb(rgb, XP, YP, WP, HP, cx, cy); return; } if (!*Fl_Graphics_Driver::id(rgb)) { cache(rgb); } float s = scale(); int Xs = Fl_Scalable_Graphics_Driver::floor(XP - cx, s); int Wfull = Fl_Scalable_Graphics_Driver::floor(XP - cx + rgb->w(), s) - Xs ; int Ys = Fl_Scalable_Graphics_Driver::floor(YP - cy, s); int Hfull = Fl_Scalable_Graphics_Driver::floor(YP - cy + rgb->h(), s) - Ys; if (Wfull == 0 || Hfull == 0) return; bool need_clip = (cx || cy || WP < rgb->w() || HP < rgb->h()); if (need_clip) push_clip(XP, YP, WP, HP); scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(), rgb->data_w() / double(Wfull), rgb->data_h() / double(Hfull), Xs + this->floor(offset_x_), Ys + this->floor(offset_y_), Wfull, Hfull); if (need_clip) pop_clip(); } /* Draws with Xrender an Fl_Offscreen with optional scaling and accounting for transparency if necessary. XP,YP,WP,HP are in drawing units */ int Fl_Xlib_Graphics_Driver::scale_and_render_pixmap(Fl_Offscreen pixmap, int depth, double scale_x, double scale_y, int XP, int YP, int WP, int HP) { bool has_alpha = (depth == 2 || depth == 4); if (!has_alpha && scale_x == 1 && scale_y == 1) { // Fix for a problem visible under XQuartz with test/device and Fl_Image_Surface: // the drawn image is fully black. The problem does not occur under linux. // Why the problem occurs under XQuartz remains unknown. // The fix is to use XCopyArea() when adequate, rather than using Xrender. XCopyArea(fl_display, pixmap, fl_window, gc_, 0, 0, WP, HP, XP, YP); return 1; } XRenderPictureAttributes srcattr; memset(&srcattr, 0, sizeof(XRenderPictureAttributes)); static XRenderPictFormat *fmt24 = XRenderFindStandardFormat(fl_display, PictStandardRGB24); static XRenderPictFormat *fmt32 = XRenderFindStandardFormat(fl_display, PictStandardARGB32); static XRenderPictFormat *dstfmt = XRenderFindVisualFormat(fl_display, fl_visual->visual); srcattr.repeat = RepeatPad; Picture src = XRenderCreatePicture(fl_display, (Pixmap)pixmap, has_alpha ?fmt32:fmt24, CPRepeat, &srcattr); Picture dst = XRenderCreatePicture(fl_display, fl_window, dstfmt, 0, 0); if (!src || !dst) { fprintf(stderr, "Failed to create Render pictures (%lu %lu)\n", src, dst); return 0; } Fl_Region r = scale_clip(scale()); const Region clipr = (Region)clip_region(); if (clipr) XRenderSetPictureClipRegion(fl_display, dst, clipr); unscale_clip(r); if (scale_x != 1 || scale_y != 1) { XTransform mat = {{ { XDoubleToFixed( scale_x ), XDoubleToFixed( 0 ), XDoubleToFixed( 0 ) }, { XDoubleToFixed( 0 ), XDoubleToFixed( scale_y ), XDoubleToFixed( 0 ) }, { XDoubleToFixed( 0 ), XDoubleToFixed( 0 ), XDoubleToFixed( 1 ) } }}; XRenderSetPictureTransform(fl_display, src, &mat); if (Fl_Image::scaling_algorithm() == FL_RGB_SCALING_BILINEAR) { XRenderSetPictureFilter(fl_display, src, FilterBilinear, 0, 0); // A note at https://www.talisman.org/~erlkonig/misc/x11-composite-tutorial/ : // "When you use a filter you'll probably want to use PictOpOver as the render op, // regardless of whether the source picture has an alpha channel or not, since // the edges may end up having alpha values after the filter has been applied." // suggests this is necessary : has_alpha = true; } } XRenderComposite(fl_display, (has_alpha ? PictOpOver : PictOpSrc), src, None, dst, 0, 0, 0, 0, XP, YP, WP, HP); XRenderFreePicture(fl_display, src); XRenderFreePicture(fl_display, dst); return 1; } #endif // HAVE_XRENDER void Fl_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) { if (id_) { XFreePixmap(fl_display, (Pixmap)id_); id_ = 0; } } void Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm) { int *pw, *ph; cache_w_h(bm, pw, ph); *pw = bm->data_w(); *ph = bm->data_h(); *Fl_Graphics_Driver::id(bm) = (fl_uintptr_t)create_bitmask(bm->data_w(), bm->data_h(), bm->array); } void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, int H, int cx, int cy) { X = floor(X)+floor(offset_x_); Y = floor(Y)+floor(offset_y_); cache_size(pxm, W, H); cx *= scale(); cy *= scale(); Fl_Region r2 = scale_clip(scale()); if (*Fl_Graphics_Driver::mask(pxm)) { // make X use the bitmap as a mask: XSetClipMask(fl_display, gc_, *Fl_Graphics_Driver::mask(pxm)); XSetClipOrigin(fl_display, gc_, X-cx, Y-cy); if (clip_region()) { // At this point, XYWH is the bounding box of the intersection between // the current clip region and the (portion of the) pixmap we have to draw. // The current clip region is often a rectangle. But, when a window with rounded // corners is moved above another window, expose events may create a complex clip // region made of several (e.g., 10) rectangles. We have to draw only in the clip // region, and also to mask out the transparent pixels of the image. This can't // be done in a single Xlib call for a multi-rectangle clip region. Thus, we // process each rectangle of the intersection between the clip region and XYWH. // See also STR #3206. Region r = (Region)XRectangleRegion(X,Y,W,H); XIntersectRegion(r, (Region)clip_region(), r); int X1, Y1, W1, H1; for (int i = 0; i < r->numRects; i++) { X1 = r->rects[i].x1; Y1 = r->rects[i].y1; W1 = r->rects[i].x2 - r->rects[i].x1; H1 = r->rects[i].y2 - r->rects[i].y1; XCopyArea(fl_display, *Fl_Graphics_Driver::id(pxm), fl_window, gc_, cx + (X1 - X), cy + (Y1 - Y), W1, H1, X1, Y1); } XDestroyRegion(r); } else { XCopyArea(fl_display, *Fl_Graphics_Driver::id(pxm), fl_window, gc_, cx, cy, W, H, X, Y); } // put the old clip region back XSetClipOrigin(fl_display, gc_, 0, 0); float s = scale(); Fl_Graphics_Driver::scale(1); restore_clip(); Fl_Graphics_Driver::scale(s); } else XCopyArea(fl_display, *Fl_Graphics_Driver::id(pxm), fl_window, gc_, cx, cy, W, H, X, Y); unscale_clip(r2); } void Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *pxm) { Fl_Image_Surface *surf = new Fl_Image_Surface(pxm->data_w(), pxm->data_h()); Fl_Surface_Device::push_current(surf); uchar **pbitmap = surf->driver()->mask_bitmap(); *pbitmap = (uchar*)1;// will instruct fl_draw_pixmap() to compute the image's mask fl_draw_pixmap(pxm->data(), 0, 0, FL_BLACK); uchar *bitmap = *pbitmap; if (bitmap) { *Fl_Graphics_Driver::mask(pxm) = (fl_uintptr_t)create_bitmask(pxm->data_w(), pxm->data_h(), bitmap); delete[] bitmap; } *pbitmap = 0; Fl_Surface_Device::pop_current(); Fl_Offscreen id = Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surf); int *pw, *ph; cache_w_h(pxm, pw, ph); *pw = pxm->data_w(); *ph = pxm->data_h(); *Fl_Graphics_Driver::id(pxm) = (fl_uintptr_t)id; } void Fl_Xlib_Graphics_Driver::uncache_pixmap(fl_uintptr_t offscreen) { XFreePixmap(fl_display, (Pixmap)offscreen); } fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx0000644000175000017500000005425315004135251024534 0ustar albrechtalbrecht// // X11 font utilities for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Select fonts from the FLTK font table. #include "../../flstring.h" #include "Fl_Xlib_Graphics_Driver.H" #include #include #include #include #include "Fl_Font.H" #include #include static char* fl_find_fontsize(char* name); static const char* fl_font_word(const char* p, int n); // WARNING: if you add to this table, you must redefine FL_FREE_FONT // in Enumerations.H & recompile!! static Fl_Xlib_Fontdesc built_in_table[] = { {"-*-helvetica-medium-r-normal--*"}, {"-*-helvetica-bold-r-normal--*"}, {"-*-helvetica-medium-o-normal--*"}, {"-*-helvetica-bold-o-normal--*"}, {"-*-courier-medium-r-normal--*"}, {"-*-courier-bold-r-normal--*"}, {"-*-courier-medium-o-normal--*"}, {"-*-courier-bold-o-normal--*"}, {"-*-times-medium-r-normal--*"}, {"-*-times-bold-r-normal--*"}, {"-*-times-medium-i-normal--*"}, {"-*-times-bold-i-normal--*"}, {"-*-symbol-*"}, {"-*-lucidatypewriter-medium-r-normal-sans-*"}, {"-*-lucidatypewriter-bold-r-normal-sans-*"}, {"-*-*zapf dingbats-*"} }; FL_EXPORT Fl_Fontdesc* fl_fonts = (Fl_Fontdesc*)built_in_table; // This function fills in the fltk font table with all the fonts that // are found on the X server. It tries to place the fonts into families // and to sort them so the first 4 in a family are normal, bold, italic, // and bold italic. // Standard X fonts are matched by a pattern that is always of // this form, and this pattern is put in the table: // "-*-family-weight-slant-width1-style-*-registry-encoding" // Non-standard font names (those not starting with '-') are matched // by a pattern of the form "prefix*suffix", where the '*' is where // fltk thinks the point size is, or by the actual font name if no // point size is found. // Fltk knows how to pull an "attribute" out of a font name, such as // bold or italic, by matching known x font field values. All words // that don't match a known attribute are combined into the "name" // of the font. Names are compared before attributes for sorting, this // makes the bold and plain version of a font come out next to each // other despite the poor X font naming scheme. // By default fl_set_fonts() only does iso8859-1 encoded fonts. You can // do all normal X fonts by passing "-*" or every possible font with "*". // Fl::set_font will take strings other than the ones this stores // and can identify any font on X that way. You may want to write your // own system of font management and not use this code. // turn word N of a X font name into either some attribute bits // (right now 0, FL_BOLD, or FL_ITALIC), or into -1 indicating that // the word should be put into the name: static int attribute(int n, const char *p) { // don't put blank things into name: if (!*p || *p=='-' || *p=='*') return 0; if (n == 3) { // weight if (!strncmp(p,"normal",6) || !strncmp(p,"light",5) || !strncmp(p,"medium",6) || !strncmp(p,"book",4)) return 0; if (!strncmp(p,"bold",4) || !strncmp(p,"demi",4)) return FL_BOLD; } else if (n == 4) { // slant if (*p == 'r') return 0; if (*p == 'i' || *p == 'o') return FL_ITALIC; } else if (n == 5) { // sWidth if (!strncmp(p,"normal",6)) return 0; } return -1; } // return non-zero if the registry-encoding should be used: extern const char* fl_encoding; static int use_registry(const char *p) { return *p && *p!='*' && strcmp(p,fl_encoding); } // Bug: older versions calculated the value for *ap as a side effect of // making the name, and then forgot about it. To avoid having to change // the header files I decided to store this value in the last character // of the font name array. #define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 // turn a stored (with *'s) X font name into a pretty name: const char* Fl_Xlib_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) { Fl_Xlib_Fontdesc *f = ((Fl_Xlib_Fontdesc*)fl_fonts) + fnum; if (!f->fontname[0]) { int type = 0; const char* p = f->name; if (!p) { if (ap) *ap = 0; return ""; } char *o = f->fontname; if (*p != '-') { // non-standard font, just replace * with spaces: if (strstr(p,"bold")) type = FL_BOLD; if (strstr(p,"ital")) type |= FL_ITALIC; for (;*p; p++) { if (*p == '*' || *p == ' ' || *p == '-') { do p++; while (*p == '*' || *p == ' ' || *p == '-'); if (!*p) break; if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = ' '; } if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = *p; } *o = 0; } else { // standard dash-separated font: // get the family: const char *x = fl_font_word(p,2); if (*x) x++; if (*x=='*') x++; if (!*x) { if (ap) *ap = 0; return p; } const char *e = fl_font_word(x,1); if ((e - x) < (int)(ENDOFBUFFER - 1)) { // MRS: we want strncpy here, not strlcpy... strncpy(o,x,e-x); o += e-x; } else { strlcpy(f->fontname, x, ENDOFBUFFER); o = f->fontname+ENDOFBUFFER-1; } // collect all the attribute words: for (int n = 3; n <= 6; n++) { // get the next word: if (*e) e++; x = e; e = fl_font_word(x,1); int t = attribute(n,x); if (t < 0) { if (o < (f->fontname + ENDOFBUFFER - 1)) *o++ = ' '; if ((e - x) < (int)(ENDOFBUFFER - (o - f->fontname) - 1)) { // MRS: we want strncpy here, not strlcpy... strncpy(o,x,e-x); o += e-x; } else { strlcpy(o,x, ENDOFBUFFER - (o - f->fontname) - 1); o = f->fontname+ENDOFBUFFER-1; } } else type |= t; } // skip over the '*' for the size and get the registry-encoding: x = fl_font_word(e,2); if (*x) {x++; *o++ = '('; while (*x) *o++ = *x++; *o++ = ')';} *o = 0; if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER); if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER); } f->fontname[ENDOFBUFFER] = (char)type; } if (ap) *ap = f->fontname[ENDOFBUFFER]; return f->fontname; } extern "C" { // sort raw (non-'*') X font names into perfect order: static int ultrasort(const void *aa, const void *bb) { const char *a = *(char **)aa; const char *b = *(char **)bb; // sort all non x-fonts at the end: if (*a != '-') { if (*b == '-') return 1; // 2 non-x fonts are matched by "numeric sort" int ret = 0; for (;;) { if (isdigit(*a) && isdigit(*b)) { int na = strtol(a, (char **)&a, 10); int nb = strtol(b, (char **)&b, 10); if (!ret) ret = na-nb; } else if (*a != *b) { return (*a-*b); } else if (!*a) { return ret; } else { a++; b++; } } } else { if (*b != '-') return -1; } // skip the foundry (assume equal): for (a++; *a && *a++!='-';); for (b++; *b && *b++!='-';); // compare the family and all the attribute words: int atype = 0; int btype = 0; for (int n = 2; n <= 6; n++) { int at = attribute(n,a); int bt = attribute(n,b); if (at < 0) { if (bt >= 0) return 1; for (;;) {if (*a!=*b) return *a-*b; b++; if (!*a || *a++=='-') break;} } else { if (bt < 0) return -1; a = fl_font_word(a,1); if (*a) a++; b = fl_font_word(b,1); if (*b) b++; atype |= at; btype |= bt; } } // remember the pixel size: int asize = atoi(a); int bsize = atoi(b); // compare the registry/encoding: a = fl_font_word(a,6); if (*a) a++; b = fl_font_word(b,6); if (*b) b++; if (use_registry(a)) { if (!use_registry(b)) return 1; int r = strcmp(a,b); if (r) return r; } else { if (use_registry(b)) return -1; } if (atype != btype) return atype-btype; if (asize != bsize) return asize-bsize; // something wrong, just do a string compare... return strcmp(*(char**)aa, *(char**)bb); } } // converts a X font name to a standard starname, returns point size: static int to_canonical(char *to, const char *from, size_t tolen) { char* c = fl_find_fontsize((char*)from); if (!c) return -1; // no point size found... const char* endptr; int size = strtol(c,(char**)&endptr,10); if (from[0] == '-') { // replace the "foundry" with -*-: *to++ = '-'; *to++ = '*'; for (from++; *from && *from != '-'; from++); // skip to the registry-encoding: endptr = (char*)fl_font_word(endptr,6); if (*endptr && !use_registry(endptr+1)) endptr = ""; } int n = c-from; // MRS: we want strncpy here, not strlcpy... if (n > (int)(tolen - 1)) return -1; strncpy(to,from,n); to[n++] = '*'; strlcpy(to+n,endptr, tolen - n); return size; } static unsigned int fl_free_font = FL_FREE_FONT; // This function fills in the fltk font table with all the fonts that // are found on the X server. It tries to place the fonts into families // and to sort them so the first 4 in a family are normal, bold, italic, // and bold italic. Fl_Font Fl_Xlib_Graphics_Driver::set_fonts(const char* xstarname) { if (fl_free_font > (unsigned)FL_FREE_FONT) // already been here return (Fl_Font)fl_free_font; fl_open_display(); int xlistsize; char buf[20]; if (!xstarname) { strcpy(buf,"-*-"); strcpy(buf+3,fl_encoding); xstarname = buf; } char **xlist = XListFonts(fl_display, xstarname, 10000, &xlistsize); if (!xlist) return (Fl_Font)fl_free_font; qsort(xlist, xlistsize, sizeof(*xlist), ultrasort); int used_xlist = 0; for (int i=0; i= 0) { for (;;) { // find all matching fonts: if (i >= xlistsize) break; const char *q = xlist[i]; char this_canon[1024]; if (to_canonical(this_canon, q, sizeof(this_canon)) < 0) break; if (strcmp(canon, this_canon)) break; i++; } /*if (*p=='-' || i > first_xlist+1)*/ p = canon; } unsigned int j; for (j = 0;; j++) { /*if (j < FL_FREE_FONT) { // see if it is one of our built-in fonts: // if so, set the list of x fonts, since we have it anyway if (fl_fonts[j].name && !strcmp(fl_fonts[j].name, p)) break; } else */{ j = fl_free_font++; if (p == canon) p = fl_strdup(p); else used_xlist = 1; Fl::set_font((Fl_Font)j, p); break; } } Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts)+j; if (!s->xlist) { s->xlist = xlist+first_xlist; s->n = -(i-first_xlist); used_xlist = 1; } } if (!used_xlist) XFreeFontNames(xlist); return (Fl_Font)fl_free_font; } int Fl_Xlib_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) { Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts)+fnum; if (!s->name) s = ((Fl_Xlib_Fontdesc*)fl_fonts); // empty slot in table, use entry 0 if (!s->xlist) { fl_open_display(); s->xlist = XListFonts(fl_display, s->name, 100, &(s->n)); if (!s->xlist) return 0; } int listsize = s->n; if (listsize<0) listsize = -listsize; static int sizes[128]; int numsizes = 0; for (int i = 0; i < listsize; i++) { char *q = s->xlist[i]; char *d = fl_find_fontsize(q); if (!d) continue; int s = strtol(d,0,10); if (!numsizes || sizes[numsizes-1] < s) { sizes[numsizes++] = s; } else { // insert-sort the new size into list: int n; for (n = numsizes-1; n > 0; n--) if (sizes[n-1] < s) break; if (sizes[n] != s) { for (int m = numsizes; m > n; m--) sizes[m] = sizes[m-1]; sizes[n] = s; numsizes++; } } } sizep = sizes; return numsizes; } #ifndef FL_DOXYGEN Fl_Xlib_Font_Descriptor::Fl_Xlib_Font_Descriptor(const char* name) : Fl_Font_Descriptor(name, 0) { font = XCreateUtf8FontStruct(fl_display, name); if (!font) { Fl::warning("bad font: %s", name); font = XCreateUtf8FontStruct(fl_display, "fixed"); } # if HAVE_GL listbase = 0; for (int u = 0; u < 64; u++) glok[u] = 0; # endif } Fl_XFont_On_Demand fl_xfont; Fl_Xlib_Font_Descriptor::~Fl_Xlib_Font_Descriptor() { # if HAVE_GL // Delete list created by gl_draw(). This is not done by this code // as it will link in GL unnecessarily. There should be some kind // of "free" routine pointer, or a subclass? # endif if (this == fl_graphics_driver->font_descriptor()) { fl_graphics_driver->font_descriptor(NULL); fl_xfont = 0; } XFreeUtf8FontStruct(fl_display, font); } //////////////////////////////////////////////////////////////// extern Fl_Fontdesc* fl_fonts; #define MAXSIZE 32767 // return dash number N, or pointer to ending null if none: static const char* fl_font_word(const char* p, int n) { while (*p) {if (*p=='-') {if (!--n) break;} p++;} return p; } // return a pointer to a number we think is "point size": static char* fl_find_fontsize(char* name) { char* c = name; // for standard x font names, try after 7th dash: if (*c == '-') { c = (char*)fl_font_word(c,7); if (*c++ && isdigit(*c)) return c; return 0; // malformed x font name? } char* r = 0; // find last set of digits: for (c++;* c; c++) if (isdigit(*c) && !isdigit(*(c-1))) r = c; return r; } //const char* fl_encoding = "iso8859-1"; const char* fl_encoding = "iso10646-1"; // return true if this matches fl_encoding: int fl_correct_encoding(const char* name) { if (*name != '-') return 0; const char* c = fl_font_word(name,13); return (*c++ && !strcmp(c,fl_encoding)); } static const char *find_best_font(const char *fname, int size) { int cnt; static char **list = NULL; // note: namebuffer must be static: its address may be returned to caller static char namebuffer[1024]; // holds scalable font name // locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size: if (list) XFreeFontNames(list); list = XListFonts(fl_display, fname, 100, &cnt); if (!list) return "fixed"; // search for largest <= font size: char* name = list[0]; int ptsize = 0; // best one found so far int matchedlength = 32767; int found_encoding = 0; int m = cnt; if (m<0) m = -m; for (int n=0; n < m; n++) { char* thisname = list[n]; if (fl_correct_encoding(thisname)) { if (!found_encoding) ptsize = 0; // force it to choose this found_encoding = 1; } else { if (found_encoding) continue; } char* c = (char*)fl_find_fontsize(thisname); int thissize = c ? atoi(c) : MAXSIZE; int thislength = strlen(thisname); if (thissize == size && thislength < matchedlength) { // exact match, use it: name = thisname; ptsize = size; matchedlength = thislength; } else if (!thissize && ptsize!=size) { // whoa! A scalable font! Use unless exact match found: int l = c-thisname; memcpy(namebuffer,thisname,l); l += snprintf(namebuffer+l, 1024-l,"%d",size); while (*c == '0') c++; strcpy(namebuffer+l,c); name = namebuffer; ptsize = size; } else if (!ptsize || // no fonts yet (thissize < ptsize && ptsize > size) || // current font too big (thissize > ptsize && thissize <= size) // current too small ) { name = thisname; ptsize = thissize; matchedlength = thislength; } } // if (ptsize != size) { // see if we already found this unscalable font: // for (f = s->first; f; f = f->next) { // if (f->minsize <= ptsize && f->maxsize >= ptsize) { // if (f->minsize > size) f->minsize = size; // if (f->maxsize < size) f->maxsize = size; // return f; // } // } // } // // // okay, we definately have some name, make the font: // f = new Fl_Font_Descriptor(name); // if (ptsize < size) {f->minsize = ptsize; f->maxsize = size;} // else {f->minsize = size; f->maxsize = ptsize;} // f->next = s->first; // s->first = f; // return f; return name; } static char *put_font_size(const char *n, int size) { int i = 0; char *buf; const char *ptr; const char *f; char *name; int nbf = 1; name = fl_strdup(n); while (name[i]) { if (name[i] == ',') {nbf++; name[i] = '\0';} i++; } buf = (char*) malloc(nbf * 256); buf[0] = '\0'; ptr = name; i = 0; while (ptr && nbf > 0) { f = find_best_font(ptr, size); while (*f) { buf[i] = *f; f++; i++; } nbf--; while (*ptr) ptr++; if (nbf) { ptr++; buf[i] = ','; i++; } while(isspace(*ptr)) ptr++; } buf[i] = '\0'; free(name); return buf; } char *fl_get_font_xfld(int fnum, int size) { Fl_Xlib_Fontdesc* s = ((Fl_Xlib_Fontdesc*)fl_fonts)+fnum; if (!s->name) s = (Fl_Xlib_Fontdesc*)fl_fonts; // use font 0 if still undefined fl_open_display(); return put_font_size(s->name, size); } // locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size: static Fl_Font_Descriptor* find(int fnum, int size) { char *name; Fl_Xlib_Fontdesc* s = ((Fl_Xlib_Fontdesc*)fl_fonts)+fnum; if (!s->name) s = (Fl_Xlib_Fontdesc*)fl_fonts; // use font 0 if still undefined Fl_Font_Descriptor* f; for (f = s->first; f; f = f->next) if (f->size == size) return f; fl_open_display(); name = put_font_size(s->name, size); f = new Fl_Xlib_Font_Descriptor(name); f->size = size; f->next = s->first; s->first = f; free(name); return f; } //////////////////////////////////////////////////////////////// // Public interface: void *fl_xftfont = 0; static GC font_gc; XFontStruct* Fl_XFont_On_Demand::value() { return ptr; } void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) { if (fnum==-1) { Fl_Graphics_Driver::font(0, 0); return; } if (fnum == Fl_Graphics_Driver::font() && size == Fl_Graphics_Driver::size()) return; Fl_Graphics_Driver::font(fnum, size); Fl_Xlib_Font_Descriptor* f = (Fl_Xlib_Font_Descriptor*)find(fnum, size); if (f != this->font_descriptor()) { this->font_descriptor(f); fl_xfont = f->font->fonts[0]; font_gc = 0; } } int Fl_Xlib_Graphics_Driver::height_unscaled() { if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->ascent + ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->descent; else return -1; } int Fl_Xlib_Graphics_Driver::descent_unscaled() { if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->descent; else return -1; } Fl_Fontsize Fl_Xlib_Graphics_Driver::size_unscaled() { if (font_descriptor()) return size_; return -1; } double Fl_Xlib_Graphics_Driver::width_unscaled(const char* c, int n) { if (font_descriptor()) return (double) XUtf8TextWidth(((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, c, n); else return -1; } double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) { if (font_descriptor()) return (double) XUtf8UcsWidth(((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, c); else return -1; } void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &W, int &H) { if (font_gc != gc_) { if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE); font_gc = gc_; XSetFont(fl_display, gc_, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->fid); } int xx, yy, ww, hh; xx = yy = ww = hh = 0; if (gc_) XUtf8_measure_extents(fl_display, fl_window, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, gc_, &xx, &yy, &ww, &hh, c, n); W = ww; H = hh; dx = xx; dy = yy; } void Fl_Xlib_Graphics_Driver::draw_unscaled(const char* c, int n, int x, int y) { // transform coordinates and clip if outside 16-bit space (STR 2798) int x1 = x + offset_x_; if (x1 < clip_min() || x1 > clip_max()) return; int y1 = y + offset_y_; if (y1 < clip_min() || y1 > clip_max()) return; if (font_gc != gc_) { if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE); font_gc = gc_; XSetFont(fl_display, gc_, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->fid); } if (gc_) XUtf8DrawString(fl_display, fl_window, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, gc_, x1, y1, c, n); } void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) { // clip if outside 16-bit space (STR 2798) if (x < clip_min() || x > clip_max()) return; if (y < clip_min() || y > clip_max()) return; static char warning = 0; // issue warning only once if (!warning && angle != 0) { warning = 1; fprintf(stderr, "libfltk: rotated text not implemented by X backend.\n" " You should use the Xft backend. Check USE_XFT in config.h.\n"); } this->draw(str, n, (int)x, (int)y); } void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int y) { // transform coordinates and clip if outside 16-bit space (STR 2798) int x1 = x + offset_x_; if (x1 < clip_min() || x1 > clip_max()) return; int y1 = y + offset_y_; if (y1 < clip_min() || y1 > clip_max()) return; if (font_gc != gc_) { if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE); font_gc = gc_; } if (gc_) XUtf8DrawRtlString(fl_display, fl_window, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, gc_, x1, y1, c, n); } float Fl_Xlib_Graphics_Driver::scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) { float ps_size = (float) s; // Non-Xft fonts can be smaller than required. // Set the PostScript font size to the display font height char *name = ((Fl_Xlib_Font_Descriptor*)desc)->font->font_name_list[0]; char *p = strstr(name, "--"); if (p) { sscanf(p + 2, "%f", &ps_size); } return ps_size; } float Fl_Xlib_Graphics_Driver::scale_bitmap_for_PostScript() { return 1; } #endif // FL_DOXYGEN fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx0000644000175000017500000014633015004135251025064 0ustar albrechtalbrecht// // More font utilities for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_DOXYGEN #include "../../flstring.h" #include "Fl_Xlib_Graphics_Driver.H" #if USE_PANGO # include "../Cairo/Fl_Cairo_Graphics_Driver.H" #endif #include #include #include // fl_strdup() #include #include #include "Fl_Font.H" #include #include #include #include #include Fl_XFont_On_Demand fl_xfont = 0; #if ! USE_PANGO // The predefined fonts that FLTK has with Xft but without Pango: static Fl_Fontdesc built_in_table[] = { #if 1 {" sans"}, {"Bsans"}, {"Isans"}, {"Psans"}, {" mono"}, {"Bmono"}, {"Imono"}, {"Pmono"}, {" serif"}, {"Bserif"}, {"Iserif"}, {"Pserif"}, {" symbol"}, {" screen"}, {"Bscreen"}, {" zapf dingbats"}, #else {" helvetica"}, {"Bhelvetica"}, {"Ihelvetica"}, {"Phelvetica"}, {" courier"}, {"Bcourier"}, {"Icourier"}, {"Pcourier"}, {" times"}, {"Btimes"}, {"Itimes"}, {"Ptimes"}, {" symbol"}, {" lucidatypewriter"}, {"Blucidatypewriter"}, {" zapf dingbats"}, #endif }; FL_EXPORT Fl_Fontdesc* fl_fonts = (Fl_Fontdesc*)built_in_table; #endif // ! USE_PANGO static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle); // For some reason Xft produces errors if you destroy a window whose id // still exists in an XftDraw structure. It would be nice if this is not // true, a lot of junk is needed to try to stop this: XftDraw* Fl_Xlib_Graphics_Driver::draw_ = 0; Window Fl_Xlib_Graphics_Driver::draw_window = (Window)0; Fl_Fontsize Fl_Xlib_Graphics_Driver::size_unscaled() { return (Fl_Fontsize)(size_); } static void correct_extents (float s, int &dx, int &dy, int &w, int &h) { if (int(s) == s) { // correct for extents non divisible by integral s int delta = dx - int(dx/s)*s; if (delta) { dx -= delta; w += delta; } delta = -dy - int((-dy)/s)*s; if (delta) { dy -= delta; h += delta; } delta = h - int(h/s)*s; if (delta) { h += delta; } delta = w - int(w/s)*s; if (delta) { w += delta; } } } #if ! USE_PANGO /////////////////////////////////////////////////////////// #define LOCAL_RAW_NAME_MAX 256 extern "C" { // sort returned fontconfig font names static int name_sort(const void *aa, const void *bb) { // What should we do here? Just do a string compare for now... // NOTE: This yeilds some oddities - in particular a Blah Bold font will be // listed before Blah... // Also - the fontconfig listing returns some faces that are effectively duplicates // as far as fltk is concerned, e.g. where there are ko or ja variants that we // can't distinguish (since we are not yet fully UTF-*) - should we strip them here? return fl_ascii_strcasecmp(*(char**)aa, *(char**)bb); } // end of name_sort } // end of extern C section // Read the "pretty" name we have derived from fontconfig then convert // it into the format fltk uses internally for Xft names... // This is just a mess - I should have tokenised the strings and gone from there, // but I really thought this would be easier! static void make_raw_name(char *raw, char *pretty) { // Input name will be "Some Name:style = Bold Italic" or whatever // The plan is this: // - the first char in the "raw" name becomes either I, B, P or " " for // italic, bold, bold italic or normal - this seems to be the fltk way... char *style = strchr(pretty, ':'); if (style) { *style = 0; // Terminate "name" string style ++; // point to start of style section } // It is still possible that the "pretty" name has multiple comma separated entries // I've seen this often in CJK fonts, for example... Keep only the first one... This // is not ideal, the CJK fonts often have the name in utf8 in several languages. What // we ought to do is use fontconfig to query the available languages and pick one... But which? #if 0 // loop to keep the LAST name entry... char *nm1 = pretty; char *nm2 = strchr(nm1, ','); while(nm2) { nm1 = nm2 + 1; nm2 = strchr(nm1, ','); } raw[0] = ' '; raw[1] = 0; // Default start of "raw name" text strncat(raw, nm1, LOCAL_RAW_NAME_MAX-1); // only copy MAX-1 chars, we have already set cell 0 // Ensure raw is terminated, just in case the given name is infeasibly long... raw[LOCAL_RAW_NAME_MAX-1] = 0; #else // keep the first remaining name entry char *nm2 = strchr(pretty, ','); if(nm2) *nm2 = 0; // terminate name after first entry raw[0] = ' '; raw[1] = 0; // Default start of "raw name" text strncat(raw, pretty, LOCAL_RAW_NAME_MAX-1); // only copy MAX-1 chars, we have already set cell 0 // Ensure raw is terminated, just in case the given name is infeasibly long... raw[LOCAL_RAW_NAME_MAX-1] = 0; #endif // At this point, the name is "marked" as regular... if (style) { #define PLAIN 0 #define BOLD 1 #define ITALIC 2 #define BITALIC (BOLD | ITALIC) int mods = PLAIN; char *last = style + strlen(style) - 2; // Now try and parse the style string - look for the "=" sign style = strchr(style, '='); while ((style) && (style < last)) { int type; while ((*style == '=') || (*style == ' ') || (*style == '\t') || (*style == ',')) { style++; // Start of Style string if ((style >= last) || (*style == 0)) continue; } type = toupper(style[0]); switch (type) { // Things we might see: Regular Normal Bold Italic Oblique (??what??) Medium // Roman Light Demi Sans SemiCondensed SuperBold Book... etc... // Things we actually care about: Bold Italic Oblique SuperBold - Others??? case 'I': if (strncasecmp(style, "Italic", 6) == 0) { mods |= ITALIC; } goto NEXT_STYLE; case 'B': if (strncasecmp(style, "Bold", 4) == 0) { if (!strstr(raw, " Demi Bold")) mods |= BOLD; } else if (strncasecmp(style, "Black", 5) == 0) { if (!strstr(raw, " Black")) strcat(raw, " Black"); } goto NEXT_STYLE; case 'D': if (strncasecmp(style, "Demi Bold", 7) == 0) { if (!strstr(raw, " Demi Bold")) strcat(raw, " Demi Bold"); } goto NEXT_STYLE; case 'O': if (strncasecmp(style, "Oblique", 7) == 0) { mods |= ITALIC; } goto NEXT_STYLE; case 'S': if (strncasecmp(style, "SuperBold", 9) == 0) { mods |= BOLD; } goto NEXT_STYLE; case 'L': if (strncasecmp(style, "Light", 5) == 0) { if (!strstr(raw, " Light")) strcat(raw, " Light"); } goto NEXT_STYLE; case 'M': if (strncasecmp(style, "Medium", 6) == 0) { if (!strstr(raw, " Medium")) strcat(raw, " Medium"); } goto NEXT_STYLE; default: // find the next gap goto NEXT_STYLE; } // switch end NEXT_STYLE: while ((*style != ' ') && (*style != '\t') && (*style != ',')) { style++; if ((style >= last) || (*style == 0)) goto STYLE_DONE; } } STYLE_DONE: // Set the "modifier" character in the raw string switch(mods) { case BOLD: raw[0] = 'B'; break; case ITALIC: raw[0] = 'I'; break; case BITALIC: raw[0] = 'P'; break; default: raw[0] = ' '; break; } } } // make_raw_name /////////////////////////////////////////////////////////// static int fl_free_font = FL_FREE_FONT; // This function fills in the fltk font table with all the fonts that // are found on the X server. It tries to place the fonts into families // and to sort them so the first 4 in a family are normal, bold, italic, // and bold italic. // Uses the fontconfig lib to construct a list of all installed fonts. // I tried using XftListFonts for this, but the API is tricky - and when // I looked at the XftList* code, it calls the Fc* functions anyway, so... // // Also, for now I'm ignoring the "pattern_name" and just getting everything... // AND I don't try and skip the fonts we've already loaded in the defaults. // Blimey! What a hack! Fl_Font Fl_Xlib_Graphics_Driver::set_fonts(const char* pattern_name) { FcFontSet *fnt_set; // Will hold the list of fonts we find FcPattern *fnt_pattern; // Holds the generic "match all names" pattern FcObjectSet *fnt_obj_set = 0; // Holds the generic "match all objects" int j; // loop iterator variable int font_count; // Total number of fonts found to process char **full_list; // The list of font names we build if (fl_free_font > FL_FREE_FONT) // already been here return (Fl_Font)fl_free_font; fl_open_display(); // Just in case... // Make sure fontconfig is ready... is this necessary? The docs say it is // safe to call it multiple times, so just go for it anyway! if (!FcInit()) { // What to do? Just return defaults... return FL_FREE_FONT; } // Create a search pattern that will match every font name - I think this // does the Right Thing, but am not certain... // // This could possibly be "enhanced" to pay attention to the requested // "pattern_name"? fnt_pattern = FcPatternCreate(); fnt_obj_set = FcObjectSetBuild(FC_FAMILY, FC_STYLE, (void *)0); // Hopefully, this is a set of all the fonts... fnt_set = FcFontList(0, fnt_pattern, fnt_obj_set); // We don't need the fnt_pattern and fnt_obj_set any more, release them FcPatternDestroy(fnt_pattern); FcObjectSetDestroy(fnt_obj_set); // Now, if we got any fonts, iterate through them... if (fnt_set) { char *stop; char *start; char *first; font_count = fnt_set->nfont; // How many fonts? // Allocate array of char*'s to hold the name strings full_list = (char **)malloc(sizeof(char *) * font_count); // iterate through all the font patterns and get the names out... for (j = 0; j < font_count; j++) { // NOTE: FcChar8 is a typedef of "unsigned char"... FcChar8 *font; // String to hold the font's name // Convert from fontconfig internal pattern to human readable name // NOTE: This WILL malloc storage, so we need to free it later... font = FcNameUnparse(fnt_set->fonts[j]); // The returned strings look like this... // Century Schoolbook:style=Bold Italic,fed kursiv,Fett Kursiv,... // So the bit we want is up to the first comma - BUT some strings have // more than one name, separated by, guess what?, a comma... stop = start = first = 0; stop = strchr((char *)font, ','); start = strchr((char *)font, ':'); if ((stop) && (start) && (stop < start)) { first = stop + 1; // discard first version of name // find first comma *after* the end of the name stop = strchr((char *)start, ','); } else { first = (char *)font; // name is just what was returned } // Truncate the name after the (english) modifiers description // Matt: Actually, there is no guarantee that the *first* description is the English one. // Matt: So we keep the entire description, just in case. //if (stop) //{ // *stop = 0; // Terminate the string at the first comma, if there is one //} // Copy the font description into our list if (first == (char *)font) { // The listed name is still OK full_list[j] = (char *)font; } else { // The listed name has been modified full_list[j] = fl_strdup(first); // Free the font name storage free (font); } // replace "style=Regular" so strcmp sorts it first if (start) { char *reg = strstr(full_list[j], "=Regular"); if (reg) reg[1]='.'; } } // Release the fnt_set - we don't need it any more FcFontSetDestroy(fnt_set); // Sort the list into alphabetic order qsort(full_list, font_count, sizeof(*full_list), name_sort); // Now let us add the names we got to fltk's font list... for (j = 0; j < font_count; j++) { if (full_list[j]) { char xft_name[LOCAL_RAW_NAME_MAX]; char *stored_name; // Parse the strings into FLTK-XFT style.. make_raw_name(xft_name, full_list[j]); // NOTE: This just adds on AFTER the default fonts - no attempt is made // to identify already loaded fonts. Is this bad? stored_name = fl_strdup(xft_name); Fl::set_font((Fl_Font)(j + FL_FREE_FONT), stored_name); fl_free_font ++; free(full_list[j]); // release that name from our internal array } } // Now we are done with the list, release it fully free(full_list); } return (Fl_Font)fl_free_font; } // ::set_fonts //////////////////////////////////////////////////////////////// // // Draw fonts using Keith Packard's Xft library to provide anti- // aliased text. Yow! // // Many thanks to Carl for making the original version of this. // // This font code only requires libXft to work. Contrary to popular // belief there is no need to have FreeType, or the Xrender extension // available to use this code. You will just get normal Xlib fonts // (Xft calls them "core" fonts) The Xft algorithms for choosing // these is about as good as the FLTK ones (I hope to fix it so it is // exactly as good...), plus it can cache its results and share them // between programs, so using this should be a win in all cases. Also // it should be obvious by comparing this file and fl_font_x.cxx that // it is a lot easier to program with Xft than with Xlib. // // Also, Xft supports UTF-8 text rendering directly, which will allow // us to support UTF-8 on all platforms more easily. // // To actually get antialiasing you need the following: // // 1. You have XFree86 4 // 2. You have the XRender extension // 3. Your X device driver supports the render extension // 4. You have libXft // 5. Your libXft has FreeType2 support compiled in // 6. You have the FreeType2 library // // Distributions that have XFree86 4.0.3 or later should have all of this... // // Unlike some other Xft packages, I tried to keep this simple and not // to work around the current problems in Xft by making the "patterns" // complicated. I believe doing this defeats our ability to improve Xft // itself. You should edit the ~/.xftconfig file to "fix" things, there // are several web pages of information on how to do this. // //static const char* fl_encoding_ = "iso8859-1"; static const char* fl_encoding_ = "iso10646-1"; void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) { fl_xft_font(this, fnum, size, 0); } static XftFont* fontopen(const char* name, /*Fl_Fontsize*/double size, bool core, int angle) { // Check: does it look like we have been passed an old-school XLFD fontname? bool is_xlfd = false; int hyphen_count = 0; int comma_count = 0; unsigned len = strlen(name); if (len > 512) len = 512; // ensure we are not passed an unbounded font name for(unsigned idx = 0; idx < len; idx++) { if(name[idx] == '-') hyphen_count++; // check for XLFD hyphens if(name[idx] == ',') comma_count++; // are there multiple names? } if(hyphen_count >= 14) is_xlfd = true; // Not a robust check, but good enough? fl_open_display(); if(!is_xlfd) { // Not an XLFD - open as a XFT style name XftFont *the_font = NULL; // the font we will return; XftPattern *fnt_pat = XftPatternCreate(); // the pattern we will use for matching int slant = XFT_SLANT_ROMAN; int weight = XFT_WEIGHT_MEDIUM; /* This "converts" FLTK-style font names back into "regular" names, extracting * the BOLD and ITALIC codes as it does so - all FLTK font names are prefixed * by 'I' (italic) 'B' (bold) 'P' (bold italic) or ' ' (regular) modifiers. * This gives a fairly limited font selection ability, but is retained for * compatibility reasons. If you really need a more complex choice, you are best * calling Fl::set_fonts(*) then selecting the font by font-index rather than by * name anyway. Probably. * If you want to load a font who's name does actually begin with I, B or P, you * MUST use a leading space OR simply use lowercase for the name... */ /* This may be efficient, but it is non-obvious. */ switch (*name++) { case 'I': slant = XFT_SLANT_ITALIC; break; // italic case 'P': slant = XFT_SLANT_ITALIC; // bold-italic (falls-through) case 'B': weight = XFT_WEIGHT_BOLD; break; // bold case ' ': break; // regular default: name--; // no prefix, restore name } if(comma_count) { // multiple comma-separated names were passed char *local_name = fl_strdup(name); // duplicate the full name so we can edit the copy char *curr = local_name; // points to first name in string char *nxt; // next name in string do { nxt = strchr(curr, ','); // find comma separator if (nxt) { *nxt = 0; // terminate first name nxt++; // first char of next name } // Add the current name to the match pattern XftPatternAddString(fnt_pat, XFT_FAMILY, curr); if(nxt) curr = nxt; // move onto next name (if it exists) // Now do a cut-down version of the FLTK name conversion. // NOTE: we only use the slant and weight of the first name, // subsequent names we ignore this for... But we still need to do the check. switch (*curr++) { case 'I': break; // italic case 'P': // bold-italic (falls-through) case 'B': break; // bold case ' ': break; // regular default: curr--; // no prefix, restore name } comma_count--; // decrement name sections count } while (comma_count >= 0); free(local_name); // release our local copy of font names } else { // single name was passed - add it directly XftPatternAddString(fnt_pat, XFT_FAMILY, name); } // Construct a match pattern for the font we want... XftPatternAddInteger(fnt_pat, XFT_WEIGHT, weight); XftPatternAddInteger(fnt_pat, XFT_SLANT, slant); XftPatternAddDouble (fnt_pat, XFT_PIXEL_SIZE, (double)size); XftPatternAddString (fnt_pat, XFT_ENCODING, fl_encoding_); // rotate font if angle!=0 if (angle !=0) { XftMatrix m; XftMatrixInit(&m); XftMatrixRotate(&m,cos(M_PI*angle/180.),sin(M_PI*angle/180.)); XftPatternAddMatrix (fnt_pat, XFT_MATRIX,&m); } if (core) { XftPatternAddBool(fnt_pat, XFT_CORE, FcTrue); XftPatternAddBool(fnt_pat, XFT_RENDER, FcFalse); } XftPattern *match_pat; // the best available match on the system XftResult match_result; // the result of our matching attempt // query the system to find a match for this font match_pat = XftFontMatch(fl_display, fl_screen, fnt_pat, &match_result); #if 0 // the XftResult never seems to get set to anything... abandon this code? switch(match_result) { // how good a match is this font for our request? case XftResultMatch: puts("Object exists with the specified ID"); break; case XftResultTypeMismatch: puts("Object exists, but the type does not match"); break; case XftResultNoId: puts("Object exists, but has fewer values than specified"); break; case FcResultOutOfMemory: puts("FcResult: Malloc failed"); break; case XftResultNoMatch: puts("Object does not exist at all"); break; default: printf("Invalid XftResult status %d \n", match_result); break; } #endif #if 0 // diagnostic to print the "full name" of the font we matched. This works. FcChar8 *picked_name = FcNameUnparse(match_pat); printf("Match: %s\n", picked_name); free(picked_name); #endif // open the matched font if (match_pat) the_font = XftFontOpenPattern(fl_display, match_pat); if (!match_pat || !the_font) { // last chance, just open any font in the right size the_font = XftFontOpen (fl_display, fl_screen, XFT_FAMILY, XftTypeString, "sans", XFT_SIZE, XftTypeDouble, (double)size, NULL); XftPatternDestroy(fnt_pat); if (!the_font) { Fl::error("Unable to find fonts. Check your FontConfig configuration.\n"); exit(1); } return the_font; } #if 0 // diagnostic to print the "full name" of the font we actually opened. This works. FcChar8 *picked_name2 = FcNameUnparse(the_font->pattern); printf("Open : %s\n", picked_name2); free(picked_name2); #endif XftPatternDestroy(fnt_pat); // XftPatternDestroy(match_pat); // FontConfig will destroy this resource for us. We must not! return the_font; } else { // We were passed a font name in XLFD format /* OksiD's X font code could handle being passed a comma separated list * of XLFD's. It then attempted to find which font was "best" from this list. * But XftFontOpenXlfd can not do this, so if a list is passed, we just * terminate it at the first comma. * A "better" solution might be to use XftXlfdParse() on each of the passed * XLFD's to construct a "super-pattern" that incorporates attributes from all * XLFD's and use that to perform a XftFontMatch(). Maybe... */ char *local_name = fl_strdup(name); if(comma_count) { // This means we were passed multiple XLFD's char *pc = strchr(local_name, ','); *pc = 0; // terminate the XLFD at the first comma } XftFont *the_font = XftFontOpenXlfd(fl_display, fl_screen, local_name); free(local_name); #if 0 // diagnostic to print the "full name" of the font we actually opened. This works. puts("Font Opened"); fflush(stdout); FcChar8 *picked_name2 = FcNameUnparse(the_font->pattern); printf("Open : %s\n", picked_name2); fflush(stdout); free(picked_name2); #endif return the_font; } } // end of fontopen Fl_Xlib_Font_Descriptor::Fl_Xlib_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) : Fl_Font_Descriptor(name, fsize) { // encoding = fl_encoding_; angle = fangle; font = fontopen(name, fsize, false, angle); } /* decodes the input UTF-8 string into a series of wchar_t characters. n is set upon return to the number of characters. Don't deallocate the returned memory. */ static const wchar_t *utf8reformat(const char *str, int& n) { static const wchar_t empty[] = {0}; static wchar_t *buffer; static int lbuf = 0; int newn; if (n == 0) return empty; newn = fl_utf8towc(str, n, (wchar_t*)buffer, lbuf); if (newn >= lbuf) { lbuf = newn + 100; if (buffer) free(buffer); buffer = (wchar_t*)malloc(lbuf * sizeof(wchar_t)); n = fl_utf8towc(str, n, (wchar_t*)buffer, lbuf); } else { n = newn; } return buffer; } static void utf8extents(Fl_Xlib_Font_Descriptor *desc, const char *str, int n, XGlyphInfo *extents) { memset(extents, 0, sizeof(XGlyphInfo)); const wchar_t *buffer = utf8reformat(str, n); #ifdef __CYGWIN__ XftTextExtents16(fl_display, desc->font, (XftChar16 *)buffer, n, extents); #else XftTextExtents32(fl_display, desc->font, (XftChar32 *)buffer, n, extents); #endif } int Fl_Xlib_Graphics_Driver::height_unscaled() { if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->ascent + ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->descent; else return -1; } int Fl_Xlib_Graphics_Driver::descent_unscaled() { if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->descent; else return -1; } double Fl_Xlib_Graphics_Driver::width_unscaled(const char* str, int n) { if (!font_descriptor()) return -1.0; XGlyphInfo i; utf8extents((Fl_Xlib_Font_Descriptor*)font_descriptor(), str, n, &i); return i.xOff; } static double fl_xft_width(Fl_Font_Descriptor *desc, FcChar32 *str, int n) { if (!desc) return -1.0; XGlyphInfo i; XftTextExtents32(fl_display, ((Fl_Xlib_Font_Descriptor*)desc)->font, str, n, &i); return i.xOff; } double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) { if (!font_descriptor()) return -1.0; return fl_xft_width(font_descriptor(), (FcChar32 *)(&c), 1); } void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &w, int &h) { if (!font_descriptor()) { w = h = 0; dx = dy = 0; return; } XGlyphInfo gi; utf8extents((Fl_Xlib_Font_Descriptor*)font_descriptor(), c, n, &gi); w = gi.width; h = gi.height; dx = -gi.x ; dy = -gi.y ; correct_extents(scale(), dx, dy, w, h); } void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y) { // transform coordinates and clip if outside 16-bit space (STR 2798) int x1 = x + floor(offset_x_) ; if (x1 < clip_min() || x1 > clip_max()) return; int y1 = y + floor(offset_y_) ; if (y1 < clip_min() || y1 > clip_max()) return; if (!draw_) draw_ = XftDrawCreate(fl_display, draw_window = fl_window, fl_visual->visual, fl_colormap); else //if (draw_window != fl_window) XftDrawChange(draw_, draw_window = fl_window); Region region = (Region)fl_clip_region(); if (!(region && XEmptyRegion(region))) { XftDrawSetClip(draw_, region); // Use fltk's color allocator, copy the results to match what // XftCollorAllocValue returns: XftColor color; color.pixel = fl_xpixel(Fl_Graphics_Driver::color()); uchar r,g,b; Fl::get_color(Fl_Graphics_Driver::color(), r,g,b); color.color.red = ((int)r)*0x101; color.color.green = ((int)g)*0x101; color.color.blue = ((int)b)*0x101; color.color.alpha = 0xffff; const wchar_t *buffer = utf8reformat(str, n); #ifdef __CYGWIN__ XftDrawString16(draw_, &color, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, x1, y1, (XftChar16 *)buffer, n); #else XftDrawString32(draw_, &color, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, x1, y1, (XftChar32 *)buffer, n); #endif } } void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) { fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size_unscaled(), angle); this->draw_unscaled(str, n, x, y); fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size_unscaled(), 0); } void Fl_Xlib_Graphics_Driver::drawUCS4(const void *str, int n, int x, int y) { if (!draw_) draw_ = XftDrawCreate(fl_display, draw_window = fl_window, fl_visual->visual, fl_colormap); else //if (draw_window != fl_window) XftDrawChange(draw_, draw_window = fl_window); Region region = (Region)fl_clip_region(); if (region && XEmptyRegion(region)) return; XftDrawSetClip(draw_, region); // Use fltk's color allocator, copy the results to match what // XftCollorAllocValue returns: XftColor color; color.pixel = fl_xpixel(this->color()); uchar r,g,b; Fl::get_color(this->color(), r,g,b); color.color.red = ((int)r)*0x101; color.color.green = ((int)g)*0x101; color.color.blue = ((int)b)*0x101; color.color.alpha = 0xffff; XftDrawString32(draw_, &color, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, x+floor(offset_x_), y+floor(offset_y_), (FcChar32 *)str, n); } void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int y) { // clip if outside 16-bit space (STR 2798) if (x < clip_min() || x > clip_max()) return; if (y < clip_min() || y > clip_max()) return; #if defined(__GNUC__) // FIXME: warning Need to improve this XFT right to left draw function #endif /*__GNUC__*/ // This actually draws LtoR, but aligned to R edge with the glyph order reversed... // but you can't just byte-rev a UTF-8 string, that isn't valid. // You can reverse a UCS4 string though... int num_chars, wid, utf_len = strlen(c); FcChar8 *u8 = (FcChar8 *)c; FcBool valid = FcUtf8Len(u8, utf_len, &num_chars, &wid); if (!valid) { // badly formed Utf-8 input string return; } if (num_chars < n) n = num_chars; // limit drawing to usable characters in input array FcChar32 *ucs_txt = new FcChar32[n+1]; FcChar32* pu; int out, sz; ucs_txt[n] = 0; out = n-1; while ((out >= 0) && (utf_len > 0)) { pu = &ucs_txt[out]; sz = FcUtf8ToUcs4(u8, pu, utf_len); utf_len = utf_len - sz; u8 = u8 + sz; out = out - 1; } // Now we have a UCS4 version of the input text, reversed, in ucs_txt int offs = (int)fl_xft_width(font_descriptor(), ucs_txt, n); drawUCS4(ucs_txt, n, (x-offs), y); delete[] ucs_txt; } extern "C" { static int int_sort(const void *aa, const void *bb) { return (*(int*)aa)-(*(int*)bb); } } //////////////////////////////////////////////////////////////// // Return all the point sizes supported by this font: // Suprisingly enough Xft works exactly like fltk does and returns // the same list. Except there is no way to tell if the font is scalable. int Fl_Xlib_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) { Fl_Fontdesc *s = fl_fonts+fnum; if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 fl_open_display(); XftFontSet* fs = XftListFonts(fl_display, fl_screen, XFT_FAMILY, XftTypeString, s->name+1, (void *)0, XFT_PIXEL_SIZE, (void *)0); static int* array = 0; static int array_size = 0; if (fs->nfont >= array_size) { delete[] array; array = new int[array_size = fs->nfont+1]; } array[0] = 0; int j = 1; // claim all fonts are scalable for (int i = 0; i < fs->nfont; i++) { double v; if (XftPatternGetDouble(fs->fonts[i], XFT_PIXEL_SIZE, 0, &v) == XftResultMatch) { array[j++] = int(v); } } qsort(array+1, j-1, sizeof(int), int_sort); XftFontSetDestroy(fs); sizep = array; return j; } #endif // !USE_PANGO float Fl_Xlib_Graphics_Driver::scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) { // Xft font height is sometimes larger than the required size (see STR 2566). // Increase the PostScript font size by 15% without exceeding the display font height int max = height_unscaled(); float ps_size = s * 1.15; if (ps_size > max) ps_size = max; return ps_size; } // Bug: older versions calculated the value for *ap as a side effect of // making the name, and then forgot about it. To avoid having to change // the header files I decided to store this value in the last character // of the font name array. #define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 // turn a stored font name in "fltk format" into a pretty name: const char* Fl_Xlib_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) { Fl_Fontdesc *f = fl_fonts + fnum; if (!f->fontname[0]) { const char* p = f->name; int type; #if USE_PANGO type = 0; if (strstr(p, " Bold")) type = FL_BOLD; if (strstr(p, " Italic") || strstr(p, " Oblique")) type += FL_ITALIC; strlcpy(f->fontname, p, ENDOFBUFFER); #else switch (p[0]) { case 'B': type = FL_BOLD; break; case 'I': type = FL_ITALIC; break; case 'P': type = FL_BOLD | FL_ITALIC; break; default: type = 0; break; } // NOTE: This can cause duplications in fonts that already have Bold or Italic in // their "name". Maybe we need to find a cleverer way? strlcpy(f->fontname, p+1, ENDOFBUFFER); if (type & FL_BOLD) strlcat(f->fontname, " bold", ENDOFBUFFER); if (type & FL_ITALIC) strlcat(f->fontname, " italic", ENDOFBUFFER); #endif // USE_PANGO f->fontname[ENDOFBUFFER] = (char)type; } if (ap) *ap = f->fontname[ENDOFBUFFER]; return f->fontname; } Fl_Xlib_Font_Descriptor::~Fl_Xlib_Font_Descriptor() { if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL); // XftFontClose(fl_display, font); #if USE_PANGO if (width) for (int i = 0; i < 64; i++) delete[] width[i]; delete[] width; #endif } void Fl_Xlib_Graphics_Driver::destroy_xft_draw(Window id) { if (id == draw_window) XftDrawChange(draw_, draw_window = fl_message_window); } void *fl_xftfont = 0; // always 0 under Pango static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle) { if (fnum==-1) { // special case to stop font caching driver->Fl_Graphics_Driver::font(0, 0); return; } Fl_Xlib_Font_Descriptor* f = (Fl_Xlib_Font_Descriptor*)driver->font_descriptor(); if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size_unscaled() && f && f->angle == angle) return; driver->Fl_Graphics_Driver::font(fnum, size); Fl_Fontdesc *font = fl_fonts + fnum; // search the fontsizes we have generated already for (f = (Fl_Xlib_Font_Descriptor*)font->first; f; f = (Fl_Xlib_Font_Descriptor*)f->next) { if (f->size == size && f->angle == angle)// && !strcasecmp(f->encoding, fl_encoding_)) break; } if (!f) { f = new Fl_Xlib_Font_Descriptor(font->name, size, angle); f->next = font->first; font->first = f; } driver->font_descriptor(f); #if XFT_MAJOR < 2 && ! USE_PANGO fl_xfont = f->font->u.core.font; #else fl_xfont = NULL; // invalidate #endif // XFT_MAJOR < 2 #if USE_PANGO fl_xftfont = NULL; #else fl_xftfont = (void*)f->font; #endif } /* This code is used (mainly by opengl) to get a bitmapped font. The * original XFT-1 code used XFT's "core" fonts methods to load an XFT * font that was actually a X-bitmap font, that could then be readily * used with GL. But XFT-2 does not provide that ability, and there * is no easy method to use an XFT font directly with GL. So... */ # if XFT_MAJOR > 1 || USE_PANGO // This function attempts, on XFT2 systems, to find a suitable "core" Xfont // for GL or other bitmap font needs (we dont have an XglUseXftFont(...) function.) // There's probably a better way to do this. I can't believe it is this hard... // Anyway... This code attempts to make an XLFD out of the fltk-style font // name it is passed, then tries to load that font. Surprisingly, this quite // often works - boxes that have XFT generally also have a fontserver that // can serve TTF and other fonts to X, and so the font name that fltk makes // from the XFT name often also "exists" as an "core" X font... // If this code fails to load the requested font, it falls back through a // series of tried 'n tested alternatives, ultimately resorting to what the // original fltk code did. // NOTE: On my test boxes (FC6, FC7, FC8, ubuntu8.04, 9.04, 9.10) this works // well for the fltk "built-in" font names. static XFontStruct* load_xfont_for_xft2(Fl_Graphics_Driver *driver) { XFontStruct* xgl_font = 0; int size = ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled(); int fnum = driver->font(); const char *wt_med = "medium"; const char *wt_bold = "bold"; const char *weight = wt_med; // no specifc weight requested - accept any char slant = 'r'; // regular non-italic by default char xlfd[128]; // we will put our synthetic XLFD in here char *pc = fl_strdup(fl_fonts[fnum].name); // what font were we asked for? #if USE_PANGO char *p = pc + 1; while (*p) { *p = tolower(*p); p++; } #endif // USE_PANGO const char *name = pc; // keep a handle to the original name for freeing later // Parse the "fltk-name" of the font switch (*name++) { case 'I': slant = 'i'; break; // italic case 'P': slant = 'i'; // bold-italic (falls-through) case 'B': weight = wt_bold; break; // bold case ' ': break; // regular default: name--; // no prefix, restore name } // first, we do a query with no prefered size, to see if the font exists at all snprintf(xlfd, 128, "-*-%s-%s-%c-*--*-*-*-*-*-*-*-*", name, weight, slant); // make up xlfd style name xgl_font = XLoadQueryFont(fl_display, xlfd); if(xgl_font) { // the face exists, but can we get it in a suitable size? XFreeFont(fl_display, xgl_font); // release the non-sized version snprintf(xlfd, 128, "-*-%s-%s-%c-*--*-%d-*-*-*-*-*-*", name, weight, slant, (size*10)); xgl_font = XLoadQueryFont(fl_display, xlfd); // attempt to load the font at the right size } //puts(xlfd); // try alternative names if (!xgl_font) { if (!strcmp(name, "sans")) { name = "helvetica"; if (slant == 'i') slant = 'o'; } else if (!strcmp(name, "mono") || !strcmp(name, "monospace")) { name = "courier"; } else if (!strcmp(name, "serif")) { name = "times"; } else if (!strcmp(name, "screen")) { name = "lucidatypewriter"; } else if (!strcmp(name, "dingbats")) { name = "zapf dingbats"; } snprintf(xlfd, 128, "-*-*%s*-%s-%c-*--*-%d-*-*-*-*-*-*", name, weight, slant, (size*10)); xgl_font = XLoadQueryFont(fl_display, xlfd); } free(pc); // release our copy of the font name // if we have nothing loaded, try a generic proportional font if(!xgl_font) { snprintf(xlfd, 128, "-*-helvetica-*-%c-*--*-%d-*-*-*-*-*-*", slant, (size*10)); xgl_font = XLoadQueryFont(fl_display, xlfd); } // If that still didn't work, try courier with resquested weight and slant if(!xgl_font && weight != wt_med) { snprintf(xlfd, 128, "-*-courier*-%s-%c-*--*-%d-*-*-*-*-*-*", weight, slant, (size*10)); xgl_font = XLoadQueryFont(fl_display, xlfd); } // If that still didn't work, try this instead if(!xgl_font) { snprintf(xlfd, 128, "-*-courier*-medium-%c-*--*-%d-*-*-*-*-*-*", slant, (size*10)); xgl_font = XLoadQueryFont(fl_display, xlfd); } //printf("glf: %d\n%s\n%s\n", size, xlfd, fl_fonts[fl_font_].name); //if(xgl_font) puts("ok"); // Last chance fallback - this usually loads something... if (!xgl_font) xgl_font = XLoadQueryFont(fl_display, "fixed"); return xgl_font; } // end of load_xfont_for_xft2 # endif static XFontStruct* fl_xxfont(Fl_Graphics_Driver *driver) { # if XFT_MAJOR > 1 || USE_PANGO // kludge! XFT 2 and later does not provide core fonts for us to use with GL // try to load a bitmap X font instead static XFontStruct* xgl_font = 0; static int glsize = 0; static int glfont = -1; // Do we need to load a new font? if ((!xgl_font) || (glsize != ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled()) || (glfont != driver->font())) { // create a dummy XLFD for some font of the appropriate size... if (xgl_font) XFreeFont(fl_display, xgl_font); // font already loaded, free it - this *might* be a Bad Idea glsize = ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled(); // record current font size glfont = driver->font(); // and face xgl_font = load_xfont_for_xft2(driver); } return xgl_font; # else // XFT-1 provides a means to load a "core" font directly if (driver->font_descriptor()->font->core) { return driver->font_descriptor()->font->u.core.font; // is the current font a "core" font? If so, use it. } static XftFont* xftfont; if (xftfont) XftFontClose (fl_display, xftfont); xftfont = fontopen(fl_fonts[driver->font()].name, ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled(), true, 0); // else request XFT to load a suitable "core" font instead. return xftfont->u.core.font; # endif // XFT_MAJOR > 1 } XFontStruct* Fl_XFont_On_Demand::value() { if (!ptr) ptr = fl_xxfont(fl_graphics_driver); return ptr; } #if USE_PANGO #include #include #if ! PANGO_VERSION_CHECK(1,8,0) #error "Requires Pango 1.8 or higher" #endif PangoFontMap *Fl_Xlib_Graphics_Driver::pfmap_ = 0; PangoContext *Fl_Xlib_Graphics_Driver::pctxt_ = 0; PangoLayout *Fl_Xlib_Graphics_Driver::playout_ = 0; PangoContext *Fl_Xlib_Graphics_Driver::context() { if (fl_display && !pctxt_) { pfmap_ = pango_xft_get_font_map(fl_display, fl_screen); // 1.2 #if PANGO_VERSION_CHECK(1,22,0) pctxt_ = pango_font_map_create_context(pfmap_); // 1.22 #else pctxt_ = pango_xft_get_context(fl_display, fl_screen); // deprecated since 1.22 #endif playout_ = pango_layout_new(pctxt_); } return pctxt_; } void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) { if (!size) return; if (size < 0) { Fl_Graphics_Driver::font(0, 0); return; } if (this->Fl_Graphics_Driver::font() == fnum && this->size_unscaled() == size && this->font_descriptor()) { pango_font_description_set_absolute_size(pfd_array[fnum], size*PANGO_SCALE); // 1.8 return; } fl_xft_font(this, fnum, size, 0); init_built_in_fonts(); if (fnum >= pfd_array_length) { int new_length = fnum + 10; PangoFontDescription **data = (PangoFontDescription**)calloc(new_length, sizeof(PangoFontDescription*)); memcpy(data, pfd_array, pfd_array_length*sizeof(PangoFontDescription*)); free(pfd_array); pfd_array = data; pfd_array_length = new_length; } if (!pfd_array[fnum]) { pfd_array[fnum] = pango_font_description_from_string(Fl::get_font_name(fnum)); } pango_font_description_set_absolute_size(pfd_array[fnum], size*PANGO_SCALE); // 1.8 if (!pctxt_) context(); Fl_Xlib_Font_Descriptor *fd = (Fl_Xlib_Font_Descriptor*)font_descriptor(); if (!fd->height_) { PangoFont *pfont = pango_font_map_load_font(pfmap_, pctxt_, pfd_array[fnum]); PangoRectangle logical_rect; pango_font_get_glyph_extents(pfont, /*PangoGlyph glyph*/'p', NULL, &logical_rect); fd->descent_ = PANGO_DESCENT(logical_rect)/PANGO_SCALE; fd->height_ = logical_rect.height/PANGO_SCALE; if (fd->height_ == 0) { // this occurs with some fonts PangoFontMetrics *pfmt = pango_font_get_metrics(pfont, pango_script_get_sample_language(PANGO_SCRIPT_LATIN) /* 1.4 */); fd->descent_ = pango_font_metrics_get_descent(pfmt)/PANGO_SCALE; fd->height_ = (pango_font_metrics_get_ascent(pfmt) + pango_font_metrics_get_descent(pfmt))/PANGO_SCALE ; pango_font_metrics_unref(pfmt); } } } void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y) { do_draw(0, str, n, x + floor(offset_x_), y + floor(offset_y_)); } void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) { PangoMatrix mat = PANGO_MATRIX_INIT; // 1.6 pango_matrix_translate(&mat, x + floor(offset_x_), y + floor(offset_y_)); // 1.6 double l = width_unscaled(str, n); pango_matrix_rotate(&mat, angle); // 1.6 pango_context_set_matrix(pctxt_, &mat); // 1.6 str = Fl_Cairo_Graphics_Driver::clean_utf8(str, n); pango_layout_set_text(playout_, str, n); int w, h; pango_layout_get_pixel_size(playout_, &w, &h); pango_matrix_scale(&mat, l/w, l/w); // 1.6 pango_context_set_matrix(pctxt_, &mat); // 1.6 do_draw(0, str, n, 0, 0); pango_context_set_matrix(pctxt_, NULL); // 1.6 } void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* str, int n, int x, int y) { do_draw(1, str, n, x+floor(offset_x_), y+floor(offset_y_)); } /* Compute dx, dy, w, h so that fl_rect(x+dx, y+dy, w, h) is the bounding box of text drawn by fl_draw(str, n, x, y). Also, compute y_correction to be used to correct the text's y coordinate to make sure drawn text does not extend below the bottom of the line of text. */ static void fl_pango_layout_get_pixel_extents(PangoLayout *layout, int &dx, int &dy, int &w, int &h, int desc, int lheight, int &y_correction) { PangoRectangle ink_rect; pango_layout_get_pixel_extents(layout, &ink_rect, NULL); dx = ink_rect.x; dy = ink_rect.y - lheight + desc; w = ink_rect.width; h = ink_rect.height; int y = ink_rect.y + ink_rect.height; y_correction = (y > lheight ? y - lheight : 0); } void Fl_Xlib_Graphics_Driver::do_draw(int from_right, const char *str, int n, int x, int y) { if (!fl_display || n == 0) return; Region region = (Region)clip_region(); if (region && XEmptyRegion(region)) return; if (!playout_) context(); char *str2 = NULL; const char *tmpv = (const char *)memchr(str, '\n', n); if (tmpv == str + n - 1) { // ignore final '\n' if (--n == 0) return; tmpv = NULL; } pango_layout_set_font_description(playout_, pfd_array[font_]); if (tmpv) { // replace newlines by spaces in a copy of str str2 = (char*)malloc(n); memcpy(str2, str, n); do { str2[tmpv - str] = ' '; if (tmpv >= str + n - 1) break; tmpv = (const char *)memchr(tmpv + 1, '\n', n - (tmpv - str + 1)); } while (tmpv); str = str2; } const char *old = 0; if (!str2) old = pango_layout_get_text(playout_); str = Fl_Cairo_Graphics_Driver::clean_utf8(str, n); if (!old || (int)strlen(old) != n || memcmp(str, old, n)) // do not re-set text if equal to text already in layout pango_layout_set_text(playout_, str, n); if (str2) free(str2); XftColor color; Fl_Color c = this->color(); color.pixel = fl_xpixel(c); uchar r,g,b; Fl::get_color(c, r,g,b); color.color.red = ((int)r)*0x101; color.color.green = ((int)g)*0x101; color.color.blue = ((int)b)*0x101; color.color.alpha = 0xffff; if (!draw_) draw_ = XftDrawCreate(fl_display, draw_window = fl_window, fl_visual->visual, fl_colormap); else XftDrawChange(draw_, draw_window = fl_window); XftDrawSetClip(draw_, region); int dx, dy, w, h, y_correction, desc = descent_unscaled(), lheight = height_unscaled(); fl_pango_layout_get_pixel_extents(playout_, dx, dy, w, h, desc, lheight, y_correction); if (from_right) { x -= w; } pango_xft_render_layout(draw_, &color, playout_, x * PANGO_SCALE, (y - y_correction - lheight + desc) * PANGO_SCALE ); // 1.8 } // cache the widths of single Unicode characters double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int utf32) { unsigned r=0; Fl_Xlib_Font_Descriptor *desc = NULL; if (utf32 <= 0xFFFF) { desc = (Fl_Xlib_Font_Descriptor*)font_descriptor(); r = (utf32 & 0xFC00) >> 10; if (!desc->width) { desc->width = (int**)new int*[64]; memset(desc->width, 0, 64*sizeof(int*)); } if (!desc->width[r]) { desc->width[r] = (int*)new int[0x0400]; for (int i = 0; i < 0x0400; i++) desc->width[r][i] = -1; } else { if ( desc->width[r][utf32&0x03FF] >= 0 ) { // already cached return double(desc->width[r][utf32 & 0x03FF]); } } } char buf4[4]; int n = fl_utf8encode(utf32, buf4); double width = do_width_unscaled_(buf4, n); if (utf32 <= 0xFFFF) { desc->width[r][utf32 & 0x03FF] = (int)width; } return width; } double Fl_Xlib_Graphics_Driver::width_unscaled(const char* str, int n) { if ((str == NULL) || (n == 0)) return 0.; if (n == fl_utf8len(*str)) { // str contains a single unicode character int l; unsigned c = fl_utf8decode(str, str+n, &l); return width_unscaled(c); // that character's width may have been cached } return do_width_unscaled_(str, n); // full width computation for multi-char strings } double Fl_Xlib_Graphics_Driver::do_width_unscaled_(const char* str, int n) { if (!n) return 0; if (!fl_display || size_ == 0) return -1; if (!playout_) context(); int width, height; pango_layout_set_font_description(playout_, pfd_array[font_]); str = Fl_Cairo_Graphics_Driver::clean_utf8(str, n); pango_layout_set_text(playout_, str, n); pango_layout_get_pixel_size(playout_, &width, &height); return (double)width; } void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *str, int n, int &dx, int &dy, int &w, int &h) { if (!playout_) context(); pango_layout_set_font_description(playout_, pfd_array[font_]); str = Fl_Cairo_Graphics_Driver::clean_utf8(str, n); pango_layout_set_text(playout_, str, n); int y_correction; fl_pango_layout_get_pixel_extents(playout_, dx, dy, w, h, descent_unscaled(), height_unscaled(), y_correction); dy -= y_correction; correct_extents(scale(), dx, dy, w, h); } int Fl_Xlib_Graphics_Driver::height_unscaled() { if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->height_; else return -1; } int Fl_Xlib_Graphics_Driver::descent_unscaled() { if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->descent_; else return -1; } // FIXME: this (static) function should likely be in Fl_Graphics_Driver. // The code is the same as in src/drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx static int font_name_process(const char *name, char &face) { int l = strlen(name); face = ' '; if (l > 8 && !memcmp(name + l - 8, " Regular", 8)) l -= 8; else if (l > 6 && !memcmp(name + l - 6, " Plain", 6)) l -= 6; else if (l > 12 && !memcmp(name + l - 12, " Bold Italic", 12)) {l -= 12; face = 'P';} else if (l > 7 && !memcmp(name + l - 7, " Italic", 7)) {l -= 7; face = 'I';} else if (l > 5 && !memcmp(name + l - 5, " Bold", 5)) {l -= 5; face = 'B';} return l; } typedef int (*sort_f_type)(const void *aa, const void *bb); static int font_sort(Fl_Fontdesc *fa, Fl_Fontdesc *fb) { char face_a, face_b; int la = font_name_process(fa->name, face_a); int lb = font_name_process(fb->name, face_b); int c = strncasecmp(fa->name, fb->name, la >= lb ? lb : la); return (c == 0 ? face_a - face_b : c); } Fl_Font Fl_Xlib_Graphics_Driver::set_fonts(const char* pattern_name) { fl_open_display(); int n_families, count = 0; PangoFontFamily **families; char *saved_lang = fl_getenv("LANG"); const char *Clang = "LANG=C"; if (saved_lang && strcmp(saved_lang, Clang)) { // Force LANG=C to prevent pango_font_face_get_face_name() below from returning // translated versions of Bold, Italic, etc… (see issue #732). // Unfortunately, using setlocale() doesn't do the job. char *p = saved_lang; saved_lang = (char*)malloc(strlen(p) + 6); memcpy(saved_lang, "LANG=", 5); strcpy(saved_lang + 5, p); fl_putenv(Clang); } else saved_lang = NULL; Fl_Xlib_Graphics_Driver::context(); Fl_Xlib_Graphics_Driver::init_built_in_fonts(); pango_font_map_list_families(Fl_Xlib_Graphics_Driver::pfmap_, &families, &n_families); for (int fam = 0; fam < n_families; fam++) { PangoFontFace **faces; int n_faces; const char *fam_name = pango_font_family_get_name (families[fam]); int lfam = strlen(fam_name); pango_font_family_list_faces(families[fam], &faces, &n_faces); for (int j = 0; j < n_faces; j++) { const char *p = pango_font_face_get_face_name(faces[j]); // Remove " Regular" suffix from font names if (!strcasecmp(p, "regular")) p = NULL; // build the font's FLTK name int lfont = lfam + (p ? strlen(p) + 2 : 1); char *q = new char[lfont]; if (p) snprintf(q, lfont, "%s %s", fam_name, p); else strcpy(q, fam_name); Fl::set_font((Fl_Font)(count++ + FL_FREE_FONT), q); } /*g_*/free(faces); // glib source code shows that g_free is equivalent to free } /*g_*/free(families); if (saved_lang) { fl_putenv(saved_lang); free(saved_lang); } // Sort the list into alphabetic order qsort(fl_fonts + FL_FREE_FONT, count, sizeof(Fl_Fontdesc), (sort_f_type)font_sort); return FL_FREE_FONT + count; } void Fl_Xlib_Graphics_Driver::init_built_in_fonts() { static int i = 0; if (!i) { while (i < FL_FREE_FONT) { i++; Fl::set_font((Fl_Font)i-1, fl_fonts[i-1].name); } } } int Fl_Xlib_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) { static int array[1] = {0}; sizep = array; return 1; } Fl_Xlib_Font_Descriptor::Fl_Xlib_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) : Fl_Font_Descriptor(name, fsize) { fl_open_display(); angle = fangle; height_ = 0; descent_ = 0; width = NULL; } #endif // USE_PANGO #endif // FL_DOXYGEN fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx0000644000175000017500000003351615004135251024173 0ustar albrechtalbrecht// // Rectangle drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Xlib_Graphics_Driver_rect.cxx \brief X11 Xlib specific line and polygon drawing with integer coordinates. */ #include #include #include #include #include #include "Fl_Xlib_Graphics_Driver.H" // Arbitrary line clipping: clip line end points to 16-bit coordinate range. // We clip at +/- 16-bit boundaries (+/- (2**15-K)) where K currently is 8 // to account for line width. We could also clip at lower bound 0 but that // would make lines less accurate (rounding effects < 1 pixel, but anyway). // Note that we're only clipping the line end points so we can send true // 16-bit coordinates to X functions. Actual clipping to window borders // and clip regions will be done by X. // Note: the current (default) approach is to clip to the current window // boundaries instead. This can avoid drawing unecessary (invisible) objects. /* Liang-Barsky line clipping algorithm. For documentation see: https://en.wikipedia.org/wiki/Liang-Barsky_algorithm . Modified by AlbrechtS for FLTK. */ /* Returns new coordinates in function arguments x1, y1, x2, y2 if the line is within or intersects the valid coordinate space so it is potentially visible. Arguments are not changed if the entire line is outside the valid coordinate space. If the return value is non-zero (true) the line is entirely *clipped* and must not be drawn with X functions because the coordinates could be outside the valid coordinate space and the result would be undefined. Returns 1 (true) if line is clipped, i.e. *not* visible. Returns 0 (false) if line is not clipped, i.e. potentially visible. */ int Fl_Xlib_Graphics_Driver::clip_line(int &x1, int &y1, int &x2, int &y2) { // define variables float p1 = float(-(x2 - x1)); float p2 = float(-p1); float p3 = float(-(y2 - y1)); float p4 = float(-p3); float q1 = float(x1 - clip_min()); float q2 = float(clip_max() - x1); float q3 = float(y1 - clip_min()); float q4 = float(clip_max() - y1); float posmin = 1; // positive minimum float negmax = 0; // negative maximum if ((p1 == 0 && q1 < 0) || (p3 == 0 && q3 < 0)) { return 1; // Line is parallel to clipping window (not visible) } if (p1 != 0) { float r1 = q1 / p1; float r2 = q2 / p2; if (p1 < 0) { if (r1 > negmax) negmax = r1; if (r2 < posmin) posmin = r2; } else { if (r2 > negmax) negmax = r2; if (r1 < posmin) posmin = r1; } } if (p3 != 0) { float r3 = q3 / p3; float r4 = q4 / p4; if (p3 < 0) { if (r3 > negmax) negmax = r3; if (r4 < posmin) posmin = r4; } else { if (r4 > negmax) negmax = r4; if (r3 < posmin) posmin = r3; } } if (negmax > posmin) // line outside clipping window return 1; // clipped // compute new points (note: order is important!) x2 = int(x1 + p2 * posmin); y2 = int(y1 + p4 * posmin); x1 = int(x1 + p2 * negmax); y1 = int(y1 + p4 * negmax); return 0; // not clipped } // clip_line() // "Old" line clipping: only horizontal and vertical lines and rectangles // line_width_ must contain the absolute value of the current // line width to be used for X11 clipping (see below). /* We need to check some coordinates for areas for clipping before we use X functions, because X can't handle coordinates outside the 16-bit range. Since all windows use relative coordinates > 0, we do also check for negative values. X11 only, see also STR #2304. Note that this is only necessary for large objects, where only a part of the object is visible. The draw() functions (e.g. box drawing) must be clipped correctly. This is usually only a matter for large container widgets. The individual child widgets will be clipped completely. We define the usable X coordinate space as [ -LW : SHRT_MAX - LW ] where LW = current line width for drawing. This is done so that horizontal and vertical line drawing works correctly, even in real border cases, e.g. drawing a rectangle slightly outside the top left window corner, but with a line width so that a part of the line should be visible (in this case 2 of 5 pixels): fl_line_style (FL_SOLID,5); // line width = 5 fl_rect (-1,-1,100,100); // top/left: 2 pixels visible In this example case, no clipping would be done, because X can handle it and clip unneeded pixels. Note that we must also take care of the case where line_width_ is zero (maybe unitialized). If this is the case, we assume a line width of 1. Todo: Arbitrary line drawings (e.g. polygons), circles and curves. */ /* clip_rect() returns 1 if the area is invisible (clipped) because ... (a) w <= 0 or h <= 0 i.e. nothing is visible (b) x+w < clip_min() or y+h < clip_min() i.e. left of or above visible area (c) x > clip_max() or y > clip_max() i.e. right of or below visible area clip_min() and clip_max() are the minimal and maximal x/y coordinate values used for clipping. In the above cases x, y, w, and h are not changed and the return value is 1 (clipped). clip_rect() returns 0 if the area is potentially visible and X can handle clipping. x, y, w, and h may have been adjusted to fit into the valid coordinate space. Use this for clipping rectangles as in fl_rect() and fl_rectf(). It is fast and convenient. */ int Fl_Xlib_Graphics_Driver::clip_rect(int &x, int &y, int &w, int &h) { if (w <= 0 || h <= 0) return 1; // (a) if (x+w < clip_min() || y+h < clip_min()) return 1; // (b) if (x > clip_max() || y > clip_max()) return 1; // (c) if (x < clip_min()) { w -= (clip_min()-x); x = clip_min(); } if (y < clip_min()) { h -= (clip_min()-y); y = clip_min(); } if (x+w > clip_max()) w = clip_max() - x; if (y+h > clip_max()) h = clip_max() - y; return 0; } // Missing X call: (is this the fastest way to init a 1-rectangle region?) // Windows equivalent exists, implemented inline in win32.H // Note: if the entire region is outside the 16-bit X coordinate space an empty // clipping region is returned which means that *nothing* will be visible. Fl_Region Fl_Xlib_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) { XRectangle R; Region r = XCreateRegion(); // create an empty region if (clip_rect(x, y, w, h)) // outside valid coordinate space return r; // empty region R.x = x; R.y = y; R.width = w; R.height = h; XUnionRectWithRegion(&R, r, r); return r; } void Fl_Xlib_Graphics_Driver::XDestroyRegion(Fl_Region r) { ::XDestroyRegion((Region)r); } // --- line and polygon drawing void Fl_Xlib_Graphics_Driver::focus_rect(int x, int y, int w, int h) { w = this->floor(x + w) - this->floor(x); h = this->floor(y + h) - this->floor(y); x = this->floor(x) + floor(offset_x_); y = this->floor(y) + floor(offset_y_); if (!clip_rect(x, y, w, h)) { int lw_save = line_width_; // preserve current line_width if (line_width_ == 0) line_style(FL_DOT, 1); else line_style(FL_DOT); XDrawRectangle(fl_display, fl_window, gc_, x, y, w, h); if (lw_save == 0) line_style(FL_SOLID, 0); // restore line type and width else line_style(FL_SOLID); } } void Fl_Xlib_Graphics_Driver::rect_unscaled(int x, int y, int w, int h) { void *old = NULL; if (line_width_ == 0) old = change_pen_width(1); // #156, #1052 XDrawRectangle(fl_display, fl_window, gc_, x, y, w, h); if (old) reset_pen_width(old); } void Fl_Xlib_Graphics_Driver::rectf_unscaled(int x, int y, int w, int h) { x += floor(offset_x_); y += floor(offset_y_); if (!clip_rect(x, y, w, h)) XFillRectangle(fl_display, fl_window, gc_, x, y, w, h); } void Fl_Xlib_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1) { draw_clipped_line(x + this->floor(offset_x_) , y + this->floor(offset_y_) , x1 + this->floor(offset_x_) , y1 + this->floor(offset_y_) ); } void Fl_Xlib_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1, int x2, int y2) { if (!clip_line(x1, y1, x, y) && !clip_line(x1, y1, x2, y2)) { XPoint p[3]; int x_offset = floor(offset_x_); int y_offset = floor(offset_y_); p[0].x = x + x_offset; p[0].y = y + y_offset; p[1].x = x1 + x_offset; p[1].y = y1 + y_offset; p[2].x = x2 + x_offset; p[2].y = y2 + y_offset; XDrawLines(fl_display, fl_window, gc_, p, 3, 0); } } void Fl_Xlib_Graphics_Driver::xyline_unscaled(int x, int y, int x1) { if (line_width_ >= 2) x1++; x += floor(offset_x_) ; y += floor(offset_y_) ; x1 += floor(offset_x_) ; draw_clipped_line(x, y, x1, y); } void Fl_Xlib_Graphics_Driver::yxline_unscaled(int x, int y, int y1) { if (line_width_ >= 2) y1++; x += floor(offset_x_) ; y += floor(offset_y_) ; y1 += floor(offset_y_) ; draw_clipped_line(x, y, x, y1); } void Fl_Xlib_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2) { XPoint p[4]; p[0].x = x + floor(offset_x_) ; p[0].y = y + floor(offset_y_) ; p[1].x = x1 + floor(offset_x_) ; p[1].y = y1 + floor(offset_y_) ; p[2].x = x2 + floor(offset_x_) ; p[2].y = y2 + floor(offset_y_) ; p[3].x = p[0].x; p[3].y = p[0].y; // *FIXME* This needs X coordinate clipping! XDrawLines(fl_display, fl_window, gc_, p, 4, 0); } void Fl_Xlib_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { XPoint p[5]; p[0].x = x + floor(offset_x_) ; p[0].y = y + floor(offset_y_) ; p[1].x = x1 + floor(offset_x_) ; p[1].y = y1 + floor(offset_y_) ; p[2].x = x2 + floor(offset_x_) ; p[2].y = y2 + floor(offset_y_) ; p[3].x = x3 + floor(offset_x_) ; p[3].y = y3 + floor(offset_y_) ; p[4].x = p[0].x; p[4].y = p[0].y; // *FIXME* This needs X coordinate clipping! XDrawLines(fl_display, fl_window, gc_, p, 5, 0); } void Fl_Xlib_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2) { XPoint p[4]; p[0].x = x + floor(offset_x_) ; p[0].y = y + floor(offset_y_) ; p[1].x = x1 + floor(offset_x_) ; p[1].y = y1 + floor(offset_y_) ; p[2].x = x2 + floor(offset_x_) ; p[2].y = y2 + floor(offset_y_) ; p[3].x = p[0].x; p[3].y = p[0].y; // *FIXME* This needs X coordinate clipping! XFillPolygon(fl_display, fl_window, gc_, p, 3, Convex, 0); XDrawLines(fl_display, fl_window, gc_, p, 4, 0); } void Fl_Xlib_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { XPoint p[5]; p[0].x = x + floor(offset_x_) ; p[0].y = y + floor(offset_y_) ; p[1].x = x1 + floor(offset_x_) ; p[1].y = y1 + floor(offset_y_) ; p[2].x = x2 + floor(offset_x_) ; p[2].y = y2 + floor(offset_y_) ; p[3].x = x3 + floor(offset_x_) ; p[3].y = y3 + floor(offset_y_) ; p[4].x = p[0].x; p[4].y = p[0].y; // *FIXME* This needs X coordinate clipping! XFillPolygon(fl_display, fl_window, gc_, p, 4, Convex, 0); XDrawLines(fl_display, fl_window, gc_, p, 5, 0); } // --- clipped line drawing in X coordinate space (16-bit) // Draw an arbitrary line with coordinates clipped to the X coordinate space. // This draws nothing if the line is entirely outside the X coordinate space. void Fl_Xlib_Graphics_Driver::draw_clipped_line(int x1, int y1, int x2, int y2) { if (!clip_line(x1, y1, x2, y2)) XDrawLine(fl_display, fl_window, gc_, x1, y1, x2, y2); } // --- clipping void Fl_Xlib_Graphics_Driver::push_clip(int x, int y, int w, int h) { Region r; if (w > 0 && h > 0) { r = (Region)XRectangleRegion(x, y, w, h); // does X coordinate clipping Region current = (Region)rstack[rstackptr]; if (current) { Region temp = XCreateRegion(); XIntersectRegion(current, r, temp); XDestroyRegion(r); r = temp; } } else { // make empty clip region: r = XCreateRegion(); } if (rstackptr < region_stack_max) rstack[++rstackptr] = r; else Fl::warning("Fl_Xlib_Graphics_Driver::push_clip: clip stack overflow!\n"); restore_clip(); } int Fl_Xlib_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H) { X = x; Y = y; W = w; H = h; // pre-clip rectangle to 16-bit coordinates (STR #3134) if (clip_rect(X, Y, W, H)) { // entirely clipped (outside) W = H = 0; return 2; } Region r = (Region)rstack[rstackptr]; if (!r) { // no clipping region if (X != x || Y != y || W != w || H != h) // pre-clipped return 1; // partially outside, region differs return 0; } switch (XRectInRegion(r, X, Y, W, H)) { case 0: // completely outside W = H = 0; return 2; case 1: // completely inside: return 0; default: // partial: break; } Region rr = (Region)XRectangleRegion(X, Y, W, H); Region temp = XCreateRegion(); XIntersectRegion(r, rr, temp); XRectangle rect; XClipBox(temp, &rect); X = rect.x; Y = rect.y; W = rect.width; H = rect.height; XDestroyRegion(temp); XDestroyRegion(rr); return 1; } int Fl_Xlib_Graphics_Driver::not_clipped(int x, int y, int w, int h) { if (x+w <= 0 || y+h <= 0) return 0; Region r = (Region)rstack[rstackptr]; if (!r) return 1; // get rid of coordinates outside the 16-bit range the X calls take. if (clip_rect(x,y,w,h)) return 0; // clipped return XRectInRegion(r, x, y, w, h); } void Fl_Xlib_Graphics_Driver::restore_clip() { fl_clip_state_number++; if (gc_) { Region r = (Region)rstack[rstackptr]; if (r) { Region r2 = (Region)scale_clip(scale()); XSetRegion(fl_display, gc_, (Region)rstack[rstackptr]); unscale_clip(r2); } else XSetClipMask(fl_display, gc_, 0); } } fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H0000644000175000017500000000224615004135251023361 0ustar albrechtalbrecht// // Copy-to-clipboard code for the Fast Light Tool Kit (FLTK). // // Copyright 2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_XLIB_COPY_SURFACE_DRIVER_H #define FL_XLIB_COPY_SURFACE_DRIVER_H #include #include #if FLTK_USE_CAIRO # include #endif // FLTK_USE_CAIRO class Fl_Image_Surface; class Fl_Xlib_Copy_Surface_Driver : public Fl_Copy_Surface_Driver { friend class Fl_Copy_Surface_Driver; void end_current() FL_OVERRIDE; protected: Fl_Image_Surface *xid; Window oldwindow; Fl_Xlib_Copy_Surface_Driver(int w, int h); ~Fl_Xlib_Copy_Surface_Driver(); void set_current() FL_OVERRIDE; void translate(int x, int y) FL_OVERRIDE; void untranslate() FL_OVERRIDE; #if FLTK_USE_CAIRO cairo_t *cairo_; #endif }; #endif // FL_XLIB_COPY_SURFACE_DRIVER_H fltk-1.4.3/src/drivers/Xlib/Fl_Font.H0000644000175000017500000000343015004135251017410 0ustar albrechtalbrecht// // Font definitions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Two internal fltk data structures: // // Fl_Fontdesc: an entry into the fl_font() table. There is one of these // for each fltk font number. // #ifndef FL_FONT_ #define FL_FONT_ #include #if USE_XFT typedef struct _XftFont XftFont; #else # include "../../Xutf8.h" #endif // USE_XFT class Fl_Xlib_Font_Descriptor : public Fl_Font_Descriptor { public: # if USE_XFT # if USE_PANGO int descent_; int height_; int **width; # else XftFont* font; # endif int angle; FL_EXPORT Fl_Xlib_Font_Descriptor(const char* xfontname, Fl_Fontsize size, int angle); # else XUtf8FontStruct* font; // X UTF-8 font information FL_EXPORT Fl_Xlib_Font_Descriptor(const char* xfontname); # if HAVE_GL char glok[64]; # endif // HAVE_GL # endif // USE_XFT virtual FL_EXPORT ~Fl_Xlib_Font_Descriptor(); }; //extern FL_EXPORT Fl_Font_Descriptor *fl_fontsize; // the currently selected one #if !USE_XFT struct Fl_Xlib_Fontdesc { // replaces Fl_Fontdesc const char *name; char fontname[128]; // "Pretty" font name Fl_Font_Descriptor *first; // linked list of sizes of this style char **xlist; // matched X font names int n; // size of xlist, negative = don't free xlist! }; #endif extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table #endif fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx0000644000175000017500000000513115004135251025375 0ustar albrechtalbrecht// // Line style code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Xlib_Graphics_Driver_line_style.cxx \brief Line style drawing utility hiding different platforms. */ #include #include #include #include "../../flstring.h" #include "Fl_Xlib_Graphics_Driver.H" #include void Fl_Xlib_Graphics_Driver::line_style_unscaled(int style, int width, char* dashes) { int ndashes = dashes ? strlen(dashes) : 0; // emulate the Windows dash patterns on X char buf[7] = {0}; if (!ndashes && (style&0xff)) { int w = width ? width : 1; char dash, dot, gap; // adjust lengths to account for cap: if (style & 0x200) { dash = char(2*w); dot = 1; // unfortunately 0 does not work gap = char(2*w-1); } else { dash = char(3*w); dot = gap = char(w); } char* p = dashes = buf; switch (style & 0xff) { case FL_DASH: *p++ = dash; *p++ = gap; break; case FL_DOT: *p++ = dot; *p++ = gap; break; case FL_DASHDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; break; case FL_DASHDOTDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; *p++ = dot; *p++ = gap; break; } ndashes = p-buf; if (*dashes == 0) ndashes = 0; // against error with very small scaling } static int Cap[4] = {CapButt, CapButt, CapRound, CapProjecting}; static int Join[4] = {JoinMiter, JoinMiter, JoinRound, JoinBevel}; XSetLineAttributes(fl_display, gc_, line_width_, ndashes ? LineOnOffDash : LineSolid, Cap[(style>>8)&3], Join[(style>>12)&3]); if (ndashes) XSetDashes(fl_display, gc_, 0, dashes, ndashes); } void *Fl_Xlib_Graphics_Driver::change_pen_width(int lwidth) { XGCValues *gc_values = (XGCValues*)malloc(sizeof(XGCValues)); gc_values->line_width = lwidth; XChangeGC(fl_display, gc_, GCLineWidth, gc_values); gc_values->line_width = line_width_; line_width_ = lwidth; return gc_values; } void Fl_Xlib_Graphics_Driver::reset_pen_width(void *data) { XGCValues *gc_values = (XGCValues*)data; line_width_ = gc_values->line_width; XChangeGC(fl_display, gc_, GCLineWidth, gc_values); free(data); } fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H0000644000175000017500000000260715004135251023472 0ustar albrechtalbrecht// // Draw-to-image code for the Fast Light Tool Kit (FLTK). // // Copyright 2022-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_XLIB_IMAGE_SURFACE_DRIVER_H #define FL_XLIB_IMAGE_SURFACE_DRIVER_H #include #if FLTK_USE_CAIRO # include #endif // FLTK_USE_CAIRO class Fl_Xlib_Image_Surface_Driver : public Fl_Image_Surface_Driver { void end_current() FL_OVERRIDE; public: Window pre_window; Fl_Xlib_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off); ~Fl_Xlib_Image_Surface_Driver(); void set_current() FL_OVERRIDE; void translate(int x, int y) FL_OVERRIDE; void untranslate() FL_OVERRIDE; Fl_RGB_Image *image() FL_OVERRIDE; void mask(const Fl_RGB_Image *) FL_OVERRIDE; #if FLTK_USE_CAIRO cairo_t *cairo_; struct shape_data_type { double scale; cairo_pattern_t *mask_pattern_; cairo_t *bg_cr; } *shape_data_; #else struct shape_data_type { Pixmap background; Fl_RGB_Image* mask; } *shape_data_; #endif }; #endif // FL_XLIB_IMAGE_SURFACE_DRIVER_H fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx0000644000175000017500000000256215004135251024151 0ustar albrechtalbrecht// // Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Xlib_Graphics_Driver.H" #include #include /** \file Fl_Xlib_Graphics_Driver_arci.cxx \brief Utility functions for drawing circles using integers */ void Fl_Xlib_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) { if (w <= 0 || h <= 0) return; x += floor(offset_x_); y += floor(offset_y_); XDrawArc(fl_display, fl_window, gc_, x, y, w, h, int(a1*64),int((a2-a1)*64)); } void Fl_Xlib_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1,double a2) { if (w <= 2 || h <= 2) return; x += floor(offset_x_); y += floor(offset_y_); int extra = scale() >= 3 ? 1 : 0; XDrawArc(fl_display, fl_window, gc_, x+1+extra, y+1+extra, w-2-2*extra, h-2-2*extra, int(a1*64), int((a2-a1)*64)); XFillArc(fl_display, fl_window, gc_, x+1, y+1, w-2, h-2, int(a1*64), int((a2-a1)*64)); } fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx0000644000175000017500000000553215004135251023775 0ustar albrechtalbrecht// // Copy-to-clipboard code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Xlib_Copy_Surface_Driver.H" #include #include #include #include #include "../X11/Fl_X11_Screen_Driver.H" #if FLTK_USE_CAIRO # include # include "../Cairo/Fl_X11_Cairo_Graphics_Driver.H" # include #else # include "Fl_Xlib_Graphics_Driver.H" #endif // FLTK_USE_CAIRO Fl_Xlib_Copy_Surface_Driver::Fl_Xlib_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) { #if FLTK_USE_CAIRO driver(new Fl_X11_Cairo_Graphics_Driver()); #else driver(new Fl_Xlib_Graphics_Driver()); #endif float s = Fl_Graphics_Driver::default_driver().scale(); driver()->scale(s); oldwindow = fl_window; xid = new Fl_Image_Surface(w, h, 1); #if FLTK_USE_CAIRO cairo_surface_t *surf = cairo_xlib_surface_create(fl_display, xid->offscreen(), fl_visual->visual, w * s, h * s); cairo_ = cairo_create(surf); cairo_surface_destroy(surf); cairo_save(cairo_); ((Fl_X11_Cairo_Graphics_Driver*)driver())->set_cairo(cairo_); #endif fl_window = xid->offscreen(); driver()->color(FL_WHITE); driver()->rectf(0, 0, w, h); fl_window = oldwindow; } Fl_Xlib_Copy_Surface_Driver::~Fl_Xlib_Copy_Surface_Driver() { Window old_win = fl_window; fl_window = xid->offscreen(); Fl_RGB_Image *rgb = Fl::screen_driver()->read_win_rectangle(0, 0, width, height, 0); fl_window = old_win; if (is_current()) end_current(); if (rgb) { Fl_X11_Screen_Driver::copy_image(rgb->array, rgb->w(), rgb->h(), 1); delete rgb; } delete xid; #if FLTK_USE_CAIRO cairo_destroy(cairo_); #endif delete driver(); } void Fl_Xlib_Copy_Surface_Driver::set_current() { Fl_Surface_Device::set_current(); oldwindow = fl_window; fl_window = xid->offscreen(); #if FLTK_USE_CAIRO Fl_Cairo_Graphics_Driver *dr = (Fl_Cairo_Graphics_Driver*)driver(); if (!dr->cr()) dr->set_cairo(cairo_); #endif } void Fl_Xlib_Copy_Surface_Driver::end_current() { fl_window = oldwindow; Fl_Surface_Device::end_current(); } void Fl_Xlib_Copy_Surface_Driver::translate(int x, int y) { #if FLTK_USE_CAIRO cairo_save(cairo_); cairo_translate(cairo_, x, y); #else ((Fl_Xlib_Graphics_Driver*)driver())->translate_all(x, y); #endif } void Fl_Xlib_Copy_Surface_Driver::untranslate() { #if FLTK_USE_CAIRO cairo_restore(cairo_); #else ((Fl_Xlib_Graphics_Driver*)driver())->untranslate_all(); #endif } fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx0000644000175000017500000001243015004135251023146 0ustar albrechtalbrecht// // Rectangle drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Xlib_Graphics_Driver.H" #include "Fl_Font.H" #include #include #include #include #if !USE_XFT extern char *fl_get_font_xfld(int fnum, int size); #endif GC Fl_Xlib_Graphics_Driver::gc_ = NULL; int Fl_Xlib_Graphics_Driver::fl_overlay = 0; /* Reference to the current graphics context For back-compatibility only. The preferred procedure to get this pointer is Fl_Surface_Device::surface()->driver()->gc(). */ GC fl_gc = 0; GC fl_x11_gc() { return fl_gc; } Fl_Xlib_Graphics_Driver::Fl_Xlib_Graphics_Driver(void) { mask_bitmap_ = NULL; short_point = NULL; #if USE_PANGO Fl_Graphics_Driver::font(0, 0); #endif offset_x_ = 0; offset_y_ = 0; depth_ = 0; clip_max_ = 32760; // clipping limit (2**15 - 8) } Fl_Xlib_Graphics_Driver::~Fl_Xlib_Graphics_Driver() { if (short_point) free(short_point); } void Fl_Xlib_Graphics_Driver::gc(void *value) { gc_ = (GC)value; fl_gc = gc_; } void Fl_Xlib_Graphics_Driver::scale(float f) { #if USE_XFT if (f != scale()) { size_ = 0; Fl_Graphics_Driver::scale(f); //fprintf(stderr, "scale=%.2f\n", scale_); line_style(FL_SOLID); // scale also default line width } #endif } void Fl_Xlib_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) { XCopyArea(fl_display, (Pixmap)pixmap, fl_window, gc_, srcx*scale(), srcy*scale(), w*scale(), h*scale(), (x+offset_x_)*scale(), (y+offset_y_)*scale()); } void Fl_Xlib_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) { XRectangle R; R.x = X; R.y = Y; R.width = W; R.height = H; XUnionRectWithRegion(&R, (Region)r, (Region)r); } void Fl_Xlib_Graphics_Driver::transformed_vertex0(float fx, float fy) { short x = short(fx), y = short(fy); if (!n || x != short_point[n-1].x || y != short_point[n-1].y) { if (n >= p_size) { p_size = short_point ? 2*p_size : 16; short_point = (XPoint*)realloc((void*)short_point, p_size*sizeof(*short_point)); } short_point[n].x = x ; short_point[n].y = y ; n++; } } void Fl_Xlib_Graphics_Driver::fixloop() { // remove equal points from closed path while (n>2 && short_point[n-1].x == short_point[0].x && short_point[n-1].y == short_point[0].y) n--; } #if !USE_XFT unsigned Fl_Xlib_Graphics_Driver::font_desc_size() { return (unsigned)sizeof(Fl_Xlib_Fontdesc); } #endif const char *Fl_Xlib_Graphics_Driver::font_name(int num) { #if USE_XFT return fl_fonts[num].name; #else return ((Fl_Xlib_Fontdesc*)fl_fonts)[num].name; #endif } void Fl_Xlib_Graphics_Driver::font_name(int num, const char *name) { #if USE_XFT # if USE_PANGO init_built_in_fonts(); if (pfd_array_length > num && pfd_array[num]) { pango_font_description_free(pfd_array[num]); pfd_array[num] = NULL; } # endif Fl_Fontdesc *s = fl_fonts + num; #else Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts) + num; #endif if (s->name) { if (!strcmp(s->name, name)) {s->name = name; return;} #if !USE_XFT if (s->xlist && s->n >= 0) XFreeFontNames(s->xlist); #endif for (Fl_Font_Descriptor* f = s->first; f;) { Fl_Font_Descriptor* n = f->next; delete f; f = n; } s->first = 0; } s->name = name; s->fontname[0] = 0; #if !USE_XFT s->xlist = 0; #endif s->first = 0; } Fl_Region Fl_Xlib_Graphics_Driver::scale_clip(float f) { Region r = (Region)rstack[rstackptr]; if (r == 0 || (f == 1 && offset_x_ == 0 && offset_y_ == 0) ) return 0; Region r2 = XCreateRegion(); for (int i = 0; i < r->numRects; i++) { int x = floor(r->rects[i].x1 + offset_x_, f); int y = floor(r->rects[i].y1 + offset_y_, f); int w = floor((r->rects[i].x2 + offset_x_) , f) - x; int h = floor((r->rects[i].y2 + offset_y_) , f) - y; Region R = (Region)XRectangleRegion(x, y, w, h); XUnionRegion(R, r2, r2); ::XDestroyRegion(R); } rstack[rstackptr] = r2; return r; } void Fl_Xlib_Graphics_Driver::translate_all(int dx, int dy) { // reversibly adds dx,dy to the offset between user and graphical coordinates if (depth_ < FL_XLIB_GRAPHICS_TRANSLATION_STACK_SIZE) { stack_x_[depth_] = offset_x_; stack_y_[depth_] = offset_y_; depth_++; } else { Fl::warning("%s: translate stack overflow!", "Fl_Xlib_Graphics_Driver"); } offset_x_ += dx; offset_y_ += dy; push_matrix(); translate(dx, dy); } void Fl_Xlib_Graphics_Driver::untranslate_all() { // undoes previous translate_all() if (depth_ > 0) depth_--; offset_x_ = stack_x_[depth_]; offset_y_ = stack_y_[depth_]; pop_matrix(); } void Fl_Xlib_Graphics_Driver::set_current_() { restore_clip(); } #if USE_PANGO int Fl_Xlib_Graphics_Driver::pfd_array_length = FL_FREE_FONT; PangoFontDescription **Fl_Xlib_Graphics_Driver::pfd_array = (PangoFontDescription**)calloc(pfd_array_length, sizeof(PangoFontDescription*)); #endif fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx0000644000175000017500000000461415004135251024550 0ustar albrechtalbrecht// // Portable drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Xlib_Graphics_Driver_vertex.cxx \brief Portable drawing code for drawing arbitrary shapes with simple 2D transformations, implemented for X11 Xlib. */ #include #include "Fl_Xlib_Graphics_Driver.H" #include #include #include void Fl_Xlib_Graphics_Driver::end_points() { if (n>1) XDrawPoints(fl_display, fl_window, gc_, short_point, n, 0); } void Fl_Xlib_Graphics_Driver::end_line() { if (n < 2) { end_points(); return; } if (n>1) XDrawLines(fl_display, fl_window, gc_, short_point, n, 0); } void Fl_Xlib_Graphics_Driver::end_loop() { fixloop(); if (n>2) { transformed_vertex0(short_point[0].x , short_point[0].y ); } end_line(); } void Fl_Xlib_Graphics_Driver::end_polygon() { fixloop(); if (n < 3) { end_line(); return; } if (n>2) XFillPolygon(fl_display, fl_window, gc_, short_point, n, Convex, 0); } void Fl_Xlib_Graphics_Driver::gap() { while (n>gap_+2 && short_point[n-1].x == short_point[gap_].x && short_point[n-1].y == short_point[gap_].y) n--; if (n > gap_+2) { transformed_vertex0(short_point[gap_].x, short_point[gap_].y); gap_ = n; } else { n = gap_; } } void Fl_Xlib_Graphics_Driver::end_complex_polygon() { gap(); if (n < 3) { end_line(); return; } if (n>2) XFillPolygon(fl_display, fl_window, gc_, short_point, n, 0, 0); } bool Fl_Xlib_Graphics_Driver::can_fill_non_convex_polygon() { return false; } // shortcut the closed circles so they use XDrawArc: // warning: these do not draw rotated ellipses correctly! // See fl_arc.c for portable version. void Fl_Xlib_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) { int llx = (int)rint(xt-rx); int w = (int)rint(xt+rx)-llx; int lly = (int)rint(yt-ry); int h = (int)rint(yt+ry)-lly; (what == POLYGON ? XFillArc : XDrawArc) (fl_display, fl_window, gc_, llx, lly, w, h, 0, 360*64); } fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx0000644000175000017500000001717515004135251024113 0ustar albrechtalbrecht// // Draw-to-image code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_Xlib_Image_Surface_Driver.H" #include "../../Fl_Screen_Driver.H" #include #if FLTK_USE_CAIRO # include # include "../Cairo/Fl_X11_Cairo_Graphics_Driver.H" #else # include "Fl_Xlib_Graphics_Driver.H" #endif // FLTK_USE_CAIRO Fl_Xlib_Image_Surface_Driver::Fl_Xlib_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) { float d = 1; if (!off) { fl_open_display(); d = Fl_Graphics_Driver::default_driver().scale(); if (d != 1 && high_res) { w = int(w*d); h = int(h*d); } offscreen = (Fl_Offscreen)XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), w, h, fl_visual->depth); } shape_data_ = NULL; #if FLTK_USE_CAIRO driver(new Fl_X11_Cairo_Graphics_Driver()); cairo_surface_t *s = cairo_xlib_surface_create(fl_display, offscreen, fl_visual->visual, w, h); cairo_ = cairo_create(s); cairo_surface_destroy(s); cairo_save(cairo_); ((Fl_X11_Cairo_Graphics_Driver*)driver())->set_cairo(cairo_); #else driver(new Fl_Xlib_Graphics_Driver()); #endif if (d != 1 && high_res) driver()->scale(d); } Fl_Xlib_Image_Surface_Driver::~Fl_Xlib_Image_Surface_Driver() { #if FLTK_USE_CAIRO if (shape_data_) { cairo_surface_t *surf; cairo_pattern_get_surface(shape_data_->mask_pattern_, &surf); unsigned char *bits = cairo_image_surface_get_data(surf); cairo_pattern_destroy(shape_data_->mask_pattern_); delete[] bits; Pixmap p = cairo_xlib_surface_get_drawable(cairo_get_target(shape_data_->bg_cr)); XFreePixmap(fl_display, p); cairo_destroy(shape_data_->bg_cr); free(shape_data_); } cairo_destroy(cairo_); #else if (shape_data_) { XFreePixmap(fl_display, shape_data_->background); delete shape_data_->mask; free(shape_data_); } #endif if (offscreen && !external_offscreen) XFreePixmap(fl_display, (Pixmap)offscreen); delete driver(); } void Fl_Xlib_Image_Surface_Driver::set_current() { Fl_Surface_Device::set_current(); pre_window = fl_window; fl_window = offscreen; #if FLTK_USE_CAIRO Fl_Cairo_Graphics_Driver *dr = (Fl_Cairo_Graphics_Driver*)driver(); if (!dr->cr()) dr->set_cairo(cairo_); #endif } void Fl_Xlib_Image_Surface_Driver::translate(int x, int y) { #if FLTK_USE_CAIRO cairo_save(cairo_); cairo_translate(cairo_, x, y); #else ((Fl_Xlib_Graphics_Driver*)driver())->translate_all(x, y); #endif } void Fl_Xlib_Image_Surface_Driver::untranslate() { #if FLTK_USE_CAIRO cairo_restore(cairo_); #else ((Fl_Xlib_Graphics_Driver*)driver())->untranslate_all(); #endif } Fl_RGB_Image* Fl_Xlib_Image_Surface_Driver::image() { if (shape_data_) { #if FLTK_USE_CAIRO // draw above the secondary offscreen the main offscreen masked by mask_pattern_ cairo_t *c = ((Fl_Cairo_Graphics_Driver*)driver())->cr(); cairo_pattern_t *paint_pattern = cairo_pattern_create_for_surface(cairo_get_target(c)); cairo_set_source(shape_data_->bg_cr, paint_pattern); cairo_mask(shape_data_->bg_cr, shape_data_->mask_pattern_); cairo_pattern_destroy(paint_pattern); // copy secondary offscreen to the main offscreen cairo_pattern_t *pat = cairo_pattern_create_for_surface(cairo_get_target(shape_data_->bg_cr)); cairo_scale(c, shape_data_->scale, shape_data_->scale); cairo_set_source(c, pat), cairo_paint(c); cairo_pattern_destroy(pat); // delete secondary offscreen cairo_surface_t *surf; cairo_pattern_get_surface(shape_data_->mask_pattern_, &surf); unsigned char *bits = cairo_image_surface_get_data(surf); cairo_pattern_destroy(shape_data_->mask_pattern_); delete[] bits; Pixmap p = cairo_xlib_surface_get_drawable(cairo_get_target(shape_data_->bg_cr)); XFreePixmap(fl_display, p); cairo_destroy(shape_data_->bg_cr); #else // !FLTK_USE_CAIRO // draw the main offscreen masked by shape_data_->mask above the background offscreen int w, h; printable_rect(&w, &h); Fl_RGB_Image *img_main = Fl::screen_driver()->read_win_rectangle(0, 0, w, h, 0); fl_window = shape_data_->background; // temporary change Fl_RGB_Image *img_background = Fl::screen_driver()->read_win_rectangle(0, 0, w, h, 0); fl_window = offscreen; Fl_Image_Surface_Driver::copy_with_mask(shape_data_->mask, (uchar*)img_background->array, (uchar*)img_main->array, 3 * shape_data_->mask->w(), false); delete img_main; // copy background offscreen to main offscreen float s = driver()->scale(); driver()->scale(1); fl_draw_image(img_background->array, 0, 0, img_background->data_w(), img_background->data_h()); driver()->scale(s); delete img_background; // delete background offscreen XFreePixmap(fl_display, shape_data_->background); delete shape_data_->mask; #endif // FLTK_USE_CAIRO free(shape_data_); shape_data_ = NULL; } Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle(0, 0, width, height, 0); return image; } void Fl_Xlib_Image_Surface_Driver::end_current() { fl_window = pre_window; Fl_Surface_Device::end_current(); } #if FLTK_USE_CAIRO void Fl_Xlib_Image_Surface_Driver::mask(const Fl_RGB_Image *mask) { bool using_copy = false; shape_data_ = (struct shape_data_type*)calloc(1, sizeof(struct shape_data_type)); int W, H; cairo_t *c = ((Fl_Cairo_Graphics_Driver*)driver())->cr(); cairo_surface_t *c_surface = cairo_get_target(c); W = cairo_xlib_surface_get_width(c_surface); H = cairo_xlib_surface_get_height(c_surface); if (W != mask->data_w() || H != mask->data_h()) { Fl_RGB_Image *copy = (Fl_RGB_Image*)mask->copy(W, H); mask = copy; using_copy = true; } shape_data_->mask_pattern_ = Fl_Cairo_Graphics_Driver::calc_cairo_mask(mask); //duplicate current offscreen content to new cairo_t* shape_data_->bg_cr int width, height; printable_rect(&width, &height); Pixmap pxm = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), W, H, fl_visual->depth); cairo_surface_t *background = cairo_xlib_surface_create(fl_display, pxm, fl_visual->visual, W, H); shape_data_->bg_cr = cairo_create(background); cairo_surface_destroy(background); cairo_surface_flush(c_surface); cairo_pattern_t *pat = cairo_pattern_create_for_surface(c_surface); cairo_set_source(shape_data_->bg_cr, pat), cairo_paint(shape_data_->bg_cr); cairo_pattern_destroy(pat); shape_data_->scale = double(width) / W; if (using_copy) delete mask; } #else void Fl_Xlib_Image_Surface_Driver::mask(const Fl_RGB_Image *mask) { shape_data_ = (struct shape_data_type*)calloc(1, sizeof(struct shape_data_type)); // get dimensions int W, H; Fl::screen_driver()->offscreen_size(offscreen, W, H); // compute depth-1 mask shape_data_->mask = Fl_Image_Surface_Driver::RGB3_to_RGB1(mask, W, H); // duplicate current offscreen content to new, background offscreen shape_data_->background = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), W, H, fl_visual->depth); driver()->restore_clip(); XCopyArea(fl_display, (Pixmap)offscreen, shape_data_->background, (GC)driver()->gc(), 0, 0, W, H, 0, 0); } #endif // FLTK_USE_CAIRO fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H0000644000175000017500000002206115004135251022534 0ustar albrechtalbrecht// // Definition of class Fl_Xlib_Graphics_Driver for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Xlib_Graphics_Driver.H \brief Definition of X11 Xlib graphics driver. */ #ifndef FL_XLIB_GRAPHICS_DRIVER_H #define FL_XLIB_GRAPHICS_DRIVER_H #include #include #include #if HAVE_X11_XREGION_H # include #else // if the X11/Xregion.h header is not available, we assume this is the layout of an X11 Region: typedef struct { short x1, x2, y1, y2; } BOX; struct _XRegion { long size; long numRects; BOX *rects; BOX extents; }; #endif // HAVE_X11_XREGION_H #if USE_PANGO #include #endif #define FL_XLIB_GRAPHICS_TRANSLATION_STACK_SIZE (20) /** \brief The Xlib-specific graphics class. This class is implemented only on the Xlib platform. */ class Fl_Xlib_Graphics_Driver : public Fl_Scalable_Graphics_Driver { private: int offset_x_, offset_y_; // translation between user and graphical coordinates: graphical = user + offset unsigned depth_; // depth of translation stack int stack_x_[FL_XLIB_GRAPHICS_TRANSLATION_STACK_SIZE]; // translation stack allowing cumulative translations int stack_y_[FL_XLIB_GRAPHICS_TRANSLATION_STACK_SIZE]; void set_current_() FL_OVERRIDE; int clip_max_; // +/- x/y coordinate limit (16-bit coordinate space) void draw_fixed(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_fixed(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_fixed(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; #if USE_PANGO double do_width_unscaled_(const char *str, int n); #endif protected: void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) FL_OVERRIDE; void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) FL_OVERRIDE; void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) FL_OVERRIDE; void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) FL_OVERRIDE; #if HAVE_XRENDER void draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; int scale_and_render_pixmap(Fl_Offscreen pixmap, int depth, double scale_x, double scale_y, int XP, int YP, int WP, int HP); #endif int height_unscaled() FL_OVERRIDE; int descent_unscaled() FL_OVERRIDE; Fl_Region scale_clip(float f) FL_OVERRIDE; #if USE_XFT void drawUCS4(const void *str, int n, int x, int y); #endif #if USE_PANGO static PangoContext *pctxt_; static PangoFontMap *pfmap_; static PangoLayout *playout_; public: PangoFontDescription *pango_font_description() FL_OVERRIDE { return pfd_array[font()]; } private: static PangoFontDescription **pfd_array; // one array element for each Fl_Font static int pfd_array_length; void do_draw(int from_right, const char *str, int n, int x, int y); static PangoContext *context(); static void init_built_in_fonts(); #endif static GC gc_; uchar *mask_bitmap_; uchar **mask_bitmap() FL_OVERRIDE {return &mask_bitmap_;} XPoint *short_point; #if USE_XFT static Window draw_window; static struct _XftDraw* draw_; #endif void cache(Fl_RGB_Image *img) FL_OVERRIDE; public: Fl_Xlib_Graphics_Driver(void); ~Fl_Xlib_Graphics_Driver() FL_OVERRIDE; void translate_all(int dx, int dy); void untranslate_all(); void scale(float f) FL_OVERRIDE; float scale() {return Fl_Graphics_Driver::scale();} int has_feature(driver_feature mask) FL_OVERRIDE { return mask & NATIVE; } void *gc() FL_OVERRIDE { return gc_; } void gc(void *value) FL_OVERRIDE; char can_do_alpha_blending() FL_OVERRIDE; #if USE_XFT static void destroy_xft_draw(Window id); #endif static int fl_overlay; // --- bitmap stuff static unsigned long create_bitmask(int w, int h, const uchar *array); // NOT virtual void delete_bitmask(fl_uintptr_t bm) FL_OVERRIDE; void draw_unscaled(const char* str, int n, int x, int y) FL_OVERRIDE; void draw_unscaled(int angle, const char *str, int n, int x, int y) FL_OVERRIDE; void rtl_draw_unscaled(const char* str, int n, int x, int y) FL_OVERRIDE; void font_unscaled(Fl_Font face, Fl_Fontsize size) FL_OVERRIDE; void cache(Fl_Pixmap *img) FL_OVERRIDE; void uncache_pixmap(fl_uintptr_t p) FL_OVERRIDE; void cache(Fl_Bitmap *img) FL_OVERRIDE; void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) FL_OVERRIDE; double width_unscaled(const char *str, int n) FL_OVERRIDE; double width_unscaled(unsigned int c) FL_OVERRIDE; void text_extents_unscaled(const char*, int n, int& dx, int& dy, int& w, int& h) FL_OVERRIDE; Fl_Fontsize size_unscaled() FL_OVERRIDE; void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) FL_OVERRIDE; void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h) FL_OVERRIDE; Fl_Region XRectangleRegion(int x, int y, int w, int h) FL_OVERRIDE; void XDestroyRegion(Fl_Region r) FL_OVERRIDE; protected: void transformed_vertex0(float x, float y) FL_OVERRIDE; void fixloop() FL_OVERRIDE; void focus_rect(int x, int y, int w, int h) FL_OVERRIDE; void rect_unscaled(int x, int y, int w, int h) FL_OVERRIDE; void rectf_unscaled(int x, int y, int w, int h) FL_OVERRIDE; void colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) FL_OVERRIDE; void line_unscaled(int x, int y, int x1, int y1) FL_OVERRIDE; void line_unscaled(int x, int y, int x1, int y1, int x2, int y2) FL_OVERRIDE; void xyline_unscaled(int x, int y, int x1) FL_OVERRIDE; void *change_pen_width(int lwidth) FL_OVERRIDE; void reset_pen_width(void *data) FL_OVERRIDE; void yxline_unscaled(int x, int y, int y1) FL_OVERRIDE; void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; // Scaling and clipping stuff for internal usage. // Currently specific to Fl_Xlib_Graphics_Driver (16-bit coordinate clipping) // These methods must not be virtual so they can be inlined. // All these methods work with "real" drawing coordinates (after scaling). // Clipping limits int clip_max() { return clip_max_; } int clip_min() { return -clip_max_; } /* clip_xy() returns a single coordinate value clipped to the 16-bit coordinate space. This can be used to draw horizontal and vertical lines that can be handled by X. Each single coordinate value can be clipped individually and the result can be used directly, e.g. in fl_xyline() and fl_yxline(). */ int clip_xy(int x) { return (x < clip_min() ? clip_min() : (x > clip_max() ? clip_max() : x )); } // clip an arbitrary line int clip_line(int &x1, int &y1, int &x2, int &y2); // clip a rectangle int clip_rect(int &x, int &y, int &w, int &h); // draw a line after clipping (if visible) void draw_clipped_line(int x1, int y1, int x2, int y2); // --- clipping void push_clip(int x, int y, int w, int h) FL_OVERRIDE; int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) FL_OVERRIDE; int not_clipped(int x, int y, int w, int h) FL_OVERRIDE; void restore_clip() FL_OVERRIDE; void end_points() FL_OVERRIDE; void end_line() FL_OVERRIDE; void end_loop() FL_OVERRIDE; void end_polygon() FL_OVERRIDE; void end_complex_polygon() FL_OVERRIDE; bool can_fill_non_convex_polygon() FL_OVERRIDE; void gap() FL_OVERRIDE; void ellipse_unscaled(double xt, double yt, double rx, double ry) FL_OVERRIDE; void arc_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void pie_unscaled(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void line_style_unscaled(int style, int width, char* dashes) FL_OVERRIDE; void color(Fl_Color c) FL_OVERRIDE; void set_color(Fl_Color i, unsigned int c) FL_OVERRIDE; void free_color(Fl_Color i, int overlay) FL_OVERRIDE; Fl_Color color() FL_OVERRIDE { return color_; } void color(uchar r, uchar g, uchar b) FL_OVERRIDE; float scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) FL_OVERRIDE; const char* get_font_name(Fl_Font fnum, int* ap) FL_OVERRIDE; int get_font_sizes(Fl_Font fnum, int*& sizep) FL_OVERRIDE; #if !USE_XFT unsigned font_desc_size() FL_OVERRIDE; float scale_bitmap_for_PostScript() FL_OVERRIDE; #endif const char *font_name(int num) FL_OVERRIDE; void font_name(int num, const char *name) FL_OVERRIDE; Fl_Font set_fonts(const char* xstarname) FL_OVERRIDE; }; #endif // FL_XLIB_GRAPHICS_DRIVER_H fltk-1.4.3/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_color.cxx0000644000175000017500000002370515004135251024353 0ustar albrechtalbrecht// // Color functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Implementation of fl_color(i), fl_color(r,g,b). // FIXME: all the global functions in this file should probably be protected // members of the driver class. Starting with 1.4 we will allow multiple drivers // to co-exist, creating conflicts with multipe mapping. // FIXME: maybe we can forget about color mapping and assume RGB? // Also code to look at the X visual and figure out the best way to turn // a color into a pixel value. // SGI compiler seems to have problems with unsigned char arguments // being used to index arrays. So I always copy them to an integer // before use. #include #include "Fl_Xlib_Graphics_Driver.H" # include "../../Fl_XColor.H" # include # include # include extern unsigned fl_cmap[256]; // defined in fl_color.cxx //////////////////////////////////////////////////////////////// // figure_out_visual() calculates masks & shifts for generating // pixels in true-color visuals: uchar fl_redmask; /**< color mask used in current color map handling */ uchar fl_greenmask; /**< color mask used in current color map handling */ uchar fl_bluemask; /**< color mask used in current color map handling */ int fl_redshift; /**< color shift used in current color map handling */ int fl_greenshift; /**< color shift used in current color map handling */ int fl_blueshift; /**< color shift used in current color map handling */ int fl_extrashift; /**< color shift used in current color map handling */ static uchar beenhere; static void figure_out_visual() { beenhere = 1; if (!fl_visual->red_mask || !fl_visual->green_mask || !fl_visual->blue_mask){ # if USE_COLORMAP fl_redmask = 0; return; # else Fl::fatal("Requires true color visual"); # endif } // get the bit masks into a more useful form: int i,j,m; for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->red_mask & m) break; for (j = i; m; j++, m<<=1) if (!(fl_visual->red_mask & m)) break; fl_redshift = j-8; fl_redmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i)); for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->green_mask & m) break; for (j = i; m; j++, m<<=1) if (!(fl_visual->green_mask & m)) break; fl_greenshift = j-8; fl_greenmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i)); for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->blue_mask & m) break; for (j = i; m; j++, m<<=1) if (!(fl_visual->blue_mask & m)) break; fl_blueshift = j-8; fl_bluemask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i)); i = fl_redshift; if (fl_greenshift < i) i = fl_greenshift; if (fl_blueshift < i) i = fl_blueshift; if (i < 0) { fl_extrashift = -i; fl_redshift -= i; fl_greenshift -= i; fl_blueshift -= i; } else fl_extrashift = 0; } Fl_XColor fl_xmap[1][256]; void Fl_Xlib_Graphics_Driver::color(Fl_Color i) { if (i & 0xffffff00) { unsigned rgb = (unsigned)i; color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8)); } else { Fl_Graphics_Driver::color(i); if(!gc_) return; // don't get a default gc if current window is not yet created/valid XSetForeground(fl_display, gc_, fl_xpixel(i)); } } void Fl_Xlib_Graphics_Driver::color(uchar r,uchar g,uchar b) { Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) ); if(!gc_) return; // don't get a default gc if current window is not yet created/valid XSetForeground(fl_display, gc_, fl_xpixel(r,g,b)); } /** \addtogroup fl_attributes @{ */ //////////////////////////////////////////////////////////////// // Get an rgb color. This is easy for a truecolor visual. For // colormapped it picks the closest color out of the cube in the // fltk colormap. However if this color cube entry has been // requested before, you will get the earlier requested color, and // even this may be approximated if the X colormap was full. /** Returns the X pixel number used to draw the given rgb color. This is the X pixel that fl_color() would use. \param[in] r,g,b color components \return X pixel number */ ulong fl_xpixel(uchar r,uchar g,uchar b) { if (!beenhere) figure_out_visual(); # if USE_COLORMAP if (!fl_redmask) { // find closest entry in the colormap: Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); Fl_XColor &xmap = fl_xmap[Fl_Xlib_Graphics_Driver::fl_overlay][i]; if (xmap.mapped) return xmap.pixel; // if not black or white, change the entry to be an exact match: if (i != FL_COLOR_CUBE && i != 0xFF) fl_cmap[i] = (r<<24)|(g<<16)|(b<<8); return fl_xpixel(i); // allocate an X color } # endif return (((r&fl_redmask) << fl_redshift)+ ((g&fl_greenmask)<> fl_extrashift; } //////////////////////////////////////////////////////////////// // Get a color out of the fltk colormap. Again for truecolor // visuals this is easy. For colormap this actually tries to allocate // an X color, and does a least-squares match to find the closest // color if X cannot allocate that color. // calculate what color is actually on the screen for a mask: static inline uchar realcolor(uchar color, uchar mask) { # if 0 // accurate version if the display has linear gamma, but fl_draw_image // works better with the simpler version on most screens... uchar m = mask; uchar result = color&m; for (;;) { while (m&mask) {m>>=1; color>>=1;} if (!m) break; mask = m; result |= color&m; } return result; # else return (color&mask) | ( (~mask)&(mask>>1) ); # endif } /** Returns the X pixel number used to draw the given FLTK color index. This is the X pixel that fl_color() would use. \param[in] i color index \return X pixel number */ ulong fl_xpixel(Fl_Color i) { if (i & 0xffffff00) { return fl_xpixel((i >> 24) & 255, (i >> 16) & 255, (i >> 8) & 255); } Fl_XColor &xmap = fl_xmap[Fl_Xlib_Graphics_Driver::fl_overlay][i]; if (xmap.mapped) return xmap.pixel; if (!beenhere) figure_out_visual(); uchar r,g,b; {unsigned c = fl_cmap[i]; r=uchar(c>>24); g=uchar(c>>16); b=uchar(c>>8);} # if USE_COLORMAP Colormap colormap = fl_colormap; if (fl_redmask) { # endif // return color for a truecolor visual: xmap.mapped = 2; // 2 prevents XFreeColor from being called xmap.r = realcolor(r, fl_redmask); xmap.g = realcolor(g, fl_greenmask); xmap.b = realcolor(b, fl_bluemask); return xmap.pixel = (((r&fl_redmask) << fl_redshift)+ ((g&fl_greenmask)<> fl_extrashift; # if USE_COLORMAP } static XColor *allcolors; static int numcolors; // I don't try to allocate colors with XAllocColor once it fails // with any color. It is possible that it will work, since a color // may have been freed, but some servers are extremely slow and this // avoids one round trip: if (!numcolors) { // don't try after a failure XColor xcol; xcol.red = r<<8; xcol.green = g<<8; xcol.blue = b<<8; if (XAllocColor(fl_display, colormap, &xcol)) { xmap.mapped = 1; xmap.r = xcol.red>>8; xmap.g = xcol.green>>8; xmap.b = xcol.blue>>8; return xmap.pixel = xcol.pixel; } // I only read the colormap once. Again this is due to the slowness // of round-trips to the X server, even though other programs may alter // the colormap after this and make decisions here wrong. numcolors = fl_visual->colormap_size; if (!allcolors) allcolors = new XColor[numcolors]; for (int p = numcolors; p--;) allcolors[p].pixel = p; XQueryColors(fl_display, colormap, allcolors, numcolors); } // find least-squares match: int mindist = 0x7FFFFFFF; unsigned int bestmatch = 0; for (unsigned int n = numcolors; n--;) { XColor &a = allcolors[n]; int d, t; t = int(r)-int(a.red>>8); d = t*t; t = int(g)-int(a.green>>8); d += t*t; t = int(b)-int(a.blue>>8); d += t*t; if (d <= mindist) {bestmatch = n; mindist = d;} } XColor &p = allcolors[bestmatch]; // It appears to "work" to not call this XAllocColor, which will // avoid another round-trip to the server. But then X does not // know that this program "owns" this value, and can (and will) // change it when the program that did allocate it exits: if (XAllocColor(fl_display, colormap, &p)) { xmap.mapped = 1; xmap.pixel = p.pixel; } else { // However, if that XAllocColor fails, I have to give up and // assume the pixel is ok for the duration of the program. This // is due to bugs (?) in the Solaris X and some X terminals // where XAllocColor *always* fails when the colormap is full, // even if we ask for a color already in it... xmap.mapped = 2; // 2 prevents XFreeColor from being called xmap.pixel = bestmatch; } xmap.r = p.red>>8; xmap.g = p.green>>8; xmap.b = p.blue>>8; return xmap.pixel; # endif } /** Free color \p i if used, and clear mapping table entry. \param[in] i color index \param[in] overlay 0 for normal, 1 for overlay color */ void Fl_Xlib_Graphics_Driver::free_color(Fl_Color i, int overlay) { if (overlay) return; if (fl_xmap[overlay][i].mapped) { # if USE_COLORMAP Colormap colormap = fl_colormap; if (fl_xmap[overlay][i].mapped == 1) XFreeColors(fl_display, colormap, &(fl_xmap[overlay][i].pixel), 1, 0); # endif fl_xmap[overlay][i].mapped = 0; } } /** Set color mapping table entry \p i to color \p c \param[in] i color index \param[in] c color */ void Fl_Xlib_Graphics_Driver::set_color(Fl_Color i, unsigned c) { if (fl_cmap[i] != c) { free_color(i,0); fl_cmap[i] = c; } } /** \} */ fltk-1.4.3/src/drivers/Cairo/0000755000175000017500000000000015004135251016107 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx0000644000175000017500000013611315004135251023451 0ustar albrechtalbrecht// // Support for Cairo graphics for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* \file Implementation of class Fl_Cairo_Graphics_Driver . */ #include #if USE_PANGO #include "Fl_Cairo_Graphics_Driver.H" #include "../../Fl_Screen_Driver.H" #include #include #include #include #include #if ! PANGO_VERSION_CHECK(1,16,0) # error "Requires Pango 1.16 or higher" #endif #if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1,10,0) # error "Requires Cairo 1.10 or higher" #endif #include #include // abs(int) #include // memcpy() #include // uint32_t extern unsigned fl_cmap[256]; // defined in fl_color.cxx // The predefined fonts that FLTK has with Pango: static Fl_Fontdesc built_in_table[] = { {"Sans"}, {"Sans Bold"}, {"Sans Italic"}, {"Sans Bold Italic"}, {"Monospace"}, {"Monospace Bold"}, {"Monospace Italic"}, {"Monospace Bold Italic"}, {"Serif"}, {"Serif Bold"}, {"Serif Italic"}, {"Serif Bold Italic"}, {"Standard Symbols PS"}, // FL_SYMBOL {"Monospace"}, {"Monospace Bold"}, {"D050000L"}, // FL_ZAPF_DINGBATS }; FL_EXPORT Fl_Fontdesc *fl_fonts = built_in_table; // Number of fonts found by Fl::set_fonts(char*) beyond FL_FREE_FONT // -1 denotes "not yet initialised" Fl_Font Fl_Cairo_Graphics_Driver::font_count_ = -1; // duplicated from Fl_PostScript.cxx struct callback_data { const uchar *data; int D, LD; }; static const int dashes_flat[5][7]={ {-1,0,0,0,0,0,0}, {3,1,-1,0,0,0,0}, {1,1,-1,0,0,0,0}, {3,1,1,1,-1,0,0}, {3,1,1,1,1,1,-1} }; static const double dashes_cap[5][7]={ {-1,0,0,0,0,0,0}, {2,2,-1,0,0,0,0}, {0.01,1.99,-1,0,0,0,0}, {2,2,0.01,1.99,-1,0,0}, {2,2,0.01,1.99,0.01,1.99,-1} }; static void draw_image_cb(void *data, int x, int y, int w, uchar *buf) { struct callback_data *cb_data; const uchar *curdata; cb_data = (struct callback_data*)data; int last = x+w; const size_t aD = abs(cb_data->D); curdata = cb_data->data + x*cb_data->D + y*cb_data->LD; for (; xD; } } // end of duplicated part Fl_Cairo_Graphics_Driver::Fl_Cairo_Graphics_Driver() : Fl_Graphics_Driver() { cairo_ = NULL; pango_layout_ = NULL; pango_context_ = NULL; dummy_cairo_ = NULL; linestyle_ = FL_SOLID; clip_ = NULL; scale_x = scale_y = 1; wld_scale = 1; angle = 0; left_margin = top_margin = 0; needs_commit_tag_ = NULL; what = NONE; } Fl_Cairo_Graphics_Driver::~Fl_Cairo_Graphics_Driver() { if (pango_layout_) g_object_unref(pango_layout_); if (pango_context_) g_object_unref(pango_context_); } const cairo_format_t Fl_Cairo_Graphics_Driver::cairo_format = CAIRO_FORMAT_ARGB32; void Fl_Cairo_Graphics_Driver::set_cairo(cairo_t *cr, float s) { if (dummy_cairo_) { cairo_destroy(dummy_cairo_); dummy_cairo_ = NULL; } cairo_ = cr; cairo_restore(cairo_); line_style(0); cairo_save(cairo_); if (s == 0) s = scale(); cairo_scale(cairo_, s, s); cairo_translate(cairo_, 0.5, 0.5); } void Fl_Cairo_Graphics_Driver::rectf(int x, int y, int w, int h) { cairo_rectangle(cairo_, x-0.5, y-0.5, w, h); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_fill(cairo_); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); check_status(); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::rect(int x, int y, int w, int h) { cairo_rectangle(cairo_, x, y, w-1, h-1); if (linestyle_ == FL_SOLID) cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_stroke(cairo_); if (linestyle_ == FL_SOLID) cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); check_status(); surface_needs_commit(); } static bool need_antialias_none(cairo_t *cairo_, int style) { cairo_matrix_t matrix; cairo_get_matrix(cairo_, &matrix); double width = cairo_get_line_width(cairo_) * matrix.xx; bool needit = (style == FL_SOLID && width < 1.5); if (needit) cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); return needit; } void Fl_Cairo_Graphics_Driver::line(int x1, int y1, int x2, int y2) { cairo_new_path(cairo_); cairo_move_to(cairo_, x1, y1); cairo_line_to(cairo_, x2, y2); bool needit = need_antialias_none(cairo_, linestyle_); cairo_stroke(cairo_); if (needit) cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::line(int x0, int y0, int x1, int y1, int x2, int y2) { cairo_new_path(cairo_); cairo_move_to(cairo_, x0, y0); cairo_line_to(cairo_, x1, y1); cairo_line_to(cairo_, x2, y2); bool needit = need_antialias_none(cairo_, linestyle_); cairo_stroke(cairo_); if (needit) cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1) { cairo_move_to(cairo_, x, y); cairo_line_to(cairo_, x1, y); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_stroke(cairo_); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); check_status(); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1, int y2) { cairo_move_to(cairo_, x, y); cairo_line_to(cairo_, x1, y); cairo_line_to(cairo_, x1, y2); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_stroke(cairo_); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); check_status(); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { cairo_move_to(cairo_, x, y); cairo_line_to(cairo_, x1, y); cairo_line_to(cairo_, x1, y2); cairo_line_to(cairo_, x3, y2); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_stroke(cairo_); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); check_status(); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1) { cairo_move_to(cairo_, x, y); cairo_line_to(cairo_, x, y1); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_stroke(cairo_); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); check_status(); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1, int x2) { cairo_move_to(cairo_, x, y); cairo_line_to(cairo_, x, y1); cairo_line_to(cairo_, x2, y1); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_stroke(cairo_); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); check_status(); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { cairo_move_to(cairo_, x, y); cairo_line_to(cairo_, x, y1); cairo_line_to(cairo_, x2, y1); cairo_line_to(cairo_, x2, y3); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_stroke(cairo_); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); check_status(); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { cairo_save(cairo_); cairo_new_path(cairo_); cairo_move_to(cairo_, x0, y0); cairo_line_to(cairo_, x1, y1); cairo_line_to(cairo_, x2, y2); cairo_close_path(cairo_); cairo_stroke(cairo_); cairo_restore(cairo_); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { cairo_save(cairo_); cairo_new_path(cairo_); cairo_move_to(cairo_, x0, y0); cairo_line_to(cairo_, x1, y1); cairo_line_to(cairo_, x2, y2); cairo_line_to(cairo_, x3, y3); cairo_close_path(cairo_); if ((y0==y1 && x1==x2 && y2==y3 && x3==x0) || (x0==x1 && y1==y2 && x2==x3 && y3==y0)) { cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); } cairo_stroke(cairo_); cairo_restore(cairo_); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { cairo_save(cairo_); cairo_new_path(cairo_); cairo_move_to(cairo_, x0, y0); cairo_line_to(cairo_, x1, y1); cairo_line_to(cairo_, x2, y2); cairo_close_path(cairo_); cairo_fill(cairo_); cairo_restore(cairo_); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { cairo_save(cairo_); cairo_new_path(cairo_); cairo_move_to(cairo_, x0, y0); cairo_line_to(cairo_, x1, y1); cairo_line_to(cairo_, x2, y2); cairo_line_to(cairo_, x3, y3); cairo_close_path(cairo_); if ((y0==y1 && x1==x2 && y2==y3 && x3==x0) || (x0==x1 && y1==y2 && x2==x3 && y3==y0)) { cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); } cairo_fill(cairo_); cairo_restore(cairo_); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::line_style(int style, int width, char* dashes) { linestyle_ = style; if(dashes){ if(dashes != linedash_) strcpy(linedash_,dashes); } else linedash_[0]=0; char width0 = 0; if (!width){ width=1; //for screen drawing compatibility width0=1; } cairo_set_line_width(cairo_, width); if(!style && (!dashes || !(*dashes)) && width0) //system lines style = FL_CAP_SQUARE; int cap = (style &0xf00); cairo_line_cap_t c_cap; if (cap == FL_CAP_SQUARE) c_cap = CAIRO_LINE_CAP_SQUARE; else if (cap == FL_CAP_FLAT) c_cap = CAIRO_LINE_CAP_BUTT; else if (cap == FL_CAP_ROUND) c_cap = CAIRO_LINE_CAP_ROUND; else c_cap = CAIRO_LINE_CAP_BUTT; cairo_set_line_cap(cairo_, c_cap); int join = (style & 0xf000); cairo_line_join_t c_join; if (join == FL_JOIN_MITER) c_join = CAIRO_LINE_JOIN_MITER; else if (join == FL_JOIN_ROUND)c_join = CAIRO_LINE_JOIN_ROUND; else if (join == FL_JOIN_BEVEL) c_join = CAIRO_LINE_JOIN_BEVEL; else c_join = CAIRO_LINE_JOIN_MITER; cairo_set_line_join(cairo_, c_join); double *ddashes = NULL; int l = 0; if (dashes && *dashes){ ddashes = new double[strlen(dashes)]; while (dashes[l]) {ddashes[l] = dashes[l]; l++; } } else if (style & 0xff) { ddashes = new double[6]; if (style & 0x200){ // round and square caps, dash length need to be adjusted const double *dt = dashes_cap[style & 0xff]; while (*dt >= 0){ ddashes[l++] = width * (*dt); dt++; } } else { const int *ds = dashes_flat[style & 0xff]; while (*ds >= 0){ ddashes[l++] = width * (*ds); ds++; } } } cairo_set_dash(cairo_, ddashes, l, 0); cairo_set_antialias(cairo_, l ? CAIRO_ANTIALIAS_NONE : CAIRO_ANTIALIAS_DEFAULT); delete[] ddashes; check_status(); } void Fl_Cairo_Graphics_Driver::color(unsigned char r, unsigned char g, unsigned char b) { Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) ); cr_ = r; cg_ = g; cb_ = b; double fr, fg, fb; fr = r/255.0; fg = g/255.0; fb = b/255.0; cairo_set_source_rgb(cairo_, fr, fg, fb); check_status(); } void Fl_Cairo_Graphics_Driver::color(Fl_Color i) { Fl_Graphics_Driver::color(i); if (!cairo_) return; // no context yet? We will assign the color later. uchar r, g, b; double fa = 1.0; if (i & 0xFFFFFF00) { // translate rgb colors into color index r = i>>24; g = i>>16; b = i>> 8; } else { // translate index into rgb: unsigned c = fl_cmap[i]; c = c ^ 0x000000ff; // trick to restore the color's correct alpha value r = c>>24; g = c>>16; b = c>> 8; fa = (c & 0xff)/255.0; } double fr = r/255.0; double fg = g/255.0; double fb = b/255.0; cairo_set_source_rgba(cairo_, fr, fg, fb, fa); } Fl_Color Fl_Cairo_Graphics_Driver::color() { return Fl_Graphics_Driver::color(); } void Fl_Cairo_Graphics_Driver::concat(){ cairo_matrix_t mat = {m.a , m.b , m.c , m.d , m.x , m.y}; cairo_transform(cairo_, &mat); } void Fl_Cairo_Graphics_Driver::reconcat(){ cairo_matrix_t mat = {m.a , m.b , m.c , m.d , m.x , m.y}; cairo_status_t stat = cairo_matrix_invert(&mat); if (stat != CAIRO_STATUS_SUCCESS) { fputs("error in cairo_matrix_invert\n", stderr); } cairo_transform(cairo_, &mat); } void Fl_Cairo_Graphics_Driver::begin_line() { cairo_save(cairo_); concat(); cairo_new_path(cairo_); gap_=1; what=LINE; } void Fl_Cairo_Graphics_Driver::begin_loop() { cairo_save(cairo_); concat(); cairo_new_path(cairo_); gap_=1; what=LOOP; } void Fl_Cairo_Graphics_Driver::begin_polygon() { cairo_save(cairo_); concat(); cairo_new_path(cairo_); gap_=1; what=POLYGON; } void Fl_Cairo_Graphics_Driver::vertex(double x, double y) { if (what==POINTS){ return Fl_Graphics_Driver::vertex(x, y); } if (gap_){ cairo_move_to(cairo_, x, y); gap_=0; } else { cairo_line_to(cairo_, x, y); surface_needs_commit(); } } void Fl_Cairo_Graphics_Driver::curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3) { if(what==NONE) return; if (what == POINTS) Fl_Graphics_Driver::curve(x, y, x1, y1, x2, y2, x3, y3); else { if(gap_) cairo_move_to(cairo_, x, y); else cairo_line_to(cairo_, x, y); gap_=0; cairo_curve_to(cairo_, x1 , y1 , x2 , y2 , x3 , y3); } surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::circle(double x, double y, double r){ if (what == NONE) { cairo_save(cairo_); concat(); cairo_arc(cairo_, x, y, r, 0, 2*M_PI); cairo_stroke(cairo_); reconcat(); cairo_restore(cairo_); } else { cairo_arc(cairo_, x, y, r, 0, 2*M_PI); } surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::arc(double x, double y, double r, double start, double a){ if (what == NONE) return; if (gap_ == 1) cairo_new_sub_path(cairo_); // 1.2 gap_ = 0; if (start > a) cairo_arc(cairo_, x, y, r, -start*M_PI/180, -a*M_PI/180); else cairo_arc_negative(cairo_, x, y, r, -start*M_PI/180, -a*M_PI/180); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) { if (w <= 1 || h <= 1) return; cairo_save(cairo_); begin_line(); cairo_translate(cairo_, x + w/2.0 -0.5 , y + h/2.0 - 0.5); cairo_scale(cairo_, (w-1)/2.0 , (h-1)/2.0); arc(0,0,1,a2,a1); cairo_scale(cairo_, 2.0/(w-1) , 2.0/(h-1)); cairo_translate(cairo_, -x - w/2.0 +0.5 , -y - h/2.0 +0.5); end_line(); cairo_restore(cairo_); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) { cairo_save(cairo_); begin_polygon(); cairo_translate(cairo_, x + w/2.0 -0.5 , y + h/2.0 - 0.5); cairo_scale(cairo_, w/2.0 , h/2.0); vertex(0,0); arc(0.0,0.0, 1, a2, a1); end_polygon(); cairo_restore(cairo_); } void Fl_Cairo_Graphics_Driver::end_points() { for (int i = 0; i < n; i++) { point(xpoint[i].x, xpoint[i].y); } } void Fl_Cairo_Graphics_Driver::end_line() { gap_ = 1; reconcat(); cairo_stroke(cairo_); cairo_restore(cairo_); what = NONE; surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::end_loop(){ gap_ = 1; reconcat(); cairo_close_path(cairo_); cairo_stroke(cairo_); cairo_restore(cairo_); what = NONE; surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::end_polygon() { gap_ = 1; reconcat(); cairo_close_path(cairo_); cairo_fill(cairo_); cairo_restore(cairo_); what = NONE; surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::transformed_vertex(double x, double y) { if (what == POINTS) { Fl_Graphics_Driver::transformed_vertex(x, y); } else { reconcat(); if (gap_) { cairo_move_to(cairo_, x, y); gap_ = 0; } else { cairo_line_to(cairo_, x, y); surface_needs_commit(); } concat(); } } void Fl_Cairo_Graphics_Driver::push_clip(int x, int y, int w, int h) { Clip *c = new Clip(); clip_box(x,y,w,h,c->x,c->y,c->w,c->h); c->prev = clip_; clip_ = c; cairo_save(cairo_); cairo_rectangle(cairo_, clip_->x - 0.5 , clip_->y - 0.5 , clip_->w, clip_->h); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_clip(cairo_); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); check_status(); } void Fl_Cairo_Graphics_Driver::push_no_clip() { Clip *c = new Clip(); c->prev = clip_; clip_ = c; clip_->x = clip_->y = clip_->w = clip_->h = -1; cairo_save(cairo_); cairo_reset_clip(cairo_); check_status(); } void Fl_Cairo_Graphics_Driver::pop_clip() { if(!clip_)return; Clip *c = clip_; clip_ = clip_->prev; delete c; cairo_restore(cairo_); check_status(); } void Fl_Cairo_Graphics_Driver::ps_origin(int x, int y) { cairo_restore(cairo_); cairo_restore(cairo_); cairo_save(cairo_); cairo_scale(cairo_, scale_x, scale_y); cairo_translate(cairo_, x, y); cairo_rotate(cairo_, angle * M_PI / 180); cairo_save(cairo_); check_status(); } void Fl_Cairo_Graphics_Driver::ps_translate(int x, int y) { cairo_save(cairo_); cairo_translate(cairo_, x, y); cairo_save(cairo_); check_status(); } void Fl_Cairo_Graphics_Driver::ps_untranslate(void) { cairo_restore(cairo_); cairo_restore(cairo_); check_status(); } void Fl_Cairo_Graphics_Driver::check_status(void) { #ifdef DEBUG if (cairo_status(cairo_) != CAIRO_STATUS_SUCCESS) { fprintf(stderr,"we have a problem"); } #endif } void Fl_Cairo_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D) { uchar *array = new uchar[iw * D * ih]; for (int l = 0; l < ih; l++) { call(data, 0, l, iw, array + l*D*iw); if (D%2 == 0) for (int i = 0; i < iw; i++) { *(array + l*D*iw + i*D + D-1) = 0xff; } } Fl_RGB_Image *rgb = new Fl_RGB_Image(array, iw, ih, D); rgb->alloc_array = 1; draw_rgb(rgb, ix, iy, iw, ih, 0, 0); delete rgb; surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::draw_image_mono(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) { struct callback_data cb_data; const size_t aD = abs(D); if (!LD) LD = iw * aD; cb_data.data = data; cb_data.D = D; cb_data.LD = LD; draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, abs(D)); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D) { draw_image(call, data, ix, iy, iw, ih, D); } int Fl_Cairo_Graphics_Driver::not_clipped(int x, int y, int w, int h) { if (!clip_) return 1; if (clip_->w < 0) return 1; int X = 0, Y = 0, W = 0, H = 0; clip_box(x, y, w, h, X, Y, W, H); if (W) return 1; return 0; } int Fl_Cairo_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) { if (!clip_) { X = x; Y = y; W = w; H = h; return 0; } if (clip_->w < 0) { X = x; Y = y; W = w; H = h; return 1; } int ret = 0; if (x > (X=clip_->x)) {X=x; ret=1;} if (y > (Y=clip_->y)) {Y=y; ret=1;} if ((x+w) < (clip_->x+clip_->w)) { W=x+w-X; ret=1; }else W = clip_->x + clip_->w - X; if(W<0){ W=0; return 1; } if ((y+h) < (clip_->y+clip_->h)) { H=y+h-Y; ret=1; }else H = clip_->y + clip_->h - Y; if(H<0){ W=0; H=0; return 1; } return ret; } void Fl_Cairo_Graphics_Driver::point(int x, int y) { rectf(x, y, 1, 1); } void Fl_Cairo_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) { if (abs(D)<3){ //mono draw_image_mono(data, ix, iy, iw, ih, D, LD); return; } struct callback_data cb_data; if (!LD) LD = iw*abs(D); cb_data.data = data; cb_data.D = D; cb_data.LD = LD; Fl_Cairo_Graphics_Driver::draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, abs(D)); } void Fl_Cairo_Graphics_Driver::overlay_rect(int x, int y, int w , int h) { cairo_save(cairo_); cairo_matrix_t mat; cairo_get_matrix(cairo_, &mat); float s = (float)mat.xx; cairo_matrix_init_identity(&mat); cairo_set_matrix(cairo_, &mat); // use drawing units int lwidth = s < 1 ? 1 : int(s); cairo_set_line_width(cairo_, lwidth); cairo_translate(cairo_, lwidth/2., lwidth/2.); // translate by half of line width double ddash = (lwidth > 2 ? lwidth : 2); if (linestyle_ == FL_DOT) { cairo_set_dash(cairo_, &ddash, 1, 0); // dash size = line width } // rectangle in drawing units int Xs = Fl_Scalable_Graphics_Driver::floor(x, s); int Ws = Fl_Scalable_Graphics_Driver::floor(x+w-1, s) - Xs; int Ys = Fl_Scalable_Graphics_Driver::floor(y, s); int Hs = Fl_Scalable_Graphics_Driver::floor(y+h-1, s) - Ys; cairo_move_to(cairo_, Xs, Ys); cairo_line_to(cairo_, Xs+Ws, Ys); cairo_line_to(cairo_, Xs+Ws, Ys+Hs); cairo_line_to(cairo_, Xs, Ys+Hs); cairo_close_path(cairo_); cairo_stroke(cairo_); cairo_restore(cairo_); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::draw_cached_pattern_(Fl_Image *img, cairo_pattern_t *pat, int X, int Y, int W, int H, int cx, int cy, int cache_w, int cache_h) { // compute size of output image in drawing units cairo_matrix_t matrix; cairo_get_matrix(cairo_, &matrix); float s = (float)matrix.xx; int Xs = Fl_Scalable_Graphics_Driver::floor(X - cx, s); int Ws = Fl_Scalable_Graphics_Driver::floor(X - cx + img->w(), s) - Xs ; int Ys = Fl_Scalable_Graphics_Driver::floor(Y - cy, s); int Hs = Fl_Scalable_Graphics_Driver::floor(Y - cy + img->h(), s) - Ys; if (Ws == 0 || Hs == 0) return; cairo_save(cairo_); bool need_extend = (cache_w != Ws || cache_h != Hs || (W >= 2 && H >= 2)); if (need_extend || cx || cy || W < img->w() || H < img->h()) { // clip when necessary cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_rectangle(cairo_, X - 0.5, Y - 0.5, W, H); cairo_clip(cairo_); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT); } // remove any scaling and the current "0.5" translation useful for lines but bad for images matrix.xx = matrix.yy = 1; matrix.x0 -= 0.5 * s; matrix.y0 -= 0.5 * s; cairo_set_matrix(cairo_, &matrix); if (img->d() >= 1) cairo_set_source(cairo_, pat); if (need_extend) { bool condition = Fl_RGB_Image::scaling_algorithm() == FL_RGB_SCALING_BILINEAR && (fabs(Ws/float(cache_w) - 1) > 0.02 || fabs(Hs/float(cache_h) - 1) > 0.02); cairo_pattern_set_filter(pat, condition ? CAIRO_FILTER_GOOD : CAIRO_FILTER_FAST); cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD); } cairo_matrix_init_scale(&matrix, double(cache_w)/Ws, double(cache_h)/Hs); cairo_matrix_translate(&matrix, -Xs , -Ys ); cairo_pattern_set_matrix(pat, &matrix); if (img->d() > 1) cairo_paint(cairo_); else cairo_mask(cairo_, pat); cairo_restore(cairo_); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; // Don't draw an empty image... if (!rgb->d() || !rgb->array) { Fl_Graphics_Driver::draw_empty(rgb, XP, YP); return; } if (start_image(rgb, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; } cairo_pattern_t *pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(rgb); if (!pat) { cache(rgb); pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(rgb); } draw_cached_pattern_(rgb, pat, X, Y, W, H, cx, cy, rgb->cache_w(), rgb->cache_h()); } static cairo_user_data_key_t data_key_for_surface = {}; static void dealloc_surface_data(void *data) { delete[] (uchar*)data; } void Fl_Cairo_Graphics_Driver::cache(Fl_RGB_Image *rgb) { int stride = cairo_format_stride_for_width(Fl_Cairo_Graphics_Driver::cairo_format, rgb->data_w()); // 1.6 uchar *BGRA = new uchar[stride * rgb->data_h()]; memset(BGRA, 0, stride * rgb->data_h()); int lrgb = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d(); uchar A = 0xff, R,G,B, *q; const uchar *r; float f = 1; if (rgb->d() >= 3) { // color images for (int j = 0; j < rgb->data_h(); j++) { r = rgb->array + j * lrgb; q = BGRA + j * stride; for (int i = 0; i < rgb->data_w(); i++) { R = *r; G = *(r+1); B = *(r+2); if (rgb->d() == 4) { A = *(r+3); f = float(A)/0xff; } // this produces ARGB data in native endian *(uint32_t *)q = A << 24 | (uchar)(R*f) << 16 | (uchar)(G*f) << 8 | (uchar)(B*f); r += rgb->d(); q += 4; } } } else if (rgb->d() == 1 || rgb->d() == 2) { // B&W for (int j = 0; j < rgb->data_h(); j++) { r = rgb->array + j * lrgb; q = BGRA + j * stride; for (int i = 0; i < rgb->data_w(); i++) { G = *r; if (rgb->d() == 2) { A = *(r+1); f = float(A)/0xff; } G = (uchar)(G * f); // this produces ARGB data in native endian *(uint32_t *)q = A << 24 | G << 16 | G << 8 | G; r += rgb->d(); q += 4; } } } cairo_surface_t *surf = cairo_image_surface_create_for_data(BGRA, Fl_Cairo_Graphics_Driver::cairo_format, rgb->data_w(), rgb->data_h(), stride); if (cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS) return; (void)cairo_surface_set_user_data(surf, &data_key_for_surface, BGRA, dealloc_surface_data); cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf); cairo_surface_destroy(surf); *Fl_Graphics_Driver::id(rgb) = (fl_uintptr_t)pat; int *pw, *ph; cache_w_h(rgb, pw, ph); *pw = rgb->data_w(); *ph = rgb->data_h(); } void Fl_Cairo_Graphics_Driver::uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) { cairo_pattern_t *pat = (cairo_pattern_t*)id_; if (pat) { cairo_pattern_destroy(pat); id_ = 0; } } void Fl_Cairo_Graphics_Driver::draw_fixed(Fl_Bitmap *bm,int XP, int YP, int WP, int HP, int cx, int cy) { cairo_pattern_t *pat = NULL; float s = wld_scale * scale(); XP = Fl_Scalable_Graphics_Driver::floor(XP, s); YP = Fl_Scalable_Graphics_Driver::floor(YP, s); cache_size(bm, WP, HP); cx *= s; cy *= s; cairo_matrix_t matrix; // temporarily remove scaling cairo_get_matrix(cairo_, &matrix); cairo_translate(cairo_, -0.5, -0.5); cairo_scale(cairo_, 1./s, 1/s); cairo_translate(cairo_, 0.5, 0.5); if (!bm->array) { draw_empty(bm, XP, YP); } else { pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(bm); color(color()); int old_w = bm->w(), old_h = bm->h(); bm->scale(bm->cache_w(), bm->cache_h(), 0, 1); // transiently draw_cached_pattern_(bm, pat, XP, YP, WP, HP, cx, cy, bm->cache_w(), bm->cache_h()); bm->scale(old_w, old_h, 0, 1); // back } cairo_set_matrix(cairo_, &matrix); } cairo_pattern_t *Fl_Cairo_Graphics_Driver::bitmap_to_pattern(Fl_Bitmap *bm, bool complement, cairo_surface_t **p_surface) { int stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, bm->data_w()); // 1.6 int w_bitmap = ((bm->data_w() + 7) / 8); uchar *BGRA = new uchar[stride * bm->data_h()]; memset(BGRA, 0, stride * bm->data_h()); for (int j = 0; j < bm->data_h(); j++) { uchar *r = (uchar *)bm->array + j * w_bitmap; uint32_t *q = (uint32_t *)(BGRA + j * stride); int k = 0; uint32_t mask32; uchar p; for (int i = 0; i < bm->data_w(); i++) { if (k == 0) { #if WORDS_BIGENDIAN mask32 = (uint32_t)(1 << 31); #else mask32 = 1; #endif } if ((k & 7) == 0) { // (k & 7) == (k % 8) p = *r++; if (complement) p = ~p; } if (p & 1) (*q) |= mask32; k++; p >>= 1; #if WORDS_BIGENDIAN mask32 >>= 1; #else mask32 <<= 1; #endif if (k == 32) { k = 0; q++; } } } cairo_surface_t *surf = cairo_image_surface_create_for_data(BGRA, CAIRO_FORMAT_A1, bm->data_w(), bm->data_h(), stride); cairo_pattern_t *pattern = cairo_pattern_create_for_surface(surf); if (p_surface) *p_surface = surf; else cairo_surface_destroy(surf); return pattern; } void Fl_Cairo_Graphics_Driver::cache(Fl_Bitmap *bm) { cairo_surface_t *surf; cairo_pattern_t *pattern = Fl_Cairo_Graphics_Driver::bitmap_to_pattern(bm, false, &surf); uchar *BGRA = cairo_image_surface_get_data(surf); // 1.2 (void)cairo_surface_set_user_data(surf, &data_key_for_surface, BGRA, dealloc_surface_data); cairo_surface_destroy(surf); *Fl_Graphics_Driver::id(bm) = (fl_uintptr_t)pattern; int *pw, *ph; cache_w_h(bm, pw, ph); *pw = bm->data_w(); *ph = bm->data_h(); } void Fl_Cairo_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) { cairo_pattern_t *pat = NULL; float s = wld_scale * scale(); XP = Fl_Scalable_Graphics_Driver::floor(XP, s); YP = Fl_Scalable_Graphics_Driver::floor(YP, s); cache_size(pxm, WP, HP); cx *= s; cy *= s; cairo_matrix_t matrix; // temporarily remove scaling cairo_get_matrix(cairo_, &matrix); cairo_translate(cairo_, -0.5, -0.5); cairo_scale(cairo_, 1/s, 1/s); cairo_translate(cairo_, 0.5, 0.5); // Don't draw an empty image... if (!pxm->data() || !pxm->w()) { Fl_Graphics_Driver::draw_empty(pxm, XP, YP); } else { pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(pxm); int old_w = pxm->w(), old_h = pxm->h(); pxm->scale(pxm->cache_w(), pxm->cache_h(), 0, 1); // transiently draw_cached_pattern_(pxm, pat, XP, YP, WP, HP, cx, cy, pxm->cache_w(), pxm->cache_h()); pxm->scale(old_w, old_h, 0, 1); // back } cairo_set_matrix(cairo_, &matrix); } void Fl_Cairo_Graphics_Driver::cache(Fl_Pixmap *pxm) { Fl_RGB_Image *rgb = new Fl_RGB_Image(pxm); cache(rgb); *Fl_Graphics_Driver::id(pxm) = *Fl_Graphics_Driver::id(rgb); *Fl_Graphics_Driver::id(rgb) = 0; delete rgb; int *pw, *ph; cache_w_h(pxm, pw, ph); *pw = pxm->data_w(); *ph = pxm->data_h(); } void Fl_Cairo_Graphics_Driver::uncache_pixmap(fl_uintptr_t p) { if (p) cairo_pattern_destroy((cairo_pattern_t*)p); } void Fl_Cairo_Graphics_Driver::delete_bitmask(fl_uintptr_t bm) { if (bm) cairo_pattern_destroy((cairo_pattern_t*)bm); } int Fl_Cairo_Graphics_Driver::height() { if (!font_descriptor()) font(0, 12); return ceil(((Fl_Cairo_Font_Descriptor*)font_descriptor())->line_height / float(PANGO_SCALE)); } int Fl_Cairo_Graphics_Driver::descent() { return font_descriptor()->descent / float(PANGO_SCALE) + 0.5; } void Fl_Cairo_Graphics_Driver::init_built_in_fonts() { static int i = 0; if (!i) { while (i < FL_FREE_FONT) { i++; Fl::set_font((Fl_Font)i-1, fl_fonts[i-1].name); } } } // FIXME: this (static) function should likely be in Fl_Graphics_Driver. // The code is the same as in src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx static int font_name_process(const char *name, char &face) { int l = strlen(name); face = ' '; if (l > 8 && !memcmp(name + l - 8, " Regular", 8)) l -= 8; else if (l > 6 && !memcmp(name + l - 6, " Plain", 6)) l -= 6; else if (l > 12 && !memcmp(name + l - 12, " Bold Italic", 12)) {l -= 12; face = 'P';} else if (l > 7 && !memcmp(name + l - 7, " Italic", 7)) {l -= 7; face = 'I';} else if (l > 5 && !memcmp(name + l - 5, " Bold", 5)) {l -= 5; face = 'B';} return l; } typedef int (*sort_f_type)(const void *aa, const void *bb); static int font_sort(Fl_Fontdesc *fa, Fl_Fontdesc *fb) { char face_a, face_b; int la = font_name_process(fa->name, face_a); int lb = font_name_process(fb->name, face_b); int c = strncasecmp(fa->name, fb->name, la >= lb ? lb : la); return (c == 0 ? face_a - face_b : c); } Fl_Font Fl_Cairo_Graphics_Driver::set_fonts(const char* /*pattern_name*/) { // Return immideatly if the fonts were already counted if (font_count_ != -1) return FL_FREE_FONT + font_count_; fl_open_display(); int n_families, count = 0; PangoFontFamily **families; char *saved_lang = fl_getenv("LANG"); const char *Clang = "LANG=C"; if (saved_lang && strcmp(saved_lang, Clang)) { // Force LANG=C to prevent pango_font_face_get_face_name() below from returning // translated versions of Bold, Italic, etc… (see issue #732). // Unfortunately, using setlocale() doesn't do the job. char *p = saved_lang; saved_lang = (char*)malloc(strlen(p) + 6); memcpy(saved_lang, "LANG=", 5); strcpy(saved_lang + 5, p); fl_putenv(Clang); } else saved_lang = NULL; static PangoFontMap *pfmap_ = pango_cairo_font_map_get_default(); // 1.10 Fl_Cairo_Graphics_Driver::init_built_in_fonts(); pango_font_map_list_families(pfmap_, &families, &n_families); for (int fam = 0; fam < n_families; fam++) { PangoFontFace **faces; int n_faces; const char *fam_name = pango_font_family_get_name (families[fam]); int lfam = strlen(fam_name); pango_font_family_list_faces(families[fam], &faces, &n_faces); for (int j = 0; j < n_faces; j++) { const char *p = pango_font_face_get_face_name(faces[j]); // Remove " Regular" suffix from font names if (!strcasecmp(p, "regular")) p = NULL; // build the font's FLTK name int lfont = lfam + (p ? strlen(p) + 2 : 1); char *q = new char[lfont]; if (p) snprintf(q, lfont, "%s %s", fam_name, p); else strcpy(q, fam_name); Fl::set_font((Fl_Font)(count++ + FL_FREE_FONT), q); } /*g_*/free(faces); // glib source code shows that g_free is equivalent to free } /*g_*/free(families); if (saved_lang) { fl_putenv(saved_lang); free(saved_lang); } // Sort the list into alphabetic order qsort(fl_fonts + FL_FREE_FONT, count, sizeof(Fl_Fontdesc), (sort_f_type)font_sort); font_count_ = count; return FL_FREE_FONT + count; } const char *Fl_Cairo_Graphics_Driver::font_name(int num) { return fl_fonts[num].name; } void Fl_Cairo_Graphics_Driver::font_name(int num, const char *name) { Fl_Fontdesc *s = fl_fonts + num; if (s->name) { if (!strcmp(s->name, name)) {s->name = name; return;} for (Fl_Font_Descriptor* f = s->first; f;) { Fl_Font_Descriptor* n = f->next; delete f; f = n; } s->first = 0; } s->name = name; s->fontname[0] = 0; s->first = 0; } // turn a stored font name into a pretty name: #define ENDOFBUFFER sizeof(fl_fonts->fontname)-1 const char* Fl_Cairo_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) { Fl_Fontdesc *f = fl_fonts + fnum; if (!f->fontname[0]) { strcpy(f->fontname, f->name); // to check const char* thisFont = f->name; if (!thisFont || !*thisFont) {if (ap) *ap = 0; return "";} int type = 0; if (strstr(f->name, "Bold")) type |= FL_BOLD; if (strstr(f->name, "Italic") || strstr(f->name, "Oblique")) type |= FL_ITALIC; f->fontname[ENDOFBUFFER] = (char)type; } if (ap) *ap = f->fontname[ENDOFBUFFER]; return f->fontname; } int Fl_Cairo_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) { static int array[128]; if (!fl_fonts) fl_fonts = calc_fl_fonts(); Fl_Fontdesc *s = fl_fonts+fnum; if (!s->name) s = fl_fonts; // empty slot in table, use entry 0 int cnt = 0; array[0] = 0; sizep = array; cnt = 1; return cnt; } Fl_Cairo_Font_Descriptor::Fl_Cairo_Font_Descriptor(const char* name, Fl_Fontsize size, PangoContext *context) : Fl_Font_Descriptor(name, size) { char *string = new char[strlen(name) + 10]; strcpy(string, name); snprintf(string + strlen(string), 10, " %dpx", size); //A PangoFontDescription describes a font in an implementation-independent manner. fontref = pango_font_description_from_string(string); delete[] string; width = NULL; //A PangoFontset represents a set of PangoFont to use when rendering text. PangoFontset *fontset = pango_font_map_load_fontset( pango_cairo_font_map_get_default(), // 1.10 context, fontref, pango_language_get_default() // 1.16 ); PangoFontMetrics *metrics = pango_fontset_get_metrics(fontset); ascent = pango_font_metrics_get_ascent(metrics); descent = pango_font_metrics_get_descent(metrics); /* Function pango_font_metrics_get_height() giving the line height of a pango font appears with pango version 1.44. However, with pango version 1.48.10 and below, this function gives values that make the underscore invisible on lowdpi display and at 100% scaling (the underscore becomes visible starting at 120% scaling). With pango version 1.50.6 (Ubuntu 22.04) this problem disappears. Consequently, function pango_font_metrics_get_height() is not used until version 1.50.6 */ //#if PANGO_VERSION_CHECK(1,44,0) #if PANGO_VERSION_CHECK(1,50,6) line_height = pango_font_metrics_get_height(metrics); // 1.44 #else line_height = (pango_font_metrics_get_ascent(metrics) + pango_font_metrics_get_descent(metrics)) * 1.025 + 0.5; #endif pango_font_metrics_unref(metrics); g_object_unref(fontset); //fprintf(stderr, "[%s](%d) ascent=%d descent=%d line_height=%d\n", name, size, ascent, descent, line_height); } Fl_Cairo_Font_Descriptor::~Fl_Cairo_Font_Descriptor() { pango_font_description_free(fontref); if (width) { for (int i = 0; i < 64; i++) delete[] width[i]; } delete[] width; } static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size, PangoContext *context) { Fl_Fontdesc* s = fl_fonts+fnum; if (!s->name) s = fl_fonts; // use 0 if fnum undefined Fl_Font_Descriptor* f; for (f = s->first; f; f = f->next) if (f->size == size) return f; f = new Fl_Cairo_Font_Descriptor(s->name, size, context); f->next = s->first; s->first = f; return f; } /* Implementation note : * The pixel width of a drawn string equals the sum of the widths of its * characters, except when kerning occurs. */ void Fl_Cairo_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize s) { if (!font_descriptor()) fl_open_display(); if (!cairo_) { cairo_surface_t *surf = cairo_image_surface_create(Fl_Cairo_Graphics_Driver::cairo_format, 100, 100); cairo_ = cairo_create(surf); cairo_surface_destroy(surf); dummy_cairo_ = cairo_; } if (s == 0) return; if (fnum == -1) { Fl_Graphics_Driver::font(0, 0); return; } Fl_Graphics_Driver::font(fnum, s); if (!pango_context_) { //A PangoFontMap represents the set of fonts available for a particular rendering system. PangoFontMap *def_font_map = pango_cairo_font_map_get_default(); // 1.10 //A PangoContext stores global information used to control the itemization process. #if PANGO_VERSION_CHECK(1,22,0) pango_context_ = pango_font_map_create_context(def_font_map); // 1.22 #else pango_context_ = pango_context_new(); pango_context_set_font_map(pango_context_, def_font_map); #endif pango_layout_ = pango_layout_new(pango_context_); } font_descriptor( find(fnum, s, pango_context_) ); //If no font description is set on the layout, the font description from the layout’s context is used. pango_context_set_font_description(pango_context_, ((Fl_Cairo_Font_Descriptor*)font_descriptor())->fontref); } // Scans the input string str with fl_utf8decode() that, by default, accepts // also non-UTF-8 and processes it as if encoded in CP1252. // Returns a true UTF-8 string and its length, possibly transformed from CP1252. // If the input string is true UTF-8, the returned string is the same pointer as input. // Otherwise, the returned string is in private memory allocated inside clean_utf8() // and extended when necessary. const char *Fl_Cairo_Graphics_Driver::clean_utf8(const char* str, int &n) { static char *utf8_buffer = NULL; static int utf8_buffer_len = 0; char *q = utf8_buffer; const char *p = str; const char *retval = str; int len, len2; const char *end = str + n; char buf4[4]; while (p < end) { unsigned codepoint = fl_utf8decode(p, end, &len); if (retval != str || (len == 1 && *(uchar*)p >= 0x80)) { // switch to using utf8_buffer len2 = fl_utf8encode(codepoint, buf4); if (!utf8_buffer_len || utf8_buffer_len < (q - utf8_buffer) + len2) { utf8_buffer_len += (q - utf8_buffer) + len2 + 1000; utf8_buffer = (char *)realloc(utf8_buffer, utf8_buffer_len); } if (retval == str) { retval = utf8_buffer; q = utf8_buffer; if (p > str) { memcpy(q, str, p - str); q += (p - str); } } memcpy(q, buf4, len2); q += len2; } p += len; } if (retval != str) n = q - retval; return retval; } void Fl_Cairo_Graphics_Driver::draw(const char* str, int n, float x, float y) { if (!n) return; cairo_save(cairo_); Fl_Cairo_Font_Descriptor *fd = (Fl_Cairo_Font_Descriptor*)font_descriptor(); cairo_translate(cairo_, x - 1, y - (fd->line_height - fd->descent) / float(PANGO_SCALE) - 1); str = clean_utf8(str, n); pango_layout_set_text(pango_layout_, str, n); pango_cairo_show_layout(cairo_, pango_layout_); // 1.1O cairo_restore(cairo_); surface_needs_commit(); } void Fl_Cairo_Graphics_Driver::draw(int rotation, const char *str, int n, int x, int y) { cairo_save(cairo_); cairo_translate(cairo_, x, y); cairo_rotate(cairo_, -rotation * M_PI / 180); this->draw(str, n, 0, 0); cairo_restore(cairo_); } void Fl_Cairo_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) { int w = (int)width(str, n); draw(str, n, x - w, y); } // cache the widths of single Unicode characters double Fl_Cairo_Graphics_Driver::width(unsigned int utf32) { unsigned r=0; Fl_Cairo_Font_Descriptor *desc = NULL; if (utf32 <= 0xFFFF) { desc = (Fl_Cairo_Font_Descriptor*)font_descriptor(); r = (utf32 & 0xFC00) >> 10; if (!desc->width) { desc->width = (int**)new int*[64]; memset(desc->width, 0, 64*sizeof(int*)); } if (!desc->width[r]) { desc->width[r] = (int*)new int[0x0400]; for (int i = 0; i < 0x0400; i++) desc->width[r][i] = -1; } else { if ( desc->width[r][utf32&0x03FF] >= 0 ) { // already cached return desc->width[r][utf32 & 0x03FF] / double(PANGO_SCALE); } } } char buf4[4]; int n = fl_utf8encode(utf32, buf4); int width = do_width_unscaled_(buf4, n); if (utf32 <= 0xFFFF) { desc->width[r][utf32 & 0x03FF] = width; } return width / double(PANGO_SCALE); } double Fl_Cairo_Graphics_Driver::width(const char* str, int n) { if (!font_descriptor()) return -1; if ((str == NULL) || (n == 0)) return 0.; if (n == fl_utf8len(*str)) { // str contains a single unicode character int l; unsigned c = fl_utf8decode(str, str+n, &l); return width(c); // that character's width may have been cached } return do_width_unscaled_(str, n) / double(PANGO_SCALE); // full width computation for multi-char strings } int Fl_Cairo_Graphics_Driver::do_width_unscaled_(const char* str, int n) { if (!n) return 0; str = clean_utf8(str, n); pango_layout_set_text(pango_layout_, str, n); PangoRectangle p_rect; pango_layout_get_extents(pango_layout_, NULL, &p_rect); return p_rect.width; } void Fl_Cairo_Graphics_Driver::text_extents(const char* txt, int n, int& dx, int& dy, int& w, int& h) { txt = clean_utf8(txt, n); pango_layout_set_text(pango_layout_, txt, n); PangoRectangle ink_rect; pango_layout_get_extents(pango_layout_, &ink_rect, NULL); double f = PANGO_SCALE; Fl_Cairo_Font_Descriptor *fd = (Fl_Cairo_Font_Descriptor*)font_descriptor(); dx = ink_rect.x / f - 1; dy = (ink_rect.y - fd->line_height + fd->descent) / f - 1; w = ceil(ink_rect.width / f); h = ceil(ink_rect.height / f); } // // Region-handling member functions. // They are used ONLY if the cairo graphics driver is the display graphics driver. // They are not used if the cairo graphics driver is used to draw PostScript. // Type cairo_region_t and associated functions require cairo ≥ 1.10 Fl_Region Fl_Cairo_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) { cairo_rectangle_int_t rect = {x, y, w, h}; return cairo_region_create_rectangle(&rect); // 1.10 } void Fl_Cairo_Graphics_Driver::add_rectangle_to_region(Fl_Region r_, int X, int Y, int W, int H) { cairo_rectangle_int_t rect = {X, Y, W, H}; cairo_region_union_rectangle((cairo_region_t*)r_, &rect); // 1.10 } void Fl_Cairo_Graphics_Driver::XDestroyRegion(Fl_Region r_) { cairo_region_destroy((cairo_region_t*)r_); // 1.10 } void Fl_Cairo_Graphics_Driver::restore_clip() { if (cairo_) { cairo_reset_clip(cairo_); // apply what's in rstack cairo_region_t *r = (cairo_region_t*)rstack[rstackptr]; if (r) { if (!clip_) { clip_ = new Clip(); clip_->prev = NULL; } int count = cairo_region_num_rectangles(r); // 1.10 cairo_rectangle_int_t rect; for (int i = 0; i < count; i++) { cairo_region_get_rectangle(r, i, &rect); // 1.10 cairo_rectangle(cairo_, rect.x - 0.5, rect.y - 0.5, rect.width, rect.height); } // put in clip_ the bounding rect of region r cairo_region_get_extents(r, &rect); // 1.10 clip_->x = rect.x; clip_->y = rect.y; clip_->w = rect.width; clip_->h = rect.height; cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_clip(cairo_); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_DEFAULT ); } else if (clip_) { clip_->w = -1; } } } char Fl_Cairo_Graphics_Driver::can_do_alpha_blending() { return 1; } float Fl_Cairo_Graphics_Driver::override_scale() { float s = scale(); if (s != 1.f && Fl_Display_Device::display_device()->is_current()) { cairo_scale(cairo_, 1./s, 1./s); Fl_Graphics_Driver::scale(1); } return s; } void Fl_Cairo_Graphics_Driver::restore_scale(float s) { if (s != 1.f && Fl_Display_Device::display_device()->is_current()) { cairo_scale(cairo_, s, s); Fl_Graphics_Driver::scale(s); } } void Fl_Cairo_Graphics_Driver::antialias(int state) { cairo_set_antialias(cairo_, state ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE); } int Fl_Cairo_Graphics_Driver::antialias() { return (cairo_get_antialias(cairo_) != CAIRO_ANTIALIAS_NONE); } void Fl_Cairo_Graphics_Driver::focus_rect(int x, int y, int w, int h) { cairo_save(cairo_); cairo_set_line_width(cairo_, 1); cairo_set_line_cap(cairo_, CAIRO_LINE_CAP_BUTT); cairo_set_line_join(cairo_, CAIRO_LINE_JOIN_MITER); static double dots[2] = {1., 1.}; cairo_set_dash(cairo_, dots, 2, 1); cairo_set_antialias(cairo_, CAIRO_ANTIALIAS_NONE); cairo_rectangle(cairo_, x, y, w-1, h-1); cairo_stroke(cairo_); cairo_restore(cairo_); surface_needs_commit(); } cairo_pattern_t *Fl_Cairo_Graphics_Driver::calc_cairo_mask(const Fl_RGB_Image *rgb) { int i, j, d = rgb->d(), w = rgb->data_w(), h = rgb->data_h(), ld = rgb->ld(); int bytesperrow = cairo_format_stride_for_width(CAIRO_FORMAT_A1, w); // 1.6 if (!ld) ld = d * w; unsigned u; uchar byte, onebit; // build a CAIRO_FORMAT_A1 surface covering the non-black part of the image uchar* bits = new uchar[h*bytesperrow]; // to store the surface data for (i = 0; i < h; i++) { const uchar* alpha = (const uchar*)*rgb->data() + i * ld; uchar *p = (uchar*)bits + i * bytesperrow; byte = 0; onebit = 1; for (j = 0; j < w; j++) { u = *alpha; u += *(alpha+1); u += *(alpha+2); if (u > 0) { // if the pixel is not black byte |= onebit; // turn on the corresponding bit of the bitmap } onebit = onebit << 1; // move the single set bit one position to the left if (onebit == 0 || j == w-1) { onebit = 1; *p++ = byte; // store in bitmap one pack of bits byte = 0; } alpha += d; // point to next rgb pixel } } cairo_surface_t *mask_surf = cairo_image_surface_create_for_data(bits, CAIRO_FORMAT_A1, w, h, bytesperrow); cairo_pattern_t *mask_pattern = cairo_pattern_create_for_surface(mask_surf); cairo_surface_destroy(mask_surf); return mask_pattern; } #endif // USE_PANGO fltk-1.4.3/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H0000644000175000017500000001763215004135251023042 0ustar albrechtalbrecht// // Support for Cairo graphics for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* \file Declaration of class Fl_Cairo_Graphics_Driver. */ #ifndef FL_CAIRO_GRAPHICS_DRIVER_H # define FL_CAIRO_GRAPHICS_DRIVER_H #include #include typedef struct _PangoLayout PangoLayout; typedef struct _PangoContext PangoContext; typedef struct _PangoFontDescription PangoFontDescription; class Fl_Cairo_Font_Descriptor : public Fl_Font_Descriptor { public: Fl_Cairo_Font_Descriptor(const char* fontname, Fl_Fontsize size, PangoContext *context); FL_EXPORT ~Fl_Cairo_Font_Descriptor() FL_OVERRIDE; PangoFontDescription *fontref; int **width; // array of arrays of character widths int line_height; }; class FL_EXPORT Fl_Cairo_Graphics_Driver : public Fl_Graphics_Driver { private: bool *needs_commit_tag_; // NULL or points to whether cairo surface was drawn to cairo_t *dummy_cairo_; // used to measure text width before showing a window int linestyle_; int do_width_unscaled_(const char* str, int n); protected: cairo_t *cairo_; PangoContext *pango_context_; PangoLayout *pango_layout_; static Fl_Font font_count_; public: Fl_Cairo_Graphics_Driver(); ~Fl_Cairo_Graphics_Driver() FL_OVERRIDE; class Clip { public: int x, y, w, h; Clip *prev; }; Clip * clip_; int gap_; cairo_t *cr() { return cairo_; } PangoLayout *pango_layout() {return pango_layout_;} void set_cairo(cairo_t *c, float f = 0); static cairo_pattern_t *calc_cairo_mask(const Fl_RGB_Image *rgb); static const char *clean_utf8(const char* str, int &n); void check_status(void); unsigned char cr_,cg_,cb_; char linedash_[256];//should be enough void concat(); // transform ror scalable dradings... void reconcat(); //invert void recover(); //recovers the state after grestore (such as line styles...) void reset(); float scale_x; float scale_y; int wld_scale; float angle; int left_margin; int top_margin; static const cairo_format_t cairo_format; void surface_needs_commit() { if (needs_commit_tag_) *needs_commit_tag_ = true; } void needs_commit_tag(bool *tag) { needs_commit_tag_ = tag; } // implementation of drawing methods void color(Fl_Color c) FL_OVERRIDE; void color(uchar r, uchar g, uchar b) FL_OVERRIDE; Fl_Color color() FL_OVERRIDE; void push_clip(int x, int y, int w, int h) FL_OVERRIDE; void push_no_clip() FL_OVERRIDE; void pop_clip() FL_OVERRIDE; void line_style(int style, int width=0, char* dashes=0) FL_OVERRIDE; void rect(int x, int y, int w, int h) FL_OVERRIDE; void rectf(int x, int y, int w, int h) FL_OVERRIDE; void xyline(int x, int y, int x1) FL_OVERRIDE; void xyline(int x, int y, int x1, int y2) FL_OVERRIDE; void xyline(int x, int y, int x1, int y2, int x3) FL_OVERRIDE; void yxline(int x, int y, int y1) FL_OVERRIDE; void yxline(int x, int y, int y1, int x2) FL_OVERRIDE; void yxline(int x, int y, int y1, int x2, int y3) FL_OVERRIDE; void line(int x1, int y1, int x2, int y2) FL_OVERRIDE; void line(int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void point(int x, int y) FL_OVERRIDE; void overlay_rect(int x, int y, int w , int h) FL_OVERRIDE; int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) FL_OVERRIDE; void restore_clip() FL_OVERRIDE; int not_clipped(int x, int y, int w, int h) FL_OVERRIDE; void begin_line() FL_OVERRIDE; void begin_loop() FL_OVERRIDE; void begin_polygon() FL_OVERRIDE; void vertex(double x, double y) FL_OVERRIDE; void curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3) FL_OVERRIDE; void circle(double x, double y, double r) FL_OVERRIDE; void arc(double x, double y, double r, double start, double a) FL_OVERRIDE; void arc(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void pie(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void end_points() FL_OVERRIDE; void end_line() FL_OVERRIDE; void end_loop() FL_OVERRIDE; void end_polygon() FL_OVERRIDE; void begin_complex_polygon() FL_OVERRIDE { begin_polygon(); } void gap() FL_OVERRIDE { gap_ = 1; } void end_complex_polygon() FL_OVERRIDE { end_polygon(); } void transformed_vertex(double x, double y) FL_OVERRIDE; void draw_image_mono(const uchar* d, int x,int y,int w,int h, int delta=1, int ld=0) FL_OVERRIDE; void draw_image(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=3) FL_OVERRIDE; void draw_image_mono(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=1) FL_OVERRIDE; void ps_origin(int x, int y); void ps_translate(int, int); void ps_untranslate(); void draw_cached_pattern_(Fl_Image *img, cairo_pattern_t *pat, int X, int Y, int W, int H, int cx, int cy, int cache_w, int cache_h); void draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) FL_OVERRIDE; void draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void cache(Fl_RGB_Image *rgb) FL_OVERRIDE; void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) FL_OVERRIDE; void draw_fixed(Fl_Bitmap *bm,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; static cairo_pattern_t *bitmap_to_pattern(Fl_Bitmap *bm, bool complement, cairo_surface_t **p_surface); void cache(Fl_Bitmap *img) FL_OVERRIDE; void delete_bitmask(fl_uintptr_t bm) FL_OVERRIDE; void cache(Fl_Pixmap *pxm) FL_OVERRIDE; void draw_fixed(Fl_Pixmap *rgb,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void uncache_pixmap(fl_uintptr_t p) FL_OVERRIDE; void font(Fl_Font fnum, Fl_Fontsize s) FL_OVERRIDE; Fl_Font font() FL_OVERRIDE { return Fl_Graphics_Driver::font(); } void draw(const char* s, int nBytes, int x, int y) FL_OVERRIDE { draw(s, nBytes, float(x), float(y)); } void draw(const char* s, int nBytes, float x, float y) FL_OVERRIDE; void draw(int angle, const char *str, int n, int x, int y) FL_OVERRIDE; void rtl_draw(const char* str, int n, int x, int y) FL_OVERRIDE; int height() FL_OVERRIDE; int descent() FL_OVERRIDE; double width(const char *str, int n) FL_OVERRIDE; double width(unsigned c) FL_OVERRIDE; void text_extents(const char* txt, int n, int& dx, int& dy, int& w, int& h) FL_OVERRIDE; PangoFontDescription* pango_font_description() FL_OVERRIDE { return ((Fl_Cairo_Font_Descriptor*)font_descriptor())->fontref; } static void init_built_in_fonts(); Fl_Font set_fonts(const char* pattern_name) FL_OVERRIDE; const char *font_name(int num) FL_OVERRIDE; void font_name(int num, const char *name) FL_OVERRIDE; const char* get_font_name(Fl_Font fnum, int* ap) FL_OVERRIDE; int get_font_sizes(Fl_Font fnum, int*& sizep) FL_OVERRIDE; Fl_Region XRectangleRegion(int x, int y, int w, int h) FL_OVERRIDE; void XDestroyRegion(Fl_Region r) FL_OVERRIDE; void add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) FL_OVERRIDE; char can_do_alpha_blending() FL_OVERRIDE; float override_scale() FL_OVERRIDE; void restore_scale(float) FL_OVERRIDE; void antialias(int state) FL_OVERRIDE; int antialias() FL_OVERRIDE; void focus_rect(int x, int y, int w, int h) FL_OVERRIDE; }; #endif // FL_CAIRO_GRAPHICS_DRIVER_H fltk-1.4.3/src/drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.H0000644000175000017500000000214115004135251023460 0ustar albrechtalbrecht// // Support for using Cairo to draw into X11 windows for the Fast Light Tool Kit (FLTK). // // Copyright 2022-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* \file Declaration of class Fl_X11_Cairo_Graphics_Driver. */ #ifndef FL_DISPLAY_CAIRO_GRAPHICS_DRIVER_H # define FL_DISPLAY_CAIRO_GRAPHICS_DRIVER_H #include "Fl_Cairo_Graphics_Driver.H" class Fl_X11_Cairo_Graphics_Driver : public Fl_Cairo_Graphics_Driver { private: static void *gc_; public: void scale(float f) FL_OVERRIDE; float scale() {return Fl_Graphics_Driver::scale();} void gc(void *value) FL_OVERRIDE; void* gc() FL_OVERRIDE; void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) FL_OVERRIDE; }; #endif // FL_DISPLAY_CAIRO_GRAPHICS_DRIVER_H fltk-1.4.3/src/drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.cxx0000644000175000017500000000335515004135251024103 0ustar albrechtalbrecht// // Support for using Cairo to draw into X11 windows for the Fast Light Tool Kit (FLTK). // // Copyright 2022-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* \file Implementation of class Fl_X11_Cairo_Graphics_Driver. */ #include "Fl_X11_Cairo_Graphics_Driver.H" #include #include #include #include void *Fl_X11_Cairo_Graphics_Driver::gc_ = NULL; GC fl_gc; ulong fl_xpixel(uchar r,uchar g,uchar b) { return 0; } ulong fl_xpixel(Fl_Color i) { return 0; } void Fl_X11_Cairo_Graphics_Driver::scale(float f) { Fl_Graphics_Driver::scale(f); if (cairo_) { cairo_restore(cairo_); cairo_save(cairo_); cairo_scale(cairo_, f, f); cairo_translate(cairo_, 0.5, 0.5); } } void Fl_X11_Cairo_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) { XCopyArea(fl_display, pixmap, fl_window, (GC)Fl_Graphics_Driver::default_driver().gc(), int(srcx*scale()), int(srcy*scale()), int(w*scale()), int(h*scale()), int(x*scale()), int(y*scale())); } void Fl_X11_Cairo_Graphics_Driver::gc(void *value) { gc_ = value; fl_gc = (GC)gc_; } void *Fl_X11_Cairo_Graphics_Driver::gc() { return gc_; } extern FL_EXPORT cairo_t* fl_cairo_gc() { return ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->cr(); } fltk-1.4.3/src/drivers/PostScript/0000755000175000017500000000000015004135251017164 5ustar albrechtalbrechtfltk-1.4.3/src/drivers/PostScript/Fl_PostScript_image.cxx0000644000175000017500000005372015004135251023614 0ustar albrechtalbrecht// // Postscript image drawing implementation for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if !defined(FL_DOXYGEN) && !defined(FL_NO_PRINT_SUPPORT) #include #include "Fl_PostScript_Graphics_Driver.H" #include #include #include #include // abs(int) #include // memcpy() #if USE_PANGO # include #else # include // fprintf() #endif struct callback_data { const uchar *data; int D, LD; }; static void draw_image_cb(void *data, int x, int y, int w, uchar *buf) { struct callback_data *cb_data; const uchar *curdata; cb_data = (struct callback_data*)data; int last = x+w; const size_t aD = abs(cb_data->D); curdata = cb_data->data + x*cb_data->D + y*cb_data->LD; for (; xD; } } void Fl_PostScript_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) { if (abs(D)<3){ //mono draw_image_mono(data, ix, iy, iw, ih, D, LD); return; } struct callback_data cb_data; if (!LD) LD = iw*abs(D); if (D<0) data += iw*abs(D); cb_data.data = data; cb_data.D = D; cb_data.LD = LD; draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, abs(D)); } #if USE_PANGO static void destroy_BGRA(void *data) { delete[] (uchar*)data; } void Fl_PostScript_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) { Fl_RGB_Image *rgb = new Fl_RGB_Image(pxm); draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy); delete rgb; } void Fl_PostScript_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) { draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy); } void Fl_PostScript_Graphics_Driver::draw_bitmap(Fl_Bitmap *bitmap,int XP, int YP, int WP, int HP, int cx, int cy) { draw_rgb_bitmap_(bitmap, XP, YP, WP, HP, cx, cy); } void Fl_PostScript_Graphics_Driver::draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy) { cairo_surface_t *surf; cairo_format_t format = (img->d() >= 1 ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_A1); int stride = cairo_format_stride_for_width(format, img->data_w()); uchar *BGRA = new uchar[stride * img->data_h()]; memset(BGRA, 0, stride * img->data_h()); if (img->d() >= 1) { // process Fl_RGB_Image of all depths Fl_RGB_Image *rgb = (Fl_RGB_Image*)img; int lrgb = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d(); uchar A = 0xff, R,G,B, *q; const uchar *r; float f = 1; if (rgb->d() >= 3) { // color images for (int j = 0; j < rgb->data_h(); j++) { r = rgb->array + j * lrgb; q = BGRA + j * stride; for (int i = 0; i < rgb->data_w(); i++) { R = *r; G = *(r+1); B = *(r+2); if (rgb->d() == 4) { A = *(r+3); f = float(A)/0xff; } *q = B * f; *(q+1) = G * f; *(q+2) = R * f; *(q+3) = A; r += rgb->d(); q += 4; } } } else if (rgb->d() == 1 || rgb->d() == 2) { // B&W for (int j = 0; j < rgb->data_h(); j++) { r = rgb->array + j * lrgb; q = BGRA + j * stride; for (int i = 0; i < rgb->data_w(); i++) { G = *r; if (rgb->d() == 2) { A = *(r+1); f = float(A)/0xff; } *(q) = G * f; *(q+1) = G * f; *(q+2) = G * f; *(q+3) = A; r += rgb->d(); q += 4; } } } } else { Fl_Bitmap *bm = (Fl_Bitmap*)img; uchar *r, p; unsigned *q; for (int j = 0; j < bm->data_h(); j++) { r = (uchar*)bm->array + j * ((bm->data_w() + 7)/8); q = (unsigned*)(BGRA + j * stride); unsigned k = 0, mask32 = 1; p = *r; for (int i = 0; i < bm->data_w(); i++) { if (p&1) (*q) |= mask32; k++; if (k % 8 != 0) p >>= 1; else p = *(++r); if (k % 32 != 0) mask32 <<= 1; else {q++; mask32 = 1;} } } } surf = cairo_image_surface_create_for_data(BGRA, format, img->data_w(), img->data_h(), stride); if (cairo_surface_status(surf) == CAIRO_STATUS_SUCCESS) { static cairo_user_data_key_t key = {}; (void)cairo_surface_set_user_data(surf, &key, BGRA, destroy_BGRA); cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf); cairo_save(cairo_); cairo_rectangle(cairo_, XP-0.5, YP-0.5, WP+1, HP+1); cairo_clip(cairo_); if (img->d() >= 1) cairo_set_source(cairo_, pat); cairo_matrix_t matrix; cairo_matrix_init_scale(&matrix, double(img->data_w())/(img->w()+1), double(img->data_h())/(img->h()+1)); cairo_matrix_translate(&matrix, -XP+0.5+cx, -YP+0.5+cy); cairo_pattern_set_matrix(pat, &matrix); cairo_mask(cairo_, pat); cairo_pattern_destroy(pat); cairo_surface_destroy(surf); cairo_restore(cairo_); check_status(); } } #else // ! USE_PANGO // // Implementation of the /ASCII85Encode PostScript filter // as described in "PostScript LANGUAGE REFERENCE third edition" p. 131 // struct struct85 { uchar bytes4[4]; // holds up to 4 input bytes int l4; // # of unencoded input bytes int blocks; // counter to insert newlines after 80 output characters uchar chars5[5]; // holds 5 output characters }; void *Fl_PostScript_Graphics_Driver::prepare85() // prepare to produce ASCII85-encoded output { struct85 *big = new struct85; big->l4 = 0; big->blocks = 0; return big; } // ASCII85-encodes 4 input bytes from bytes4 into chars5 array // returns # of output chars static int convert85(const uchar *bytes4, uchar *chars5) { if (bytes4[0] == 0 && bytes4[1] == 0 && bytes4[2] == 0 && bytes4[3] == 0) { chars5[0] = 'z'; return 1; } unsigned val = bytes4[0]*(256*256*256) + bytes4[1]*(256*256) + bytes4[2]*256 + bytes4[3]; chars5[0] = val / 52200625 + 33; // 52200625 = 85 to the 4th val = val % 52200625; chars5[1] = val / 614125 + 33; // 614125 = 85 cube val = val % 614125; chars5[2] = val / 7225 + 33; // 7225 = 85 squared val = val % 7225; chars5[3] = val / 85 + 33; chars5[4] = val % 85 + 33; return 5; } void Fl_PostScript_Graphics_Driver::write85(void *data, const uchar *p, int len) // sends len input bytes for ASCII85 encoding { struct85 *big = (struct85 *)data; const uchar *last = p + len; while (p < last) { int c = 4 - big->l4; if (last-p < c) c = int(last-p); memcpy(big->bytes4 + big->l4, p, c); p += c; big->l4 += c; if (big->l4 == 4) { c = convert85(big->bytes4, big->chars5); fwrite(big->chars5, c, 1, output); big->l4 = 0; if (++big->blocks >= 16) { fputc('\n', output); big->blocks = 0; } } } } void Fl_PostScript_Graphics_Driver::close85(void *data) // stops ASCII85-encoding after processing remaining unencoded input bytes, if any { struct85 *big = (struct85 *)data; int l; if (big->l4) { // # of remaining unencoded input bytes l = big->l4; while (l < 4) big->bytes4[l++] = 0; // complete them with 0s l = convert85(big->bytes4, big->chars5); // encode them if (l == 1) memset(big->chars5, '!', 5); fwrite(big->chars5, big->l4 + 1, 1, output); } fputs("~>", output); // write EOD mark delete big; } // // End of implementation of the /ASCII85Encode PostScript filter // // // Implementation of the /RunLengthEncode + /ASCII85Encode PostScript filter // as described in "PostScript LANGUAGE REFERENCE third edition" p. 142 // struct struct_rle85 { struct85 *data85; // aux data for ASCII85 encoding uchar buffer[128]; // holds non-run data int count; // current buffer length int run_length; // current length of run }; void *Fl_PostScript_Graphics_Driver::prepare_rle85() // prepare to produce RLE+ASCII85-encoded output { struct_rle85 *rle = new struct_rle85; rle->count = 0; rle->run_length = 0; rle->data85 = (struct85*)prepare85(); return rle; } void Fl_PostScript_Graphics_Driver::write_rle85(uchar b, void *data) // sends one input byte to RLE+ASCII85 encoding { struct_rle85 *rle = (struct_rle85 *)data; uchar c; if (rle->run_length > 0) { // if within a run if (b == rle->buffer[0] && rle->run_length < 128) { // the run can be extended rle->run_length++; return; } else { // output the run c = (uchar)(257 - rle->run_length); write85(rle->data85, &c, 1); // the run-length info write85(rle->data85, rle->buffer, 1); // the byte of the run rle->run_length = 0; } } if (rle->count >= 2 && b == rle->buffer[rle->count-1] && b == rle->buffer[rle->count-2]) { // about to begin a run if (rle->count > 2) { // there is non-run data before the run in the buffer c = (uchar)(rle->count-2 - 1); write85(rle->data85, &c, 1); // length of non-run data write85(rle->data85, rle->buffer, rle->count-2); // non-run data } rle->run_length = 3; rle->buffer[0] = b; rle->count = 0; return; } if (rle->count >= 128) { // the non-run buffer is full, output it c = (uchar)(rle->count - 1); write85(rle->data85, &c, 1); // length of non-run data write85(rle->data85, rle->buffer, rle->count); // non-run data rle->count = 0; } rle->buffer[rle->count++] = b; // add byte to end of non-run buffer } void Fl_PostScript_Graphics_Driver::close_rle85(void *data) // stop doing RLE+ASCII85 encoding { struct_rle85 *rle = (struct_rle85 *)data; uchar c; if (rle->run_length > 0) { // if within a run, output it c = (uchar)(257 - rle->run_length); write85(rle->data85, &c, 1); write85(rle->data85, rle->buffer, 1); } else if (rle->count) { // output the non-run buffer, if not empty c = (uchar)(rle->count - 1); write85(rle->data85, &c, 1); write85(rle->data85, rle->buffer, rle->count); } c = (uchar)128; write85(rle->data85, &c, 1); // output EOD mark close85(rle->data85); // close ASCII85 encoding process delete rle; } // // End of implementation of the /RunLengthEncode + /ASCII85Encode PostScript filter // int Fl_PostScript_Graphics_Driver::alpha_mask(const uchar * data, int w, int h, int D, int LD){ mask = 0; if ((D/2)*2 != D){ //no mask info return 0; } int xx; int i,j, k, l; LD += w*D; int V255=0; int V0 =0; int V_=0; for (j=0;j127){ mask[jj*xx+ii/8] |= 1 << (ii % 8); //set mask bit error = val-255; }else error = val; ////// error spreading ///// if (error >0){ next[ii] += o1 = (error * 3 + 8)/16; current[ii+2] += o2 = (error * 7 + 8)/16; next[ii+2] = o3 =(error + 8)/16; // *1 - ok replacing (cleaning) } else { next[ii] += o1 = (error * 3 - 8)/16; current[ii+2] += o2 = (error * 7 - 8)/16; next[ii+2] = o3 = (error - 8)/16; } next[1+ii] += error - o1 - o2 - o3; } } l++; ////// backward jj = j*4+l; swap = next; next = current; current = swap; *(next+1) = 0; // must clean the first cell, next are overridden by *1 for (i = w-1; i >= 0; i--){ for (k=3; k>=0; k--){ // generating 4 x-pixels for 1 RGB short error, o1, o2, o3; int ii = i*4+k; // mask cell index short val = data[j*LD+D*i+D-1] + current[1+ii]; if (val>127){ mask[jj*xx+ii/8] |= 1 << (ii % 8); //set mask bit error = val-255; } else error = val; ////// error spreading ///// if (error >0){ next[ii+2] += o1 = (error * 3 + 8)/16; current[ii] += o2 = (error * 7 + 8)/16; next[ii] = o3 =(error + 8)/16; // *1 - ok replacing (cleaning) } else { next[ii+2] += o1 = (error * 3 - 8)/16; current[ii] += o2 = (error * 7 - 8)/16; next[ii] = o3 = (error - 8)/16; } next[1+ii] += error - o1 - o2 - o3; } } l++; } } delete[] errors1; delete[] errors2; return 0; } // bitwise inversion of all 4-bit quantities static const unsigned char swapped[16] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}; // bitwise inversion of a byte static inline uchar swap_byte(const uchar b) { return (swapped[b & 0xF] << 4) | swapped[b >> 4]; } void Fl_PostScript_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D) { double x = ix, y = iy, w = iw, h = ih; int level2_mask = 0; fprintf(output,"save\n"); int i,j,k; const char * interpol; if (lang_level_ > 1) { if (interpolate_) interpol="true"; else interpol="false"; if (mask && lang_level_ > 2) { fprintf(output, "%g %g %g %g %i %i %i %i %s CIM\n", x , y+h , w , -h , iw , ih, mx, my, interpol); } else if (mask && lang_level_ == 2) { level2_mask = 1; // use method for drawing masked color image with PostScript level 2 fprintf(output, " %g %g %g %g %d %d pixmap_plot\n", x, y, w, h, iw, ih); } else { fprintf(output, "%g %g %g %g %i %i %s CII\n", x , y+h , w , -h , iw , ih, interpol); } } else { fprintf(output , "%g %g %g %g %i %i CI", x , y+h , w , -h , iw , ih); } int LD=iw*abs(D); uchar *rgbdata=new uchar[LD]; uchar *curmask=mask; void *big = prepare_rle85(); if (level2_mask) { for (j = ih - 1; j >= 0; j--) { // output full image data call(data, 0, j, iw, rgbdata); uchar *curdata = rgbdata; for (i=0 ; i= 0; j--) { // output mask data curmask = mask + j * (my/ih) * ((mx+7)/8); for (k=0; k < my/ih; k++) { for (i=0; i < ((mx+7)/8); i++) { write_rle85(swap_byte(*curmask), big); curmask++; } } } } else { for (j=0; j 2) { // InterleaveType 2 mask data for (k=0; k3) { //can do mixing using bg_* colors) unsigned int a2 = curdata[3]; //must be int unsigned int a = 255-a2; r = (a2 * r + bg_r * a)/255; g = (a2 * g + bg_g * a)/255; b = (a2 * b + bg_b * a)/255; } write_rle85(r, big); write_rle85(g, big); write_rle85(b, big); curdata +=D; } } } close_rle85(big); fprintf(output,"\nrestore\n"); delete[] rgbdata; } void Fl_PostScript_Graphics_Driver::draw_image_mono(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) { double x = ix, y = iy, w = iw, h = ih; fprintf(output,"save\n"); int i,j, k; const char * interpol; if (lang_level_>1){ if (interpolate_) interpol="true"; else interpol="false"; if (mask && lang_level_>2) fprintf(output, "%g %g %g %g %i %i %i %i %s GIM\n", x , y+h , w , -h , iw , ih, mx, my, interpol); else fprintf(output, "%g %g %g %g %i %i %s GII\n", x , y+h , w , -h , iw , ih, interpol); }else fprintf(output , "%g %g %g %g %i %i GI", x , y+h , w , -h , iw , ih); if (!LD) LD = iw*abs(D); int bg = (bg_r + bg_g + bg_b)/3; uchar *curmask=mask; void *big = prepare_rle85(); for (j=0; j1) { //can do mixing unsigned int a2 = curdata[1]; //must be int unsigned int a = 255-a2; r = (a2 * r + bg * a)/255; } write_rle85(r, big); curdata +=D; } } close_rle85(big); fprintf(output,"restore\n"); } void Fl_PostScript_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D) { double x = ix, y = iy, w = iw, h = ih; fprintf(output,"save\n"); int i,j,k; const char * interpol; if (lang_level_>1){ if (interpolate_) interpol="true"; else interpol="false"; if (mask && lang_level_>2) fprintf(output, "%g %g %g %g %i %i %i %i %s GIM\n", x , y+h , w , -h , iw , ih, mx, my, interpol); else fprintf(output, "%g %g %g %g %i %i %s GII\n", x , y+h , w , -h , iw , ih, interpol); } else fprintf(output , "%g %g %g %g %i %i GI", x , y+h , w , -h , iw , ih); int LD=iw*D; uchar *rgbdata=new uchar[LD]; uchar *curmask=mask; void *big = prepare_rle85(); for (j=0; j2){ // InterleaveType 2 mask data for (k=0; kdata(); int w,h; if (!fl_measure_pixmap(di, w, h)) return; mask=(uchar*)1;// will instruct fl_draw_pixmap() to compute the image's mask mx = w; my = h; fl_draw_pixmap(di, 0, 0, FL_BLACK); // assigns mask to an array delete[] mask; mask=0; clocale_printf("GR GR\n"); pop_clip(); // matches push_no_clip in scale_for_image_ } void Fl_PostScript_Graphics_Driver::draw_rgb(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) { if (scale_for_image_(rgb, XP, YP, WP, HP, cx, cy)) return; const uchar *di = rgb->array; int w = rgb->data_w(); int h = rgb->data_h(); mask = 0; if (lang_level_ <= 2 || !alpha_mask(di, w, h, rgb->d(),rgb->ld()) ) { draw_image(di, 0, 0, w, h, rgb->d(), rgb->ld()); delete[] mask; mask=0; } clocale_printf("GR GR\n"); pop_clip(); // matches push_no_clip in scale_for_image_ } void Fl_PostScript_Graphics_Driver::draw_bitmap(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy) { if (scale_for_image_(bitmap, XP, YP, WP, HP, cx, cy)) return; WP = bitmap->data_w(), HP = bitmap->data_h(); const uchar * di = bitmap->array; int i, j, xx = (WP+7)/8; fprintf(output , "%i %i %i %i %i %i MI\n", 0, HP, WP, -HP, WP, HP); void *rle85 = prepare_rle85(); for (j=0; jw())/img->data_w(), float(img->h())/img->data_h()); return 0; } #endif // USE_PANGO #endif // !defined(FL_DOXYGEN) && !defined(FL_NO_PRINT_SUPPORT) fltk-1.4.3/src/drivers/PostScript/Fl_PostScript.cxx0000644000175000017500000017555315004135251022463 0ustar albrechtalbrecht// // Classes Fl_PostScript_File_Device and Fl_PostScript_Graphics_Driver for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if !defined(FL_NO_PRINT_SUPPORT) #include #include #include #include #include "Fl_PostScript_Graphics_Driver.H" #include #include #include #include #include "../../Fl_System_Driver.H" #include #include #include #include #include #include #include #include #include #if USE_PANGO #include // for M_PI #include #include #include #include # if ! PANGO_VERSION_CHECK(1,10,0) # error "Requires Pango 1.10 or higher" # endif #endif const char *Fl_PostScript_File_Device::file_chooser_title = "Select a .ps file"; Fl_PostScript_File_Device::Fl_PostScript_File_Device(void) { Fl_Surface_Device::driver( new Fl_PostScript_Graphics_Driver() ); } FILE *Fl_PostScript_File_Device::file() { return driver()->file(); } int Fl_PostScript_File_Device::begin_job (int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) { Fl_Native_File_Chooser fnfc; fnfc.title(Fl_PostScript_File_Device::file_chooser_title); fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | Fl_Native_File_Chooser::USE_FILTER_EXT); fnfc.filter("PostScript\t*.ps\n"); // Show native chooser if ( fnfc.show() ) return 1; Fl_PostScript_Graphics_Driver *ps = driver(); ps->output = fl_fopen(fnfc.filename(), "w"); if(ps->output == NULL) return 2; ps->ps_filename_ = fl_strdup(fnfc.filename()); ps->start_postscript(pagecount, format, layout); return 0; } extern "C" { static int dont_close(FILE *f) { return 0; } } int Fl_PostScript_File_Device::begin_job (FILE *ps_output, int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) { Fl_PostScript_Graphics_Driver *ps = driver(); ps->output = ps_output; ps->ps_filename_ = NULL; ps->start_postscript(pagecount, format, layout); ps->close_command(dont_close); // so that end_job() doesn't close the file return 0; } int Fl_PostScript_File_Device::begin_job(int pagecount, int* from, int* to, char **) { return 1; } Fl_PostScript_File_Device::~Fl_PostScript_File_Device() { Fl_PostScript_Graphics_Driver *ps = driver(); if (ps) delete ps; } void Fl_PostScript_File_Device::set_current() { Fl_Graphics_Driver& driver = Fl_Graphics_Driver::default_driver(); display_font_ = driver.font(); display_size_ = driver.size(); Fl_Paged_Device::set_current(); } void Fl_PostScript_File_Device::end_current() { if (display_font_ >= 0 && display_size_ > 0) { Fl_Graphics_Driver& driver = Fl_Graphics_Driver::default_driver(); driver.font(display_font_, display_size_); } Fl_Paged_Device::end_current(); } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #if ! USE_PANGO static const int dashes_flat[5][7]={ {-1,0,0,0,0,0,0}, {3,1,-1,0,0,0,0}, {1,1,-1,0,0,0,0}, {3,1,1,1,-1,0,0}, {3,1,1,1,1,1,-1} }; //yeah, hack... static const double dashes_cap[5][7]={ {-1,0,0,0,0,0,0}, {2,2,-1,0,0,0,0}, {0.01,1.99,-1,0,0,0,0}, {2,2,0.01,1.99,-1,0,0}, {2,2,0.01,1.99,0.01,1.99,-1} }; #endif /** \brief The constructor. */ Fl_PostScript_Graphics_Driver::Fl_PostScript_Graphics_Driver(void) { close_cmd_ = 0; #if ! USE_PANGO //lang_level_ = 3; lang_level_ = 2; mask = 0; bg_r = bg_g = bg_b = 255; clip_ = NULL; scale_x = scale_y = 1.; #endif ps_filename_ = NULL; nPages = 0; } /** \brief The destructor. */ Fl_PostScript_Graphics_Driver::~Fl_PostScript_Graphics_Driver() { if(ps_filename_) free(ps_filename_); } #if ! USE_PANGO static const char *_fontNames[] = { "Helvetica2B", "Helvetica-Bold2B", "Helvetica-Oblique2B", "Helvetica-BoldOblique2B", "Courier2B", "Courier-Bold2B", "Courier-Oblique2B", "Courier-BoldOblique2B", "Times-Roman2B", "Times-Bold2B", "Times-Italic2B", "Times-BoldItalic2B", "Symbol", "Courier2B", "Courier-Bold2B", "ZapfDingbats" }; #endif void Fl_PostScript_Graphics_Driver::font(int f, int s) { Fl_Graphics_Driver& driver = Fl_Graphics_Driver::default_driver(); driver.font(f,s); // Use display fonts for font measurement Fl_Graphics_Driver::font(f, s); Fl_Font_Descriptor *desc = driver.font_descriptor(); this->font_descriptor(desc); #if ! USE_PANGO if (f < FL_FREE_FONT) { fprintf(output, "/%s SF\n" , _fontNames[f]); float ps_size = driver.scale_font_for_PostScript(desc, s); clocale_printf("%.1f FS\n", ps_size); } #endif } Fl_Font Fl_PostScript_Graphics_Driver::font() { return Fl_Graphics_Driver:: font(); } double Fl_PostScript_Graphics_Driver::width(const char *s, int n) { return Fl_Graphics_Driver::default_driver().width(s, n); } double Fl_PostScript_Graphics_Driver::width(unsigned u) { return Fl_Graphics_Driver::default_driver().width(u); } int Fl_PostScript_Graphics_Driver::height() { return Fl_Graphics_Driver::default_driver().height(); } int Fl_PostScript_Graphics_Driver::descent() { return Fl_Graphics_Driver::default_driver().descent(); } void Fl_PostScript_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) { Fl_Graphics_Driver::default_driver().text_extents(c, n, dx, dy, w, h); } void Fl_PostScript_Graphics_Driver::point(int x, int y){ rectf(x,y,1,1); } int Fl_PostScript_Graphics_Driver::not_clipped(int x, int y, int w, int h) { if (!clip_) return 1; if (clip_->w < 0) return 1; int X = 0, Y = 0, W = 0, H = 0; clip_box(x, y, w, h, X, Y, W, H); if (W) return 1; return 0; } int Fl_PostScript_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) { if (!clip_) { X = x; Y = y; W = w; H = h; return 0; } if (clip_->w < 0) { X = x; Y = y; W = w; H = h; return 1; } int ret = 0; if (x > (X=clip_->x)) {X=x; ret=1;} if (y > (Y=clip_->y)) {Y=y; ret=1;} if ((x+w) < (clip_->x+clip_->w)) { W=x+w-X; ret=1; }else W = clip_->x + clip_->w - X; if(W<0){ W=0; return 1; } if ((y+h) < (clip_->y+clip_->h)) { H=y+h-Y; ret=1; }else H = clip_->y + clip_->h - Y; if(H<0){ W=0; H=0; return 1; } return ret; } #if ! USE_PANGO int Fl_PostScript_Graphics_Driver::clocale_printf(const char *format, ...) { va_list args; va_start(args, format); int retval = Fl::system_driver()->clocale_vprintf(output, format, args); va_end(args); return retval; } // Prolog string static const char * prolog = "/L { /y2 exch def\n" "/x2 exch def\n" "/y1 exch def\n" "/x1 exch def\n" "newpath x1 y1 moveto x2 y2 lineto\n" "stroke}\n" "bind def\n" "/R { /dy exch def\n" "/dx exch def\n" "/y exch def\n" "/x exch def\n" "newpath\n" "x y moveto\n" "dx 0 rlineto\n" "0 dy rlineto\n" "dx neg 0 rlineto\n" "closepath stroke\n" "} bind def\n" "/CL {\n" "/dy exch def\n" "/dx exch def\n" "/y exch def\n" "/x exch def\n" "newpath\n" "x y moveto\n" "dx 0 rlineto\n" "0 dy rlineto\n" "dx neg 0 rlineto\n" "closepath\n" "clip\n" "} bind def\n" "/FR { /dy exch def\n" "/dx exch def\n" "/y exch def\n" "/x exch def\n" "currentlinewidth 0 setlinewidth newpath\n" "x y moveto\n" "dx 0 rlineto\n" "0 dy rlineto\n" "dx neg 0 rlineto\n" "closepath fill setlinewidth\n" "} bind def\n" "/GS { gsave } bind def\n" "/GR { grestore } bind def\n" "/SP { showpage } bind def\n" "/LW { setlinewidth } bind def\n" "/CF /Courier def\n" "/SF { /CF exch def } bind def\n" "/fsize 12 def\n" "/FS { /fsize exch def fsize CF findfont exch scalefont setfont }def \n" "/GL { setgray } bind def\n" "/SRGB { setrgbcolor } bind def\n" "/A85RLE { /ASCII85Decode filter /RunLengthDecode filter } bind def\n" // ASCII85Decode followed by RunLengthDecode filters // color images "/CI { GS /py exch def /px exch def /sy exch def /sx exch def\n" "translate \n" "sx sy scale px py 8 \n" "[ px 0 0 py neg 0 py ]\n" "currentfile A85RLE\n false 3" " colorimage GR\n" "} bind def\n" // gray images "/GI { GS /py exch def /px exch def /sy exch def /sx exch def \n" "translate \n" "sx sy scale px py 8 \n" "[ px 0 0 py neg 0 py ]\n" "currentfile A85RLE\n" "image GR\n" "} bind def\n" // single-color bitmask "/MI { GS /py exch def /px exch def /sy exch def /sx exch def \n" "translate \n" "sx sy scale px py true \n" "[ px 0 0 py neg 0 py ]\n" "currentfile A85RLE\n" "imagemask GR\n" "} bind def\n" // path "/BFP { newpath moveto } def\n" "/BP { newpath } bind def \n" "/PL { lineto } bind def \n" "/PM { moveto } bind def \n" "/MT { moveto } bind def \n" "/LT { lineto } bind def \n" "/EFP { closepath fill } bind def\n" //was:stroke "/ELP { stroke } bind def\n" "/ECP { closepath stroke } bind def\n" // Closed (loop) "/LW { setlinewidth } bind def\n" // ////////////////////////// misc //////////////// "/TR { translate } bind def\n" "/CT { concat } bind def\n" "/RCT { matrix invertmatrix concat} bind def\n" "/SC { scale } bind def\n" //"/GPD { currentpagedevice /PageSize get} def\n" // show at position with desired width // usage: // width (string) x y show_pos_width "/show_pos_width {GS moveto dup dup stringwidth pop exch length 2 div dup 2 le {pop 9999} if " "1 sub exch 3 index exch sub exch " "div 0 2 index 1 -1 scale ashow pop pop GR} bind def\n" // spacing altered to match desired width //"/show_pos_width {GS moveto dup stringwidth pop 3 2 roll exch div -1 matrix scale concat " //"show GR } bind def\n" // horizontally scaled text to match desired width ; static const char * prolog_2 = // prolog relevant only if lang_level >1 // color image dictionaries "/CII {GS /inter exch def /py exch def /px exch def /sy exch def /sx exch def \n" "translate \n" "sx sy scale\n" "/DeviceRGB setcolorspace\n" "/IDD 8 dict def\n" "IDD begin\n" "/ImageType 1 def\n" "/Width px def\n" "/Height py def\n" "/BitsPerComponent 8 def\n" "/Interpolate inter def\n" "/DataSource currentfile A85RLE def\n" "/MultipleDataSources false def\n" "/ImageMatrix [ px 0 0 py neg 0 py ] def\n" "/Decode [ 0 1 0 1 0 1 ] def\n" "end\n" "IDD image GR} bind def\n" // gray image dict "/GII {GS /inter exch def /py exch def /px exch def /sy exch def /sx exch def \n" "translate \n" "sx sy scale\n" "/DeviceGray setcolorspace\n" "/IDD 8 dict def\n" "IDD begin\n" "/ImageType 1 def\n" "/Width px def\n" "/Height py def\n" "/BitsPerComponent 8 def\n" "/Interpolate inter def\n" "/DataSource currentfile A85RLE def\n" "/MultipleDataSources false def\n" "/ImageMatrix [ px 0 0 py neg 0 py ] def\n" "/Decode [ 0 1 ] def\n" "end\n" "IDD image GR} bind def\n" // Create a custom PostScript font derived from PostScript standard text fonts // The encoding of this custom font is as follows: // 0000-00FF coincides with Unicode, that is to ASCII + Latin-1 // 0100-017F coincides with Unicode, that is to Latin Extended-A // 0180-01A6 encodes miscellaneous characters present in PostScript standard text fonts // use ISOLatin1Encoding for all text fonts "/ToISO { dup findfont dup length dict copy begin /Encoding ISOLatin1Encoding def currentdict end definefont pop } def\n" "/Helvetica ToISO /Helvetica-Bold ToISO /Helvetica-Oblique ToISO /Helvetica-BoldOblique ToISO \n" "/Courier ToISO /Courier-Bold ToISO /Courier-Oblique ToISO /Courier-BoldOblique ToISO \n" "/Times-Roman ToISO /Times-Bold ToISO /Times-Italic ToISO /Times-BoldItalic ToISO \n" // define LatinExtA, the encoding of Latin-extended-A + some additional characters // see http://partners.adobe.com/public/developer/en/opentype/glyphlist.txt for their names "/LatinExtA \n" "[ " " /Amacron /amacron /Abreve /abreve /Aogonek /aogonek\n" // begin of Latin Extended-A code page " /Cacute /cacute /Ccircumflex /ccircumflex /Cdotaccent /cdotaccent /Ccaron /ccaron \n" " /Dcaron /dcaron /Dcroat /dcroat\n" " /Emacron /emacron /Ebreve /ebreve /Edotaccent /edotaccent /Eogonek /eogonek /Ecaron /ecaron\n" " /Gcircumflex /gcircumflex /Gbreve /gbreve /Gdotaccent /gdotaccent /Gcommaaccent /gcommaaccent \n" " /Hcircumflex /hcircumflex /Hbar /hbar \n" " /Itilde /itilde /Imacron /imacron /Ibreve /ibreve /Iogonek /iogonek /Idotaccent /dotlessi \n" " /IJ /ij /Jcircumflex /jcircumflex\n" " /Kcommaaccent /kcommaaccent /kgreenlandic \n" " /Lacute /lacute /Lcommaaccent /lcommaaccent /Lcaron /lcaron /Ldotaccent /ldotaccent /Lslash /lslash \n" " /Nacute /nacute /Ncommaaccent /ncommaaccent /Ncaron /ncaron /napostrophe /Eng /eng \n" " /Omacron /omacron /Obreve /obreve /Ohungarumlaut /ohungarumlaut /OE /oe \n" " /Racute /racute /Rcommaaccent /rcommaaccent /Rcaron /rcaron \n" " /Sacute /sacute /Scircumflex /scircumflex /Scedilla /scedilla /Scaron /scaron \n" " /Tcommaaccent /tcommaaccent /Tcaron /tcaron /Tbar /tbar \n" " /Utilde /utilde /Umacron /umacron /Ubreve /ubreve /Uring /uring /Uhungarumlaut /uhungarumlaut /Uogonek /uogonek \n" " /Wcircumflex /wcircumflex /Ycircumflex /ycircumflex /Ydieresis \n" " /Zacute /zacute /Zdotaccent /zdotaccent /Zcaron /zcaron \n" " /longs \n" // end of Latin Extended-A code page " /florin /circumflex /caron /breve /dotaccent /ring \n" // remaining characters from PostScript standard text fonts " /ogonek /tilde /hungarumlaut /endash /emdash \n" " /quoteleft /quoteright /quotesinglbase /quotedblleft /quotedblright \n" " /quotedblbase /dagger /daggerdbl /bullet /ellipsis \n" " /perthousand /guilsinglleft /guilsinglright /fraction /Euro \n" " /trademark /partialdiff /Delta /summation /radical \n" " /infinity /notequal /lessequal /greaterequal /lozenge \n" " /fi /fl /apple \n" " ] def \n" // deal with alternative PostScript names of some characters " /mycharstrings /Helvetica findfont /CharStrings get def\n" " /PSname2 { dup mycharstrings exch known {LatinExtA 3 -1 roll 3 -1 roll put}{pop pop} ifelse } def \n" " 16#20 /Gdot PSname2 16#21 /gdot PSname2 16#30 /Idot PSname2 16#3F /Ldot PSname2 16#40 /ldot PSname2 16#7F /slong PSname2 \n" // proc that gives LatinExtA encoding to a font "/ToLatinExtA { findfont dup length dict copy begin /Encoding LatinExtA def currentdict end definefont pop } def\n" // create Ext-versions of standard fonts that use LatinExtA encoding \n" "/HelveticaExt /Helvetica ToLatinExtA \n" "/Helvetica-BoldExt /Helvetica-Bold ToLatinExtA /Helvetica-ObliqueExt /Helvetica-Oblique ToLatinExtA \n" "/Helvetica-BoldObliqueExt /Helvetica-BoldOblique ToLatinExtA \n" "/CourierExt /Courier ToLatinExtA /Courier-BoldExt /Courier-Bold ToLatinExtA \n" "/Courier-ObliqueExt /Courier-Oblique ToLatinExtA /Courier-BoldObliqueExt /Courier-BoldOblique ToLatinExtA \n" "/Times-RomanExt /Times-Roman ToLatinExtA /Times-BoldExt /Times-Bold ToLatinExtA \n" "/Times-ItalicExt /Times-Italic ToLatinExtA /Times-BoldItalicExt /Times-BoldItalic ToLatinExtA \n" // proc to create a Type 0 font with 2-byte encoding // that merges a text font with ISO encoding + same font with LatinExtA encoding "/To2byte { 6 dict begin /FontType 0 def \n" "/FDepVector 3 1 roll findfont exch findfont 2 array astore def \n" "/FontMatrix [1 0 0 1 0 0] def /FMapType 6 def /Encoding [ 0 1 0 ] def\n" // 100: Hexa count of ISO array; A7: hexa count of LatinExtA array "/SubsVector < 01 0100 00A7 > def\n" "currentdict end definefont pop } def\n" // create Type 0 versions of standard fonts "/Helvetica2B /HelveticaExt /Helvetica To2byte \n" "/Helvetica-Bold2B /Helvetica-BoldExt /Helvetica-Bold To2byte \n" "/Helvetica-Oblique2B /Helvetica-ObliqueExt /Helvetica-Oblique To2byte \n" "/Helvetica-BoldOblique2B /Helvetica-BoldObliqueExt /Helvetica-BoldOblique To2byte \n" "/Courier2B /CourierExt /Courier To2byte \n" "/Courier-Bold2B /Courier-BoldExt /Courier-Bold To2byte \n" "/Courier-Oblique2B /Courier-ObliqueExt /Courier-Oblique To2byte \n" "/Courier-BoldOblique2B /Courier-BoldObliqueExt /Courier-BoldOblique To2byte \n" "/Times-Roman2B /Times-RomanExt /Times-Roman To2byte \n" "/Times-Bold2B /Times-BoldExt /Times-Bold To2byte \n" "/Times-Italic2B /Times-ItalicExt /Times-Italic To2byte \n" "/Times-BoldItalic2B /Times-BoldItalicExt /Times-BoldItalic To2byte \n" ; static const char * prolog_2_pixmap = // prolog relevant only if lang_level == 2 for pixmaps/masked color images "/pixmap_mat {[ pixmap_sx 0 0 pixmap_sy neg 0 pixmap_sy ]} bind def\n" "/pixmap_dict {" "<< /PatternType 1 " "/PaintType 1 " "/TilingType 2 " "/BBox [0 0 pixmap_sx pixmap_sy] " "/XStep pixmap_sx " "/YStep pixmap_sy\n" "/PaintProc " "{ begin " "pixmap_w pixmap_h scale " "pixmap_sx pixmap_sy 8 " "pixmap_mat " "currentfile A85RLE " "false 3 " "colorimage " "end " "} bind " ">>\n" "} bind def\n" "/pixmap_plot {" "GS " "/pixmap_sy exch def /pixmap_sx exch def\n" "/pixmap_h exch def /pixmap_w exch def\n" "translate\n" "pixmap_dict matrix makepattern setpattern\n" "pixmap_w pixmap_h scale\n" "pixmap_sx pixmap_sy\n" "true\n" "pixmap_mat\n" "currentfile A85RLE\n" "imagemask\n" "GR\n" "} bind def\n" ; static const char * prolog_3 = // prolog relevant only if lang_level >2 // masked color images "/CIM {GS /inter exch def /my exch def /mx exch def /py exch def /px exch def /sy exch def /sx exch def \n" "translate \n" "sx sy scale\n" "/DeviceRGB setcolorspace\n" "/IDD 8 dict def\n" "IDD begin\n" "/ImageType 1 def\n" "/Width px def\n" "/Height py def\n" "/BitsPerComponent 8 def\n" "/Interpolate inter def\n" "/DataSource currentfile A85RLE def\n" "/MultipleDataSources false def\n" "/ImageMatrix [ px 0 0 py neg 0 py ] def\n" "/Decode [ 0 1 0 1 0 1 ] def\n" "end\n" "/IMD 8 dict def\n" "IMD begin\n" "/ImageType 1 def\n" "/Width mx def\n" "/Height my def\n" "/BitsPerComponent 1 def\n" // "/Interpolate inter def\n" "/ImageMatrix [ mx 0 0 my neg 0 my ] def\n" "/Decode [ 1 0 ] def\n" "end\n" "<<\n" "/ImageType 3\n" "/InterleaveType 2\n" "/MaskDict IMD\n" "/DataDict IDD\n" ">> image GR\n" "} bind def\n" // masked gray images "/GIM {GS /inter exch def /my exch def /mx exch def /py exch def /px exch def /sy exch def /sx exch def \n" "translate \n" "sx sy scale\n" "/DeviceGray setcolorspace\n" "/IDD 8 dict def\n" "IDD begin\n" "/ImageType 1 def\n" "/Width px def\n" "/Height py def\n" "/BitsPerComponent 8 def\n" "/Interpolate inter def\n" "/DataSource currentfile A85RLE def\n" "/MultipleDataSources false def\n" "/ImageMatrix [ px 0 0 py neg 0 py ] def\n" "/Decode [ 0 1 ] def\n" "end\n" "/IMD 8 dict def\n" "IMD begin\n" "/ImageType 1 def\n" "/Width mx def\n" "/Height my def\n" "/BitsPerComponent 1 def\n" "/ImageMatrix [ mx 0 0 my neg 0 my ] def\n" "/Decode [ 1 0 ] def\n" "end\n" "<<\n" "/ImageType 3\n" "/InterleaveType 2\n" "/MaskDict IMD\n" "/DataDict IDD\n" ">> image GR\n" "} bind def\n" "\n" ; // end prolog int Fl_PostScript_Graphics_Driver::start_postscript (int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) //returns 0 iff OK { int w, h, x; if (format == Fl_Paged_Device::A4) { left_margin = 18; top_margin = 18; } else { left_margin = 12; top_margin = 12; } // combine the format and layout information page_format_ = ((int)format | (int)layout); if (layout & Fl_Paged_Device::LANDSCAPE){ ph_ = Fl_Paged_Device::page_formats[format].width; pw_ = Fl_Paged_Device::page_formats[format].height; } else { pw_ = Fl_Paged_Device::page_formats[format].width; ph_ = Fl_Paged_Device::page_formats[format].height; } fputs("%!PS-Adobe-3.0\n", output); fputs("%%Creator: FLTK\n", output); if (lang_level_>1) fprintf(output, "%%%%LanguageLevel: %i\n" , lang_level_); if ((pages_ = pagecount)) fprintf(output, "%%%%Pages: %i\n", pagecount); else fputs("%%Pages: (atend)\n", output); fprintf(output, "%%%%BeginFeature: *PageSize %s\n", Fl_Paged_Device::page_formats[format].name ); w = Fl_Paged_Device::page_formats[format].width; h = Fl_Paged_Device::page_formats[format].height; if (lang_level_ == 3 && (layout & Fl_Paged_Device::LANDSCAPE) ) { x = w; w = h; h = x; } fprintf(output, "<>setpagedevice\n", w, h ); fputs("%%EndFeature\n", output); fputs("%%EndComments\n%%BeginProlog\n", output); fputs(prolog, output); if (lang_level_ > 1) { fputs(prolog_2, output); } if (lang_level_ == 2) { fputs(prolog_2_pixmap, output); } if (lang_level_ > 2) fputs(prolog_3, output); if (lang_level_ >= 3) { fputs("/CS { clipsave } bind def\n", output); fputs("/CR { cliprestore } bind def\n", output); } else { fputs("/CS { GS } bind def\n", output); fputs("/CR { GR } bind def\n", output); } page_policy_ = 1; fputs("%%EndProlog\n",output); if (lang_level_ >= 2) fprintf(output,"<< /Policies << /Pagesize 1 >> >> setpagedevice\n"); reset(); nPages=0; return 0; } int Fl_PostScript_Graphics_Driver::start_eps (int width, int height) { pw_ = width; ph_ = height; fputs("%!PS-Adobe-3.0 EPSF-3.0\n", output); fputs("%%Creator: (FLTK)\n", output); fprintf(output,"%%%%BoundingBox: 1 1 %d %d\n", width, height); if (ps_filename_) fprintf(output,"%%%%Title: (%s)\n", fl_filename_name(ps_filename_)); time_t lt = time(NULL); fprintf(output,"%%%%CreationDate: %s", ctime(<)+4); lang_level_= 2; fprintf(output, "%%%%LanguageLevel: 2\n"); fputs("%%Pages: 1\n%%EndComments\n", output); fputs("%%BeginProlog\n", output); fputs("%%EndProlog\n",output); fprintf(output, "save\n"); fputs("/FLTK 20 dict def FLTK begin\n" "/x1 0 def /x2 0 def /y1 0 def /y2 0 def /x 0 def /y 0 def /dx 0 def /dy 0 def\n" "/px 0 def /py 0 def /sx 0 def /sy 0 def /inter 0 def\n" "/pixmap_sx 0 def /pixmap_sy 0 def /pixmap_w 0 def /pixmap_h 0 def\n", output); fputs(prolog, output); fputs(prolog_2, output); fputs(prolog_2_pixmap, output); fputs("/CS { GS } bind def\n", output); fputs("/CR { GR } bind def\n", output); page_policy_ = 1; reset(); nPages=0; fprintf(output, "GS\n"); clocale_printf( "%g %g TR\n", (double)0, ph_); fprintf(output, "1 -1 SC\n"); line_style(0); fprintf(output, "GS GS\n"); return 0; } void Fl_PostScript_Graphics_Driver::recover(){ color(cr_,cg_,cb_); line_style(linestyle_,linewidth_,linedash_); font(Fl_Graphics_Driver::font(), Fl_Graphics_Driver::size()); } void Fl_PostScript_Graphics_Driver::reset(){ gap_=1; clip_=0; cr_=cg_=cb_=0; Fl_Graphics_Driver::font(FL_HELVETICA, 12); linewidth_=0; linestyle_=FL_SOLID; strcpy(linedash_,""); Clip *c=clip_; ////just not to have memory leaks for badly writen code (forgotten clip popping) while(c){ clip_=clip_->prev; delete c; c=clip_; } } void Fl_PostScript_Graphics_Driver::page_policy(int p){ page_policy_ = p; if(lang_level_>=2) fprintf(output,"<< /Policies << /Pagesize %i >> >> setpagedevice\n", p); } // //////////////////// paging ////////////////////////////////////////// void Fl_PostScript_Graphics_Driver::page(double pw, double ph, int media) { if (nPages){ fprintf(output, "CR\nGR\nGR\nGR\nSP\nrestore\n"); } ++nPages; fprintf(output, "%%%%Page: %i %i\n" , nPages , nPages); fprintf(output, "%%%%PageBoundingBox: 0 0 %d %d\n", pw > ph ? (int)ph : (int)pw , pw > ph ? (int)pw : (int)ph); if (pw>ph){ fprintf(output, "%%%%PageOrientation: Landscape\n"); }else{ fprintf(output, "%%%%PageOrientation: Portrait\n"); } fprintf(output, "%%%%BeginPageSetup\n"); if((media & Fl_Paged_Device::MEDIA) &&(lang_level_>1)){ int r = media & Fl_Paged_Device::REVERSED; if(r) r = 2; fprintf(output, "<< /PageSize [%i %i] /Orientation %i>> setpagedevice\n", (int)(pw+.5), (int)(ph+.5), r); } fprintf(output, "%%%%EndPageSetup\n"); /* pw_ = pw; ph_ = ph;*/ reset(); fprintf(output, "save\n"); fprintf(output, "GS\n"); clocale_printf( "%g %g TR\n", (double)0 /*lm_*/ , ph_ /* - tm_*/); fprintf(output, "1 -1 SC\n"); line_style(0); fprintf(output, "GS\n"); if (!((media & Fl_Paged_Device::MEDIA) &&(lang_level_>1))){ if (pw > ph) { if(media & Fl_Paged_Device::REVERSED) { fprintf(output, "-90 rotate %i 0 translate\n", int(-pw)); } else { fprintf(output, "90 rotate -%i -%i translate\n", (lang_level_ == 2 ? int(pw - ph) : 0), int(ph)); } } else { if(media & Fl_Paged_Device::REVERSED) fprintf(output, "180 rotate %i %i translate\n", int(-pw), int(-ph)); } } fprintf(output, "GS\nCS\n"); } void Fl_PostScript_Graphics_Driver::page(int format){ /* if(format & Fl_Paged_Device::LANDSCAPE){ ph_=Fl_Paged_Device::page_formats[format & 0xFF].width; pw_=Fl_Paged_Device::page_formats[format & 0xFF].height; }else{ pw_=Fl_Paged_Device::page_formats[format & 0xFF].width; ph_=Fl_Paged_Device::page_formats[format & 0xFF].height; }*/ page(pw_,ph_,format & 0xFF00);//,orientation only; } void Fl_PostScript_Graphics_Driver::rect(int x, int y, int w, int h) { // Commented code does not work, i can't find the bug ;-( // fprintf(output, "GS\n"); // fprintf(output, "%i, %i, %i, %i R\n", x , y , w, h); // fprintf(output, "GR\n"); fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output, "%i %i MT\n", x , y); fprintf(output, "%i %i LT\n", x+w-1 , y); fprintf(output, "%i %i LT\n", x+w-1 , y+h-1); fprintf(output, "%i %i LT\n", x , y+h-1); fprintf(output, "ECP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::rectf(int x, int y, int w, int h) { clocale_printf( "%g %g %i %i FR\n", x-0.5, y-0.5, w, h); } void Fl_PostScript_Graphics_Driver::line(int x1, int y1, int x2, int y2) { fprintf(output, "GS\n"); fprintf(output, "%i %i %i %i L\n", x1 , y1, x2 ,y2); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::line(int x0, int y0, int x1, int y1, int x2, int y2) { fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output, "%i %i MT\n", x0 , y0); fprintf(output, "%i %i LT\n", x1 , y1); fprintf(output, "%i %i LT\n", x2 , y2); fprintf(output, "ELP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3){ fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output, "%i %i MT\n", x , y ); fprintf(output, "%i %i LT\n", x1 , y ); fprintf(output, "%i %i LT\n", x1 , y2); fprintf(output,"%i %i LT\n", x3 , y2); fprintf(output, "ELP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1, int y2){ fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output, "%i %i MT\n", x , y); fprintf(output,"%i %i LT\n", x1 , y); fprintf(output, "%i %i LT\n", x1 , y2 ); fprintf(output, "ELP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::xyline(int x, int y, int x1){ fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output, "%i %i MT\n", x , y); fprintf(output, "%i %i LT\n", x1 , y ); fprintf(output, "ELP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3){ fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output,"%i %i MT\n", x , y); fprintf(output, "%i %i LT\n", x , y1 ); fprintf(output, "%i %i LT\n", x2 , y1 ); fprintf(output , "%i %i LT\n", x2 , y3); fprintf(output, "ELP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1, int x2){ fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output, "%i %i MT\n", x , y); fprintf(output, "%i %i LT\n", x , y1); fprintf(output, "%i %i LT\n", x2 , y1); fprintf(output, "ELP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::yxline(int x, int y, int y1){ fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output, "%i %i MT\n", x , y); fprintf(output, "%i %i LT\n", x , y1); fprintf(output, "ELP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output, "%i %i MT\n", x0 , y0); fprintf(output, "%i %i LT\n", x1 , y1); fprintf(output, "%i %i LT\n", x2 , y2); fprintf(output, "ECP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output, "%i %i MT\n", x0 , y0); fprintf(output, "%i %i LT\n", x1 , y1); fprintf(output, "%i %i LT\n", x2 , y2); fprintf(output, "%i %i LT\n", x3 , y3); fprintf(output, "ECP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output, "%i %i MT\n", x0 , y0); fprintf(output,"%i %i LT\n", x1 , y1); fprintf(output, "%i %i LT\n", x2 , y2); fprintf(output, "EFP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { fprintf(output, "GS\n"); fprintf(output,"BP\n"); fprintf(output, "%i %i MT\n", x0 , y0 ); fprintf(output, "%i %i LT\n", x1 , y1 ); fprintf(output, "%i %i LT\n", x2 , y2 ); fprintf(output, "%i %i LT\n", x3 , y3 ); fprintf(output, "EFP\n"); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::line_style(int style, int width, char* dashes){ //line_styled_=1; linewidth_=width; linestyle_=style; //dashes_= dashes; if(dashes){ if(dashes != linedash_) strcpy(linedash_,dashes); }else linedash_[0]=0; char width0 = 0; if(!width){ width=1; //for screen drawing compatibility width0=1; } fprintf(output, "%i setlinewidth\n", width); if(!style && (!dashes || !(*dashes)) && width0) //system lines style = FL_CAP_SQUARE; int cap = (style &0xf00) >> 8; if(cap) cap--; fprintf(output,"%i setlinecap\n", cap); int join = (style & 0xf000) >> 12; if(join) join--; fprintf(output,"%i setlinejoin\n", join); fprintf(output, "["); if(dashes && *dashes){ while(*dashes){ fprintf(output, "%i ", *dashes); dashes++; } }else{ if(style & 0x200){ // round and square caps, dash length need to be adjusted const double *dt = dashes_cap[style & 0xff]; while (*dt >= 0){ clocale_printf("%g ",width * (*dt)); dt++; } }else{ const int *ds = dashes_flat[style & 0xff]; while (*ds >= 0){ fprintf(output, "%i ",width * (*ds)); ds++; } } } fprintf(output, "] 0 setdash\n"); } void Fl_PostScript_Graphics_Driver::color(Fl_Color c) { Fl::get_color(c, cr_, cg_, cb_); color(cr_, cg_, cb_); } Fl_Color Fl_PostScript_Graphics_Driver::color() { return Fl_Graphics_Driver::color(); } void Fl_PostScript_Graphics_Driver::color(unsigned char r, unsigned char g, unsigned char b) { Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) ); cr_ = r; cg_ = g; cb_ = b; if (r == g && g == b) { double gray = r/255.0; clocale_printf("%g GL\n", gray); } else { double fr, fg, fb; fr = r/255.0; fg = g/255.0; fb = b/255.0; clocale_printf("%g %g %g SRGB\n", fr , fg , fb); } } void Fl_PostScript_Graphics_Driver::draw(int rotation, const char *str, int n, int x, int y) { fprintf(output, "GS %d %d translate %d rotate\n", x, y, -rotation); this->transformed_draw(str, n, 0, 0); fprintf(output, "GR\n"); } // computes the mask for the RGB image img of all pixels with color != bg static uchar *calc_mask(uchar *img, int w, int h, Fl_Color bg) { uchar red, green, blue, r, g, b; uchar bit, byte, *q; Fl::get_color(bg, red, green, blue); int W = (w+7)/8; // width of mask uchar* mask = new uchar[W * h]; q = mask; while (h-- > 0) { // for each row bit = 0x80; // byte with last bit set byte = 0; // next mask byte to compute for (int j = 0; j < w; j++) { // for each column r = *img++; // the pixel color components g = *img++; b = *img++; // if pixel doesn't have bg color, put it in mask if (r != red || g != green || b != blue) byte |= bit; bit = bit>>1; // shift bit one step to the right if (bit == 0) { // single set bit has fallen out *q++ = byte; // enter byte in mask byte = 0; // reset next mask byte to zero bit = 0x80; // and this byte } } if (bit != 0x80) *q++ = byte; // enter last columns' byte in mask } return mask; } // write to PostScript a bitmap image of a UTF8 string void Fl_PostScript_Graphics_Driver::transformed_draw_extra(const char* str, int n, double x, double y, int w, bool rtl) { // scale for bitmask computation is set to 1 when we can't expect to have scalable fonts float scale = Fl_Graphics_Driver::default_driver().scale_bitmap_for_PostScript(); Fl_Fontsize old_size = size(); Fl_Font fontnum = Fl_Graphics_Driver::font(); int w_scaled = (int)(w * (scale + 0.5) + 1); int h = (int)(height() * scale); // create an offscreen image of the string Fl_Color text_color = Fl_Graphics_Driver::color(); Fl_Color bg_color = fl_contrast(FL_WHITE, text_color); Fl_Image_Surface *off = new Fl_Image_Surface(w_scaled, (int)(h+3*scale), 1); Fl_Surface_Device::push_current(off); fl_color(bg_color); // color offscreen background with a shade contrasting with the text color fl_rectf(0, 0, w_scaled, (int)(h+3*scale) ); fl_color(text_color); if (scale < 1.5) { // force seeing this font as new so it's applied to the offscreen graphics context fl_graphics_driver->font_descriptor(NULL); fl_font(fontnum, 0); } fl_font(fontnum, (Fl_Fontsize)(scale * old_size) ); int w2 = (int)fl_width(str, n); if (w2 > w_scaled) w2 = w_scaled; // draw string in offscreen if (rtl) fl_rtl_draw(str, n, w2, (int)(h * 0.8) ); else fl_draw(str, n, 0, (int)(h * 0.8) ); // read (most of) the offscreen image uchar *img = fl_read_image(NULL, 0, 1, w2, h, 0); Fl_Surface_Device::pop_current(); font(fontnum, old_size); delete off; // compute the mask of what is not the background uchar *img_mask = calc_mask(img, w2, h, bg_color); delete[] img; // write the string image to PostScript as a scaled bitmask scale = w2 / float(w); clocale_printf("%g %g %g %g %d %d MI\n", x, y - h*0.77/scale, w2/scale, h/scale, w2, h); uchar *di; int wmask = (w2+7)/8; void *rle85 = prepare_rle85(); for (int j = h - 1; j >= 0; j--){ di = img_mask + j * wmask; for (int i = 0; i < wmask; i++){ write_rle85(*di, rle85); di++; } } close_rle85(rle85); fputc('\n', output); delete[] img_mask; } static int is_in_table(unsigned utf) { unsigned i; static unsigned extra_table_roman[] = { // unicodes/*names*/ of other characters from PostScript standard fonts 0x192/*florin*/, 0x2C6/*circumflex*/, 0x2C7/*caron*/, 0x2D8/*breve*/, 0x2D9/*dotaccent*/, 0x2DA/*ring*/, 0x2DB/*ogonek*/, 0x2DC/*tilde*/, 0x2DD/*hungarumlaut*/, 0x2013/*endash*/, 0x2014/*emdash*/, 0x2018/*quoteleft*/, 0x2019/*quoteright*/, 0x201A/*quotesinglbase*/, 0x201C/*quotedblleft*/, 0x201D/*quotedblright*/, 0x201E/*quotedblbase*/, 0x2020/*dagger*/, 0x2021/*daggerdbl*/, 0x2022/*bullet*/, 0x2026/*ellipsis*/, 0x2030/*perthousand*/, 0x2039/*guilsinglleft*/, 0x203A/*guilsinglright*/, 0x2044/*fraction*/, 0x20AC/*Euro*/, 0x2122/*trademark*/, 0x2202/*partialdiff*/, 0x2206/*Delta*/, 0x2211/*summation*/, 0x221A/*radical*/, 0x221E/*infinity*/, 0x2260/*notequal*/, 0x2264/*lessequal*/, 0x2265/*greaterequal*/, 0x25CA/*lozenge*/, 0xFB01/*fi*/, 0xFB02/*fl*/, 0xF8FF/*apple*/ }; for ( i = 0; i < sizeof(extra_table_roman)/sizeof(int); i++) { if (extra_table_roman[i] == utf) return i + 0x180; } return 0; } // outputs in PostScript a UTF8 string using the same width in points as on display void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, double x, double y) { int len, code; if (!n || !str || !*str) return; // compute display width of string int w = (int)width(str, n); if (w == 0) return; if (Fl_Graphics_Driver::font() >= FL_FREE_FONT) { transformed_draw_extra(str, n, x, y, w, false); return; } fprintf(output, "%d <~", w); void *data = prepare85(); // transforms UTF8 encoding to our custom PostScript encoding as follows: // extract each unicode character // if unicode <= 0x17F, unicode and PostScript codes are identical // if unicode is one of the values listed in extra_table_roman above // its PostScript code is 0x180 + the character's rank in extra_table_roman // if unicode is something else, draw all string as bitmap image const char *last = str + n; const char *str2 = str; while (str2 < last) { // Extract each unicode character of string. unsigned utf = fl_utf8decode(str2, last, &len); str2 += len; if (utf <= 0x17F) { // until Latin Extended-A ; } else if ( (code = is_in_table(utf)) != 0) { // other handled characters utf = code; } else { // unhandled character: draw all string as bitmap image fprintf(output, "~> pop pop\n"); // close and ignore the opened hex string transformed_draw_extra(str, n, x, y, w, false); return; } // 2 bytes per character, high-order byte first, encode that to ASCII85 uchar c[2]; c[1] = utf & 0xFF; c[0] = (utf & 0xFF00)>>8; write85(data, c, 2); } close85(data); clocale_printf(" %g %g show_pos_width\n", x, y); } void Fl_PostScript_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) { int w = (int)width(str, n); transformed_draw_extra(str, n, x - w, y, w, true); } void Fl_PostScript_Graphics_Driver::concat(){ clocale_printf("[%g %g %g %g %g %g] CT\n", m.a , m.b , m.c , m.d , m.x , m.y); } void Fl_PostScript_Graphics_Driver::reconcat(){ clocale_printf("[%g %g %g %g %g %g] RCT\n" , m.a , m.b , m.c , m.d , m.x , m.y); } ///////////////// transformed (double) drawings //////////////////////////////// void Fl_PostScript_Graphics_Driver::begin_points(){ fprintf(output, "GS\n"); concat(); fprintf(output, "BP\n"); gap_=1; what=POINTS; } void Fl_PostScript_Graphics_Driver::begin_line(){ fprintf(output, "GS\n"); concat(); fprintf(output, "BP\n"); gap_=1; what=LINE; } void Fl_PostScript_Graphics_Driver::begin_loop(){ fprintf(output, "GS\n"); concat(); fprintf(output, "BP\n"); gap_=1; what=LOOP; } void Fl_PostScript_Graphics_Driver::begin_polygon(){ fprintf(output, "GS\n"); concat(); fprintf(output, "BP\n"); gap_=1; what=POLYGON; } void Fl_PostScript_Graphics_Driver::vertex(double x, double y){ if(what==POINTS){ clocale_printf("%g %g MT\n", x , y); gap_=1; return; } if(gap_){ clocale_printf("%g %g MT\n", x , y); gap_=0; }else clocale_printf("%g %g LT\n", x , y); } void Fl_PostScript_Graphics_Driver::curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3){ if(what==NONE) return; if(gap_) clocale_printf("%g %g MT\n", x , y); else clocale_printf("%g %g LT\n", x , y); gap_=0; clocale_printf("%g %g %g %g %g %g curveto \n", x1 , y1 , x2 , y2 , x3 , y3); } void Fl_PostScript_Graphics_Driver::circle(double x, double y, double r){ if(what==NONE){ fprintf(output, "GS\n"); concat(); // fprintf(output, "BP\n"); clocale_printf("%g %g %g 0 360 arc\n", x , y , r); reconcat(); // fprintf(output, "ELP\n"); fprintf(output, "GR\n"); }else clocale_printf("%g %g %g 0 360 arc\n", x , y , r); } void Fl_PostScript_Graphics_Driver::arc(double x, double y, double r, double start, double a){ if(what==NONE) return; gap_=0; if(start>a) clocale_printf("%g %g %g %g %g arc\n", x , y , r , -start, -a); else clocale_printf("%g %g %g %g %g arcn\n", x , y , r , -start, -a); } void Fl_PostScript_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) { if (w <= 1 || h <= 1) return; fprintf(output, "GS\n"); //fprintf(output, "BP\n"); begin_line(); clocale_printf("%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); clocale_printf("%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); arc(0,0,1,a2,a1); // fprintf(output, "0 0 1 %g %g arc\n" , -a1 , -a2); clocale_printf("%g %g SC\n", 2.0/(w-1) , 2.0/(h-1) ); clocale_printf("%g %g TR\n", -x - w/2.0 +0.5 , -y - h/2.0 +0.5); end_line(); // fprintf(output, "%g setlinewidth\n", 2/sqrt(w*h)); // fprintf(output, "ELP\n"); // fprintf(output, 2.0/w , 2.0/w , " SC\n"; // fprintf(output, (-x - w/2.0) , (-y - h/2) , " TR\n"; fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) { fprintf(output, "GS\n"); begin_polygon(); clocale_printf("%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); clocale_printf("%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); vertex(0,0); arc(0.0,0.0, 1, a2, a1); end_polygon(); fprintf(output, "GR\n"); } void Fl_PostScript_Graphics_Driver::end_points(){ gap_=1; reconcat(); fprintf(output, "ELP\n"); //?? fprintf(output, "GR\n"); what=NONE; } void Fl_PostScript_Graphics_Driver::end_line(){ gap_=1; reconcat(); fprintf(output, "ELP\n"); fprintf(output, "GR\n"); what=NONE; } void Fl_PostScript_Graphics_Driver::end_loop(){ gap_=1; reconcat(); fprintf(output, "ECP\n"); fprintf(output, "GR\n"); what=NONE; } void Fl_PostScript_Graphics_Driver::end_polygon(){ gap_=1; reconcat(); fprintf(output, "EFP\n"); fprintf(output, "GR\n"); what=NONE; } void Fl_PostScript_Graphics_Driver::transformed_vertex(double x, double y){ reconcat(); if(gap_){ clocale_printf("%g %g MT\n", x , y); gap_=0; }else clocale_printf("%g %g LT\n", x , y); concat(); } ///////////////////////////// Clipping ///////////////////////////////////////////// void Fl_PostScript_Graphics_Driver::push_clip(int x, int y, int w, int h) { Clip * c=new Clip(); clip_box(x,y,w,h,c->x,c->y,c->w,c->h); c->prev=clip_; clip_=c; fprintf(output, "CR\nCS\n"); if(lang_level_<3) recover(); clocale_printf("%g %g %i %i CL\n", clip_->x-0.5 , clip_->y-0.5 , clip_->w , clip_->h); } void Fl_PostScript_Graphics_Driver::push_no_clip() { Clip * c = new Clip(); c->prev=clip_; clip_=c; clip_->x = clip_->y = clip_->w = clip_->h = -1; fprintf(output, "CR\nCS\n"); if(lang_level_<3) recover(); } void Fl_PostScript_Graphics_Driver::pop_clip() { if(!clip_)return; Clip * c=clip_; clip_=clip_->prev; delete c; fprintf(output, "CR\nCS\n"); if(clip_ && clip_->w >0) clocale_printf("%g %g %i %i CL\n", clip_->x - 0.5, clip_->y - 0.5, clip_->w , clip_->h); // uh, -0.5 is to match screen clipping, for floats there should be something beter if(lang_level_<3) recover(); } void Fl_PostScript_Graphics_Driver::ps_origin(int x, int y) { clocale_printf("GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", left_margin, top_margin, scale_x, scale_y, x, y, angle); } void Fl_PostScript_Graphics_Driver::ps_translate(int x, int y) { fprintf(output, "GS %d %d translate GS\n", x, y); } void Fl_PostScript_Graphics_Driver::ps_untranslate(void) { fprintf(output, "GR GR\n"); } #if defined(FLTK_USE_X11) || defined(FLTK_USE_WAYLAND) Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) { *pfname = NULL; return new Fl_PostScript_File_Device; } int Fl_PDF_File_Surface::begin_job(const char* defaultfilename, char **perr_message) { if (perr_message) { *perr_message = strdup("Class Fl_PDF_File_Surface requires PANGO to be usable."); } return 2; } int Fl_PDF_File_Surface::begin_document(const char* defaultfilename, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout, char **perr_message) { return begin_job(NULL, perr_message); } #endif // defined(FLTK_USE_X11) || defined(FLTK_USE_WAYLAND) # else // USE_PANGO /* Cairo-based implementation of the PostScript graphics driver */ static cairo_status_t write_to_cairo_stream(FILE *output, unsigned char *data, unsigned int length) { size_t l = fwrite(data, 1, length, output); return (l == length ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR); } static cairo_t* init_cairo_postscript(FILE* output, int w, int h) { cairo_surface_t* cs = cairo_ps_surface_create_for_stream( (cairo_write_func_t)write_to_cairo_stream, output, w, h); if (cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) return NULL; cairo_ps_surface_restrict_to_level(cs, CAIRO_PS_LEVEL_2); cairo_t* cairo_ = cairo_create(cs); cairo_surface_destroy(cs); return cairo_; } int Fl_PostScript_Graphics_Driver::start_postscript(int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout) //returns 0 iff OK { if (format == Fl_Paged_Device::A4) { left_margin = 18; top_margin = 18; } else { left_margin = 12; top_margin = 12; } // combine the format and layout information page_format_ = ((int)format | (int)layout); if (layout & Fl_Paged_Device::LANDSCAPE){ ph_ = Fl_Paged_Device::page_formats[format].width; pw_ = Fl_Paged_Device::page_formats[format].height; } else { pw_ = Fl_Paged_Device::page_formats[format].width; ph_ = Fl_Paged_Device::page_formats[format].height; } cairo_ = init_cairo_postscript(output, Fl_Paged_Device::page_formats[format].width, Fl_Paged_Device::page_formats[format].height); if (!cairo_) return 1; nPages=0; char feature[250]; snprintf(feature, 250, "%%%%BeginFeature: *PageSize %s\n<>setpagedevice\n%%%%EndFeature", Fl_Paged_Device::page_formats[format].name, Fl_Paged_Device::page_formats[format].width, Fl_Paged_Device::page_formats[format].height); cairo_ps_surface_dsc_comment(cairo_get_target(cairo_), feature); return 0; } int Fl_PostScript_Graphics_Driver::start_eps(int width, int height) { pw_ = width; ph_ = height; cairo_ = init_cairo_postscript(output, width, height); if (!cairo_) return 1; cairo_ps_surface_set_eps(cairo_get_target(cairo_), true); nPages=0; //useful? return 0; } void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, double x, double y) { if (!n) return; if (!pango_context_) { PangoFontMap *def_font_map = pango_cairo_font_map_get_default(); // 1.10 #if PANGO_VERSION_CHECK(1,22,0) pango_context_ = pango_font_map_create_context(def_font_map); // 1.22 #else pango_context_ = pango_context_new(); pango_context_set_font_map(pango_context_, def_font_map); #endif pango_layout_ = pango_layout_new(pango_context_); } PangoFontDescription *pfd = Fl_Graphics_Driver::default_driver().pango_font_description(); pango_layout_set_font_description(pango_layout_, pfd); int pwidth, pheight; cairo_save(cairo_); str = Fl_Cairo_Graphics_Driver::clean_utf8(str, n); pango_layout_set_text(pango_layout_, str, n); pango_layout_get_size(pango_layout_, &pwidth, &pheight); if (pwidth > 0) { double s = width(str, n); cairo_translate(cairo_, x, y - height() + descent()); s = (s/pwidth) * PANGO_SCALE; cairo_scale(cairo_, s, s); pango_cairo_show_layout(cairo_, pango_layout_); // 1.10 } cairo_restore(cairo_); check_status(); } // ======================================================= class Fl_PDF_Pango_File_Surface : public Fl_PostScript_File_Device { public: char *doc_fname; Fl_PDF_Pango_File_Surface(); ~Fl_PDF_Pango_File_Surface() { if (doc_fname) free(doc_fname); } int begin_job(const char *defaultname, char **perr_message = NULL); int begin_job(int, int*, int *, char **) FL_OVERRIDE {return 1;} // don't use int begin_document(const char* outname, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout, char **perr_message); int begin_page() FL_OVERRIDE; void end_job() FL_OVERRIDE; }; Fl_PDF_Pango_File_Surface::Fl_PDF_Pango_File_Surface() { doc_fname = NULL; driver()->output = NULL; } static Fl_Paged_Device::Page_Format menu_to_size[] = {Fl_Paged_Device::A3, Fl_Paged_Device::A4, Fl_Paged_Device::A5, Fl_Paged_Device::B4, Fl_Paged_Device::B5, Fl_Paged_Device::EXECUTIVE, Fl_Paged_Device::LEGAL, Fl_Paged_Device::LETTER, Fl_Paged_Device::TABLOID }; static int size_count = sizeof(menu_to_size) / sizeof(menu_to_size[0]); static int update_format_layout(int rank, Fl_Paged_Device::Page_Layout layout, bool &need_set_default_psize) { int status = -1; Fl_Window *modal = new Fl_Window(510, 90, Fl_PDF_File_Surface::format_dialog_title); modal->begin(); Fl_Choice *psize = new Fl_Choice(140, 10, 110, 30, Fl_PDF_File_Surface::format_dialog_page_size); psize->when(FL_WHEN_CHANGED); for (int i = 0; i < size_count; i++) { psize->add(Fl_Paged_Device::page_formats[menu_to_size[i]].name); } psize->value(rank); Fl_Check_Button *default_size = new Fl_Check_Button(psize->x(), psize->y() + psize->h(), psize->w(), psize->h(), Fl_PDF_File_Surface::format_dialog_default); default_size->value(1); default_size->user_data(&need_set_default_psize); FL_INLINE_CALLBACK_2(psize, Fl_Choice*, choice, psize, Fl_Check_Button*, check_but, default_size, { if (check_but->value() && choice->mvalue() && choice->prev_mvalue() && choice->prev_mvalue() != choice->mvalue()) { check_but->value(0); } }); FL_INLINE_CALLBACK_2( modal, Fl_Window*, win, modal, Fl_Check_Button*, check_but, default_size, { *((bool*)check_but->user_data()) = check_but->value(); win->hide(); } ); Fl_Choice *orientation = new Fl_Choice(psize->x() + psize->w() + 120, psize->y(), 130, psize->h(), Fl_PDF_File_Surface::format_dialog_orientation); orientation->add("PORTRAIT|LANDSCAPE"); orientation->value(layout == Fl_Paged_Device::PORTRAIT ? 0 : 1); Fl_Return_Button *ok = new Fl_Return_Button(orientation->x() + orientation->w() - 55, psize->y() + psize->h() + 10, 55, 30, fl_ok); FL_INLINE_CALLBACK_4( ok, Fl_Widget*, b, ok, int*, pstatus, &status, Fl_Choice*, psize, psize, Fl_Choice*, orientation, orientation, { *pstatus = menu_to_size[psize->value()] + 0x100 * orientation->value(); b->window()->do_callback(); } ); Fl_Button *cancel = new Fl_Button(ok->x() - 90, psize->y() + psize->h() + 10, 70, 30, fl_cancel); FL_INLINE_CALLBACK_1( cancel, Fl_Widget*, wid, cancel, { wid->window()->do_callback(); } ); modal->end(); modal->set_modal(); modal->show(); while (modal->shown()) Fl::wait(); delete modal; return status; } int Fl_PDF_Pango_File_Surface::begin_job(const char *defaultname, char **perr_message) { static Page_Layout layout = PORTRAIT; Fl_Preferences print_prefs(Fl_Preferences::CORE_USER, "fltk.org", "printers"); char *pref_format; print_prefs.get("PDF/page_size", pref_format, "A4"); int rank = 1; // corresponds to A4 for (int i = 0; i < size_count; i++) { if (strcmp(pref_format, Fl_Paged_Device::page_formats[menu_to_size[i]].name) == 0) { rank = i; break; } } bool need_set_default_psize; int status = update_format_layout(rank, layout, need_set_default_psize); if (status == -1) return 1; Page_Format format = (Page_Format)(status & 0xFF); if (need_set_default_psize) print_prefs.set("PDF/page_size", Fl_Paged_Device::page_formats[format].name); Fl_Native_File_Chooser ch(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); ch.preset_file(defaultname); ch.filter("*.pdf"); ch.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM); int retval = ch.show(); if (retval) return (retval == -1 ? 2 : 1); layout = (Page_Layout)(status & 0x100); return begin_document(ch.filename(), format, layout, perr_message); } int Fl_PDF_Pango_File_Surface::begin_document(const char* outfname, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout, char **perr_message) { int w = page_formats[format].width; int h = page_formats[format].height; if (layout == LANDSCAPE) { int tmp = w; w = h; h = tmp; } Fl_PostScript_Graphics_Driver *dr = driver(); dr->output = fopen(outfname, "w"); cairo_status_t status = CAIRO_STATUS_WRITE_ERROR; cairo_surface_t* cs = NULL; if (dr->output) { cs = cairo_pdf_surface_create_for_stream ( (cairo_write_func_t)write_to_cairo_stream, dr->output, w, h); status = cairo_surface_status(cs); } if (status != CAIRO_STATUS_SUCCESS) { if (perr_message) { const char *mess = cairo_status_to_string(status); size_t l = strlen(mess) + strlen(outfname) + 100; *perr_message = new char[l]; snprintf(*perr_message, l, "Error '%s' while attempting to create %s.", mess, outfname); } if (cs) cairo_surface_destroy(cs); return 2; } cairo_pdf_surface_restrict_to_version(cs, CAIRO_PDF_VERSION_1_4); cairo_t *cr = cairo_create(cs); cairo_surface_destroy(cs); dr->set_cairo(cr); dr->pw_ = w; dr->ph_ = h; if (format == Fl_Paged_Device::A4) { dr->left_margin = 18; dr->top_margin = 18; } else { dr->left_margin = 12; dr->top_margin = 12; } doc_fname = strdup(outfname); return 0; } int Fl_PDF_Pango_File_Surface::begin_page(void) { Fl_PostScript_Graphics_Driver *ps = driver(); Fl_Surface_Device::push_current(this); cairo_save(ps->cr()); cairo_translate(ps->cr(), ps->left_margin, ps->top_margin); cairo_set_line_width(ps->cr(), 1); cairo_set_source_rgb(ps->cr(), 1.0, 1.0, 1.0); // white background cairo_save(ps->cr()); cairo_save(ps->cr()); ps->check_status(); x_offset = 0; y_offset = 0; ps->scale_x = ps->scale_y = 1.; ps->angle = 0; return 0; } void Fl_PDF_Pango_File_Surface::end_job() { Fl_PostScript_Graphics_Driver *ps = driver(); int error = 0; cairo_surface_t *s = cairo_get_target(ps->cr()); cairo_surface_finish(s); error = cairo_surface_status(s); int err2 = fclose(ps->output); ps->output = NULL; if (!error) error = err2; cairo_destroy(ps->cr()); while (ps->clip_){ Fl_PostScript_Graphics_Driver::Clip * c= ps->clip_; ps->clip_= ps->clip_->prev; delete c; } if (error) fl_alert ("Error during PostScript data output."); } Fl_Paged_Device *Fl_PDF_File_Surface::new_platform_pdf_surface_(const char ***pfname) { Fl_PDF_Pango_File_Surface *surf = new Fl_PDF_Pango_File_Surface(); *pfname = (const char**)&surf->doc_fname; return surf; } int Fl_PDF_File_Surface::begin_job(const char* defaultfilename, char **perr_message) { return ((Fl_PDF_Pango_File_Surface*)platform_surface_)->begin_job(defaultfilename, perr_message); } int Fl_PDF_File_Surface::begin_document(const char* defaultfilename, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout, char **perr_message) { return ((Fl_PDF_Pango_File_Surface*)platform_surface_)->begin_document(defaultfilename, format, layout, perr_message); } #endif // USE_PANGO /** \} \endcond */ void Fl_PostScript_File_Device::margins(int *left, int *top, int *right, int *bottom) // to implement { Fl_PostScript_Graphics_Driver *ps = driver(); if(left) *left = (int)(ps->left_margin / ps->scale_x + .5); if(right) *right = (int)(ps->left_margin / ps->scale_x + .5); if(top) *top = (int)(ps->top_margin / ps->scale_y + .5); if(bottom) *bottom = (int)(ps->top_margin / ps->scale_y + .5); } int Fl_PostScript_File_Device::printable_rect(int *w, int *h) //returns 0 iff OK { Fl_PostScript_Graphics_Driver *ps = driver(); if(w) *w = (int)((ps->pw_ - 2 * ps->left_margin) / ps->scale_x + .5); if(h) *h = (int)((ps->ph_ - 2 * ps->top_margin) / ps->scale_y + .5); return 0; } void Fl_PostScript_File_Device::origin(int *x, int *y) { Fl_Paged_Device::origin(x, y); } void Fl_PostScript_File_Device::origin(int x, int y) { x_offset = x; y_offset = y; driver()->ps_origin(x, y); } void Fl_PostScript_File_Device::scale (float s_x, float s_y) { if (s_y == 0.) s_y = s_x; Fl_PostScript_Graphics_Driver *ps = driver(); ps->scale_x = s_x; ps->scale_y = s_y; #if USE_PANGO cairo_restore(ps->cr()); cairo_restore(ps->cr()); cairo_save(ps->cr()); cairo_scale(ps->cr(), s_x, s_y); cairo_rotate(ps->cr(), ps->angle * M_PI / 180); cairo_save(ps->cr()); #else ps->clocale_printf("GR GR GS %d %d TR %f %f SC %f rotate GS\n", ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, ps->angle); #endif } void Fl_PostScript_File_Device::rotate (float rot_angle) { Fl_PostScript_Graphics_Driver *ps = driver(); ps->angle = - rot_angle; #if USE_PANGO cairo_restore(ps->cr()); cairo_restore(ps->cr()); cairo_save(ps->cr()); cairo_scale(ps->cr(), ps->scale_x, ps->scale_y); cairo_translate(ps->cr(), x_offset, y_offset); cairo_rotate(ps->cr(), ps->angle * M_PI / 180); cairo_save(ps->cr()); #else ps->clocale_printf("GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, x_offset, y_offset, ps->angle); #endif } void Fl_PostScript_File_Device::translate(int x, int y) { driver()->ps_translate(x, y); } void Fl_PostScript_File_Device::untranslate(void) { driver()->ps_untranslate(); } int Fl_PostScript_File_Device::begin_page (void) { Fl_PostScript_Graphics_Driver *ps = driver(); Fl_Surface_Device::push_current(this); #if USE_PANGO cairo_ps_surface_dsc_begin_page_setup(cairo_get_target(ps->cr())); char feature[200]; snprintf(feature, 200, "%%%%PageOrientation: %s", ps->pw_ > ps->ph_ ? "Landscape" : "Portrait"); cairo_ps_surface_dsc_comment(cairo_get_target(ps->cr()), feature); cairo_save(ps->cr()); if (ps->pw_ > ps->ph_) { cairo_translate(ps->cr(), 0, ps->pw_); cairo_rotate(ps->cr(), -M_PI/2); } cairo_translate(ps->cr(), ps->left_margin, ps->top_margin); cairo_set_line_width(ps->cr(), 1); cairo_set_source_rgb(ps->cr(), 1.0, 1.0, 1.0); // white background cairo_save(ps->cr()); cairo_save(ps->cr()); ps->check_status(); #else ps->page(ps->page_format_); #endif x_offset = 0; y_offset = 0; ps->scale_x = ps->scale_y = 1.; ps->angle = 0; #if ! USE_PANGO fprintf(ps->output, "GR GR GS %d %d translate GS\n", ps->left_margin, ps->top_margin); #endif return 0; } int Fl_PostScript_File_Device::end_page (void) { #if USE_PANGO Fl_PostScript_Graphics_Driver *ps = (Fl_PostScript_Graphics_Driver*)driver(); cairo_restore(ps->cr()); cairo_restore(ps->cr()); cairo_restore(ps->cr()); cairo_show_page(ps->cr()); ps->check_status(); #endif Fl_Surface_Device::pop_current(); return 0; } void Fl_PostScript_File_Device::end_job (void) // finishes PostScript & closes file { Fl_PostScript_Graphics_Driver *ps = driver(); int error = 0; #if USE_PANGO cairo_surface_t *s = cairo_get_target(ps->cr()); cairo_surface_finish(s); error = cairo_surface_status(s); if (error) { fclose(ps->output); fputs("\n", ps->output); // creates an stdio error } cairo_destroy(ps->cr()); if (!error) error = fflush(ps->output); #else if (ps->nPages) { // for eps nPages is 0 so it is fine .... fprintf(ps->output, "CR\nGR\nGR\nGR\nSP\n restore\n"); if (!ps->pages_){ fprintf(ps->output, "%%%%Trailer\n"); fprintf(ps->output, "%%%%Pages: %i\n" , ps->nPages); }; } else fprintf(ps->output, "GR\n restore\n"); fputs("%%EOF",ps->output); fflush(ps->output); error = ferror(ps->output); ps->reset(); #endif while (ps->clip_){ Fl_PostScript_Graphics_Driver::Clip * c= ps->clip_; ps->clip_= ps->clip_->prev; delete c; } int err2 = (ps->close_cmd_ ? (ps->close_cmd_)(ps->output) : fclose(ps->output) ); if (!error) error = err2; if (error && ps->close_cmd_ == NULL) { fl_alert ("Error during PostScript data output."); } } void Fl_PostScript_File_Device::close_command(Fl_PostScript_Close_Command cmd) { driver()->close_command(cmd); } Fl_EPS_File_Surface::Fl_EPS_File_Surface(int width, int height, FILE *eps, Fl_Color background, Fl_PostScript_Close_Command closef) : Fl_Widget_Surface(new Fl_PostScript_Graphics_Driver()) { Fl_PostScript_Graphics_Driver *ps = driver(); ps->output = eps; ps->close_cmd_ = closef; if (ps->output) { float s = Fl::screen_scale(0); ps->start_eps(int(width*s), int(height*s)); #if USE_PANGO cairo_save(ps->cr()); ps->left_margin = ps->top_margin = 0; cairo_scale(ps->cr(), s, s); cairo_set_line_width(ps->cr(), 1); cairo_set_source_rgb(ps->cr(), 1.0, 1.0, 1.0); // white background cairo_save(ps->cr()); cairo_save(ps->cr()); ps->check_status(); #else if (s != 1) { ps->clocale_printf("GR GR GS %f %f SC GS\n", s, s); } Fl::get_color(background, ps->bg_r, ps->bg_g, ps->bg_b); #endif ps->scale_x = ps->scale_y = s; } } int Fl_EPS_File_Surface::close() { int error = 0; Fl_PostScript_Graphics_Driver *ps = driver(); #if USE_PANGO cairo_surface_t *s = cairo_get_target(ps->cr()); cairo_surface_finish(s); cairo_status_t status = cairo_surface_status(s); cairo_destroy(ps->cr()); fflush(ps->output); error = ferror(ps->output); if (status != CAIRO_STATUS_SUCCESS) error = status; #else if(ps->output) { fputs("GR\nend %matches begin of FLTK dict\n", ps->output); fputs("restore\n", ps->output); fputs("%%EOF\n", ps->output); ps->reset(); fflush(ps->output); error = ferror(ps->output); } #endif int err2 = (ps->close_cmd_ ? (ps->close_cmd_)(ps->output) : fclose(ps->output)); if (err2) error = err2; while (ps->clip_){ Fl_PostScript_Graphics_Driver::Clip * c= ps->clip_; ps->clip_= ps->clip_->prev; delete c; } ps->output = NULL; return error; } Fl_EPS_File_Surface::~Fl_EPS_File_Surface() { if (driver()->output) { if ( close() ) { fl_open_display(); fl_alert ("Error during encapsulated PostScript data output."); } } delete driver(); } FILE *Fl_EPS_File_Surface::file() { Fl_PostScript_Graphics_Driver *ps = driver(); return ps ? ps->output : NULL; } int Fl_EPS_File_Surface::printable_rect(int *w, int *h) { Fl_PostScript_Graphics_Driver *ps = driver(); *w = int(ps->pw_); *h = int(ps->ph_); return 0; } void Fl_EPS_File_Surface::origin(int x, int y) { x_offset = x; y_offset = y; driver()->ps_origin(x, y); } void Fl_EPS_File_Surface::origin(int *px, int *py) { Fl_Widget_Surface::origin(px, py); } void Fl_EPS_File_Surface::translate(int x, int y) { driver()->ps_translate(x, y); } void Fl_EPS_File_Surface::untranslate() { driver()->ps_untranslate(); } #endif // !defined(FL_NO_PRINT_SUPPORT) fltk-1.4.3/src/drivers/PostScript/Fl_PostScript_Graphics_Driver.H0000644000175000017500000002357615004135251025200 0ustar albrechtalbrecht// // Support for graphics output to PostScript file for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Pango_PostScript_Graphics_Driver.H Declaration of class Fl_PostScript_Graphics_Driver. */ #ifndef FL_POSTSCRIPT_GRAPHICS_DRIVER_H #define FL_POSTSCRIPT_GRAPHICS_DRIVER_H #include #include #ifndef USE_PANGO #define USE_PANGO 0 #endif /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** PostScript graphical backend. */ #if USE_PANGO #include "../Cairo/Fl_Cairo_Graphics_Driver.H" class Fl_PostScript_Graphics_Driver : public Fl_Cairo_Graphics_Driver { public: FILE *output; Fl_PostScript_Close_Command close_cmd_; int page_format_; char *ps_filename_; int nPages; double pw_, ph_; Fl_PostScript_Graphics_Driver(); ~Fl_PostScript_Graphics_Driver(); void close_command(Fl_PostScript_Close_Command cmd){close_cmd_=cmd;} FILE * file() {return output;} inline void set_cairo(cairo_t *cr) { cairo_ = cr; } void page(double pw, double ph, int media = 0); void page(int format); int start_postscript (int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout); int start_eps(int width, int height); void draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) FL_OVERRIDE; void draw_image(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=3) FL_OVERRIDE { Fl_Cairo_Graphics_Driver::draw_image(call, data, x,y,w,h,delta); } void font(int f, int s) FL_OVERRIDE; Fl_Font font() FL_OVERRIDE; double width(const char *s, int n) FL_OVERRIDE; double width(unsigned u) FL_OVERRIDE; int height() FL_OVERRIDE; int descent() FL_OVERRIDE; void text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) FL_OVERRIDE; // draw text at width measured on display void transformed_draw(const char* s, int n, double x, double y); void draw(const char* s, int nBytes, int x, int y) FL_OVERRIDE {transformed_draw(s,nBytes,x,y); } void draw(const char* s, int nBytes, float x, float y) FL_OVERRIDE {transformed_draw(s,nBytes,x,y); } void draw(int angle, const char *str, int n, int x, int y) FL_OVERRIDE {Fl_Cairo_Graphics_Driver::draw(angle, str, n, x, y);} void point(int x, int y) FL_OVERRIDE; int not_clipped(int x, int y, int w, int h) FL_OVERRIDE; int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) FL_OVERRIDE; virtual int has_feature(driver_feature feature_mask) FL_OVERRIDE { return feature_mask & PRINTER; } // draw image classes without caching them void draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy); void draw_pixmap(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_bitmap(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_rgb(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; }; #else // ! USE_PANGO class Fl_PostScript_Graphics_Driver : public Fl_Graphics_Driver { private: void transformed_draw_extra(const char* str, int n, double x, double y, int w, bool rtl); void *prepare_rle85(); void write_rle85(uchar b, void *data); void close_rle85(void *data); void *prepare85(); void write85(void *data, const uchar *p, int len); void close85(void *data); int scale_for_image_(Fl_Image *img, int XP, int YP, int WP, int HP,int cx, int cy); protected: uchar **mask_bitmap() FL_OVERRIDE {return &mask;} public: Fl_PostScript_Graphics_Driver(); class Clip { public: int x, y, w, h; Clip *prev; }; Clip * clip_; int lang_level_; int gap_; int pages_; int interpolate_; //interpolation of images uchar * mask; int mx; // width of mask; int my; // mask lines int page_policy_; void page_policy(int p); int page_policy() { return page_policy_; } int alpha_mask(const uchar * data, int w, int h, int D, int LD=0); /** Shields output PostScript data from modifications of the current locale. It typically avoids PostScript errors caused if the current locale uses comma instead of dot as "decimal point". \param format directives controlling output PostScript data \return value returned by vfprintf() call */ int clocale_printf(const char *format, ...); int linewidth_;// need for clipping, lang level 1-2 int linestyle_;// unsigned char cr_,cg_,cb_; char linedash_[256];//should be enough void concat(); // transform ror scalable dradings... void reconcat(); //invert void recover(); //recovers the state after grestore (such as line styles...) void reset(); Fl_PostScript_Close_Command close_cmd_; int nPages; //int orientation_; float scale_x; float scale_y; float angle; int left_margin; int top_margin; FILE *output; double pw_, ph_; uchar bg_r, bg_g, bg_b; int start_postscript (int pagecount, enum Fl_Paged_Device::Page_Format format, enum Fl_Paged_Device::Page_Layout layout); int start_eps(int width, int height); void transformed_draw(const char* s, int n, double x, double y); //precise text placing //void transformed_draw(const char* s, double x, double y); int page_format_; char *ps_filename_; void close_command(Fl_PostScript_Close_Command cmd){close_cmd_=cmd;} FILE * file() {return output;} //void orientation (int o); //Fl_PostScript_Graphics_Driver(FILE *o, int lang_level, int pages = 0); // ps (also multi-page) constructor //void interpolate(int i){interpolate_=i;} //int interpolate(){return interpolate_;} void page(double pw, double ph, int media = 0); void page(int format); // implementation of drawing methods void color(Fl_Color c) FL_OVERRIDE; void color(uchar r, uchar g, uchar b) FL_OVERRIDE; Fl_Color color() FL_OVERRIDE; void push_clip(int x, int y, int w, int h) FL_OVERRIDE; int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) FL_OVERRIDE; int not_clipped(int x, int y, int w, int h) FL_OVERRIDE; void push_no_clip() FL_OVERRIDE; void pop_clip() FL_OVERRIDE; void line_style(int style, int width=0, char* dashes=0) FL_OVERRIDE; void rect(int x, int y, int w, int h) FL_OVERRIDE; void rectf(int x, int y, int w, int h) FL_OVERRIDE; void xyline(int x, int y, int x1) FL_OVERRIDE; void xyline(int x, int y, int x1, int y2) FL_OVERRIDE; void xyline(int x, int y, int x1, int y2, int x3) FL_OVERRIDE; void yxline(int x, int y, int y1) FL_OVERRIDE; void yxline(int x, int y, int y1, int x2) FL_OVERRIDE; void yxline(int x, int y, int y1, int x2, int y3) FL_OVERRIDE; void line(int x1, int y1, int x2, int y2) FL_OVERRIDE; void line(int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2) FL_OVERRIDE; void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) FL_OVERRIDE; void point(int x, int y) FL_OVERRIDE; void begin_points() FL_OVERRIDE; void begin_line() FL_OVERRIDE; void begin_loop() FL_OVERRIDE; void begin_polygon() FL_OVERRIDE; void vertex(double x, double y) FL_OVERRIDE; void curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3) FL_OVERRIDE; void circle(double x, double y, double r) FL_OVERRIDE; void arc(double x, double y, double r, double start, double a) FL_OVERRIDE; void arc(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void pie(int x, int y, int w, int h, double a1, double a2) FL_OVERRIDE; void end_points() FL_OVERRIDE; void end_line() FL_OVERRIDE; void end_loop() FL_OVERRIDE; void end_polygon() FL_OVERRIDE; void begin_complex_polygon() FL_OVERRIDE {begin_polygon();} void gap() FL_OVERRIDE {gap_=1;} void end_complex_polygon() FL_OVERRIDE {end_polygon();} void transformed_vertex(double x, double y) FL_OVERRIDE; void draw_image(const uchar* d, int x,int y,int w,int h, int delta=3, int ldelta=0) FL_OVERRIDE; void draw_image_mono(const uchar* d, int x,int y,int w,int h, int delta=1, int ld=0) FL_OVERRIDE; void draw_image(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=3) FL_OVERRIDE; void draw_image_mono(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=1) FL_OVERRIDE; void draw(const char* s, int nBytes, int x, int y) FL_OVERRIDE {transformed_draw(s,nBytes,x,y); } void draw(const char* s, int nBytes, float x, float y) FL_OVERRIDE {transformed_draw(s,nBytes,x,y); } void draw(int angle, const char *str, int n, int x, int y) FL_OVERRIDE; void rtl_draw(const char* s, int n, int x, int y) FL_OVERRIDE; void font(int face, int size) FL_OVERRIDE; Fl_Font font() FL_OVERRIDE; double width(const char *, int) FL_OVERRIDE; double width(unsigned int u) FL_OVERRIDE; void text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) FL_OVERRIDE; int height() FL_OVERRIDE; int descent() FL_OVERRIDE; void draw_pixmap(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_bitmap(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; void draw_rgb(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) FL_OVERRIDE; ~Fl_PostScript_Graphics_Driver(); int has_feature(driver_feature feature_mask) FL_OVERRIDE { return feature_mask & PRINTER; } void ps_origin(int x, int y); void ps_translate(int, int); void ps_untranslate(); }; #endif // USE_PANGO /** \} \endcond */ #endif // FL_POSTSCRIPT_GRAPHICS_DRIVER_H fltk-1.4.3/src/Fl_Tree_Item.cxx0000644000175000017500000015306115004135251016424 0ustar albrechtalbrecht// #include #include #include #include #include #include #include #include #include #include "Fl_System_Driver.H" ////////////////////// // Fl_Tree_Item.cxx ////////////////////// // // Fl_Tree -- This file is part of the Fl_Tree widget for FLTK // Copyright (C) 2009-2010 by Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /////////////////////////////////////////////////////////////////////////// 80 / // Was the last event inside the specified xywh? static int event_inside(const int xywh[4]) { return(Fl::event_inside(xywh[0],xywh[1],xywh[2],xywh[3])); } /// Constructor. /// Makes a new instance of Fl_Tree_Item using defaults from \p 'prefs'. /// \deprecated in 1.3.3 ABI -- you must use Fl_Tree_Item(Fl_Tree*) for proper horizontal scrollbar behavior. /// Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Prefs &prefs) { _Init(prefs, 0); } // Initialize the tree item // Used by constructors // void Fl_Tree_Item::_Init(const Fl_Tree_Prefs &prefs, Fl_Tree *tree) { _tree = tree; _label = 0; _labelfont = prefs.labelfont(); _labelsize = prefs.labelsize(); _labelfgcolor = prefs.labelfgcolor(); _labelbgcolor = prefs.labelbgcolor(); _widget = 0; _flags = OPEN|VISIBLE|ACTIVE; _xywh[0] = 0; _xywh[1] = 0; _xywh[2] = 0; _xywh[3] = 0; _collapse_xywh[0] = 0; _collapse_xywh[1] = 0; _collapse_xywh[2] = 0; _collapse_xywh[3] = 0; _label_xywh[0] = 0; _label_xywh[1] = 0; _label_xywh[2] = 0; _label_xywh[3] = 0; _usericon = 0; _userdeicon = 0; _userdata = 0; _parent = 0; _children.manage_item_destroy(1); // let array's dtor manage destroying Fl_Tree_Items _prev_sibling = 0; _next_sibling = 0; } /// Constructor. /// Makes a new instance of Fl_Tree_Item for \p 'tree'. /// /// This must be used instead of the older, deprecated Fl_Tree_Item(Fl_Tree_Prefs) /// constructor for proper horizontal scrollbar calculation. /// /// \version 1.3.3 ABI feature /// Fl_Tree_Item::Fl_Tree_Item(Fl_Tree *tree) { _Init(tree->_prefs, tree); } // DTOR Fl_Tree_Item::~Fl_Tree_Item() { if ( _label ) { free((void*)_label); _label = 0; } _widget = 0; // Fl_Group will handle destruction _usericon = 0; // user handled allocation _userdeicon = 0; // user handled allocation // focus item? set to null if ( _tree && this == _tree->_item_focus ) { _tree->_item_focus = 0; } //_children.clear(); // array's destructor handles itself } /// Copy constructor. Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Item *o) { _tree = o->_tree; _label = o->label() ? fl_strdup(o->label()) : 0; _labelfont = o->labelfont(); _labelsize = o->labelsize(); _labelfgcolor = o->labelfgcolor(); _labelbgcolor = o->labelbgcolor(); _widget = o->widget(); _flags = o->_flags; _xywh[0] = o->_xywh[0]; _xywh[1] = o->_xywh[1]; _xywh[2] = o->_xywh[2]; _xywh[3] = o->_xywh[3]; _collapse_xywh[0] = o->_collapse_xywh[0]; _collapse_xywh[1] = o->_collapse_xywh[1]; _collapse_xywh[2] = o->_collapse_xywh[2]; _collapse_xywh[3] = o->_collapse_xywh[3]; _label_xywh[0] = o->_label_xywh[0]; _label_xywh[1] = o->_label_xywh[1]; _label_xywh[2] = o->_label_xywh[2]; _label_xywh[3] = o->_label_xywh[3]; _usericon = o->usericon(); _userdata = o->user_data(); _parent = o->_parent; _prev_sibling = 0; // do not copy ptrs! use update_prev_next() _next_sibling = 0; // do not copy ptrs! use update_prev_next() } /// Print the tree as 'ascii art' to stdout. /// Used mainly for debugging. /// void Fl_Tree_Item::show_self(const char *indent) const { const char *thelabel = label() ? label() : "(NULL)"; printf("%s-%s (%d children, this=%p, parent=%p, prev=%p, next=%p, depth=%d)\n", indent, thelabel, children(), (void*)this, (void*)_parent, (void*)_prev_sibling, (void*)_next_sibling, depth()); if ( children() ) { char *i2 = new char [strlen(indent)+3]; // 2 + nul byte strcpy(i2, indent); strcat(i2, " |"); for ( int t=0; tshow_self(i2); } delete[] i2; } fflush(stdout); } /// Set the label to \p 'name'. /// Makes and manages an internal copy of \p 'name'. /// void Fl_Tree_Item::label(const char *name) { if ( _label ) { free((void*)_label); _label = 0; } _label = name ? fl_strdup(name) : 0; recalc_tree(); // may change label geometry } /// Return the label. const char *Fl_Tree_Item::label() const { return(_label); } /// Return const child item for the specified 'index'. const Fl_Tree_Item *Fl_Tree_Item::child(int index) const { return(_children[index]); } /// Clear all the children for this item. void Fl_Tree_Item::clear_children() { _children.clear(); recalc_tree(); // may change tree geometry } /// Return the index of the immediate child of this item /// that has the label \p 'name'. /// /// \returns index of found item, or -1 if not found. /// \version 1.3.0 release /// int Fl_Tree_Item::find_child(const char *name) { if ( name ) { for ( int t=0; tlabel() ) if ( strcmp(child(t)->label(), name) == 0 ) return(t); } return(-1); } /// Return the /immediate/ child of current item /// that has the label \p 'name'. /// /// \returns const found item, or 0 if not found. /// \version 1.3.3 /// const Fl_Tree_Item* Fl_Tree_Item::find_child_item(const char *name) const { if ( name ) for ( int t=0; tlabel() ) if ( strcmp(child(t)->label(), name) == 0 ) return(child(t)); return(0); } /// Non-const version of Fl_Tree_Item::find_child_item(const char *name) const. Fl_Tree_Item* Fl_Tree_Item::find_child_item(const char *name) { // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. return(const_cast( static_cast(*this).find_child_item(name))); } /// Find child item by descending array \p 'arr' of names. /// Does not include self in search. /// Only Fl_Tree should need this method. /// /// \returns item, or 0 if not found /// \version 1.3.0 release /// const Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) const { for ( int t=0; tlabel() ) { if ( strcmp(child(t)->label(), *arr) == 0 ) { // match? if ( *(arr+1) ) { // more in arr? descend return(_children[t]->find_child_item(arr+1)); } else { // end of arr? done return(_children[t]); } } } } return(0); } /// Non-const version of Fl_Tree_Item::find_child_item(char **arr) const. Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) { // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. return(const_cast( static_cast(*this).find_child_item(arr))); } /// Find item by descending array of \p 'names'. /// Includes self in search. /// Only Fl_Tree should need this method. Use Fl_Tree::find_item() instead. /// /// \returns const item, or 0 if not found /// const Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) const { if ( ! *names ) return(0); if ( label() && strcmp(label(), *names) == 0 ) { // match self? ++names; // skip self if ( *names == 0 ) return(this); // end of names, found ourself } if ( children() ) { // check children.. return(find_child_item(names)); } return(0); } /// Non-const version of Fl_Tree_Item::find_item(char **names) const. Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) { // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. return(const_cast( static_cast(*this).find_item(names))); } /// Find the index number for the specified \p 'item' /// in the current item's list of children. /// /// \returns the index, or -1 if not found. /// int Fl_Tree_Item::find_child(Fl_Tree_Item *item) { for ( int t=0; tlabel(new_label); } recalc_tree(); // may change tree geometry item->_parent = this; switch ( prefs.sortorder() ) { case FL_TREE_SORT_NONE: { _children.add(item); return(item); } case FL_TREE_SORT_ASCENDING: { for ( int t=0; t<_children.total(); t++ ) { Fl_Tree_Item *c = _children[t]; if ( c->label() && strcmp(c->label(), new_label) > 0 ) { _children.insert(t, item); return(item); } } _children.add(item); return(item); } case FL_TREE_SORT_DESCENDING: { for ( int t=0; t<_children.total(); t++ ) { Fl_Tree_Item *c = _children[t]; if ( c->label() && strcmp(c->label(), new_label) < 0 ) { _children.insert(t, item); return(item); } } _children.add(item); return(item); } } return(item); } /// Descend into the path specified by \p 'arr', and add a new child there. /// Should be used only by Fl_Tree's internals. /// Adds the item based on the value of prefs.sortorder(). /// \returns the item added. /// \version 1.3.0 release /// Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, char **arr) { return add(prefs, arr, 0); } /// Descend into path specified by \p 'arr' and add \p 'newitem' there. /// Should be used only by Fl_Tree's internals. /// If item is NULL, a new item is created. /// Adds the item based on the value of prefs.sortorder(). /// \returns the item added. /// \version 1.3.3 ABI feature /// Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, char **arr, Fl_Tree_Item *newitem) { if ( !*arr ) return 0; // See if we can find an existing child with name requested. Fl_Tree_Item *child = find_child_item(*arr); if ( child ) { // Child found? if ( *(arr+1) == 0 ) { // ..and at end of path? if ( !newitem ) { // ..and no item specified? return 0; // ..error: child exists already } else { // Child found, end of path, item specified return child->add(prefs, newitem->label(), newitem); } } // Child found: more path elements to go or item specified? // Descend into child to handle add.. return child->add(prefs, arr+1, newitem); // recurse } // No child found, see if we reached end of path. // If so, add as an immediate child, done if ( *(arr+1) == 0 ) // end of path? return add(prefs, *arr, newitem); // add as immediate child // No child found, but more to path? // If so, create new child to handle add() Fl_Tree_Item *newchild; return (newchild=add(prefs, *arr)) // create new immediate child ? newchild->add(prefs,arr+1,newitem) // it worked? recurse to add : 0; // failed? error } /** Insert a new item named \p 'new_label' into current item's children at a specified position \p 'pos'. If \p pos is out of range the new item is - prepended if \p pos \< 0 or - appended if \p pos \> item->children(). \returns the new item inserted \see Fl_Tree::insert() */ Fl_Tree_Item *Fl_Tree_Item::insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos) { (void) prefs; // quiet warnings unused params Fl_Tree_Item *item = new Fl_Tree_Item(_tree); item->label(new_label); item->_parent = this; _children.insert(pos, item); recalc_tree(); // may change tree geometry return(item); } /// Insert a new item named \p 'new_label' above this item. /// \returns the new item inserted, or 0 if an error occurred. /// Fl_Tree_Item *Fl_Tree_Item::insert_above(const Fl_Tree_Prefs &prefs, const char *new_label) { Fl_Tree_Item *p = _parent; if ( ! p ) return(0); // Walk our parent's children to find ourself for ( int t=0; tchildren(); t++ ) { Fl_Tree_Item *c = p->child(t); if ( this == c ) { return(p->insert(prefs, new_label, t)); } } return(0); } /// Deparent child at index position \p 'pos'. /// This creates an "orphaned" item that is still allocated, /// but has no parent or siblings. Normally the caller would /// want to immediately reparent the orphan elsewhere. /// /// A successfully orphaned item will have its parent() /// and prev_sibling()/next_sibling() set to NULL. /// /// \returns /// - pointer to orphaned item on success /// - NULL on error (could not deparent the item) /// \see reparent() /// Fl_Tree_Item* Fl_Tree_Item::deparent(int pos) { Fl_Tree_Item *orphan = _children[pos]; if ( _children.deparent(pos) < 0 ) return NULL; return orphan; } /// Reparent specified item as a child of ourself at position \p 'pos'. /// Typically \p 'newchild' was recently orphaned with deparent(). /// /// \returns /// - 0: on success /// - -1: on error (e.g. if \p 'pos' out of range) with no changes made. /// \see deparent() /// int Fl_Tree_Item::reparent(Fl_Tree_Item *newchild, int pos) { int ret; if ( (ret = _children.reparent(newchild, this, pos)) < 0 ) return ret; newchild->parent(this); // take custody return 0; } /// Move an item within its parent using index numbers. /// Item is moved \p 'to' its new position \p 'from' its old position. /// /// \returns /// - 0: Success /// - -1: range error (e.g. if \p 'to' or \p 'from' out of range). /// - (Other return values reserved for future use) /// \see move_above(), move_below(), move_into(), move(Fl_Tree_Item*,int,int) /// int Fl_Tree_Item::move(int to, int from) { return _children.move(to, from); } /// Move the current item above/below/into the specified \p 'item', /// where \p 'op' determines the type of move: /// /// - 0: move above \p 'item' (\p 'pos' ignored) /// - 1: move below \p 'item' (\p 'pos' ignored) /// - 2: move into \p 'item' as a child (at optional position \p 'pos') /// /// ..and \p 'pos' determines an optional index position after the move. /// /// \returns 0 on success. a negative number on error: /// - -1: one of the items has no parent /// - -2: item's index could not be determined /// - -3: bad 'op' /// - -4: index range error /// - -5: could not deparent /// - -6: could not reparent at \p 'pos' /// - (Other return values reserved for future use.) /// /// \see move_above(), move_below(), move_into(), move(int,int) /// int Fl_Tree_Item::move(Fl_Tree_Item *item, int op, int pos) { Fl_Tree_Item *from_parent, *to_parent; int from, to; switch (op) { case 0: // "above" from_parent = this->parent(); to_parent = item->parent(); if ( !from_parent || !to_parent ) return -1; from = from_parent->find_child(this); to = to_parent->find_child(item); break; case 1: // "below" from_parent = this->parent(); to_parent = item->parent(); if ( !from_parent || !to_parent ) return -1; from = from_parent->find_child(this); to = to_parent->find_child(item); break; case 2: // "into" from_parent = this->parent(); if ( !from_parent ) return -1; to_parent = item; from = from_parent->find_child(this); to = pos; break; default: return -3; } if ( !from_parent || !to_parent ) return -1; if ( from < 0 || to < 0 ) return -2; if ( from_parent == to_parent ) { // same parent? switch (op) { // 'to' offsets due to scroll case 0: if ( from < to && to > 0 ) --to; break; case 1: if ( from > to && to < to_parent->children() ) ++to; break; } if ( from_parent->move(to, from) < 0 ) // simple move among siblings return -4; } else { // different parent? if ( to > to_parent->children() ) // try to prevent a reparent() error return -4; if ( from_parent->deparent(from) == NULL ) // deparent self from current parent return -5; if ( to_parent->reparent(this, to) < 0 ) { // reparent self to new parent at position 'to' to_parent->reparent(this, 0); // failed? shouldn't happen, reparent at 0 return -6; } } return 0; } /// Move the current item above the specified \p 'item'. /// This is the equivalent of calling move(item,0,0). /// /// \returns 0 on success.
/// On error returns a negative value; /// see move(Fl_Tree_Item*,int,int) for possible error codes. /// /// \see move_below(), move_into(), move(int,int), move(Fl_Tree_Item*,int,int) /// int Fl_Tree_Item::move_above(Fl_Tree_Item *item) { return move(item, 0, 0); } /// Move the current item below the specified \p 'item'. /// This is the equivalent of calling move(item,1,0). /// /// \returns 0 on success.
/// On error returns a negative value; /// see move(Fl_Tree_Item*,int,int) for possible error codes. /// /// \see move_above(), move_into(), move(int,int), move(Fl_Tree_Item*,int,int) /// int Fl_Tree_Item::move_below(Fl_Tree_Item *item) { return move(item, 1, 0); } /// Parent the current item as a child of the specified \p 'item'. /// This is the equivalent of calling move(item,2,pos). /// /// \returns 0 on success.
/// On error returns a negative value; /// see move(Fl_Tree_Item*,int,int) for possible error codes. /// /// \see move_above(), move_below(), move(int,int), move(Fl_Tree_Item*,int,int) /// int Fl_Tree_Item::move_into(Fl_Tree_Item *item, int pos) { return move(item, 2, pos); } /// Return the parent tree's prefs. /// \returns a reference to the parent tree's Fl_Tree_Prefs /// \version 1.3.3 ABI feature /// const Fl_Tree_Prefs& Fl_Tree_Item::prefs() const { return(_tree->_prefs); } /// Replace the current item with a new item. /// /// The current item is destroyed if successful. /// No checks are made to see if an item with the same name exists. /// /// This method can be used to, for example, install 'custom' items /// into the tree derived from Fl_Tree_Item; see draw_item_content(). /// /// \param[in] newitem The new item to replace the current item /// \returns newitem on success, NULL if could not be replaced. /// \see Fl_Tree_Item::draw_item_content(), Fl_Tree::root(Fl_Tree_Item*) /// \version 1.3.3 ABI feature /// Fl_Tree_Item *Fl_Tree_Item::replace(Fl_Tree_Item *newitem) { Fl_Tree_Item *p = parent(); if ( !p ) { // no parent? then we're the tree's root.. _tree->root(newitem); // ..tell tree to replace root return newitem; } // has parent? ask parent to replace us return p->replace_child(this, newitem); } /// Replace existing child \p 'olditem' with \p 'newitem'. /// /// The \p 'olditem' is destroyed if successful. /// Can be used to put custom items (derived from Fl_Tree_Item) into the tree. /// No checks are made to see if an item with the same name exists. /// /// \param[in] olditem The item to be found and replaced /// \param[in] newitem The new item to take the place of \p 'olditem' /// \returns newitem on success and \p 'olditem' is destroyed. /// NULL on error if \p 'olditem' was not found /// as an immediate child. /// \see replace(), Fl_Tree_Item::draw() /// \version 1.3.3 ABI feature /// Fl_Tree_Item *Fl_Tree_Item::replace_child(Fl_Tree_Item *olditem, Fl_Tree_Item *newitem) { int pos = find_child(olditem); // find our index for olditem if ( pos == -1 ) return(NULL); newitem->_parent = this; // replace in array (handles stitching neighboring items) _children.replace(pos, newitem); recalc_tree(); // newitem may have changed tree geometry return newitem; } /// Remove \p 'item' from the current item's children. /// \returns 0 if removed, -1 if item not an immediate child. /// int Fl_Tree_Item::remove_child(Fl_Tree_Item *item) { for ( int t=0; tclear_children(); _children.remove(t); recalc_tree(); // may change tree geometry return(0); } } return(-1); } /// Remove immediate child (and its children) by its label \p 'name'. /// If more than one item matches \p 'name', only the first /// matching item is removed. /// \param[in] name The label name of the immediate child to remove /// \returns 0 if removed, -1 if not found. /// \version 1.3.3 /// int Fl_Tree_Item::remove_child(const char *name) { for ( int t=0; tlabel() ) { if ( strcmp(child(t)->label(), name) == 0 ) { _children.remove(t); recalc_tree(); // may change tree geometry return(0); } } } return(-1); } /// Swap two of our children, given two child index values \p 'ax' and \p 'bx'. /// Use e.g. for sorting.
/// This method is FAST, and does not involve lookups.
/// No range checking is done on either index value. /// \param[in] ax,bx the index of the items to swap /// void Fl_Tree_Item::swap_children(int ax, int bx) { _children.swap(ax, bx); } /// Swap two of our immediate children, given item pointers. /// Use e.g. for sorting. /// /// This method is SLOW because it involves linear lookups.
/// For speed, use swap_children(int,int) instead. /// /// \param[in] a,b The item ptrs of the two items to swap. /// Both must be immediate children of the current item. /// \returns /// - 0 : OK /// - -1 : failed: item \p 'a' or \p 'b' is not our child. /// int Fl_Tree_Item::swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b) { int ax = -1, bx = -1; for ( int t=0; t= _xywh[1] && Fl::event_y() <= (_xywh[1]+_xywh[3]) ) { return(this); } } else { if ( event_inside(_xywh) ) { // event within this item? return(this); // found } } } if ( is_open() ) { // open? check children of this item for ( int t=0; tfind_clicked(prefs, yonly)) != NULL) // recurse into child for descendents return(item); // found? } } return(0); } /// Non-const version of Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs&,int) const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly) { // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. return(const_cast( static_cast(*this).find_clicked(prefs, yonly))); } /// Return the item's 'visible' height. Takes into account the item's: /// - visibility (if !is_visible(), returns 0) /// - labelfont() height: if label() != NULL /// - widget() height: if widget() != NULL /// - openicon() height (if has children) /// - usericon() height (if not NULL) /// Does NOT include Fl_Tree::linespacing(); /// \returns maximum pixel height /// int Fl_Tree_Item::calc_item_height(const Fl_Tree_Prefs &prefs) const { if ( ! is_visible() ) return(0); int H = 0; if ( _label ) { fl_font(_labelfont, _labelsize); // fl_descent() needs this :/ H = _labelsize + fl_descent() + 1; // at least one pixel space below descender } if ( widget() && (prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET) && H < widget()->h()) { H = widget()->h(); } if ( has_children() && H < prefs.openicon_h() ) H = prefs.openicon_h(); if ( usericon() && Hh() ) H = usericon()->h(); return(H); } // These methods held for 1.3.3 ABI: all need 'tree()' back-reference. /// Returns the recommended foreground color used for drawing this item. /// \see draw_item_content() /// \version 1.3.3 ABI ABI /// Fl_Color Fl_Tree_Item::drawfgcolor() const { return is_selected() ? fl_contrast(_labelfgcolor, tree()->selection_color()) : (is_active() && tree()->active_r()) ? _labelfgcolor : fl_inactive(_labelfgcolor); } /// Returns the recommended background color used for drawing this item. /// \see draw_item_content() /// \version 1.3.3 ABI /// Fl_Color Fl_Tree_Item::drawbgcolor() const { const Fl_Color unspecified = 0xffffffff; return is_selected() ? is_active() && tree()->active_r() ? tree()->selection_color() : fl_inactive(tree()->selection_color()) : _labelbgcolor == unspecified ? tree()->color() : _labelbgcolor; } /// Draw the item content /// /// This method can be overridden to implement custom drawing /// by filling the label_[xywh]() area with content. /// /// A minimal example of how to override draw_item_content() /// and draw just a normal item's background and label ourselves: /// /// \code /// class MyTreeItem : public Fl_Tree_Item { /// public: /// MyTreeItem() { } /// ~MyTreeItem() { } /// // DRAW OUR CUSTOM CONTENT FOR THE ITEM /// int draw_item_content(int render) { /// // Our item's dimensions + text content /// int X=label_x(), Y=label_y(), W=label_w(), H=label_h(); /// const char *text = label() ? label() : ""; /// // Rendering? Do any drawing that's needed /// if ( render ) { /// // Draw bg -- a filled rectangle /// fl_color(drawbgcolor()); fl_rectf(X,Y,W,H); /// // Draw label /// fl_font(labelfont(), labelsize()); // use item's label font/size /// fl_color(drawfgcolor()); // use recommended fg color /// fl_draw(text, X,Y,W,H, FL_ALIGN_LEFT); // draw the item's label /// } /// // Rendered or not, we must calculate content's max X position /// int lw=0, lh=0; /// fl_measure(text, lw, lh); // get width of label text /// return X + lw; // return X + label width /// } /// }; /// \endcode /// /// You can draw anything you want inside draw_item_content() /// using any of the fl_draw.H functions, as long as it's /// within the label's xywh area. /// /// To add instances of your custom item to the tree, you can use: /// /// \code /// // Example #1: using add() /// MyTreeItem *bart = new MyTreeItem(..); // class derived from Fl_Tree_Item /// tree->add("/Simpsons/Bart", bart); // Add item as /Simpsons/Bart /// \endcode /// /// ..or you can insert or replace existing items: /// /// \code /// // Example #2: using replace() /// MyTreeItem *marge = new MyTreeItem(..); // class derived from Fl_Tree_Item /// item = tree->add("/Simpsons/Marge"); // create item /// item->replace(mi); // replace it with our own /// \endcode /// /// \param[in] render Whether we should render content (1), or just tally /// the geometry (0). Fl_Tree may want only to find the widest /// item in the tree for scrollbar calculations. /// /// \returns the right-most X coordinate, or 'xmax' of content we drew, /// i.e. the "scrollable" content. /// The tree uses the largest xmax to determine the maximum /// width of the tree's content (needed for e.g. computing the /// horizontal scrollbar's size). /// \version 1.3.3 ABI feature /// int Fl_Tree_Item::draw_item_content(int render) { Fl_Color fg = drawfgcolor(); Fl_Color bg = drawbgcolor(); const Fl_Tree_Prefs &prefs = tree()->prefs(); int xmax = label_x(); // Background for this item, only if different from tree's bg if ( render && (bg != tree()->color() || is_selected()) ) { if ( is_selected() ) { // Selected? Use selectbox() style fl_draw_box(prefs.selectbox(), label_x(), label_y(), label_w(), label_h(), bg); } else { // Not Selected? use plain filled rectangle fl_color(bg); fl_rectf(label_x(), label_y(), label_w(), label_h()); } if ( widget() ) widget()->damage(FL_DAMAGE_ALL); // if there's a child widget, we just damaged it } // Draw label if ( _label && ( !widget() || (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) ) { if ( render ) { fl_color(fg); fl_font(_labelfont, _labelsize); } int lx = label_x()+(_label ? prefs.labelmarginleft() : 0); int ly = label_y()+(label_h()/2)+(_labelsize/2)-fl_descent()/2; int lw=0, lh=0; fl_measure(_label, lw, lh); // get box around text (including white space) if ( render ) fl_draw(_label, lx, ly); xmax = lx + lw; // update max width of drawn item } return xmax; } /// Draw this item and its children. /// /// \param[in] X Horizontal position for item being drawn /// \param[in,out] Y Vertical position for item being drawn, /// returns new position for next item /// \param[in] W Recommended width for item /// \param[in] itemfocus The tree's current focus item (if any) /// \param[in,out] tree_item_xmax The tree's running xmax (right-most edge so far). /// Mainly used by parent tree when render==0 to /// calculate tree's max width. /// \param[in] lastchild Is this item the last child in a subtree? /// \param[in] render Whether or not to render the item: /// 0: no rendering, just calculate size w/out drawing. /// 1: render item as well as size calc /// /// \version 1.3.3 ABI feature: modified parameters /// void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Tree_Item *itemfocus, int &tree_item_xmax, int lastchild, int render) { Fl_Tree_Prefs &prefs = _tree->_prefs; if ( !is_visible() ) return; int tree_top = tree()->_tiy; int tree_bot = tree_top + tree()->_tih; int H = calc_item_height(prefs); // height of item int H2 = H + prefs.linespacing(); // height of item with line spacing // Update the xywh of this item _xywh[0] = X; _xywh[1] = Y; _xywh[2] = W; _xywh[3] = H; // Determine collapse icon's xywh // Note: calculate collapse icon's xywh for possible mouse click detection. // We don't care about items clipped off the viewport; they won't get mouse events. // int item_y_center = (Y+(H/2))|1; // |1: force alignment w/dot pattern _collapse_xywh[2] = prefs.openicon_w(); int &icon_w = _collapse_xywh[2]; _collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 3; int &icon_x = _collapse_xywh[0]; _collapse_xywh[1] = item_y_center - prefs.openicon_h()/2; int &icon_y = _collapse_xywh[1]; _collapse_xywh[3] = prefs.openicon_h(); // Horizontal connector values // Must calculate these even if(clipped) because 'draw children' code (below) // needs hconn_x_center value. (Otherwise, these calculations could be 'clipped') // int hconn_x = X+icon_w/2-1; int hconn_x2 = hconn_x + prefs.connectorwidth(); int hconn_x_center = X + icon_w + ((hconn_x2 - (X + icon_w)) / 2); int cw1 = icon_w+prefs.connectorwidth()/2, cw2 = prefs.connectorwidth(); int conn_w = cw1>cw2 ? cw1 : cw2; // Usericon position int uicon_x = X+(icon_w/2-1+conn_w) + ( (usericon() || prefs.usericon()) ? prefs.usericonmarginleft() : 0); int uicon_w = usericon() ? usericon()->w() : prefs.usericon() ? prefs.usericon()->w() : 0; // Label xywh _label_xywh[0] = uicon_x + uicon_w + prefs.labelmarginleft(); _label_xywh[1] = Y; _label_xywh[2] = tree()->_tix + tree()->_tiw - _label_xywh[0]; _label_xywh[3] = H; // Begin calc of this item's max width.. // It might not even be visible, so start at zero. // int xmax = 0; // Recalc widget position // Do this whether clipped or not, so that when scrolled, // the widgets move to appropriate 'offscreen' positions // (so that they don't get mouse events, etc) // if ( widget() ) { int wx = uicon_x + uicon_w + (_label ? prefs.labelmarginleft() : 0); int wy = label_y(); int ww = widget()->w(); // use widget's width int wh = (prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET) ? widget()->h() : H; if ( _label && (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) { fl_font(_labelfont, _labelsize); // fldescent() needs this int lw=0, lh=0; fl_measure(_label,lw,lh); // get box around text (including white space) wx += (lw + prefs.widgetmarginleft()); } if ( widget()->x() != wx || widget()->y() != wy || widget()->w() != ww || widget()->h() != wh ) { widget()->resize(wx,wy,ww,wh); // we'll handle redraw below } } char clipped = ((Y+H) < tree_top) || (Y>tree_bot) ? 1 : 0; if (!render) clipped = 0; // NOT rendering? Then don't clip, so we calc unclipped items char active = (is_active() && tree()->active_r()) ? 1 : 0; char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1; if ( !clipped ) { Fl_Color fg = drawfgcolor(); Fl_Color bg = drawbgcolor(); // See if we should draw this item // If this item is root, and showroot() is disabled, don't draw. // 'clipped' is an optimization to prevent drawing anything offscreen. // if ( drawthis ) { // draw this item at all? if ( (tree()->damage() & ~FL_DAMAGE_CHILD) || !render ) { // non-child damage? // Draw connectors if ( render && prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) { // Horiz connector to center of icon draw_horizontal_connector(hconn_x, hconn_x_center, item_y_center, prefs); // Small vertical line down to children if ( has_children() && is_open() ) draw_vertical_connector(hconn_x_center, item_y_center, Y+H2, prefs); // Connectors for last child if ( !is_root() ) { if ( lastchild ) draw_vertical_connector(hconn_x, Y, item_y_center, prefs); else draw_vertical_connector(hconn_x, Y, Y+H2, prefs); } } // Draw collapse icon if ( render && has_children() && prefs.showcollapse() ) { // Draw icon image if ( is_open() ) { if ( prefs.closeicon() ) { if ( active ) prefs.closeicon()->draw(icon_x, icon_y); else prefs.closedeicon()->draw(icon_x, icon_y); } else { Fl::system_driver()->tree_draw_expando_button(icon_x, icon_y, false, active); } } else { if ( prefs.openicon() ) { if ( active ) prefs.openicon()->draw(icon_x, icon_y); else prefs.opendeicon()->draw(icon_x, icon_y); } else { Fl::system_driver()->tree_draw_expando_button(icon_x, icon_y, true, active); } } } // Draw user icon (if any) if ( render && usericon() ) { // Item has user icon? Use it int uicon_y = item_y_center - (usericon()->h() >> 1); if ( active ) usericon()->draw(uicon_x,uicon_y); else if ( userdeicon() ) userdeicon()->draw(uicon_x,uicon_y); } else if ( render && prefs.usericon() ) { // Prefs has user icon? Use it int uicon_y = item_y_center - (prefs.usericon()->h() >> 1); if ( active ) prefs.usericon()->draw(uicon_x,uicon_y); else if ( prefs.userdeicon() ) prefs.userdeicon()->draw(uicon_x,uicon_y); } // Draw item's content xmax = draw_item_content(render); } // end non-child damage // Draw child FLTK widget? if ( widget() ) { if (render) tree()->draw_child(*widget()); // let group handle drawing child if ( widget()->label() && render ) tree()->draw_outside_label(*widget());// label too xmax = widget()->x() + widget()->w(); // update max width of widget } // Draw focus box around item's bg last if ( render && this == itemfocus && Fl::visible_focus() && Fl::focus() == tree() && prefs.selectmode() != FL_TREE_SELECT_NONE ) { fl_draw_box_focus(FL_NO_BOX, label_x()+1, label_y()+1, label_w()-1, label_h()-1, fg, bg); } } // end drawthis } // end clipped if ( drawthis ) Y += H2; // adjust Y (even if clipped) // Manage tree_item_xmax if ( xmax > tree_item_xmax ) tree_item_xmax = xmax; // Draw child items (if any) if ( has_children() && is_open() ) { int child_x = drawthis ? (hconn_x_center - (icon_w/2) + 1) // offset children to right, : X; // unless didn't drawthis int child_w = W - (child_x-X); int child_y_start = Y; for ( int t=0; tdraw(child_x, Y, child_w, itemfocus, tree_item_xmax, is_lastchild, render); } if ( has_children() && is_open() ) { Y += prefs.openchild_marginbottom(); // offset below open child tree } if ( ! lastchild ) { // Draw vertical connector between this item and the bottom of its children. // // o Aaa <- Item we're drawing has >20k children. // ytop → : :.. 0001 // : :.. 0002 // : : } ~20k items // : :.. 19998 // ┌──:──:.. 19999 ──┐ // │ : :.. 20000 │ // │ : :.. 20001 │ <- visible screen // │ : :.. 20002 │ area // └──:──:.. 20003 ──┘ // : :.. 20004 // : // ybot → : ← we're drawing this long vertical connector // : // o Bbb // int ytop = child_y_start; int ybot = Y; int is_clipped = ((ytop < tree_top) && (ybot < tree_top)) || // completely off top of scrn? clip ((ytop > tree_bot) && (ybot > tree_bot)); // completely off bot of scrn? clip if (render && !is_clipped ) { // Clip vert line to within screen area ytop = (ytop < tree_top) ? tree_top : ytop; ybot = (ybot > tree_bot) ? tree_bot : ybot; draw_vertical_connector(hconn_x, ytop, ybot, prefs); } } } } /// Was the event on the 'collapse' button of this item? /// int Fl_Tree_Item::event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const { if ( is_visible() && is_active() && has_children() && prefs.showcollapse() ) { return(event_inside(_collapse_xywh) ? 1 : 0); } else { return(0); } } /// Was the event on the 'user icon' of this item, if any? /// int Fl_Tree_Item::event_on_user_icon(const Fl_Tree_Prefs &prefs) const { // NOTE: Fl_Tree_Item doesn't keep an _xywh[] for usericon, but we can derive it as // by elimitation of all other possibilities. if ( !is_visible() ) return 0; // item not visible? not us if ( !event_inside(_xywh) ) return 0; // not inside item? not us if ( event_on_collapse_icon(prefs) ) return 0; // inside collapse icon? not us if ( Fl::event_x() >= _label_xywh[0] ) return 0; // inside label or beyond (e.g. widget())? not us // Is a user icon being shown? // TBD: Determining usericon xywh and 'if displayed' should be class methods used here and by draw_*() Fl_Image *ui = 0; if ( is_active() ) { if ( usericon() ) ui = usericon(); // user icon for item? else if ( prefs.usericon() ) ui = prefs.usericon(); // user icon for tree? } else { if ( userdeicon() ) ui = userdeicon(); // user deicon for this item? else if ( prefs.userdeicon() ) ui = prefs.userdeicon(); // user deicon for tree? } if ( !ui ) return 0; // no user icon? not us int uix = _label_xywh[0]-ui->w(); // find x position of usericon if ( Fl::event_x() < uix ) return 0; // event left of usericon? not us return 1; // must be inside usericon by elimination } /// Was event anywhere on the item? int Fl_Tree_Item::event_on_item(const Fl_Tree_Prefs &prefs) const { (void) prefs; // quiet warnings unused params return(event_inside(_xywh) ? 1 : 0); } /// Was event on the label() of this item? int Fl_Tree_Item::event_on_label(const Fl_Tree_Prefs &prefs) const { (void) prefs; // quiet warnings unused params if ( is_visible() && is_active() ) { return(event_inside(_label_xywh) ? 1 : 0); } else { return(0); } } /// Internal: Show the FLTK widget() for this item and all children. /// Used by open() to re-show widgets that were hidden by a previous close() /// void Fl_Tree_Item::show_widgets() { if ( _widget ) _widget->show(); if ( is_open() ) { for ( int t=0; t<_children.total(); t++ ) { _children[t]->show_widgets(); } } } /// Internal: Hide the FLTK widget() for this item and all children. /// Used by close() to hide widgets. /// void Fl_Tree_Item::hide_widgets() { if ( _widget ) _widget->hide(); for ( int t=0; t<_children.total(); t++ ) { _children[t]->hide_widgets(); } } /// Open this item and all its children. void Fl_Tree_Item::open() { set_flag(OPEN,1); // Tell children to show() their widgets for ( int t=0; t<_children.total(); t++ ) { _children[t]->show_widgets(); } recalc_tree(); // may change tree geometry } /// Close this item and all its children. void Fl_Tree_Item::close() { set_flag(OPEN,0); // Tell children to hide() their widgets for ( int t=0; t<_children.total(); t++ ) { _children[t]->hide_widgets(); } recalc_tree(); // may change tree geometry } /// Returns how many levels deep this item is in the hierarchy. /// /// For instance; root has a depth of zero, and its immediate children /// would have a depth of 1, and so on. Use e.g. for determining the /// horizontal indent of this item during drawing. /// int Fl_Tree_Item::depth() const { int count = 0; const Fl_Tree_Item *item = parent(); while ( item ) { ++count; item = item->parent(); } return(count); } /// Return the next item in the tree. /// /// This method can be used to walk the tree forward. /// For an example of how to use this method, see Fl_Tree::first(). /// /// \returns the next item in the tree, or 0 if there's no more items. /// Fl_Tree_Item *Fl_Tree_Item::next() { Fl_Tree_Item *p, *c = this; if ( c->has_children() ) { return(c->child(0)); } while ( ( p = c->parent() ) != NULL ) { // loop upwards through parents if ( c->_next_sibling ) // not last child? return(c->_next_sibling); // return next child c = p; // child becomes parent to move up generation } // loop: moves up to next parent return(0); // hit root? done } /// Return the previous item in the tree. /// /// This method can be used to walk the tree backwards. /// For an example of how to use this method, see Fl_Tree::last(). /// /// \returns the previous item in the tree, /// or 0 if there's no item above this one (hit the root). /// Fl_Tree_Item *Fl_Tree_Item::prev() { if ( !parent() ) return(0); // hit root? done if ( !_prev_sibling ) { // are we first child? return(parent()); // return parent } // Tricky: in the following example our current position // in the tree is 'j', and we need to move "up one" to 'i': // // ROOT // |-- a // b-- c // | d-- e // | | f // | | // | g-- h // | i // j // // We do this via b->g->i: // 1. Find j's prev_sibling (b) _ // 2. Find b's 'last child' (g) |_ while loop // 3. Find g's 'last child' (i) _| // Fl_Tree_Item *p = _prev_sibling; // focus on our prev sibling while ( p->has_children() ) { // item has children? p = p->child(p->children()-1); // descend hierarchy finding deepest 'last child' } return(p); } /// Return this item's next sibling. /// /// Moves to the next item below us at the same level (sibling). /// Use this to move down the tree without changing depth(). /// effectively skipping over this item's children/descendents. /// /// \returns item's next sibling, or 0 if none. /// Fl_Tree_Item *Fl_Tree_Item::next_sibling() { return(_next_sibling); } /// Return this item's previous sibling. /// /// Moves to the previous item above us at the same level (sibling). /// Use this to move up the tree without changing depth(). /// /// \returns This item's previous sibling, or 0 if none. /// Fl_Tree_Item *Fl_Tree_Item::prev_sibling() { return(_prev_sibling); } /// Update our _prev_sibling and _next_sibling pointers to point to neighbors /// given \p index as being our current position in the parent's item array. /// Call this whenever items in the array are added/removed/moved/swapped/etc. /// \param[in] index Our index# in the parent.
/// Special case if index=-1: become an orphan; null out all parent/sibling associations. /// void Fl_Tree_Item::update_prev_next(int index) { if ( index == -1 ) { // special case: become an orphan _parent = 0; _prev_sibling = 0; _next_sibling = 0; return; } int pchildren = parent() ? parent()->children() : 0; int index_prev = index-1; int index_next = index+1; // Get pointers to prev+next items Fl_Tree_Item *item_prev = (index_prev>=0)&&(index_prevchild(index_prev) : 0; Fl_Tree_Item *item_next = (index_next>=0)&&(index_nextchild(index_next) : 0; // Adjust our prev+next ptrs _prev_sibling = item_prev; _next_sibling = item_next; // Adjust neighbors to point to us if ( item_prev ) item_prev->_next_sibling = this; if ( item_next ) item_next->_prev_sibling = this; } /// Return the next open(), visible() item. /// (If this item has children and is closed, children are skipped) /// /// This method can be used to walk the tree forward, skipping items /// that are not currently open/visible to the user. /// /// \returns the next open() visible() item below us, /// or 0 if there's no more items. /// \version 1.3.3 /// Fl_Tree_Item *Fl_Tree_Item::next_visible(Fl_Tree_Prefs &prefs) { Fl_Tree_Item *item = this; while ( 1 ) { item = item->next(); if ( !item ) return 0; if ( item->is_root() && !prefs.showroot() ) continue; if ( item->visible_r() ) return(item); } } /// Same as next_visible(). /// \deprecated in 1.3.3 for confusing name, use next_visible() instead Fl_Tree_Item *Fl_Tree_Item::next_displayed(Fl_Tree_Prefs &prefs) { return next_visible(prefs); } /// Return the previous open(), visible() item. /// (If this item above us has children and is closed, its children are skipped) /// /// This method can be used to walk the tree backward, /// skipping items that are not currently open/visible to the user. /// /// \returns the previous open() visible() item above us, /// or 0 if there's no more items. /// Fl_Tree_Item *Fl_Tree_Item::prev_visible(Fl_Tree_Prefs &prefs) { Fl_Tree_Item *c = this; while ( c ) { c = c->prev(); // previous item if ( !c ) break; // no more items? done if ( c->is_root() ) // root return((prefs.showroot()&&c->visible()) ? c : 0); // return root if visible if ( !c->visible() ) continue; // item not visible? skip // Check all parents to be sure none are closed. // If closed, move up to that level and repeat until sure none are closed. Fl_Tree_Item *p = c->parent(); while (1) { if ( !p || p->is_root() ) return(c); // hit top? then we're displayed, return c if ( p->is_close() ) c = p; // found closed parent? make it current p = p->parent(); // continue up tree } } return(0); // hit end: no more items } /// Same as prev_visible(). /// \deprecated in 1.3.3 for confusing name, use prev_visible() /// Fl_Tree_Item *Fl_Tree_Item::prev_displayed(Fl_Tree_Prefs &prefs) { return prev_visible(prefs); } /// See if item and all its parents are open() and visible(). /// \returns /// 1 -- item and its parents are open() and visible() /// 0 -- item or one of its parents are either not visible() or close()ed. /// int Fl_Tree_Item::is_visible_r() const { if ( !visible() ) return(0); for (const Fl_Tree_Item *p=parent(); p; p=p->parent())// move up through parents if (!p->visible() || p->is_close()) return(0); // any parent not visible or closed? return(1); } /// Call this when our geometry is changed. (Font size, label contents, etc) /// Schedules tree to recalculate itself, as changes to us may affect tree /// widget's scrollbar visibility and tab sizes. /// \version 1.3.3 ABI /// void Fl_Tree_Item::recalc_tree() { _tree->recalc_tree(); } fltk-1.4.3/src/freeglut_teapot_data.h0000644000175000017500000001555115004135251017736 0ustar albrechtalbrecht/* * freeglut_teapot_data.h * * The freeglut library teapot data include file. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef FREEGLUT_TEAPOT_DATA_H #define FREEGLUT_TEAPOT_DATA_H /* * Original teapot code copyright follows: */ /* * (c) Copyright 1993, Silicon Graphics, Inc. * * ALL RIGHTS RESERVED * * Permission to use, copy, modify, and distribute this software * for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that * both the copyright notice and this permission notice appear in * supporting documentation, and that the name of Silicon * Graphics, Inc. not be used in advertising or publicity * pertaining to distribution of the software without specific, * written prior permission. * * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU * "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR * OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO * EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE * ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER, * INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE, * SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR * NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY * OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR * PERFORMANCE OF THIS SOFTWARE. * * US Government Users Restricted Rights * * Use, duplication, or disclosure by the Government is subject to * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph * (c)(1)(ii) of the Rights in Technical Data and Computer * Software clause at DFARS 252.227-7013 and/or in similar or * successor clauses in the FAR or the DOD or NASA FAR * Supplement. Unpublished-- rights reserved under the copyright * laws of the United States. Contractor/manufacturer is Silicon * Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA * 94039-7311. * * OpenGL(TM) is a trademark of Silicon Graphics, Inc. */ /* * Rim, body, lid, and bottom data must be reflected in x and y; * handle and spout data across the y axis only. */ static int patchdata[][16] = { { 102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, /* rim */ { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }, /* body */ { 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 }, { 96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3 }, /* lid */ { 0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117 }, { 118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37 }, /* bottom */ { 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 }, /* handle */ { 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 28, 65, 66, 67 }, { 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83 }, /* spout */ { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95 } }; static double cpdata[][3] = { {0.2, 0, 2.7}, {0.2, -0.112, 2.7}, {0.112, -0.2, 2.7}, {0, -0.2, 2.7}, {1.3375, 0, 2.53125}, {1.3375, -0.749, 2.53125}, {0.749, -1.3375, 2.53125}, {0, -1.3375, 2.53125}, {1.4375, 0, 2.53125}, {1.4375, -0.805, 2.53125}, {0.805, -1.4375, 2.53125}, {0, -1.4375, 2.53125}, {1.5, 0, 2.4}, {1.5, -0.84, 2.4}, {0.84, -1.5, 2.4}, {0, -1.5, 2.4}, {1.75, 0, 1.875}, {1.75, -0.98, 1.875}, {0.98, -1.75, 1.875}, {0, -1.75, 1.875}, {2, 0, 1.35}, {2, -1.12, 1.35}, {1.12, -2, 1.35}, {0, -2, 1.35}, {2, 0, 0.9}, {2, -1.12, 0.9}, {1.12, -2, 0.9}, {0, -2, 0.9}, {-2, 0, 0.9}, {2, 0, 0.45}, {2, -1.12, 0.45}, {1.12, -2, 0.45}, {0, -2, 0.45}, {1.5, 0, 0.225}, {1.5, -0.84, 0.225}, {0.84, -1.5, 0.225}, {0, -1.5, 0.225}, {1.5, 0, 0.15}, {1.5, -0.84, 0.15}, {0.84, -1.5, 0.15}, {0, -1.5, 0.15}, {-1.6, 0, 2.025}, {-1.6, -0.3, 2.025}, {-1.5, -0.3, 2.25}, {-1.5, 0, 2.25}, {-2.3, 0, 2.025}, {-2.3, -0.3, 2.025}, {-2.5, -0.3, 2.25}, {-2.5, 0, 2.25}, {-2.7, 0, 2.025}, {-2.7, -0.3, 2.025}, {-3, -0.3, 2.25}, {-3, 0, 2.25}, {-2.7, 0, 1.8}, {-2.7, -0.3, 1.8}, {-3, -0.3, 1.8}, {-3, 0, 1.8}, {-2.7, 0, 1.575}, {-2.7, -0.3, 1.575}, {-3, -0.3, 1.35}, {-3, 0, 1.35}, {-2.5, 0, 1.125}, {-2.5, -0.3, 1.125}, {-2.65, -0.3, 0.9375}, {-2.65, 0, 0.9375}, {-2, -0.3, 0.9}, {-1.9, -0.3, 0.6}, {-1.9, 0, 0.6}, {1.7, 0, 1.425}, {1.7, -0.66, 1.425}, {1.7, -0.66, 0.6}, {1.7, 0, 0.6}, {2.6, 0, 1.425}, {2.6, -0.66, 1.425}, {3.1, -0.66, 0.825}, {3.1, 0, 0.825}, {2.3, 0, 2.1}, {2.3, -0.25, 2.1}, {2.4, -0.25, 2.025}, {2.4, 0, 2.025}, {2.7, 0, 2.4}, {2.7, -0.25, 2.4}, {3.3, -0.25, 2.4}, {3.3, 0, 2.4}, {2.8, 0, 2.475}, {2.8, -0.25, 2.475}, {3.525, -0.25, 2.49375}, {3.525, 0, 2.49375}, {2.9, 0, 2.475}, {2.9, -0.15, 2.475}, {3.45, -0.15, 2.5125}, {3.45, 0, 2.5125}, {2.8, 0, 2.4}, {2.8, -0.15, 2.4}, {3.2, -0.15, 2.4}, {3.2, 0, 2.4}, {0, 0, 3.15}, {0.8, 0, 3.15}, {0.8, -0.45, 3.15}, {0.45, -0.8, 3.15}, {0, -0.8, 3.15}, {0, 0, 2.85}, {1.4, 0, 2.4}, {1.4, -0.784, 2.4}, {0.784, -1.4, 2.4}, {0, -1.4, 2.4}, {0.4, 0, 2.55}, {0.4, -0.224, 2.55}, {0.224, -0.4, 2.55}, {0, -0.4, 2.55}, {1.3, 0, 2.55}, {1.3, -0.728, 2.55}, {0.728, -1.3, 2.55}, {0, -1.3, 2.55}, {1.3, 0, 2.4}, {1.3, -0.728, 2.4}, {0.728, -1.3, 2.4}, {0, -1.3, 2.4}, {0, 0, 0}, {1.425, -0.798, 0}, {1.5, 0, 0.075}, {1.425, 0, 0}, {0.798, -1.425, 0}, {0, -1.5, 0.075}, {0, -1.425, 0}, {1.5, -0.84, 0.075}, {0.84, -1.5, 0.075} }; static double tex[2][2][2] = { { {0.0, 0.0}, {1.0, 0.0} }, { {0.0, 1.0}, {1.0, 1.0} } }; #endif /* FREEGLUT_TEAPOT_DATA_H */ fltk-1.4.3/src/Fl_Terminal.cxx0000644000175000017500000047667715004135251016347 0ustar albrechtalbrecht// // Fl_Terminal - A terminal widget for Fast Light Tool Kit (FLTK). // // Copyright 2022 by Greg Ercolano. // Copyright 2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // TODO: double clicking text should make word selection, and drag should word-enlarge selection // TODO: Add JG's ScrollbarStyle option to vertical scrollbar // FIXME: While dragging a selection, hitting shift stops the selection // This must appear above #include #ifndef NDEBUG #define NDEBUG // comment out to enable assert() #endif #include // isdigit #include // malloc #include // strlen #include // vprintf, va_list #include #include #include #include // fl_utf8len1 #include #include #include "Fl_String.H" ///////////////////////////////// ////// Static Functions ///////// ///////////////////////////////// #define MIN(a,b) ((a)<=(b)) ? (a) : (b) // Return smaller of two values #define MAX(a,b) ((a)>=(b)) ? (a) : (b) // Return larger of two values #define ABS(a) ((a)<0) ? -(a) : (a) // Return abs value // Return val clamped between min and max static int clamp(int val, int min, int max) { return (valmax) ? max : val; } // Swap integer values a and b static void swap(int &a, int &b) { int asave = a; a = b; b = asave; } static int normalize(int row, int maxrows) { row = row % maxrows; if (row < 0) row = maxrows + row; // negative? index relative to end return row; } // Color channel management static int red(Fl_Color val) { return (val & 0xff000000) >> 24; } static int grn(Fl_Color val) { return (val & 0x00ff0000) >> 16; } static int blu(Fl_Color val) { return (val & 0x0000ff00) >> 8; } static Fl_Color rgb(int r,int g,int b) { return (r << 24) | (g << 16) | (b << 8); } // Return dim version of color 'val' static Fl_Color dim_color(Fl_Color val) { int r = clamp(red(val) - 0x20, 0, 255); int g = clamp(grn(val) - 0x20, 0, 255); int b = clamp(blu(val) - 0x20, 0, 255); //DEBUG ::printf("DIM COLOR: %08x -> %08x\n", val, rgb(r,g,b)); return rgb(r,g,b); } // Return bold version of color 'val' static Fl_Color bold_color(Fl_Color val) { int r = clamp(red(val) + 0x20, 0, 255); int g = clamp(grn(val) + 0x20, 0, 255); int b = clamp(blu(val) + 0x20, 0, 255); //DEBUG ::printf("BOLD COLOR: %08x -> %08x\n", val, rgb(r,g,b)); return rgb(r,g,b); } // Return an FLTK color for given XTERM foreground color index (0..7) Fl_Color Fl_Terminal::CharStyle::fltk_fg_color(uchar ci) { static const Fl_Color xterm_fg_colors_[] = { 0x00000000, // 0 0xd0000000, // 1 - red 0x00d00000, // 2 - grn 0xd0d00000, // 3 - yel 0x0000d000, // 4 - blu 0xd000d000, // 5 - mag 0x00d0d000, // 6 - cyn 0xd0d0d000 // 7 - white }; if (ci==39) return defaultfgcolor_; // special case for 'reset' color if (ci==49) return defaultbgcolor_; // special case for 'reset' color ci &= 0x07; // clamp to array size return xterm_fg_colors_[ci]; } // Return an FLTK color for the given background color index (0..7) and attribute. // Background colors should be just a little darker than // the fg colors to prevent too much brightness clashing // for 'normal' bg vs fg colors. // Fl_Color Fl_Terminal::CharStyle::fltk_bg_color(uchar ci) { static const Fl_Color xterm_bg_colors_[] = { 0x00000000, // 0 0xc0000000, // 1 - red 0x00c00000, // 2 - grn 0xc0c00000, // 3 - yel 0x0000c000, // 4 - blu 0xc000c000, // 5 - mag 0x00c0c000, // 6 - cyn 0xc0c0c000 // 7 - white }; if (ci==39) return defaultfgcolor_; // special case for 'reset' color if (ci==49) return defaultbgcolor_; // special case for 'reset' color ci &= 0x07; // clamp to array size return xterm_bg_colors_[ci]; } // See if an Fl_Boxtype is FL_XXX_FRAME static bool is_frame(Fl_Boxtype b) { if (b == FL_UP_FRAME || b == FL_DOWN_FRAME || b == FL_THIN_UP_FRAME || b == FL_THIN_DOWN_FRAME || b == FL_ENGRAVED_FRAME || b == FL_EMBOSSED_FRAME || b == FL_BORDER_FRAME) return true; return false; } /////////////////////////////////////// ////// Selection Class Methods //////// /////////////////////////////////////// // Ctor Fl_Terminal::Selection::Selection(Fl_Terminal *terminal) : terminal_(terminal) { // These are used to set/get the mouse selection srow_ = scol_ = erow_ = ecol_ = 0; // FL_PUSH event row/col push_clear(); selectionfgcolor_ = FL_BLACK; selectionbgcolor_ = FL_WHITE; state_ = 0; is_selection_ = false; } /** Return selection start/end. Ensures (start < end) to allow walking 'forward' thru selection, left-to-right, top-to-bottom. Returns: - true -- valid selection values returned - false -- no selection was made, returned values undefined */ bool Fl_Terminal::Selection::get_selection(int &srow,int &scol, int &erow,int &ecol) const { srow = srow_; scol = scol_; erow = erow_; ecol = ecol_; if (!is_selection_) return false; // Ensure (start < end) on return if (srow_ == erow_ && scol_ > ecol_) swap(scol, ecol); if (srow_ > erow_) { swap(srow, erow); swap(scol, ecol); } return true; } // Start new selection at specified row,col // Always returns true. // bool Fl_Terminal::Selection::start(int row, int col, bool char_right) { (void) char_right; // silence warning srow_ = erow_ = row; scol_ = ecol_ = col; state_ = 1; // state: "started selection" is_selection_ = true; return true; } // Extend existing selection to row,col // Returns true if anything changed, false if not. // bool Fl_Terminal::Selection::extend(int row, int col, bool char_right) { // no selection started yet? start and return true int osrow = srow_, oerow = erow_, oscol = scol_, oecol = ecol_; bool oselection = is_selection_; if (state_ == 0) return start(row, col, char_right); state_ = 2; // state: "extending selection" if ((row==push_row_) && (col+char_right==push_col_+push_char_right_)) { // we are in the box of the original push event srow_ = erow_ = row; scol_ = ecol_ = col; is_selection_ = false; } else if ((row>push_row_) || ((row==push_row_) && (col+char_right>push_col_+push_char_right_))) { // extend to the right and down scol_ = push_col_ + push_char_right_; ecol_ = col - 1 + char_right; is_selection_ = true; } else { // extend to the left and up scol_ = push_col_ - 1 + push_char_right_; ecol_ = col + char_right; is_selection_ = true; } if (scol_<0) scol_ = 0; if (ecol_<0) ecol_ = 0; int maxCol = terminal_->ring_cols()-1; if (scol_>maxCol) scol_ = maxCol; if (ecol_>maxCol) ecol_ = maxCol; srow_ = push_row_; erow_ = row; bool changed = ( (osrow != srow_) || (oerow != erow_) || (oscol != scol_) || (oecol != ecol_) || (oselection != is_selection_) ); return !changed; } // End selection (turn dragging() off) void Fl_Terminal::Selection::end(void) { state_ = 3; // state: "finished selection" // Order selection if (erow_ < srow_) { swap(srow_, erow_); swap(scol_, ecol_); } if (erow_ == srow_ && scol_ > ecol_) swap(scol_, ecol_); } // Create a complete selection void Fl_Terminal::Selection::select(int srow, int scol, int erow, int ecol) { srow_ = srow; scol_ = scol; erow_ = erow; ecol_ = ecol; state_ = 3; // state: "finished selection" is_selection_ = true; } // Clear selection // Returns true if there was a selection, false if there wasn't // bool Fl_Terminal::Selection::clear(void) { bool was_selected = is_selection(); // save for return srow_ = scol_ = erow_ = ecol_ = 0; state_ = 0; is_selection_ = false; return was_selected; } // Scroll the selection up(+)/down(-) number of rows void Fl_Terminal::Selection::scroll(int nrows) { if (is_selection()) { srow_ -= nrows; erow_ -= nrows; // Selection scrolled off? clear selection if (srow_ < 0 || erow_ < 0) clear(); } } /////////////////////////////////////// ////// EscapeSeq Class Methods //////// /////////////////////////////////////// // Append char to buff[] safely (with bounds checking) // Returns: // success - ok // fail - buffer full/overflow // int Fl_Terminal::EscapeSeq::append_buff(char c) { if (buffp_ >= buffendp_) return fail; // end of buffer reached? *buffp_++ = c; *buffp_ = 0; // keep buff[] null terminated return success; } // Append whatever integer string is at valbuffp into vals_[] safely w/bounds checking // Assumes valbuffp points to a null terminated string. // Returns: // success - parsed ok // fail - error occurred (non-integer, or vals_[] full) // int Fl_Terminal::EscapeSeq::append_val(void) { if (vali_ >= maxvals) // vals_[] full? { vali_ = maxvals-1; return fail; } // clamp index, fail if (!valbuffp_ || (*valbuffp_ == 0)) // no integer to parse? e.g. ESC[m, ESC[;m { vals_[vali_] = 0; return success; } // zero in array, do not inc vali if (sscanf(valbuffp_, "%d", &vals_[vali_]) != 1) // Parse integer into vals_[] { return fail; } // fail if parsed a non-integer vals_[vali_] &= 0x3ff; // sanity: enforce int in range 0 ~ 1023 (prevent DoS attack) if (++vali_ >= maxvals) // advance val index, fail if too many vals { vali_ = maxvals-1; return fail; } // clamp + fail valbuffp_ = 0; // parsed val ok, reset valbuffp to NULL return success; } // Ctor Fl_Terminal::EscapeSeq::EscapeSeq(void) { reset(); save_row_ = -1; // only in ctor save_col_ = -1; } // Reset the class // Named reset to not be confused with clear() screen/line/etc // void Fl_Terminal::EscapeSeq::reset(void) { esc_mode_ = 0; // disable ESC mode, so parse_in_progress() returns false csi_ = false; // CSI off until '[' received buffp_ = buff_; // point to beginning of buffer buffendp_ = buff_ + (maxbuff - 1); // point to end of buffer valbuffp_ = 0; // disable val ptr (no vals parsed yet) vali_ = 0; // zero val index buff_[0] = 0; // null terminate buffer vals_[0] = 0; // first val[] 0 memset(vals_, 0, sizeof(vals_)); } // Return current escape mode. // This is really only valid after parse() returns 'completed'. // After a reset() this will return 0. // char Fl_Terminal::EscapeSeq::esc_mode(void) const { return esc_mode_; } // Set current escape mode. void Fl_Terminal::EscapeSeq::esc_mode(char val) { esc_mode_ = val; } // Return the total vals parsed. // This is really only valid after parse() returns 'completed'. // int Fl_Terminal::EscapeSeq::total_vals(void) const { return vali_; } // Return the value at index i. // i is not range checked; it's assumed 0 <= i < total_vals(). // It is only valid to call this after parse() returns 'completed'. // int Fl_Terminal::EscapeSeq::val(int i) const { return vals_[i]; } // See if we're in the middle of parsing an ESC sequence bool Fl_Terminal::EscapeSeq::parse_in_progress(void) const { return (esc_mode_ == 0) ? false : true; } // See if we're in the middle of parsing an ESC sequence bool Fl_Terminal::EscapeSeq::is_csi(void) const { return csi_; } // Return with default value (if none) or vals[0] (if at least one val spec'd). // Handles default for single values (e.g. ESC[#H vs. ESC[H) // vals[0] is clamped between 0 and 'max' // int Fl_Terminal::EscapeSeq::defvalmax(int dval, int max) const { if (total_vals() == 0) return dval; else return clamp(vals_[0], 0, max); } // Save row,col for later retrieval void Fl_Terminal::EscapeSeq::save_cursor(int row, int col) { save_row_ = row; save_col_ = col; } // Restore last saved cursor position into row,col void Fl_Terminal::EscapeSeq::restore_cursor(int &row, int &col) { row = save_row_; col = save_col_; } // Handle parsing an escape sequence. // Call this only if parse_in_progress() is true. // Passing ESC does a reset() and sets esc_mode() to ESC. // When a full escape sequence has been parsed, 'completed' is returned (see below). // // Returns: // fail - error occurred: escape sequence invalid, class is reset() // success - parsing ESC sequence OK so far, still in progress/not done yet // completed - complete ESC sequence was parsed, esc_mode() will be the operation, e.g. // 'm' - [1m -- is_csi() will be true, val() has value(s) parsed // 'A' - A -- is_csi() will be false (no vals) // int Fl_Terminal::EscapeSeq::parse(char c) { // NOTE: During parsing esc_mode() will be: // 0 - reset/not parsing // 0x1b - ESC received, expecting next one of A/B/C/D or '[' // '[' - actively parsing CSI sequence, e.g. ESC[ // // At the /end/ of parsing, after 'completed' is returned, // esc_mode() will be the mode setting char, e.g. 'm' for 'ESC[0m', etc. // if (c == 0) { // NULL? (caller should really never send us this) return success; // do nothing -- leave state unchanged, return 'success' } else if (c == 0x1b) { // ESC at ANY time resets class/begins new ESC sequence reset(); esc_mode(0x1b); if (append_buff(c) < 0) goto pfail; // save ESC in buf return success; } else if (c < ' ' || c >= 0x7f) { // any other control or binary characters? goto pfail; // reset + fail out of esc sequence parsing } // Whatever the character is, handle it depending on esc_mode.. if (esc_mode() == 0x1b) { // in ESC mode? if (c == '[') { // [? CSI (Ctrl Seq Introducer) esc_mode(c); // switch to parsing mode for ESC[#;#;#.. csi_ = true; // this is now a CSI sequence vali_ = 0; // zero vals_[] index valbuffp_ = 0; // valbuffp NULL (no vals yet) if (append_buff(c) < 0) goto pfail; // save '[' in buf return success; // success } else if ((c >= '@' && c <= 'Z') || // C1 control code (e.g. D, c, etc) (c >= 'a' && c <= 'z')) { esc_mode(c); // save op in esc_mode() for caller to see csi_ = false; // NOT a CSI sequence vali_ = 0; valbuffp_ = 0; // valbuffp NULL (no vals yet) if (append_buff(c) < 0) goto pfail; // save op in buf return completed; // completed sequence } else { // ESCx? goto pfail; // not supported } } else if (esc_mode() == '[') { // '[' mode? e.g. ESC[... aka. is_csi() if (c == ';') { // ';' indicates end of a value, e.g. ESC[0;2.. if (append_val() < 0) goto pfail; // append value parsed so far, vali gets inc'ed if (append_buff(c) < 0) goto pfail; // save ';' in buf return success; } if (isdigit(c)) { // parsing an integer? if (!valbuffp_) // valbuffp not set yet? { valbuffp_ = buffp_; } // point to first char in integer string if (append_buff(c) < 0) goto pfail; // add value to buffer return success; } // Not a ; or digit? fall thru to [A-Z,a-z] check } else { // all other esc_mode() chars are fail/unknown goto pfail; } if (( c >= '@' && c<= 'Z') || // ESC#X or ESC[...X, where X is [A-Z,a-z]? ( c >= 'a' && c<= 'z')) { if (append_val() < 0 ) goto pfail; // append any trailing vals just before letter if (append_buff(c) < 0 ) goto pfail; // save letter in buffer esc_mode(c); // change mode to the mode setting char return completed; // completed/done } // Any other chars? reset+fail pfail: reset(); return fail; } ////////////////////////////////////// ///// CharStyle Class Methods //////// ////////////////////////////////////// // Ctor // fontsize_defer - if true, hold off on doing fl_font() oriented calculations until // just before draw(). This is for fluid's headless mode. (issue 837) // Fl_Terminal::CharStyle::CharStyle(bool fontsize_defer) { attrib_ = 0; charflags_ = (FG_XTERM | BG_XTERM); defaultfgcolor_ = 0xd0d0d000; // off white defaultbgcolor_ = 0xffffffff; // special color: doesn't draw, 'shows thru' to box() fgcolor_ = defaultfgcolor_; bgcolor_ = defaultbgcolor_; fontface_ = FL_COURIER; fontsize_ = 14; if (!fontsize_defer) update(); // normal behavior else update_fake(); // use fake values instead } // Update fontheight/descent cache whenever font changes void Fl_Terminal::CharStyle::update(void) { // cache these values fl_font(fontface_, fontsize_); fontheight_ = int(fl_height() + 0.5); fontdescent_ = int(fl_descent() + 0.5); charwidth_ = int(fl_width("X") + 0.5); } // Update fontheight/descent cache with fake values (issue 837) // XXX: Please remove this issue 837 hack the minute fluid no longer has to // instance fltk classes in headless mode // void Fl_Terminal::CharStyle::update_fake(void) { fontheight_ = 99; // Use fake values until first draw() when we call update() for real values. fontdescent_ = 99; // Use absurdly large values here to make un-updated sizes clearly evident charwidth_ = 99; } // Return fg color Fl_Color Fl_Terminal::CharStyle::fgcolor(void) const { return fgcolor_; } // Return bg color Fl_Color Fl_Terminal::CharStyle::bgcolor(void) const { return bgcolor_; } // Return only the color bit flags // Only the color bits of 'inflags' are modified with our color bits. // uchar Fl_Terminal::CharStyle::colorbits_only(uchar inflags) const { return (inflags & ~COLORMASK) | (charflags_ & COLORMASK); // add color bits only } void Fl_Terminal::CharStyle::fgcolor_xterm(uchar val) { fgcolor_ = fltk_fg_color(val); set_charflag(FG_XTERM); } void Fl_Terminal::CharStyle::bgcolor_xterm(uchar val) { bgcolor_ = fltk_bg_color(val); set_charflag(BG_XTERM); } /////////////////////////////////// ///// Cursor Class Methods //////// /////////////////////////////////// // Is cursor at display row,col? bool Fl_Terminal::Cursor::is_rowcol(int drow,int dcol) const { return(drow == row_ && dcol == col_); } // Scroll (move) the cursor row up(+)/down(-) number of rows void Fl_Terminal::Cursor::scroll(int nrows) { row_ = MAX(row_ - nrows, 0); // don't let (row_<0) } ///////////////////////////////////// ///// Utf8Char Class Methods //////// ///////////////////////////////////// // Ctor Fl_Terminal::Utf8Char::Utf8Char(void) { text_[0] = ' '; len_ = 1; attrib_ = 0; charflags_ = 0; fgcolor_ = 0xffffff00; bgcolor_ = 0xffffffff; // special color: doesn't draw, 'shows thru' to box() } // copy ctor Fl_Terminal::Utf8Char::Utf8Char(const Utf8Char& src) { // local instance not initialized yet; init first, then copy text text_[0] = ' '; len_ = 1; attrib_ = src.attrib_; charflags_ = src.charflags_; fgcolor_ = src.fgcolor_; bgcolor_ = src.bgcolor_; text_utf8_(src.text_utf8(), src.length()); // copy the src text } // assignment Fl_Terminal::Utf8Char& Fl_Terminal::Utf8Char::operator=(const Utf8Char& src) { // local instance is already initialized, so just change its contents text_utf8_(src.text_utf8(), src.length()); // local copy src text attrib_ = src.attrib_; charflags_ = src.charflags_; fgcolor_ = src.fgcolor_; bgcolor_ = src.bgcolor_; return *this; } // dtor Fl_Terminal::Utf8Char::~Utf8Char(void) { len_ = 0; } // Set 'text_' to valid UTF-8 string 'text'. // // text_ must not be NULL, and len must be in range: 1 <= len <= max_utf8(). // NOTE: Caller must handle such checks, and use handle_unknown_char() // for invalid chars. // void Fl_Terminal::Utf8Char::text_utf8_(const char *text, int len) { memcpy(text_, text, len); len_ = len; // update new length } // Set UTF-8 string for this char. // // text_ must not be NULL, and len must be in range: 1 <= len <= max_utf8(). // NOTE: Caller must handle such checks, and use handle_unknown_char() // for invalid chars. // void Fl_Terminal::Utf8Char::text_utf8(const char *text, int len, const CharStyle& style) { text_utf8_(text, len); // updates text_, len_ //issue 837 // fl_font(style.fontface(), style.fontsize()); // need font to calc UTF-8 width attrib_ = style.attrib(); charflags_ = style.colorbits_only(charflags_); fgcolor_ = style.fgcolor(); bgcolor_ = style.bgcolor(); } // Set char to single printable ASCII character 'c' // 'c' must be "printable" ASCII in the range (0x20 <= c <= 0x7e). // Anything outside of that is silently ignored. // void Fl_Terminal::Utf8Char::text_ascii(char c, const CharStyle& style) { // Signed char vals above 0x7f are /negative/, so <0x20 check covers those if (c < 0x20 || c >= 0x7e) return; // ASCII non-printable? text_utf8(&c, 1, style); } // Set fl_font() based on specified style for this char's attribute void Fl_Terminal::Utf8Char::fl_font_set(const CharStyle& style) const { int face = style.fontface() | ((attrib_ & Fl_Terminal::BOLD) ? FL_BOLD : 0) | ((attrib_ & Fl_Terminal::ITALIC) ? FL_ITALIC : 0); fl_font(face, style.fontsize()); } // Return the foreground color as an fltk color Fl_Color Fl_Terminal::Utf8Char::fgcolor(void) const { return fgcolor_; } // Return the background color as an fltk color Fl_Color Fl_Terminal::Utf8Char::bgcolor(void) const { return bgcolor_; } // Return the width of this character in floating point pixels // // WARNING: Uses current font, so assumes fl_font(face,size) // has already been set to current font! // double Fl_Terminal::Utf8Char::pwidth(void) const { return fl_width(text_, len_); } // Return the width of this character in integer pixels // // WARNING: Uses current font, so assumes fl_font(face,size) // has already been set to current font! // int Fl_Terminal::Utf8Char::pwidth_int(void) const { return int(fl_width(text_, len_) + 0.5); } // Return color \p col, possibly influenced by BOLD or DIM attributes \p attr. // If a \p grp widget is specified (i.e. not NULL), don't let the color \p col be // influenced by the attribute bits /if/ \p col matches the \p grp widget's own color(). // Fl_Color Fl_Terminal::Utf8Char::attr_color_(Fl_Color col, const Fl_Widget *grp) const { // Don't modify color if it's the special 'see thru' color 0xffffffff or widget's color() if (grp && ((col == 0xffffffff) || (col == grp->color()))) return grp->color(); switch (attrib_ & (Fl_Terminal::BOLD|Fl_Terminal::DIM)) { case 0: return col; // not bold or dim? no change case Fl_Terminal::BOLD: return bold_color(col); // bold? use bold_color() case Fl_Terminal::DIM : return dim_color(col); // dim? use dim_color() default: return col; // bold + dim? cancel out } } // Return the fg color of char \p u8c possibly influenced by BOLD or DIM. // If a \p grp widget is specified (i.e. not NULL), don't let the color \p col be // influenced by the attribute bits /if/ \p col matches the \p grp widget's own color(). // Fl_Color Fl_Terminal::Utf8Char::attr_fg_color(const Fl_Widget *grp) const { if (grp && (fgcolor_ == 0xffffffff)) // see thru color? { return grp->color(); } // return grp's color() return (charflags_ & Fl_Terminal::FG_XTERM) // fg is an xterm color? ? attr_color_(fgcolor(), grp) // ..use attributes : fgcolor(); // ..ignore attributes. } Fl_Color Fl_Terminal::Utf8Char::attr_bg_color(const Fl_Widget *grp) const { if (grp && (bgcolor_ == 0xffffffff)) // see thru color? { return grp->color(); } // return grp's color() return (charflags_ & Fl_Terminal::BG_XTERM) // bg is an xterm color? ? attr_color_(bgcolor(), grp) // ..use attributes : bgcolor(); // ..ignore attributes. } //////////////////////////////////// ///// RingBuffer Class Methods ///// //////////////////////////////////// // Handle adjusting 'offset_' specified number of rows to do "scrolling". // rows can be +/-: positive effectively scrolls "up", negative scrolls "down". // rows will be clamped // void Fl_Terminal::RingBuffer::offset_adjust(int rows) { if (!rows) return; // early exit if nothing to do if (rows>0) { // advance? offset_ = (offset_ + rows) % ring_rows_; // apply, and keep offset_ within ring_rows } else { rows = clamp(-rows, 1, ring_rows_); // make positive, limit to ring size offset_ -= rows; // apply offset if (offset_<0) offset_ += ring_rows_; // wrap underflows } } // Create a new copy of the buffer with different row/col sizes // Preserves old contents of display and history in use. // // The old buffer might have an offset and the hist/disp might wrap // around the end of the ring. The NEW buffer's offset will be zero, // so the hist/disp do NOT wrap around, making the move operation easier to debug. // // The copy preservation starts at the LAST ROW in display of both old (src) and new (dst) // buffers, and copies rows in reverse until hist_use_srow() reached, or if we hit top // of the new history (index=0), which ever comes first. So in the following where the // display is being enlarged, the copy preservation starts at "Line 5" (bottom of display) // and works upwards, ending at "Line 1" (top of history use): // // OLD (SRC) NEW (DST) // _____________ _____________ ___ // | x x x x x x | | x x x x x x | ʌ 'x' indicates // | Line 1 | ─┐ | x x x x x x | | hist_rows unused history // | Line 2 | └─> | Line 1 | v buffer memory. // |-------------| |-------------| --- // | Line 3 | | Line 2 | ʌ // | Line 4 | | Line 3 | | // | Line 5 | ─┐ | Line 4 | | disp_rows // |_____________| └─> | Line 5 | | // |_____________| _v_ // void Fl_Terminal::RingBuffer::new_copy(int drows, int dcols, int hrows, const CharStyle& style) { (void)style; // currently unused - need parameterized ctor (†) // Create new buffer int addhist = disp_rows() - drows; // adjust history use int new_ring_rows = (drows+hrows); int new_hist_use = clamp(hist_use_ + addhist, 0, hrows); // clamp incase new_hist_rows smaller than old int new_nchars = (new_ring_rows * dcols); Utf8Char *new_ring_chars = new Utf8Char[new_nchars]; // Create new ring buffer (†) // Preserve old contents in new buffer int dst_cols = dcols; int src_stop_row = hist_use_srow(); int tcols = MIN(ring_cols(), dcols); int src_row = hist_use_srow() + hist_use_ + disp_rows_ - 1; // use row#s relative to hist_use_srow() int dst_row = new_ring_rows - 1; // Copy rows: working up from bottom of disp, stop at top of hist while ((src_row >= src_stop_row) && (dst_row >= 0)) { Utf8Char *src = u8c_ring_row(src_row); Utf8Char *dst = new_ring_chars + (dst_row*dst_cols); for (int col=0; col= htop) && (grow <= hbot)); } // See if 'grow' is within the display buffer // It's assumed grow is in the range hist_rows() .. ring_rows()-1. // bool Fl_Terminal::RingBuffer::is_disp_ring_row(int grow) const { grow %= ring_rows_; grow -= offset_; if (grow < 0) { grow = (ring_rows_ + grow); } int dtop = hist_rows_; int dbot = hist_rows_ + disp_rows_ - 1; return ((grow >= dtop) && (grow <= dbot)); } // Move display row from src_row to dst_row void Fl_Terminal::RingBuffer::move_disp_row(int src_row, int dst_row) { Utf8Char *src = u8c_disp_row(src_row); Utf8Char *dst = u8c_disp_row(dst_row); for (int col=0; colclear(style); } } // Scroll the ring buffer up or down #rows, using 'style' for empty rows // > Positive rows scroll "up", moves top line(s) into history, clears bot line(s) // Increases hist_use (unless maxed out). // > Negative rows scroll "down", clears top line(s), history unaffected // void Fl_Terminal::RingBuffer::scroll(int rows, const CharStyle& style) { if (rows > 0) { // Scroll up into history // Example: scroll(2): // // BEFORE AFTER // --------------- --------------- // | H i s t | --- | x x x x x x x | \_ blanked rows // | | \ | x x x x x x x | / // | | ---> |---------------| <- disp_erow() // | | | H i s t | // | | | | // disp_srow() -> |---------------| --- | 0001 | // | 0001 | \ | 0002 | // | 0002 | ---> |---------------| <- disp_srow() // | 0003 | | 0003 | // | 0004 | | 0004 | // | 0005 | --- | 0005 | // | 0006 | \ | 0006 | // disp_erow() -> --------------- ---> --------------- // // \______/ // Simple // Offset rows = clamp(rows, 1, disp_rows()); // sanity // Scroll up into history offset_adjust(rows); // Adjust hist_use, clamp to max hist_use_ = clamp(hist_use_ + rows, 0, hist_rows_); // Clear exposed lines at bottom int srow = (disp_rows() - rows) % disp_rows(); int erow = disp_rows() - 1; clear_disp_rows(srow, erow, style); } else { // Scroll down w/out affecting history // To leave history unaffected, we must move memory. // Start at bottom row [A] and work up to top row [B]. // // Example: scroll(-2): // // BEFORE AFTER // ----------------- ----------------- _ // | 0001 [B] | ---┐ | x x x x x x x x | \_ blanked // | 0002 | | | x x x x x x x x | _/ rows // | 0003 | └---> | 0001 | // | 0004 [A] | ---┐ | 0002 | // | 0005 | | | 0003 | // | 0006 | └---> | 0004 | // ----------------- ----------------- // \______/ // Memory // move rows = clamp(-rows, 1, disp_rows()); // make rows positive + sane for (int row=disp_rows()-1; row>=0; row--) { // start at end of disp and work up int src_row = (row - rows); // src is offset #rows being scrolled int dst_row = row; // dst is display if (src_row >= 0) move_disp_row(src_row, dst_row); // ok to move row? move row down else clear_disp_rows(dst_row, dst_row, style); // hit top? blank rest of rows } } } // Return UTF-8 char for 'row' in the ring // Scrolling offset is NOT applied; this is raw access to the ring's rows. // // Example: // // Walk ALL rows in the ring buffer.. // for (int row=0; row= 0 && row < ring_rows_); return &ring_chars_[row * ring_cols()]; } // Return UTF-8 char for beginning of 'row' in the history buffer. // Example: // // Walk ALL rows in history.. // for (int hrow=0; hrow= 0 && rowi <= ring_rows_); return &ring_chars_[rowi * ring_cols()]; } // Special case to walk the "in use" rows of the history // Example: // // Walk the "in use" rows of history.. // for (int hrow=0; hrow= 0 && hurow <= hist_use()); return &ring_chars_[hurow * ring_cols()]; } // Return UTF-8 char for beginning of 'row' in the display buffer // Example: // // Walk ALL rows in display.. // for (int drow=0; drow= 0 && rowi <= ring_rows_); return &ring_chars_[rowi * ring_cols()]; } // non-const versions of the above //////////////////////////////////////////////// // Return UTF-8 char for 'row' in the ring. // Scrolling offset is NOT applied; this is raw access to the ring's rows. // Example: // // Walk ALL rows in the ring buffer.. // for (int row=0; row(const_cast(this)->u8c_ring_row(row)); } Fl_Terminal::Utf8Char* Fl_Terminal::RingBuffer::u8c_hist_row(int hrow) { return const_cast(const_cast(this)->u8c_hist_row(hrow)); } Fl_Terminal::Utf8Char* Fl_Terminal::RingBuffer::u8c_hist_use_row(int hurow) { return const_cast(const_cast(this)->u8c_hist_use_row(hurow)); } // Return UTF-8 char for beginning of 'row' in the display buffer // Example: // // Walk ALL rows in display.. // for (int drow=0; drow(const_cast(this)->u8c_disp_row(drow)); } // Resize ring buffer by creating new one, dumping old (if any). // Input: // drows -- display height in lines of text (rows) // dcols -- display width in characters (columns) // hrows -- scrollback history size in lines of text (rows) // void Fl_Terminal::RingBuffer::create(int drows, int dcols, int hrows) { clear(); // History hist_rows_ = hrows; hist_use_ = 0; // Display disp_rows_ = drows; // Ring buffer ring_rows_ = hist_rows_ + disp_rows_; ring_cols_ = dcols; nchars_ = ring_rows_ * ring_cols_; ring_chars_ = new Utf8Char[nchars_]; } // Resize the buffer, preserve previous contents as much as possible void Fl_Terminal::RingBuffer::resize(int drows, int dcols, int hrows, const CharStyle& style) { int new_rows = drows + hrows; // old display + history rows int old_rows = disp_rows() + hist_rows(); // new display + history rows bool cols_changed = (dcols != disp_cols()); // was there a change in total #columns? bool rows_changed = (new_rows != old_rows); // was there a change in total #rows? // If rows or cols changed, make a NEW buffer and copy old contents. // New copy will have disp/hist_rows/cols and nchars adjusted. if (cols_changed || rows_changed) { // rows or cols changed? new_copy(drows, dcols, hrows, style); // rebuild ring buffer, preserving contents } else { // Cols and total rows the same, probably just changed disp/hist ratio int addhist = disp_rows() - drows; // adj hist_use smaller if disp enlarged hist_rows_ = hrows; // adj hist rows for new value disp_rows_ = drows; // adj disp rows for new value hist_use_ = clamp(hist_use_ + addhist, 0, hrows); } } // Change the display rows. Use style for new rows, if any. void Fl_Terminal::RingBuffer::change_disp_rows(int drows, const CharStyle& style) { resize(drows, ring_cols(), hist_rows(), style); } // Change the display columns. Use style for new columns, if any. void Fl_Terminal::RingBuffer::change_disp_cols(int dcols, const CharStyle& style) { resize(disp_rows(), dcols, hist_rows(), style); } ///////////////////////////////////// ///// Fl_Terminal Class Methods ///// ///////////////////////////////////// /// See docs for non-const version of u8c_ring_row(int) const Fl_Terminal::Utf8Char* Fl_Terminal::u8c_ring_row(int grow) const { return ring_.u8c_ring_row(grow); } /// See docs for non-const version of u8c_hist_row(int) const Fl_Terminal::Utf8Char* Fl_Terminal::u8c_hist_row(int hrow) const { return ring_.u8c_hist_row(hrow); } /// See docs for non-const version of u8c_hist_use_row(int) const Fl_Terminal::Utf8Char* Fl_Terminal::u8c_hist_use_row(int hurow) const { return ring_.u8c_hist_use_row(hurow); } /// See docs for non-const version of u8c_disp_row(int) const Fl_Terminal::Utf8Char* Fl_Terminal::u8c_disp_row(int drow) const { return ring_.u8c_disp_row(drow); } // non-const versions of the above //////////////////////////////////////////////// /** Return UTF-8 char for row \p grow in the ring buffer. \p grow is globally indexed relative to the beginning of the ring buffer, so this method can access ANY character in the entire ring buffer (hist or disp) by the global index. Scrolling offset is NOT applied; this is raw access to the ring's rows. Should really ONLY be used for making a complete copy of the ring. Example: \code // Walk ALL rows and cols in the ring buffer.. for (int row=0; rowxxx() methods.. } } \endcode */ Fl_Terminal::Utf8Char* Fl_Terminal::u8c_ring_row(int grow) { return const_cast(const_cast(this)->u8c_ring_row(grow)); } /** Return u8c for beginning of a row inside the scrollback history. 'hrow' is indexed relative to the beginning of the scrollback history buffer. \see u8c_disp_row(int) for example use. */ Fl_Terminal::Utf8Char* Fl_Terminal::u8c_hist_row(int hrow) { return const_cast(const_cast(this)->u8c_hist_row(hrow)); } /** Return u8c for beginning of row \p hurow inside the 'in use' part of the scrollback history. 'hurow' is indexed relative to the beginning of the 'in use' part of the scrollback history buffer. This may be a different from u8c_hist_row(int) if the history was recently cleared, and there aren't many (or any) rows in the history buffer that have been populated with scrollback text yet. \see u8c_disp_row(int) for example use. */ Fl_Terminal::Utf8Char* Fl_Terminal::u8c_hist_use_row(int hurow) { return const_cast(const_cast(this)->u8c_hist_use_row(hurow)); } /** Return pointer to the first u8c character in row \p drow of the display. - 'drow' is indexed relative to the beginning of the display buffer. - This can be used to walk all columns in the specfied row, e.g. \code // Print all chars in first row of display (ASCII and UTF-8) Utf8Char *u8c = u8c_disp_row(0); // first char of first display row int scol = 0, ecol = disp_cols(); // start/end for column loop for (int col=scol; coltext_utf8(); // text string for char int len = u8c->length(); // text string length for char ::printf("<%.*s>", len, text); // print potentially multibyte char } \endcode */ Fl_Terminal::Utf8Char* Fl_Terminal::u8c_disp_row(int drow) { return const_cast(const_cast(this)->u8c_disp_row(drow)); } // Create ring buffer. // Input: // drows -- display height in lines of text (rows) // dcols -- display width in characters (columns) // hrows -- scrollback history size in lines of text (rows) // // NOTE: Caller should call update_screen() at some point // to fix the scrollbar and other things. // void Fl_Terminal::create_ring(int drows, int dcols, int hrows) { // recreate tabstops if col width being changed if (dcols != ring_.ring_cols()) init_tabstops(dcols); // recreate ring (dumps old) ring_.create(drows, dcols, hrows); // ensure cursor starts at home position cursor_.home(); } /// Return the Utf8Char* for character under cursor. Fl_Terminal::Utf8Char* Fl_Terminal::u8c_cursor(void) { return u8c_disp_row(cursor_.row()) + cursor_.col(); } // Initialize tabstops for terminal // NOTE: 'newsize' should always be at least 'ring_cols()'.. // void Fl_Terminal::init_tabstops(int newsize) { if (newsize > tabstops_size_) { // enlarge? char *oldstops = tabstops_; // save old stops int oldsize = tabstops_size_; // save old size tabstops_ = (char*)malloc(newsize); // alloc new for (int t=0; ttype() == FL_HORIZONTAL); int diff = max - min; int length = is_hor ? scroll->w() : scroll->h(); // long side of scrollbar in pixels float tabsize = min / float(max); // fractional size of tab float minpix = float(MAX(10, scrollbar_actual_size())); // scrollbar_size preferred, 10pix min (**) float minfrac = minpix / length; // slide_size wants a fraction tabsize = MAX(minfrac, tabsize); // use best fractional size scroll->slider_size(tabsize); // size of slider's tab if (is_hor) scroll->range(0, diff); // range of values hscroll returns (0=left) else scroll->range(diff, 0); // ditto, but for vscroll 0=BOTTOM scroll->step(0.25); // Fl_Slider's resolution: 4 : 1 } // Update both scrollbars based on screen, history buffer, etc // Vertical scrollbar should range from 0 (bottom) to history_use() (top), // the scrollbar's value being "how many lines we're scrolled back" // into the screen history. // Horizontal scrollbar should range from 0 (left) to the number of columns // that are offscreen. // void Fl_Terminal::update_scrollbar(void) { // // Vertical scrollbar // int value_before = scrollbar->value(); { // Set vert scrollbar params int trows = disp_rows() + history_use(); // total rows we can scroll to int vrows = disp_rows(); // visible rows set_scrollbar_params(scrollbar, vrows, trows); } if (value_before == 0) scrollbar->value(0); // was at bottom? stay at bottom // Ensure scrollbar in proper position update_screen_xywh(); // ensure scrn_ up to date first int sx = scrn_.r() + margin_.right(); int sy = scrn_.y() - margin_.top(); int sw = scrollbar_actual_size(); int sh = scrn_.h() + margin_.top() + margin_.bottom(); bool vchanged = scrollbar->x() != sx || scrollbar->y() != sy || scrollbar->w() != sw || scrollbar->h() != sh; if (vchanged) scrollbar->resize(sx, sy, sw, sh); // // Horizontal scrollbar // int hh; int hx = scrn_.x() - margin_.left(); int hy = scrn_.b() + margin_.bottom(); int hw = scrn_.w() + margin_.left() + margin_.right(); unsigned int hv = hscrollbar->visible(); // Set horiz scrollbar params int vcols = w_to_col(scrn_.w()); // visible cols int tcols = disp_cols(); // total cols we can scroll to if (vcols > tcols) vcols = tcols; // don't be larger than total set_scrollbar_params(hscrollbar, vcols, tcols); // Horiz scrollbar visibility if (hscrollbar_style_ == SCROLLBAR_OFF) { hscrollbar->hide(); hh = 0; } else if (vcols < tcols || hscrollbar_style_ == SCROLLBAR_ON) { hscrollbar->show(); hh = scrollbar_actual_size(); } else { hscrollbar->hide(); hh = 0; } // Update system as necessary bool hchanged = hscrollbar->x() != hx || hscrollbar->y() != hy || hscrollbar->w() != hw || hscrollbar->h() != hh || hscrollbar->visible() != hv; if (hchanged) hscrollbar->resize(hx, hy, hw, hh); if (vchanged || hchanged) { init_sizes(); // tell Fl_Group child changed size.. update_screen_xywh(); // ensure scrn_ is aware of sw change display_modified(); // redraw Fl_Terminal since scroller changed size } scrollbar->redraw(); // redraw scroll always } // Refit the display - (display_rows()/cols()) to match screen (scrn_.h()/w()) // This implements an xterm-like resizing behavior. Refer to README-Fl_Terminal.txt, // section "TERMINAL RESIZING" for a diagram of cases showing how this is implemented. // See also issue #844. // void Fl_Terminal::refit_disp_to_screen(void) { // TODO: Needs to account for change in width too - implement dcol_diff int dh = h_to_row(scrn_.h()); // disp height: in rows for tty pixel height int dw = MAX(w_to_col(scrn_.w()), disp_cols()); // disp width: in cols from pixel width - enlarge only! int drows = clamp(dh, 2, dh); // disp rows: 2 rows minimum int dcols = clamp(dw, 10, dw); // disp cols: 10 cols minimum int drow_diff = drows - display_rows(); // disp row diff: change in rows? int is_enlarge = drows >= display_rows(); // enlarging display size? // NOTE: Zeroing scrollbar can be avoided if we took the scroll position // into account for the below calculations. But for now.. scrollbar->value(0); // force scrollbar to bottom before refit if (drow_diff) { // change in display rows means shrink|enlarge if (is_enlarge) { // enlarging widget? for (int i=0; i 0) { // CASE 1: Drag lines down from history cursor_.scroll(-1); // cursor chases ring_.resize() } else { // CASE 2: add blank lines below cursor scroll(1); // scroll up to create blank lines at bottom } // Handle enlarging ring's display ring_.resize(display_rows()+1, dcols, hist_rows(), *current_style_); } } else { // shrinking widget? for (int i=0; i<(-drow_diff); i++) { // carefully loop thru each row change int cur_row = cursor_.row(); // cursor row int below_cur = (drows > cur_row); // shrink is below cursor row? if (below_cur) { // CASE 3: shrinking below cursor? drop lines below ring_.disp_rows(display_rows() - 1); // effectively "deletes" lines below cursor } else { // CASE 4: need to move cursor + lines up into hist cursor_up(-1, false); // move cursor down to follow ring_.resize() // Handle shrinking ring's display up into history ring_.resize(display_rows()-1, dcols, hist_rows(), *current_style_); } } } } clear_mouse_selection(); update_screen(false); } // Resize the display's vertical size to (drows). // When enlarging / shrinking, KEEP BOTTOM OF DISPLAY THE SAME, e.g. // // Display Display // BEFORE: SMALLER: // ___________ ___________ // | Hist -3 | ʌ | Hist -3 | ʌ // | Hist -2 | |- 3 | Hist -2 | | // | Hist -1 | v | Hist -1 | |-- new hist size // |-----------| ---┐ | Line 1 | | // | Line 1 | | | Line 2 | v // | Line 2 | └---> |-----------| // | Line 3 | | Line 3 | ʌ // | : | | : | |-- new disp size // | Line 25 | -------> | Line 25 | v // ----------- ----------- // // Display Display // BEFORE: LARGER // ___________ ___________ // | Hist -3 | ʌ | Hist -3 | --- new hist size // | Hist -2 | |- 3 ┌-->|-----------| // | Hist -1 | v | | Hist -2 | ʌ // |-----------| ------┘ | Hist -1 | | // | Line 1 | | Line 1 | | // | Line 2 | | Line 2 | |-- new disp size // | Line 3 | | Line 3 | | // | : | | : | | // | Line 25 | --------> | Line 25 | v // ----------- ----------- // // void Fl_Terminal::resize_display_rows(int drows) { int drow_diff = drows - ring_.disp_rows(); // Change in rows? if (drow_diff == 0) return; // No changes? early exit int new_dcols = ring_cols(); // keep cols the same int new_hrows = hist_rows() - drow_diff; // keep disp:hist ratio same if (new_hrows<0) new_hrows = 0; // don't let hist be <0 ring_.resize(drows, new_dcols, new_hrows, *current_style_); // ..update cursor/selections to track text position cursor_.scroll(-drow_diff); select_.clear(); // clear any mouse selection // ..update scrollbar, since disp_height relative to hist_use changed update_scrollbar(); } // Resize the display's columns // This affects the history and entire ring buffer too. // Make an effort to preserve previous content. // Up to caller to enforce any 'minimum' size for drows. // void Fl_Terminal::resize_display_columns(int dcols) { // No changes? early exit if (dcols == disp_cols()) return; // Change cols, preserves previous content if possible ring_.resize(disp_rows(), dcols, hist_rows(), *current_style_); update_scrollbar(); } // Update only the internal terminal screen xywh and x2/y2 values void Fl_Terminal::update_screen_xywh(void) { const Margin &m = margin_; scrn_ = *this; // start with widget's current xywh scrn_.inset(box()); // apply box offset scrn_.inset(m.left(), m.top(), m.right(), m.bottom()); // apply margins offset scrn_.inset(0, 0, scrollbar_actual_size(), 0); // apply scrollbar width if (hscrollbar && hscrollbar->visible()) scrn_.inset(0, 0, 0, scrollbar_actual_size()); // apply hscrollbar height } // Update internals when something "global" changes // Call this when something important is changed: // Resizing screen or changing font/size affect internals globally. // Font change affects per-character caching of char widths. // Display resize affects scrn_ cache, scrollbars, etc. // void Fl_Terminal::update_screen(bool font_changed) { // current_style: update cursor's size for current font/size if (font_changed) { // Change font and current_style's font height if (!fontsize_defer_) { // issue 837 //DEBUG fprintf(stderr, "update_screen(font change): row/cols=%d/%d, cs.width=%d, cs.height=%d\n", display_rows(), display_columns(), current_style_->charwidth(), current_style_->fontheight()); fl_font(current_style_->fontface(), current_style_->fontsize()); } cursor_.h(current_style_->fontheight()); } // Update the scrn_* values update_screen_xywh(); // Recalc the scrollbar size/position/etc update_scrollbar(); } /** Return terminal's scrollback history buffer size in lines of text (rows). */ int Fl_Terminal::history_rows(void) const { return hist_rows(); } /** Set terminal's scrollback history buffer size in lines of text (rows). */ void Fl_Terminal::history_rows(int hrows) { if (hrows == history_rows()) return; // no change? done ring_.resize(disp_rows(), disp_cols(), hrows, *current_style_); update_screen(false); // false: no font change display_modified(); } /** Returns how many lines are "in use" by the screen history buffer. This value will be 0 if history was recently cleared with e.g. clear_history() or \c "c". Return value will be in the range 0 .. (history_lines()-1). */ int Fl_Terminal::history_use(void) const { return ring_.hist_use(); } /** Return terminal's display height in lines of text (rows). This value is normally managed automatically by resize() based on the current font size. */ int Fl_Terminal::display_rows(void) const { return ring_.disp_rows(); } /** Set terminal's display height in lines of text (rows). This value is normally managed automatically by resize() based on the current font size, and should not be changed. To change the display height, use resize() instead. */ void Fl_Terminal::display_rows(int drows) { if (drows == disp_rows()) return; // no change? early exit ring_.resize(drows, disp_cols(), hist_rows(), *current_style_); update_screen(false); // false: no font change ?NEED? refit_disp_to_screen(); } /** Return terminal's display width in columns of text characters. This value is normally managed automatically by resize() based on the current font size. */ int Fl_Terminal::display_columns(void) const { return ring_.disp_cols(); } /** Set terminal's display width in columns of text characters. This value is normally managed automatically by resize() based on the current font size, and should not be changed. You CAN make the display_columns() larger than the width of the widget; text in the terminal will simply run off the screen edge and be clipped; the only way to reveal that text is if the user enlarges the widget, or the font size made smaller. To change the display width, it is best to use resize() instead. */ void Fl_Terminal::display_columns(int dcols) { if (dcols == disp_cols()) return; // no change? early exit // Change cols, preserves previous content if possible ring_.resize(disp_rows(), dcols, hist_rows(), *current_style_); update_screen(false); // false: no font change ?NEED? refit_disp_to_screen(); } /** Return reference to internal current style for rendering text. */ Fl_Terminal::CharStyle& Fl_Terminal::current_style(void) const { return *current_style_; } /** Set current style for rendering text. */ void Fl_Terminal::current_style(const CharStyle& sty) { *current_style_ = sty; } /** Set the left margin; see \ref Fl_Terminal_Margins. */ void Fl_Terminal::margin_left(int val) { val = clamp(val,0,w()-1); margin_.left(val); update_screen(true); refit_disp_to_screen(); } /** Set the right margin; see \ref Fl_Terminal_Margins. */ void Fl_Terminal::margin_right(int val) { val = clamp(val,0,w()-1); margin_.right(val); update_screen(true); refit_disp_to_screen(); } /** Set the top margin; see \ref Fl_Terminal_Margins. */ void Fl_Terminal::margin_top(int val) { val = clamp(val,0,h()-1); margin_.top(val); update_screen(true); refit_disp_to_screen(); } /** Set the bottom margin; see \ref Fl_Terminal_Margins. */ void Fl_Terminal::margin_bottom(int val) { val = clamp(val,0,h()-1); margin_.bottom(val); update_screen(true); refit_disp_to_screen(); } /** Sets the font used for all text displayed in the terminal. This affects all existing text (in display and history) as well as any newly printed text. Only monospace fonts are recommended, such as FL_COURIER or FL_SCREEN. Custom fonts configured with Fl::set_font() will also work, as long as they are monospace. */ void Fl_Terminal::textfont(Fl_Font val) { current_style_->fontface(val); update_screen(true); display_modified(); } /** Sets the font size used for all text displayed in the terminal. This affects all existing text (in display and history) as well as any newly printed text. Changing this will affect the display_rows() and display_columns(). */ void Fl_Terminal::textsize(Fl_Fontsize val) { current_style_->fontsize(val); update_screen(true); // Changing font size affects #lines in display, so resize it refit_disp_to_screen(); display_modified(); } /** Sets the foreground text color as one of the 8 'xterm color' values. This will be the foreground color used for all newly printed text, similar to the \c \[\#m escape sequence, where \# is between 30 and 37. This color will be reset to the default fg color if reset_terminal() is called, or by \c \c, \c \[0m, etc. The xterm color intensity values can be influenced by the Dim/Bold/Normal modes (which can be set with e.g. \c \[1m, textattrib(), etc), so the actual RGB values of these colors allow room for Dim/Bold to influence their brightness. For instance, "Normal Red" is not full brightness to allow "Bold Red" to be brighter. This goes for all colors except 'Black', which is not influenced by Dim or Bold; Black is always Black. The 8 color xterm values are: - 0 = Black - 1 = Red - 2 = Green - 3 = Yellow - 4 = Blue - 5 = Magenta - 6 = Cyan - 7 = White \see textfgcolor_default(Fl_Color) */ void Fl_Terminal::textfgcolor_xterm(uchar val) { current_style_->fgcolor_xterm(val); } /** Sets the background text color as one of the 8 'xterm color' values. This will be the foreground color used for all newly printed text, similar to the \c \[\#m escape sequence, where \# is between 40 and 47. This color will be reset to the default bg color if reset_terminal() is called, or by \c \c, \c \[0m, etc. The xterm color intensity values can be influenced by the Dim/Bold/Normal modes (which can be set with e.g. \c \[1m, textattrib(), etc), so the actual RGB values of these colors allow room for Dim/Bold to influence their brightness. For instance, "Normal Red" is not full brightness to allow "Bold Red" to be brighter. This goes for all colors except 'Black', which is not influenced by Dim or Bold; Black is always Black. The 8 color xterm values are: - 0 = Black - 1 = Red - 2 = Green - 3 = Yellow - 4 = Blue - 5 = Magenta - 6 = Cyan - 7 = White \see textbgcolor_default(Fl_Color) */ void Fl_Terminal::textbgcolor_xterm(uchar val) { current_style_->bgcolor_xterm(val); } /** Set the text color for the terminal. This is a convenience method that sets *both* textfgcolor() and textfgcolor_default(), ensuring both are set to the same value. Colors set this way will NOT be influenced by the xterm Dim/Bold color intensity attributes. For that, use textcolor_xterm() instead. \see textfgcolor(Fl_Color), textfgcolor_default(Fl_Color), textbgcolor_xterm(uchar) */ void Fl_Terminal::textcolor(Fl_Color val) { textfgcolor(val); textfgcolor_default(val); } /** Sets the background color for the terminal's Fl_Group::box(). If the textbgcolor() and textbgcolor_default() are set to the special "see through" color 0xffffffff when any text was added, changing color() affects the color that shows through behind that existing text. Otherwise, whatever specific background color was set for existing text will persist after changing color(). To see the effects of a change to color(), follow up with a call to redraw(). The default value is 0x0. */ void Fl_Terminal::color(Fl_Color val) { Fl_Group::color(val); } /** Set text foreground drawing color to fltk color \p val used by any new text added. Use this for temporary color changes, similar to \[38;2;\;\;\m Colors set this way will NOT be influenced by the xterm Dim/Bold color intensity attributes. For that, use textfgcolor_xterm(uchar) instead. This setting does _not_ affect the 'default' text colors used by \[0m, \c, reset_terminal(), etc. To change both the current _and_ default fg color, also use textfgcolor_default(Fl_Color). Example: \par \code // Set both 'current' and 'default' colors Fl_Color amber = 0xd0704000; tty->textfgcolor(amber); // set 'current' fg color tty->textfgcolor_default(amber); // set 'default' fg color used by ESC[0m reset \endcode \see textfgcolor_default(Fl_Color), textfgcolor_xterm(uchar) */ void Fl_Terminal::textfgcolor(Fl_Color val) { current_style_->fgcolor(val); // also clears FG_XTERM charflag } /** Set text background color to fltk color \p val used by any new text added. Use this for temporary color changes, similar to \[48;2;\;\;\m Colors set this way will NOT be influenced by the xterm Dim/Bold color intensity attributes. For that, use textbgcolor_xterm(uchar) instead. This setting does _not_ affect the 'default' text colors used by \[0m, \c, reset_terminal(), etc. To set that too, also set textbgcolor_default(Fl_Color), e.g. \par \code // Set both 'current' and 'default' colors Fl_Color darkamber = 0x20100000; tty->textbgcolor(darkamber); // set 'current' bg color tty->textbgcolor_default(darkamber); // set 'default' bg color used by ESC[0m reset \endcode The special color value 0xffffffff (all ff's) is the "see through" color, which lets the widget's own Fl_Group::color() show through behind the text. This special text background color is the _default_, and is what most situations need. \see textbgcolor_default(Fl_Color), textbgcolor_xterm(uchar) */ void Fl_Terminal::textbgcolor(Fl_Color val) { current_style_->bgcolor(val); // also clears BG_XTERM charflag } /** Set the default text foreground color used by \c \c, \c \[0m, and reset_terminal(). Does not affect the 'current' text foreground color; use textfgcolor(Fl_Color) to set that. \see textfgcolor(Fl_Color) */ void Fl_Terminal::textfgcolor_default(Fl_Color val) { current_style_->defaultfgcolor(val); } /** Set the default text background color used by any new text added after a reset (\c \c, \c \[0m, or reset_terminal()). Does not affect the 'current' text background color; use textbgcolor(Fl_Color) to set that. The special color value 0xffffffff (all ff's) is the "see through" color, which lets the widget's own Fl_Group::color() show through behind the text. This special text background color is the _default_, and is what most situations need. \see textbgcolor(Fl_Color) */ void Fl_Terminal::textbgcolor_default(Fl_Color val) { current_style_->defaultbgcolor(val); } /** Set text attribute bits (underline, inverse, etc). This will be the default attribute used for all newly printed text. \see Fl_Terminal::Attrib */ void Fl_Terminal::textattrib(uchar val) { current_style_->attrib(val); } /** Get text attribute bits (underline, inverse, etc). This is the default attribute used for all newly printed text. \see textattrib(uchar), Fl_Terminal::Attrib */ uchar Fl_Terminal::textattrib() const { return current_style_->attrib(); } /** Convert fltk window X coord to column 'gcol' on specified global 'grow' \returns - 1 if 'gcol' was found - 0 if X not within any char in 'grow' */ int Fl_Terminal::x_to_glob_col(int X, int grow, int &gcol, bool &gcr) const { int cx = scrn_.x(); // leftmost char x position const Utf8Char *u8c = utf8_char_at_glob(grow, 0); for (gcol=0; gcolfl_font_set(*current_style_); // pwidth_int() needs fl_font set int cx2 = cx + u8c->pwidth_int(); // char x2 (right edge of char) if (X >= cx && X < cx2) { gcr = (X > ((cx+cx2)/2)); // X is in right half of character return 1; // found? return with gcol and gcr set } cx += u8c->pwidth_int(); // move cx to start x of next char } gcol = ring_cols()-1; // don't leave larger than #cols return 0; // not found } // Convert fltk window X,Y coords to row + column indexing into ring_chars[] // Returns: // 1 -- found row,col // 0 -- not found, outside display's character area // -1/-2/-3/-4 -- not found, off top/bot/lt/rt edge respectively // int Fl_Terminal::xy_to_glob_rowcol(int X, int Y, int &grow, int &gcol, bool &gcr) const { // X,Y outside terminal area? early exit if (Yscrn_.b()) return -2; // dn (off bot edge) if (Xscrn_.r()) return -4; // rt (off right edge) // Find toprow of what's currently drawn on screen int toprow = disp_srow() - scrollbar->value(); // Find row the 'Y' value is in grow = toprow + ( (Y-scrn_.y()) / current_style_->fontheight()); return x_to_glob_col(X, grow, gcol, gcr); } /** Clears the screen to the current textbgcolor(), and homes the cursor. \see clear_screen(), clear_screen_home(), cursor_home() */ void Fl_Terminal::clear(void) { clear_screen_home(); } /** Clears the screen to a specific color \p val and homes the cursor. \see clear_screen(), clear_screen_home(), cursor_home() */ void Fl_Terminal::clear(Fl_Color val) { Fl_Color save = textbgcolor(); textbgcolor(val); clear_screen_home(); textbgcolor(save); } /** Clear the terminal screen only; does not affect the cursor position. Also clears the current mouse selection. If \p 'scroll_to_hist' is true, the screen is cleared by scrolling the contents into the scrollback history, where it can be retrieved with the scrollbar. This is the default behavior. If false, the screen is cleared and the scrollback history is unchanged. Similar to the escape sequence \c "[2J". \see clear_screen_home() */ void Fl_Terminal::clear_screen(bool scroll_to_hist) { if (scroll_to_hist) { scroll(disp_rows()); return; } for (int drow=0; drow[2J[H". \see clear_screen() */ void Fl_Terminal::clear_screen_home(bool scroll_to_hist) { cursor_home(); clear_screen(scroll_to_hist); } /// Clear from cursor to Start Of Display (EOD), like \c "[1J". void Fl_Terminal::clear_sod(void) { for (int drow=0; drow <= cursor_.row(); drow++) if (drow == cursor_.row()) for (int dcol=0; dcol<=cursor_.col(); dcol++) plot_char(' ', drow, dcol); else for (int dcol=0; dcol[J[0J". void Fl_Terminal::clear_eod(void) { for (int drow=cursor_.row(); drow[K". void Fl_Terminal::clear_eol(void) { Utf8Char *u8c = u8c_disp_row(cursor_.row()) + cursor_.col(); // start at cursor for (int col=cursor_.col(); colclear(*current_style_); //TODO: Clear mouse selection? } /// Clear from cursor to Start Of Line (SOL), like \c "[1K". void Fl_Terminal::clear_sol(void) { Utf8Char *u8c = u8c_disp_row(cursor_.row()); // start at sol for (int col=0; col<=cursor_.col(); col++) // run from sol to cursor (u8c++)->clear(*current_style_); //TODO: Clear mouse selection? } /// Clear entire line for specified row. void Fl_Terminal::clear_line(int drow) { Utf8Char *u8c = u8c_disp_row(drow); // start at sol for (int col=0; colclear(*current_style_); //TODO: Clear mouse selection? } /// Clear entire line cursor is currently on. void Fl_Terminal::clear_line(void) { clear_line(cursor_.row()); } /// Returns true if there's a mouse selection. bool Fl_Terminal::is_selection(void) const { return select_.is_selection(); } /** Walk the mouse selection one character at a time from beginning to end, returning a Utf8Char* to the next character in the selection, or NULL if the end was reached, or if there's no selection. This is easier to use for walking the selection than get_selection(). \p u8c should start out as NULL, rewinding to the beginning of the selection. If the returned Utf8Char* is not NULL, \p row and \p col return the character's row/column position in the ring buffer. \par \code // EXAMPLE: Walk the entire mouse selection, if any int row,col; // the returned row/col for each char Utf8Char *u8c = NULL; // start with NULL to begin walk while ((u8c = walk_selection(u8c, row, col))) { // loop until end char reached ..do something with *u8c.. } \endcode \see get_selection(), is_selection() */ const Fl_Terminal::Utf8Char* Fl_Terminal::walk_selection( const Utf8Char *u8c, ///< NULL on first iter int &row, ///< returned row# int &col ///< returned col# ) const { if (u8c==NULL) { int erow,ecol; // unused if (!get_selection(row,col,erow,ecol)) return NULL; // no selection u8c = u8c_ring_row(row); } else { int srow,scol,erow,ecol; if (!get_selection(srow,scol,erow,ecol)) return NULL; // no selection // At end? done if (row == erow && col == ecol) return NULL; if (++col >= ring_cols()) // advance to next char { col = 0; ++row; } // wrapped to next row? } return u8c_ring_row(row) + col; } /** Return mouse selection's start/end position in the ring buffer, if any. Ensures (start < end) to allow walking 'forward' thru selection, left-to-right, top-to-bottom. The row/col values are indexes into the entire ring buffer. Example: walk the characters of the mouse selection: \par \code // Get selection int srow,scol,erow,ecol; if (get_selection(srow,scol,erow,ecol)) { // mouse selection exists? // Walk entire selection from start to end for (int row=srow; row<=erow; row++) { // walk rows of selection const Utf8Char *u8c = u8c_ring_row(row); // ptr to first character in row int col_start = (row==srow) ? scol : 0; // start row? start at scol int col_end = (row==erow) ? ecol : ring_cols(); // end row? end at ecol u8c += col_start; // include col offset (if any) for (int col=col_start; col<=col_end; col++,u8c++) { // walk columns ..do something with each char at *u8c.. } } } \endcode Returns: - true -- valid selection values returned - false -- no selection was made, returned values undefined \see walk_selection(), is_selection() */ bool Fl_Terminal::get_selection(int &srow, ///< starting row for selection int &scol, ///< starting column for selection int &erow, ///< ending row for selection int &ecol ///< ending column for selection ) const { return select_.get_selection(srow, scol, erow, ecol); } /** Is global row/column inside the current mouse selection? \returns - true -- (\p grow, \p gcol) is inside a valid selection. - false -- (\p grow, \p gcol) is outside, or no valid selection. */ bool Fl_Terminal::is_inside_selection(int grow, int gcol) const { if (!is_selection()) return false; int ncols = ring_cols(); // Calculate row/col magnitudes to simplify test int check = (grow * ncols) + gcol; int start = (select_.srow() * ncols) + select_.scol(); int end = (select_.erow() * ncols) + select_.ecol(); if (start > end) swap(start, end); // ensure (start < end) return (check >= start && check <= end); } // See if global row (grow) is inside the 'display' area // // No wrap case: Wrap case: // ______________ ______________ // ring_srow() -> | | ring_srow() -> | [C] | // | | : | | // | | : | Display | ... // | History | : | | : // | | disp_erow() -> | [C] | : // | | |--------------| : // |______________| | | : Display // disp_srow() -> | [A] | | History | : straddles // : | | | | : end of ring // : | Display | |--------------| : // : | | disp_srow() -> | [D] | ..: // : | | : | Display | // : | | : | | // disp_erow ┬─> | [B] | ring_erow() -> | [D] | // ring_erow ┘ -------------- -------------- // bool Fl_Terminal::is_disp_ring_row(int grow) const { return ring_.is_disp_ring_row(grow); } /** Return byte length of all UTF-8 chars in selection, or 0 if no selection. NOTE: Length includes trailing white on each line. */ int Fl_Terminal::selection_text_len(void) const { int row,col,len=0; const Utf8Char *u8c = NULL; // start with NULL to begin walk while ((u8c = walk_selection(u8c, row, col))) // loop until end char reached len += u8c->length(); return len; } /** Return text selection (for copy()/paste() operations) - Returns allocated NULL terminated string for entire selection. - Caller must free() this memory when done. - Unicode safe. */ const char* Fl_Terminal::selection_text(void) const { if (!is_selection()) return fl_strdup(""); // no selection? empty string // Allocate buff large enough for all UTF-8 chars int clen = 0; // char length int buflen = selection_text_len(); char *buf = (char*)malloc(buflen+1); // +1 for NULL char *bufp = buf; char *nspc = bufp; // last 'non-space' char // Loop from srow,scol .. erow,ecol int row,col; const Utf8Char *u8c = NULL; // start with NULL to begin walk while ((u8c = walk_selection(u8c, row, col))) { // loop until end char reached clen = u8c->length(); // get char length memcpy(bufp, u8c->text_utf8(), clen); // append UTF-8 string to buffer // Handle ignoring trailing whitespace if (!u8c->is_char(' ')) nspc = bufp + clen; // save end pos of last non-spc bufp += clen; // advance into buffer if (col >= (ring_cols()-1)) { // eol? handle trailing white if (nspc && nspc != bufp) { // trailing white space? bufp = nspc; // rewind bufp, and.. *bufp++ = '\n'; // ..append crlf nspc = bufp; // becomes new nspc for nxt row } } } *bufp = 0; return buf; } /// Clear any current mouse selection. void Fl_Terminal::clear_mouse_selection(void) { select_.clear(); } /** Extend selection to FLTK coords X,Y. Returns true if extended, false if nothing done (X,Y offscreen) */ bool Fl_Terminal::selection_extend(int X,int Y) { if (is_selection()) { // selection already? int grow, gcol; bool gcr; if (xy_to_glob_rowcol(X, Y, grow, gcol, gcr) > 0) { select_.extend(grow, gcol, gcr); // extend it return true; } else { // TODO: If X,Y outside row/col area and SHIFT down, // extend selection to nearest edge. } } return false; } /** Select the word around the given row and column. */ void Fl_Terminal::select_word(int grow, int gcol) { int i, c0, c1; int r = grow, c = gcol; Utf8Char *row = u8c_ring_row(r); int n = ring_cols(); if (c >= n) return; if (row[c].text_utf8()[0]==' ') { for (i=c; i>0; i--) if (row[i-1].text_utf8()[0]!=' ') break; c0 = i; for (i=c; i0; i--) if (row[i-1].text_utf8()[0]==' ') break; c0 = i; for (i=c; i 0) update_scrollbar(); // scroll up? changes hist, so scrollbar affected else clear_mouse_selection(); // scroll dn? clear mouse select; it might wrap ring } /** Insert (count) rows at current cursor position. Causes rows below to scroll down, and empty lines created. Lines deleted by scroll down are NOT moved into the scroll history. */ void Fl_Terminal::insert_rows(int count) { int dst_drow = disp_rows()-1; // dst is bottom of display int src_drow = clamp((dst_drow-count), 1, (disp_rows()-1)); // src is count lines up from dst while (src_drow >= cursor_.row()) { // walk srcrow upwards to cursor row Utf8Char *src = u8c_disp_row(src_drow--); Utf8Char *dst = u8c_disp_row(dst_drow--); for (int dcol=0; dcol= cursor_.row()) { // walk srcrow to curs line Utf8Char *dst = u8c_disp_row(dst_drow--); for (int dcol=0; dcolclear(*current_style_); } clear_mouse_selection(); } /** Delete (count) rows at cursor position. Causes rows to scroll up, and empty lines created at bottom of screen. Lines deleted by scroll up are NOT moved into the scroll history. */ void Fl_Terminal::delete_rows(int count) { int dst_drow = cursor_.row(); // dst is cursor row int src_drow = clamp((dst_drow+count), 1, (disp_rows()-1)); // src is count rows below cursor while (src_drow < disp_rows()) { // walk srcrow to EOD Utf8Char *src = u8c_disp_row(src_drow++); Utf8Char *dst = u8c_disp_row(dst_drow++); for (int dcol=0; dcolclear(*current_style_); } clear_mouse_selection(); } // Repeat printing char 'c' for 'rep' times, not to exceed end of line. void Fl_Terminal::repeat_char(char c, int rep) { rep = clamp(rep, 1, disp_cols()); while ( rep-- > 0 && cursor_.col() < disp_cols() ) print_char(c); } /// Insert char 'c' for 'rep' times at display row \p 'drow' and column \p 'dcol'. void Fl_Terminal::insert_char_eol(char c, int drow, int dcol, int rep) { // Walk the row from the eol backwards to the col position // In this example, rep=3: // // dcol // v // BEFORE: |a|b|c|d|e|f|g|h|i|j| <- eol (disp_cols()-1) // | | | | |_____ // src end -> |_____ | <-- src start // | | | | | // v v v v v // AFTER: |a|b|‸|‸|‸|c|d|e|f|g| // |_|_| <-- spaces added last // rep = clamp(rep, 0, disp_cols()); // sanity if (rep == 0) return; const CharStyle &style = *current_style_; Utf8Char *src = u8c_disp_row(drow)+disp_cols()-1-rep; // start src at 'g' Utf8Char *dst = u8c_disp_row(drow)+disp_cols()-1; // start dst at 'j' for (int col=(disp_cols()-1); col>=dcol; col--) { // loop col in reverse: eol -> dcol if (col >= (dcol+rep)) *dst-- = *src--; // let assignment do move else (dst--)->text_ascii(c,style);// assign chars displaced } } /** Insert char 'c' at the current cursor position for 'rep' times. Does not wrap; characters at end of line are lost. */ void Fl_Terminal::insert_char(char c, int rep) { insert_char_eol(c, cursor_.row(), cursor_.col(), rep); } /// Delete char(s) at (drow,dcol) for 'rep' times. void Fl_Terminal::delete_chars(int drow, int dcol, int rep) { rep = clamp(rep, 0, disp_cols()); // sanity if (rep == 0) return; const CharStyle &style = *current_style_; Utf8Char *u8c = u8c_disp_row(drow); for (int col=dcol; col= disp_cols()) u8c[col].text_ascii(' ', style); // blanks else u8c[col] = u8c[col+rep]; // move } /// Delete char(s) at cursor position for 'rep' times. void Fl_Terminal::delete_chars(int rep) { delete_chars(cursor_.row(), cursor_.col(), rep); } /** Clears the scroll history buffer and adjusts scrollbar, forcing it to redraw(). */ void Fl_Terminal::clear_history(void) { // Adjust history use ring_.clear_hist(); scrollbar->value(0); // zero scroll position // Clear entire history buffer for (int hrow=0; hrowclear(*current_style_); } } // Adjust scrollbar (hist_use changed) update_scrollbar(); } /** Resets terminal to default colors, clears screen, history and mouse selection, homes cursor, resets tabstops. Same as \c "c" */ void Fl_Terminal::reset_terminal(void) { current_style_->sgr_reset(); // reset current style clear_screen_home(); // clear screen, home cursor clear_history(); clear_mouse_selection(); default_tabstops(); // reset tabstops to default 8 char } //DEBUG void Fl_Terminal::RingBuffer::show_ring_info(void) const { //DEBUG ::printf("\033[s"); // save cursor //DEBUG ::printf("\033[05C -- Ring Index\n"); //DEBUG ::printf("\033[05C ring_rows_: %d\n", ring_rows_); //DEBUG ::printf("\033[05C ring_cols_: %d\n", ring_cols_); //DEBUG ::printf("\033[05C offset_: %d\n", offset_); //DEBUG ::printf("\033[u"); // restore cursor //DEBUG ::printf("\033[30C -- History Index\n"); //DEBUG ::printf("\033[30C hist_rows_: %d srow=%d\n", hist_rows(), hist_srow()); //DEBUG ::printf("\033[30C hist_cols_: %d erow=%d\n", hist_cols(), hist_erow()); //DEBUG ::printf("\033[30C hist_use_: %d\n", hist_use()); //DEBUG ::printf("\033[u"); // restore cursor //DEBUG ::printf("\033[60C -- Display Index\n"); //DEBUG ::printf("\033[60C disp_rows_: %d srow=%d\n", disp_rows(), disp_srow()); //DEBUG ::printf("\033[60C disp_cols_: %d erow=%d\n", disp_cols(), disp_erow()); //DEBUG ::printf("\n\n"); //DEBUG } //DEBUG // Save specified row from ring buffer 'ring' to FILE* //DEBUG void Fl_Terminal::write_row(FILE *fp, Utf8Char *u8c, int cols) const { //DEBUG cols = (cols != 0) ? cols : ring_cols(); //DEBUG for (int col=0; collength(), u8c->text_utf8()); //DEBUG } //DEBUG } //DEBUG // Show two buffers side-by-side on stdout. //DEBUG // Second buffer can be NULL to just show the a buffer. //DEBUG // //DEBUG void Fl_Terminal::show_buffers(RingBuffer *a, RingBuffer *b) const { //DEBUG int arows = a->ring_rows(), acols = a->ring_cols(); //DEBUG int brows = b ? b->ring_rows() : 0, bcols = b ? b->ring_cols() : 0; //DEBUG int trows = MAX(arows,brows); //DEBUG // Show header //DEBUG ::printf("\033[H"); //DEBUG if (a) ::printf("SRC %d x %d huse=%d off=%d", arows,acols, a->hist_use(), a->offset()); //DEBUG if (b) ::printf(", DST %d x %d huse=%d off=%d", brows, bcols, b->hist_use(), b->offset()); //DEBUG ::printf("\033[K\n"); //DEBUG Utf8Char *u8c; //DEBUG // Show rows //DEBUG for (int row=0; row < trows; row++) { //DEBUG // 'A' buffer //DEBUG if (row >= arows) { //DEBUG ::printf(" %*s ", acols, ""); //DEBUG } else { //DEBUG u8c = a->ring_chars()+(arows*acols); //DEBUG ::printf("%3d/%3d [", row, trows-1); write_row(stdout, u8c, acols); ::printf("] "); //DEBUG } //DEBUG if (!b) { ::printf("\033[K\n"); continue; } //DEBUG // 'B' buffer //DEBUG if (row < brows) { //DEBUG u8c = b->ring_chars()+(brows*bcols); //DEBUG ::printf("["); write_row(stdout, u8c, bcols); ::printf("]"); //DEBUG } //DEBUG ::printf("\033[K\n"); //DEBUG } //DEBUG ::printf("--- END\033[0J\n"); // clear eos //DEBUG ::printf(" HIT ENTER TO CONTINUE: "); getchar(); //DEBUG fflush(stdout); //DEBUG } /////////////////////////////// ////// CURSOR MANAGEMENT ////// /////////////////////////////// /** Set the cursor's foreground color used for text under the cursor. */ void Fl_Terminal::cursorfgcolor(Fl_Color val) { cursor_.fgcolor(val); } /** Set the cursor's background color used for the cursor itself. */ void Fl_Terminal::cursorbgcolor(Fl_Color val) { cursor_.bgcolor(val); } /** Get the cursor's foreground color used for text under the cursor. */ Fl_Color Fl_Terminal::cursorfgcolor(void) const { return cursor_.fgcolor(); } /** Get the cursor's background color used for the cursor itself. */ Fl_Color Fl_Terminal::cursorbgcolor(void) const { return cursor_.bgcolor(); } /** Move cursor to the specified row \p row. This value is clamped to the range (0..display_rows()-1). */ void Fl_Terminal::cursor_row(int row) { cursor_.row( clamp(row,0,disp_rows()-1) ); } /** Move cursor to the specified column \p col. This value is clamped to the range (0..display_columns()-1). */ void Fl_Terminal::cursor_col(int col) { cursor_.col( clamp(col,0,disp_cols()-1) ); } /** Return the cursor's current row position on the screen. */ int Fl_Terminal::cursor_row(void) const { return cursor_.row(); } /** Return the cursor's current column position on the screen. */ int Fl_Terminal::cursor_col(void) const { return cursor_.col(); } /** Moves cursor up \p count lines. If cursor hits screen top, it either stops (does not wrap) if \p do_scroll is false, or scrolls down if \p do_scroll is true. */ void Fl_Terminal::cursor_up(int count, bool do_scroll) { count = clamp(count, 1, disp_rows() * 2); // sanity (max 2 scrns) while (count-- > 0) { if (cursor_.up() <= 0) { // hit screen top? cursor_.row(0); // clamp cursor to top if (do_scroll) scroll(-1); // scrolling on? scroll down else return; // scrolling off? stop at top } } } /** Moves cursor down \p count lines. If cursor hits screen bottom, it either stops (does not wrap) if \p do_scroll is false, or wraps and scrolls up if \p do_scroll is true. */ void Fl_Terminal::cursor_down(int count, ///< Number of lines to move cursor down bool do_scroll ///< Enable scrolling if set to true ) { count = clamp(count, 1, ring_rows()); // sanity while (count-- > 0) { if (cursor_.down() >= disp_rows()) { // hit screen bottom? cursor_.row(disp_rows() - 1); // clamp if (!do_scroll) break; // don't scroll? done scroll(1); // scroll up 1 row to make room for new line } } } /** Moves cursor left \p count columns, and cursor stops (does not wrap) if it hits screen edge. */ void Fl_Terminal::cursor_left(int count) { count = clamp(count, 1, disp_cols()); // sanity while (count-- > 0 ) if (cursor_.left() < 0) // hit left edge of screen? { cursor_sol(); return; } // stop, done } /** Moves cursor right \p count columns. If cursor hits right edge of screen, it either stops (does not wrap) if \p do_scroll is false, or wraps and scrolls up one line if \p do_scroll is true. */ void Fl_Terminal::cursor_right(int count, bool do_scroll) { while (count-- > 0) { if (cursor_.right() >= disp_cols()) { // hit right edge? if (!do_scroll) // no scroll? { cursor_eol(); return; } // stop at EOL, done else { cursor_crlf(1); } // do scroll? crlf } } } /** Move cursor to the home position (top/left). */ void Fl_Terminal::cursor_home(void) { cursor_.col(0); cursor_.row(0); } /** Move cursor to the last column (at the far right) on the current line. */ void Fl_Terminal::cursor_eol(void) { cursor_.col(disp_cols()-1); } /** Move cursor to the first column (at the far left) on the current line. */ void Fl_Terminal::cursor_sol(void) { cursor_.col(0); } /** Move cursor as if a CR (\\r) was received. Same as cursor_sol() */ void Fl_Terminal::cursor_cr(void) { cursor_sol(); } /** Move cursor as if a CR/LF pair (\\r\\n) was received. */ void Fl_Terminal::cursor_crlf(int count) { const bool do_scroll = true; count = clamp(count, 1, ring_rows()); // sanity cursor_sol(); cursor_down(count, do_scroll); } /// Tab right, do not wrap beyond right edge. void Fl_Terminal::cursor_tab_right(int count) { count = clamp(count, 1, disp_cols()); // sanity int X = cursor_.col(); while (count-- > 0) { // Find next tabstop while (++X < disp_cols()) { if ( (X 0 ) while ( --X > 0 ) // search for tabstop if ( (X=0x20) && (c<=0x7e)); } // Is char a ctrl character? (0x00 thru 0x1f) bool Fl_Terminal::is_ctrl(char c) { return ((c >= 0x00) && (c < 0x20)) ? true : false; } // Handle ESC[m sequences. // This is different from the others in that the list of vals // separated by ;'s can be long, to allow combining multiple mode // settings at once, e.g. fg and bg colors, multiple attributes, etc. // void Fl_Terminal::handle_SGR(void) { // ESC[...m? // Shortcut varnames.. EscapeSeq &esc = escseq; int tot = esc.total_vals(); // Handle ESC[m or ESC[;m if (tot == 0) { current_style_->sgr_reset(); return; } // Handle ESC[#;#;#...m int rgbcode = 0; // 0=none, 38=fg, 48=bg int rgbmode = 0; // 0=none, 1="2", 2=, 3=, 4= int r=0,g=0,b=0; for (int i=0; i;;m case 48: // bg RGB mode? e.g. ESC[48;2;;;m rgbmode = 1; rgbcode = val; continue; } break; case 1: if (val == 2) { rgbmode++; continue; } // '2'? rgbcode = rgbmode = 0; // not '2'? cancel handle_unknown_char(); break; case 2: r=clamp(val,0,255); ++rgbmode; continue; // parse red value case 3: g=clamp(val,0,255); ++rgbmode; continue; // parse grn value case 4: b=clamp(val,0,255); // parse blu value switch (rgbcode) { case 38: current_style_->fgcolor(r,g,b); // Set fg rgb break; case 48: current_style_->bgcolor(r,g,b); // Set bg rgb break; } rgbcode = rgbmode = 0; // done w/rgb mode parsing continue; // continue loop to parse more vals } if (val < 10) { // Set attribute? (bold,underline..) switch (val) { case 0: current_style_->sgr_reset(); break; // ESC[0m - reset case 1: current_style_->sgr_bold(1); break; // ESC[1m - bold case 2: current_style_->sgr_dim(1); break; // ESC[2m - dim case 3: current_style_->sgr_italic(1); break; // ESC[3m - italic case 4: current_style_->sgr_underline(1);break; // ESC[4m - underline case 5: current_style_->sgr_blink(1); break; // ESC[5m - blink case 6: handle_unknown_char(); break; // ESC[6m - (unused) case 7: current_style_->sgr_inverse(1); break; // ESC[7m - inverse case 8: handle_unknown_char(); break; // ESC[8m - (unused) case 9: current_style_->sgr_strike(1); break; // ESC[9m - strikeout } } else if (val >= 21 && val <= 29) { // attribute extras switch (val) { case 21: current_style_->sgr_dbl_under(1);break; // ESC[21m - doubly underline case 22: current_style_->sgr_dim(0); // ESC[22m - disable bold/dim current_style_->sgr_bold(0); break; // case 23: current_style_->sgr_italic(0); break; // ESC[23m - disable italic case 24: current_style_->sgr_underline(0);break; // ESC[24m - disable underline case 25: current_style_->sgr_blink(0); break; // ESC[25m - disable blink case 26: handle_unknown_char(); break; // ESC[26m - (unused) case 27: current_style_->sgr_inverse(0); break; // ESC[27m - disable inverse case 28: handle_unknown_char(); break; // ESC[28m - disable hidden case 29: current_style_->sgr_strike(0); break; // ESC[29m - disable strikeout } } else if (val >= 30 && val <= 37) { // Set fg color? uchar uval = (val - 30); current_style_->fgcolor_xterm(uval); } else if (val == 39) { // ESC[39m -- "normal" fg color: Fl_Color fg = current_style_->defaultfgcolor(); // ..get default color current_style_->fgcolor_xterm(fg); // ..set current color } else if (val >= 40 && val <= 47) { // Set bg color? uchar uval = (val - 40); current_style_->bgcolor_xterm(uval); } else if (val == 49) { // ESC[49m -- "normal" bg color: Fl_Color bg = current_style_->defaultbgcolor(); // ..get default bg color current_style_->bgcolor_xterm(bg); // ..set current bg color } else { handle_unknown_char(); // does an escseq.reset() // unimplemented SGR codes } } } /** Handle the VT100 sequence ESC [ top ; lt ; bot ; rt ; att $ t top/lt/bot/rt is the screen area to affect, 'att' is the attrib to xor, i.e. 1(bold),4,5,7(inverse). \note - gnome-term doesn't support this, but xterm does. - Currently unsupported by Fl_Terminal */ void Fl_Terminal::handle_DECRARA(void) { // TODO: MAYBE NEVER } /** Handle an escape sequence character. Call this on a character only if escseq.parse_in_progress() is true. If this char is the end of the sequence, do the operation (if possible), then does an escseq.reset() to finish parsing. */ void Fl_Terminal::handle_escseq(char c) { // NOTE: Use xterm to test. gnome-terminal has bugs, even in 2022. const bool do_scroll = true; const bool no_scroll = false; switch (escseq.parse(c)) { // parse char, advance s.. case EscapeSeq::fail: // failed? escseq.reset(); // ..reset to let error_char be visible handle_unknown_char(); // ..show error char (if enabled) print_char(c); // ..show char we couldn't handle return; // ..done. case EscapeSeq::success: // success? return; // ..keep parsing case EscapeSeq::completed: // parsed complete esc sequence? break; // ..fall through to handle operation } // Shortcut varnames for escseq parsing.. EscapeSeq &esc = escseq; char mode = esc.esc_mode(); int tot = esc.total_vals(); int val0 = (tot==0) ? 0 : esc.val(0); int val1 = (tot<2) ? 0 : esc.val(1); const int& dw = disp_cols(); const int& dh = disp_rows(); if (esc.is_csi()) { // Was this a CSI (ESC[..) sequence? switch (mode) { case '@': // [#@ - (ICH) Insert blank Chars (default=1) insert_char(' ', esc.defvalmax(1,dw)); break; case 'A': // [#A - (CUU) cursor up, no scroll/wrap cursor_up(esc.defvalmax(1,dh)); break; case 'B': // [#B - (CUD) cursor down, no scroll/wrap cursor_down(esc.defvalmax(1,dh), no_scroll); break; case 'C': // [#C - (CUF) cursor right, no wrap cursor_right(esc.defvalmax(1,dw), no_scroll); break; case 'D': // [#D - (CUB) cursor left, no wrap cursor_left(esc.defvalmax(1,dw)); break; case 'E': // [#E - (CNL) cursor next line (crlf) xterm, !gnome cursor_crlf(esc.defvalmax(1,dh)); break; case 'F': // [#F - (CPL) move to sol and up # lines cursor_cr(); cursor_up(esc.defvalmax(1,dh)); break; case 'G': // [#G - (CHA) cursor horizal absolute switch (clamp(tot,0,1)) { // │ case 0: // ├── [G -- move to sol cursor_sol(); // │ default [1G break; // │ case 1: // └── [#G -- move to column cursor_col(clamp(val0,1,dw)-1); break; } break; case 'H': cup: switch (clamp(tot,0,2)) { // [#H - (CUP) cursor position (#'s are 1 based) case 0: // ├── [H -- no vals? cursor_home(); // │ default [1H break; // │ case 1: // ├── [#H -- go to (row #) cursor_row(clamp(val0,1,dh)-1); // │ NOTE: ESC[5H == ESC[5;1H cursor_col(0); // │ break; // │ case 2: // └── [#;#H -- go to (row# ; col#) cursor_row(clamp(val0,1,dh)-1); cursor_col(clamp(val1,1,dw)-1); break; } break; case 'I': // [#I - (CHT) cursor forward tab (default=1) switch (clamp(tot,0,1)) { // │ case 0: // ├── [I -- no vals cursor_tab_right(1); // │ default [1I break; // │ case 1: // └── [#I -- tab # times cursor_tab_right(clamp(val0,1,dw)); // break; } break; case 'J': // [#J - (ED) erase in display switch (clamp(tot,0,1)) { // │ case 0: clear_eol(); break; // ├── [J -- no vals: default [0J case 1: // │ switch (clamp(val0,0,3)) { // │ case 0: clear_eod(); break; // ├── [0J -- clear to end of display case 1: clear_sod(); break; // ├── [1J -- clear to start of display case 2: clear_screen(); break; // ├── [2J -- clear all lines case 3: clear_history(); break; // └── [3J -- clear screen history } break; } break; case 'K': switch (clamp(tot,0,1)) { // [#K - (EL) Erase in Line case 0: clear_eol(); break; // ├── [K -- no vals case 1: switch (clamp(val0,0,2)) { // │ case 0: clear_eol(); break; // ├── [0K -- clear to end of line case 1: clear_sol(); break; // ├── [1K -- clear to start of line case 2: clear_line(); break; // └── [2K -- clear current line } break; } break; case 'L': // ESC[#L - Insert # lines (def=1) insert_rows(esc.defvalmax(1,dh)); break; case 'M': // ESC[#M - Delete # lines (def=1) delete_rows(esc.defvalmax(1,dh)); break; case 'P': // ESC[#P - Delete # chars (def=1) delete_chars(esc.defvalmax(1,dh)); break; case 'S': // ESC[#S - scroll up # lines (def=1) scroll( +(esc.defvalmax(1,dh)) ); // ⮤ positive=scroll up break; case 'T': // ESC[#T - scroll dn # lines (def=1) scroll( -(esc.defvalmax(1,dh)) ); // ⮤ negative=scroll down break; case 'X': // [#X - (ECH) Erase Characters (default=1) repeat_char(' ', esc.defvalmax(1,dw)); break; case 'Z': // ESC[#Z - backtab # tabs switch (clamp(tot,0,1)) { // │ case 0: // ├── [Z -- no vals cursor_tab_left(1); // │ default [1Z break; // │ case 1: // └── [#Z -- tab # times cursor_tab_left(clamp(val0,1,dw)); break; } break; case 'a': // TODO // ESC[#a - (HPR) move cursor relative [columns] (default=[row,col+1]) case 'b': // TODO // ESC[#b - (REP) repeat prev graphics char # times case 'd': // TODO // ESC[#d - (VPA) line pos absolute [row] case 'e': // TODO // ESC[#e - line pos relative [rows] handle_unknown_char(); // does an escseq.reset() break; case 'f': // [#f - (CUP) cursor position (#'s 1 based) goto cup; // (same as ESC[H) case 'g': // ESC[...g? Tabulation Clear (TBC) switch (val0) { case 0: clear_tabstop(); break; // clears tabstop at cursor case 3: clear_all_tabstops(); break; // clears all tabstops default: handle_unknown_char(); // does an escseq.reset() break; } break; case 'm': handle_SGR(); break; // ESC[#m - set character attributes (SGR) case 's': save_cursor(); break; // ESC[s - save cur pos (xterm+gnome) case 'u': restore_cursor(); break; // ESC[u - restore cur pos (xterm+gnome) case 'q': // TODO? // ESC[>#q set cursor style (block/line/blink..) case 'r': // TODO // ESC[#;#r set scroll region top;bot // default=full window handle_unknown_char(); // does an escseq.reset() break; case 't': handle_DECRARA(); break; // ESC[#..$t -- (DECRARA) // Reverse attribs in Rect Area (row,col) default: handle_unknown_char(); // does an escseq.reset() break; } } else { // Not CSI? Might be C1 Control code (D, etc) switch (esc.esc_mode()) { case 'c': reset_terminal(); break;// c - Reset term to Initial State (RIS) case 'D': cursor_down(1, do_scroll); break;// D - down line, scroll at bottom case 'E': cursor_crlf(); break;// E - do a crlf case 'H': set_tabstop(); break;// H - set a tabstop case 'M': cursor_up(1, true); break;// M - (RI) Reverse Index (up w/scroll) case '7': handle_unknown_char(); break;// 7 - Save cursor & attrs // TODO case '8': handle_unknown_char(); break;// 8 - Restore cursor & attrs // TODO default: handle_unknown_char(); // does an escseq.reset() break; } } esc.reset(); // done handling escseq, reset() } /** Clears that the display has been modified; sets internal redraw_modified_ to false. */ void Fl_Terminal::display_modified_clear(void) { redraw_modified_ = false; } /** Flag that the display has been modified, triggering redraws. Sets the internal redraw_modified_ flag to true. */ void Fl_Terminal::display_modified(void) { if (is_redraw_style(RATE_LIMITED)) { if (!redraw_modified_) { // wasn't before but now is? if (!redraw_timer_) { Fl::add_timeout(.01, redraw_timer_cb, this); // turn on timer redraw_timer_ = true; } redraw_modified_ = true; } } else if (is_redraw_style(PER_WRITE)) { if (!redraw_modified_) { redraw_modified_ = true; redraw(); // only call redraw once } } else { // NO_REDRAW? // do nothing } } /** Clear the character at the specified display row and column. No range checking done on drow,dcol: - \p drow must be in range 0..(disp_rows()-1) - \p dcol must be in range 0..(disp_cols()-1) - Does not trigger redraws */ void Fl_Terminal::clear_char_at_disp(int drow, int dcol) { Utf8Char *u8c = u8c_disp_row(drow) + dcol; u8c->clear(*current_style_); } /** Return Utf8Char* for char at specified display row and column. This accesses any character in the display part of the ring buffer. No range checking done on drow,dcol: - \p drow must be in range 0..(disp_rows()-1) - \p dcol must be in range 0..(disp_cols()-1) \see u8c_disp_row() */ const Fl_Terminal::Utf8Char* Fl_Terminal::utf8_char_at_disp(int drow, int dcol) const { return u8c_disp_row(drow) + dcol; } /** Return Utf8Char* for char at specified global (grow,gcol). This accesses any character in the ring buffer (history + display). No range checking done on grow,gcol: - \p grow must be in range 0..(ring_rows()-1) - \p gcol must be in range 0..(ring_cols()-1) \see u8c_ring_row() */ const Fl_Terminal::Utf8Char* Fl_Terminal::utf8_char_at_glob(int grow, int gcol) const { return u8c_ring_row(grow) + gcol; } /** Plot the UTF-8 character \p text of length \p len at display position \p (drow,dcol). The character is displayed using the current text color/attributes. This is a very low level method. No range checking is done on drow,dcol: - \p drow must be in range 0..(display_rows()-1) - \p dcol must be in range 0..(display_columns()-1) - Does not trigger redraws - Does not handle control codes, ANSI or XTERM escape sequences. - Invalid UTF-8 chars show the error character (¿) depending on show_unknown(bool). \see handle_unknown_char() */ void Fl_Terminal::plot_char(const char *text, int len, int drow, int dcol) { Utf8Char *u8c = u8c_disp_row(drow) + dcol; // text_utf8() warns we must do invalid checks first if (!text || len<1 || len>u8c->max_utf8() || len!=fl_utf8len(*text)) { handle_unknown_char(drow, dcol); return; } u8c->text_utf8(text, len, *current_style_); } /** Plot the ASCII character \p c at the terminal's display position \p (drow,dcol). The character MUST be printable (in range 0x20 - 0x7e), and is displayed using the current text color/attributes. Characters outside that range are either ignored or print the error character (¿), depending on show_unknown(bool). This is a very low level method. No range checking is done on drow,dcol: - \p drow must be in range 0..(display_rows()-1) - \p dcol must be in range 0..(display_columns()-1) - Does not trigger redraws - Does NOT handle control codes, ANSI or XTERM escape sequences. \see show_unknown(bool), handle_unknown_char(), is_printable() */ void Fl_Terminal::plot_char(char c, int drow, int dcol) { if (!is_printable(c)) { handle_unknown_char(drow, dcol); return; } Utf8Char *u8c = u8c_disp_row(drow) + dcol; u8c->text_ascii(c, *current_style_); } /** Prints single UTF-8 char \p text of optional byte length \p len at current cursor position, and advances the cursor if the character is printable. Handles ASCII and control codes (CR, LF, etc). The character is displayed at the current cursor position using the current text color/attributes. Handles control codes and can be used to construct ANSI/XTERM escape sequences. - If optional \p len isn't specified or <0, strlen(text) is used. - \p text must not be NULL. - \p len must not be 0. - \p text must be a single char only (whether UTF-8 or ASCII) - \p text can be an ASCII character, though not as efficent as print_char() - Invalid UTF-8 chars show the error character (¿) depending on show_unknown(bool). - Does not trigger redraws \see show_unknown(bool), handle_unknown_char() */ void Fl_Terminal::print_char(const char *text, int len/*=-1*/) { len = len<0 ? fl_utf8len(*text) : len; // int(strlen(text)) : len; const bool do_scroll = true; if (is_ctrl(text[0])) { // Handle ctrl character handle_ctrl(*text); } else if (escseq.parse_in_progress()) { // ESC sequence in progress? handle_escseq(*text); } else { // Handle printable char.. plot_char(text, len, cursor_row(), cursor_col()); cursor_right(1, do_scroll); } } /** Prints single ASCII char \p c at current cursor position, and advances the cursor. The character is displayed at the current cursor position using the current text color/attributes. - \p c must be ASCII, not utf-8 - Does not trigger redraws */ void Fl_Terminal::print_char(char c) { const bool do_scroll = true; if (is_ctrl(c)) { // Handle ctrl character handle_ctrl(c); } else if (escseq.parse_in_progress()) { // ESC sequence in progress? handle_escseq(c); } else { // Handle printable char.. plot_char(c, cursor_row(), cursor_col()); cursor_right(1, do_scroll); return; } } // Clear the Partial UTF-8 Buffer cache void Fl_Terminal::utf8_cache_clear(void) { pub_.clear(); } // Flush the Partial UTF-8 Buffer cache, and clear void Fl_Terminal::utf8_cache_flush(void) { if (pub_.buflen() > 0) print_char(pub_.buf(), pub_.buflen()); pub_.clear(); } /** Append NULL terminated UTF-8 string to terminal. - If buf is NULL, UTF-8 cache buffer is cleared - If optional \p len isn't specified or is -1, strlen(text) is used. - If \p len is 0 or <-1, no changes are made - Handles UTF-8 chars split across calls (e.g. block writes from pipes, etc) - Redraws are triggered automatically, depending on redraw_style() */ void Fl_Terminal::append_utf8(const char *buf, int len/*=-1*/) { int mod = 0; // assume no modifications if (!buf) { utf8_cache_clear(); return; } // clear cache, done if (len == -1) len = int(strlen(buf)); // len optional if (len<=0) return; // bad len? early exit // Handle any partial UTF-8 from last write // Try to parse up rest of incomplete buffered char from end // of last block, and flush it to terminal. // if (pub_.buflen() > 0) { // partial UTF-8 to deal with? while (len>0 && pub_.is_continuation(*buf)) { // buffer 'continuation' chars if (pub_.append(buf, 1) == false) // append byte to partial UTF-8 buffer { mod |= handle_unknown_char(); break; } // overrun? break loop else { buf++; len--; } // shrink our buffer } if (pub_.is_complete()) utf8_cache_flush(); // complete UTF-8 captured? flush to tty if (len <= 0) { // check len again, we may have run out if (mod) display_modified(); return; } } // For sure buf is now pointing at a valid char, so walk to end of buffer int clen; // char length const char *p = buf; // ptr to walk buffer while (len>0) { clen = fl_utf8len(*p); // how many bytes long is this char? if (clen == -1) { // not expecting bad UTF-8 here mod |= handle_unknown_char(); p += 1; len -= 1; } else { if (len && clen>len) { // char longer than buffer? if (pub_.append(p, len) == false) { // buffer it mod |= handle_unknown_char(); utf8_cache_clear(); } break; } print_char(p, clen); // write complete UTF-8 char to terminal p += clen; // advance to next char len -= clen; // adjust len mod |= 1; } } if (mod) display_modified(); } /** Append NULL terminated ASCII string to terminal, slightly more efficient than append_utf8(). - If \p s is NULL, behavior is to do nothing - Redraws are triggered automatically, depending on redraw_style() */ void Fl_Terminal::append_ascii(const char *s) { if (!s) return; while ( *s ) print_char(*s++); // handles display_modified() display_modified(); } /** Appends string \p s to the terminal at the current cursor position using the current text color/attributes. If \p s is NULL, the UTF-8 character cache is cleared, which is recommended before starting a block reading loop, and again after the block loop has completed. If \p len is not specified, it's assumed \p s is a NULL terminated string. If \p len IS specified, it can be used for writing strings that aren't NULL terminated, such as block reads on a pipe, network, or other block oriented data source. Redraws of the terminal widget are by default handled automatically, but can be changed with redraw_rate() and redraw_style(). Block I/O When reading block oriented sources (such as pipes), append() will handle partial UTF-8 chars straddling the block boundaries. It does this using an internal byte cache, which should be cleared before and after block I/O loops by calling append(NULL) as shown in the example below, to prevent the possibilities of partial UTF-8 characters left behind by an interrupted or incomplete block loop. \par \code // Example block reading a command pipe in Unix // Run command and read as a pipe FILE *fp = popen("ls -la", "r"); if (!fp) { ..error_handling.. } // Enable non-blocking I/O int fd = fileno(fp); fcntl(fd, F_SETFL, O_NONBLOCK); // Clear UTF-8 character cache before starting block loop G_tty->append(NULL); // prevents leftover partial UTF-8 bytes // Block read loop while (1) { Fl::wait(0.05); // give fltk .05 secs of cpu to manage UI ssize_t bytes = read(fd, s, sizeof(s)); // read block from pipe if (bytes == -1 && errno == EAGAIN) continue; // no data yet? continue if (bytes > 0) G_tty->append(s); // append output to terminal else break; // end of pipe? } // Flush cache again after block loop completes G_tty->append(NULL); // Close pipe, done pclose(fp); \endcode \note - String can contain ASCII or UTF-8 chars - \p len is optional; if unspecified, expects \p s to be a NULL terminated string - Handles partial UTF-8 chars split between calls (e.g. block oriented writes) - If \p s is NULL, this clears the "partial UTF-8" character cache - Redraws are managed automatically by default; see redraw_style() */ void Fl_Terminal::append(const char *s, int len/*=-1*/) { append_utf8(s, len); } /** Handle an unknown char by either emitting an error symbol to the tty, or do nothing, depending on the user configurable value of show_unknown(). This writes the "unknown" character to the output stream if show_unknown() is true. Returns 1 if tty modified, 0 if not. \see show_unknown() */ int Fl_Terminal::handle_unknown_char(void) { if (!show_unknown_) return 0; escseq.reset(); // disable any pending esc seq to prevent eating unknown char print_char(error_char_); return 1; } /** Handle an unknown char by either emitting an error symbol to the tty, or do nothing, depending on the user configurable value of show_unknown(). This writes the "unknown" character to the display position \p (drow,dcol) if show_unknown() is true. Returns 1 if tty modified, 0 if not. \see show_unknown() */ int Fl_Terminal::handle_unknown_char(int drow, int dcol) { if (!show_unknown_) return 0; int len = (int)strlen(error_char_); Utf8Char *u8c = u8c_disp_row(drow) + dcol; u8c->text_utf8(error_char_, len, *current_style_); return 1; } // Handle user interactive scrolling // Note: this callback shared by vertical and horizontal scrollbars // void Fl_Terminal::scrollbar_cb(Fl_Widget*, void* userdata) { Fl_Terminal *o = (Fl_Terminal*)userdata; o->redraw(); } // Handle mouse selection autoscrolling void Fl_Terminal::autoscroll_timer_cb2(void) { // Move scrollbar // NOTE: scrollbar is inverted; 0=tab at bot, so minimum() is really max // int amt = autoscroll_amt_; // (amt<0):above top, (amt>0):below bottom int val = scrollbar->value(); int max = int(scrollbar->minimum()+.5); // NOTE: minimum() is really max val = (amt<0) ? (val+clamp((-amt/10),1,5)) : // above top edge? (amt>0) ? (val-clamp((+amt/10),1,5)) : 0; // below bot edge? val = clamp(val,0,max); // limit val to scroll's range int diff = ABS(val - scrollbar->value()); // how far scroll tab moved up/dn // Move scrollbar scrollbar->value(val); // Extend selection if (diff) { // >0 if up or down int srow = select_.srow(), scol = select_.scol(); int erow = select_.erow(), ecol = select_.ecol(); int ltcol = 0, rtcol = ring_cols() - 1; if (amt<0) { erow -= diff; ecol = ltcol; } // above top? use erow: reverse-selecting if (amt>0) { erow += diff; ecol = rtcol; } // below bot? use erow: forward-selecting select_.select(srow, scol, erow, ecol); } // Restart timeout Fl::repeat_timeout(.1, autoscroll_timer_cb, this); redraw(); } // Handle mouse selection autoscrolling void Fl_Terminal::autoscroll_timer_cb(void *udata) { Fl_Terminal *tty = (Fl_Terminal*)udata; tty->autoscroll_timer_cb2(); } // Handle triggering rate limited redraw() updates // When data comes in quickly, append() sets the redraw_modified_ flag // so our timer can trigger the redraw()s at a controlled rate. // void Fl_Terminal::redraw_timer_cb2(void) { //DRAWDEBUG ::printf("--- UPDATE TICK %.02f\n", redraw_rate_); fflush(stdout); if (redraw_modified_) { redraw(); // Timer triggered redraw redraw_modified_ = false; // acknowledge modified flag Fl::repeat_timeout(redraw_rate_, redraw_timer_cb, this); // restart timer } else { // Timer went off and nothing to redraw? disable Fl::remove_timeout(redraw_timer_cb, this); redraw_timer_ = false; } } void Fl_Terminal::redraw_timer_cb(void *udata) { Fl_Terminal *tty = (Fl_Terminal*)udata; tty->redraw_timer_cb2(); } /** The constructor for Fl_Terminal. This creates an empty terminal with defaults: - white on black text; see textfgcolor(Fl_Color), textbgcolor(Fl_Color) - rows/cols based on the \p W and \p H values, see display_rows(), display_columns() - scrollback history of 100 lines, see history_rows() - redraw_style() set to RATE_LIMITED, redraw_rate() set to 0.10 seconds Note: While Fl_Terminal derives from Fl_Group, it's not intended for user code to use it as a parent for other widgets, so end() is called. \param[in] X,Y,W,H position and size. \param[in] L label string (optional), may be NULL. */ Fl_Terminal::Fl_Terminal(int X,int Y,int W,int H,const char*L) : Fl_Group(X,Y,W,H,L), select_(this) { bool fontsize_defer = false; init_(X,Y,W,H,L,-1,-1,100,fontsize_defer); } /** Same as the default FLTK constructor, but lets the user force the rows, columns and history to specific sizes on creation. Since the row/cols/hist are specified directly, this prevents the widget from auto-calculating the initial text buffer size based on the widget's pixel width/height, bypassing calls to the font system before the widget is displayed. \note fluid uses this constructor internally to avoid font calculations that opens the display, useful for when running in a headless context. (issue 837) */ Fl_Terminal::Fl_Terminal(int X,int Y,int W,int H,const char*L,int rows,int cols,int hist) : Fl_Group(X,Y,W,H,L), select_(this) { bool fontsize_defer = true; init_(X,Y,W,H,L,rows,cols,hist,fontsize_defer); } // Private constructor method void Fl_Terminal::init_(int X,int Y,int W,int H,const char*L,int rows,int cols,int hist,bool fontsize_defer) { error_char_ = "¿"; scrollbar = hscrollbar = 0; // avoid problems w/update_screen_xywh() // currently unused params (void)X; (void)Y; (void)W; (void)H; (void)L; fontsize_defer_ = fontsize_defer; // defer font calls until draw() (issue 837) current_style_ = new CharStyle(fontsize_defer); oflags_ = LF_TO_CRLF; // default: "\n" handled as "\r\n" // scrollbar_size must be set before scrn_ scrollbar_size_ = 0; // 0 uses Fl::scrollbar_size() Fl_Group::box(FL_DOWN_FRAME); // set before update_screen_xywh() update_screen_xywh(); // Tabs tabstops_ = 0; tabstops_size_ = 0; // Init ringbuffer. Also creates default tabstops if (rows == -1 || cols == -1) { int newrows = h_to_row(scrn_.h()); // rows based on height int newcols = w_to_col(scrn_.w()); // cols based on width // Sanity check newrows = (newrows >= 1) ? newrows : 1; newcols = (newcols >= 1) ? newcols : 1; create_ring(newrows, newcols, hist); } else { create_ring(rows, cols, 100); } // Misc redraw_style_ = RATE_LIMITED; // NO_REDRAW, RATE_LIMITED, PER_WRITE redraw_rate_ = 0.10f; // maximum rate in seconds (1/10=10fps) redraw_modified_ = false; // display 'modified' flag redraw_timer_ = false; autoscroll_dir_ = 0; autoscroll_amt_ = 0; // Create scrollbars // Final position/size/parameters are set by update_screen() ** // scrollbar = new Fl_Scrollbar(x(), y(), scrollbar_actual_size(), h()); // tmp xywh (changed later) ** scrollbar->type(FL_VERTICAL); scrollbar->value(0); scrollbar->callback(scrollbar_cb, (void*)this); hscrollbar = new Fl_Scrollbar(x(), y(), w(), scrollbar_actual_size()); // tmp xywh (changed later) ** hscrollbar->type(FL_HORIZONTAL); hscrollbar->value(0); hscrollbar->callback(scrollbar_cb, (void *)this); hscrollbar_style_ = SCROLLBAR_AUTO; resizable(0); Fl_Group::color(FL_BLACK); // black bg by default update_screen(true); // update internal vars after setting screen size/font clear_screen_home(); // clear screen, home cursor clear_history(); // clear history buffer show_unknown_ = false; // default "off" ansi_ = true; // default "on" // End group end(); } /** The destructor for Fl_Terminal. Destroys the terminal display, scroll history, and associated widgets. */ Fl_Terminal::~Fl_Terminal(void) { // Note: RingBuffer class handles destroying itself if (tabstops_) { free(tabstops_); tabstops_ = 0; } if (autoscroll_dir_) { Fl::remove_timeout(autoscroll_timer_cb, this); autoscroll_dir_ = 0; } if (redraw_timer_) { Fl::remove_timeout(redraw_timer_cb, this); redraw_timer_ = false; } delete current_style_; } /** Returns the scrollbar's actual "trough size", which is the width of FL_VERTICAL scrollbars, or height of FL_HORIZONTAL scrollbars. If scrollbar_size() is zero (default), then the value of the global Fl::scrollbar_size() is returned, which is the default global scrollbar size for the entire application. */ int Fl_Terminal::scrollbar_actual_size(void) const { return scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size(); } /** Get current pixel size of all the scrollbar's troughs for this widget, or zero if the global Fl::scrollbar_size() is being used (default). If this value returns *zero*, this widget's scrollbars are using the global Fl::scrollbar_size(), in which case use scrollbar_actual_size() to get the actual (effective) pixel scrollbar size being used. \returns Scrollbar trough size in pixels, or 0 if the global Fl::scrollbar_size() is being used. \see Fl::scrollbar_size(int), scrollbar_actual_size() */ int Fl_Terminal::scrollbar_size(void) const { return scrollbar_size_; } /** Set the pixel size of both horizontal and vertical scrollbar's "trough" to \p val. Setting \p val to the special value 0 causes the widget to track the global Fl::scrollbar_size(). Use non-zero values *only* if you need to override the global Fl::scrollbar_size() size. \see Fl::scrollbar_size(), scrollbar_actual_size() */ void Fl_Terminal::scrollbar_size(int val) { scrollbar_size_ = val; update_scrollbar(); refit_disp_to_screen(); } /** Get the horizontal scrollbar behavior style. This determines when the scrollbar is visible. Value will be one of the Fl_Terminal::ScrollbarStyle enum values. \see hscrollbar_style(Fl_Terminal::ScrollbarStyle) */ Fl_Terminal::ScrollbarStyle Fl_Terminal::hscrollbar_style() const { return hscrollbar_style_; } /** Set the horizontal scrollbar behavior style. This determines when the scrollbar is visible. \par | ScrollbarStyle enum | Description | :-----------------------: | :----------------------------------------------------------- | \ref SCROLLBAR_ON | Horizontal scrollbar always displayed. | \ref SCROLLBAR_OFF | Horizontal scrollbar never displayed. | \ref SCROLLBAR_AUTO | Horizontal scrollbar displayed whenever widget width hides columns. The default style is SCROLLBAR_AUTO. \see ScrollbarStyle */ void Fl_Terminal::hscrollbar_style(ScrollbarStyle val) { hscrollbar_style_ = val; update_scrollbar(); refit_disp_to_screen(); } //////////////////////////// ////// SCREEN DRAWING ////// //////////////////////////// /** Draw the background for the specified ring_chars[] global row \p grow starting at FLTK coords \p X and \p Y. Note we may be called to draw display, or even history if we're scrolled back. If there's any change in bg color, we draw the filled rects here. If the bg color for a character is the special "see through" color 0xffffffff, no pixels are drawn. \param[in] grow row number \param[in] X, Y top left corner of the row in FLTK coordinates */ void Fl_Terminal::draw_row_bg(int grow, int X, int Y) const { int bg_h = current_style_->fontheight(); int bg_y = Y; Fl_Color bg_col; int pwidth = 9; int start_col = hscrollbar->visible() ? hscrollbar->value() : 0; int end_col = disp_cols(); const Utf8Char *u8c = u8c_ring_row(grow) + start_col; // start of spec'd row uchar lastattr = u8c->attrib(); for (int gcol=start_col; gcolattrib() != lastattr) { u8c->fl_font_set(*current_style_); // pwidth_int() needs fl_font set lastattr = u8c->attrib(); } pwidth = u8c->pwidth_int(); bg_col = is_inside_selection(grow, gcol) // text in mouse select? ? select_.selectionbgcolor() // ..use select bg color : (u8c->attrib() & Fl_Terminal::INVERSE) // Inverse mode? ? u8c->attr_fg_color(this) // ..use fg color for bg : u8c->attr_bg_color(this); // ..use bg color for bg // Draw only if color != 0xffffffff ('see through' color) or widget's own color(). if (bg_col != 0xffffffff && bg_col != Fl_Group::color()) { fl_color(bg_col); fl_rectf(X, bg_y, pwidth, bg_h); } X += pwidth; // advance X to next char } } /** Draw the specified global row, which is the row in ring_chars[]. The global row includes history + display buffers. \param[in] grow row number \param[in] Y top position of characters in the row in FLTK coordinates */ void Fl_Terminal::draw_row(int grow, int Y) const { // Draw background color spans, if any int X = scrn_.x(); draw_row_bg(grow, X, Y); // Draw forground text int baseline = Y + current_style_->fontheight() - current_style_->fontdescent(); int scrollval = scrollbar->value(); int disp_top = (disp_srow() - scrollval); // top row we need to view int drow = grow - disp_top; // disp row bool inside_display = is_disp_ring_row(grow); // row inside 'display'? // This looks better on macOS, but too low for X. Maybe we can get better results using fl_text_extents()? // int strikeout_y = baseline - (current_style_->fontheight() / 4); // int underline_y = baseline + (current_style_->fontheight() / 5); int strikeout_y = baseline - (current_style_->fontheight() / 3); int underline_y = baseline; uchar lastattr = -1; bool is_cursor; Fl_Color fg; int start_col = hscrollbar->visible() ? hscrollbar->value() : 0; int end_col = disp_cols(); const Utf8Char *u8c = u8c_ring_row(grow) + start_col; for (int gcol=start_col; gcolattrib() != lastattr) { u8c->fl_font_set(*current_style_); // pwidth_int() needs fl_font set lastattr = u8c->attrib(); } int pwidth = u8c->pwidth_int(); // DRAW CURSOR BLOCK - TODO: support other cursor types? if (is_cursor) { int cx = X; int cy = Y + current_style_->fontheight() - cursor_.h(); int cw = pwidth; int ch = cursor_.h(); fl_color(cursorbgcolor()); if (Fl::focus() == this) fl_rectf(cx, cy, cw, ch); else fl_rect(cx, cy, cw, ch); } // DRAW TEXT // 1) Color for text if (is_cursor) fg = cursorfgcolor(); // color for text under cursor else fg = is_inside_selection(grow, gcol) // text in mouse selection? ? select_.selectionfgcolor() // ..use selection FG color : (u8c->attrib() & Fl_Terminal::INVERSE) // Inverse attrib? ? u8c->attr_bg_color(this) // ..use char's bg color for fg : u8c->attr_fg_color(this); // ..use char's fg color for fg fl_color(fg); // 2) Font for text - already set by u8c->fl_font_set() in the above if (is_cursor) { fl_font(fl_font()|FL_BOLD, fl_size()); // force text under cursor BOLD lastattr = -1; // (ensure font reset on next iter) } // 3) Draw text for UTF-8 char. No need to draw spaces if (!u8c->is_char(' ')) fl_draw(u8c->text_utf8(), u8c->length(), X, baseline); // 4) Strike or underline? if (u8c->attrib() & Fl_Terminal::UNDERLINE) fl_line(X, underline_y, X+pwidth, underline_y); if (u8c->attrib() & Fl_Terminal::STRIKEOUT) fl_line(X, strikeout_y, X+pwidth, strikeout_y); // Move to next char pixel position X += pwidth; } } /** Draws the buffer position we are scrolled to onto the FLTK screen starting at pixel position Y. This can be anywhere in the ring buffer, not just the 'active diplay'; depends on what position the scrollbar is set to. Handles attributes, colors, text selections, cursor. \param[in] Y top position of top left character in the window in FLTK coordinates */ void Fl_Terminal::draw_buff(int Y) const { int srow = disp_srow() - scrollbar->value(); int erow = srow + disp_rows(); const int rowheight = current_style_->fontheight(); for (int grow=srow; (growupdate(); // do deferred update here update_screen(true); // update fonts } // Detect if Fl::scrollbar_size() was changed in size, recalc if so if (scrollbar_size_ == 0 && ((scrollbar->visible() && scrollbar->w() != Fl::scrollbar_size()) || (hscrollbar->visible() && hscrollbar->h() != Fl::scrollbar_size()))) { update_scrollbar(); } // Draw group first, terminal last Fl_Group::draw(); // Draw that little square between the scrollbars: if (scrollbar->visible() && hscrollbar->visible()) { fl_color(parent()->color()); fl_rectf(scrollbar->x(), hscrollbar->y(), scrollbar_actual_size(), scrollbar_actual_size()); } if (is_frame(box())) { // Is box() a frame? Fill area inside frame with rectf(). // FL_XXX_FRAME types allow Fl_Terminal to have a /flat/ background. // FL_XXX_BOX types inherit Fl::scheme() which can provide unwanted gradients. // fl_color(Fl_Group::color()); // Draw flat field (inside border drawn by Fl_Group::draw() above) int X = x() + Fl::box_dx(box()); int Y = y() + Fl::box_dy(box()); int W = w() - Fl::box_dw(box()); int H = h() - Fl::box_dh(box()); if (scrollbar->visible()) W -= scrollbar_actual_size(); if (hscrollbar->visible()) H -= scrollbar_actual_size(); fl_rectf(X,Y,W,H); } //DEBUG fl_color(0x80000000); // dark red box inside margins //DEBUG fl_rect(scrn_); fl_push_clip(scrn_.x(), scrn_.y(), scrn_.w(), scrn_.h()); int Y = scrn_.y(); draw_buff(Y); fl_pop_clip(); } /** Given a width in pixels, return number of columns that "fits" into that area. This is used by the constructor to size the row/cols to fit the widget size. */ int Fl_Terminal::w_to_col(int W) const { return W / current_style_->charwidth(); } /** Given a height in pixels, return number of rows that "fits" into that area. This is used by the constructor to size the row/cols to fit the widget size. */ int Fl_Terminal::h_to_row(int H) const { return H / current_style_->fontheight(); } /** Handle widget resizing, such as if user resizes parent window. This may increase the column width of the widget if the width of the widget is made larger than it was. \note Resizing currently does not rewrap existing text. Currently enlarging makes room for longer lines, and shrinking the size lets long lines run off the right edge of the display, hidden from view. This behavior may change in the future to rewrap. */ void Fl_Terminal::resize(int X,int Y,int W,int H) { // Let group resize itself Fl_Group::resize(X,Y,W,H); // Update screen stuff; margins, etc update_screen(false); // no change in font, just resizing // resize the display's rows+cols to match window size refit_disp_to_screen(); } // Handle autoscrolling vals + timer // If mouse dragged beyond top/bottom, start/continue auto-scroll select // void Fl_Terminal::handle_selection_autoscroll(void) { int Y = Fl::event_y(); int top = scrn_.y(); int bot = scrn_.b(); int dist = (Y < top) ? Y - top : // <0 if above top (Y > bot) ? Y - bot : 0; // >0 if below bottom if (dist == 0) { // Not off edge? stop autoscrolling, done if (autoscroll_dir_) Fl::remove_timeout(autoscroll_timer_cb, this); autoscroll_dir_ = 0; } else { // Above top/below bot? Start/continue autoscroll select if (!autoscroll_dir_) Fl::add_timeout(.01, autoscroll_timer_cb, this); autoscroll_amt_ = dist; // <0 if above top, >0 if below bot autoscroll_dir_ = (dist < 0) ? 3 : 4; // 3=scrolling up, 4=scrolling dn } } /** Handle mouse selection on LEFT-CLICK push/drag/release. Returns: 1 if 'handled', 0 if not. */ int Fl_Terminal::handle_selection(int e) { int grow=0, gcol=0; bool gcr = false; bool is_rowcol = (xy_to_glob_rowcol(Fl::event_x(), Fl::event_y(), grow, gcol, gcr) > 0) ? true : false; switch (e) { case FL_PUSH: { // SHIFT-LEFT-CLICK? Extend or start new if (Fl::event_state(FL_SHIFT)) { if (is_selection()) { // extend if select in progress selection_extend(Fl::event_x(), Fl::event_y()); redraw(); return 1; // express interest in FL_DRAG } } else { // Start a new selection select_.push_rowcol(grow, gcol, gcr); if (select_.clear()) redraw(); // clear prev selection if (is_rowcol) { switch (Fl::event_clicks()) { case 1: select_word(grow, gcol); break; case 2: select_line(grow); break; } return 1; // express interest in FL_DRAG } } // Left-Click outside terminal area? if (!Fl::event_state(FL_SHIFT)) { select_.push_clear(); clear_mouse_selection(); redraw(); } return 0; // event NOT handled } case FL_DRAG: { if (is_rowcol) { if (!is_selection()) { // no selection yet? if (select_.dragged_off(grow, gcol, gcr)) { // dragged off FL_PUSH? enough to start select_.start_push(); // ..start drag with FL_PUSH position } } else { if (select_.extend(grow, gcol, gcr)) redraw(); // redraw if selection changed } } // If we leave scrn area, start timer to auto-scroll+select handle_selection_autoscroll(); return 1; } case FL_RELEASE: { select_.end(); // middlemouse gets immediate copy of selection if (is_selection()) { const char *copy = selection_text(); if (*copy) Fl::copy(copy, (int)strlen(copy), 0); free((void*)copy); } return 1; } default: break; } return 0; } /** Handle FLTK events. */ int Fl_Terminal::handle(int e) { int ret = Fl_Group::handle(e); if (Fl::event_inside(scrollbar)) return ret; // early exit for scrollbar if (Fl::event_inside(hscrollbar)) return ret; // early exit for hscrollbar switch (e) { case FL_ENTER: case FL_LEAVE: return 1; case FL_UNFOCUS: case FL_FOCUS: redraw(); return Fl::visible_focus() ? 1 : 0; case FL_KEYBOARD: // ^C -- Copy? if ((Fl::event_state()&(FL_CTRL|FL_COMMAND)) && Fl::event_key()=='c') { const char *copy = is_selection() ? selection_text() : fl_strdup(" "); if (*copy) Fl::copy(copy, (int)strlen(copy), 1); // paste buffer free((void*)copy); return 1; } // ^A -- Select all? if ((Fl::event_state()&(FL_CTRL|FL_COMMAND)) && Fl::event_key()=='a') { // Select entire screen and history buffer int srow = disp_srow() - hist_use(); int erow = disp_srow() + disp_rows()-1; //DEBUG ::printf("CTRL-A: srow=%d erow=%d\n", srow, erow); select_.select(srow, 0, erow, disp_cols()-1); const char *copy = selection_text(); if (*copy) Fl::copy(copy, (int) strlen(copy), 0); // middle mouse buffer free((void*)copy); redraw(); return 1; } // Let scrollbar handle these when we have focus if (Fl::focus() == this) { switch (Fl::event_key()) { case FL_Page_Up: case FL_Page_Down: case FL_Up: case FL_Down: case FL_Left: case FL_Right: return scrollbar->handle(e); } } break; case FL_PUSH: if (handle(FL_FOCUS)) Fl::focus(this); // Accepting focus? take it if (Fl::event_button() == FL_LEFT_MOUSE) // LEFT-CLICK? { ret = handle_selection(FL_PUSH); } break; case FL_DRAG: // TODO: This logic can probably be improved to allow an FL_PUSH in margins // to drag into terminal area to start a selection. if (Fl::event_button() == FL_LEFT_MOUSE) // LEFT-DRAG? { ret = handle_selection(FL_DRAG); } break; case FL_RELEASE: // Selection mouse release? if (Fl::event_button() == FL_LEFT_MOUSE) // LEFT-RELEASE? { ret = handle_selection(FL_RELEASE); } // Disable autoscroll timer, if any if (autoscroll_dir_) { Fl::remove_timeout(autoscroll_timer_cb, this); autoscroll_dir_ = 0; } break; } // switch return ret; } /** Return a string copy of all lines in the terminal (including history). The returned string is allocated with strdup(3), which the caller must free. If \p 'lines_below_cursor' is false (default), lines below the cursor on down to the bottom of the display are ignored, and not included in the returned string. If \p 'lines_below_cursor' is true, then all lines in the display are returned including any below the cursor, even if all are blank. Example use: \par \code Fl_Terminal *tty = new Fl_Terminal(..); : const char *s = tty->text(); // get a copy of the terminal's contents printf("Terminal's contents is:\n%s\n", s); free((void*)s); // free() the copy when done! \endcode \param[in] lines_below_cursor include lines below cursor, default: false \return A string allocated with strdup(3) which must be free'd, text is UTF-8. */ const char* Fl_Terminal::text(bool lines_below_cursor) const { Fl_String lines; // lines of text we'll return // See how many display rows we need to include int disprows = lines_below_cursor ? disp_rows() - 1 // all display lines : cursor_row(); // only lines up to cursor // Start at top of 'in use' history, and walk to end of display int srow = hist_use_srow(); // start row of text to return int erow = srow + hist_use() + disprows; // end row of text to return for (int row=srow; row<=erow; row++) { // walk rows const Utf8Char *u8c = u8c_ring_row(row); // start of row int trim = 0; for (int col=0; coltext_utf8(); // first byte of char for (int i=0; ilength(); i++) lines += *s++; // append all bytes in multibyte char // Count any trailing whitespace to trim if (u8c->length()==1 && s[-1]==' ') trim++; // trailing whitespace? trim else trim = 0; // non-whitespace? don't trim } // trim trailing whitespace from each line, if any if (trim) lines.resize(lines.size() - trim); lines += "\n"; } return fl_strdup(lines.c_str()); } /** Get the redraw style. This determines when the terminal redraws itself while text is being added to it. Value will be one of the Fl_Terminal::RedrawStyle enum values. \see redraw_style(Fl_Terminal::RedrawStyle) */ Fl_Terminal::RedrawStyle Fl_Terminal::redraw_style() const { return redraw_style_; } /** Set how Fl_Terminal manages screen redrawing. This setting is relevant when Fl_Terminal is used for high bandwidth data; too many redraws will slow things down, too few cause redraws to be 'choppy' when realtime data comes in. Redrawing can be cpu intensive, depending on how many rows/cols are being displayed; worst case: large display + small font. Speed largely depends on the end user's graphics hardware and font drawing system. \par | RedrawStyle enum | Description | :-------------------: | :----------------------------------------------------------- | \ref NO_REDRAW | App must call redraw() as needed to update text to screen | \ref RATE_LIMITED | Rate limited, timer controlled redraws. (DEFAULT) See redraw_rate() | \ref PER_WRITE | Redraw triggered *every* call to append() / printf() / etc. The default style is RATE_LIMITED, which is the easiest to use, and automates redrawing to be capped at 10 redraws per second max. See redraw_rate(float) to control this automated redraw speed. \see redraw_rate(), RedrawStyle */ void Fl_Terminal::redraw_style(RedrawStyle val) { redraw_style_ = val; // Disable rate limit timer if it's being turned off if (redraw_style_ != RATE_LIMITED && redraw_timer_) { Fl::remove_timeout(redraw_timer_cb, this); redraw_timer_ = false; } } /** Get max rate redraw speed in floating point seconds. */ float Fl_Terminal::redraw_rate(void) const { return redraw_rate_; } /** Set the maximum rate redraw speed in floating point seconds if redraw_style() is set to RATE_LIMITED. When output is sent to the terminal, rather than calling redraw() right away, a timer is started with this value indicating how long to wait before calling redraw(), causing the output to be shown. 0.10 is recommended (1/10th of a second), to limit redraws to no more than 10 redraws per second. The value that works best depends on how fast data arrives, and how fast the font system can draw text at runtime. Values too small cause too many redraws to occur, causing the terminal to get backlogged if large bursts of data arrive quickly. Values too large cause realtime output to be too "choppy". */ void Fl_Terminal::redraw_rate(float val) { redraw_rate_ = val; } /** Return the "show unknown" flag. \see show_unknown(bool), error_char(const char*). */ bool Fl_Terminal::show_unknown(void) const { return show_unknown_; } /** Set the "show unknown" flag. If true, invalid utf8 and invalid ANSI sequences will be shown with the error character "¿". If false, errors characters won't be shown. \see handle_unknown_char(), error_char(const char*). */ void Fl_Terminal::show_unknown(bool val) { show_unknown_ = val; } /** Return the state of the ANSI flag. \see ansi(bool) */ bool Fl_Terminal::ansi(void) const { return ansi_; } /** Enable/disable the ANSI mode flag. If true, ANSI and VT100/xterm codes will be processed. If false, these codes won't be processed and will either be ignored or print the error character "¿", depending on the value of show_unknown(). \see show_unknown(), \ref Fl_Terminal_escape_codes */ void Fl_Terminal::ansi(bool val) { ansi_ = val; // If disabled, reset the class to clear old state information if (!ansi_) escseq.reset(); } /** Return the number of lines of screen history. */ int Fl_Terminal::history_lines(void) const { return history_rows(); } /** Set the number of lines of screen history. Large values can be briefly heavy on cpu and memory usage. */ void Fl_Terminal::history_lines(int val) { history_rows(val); } /** Appends printf formatted messages to the terminal. The string can contain UTF-8, crlf's, and ANSI sequences are also supported. Example: \par \code #include int main(..) { : // Create a terminal, and append some messages to it Fl_Terminal *tty = new Fl_Terminal(..); : // Append three lines of formatted text to the buffer tty->printf("The current date is: %s.\nThe time is: %s\n", date_str, time_str); tty->printf("The current PID is %ld.\n", (long)getpid()); : \endcode \note The expanded string is currently limited to 1024 characters (including NULL). For longer strings use append() which has no string limits. */ void Fl_Terminal::printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); Fl_Terminal::vprintf(fmt, ap); va_end(ap); } /** Appends printf formatted messages to the terminal. Subclasses can use this to implement their own printf() functionality. The string can contain UTF-8, crlf's, and ANSI sequences are also supported when ansi(bool) is set to 'true'. \note The expanded string is currently limited to 1024 characters (including NULL). For longer strings use append() which has no string limits. \param fmt is a printf format string for the message text. \param ap is a va_list created by va_start() and closed with va_end(), which the caller is responsible for handling. */ void Fl_Terminal::vprintf(const char *fmt, va_list ap) { char buffer[1024]; // XXX: should be user configurable.. ::vsnprintf(buffer, 1024, fmt, ap); buffer[1024-1] = 0; // XXX: MICROSOFT append(buffer); } fltk-1.4.3/src/Fl_Preferences.cxx0000644000175000017500000020407515004135251017012 0ustar albrechtalbrecht// // Preferences methods for the Fast Light Tool Kit (FLTK). // // Copyright 2002-2010 by Matthias Melcher. // Copyright 2011-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_System_Driver.H" #include #include #include #include #include #include "flstring.h" #include #include #include #if (FLTK_USE_STD) #include #endif /* The format of preferences files is not part of the FLTK specification and intentionally undocumented in Doxygen. The following documentation is FOR CORE DEVELOPERS ONLY. Don't let any app developer see this! This is the unofficial documentation of the file format as it currently stands. The format may change at any point (although it really should stay backwards compatible). Preferences files are *not* supposed to be edited manually. Nevertheless, here are the docs: A .prefs file contains multiple lines. A line is defined by 0 or more ASCII characters in the range from 0x20 to 0x7e, followed by a single '\n' line ending character. Note that there are no tabs, \0 characters, or '\r' characters anywhere in a line. Some parts of a line may allow 0x80 to 0xff to support Unicode UTF-8 octets. The first line is always "; FLTK preferences file format 1.0", followed by a '\n' to indicate the end of the line. The version number may change some time in the future if the file format ever changes. The second line contains the vendor information when the file was created: "; vendor: VENDOR\n" The third line contains the application name "; application: APPLICATION_NAME\n" Any following line that starts with a ';' is not relevant for data and seen as a comment. Fl_Preferences tries to preserve comments, but has no API to set or read comments. All data is stored in key/value pairs. All key/value pairs are stored inside their group. There can be multiple groups. Group naming is used to indicate a hierarchy. A line starting with a '[' starts a group. Before and after a group line, there is always an empty line (no characters, just a '\n'). A group line ends in "]\n". Directly between the '[' and ']' is the name of the group. The first ("root")-group is always declared with the line "[.]\n". Simple group names are written starting with "./", for example "[./name]\n". To generate a hierarchy of groups, deeper nested names are generated by adding more '/name" segments (just like a Unix file path), for example "[./dialog/button/position]\n". Remember that there is an empty line after the group line. A group line is followed by 0 or more lines containing key/value pairs for the given group. A key is a sequence of ASCII letters, numbers, ".", or "_". The key should not be longer than 32 characters. The key is followed by the ":" character and the value. There is no space before or after the ":". The value may contain more ":" characters. The value is a text of ASCII characters 0x20 to 0x7e or UTF-8 Unicode octets 0x80 to 0xff. The key/value line ends in a "\n". Key/value lines wrap before or at column 80 with a "\n" and continue in the next line, starting with a "+" which indicates that this is an overflow line and is furthermore ignored. The type of a value is not stored in the file. It is not an error to call Fl_Preferences::set with a "double" and read back a string. * Integers are written as signed int using "%d". * Floating point values are written with decimal points if C_LOCALE is set when creating the file. * When text is written, "\r", "\n", and the "\" character are escaped by prepending them with an additional "\", other characters <0x20 and 0x7f are encoded in octal format: "\001", UTF-8 is allowed. * Binary data is written as lower case hex digits, two digits per byte. Example data as generated by the test/preferences app: ``` ; FLTK preferences file format 1.0 ; vendor: fltk.org ; application: test/preferences [.] [./Bed] ; The value is "8:00". Values can contain a ':' character alarm:8:00 ; Some integer values ampm:0 wear:2 side:1 taskFlags:5 [./Breakfast] drink:1 wMilk:1 bread:1 wButter:1 nEggs:2 ; A floating point value minutes:4.91 newspaper:NY Tymes ; A text value containing newlines and two other control codes foo:bar\nfly\rBackslash: \\ and bell: \007 and delete: \177\n ; A key can be numeric, but the numeric value has no special meaning 3:Test3 ; Short binary data block. Data is written verbatim, ; CPU endianess has no meaning here binFoo:2387efcd ; A long binary data block, generating wrapped lines binFoo2:7c0802a6bfc1fff8900100089421ff707c3e0b78429f00057fe802a6381e +00487c030378388000013c5f000538a287c43c5f000538c287d04801be31381e0050385e00487c03 +03787c4413783c5f000538a287e44801b6f93c5f00053842dc70800200007c030378480450197c69 +1b78381e00507c0303783c5f0005388287e87d254b784801ab253c5f00053842dc6c800200007c03 +0378480450097c691b78381e00507c0303783c5f0005388287f87d254b784801af8d3c5f00053842 +dc14800200007c03037848044fd97c691b78381e00507c0303783c5f0005388288007d254b784801 +af5d38000000901e00403c5f00053842db84800200007c030378 ``` */ char Fl_Preferences::nameBuffer[128]; char Fl_Preferences::uuidBuffer[40]; Fl_Preferences *Fl_Preferences::runtimePrefs = 0; unsigned int Fl_Preferences::fileAccess_ = Fl_Preferences::ALL; static int clocale_snprintf(char *buffer, size_t buffer_size, const char *format, ...) { va_list args; va_start(args, format); int retval = Fl::system_driver()->clocale_vsnprintf(buffer, buffer_size, format, args); va_end(args); return retval; } static int clocale_sscanf(const char *input, const char *format, ...) { va_list args; va_start(args, format); int retval = Fl::system_driver()->clocale_vsscanf(input, format, args); va_end(args); return retval; } /** Returns a UUID as generated by the system. A UUID is a "universally unique identifier" which is commonly used in configuration files to create identities. A UUID in ASCII looks like this: 937C4900-51AA-4C11-8DD3-7AB59944F03E. It has always 36 bytes plus a trailing zero. \return a pointer to a static buffer containing the new UUID in ASCII format. The buffer is overwritten during every call to this function! */ const char *Fl_Preferences::new_UUID() { Fl::system_driver()->newUUID(uuidBuffer); return uuidBuffer; } /** Tell the FLTK preferences system which files in the file system it may read, create, or write. The FLTK core library will try to read or even create or write preference files when calling Fl::option(), Fl_File_Chooser, the printing panel, and possibly some other internal functions. If your application wants to keep FLTK from touching the file system, call this function before making any other FLTK calls: \code // neither FLTK nor the app may read, create, or write preference files Fl_Preferences::file_access( Fl_Preferences::NONE ); \endcode or \code // FLTK may not read, create, or write preference files, but the application may Fl_Preferences::file_access( Fl_Preferences::APP_OK ); \endcode All flags can be combined using an OR operator. If flags are not set, that specific access to the file system will not be allowed. By default, all access is granted. To clear one or more flags from the default setting, use: \code Fl_Preferences::file_access( Fl_Preferences::file_access() &~ Fl_Preferences::SYSTEM_WRITE ); \endcode If preferences are created using a filename (instead of Fl_Preferences::USER or Fl_Preferences::SYSTEM), file access is handled as if the Fl_Preferences::USER flag was set. \see Fl_Preferences::NONE and others for a list of flags. \see Fl_Preferences::file_access() */ void Fl_Preferences::file_access(unsigned int flags) { fileAccess_ = flags; } /** Return the current file access permissions for the FLTK preferences system. \see Fl_Preferences::file_access(unsigned int) */ unsigned int Fl_Preferences::file_access() { return fileAccess_; } /** Determine the file name and path to preferences that would be opened with these parameters. Find the possible location of a preference file on disk without touching any of the pathname components. This can be used to check if a preference file already exists. \param[out] buffer write the resulting path into this buffer \param[in] buffer_size size of the `buffer` in bytes \param[in] root can be \c USER_L or \c SYSTEM_L for user specific or system wide preferences \param[in] vendor unique text describing the company or author of this file, must be a valid filepath segment \param[in] application unique text describing the application, must be a valid filepath segment \return the input root value, or Fl_Preferences::UNKNOWN_ROOT_TYPE if the path could not be determined. \see Fl_Preferences( Root root, const char *vendor, const char *application ) */ Fl_Preferences::Root Fl_Preferences::filename( char *buffer, size_t buffer_size, Root root, const char *vendor, const char *application ) { Root ret = UNKNOWN_ROOT_TYPE; if (buffer && buffer_size>0) { char *fn = Fl::system_driver()->preference_rootnode(NULL, root, vendor, application); if (fn) { fl_strlcpy(buffer, fn, buffer_size); // FLTK always returns forward slashes in paths { char *s; for ( s = buffer; *s; s++ ) if ( *s == '\\' ) *s = '/'; } ret = root; } else { buffer[0] = 0; } } return ret; } /** The constructor creates a group that manages key/value pairs and child groups. Preferences can be stored per user using the root type `Fl_Preferences::USER_L`, or stored system-wide using `Fl_Preferences::SYSTEM_L`. Groups and key/value pairs can be read and written randomly. Reading undefined values will return the default value. Writing undefined values will create all required groups and key/vlaue pairs. This constructor creates the base instance for all following entries and reads the database from disk into memory if it exists. The vendor argument is a unique text string identifying the development team or vendor of an application. A domain name or an EMail address (replacing the '@' with a '.') are great unique names, e.g. "research.matthiasm.com" or "fluid.fltk.org". The application argument can be the working title or final name of your application. Both vendor and application must be valid UNIX path segments as they become parts of the preference file path and may contain forward slashes to create deeper file structures. \note On \b Windows, the directory is constructed by querying the Common AppData or AppData key of the Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders registry entry. The filename and path is then constructed as \$(query)/\$(vendor)/\$(application).prefs . If the query call fails, data will be stored in RAM only. It will be lost when the app exits. \par In FLTK versions before 1.4.0, if querying the registry failed, preferences would be written to C:\\FLTK\\\$(vendor)\\\$(application).prefs . \note On \b Linux, the \c USER directory is constructed by reading \c $HOME . If \c $HOME is not set or not pointing to an existing directory, FLTK will check the path member of the passwd struct returned by \c getpwuid(getuid()) . If all attempts fail, data will be stored in RAM only and be lost when the app exits. The \c SYSTEM preference filename is hardcoded as /etc/fltk/\$(vendor)/\$(application).prefs . For backward compatibility, the old \c USER `.prefs` file naming scheme \$(directory)/.fltk/\$(vendor)/\$(application).prefs is checked first. If that file does not exist, the environment variable `$XDG_CONFIG_HOME` is read as a base directory. If `$XDG_CONFIG_HOME` is not set, the base directory defaults to `$HOME/.config/`. The user preferences will be stored in \$(directory)/\$(vendor)/\$(application).prefs. The user data path will be \$(directory)/\$(vendor)/\$(application)/. In FLTK versions before 1.4.0, if \c $HOME was not set, the \c USER path would be empty, generating \$(vendor)/\$(application).prefs, which was used relative to the current working directory. \note On \b macOS, the \c USER directory is constructed by reading \c $HOME . If \c $HOME is not set or not pointing to an existing directory, we check the path returned by \c NSHomeDirectory() , and finally checking the path member of the passwd struct returned by \c getpwuid(getuid()) . If all attempts fail, data will be stored in RAM only and be lost when the app exits. The filename and path is then constructed as \$(directory)/Library/Preferences/\$(vendor)/\$(application).prefs . The \c SYSTEM directory is hardcoded as /Library/Preferences/\$(vendor)/\$(application).prefs . \par In FLTK versions before 1.4.0, if \c $HOME was not set, the \c USER path would be \c NULL , generating \/Library/Preferences/\$(vendor)/\$(application).prefs, which would silently fail to create a preference file. \param[in] root can be \c USER_L or \c SYSTEM_L for user specific or system wide preferences, add the \c CLEAR flag to start with a clean set of preferences instead of reading them from a preexisting database \param[in] vendor unique text describing the company or author of this file, must be a valid filepath segment \param[in] application unique text describing the application, must be a valid filepath segment \see Fl_Preferences(Fl_Preferences *parent, const char *group) with parent set to NULL */ Fl_Preferences::Fl_Preferences( Root root, const char *vendor, const char *application ) { node = new Node( "." ); rootNode = new RootNode( this, root, vendor, application ); node->setRoot(rootNode); if (root & CLEAR) clear(); } /** \brief Deprecated: Use this constructor to create or read a preference file at an arbitrary position in the file system. This constructor should no longer be used because the generated database uses the current locale, making it impossible to exchange floating point settings between machines with different language settings. Use `Fl_Preferences(path, vendor, application, Fl_Preferences::C_LOCALE)` in new projects and `Fl_Preferences(path, vendor, application, 0)` if you must keep backward compatibility. \see Fl_Preferences( const char *path, const char *vendor, const char *application, Root flags ) */ Fl_Preferences::Fl_Preferences( const char *path, const char *vendor, const char *application ) { node = new Node( "." ); rootNode = new RootNode( this, path, vendor, application, (Root)0 ); node->setRoot(rootNode); } /** \brief Use this constructor to create or read a preference file at an arbitrary position in the file system. The file name is generated in the form \$(path)/\$(application).prefs. If \p application is \c NULL, \p path is taken literally as the file path and name. ``` // Example: read from an existing database and write modifications when flushed // or destructor is called Fl_Preferences database("/user/matt/test.prefs", "org.fltk.test", NULL, Fl_Preferences::C_LOCALE); // Example: create a new preferences file with an empty data set Fl_Preferences database("/user/matt/test.prefs", "org.fltk.test", NULL, (Fl_Preferences::Root)(Fl_Preferences::C_LOCALE|Fl_Preferences::CLEAR)); ``` \note the C_LOCALE flag is is not set by default for backward compatibility, but it is highly recommended to set it when opening a database. \param[in] path path to the directory that contains the preference file \param[in] vendor unique text describing the company or author of this file, must be a valid file path segment \param[in] application unique text describing the application, must be a valid filename or NULL \param[in] flags C_LOCALE to make the preferences file independent of the current locale, add the CLEAR flag to start with a clean set of preferences instead of reading from the database */ Fl_Preferences::Fl_Preferences( const char *path, const char *vendor, const char *application, Root flags ) { node = new Node( "." ); rootNode = new RootNode( this, path, vendor, application, flags ); node->setRoot(rootNode); if (flags & CLEAR) clear(); } /** \brief Generate or read a new group of entries within another group. Use the \p group argument to name the group that you would like to access. \p Group can also contain a path to a group further down the hierarchy by separating group names with a forward slash '/'. \param[in] parent reference object for the new group \param[in] group name of the group to access (may contain '/'s) */ Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, const char *group ) { rootNode = parent.rootNode; node = parent.node->addChild( group ); } /** \brief Create or access a group of preferences using a name. Parent should point to a previously created parent preferences group to create a preferences hierarchy. If `parent` is set to `NULL`, an unnamed database will be accessed that exists only in local memory and is not associated with a file on disk. The root type of this database is set to `Fl_Preferences::MEMORY`. - the memory database is \em not shared among multiple instances of the same app - memory databases are \em not thread safe - all data will be lost when the app quits ``` void some_function() { Fl_Preferences guide( NULL, "Guide" ); guide.set("answer", 42); } void other_function() { int x; Fl_Preferences guide( NULL, "Guide" ); guide.get("answer", x, -1); } ``` FLTK uses the memory database to manage plugins. See `Fl_Plugin`. \param[in] parent the parameter parent is a pointer to the parent group. If \p parent is \p NULL, the new preferences item refers to an application internal database ("runtime prefs") which exists only once, and remains in RAM only until the application quits. This database is used to manage plugins and other data indexes by strings. Runtime prefs are \em not thread-safe. \param[in] group a group name that is used as a key into the database \see Fl_Preferences( Fl_Preferences&, const char *group ) */ Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, const char *group ) { if (parent==NULL) { if (!runtimePrefs) { runtimePrefs = new Fl_Preferences(); runtimePrefs->node = new Node( "." ); runtimePrefs->rootNode = new RootNode( runtimePrefs ); runtimePrefs->node->setRoot(runtimePrefs->rootNode); } parent = runtimePrefs; } rootNode = parent->rootNode; node = parent->node->addChild( group ); } /** \brief Open a child group using a given index. Use the \p groupIndex argument to find the group that you would like to access. If the given index is invalid (negative or too high), a new group is created with a UUID as a name. The index needs to be fixed. It is currently backward. Index 0 points to the last member in the 'list' of preferences. \param[in] parent reference object for the new group \param[in] groupIndex zero based index into child groups */ Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, int groupIndex ) { rootNode = parent.rootNode; if (groupIndex<0 || groupIndex>=parent.groups()) { node = parent.node->addChild( newUUID() ); } else { node = parent.node->childNode( groupIndex ); } } /** \see Fl_Preferences( Fl_Preferences&, int groupIndex ) */ Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, int groupIndex ) { rootNode = parent->rootNode; if (groupIndex<0 || groupIndex>=parent->groups()) { node = parent->node->addChild( newUUID() ); } else { node = parent->node->childNode( groupIndex ); } } /** Create a new dataset access point using a dataset ID. ID's are a great way to remember shortcuts to database entries that are deeply nested in a preferences database, as long as the database root is not deleted. An ID can be retrieved from any Fl_Preferences dataset, and can then be used to create multiple new references to the same dataset. ID's can be very helpful when put into the user_data() field of widget callbacks. */ Fl_Preferences::Fl_Preferences( Fl_Preferences::ID id ) { node = (Node*)id; rootNode = node->findRoot(); } /** Create another reference to a Preferences group. */ Fl_Preferences::Fl_Preferences(const Fl_Preferences &rhs) : node(rhs.node), rootNode(rhs.rootNode) { } /** Assign another reference to a preference group. */ Fl_Preferences &Fl_Preferences::operator=(const Fl_Preferences &rhs) { if (&rhs != this) { node = rhs.node; rootNode = rhs.rootNode; } return *this; } /** The destructor removes allocated resources. When used on the \em base preferences group, the destructor flushes all changes to the preference file and deletes all internal databases. The destructor does not remove any data from the database. It merely deletes your reference to the database. */ Fl_Preferences::~Fl_Preferences() { if (node && !node->parent()) delete rootNode; // DO NOT delete nodes! The root node will do that after writing the preferences. // Zero all pointer to avoid memory errors, even though // Valgrind does not complain (Cygwin does though) node = 0L; rootNode = 0L; } /** Return the file name and path to the preference file. If the preferences have not changed or have not been flushed, the file or directory may not have been created yet. \param[out] buffer write the resulting path into this buffer \param[in] buffer_size size of the `buffer` in bytes \return the root type at creation type, or MEMORY for runtime prefs, it does not return CORE or LOCALE flags. */ Fl_Preferences::Root Fl_Preferences::filename( char *buffer, size_t buffer_size) { if (!buffer || buffer_size==0) return UNKNOWN_ROOT_TYPE; RootNode *rn = rootNode; if (!rn) return UNKNOWN_ROOT_TYPE; if (rn->root()==MEMORY) return MEMORY; char *fn = rn->filename(); if (!fn) return UNKNOWN_ROOT_TYPE; fl_strlcpy(buffer, fn, buffer_size); if (buffer[0]==0) return UNKNOWN_ROOT_TYPE; return (Root)(rn->root() & ROOT_MASK); } /** Returns the number of groups that are contained within a group. \return 0 for no groups at all */ int Fl_Preferences::groups() { return node->nChildren(); } /** Returns the name of the Nth (\p num_group) group. There is no guaranteed order of group names. The index must be within the range given by groups(). \param[in] num_group number indexing the requested group \return 'C' string pointer to the group name */ const char *Fl_Preferences::group( int num_group ) { return node->child( num_group ); } /** Returns non-zero if a group with this name exists. Group names are relative to the Fl_Preferences node and can contain a path. "." describes the current node, "./" describes the topmost node. By preceding a groupname with a "./" its path becomes relative to the topmost node. \param[in] key name of group that is searched for \return 0 if no group by that name was found */ char Fl_Preferences::group_exists( const char *key ) { return node->search( key ) ? 1 : 0 ; } /** Deletes a group. Removes a group and all keys and groups within that group from the database. \param[in] group name of the group to delete \return 0 if call failed */ char Fl_Preferences::delete_group( const char *group ) { Node *nd = node->search( group ); if ( nd ) return nd->remove(); return 0; } /** Delete all groups. */ char Fl_Preferences::delete_all_groups() { node->deleteAllChildren(); return 1; } /** Returns the number of entries (name/value pairs) in a group. \return number of entries */ int Fl_Preferences::entries() { return node->nEntry(); } /** Returns the name of an entry. There is no guaranteed order of entry names. The index must be within the range given by entries(). \param[in] index number indexing the requested entry \return pointer to value cstring */ const char *Fl_Preferences::entry( int index ) { return node->entry(index).name; } /** Returns non-zero if an entry with this name exists. \param[in] key name of entry that is searched for \return 0 if entry was not found */ char Fl_Preferences::entry_exists( const char *key ) { return node->getEntry( key )>=0 ? 1 : 0 ; } /** Deletes a single name/value pair. This function removes the entry \p key from the database. \param[in] key name of entry to delete \return 0 if deleting the entry failed */ char Fl_Preferences::delete_entry( const char *key ) { return node->deleteEntry( key ); } /** Delete all entries. */ char Fl_Preferences::delete_all_entries() { node->deleteAllEntries(); return 1; } /** Delete all groups and all entries. */ char Fl_Preferences::clear() { char ret1 = deleteAllGroups(); char ret2 = deleteAllEntries(); return ret1 & ret2; } /** Reads an entry from the group. A default value must be supplied. The return value indicates if the value was available (non-zero) or the default was used (0). \param[in] key name of entry \param[out] value returned from preferences or default value if none was set \param[in] defaultValue default value to be used if no preference was set \return 0 if the default value was used */ char Fl_Preferences::get( const char *key, int &value, int defaultValue ) { const char *v = node->get( key ); value = v ? atoi( v ) : defaultValue; return ( v != 0 ); } /** Sets an entry (name/value pair). The return value indicates if there was a problem storing the data in memory. However it does not reflect if the value was actually stored in the preference file. \param[in] key name of entry \param[in] value set this entry to \p value \return 0 if setting the value failed */ char Fl_Preferences::set( const char *key, int value ) { snprintf( nameBuffer, sizeof(nameBuffer), "%d", value ); node->set( key, nameBuffer ); return 1; } /** Reads an entry from the group. A default value must be supplied. The return value indicates if the value was available (non-zero) or the default was used (0). \param[in] key name of entry \param[out] value returned from preferences or default value if none was set \param[in] defaultValue default value to be used if no preference was set \return 0 if the default value was used */ char Fl_Preferences::get( const char *key, float &value, float defaultValue ) { const char *v = node->get( key ); if (v) { if (rootNode->root() & C_LOCALE) { clocale_sscanf(v, "%g", &value); } else { value = (float)atof(v); } } else { value = defaultValue; } return ( v != NULL ); } /** Sets an entry (name/value pair). The return value indicates if there was a problem storing the data in memory. However it does not reflect if the value was actually stored in the preference file. \param[in] key name of entry \param[in] value set this entry to \p value \return 0 if setting the value failed */ char Fl_Preferences::set( const char *key, float value ) { if (rootNode->root() & C_LOCALE) { clocale_snprintf( nameBuffer, sizeof(nameBuffer), "%g", value ); } else { snprintf( nameBuffer, sizeof(nameBuffer), "%g", value ); } node->set( key, nameBuffer ); return 1; } /** Sets an entry (name/value pair). The return value indicates if there was a problem storing the data in memory. However it does not reflect if the value was actually stored in the preference file. \param[in] key name of entry \param[in] value set this entry to \p value \param[in] precision number of decimal digits to represent value \return 0 if setting the value failed */ char Fl_Preferences::set( const char *key, float value, int precision ) { if (rootNode->root() & C_LOCALE) { clocale_snprintf( nameBuffer, sizeof(nameBuffer), "%.*g", precision, value ); } else { snprintf( nameBuffer, sizeof(nameBuffer), "%.*g", precision, value ); } node->set( key, nameBuffer ); return 1; } /** Reads an entry from the group. A default value must be supplied. The return value indicates if the value was available (non-zero) or the default was used (0). \param[in] key name of entry \param[out] value returned from preferences or default value if none was set \param[in] defaultValue default value to be used if no preference was set \return 0 if the default value was used */ char Fl_Preferences::get( const char *key, double &value, double defaultValue ) { const char *v = node->get( key ); if (v) { if (rootNode->root() & C_LOCALE) { clocale_sscanf(v, "%lg", &value); } else { value = atof(v); } } else { value = defaultValue; } return ( v != NULL ); } /** Sets an entry (name/value pair). The return value indicates if there was a problem storing the data in memory. However it does not reflect if the value was actually stored in the preference file. \param[in] key name of entry \param[in] value set this entry to \p value \return 0 if setting the value failed */ char Fl_Preferences::set( const char *key, double value ) { if (rootNode->root() & C_LOCALE) { clocale_snprintf( nameBuffer, sizeof(nameBuffer), "%lg", value ); } else { snprintf( nameBuffer, sizeof(nameBuffer), "%lg", value ); } node->set( key, nameBuffer ); return 1; } /** Sets an entry (name/value pair). The return value indicates if there was a problem storing the data in memory. However it does not reflect if the value was actually stored in the preference file. \param[in] key name of entry \param[in] value set this entry to \p value \param[in] precision number of decimal digits to represent value \return 0 if setting the value failed */ char Fl_Preferences::set( const char *key, double value, int precision ) { if (rootNode->root() & C_LOCALE) { clocale_snprintf( nameBuffer, sizeof(nameBuffer), "%.*lg", precision, value ); } else { snprintf( nameBuffer, sizeof(nameBuffer), "%.*lg", precision, value ); } node->set( key, nameBuffer ); return 1; } // remove control sequences from a string static char *decodeText( const char *src ) { int len = 0; const char *s = src; for ( ; *s; s++, len++ ) { if ( *s == '\\' ) { if ( isdigit( s[1] ) ) { s+=3; } else { s+=1; } } } char *dst = (char*)malloc( len+1 ), *d = dst; for ( s = src; *s; s++ ) { char c = *s; if ( c == '\\' ) { if ( s[1] == '\\' ) { *d++ = c; s++; } else if ( s[1] == 'n' ) { *d++ = '\n'; s++; } else if ( s[1] == 'r' ) { *d++ = '\r'; s++; } else if ( isdigit( s[1] ) ) { *d++ = ((s[1]-'0')<<6) + ((s[2]-'0')<<3) + (s[3]-'0'); s+=3; } else s++; // error } else *d++ = c; } *d = 0; return dst; } /** Reads an entry from the group. A default value must be supplied. The return value indicates if the value was available (non-zero) or the default was used (0). 'maxSize' is the maximum length of text that will be read. The text buffer must allow for one additional byte for a trailing zero. \param[in] key name of entry \param[out] text returned from preferences or default value if none was set \param[in] defaultValue default value to be used if no preference was set \param[in] maxSize maximum length of value plus one byte for a trailing zero \return 0 if the default value was used */ char Fl_Preferences::get( const char *key, char *text, const char *defaultValue, int maxSize ) { const char *v = node->get( key ); if ( v && strchr( v, '\\' ) ) { char *w = decodeText( v ); strlcpy(text, w, maxSize); free( w ); return 1; } if ( !v ) v = defaultValue; if ( v ) strlcpy(text, v, maxSize); else *text = 0; return ( v != defaultValue ); } /** Reads an entry from the group. A default value must be supplied. The return value indicates if the value was available (non-zero) or the default was used (0). get() allocates memory of sufficient size to hold the value. The buffer must be free'd by the developer using 'free(value)'. \param[in] key name of entry \param[out] text returned from preferences or default value if none was set \param[in] defaultValue default value to be used if no preference was set \return 0 if the default value was used */ char Fl_Preferences::get( const char *key, char *&text, const char *defaultValue ) { const char *v = node->get( key ); if ( v && strchr( v, '\\' ) ) { text = decodeText( v ); return 1; } if ( !v ) v = defaultValue; if ( v ) text = fl_strdup( v ); else text = 0; return ( v != defaultValue ); } #if (FLTK_USE_STD) /** Reads an entry from the group. A default value must be supplied. The return value indicates if the value was available (non-zero) or the default was used (0). \param[in] key name of entry \param[out] value returned from preferences or default value if none was set \param[in] defaultValue default value to be used if no preference was set \return 0 if the default value was used */ char Fl_Preferences::get( const char *key, std::string &value, const std::string &defaultValue ) { const char *v = node->get( key ); if (v) { if ( strchr( v, '\\' ) ) { char *text = decodeText( v ); value = text; ::free(text); } else { value = v; } return 1; } else { value = defaultValue; return 0; } } #endif /** Sets an entry (name/value pair). The return value indicates if there was a problem storing the data in memory. However it does not reflect if the value was actually stored in the preference file. \param[in] key name of entry \param[in] text set this entry to \p value \return 0 if setting the value failed */ char Fl_Preferences::set( const char *key, const char *text ) { const char *s = text ? text : ""; int n=0, ns=0; for ( ; *s; s++ ) { n++; if ( *s<32 || *s=='\\' || *s==0x7f ) ns+=4; } if ( ns ) { char *buffer = (char*)malloc( n+ns+1 ), *d = buffer; for ( s=text; *s; ) { char c = *s; if ( c=='\\' ) { *d++ = '\\'; *d++ = '\\'; s++; } else if ( c=='\n' ) { *d++ = '\\'; *d++ = 'n'; s++; } else if ( c=='\r' ) { *d++ = '\\'; *d++ = 'r'; s++; } else if ( c<32 || c==0x7f ) { *d++ = '\\'; *d++ = '0'+((c>>6)&3); *d++ = '0'+((c>>3)&7); *d++ = '0'+(c&7); s++; } else *d++ = *s++; } *d = 0; node->set( key, buffer ); free( buffer ); } else node->set( key, text ); return 1; } // convert a hex string to binary data static void *decodeHex( const char *src, int &size ) { size = (int) strlen( src )/2; unsigned char *data = (unsigned char*)malloc( size ), *d = data; const char *s = src; for ( int i=size; i>0; i-- ) { int v; char x = tolower(*s++); if ( x >= 'a' ) v = x-'a'+10; else v = x-'0'; v = v<<4; x = tolower(*s++); if ( x >= 'a' ) v += x-'a'+10; else v += x-'0'; *d++ = (uchar)v; } return (void*)data; } /** Reads a binary entry from the group, encoded in hexadecimal blocks. \param[in] key name of entry \param[out] data value returned from preferences or default value if none was set \param[in] defaultValue default value \param[in] defaultSize size of default value array \param[in] maxSize maximum length of value, to receive the number of bytes read, use the function below instead. \return 0 if the default value was used \see Fl_Preferences::get( const char *key, void *data, const void *defaultValue, int defaultSize, int *maxSize ) */ char Fl_Preferences::get( const char *key, void *data, const void *defaultValue, int defaultSize, int maxSize ) { const char *v = node->get( key ); if ( v ) { int dsize; void *w = decodeHex( v, dsize ); memmove( data, w, dsize>maxSize?maxSize:dsize ); free( w ); return 1; } if ( defaultValue ) memmove( data, defaultValue, defaultSize>maxSize?maxSize:defaultSize ); return 0; } /** Reads a binary entry from the group, encoded in hexadecimal blocks. A binary (not hex) default value can be supplied. The return value indicates if the value was available (non-zero) or the default was used (0). `maxSize` is the maximum length of text that will be read and returns the actual number of bytes read. \param[in] key name of entry \param[out] data value returned from preferences or default value if none was set \param[in] defaultValue default value to be used if no preference was set \param[in] defaultSize size of default value array \param[inout] maxSize maximum length of value and actual number of bytes set \return 0 if the default value was used */ char Fl_Preferences::get( const char *key, void *data, const void *defaultValue, int defaultSize, int *maxSize ) { if (!maxSize || !data) return -1; int capacity = *maxSize; const char *v = node->get( key ); if ( v ) { int nFound; void *w = decodeHex( v, nFound ); int nWrite = (nFound>capacity) ? capacity : nFound; memmove( data, w, nWrite); free( w ); *maxSize = nWrite; return 1; } if ( defaultValue ) { int nWrite = (defaultSize>capacity) ? capacity : defaultSize; memmove( data, defaultValue, nWrite ); *maxSize = nWrite; } else { *maxSize = 0; } return 0; } /** Reads an entry from the group. A default value must be supplied. The return value indicates if the value was available (non-zero) or the default was used (0). get() allocates memory of sufficient size to hold the value. The buffer must be free'd by the developer using 'free(value)'. \param[in] key name of entry \param[out] data returned from preferences or default value if none was set \param[in] defaultValue default value to be used if no preference was set \param[in] defaultSize size of default value array \return 0 if the default value was used */ char Fl_Preferences::get( const char *key, void *&data, const void *defaultValue, int defaultSize ) { const char *v = node->get( key ); if ( v ) { int dsize; data = decodeHex( v, dsize ); return 1; } if ( defaultValue ) { data = (void*)malloc( defaultSize ); memmove( data, defaultValue, defaultSize ); } else data = 0; return 0; } /** Sets an entry (name/value pair). The return value indicates if there was a problem storing the data in memory. However it does not reflect if the value was actually stored in the preference file. \param[in] key name of entry \param[in] data set this entry to \p value \param[in] dsize size of data array \return 0 if setting the value failed */ char Fl_Preferences::set( const char *key, const void *data, int dsize ) { char *buffer = (char*)malloc( dsize*2+1 ), *d = buffer;; unsigned char *s = (unsigned char*)data; for ( ; dsize>0; dsize-- ) { static char lu[] = "0123456789abcdef"; unsigned char v = *s++; *d++ = lu[v>>4]; *d++ = lu[v&0xf]; } *d = 0; node->set( key, buffer ); free( buffer ); return 1; } #if (FLTK_USE_STD) /** Sets an entry (name/value pair). The return value indicates if there was a problem storing the data in memory. However it does not reflect if the value was actually stored in the preference file. \param[in] entry name of entry \param[in] value set this entry to value (stops at the first nul character). \return 0 if setting the value failed */ char Fl_Preferences::set( const char *entry, const std::string &value ) { return set(entry, value.c_str()); } #endif // FLTK_USE_STD /** Returns the size of the value part of an entry. \param[in] key name of entry \return size of value */ int Fl_Preferences::size( const char *key ) { const char *v = node->get( key ); return (int) (v ? strlen( v ) : 0); } /** \brief Creates a path that is related to the preference file and that is usable for additional application data. This function creates a directory that is named after the preferences database without the \c .prefs extension and located in the same directory. It then fills the given buffer with the complete path name. There is no way to verify that the path name fit into the buffer. If the name is too long, it will be clipped. This function can be used with direct paths that don't end in \c .prefs . \a getUserDataPath() will remove any extension and end the path with a \c / . If the file name has no extension, \a getUserDataPath() will append \c .data/ to the path name. Example: \code Fl_Preferences prefs( USER, "matthiasm.com", "test" ); char path[FL_PATH_MAX]; prefs.getUserdataPath( path, FL_PATH_MAX ); \endcode creates the preferences database in the directory (User 'matt' on Linux): \code /Users/matt/.fltk/matthiasm.com/test.prefs \endcode ..and returns the userdata path: \code /Users/matt/.fltk/matthiasm.com/test/ \endcode \param[out] path buffer for user data path \param[in] pathlen size of path buffer (should be at least \c FL_PATH_MAX ) \return 1 if there is no filename (\a path will be unmodified) \return 1 if \a pathlen is 0 (\a path will be unmodified) \return 1 if a path was created successfully, \a path will contain the path name ending in a '/' \return 0 if path was not created for some reason; \a path will contain the pathname that could not be created \see Fl_Preferences::Fl_Preferences(Root, const char*, const char*) */ char Fl_Preferences::get_userdata_path( char *path, int pathlen ) { if ( rootNode ) return rootNode->getPath( path, pathlen ); return 0; } /** Writes preferences to disk if they were modified. This method can be used to verify that writing a preference file went well. Deleting the base preferences object will also write the contents of the database to disk. \return -1 if anything went wrong, i.e. file could not be opened, permissions blocked writing, etc. \return 0 if the file was written to disk. This does not check if the disk ran out of space and the file is truncated. \return 1 if no data was written to the database and no write attempt to disk was made. */ int Fl_Preferences::flush() { int ret = dirty(); if (ret != 1) return ret; return rootNode->write(); } /** Check if there were changes to the database that need to be written to disk. \return 1 if the database will be written to disk by `flush` or destructor. \return 0 if the database is unchanged since the last write operation. \return -1 f there is an internal database error. */ int Fl_Preferences::dirty() { Node *n = node; while (n && n->parent()) n = n->parent(); if (!n) return -1; return n->dirty(); } //----------------------------------------------------------------------------- // helper class to create dynamic group and entry names on the fly // /** Creates a group name or entry name on the fly. This version creates a simple unsigned integer as an entry name. \code int n, i; Fl_Preferences prev( appPrefs, "PreviousFiles" ); prev.get( "n", 0 ); for ( i=0; ipreference_rootnode(prefs, root, vendor, application); filename_ = filename ? fl_strdup(filename) : 0L; vendor_ = fl_strdup(vendor); application_ = fl_strdup(application); if ( (root & CLEAR) == 0 ) read(); } // create the root node // - construct the name of the file that will hold our preferences Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs, const char *path, const char *vendor, const char *application, Root flags ) : prefs_(prefs), filename_(0L), vendor_(0L), application_(0L), root_type_( (Root)(USER | (flags & C_LOCALE) )) { if (!vendor) vendor = "unknown"; if (!application) { application = "unknown"; filename_ = fl_strdup(path); } else { char filename[ FL_PATH_MAX ]; filename[0] = 0; snprintf(filename, sizeof(filename), "%s/%s.prefs", path, application); filename_ = fl_strdup(filename); } vendor_ = fl_strdup(vendor); application_ = fl_strdup(application); if ( (flags & CLEAR) == 0 ) read(); } // create a root node that exists only on RAM and can not be read or written to // a file Fl_Preferences::RootNode::RootNode( Fl_Preferences *prefs ) : prefs_(prefs), filename_(0L), vendor_(0L), application_(0L), root_type_(Fl_Preferences::MEMORY) { } // destroy the root node and all depending nodes Fl_Preferences::RootNode::~RootNode() { if ( prefs_->node->dirty() ) write(); if ( filename_ ) { free( filename_ ); filename_ = 0L; } if ( vendor_ ) { free( vendor_ ); vendor_ = 0L; } if ( application_ ) { free( application_ ); application_ = 0L; } delete prefs_->node; prefs_->node = 0L; } // read a preference file and construct the group tree and all entry leaves int Fl_Preferences::RootNode::read() { if ( (root_type_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::MEMORY ) { prefs_->node->clearDirtyFlags(); return 0; } if (!filename_ || !filename_[0]) // filename could not be created return -1; if ( (root_type_ & Fl_Preferences::CORE) && !(fileAccess_ & Fl_Preferences::CORE_READ_OK) ) { prefs_->node->clearDirtyFlags(); return -1; } if ( ((root_type_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::USER) && !(fileAccess_ & Fl_Preferences::USER_READ_OK) ) { prefs_->node->clearDirtyFlags(); return -1; } if ( ((root_type_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::SYSTEM) && !(fileAccess_ & Fl_Preferences::SYSTEM_READ_OK) ) { prefs_->node->clearDirtyFlags(); return -1; } char buf[1024]; FILE *f = fl_fopen( filename_, "rb" ); if ( !f ) return -1; if (fgets( buf, 1024, f )==0) { /* ignore: "; FLTK preferences file format 1.0" */ } if (fgets( buf, 1024, f )==0) { /* ignore: "; vendor: ..." */ } if (fgets( buf, 1024, f )==0) { /* ignore: "; application: ..." */ } Node *nd = prefs_->node; for (;;) { if ( !fgets( buf, 1024, f ) ) break; // EOF or Error if ( buf[0]=='[' ) { // read a new group size_t end = strcspn( buf+1, "]\n\r" ); buf[ end+1 ] = 0; nd = prefs_->node->find( buf+1 ); } else if ( buf[0]=='+' ) { // value of previous name/value pair spans multiple lines size_t end = strcspn( buf+1, "\n\r" ); if ( end != 0 ) { // if entry is not empty buf[ end+1 ] = 0; if (nd) nd->add( buf+1 ); } } else { // read a name/value pair size_t end = strcspn( buf, "\n\r" ); if ( end != 0 ) { // if entry is not empty buf[ end ] = 0; if (nd) nd->set( buf ); } } } fclose( f ); prefs_->node->clearDirtyFlags(); return 0; } // write the group tree and all entry leaves int Fl_Preferences::RootNode::write() { if ( (root_type_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::MEMORY ) { prefs_->node->clearDirtyFlags(); return 0; } if (!filename_ || !filename_[0]) // filename could not be created return -1; if ( (root_type_ & Fl_Preferences::CORE) && !(fileAccess_ & Fl_Preferences::CORE_WRITE_OK) ) return -1; if ( ((root_type_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::USER) && !(fileAccess_ & Fl_Preferences::USER_WRITE_OK) ) return -1; if ( ((root_type_&Fl_Preferences::ROOT_MASK)==Fl_Preferences::SYSTEM) && !(fileAccess_ & Fl_Preferences::SYSTEM_WRITE_OK) ) return -1; fl_make_path_for_file(filename_); FILE *f = fl_fopen( filename_, "wb" ); if ( !f ) return -1; fprintf( f, "; FLTK preferences file format 1.0\n" ); fprintf( f, "; vendor: %s\n", vendor_ ); fprintf( f, "; application: %s\n", application_ ); prefs_->node->write( f ); fclose( f ); if (Fl::system_driver()->preferences_need_protection_check()) { // unix: make sure that system prefs are user-readable if (strncmp(filename_, "/etc/fltk/", 10) == 0) { char *p; p = filename_ + 9; do { // for each directory to the pref file *p = 0; fl_chmod(filename_, 0755); // rwxr-xr-x *p = '/'; p = strchr(p+1, '/'); } while (p); fl_chmod(filename_, 0644); // rw-r--r-- } } return 0; } // get the path to the preferences directory // - copy the path into the buffer at "path" // - if the resulting path is longer than "pathlen", it will be cropped char Fl_Preferences::RootNode::getPath( char *path, int pathlen ) { if (!filename_) // RUNTIME preferences. or filename could not be created return 1; // return 1 (not -1) to be consistent with fl_make_path() if (pathlen<=0) return 1; // copy the root filepath into the provided buffer strlcpy( path, filename_, pathlen); char *name = 0L, *ext = 0L; // use Unix style separators { char *s; for ( s = path; *s; s++ ) if ( *s == '\\' ) *s = '/'; } // find the start of the filename inside the path name = strrchr( path, '/' ); // this is a safety measure. The root path should be absolute and contain '/'s if (name) name++; // point right after the '/' character else name = path; // point at the first character of a filename-only path // find the last '.' which may be the start of a file extension ext = strrchr( path, '.' ); if ( (ext==0L) || (extpreferences_need_protection_check() && strncmp(path, "/etc/fltk/", 10) == 0) { fl_chmod(path, 0755); // rwxr-xr-x } strlcat( path, "/", pathlen ); return ret; } // create a node that represents a group // - path must be a single word, preferable alnum(), dot and underscore only. Space is ok. Fl_Preferences::Node::Node( const char *path ) { if ( path ) path_ = fl_strdup( path ); else path_ = 0; first_child_ = 0; next_ = 0; parent_ = 0; entry_ = 0; nEntry_ = NEntry_ = 0; dirty_ = 0; top_ = 0; indexed_ = 0; index_ = 0; nIndex_ = NIndex_ = 0; } void Fl_Preferences::Node::deleteAllChildren() { Node *next_node = NULL; for ( Node *current_node = first_child_; current_node; current_node = next_node ) { next_node = current_node->next_; delete current_node; } first_child_ = NULL; dirty_ = 1; updateIndex(); } void Fl_Preferences::Node::deleteAllEntries() { if ( entry_ ) { for ( int i = 0; i < nEntry_; i++ ) { if ( entry_[i].name ) { ::free( entry_[i].name ); entry_[i].name = NULL; } if ( entry_[i].value ) { ::free( entry_[i].value ); entry_[i].value = NULL; } } free( entry_ ); entry_ = NULL; nEntry_ = 0; NEntry_ = 0; } dirty_ = 1; } // delete this and all depending nodes Fl_Preferences::Node::~Node() { next_ = NULL; parent_ = NULL; deleteAllChildren(); deleteAllEntries(); deleteIndex(); if ( path_ ) { ::free( path_ ); path_ = NULL; } } // recursively check if any entry is dirty (was changed after loading a fresh prefs file) char Fl_Preferences::Node::dirty() { if ( dirty_ ) return 1; if ( next_ && next_->dirty() ) return 1; if ( first_child_ && first_child_->dirty() ) return 1; return 0; } // recursively clear all dirty flags void Fl_Preferences::Node::clearDirtyFlags() { Fl_Preferences::Node *nd = this; while (nd) { nd->dirty_ = 0; if ( nd->first_child_ ) nd->first_child_->clearDirtyFlags(); nd = nd->next_; } } // write this node (recursively from the last neighbor back to this) // write all entries // write all children int Fl_Preferences::Node::write( FILE *f ) { if ( next_ ) next_->write( f ); fprintf( f, "\n[%s]\n\n", path_ ); for ( int i = 0; i < nEntry_; i++ ) { char *src = entry_[i].value; if ( src ) { // hack it into smaller pieces if needed fprintf( f, "%s:", entry_[i].name ); size_t cnt, written = 0; for ( cnt = 0; cnt < 60; cnt++ ) if ( src[cnt]==0 ) break; written += fwrite( src, cnt, 1, f ); fprintf( f, "\n" ); src += cnt; for (;*src;) { for ( cnt = 0; cnt < 80; cnt++ ) if ( src[cnt]==0 ) break; fputc( '+', f ); written += fwrite( src, cnt, 1, f ); fputc( '\n', f ); src += cnt; } (void)written; // silence warning } else fprintf( f, "%s\n", entry_[i].name ); } if ( first_child_ ) first_child_->write( f ); dirty_ = 0; return 0; } // set the parent node and create the full path void Fl_Preferences::Node::setParent( Node *pn ) { parent_ = pn; next_ = pn->first_child_; pn->first_child_ = this; snprintf( nameBuffer, sizeof(nameBuffer), "%s/%s", pn->path_, path_ ); free( path_ ); path_ = fl_strdup( nameBuffer ); } // find the corresponding root node Fl_Preferences::RootNode *Fl_Preferences::Node::findRoot() { Node *n = this; do { if (n->top_) return n->root_node_; n = n->parent(); } while (n); return 0L; } // add a child to this node and set its path (try to find it first...) Fl_Preferences::Node *Fl_Preferences::Node::addChild( const char *path ) { snprintf( nameBuffer, sizeof(nameBuffer), "%s/%s", path_, path ); char *name = fl_strdup( nameBuffer ); Node *nd = find( name ); free( name ); updateIndex(); return nd; } // create and set, or change an entry within this node void Fl_Preferences::Node::set( const char *name, const char *value ) { for ( int i=0; i= sizeof( nameBuffer ) ) len = sizeof( nameBuffer ); strlcpy( nameBuffer, line, len ); set( nameBuffer, c+1 ); } else { set( line, "" ); } } dirty_ = dirt; } // Append data to an existing node. This is only used in read operations when // a single entry stretches over multiple lines in the prefs file. void Fl_Preferences::Node::add( const char *line ) { if ( lastEntrySet<0 || lastEntrySet>=nEntry_ ) return; char *&dst = entry_[ lastEntrySet ].value; size_t a = strlen( dst ); size_t b = strlen( line ); dst = (char*)realloc( dst, a+b+1 ); memcpy( dst+a, line, b+1 ); } // get the value for a name, returns 0 if no such name const char *Fl_Preferences::Node::get( const char *name ) { int i = getEntry( name ); return i>=0 ? entry_[i].value : 0 ; } // find the index of an entry, returns -1 if no such entry int Fl_Preferences::Node::getEntry( const char *name ) { for ( int i=0; inext_ ) { Node *nn = nd->find( path ); if ( nn ) return nn; } const char *s = path+len+1; const char *e = strchr( s, '/' ); if (e) strlcpy( nameBuffer, s, e-s+1 ); else strlcpy( nameBuffer, s, sizeof(nameBuffer)); nd = new Node( nameBuffer ); nd->setParent( this ); dirty_ = 1; return nd->find( path ); } } return 0; } // find a group somewhere in the tree starting here // caller must not set 'offset' argument // - if the node does not exist, 'search' returns NULL // - if the pathname is "." (current node) return this node // - if the pathname is "./" (root node) return the topmost node // - if the pathname starts with "./", start the search at the root node instead Fl_Preferences::Node *Fl_Preferences::Node::search( const char *path, int offset ) { if ( offset == 0 ) { if ( path[0] == '.' ) { if ( path[1] == 0 ) { return this; // user was searching for current node } else if ( path[1] == '/' ) { Node *nn = this; while ( nn->parent() ) nn = nn->parent(); if ( path[2]==0 ) { // user is searching for root ( "./" ) return nn; } return nn->search( path+2, 2 ); // do a relative search on the root node } } offset = (int) strlen( path_ ) + 1; } int len = (int) strlen( path_ ); if ( len < offset-1 ) return 0; len -= offset; if ( ( len <= 0 ) || ( strncmp( path, path_+offset, len ) == 0 ) ) { if ( len > 0 && path[ len ] == 0 ) return this; if ( len <= 0 || path[ len ] == '/' ) { for ( Node *nd = first_child_; nd; nd = nd->next_ ) { Node *nn = nd->search( path, offset ); if ( nn ) return nn; } return 0; } } return 0; } // return the number of child nodes (groups) int Fl_Preferences::Node::nChildren() { if (indexed_) { return nIndex_; } else { int cnt = 0; for ( Node *nd = first_child_; nd; nd = nd->next_ ) cnt++; return cnt; } } // return the node name const char *Fl_Preferences::Node::name() { if ( path_ ) { char *r = strrchr( path_, '/' ); return r ? r+1 : path_ ; } else { return 0L ; } } // return the n'th child node's name const char *Fl_Preferences::Node::child( int ix ) { Node *nd = childNode( ix ); if ( nd ) return nd->name(); else return 0L ; } // return the n'th child node Fl_Preferences::Node *Fl_Preferences::Node::childNode( int ix ) { createIndex(); if (indexed_) { // usually faster access in correct order, but needing more memory return index_[ix]; } else { // slow access and reverse order int n = nChildren(); ix = n - ix -1; Node *nd; for ( nd = first_child_; nd; nd = nd->next_ ) { if ( !ix-- ) break; if ( !nd ) break; } return nd; } } // remove myself from the list and delete me (and all children) char Fl_Preferences::Node::remove() { Node *nd = NULL, *np = NULL; Node *parent_node = parent(); if ( parent_node ) { nd = parent_node->first_child_; np = NULL; for ( ; nd; np = nd, nd = nd->next_ ) { if ( nd == this ) { if ( np ) np->next_ = next_; else parent_node->first_child_ = next_; next_ = NULL; break; } } parent_node->dirty_ = 1; parent_node->updateIndex(); } delete this; return ( nd != NULL ); } void Fl_Preferences::Node::createIndex() { if (indexed_) return; int n = nChildren(); if (n>NIndex_) { NIndex_ = n + 16; index_ = (Node**)realloc(index_, NIndex_*sizeof(Node*)); } Node *nd; int i = 0; for (nd = first_child_; nd; nd = nd->next_, i++) { index_[n-i-1] = nd; } nIndex_ = n; indexed_ = 1; } void Fl_Preferences::Node::updateIndex() { indexed_ = 0; } void Fl_Preferences::Node::deleteIndex() { if (index_) ::free(index_); index_ = NULL; NIndex_ = nIndex_ = 0; indexed_ = 0; } /** \brief Create a plugin. \param[in] klass plugins are grouped in classes \param[in] name every plugin should have a unique name */ Fl_Plugin::Fl_Plugin(const char *klass, const char *name) : id(0) { #ifdef FL_PLUGIN_VERBOSE printf("Fl_Plugin: creating a plugin, class \"%s\", name \"%s\"\n", klass, name); #endif Fl_Plugin_Manager pm(klass); id = pm.addPlugin(name, this); } /** \brief Clear the plugin and remove it from the database. */ Fl_Plugin::~Fl_Plugin() { #ifdef FL_PLUGIN_VERBOSE printf("Fl_Plugin: deleting a plugin\n"); #endif if (id) Fl_Plugin_Manager::remove(id); } /** \brief Manage all plugins belonging to one class. */ Fl_Plugin_Manager::Fl_Plugin_Manager(const char *klass) : Fl_Preferences(0, Fl_Preferences::Name("%s/%s", "plugins", klass)) { #ifdef FL_PLUGIN_VERBOSE printf("Fl_Plugin: creating a plugin manager for class \"%s\"\n", klass); #endif } /** \brief Remove the plugin manager. Calling this does not remove the database itself or any plugins. It just removes the reference to the database. */ Fl_Plugin_Manager::~Fl_Plugin_Manager() { #ifdef FL_PLUGIN_VERBOSE printf("Fl_Plugin: deleting a plugin manager\n"); #endif } static unsigned char x2i(char hi, char lo) { return ((hi-'A')<<4) | (lo-'A'); } static void i2x(unsigned char v, char *d) { d[0] = ((v>>4)&0x0f)+'A'; d[1] = (v&0x0f)+'A'; } static void *a2p(const char *s) { union { void *ret; unsigned char d[sizeof(void*)]; } v; v.ret = 0L; int i=0, n=sizeof(void*); for (i=0; iload(filename); // There is no way of unloading a plugin! return (dl != 0) ? 0 : -1; } /** Use this function to load a whole directory full of modules. \param dirpath Pathname of a directory. It \b must end with the platform's directory separator character (i.e., '\\' under Windows, '/' otherwise). \param pattern A filename pattern to catch all modules of interest in the targeted directory (e.g., "{*.so,*.dll,*.dylib}"), or NULL to catch all files in the directory. */ int Fl_Plugin_Manager::loadAll(const char *dirpath, const char *pattern) { struct dirent **dir; int i, n = fl_filename_list(dirpath, &dir); for (i=0; id_name, pattern)) { load(Fl_Preferences::Name("%s%s", dirpath, e->d_name)); } free(e); } free(dir); return 0; } fltk-1.4.3/src/Fl_Message.h0000644000175000017500000001255615004135251015563 0ustar albrechtalbrecht// // Common dialog header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _src_Fl_Message_h_ #define _src_Fl_Message_h_ #include #include #include class Fl_Button; class Fl_Input; /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** Fl_Message_Box is a tiny class that features copying the message text. This class is used in Fl_Message and handles ctrl-c or command-c (on macOS) to copy the given message text to the clipboard. */ /* Note: Do not FL_EXPORT this class, it's for internal use only */ class Fl_Message_Box : public Fl_Box { public: Fl_Message_Box(int X, int Y, int W, int H) : Fl_Box(X, Y, W, H) {} int handle(int e) FL_OVERRIDE; }; // class Fl_Message_Box /** This is the base class for all common FLTK dialog windows used in fl_message(), fl_ask(), fl_choice(), fl_input(), and fl_password(). \note Internal use only. This class may be changed as required without notice.\n This class is reserved for FLTK's internal usage in common dialogs in FLTK 1.4.x and later. The header file is "hidden" in the src/ folder and not installed with the public header files. This class uses some static variables used to let the user code change the behavior and look of the \b next call of some of the message related functions. This is necessary to support the existing fl_message() and similar functions and is safe as long as the variables are reset before the function pops up (shows) the message window and enters the internal (i.e. nested) event loop. \since 1.4.0 */ /* Note: Do not FL_EXPORT this class, it's for internal use only */ class Fl_Message { // static variables and methods private: static Fl_Box *message_icon_; // returned by Fl_Message::message_icon() static const char *message_title_; static const char *message_title_default_; // icon label for next dialog (STR #2762) static const char *message_icon_label_; // Note: since Fl_Message objects are destroyed before fl_input() // and fl_password() return their input text, we *need* to store // the text in an internal (static) buffer. :-( static char *input_buffer_; // points to the allocated text buffer static int input_size_; // size of allocated text buffer // the callback for all buttons: static void button_cb_(Fl_Widget *w, void *d); // the window callback: static void window_cb_(Fl_Widget *w, void *d); // resize to make text and buttons fit void resizeform(); public: static Fl_Box *message_icon(); static void message_title(const char *title); static void message_title_default(const char *title); static void icon_label(const char *str); /** Implements fl_message_position(const int, const int y, const int center). */ static void message_position(const int x, const int y, const int center) { form_x_ = x; form_y_ = y; form_position_ = center ? 2 : 1; } /** Implements fl_message_position(Fl_Widget *widget). */ static void message_position(Fl_Widget *widget) { int xo, yo; Fl_Window *win = widget->top_window_offset(xo, yo); form_x_ = xo + widget->w() / 2; form_y_ = yo + widget->h() / 2; if (win) { form_x_ += win->x(); form_y_ += win->y(); } form_position_ = 2; } /** Implements fl_message_position(int *x, int *y). */ static int message_position(int *x, int *y) { if (x) *x = form_position_ ? form_x_ : -1; if (y) *y = form_position_ ? form_y_ : -1; return form_position_; } /** Implements void fl_message_hotspot(int). */ static void message_hotspot(int enable) { enable_hotspot_ = enable ? 1 : 0; } /** Implements int fl_message_hotspot(). */ static int message_hotspot() { return enable_hotspot_; } int window_closed() const { return window_closed_; } // member variables and methods private: Fl_Window *window_; ///< message window Fl_Message_Box *message_; ///< message text (handles ctrl-c) Fl_Box *icon_; ///< contains the icon Fl_Button *button_[3]; ///< buttons used internally Fl_Input *input_; ///< normal text or secret input int retval_; ///< internally used to store the return value int window_closed_; ///< window close flag (-1 = Escape, -2 = close button) // static (private) variables static int enable_hotspot_; ///< follow the mouse pointer (hotspot) static int form_x_; ///< x position for next dialog static int form_y_; ///< y position for next dialog static int form_position_; ///< 0 = not set (may be hotspot), 1 = absolute, 2 = centered public: // Constructor Fl_Message(const char *iconlabel); /** Destructor. */ ~Fl_Message() { delete window_; } int innards(const char *fmt, va_list ap, const char *b0, const char *b1, const char *b2); const char *input_innards(const char *fmt, va_list ap, const char *defstr, uchar type, int maxchar = -1, bool str = false); }; /** \} \endcond */ #endif // _src_Fl_Message_h_ fltk-1.4.3/src/filename_match.cxx0000644000175000017500000000720015004135251017053 0ustar albrechtalbrecht// // Pattern matching routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* Adapted from Rich Salz. */ #include #include /** Checks if a string \p s matches a pattern \p p. The following syntax is used for the pattern: - * matches any sequence of 0 or more characters. - ? matches any single character. - [set] matches any character in the set. Set can contain any single characters, or a-z to represent a range. To match ] or - they must be the first characters. To match ^ or ! they must not be the first characters. - [^set] or [!set] matches any character not in the set. - {X|Y|Z} or {X,Y,Z} matches any one of the subexpressions literally. - \\x quotes the character x so it has no special meaning. - x all other characters are matched "exactly" on a \b case-insensitive basis. Notes: - \p s and \p p are matched on a char/byte basis, not as UCS codepoints or UTF-8 sequences. - [set] ranges must run from low to high, i.e. [a-z] and not [z-a] - [set] comparison is \b case-sensitive, i.e. [a-z] won't match "A". - \\x only applies to the fl_filename_match special characters * ? [ { - \\x needs a double \\ or the compiler will complain about non-standard escape sequences. \b Include: \code #include \endcode \param[in] s the string to check for a match \param[in] p the string pattern \return non zero if the string matches the pattern */ int fl_filename_match(const char *s, const char *p) { int matched; for (;;) { switch(*p++) { case '?' : // match any single character if (!*s++) return 0; break; case '*' : // match 0-n of any characters if (!*p) return 1; // do trailing * quickly while (!fl_filename_match(s, p)) if (!*s++) return 0; return 1; case '[': { // match one character in set of form [abc-d] or [^a-b] if (!*s) return 0; int reverse = (*p=='^' || *p=='!'); if (reverse) p++; matched = 0; char last = 0; while (*p) { if (*p=='-' && last) { if (*s <= *++p && *s >= last ) matched = 1; last = 0; } else { if (*s == *p) matched = 1; } last = *p++; if (*p==']') break; } if (matched == reverse) return 0; s++; p++;} break; case '{' : // {pattern1|pattern2|pattern3} NEXTCASE: if (fl_filename_match(s,p)) return 1; for (matched = 0;;) { switch (*p++) { case '\\': if (*p) p++; break; case '{': matched++; break; case '}': if (!matched--) return 0; break; case '|': case ',': if (matched==0) goto NEXTCASE; case 0: return 0; } } case '|': // skip rest of |pattern|pattern} when called recursively case ',': for (matched = 0; *p && matched >= 0;) { switch (*p++) { case '\\': if (*p) p++; break; case '{': matched++; break; case '}': matched--; break; } } break; case '}': break; case 0: // end of pattern return !*s; case '\\': // quote next character if (*p) p++; /* FALLTHROUGH */ default: if (tolower(*s) != tolower(*(p-1))) return 0; s++; break; } } } fltk-1.4.3/src/Fl_abort.cxx0000644000175000017500000000150215004135251015646 0ustar albrechtalbrecht// // Warning/error message code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2011 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // You can also override this by redefining all of these. #include #include "Fl_System_Driver.H" #include void (*Fl::warning)(const char* format, ...) = Fl_System_Driver::warning; void (*Fl::error)(const char* format, ...) = Fl_System_Driver::error; void (*Fl::fatal)(const char* format, ...) = Fl_System_Driver::fatal; fltk-1.4.3/src/Makefile0000644000175000017500000011523515004135251015043 0ustar albrechtalbrecht# # Library Makefile for the Fast Light Tool Kit (FLTK). # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # # Note: see ../configure.ac and/or ../makeinclude for definition of # FL_VERSION (x.y.z), FL_ABI_VERSION (x.y.0), and FL_DSO_VERSION (x.y) CPPFILES = \ Fl.cxx \ Fl_Adjuster.cxx \ Fl_Bitmap.cxx \ Fl_Browser.cxx \ Fl_Browser_.cxx \ Fl_Browser_load.cxx \ Fl_Box.cxx \ Fl_Button.cxx \ Fl_Cairo.cxx \ Fl_Chart.cxx \ Fl_Check_Browser.cxx \ Fl_Check_Button.cxx \ Fl_Choice.cxx \ Fl_Clock.cxx \ Fl_Color_Chooser.cxx \ Fl_Copy_Surface.cxx \ Fl_Counter.cxx \ Fl_Dial.cxx \ Fl_Device.cxx \ Fl_Double_Window.cxx \ Fl_File_Browser.cxx \ Fl_File_Chooser.cxx \ Fl_File_Chooser2.cxx \ Fl_File_Icon.cxx \ Fl_File_Input.cxx \ Fl_Flex.cxx \ Fl_Graphics_Driver.cxx \ Fl_Grid.cxx \ Fl_Group.cxx \ Fl_Help_View.cxx \ Fl_Image.cxx \ Fl_Image_Surface.cxx \ Fl_Input.cxx \ Fl_Input_.cxx \ Fl_Input_Choice.cxx \ Fl_Int_Vector.cxx \ Fl_Light_Button.cxx \ Fl_Menu.cxx \ Fl_Menu_.cxx \ Fl_Menu_Bar.cxx \ Fl_Menu_Button.cxx \ Fl_Menu_Window.cxx \ Fl_Menu_add.cxx \ Fl_Menu_global.cxx \ Fl_Message.cxx \ Fl_Multi_Label.cxx \ Fl_Native_File_Chooser.cxx \ Fl_Overlay_Window.cxx \ Fl_Pack.cxx \ Fl_Paged_Device.cxx \ Fl_Pixmap.cxx \ Fl_Positioner.cxx \ Fl_Preferences.cxx \ Fl_Printer.cxx \ Fl_Progress.cxx \ Fl_Repeat_Button.cxx \ Fl_Return_Button.cxx \ Fl_Roller.cxx \ Fl_Round_Button.cxx \ Fl_Screen_Driver.cxx \ Fl_Scheme.cxx \ Fl_Scheme_Choice.cxx \ Fl_Scroll.cxx \ Fl_Scrollbar.cxx \ Fl_Shared_Image.cxx \ Fl_Shortcut_Button.cxx \ Fl_Single_Window.cxx \ Fl_Slider.cxx \ Fl_Spinner.cxx \ Fl_String.cxx \ Fl_Sys_Menu_Bar.cxx \ Fl_System_Driver.cxx \ Fl_Table.cxx \ Fl_Table_Row.cxx \ Fl_Tabs.cxx \ Fl_Terminal.cxx \ Fl_Text_Buffer.cxx \ Fl_Text_Display.cxx \ Fl_Text_Editor.cxx \ Fl_Tile.cxx \ Fl_Tiled_Image.cxx \ Fl_Timeout.cxx \ Fl_Tree.cxx \ Fl_Tree_Item.cxx \ Fl_Tree_Item_Array.cxx \ Fl_Tree_Prefs.cxx \ Fl_Tooltip.cxx \ Fl_Valuator.cxx \ Fl_Value_Input.cxx \ Fl_Value_Output.cxx \ Fl_Value_Slider.cxx \ Fl_Widget.cxx \ Fl_Widget_Surface.cxx \ Fl_Window.cxx \ Fl_Window_Driver.cxx \ Fl_Window_fullscreen.cxx \ Fl_Window_hotspot.cxx \ Fl_Window_iconize.cxx \ Fl_Wizard.cxx \ Fl_XBM_Image.cxx \ Fl_XPM_Image.cxx \ Fl_abort.cxx \ Fl_add_idle.cxx \ Fl_arg.cxx \ Fl_compose.cxx \ Fl_display.cxx \ Fl_get_system_colors.cxx \ Fl_grab.cxx \ Fl_lock.cxx \ Fl_own_colormap.cxx \ Fl_visual.cxx \ filename_absolute.cxx \ filename_expand.cxx \ filename_ext.cxx \ filename_isdir.cxx \ filename_list.cxx \ filename_match.cxx \ filename_setext.cxx \ fl_arc.cxx \ fl_ask.cxx \ fl_boxtype.cxx \ fl_color.cxx \ fl_contrast.cxx \ fl_cursor.cxx \ fl_curve.cxx \ fl_diamond_box.cxx \ fl_draw.cxx \ fl_draw_arrow.cxx \ fl_draw_pixmap.cxx \ fl_encoding_latin1.cxx \ fl_encoding_mac_roman.cxx \ fl_engraved_label.cxx \ fl_file_dir.cxx \ fl_font.cxx \ fl_gleam.cxx \ fl_gtk.cxx \ fl_labeltype.cxx \ fl_open_uri.cxx \ fl_oval_box.cxx \ fl_overlay.cxx \ fl_oxy.cxx \ fl_plastic.cxx \ fl_read_image.cxx \ fl_rect.cxx \ fl_round_box.cxx \ fl_rounded_box.cxx \ fl_set_font.cxx \ fl_scroll_area.cxx \ fl_shadow_box.cxx \ fl_shortcut.cxx \ fl_show_colormap.cxx \ fl_string_functions.cxx \ fl_symbols.cxx \ fl_utf8.cxx \ fl_vertex.cxx \ print_button.cxx \ screen_xywh.cxx OBJCPPFILES = \ Fl_cocoa.mm \ drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm \ Fl_Native_File_Chooser_MAC.mm \ Fl_MacOS_Sys_Menu_Bar.mm FLCPPFILES = \ forms_compatibility.cxx \ forms_bitmap.cxx \ forms_free.cxx \ forms_fselect.cxx \ forms_pixmap.cxx \ forms_timer.cxx GLCPPFILES = \ Fl_Gl_Choice.cxx \ Fl_Gl_Overlay.cxx \ Fl_Gl_Device_Plugin.cxx \ Fl_Gl_Window.cxx \ freeglut_geometry.cxx \ freeglut_stroke_mono_roman.cxx \ freeglut_stroke_roman.cxx \ freeglut_teapot.cxx \ gl_draw.cxx \ gl_start.cxx \ glut_compatibility.cxx \ glut_font.cxx \ drivers/OpenGL/Fl_OpenGL_Display_Device.cxx \ drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.cxx \ drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.cxx \ drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.cxx \ drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.cxx \ drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.cxx \ drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.cxx GLOBJCPPFILES = drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm GLCPPFILES_X11 = drivers/X11/Fl_X11_Gl_Window_Driver.cxx GLCPPFILES_XFT = $(GLCPPFILES_X11) GLCPPFILES_CAIRO = $(GLCPPFILES_X11) GLCPPFILES_WIN = drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx GLCPPFILES_WAYLAND = drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx GLCPPFILES_WAYLANDX11 = $(GLCPPFILES_WAYLAND) \ drivers/X11/Fl_X11_Gl_Window_Driver.cxx GLCPPFILES += $(GLCPPFILES_$(BUILD)) GLMMFILES_OSX = $(GLOBJCPPFILES) GLMMFILES = $(GLMMFILES_$(BUILD)) # the following file currently doesn't contribute code to GLCPPFILES # drivers/OpenGL/Fl_OpenGL_Graphics_Driver.cxx IMGCPPFILES = \ fl_images_core.cxx \ fl_write_png.cxx \ Fl_BMP_Image.cxx \ Fl_File_Icon2.cxx \ Fl_GIF_Image.cxx \ Fl_Anim_GIF_Image.cxx \ Fl_Help_Dialog.cxx \ Fl_ICO_Image.cxx \ Fl_JPEG_Image.cxx \ Fl_PNG_Image.cxx \ Fl_PNM_Image.cxx \ Fl_Image_Reader.cxx \ Fl_SVG_Image.cxx \ nanosvg.cxx \ drivers/SVG/Fl_SVG_File_Surface.cxx CFILES = flstring.c numericsort.c vsnprintf.c CFILES_WIN = fl_call_main.c UTF8CFILES = \ xutf8/case.c \ xutf8/is_right2left.c \ xutf8/is_spacing.c QUARTZCPPFILES = \ drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx \ drivers/Quartz/Fl_Quartz_Graphics_Driver_color.cxx \ drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx \ drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx \ drivers/Quartz/Fl_Quartz_Graphics_Driver_vertex.cxx \ drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx \ drivers/Quartz/Fl_Quartz_Graphics_Driver_arci.cxx \ drivers/Quartz/Fl_Quartz_Graphics_Driver_line_style.cxx \ drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx \ drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx \ drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx \ drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx \ drivers/Posix/Fl_Posix_System_Driver.cxx \ drivers/Darwin/Fl_Darwin_System_Driver.cxx \ drivers/Darwin/fl_macOS_platform_init.cxx \ Fl_get_key_mac.cxx # These C++ files are used under condition: BUILD_X11 XLIBCPPFILES = \ drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx \ drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx \ drivers/X11/Fl_X11_Window_Driver.cxx \ drivers/X11/Fl_X11_Screen_Driver.cxx \ drivers/Posix/Fl_Posix_System_Driver.cxx \ drivers/Unix/Fl_Unix_System_Driver.cxx \ drivers/Unix/Fl_Unix_Screen_Driver.cxx \ drivers/Posix/Fl_Posix_Printer_Driver.cxx \ drivers/X11/fl_X11_platform_init.cxx \ Fl_x.cxx \ fl_dnd_x.cxx \ Fl_Native_File_Chooser_FLTK.cxx \ Fl_Native_File_Chooser_GTK.cxx\ Fl_Native_File_Chooser_Kdialog.cxx \ Fl_Native_File_Chooser_Zenity.cxx \ Fl_get_key.cxx # These graphics driver files are used under condition: BUILD_CAIRO CAIROGDFILES = \ drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx \ drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.cxx # These graphics driver files are used under condition: BUILD_X11 AND BUILD_XFT XLIBGDFILES = drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx \ drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx \ drivers/Xlib/Fl_Xlib_Graphics_Driver_color.cxx \ drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx \ drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx \ drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx \ drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx # These C++ files are used under conditions: BUILD_WAYLAND or BUILD_WAYLANDX11 WLCPPFILES = \ drivers/Posix/Fl_Posix_Printer_Driver.cxx \ Fl_Native_File_Chooser_FLTK.cxx \ Fl_Native_File_Chooser_GTK.cxx \ Fl_Native_File_Chooser_Kdialog.cxx \ Fl_Native_File_Chooser_Zenity.cxx \ drivers/Posix/Fl_Posix_System_Driver.cxx \ drivers/Unix/Fl_Unix_System_Driver.cxx \ drivers/Unix/Fl_Unix_Screen_Driver.cxx \ drivers/Wayland/Fl_Wayland_Screen_Driver.cxx \ drivers/Wayland/Fl_Wayland_Window_Driver.cxx \ drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx \ drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx \ drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx \ drivers/Wayland/fl_wayland_platform_init.cxx \ drivers/Wayland/fl_wayland_clipboard_dnd.cxx # These C++ files are used under condition: BUILD_WAYLANDX11 WLX11CPPFILES = \ drivers/X11/Fl_X11_Screen_Driver.cxx \ drivers/X11/Fl_X11_Window_Driver.cxx \ drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.cxx \ drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx \ drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx \ Fl_x.cxx \ fl_dnd_x.cxx \ Fl_get_key.cxx # fl_dnd_x.cxx Fl_Native_File_Chooser_GTK.cxx # This C file is used under condition: BUILD_X11 XLIBCFILES = \ xutf8/keysym2Ucs.c \ scandir_posix.c # These C files are used under condition: BUILD_X11 AND NOT BUILD_XFT XLIBXCFILES = \ xutf8/utf8Input.c \ xutf8/utf8Utils.c \ xutf8/utf8Wrap.c # These C++ files are used under condition: BUILD_X11 AND NOT BUILD_XFT XLIBFONTFILES = \ drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx # These C++ files are used under condition: BUILD_X11 AND BUILD_XFT XLIBXFTFILES = \ drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx \ drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx # This C file is used under condition: BUILD_WAYLAND WLCFILES = \ xutf8/keysym2Ucs.c \ scandir_posix.c # These C++ files are used under conditions: BUILD_WAYLAND or BUILD_WAYLANDX11 WLXFTFILES = \ drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx # These C++ files are used under condition: BUILD_GDI GDICPPFILES = \ drivers/GDI/Fl_GDI_Graphics_Driver.cxx \ drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx \ drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx \ drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx \ drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx \ drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx \ drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx \ drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx \ drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx \ drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx \ drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx \ drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx \ drivers/WinAPI/Fl_WinAPI_System_Driver.cxx \ drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx \ drivers/WinAPI/fl_WinAPI_platform_init.cxx \ Fl_win32.cxx \ fl_dnd_win32.cxx \ Fl_Native_File_Chooser_WIN32.cxx \ Fl_get_key_win32.cxx # These C files are used under condition: BUILD_GDI GDICFILES = \ scandir_win32.c PSCPPFILES = \ drivers/PostScript/Fl_PostScript.cxx \ drivers/PostScript/Fl_PostScript_image.cxx ################################################################ FLTKFLAGS = -DFL_LIBRARY include ../makeinclude # makeinclude has set this variable: # BUILD = {WIN|X11|XFT|CAIRO|OSX|WAYLAND|WAYLANDX11} MMFILES_OSX = $(OBJCPPFILES) MMFILES = $(MMFILES_$(BUILD)) CPPFILES += $(PSCPPFILES) CPPFILES_OSX = $(QUARTZCPPFILES) CPPFILES_XFT = $(XLIBCPPFILES) $(XLIBGDFILES) $(XLIBXFTFILES) CPPFILES_X11 = $(XLIBCPPFILES) $(XLIBGDFILES) $(XLIBFONTFILES) CPPFILES_CAIRO = $(XLIBCPPFILES) $(CAIROGDFILES) CPPFILES_WAYLAND = $(WLCPPFILES) $(WLXFTFILES) CPPFILES_WAYLANDX11 = $(CPPFILES_WAYLAND) $(WLX11CPPFILES) CPPFILES_WIN = $(GDICPPFILES) CPPFILES += $(CPPFILES_$(BUILD)) CFILES_X11 = $(XLIBCFILES) $(XLIBXCFILES) CFILES_CAIRO = $(XLIBCFILES) CFILES_XFT = $(XLIBCFILES) CFILES_WAYLANDX11 = $(WLCFILES) EXTRA_OBJECTS_WAYLAND = ../libdecor/build/fl_libdecor.o ../libdecor/build/libdecor-cairo-blur.o \ ../libdecor/build/fl_libdecor-plugins.o \ xdg-decoration-protocol.o xdg-shell-protocol.o text-input-protocol.o \ gtk-shell-protocol.o \ ../libdecor/build/desktop-settings.o ../libdecor/build/os-compatibility.o EXTRA_OBJECTS_WAYLANDX11 = $(EXTRA_OBJECTS_WAYLAND) EXTRA_CXXFLAGS_WAYLAND = -I. EXTRA_CXXFLAGS_WAYLANDX11 = $(EXTRA_CXXFLAGS_WAYLAND) CFILES_WIN += $(GDICFILES) CFILES += $(CFILES_$(BUILD)) CXXFLAGS += $(EXTRA_CXXFLAGS_$(BUILD)) OBJECTS = $(MMFILES:.mm=.o) $(CPPFILES:.cxx=.o) $(CFILES:.c=.o) $(UTF8CFILES:.c=.o) OBJECTS += $(EXTRA_OBJECTS_$(BUILD)) GLOBJECTS = $(GLCPPFILES:.cxx=.o) $(GLMMFILES:.mm=.o) FLOBJECTS = $(FLCPPFILES:.cxx=.o) IMGOBJECTS = $(IMGCPPFILES:.cxx=.o) all: $(LIBNAME) $(DSONAME) \ $(FLLIBNAME) $(FLDSONAME) \ $(GLLIBNAME) $(GLDSONAME) \ $(IMGLIBNAME) $(IMGDSONAME) $(LIBNAME): $(OBJECTS) echo $(LIBCOMMAND) $@ ... $(RM) $@ $(LIBCOMMAND) $@ $(OBJECTS) $(RANLIB) $@ libfltk.so.$(FL_DSO_VERSION): $(OBJECTS) echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ $(OBJECTS) $(LDFLAGS) $(LDLIBS) $(CAIROLIBS) $(RM) libfltk.so $(LN) libfltk.so.$(FL_DSO_VERSION) libfltk.so libfltk.sl.$(FL_DSO_VERSION): $(OBJECTS) echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ $(OBJECTS) $(RM) libfltk.sl $(LN) libfltk.sl.$(FL_DSO_VERSION) libfltk.sl libfltk.$(FL_DSO_VERSION).dylib: $(OBJECTS) echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ \ -install_name $(libdir)/$@ \ -current_version $(FL_VERSION) \ -compatibility_version $(FL_DSO_VERSION).0 \ $(OBJECTS) $(LDFLAGS) $(LDLIBS) $(CAIROLIBS) $(RM) libfltk.dylib $(LN) libfltk.$(FL_DSO_VERSION).dylib libfltk.dylib libfltk_s.a: $(OBJECTS) echo $(DSOCOMMAND) libfltk_s.o ... $(DSOCOMMAND) libfltk_s.o $(OBJECTS) $(IMAGELIBS) echo $(LIBCOMMAND) libfltk_s.a libfltk_s.o $(RM) $@ $(LIBCOMMAND) libfltk_s.a libfltk_s.o $(CHMOD) +x libfltk_s.a $(FLLIBNAME): $(FLOBJECTS) echo $(LIBCOMMAND) $@ ... $(RM) $@ $(LIBCOMMAND) $@ $(FLOBJECTS) $(RANLIB) $@ libfltk_forms.so.$(FL_DSO_VERSION): $(FLOBJECTS) libfltk.so.$(FL_DSO_VERSION) echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ $(FLOBJECTS) -L. -lfltk $(LDFLAGS) $(LDLIBS) $(RM) libfltk_forms.so $(LN) libfltk_forms.so.$(FL_DSO_VERSION) libfltk_forms.so libfltk_forms.sl.$(FL_DSO_VERSION): $(FLOBJECTS) libfltk.sl.$(FL_DSO_VERSION) echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ $(FLOBJECTS) -L. -lfltk $(RM) libfltk_forms.sl $(LN) libfltk_forms.sl.$(FL_DSO_VERSION) libfltk_forms.sl libfltk_forms.$(FL_DSO_VERSION).dylib: $(FLOBJECTS) libfltk.$(FL_DSO_VERSION).dylib echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ \ -install_name $(libdir)/$@ \ -current_version $(FL_VERSION) \ -compatibility_version $(FL_ABI_VERSION) \ $(FLOBJECTS) -L. $(LDFLAGS) $(LDLIBS) -lfltk $(RM) libfltk_forms.dylib $(LN) libfltk_forms.$(FL_DSO_VERSION).dylib libfltk_forms.dylib libfltk_forms_s.a: $(FLOBJECTS) echo $(DSOCOMMAND) libfltk_forms_s.o ... $(DSOCOMMAND) libfltk_forms_s.o $(FLOBJECTS) echo $(LIBCOMMAND) libfltk_forms_s.a libfltk_forms_s.o $(RM) $@ $(LIBCOMMAND) libfltk_forms_s.a libfltk_forms_s.o $(CHMOD) +x libfltk_forms_s.a $(GLLIBNAME): $(GLOBJECTS) echo $(LIBCOMMAND) $@ ... $(RM) $@ $(LIBCOMMAND) $@ $(GLOBJECTS) $(RANLIB) $@ libfltk_gl.so.$(FL_DSO_VERSION): $(GLOBJECTS) libfltk.so.$(FL_DSO_VERSION) echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ $(GLOBJECTS) -L. -lfltk $(LDFLAGS) $(LDLIBS) $(GLDLIBS) $(RM) libfltk_gl.so $(LN) libfltk_gl.so.$(FL_DSO_VERSION) libfltk_gl.so libfltk_gl.sl.$(FL_DSO_VERSION): $(GLOBJECTS) libfltk.sl.$(FL_DSO_VERSION) echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ $(GLOBJECTS) -L. -lfltk $(RM) libfltk_gl.sl $(LN) libfltk_gl.sl.$(FL_DSO_VERSION) libfltk_gl.sl libfltk_gl.$(FL_DSO_VERSION).dylib: $(GLOBJECTS) libfltk.$(FL_DSO_VERSION).dylib echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ \ -install_name $(libdir)/$@ \ -current_version $(FL_VERSION) \ -compatibility_version $(FL_ABI_VERSION) \ $(GLOBJECTS) -L. $(GLDLIBS) -lfltk $(RM) libfltk_gl.dylib $(LN) libfltk_gl.$(FL_DSO_VERSION).dylib libfltk_gl.dylib libfltk_gl_s.a: $(GLOBJECTS) echo $(DSOCOMMAND) libfltk_gl_s.o ... $(DSOCOMMAND) libfltk_gl_s.o $(GLOBJECTS) echo $(LIBCOMMAND) libfltk_gl_s.a libfltk_gl_s.o $(RM) $@ $(LIBCOMMAND) libfltk_gl_s.a libfltk_gl_s.o $(CHMOD) +x libfltk_gl_s.a $(IMGLIBNAME): $(IMGOBJECTS) echo $(LIBCOMMAND) $@ ... $(RM) $@ $(LIBCOMMAND) $@ $(IMGOBJECTS) $(RANLIB) $@ libfltk_images.so.$(FL_DSO_VERSION): $(IMGOBJECTS) libfltk.so.$(FL_DSO_VERSION) echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ $(IMGOBJECTS) -L. $(IMAGELIBS) -lfltk $(LDFLAGS) $(LDLIBS) $(RM) libfltk_images.so $(LN) libfltk_images.so.$(FL_DSO_VERSION) libfltk_images.so libfltk_images.sl.$(FL_DSO_VERSION): $(IMGOBJECTS) libfltk.sl.$(FL_DSO_VERSION) echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ $(IMGOBJECTS) -L. $(IMAGELIBS) -lfltk $(RM) libfltk_images.sl $(LN) libfltk_images.sl.$(FL_DSO_VERSION) libfltk_images.sl libfltk_images.$(FL_DSO_VERSION).dylib: $(IMGOBJECTS) libfltk.$(FL_DSO_VERSION).dylib echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ \ -install_name $(libdir)/$@ \ -current_version $(FL_VERSION) \ -compatibility_version $(FL_ABI_VERSION) \ $(IMGOBJECTS) -L. $(LDFLAGS) $(LDLIBS) $(IMAGELIBS) -lfltk $(RM) libfltk_images.dylib $(LN) libfltk_images.$(FL_DSO_VERSION).dylib libfltk_images.dylib libfltk_images_s.a: $(IMGOBJECTS) echo $(DSOCOMMAND) libfltk_images_s.o ... $(DSOCOMMAND) libfltk_images_s.o $(IMGOBJECTS) echo $(LIBCOMMAND) libfltk_images_s.a libfltk_images_s.o $(RM) $@ $(LIBCOMMAND) libfltk_images_s.a libfltk_images_s.o $(CHMOD) +x libfltk_images_s.a #----------------------------------------------------------------- # - the import libraries libfltk*.dll.a and the .dll files # are created from the libfltk*.a files. They are built # into the src dir. # - The _images, _gl, _forms and dlls must be linked # against the import libraries in the src dir. #----------------------------------------------------------------- #----------------------------------------------------------------- # cygwin GDI shared libraries #----------------------------------------------------------------- cygfltknox-$(FL_DSO_VERSION).dll: $(LIBNAME) echo $(DSOCOMMAND) $(LIBNAME) ... $(DSOCOMMAND) $(LIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk.dll.a $(LDLIBS) cygfltknox_forms-$(FL_DSO_VERSION).dll: $(FLLIBNAME) cygfltknox-$(FL_DSO_VERSION).dll echo $(DSOCOMMAND) $(FLLIBNAME) ... $(DSOCOMMAND) $(FLLIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk_forms.dll.a \ -L. -lfltk $(LDLIBS) cygfltknox_gl-$(FL_DSO_VERSION).dll: $(GLLIBNAME) cygfltknox-$(FL_DSO_VERSION).dll echo $(DSOCOMMAND) $(GLLIBNAME) ... $(DSOCOMMAND) $(GLLIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk_gl.dll.a \ -L. -lfltk $(GLDLIBS) cygfltknox_images-$(FL_DSO_VERSION).dll: $(IMGLIBNAME) cygfltknox-$(FL_DSO_VERSION).dll echo $(DSOCOMMAND) $(IMGLIBNAME) ... $(DSOCOMMAND) $(IMGLIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk_images.dll.a \ -L. -lfltk -Wl,--exclude-libs -Wl,libfltk_png.a \ $(IMAGELIBS) $(LDLIBS) #----------------------------------------------------------------- # cygwin X11 shared libraries #----------------------------------------------------------------- cygfltk-$(FL_DSO_VERSION).dll: $(LIBNAME) echo $(DSOCOMMAND) $(LIBNAME) ... $(DSOCOMMAND) $(LIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk.dll.a $(LDLIBS) cygfltk_forms-$(FL_DSO_VERSION).dll: $(FLLIBNAME) cygfltk-$(FL_DSO_VERSION).dll echo $(DSOCOMMAND) $(FLLIBNAME) ... $(DSOCOMMAND) $(FLLIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk_forms.dll.a \ -L. -lfltk $(LDLIBS) cygfltk_gl-$(FL_DSO_VERSION).dll: $(GLLIBNAME) cygfltk-$(FL_DSO_VERSION).dll echo $(DSOCOMMAND) $(GLLIBNAME) ... $(DSOCOMMAND) $(GLLIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk_gl.dll.a \ -L. -lfltk $(GLDLIBS) cygfltk_images-$(FL_DSO_VERSION).dll: $(IMGLIBNAME) cygfltk-$(FL_DSO_VERSION).dll echo $(DSOCOMMAND) $(IMGLIBNAME) ... $(DSOCOMMAND) $(IMGLIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk_images.dll.a \ -L. -lfltk -Wl,--exclude-libs -Wl,libfltk_png.a \ $(IMAGELIBS) $(LDLIBS) mgwfltknox-$(FL_DSO_VERSION).dll: $(LIBNAME) echo $(DSOCOMMAND) $(LIBNAME) ... $(DSOCOMMAND) $(LIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk.dll.a $(LDLIBS) mgwfltknox_forms-$(FL_DSO_VERSION).dll: $(FLLIBNAME) mgwfltknox-$(FL_DSO_VERSION).dll echo $(DSOCOMMAND) $(FLLIBNAME) ... $(DSOCOMMAND) $(FLLIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk_forms.dll.a \ -L. -lfltk $(LDLIBS) mgwfltknox_gl-$(FL_DSO_VERSION).dll: $(GLLIBNAME) mgwfltknox-$(FL_DSO_VERSION).dll echo $(DSOCOMMAND) $(GLLIBNAME) ... $(DSOCOMMAND) $(GLLIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk_gl.dll.a \ -L. -lfltk $(GLDLIBS) #----------------------------------------------------- # See STR #1585 for --exclude-libs #----------------------------------------------------- mgwfltknox_images-$(FL_DSO_VERSION).dll: $(IMGLIBNAME) mgwfltknox-$(FL_DSO_VERSION).dll echo $(DSOCOMMAND) $(IMGLIBNAME) ... $(DSOCOMMAND) $(IMGLIBNAME) -Wl,--no-whole-archive \ -Wl,--out-implib=libfltk_images.dll.a \ -L. -lfltk -Wl,--exclude-libs -Wl,libfltk_png.a \ $(IMAGELIBS) $(LDLIBS) # Note: The rebuild target can only be used if you have the original .fl # files. This is normally only used by the FLTK maintainers... # It *must* be executed *after* fluid has been built and # the libs must be rebuilt if any {.fl|.cxx|.h} files were changed. rebuild: echo 'Rebuilding fluid (.fl) and .cxx/.h files from .fl files ...' ../fluid/fluid$(EXEEXT) -u -c Fl_File_Chooser.fl ../fluid/fluid$(EXEEXT) -u -c Fl_Help_Dialog.fl clean: -$(RM) *.o xutf8/*.o *.dll.a core.* *~ *.bak *.bck -$(RM) drivers/Cairo/*.o -$(RM) drivers/Cocoa/*.o -$(RM) drivers/Darwin/*.o -$(RM) drivers/GDI/*.o -$(RM) drivers/OpenGL/*.o -$(RM) drivers/Posix/*.o -$(RM) drivers/PostScript/*.o -$(RM) drivers/Quartz/*.o -$(RM) drivers/SVG/*.o -$(RM) drivers/Unix/*.o -$(RM) drivers/WinAPI/*.o -$(RM) drivers/X11/*.o -$(RM) drivers/Xlib/*.o -$(RM) drivers/Wayland/*.o -$(RM) $(DSONAME) $(FLDSONAME) $(GLDSONAME) $(IMGDSONAME) \ $(LIBNAME) $(FLLIBNAME) $(GLLIBNAME) \ $(IMGLIBNAME) \ libfltk.so libfltk_forms.so libfltk_gl.so libfltk_images.so \ libfltk.sl libfltk_forms.sl libfltk_gl.sl libfltk_images.sl \ libfltk.dylib libfltk_forms.dylib \ libfltk_gl.dylib libfltk_images.dylib \ cmap core depend: $(CPPFILES) $(MMFILES) $(FLCPPFILES) $(GLCPPFILES) $(IMGCPPFILES) $(CFILES) $(UTF8CFILES) $(XLIBCFILES) makedepend -Y -I.. -f makedepend -w 20 $(CPPFILES) $(MMFILES) $(FLCPPFILES) \ $(GLCPPFILES) $(IMGCPPFILES) $(CFILES) $(UTF8CFILES) $(XLIBCFILES) echo "# DO NOT DELETE THIS LINE -- make depend depends on it." > makedepend.tmp echo "" >> makedepend.tmp grep '^[a-zA-Z]' makedepend | ( LC_ALL=C sort -u -f >> makedepend.tmp; ) mv makedepend.tmp makedepend # Automatically generated dependencies... generated on a Linux/Unix host ! include makedepend # These dependencies aren't part of the makedepend file since # they are part of the Windows and MacOS code base... # Please add only non-Linux/Unix files or such that are optional # (like "*non-Xft*") here: Fl_get_key_mac.o: Fl_get_key_mac.cxx Fl_get_key_win32.o: Fl_get_key_win32.cxx scandir_win32.o: scandir_win32.c Fl_Native_File_Chooser_WIN32.o: Fl_Native_File_Chooser_WIN32.cxx Fl_Native_File_Chooser_MAC.o: Fl_Native_File_Chooser_MAC.mm Fl_Native_File_Chooser_FLTK.o: Fl_Native_File_Chooser_FLTK.cxx Fl_Native_File_Chooser_GTK.o: Fl_Native_File_Chooser_GTK.cxx Fl_win32.o: Fl_win32.cxx Fl_cocoa.o: Fl_cocoa.mm fl_color.o: fl_dnd_win32.o: fl_dnd_win32.cxx fl_dnd_x.o: fl_dnd_x.cxx Fl_Printer.o: ../src/drivers/PostScript/Fl_PostScript.cxx Fl_Quartz_Printer.o: Fl_Quartz_Printer.mm fl_arci.o: ../FL/mac.H ../FL/win32.H Fl_arg.o: ../FL/mac.H ../FL/win32.H fl_ask.o: ../FL/mac.H ../FL/win32.H Fl_Bitmap.o: ../FL/mac.H ../FL/win32.H fl_color.o: ../FL/mac.H ../FL/win32.H fl_cursor.o: ../FL/mac.H ../FL/win32.H Fl_Double_Window.o: ../FL/mac.H ../FL/win32.H fl_draw_image.o: ../FL/mac.H ../FL/win32.H fl_draw_pixmap.o: ../FL/mac.H ../FL/win32.H fl_encoding_latin1.o: ../FL/mac.H ../FL/win32.H fl_encoding_mac_roman.o: ../FL/mac.H ../FL/win32.H Fl_File_Chooser2.o: ../FL/mac.H ../FL/win32.H fl_font.o: ../FL/mac.H ../FL/win32.H Fl_get_system_colors.o: ../FL/mac.H ../FL/win32.H Fl_Gl_Choice.o: ../FL/mac.H ../FL/win32.H Fl_Gl_Overlay.o: ../FL/mac.H ../FL/win32.H Fl_Gl_Window.o: ../FL/mac.H ../FL/win32.H Fl_grab.o: ../FL/mac.H ../FL/win32.H Fl_Image.o: ../FL/mac.H ../FL/win32.H fl_line_style.o: ../FL/mac.H ../FL/win32.H Fl_Menu_Window.o: ../FL/mac.H ../FL/win32.H fl_overlay.o: ../FL/mac.H ../FL/win32.H Fl_Overlay_Window.o: ../FL/mac.H ../FL/win32.H Fl_own_colormap.o: ../FL/mac.H ../FL/win32.H Fl_Pixmap.o: ../FL/mac.H ../FL/win32.H Fl_Printer.o: ../FL/mac.H ../FL/win32.H fl_rect.o: ../FL/mac.H ../FL/win32.H fl_scroll_area.o: ../FL/mac.H ../FL/win32.H fl_set_font.o: ../FL/mac.H ../FL/win32.H fl_set_fonts.o: ../FL/mac.H ../FL/win32.H fl_shortcut.o: ../FL/mac.H ../FL/win32.H fl_vertex.o: ../FL/mac.H ../FL/win32.H Fl_visual.o: ../FL/mac.H ../FL/win32.H Fl_Window_fullscreen.o: ../FL/mac.H ../FL/win32.H Fl_Window_iconize.o: ../FL/mac.H ../FL/win32.H gl_draw.o: ../FL/mac.H ../FL/win32.H gl_start.o: ../FL/mac.H ../FL/win32.H # these additional dependencies are for non-Xft builds on Linux/Unix drivers/X11/Fl_X11_Screen_Driver.o: Xutf8.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: drivers/Xlib/Fl_Font.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/fl_config.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Enumerations.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Fl_Bitmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Fl_Device.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/fl_draw.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Fl_Export.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Fl_Graphics_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Fl.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Fl_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Fl_Pixmap.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Fl_Plugin.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Fl_Preferences.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Fl_RGB_Image.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/fl_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/fl_utf8.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/Fl_Widget.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/platform.H drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: ../FL/platform_types.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: flstring.h drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.o: Xutf8.h drivers/Xlib/Fl_Xlib_Graphics_Driver.o: Xutf8.h gl_draw.o: Xutf8.h xutf8/utf8Utils.o: ../FL/Fl_Export.H xutf8/utf8Utils.o: Xutf8.h xutf8/utf8Wrap.o: ../FL/Fl_Export.H xutf8/utf8Wrap.o: utf8_internal.h xutf8/utf8Wrap.o: Xutf8.h xutf8/utf8Wrap.o: xutf8/headers/dingbats_.h xutf8/utf8Wrap.o: xutf8/headers/symbol_.h xutf8/utf8Wrap.o: xutf8/lcUniConv/big5.h xutf8/utf8Wrap.o: xutf8/lcUniConv/cp1251.h xutf8/utf8Wrap.o: xutf8/lcUniConv/cp936ext.h xutf8/utf8Wrap.o: xutf8/lcUniConv/gb2312.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_10.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_11.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_13.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_14.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_15.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_2.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_3.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_4.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_5.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_6.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_7.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_8.h xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_9.h xutf8/utf8Wrap.o: xutf8/lcUniConv/jisx0201.h xutf8/utf8Wrap.o: xutf8/lcUniConv/jisx0208.h xutf8/utf8Wrap.o: xutf8/lcUniConv/jisx0212.h xutf8/utf8Wrap.o: xutf8/lcUniConv/koi8_r.h xutf8/utf8Wrap.o: xutf8/lcUniConv/koi8_u.h xutf8/utf8Wrap.o: xutf8/lcUniConv/ksc5601.h xutf8/utf8Wrap.o: xutf8/ucs2fontmap.c ################################################################ install: $(LIBNAME) $(DSONAME) \ $(FLLIBNAME) $(FLDSONAME) \ $(GLLIBNAME) $(GLDSONAME) \ $(IMGLIBNAME) $(IMGDSONAME) echo "Installing libraries in $(DESTDIR)$(libdir)..." -$(INSTALL_DIR) "$(DESTDIR)$(libdir)" -$(INSTALL_DIR) "$(DESTDIR)$(bindir)" $(RM) "$(DESTDIR)$(libdir)/$(LIBBASENAME)" $(INSTALL_LIB) $(LIBNAME) "$(DESTDIR)$(libdir)" $(INSTALL_LIB) $(FLLIBNAME) "$(DESTDIR)$(libdir)" $(INSTALL_LIB) $(IMGLIBNAME) "$(DESTDIR)$(libdir)" $(RANLIB) "$(DESTDIR)$(libdir)/$(LIBBASENAME)" $(RANLIB) "$(DESTDIR)$(libdir)/$(FLLIBBASENAME)" if test x$(GLLIBNAME) != x; then \ $(INSTALL_LIB) $(GLLIBNAME) "$(DESTDIR)$(libdir)"; \ $(RANLIB) "$(DESTDIR)$(libdir)/$(GLLIBBASENAME)"; \ fi $(RANLIB) "$(DESTDIR)$(libdir)/$(IMGLIBBASENAME)" if test x$(DSONAME) = xlibfltk.so.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk.so*;\ $(INSTALL_LIB) libfltk.so.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)"; \ $(LN) libfltk.so.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)/libfltk.so";\ fi if test x$(DSONAME) = xlibfltk.sl.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk.sl*;\ $(INSTALL_LIB) libfltk.sl.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)"; \ $(LN) libfltk.sl.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)/libfltk.sl";\ fi if test x$(DSONAME) = xlibfltk.$(FL_DSO_VERSION).dylib; then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk.*dylib;\ $(INSTALL_LIB) libfltk.$(FL_DSO_VERSION).dylib "$(DESTDIR)$(libdir)"; \ $(LN) libfltk.$(FL_DSO_VERSION).dylib "$(DESTDIR)$(libdir)/libfltk.dylib";\ fi if test x$(DSONAME) = xlibfltk_s.a; then\ $(RM) "$(DESTDIR)$(libdir)/libfltk_s.a";\ $(INSTALL_LIB) libfltk_s.a "$(DESTDIR)$(libdir)"; \ fi if test x$(DSONAME) = xcygfltknox-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(DSONAME)";\ $(INSTALL_LIB) $(DSONAME) "$(DESTDIR)$(bindir)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk.dll.a";\ $(INSTALL_LIB) libfltk.dll.a "$(DESTDIR)$(libdir)"; \ fi if test x$(DSONAME) = xmgwfltknox-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(DSONAME)";\ $(INSTALL_LIB) $(DSONAME) "$(DESTDIR)$(bindir)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk.dll.a";\ $(INSTALL_LIB) libfltk.dll.a "$(DESTDIR)$(libdir)"; \ fi if test x$(FLDSONAME) = xlibfltk_forms.so.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_forms.so*;\ $(INSTALL_LIB) libfltk_forms.so.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)"; \ $(LN) libfltk_forms.so.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)/libfltk_forms.so";\ fi if test x$(FLDSONAME) = xlibfltk_forms.sl.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_forms.sl*;\ $(INSTALL_LIB) libfltk_forms.sl.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)"; \ $(LN) libfltk_forms.sl.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)/libfltk_forms.sl";\ fi if test x$(FLDSONAME) = xlibfltk_forms.$(FL_DSO_VERSION).dylib; then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_forms.*dylib;\ $(INSTALL_LIB) libfltk_forms.$(FL_DSO_VERSION).dylib "$(DESTDIR)$(libdir)"; \ $(LN) libfltk_forms.$(FL_DSO_VERSION).dylib "$(DESTDIR)$(libdir)/libfltk_forms.dylib";\ fi if test x$(FLDSONAME) = xlibfltk_forms_s.a; then\ $(RM) "$(DESTDIR)$(libdir)/libfltk_forms_s.a";\ $(INSTALL_LIB) libfltk_forms_s.a "$(DESTDIR)$(libdir)"; \ fi if test x$(FLDSONAME) = xcygfltknox_forms-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(FLDSONAME)";\ $(INSTALL_LIB) $(FLDSONAME) "$(DESTDIR)$(bindir)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_forms.dll.a";\ $(INSTALL_LIB) libfltk_forms.dll.a "$(DESTDIR)$(libdir)"; \ fi if test x$(FLDSONAME) = xmgwfltknox_forms-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(FLDSONAME)";\ $(INSTALL_LIB) $(FLDSONAME) "$(DESTDIR)$(bindir)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_forms.dll.a";\ $(INSTALL_LIB) libfltk_forms.dll.a "$(DESTDIR)$(libdir)"; \ fi if test x$(GLDSONAME) = xlibfltk_gl.so.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_gl.so*;\ $(INSTALL_LIB) libfltk_gl.so.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)"; \ $(LN) libfltk_gl.so.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)/libfltk_gl.so";\ fi if test x$(GLDSONAME) = xlibfltk_gl.sl.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_gl.sl*;\ $(INSTALL_LIB) libfltk_gl.sl.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)"; \ $(LN) libfltk_gl.sl.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)/libfltk_gl.sl";\ fi if test x$(GLDSONAME) = xlibfltk_gl.$(FL_DSO_VERSION).dylib; then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_gl.*dylib;\ $(INSTALL_LIB) libfltk_gl.$(FL_DSO_VERSION).dylib "$(DESTDIR)$(libdir)"; \ $(LN) libfltk_gl.$(FL_DSO_VERSION).dylib "$(DESTDIR)$(libdir)/libfltk_gl.dylib";\ fi if test x$(GLDSONAME) = xlibfltk_gl_s.a; then\ $(RM) "$(DESTDIR)$(libdir)/libfltk_gl_s.a";\ $(INSTALL_LIB) libfltk_gl_s.a "$(DESTDIR)$(libdir)"; \ fi if test x$(GLDSONAME) = xcygfltknox_gl-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(GLDSONAME)";\ $(INSTALL_LIB) $(GLDSONAME) "$(DESTDIR)$(bindir)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_gl.dll.a";\ $(INSTALL_LIB) libfltk_gl.dll.a "$(DESTDIR)$(libdir)"; \ fi if test x$(GLDSONAME) = xmgwfltknox_gl-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(GLDSONAME)";\ $(INSTALL_LIB) $(GLDSONAME) "$(DESTDIR)$(bindir)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_gl.dll.a";\ $(INSTALL_LIB) libfltk_gl.dll.a "$(DESTDIR)$(libdir)"; \ fi if test x$(IMGDSONAME) = xlibfltk_images.so.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_images.so*;\ $(INSTALL_LIB) libfltk_images.so.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)"; \ $(LN) libfltk_images.so.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)/libfltk_images.so";\ fi if test x$(IMGDSONAME) = xlibfltk_images.sl.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_images.sl*;\ $(INSTALL_LIB) libfltk_images.sl.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)"; \ $(LN) libfltk_images.sl.$(FL_DSO_VERSION) "$(DESTDIR)$(libdir)/libfltk_images.sl";\ fi if test x$(IMGDSONAME) = xlibfltk_images.$(FL_DSO_VERSION).dylib; then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_images.*dylib;\ $(INSTALL_LIB) libfltk_images.$(FL_DSO_VERSION).dylib "$(DESTDIR)$(libdir)"; \ $(LN) libfltk_images.$(FL_DSO_VERSION).dylib "$(DESTDIR)$(libdir)/libfltk_images.dylib";\ fi if test x$(IMGDSONAME) = xlibfltk_images_s.a; then\ $(RM) "$(DESTDIR)$(libdir)/libfltk_images_s.a";\ $(INSTALL_LIB) libfltk_images_s.a "$(DESTDIR)$(libdir)"; \ fi if test x$(IMGDSONAME) = xcygfltknox_images-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(IMGDSONAME)"; \ $(INSTALL_LIB) $(IMGDSONAME) "$(DESTDIR)$(bindir)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_images.dll.a";\ $(INSTALL_LIB) libfltk_images.dll.a "$(DESTDIR)$(libdir)"; \ fi if test x$(IMGDSONAME) = xmgwfltknox_images-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(IMGDSONAME)"; \ $(INSTALL_LIB) $(IMGDSONAME) "$(DESTDIR)$(bindir)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_images.dll.a";\ $(INSTALL_LIB) libfltk_images.dll.a "$(DESTDIR)$(libdir)"; \ fi uninstall: echo "Uninstalling libraries..." $(RM) "$(DESTDIR)$(libdir)/$(LIBBASENAME)" if test x$(DSONAME) = xlibfltk.so.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk.so*;\ fi if test x$(DSONAME) = xlibfltk.sl.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk.sl*;\ fi if test x$(DSONAME) = xlibfltk.$(FL_DSO_VERSION).dylib; then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk.*dylib;\ fi if test x$(DSONAME) = xlibfltk_s.a; then\ $(RM) "$(DESTDIR)$(libdir)/libfltk_s.a";\ fi if test x$(DSONAME) = xcygfltknox-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(DSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk.dll.a";\ fi if test x$(DSONAME) = xcygfltk-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(DSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk.dll.a";\ fi if test x$(DSONAME) = xmgwfltknox-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(DSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk.dll.a";\ fi $(RM) "$(DESTDIR)$(libdir)/$(FLLIBBASENAME)"; if test x$(FLDSONAME) = xlibfltk_forms.so.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_forms.so*;\ fi if test x$(FLDSONAME) = xlibfltk_forms.sl.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_forms.sl*;\ fi if test x$(FLDSONAME) = xlibfltk_forms.$(FL_DSO_VERSION).dylib; then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_forms.*dylib;\ fi if test x$(FLDSONAME) = xlibfltk_forms_s.a; then\ $(RM) "$(DESTDIR)$(libdir)/libfltk_forms_s.a";\ fi if test x$(FLDSONAME) = xcygfltknox_forms-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(FLDSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_forms.dll.a";\ fi if test x$(FLDSONAME) = xcygfltk_forms-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(FLDSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_forms.dll.a";\ fi if test x$(FLDSONAME) = xmgwfltknox_forms-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(FLDSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_forms.dll.a";\ fi if test x$(GLLIBNAME) != x; then\ $(RM) "$(DESTDIR)$(libdir)/$(GLLIBBASENAME)";\ fi if test x$(GLDSONAME) = xlibfltk_gl.so.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_gl.so*;\ fi if test x$(GLDSONAME) = xlibfltk_gl.sl.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_gl.sl*;\ fi if test x$(GLDSONAME) = xlibfltk_gl.$(FL_DSO_VERSION).dylib; then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_gl.*dylib;\ fi if test x$(GLDSONAME) = xlibfltk_gl_s.a; then\ $(RM) "$(DESTDIR)$(libdir)/libfltk_gl_s.a";\ fi if test x$(GLDSONAME) = xcygfltknox_gl-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(GLDSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_gl.dll.a";\ fi if test x$(GLDSONAME) = xcygfltk_gl-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(GLDSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_gl.dll.a";\ fi if test x$(GLDSONAME) = xmgwfltknox_gl-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(GLDSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_gl.dll.a";\ fi if test x$(IMGLIBNAME) != x; then\ $(RM) "$(DESTDIR)$(libdir)/$(IMGLIBBASENAME)";\ fi if test x$(IMGDSONAME) = xlibfltk_images.so.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_images.so*;\ fi if test x$(IMGDSONAME) = xlibfltk_images.sl.$(FL_DSO_VERSION); then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_images.sl*;\ fi if test x$(IMGDSONAME) = xlibfltk_images.$(FL_DSO_VERSION).dylib; then\ $(RM) "$(DESTDIR)$(libdir)"/libfltk_images.*dylib;\ fi if test x$(IMGDSONAME) = xlibfltk_images_s.a; then\ $(RM) "$(DESTDIR)$(libdir)/libfltk_images_s.a";\ fi if test x$(IMGDSONAME) = xcygfltknox_images-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(IMGDSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_images.dll.a";\ fi if test x$(IMGDSONAME) = xcygfltk_images-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(IMGDSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_images.dll.a";\ fi if test x$(IMGDSONAME) = xmgwfltknox_images-$(FL_DSO_VERSION).dll; then\ $(RM) "$(DESTDIR)$(bindir)/$(IMGDSONAME)"; \ $(RM) "$(DESTDIR)$(libdir)/libfltk_images.dll.a";\ fi fltk-1.4.3/src/numericsort.c0000644000175000017500000000715515004135251016122 0ustar albrechtalbrecht/* * Numeric sorting routine for the Fast Light Tool Kit (FLTK). * * Copyright 1998-2018 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #include #include #include #include #include #include /** \file numericsort.c */ /* numericsort() - Compare two directory entries, possibly with a case-insensitive comparison... */ static int numericsort(struct dirent **A, struct dirent **B, int cs) { const char* a = (*A)->d_name; const char* b = (*B)->d_name; int len_a, len_b; const char *end_a = a + strlen(a); const char *end_b = b + strlen(b); unsigned UTF_A, UTF_B; int ret = 0; while (1) { UTF_A = fl_utf8decode(a, end_a, &len_a); a += len_a; UTF_B = fl_utf8decode(b, end_b, &len_b); b += len_b; if (UTF_A <= 255 && UTF_B <= 255 && isdigit(UTF_A) && isdigit(UTF_B)) { int diff,magdiff; while (UTF_A == '0') {UTF_A = fl_utf8decode(a, end_a, &len_a); a += len_a;} while (UTF_B == '0') {UTF_B = fl_utf8decode(b, end_b, &len_b); b += len_b;} while (UTF_A <= 255 && isdigit(UTF_A) && UTF_A == UTF_B) { UTF_A = fl_utf8decode(a, end_a, &len_a); a += len_a; UTF_B = fl_utf8decode(b, end_b, &len_b); b += len_b; } diff = (UTF_A <= 255 && UTF_B <= 255 && isdigit(UTF_A) && isdigit(UTF_B)) ? UTF_A - UTF_B : 0; magdiff = 0; while (UTF_A <= 255 && isdigit(UTF_A)) { magdiff++; UTF_A = fl_utf8decode(a, end_a, &len_a); a += len_a; } while (UTF_B <= 255 && isdigit(UTF_B)) { magdiff--; UTF_B = fl_utf8decode(b, end_b, &len_b); b += len_b; } if (magdiff) {ret = magdiff; break;} /* compare # of significant digits */ if (diff) {ret = diff; break;} /* compare first non-zero digit */ } else { if (cs) { /* compare case-sensitive */ if ((ret = UTF_A - UTF_B)) break; } else { /* compare case-insensitive */ if ((ret = fl_tolower(UTF_A) - fl_tolower(UTF_B))) break; } if (a >= end_a) break; } } if (!ret) return 0; else return (ret < 0) ? -1 : 1; } /** Compares directory entries alphanumerically (case-insensitive). \note This comparison is UTF-8 aware. \see fl_numericsort() */ int fl_casenumericsort(struct dirent **A, struct dirent **B) { return numericsort(A, B, 0); } /** Compares directory entries alphanumerically (case-sensitive). Numbers are compared without sign, i.e. "-" is not taken as a sign of following numerical values. The following list of files would be in ascending order (examples are ASCII and numbers only for simplicity): -# 1zzz.txt -# 2xxx.txt -# 19uuu.txt -# 100aaa.txt -# file1z.txt -# file5a.txt -# file5z.txt -# file30z.txt -# file200a.txt -# temp+5.txt ('+' is lexically lower than '-') -# temp-5.txt ('-' is not a sign) -# temp-100.txt (100 is bigger than 5, no sign) \param[in] A first directory entry \param[in] B second directory entry \returns comparison result (-1, 0, or +1) \retval -1 A \< B \retval 0 A == B \retval +1 A \> B \note This comparison is UTF-8 aware. \see fl_casenumericsort() */ int fl_numericsort(struct dirent **A, struct dirent **B) { return numericsort(A, B, 1); } fltk-1.4.3/src/vsnprintf.c0000644000175000017500000002071015004135251015571 0ustar albrechtalbrecht/* * snprintf() and vsnprintf() functions for the Fast Light Tool Kit (FLTK). * * Copyright 1998-2010 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #include #include "flstring.h" #ifdef HAVE_SYS_STDTYPES_H # include #endif /* HAVE_SYS_STDTYPES_H */ #ifdef __cplusplus extern "C" { #endif /** \file vsnprintf.c \brief Portable vsnprintf() implementation. */ /** FLTK's platform independent wrapper for the vsnprintf() C library function. This function guarantees: - access to vsnprintf(), even on systems that don't have it (FLTK's own built-in code is used) - Guarantees NUL termination. Even if string expands larger than the buffer, a terminating NUL is included, unlike some implementations of vsnprintf(), notably Microsoft Visual Studio (pre-2015), which can leave the string unterminated when truncated. If the build environment for FLTK has vsnprintf(), fl_vsnprintf() is just a wrapper around the compiler's provided function. Otherwise, if the function is NOT available, FLTK's own built-in version is provided. The FLTK built in provides these style options: - %[ -+#'] - * -- padding width - .* -- precision width - Data types: h, l, ll, L - Floating point formats: E, G, e, f, g - Integer formats: B, X, b, d, i, o, u, x - Pointer format: p - String/char: c, s, n */ int fl_vsnprintf(char* buffer, size_t bufsize, const char* format, va_list ap) { #if defined(HAVE_VSNPRINTF) && defined(__linux__) return vsnprintf(buffer, bufsize, format, ap); #else char *bufptr, /* Pointer to position in buffer */ *bufend, /* Pointer to end of buffer */ sign, /* Sign of format width */ size, /* Size character (h, l, L) */ type; /* Format type character */ int width, /* Width of field */ prec; /* Number of characters of precision */ char tformat[100], /* Temporary format string for sprintf() */ *tptr, /* Pointer into temporary format */ temp[1024]; /* Buffer for formatted numbers */ char *s; /* Pointer to string */ int slen; /* Length of string */ int bytes; /* Total number of bytes needed */ /* * Loop through the format string, formatting as needed... */ bufptr = buffer; bufend = buffer + bufsize - 1; bytes = 0; while (*format) { if (*format == '%') { tptr = tformat; *tptr++ = *format++; if (*format == '%') { if (bufptr && bufptr < bufend) *bufptr++ = *format; bytes ++; format ++; continue; } else if (strchr(" -+#\'", *format)) { *tptr++ = *format; sign = *format++; } else sign = 0; if (*format == '*') { /* Get width from argument... */ format ++; width = va_arg(ap, int); snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width); tptr += strlen(tptr); } else { width = 0; while (isdigit(*format & 255)) { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; width = width * 10 + *format++ - '0'; } } if (*format == '.') { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; format ++; if (*format == '*') { /* Get precision from argument... */ format ++; prec = va_arg(ap, int); snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec); tptr += strlen(tptr); } else { prec = 0; while (isdigit(*format & 255)) { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; prec = prec * 10 + *format++ - '0'; } } } else prec = -1; size = '\0'; if (*format == 'l' && format[1] == 'l') { size = 'L'; if (tptr < (tformat + sizeof(tformat) - 2)) { *tptr++ = 'l'; *tptr++ = 'l'; } format += 2; } else if (*format == 'h' || *format == 'l' || *format == 'L') { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; size = *format++; } if (!*format) break; if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; type = *format++; *tptr = '\0'; switch (type) { case 'E' : /* Floating point formats */ case 'G' : case 'e' : case 'f' : case 'g' : if ((width + 2) > (int)sizeof(temp)) break; sprintf(temp, tformat, va_arg(ap, double)); bytes += (int) strlen(temp); if (bufptr) { if ((bufptr + strlen(temp)) > bufend) { strncpy(bufptr, temp, (size_t)(bufend - bufptr)); bufptr = bufend; } else { strcpy(bufptr, temp); bufptr += strlen(temp); } } break; case 'B' : /* Integer formats */ case 'X' : case 'b' : case 'd' : case 'i' : case 'o' : case 'u' : case 'x' : if ((width + 2) > (int)sizeof(temp)) break; #ifdef HAVE_LONG_LONG if (size == 'L') sprintf(temp, tformat, va_arg(ap, long long)); else #endif /* HAVE_LONG_LONG */ if (size == 'l') sprintf(temp, tformat, va_arg(ap, long)); else sprintf(temp, tformat, va_arg(ap, int)); bytes += (int) strlen(temp); if (bufptr) { if ((bufptr + strlen(temp)) > bufend) { strncpy(bufptr, temp, (size_t)(bufend - bufptr)); bufptr = bufend; } else { strcpy(bufptr, temp); bufptr += strlen(temp); } } break; case 'p' : /* Pointer value */ if ((width + 2) > (int)sizeof(temp)) break; sprintf(temp, tformat, va_arg(ap, void *)); bytes += (int) strlen(temp); if (bufptr) { if ((bufptr + strlen(temp)) > bufend) { strncpy(bufptr, temp, (size_t)(bufend - bufptr)); bufptr = bufend; } else { strcpy(bufptr, temp); bufptr += strlen(temp); } } break; case 'c' : /* Character or character array */ bytes += width; if (bufptr) { if (width <= 1) *bufptr++ = va_arg(ap, int); else { if ((bufptr + width) > bufend) width = (int) (bufend - bufptr); memcpy(bufptr, va_arg(ap, char *), (size_t)width); bufptr += width; } } break; case 's' : /* String */ if ((s = va_arg(ap, char *)) == NULL) s = "(null)"; slen = (int) strlen(s); if (slen > width && prec != width) width = slen; bytes += width; if (bufptr) { if ((bufptr + width) > bufend) width = (int) (bufend - bufptr); if (slen > width) slen = width; if (sign == '-') { strncpy(bufptr, s, (size_t)slen); memset(bufptr + slen, ' ', (size_t)(width - slen)); } else { memset(bufptr, ' ', (size_t)(width - slen)); strncpy(bufptr + width - slen, s, (size_t)slen); } bufptr += width; } break; case 'n' : /* Output number of chars so far */ *(va_arg(ap, int *)) = bytes; break; } } else { bytes ++; if (bufptr && bufptr < bufend) *bufptr++ = *format; format ++; } } /* * Nul-terminate the string and return the number of characters needed. */ if (bufptr) *bufptr = '\0'; return (bytes); #endif /* HAVE_VSNPRINTF */ } int fl_snprintf(char* str, size_t size, const char* fmt, ...) { int ret; va_list ap; va_start(ap, fmt); ret = vsnprintf(str, size, fmt, ap); va_end(ap); return ret; } #ifdef __cplusplus } #endif fltk-1.4.3/src/Fl_XBM_Image.cxx0000644000175000017500000000373215004135251016276 0ustar albrechtalbrecht// // Fl_XBM_Image routines. // // Copyright 1997-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // Fl_XBM_Image::Fl_XBM_Image() - Load an XBM file. // // // Include necessary header files... // #include #include #include #include #include #include "flstring.h" // // 'Fl_XBM_Image::Fl_XBM_Image()' - Load an XBM file. // /** The constructor loads the named XBM file from the given name filename. The destructor frees all memory and server resources that are used by the image. */ Fl_XBM_Image::Fl_XBM_Image(const char *name) : Fl_Bitmap((const char *)0,0,0) { FILE *f; uchar *ptr; if ((f = fl_fopen(name, "rb")) == NULL) return; char buffer[1024]; char junk[1024]; int wh[2]; // width and height int i; for (i = 0; i<2; i++) { for (;;) { if (!fgets(buffer,1024,f)) { fclose(f); return; } int r = sscanf(buffer,"#define %s %d",junk,&wh[i]); if (r >= 2) break; } } // skip to data array: for (;;) { if (!fgets(buffer,1024,f)) { fclose(f); return; } if (!strncmp(buffer,"static ",7)) break; } // Allocate memory... w(wh[0]); h(wh[1]); int n = ((wh[0]+7)/8)*wh[1]; array = new uchar[n]; // read the data: for (i = 0, ptr = (uchar *)array; i < n;) { if (!fgets(buffer,1024,f)) { fclose(f); return; } const char *a = buffer; while (*a && i0) { *ptr++ = (uchar)t; i ++; } while (*a && *a++ != ',') {/*empty*/} } } fclose(f); } fltk-1.4.3/src/Fl_PNM_Image.cxx0000644000175000017500000001252415004135251016301 0ustar albrechtalbrecht// // Fl_PNM_Image routines. // // Copyright 1997-2010 by Easy Software Products. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // Fl_PNM_Image::Fl_PNM_Image() - Load a PNM image... // // // Include necessary header files... // #include #include #include #include #include #include "flstring.h" // // 'Fl_PNM_Image::Fl_PNM_Image()' - Load a PNM image... // /** The constructor loads the named PNM image. The destructor frees all memory and server resources that are used by the image. Use Fl_Image::fail() to check if Fl_PNM_Image failed to load. fail() returns ERR_FILE_ACCESS if the file could not be opened or read, ERR_FORMAT if the PNM format could not be decoded, and ERR_NO_IMAGE if the image could not be loaded for another reason. \param[in] filename a full path and name pointing to a valid jpeg file. */ Fl_PNM_Image::Fl_PNM_Image(const char *filename) // I - File to read : Fl_RGB_Image(0,0,0) { FILE *fp; // File pointer int x, y; // Looping vars char line[1024], // Input line *lineptr; // Pointer in line uchar *ptr, // Pointer to pixel values byte, // Byte from file bit; // Bit in pixel int format, // Format of PNM file val, // Pixel value maxval; // Maximum pixel value if ((fp = fl_fopen(filename, "rb")) == NULL) { ld(ERR_FILE_ACCESS); return; } // // Read the file header in the format: // // Pformat // # comment1 // # comment2 // ... // # commentN // width // height // max sample // lineptr = fgets(line, sizeof(line), fp); if (!lineptr) { fclose(fp); Fl::error("Early end-of-file in PNM file \"%s\"!", filename); ld(ERR_FILE_ACCESS); return; } lineptr ++; format = atoi(lineptr); while (isdigit(*lineptr)) lineptr ++; if (format == 7) lineptr = (char *)""; while (lineptr != NULL && w() == 0) { if (*lineptr == '\0' || *lineptr == '#') { lineptr = fgets(line, sizeof(line), fp); } else if (isdigit(*lineptr)) { w((int)strtol(lineptr, &lineptr, 10)); } else lineptr ++; } while (lineptr != NULL && h() == 0) { if (*lineptr == '\0' || *lineptr == '#') { lineptr = fgets(line, sizeof(line), fp); } else if (isdigit(*lineptr)) { h((int)strtol(lineptr, &lineptr, 10)); } else lineptr ++; } if (format != 1 && format != 4) { maxval = 0; while (lineptr != NULL && maxval == 0) { if (*lineptr == '\0' || *lineptr == '#') { lineptr = fgets(line, sizeof(line), fp); } else if (isdigit(*lineptr)) { maxval = (int)strtol(lineptr, &lineptr, 10); } else lineptr ++; } } else maxval = 1; // Allocate memory... if (format == 1 || format == 2 || format == 4 || format == 5) d(1); else d(3); // printf("%s = %dx%dx%d\n", filename, w(), h(), d()); if (((size_t)w()) * h() * d() > max_size() ) { Fl::warning("PNM file \"%s\" is too large!\n", filename); fclose(fp); w(0); h(0); d(0); ld(ERR_FORMAT); return; } array = new uchar[w() * h() * d()]; alloc_array = 1; // Read the image file... for (y = 0; y < h(); y ++) { ptr = (uchar *)array + y * w() * d(); switch (format) { case 1 : for (x = w(); x > 0; x --) if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * (1-val)); break; case 2 : for (x = w(); x > 0; x --) if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval); break; case 3 : for (x = w(); x > 0; x --) { if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval); if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval); if (fscanf(fp, "%d", &val) == 1) *ptr++ = (uchar)(255 * val / maxval); } break; case 4 : for (x = w(), byte = (uchar)getc(fp), bit = 128; x > 0; x --) { if ((byte & bit) == 0) *ptr++ = 255; // 0 bit for white pixel else *ptr++ = 0; // 1 bit for black pixel if (bit > 1) bit >>= 1; else { bit = 128; if (x > 1) byte = (uchar)getc(fp); } } break; case 5 : case 6 : if (maxval < 256) { if (fread(ptr, w(), d(), fp)) { /* ignored */ } } else { for (x = d() * w(); x > 0; x --) { val = (uchar)getc(fp); val = (val<<8)|(uchar)getc(fp); *ptr++ = (255*val)/maxval; } } break; case 7 : /* XV 3:3:2 thumbnail format */ for (x = w(); x > 0; x --) { byte = (uchar)getc(fp); *ptr++ = (uchar)(255 * ((byte >> 5) & 7) / 7); *ptr++ = (uchar)(255 * ((byte >> 2) & 7) / 7); *ptr++ = (uchar)(255 * (byte & 3) / 3); } break; } } fclose(fp); } fltk-1.4.3/src/Fl_Box.cxx0000644000175000017500000000156415004135251015277 0ustar albrechtalbrecht// // Box widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include Fl_Box::Fl_Box(int X, int Y, int W, int H, const char *l) : Fl_Widget(X,Y,W,H,l) { } Fl_Box::Fl_Box(Fl_Boxtype b, int X, int Y, int W, int H, const char *l) : Fl_Widget(X,Y,W,H,l) { box(b); } void Fl_Box::draw() { draw_box(); draw_label(); } int Fl_Box::handle(int event) { if (event == FL_ENTER || event == FL_LEAVE) return 1; else return 0; } fltk-1.4.3/src/Fl_Value_Input.cxx0000644000175000017500000000726515004135251017006 0ustar albrechtalbrecht// // Value input widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // FLTK widget for drag-adjusting a floating point value. // Warning: this works by making a child Fl_Input object, even // though this object is *not* an Fl_Group. May be a kludge? #include #include #include #include #include void Fl_Value_Input::input_cb(Fl_Widget*, void* v) { Fl_Value_Input& t = *(Fl_Value_Input*)v; double nv; if ((t.step() - floor(t.step()))>0.0 || t.step() == 0.0) nv = strtod(t.input.value(), 0); else nv = strtol(t.input.value(), 0, 0); if (nv != t.value() || t.when() & FL_WHEN_NOT_CHANGED) { t.set_value(nv); t.set_changed(); if (t.when()) t.do_callback(FL_REASON_CHANGED); } } void Fl_Value_Input::draw() { if (damage()&~FL_DAMAGE_CHILD) input.clear_damage(FL_DAMAGE_ALL); input.box(box()); input.color(color(), selection_color()); Fl_Widget *i = &input; i->draw(); // calls protected input.draw() input.clear_damage(); } void Fl_Value_Input::resize(int X, int Y, int W, int H) { Fl_Valuator::resize(X, Y, W, H); input.resize(X, Y, W, H); } void Fl_Value_Input::value_damage() { char buf[128]; format(buf); input.value(buf); input.mark(input.insert_position()); // turn off selection highlight } int Fl_Value_Input::handle(int event) { double v; int delta; int mx = Fl::event_x_root(); static int ix, drag; input.when(when()); switch (event) { case FL_PUSH: if (!step()) goto DEFAULT; ix = mx; drag = Fl::event_button(); handle_push(); return 1; case FL_DRAG: if (!step()) goto DEFAULT; delta = mx-ix; if (delta > 5) delta -= 5; else if (delta < -5) delta += 5; else delta = 0; switch (drag) { case 3: v = increment(previous_value(), delta*100); break; case 2: v = increment(previous_value(), delta*10); break; default:v = increment(previous_value(), delta); break; } v = round(v); handle_drag(soft()?softclamp(v):clamp(v));; return 1; case FL_RELEASE: if (!step()) goto DEFAULT; if (value() != previous_value() || !Fl::event_is_click()) handle_release(); else { Fl_Widget_Tracker wp(&input); input.handle(FL_PUSH); if (wp.exists()) input.handle(FL_RELEASE); } return 1; case FL_FOCUS: return input.take_focus(); case FL_SHORTCUT: return input.handle(event); default: DEFAULT: input.type(((step() - floor(step()))>0.0 || step() == 0.0) ? FL_FLOAT_INPUT : FL_INT_INPUT); return input.handle(event); } } /** Creates a new Fl_Value_Input widget using the given position, size, and label string. The default boxtype is FL_DOWN_BOX. */ Fl_Value_Input::Fl_Value_Input(int X, int Y, int W, int H, const char* l) : Fl_Valuator(X, Y, W, H, l), input(X, Y, W, H, 0) { soft_ = 0; if (input.parent()) // defeat automatic-add input.parent()->remove(input); input.parent((Fl_Group *)this); // kludge! input.callback(input_cb, this); input.when(FL_WHEN_CHANGED); box(input.box()); color(input.color()); selection_color(input.selection_color()); align(FL_ALIGN_LEFT); value_damage(); set_flag(SHORTCUT_LABEL); } Fl_Value_Input::~Fl_Value_Input() { if (input.parent() == (Fl_Group *)this) input.parent(0); // *revert* ctor kludge! } fltk-1.4.3/src/Fl_Wizard.cxx0000644000175000017500000000750215004135251016005 0ustar albrechtalbrecht// // Fl_Wizard widget routines. // // Copyright 1997-2010 by Easy Software Products. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // Fl_Wizard::Fl_Wizard() - Create an Fl_Wizard widget. // Fl_Wizard::draw() - Draw the wizard border and visible child. // Fl_Wizard::next() - Show the next child. // Fl_Wizard::prev() - Show the previous child. // Fl_Wizard::value() - Return the current visible child. // Fl_Wizard::value() - Set the visible child. // // // Include necessary header files... // #include #include #include // // 'Fl_Wizard::Fl_Wizard()' - Create an Fl_Wizard widget. // /** The constructor creates the Fl_Wizard widget at the specified position and size.

The inherited destructor destroys the widget and its children. */ Fl_Wizard::Fl_Wizard(int xx, // I - Lefthand position int yy, // I - Upper position int ww, // I - Width int hh, // I - Height const char *l) : // I - Label Fl_Group(xx, yy, ww, hh, l) { box(FL_THIN_UP_BOX); value_ = (Fl_Widget *)0; } // /** Draws the wizard border and visible child. */ void Fl_Wizard::draw() { Fl_Widget *kid; // Visible child kid = value(); if (damage() & FL_DAMAGE_ALL) { // Redraw everything... if (kid) { draw_box(box(), x(), y(), w(), h(), kid->color()); draw_child(*kid); } else draw_box(box(), x(), y(), w(), h(), color()); } else if (kid) update_child(*kid); } /** This method shows the next child of the wizard. If the last child is already visible, this function does nothing. */ void Fl_Wizard::next() { int num_kids; Fl_Widget * const *kids; if ((num_kids = children()) == 0) return; for (kids = array(); num_kids > 0; kids ++, num_kids --) if ((*kids)->visible()) break; if (num_kids > 1) value(kids[1]); } /** Shows the previous child.*/ void Fl_Wizard::prev() { int num_kids; Fl_Widget * const *kids; if ((num_kids = children()) == 0) return; for (kids = array(); num_kids > 0; kids ++, num_kids --) if ((*kids)->visible()) break; if (num_kids > 0 && num_kids < children()) value(kids[-1]); } /** Gets the current visible child widget. */ Fl_Widget* Fl_Wizard::value() { int num_kids; Fl_Widget * const *kids; Fl_Widget *kid; if ((num_kids = children()) == 0) return ((Fl_Widget *)0); for (kids = array(), kid = (Fl_Widget *)0; num_kids > 0; kids ++, num_kids --) { if ((*kids)->visible()) { if (kid) (*kids)->hide(); else kid = *kids; } } if (!kid) { kids --; kid = *kids; kid->show(); } return (kid); } /** Sets the child widget that is visible.*/ void Fl_Wizard::value(Fl_Widget *kid) { int num_kids; Fl_Widget * const *kids; if ((num_kids = children()) == 0) return; for (kids = array(); num_kids > 0; kids ++, num_kids --) { if (*kids == kid) { if (!kid->visible()) kid->show(); } else (*kids)->hide(); } // This will restore the mouse pointer to the window's default cursor // whenever the wizard pane is changed. Otherwise text widgets that // show the next pane may leave the cursor set to the I beam, etc... if (window()) window()->cursor(FL_CURSOR_DEFAULT); } fltk-1.4.3/src/fl_oval_box.cxx0000644000175000017500000000401715004135251016414 0ustar albrechtalbrecht// // Oval box drawing code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Less-used box types are in separate files so they are not linked // in if not used. #include #include // Global parameters for box drawing algorithm: // // BW = box shadow width #define BW (Fl::box_shadow_width()) static void fl_oval_flat_box(int x, int y, int w, int h, Fl_Color c) { Fl::set_box_color(c); fl_pie(x, y, w, h, 0, 360); } static void fl_oval_frame(int x, int y, int w, int h, Fl_Color c) { Fl::set_box_color(c); fl_arc(x, y, w, h, 0, 360); } static void fl_oval_box(int x, int y, int w, int h, Fl_Color c) { fl_oval_flat_box(x,y,w,h,c); fl_oval_frame(x,y,w,h,FL_BLACK); } static void fl_oval_shadow_box(int x, int y, int w, int h, Fl_Color c) { fl_oval_flat_box(x+BW,y+BW,w,h,FL_DARK3); fl_oval_box(x,y,w,h,c); } void fl_oval_focus(Fl_Boxtype bt, int x, int y, int w, int h, Fl_Color fg, Fl_Color bg) { x += Fl::box_dx(bt)+1; y += Fl::box_dy(bt)+1; w -= Fl::box_dw(bt)+2; h -= Fl::box_dh(bt)+2; Fl_Color savecolor = fl_color(); fl_color(fl_contrast(fg, bg)); fl_line_style(FL_DOT); fl_arc(x, y, w, h, 0, 360); fl_line_style(FL_SOLID); fl_color(savecolor); } extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*, Fl_Box_Draw_Focus_F* =NULL); Fl_Boxtype fl_define_FL_OVAL_BOX() { fl_internal_boxtype(_FL_OSHADOW_BOX, fl_oval_shadow_box, fl_oval_focus); fl_internal_boxtype(_FL_OVAL_FRAME, fl_oval_frame, fl_oval_focus); fl_internal_boxtype(_FL_OFLAT_BOX, fl_oval_flat_box, fl_oval_focus); fl_internal_boxtype(_FL_OVAL_BOX, fl_oval_box, fl_oval_focus); return _FL_OVAL_BOX; } fltk-1.4.3/src/fl_contrast.cxx0000644000175000017500000004546515004135251016454 0ustar albrechtalbrecht// // Color contrast functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file fl_contrast.cxx \brief Color contrast handling Implementation of fl_contrast() and its variants. */ #include #include #ifndef DEBUG_CONTRAST_LEGACY #define DEBUG_CONTRAST_LEGACY 0 #endif // DEBUG_CONTRAST_LEGACY // Initial values of global/static variables defined by fl_contrast_* functions. // This defines the default contrast mode since FLTK 1.4.0 static int fl_contrast_mode_ = FL_CONTRAST_CIELAB; // This defines the default contrast level per contrast mode static int fl_contrast_level_[10] = { 0, // 0 = FL_CONTRAST_NONE 50, // 1 = FL_CONTRAST_LEGACY 39, // 2 = FL_CONTRAST_CIELAB 0, // 3 = FL_CONTRAST_CUSTOM 0 // 4-9 = not yet defined }; // There is no default custom contrast function static Fl_Contrast_Function *fl_contrast_function_ = 0; // The following function is (and must be!) the same as Fl::get_color() but // can be inlined. We need this additional implementation because all contrast // related functions have been moved from fl_color.cxx to fl_contrast.cxx // or have been directly implemented in fl_contrast.cxx (new functions). // Inlining will hopefully prevent an extra function call. extern unsigned fl_cmap[256]; // defined in fl_color.cxx inline unsigned get_color(Fl_Color i) { // see Fl::get_color() ! if (i & 0xffffff00) return (i); else return fl_cmap[i]; } /** \addtogroup fl_attributes \{ */ /** Return the raw / physical luminance of a color. This function calculates the physical luminance of Fl_Color \p color. The returned luminance value (aka \p Y) is the physical luminance of the Fl_Color \p color. The result is in the range 0.0 (black) to 1.0 (white). \note This is probably not what you want if you are interested in perceived contrast or lightness calculation because the luminance \p Y is \b not linear with respect to human perception. See fl_lightness(Fl_Color) for a function that returns the perceived lightness of a color which can be used directly for contrast calculation. \param[in] color Fl_Color value \return Raw (physical) luminance (0.0 .. 1.0) \since 1.4.0 \see fl_lightness(Fl_Color) */ double fl_luminance(Fl_Color color) { // Get the sRGB (0xrrggbb) components of the FLTK color unsigned col = get_color(color) >> 8; int r = (col & 0xFF0000) >> 16; int g = (col & 0x00FF00) >> 8; int b = (col & 0x0000FF); return (0.2126729 * pow(r/255.0, 2.4) + 0.7151522 * pow(g/255.0, 2.4) + 0.0721750 * pow(b/255.0, 2.4)); } /** Return the perceived lightness of a color. This function calculates the perceived lightness of Fl_Color \p color. The returned lightness value \p Lstar according to the CIELAB (L*a*b*) color model is almost linear with respect to human perception. It is in the range 0 (black) to 100 (white). The result values of two colors can be compared directly and the difference is their perceived contrast. \param[in] color Fl_Color value \return perceived lightness (0 .. 100) \since 1.4.0 */ double fl_lightness(Fl_Color color) { // compute the raw luminance Y (0.0 .. 1.0) double Y = fl_luminance(color); // return the perceived lightness L* (Lstar) if (Y <= (216/24389.)) return Y * (24389/27.); else return pow(Y, (1/3.)) * 116 - 16; } /** Set the contrast level (sensitivity) of the fl_contrast() method. This can be used to tune the legacy fl_contrast() function to achieve slightly better results. The default value is defined per contrast mode (see below). Values between 50 and 70 may be useful for the legacy contrast mode but you can raise it up to 100. Lower values than 50 are probably not useful. The contrast \p level affects not only the legacy (1.3.x) fl_contrast() function but also the new CIELAB contrast mode which is the default since FLTK 1.4.0. See default value below. Other contrast modes are currently not affected by the contrast level. You may use the contrast level if you define your own custom contrast function in mode FL_CONTRAST_CUSTOM. \note All contrast modes store their own contrast level because the behavior is slightly different. You must change the contrast mode fl_contrast_mode() \b before you set or get the contrast level. The default contrast level is - 50 in mode FL_CONTRAST_LEGACY (compatible with FLTK 1.3.x) - 39 in mode FL_CONTRAST_CIELAB (similar threshold as in FLTK 1.3.x) - 0 (undefined) for all other modes See the description of fl_contrast_mode(int mode) for more information about the contrast level per mode. Example: \code fl_contrast_mode(FL_CONTRAST_LEGACY); fl_contrast_level(60); \endcode A \p level greater than 50 (probably best in the range 50 to 70) may achieve better results of the legacy fl_contrast() function in some border cases of low contrast between foreground and background colors but we recommend to use the new default algorithm \c FL_CONTRAST_CIELAB unless you need strict backwards compatibility or use a CPU constrained embedded system. \param[in] level valid range is 0 to 100 \since 1.4.0 */ void fl_contrast_level(int level) { if (level < 0) level = 0; else if (level > 100) level = 100; fl_contrast_level_[fl_contrast_mode_] = level; } /** Get the contrast level (sensitivity) of the fl_contrast() method. This returns the level of the currently selected contrast mode. \return The current contrast level. \see fl_contrast_level(int level) \see fl_contrast_mode(int mode) \since 1.4.0 */ int fl_contrast_level() { return fl_contrast_level_[fl_contrast_mode_]; } /** Set the contrast algorithm (mode). You can use one of - FL_CONTRAST_NONE (not recommended: returns the foreground color) - FL_CONTRAST_LEGACY (same as in FLTK 1.3.x) - FL_CONTRAST_CIELAB (better, this is the default since FLTK 1.4.0) - FL_CONTRAST_CUSTOM (you must define your own contrast algorithm) If you set FL_CONTRAST_CUSTOM you must also register your custom contrast function by calling fl_contrast_function(). You may set the contrast level fl_contrast_level(int) after setting the contrast mode. This affects the contrast algorithm as described below: - FL_CONTRAST_LEGACY: default level is 50 which is compatible with FLTK 1.3.x and older. This mode is no longer the default and is not recommended because it doesn't take human contrast perception into account and doesn't properly handle sRGB color values. You may get better contrasts if you set the level higher than 50. Values in the range 50 to 70 may be useful. Higher values result in higher contrast, i.e. the algorithm switches "earlier" to black or white mode. - FL_CONTRAST_CIELAB: defaut level is 39 which appears to be a good value. The higher the level is, the more contrast is to be expected. Values in the range below 39 accept lower contrast and values above 39 switch "earlier" to black or white. Values between 36 and 46 may yield usable contrast experience. \note The goal of fl_contrast() is to achieve a "sufficient" contrast between text and background. Level 39 in CIELAB mode means that the accepted contrast is about 39% of the lightness difference between both colors. This can be perceived as very low contrast in some cases, but the text should at least be readable. Note that the highest possible contrast value on a medium gray background is 50% (either black or white). Bill Spitzak wrote on May 16, 2024 in fltk.general in thread "FLTK 1.4 Menu Bar Style": "I would certainly aim for a function that does not alter color combinations where it is physically possible to read the text, even if squinting is needed."\n See https://groups.google.com/g/fltkgeneral/c/EkWI4HTHSLA/m/rsZunZ1vAwAJ \param[in] mode if invalid, FL_CONTRAST_CIELAB will be selected \since 1.4.0 \see fl_contrast_function(Fl_Contrast_Function *) \see fl_contrast_level(int) */ void fl_contrast_mode(int mode) { if (mode >= 0 && mode < FL_CONTRAST_LAST) fl_contrast_mode_ = mode; else fl_contrast_mode_ = FL_CONTRAST_CIELAB; } /** Return the current contrast algorithm (mode). \return Contrast algorithm (mode). \since 1.4.0 \see fl_contrast_mode(int) */ int fl_contrast_mode() { return fl_contrast_mode_; } /** Register a custom contrast function. Your custom contrast function will be called when fl_contrast() is called if and only if you previously registered your function and called fl_contrast_mode(FL_CONTRAST_CUSTOM) . Your custom contrast function must provide the signature \code Fl_Color my_contrast_function(Fl_Color fg, Fl_Color bg, int context, int size) \endcode The arguments are the same as for the full fl_contrast() function since FLTK 1.4. You can use the supplied \p size to modify the result. Depending on the caller the \p size parameter can be 0 (default) or a valid size. In the context of text, i.e. \p context == 0, the \p size parameter is the fontsize. The \p context parameter is not yet used and will always be 0 unless included in a call to fl_contrast(). The value 0 must be interpreted as text. In the future the \p context argument will be used to supply a different context than text (small icons, large icons, etc.). The exact usage is not yet specified. Your function may also use fl_contrast_level() to modify the result accordingly. \since 1.4.0 \see fl_contrast_mode(int) \see fl_contrast_level(int) \see fl_contrast() */ void fl_contrast_function(Fl_Contrast_Function *f) { fl_contrast_function_ = f; } /* Returns a color that contrasts with the background color. This is functionally identical to the algorithm used in FLTK 1.3.x, modified only to utilize fl_contrast_level() (since 1.4.0). *** This function is intentionally not public and not documented. *** Do not change this except for level adjustment (backwards compatibility). Note: this is fast but *inaccurate* WRT human contrast perception. The default since FLTK 1.4 is to use fl_contrast_cielab(). \param[in] fg,bg foreground and background colors \param[in] fs,context fontsize and context (unused) \return contrasting color */ static Fl_Color fl_contrast_legacy(Fl_Color fg, Fl_Color bg, int context, int size) { (void) context; // currently ignored (void) size; // currently ignored // internal static variables, recalculated only if fl_contrast_level() is changed static int level = 50; // default, compatible with FLTK 1.3.x static int tc = 99; // sufficient contrast threshold (99 <=> 38.82 %) static int tbw = 127; // black/white threshold (127 <=> 49.80 %) // new in FLTK 1.4: adjust thresholds if fl_contrast_level() was changed if (fl_contrast_level() != level) { level = fl_contrast_level(); if (level == 100) tc = 256; else if (level == 0) tc = 0; else if (level > 50) tc = 99 + ((level - 50) * (255 - 99) / 50); else tc = 99 - ((50 - level) * 99 / 50); } // Get the real sRGB values for each color... unsigned cfg = get_color(fg); unsigned cbg = get_color(bg); // Compute the luminance for each color (0 .. 255) // Note: FLTK 1.3 compatible, don't change this! int lfg = ((cfg >> 24) * 30 + ((cfg >> 16) & 255) * 59 + ((cfg >> 8) & 255) * 11) / 100; int lbg = ((cbg >> 24) * 30 + ((cbg >> 16) & 255) * 59 + ((cbg >> 8) & 255) * 11) / 100; int lc = lfg - lbg; // calculated contrast (-255 .. 255) #if DEBUG_CONTRAST_LEGACY const char *rv = "?"; // return value as text (init) if (lc > tc || lc < -tc) rv = "fg"; // sufficient contrast else if (lbg > tbw) rv = "BLACK"; // light background else rv = "WHITE"; // dark background printf("fl_contrast_legacy: lfg %4d (%7.2f) lbg %4d (%7.2f) lc %4d (%7.2f) => %s\n", lfg, lfg/255.*100, lbg, lbg/255.*100, lc, lc/255.*100, rv); #endif // DEBUG_CONTRAST_LEGACY // Compare and return the contrasting color... if (lc > tc || lc < -tc) return fg; // sufficient contrast if (lbg > tbw) return FL_BLACK; // light background return FL_WHITE; // dark background } /* Returns a color that contrasts with the background color. ** This function is intentionally not public and not documented. ** This is an improved algorithm compared to the one used in FLTK 1.3.x. It is slower (uses floating point and pow()) but is much more accurate WRT human contrast perception. \param[in] fg,bg foreground and background colors \param[in] fs,context unused: fontsize and context \return contrasting color */ static Fl_Color fl_contrast_cielab(Fl_Color fg, Fl_Color bg, int context, int size) { (void) context; // currently ignored (void) size; // currently ignored double tc = (double)fl_contrast_level(); // sufficient contrast threshold double tbw = 50.; // black/white threshold // Compute the perceived lightness L* (Lstar) and the contrast double lfg = fl_lightness(fg); double lbg = fl_lightness(bg); double lc = lfg - lbg; // Compare and return the contrasting color... if (lc >= tc || lc <= -tc) return fg; // sufficient contrast if (lbg > tbw) return (Fl_Color)FL_BLACK; // black return (Fl_Color)FL_WHITE; // white } /** Returns a color that contrasts with the background color. This will be the foreground color if it contrasts sufficiently with the background color. Otherwise, returns \p FL_WHITE or \p FL_BLACK depending on which color provides the best contrast. FLTK 1.4.0 uses a different default contrast function than earlier releases (1.3.x) but you can use the old "legacy" contrast function by calling \code fl_contrast_mode(FL_CONTRAST_LEGACY); \endcode early in your main program. \note It is a known issue that static initialization using fl_contrast() may already have been executed before you call this function in main(). You should be aware of this and, if necessary, write your own (static) contrast initialization function. This should rarely be necessary. You can change the behavior of fl_contrast() in several ways: - Change the "level" (sensitivity) for contrast calculation, see fl_contrast_level(). Valid levels are 0 - 100, the default "medium" value depends on the contrast mode. If you raise the level above the default value the overall contrast will generally be higher, i.e. the required contrast to return the foreground color is raised and therefore the calculated color switches "earlier" to either black or white. In other words, using the following values: - 0 always uses the foreground color - the default, unmodified algorithm allows a sufficient contrast such that the text is readable - 100 will always use black or white Changing the \p level is particularly useful and intended for the "legacy mode" to improve the results partially. Values slightly above 50 (50 - 70) will likely return the best results (50 is the default, as used in FLTK 1.3.x). \note Different contrast modes (algorithms) can use their own values and defaults of fl_contrast_level(). - Change the used contrast calculation function. You can either use the old (FLTK 1.3.x) function or use the better but slower function based on the CIELAB (L*a*b*) color model, or you can define your own custom contrast function if you need even better contrast results. The following contrast functions are available: - FL_CONTRAST_LEGACY, the old FLTK 1.3.x compatible function. This is the fastest function (using integer arithmetic) but it provides worse results in border cases. You may want to use this on embedded or otherwise CPU constrained systems or if you need strict backwards compatibility. For slightly better results you may utilize the new fl_contrast_level(int) function (since 1.4.0) to increase the contrast sensitivity. This will provide slightly better results than FLTK 1.3.x and earlier but we recommend to use the new default function: - FL_CONTRAST_CIELAB, based on the CIELAB (L*a*b*) color model. This function is superior regarding the human contrast perception but may be slightly slower - which should not matter on a modern CPU. The default contrast level in this mode is 39 which results in a very similar experience as the old contrast function but avoids unreadable border cases. This is the default since FLTK 1.4.0. - FL_CONTRAST_CUSTOM, your own contrast calculation function. In the future we \b may provide even more (and superior) contrast algorithms. The new parameters \p context and \p size (since 1.4.0) are defined for future extensions and are currently not used. Default values are 0. - The \p context is intended to differentiate text and other kinds of objects, e.g. radio buttons, check marks, or icon types. - The \p size parameter is an unspecified (object) size that may be used to calculate the required contrast. In text mode this must be the font size. Rule: the larger the object (font), the lower the required contrast. \note These new optional parameters must be provided in the custom contrast function which is the reason why they are added now. In the future we may use the (font) size to adjust the calculated contrast, and users defining their own contrast functions may use them in their functions. \param[in] fg foreground (text) color \param[in] bg background color \param[in] context graphical context (optional, default = 0 == text) \param[in] size unspecified size (optional, default = 0 == undefined) \return contrasting color: \p fg, \p FL_BLACK, or \p FL_WHITE \see fl_contrast_level(int) \see fl_contrast_mode(int) \see fl_contrast_function() */ Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg, int context, int size) { switch (fl_contrast_mode_) { case FL_CONTRAST_LEGACY: return fl_contrast_legacy(fg, bg, context, size); case FL_CONTRAST_CUSTOM: if (fl_contrast_function_) return (fl_contrast_function_)(fg, bg, context, size); // FALLTHROUGH case FL_CONTRAST_CIELAB: return fl_contrast_cielab(fg, bg, context, size); default: // unknown (none): return fg break; } return fg; } // fl_contrast() /** \} */ fltk-1.4.3/src/xutf8/0000755000175000017500000000000015004135251014452 5ustar albrechtalbrechtfltk-1.4.3/src/xutf8/test2.c0000644000175000017500000001522115004135251015660 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * UTF-8 X test program * ***************** * To test it do : ***************** kinput2 -canna XMODIFIERS="@im=kinput2"; export XMODIFIERS LANG=ja_JP; export LANG ./test to open a conversion window press "Shift space" type some keys. press space. select glyph with arrows keys. press return. press return. press "Shift space" to close the window LANG=ar_AE; export LANG LANG=he_IL; export LANG export LANG=ja_JP; export XMODIFIERS="@im=kinput2" export LANG=ja_JP; export XMODIFIERS="@im=nicolatter" export LANG=ja_JP; export XMODIFIERS="@im=jmode" export LANG=ja_JP; export XMODIFIERS="@im=htt" export LANG=ko_KR; export XMODIFIERS="@im=ami" export LANG=zh_TW; export XMODIFIERS="@im=xcin-zh_TW" export LANG=zh_TW; export XMODIFIERS="@im=xcin-zh_CN" export LANG=fr_FR.UTF-8; export XMODIFIERS="@im=interxim" export LD_PRELOAD="/usr/src/x11/xc/exports/lib/libX11.so /usr/src/x11/xc/exports/lib/libxlcDef.so.2 /usr/src/x11/xc/exports/lib/libxlibi18n.so.2 /usr/src/x11/xc/exports/lib/libxlocale.so.2 /usr/src/x11/xc/exports/lib/libxomGeneric.so.2 /usr/src/x11/xc/exports/lib/libximcp.so.2" */ #include #include #include #include #include #include #include #include #include #include char *jp_txt = "é UTF-8 e\xCC\x82=\xC3\xAA" " \357\274\270\357\274\254\357\274\246\357\274" "\244\345\220\215\343\201\247\346\214\207 \345\256\232" "\343\201\231\343\202\213"; char *rtl_txt = "->e\xCC\x82=\xC3\xAA"; XIM xim_im = NULL; XIC xim_ic = NULL; static XIMStyles* xim_styles = NULL; XFontSet fontset; GC gc; int x = 2; int y = 40; int main(int argc, char**argv) { char **missing_charset_list; int missing_charset_count; XGCValues xgcv; unsigned long mask; Display* dpy; int scr; Window w, root; XSetWindowAttributes set_attr; int i; XIMStyle *style; static char buf[128]; KeySym keysym = 0; Status status; XWMHints wm_hints; XClassHint class_hints; XIMStyle input_style = 0; char **font_name_list; char *def_string; XFontStruct **font_struct_list; char **font_encoding_list; int nb_font; int len = 0; int no_xim = 0; char **missing_charset_list_return; int missing_charset_count_return; char *def_string_return; if (!setlocale(LC_ALL, "")) puts("locale not supported by C library, locale unchanged"); if (!XSetLocaleModifiers("")) puts("X locale modifiers not supported, using default"); dpy = XOpenDisplay(0); scr = DefaultScreen(dpy); root = RootWindow(dpy, scr); set_attr.event_mask = KeyPressMask|FocusChangeMask; set_attr.background_pixel = WhitePixel(dpy, DefaultScreen(dpy)); set_attr.border_pixel = BlackPixel(dpy, DefaultScreen(dpy)); w = XCreateWindow(dpy, root, 10,10,200,100,0, DefaultDepth(dpy, DefaultScreen(dpy)), InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)), CWEventMask | CWBackPixel | CWBorderPixel, &set_attr); class_hints.res_name = "test"; class_hints.res_class = "Test"; wm_hints.input = True; wm_hints.flags = InputHint; XmbSetWMProperties(dpy, w, "test", "test", NULL, 0, NULL, &wm_hints, &class_hints); XMapWindow(dpy, w); xim_im = XOpenIM(dpy, NULL, "test", "Test"); XGetIMValues(xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL); for (i = 0, style = xim_styles->supported_styles; i < xim_styles->count_styles; i++, style++) { if (*style == (XIMStatusNone|XIMPreeditNone)) { printf("this is not a XIM server !!!\n"); no_xim = 1; } printf("input style : 0x%X\n", *style); } XFree(xim_styles); xim_ic = XCreateIC(xim_im, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, w, XNFocusWindow, w, NULL); XSetICFocus(xim_ic); /*************************************************************** * I don't recommend to use a font base name list similar * to the following one in a real application ;-) ***************************************************************/ fontset = XCreateFontSet(dpy, "-*-*-*-*-*-*-*-*-*-*-*-*-iso8858-3," /* not valid */ "-*-*-medium-r-*-*-*-*-*-*-*-*-iso8859-1," "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-6," "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-8," "-*-symbol-*-*-*-*-*-*-*-*-*-*-adobe-fontspecific," "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-2," "-*-*-*-*-*-*-*-*-*-*-*-*-koi8-1," "-*-*-*-*-*-*-*-*-*-*-*-*-jisx0208.1983-0," "-*-*-*-*-*-*-*-*-*-*-*-*-jisx0212.1990-0," "-*-*-*-*-*-*-*-*-*-*-*-*-big5-0," "-*-*-*-*-*-*-*-*-*-*-*-*-jisx0201.1976-0," "-*-unifont-*-*-*-*-*-*-*-*-*-*-iso10646-1[0x300 0x400_0x500]," "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", &missing_charset_list_return, &missing_charset_count_return, &def_string_return); mask = (GCForeground | GCBackground); xgcv.foreground = BlackPixel(dpy, DefaultScreen(dpy)); xgcv.background = WhitePixel(dpy, DefaultScreen(dpy)); gc = XCreateGC(dpy, w, mask, &xgcv); /***************************************************************/ while (1) { int filtered; static XEvent xevent; static XVaNestedList list1 = 0; int r; XNextEvent(dpy, &xevent); if (xevent.type == KeyPress) { XKeyEvent *e = (XKeyEvent*) &xevent; printf ("0x%X %d\n", e->state, e->keycode); } filtered = XFilterEvent(&xevent, w); if (xevent.type == FocusOut) XUnsetICFocus(xim_ic); if (xevent.type == FocusIn) XSetICFocus(xim_ic); if (xevent.type == KeyPress && !filtered) { len = Xutf8LookupString(xim_ic, &xevent.xkey, buf, 127, &keysym, &status); Xutf8DrawImageString(dpy, w, fontset, gc, x, y, buf, len); Xutf8DrawString(dpy, w, fontset, gc, 0, 20, jp_txt, strlen(jp_txt)); Xutf8DrawString(dpy, w, fontset, gc, 50, 90, rtl_txt, strlen(rtl_txt)); buf[len] = 0; printf("'%s' %d\n", buf, keysym); buf[0] = 0; XCloseIM(xim_im); } if (filtered) { printf("Dead key\n"); } } XFreeFontSet(dpy, fontset); return 0; } fltk-1.4.3/src/xutf8/headers/0000755000175000017500000000000015004135251016065 5ustar albrechtalbrechtfltk-1.4.3/src/xutf8/headers/case.h0000644000175000017500000005225015004135251017155 0ustar albrechtalbrecht/* spacing */ static const unsigned short ucs_table_0041[] = { /* U+0041 */ 0x0061, /* U+0042 */ 0x0062, /* U+0043 */ 0x0063, /* U+0044 */ 0x0064, /* U+0045 */ 0x0065, /* U+0046 */ 0x0066, /* U+0047 */ 0x0067, /* U+0048 */ 0x0068, /* U+0049 */ 0x0069, /* U+004A */ 0x006A, /* U+004B */ 0x006B, /* U+004C */ 0x006C, /* U+004D */ 0x006D, /* U+004E */ 0x006E, /* U+004F */ 0x006F, /* U+0050 */ 0x0070, /* U+0051 */ 0x0071, /* U+0052 */ 0x0072, /* U+0053 */ 0x0073, /* U+0054 */ 0x0074, /* U+0055 */ 0x0075, /* U+0056 */ 0x0076, /* U+0057 */ 0x0077, /* U+0058 */ 0x0078, /* U+0059 */ 0x0079, /* U+005A */ 0x007A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+00C0 */ 0x00E0, /* U+00C1 */ 0x00E1, /* U+00C2 */ 0x00E2, /* U+00C3 */ 0x00E3, /* U+00C4 */ 0x00E4, /* U+00C5 */ 0x00E5, /* U+00C6 */ 0x00E6, /* U+00C7 */ 0x00E7, /* U+00C8 */ 0x00E8, /* U+00C9 */ 0x00E9, /* U+00CA */ 0x00EA, /* U+00CB */ 0x00EB, /* U+00CC */ 0x00EC, /* U+00CD */ 0x00ED, /* U+00CE */ 0x00EE, /* U+00CF */ 0x00EF, /* U+00D0 */ 0x00F0, /* U+00D1 */ 0x00F1, /* U+00D2 */ 0x00F2, /* U+00D3 */ 0x00F3, /* U+00D4 */ 0x00F4, /* U+00D5 */ 0x00F5, /* U+00D6 */ 0x00F6, 0x00, /* U+00D8 */ 0x00F8, /* U+00D9 */ 0x00F9, /* U+00DA */ 0x00FA, /* U+00DB */ 0x00FB, /* U+00DC */ 0x00FC, /* U+00DD */ 0x00FD, /* U+00DE */ 0x00FE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0100 */ 0x0101, 0x00, /* U+0102 */ 0x0103, 0x00, /* U+0104 */ 0x0105, 0x00, /* U+0106 */ 0x0107, 0x00, /* U+0108 */ 0x0109, 0x00, /* U+010A */ 0x010B, 0x00, /* U+010C */ 0x010D, 0x00, /* U+010E */ 0x010F, 0x00, /* U+0110 */ 0x0111, 0x00, /* U+0112 */ 0x0113, 0x00, /* U+0114 */ 0x0115, 0x00, /* U+0116 */ 0x0117, 0x00, /* U+0118 */ 0x0119, 0x00, /* U+011A */ 0x011B, 0x00, /* U+011C */ 0x011D, 0x00, /* U+011E */ 0x011F, 0x00, /* U+0120 */ 0x0121, 0x00, /* U+0122 */ 0x0123, 0x00, /* U+0124 */ 0x0125, 0x00, /* U+0126 */ 0x0127, 0x00, /* U+0128 */ 0x0129, 0x00, /* U+012A */ 0x012B, 0x00, /* U+012C */ 0x012D, 0x00, /* U+012E */ 0x012F, 0x00, /* U+0130 */ 0x0, 0x00, /* U+0132 */ 0x0133, 0x00, /* U+0134 */ 0x0135, 0x00, /* U+0136 */ 0x0137, 0x00, 0x00, /* U+0139 */ 0x013A, 0x00, /* U+013B */ 0x013C, 0x00, /* U+013D */ 0x013E, 0x00, /* U+013F */ 0x0140, 0x00, /* U+0141 */ 0x0142, 0x00, /* U+0143 */ 0x0144, 0x00, /* U+0145 */ 0x0146, 0x00, /* U+0147 */ 0x0148, 0x00, 0x00, /* U+014A */ 0x014B, 0x00, /* U+014C */ 0x014D, 0x00, /* U+014E */ 0x014F, 0x00, /* U+0150 */ 0x0151, 0x00, /* U+0152 */ 0x0153, 0x00, /* U+0154 */ 0x0155, 0x00, /* U+0156 */ 0x0157, 0x00, /* U+0158 */ 0x0159, 0x00, /* U+015A */ 0x015B, 0x00, /* U+015C */ 0x015D, 0x00, /* U+015E */ 0x015F, 0x00, /* U+0160 */ 0x0161, 0x00, /* U+0162 */ 0x0163, 0x00, /* U+0164 */ 0x0165, 0x00, /* U+0166 */ 0x0167, 0x00, /* U+0168 */ 0x0169, 0x00, /* U+016A */ 0x016B, 0x00, /* U+016C */ 0x016D, 0x00, /* U+016E */ 0x016F, 0x00, /* U+0170 */ 0x0171, 0x00, /* U+0172 */ 0x0173, 0x00, /* U+0174 */ 0x0175, 0x00, /* U+0176 */ 0x0177, 0x00, /* U+0178 */ 0x00FF, /* U+0179 */ 0x017A, 0x00, /* U+017B */ 0x017C, 0x00, /* U+017D */ 0x017E, 0x00, 0x00, 0x00, /* U+0181 */ 0x0253, /* U+0182 */ 0x0183, 0x00, /* U+0184 */ 0x0185, 0x00, /* U+0186 */ 0x0254, /* U+0187 */ 0x0188, 0x00, /* U+0189 */ 0x0, /* U+018A */ 0x0257, /* U+018B */ 0x018C, 0x00, 0x00, /* U+018E */ 0x0258, /* U+018F */ 0x0259, /* U+0190 */ 0x025B, /* U+0191 */ 0x0192, 0x00, /* U+0193 */ 0x0260, /* U+0194 */ 0x0263, 0x00, /* U+0196 */ 0x0269, /* U+0197 */ 0x0268, /* U+0198 */ 0x0199, 0x00, 0x00, 0x00, /* U+019C */ 0x026F, /* U+019D */ 0x0272, 0x00, /* U+019F */ 0x0, /* U+01A0 */ 0x01A1, 0x00, /* U+01A2 */ 0x01A3, 0x00, /* U+01A4 */ 0x01A5, 0x00, 0x00, /* U+01A7 */ 0x01A8, 0x00, /* U+01A9 */ 0x0283, 0x00, 0x00, /* U+01AC */ 0x01AD, 0x00, /* U+01AE */ 0x0288, /* U+01AF */ 0x01B0, 0x00, /* U+01B1 */ 0x028A, /* U+01B2 */ 0x028B, /* U+01B3 */ 0x01B4, 0x00, /* U+01B5 */ 0x01B6, 0x00, /* U+01B7 */ 0x0292, /* U+01B8 */ 0x01B9, 0x00, 0x00, 0x00, /* U+01BC */ 0x01BD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+01C4 */ 0x01C6, /* U+01C5 */ 0x0, 0x00, /* U+01C7 */ 0x01C9, /* U+01C8 */ 0x0, 0x00, /* U+01CA */ 0x01CC, /* U+01CB */ 0x0, 0x00, /* U+01CD */ 0x01CE, 0x00, /* U+01CF */ 0x01D0, 0x00, /* U+01D1 */ 0x01D2, 0x00, /* U+01D3 */ 0x01D4, 0x00, /* U+01D5 */ 0x01D6, 0x00, /* U+01D7 */ 0x01D8, 0x00, /* U+01D9 */ 0x01DA, 0x00, /* U+01DB */ 0x01DC, 0x00, 0x00, /* U+01DE */ 0x01DF, 0x00, /* U+01E0 */ 0x01E1, 0x00, /* U+01E2 */ 0x01E3, 0x00, /* U+01E4 */ 0x01E5, 0x00, /* U+01E6 */ 0x01E7, 0x00, /* U+01E8 */ 0x01E9, 0x00, /* U+01EA */ 0x01EB, 0x00, /* U+01EC */ 0x01ED, 0x00, /* U+01EE */ 0x01EF, 0x00, 0x00, /* U+01F1 */ 0x01F3, /* U+01F2 */ 0x0, 0x00, /* U+01F4 */ 0x01F5, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+01FA */ 0x01FB, 0x00, /* U+01FC */ 0x01FD, 0x00, /* U+01FE */ 0x01FF, 0x00, /* U+0200 */ 0x0201, 0x00, /* U+0202 */ 0x0203, 0x00, /* U+0204 */ 0x0205, 0x00, /* U+0206 */ 0x0207, 0x00, /* U+0208 */ 0x0209, 0x00, /* U+020A */ 0x020B, 0x00, /* U+020C */ 0x020D, 0x00, /* U+020E */ 0x020F, 0x00, /* U+0210 */ 0x0211, 0x00, /* U+0212 */ 0x0213, 0x00, /* U+0214 */ 0x0215, 0x00, /* U+0216 */ 0x0217, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0262 */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+026A */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0274 */ 0x0, 0x00, /* U+0276 */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0280 */ 0x0, /* U+0281 */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+028F */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0299 */ 0x0, 0x00, /* U+029B */ 0x0, /* U+029C */ 0x0, 0x00, 0x00, /* U+029F */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+02B6 */ 0x0, }; static const unsigned short ucs_table_0386[] = { /* U+0386 */ 0x03AC, 0x00, /* U+0388 */ 0x03AD, /* U+0389 */ 0x03AE, /* U+038A */ 0x03AF, 0x00, /* U+038C */ 0x03CC, 0x00, /* U+038E */ 0x03CD, /* U+038F */ 0x03CE, 0x00, /* U+0391 */ 0x03B1, /* U+0392 */ 0x03B2, /* U+0393 */ 0x03B3, /* U+0394 */ 0x03B4, /* U+0395 */ 0x03B5, /* U+0396 */ 0x03B6, /* U+0397 */ 0x03B7, /* U+0398 */ 0x03B8, /* U+0399 */ 0x03B9, /* U+039A */ 0x03BA, /* U+039B */ 0x03BB, /* U+039C */ 0x03BC, /* U+039D */ 0x03BD, /* U+039E */ 0x03BE, /* U+039F */ 0x03BF, /* U+03A0 */ 0x03C0, /* U+03A1 */ 0x03C1, 0x00, /* U+03A3 */ 0x03C3, /* U+03A4 */ 0x03C4, /* U+03A5 */ 0x03C5, /* U+03A6 */ 0x03C6, /* U+03A7 */ 0x03C7, /* U+03A8 */ 0x03C8, /* U+03A9 */ 0x03C9, /* U+03AA */ 0x03CA, /* U+03AB */ 0x03CB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+03D2 */ 0x03D2, /* U+03D3 */ 0x03D3, /* U+03D4 */ 0x03D4, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+03DA */ 0x03DA, 0x00, /* U+03DC */ 0x03DC, 0x00, /* U+03DE */ 0x03DE, 0x00, /* U+03E0 */ 0x03E0, 0x00, /* U+03E2 */ 0x03E3, 0x00, /* U+03E4 */ 0x03E5, 0x00, /* U+03E6 */ 0x03E7, 0x00, /* U+03E8 */ 0x03E9, 0x00, /* U+03EA */ 0x03EB, 0x00, /* U+03EC */ 0x03ED, 0x00, /* U+03EE */ 0x03EF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0401 */ 0x0451, /* U+0402 */ 0x0452, /* U+0403 */ 0x0453, /* U+0404 */ 0x0454, /* U+0405 */ 0x0455, /* U+0406 */ 0x0456, /* U+0407 */ 0x0457, /* U+0408 */ 0x0458, /* U+0409 */ 0x0459, /* U+040A */ 0x045A, /* U+040B */ 0x045B, /* U+040C */ 0x045C, 0x00, /* U+040E */ 0x045E, /* U+040F */ 0x045F, /* U+0410 */ 0x0430, /* U+0411 */ 0x0431, /* U+0412 */ 0x0432, /* U+0413 */ 0x0433, /* U+0414 */ 0x0434, /* U+0415 */ 0x0435, /* U+0416 */ 0x0436, /* U+0417 */ 0x0437, /* U+0418 */ 0x0438, /* U+0419 */ 0x0439, /* U+041A */ 0x043A, /* U+041B */ 0x043B, /* U+041C */ 0x043C, /* U+041D */ 0x043D, /* U+041E */ 0x043E, /* U+041F */ 0x043F, /* U+0420 */ 0x0440, /* U+0421 */ 0x0441, /* U+0422 */ 0x0442, /* U+0423 */ 0x0443, /* U+0424 */ 0x0444, /* U+0425 */ 0x0445, /* U+0426 */ 0x0446, /* U+0427 */ 0x0447, /* U+0428 */ 0x0448, /* U+0429 */ 0x0449, /* U+042A */ 0x044A, /* U+042B */ 0x044B, /* U+042C */ 0x044C, /* U+042D */ 0x044D, /* U+042E */ 0x044E, /* U+042F */ 0x044F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0460 */ 0x0461, 0x00, /* U+0462 */ 0x0463, 0x00, /* U+0464 */ 0x0465, 0x00, /* U+0466 */ 0x0467, 0x00, /* U+0468 */ 0x0469, 0x00, /* U+046A */ 0x046B, 0x00, /* U+046C */ 0x046D, 0x00, /* U+046E */ 0x046F, 0x00, /* U+0470 */ 0x0471, 0x00, /* U+0472 */ 0x0473, 0x00, /* U+0474 */ 0x0475, 0x00, /* U+0476 */ 0x0477, 0x00, /* U+0478 */ 0x0479, 0x00, /* U+047A */ 0x047B, 0x00, /* U+047C */ 0x047D, 0x00, /* U+047E */ 0x047F, 0x00, /* U+0480 */ 0x0481, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0490 */ 0x0491, 0x00, /* U+0492 */ 0x0493, 0x00, /* U+0494 */ 0x0495, 0x00, /* U+0496 */ 0x0497, 0x00, /* U+0498 */ 0x0499, 0x00, /* U+049A */ 0x049B, 0x00, /* U+049C */ 0x049D, 0x00, /* U+049E */ 0x049F, 0x00, /* U+04A0 */ 0x04A1, 0x00, /* U+04A2 */ 0x04A3, 0x00, /* U+04A4 */ 0x04A5, 0x00, /* U+04A6 */ 0x04A7, 0x00, /* U+04A8 */ 0x04A9, 0x00, /* U+04AA */ 0x04AB, 0x00, /* U+04AC */ 0x04AD, 0x00, /* U+04AE */ 0x04AF, 0x00, /* U+04B0 */ 0x04B1, 0x00, /* U+04B2 */ 0x04B3, 0x00, /* U+04B4 */ 0x04B5, 0x00, /* U+04B6 */ 0x04B7, 0x00, /* U+04B8 */ 0x04B9, 0x00, /* U+04BA */ 0x04BB, 0x00, /* U+04BC */ 0x04BD, 0x00, /* U+04BE */ 0x04BF, 0x00, 0x00, /* U+04C1 */ 0x04C2, 0x00, /* U+04C3 */ 0x04C4, 0x00, 0x00, 0x00, /* U+04C7 */ 0x04C8, 0x00, 0x00, 0x00, /* U+04CB */ 0x04CC, 0x00, 0x00, 0x00, 0x00, /* U+04D0 */ 0x04D1, 0x00, /* U+04D2 */ 0x04D3, 0x00, /* U+04D4 */ 0x04D5, 0x00, /* U+04D6 */ 0x04D7, 0x00, /* U+04D8 */ 0x04D9, 0x00, /* U+04DA */ 0x04DB, 0x00, /* U+04DC */ 0x04DD, 0x00, /* U+04DE */ 0x04DF, 0x00, /* U+04E0 */ 0x04E1, 0x00, /* U+04E2 */ 0x04E3, 0x00, /* U+04E4 */ 0x04E5, 0x00, /* U+04E6 */ 0x04E7, 0x00, /* U+04E8 */ 0x04E9, 0x00, /* U+04EA */ 0x04EB, 0x00, 0x00, 0x00, /* U+04EE */ 0x04EF, 0x00, /* U+04F0 */ 0x04F1, 0x00, /* U+04F2 */ 0x04F3, 0x00, /* U+04F4 */ 0x04F5, 0x00, 0x00, 0x00, /* U+04F8 */ 0x04F9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0531 */ 0x0561, /* U+0532 */ 0x0562, /* U+0533 */ 0x0563, /* U+0534 */ 0x0564, /* U+0535 */ 0x0565, /* U+0536 */ 0x0566, /* U+0537 */ 0x0567, /* U+0538 */ 0x0568, /* U+0539 */ 0x0569, /* U+053A */ 0x056A, /* U+053B */ 0x056B, /* U+053C */ 0x056C, /* U+053D */ 0x056D, /* U+053E */ 0x056E, /* U+053F */ 0x056F, /* U+0540 */ 0x0570, /* U+0541 */ 0x0571, /* U+0542 */ 0x0572, /* U+0543 */ 0x0573, /* U+0544 */ 0x0574, /* U+0545 */ 0x0575, /* U+0546 */ 0x0576, /* U+0547 */ 0x0577, /* U+0548 */ 0x0578, /* U+0549 */ 0x0579, /* U+054A */ 0x057A, /* U+054B */ 0x057B, /* U+054C */ 0x057C, /* U+054D */ 0x057D, /* U+054E */ 0x057E, /* U+054F */ 0x057F, /* U+0550 */ 0x0580, /* U+0551 */ 0x0581, /* U+0552 */ 0x0582, /* U+0553 */ 0x0583, /* U+0554 */ 0x0584, /* U+0555 */ 0x0585, /* U+0556 */ 0x0586, }; static const unsigned short ucs_table_10A0[] = { /* U+10A0 */ 0x10D0, /* U+10A1 */ 0x10D1, /* U+10A2 */ 0x10D2, /* U+10A3 */ 0x10D3, /* U+10A4 */ 0x10D4, /* U+10A5 */ 0x10D5, /* U+10A6 */ 0x10D6, /* U+10A7 */ 0x10D7, /* U+10A8 */ 0x10D8, /* U+10A9 */ 0x10D9, /* U+10AA */ 0x10DA, /* U+10AB */ 0x10DB, /* U+10AC */ 0x10DC, /* U+10AD */ 0x10DD, /* U+10AE */ 0x10DE, /* U+10AF */ 0x10DF, /* U+10B0 */ 0x10E0, /* U+10B1 */ 0x10E1, /* U+10B2 */ 0x10E2, /* U+10B3 */ 0x10E3, /* U+10B4 */ 0x10E4, /* U+10B5 */ 0x10E5, /* U+10B6 */ 0x10E6, /* U+10B7 */ 0x10E7, /* U+10B8 */ 0x10E8, /* U+10B9 */ 0x10E9, /* U+10BA */ 0x10EA, /* U+10BB */ 0x10EB, /* U+10BC */ 0x10EC, /* U+10BD */ 0x10ED, /* U+10BE */ 0x10EE, /* U+10BF */ 0x10EF, /* U+10C0 */ 0x10F0, /* U+10C1 */ 0x10F1, /* U+10C2 */ 0x10F2, /* U+10C3 */ 0x10F3, /* U+10C4 */ 0x10F4, /* U+10C5 */ 0x10F5, }; static const unsigned short ucs_table_1E00[] = { /* U+1E00 */ 0x1E01, 0x00, /* U+1E02 */ 0x1E03, 0x00, /* U+1E04 */ 0x1E05, 0x00, /* U+1E06 */ 0x1E07, 0x00, /* U+1E08 */ 0x1E09, 0x00, /* U+1E0A */ 0x1E0B, 0x00, /* U+1E0C */ 0x1E0D, 0x00, /* U+1E0E */ 0x1E0F, 0x00, /* U+1E10 */ 0x1E11, 0x00, /* U+1E12 */ 0x1E13, 0x00, /* U+1E14 */ 0x1E15, 0x00, /* U+1E16 */ 0x1E17, 0x00, /* U+1E18 */ 0x1E19, 0x00, /* U+1E1A */ 0x1E1B, 0x00, /* U+1E1C */ 0x1E1D, 0x00, /* U+1E1E */ 0x1E1F, 0x00, /* U+1E20 */ 0x1E21, 0x00, /* U+1E22 */ 0x1E23, 0x00, /* U+1E24 */ 0x1E25, 0x00, /* U+1E26 */ 0x1E27, 0x00, /* U+1E28 */ 0x1E29, 0x00, /* U+1E2A */ 0x1E2B, 0x00, /* U+1E2C */ 0x1E2D, 0x00, /* U+1E2E */ 0x1E2F, 0x00, /* U+1E30 */ 0x1E31, 0x00, /* U+1E32 */ 0x1E33, 0x00, /* U+1E34 */ 0x1E35, 0x00, /* U+1E36 */ 0x1E37, 0x00, /* U+1E38 */ 0x1E39, 0x00, /* U+1E3A */ 0x1E3B, 0x00, /* U+1E3C */ 0x1E3D, 0x00, /* U+1E3E */ 0x1E3F, 0x00, /* U+1E40 */ 0x1E41, 0x00, /* U+1E42 */ 0x1E43, 0x00, /* U+1E44 */ 0x1E45, 0x00, /* U+1E46 */ 0x1E47, 0x00, /* U+1E48 */ 0x1E49, 0x00, /* U+1E4A */ 0x1E4B, 0x00, /* U+1E4C */ 0x1E4D, 0x00, /* U+1E4E */ 0x1E4F, 0x00, /* U+1E50 */ 0x1E51, 0x00, /* U+1E52 */ 0x1E53, 0x00, /* U+1E54 */ 0x1E55, 0x00, /* U+1E56 */ 0x1E57, 0x00, /* U+1E58 */ 0x1E59, 0x00, /* U+1E5A */ 0x1E5B, 0x00, /* U+1E5C */ 0x1E5D, 0x00, /* U+1E5E */ 0x1E5F, 0x00, /* U+1E60 */ 0x1E61, 0x00, /* U+1E62 */ 0x1E63, 0x00, /* U+1E64 */ 0x1E65, 0x00, /* U+1E66 */ 0x1E67, 0x00, /* U+1E68 */ 0x1E69, 0x00, /* U+1E6A */ 0x1E6B, 0x00, /* U+1E6C */ 0x1E6D, 0x00, /* U+1E6E */ 0x1E6F, 0x00, /* U+1E70 */ 0x1E71, 0x00, /* U+1E72 */ 0x1E73, 0x00, /* U+1E74 */ 0x1E75, 0x00, /* U+1E76 */ 0x1E77, 0x00, /* U+1E78 */ 0x1E79, 0x00, /* U+1E7A */ 0x1E7B, 0x00, /* U+1E7C */ 0x1E7D, 0x00, /* U+1E7E */ 0x1E7F, 0x00, /* U+1E80 */ 0x1E81, 0x00, /* U+1E82 */ 0x1E83, 0x00, /* U+1E84 */ 0x1E85, 0x00, /* U+1E86 */ 0x1E87, 0x00, /* U+1E88 */ 0x1E89, 0x00, /* U+1E8A */ 0x1E8B, 0x00, /* U+1E8C */ 0x1E8D, 0x00, /* U+1E8E */ 0x1E8F, 0x00, /* U+1E90 */ 0x1E91, 0x00, /* U+1E92 */ 0x1E93, 0x00, /* U+1E94 */ 0x1E95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1EA0 */ 0x1EA1, 0x00, /* U+1EA2 */ 0x1EA3, 0x00, /* U+1EA4 */ 0x1EA5, 0x00, /* U+1EA6 */ 0x1EA7, 0x00, /* U+1EA8 */ 0x1EA9, 0x00, /* U+1EAA */ 0x1EAB, 0x00, /* U+1EAC */ 0x1EAD, 0x00, /* U+1EAE */ 0x1EAF, 0x00, /* U+1EB0 */ 0x1EB1, 0x00, /* U+1EB2 */ 0x1EB3, 0x00, /* U+1EB4 */ 0x1EB5, 0x00, /* U+1EB6 */ 0x1EB7, 0x00, /* U+1EB8 */ 0x1EB9, 0x00, /* U+1EBA */ 0x1EBB, 0x00, /* U+1EBC */ 0x1EBD, 0x00, /* U+1EBE */ 0x1EBF, 0x00, /* U+1EC0 */ 0x1EC1, 0x00, /* U+1EC2 */ 0x1EC3, 0x00, /* U+1EC4 */ 0x1EC5, 0x00, /* U+1EC6 */ 0x1EC7, 0x00, /* U+1EC8 */ 0x1EC9, 0x00, /* U+1ECA */ 0x1ECB, 0x00, /* U+1ECC */ 0x1ECD, 0x00, /* U+1ECE */ 0x1ECF, 0x00, /* U+1ED0 */ 0x1ED1, 0x00, /* U+1ED2 */ 0x1ED3, 0x00, /* U+1ED4 */ 0x1ED5, 0x00, /* U+1ED6 */ 0x1ED7, 0x00, /* U+1ED8 */ 0x1ED9, 0x00, /* U+1EDA */ 0x1EDB, 0x00, /* U+1EDC */ 0x1EDD, 0x00, /* U+1EDE */ 0x1EDF, 0x00, /* U+1EE0 */ 0x1EE1, 0x00, /* U+1EE2 */ 0x1EE3, 0x00, /* U+1EE4 */ 0x1EE5, 0x00, /* U+1EE6 */ 0x1EE7, 0x00, /* U+1EE8 */ 0x1EE9, 0x00, /* U+1EEA */ 0x1EEB, 0x00, /* U+1EEC */ 0x1EED, 0x00, /* U+1EEE */ 0x1EEF, 0x00, /* U+1EF0 */ 0x1EF1, 0x00, /* U+1EF2 */ 0x1EF3, 0x00, /* U+1EF4 */ 0x1EF5, 0x00, /* U+1EF6 */ 0x1EF7, 0x00, /* U+1EF8 */ 0x1EF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1F08 */ 0x1F00, /* U+1F09 */ 0x1F01, /* U+1F0A */ 0x1F02, /* U+1F0B */ 0x1F03, /* U+1F0C */ 0x1F04, /* U+1F0D */ 0x1F05, /* U+1F0E */ 0x1F06, /* U+1F0F */ 0x1F07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1F18 */ 0x1F10, /* U+1F19 */ 0x1F11, /* U+1F1A */ 0x1F12, /* U+1F1B */ 0x1F13, /* U+1F1C */ 0x1F14, /* U+1F1D */ 0x1F15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1F28 */ 0x1F20, /* U+1F29 */ 0x1F21, /* U+1F2A */ 0x1F22, /* U+1F2B */ 0x1F23, /* U+1F2C */ 0x1F24, /* U+1F2D */ 0x1F25, /* U+1F2E */ 0x1F26, /* U+1F2F */ 0x1F27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1F38 */ 0x1F30, /* U+1F39 */ 0x1F31, /* U+1F3A */ 0x1F32, /* U+1F3B */ 0x1F33, /* U+1F3C */ 0x1F34, /* U+1F3D */ 0x1F35, /* U+1F3E */ 0x1F36, /* U+1F3F */ 0x1F37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1F48 */ 0x1F40, /* U+1F49 */ 0x1F41, /* U+1F4A */ 0x1F42, /* U+1F4B */ 0x1F43, /* U+1F4C */ 0x1F44, /* U+1F4D */ 0x1F45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1F59 */ 0x1F51, 0x00, /* U+1F5B */ 0x1F53, 0x00, /* U+1F5D */ 0x1F55, 0x00, /* U+1F5F */ 0x1F57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1F68 */ 0x1F60, /* U+1F69 */ 0x1F61, /* U+1F6A */ 0x1F62, /* U+1F6B */ 0x1F63, /* U+1F6C */ 0x1F64, /* U+1F6D */ 0x1F65, /* U+1F6E */ 0x1F66, /* U+1F6F */ 0x1F67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1F88 */ 0x0, /* U+1F89 */ 0x0, /* U+1F8A */ 0x0, /* U+1F8B */ 0x0, /* U+1F8C */ 0x0, /* U+1F8D */ 0x0, /* U+1F8E */ 0x0, /* U+1F8F */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1F98 */ 0x0, /* U+1F99 */ 0x0, /* U+1F9A */ 0x0, /* U+1F9B */ 0x0, /* U+1F9C */ 0x0, /* U+1F9D */ 0x0, /* U+1F9E */ 0x0, /* U+1F9F */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1FA8 */ 0x0, /* U+1FA9 */ 0x0, /* U+1FAA */ 0x0, /* U+1FAB */ 0x0, /* U+1FAC */ 0x0, /* U+1FAD */ 0x0, /* U+1FAE */ 0x0, /* U+1FAF */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1FB8 */ 0x1FB0, /* U+1FB9 */ 0x1FB1, /* U+1FBA */ 0x1F70, /* U+1FBB */ 0x1F71, /* U+1FBC */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1FC8 */ 0x1F72, /* U+1FC9 */ 0x1F73, /* U+1FCA */ 0x1F74, /* U+1FCB */ 0x1F75, /* U+1FCC */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1FD8 */ 0x1FD0, /* U+1FD9 */ 0x1FD1, /* U+1FDA */ 0x1F76, /* U+1FDB */ 0x1F77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1FE8 */ 0x1FE0, /* U+1FE9 */ 0x1FE1, /* U+1FEA */ 0x1F7A, /* U+1FEB */ 0x1F7B, /* U+1FEC */ 0x1FE5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+1FF8 */ 0x1F78, /* U+1FF9 */ 0x1F79, /* U+1FFA */ 0x1F7C, /* U+1FFB */ 0x1F7D, /* U+1FFC */ 0x0, }; static const unsigned short ucs_table_2102[] = { /* U+2102 */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+210B */ 0x0, /* U+210C */ 0x0, /* U+210D */ 0x0, 0x00, 0x00, /* U+2110 */ 0x0, /* U+2111 */ 0x0, /* U+2112 */ 0x2113, 0x00, 0x00, /* U+2115 */ 0x0, 0x00, 0x00, /* U+2118 */ 0x0, /* U+2119 */ 0x0, /* U+211A */ 0x0, /* U+211B */ 0x0, /* U+211C */ 0x0, /* U+211D */ 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2124 */ 0x0, 0x00, 0x00, 0x00, /* U+2128 */ 0x0, 0x00, 0x00, 0x00, /* U+212C */ 0x0, /* U+212D */ 0x0, 0x00, 0x00, /* U+2130 */ 0x212F, /* U+2131 */ 0x0, /* U+2132 */ 0x0, /* U+2133 */ 0x0, }; static const unsigned short ucs_table_24B6[] = { /* U+24B6 */ 0x24D0, /* U+24B7 */ 0x24D1, /* U+24B8 */ 0x24D2, /* U+24B9 */ 0x24D3, /* U+24BA */ 0x24D4, /* U+24BB */ 0x24D5, /* U+24BC */ 0x24D6, /* U+24BD */ 0x24D7, /* U+24BE */ 0x24D8, /* U+24BF */ 0x24D9, /* U+24C0 */ 0x24DA, /* U+24C1 */ 0x24DB, /* U+24C2 */ 0x24DC, /* U+24C3 */ 0x24DD, /* U+24C4 */ 0x24DE, /* U+24C5 */ 0x24DF, /* U+24C6 */ 0x24E0, /* U+24C7 */ 0x24E1, /* U+24C8 */ 0x24E2, /* U+24C9 */ 0x24E3, /* U+24CA */ 0x24E4, /* U+24CB */ 0x24E5, /* U+24CC */ 0x24E6, /* U+24CD */ 0x24E7, /* U+24CE */ 0x24E8, /* U+24CF */ 0x24E9, }; static const unsigned short ucs_table_33CE[] = { /* U+33CE */ 0x0, }; static const unsigned short ucs_table_FF21[] = { /* U+FF21 */ 0xFF41, /* U+FF22 */ 0xFF42, /* U+FF23 */ 0xFF43, /* U+FF24 */ 0xFF44, /* U+FF25 */ 0xFF45, /* U+FF26 */ 0xFF46, /* U+FF27 */ 0xFF47, /* U+FF28 */ 0xFF48, /* U+FF29 */ 0xFF49, /* U+FF2A */ 0xFF4A, /* U+FF2B */ 0xFF4B, /* U+FF2C */ 0xFF4C, /* U+FF2D */ 0xFF4D, /* U+FF2E */ 0xFF4E, /* U+FF2F */ 0xFF4F, /* U+FF30 */ 0xFF50, /* U+FF31 */ 0xFF51, /* U+FF32 */ 0xFF52, /* U+FF33 */ 0xFF53, /* U+FF34 */ 0xFF54, /* U+FF35 */ 0xFF55, /* U+FF36 */ 0xFF56, /* U+FF37 */ 0xFF57, /* U+FF38 */ 0xFF58, /* U+FF39 */ 0xFF59, /* U+FF3A */ 0xFF5A, }; fltk-1.4.3/src/xutf8/headers/dingbats_.h0000644000175000017500000001537415004135251020202 0ustar albrechtalbrecht/* dingbats */ static const char unicode_to_dingbats_1b_0020[] = { /* U+0020 */ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+00A0 */ 0x20, }; static const char unicode_to_dingbats_1b_2192[] = { /* U+2192 */ (char)0xD5, 0x00, /* U+2194 */ (char)0xD6, /* U+2195 */ (char)0xD7, }; static const char unicode_to_dingbats_1b_2460[] = { /* U+2460 */ (char)0xAC, /* U+2461 */ (char)0xAD, /* U+2462 */ (char)0xAE, /* U+2463 */ (char)0xAF, /* U+2464 */ (char)0xB0, /* U+2465 */ (char)0xB1, /* U+2466 */ (char)0xB2, /* U+2467 */ (char)0xB3, /* U+2468 */ (char)0xB4, /* U+2469 */ (char)0xB5, }; static const char unicode_to_dingbats_1b_25A0[] = { /* U+25A0 */ 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+25B2 */ 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+25BC */ 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+25C6 */ 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+25CF */ 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+25D7 */ 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2605 */ 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+260E */ 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+261B */ 0x2A, 0x00, 0x00, /* U+261E */ 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2660 */ (char)0xAB, 0x00, 0x00, /* U+2663 */ (char)0xA8, 0x00, /* U+2665 */ (char)0xAA, /* U+2666 */ (char)0xA9, }; static const char unicode_to_dingbats_1b_2701[] = { /* U+2701 */ 0x21, /* U+2702 */ 0x22, /* U+2703 */ 0x23, /* U+2704 */ 0x24, 0x00, /* U+2706 */ 0x26, /* U+2707 */ 0x27, /* U+2708 */ 0x28, /* U+2709 */ 0x29, 0x00, 0x00, /* U+270C */ 0x2C, /* U+270D */ 0x2D, /* U+270E */ 0x2E, /* U+270F */ 0x2F, /* U+2710 */ 0x30, /* U+2711 */ 0x31, /* U+2712 */ 0x32, /* U+2713 */ 0x33, /* U+2714 */ 0x34, /* U+2715 */ 0x35, /* U+2716 */ 0x36, /* U+2717 */ 0x37, /* U+2718 */ 0x38, /* U+2719 */ 0x39, /* U+271A */ 0x3A, /* U+271B */ 0x3B, /* U+271C */ 0x3C, /* U+271D */ 0x3D, /* U+271E */ 0x3E, /* U+271F */ 0x3F, /* U+2720 */ 0x40, /* U+2721 */ 0x41, /* U+2722 */ 0x42, /* U+2723 */ 0x43, /* U+2724 */ 0x44, /* U+2725 */ 0x45, /* U+2726 */ 0x46, /* U+2727 */ 0x47, 0x00, /* U+2729 */ 0x49, /* U+272A */ 0x4A, /* U+272B */ 0x4B, /* U+272C */ 0x4C, /* U+272D */ 0x4D, /* U+272E */ 0x4E, /* U+272F */ 0x4F, /* U+2730 */ 0x50, /* U+2731 */ 0x51, /* U+2732 */ 0x52, /* U+2733 */ 0x53, /* U+2734 */ 0x54, /* U+2735 */ 0x55, /* U+2736 */ 0x56, /* U+2737 */ 0x57, /* U+2738 */ 0x58, /* U+2739 */ 0x59, /* U+273A */ 0x5A, /* U+273B */ 0x5B, /* U+273C */ 0x5C, /* U+273D */ 0x5D, /* U+273E */ 0x5E, /* U+273F */ 0x5F, /* U+2740 */ 0x60, /* U+2741 */ 0x61, /* U+2742 */ 0x62, /* U+2743 */ 0x63, /* U+2744 */ 0x64, /* U+2745 */ 0x65, /* U+2746 */ 0x66, /* U+2747 */ 0x67, /* U+2748 */ 0x68, /* U+2749 */ 0x69, /* U+274A */ 0x6A, /* U+274B */ 0x6B, 0x00, /* U+274D */ 0x6D, 0x00, /* U+274F */ 0x6F, /* U+2750 */ 0x70, /* U+2751 */ 0x71, /* U+2752 */ 0x72, 0x00, 0x00, 0x00, /* U+2756 */ 0x76, 0x00, /* U+2758 */ 0x78, /* U+2759 */ 0x79, /* U+275A */ 0x7A, /* U+275B */ 0x7B, /* U+275C */ 0x7C, /* U+275D */ 0x7D, /* U+275E */ 0x7E, 0x00, 0x00, /* U+2761 */ (char)0xA1, /* U+2762 */ (char)0xA2, /* U+2763 */ (char)0xA3, /* U+2764 */ (char)0xA4, /* U+2765 */ (char)0xA5, /* U+2766 */ (char)0xA6, /* U+2767 */ (char)0xA7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2776 */ (char)0xB6, /* U+2777 */ (char)0xB7, /* U+2778 */ (char)0xB8, /* U+2779 */ (char)0xB9, /* U+277A */ (char)0xBA, /* U+277B */ (char)0xBB, /* U+277C */ (char)0xBC, /* U+277D */ (char)0xBD, /* U+277E */ (char)0xBE, /* U+277F */ (char)0xBF, /* U+2780 */ (char)0xC0, /* U+2781 */ (char)0xC1, /* U+2782 */ (char)0xC2, /* U+2783 */ (char)0xC3, /* U+2784 */ (char)0xC4, /* U+2785 */ (char)0xC5, /* U+2786 */ (char)0xC6, /* U+2787 */ (char)0xC7, /* U+2788 */ (char)0xC8, /* U+2789 */ (char)0xC9, /* U+278A */ (char)0xCA, /* U+278B */ (char)0xCB, /* U+278C */ (char)0xCC, /* U+278D */ (char)0xCD, /* U+278E */ (char)0xCE, /* U+278F */ (char)0xCF, /* U+2790 */ (char)0xD0, /* U+2791 */ (char)0xD1, /* U+2792 */ (char)0xD2, /* U+2793 */ (char)0xD3, /* U+2794 */ (char)0xD4, 0x00, 0x00, 0x00, /* U+2798 */ (char)0xD8, /* U+2799 */ (char)0xD9, /* U+279A */ (char)0xDA, /* U+279B */ (char)0xDB, /* U+279C */ (char)0xDC, /* U+279D */ (char)0xDD, /* U+279E */ (char)0xDE, /* U+279F */ (char)0xDF, /* U+27A0 */ (char)0xE0, /* U+27A1 */ (char)0xE1, /* U+27A2 */ (char)0xE2, /* U+27A3 */ (char)0xE3, /* U+27A4 */ (char)0xE4, /* U+27A5 */ (char)0xE5, /* U+27A6 */ (char)0xE6, /* U+27A7 */ (char)0xE7, /* U+27A8 */ (char)0xE8, /* U+27A9 */ (char)0xE9, /* U+27AA */ (char)0xEA, /* U+27AB */ (char)0xEB, /* U+27AC */ (char)0xEC, /* U+27AD */ (char)0xED, /* U+27AE */ (char)0xEE, /* U+27AF */ (char)0xEF, 0x00, /* U+27B1 */ (char)0xF1, /* U+27B2 */ (char)0xF2, /* U+27B3 */ (char)0xF3, /* U+27B4 */ (char)0xF4, /* U+27B5 */ (char)0xF5, /* U+27B6 */ (char)0xF6, /* U+27B7 */ (char)0xF7, /* U+27B8 */ (char)0xF8, /* U+27B9 */ (char)0xF9, /* U+27BA */ (char)0xFA, /* U+27BB */ (char)0xFB, /* U+27BC */ (char)0xFC, /* U+27BD */ (char)0xFD, /* U+27BE */ (char)0xFE, }; static const char unicode_to_dingbats_1b_F8D7[] = { /* U+F8D7 */ (char)0x80, /* U+F8D8 */ (char)0x81, /* U+F8D9 */ (char)0x82, /* U+F8DA */ (char)0x83, /* U+F8DB */ (char)0x84, /* U+F8DC */ (char)0x85, /* U+F8DD */ (char)0x86, /* U+F8DE */ (char)0x87, /* U+F8DF */ (char)0x88, /* U+F8E0 */ (char)0x89, /* U+F8E1 */ (char)0x8A, /* U+F8E2 */ (char)0x8B, /* U+F8E3 */ (char)0x8C, /* U+F8E4 */ (char)0x8D, }; fltk-1.4.3/src/xutf8/headers/spacing.h0000644000175000017500000004212315004135251017664 0ustar albrechtalbrecht/* spacing */ static const unsigned short ucs_table_0300[] = { /* U+0300 */ 0x0060, /* U+0301 */ 0x00B4, /* U+0302 */ 0x005E, /* U+0303 */ 0x02DC, /* U+0304 */ 0x00AF, /* U+0305 */ 0x203E, /* U+0306 */ 0x02D8, /* U+0307 */ 0x02D9, /* U+0308 */ 0x00A8, /* U+0309 */ 0x0309, /* U+030A */ 0x02DA, /* U+030B */ 0x02DD, /* U+030C */ 0x030C, /* U+030D */ 0x030D, /* U+030E */ 0x030E, /* U+030F */ 0x030F, /* U+0310 */ 0x0310, /* U+0311 */ 0x0311, /* U+0312 */ 0x0312, /* U+0313 */ 0x1FBD, /* U+0314 */ 0x1FFE, /* U+0315 */ 0x0315, /* U+0316 */ 0x0316, /* U+0317 */ 0x0317, /* U+0318 */ 0x0318, /* U+0319 */ 0x0319, /* U+031A */ 0x031A, /* U+031B */ 0x031B, /* U+031C */ 0x031C, /* U+031D */ 0x031D, /* U+031E */ 0x031E, /* U+031F */ 0x031F, /* U+0320 */ 0x0320, /* U+0321 */ 0x0321, /* U+0322 */ 0x0322, /* U+0323 */ 0x0323, /* U+0324 */ 0x0324, /* U+0325 */ 0x0325, /* U+0326 */ 0x0326, /* U+0327 */ 0x00B8, /* U+0328 */ 0x02DB, /* U+0329 */ 0x0329, /* U+032A */ 0x032A, /* U+032B */ 0x032B, /* U+032C */ 0x032C, /* U+032D */ 0x032D, /* U+032E */ 0x032E, /* U+032F */ 0x032F, /* U+0330 */ 0x0330, /* U+0331 */ 0x0331, /* U+0332 */ 0x005F, /* U+0333 */ 0x2017, /* U+0334 */ 0x0334, /* U+0335 */ 0x0335, /* U+0336 */ 0x0336, /* U+0337 */ 0x0337, /* U+0338 */ 0x0338, /* U+0339 */ 0x0339, /* U+033A */ 0x033A, /* U+033B */ 0x033B, /* U+033C */ 0x033C, /* U+033D */ 0x033D, /* U+033E */ 0x033E, /* U+033F */ 0x033F, /* U+0340 */ 0x0340, /* U+0341 */ 0x0341, /* U+0342 */ 0x1FC0, /* U+0343 */ 0x0343, /* U+0344 */ 0x0344, /* U+0345 */ 0x037A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0360 */ 0x0360, /* U+0361 */ 0x0361, }; static const unsigned short ucs_table_0483[] = { /* U+0483 */ 0x0483, /* U+0484 */ 0x0484, /* U+0485 */ 0x0485, /* U+0486 */ 0x0486, }; static const unsigned short ucs_table_0591[] = { /* U+0591 */ 0x0591, /* U+0592 */ 0x0592, /* U+0593 */ 0x0593, /* U+0594 */ 0x0594, /* U+0595 */ 0x0595, /* U+0596 */ 0x0596, /* U+0597 */ 0x0597, /* U+0598 */ 0x0598, /* U+0599 */ 0x0599, /* U+059A */ 0x059A, /* U+059B */ 0x059B, /* U+059C */ 0x059C, /* U+059D */ 0x059D, /* U+059E */ 0x059E, /* U+059F */ 0x059F, /* U+05A0 */ 0x05A0, /* U+05A1 */ 0x05A1, 0x00, /* U+05A3 */ 0x05A3, /* U+05A4 */ 0x05A4, /* U+05A5 */ 0x05A5, /* U+05A6 */ 0x05A6, /* U+05A7 */ 0x05A7, /* U+05A8 */ 0x05A8, /* U+05A9 */ 0x05A9, /* U+05AA */ 0x05AA, /* U+05AB */ 0x05AB, /* U+05AC */ 0x05AC, /* U+05AD */ 0x05AD, /* U+05AE */ 0x05AE, /* U+05AF */ 0x05AF, /* U+05B0 */ 0x05B0, /* U+05B1 */ 0x05B1, /* U+05B2 */ 0x05B2, /* U+05B3 */ 0x05B3, /* U+05B4 */ 0x05B4, /* U+05B5 */ 0x05B5, /* U+05B6 */ 0x05B6, /* U+05B7 */ 0x05B7, /* U+05B8 */ 0x05B8, /* U+05B9 */ 0x05B9, 0x00, /* U+05BB */ 0x05BB, /* U+05BC */ 0x05BC, /* U+05BD */ 0x05BD, 0x00, /* U+05BF */ 0x05BF, 0x00, /* U+05C1 */ 0x05C1, /* U+05C2 */ 0x05C2, 0x00, /* U+05C4 */ 0x05C4, }; static const unsigned short ucs_table_064B[] = { /* U+064B */ 0xFE70, /* U+064C */ 0xFE72, /* U+064D */ 0xFE74, /* U+064E */ 0xFE76, /* U+064F */ 0xFE78, /* U+0650 */ 0xFE7A, /* U+0651 */ 0xFE7C, /* U+0652 */ 0xFE7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0670 */ 0x0670, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+06D6 */ 0x06D6, /* U+06D7 */ 0x06D7, /* U+06D8 */ 0x06D8, /* U+06D9 */ 0x06D9, /* U+06DA */ 0x06DA, /* U+06DB */ 0x06DB, /* U+06DC */ 0x06DC, 0x00, 0x00, /* U+06DF */ 0x06DF, /* U+06E0 */ 0x06E0, /* U+06E1 */ 0x06E1, /* U+06E2 */ 0x06E2, /* U+06E3 */ 0x06E3, /* U+06E4 */ 0x06E4, 0x00, 0x00, /* U+06E7 */ 0x06E7, /* U+06E8 */ 0x06E8, 0x00, /* U+06EA */ 0x06EA, /* U+06EB */ 0x06EB, /* U+06EC */ 0x06EC, /* U+06ED */ 0x06ED, }; static const unsigned short ucs_table_0901[] = { /* U+0901 */ 0x0901, /* U+0902 */ 0x0902, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+093C */ 0x093C, 0x00, 0x00, 0x00, 0x00, /* U+0941 */ 0x0941, /* U+0942 */ 0x0942, /* U+0943 */ 0x0943, /* U+0944 */ 0x0944, /* U+0945 */ 0x0945, /* U+0946 */ 0x0946, /* U+0947 */ 0x0947, /* U+0948 */ 0x0948, 0x00, 0x00, 0x00, 0x00, /* U+094D */ 0x094D, 0x00, 0x00, 0x00, /* U+0951 */ 0x0951, /* U+0952 */ 0x0952, /* U+0953 */ 0x0953, /* U+0954 */ 0x0954, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0962 */ 0x0962, /* U+0963 */ 0x0963, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0981 */ 0x0981, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+09BC */ 0x09BC, 0x00, 0x00, 0x00, 0x00, /* U+09C1 */ 0x09C1, /* U+09C2 */ 0x09C2, /* U+09C3 */ 0x09C3, /* U+09C4 */ 0x09C4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+09CD */ 0x09CD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+09E2 */ 0x09E2, /* U+09E3 */ 0x09E3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0A02 */ 0x0A02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0A3C */ 0x0A3C, 0x00, 0x00, 0x00, 0x00, /* U+0A41 */ 0x0A41, /* U+0A42 */ 0x0A42, 0x00, 0x00, 0x00, 0x00, /* U+0A47 */ 0x0A47, /* U+0A48 */ 0x0A48, 0x00, 0x00, /* U+0A4B */ 0x0A4B, /* U+0A4C */ 0x0A4C, /* U+0A4D */ 0x0A4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0A70 */ 0x0A70, /* U+0A71 */ 0x0A71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0A81 */ 0x0A81, /* U+0A82 */ 0x0A82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0ABC */ 0x0ABC, 0x00, 0x00, 0x00, 0x00, /* U+0AC1 */ 0x0AC1, /* U+0AC2 */ 0x0AC2, /* U+0AC3 */ 0x0AC3, /* U+0AC4 */ 0x0AC4, /* U+0AC5 */ 0x0AC5, 0x00, /* U+0AC7 */ 0x0AC7, /* U+0AC8 */ 0x0AC8, 0x00, 0x00, 0x00, 0x00, /* U+0ACD */ 0x0ACD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0B01 */ 0x0B01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0B3C */ 0x0B3C, 0x00, 0x00, /* U+0B3F */ 0x0B3F, 0x00, /* U+0B41 */ 0x0B41, /* U+0B42 */ 0x0B42, /* U+0B43 */ 0x0B43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0B4D */ 0x0B4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0B56 */ 0x0B56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0B82 */ 0x0B82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0BC0 */ 0x0BC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0BCD */ 0x0BCD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0C3E */ 0x0C3E, /* U+0C3F */ 0x0C3F, /* U+0C40 */ 0x0C40, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0C46 */ 0x0C46, /* U+0C47 */ 0x0C47, /* U+0C48 */ 0x0C48, 0x00, /* U+0C4A */ 0x0C4A, /* U+0C4B */ 0x0C4B, /* U+0C4C */ 0x0C4C, /* U+0C4D */ 0x0C4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0C55 */ 0x0C55, /* U+0C56 */ 0x0C56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0CBF */ 0x0CBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0CC6 */ 0x0CC6, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0CCC */ 0x0CCC, /* U+0CCD */ 0x0CCD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0D41 */ 0x0D41, /* U+0D42 */ 0x0D42, /* U+0D43 */ 0x0D43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0D4D */ 0x0D4D, }; static const unsigned short ucs_table_0E31[] = { /* U+0E31 */ 0x0E31, 0x00, 0x00, /* U+0E34 */ 0x0E34, /* U+0E35 */ 0x0E35, /* U+0E36 */ 0x0E36, /* U+0E37 */ 0x0E37, /* U+0E38 */ 0x0E38, /* U+0E39 */ 0x0E39, /* U+0E3A */ 0x0E3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0E47 */ 0x0E47, /* U+0E48 */ 0x0E48, /* U+0E49 */ 0x0E49, /* U+0E4A */ 0x0E4A, /* U+0E4B */ 0x0E4B, /* U+0E4C */ 0x0E4C, /* U+0E4D */ 0x0E4D, /* U+0E4E */ 0x0E4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0EB1 */ 0x0EB1, 0x00, 0x00, /* U+0EB4 */ 0x0EB4, /* U+0EB5 */ 0x0EB5, /* U+0EB6 */ 0x0EB6, /* U+0EB7 */ 0x0EB7, /* U+0EB8 */ 0x0EB8, /* U+0EB9 */ 0x0EB9, 0x00, /* U+0EBB */ 0x0EBB, /* U+0EBC */ 0x0EBC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0EC8 */ 0x0EC8, /* U+0EC9 */ 0x0EC9, /* U+0ECA */ 0x0ECA, /* U+0ECB */ 0x0ECB, /* U+0ECC */ 0x0ECC, /* U+0ECD */ 0x0ECD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0F18 */ 0x0F18, /* U+0F19 */ 0x0F19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0F35 */ 0x0F35, 0x00, /* U+0F37 */ 0x0F37, 0x00, /* U+0F39 */ 0x0F39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0F71 */ 0x0F71, /* U+0F72 */ 0x0F72, /* U+0F73 */ 0x0F73, /* U+0F74 */ 0x0F74, /* U+0F75 */ 0x0F75, /* U+0F76 */ 0x0F76, /* U+0F77 */ 0x0F77, /* U+0F78 */ 0x0F78, /* U+0F79 */ 0x0F79, /* U+0F7A */ 0x0F7A, /* U+0F7B */ 0x0F7B, /* U+0F7C */ 0x0F7C, /* U+0F7D */ 0x0F7D, /* U+0F7E */ 0x0F7E, 0x00, /* U+0F80 */ 0x0F80, /* U+0F81 */ 0x0F81, /* U+0F82 */ 0x0F82, /* U+0F83 */ 0x0F83, /* U+0F84 */ 0x0F84, 0x00, /* U+0F86 */ 0x0F86, /* U+0F87 */ 0x0F87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+0F90 */ 0x0F90, /* U+0F91 */ 0x0F91, /* U+0F92 */ 0x0F92, /* U+0F93 */ 0x0F93, /* U+0F94 */ 0x0F94, /* U+0F95 */ 0x0F95, 0x00, /* U+0F97 */ 0x0F97, 0x00, /* U+0F99 */ 0x0F99, /* U+0F9A */ 0x0F9A, /* U+0F9B */ 0x0F9B, /* U+0F9C */ 0x0F9C, /* U+0F9D */ 0x0F9D, /* U+0F9E */ 0x0F9E, /* U+0F9F */ 0x0F9F, /* U+0FA0 */ 0x0FA0, /* U+0FA1 */ 0x0FA1, /* U+0FA2 */ 0x0FA2, /* U+0FA3 */ 0x0FA3, /* U+0FA4 */ 0x0FA4, /* U+0FA5 */ 0x0FA5, /* U+0FA6 */ 0x0FA6, /* U+0FA7 */ 0x0FA7, /* U+0FA8 */ 0x0FA8, /* U+0FA9 */ 0x0FA9, /* U+0FAA */ 0x0FAA, /* U+0FAB */ 0x0FAB, /* U+0FAC */ 0x0FAC, /* U+0FAD */ 0x0FAD, 0x00, 0x00, 0x00, /* U+0FB1 */ 0x0FB1, /* U+0FB2 */ 0x0FB2, /* U+0FB3 */ 0x0FB3, /* U+0FB4 */ 0x0FB4, /* U+0FB5 */ 0x0FB5, /* U+0FB6 */ 0x0FB6, /* U+0FB7 */ 0x0FB7, 0x00, /* U+0FB9 */ 0x0FB9, }; static const unsigned short ucs_table_20D0[] = { /* U+20D0 */ 0x20D0, /* U+20D1 */ 0x20D1, /* U+20D2 */ 0x20D2, /* U+20D3 */ 0x20D3, /* U+20D4 */ 0x20D4, /* U+20D5 */ 0x20D5, /* U+20D6 */ 0x20D6, /* U+20D7 */ 0x20D7, /* U+20D8 */ 0x20D8, /* U+20D9 */ 0x20D9, /* U+20DA */ 0x20DA, /* U+20DB */ 0x20DB, /* U+20DC */ 0x20DC, 0x00, 0x00, 0x00, 0x00, /* U+20E1 */ 0x20E1, }; static const unsigned short ucs_table_302A[] = { /* U+302A */ 0x302A, /* U+302B */ 0x302B, /* U+302C */ 0x302C, /* U+302D */ 0x302D, /* U+302E */ 0x302E, /* U+302F */ 0x302F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+3099 */ 0x309B, /* U+309A */ 0x309C, }; static const unsigned short ucs_table_FB1E[] = { /* U+FB1E */ 0xFB1E, }; static const unsigned short ucs_table_FE20[] = { /* U+FE20 */ 0xFE20, /* U+FE21 */ 0xFE21, /* U+FE22 */ 0xFE22, /* U+FE23 */ 0xFE23, }; fltk-1.4.3/src/xutf8/headers/tbl.txt0000644000175000017500000001516415004135251017416 0ustar albrechtalbrechtunicode_to_iso8859_1_1b_0001[]; /* end: U+00FF */ unicode_to_iso8859_2_1b_0001[]; /* end: U+017E */ unicode_to_iso8859_2_1b_02C7[]; /* end: U+02DD */ unicode_to_iso8859_3_1b_0001[]; /* end: U+017C */ unicode_to_iso8859_3_1b_02D8[]; /* end: U+02D9 */ unicode_to_iso8859_4_1b_0001[]; /* end: U+017E */ unicode_to_iso8859_4_1b_02C7[]; /* end: U+02DB */ unicode_to_iso8859_5_1b_0001[]; /* end: U+00AD */ unicode_to_iso8859_5_1b_0401[]; /* end: U+045F */ unicode_to_iso8859_5_1b_2116[]; /* end: U+2116 */ unicode_to_iso8859_6_1b_0001[]; /* end: U+00AD */ unicode_to_iso8859_6_1b_060C[]; /* end: U+0652 */ unicode_to_iso8859_7_1b_0001[]; /* end: U+00BD */ unicode_to_iso8859_7_1b_0384[]; /* end: U+03CE */ unicode_to_iso8859_7_1b_2015[]; /* end: U+2019 */ unicode_to_iso8859_8_1b_0001[]; /* end: U+00F7 */ unicode_to_iso8859_8_1b_05D0[]; /* end: U+05EA */ unicode_to_iso8859_8_1b_200E[]; /* end: U+2017 */ unicode_to_iso8859_9_1b_0001[]; /* end: U+015F */ unicode_to_iso8859_10_1b_0001[]; /* end: U+017E */ unicode_to_iso8859_10_1b_2015[]; /* end: U+2015 */ unicode_to_iso8859_13_1b_0001[]; /* end: U+017E */ unicode_to_iso8859_13_1b_2019[]; /* end: U+201E */ unicode_to_iso8859_14_1b_0001[]; /* end: U+0178 */ unicode_to_iso8859_14_1b_1E02[]; /* end: U+1EF3 */ unicode_to_iso8859_15_1b_0001[]; /* end: U+017E */ unicode_to_iso8859_15_1b_20AC[]; /* end: U+20AC */ unicode_to_koi8_1_1b_0001[]; /* end: U+00F7 */ unicode_to_koi8_1_1b_0401[]; /* end: U+0451 */ unicode_to_koi8_1_1b_2219[]; /* end: U+2265 */ unicode_to_koi8_1_1b_2320[]; /* end: U+2321 */ unicode_to_koi8_1_1b_2500[]; /* end: U+25A0 */ unicode_to_big5_0_2b_00A2[]; /* end: U+00F7 */ unicode_to_big5_0_2b_02C7[]; /* end: U+02D9 */ unicode_to_big5_0_2b_0391[]; /* end: U+0451 */ unicode_to_big5_0_2b_2013[]; /* end: U+203E */ unicode_to_big5_0_2b_2103[]; /* end: U+2199 */ unicode_to_big5_0_2b_221A[]; /* end: U+22BF */ unicode_to_big5_0_2b_2460[]; /* end: U+247D */ unicode_to_big5_0_2b_2500[]; /* end: U+2642 */ unicode_to_big5_0_2b_3000[]; /* end: U+3129 */ unicode_to_big5_0_2b_32A3[]; /* end: U+32A3 */ unicode_to_big5_0_2b_338E[]; /* end: U+33D5 */ unicode_to_big5_0_2b_4E00[]; /* end: U+7E9C */ unicode_to_big5_0_2b_7F36[]; /* end: U+8B9F */ unicode_to_big5_0_2b_8C37[]; /* end: U+9483 */ unicode_to_big5_0_2b_9577[]; /* end: U+9FA4 */ unicode_to_big5_0_2b_FA0C[]; /* end: U+FA0D */ unicode_to_big5_0_2b_FE30[]; /* end: U+FE6B */ unicode_to_big5_0_2b_FF01[]; /* end: U+FF64 */ unicode_to_big5_0_2b_FFFD[]; /* end: U+FFFD */ unicode_to_ksc5601_1987_0_2b_00A1[]; /* end: U+0167 */ unicode_to_ksc5601_1987_0_2b_02C7[]; /* end: U+02DD */ unicode_to_ksc5601_1987_0_2b_0391[]; /* end: U+0451 */ unicode_to_ksc5601_1987_0_2b_2015[]; /* end: U+2312 */ unicode_to_ksc5601_1987_0_2b_2460[]; /* end: U+266D */ unicode_to_ksc5601_1987_0_2b_3000[]; /* end: U+327F */ unicode_to_ksc5601_1987_0_2b_3380[]; /* end: U+33DD */ unicode_to_ksc5601_1987_0_2b_4E00[]; /* end: U+7E9C */ unicode_to_ksc5601_1987_0_2b_7F36[]; /* end: U+8B9A */ unicode_to_ksc5601_1987_0_2b_8C37[]; /* end: U+947F */ unicode_to_ksc5601_1987_0_2b_9577[]; /* end: U+9C57 */ unicode_to_ksc5601_1987_0_2b_9CE5[]; /* end: U+9F9C */ unicode_to_ksc5601_1987_0_2b_AC00[]; /* end: U+D79D */ unicode_to_ksc5601_1987_0_2b_F900[]; /* end: U+FA0B */ unicode_to_ksc5601_1987_0_2b_FF01[]; /* end: U+FF5E */ unicode_to_ksc5601_1987_0_2b_FFE0[]; /* end: U+FFE6 */ unicode_to_gb2312_1980_0_2b_00A4[]; /* end: U+01DC */ unicode_to_gb2312_1980_0_2b_02C7[]; /* end: U+02C9 */ unicode_to_gb2312_1980_0_2b_0391[]; /* end: U+0451 */ unicode_to_gb2312_1980_0_2b_2015[]; /* end: U+203B */ unicode_to_gb2312_1980_0_2b_2103[]; /* end: U+2312 */ unicode_to_gb2312_1980_0_2b_2460[]; /* end: U+2642 */ unicode_to_gb2312_1980_0_2b_3000[]; /* end: U+3129 */ unicode_to_gb2312_1980_0_2b_3220[]; /* end: U+3229 */ unicode_to_gb2312_1980_0_2b_4E00[]; /* end: U+7DAE */ unicode_to_gb2312_1980_0_2b_7E3B[]; /* end: U+8C98 */ unicode_to_gb2312_1980_0_2b_8D1D[]; /* end: U+8ECE */ unicode_to_gb2312_1980_0_2b_8F66[]; /* end: U+91DC */ unicode_to_gb2312_1980_0_2b_9274[]; /* end: U+99A8 */ unicode_to_gb2312_1980_0_2b_9A6C[]; /* end: U+9B54 */ unicode_to_gb2312_1980_0_2b_9C7C[]; /* end: U+9CE2 */ unicode_to_gb2312_1980_0_2b_9E1F[]; /* end: U+9FA0 */ unicode_to_gb2312_1980_0_2b_FF01[]; /* end: U+FF5E */ unicode_to_gb2312_1980_0_2b_FFE0[]; /* end: U+FFE5 */ unicode_to_jisx0201_1976_0_1b_0020[]; /* end: U+00A5 */ unicode_to_jisx0201_1976_0_1b_203E[]; /* end: U+203E */ unicode_to_jisx0201_1976_0_1b_FF61[]; /* end: U+FF9F */ unicode_to_jisx0208_1983_0_2b_005C[]; /* end: U+00F7 */ unicode_to_jisx0208_1983_0_2b_0391[]; /* end: U+0451 */ unicode_to_jisx0208_1983_0_2b_2010[]; /* end: U+203B */ unicode_to_jisx0208_1983_0_2b_2103[]; /* end: U+2312 */ unicode_to_jisx0208_1983_0_2b_2500[]; /* end: U+266F */ unicode_to_jisx0208_1983_0_2b_3000[]; /* end: U+30FE */ unicode_to_jisx0208_1983_0_2b_4E00[]; /* end: U+7E9C */ unicode_to_jisx0208_1983_0_2b_7F36[]; /* end: U+8B9A */ unicode_to_jisx0208_1983_0_2b_8C37[]; /* end: U+9481 */ unicode_to_jisx0208_1983_0_2b_9577[]; /* end: U+9FA0 */ unicode_to_jisx0208_1983_0_2b_FF01[]; /* end: U+FF5D */ unicode_to_jisx0208_1983_0_2b_FFE3[]; /* end: U+FFE5 */ unicode_to_jisx0212_1990_0_2b_007E[]; /* end: U+01F5 */ unicode_to_jisx0212_1990_0_2b_02C7[]; /* end: U+02DD */ unicode_to_jisx0212_1990_0_2b_0384[]; /* end: U+045F */ unicode_to_jisx0212_1990_0_2b_2116[]; /* end: U+2122 */ unicode_to_jisx0212_1990_0_2b_4E02[]; /* end: U+7E9E */ unicode_to_jisx0212_1990_0_2b_7F3B[]; /* end: U+8B9F */ unicode_to_jisx0212_1990_0_2b_8C38[]; /* end: U+9484 */ unicode_to_jisx0212_1990_0_2b_9578[]; /* end: U+9FA5 */ unicode_to_symbol_1b_0020[]; /* end: U+00F7 */ unicode_to_symbol_1b_0192[]; /* end: U+0192 */ unicode_to_symbol_1b_0391[]; /* end: U+03D6 */ unicode_to_symbol_1b_2022[]; /* end: U+232A */ unicode_to_symbol_1b_25CA[]; /* end: U+25CA */ unicode_to_symbol_1b_2660[]; /* end: U+2666 */ unicode_to_symbol_1b_F6D9[]; /* end: U+F6DB */ unicode_to_symbol_1b_F8E5[]; /* end: U+F8FE */ unicode_to_dingbats_1b_0020[]; /* end: U+00A0 */ unicode_to_dingbats_1b_2192[]; /* end: U+2195 */ unicode_to_dingbats_1b_2460[]; /* end: U+2469 */ unicode_to_dingbats_1b_25A0[]; /* end: U+2666 */ unicode_to_dingbats_1b_2701[]; /* end: U+27BE */ unicode_to_dingbats_1b_F8D7[]; /* end: U+F8E4 */ fltk-1.4.3/src/xutf8/headers/case_tbl.txt0000644000175000017500000000052015004135251020377 0ustar albrechtalbrechtucs_table_0041[]; /* end: U+02B6 */ ucs_table_0386[]; /* end: U+0556 */ ucs_table_10A0[]; /* end: U+10C5 */ ucs_table_1E00[]; /* end: U+1FFC */ ucs_table_2102[]; /* end: U+2133 */ ucs_table_24B6[]; /* end: U+24CF */ ucs_table_33CE[]; /* end: U+33CE */ ucs_table_FF21[]; /* end: U+FF3A */ fltk-1.4.3/src/xutf8/headers/symbol_.h0000644000175000017500000002363715004135251017715 0ustar albrechtalbrecht/* symbol */ static const char unicode_to_symbol_1b_0020[] = { /* U+0020 */ 0x20, /* U+0021 */ 0x21, 0x00, /* U+0023 */ 0x23, 0x00, /* U+0025 */ 0x25, /* U+0026 */ 0x26, 0x00, /* U+0028 */ 0x28, /* U+0029 */ 0x29, 0x00, /* U+002B */ 0x2B, /* U+002C */ 0x2C, 0x00, /* U+002E */ 0x2E, /* U+002F */ 0x2F, /* U+0030 */ 0x30, /* U+0031 */ 0x31, /* U+0032 */ 0x32, /* U+0033 */ 0x33, /* U+0034 */ 0x34, /* U+0035 */ 0x35, /* U+0036 */ 0x36, /* U+0037 */ 0x37, /* U+0038 */ 0x38, /* U+0039 */ 0x39, /* U+003A */ 0x3A, /* U+003B */ 0x3B, /* U+003C */ 0x3C, /* U+003D */ 0x3D, /* U+003E */ 0x3E, /* U+003F */ 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+005B */ 0x5B, 0x00, /* U+005D */ 0x5D, 0x00, /* U+005F */ 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+007B */ 0x7B, /* U+007C */ 0x7C, /* U+007D */ 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+00A0 */ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+00AC */ (char)0xD8, 0x00, 0x00, 0x00, /* U+00B0 */ (char)0xB0, /* U+00B1 */ (char)0xB1, 0x00, 0x00, 0x00, /* U+00B5 */ 0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+00D7 */ (char)0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+00F7 */ (char)0xB8, }; static const char unicode_to_symbol_1b_0192[] = { /* U+0192 */ (char)0xA6, }; static const char unicode_to_symbol_1b_0391[] = { /* U+0391 */ 0x41, /* U+0392 */ 0x42, /* U+0393 */ 0x47, /* U+0394 */ 0x44, /* U+0395 */ 0x45, /* U+0396 */ 0x5A, /* U+0397 */ 0x48, /* U+0398 */ 0x51, /* U+0399 */ 0x49, /* U+039A */ 0x4B, /* U+039B */ 0x4C, /* U+039C */ 0x4D, /* U+039D */ 0x4E, /* U+039E */ 0x58, /* U+039F */ 0x4F, /* U+03A0 */ 0x50, /* U+03A1 */ 0x52, 0x00, /* U+03A3 */ 0x53, /* U+03A4 */ 0x54, /* U+03A5 */ 0x55, /* U+03A6 */ 0x46, /* U+03A7 */ 0x43, /* U+03A8 */ 0x59, /* U+03A9 */ 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+03B1 */ 0x61, /* U+03B2 */ 0x62, /* U+03B3 */ 0x67, /* U+03B4 */ 0x64, /* U+03B5 */ 0x65, /* U+03B6 */ 0x7A, /* U+03B7 */ 0x68, /* U+03B8 */ 0x71, /* U+03B9 */ 0x69, /* U+03BA */ 0x6B, /* U+03BB */ 0x6C, /* U+03BC */ 0x6D, /* U+03BD */ 0x6E, /* U+03BE */ 0x78, /* U+03BF */ 0x6F, /* U+03C0 */ 0x70, /* U+03C1 */ 0x72, /* U+03C2 */ 0x56, /* U+03C3 */ 0x73, /* U+03C4 */ 0x74, /* U+03C5 */ 0x75, /* U+03C6 */ 0x66, /* U+03C7 */ 0x63, /* U+03C8 */ 0x79, /* U+03C9 */ 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+03D1 */ 0x4A, /* U+03D2 */ (char)0xA1, 0x00, 0x00, /* U+03D5 */ 0x6A, /* U+03D6 */ 0x76, }; static const char unicode_to_symbol_1b_2022[] = { /* U+2022 */ (char)0xB7, 0x00, 0x00, 0x00, /* U+2026 */ (char)0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2032 */ (char)0xA2, /* U+2033 */ (char)0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2044 */ (char)0xA4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+20AC */ (char)0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2111 */ (char)0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2118 */ (char)0xC3, 0x00, 0x00, 0x00, /* U+211C */ (char)0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2126 */ 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2135 */ (char)0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2190 */ (char)0xAC, /* U+2191 */ (char)0xAD, /* U+2192 */ (char)0xAE, /* U+2193 */ (char)0xAF, /* U+2194 */ (char)0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+21B5 */ (char)0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+21D0 */ (char)0xDC, /* U+21D1 */ (char)0xDD, /* U+21D2 */ (char)0xDE, /* U+21D3 */ (char)0xDF, /* U+21D4 */ (char)0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2200 */ 0x22, 0x00, /* U+2202 */ (char)0xB6, /* U+2203 */ 0x24, 0x00, /* U+2205 */ (char)0xC6, /* U+2206 */ 0x44, /* U+2207 */ (char)0xD1, /* U+2208 */ (char)0xCE, /* U+2209 */ (char)0xCF, 0x00, /* U+220B */ 0x27, 0x00, 0x00, 0x00, /* U+220F */ (char)0xD5, 0x00, /* U+2211 */ (char)0xE5, /* U+2212 */ 0x2D, 0x00, 0x00, /* U+2215 */ (char)0xA4, 0x00, /* U+2217 */ 0x2A, 0x00, 0x00, /* U+221A */ (char)0xD6, 0x00, 0x00, /* U+221D */ (char)0xB5, /* U+221E */ (char)0xA5, 0x00, /* U+2220 */ (char)0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2227 */ (char)0xD9, /* U+2228 */ (char)0xDA, /* U+2229 */ (char)0xC7, /* U+222A */ (char)0xC8, /* U+222B */ (char)0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2234 */ 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+223C */ 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2245 */ 0x40, 0x00, 0x00, /* U+2248 */ (char)0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2260 */ (char)0xB9, /* U+2261 */ (char)0xBA, 0x00, 0x00, /* U+2264 */ (char)0xA3, /* U+2265 */ (char)0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2282 */ (char)0xCC, /* U+2283 */ (char)0xC9, /* U+2284 */ (char)0xCB, 0x00, /* U+2286 */ (char)0xCD, /* U+2287 */ (char)0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2295 */ (char)0xC5, 0x00, /* U+2297 */ (char)0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+22A5 */ 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+22C5 */ (char)0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2320 */ (char)0xF3, /* U+2321 */ (char)0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* U+2329 */ (char)0xE1, /* U+232A */ (char)0xF1, }; static const char unicode_to_symbol_1b_25CA[] = { /* U+25CA */ (char)0xE0, }; static const char unicode_to_symbol_1b_2660[] = { /* U+2660 */ (char)0xAA, 0x00, 0x00, /* U+2663 */ (char)0xA7, 0x00, /* U+2665 */ (char)0xA9, /* U+2666 */ (char)0xA8, }; static const char unicode_to_symbol_1b_F6D9[] = { /* U+F6D9 */ (char)0xD3, /* U+F6DA */ (char)0xD2, /* U+F6DB */ (char)0xD4, }; static const char unicode_to_symbol_1b_F8E5[] = { /* U+F8E5 */ 0x60, /* U+F8E6 */ (char)0xBD, /* U+F8E7 */ (char)0xBE, /* U+F8E8 */ (char)0xE2, /* U+F8E9 */ (char)0xE3, /* U+F8EA */ (char)0xE4, /* U+F8EB */ (char)0xE6, /* U+F8EC */ (char)0xE7, /* U+F8ED */ (char)0xE8, /* U+F8EE */ (char)0xE9, /* U+F8EF */ (char)0xEA, /* U+F8F0 */ (char)0xEB, /* U+F8F1 */ (char)0xEC, /* U+F8F2 */ (char)0xED, /* U+F8F3 */ (char)0xEE, /* U+F8F4 */ (char)0xEF, /* U+F8F5 */ (char)0xF4, /* U+F8F6 */ (char)0xF6, /* U+F8F7 */ (char)0xF7, /* U+F8F8 */ (char)0xF8, /* U+F8F9 */ (char)0xF9, /* U+F8FA */ (char)0xFA, /* U+F8FB */ (char)0xFB, /* U+F8FC */ (char)0xFC, /* U+F8FD */ (char)0xFD, /* U+F8FE */ (char)0xFE, }; fltk-1.4.3/src/xutf8/headers/spacing_tbl.txt0000644000175000017500000000064415004135251021117 0ustar albrechtalbrechtucs_table_0300[]; /* end: U+0361 */ ucs_table_0483[]; /* end: U+0486 */ ucs_table_0591[]; /* end: U+05C4 */ ucs_table_064B[]; /* end: U+06ED */ ucs_table_0901[]; /* end: U+0D4D */ ucs_table_0E31[]; /* end: U+0FB9 */ ucs_table_20D0[]; /* end: U+20E1 */ ucs_table_302A[]; /* end: U+309A */ ucs_table_FB1E[]; /* end: U+FB1E */ ucs_table_FE20[]; /* end: U+FE23 */ fltk-1.4.3/src/xutf8/utils/0000755000175000017500000000000015004135251015612 5ustar albrechtalbrechtfltk-1.4.3/src/xutf8/utils/case.sh0000755000175000017500000000371715004135251017074 0ustar albrechtalbrecht#!/bin/sh nopsc=`grep 'CAPITAL' ../UnicodeData-2.txt` IFS=" " #echo "# # List of case chars # # # Format: Three tab-separated columns # Column #1 is the non-spacing Unicode (in hex as 0xXXXX) # Column #2 is the spacing Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # " > case.txt rm -f case.txt for line in ${nopsc} do ucs=`echo ${line} | cut -d\; -f1` name=`echo ${line} | cut -d\; -f2 | cut -d\; -f1| sed s/CAPITAL/SMALL/` small=`grep ";${name};" ../UnicodeData-2.txt` if test "X${small}" != X ;then tbl=`echo ${small} | cut -d\; -f1` # echo "0x${ucs} 0x${tbl} # ${name}" >> space.txt echo "/* U+${ucs} */ 0x${tbl}," >> case.txt else # echo "0x${ucs} 0x${ucs} # ${name}" >> space.txt echo "/* U+${ucs} */ 0x0," >> case.txt fi done unset nospc # echo "/* EOF */" >> space.txt cat case.txt | ./create_table "spacing" > "../headers/case.h" 2> ../headers/case_tbl.txt rm -f case.txt cat >../case.c << ENDOFTEXT /* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #include "headers/case.h" ENDOFTEXT echo " int XUtf8Tolower( int ucs) { int ret; " >>../case.c tables=`cat ../headers/case_tbl.txt` for line in ${tables} do tbl=`echo ${line} | cut -d']' -f1` bot=`echo ${line} | cut -d'_' -f3 | cut -d'[' -f1` eot=`echo ${line} | cut -d' ' -f2 | cut -d'+' -f2 | cut -d' ' -f1` echo "\ if (ucs <= 0x${eot}) { if (ucs >= 0x${bot}) { ret = ${tbl}ucs - 0x${bot}]; if (ret > 0) return ret; } return ucs; } " >>../case.c done echo " return ucs; } " >>../case.c fltk-1.4.3/src/xutf8/utils/README.txt0000644000175000017500000000054315004135251017312 0ustar albrechtalbrechttbl_gen.sh : shell script that convert unicode.org mappings tables to c headers. Also creates unicode2fontmap.c. conv_gen.c: create unicode2fontmap.c functions. convert_map.c: convert diffrent unicode.org mappings to a unique format. create_table.c: convert text files created by convert_map.c to to c tables. fltk-1.4.3/src/xutf8/utils/tbl_gen.sh0000755000175000017500000000767615004135251017603 0ustar albrechtalbrecht#!/bin/sh #/* # * generates ucs2fontmap.c and headers/*_.h # * # * Author: Jean-Marc Lienher ( http://oksid.ch ) # * Copyright 2000-2003 by O'ksi'D. # * # * This library is free software. Distribution and use rights are outlined in # * the file "COPYING" which should have been included with this file. If this # * file is missing or damaged, see the license at: # * # * https://www.fltk.org/COPYING.php # * # * Please see the following page on how to report bugs and issues: # * # * https://www.fltk.org/bugs.php # */ # # iso10646-1 encode="iso8859-1 iso8859-2 iso8859-3 \ iso8859-4 iso8859-5 iso8859-6 iso8859-7 iso8859-8 iso8859-9 \ iso8859-10 iso8859-13 iso8859-14 iso8859-15 \ koi8-1 big5-0 ksc5601.1987-0 gb2312.1980-0 jisx0201.1976-0 \ jisx0208.1983-0 jisx0212.1990-0 symbol dingbats" mkdir -p ../headers/ rm -f ../headers/* ucs2fontmap for enc in ${encode} do echo ${enc} case ${enc} in ksc5601.1987-0) # cat ../MAPPINGS/EASTASIA/KSC/KSC5601.TXT | \ cat ../MAPPINGS/EASTASIA/KSC/KSX1001.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; koi8-1) cat ../MAPPINGS/VENDORS/MISC/KOI8-R.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-14) cat ../MAPPINGS/ISO8859/8859-14.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-13) cat ../MAPPINGS/ISO8859/8859-13.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-5) cat ../MAPPINGS/ISO8859/8859-5.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-6) cat ../MAPPINGS/ISO8859/8859-6.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-1) cat ../MAPPINGS/ISO8859/8859-1.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-10) cat ../MAPPINGS/ISO8859/8859-10.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-15) cat ../MAPPINGS/ISO8859/8859-15.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-2) cat ../MAPPINGS/ISO8859/8859-2.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-3) cat ../MAPPINGS/ISO8859/8859-3.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-4) cat ../MAPPINGS/ISO8859/8859-4.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-7) cat ../MAPPINGS/ISO8859/8859-7.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-8) cat ../MAPPINGS/ISO8859/8859-8.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; iso8859-9) cat ../MAPPINGS/ISO8859/8859-9.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; dingbats) cat ../MAPPINGS/VENDORS/ADOBE/zdingbat.txt | \ ./convert_map "${enc}" > ${enc}.txt ;; symbol) cat ../MAPPINGS/VENDORS/ADOBE/symbol.txt | \ ./convert_map "${enc}" > ${enc}.txt ;; big5-0) cat ../MAPPINGS/EASTASIA/OTHER/BIG5.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; gb2312.1980-0) cat ../MAPPINGS/EASTASIA/GB/GB2312.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; jisx0212.1990-0) cat ../MAPPINGS/EASTASIA/JIS/JIS0212.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; jisx0208.1983-0) cat ../MAPPINGS/EASTASIA/JIS/JIS0208.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; jisx0201.1976-0) cat ../MAPPINGS/EASTASIA/JIS/JIS0201.TXT | \ ./convert_map "${enc}" > ${enc}.txt ;; esac nm=`echo ${enc} |tr '.' '_' | tr '-' '_'` cat ${enc}.txt | sort | uniq | \ ./create_table "${nm}" >> ../headers/${nm}_.h 2>> ../headers/tbl.txt rm -f ${enc}.txt enc=" " done cat > ../ucs2fontmap.c << ENDOFTEXT /* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ ENDOFTEXT he=`cd ..; ls headers/*.h` for hea in ${he} do echo "#include \"${hea}\"" >> ../ucs2fontmap.c done cat ../headers/tbl.txt | ./conv_gen >> ../ucs2fontmap.c fltk-1.4.3/src/xutf8/utils/INSTALL0000644000175000017500000000075315004135251016650 0ustar albrechtalbrecht Default install : tar -xvzf Xutf8.tar.gz cd Xutf8 ./configure --prefix=/usr su -c "make install" Install with tables generation : You must have a copy of http://www.unicode.org/Public/MAPPINGS/ in the ./MAPPINGS/ directory and a copy of UnicodeData-2.txt in ./ to generate the conversion tables. To add a table, edit utils/tbl_gen.sh and utils/convert_map.c. tar -xvzf Xutf8.tar.gz cd Xutf8 ./configure cd utils make cd .. su -c "make install" fltk-1.4.3/src/xutf8/utils/euc_tw.c0000644000175000017500000000250715004135251017250 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * generate the "if(){} else if ..." structure of ucs2fontmap() */ #include #include #include char uni[0x10000]; #include "../utf8Utils.c" int main(int argc, char **argv) { iconv_t cd; int i; cd = iconv_open("EUC-TW", "UTF16"); for(i = 0; i < 0x10000; i++) uni[i] = 0; for(i = 0x00000000; i < 0xFFFFFFFF; i++) { char buf[4], ob[6]; char *b = buf; int ucs = -1; int l1 = 4, l2 = 6; char *o = ob ; buf[0] = i & 0xff; buf[1] = (i >> 8) & 0xFF; buf[2] = (i >> 16) & 0xFF; buf[3] = (i >> 24) & 0xFF; iconv(cd, NULL, NULL, NULL, NULL); iconv(cd, &b, &l1, &o, &l2); if (l2 != 6) { ucs = (unsigned)ob[0]; ucs += (unsigned) (ob[1] << 8); /* XConvertUtf8ToUcs((unsigned char*)ob, 6 - l2, &ucs); */ printf ("%x --> %X\n", i, ucs & 0xFFFF); } } iconv_close(cd); return 0; } fltk-1.4.3/src/xutf8/utils/Makefile0000644000175000017500000000055415004135251017256 0ustar albrechtalbrechteuc_tw: euc_tw.c gcc euc_tw.c -o euc_tw all: convert_map create_table conv_gen ./tbl_gen.sh ./non_spacing.sh ./case.sh conv_gen: conv_gen.c gcc conv_gen.c -o conv_gen convert_map: convert_map.c gcc convert_map.c -o convert_map create_table: create_table.c gcc create_table.c -o create_table clean: rm -f *.o convert_map create_table conv_gen euc_tw fltk-1.4.3/src/xutf8/utils/conv_gen.c0000644000175000017500000000776415004135251017572 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * generate the "if(){} else if ..." structure of ucs2fontmap() */ #include #include char buffer[1000000]; int main(int argc, char **argv) { char buf[80]; int len; char *encode[256]; int encode_number = 0; unsigned int i = 0; unsigned char *ptr; unsigned char *lst = ""; size_t nb; int nbb = 0; len = fread(buffer, 1, 1000000, stdin); puts(" "); puts(" /*************** conv_gen.c ************/"); buffer[len] = '\0'; ptr = buffer; printf("const int ucs2fontmap" "(char *s, unsigned int ucs, int enc)\n"); printf("{\n"); printf(" switch(enc) {\n"); printf(" case 0:\n"); printf(" s[0] = (char) ((ucs & 0xFF00) >> 8);\n"); printf(" s[1] = (char) (ucs & 0xFF);\n"); printf(" return 0;"); while (len > 0) { unsigned char *p = ptr; unsigned char *f, *t; while (*p != ']') { i++; p++; } *(p - 1) = '\0'; *(p - 6) = '\0'; f = p - 5; while (*p != '+') { i++; p++;} p++; t = p; *(p + 4) = '\0'; if (strcmp(lst, ptr)) { encode_number++; encode[encode_number] = ptr; printf("\n break;"); printf("\n case %d:\n", encode_number); printf(" "); } else { printf(" else "); } lst = ptr; printf("if (ucs <= 0x%s) {\n", t); printf(" if (ucs >= 0x%s) {\n", f); if (*(f - 3) == '2') { printf(" int i = (ucs - 0x%s) * 2;\n", f); printf(" s[0] = %s_%s[i++];\n", ptr, f, f); printf(" s[1] = %s_%s[i];\n", ptr, f, f); printf(" if (s[0] || s[1]) return %d;\n", encode_number); } else { printf(" s[0] = 0;\n"); printf(" s[1] = %s_%s[ucs - 0x%s];\n", ptr, f, f); printf(" if (s[1]) return %d;\n", encode_number); } printf(" }\n"); printf(" }"); while (*ptr != '\n') { ptr++; len--; } ptr++; len--; } printf("\n break;\n"); printf("\n default:\n"); printf(" break;\n"); printf(" };\n"); printf(" return -1;\n"); printf("};\n\n"); printf("const int encoding_number(const char *enc)\n{\n"); printf(" if (!enc || !strcmp(enc, \"iso10646-1\")) {\n"); printf(" return 0;\n"); i = 1; while (i <= encode_number) { int l; char *ptr; l = strlen(encode[i]) - 3; ptr = encode[i] + l; *(ptr) = '\0'; ptr--; while (ptr != encode[i]) { if (*ptr == '_') { *ptr = '-'; ptr--; break; } ptr--; } while (ptr != encode[i]) { if (*ptr == '_') { *ptr = '.'; } ptr--; } printf(" } else if (!strcmp(enc, \"%s\")", encode[i] +11); if (!strcmp(encode[i] + 11, "big5-0")) { printf(" || !strcmp(enc, \"big5.eten-0\")"); } else if (!strcmp(encode[i] + 11, "dingbats")) { printf(" || !strcmp(enc, \"zapfdingbats\")"); printf(" || !strcmp(enc, \"zapf dingbats\")"); printf(" || !strcmp(enc, \"itc zapf dingbats\")"); } else if (!strcmp(encode[i] + 11, "jisx0208.1983-0")) { printf(" || !strcmp(enc, \"jisx0208.1990-0\")"); } printf(") {\n"); printf(" return %d;\n", i); i++; } printf(" };\n"); printf(" return -1;\n"); printf("};\n\n"); printf("/*\n"); printf("const char *encoding_name(int num)\n{\n"); printf(" switch (num) {\n"); i = 1; while (i <= encode_number) { printf(" case %d:\n", i); printf(" return \"%s\";\n", encode[i] + 11); i++; } printf(" };\n"); printf(" return \"iso10646-1\";\n"); printf("};\n\n"); printf("*/\n"); return 0; } fltk-1.4.3/src/xutf8/utils/non_spacing.sh0000755000175000017500000000371015004135251020450 0ustar albrechtalbrecht#!/bin/sh nopsc=`grep ';Mn;' ../UnicodeData-2.txt` IFS=" " #echo "# # List of non-spacing chars # # # Format: Three tab-separated columns # Column #1 is the non-spacing Unicode (in hex as 0xXXXX) # Column #2 is the spacing Unicode (in hex as 0xXXXX) # Column #3 the Unicode name (follows a comment sign, '#') # " > space.txt rm -f space.txt for line in ${nopsc} do ucs=`echo ${line} | cut -d\; -f1` name=`echo ${line} | cut -d\; -f2` space=`grep " 0020 ${ucs};" ../UnicodeData-2.txt` if test "X${space}" != X ;then tbl=`echo ${space} | cut -d\; -f1` # echo "0x${ucs} 0x${tbl} # ${name}" >> space.txt echo "/* U+${ucs} */ 0x${tbl}," >> space.txt else # echo "0x${ucs} 0x${ucs} # ${name}" >> space.txt echo "/* U+${ucs} */ 0x${ucs}," >> space.txt fi done unset nospc # echo "/* EOF */" >> space.txt cat space.txt | ./create_table "spacing" > "../headers/spacing.h" 2> ../headers/spacing_tbl.txt rm -f space.txt cat >../is_spacing.c << ENDOFTEXT /* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #include "headers/spacing.h" ENDOFTEXT echo " unsigned short XUtf8IsNonSpacing( unsigned int ucs) { " >>../is_spacing.c tables=`cat ../headers/spacing_tbl.txt` for line in ${tables} do tbl=`echo ${line} | cut -d']' -f1` bot=`echo ${line} | cut -d'_' -f3 | cut -d'[' -f1` eot=`echo ${line} | cut -d' ' -f2 | cut -d'+' -f2 | cut -d' ' -f1` echo "\ if (ucs <= 0x${eot}) { if (ucs >= 0x${bot}) return ${tbl}ucs - 0x${bot}]; return 0; } " >>../is_spacing.c done echo " return 0; } " >>../is_spacing.c fltk-1.4.3/src/xutf8/utils/convert_map.c0000644000175000017500000000763015004135251020301 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * read the http://www.unicode.org/Public/MAPPINGS/ and create something * usable in C. */ #include #include char buffer[1000000]; int JIS0208(unsigned char * ptr) { int i = 0; unsigned int fmap; unsigned int ucs; while(*ptr != '\t') { ptr++; i++; } ptr++; i++; *(ptr+6) = '\0'; fmap = (unsigned int)strtoul(ptr, NULL, 16); while(*ptr != '\0') { ptr++; i++; } i++; ptr++; *(ptr+6) = '\0'; ucs = (unsigned int)strtoul(ptr, NULL, 16); if (ucs) printf("/* U+%04X */ 0x%02X, 0x%02X,\n", ucs, (fmap & 0xFF00) >> 8, fmap & 0xFF); while(*ptr != '\0') { ptr++; i++; } i++; ptr++; while(*ptr != '\n') { ptr++; i++; } i++; return i; } int JIS0201(unsigned char * ptr) { int i = 0; unsigned int fmap; unsigned int ucs; *(ptr+4) = '\0'; fmap = (unsigned int)strtoul(ptr, NULL, 16); while(*ptr != '\0') { ptr++; i++; } i++; ptr++; *(ptr+6) = '\0'; ucs = (unsigned int)strtoul(ptr, NULL, 16); if (*(ptr + 1) != 'x') { printf("/* EOF */\n"); abort(); } if (ucs) printf("/* U+%04X */ 0x%02X,\n", ucs, (unsigned char)fmap); while(*ptr != '\0') { ptr++; i++; } i++; ptr++; while(*ptr != '\n') { ptr++; i++; } i++; return i; } int ADOBE(unsigned char * ptr) { int i = 0; unsigned int fmap; unsigned int ucs; *(ptr+4) = '\0'; ucs = (unsigned int)strtoul(ptr, NULL, 16); while(*ptr != '\0') { ptr++; i++; } i++; ptr++; *(ptr+2) = '\0'; fmap = (unsigned int)strtoul(ptr, NULL, 16); if (fmap < 1) { printf("/* EOF */\n"); abort(); } if (ucs) printf("/* U+%04X */ 0x%02X,\n", ucs, (unsigned char)fmap); while(*ptr != '\0') { ptr++; i++; } i++; ptr++; while(*ptr != '\n') { ptr++; i++; } i++; return i; } int JIS0212(unsigned char * ptr) { int i = 0; unsigned int fmap; unsigned int ucs; *(ptr+6) = '\0'; fmap = (unsigned int)strtoul(ptr, NULL, 16); ptr += 7; i += 7; while(*ptr == ' ') { ptr++; i++; } /* i++; ptr++; */ *(ptr+6) = '\0'; ucs = (unsigned int)strtoul(ptr, NULL, 16); if (*(ptr + 1) != 'x') { printf("/* EOF */\n"); abort(); } if (ucs) printf("/* U+%04X */ 0x%02X, 0x%02X,\n", ucs, (fmap & 0xFF00) >> 8, fmap & 0xFF); while(*ptr != '\0') { ptr++; i++; } i++; ptr++; while(*ptr != '\n') { ptr++; i++; } i++; return i; } int main(int argc, char **argv) { char buf[80]; int len; int i; unsigned char *ptr; size_t nb; len = fread(buffer, 1, 1000000, stdin); buffer[len] = '\0'; ptr = (unsigned char *)buffer; while (*ptr !='\n') {ptr++; len--;}; ptr++; len--; while (*ptr == '#') { while (*ptr !='\n') { ptr++; len--; } ptr++; len--; } while (len > 0) { nb = 0; if (!strcmp("jisx0208.1983-0", argv[1])) { nb = JIS0208(ptr); } else if (!strcmp("jisx0201.1976-0", argv[1])) { nb = JIS0201(ptr); } else if (!strcmp("jisx0212.1990-0", argv[1])) { nb = JIS0212(ptr); } else if (!strcmp("gb2312.1980-0", argv[1])) { nb = JIS0212(ptr); } else if (!strcmp("ksc5601.1987-0", argv[1])) { nb = JIS0212(ptr); } else if (!strcmp("big5-0", argv[1])) { nb = JIS0212(ptr); } else if (!strncmp("iso8859", argv[1], 7)) { nb = JIS0201(ptr); } else if (!strcmp("koi8-1", argv[1])) { nb = JIS0201(ptr); } else if (!strcmp("dingbats", argv[1]) || !strcmp("symbol", argv[1])) { nb = ADOBE(ptr); } else { len = 0; } ptr += nb; len = len - nb; } return 0; } fltk-1.4.3/src/xutf8/utils/create_table.c0000644000175000017500000000453315004135251020375 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #include #include char buffer[1000000]; /*** you can try to modifie this value to have better performences **/ #define MAX_DELTA 0x80 int main(int argc, char **argv) { char buf[80]; int len; unsigned int i = 0; unsigned char *ptr; size_t nb; int nbb = 0; len = fread(buffer, 1, 1000000, stdin); buffer[len] = '\0'; ptr = (unsigned char *)buffer; while (*ptr != '\n') ptr++; ptr++; while (*ptr != '\n') { if (*ptr == ',') nbb++; ptr++; } ptr = (unsigned char *)buffer; printf("/* %s */\n", argv[1]); while (len > 0) { unsigned int ucs = 0; char *p = ptr; char pp[20]; nb = 0; pp[0] = '\0'; while (*p != 'U') p++; strncat(pp, p, 6); *pp = '0'; *(pp+1) = 'x'; ucs = (unsigned int)strtoul(pp, NULL, 16);; if (ucs < 1) { printf("ERROR %d %d\n", len, ucs); abort(); } if (i != ucs - 1 || !i) { if ((ucs - i) > MAX_DELTA || !i) { if (i) { printf("};\n"); fprintf(stderr, "\t/* end: U+%04X */\n", i); } if (strcmp(argv[1], "spacing")) { printf("\nstatic const char unicode_to_%s_%db_%04X[] = {\n", argv[1], nbb, ucs); fprintf(stderr, "unicode_to_%s_%db_%04X[]; ", argv[1], nbb, ucs); } else { printf("\nstatic const unsigned short" " ucs_table_%04X[]" " = {\n", ucs); fprintf(stderr, "ucs_table_%04X[]; ", ucs); } } else { while (i < ucs - 1) { i++; if (nbb == 1) { printf("0x00,\n"); } else { printf("0x00, 0x00,\n"); } }; } } i = ucs; while (*ptr != '\n') { printf("%c", *ptr); ptr++; len--; } printf("\n"); ptr++; len--; } printf("};\n"); fprintf(stderr, "\t/* end: U+%04X */\n", i); return 0; } fltk-1.4.3/src/xutf8/utf8Input.c0000644000175000017500000002611215004135251016526 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * Copyright 2004-2021 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #include #if defined(FLTK_USE_X11) #include "../Xutf8.h" #include #include #include #include #include #ifdef HAVE_LIBC_ICONV #include #endif /* I haven't found much doc on the web about EUC encodings, so I've used GNU libiconv source code as a reference. http://clisp.cons.org/~haible/packages-libiconv.html */ #define RET_ILSEQ -1 #define RET_TOOFEW(x) (-10 - x) #define RET_TOOSMALL -2 #define conv_t void* #define ucs4_t unsigned int typedef struct { unsigned short indx; unsigned short used; } Summary16; #ifndef X_HAVE_UTF8_STRING #define NEED_TOWC /* indicates what part of these include files is needed here (avoid compilation warnings) */ #include "lcUniConv/big5.h" #include "lcUniConv/gb2312.h" #include "lcUniConv/cp936ext.h" #include "lcUniConv/jisx0201.h" #include "lcUniConv/jisx0208.h" #include "lcUniConv/jisx0212.h" #include "lcUniConv/ksc5601.h" static int XConvertEucTwToUtf8(char* buffer_return, int len) { /* FIXME */ #ifdef HAVE_LIBC_ICONV iconv_t cd; int cdl; #else int i = 0; #endif int l = 0; char *buf; /* , *b; */ if (len < 1) return 0; /*b = */ buf = (char*) malloc((unsigned)len); memcpy(buf, buffer_return, (unsigned) len); #ifdef HAVE_LIBC_ICONV l = cdl = len; cd = iconv_open("EUC-TW", "UTF-8"); iconv(cd, &b, &len, &buffer_return, &cdl); iconv_close(cd); l -= cdl; #else while (i < len) { unsigned int ucs; unsigned char c; c = (unsigned char) buf[i]; if (c < 0x80) { ucs = c; i++; } else if (c >= 0xa1 && c < 0xff && len - i > 1 ) { #if 0 unsigned char b[2]; b[0] = (unsigned char) c - 0x80; b[1] = (unsigned char) buf[i + 1] - 0x80; #endif ucs = ' '; i += 2; } else if (c == 0x8e && len - i > 3) { unsigned char c1 = buf[i + 1]; unsigned char c2 = buf[i + 2]; unsigned char c3 = buf[i + 3]; #if 0 unsigned char b[2]; b[0] = (unsigned char) buf[i + 2] - 0x80; b[1] = (unsigned char) buf[i + 3] - 0x80; #endif if (c1 >= 0xa1 && c1 <= 0xb0) { if (c2 >= 0xa1 && c2 < 0xff && c3 >= 0xa1 && c3 < 0xff) { ucs = ' '; i += 4; } else { ucs = '?'; i++; } } else { ucs = '?'; i++; } } else { ucs = '?'; i++; } l += XConvertUcsToUtf8(ucs, buffer_return + l); } #endif free(buf); return l; } static int XConvertEucKrToUtf8(char* buffer_return, int len) { int i = 0, l = 0; char *buf; if (len < 1) return 0; buf = (char*) malloc((unsigned)len); memcpy(buf, buffer_return, (unsigned)len); while (i < len) { unsigned int ucs; unsigned char c, c1; c = (unsigned char) buf[i]; if (c < 0x80) { ucs = c; i++; } else if (c >= 0xA1 && c < 0xFF && len - i > 1) { c1 = (unsigned char) buf[i + 1]; if (c1 >= 0xa1 && c1 < 0xff) { unsigned char b[2]; b[0] = c - 0x80; b[1] = c1 - 0x80; if (ksc5601_mbtowc(NULL, &ucs, b, 2) < 1) { ucs = '?'; } } else { ucs = '?'; } i += 2; } else { ucs = '?'; i++; } l += XConvertUcsToUtf8(ucs, buffer_return + l); } free(buf); return l; } static int XConvertBig5ToUtf8(char* buffer_return, int len) { int i = 0, l = 0; char *buf; if (len < 1) return 0; buf = (char*) malloc((unsigned)len); memcpy(buf, buffer_return, (unsigned)len); if (len == 1) { l += XConvertUcsToUtf8((unsigned int)buf[i], buffer_return + l); } while (i + 1 < len) { unsigned int ucs; unsigned char b[2]; b[0] = (unsigned char) buf[i]; b[1] = (unsigned char) buf[i + 1]; if (big5_mbtowc(NULL, &ucs, b, 2) == 2) { i += 2; } else { ucs = '?'; i++; } l += XConvertUcsToUtf8(ucs, buffer_return + l); } free(buf); return l; } static int XConvertCp936extToUtf8(char* buffer_return, int len) { int i = 0, l = 0; char *buf; if (len < 1) return 0; buf = (char*) malloc((unsigned)len); memcpy(buf, buffer_return, (unsigned)len); if (len == 1) { l += XConvertUcsToUtf8((unsigned int)buf[i], buffer_return + l); } while (i + 1 < len) { unsigned int ucs; unsigned char b[2]; b[0] = (unsigned char) buf[i]; b[1] = (unsigned char) buf[i + 1]; if (cp936ext_mbtowc(NULL, &ucs, b, 2) == 2) { i += 2; } else { if ( b[0] < 0x80) { ucs = b[0]; }else{ ucs = '?'; } i++; } l += XConvertUcsToUtf8(ucs, buffer_return + l); } if(i + 1 == len) { l += XConvertUcsToUtf8((unsigned int)buf[i], buffer_return + l); } free(buf); return l; } static int XConvertGb2312ToUtf8(char* buffer_return, int len) { int i = 0, l = 0; char *buf; if (len < 1) return 0; buf = (char*) malloc((unsigned)len); memcpy(buf, buffer_return, (unsigned)len); if (len == 1) { l += XConvertUcsToUtf8((unsigned int)buf[i], buffer_return + l); } while (i + 1 < len) { unsigned int ucs; unsigned char b[2]; b[0] = (unsigned char) buf[i]; b[1] = (unsigned char) buf[i + 1]; if ( b[0] < 0x80 ) { ucs = b[0]; i++; } else if (gb2312_mbtowc(NULL, &ucs, b, 2) == 2) { i += 2; } else { ucs = '?'; i++; } l += XConvertUcsToUtf8(ucs, buffer_return + l); } if (i + 1 == len) { l += XConvertUcsToUtf8((unsigned int)buf[i], buffer_return + l); } free(buf); return l; } static int XConvertEucCnToUtf8(char* buffer_return, int len) { int i = 0, l = 0; char *buf; if (len < 1) return 0; buf = (char*) malloc((unsigned)len); memcpy(buf, buffer_return, (unsigned)len); while (i < len) { unsigned int ucs; unsigned char c, c1; c = (unsigned char) buf[i]; if (c < 0x80) { ucs = c; i++; } else if (c >= 0xA1 && c < 0xFF && len - i > 1) { c1 = (unsigned char) buf[i + 1]; if (c1 >= 0xa1 && c1 < 0xff) { unsigned char b[2]; b[0] = (unsigned char) c; b[1] = (unsigned char) c1; if (gb2312_mbtowc(NULL, &ucs, b, 2) < 1) { ucs = '?'; } } else { ucs = '?'; } i += 2; } else { ucs = '?'; i++; } l += XConvertUcsToUtf8(ucs, buffer_return + l); } free(buf); return l; } static int XConvertEucJpToUtf8(char* buffer_return, int len) { int i = 0, l = 0; char *buf; if (len < 1) return 0; buf = (char*) malloc((unsigned)len); memcpy(buf, buffer_return, (unsigned)len); while (i < len) { unsigned int ucs; unsigned char c, c1; c = (unsigned char) buf[i]; if (c < 0x80) { ucs = c; i++; } else if (c >= 0xA1 && c < 0xFF && len - i > 1) { c1 = (unsigned char) buf[i + 1]; if (c < 0xF5 && c1 >= 0xa1) { unsigned char b[2]; b[0] = c - 0x80; b[1] = c1 - 0x80; if (jisx0208_mbtowc(NULL, &ucs, b, 2) < 1) { ucs = '?'; } } else if (c1 >= 0xA1 && c1 < 0xFF) { ucs = 0xE000 + 94 * (c - 0xF5) + (c1 - 0xA1); } else { ucs = '?'; } i += 2; } else if (c == 0x8E && len - i > 1) { c1 = (unsigned char) buf[i + 1]; if (c1 >= 0xa1 && c1 <= 0xe0) { if (jisx0201_mbtowc(NULL, &ucs, &c1, 1) != 1) { ucs = '?'; } } else { ucs = '?'; } i += 2; } else if (c == 0x8F && len - i > 2) { c = (unsigned char) buf[i + 1]; c1 = (unsigned char) buf[i + 2]; if (c >= 0xa1 && c < 0xff) { if (c < 0xf5 && c1 >= 0xa1 && c1 < 0xff) { unsigned char b[2]; b[0] = c - 0x80; b[1] = c1 - 0x80; if (jisx0212_mbtowc(NULL, &ucs, b, 2) < 1) { ucs = '?'; } } else { ucs = '?'; } } else { if (c1 >= 0xa1 && c1 < 0xff) { ucs = 0xe3ac + 94 * (c - 0xF5) + (c1 - 0xA1); } else { ucs = '?'; } } i += 3; } else { ucs = '?'; i++; } l += XConvertUcsToUtf8(ucs, buffer_return + l); } free(buf); return l; } static int XConvertEucToUtf8(const char* locale, char* buffer_return, int len, int bytes_buffer) { /* if (!locale) { */ /* if (!locale || strstr(locale, "UTF") || strstr(locale, "utf")) { */ if (!locale || strstr(locale, "UTF") || strstr(locale, "utf")) { return len; } if (strstr(locale, "ja")) { return XConvertEucJpToUtf8(buffer_return, len); } else if (strstr(locale, "Big5") || strstr(locale, "big5")) { /* BIG5 */ return XConvertBig5ToUtf8(buffer_return, len); } else if (strstr(locale, "GBK") || strstr(locale, "gbk")) { return XConvertCp936extToUtf8(buffer_return, len); } else if (strstr(locale, "zh") || strstr(locale, "chinese-")) { if (strstr(locale, "TW") || strstr(locale, "chinese-t")) { if (strstr(locale, "EUC") || strstr(locale, "euc") || strstr(locale, "chinese-t")) { return XConvertEucTwToUtf8(buffer_return, len); } return XConvertBig5ToUtf8(buffer_return, len); } if (strstr(locale, "EUC") || strstr(locale, "euc")) { return XConvertEucCnToUtf8(buffer_return, len); } return XConvertGb2312ToUtf8(buffer_return, len); } else if (strstr(locale, "ko")) { return XConvertEucKrToUtf8(buffer_return, len); } return len; } int XUtf8LookupString(XIC ic, XKeyPressedEvent* event, char* buffer_return, int bytes_buffer, KeySym* keysym, Status* status_return) { long ucs = -1; int len; len = XmbLookupString(ic, event, buffer_return, bytes_buffer / 5, keysym, status_return); if (*status_return == XBufferOverflow) { return len * 5; } if (*keysym > 0 && *keysym < 0x100 && len == 1) { if (*keysym < 0x80) { ucs = (unsigned char)buffer_return[0]; } else { ucs = (long)*keysym; } } else if (((*keysym >= 0x100 && *keysym <= 0xf000) || (*keysym & 0xff000000U) == 0x01000000)) { ucs = XKeysymToUcs(*keysym); } else { ucs = -2; } if (ucs > 0) { len = XConvertUcsToUtf8((unsigned)ucs, (char *)buffer_return); } else if (len > 0) { XIM im; if (!ic) return 0; im = XIMOfIC(ic); if (!im) return 0; len = XConvertEucToUtf8(XLocaleOfIM(im), buffer_return, len, bytes_buffer); } return len; } #endif /* X11 has UTF-8 */ #endif /* X11 only */ fltk-1.4.3/src/xutf8/README.txt0000644000175000017500000000200515004135251016145 0ustar albrechtalbrecht--------------------------------------------------------------------------- Important note: this file is outdated (as of FLTK 1.3.x, 2012 and later). Many things have been changed meanwhile. Use all information with care! --------------------------------------------------------------------------- supported encodings : --------------------- iso10646-1 iso8859-1 iso8859-2 iso8859-3 iso8859-4 iso8859-5 iso8859-6 iso8859-7 iso8859-8 iso8859-9 iso8859-10 iso8859-11 iso8859-13 iso8859-14 iso8859-15 koi8-r koi8-u big5-0 gbk gb2312.1980-0 jisx0201.1976-0 jisx0208.1983-0 jisx0212.1990-0 ksc5601.1987-0 symbol dingbats ORIGINAL FILES : ================ The directory lcUniConv is copied from the xfree project cvs system. ( export CVS_RSH=ssh export CVSROOT=anoncvs@anoncvs.xfree86.org:/cvs cvs checkout xc/lib/X11/lcUniConv password: anoncvs ) The file imKStoUCS.c is copied from the xfree project cvs system. ( export CVS_RSH=ssh export CVSROOT=anoncvs@anoncvs.xfree86.org:/cvs cvs checkout xc/lib/X11 password: anoncvs ) fltk-1.4.3/src/xutf8/ucs2fontmap.c0000644000175000017500000002332515004135251017064 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #include #include #define RET_ILSEQ -1 #define RET_TOOFEW(x) (-10 - x) #define RET_TOOSMALL -2 #define conv_t void* #define ucs4_t unsigned int typedef struct { unsigned short indx; unsigned short used; } Summary16; #define NEED_TOMB /* indicates what part of these include files is needed here (avoid compilation warnings) */ #include "lcUniConv/cp936ext.h" #include "lcUniConv/big5.h" #include "lcUniConv/gb2312.h" #include "lcUniConv/iso8859_10.h" #include "lcUniConv/iso8859_11.h" #include "lcUniConv/iso8859_13.h" #include "lcUniConv/iso8859_14.h" #include "lcUniConv/iso8859_15.h" #include "lcUniConv/iso8859_2.h" #include "lcUniConv/iso8859_3.h" #include "lcUniConv/iso8859_4.h" #include "lcUniConv/iso8859_5.h" #include "lcUniConv/iso8859_6.h" #include "lcUniConv/iso8859_7.h" #include "lcUniConv/iso8859_8.h" #include "lcUniConv/iso8859_9.h" #include "lcUniConv/jisx0201.h" #include "lcUniConv/jisx0208.h" #include "lcUniConv/jisx0212.h" #include "lcUniConv/koi8_r.h" #include "lcUniConv/koi8_u.h" #include "lcUniConv/ksc5601.h" #include "lcUniConv/cp1251.h" #include "headers/symbol_.h" #include "headers/dingbats_.h" /*************** conv_gen.c ************/ /*const*/ static int ucs2fontmap(char *s, unsigned int ucs, int enc) { switch(enc) { case 0: /* iso10646-1 */ s[0] = (char) ((ucs & 0xFF00) >> 8); s[1] = (char) (ucs & 0xFF); return 0; case 1: /* iso8859-1 */ if (ucs <= 0x00FF) { if (ucs >= 0x0001) { s[0] = 0; s[1] = (char) (ucs & 0xFF); return 1; } } break; case 2: /* iso8859-2 */ if (ucs <= 0x00a0) { s[0] = 0; s[1] = (char) ucs; return 2; } else if (ucs < 0x0180) { if (ucs >= 0x00a0) { s[0] = 0; s[1] = (char) iso8859_2_page00[ucs-0x00a0]; if (s[1]) return 2; } } else if (ucs < 0x02e0) { if (ucs >= 0x02c0) { s[0] = 0; s[1] = (char) iso8859_2_page02[ucs-0x02c0]; if (s[1]) return 2; } } break; case 3: /* iso8859-3 */ if (iso8859_3_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 3; } break; case 4: /* iso8859-4 */ if (iso8859_4_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 4; } break; case 5: /* iso8859-5 */ if (iso8859_5_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 5; } break; case 6: /* iso8859-6 */ if (iso8859_6_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 6; } break; case 7: /* iso8859-7 */ if (iso8859_7_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 7; } break; case 8: /* iso8859-8 */ if (iso8859_8_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 8; } break; case 9: /* iso8859-9 */ if (iso8859_9_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 9; } break; case 10: /* iso8859-10 */ if (iso8859_10_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 10; } break; case 25: /* iso8859-11 */ if (iso8859_11_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 25; } break; case 11: /* iso8859-13 */ if (iso8859_13_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 11; } break; case 12: /* iso8859-14 */ if (iso8859_14_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 12; } break; case 13: /* iso8859-15 */ if (iso8859_15_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 13; } break; case 14: /* koi8-r */ if (koi8_r_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 14; } break; case 15: /* big5 */ if (big5_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 15; } break; case 16: /* ksc5601.1987-0 */ if (ksc5601_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 16; } break; case 17: /* gb2312.1980-0 */ if (gb2312_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 17; } break; case 18: /* jisx0201.1976-0 */ if (jisx0201_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 18; } break; case 19: /* jisx0208.1983-0 */ if (jisx0208_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 19; } break; case 20: /* jisx0212.1990-0 */ if (jisx0212_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 20; } break; case 21: /* symbol */ if (ucs <= 0x00F7) { if (ucs >= 0x0020) { s[0] = 0; s[1] = unicode_to_symbol_1b_0020[ucs - 0x0020]; if (s[1]) return 21; } } else if (ucs <= 0x0192) { if (ucs >= 0x0192) { s[0] = 0; s[1] = unicode_to_symbol_1b_0192[ucs - 0x0192]; if (s[1]) return 21; } } else if (ucs <= 0x03D6) { if (ucs >= 0x0391) { s[0] = 0; s[1] = unicode_to_symbol_1b_0391[ucs - 0x0391]; if (s[1]) return 21; } } else if (ucs <= 0x232A) { if (ucs >= 0x2022) { s[0] = 0; s[1] = unicode_to_symbol_1b_2022[ucs - 0x2022]; if (s[1]) return 21; } } else if (ucs <= 0x25CA) { if (ucs >= 0x25CA) { s[0] = 0; s[1] = unicode_to_symbol_1b_25CA[ucs - 0x25CA]; if (s[1]) return 21; } } else if (ucs <= 0x2666) { if (ucs >= 0x2660) { s[0] = 0; s[1] = unicode_to_symbol_1b_2660[ucs - 0x2660]; if (s[1]) return 21; } } else if (ucs <= 0xF6DB) { if (ucs >= 0xF6D9) { s[0] = 0; s[1] = unicode_to_symbol_1b_F6D9[ucs - 0xF6D9]; if (s[1]) return 21; } } else if (ucs <= 0xF8FE) { if (ucs >= 0xF8E5) { s[0] = 0; s[1] = unicode_to_symbol_1b_F8E5[ucs - 0xF8E5]; if (s[1]) return 21; } } break; case 22: /* dingbats */ if (ucs <= 0x00A0) { if (ucs >= 0x0020) { s[0] = 0; s[1] = unicode_to_dingbats_1b_0020[ucs - 0x0020]; if (s[1]) return 22; } } else if (ucs <= 0x2195) { if (ucs >= 0x2192) { s[0] = 0; s[1] = unicode_to_dingbats_1b_2192[ucs - 0x2192]; if (s[1]) return 22; } } else if (ucs <= 0x2469) { if (ucs >= 0x2460) { s[0] = 0; s[1] = unicode_to_dingbats_1b_2460[ucs - 0x2460]; if (s[1]) return 22; } } else if (ucs <= 0x2666) { if (ucs >= 0x25A0) { s[0] = 0; s[1] = unicode_to_dingbats_1b_25A0[ucs - 0x25A0]; if (s[1]) return 22; } } else if (ucs <= 0x27BE) { if (ucs >= 0x2701) { s[0] = 0; s[1] = unicode_to_dingbats_1b_2701[ucs - 0x2701]; if (s[1]) return 22; } } else if (ucs <= 0xF8E4) { if (ucs >= 0xF8D7) { s[0] = 0; s[1] = unicode_to_dingbats_1b_F8D7[ucs - 0xF8D7]; if (s[1]) return 22; } } break; case 23: /* koi8-u */ if (koi8_u_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 23; } break; case 24: /* microsoft-cp1251 */ if (cp1251_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 24; } break; case 26: /* gbk/cp936ext */ if (cp936ext_wctomb(NULL, (unsigned char*)s, ucs, 2) > 0) { return 26; } break; default: break; }; return -1; } /*const*/ static int encoding_number(const char *enc) { if (!enc || !strncmp(enc, "iso10646-1", 10)) { return 0; } else if (!strcmp(enc, "iso8859-1")) { return 1; } else if (!strcmp(enc, "iso8859-2")) { return 2; } else if (!strcmp(enc, "iso8859-3")) { return 3; } else if (!strcmp(enc, "iso8859-4")) { return 4; } else if (!strcmp(enc, "iso8859-5")) { return 5; } else if (!strcmp(enc, "iso8859-6")) { return 6; } else if (!strcmp(enc, "iso8859-7")) { return 7; } else if (!strcmp(enc, "iso8859-8")) { return 8; } else if (!strcmp(enc, "iso8859-9")) { return 9; } else if (!strcmp(enc, "iso8859-10")) { return 10; } else if (!strcmp(enc, "iso8859-13")) { return 11; } else if (!strcmp(enc, "iso8859-14")) { return 12; } else if (!strcmp(enc, "iso8859-15")) { return 13; } else if (!strcmp(enc, "koi8-r")) { return 14; } else if (!strcmp(enc, "big5-0") || !strcmp(enc, "big5.eten-0") || !strcmp(enc, "big5p-0")) { return 15; } else if (!strcmp(enc, "ksc5601.1987-0")) { return 16; } else if (!strcmp(enc, "gb2312.1980-0") || !strcmp(enc, "gb2312.80-0") || !strcmp(enc, "gb2312.80&gb8565.88") || !strcmp(enc, "gb2312.80-0")) { return 17; } else if (!strcmp(enc, "jisx0201.1976-0")) { return 18; } else if (!strcmp(enc, "jisx0208.1983-0") || !strcmp(enc, "jisx0208.1990-0") || !strcmp(enc, "jisx0208.1978-0")) { return 19; } else if (!strcmp(enc, "jisx0212.1990-0")) { return 20; } else if (!strcmp(enc, "symbol")) { return 21; } else if (!strcmp(enc, "dingbats") || !strcmp(enc, "zapfdingbats") || !strcmp(enc, "zapf dingbats") || !strcmp(enc, "itc zapf dingbats")) { return 22; } else if (!strcmp(enc, "koi8-u")) { return 23; } else if (!strcmp(enc, "microsoft-cp1251")) { return 24; } else if (!strcmp(enc, "iso8859-11")) { return 25; } else if (!strcmp(enc, "gbk-0") || !strcmp(enc, "cp936") || !strcmp(enc, "gbk")) { return 26; }; return -1; } fltk-1.4.3/src/xutf8/test.c0000644000175000017500000002075615004135251015607 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * UTF-8 X test program (It contains MINIMAL code to support XIM !!!) * **************** * To test it do: **************** kinput2 -canna XMODIFIERS="@im=kinput2"; export XMODIFIERS LANG=ja_JP; export LANG ./test to open a conversion window press "Shift space" type some keys. press space. select glyph with arrows keys. press return. press return. press "Shift space" to close the window LANG=ar_AE; export LANG LANG=he_IL; export LANG export LANG=ja_JP; export XMODIFIERS="@im=kinput2" export LANG=ja_JP; export XMODIFIERS="@im=nicolatter" export LANG=ja_JP; export XMODIFIERS="@im=jmode" export LANG=ja_JP; export XMODIFIERS="@im=htt" export LANG=ko_KR; export XMODIFIERS="@im=Ami" export LANG=zh_TW; export XMODIFIERS="@im=xcin-zh_TW" export LANG=zh_TW; export XMODIFIERS="@im=xcin-zh_CN" export LANG=C; export XMODIFIERS="@im=interxim" **********************************************************/ #include #include #include #include #include "Xutf8.h" #include #include #include #include #include #include char *jp_txt = "é UTF-8 e\xCC\x82=\xC3\xAA" " \357\274\270\357\274\254\357\274\246\357\274" "\244\345\220\215\343\201\247\346\214\207 \345\256\232" "\343\201\231\343\202\213"; char *rtl_txt = "->e\xCC\x82=\xC3\xAA"; XIM xim_im = NULL; XIC xim_ic = NULL; static XIMStyles* xim_styles = NULL; XUtf8FontStruct *fontset; GC gc; int x = 2; int y = 40; int main(int argc, char**argv) { char **missing_charset_list; int missing_charset_count; XGCValues xgcv; unsigned long mask; Display* dpy; int scr; Window w, root; XSetWindowAttributes set_attr; int i; XIMStyle *style; static char buf[128]; KeySym keysym = 0; Status status; XWMHints wm_hints; XClassHint class_hints; XIMStyle input_style = 0; char **font_name_list; char *def_string; XFontStruct **font_struct_list; char **font_encoding_list; int nb_font; int len = 0; int no_xim = 0; printf ("A -> %c \n", XUtf8Tolower('A')); if (!setlocale(LC_ALL, "")) puts("locale not supported by C library, locale unchanged"); if (!XSetLocaleModifiers("")) puts("X locale modifiers not supported, using default"); dpy = XOpenDisplay(0); if (!dpy) { puts("cannot open display.\n"); exit(-1); } scr = DefaultScreen(dpy); root = RootWindow(dpy, scr); set_attr.event_mask = KeyPressMask|FocusChangeMask; set_attr.background_pixel = WhitePixel(dpy, DefaultScreen(dpy)); set_attr.border_pixel = BlackPixel(dpy, DefaultScreen(dpy)); w = XCreateWindow(dpy, root, 10,10,200,100,0, DefaultDepth(dpy, DefaultScreen(dpy)), InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)), CWEventMask | CWBackPixel | CWBorderPixel, &set_attr); if (!w) { puts("cannot creat window.\n"); exit(-1); } class_hints.res_name = "test"; class_hints.res_class = "Test"; wm_hints.input = True; wm_hints.flags = InputHint; XmbSetWMProperties(dpy, w, "test", "test", NULL, 0, NULL, &wm_hints, &class_hints); XMapWindow(dpy, w); xim_im = XOpenIM(dpy, NULL, "test", "Test"); if (!xim_im) { puts("cannot Open Input Manager: Try default.\n"); XSetLocaleModifiers("@im="); xim_im = XOpenIM(dpy, NULL, "test", "Test"); if (!xim_im) { puts("Failed exiting.\n"); exit(-1); } } XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL); for (i = 0, style = xim_styles->supported_styles; i < xim_styles->count_styles; i++, style++) { if (i == 0 && *style == (XIMStatusNone|XIMPreeditNone)) { printf("this is not a XIM server !!!\n"); no_xim = 1; } printf("input style : 0x%X\n", *style); } xim_ic = XCreateIC(xim_im, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, w, XNFocusWindow, w, NULL); if (!xim_ic) { puts("cannot create Input Context.\n"); exit(-1); } XFree(xim_styles); XSetICFocus(xim_ic); /*************************************************************** * I don't recommend to use a font base name list similar * to the following one in a real application ;-) * You should use an iso8859-1 font, plus a single font for * your language. ***************************************************************/ fontset = XCreateUtf8FontStruct(dpy, "-*-*-*-*-*-*-*-*-*-*-*-*-iso8858-3," /* not valid */ "-*-*-medium-r-*-*-*-*-*-*-*-*-iso8859-1," "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-6," "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-8," "-*-*-*-*-*-*-*-*-*-*-*-*-ksc5601.1987-0," "-*-symbol-*-*-*-*-*-*-*-*-*-*-adobe-fontspecific," "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-2," "-*-*-*-*-*-*-*-*-*-*-*-*-koi8-1," "-*-*-*-*-*-*-*-*-*-*-*-*-jisx0208.1983-0," "-*-*-*-*-*-*-*-*-*-*-*-*-jisx0212.1990-0," "-*-*-*-*-*-*-*-*-*-*-*-*-big5-0," "-*-*-*-*-*-*-*-*-*-*-*-*-jisx0201.1976-0," "-*-unifont-*-*-*-*-*-*-*-*-*-*-iso10646-1[0x300 0x400_0x500]," "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"); /* THIS PART IS NOT REQUIERED */ nb_font = fontset->nb_font; while (nb_font > 0) { nb_font--; if (fontset->fonts[nb_font]) { printf("encoding=\"\" fid=%d \n %s\n", /* fontset->encodings[nb_font], */ fontset->fonts[nb_font]->fid, fontset->font_name_list[nb_font]); } } /* END OF NOT REQUIERED PART*/ mask = (GCForeground | GCBackground); xgcv.foreground = BlackPixel(dpy, DefaultScreen(dpy)); xgcv.background = WhitePixel(dpy, DefaultScreen(dpy)); gc = XCreateGC(dpy, w, mask, &xgcv); if (!gc) { puts("cannot create Graphic Context.\n"); exit(-1); } /***************************************************************/ while (1) { int filtered; static XEvent xevent; static XVaNestedList list1 = 0; int r; XNextEvent(dpy, &xevent); if (xevent.type == KeyPress) { XKeyEvent *e = (XKeyEvent*) &xevent; printf ("0x%X %d\n", e->state, e->keycode); } if (xevent.type == DestroyNotify) { /* XIM server has crashed */ no_xim = 1; XSetLocaleModifiers("@im="); xim_im = XOpenIM(dpy, NULL, "test", "Test"); if (xim_im) { xim_ic = XCreateIC(xim_im, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, w, XNFocusWindow, w, NULL); } else { xim_ic = NULL; } if (!xim_ic) { puts("Crash recovery failed. exiting.\n"); exit(-1); } } if (xevent.type != DestroyNotify) { filtered = XFilterEvent(&xevent, 0); } if (xevent.type == FocusOut && xim_ic) XUnsetICFocus(xim_ic); if (xevent.type == FocusIn && xim_ic) XSetICFocus(xim_ic); if (xevent.type == KeyPress && !filtered) { len = XUtf8LookupString(xim_ic, &xevent.xkey, buf, 127, &keysym, &status); if (len == 1 && buf[0] == '\b') { x -= XUtf8TextWidth(fontset, buf, len); XUtf8DrawImageString(dpy, w, fontset, gc, x, y, buf, len); } else if (len == 1 && buf[0] == '\r') { y += fontset->ascent + fontset->descent; x = 0; XCloseIM(xim_im); } else { XUtf8DrawImageString(dpy, w, fontset, gc, x, y, buf, len); x += XUtf8TextWidth(fontset, buf, len); } XUtf8DrawString(dpy, w, fontset, gc, 0, 20, jp_txt, strlen(jp_txt)); XUtf8DrawString(dpy, w, fontset, gc, 50, 90, rtl_txt, strlen(rtl_txt)); XUtf8DrawRtlString(dpy, w, fontset, gc, 50, 90, rtl_txt, strlen(rtl_txt)); buf[len] = 0; printf("'%s' %d %x\n", buf, keysym, keysym); buf[0] = 0; } if (filtered) { printf("Dead key\n"); } } XFreeUtf8FontStruct(dpy, fontset); return 0; } fltk-1.4.3/src/xutf8/keysym2Ucs.c0000644000175000017500000000110115004135251016665 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #include "../Xutf8.h" #include "imKStoUCS.c" long XKeysymToUcs(KeySym keysym) { return (long) KeySymToUcs4(keysym); } fltk-1.4.3/src/xutf8/utf8Utils.c0000644000175000017500000001443115004135251016530 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * Unicode to UTF-8 conversion functions. * * This file is compiled and linked only for X11 w/o Xft. */ #include "../Xutf8.h" /*** NOTE : all functions are LIMITED to 24 bits Unicode values !!! ***/ /* * Converts the first char of the UTF-8 string to an Unicode value * Returns the byte length of the converted UTF-8 char * Returns -1 if the UTF-8 string is not valid */ int XConvertUtf8ToUcs(const unsigned char *buf, int len, unsigned int *ucs) { if (buf[0] & 0x80) { if (buf[0] & 0x40) { if (buf[0] & 0x20) { if (buf[0] & 0x10) { if (buf[0] & 0x08) { if (buf[0] & 0x04) { if (buf[0] & 0x02) { /* bad UTF-8 string */ } else { /* 0x04000000 - 0x7FFFFFFF */ } } else if (len > 4 && (buf[1] & 0xC0) == 0x80 && (buf[2] & 0xC0) == 0x80 && (buf[3] & 0xC0) == 0x80 && (buf[4] & 0xC0) == 0x80) { /* 0x00200000 - 0x03FFFFFF */ *ucs = ((buf[0] & ~0xF8) << 24) + ((buf[1] & ~0x80) << 18) + ((buf[2] & ~0x80) << 12) + ((buf[3] & ~0x80) << 6) + (buf[4] & ~0x80); if (*ucs > 0x001FFFFF && *ucs < 0x01000000) return 5; } } else if (len > 3 && (buf[1] & 0xC0) == 0x80 && (buf[2] & 0xC0) == 0x80 && (buf[3] & 0xC0) == 0x80) { /* 0x00010000 - 0x001FFFFF */ *ucs = ((buf[0] & ~0xF0) << 18) + ((buf[1] & ~0x80) << 12) + ((buf[2] & ~0x80) << 6) + (buf[3] & ~0x80); if (*ucs > 0x0000FFFF) return 4; } } else if (len > 2 && (buf[1] & 0xC0) == 0x80 && (buf[2] & 0xC0) == 0x80) { /* 0x00000800 - 0x0000FFFF */ *ucs = ((buf[0] & ~0xE0) << 12) + ((buf[1] & ~0x80) << 6) + (buf[2] & ~0x80); if (*ucs > 0x000007FF) return 3; } } else if (len > 1 && (buf[1] & 0xC0) == 0x80) { /* 0x00000080 - 0x000007FF */ *ucs = ((buf[0] & ~0xC0) << 6) + (buf[1] & ~0x80); if (*ucs > 0x0000007F) return 2; } } } else if (len > 0) { /* 0x00000000 - 0x0000007F */ *ucs = buf[0]; return 1; } *ucs = (unsigned int) '?'; /* bad UTF-8 string */ return -1; } /* * Converts an Unicode value to an UTF-8 string * NOTE : the buffer (buf) must be at least 5 bytes long !!! */ int XConvertUcsToUtf8(unsigned int ucs, char *buf) { if (ucs < 0x000080) { buf[0] = ucs; return 1; } else if (ucs < 0x000800) { buf[0] = 0xC0 | (ucs >> 6); buf[1] = 0x80 | (ucs & 0x3F); return 2; } else if (ucs < 0x010000) { buf[0] = 0xE0 | (ucs >> 12); buf[1] = 0x80 | ((ucs >> 6) & 0x3F); buf[2] = 0x80 | (ucs & 0x3F); return 3; } else if (ucs < 0x00200000) { buf[0] = 0xF0 | (ucs >> 18); buf[1] = 0x80 | ((ucs >> 12) & 0x3F); buf[2] = 0x80 | ((ucs >> 6) & 0x3F); buf[3] = 0x80 | (ucs & 0x3F); return 4; } else if (ucs < 0x01000000) { buf[0] = 0xF8 | (ucs >> 24); buf[1] = 0x80 | ((ucs >> 18) & 0x3F); buf[2] = 0x80 | ((ucs >> 12) & 0x3F); buf[3] = 0x80 | ((ucs >> 6) & 0x3F); buf[4] = 0x80 | (ucs & 0x3F); return 5; } buf[0] = '?'; return -1; } /* * returns the byte length of the first UTF-8 char * (returns -1 if not valid) */ int XUtf8CharByteLen(const unsigned char *buf, int len) { unsigned int ucs; return XConvertUtf8ToUcs(buf, len, &ucs); } /* * returns the quantity of Unicode chars in the UTF-8 string */ int XCountUtf8Char(const unsigned char *buf, int len) { int i = 0; int nbc = 0; while (i < len) { int cl = XUtf8CharByteLen(buf + i, len - i); if (cl < 1) cl = 1; nbc++; i += cl; } return nbc; } /* * Same as XConvertUtf8ToUcs but no sanity check is done. */ int XFastConvertUtf8ToUcs(const unsigned char *buf, int len, unsigned int *ucs) { if (buf[0] & 0x80) { if (buf[0] & 0x40) { if (buf[0] & 0x20) { if (buf[0] & 0x10) { if (buf[0] & 0x08) { if (buf[0] & 0x04) { if (buf[0] & 0x02) { /* bad UTF-8 string */ } else { /* 0x04000000 - 0x7FFFFFFF */ } } else if (len > 4) { /* 0x00200000 - 0x03FFFFFF */ *ucs = ((buf[0] & ~0xF8) << 24) + ((buf[1] & ~0x80) << 18) + ((buf[2] & ~0x80) << 12) + ((buf[3] & ~0x80) << 6) + (buf[4] & ~0x80); return 5; } } else if (len > 3) { /* 0x00010000 - 0x001FFFFF */ *ucs = ((buf[0] & ~0xF0) << 18) + ((buf[1] & ~0x80) << 12) + ((buf[2] & ~0x80) << 6) + (buf[3] & ~0x80); return 4; } } else if (len > 2) { /* 0x00000800 - 0x0000FFFF */ *ucs = ((buf[0] & ~0xE0) << 12) + ((buf[1] & ~0x80) << 6) + (buf[2] & ~0x80); return 3; } } else if (len > 1) { /* 0x00000080 - 0x000007FF */ *ucs = ((buf[0] & ~0xC0) << 6) + (buf[1] & ~0x80); return 2; } } } else if (len > 0) { /* 0x00000000 - 0x0000007F */ *ucs = buf[0]; return 1; } *ucs = (unsigned int) '?'; /* bad UTF-8 string */ return -1; } fltk-1.4.3/src/xutf8/is_spacing.c0000644000175000017500000000324215004135251016736 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2010 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * This file is required on all platforms for UTF-8 support */ #include "../utf8_internal.h" /* include UCS tables */ #include "headers/spacing.h" unsigned short XUtf8IsNonSpacing(unsigned int ucs) { if (ucs <= 0x0361) { if (ucs >= 0x0300) return ucs_table_0300[ucs - 0x0300]; return 0; } if (ucs <= 0x0486) { if (ucs >= 0x0483) return ucs_table_0483[ucs - 0x0483]; return 0; } if (ucs <= 0x05C4) { if (ucs >= 0x0591) return ucs_table_0591[ucs - 0x0591]; return 0; } if (ucs <= 0x06ED) { if (ucs >= 0x064B) return ucs_table_064B[ucs - 0x064B]; return 0; } if (ucs <= 0x0D4D) { if (ucs >= 0x0901) return ucs_table_0901[ucs - 0x0901]; return 0; } if (ucs <= 0x0FB9) { if (ucs >= 0x0E31) return ucs_table_0E31[ucs - 0x0E31]; return 0; } if (ucs <= 0x20E1) { if (ucs >= 0x20D0) return ucs_table_20D0[ucs - 0x20D0]; return 0; } if (ucs <= 0x309A) { if (ucs >= 0x302A) return ucs_table_302A[ucs - 0x302A]; return 0; } if (ucs <= 0xFB1E) { if (ucs >= 0xFB1E) return ucs_table_FB1E[ucs - 0xFB1E]; return 0; } if (ucs <= 0xFE23) { if (ucs >= 0xFE20) return ucs_table_FE20[ucs - 0xFE20]; return 0; } return 0; } fltk-1.4.3/src/xutf8/ucs2fontmap.c.mini0000644000175000017500000000132115004135251020007 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ int ucs2fontmap(char *s, unsigned long ucs, int enc) { s[0] = (char) ((ucs & 0xFF00) >> 8); s[1] = (char) (ucs & 0xFF); return 0; } int encoding_number(const char *enc) { return 0; } const char *encoding_name(int num) { return "iso10646-1"; }; fltk-1.4.3/src/xutf8/mk_wcwidth.c0000644000175000017500000003507315004135251016766 0ustar albrechtalbrecht/* * FLTK: Important! * This file should remain as close to Markus Kuhn's original source * as possible for easy checking for changes later, however unlikely. * All customisations to work with FLTK shall be annotated! */ /* * This is an implementation of wcwidth() and wcswidth() (defined in * IEEE Std 1002.1-2001) for Unicode. * * http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html * http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html * * In fixed-width output devices, Latin characters all occupy a single * "cell" position of equal width, whereas ideographic CJK characters * occupy two such cells. Interoperability between terminal-line * applications and (teletype-style) character terminals using the * UTF-8 encoding requires agreement on which character should advance * the cursor by how many cell positions. No established formal * standards exist at present on which Unicode character shall occupy * how many cell positions on character terminals. These routines are * a first attempt of defining such behavior based on simple rules * applied to data provided by the Unicode Consortium. * * For some graphical characters, the Unicode standard explicitly * defines a character-cell width via the definition of the East Asian * FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes. * In all these cases, there is no ambiguity about which width a * terminal shall use. For characters in the East Asian Ambiguous (A) * class, the width choice depends purely on a preference of backward * compatibility with either historic CJK or Western practice. * Choosing single-width for these characters is easy to justify as * the appropriate long-term solution, as the CJK practice of * displaying these characters as double-width comes from historic * implementation simplicity (8-bit encoded characters were displayed * single-width and 16-bit ones double-width, even for Greek, * Cyrillic, etc.) and not any typographic considerations. * * Much less clear is the choice of width for the Not East Asian * (Neutral) class. Existing practice does not dictate a width for any * of these characters. It would nevertheless make sense * typographically to allocate two character cells to characters such * as for instance EM SPACE or VOLUME INTEGRAL, which cannot be * represented adequately with a single-width glyph. The following * routines at present merely assign a single-cell width to all * neutral characters, in the interest of simplicity. This is not * entirely satisfactory and should be reconsidered before * establishing a formal standard in this area. At the moment, the * decision which Not East Asian (Neutral) characters should be * represented by double-width glyphs cannot yet be answered by * applying a simple rule from the Unicode database content. Setting * up a proper standard for the behavior of UTF-8 character terminals * will require a careful analysis not only of each Unicode character, * but also of each presentation form, something the author of these * routines has avoided to do so far. * * http://www.unicode.org/unicode/reports/tr11/ * * Markus Kuhn -- 2007-05-26 (Unicode 5.0) * * Permission to use, copy, modify, and distribute this software * for any purpose and without fee is hereby granted. The author * disclaims all warranties with regard to this software. * * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c */ /* * FLTK - avoid possible problems on systems with 32-bit wchar_t. * Don't include wchar.h, and change wchar_t to unsigned int. * Can we guarantee sizeof(unsigned int) >= 4 ? */ #if 0 #include #endif struct interval { unsigned int first; unsigned int last; }; /* auxiliary function for binary search in interval table */ /* * FLTK: was static int bisearch(wchar_t ucs, const struct interval *table, int max) { */ static int bisearch(unsigned int ucs, const struct interval *table, int max) { int min = 0; int mid; if (ucs < table[0].first || ucs > table[max].last) return 0; while (max >= min) { mid = (min + max) / 2; if (ucs > table[mid].last) min = mid + 1; else if (ucs < table[mid].first) max = mid - 1; else return 1; } return 0; } /* The following two functions define the column width of an ISO 10646 * character as follows: * * - The null character (U+0000) has a column width of 0. * * - Other C0/C1 control characters and DEL will lead to a return * value of -1. * * - Non-spacing and enclosing combining characters (general * category code Mn or Me in the Unicode database) have a * column width of 0. * * - SOFT HYPHEN (U+00AD) has a column width of 1. * * - Other format characters (general category code Cf in the Unicode * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0. * * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF) * have a column width of 0. * * - Spacing characters in the East Asian Wide (W) or East Asian * Full-width (F) category as defined in Unicode Technical * Report #11 have a column width of 2. * * - All remaining characters (including all printable * ISO 8859-1 and WGL4 characters, Unicode control characters, * etc.) have a column width of 1. * * This implementation assumes that wchar_t characters are encoded * in ISO 10646. */ /* * FLTK: was int mk_wcwidth(wchar_t ucs) */ int mk_wcwidth(unsigned int ucs) { /* sorted list of non-overlapping intervals of non-spacing characters */ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ static const struct interval combining[] = { { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 }, { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 }, { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 }, { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A }, { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 }, { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC }, { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 }, { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F }, { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 }, { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD }, { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD }, { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 }, { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B }, { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 }, { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 }, { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF }, { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 }, { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F }, { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B }, { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F }, { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB }, { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F }, { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 }, { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD }, { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F }, { 0xE0100, 0xE01EF } }; /* test for 8-bit control characters */ if (ucs == 0) return 0; if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) return -1; /* binary search in table of non-spacing characters */ if (bisearch(ucs, combining, sizeof(combining) / sizeof(struct interval) - 1)) return 0; /* if we arrive here, ucs is not a combining or C0/C1 control character */ return 1 + (ucs >= 0x1100 && (ucs <= 0x115f || /* Hangul Jamo init. consonants */ ucs == 0x2329 || ucs == 0x232a || (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) || /* CJK ... Yi */ (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ (ucs >= 0xffe0 && ucs <= 0xffe6) || (ucs >= 0x20000 && ucs <= 0x2fffd) || (ucs >= 0x30000 && ucs <= 0x3fffd))); } /* * FLTK: comment out the remaining functions, as we don't need themm. */ #if 0 /* * FLTK: was int mk_wcswidth(const wchar_t *pwcs, size_t n) */ int mk_wcswidth(const unsigned int *pwcs, size_t n) { int w, width = 0; for (;*pwcs && n-- > 0; pwcs++) if ((w = mk_wcwidth(*pwcs)) < 0) return -1; else width += w; return width; } /* * The following functions are the same as mk_wcwidth() and * mk_wcswidth(), except that spacing characters in the East Asian * Ambiguous (A) category as defined in Unicode Technical Report #11 * have a column width of 2. This variant might be useful for users of * CJK legacy encodings who want to migrate to UCS without changing * the traditional terminal character-width behaviour. It is not * otherwise recommended for general use. */ /* * FLTK: was int mk_wcwidth_cjk(wchar_t ucs) */ int mk_wcwidth_cjk(unsigned int ucs) { /* sorted list of non-overlapping intervals of East Asian Ambiguous * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */ static const struct interval ambiguous[] = { { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 }, { 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 }, { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 }, { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 }, { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED }, { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA }, { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 }, { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B }, { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 }, { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 }, { 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 }, { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE }, { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 }, { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA }, { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 }, { 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB }, { 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB }, { 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 }, { 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 }, { 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 }, { 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 }, { 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 }, { 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 }, { 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 }, { 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC }, { 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 }, { 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 }, { 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 }, { 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 }, { 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 }, { 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 }, { 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B }, { 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 }, { 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 }, { 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E }, { 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 }, { 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 }, { 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F }, { 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 }, { 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF }, { 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B }, { 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 }, { 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 }, { 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 }, { 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 }, { 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 }, { 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 }, { 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 }, { 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 }, { 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F }, { 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF }, { 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD } }; /* binary search in table of non-spacing characters */ if (bisearch(ucs, ambiguous, sizeof(ambiguous) / sizeof(struct interval) - 1)) return 2; return mk_wcwidth(ucs); } /* * FLTK: was int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n) */ int mk_wcswidth_cjk(const unsigned int *pwcs, size_t n) { int w, width = 0; for (;*pwcs && n-- > 0; pwcs++) if ((w = mk_wcwidth_cjk(*pwcs)) < 0) return -1; else width += w; return width; } /* * FLTK: end of commented out functions */ #endif fltk-1.4.3/src/xutf8/COPYING0000644000175000017500000000342015004135251015504 0ustar albrechtalbrecht * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php lcUniConv directory: Copyright (c) 1999-2000 Free Software Foundation, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FREE SOFTWARE FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the Free Software Foundation shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the Free Software Foundation. fltk-1.4.3/src/xutf8/case.c0000644000175000017500000000441215004135251015532 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2010 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * This file is required on all platforms for UTF-8 support */ #include "../utf8_internal.h" #include /* include UCS tables */ #include "headers/case.h" int XUtf8Tolower(int ucs) { int ret; if (ucs <= 0x02B6) { if (ucs >= 0x0041) { ret = ucs_table_0041[ucs - 0x0041]; if (ret > 0) return ret; } return ucs; } if (ucs <= 0x0556) { if (ucs >= 0x0386) { ret = ucs_table_0386[ucs - 0x0386]; if (ret > 0) return ret; } return ucs; } if (ucs <= 0x10C5) { if (ucs >= 0x10A0) { ret = ucs_table_10A0[ucs - 0x10A0]; if (ret > 0) return ret; } return ucs; } if (ucs <= 0x1FFC) { if (ucs >= 0x1E00) { ret = ucs_table_1E00[ucs - 0x1E00]; if (ret > 0) return ret; } return ucs; } if (ucs <= 0x2133) { if (ucs >= 0x2102) { ret = ucs_table_2102[ucs - 0x2102]; if (ret > 0) return ret; } return ucs; } if (ucs <= 0x24CF) { if (ucs >= 0x24B6) { ret = ucs_table_24B6[ucs - 0x24B6]; if (ret > 0) return ret; } return ucs; } if (ucs <= 0x33CE) { if (ucs >= 0x33CE) { ret = ucs_table_33CE[ucs - 0x33CE]; if (ret > 0) return ret; } return ucs; } if (ucs <= 0xFF3A) { if (ucs >= 0xFF21) { ret = ucs_table_FF21[ucs - 0xFF21]; if (ret > 0) return ret; } return ucs; } return ucs; } int XUtf8Toupper(int ucs) { int i; static unsigned short *table = NULL; if (!table) { table = (unsigned short*) malloc(sizeof(unsigned short) * 0x10000); for (i = 0; i < 0x10000; i++) { table[i] = (unsigned short) i; } for (i = 0; i < 0x10000; i++) { int l; l = XUtf8Tolower(i); if (l != i) table[l] = (unsigned short) i; } } if (ucs >= 0x10000 || ucs < 0) return ucs; return table[ucs]; } fltk-1.4.3/src/xutf8/is_right2left.c0000644000175000017500000000244015004135251017363 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2010 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * This file is required on all platforms for UTF-8 support */ #include "../utf8_internal.h" unsigned short XUtf8IsRightToLeft(unsigned int ucs) { #if 0 /* for debug only */ if (ucs <= 0x005A) { if (ucs >= 0x0041) return 1; return 0; } #endif /* HEBREW */ if (ucs <= 0x05F4) { if (ucs >= 0x0591) return 1; return 0; } /* ARABIC */ if (ucs <= 0x06ED) { if (ucs >= 0x060C) return 1; return 0; } if (ucs <= 0x06F9) { if (ucs >= 0x06F0) return 1; return 0; } if (ucs == 0x200F) return 1; if (ucs == 0x202B) return 1; if (ucs == 0x202E) return 1; if (ucs <= 0xFB4F) { if (ucs >= 0xFB1E) return 1; return 0; } if (ucs <= 0xFDFB) { if (ucs >= 0xFB50) return 1; return 0; } if (ucs <= 0xFEFC) { if (ucs >= 0xFE70) return 1; return 0; } return 0; } fltk-1.4.3/src/xutf8/Xlibint.h0000644000175000017500000000000015004135251016222 0ustar albrechtalbrechtfltk-1.4.3/src/xutf8/imKStoUCS.c0000644000175000017500000005164315004135251016410 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/imKStoUCS.c,v 1.5 2003/11/17 22:20:11 dawes Exp $ */ #include "Xlibint.h" #include "Ximint.h" static unsigned short const keysym_to_unicode_1a1_1ff[] = { 0x0104, 0x02d8, 0x0141, 0x0000, 0x013d, 0x015a, 0x0000, /* 0x01a0-0x01a7 */ 0x0000, 0x0160, 0x015e, 0x0164, 0x0179, 0x0000, 0x017d, 0x017b, /* 0x01a8-0x01af */ 0x0000, 0x0105, 0x02db, 0x0142, 0x0000, 0x013e, 0x015b, 0x02c7, /* 0x01b0-0x01b7 */ 0x0000, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* 0x01b8-0x01bf */ 0x0154, 0x0000, 0x0000, 0x0102, 0x0000, 0x0139, 0x0106, 0x0000, /* 0x01c0-0x01c7 */ 0x010c, 0x0000, 0x0118, 0x0000, 0x011a, 0x0000, 0x0000, 0x010e, /* 0x01c8-0x01cf */ 0x0110, 0x0143, 0x0147, 0x0000, 0x0000, 0x0150, 0x0000, 0x0000, /* 0x01d0-0x01d7 */ 0x0158, 0x016e, 0x0000, 0x0170, 0x0000, 0x0000, 0x0162, 0x0000, /* 0x01d8-0x01df */ 0x0155, 0x0000, 0x0000, 0x0103, 0x0000, 0x013a, 0x0107, 0x0000, /* 0x01e0-0x01e7 */ 0x010d, 0x0000, 0x0119, 0x0000, 0x011b, 0x0000, 0x0000, 0x010f, /* 0x01e8-0x01ef */ 0x0111, 0x0144, 0x0148, 0x0000, 0x0000, 0x0151, 0x0000, 0x0000, /* 0x01f0-0x01f7 */ 0x0159, 0x016f, 0x0000, 0x0171, 0x0000, 0x0000, 0x0163, 0x02d9 /* 0x01f8-0x01ff */ }; static unsigned short const keysym_to_unicode_2a1_2fe[] = { 0x0126, 0x0000, 0x0000, 0x0000, 0x0000, 0x0124, 0x0000, /* 0x02a0-0x02a7 */ 0x0000, 0x0130, 0x0000, 0x011e, 0x0134, 0x0000, 0x0000, 0x0000, /* 0x02a8-0x02af */ 0x0000, 0x0127, 0x0000, 0x0000, 0x0000, 0x0000, 0x0125, 0x0000, /* 0x02b0-0x02b7 */ 0x0000, 0x0131, 0x0000, 0x011f, 0x0135, 0x0000, 0x0000, 0x0000, /* 0x02b8-0x02bf */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010a, 0x0108, 0x0000, /* 0x02c0-0x02c7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02c8-0x02cf */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0120, 0x0000, 0x0000, /* 0x02d0-0x02d7 */ 0x011c, 0x0000, 0x0000, 0x0000, 0x0000, 0x016c, 0x015c, 0x0000, /* 0x02d8-0x02df */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010b, 0x0109, 0x0000, /* 0x02e0-0x02e7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02e8-0x02ef */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0121, 0x0000, 0x0000, /* 0x02f0-0x02f7 */ 0x011d, 0x0000, 0x0000, 0x0000, 0x0000, 0x016d, 0x015d /* 0x02f8-0x02ff */ }; static unsigned short const keysym_to_unicode_3a2_3fe[] = { 0x0138, 0x0156, 0x0000, 0x0128, 0x013b, 0x0000, /* 0x03a0-0x03a7 */ 0x0000, 0x0000, 0x0112, 0x0122, 0x0166, 0x0000, 0x0000, 0x0000, /* 0x03a8-0x03af */ 0x0000, 0x0000, 0x0000, 0x0157, 0x0000, 0x0129, 0x013c, 0x0000, /* 0x03b0-0x03b7 */ 0x0000, 0x0000, 0x0113, 0x0123, 0x0167, 0x014a, 0x0000, 0x014b, /* 0x03b8-0x03bf */ 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012e, /* 0x03c0-0x03c7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0116, 0x0000, 0x0000, 0x012a, /* 0x03c8-0x03cf */ 0x0000, 0x0145, 0x014c, 0x0136, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03d0-0x03d7 */ 0x0000, 0x0172, 0x0000, 0x0000, 0x0000, 0x0168, 0x016a, 0x0000, /* 0x03d8-0x03df */ 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012f, /* 0x03e0-0x03e7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0117, 0x0000, 0x0000, 0x012b, /* 0x03e8-0x03ef */ 0x0000, 0x0146, 0x014d, 0x0137, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03f0-0x03f7 */ 0x0000, 0x0173, 0x0000, 0x0000, 0x0000, 0x0169, 0x016b /* 0x03f8-0x03ff */ }; static unsigned short const keysym_to_unicode_4a1_4df[] = { 0x3002, 0x3008, 0x3009, 0x3001, 0x30fb, 0x30f2, 0x30a1, /* 0x04a0-0x04a7 */ 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3, /* 0x04a8-0x04af */ 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad, /* 0x04b0-0x04b7 */ 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd, /* 0x04b8-0x04bf */ 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc, /* 0x04c0-0x04c7 */ 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de, /* 0x04c8-0x04cf */ 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9, /* 0x04d0-0x04d7 */ 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c /* 0x04d8-0x04df */ }; static unsigned short const keysym_to_unicode_590_5fe[] = { 0x06f0, 0x06f1, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06f6, 0x06f7, /* 0x0590-0x0597 */ 0x06f8, 0x06f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0598-0x059f */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x066a, 0x0670, 0x0679, /* 0x05a0-0x05a7 */ 0x067e, 0x0686, 0x0688, 0x0691, 0x060c, 0x0000, 0x06d4, 0x0000, /* 0x05ac-0x05af */ 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, /* 0x05b0-0x05b7 */ 0x0668, 0x0669, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f, /* 0x05b8-0x05bf */ 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, /* 0x05c0-0x05c7 */ 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, /* 0x05c8-0x05cf */ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, /* 0x05d0-0x05d7 */ 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x05d8-0x05df */ 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, /* 0x05e0-0x05e7 */ 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, /* 0x05e8-0x05ef */ 0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0698, 0x06a4, /* 0x05f0-0x05f7 */ 0x06a9, 0x06af, 0x06ba, 0x06be, 0x06cc, 0x06d2, 0x06c1 /* 0x05f8-0x05fe */ }; static unsigned short keysym_to_unicode_680_6ff[] = { 0x0492, 0x0496, 0x049a, 0x049c, 0x04a2, 0x04ae, 0x04b0, 0x04b2, /* 0x0680-0x0687 */ 0x04b6, 0x04b8, 0x04ba, 0x0000, 0x04d8, 0x04e2, 0x04e8, 0x04ee, /* 0x0688-0x068f */ 0x0493, 0x0497, 0x049b, 0x049d, 0x04a3, 0x04af, 0x04b1, 0x04b3, /* 0x0690-0x0697 */ 0x04b7, 0x04b9, 0x04bb, 0x0000, 0x04d9, 0x04e3, 0x04e9, 0x04ef, /* 0x0698-0x069f */ 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, /* 0x06a0-0x06a7 */ 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0491, 0x045e, 0x045f, /* 0x06a8-0x06af */ 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, /* 0x06b0-0x06b7 */ 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0490, 0x040e, 0x040f, /* 0x06b8-0x06bf */ 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, /* 0x06c0-0x06c7 */ 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, /* 0x06c8-0x06cf */ 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, /* 0x06d0-0x06d7 */ 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, /* 0x06d8-0x06df */ 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, /* 0x06e0-0x06e7 */ 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, /* 0x06e8-0x06ef */ 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, /* 0x06f0-0x06f7 */ 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a /* 0x06f8-0x06ff */ }; static unsigned short const keysym_to_unicode_7a1_7f9[] = { 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, /* 0x07a0-0x07a7 */ 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, /* 0x07a8-0x07af */ 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, /* 0x07b0-0x07b7 */ 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07b8-0x07bf */ 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, /* 0x07c0-0x07c7 */ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, /* 0x07c8-0x07cf */ 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, /* 0x07d0-0x07d7 */ 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07d8-0x07df */ 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, /* 0x07e0-0x07e7 */ 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, /* 0x07e8-0x07ef */ 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, /* 0x07f0-0x07f7 */ 0x03c8, 0x03c9 /* 0x07f8-0x07ff */ }; static unsigned short const keysym_to_unicode_8a4_8fe[] = { 0x2320, 0x2321, 0x0000, 0x231c, /* 0x08a0-0x08a7 */ 0x231d, 0x231e, 0x231f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08a8-0x08af */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08b0-0x08b7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222b, /* 0x08b8-0x08bf */ 0x2234, 0x0000, 0x221e, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, /* 0x08c0-0x08c7 */ 0x2245, 0x2246, 0x0000, 0x0000, 0x0000, 0x0000, 0x22a2, 0x0000, /* 0x08c8-0x08cf */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221a, 0x0000, /* 0x08d0-0x08d7 */ 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222a, 0x2227, 0x2228, /* 0x08d8-0x08df */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08e0-0x08e7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08e8-0x08ef */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, /* 0x08f0-0x08f7 */ 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193 /* 0x08f8-0x08ff */ }; static unsigned short const keysym_to_unicode_9df_9f8[] = { 0x2422, /* 0x09d8-0x09df */ 0x2666, 0x25a6, 0x2409, 0x240c, 0x240d, 0x240a, 0x0000, 0x0000, /* 0x09e0-0x09e7 */ 0x240a, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x2500, /* 0x09e8-0x09ef */ 0x0000, 0x0000, 0x0000, 0x0000, 0x251c, 0x2524, 0x2534, 0x252c, /* 0x09f0-0x09f7 */ 0x2502 /* 0x09f8-0x09ff */ }; static unsigned short const keysym_to_unicode_aa1_afe[] = { 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, /* 0x0aa0-0x0aa7 */ 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, /* 0x0aa8-0x0aaf */ 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, /* 0x0ab0-0x0ab7 */ 0x2105, 0x0000, 0x0000, 0x2012, 0x2039, 0x2024, 0x203a, 0x0000, /* 0x0ab8-0x0abf */ 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, /* 0x0ac0-0x0ac7 */ 0x0000, 0x2122, 0x2120, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25ad, /* 0x0ac8-0x0acf */ 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033, /* 0x0ad0-0x0ad7 */ 0x0000, 0x271d, 0x0000, 0x220e, 0x25c2, 0x2023, 0x25cf, 0x25ac, /* 0x0ad8-0x0adf */ 0x25e6, 0x25ab, 0x25ae, 0x25b5, 0x25bf, 0x2606, 0x2022, 0x25aa, /* 0x0ae0-0x0ae7 */ 0x25b4, 0x25be, 0x261a, 0x261b, 0x2663, 0x2666, 0x2665, 0x0000, /* 0x0ae8-0x0aef */ 0x2720, 0x2020, 0x2021, 0x2713, 0x2612, 0x266f, 0x266d, 0x2642, /* 0x0af0-0x0af7 */ 0x2640, 0x2121, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e /* 0x0af8-0x0aff */ }; /* none of the APL keysyms match the Unicode characters */ static unsigned short const keysym_to_unicode_cdf_cfa[] = { 0x2017, /* 0x0cd8-0x0cdf */ 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, /* 0x0ce0-0x0ce7 */ 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, /* 0x0ce8-0x0cef */ 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, /* 0x0cf0-0x0cf7 */ 0x05e8, 0x05e9, 0x05ea /* 0x0cf8-0x0cff */ }; static unsigned short const keysym_to_unicode_da1_df9[] = { 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, /* 0x0da0-0x0da7 */ 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, /* 0x0da8-0x0daf */ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, /* 0x0db0-0x0db7 */ 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, /* 0x0db8-0x0dbf */ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, /* 0x0dc0-0x0dc7 */ 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, /* 0x0dc8-0x0dcf */ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, /* 0x0dd0-0x0dd7 */ 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0e3e, 0x0e3f, /* 0x0dd8-0x0ddf */ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, /* 0x0de0-0x0de7 */ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0000, 0x0000, /* 0x0de8-0x0def */ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, /* 0x0df0-0x0df7 */ 0x0e58, 0x0e59 /* 0x0df8-0x0dff */ }; static unsigned short const keysym_to_unicode_ea0_eff[] = { 0x0000, 0x1101, 0x1101, 0x11aa, 0x1102, 0x11ac, 0x11ad, 0x1103, /* 0x0ea0-0x0ea7 */ 0x1104, 0x1105, 0x11b0, 0x11b1, 0x11b2, 0x11b3, 0x11b4, 0x11b5, /* 0x0ea8-0x0eaf */ 0x11b6, 0x1106, 0x1107, 0x1108, 0x11b9, 0x1109, 0x110a, 0x110b, /* 0x0eb0-0x0eb7 */ 0x110c, 0x110d, 0x110e, 0x110f, 0x1110, 0x1111, 0x1112, 0x1161, /* 0x0eb8-0x0ebf */ 0x1162, 0x1163, 0x1164, 0x1165, 0x1166, 0x1167, 0x1168, 0x1169, /* 0x0ec0-0x0ec7 */ 0x116a, 0x116b, 0x116c, 0x116d, 0x116e, 0x116f, 0x1170, 0x1171, /* 0x0ec8-0x0ecf */ 0x1172, 0x1173, 0x1174, 0x1175, 0x11a8, 0x11a9, 0x11aa, 0x11ab, /* 0x0ed0-0x0ed7 */ 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, /* 0x0ed8-0x0edf */ 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, /* 0x0ee0-0x0ee7 */ 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x0000, /* 0x0ee8-0x0eef */ 0x0000, 0x0000, 0x1140, 0x0000, 0x0000, 0x1159, 0x119e, 0x0000, /* 0x0ef0-0x0ef7 */ 0x11eb, 0x0000, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9, /* 0x0ef8-0x0eff */ }; static unsigned short keysym_to_unicode_12a1_12fe[] = { 0x1e02, 0x1e03, 0x0000, 0x0000, 0x0000, 0x1e0a, 0x0000, /* 0x12a0-0x12a7 */ 0x1e80, 0x0000, 0x1e82, 0x1e0b, 0x1ef2, 0x0000, 0x0000, 0x0000, /* 0x12a8-0x12af */ 0x1e1e, 0x1e1f, 0x0000, 0x0000, 0x1e40, 0x1e41, 0x0000, 0x1e56, /* 0x12b0-0x12b7 */ 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, /* 0x12b8-0x12bf */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c0-0x12c7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c8-0x12cf */ 0x0174, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6a, /* 0x12d0-0x12d7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0176, 0x0000, /* 0x12d8-0x12df */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e0-0x12e7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e8-0x12ef */ 0x0175, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6b, /* 0x12f0-0x12f7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0177 /* 0x12f0-0x12ff */ }; static unsigned short const keysym_to_unicode_13bc_13be[] = { 0x0152, 0x0153, 0x0178 /* 0x13b8-0x13bf */ }; static unsigned short keysym_to_unicode_14a1_14ff[] = { 0x2741, 0x00a7, 0x0589, 0x0029, 0x0028, 0x00bb, 0x00ab, /* 0x14a0-0x14a7 */ 0x2014, 0x002e, 0x055d, 0x002c, 0x2013, 0x058a, 0x2026, 0x055c, /* 0x14a8-0x14af */ 0x055b, 0x055e, 0x0531, 0x0561, 0x0532, 0x0562, 0x0533, 0x0563, /* 0x14b0-0x14b7 */ 0x0534, 0x0564, 0x0535, 0x0565, 0x0536, 0x0566, 0x0537, 0x0567, /* 0x14b8-0x14bf */ 0x0538, 0x0568, 0x0539, 0x0569, 0x053a, 0x056a, 0x053b, 0x056b, /* 0x14c0-0x14c7 */ 0x053c, 0x056c, 0x053d, 0x056d, 0x053e, 0x056e, 0x053f, 0x056f, /* 0x14c8-0x14cf */ 0x0540, 0x0570, 0x0541, 0x0571, 0x0542, 0x0572, 0x0543, 0x0573, /* 0x14d0-0x14d7 */ 0x0544, 0x0574, 0x0545, 0x0575, 0x0546, 0x0576, 0x0547, 0x0577, /* 0x14d8-0x14df */ 0x0548, 0x0578, 0x0549, 0x0579, 0x054a, 0x057a, 0x054b, 0x057b, /* 0x14e0-0x14e7 */ 0x054c, 0x057c, 0x054d, 0x057d, 0x054e, 0x057e, 0x054f, 0x057f, /* 0x14e8-0x14ef */ 0x0550, 0x0580, 0x0551, 0x0581, 0x0552, 0x0582, 0x0553, 0x0583, /* 0x14f0-0x14f7 */ 0x0554, 0x0584, 0x0555, 0x0585, 0x0556, 0x0586, 0x2019, 0x0027, /* 0x14f8-0x14ff */ }; static unsigned short keysym_to_unicode_15d0_15f6[] = { 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, /* 0x15d0-0x15d7 */ 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, /* 0x15d8-0x15df */ 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, /* 0x15e0-0x15e7 */ 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, /* 0x15e8-0x15ef */ 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6 /* 0x15f0-0x15f7 */ }; static unsigned short keysym_to_unicode_16a0_16f6[] = { 0x0000, 0x0000, 0xf0a2, 0x1e8a, 0x0000, 0xf0a5, 0x012c, 0xf0a7, /* 0x16a0-0x16a7 */ 0xf0a8, 0x01b5, 0x01e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x019f, /* 0x16a8-0x16af */ 0x0000, 0x0000, 0xf0b2, 0x1e8b, 0x01d1, 0xf0b5, 0x012d, 0xf0b7, /* 0x16b0-0x16b7 */ 0xf0b8, 0x01b6, 0x01e7, 0x0000, 0x0000, 0x01d2, 0x0000, 0x0275, /* 0x16b8-0x16bf */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x018f, 0x0000, /* 0x16c0-0x16c7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16c8-0x16cf */ 0x0000, 0x1e36, 0xf0d2, 0xf0d3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d0-0x16d7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d8-0x16df */ 0x0000, 0x1e37, 0xf0e2, 0xf0e3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e0-0x16e7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e8-0x16ef */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0259 /* 0x16f0-0x16f6 */ }; static unsigned short const keysym_to_unicode_1e9f_1eff[] = { 0x0303, 0x1ea0, 0x1ea1, 0x1ea2, 0x1ea3, 0x1ea4, 0x1ea5, 0x1ea6, 0x1ea7, /* 0x1ea0-0x1ea7 */ 0x1ea8, 0x1ea9, 0x1eaa, 0x1eab, 0x1eac, 0x1ead, 0x1eae, 0x1eaf, /* 0x1ea8-0x1eaf */ 0x1eb0, 0x1eb1, 0x1eb2, 0x1eb3, 0x1eb4, 0x1eb5, 0x1eb6, 0x1eb7, /* 0x1eb0-0x1eb7 */ 0x1eb8, 0x1eb9, 0x1eba, 0x1ebb, 0x1ebc, 0x1ebd, 0x1ebe, 0x1ebf, /* 0x1eb8-0x1ebf */ 0x1ec0, 0x1ec1, 0x1ec2, 0x1ec3, 0x1ec4, 0x1ec5, 0x1ec6, 0x1ec7, /* 0x1ec0-0x1ec7 */ 0x1ec8, 0x1ec9, 0x1eca, 0x1ecb, 0x1ecc, 0x1ecd, 0x1ece, 0x1ecf, /* 0x1ec8-0x1ecf */ 0x1ed0, 0x1ed1, 0x1ed2, 0x1ed3, 0x1ed4, 0x1ed5, 0x1ed6, 0x1ed7, /* 0x1ed0-0x1ed7 */ 0x1ed8, 0x1ed9, 0x1eda, 0x1edb, 0x1edc, 0x1edd, 0x1ede, 0x1edf, /* 0x1ed8-0x1edf */ 0x1ee0, 0x1ee1, 0x1ee2, 0x1ee3, 0x1ee4, 0x1ee5, 0x1ee6, 0x1ee7, /* 0x1ee0-0x1ee7 */ 0x1ee8, 0x1ee9, 0x1eea, 0x1eeb, 0x1eec, 0x1eed, 0x1eee, 0x1eef, /* 0x1ee8-0x1eef */ 0x1ef0, 0x1ef1, 0x0300, 0x0301, 0x1ef4, 0x1ef5, 0x1ef6, 0x1ef7, /* 0x1ef0-0x1ef7 */ 0x1ef8, 0x1ef9, 0x01a0, 0x01a1, 0x01af, 0x01b0, 0x0309, 0x0323 /* 0x1ef8-0x1eff */ }; static unsigned short const keysym_to_unicode_20a0_20ac[] = { 0x20a0, 0x20a1, 0x20a2, 0x20a3, 0x20a4, 0x20a5, 0x20a6, 0x20a7, /* 0x20a0-0x20a7 */ 0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac /* 0x20a8-0x20af */ }; static unsigned int KeySymToUcs4(KeySym keysym) { /* 'Unicode keysym' */ if ((keysym & 0xff000000) == 0x01000000) return (keysym & 0x00ffffff); if (keysym > 0 && keysym < 0x100) return keysym; else if (keysym > 0x1a0 && keysym < 0x200) return keysym_to_unicode_1a1_1ff[keysym - 0x1a1]; else if (keysym > 0x2a0 && keysym < 0x2ff) return keysym_to_unicode_2a1_2fe[keysym - 0x2a1]; else if (keysym > 0x3a1 && keysym < 0x3ff) return keysym_to_unicode_3a2_3fe[keysym - 0x3a2]; else if (keysym > 0x4a0 && keysym < 0x4e0) return keysym_to_unicode_4a1_4df[keysym - 0x4a1]; else if (keysym > 0x589 && keysym < 0x5ff) return keysym_to_unicode_590_5fe[keysym - 0x590]; else if (keysym > 0x67f && keysym < 0x700) return keysym_to_unicode_680_6ff[keysym - 0x680]; else if (keysym > 0x7a0 && keysym < 0x7fa) return keysym_to_unicode_7a1_7f9[keysym - 0x7a1]; else if (keysym > 0x8a3 && keysym < 0x8ff) return keysym_to_unicode_8a4_8fe[keysym - 0x8a4]; else if (keysym > 0x9de && keysym < 0x9f9) return keysym_to_unicode_9df_9f8[keysym - 0x9df]; else if (keysym > 0xaa0 && keysym < 0xaff) return keysym_to_unicode_aa1_afe[keysym - 0xaa1]; else if (keysym > 0xcde && keysym < 0xcfb) return keysym_to_unicode_cdf_cfa[keysym - 0xcdf]; else if (keysym > 0xda0 && keysym < 0xdfa) return keysym_to_unicode_da1_df9[keysym - 0xda1]; else if (keysym > 0xe9f && keysym < 0xf00) return keysym_to_unicode_ea0_eff[keysym - 0xea0]; else if (keysym > 0x12a0 && keysym < 0x12ff) return keysym_to_unicode_12a1_12fe[keysym - 0x12a1]; else if (keysym > 0x13bb && keysym < 0x13bf) return keysym_to_unicode_13bc_13be[keysym - 0x13bc]; else if (keysym > 0x14a0 && keysym < 0x1500) return keysym_to_unicode_14a1_14ff[keysym - 0x14a1]; else if (keysym > 0x15cf && keysym < 0x15f7) return keysym_to_unicode_15d0_15f6[keysym - 0x15d0]; else if (keysym > 0x169f && keysym < 0x16f7) return keysym_to_unicode_16a0_16f6[keysym - 0x16a0]; else if (keysym > 0x1e9e && keysym < 0x1f00) return keysym_to_unicode_1e9f_1eff[keysym - 0x1e9f]; else if (keysym > 0x209f && keysym < 0x20ad) return keysym_to_unicode_20a0_20ac[keysym - 0x20a0]; else return 0; } fltk-1.4.3/src/xutf8/Ximint.h0000644000175000017500000000000015004135251016061 0ustar albrechtalbrechtfltk-1.4.3/src/xutf8/utf8Wrap.c0000644000175000017500000007314415004135251016347 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * X11 UTF-8 text drawing functions. * * This file is compiled and linked only for X11 w/o Xft. */ #include "../Xutf8.h" #include #include // fl_strdup() #include #include #include #include #include "../utf8_internal.h" /* External auto generated functions : */ #include "ucs2fontmap.c" /* * extern int ucs2fontmap(char *s, unsigned int ucs, int enc); * extern int encoding_number(const char *enc); * extern const char *encoding_name(int num); */ /* The ARM header files have a bug by not taking into account that ARM cpu * likes padding to 4 bytes. This little trick defines our own version of * XChar2b which does not have this problem */ #if defined(__GNUC__) && defined(__arm__) && !defined(__ARM_EABI__) typedef struct { unsigned char byte1; unsigned char byte2; } __attribute__ ((packed)) Fl_XChar2b; #else #define Fl_XChar2b XChar2b #endif /*********************************************************************/ /** extract a list of font from the base font name list **/ /*********************************************************************/ static int get_font_list( const char *base_font_name_list, char ***flist) { const char *ptr; const char *p; int nb; int nb_name; ptr = base_font_name_list; p = NULL; nb = 0; nb_name = 1; while (*ptr) { if (*ptr == ',') nb_name++; ptr++; } *flist = (char **) malloc(sizeof(char*) * nb_name); ptr = base_font_name_list; while (*ptr) { int l = 0, i = 0; while(isspace((int)(unsigned char)*ptr)) ptr++; p = ptr; while (*ptr && *ptr != ',') { ptr++; l++; } if (l > 2) { (*flist)[nb] = (char*) malloc((unsigned)l + 2); while (p != ptr) { ((*flist)[nb])[i] = *p; i++; p++; } (*flist)[nb][i] = '\0'; nb++; } if (*ptr) ptr++; } if (nb < 1) { free(*flist); *flist = (char**)NULL; } return nb; } /*********************************************************************/ /** get the font name used as encoding for "fontspecific" encoding **/ /** (mainly used for adobe-symbol and adobe-zapfdingbats) **/ /*********************************************************************/ static int font_spec_enc(char *font) { int ret; char *enc; char *end; enc = font; while (*enc != '-') enc++; enc++; while (*enc != '-') enc++; enc++; end = enc; while (*end != '-') end++; *end = '\0'; ret = encoding_number(enc); *end = '-'; return ret; } /*********************************************************************/ /** get the sub range of a iso10646-1 font **/ /*********************************************************************/ static void get_range(const char *enc, int *min, int *max) { const char *ptr = enc; const char *ptr1; if (!enc) return; while (*ptr && *ptr != '-') ptr++; if (!*ptr) return; while (*ptr && *ptr != '[') ptr++; if (!*ptr) return; *min = 0xFFFF; *max = 0; while (*ptr && *ptr != ']') { int val; ptr++; ptr1 = ptr; while (*ptr && *ptr != ']' && *ptr != ' ' && *ptr != '_') ptr++; val = strtol(ptr1, NULL, 0); if (val < *min) *min = val; if (val > *max) *max = val; } } /*********************************************************************/ /** get the internal encoding number of each fonts **/ /*********************************************************************/ static int * get_encodings(char **font_name_list, int *ranges, int nb_font) { int *font_encoding_list; int i; i = 0; font_encoding_list = (int *) malloc(sizeof(int) * nb_font); while (i < nb_font) { char *ptr; int ec; ptr = font_name_list[i]; ec = 0; font_encoding_list[i] = -1; ranges[i * 2] = 0; ranges[i * 2 + 1] = 0xFFFF; if (ptr && strstr(ptr, "fontspecific")) { font_encoding_list[i] = font_spec_enc(ptr); ptr = NULL; } while (ptr && *ptr) { if (*ptr == '-') { ec++; if (ec == 13) { font_encoding_list[i] = encoding_number(ptr + 1); if (font_encoding_list[i] == 0) { get_range(ptr + 1, ranges + i * 2, ranges + i * 2 + 1); } break; } } ptr++; } if (font_encoding_list[i] < 0) font_encoding_list[i] = 1; i++; } return font_encoding_list; } /*********************************************************************/ /** find the first font which matches the name and load it. **/ /*********************************************************************/ static XFontStruct * find_best_font(Display *dpy, char **name) { char **list; int cnt; XFontStruct *s; list = XListFonts(dpy, *name, 1, &cnt); if (cnt && list) { free(*name); *name = fl_strdup(list[0]); s = XLoadQueryFont(dpy, *name); XFreeFontNames(list); return s; } return NULL; } /*********************************************************************/ /** load all fonts **/ /*********************************************************************/ static void load_fonts(Display *dpy, XUtf8FontStruct *font_set) { int i = 0; font_set->fonts = (XFontStruct**) malloc(sizeof(XFontStruct*) * font_set->nb_font); font_set->ranges = (int*) malloc(sizeof(int) * font_set->nb_font * 2); font_set->descent = 0; font_set->ascent = 0; font_set->fid = 0; while (i < font_set->nb_font) { XFontStruct *fnt; fnt = font_set->fonts[i] = find_best_font(dpy, &(font_set->font_name_list[i])); if (fnt) { font_set->fid = fnt->fid; if (fnt->ascent > font_set->ascent) { font_set->ascent = fnt->ascent; } if (fnt->descent > font_set->descent) { font_set->descent = fnt->descent; } } else { free(font_set->font_name_list[i]); font_set->font_name_list[i] = NULL; } i++; } font_set->encodings = get_encodings(font_set->font_name_list, font_set->ranges, font_set->nb_font); /* unload fonts with same encoding */ for (i = 0; i < font_set->nb_font; i++) { if (font_set->font_name_list[i]) { int j; for (j = 0; j < i; j++) { if (font_set->font_name_list[j] && font_set->encodings[j] == font_set->encodings[i] && font_set->ranges[2*j] == font_set->ranges[2*i] && font_set->ranges[(2*j)+1] && font_set->ranges[(2*i)+1]) { XFreeFont(dpy, font_set->fonts[i]); free(font_set->font_name_list[i]); font_set->font_name_list[i] = NULL; font_set->fonts[i] = 0; } } } } } /*********************************************************************/ /** Creates an array of XFontStruct acording to the comma separated **/ /** list of fonts. XLoad all fonts. **/ /*********************************************************************/ XUtf8FontStruct * XCreateUtf8FontStruct(Display *dpy, const char *base_font_name_list) { XUtf8FontStruct *font_set; font_set = (XUtf8FontStruct*)malloc(sizeof(XUtf8FontStruct)); if (!font_set) { return NULL; } font_set->nb_font = get_font_list(base_font_name_list, &font_set->font_name_list); if (font_set->nb_font < 1) { free(font_set); return NULL; } load_fonts(dpy, font_set); return font_set; } /*****************************************************************************/ /** draw a Right To Left UTF-8 string using multiple fonts as needed. **/ /*****************************************************************************/ void XUtf8DrawRtlString(Display *display, Drawable d, XUtf8FontStruct *font_set, GC gc, int x, int y, const char *string, int num_bytes) { int *encodings; /* encodings array */ XFontStruct **fonts; /* fonts array */ Fl_XChar2b buf[128]; /* drawing buffer */ Fl_XChar2b *ptr; /* pointer to the drawing buffer */ int fnum; /* index of the current font in the fonts array*/ int i; /* current byte in the XChar2b buffer */ int first; /* first valid font index */ int last_fnum; /* font index of the previous char */ int nb_font; /* quantity of fonts in the font array */ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */ int *ranges; /* sub range of iso10646 */ nb_font = font_set->nb_font; if (nb_font < 1) { /* there is no font in the font_set :-( */ return; } ranges = font_set->ranges; fonts = font_set->fonts; encodings = font_set->encodings; i = 0; fnum = 0; ptr = buf + 128; while(fnum < nb_font && !fonts[fnum]) fnum++; if (fnum >= nb_font) { /* there is no valid font for the X server */ return; } first = fnum; last_fnum = fnum; while (num_bytes > 0) { int ulen; /* byte length of the UTF-8 char */ unsigned int ucs; /* Unicode value of the UTF-8 char */ unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */ if (i > 120) { /*** draw the buffer **/ XSetFont(display, gc, fonts[fnum]->fid); x -= XTextWidth16(fonts[fnum], ptr, i); XDrawString16(display, d, gc, x, y, ptr, i); i = 0; ptr = buf + 128; } ulen = XFastConvertUtf8ToUcs((const unsigned char*)string, num_bytes, &ucs); if (ulen < 1) ulen = 1; no_spc = XUtf8IsNonSpacing(ucs); if (no_spc) ucs = no_spc; /* * find the first encoding which can be used to * draw the glyph */ fnum = first; while (fnum < nb_font) { if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { if (encodings[fnum] != 0 || ((int)ucs >= ranges[fnum * 2] && (int)ucs <= ranges[fnum * 2 + 1])) { break; } } fnum++; } if (fnum == nb_font) { /* the char is not valid in all encodings -> * draw it using the first font :-( */ fnum = first; ucs2fontmap(glyph, '?', encodings[fnum]); } if (last_fnum != fnum || no_spc) { XSetFont(display, gc, fonts[last_fnum]->fid); x -= XTextWidth16(fonts[last_fnum], ptr, i); XDrawString16(display, d, gc, x, y, ptr, i); i = 0; ptr = buf + 127; (*ptr).byte1 = glyph[0]; (*ptr).byte2 = glyph[1]; if (no_spc) { x += XTextWidth16(fonts[fnum], ptr, 1); } } else { ptr--; (*ptr).byte1 = glyph[0]; (*ptr).byte2 = glyph[1]; } last_fnum = fnum; i++; string += ulen; num_bytes -= ulen; } if (i < 1) return; XSetFont(display, gc, fonts[fnum]->fid); x -= XTextWidth16(fonts[last_fnum], ptr, i); XDrawString16(display, d, gc, x, y, ptr, i); } /*****************************************************************************/ /** draw an UTF-8 string using multiple fonts as needed. **/ /*****************************************************************************/ void XUtf8DrawString(Display *display, Drawable d, XUtf8FontStruct *font_set, GC gc, int x, int y, const char *string, int num_bytes) { int *encodings; /* encodings array */ XFontStruct **fonts; /* fonts array */ Fl_XChar2b buf[128]; /* drawing buffer */ int fnum; /* index of the current font in the fonts array*/ int i; /* current byte in the XChar2b buffer */ int first; /* first valid font index */ int last_fnum; /* font index of the previous char */ int nb_font; /* quantity of fonts in the font array */ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */ int *ranges; /* sub range of iso10646 */ nb_font = font_set->nb_font; if (nb_font < 1) { /* there is no font in the font_set :-( */ return; } ranges = font_set->ranges; fonts = font_set->fonts; encodings = font_set->encodings; i = 0; fnum = 0; while(fnum < nb_font && !fonts[fnum]) fnum++; if (fnum >= nb_font) { /* there is no valid font for the X server */ return; } first = fnum; last_fnum = fnum; while (num_bytes > 0) { int ulen; /* byte length of the UTF-8 char */ unsigned int ucs; /* Unicode value of the UTF-8 char */ unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */ if (i > 120) { /*** draw the buffer **/ XSetFont(display, gc, fonts[fnum]->fid); XDrawString16(display, d, gc, x, y, buf, i); x += XTextWidth16(fonts[fnum], buf, i); i = 0; } ulen = XFastConvertUtf8ToUcs((const unsigned char*)string, num_bytes, &ucs); if (ulen < 1) ulen = 1; no_spc = XUtf8IsNonSpacing(ucs); if (no_spc) ucs = no_spc; /* * find the first encoding which can be used to * draw the glyph */ fnum = first; while (fnum < nb_font) { if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { if (encodings[fnum] != 0 || ((int)ucs >= ranges[fnum * 2] && (int)ucs <= ranges[fnum * 2 + 1])) { break; } } fnum++; } if (fnum == nb_font) { /* the char is not valid in all encodings -> * draw it using the first font :-( */ fnum = first; ucs2fontmap(glyph, '?', encodings[fnum]); } if (last_fnum != fnum || no_spc) { XSetFont(display, gc, fonts[last_fnum]->fid); XDrawString16(display, d, gc, x, y, buf, i); x += XTextWidth16(fonts[last_fnum], buf, i); i = 0; (*buf).byte1 = glyph[0]; (*buf).byte2 = glyph[1]; if (no_spc) { x -= XTextWidth16(fonts[fnum], buf, 1); } } else { (*(buf + i)).byte1 = glyph[0]; (*(buf + i)).byte2 = glyph[1]; } last_fnum = fnum; i++; string += ulen; num_bytes -= ulen; } XSetFont(display, gc, fonts[fnum]->fid); XDrawString16(display, d, gc, x, y, buf, i); } /*****************************************************************************/ /** Measure the inked extents of a UTF-8 string using multiple fonts as **/ /** needed. Tries to mirror the behaviour of the draw function **/ /** XUtf8DrawString() as closely as possible to get consistent sizes. **/ /*****************************************************************************/ void XUtf8_measure_extents( Display *display, Drawable d, XUtf8FontStruct *font_set, GC gc, int *xx, /* x-offset from origin */ int *yy, /* y-offset from origin */ int *ww, /* overall inked width */ int *hh, /* maximum inked height */ const char *string, /* text to measure */ int num_bytes) { int *encodings; /* encodings array */ XFontStruct **fonts; /* fonts array */ Fl_XChar2b buf[128]; /* drawing buffer */ int fnum; /* index of the current font in the fonts array*/ int i; /* current byte in the XChar2b buffer */ int first; /* first valid font index */ int last_fnum; /* font index of the previous char */ int nb_font; /* quantity of fonts in the font array */ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */ int *ranges; /* sub range of iso10646 */ int wd = 0; /* accumulates the width of the text */ int ht = 0; /* used to find max height in text */ int hs; /* "height sum" of current text segment */ int yt = 0x7FFFFFFF; /* used to find bounding rectangle delta-y */ /* int res; */ /* result from calling XTextExtents16() - we should test this is OK! */ /* FC: the man does not specify error codes for it, but X will generate X errors like BadGC or BadFont. */ XCharStruct sizes; int dir_ret = 0; int fnt_asc = 0; int fnt_dsc = 0; nb_font = font_set->nb_font; if (nb_font < 1) { /* there is no font in the font_set :-( */ return; } ranges = font_set->ranges; fonts = font_set->fonts; encodings = font_set->encodings; i = 0; fnum = 0; while(fnum < nb_font && !fonts[fnum]) fnum++; if (fnum >= nb_font) { /* there is no valid font for the X server */ return; } first = fnum; last_fnum = fnum; while (num_bytes > 0) { int ulen; /* byte length of the UTF-8 char */ unsigned int ucs; /* Unicode value of the UTF-8 char */ unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */ if (i > 120) { /*** draw the buffer **/ XSetFont(display, gc, fonts[fnum]->fid); /* res = */ XTextExtents16(fonts[fnum], buf, i, &dir_ret, &fnt_asc, &fnt_dsc, &sizes); /* recover the dimensions - should verify that res == 0 first! */ wd += sizes.width; /* accumulate the width */ hs = sizes.ascent + sizes.descent; /* total height */ if(hs > ht) ht = hs; /* new height exceeds previous height */ if(yt > (-sizes.ascent)) yt = -sizes.ascent; /* delta y offset */ i = 0; } ulen = XFastConvertUtf8ToUcs((const unsigned char*)string, num_bytes, &ucs); if (ulen < 1) ulen = 1; no_spc = XUtf8IsNonSpacing(ucs); if (no_spc) ucs = no_spc; /* * find the first encoding which can be used to * draw the glyph */ fnum = first; while (fnum < nb_font) { if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { if (encodings[fnum] != 0 || ((int)ucs >= ranges[fnum * 2] && (int)ucs <= ranges[fnum * 2 + 1])) { break; } } fnum++; } if (fnum == nb_font) { /* the char is not valid in all encodings -> * draw it using the first font :-( */ fnum = first; ucs2fontmap(glyph, '?', encodings[fnum]); } if (last_fnum != fnum || no_spc) { XSetFont(display, gc, fonts[last_fnum]->fid); /* res = */ XTextExtents16(fonts[last_fnum], buf, i, &dir_ret, &fnt_asc, &fnt_dsc, &sizes); /* recover the dimensions - should verify that res == 0 first! */ wd += sizes.width; /* accumulate the width */ hs = sizes.ascent + sizes.descent; /* total height */ if(hs > ht) ht = hs; /* new height exceeds previous height */ if(yt > (-sizes.ascent)) yt = -sizes.ascent; /* delta y offset */ i = 0; (*buf).byte1 = glyph[0]; (*buf).byte2 = glyph[1]; if (no_spc) { wd -= XTextWidth16(fonts[fnum], buf, 1); } } else { (*(buf + i)).byte1 = glyph[0]; (*(buf + i)).byte2 = glyph[1]; } last_fnum = fnum; i++; string += ulen; num_bytes -= ulen; } XSetFont(display, gc, fonts[fnum]->fid); /* res = */ XTextExtents16(fonts[fnum], buf, i, &dir_ret, &fnt_asc, &fnt_dsc, &sizes); /* recover the dimensions - should verify that res == 0 first! */ wd += sizes.width; /* accumulate the width */ hs = sizes.ascent + sizes.descent; /* total height */ if(hs > ht) ht = hs; /* new height exceeds previous height */ if(yt > (-sizes.ascent)) yt = -sizes.ascent; /* delta y offset */ /* return values */ *ww = wd; /* width of inked area rectangle */ *hh = ht; /* max height of inked area rectangle */ *xx = 0; /* x-offset from origin to start of inked area - this is wrong! */ *yy = yt; /* y-offset from origin to start of inked rectangle */ } /*****************************************************************************/ /** returns the pixel width of a UTF-8 string **/ /*****************************************************************************/ int XUtf8TextWidth(XUtf8FontStruct *font_set, const char *string, int num_bytes) { int x; int *encodings; /* encodings array */ XFontStruct **fonts; /* fonts array */ Fl_XChar2b buf[128]; /* drawing buffer */ int fnum; /* index of the current font in the fonts array*/ int i; /* current byte in the XChar2b buffer */ int first; /* first valid font index */ int last_fnum; /* font index of the previous char */ int nb_font; /* quantity of fonts in the font array */ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */ int *ranges; /* sub range of iso10646 */ nb_font = font_set->nb_font; x = 0; if (nb_font < 1) { /* there is no font in the font_set :-( */ return x; } ranges = font_set->ranges; fonts = font_set->fonts; encodings = font_set->encodings; i = 0; fnum = 0; while(fnum < nb_font && !fonts[fnum]) fnum++; if (fnum >= nb_font) { /* there is no valid font for the X server */ return x; } first = fnum; last_fnum = fnum; while (num_bytes > 0) { int ulen; /* byte length of the UTF-8 char */ unsigned int ucs; /* Unicode value of the UTF-8 char */ unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */ if (i > 120) { /*** measure the buffer **/ x += XTextWidth16(fonts[fnum], buf, i); i = 0; } ulen = XFastConvertUtf8ToUcs((const unsigned char*)string, num_bytes, &ucs); if (ulen < 1) ulen = 1; no_spc = XUtf8IsNonSpacing(ucs); if (no_spc) { ucs = no_spc; } /* * find the first encoding which can be used to * draw the glyph */ fnum = first; while (fnum < nb_font) { if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { if (encodings[fnum] != 0 || ((int)ucs >= ranges[fnum * 2] && (int)ucs <= ranges[fnum * 2 + 1])) { break; } } fnum++; } if (fnum == nb_font) { /* the char is not valid in all encodings -> * draw it using the first font :-( */ fnum = first; ucs2fontmap(glyph, '?', encodings[fnum]); } if (last_fnum != fnum || no_spc) { x += XTextWidth16(fonts[last_fnum], buf, i); i = 0; (*buf).byte1 = glyph[0]; (*buf).byte2 = glyph[1]; if (no_spc) { /* go back to draw the non-spacing char over the previous char */ x -= XTextWidth16(fonts[fnum], buf, 1); } } else { (*(buf + i)).byte1 = glyph[0]; (*(buf + i)).byte2 = glyph[1]; } last_fnum = fnum; i++; string += ulen; num_bytes -= ulen; } x += XTextWidth16(fonts[last_fnum], buf, i); return x; } /*****************************************************************************/ /** get the X font and glyph ID of a UCS char **/ /*****************************************************************************/ int fl_XGetUtf8FontAndGlyph(XUtf8FontStruct *font_set, unsigned int ucs, XFontStruct **fnt, unsigned short *id) { int *encodings; /* encodings array */ XFontStruct **fonts; /* fonts array */ int fnum; /* index of the current font in the fonts array*/ int first; /* first valid font index */ int nb_font; /* quantity of fonts in the font array */ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */ int *ranges; /* sub range of iso10646 */ nb_font = font_set->nb_font; if (nb_font < 1) { /* there is no font in the font_set :-( */ return -1; } ranges = font_set->ranges; fonts = font_set->fonts; encodings = font_set->encodings; fnum = 0; while(fnum < nb_font && !fonts[fnum]) fnum++; if (fnum >= nb_font) { /* there is no valid font for the X server */ return -1; } first = fnum; /* * find the first encoding which can be used to draw the glyph */ fnum = first; while (fnum < nb_font) { if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { if (encodings[fnum] != 0 || ((int)ucs >= ranges[fnum * 2] && (int)ucs <= ranges[fnum * 2 + 1])) { break; } } fnum++; } if (fnum == nb_font) { /* the char is not valid in all encodings -> * draw it using the first font :-( */ fnum = first; ucs2fontmap(glyph, '?', encodings[fnum]); } *id = ((unsigned char)glyph[0] << 8) | (unsigned char)glyph[1] ; *fnt = fonts[fnum]; return 0; } /*****************************************************************************/ /** returns the pixel width of a UCS char **/ /*****************************************************************************/ int XUtf8UcsWidth(XUtf8FontStruct *font_set, unsigned int ucs) { int x; int *encodings; /* encodings array */ XFontStruct **fonts; /* fonts array */ Fl_XChar2b buf[8]; /* drawing buffer */ int fnum; /* index of the current font in the fonts array*/ int first; /* first valid font index */ int nb_font; /* quantity of fonts in the font array */ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */ int *ranges; /* sub range of iso10646 */ unsigned int no_spc; nb_font = font_set->nb_font; x = 0; if (nb_font < 1) { /* there is no font in the font_set :-( */ return x; } ranges = font_set->ranges; fonts = font_set->fonts; encodings = font_set->encodings; fnum = 0; while(fnum < nb_font && !fonts[fnum]) fnum++; if (fnum >= nb_font) { /* there is no valid font for the X server */ return x; } first = fnum; no_spc = XUtf8IsNonSpacing(ucs); if (no_spc) ucs = no_spc; /* * find the first encoding which can be used to * draw the glyph */ fnum = first; while (fnum < nb_font) { if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) { if (encodings[fnum] != 0 || ((int)ucs >= ranges[fnum * 2] && (int)ucs <= ranges[fnum * 2 + 1])) { break; } } fnum++; } if (fnum == nb_font) { /* the char is not valid in all encodings -> * draw it using the first font :-( */ fnum = first; ucs2fontmap(glyph, '?', encodings[fnum]); } (*buf).byte1 = glyph[0]; (*buf).byte2 = glyph[1]; x += XTextWidth16(fonts[fnum], buf, 1); return x; } /*****************************************************************************/ /** draw an UTF-8 string and clear the background. **/ /*****************************************************************************/ void XUtf8DrawImageString(Display *display, Drawable d, XUtf8FontStruct *font_set, GC gc, int x, int y, const char *string, int num_bytes) { /* FIXME: must be improved ! */ int w; int fill_style; unsigned long foreground; unsigned long background; int function; XGCValues xgcv; w = XUtf8TextWidth(font_set, string, num_bytes); XGetGCValues(display, gc, GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv); function = xgcv.function; fill_style = xgcv.fill_style; foreground = xgcv.foreground; background = xgcv.background; xgcv.function = GXcopy; xgcv.foreground = background; xgcv.background = foreground; xgcv.fill_style = FillSolid; XChangeGC(display, gc, GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv); XFillRectangle(display, d, gc, x, y - font_set->ascent, (unsigned)w, (unsigned)(font_set->ascent + font_set->descent)); xgcv.function = function; xgcv.foreground = foreground; xgcv.background = background; xgcv.fill_style = fill_style; XChangeGC(display, gc, GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv); XUtf8DrawString(display, d, font_set, gc, x, y, string, num_bytes); } /*****************************************************************************/ /** free the XFontSet and others things created by XCreateUtf8FontSet **/ /*****************************************************************************/ void XFreeUtf8FontStruct(Display *dpy, XUtf8FontStruct *font_set) { int i; i = 0; while (i < font_set->nb_font) { if (font_set->fonts[i]) { XFreeFont(dpy, font_set->fonts[i]); free(font_set->font_name_list[i]); } i++; } free(font_set->ranges); free(font_set->font_name_list); free(font_set->fonts); free(font_set->encodings); free(font_set); } fltk-1.4.3/src/xutf8/fl_wcwidth.c0000644000175000017500000000214215004135251016747 0ustar albrechtalbrecht/* * wrapper(s) around Markus Kuhn's wcwidth() implementation. * * Copyright 2006-2010 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* include Markus Kuhn's wcwidth() implementation. * Note: only the filename has been changes at the moment. * forward declare the routines as static to avoid name leakage. */ #if 0 #include /* for size_t only */ #endif static int mk_wcwidth(unsigned int ucs); #if 0 static int mk_wcswidth(const unsigned int *pwcs, size_t n); static int mk_wcwidth_cjk(unsigned int ucs); static int mk_wcswidth_cjk(const unsigned int *pwcs, size_t n); #endif #include "mk_wcwidth.c" int fl_wcwidth(unsigned int ucs) { /* warning: we have problems if sizeof(wchar_t) == 2 and ucs > 0xffff */ return mk_wcwidth(ucs); } fltk-1.4.3/src/xutf8/lcUniConv/0000755000175000017500000000000015004135251016352 5ustar albrechtalbrechtfltk-1.4.3/src/xutf8/lcUniConv/koi8_u.h0000644000175000017500000001471515004135251017731 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/koi8_u.h,v 1.3 2000/11/29 17:40:34 dawes Exp $ */ /* * KOI8-U */ /* Specification: RFC 2319 */ #ifdef NEED_TOWC static const unsigned short koi8_u_2uni[128] = { /* 0x80 */ 0x2500, 0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524, 0x252c, 0x2534, 0x253c, 0x2580, 0x2584, 0x2588, 0x258c, 0x2590, /* 0x90 */ 0x2591, 0x2592, 0x2593, 0x2320, 0x25a0, 0x2219, 0x221a, 0x2248, 0x2264, 0x2265, 0x00a0, 0x2321, 0x00b0, 0x00b2, 0x00b7, 0x00f7, /* 0xa0 */ 0x2550, 0x2551, 0x2552, 0x0451, 0x0454, 0x2554, 0x0456, 0x0457, 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x0491, 0x255d, 0x255e, /* 0xb0 */ 0x255f, 0x2560, 0x2561, 0x0401, 0x0404, 0x2563, 0x0406, 0x0407, 0x2566, 0x2567, 0x2568, 0x2569, 0x256a, 0x0490, 0x256c, 0x00a9, /* 0xc0 */ 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, /* 0xd0 */ 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, /* 0xe0 */ 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, /* 0xf0 */ 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a, }; static int koi8_u_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x80) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) koi8_u_2uni[c-0x80]; return 1; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char koi8_u_page00[88] = { 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */ 0x9c, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xb0-0xb7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, /* 0xf0-0xf7 */ }; static const unsigned char koi8_u_page04[152] = { 0x00, 0xb3, 0x00, 0x00, 0xb4, 0x00, 0xb6, 0xb7, /* 0x00-0x07 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa, /* 0x10-0x17 */ 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, /* 0x18-0x1f */ 0xf2, 0xf3, 0xf4, 0xf5, 0xe6, 0xe8, 0xe3, 0xfe, /* 0x20-0x27 */ 0xfb, 0xfd, 0xff, 0xf9, 0xf8, 0xfc, 0xe0, 0xf1, /* 0x28-0x2f */ 0xc1, 0xc2, 0xd7, 0xc7, 0xc4, 0xc5, 0xd6, 0xda, /* 0x30-0x37 */ 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, /* 0x38-0x3f */ 0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde, /* 0x40-0x47 */ 0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1, /* 0x48-0x4f */ 0x00, 0xa3, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0xa7, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0xbd, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ }; static const unsigned char koi8_u_page22[80] = { 0x00, 0x95, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x98, 0x99, 0x00, 0x00, /* 0x60-0x67 */ }; static const unsigned char koi8_u_page23[8] = { 0x93, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ }; static const unsigned char koi8_u_page25[168] = { 0x80, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */ 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x85, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0xa0, 0xa1, 0xa2, 0x00, 0xa5, 0x00, 0x00, 0xa8, /* 0x50-0x57 */ 0xa9, 0xaa, 0xab, 0xac, 0x00, 0xae, 0xaf, 0xb0, /* 0x58-0x5f */ 0xb1, 0xb2, 0x00, 0xb5, 0x00, 0x00, 0xb8, 0xb9, /* 0x60-0x67 */ 0xba, 0xbb, 0xbc, 0x00, 0xbe, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0x8b, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x8d, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0x8f, 0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */ 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ }; static int koi8_u_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x0080) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00f8) c = koi8_u_page00[wc-0x00a0]; else if (wc >= 0x0400 && wc < 0x0498) c = koi8_u_page04[wc-0x0400]; else if (wc >= 0x2218 && wc < 0x2268) c = koi8_u_page22[wc-0x2218]; else if (wc >= 0x2320 && wc < 0x2328) c = koi8_u_page23[wc-0x2320]; else if (wc >= 0x2500 && wc < 0x25a8) c = koi8_u_page25[wc-0x2500]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/tatar_cyr.h0000644000175000017500000001225415004135251020517 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/tatar_cyr.h,v 1.3 2000/12/04 18:49:42 dawes Exp $ */ /* * TATAR-CYR */ static const unsigned short tatar_cyr_2uni[128] = { /* 0x80 */ 0x04d8, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, 0x20ac, 0x2030, 0x04e8, 0x2039, 0x04ae, 0x0496, 0x04a2, 0x04ba, /* 0x90 */ 0x04d9, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x98, 0x2122, 0x04e9, 0x203a, 0x04af, 0x0497, 0x04a3, 0x04bb, /* 0xa0 */ 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, /* 0xb0 */ 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, /* 0xc0 */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, /* 0xd0 */ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, /* 0xe0 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, /* 0xf0 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, }; static int tatar_cyr_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x80) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) tatar_cyr_2uni[c-0x80]; return 1; } static const unsigned char tatar_cyr_page00[32] = { 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */ 0x00, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00, /* 0xa8-0xaf */ 0xb0, 0xb1, 0x00, 0x00, 0x00, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */ 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ }; static const unsigned char tatar_cyr_page04[240] = { 0x00, 0xa8, 0x00, 0x81, 0xaa, 0xbd, 0xb2, 0xaf, /* 0x00-0x07 */ 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, /* 0x08-0x0f */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x10-0x17 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x18-0x1f */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x20-0x27 */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0x28-0x2f */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x30-0x37 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x38-0x3f */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x40-0x47 */ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0x48-0x4f */ 0x00, 0xb8, 0x00, 0x83, 0xba, 0xbe, 0xb3, 0xbf, /* 0x50-0x57 */ 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x00, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0xa5, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x9d, /* 0x90-0x97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */ 0x00, 0x00, 0x8e, 0x9e, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x9c, /* 0xa8-0xaf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ 0x00, 0x00, 0x8f, 0x9f, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ 0x80, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */ 0x8a, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ }; static const unsigned char tatar_cyr_page20[48] = { 0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */ 0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ }; static const unsigned char tatar_cyr_page21[24] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x00, /* 0x10-0x17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ }; static const unsigned char tatar_cyr_page22[1] = { 0xb0, /* 0x16-0x16 */ }; static int tatar_cyr_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x0080) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00bc) c = tatar_cyr_page00[wc-0x00a0]; else if (wc >= 0x0400 && wc < 0x04ef) c = tatar_cyr_page04[wc-0x0400]; else if (wc >= 0x2010 && wc < 0x203b) c = tatar_cyr_page20[wc-0x2010]; else if (wc == 0x20ac) c = 0x88; else if (wc >= 0x2110 && wc < 0x2123) c = tatar_cyr_page21[wc-0x2110]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/armscii_8.h0000644000175000017500000000664115004135251020410 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/armscii_8.h,v 1.4 2003/07/15 17:33:45 pascal Exp $ */ /* * ARMSCII-8 */ static const unsigned short armscii_8_2uni[96] = { /* 0xa0 */ 0x00a0, 0xfffd, 0x0587, 0x0589, 0x0029, 0x0028, 0x00bb, 0x00ab, 0x2014, 0x002e, 0x055d, 0x002c, 0x002d, 0x058a, 0x2026, 0x055c, /* 0xb0 */ 0x055b, 0x055e, 0x0531, 0x0561, 0x0532, 0x0562, 0x0533, 0x0563, 0x0534, 0x0564, 0x0535, 0x0565, 0x0536, 0x0566, 0x0537, 0x0567, /* 0xc0 */ 0x0538, 0x0568, 0x0539, 0x0569, 0x053a, 0x056a, 0x053b, 0x056b, 0x053c, 0x056c, 0x053d, 0x056d, 0x053e, 0x056e, 0x053f, 0x056f, /* 0xd0 */ 0x0540, 0x0570, 0x0541, 0x0571, 0x0542, 0x0572, 0x0543, 0x0573, 0x0544, 0x0574, 0x0545, 0x0575, 0x0546, 0x0576, 0x0547, 0x0577, /* 0xe0 */ 0x0548, 0x0578, 0x0549, 0x0579, 0x054a, 0x057a, 0x054b, 0x057b, 0x054c, 0x057c, 0x054d, 0x057d, 0x054e, 0x057e, 0x054f, 0x057f, /* 0xf0 */ 0x0550, 0x0580, 0x0551, 0x0581, 0x0552, 0x0582, 0x0553, 0x0583, 0x0554, 0x0584, 0x0555, 0x0585, 0x0556, 0x0586, 0x055a, 0xfffd, }; static int armscii_8_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) { *pwc = (ucs4_t) c; return 1; } else { unsigned short wc = armscii_8_2uni[c-0xa0]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } return RET_ILSEQ; } static const unsigned char armscii_8_page00[8] = { 0xa5, 0xa4, 0x2a, 0x2b, 0xab, 0xac, 0xa9, 0x2f, /* 0x28-0x2f */ }; static const unsigned char armscii_8_page00_1[32] = { 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ }; static const unsigned char armscii_8_page05[96] = { 0x00, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, /* 0x30-0x37 */ 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, /* 0x38-0x3f */ 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, /* 0x40-0x47 */ 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, /* 0x48-0x4f */ 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0xfe, 0xb0, 0xaf, 0xaa, 0xb1, 0x00, /* 0x58-0x5f */ 0x00, 0xb3, 0xb5, 0xb7, 0xb9, 0xbb, 0xbd, 0xbf, /* 0x60-0x67 */ 0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf, /* 0x68-0x6f */ 0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf, /* 0x70-0x77 */ 0xe1, 0xe3, 0xe5, 0xe7, 0xe9, 0xeb, 0xed, 0xef, /* 0x78-0x7f */ 0xf1, 0xf3, 0xf5, 0xf7, 0xf9, 0xfb, 0xfd, 0xa2, /* 0x80-0x87 */ 0x00, 0xa3, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ }; static const unsigned char armscii_8_page20[24] = { 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, /* 0x20-0x27 */ }; static int armscii_8_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x0028) { *r = wc; return 1; } else if (wc >= 0x0028 && wc < 0x0030) c = armscii_8_page00[wc-0x0028]; else if (wc >= 0x0030 && wc < 0x00a0) c = wc; else if (wc >= 0x00a0 && wc < 0x00c0) c = armscii_8_page00_1[wc-0x00a0]; else if (wc >= 0x0530 && wc < 0x0590) c = armscii_8_page05[wc-0x0530]; else if (wc >= 0x2010 && wc < 0x2028) c = armscii_8_page20[wc-0x2010]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/iso8859_13.h0000644000175000017500000000730715004135251020165 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_13.h,v 1.2 2000/11/28 16:10:26 dawes Exp $ */ /* * ISO-8859-13 */ #ifdef NEED_TOWC static const unsigned short iso8859_13_2uni[96] = { /* 0xa0 */ 0x00a0, 0x201d, 0x00a2, 0x00a3, 0x00a4, 0x201e, 0x00a6, 0x00a7, 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6, /* 0xb0 */ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x201c, 0x00b5, 0x00b6, 0x00b7, 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6, /* 0xc0 */ 0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b, /* 0xd0 */ 0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df, /* 0xe0 */ 0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c, /* 0xf0 */ 0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x2019, }; static int iso8859_13_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) iso8859_13_2uni[c-0xa0]; return 1; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_13_page00[224] = { 0xa0, 0x00, 0xa2, 0xa3, 0xa4, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */ 0x00, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00, /* 0xa8-0xaf */ 0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */ 0x00, 0xb9, 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, /* 0xb8-0xbf */ 0x00, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0xaf, 0x00, /* 0xc0-0xc7 */ 0x00, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0xd3, 0x00, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */ 0xa8, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */ 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe5, 0xbf, 0x00, /* 0xe0-0xe7 */ 0x00, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ 0x00, 0x00, 0x00, 0xf3, 0x00, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */ 0xb8, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */ /* 0x0100 */ 0xc2, 0xe2, 0x00, 0x00, 0xc0, 0xe0, 0xc3, 0xe3, /* 0x00-0x07 */ 0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00, /* 0x08-0x0f */ 0x00, 0x00, 0xc7, 0xe7, 0x00, 0x00, 0xcb, 0xeb, /* 0x10-0x17 */ 0xc6, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0xce, 0xee, 0x00, 0x00, 0xc1, 0xe1, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xed, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0xcf, 0xef, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0xd9, 0xf9, 0xd1, 0xf1, 0xd2, 0xf2, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0x00, 0x00, 0xd4, 0xf4, 0x00, 0x00, /* 0x48-0x4f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xba, /* 0x50-0x57 */ 0x00, 0x00, 0xda, 0xfa, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0xdb, 0xfb, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0xd8, 0xf8, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0xca, 0xea, 0xdd, 0xfd, 0xde, 0xfe, 0x00, /* 0x78-0x7f */ }; static const unsigned char iso8859_13_page20[8] = { 0x00, 0xff, 0x00, 0x00, 0xb4, 0xa1, 0xa5, 0x00, /* 0x18-0x1f */ }; static int iso8859_13_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x0180) c = iso8859_13_page00[wc-0x00a0]; else if (wc >= 0x2018 && wc < 0x2020) c = iso8859_13_page20[wc-0x2018]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOWC */ fltk-1.4.3/src/xutf8/lcUniConv/iso8859_9e.h0000644000175000017500000001002715004135251020250 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_9e.h,v 1.3 2000/11/28 16:10:28 dawes Exp $ */ /* * ISO-8859-9E */ static const unsigned short iso8859_9e_2uni[96] = { /* 0xa0 */ 0x00a0, 0x017d, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x012c, 0x00a7, 0x016c, 0x00a9, 0x01e6, 0x00ab, 0x014a, 0x00ad, 0x00ae, 0x01d1, /* 0xb0 */ 0x00b0, 0x017e, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x012d, 0x00b7, 0x016d, 0x00b9, 0x01e7, 0x00bb, 0x014b, 0x00bd, 0x0178, 0x01d2, /* 0xc0 */ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x018f, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, /* 0xd0 */ 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00dd, 0x019f, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, /* 0xe0 */ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x0259, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* 0xf0 */ 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00fd, 0x0275, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, }; static int iso8859_9e_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c >= 0xa0) *pwc = (ucs4_t) iso8859_9e_2uni[c-0xa0]; else *pwc = (ucs4_t) c; return 1; } static const unsigned char iso8859_9e_page00[96] = { 0xa0, 0x00, 0xa2, 0xa3, 0x00, 0xa5, 0x00, 0xa7, /* 0xa0-0xa7 */ 0x00, 0xa9, 0x00, 0xab, 0x00, 0xad, 0xae, 0x00, /* 0xa8-0xaf */ 0xb0, 0x00, 0xb2, 0xb3, 0xb4, 0xb5, 0x00, 0xb7, /* 0xb0-0xb7 */ 0x00, 0xb9, 0x00, 0xbb, 0x00, 0xbd, 0x00, 0x00, /* 0xb8-0xbf */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0x00, 0xc7, /* 0xc0-0xc7 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */ 0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* 0xd0-0xd7 */ 0x00, 0xd9, 0xda, 0xdb, 0xdc, 0xd7, 0x00, 0xdf, /* 0xd8-0xdf */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0x00, 0xe7, /* 0xe0-0xe7 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0x00, /* 0xf0-0xf7 */ 0x00, 0xf9, 0xfa, 0xfb, 0xfc, 0xf7, 0x00, 0xff, /* 0xf8-0xff */ }; static const unsigned char iso8859_9e_page01[136] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xf0, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0xa6, 0xb6, 0x00, 0x00, /* 0x28-0x2f */ 0xdd, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0xac, 0xbc, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xfe, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0xa8, 0xb8, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0xbe, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xb1, 0x00, /* 0x78-0x7f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, /* 0x88-0x8f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, /* 0x98-0x9f */ }; static const unsigned char iso8859_9e_page01_d[24] = { 0x00, 0xaf, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xba, /* 0xe0-0xe7 */ }; static int iso8859_9e_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x0100) c = iso8859_9e_page00[wc-0x00a0]; else if (wc >= 0x0118 && wc < 0x01a0) c = iso8859_9e_page01[wc-0x0118]; else if (wc >= 0x01d0 && wc < 0x01e8) c = iso8859_9e_page01_d[wc-0x01d0]; else if (wc == 0x0259) c = 0xe6; else if (wc == 0x0275) c = 0xf8; else if (wc == 0x20ac) c = 0xa4; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/iso8859_14.h0000644000175000017500000001105115004135251020155 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_14.h,v 1.3 2000/11/29 17:40:30 dawes Exp $ */ /* * ISO-8859-14 */ #ifdef NEED_TOWC static const unsigned short iso8859_14_2uni[96] = { /* 0xa0 */ 0x00a0, 0x1e02, 0x1e03, 0x00a3, 0x010a, 0x010b, 0x1e0a, 0x00a7, 0x1e80, 0x00a9, 0x1e82, 0x1e0b, 0x1ef2, 0x00ad, 0x00ae, 0x0178, /* 0xb0 */ 0x1e1e, 0x1e1f, 0x0120, 0x0121, 0x1e40, 0x1e41, 0x00b6, 0x1e56, 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, /* 0xc0 */ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, /* 0xd0 */ 0x0174, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x1e6a, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x0176, 0x00df, /* 0xe0 */ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* 0xf0 */ 0x0175, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x1e6b, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x0177, 0x00ff, }; static int iso8859_14_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c >= 0xa0) *pwc = (ucs4_t) iso8859_14_2uni[c-0xa0]; else *pwc = (ucs4_t) c; return 1; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_14_page00[96] = { 0xa0, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */ 0x00, 0xa9, 0x00, 0x00, 0x00, 0xad, 0xae, 0x00, /* 0xa8-0xaf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, /* 0xb0-0xb7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */ 0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* 0xd0-0xd7 */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x00, 0xdf, /* 0xd8-0xdf */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0x00, /* 0xf0-0xf7 */ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0x00, 0xff, /* 0xf8-0xff */ }; static const unsigned char iso8859_14_page01_0[32] = { 0x00, 0x00, 0xa4, 0xa5, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0xb2, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ }; static const unsigned char iso8859_14_page01_1[16] = { 0x00, 0x00, 0x00, 0x00, 0xd0, 0xf0, 0xde, 0xfe, /* 0x70-0x77 */ 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ }; static const unsigned char iso8859_14_page1e_0[136] = { 0x00, 0x00, 0xa1, 0xa2, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */ 0x00, 0x00, 0xa6, 0xab, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb1, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0xb4, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xb9, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0xbb, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0xd7, 0xf7, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0xa8, 0xb8, 0xaa, 0xba, 0xbd, 0xbe, 0x00, 0x00, /* 0x80-0x87 */ }; static const unsigned char iso8859_14_page1e_1[8] = { 0x00, 0x00, 0xac, 0xbc, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */ }; static int iso8859_14_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x0100) c = iso8859_14_page00[wc-0x00a0]; else if (wc >= 0x0108 && wc < 0x0128) c = iso8859_14_page01_0[wc-0x0108]; else if (wc >= 0x0170 && wc < 0x0180) c = iso8859_14_page01_1[wc-0x0170]; else if (wc >= 0x1e00 && wc < 0x1e88) c = iso8859_14_page1e_0[wc-0x1e00]; else if (wc >= 0x1ef0 && wc < 0x1ef8) c = iso8859_14_page1e_1[wc-0x1ef0]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/koi8_r.h0000644000175000017500000001367515004135251017732 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/koi8_r.h,v 1.3 2000/11/29 17:40:34 dawes Exp $ */ /* * KOI8-R */ /* Specification: RFC 1489 */ #ifdef NEED_TOWC static const unsigned short koi8_r_2uni[128] = { /* 0x80 */ 0x2500, 0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524, 0x252c, 0x2534, 0x253c, 0x2580, 0x2584, 0x2588, 0x258c, 0x2590, /* 0x90 */ 0x2591, 0x2592, 0x2593, 0x2320, 0x25a0, 0x2219, 0x221a, 0x2248, 0x2264, 0x2265, 0x00a0, 0x2321, 0x00b0, 0x00b2, 0x00b7, 0x00f7, /* 0xa0 */ 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e, /* 0xb0 */ 0x255f, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x00a9, /* 0xc0 */ 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, /* 0xd0 */ 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, /* 0xe0 */ 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, /* 0xf0 */ 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a, }; static int koi8_r_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x80) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) koi8_r_2uni[c-0x80]; return 1; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char koi8_r_page00[88] = { 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */ 0x9c, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x9e, /* 0xb0-0xb7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, /* 0xf0-0xf7 */ }; static const unsigned char koi8_r_page04[88] = { 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa, /* 0x10-0x17 */ 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, /* 0x18-0x1f */ 0xf2, 0xf3, 0xf4, 0xf5, 0xe6, 0xe8, 0xe3, 0xfe, /* 0x20-0x27 */ 0xfb, 0xfd, 0xff, 0xf9, 0xf8, 0xfc, 0xe0, 0xf1, /* 0x28-0x2f */ 0xc1, 0xc2, 0xd7, 0xc7, 0xc4, 0xc5, 0xd6, 0xda, /* 0x30-0x37 */ 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, /* 0x38-0x3f */ 0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde, /* 0x40-0x47 */ 0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1, /* 0x48-0x4f */ 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ }; static const unsigned char koi8_r_page22[80] = { 0x00, 0x95, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x98, 0x99, 0x00, 0x00, /* 0x60-0x67 */ }; static const unsigned char koi8_r_page23[8] = { 0x93, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ }; static const unsigned char koi8_r_page25[168] = { 0x80, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */ 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x85, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0xa0, 0xa1, 0xa2, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, /* 0x50-0x57 */ 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, /* 0x58-0x5f */ 0xb1, 0xb2, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, /* 0x60-0x67 */ 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0x8b, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x8d, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0x8f, 0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */ 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ }; static int koi8_r_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x0080) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00f8) c = koi8_r_page00[wc-0x00a0]; else if (wc >= 0x0400 && wc < 0x0458) c = koi8_r_page04[wc-0x0400]; else if (wc >= 0x2218 && wc < 0x2268) c = koi8_r_page22[wc-0x2218]; else if (wc >= 0x2320 && wc < 0x2328) c = koi8_r_page23[wc-0x2320]; else if (wc >= 0x2500 && wc < 0x25a8) c = koi8_r_page25[wc-0x2500]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/georgian_academy.h0000644000175000017500000000634715004135251022013 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/georgian_academy.h,v 1.3 2000/11/29 17:40:29 dawes Exp $ */ /* * GEORGIAN-ACADEMY */ static const unsigned short georgian_academy_2uni[32] = { /* 0x80 */ 0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 0x90 */ 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, }; static int georgian_academy_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c >= 0x80 && c < 0xa0) *pwc = (ucs4_t) georgian_academy_2uni[c-0x80]; else if (c >= 0xc0 && c < 0xe7) *pwc = (ucs4_t) c + 0x1010; else *pwc = (ucs4_t) c; return 1; } static const unsigned char georgian_academy_page00[32] = { 0x80, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */ 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */ }; static const unsigned char georgian_academy_page01[72] = { 0x00, 0x00, 0x8c, 0x9c, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0x8a, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ }; static const unsigned char georgian_academy_page02[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ }; static const unsigned char georgian_academy_page20[48] = { 0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */ 0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ }; static int georgian_academy_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x0080) { *r = wc; return 1; } else if (wc >= 0x0080 && wc < 0x00a0) c = georgian_academy_page00[wc-0x0080]; else if ((wc >= 0x00a0 && wc < 0x00c0) || (wc >= 0x00e7 && wc < 0x0100)) c = wc; else if (wc >= 0x0150 && wc < 0x0198) c = georgian_academy_page01[wc-0x0150]; else if (wc >= 0x02c0 && wc < 0x02e0) c = georgian_academy_page02[wc-0x02c0]; else if (wc >= 0x10d0 && wc < 0x10f7) c = wc-0x1010; else if (wc >= 0x2010 && wc < 0x2040) c = georgian_academy_page20[wc-0x2010]; else if (wc == 0x2122) c = 0x99; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/mulelao.h0000644000175000017500000000474615004135251020174 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/mulelao.h,v 1.3 2000/11/29 17:40:35 dawes Exp $ */ /* * MULELAO-1 */ static const unsigned short mulelao_2uni[96] = { /* 0xa0 */ 0x00a0, 0x0e81, 0x0e82, 0xfffd, 0x0e84, 0xfffd, 0xfffd, 0x0e87, 0x0e88, 0xfffd, 0x0e8a, 0xfffd, 0xfffd, 0x0e8d, 0xfffd, 0xfffd, /* 0xb0 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0e94, 0x0e95, 0x0e96, 0x0e97, 0xfffd, 0x0e99, 0x0e9a, 0x0e9b, 0x0e9c, 0x0e9d, 0x0e9e, 0x0e9f, /* 0xc0 */ 0xfffd, 0x0ea1, 0x0ea2, 0x0ea3, 0xfffd, 0x0ea5, 0xfffd, 0x0ea7, 0xfffd, 0xfffd, 0x0eaa, 0x0eab, 0xfffd, 0x0ead, 0x0eae, 0x0eaf, /* 0xd0 */ 0x0eb0, 0x0eb1, 0x0eb2, 0x0eb3, 0x0eb4, 0x0eb5, 0x0eb6, 0x0eb7, 0x0eb8, 0x0eb9, 0xfffd, 0x0ebb, 0x0ebc, 0x0ebd, 0xfffd, 0xfffd, /* 0xe0 */ 0x0ec0, 0x0ec1, 0x0ec2, 0x0ec3, 0x0ec4, 0xfffd, 0x0ec6, 0xfffd, 0x0ec8, 0x0ec9, 0x0eca, 0x0ecb, 0x0ecc, 0x0ecd, 0xfffd, 0xfffd, /* 0xf0 */ 0x0ed0, 0x0ed1, 0x0ed2, 0x0ed3, 0x0ed4, 0x0ed5, 0x0ed6, 0x0ed7, 0x0ed8, 0x0ed9, 0xfffd, 0xfffd, 0x0edc, 0x0edd, 0xfffd, 0xfffd, }; static int mulelao_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) { *pwc = (ucs4_t) c; return 1; } else { unsigned short wc = mulelao_2uni[c-0xa0]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } return RET_ILSEQ; } static const unsigned char mulelao_page0e[96] = { 0x00, 0xa1, 0xa2, 0x00, 0xa4, 0x00, 0x00, 0xa7, /* 0x80-0x87 */ 0xa8, 0x00, 0xaa, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0x88-0x8f */ 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x90-0x97 */ 0x00, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0x98-0x9f */ 0x00, 0xc1, 0xc2, 0xc3, 0x00, 0xc5, 0x00, 0xc7, /* 0xa0-0xa7 */ 0x00, 0x00, 0xca, 0xcb, 0x00, 0xcd, 0xce, 0xcf, /* 0xa8-0xaf */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xb0-0xb7 */ 0xd8, 0xd9, 0x00, 0xdb, 0xdc, 0xdd, 0x00, 0x00, /* 0xb8-0xbf */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x00, 0xe6, 0x00, /* 0xc0-0xc7 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0x00, 0x00, /* 0xc8-0xcf */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xd0-0xd7 */ 0xf8, 0xf9, 0x00, 0x00, 0xfc, 0xfd, 0x00, 0x00, /* 0xd8-0xdf */ }; static int mulelao_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc == 0x00a0) c = 0xa0; else if (wc >= 0x0e80 && wc < 0x0ee0) c = mulelao_page0e[wc-0x0e80]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/cp1133.h0000644000175000017500000000546715004135251017451 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/cp1133.h,v 1.3 2000/11/29 17:40:28 dawes Exp $ */ /* * IBM-CP1133 */ static const unsigned short cp1133_2uni_1[64] = { /* 0xa0 */ 0x00a0, 0x0e81, 0x0e82, 0x0e84, 0x0e87, 0x0e88, 0x0eaa, 0x0e8a, 0x0e8d, 0x0e94, 0x0e95, 0x0e96, 0x0e97, 0x0e99, 0x0e9a, 0x0e9b, /* 0xb0 */ 0x0e9c, 0x0e9d, 0x0e9e, 0x0e9f, 0x0ea1, 0x0ea2, 0x0ea3, 0x0ea5, 0x0ea7, 0x0eab, 0x0ead, 0x0eae, 0xfffd, 0xfffd, 0xfffd, 0x0eaf, /* 0xc0 */ 0x0eb0, 0x0eb2, 0x0eb3, 0x0eb4, 0x0eb5, 0x0eb6, 0x0eb7, 0x0eb8, 0x0eb9, 0x0ebc, 0x0eb1, 0x0ebb, 0x0ebd, 0xfffd, 0xfffd, 0xfffd, /* 0xd0 */ 0x0ec0, 0x0ec1, 0x0ec2, 0x0ec3, 0x0ec4, 0x0ec8, 0x0ec9, 0x0eca, 0x0ecb, 0x0ecc, 0x0ecd, 0x0ec6, 0xfffd, 0x0edc, 0x0edd, 0x20ad, }; static const unsigned short cp1133_2uni_2[16] = { /* 0xf0 */ 0x0ed0, 0x0ed1, 0x0ed2, 0x0ed3, 0x0ed4, 0x0ed5, 0x0ed6, 0x0ed7, 0x0ed8, 0x0ed9, 0xfffd, 0xfffd, 0x00a2, 0x00ac, 0x00a6, 0xfffd, }; static int cp1133_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) { *pwc = (ucs4_t) c; return 1; } else if (c < 0xe0) { unsigned short wc = cp1133_2uni_1[c-0xa0]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } else if (c < 0xf0) { } else { unsigned short wc = cp1133_2uni_2[c-0xf0]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } return RET_ILSEQ; } static const unsigned char cp1133_page00[16] = { 0xa0, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfe, 0x00, /* 0xa0-0xa7 */ 0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, /* 0xa8-0xaf */ }; static const unsigned char cp1133_page0e[96] = { 0x00, 0xa1, 0xa2, 0x00, 0xa3, 0x00, 0x00, 0xa4, /* 0x80-0x87 */ 0xa5, 0x00, 0xa7, 0x00, 0x00, 0xa8, 0x00, 0x00, /* 0x88-0x8f */ 0x00, 0x00, 0x00, 0x00, 0xa9, 0xaa, 0xab, 0xac, /* 0x90-0x97 */ 0x00, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, /* 0x98-0x9f */ 0x00, 0xb4, 0xb5, 0xb6, 0x00, 0xb7, 0x00, 0xb8, /* 0xa0-0xa7 */ 0x00, 0x00, 0xa6, 0xb9, 0x00, 0xba, 0xbb, 0xbf, /* 0xa8-0xaf */ 0xc0, 0xca, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, /* 0xb0-0xb7 */ 0xc7, 0xc8, 0x00, 0xcb, 0xc9, 0xcc, 0x00, 0x00, /* 0xb8-0xbf */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0x00, 0xdb, 0x00, /* 0xc0-0xc7 */ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0x00, 0x00, /* 0xc8-0xcf */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xd0-0xd7 */ 0xf8, 0xf9, 0x00, 0x00, 0xdd, 0xde, 0x00, 0x00, /* 0xd8-0xdf */ }; static int cp1133_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00b0) c = cp1133_page00[wc-0x00a0]; else if (wc >= 0x0e80 && wc < 0x0ee0) c = cp1133_page0e[wc-0x0e80]; else if (wc == 0x20ad) c = 0xdf; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/gb2312.h0000644000175000017500000046350215004135251017435 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/gb2312.h,v 1.5 2003/05/27 22:26:29 tsi Exp $ */ /* * GB2312.1980-0 */ #ifdef NEED_TOWC static const unsigned short gb2312_2uni_page21[831] = { /* 0x21 */ 0x3000, 0x3001, 0x3002, 0x30fb, 0x02c9, 0x02c7, 0x00a8, 0x3003, 0x3005, 0x2015, 0xff5e, 0x2016, 0x2026, 0x2018, 0x2019, 0x201c, 0x201d, 0x3014, 0x3015, 0x3008, 0x3009, 0x300a, 0x300b, 0x300c, 0x300d, 0x300e, 0x300f, 0x3016, 0x3017, 0x3010, 0x3011, 0x00b1, 0x00d7, 0x00f7, 0x2236, 0x2227, 0x2228, 0x2211, 0x220f, 0x222a, 0x2229, 0x2208, 0x2237, 0x221a, 0x22a5, 0x2225, 0x2220, 0x2312, 0x2299, 0x222b, 0x222e, 0x2261, 0x224c, 0x2248, 0x223d, 0x221d, 0x2260, 0x226e, 0x226f, 0x2264, 0x2265, 0x221e, 0x2235, 0x2234, 0x2642, 0x2640, 0x00b0, 0x2032, 0x2033, 0x2103, 0xff04, 0x00a4, 0xffe0, 0xffe1, 0x2030, 0x00a7, 0x2116, 0x2606, 0x2605, 0x25cb, 0x25cf, 0x25ce, 0x25c7, 0x25c6, 0x25a1, 0x25a0, 0x25b3, 0x25b2, 0x203b, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, /* 0x22 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x2488, 0x2489, 0x248a, 0x248b, 0x248c, 0x248d, 0x248e, 0x248f, 0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497, 0x2498, 0x2499, 0x249a, 0x249b, 0x2474, 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, 0x247e, 0x247f, 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0xfffd, 0xfffd, 0x3220, 0x3221, 0x3222, 0x3223, 0x3224, 0x3225, 0x3226, 0x3227, 0x3228, 0x3229, 0xfffd, 0xfffd, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b, 0xfffd, 0xfffd, /* 0x23 */ 0xff01, 0xff02, 0xff03, 0xffe5, 0xff05, 0xff06, 0xff07, 0xff08, 0xff09, 0xff0a, 0xff0b, 0xff0c, 0xff0d, 0xff0e, 0xff0f, 0xff10, 0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, 0xff18, 0xff19, 0xff1a, 0xff1b, 0xff1c, 0xff1d, 0xff1e, 0xff1f, 0xff20, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0xff3b, 0xff3c, 0xff3d, 0xff3e, 0xff3f, 0xff40, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, 0xff58, 0xff59, 0xff5a, 0xff5b, 0xff5c, 0xff5d, 0xffe3, /* 0x24 */ 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, 0x304a, 0x304b, 0x304c, 0x304d, 0x304e, 0x304f, 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e, 0x305f, 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068, 0x3069, 0x306a, 0x306b, 0x306c, 0x306d, 0x306e, 0x306f, 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, 0x3078, 0x3079, 0x307a, 0x307b, 0x307c, 0x307d, 0x307e, 0x307f, 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087, 0x3088, 0x3089, 0x308a, 0x308b, 0x308c, 0x308d, 0x308e, 0x308f, 0x3090, 0x3091, 0x3092, 0x3093, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x25 */ 0x30a1, 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9, 0x30aa, 0x30ab, 0x30ac, 0x30ad, 0x30ae, 0x30af, 0x30b0, 0x30b1, 0x30b2, 0x30b3, 0x30b4, 0x30b5, 0x30b6, 0x30b7, 0x30b8, 0x30b9, 0x30ba, 0x30bb, 0x30bc, 0x30bd, 0x30be, 0x30bf, 0x30c0, 0x30c1, 0x30c2, 0x30c3, 0x30c4, 0x30c5, 0x30c6, 0x30c7, 0x30c8, 0x30c9, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d0, 0x30d1, 0x30d2, 0x30d3, 0x30d4, 0x30d5, 0x30d6, 0x30d7, 0x30d8, 0x30d9, 0x30da, 0x30db, 0x30dc, 0x30dd, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ee, 0x30ef, 0x30f0, 0x30f1, 0x30f2, 0x30f3, 0x30f4, 0x30f5, 0x30f6, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x26 */ 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x27 */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x28 */ 0x0101, 0x00e1, 0x01ce, 0x00e0, 0x0113, 0x00e9, 0x011b, 0x00e8, 0x012b, 0x00ed, 0x01d0, 0x00ec, 0x014d, 0x00f3, 0x01d2, 0x00f2, 0x016b, 0x00fa, 0x01d4, 0x00f9, 0x01d6, 0x01d8, 0x01da, 0x01dc, 0x00fc, 0x00ea, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x3105, 0x3106, 0x3107, 0x3108, 0x3109, 0x310a, 0x310b, 0x310c, 0x310d, 0x310e, 0x310f, 0x3110, 0x3111, 0x3112, 0x3113, 0x3114, 0x3115, 0x3116, 0x3117, 0x3118, 0x3119, 0x311a, 0x311b, 0x311c, 0x311d, 0x311e, 0x311f, 0x3120, 0x3121, 0x3122, 0x3123, 0x3124, 0x3125, 0x3126, 0x3127, 0x3128, 0x3129, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x29 */ 0xfffd, 0xfffd, 0xfffd, 0x2500, 0x2501, 0x2502, 0x2503, 0x2504, 0x2505, 0x2506, 0x2507, 0x2508, 0x2509, 0x250a, 0x250b, 0x250c, 0x250d, 0x250e, 0x250f, 0x2510, 0x2511, 0x2512, 0x2513, 0x2514, 0x2515, 0x2516, 0x2517, 0x2518, 0x2519, 0x251a, 0x251b, 0x251c, 0x251d, 0x251e, 0x251f, 0x2520, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, 0x2528, 0x2529, 0x252a, 0x252b, 0x252c, 0x252d, 0x252e, 0x252f, 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, 0x2538, 0x2539, 0x253a, 0x253b, 0x253c, 0x253d, 0x253e, 0x253f, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, }; static const unsigned short gb2312_2uni_page30[6768] = { /* 0x30 */ 0x554a, 0x963f, 0x57c3, 0x6328, 0x54ce, 0x5509, 0x54c0, 0x7691, 0x764c, 0x853c, 0x77ee, 0x827e, 0x788d, 0x7231, 0x9698, 0x978d, 0x6c28, 0x5b89, 0x4ffa, 0x6309, 0x6697, 0x5cb8, 0x80fa, 0x6848, 0x80ae, 0x6602, 0x76ce, 0x51f9, 0x6556, 0x71ac, 0x7ff1, 0x8884, 0x50b2, 0x5965, 0x61ca, 0x6fb3, 0x82ad, 0x634c, 0x6252, 0x53ed, 0x5427, 0x7b06, 0x516b, 0x75a4, 0x5df4, 0x62d4, 0x8dcb, 0x9776, 0x628a, 0x8019, 0x575d, 0x9738, 0x7f62, 0x7238, 0x767d, 0x67cf, 0x767e, 0x6446, 0x4f70, 0x8d25, 0x62dc, 0x7a17, 0x6591, 0x73ed, 0x642c, 0x6273, 0x822c, 0x9881, 0x677f, 0x7248, 0x626e, 0x62cc, 0x4f34, 0x74e3, 0x534a, 0x529e, 0x7eca, 0x90a6, 0x5e2e, 0x6886, 0x699c, 0x8180, 0x7ed1, 0x68d2, 0x78c5, 0x868c, 0x9551, 0x508d, 0x8c24, 0x82de, 0x80de, 0x5305, 0x8912, 0x5265, /* 0x31 */ 0x8584, 0x96f9, 0x4fdd, 0x5821, 0x9971, 0x5b9d, 0x62b1, 0x62a5, 0x66b4, 0x8c79, 0x9c8d, 0x7206, 0x676f, 0x7891, 0x60b2, 0x5351, 0x5317, 0x8f88, 0x80cc, 0x8d1d, 0x94a1, 0x500d, 0x72c8, 0x5907, 0x60eb, 0x7119, 0x88ab, 0x5954, 0x82ef, 0x672c, 0x7b28, 0x5d29, 0x7ef7, 0x752d, 0x6cf5, 0x8e66, 0x8ff8, 0x903c, 0x9f3b, 0x6bd4, 0x9119, 0x7b14, 0x5f7c, 0x78a7, 0x84d6, 0x853d, 0x6bd5, 0x6bd9, 0x6bd6, 0x5e01, 0x5e87, 0x75f9, 0x95ed, 0x655d, 0x5f0a, 0x5fc5, 0x8f9f, 0x58c1, 0x81c2, 0x907f, 0x965b, 0x97ad, 0x8fb9, 0x7f16, 0x8d2c, 0x6241, 0x4fbf, 0x53d8, 0x535e, 0x8fa8, 0x8fa9, 0x8fab, 0x904d, 0x6807, 0x5f6a, 0x8198, 0x8868, 0x9cd6, 0x618b, 0x522b, 0x762a, 0x5f6c, 0x658c, 0x6fd2, 0x6ee8, 0x5bbe, 0x6448, 0x5175, 0x51b0, 0x67c4, 0x4e19, 0x79c9, 0x997c, 0x70b3, /* 0x32 */ 0x75c5, 0x5e76, 0x73bb, 0x83e0, 0x64ad, 0x62e8, 0x94b5, 0x6ce2, 0x535a, 0x52c3, 0x640f, 0x94c2, 0x7b94, 0x4f2f, 0x5e1b, 0x8236, 0x8116, 0x818a, 0x6e24, 0x6cca, 0x9a73, 0x6355, 0x535c, 0x54fa, 0x8865, 0x57e0, 0x4e0d, 0x5e03, 0x6b65, 0x7c3f, 0x90e8, 0x6016, 0x64e6, 0x731c, 0x88c1, 0x6750, 0x624d, 0x8d22, 0x776c, 0x8e29, 0x91c7, 0x5f69, 0x83dc, 0x8521, 0x9910, 0x53c2, 0x8695, 0x6b8b, 0x60ed, 0x60e8, 0x707f, 0x82cd, 0x8231, 0x4ed3, 0x6ca7, 0x85cf, 0x64cd, 0x7cd9, 0x69fd, 0x66f9, 0x8349, 0x5395, 0x7b56, 0x4fa7, 0x518c, 0x6d4b, 0x5c42, 0x8e6d, 0x63d2, 0x53c9, 0x832c, 0x8336, 0x67e5, 0x78b4, 0x643d, 0x5bdf, 0x5c94, 0x5dee, 0x8be7, 0x62c6, 0x67f4, 0x8c7a, 0x6400, 0x63ba, 0x8749, 0x998b, 0x8c17, 0x7f20, 0x94f2, 0x4ea7, 0x9610, 0x98a4, 0x660c, 0x7316, /* 0x33 */ 0x573a, 0x5c1d, 0x5e38, 0x957f, 0x507f, 0x80a0, 0x5382, 0x655e, 0x7545, 0x5531, 0x5021, 0x8d85, 0x6284, 0x949e, 0x671d, 0x5632, 0x6f6e, 0x5de2, 0x5435, 0x7092, 0x8f66, 0x626f, 0x64a4, 0x63a3, 0x5f7b, 0x6f88, 0x90f4, 0x81e3, 0x8fb0, 0x5c18, 0x6668, 0x5ff1, 0x6c89, 0x9648, 0x8d81, 0x886c, 0x6491, 0x79f0, 0x57ce, 0x6a59, 0x6210, 0x5448, 0x4e58, 0x7a0b, 0x60e9, 0x6f84, 0x8bda, 0x627f, 0x901e, 0x9a8b, 0x79e4, 0x5403, 0x75f4, 0x6301, 0x5319, 0x6c60, 0x8fdf, 0x5f1b, 0x9a70, 0x803b, 0x9f7f, 0x4f88, 0x5c3a, 0x8d64, 0x7fc5, 0x65a5, 0x70bd, 0x5145, 0x51b2, 0x866b, 0x5d07, 0x5ba0, 0x62bd, 0x916c, 0x7574, 0x8e0c, 0x7a20, 0x6101, 0x7b79, 0x4ec7, 0x7ef8, 0x7785, 0x4e11, 0x81ed, 0x521d, 0x51fa, 0x6a71, 0x53a8, 0x8e87, 0x9504, 0x96cf, 0x6ec1, 0x9664, 0x695a, /* 0x34 */ 0x7840, 0x50a8, 0x77d7, 0x6410, 0x89e6, 0x5904, 0x63e3, 0x5ddd, 0x7a7f, 0x693d, 0x4f20, 0x8239, 0x5598, 0x4e32, 0x75ae, 0x7a97, 0x5e62, 0x5e8a, 0x95ef, 0x521b, 0x5439, 0x708a, 0x6376, 0x9524, 0x5782, 0x6625, 0x693f, 0x9187, 0x5507, 0x6df3, 0x7eaf, 0x8822, 0x6233, 0x7ef0, 0x75b5, 0x8328, 0x78c1, 0x96cc, 0x8f9e, 0x6148, 0x74f7, 0x8bcd, 0x6b64, 0x523a, 0x8d50, 0x6b21, 0x806a, 0x8471, 0x56f1, 0x5306, 0x4ece, 0x4e1b, 0x51d1, 0x7c97, 0x918b, 0x7c07, 0x4fc3, 0x8e7f, 0x7be1, 0x7a9c, 0x6467, 0x5d14, 0x50ac, 0x8106, 0x7601, 0x7cb9, 0x6dec, 0x7fe0, 0x6751, 0x5b58, 0x5bf8, 0x78cb, 0x64ae, 0x6413, 0x63aa, 0x632b, 0x9519, 0x642d, 0x8fbe, 0x7b54, 0x7629, 0x6253, 0x5927, 0x5446, 0x6b79, 0x50a3, 0x6234, 0x5e26, 0x6b86, 0x4ee3, 0x8d37, 0x888b, 0x5f85, 0x902e, /* 0x35 */ 0x6020, 0x803d, 0x62c5, 0x4e39, 0x5355, 0x90f8, 0x63b8, 0x80c6, 0x65e6, 0x6c2e, 0x4f46, 0x60ee, 0x6de1, 0x8bde, 0x5f39, 0x86cb, 0x5f53, 0x6321, 0x515a, 0x8361, 0x6863, 0x5200, 0x6363, 0x8e48, 0x5012, 0x5c9b, 0x7977, 0x5bfc, 0x5230, 0x7a3b, 0x60bc, 0x9053, 0x76d7, 0x5fb7, 0x5f97, 0x7684, 0x8e6c, 0x706f, 0x767b, 0x7b49, 0x77aa, 0x51f3, 0x9093, 0x5824, 0x4f4e, 0x6ef4, 0x8fea, 0x654c, 0x7b1b, 0x72c4, 0x6da4, 0x7fdf, 0x5ae1, 0x62b5, 0x5e95, 0x5730, 0x8482, 0x7b2c, 0x5e1d, 0x5f1f, 0x9012, 0x7f14, 0x98a0, 0x6382, 0x6ec7, 0x7898, 0x70b9, 0x5178, 0x975b, 0x57ab, 0x7535, 0x4f43, 0x7538, 0x5e97, 0x60e6, 0x5960, 0x6dc0, 0x6bbf, 0x7889, 0x53fc, 0x96d5, 0x51cb, 0x5201, 0x6389, 0x540a, 0x9493, 0x8c03, 0x8dcc, 0x7239, 0x789f, 0x8776, 0x8fed, 0x8c0d, 0x53e0, /* 0x36 */ 0x4e01, 0x76ef, 0x53ee, 0x9489, 0x9876, 0x9f0e, 0x952d, 0x5b9a, 0x8ba2, 0x4e22, 0x4e1c, 0x51ac, 0x8463, 0x61c2, 0x52a8, 0x680b, 0x4f97, 0x606b, 0x51bb, 0x6d1e, 0x515c, 0x6296, 0x6597, 0x9661, 0x8c46, 0x9017, 0x75d8, 0x90fd, 0x7763, 0x6bd2, 0x728a, 0x72ec, 0x8bfb, 0x5835, 0x7779, 0x8d4c, 0x675c, 0x9540, 0x809a, 0x5ea6, 0x6e21, 0x5992, 0x7aef, 0x77ed, 0x953b, 0x6bb5, 0x65ad, 0x7f0e, 0x5806, 0x5151, 0x961f, 0x5bf9, 0x58a9, 0x5428, 0x8e72, 0x6566, 0x987f, 0x56e4, 0x949d, 0x76fe, 0x9041, 0x6387, 0x54c6, 0x591a, 0x593a, 0x579b, 0x8eb2, 0x6735, 0x8dfa, 0x8235, 0x5241, 0x60f0, 0x5815, 0x86fe, 0x5ce8, 0x9e45, 0x4fc4, 0x989d, 0x8bb9, 0x5a25, 0x6076, 0x5384, 0x627c, 0x904f, 0x9102, 0x997f, 0x6069, 0x800c, 0x513f, 0x8033, 0x5c14, 0x9975, 0x6d31, 0x4e8c, /* 0x37 */ 0x8d30, 0x53d1, 0x7f5a, 0x7b4f, 0x4f10, 0x4e4f, 0x9600, 0x6cd5, 0x73d0, 0x85e9, 0x5e06, 0x756a, 0x7ffb, 0x6a0a, 0x77fe, 0x9492, 0x7e41, 0x51e1, 0x70e6, 0x53cd, 0x8fd4, 0x8303, 0x8d29, 0x72af, 0x996d, 0x6cdb, 0x574a, 0x82b3, 0x65b9, 0x80aa, 0x623f, 0x9632, 0x59a8, 0x4eff, 0x8bbf, 0x7eba, 0x653e, 0x83f2, 0x975e, 0x5561, 0x98de, 0x80a5, 0x532a, 0x8bfd, 0x5420, 0x80ba, 0x5e9f, 0x6cb8, 0x8d39, 0x82ac, 0x915a, 0x5429, 0x6c1b, 0x5206, 0x7eb7, 0x575f, 0x711a, 0x6c7e, 0x7c89, 0x594b, 0x4efd, 0x5fff, 0x6124, 0x7caa, 0x4e30, 0x5c01, 0x67ab, 0x8702, 0x5cf0, 0x950b, 0x98ce, 0x75af, 0x70fd, 0x9022, 0x51af, 0x7f1d, 0x8bbd, 0x5949, 0x51e4, 0x4f5b, 0x5426, 0x592b, 0x6577, 0x80a4, 0x5b75, 0x6276, 0x62c2, 0x8f90, 0x5e45, 0x6c1f, 0x7b26, 0x4f0f, 0x4fd8, 0x670d, /* 0x38 */ 0x6d6e, 0x6daa, 0x798f, 0x88b1, 0x5f17, 0x752b, 0x629a, 0x8f85, 0x4fef, 0x91dc, 0x65a7, 0x812f, 0x8151, 0x5e9c, 0x8150, 0x8d74, 0x526f, 0x8986, 0x8d4b, 0x590d, 0x5085, 0x4ed8, 0x961c, 0x7236, 0x8179, 0x8d1f, 0x5bcc, 0x8ba3, 0x9644, 0x5987, 0x7f1a, 0x5490, 0x5676, 0x560e, 0x8be5, 0x6539, 0x6982, 0x9499, 0x76d6, 0x6e89, 0x5e72, 0x7518, 0x6746, 0x67d1, 0x7aff, 0x809d, 0x8d76, 0x611f, 0x79c6, 0x6562, 0x8d63, 0x5188, 0x521a, 0x94a2, 0x7f38, 0x809b, 0x7eb2, 0x5c97, 0x6e2f, 0x6760, 0x7bd9, 0x768b, 0x9ad8, 0x818f, 0x7f94, 0x7cd5, 0x641e, 0x9550, 0x7a3f, 0x544a, 0x54e5, 0x6b4c, 0x6401, 0x6208, 0x9e3d, 0x80f3, 0x7599, 0x5272, 0x9769, 0x845b, 0x683c, 0x86e4, 0x9601, 0x9694, 0x94ec, 0x4e2a, 0x5404, 0x7ed9, 0x6839, 0x8ddf, 0x8015, 0x66f4, 0x5e9a, 0x7fb9, /* 0x39 */ 0x57c2, 0x803f, 0x6897, 0x5de5, 0x653b, 0x529f, 0x606d, 0x9f9a, 0x4f9b, 0x8eac, 0x516c, 0x5bab, 0x5f13, 0x5de9, 0x6c5e, 0x62f1, 0x8d21, 0x5171, 0x94a9, 0x52fe, 0x6c9f, 0x82df, 0x72d7, 0x57a2, 0x6784, 0x8d2d, 0x591f, 0x8f9c, 0x83c7, 0x5495, 0x7b8d, 0x4f30, 0x6cbd, 0x5b64, 0x59d1, 0x9f13, 0x53e4, 0x86ca, 0x9aa8, 0x8c37, 0x80a1, 0x6545, 0x987e, 0x56fa, 0x96c7, 0x522e, 0x74dc, 0x5250, 0x5be1, 0x6302, 0x8902, 0x4e56, 0x62d0, 0x602a, 0x68fa, 0x5173, 0x5b98, 0x51a0, 0x89c2, 0x7ba1, 0x9986, 0x7f50, 0x60ef, 0x704c, 0x8d2f, 0x5149, 0x5e7f, 0x901b, 0x7470, 0x89c4, 0x572d, 0x7845, 0x5f52, 0x9f9f, 0x95fa, 0x8f68, 0x9b3c, 0x8be1, 0x7678, 0x6842, 0x67dc, 0x8dea, 0x8d35, 0x523d, 0x8f8a, 0x6eda, 0x68cd, 0x9505, 0x90ed, 0x56fd, 0x679c, 0x88f9, 0x8fc7, 0x54c8, /* 0x3a */ 0x9ab8, 0x5b69, 0x6d77, 0x6c26, 0x4ea5, 0x5bb3, 0x9a87, 0x9163, 0x61a8, 0x90af, 0x97e9, 0x542b, 0x6db5, 0x5bd2, 0x51fd, 0x558a, 0x7f55, 0x7ff0, 0x64bc, 0x634d, 0x65f1, 0x61be, 0x608d, 0x710a, 0x6c57, 0x6c49, 0x592f, 0x676d, 0x822a, 0x58d5, 0x568e, 0x8c6a, 0x6beb, 0x90dd, 0x597d, 0x8017, 0x53f7, 0x6d69, 0x5475, 0x559d, 0x8377, 0x83cf, 0x6838, 0x79be, 0x548c, 0x4f55, 0x5408, 0x76d2, 0x8c89, 0x9602, 0x6cb3, 0x6db8, 0x8d6b, 0x8910, 0x9e64, 0x8d3a, 0x563f, 0x9ed1, 0x75d5, 0x5f88, 0x72e0, 0x6068, 0x54fc, 0x4ea8, 0x6a2a, 0x8861, 0x6052, 0x8f70, 0x54c4, 0x70d8, 0x8679, 0x9e3f, 0x6d2a, 0x5b8f, 0x5f18, 0x7ea2, 0x5589, 0x4faf, 0x7334, 0x543c, 0x539a, 0x5019, 0x540e, 0x547c, 0x4e4e, 0x5ffd, 0x745a, 0x58f6, 0x846b, 0x80e1, 0x8774, 0x72d0, 0x7cca, 0x6e56, /* 0x3b */ 0x5f27, 0x864e, 0x552c, 0x62a4, 0x4e92, 0x6caa, 0x6237, 0x82b1, 0x54d7, 0x534e, 0x733e, 0x6ed1, 0x753b, 0x5212, 0x5316, 0x8bdd, 0x69d0, 0x5f8a, 0x6000, 0x6dee, 0x574f, 0x6b22, 0x73af, 0x6853, 0x8fd8, 0x7f13, 0x6362, 0x60a3, 0x5524, 0x75ea, 0x8c62, 0x7115, 0x6da3, 0x5ba6, 0x5e7b, 0x8352, 0x614c, 0x9ec4, 0x78fa, 0x8757, 0x7c27, 0x7687, 0x51f0, 0x60f6, 0x714c, 0x6643, 0x5e4c, 0x604d, 0x8c0e, 0x7070, 0x6325, 0x8f89, 0x5fbd, 0x6062, 0x86d4, 0x56de, 0x6bc1, 0x6094, 0x6167, 0x5349, 0x60e0, 0x6666, 0x8d3f, 0x79fd, 0x4f1a, 0x70e9, 0x6c47, 0x8bb3, 0x8bf2, 0x7ed8, 0x8364, 0x660f, 0x5a5a, 0x9b42, 0x6d51, 0x6df7, 0x8c41, 0x6d3b, 0x4f19, 0x706b, 0x83b7, 0x6216, 0x60d1, 0x970d, 0x8d27, 0x7978, 0x51fb, 0x573e, 0x57fa, 0x673a, 0x7578, 0x7a3d, 0x79ef, 0x7b95, /* 0x3c */ 0x808c, 0x9965, 0x8ff9, 0x6fc0, 0x8ba5, 0x9e21, 0x59ec, 0x7ee9, 0x7f09, 0x5409, 0x6781, 0x68d8, 0x8f91, 0x7c4d, 0x96c6, 0x53ca, 0x6025, 0x75be, 0x6c72, 0x5373, 0x5ac9, 0x7ea7, 0x6324, 0x51e0, 0x810a, 0x5df1, 0x84df, 0x6280, 0x5180, 0x5b63, 0x4f0e, 0x796d, 0x5242, 0x60b8, 0x6d4e, 0x5bc4, 0x5bc2, 0x8ba1, 0x8bb0, 0x65e2, 0x5fcc, 0x9645, 0x5993, 0x7ee7, 0x7eaa, 0x5609, 0x67b7, 0x5939, 0x4f73, 0x5bb6, 0x52a0, 0x835a, 0x988a, 0x8d3e, 0x7532, 0x94be, 0x5047, 0x7a3c, 0x4ef7, 0x67b6, 0x9a7e, 0x5ac1, 0x6b7c, 0x76d1, 0x575a, 0x5c16, 0x7b3a, 0x95f4, 0x714e, 0x517c, 0x80a9, 0x8270, 0x5978, 0x7f04, 0x8327, 0x68c0, 0x67ec, 0x78b1, 0x7877, 0x62e3, 0x6361, 0x7b80, 0x4fed, 0x526a, 0x51cf, 0x8350, 0x69db, 0x9274, 0x8df5, 0x8d31, 0x89c1, 0x952e, 0x7bad, 0x4ef6, /* 0x3d */ 0x5065, 0x8230, 0x5251, 0x996f, 0x6e10, 0x6e85, 0x6da7, 0x5efa, 0x50f5, 0x59dc, 0x5c06, 0x6d46, 0x6c5f, 0x7586, 0x848b, 0x6868, 0x5956, 0x8bb2, 0x5320, 0x9171, 0x964d, 0x8549, 0x6912, 0x7901, 0x7126, 0x80f6, 0x4ea4, 0x90ca, 0x6d47, 0x9a84, 0x5a07, 0x56bc, 0x6405, 0x94f0, 0x77eb, 0x4fa5, 0x811a, 0x72e1, 0x89d2, 0x997a, 0x7f34, 0x7ede, 0x527f, 0x6559, 0x9175, 0x8f7f, 0x8f83, 0x53eb, 0x7a96, 0x63ed, 0x63a5, 0x7686, 0x79f8, 0x8857, 0x9636, 0x622a, 0x52ab, 0x8282, 0x6854, 0x6770, 0x6377, 0x776b, 0x7aed, 0x6d01, 0x7ed3, 0x89e3, 0x59d0, 0x6212, 0x85c9, 0x82a5, 0x754c, 0x501f, 0x4ecb, 0x75a5, 0x8beb, 0x5c4a, 0x5dfe, 0x7b4b, 0x65a4, 0x91d1, 0x4eca, 0x6d25, 0x895f, 0x7d27, 0x9526, 0x4ec5, 0x8c28, 0x8fdb, 0x9773, 0x664b, 0x7981, 0x8fd1, 0x70ec, 0x6d78, /* 0x3e */ 0x5c3d, 0x52b2, 0x8346, 0x5162, 0x830e, 0x775b, 0x6676, 0x9cb8, 0x4eac, 0x60ca, 0x7cbe, 0x7cb3, 0x7ecf, 0x4e95, 0x8b66, 0x666f, 0x9888, 0x9759, 0x5883, 0x656c, 0x955c, 0x5f84, 0x75c9, 0x9756, 0x7adf, 0x7ade, 0x51c0, 0x70af, 0x7a98, 0x63ea, 0x7a76, 0x7ea0, 0x7396, 0x97ed, 0x4e45, 0x7078, 0x4e5d, 0x9152, 0x53a9, 0x6551, 0x65e7, 0x81fc, 0x8205, 0x548e, 0x5c31, 0x759a, 0x97a0, 0x62d8, 0x72d9, 0x75bd, 0x5c45, 0x9a79, 0x83ca, 0x5c40, 0x5480, 0x77e9, 0x4e3e, 0x6cae, 0x805a, 0x62d2, 0x636e, 0x5de8, 0x5177, 0x8ddd, 0x8e1e, 0x952f, 0x4ff1, 0x53e5, 0x60e7, 0x70ac, 0x5267, 0x6350, 0x9e43, 0x5a1f, 0x5026, 0x7737, 0x5377, 0x7ee2, 0x6485, 0x652b, 0x6289, 0x6398, 0x5014, 0x7235, 0x89c9, 0x51b3, 0x8bc0, 0x7edd, 0x5747, 0x83cc, 0x94a7, 0x519b, 0x541b, 0x5cfb, /* 0x3f */ 0x4fca, 0x7ae3, 0x6d5a, 0x90e1, 0x9a8f, 0x5580, 0x5496, 0x5361, 0x54af, 0x5f00, 0x63e9, 0x6977, 0x51ef, 0x6168, 0x520a, 0x582a, 0x52d8, 0x574e, 0x780d, 0x770b, 0x5eb7, 0x6177, 0x7ce0, 0x625b, 0x6297, 0x4ea2, 0x7095, 0x8003, 0x62f7, 0x70e4, 0x9760, 0x5777, 0x82db, 0x67ef, 0x68f5, 0x78d5, 0x9897, 0x79d1, 0x58f3, 0x54b3, 0x53ef, 0x6e34, 0x514b, 0x523b, 0x5ba2, 0x8bfe, 0x80af, 0x5543, 0x57a6, 0x6073, 0x5751, 0x542d, 0x7a7a, 0x6050, 0x5b54, 0x63a7, 0x62a0, 0x53e3, 0x6263, 0x5bc7, 0x67af, 0x54ed, 0x7a9f, 0x82e6, 0x9177, 0x5e93, 0x88e4, 0x5938, 0x57ae, 0x630e, 0x8de8, 0x80ef, 0x5757, 0x7b77, 0x4fa9, 0x5feb, 0x5bbd, 0x6b3e, 0x5321, 0x7b50, 0x72c2, 0x6846, 0x77ff, 0x7736, 0x65f7, 0x51b5, 0x4e8f, 0x76d4, 0x5cbf, 0x7aa5, 0x8475, 0x594e, 0x9b41, 0x5080, /* 0x40 */ 0x9988, 0x6127, 0x6e83, 0x5764, 0x6606, 0x6346, 0x56f0, 0x62ec, 0x6269, 0x5ed3, 0x9614, 0x5783, 0x62c9, 0x5587, 0x8721, 0x814a, 0x8fa3, 0x5566, 0x83b1, 0x6765, 0x8d56, 0x84dd, 0x5a6a, 0x680f, 0x62e6, 0x7bee, 0x9611, 0x5170, 0x6f9c, 0x8c30, 0x63fd, 0x89c8, 0x61d2, 0x7f06, 0x70c2, 0x6ee5, 0x7405, 0x6994, 0x72fc, 0x5eca, 0x90ce, 0x6717, 0x6d6a, 0x635e, 0x52b3, 0x7262, 0x8001, 0x4f6c, 0x59e5, 0x916a, 0x70d9, 0x6d9d, 0x52d2, 0x4e50, 0x96f7, 0x956d, 0x857e, 0x78ca, 0x7d2f, 0x5121, 0x5792, 0x64c2, 0x808b, 0x7c7b, 0x6cea, 0x68f1, 0x695e, 0x51b7, 0x5398, 0x68a8, 0x7281, 0x9ece, 0x7bf1, 0x72f8, 0x79bb, 0x6f13, 0x7406, 0x674e, 0x91cc, 0x9ca4, 0x793c, 0x8389, 0x8354, 0x540f, 0x6817, 0x4e3d, 0x5389, 0x52b1, 0x783e, 0x5386, 0x5229, 0x5088, 0x4f8b, 0x4fd0, /* 0x41 */ 0x75e2, 0x7acb, 0x7c92, 0x6ca5, 0x96b6, 0x529b, 0x7483, 0x54e9, 0x4fe9, 0x8054, 0x83b2, 0x8fde, 0x9570, 0x5ec9, 0x601c, 0x6d9f, 0x5e18, 0x655b, 0x8138, 0x94fe, 0x604b, 0x70bc, 0x7ec3, 0x7cae, 0x51c9, 0x6881, 0x7cb1, 0x826f, 0x4e24, 0x8f86, 0x91cf, 0x667e, 0x4eae, 0x8c05, 0x64a9, 0x804a, 0x50da, 0x7597, 0x71ce, 0x5be5, 0x8fbd, 0x6f66, 0x4e86, 0x6482, 0x9563, 0x5ed6, 0x6599, 0x5217, 0x88c2, 0x70c8, 0x52a3, 0x730e, 0x7433, 0x6797, 0x78f7, 0x9716, 0x4e34, 0x90bb, 0x9cde, 0x6dcb, 0x51db, 0x8d41, 0x541d, 0x62ce, 0x73b2, 0x83f1, 0x96f6, 0x9f84, 0x94c3, 0x4f36, 0x7f9a, 0x51cc, 0x7075, 0x9675, 0x5cad, 0x9886, 0x53e6, 0x4ee4, 0x6e9c, 0x7409, 0x69b4, 0x786b, 0x998f, 0x7559, 0x5218, 0x7624, 0x6d41, 0x67f3, 0x516d, 0x9f99, 0x804b, 0x5499, 0x7b3c, 0x7abf, /* 0x42 */ 0x9686, 0x5784, 0x62e2, 0x9647, 0x697c, 0x5a04, 0x6402, 0x7bd3, 0x6f0f, 0x964b, 0x82a6, 0x5362, 0x9885, 0x5e90, 0x7089, 0x63b3, 0x5364, 0x864f, 0x9c81, 0x9e93, 0x788c, 0x9732, 0x8def, 0x8d42, 0x9e7f, 0x6f5e, 0x7984, 0x5f55, 0x9646, 0x622e, 0x9a74, 0x5415, 0x94dd, 0x4fa3, 0x65c5, 0x5c65, 0x5c61, 0x7f15, 0x8651, 0x6c2f, 0x5f8b, 0x7387, 0x6ee4, 0x7eff, 0x5ce6, 0x631b, 0x5b6a, 0x6ee6, 0x5375, 0x4e71, 0x63a0, 0x7565, 0x62a1, 0x8f6e, 0x4f26, 0x4ed1, 0x6ca6, 0x7eb6, 0x8bba, 0x841d, 0x87ba, 0x7f57, 0x903b, 0x9523, 0x7ba9, 0x9aa1, 0x88f8, 0x843d, 0x6d1b, 0x9a86, 0x7edc, 0x5988, 0x9ebb, 0x739b, 0x7801, 0x8682, 0x9a6c, 0x9a82, 0x561b, 0x5417, 0x57cb, 0x4e70, 0x9ea6, 0x5356, 0x8fc8, 0x8109, 0x7792, 0x9992, 0x86ee, 0x6ee1, 0x8513, 0x66fc, 0x6162, 0x6f2b, /* 0x43 */ 0x8c29, 0x8292, 0x832b, 0x76f2, 0x6c13, 0x5fd9, 0x83bd, 0x732b, 0x8305, 0x951a, 0x6bdb, 0x77db, 0x94c6, 0x536f, 0x8302, 0x5192, 0x5e3d, 0x8c8c, 0x8d38, 0x4e48, 0x73ab, 0x679a, 0x6885, 0x9176, 0x9709, 0x7164, 0x6ca1, 0x7709, 0x5a92, 0x9541, 0x6bcf, 0x7f8e, 0x6627, 0x5bd0, 0x59b9, 0x5a9a, 0x95e8, 0x95f7, 0x4eec, 0x840c, 0x8499, 0x6aac, 0x76df, 0x9530, 0x731b, 0x68a6, 0x5b5f, 0x772f, 0x919a, 0x9761, 0x7cdc, 0x8ff7, 0x8c1c, 0x5f25, 0x7c73, 0x79d8, 0x89c5, 0x6ccc, 0x871c, 0x5bc6, 0x5e42, 0x68c9, 0x7720, 0x7ef5, 0x5195, 0x514d, 0x52c9, 0x5a29, 0x7f05, 0x9762, 0x82d7, 0x63cf, 0x7784, 0x85d0, 0x79d2, 0x6e3a, 0x5e99, 0x5999, 0x8511, 0x706d, 0x6c11, 0x62bf, 0x76bf, 0x654f, 0x60af, 0x95fd, 0x660e, 0x879f, 0x9e23, 0x94ed, 0x540d, 0x547d, 0x8c2c, 0x6478, /* 0x44 */ 0x6479, 0x8611, 0x6a21, 0x819c, 0x78e8, 0x6469, 0x9b54, 0x62b9, 0x672b, 0x83ab, 0x58a8, 0x9ed8, 0x6cab, 0x6f20, 0x5bde, 0x964c, 0x8c0b, 0x725f, 0x67d0, 0x62c7, 0x7261, 0x4ea9, 0x59c6, 0x6bcd, 0x5893, 0x66ae, 0x5e55, 0x52df, 0x6155, 0x6728, 0x76ee, 0x7766, 0x7267, 0x7a46, 0x62ff, 0x54ea, 0x5450, 0x94a0, 0x90a3, 0x5a1c, 0x7eb3, 0x6c16, 0x4e43, 0x5976, 0x8010, 0x5948, 0x5357, 0x7537, 0x96be, 0x56ca, 0x6320, 0x8111, 0x607c, 0x95f9, 0x6dd6, 0x5462, 0x9981, 0x5185, 0x5ae9, 0x80fd, 0x59ae, 0x9713, 0x502a, 0x6ce5, 0x5c3c, 0x62df, 0x4f60, 0x533f, 0x817b, 0x9006, 0x6eba, 0x852b, 0x62c8, 0x5e74, 0x78be, 0x64b5, 0x637b, 0x5ff5, 0x5a18, 0x917f, 0x9e1f, 0x5c3f, 0x634f, 0x8042, 0x5b7d, 0x556e, 0x954a, 0x954d, 0x6d85, 0x60a8, 0x67e0, 0x72de, 0x51dd, 0x5b81, /* 0x45 */ 0x62e7, 0x6cde, 0x725b, 0x626d, 0x94ae, 0x7ebd, 0x8113, 0x6d53, 0x519c, 0x5f04, 0x5974, 0x52aa, 0x6012, 0x5973, 0x6696, 0x8650, 0x759f, 0x632a, 0x61e6, 0x7cef, 0x8bfa, 0x54e6, 0x6b27, 0x9e25, 0x6bb4, 0x85d5, 0x5455, 0x5076, 0x6ca4, 0x556a, 0x8db4, 0x722c, 0x5e15, 0x6015, 0x7436, 0x62cd, 0x6392, 0x724c, 0x5f98, 0x6e43, 0x6d3e, 0x6500, 0x6f58, 0x76d8, 0x78d0, 0x76fc, 0x7554, 0x5224, 0x53db, 0x4e53, 0x5e9e, 0x65c1, 0x802a, 0x80d6, 0x629b, 0x5486, 0x5228, 0x70ae, 0x888d, 0x8dd1, 0x6ce1, 0x5478, 0x80da, 0x57f9, 0x88f4, 0x8d54, 0x966a, 0x914d, 0x4f69, 0x6c9b, 0x55b7, 0x76c6, 0x7830, 0x62a8, 0x70f9, 0x6f8e, 0x5f6d, 0x84ec, 0x68da, 0x787c, 0x7bf7, 0x81a8, 0x670b, 0x9e4f, 0x6367, 0x78b0, 0x576f, 0x7812, 0x9739, 0x6279, 0x62ab, 0x5288, 0x7435, 0x6bd7, /* 0x46 */ 0x5564, 0x813e, 0x75b2, 0x76ae, 0x5339, 0x75de, 0x50fb, 0x5c41, 0x8b6c, 0x7bc7, 0x504f, 0x7247, 0x9a97, 0x98d8, 0x6f02, 0x74e2, 0x7968, 0x6487, 0x77a5, 0x62fc, 0x9891, 0x8d2b, 0x54c1, 0x8058, 0x4e52, 0x576a, 0x82f9, 0x840d, 0x5e73, 0x51ed, 0x74f6, 0x8bc4, 0x5c4f, 0x5761, 0x6cfc, 0x9887, 0x5a46, 0x7834, 0x9b44, 0x8feb, 0x7c95, 0x5256, 0x6251, 0x94fa, 0x4ec6, 0x8386, 0x8461, 0x83e9, 0x84b2, 0x57d4, 0x6734, 0x5703, 0x666e, 0x6d66, 0x8c31, 0x66dd, 0x7011, 0x671f, 0x6b3a, 0x6816, 0x621a, 0x59bb, 0x4e03, 0x51c4, 0x6f06, 0x67d2, 0x6c8f, 0x5176, 0x68cb, 0x5947, 0x6b67, 0x7566, 0x5d0e, 0x8110, 0x9f50, 0x65d7, 0x7948, 0x7941, 0x9a91, 0x8d77, 0x5c82, 0x4e5e, 0x4f01, 0x542f, 0x5951, 0x780c, 0x5668, 0x6c14, 0x8fc4, 0x5f03, 0x6c7d, 0x6ce3, 0x8bab, 0x6390, /* 0x47 */ 0x6070, 0x6d3d, 0x7275, 0x6266, 0x948e, 0x94c5, 0x5343, 0x8fc1, 0x7b7e, 0x4edf, 0x8c26, 0x4e7e, 0x9ed4, 0x94b1, 0x94b3, 0x524d, 0x6f5c, 0x9063, 0x6d45, 0x8c34, 0x5811, 0x5d4c, 0x6b20, 0x6b49, 0x67aa, 0x545b, 0x8154, 0x7f8c, 0x5899, 0x8537, 0x5f3a, 0x62a2, 0x6a47, 0x9539, 0x6572, 0x6084, 0x6865, 0x77a7, 0x4e54, 0x4fa8, 0x5de7, 0x9798, 0x64ac, 0x7fd8, 0x5ced, 0x4fcf, 0x7a8d, 0x5207, 0x8304, 0x4e14, 0x602f, 0x7a83, 0x94a6, 0x4fb5, 0x4eb2, 0x79e6, 0x7434, 0x52e4, 0x82b9, 0x64d2, 0x79bd, 0x5bdd, 0x6c81, 0x9752, 0x8f7b, 0x6c22, 0x503e, 0x537f, 0x6e05, 0x64ce, 0x6674, 0x6c30, 0x60c5, 0x9877, 0x8bf7, 0x5e86, 0x743c, 0x7a77, 0x79cb, 0x4e18, 0x90b1, 0x7403, 0x6c42, 0x56da, 0x914b, 0x6cc5, 0x8d8b, 0x533a, 0x86c6, 0x66f2, 0x8eaf, 0x5c48, 0x9a71, 0x6e20, /* 0x48 */ 0x53d6, 0x5a36, 0x9f8b, 0x8da3, 0x53bb, 0x5708, 0x98a7, 0x6743, 0x919b, 0x6cc9, 0x5168, 0x75ca, 0x62f3, 0x72ac, 0x5238, 0x529d, 0x7f3a, 0x7094, 0x7638, 0x5374, 0x9e4a, 0x69b7, 0x786e, 0x96c0, 0x88d9, 0x7fa4, 0x7136, 0x71c3, 0x5189, 0x67d3, 0x74e4, 0x58e4, 0x6518, 0x56b7, 0x8ba9, 0x9976, 0x6270, 0x7ed5, 0x60f9, 0x70ed, 0x58ec, 0x4ec1, 0x4eba, 0x5fcd, 0x97e7, 0x4efb, 0x8ba4, 0x5203, 0x598a, 0x7eab, 0x6254, 0x4ecd, 0x65e5, 0x620e, 0x8338, 0x84c9, 0x8363, 0x878d, 0x7194, 0x6eb6, 0x5bb9, 0x7ed2, 0x5197, 0x63c9, 0x67d4, 0x8089, 0x8339, 0x8815, 0x5112, 0x5b7a, 0x5982, 0x8fb1, 0x4e73, 0x6c5d, 0x5165, 0x8925, 0x8f6f, 0x962e, 0x854a, 0x745e, 0x9510, 0x95f0, 0x6da6, 0x82e5, 0x5f31, 0x6492, 0x6d12, 0x8428, 0x816e, 0x9cc3, 0x585e, 0x8d5b, 0x4e09, 0x53c1, /* 0x49 */ 0x4f1e, 0x6563, 0x6851, 0x55d3, 0x4e27, 0x6414, 0x9a9a, 0x626b, 0x5ac2, 0x745f, 0x8272, 0x6da9, 0x68ee, 0x50e7, 0x838e, 0x7802, 0x6740, 0x5239, 0x6c99, 0x7eb1, 0x50bb, 0x5565, 0x715e, 0x7b5b, 0x6652, 0x73ca, 0x82eb, 0x6749, 0x5c71, 0x5220, 0x717d, 0x886b, 0x95ea, 0x9655, 0x64c5, 0x8d61, 0x81b3, 0x5584, 0x6c55, 0x6247, 0x7f2e, 0x5892, 0x4f24, 0x5546, 0x8d4f, 0x664c, 0x4e0a, 0x5c1a, 0x88f3, 0x68a2, 0x634e, 0x7a0d, 0x70e7, 0x828d, 0x52fa, 0x97f6, 0x5c11, 0x54e8, 0x90b5, 0x7ecd, 0x5962, 0x8d4a, 0x86c7, 0x820c, 0x820d, 0x8d66, 0x6444, 0x5c04, 0x6151, 0x6d89, 0x793e, 0x8bbe, 0x7837, 0x7533, 0x547b, 0x4f38, 0x8eab, 0x6df1, 0x5a20, 0x7ec5, 0x795e, 0x6c88, 0x5ba1, 0x5a76, 0x751a, 0x80be, 0x614e, 0x6e17, 0x58f0, 0x751f, 0x7525, 0x7272, 0x5347, 0x7ef3, /* 0x4a */ 0x7701, 0x76db, 0x5269, 0x80dc, 0x5723, 0x5e08, 0x5931, 0x72ee, 0x65bd, 0x6e7f, 0x8bd7, 0x5c38, 0x8671, 0x5341, 0x77f3, 0x62fe, 0x65f6, 0x4ec0, 0x98df, 0x8680, 0x5b9e, 0x8bc6, 0x53f2, 0x77e2, 0x4f7f, 0x5c4e, 0x9a76, 0x59cb, 0x5f0f, 0x793a, 0x58eb, 0x4e16, 0x67ff, 0x4e8b, 0x62ed, 0x8a93, 0x901d, 0x52bf, 0x662f, 0x55dc, 0x566c, 0x9002, 0x4ed5, 0x4f8d, 0x91ca, 0x9970, 0x6c0f, 0x5e02, 0x6043, 0x5ba4, 0x89c6, 0x8bd5, 0x6536, 0x624b, 0x9996, 0x5b88, 0x5bff, 0x6388, 0x552e, 0x53d7, 0x7626, 0x517d, 0x852c, 0x67a2, 0x68b3, 0x6b8a, 0x6292, 0x8f93, 0x53d4, 0x8212, 0x6dd1, 0x758f, 0x4e66, 0x8d4e, 0x5b70, 0x719f, 0x85af, 0x6691, 0x66d9, 0x7f72, 0x8700, 0x9ecd, 0x9f20, 0x5c5e, 0x672f, 0x8ff0, 0x6811, 0x675f, 0x620d, 0x7ad6, 0x5885, 0x5eb6, 0x6570, 0x6f31, /* 0x4b */ 0x6055, 0x5237, 0x800d, 0x6454, 0x8870, 0x7529, 0x5e05, 0x6813, 0x62f4, 0x971c, 0x53cc, 0x723d, 0x8c01, 0x6c34, 0x7761, 0x7a0e, 0x542e, 0x77ac, 0x987a, 0x821c, 0x8bf4, 0x7855, 0x6714, 0x70c1, 0x65af, 0x6495, 0x5636, 0x601d, 0x79c1, 0x53f8, 0x4e1d, 0x6b7b, 0x8086, 0x5bfa, 0x55e3, 0x56db, 0x4f3a, 0x4f3c, 0x9972, 0x5df3, 0x677e, 0x8038, 0x6002, 0x9882, 0x9001, 0x5b8b, 0x8bbc, 0x8bf5, 0x641c, 0x8258, 0x64de, 0x55fd, 0x82cf, 0x9165, 0x4fd7, 0x7d20, 0x901f, 0x7c9f, 0x50f3, 0x5851, 0x6eaf, 0x5bbf, 0x8bc9, 0x8083, 0x9178, 0x849c, 0x7b97, 0x867d, 0x968b, 0x968f, 0x7ee5, 0x9ad3, 0x788e, 0x5c81, 0x7a57, 0x9042, 0x96a7, 0x795f, 0x5b59, 0x635f, 0x7b0b, 0x84d1, 0x68ad, 0x5506, 0x7f29, 0x7410, 0x7d22, 0x9501, 0x6240, 0x584c, 0x4ed6, 0x5b83, 0x5979, 0x5854, /* 0x4c */ 0x736d, 0x631e, 0x8e4b, 0x8e0f, 0x80ce, 0x82d4, 0x62ac, 0x53f0, 0x6cf0, 0x915e, 0x592a, 0x6001, 0x6c70, 0x574d, 0x644a, 0x8d2a, 0x762b, 0x6ee9, 0x575b, 0x6a80, 0x75f0, 0x6f6d, 0x8c2d, 0x8c08, 0x5766, 0x6bef, 0x8892, 0x78b3, 0x63a2, 0x53f9, 0x70ad, 0x6c64, 0x5858, 0x642a, 0x5802, 0x68e0, 0x819b, 0x5510, 0x7cd6, 0x5018, 0x8eba, 0x6dcc, 0x8d9f, 0x70eb, 0x638f, 0x6d9b, 0x6ed4, 0x7ee6, 0x8404, 0x6843, 0x9003, 0x6dd8, 0x9676, 0x8ba8, 0x5957, 0x7279, 0x85e4, 0x817e, 0x75bc, 0x8a8a, 0x68af, 0x5254, 0x8e22, 0x9511, 0x63d0, 0x9898, 0x8e44, 0x557c, 0x4f53, 0x66ff, 0x568f, 0x60d5, 0x6d95, 0x5243, 0x5c49, 0x5929, 0x6dfb, 0x586b, 0x7530, 0x751c, 0x606c, 0x8214, 0x8146, 0x6311, 0x6761, 0x8fe2, 0x773a, 0x8df3, 0x8d34, 0x94c1, 0x5e16, 0x5385, 0x542c, 0x70c3, /* 0x4d */ 0x6c40, 0x5ef7, 0x505c, 0x4ead, 0x5ead, 0x633a, 0x8247, 0x901a, 0x6850, 0x916e, 0x77b3, 0x540c, 0x94dc, 0x5f64, 0x7ae5, 0x6876, 0x6345, 0x7b52, 0x7edf, 0x75db, 0x5077, 0x6295, 0x5934, 0x900f, 0x51f8, 0x79c3, 0x7a81, 0x56fe, 0x5f92, 0x9014, 0x6d82, 0x5c60, 0x571f, 0x5410, 0x5154, 0x6e4d, 0x56e2, 0x63a8, 0x9893, 0x817f, 0x8715, 0x892a, 0x9000, 0x541e, 0x5c6f, 0x81c0, 0x62d6, 0x6258, 0x8131, 0x9e35, 0x9640, 0x9a6e, 0x9a7c, 0x692d, 0x59a5, 0x62d3, 0x553e, 0x6316, 0x54c7, 0x86d9, 0x6d3c, 0x5a03, 0x74e6, 0x889c, 0x6b6a, 0x5916, 0x8c4c, 0x5f2f, 0x6e7e, 0x73a9, 0x987d, 0x4e38, 0x70f7, 0x5b8c, 0x7897, 0x633d, 0x665a, 0x7696, 0x60cb, 0x5b9b, 0x5a49, 0x4e07, 0x8155, 0x6c6a, 0x738b, 0x4ea1, 0x6789, 0x7f51, 0x5f80, 0x65fa, 0x671b, 0x5fd8, 0x5984, 0x5a01, /* 0x4e */ 0x5dcd, 0x5fae, 0x5371, 0x97e6, 0x8fdd, 0x6845, 0x56f4, 0x552f, 0x60df, 0x4e3a, 0x6f4d, 0x7ef4, 0x82c7, 0x840e, 0x59d4, 0x4f1f, 0x4f2a, 0x5c3e, 0x7eac, 0x672a, 0x851a, 0x5473, 0x754f, 0x80c3, 0x5582, 0x9b4f, 0x4f4d, 0x6e2d, 0x8c13, 0x5c09, 0x6170, 0x536b, 0x761f, 0x6e29, 0x868a, 0x6587, 0x95fb, 0x7eb9, 0x543b, 0x7a33, 0x7d0a, 0x95ee, 0x55e1, 0x7fc1, 0x74ee, 0x631d, 0x8717, 0x6da1, 0x7a9d, 0x6211, 0x65a1, 0x5367, 0x63e1, 0x6c83, 0x5deb, 0x545c, 0x94a8, 0x4e4c, 0x6c61, 0x8bec, 0x5c4b, 0x65e0, 0x829c, 0x68a7, 0x543e, 0x5434, 0x6bcb, 0x6b66, 0x4e94, 0x6342, 0x5348, 0x821e, 0x4f0d, 0x4fae, 0x575e, 0x620a, 0x96fe, 0x6664, 0x7269, 0x52ff, 0x52a1, 0x609f, 0x8bef, 0x6614, 0x7199, 0x6790, 0x897f, 0x7852, 0x77fd, 0x6670, 0x563b, 0x5438, 0x9521, 0x727a, /* 0x4f */ 0x7a00, 0x606f, 0x5e0c, 0x6089, 0x819d, 0x5915, 0x60dc, 0x7184, 0x70ef, 0x6eaa, 0x6c50, 0x7280, 0x6a84, 0x88ad, 0x5e2d, 0x4e60, 0x5ab3, 0x559c, 0x94e3, 0x6d17, 0x7cfb, 0x9699, 0x620f, 0x7ec6, 0x778e, 0x867e, 0x5323, 0x971e, 0x8f96, 0x6687, 0x5ce1, 0x4fa0, 0x72ed, 0x4e0b, 0x53a6, 0x590f, 0x5413, 0x6380, 0x9528, 0x5148, 0x4ed9, 0x9c9c, 0x7ea4, 0x54b8, 0x8d24, 0x8854, 0x8237, 0x95f2, 0x6d8e, 0x5f26, 0x5acc, 0x663e, 0x9669, 0x73b0, 0x732e, 0x53bf, 0x817a, 0x9985, 0x7fa1, 0x5baa, 0x9677, 0x9650, 0x7ebf, 0x76f8, 0x53a2, 0x9576, 0x9999, 0x7bb1, 0x8944, 0x6e58, 0x4e61, 0x7fd4, 0x7965, 0x8be6, 0x60f3, 0x54cd, 0x4eab, 0x9879, 0x5df7, 0x6a61, 0x50cf, 0x5411, 0x8c61, 0x8427, 0x785d, 0x9704, 0x524a, 0x54ee, 0x56a3, 0x9500, 0x6d88, 0x5bb5, 0x6dc6, 0x6653, /* 0x50 */ 0x5c0f, 0x5b5d, 0x6821, 0x8096, 0x5578, 0x7b11, 0x6548, 0x6954, 0x4e9b, 0x6b47, 0x874e, 0x978b, 0x534f, 0x631f, 0x643a, 0x90aa, 0x659c, 0x80c1, 0x8c10, 0x5199, 0x68b0, 0x5378, 0x87f9, 0x61c8, 0x6cc4, 0x6cfb, 0x8c22, 0x5c51, 0x85aa, 0x82af, 0x950c, 0x6b23, 0x8f9b, 0x65b0, 0x5ffb, 0x5fc3, 0x4fe1, 0x8845, 0x661f, 0x8165, 0x7329, 0x60fa, 0x5174, 0x5211, 0x578b, 0x5f62, 0x90a2, 0x884c, 0x9192, 0x5e78, 0x674f, 0x6027, 0x59d3, 0x5144, 0x51f6, 0x80f8, 0x5308, 0x6c79, 0x96c4, 0x718a, 0x4f11, 0x4fee, 0x7f9e, 0x673d, 0x55c5, 0x9508, 0x79c0, 0x8896, 0x7ee3, 0x589f, 0x620c, 0x9700, 0x865a, 0x5618, 0x987b, 0x5f90, 0x8bb8, 0x84c4, 0x9157, 0x53d9, 0x65ed, 0x5e8f, 0x755c, 0x6064, 0x7d6e, 0x5a7f, 0x7eea, 0x7eed, 0x8f69, 0x55a7, 0x5ba3, 0x60ac, 0x65cb, 0x7384, /* 0x51 */ 0x9009, 0x7663, 0x7729, 0x7eda, 0x9774, 0x859b, 0x5b66, 0x7a74, 0x96ea, 0x8840, 0x52cb, 0x718f, 0x5faa, 0x65ec, 0x8be2, 0x5bfb, 0x9a6f, 0x5de1, 0x6b89, 0x6c5b, 0x8bad, 0x8baf, 0x900a, 0x8fc5, 0x538b, 0x62bc, 0x9e26, 0x9e2d, 0x5440, 0x4e2b, 0x82bd, 0x7259, 0x869c, 0x5d16, 0x8859, 0x6daf, 0x96c5, 0x54d1, 0x4e9a, 0x8bb6, 0x7109, 0x54bd, 0x9609, 0x70df, 0x6df9, 0x76d0, 0x4e25, 0x7814, 0x8712, 0x5ca9, 0x5ef6, 0x8a00, 0x989c, 0x960e, 0x708e, 0x6cbf, 0x5944, 0x63a9, 0x773c, 0x884d, 0x6f14, 0x8273, 0x5830, 0x71d5, 0x538c, 0x781a, 0x96c1, 0x5501, 0x5f66, 0x7130, 0x5bb4, 0x8c1a, 0x9a8c, 0x6b83, 0x592e, 0x9e2f, 0x79e7, 0x6768, 0x626c, 0x4f6f, 0x75a1, 0x7f8a, 0x6d0b, 0x9633, 0x6c27, 0x4ef0, 0x75d2, 0x517b, 0x6837, 0x6f3e, 0x9080, 0x8170, 0x5996, 0x7476, /* 0x52 */ 0x6447, 0x5c27, 0x9065, 0x7a91, 0x8c23, 0x59da, 0x54ac, 0x8200, 0x836f, 0x8981, 0x8000, 0x6930, 0x564e, 0x8036, 0x7237, 0x91ce, 0x51b6, 0x4e5f, 0x9875, 0x6396, 0x4e1a, 0x53f6, 0x66f3, 0x814b, 0x591c, 0x6db2, 0x4e00, 0x58f9, 0x533b, 0x63d6, 0x94f1, 0x4f9d, 0x4f0a, 0x8863, 0x9890, 0x5937, 0x9057, 0x79fb, 0x4eea, 0x80f0, 0x7591, 0x6c82, 0x5b9c, 0x59e8, 0x5f5d, 0x6905, 0x8681, 0x501a, 0x5df2, 0x4e59, 0x77e3, 0x4ee5, 0x827a, 0x6291, 0x6613, 0x9091, 0x5c79, 0x4ebf, 0x5f79, 0x81c6, 0x9038, 0x8084, 0x75ab, 0x4ea6, 0x88d4, 0x610f, 0x6bc5, 0x5fc6, 0x4e49, 0x76ca, 0x6ea2, 0x8be3, 0x8bae, 0x8c0a, 0x8bd1, 0x5f02, 0x7ffc, 0x7fcc, 0x7ece, 0x8335, 0x836b, 0x56e0, 0x6bb7, 0x97f3, 0x9634, 0x59fb, 0x541f, 0x94f6, 0x6deb, 0x5bc5, 0x996e, 0x5c39, 0x5f15, 0x9690, /* 0x53 */ 0x5370, 0x82f1, 0x6a31, 0x5a74, 0x9e70, 0x5e94, 0x7f28, 0x83b9, 0x8424, 0x8425, 0x8367, 0x8747, 0x8fce, 0x8d62, 0x76c8, 0x5f71, 0x9896, 0x786c, 0x6620, 0x54df, 0x62e5, 0x4f63, 0x81c3, 0x75c8, 0x5eb8, 0x96cd, 0x8e0a, 0x86f9, 0x548f, 0x6cf3, 0x6d8c, 0x6c38, 0x607f, 0x52c7, 0x7528, 0x5e7d, 0x4f18, 0x60a0, 0x5fe7, 0x5c24, 0x7531, 0x90ae, 0x94c0, 0x72b9, 0x6cb9, 0x6e38, 0x9149, 0x6709, 0x53cb, 0x53f3, 0x4f51, 0x91c9, 0x8bf1, 0x53c8, 0x5e7c, 0x8fc2, 0x6de4, 0x4e8e, 0x76c2, 0x6986, 0x865e, 0x611a, 0x8206, 0x4f59, 0x4fde, 0x903e, 0x9c7c, 0x6109, 0x6e1d, 0x6e14, 0x9685, 0x4e88, 0x5a31, 0x96e8, 0x4e0e, 0x5c7f, 0x79b9, 0x5b87, 0x8bed, 0x7fbd, 0x7389, 0x57df, 0x828b, 0x90c1, 0x5401, 0x9047, 0x55bb, 0x5cea, 0x5fa1, 0x6108, 0x6b32, 0x72f1, 0x80b2, 0x8a89, /* 0x54 */ 0x6d74, 0x5bd3, 0x88d5, 0x9884, 0x8c6b, 0x9a6d, 0x9e33, 0x6e0a, 0x51a4, 0x5143, 0x57a3, 0x8881, 0x539f, 0x63f4, 0x8f95, 0x56ed, 0x5458, 0x5706, 0x733f, 0x6e90, 0x7f18, 0x8fdc, 0x82d1, 0x613f, 0x6028, 0x9662, 0x66f0, 0x7ea6, 0x8d8a, 0x8dc3, 0x94a5, 0x5cb3, 0x7ca4, 0x6708, 0x60a6, 0x9605, 0x8018, 0x4e91, 0x90e7, 0x5300, 0x9668, 0x5141, 0x8fd0, 0x8574, 0x915d, 0x6655, 0x97f5, 0x5b55, 0x531d, 0x7838, 0x6742, 0x683d, 0x54c9, 0x707e, 0x5bb0, 0x8f7d, 0x518d, 0x5728, 0x54b1, 0x6512, 0x6682, 0x8d5e, 0x8d43, 0x810f, 0x846c, 0x906d, 0x7cdf, 0x51ff, 0x85fb, 0x67a3, 0x65e9, 0x6fa1, 0x86a4, 0x8e81, 0x566a, 0x9020, 0x7682, 0x7076, 0x71e5, 0x8d23, 0x62e9, 0x5219, 0x6cfd, 0x8d3c, 0x600e, 0x589e, 0x618e, 0x66fe, 0x8d60, 0x624e, 0x55b3, 0x6e23, 0x672d, 0x8f67, /* 0x55 */ 0x94e1, 0x95f8, 0x7728, 0x6805, 0x69a8, 0x548b, 0x4e4d, 0x70b8, 0x8bc8, 0x6458, 0x658b, 0x5b85, 0x7a84, 0x503a, 0x5be8, 0x77bb, 0x6be1, 0x8a79, 0x7c98, 0x6cbe, 0x76cf, 0x65a9, 0x8f97, 0x5d2d, 0x5c55, 0x8638, 0x6808, 0x5360, 0x6218, 0x7ad9, 0x6e5b, 0x7efd, 0x6a1f, 0x7ae0, 0x5f70, 0x6f33, 0x5f20, 0x638c, 0x6da8, 0x6756, 0x4e08, 0x5e10, 0x8d26, 0x4ed7, 0x80c0, 0x7634, 0x969c, 0x62db, 0x662d, 0x627e, 0x6cbc, 0x8d75, 0x7167, 0x7f69, 0x5146, 0x8087, 0x53ec, 0x906e, 0x6298, 0x54f2, 0x86f0, 0x8f99, 0x8005, 0x9517, 0x8517, 0x8fd9, 0x6d59, 0x73cd, 0x659f, 0x771f, 0x7504, 0x7827, 0x81fb, 0x8d1e, 0x9488, 0x4fa6, 0x6795, 0x75b9, 0x8bca, 0x9707, 0x632f, 0x9547, 0x9635, 0x84b8, 0x6323, 0x7741, 0x5f81, 0x72f0, 0x4e89, 0x6014, 0x6574, 0x62ef, 0x6b63, 0x653f, /* 0x56 */ 0x5e27, 0x75c7, 0x90d1, 0x8bc1, 0x829d, 0x679d, 0x652f, 0x5431, 0x8718, 0x77e5, 0x80a2, 0x8102, 0x6c41, 0x4e4b, 0x7ec7, 0x804c, 0x76f4, 0x690d, 0x6b96, 0x6267, 0x503c, 0x4f84, 0x5740, 0x6307, 0x6b62, 0x8dbe, 0x53ea, 0x65e8, 0x7eb8, 0x5fd7, 0x631a, 0x63b7, 0x81f3, 0x81f4, 0x7f6e, 0x5e1c, 0x5cd9, 0x5236, 0x667a, 0x79e9, 0x7a1a, 0x8d28, 0x7099, 0x75d4, 0x6ede, 0x6cbb, 0x7a92, 0x4e2d, 0x76c5, 0x5fe0, 0x949f, 0x8877, 0x7ec8, 0x79cd, 0x80bf, 0x91cd, 0x4ef2, 0x4f17, 0x821f, 0x5468, 0x5dde, 0x6d32, 0x8bcc, 0x7ca5, 0x8f74, 0x8098, 0x5e1a, 0x5492, 0x76b1, 0x5b99, 0x663c, 0x9aa4, 0x73e0, 0x682a, 0x86db, 0x6731, 0x732a, 0x8bf8, 0x8bdb, 0x9010, 0x7af9, 0x70db, 0x716e, 0x62c4, 0x77a9, 0x5631, 0x4e3b, 0x8457, 0x67f1, 0x52a9, 0x86c0, 0x8d2e, 0x94f8, 0x7b51, /* 0x57 */ 0x4f4f, 0x6ce8, 0x795d, 0x9a7b, 0x6293, 0x722a, 0x62fd, 0x4e13, 0x7816, 0x8f6c, 0x64b0, 0x8d5a, 0x7bc6, 0x6869, 0x5e84, 0x88c5, 0x5986, 0x649e, 0x58ee, 0x72b6, 0x690e, 0x9525, 0x8ffd, 0x8d58, 0x5760, 0x7f00, 0x8c06, 0x51c6, 0x6349, 0x62d9, 0x5353, 0x684c, 0x7422, 0x8301, 0x914c, 0x5544, 0x7740, 0x707c, 0x6d4a, 0x5179, 0x54a8, 0x8d44, 0x59ff, 0x6ecb, 0x6dc4, 0x5b5c, 0x7d2b, 0x4ed4, 0x7c7d, 0x6ed3, 0x5b50, 0x81ea, 0x6e0d, 0x5b57, 0x9b03, 0x68d5, 0x8e2a, 0x5b97, 0x7efc, 0x603b, 0x7eb5, 0x90b9, 0x8d70, 0x594f, 0x63cd, 0x79df, 0x8db3, 0x5352, 0x65cf, 0x7956, 0x8bc5, 0x963b, 0x7ec4, 0x94bb, 0x7e82, 0x5634, 0x9189, 0x6700, 0x7f6a, 0x5c0a, 0x9075, 0x6628, 0x5de6, 0x4f50, 0x67de, 0x505a, 0x4f5c, 0x5750, 0x5ea7, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x58 */ 0x4e8d, 0x4e0c, 0x5140, 0x4e10, 0x5eff, 0x5345, 0x4e15, 0x4e98, 0x4e1e, 0x9b32, 0x5b6c, 0x5669, 0x4e28, 0x79ba, 0x4e3f, 0x5315, 0x4e47, 0x592d, 0x723b, 0x536e, 0x6c10, 0x56df, 0x80e4, 0x9997, 0x6bd3, 0x777e, 0x9f17, 0x4e36, 0x4e9f, 0x9f10, 0x4e5c, 0x4e69, 0x4e93, 0x8288, 0x5b5b, 0x556c, 0x560f, 0x4ec4, 0x538d, 0x539d, 0x53a3, 0x53a5, 0x53ae, 0x9765, 0x8d5d, 0x531a, 0x53f5, 0x5326, 0x532e, 0x533e, 0x8d5c, 0x5366, 0x5363, 0x5202, 0x5208, 0x520e, 0x522d, 0x5233, 0x523f, 0x5240, 0x524c, 0x525e, 0x5261, 0x525c, 0x84af, 0x527d, 0x5282, 0x5281, 0x5290, 0x5293, 0x5182, 0x7f54, 0x4ebb, 0x4ec3, 0x4ec9, 0x4ec2, 0x4ee8, 0x4ee1, 0x4eeb, 0x4ede, 0x4f1b, 0x4ef3, 0x4f22, 0x4f64, 0x4ef5, 0x4f25, 0x4f27, 0x4f09, 0x4f2b, 0x4f5e, 0x4f67, 0x6538, 0x4f5a, 0x4f5d, /* 0x59 */ 0x4f5f, 0x4f57, 0x4f32, 0x4f3d, 0x4f76, 0x4f74, 0x4f91, 0x4f89, 0x4f83, 0x4f8f, 0x4f7e, 0x4f7b, 0x4faa, 0x4f7c, 0x4fac, 0x4f94, 0x4fe6, 0x4fe8, 0x4fea, 0x4fc5, 0x4fda, 0x4fe3, 0x4fdc, 0x4fd1, 0x4fdf, 0x4ff8, 0x5029, 0x504c, 0x4ff3, 0x502c, 0x500f, 0x502e, 0x502d, 0x4ffe, 0x501c, 0x500c, 0x5025, 0x5028, 0x507e, 0x5043, 0x5055, 0x5048, 0x504e, 0x506c, 0x507b, 0x50a5, 0x50a7, 0x50a9, 0x50ba, 0x50d6, 0x5106, 0x50ed, 0x50ec, 0x50e6, 0x50ee, 0x5107, 0x510b, 0x4edd, 0x6c3d, 0x4f58, 0x4f65, 0x4fce, 0x9fa0, 0x6c46, 0x7c74, 0x516e, 0x5dfd, 0x9ec9, 0x9998, 0x5181, 0x5914, 0x52f9, 0x530d, 0x8a07, 0x5310, 0x51eb, 0x5919, 0x5155, 0x4ea0, 0x5156, 0x4eb3, 0x886e, 0x88a4, 0x4eb5, 0x8114, 0x88d2, 0x7980, 0x5b34, 0x8803, 0x7fb8, 0x51ab, 0x51b1, 0x51bd, 0x51bc, /* 0x5a */ 0x51c7, 0x5196, 0x51a2, 0x51a5, 0x8ba0, 0x8ba6, 0x8ba7, 0x8baa, 0x8bb4, 0x8bb5, 0x8bb7, 0x8bc2, 0x8bc3, 0x8bcb, 0x8bcf, 0x8bce, 0x8bd2, 0x8bd3, 0x8bd4, 0x8bd6, 0x8bd8, 0x8bd9, 0x8bdc, 0x8bdf, 0x8be0, 0x8be4, 0x8be8, 0x8be9, 0x8bee, 0x8bf0, 0x8bf3, 0x8bf6, 0x8bf9, 0x8bfc, 0x8bff, 0x8c00, 0x8c02, 0x8c04, 0x8c07, 0x8c0c, 0x8c0f, 0x8c11, 0x8c12, 0x8c14, 0x8c15, 0x8c16, 0x8c19, 0x8c1b, 0x8c18, 0x8c1d, 0x8c1f, 0x8c20, 0x8c21, 0x8c25, 0x8c27, 0x8c2a, 0x8c2b, 0x8c2e, 0x8c2f, 0x8c32, 0x8c33, 0x8c35, 0x8c36, 0x5369, 0x537a, 0x961d, 0x9622, 0x9621, 0x9631, 0x962a, 0x963d, 0x963c, 0x9642, 0x9649, 0x9654, 0x965f, 0x9667, 0x966c, 0x9672, 0x9674, 0x9688, 0x968d, 0x9697, 0x96b0, 0x9097, 0x909b, 0x909d, 0x9099, 0x90ac, 0x90a1, 0x90b4, 0x90b3, 0x90b6, 0x90ba, /* 0x5b */ 0x90b8, 0x90b0, 0x90cf, 0x90c5, 0x90be, 0x90d0, 0x90c4, 0x90c7, 0x90d3, 0x90e6, 0x90e2, 0x90dc, 0x90d7, 0x90db, 0x90eb, 0x90ef, 0x90fe, 0x9104, 0x9122, 0x911e, 0x9123, 0x9131, 0x912f, 0x9139, 0x9143, 0x9146, 0x520d, 0x5942, 0x52a2, 0x52ac, 0x52ad, 0x52be, 0x54ff, 0x52d0, 0x52d6, 0x52f0, 0x53df, 0x71ee, 0x77cd, 0x5ef4, 0x51f5, 0x51fc, 0x9b2f, 0x53b6, 0x5f01, 0x755a, 0x5def, 0x574c, 0x57a9, 0x57a1, 0x587e, 0x58bc, 0x58c5, 0x58d1, 0x5729, 0x572c, 0x572a, 0x5733, 0x5739, 0x572e, 0x572f, 0x575c, 0x573b, 0x5742, 0x5769, 0x5785, 0x576b, 0x5786, 0x577c, 0x577b, 0x5768, 0x576d, 0x5776, 0x5773, 0x57ad, 0x57a4, 0x578c, 0x57b2, 0x57cf, 0x57a7, 0x57b4, 0x5793, 0x57a0, 0x57d5, 0x57d8, 0x57da, 0x57d9, 0x57d2, 0x57b8, 0x57f4, 0x57ef, 0x57f8, 0x57e4, 0x57dd, /* 0x5c */ 0x580b, 0x580d, 0x57fd, 0x57ed, 0x5800, 0x581e, 0x5819, 0x5844, 0x5820, 0x5865, 0x586c, 0x5881, 0x5889, 0x589a, 0x5880, 0x99a8, 0x9f19, 0x61ff, 0x8279, 0x827d, 0x827f, 0x828f, 0x828a, 0x82a8, 0x8284, 0x828e, 0x8291, 0x8297, 0x8299, 0x82ab, 0x82b8, 0x82be, 0x82b0, 0x82c8, 0x82ca, 0x82e3, 0x8298, 0x82b7, 0x82ae, 0x82cb, 0x82cc, 0x82c1, 0x82a9, 0x82b4, 0x82a1, 0x82aa, 0x829f, 0x82c4, 0x82ce, 0x82a4, 0x82e1, 0x8309, 0x82f7, 0x82e4, 0x830f, 0x8307, 0x82dc, 0x82f4, 0x82d2, 0x82d8, 0x830c, 0x82fb, 0x82d3, 0x8311, 0x831a, 0x8306, 0x8314, 0x8315, 0x82e0, 0x82d5, 0x831c, 0x8351, 0x835b, 0x835c, 0x8308, 0x8392, 0x833c, 0x8334, 0x8331, 0x839b, 0x835e, 0x832f, 0x834f, 0x8347, 0x8343, 0x835f, 0x8340, 0x8317, 0x8360, 0x832d, 0x833a, 0x8333, 0x8366, 0x8365, /* 0x5d */ 0x8368, 0x831b, 0x8369, 0x836c, 0x836a, 0x836d, 0x836e, 0x83b0, 0x8378, 0x83b3, 0x83b4, 0x83a0, 0x83aa, 0x8393, 0x839c, 0x8385, 0x837c, 0x83b6, 0x83a9, 0x837d, 0x83b8, 0x837b, 0x8398, 0x839e, 0x83a8, 0x83ba, 0x83bc, 0x83c1, 0x8401, 0x83e5, 0x83d8, 0x5807, 0x8418, 0x840b, 0x83dd, 0x83fd, 0x83d6, 0x841c, 0x8438, 0x8411, 0x8406, 0x83d4, 0x83df, 0x840f, 0x8403, 0x83f8, 0x83f9, 0x83ea, 0x83c5, 0x83c0, 0x8426, 0x83f0, 0x83e1, 0x845c, 0x8451, 0x845a, 0x8459, 0x8473, 0x8487, 0x8488, 0x847a, 0x8489, 0x8478, 0x843c, 0x8446, 0x8469, 0x8476, 0x848c, 0x848e, 0x8431, 0x846d, 0x84c1, 0x84cd, 0x84d0, 0x84e6, 0x84bd, 0x84d3, 0x84ca, 0x84bf, 0x84ba, 0x84e0, 0x84a1, 0x84b9, 0x84b4, 0x8497, 0x84e5, 0x84e3, 0x850c, 0x750d, 0x8538, 0x84f0, 0x8539, 0x851f, 0x853a, /* 0x5e */ 0x8556, 0x853b, 0x84ff, 0x84fc, 0x8559, 0x8548, 0x8568, 0x8564, 0x855e, 0x857a, 0x77a2, 0x8543, 0x8572, 0x857b, 0x85a4, 0x85a8, 0x8587, 0x858f, 0x8579, 0x85ae, 0x859c, 0x8585, 0x85b9, 0x85b7, 0x85b0, 0x85d3, 0x85c1, 0x85dc, 0x85ff, 0x8627, 0x8605, 0x8629, 0x8616, 0x863c, 0x5efe, 0x5f08, 0x593c, 0x5941, 0x8037, 0x5955, 0x595a, 0x5958, 0x530f, 0x5c22, 0x5c25, 0x5c2c, 0x5c34, 0x624c, 0x626a, 0x629f, 0x62bb, 0x62ca, 0x62da, 0x62d7, 0x62ee, 0x6322, 0x62f6, 0x6339, 0x634b, 0x6343, 0x63ad, 0x63f6, 0x6371, 0x637a, 0x638e, 0x63b4, 0x636d, 0x63ac, 0x638a, 0x6369, 0x63ae, 0x63bc, 0x63f2, 0x63f8, 0x63e0, 0x63ff, 0x63c4, 0x63de, 0x63ce, 0x6452, 0x63c6, 0x63be, 0x6445, 0x6441, 0x640b, 0x641b, 0x6420, 0x640c, 0x6426, 0x6421, 0x645e, 0x6484, 0x646d, 0x6496, /* 0x5f */ 0x647a, 0x64b7, 0x64b8, 0x6499, 0x64ba, 0x64c0, 0x64d0, 0x64d7, 0x64e4, 0x64e2, 0x6509, 0x6525, 0x652e, 0x5f0b, 0x5fd2, 0x7519, 0x5f11, 0x535f, 0x53f1, 0x53fd, 0x53e9, 0x53e8, 0x53fb, 0x5412, 0x5416, 0x5406, 0x544b, 0x5452, 0x5453, 0x5454, 0x5456, 0x5443, 0x5421, 0x5457, 0x5459, 0x5423, 0x5432, 0x5482, 0x5494, 0x5477, 0x5471, 0x5464, 0x549a, 0x549b, 0x5484, 0x5476, 0x5466, 0x549d, 0x54d0, 0x54ad, 0x54c2, 0x54b4, 0x54d2, 0x54a7, 0x54a6, 0x54d3, 0x54d4, 0x5472, 0x54a3, 0x54d5, 0x54bb, 0x54bf, 0x54cc, 0x54d9, 0x54da, 0x54dc, 0x54a9, 0x54aa, 0x54a4, 0x54dd, 0x54cf, 0x54de, 0x551b, 0x54e7, 0x5520, 0x54fd, 0x5514, 0x54f3, 0x5522, 0x5523, 0x550f, 0x5511, 0x5527, 0x552a, 0x5567, 0x558f, 0x55b5, 0x5549, 0x556d, 0x5541, 0x5555, 0x553f, 0x5550, 0x553c, /* 0x60 */ 0x5537, 0x5556, 0x5575, 0x5576, 0x5577, 0x5533, 0x5530, 0x555c, 0x558b, 0x55d2, 0x5583, 0x55b1, 0x55b9, 0x5588, 0x5581, 0x559f, 0x557e, 0x55d6, 0x5591, 0x557b, 0x55df, 0x55bd, 0x55be, 0x5594, 0x5599, 0x55ea, 0x55f7, 0x55c9, 0x561f, 0x55d1, 0x55eb, 0x55ec, 0x55d4, 0x55e6, 0x55dd, 0x55c4, 0x55ef, 0x55e5, 0x55f2, 0x55f3, 0x55cc, 0x55cd, 0x55e8, 0x55f5, 0x55e4, 0x8f94, 0x561e, 0x5608, 0x560c, 0x5601, 0x5624, 0x5623, 0x55fe, 0x5600, 0x5627, 0x562d, 0x5658, 0x5639, 0x5657, 0x562c, 0x564d, 0x5662, 0x5659, 0x565c, 0x564c, 0x5654, 0x5686, 0x5664, 0x5671, 0x566b, 0x567b, 0x567c, 0x5685, 0x5693, 0x56af, 0x56d4, 0x56d7, 0x56dd, 0x56e1, 0x56f5, 0x56eb, 0x56f9, 0x56ff, 0x5704, 0x570a, 0x5709, 0x571c, 0x5e0f, 0x5e19, 0x5e14, 0x5e11, 0x5e31, 0x5e3b, 0x5e3c, /* 0x61 */ 0x5e37, 0x5e44, 0x5e54, 0x5e5b, 0x5e5e, 0x5e61, 0x5c8c, 0x5c7a, 0x5c8d, 0x5c90, 0x5c96, 0x5c88, 0x5c98, 0x5c99, 0x5c91, 0x5c9a, 0x5c9c, 0x5cb5, 0x5ca2, 0x5cbd, 0x5cac, 0x5cab, 0x5cb1, 0x5ca3, 0x5cc1, 0x5cb7, 0x5cc4, 0x5cd2, 0x5ce4, 0x5ccb, 0x5ce5, 0x5d02, 0x5d03, 0x5d27, 0x5d26, 0x5d2e, 0x5d24, 0x5d1e, 0x5d06, 0x5d1b, 0x5d58, 0x5d3e, 0x5d34, 0x5d3d, 0x5d6c, 0x5d5b, 0x5d6f, 0x5d5d, 0x5d6b, 0x5d4b, 0x5d4a, 0x5d69, 0x5d74, 0x5d82, 0x5d99, 0x5d9d, 0x8c73, 0x5db7, 0x5dc5, 0x5f73, 0x5f77, 0x5f82, 0x5f87, 0x5f89, 0x5f8c, 0x5f95, 0x5f99, 0x5f9c, 0x5fa8, 0x5fad, 0x5fb5, 0x5fbc, 0x8862, 0x5f61, 0x72ad, 0x72b0, 0x72b4, 0x72b7, 0x72b8, 0x72c3, 0x72c1, 0x72ce, 0x72cd, 0x72d2, 0x72e8, 0x72ef, 0x72e9, 0x72f2, 0x72f4, 0x72f7, 0x7301, 0x72f3, 0x7303, 0x72fa, /* 0x62 */ 0x72fb, 0x7317, 0x7313, 0x7321, 0x730a, 0x731e, 0x731d, 0x7315, 0x7322, 0x7339, 0x7325, 0x732c, 0x7338, 0x7331, 0x7350, 0x734d, 0x7357, 0x7360, 0x736c, 0x736f, 0x737e, 0x821b, 0x5925, 0x98e7, 0x5924, 0x5902, 0x9963, 0x9967, 0x9968, 0x9969, 0x996a, 0x996b, 0x996c, 0x9974, 0x9977, 0x997d, 0x9980, 0x9984, 0x9987, 0x998a, 0x998d, 0x9990, 0x9991, 0x9993, 0x9994, 0x9995, 0x5e80, 0x5e91, 0x5e8b, 0x5e96, 0x5ea5, 0x5ea0, 0x5eb9, 0x5eb5, 0x5ebe, 0x5eb3, 0x8d53, 0x5ed2, 0x5ed1, 0x5edb, 0x5ee8, 0x5eea, 0x81ba, 0x5fc4, 0x5fc9, 0x5fd6, 0x5fcf, 0x6003, 0x5fee, 0x6004, 0x5fe1, 0x5fe4, 0x5ffe, 0x6005, 0x6006, 0x5fea, 0x5fed, 0x5ff8, 0x6019, 0x6035, 0x6026, 0x601b, 0x600f, 0x600d, 0x6029, 0x602b, 0x600a, 0x603f, 0x6021, 0x6078, 0x6079, 0x607b, 0x607a, 0x6042, /* 0x63 */ 0x606a, 0x607d, 0x6096, 0x609a, 0x60ad, 0x609d, 0x6083, 0x6092, 0x608c, 0x609b, 0x60ec, 0x60bb, 0x60b1, 0x60dd, 0x60d8, 0x60c6, 0x60da, 0x60b4, 0x6120, 0x6126, 0x6115, 0x6123, 0x60f4, 0x6100, 0x610e, 0x612b, 0x614a, 0x6175, 0x61ac, 0x6194, 0x61a7, 0x61b7, 0x61d4, 0x61f5, 0x5fdd, 0x96b3, 0x95e9, 0x95eb, 0x95f1, 0x95f3, 0x95f5, 0x95f6, 0x95fc, 0x95fe, 0x9603, 0x9604, 0x9606, 0x9608, 0x960a, 0x960b, 0x960c, 0x960d, 0x960f, 0x9612, 0x9615, 0x9616, 0x9617, 0x9619, 0x961a, 0x4e2c, 0x723f, 0x6215, 0x6c35, 0x6c54, 0x6c5c, 0x6c4a, 0x6ca3, 0x6c85, 0x6c90, 0x6c94, 0x6c8c, 0x6c68, 0x6c69, 0x6c74, 0x6c76, 0x6c86, 0x6ca9, 0x6cd0, 0x6cd4, 0x6cad, 0x6cf7, 0x6cf8, 0x6cf1, 0x6cd7, 0x6cb2, 0x6ce0, 0x6cd6, 0x6cfa, 0x6ceb, 0x6cee, 0x6cb1, 0x6cd3, 0x6cef, 0x6cfe, /* 0x64 */ 0x6d39, 0x6d27, 0x6d0c, 0x6d43, 0x6d48, 0x6d07, 0x6d04, 0x6d19, 0x6d0e, 0x6d2b, 0x6d4d, 0x6d2e, 0x6d35, 0x6d1a, 0x6d4f, 0x6d52, 0x6d54, 0x6d33, 0x6d91, 0x6d6f, 0x6d9e, 0x6da0, 0x6d5e, 0x6d93, 0x6d94, 0x6d5c, 0x6d60, 0x6d7c, 0x6d63, 0x6e1a, 0x6dc7, 0x6dc5, 0x6dde, 0x6e0e, 0x6dbf, 0x6de0, 0x6e11, 0x6de6, 0x6ddd, 0x6dd9, 0x6e16, 0x6dab, 0x6e0c, 0x6dae, 0x6e2b, 0x6e6e, 0x6e4e, 0x6e6b, 0x6eb2, 0x6e5f, 0x6e86, 0x6e53, 0x6e54, 0x6e32, 0x6e25, 0x6e44, 0x6edf, 0x6eb1, 0x6e98, 0x6ee0, 0x6f2d, 0x6ee2, 0x6ea5, 0x6ea7, 0x6ebd, 0x6ebb, 0x6eb7, 0x6ed7, 0x6eb4, 0x6ecf, 0x6e8f, 0x6ec2, 0x6e9f, 0x6f62, 0x6f46, 0x6f47, 0x6f24, 0x6f15, 0x6ef9, 0x6f2f, 0x6f36, 0x6f4b, 0x6f74, 0x6f2a, 0x6f09, 0x6f29, 0x6f89, 0x6f8d, 0x6f8c, 0x6f78, 0x6f72, 0x6f7c, 0x6f7a, 0x6fd1, /* 0x65 */ 0x6fc9, 0x6fa7, 0x6fb9, 0x6fb6, 0x6fc2, 0x6fe1, 0x6fee, 0x6fde, 0x6fe0, 0x6fef, 0x701a, 0x7023, 0x701b, 0x7039, 0x7035, 0x704f, 0x705e, 0x5b80, 0x5b84, 0x5b95, 0x5b93, 0x5ba5, 0x5bb8, 0x752f, 0x9a9e, 0x6434, 0x5be4, 0x5bee, 0x8930, 0x5bf0, 0x8e47, 0x8b07, 0x8fb6, 0x8fd3, 0x8fd5, 0x8fe5, 0x8fee, 0x8fe4, 0x8fe9, 0x8fe6, 0x8ff3, 0x8fe8, 0x9005, 0x9004, 0x900b, 0x9026, 0x9011, 0x900d, 0x9016, 0x9021, 0x9035, 0x9036, 0x902d, 0x902f, 0x9044, 0x9051, 0x9052, 0x9050, 0x9068, 0x9058, 0x9062, 0x905b, 0x66b9, 0x9074, 0x907d, 0x9082, 0x9088, 0x9083, 0x908b, 0x5f50, 0x5f57, 0x5f56, 0x5f58, 0x5c3b, 0x54ab, 0x5c50, 0x5c59, 0x5b71, 0x5c63, 0x5c66, 0x7fbc, 0x5f2a, 0x5f29, 0x5f2d, 0x8274, 0x5f3c, 0x9b3b, 0x5c6e, 0x5981, 0x5983, 0x598d, 0x59a9, 0x59aa, 0x59a3, /* 0x66 */ 0x5997, 0x59ca, 0x59ab, 0x599e, 0x59a4, 0x59d2, 0x59b2, 0x59af, 0x59d7, 0x59be, 0x5a05, 0x5a06, 0x59dd, 0x5a08, 0x59e3, 0x59d8, 0x59f9, 0x5a0c, 0x5a09, 0x5a32, 0x5a34, 0x5a11, 0x5a23, 0x5a13, 0x5a40, 0x5a67, 0x5a4a, 0x5a55, 0x5a3c, 0x5a62, 0x5a75, 0x80ec, 0x5aaa, 0x5a9b, 0x5a77, 0x5a7a, 0x5abe, 0x5aeb, 0x5ab2, 0x5ad2, 0x5ad4, 0x5ab8, 0x5ae0, 0x5ae3, 0x5af1, 0x5ad6, 0x5ae6, 0x5ad8, 0x5adc, 0x5b09, 0x5b17, 0x5b16, 0x5b32, 0x5b37, 0x5b40, 0x5c15, 0x5c1c, 0x5b5a, 0x5b65, 0x5b73, 0x5b51, 0x5b53, 0x5b62, 0x9a75, 0x9a77, 0x9a78, 0x9a7a, 0x9a7f, 0x9a7d, 0x9a80, 0x9a81, 0x9a85, 0x9a88, 0x9a8a, 0x9a90, 0x9a92, 0x9a93, 0x9a96, 0x9a98, 0x9a9b, 0x9a9c, 0x9a9d, 0x9a9f, 0x9aa0, 0x9aa2, 0x9aa3, 0x9aa5, 0x9aa7, 0x7e9f, 0x7ea1, 0x7ea3, 0x7ea5, 0x7ea8, 0x7ea9, /* 0x67 */ 0x7ead, 0x7eb0, 0x7ebe, 0x7ec0, 0x7ec1, 0x7ec2, 0x7ec9, 0x7ecb, 0x7ecc, 0x7ed0, 0x7ed4, 0x7ed7, 0x7edb, 0x7ee0, 0x7ee1, 0x7ee8, 0x7eeb, 0x7eee, 0x7eef, 0x7ef1, 0x7ef2, 0x7f0d, 0x7ef6, 0x7efa, 0x7efb, 0x7efe, 0x7f01, 0x7f02, 0x7f03, 0x7f07, 0x7f08, 0x7f0b, 0x7f0c, 0x7f0f, 0x7f11, 0x7f12, 0x7f17, 0x7f19, 0x7f1c, 0x7f1b, 0x7f1f, 0x7f21, 0x7f22, 0x7f23, 0x7f24, 0x7f25, 0x7f26, 0x7f27, 0x7f2a, 0x7f2b, 0x7f2c, 0x7f2d, 0x7f2f, 0x7f30, 0x7f31, 0x7f32, 0x7f33, 0x7f35, 0x5e7a, 0x757f, 0x5ddb, 0x753e, 0x9095, 0x738e, 0x7391, 0x73ae, 0x73a2, 0x739f, 0x73cf, 0x73c2, 0x73d1, 0x73b7, 0x73b3, 0x73c0, 0x73c9, 0x73c8, 0x73e5, 0x73d9, 0x987c, 0x740a, 0x73e9, 0x73e7, 0x73de, 0x73ba, 0x73f2, 0x740f, 0x742a, 0x745b, 0x7426, 0x7425, 0x7428, 0x7430, 0x742e, 0x742c, /* 0x68 */ 0x741b, 0x741a, 0x7441, 0x745c, 0x7457, 0x7455, 0x7459, 0x7477, 0x746d, 0x747e, 0x749c, 0x748e, 0x7480, 0x7481, 0x7487, 0x748b, 0x749e, 0x74a8, 0x74a9, 0x7490, 0x74a7, 0x74d2, 0x74ba, 0x97ea, 0x97eb, 0x97ec, 0x674c, 0x6753, 0x675e, 0x6748, 0x6769, 0x67a5, 0x6787, 0x676a, 0x6773, 0x6798, 0x67a7, 0x6775, 0x67a8, 0x679e, 0x67ad, 0x678b, 0x6777, 0x677c, 0x67f0, 0x6809, 0x67d8, 0x680a, 0x67e9, 0x67b0, 0x680c, 0x67d9, 0x67b5, 0x67da, 0x67b3, 0x67dd, 0x6800, 0x67c3, 0x67b8, 0x67e2, 0x680e, 0x67c1, 0x67fd, 0x6832, 0x6833, 0x6860, 0x6861, 0x684e, 0x6862, 0x6844, 0x6864, 0x6883, 0x681d, 0x6855, 0x6866, 0x6841, 0x6867, 0x6840, 0x683e, 0x684a, 0x6849, 0x6829, 0x68b5, 0x688f, 0x6874, 0x6877, 0x6893, 0x686b, 0x68c2, 0x696e, 0x68fc, 0x691f, 0x6920, 0x68f9, /* 0x69 */ 0x6924, 0x68f0, 0x690b, 0x6901, 0x6957, 0x68e3, 0x6910, 0x6971, 0x6939, 0x6960, 0x6942, 0x695d, 0x6984, 0x696b, 0x6980, 0x6998, 0x6978, 0x6934, 0x69cc, 0x6987, 0x6988, 0x69ce, 0x6989, 0x6966, 0x6963, 0x6979, 0x699b, 0x69a7, 0x69bb, 0x69ab, 0x69ad, 0x69d4, 0x69b1, 0x69c1, 0x69ca, 0x69df, 0x6995, 0x69e0, 0x698d, 0x69ff, 0x6a2f, 0x69ed, 0x6a17, 0x6a18, 0x6a65, 0x69f2, 0x6a44, 0x6a3e, 0x6aa0, 0x6a50, 0x6a5b, 0x6a35, 0x6a8e, 0x6a79, 0x6a3d, 0x6a28, 0x6a58, 0x6a7c, 0x6a91, 0x6a90, 0x6aa9, 0x6a97, 0x6aab, 0x7337, 0x7352, 0x6b81, 0x6b82, 0x6b87, 0x6b84, 0x6b92, 0x6b93, 0x6b8d, 0x6b9a, 0x6b9b, 0x6ba1, 0x6baa, 0x8f6b, 0x8f6d, 0x8f71, 0x8f72, 0x8f73, 0x8f75, 0x8f76, 0x8f78, 0x8f77, 0x8f79, 0x8f7a, 0x8f7c, 0x8f7e, 0x8f81, 0x8f82, 0x8f84, 0x8f87, 0x8f8b, /* 0x6a */ 0x8f8d, 0x8f8e, 0x8f8f, 0x8f98, 0x8f9a, 0x8ece, 0x620b, 0x6217, 0x621b, 0x621f, 0x6222, 0x6221, 0x6225, 0x6224, 0x622c, 0x81e7, 0x74ef, 0x74f4, 0x74ff, 0x750f, 0x7511, 0x7513, 0x6534, 0x65ee, 0x65ef, 0x65f0, 0x660a, 0x6619, 0x6772, 0x6603, 0x6615, 0x6600, 0x7085, 0x66f7, 0x661d, 0x6634, 0x6631, 0x6636, 0x6635, 0x8006, 0x665f, 0x6654, 0x6641, 0x664f, 0x6656, 0x6661, 0x6657, 0x6677, 0x6684, 0x668c, 0x66a7, 0x669d, 0x66be, 0x66db, 0x66dc, 0x66e6, 0x66e9, 0x8d32, 0x8d33, 0x8d36, 0x8d3b, 0x8d3d, 0x8d40, 0x8d45, 0x8d46, 0x8d48, 0x8d49, 0x8d47, 0x8d4d, 0x8d55, 0x8d59, 0x89c7, 0x89ca, 0x89cb, 0x89cc, 0x89ce, 0x89cf, 0x89d0, 0x89d1, 0x726e, 0x729f, 0x725d, 0x7266, 0x726f, 0x727e, 0x727f, 0x7284, 0x728b, 0x728d, 0x728f, 0x7292, 0x6308, 0x6332, 0x63b0, /* 0x6b */ 0x643f, 0x64d8, 0x8004, 0x6bea, 0x6bf3, 0x6bfd, 0x6bf5, 0x6bf9, 0x6c05, 0x6c07, 0x6c06, 0x6c0d, 0x6c15, 0x6c18, 0x6c19, 0x6c1a, 0x6c21, 0x6c29, 0x6c24, 0x6c2a, 0x6c32, 0x6535, 0x6555, 0x656b, 0x724d, 0x7252, 0x7256, 0x7230, 0x8662, 0x5216, 0x809f, 0x809c, 0x8093, 0x80bc, 0x670a, 0x80bd, 0x80b1, 0x80ab, 0x80ad, 0x80b4, 0x80b7, 0x80e7, 0x80e8, 0x80e9, 0x80ea, 0x80db, 0x80c2, 0x80c4, 0x80d9, 0x80cd, 0x80d7, 0x6710, 0x80dd, 0x80eb, 0x80f1, 0x80f4, 0x80ed, 0x810d, 0x810e, 0x80f2, 0x80fc, 0x6715, 0x8112, 0x8c5a, 0x8136, 0x811e, 0x812c, 0x8118, 0x8132, 0x8148, 0x814c, 0x8153, 0x8174, 0x8159, 0x815a, 0x8171, 0x8160, 0x8169, 0x817c, 0x817d, 0x816d, 0x8167, 0x584d, 0x5ab5, 0x8188, 0x8182, 0x8191, 0x6ed5, 0x81a3, 0x81aa, 0x81cc, 0x6726, 0x81ca, 0x81bb, /* 0x6c */ 0x81c1, 0x81a6, 0x6b24, 0x6b37, 0x6b39, 0x6b43, 0x6b46, 0x6b59, 0x98d1, 0x98d2, 0x98d3, 0x98d5, 0x98d9, 0x98da, 0x6bb3, 0x5f40, 0x6bc2, 0x89f3, 0x6590, 0x9f51, 0x6593, 0x65bc, 0x65c6, 0x65c4, 0x65c3, 0x65cc, 0x65ce, 0x65d2, 0x65d6, 0x7080, 0x709c, 0x7096, 0x709d, 0x70bb, 0x70c0, 0x70b7, 0x70ab, 0x70b1, 0x70e8, 0x70ca, 0x7110, 0x7113, 0x7116, 0x712f, 0x7131, 0x7173, 0x715c, 0x7168, 0x7145, 0x7172, 0x714a, 0x7178, 0x717a, 0x7198, 0x71b3, 0x71b5, 0x71a8, 0x71a0, 0x71e0, 0x71d4, 0x71e7, 0x71f9, 0x721d, 0x7228, 0x706c, 0x7118, 0x7166, 0x71b9, 0x623e, 0x623d, 0x6243, 0x6248, 0x6249, 0x793b, 0x7940, 0x7946, 0x7949, 0x795b, 0x795c, 0x7953, 0x795a, 0x7962, 0x7957, 0x7960, 0x796f, 0x7967, 0x797a, 0x7985, 0x798a, 0x799a, 0x79a7, 0x79b3, 0x5fd1, 0x5fd0, /* 0x6d */ 0x603c, 0x605d, 0x605a, 0x6067, 0x6041, 0x6059, 0x6063, 0x60ab, 0x6106, 0x610d, 0x615d, 0x61a9, 0x619d, 0x61cb, 0x61d1, 0x6206, 0x8080, 0x807f, 0x6c93, 0x6cf6, 0x6dfc, 0x77f6, 0x77f8, 0x7800, 0x7809, 0x7817, 0x7818, 0x7811, 0x65ab, 0x782d, 0x781c, 0x781d, 0x7839, 0x783a, 0x783b, 0x781f, 0x783c, 0x7825, 0x782c, 0x7823, 0x7829, 0x784e, 0x786d, 0x7856, 0x7857, 0x7826, 0x7850, 0x7847, 0x784c, 0x786a, 0x789b, 0x7893, 0x789a, 0x7887, 0x789c, 0x78a1, 0x78a3, 0x78b2, 0x78b9, 0x78a5, 0x78d4, 0x78d9, 0x78c9, 0x78ec, 0x78f2, 0x7905, 0x78f4, 0x7913, 0x7924, 0x791e, 0x7934, 0x9f9b, 0x9ef9, 0x9efb, 0x9efc, 0x76f1, 0x7704, 0x770d, 0x76f9, 0x7707, 0x7708, 0x771a, 0x7722, 0x7719, 0x772d, 0x7726, 0x7735, 0x7738, 0x7750, 0x7751, 0x7747, 0x7743, 0x775a, 0x7768, /* 0x6e */ 0x7762, 0x7765, 0x777f, 0x778d, 0x777d, 0x7780, 0x778c, 0x7791, 0x779f, 0x77a0, 0x77b0, 0x77b5, 0x77bd, 0x753a, 0x7540, 0x754e, 0x754b, 0x7548, 0x755b, 0x7572, 0x7579, 0x7583, 0x7f58, 0x7f61, 0x7f5f, 0x8a48, 0x7f68, 0x7f74, 0x7f71, 0x7f79, 0x7f81, 0x7f7e, 0x76cd, 0x76e5, 0x8832, 0x9485, 0x9486, 0x9487, 0x948b, 0x948a, 0x948c, 0x948d, 0x948f, 0x9490, 0x9494, 0x9497, 0x9495, 0x949a, 0x949b, 0x949c, 0x94a3, 0x94a4, 0x94ab, 0x94aa, 0x94ad, 0x94ac, 0x94af, 0x94b0, 0x94b2, 0x94b4, 0x94b6, 0x94b7, 0x94b8, 0x94b9, 0x94ba, 0x94bc, 0x94bd, 0x94bf, 0x94c4, 0x94c8, 0x94c9, 0x94ca, 0x94cb, 0x94cc, 0x94cd, 0x94ce, 0x94d0, 0x94d1, 0x94d2, 0x94d5, 0x94d6, 0x94d7, 0x94d9, 0x94d8, 0x94db, 0x94de, 0x94df, 0x94e0, 0x94e2, 0x94e4, 0x94e5, 0x94e7, 0x94e8, 0x94ea, /* 0x6f */ 0x94e9, 0x94eb, 0x94ee, 0x94ef, 0x94f3, 0x94f4, 0x94f5, 0x94f7, 0x94f9, 0x94fc, 0x94fd, 0x94ff, 0x9503, 0x9502, 0x9506, 0x9507, 0x9509, 0x950a, 0x950d, 0x950e, 0x950f, 0x9512, 0x9513, 0x9514, 0x9515, 0x9516, 0x9518, 0x951b, 0x951d, 0x951e, 0x951f, 0x9522, 0x952a, 0x952b, 0x9529, 0x952c, 0x9531, 0x9532, 0x9534, 0x9536, 0x9537, 0x9538, 0x953c, 0x953e, 0x953f, 0x9542, 0x9535, 0x9544, 0x9545, 0x9546, 0x9549, 0x954c, 0x954e, 0x954f, 0x9552, 0x9553, 0x9554, 0x9556, 0x9557, 0x9558, 0x9559, 0x955b, 0x955e, 0x955f, 0x955d, 0x9561, 0x9562, 0x9564, 0x9565, 0x9566, 0x9567, 0x9568, 0x9569, 0x956a, 0x956b, 0x956c, 0x956f, 0x9571, 0x9572, 0x9573, 0x953a, 0x77e7, 0x77ec, 0x96c9, 0x79d5, 0x79ed, 0x79e3, 0x79eb, 0x7a06, 0x5d47, 0x7a03, 0x7a02, 0x7a1e, 0x7a14, /* 0x70 */ 0x7a39, 0x7a37, 0x7a51, 0x9ecf, 0x99a5, 0x7a70, 0x7688, 0x768e, 0x7693, 0x7699, 0x76a4, 0x74de, 0x74e0, 0x752c, 0x9e20, 0x9e22, 0x9e28, 0x9e29, 0x9e2a, 0x9e2b, 0x9e2c, 0x9e32, 0x9e31, 0x9e36, 0x9e38, 0x9e37, 0x9e39, 0x9e3a, 0x9e3e, 0x9e41, 0x9e42, 0x9e44, 0x9e46, 0x9e47, 0x9e48, 0x9e49, 0x9e4b, 0x9e4c, 0x9e4e, 0x9e51, 0x9e55, 0x9e57, 0x9e5a, 0x9e5b, 0x9e5c, 0x9e5e, 0x9e63, 0x9e66, 0x9e67, 0x9e68, 0x9e69, 0x9e6a, 0x9e6b, 0x9e6c, 0x9e71, 0x9e6d, 0x9e73, 0x7592, 0x7594, 0x7596, 0x75a0, 0x759d, 0x75ac, 0x75a3, 0x75b3, 0x75b4, 0x75b8, 0x75c4, 0x75b1, 0x75b0, 0x75c3, 0x75c2, 0x75d6, 0x75cd, 0x75e3, 0x75e8, 0x75e6, 0x75e4, 0x75eb, 0x75e7, 0x7603, 0x75f1, 0x75fc, 0x75ff, 0x7610, 0x7600, 0x7605, 0x760c, 0x7617, 0x760a, 0x7625, 0x7618, 0x7615, 0x7619, /* 0x71 */ 0x761b, 0x763c, 0x7622, 0x7620, 0x7640, 0x762d, 0x7630, 0x763f, 0x7635, 0x7643, 0x763e, 0x7633, 0x764d, 0x765e, 0x7654, 0x765c, 0x7656, 0x766b, 0x766f, 0x7fca, 0x7ae6, 0x7a78, 0x7a79, 0x7a80, 0x7a86, 0x7a88, 0x7a95, 0x7aa6, 0x7aa0, 0x7aac, 0x7aa8, 0x7aad, 0x7ab3, 0x8864, 0x8869, 0x8872, 0x887d, 0x887f, 0x8882, 0x88a2, 0x88c6, 0x88b7, 0x88bc, 0x88c9, 0x88e2, 0x88ce, 0x88e3, 0x88e5, 0x88f1, 0x891a, 0x88fc, 0x88e8, 0x88fe, 0x88f0, 0x8921, 0x8919, 0x8913, 0x891b, 0x890a, 0x8934, 0x892b, 0x8936, 0x8941, 0x8966, 0x897b, 0x758b, 0x80e5, 0x76b2, 0x76b4, 0x77dc, 0x8012, 0x8014, 0x8016, 0x801c, 0x8020, 0x8022, 0x8025, 0x8026, 0x8027, 0x8029, 0x8028, 0x8031, 0x800b, 0x8035, 0x8043, 0x8046, 0x804d, 0x8052, 0x8069, 0x8071, 0x8983, 0x9878, 0x9880, 0x9883, /* 0x72 */ 0x9889, 0x988c, 0x988d, 0x988f, 0x9894, 0x989a, 0x989b, 0x989e, 0x989f, 0x98a1, 0x98a2, 0x98a5, 0x98a6, 0x864d, 0x8654, 0x866c, 0x866e, 0x867f, 0x867a, 0x867c, 0x867b, 0x86a8, 0x868d, 0x868b, 0x86ac, 0x869d, 0x86a7, 0x86a3, 0x86aa, 0x8693, 0x86a9, 0x86b6, 0x86c4, 0x86b5, 0x86ce, 0x86b0, 0x86ba, 0x86b1, 0x86af, 0x86c9, 0x86cf, 0x86b4, 0x86e9, 0x86f1, 0x86f2, 0x86ed, 0x86f3, 0x86d0, 0x8713, 0x86de, 0x86f4, 0x86df, 0x86d8, 0x86d1, 0x8703, 0x8707, 0x86f8, 0x8708, 0x870a, 0x870d, 0x8709, 0x8723, 0x873b, 0x871e, 0x8725, 0x872e, 0x871a, 0x873e, 0x8748, 0x8734, 0x8731, 0x8729, 0x8737, 0x873f, 0x8782, 0x8722, 0x877d, 0x877e, 0x877b, 0x8760, 0x8770, 0x874c, 0x876e, 0x878b, 0x8753, 0x8763, 0x877c, 0x8764, 0x8759, 0x8765, 0x8793, 0x87af, 0x87a8, 0x87d2, /* 0x73 */ 0x87c6, 0x8788, 0x8785, 0x87ad, 0x8797, 0x8783, 0x87ab, 0x87e5, 0x87ac, 0x87b5, 0x87b3, 0x87cb, 0x87d3, 0x87bd, 0x87d1, 0x87c0, 0x87ca, 0x87db, 0x87ea, 0x87e0, 0x87ee, 0x8816, 0x8813, 0x87fe, 0x880a, 0x881b, 0x8821, 0x8839, 0x883c, 0x7f36, 0x7f42, 0x7f44, 0x7f45, 0x8210, 0x7afa, 0x7afd, 0x7b08, 0x7b03, 0x7b04, 0x7b15, 0x7b0a, 0x7b2b, 0x7b0f, 0x7b47, 0x7b38, 0x7b2a, 0x7b19, 0x7b2e, 0x7b31, 0x7b20, 0x7b25, 0x7b24, 0x7b33, 0x7b3e, 0x7b1e, 0x7b58, 0x7b5a, 0x7b45, 0x7b75, 0x7b4c, 0x7b5d, 0x7b60, 0x7b6e, 0x7b7b, 0x7b62, 0x7b72, 0x7b71, 0x7b90, 0x7ba6, 0x7ba7, 0x7bb8, 0x7bac, 0x7b9d, 0x7ba8, 0x7b85, 0x7baa, 0x7b9c, 0x7ba2, 0x7bab, 0x7bb4, 0x7bd1, 0x7bc1, 0x7bcc, 0x7bdd, 0x7bda, 0x7be5, 0x7be6, 0x7bea, 0x7c0c, 0x7bfe, 0x7bfc, 0x7c0f, 0x7c16, 0x7c0b, /* 0x74 */ 0x7c1f, 0x7c2a, 0x7c26, 0x7c38, 0x7c41, 0x7c40, 0x81fe, 0x8201, 0x8202, 0x8204, 0x81ec, 0x8844, 0x8221, 0x8222, 0x8223, 0x822d, 0x822f, 0x8228, 0x822b, 0x8238, 0x823b, 0x8233, 0x8234, 0x823e, 0x8244, 0x8249, 0x824b, 0x824f, 0x825a, 0x825f, 0x8268, 0x887e, 0x8885, 0x8888, 0x88d8, 0x88df, 0x895e, 0x7f9d, 0x7f9f, 0x7fa7, 0x7faf, 0x7fb0, 0x7fb2, 0x7c7c, 0x6549, 0x7c91, 0x7c9d, 0x7c9c, 0x7c9e, 0x7ca2, 0x7cb2, 0x7cbc, 0x7cbd, 0x7cc1, 0x7cc7, 0x7ccc, 0x7ccd, 0x7cc8, 0x7cc5, 0x7cd7, 0x7ce8, 0x826e, 0x66a8, 0x7fbf, 0x7fce, 0x7fd5, 0x7fe5, 0x7fe1, 0x7fe6, 0x7fe9, 0x7fee, 0x7ff3, 0x7cf8, 0x7d77, 0x7da6, 0x7dae, 0x7e47, 0x7e9b, 0x9eb8, 0x9eb4, 0x8d73, 0x8d84, 0x8d94, 0x8d91, 0x8db1, 0x8d67, 0x8d6d, 0x8c47, 0x8c49, 0x914a, 0x9150, 0x914e, 0x914f, 0x9164, /* 0x75 */ 0x9162, 0x9161, 0x9170, 0x9169, 0x916f, 0x917d, 0x917e, 0x9172, 0x9174, 0x9179, 0x918c, 0x9185, 0x9190, 0x918d, 0x9191, 0x91a2, 0x91a3, 0x91aa, 0x91ad, 0x91ae, 0x91af, 0x91b5, 0x91b4, 0x91ba, 0x8c55, 0x9e7e, 0x8db8, 0x8deb, 0x8e05, 0x8e59, 0x8e69, 0x8db5, 0x8dbf, 0x8dbc, 0x8dba, 0x8dc4, 0x8dd6, 0x8dd7, 0x8dda, 0x8dde, 0x8dce, 0x8dcf, 0x8ddb, 0x8dc6, 0x8dec, 0x8df7, 0x8df8, 0x8de3, 0x8df9, 0x8dfb, 0x8de4, 0x8e09, 0x8dfd, 0x8e14, 0x8e1d, 0x8e1f, 0x8e2c, 0x8e2e, 0x8e23, 0x8e2f, 0x8e3a, 0x8e40, 0x8e39, 0x8e35, 0x8e3d, 0x8e31, 0x8e49, 0x8e41, 0x8e42, 0x8e51, 0x8e52, 0x8e4a, 0x8e70, 0x8e76, 0x8e7c, 0x8e6f, 0x8e74, 0x8e85, 0x8e8f, 0x8e94, 0x8e90, 0x8e9c, 0x8e9e, 0x8c78, 0x8c82, 0x8c8a, 0x8c85, 0x8c98, 0x8c94, 0x659b, 0x89d6, 0x89de, 0x89da, 0x89dc, /* 0x76 */ 0x89e5, 0x89eb, 0x89ef, 0x8a3e, 0x8b26, 0x9753, 0x96e9, 0x96f3, 0x96ef, 0x9706, 0x9701, 0x9708, 0x970f, 0x970e, 0x972a, 0x972d, 0x9730, 0x973e, 0x9f80, 0x9f83, 0x9f85, 0x9f86, 0x9f87, 0x9f88, 0x9f89, 0x9f8a, 0x9f8c, 0x9efe, 0x9f0b, 0x9f0d, 0x96b9, 0x96bc, 0x96bd, 0x96ce, 0x96d2, 0x77bf, 0x96e0, 0x928e, 0x92ae, 0x92c8, 0x933e, 0x936a, 0x93ca, 0x938f, 0x943e, 0x946b, 0x9c7f, 0x9c82, 0x9c85, 0x9c86, 0x9c87, 0x9c88, 0x7a23, 0x9c8b, 0x9c8e, 0x9c90, 0x9c91, 0x9c92, 0x9c94, 0x9c95, 0x9c9a, 0x9c9b, 0x9c9e, 0x9c9f, 0x9ca0, 0x9ca1, 0x9ca2, 0x9ca3, 0x9ca5, 0x9ca6, 0x9ca7, 0x9ca8, 0x9ca9, 0x9cab, 0x9cad, 0x9cae, 0x9cb0, 0x9cb1, 0x9cb2, 0x9cb3, 0x9cb4, 0x9cb5, 0x9cb6, 0x9cb7, 0x9cba, 0x9cbb, 0x9cbc, 0x9cbd, 0x9cc4, 0x9cc5, 0x9cc6, 0x9cc7, 0x9cca, 0x9ccb, /* 0x77 */ 0x9ccc, 0x9ccd, 0x9cce, 0x9ccf, 0x9cd0, 0x9cd3, 0x9cd4, 0x9cd5, 0x9cd7, 0x9cd8, 0x9cd9, 0x9cdc, 0x9cdd, 0x9cdf, 0x9ce2, 0x977c, 0x9785, 0x9791, 0x9792, 0x9794, 0x97af, 0x97ab, 0x97a3, 0x97b2, 0x97b4, 0x9ab1, 0x9ab0, 0x9ab7, 0x9e58, 0x9ab6, 0x9aba, 0x9abc, 0x9ac1, 0x9ac0, 0x9ac5, 0x9ac2, 0x9acb, 0x9acc, 0x9ad1, 0x9b45, 0x9b43, 0x9b47, 0x9b49, 0x9b48, 0x9b4d, 0x9b51, 0x98e8, 0x990d, 0x992e, 0x9955, 0x9954, 0x9adf, 0x9ae1, 0x9ae6, 0x9aef, 0x9aeb, 0x9afb, 0x9aed, 0x9af9, 0x9b08, 0x9b0f, 0x9b13, 0x9b1f, 0x9b23, 0x9ebd, 0x9ebe, 0x7e3b, 0x9e82, 0x9e87, 0x9e88, 0x9e8b, 0x9e92, 0x93d6, 0x9e9d, 0x9e9f, 0x9edb, 0x9edc, 0x9edd, 0x9ee0, 0x9edf, 0x9ee2, 0x9ee9, 0x9ee7, 0x9ee5, 0x9eea, 0x9eef, 0x9f22, 0x9f2c, 0x9f2f, 0x9f39, 0x9f37, 0x9f3d, 0x9f3e, 0x9f44, }; static int gb2312_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c1 = (s[0] & 0x7F); if ((c1 >= 0x21 && c1 <= 0x29) || (c1 >= 0x30 && c1 <= 0x77)) { if (n >= 2) { unsigned char c2 = (s[1] & 0x7F); if (c2 >= 0x21 && c2 < 0x7f) { unsigned int i = 94 * (c1 - 0x21) + (c2 - 0x21); unsigned short wc = 0xfffd; if (i < 1410) { if (i < 831) wc = gb2312_2uni_page21[i]; } else { if (i < 8178) wc = gb2312_2uni_page30[i-1410]; } if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 2; } } return RET_ILSEQ; } return RET_TOOFEW(0); } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned short gb2312_2charset[7445] = { 0x2168, 0x216c, 0x2127, 0x2163, 0x2140, 0x2141, 0x2824, 0x2822, 0x2828, 0x2826, 0x283a, 0x282c, 0x282a, 0x2830, 0x282e, 0x2142, 0x2834, 0x2832, 0x2839, 0x2821, 0x2825, 0x2827, 0x2829, 0x282d, 0x2831, 0x2823, 0x282b, 0x282f, 0x2833, 0x2835, 0x2836, 0x2837, 0x2838, 0x2126, 0x2125, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, 0x2627, 0x2628, 0x2629, 0x262a, 0x262b, 0x262c, 0x262d, 0x262e, 0x262f, 0x2630, 0x2631, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636, 0x2637, 0x2638, 0x2641, 0x2642, 0x2643, 0x2644, 0x2645, 0x2646, 0x2647, 0x2648, 0x2649, 0x264a, 0x264b, 0x264c, 0x264d, 0x264e, 0x264f, 0x2650, 0x2651, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656, 0x2657, 0x2658, 0x2727, 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2728, 0x2729, 0x272a, 0x272b, 0x272c, 0x272d, 0x272e, 0x272f, 0x2730, 0x2731, 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737, 0x2738, 0x2739, 0x273a, 0x273b, 0x273c, 0x273d, 0x273e, 0x273f, 0x2740, 0x2741, 0x2751, 0x2752, 0x2753, 0x2754, 0x2755, 0x2756, 0x2758, 0x2759, 0x275a, 0x275b, 0x275c, 0x275d, 0x275e, 0x275f, 0x2760, 0x2761, 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x2768, 0x2769, 0x276a, 0x276b, 0x276c, 0x276d, 0x276e, 0x276f, 0x2770, 0x2771, 0x2757, 0x212a, 0x212c, 0x212e, 0x212f, 0x2130, 0x2131, 0x212d, 0x216b, 0x2164, 0x2165, 0x2179, 0x2166, 0x216d, 0x2271, 0x2272, 0x2273, 0x2274, 0x2275, 0x2276, 0x2277, 0x2278, 0x2279, 0x227a, 0x227b, 0x227c, 0x217b, 0x217c, 0x217a, 0x217d, 0x214a, 0x2147, 0x2146, 0x214c, 0x2158, 0x215e, 0x214f, 0x214e, 0x2144, 0x2145, 0x2149, 0x2148, 0x2152, 0x2153, 0x2160, 0x215f, 0x2143, 0x214b, 0x2157, 0x2156, 0x2155, 0x2159, 0x2154, 0x215c, 0x215d, 0x215a, 0x215b, 0x2151, 0x214d, 0x2150, 0x2259, 0x225a, 0x225b, 0x225c, 0x225d, 0x225e, 0x225f, 0x2260, 0x2261, 0x2262, 0x2245, 0x2246, 0x2247, 0x2248, 0x2249, 0x224a, 0x224b, 0x224c, 0x224d, 0x224e, 0x224f, 0x2250, 0x2251, 0x2252, 0x2253, 0x2254, 0x2255, 0x2256, 0x2257, 0x2258, 0x2231, 0x2232, 0x2233, 0x2234, 0x2235, 0x2236, 0x2237, 0x2238, 0x2239, 0x223a, 0x223b, 0x223c, 0x223d, 0x223e, 0x223f, 0x2240, 0x2241, 0x2242, 0x2243, 0x2244, 0x2924, 0x2925, 0x2926, 0x2927, 0x2928, 0x2929, 0x292a, 0x292b, 0x292c, 0x292d, 0x292e, 0x292f, 0x2930, 0x2931, 0x2932, 0x2933, 0x2934, 0x2935, 0x2936, 0x2937, 0x2938, 0x2939, 0x293a, 0x293b, 0x293c, 0x293d, 0x293e, 0x293f, 0x2940, 0x2941, 0x2942, 0x2943, 0x2944, 0x2945, 0x2946, 0x2947, 0x2948, 0x2949, 0x294a, 0x294b, 0x294c, 0x294d, 0x294e, 0x294f, 0x2950, 0x2951, 0x2952, 0x2953, 0x2954, 0x2955, 0x2956, 0x2957, 0x2958, 0x2959, 0x295a, 0x295b, 0x295c, 0x295d, 0x295e, 0x295f, 0x2960, 0x2961, 0x2962, 0x2963, 0x2964, 0x2965, 0x2966, 0x2967, 0x2968, 0x2969, 0x296a, 0x296b, 0x296c, 0x296d, 0x296e, 0x296f, 0x2176, 0x2175, 0x2178, 0x2177, 0x2174, 0x2173, 0x2170, 0x2172, 0x2171, 0x216f, 0x216e, 0x2162, 0x2161, 0x2121, 0x2122, 0x2123, 0x2128, 0x2129, 0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213a, 0x213b, 0x213e, 0x213f, 0x217e, 0x2132, 0x2133, 0x213c, 0x213d, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427, 0x2428, 0x2429, 0x242a, 0x242b, 0x242c, 0x242d, 0x242e, 0x242f, 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, 0x2438, 0x2439, 0x243a, 0x243b, 0x243c, 0x243d, 0x243e, 0x243f, 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, 0x2448, 0x2449, 0x244a, 0x244b, 0x244c, 0x244d, 0x244e, 0x244f, 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, 0x2458, 0x2459, 0x245a, 0x245b, 0x245c, 0x245d, 0x245e, 0x245f, 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x246f, 0x2470, 0x2471, 0x2472, 0x2473, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, 0x2528, 0x2529, 0x252a, 0x252b, 0x252c, 0x252d, 0x252e, 0x252f, 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, 0x2538, 0x2539, 0x253a, 0x253b, 0x253c, 0x253d, 0x253e, 0x253f, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d, 0x254e, 0x254f, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e, 0x255f, 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x256d, 0x256e, 0x256f, 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0x2124, 0x2845, 0x2846, 0x2847, 0x2848, 0x2849, 0x284a, 0x284b, 0x284c, 0x284d, 0x284e, 0x284f, 0x2850, 0x2851, 0x2852, 0x2853, 0x2854, 0x2855, 0x2856, 0x2857, 0x2858, 0x2859, 0x285a, 0x285b, 0x285c, 0x285d, 0x285e, 0x285f, 0x2860, 0x2861, 0x2862, 0x2863, 0x2864, 0x2865, 0x2866, 0x2867, 0x2868, 0x2869, 0x2265, 0x2266, 0x2267, 0x2268, 0x2269, 0x226a, 0x226b, 0x226c, 0x226d, 0x226e, 0x523b, 0x3621, 0x465f, 0x4d72, 0x5549, 0x487d, 0x494f, 0x4f42, 0x5822, 0x323b, 0x536b, 0x5824, 0x3373, 0x5728, 0x4752, 0x5827, 0x4a40, 0x4770, 0x317b, 0x5235, 0x3454, 0x362b, 0x4b3f, 0x5829, 0x362a, 0x413d, 0x514f, 0x4925, 0x582d, 0x3876, 0x513e, 0x635c, 0x5650, 0x3761, 0x342e, 0x4159, 0x583c, 0x4d68, 0x3524, 0x4e2a, 0x5677, 0x4076, 0x3e59, 0x582f, 0x444b, 0x3e43, 0x5831, 0x4334, 0x5265, 0x562e, 0x4e5a, 0x5527, 0x3a75, 0x3726, 0x4056, 0x4639, 0x4552, 0x4747, 0x3954, 0x334b, 0x5252, 0x583f, 0x3e45, 0x4672, 0x5232, 0x4f30, 0x4f67, 0x4a69, 0x5840, 0x4272, 0x4252, 0x4869, 0x472c, 0x414b, 0x5368, 0x5579, 0x4a42, 0x367e, 0x5821, 0x535a, 0x3f77, 0x5446, 0x3b25, 0x5841, 0x4e65, 0x3e2e, 0x5828, 0x5147, 0x5029, 0x583d, 0x596f, 0x4d76, 0x3f3a, 0x3d3b, 0x3a25, 0x5260, 0x327a, 0x3a60, 0x4436, 0x4f6d, 0x3e29, 0x4d24, 0x4141, 0x4757, 0x5971, 0x5974, 0x484b, 0x5869, 0x525a, 0x4a32, 0x484a, 0x586c, 0x586a, 0x5846, 0x3d76, 0x464d, 0x3370, 0x586b, 0x3d71, 0x3d69, 0x4854, 0x3453, 0x4258, 0x3256, 0x5750, 0x4a4b, 0x4b7b, 0x554c, 0x3836, 0x4f49, 0x595a, 0x5870, 0x472a, 0x586e, 0x347a, 0x416e, 0x5254, 0x586d, 0x5247, 0x586f, 0x4347, 0x5176, 0x5659, 0x5872, 0x5875, 0x3c7e, 0x3c5b, 0x484e, 0x375d, 0x3742, 0x4673, 0x5878, 0x5241, 0x4e69, 0x3c3f, 0x377c, 0x3725, 0x505d, 0x565a, 0x5345, 0x3b6f, 0x3b61, 0x5871, 0x4921, 0x4e30, 0x342b, 0x5873, 0x494b, 0x5876, 0x4257, 0x5877, 0x4e31, 0x5879, 0x322e, 0x3940, 0x5923, 0x3069, 0x4166, 0x496c, 0x4b45, 0x4b46, 0x5924, 0x3568, 0x352b, 0x4e3b, 0x354d, 0x5721, 0x5774, 0x5353, 0x4c65, 0x3a4e, 0x5922, 0x595c, 0x5360, 0x587d, 0x3770, 0x5777, 0x587e, 0x587a, 0x5921, 0x4463, 0x5336, 0x5874, 0x595d, 0x587b, 0x4565, 0x4050, 0x5170, 0x305b, 0x3c51, 0x5926, 0x5925, 0x592c, 0x592e, 0x592b, 0x4a39, 0x5929, 0x5636, 0x335e, 0x5928, 0x407d, 0x4a4c, 0x592a, 0x5927, 0x5930, 0x3631, 0x3929, 0x5240, 0x4f40, 0x4242, 0x3d44, 0x556c, 0x3260, 0x4748, 0x3f6b, 0x592d, 0x592f, 0x4e6a, 0x3a6e, 0x4756, 0x3163, 0x3459, 0x366d, 0x5934, 0x3f21, 0x595e, 0x474e, 0x407e, 0x5938, 0x4b57, 0x377d, 0x5935, 0x5937, 0x3123, 0x5361, 0x5939, 0x5045, 0x5936, 0x5931, 0x5932, 0x4129, 0x5933, 0x3c73, 0x505e, 0x3829, 0x3e63, 0x593d, 0x593a, 0x3033, 0x5942, 0x5944, 0x3136, 0x593f, 0x3539, 0x3e73, 0x4c48, 0x3a72, 0x5250, 0x5943, 0x3d68, 0x332b, 0x5945, 0x3e6b, 0x5946, 0x593b, 0x445f, 0x593e, 0x5941, 0x5940, 0x552e, 0x5635, 0x4763, 0x5948, 0x3c59, 0x594a, 0x593c, 0x594b, 0x462b, 0x5949, 0x5776, 0x4d23, 0x3d21, 0x594c, 0x453c, 0x4d35, 0x594d, 0x5947, 0x3325, 0x3f7e, 0x3835, 0x407c, 0x3078, 0x3476, 0x594e, 0x594f, 0x3422, 0x5950, 0x345f, 0x3041, 0x5951, 0x4935, 0x4f71, 0x5952, 0x4145, 0x5956, 0x492e, 0x5955, 0x5954, 0x5957, 0x4b5b, 0x3d29, 0x4627, 0x5953, 0x5958, 0x5959, 0x4865, 0x405c, 0x3679, 0x5823, 0x544a, 0x542a, 0x5056, 0x3364, 0x5557, 0x4f48, 0x3962, 0x3f4b, 0x4362, 0x3652, 0x4d43, 0x596e, 0x5970, 0x3533, 0x3635, 0x3e24, 0x486b, 0x482b, 0x304b, 0x392b, 0x4179, 0x5962, 0x403c, 0x3932, 0x3958, 0x504b, 0x3178, 0x4664, 0x3e5f, 0x3564, 0x5748, 0x5178, 0x3c66, 0x4a5e, 0x3c3d, 0x5966, 0x5867, 0x445a, 0x3854, 0x483d, 0x3261, 0x5459, 0x4330, 0x4361, 0x5a22, 0x485f, 0x5034, 0x3e7c, 0x4529, 0x395a, 0x5a23, 0x5429, 0x5a24, 0x597b, 0x362c, 0x376b, 0x3179, 0x597c, 0x3365, 0x3e76, 0x3f76, 0x5231, 0x4064, 0x3633, 0x597e, 0x597d, 0x3e3b, 0x4660, 0x573c, 0x5a21, 0x4139, 0x3572, 0x4168, 0x3c75, 0x3455, 0x415d, 0x447d, 0x3c38, 0x3732, 0x376f, 0x596c, 0x463e, 0x3f2d, 0x3b4b, 0x354a, 0x5b49, 0x5057, 0x4d39, 0x303c, 0x3376, 0x3b77, 0x5b4a, 0x3a2f, 0x5464, 0x3536, 0x3573, 0x5856, 0x4850, 0x3756, 0x4750, 0x5857, 0x3f2f, 0x5b3b, 0x5858, 0x504c, 0x3b2e, 0x6b3e, 0x4150, 0x4175, 0x5472, 0x3855, 0x3434, 0x3375, 0x493e, 0x4550, 0x4559, 0x407b, 0x3170, 0x5859, 0x394e, 0x353d, 0x585a, 0x5646, 0x4b22, 0x482f, 0x4932, 0x344c, 0x3f4c, 0x3974, 0x585b, 0x585c, 0x3667, 0x3c41, 0x4c6a, 0x4f77, 0x585d, 0x4730, 0x3950, 0x3d23, 0x4c5e, 0x464a, 0x5860, 0x585e, 0x585f, 0x307e, 0x3e67, 0x4a23, 0x3c74, 0x3831, 0x386e, 0x5862, 0x3d4b, 0x5864, 0x5863, 0x457c, 0x5865, 0x5866, 0x4126, 0x4830, 0x306c, 0x3926, 0x3c53, 0x4e71, 0x5b3d, 0x4153, 0x362f, 0x567a, 0x452c, 0x3d59, 0x5b3e, 0x5b3f, 0x4078, 0x3e22, 0x404d, 0x5b40, 0x4a46, 0x322a, 0x5342, 0x4363, 0x512b, 0x5b42, 0x4055, 0x5b43, 0x3f31, 0x443c, 0x475a, 0x5b44, 0x5968, 0x4957, 0x3934, 0x4e70, 0x5448, 0x307c, 0x3452, 0x5059, 0x5969, 0x5e4b, 0x596b, 0x5830, 0x3b2f, 0x3131, 0x3357, 0x584e, 0x5451, 0x3d33, 0x3f6f, 0x4f3b, 0x5850, 0x374b, 0x5851, 0x4625, 0x4778, 0x523d, 0x5852, 0x4464, 0x4a2e, 0x4727, 0x5826, 0x497d, 0x4e67, 0x3b5c, 0x306b, 0x3b2a, 0x502d, 0x3130, 0x5764, 0x573f, 0x3525, 0x4274, 0x444f, 0x3229, 0x3237, 0x3165, 0x5f32, 0x553c, 0x3f28, 0x422c, 0x5855, 0x4231, 0x5854, 0x4e54, 0x5a60, 0x4e40, 0x5834, 0x432e, 0x5321, 0x4e23, 0x3c34, 0x4834, 0x4251, 0x3e6d, 0x5036, 0x5a61, 0x4764, 0x3327, 0x3672, 0x4c7c, 0x407a, 0x4077, 0x5139, 0x5161, 0x5847, 0x325e, 0x4065, 0x3a71, 0x5848, 0x542d, 0x4f61, 0x5849, 0x584a, 0x4f43, 0x3378, 0x3e47, 0x584b, 0x5b4c, 0x4825, 0x4f58, 0x487e, 0x324e, 0x5356, 0x3266, 0x3c30, 0x5351, 0x4b2b, 0x3734, 0x3722, 0x4a65, 0x4821, 0x4a5c, 0x3164, 0x5070, 0x4551, 0x5b45, 0x357e, 0x3f5a, 0x3945, 0x3e64, 0x416d, 0x5f36, 0x5f35, 0x563b, 0x3d50, 0x5559, 0x3048, 0x3623, 0x3f49, 0x4c28, 0x5f33, 0x4a37, 0x5352, 0x584f, 0x5236, 0x3a45, 0x4b3e, 0x4c3e, 0x5f37, 0x3570, 0x5f34, 0x5375, 0x3354, 0x3877, 0x5f3a, 0x3a4f, 0x3c2a, 0x3575, 0x4d2c, 0x437b, 0x3a73, 0x4074, 0x4d42, 0x4f72, 0x5f38, 0x4f45, 0x4240, 0x5f39, 0x4270, 0x3e7d, 0x415f, 0x4d4c, 0x5277, 0x374d, 0x5f41, 0x5f44, 0x3771, 0x3049, 0x3656, 0x3754, 0x3a2c, 0x4c7d, 0x3f54, 0x4b31, 0x4674, 0x5628, 0x5f45, 0x4e62, 0x3333, 0x4e7c, 0x3435, 0x4e47, 0x3a70, 0x4e61, 0x513d, 0x5f40, 0x3474, 0x334a, 0x3866, 0x5f3b, 0x4445, 0x5f3c, 0x5f3d, 0x5f3e, 0x453b, 0x5f3f, 0x5f42, 0x5431, 0x5f43, 0x473a, 0x4e58, 0x4458, 0x5f4a, 0x5f4f, 0x565c, 0x5f49, 0x5f5a, 0x4e36, 0x3a47, 0x5f4e, 0x5f48, 0x455e, 0x496b, 0x3a74, 0x437c, 0x3e57, 0x5f46, 0x5f4d, 0x4558, 0x5526, 0x3a4d, 0x3e4c, 0x533d, 0x3840, 0x5664, 0x5f47, 0x393e, 0x3f27, 0x417c, 0x5f4b, 0x5f4c, 0x5f50, 0x5f5b, 0x5f65, 0x5f57, 0x5f56, 0x5749, 0x5f63, 0x5f64, 0x656b, 0x5227, 0x5f52, 0x3f29, 0x545b, 0x3f48, 0x5f54, 0x4f4c, 0x5f5d, 0x514a, 0x5f5e, 0x3027, 0x4637, 0x5f53, 0x3a65, 0x365f, 0x4d5b, 0x397e, 0x5455, 0x5f5f, 0x4f6c, 0x3025, 0x5f67, 0x5f51, 0x5146, 0x5f55, 0x5f58, 0x5f59, 0x5f5c, 0x3b29, 0x5f60, 0x5f61, 0x5f62, 0x5f66, 0x5f68, 0x5334, 0x3867, 0x4536, 0x5f6a, 0x495a, 0x4128, 0x4444, 0x3f5e, 0x4f78, 0x555c, 0x5f6e, 0x3238, 0x3a5f, 0x5f6c, 0x5b41, 0x5164, 0x4b74, 0x343d, 0x3026, 0x5f71, 0x4c46, 0x5f72, 0x5f6d, 0x5f69, 0x5f6b, 0x5f6f, 0x5f70, 0x3b3d, 0x5f73, 0x5f74, 0x3b23, 0x4a5b, 0x4e28, 0x6027, 0x332a, 0x6026, 0x6021, 0x5f7e, 0x4d59, 0x5f7c, 0x5f7a, 0x3f50, 0x5744, 0x494c, 0x5f78, 0x3021, 0x5f7d, 0x5f7b, 0x6022, 0x6028, 0x3748, 0x4621, 0x4936, 0x4032, 0x5f75, 0x453e, 0x5844, 0x5f79, 0x4476, 0x6023, 0x6024, 0x6025, 0x5025, 0x6034, 0x4c64, 0x6031, 0x3f26, 0x602f, 0x4e39, 0x602b, 0x4946, 0x402e, 0x602e, 0x3a6d, 0x3a30, 0x6029, 0x5f76, 0x6033, 0x6038, 0x342d, 0x6039, 0x4f32, 0x3a48, 0x6030, 0x507a, 0x602c, 0x547b, 0x5f77, 0x4567, 0x602d, 0x5377, 0x6036, 0x6037, 0x6044, 0x5061, 0x603c, 0x6049, 0x604a, 0x603e, 0x602a, 0x4924, 0x6041, 0x6032, 0x4a48, 0x6043, 0x6035, 0x4e4b, 0x4b43, 0x604d, 0x6046, 0x6042, 0x604b, 0x603a, 0x603f, 0x6040, 0x6045, 0x6047, 0x6048, 0x604c, 0x603b, 0x4b54, 0x6055, 0x6056, 0x6052, 0x6050, 0x3c4e, 0x6051, 0x3842, 0x5845, 0x506a, 0x426f, 0x604f, 0x603d, 0x6054, 0x6053, 0x6057, 0x605c, 0x6058, 0x5676, 0x3330, 0x576c, 0x4b3b, 0x605a, 0x4e7b, 0x3a59, 0x6061, 0x605d, 0x522d, 0x6062, 0x605b, 0x6059, 0x605f, 0x6060, 0x605e, 0x6064, 0x4677, 0x582c, 0x546b, 0x6066, 0x4a49, 0x6065, 0x3841, 0x6067, 0x6068, 0x6069, 0x6063, 0x3a3f, 0x4c67, 0x606a, 0x4f79, 0x606b, 0x4842, 0x3d40, 0x4452, 0x606c, 0x606d, 0x4774, 0x4b44, 0x606e, 0x3b58, 0x5836, 0x5272, 0x606f, 0x4d45, 0x365a, 0x6071, 0x5430, 0x4027, 0x3451, 0x4e27, 0x6070, 0x6072, 0x394c, 0x397a, 0x4d3c, 0x6073, 0x4654, 0x6074, 0x5432, 0x4826, 0x6076, 0x6075, 0x6077, 0x4d41, 0x4a25, 0x545a, 0x5b57, 0x5b59, 0x5b58, 0x3967, 0x5b5c, 0x5b5d, 0x3558, 0x5b5a, 0x5b5b, 0x3321, 0x5b5f, 0x3b78, 0x5637, 0x5b60, 0x3e79, 0x373b, 0x5b50, 0x4c2e, 0x3f32, 0x3b35, 0x5778, 0x3f53, 0x3f69, 0x3c61, 0x4c33, 0x5b5e, 0x3053, 0x4e6b, 0x3758, 0x5739, 0x4642, 0x4024, 0x4c39, 0x5b67, 0x5b61, 0x463a, 0x5b63, 0x5b68, 0x4577, 0x5b6a, 0x5b69, 0x3f40, 0x5b66, 0x5b65, 0x3439, 0x402c, 0x4222, 0x5b62, 0x5b64, 0x504d, 0x5b6d, 0x405d, 0x5b72, 0x3662, 0x5b73, 0x5b52, 0x3938, 0x542b, 0x5b6c, 0x3f51, 0x5b70, 0x5b51, 0x3566, 0x5b6b, 0x3f65, 0x5b6e, 0x5b71, 0x5b79, 0x3921, 0x3023, 0x4271, 0x3347, 0x5b6f, 0x5b78, 0x4652, 0x5b74, 0x5b75, 0x5b77, 0x5b76, 0x5b7e, 0x5372, 0x323a, 0x5b7d, 0x5c24, 0x5b7b, 0x5b7a, 0x5b7c, 0x4560, 0x3b79, 0x5c23, 0x5c25, 0x4c43, 0x3651, 0x5d40, 0x5c21, 0x5c22, 0x4735, 0x3669, 0x5c27, 0x5c26, 0x5c29, 0x3124, 0x354c, 0x3f30, 0x515f, 0x3642, 0x5c28, 0x4b7a, 0x6b73, 0x4b5c, 0x4b7e, 0x4c41, 0x487b, 0x5c2a, 0x4c6e, 0x5c2b, 0x5b53, 0x5c2f, 0x5c2c, 0x3e33, 0x4a7b, 0x5c2d, 0x494a, 0x4439, 0x473d, 0x5c2e, 0x5476, 0x5066, 0x442b, 0x3655, 0x5b54, 0x315a, 0x5b55, 0x5b56, 0x3a3e, 0x4840, 0x4a3f, 0x4849, 0x5733, 0x4979, 0x3f47, 0x3a78, 0x523c, 0x623a, 0x3426, 0x3138, 0x3834, 0x4f44, 0x5967, 0x4f26, 0x4d62, 0x596d, 0x3660, 0x5239, 0x393b, 0x6239, 0x6237, 0x3473, 0x4c6c, 0x4c2b, 0x3772, 0x5832, 0x516b, 0x3a3b, 0x4a27, 0x4d37, 0x5244, 0x3f64, 0x3c50, 0x3661, 0x5e45, 0x5e46, 0x5b3c, 0x5159, 0x4666, 0x444e, 0x376e, 0x375c, 0x3f7c, 0x5760, 0x4675, 0x313c, 0x5e48, 0x3d31, 0x4c57, 0x5e4a, 0x5e49, 0x356c, 0x495d, 0x3042, 0x452e, 0x452b, 0x444c, 0x3c69, 0x4b7d, 0x3a43, 0x6579, 0x4867, 0x657a, 0x4d7d, 0x5731, 0x383e, 0x4268, 0x4851, 0x657b, 0x364a, 0x3c4b, 0x517d, 0x6621, 0x436e, 0x6624, 0x657e, 0x6625, 0x4d57, 0x3741, 0x657c, 0x657d, 0x6623, 0x445d, 0x6628, 0x6627, 0x4343, 0x465e, 0x662a, 0x4437, 0x6622, 0x4a3c, 0x3d63, 0x3943, 0x6626, 0x5055, 0x4e2f, 0x6629, 0x6630, 0x5226, 0x3d2a, 0x662d, 0x662f, 0x4051, 0x524c, 0x3c27, 0x6631, 0x5276, 0x574b, 0x4d7e, 0x4d5e, 0x4226, 0x662b, 0x662c, 0x3d3f, 0x662e, 0x6633, 0x6632, 0x6636, 0x6638, 0x446f, 0x4448, 0x3e6a, 0x496f, 0x6637, 0x3670, 0x4364, 0x5369, 0x6634, 0x6635, 0x4822, 0x663d, 0x6639, 0x4645, 0x4d71, 0x663b, 0x663c, 0x3b69, 0x663e, 0x663a, 0x4037, 0x5324, 0x663f, 0x4974, 0x6643, 0x6644, 0x5076, 0x433d, 0x4344, 0x6642, 0x6641, 0x6647, 0x4f31, 0x6b74, 0x664a, 0x6645, 0x3c5e, 0x4929, 0x3c35, 0x4f53, 0x6648, 0x6649, 0x664e, 0x6650, 0x6651, 0x664b, 0x3555, 0x664c, 0x664f, 0x445b, 0x6646, 0x664d, 0x6652, 0x6654, 0x6653, 0x6655, 0x5978, 0x6656, 0x6657, 0x5753, 0x665d, 0x665e, 0x3f57, 0x5450, 0x5756, 0x3466, 0x4b6f, 0x665a, 0x5843, 0x574e, 0x5022, 0x434f, 0x665f, 0x3c3e, 0x3942, 0x665b, 0x5127, 0x3a22, 0x424f, 0x582b, 0x4a6b, 0x656e, 0x665c, 0x3775, 0x4866, 0x4475, 0x6532, 0x447e, 0x4b7c, 0x6533, 0x552c, 0x536e, 0x4a58, 0x3032, 0x4b4e, 0x4d6a, 0x3a6a, 0x6535, 0x6534, 0x575a, 0x3959, 0x5666, 0x3628, 0x4d70, 0x524b, 0x3126, 0x4a35, 0x3368, 0x4973, 0x3f4d, 0x507b, 0x4a52, 0x6536, 0x3b42, 0x4f5c, 0x392c, 0x5457, 0x3a26, 0x5167, 0x4f7c, 0x3c52, 0x6537, 0x485d, 0x3f6d, 0x3176, 0x4b5e, 0x3c45, 0x3c44, 0x527a, 0x435c, 0x3f5c, 0x383b, 0x4342, 0x3a2e, 0x5422, 0x475e, 0x442f, 0x326c, 0x3951, 0x653b, 0x4148, 0x552f, 0x653c, 0x653e, 0x3467, 0x3654, 0x4b42, 0x5130, 0x353c, 0x4a59, 0x3762, 0x4964, 0x3d2b, 0x4e3e, 0x5770, 0x5021, 0x4959, 0x367b, 0x6658, 0x3c62, 0x333e, 0x4950, 0x6659, 0x3322, 0x5e4c, 0x5348, 0x5e4d, 0x5222, 0x5e4e, 0x3e4d, 0x5e4f, 0x4a2c, 0x527c, 0x335f, 0x656a, 0x4461, 0x3e21, 0x4e32, 0x4472, 0x3e56, 0x4628, 0x3263, 0x3e53, 0x477c, 0x4c6b, 0x3d6c, 0x4e5d, 0x4a3a, 0x4641, 0x656c, 0x503c, 0x5539, 0x656d, 0x4a74, 0x4d40, 0x4245, 0x656f, 0x4244, 0x6570, 0x6578, 0x4d4d, 0x493d, 0x5259, 0x6128, 0x536c, 0x4b6a, 0x4671, 0x612c, 0x6127, 0x6129, 0x612a, 0x612f, 0x326d, 0x612b, 0x385a, 0x612d, 0x612e, 0x6130, 0x353a, 0x6131, 0x6133, 0x6138, 0x5152, 0x6136, 0x6135, 0x416b, 0x6137, 0x5440, 0x6132, 0x613a, 0x3036, 0x6134, 0x3f79, 0x6139, 0x613b, 0x613e, 0x613c, 0x5645, 0x4f3f, 0x613d, 0x613f, 0x424d, 0x366b, 0x5378, 0x474d, 0x3765, 0x3e7e, 0x6140, 0x6141, 0x6147, 0x3367, 0x4669, 0x345e, 0x5142, 0x6148, 0x6146, 0x6145, 0x6143, 0x6142, 0x3140, 0x5538, 0x6144, 0x614b, 0x614c, 0x614a, 0x6f7a, 0x6153, 0x6152, 0x4736, 0x6149, 0x614e, 0x6150, 0x6154, 0x6151, 0x614d, 0x614f, 0x6155, 0x6156, 0x6157, 0x6158, 0x615a, 0x615b, 0x4e21, 0x675d, 0x3428, 0x565d, 0x5132, 0x3332, 0x3924, 0x5773, 0x4749, 0x3e5e, 0x392e, 0x4e57, 0x326e, 0x5b4f, 0x3c3a, 0x5251, 0x4b48, 0x304d, 0x4f6f, 0x5963, 0x3d6d, 0x3152, 0x4a50, 0x323c, 0x4b27, 0x372b, 0x4a26, 0x4f23, 0x6078, 0x554a, 0x607b, 0x607a, 0x4541, 0x4c7b, 0x4131, 0x6079, 0x5663, 0x322f, 0x5644, 0x355b, 0x3478, 0x5621, 0x4f2f, 0x306f, 0x607c, 0x6121, 0x3323, 0x607d, 0x607e, 0x4331, 0x435d, 0x6122, 0x3779, 0x3b4f, 0x6123, 0x443b, 0x6124, 0x6125, 0x6126, 0x3431, 0x3849, 0x463d, 0x446a, 0x3222, 0x5052, 0x675b, 0x3b43, 0x5357, 0x5344, 0x3963, 0x624f, 0x572f, 0x476c, 0x3153, 0x3432, 0x6251, 0x5072, 0x422e, 0x6250, 0x3f62, 0x5326, 0x3557, 0x6252, 0x356a, 0x436d, 0x387d, 0x382e, 0x4553, 0x374f, 0x6254, 0x6253, 0x3648, 0x5779, 0x4d25, 0x6258, 0x6256, 0x4a7c, 0x3f35, 0x5339, 0x6255, 0x6257, 0x412e, 0x4048, 0x625b, 0x625a, 0x402a, 0x414e, 0x625c, 0x625d, 0x625e, 0x5b48, 0x5153, 0x4d22, 0x3d28, 0x5e43, 0x5825, 0x3f2a, 0x5b4d, 0x526c, 0x467a, 0x452a, 0x5e44, 0x3157, 0x5f2e, 0x4a3d, 0x5f31, 0x392d, 0x527d, 0x3825, 0x3a6b, 0x335a, 0x355c, 0x5545, 0x4356, 0x4f52, 0x3b21, 0x6573, 0x6572, 0x6574, 0x4d64, 0x4875, 0x352f, 0x473f, 0x6576, 0x6c30, 0x6566, 0x3969, 0x3531, 0x423c, 0x6568, 0x6567, 0x6569, 0x524d, 0x616a, 0x504e, 0x4d2e, 0x5165, 0x324a, 0x316b, 0x3172, 0x456d, 0x5543, 0x5330, 0x615c, 0x615d, 0x525b, 0x3339, 0x314b, 0x4d79, 0x5577, 0x615e, 0x3e36, 0x347d, 0x615f, 0x3a5c, 0x6160, 0x3b32, 0x4249, 0x6161, 0x506c, 0x4d3d, 0x6162, 0x3543, 0x4547, 0x6163, 0x6164, 0x5379, 0x6165, 0x512d, 0x6166, 0x4e22, 0x6167, 0x3542, 0x6168, 0x3b55, 0x5044, 0x6260, 0x3158, 0x5264, 0x6261, 0x3c49, 0x484c, 0x6263, 0x6c7e, 0x6c7d, 0x5f2f, 0x6262, 0x563e, 0x4d7c, 0x4326, 0x6343, 0x5652, 0x6267, 0x6268, 0x5347, 0x626c, 0x3f6c, 0x626d, 0x6265, 0x3340, 0x446e, 0x626e, 0x5043, 0x3a76, 0x6269, 0x375e, 0x3b33, 0x4c2c, 0x4b4b, 0x6264, 0x6266, 0x626a, 0x626b, 0x6277, 0x6274, 0x5475, 0x6273, 0x452d, 0x557a, 0x4542, 0x3240, 0x626f, 0x6272, 0x412f, 0x4b3c, 0x3521, 0x6279, 0x3c31, 0x6271, 0x5054, 0x5439, 0x6275, 0x3956, 0x6276, 0x4753, 0x6270, 0x575c, 0x6d21, 0x6278, 0x6d25, 0x627e, 0x4a51, 0x4135, 0x3b50, 0x3f56, 0x3a63, 0x4b21, 0x6d26, 0x6d23, 0x6d22, 0x3b56, 0x6d27, 0x5074, 0x6d24, 0x3a5e, 0x3677, 0x6321, 0x3632, 0x4c71, 0x3927, 0x4f22, 0x4721, 0x3f52, 0x3671, 0x627a, 0x627b, 0x627d, 0x627c, 0x4455, 0x6322, 0x5341, 0x6327, 0x4744, 0x4f24, 0x6329, 0x3a37, 0x6328, 0x3b5a, 0x6323, 0x6324, 0x632a, 0x6326, 0x4e72, 0x5346, 0x3b3c, 0x5443, 0x447a, 0x6d28, 0x507c, 0x6325, 0x4375, 0x632d, 0x312f, 0x6332, 0x3c42, 0x632c, 0x353f, 0x4769, 0x6330, 0x3e2a, 0x4d6f, 0x3b73, 0x4c68, 0x632f, 0x6331, 0x4f27, 0x632e, 0x4e29, 0x3b5d, 0x356b, 0x3e65, 0x3252, 0x334d, 0x3139, 0x632b, 0x3251, 0x352c, 0x395f, 0x3668, 0x4f6b, 0x6337, 0x3b4c, 0x4847, 0x504a, 0x6338, 0x336e, 0x6d29, 0x537a, 0x5364, 0x6d2a, 0x6339, 0x5262, 0x6335, 0x535e, 0x3850, 0x6333, 0x6336, 0x375f, 0x6334, 0x4022, 0x633a, 0x5438, 0x3448, 0x633b, 0x3b45, 0x4977, 0x4965, 0x443d, 0x6d2b, 0x427d, 0x3b5b, 0x3f2e, 0x4e3f, 0x633c, 0x3f36, 0x316f, 0x5477, 0x633e, 0x6d2d, 0x633f, 0x3a29, 0x6d2c, 0x633d, 0x6340, 0x3a36, 0x362e, 0x5038, 0x3043, 0x6d2e, 0x6d2f, 0x4041, 0x6341, 0x4533, 0x6342, 0x5c32, 0x6d30, 0x386a, 0x4e6c, 0x6a27, 0x5067, 0x4a79, 0x4856, 0x4f37, 0x3349, 0x4e52, 0x3d64, 0x635e, 0x3b72, 0x6a28, 0x553d, 0x465d, 0x6a29, 0x6a2a, 0x6a2c, 0x6a2b, 0x6a2e, 0x6a2d, 0x3d58, 0x6a2f, 0x423e, 0x3441, 0x3477, 0x3b27, 0x6c66, 0x6c65, 0x373f, 0x4b79, 0x3162, 0x6c67, 0x4948, 0x6c68, 0x6c69, 0x4a56, 0x5e50, 0x3245, 0x547a, 0x464b, 0x3047, 0x3472, 0x4853, 0x4d50, 0x3f38, 0x3f5b, 0x4724, 0x5634, 0x4029, 0x5e51, 0x4928, 0x516f, 0x4524, 0x3067, 0x3336, 0x4845, 0x3062, 0x3776, 0x457a, 0x3673, 0x5552, 0x3350, 0x3c3c, 0x332d, 0x3e71, 0x3051, 0x5256, 0x4a63, 0x5725, 0x4d36, 0x3636, 0x3f39, 0x555b, 0x3827, 0x4557, 0x5e52, 0x3f59, 0x4255, 0x4740, 0x3b24, 0x3128, 0x456a, 0x457b, 0x4c27, 0x3127, 0x3556, 0x4428, 0x5e53, 0x513a, 0x3369, 0x4372, 0x3777, 0x5674, 0x3523, 0x3270, 0x4434, 0x4469, 0x402d, 0x5e54, 0x3068, 0x4544, 0x4160, 0x3955, 0x3e5c, 0x4d58, 0x304e, 0x4d4f, 0x5e56, 0x3e50, 0x573e, 0x5e55, 0x5550, 0x305d, 0x4462, 0x4223, 0x3c70, 0x5335, 0x4039, 0x4521, 0x3226, 0x5471, 0x4028, 0x4a43, 0x5e57, 0x557c, 0x3930, 0x482d, 0x4b29, 0x5e59, 0x3f3d, 0x4634, 0x5727, 0x4a30, 0x4443, 0x3356, 0x3952, 0x5638, 0x6a7c, 0x3034, 0x3f66, 0x4c74, 0x4d5a, 0x563f, 0x424e, 0x4e4e, 0x4c22, 0x502e, 0x4453, 0x3532, 0x5e58, 0x5575, 0x3c37, 0x3b53, 0x3024, 0x4532, 0x346c, 0x5571, 0x6a7d, 0x5e5a, 0x4d26, 0x4d6c, 0x4e66, 0x5e5c, 0x4d31, 0x4026, 0x573d, 0x5e5b, 0x3046, 0x3a34, 0x4953, 0x4473, 0x3e68, 0x3236, 0x404c, 0x4b70, 0x3c71, 0x3b3b, 0x3537, 0x4575, 0x5e66, 0x5e63, 0x3e5d, 0x5e5f, 0x3437, 0x3d5d, 0x5e60, 0x446d, 0x4f46, 0x3560, 0x365e, 0x4a5a, 0x3574, 0x5e65, 0x5546, 0x5e61, 0x4c4d, 0x467e, 0x4545, 0x5234, 0x3e72, 0x4253, 0x4c3d, 0x3338, 0x3d53, 0x3f58, 0x4d46, 0x515a, 0x346b, 0x5e64, 0x5e5d, 0x5e67, 0x6a7e, 0x4230, 0x5e62, 0x5640, 0x3527, 0x3274, 0x5e68, 0x5e72, 0x5e6d, 0x5e71, 0x4860, 0x5761, 0x5e6f, 0x4368, 0x4c61, 0x3265, 0x523e, 0x5e6e, 0x5e6b, 0x4e55, 0x3427, 0x3f2b, 0x3e3e, 0x3d52, 0x5e69, 0x542e, 0x5e5e, 0x5e6a, 0x403f, 0x5e6c, 0x3273, 0x3869, 0x4227, 0x3d41, 0x5e75, 0x5e78, 0x322b, 0x3424, 0x346a, 0x4926, 0x5e76, 0x4b51, 0x3863, 0x5e77, 0x5e7a, 0x5e79, 0x4c42, 0x3061, 0x346e, 0x653a, 0x502f, 0x326b, 0x6b21, 0x5e74, 0x4963, 0x5e73, 0x305a, 0x5221, 0x3177, 0x4c2f, 0x5e70, 0x4b24, 0x552a, 0x5e7b, 0x345d, 0x4426, 0x5e7d, 0x437e, 0x4421, 0x5f21, 0x414c, 0x5e7c, 0x3e6f, 0x4632, 0x3345, 0x4876, 0x4b3a, 0x5e7e, 0x5f24, 0x5732, 0x3337, 0x4143, 0x474b, 0x3225, 0x3469, 0x572b, 0x446c, 0x5f22, 0x5f23, 0x5f25, 0x3a33, 0x5f26, 0x405e, 0x4943, 0x3259, 0x4766, 0x5f27, 0x475c, 0x5f28, 0x6b22, 0x4b53, 0x5f2a, 0x5f29, 0x3241, 0x454a, 0x5f2b, 0x545c, 0x4841, 0x5f2c, 0x3e70, 0x5f2d, 0x5627, 0x6a37, 0x6b36, 0x4a55, 0x587c, 0x3844, 0x3925, 0x3745, 0x557e, 0x394a, 0x5027, 0x744d, 0x3550, 0x4374, 0x3e48, 0x6b37, 0x303d, 0x3d4c, 0x4132, 0x3156, 0x3328, 0x3852, 0x4922, 0x3658, 0x6b38, 0x3e34, 0x4a7d, 0x4743, 0x557b, 0x3773, 0x4e44, 0x552b, 0x3173, 0x6c33, 0x305f, 0x6c35, 0x3637, 0x414f, 0x757a, 0x5031, 0x5565, 0x4e53, 0x3d6f, 0x3362, 0x382b, 0x5536, 0x6d3d, 0x364f, 0x4b39, 0x5042, 0x373d, 0x6c36, 0x4a29, 0x4554, 0x6c39, 0x6c38, 0x4243, 0x6c37, 0x507d, 0x6c3a, 0x6c3b, 0x5765, 0x6c3c, 0x6c3d, 0x466c, 0x4e5e, 0x3c48, 0x4855, 0x3529, 0x3e49, 0x563c, 0x5467, 0x512e, 0x5071, 0x6a38, 0x6a39, 0x6a3a, 0x3a35, 0x4a31, 0x3f75, 0x4d7a, 0x6a40, 0x303a, 0x6a3e, 0x4025, 0x6a3b, 0x327d, 0x4377, 0x3b68, 0x5257, 0x4e74, 0x6a3f, 0x6a3c, 0x6a43, 0x5047, 0x5333, 0x343a, 0x4341, 0x5772, 0x5551, 0x4a47, 0x6a45, 0x6a44, 0x6a47, 0x6a46, 0x5667, 0x4f54, 0x6a4b, 0x3b4e, 0x3d7a, 0x494e, 0x6a4c, 0x4939, 0x4f7e, 0x6a4a, 0x544e, 0x6a4d, 0x6a4f, 0x4d6d, 0x6a49, 0x6a4e, 0x4e6e, 0x3b5e, 0x333f, 0x4655, 0x3e30, 0x4e7a, 0x4767, 0x3e27, 0x6a50, 0x5647, 0x4140, 0x545d, 0x6a51, 0x4f3e, 0x6a52, 0x4a6e, 0x452f, 0x3035, 0x6a54, 0x6a53, 0x745f, 0x443a, 0x3129, 0x655f, 0x6a55, 0x4a6f, 0x6a56, 0x6a57, 0x4658, 0x6a58, 0x6a59, 0x543b, 0x477a, 0x5237, 0x387c, 0x6a42, 0x325c, 0x427c, 0x5478, 0x4c66, 0x576e, 0x5442, 0x5350, 0x6b43, 0x4573, 0x377e, 0x6b54, 0x4b37, 0x6b5e, 0x404a, 0x4d7b, 0x332f, 0x465a, 0x6b7c, 0x443e, 0x4e34, 0x4429, 0x313e, 0x547d, 0x4a75, 0x566c, 0x4653, 0x3664, 0x3b7a, 0x5060, 0x4931, 0x5453, 0x4828, 0x384b, 0x683e, 0x493c, 0x683b, 0x406e, 0x5053, 0x3244, 0x3465, 0x683c, 0x5548, 0x3645, 0x683d, 0x4a78, 0x385c, 0x4c75, 0x4034, 0x516e, 0x683f, 0x6842, 0x3a3c, 0x312d, 0x3d5c, 0x6a3d, 0x6843, 0x6846, 0x684b, 0x684c, 0x4b49, 0x3065, 0x3c2b, 0x3939, 0x6841, 0x4d77, 0x684a, 0x4e76, 0x556d, 0x4156, 0x6844, 0x4336, 0x397b, 0x5626, 0x6848, 0x4a60, 0x5466, 0x6840, 0x6845, 0x6847, 0x4739, 0x3763, 0x6849, 0x3f5d, 0x6852, 0x6857, 0x6855, 0x3c5c, 0x3c4f, 0x685b, 0x685e, 0x685a, 0x317a, 0x3058, 0x4433, 0x384c, 0x4662, 0x483e, 0x4861, 0x684f, 0x6854, 0x6856, 0x3971, 0x6858, 0x5775, 0x447b, 0x685c, 0x3269, 0x6851, 0x3c6d, 0x3f42, 0x684d, 0x5679, 0x4178, 0x3271, 0x685f, 0x4a41, 0x6859, 0x5524, 0x316a, 0x553b, 0x684e, 0x6850, 0x3630, 0x6853, 0x685d, 0x4038, 0x4a77, 0x4b28, 0x465c, 0x4075, 0x6869, 0x5023, 0x6872, 0x566a, 0x6860, 0x6861, 0x5179, 0x3a4b, 0x3879, 0x3871, 0x5454, 0x686f, 0x686e, 0x686c, 0x3970, 0x4c52, 0x6866, 0x4e26, 0x3f72, 0x3038, 0x6871, 0x6870, 0x5740, 0x6864, 0x4d29, 0x4923, 0x3b38, 0x3d5b, 0x686a, 0x6862, 0x6863, 0x6865, 0x3535, 0x6867, 0x4745, 0x686b, 0x686d, 0x3d30, 0x572e, 0x6878, 0x6875, 0x4d30, 0x6876, 0x413a, 0x6868, 0x4337, 0x3070, 0x6874, 0x6877, 0x3923, 0x4952, 0x434e, 0x4e60, 0x4066, 0x4b73, 0x4c5d, 0x5035, 0x4a61, 0x6873, 0x3c6c, 0x6879, 0x435e, 0x4665, 0x3977, 0x3074, 0x5758, 0x3c2c, 0x456f, 0x4c44, 0x6926, 0x492d, 0x6922, 0x4062, 0x3f43, 0x687e, 0x3957, 0x687b, 0x6924, 0x524e, 0x6923, 0x5632, 0x5735, 0x6927, 0x3d37, 0x687c, 0x687d, 0x6921, 0x4d56, 0x522c, 0x6932, 0x6929, 0x342a, 0x343b, 0x692b, 0x5028, 0x6925, 0x337e, 0x692c, 0x4063, 0x692a, 0x6939, 0x6938, 0x692e, 0x687a, 0x6928, 0x3f2c, 0x6931, 0x693a, 0x4225, 0x692f, 0x3845, 0x692d, 0x535c, 0x6934, 0x6935, 0x6937, 0x6947, 0x4046, 0x6945, 0x6930, 0x693b, 0x3071, 0x693c, 0x5525, 0x693e, 0x693f, 0x6941, 0x4171, 0x4836, 0x693d, 0x6942, 0x6943, 0x6933, 0x6936, 0x3b31, 0x6940, 0x3c77, 0x6944, 0x6946, 0x694a, 0x694e, 0x325b, 0x6948, 0x372e, 0x694b, 0x694c, 0x5541, 0x4423, 0x6958, 0x3a61, 0x6949, 0x5323, 0x6954, 0x6957, 0x6950, 0x694f, 0x4741, 0x6952, 0x6959, 0x3348, 0x6953, 0x4f70, 0x694d, 0x3377, 0x6956, 0x695a, 0x4c34, 0x4f2d, 0x6955, 0x695c, 0x695b, 0x695e, 0x6951, 0x695d, 0x695f, 0x434a, 0x4737, 0x344e, 0x3b36, 0x5040, 0x6c23, 0x4537, 0x537b, 0x6c24, 0x6c25, 0x465b, 0x3f6e, 0x6c26, 0x6c27, 0x502a, 0x4738, 0x3868, 0x6c28, 0x5639, 0x557d, 0x344b, 0x323d, 0x4e64, 0x4667, 0x4d61, 0x3475, 0x4b40, 0x3c5f, 0x6962, 0x6963, 0x516a, 0x6965, 0x3479, 0x6964, 0x5133, 0x4a62, 0x3250, 0x6968, 0x6966, 0x6967, 0x5633, 0x6969, 0x696a, 0x696b, 0x696c, 0x6c2f, 0x4539, 0x364e, 0x5273, 0x356e, 0x3b59, 0x6c31, 0x5263, 0x4e63, 0x4438, 0x433f, 0x363e, 0x5839, 0x3148, 0x314f, 0x3151, 0x457e, 0x3150, 0x432b, 0x5531, 0x6b24, 0x3a41, 0x4c3a, 0x6b25, 0x6b27, 0x6b28, 0x6b26, 0x6b29, 0x6b2b, 0x6b2a, 0x6b2c, 0x4a4f, 0x5835, 0x4371, 0x4325, 0x4678, 0x6b2d, 0x444a, 0x6b2e, 0x6b2f, 0x6b30, 0x3755, 0x377a, 0x6b31, 0x4762, 0x6b33, 0x3a24, 0x5175, 0x3031, 0x6b32, 0x6b34, 0x352a, 0x4248, 0x4768, 0x6b35, 0x4b2e, 0x635f, 0x5340, 0x595b, 0x4d21, 0x562d, 0x4773, 0x5960, 0x3b63, 0x3a3a, 0x6362, 0x4f2b, 0x6360, 0x4947, 0x3a39, 0x5134, 0x6361, 0x486a, 0x392f, 0x3d2d, 0x3358, 0x4e5b, 0x4c40, 0x6368, 0x6369, 0x4d74, 0x4c2d, 0x3c33, 0x636a, 0x636b, 0x505a, 0x467b, 0x375a, 0x475f, 0x524a, 0x4e56, 0x6364, 0x636c, 0x4972, 0x3341, 0x6367, 0x4663, 0x6365, 0x6d33, 0x6366, 0x4933, 0x4566, 0x3935, 0x433b, 0x6363, 0x453d, 0x4124, 0x4259, 0x3257, 0x636d, 0x3b26, 0x442d, 0x6370, 0x3e5a, 0x637b, 0x6375, 0x3a53, 0x3750, 0x534d, 0x564e, 0x5553, 0x3941, 0x5534, 0x5158, 0x5039, 0x4776, 0x482a, 0x3234, 0x435a, 0x636e, 0x637c, 0x636f, 0x3728, 0x6377, 0x6374, 0x373a, 0x4522, 0x6376, 0x455d, 0x3228, 0x467c, 0x4460, 0x5722, 0x4061, 0x6379, 0x637a, 0x637d, 0x4c29, 0x6373, 0x533e, 0x3143, 0x6d34, 0x6371, 0x6372, 0x6378, 0x503a, 0x4643, 0x5473, 0x637e, 0x3d60, 0x6427, 0x6426, 0x5173, 0x6423, 0x6429, 0x4877, 0x4f34, 0x6428, 0x642e, 0x4265, 0x3634, 0x3d72, 0x6422, 0x3a69, 0x642a, 0x642c, 0x367d, 0x565e, 0x6432, 0x642d, 0x6421, 0x3b6e, 0x4d5d, 0x4722, 0x4549, 0x4177, 0x6424, 0x4733, 0x3d2c, 0x3d3d, 0x6425, 0x5747, 0x3262, 0x642b, 0x3c43, 0x642f, 0x3b6b, 0x6430, 0x4528, 0x6431, 0x5563, 0x3f23, 0x643a, 0x6437, 0x643b, 0x643d, 0x4656, 0x3a46, 0x404b, 0x3821, 0x6434, 0x5421, 0x3a23, 0x3d7e, 0x643c, 0x4d3f, 0x4479, 0x4f7b, 0x4966, 0x533f, 0x4f51, 0x6433, 0x6438, 0x6439, 0x4c69, 0x4c4e, 0x4054, 0x6435, 0x4130, 0x6436, 0x4e50, 0x3b41, 0x3553, 0x4873, 0x3d27, 0x5547, 0x492c, 0x3822, 0x644a, 0x644c, 0x5144, 0x523a, 0x3a2d, 0x3a54, 0x6443, 0x356d, 0x574d, 0x6440, 0x4f7d, 0x643f, 0x415c, 0x4c4a, 0x4a67, 0x4457, 0x4c54, 0x6448, 0x6447, 0x6441, 0x6444, 0x352d, 0x5359, 0x6446, 0x5279, 0x3463, 0x3b34, 0x496e, 0x343e, 0x3b6c, 0x514d, 0x4c6d, 0x6d35, 0x4765, 0x5428, 0x644b, 0x5755, 0x6442, 0x3d25, 0x6445, 0x5366, 0x6449, 0x4978, 0x643e, 0x5365, 0x477e, 0x3649, 0x547c, 0x3233, 0x6457, 0x4e42, 0x644d, 0x4e3c, 0x385b, 0x6456, 0x3f4a, 0x534e, 0x436c, 0x4548, 0x6458, 0x4d44, 0x644f, 0x6454, 0x6455, 0x3a7e, 0x4f66, 0x553f, 0x6452, 0x6450, 0x644e, 0x4d65, 0x4a2a, 0x4023, 0x3d26, 0x6453, 0x3848, 0x6467, 0x5434, 0x645b, 0x416f, 0x6469, 0x5267, 0x645f, 0x6460, 0x4f2a, 0x4b5d, 0x645a, 0x6451, 0x6465, 0x485c, 0x6463, 0x4467, 0x6462, 0x6461, 0x337c, 0x6468, 0x3561, 0x574c, 0x6466, 0x3b2c, 0x5752, 0x4c4f, 0x6b78, 0x6464, 0x3976, 0x564d, 0x6459, 0x645c, 0x427a, 0x645e, 0x424b, 0x4044, 0x4250, 0x3175, 0x4c32, 0x354e, 0x646f, 0x462f, 0x4661, 0x6475, 0x4229, 0x406c, 0x515d, 0x646e, 0x442e, 0x646d, 0x6476, 0x6474, 0x427e, 0x645d, 0x6470, 0x4a7e, 0x5544, 0x6471, 0x517a, 0x646b, 0x646c, 0x6472, 0x4e2b, 0x454b, 0x4731, 0x423a, 0x646a, 0x414a, 0x4c36, 0x3331, 0x647b, 0x6473, 0x647a, 0x647d, 0x647c, 0x334e, 0x333a, 0x6477, 0x6479, 0x6478, 0x456c, 0x403d, 0x5468, 0x6522, 0x3044, 0x6524, 0x6523, 0x3c24, 0x6525, 0x6521, 0x647e, 0x3174, 0x6528, 0x6529, 0x6526, 0x6527, 0x652a, 0x4659, 0x652b, 0x652d, 0x652c, 0x652f, 0x652e, 0x3960, 0x6530, 0x6531, 0x3b70, 0x6c61, 0x4370, 0x3546, 0x3b52, 0x4169, 0x546e, 0x3e44, 0x5746, 0x5456, 0x3253, 0x6c3e, 0x6a41, 0x422f, 0x3436, 0x5157, 0x3334, 0x4832, 0x3f3b, 0x6c40, 0x564b, 0x6c3f, 0x6c41, 0x6c45, 0x3e66, 0x4c3f, 0x455a, 0x3e3c, 0x6c46, 0x317e, 0x6c44, 0x5528, 0x3563, 0x6c42, 0x4136, 0x3363, 0x6c43, 0x4b38, 0x4043, 0x4c7e, 0x4152, 0x6c48, 0x3a66, 0x4053, 0x5672, 0x514c, 0x3f3e, 0x3733, 0x4955, 0x6c47, 0x3b62, 0x4c4c, 0x3d7d, 0x4848, 0x4f29, 0x4d69, 0x456b, 0x3769, 0x5149, 0x3a38, 0x6c49, 0x6c4a, 0x3b40, 0x6c4b, 0x6c62, 0x313a, 0x3759, 0x3d39, 0x6c4c, 0x5166, 0x6c4d, 0x483b, 0x6c51, 0x6c53, 0x3b4d, 0x3c65, 0x6c4f, 0x4937, 0x433a, 0x6c63, 0x5555, 0x6c50, 0x5673, 0x6c52, 0x6c4e, 0x6c54, 0x6c55, 0x493f, 0x4f28, 0x505c, 0x512c, 0x485b, 0x6c56, 0x4e75, 0x4a6c, 0x6c5a, 0x6c59, 0x303e, 0x6c57, 0x6c58, 0x6c64, 0x483c, 0x4147, 0x6c5c, 0x5160, 0x6c5b, 0x546f, 0x6c5d, 0x5b46, 0x6c5e, 0x312c, 0x6c5f, 0x6c60, 0x5726, 0x4540, 0x6b3c, 0x302e, 0x3e74, 0x3838, 0x522f, 0x3056, 0x3579, 0x5833, 0x4b2c, 0x635d, 0x462c, 0x3066, 0x4546, 0x6b39, 0x6b3a, 0x6b3b, 0x5140, 0x4523, 0x6a72, 0x4432, 0x4435, 0x404e, 0x6a73, 0x4441, 0x4e6f, 0x6a70, 0x6a74, 0x497c, 0x4723, 0x4c58, 0x4e7e, 0x6a75, 0x6a76, 0x4f2c, 0x4067, 0x6a77, 0x363f, 0x6a78, 0x6a79, 0x6a7a, 0x6a7b, 0x6a71, 0x482e, 0x616b, 0x3738, 0x616c, 0x616d, 0x5734, 0x616e, 0x616f, 0x534c, 0x6171, 0x3f71, 0x6170, 0x3552, 0x3137, 0x6173, 0x6172, 0x3a7c, 0x6174, 0x3937, 0x3e51, 0x447c, 0x3a5d, 0x3d46, 0x6175, 0x6177, 0x3640, 0x4f41, 0x4a28, 0x6176, 0x5578, 0x537c, 0x6178, 0x617c, 0x6179, 0x617a, 0x406a, 0x617e, 0x6221, 0x4047, 0x617b, 0x617d, 0x6225, 0x4154, 0x6223, 0x6228, 0x327e, 0x6222, 0x434d, 0x3242, 0x6227, 0x6226, 0x6224, 0x6229, 0x622b, 0x5049, 0x566d, 0x4328, 0x622c, 0x4f57, 0x622e, 0x3a6f, 0x6960, 0x622d, 0x622a, 0x3b2b, 0x5433, 0x6230, 0x622f, 0x6961, 0x6231, 0x6232, 0x6233, 0x4c21, 0x6234, 0x6235, 0x507e, 0x424a, 0x5371, 0x4d75, 0x6760, 0x6761, 0x3e41, 0x426a, 0x6764, 0x6763, 0x4d66, 0x4335, 0x6762, 0x3b37, 0x4f56, 0x4161, 0x6769, 0x6768, 0x6774, 0x3223, 0x676a, 0x6766, 0x676c, 0x676b, 0x493a, 0x5564, 0x6765, 0x3729, 0x6767, 0x676e, 0x6773, 0x5669, 0x676d, 0x6772, 0x6771, 0x3060, 0x6775, 0x4772, 0x4045, 0x406d, 0x4170, 0x6770, 0x6776, 0x4b76, 0x6822, 0x6821, 0x5741, 0x677a, 0x6779, 0x677b, 0x6777, 0x677e, 0x677d, 0x677c, 0x4155, 0x4759, 0x457d, 0x4543, 0x476d, 0x6823, 0x6826, 0x6825, 0x6827, 0x3a77, 0x6778, 0x6824, 0x4870, 0x492a, 0x6829, 0x3965, 0x517e, 0x6828, 0x682a, 0x682d, 0x682e, 0x4127, 0x682f, 0x6830, 0x682c, 0x6834, 0x682b, 0x6831, 0x6835, 0x6832, 0x6833, 0x6837, 0x6836, 0x394f, 0x702c, 0x702d, 0x4630, 0x306a, 0x483f, 0x4d5f, 0x4e4d, 0x6a31, 0x6a32, 0x463f, 0x3449, 0x6a33, 0x5567, 0x5d79, 0x6a34, 0x6a35, 0x6a36, 0x384a, 0x5f30, 0x4975, 0x4c70, 0x497a, 0x497b, 0x5343, 0x4b26, 0x3826, 0x702e, 0x3142, 0x6538, 0x4c6f, 0x5349, 0x3c57, 0x496a, 0x3567, 0x4450, 0x3569, 0x6e2e, 0x3b2d, 0x675e, 0x6e2f, 0x3329, 0x6e32, 0x6e31, 0x3d67, 0x6e30, 0x4e37, 0x454f, 0x4174, 0x5b4e, 0x6e33, 0x5073, 0x4254, 0x4668, 0x372c, 0x6e34, 0x336b, 0x3b7b, 0x6e35, 0x675c, 0x6e36, 0x3d2e, 0x7162, 0x4a68, 0x5249, 0x705a, 0x705b, 0x705c, 0x4146, 0x386d, 0x3e4e, 0x705e, 0x4531, 0x705d, 0x5171, 0x7060, 0x304c, 0x3d6a, 0x525f, 0x705f, 0x342f, 0x3768, 0x7066, 0x7065, 0x4623, 0x7061, 0x7062, 0x3443, 0x7063, 0x556e, 0x4c5b, 0x3e52, 0x3c32, 0x7068, 0x7067, 0x7064, 0x3221, 0x5622, 0x5338, 0x3e37, 0x482c, 0x706a, 0x5177, 0x564c, 0x3a5b, 0x7069, 0x363b, 0x4d34, 0x4626, 0x4121, 0x706b, 0x706e, 0x706d, 0x7070, 0x706c, 0x3b3e, 0x706f, 0x4c35, 0x7072, 0x3355, 0x3154, 0x7073, 0x7074, 0x7076, 0x3461, 0x7071, 0x7077, 0x707a, 0x7078, 0x7075, 0x707d, 0x7079, 0x707c, 0x707e, 0x7121, 0x4e41, 0x7124, 0x7123, 0x4176, 0x707b, 0x4a5d, 0x3471, 0x3171, 0x4c31, 0x7126, 0x7127, 0x712c, 0x554e, 0x7129, 0x4833, 0x7122, 0x712b, 0x7128, 0x7125, 0x712a, 0x3029, 0x712d, 0x712f, 0x7131, 0x7130, 0x712e, 0x5122, 0x7132, 0x7133, 0x396f, 0x3547, 0x3057, 0x3059, 0x546d, 0x3544, 0x3d54, 0x3b4a, 0x7027, 0x385e, 0x7028, 0x3028, 0x7029, 0x4d6e, 0x702a, 0x702b, 0x4624, 0x5665, 0x7164, 0x7165, 0x4373, 0x535b, 0x5651, 0x4568, 0x532f, 0x5266, 0x6e41, 0x303b, 0x5535, 0x514e, 0x3c60, 0x3a50, 0x3f78, 0x3847, 0x3541, 0x454c, 0x4a22, 0x434b, 0x6e42, 0x443f, 0x3622, 0x6d6c, 0x4324, 0x5631, 0x4f60, 0x6d6f, 0x454e, 0x365c, 0x4a21, 0x6d6d, 0x6d70, 0x6d71, 0x433c, 0x3f34, 0x6d6e, 0x6d74, 0x6d72, 0x5566, 0x435f, 0x6d73, 0x6d76, 0x5523, 0x5123, 0x6d75, 0x4350, 0x6d77, 0x3f74, 0x3e6c, 0x6d78, 0x4c77, 0x515b, 0x5745, 0x5576, 0x6d7c, 0x6d7b, 0x6d79, 0x6d7a, 0x6d7d, 0x3e26, 0x4b2f, 0x6e21, 0x363d, 0x6e22, 0x4440, 0x6d7e, 0x3d5e, 0x3247, 0x3643, 0x6e25, 0x583a, 0x6e23, 0x6e26, 0x4369, 0x3372, 0x6e27, 0x6e24, 0x4f39, 0x6e28, 0x4277, 0x6e29, 0x6e2a, 0x5e2b, 0x4633, 0x4746, 0x5675, 0x3549, 0x4b32, 0x6e2b, 0x4d2b, 0x6e2c, 0x5530, 0x6e2d, 0x7644, 0x5b47, 0x3423, 0x432c, 0x7166, 0x4a38, 0x5253, 0x562a, 0x6f72, 0x3e58, 0x3d43, 0x6f73, 0x364c, 0x302b, 0x4a2f, 0x6d36, 0x6d37, 0x4e79, 0x372f, 0x3f73, 0x6d38, 0x426b, 0x4930, 0x6d39, 0x4676, 0x3f33, 0x6d3c, 0x4578, 0x5150, 0x5729, 0x6d3a, 0x6d3b, 0x5162, 0x6d3f, 0x6d40, 0x6d44, 0x6d48, 0x6d46, 0x6d4e, 0x5568, 0x6d49, 0x6d47, 0x6d3e, 0x4569, 0x4646, 0x4969, 0x5452, 0x6d41, 0x6d42, 0x6d43, 0x6d45, 0x4079, 0x3421, 0x3968, 0x6d50, 0x6d51, 0x6d4a, 0x6d4f, 0x4e78, 0x4b36, 0x6d4c, 0x6d4d, 0x4f75, 0x6d52, 0x4172, 0x5332, 0x6d4b, 0x4837, 0x3c6f, 0x4570, 0x6d56, 0x356f, 0x4235, 0x302d, 0x4b69, 0x312e, 0x6d54, 0x4d6b, 0x3562, 0x6d55, 0x6d53, 0x6d57, 0x357a, 0x6d58, 0x6d59, 0x6d5c, 0x314c, 0x4576, 0x3c6e, 0x6d5a, 0x4c3c, 0x326a, 0x6d5b, 0x446b, 0x3445, 0x3075, 0x6d5f, 0x405a, 0x3468, 0x454d, 0x6d5d, 0x3f44, 0x6d5e, 0x4425, 0x6d60, 0x6d61, 0x6d63, 0x4157, 0x3b47, 0x3d38, 0x6d62, 0x6d64, 0x6d66, 0x6d65, 0x6d67, 0x4a3e, 0x6c6a, 0x4071, 0x4967, 0x6c6b, 0x466e, 0x6c6c, 0x466d, 0x6c6d, 0x6c70, 0x5766, 0x6c73, 0x6c71, 0x6c6e, 0x6c6f, 0x5723, 0x4971, 0x4b6e, 0x6c74, 0x6c72, 0x4f69, 0x6c76, 0x4631, 0x3c40, 0x6c75, 0x353b, 0x3b76, 0x6c77, 0x5977, 0x3d7b, 0x423b, 0x6c78, 0x6c79, 0x3823, 0x6c7a, 0x6c7b, 0x6c7c, 0x536d, 0x582e, 0x406b, 0x475d, 0x3a4c, 0x5063, 0x4b3d, 0x4d3a, 0x3851, 0x317c, 0x476f, 0x5656, 0x3f46, 0x436b, 0x6f75, 0x4358, 0x5762, 0x6f77, 0x3353, 0x4758, 0x516d, 0x5648, 0x6f78, 0x6f76, 0x3b7d, 0x3346, 0x3d55, 0x5246, 0x3b60, 0x4f21, 0x6f7c, 0x6f7b, 0x6f79, 0x334c, 0x4954, 0x4b30, 0x6f7e, 0x305e, 0x5649, 0x6f7d, 0x336d, 0x7655, 0x4e48, 0x7022, 0x7021, 0x353e, 0x3c5a, 0x3b7c, 0x3865, 0x4442, 0x7023, 0x4b6b, 0x7026, 0x5128, 0x3e3f, 0x476e, 0x7136, 0x7137, 0x3f55, 0x3429, 0x7138, 0x4d3b, 0x4754, 0x552d, 0x7139, 0x713a, 0x474f, 0x5224, 0x564f, 0x713b, 0x3d51, 0x3430, 0x3e3d, 0x345c, 0x4e51, 0x3f5f, 0x713d, 0x3f7a, 0x713c, 0x713f, 0x713e, 0x7140, 0x7141, 0x417e, 0x4122, 0x4a7a, 0x553e, 0x3e3a, 0x3e39, 0x5542, 0x3f22, 0x4d2f, 0x7135, 0x3d5f, 0x364b, 0x5671, 0x7343, 0x7344, 0x384d, 0x7346, 0x7347, 0x304a, 0x7345, 0x7349, 0x4b71, 0x734b, 0x5026, 0x314a, 0x7348, 0x734f, 0x3551, 0x7357, 0x7352, 0x7354, 0x7353, 0x377b, 0x313f, 0x734e, 0x734a, 0x355a, 0x7350, 0x7351, 0x7355, 0x734d, 0x3c63, 0x417d, 0x7356, 0x735a, 0x734c, 0x3548, 0x3d6e, 0x735c, 0x3724, 0x3f70, 0x567e, 0x4d32, 0x3470, 0x325f, 0x7358, 0x7359, 0x4938, 0x735d, 0x735e, 0x7361, 0x735f, 0x7363, 0x7362, 0x735b, 0x3f6a, 0x336f, 0x7360, 0x4729, 0x3c72, 0x736b, 0x393f, 0x7364, 0x322d, 0x3b7e, 0x4b63, 0x736d, 0x7369, 0x395c, 0x736e, 0x7365, 0x7366, 0x736a, 0x4261, 0x736c, 0x736f, 0x7368, 0x3c7d, 0x4f64, 0x7370, 0x7367, 0x7372, 0x572d, 0x462a, 0x7373, 0x7371, 0x4228, 0x385d, 0x7375, 0x7374, 0x345b, 0x7376, 0x7377, 0x7378, 0x403a, 0x4069, 0x4571, 0x737b, 0x737a, 0x3458, 0x737e, 0x7379, 0x737c, 0x737d, 0x7421, 0x7423, 0x3b49, 0x7422, 0x7424, 0x323e, 0x7426, 0x7425, 0x3c2e, 0x4357, 0x5961, 0x4060, 0x744c, 0x5751, 0x375b, 0x744e, 0x4123, 0x4649, 0x3456, 0x5533, 0x7450, 0x744f, 0x7451, 0x4b5a, 0x7452, 0x5441, 0x5660, 0x3760, 0x4138, 0x413b, 0x7453, 0x3e2c, 0x3462, 0x7454, 0x7455, 0x3e2b, 0x7456, 0x745b, 0x7457, 0x745a, 0x3a7d, 0x7458, 0x7459, 0x3862, 0x4c47, 0x745c, 0x325a, 0x4353, 0x5463, 0x3f37, 0x745d, 0x4534, 0x7469, 0x4f35, 0x4e49, 0x4b58, 0x4b77, 0x3d74, 0x574f, 0x405b, 0x5075, 0x746a, 0x746b, 0x746c, 0x7763, 0x3731, 0x746d, 0x576b, 0x746e, 0x6679, 0x3e40, 0x667a, 0x3a6c, 0x667b, 0x4f4b, 0x667c, 0x543c, 0x3c36, 0x667d, 0x667e, 0x3c4d, 0x4852, 0x4e33, 0x6721, 0x343f, 0x6722, 0x4934, 0x3859, 0x4449, 0x575d, 0x425a, 0x3757, 0x563d, 0x4e46, 0x3744, 0x4526, 0x6723, 0x4f5f, 0x6724, 0x6725, 0x6726, 0x4137, 0x5769, 0x4970, 0x4f38, 0x562f, 0x5655, 0x6727, 0x306d, 0x6728, 0x6729, 0x495c, 0x526f, 0x3e2d, 0x672a, 0x3073, 0x485e, 0x3d61, 0x672b, 0x4846, 0x672c, 0x3b66, 0x3878, 0x5124, 0x672d, 0x4267, 0x3e78, 0x3d4a, 0x4d33, 0x672e, 0x672f, 0x3e6e, 0x5065, 0x4b67, 0x4c50, 0x3c4c, 0x6730, 0x3c28, 0x5077, 0x6731, 0x5078, 0x6732, 0x6733, 0x3442, 0x6734, 0x6735, 0x497e, 0x4e2c, 0x4360, 0x6737, 0x3141, 0x3371, 0x6738, 0x6739, 0x575b, 0x5540, 0x673a, 0x424c, 0x573a, 0x673b, 0x673c, 0x673d, 0x3c6a, 0x4365, 0x4042, 0x673e, 0x673f, 0x3c29, 0x6740, 0x6741, 0x6736, 0x3650, 0x6742, 0x6743, 0x6744, 0x3b3a, 0x355e, 0x4246, 0x3160, 0x6745, 0x5435, 0x6746, 0x383f, 0x6748, 0x6747, 0x376c, 0x6749, 0x3278, 0x674a, 0x674b, 0x674c, 0x674d, 0x674e, 0x674f, 0x6750, 0x5327, 0x4b75, 0x6751, 0x6752, 0x6753, 0x6754, 0x4949, 0x6755, 0x6756, 0x6757, 0x6758, 0x6759, 0x3d49, 0x675a, 0x733e, 0x3857, 0x4831, 0x733f, 0x7340, 0x7341, 0x395e, 0x4d78, 0x5868, 0x3a31, 0x425e, 0x6e37, 0x3723, 0x6e39, 0x6e38, 0x3055, 0x6e3b, 0x5556, 0x576f, 0x5643, 0x6e3d, 0x4a70, 0x6e3c, 0x6e3e, 0x6e40, 0x6e3f, 0x5172, 0x473c, 0x4340, 0x3861, 0x4167, 0x7446, 0x505f, 0x7447, 0x4f5b, 0x483a, 0x7448, 0x7449, 0x744a, 0x744b, 0x597a, 0x387e, 0x6571, 0x5370, 0x7460, 0x4e4c, 0x3361, 0x7134, 0x526e, 0x7461, 0x4f68, 0x7462, 0x474c, 0x3554, 0x3464, 0x7464, 0x7463, 0x7465, 0x7466, 0x7467, 0x3a32, 0x303f, 0x7468, 0x372d, 0x526d, 0x522b, 0x404f, 0x3f3c, 0x6b23, 0x555f, 0x6a48, 0x7173, 0x3678, 0x4b23, 0x444d, 0x7167, 0x7168, 0x387b, 0x7169, 0x3a44, 0x5445, 0x3052, 0x716a, 0x716b, 0x716c, 0x716d, 0x716e, 0x716f, 0x7171, 0x7170, 0x4555, 0x7172, 0x367a, 0x7174, 0x522e, 0x5e47, 0x4b4a, 0x335c, 0x3522, 0x3922, 0x4474, 0x7175, 0x7176, 0x4144, 0x417b, 0x5630, 0x7177, 0x7178, 0x412a, 0x4638, 0x3e5b, 0x7179, 0x344f, 0x717a, 0x6d32, 0x6d31, 0x4b60, 0x525e, 0x4b41, 0x5558, 0x4862, 0x405f, 0x3c21, 0x6b41, 0x5024, 0x5662, 0x3647, 0x3858, 0x6b40, 0x384e, 0x6b3f, 0x3326, 0x3949, 0x562b, 0x3774, 0x374a, 0x3c67, 0x373e, 0x6b46, 0x6b47, 0x3039, 0x3f4f, 0x6b45, 0x537d, 0x6b48, 0x6b49, 0x374e, 0x6b42, 0x6b44, 0x4976, 0x5657, 0x554d, 0x5032, 0x6b4f, 0x4e38, 0x6b50, 0x3528, 0x3133, 0x6b52, 0x4c25, 0x4556, 0x6b53, 0x6b51, 0x455f, 0x6b4e, 0x4a24, 0x6b55, 0x307b, 0x3a7a, 0x5837, 0x7163, 0x6b4a, 0x6b4b, 0x6b4c, 0x6b4d, 0x6b56, 0x6640, 0x6b59, 0x3f68, 0x5248, 0x6b57, 0x6b5c, 0x386c, 0x6b58, 0x3d3a, 0x5058, 0x3037, 0x6b5d, 0x445c, 0x562c, 0x3460, 0x4276, 0x3c39, 0x6b5a, 0x6b5b, 0x5460, 0x466a, 0x4454, 0x6b5f, 0x4527, 0x5975, 0x3231, 0x6b64, 0x3d45, 0x6b62, 0x6b63, 0x382c, 0x4d51, 0x6b65, 0x6b61, 0x4133, 0x4622, 0x4c73, 0x6b66, 0x4030, 0x5238, 0x6b67, 0x382f, 0x382d, 0x6b68, 0x473b, 0x4d73, 0x6b6a, 0x6b6b, 0x6b6d, 0x5048, 0x6b72, 0x6b6e, 0x6b71, 0x4879, 0x517c, 0x6b6c, 0x6b69, 0x3839, 0x4f59, 0x4465, 0x6b6f, 0x6b70, 0x4c5a, 0x4d48, 0x3072, 0x6b76, 0x6b75, 0x3232, 0x3860, 0x6b77, 0x316c, 0x4c45, 0x4424, 0x4f25, 0x6b79, 0x6c22, 0x4572, 0x6b7a, 0x4945, 0x625f, 0x6b7e, 0x4d4e, 0x6c21, 0x315b, 0x5337, 0x525c, 0x6b7d, 0x6b7b, 0x333c, 0x6a30, 0x5754, 0x742b, 0x3374, 0x5641, 0x5642, 0x5569, 0x3e4a, 0x7427, 0x5228, 0x7428, 0x7429, 0x742a, 0x3e4b, 0x535f, 0x4960, 0x4961, 0x7342, 0x4a66, 0x4c72, 0x6236, 0x4b34, 0x4e68, 0x565b, 0x742d, 0x742e, 0x742f, 0x7432, 0x3a3d, 0x7433, 0x3063, 0x7430, 0x7431, 0x3d22, 0x3255, 0x7436, 0x7437, 0x3666, 0x3230, 0x4f4f, 0x7434, 0x342c, 0x7435, 0x7438, 0x7439, 0x4d27, 0x743a, 0x743b, 0x743c, 0x4b52, 0x743d, 0x743e, 0x743f, 0x745e, 0x413c, 0x3c68, 0x492b, 0x515e, 0x6575, 0x5c33, 0x5255, 0x5c34, 0x302c, 0x5c35, 0x3d5a, 0x5c39, 0x5842, 0x5c37, 0x5373, 0x4956, 0x5c3a, 0x5c36, 0x5c3b, 0x4322, 0x5c3c, 0x5c45, 0x5c3d, 0x4e5f, 0x5625, 0x5c4f, 0x5c4d, 0x5c52, 0x3d66, 0x422b, 0x5c38, 0x5c4b, 0x5c4e, 0x5c3e, 0x3752, 0x3045, 0x5c47, 0x503e, 0x5c41, 0x3b28, 0x373c, 0x5c4c, 0x5c46, 0x5c3f, 0x475b, 0x513f, 0x5c40, 0x5c4a, 0x5c50, 0x4e2d, 0x5c42, 0x5c43, 0x5c48, 0x5c49, 0x3254, 0x5c51, 0x4b55, 0x5437, 0x5c5b, 0x5c5f, 0x4c26, 0x5c66, 0x4367, 0x5c5c, 0x3f41, 0x5c59, 0x307a, 0x3936, 0x5c65, 0x5c53, 0x5c44, 0x5c56, 0x4874, 0x3f60, 0x493b, 0x313d, 0x5322, 0x5c5a, 0x5c55, 0x463b, 0x5c5e, 0x5742, 0x432f, 0x3736, 0x4751, 0x4329, 0x5c62, 0x5c58, 0x5c6b, 0x5c54, 0x5c5d, 0x3e25, 0x5c57, 0x5c60, 0x5c63, 0x5c64, 0x5c78, 0x5c61, 0x5d22, 0x5c67, 0x3c6b, 0x3444, 0x4323, 0x3267, 0x5c7a, 0x5c72, 0x5c6f, 0x5c7c, 0x5c6e, 0x5270, 0x3268, 0x4857, 0x4863, 0x5c7b, 0x5c6d, 0x5c77, 0x5c75, 0x3e23, 0x5c74, 0x325d, 0x5c73, 0x3c76, 0x5c68, 0x3b44, 0x4073, 0x3c54, 0x5c69, 0x5c6a, 0x5c71, 0x5c76, 0x5c79, 0x3534, 0x4859, 0x3b67, 0x5c7e, 0x5c7d, 0x532b, 0x5d21, 0x5d23, 0x5d25, 0x5271, 0x5d24, 0x5d26, 0x5d27, 0x5229, 0x3a49, 0x5d29, 0x5d36, 0x5d31, 0x5d34, 0x5d30, 0x464e, 0x4072, 0x492f, 0x5c6c, 0x5d2e, 0x5d37, 0x5c70, 0x5d2f, 0x5d38, 0x5d2c, 0x5d39, 0x5d33, 0x5d2d, 0x442a, 0x5d28, 0x4033, 0x412b, 0x5d2a, 0x5d2b, 0x5d32, 0x3b71, 0x5d35, 0x5328, 0x5d3a, 0x5d3b, 0x4327, 0x5d52, 0x5d3c, 0x5d51, 0x393d, 0x3e55, 0x3e7a, 0x3a4a, 0x5d4a, 0x5d45, 0x5d3f, 0x324b, 0x5d43, 0x5d4b, 0x3224, 0x5d55, 0x5d3e, 0x4650, 0x5d50, 0x5d54, 0x4162, 0x3746, 0x5d4e, 0x5d4f, 0x5d44, 0x5d3d, 0x5d4d, 0x4c51, 0x5d49, 0x5d42, 0x4348, 0x463c, 0x4e2e, 0x5d4c, 0x5d48, 0x5d41, 0x5d46, 0x425c, 0x5329, 0x532a, 0x5d53, 0x4f74, 0x4878, 0x5d66, 0x5d47, 0x5d60, 0x4264, 0x5d61, 0x5d57, 0x5678, 0x5d59, 0x5d58, 0x3870, 0x5d56, 0x464f, 0x362d, 0x5d62, 0x3a79, 0x5461, 0x5d67, 0x3450, 0x5d5a, 0x3f7b, 0x5d63, 0x5d5f, 0x5d5d, 0x3559, 0x5d5b, 0x5d5c, 0x5d5e, 0x3d2f, 0x5d64, 0x5d65, 0x5d75, 0x4349, 0x4b62, 0x5d72, 0x5861, 0x4651, 0x5d74, 0x5574, 0x5d73, 0x5d70, 0x5d6c, 0x5d6f, 0x5d68, 0x506e, 0x4858, 0x5d6e, 0x5d69, 0x5d6a, 0x4b72, 0x5d6d, 0x314d, 0x4036, 0x3c3b, 0x5d71, 0x5d77, 0x5d76, 0x5d6b, 0x456e, 0x5d7b, 0x5e24, 0x5e23, 0x5d78, 0x436f, 0x427b, 0x5561, 0x4e35, 0x5d7d, 0x324c, 0x4468, 0x4a5f, 0x473e, 0x5d7a, 0x5d7c, 0x5d7e, 0x5e22, 0x302a, 0x314e, 0x5e2c, 0x5e26, 0x3d36, 0x486f, 0x5e21, 0x5e25, 0x5e29, 0x5e28, 0x5e27, 0x5e2d, 0x544c, 0x5e33, 0x5e2a, 0x5e2e, 0x4059, 0x3121, 0x5e36, 0x5e31, 0x5e32, 0x5126, 0x5e35, 0x5e2f, 0x5e30, 0x503d, 0x5e34, 0x4a6d, 0x5e39, 0x5e38, 0x5e37, 0x5e3b, 0x3d65, 0x3258, 0x436a, 0x5e3a, 0x453a, 0x5e3c, 0x4c59, 0x372a, 0x5465, 0x5e3d, 0x5e3f, 0x4422, 0x5e41, 0x5e3e, 0x5e40, 0x553a, 0x5e42, 0x722e, 0x3b22, 0x4232, 0x4530, 0x4247, 0x722f, 0x5069, 0x535d, 0x6b3d, 0x3366, 0x7230, 0x7231, 0x4a2d, 0x3a67, 0x7233, 0x7235, 0x7234, 0x4b64, 0x4f3a, 0x7232, 0x4a34, 0x524f, 0x426c, 0x4e43, 0x7238, 0x3076, 0x7237, 0x723e, 0x324f, 0x5141, 0x723a, 0x723c, 0x5469, 0x723b, 0x7236, 0x723f, 0x723d, 0x7239, 0x7247, 0x7244, 0x7246, 0x724a, 0x7242, 0x7240, 0x7245, 0x567b, 0x7241, 0x4779, 0x495f, 0x7248, 0x3946, 0x3530, 0x7243, 0x7249, 0x7250, 0x7256, 0x3b57, 0x7255, 0x4d5c, 0x566b, 0x7252, 0x7254, 0x3872, 0x724b, 0x724e, 0x4279, 0x555d, 0x724c, 0x724d, 0x724f, 0x7253, 0x7259, 0x533c, 0x366a, 0x4a71, 0x3764, 0x7257, 0x7258, 0x725a, 0x725d, 0x725b, 0x725c, 0x5151, 0x7251, 0x4d49, 0x4e4f, 0x5629, 0x7263, 0x435b, 0x7260, 0x402f, 0x726c, 0x725e, 0x7261, 0x7268, 0x7262, 0x7267, 0x7266, 0x7269, 0x725f, 0x7264, 0x726a, 0x532c, 0x7265, 0x3275, 0x7272, 0x502b, 0x7275, 0x3b48, 0x7279, 0x7270, 0x7276, 0x7278, 0x727a, 0x7273, 0x7271, 0x3a7b, 0x357b, 0x726f, 0x7277, 0x726d, 0x726e, 0x726b, 0x7326, 0x7323, 0x7322, 0x7274, 0x485a, 0x727b, 0x7325, 0x4378, 0x727d, 0x7327, 0x7329, 0x7324, 0x727c, 0x732b, 0x732a, 0x425d, 0x732e, 0x7330, 0x7321, 0x7331, 0x732c, 0x732f, 0x727e, 0x732d, 0x7332, 0x7334, 0x7328, 0x7333, 0x7335, 0x5037, 0x7338, 0x5979, 0x7339, 0x7337, 0x4864, 0x7336, 0x733a, 0x733b, 0x3440, 0x6e43, 0x733c, 0x733d, 0x512a, 0x742c, 0x5046, 0x5050, 0x515c, 0x4f4e, 0x3d56, 0x5143, 0x3a62, 0x6169, 0x5242, 0x7142, 0x3239, 0x316d, 0x7143, 0x4940, 0x3344, 0x5972, 0x4b25, 0x7144, 0x5654, 0x7145, 0x7440, 0x7146, 0x542c, 0x7147, 0x3040, 0x7441, 0x7442, 0x347c, 0x455b, 0x4c3b, 0x5064, 0x4d60, 0x7148, 0x5973, 0x313b, 0x4f2e, 0x3824, 0x714a, 0x714b, 0x3243, 0x4151, 0x5730, 0x7149, 0x714c, 0x714e, 0x5976, 0x5261, 0x5423, 0x7443, 0x4839, 0x7444, 0x714d, 0x714f, 0x3f63, 0x7150, 0x7154, 0x7156, 0x7151, 0x4951, 0x4561, 0x4263, 0x397c, 0x7153, 0x7155, 0x3953, 0x715b, 0x3a56, 0x307d, 0x7159, 0x7158, 0x7152, 0x715a, 0x7157, 0x486c, 0x4d4a, 0x715d, 0x653d, 0x715c, 0x715e, 0x715f, 0x4f65, 0x7445, 0x3d73, 0x7160, 0x7161, 0x4e77, 0x522a, 0x717b, 0x3832, 0x3c7b, 0x395b, 0x3966, 0x4359, 0x4a53, 0x6a68, 0x4040, 0x3e75, 0x6a69, 0x6a6a, 0x6a6b, 0x6a6c, 0x6a6d, 0x6a6e, 0x6a6f, 0x3d47, 0x757b, 0x757d, 0x757e, 0x757c, 0x3d62, 0x7621, 0x3425, 0x7622, 0x7623, 0x6c32, 0x5154, 0x596a, 0x7624, 0x6e3a, 0x5532, 0x537e, 0x4c5c, 0x4a44, 0x6540, 0x7625, 0x3e2f, 0x4629, 0x5a25, 0x3c46, 0x3629, 0x383c, 0x484f, 0x3c25, 0x5a26, 0x5a27, 0x4c56, 0x4843, 0x5a28, 0x467d, 0x5135, 0x5269, 0x5136, 0x3c47, 0x3d32, 0x3b64, 0x5a29, 0x5a2a, 0x5148, 0x5a2b, 0x506d, 0x366f, 0x425b, 0x4b4f, 0x376d, 0x4968, 0x3743, 0x3e77, 0x5624, 0x5a2c, 0x5a2d, 0x4640, 0x5767, 0x4a36, 0x5529, 0x4b5f, 0x556f, 0x5a2e, 0x565f, 0x344a, 0x5a30, 0x5a2f, 0x526b, 0x5a31, 0x5a32, 0x5a33, 0x4a54, 0x5a34, 0x4a2b, 0x5a35, 0x5a36, 0x334f, 0x566f, 0x5a37, 0x3b30, 0x352e, 0x5a38, 0x5a39, 0x396e, 0x512f, 0x5268, 0x5a3a, 0x3843, 0x4f6a, 0x326f, 0x5a3b, 0x5a3c, 0x3d6b, 0x4e5c, 0x536f, 0x5a3d, 0x4e73, 0x5a3e, 0x5355, 0x3b65, 0x5a3f, 0x4b35, 0x4b50, 0x5a40, 0x476b, 0x566e, 0x5a41, 0x4535, 0x3641, 0x5a42, 0x374c, 0x3f4e, 0x5a43, 0x5a44, 0x4b2d, 0x5a45, 0x3577, 0x5a46, 0x4142, 0x573b, 0x5a47, 0x4c38, 0x526a, 0x4431, 0x5a48, 0x357d, 0x3b51, 0x5a49, 0x5033, 0x5a4a, 0x5a4b, 0x4e3d, 0x5a4c, 0x5a4d, 0x5a4e, 0x3277, 0x5a51, 0x5a4f, 0x5168, 0x5a50, 0x4355, 0x5a52, 0x5a53, 0x5a54, 0x5a55, 0x503b, 0x5225, 0x3079, 0x5a56, 0x472b, 0x5a57, 0x3d77, 0x4321, 0x5a58, 0x5a59, 0x437d, 0x4c37, 0x5a5a, 0x5a5b, 0x403e, 0x4657, 0x5a5c, 0x5a5d, 0x4734, 0x5a5e, 0x5a5f, 0x3948, 0x3b6d, 0x3639, 0x7478, 0x7479, 0x4d63, 0x7539, 0x6b60, 0x4f73, 0x3b3f, 0x3a40, 0x5425, 0x6159, 0x7574, 0x312a, 0x3272, 0x7575, 0x7577, 0x3a51, 0x7576, 0x4332, 0x7579, 0x7578, 0x3134, 0x556a, 0x383a, 0x3931, 0x3246, 0x5470, 0x4f4d, 0x305c, 0x554b, 0x3b75, 0x564a, 0x3737, 0x4c30, 0x4636, 0x3161, 0x393a, 0x567c, 0x3961, 0x3721, 0x3c7a, 0x6a5a, 0x6a5b, 0x4c79, 0x3973, 0x6a5c, 0x347b, 0x4333, 0x3751, 0x3a58, 0x6a5d, 0x5474, 0x6a5e, 0x3c56, 0x3b5f, 0x6a5f, 0x415e, 0x4238, 0x545f, 0x574a, 0x6a60, 0x6a61, 0x6a64, 0x6a62, 0x6a63, 0x495e, 0x3833, 0x3644, 0x6a65, 0x4a6a, 0x494d, 0x344d, 0x6259, 0x4562, 0x6a66, 0x4035, 0x5738, 0x6a67, 0x572c, 0x487c, 0x5853, 0x584d, 0x545e, 0x5479, 0x4944, 0x532e, 0x3853, 0x3360, 0x4962, 0x7476, 0x3a55, 0x7477, 0x575f, 0x7471, 0x3830, 0x5554, 0x384f, 0x4670, 0x3343, 0x7472, 0x332c, 0x543d, 0x4777, 0x7474, 0x7473, 0x4c4b, 0x4824, 0x7475, 0x5763, 0x453f, 0x7540, 0x753b, 0x7543, 0x7542, 0x563a, 0x7541, 0x543e, 0x7544, 0x754c, 0x304f, 0x3578, 0x7549, 0x754a, 0x455c, 0x7545, 0x7546, 0x7547, 0x754b, 0x3e60, 0x7548, 0x387a, 0x7550, 0x7553, 0x3f67, 0x3972, 0x753c, 0x754d, 0x4237, 0x4c78, 0x3c79, 0x754e, 0x754f, 0x7551, 0x3665, 0x7552, 0x7555, 0x753d, 0x7554, 0x533b, 0x336c, 0x4c24, 0x7556, 0x7557, 0x3e61, 0x7558, 0x4c5f, 0x755b, 0x3248, 0x5759, 0x7559, 0x755a, 0x755c, 0x7562, 0x7560, 0x755f, 0x755d, 0x7561, 0x755e, 0x7564, 0x7565, 0x4c63, 0x653f, 0x3538, 0x7563, 0x7568, 0x4c23, 0x7566, 0x7567, 0x753e, 0x3144, 0x753f, 0x3545, 0x3264, 0x756c, 0x7569, 0x3657, 0x756d, 0x756a, 0x756b, 0x345a, 0x546a, 0x756e, 0x3379, 0x756f, 0x7571, 0x7570, 0x7572, 0x7573, 0x496d, 0x392a, 0x477b, 0x3663, 0x4c49, 0x6a26, 0x3335, 0x547e, 0x396c, 0x5079, 0x696d, 0x572a, 0x696e, 0x4256, 0x486d, 0x3a64, 0x696f, 0x6970, 0x6971, 0x5661, 0x6972, 0x6973, 0x6975, 0x6974, 0x6976, 0x6977, 0x4761, 0x6978, 0x5458, 0x6979, 0x3d4e, 0x697a, 0x697b, 0x3d4f, 0x697c, 0x3828, 0x413e, 0x697d, 0x3132, 0x3b54, 0x3975, 0x697e, 0x6a21, 0x6a22, 0x6a23, 0x3778, 0x3c2d, 0x4a64, 0x604e, 0x542f, 0x4f3d, 0x5537, 0x6a24, 0x555e, 0x6a25, 0x5041, 0x393c, 0x3447, 0x3159, 0x4031, 0x3166, 0x3167, 0x3168, 0x333d, 0x4868, 0x6541, 0x315f, 0x4149, 0x346f, 0x4728, 0x5358, 0x4679, 0x5138, 0x397d, 0x4275, 0x532d, 0x544b, 0x3d7c, 0x6542, 0x3735, 0x6543, 0x3b39, 0x5562, 0x3d78, 0x5436, 0x4e25, 0x412c, 0x3359, 0x4c76, 0x6546, 0x6544, 0x6548, 0x654a, 0x6547, 0x354f, 0x4648, 0x357c, 0x6545, 0x4a76, 0x6549, 0x4354, 0x3145, 0x3c23, 0x5737, 0x4d4b, 0x4b4d, 0x4a4a, 0x4c53, 0x654c, 0x654b, 0x4466, 0x5121, 0x5137, 0x654d, 0x6550, 0x4d38, 0x5670, 0x654f, 0x355d, 0x4d3e, 0x6551, 0x363a, 0x4d28, 0x3964, 0x4a45, 0x3351, 0x4b59, 0x546c, 0x6552, 0x376a, 0x654e, 0x6555, 0x347e, 0x6556, 0x6553, 0x6554, 0x525d, 0x425f, 0x3146, 0x5362, 0x365d, 0x4b6c, 0x6557, 0x5376, 0x3169, 0x3674, 0x655a, 0x6558, 0x6559, 0x3540, 0x5245, 0x655c, 0x655e, 0x655d, 0x4732, 0x5223, 0x655b, 0x5462, 0x555a, 0x6560, 0x5771, 0x6561, 0x315c, 0x517b, 0x6562, 0x6564, 0x6563, 0x6565, 0x5258, 0x354b, 0x675f, 0x5a75, 0x5a78, 0x5a76, 0x5a77, 0x5a7a, 0x504f, 0x4447, 0x306e, 0x5030, 0x5a79, 0x534a, 0x3a2a, 0x5b22, 0x4771, 0x5a7c, 0x5a7b, 0x495b, 0x5a7d, 0x5b21, 0x575e, 0x5a7e, 0x415a, 0x5b25, 0x5374, 0x5b27, 0x5b24, 0x5b28, 0x3d3c, 0x4049, 0x5b23, 0x5b26, 0x5623, 0x5b29, 0x5b2d, 0x5b2e, 0x5b2c, 0x3a42, 0x3f24, 0x5b2b, 0x5b2a, 0x5447, 0x323f, 0x5b2f, 0x3979, 0x5b30, 0x333b, 0x3526, 0x363c, 0x5b31, 0x3675, 0x5b32, 0x3149, 0x5b34, 0x5b33, 0x5b35, 0x5b37, 0x5b36, 0x5b38, 0x5b39, 0x5b3a, 0x534f, 0x747a, 0x4775, 0x5743, 0x4564, 0x747c, 0x747d, 0x747b, 0x3e46, 0x506f, 0x3753, 0x544d, 0x4c2a, 0x7522, 0x7521, 0x3a28, 0x747e, 0x4b56, 0x7524, 0x4052, 0x336a, 0x4d2a, 0x7525, 0x7523, 0x3d34, 0x7528, 0x7529, 0x3d4d, 0x4338, 0x3f61, 0x4b61, 0x752a, 0x7526, 0x7527, 0x4470, 0x752c, 0x343c, 0x576d, 0x3457, 0x752b, 0x752e, 0x752d, 0x752f, 0x5051, 0x4351, 0x4829, 0x7530, 0x7531, 0x7532, 0x7533, 0x7534, 0x7535, 0x7537, 0x7536, 0x7538, 0x3249, 0x5354, 0x4a4d, 0x406f, 0x5658, 0x5230, 0x413f, 0x3d70, 0x382a, 0x3c78, 0x7646, 0x7647, 0x7648, 0x7649, 0x764a, 0x764c, 0x764b, 0x7769, 0x764d, 0x764e, 0x6e44, 0x6e45, 0x6e46, 0x556b, 0x3624, 0x6e48, 0x6e47, 0x6e49, 0x6e4a, 0x4725, 0x6e4b, 0x6e4c, 0x3730, 0x3576, 0x6e4d, 0x6e4f, 0x6e4e, 0x3846, 0x6e50, 0x6e51, 0x6e52, 0x365b, 0x332e, 0x5653, 0x4446, 0x3135, 0x3856, 0x6e53, 0x6e54, 0x543f, 0x4755, 0x3e7b, 0x4e59, 0x3933, 0x6e56, 0x6e55, 0x6e58, 0x6e57, 0x4525, 0x6e59, 0x6e5a, 0x472e, 0x6e5b, 0x472f, 0x6e5c, 0x3227, 0x6e5d, 0x6e5e, 0x6e5f, 0x6e60, 0x6e61, 0x576a, 0x6e62, 0x6e63, 0x3c58, 0x6e64, 0x534b, 0x4c7a, 0x322c, 0x4165, 0x6e65, 0x4726, 0x432d, 0x6e66, 0x6e67, 0x6e68, 0x6e69, 0x6e6a, 0x6e6b, 0x6e6c, 0x6e6d, 0x6e6e, 0x6e6f, 0x6e70, 0x6e71, 0x6e72, 0x6e74, 0x6e73, 0x6e75, 0x4d2d, 0x4241, 0x6e76, 0x6e77, 0x6e78, 0x5521, 0x6e79, 0x4f33, 0x6e7a, 0x6e7b, 0x6e7c, 0x6e7d, 0x6f21, 0x6e7e, 0x6f22, 0x3875, 0x437a, 0x6f23, 0x6f24, 0x3d42, 0x523f, 0x3279, 0x6f25, 0x6f26, 0x6f27, 0x5278, 0x6f28, 0x567d, 0x6f29, 0x464c, 0x6f2a, 0x6f2b, 0x4134, 0x6f2c, 0x4f7a, 0x4b78, 0x6f2e, 0x6f2d, 0x337a, 0x3978, 0x6f2f, 0x6f30, 0x5062, 0x6f31, 0x6f32, 0x3766, 0x503f, 0x6f33, 0x6f34, 0x6f35, 0x4871, 0x4c60, 0x6f36, 0x6f37, 0x6f38, 0x6f39, 0x6f3a, 0x5560, 0x6f3b, 0x346d, 0x432a, 0x6f3c, 0x6f3d, 0x6f3e, 0x6f3f, 0x4e7d, 0x6f40, 0x4260, 0x3438, 0x5736, 0x3d75, 0x4f47, 0x6f43, 0x6f41, 0x6f42, 0x6f44, 0x3627, 0x3c7c, 0x3e62, 0x434c, 0x6f45, 0x6f46, 0x6f47, 0x6f4f, 0x6f48, 0x6f49, 0x6f4a, 0x4742, 0x6f71, 0x364d, 0x6f4b, 0x6f4c, 0x6f4d, 0x3646, 0x433e, 0x6f4e, 0x6f50, 0x6f51, 0x6f52, 0x5572, 0x6f53, 0x4477, 0x6f54, 0x4478, 0x6f55, 0x6f56, 0x3864, 0x3077, 0x6f57, 0x6f58, 0x6f59, 0x6f5a, 0x6f5b, 0x6f5c, 0x6f5d, 0x6f5e, 0x3e35, 0x6f61, 0x6f5f, 0x6f60, 0x6f62, 0x6f63, 0x414d, 0x6f64, 0x6f65, 0x6f66, 0x6f67, 0x6f68, 0x6f69, 0x6f6a, 0x6f6b, 0x6f6c, 0x4058, 0x6f6d, 0x412d, 0x6f6e, 0x6f6f, 0x6f70, 0x4f62, 0x3324, 0x4345, 0x6345, 0x4941, 0x6346, 0x3155, 0x4e4a, 0x3433, 0x4872, 0x6347, 0x4f50, 0x6348, 0x3c64, 0x6349, 0x634a, 0x4346, 0x5522, 0x4456, 0x396b, 0x4e45, 0x634b, 0x4376, 0x634c, 0x3727, 0x3873, 0x3a52, 0x634d, 0x634e, 0x5444, 0x634f, 0x6350, 0x514b, 0x6351, 0x6352, 0x6353, 0x6354, 0x5156, 0x6355, 0x327b, 0x403b, 0x6356, 0x402b, 0x6357, 0x6358, 0x6359, 0x635a, 0x635b, 0x3837, 0x5a62, 0x3653, 0x5a64, 0x5a63, 0x5a66, 0x486e, 0x5a65, 0x3740, 0x5174, 0x5275, 0x5573, 0x3d57, 0x5768, 0x5a68, 0x5a67, 0x3022, 0x4d53, 0x5a69, 0x383d, 0x3c4a, 0x423d, 0x4224, 0x3342, 0x5a6a, 0x422a, 0x4430, 0x3d35, 0x4f5e, 0x5a6b, 0x4942, 0x315d, 0x5a6c, 0x3638, 0x543a, 0x337d, 0x5a6d, 0x5449, 0x4f55, 0x4563, 0x5a6e, 0x5a6f, 0x5a70, 0x416a, 0x4c55, 0x4f5d, 0x5367, 0x4221, 0x5a71, 0x4b65, 0x5a72, 0x4b66, 0x527e, 0x3874, 0x5a73, 0x302f, 0x4f36, 0x554f, 0x4b6d, 0x5a74, 0x6344, 0x4125, 0x763f, 0x7640, 0x7641, 0x4451, 0x4838, 0x5163, 0x505b, 0x5145, 0x3c2f, 0x394d, 0x6f74, 0x3446, 0x533a, 0x7642, 0x337b, 0x7643, 0x3571, 0x7645, 0x536a, 0x7627, 0x5129, 0x7629, 0x7628, 0x4163, 0x4057, 0x3122, 0x4e6d, 0x5068, 0x762b, 0x4f76, 0x762a, 0x5570, 0x762c, 0x4339, 0x3b74, 0x762e, 0x762d, 0x445e, 0x4158, 0x4b2a, 0x4f3c, 0x762f, 0x7630, 0x7631, 0x4236, 0x3054, 0x4579, 0x7632, 0x4760, 0x7626, 0x3e38, 0x3e32, 0x3565, 0x3747, 0x3f3f, 0x4352, 0x4366, 0x584c, 0x386f, 0x3d79, 0x5125, 0x3050, 0x7730, 0x7731, 0x502c, 0x3030, 0x7732, 0x7733, 0x7734, 0x474a, 0x3e4f, 0x7737, 0x7736, 0x315e, 0x7735, 0x7738, 0x7739, 0x4e24, 0x484d, 0x3a2b, 0x6838, 0x6839, 0x683a, 0x3e42, 0x5274, 0x544f, 0x4958, 0x5233, 0x3625, 0x476a, 0x717c, 0x4f6e, 0x4b33, 0x506b, 0x676f, 0x4d67, 0x394b, 0x3659, 0x717d, 0x3064, 0x4b4c, 0x717e, 0x5424, 0x422d, 0x416c, 0x4644, 0x3e31, 0x7221, 0x3c55, 0x7222, 0x7223, 0x7224, 0x5243, 0x4635, 0x4d47, 0x7225, 0x5331, 0x3f45, 0x4c62, 0x7226, 0x7227, 0x5155, 0x366e, 0x7228, 0x7229, 0x355f, 0x722a, 0x722b, 0x327c, 0x722c, 0x722d, 0x4827, 0x3767, 0x6c29, 0x6c2a, 0x6c2b, 0x6c2c, 0x462e, 0x6c2d, 0x6c2e, 0x3749, 0x4a33, 0x6238, 0x774f, 0x7750, 0x324d, 0x7751, 0x7753, 0x7752, 0x623b, 0x3c22, 0x623c, 0x623d, 0x623e, 0x623f, 0x6240, 0x6241, 0x3739, 0x527b, 0x3d24, 0x4a4e, 0x3125, 0x4b47, 0x6242, 0x367c, 0x4844, 0x6243, 0x3d48, 0x317d, 0x6244, 0x3676, 0x6245, 0x4459, 0x6246, 0x4f5a, 0x395d, 0x6247, 0x4021, 0x6248, 0x3276, 0x6249, 0x4173, 0x624a, 0x624b, 0x4278, 0x624c, 0x624d, 0x624e, 0x4a57, 0x5838, 0x5965, 0x4f63, 0x7025, 0x5c30, 0x426d, 0x5426, 0x4d54, 0x5131, 0x335b, 0x477d, 0x3235, 0x423f, 0x6660, 0x4a3b, 0x6661, 0x6662, 0x3e54, 0x6663, 0x5724, 0x4d55, 0x6665, 0x3c5d, 0x6664, 0x6666, 0x6667, 0x426e, 0x3d3e, 0x6668, 0x4266, 0x3a27, 0x6669, 0x666a, 0x3352, 0x5169, 0x3f25, 0x666b, 0x466f, 0x666c, 0x666d, 0x666e, 0x462d, 0x666f, 0x4927, 0x6670, 0x6671, 0x6672, 0x6539, 0x6673, 0x6674, 0x4262, 0x6675, 0x6676, 0x5668, 0x6677, 0x6678, 0x3947, 0x773b, 0x773a, 0x773e, 0x773c, 0x3a21, 0x773f, 0x7740, 0x7742, 0x7741, 0x7744, 0x7743, 0x7745, 0x7746, 0x7747, 0x4b68, 0x385f, 0x7754, 0x7755, 0x7756, 0x7758, 0x775a, 0x7757, 0x775b, 0x7759, 0x5757, 0x775c, 0x775d, 0x775e, 0x775f, 0x7760, 0x5b4b, 0x582a, 0x6577, 0x396d, 0x3f7d, 0x3b6a, 0x7749, 0x4647, 0x7748, 0x774a, 0x774c, 0x774b, 0x774d, 0x4e3a, 0x774e, 0x4427, 0x5363, 0x764f, 0x4233, 0x7650, 0x7651, 0x7652, 0x7653, 0x7654, 0x7656, 0x312b, 0x7657, 0x7658, 0x7659, 0x765a, 0x765b, 0x765c, 0x765d, 0x765e, 0x4f4a, 0x765f, 0x7660, 0x7661, 0x7662, 0x7663, 0x7664, 0x4070, 0x7665, 0x7666, 0x7667, 0x7668, 0x7669, 0x766a, 0x766b, 0x766c, 0x766d, 0x766e, 0x766f, 0x7670, 0x7671, 0x7672, 0x7673, 0x7674, 0x3e28, 0x7675, 0x7676, 0x7677, 0x7678, 0x487a, 0x7679, 0x767a, 0x767b, 0x767c, 0x767d, 0x767e, 0x7721, 0x7722, 0x7723, 0x7724, 0x7725, 0x7726, 0x7727, 0x7728, 0x316e, 0x7729, 0x772a, 0x772b, 0x772c, 0x772d, 0x415b, 0x772e, 0x772f, 0x4471, 0x702f, 0x3c26, 0x7030, 0x4379, 0x4538, 0x513b, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x513c, 0x516c, 0x7037, 0x7036, 0x5427, 0x4d52, 0x7038, 0x703a, 0x7039, 0x703b, 0x703c, 0x386b, 0x703d, 0x3a68, 0x703e, 0x703f, 0x3e69, 0x7040, 0x366c, 0x7041, 0x7042, 0x7043, 0x7044, 0x4835, 0x7045, 0x7046, 0x7047, 0x4574, 0x7048, 0x7049, 0x704a, 0x773d, 0x704b, 0x704c, 0x704d, 0x704e, 0x704f, 0x3a57, 0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7058, 0x5325, 0x7057, 0x7059, 0x753a, 0x4239, 0x7764, 0x7765, 0x7766, 0x7767, 0x7768, 0x4234, 0x776a, 0x776b, 0x4273, 0x7470, 0x746f, 0x4269, 0x7761, 0x7762, 0x3b46, 0x5964, 0x4a72, 0x4068, 0x7024, 0x3a5a, 0x472d, 0x442c, 0x776c, 0x776d, 0x776e, 0x7770, 0x776f, 0x7771, 0x7774, 0x7773, 0x7772, 0x7775, 0x7776, 0x6d69, 0x6d6a, 0x6d6b, 0x763c, 0x763d, 0x763e, 0x3626, 0x583e, 0x3944, 0x583b, 0x5c31, 0x4a73, 0x7777, 0x7778, 0x7779, 0x777b, 0x777a, 0x3147, 0x777c, 0x777d, 0x777e, 0x466b, 0x6c34, 0x335d, 0x7633, 0x7634, 0x4164, 0x7635, 0x7636, 0x7637, 0x7638, 0x7639, 0x763a, 0x4823, 0x763b, 0x417a, 0x3928, 0x6d68, 0x396a, 0x595f, 0x2321, 0x2322, 0x2323, 0x2167, 0x2325, 0x2326, 0x2327, 0x2328, 0x2329, 0x232a, 0x232b, 0x232c, 0x232d, 0x232e, 0x232f, 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337, 0x2338, 0x2339, 0x233a, 0x233b, 0x233c, 0x233d, 0x233e, 0x233f, 0x2340, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347, 0x2348, 0x2349, 0x234a, 0x234b, 0x234c, 0x234d, 0x234e, 0x234f, 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357, 0x2358, 0x2359, 0x235a, 0x235b, 0x235c, 0x235d, 0x235e, 0x235f, 0x2360, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367, 0x2368, 0x2369, 0x236a, 0x236b, 0x236c, 0x236d, 0x236e, 0x236f, 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377, 0x2378, 0x2379, 0x237a, 0x237b, 0x237c, 0x237d, 0x212b, 0x2169, 0x216a, 0x237e, 0x2324, }; static const Summary16 gb2312_uni2indx_page00[70] = { /* 0x0000 */ { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0190 }, { 3, 0x0003 }, { 5, 0x0000 }, { 5, 0x0080 }, { 6, 0x3703 }, { 13, 0x168c }, /* 0x0100 */ { 19, 0x0002 }, { 20, 0x0808 }, { 22, 0x0800 }, { 23, 0x0000 }, { 23, 0x2000 }, { 24, 0x0000 }, { 24, 0x0800 }, { 25, 0x0000 }, { 25, 0x0000 }, { 25, 0x0000 }, { 25, 0x0000 }, { 25, 0x0000 }, { 25, 0x4000 }, { 26, 0x1555 }, { 33, 0x0000 }, { 33, 0x0000 }, /* 0x0200 */ { 33, 0x0000 }, { 33, 0x0000 }, { 33, 0x0000 }, { 33, 0x0000 }, { 33, 0x0000 }, { 33, 0x0000 }, { 33, 0x0000 }, { 33, 0x0000 }, { 33, 0x0000 }, { 33, 0x0000 }, { 33, 0x0000 }, { 33, 0x0000 }, { 33, 0x0280 }, { 35, 0x0000 }, { 35, 0x0000 }, { 35, 0x0000 }, /* 0x0300 */ { 35, 0x0000 }, { 35, 0x0000 }, { 35, 0x0000 }, { 35, 0x0000 }, { 35, 0x0000 }, { 35, 0x0000 }, { 35, 0x0000 }, { 35, 0x0000 }, { 35, 0x0000 }, { 35, 0xfffe }, { 50, 0x03fb }, { 59, 0xfffe }, { 74, 0x03fb }, { 83, 0x0000 }, { 83, 0x0000 }, { 83, 0x0000 }, /* 0x0400 */ { 83, 0x0002 }, { 84, 0xffff }, { 100, 0xffff }, { 116, 0xffff }, { 132, 0xffff }, { 148, 0x0002 }, }; static const Summary16 gb2312_uni2indx_page20[101] = { /* 0x2000 */ { 149, 0x0000 }, { 149, 0x3360 }, { 155, 0x0040 }, { 156, 0x080d }, { 160, 0x0000 }, { 160, 0x0000 }, { 160, 0x0000 }, { 160, 0x0000 }, { 160, 0x0000 }, { 160, 0x0000 }, { 160, 0x0000 }, { 160, 0x0000 }, { 160, 0x0000 }, { 160, 0x0000 }, { 160, 0x0000 }, { 160, 0x0000 }, /* 0x2100 */ { 160, 0x0008 }, { 161, 0x0040 }, { 162, 0x0000 }, { 162, 0x0000 }, { 162, 0x0000 }, { 162, 0x0000 }, { 162, 0x0fff }, { 174, 0x0000 }, { 174, 0x0000 }, { 174, 0x000f }, { 178, 0x0000 }, { 178, 0x0000 }, { 178, 0x0000 }, { 178, 0x0000 }, { 178, 0x0000 }, { 178, 0x0000 }, /* 0x2200 */ { 178, 0x8100 }, { 180, 0x6402 }, { 184, 0x4fa1 }, { 192, 0x20f0 }, { 197, 0x1100 }, { 199, 0x0000 }, { 199, 0xc033 }, { 205, 0x0000 }, { 205, 0x0000 }, { 205, 0x0200 }, { 206, 0x0020 }, { 207, 0x0000 }, { 207, 0x0000 }, { 207, 0x0000 }, { 207, 0x0000 }, { 207, 0x0000 }, /* 0x2300 */ { 207, 0x0000 }, { 207, 0x0004 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, /* 0x2400 */ { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x0000 }, { 208, 0x03ff }, { 218, 0xfff0 }, { 230, 0xffff }, { 246, 0x0fff }, { 258, 0x0000 }, { 258, 0x0000 }, { 258, 0x0000 }, { 258, 0x0000 }, { 258, 0x0000 }, { 258, 0x0000 }, /* 0x2500 */ { 258, 0xffff }, { 274, 0xffff }, { 290, 0xffff }, { 306, 0xffff }, { 322, 0x0fff }, { 334, 0x0000 }, { 334, 0x0000 }, { 334, 0x0000 }, { 334, 0x0000 }, { 334, 0x0000 }, { 334, 0x0003 }, { 336, 0x000c }, { 338, 0xc8c0 }, { 343, 0x0000 }, { 343, 0x0000 }, { 343, 0x0000 }, /* 0x2600 */ { 343, 0x0060 }, { 345, 0x0000 }, { 345, 0x0000 }, { 345, 0x0000 }, { 345, 0x0005 }, }; static const Summary16 gb2312_uni2indx_page30[35] = { /* 0x3000 */ { 347, 0xff2f }, { 360, 0x00fb }, { 367, 0x0000 }, { 367, 0x0000 }, { 367, 0xfffe }, { 382, 0xffff }, { 398, 0xffff }, { 414, 0xffff }, { 430, 0xffff }, { 446, 0x000f }, { 450, 0xfffe }, { 465, 0xffff }, { 481, 0xffff }, { 497, 0xffff }, { 513, 0xffff }, { 529, 0x087f }, /* 0x3100 */ { 537, 0xffe0 }, { 548, 0xffff }, { 564, 0x03ff }, { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x0000 }, /* 0x3200 */ { 574, 0x0000 }, { 574, 0x0000 }, { 574, 0x03ff }, }; static const Summary16 gb2312_uni2indx_page4e[1263] = { /* 0x4e00 */ { 584, 0x7f8b }, { 595, 0x7f7b }, { 608, 0x3db4 }, { 617, 0xef55 }, { 628, 0xfba8 }, { 638, 0xf35d }, { 649, 0x0243 }, { 653, 0x400b }, { 657, 0xfb40 }, { 665, 0x8d3e }, { 674, 0x7bf7 }, { 687, 0x8c2c }, { 693, 0x6eff }, { 706, 0xe3fa }, { 717, 0x1d3a }, { 725, 0xa8ed }, /* 0x4f00 */ { 734, 0xe602 }, { 740, 0xcf83 }, { 749, 0x8cf5 }, { 758, 0x3555 }, { 766, 0xe048 }, { 771, 0xffab }, { 784, 0x92b9 }, { 792, 0xd859 }, { 800, 0xab18 }, { 807, 0x2892 }, { 812, 0xd7e9 }, { 823, 0x8020 }, { 825, 0xc438 }, { 831, 0xf583 }, { 840, 0xe74a }, { 849, 0x450a }, /* 0x5000 */ { 854, 0xb000 }, { 857, 0x9714 }, { 864, 0x7762 }, { 873, 0x5400 }, { 876, 0xd188 }, { 882, 0x1420 }, { 885, 0x1020 }, { 887, 0xc8c0 }, { 892, 0x2121 }, { 896, 0x0000 }, { 896, 0x13a8 }, { 902, 0x0c04 }, { 905, 0x8000 }, { 906, 0x0440 }, { 908, 0x70c0 }, { 913, 0x0828 }, /* 0x5100 */ { 916, 0x08c0 }, { 919, 0x0004 }, { 920, 0x0002 }, { 921, 0x8000 }, { 922, 0x2b7b }, { 932, 0x1472 }, { 938, 0x7924 }, { 945, 0x3bfb }, { 957, 0x3327 }, { 965, 0x1ae4 }, { 972, 0x9835 }, { 979, 0x38ef }, { 989, 0x9ad1 }, { 997, 0x2802 }, { 1000, 0xa813 }, { 1006, 0xbf69 }, /* 0x5200 */ { 1017, 0x65cf }, { 1027, 0x2fc6 }, { 1036, 0x6b11 }, { 1043, 0xafc9 }, { 1053, 0x340f }, { 1060, 0x5053 }, { 1066, 0x86a2 }, { 1072, 0xa004 }, { 1075, 0x0106 }, { 1078, 0xe809 }, { 1084, 0x3f0f }, { 1094, 0xc00e }, { 1099, 0x0a88 }, { 1103, 0x8145 }, { 1108, 0x0010 }, { 1109, 0xc601 }, /* 0x5300 */ { 1114, 0xa161 }, { 1120, 0x26e1 }, { 1127, 0x444b }, { 1133, 0xce00 }, { 1138, 0xc7aa }, { 1147, 0xd4ee }, { 1157, 0xcadf }, { 1168, 0x85bb }, { 1177, 0x3a74 }, { 1185, 0xa520 }, { 1190, 0x436c }, { 1197, 0x8840 }, { 1200, 0x3f06 }, { 1208, 0x8bd2 }, { 1216, 0xff79 }, { 1229, 0x3bef }, /* 0x5400 */ { 1241, 0xf75a }, { 1252, 0xe8ef }, { 1263, 0xfbcb }, { 1275, 0x5b36 }, { 1284, 0x0d49 }, { 1290, 0x1bfd }, { 1301, 0x0154 }, { 1305, 0x39ee }, { 1315, 0xd855 }, { 1323, 0x2e75 }, { 1332, 0xbfd8 }, { 1343, 0xa91a }, { 1350, 0xf3d7 }, { 1362, 0xf6bf }, { 1375, 0x67e0 }, { 1383, 0xb40c }, /* 0x5500 */ { 1389, 0x82c2 }, { 1394, 0x0813 }, { 1398, 0xd49d }, { 1407, 0xd08b }, { 1414, 0x065a }, { 1420, 0x1061 }, { 1424, 0x74f2 }, { 1433, 0x59e0 }, { 1440, 0x8f9f }, { 1451, 0xb312 }, { 1458, 0x0080 }, { 1459, 0x6aaa }, { 1467, 0x3230 }, { 1472, 0xb05e }, { 1480, 0x9d7a }, { 1490, 0x60ac }, /* 0x5600 */ { 1496, 0xd303 }, { 1503, 0xc900 }, { 1507, 0x3098 }, { 1512, 0x8a56 }, { 1519, 0x7000 }, { 1522, 0x1390 }, { 1527, 0x1f14 }, { 1534, 0x1842 }, { 1538, 0xc060 }, { 1542, 0x0008 }, { 1543, 0x8008 }, { 1545, 0x1080 }, { 1547, 0x0400 }, { 1548, 0xec90 }, { 1555, 0x2817 }, { 1561, 0xe633 }, /* 0x5700 */ { 1570, 0x0758 }, { 1576, 0x9000 }, { 1578, 0xf708 }, { 1586, 0x4e09 }, { 1592, 0xf485 }, { 1600, 0xfc83 }, { 1609, 0xaf53 }, { 1619, 0x18c8 }, { 1624, 0x187c }, { 1631, 0x080c }, { 1634, 0x6adf }, { 1645, 0x0114 }, { 1648, 0xc80c }, { 1653, 0xa734 }, { 1661, 0xa011 }, { 1665, 0x2710 }, /* 0x5800 */ { 1670, 0x28c5 }, { 1676, 0x4222 }, { 1680, 0x0413 }, { 1684, 0x0021 }, { 1686, 0x3010 }, { 1689, 0x4112 }, { 1693, 0x1820 }, { 1696, 0x4000 }, { 1697, 0x022b }, { 1702, 0xc60c }, { 1708, 0x0300 }, { 1710, 0x1000 }, { 1711, 0x0022 }, { 1713, 0x0022 }, { 1715, 0x5810 }, { 1719, 0x0249 }, /* 0x5900 */ { 1723, 0xa094 }, { 1728, 0x9670 }, { 1735, 0xeeb0 }, { 1744, 0x1792 }, { 1751, 0xcb96 }, { 1760, 0x05f2 }, { 1767, 0x0025 }, { 1770, 0x2358 }, { 1776, 0x25de }, { 1785, 0x42cc }, { 1791, 0xcf38 }, { 1800, 0x4a04 }, { 1804, 0x0c40 }, { 1807, 0x359f }, { 1817, 0x1128 }, { 1821, 0x8a00 }, /* 0x5a00 */ { 1824, 0x13fa }, { 1833, 0x910a }, { 1838, 0x0229 }, { 1842, 0x1056 }, { 1847, 0x0641 }, { 1851, 0x0420 }, { 1853, 0x0484 }, { 1856, 0x84f0 }, { 1862, 0x0000 }, { 1862, 0x0c04 }, { 1865, 0x0400 }, { 1866, 0x412c }, { 1871, 0x1206 }, { 1875, 0x1154 }, { 1880, 0x0a4b }, { 1886, 0x0002 }, /* 0x5b00 */ { 1887, 0x0200 }, { 1888, 0x00c0 }, { 1890, 0x0000 }, { 1890, 0x0094 }, { 1893, 0x0001 }, { 1894, 0xbfbb }, { 1907, 0x167c }, { 1915, 0x242b }, { 1921, 0x9bbb }, { 1932, 0x7fa8 }, { 1942, 0x0c7f }, { 1951, 0xe379 }, { 1961, 0x10f4 }, { 1967, 0xe00d }, { 1973, 0x4132 }, { 1978, 0x9f01 }, /* 0x5c00 */ { 1985, 0x8652 }, { 1991, 0x3572 }, { 1999, 0x10b4 }, { 2004, 0xff12 }, { 2014, 0xcf27 }, { 2024, 0x4223 }, { 2029, 0xc06b }, { 2036, 0x8602 }, { 2040, 0x3106 }, { 2045, 0x1fd3 }, { 2055, 0x3a0c }, { 2061, 0xa1aa }, { 2068, 0x0812 }, { 2071, 0x0204 }, { 2073, 0x2572 }, { 2080, 0x0801 }, /* 0x5d00 */ { 2082, 0x40cc }, { 2087, 0x4850 }, { 2091, 0x62d0 }, { 2097, 0x6010 }, { 2100, 0x1c80 }, { 2104, 0x2900 }, { 2107, 0x9a00 }, { 2111, 0x0010 }, { 2112, 0x0004 }, { 2113, 0x2200 }, { 2115, 0x0000 }, { 2115, 0x0080 }, { 2116, 0x2020 }, { 2118, 0x6800 }, { 2121, 0xcbe6 }, { 2131, 0x609e }, /* 0x5e00 */ { 2138, 0x916e }, { 2146, 0x3f73 }, { 2157, 0x60c0 }, { 2161, 0x3982 }, { 2167, 0x1034 }, { 2171, 0x4830 }, { 2175, 0x0006 }, { 2177, 0xbd5c }, { 2187, 0x8cd1 }, { 2194, 0xd6fb }, { 2206, 0x20e1 }, { 2211, 0x43e8 }, { 2218, 0x0600 }, { 2220, 0x084e }, { 2225, 0x0500 }, { 2227, 0xc4d0 }, /* 0x5f00 */ { 2233, 0x8d1f }, { 2242, 0x89aa }, { 2249, 0xa6e1 }, { 2257, 0x1602 }, { 2261, 0x0001 }, { 2262, 0x21ed }, { 2270, 0x3656 }, { 2278, 0x1a8b }, { 2285, 0x1fb7 }, { 2296, 0x13a5 }, { 2303, 0x6502 }, { 2308, 0x30a0 }, { 2312, 0xb278 }, { 2320, 0x23c7 }, { 2328, 0x6c93 }, { 2336, 0xe922 }, /* 0x6000 */ { 2343, 0xe47f }, { 2354, 0x3a74 }, { 2362, 0x8fe3 }, { 2372, 0x9820 }, { 2376, 0x280e }, { 2381, 0x2625 }, { 2387, 0xbf9c }, { 2398, 0xbf49 }, { 2408, 0x3218 }, { 2413, 0xac54 }, { 2420, 0xb949 }, { 2428, 0x1916 }, { 2434, 0x0c60 }, { 2438, 0xb522 }, { 2445, 0xfbc1 }, { 2455, 0x0659 }, /* 0x6100 */ { 2461, 0xe343 }, { 2469, 0x8420 }, { 2472, 0x08d9 }, { 2478, 0x8000 }, { 2479, 0x5500 }, { 2483, 0x2022 }, { 2486, 0x0184 }, { 2489, 0x00a1 }, { 2492, 0x4800 }, { 2494, 0x2010 }, { 2496, 0x1380 }, { 2500, 0x4080 }, { 2502, 0x0d04 }, { 2506, 0x0016 }, { 2509, 0x0040 }, { 2510, 0x8020 }, /* 0x6200 */ { 2512, 0xfd40 }, { 2520, 0x8de7 }, { 2530, 0x5436 }, { 2537, 0xe098 }, { 2543, 0x7b8b }, { 2553, 0x091e }, { 2559, 0xfec8 }, { 2569, 0xd249 }, { 2576, 0x0611 }, { 2580, 0x8dee }, { 2590, 0x1937 }, { 2598, 0xba22 }, { 2605, 0x77f4 }, { 2616, 0x9fdd }, { 2628, 0xf3ec }, { 2639, 0xf0da }, /* 0x6300 */ { 2648, 0x4386 }, { 2654, 0xec42 }, { 2661, 0x8d3f }, { 2671, 0x2604 }, { 2675, 0xfa6c }, { 2685, 0xc021 }, { 2689, 0x628e }, { 2696, 0x0cc2 }, { 2701, 0xd785 }, { 2710, 0x0145 }, { 2714, 0x77ad }, { 2725, 0x5599 }, { 2733, 0xe250 }, { 2739, 0x4045 }, { 2743, 0x260b }, { 2749, 0xa154 }, /* 0x6400 */ { 2755, 0x9827 }, { 2762, 0x5819 }, { 2768, 0x3443 }, { 2774, 0xa410 }, { 2778, 0x05f2 }, { 2785, 0x4114 }, { 2789, 0x2280 }, { 2792, 0x0700 }, { 2795, 0x00b4 }, { 2799, 0x4266 }, { 2805, 0x7210 }, { 2810, 0x15a1 }, { 2816, 0x6025 }, { 2821, 0x4185 }, { 2826, 0x0054 }, { 2829, 0x0000 }, /* 0x6500 */ { 2829, 0x0201 }, { 2831, 0x0104 }, { 2833, 0xc820 }, { 2837, 0xcb70 }, { 2845, 0x9320 }, { 2850, 0x6a62 }, { 2857, 0x184c }, { 2862, 0x0095 }, { 2866, 0x1880 }, { 2869, 0x9a8b }, { 2877, 0xaab2 }, { 2885, 0x3201 }, { 2889, 0xd87a }, { 2898, 0x00c4 }, { 2901, 0xf3e5 }, { 2912, 0x04c3 }, /* 0x6600 */ { 2917, 0xd44d }, { 2925, 0xa238 }, { 2931, 0xa1a1 }, { 2937, 0x5072 }, { 2943, 0x980a }, { 2948, 0x84fc }, { 2956, 0xc152 }, { 2962, 0x44d1 }, { 2968, 0x1094 }, { 2972, 0x20c2 }, { 2976, 0x4180 }, { 2979, 0x4210 }, { 2982, 0x0000 }, { 2982, 0x3a00 }, { 2986, 0x0240 }, { 2988, 0xd29d }, /* 0x6700 */ { 2997, 0x2f01 }, { 3003, 0xa8b1 }, { 3010, 0xbd40 }, { 3017, 0x2432 }, { 3022, 0xd34d }, { 3031, 0xd04b }, { 3038, 0xa723 }, { 3046, 0xd0ad }, { 3054, 0x0a92 }, { 3059, 0x75a1 }, { 3067, 0xadac }, { 3076, 0x01e9 }, { 3082, 0x801a }, { 3086, 0x771f }, { 3097, 0x9225 }, { 3103, 0xa01b }, /* 0x6800 */ { 3109, 0xdfa1 }, { 3119, 0x20ca }, { 3124, 0x0602 }, { 3127, 0x738c }, { 3135, 0x577f }, { 3147, 0x003b }, { 3152, 0x0bff }, { 3163, 0x00d0 }, { 3166, 0x806a }, { 3171, 0x0088 }, { 3173, 0xa1c4 }, { 3179, 0x0029 }, { 3182, 0x2a05 }, { 3187, 0x0524 }, { 3191, 0x4009 }, { 3194, 0x1623 }, /* 0x6900 */ { 3200, 0x6822 }, { 3205, 0x8005 }, { 3208, 0x2011 }, { 3211, 0xa211 }, { 3216, 0x0004 }, { 3217, 0x6490 }, { 3222, 0x4849 }, { 3227, 0x1382 }, { 3232, 0x23d5 }, { 3240, 0x1930 }, { 3245, 0x2980 }, { 3249, 0x0892 }, { 3253, 0x5402 }, { 3257, 0x8811 }, { 3261, 0x2001 }, { 3263, 0xa004 }, /* 0x6a00 */ { 3266, 0x0400 }, { 3267, 0x8180 }, { 3270, 0x8502 }, { 3274, 0x6022 }, { 3278, 0x0090 }, { 3280, 0x0b01 }, { 3284, 0x0022 }, { 3286, 0x1202 }, { 3289, 0x4011 }, { 3292, 0x0083 }, { 3295, 0x1a01 }, { 3299, 0x0000 }, { 3299, 0x0000 }, { 3299, 0x0000 }, { 3299, 0x0000 }, { 3299, 0x0000 }, /* 0x6b00 */ { 3299, 0x0000 }, { 3299, 0x0000 }, { 3299, 0x009f }, { 3305, 0x4684 }, { 3310, 0x12c8 }, { 3315, 0x0200 }, { 3316, 0x04fc }, { 3323, 0x1a00 }, { 3326, 0x2ede }, { 3336, 0x0c4c }, { 3341, 0x0402 }, { 3343, 0x80b8 }, { 3348, 0xa826 }, { 3354, 0x0afc }, { 3362, 0x8c02 }, { 3366, 0x2228 }, /* 0x6c00 */ { 3370, 0xa0e0 }, { 3375, 0x8f7b }, { 3386, 0xc7d6 }, { 3396, 0x2135 }, { 3402, 0x06c7 }, { 3409, 0xf8b1 }, { 3418, 0x0713 }, { 3424, 0x6255 }, { 3431, 0x936e }, { 3440, 0x8a19 }, { 3446, 0x6efa }, { 3457, 0xfb0e }, { 3467, 0x1630 }, { 3472, 0x48f9 }, { 3480, 0xcd2f }, { 3490, 0x7deb }, /* 0x6d00 */ { 3502, 0x5892 }, { 3508, 0x4e84 }, { 3514, 0x4ca0 }, { 3519, 0x7a2e }, { 3528, 0xedea }, { 3539, 0x561e }, { 3547, 0xc649 }, { 3554, 0x1190 }, { 3558, 0x5324 }, { 3564, 0xe83a }, { 3572, 0xcfdb }, { 3584, 0x8124 }, { 3588, 0x18f1 }, { 3595, 0x6342 }, { 3601, 0x5853 }, { 3608, 0x1a8a }, /* 0x6e00 */ { 3614, 0x7420 }, { 3619, 0x24d3 }, { 3626, 0xaa3b }, { 3635, 0x0514 }, { 3639, 0x6018 }, { 3643, 0x8958 }, { 3649, 0x4800 }, { 3651, 0xc000 }, { 3653, 0x8268 }, { 3658, 0x9101 }, { 3662, 0x84a4 }, { 3667, 0x2cd6 }, { 3675, 0x8886 }, { 3680, 0xc4ba }, { 3688, 0x0377 }, { 3696, 0x0210 }, /* 0x6f00 */ { 3698, 0x8244 }, { 3702, 0x0038 }, { 3705, 0xae11 }, { 3712, 0x404a }, { 3716, 0x28c0 }, { 3720, 0x5100 }, { 3723, 0x6044 }, { 3727, 0x1514 }, { 3732, 0x7310 }, { 3738, 0x1000 }, { 3739, 0x0082 }, { 3741, 0x0248 }, { 3744, 0x0205 }, { 3747, 0x4006 }, { 3750, 0xc003 }, { 3754, 0x0000 }, /* 0x7000 */ { 3754, 0x0000 }, { 3754, 0x0c02 }, { 3757, 0x0008 }, { 3758, 0x0220 }, { 3760, 0x9000 }, { 3762, 0x4000 }, { 3763, 0xb800 }, { 3767, 0xd161 }, { 3774, 0x4621 }, { 3779, 0x3274 }, { 3786, 0xf800 }, { 3791, 0x3b8a }, { 3799, 0x050f }, { 3805, 0x8b00 }, { 3809, 0xbbd0 }, { 3818, 0x2280 }, /* 0x7100 */ { 3821, 0x0600 }, { 3823, 0x0769 }, { 3830, 0x8040 }, { 3832, 0x0043 }, { 3835, 0x5420 }, { 3839, 0x5000 }, { 3841, 0x41d0 }, { 3846, 0x250c }, { 3851, 0x8410 }, { 3854, 0x8310 }, { 3858, 0x1101 }, { 3861, 0x0228 }, { 3864, 0x4008 }, { 3866, 0x0030 }, { 3868, 0x40a1 }, { 3872, 0x0200 }, /* 0x7200 */ { 3873, 0x0040 }, { 3874, 0x2000 }, { 3875, 0x1500 }, { 3878, 0xabe3 }, { 3888, 0x3180 }, { 3892, 0xaa44 }, { 3898, 0xc2c6 }, { 3905, 0xc624 }, { 3911, 0xac13 }, { 3918, 0x8004 }, { 3920, 0xb000 }, { 3923, 0x03d1 }, { 3929, 0x611e }, { 3936, 0x4285 }, { 3941, 0xf303 }, { 3949, 0x1d9f }, /* 0x7300 */ { 3959, 0x440a }, { 3963, 0x78e8 }, { 3971, 0x5e26 }, { 3979, 0xc392 }, { 3986, 0x2000 }, { 3987, 0x0085 }, { 3990, 0xb001 }, { 3994, 0x4000 }, { 3995, 0x4a90 }, { 4000, 0x8842 }, { 4004, 0xca04 }, { 4009, 0x0c8d }, { 4015, 0xa705 }, { 4022, 0x4203 }, { 4026, 0x22a1 }, { 4031, 0x0004 }, /* 0x7400 */ { 4032, 0x8668 }, { 4038, 0x0c01 }, { 4041, 0x5564 }, { 4048, 0x1079 }, { 4054, 0x0002 }, { 4055, 0xdea0 }, { 4063, 0x2000 }, { 4064, 0x40c1 }, { 4068, 0x488b }, { 4074, 0x5001 }, { 4077, 0x0380 }, { 4080, 0x0400 }, { 4081, 0x0000 }, { 4081, 0x5004 }, { 4084, 0xc05d }, { 4091, 0x80d0 }, /* 0x7500 */ { 4095, 0xa010 }, { 4098, 0x970a }, { 4105, 0xbb20 }, { 4112, 0x4daf }, { 4122, 0xd921 }, { 4129, 0x1e10 }, { 4134, 0x0460 }, { 4137, 0x8314 }, { 4142, 0x8848 }, { 4146, 0xa6d6 }, { 4155, 0xd83b }, { 4164, 0x733f }, { 4175, 0x27bc }, { 4184, 0x4974 }, { 4191, 0x0ddc }, { 4199, 0x9213 }, /* 0x7600 */ { 4205, 0x142b }, { 4211, 0x8ba1 }, { 4218, 0x2e75 }, { 4227, 0xd139 }, { 4235, 0x3009 }, { 4239, 0x5050 }, { 4243, 0x8808 }, { 4246, 0x6900 }, { 4250, 0x49d4 }, { 4257, 0x024a }, { 4261, 0x4010 }, { 4263, 0x8016 }, { 4267, 0xe564 }, { 4275, 0x89d7 }, { 4284, 0xc020 }, { 4287, 0x5316 }, /* 0x7700 */ { 4294, 0x2b92 }, { 4301, 0x8600 }, { 4304, 0xa345 }, { 4311, 0x15e0 }, { 4317, 0x008b }, { 4321, 0x0c03 }, { 4325, 0x196e }, { 4333, 0xe200 }, { 4337, 0x7031 }, { 4343, 0x8006 }, { 4346, 0x16a5 }, { 4353, 0xa829 }, { 4359, 0x2000 }, { 4360, 0x1880 }, { 4363, 0x7aac }, { 4372, 0xe148 }, /* 0x7800 */ { 4378, 0x3207 }, { 4384, 0xb5d6 }, { 4394, 0x32e8 }, { 4401, 0x5f91 }, { 4410, 0x50a1 }, { 4415, 0x20e5 }, { 4421, 0x7c00 }, { 4426, 0x1080 }, { 4428, 0x7280 }, { 4433, 0x9d8a }, { 4441, 0x00aa }, { 4445, 0x421f }, { 4452, 0x0e22 }, { 4457, 0x0231 }, { 4461, 0x1100 }, { 4463, 0x0494 }, /* 0x7900 */ { 4467, 0x0022 }, { 4469, 0x4008 }, { 4471, 0x0010 }, { 4472, 0x5c10 }, { 4477, 0x0343 }, { 4482, 0xfcc8 }, { 4491, 0xa1a5 }, { 4498, 0x0580 }, { 4501, 0x8433 }, { 4507, 0x0400 }, { 4508, 0x0080 }, { 4509, 0x6e08 }, { 4515, 0x2a4b }, { 4522, 0x8126 }, { 4527, 0xaad8 }, { 4535, 0x2901 }, /* 0x7a00 */ { 4539, 0x684d }, { 4546, 0x4490 }, { 4550, 0x0009 }, { 4552, 0xba88 }, { 4559, 0x0040 }, { 4560, 0x0082 }, { 4562, 0x0000 }, { 4562, 0x87d1 }, { 4570, 0x215b }, { 4577, 0xb1e6 }, { 4586, 0x3161 }, { 4592, 0x8008 }, { 4594, 0x0800 }, { 4595, 0xc240 }, { 4599, 0xa069 }, { 4605, 0xa600 }, /* 0x7b00 */ { 4609, 0x8d58 }, { 4616, 0x4a32 }, { 4622, 0x5d71 }, { 4631, 0x550a }, { 4637, 0x9aa0 }, { 4643, 0x2d57 }, { 4652, 0x4005 }, { 4655, 0x4aa6 }, { 4662, 0x2021 }, { 4665, 0x30b1 }, { 4671, 0x3fc6 }, { 4681, 0x0112 }, { 4684, 0x10c2 }, { 4688, 0x260a }, { 4693, 0x4462 }, { 4698, 0x5082 }, /* 0x7c00 */ { 4702, 0x9880 }, { 4706, 0x8040 }, { 4708, 0x04c0 }, { 4711, 0x8100 }, { 4713, 0x2003 }, { 4716, 0x0000 }, { 4716, 0x0000 }, { 4716, 0x3818 }, { 4721, 0x0200 }, { 4722, 0xf1a6 }, { 4731, 0x4434 }, { 4736, 0x720e }, { 4743, 0x35a2 }, { 4750, 0x92e0 }, { 4756, 0x8101 }, { 4759, 0x0900 }, /* 0x7d00 */ { 4761, 0x0400 }, { 4762, 0x0000 }, { 4762, 0x8885 }, { 4767, 0x0000 }, { 4767, 0x0000 }, { 4767, 0x0000 }, { 4767, 0x4000 }, { 4768, 0x0080 }, { 4769, 0x0000 }, { 4769, 0x0000 }, { 4769, 0x4040 }, { 4771, 0x0000 }, { 4771, 0x0000 }, { 4771, 0x0000 }, { 4771, 0x0000 }, { 4771, 0x0000 }, /* 0x7e00 */ { 4771, 0x0000 }, { 4771, 0x0000 }, { 4771, 0x0000 }, { 4771, 0x0800 }, { 4772, 0x0082 }, { 4774, 0x0000 }, { 4774, 0x0000 }, { 4774, 0x0000 }, { 4774, 0x0004 }, { 4775, 0x8800 }, { 4777, 0xbfff }, { 4792, 0xe7ef }, { 4805, 0xffff }, { 4821, 0xffbf }, { 4836, 0xefef }, { 4850, 0xfdff }, /* 0x7f00 */ { 4865, 0xfbff }, { 4880, 0xbffe }, { 4894, 0xffff }, { 4910, 0x057f }, { 4919, 0x0034 }, { 4922, 0x85b3 }, { 4930, 0x4706 }, { 4936, 0x4216 }, { 4941, 0x5402 }, { 4945, 0xe410 }, { 4950, 0x8092 }, { 4954, 0xb305 }, { 4961, 0x5422 }, { 4966, 0x8130 }, { 4970, 0x4263 }, { 4976, 0x180b }, /* 0x8000 */ { 4981, 0x387b }, { 4990, 0x13f5 }, { 4999, 0x07e5 }, { 5007, 0xa9ea }, { 5016, 0x3c4c }, { 5023, 0x0514 }, { 5027, 0x0600 }, { 5029, 0x8002 }, { 5031, 0x1ad9 }, { 5039, 0xbd48 }, { 5047, 0xee37 }, { 5058, 0xf496 }, { 5067, 0x705f }, { 5076, 0x7ec0 }, { 5084, 0xbfb2 }, { 5095, 0x355f }, /* 0x8100 */ { 5105, 0xe644 }, { 5112, 0x455f }, { 5121, 0x9000 }, { 5123, 0x4146 }, { 5128, 0x1d40 }, { 5133, 0x063b }, { 5140, 0x62a1 }, { 5146, 0xfe13 }, { 5156, 0x8505 }, { 5161, 0x3902 }, { 5166, 0x0548 }, { 5170, 0x0c08 }, { 5173, 0x144f }, { 5180, 0x0000 }, { 5180, 0x3488 }, { 5185, 0x5818 }, /* 0x8200 */ { 5190, 0x3077 }, { 5198, 0xd815 }, { 5205, 0xbd0e }, { 5214, 0x4bfb }, { 5225, 0x8a90 }, { 5230, 0x8500 }, { 5233, 0xc100 }, { 5236, 0xe61d }, { 5245, 0xed14 }, { 5253, 0xb386 }, { 5261, 0xff72 }, { 5273, 0x639b }, { 5282, 0xfd92 }, { 5292, 0xd9be }, { 5303, 0x887b }, { 5311, 0x0a92 }, /* 0x8300 */ { 5316, 0xd3fe }, { 5328, 0x1cb2 }, { 5335, 0xb980 }, { 5341, 0x177a }, { 5350, 0x82c9 }, { 5356, 0xdc17 }, { 5365, 0xfffb }, { 5380, 0x3980 }, { 5385, 0x4260 }, { 5389, 0x590c }, { 5395, 0x0f01 }, { 5400, 0x37df }, { 5412, 0x94a3 }, { 5419, 0xb150 }, { 5425, 0x0623 }, { 5430, 0x2307 }, /* 0x8400 */ { 5436, 0xf85a }, { 5445, 0x3102 }, { 5449, 0x01f0 }, { 5454, 0x3102 }, { 5458, 0x0040 }, { 5459, 0x1e82 }, { 5465, 0x3a0a }, { 5471, 0x056a }, { 5477, 0x5b84 }, { 5484, 0x1280 }, { 5487, 0x8002 }, { 5489, 0xa714 }, { 5496, 0x2612 }, { 5501, 0xa04b }, { 5507, 0x1069 }, { 5512, 0x9001 }, /* 0x8500 */ { 5515, 0x1000 }, { 5516, 0x848a }, { 5521, 0x1802 }, { 5524, 0x3f80 }, { 5531, 0x0708 }, { 5535, 0x4240 }, { 5538, 0x0110 }, { 5540, 0x4e14 }, { 5546, 0x80b0 }, { 5550, 0x1800 }, { 5552, 0xc510 }, { 5557, 0x0281 }, { 5560, 0x8202 }, { 5563, 0x1029 }, { 5567, 0x0210 }, { 5569, 0x8800 }, /* 0x8600 */ { 5571, 0x0020 }, { 5572, 0x0042 }, { 5574, 0x0280 }, { 5576, 0x1100 }, { 5578, 0xe000 }, { 5581, 0x4413 }, { 5586, 0x5804 }, { 5590, 0xfe02 }, { 5598, 0x3c07 }, { 5605, 0x3028 }, { 5609, 0x9798 }, { 5617, 0x0473 }, { 5623, 0xced1 }, { 5632, 0xcb13 }, { 5640, 0x6210 }, { 5644, 0x431f }, /* 0x8700 */ { 5652, 0x278d }, { 5660, 0x55ac }, { 5668, 0x422e }, { 5674, 0xc892 }, { 5680, 0x5380 }, { 5685, 0x0288 }, { 5688, 0x4039 }, { 5693, 0x7851 }, { 5700, 0x292c }, { 5706, 0x8088 }, { 5709, 0xb900 }, { 5714, 0x2428 }, { 5718, 0x0c41 }, { 5722, 0x080e }, { 5726, 0x4421 }, { 5730, 0x4200 }, /* 0x8800 */ { 5732, 0x0408 }, { 5734, 0x0868 }, { 5738, 0x0006 }, { 5740, 0x1204 }, { 5743, 0x3031 }, { 5748, 0x0290 }, { 5751, 0x5b3e }, { 5761, 0xe085 }, { 5767, 0x2936 }, { 5774, 0x1044 }, { 5777, 0x2814 }, { 5781, 0x1082 }, { 5784, 0x4266 }, { 5790, 0x8334 }, { 5796, 0x013c }, { 5801, 0x531b }, /* 0x8900 */ { 5809, 0x0404 }, { 5811, 0x0e0d }, { 5817, 0x0c22 }, { 5821, 0x0051 }, { 5824, 0x0012 }, { 5826, 0xc000 }, { 5828, 0x0040 }, { 5829, 0x8800 }, { 5831, 0x004a }, { 5834, 0x0000 }, { 5834, 0x0000 }, { 5834, 0x0000 }, { 5834, 0xdff6 }, { 5847, 0x5447 }, { 5854, 0x8868 }, { 5859, 0x0008 }, /* 0x8a00 */ { 5860, 0x0081 }, { 5862, 0x0000 }, { 5862, 0x0000 }, { 5862, 0x4000 }, { 5863, 0x0100 }, { 5864, 0x0000 }, { 5864, 0x0000 }, { 5864, 0x0200 }, { 5865, 0x0600 }, { 5867, 0x0008 }, { 5868, 0x0000 }, { 5868, 0x0000 }, { 5868, 0x0000 }, { 5868, 0x0000 }, { 5868, 0x0000 }, { 5868, 0x0000 }, /* 0x8b00 */ { 5868, 0x0080 }, { 5869, 0x0000 }, { 5869, 0x0040 }, { 5870, 0x0000 }, { 5870, 0x0000 }, { 5870, 0x0000 }, { 5870, 0x1040 }, { 5872, 0x0000 }, { 5872, 0x0000 }, { 5872, 0x0000 }, { 5872, 0xefff }, { 5887, 0xf7fd }, { 5901, 0xff7f }, { 5916, 0xfffe }, { 5931, 0xfbff }, { 5946, 0xffff }, /* 0x8c00 */ { 5962, 0xfdff }, { 5977, 0xbfff }, { 5992, 0xffff }, { 6008, 0x00ff }, { 6016, 0x12c2 }, { 6021, 0x0420 }, { 6023, 0x0c06 }, { 6027, 0x0708 }, { 6031, 0x1624 }, { 6036, 0x0110 }, { 6038, 0x0000 }, { 6038, 0x0000 }, { 6038, 0x0000 }, { 6038, 0x0000 }, { 6038, 0x0000 }, { 6038, 0x0000 }, /* 0x8d00 */ { 6038, 0x0000 }, { 6038, 0xe000 }, { 6041, 0xfffe }, { 6056, 0xffff }, { 6072, 0xffff }, { 6088, 0x7f79 }, { 6100, 0x28df }, { 6109, 0x00f9 }, { 6115, 0x0c32 }, { 6120, 0x8012 }, { 6123, 0x0008 }, { 6124, 0xd53a }, { 6133, 0xd858 }, { 6140, 0xecc2 }, { 6148, 0x9d18 }, { 6155, 0x2fa8 }, /* 0x8e00 */ { 6163, 0x9620 }, { 6168, 0xe010 }, { 6172, 0xd60c }, { 6179, 0x2622 }, { 6184, 0x0f97 }, { 6193, 0x0206 }, { 6196, 0xb240 }, { 6201, 0x9055 }, { 6207, 0x80a2 }, { 6211, 0x5011 }, { 6215, 0x9800 }, { 6218, 0x0404 }, { 6220, 0x4000 }, { 6221, 0x0000 }, { 6221, 0x0000 }, { 6221, 0x0000 }, /* 0x8f00 */ { 6221, 0x0000 }, { 6221, 0x0000 }, { 6221, 0x0000 }, { 6221, 0x0000 }, { 6221, 0x0000 }, { 6221, 0x0000 }, { 6221, 0xfbc0 }, { 6230, 0xffff }, { 6246, 0xeffe }, { 6260, 0xdffb }, { 6274, 0x0b08 }, { 6278, 0x6243 }, { 6284, 0x41b6 }, { 6291, 0xfb3b }, { 6303, 0x6f74 }, { 6313, 0x2389 }, /* 0x9000 */ { 6319, 0xae7f }, { 6331, 0xecd7 }, { 6342, 0xe047 }, { 6349, 0x5960 }, { 6355, 0xa096 }, { 6361, 0x098f }, { 6368, 0x612c }, { 6374, 0xa030 }, { 6378, 0x090d }, { 6383, 0x2aaa }, { 6390, 0xd44e }, { 6398, 0x4f7b }, { 6409, 0xc4b2 }, { 6416, 0x388b }, { 6423, 0xa9c6 }, { 6431, 0x6110 }, /* 0x9100 */ { 6435, 0x0014 }, { 6437, 0x4200 }, { 6439, 0x800c }, { 6442, 0x0202 }, { 6444, 0xfe48 }, { 6453, 0x6485 }, { 6459, 0xd63e }, { 6469, 0xe3f7 }, { 6481, 0x3aa0 }, { 6487, 0x0c07 }, { 6492, 0xe40c }, { 6498, 0x0430 }, { 6501, 0xf680 }, { 6508, 0x1002 }, { 6510, 0x0000 }, { 6510, 0x0000 }, /* 0x9200 */ { 6510, 0x0000 }, { 6510, 0x0000 }, { 6510, 0x0000 }, { 6510, 0x0000 }, { 6510, 0x0000 }, { 6510, 0x0000 }, { 6510, 0x0000 }, { 6510, 0x0010 }, { 6511, 0x4000 }, { 6512, 0x0000 }, { 6512, 0x4000 }, { 6513, 0x0000 }, { 6513, 0x0100 }, { 6514, 0x0000 }, { 6514, 0x0000 }, { 6514, 0x0000 }, /* 0x9300 */ { 6514, 0x0000 }, { 6514, 0x0000 }, { 6514, 0x0000 }, { 6514, 0x4000 }, { 6515, 0x0000 }, { 6515, 0x0000 }, { 6515, 0x0400 }, { 6516, 0x0000 }, { 6516, 0x8000 }, { 6517, 0x0000 }, { 6517, 0x0000 }, { 6517, 0x0000 }, { 6517, 0x0400 }, { 6518, 0x0040 }, { 6519, 0x0000 }, { 6519, 0x0000 }, /* 0x9400 */ { 6519, 0x0000 }, { 6519, 0x0000 }, { 6519, 0x0000 }, { 6519, 0x4000 }, { 6520, 0x0000 }, { 6520, 0x0000 }, { 6520, 0x0800 }, { 6521, 0x0000 }, { 6521, 0xffe0 }, { 6532, 0xfebd }, { 6545, 0xffff }, { 6561, 0xffff }, { 6577, 0x7f7f }, { 6591, 0xfbe7 }, { 6604, 0xffbf }, { 6619, 0xf7ff }, /* 0x9500 */ { 6634, 0xffff }, { 6650, 0xefff }, { 6665, 0xff7e }, { 6679, 0xdff7 }, { 6693, 0xf6f7 }, { 6706, 0xfbdf }, { 6720, 0xbffe }, { 6734, 0x804f }, { 6740, 0x0000 }, { 6740, 0x0000 }, { 6740, 0x0000 }, { 6740, 0x0000 }, { 6740, 0x0000 }, { 6740, 0x0000 }, { 6740, 0xef00 }, { 6747, 0x7fff }, /* 0x9600 */ { 6762, 0xff7f }, { 6777, 0xb6f7 }, { 6789, 0x4406 }, { 6793, 0xb87e }, { 6803, 0x3bf5 }, { 6814, 0x8831 }, { 6819, 0x1796 }, { 6827, 0x00f4 }, { 6832, 0xa960 }, { 6838, 0x1391 }, { 6844, 0x0080 }, { 6845, 0x7249 }, { 6852, 0xf2f3 }, { 6863, 0x0024 }, { 6865, 0x8701 }, { 6870, 0x42c8 }, /* 0x9700 */ { 6875, 0xe3d3 }, { 6885, 0x5048 }, { 6889, 0x2400 }, { 6891, 0x4305 }, { 6896, 0x0000 }, { 6896, 0x4a4c }, { 6902, 0x0227 }, { 6907, 0x1058 }, { 6911, 0x2820 }, { 6914, 0x0116 }, { 6918, 0xa809 }, { 6923, 0x0014 }, { 6925, 0x0000 }, { 6925, 0x0000 }, { 6925, 0x3ec0 }, { 6932, 0x0068 }, /* 0x9800 */ { 6935, 0x0000 }, { 6935, 0x0000 }, { 6935, 0x0000 }, { 6935, 0x0000 }, { 6935, 0x0000 }, { 6935, 0x0000 }, { 6935, 0x0000 }, { 6935, 0xffe0 }, { 6946, 0xb7ff }, { 6960, 0xfddb }, { 6973, 0x00f7 }, { 6980, 0x0000 }, { 6980, 0x4000 }, { 6981, 0xc72e }, { 6990, 0x0180 }, { 6992, 0x0000 }, /* 0x9900 */ { 6992, 0x2000 }, { 6993, 0x0001 }, { 6994, 0x4000 }, { 6995, 0x0000 }, { 6995, 0x0000 }, { 6995, 0x0030 }, { 6997, 0xffa8 }, { 7008, 0xb4f7 }, { 7019, 0xadf3 }, { 7030, 0x03ff }, { 7040, 0x0120 }, { 7042, 0x0000 }, { 7042, 0x0000 }, { 7042, 0x0000 }, { 7042, 0x0000 }, { 7042, 0x0000 }, /* 0x9a00 */ { 7042, 0x0000 }, { 7042, 0x0000 }, { 7042, 0x0000 }, { 7042, 0x0000 }, { 7042, 0x0000 }, { 7042, 0x0000 }, { 7042, 0xf000 }, { 7046, 0xfffb }, { 7061, 0x9df7 }, { 7073, 0xfdcf }, { 7086, 0x01bf }, { 7094, 0x15c3 }, { 7101, 0x1827 }, { 7107, 0x810a }, { 7111, 0xa842 }, { 7116, 0x0a00 }, /* 0x9b00 */ { 7118, 0x8108 }, { 7121, 0x8008 }, { 7123, 0x8008 }, { 7125, 0x1804 }, { 7128, 0xa3be }, { 7138, 0x0012 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, /* 0x9c00 */ { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x0000 }, { 7140, 0x9000 }, { 7142, 0x69e6 }, { 7151, 0xdc37 }, { 7161, 0x6bff }, { 7174, 0x3dff }, { 7187, 0xfcf8 }, { 7198, 0xf3f9 }, { 7210, 0x0004 }, }; static const Summary16 gb2312_uni2indx_page9e[27] = { /* 0x9e00 */ { 7211, 0x0000 }, { 7211, 0x8000 }, { 7212, 0xbf6f }, { 7225, 0xe7ee }, { 7237, 0xdffe }, { 7251, 0x5da2 }, { 7259, 0x3fd8 }, { 7269, 0xc00b }, { 7274, 0x0984 }, { 7278, 0xa00c }, { 7282, 0x0040 }, { 7283, 0x6910 }, { 7288, 0xe210 }, { 7293, 0xb912 }, { 7300, 0x86a5 }, { 7307, 0x5a00 }, /* 0x9f00 */ { 7311, 0x6800 }, { 7314, 0x0289 }, { 7318, 0x9005 }, { 7322, 0x6a80 }, { 7327, 0x0010 }, { 7328, 0x0003 }, { 7330, 0x0000 }, { 7330, 0x8000 }, { 7331, 0x1ff9 }, { 7342, 0x8e00 }, { 7346, 0x0001 }, }; static const Summary16 gb2312_uni2indx_pageff[15] = { /* 0xff00 */ { 7347, 0xfffe }, { 7362, 0xffff }, { 7378, 0xffff }, { 7394, 0xffff }, { 7410, 0xffff }, { 7426, 0x7fff }, { 7441, 0x0000 }, { 7441, 0x0000 }, { 7441, 0x0000 }, { 7441, 0x0000 }, { 7441, 0x0000 }, { 7441, 0x0000 }, { 7441, 0x0000 }, { 7441, 0x0000 }, { 7441, 0x002b }, }; static int gb2312_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; if (n >= 2) { const Summary16 *summary = NULL; if (wc < 0x0460) summary = &gb2312_uni2indx_page00[(wc>>4)]; else if (wc >= 0x2000 && wc < 0x2650) summary = &gb2312_uni2indx_page20[(wc>>4)-0x200]; else if (wc >= 0x3000 && wc < 0x3230) summary = &gb2312_uni2indx_page30[(wc>>4)-0x300]; else if (wc >= 0x4e00 && wc < 0x9cf0) summary = &gb2312_uni2indx_page4e[(wc>>4)-0x4e0]; else if (wc >= 0x9e00 && wc < 0x9fb0) summary = &gb2312_uni2indx_page9e[(wc>>4)-0x9e0]; else if (wc >= 0xff00 && wc < 0xfff0) summary = &gb2312_uni2indx_pageff[(wc>>4)-0xff0]; if (summary) { unsigned short used = summary->used; unsigned int i = wc & 0x0f; if (used & ((unsigned short) 1 << i)) { unsigned short c; /* Keep in `used' only the bits 0..i-1. */ used &= ((unsigned short) 1 << i) - 1; /* Add `summary->indx' and the number of bits set in `used'. */ used = (used & 0x5555) + ((used & 0xaaaa) >> 1); used = (used & 0x3333) + ((used & 0xcccc) >> 2); used = (used & 0x0f0f) + ((used & 0xf0f0) >> 4); used = (used & 0x00ff) + (used >> 8); c = gb2312_2charset[summary->indx + used]; r[0] = (c >> 8); r[1] = (c & 0xff); return 2; } } return RET_ILSEQ; } return RET_TOOSMALL; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/README.txt0000644000175000017500000000105615004135251020052 0ustar albrechtalbrecht$XFree86: xc/lib/X11/lcUniConv/README,v 1.3 2003/10/24 15:34:01 tsi Exp $ The files in this directory are taken from the libiconv-1.1 package. The *.h files were generated from tables (mostly from ftp.unicode.org) using the programs '8bit_tab_to_h.c', 'cjk_tab_to_h.c' and 'gbk_tab_to_h.c'. On some of them, further optimizations were applied by hand. If you find a bug in these files, instead of modifying them in XFree86 and let it diverge from libiconv, please notify the libiconv maintainer (currently ) so he can fix both in synch. fltk-1.4.3/src/xutf8/lcUniConv/iso8859_16.h0000644000175000017500000000751615004135251020172 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_16.h,v 1.4 2003/07/15 17:33:45 pascal Exp $ */ /* * ISO-8859-16 */ static const unsigned short iso8859_16_2uni[96] = { /* 0xa0 */ 0x00a0, 0x0104, 0x0105, 0x0141, 0x20ac, 0x201e, 0x0160, 0x00a7, 0x0161, 0x00a9, 0x0218, 0x00ab, 0x0179, 0x00ad, 0x017a, 0x017b, /* 0xb0 */ 0x00b0, 0x00b1, 0x010c, 0x0142, 0x017d, 0x201d, 0x00b6, 0x00b7, 0x017e, 0x010d, 0x0219, 0x00bb, 0x0152, 0x0153, 0x0178, 0x017c, /* 0xc0 */ 0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0106, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, /* 0xd0 */ 0x0110, 0x0143, 0x00d2, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x015a, 0x0170, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0118, 0x021a, 0x00df, /* 0xe0 */ 0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x0107, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* 0xf0 */ 0x0111, 0x0144, 0x00f2, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x015b, 0x0171, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0119, 0x021b, 0x00ff, }; static int iso8859_16_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) iso8859_16_2uni[c-0xa0]; return 1; } static const unsigned char iso8859_16_page00[224] = { 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */ 0x00, 0xa9, 0x00, 0xab, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */ 0xb0, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xb6, 0xb7, /* 0xb0-0xb7 */ 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ 0xc0, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0xc6, 0xc7, /* 0xc0-0xc7 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */ 0x00, 0x00, 0xd2, 0xd3, 0xd4, 0x00, 0xd6, 0x00, /* 0xd0-0xd7 */ 0x00, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */ 0xe0, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0xe7, /* 0xe0-0xe7 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */ 0x00, 0x00, 0xf2, 0xf3, 0xf4, 0x00, 0xf6, 0x00, /* 0xf0-0xf7 */ 0x00, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0xff, /* 0xf8-0xff */ /* 0x0100 */ 0x00, 0x00, 0xc3, 0xe3, 0xa1, 0xa2, 0xc5, 0xe5, /* 0x00-0x07 */ 0x00, 0x00, 0x00, 0x00, 0xb2, 0xb9, 0x00, 0x00, /* 0x08-0x0f */ 0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0xdd, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0xa3, 0xb3, 0xd1, 0xf1, 0x00, 0x00, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0xd5, 0xf5, 0xbc, 0xbd, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0xd7, 0xf7, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0xa6, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0xd8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0xbe, 0xac, 0xae, 0xaf, 0xbf, 0xb4, 0xb8, 0x00, /* 0x78-0x7f */ }; static const unsigned char iso8859_16_page02[8] = { 0xaa, 0xba, 0xde, 0xfe, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ }; static const unsigned char iso8859_16_page20[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xa5, 0x00, /* 0x18-0x1f */ }; static int iso8859_16_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x0180) c = iso8859_16_page00[wc-0x00a0]; else if (wc >= 0x0218 && wc < 0x0220) c = iso8859_16_page02[wc-0x0218]; else if (wc >= 0x2018 && wc < 0x2020) c = iso8859_16_page20[wc-0x2018]; else if (wc == 0x20ac) c = 0xa4; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/iso8859_8.h0000644000175000017500000000621115004135251020102 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_8.h,v 1.3 2000/11/29 17:40:32 dawes Exp $ */ /* * ISO-8859-8 */ #ifdef NEED_TOWC static const unsigned short iso8859_8_2uni[96] = { /* 0xa0 */ 0x00a0, 0xfffd, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, /* 0xb0 */ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0xfffd, /* 0xc0 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xd0 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x2017, /* 0xe0 */ 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, /* 0xf0 */ 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0xfffd, 0xfffd, 0x200e, 0x200f, 0xfffd, }; static int iso8859_8_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c >= 0xa0) { unsigned short wc = iso8859_8_2uni[c-0xa0]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } else { *pwc = (ucs4_t) c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_8_page00[88] = { 0xa0, 0x00, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */ 0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */ 0xb8, 0xb9, 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, /* 0xb8-0xbf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, /* 0xd0-0xd7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, /* 0xf0-0xf7 */ }; static const unsigned char iso8859_8_page05[32] = { 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xd0-0xd7 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xd8-0xdf */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xe0-0xe7 */ 0xf8, 0xf9, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ }; static const unsigned char iso8859_8_page20[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfe, /* 0x08-0x0f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, /* 0x10-0x17 */ }; static int iso8859_8_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00f8) c = iso8859_8_page00[wc-0x00a0]; else if (wc >= 0x05d0 && wc < 0x05f0) c = iso8859_8_page05[wc-0x05d0]; else if (wc >= 0x2008 && wc < 0x2018) c = iso8859_8_page20[wc-0x2008]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/viscii.h0000644000175000017500000001234615004135251020017 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/viscii.h,v 1.3 2000/11/29 17:40:35 dawes Exp $ */ /* * VISCII1.1-1 */ /* Specification: RFC 1456 */ static const unsigned short viscii_2uni_1[32] = { /* 0x00 */ 0x0000, 0x0001, 0x1eb2, 0x0003, 0x0004, 0x1eb4, 0x1eaa, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, /* 0x10 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x1ef6, 0x0015, 0x0016, 0x0017, 0x0018, 0x1ef8, 0x001a, 0x001b, 0x001c, 0x001d, 0x1ef4, 0x001f, }; static const unsigned short viscii_2uni_2[128] = { /* 0x80 */ 0x1ea0, 0x1eae, 0x1eb0, 0x1eb6, 0x1ea4, 0x1ea6, 0x1ea8, 0x1eac, 0x1ebc, 0x1eb8, 0x1ebe, 0x1ec0, 0x1ec2, 0x1ec4, 0x1ec6, 0x1ed0, /* 0x90 */ 0x1ed2, 0x1ed4, 0x1ed6, 0x1ed8, 0x1ee2, 0x1eda, 0x1edc, 0x1ede, 0x1eca, 0x1ece, 0x1ecc, 0x1ec8, 0x1ee6, 0x0168, 0x1ee4, 0x1ef2, /* 0xa0 */ 0x00d5, 0x1eaf, 0x1eb1, 0x1eb7, 0x1ea5, 0x1ea7, 0x1ea9, 0x1ead, 0x1ebd, 0x1eb9, 0x1ebf, 0x1ec1, 0x1ec3, 0x1ec5, 0x1ec7, 0x1ed1, /* 0xb0 */ 0x1ed3, 0x1ed5, 0x1ed7, 0x1ee0, 0x01a0, 0x1ed9, 0x1edd, 0x1edf, 0x1ecb, 0x1ef0, 0x1ee8, 0x1eea, 0x1eec, 0x01a1, 0x1edb, 0x01af, /* 0xc0 */ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x1ea2, 0x0102, 0x1eb3, 0x1eb5, 0x00c8, 0x00c9, 0x00ca, 0x1eba, 0x00cc, 0x00cd, 0x0128, 0x1ef3, /* 0xd0 */ 0x0110, 0x1ee9, 0x00d2, 0x00d3, 0x00d4, 0x1ea1, 0x1ef7, 0x1eeb, 0x1eed, 0x00d9, 0x00da, 0x1ef9, 0x1ef5, 0x00dd, 0x1ee1, 0x01b0, /* 0xe0 */ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x1ea3, 0x0103, 0x1eef, 0x1eab, 0x00e8, 0x00e9, 0x00ea, 0x1ebb, 0x00ec, 0x00ed, 0x0129, 0x1ec9, /* 0xf0 */ 0x0111, 0x1ef1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x1ecf, 0x1ecd, 0x1ee5, 0x00f9, 0x00fa, 0x0169, 0x1ee7, 0x00fd, 0x1ee3, 0x1eee, }; static int viscii_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x20) *pwc = (ucs4_t) viscii_2uni_1[c]; else if (c < 0x80) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) viscii_2uni_2[c-0x80]; return 1; } static const unsigned char viscii_page00[64+184] = { 0xc0, 0xc1, 0xc2, 0xc3, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ 0xc8, 0xc9, 0xca, 0x00, 0xcc, 0xcd, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0xd2, 0xd3, 0xd4, 0xa0, 0x00, 0x00, /* 0xd0-0xd7 */ 0x00, 0xd9, 0xda, 0x00, 0x00, 0xdd, 0x00, 0x00, /* 0xd8-0xdf */ 0xe0, 0xe1, 0xe2, 0xe3, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */ 0xe8, 0xe9, 0xea, 0x00, 0xec, 0xed, 0x00, 0x00, /* 0xe8-0xef */ 0x00, 0x00, 0xf2, 0xf3, 0xf4, 0xf5, 0x00, 0x00, /* 0xf0-0xf7 */ 0x00, 0xf9, 0xfa, 0x00, 0x00, 0xfd, 0x00, 0x00, /* 0xf8-0xff */ /* 0x0100 */ 0x00, 0x00, 0xc5, 0xe5, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0xce, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x9d, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */ 0xb4, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, /* 0xa8-0xaf */ 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ }; static const unsigned char viscii_page1e[96] = { 0x80, 0xd5, 0xc4, 0xe4, 0x84, 0xa4, 0x85, 0xa5, /* 0xa0-0xa7 */ 0x86, 0xa6, 0x06, 0xe7, 0x87, 0xa7, 0x81, 0xa1, /* 0xa8-0xaf */ 0x82, 0xa2, 0x02, 0xc6, 0x05, 0xc7, 0x83, 0xa3, /* 0xb0-0xb7 */ 0x89, 0xa9, 0xcb, 0xeb, 0x88, 0xa8, 0x8a, 0xaa, /* 0xb8-0xbf */ 0x8b, 0xab, 0x8c, 0xac, 0x8d, 0xad, 0x8e, 0xae, /* 0xc0-0xc7 */ 0x9b, 0xef, 0x98, 0xb8, 0x9a, 0xf7, 0x99, 0xf6, /* 0xc8-0xcf */ 0x8f, 0xaf, 0x90, 0xb0, 0x91, 0xb1, 0x92, 0xb2, /* 0xd0-0xd7 */ 0x93, 0xb5, 0x95, 0xbe, 0x96, 0xb6, 0x97, 0xb7, /* 0xd8-0xdf */ 0xb3, 0xde, 0x94, 0xfe, 0x9e, 0xf8, 0x9c, 0xfc, /* 0xe0-0xe7 */ 0xba, 0xd1, 0xbb, 0xd7, 0xbc, 0xd8, 0xff, 0xe6, /* 0xe8-0xef */ 0xb9, 0xf1, 0x9f, 0xcf, 0x1e, 0xdc, 0x14, 0xd6, /* 0xf0-0xf7 */ 0x19, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */ }; static int viscii_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x0080 && (wc >= 0x0020 || (0x42100064 & (1 << wc)) == 0)) { *r = wc; return 1; } else if (wc >= 0x00c0 && wc < 0x01b8) c = viscii_page00[wc-0x00c0]; else if (wc >= 0x1ea0 && wc < 0x1f00) c = viscii_page1e[wc-0x1ea0]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/tis620.h0000644000175000017500000000472215004135251017557 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/tis620.h,v 1.4 2001/02/09 00:02:54 dawes Exp $ */ /* * TIS620-0 */ static const unsigned short tis620_2uni[96] = { /* 0xa0 */ 0xfffd, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, /* 0xb0 */ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, /* 0xc0 */ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, /* 0xd0 */ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0e3f, /* 0xe0 */ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f, /* 0xf0 */ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xfffd, 0xfffd, 0xfffd, 0xfffd, }; static int tis620_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x80) { *pwc = (ucs4_t) c; return 1; } else if (c < 0xa0) { } else { unsigned short wc = tis620_2uni[c-0xa0]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } return RET_ILSEQ; } static const unsigned char tis620_page0e[96] = { 0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x00-0x07 */ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0x08-0x0f */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x10-0x17 */ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0x18-0x1f */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x20-0x27 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x28-0x2f */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x30-0x37 */ 0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0xdf, /* 0x38-0x3f */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x40-0x47 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x48-0x4f */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x50-0x57 */ 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ }; static int tis620_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x0080) { *r = wc; return 1; } else if (wc >= 0x0e00 && wc < 0x0e60) c = tis620_page0e[wc-0x0e00]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/cjk_tab_to_h.c0000644000175000017500000007234015004135251021132 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/cjk_tab_to_h.c,v 1.2 2000/12/04 18:49:31 dawes Exp $ */ /* * Generates a CJK character set table from a .TXT table as found on * ftp.unicode.org or in the X nls directory. * Examples: * * ./cjk_tab_to_h GB2312.1980-0 gb2312 > gb2312.h < gb2312 * ./cjk_tab_to_h JISX0208.1983-0 jisx0208 > jisx0208.h < jis0208 * ./cjk_tab_to_h KSC5601.1987-0 ksc5601 > ksc5601.h < ksc5601 * * ./cjk_tab_to_h GB2312.1980-0 gb2312 > gb2312.h < GB2312.TXT * ./cjk_tab_to_h JISX0208.1983-0 jisx0208 > jisx0208.h < JIS0208.TXT * ./cjk_tab_to_h JISX0212.1990-0 jisx0212 > jisx0212.h < JIS0212.TXT * ./cjk_tab_to_h KSC5601.1987-0 ksc5601 > ksc5601.h < KSC5601.TXT * ./cjk_tab_to_h KSX1001.1992-0 ksc5601 > ksc5601.h < KSX1001.TXT * * ./cjk_tab_to_h BIG5 big5 > big5.h < BIG5.TXT * * ./cjk_tab_to_h JOHAB johab > johab.h < JOHAB.TXT */ #include #include #include #include typedef struct { int start; int end; } Block; typedef struct { int rows; /* number of possible values for the 1st byte */ int cols; /* number of possible values for the 2nd byte */ int (*row_byte) (int row); /* returns the 1st byte value for a given row */ int (*col_byte) (int col); /* returns the 2nd byte value for a given col */ int (*byte_row) (int byte); /* converts a 1st byte value to a row, else -1 */ int (*byte_col) (int byte); /* converts a 2nd byte value to a col, else -1 */ const char* check_row_expr; /* format string for 1st byte value checking */ const char* check_col_expr; /* format string for 2nd byte value checking */ const char* byte_row_expr; /* format string for 1st byte value to row */ const char* byte_col_expr; /* format string for 2nd byte value to col */ int** charset2uni; /* charset2uni[0..rows-1][0..cols-1] is valid */ /* You'll understand the terms "row" and "col" when you buy Ken Lunde's book. Once a row is fixed, choosing a "col" is the same as choosing a "cell". */ int* charsetpage; /* charsetpage[0..rows]: how large is a page for a row */ int ncharsetblocks; Block* charsetblocks; /* blocks[0..nblocks-1] */ int* uni2charset; /* uni2charset[0x0000..0xffff] */ } Encoding; /* * Outputs the file title. */ static void output_title (const char *charsetname) { printf("\n"); printf("/*\n"); printf(" * %s\n", charsetname); printf(" */\n"); printf("\n"); } /* * Reads the charset2uni table from standard input. */ static void read_table (Encoding* enc) { int row, col, i, i1, i2, c, j; enc->charset2uni = (int**) malloc(enc->rows*sizeof(int*)); for (row = 0; row < enc->rows; row++) enc->charset2uni[row] = (int*) malloc(enc->cols*sizeof(int)); for (row = 0; row < enc->rows; row++) for (col = 0; col < enc->cols; col++) enc->charset2uni[row][col] = 0xfffd; c = getc(stdin); ungetc(c,stdin); if (c == '#') { /* Read a unicode.org style .TXT file. */ for (;;) { c = getc(stdin); if (c == EOF) break; if (c == '\n' || c == ' ' || c == '\t') continue; if (c == '#') { do { c = getc(stdin); } while (!(c == EOF || c == '\n')); continue; } ungetc(c,stdin); if (scanf("0x%x", &j) != 1) exit(1); i1 = j >> 8; i2 = j & 0xff; row = enc->byte_row(i1); col = enc->byte_col(i2); if (row < 0 || col < 0) { fprintf(stderr, "lost entry for %02x %02x\n", i1, i2); exit(1); } if (scanf(" 0x%x", &enc->charset2uni[row][col]) != 1) exit(1); } } else { /* Read a table of hexadecimal Unicode values. */ for (i1 = 32; i1 < 132; i1++) for (i2 = 32; i2 < 132; i2++) { i = scanf("%x", &j); if (i == EOF) goto read_done; if (i != 1) exit(1); if (j < 0 || j == 0xffff) j = 0xfffd; if (j != 0xfffd) { if (enc->byte_row(i1) < 0 || enc->byte_col(i2) < 0) { fprintf(stderr, "lost entry at %02x %02x\n", i1, i2); exit (1); } enc->charset2uni[enc->byte_row(i1)][enc->byte_col(i2)] = j; } } read_done: ; } } /* * Computes the charsetpage[0..rows] array. */ static void find_charset2uni_pages (Encoding* enc) { int row, col; enc->charsetpage = (int*) malloc((enc->rows+1)*sizeof(int)); for (row = 0; row <= enc->rows; row++) enc->charsetpage[row] = 0; for (row = 0; row < enc->rows; row++) { int used = 0; for (col = 0; col < enc->cols; col++) if (enc->charset2uni[row][col] != 0xfffd) used = col+1; enc->charsetpage[row] = used; } } /* * Fills in nblocks and blocks. */ static void find_charset2uni_blocks (Encoding* enc) { int n, row, lastrow; enc->charsetblocks = (Block*) malloc(enc->rows*sizeof(Block)); n = 0; for (row = 0; row < enc->rows; row++) if (enc->charsetpage[row] > 0 && (row == 0 || enc->charsetpage[row-1] == 0)) { for (lastrow = row; enc->charsetpage[lastrow+1] > 0; lastrow++); enc->charsetblocks[n].start = row * enc->cols; enc->charsetblocks[n].end = lastrow * enc->cols + enc->charsetpage[lastrow]; n++; } enc->ncharsetblocks = n; } /* * Outputs the charset to unicode table and function. */ static void output_charset2uni (const char* name, Encoding* enc) { int row, col, lastrow, col_max, i, i1_min, i1_max; find_charset2uni_pages(enc); find_charset2uni_blocks(enc); for (row = 0; row < enc->rows; row++) if (enc->charsetpage[row] > 0) { if (row == 0 || enc->charsetpage[row-1] == 0) { /* Start a new block. */ for (lastrow = row; enc->charsetpage[lastrow+1] > 0; lastrow++); printf("static const unsigned short %s_2uni_page%02x[%d] = {\n", name, enc->row_byte(row), (lastrow-row) * enc->cols + enc->charsetpage[lastrow]); } printf(" /""* 0x%02x *""/\n ", enc->row_byte(row)); col_max = (enc->charsetpage[row+1] > 0 ? enc->cols : enc->charsetpage[row]); for (col = 0; col < col_max; col++) { printf(" 0x%04x,", enc->charset2uni[row][col]); if ((col % 8) == 7 && (col+1 < col_max)) printf("\n "); } printf("\n"); if (enc->charsetpage[row+1] == 0) { /* End a block. */ printf("};\n"); } } printf("\n"); printf("static int\n"); printf("%s_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n)\n", name); printf("{\n"); printf(" unsigned char c1 = s[0];\n"); printf(" if ("); for (i = 0; i < enc->ncharsetblocks; i++) { i1_min = enc->row_byte(enc->charsetblocks[i].start / enc->cols); i1_max = enc->row_byte((enc->charsetblocks[i].end-1) / enc->cols); if (i > 0) printf(" || "); if (i1_min == i1_max) printf("(c1 == 0x%02x)", i1_min); else printf("(c1 >= 0x%02x && c1 <= 0x%02x)", i1_min, i1_max); } printf(") {\n"); printf(" if (n >= 2) {\n"); printf(" unsigned char c2 = s[1];\n"); printf(" if ("); printf(enc->check_col_expr, "c2"); printf(") {\n"); printf(" unsigned int i = %d * (", enc->cols); printf(enc->byte_row_expr, "c1"); printf(") + ("); printf(enc->byte_col_expr, "c2"); printf(");\n"); printf(" unsigned short wc = 0xfffd;\n"); for (i = 0; i < enc->ncharsetblocks; i++) { printf(" "); if (i > 0) printf("} else "); if (i < enc->ncharsetblocks-1) printf("if (i < %d) ", enc->charsetblocks[i+1].start); printf("{\n"); printf(" if (i < %d)\n", enc->charsetblocks[i].end); printf(" wc = %s_2uni_page%02x[i", name, enc->row_byte(enc->charsetblocks[i].start / enc->cols)); if (enc->charsetblocks[i].start > 0) printf("-%d", enc->charsetblocks[i].start); printf("];\n"); } printf(" }\n"); printf(" if (wc != 0xfffd) {\n"); printf(" *pwc = (ucs4_t) wc;\n"); printf(" return 2;\n"); printf(" }\n"); printf(" }\n"); printf(" return RET_ILSEQ;\n"); printf(" }\n"); printf(" return RET_TOOFEW(0);\n"); printf(" }\n"); printf(" return RET_ILSEQ;\n"); printf("}\n"); printf("\n"); } /* * Computes the uni2charset[0x0000..0xffff] array. */ static void invert (Encoding* enc) { int row, col, j; enc->uni2charset = (int*) malloc(0x10000*sizeof(int)); for (j = 0; j < 0x10000; j++) enc->uni2charset[j] = 0; for (row = 0; row < enc->rows; row++) for (col = 0; col < enc->cols; col++) { j = enc->charset2uni[row][col]; if (j != 0xfffd) enc->uni2charset[j] = 0x100 * enc->row_byte(row) + enc->col_byte(col); } } /* * Outputs the unicode to charset table and function, using a linear array. * (Suitable if the table is dense.) */ static void output_uni2charset_dense (const char* name, Encoding* enc) { /* Like in 8bit_tab_to_h.c */ bool pages[0x100]; int line[0x2000]; int tableno; struct { int minline; int maxline; int usecount; } tables[0x2000]; bool first; int row, col, j, p, j1, j2, t; for (p = 0; p < 0x100; p++) pages[p] = false; for (row = 0; row < enc->rows; row++) for (col = 0; col < enc->cols; col++) { j = enc->charset2uni[row][col]; if (j != 0xfffd) pages[j>>8] = true; } for (j1 = 0; j1 < 0x2000; j1++) { bool all_invalid = true; for (j2 = 0; j2 < 8; j2++) { j = 8*j1+j2; if (enc->uni2charset[j] != 0) all_invalid = false; } if (all_invalid) line[j1] = -1; else line[j1] = 0; } tableno = 0; for (j1 = 0; j1 < 0x2000; j1++) { if (line[j1] >= 0) { if (tableno > 0 && ((j1 > 0 && line[j1-1] == tableno-1) || ((tables[tableno-1].maxline >> 5) == (j1 >> 5) && j1 - tables[tableno-1].maxline <= 8))) { line[j1] = tableno-1; tables[tableno-1].maxline = j1; } else { tableno++; line[j1] = tableno-1; tables[tableno-1].minline = tables[tableno-1].maxline = j1; } } } for (t = 0; t < tableno; t++) { tables[t].usecount = 0; j1 = 8*tables[t].minline; j2 = 8*(tables[t].maxline+1); for (j = j1; j < j2; j++) if (enc->uni2charset[j] != 0) tables[t].usecount++; } { p = -1; for (t = 0; t < tableno; t++) if (tables[t].usecount > 1) { p = tables[t].minline >> 5; printf("static const unsigned short %s_page%02x[%d] = {\n", name, p, 8*(tables[t].maxline-tables[t].minline+1)); for (j1 = tables[t].minline; j1 <= tables[t].maxline; j1++) { if ((j1 % 0x20) == 0 && j1 > tables[t].minline) printf(" /* 0x%04x */\n", 8*j1); printf(" "); for (j2 = 0; j2 < 8; j2++) { j = 8*j1+j2; printf(" 0x%04x,", enc->uni2charset[j]); } printf(" /*0x%02x-0x%02x*/\n", 8*(j1 % 0x20), 8*(j1 % 0x20)+7); } printf("};\n"); } if (p >= 0) printf("\n"); } printf("static int\n%s_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n)\n", name); printf("{\n"); printf(" if (n >= 2) {\n"); printf(" unsigned short c = 0;\n"); first = true; for (j1 = 0; j1 < 0x2000;) { t = line[j1]; for (j2 = j1; j2 < 0x2000 && line[j2] == t; j2++); if (t >= 0) { if (j1 != tables[t].minline) abort(); if (j2 > tables[t].maxline+1) abort(); j2 = tables[t].maxline+1; if (first) printf(" "); else printf(" else "); first = false; if (tables[t].usecount == 0) abort(); if (tables[t].usecount == 1) { if (j2 != j1+1) abort(); for (j = 8*j1; j < 8*j2; j++) if (enc->uni2charset[j] != 0) { printf("if (wc == 0x%04x)\n c = 0x%02x;\n", j, enc->uni2charset[j]); break; } } else { if (j1 == 0) { printf("if (wc < 0x%04x)", 8*j2); } else { printf("if (wc >= 0x%04x && wc < 0x%04x)", 8*j1, 8*j2); } printf("\n c = %s_page%02x[wc", name, j1 >> 5); if (tables[t].minline > 0) printf("-0x%04x", 8*j1); printf("];\n"); } } j1 = j2; } printf(" if (c != 0) {\n"); printf(" r[0] = (c >> 8); r[1] = (c & 0xff);\n"); printf(" return 2;\n"); printf(" }\n"); printf(" return RET_ILSEQ;\n"); printf(" }\n"); printf(" return RET_TOOSMALL;\n"); printf("}\n"); } /* * Outputs the unicode to charset table and function, using a packed array. * (Suitable if the table is sparse.) */ static void output_uni2charset_sparse (const char* name, Encoding* enc) { bool pages[0x100]; Block pageblocks[0x100]; int npageblocks; int indx2charset[0x10000]; int summary_indx[0x1000]; int summary_used[0x1000]; int i, row, col, j, p, j1, j2, indx; /* Fill pages[0x100]. */ for (p = 0; p < 0x100; p++) pages[p] = false; for (row = 0; row < enc->rows; row++) for (col = 0; col < enc->cols; col++) { j = enc->charset2uni[row][col]; if (j != 0xfffd) pages[j>>8] = true; } #if 0 for (p = 0; p < 0x100; p++) if (pages[p]) { printf("static const unsigned short %s_page%02x[256] = {\n", name, p); for (j1 = 0; j1 < 32; j1++) { printf(" "); for (j2 = 0; j2 < 8; j2++) printf("0x%04x, ", enc->uni2charset[256*p+8*j1+j2]); printf("/""*0x%02x-0x%02x*""/\n", 8*j1, 8*j1+7); } printf("};\n"); } printf("\n"); #endif /* Fill summary_indx[] and summary_used[]. */ indx = 0; for (j1 = 0; j1 < 0x1000; j1++) { summary_indx[j1] = indx; summary_used[j1] = 0; for (j2 = 0; j2 < 16; j2++) { j = 16*j1+j2; if (enc->uni2charset[j] != 0) { indx2charset[indx++] = enc->uni2charset[j]; summary_used[j1] |= (1 << j2); } } } /* Fill npageblocks and pageblocks[]. */ npageblocks = 0; for (p = 0; p < 0x100; ) { if (pages[p] && (p == 0 || !pages[p-1])) { pageblocks[npageblocks].start = 16*p; do p++; while (p < 0x100 && pages[p]); j1 = 16*p; while (summary_used[j1-1] == 0) j1--; pageblocks[npageblocks].end = j1; npageblocks++; } else p++; } printf("static const unsigned short %s_2charset[%d] = {\n", name, indx); for (i = 0; i < indx; ) { if ((i % 8) == 0) printf(" "); printf(" 0x%04x,", indx2charset[i]); i++; if ((i % 8) == 0 || i == indx) printf("\n"); } printf("};\n"); printf("\n"); for (i = 0; i < npageblocks; i++) { printf("static const Summary16 %s_uni2indx_page%02x[%d] = {\n", name, pageblocks[i].start/16, pageblocks[i].end-pageblocks[i].start); for (j1 = pageblocks[i].start; j1 < pageblocks[i].end; ) { if (((16*j1) % 0x100) == 0) printf(" /""* 0x%04x *""/\n", 16*j1); if ((j1 % 4) == 0) printf(" "); printf(" { %4d, 0x%04x },", summary_indx[j1], summary_used[j1]); j1++; if ((j1 % 4) == 0 || j1 == pageblocks[i].end) printf("\n"); } printf("};\n"); } printf("\n"); printf("static int\n"); printf("%s_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n)\n", name); printf("{\n"); printf(" if (n >= 2) {\n"); printf(" const Summary16 *summary = NULL;\n"); for (i = 0; i < npageblocks; i++) { printf(" "); if (i > 0) printf("else "); printf("if (wc >= 0x%04x && wc < 0x%04x)\n", 16*pageblocks[i].start, 16*pageblocks[i].end); printf(" summary = &%s_uni2indx_page%02x[(wc>>4)", name, pageblocks[i].start/16); if (pageblocks[i].start > 0) printf("-0x%03x", pageblocks[i].start); printf("];\n"); } printf(" if (summary) {\n"); printf(" unsigned short used = summary->used;\n"); printf(" unsigned int i = wc & 0x0f;\n"); printf(" if (used & ((unsigned short) 1 << i)) {\n"); printf(" unsigned short c;\n"); printf(" /* Keep in `used' only the bits 0..i-1. */\n"); printf(" used &= ((unsigned short) 1 << i) - 1;\n"); printf(" /* Add `summary->indx' and the number of bits set in `used'. */\n"); printf(" used = (used & 0x5555) + ((used & 0xaaaa) >> 1);\n"); printf(" used = (used & 0x3333) + ((used & 0xcccc) >> 2);\n"); printf(" used = (used & 0x0f0f) + ((used & 0xf0f0) >> 4);\n"); printf(" used = (used & 0x00ff) + (used >> 8);\n"); printf(" c = %s_2charset[summary->indx + used];\n", name); printf(" r[0] = (c >> 8); r[1] = (c & 0xff);\n"); printf(" return 2;\n"); printf(" }\n"); printf(" }\n"); printf(" return RET_ILSEQ;\n"); printf(" }\n"); printf(" return RET_TOOSMALL;\n"); printf("}\n"); } /* ISO-2022/EUC specifics */ static int row_byte_normal (int row) { return 0x21+row; } static int col_byte_normal (int col) { return 0x21+col; } static int byte_row_normal (int byte) { return byte-0x21; } static int byte_col_normal (int byte) { return byte-0x21; } static void do_normal (const char* name) { Encoding enc; enc.rows = 94; enc.cols = 94; enc.row_byte = row_byte_normal; enc.col_byte = col_byte_normal; enc.byte_row = byte_row_normal; enc.byte_col = byte_col_normal; enc.check_row_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.check_col_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.byte_row_expr = "%1$s - 0x21"; enc.byte_col_expr = "%1$s - 0x21"; read_table(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_sparse(name,&enc); } /* Note: On first sight, the jisx0212_2charset[] table seems to be in order, starting from the charset=0x3021/uni=0x4e02 pair. But it's only mostly in order. There are 75 out-of-order values, scattered all throughout the table. */ static void do_normal_only_charset2uni (const char* name) { Encoding enc; enc.rows = 94; enc.cols = 94; enc.row_byte = row_byte_normal; enc.col_byte = col_byte_normal; enc.byte_row = byte_row_normal; enc.byte_col = byte_col_normal; enc.check_row_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.check_col_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.byte_row_expr = "%1$s - 0x21"; enc.byte_col_expr = "%1$s - 0x21"; read_table(&enc); output_charset2uni(name,&enc); } /* CNS 11643 specifics - trick to put two tables into one */ static int row_byte_cns11643 (int row) { return 0x100 * (row / 94) + (row % 94) + 0x21; } static int byte_row_cns11643 (int byte) { return (byte >= 0x100 && byte < 0x200 ? byte-0x121 : byte >= 0x200 && byte < 0x300 ? byte-0x221+94 : byte >= 0x300 && byte < 0x400 ? byte-0x321+2*94 : -1); } static void do_cns11643_only_uni2charset (const char* name) { Encoding enc; int j, x; enc.rows = 3*94; enc.cols = 94; enc.row_byte = row_byte_cns11643; enc.col_byte = col_byte_normal; enc.byte_row = byte_row_cns11643; enc.byte_col = byte_col_normal; enc.check_row_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.check_col_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.byte_row_expr = "%1$s - 0x21"; enc.byte_col_expr = "%1$s - 0x21"; read_table(&enc); invert(&enc); /* Move the 2 plane bits into the unused bits 15 and 7. */ for (j = 0; j < 0x10000; j++) { x = enc.uni2charset[j]; if (x != 0) { if (x & 0x8080) abort(); switch (x >> 16) { case 0: /* plane 1 */ x = (x & 0xffff) | 0x0000; break; case 1: /* plane 2 */ x = (x & 0xffff) | 0x0080; break; case 2: /* plane 3 */ x = (x & 0xffff) | 0x8000; break; default: abort(); } enc.uni2charset[j] = x; } } output_uni2charset_sparse(name,&enc); } /* GBK specifics */ static int row_byte_gbk1 (int row) { return 0x81+row; } static int col_byte_gbk1 (int col) { return (col >= 0x3f ? 0x41 : 0x40) + col; } static int byte_row_gbk1 (int byte) { if (byte >= 0x81 && byte < 0xff) return byte-0x81; else return -1; } static int byte_col_gbk1 (int byte) { if (byte >= 0x40 && byte < 0x7f) return byte-0x40; else if (byte >= 0x80 && byte < 0xff) return byte-0x41; else return -1; } static void do_gbk1 (const char* name) { Encoding enc; enc.rows = 126; enc.cols = 190; enc.row_byte = row_byte_gbk1; enc.col_byte = col_byte_gbk1; enc.byte_row = byte_row_gbk1; enc.byte_col = byte_col_gbk1; enc.check_row_expr = "%1$s >= 0x81 && %1$s < 0xff"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0x80 && %1$s < 0xff)"; enc.byte_row_expr = "%1$s - 0x81"; enc.byte_col_expr = "%1$s - (%1$s >= 0x80 ? 0x41 : 0x40)"; read_table(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_dense(name,&enc); } static void do_gbk1_only_charset2uni (const char* name) { Encoding enc; enc.rows = 126; enc.cols = 190; enc.row_byte = row_byte_gbk1; enc.col_byte = col_byte_gbk1; enc.byte_row = byte_row_gbk1; enc.byte_col = byte_col_gbk1; enc.check_row_expr = "%1$s >= 0x81 && %1$s < 0xff"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0x80 && %1$s < 0xff)"; enc.byte_row_expr = "%1$s - 0x81"; enc.byte_col_expr = "%1$s - (%1$s >= 0x80 ? 0x41 : 0x40)"; read_table(&enc); output_charset2uni(name,&enc); } static int row_byte_gbk2 (int row) { return 0x81+row; } static int col_byte_gbk2 (int col) { return (col >= 0x3f ? 0x41 : 0x40) + col; } static int byte_row_gbk2 (int byte) { if (byte >= 0x81 && byte < 0xff) return byte-0x81; else return -1; } static int byte_col_gbk2 (int byte) { if (byte >= 0x40 && byte < 0x7f) return byte-0x40; else if (byte >= 0x80 && byte < 0xa1) return byte-0x41; else return -1; } static void do_gbk2_only_charset2uni (const char* name) { Encoding enc; enc.rows = 126; enc.cols = 96; enc.row_byte = row_byte_gbk2; enc.col_byte = col_byte_gbk2; enc.byte_row = byte_row_gbk2; enc.byte_col = byte_col_gbk2; enc.check_row_expr = "%1$s >= 0x81 && %1$s < 0xff"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0x80 && %1$s < 0xa1)"; enc.byte_row_expr = "%1$s - 0x81"; enc.byte_col_expr = "%1$s - (%1$s >= 0x80 ? 0x41 : 0x40)"; read_table(&enc); output_charset2uni(name,&enc); } static void do_gbk1_only_uni2charset (const char* name) { Encoding enc; enc.rows = 126; enc.cols = 190; enc.row_byte = row_byte_gbk1; enc.col_byte = col_byte_gbk1; enc.byte_row = byte_row_gbk1; enc.byte_col = byte_col_gbk1; enc.check_row_expr = "%1$s >= 0x81 && %1$s < 0xff"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0x80 && %1$s < 0xff)"; enc.byte_row_expr = "%1$s - 0x81"; enc.byte_col_expr = "%1$s - (%1$s >= 0x80 ? 0x41 : 0x40)"; read_table(&enc); invert(&enc); output_uni2charset_sparse(name,&enc); } /* KSC 5601 specifics */ /* * Reads the charset2uni table from standard input. */ static void read_table_ksc5601 (Encoding* enc) { int row, col, i, i1, i2, c, j; enc->charset2uni = (int**) malloc(enc->rows*sizeof(int*)); for (row = 0; row < enc->rows; row++) enc->charset2uni[row] = (int*) malloc(enc->cols*sizeof(int)); for (row = 0; row < enc->rows; row++) for (col = 0; col < enc->cols; col++) enc->charset2uni[row][col] = 0xfffd; c = getc(stdin); ungetc(c,stdin); if (c == '#') { /* Read a unicode.org style .TXT file. */ for (;;) { c = getc(stdin); if (c == EOF) break; if (c == '\n' || c == ' ' || c == '\t') continue; if (c == '#') { do { c = getc(stdin); } while (!(c == EOF || c == '\n')); continue; } ungetc(c,stdin); if (scanf("0x%x", &j) != 1) exit(1); i1 = j >> 8; i2 = j & 0xff; if (scanf(" 0x%x", &j) != 1) exit(1); /* Take only the range covered by KS C 5601.1987-0 = KS C 5601.1989-0 = KS X 1001.1992, ignore the rest. */ if (!(i1 >= 128+33 && i1 < 128+127 && i2 >= 128+33 && i2 < 128+127)) continue; /* KSC5601 specific */ i1 &= 0x7f; /* KSC5601 specific */ i2 &= 0x7f; /* KSC5601 specific */ row = enc->byte_row(i1); col = enc->byte_col(i2); if (row < 0 || col < 0) { fprintf(stderr, "lost entry for %02x %02x\n", i1, i2); exit(1); } enc->charset2uni[row][col] = j; } } else { /* Read a table of hexadecimal Unicode values. */ for (i1 = 33; i1 < 127; i1++) for (i2 = 33; i2 < 127; i2++) { i = scanf("%x", &j); if (i == EOF) goto read_done; if (i != 1) exit(1); if (j < 0 || j == 0xffff) j = 0xfffd; if (j != 0xfffd) { if (enc->byte_row(i1) < 0 || enc->byte_col(i2) < 0) { fprintf(stderr, "lost entry at %02x %02x\n", i1, i2); exit (1); } enc->charset2uni[enc->byte_row(i1)][enc->byte_col(i2)] = j; } } read_done: ; } } static void do_ksc5601 (const char* name) { Encoding enc; enc.rows = 94; enc.cols = 94; enc.row_byte = row_byte_normal; enc.col_byte = col_byte_normal; enc.byte_row = byte_row_normal; enc.byte_col = byte_col_normal; enc.check_row_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.check_col_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.byte_row_expr = "%1$s - 0x21"; enc.byte_col_expr = "%1$s - 0x21"; read_table_ksc5601(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_sparse(name,&enc); } /* Big5 specifics */ static int row_byte_big5 (int row) { return 0xa1+row; } static int col_byte_big5 (int col) { return (col >= 0x3f ? 0x62 : 0x40) + col; } static int byte_row_big5 (int byte) { if (byte >= 0xa1 && byte < 0xff) return byte-0xa1; else return -1; } static int byte_col_big5 (int byte) { if (byte >= 0x40 && byte < 0x7f) return byte-0x40; else if (byte >= 0xa1 && byte < 0xff) return byte-0x62; else return -1; } static void do_big5 (const char* name) { Encoding enc; enc.rows = 94; enc.cols = 157; enc.row_byte = row_byte_big5; enc.col_byte = col_byte_big5; enc.byte_row = byte_row_big5; enc.byte_col = byte_col_big5; enc.check_row_expr = "%1$s >= 0xa1 && %1$s < 0xff"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0xa1 && %1$s < 0xff)"; enc.byte_row_expr = "%1$s - 0xa1"; enc.byte_col_expr = "%1$s - (%1$s >= 0xa1 ? 0x62 : 0x40)"; read_table(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_sparse(name,&enc); } /* Johab Hangul specifics */ static int row_byte_johab_hangul (int row) { return 0x84+row; } static int col_byte_johab_hangul (int col) { return (col >= 0x3e ? 0x43 : 0x41) + col; } static int byte_row_johab_hangul (int byte) { if (byte >= 0x84 && byte < 0xd4) return byte-0x84; else return -1; } static int byte_col_johab_hangul (int byte) { if (byte >= 0x41 && byte < 0x7f) return byte-0x41; else if (byte >= 0x81 && byte < 0xff) return byte-0x43; else return -1; } static void do_johab_hangul (const char* name) { Encoding enc; enc.rows = 80; enc.cols = 188; enc.row_byte = row_byte_johab_hangul; enc.col_byte = col_byte_johab_hangul; enc.byte_row = byte_row_johab_hangul; enc.byte_col = byte_col_johab_hangul; enc.check_row_expr = "%1$s >= 0x84 && %1$s < 0xd4"; enc.check_col_expr = "(%1$s >= 0x41 && %1$s < 0x7f) || (%1$s >= 0x81 && %1$s < 0xff)"; enc.byte_row_expr = "%1$s - 0x84"; enc.byte_col_expr = "%1$s - (%1$s >= 0x81 ? 0x43 : 0x41)"; read_table(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_dense(name,&enc); } /* SJIS specifics */ static int row_byte_sjis (int row) { return (row >= 0x1f ? 0xc1 : 0x81) + row; } static int col_byte_sjis (int col) { return (col >= 0x3f ? 0x41 : 0x40) + col; } static int byte_row_sjis (int byte) { if (byte >= 0x81 && byte < 0xa0) return byte-0x81; else if (byte >= 0xe0) return byte-0xc1; else return -1; } static int byte_col_sjis (int byte) { if (byte >= 0x40 && byte < 0x7f) return byte-0x40; else if (byte >= 0x80 && byte < 0xfd) return byte-0x41; else return -1; } static void do_sjis (const char* name) { Encoding enc; enc.rows = 94; enc.cols = 188; enc.row_byte = row_byte_sjis; enc.col_byte = col_byte_sjis; enc.byte_row = byte_row_sjis; enc.byte_col = byte_col_sjis; enc.check_row_expr = "(%1$s >= 0x81 && %1$s < 0xa0) || (%1$s >= 0xe0)"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0x80 && %1$s < 0xfd)"; enc.byte_row_expr = "%1$s - (%1$s >= 0xe0 ? 0xc1 : 0x81)"; enc.byte_col_expr = "%1$s - (%1$s >= 0x80 ? 0x41 : 0x40)"; read_table(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_sparse(name,&enc); } /* Main program */ int main (int argc, char *argv[]) { const char* charsetname; const char* name; if (argc != 3) exit(1); charsetname = argv[1]; name = argv[2]; output_title(charsetname); if (!strcmp(name,"gb2312") || !strcmp(name,"gb12345ext") || !strcmp(name,"jisx0208") || !strcmp(name,"jisx0212")) do_normal(name); else if (!strcmp(name,"cns11643_1") || !strcmp(name,"cns11643_2") || !strcmp(name,"cns11643_3")) do_normal_only_charset2uni(name); else if (!strcmp(name,"cns11643_inv")) do_cns11643_only_uni2charset(name); else if (!strcmp(name,"gbkext1")) do_gbk1_only_charset2uni(name); else if (!strcmp(name,"gbkext2")) do_gbk2_only_charset2uni(name); else if (!strcmp(name,"gbkext_inv")) do_gbk1_only_uni2charset(name); else if (!strcmp(name,"cp936ext")) do_gbk1(name); else if (!strcmp(name,"ksc5601")) do_ksc5601(name); else if (!strcmp(name,"big5") || !strcmp(name,"cp950ext")) do_big5(name); else if (!strcmp(name,"johab_hangul")) do_johab_hangul(name); else if (!strcmp(name,"cp932ext")) do_sjis(name); else exit(1); return 0; } fltk-1.4.3/src/xutf8/lcUniConv/gbk_tab_to_h.c0000644000175000017500000007177415004135251021140 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/cjk_tab_to_h.c,v 1.2 2000/12/04 18:49:31 dawes Exp $ */ /* 2009-02-17 : Create gbk_tab_to_h.c from * cjk_tab_to_h.c to generate GBK(cp936ext) table correctly. * * * Generates a CJK character set table from a .TXT table as found on * ftp.unicode.org or in the X nls directory. * Examples: * * ./gbk_tab_to_h CP936EXT cp936ext > cp936ext.h < CP936EXT.TXT * */ #include #include #include #include typedef struct { int start; int end; } Block; typedef struct { int rows; /* number of possible values for the 1st byte */ int cols; /* number of possible values for the 2nd byte */ int (*row_byte) (int row); /* returns the 1st byte value for a given row */ int (*col_byte) (int col); /* returns the 2nd byte value for a given col */ int (*byte_row) (int byte); /* converts a 1st byte value to a row, else -1 */ int (*byte_col) (int byte); /* converts a 2nd byte value to a col, else -1 */ const char* check_row_expr; /* format string for 1st byte value checking */ const char* check_col_expr; /* format string for 2nd byte value checking */ const char* byte_row_expr; /* format string for 1st byte value to row */ const char* byte_col_expr; /* format string for 2nd byte value to col */ int** charset2uni; /* charset2uni[0..rows-1][0..cols-1] is valid */ /* You'll understand the terms "row" and "col" when you buy Ken Lunde's book. Once a row is fixed, choosing a "col" is the same as choosing a "cell". */ int* charsetpage; /* charsetpage[0..rows]: how large is a page for a row */ int ncharsetblocks; Block* charsetblocks; /* blocks[0..nblocks-1] */ int* uni2charset; /* uni2charset[0x0000..0xffff] */ } Encoding; /* * Outputs the file title. */ static void output_title (const char *charsetname) { printf("\n"); printf("/*\n"); printf(" * %s\n", charsetname); printf(" */\n"); printf("\n"); } /* * Reads the charset2uni table from standard input. */ static void read_table (Encoding* enc) { int row, col, i, i1, i2, c, j; enc->charset2uni = (int**) malloc(enc->rows*sizeof(int*)); for (row = 0; row < enc->rows; row++) enc->charset2uni[row] = (int*) malloc(enc->cols*sizeof(int)); for (row = 0; row < enc->rows; row++) for (col = 0; col < enc->cols; col++) enc->charset2uni[row][col] = 0xfffd; c = getc(stdin); ungetc(c,stdin); if (c == '#') { /* Read a unicode.org style .TXT file. */ for (;;) { c = getc(stdin); if (c == EOF) break; if (c == '\n' || c == ' ' || c == '\t') continue; if (c == '#') { do { c = getc(stdin); } while (!(c == EOF || c == '\n')); continue; } ungetc(c,stdin); if (scanf("0x%x", &j) != 1) exit(1); i1 = j >> 8; i2 = j & 0xff; row = enc->byte_row(i1); col = enc->byte_col(i2); if (row < 0 || col < 0) { fprintf(stderr, "lost entry for %02x %02x\n", i1, i2); exit(1); } if (scanf(" 0x%x", &enc->charset2uni[row][col]) != 1) exit(1); } } else { /* Read a table of hexadecimal Unicode values. */ for (i1 = 32; i1 < 132; i1++) for (i2 = 32; i2 < 132; i2++) { i = scanf("%x", &j); if (i == EOF) goto read_done; if (i != 1) exit(1); if (j < 0 || j == 0xffff) j = 0xfffd; if (j != 0xfffd) { if (enc->byte_row(i1) < 0 || enc->byte_col(i2) < 0) { fprintf(stderr, "lost entry at %02x %02x\n", i1, i2); exit (1); } enc->charset2uni[enc->byte_row(i1)][enc->byte_col(i2)] = j; } } read_done: ; } } /* * Computes the charsetpage[0..rows] array. */ static void find_charset2uni_pages (Encoding* enc) { int row, col; enc->charsetpage = (int*) malloc((enc->rows+1)*sizeof(int)); for (row = 0; row <= enc->rows; row++) enc->charsetpage[row] = 0; for (row = 0; row < enc->rows; row++) { int used = 0; for (col = 0; col < enc->cols; col++) if (enc->charset2uni[row][col] != 0xfffd) used = col+1; enc->charsetpage[row] = used; } } /* * Fills in nblocks and blocks. */ static void find_charset2uni_blocks (Encoding* enc) { int n, row, lastrow; enc->charsetblocks = (Block*) malloc(enc->rows*sizeof(Block)); n = 0; for (row = 0; row < enc->rows; row++) if (enc->charsetpage[row] > 0 && (row == 0 || enc->charsetpage[row-1] == 0)) { for (lastrow = row; enc->charsetpage[lastrow+1] > 0; lastrow++); enc->charsetblocks[n].start = row * enc->cols; enc->charsetblocks[n].end = lastrow * enc->cols + enc->charsetpage[lastrow]; n++; } enc->ncharsetblocks = n; } /* * Outputs the charset to unicode table and function. */ static void output_charset2uni (const char* name, Encoding* enc) { int row, col, lastrow, col_max, i, i1_min, i1_max; find_charset2uni_pages(enc); find_charset2uni_blocks(enc); for (row = 0; row < enc->rows; row++) if (enc->charsetpage[row] > 0) { if (row == 0 || enc->charsetpage[row-1] == 0) { /* Start a new block. */ for (lastrow = row; enc->charsetpage[lastrow+1] > 0; lastrow++); printf("static const unsigned short %s_2uni_page%02x[%d] = {\n", name, enc->row_byte(row), (lastrow-row) * enc->cols + enc->charsetpage[lastrow]); } printf(" /""* 0x%02x *""/\n ", enc->row_byte(row)); col_max = (enc->charsetpage[row+1] > 0 ? enc->cols : enc->charsetpage[row]); for (col = 0; col < col_max; col++) { printf(" 0x%04x,", enc->charset2uni[row][col]); if ((col % 8) == 7 && (col+1 < col_max)) printf("\n "); } printf("\n"); if (enc->charsetpage[row+1] == 0) { /* End a block. */ printf("};\n"); } } printf("\n"); printf("static int\n"); printf("%s_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n)\n", name); printf("{\n"); printf(" unsigned char c1 = s[0];\n"); printf(" if ("); for (i = 0; i < enc->ncharsetblocks; i++) { i1_min = enc->row_byte(enc->charsetblocks[i].start / enc->cols); i1_max = enc->row_byte((enc->charsetblocks[i].end-1) / enc->cols); if (i > 0) printf(" || "); if (i1_min == i1_max) printf("(c1 == 0x%02x)", i1_min); else printf("(c1 >= 0x%02x && c1 <= 0x%02x)", i1_min, i1_max); } printf(") {\n"); printf(" if (n >= 2) {\n"); printf(" unsigned char c2 = s[1];\n"); printf(" if ("); printf(enc->check_col_expr, "c2"); printf(") {\n"); printf(" unsigned int i = %d * (", enc->cols); printf(enc->byte_row_expr, "c1"); printf(") + ("); printf(enc->byte_col_expr, "c2"); printf(");\n"); printf(" unsigned short wc = 0xfffd;\n"); for (i = 0; i < enc->ncharsetblocks; i++) { printf(" "); if (i > 0) printf("} else "); if (i < enc->ncharsetblocks-1) printf("if (i < %d) ", enc->charsetblocks[i+1].start); printf("{\n"); printf(" if (i < %d)\n", enc->charsetblocks[i].end); printf(" wc = %s_2uni_page%02x[i", name, enc->row_byte(enc->charsetblocks[i].start / enc->cols)); if (enc->charsetblocks[i].start > 0) printf("-%d", enc->charsetblocks[i].start); printf("];\n"); } printf(" }\n"); printf(" if (wc != 0xfffd) {\n"); printf(" *pwc = (ucs4_t) wc;\n"); printf(" return 2;\n"); printf(" }\n"); printf(" }\n"); printf(" return RET_ILSEQ;\n"); printf(" }\n"); printf(" return RET_TOOFEW(0);\n"); printf(" }\n"); printf(" return RET_ILSEQ;\n"); printf("}\n"); printf("\n"); } /* * Computes the uni2charset[0x0000..0xffff] array. */ static void invert (Encoding* enc) { int row, col, j; enc->uni2charset = (int*) malloc(0x10000*sizeof(int)); for (j = 0; j < 0x10000; j++) enc->uni2charset[j] = 0; for (row = 0; row < enc->rows; row++) for (col = 0; col < enc->cols; col++) { j = enc->charset2uni[row][col]; if (j != 0xfffd) enc->uni2charset[j] = 0x100 * enc->row_byte(row) + enc->col_byte(col); } } /* * Outputs the unicode to charset table and function, using a linear array. * (Suitable if the table is dense.) */ static void output_uni2charset_dense (const char* name, Encoding* enc) { /* Like in 8bit_tab_to_h.c */ bool pages[0x100]; int line[0x2000]; int tableno; struct { int minline; int maxline; int usecount; } tables[0x2000]; bool first; int row, col, j, p, j1, j2, t; for (p = 0; p < 0x100; p++) pages[p] = false; for (row = 0; row < enc->rows; row++) for (col = 0; col < enc->cols; col++) { j = enc->charset2uni[row][col]; if (j != 0xfffd) pages[j>>8] = true; } for (j1 = 0; j1 < 0x2000; j1++) { bool all_invalid = true; for (j2 = 0; j2 < 8; j2++) { j = 8*j1+j2; if (enc->uni2charset[j] != 0) all_invalid = false; } if (all_invalid) line[j1] = -1; else line[j1] = 0; } tableno = 0; for (j1 = 0; j1 < 0x2000; j1++) { if (line[j1] >= 0) { if (tableno > 0 && ((j1 > 0 && line[j1-1] == tableno-1) || ((tables[tableno-1].maxline >> 5) == (j1 >> 5) && j1 - tables[tableno-1].maxline <= 8))) { line[j1] = tableno-1; tables[tableno-1].maxline = j1; } else { tableno++; line[j1] = tableno-1; tables[tableno-1].minline = tables[tableno-1].maxline = j1; } } } for (t = 0; t < tableno; t++) { tables[t].usecount = 0; j1 = 8*tables[t].minline; j2 = 8*(tables[t].maxline+1); for (j = j1; j < j2; j++) if (enc->uni2charset[j] != 0) tables[t].usecount++; } { p = -1; for (t = 0; t < tableno; t++) if (tables[t].usecount > 1) { /* p = tables[t].minline >> 5; */ p = tables[t].minline ; /* printf("static const unsigned short %s_page%02x[%d] = {\n", name, p, 8*(tables[t].maxline-tables[t].minline+1)); */ printf("static const unsigned short %s_page%04x[%d] = {\n", name, p, 8*(tables[t].maxline-tables[t].minline+1)); for (j1 = tables[t].minline; j1 <= tables[t].maxline; j1++) { if ((j1 % 0x20) == 0 && j1 > tables[t].minline) printf(" /* 0x%04x */\n", 8*j1); printf(" "); for (j2 = 0; j2 < 8; j2++) { j = 8*j1+j2; printf(" 0x%04x,", enc->uni2charset[j]); } printf(" /*0x%02x-0x%02x*/\n", 8*(j1 % 0x20), 8*(j1 % 0x20)+7); } printf("};\n"); } if (p >= 0) printf("\n"); } printf("static int\n%s_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n)\n", name); printf("{\n"); printf(" if (n >= 2) {\n"); printf(" unsigned short c = 0;\n"); first = true; for (j1 = 0; j1 < 0x2000;) { t = line[j1]; for (j2 = j1; j2 < 0x2000 && line[j2] == t; j2++); if (t >= 0) { if (j1 != tables[t].minline) abort(); if (j2 > tables[t].maxline+1) abort(); j2 = tables[t].maxline+1; if (first) printf(" "); else printf(" else "); first = false; if (tables[t].usecount == 0) abort(); if (tables[t].usecount == 1) { if (j2 != j1+1) abort(); for (j = 8*j1; j < 8*j2; j++) if (enc->uni2charset[j] != 0) { printf("if (wc == 0x%04x)\n c = 0x%02x;\n", j, enc->uni2charset[j]); break; } } else { if (j1 == 0) { printf("if (wc < 0x%04x)", 8*j2); } else { printf("if (wc >= 0x%04x && wc < 0x%04x)", 8*j1, 8*j2); } /* printf("\n c = %s_page%02x[wc", name, j1 >> 5); */ printf("\n c = %s_page%04x[wc", name, j1); if (tables[t].minline > 0) printf("-0x%04x", 8*j1); printf("];\n"); } } j1 = j2; } printf(" if (c != 0) {\n"); printf(" r[0] = (c >> 8); r[1] = (c & 0xff);\n"); printf(" return 2;\n"); printf(" }\n"); printf(" return RET_ILSEQ;\n"); printf(" }\n"); printf(" return RET_TOOSMALL;\n"); printf("}\n"); } /* * Outputs the unicode to charset table and function, using a packed array. * (Suitable if the table is sparse.) */ static void output_uni2charset_sparse (const char* name, Encoding* enc) { bool pages[0x100]; Block pageblocks[0x100]; int npageblocks; int indx2charset[0x10000]; int summary_indx[0x1000]; int summary_used[0x1000]; int i, row, col, j, p, j1, j2, indx; /* Fill pages[0x100]. */ for (p = 0; p < 0x100; p++) pages[p] = false; for (row = 0; row < enc->rows; row++) for (col = 0; col < enc->cols; col++) { j = enc->charset2uni[row][col]; if (j != 0xfffd) pages[j>>8] = true; } #if 0 for (p = 0; p < 0x100; p++) if (pages[p]) { printf("static const unsigned short %s_page%02x[256] = {\n", name, p); for (j1 = 0; j1 < 32; j1++) { printf(" "); for (j2 = 0; j2 < 8; j2++) printf("0x%04x, ", enc->uni2charset[256*p+8*j1+j2]); printf("/""*0x%02x-0x%02x*""/\n", 8*j1, 8*j1+7); } printf("};\n"); } printf("\n"); #endif /* Fill summary_indx[] and summary_used[]. */ indx = 0; for (j1 = 0; j1 < 0x1000; j1++) { summary_indx[j1] = indx; summary_used[j1] = 0; for (j2 = 0; j2 < 16; j2++) { j = 16*j1+j2; if (enc->uni2charset[j] != 0) { indx2charset[indx++] = enc->uni2charset[j]; summary_used[j1] |= (1 << j2); } } } /* Fill npageblocks and pageblocks[]. */ npageblocks = 0; for (p = 0; p < 0x100; ) { if (pages[p] && (p == 0 || !pages[p-1])) { pageblocks[npageblocks].start = 16*p; do p++; while (p < 0x100 && pages[p]); j1 = 16*p; while (summary_used[j1-1] == 0) j1--; pageblocks[npageblocks].end = j1; npageblocks++; } else p++; } printf("static const unsigned short %s_2charset[%d] = {\n", name, indx); for (i = 0; i < indx; ) { if ((i % 8) == 0) printf(" "); printf(" 0x%04x,", indx2charset[i]); i++; if ((i % 8) == 0 || i == indx) printf("\n"); } printf("};\n"); printf("\n"); for (i = 0; i < npageblocks; i++) { printf("static const Summary16 %s_uni2indx_page%02x[%d] = {\n", name, pageblocks[i].start/16, pageblocks[i].end-pageblocks[i].start); for (j1 = pageblocks[i].start; j1 < pageblocks[i].end; ) { if (((16*j1) % 0x100) == 0) printf(" /""* 0x%04x *""/\n", 16*j1); if ((j1 % 4) == 0) printf(" "); printf(" { %4d, 0x%04x },", summary_indx[j1], summary_used[j1]); j1++; if ((j1 % 4) == 0 || j1 == pageblocks[i].end) printf("\n"); } printf("};\n"); } printf("\n"); printf("static int\n"); printf("%s_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n)\n", name); printf("{\n"); printf(" if (n >= 2) {\n"); printf(" const Summary16 *summary = NULL;\n"); for (i = 0; i < npageblocks; i++) { printf(" "); if (i > 0) printf("else "); printf("if (wc >= 0x%04x && wc < 0x%04x)\n", 16*pageblocks[i].start, 16*pageblocks[i].end); printf(" summary = &%s_uni2indx_page%02x[(wc>>4)", name, pageblocks[i].start/16); if (pageblocks[i].start > 0) printf("-0x%03x", pageblocks[i].start); printf("];\n"); } printf(" if (summary) {\n"); printf(" unsigned short used = summary->used;\n"); printf(" unsigned int i = wc & 0x0f;\n"); printf(" if (used & ((unsigned short) 1 << i)) {\n"); printf(" unsigned short c;\n"); printf(" /* Keep in `used' only the bits 0..i-1. */\n"); printf(" used &= ((unsigned short) 1 << i) - 1;\n"); printf(" /* Add `summary->indx' and the number of bits set in `used'. */\n"); printf(" used = (used & 0x5555) + ((used & 0xaaaa) >> 1);\n"); printf(" used = (used & 0x3333) + ((used & 0xcccc) >> 2);\n"); printf(" used = (used & 0x0f0f) + ((used & 0xf0f0) >> 4);\n"); printf(" used = (used & 0x00ff) + (used >> 8);\n"); printf(" c = %s_2charset[summary->indx + used];\n", name); printf(" r[0] = (c >> 8); r[1] = (c & 0xff);\n"); printf(" return 2;\n"); printf(" }\n"); printf(" }\n"); printf(" return RET_ILSEQ;\n"); printf(" }\n"); printf(" return RET_TOOSMALL;\n"); printf("}\n"); } /* ISO-2022/EUC specifics */ static int row_byte_normal (int row) { return 0x21+row; } static int col_byte_normal (int col) { return 0x21+col; } static int byte_row_normal (int byte) { return byte-0x21; } static int byte_col_normal (int byte) { return byte-0x21; } static void do_normal (const char* name) { Encoding enc; enc.rows = 94; enc.cols = 94; enc.row_byte = row_byte_normal; enc.col_byte = col_byte_normal; enc.byte_row = byte_row_normal; enc.byte_col = byte_col_normal; enc.check_row_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.check_col_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.byte_row_expr = "%1$s - 0x21"; enc.byte_col_expr = "%1$s - 0x21"; read_table(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_sparse(name,&enc); } /* Note: On first sight, the jisx0212_2charset[] table seems to be in order, starting from the charset=0x3021/uni=0x4e02 pair. But it's only mostly in order. There are 75 out-of-order values, scattered all throughout the table. */ static void do_normal_only_charset2uni (const char* name) { Encoding enc; enc.rows = 94; enc.cols = 94; enc.row_byte = row_byte_normal; enc.col_byte = col_byte_normal; enc.byte_row = byte_row_normal; enc.byte_col = byte_col_normal; enc.check_row_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.check_col_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.byte_row_expr = "%1$s - 0x21"; enc.byte_col_expr = "%1$s - 0x21"; read_table(&enc); output_charset2uni(name,&enc); } /* CNS 11643 specifics - trick to put two tables into one */ static int row_byte_cns11643 (int row) { return 0x100 * (row / 94) + (row % 94) + 0x21; } static int byte_row_cns11643 (int byte) { return (byte >= 0x100 && byte < 0x200 ? byte-0x121 : byte >= 0x200 && byte < 0x300 ? byte-0x221+94 : byte >= 0x300 && byte < 0x400 ? byte-0x321+2*94 : -1); } static void do_cns11643_only_uni2charset (const char* name) { Encoding enc; int j, x; enc.rows = 3*94; enc.cols = 94; enc.row_byte = row_byte_cns11643; enc.col_byte = col_byte_normal; enc.byte_row = byte_row_cns11643; enc.byte_col = byte_col_normal; enc.check_row_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.check_col_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.byte_row_expr = "%1$s - 0x21"; enc.byte_col_expr = "%1$s - 0x21"; read_table(&enc); invert(&enc); /* Move the 2 plane bits into the unused bits 15 and 7. */ for (j = 0; j < 0x10000; j++) { x = enc.uni2charset[j]; if (x != 0) { if (x & 0x8080) abort(); switch (x >> 16) { case 0: /* plane 1 */ x = (x & 0xffff) | 0x0000; break; case 1: /* plane 2 */ x = (x & 0xffff) | 0x0080; break; case 2: /* plane 3 */ x = (x & 0xffff) | 0x8000; break; default: abort(); } enc.uni2charset[j] = x; } } output_uni2charset_sparse(name,&enc); } /* GBK specifics */ static int row_byte_gbk1 (int row) { return 0x81+row; } static int col_byte_gbk1 (int col) { return (col >= 0x3f ? 0x41 : 0x40) + col; } static int byte_row_gbk1 (int byte) { if (byte >= 0x81 && byte < 0xff) return byte-0x81; else return -1; } static int byte_col_gbk1 (int byte) { if (byte >= 0x40 && byte < 0x7f) return byte-0x40; else if (byte >= 0x80 && byte < 0xff) return byte-0x41; else return -1; } static void do_gbk1 (const char* name) { Encoding enc; enc.rows = 126; enc.cols = 190; enc.row_byte = row_byte_gbk1; enc.col_byte = col_byte_gbk1; enc.byte_row = byte_row_gbk1; enc.byte_col = byte_col_gbk1; enc.check_row_expr = "%1$s >= 0x81 && %1$s < 0xff"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0x80 && %1$s < 0xff)"; enc.byte_row_expr = "%1$s - 0x81"; enc.byte_col_expr = "%1$s - (%1$s >= 0x80 ? 0x41 : 0x40)"; read_table(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_dense(name,&enc); } static void do_gbk1_only_charset2uni (const char* name) { Encoding enc; enc.rows = 126; enc.cols = 190; enc.row_byte = row_byte_gbk1; enc.col_byte = col_byte_gbk1; enc.byte_row = byte_row_gbk1; enc.byte_col = byte_col_gbk1; enc.check_row_expr = "%1$s >= 0x81 && %1$s < 0xff"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0x80 && %1$s < 0xff)"; enc.byte_row_expr = "%1$s - 0x81"; enc.byte_col_expr = "%1$s - (%1$s >= 0x80 ? 0x41 : 0x40)"; read_table(&enc); output_charset2uni(name,&enc); } static int row_byte_gbk2 (int row) { return 0x81+row; } static int col_byte_gbk2 (int col) { return (col >= 0x3f ? 0x41 : 0x40) + col; } static int byte_row_gbk2 (int byte) { if (byte >= 0x81 && byte < 0xff) return byte-0x81; else return -1; } static int byte_col_gbk2 (int byte) { if (byte >= 0x40 && byte < 0x7f) return byte-0x40; else if (byte >= 0x80 && byte < 0xa1) return byte-0x41; else return -1; } static void do_gbk2_only_charset2uni (const char* name) { Encoding enc; enc.rows = 126; enc.cols = 96; enc.row_byte = row_byte_gbk2; enc.col_byte = col_byte_gbk2; enc.byte_row = byte_row_gbk2; enc.byte_col = byte_col_gbk2; enc.check_row_expr = "%1$s >= 0x81 && %1$s < 0xff"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0x80 && %1$s < 0xa1)"; enc.byte_row_expr = "%1$s - 0x81"; enc.byte_col_expr = "%1$s - (%1$s >= 0x80 ? 0x41 : 0x40)"; read_table(&enc); output_charset2uni(name,&enc); } static void do_gbk1_only_uni2charset (const char* name) { Encoding enc; enc.rows = 126; enc.cols = 190; enc.row_byte = row_byte_gbk1; enc.col_byte = col_byte_gbk1; enc.byte_row = byte_row_gbk1; enc.byte_col = byte_col_gbk1; enc.check_row_expr = "%1$s >= 0x81 && %1$s < 0xff"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0x80 && %1$s < 0xff)"; enc.byte_row_expr = "%1$s - 0x81"; enc.byte_col_expr = "%1$s - (%1$s >= 0x80 ? 0x41 : 0x40)"; read_table(&enc); invert(&enc); output_uni2charset_sparse(name,&enc); } /* KSC 5601 specifics */ /* * Reads the charset2uni table from standard input. */ static void read_table_ksc5601 (Encoding* enc) { int row, col, i, i1, i2, c, j; enc->charset2uni = (int**) malloc(enc->rows*sizeof(int*)); for (row = 0; row < enc->rows; row++) enc->charset2uni[row] = (int*) malloc(enc->cols*sizeof(int)); for (row = 0; row < enc->rows; row++) for (col = 0; col < enc->cols; col++) enc->charset2uni[row][col] = 0xfffd; c = getc(stdin); ungetc(c,stdin); if (c == '#') { /* Read a unicode.org style .TXT file. */ for (;;) { c = getc(stdin); if (c == EOF) break; if (c == '\n' || c == ' ' || c == '\t') continue; if (c == '#') { do { c = getc(stdin); } while (!(c == EOF || c == '\n')); continue; } ungetc(c,stdin); if (scanf("0x%x", &j) != 1) exit(1); i1 = j >> 8; i2 = j & 0xff; if (scanf(" 0x%x", &j) != 1) exit(1); /* Take only the range covered by KS C 5601.1987-0 = KS C 5601.1989-0 = KS X 1001.1992, ignore the rest. */ if (!(i1 >= 128+33 && i1 < 128+127 && i2 >= 128+33 && i2 < 128+127)) continue; /* KSC5601 specific */ i1 &= 0x7f; /* KSC5601 specific */ i2 &= 0x7f; /* KSC5601 specific */ row = enc->byte_row(i1); col = enc->byte_col(i2); if (row < 0 || col < 0) { fprintf(stderr, "lost entry for %02x %02x\n", i1, i2); exit(1); } enc->charset2uni[row][col] = j; } } else { /* Read a table of hexadecimal Unicode values. */ for (i1 = 33; i1 < 127; i1++) for (i2 = 33; i2 < 127; i2++) { i = scanf("%x", &j); if (i == EOF) goto read_done; if (i != 1) exit(1); if (j < 0 || j == 0xffff) j = 0xfffd; if (j != 0xfffd) { if (enc->byte_row(i1) < 0 || enc->byte_col(i2) < 0) { fprintf(stderr, "lost entry at %02x %02x\n", i1, i2); exit (1); } enc->charset2uni[enc->byte_row(i1)][enc->byte_col(i2)] = j; } } read_done: ; } } static void do_ksc5601 (const char* name) { Encoding enc; enc.rows = 94; enc.cols = 94; enc.row_byte = row_byte_normal; enc.col_byte = col_byte_normal; enc.byte_row = byte_row_normal; enc.byte_col = byte_col_normal; enc.check_row_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.check_col_expr = "%1$s >= 0x21 && %1$s < 0x7f"; enc.byte_row_expr = "%1$s - 0x21"; enc.byte_col_expr = "%1$s - 0x21"; read_table_ksc5601(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_sparse(name,&enc); } /* Big5 specifics */ static int row_byte_big5 (int row) { return 0xa1+row; } static int col_byte_big5 (int col) { return (col >= 0x3f ? 0x62 : 0x40) + col; } static int byte_row_big5 (int byte) { if (byte >= 0xa1 && byte < 0xff) return byte-0xa1; else return -1; } static int byte_col_big5 (int byte) { if (byte >= 0x40 && byte < 0x7f) return byte-0x40; else if (byte >= 0xa1 && byte < 0xff) return byte-0x62; else return -1; } static void do_big5 (const char* name) { Encoding enc; enc.rows = 94; enc.cols = 157; enc.row_byte = row_byte_big5; enc.col_byte = col_byte_big5; enc.byte_row = byte_row_big5; enc.byte_col = byte_col_big5; enc.check_row_expr = "%1$s >= 0xa1 && %1$s < 0xff"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0xa1 && %1$s < 0xff)"; enc.byte_row_expr = "%1$s - 0xa1"; enc.byte_col_expr = "%1$s - (%1$s >= 0xa1 ? 0x62 : 0x40)"; read_table(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_sparse(name,&enc); } /* Johab Hangul specifics */ static int row_byte_johab_hangul (int row) { return 0x84+row; } static int col_byte_johab_hangul (int col) { return (col >= 0x3e ? 0x43 : 0x41) + col; } static int byte_row_johab_hangul (int byte) { if (byte >= 0x84 && byte < 0xd4) return byte-0x84; else return -1; } static int byte_col_johab_hangul (int byte) { if (byte >= 0x41 && byte < 0x7f) return byte-0x41; else if (byte >= 0x81 && byte < 0xff) return byte-0x43; else return -1; } static void do_johab_hangul (const char* name) { Encoding enc; enc.rows = 80; enc.cols = 188; enc.row_byte = row_byte_johab_hangul; enc.col_byte = col_byte_johab_hangul; enc.byte_row = byte_row_johab_hangul; enc.byte_col = byte_col_johab_hangul; enc.check_row_expr = "%1$s >= 0x84 && %1$s < 0xd4"; enc.check_col_expr = "(%1$s >= 0x41 && %1$s < 0x7f) || (%1$s >= 0x81 && %1$s < 0xff)"; enc.byte_row_expr = "%1$s - 0x84"; enc.byte_col_expr = "%1$s - (%1$s >= 0x81 ? 0x43 : 0x41)"; read_table(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_dense(name,&enc); } /* SJIS specifics */ static int row_byte_sjis (int row) { return (row >= 0x1f ? 0xc1 : 0x81) + row; } static int col_byte_sjis (int col) { return (col >= 0x3f ? 0x41 : 0x40) + col; } static int byte_row_sjis (int byte) { if (byte >= 0x81 && byte < 0xa0) return byte-0x81; else if (byte >= 0xe0) return byte-0xc1; else return -1; } static int byte_col_sjis (int byte) { if (byte >= 0x40 && byte < 0x7f) return byte-0x40; else if (byte >= 0x80 && byte < 0xfd) return byte-0x41; else return -1; } static void do_sjis (const char* name) { Encoding enc; enc.rows = 94; enc.cols = 188; enc.row_byte = row_byte_sjis; enc.col_byte = col_byte_sjis; enc.byte_row = byte_row_sjis; enc.byte_col = byte_col_sjis; enc.check_row_expr = "(%1$s >= 0x81 && %1$s < 0xa0) || (%1$s >= 0xe0)"; enc.check_col_expr = "(%1$s >= 0x40 && %1$s < 0x7f) || (%1$s >= 0x80 && %1$s < 0xfd)"; enc.byte_row_expr = "%1$s - (%1$s >= 0xe0 ? 0xc1 : 0x81)"; enc.byte_col_expr = "%1$s - (%1$s >= 0x80 ? 0x41 : 0x40)"; read_table(&enc); output_charset2uni(name,&enc); invert(&enc); output_uni2charset_sparse(name,&enc); } /* Main program */ int main (int argc, char *argv[]) { const char* charsetname; const char* name; if (argc != 3) exit(1); charsetname = argv[1]; name = argv[2]; output_title(charsetname); if (!strcmp(name,"gb2312") || !strcmp(name,"gb12345ext") || !strcmp(name,"jisx0208") || !strcmp(name,"jisx0212")) do_normal(name); else if (!strcmp(name,"cns11643_1") || !strcmp(name,"cns11643_2") || !strcmp(name,"cns11643_3")) do_normal_only_charset2uni(name); else if (!strcmp(name,"cns11643_inv")) do_cns11643_only_uni2charset(name); else if (!strcmp(name,"gbkext1")) do_gbk1_only_charset2uni(name); else if (!strcmp(name,"gbkext2")) do_gbk2_only_charset2uni(name); else if (!strcmp(name,"gbkext_inv")) do_gbk1_only_uni2charset(name); else if (!strcmp(name,"cp936ext")) do_gbk1(name); else if (!strcmp(name,"ksc5601")) do_ksc5601(name); else if (!strcmp(name,"big5") || !strcmp(name,"cp950ext")) do_big5(name); else if (!strcmp(name,"johab_hangul")) do_johab_hangul(name); else if (!strcmp(name,"cp932ext")) do_sjis(name); else exit(1); return 0; } fltk-1.4.3/src/xutf8/lcUniConv/jisx0201.h0000644000175000017500000000175015004135251020006 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/jisx0201.h,v 1.3 2000/11/29 17:40:33 dawes Exp $ */ /* * JISX0201.1976-0 */ #ifdef NEED_TOWC static int jisx0201_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x80) { if (c == 0x5c) *pwc = (ucs4_t) 0x00a5; else if (c == 0x7e) *pwc = (ucs4_t) 0x203e; else *pwc = (ucs4_t) c; return 1; } else { if (c >= 0xa1 && c < 0xe0) { *pwc = (ucs4_t) c + 0xfec0; return 1; } } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static int jisx0201_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; if (wc < 0x0080 && !(wc == 0x005c || wc == 0x007e)) { *r = wc; return 1; } if (wc == 0x00a5) { *r = 0x5c; return 1; } if (wc == 0x203e) { *r = 0x7e; return 1; } if (wc >= 0xff61 && wc < 0xffa0) { *r = wc - 0xfec0; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/iso8859_10.h0000644000175000017500000000704715004135251020163 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_10.h,v 1.3 2000/11/29 17:40:30 dawes Exp $ */ /* * ISO-8859-10 */ #ifdef NEED_TOWC static const unsigned short iso8859_10_2uni[96] = { /* 0xa0 */ 0x00a0, 0x0104, 0x0112, 0x0122, 0x012a, 0x0128, 0x0136, 0x00a7, 0x013b, 0x0110, 0x0160, 0x0166, 0x017d, 0x00ad, 0x016a, 0x014a, /* 0xb0 */ 0x00b0, 0x0105, 0x0113, 0x0123, 0x012b, 0x0129, 0x0137, 0x00b7, 0x013c, 0x0111, 0x0161, 0x0167, 0x017e, 0x2015, 0x016b, 0x014b, /* 0xc0 */ 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x00cf, /* 0xd0 */ 0x00d0, 0x0145, 0x014c, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0168, 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, /* 0xe0 */ 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x00ef, /* 0xf0 */ 0x00f0, 0x0146, 0x014d, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x0169, 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x0138, }; static int iso8859_10_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) iso8859_10_2uni[c-0xa0]; return 1; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_10_page00[224] = { 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */ 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, /* 0xb0-0xb7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ 0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0x00, /* 0xc0-0xc7 */ 0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */ 0xd0, 0x00, 0x00, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* 0xd0-0xd7 */ 0xd8, 0x00, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */ 0x00, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0x00, /* 0xe0-0xe7 */ 0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0xef, /* 0xe8-0xef */ 0xf0, 0x00, 0x00, 0xf3, 0xf4, 0xf5, 0xf6, 0x00, /* 0xf0-0xf7 */ 0xf8, 0x00, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00, /* 0xf8-0xff */ /* 0x0100 */ 0xc0, 0xe0, 0x00, 0x00, 0xa1, 0xb1, 0x00, 0x00, /* 0x00-0x07 */ 0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00, /* 0x08-0x0f */ 0xa9, 0xb9, 0xa2, 0xb2, 0x00, 0x00, 0xcc, 0xec, /* 0x10-0x17 */ 0xca, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0xa3, 0xb3, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0xa5, 0xb5, 0xa4, 0xb4, 0x00, 0x00, 0xc7, 0xe7, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0xb6, /* 0x30-0x37 */ 0xff, 0x00, 0x00, 0xa8, 0xb8, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf1, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0xaf, 0xbf, 0xd2, 0xf2, 0x00, 0x00, /* 0x48-0x4f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0xaa, 0xba, 0x00, 0x00, 0x00, 0x00, 0xab, 0xbb, /* 0x60-0x67 */ 0xd7, 0xf7, 0xae, 0xbe, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0xd9, 0xf9, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0xbc, 0x00, /* 0x78-0x7f */ }; static int iso8859_10_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x0180) c = iso8859_10_page00[wc-0x00a0]; else if (wc == 0x2015) c = 0xbd; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/iso8859_11.h0000644000175000017500000000514615004135251020162 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_11.h,v 1.2 2002/10/09 16:38:19 tsi Exp $ */ /* * ISO8859-11 */ #ifdef NEED_TOWC static const unsigned short iso8859_11_2uni[96] = { /* 0xa0 */ 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, /* 0xb0 */ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, /* 0xc0 */ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, /* 0xd0 */ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0e3f, /* 0xe0 */ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f, /* 0xf0 */ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xfffd, 0xfffd, 0xfffd, 0xfffd, }; static int iso8859_11_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x80) { *pwc = (ucs4_t) c; return 1; } else if (c < 0xa0) { } else { unsigned short wc = iso8859_11_2uni[c-0xa0]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_11_page0e[96] = { 0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x00-0x07 */ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0x08-0x0f */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x10-0x17 */ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0x18-0x1f */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x20-0x27 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x28-0x2f */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x30-0x37 */ 0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0xdf, /* 0x38-0x3f */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x40-0x47 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x48-0x4f */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x50-0x57 */ 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ }; static int iso8859_11_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x0080 || wc == 0x00a0) { *r = wc; return 1; } else if (wc >= 0x0e00 && wc < 0x0e60) c = iso8859_11_page0e[wc-0x0e00]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/big5_emacs.h0000644000175000017500000001122215004135251020517 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/big5_emacs.h,v 1.1 2000/11/28 18:50:06 dawes Exp $ */ /* * BIG5-0 and BIG5-1 */ /* BIG5 with its 13494 characters doesn't fit in a single 94x94 or 96x96 block. Therefore Emacs/Mule developers, in a typically Japanese way of thinking, have developed an alternative encoding of BIG5 in two 94x94 planes, very similar to the SHIFT_JIS encoding for JISX0208. Conversion between BIG5 codes (s1,s2) and BIG5-0 codes (c1,c2): Example. (s1,s2) = 0xA140, (c1,c2) = 0x2121. 0xA1 <= s1 <= 0xC7, 0x40 <= s2 <= 0x7E || 0xA1 <= s2 <= 0xFE, 0x21 <= c1 <= 0x62, 0x21 <= c2 <= 0x7E. Invariant: 157*(s1-0xA1) + (s2 < 0x80 ? s2-0x40 : s2-0x62) = 94*(c1-0x21)+(c2-0x21) Conversion (s1,s2) -> (c1,c2): t := 157*(s1-0xA1) + (s2 < 0x80 ? s2-0x40 : s2-0x62) c1 := (t div 94) + 0x21 c2 := (t mod 94) + 0x21 Conversion (c1,c2) -> (s1,s2): t := 94*(c1-0x21)+(c2-0x21) t2 := t mod 157 s1 := (t div 157) + 0xA1 s2 := (t2 < 0x3F ? t2+0x40 : t2+0x62) Conversion between BIG5 codes (s1,s2) and BIG5-1 codes (c1,c2): Example. (s1,s2) = 0xC940, (c1,c2) = 0x2121. 0xC9 <= s1 <= 0xF9, 0x40 <= s2 <= 0x7E || 0xA1 <= s2 <= 0xFE, 0x21 <= c1 <= 0x72, 0x21 <= c2 <= 0x7E. Invariant: 157*(s1-0xC9) + (s2 < 0x80 ? s2-0x40 : s2-0x62) = 94*(c1-0x21)+(c2-0x21) Conversion (s1,s2) -> (c1,c2): t := 157*(s1-0xC9) + (s2 < 0x80 ? s2-0x40 : s2-0x62) c1 := (t div 94) + 0x21 c2 := (t mod 94) + 0x21 Conversion (c1,c2) -> (s1,s2): t := 94*(c1-0x21)+(c2-0x21) t2 := t mod 157 s1 := (t div 157) + 0xC9 s2 := (t2 < 0x3F ? t2+0x40 : t2+0x62) */ static int big5_0_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c1 = s[0]; if (c1 >= 0x21 && c1 <= 0x62) { if (n >= 2) { unsigned char c2 = s[1]; if (c2 >= 0x21 && c2 <= 0x7e) { unsigned int i = 94 * (c1 - 0x21) + (c2 - 0x21); if (0) { /* Unoptimized. */ unsigned char buf[2]; buf[0] = (i / 157) + 0xa1; i = i % 157; buf[1] = i + (i < 0x3f ? 0x40 : 0x62); return big5_mbtowc(conv,pwc,buf,2); } else { /* Inline the implementation of big5_mbtowc. */ if (i < 6121) { unsigned short wc = big5_2uni_pagea1[i]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 2; } } } } return RET_ILSEQ; } return RET_TOOFEW(0); } return RET_ILSEQ; } static int big5_1_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c1 = s[0]; if (c1 >= 0x21 && c1 <= 0x72) { if (n >= 2) { unsigned char c2 = s[1]; if (c2 >= 0x21 && c2 <= 0x7e) { unsigned int i = 94 * (c1 - 0x21) + (c2 - 0x21); if (0) { /* Unoptimized. */ unsigned char buf[2]; buf[0] = (i / 157) + 0xc9; i = i % 157; buf[1] = i + (i < 0x3f ? 0x40 : 0x62); return big5_mbtowc(conv,pwc,buf,2); } else { /* Inline the implementation of big5_mbtowc. */ if (i < 7652) { unsigned short wc = big5_2uni_pagec9[i]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 2; } } } } return RET_ILSEQ; } return RET_TOOFEW(0); } return RET_ILSEQ; } static int big5_0_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { if (n >= 2) { unsigned char buf[2]; int ret = big5_wctomb(conv,buf,wc,2); if (ret != RET_ILSEQ) { unsigned char s1, s2; if (ret != 2) abort(); s1 = buf[0]; s2 = buf[1]; if (!(s1 >= 0xa1)) abort(); if (!((s2 >= 0x40 && s2 <= 0x7e) || (s2 >= 0xa1 && s2 <= 0xfe))) abort(); if (s1 < 0xc9) { unsigned int t = 157 * (s1 - 0xa1) + s2 - (s2 < 0x80 ? 0x40 : 0x62); r[0] = (t / 94) + 0x21; r[1] = (t % 94) + 0x21; return 2; } } return RET_ILSEQ; } return RET_TOOSMALL; } static int big5_1_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { if (n >= 2) { unsigned char buf[2]; int ret = big5_wctomb(conv,buf,wc,2); if (ret != RET_ILSEQ) { unsigned char s1, s2; if (ret != 2) abort(); s1 = buf[0]; s2 = buf[1]; if (!(s1 <= 0xf9)) abort(); if (!((s2 >= 0x40 && s2 <= 0x7e) || (s2 >= 0xa1 && s2 <= 0xfe))) abort(); if (s1 >= 0xc9) { unsigned int t = 157 * (s1 - 0xc9) + s2 - (s2 < 0x80 ? 0x40 : 0x62); r[0] = (t / 94) + 0x21; r[1] = (t % 94) + 0x21; return 2; } } return RET_ILSEQ; } return RET_TOOSMALL; } fltk-1.4.3/src/xutf8/lcUniConv/iso8859_3.h0000644000175000017500000000753615004135251020110 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_3.h,v 1.3 2000/11/29 17:40:31 dawes Exp $ */ /* * ISO-8859-3 */ #ifdef NEED_TOWC static const unsigned short iso8859_3_2uni[96] = { /* 0xa0 */ 0x00a0, 0x0126, 0x02d8, 0x00a3, 0x00a4, 0xfffd, 0x0124, 0x00a7, 0x00a8, 0x0130, 0x015e, 0x011e, 0x0134, 0x00ad, 0xfffd, 0x017b, /* 0xb0 */ 0x00b0, 0x0127, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x0125, 0x00b7, 0x00b8, 0x0131, 0x015f, 0x011f, 0x0135, 0x00bd, 0xfffd, 0x017c, /* 0xc0 */ 0x00c0, 0x00c1, 0x00c2, 0xfffd, 0x00c4, 0x010a, 0x0108, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, /* 0xd0 */ 0xfffd, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x0120, 0x00d6, 0x00d7, 0x011c, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x016c, 0x015c, 0x00df, /* 0xe0 */ 0x00e0, 0x00e1, 0x00e2, 0xfffd, 0x00e4, 0x010b, 0x0109, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* 0xf0 */ 0xfffd, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x0121, 0x00f6, 0x00f7, 0x011d, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x016d, 0x015d, 0x02d9, }; static int iso8859_3_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) { *pwc = (ucs4_t) c; return 1; } else { unsigned short wc = iso8859_3_2uni[c-0xa0]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_3_page00[96] = { 0xa0, 0x00, 0x00, 0xa3, 0xa4, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */ 0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */ 0xb0, 0x00, 0xb2, 0xb3, 0xb4, 0xb5, 0x00, 0xb7, /* 0xb0-0xb7 */ 0xb8, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, /* 0xb8-0xbf */ 0xc0, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0x00, 0xc7, /* 0xc0-0xc7 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */ 0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */ 0x00, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */ 0xe0, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0x00, 0xe7, /* 0xe0-0xe7 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, /* 0xf0-0xf7 */ 0x00, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */ }; static const unsigned char iso8859_3_page01[120] = { 0xc6, 0xe6, 0xc5, 0xe5, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x00, 0x00, 0x00, 0x00, 0xd8, 0xf8, 0xab, 0xbb, /* 0x18-0x1f */ 0xd5, 0xf5, 0x00, 0x00, 0xa6, 0xb6, 0xa1, 0xb1, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0xa9, 0xb9, 0x00, 0x00, 0xac, 0xbc, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0xde, 0xfe, 0xaa, 0xba, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0xdd, 0xfd, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0xaf, 0xbf, 0x00, 0x00, 0x00, /* 0x78-0x7f */ }; static const unsigned char iso8859_3_page02[8] = { 0xa2, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ }; static int iso8859_3_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x0100) c = iso8859_3_page00[wc-0x00a0]; else if (wc >= 0x0108 && wc < 0x0180) c = iso8859_3_page01[wc-0x0108]; else if (wc >= 0x02d8 && wc < 0x02e0) c = iso8859_3_page02[wc-0x02d8]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/cp1255.h0000644000175000017500000001072415004135251017446 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/cp1255.h,v 1.1 2000/12/04 18:49:33 dawes Exp $ */ /* * CP1255 */ static const unsigned short cp1255_2uni[128] = { /* 0x80 */ 0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0xfffd, 0x2039, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x90 */ 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0xfffd, 0x203a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xa0 */ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20aa, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, /* 0xb0 */ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, /* 0xc0 */ 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, 0x05b8, 0x05b9, 0xfffd, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf, /* 0xd0 */ 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f0, 0x05f1, 0x05f2, 0x05f3, 0x05f4, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xe0 */ 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, /* 0xf0 */ 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0xfffd, 0xfffd, 0x200e, 0x200f, 0xfffd, }; static int cp1255_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x80) { *pwc = (ucs4_t) c; return 1; } else { unsigned short wc = cp1255_2uni[c-0x80]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } return RET_ILSEQ; } static const unsigned char cp1255_page00[88] = { 0xa0, 0xa1, 0xa2, 0xa3, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */ 0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */ 0xb8, 0xb9, 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, /* 0xd0-0xd7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, /* 0xf0-0xf7 */ }; static const unsigned char cp1255_page02[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ }; static const unsigned char cp1255_page05[72] = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xb0-0xb7 */ 0xc8, 0xc9, 0x00, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xb8-0xbf */ 0xd0, 0xd1, 0xd2, 0xd3, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xd0-0xd7 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xd8-0xdf */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xe0-0xe7 */ 0xf8, 0xf9, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */ }; static const unsigned char cp1255_page20[56] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfe, /* 0x08-0x0f */ 0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */ 0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ }; static int cp1255_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x0080) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00f8) c = cp1255_page00[wc-0x00a0]; else if (wc == 0x0192) c = 0x83; else if (wc >= 0x02c0 && wc < 0x02e0) c = cp1255_page02[wc-0x02c0]; else if (wc >= 0x05b0 && wc < 0x05f8) c = cp1255_page05[wc-0x05b0]; else if (wc >= 0x2008 && wc < 0x2040) c = cp1255_page20[wc-0x2008]; else if (wc == 0x20aa) c = 0xa4; else if (wc == 0x20ac) c = 0x80; else if (wc == 0x2122) c = 0x99; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/cp1256.h0000644000175000017500000001345615004135251017454 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/cp1256.h,v 1.1 2000/12/04 18:49:34 dawes Exp $ */ /* * CP1256 */ static const unsigned short cp1256_2uni[128] = { /* 0x80 */ 0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, /* 0x90 */ 0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba, /* 0xa0 */ 0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, /* 0xb0 */ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f, /* 0xc0 */ 0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, /* 0xd0 */ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7, 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643, /* 0xe0 */ 0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef, /* 0xf0 */ 0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7, 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2, }; static int cp1256_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x80) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) cp1256_2uni[c-0x80]; return 1; } static const unsigned char cp1256_page00[96] = { 0xa0, 0x00, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */ 0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */ 0xb8, 0xb9, 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, /* 0xb8-0xbf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, /* 0xd0-0xd7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ 0xe0, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, 0xe7, /* 0xe0-0xe7 */ 0xe8, 0xe9, 0xea, 0xeb, 0x00, 0x00, 0xee, 0xef, /* 0xe8-0xef */ 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */ 0x00, 0xf9, 0x00, 0xfb, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */ }; static const unsigned char cp1256_page01[72] = { 0x00, 0x00, 0x8c, 0x9c, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ }; static const unsigned char cp1256_page06[208] = { 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0xbf, /* 0x18-0x1f */ 0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x20-0x27 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x28-0x2f */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd8, /* 0x30-0x37 */ 0xd9, 0xda, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0xdc, 0xdd, 0xde, 0xdf, 0xe1, 0xe3, 0xe4, 0xe5, /* 0x40-0x47 */ 0xe6, 0xec, 0xed, 0xf0, 0xf1, 0xf2, 0xf3, 0xf5, /* 0x48-0x4f */ 0xf6, 0xf8, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, /* 0x78-0x7f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, /* 0x80-0x87 */ 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, /* 0xa8-0xaf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xaa, 0x00, /* 0xb8-0xbf */ 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ }; static const unsigned char cp1256_page20[56] = { 0x00, 0x00, 0x00, 0x00, 0x9d, 0x9e, 0xfd, 0xfe, /* 0x08-0x0f */ 0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */ 0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ }; static int cp1256_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x0080) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x0100) c = cp1256_page00[wc-0x00a0]; else if (wc >= 0x0150 && wc < 0x0198) c = cp1256_page01[wc-0x0150]; else if (wc == 0x02c6) c = 0x88; else if (wc >= 0x0608 && wc < 0x06d8) c = cp1256_page06[wc-0x0608]; else if (wc >= 0x2008 && wc < 0x2040) c = cp1256_page20[wc-0x2008]; else if (wc == 0x20ac) c = 0x80; else if (wc == 0x2122) c = 0x99; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/cp1251.h0000644000175000017500000001042415004135251017437 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/cp1251.h,v 1.1 2000/12/04 18:49:32 dawes Exp $ */ /* * CP1251 */ #ifdef NEED_TOWC static const unsigned short cp1251_2uni[128] = { /* 0x80 */ 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, /* 0x90 */ 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0xfffd, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, /* 0xa0 */ 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, /* 0xb0 */ 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, /* 0xc0 */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, /* 0xd0 */ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, /* 0xe0 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, /* 0xf0 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, }; static int cp1251_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x80) { *pwc = (ucs4_t) c; return 1; } else { unsigned short wc = cp1251_2uni[c-0x80]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char cp1251_page00[32] = { 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */ 0x00, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00, /* 0xa8-0xaf */ 0xb0, 0xb1, 0x00, 0x00, 0x00, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */ 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ }; static const unsigned char cp1251_page04[152] = { 0x00, 0xa8, 0x80, 0x81, 0xaa, 0xbd, 0xb2, 0xaf, /* 0x00-0x07 */ 0xa3, 0x8a, 0x8c, 0x8e, 0x8d, 0x00, 0xa1, 0x8f, /* 0x08-0x0f */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x10-0x17 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x18-0x1f */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x20-0x27 */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0x28-0x2f */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x30-0x37 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x38-0x3f */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x40-0x47 */ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0x48-0x4f */ 0x00, 0xb8, 0x90, 0x83, 0xba, 0xbe, 0xb3, 0xbf, /* 0x50-0x57 */ 0xbc, 0x9a, 0x9c, 0x9e, 0x9d, 0x00, 0xa2, 0x9f, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0xa5, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ }; static const unsigned char cp1251_page20[48] = { 0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */ 0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ }; static int cp1251_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x0080) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00c0) c = cp1251_page00[wc-0x00a0]; else if (wc >= 0x0400 && wc < 0x0498) c = cp1251_page04[wc-0x0400]; else if (wc >= 0x2010 && wc < 0x2040) c = cp1251_page20[wc-0x2010]; else if (wc == 0x20ac) c = 0x88; else if (wc == 0x2116) c = 0xb9; else if (wc == 0x2122) c = 0x99; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/iso8859_2.h0000644000175000017500000000756315004135251020107 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_2.h,v 1.3 2000/11/29 17:40:31 dawes Exp $ */ /* * ISO-8859-2 */ #ifdef NEED_TOWC static const unsigned short iso8859_2_2uni[96] = { /* 0xa0 */ 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, /* 0xb0 */ 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* 0xc0 */ 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, /* 0xd0 */ 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, /* 0xe0 */ 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, /* 0xf0 */ 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, }; static int iso8859_2_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) iso8859_2_2uni[c-0xa0]; return 1; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_2_page00[224] = { 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */ 0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */ 0xb0, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ 0x00, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0x00, 0xc7, /* 0xc0-0xc7 */ 0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */ 0x00, 0x00, 0xda, 0x00, 0xdc, 0xdd, 0x00, 0xdf, /* 0xd8-0xdf */ 0x00, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0x00, 0xe7, /* 0xe0-0xe7 */ 0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0x00, /* 0xe8-0xef */ 0x00, 0x00, 0x00, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, /* 0xf0-0xf7 */ 0x00, 0x00, 0xfa, 0x00, 0xfc, 0xfd, 0x00, 0x00, /* 0xf8-0xff */ /* 0x0100 */ 0x00, 0x00, 0xc3, 0xe3, 0xa1, 0xb1, 0xc6, 0xe6, /* 0x00-0x07 */ 0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0xcf, 0xef, /* 0x08-0x0f */ 0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0xca, 0xea, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0xc5, 0xe5, 0x00, 0x00, 0xa5, 0xb5, 0x00, /* 0x38-0x3f */ 0x00, 0xa3, 0xb3, 0xd1, 0xf1, 0x00, 0x00, 0xd2, /* 0x40-0x47 */ 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0xd5, 0xf5, 0x00, 0x00, 0xc0, 0xe0, 0x00, 0x00, /* 0x50-0x57 */ 0xd8, 0xf8, 0xa6, 0xb6, 0x00, 0x00, 0xaa, 0xba, /* 0x58-0x5f */ 0xa9, 0xb9, 0xde, 0xfe, 0xab, 0xbb, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xf9, /* 0x68-0x6f */ 0xdb, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0xac, 0xbc, 0xaf, 0xbf, 0xae, 0xbe, 0x00, /* 0x78-0x7f */ }; static const unsigned char iso8859_2_page02[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ 0xa2, 0xff, 0x00, 0xb2, 0x00, 0xbd, 0x00, 0x00, /* 0xd8-0xdf */ }; /* static int iso8859_2_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x0180) c = iso8859_2_page00[wc-0x00a0]; else if (wc >= 0x02c0 && wc < 0x02e0) c = iso8859_2_page02[wc-0x02c0]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } */ #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/koi8_c.h0000644000175000017500000001021515004135251017676 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/koi8_c.h,v 1.2 2000/11/28 16:10:29 dawes Exp $ */ /* * KOI8-C */ static const unsigned short koi8_c_2uni[128] = { /* 0x80 */ 0x0493, 0x0497, 0x049b, 0x049d, 0x04a3, 0x04af, 0x04b1, 0x04b3, 0x04b7, 0x04b9, 0x04bb, 0x2580, 0x04d9, 0x04e3, 0x04e9, 0x04ef, /* 0x90 */ 0x0492, 0x0496, 0x049a, 0x049c, 0x04a2, 0x04ae, 0x04b0, 0x04b2, 0x04b6, 0x04b8, 0x04ba, 0x2321, 0x04d8, 0x04e2, 0x04e8, 0x04ee, /* 0xa0 */ 0x00a0, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0491, 0x045e, 0x045f, /* 0xb0 */ 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, 0x0486, 0x0409, 0x040a, 0x040b, 0x040c, 0x0490, 0x040e, 0x040f, /* 0xc0 */ 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, /* 0xd0 */ 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, /* 0xe0 */ 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, /* 0xf0 */ 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a, }; static int koi8_c_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x80) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) koi8_c_2uni[c-0x80]; return 1; } static const unsigned char koi8_c_page00[1] = { 0xa0, /* 0xa0-0xa7 */ }; static const unsigned char koi8_c_page04[240] = { 0x00, 0xb3, 0xb1, 0xb2, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x00-0x07 */ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0x00, 0xbe, 0xbf, /* 0x08-0x0f */ 0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa, /* 0x10-0x17 */ 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, /* 0x18-0x1f */ 0xf2, 0xf3, 0xf4, 0xf5, 0xe6, 0xe8, 0xe3, 0xfe, /* 0x20-0x27 */ 0xfb, 0xfd, 0xff, 0xf9, 0xf8, 0xfc, 0xe0, 0xf1, /* 0x28-0x2f */ 0xc1, 0xc2, 0xd7, 0xc7, 0xc4, 0xc5, 0xd6, 0xda, /* 0x30-0x37 */ 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, /* 0x38-0x3f */ 0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde, /* 0x40-0x47 */ 0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1, /* 0x48-0x4f */ 0x00, 0xa3, 0xa1, 0xa2, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x50-0x57 */ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0x00, 0xae, 0xaf, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0xbd, 0xad, 0x90, 0x80, 0x00, 0x00, 0x91, 0x81, /* 0x90-0x97 */ 0x00, 0x00, 0x92, 0x82, 0x93, 0x83, 0x00, 0x00, /* 0x98-0x9f */ 0x00, 0x00, 0x94, 0x84, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x85, /* 0xa8-0xaf */ 0x96, 0x86, 0x97, 0x87, 0x00, 0x00, 0x98, 0x88, /* 0xb0-0xb7 */ 0x99, 0x89, 0x9a, 0x8a, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ 0x9c, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ 0x00, 0x00, 0x9d, 0x8d, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */ 0x9e, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x8f, /* 0xe8-0xef */ }; static const unsigned char koi8_c_page22[1] = { 0xb0, /* 0x16-0x16 */ }; static int koi8_c_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x0080) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00a1) c = koi8_c_page00[wc-0x00a0]; else if (wc >= 0x0400 && wc < 0x04ef) c = koi8_c_page04[wc-0x0400]; else if (wc >= 0x2216 && wc < 0x2217) c = koi8_c_page22[wc-0x2216]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/ucs2be.h0000644000175000017500000000126115004135251017706 0ustar albrechtalbrecht/* * UCS-2BE = UCS-2 big endian */ /* $XFree86: xc/lib/X11/lcUniConv/ucs2be.h,v 1.1 2000/11/28 17:25:09 dawes Exp $ */ static int ucs2be_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { if (n >= 2) { if (s[0] >= 0xd8 && s[0] < 0xe0) { return RET_ILSEQ; } else { *pwc = (s[0] << 8) + s[1]; return 2; } } return RET_TOOFEW(0); } static int ucs2be_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { if (wc < 0x10000 && !(wc >= 0xd800 && wc < 0xe000)) { if (n >= 2) { r[0] = (unsigned char) (wc >> 8); r[1] = (unsigned char) wc; return 2; } else return RET_TOOSMALL; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/big5.h0000644000175000017500000077615715004135251017400 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/big5.h,v 1.2 2003/05/27 22:26:28 tsi Exp $ */ /* * BIG5 */ #ifdef NEED_TOWC static const unsigned short big5_2uni_pagea1[6121] = { /* 0xa1 */ 0x3000, 0xff0c, 0x3001, 0x3002, 0xff0e, 0x2022, 0xff1b, 0xff1a, 0xff1f, 0xff01, 0xfe30, 0x2026, 0x2025, 0xfe50, 0xff64, 0xfe52, 0x00b7, 0xfe54, 0xfe55, 0xfe56, 0xfe57, 0xff5c, 0x2013, 0xfe31, 0x2014, 0xfe33, 0xfffd, 0xfe34, 0xfe4f, 0xff08, 0xff09, 0xfe35, 0xfe36, 0xff5b, 0xff5d, 0xfe37, 0xfe38, 0x3014, 0x3015, 0xfe39, 0xfe3a, 0x3010, 0x3011, 0xfe3b, 0xfe3c, 0x300a, 0x300b, 0xfe3d, 0xfe3e, 0x3008, 0x3009, 0xfe3f, 0xfe40, 0x300c, 0x300d, 0xfe41, 0xfe42, 0x300e, 0x300f, 0xfe43, 0xfe44, 0xfe59, 0xfe5a, 0xfe5b, 0xfe5c, 0xfe5d, 0xfe5e, 0x2018, 0x2019, 0x201c, 0x201d, 0x301d, 0x301e, 0x2035, 0x2032, 0xff03, 0xff06, 0xff0a, 0x203b, 0x00a7, 0x3003, 0x25cb, 0x25cf, 0x25b3, 0x25b2, 0x25ce, 0x2606, 0x2605, 0x25c7, 0x25c6, 0x25a1, 0x25a0, 0x25bd, 0x25bc, 0x32a3, 0x2105, 0x203e, 0xfffd, 0xff3f, 0xfffd, 0xfe49, 0xfe4a, 0xfe4d, 0xfe4e, 0xfe4b, 0xfe4c, 0xfe5f, 0xfe60, 0xfe61, 0xff0b, 0xff0d, 0x00d7, 0x00f7, 0x00b1, 0x221a, 0xff1c, 0xff1e, 0xff1d, 0x2266, 0x2267, 0x2260, 0x221e, 0x2252, 0x2261, 0xfe62, 0xfe63, 0xfe64, 0xfe65, 0xfe66, 0x223c, 0x2229, 0x222a, 0x22a5, 0x2220, 0x221f, 0x22bf, 0x33d2, 0x33d1, 0x222b, 0x222e, 0x2235, 0x2234, 0x2640, 0x2642, 0x2641, 0x2609, 0x2191, 0x2193, 0x2190, 0x2192, 0x2196, 0x2197, 0x2199, 0x2198, 0x2225, 0x2223, 0xfffd, /* 0xa2 */ 0xfffd, 0xff0f, 0xff3c, 0xff04, 0x00a5, 0x3012, 0x00a2, 0x00a3, 0xff05, 0xff20, 0x2103, 0x2109, 0xfe69, 0xfe6a, 0xfe6b, 0x33d5, 0x339c, 0x339d, 0x339e, 0x33ce, 0x33a1, 0x338e, 0x338f, 0x33c4, 0x00b0, 0x5159, 0x515b, 0x515e, 0x515d, 0x5161, 0x5163, 0x55e7, 0x74e9, 0x7cce, 0x2581, 0x2582, 0x2583, 0x2584, 0x2585, 0x2586, 0x2587, 0x2588, 0x258f, 0x258e, 0x258d, 0x258c, 0x258b, 0x258a, 0x2589, 0x253c, 0x2534, 0x252c, 0x2524, 0x251c, 0x2594, 0x2500, 0x2502, 0x2595, 0x250c, 0x2510, 0x2514, 0x2518, 0x256d, 0x256e, 0x2570, 0x256f, 0x2550, 0x255e, 0x256a, 0x2561, 0x25e2, 0x25e3, 0x25e5, 0x25e4, 0x2571, 0x2572, 0x2573, 0xff10, 0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, 0xff18, 0xff19, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x3021, 0x3022, 0x3023, 0x3024, 0x3025, 0x3026, 0x3027, 0x3028, 0x3029, 0xfffd, 0x5344, 0xfffd, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, /* 0xa3 */ 0xff57, 0xff58, 0xff59, 0xff5a, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x3105, 0x3106, 0x3107, 0x3108, 0x3109, 0x310a, 0x310b, 0x310c, 0x310d, 0x310e, 0x310f, 0x3110, 0x3111, 0x3112, 0x3113, 0x3114, 0x3115, 0x3116, 0x3117, 0x3118, 0x3119, 0x311a, 0x311b, 0x311c, 0x311d, 0x311e, 0x311f, 0x3120, 0x3121, 0x3122, 0x3123, 0x3124, 0x3125, 0x3126, 0x3127, 0x3128, 0x3129, 0x02d9, 0x02c9, 0x02ca, 0x02c7, 0x02cb, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xa4 */ 0x4e00, 0x4e59, 0x4e01, 0x4e03, 0x4e43, 0x4e5d, 0x4e86, 0x4e8c, 0x4eba, 0x513f, 0x5165, 0x516b, 0x51e0, 0x5200, 0x5201, 0x529b, 0x5315, 0x5341, 0x535c, 0x53c8, 0x4e09, 0x4e0b, 0x4e08, 0x4e0a, 0x4e2b, 0x4e38, 0x51e1, 0x4e45, 0x4e48, 0x4e5f, 0x4e5e, 0x4e8e, 0x4ea1, 0x5140, 0x5203, 0x52fa, 0x5343, 0x53c9, 0x53e3, 0x571f, 0x58eb, 0x5915, 0x5927, 0x5973, 0x5b50, 0x5b51, 0x5b53, 0x5bf8, 0x5c0f, 0x5c22, 0x5c38, 0x5c71, 0x5ddd, 0x5de5, 0x5df1, 0x5df2, 0x5df3, 0x5dfe, 0x5e72, 0x5efe, 0x5f0b, 0x5f13, 0x624d, 0x4e11, 0x4e10, 0x4e0d, 0x4e2d, 0x4e30, 0x4e39, 0x4e4b, 0x5c39, 0x4e88, 0x4e91, 0x4e95, 0x4e92, 0x4e94, 0x4ea2, 0x4ec1, 0x4ec0, 0x4ec3, 0x4ec6, 0x4ec7, 0x4ecd, 0x4eca, 0x4ecb, 0x4ec4, 0x5143, 0x5141, 0x5167, 0x516d, 0x516e, 0x516c, 0x5197, 0x51f6, 0x5206, 0x5207, 0x5208, 0x52fb, 0x52fe, 0x52ff, 0x5316, 0x5339, 0x5348, 0x5347, 0x5345, 0x535e, 0x5384, 0x53cb, 0x53ca, 0x53cd, 0x58ec, 0x5929, 0x592b, 0x592a, 0x592d, 0x5b54, 0x5c11, 0x5c24, 0x5c3a, 0x5c6f, 0x5df4, 0x5e7b, 0x5eff, 0x5f14, 0x5f15, 0x5fc3, 0x6208, 0x6236, 0x624b, 0x624e, 0x652f, 0x6587, 0x6597, 0x65a4, 0x65b9, 0x65e5, 0x66f0, 0x6708, 0x6728, 0x6b20, 0x6b62, 0x6b79, 0x6bcb, 0x6bd4, 0x6bdb, 0x6c0f, 0x6c34, 0x706b, 0x722a, 0x7236, 0x723b, 0x7247, 0x7259, 0x725b, 0x72ac, 0x738b, 0x4e19, /* 0xa5 */ 0x4e16, 0x4e15, 0x4e14, 0x4e18, 0x4e3b, 0x4e4d, 0x4e4f, 0x4e4e, 0x4ee5, 0x4ed8, 0x4ed4, 0x4ed5, 0x4ed6, 0x4ed7, 0x4ee3, 0x4ee4, 0x4ed9, 0x4ede, 0x5145, 0x5144, 0x5189, 0x518a, 0x51ac, 0x51f9, 0x51fa, 0x51f8, 0x520a, 0x52a0, 0x529f, 0x5305, 0x5306, 0x5317, 0x531d, 0x4edf, 0x534a, 0x5349, 0x5361, 0x5360, 0x536f, 0x536e, 0x53bb, 0x53ef, 0x53e4, 0x53f3, 0x53ec, 0x53ee, 0x53e9, 0x53e8, 0x53fc, 0x53f8, 0x53f5, 0x53eb, 0x53e6, 0x53ea, 0x53f2, 0x53f1, 0x53f0, 0x53e5, 0x53ed, 0x53fb, 0x56db, 0x56da, 0x5916, 0x592e, 0x5931, 0x5974, 0x5976, 0x5b55, 0x5b83, 0x5c3c, 0x5de8, 0x5de7, 0x5de6, 0x5e02, 0x5e03, 0x5e73, 0x5e7c, 0x5f01, 0x5f18, 0x5f17, 0x5fc5, 0x620a, 0x6253, 0x6254, 0x6252, 0x6251, 0x65a5, 0x65e6, 0x672e, 0x672c, 0x672a, 0x672b, 0x672d, 0x6b63, 0x6bcd, 0x6c11, 0x6c10, 0x6c38, 0x6c41, 0x6c40, 0x6c3e, 0x72af, 0x7384, 0x7389, 0x74dc, 0x74e6, 0x7518, 0x751f, 0x7528, 0x7529, 0x7530, 0x7531, 0x7532, 0x7533, 0x758b, 0x767d, 0x76ae, 0x76bf, 0x76ee, 0x77db, 0x77e2, 0x77f3, 0x793a, 0x79be, 0x7a74, 0x7acb, 0x4e1e, 0x4e1f, 0x4e52, 0x4e53, 0x4e69, 0x4e99, 0x4ea4, 0x4ea6, 0x4ea5, 0x4eff, 0x4f09, 0x4f19, 0x4f0a, 0x4f15, 0x4f0d, 0x4f10, 0x4f11, 0x4f0f, 0x4ef2, 0x4ef6, 0x4efb, 0x4ef0, 0x4ef3, 0x4efd, 0x4f01, 0x4f0b, 0x5149, 0x5147, 0x5146, 0x5148, 0x5168, /* 0xa6 */ 0x5171, 0x518d, 0x51b0, 0x5217, 0x5211, 0x5212, 0x520e, 0x5216, 0x52a3, 0x5308, 0x5321, 0x5320, 0x5370, 0x5371, 0x5409, 0x540f, 0x540c, 0x540a, 0x5410, 0x5401, 0x540b, 0x5404, 0x5411, 0x540d, 0x5408, 0x5403, 0x540e, 0x5406, 0x5412, 0x56e0, 0x56de, 0x56dd, 0x5733, 0x5730, 0x5728, 0x572d, 0x572c, 0x572f, 0x5729, 0x5919, 0x591a, 0x5937, 0x5938, 0x5984, 0x5978, 0x5983, 0x597d, 0x5979, 0x5982, 0x5981, 0x5b57, 0x5b58, 0x5b87, 0x5b88, 0x5b85, 0x5b89, 0x5bfa, 0x5c16, 0x5c79, 0x5dde, 0x5e06, 0x5e76, 0x5e74, 0x5f0f, 0x5f1b, 0x5fd9, 0x5fd6, 0x620e, 0x620c, 0x620d, 0x6210, 0x6263, 0x625b, 0x6258, 0x6536, 0x65e9, 0x65e8, 0x65ec, 0x65ed, 0x66f2, 0x66f3, 0x6709, 0x673d, 0x6734, 0x6731, 0x6735, 0x6b21, 0x6b64, 0x6b7b, 0x6c16, 0x6c5d, 0x6c57, 0x6c59, 0x6c5f, 0x6c60, 0x6c50, 0x6c55, 0x6c61, 0x6c5b, 0x6c4d, 0x6c4e, 0x7070, 0x725f, 0x725d, 0x767e, 0x7af9, 0x7c73, 0x7cf8, 0x7f36, 0x7f8a, 0x7fbd, 0x8001, 0x8003, 0x800c, 0x8012, 0x8033, 0x807f, 0x8089, 0x808b, 0x808c, 0x81e3, 0x81ea, 0x81f3, 0x81fc, 0x820c, 0x821b, 0x821f, 0x826e, 0x8272, 0x827e, 0x866b, 0x8840, 0x884c, 0x8863, 0x897f, 0x9621, 0x4e32, 0x4ea8, 0x4f4d, 0x4f4f, 0x4f47, 0x4f57, 0x4f5e, 0x4f34, 0x4f5b, 0x4f55, 0x4f30, 0x4f50, 0x4f51, 0x4f3d, 0x4f3a, 0x4f38, 0x4f43, 0x4f54, 0x4f3c, 0x4f46, 0x4f63, /* 0xa7 */ 0x4f5c, 0x4f60, 0x4f2f, 0x4f4e, 0x4f36, 0x4f59, 0x4f5d, 0x4f48, 0x4f5a, 0x514c, 0x514b, 0x514d, 0x5175, 0x51b6, 0x51b7, 0x5225, 0x5224, 0x5229, 0x522a, 0x5228, 0x52ab, 0x52a9, 0x52aa, 0x52ac, 0x5323, 0x5373, 0x5375, 0x541d, 0x542d, 0x541e, 0x543e, 0x5426, 0x544e, 0x5427, 0x5446, 0x5443, 0x5433, 0x5448, 0x5442, 0x541b, 0x5429, 0x544a, 0x5439, 0x543b, 0x5438, 0x542e, 0x5435, 0x5436, 0x5420, 0x543c, 0x5440, 0x5431, 0x542b, 0x541f, 0x542c, 0x56ea, 0x56f0, 0x56e4, 0x56eb, 0x574a, 0x5751, 0x5740, 0x574d, 0x5747, 0x574e, 0x573e, 0x5750, 0x574f, 0x573b, 0x58ef, 0x593e, 0x599d, 0x5992, 0x59a8, 0x599e, 0x59a3, 0x5999, 0x5996, 0x598d, 0x59a4, 0x5993, 0x598a, 0x59a5, 0x5b5d, 0x5b5c, 0x5b5a, 0x5b5b, 0x5b8c, 0x5b8b, 0x5b8f, 0x5c2c, 0x5c40, 0x5c41, 0x5c3f, 0x5c3e, 0x5c90, 0x5c91, 0x5c94, 0x5c8c, 0x5deb, 0x5e0c, 0x5e8f, 0x5e87, 0x5e8a, 0x5ef7, 0x5f04, 0x5f1f, 0x5f64, 0x5f62, 0x5f77, 0x5f79, 0x5fd8, 0x5fcc, 0x5fd7, 0x5fcd, 0x5ff1, 0x5feb, 0x5ff8, 0x5fea, 0x6212, 0x6211, 0x6284, 0x6297, 0x6296, 0x6280, 0x6276, 0x6289, 0x626d, 0x628a, 0x627c, 0x627e, 0x6279, 0x6273, 0x6292, 0x626f, 0x6298, 0x626e, 0x6295, 0x6293, 0x6291, 0x6286, 0x6539, 0x653b, 0x6538, 0x65f1, 0x66f4, 0x675f, 0x674e, 0x674f, 0x6750, 0x6751, 0x675c, 0x6756, 0x675e, 0x6749, 0x6746, 0x6760, /* 0xa8 */ 0x6753, 0x6757, 0x6b65, 0x6bcf, 0x6c42, 0x6c5e, 0x6c99, 0x6c81, 0x6c88, 0x6c89, 0x6c85, 0x6c9b, 0x6c6a, 0x6c7a, 0x6c90, 0x6c70, 0x6c8c, 0x6c68, 0x6c96, 0x6c92, 0x6c7d, 0x6c83, 0x6c72, 0x6c7e, 0x6c74, 0x6c86, 0x6c76, 0x6c8d, 0x6c94, 0x6c98, 0x6c82, 0x7076, 0x707c, 0x707d, 0x7078, 0x7262, 0x7261, 0x7260, 0x72c4, 0x72c2, 0x7396, 0x752c, 0x752b, 0x7537, 0x7538, 0x7682, 0x76ef, 0x77e3, 0x79c1, 0x79c0, 0x79bf, 0x7a76, 0x7cfb, 0x7f55, 0x8096, 0x8093, 0x809d, 0x8098, 0x809b, 0x809a, 0x80b2, 0x826f, 0x8292, 0x828b, 0x828d, 0x898b, 0x89d2, 0x8a00, 0x8c37, 0x8c46, 0x8c55, 0x8c9d, 0x8d64, 0x8d70, 0x8db3, 0x8eab, 0x8eca, 0x8f9b, 0x8fb0, 0x8fc2, 0x8fc6, 0x8fc5, 0x8fc4, 0x5de1, 0x9091, 0x90a2, 0x90aa, 0x90a6, 0x90a3, 0x9149, 0x91c6, 0x91cc, 0x9632, 0x962e, 0x9631, 0x962a, 0x962c, 0x4e26, 0x4e56, 0x4e73, 0x4e8b, 0x4e9b, 0x4e9e, 0x4eab, 0x4eac, 0x4f6f, 0x4f9d, 0x4f8d, 0x4f73, 0x4f7f, 0x4f6c, 0x4f9b, 0x4f8b, 0x4f86, 0x4f83, 0x4f70, 0x4f75, 0x4f88, 0x4f69, 0x4f7b, 0x4f96, 0x4f7e, 0x4f8f, 0x4f91, 0x4f7a, 0x5154, 0x5152, 0x5155, 0x5169, 0x5177, 0x5176, 0x5178, 0x51bd, 0x51fd, 0x523b, 0x5238, 0x5237, 0x523a, 0x5230, 0x522e, 0x5236, 0x5241, 0x52be, 0x52bb, 0x5352, 0x5354, 0x5353, 0x5351, 0x5366, 0x5377, 0x5378, 0x5379, 0x53d6, 0x53d4, 0x53d7, 0x5473, 0x5475, /* 0xa9 */ 0x5496, 0x5478, 0x5495, 0x5480, 0x547b, 0x5477, 0x5484, 0x5492, 0x5486, 0x547c, 0x5490, 0x5471, 0x5476, 0x548c, 0x549a, 0x5462, 0x5468, 0x548b, 0x547d, 0x548e, 0x56fa, 0x5783, 0x5777, 0x576a, 0x5769, 0x5761, 0x5766, 0x5764, 0x577c, 0x591c, 0x5949, 0x5947, 0x5948, 0x5944, 0x5954, 0x59be, 0x59bb, 0x59d4, 0x59b9, 0x59ae, 0x59d1, 0x59c6, 0x59d0, 0x59cd, 0x59cb, 0x59d3, 0x59ca, 0x59af, 0x59b3, 0x59d2, 0x59c5, 0x5b5f, 0x5b64, 0x5b63, 0x5b97, 0x5b9a, 0x5b98, 0x5b9c, 0x5b99, 0x5b9b, 0x5c1a, 0x5c48, 0x5c45, 0x5c46, 0x5cb7, 0x5ca1, 0x5cb8, 0x5ca9, 0x5cab, 0x5cb1, 0x5cb3, 0x5e18, 0x5e1a, 0x5e16, 0x5e15, 0x5e1b, 0x5e11, 0x5e78, 0x5e9a, 0x5e97, 0x5e9c, 0x5e95, 0x5e96, 0x5ef6, 0x5f26, 0x5f27, 0x5f29, 0x5f80, 0x5f81, 0x5f7f, 0x5f7c, 0x5fdd, 0x5fe0, 0x5ffd, 0x5ff5, 0x5fff, 0x600f, 0x6014, 0x602f, 0x6035, 0x6016, 0x602a, 0x6015, 0x6021, 0x6027, 0x6029, 0x602b, 0x601b, 0x6216, 0x6215, 0x623f, 0x623e, 0x6240, 0x627f, 0x62c9, 0x62cc, 0x62c4, 0x62bf, 0x62c2, 0x62b9, 0x62d2, 0x62db, 0x62ab, 0x62d3, 0x62d4, 0x62cb, 0x62c8, 0x62a8, 0x62bd, 0x62bc, 0x62d0, 0x62d9, 0x62c7, 0x62cd, 0x62b5, 0x62da, 0x62b1, 0x62d8, 0x62d6, 0x62d7, 0x62c6, 0x62ac, 0x62ce, 0x653e, 0x65a7, 0x65bc, 0x65fa, 0x6614, 0x6613, 0x660c, 0x6606, 0x6602, 0x660e, 0x6600, 0x660f, 0x6615, 0x660a, /* 0xaa */ 0x6607, 0x670d, 0x670b, 0x676d, 0x678b, 0x6795, 0x6771, 0x679c, 0x6773, 0x6777, 0x6787, 0x679d, 0x6797, 0x676f, 0x6770, 0x677f, 0x6789, 0x677e, 0x6790, 0x6775, 0x679a, 0x6793, 0x677c, 0x676a, 0x6772, 0x6b23, 0x6b66, 0x6b67, 0x6b7f, 0x6c13, 0x6c1b, 0x6ce3, 0x6ce8, 0x6cf3, 0x6cb1, 0x6ccc, 0x6ce5, 0x6cb3, 0x6cbd, 0x6cbe, 0x6cbc, 0x6ce2, 0x6cab, 0x6cd5, 0x6cd3, 0x6cb8, 0x6cc4, 0x6cb9, 0x6cc1, 0x6cae, 0x6cd7, 0x6cc5, 0x6cf1, 0x6cbf, 0x6cbb, 0x6ce1, 0x6cdb, 0x6cca, 0x6cac, 0x6cef, 0x6cdc, 0x6cd6, 0x6ce0, 0x7095, 0x708e, 0x7092, 0x708a, 0x7099, 0x722c, 0x722d, 0x7238, 0x7248, 0x7267, 0x7269, 0x72c0, 0x72ce, 0x72d9, 0x72d7, 0x72d0, 0x73a9, 0x73a8, 0x739f, 0x73ab, 0x73a5, 0x753d, 0x759d, 0x7599, 0x759a, 0x7684, 0x76c2, 0x76f2, 0x76f4, 0x77e5, 0x77fd, 0x793e, 0x7940, 0x7941, 0x79c9, 0x79c8, 0x7a7a, 0x7a79, 0x7afa, 0x7cfe, 0x7f54, 0x7f8c, 0x7f8b, 0x8005, 0x80ba, 0x80a5, 0x80a2, 0x80b1, 0x80a1, 0x80ab, 0x80a9, 0x80b4, 0x80aa, 0x80af, 0x81e5, 0x81fe, 0x820d, 0x82b3, 0x829d, 0x8299, 0x82ad, 0x82bd, 0x829f, 0x82b9, 0x82b1, 0x82ac, 0x82a5, 0x82af, 0x82b8, 0x82a3, 0x82b0, 0x82be, 0x82b7, 0x864e, 0x8671, 0x521d, 0x8868, 0x8ecb, 0x8fce, 0x8fd4, 0x8fd1, 0x90b5, 0x90b8, 0x90b1, 0x90b6, 0x91c7, 0x91d1, 0x9577, 0x9580, 0x961c, 0x9640, 0x963f, 0x963b, 0x9644, /* 0xab */ 0x9642, 0x96b9, 0x96e8, 0x9752, 0x975e, 0x4e9f, 0x4ead, 0x4eae, 0x4fe1, 0x4fb5, 0x4faf, 0x4fbf, 0x4fe0, 0x4fd1, 0x4fcf, 0x4fdd, 0x4fc3, 0x4fb6, 0x4fd8, 0x4fdf, 0x4fca, 0x4fd7, 0x4fae, 0x4fd0, 0x4fc4, 0x4fc2, 0x4fda, 0x4fce, 0x4fde, 0x4fb7, 0x5157, 0x5192, 0x5191, 0x51a0, 0x524e, 0x5243, 0x524a, 0x524d, 0x524c, 0x524b, 0x5247, 0x52c7, 0x52c9, 0x52c3, 0x52c1, 0x530d, 0x5357, 0x537b, 0x539a, 0x53db, 0x54ac, 0x54c0, 0x54a8, 0x54ce, 0x54c9, 0x54b8, 0x54a6, 0x54b3, 0x54c7, 0x54c2, 0x54bd, 0x54aa, 0x54c1, 0x54c4, 0x54c8, 0x54af, 0x54ab, 0x54b1, 0x54bb, 0x54a9, 0x54a7, 0x54bf, 0x56ff, 0x5782, 0x578b, 0x57a0, 0x57a3, 0x57a2, 0x57ce, 0x57ae, 0x5793, 0x5955, 0x5951, 0x594f, 0x594e, 0x5950, 0x59dc, 0x59d8, 0x59ff, 0x59e3, 0x59e8, 0x5a03, 0x59e5, 0x59ea, 0x59da, 0x59e6, 0x5a01, 0x59fb, 0x5b69, 0x5ba3, 0x5ba6, 0x5ba4, 0x5ba2, 0x5ba5, 0x5c01, 0x5c4e, 0x5c4f, 0x5c4d, 0x5c4b, 0x5cd9, 0x5cd2, 0x5df7, 0x5e1d, 0x5e25, 0x5e1f, 0x5e7d, 0x5ea0, 0x5ea6, 0x5efa, 0x5f08, 0x5f2d, 0x5f65, 0x5f88, 0x5f85, 0x5f8a, 0x5f8b, 0x5f87, 0x5f8c, 0x5f89, 0x6012, 0x601d, 0x6020, 0x6025, 0x600e, 0x6028, 0x604d, 0x6070, 0x6068, 0x6062, 0x6046, 0x6043, 0x606c, 0x606b, 0x606a, 0x6064, 0x6241, 0x62dc, 0x6316, 0x6309, 0x62fc, 0x62ed, 0x6301, 0x62ee, 0x62fd, 0x6307, 0x62f1, 0x62f7, /* 0xac */ 0x62ef, 0x62ec, 0x62fe, 0x62f4, 0x6311, 0x6302, 0x653f, 0x6545, 0x65ab, 0x65bd, 0x65e2, 0x6625, 0x662d, 0x6620, 0x6627, 0x662f, 0x661f, 0x6628, 0x6631, 0x6624, 0x66f7, 0x67ff, 0x67d3, 0x67f1, 0x67d4, 0x67d0, 0x67ec, 0x67b6, 0x67af, 0x67f5, 0x67e9, 0x67ef, 0x67c4, 0x67d1, 0x67b4, 0x67da, 0x67e5, 0x67b8, 0x67cf, 0x67de, 0x67f3, 0x67b0, 0x67d9, 0x67e2, 0x67dd, 0x67d2, 0x6b6a, 0x6b83, 0x6b86, 0x6bb5, 0x6bd2, 0x6bd7, 0x6c1f, 0x6cc9, 0x6d0b, 0x6d32, 0x6d2a, 0x6d41, 0x6d25, 0x6d0c, 0x6d31, 0x6d1e, 0x6d17, 0x6d3b, 0x6d3d, 0x6d3e, 0x6d36, 0x6d1b, 0x6cf5, 0x6d39, 0x6d27, 0x6d38, 0x6d29, 0x6d2e, 0x6d35, 0x6d0e, 0x6d2b, 0x70ab, 0x70ba, 0x70b3, 0x70ac, 0x70af, 0x70ad, 0x70b8, 0x70ae, 0x70a4, 0x7230, 0x7272, 0x726f, 0x7274, 0x72e9, 0x72e0, 0x72e1, 0x73b7, 0x73ca, 0x73bb, 0x73b2, 0x73cd, 0x73c0, 0x73b3, 0x751a, 0x752d, 0x754f, 0x754c, 0x754e, 0x754b, 0x75ab, 0x75a4, 0x75a5, 0x75a2, 0x75a3, 0x7678, 0x7686, 0x7687, 0x7688, 0x76c8, 0x76c6, 0x76c3, 0x76c5, 0x7701, 0x76f9, 0x76f8, 0x7709, 0x770b, 0x76fe, 0x76fc, 0x7707, 0x77dc, 0x7802, 0x7814, 0x780c, 0x780d, 0x7946, 0x7949, 0x7948, 0x7947, 0x79b9, 0x79ba, 0x79d1, 0x79d2, 0x79cb, 0x7a7f, 0x7a81, 0x7aff, 0x7afd, 0x7c7d, 0x7d02, 0x7d05, 0x7d00, 0x7d09, 0x7d07, 0x7d04, 0x7d06, 0x7f38, 0x7f8e, 0x7fbf, 0x8004, /* 0xad */ 0x8010, 0x800d, 0x8011, 0x8036, 0x80d6, 0x80e5, 0x80da, 0x80c3, 0x80c4, 0x80cc, 0x80e1, 0x80db, 0x80ce, 0x80de, 0x80e4, 0x80dd, 0x81f4, 0x8222, 0x82e7, 0x8303, 0x8305, 0x82e3, 0x82db, 0x82e6, 0x8304, 0x82e5, 0x8302, 0x8309, 0x82d2, 0x82d7, 0x82f1, 0x8301, 0x82dc, 0x82d4, 0x82d1, 0x82de, 0x82d3, 0x82df, 0x82ef, 0x8306, 0x8650, 0x8679, 0x867b, 0x867a, 0x884d, 0x886b, 0x8981, 0x89d4, 0x8a08, 0x8a02, 0x8a03, 0x8c9e, 0x8ca0, 0x8d74, 0x8d73, 0x8db4, 0x8ecd, 0x8ecc, 0x8ff0, 0x8fe6, 0x8fe2, 0x8fea, 0x8fe5, 0x8fed, 0x8feb, 0x8fe4, 0x8fe8, 0x90ca, 0x90ce, 0x90c1, 0x90c3, 0x914b, 0x914a, 0x91cd, 0x9582, 0x9650, 0x964b, 0x964c, 0x964d, 0x9762, 0x9769, 0x97cb, 0x97ed, 0x97f3, 0x9801, 0x98a8, 0x98db, 0x98df, 0x9996, 0x9999, 0x4e58, 0x4eb3, 0x500c, 0x500d, 0x5023, 0x4fef, 0x5026, 0x5025, 0x4ff8, 0x5029, 0x5016, 0x5006, 0x503c, 0x501f, 0x501a, 0x5012, 0x5011, 0x4ffa, 0x5000, 0x5014, 0x5028, 0x4ff1, 0x5021, 0x500b, 0x5019, 0x5018, 0x4ff3, 0x4fee, 0x502d, 0x502a, 0x4ffe, 0x502b, 0x5009, 0x517c, 0x51a4, 0x51a5, 0x51a2, 0x51cd, 0x51cc, 0x51c6, 0x51cb, 0x5256, 0x525c, 0x5254, 0x525b, 0x525d, 0x532a, 0x537f, 0x539f, 0x539d, 0x53df, 0x54e8, 0x5510, 0x5501, 0x5537, 0x54fc, 0x54e5, 0x54f2, 0x5506, 0x54fa, 0x5514, 0x54e9, 0x54ed, 0x54e1, 0x5509, 0x54ee, 0x54ea, /* 0xae */ 0x54e6, 0x5527, 0x5507, 0x54fd, 0x550f, 0x5703, 0x5704, 0x57c2, 0x57d4, 0x57cb, 0x57c3, 0x5809, 0x590f, 0x5957, 0x5958, 0x595a, 0x5a11, 0x5a18, 0x5a1c, 0x5a1f, 0x5a1b, 0x5a13, 0x59ec, 0x5a20, 0x5a23, 0x5a29, 0x5a25, 0x5a0c, 0x5a09, 0x5b6b, 0x5c58, 0x5bb0, 0x5bb3, 0x5bb6, 0x5bb4, 0x5bae, 0x5bb5, 0x5bb9, 0x5bb8, 0x5c04, 0x5c51, 0x5c55, 0x5c50, 0x5ced, 0x5cfd, 0x5cfb, 0x5cea, 0x5ce8, 0x5cf0, 0x5cf6, 0x5d01, 0x5cf4, 0x5dee, 0x5e2d, 0x5e2b, 0x5eab, 0x5ead, 0x5ea7, 0x5f31, 0x5f92, 0x5f91, 0x5f90, 0x6059, 0x6063, 0x6065, 0x6050, 0x6055, 0x606d, 0x6069, 0x606f, 0x6084, 0x609f, 0x609a, 0x608d, 0x6094, 0x608c, 0x6085, 0x6096, 0x6247, 0x62f3, 0x6308, 0x62ff, 0x634e, 0x633e, 0x632f, 0x6355, 0x6342, 0x6346, 0x634f, 0x6349, 0x633a, 0x6350, 0x633d, 0x632a, 0x632b, 0x6328, 0x634d, 0x634c, 0x6548, 0x6549, 0x6599, 0x65c1, 0x65c5, 0x6642, 0x6649, 0x664f, 0x6643, 0x6652, 0x664c, 0x6645, 0x6641, 0x66f8, 0x6714, 0x6715, 0x6717, 0x6821, 0x6838, 0x6848, 0x6846, 0x6853, 0x6839, 0x6842, 0x6854, 0x6829, 0x68b3, 0x6817, 0x684c, 0x6851, 0x683d, 0x67f4, 0x6850, 0x6840, 0x683c, 0x6843, 0x682a, 0x6845, 0x6813, 0x6818, 0x6841, 0x6b8a, 0x6b89, 0x6bb7, 0x6c23, 0x6c27, 0x6c28, 0x6c26, 0x6c24, 0x6cf0, 0x6d6a, 0x6d95, 0x6d88, 0x6d87, 0x6d66, 0x6d78, 0x6d77, 0x6d59, 0x6d93, /* 0xaf */ 0x6d6c, 0x6d89, 0x6d6e, 0x6d5a, 0x6d74, 0x6d69, 0x6d8c, 0x6d8a, 0x6d79, 0x6d85, 0x6d65, 0x6d94, 0x70ca, 0x70d8, 0x70e4, 0x70d9, 0x70c8, 0x70cf, 0x7239, 0x7279, 0x72fc, 0x72f9, 0x72fd, 0x72f8, 0x72f7, 0x7386, 0x73ed, 0x7409, 0x73ee, 0x73e0, 0x73ea, 0x73de, 0x7554, 0x755d, 0x755c, 0x755a, 0x7559, 0x75be, 0x75c5, 0x75c7, 0x75b2, 0x75b3, 0x75bd, 0x75bc, 0x75b9, 0x75c2, 0x75b8, 0x768b, 0x76b0, 0x76ca, 0x76cd, 0x76ce, 0x7729, 0x771f, 0x7720, 0x7728, 0x77e9, 0x7830, 0x7827, 0x7838, 0x781d, 0x7834, 0x7837, 0x7825, 0x782d, 0x7820, 0x781f, 0x7832, 0x7955, 0x7950, 0x7960, 0x795f, 0x7956, 0x795e, 0x795d, 0x7957, 0x795a, 0x79e4, 0x79e3, 0x79e7, 0x79df, 0x79e6, 0x79e9, 0x79d8, 0x7a84, 0x7a88, 0x7ad9, 0x7b06, 0x7b11, 0x7c89, 0x7d21, 0x7d17, 0x7d0b, 0x7d0a, 0x7d20, 0x7d22, 0x7d14, 0x7d10, 0x7d15, 0x7d1a, 0x7d1c, 0x7d0d, 0x7d19, 0x7d1b, 0x7f3a, 0x7f5f, 0x7f94, 0x7fc5, 0x7fc1, 0x8006, 0x8018, 0x8015, 0x8019, 0x8017, 0x803d, 0x803f, 0x80f1, 0x8102, 0x80f0, 0x8105, 0x80ed, 0x80f4, 0x8106, 0x80f8, 0x80f3, 0x8108, 0x80fd, 0x810a, 0x80fc, 0x80ef, 0x81ed, 0x81ec, 0x8200, 0x8210, 0x822a, 0x822b, 0x8228, 0x822c, 0x82bb, 0x832b, 0x8352, 0x8354, 0x834a, 0x8338, 0x8350, 0x8349, 0x8335, 0x8334, 0x834f, 0x8332, 0x8339, 0x8336, 0x8317, 0x8340, 0x8331, 0x8328, 0x8343, /* 0xb0 */ 0x8654, 0x868a, 0x86aa, 0x8693, 0x86a4, 0x86a9, 0x868c, 0x86a3, 0x869c, 0x8870, 0x8877, 0x8881, 0x8882, 0x887d, 0x8879, 0x8a18, 0x8a10, 0x8a0e, 0x8a0c, 0x8a15, 0x8a0a, 0x8a17, 0x8a13, 0x8a16, 0x8a0f, 0x8a11, 0x8c48, 0x8c7a, 0x8c79, 0x8ca1, 0x8ca2, 0x8d77, 0x8eac, 0x8ed2, 0x8ed4, 0x8ecf, 0x8fb1, 0x9001, 0x9006, 0x8ff7, 0x9000, 0x8ffa, 0x8ff4, 0x9003, 0x8ffd, 0x9005, 0x8ff8, 0x9095, 0x90e1, 0x90dd, 0x90e2, 0x9152, 0x914d, 0x914c, 0x91d8, 0x91dd, 0x91d7, 0x91dc, 0x91d9, 0x9583, 0x9662, 0x9663, 0x9661, 0x965b, 0x965d, 0x9664, 0x9658, 0x965e, 0x96bb, 0x98e2, 0x99ac, 0x9aa8, 0x9ad8, 0x9b25, 0x9b32, 0x9b3c, 0x4e7e, 0x507a, 0x507d, 0x505c, 0x5047, 0x5043, 0x504c, 0x505a, 0x5049, 0x5065, 0x5076, 0x504e, 0x5055, 0x5075, 0x5074, 0x5077, 0x504f, 0x500f, 0x506f, 0x506d, 0x515c, 0x5195, 0x51f0, 0x526a, 0x526f, 0x52d2, 0x52d9, 0x52d8, 0x52d5, 0x5310, 0x530f, 0x5319, 0x533f, 0x5340, 0x533e, 0x53c3, 0x66fc, 0x5546, 0x556a, 0x5566, 0x5544, 0x555e, 0x5561, 0x5543, 0x554a, 0x5531, 0x5556, 0x554f, 0x5555, 0x552f, 0x5564, 0x5538, 0x552e, 0x555c, 0x552c, 0x5563, 0x5533, 0x5541, 0x5557, 0x5708, 0x570b, 0x5709, 0x57df, 0x5805, 0x580a, 0x5806, 0x57e0, 0x57e4, 0x57fa, 0x5802, 0x5835, 0x57f7, 0x57f9, 0x5920, 0x5962, 0x5a36, 0x5a41, 0x5a49, 0x5a66, 0x5a6a, 0x5a40, /* 0xb1 */ 0x5a3c, 0x5a62, 0x5a5a, 0x5a46, 0x5a4a, 0x5b70, 0x5bc7, 0x5bc5, 0x5bc4, 0x5bc2, 0x5bbf, 0x5bc6, 0x5c09, 0x5c08, 0x5c07, 0x5c60, 0x5c5c, 0x5c5d, 0x5d07, 0x5d06, 0x5d0e, 0x5d1b, 0x5d16, 0x5d22, 0x5d11, 0x5d29, 0x5d14, 0x5d19, 0x5d24, 0x5d27, 0x5d17, 0x5de2, 0x5e38, 0x5e36, 0x5e33, 0x5e37, 0x5eb7, 0x5eb8, 0x5eb6, 0x5eb5, 0x5ebe, 0x5f35, 0x5f37, 0x5f57, 0x5f6c, 0x5f69, 0x5f6b, 0x5f97, 0x5f99, 0x5f9e, 0x5f98, 0x5fa1, 0x5fa0, 0x5f9c, 0x607f, 0x60a3, 0x6089, 0x60a0, 0x60a8, 0x60cb, 0x60b4, 0x60e6, 0x60bd, 0x60c5, 0x60bb, 0x60b5, 0x60dc, 0x60bc, 0x60d8, 0x60d5, 0x60c6, 0x60df, 0x60b8, 0x60da, 0x60c7, 0x621a, 0x621b, 0x6248, 0x63a0, 0x63a7, 0x6372, 0x6396, 0x63a2, 0x63a5, 0x6377, 0x6367, 0x6398, 0x63aa, 0x6371, 0x63a9, 0x6389, 0x6383, 0x639b, 0x636b, 0x63a8, 0x6384, 0x6388, 0x6399, 0x63a1, 0x63ac, 0x6392, 0x638f, 0x6380, 0x637b, 0x6369, 0x6368, 0x637a, 0x655d, 0x6556, 0x6551, 0x6559, 0x6557, 0x555f, 0x654f, 0x6558, 0x6555, 0x6554, 0x659c, 0x659b, 0x65ac, 0x65cf, 0x65cb, 0x65cc, 0x65ce, 0x665d, 0x665a, 0x6664, 0x6668, 0x6666, 0x665e, 0x66f9, 0x52d7, 0x671b, 0x6881, 0x68af, 0x68a2, 0x6893, 0x68b5, 0x687f, 0x6876, 0x68b1, 0x68a7, 0x6897, 0x68b0, 0x6883, 0x68c4, 0x68ad, 0x6886, 0x6885, 0x6894, 0x689d, 0x68a8, 0x689f, 0x68a1, 0x6882, 0x6b32, 0x6bba, /* 0xb2 */ 0x6beb, 0x6bec, 0x6c2b, 0x6d8e, 0x6dbc, 0x6df3, 0x6dd9, 0x6db2, 0x6de1, 0x6dcc, 0x6de4, 0x6dfb, 0x6dfa, 0x6e05, 0x6dc7, 0x6dcb, 0x6daf, 0x6dd1, 0x6dae, 0x6dde, 0x6df9, 0x6db8, 0x6df7, 0x6df5, 0x6dc5, 0x6dd2, 0x6e1a, 0x6db5, 0x6dda, 0x6deb, 0x6dd8, 0x6dea, 0x6df1, 0x6dee, 0x6de8, 0x6dc6, 0x6dc4, 0x6daa, 0x6dec, 0x6dbf, 0x6de6, 0x70f9, 0x7109, 0x710a, 0x70fd, 0x70ef, 0x723d, 0x727d, 0x7281, 0x731c, 0x731b, 0x7316, 0x7313, 0x7319, 0x7387, 0x7405, 0x740a, 0x7403, 0x7406, 0x73fe, 0x740d, 0x74e0, 0x74f6, 0x74f7, 0x751c, 0x7522, 0x7565, 0x7566, 0x7562, 0x7570, 0x758f, 0x75d4, 0x75d5, 0x75b5, 0x75ca, 0x75cd, 0x768e, 0x76d4, 0x76d2, 0x76db, 0x7737, 0x773e, 0x773c, 0x7736, 0x7738, 0x773a, 0x786b, 0x7843, 0x784e, 0x7965, 0x7968, 0x796d, 0x79fb, 0x7a92, 0x7a95, 0x7b20, 0x7b28, 0x7b1b, 0x7b2c, 0x7b26, 0x7b19, 0x7b1e, 0x7b2e, 0x7c92, 0x7c97, 0x7c95, 0x7d46, 0x7d43, 0x7d71, 0x7d2e, 0x7d39, 0x7d3c, 0x7d40, 0x7d30, 0x7d33, 0x7d44, 0x7d2f, 0x7d42, 0x7d32, 0x7d31, 0x7f3d, 0x7f9e, 0x7f9a, 0x7fcc, 0x7fce, 0x7fd2, 0x801c, 0x804a, 0x8046, 0x812f, 0x8116, 0x8123, 0x812b, 0x8129, 0x8130, 0x8124, 0x8202, 0x8235, 0x8237, 0x8236, 0x8239, 0x838e, 0x839e, 0x8398, 0x8378, 0x83a2, 0x8396, 0x83bd, 0x83ab, 0x8392, 0x838a, 0x8393, 0x8389, 0x83a0, 0x8377, 0x837b, 0x837c, /* 0xb3 */ 0x8386, 0x83a7, 0x8655, 0x5f6a, 0x86c7, 0x86c0, 0x86b6, 0x86c4, 0x86b5, 0x86c6, 0x86cb, 0x86b1, 0x86af, 0x86c9, 0x8853, 0x889e, 0x8888, 0x88ab, 0x8892, 0x8896, 0x888d, 0x888b, 0x8993, 0x898f, 0x8a2a, 0x8a1d, 0x8a23, 0x8a25, 0x8a31, 0x8a2d, 0x8a1f, 0x8a1b, 0x8a22, 0x8c49, 0x8c5a, 0x8ca9, 0x8cac, 0x8cab, 0x8ca8, 0x8caa, 0x8ca7, 0x8d67, 0x8d66, 0x8dbe, 0x8dba, 0x8edb, 0x8edf, 0x9019, 0x900d, 0x901a, 0x9017, 0x9023, 0x901f, 0x901d, 0x9010, 0x9015, 0x901e, 0x9020, 0x900f, 0x9022, 0x9016, 0x901b, 0x9014, 0x90e8, 0x90ed, 0x90fd, 0x9157, 0x91ce, 0x91f5, 0x91e6, 0x91e3, 0x91e7, 0x91ed, 0x91e9, 0x9589, 0x966a, 0x9675, 0x9673, 0x9678, 0x9670, 0x9674, 0x9676, 0x9677, 0x966c, 0x96c0, 0x96ea, 0x96e9, 0x7ae0, 0x7adf, 0x9802, 0x9803, 0x9b5a, 0x9ce5, 0x9e75, 0x9e7f, 0x9ea5, 0x9ebb, 0x50a2, 0x508d, 0x5085, 0x5099, 0x5091, 0x5080, 0x5096, 0x5098, 0x509a, 0x6700, 0x51f1, 0x5272, 0x5274, 0x5275, 0x5269, 0x52de, 0x52dd, 0x52db, 0x535a, 0x53a5, 0x557b, 0x5580, 0x55a7, 0x557c, 0x558a, 0x559d, 0x5598, 0x5582, 0x559c, 0x55aa, 0x5594, 0x5587, 0x558b, 0x5583, 0x55b3, 0x55ae, 0x559f, 0x553e, 0x55b2, 0x559a, 0x55bb, 0x55ac, 0x55b1, 0x557e, 0x5589, 0x55ab, 0x5599, 0x570d, 0x582f, 0x582a, 0x5834, 0x5824, 0x5830, 0x5831, 0x5821, 0x581d, 0x5820, 0x58f9, 0x58fa, 0x5960, /* 0xb4 */ 0x5a77, 0x5a9a, 0x5a7f, 0x5a92, 0x5a9b, 0x5aa7, 0x5b73, 0x5b71, 0x5bd2, 0x5bcc, 0x5bd3, 0x5bd0, 0x5c0a, 0x5c0b, 0x5c31, 0x5d4c, 0x5d50, 0x5d34, 0x5d47, 0x5dfd, 0x5e45, 0x5e3d, 0x5e40, 0x5e43, 0x5e7e, 0x5eca, 0x5ec1, 0x5ec2, 0x5ec4, 0x5f3c, 0x5f6d, 0x5fa9, 0x5faa, 0x5fa8, 0x60d1, 0x60e1, 0x60b2, 0x60b6, 0x60e0, 0x611c, 0x6123, 0x60fa, 0x6115, 0x60f0, 0x60fb, 0x60f4, 0x6168, 0x60f1, 0x610e, 0x60f6, 0x6109, 0x6100, 0x6112, 0x621f, 0x6249, 0x63a3, 0x638c, 0x63cf, 0x63c0, 0x63e9, 0x63c9, 0x63c6, 0x63cd, 0x63d2, 0x63e3, 0x63d0, 0x63e1, 0x63d6, 0x63ed, 0x63ee, 0x6376, 0x63f4, 0x63ea, 0x63db, 0x6452, 0x63da, 0x63f9, 0x655e, 0x6566, 0x6562, 0x6563, 0x6591, 0x6590, 0x65af, 0x666e, 0x6670, 0x6674, 0x6676, 0x666f, 0x6691, 0x667a, 0x667e, 0x6677, 0x66fe, 0x66ff, 0x671f, 0x671d, 0x68fa, 0x68d5, 0x68e0, 0x68d8, 0x68d7, 0x6905, 0x68df, 0x68f5, 0x68ee, 0x68e7, 0x68f9, 0x68d2, 0x68f2, 0x68e3, 0x68cb, 0x68cd, 0x690d, 0x6912, 0x690e, 0x68c9, 0x68da, 0x696e, 0x68fb, 0x6b3e, 0x6b3a, 0x6b3d, 0x6b98, 0x6b96, 0x6bbc, 0x6bef, 0x6c2e, 0x6c2f, 0x6c2c, 0x6e2f, 0x6e38, 0x6e54, 0x6e21, 0x6e32, 0x6e67, 0x6e4a, 0x6e20, 0x6e25, 0x6e23, 0x6e1b, 0x6e5b, 0x6e58, 0x6e24, 0x6e56, 0x6e6e, 0x6e2d, 0x6e26, 0x6e6f, 0x6e34, 0x6e4d, 0x6e3a, 0x6e2c, 0x6e43, 0x6e1d, 0x6e3e, 0x6ecb, /* 0xb5 */ 0x6e89, 0x6e19, 0x6e4e, 0x6e63, 0x6e44, 0x6e72, 0x6e69, 0x6e5f, 0x7119, 0x711a, 0x7126, 0x7130, 0x7121, 0x7136, 0x716e, 0x711c, 0x724c, 0x7284, 0x7280, 0x7336, 0x7325, 0x7334, 0x7329, 0x743a, 0x742a, 0x7433, 0x7422, 0x7425, 0x7435, 0x7436, 0x7434, 0x742f, 0x741b, 0x7426, 0x7428, 0x7525, 0x7526, 0x756b, 0x756a, 0x75e2, 0x75db, 0x75e3, 0x75d9, 0x75d8, 0x75de, 0x75e0, 0x767b, 0x767c, 0x7696, 0x7693, 0x76b4, 0x76dc, 0x774f, 0x77ed, 0x785d, 0x786c, 0x786f, 0x7a0d, 0x7a08, 0x7a0b, 0x7a05, 0x7a00, 0x7a98, 0x7a97, 0x7a96, 0x7ae5, 0x7ae3, 0x7b49, 0x7b56, 0x7b46, 0x7b50, 0x7b52, 0x7b54, 0x7b4d, 0x7b4b, 0x7b4f, 0x7b51, 0x7c9f, 0x7ca5, 0x7d5e, 0x7d50, 0x7d68, 0x7d55, 0x7d2b, 0x7d6e, 0x7d72, 0x7d61, 0x7d66, 0x7d62, 0x7d70, 0x7d73, 0x5584, 0x7fd4, 0x7fd5, 0x800b, 0x8052, 0x8085, 0x8155, 0x8154, 0x814b, 0x8151, 0x814e, 0x8139, 0x8146, 0x813e, 0x814c, 0x8153, 0x8174, 0x8212, 0x821c, 0x83e9, 0x8403, 0x83f8, 0x840d, 0x83e0, 0x83c5, 0x840b, 0x83c1, 0x83ef, 0x83f1, 0x83f4, 0x8457, 0x840a, 0x83f0, 0x840c, 0x83cc, 0x83fd, 0x83f2, 0x83ca, 0x8438, 0x840e, 0x8404, 0x83dc, 0x8407, 0x83d4, 0x83df, 0x865b, 0x86df, 0x86d9, 0x86ed, 0x86d4, 0x86db, 0x86e4, 0x86d0, 0x86de, 0x8857, 0x88c1, 0x88c2, 0x88b1, 0x8983, 0x8996, 0x8a3b, 0x8a60, 0x8a55, 0x8a5e, 0x8a3c, 0x8a41, /* 0xb6 */ 0x8a54, 0x8a5b, 0x8a50, 0x8a46, 0x8a34, 0x8a3a, 0x8a36, 0x8a56, 0x8c61, 0x8c82, 0x8caf, 0x8cbc, 0x8cb3, 0x8cbd, 0x8cc1, 0x8cbb, 0x8cc0, 0x8cb4, 0x8cb7, 0x8cb6, 0x8cbf, 0x8cb8, 0x8d8a, 0x8d85, 0x8d81, 0x8dce, 0x8ddd, 0x8dcb, 0x8dda, 0x8dd1, 0x8dcc, 0x8ddb, 0x8dc6, 0x8efb, 0x8ef8, 0x8efc, 0x8f9c, 0x902e, 0x9035, 0x9031, 0x9038, 0x9032, 0x9036, 0x9102, 0x90f5, 0x9109, 0x90fe, 0x9163, 0x9165, 0x91cf, 0x9214, 0x9215, 0x9223, 0x9209, 0x921e, 0x920d, 0x9210, 0x9207, 0x9211, 0x9594, 0x958f, 0x958b, 0x9591, 0x9593, 0x9592, 0x958e, 0x968a, 0x968e, 0x968b, 0x967d, 0x9685, 0x9686, 0x968d, 0x9672, 0x9684, 0x96c1, 0x96c5, 0x96c4, 0x96c6, 0x96c7, 0x96ef, 0x96f2, 0x97cc, 0x9805, 0x9806, 0x9808, 0x98e7, 0x98ea, 0x98ef, 0x98e9, 0x98f2, 0x98ed, 0x99ae, 0x99ad, 0x9ec3, 0x9ecd, 0x9ed1, 0x4e82, 0x50ad, 0x50b5, 0x50b2, 0x50b3, 0x50c5, 0x50be, 0x50ac, 0x50b7, 0x50bb, 0x50af, 0x50c7, 0x527f, 0x5277, 0x527d, 0x52df, 0x52e6, 0x52e4, 0x52e2, 0x52e3, 0x532f, 0x55df, 0x55e8, 0x55d3, 0x55e6, 0x55ce, 0x55dc, 0x55c7, 0x55d1, 0x55e3, 0x55e4, 0x55ef, 0x55da, 0x55e1, 0x55c5, 0x55c6, 0x55e5, 0x55c9, 0x5712, 0x5713, 0x585e, 0x5851, 0x5858, 0x5857, 0x585a, 0x5854, 0x586b, 0x584c, 0x586d, 0x584a, 0x5862, 0x5852, 0x584b, 0x5967, 0x5ac1, 0x5ac9, 0x5acc, 0x5abe, 0x5abd, 0x5abc, /* 0xb7 */ 0x5ab3, 0x5ac2, 0x5ab2, 0x5d69, 0x5d6f, 0x5e4c, 0x5e79, 0x5ec9, 0x5ec8, 0x5f12, 0x5f59, 0x5fac, 0x5fae, 0x611a, 0x610f, 0x6148, 0x611f, 0x60f3, 0x611b, 0x60f9, 0x6101, 0x6108, 0x614e, 0x614c, 0x6144, 0x614d, 0x613e, 0x6134, 0x6127, 0x610d, 0x6106, 0x6137, 0x6221, 0x6222, 0x6413, 0x643e, 0x641e, 0x642a, 0x642d, 0x643d, 0x642c, 0x640f, 0x641c, 0x6414, 0x640d, 0x6436, 0x6416, 0x6417, 0x6406, 0x656c, 0x659f, 0x65b0, 0x6697, 0x6689, 0x6687, 0x6688, 0x6696, 0x6684, 0x6698, 0x668d, 0x6703, 0x6994, 0x696d, 0x695a, 0x6977, 0x6960, 0x6954, 0x6975, 0x6930, 0x6982, 0x694a, 0x6968, 0x696b, 0x695e, 0x6953, 0x6979, 0x6986, 0x695d, 0x6963, 0x695b, 0x6b47, 0x6b72, 0x6bc0, 0x6bbf, 0x6bd3, 0x6bfd, 0x6ea2, 0x6eaf, 0x6ed3, 0x6eb6, 0x6ec2, 0x6e90, 0x6e9d, 0x6ec7, 0x6ec5, 0x6ea5, 0x6e98, 0x6ebc, 0x6eba, 0x6eab, 0x6ed1, 0x6e96, 0x6e9c, 0x6ec4, 0x6ed4, 0x6eaa, 0x6ea7, 0x6eb4, 0x714e, 0x7159, 0x7169, 0x7164, 0x7149, 0x7167, 0x715c, 0x716c, 0x7166, 0x714c, 0x7165, 0x715e, 0x7146, 0x7168, 0x7156, 0x723a, 0x7252, 0x7337, 0x7345, 0x733f, 0x733e, 0x746f, 0x745a, 0x7455, 0x745f, 0x745e, 0x7441, 0x743f, 0x7459, 0x745b, 0x745c, 0x7576, 0x7578, 0x7600, 0x75f0, 0x7601, 0x75f2, 0x75f1, 0x75fa, 0x75ff, 0x75f4, 0x75f3, 0x76de, 0x76df, 0x775b, 0x776b, 0x7766, 0x775e, 0x7763, /* 0xb8 */ 0x7779, 0x776a, 0x776c, 0x775c, 0x7765, 0x7768, 0x7762, 0x77ee, 0x788e, 0x78b0, 0x7897, 0x7898, 0x788c, 0x7889, 0x787c, 0x7891, 0x7893, 0x787f, 0x797a, 0x797f, 0x7981, 0x842c, 0x79bd, 0x7a1c, 0x7a1a, 0x7a20, 0x7a14, 0x7a1f, 0x7a1e, 0x7a9f, 0x7aa0, 0x7b77, 0x7bc0, 0x7b60, 0x7b6e, 0x7b67, 0x7cb1, 0x7cb3, 0x7cb5, 0x7d93, 0x7d79, 0x7d91, 0x7d81, 0x7d8f, 0x7d5b, 0x7f6e, 0x7f69, 0x7f6a, 0x7f72, 0x7fa9, 0x7fa8, 0x7fa4, 0x8056, 0x8058, 0x8086, 0x8084, 0x8171, 0x8170, 0x8178, 0x8165, 0x816e, 0x8173, 0x816b, 0x8179, 0x817a, 0x8166, 0x8205, 0x8247, 0x8482, 0x8477, 0x843d, 0x8431, 0x8475, 0x8466, 0x846b, 0x8449, 0x846c, 0x845b, 0x843c, 0x8435, 0x8461, 0x8463, 0x8469, 0x846d, 0x8446, 0x865e, 0x865c, 0x865f, 0x86f9, 0x8713, 0x8708, 0x8707, 0x8700, 0x86fe, 0x86fb, 0x8702, 0x8703, 0x8706, 0x870a, 0x8859, 0x88df, 0x88d4, 0x88d9, 0x88dc, 0x88d8, 0x88dd, 0x88e1, 0x88ca, 0x88d5, 0x88d2, 0x899c, 0x89e3, 0x8a6b, 0x8a72, 0x8a73, 0x8a66, 0x8a69, 0x8a70, 0x8a87, 0x8a7c, 0x8a63, 0x8aa0, 0x8a71, 0x8a85, 0x8a6d, 0x8a62, 0x8a6e, 0x8a6c, 0x8a79, 0x8a7b, 0x8a3e, 0x8a68, 0x8c62, 0x8c8a, 0x8c89, 0x8cca, 0x8cc7, 0x8cc8, 0x8cc4, 0x8cb2, 0x8cc3, 0x8cc2, 0x8cc5, 0x8de1, 0x8ddf, 0x8de8, 0x8def, 0x8df3, 0x8dfa, 0x8dea, 0x8de4, 0x8de6, 0x8eb2, 0x8f03, 0x8f09, 0x8efe, 0x8f0a, /* 0xb9 */ 0x8f9f, 0x8fb2, 0x904b, 0x904a, 0x9053, 0x9042, 0x9054, 0x903c, 0x9055, 0x9050, 0x9047, 0x904f, 0x904e, 0x904d, 0x9051, 0x903e, 0x9041, 0x9112, 0x9117, 0x916c, 0x916a, 0x9169, 0x91c9, 0x9237, 0x9257, 0x9238, 0x923d, 0x9240, 0x923e, 0x925b, 0x924b, 0x9264, 0x9251, 0x9234, 0x9249, 0x924d, 0x9245, 0x9239, 0x923f, 0x925a, 0x9598, 0x9698, 0x9694, 0x9695, 0x96cd, 0x96cb, 0x96c9, 0x96ca, 0x96f7, 0x96fb, 0x96f9, 0x96f6, 0x9756, 0x9774, 0x9776, 0x9810, 0x9811, 0x9813, 0x980a, 0x9812, 0x980c, 0x98fc, 0x98f4, 0x98fd, 0x98fe, 0x99b3, 0x99b1, 0x99b4, 0x9ae1, 0x9ce9, 0x9e82, 0x9f0e, 0x9f13, 0x9f20, 0x50e7, 0x50ee, 0x50e5, 0x50d6, 0x50ed, 0x50da, 0x50d5, 0x50cf, 0x50d1, 0x50f1, 0x50ce, 0x50e9, 0x5162, 0x51f3, 0x5283, 0x5282, 0x5331, 0x53ad, 0x55fe, 0x5600, 0x561b, 0x5617, 0x55fd, 0x5614, 0x5606, 0x5609, 0x560d, 0x560e, 0x55f7, 0x5616, 0x561f, 0x5608, 0x5610, 0x55f6, 0x5718, 0x5716, 0x5875, 0x587e, 0x5883, 0x5893, 0x588a, 0x5879, 0x5885, 0x587d, 0x58fd, 0x5925, 0x5922, 0x5924, 0x596a, 0x5969, 0x5ae1, 0x5ae6, 0x5ae9, 0x5ad7, 0x5ad6, 0x5ad8, 0x5ae3, 0x5b75, 0x5bde, 0x5be7, 0x5be1, 0x5be5, 0x5be6, 0x5be8, 0x5be2, 0x5be4, 0x5bdf, 0x5c0d, 0x5c62, 0x5d84, 0x5d87, 0x5e5b, 0x5e63, 0x5e55, 0x5e57, 0x5e54, 0x5ed3, 0x5ed6, 0x5f0a, 0x5f46, 0x5f70, 0x5fb9, 0x6147, /* 0xba */ 0x613f, 0x614b, 0x6177, 0x6162, 0x6163, 0x615f, 0x615a, 0x6158, 0x6175, 0x622a, 0x6487, 0x6458, 0x6454, 0x64a4, 0x6478, 0x645f, 0x647a, 0x6451, 0x6467, 0x6434, 0x646d, 0x647b, 0x6572, 0x65a1, 0x65d7, 0x65d6, 0x66a2, 0x66a8, 0x669d, 0x699c, 0x69a8, 0x6995, 0x69c1, 0x69ae, 0x69d3, 0x69cb, 0x699b, 0x69b7, 0x69bb, 0x69ab, 0x69b4, 0x69d0, 0x69cd, 0x69ad, 0x69cc, 0x69a6, 0x69c3, 0x69a3, 0x6b49, 0x6b4c, 0x6c33, 0x6f33, 0x6f14, 0x6efe, 0x6f13, 0x6ef4, 0x6f29, 0x6f3e, 0x6f20, 0x6f2c, 0x6f0f, 0x6f02, 0x6f22, 0x6eff, 0x6eef, 0x6f06, 0x6f31, 0x6f38, 0x6f32, 0x6f23, 0x6f15, 0x6f2b, 0x6f2f, 0x6f88, 0x6f2a, 0x6eec, 0x6f01, 0x6ef2, 0x6ecc, 0x6ef7, 0x7194, 0x7199, 0x717d, 0x718a, 0x7184, 0x7192, 0x723e, 0x7292, 0x7296, 0x7344, 0x7350, 0x7464, 0x7463, 0x746a, 0x7470, 0x746d, 0x7504, 0x7591, 0x7627, 0x760d, 0x760b, 0x7609, 0x7613, 0x76e1, 0x76e3, 0x7784, 0x777d, 0x777f, 0x7761, 0x78c1, 0x789f, 0x78a7, 0x78b3, 0x78a9, 0x78a3, 0x798e, 0x798f, 0x798d, 0x7a2e, 0x7a31, 0x7aaa, 0x7aa9, 0x7aed, 0x7aef, 0x7ba1, 0x7b95, 0x7b8b, 0x7b75, 0x7b97, 0x7b9d, 0x7b94, 0x7b8f, 0x7bb8, 0x7b87, 0x7b84, 0x7cb9, 0x7cbd, 0x7cbe, 0x7dbb, 0x7db0, 0x7d9c, 0x7dbd, 0x7dbe, 0x7da0, 0x7dca, 0x7db4, 0x7db2, 0x7db1, 0x7dba, 0x7da2, 0x7dbf, 0x7db5, 0x7db8, 0x7dad, 0x7dd2, 0x7dc7, 0x7dac, /* 0xbb */ 0x7f70, 0x7fe0, 0x7fe1, 0x7fdf, 0x805e, 0x805a, 0x8087, 0x8150, 0x8180, 0x818f, 0x8188, 0x818a, 0x817f, 0x8182, 0x81e7, 0x81fa, 0x8207, 0x8214, 0x821e, 0x824b, 0x84c9, 0x84bf, 0x84c6, 0x84c4, 0x8499, 0x849e, 0x84b2, 0x849c, 0x84cb, 0x84b8, 0x84c0, 0x84d3, 0x8490, 0x84bc, 0x84d1, 0x84ca, 0x873f, 0x871c, 0x873b, 0x8722, 0x8725, 0x8734, 0x8718, 0x8755, 0x8737, 0x8729, 0x88f3, 0x8902, 0x88f4, 0x88f9, 0x88f8, 0x88fd, 0x88e8, 0x891a, 0x88ef, 0x8aa6, 0x8a8c, 0x8a9e, 0x8aa3, 0x8a8d, 0x8aa1, 0x8a93, 0x8aa4, 0x8aaa, 0x8aa5, 0x8aa8, 0x8a98, 0x8a91, 0x8a9a, 0x8aa7, 0x8c6a, 0x8c8d, 0x8c8c, 0x8cd3, 0x8cd1, 0x8cd2, 0x8d6b, 0x8d99, 0x8d95, 0x8dfc, 0x8f14, 0x8f12, 0x8f15, 0x8f13, 0x8fa3, 0x9060, 0x9058, 0x905c, 0x9063, 0x9059, 0x905e, 0x9062, 0x905d, 0x905b, 0x9119, 0x9118, 0x911e, 0x9175, 0x9178, 0x9177, 0x9174, 0x9278, 0x9280, 0x9285, 0x9298, 0x9296, 0x927b, 0x9293, 0x929c, 0x92a8, 0x927c, 0x9291, 0x95a1, 0x95a8, 0x95a9, 0x95a3, 0x95a5, 0x95a4, 0x9699, 0x969c, 0x969b, 0x96cc, 0x96d2, 0x9700, 0x977c, 0x9785, 0x97f6, 0x9817, 0x9818, 0x98af, 0x98b1, 0x9903, 0x9905, 0x990c, 0x9909, 0x99c1, 0x9aaf, 0x9ab0, 0x9ae6, 0x9b41, 0x9b42, 0x9cf4, 0x9cf6, 0x9cf3, 0x9ebc, 0x9f3b, 0x9f4a, 0x5104, 0x5100, 0x50fb, 0x50f5, 0x50f9, 0x5102, 0x5108, 0x5109, 0x5105, 0x51dc, /* 0xbc */ 0x5287, 0x5288, 0x5289, 0x528d, 0x528a, 0x52f0, 0x53b2, 0x562e, 0x563b, 0x5639, 0x5632, 0x563f, 0x5634, 0x5629, 0x5653, 0x564e, 0x5657, 0x5674, 0x5636, 0x562f, 0x5630, 0x5880, 0x589f, 0x589e, 0x58b3, 0x589c, 0x58ae, 0x58a9, 0x58a6, 0x596d, 0x5b09, 0x5afb, 0x5b0b, 0x5af5, 0x5b0c, 0x5b08, 0x5bee, 0x5bec, 0x5be9, 0x5beb, 0x5c64, 0x5c65, 0x5d9d, 0x5d94, 0x5e62, 0x5e5f, 0x5e61, 0x5ee2, 0x5eda, 0x5edf, 0x5edd, 0x5ee3, 0x5ee0, 0x5f48, 0x5f71, 0x5fb7, 0x5fb5, 0x6176, 0x6167, 0x616e, 0x615d, 0x6155, 0x6182, 0x617c, 0x6170, 0x616b, 0x617e, 0x61a7, 0x6190, 0x61ab, 0x618e, 0x61ac, 0x619a, 0x61a4, 0x6194, 0x61ae, 0x622e, 0x6469, 0x646f, 0x6479, 0x649e, 0x64b2, 0x6488, 0x6490, 0x64b0, 0x64a5, 0x6493, 0x6495, 0x64a9, 0x6492, 0x64ae, 0x64ad, 0x64ab, 0x649a, 0x64ac, 0x6499, 0x64a2, 0x64b3, 0x6575, 0x6577, 0x6578, 0x66ae, 0x66ab, 0x66b4, 0x66b1, 0x6a23, 0x6a1f, 0x69e8, 0x6a01, 0x6a1e, 0x6a19, 0x69fd, 0x6a21, 0x6a13, 0x6a0a, 0x69f3, 0x6a02, 0x6a05, 0x69ed, 0x6a11, 0x6b50, 0x6b4e, 0x6ba4, 0x6bc5, 0x6bc6, 0x6f3f, 0x6f7c, 0x6f84, 0x6f51, 0x6f66, 0x6f54, 0x6f86, 0x6f6d, 0x6f5b, 0x6f78, 0x6f6e, 0x6f8e, 0x6f7a, 0x6f70, 0x6f64, 0x6f97, 0x6f58, 0x6ed5, 0x6f6f, 0x6f60, 0x6f5f, 0x719f, 0x71ac, 0x71b1, 0x71a8, 0x7256, 0x729b, 0x734e, 0x7357, 0x7469, 0x748b, 0x7483, /* 0xbd */ 0x747e, 0x7480, 0x757f, 0x7620, 0x7629, 0x761f, 0x7624, 0x7626, 0x7621, 0x7622, 0x769a, 0x76ba, 0x76e4, 0x778e, 0x7787, 0x778c, 0x7791, 0x778b, 0x78cb, 0x78c5, 0x78ba, 0x78ca, 0x78be, 0x78d5, 0x78bc, 0x78d0, 0x7a3f, 0x7a3c, 0x7a40, 0x7a3d, 0x7a37, 0x7a3b, 0x7aaf, 0x7aae, 0x7bad, 0x7bb1, 0x7bc4, 0x7bb4, 0x7bc6, 0x7bc7, 0x7bc1, 0x7ba0, 0x7bcc, 0x7cca, 0x7de0, 0x7df4, 0x7def, 0x7dfb, 0x7dd8, 0x7dec, 0x7ddd, 0x7de8, 0x7de3, 0x7dda, 0x7dde, 0x7de9, 0x7d9e, 0x7dd9, 0x7df2, 0x7df9, 0x7f75, 0x7f77, 0x7faf, 0x7fe9, 0x8026, 0x819b, 0x819c, 0x819d, 0x81a0, 0x819a, 0x8198, 0x8517, 0x853d, 0x851a, 0x84ee, 0x852c, 0x852d, 0x8513, 0x8511, 0x8523, 0x8521, 0x8514, 0x84ec, 0x8525, 0x84ff, 0x8506, 0x8782, 0x8774, 0x8776, 0x8760, 0x8766, 0x8778, 0x8768, 0x8759, 0x8757, 0x874c, 0x8753, 0x885b, 0x885d, 0x8910, 0x8907, 0x8912, 0x8913, 0x8915, 0x890a, 0x8abc, 0x8ad2, 0x8ac7, 0x8ac4, 0x8a95, 0x8acb, 0x8af8, 0x8ab2, 0x8ac9, 0x8ac2, 0x8abf, 0x8ab0, 0x8ad6, 0x8acd, 0x8ab6, 0x8ab9, 0x8adb, 0x8c4c, 0x8c4e, 0x8c6c, 0x8ce0, 0x8cde, 0x8ce6, 0x8ce4, 0x8cec, 0x8ced, 0x8ce2, 0x8ce3, 0x8cdc, 0x8cea, 0x8ce1, 0x8d6d, 0x8d9f, 0x8da3, 0x8e2b, 0x8e10, 0x8e1d, 0x8e22, 0x8e0f, 0x8e29, 0x8e1f, 0x8e21, 0x8e1e, 0x8eba, 0x8f1d, 0x8f1b, 0x8f1f, 0x8f29, 0x8f26, 0x8f2a, 0x8f1c, 0x8f1e, /* 0xbe */ 0x8f25, 0x9069, 0x906e, 0x9068, 0x906d, 0x9077, 0x9130, 0x912d, 0x9127, 0x9131, 0x9187, 0x9189, 0x918b, 0x9183, 0x92c5, 0x92bb, 0x92b7, 0x92ea, 0x92ac, 0x92e4, 0x92c1, 0x92b3, 0x92bc, 0x92d2, 0x92c7, 0x92f0, 0x92b2, 0x95ad, 0x95b1, 0x9704, 0x9706, 0x9707, 0x9709, 0x9760, 0x978d, 0x978b, 0x978f, 0x9821, 0x982b, 0x981c, 0x98b3, 0x990a, 0x9913, 0x9912, 0x9918, 0x99dd, 0x99d0, 0x99df, 0x99db, 0x99d1, 0x99d5, 0x99d2, 0x99d9, 0x9ab7, 0x9aee, 0x9aef, 0x9b27, 0x9b45, 0x9b44, 0x9b77, 0x9b6f, 0x9d06, 0x9d09, 0x9d03, 0x9ea9, 0x9ebe, 0x9ece, 0x58a8, 0x9f52, 0x5112, 0x5118, 0x5114, 0x5110, 0x5115, 0x5180, 0x51aa, 0x51dd, 0x5291, 0x5293, 0x52f3, 0x5659, 0x566b, 0x5679, 0x5669, 0x5664, 0x5678, 0x566a, 0x5668, 0x5665, 0x5671, 0x566f, 0x566c, 0x5662, 0x5676, 0x58c1, 0x58be, 0x58c7, 0x58c5, 0x596e, 0x5b1d, 0x5b34, 0x5b78, 0x5bf0, 0x5c0e, 0x5f4a, 0x61b2, 0x6191, 0x61a9, 0x618a, 0x61cd, 0x61b6, 0x61be, 0x61ca, 0x61c8, 0x6230, 0x64c5, 0x64c1, 0x64cb, 0x64bb, 0x64bc, 0x64da, 0x64c4, 0x64c7, 0x64c2, 0x64cd, 0x64bf, 0x64d2, 0x64d4, 0x64be, 0x6574, 0x66c6, 0x66c9, 0x66b9, 0x66c4, 0x66c7, 0x66b8, 0x6a3d, 0x6a38, 0x6a3a, 0x6a59, 0x6a6b, 0x6a58, 0x6a39, 0x6a44, 0x6a62, 0x6a61, 0x6a4b, 0x6a47, 0x6a35, 0x6a5f, 0x6a48, 0x6b59, 0x6b77, 0x6c05, 0x6fc2, 0x6fb1, 0x6fa1, /* 0xbf */ 0x6fc3, 0x6fa4, 0x6fc1, 0x6fa7, 0x6fb3, 0x6fc0, 0x6fb9, 0x6fb6, 0x6fa6, 0x6fa0, 0x6fb4, 0x71be, 0x71c9, 0x71d0, 0x71d2, 0x71c8, 0x71d5, 0x71b9, 0x71ce, 0x71d9, 0x71dc, 0x71c3, 0x71c4, 0x7368, 0x749c, 0x74a3, 0x7498, 0x749f, 0x749e, 0x74e2, 0x750c, 0x750d, 0x7634, 0x7638, 0x763a, 0x76e7, 0x76e5, 0x77a0, 0x779e, 0x779f, 0x77a5, 0x78e8, 0x78da, 0x78ec, 0x78e7, 0x79a6, 0x7a4d, 0x7a4e, 0x7a46, 0x7a4c, 0x7a4b, 0x7aba, 0x7bd9, 0x7c11, 0x7bc9, 0x7be4, 0x7bdb, 0x7be1, 0x7be9, 0x7be6, 0x7cd5, 0x7cd6, 0x7e0a, 0x7e11, 0x7e08, 0x7e1b, 0x7e23, 0x7e1e, 0x7e1d, 0x7e09, 0x7e10, 0x7f79, 0x7fb2, 0x7ff0, 0x7ff1, 0x7fee, 0x8028, 0x81b3, 0x81a9, 0x81a8, 0x81fb, 0x8208, 0x8258, 0x8259, 0x854a, 0x8559, 0x8548, 0x8568, 0x8569, 0x8543, 0x8549, 0x856d, 0x856a, 0x855e, 0x8783, 0x879f, 0x879e, 0x87a2, 0x878d, 0x8861, 0x892a, 0x8932, 0x8925, 0x892b, 0x8921, 0x89aa, 0x89a6, 0x8ae6, 0x8afa, 0x8aeb, 0x8af1, 0x8b00, 0x8adc, 0x8ae7, 0x8aee, 0x8afe, 0x8b01, 0x8b02, 0x8af7, 0x8aed, 0x8af3, 0x8af6, 0x8afc, 0x8c6b, 0x8c6d, 0x8c93, 0x8cf4, 0x8e44, 0x8e31, 0x8e34, 0x8e42, 0x8e39, 0x8e35, 0x8f3b, 0x8f2f, 0x8f38, 0x8f33, 0x8fa8, 0x8fa6, 0x9075, 0x9074, 0x9078, 0x9072, 0x907c, 0x907a, 0x9134, 0x9192, 0x9320, 0x9336, 0x92f8, 0x9333, 0x932f, 0x9322, 0x92fc, 0x932b, 0x9304, 0x931a, /* 0xc0 */ 0x9310, 0x9326, 0x9321, 0x9315, 0x932e, 0x9319, 0x95bb, 0x96a7, 0x96a8, 0x96aa, 0x96d5, 0x970e, 0x9711, 0x9716, 0x970d, 0x9713, 0x970f, 0x975b, 0x975c, 0x9766, 0x9798, 0x9830, 0x9838, 0x983b, 0x9837, 0x982d, 0x9839, 0x9824, 0x9910, 0x9928, 0x991e, 0x991b, 0x9921, 0x991a, 0x99ed, 0x99e2, 0x99f1, 0x9ab8, 0x9abc, 0x9afb, 0x9aed, 0x9b28, 0x9b91, 0x9d15, 0x9d23, 0x9d26, 0x9d28, 0x9d12, 0x9d1b, 0x9ed8, 0x9ed4, 0x9f8d, 0x9f9c, 0x512a, 0x511f, 0x5121, 0x5132, 0x52f5, 0x568e, 0x5680, 0x5690, 0x5685, 0x5687, 0x568f, 0x58d5, 0x58d3, 0x58d1, 0x58ce, 0x5b30, 0x5b2a, 0x5b24, 0x5b7a, 0x5c37, 0x5c68, 0x5dbc, 0x5dba, 0x5dbd, 0x5db8, 0x5e6b, 0x5f4c, 0x5fbd, 0x61c9, 0x61c2, 0x61c7, 0x61e6, 0x61cb, 0x6232, 0x6234, 0x64ce, 0x64ca, 0x64d8, 0x64e0, 0x64f0, 0x64e6, 0x64ec, 0x64f1, 0x64e2, 0x64ed, 0x6582, 0x6583, 0x66d9, 0x66d6, 0x6a80, 0x6a94, 0x6a84, 0x6aa2, 0x6a9c, 0x6adb, 0x6aa3, 0x6a7e, 0x6a97, 0x6a90, 0x6aa0, 0x6b5c, 0x6bae, 0x6bda, 0x6c08, 0x6fd8, 0x6ff1, 0x6fdf, 0x6fe0, 0x6fdb, 0x6fe4, 0x6feb, 0x6fef, 0x6f80, 0x6fec, 0x6fe1, 0x6fe9, 0x6fd5, 0x6fee, 0x6ff0, 0x71e7, 0x71df, 0x71ee, 0x71e6, 0x71e5, 0x71ed, 0x71ec, 0x71f4, 0x71e0, 0x7235, 0x7246, 0x7370, 0x7372, 0x74a9, 0x74b0, 0x74a6, 0x74a8, 0x7646, 0x7642, 0x764c, 0x76ea, 0x77b3, 0x77aa, 0x77b0, 0x77ac, /* 0xc1 */ 0x77a7, 0x77ad, 0x77ef, 0x78f7, 0x78fa, 0x78f4, 0x78ef, 0x7901, 0x79a7, 0x79aa, 0x7a57, 0x7abf, 0x7c07, 0x7c0d, 0x7bfe, 0x7bf7, 0x7c0c, 0x7be0, 0x7ce0, 0x7cdc, 0x7cde, 0x7ce2, 0x7cdf, 0x7cd9, 0x7cdd, 0x7e2e, 0x7e3e, 0x7e46, 0x7e37, 0x7e32, 0x7e43, 0x7e2b, 0x7e3d, 0x7e31, 0x7e45, 0x7e41, 0x7e34, 0x7e39, 0x7e48, 0x7e35, 0x7e3f, 0x7e2f, 0x7f44, 0x7ff3, 0x7ffc, 0x8071, 0x8072, 0x8070, 0x806f, 0x8073, 0x81c6, 0x81c3, 0x81ba, 0x81c2, 0x81c0, 0x81bf, 0x81bd, 0x81c9, 0x81be, 0x81e8, 0x8209, 0x8271, 0x85aa, 0x8584, 0x857e, 0x859c, 0x8591, 0x8594, 0x85af, 0x859b, 0x8587, 0x85a8, 0x858a, 0x8667, 0x87c0, 0x87d1, 0x87b3, 0x87d2, 0x87c6, 0x87ab, 0x87bb, 0x87ba, 0x87c8, 0x87cb, 0x893b, 0x8936, 0x8944, 0x8938, 0x893d, 0x89ac, 0x8b0e, 0x8b17, 0x8b19, 0x8b1b, 0x8b0a, 0x8b20, 0x8b1d, 0x8b04, 0x8b10, 0x8c41, 0x8c3f, 0x8c73, 0x8cfa, 0x8cfd, 0x8cfc, 0x8cf8, 0x8cfb, 0x8da8, 0x8e49, 0x8e4b, 0x8e48, 0x8e4a, 0x8f44, 0x8f3e, 0x8f42, 0x8f45, 0x8f3f, 0x907f, 0x907d, 0x9084, 0x9081, 0x9082, 0x9080, 0x9139, 0x91a3, 0x919e, 0x919c, 0x934d, 0x9382, 0x9328, 0x9375, 0x934a, 0x9365, 0x934b, 0x9318, 0x937e, 0x936c, 0x935b, 0x9370, 0x935a, 0x9354, 0x95ca, 0x95cb, 0x95cc, 0x95c8, 0x95c6, 0x96b1, 0x96b8, 0x96d6, 0x971c, 0x971e, 0x97a0, 0x97d3, 0x9846, 0x98b6, 0x9935, 0x9a01, /* 0xc2 */ 0x99ff, 0x9bae, 0x9bab, 0x9baa, 0x9bad, 0x9d3b, 0x9d3f, 0x9e8b, 0x9ecf, 0x9ede, 0x9edc, 0x9edd, 0x9edb, 0x9f3e, 0x9f4b, 0x53e2, 0x5695, 0x56ae, 0x58d9, 0x58d8, 0x5b38, 0x5f5d, 0x61e3, 0x6233, 0x64f4, 0x64f2, 0x64fe, 0x6506, 0x64fa, 0x64fb, 0x64f7, 0x65b7, 0x66dc, 0x6726, 0x6ab3, 0x6aac, 0x6ac3, 0x6abb, 0x6ab8, 0x6ac2, 0x6aae, 0x6aaf, 0x6b5f, 0x6b78, 0x6baf, 0x7009, 0x700b, 0x6ffe, 0x7006, 0x6ffa, 0x7011, 0x700f, 0x71fb, 0x71fc, 0x71fe, 0x71f8, 0x7377, 0x7375, 0x74a7, 0x74bf, 0x7515, 0x7656, 0x7658, 0x7652, 0x77bd, 0x77bf, 0x77bb, 0x77bc, 0x790e, 0x79ae, 0x7a61, 0x7a62, 0x7a60, 0x7ac4, 0x7ac5, 0x7c2b, 0x7c27, 0x7c2a, 0x7c1e, 0x7c23, 0x7c21, 0x7ce7, 0x7e54, 0x7e55, 0x7e5e, 0x7e5a, 0x7e61, 0x7e52, 0x7e59, 0x7f48, 0x7ff9, 0x7ffb, 0x8077, 0x8076, 0x81cd, 0x81cf, 0x820a, 0x85cf, 0x85a9, 0x85cd, 0x85d0, 0x85c9, 0x85b0, 0x85ba, 0x85b9, 0x85a6, 0x87ef, 0x87ec, 0x87f2, 0x87e0, 0x8986, 0x89b2, 0x89f4, 0x8b28, 0x8b39, 0x8b2c, 0x8b2b, 0x8c50, 0x8d05, 0x8e59, 0x8e63, 0x8e66, 0x8e64, 0x8e5f, 0x8e55, 0x8ec0, 0x8f49, 0x8f4d, 0x9087, 0x9083, 0x9088, 0x91ab, 0x91ac, 0x91d0, 0x9394, 0x938a, 0x9396, 0x93a2, 0x93b3, 0x93ae, 0x93ac, 0x93b0, 0x9398, 0x939a, 0x9397, 0x95d4, 0x95d6, 0x95d0, 0x95d5, 0x96e2, 0x96dc, 0x96d9, 0x96db, 0x96de, 0x9724, 0x97a3, 0x97a6, /* 0xc3 */ 0x97ad, 0x97f9, 0x984d, 0x984f, 0x984c, 0x984e, 0x9853, 0x98ba, 0x993e, 0x993f, 0x993d, 0x992e, 0x99a5, 0x9a0e, 0x9ac1, 0x9b03, 0x9b06, 0x9b4f, 0x9b4e, 0x9b4d, 0x9bca, 0x9bc9, 0x9bfd, 0x9bc8, 0x9bc0, 0x9d51, 0x9d5d, 0x9d60, 0x9ee0, 0x9f15, 0x9f2c, 0x5133, 0x56a5, 0x58de, 0x58df, 0x58e2, 0x5bf5, 0x9f90, 0x5eec, 0x61f2, 0x61f7, 0x61f6, 0x61f5, 0x6500, 0x650f, 0x66e0, 0x66dd, 0x6ae5, 0x6add, 0x6ada, 0x6ad3, 0x701b, 0x701f, 0x7028, 0x701a, 0x701d, 0x7015, 0x7018, 0x7206, 0x720d, 0x7258, 0x72a2, 0x7378, 0x737a, 0x74bd, 0x74ca, 0x74e3, 0x7587, 0x7586, 0x765f, 0x7661, 0x77c7, 0x7919, 0x79b1, 0x7a6b, 0x7a69, 0x7c3e, 0x7c3f, 0x7c38, 0x7c3d, 0x7c37, 0x7c40, 0x7e6b, 0x7e6d, 0x7e79, 0x7e69, 0x7e6a, 0x7f85, 0x7e73, 0x7fb6, 0x7fb9, 0x7fb8, 0x81d8, 0x85e9, 0x85dd, 0x85ea, 0x85d5, 0x85e4, 0x85e5, 0x85f7, 0x87fb, 0x8805, 0x880d, 0x87f9, 0x87fe, 0x8960, 0x895f, 0x8956, 0x895e, 0x8b41, 0x8b5c, 0x8b58, 0x8b49, 0x8b5a, 0x8b4e, 0x8b4f, 0x8b46, 0x8b59, 0x8d08, 0x8d0a, 0x8e7c, 0x8e72, 0x8e87, 0x8e76, 0x8e6c, 0x8e7a, 0x8e74, 0x8f54, 0x8f4e, 0x8fad, 0x908a, 0x908b, 0x91b1, 0x91ae, 0x93e1, 0x93d1, 0x93df, 0x93c3, 0x93c8, 0x93dc, 0x93dd, 0x93d6, 0x93e2, 0x93cd, 0x93d8, 0x93e4, 0x93d7, 0x93e8, 0x95dc, 0x96b4, 0x96e3, 0x972a, 0x9727, 0x9761, 0x97dc, 0x97fb, 0x985e, /* 0xc4 */ 0x9858, 0x985b, 0x98bc, 0x9945, 0x9949, 0x9a16, 0x9a19, 0x9b0d, 0x9be8, 0x9be7, 0x9bd6, 0x9bdb, 0x9d89, 0x9d61, 0x9d72, 0x9d6a, 0x9d6c, 0x9e92, 0x9e97, 0x9e93, 0x9eb4, 0x52f8, 0x56a8, 0x56b7, 0x56b6, 0x56b4, 0x56bc, 0x58e4, 0x5b40, 0x5b43, 0x5b7d, 0x5bf6, 0x5dc9, 0x61f8, 0x61fa, 0x6518, 0x6514, 0x6519, 0x66e6, 0x6727, 0x6aec, 0x703e, 0x7030, 0x7032, 0x7210, 0x737b, 0x74cf, 0x7662, 0x7665, 0x7926, 0x792a, 0x792c, 0x792b, 0x7ac7, 0x7af6, 0x7c4c, 0x7c43, 0x7c4d, 0x7cef, 0x7cf0, 0x8fae, 0x7e7d, 0x7e7c, 0x7e82, 0x7f4c, 0x8000, 0x81da, 0x8266, 0x85fb, 0x85f9, 0x8611, 0x85fa, 0x8606, 0x860b, 0x8607, 0x860a, 0x8814, 0x8815, 0x8964, 0x89ba, 0x89f8, 0x8b70, 0x8b6c, 0x8b66, 0x8b6f, 0x8b5f, 0x8b6b, 0x8d0f, 0x8d0d, 0x8e89, 0x8e81, 0x8e85, 0x8e82, 0x91b4, 0x91cb, 0x9418, 0x9403, 0x93fd, 0x95e1, 0x9730, 0x98c4, 0x9952, 0x9951, 0x99a8, 0x9a2b, 0x9a30, 0x9a37, 0x9a35, 0x9c13, 0x9c0d, 0x9e79, 0x9eb5, 0x9ee8, 0x9f2f, 0x9f5f, 0x9f63, 0x9f61, 0x5137, 0x5138, 0x56c1, 0x56c0, 0x56c2, 0x5914, 0x5c6c, 0x5dcd, 0x61fc, 0x61fe, 0x651d, 0x651c, 0x6595, 0x66e9, 0x6afb, 0x6b04, 0x6afa, 0x6bb2, 0x704c, 0x721b, 0x72a7, 0x74d6, 0x74d4, 0x7669, 0x77d3, 0x7c50, 0x7e8f, 0x7e8c, 0x7fbc, 0x8617, 0x862d, 0x861a, 0x8823, 0x8822, 0x8821, 0x881f, 0x896a, 0x896c, 0x89bd, 0x8b74, /* 0xc5 */ 0x8b77, 0x8b7d, 0x8d13, 0x8e8a, 0x8e8d, 0x8e8b, 0x8f5f, 0x8faf, 0x91ba, 0x942e, 0x9433, 0x9435, 0x943a, 0x9438, 0x9432, 0x942b, 0x95e2, 0x9738, 0x9739, 0x9732, 0x97ff, 0x9867, 0x9865, 0x9957, 0x9a45, 0x9a43, 0x9a40, 0x9a3e, 0x9acf, 0x9b54, 0x9b51, 0x9c2d, 0x9c25, 0x9daf, 0x9db4, 0x9dc2, 0x9db8, 0x9e9d, 0x9eef, 0x9f19, 0x9f5c, 0x9f66, 0x9f67, 0x513c, 0x513b, 0x56c8, 0x56ca, 0x56c9, 0x5b7f, 0x5dd4, 0x5dd2, 0x5f4e, 0x61ff, 0x6524, 0x6b0a, 0x6b61, 0x7051, 0x7058, 0x7380, 0x74e4, 0x758a, 0x766e, 0x766c, 0x79b3, 0x7c60, 0x7c5f, 0x807e, 0x807d, 0x81df, 0x8972, 0x896f, 0x89fc, 0x8b80, 0x8d16, 0x8d17, 0x8e91, 0x8e93, 0x8f61, 0x9148, 0x9444, 0x9451, 0x9452, 0x973d, 0x973e, 0x97c3, 0x97c1, 0x986b, 0x9955, 0x9a55, 0x9a4d, 0x9ad2, 0x9b1a, 0x9c49, 0x9c31, 0x9c3e, 0x9c3b, 0x9dd3, 0x9dd7, 0x9f34, 0x9f6c, 0x9f6a, 0x9f94, 0x56cc, 0x5dd6, 0x6200, 0x6523, 0x652b, 0x652a, 0x66ec, 0x6b10, 0x74da, 0x7aca, 0x7c64, 0x7c63, 0x7c65, 0x7e93, 0x7e96, 0x7e94, 0x81e2, 0x8638, 0x863f, 0x8831, 0x8b8a, 0x9090, 0x908f, 0x9463, 0x9460, 0x9464, 0x9768, 0x986f, 0x995c, 0x9a5a, 0x9a5b, 0x9a57, 0x9ad3, 0x9ad4, 0x9ad1, 0x9c54, 0x9c57, 0x9c56, 0x9de5, 0x9e9f, 0x9ef4, 0x56d1, 0x58e9, 0x652c, 0x705e, 0x7671, 0x7672, 0x77d7, 0x7f50, 0x7f88, 0x8836, 0x8839, 0x8862, 0x8b93, 0x8b92, /* 0xc6 */ 0x8b96, 0x8277, 0x8d1b, 0x91c0, 0x946a, 0x9742, 0x9748, 0x9744, 0x97c6, 0x9870, 0x9a5f, 0x9b22, 0x9b58, 0x9c5f, 0x9df9, 0x9dfa, 0x9e7c, 0x9e7d, 0x9f07, 0x9f77, 0x9f72, 0x5ef3, 0x6b16, 0x7063, 0x7c6c, 0x7c6e, 0x883b, 0x89c0, 0x8ea1, 0x91c1, 0x9472, 0x9470, 0x9871, 0x995e, 0x9ad6, 0x9b23, 0x9ecc, 0x7064, 0x77da, 0x8b9a, 0x9477, 0x97c9, 0x9a62, 0x9a65, 0x7e9c, 0x8b9c, 0x8eaa, 0x91c5, 0x947d, 0x947e, 0x947c, 0x9c77, 0x9c78, 0x9ef7, 0x8c54, 0x947f, 0x9e1a, 0x7228, 0x9a6a, 0x9b31, 0x9e1b, 0x9e1e, 0x7c72, 0x30fe, 0x309d, 0x309e, 0x3005, 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, 0x304a, 0x304b, 0x304c, 0x304d, 0x304e, 0x304f, 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e, 0x305f, 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068, 0x3069, 0x306a, 0x306b, 0x306c, 0x306d, 0x306e, 0x306f, 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, 0x3078, 0x3079, 0x307a, 0x307b, 0x307c, 0x307d, 0x307e, 0x307f, 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087, 0x3088, 0x3089, 0x308a, 0x308b, 0x308c, 0x308d, 0x308e, 0x308f, 0x3090, 0x3091, 0x3092, 0x3093, 0x30a1, 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, /* 0xc7 */ 0x30a8, 0x30a9, 0x30aa, 0x30ab, 0x30ac, 0x30ad, 0x30ae, 0x30af, 0x30b0, 0x30b1, 0x30b2, 0x30b3, 0x30b4, 0x30b5, 0x30b6, 0x30b7, 0x30b8, 0x30b9, 0x30ba, 0x30bb, 0x30bc, 0x30bd, 0x30be, 0x30bf, 0x30c0, 0x30c1, 0x30c2, 0x30c3, 0x30c4, 0x30c5, 0x30c6, 0x30c7, 0x30c8, 0x30c9, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d0, 0x30d1, 0x30d2, 0x30d3, 0x30d4, 0x30d5, 0x30d6, 0x30d7, 0x30d8, 0x30d9, 0x30da, 0x30db, 0x30dc, 0x30dd, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ee, 0x30ef, 0x30f0, 0x30f1, 0x30f2, 0x30f3, 0x30f4, 0x30f5, 0x30f6, 0x0414, 0x0415, 0x0401, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x2474, 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, }; static const unsigned short big5_2uni_pagec9[7652] = { /* 0xc9 */ 0x4e42, 0x4e5c, 0x51f5, 0x531a, 0x5382, 0x4e07, 0x4e0c, 0x4e47, 0x4e8d, 0x56d7, 0xfa0c, 0x5c6e, 0x5f73, 0x4e0f, 0x5187, 0x4e0e, 0x4e2e, 0x4e93, 0x4ec2, 0x4ec9, 0x4ec8, 0x5198, 0x52fc, 0x536c, 0x53b9, 0x5720, 0x5903, 0x592c, 0x5c10, 0x5dff, 0x65e1, 0x6bb3, 0x6bcc, 0x6c14, 0x723f, 0x4e31, 0x4e3c, 0x4ee8, 0x4edc, 0x4ee9, 0x4ee1, 0x4edd, 0x4eda, 0x520c, 0x531c, 0x534c, 0x5722, 0x5723, 0x5917, 0x592f, 0x5b81, 0x5b84, 0x5c12, 0x5c3b, 0x5c74, 0x5c73, 0x5e04, 0x5e80, 0x5e82, 0x5fc9, 0x6209, 0x6250, 0x6c15, 0x6c36, 0x6c43, 0x6c3f, 0x6c3b, 0x72ae, 0x72b0, 0x738a, 0x79b8, 0x808a, 0x961e, 0x4f0e, 0x4f18, 0x4f2c, 0x4ef5, 0x4f14, 0x4ef1, 0x4f00, 0x4ef7, 0x4f08, 0x4f1d, 0x4f02, 0x4f05, 0x4f22, 0x4f13, 0x4f04, 0x4ef4, 0x4f12, 0x51b1, 0x5213, 0x5209, 0x5210, 0x52a6, 0x5322, 0x531f, 0x534d, 0x538a, 0x5407, 0x56e1, 0x56df, 0x572e, 0x572a, 0x5734, 0x593c, 0x5980, 0x597c, 0x5985, 0x597b, 0x597e, 0x5977, 0x597f, 0x5b56, 0x5c15, 0x5c25, 0x5c7c, 0x5c7a, 0x5c7b, 0x5c7e, 0x5ddf, 0x5e75, 0x5e84, 0x5f02, 0x5f1a, 0x5f74, 0x5fd5, 0x5fd4, 0x5fcf, 0x625c, 0x625e, 0x6264, 0x6261, 0x6266, 0x6262, 0x6259, 0x6260, 0x625a, 0x6265, 0x65ef, 0x65ee, 0x673e, 0x6739, 0x6738, 0x673b, 0x673a, 0x673f, 0x673c, 0x6733, 0x6c18, 0x6c46, 0x6c52, 0x6c5c, 0x6c4f, 0x6c4a, 0x6c54, 0x6c4b, /* 0xca */ 0x6c4c, 0x7071, 0x725e, 0x72b4, 0x72b5, 0x738e, 0x752a, 0x767f, 0x7a75, 0x7f51, 0x8278, 0x827c, 0x8280, 0x827d, 0x827f, 0x864d, 0x897e, 0x9099, 0x9097, 0x9098, 0x909b, 0x9094, 0x9622, 0x9624, 0x9620, 0x9623, 0x4f56, 0x4f3b, 0x4f62, 0x4f49, 0x4f53, 0x4f64, 0x4f3e, 0x4f67, 0x4f52, 0x4f5f, 0x4f41, 0x4f58, 0x4f2d, 0x4f33, 0x4f3f, 0x4f61, 0x518f, 0x51b9, 0x521c, 0x521e, 0x5221, 0x52ad, 0x52ae, 0x5309, 0x5363, 0x5372, 0x538e, 0x538f, 0x5430, 0x5437, 0x542a, 0x5454, 0x5445, 0x5419, 0x541c, 0x5425, 0x5418, 0x543d, 0x544f, 0x5441, 0x5428, 0x5424, 0x5447, 0x56ee, 0x56e7, 0x56e5, 0x5741, 0x5745, 0x574c, 0x5749, 0x574b, 0x5752, 0x5906, 0x5940, 0x59a6, 0x5998, 0x59a0, 0x5997, 0x598e, 0x59a2, 0x5990, 0x598f, 0x59a7, 0x59a1, 0x5b8e, 0x5b92, 0x5c28, 0x5c2a, 0x5c8d, 0x5c8f, 0x5c88, 0x5c8b, 0x5c89, 0x5c92, 0x5c8a, 0x5c86, 0x5c93, 0x5c95, 0x5de0, 0x5e0a, 0x5e0e, 0x5e8b, 0x5e89, 0x5e8c, 0x5e88, 0x5e8d, 0x5f05, 0x5f1d, 0x5f78, 0x5f76, 0x5fd2, 0x5fd1, 0x5fd0, 0x5fed, 0x5fe8, 0x5fee, 0x5ff3, 0x5fe1, 0x5fe4, 0x5fe3, 0x5ffa, 0x5fef, 0x5ff7, 0x5ffb, 0x6000, 0x5ff4, 0x623a, 0x6283, 0x628c, 0x628e, 0x628f, 0x6294, 0x6287, 0x6271, 0x627b, 0x627a, 0x6270, 0x6281, 0x6288, 0x6277, 0x627d, 0x6272, 0x6274, 0x6537, 0x65f0, 0x65f4, 0x65f3, 0x65f2, 0x65f5, 0x6745, 0x6747, /* 0xcb */ 0x6759, 0x6755, 0x674c, 0x6748, 0x675d, 0x674d, 0x675a, 0x674b, 0x6bd0, 0x6c19, 0x6c1a, 0x6c78, 0x6c67, 0x6c6b, 0x6c84, 0x6c8b, 0x6c8f, 0x6c71, 0x6c6f, 0x6c69, 0x6c9a, 0x6c6d, 0x6c87, 0x6c95, 0x6c9c, 0x6c66, 0x6c73, 0x6c65, 0x6c7b, 0x6c8e, 0x7074, 0x707a, 0x7263, 0x72bf, 0x72bd, 0x72c3, 0x72c6, 0x72c1, 0x72ba, 0x72c5, 0x7395, 0x7397, 0x7393, 0x7394, 0x7392, 0x753a, 0x7539, 0x7594, 0x7595, 0x7681, 0x793d, 0x8034, 0x8095, 0x8099, 0x8090, 0x8092, 0x809c, 0x8290, 0x828f, 0x8285, 0x828e, 0x8291, 0x8293, 0x828a, 0x8283, 0x8284, 0x8c78, 0x8fc9, 0x8fbf, 0x909f, 0x90a1, 0x90a5, 0x909e, 0x90a7, 0x90a0, 0x9630, 0x9628, 0x962f, 0x962d, 0x4e33, 0x4f98, 0x4f7c, 0x4f85, 0x4f7d, 0x4f80, 0x4f87, 0x4f76, 0x4f74, 0x4f89, 0x4f84, 0x4f77, 0x4f4c, 0x4f97, 0x4f6a, 0x4f9a, 0x4f79, 0x4f81, 0x4f78, 0x4f90, 0x4f9c, 0x4f94, 0x4f9e, 0x4f92, 0x4f82, 0x4f95, 0x4f6b, 0x4f6e, 0x519e, 0x51bc, 0x51be, 0x5235, 0x5232, 0x5233, 0x5246, 0x5231, 0x52bc, 0x530a, 0x530b, 0x533c, 0x5392, 0x5394, 0x5487, 0x547f, 0x5481, 0x5491, 0x5482, 0x5488, 0x546b, 0x547a, 0x547e, 0x5465, 0x546c, 0x5474, 0x5466, 0x548d, 0x546f, 0x5461, 0x5460, 0x5498, 0x5463, 0x5467, 0x5464, 0x56f7, 0x56f9, 0x576f, 0x5772, 0x576d, 0x576b, 0x5771, 0x5770, 0x5776, 0x5780, 0x5775, 0x577b, 0x5773, 0x5774, 0x5762, /* 0xcc */ 0x5768, 0x577d, 0x590c, 0x5945, 0x59b5, 0x59ba, 0x59cf, 0x59ce, 0x59b2, 0x59cc, 0x59c1, 0x59b6, 0x59bc, 0x59c3, 0x59d6, 0x59b1, 0x59bd, 0x59c0, 0x59c8, 0x59b4, 0x59c7, 0x5b62, 0x5b65, 0x5b93, 0x5b95, 0x5c44, 0x5c47, 0x5cae, 0x5ca4, 0x5ca0, 0x5cb5, 0x5caf, 0x5ca8, 0x5cac, 0x5c9f, 0x5ca3, 0x5cad, 0x5ca2, 0x5caa, 0x5ca7, 0x5c9d, 0x5ca5, 0x5cb6, 0x5cb0, 0x5ca6, 0x5e17, 0x5e14, 0x5e19, 0x5f28, 0x5f22, 0x5f23, 0x5f24, 0x5f54, 0x5f82, 0x5f7e, 0x5f7d, 0x5fde, 0x5fe5, 0x602d, 0x6026, 0x6019, 0x6032, 0x600b, 0x6034, 0x600a, 0x6017, 0x6033, 0x601a, 0x601e, 0x602c, 0x6022, 0x600d, 0x6010, 0x602e, 0x6013, 0x6011, 0x600c, 0x6009, 0x601c, 0x6214, 0x623d, 0x62ad, 0x62b4, 0x62d1, 0x62be, 0x62aa, 0x62b6, 0x62ca, 0x62ae, 0x62b3, 0x62af, 0x62bb, 0x62a9, 0x62b0, 0x62b8, 0x653d, 0x65a8, 0x65bb, 0x6609, 0x65fc, 0x6604, 0x6612, 0x6608, 0x65fb, 0x6603, 0x660b, 0x660d, 0x6605, 0x65fd, 0x6611, 0x6610, 0x66f6, 0x670a, 0x6785, 0x676c, 0x678e, 0x6792, 0x6776, 0x677b, 0x6798, 0x6786, 0x6784, 0x6774, 0x678d, 0x678c, 0x677a, 0x679f, 0x6791, 0x6799, 0x6783, 0x677d, 0x6781, 0x6778, 0x6779, 0x6794, 0x6b25, 0x6b80, 0x6b7e, 0x6bde, 0x6c1d, 0x6c93, 0x6cec, 0x6ceb, 0x6cee, 0x6cd9, 0x6cb6, 0x6cd4, 0x6cad, 0x6ce7, 0x6cb7, 0x6cd0, 0x6cc2, 0x6cba, 0x6cc3, 0x6cc6, 0x6ced, 0x6cf2, /* 0xcd */ 0x6cd2, 0x6cdd, 0x6cb4, 0x6c8a, 0x6c9d, 0x6c80, 0x6cde, 0x6cc0, 0x6d30, 0x6ccd, 0x6cc7, 0x6cb0, 0x6cf9, 0x6ccf, 0x6ce9, 0x6cd1, 0x7094, 0x7098, 0x7085, 0x7093, 0x7086, 0x7084, 0x7091, 0x7096, 0x7082, 0x709a, 0x7083, 0x726a, 0x72d6, 0x72cb, 0x72d8, 0x72c9, 0x72dc, 0x72d2, 0x72d4, 0x72da, 0x72cc, 0x72d1, 0x73a4, 0x73a1, 0x73ad, 0x73a6, 0x73a2, 0x73a0, 0x73ac, 0x739d, 0x74dd, 0x74e8, 0x753f, 0x7540, 0x753e, 0x758c, 0x7598, 0x76af, 0x76f3, 0x76f1, 0x76f0, 0x76f5, 0x77f8, 0x77fc, 0x77f9, 0x77fb, 0x77fa, 0x77f7, 0x7942, 0x793f, 0x79c5, 0x7a78, 0x7a7b, 0x7afb, 0x7c75, 0x7cfd, 0x8035, 0x808f, 0x80ae, 0x80a3, 0x80b8, 0x80b5, 0x80ad, 0x8220, 0x82a0, 0x82c0, 0x82ab, 0x829a, 0x8298, 0x829b, 0x82b5, 0x82a7, 0x82ae, 0x82bc, 0x829e, 0x82ba, 0x82b4, 0x82a8, 0x82a1, 0x82a9, 0x82c2, 0x82a4, 0x82c3, 0x82b6, 0x82a2, 0x8670, 0x866f, 0x866d, 0x866e, 0x8c56, 0x8fd2, 0x8fcb, 0x8fd3, 0x8fcd, 0x8fd6, 0x8fd5, 0x8fd7, 0x90b2, 0x90b4, 0x90af, 0x90b3, 0x90b0, 0x9639, 0x963d, 0x963c, 0x963a, 0x9643, 0x4fcd, 0x4fc5, 0x4fd3, 0x4fb2, 0x4fc9, 0x4fcb, 0x4fc1, 0x4fd4, 0x4fdc, 0x4fd9, 0x4fbb, 0x4fb3, 0x4fdb, 0x4fc7, 0x4fd6, 0x4fba, 0x4fc0, 0x4fb9, 0x4fec, 0x5244, 0x5249, 0x52c0, 0x52c2, 0x533d, 0x537c, 0x5397, 0x5396, 0x5399, 0x5398, 0x54ba, 0x54a1, 0x54ad, 0x54a5, 0x54cf, /* 0xce */ 0x54c3, 0x830d, 0x54b7, 0x54ae, 0x54d6, 0x54b6, 0x54c5, 0x54c6, 0x54a0, 0x5470, 0x54bc, 0x54a2, 0x54be, 0x5472, 0x54de, 0x54b0, 0x57b5, 0x579e, 0x579f, 0x57a4, 0x578c, 0x5797, 0x579d, 0x579b, 0x5794, 0x5798, 0x578f, 0x5799, 0x57a5, 0x579a, 0x5795, 0x58f4, 0x590d, 0x5953, 0x59e1, 0x59de, 0x59ee, 0x5a00, 0x59f1, 0x59dd, 0x59fa, 0x59fd, 0x59fc, 0x59f6, 0x59e4, 0x59f2, 0x59f7, 0x59db, 0x59e9, 0x59f3, 0x59f5, 0x59e0, 0x59fe, 0x59f4, 0x59ed, 0x5ba8, 0x5c4c, 0x5cd0, 0x5cd8, 0x5ccc, 0x5cd7, 0x5ccb, 0x5cdb, 0x5cde, 0x5cda, 0x5cc9, 0x5cc7, 0x5cca, 0x5cd6, 0x5cd3, 0x5cd4, 0x5ccf, 0x5cc8, 0x5cc6, 0x5cce, 0x5cdf, 0x5cf8, 0x5df9, 0x5e21, 0x5e22, 0x5e23, 0x5e20, 0x5e24, 0x5eb0, 0x5ea4, 0x5ea2, 0x5e9b, 0x5ea3, 0x5ea5, 0x5f07, 0x5f2e, 0x5f56, 0x5f86, 0x6037, 0x6039, 0x6054, 0x6072, 0x605e, 0x6045, 0x6053, 0x6047, 0x6049, 0x605b, 0x604c, 0x6040, 0x6042, 0x605f, 0x6024, 0x6044, 0x6058, 0x6066, 0x606e, 0x6242, 0x6243, 0x62cf, 0x630d, 0x630b, 0x62f5, 0x630e, 0x6303, 0x62eb, 0x62f9, 0x630f, 0x630c, 0x62f8, 0x62f6, 0x6300, 0x6313, 0x6314, 0x62fa, 0x6315, 0x62fb, 0x62f0, 0x6541, 0x6543, 0x65aa, 0x65bf, 0x6636, 0x6621, 0x6632, 0x6635, 0x661c, 0x6626, 0x6622, 0x6633, 0x662b, 0x663a, 0x661d, 0x6634, 0x6639, 0x662e, 0x670f, 0x6710, 0x67c1, 0x67f2, 0x67c8, 0x67ba, /* 0xcf */ 0x67dc, 0x67bb, 0x67f8, 0x67d8, 0x67c0, 0x67b7, 0x67c5, 0x67eb, 0x67e4, 0x67df, 0x67b5, 0x67cd, 0x67b3, 0x67f7, 0x67f6, 0x67ee, 0x67e3, 0x67c2, 0x67b9, 0x67ce, 0x67e7, 0x67f0, 0x67b2, 0x67fc, 0x67c6, 0x67ed, 0x67cc, 0x67ae, 0x67e6, 0x67db, 0x67fa, 0x67c9, 0x67ca, 0x67c3, 0x67ea, 0x67cb, 0x6b28, 0x6b82, 0x6b84, 0x6bb6, 0x6bd6, 0x6bd8, 0x6be0, 0x6c20, 0x6c21, 0x6d28, 0x6d34, 0x6d2d, 0x6d1f, 0x6d3c, 0x6d3f, 0x6d12, 0x6d0a, 0x6cda, 0x6d33, 0x6d04, 0x6d19, 0x6d3a, 0x6d1a, 0x6d11, 0x6d00, 0x6d1d, 0x6d42, 0x6d01, 0x6d18, 0x6d37, 0x6d03, 0x6d0f, 0x6d40, 0x6d07, 0x6d20, 0x6d2c, 0x6d08, 0x6d22, 0x6d09, 0x6d10, 0x70b7, 0x709f, 0x70be, 0x70b1, 0x70b0, 0x70a1, 0x70b4, 0x70b5, 0x70a9, 0x7241, 0x7249, 0x724a, 0x726c, 0x7270, 0x7273, 0x726e, 0x72ca, 0x72e4, 0x72e8, 0x72eb, 0x72df, 0x72ea, 0x72e6, 0x72e3, 0x7385, 0x73cc, 0x73c2, 0x73c8, 0x73c5, 0x73b9, 0x73b6, 0x73b5, 0x73b4, 0x73eb, 0x73bf, 0x73c7, 0x73be, 0x73c3, 0x73c6, 0x73b8, 0x73cb, 0x74ec, 0x74ee, 0x752e, 0x7547, 0x7548, 0x75a7, 0x75aa, 0x7679, 0x76c4, 0x7708, 0x7703, 0x7704, 0x7705, 0x770a, 0x76f7, 0x76fb, 0x76fa, 0x77e7, 0x77e8, 0x7806, 0x7811, 0x7812, 0x7805, 0x7810, 0x780f, 0x780e, 0x7809, 0x7803, 0x7813, 0x794a, 0x794c, 0x794b, 0x7945, 0x7944, 0x79d5, 0x79cd, 0x79cf, 0x79d6, 0x79ce, 0x7a80, /* 0xd0 */ 0x7a7e, 0x7ad1, 0x7b00, 0x7b01, 0x7c7a, 0x7c78, 0x7c79, 0x7c7f, 0x7c80, 0x7c81, 0x7d03, 0x7d08, 0x7d01, 0x7f58, 0x7f91, 0x7f8d, 0x7fbe, 0x8007, 0x800e, 0x800f, 0x8014, 0x8037, 0x80d8, 0x80c7, 0x80e0, 0x80d1, 0x80c8, 0x80c2, 0x80d0, 0x80c5, 0x80e3, 0x80d9, 0x80dc, 0x80ca, 0x80d5, 0x80c9, 0x80cf, 0x80d7, 0x80e6, 0x80cd, 0x81ff, 0x8221, 0x8294, 0x82d9, 0x82fe, 0x82f9, 0x8307, 0x82e8, 0x8300, 0x82d5, 0x833a, 0x82eb, 0x82d6, 0x82f4, 0x82ec, 0x82e1, 0x82f2, 0x82f5, 0x830c, 0x82fb, 0x82f6, 0x82f0, 0x82ea, 0x82e4, 0x82e0, 0x82fa, 0x82f3, 0x82ed, 0x8677, 0x8674, 0x867c, 0x8673, 0x8841, 0x884e, 0x8867, 0x886a, 0x8869, 0x89d3, 0x8a04, 0x8a07, 0x8d72, 0x8fe3, 0x8fe1, 0x8fee, 0x8fe0, 0x90f1, 0x90bd, 0x90bf, 0x90d5, 0x90c5, 0x90be, 0x90c7, 0x90cb, 0x90c8, 0x91d4, 0x91d3, 0x9654, 0x964f, 0x9651, 0x9653, 0x964a, 0x964e, 0x501e, 0x5005, 0x5007, 0x5013, 0x5022, 0x5030, 0x501b, 0x4ff5, 0x4ff4, 0x5033, 0x5037, 0x502c, 0x4ff6, 0x4ff7, 0x5017, 0x501c, 0x5020, 0x5027, 0x5035, 0x502f, 0x5031, 0x500e, 0x515a, 0x5194, 0x5193, 0x51ca, 0x51c4, 0x51c5, 0x51c8, 0x51ce, 0x5261, 0x525a, 0x5252, 0x525e, 0x525f, 0x5255, 0x5262, 0x52cd, 0x530e, 0x539e, 0x5526, 0x54e2, 0x5517, 0x5512, 0x54e7, 0x54f3, 0x54e4, 0x551a, 0x54ff, 0x5504, 0x5508, 0x54eb, 0x5511, 0x5505, 0x54f1, /* 0xd1 */ 0x550a, 0x54fb, 0x54f7, 0x54f8, 0x54e0, 0x550e, 0x5503, 0x550b, 0x5701, 0x5702, 0x57cc, 0x5832, 0x57d5, 0x57d2, 0x57ba, 0x57c6, 0x57bd, 0x57bc, 0x57b8, 0x57b6, 0x57bf, 0x57c7, 0x57d0, 0x57b9, 0x57c1, 0x590e, 0x594a, 0x5a19, 0x5a16, 0x5a2d, 0x5a2e, 0x5a15, 0x5a0f, 0x5a17, 0x5a0a, 0x5a1e, 0x5a33, 0x5b6c, 0x5ba7, 0x5bad, 0x5bac, 0x5c03, 0x5c56, 0x5c54, 0x5cec, 0x5cff, 0x5cee, 0x5cf1, 0x5cf7, 0x5d00, 0x5cf9, 0x5e29, 0x5e28, 0x5ea8, 0x5eae, 0x5eaa, 0x5eac, 0x5f33, 0x5f30, 0x5f67, 0x605d, 0x605a, 0x6067, 0x6041, 0x60a2, 0x6088, 0x6080, 0x6092, 0x6081, 0x609d, 0x6083, 0x6095, 0x609b, 0x6097, 0x6087, 0x609c, 0x608e, 0x6219, 0x6246, 0x62f2, 0x6310, 0x6356, 0x632c, 0x6344, 0x6345, 0x6336, 0x6343, 0x63e4, 0x6339, 0x634b, 0x634a, 0x633c, 0x6329, 0x6341, 0x6334, 0x6358, 0x6354, 0x6359, 0x632d, 0x6347, 0x6333, 0x635a, 0x6351, 0x6338, 0x6357, 0x6340, 0x6348, 0x654a, 0x6546, 0x65c6, 0x65c3, 0x65c4, 0x65c2, 0x664a, 0x665f, 0x6647, 0x6651, 0x6712, 0x6713, 0x681f, 0x681a, 0x6849, 0x6832, 0x6833, 0x683b, 0x684b, 0x684f, 0x6816, 0x6831, 0x681c, 0x6835, 0x682b, 0x682d, 0x682f, 0x684e, 0x6844, 0x6834, 0x681d, 0x6812, 0x6814, 0x6826, 0x6828, 0x682e, 0x684d, 0x683a, 0x6825, 0x6820, 0x6b2c, 0x6b2f, 0x6b2d, 0x6b31, 0x6b34, 0x6b6d, 0x8082, 0x6b88, 0x6be6, 0x6be4, /* 0xd2 */ 0x6be8, 0x6be3, 0x6be2, 0x6be7, 0x6c25, 0x6d7a, 0x6d63, 0x6d64, 0x6d76, 0x6d0d, 0x6d61, 0x6d92, 0x6d58, 0x6d62, 0x6d6d, 0x6d6f, 0x6d91, 0x6d8d, 0x6def, 0x6d7f, 0x6d86, 0x6d5e, 0x6d67, 0x6d60, 0x6d97, 0x6d70, 0x6d7c, 0x6d5f, 0x6d82, 0x6d98, 0x6d2f, 0x6d68, 0x6d8b, 0x6d7e, 0x6d80, 0x6d84, 0x6d16, 0x6d83, 0x6d7b, 0x6d7d, 0x6d75, 0x6d90, 0x70dc, 0x70d3, 0x70d1, 0x70dd, 0x70cb, 0x7f39, 0x70e2, 0x70d7, 0x70d2, 0x70de, 0x70e0, 0x70d4, 0x70cd, 0x70c5, 0x70c6, 0x70c7, 0x70da, 0x70ce, 0x70e1, 0x7242, 0x7278, 0x7277, 0x7276, 0x7300, 0x72fa, 0x72f4, 0x72fe, 0x72f6, 0x72f3, 0x72fb, 0x7301, 0x73d3, 0x73d9, 0x73e5, 0x73d6, 0x73bc, 0x73e7, 0x73e3, 0x73e9, 0x73dc, 0x73d2, 0x73db, 0x73d4, 0x73dd, 0x73da, 0x73d7, 0x73d8, 0x73e8, 0x74de, 0x74df, 0x74f4, 0x74f5, 0x7521, 0x755b, 0x755f, 0x75b0, 0x75c1, 0x75bb, 0x75c4, 0x75c0, 0x75bf, 0x75b6, 0x75ba, 0x768a, 0x76c9, 0x771d, 0x771b, 0x7710, 0x7713, 0x7712, 0x7723, 0x7711, 0x7715, 0x7719, 0x771a, 0x7722, 0x7727, 0x7823, 0x782c, 0x7822, 0x7835, 0x782f, 0x7828, 0x782e, 0x782b, 0x7821, 0x7829, 0x7833, 0x782a, 0x7831, 0x7954, 0x795b, 0x794f, 0x795c, 0x7953, 0x7952, 0x7951, 0x79eb, 0x79ec, 0x79e0, 0x79ee, 0x79ed, 0x79ea, 0x79dc, 0x79de, 0x79dd, 0x7a86, 0x7a89, 0x7a85, 0x7a8b, 0x7a8c, 0x7a8a, 0x7a87, 0x7ad8, 0x7b10, /* 0xd3 */ 0x7b04, 0x7b13, 0x7b05, 0x7b0f, 0x7b08, 0x7b0a, 0x7b0e, 0x7b09, 0x7b12, 0x7c84, 0x7c91, 0x7c8a, 0x7c8c, 0x7c88, 0x7c8d, 0x7c85, 0x7d1e, 0x7d1d, 0x7d11, 0x7d0e, 0x7d18, 0x7d16, 0x7d13, 0x7d1f, 0x7d12, 0x7d0f, 0x7d0c, 0x7f5c, 0x7f61, 0x7f5e, 0x7f60, 0x7f5d, 0x7f5b, 0x7f96, 0x7f92, 0x7fc3, 0x7fc2, 0x7fc0, 0x8016, 0x803e, 0x8039, 0x80fa, 0x80f2, 0x80f9, 0x80f5, 0x8101, 0x80fb, 0x8100, 0x8201, 0x822f, 0x8225, 0x8333, 0x832d, 0x8344, 0x8319, 0x8351, 0x8325, 0x8356, 0x833f, 0x8341, 0x8326, 0x831c, 0x8322, 0x8342, 0x834e, 0x831b, 0x832a, 0x8308, 0x833c, 0x834d, 0x8316, 0x8324, 0x8320, 0x8337, 0x832f, 0x8329, 0x8347, 0x8345, 0x834c, 0x8353, 0x831e, 0x832c, 0x834b, 0x8327, 0x8348, 0x8653, 0x8652, 0x86a2, 0x86a8, 0x8696, 0x868d, 0x8691, 0x869e, 0x8687, 0x8697, 0x8686, 0x868b, 0x869a, 0x8685, 0x86a5, 0x8699, 0x86a1, 0x86a7, 0x8695, 0x8698, 0x868e, 0x869d, 0x8690, 0x8694, 0x8843, 0x8844, 0x886d, 0x8875, 0x8876, 0x8872, 0x8880, 0x8871, 0x887f, 0x886f, 0x8883, 0x887e, 0x8874, 0x887c, 0x8a12, 0x8c47, 0x8c57, 0x8c7b, 0x8ca4, 0x8ca3, 0x8d76, 0x8d78, 0x8db5, 0x8db7, 0x8db6, 0x8ed1, 0x8ed3, 0x8ffe, 0x8ff5, 0x9002, 0x8fff, 0x8ffb, 0x9004, 0x8ffc, 0x8ff6, 0x90d6, 0x90e0, 0x90d9, 0x90da, 0x90e3, 0x90df, 0x90e5, 0x90d8, 0x90db, 0x90d7, 0x90dc, 0x90e4, 0x9150, /* 0xd4 */ 0x914e, 0x914f, 0x91d5, 0x91e2, 0x91da, 0x965c, 0x965f, 0x96bc, 0x98e3, 0x9adf, 0x9b2f, 0x4e7f, 0x5070, 0x506a, 0x5061, 0x505e, 0x5060, 0x5053, 0x504b, 0x505d, 0x5072, 0x5048, 0x504d, 0x5041, 0x505b, 0x504a, 0x5062, 0x5015, 0x5045, 0x505f, 0x5069, 0x506b, 0x5063, 0x5064, 0x5046, 0x5040, 0x506e, 0x5073, 0x5057, 0x5051, 0x51d0, 0x526b, 0x526d, 0x526c, 0x526e, 0x52d6, 0x52d3, 0x532d, 0x539c, 0x5575, 0x5576, 0x553c, 0x554d, 0x5550, 0x5534, 0x552a, 0x5551, 0x5562, 0x5536, 0x5535, 0x5530, 0x5552, 0x5545, 0x550c, 0x5532, 0x5565, 0x554e, 0x5539, 0x5548, 0x552d, 0x553b, 0x5540, 0x554b, 0x570a, 0x5707, 0x57fb, 0x5814, 0x57e2, 0x57f6, 0x57dc, 0x57f4, 0x5800, 0x57ed, 0x57fd, 0x5808, 0x57f8, 0x580b, 0x57f3, 0x57cf, 0x5807, 0x57ee, 0x57e3, 0x57f2, 0x57e5, 0x57ec, 0x57e1, 0x580e, 0x57fc, 0x5810, 0x57e7, 0x5801, 0x580c, 0x57f1, 0x57e9, 0x57f0, 0x580d, 0x5804, 0x595c, 0x5a60, 0x5a58, 0x5a55, 0x5a67, 0x5a5e, 0x5a38, 0x5a35, 0x5a6d, 0x5a50, 0x5a5f, 0x5a65, 0x5a6c, 0x5a53, 0x5a64, 0x5a57, 0x5a43, 0x5a5d, 0x5a52, 0x5a44, 0x5a5b, 0x5a48, 0x5a8e, 0x5a3e, 0x5a4d, 0x5a39, 0x5a4c, 0x5a70, 0x5a69, 0x5a47, 0x5a51, 0x5a56, 0x5a42, 0x5a5c, 0x5b72, 0x5b6e, 0x5bc1, 0x5bc0, 0x5c59, 0x5d1e, 0x5d0b, 0x5d1d, 0x5d1a, 0x5d20, 0x5d0c, 0x5d28, 0x5d0d, 0x5d26, 0x5d25, 0x5d0f, /* 0xd5 */ 0x5d30, 0x5d12, 0x5d23, 0x5d1f, 0x5d2e, 0x5e3e, 0x5e34, 0x5eb1, 0x5eb4, 0x5eb9, 0x5eb2, 0x5eb3, 0x5f36, 0x5f38, 0x5f9b, 0x5f96, 0x5f9f, 0x608a, 0x6090, 0x6086, 0x60be, 0x60b0, 0x60ba, 0x60d3, 0x60d4, 0x60cf, 0x60e4, 0x60d9, 0x60dd, 0x60c8, 0x60b1, 0x60db, 0x60b7, 0x60ca, 0x60bf, 0x60c3, 0x60cd, 0x60c0, 0x6332, 0x6365, 0x638a, 0x6382, 0x637d, 0x63bd, 0x639e, 0x63ad, 0x639d, 0x6397, 0x63ab, 0x638e, 0x636f, 0x6387, 0x6390, 0x636e, 0x63af, 0x6375, 0x639c, 0x636d, 0x63ae, 0x637c, 0x63a4, 0x633b, 0x639f, 0x6378, 0x6385, 0x6381, 0x6391, 0x638d, 0x6370, 0x6553, 0x65cd, 0x6665, 0x6661, 0x665b, 0x6659, 0x665c, 0x6662, 0x6718, 0x6879, 0x6887, 0x6890, 0x689c, 0x686d, 0x686e, 0x68ae, 0x68ab, 0x6956, 0x686f, 0x68a3, 0x68ac, 0x68a9, 0x6875, 0x6874, 0x68b2, 0x688f, 0x6877, 0x6892, 0x687c, 0x686b, 0x6872, 0x68aa, 0x6880, 0x6871, 0x687e, 0x689b, 0x6896, 0x688b, 0x68a0, 0x6889, 0x68a4, 0x6878, 0x687b, 0x6891, 0x688c, 0x688a, 0x687d, 0x6b36, 0x6b33, 0x6b37, 0x6b38, 0x6b91, 0x6b8f, 0x6b8d, 0x6b8e, 0x6b8c, 0x6c2a, 0x6dc0, 0x6dab, 0x6db4, 0x6db3, 0x6e74, 0x6dac, 0x6de9, 0x6de2, 0x6db7, 0x6df6, 0x6dd4, 0x6e00, 0x6dc8, 0x6de0, 0x6ddf, 0x6dd6, 0x6dbe, 0x6de5, 0x6ddc, 0x6ddd, 0x6ddb, 0x6df4, 0x6dca, 0x6dbd, 0x6ded, 0x6df0, 0x6dba, 0x6dd5, 0x6dc2, 0x6dcf, 0x6dc9, /* 0xd6 */ 0x6dd0, 0x6df2, 0x6dd3, 0x6dfd, 0x6dd7, 0x6dcd, 0x6de3, 0x6dbb, 0x70fa, 0x710d, 0x70f7, 0x7117, 0x70f4, 0x710c, 0x70f0, 0x7104, 0x70f3, 0x7110, 0x70fc, 0x70ff, 0x7106, 0x7113, 0x7100, 0x70f8, 0x70f6, 0x710b, 0x7102, 0x710e, 0x727e, 0x727b, 0x727c, 0x727f, 0x731d, 0x7317, 0x7307, 0x7311, 0x7318, 0x730a, 0x7308, 0x72ff, 0x730f, 0x731e, 0x7388, 0x73f6, 0x73f8, 0x73f5, 0x7404, 0x7401, 0x73fd, 0x7407, 0x7400, 0x73fa, 0x73fc, 0x73ff, 0x740c, 0x740b, 0x73f4, 0x7408, 0x7564, 0x7563, 0x75ce, 0x75d2, 0x75cf, 0x75cb, 0x75cc, 0x75d1, 0x75d0, 0x768f, 0x7689, 0x76d3, 0x7739, 0x772f, 0x772d, 0x7731, 0x7732, 0x7734, 0x7733, 0x773d, 0x7725, 0x773b, 0x7735, 0x7848, 0x7852, 0x7849, 0x784d, 0x784a, 0x784c, 0x7826, 0x7845, 0x7850, 0x7964, 0x7967, 0x7969, 0x796a, 0x7963, 0x796b, 0x7961, 0x79bb, 0x79fa, 0x79f8, 0x79f6, 0x79f7, 0x7a8f, 0x7a94, 0x7a90, 0x7b35, 0x7b47, 0x7b34, 0x7b25, 0x7b30, 0x7b22, 0x7b24, 0x7b33, 0x7b18, 0x7b2a, 0x7b1d, 0x7b31, 0x7b2b, 0x7b2d, 0x7b2f, 0x7b32, 0x7b38, 0x7b1a, 0x7b23, 0x7c94, 0x7c98, 0x7c96, 0x7ca3, 0x7d35, 0x7d3d, 0x7d38, 0x7d36, 0x7d3a, 0x7d45, 0x7d2c, 0x7d29, 0x7d41, 0x7d47, 0x7d3e, 0x7d3f, 0x7d4a, 0x7d3b, 0x7d28, 0x7f63, 0x7f95, 0x7f9c, 0x7f9d, 0x7f9b, 0x7fca, 0x7fcb, 0x7fcd, 0x7fd0, 0x7fd1, 0x7fc7, 0x7fcf, 0x7fc9, 0x801f, /* 0xd7 */ 0x801e, 0x801b, 0x8047, 0x8043, 0x8048, 0x8118, 0x8125, 0x8119, 0x811b, 0x812d, 0x811f, 0x812c, 0x811e, 0x8121, 0x8115, 0x8127, 0x811d, 0x8122, 0x8211, 0x8238, 0x8233, 0x823a, 0x8234, 0x8232, 0x8274, 0x8390, 0x83a3, 0x83a8, 0x838d, 0x837a, 0x8373, 0x83a4, 0x8374, 0x838f, 0x8381, 0x8395, 0x8399, 0x8375, 0x8394, 0x83a9, 0x837d, 0x8383, 0x838c, 0x839d, 0x839b, 0x83aa, 0x838b, 0x837e, 0x83a5, 0x83af, 0x8388, 0x8397, 0x83b0, 0x837f, 0x83a6, 0x8387, 0x83ae, 0x8376, 0x839a, 0x8659, 0x8656, 0x86bf, 0x86b7, 0x86c2, 0x86c1, 0x86c5, 0x86ba, 0x86b0, 0x86c8, 0x86b9, 0x86b3, 0x86b8, 0x86cc, 0x86b4, 0x86bb, 0x86bc, 0x86c3, 0x86bd, 0x86be, 0x8852, 0x8889, 0x8895, 0x88a8, 0x88a2, 0x88aa, 0x889a, 0x8891, 0x88a1, 0x889f, 0x8898, 0x88a7, 0x8899, 0x889b, 0x8897, 0x88a4, 0x88ac, 0x888c, 0x8893, 0x888e, 0x8982, 0x89d6, 0x89d9, 0x89d5, 0x8a30, 0x8a27, 0x8a2c, 0x8a1e, 0x8c39, 0x8c3b, 0x8c5c, 0x8c5d, 0x8c7d, 0x8ca5, 0x8d7d, 0x8d7b, 0x8d79, 0x8dbc, 0x8dc2, 0x8db9, 0x8dbf, 0x8dc1, 0x8ed8, 0x8ede, 0x8edd, 0x8edc, 0x8ed7, 0x8ee0, 0x8ee1, 0x9024, 0x900b, 0x9011, 0x901c, 0x900c, 0x9021, 0x90ef, 0x90ea, 0x90f0, 0x90f4, 0x90f2, 0x90f3, 0x90d4, 0x90eb, 0x90ec, 0x90e9, 0x9156, 0x9158, 0x915a, 0x9153, 0x9155, 0x91ec, 0x91f4, 0x91f1, 0x91f3, 0x91f8, 0x91e4, 0x91f9, 0x91ea, /* 0xd8 */ 0x91eb, 0x91f7, 0x91e8, 0x91ee, 0x957a, 0x9586, 0x9588, 0x967c, 0x966d, 0x966b, 0x9671, 0x966f, 0x96bf, 0x976a, 0x9804, 0x98e5, 0x9997, 0x509b, 0x5095, 0x5094, 0x509e, 0x508b, 0x50a3, 0x5083, 0x508c, 0x508e, 0x509d, 0x5068, 0x509c, 0x5092, 0x5082, 0x5087, 0x515f, 0x51d4, 0x5312, 0x5311, 0x53a4, 0x53a7, 0x5591, 0x55a8, 0x55a5, 0x55ad, 0x5577, 0x5645, 0x55a2, 0x5593, 0x5588, 0x558f, 0x55b5, 0x5581, 0x55a3, 0x5592, 0x55a4, 0x557d, 0x558c, 0x55a6, 0x557f, 0x5595, 0x55a1, 0x558e, 0x570c, 0x5829, 0x5837, 0x5819, 0x581e, 0x5827, 0x5823, 0x5828, 0x57f5, 0x5848, 0x5825, 0x581c, 0x581b, 0x5833, 0x583f, 0x5836, 0x582e, 0x5839, 0x5838, 0x582d, 0x582c, 0x583b, 0x5961, 0x5aaf, 0x5a94, 0x5a9f, 0x5a7a, 0x5aa2, 0x5a9e, 0x5a78, 0x5aa6, 0x5a7c, 0x5aa5, 0x5aac, 0x5a95, 0x5aae, 0x5a37, 0x5a84, 0x5a8a, 0x5a97, 0x5a83, 0x5a8b, 0x5aa9, 0x5a7b, 0x5a7d, 0x5a8c, 0x5a9c, 0x5a8f, 0x5a93, 0x5a9d, 0x5bea, 0x5bcd, 0x5bcb, 0x5bd4, 0x5bd1, 0x5bca, 0x5bce, 0x5c0c, 0x5c30, 0x5d37, 0x5d43, 0x5d6b, 0x5d41, 0x5d4b, 0x5d3f, 0x5d35, 0x5d51, 0x5d4e, 0x5d55, 0x5d33, 0x5d3a, 0x5d52, 0x5d3d, 0x5d31, 0x5d59, 0x5d42, 0x5d39, 0x5d49, 0x5d38, 0x5d3c, 0x5d32, 0x5d36, 0x5d40, 0x5d45, 0x5e44, 0x5e41, 0x5f58, 0x5fa6, 0x5fa5, 0x5fab, 0x60c9, 0x60b9, 0x60cc, 0x60e2, 0x60ce, 0x60c4, 0x6114, /* 0xd9 */ 0x60f2, 0x610a, 0x6116, 0x6105, 0x60f5, 0x6113, 0x60f8, 0x60fc, 0x60fe, 0x60c1, 0x6103, 0x6118, 0x611d, 0x6110, 0x60ff, 0x6104, 0x610b, 0x624a, 0x6394, 0x63b1, 0x63b0, 0x63ce, 0x63e5, 0x63e8, 0x63ef, 0x63c3, 0x649d, 0x63f3, 0x63ca, 0x63e0, 0x63f6, 0x63d5, 0x63f2, 0x63f5, 0x6461, 0x63df, 0x63be, 0x63dd, 0x63dc, 0x63c4, 0x63d8, 0x63d3, 0x63c2, 0x63c7, 0x63cc, 0x63cb, 0x63c8, 0x63f0, 0x63d7, 0x63d9, 0x6532, 0x6567, 0x656a, 0x6564, 0x655c, 0x6568, 0x6565, 0x658c, 0x659d, 0x659e, 0x65ae, 0x65d0, 0x65d2, 0x667c, 0x666c, 0x667b, 0x6680, 0x6671, 0x6679, 0x666a, 0x6672, 0x6701, 0x690c, 0x68d3, 0x6904, 0x68dc, 0x692a, 0x68ec, 0x68ea, 0x68f1, 0x690f, 0x68d6, 0x68f7, 0x68eb, 0x68e4, 0x68f6, 0x6913, 0x6910, 0x68f3, 0x68e1, 0x6907, 0x68cc, 0x6908, 0x6970, 0x68b4, 0x6911, 0x68ef, 0x68c6, 0x6914, 0x68f8, 0x68d0, 0x68fd, 0x68fc, 0x68e8, 0x690b, 0x690a, 0x6917, 0x68ce, 0x68c8, 0x68dd, 0x68de, 0x68e6, 0x68f4, 0x68d1, 0x6906, 0x68d4, 0x68e9, 0x6915, 0x6925, 0x68c7, 0x6b39, 0x6b3b, 0x6b3f, 0x6b3c, 0x6b94, 0x6b97, 0x6b99, 0x6b95, 0x6bbd, 0x6bf0, 0x6bf2, 0x6bf3, 0x6c30, 0x6dfc, 0x6e46, 0x6e47, 0x6e1f, 0x6e49, 0x6e88, 0x6e3c, 0x6e3d, 0x6e45, 0x6e62, 0x6e2b, 0x6e3f, 0x6e41, 0x6e5d, 0x6e73, 0x6e1c, 0x6e33, 0x6e4b, 0x6e40, 0x6e51, 0x6e3b, 0x6e03, 0x6e2e, 0x6e5e, /* 0xda */ 0x6e68, 0x6e5c, 0x6e61, 0x6e31, 0x6e28, 0x6e60, 0x6e71, 0x6e6b, 0x6e39, 0x6e22, 0x6e30, 0x6e53, 0x6e65, 0x6e27, 0x6e78, 0x6e64, 0x6e77, 0x6e55, 0x6e79, 0x6e52, 0x6e66, 0x6e35, 0x6e36, 0x6e5a, 0x7120, 0x711e, 0x712f, 0x70fb, 0x712e, 0x7131, 0x7123, 0x7125, 0x7122, 0x7132, 0x711f, 0x7128, 0x713a, 0x711b, 0x724b, 0x725a, 0x7288, 0x7289, 0x7286, 0x7285, 0x728b, 0x7312, 0x730b, 0x7330, 0x7322, 0x7331, 0x7333, 0x7327, 0x7332, 0x732d, 0x7326, 0x7323, 0x7335, 0x730c, 0x742e, 0x742c, 0x7430, 0x742b, 0x7416, 0x741a, 0x7421, 0x742d, 0x7431, 0x7424, 0x7423, 0x741d, 0x7429, 0x7420, 0x7432, 0x74fb, 0x752f, 0x756f, 0x756c, 0x75e7, 0x75da, 0x75e1, 0x75e6, 0x75dd, 0x75df, 0x75e4, 0x75d7, 0x7695, 0x7692, 0x76da, 0x7746, 0x7747, 0x7744, 0x774d, 0x7745, 0x774a, 0x774e, 0x774b, 0x774c, 0x77de, 0x77ec, 0x7860, 0x7864, 0x7865, 0x785c, 0x786d, 0x7871, 0x786a, 0x786e, 0x7870, 0x7869, 0x7868, 0x785e, 0x7862, 0x7974, 0x7973, 0x7972, 0x7970, 0x7a02, 0x7a0a, 0x7a03, 0x7a0c, 0x7a04, 0x7a99, 0x7ae6, 0x7ae4, 0x7b4a, 0x7b3b, 0x7b44, 0x7b48, 0x7b4c, 0x7b4e, 0x7b40, 0x7b58, 0x7b45, 0x7ca2, 0x7c9e, 0x7ca8, 0x7ca1, 0x7d58, 0x7d6f, 0x7d63, 0x7d53, 0x7d56, 0x7d67, 0x7d6a, 0x7d4f, 0x7d6d, 0x7d5c, 0x7d6b, 0x7d52, 0x7d54, 0x7d69, 0x7d51, 0x7d5f, 0x7d4e, 0x7f3e, 0x7f3f, 0x7f65, /* 0xdb */ 0x7f66, 0x7fa2, 0x7fa0, 0x7fa1, 0x7fd7, 0x8051, 0x804f, 0x8050, 0x80fe, 0x80d4, 0x8143, 0x814a, 0x8152, 0x814f, 0x8147, 0x813d, 0x814d, 0x813a, 0x81e6, 0x81ee, 0x81f7, 0x81f8, 0x81f9, 0x8204, 0x823c, 0x823d, 0x823f, 0x8275, 0x833b, 0x83cf, 0x83f9, 0x8423, 0x83c0, 0x83e8, 0x8412, 0x83e7, 0x83e4, 0x83fc, 0x83f6, 0x8410, 0x83c6, 0x83c8, 0x83eb, 0x83e3, 0x83bf, 0x8401, 0x83dd, 0x83e5, 0x83d8, 0x83ff, 0x83e1, 0x83cb, 0x83ce, 0x83d6, 0x83f5, 0x83c9, 0x8409, 0x840f, 0x83de, 0x8411, 0x8406, 0x83c2, 0x83f3, 0x83d5, 0x83fa, 0x83c7, 0x83d1, 0x83ea, 0x8413, 0x83c3, 0x83ec, 0x83ee, 0x83c4, 0x83fb, 0x83d7, 0x83e2, 0x841b, 0x83db, 0x83fe, 0x86d8, 0x86e2, 0x86e6, 0x86d3, 0x86e3, 0x86da, 0x86ea, 0x86dd, 0x86eb, 0x86dc, 0x86ec, 0x86e9, 0x86d7, 0x86e8, 0x86d1, 0x8848, 0x8856, 0x8855, 0x88ba, 0x88d7, 0x88b9, 0x88b8, 0x88c0, 0x88be, 0x88b6, 0x88bc, 0x88b7, 0x88bd, 0x88b2, 0x8901, 0x88c9, 0x8995, 0x8998, 0x8997, 0x89dd, 0x89da, 0x89db, 0x8a4e, 0x8a4d, 0x8a39, 0x8a59, 0x8a40, 0x8a57, 0x8a58, 0x8a44, 0x8a45, 0x8a52, 0x8a48, 0x8a51, 0x8a4a, 0x8a4c, 0x8a4f, 0x8c5f, 0x8c81, 0x8c80, 0x8cba, 0x8cbe, 0x8cb0, 0x8cb9, 0x8cb5, 0x8d84, 0x8d80, 0x8d89, 0x8dd8, 0x8dd3, 0x8dcd, 0x8dc7, 0x8dd6, 0x8ddc, 0x8dcf, 0x8dd5, 0x8dd9, 0x8dc8, 0x8dd7, 0x8dc5, 0x8eef, 0x8ef7, 0x8efa, /* 0xdc */ 0x8ef9, 0x8ee6, 0x8eee, 0x8ee5, 0x8ef5, 0x8ee7, 0x8ee8, 0x8ef6, 0x8eeb, 0x8ef1, 0x8eec, 0x8ef4, 0x8ee9, 0x902d, 0x9034, 0x902f, 0x9106, 0x912c, 0x9104, 0x90ff, 0x90fc, 0x9108, 0x90f9, 0x90fb, 0x9101, 0x9100, 0x9107, 0x9105, 0x9103, 0x9161, 0x9164, 0x915f, 0x9162, 0x9160, 0x9201, 0x920a, 0x9225, 0x9203, 0x921a, 0x9226, 0x920f, 0x920c, 0x9200, 0x9212, 0x91ff, 0x91fd, 0x9206, 0x9204, 0x9227, 0x9202, 0x921c, 0x9224, 0x9219, 0x9217, 0x9205, 0x9216, 0x957b, 0x958d, 0x958c, 0x9590, 0x9687, 0x967e, 0x9688, 0x9689, 0x9683, 0x9680, 0x96c2, 0x96c8, 0x96c3, 0x96f1, 0x96f0, 0x976c, 0x9770, 0x976e, 0x9807, 0x98a9, 0x98eb, 0x9ce6, 0x9ef9, 0x4e83, 0x4e84, 0x4eb6, 0x50bd, 0x50bf, 0x50c6, 0x50ae, 0x50c4, 0x50ca, 0x50b4, 0x50c8, 0x50c2, 0x50b0, 0x50c1, 0x50ba, 0x50b1, 0x50cb, 0x50c9, 0x50b6, 0x50b8, 0x51d7, 0x527a, 0x5278, 0x527b, 0x527c, 0x55c3, 0x55db, 0x55cc, 0x55d0, 0x55cb, 0x55ca, 0x55dd, 0x55c0, 0x55d4, 0x55c4, 0x55e9, 0x55bf, 0x55d2, 0x558d, 0x55cf, 0x55d5, 0x55e2, 0x55d6, 0x55c8, 0x55f2, 0x55cd, 0x55d9, 0x55c2, 0x5714, 0x5853, 0x5868, 0x5864, 0x584f, 0x584d, 0x5849, 0x586f, 0x5855, 0x584e, 0x585d, 0x5859, 0x5865, 0x585b, 0x583d, 0x5863, 0x5871, 0x58fc, 0x5ac7, 0x5ac4, 0x5acb, 0x5aba, 0x5ab8, 0x5ab1, 0x5ab5, 0x5ab0, 0x5abf, 0x5ac8, 0x5abb, 0x5ac6, /* 0xdd */ 0x5ab7, 0x5ac0, 0x5aca, 0x5ab4, 0x5ab6, 0x5acd, 0x5ab9, 0x5a90, 0x5bd6, 0x5bd8, 0x5bd9, 0x5c1f, 0x5c33, 0x5d71, 0x5d63, 0x5d4a, 0x5d65, 0x5d72, 0x5d6c, 0x5d5e, 0x5d68, 0x5d67, 0x5d62, 0x5df0, 0x5e4f, 0x5e4e, 0x5e4a, 0x5e4d, 0x5e4b, 0x5ec5, 0x5ecc, 0x5ec6, 0x5ecb, 0x5ec7, 0x5f40, 0x5faf, 0x5fad, 0x60f7, 0x6149, 0x614a, 0x612b, 0x6145, 0x6136, 0x6132, 0x612e, 0x6146, 0x612f, 0x614f, 0x6129, 0x6140, 0x6220, 0x9168, 0x6223, 0x6225, 0x6224, 0x63c5, 0x63f1, 0x63eb, 0x6410, 0x6412, 0x6409, 0x6420, 0x6424, 0x6433, 0x6443, 0x641f, 0x6415, 0x6418, 0x6439, 0x6437, 0x6422, 0x6423, 0x640c, 0x6426, 0x6430, 0x6428, 0x6441, 0x6435, 0x642f, 0x640a, 0x641a, 0x6440, 0x6425, 0x6427, 0x640b, 0x63e7, 0x641b, 0x642e, 0x6421, 0x640e, 0x656f, 0x6592, 0x65d3, 0x6686, 0x668c, 0x6695, 0x6690, 0x668b, 0x668a, 0x6699, 0x6694, 0x6678, 0x6720, 0x6966, 0x695f, 0x6938, 0x694e, 0x6962, 0x6971, 0x693f, 0x6945, 0x696a, 0x6939, 0x6942, 0x6957, 0x6959, 0x697a, 0x6948, 0x6949, 0x6935, 0x696c, 0x6933, 0x693d, 0x6965, 0x68f0, 0x6978, 0x6934, 0x6969, 0x6940, 0x696f, 0x6944, 0x6976, 0x6958, 0x6941, 0x6974, 0x694c, 0x693b, 0x694b, 0x6937, 0x695c, 0x694f, 0x6951, 0x6932, 0x6952, 0x692f, 0x697b, 0x693c, 0x6b46, 0x6b45, 0x6b43, 0x6b42, 0x6b48, 0x6b41, 0x6b9b, 0xfa0d, 0x6bfb, 0x6bfc, /* 0xde */ 0x6bf9, 0x6bf7, 0x6bf8, 0x6e9b, 0x6ed6, 0x6ec8, 0x6e8f, 0x6ec0, 0x6e9f, 0x6e93, 0x6e94, 0x6ea0, 0x6eb1, 0x6eb9, 0x6ec6, 0x6ed2, 0x6ebd, 0x6ec1, 0x6e9e, 0x6ec9, 0x6eb7, 0x6eb0, 0x6ecd, 0x6ea6, 0x6ecf, 0x6eb2, 0x6ebe, 0x6ec3, 0x6edc, 0x6ed8, 0x6e99, 0x6e92, 0x6e8e, 0x6e8d, 0x6ea4, 0x6ea1, 0x6ebf, 0x6eb3, 0x6ed0, 0x6eca, 0x6e97, 0x6eae, 0x6ea3, 0x7147, 0x7154, 0x7152, 0x7163, 0x7160, 0x7141, 0x715d, 0x7162, 0x7172, 0x7178, 0x716a, 0x7161, 0x7142, 0x7158, 0x7143, 0x714b, 0x7170, 0x715f, 0x7150, 0x7153, 0x7144, 0x714d, 0x715a, 0x724f, 0x728d, 0x728c, 0x7291, 0x7290, 0x728e, 0x733c, 0x7342, 0x733b, 0x733a, 0x7340, 0x734a, 0x7349, 0x7444, 0x744a, 0x744b, 0x7452, 0x7451, 0x7457, 0x7440, 0x744f, 0x7450, 0x744e, 0x7442, 0x7446, 0x744d, 0x7454, 0x74e1, 0x74ff, 0x74fe, 0x74fd, 0x751d, 0x7579, 0x7577, 0x6983, 0x75ef, 0x760f, 0x7603, 0x75f7, 0x75fe, 0x75fc, 0x75f9, 0x75f8, 0x7610, 0x75fb, 0x75f6, 0x75ed, 0x75f5, 0x75fd, 0x7699, 0x76b5, 0x76dd, 0x7755, 0x775f, 0x7760, 0x7752, 0x7756, 0x775a, 0x7769, 0x7767, 0x7754, 0x7759, 0x776d, 0x77e0, 0x7887, 0x789a, 0x7894, 0x788f, 0x7884, 0x7895, 0x7885, 0x7886, 0x78a1, 0x7883, 0x7879, 0x7899, 0x7880, 0x7896, 0x787b, 0x797c, 0x7982, 0x797d, 0x7979, 0x7a11, 0x7a18, 0x7a19, 0x7a12, 0x7a17, 0x7a15, 0x7a22, 0x7a13, /* 0xdf */ 0x7a1b, 0x7a10, 0x7aa3, 0x7aa2, 0x7a9e, 0x7aeb, 0x7b66, 0x7b64, 0x7b6d, 0x7b74, 0x7b69, 0x7b72, 0x7b65, 0x7b73, 0x7b71, 0x7b70, 0x7b61, 0x7b78, 0x7b76, 0x7b63, 0x7cb2, 0x7cb4, 0x7caf, 0x7d88, 0x7d86, 0x7d80, 0x7d8d, 0x7d7f, 0x7d85, 0x7d7a, 0x7d8e, 0x7d7b, 0x7d83, 0x7d7c, 0x7d8c, 0x7d94, 0x7d84, 0x7d7d, 0x7d92, 0x7f6d, 0x7f6b, 0x7f67, 0x7f68, 0x7f6c, 0x7fa6, 0x7fa5, 0x7fa7, 0x7fdb, 0x7fdc, 0x8021, 0x8164, 0x8160, 0x8177, 0x815c, 0x8169, 0x815b, 0x8162, 0x8172, 0x6721, 0x815e, 0x8176, 0x8167, 0x816f, 0x8144, 0x8161, 0x821d, 0x8249, 0x8244, 0x8240, 0x8242, 0x8245, 0x84f1, 0x843f, 0x8456, 0x8476, 0x8479, 0x848f, 0x848d, 0x8465, 0x8451, 0x8440, 0x8486, 0x8467, 0x8430, 0x844d, 0x847d, 0x845a, 0x8459, 0x8474, 0x8473, 0x845d, 0x8507, 0x845e, 0x8437, 0x843a, 0x8434, 0x847a, 0x8443, 0x8478, 0x8432, 0x8445, 0x8429, 0x83d9, 0x844b, 0x842f, 0x8442, 0x842d, 0x845f, 0x8470, 0x8439, 0x844e, 0x844c, 0x8452, 0x846f, 0x84c5, 0x848e, 0x843b, 0x8447, 0x8436, 0x8433, 0x8468, 0x847e, 0x8444, 0x842b, 0x8460, 0x8454, 0x846e, 0x8450, 0x870b, 0x8704, 0x86f7, 0x870c, 0x86fa, 0x86d6, 0x86f5, 0x874d, 0x86f8, 0x870e, 0x8709, 0x8701, 0x86f6, 0x870d, 0x8705, 0x88d6, 0x88cb, 0x88cd, 0x88ce, 0x88de, 0x88db, 0x88da, 0x88cc, 0x88d0, 0x8985, 0x899b, 0x89df, 0x89e5, 0x89e4, /* 0xe0 */ 0x89e1, 0x89e0, 0x89e2, 0x89dc, 0x89e6, 0x8a76, 0x8a86, 0x8a7f, 0x8a61, 0x8a3f, 0x8a77, 0x8a82, 0x8a84, 0x8a75, 0x8a83, 0x8a81, 0x8a74, 0x8a7a, 0x8c3c, 0x8c4b, 0x8c4a, 0x8c65, 0x8c64, 0x8c66, 0x8c86, 0x8c84, 0x8c85, 0x8ccc, 0x8d68, 0x8d69, 0x8d91, 0x8d8c, 0x8d8e, 0x8d8f, 0x8d8d, 0x8d93, 0x8d94, 0x8d90, 0x8d92, 0x8df0, 0x8de0, 0x8dec, 0x8df1, 0x8dee, 0x8dd0, 0x8de9, 0x8de3, 0x8de2, 0x8de7, 0x8df2, 0x8deb, 0x8df4, 0x8f06, 0x8eff, 0x8f01, 0x8f00, 0x8f05, 0x8f07, 0x8f08, 0x8f02, 0x8f0b, 0x9052, 0x903f, 0x9044, 0x9049, 0x903d, 0x9110, 0x910d, 0x910f, 0x9111, 0x9116, 0x9114, 0x910b, 0x910e, 0x916e, 0x916f, 0x9248, 0x9252, 0x9230, 0x923a, 0x9266, 0x9233, 0x9265, 0x925e, 0x9283, 0x922e, 0x924a, 0x9246, 0x926d, 0x926c, 0x924f, 0x9260, 0x9267, 0x926f, 0x9236, 0x9261, 0x9270, 0x9231, 0x9254, 0x9263, 0x9250, 0x9272, 0x924e, 0x9253, 0x924c, 0x9256, 0x9232, 0x959f, 0x959c, 0x959e, 0x959b, 0x9692, 0x9693, 0x9691, 0x9697, 0x96ce, 0x96fa, 0x96fd, 0x96f8, 0x96f5, 0x9773, 0x9777, 0x9778, 0x9772, 0x980f, 0x980d, 0x980e, 0x98ac, 0x98f6, 0x98f9, 0x99af, 0x99b2, 0x99b0, 0x99b5, 0x9aad, 0x9aab, 0x9b5b, 0x9cea, 0x9ced, 0x9ce7, 0x9e80, 0x9efd, 0x50e6, 0x50d4, 0x50d7, 0x50e8, 0x50f3, 0x50db, 0x50ea, 0x50dd, 0x50e4, 0x50d3, 0x50ec, 0x50f0, 0x50ef, 0x50e3, 0x50e0, /* 0xe1 */ 0x51d8, 0x5280, 0x5281, 0x52e9, 0x52eb, 0x5330, 0x53ac, 0x5627, 0x5615, 0x560c, 0x5612, 0x55fc, 0x560f, 0x561c, 0x5601, 0x5613, 0x5602, 0x55fa, 0x561d, 0x5604, 0x55ff, 0x55f9, 0x5889, 0x587c, 0x5890, 0x5898, 0x5886, 0x5881, 0x587f, 0x5874, 0x588b, 0x587a, 0x5887, 0x5891, 0x588e, 0x5876, 0x5882, 0x5888, 0x587b, 0x5894, 0x588f, 0x58fe, 0x596b, 0x5adc, 0x5aee, 0x5ae5, 0x5ad5, 0x5aea, 0x5ada, 0x5aed, 0x5aeb, 0x5af3, 0x5ae2, 0x5ae0, 0x5adb, 0x5aec, 0x5ade, 0x5add, 0x5ad9, 0x5ae8, 0x5adf, 0x5b77, 0x5be0, 0x5be3, 0x5c63, 0x5d82, 0x5d80, 0x5d7d, 0x5d86, 0x5d7a, 0x5d81, 0x5d77, 0x5d8a, 0x5d89, 0x5d88, 0x5d7e, 0x5d7c, 0x5d8d, 0x5d79, 0x5d7f, 0x5e58, 0x5e59, 0x5e53, 0x5ed8, 0x5ed1, 0x5ed7, 0x5ece, 0x5edc, 0x5ed5, 0x5ed9, 0x5ed2, 0x5ed4, 0x5f44, 0x5f43, 0x5f6f, 0x5fb6, 0x612c, 0x6128, 0x6141, 0x615e, 0x6171, 0x6173, 0x6152, 0x6153, 0x6172, 0x616c, 0x6180, 0x6174, 0x6154, 0x617a, 0x615b, 0x6165, 0x613b, 0x616a, 0x6161, 0x6156, 0x6229, 0x6227, 0x622b, 0x642b, 0x644d, 0x645b, 0x645d, 0x6474, 0x6476, 0x6472, 0x6473, 0x647d, 0x6475, 0x6466, 0x64a6, 0x644e, 0x6482, 0x645e, 0x645c, 0x644b, 0x6453, 0x6460, 0x6450, 0x647f, 0x643f, 0x646c, 0x646b, 0x6459, 0x6465, 0x6477, 0x6573, 0x65a0, 0x66a1, 0x66a0, 0x669f, 0x6705, 0x6704, 0x6722, 0x69b1, 0x69b6, 0x69c9, /* 0xe2 */ 0x69a0, 0x69ce, 0x6996, 0x69b0, 0x69ac, 0x69bc, 0x6991, 0x6999, 0x698e, 0x69a7, 0x698d, 0x69a9, 0x69be, 0x69af, 0x69bf, 0x69c4, 0x69bd, 0x69a4, 0x69d4, 0x69b9, 0x69ca, 0x699a, 0x69cf, 0x69b3, 0x6993, 0x69aa, 0x69a1, 0x699e, 0x69d9, 0x6997, 0x6990, 0x69c2, 0x69b5, 0x69a5, 0x69c6, 0x6b4a, 0x6b4d, 0x6b4b, 0x6b9e, 0x6b9f, 0x6ba0, 0x6bc3, 0x6bc4, 0x6bfe, 0x6ece, 0x6ef5, 0x6ef1, 0x6f03, 0x6f25, 0x6ef8, 0x6f37, 0x6efb, 0x6f2e, 0x6f09, 0x6f4e, 0x6f19, 0x6f1a, 0x6f27, 0x6f18, 0x6f3b, 0x6f12, 0x6eed, 0x6f0a, 0x6f36, 0x6f73, 0x6ef9, 0x6eee, 0x6f2d, 0x6f40, 0x6f30, 0x6f3c, 0x6f35, 0x6eeb, 0x6f07, 0x6f0e, 0x6f43, 0x6f05, 0x6efd, 0x6ef6, 0x6f39, 0x6f1c, 0x6efc, 0x6f3a, 0x6f1f, 0x6f0d, 0x6f1e, 0x6f08, 0x6f21, 0x7187, 0x7190, 0x7189, 0x7180, 0x7185, 0x7182, 0x718f, 0x717b, 0x7186, 0x7181, 0x7197, 0x7244, 0x7253, 0x7297, 0x7295, 0x7293, 0x7343, 0x734d, 0x7351, 0x734c, 0x7462, 0x7473, 0x7471, 0x7475, 0x7472, 0x7467, 0x746e, 0x7500, 0x7502, 0x7503, 0x757d, 0x7590, 0x7616, 0x7608, 0x760c, 0x7615, 0x7611, 0x760a, 0x7614, 0x76b8, 0x7781, 0x777c, 0x7785, 0x7782, 0x776e, 0x7780, 0x776f, 0x777e, 0x7783, 0x78b2, 0x78aa, 0x78b4, 0x78ad, 0x78a8, 0x787e, 0x78ab, 0x789e, 0x78a5, 0x78a0, 0x78ac, 0x78a2, 0x78a4, 0x7998, 0x798a, 0x798b, 0x7996, 0x7995, 0x7994, 0x7993, /* 0xe3 */ 0x7997, 0x7988, 0x7992, 0x7990, 0x7a2b, 0x7a4a, 0x7a30, 0x7a2f, 0x7a28, 0x7a26, 0x7aa8, 0x7aab, 0x7aac, 0x7aee, 0x7b88, 0x7b9c, 0x7b8a, 0x7b91, 0x7b90, 0x7b96, 0x7b8d, 0x7b8c, 0x7b9b, 0x7b8e, 0x7b85, 0x7b98, 0x5284, 0x7b99, 0x7ba4, 0x7b82, 0x7cbb, 0x7cbf, 0x7cbc, 0x7cba, 0x7da7, 0x7db7, 0x7dc2, 0x7da3, 0x7daa, 0x7dc1, 0x7dc0, 0x7dc5, 0x7d9d, 0x7dce, 0x7dc4, 0x7dc6, 0x7dcb, 0x7dcc, 0x7daf, 0x7db9, 0x7d96, 0x7dbc, 0x7d9f, 0x7da6, 0x7dae, 0x7da9, 0x7da1, 0x7dc9, 0x7f73, 0x7fe2, 0x7fe3, 0x7fe5, 0x7fde, 0x8024, 0x805d, 0x805c, 0x8189, 0x8186, 0x8183, 0x8187, 0x818d, 0x818c, 0x818b, 0x8215, 0x8497, 0x84a4, 0x84a1, 0x849f, 0x84ba, 0x84ce, 0x84c2, 0x84ac, 0x84ae, 0x84ab, 0x84b9, 0x84b4, 0x84c1, 0x84cd, 0x84aa, 0x849a, 0x84b1, 0x84d0, 0x849d, 0x84a7, 0x84bb, 0x84a2, 0x8494, 0x84c7, 0x84cc, 0x849b, 0x84a9, 0x84af, 0x84a8, 0x84d6, 0x8498, 0x84b6, 0x84cf, 0x84a0, 0x84d7, 0x84d4, 0x84d2, 0x84db, 0x84b0, 0x8491, 0x8661, 0x8733, 0x8723, 0x8728, 0x876b, 0x8740, 0x872e, 0x871e, 0x8721, 0x8719, 0x871b, 0x8743, 0x872c, 0x8741, 0x873e, 0x8746, 0x8720, 0x8732, 0x872a, 0x872d, 0x873c, 0x8712, 0x873a, 0x8731, 0x8735, 0x8742, 0x8726, 0x8727, 0x8738, 0x8724, 0x871a, 0x8730, 0x8711, 0x88f7, 0x88e7, 0x88f1, 0x88f2, 0x88fa, 0x88fe, 0x88ee, 0x88fc, 0x88f6, 0x88fb, /* 0xe4 */ 0x88f0, 0x88ec, 0x88eb, 0x899d, 0x89a1, 0x899f, 0x899e, 0x89e9, 0x89eb, 0x89e8, 0x8aab, 0x8a99, 0x8a8b, 0x8a92, 0x8a8f, 0x8a96, 0x8c3d, 0x8c68, 0x8c69, 0x8cd5, 0x8ccf, 0x8cd7, 0x8d96, 0x8e09, 0x8e02, 0x8dff, 0x8e0d, 0x8dfd, 0x8e0a, 0x8e03, 0x8e07, 0x8e06, 0x8e05, 0x8dfe, 0x8e00, 0x8e04, 0x8f10, 0x8f11, 0x8f0e, 0x8f0d, 0x9123, 0x911c, 0x9120, 0x9122, 0x911f, 0x911d, 0x911a, 0x9124, 0x9121, 0x911b, 0x917a, 0x9172, 0x9179, 0x9173, 0x92a5, 0x92a4, 0x9276, 0x929b, 0x927a, 0x92a0, 0x9294, 0x92aa, 0x928d, 0x92a6, 0x929a, 0x92ab, 0x9279, 0x9297, 0x927f, 0x92a3, 0x92ee, 0x928e, 0x9282, 0x9295, 0x92a2, 0x927d, 0x9288, 0x92a1, 0x928a, 0x9286, 0x928c, 0x9299, 0x92a7, 0x927e, 0x9287, 0x92a9, 0x929d, 0x928b, 0x922d, 0x969e, 0x96a1, 0x96ff, 0x9758, 0x977d, 0x977a, 0x977e, 0x9783, 0x9780, 0x9782, 0x977b, 0x9784, 0x9781, 0x977f, 0x97ce, 0x97cd, 0x9816, 0x98ad, 0x98ae, 0x9902, 0x9900, 0x9907, 0x999d, 0x999c, 0x99c3, 0x99b9, 0x99bb, 0x99ba, 0x99c2, 0x99bd, 0x99c7, 0x9ab1, 0x9ae3, 0x9ae7, 0x9b3e, 0x9b3f, 0x9b60, 0x9b61, 0x9b5f, 0x9cf1, 0x9cf2, 0x9cf5, 0x9ea7, 0x50ff, 0x5103, 0x5130, 0x50f8, 0x5106, 0x5107, 0x50f6, 0x50fe, 0x510b, 0x510c, 0x50fd, 0x510a, 0x528b, 0x528c, 0x52f1, 0x52ef, 0x5648, 0x5642, 0x564c, 0x5635, 0x5641, 0x564a, 0x5649, 0x5646, 0x5658, /* 0xe5 */ 0x565a, 0x5640, 0x5633, 0x563d, 0x562c, 0x563e, 0x5638, 0x562a, 0x563a, 0x571a, 0x58ab, 0x589d, 0x58b1, 0x58a0, 0x58a3, 0x58af, 0x58ac, 0x58a5, 0x58a1, 0x58ff, 0x5aff, 0x5af4, 0x5afd, 0x5af7, 0x5af6, 0x5b03, 0x5af8, 0x5b02, 0x5af9, 0x5b01, 0x5b07, 0x5b05, 0x5b0f, 0x5c67, 0x5d99, 0x5d97, 0x5d9f, 0x5d92, 0x5da2, 0x5d93, 0x5d95, 0x5da0, 0x5d9c, 0x5da1, 0x5d9a, 0x5d9e, 0x5e69, 0x5e5d, 0x5e60, 0x5e5c, 0x7df3, 0x5edb, 0x5ede, 0x5ee1, 0x5f49, 0x5fb2, 0x618b, 0x6183, 0x6179, 0x61b1, 0x61b0, 0x61a2, 0x6189, 0x619b, 0x6193, 0x61af, 0x61ad, 0x619f, 0x6192, 0x61aa, 0x61a1, 0x618d, 0x6166, 0x61b3, 0x622d, 0x646e, 0x6470, 0x6496, 0x64a0, 0x6485, 0x6497, 0x649c, 0x648f, 0x648b, 0x648a, 0x648c, 0x64a3, 0x649f, 0x6468, 0x64b1, 0x6498, 0x6576, 0x657a, 0x6579, 0x657b, 0x65b2, 0x65b3, 0x66b5, 0x66b0, 0x66a9, 0x66b2, 0x66b7, 0x66aa, 0x66af, 0x6a00, 0x6a06, 0x6a17, 0x69e5, 0x69f8, 0x6a15, 0x69f1, 0x69e4, 0x6a20, 0x69ff, 0x69ec, 0x69e2, 0x6a1b, 0x6a1d, 0x69fe, 0x6a27, 0x69f2, 0x69ee, 0x6a14, 0x69f7, 0x69e7, 0x6a40, 0x6a08, 0x69e6, 0x69fb, 0x6a0d, 0x69fc, 0x69eb, 0x6a09, 0x6a04, 0x6a18, 0x6a25, 0x6a0f, 0x69f6, 0x6a26, 0x6a07, 0x69f4, 0x6a16, 0x6b51, 0x6ba5, 0x6ba3, 0x6ba2, 0x6ba6, 0x6c01, 0x6c00, 0x6bff, 0x6c02, 0x6f41, 0x6f26, 0x6f7e, 0x6f87, 0x6fc6, 0x6f92, /* 0xe6 */ 0x6f8d, 0x6f89, 0x6f8c, 0x6f62, 0x6f4f, 0x6f85, 0x6f5a, 0x6f96, 0x6f76, 0x6f6c, 0x6f82, 0x6f55, 0x6f72, 0x6f52, 0x6f50, 0x6f57, 0x6f94, 0x6f93, 0x6f5d, 0x6f00, 0x6f61, 0x6f6b, 0x6f7d, 0x6f67, 0x6f90, 0x6f53, 0x6f8b, 0x6f69, 0x6f7f, 0x6f95, 0x6f63, 0x6f77, 0x6f6a, 0x6f7b, 0x71b2, 0x71af, 0x719b, 0x71b0, 0x71a0, 0x719a, 0x71a9, 0x71b5, 0x719d, 0x71a5, 0x719e, 0x71a4, 0x71a1, 0x71aa, 0x719c, 0x71a7, 0x71b3, 0x7298, 0x729a, 0x7358, 0x7352, 0x735e, 0x735f, 0x7360, 0x735d, 0x735b, 0x7361, 0x735a, 0x7359, 0x7362, 0x7487, 0x7489, 0x748a, 0x7486, 0x7481, 0x747d, 0x7485, 0x7488, 0x747c, 0x7479, 0x7508, 0x7507, 0x757e, 0x7625, 0x761e, 0x7619, 0x761d, 0x761c, 0x7623, 0x761a, 0x7628, 0x761b, 0x769c, 0x769d, 0x769e, 0x769b, 0x778d, 0x778f, 0x7789, 0x7788, 0x78cd, 0x78bb, 0x78cf, 0x78cc, 0x78d1, 0x78ce, 0x78d4, 0x78c8, 0x78c3, 0x78c4, 0x78c9, 0x799a, 0x79a1, 0x79a0, 0x799c, 0x79a2, 0x799b, 0x6b76, 0x7a39, 0x7ab2, 0x7ab4, 0x7ab3, 0x7bb7, 0x7bcb, 0x7bbe, 0x7bac, 0x7bce, 0x7baf, 0x7bb9, 0x7bca, 0x7bb5, 0x7cc5, 0x7cc8, 0x7ccc, 0x7ccb, 0x7df7, 0x7ddb, 0x7dea, 0x7de7, 0x7dd7, 0x7de1, 0x7e03, 0x7dfa, 0x7de6, 0x7df6, 0x7df1, 0x7df0, 0x7dee, 0x7ddf, 0x7f76, 0x7fac, 0x7fb0, 0x7fad, 0x7fed, 0x7feb, 0x7fea, 0x7fec, 0x7fe6, 0x7fe8, 0x8064, 0x8067, 0x81a3, 0x819f, /* 0xe7 */ 0x819e, 0x8195, 0x81a2, 0x8199, 0x8197, 0x8216, 0x824f, 0x8253, 0x8252, 0x8250, 0x824e, 0x8251, 0x8524, 0x853b, 0x850f, 0x8500, 0x8529, 0x850e, 0x8509, 0x850d, 0x851f, 0x850a, 0x8527, 0x851c, 0x84fb, 0x852b, 0x84fa, 0x8508, 0x850c, 0x84f4, 0x852a, 0x84f2, 0x8515, 0x84f7, 0x84eb, 0x84f3, 0x84fc, 0x8512, 0x84ea, 0x84e9, 0x8516, 0x84fe, 0x8528, 0x851d, 0x852e, 0x8502, 0x84fd, 0x851e, 0x84f6, 0x8531, 0x8526, 0x84e7, 0x84e8, 0x84f0, 0x84ef, 0x84f9, 0x8518, 0x8520, 0x8530, 0x850b, 0x8519, 0x852f, 0x8662, 0x8756, 0x8763, 0x8764, 0x8777, 0x87e1, 0x8773, 0x8758, 0x8754, 0x875b, 0x8752, 0x8761, 0x875a, 0x8751, 0x875e, 0x876d, 0x876a, 0x8750, 0x874e, 0x875f, 0x875d, 0x876f, 0x876c, 0x877a, 0x876e, 0x875c, 0x8765, 0x874f, 0x877b, 0x8775, 0x8762, 0x8767, 0x8769, 0x885a, 0x8905, 0x890c, 0x8914, 0x890b, 0x8917, 0x8918, 0x8919, 0x8906, 0x8916, 0x8911, 0x890e, 0x8909, 0x89a2, 0x89a4, 0x89a3, 0x89ed, 0x89f0, 0x89ec, 0x8acf, 0x8ac6, 0x8ab8, 0x8ad3, 0x8ad1, 0x8ad4, 0x8ad5, 0x8abb, 0x8ad7, 0x8abe, 0x8ac0, 0x8ac5, 0x8ad8, 0x8ac3, 0x8aba, 0x8abd, 0x8ad9, 0x8c3e, 0x8c4d, 0x8c8f, 0x8ce5, 0x8cdf, 0x8cd9, 0x8ce8, 0x8cda, 0x8cdd, 0x8ce7, 0x8da0, 0x8d9c, 0x8da1, 0x8d9b, 0x8e20, 0x8e23, 0x8e25, 0x8e24, 0x8e2e, 0x8e15, 0x8e1b, 0x8e16, 0x8e11, 0x8e19, 0x8e26, 0x8e27, /* 0xe8 */ 0x8e14, 0x8e12, 0x8e18, 0x8e13, 0x8e1c, 0x8e17, 0x8e1a, 0x8f2c, 0x8f24, 0x8f18, 0x8f1a, 0x8f20, 0x8f23, 0x8f16, 0x8f17, 0x9073, 0x9070, 0x906f, 0x9067, 0x906b, 0x912f, 0x912b, 0x9129, 0x912a, 0x9132, 0x9126, 0x912e, 0x9185, 0x9186, 0x918a, 0x9181, 0x9182, 0x9184, 0x9180, 0x92d0, 0x92c3, 0x92c4, 0x92c0, 0x92d9, 0x92b6, 0x92cf, 0x92f1, 0x92df, 0x92d8, 0x92e9, 0x92d7, 0x92dd, 0x92cc, 0x92ef, 0x92c2, 0x92e8, 0x92ca, 0x92c8, 0x92ce, 0x92e6, 0x92cd, 0x92d5, 0x92c9, 0x92e0, 0x92de, 0x92e7, 0x92d1, 0x92d3, 0x92b5, 0x92e1, 0x92c6, 0x92b4, 0x957c, 0x95ac, 0x95ab, 0x95ae, 0x95b0, 0x96a4, 0x96a2, 0x96d3, 0x9705, 0x9708, 0x9702, 0x975a, 0x978a, 0x978e, 0x9788, 0x97d0, 0x97cf, 0x981e, 0x981d, 0x9826, 0x9829, 0x9828, 0x9820, 0x981b, 0x9827, 0x98b2, 0x9908, 0x98fa, 0x9911, 0x9914, 0x9916, 0x9917, 0x9915, 0x99dc, 0x99cd, 0x99cf, 0x99d3, 0x99d4, 0x99ce, 0x99c9, 0x99d6, 0x99d8, 0x99cb, 0x99d7, 0x99cc, 0x9ab3, 0x9aec, 0x9aeb, 0x9af3, 0x9af2, 0x9af1, 0x9b46, 0x9b43, 0x9b67, 0x9b74, 0x9b71, 0x9b66, 0x9b76, 0x9b75, 0x9b70, 0x9b68, 0x9b64, 0x9b6c, 0x9cfc, 0x9cfa, 0x9cfd, 0x9cff, 0x9cf7, 0x9d07, 0x9d00, 0x9cf9, 0x9cfb, 0x9d08, 0x9d05, 0x9d04, 0x9e83, 0x9ed3, 0x9f0f, 0x9f10, 0x511c, 0x5113, 0x5117, 0x511a, 0x5111, 0x51de, 0x5334, 0x53e1, 0x5670, 0x5660, 0x566e, /* 0xe9 */ 0x5673, 0x5666, 0x5663, 0x566d, 0x5672, 0x565e, 0x5677, 0x571c, 0x571b, 0x58c8, 0x58bd, 0x58c9, 0x58bf, 0x58ba, 0x58c2, 0x58bc, 0x58c6, 0x5b17, 0x5b19, 0x5b1b, 0x5b21, 0x5b14, 0x5b13, 0x5b10, 0x5b16, 0x5b28, 0x5b1a, 0x5b20, 0x5b1e, 0x5bef, 0x5dac, 0x5db1, 0x5da9, 0x5da7, 0x5db5, 0x5db0, 0x5dae, 0x5daa, 0x5da8, 0x5db2, 0x5dad, 0x5daf, 0x5db4, 0x5e67, 0x5e68, 0x5e66, 0x5e6f, 0x5ee9, 0x5ee7, 0x5ee6, 0x5ee8, 0x5ee5, 0x5f4b, 0x5fbc, 0x619d, 0x61a8, 0x6196, 0x61c5, 0x61b4, 0x61c6, 0x61c1, 0x61cc, 0x61ba, 0x61bf, 0x61b8, 0x618c, 0x64d7, 0x64d6, 0x64d0, 0x64cf, 0x64c9, 0x64bd, 0x6489, 0x64c3, 0x64db, 0x64f3, 0x64d9, 0x6533, 0x657f, 0x657c, 0x65a2, 0x66c8, 0x66be, 0x66c0, 0x66ca, 0x66cb, 0x66cf, 0x66bd, 0x66bb, 0x66ba, 0x66cc, 0x6723, 0x6a34, 0x6a66, 0x6a49, 0x6a67, 0x6a32, 0x6a68, 0x6a3e, 0x6a5d, 0x6a6d, 0x6a76, 0x6a5b, 0x6a51, 0x6a28, 0x6a5a, 0x6a3b, 0x6a3f, 0x6a41, 0x6a6a, 0x6a64, 0x6a50, 0x6a4f, 0x6a54, 0x6a6f, 0x6a69, 0x6a60, 0x6a3c, 0x6a5e, 0x6a56, 0x6a55, 0x6a4d, 0x6a4e, 0x6a46, 0x6b55, 0x6b54, 0x6b56, 0x6ba7, 0x6baa, 0x6bab, 0x6bc8, 0x6bc7, 0x6c04, 0x6c03, 0x6c06, 0x6fad, 0x6fcb, 0x6fa3, 0x6fc7, 0x6fbc, 0x6fce, 0x6fc8, 0x6f5e, 0x6fc4, 0x6fbd, 0x6f9e, 0x6fca, 0x6fa8, 0x7004, 0x6fa5, 0x6fae, 0x6fba, 0x6fac, 0x6faa, 0x6fcf, 0x6fbf, 0x6fb8, /* 0xea */ 0x6fa2, 0x6fc9, 0x6fab, 0x6fcd, 0x6faf, 0x6fb2, 0x6fb0, 0x71c5, 0x71c2, 0x71bf, 0x71b8, 0x71d6, 0x71c0, 0x71c1, 0x71cb, 0x71d4, 0x71ca, 0x71c7, 0x71cf, 0x71bd, 0x71d8, 0x71bc, 0x71c6, 0x71da, 0x71db, 0x729d, 0x729e, 0x7369, 0x7366, 0x7367, 0x736c, 0x7365, 0x736b, 0x736a, 0x747f, 0x749a, 0x74a0, 0x7494, 0x7492, 0x7495, 0x74a1, 0x750b, 0x7580, 0x762f, 0x762d, 0x7631, 0x763d, 0x7633, 0x763c, 0x7635, 0x7632, 0x7630, 0x76bb, 0x76e6, 0x779a, 0x779d, 0x77a1, 0x779c, 0x779b, 0x77a2, 0x77a3, 0x7795, 0x7799, 0x7797, 0x78dd, 0x78e9, 0x78e5, 0x78ea, 0x78de, 0x78e3, 0x78db, 0x78e1, 0x78e2, 0x78ed, 0x78df, 0x78e0, 0x79a4, 0x7a44, 0x7a48, 0x7a47, 0x7ab6, 0x7ab8, 0x7ab5, 0x7ab1, 0x7ab7, 0x7bde, 0x7be3, 0x7be7, 0x7bdd, 0x7bd5, 0x7be5, 0x7bda, 0x7be8, 0x7bf9, 0x7bd4, 0x7bea, 0x7be2, 0x7bdc, 0x7beb, 0x7bd8, 0x7bdf, 0x7cd2, 0x7cd4, 0x7cd7, 0x7cd0, 0x7cd1, 0x7e12, 0x7e21, 0x7e17, 0x7e0c, 0x7e1f, 0x7e20, 0x7e13, 0x7e0e, 0x7e1c, 0x7e15, 0x7e1a, 0x7e22, 0x7e0b, 0x7e0f, 0x7e16, 0x7e0d, 0x7e14, 0x7e25, 0x7e24, 0x7f43, 0x7f7b, 0x7f7c, 0x7f7a, 0x7fb1, 0x7fef, 0x802a, 0x8029, 0x806c, 0x81b1, 0x81a6, 0x81ae, 0x81b9, 0x81b5, 0x81ab, 0x81b0, 0x81ac, 0x81b4, 0x81b2, 0x81b7, 0x81a7, 0x81f2, 0x8255, 0x8256, 0x8257, 0x8556, 0x8545, 0x856b, 0x854d, 0x8553, 0x8561, 0x8558, /* 0xeb */ 0x8540, 0x8546, 0x8564, 0x8541, 0x8562, 0x8544, 0x8551, 0x8547, 0x8563, 0x853e, 0x855b, 0x8571, 0x854e, 0x856e, 0x8575, 0x8555, 0x8567, 0x8560, 0x858c, 0x8566, 0x855d, 0x8554, 0x8565, 0x856c, 0x8663, 0x8665, 0x8664, 0x879b, 0x878f, 0x8797, 0x8793, 0x8792, 0x8788, 0x8781, 0x8796, 0x8798, 0x8779, 0x8787, 0x87a3, 0x8785, 0x8790, 0x8791, 0x879d, 0x8784, 0x8794, 0x879c, 0x879a, 0x8789, 0x891e, 0x8926, 0x8930, 0x892d, 0x892e, 0x8927, 0x8931, 0x8922, 0x8929, 0x8923, 0x892f, 0x892c, 0x891f, 0x89f1, 0x8ae0, 0x8ae2, 0x8af2, 0x8af4, 0x8af5, 0x8add, 0x8b14, 0x8ae4, 0x8adf, 0x8af0, 0x8ac8, 0x8ade, 0x8ae1, 0x8ae8, 0x8aff, 0x8aef, 0x8afb, 0x8c91, 0x8c92, 0x8c90, 0x8cf5, 0x8cee, 0x8cf1, 0x8cf0, 0x8cf3, 0x8d6c, 0x8d6e, 0x8da5, 0x8da7, 0x8e33, 0x8e3e, 0x8e38, 0x8e40, 0x8e45, 0x8e36, 0x8e3c, 0x8e3d, 0x8e41, 0x8e30, 0x8e3f, 0x8ebd, 0x8f36, 0x8f2e, 0x8f35, 0x8f32, 0x8f39, 0x8f37, 0x8f34, 0x9076, 0x9079, 0x907b, 0x9086, 0x90fa, 0x9133, 0x9135, 0x9136, 0x9193, 0x9190, 0x9191, 0x918d, 0x918f, 0x9327, 0x931e, 0x9308, 0x931f, 0x9306, 0x930f, 0x937a, 0x9338, 0x933c, 0x931b, 0x9323, 0x9312, 0x9301, 0x9346, 0x932d, 0x930e, 0x930d, 0x92cb, 0x931d, 0x92fa, 0x9325, 0x9313, 0x92f9, 0x92f7, 0x9334, 0x9302, 0x9324, 0x92ff, 0x9329, 0x9339, 0x9335, 0x932a, 0x9314, 0x930c, /* 0xec */ 0x930b, 0x92fe, 0x9309, 0x9300, 0x92fb, 0x9316, 0x95bc, 0x95cd, 0x95be, 0x95b9, 0x95ba, 0x95b6, 0x95bf, 0x95b5, 0x95bd, 0x96a9, 0x96d4, 0x970b, 0x9712, 0x9710, 0x9799, 0x9797, 0x9794, 0x97f0, 0x97f8, 0x9835, 0x982f, 0x9832, 0x9924, 0x991f, 0x9927, 0x9929, 0x999e, 0x99ee, 0x99ec, 0x99e5, 0x99e4, 0x99f0, 0x99e3, 0x99ea, 0x99e9, 0x99e7, 0x9ab9, 0x9abf, 0x9ab4, 0x9abb, 0x9af6, 0x9afa, 0x9af9, 0x9af7, 0x9b33, 0x9b80, 0x9b85, 0x9b87, 0x9b7c, 0x9b7e, 0x9b7b, 0x9b82, 0x9b93, 0x9b92, 0x9b90, 0x9b7a, 0x9b95, 0x9b7d, 0x9b88, 0x9d25, 0x9d17, 0x9d20, 0x9d1e, 0x9d14, 0x9d29, 0x9d1d, 0x9d18, 0x9d22, 0x9d10, 0x9d19, 0x9d1f, 0x9e88, 0x9e86, 0x9e87, 0x9eae, 0x9ead, 0x9ed5, 0x9ed6, 0x9efa, 0x9f12, 0x9f3d, 0x5126, 0x5125, 0x5122, 0x5124, 0x5120, 0x5129, 0x52f4, 0x5693, 0x568c, 0x568d, 0x5686, 0x5684, 0x5683, 0x567e, 0x5682, 0x567f, 0x5681, 0x58d6, 0x58d4, 0x58cf, 0x58d2, 0x5b2d, 0x5b25, 0x5b32, 0x5b23, 0x5b2c, 0x5b27, 0x5b26, 0x5b2f, 0x5b2e, 0x5b7b, 0x5bf1, 0x5bf2, 0x5db7, 0x5e6c, 0x5e6a, 0x5fbe, 0x5fbb, 0x61c3, 0x61b5, 0x61bc, 0x61e7, 0x61e0, 0x61e5, 0x61e4, 0x61e8, 0x61de, 0x64ef, 0x64e9, 0x64e3, 0x64eb, 0x64e4, 0x64e8, 0x6581, 0x6580, 0x65b6, 0x65da, 0x66d2, 0x6a8d, 0x6a96, 0x6a81, 0x6aa5, 0x6a89, 0x6a9f, 0x6a9b, 0x6aa1, 0x6a9e, 0x6a87, 0x6a93, 0x6a8e, /* 0xed */ 0x6a95, 0x6a83, 0x6aa8, 0x6aa4, 0x6a91, 0x6a7f, 0x6aa6, 0x6a9a, 0x6a85, 0x6a8c, 0x6a92, 0x6b5b, 0x6bad, 0x6c09, 0x6fcc, 0x6fa9, 0x6ff4, 0x6fd4, 0x6fe3, 0x6fdc, 0x6fed, 0x6fe7, 0x6fe6, 0x6fde, 0x6ff2, 0x6fdd, 0x6fe2, 0x6fe8, 0x71e1, 0x71f1, 0x71e8, 0x71f2, 0x71e4, 0x71f0, 0x71e2, 0x7373, 0x736e, 0x736f, 0x7497, 0x74b2, 0x74ab, 0x7490, 0x74aa, 0x74ad, 0x74b1, 0x74a5, 0x74af, 0x7510, 0x7511, 0x7512, 0x750f, 0x7584, 0x7643, 0x7648, 0x7649, 0x7647, 0x76a4, 0x76e9, 0x77b5, 0x77ab, 0x77b2, 0x77b7, 0x77b6, 0x77b4, 0x77b1, 0x77a8, 0x77f0, 0x78f3, 0x78fd, 0x7902, 0x78fb, 0x78fc, 0x78f2, 0x7905, 0x78f9, 0x78fe, 0x7904, 0x79ab, 0x79a8, 0x7a5c, 0x7a5b, 0x7a56, 0x7a58, 0x7a54, 0x7a5a, 0x7abe, 0x7ac0, 0x7ac1, 0x7c05, 0x7c0f, 0x7bf2, 0x7c00, 0x7bff, 0x7bfb, 0x7c0e, 0x7bf4, 0x7c0b, 0x7bf3, 0x7c02, 0x7c09, 0x7c03, 0x7c01, 0x7bf8, 0x7bfd, 0x7c06, 0x7bf0, 0x7bf1, 0x7c10, 0x7c0a, 0x7ce8, 0x7e2d, 0x7e3c, 0x7e42, 0x7e33, 0x9848, 0x7e38, 0x7e2a, 0x7e49, 0x7e40, 0x7e47, 0x7e29, 0x7e4c, 0x7e30, 0x7e3b, 0x7e36, 0x7e44, 0x7e3a, 0x7f45, 0x7f7f, 0x7f7e, 0x7f7d, 0x7ff4, 0x7ff2, 0x802c, 0x81bb, 0x81c4, 0x81cc, 0x81ca, 0x81c5, 0x81c7, 0x81bc, 0x81e9, 0x825b, 0x825a, 0x825c, 0x8583, 0x8580, 0x858f, 0x85a7, 0x8595, 0x85a0, 0x858b, 0x85a3, 0x857b, 0x85a4, 0x859a, 0x859e, /* 0xee */ 0x8577, 0x857c, 0x8589, 0x85a1, 0x857a, 0x8578, 0x8557, 0x858e, 0x8596, 0x8586, 0x858d, 0x8599, 0x859d, 0x8581, 0x85a2, 0x8582, 0x8588, 0x8585, 0x8579, 0x8576, 0x8598, 0x8590, 0x859f, 0x8668, 0x87be, 0x87aa, 0x87ad, 0x87c5, 0x87b0, 0x87ac, 0x87b9, 0x87b5, 0x87bc, 0x87ae, 0x87c9, 0x87c3, 0x87c2, 0x87cc, 0x87b7, 0x87af, 0x87c4, 0x87ca, 0x87b4, 0x87b6, 0x87bf, 0x87b8, 0x87bd, 0x87de, 0x87b2, 0x8935, 0x8933, 0x893c, 0x893e, 0x8941, 0x8952, 0x8937, 0x8942, 0x89ad, 0x89af, 0x89ae, 0x89f2, 0x89f3, 0x8b1e, 0x8b18, 0x8b16, 0x8b11, 0x8b05, 0x8b0b, 0x8b22, 0x8b0f, 0x8b12, 0x8b15, 0x8b07, 0x8b0d, 0x8b08, 0x8b06, 0x8b1c, 0x8b13, 0x8b1a, 0x8c4f, 0x8c70, 0x8c72, 0x8c71, 0x8c6f, 0x8c95, 0x8c94, 0x8cf9, 0x8d6f, 0x8e4e, 0x8e4d, 0x8e53, 0x8e50, 0x8e4c, 0x8e47, 0x8f43, 0x8f40, 0x9085, 0x907e, 0x9138, 0x919a, 0x91a2, 0x919b, 0x9199, 0x919f, 0x91a1, 0x919d, 0x91a0, 0x93a1, 0x9383, 0x93af, 0x9364, 0x9356, 0x9347, 0x937c, 0x9358, 0x935c, 0x9376, 0x9349, 0x9350, 0x9351, 0x9360, 0x936d, 0x938f, 0x934c, 0x936a, 0x9379, 0x9357, 0x9355, 0x9352, 0x934f, 0x9371, 0x9377, 0x937b, 0x9361, 0x935e, 0x9363, 0x9367, 0x9380, 0x934e, 0x9359, 0x95c7, 0x95c0, 0x95c9, 0x95c3, 0x95c5, 0x95b7, 0x96ae, 0x96b0, 0x96ac, 0x9720, 0x971f, 0x9718, 0x971d, 0x9719, 0x979a, 0x97a1, 0x979c, /* 0xef */ 0x979e, 0x979d, 0x97d5, 0x97d4, 0x97f1, 0x9841, 0x9844, 0x984a, 0x9849, 0x9845, 0x9843, 0x9925, 0x992b, 0x992c, 0x992a, 0x9933, 0x9932, 0x992f, 0x992d, 0x9931, 0x9930, 0x9998, 0x99a3, 0x99a1, 0x9a02, 0x99fa, 0x99f4, 0x99f7, 0x99f9, 0x99f8, 0x99f6, 0x99fb, 0x99fd, 0x99fe, 0x99fc, 0x9a03, 0x9abe, 0x9afe, 0x9afd, 0x9b01, 0x9afc, 0x9b48, 0x9b9a, 0x9ba8, 0x9b9e, 0x9b9b, 0x9ba6, 0x9ba1, 0x9ba5, 0x9ba4, 0x9b86, 0x9ba2, 0x9ba0, 0x9baf, 0x9d33, 0x9d41, 0x9d67, 0x9d36, 0x9d2e, 0x9d2f, 0x9d31, 0x9d38, 0x9d30, 0x9d45, 0x9d42, 0x9d43, 0x9d3e, 0x9d37, 0x9d40, 0x9d3d, 0x7ff5, 0x9d2d, 0x9e8a, 0x9e89, 0x9e8d, 0x9eb0, 0x9ec8, 0x9eda, 0x9efb, 0x9eff, 0x9f24, 0x9f23, 0x9f22, 0x9f54, 0x9fa0, 0x5131, 0x512d, 0x512e, 0x5698, 0x569c, 0x5697, 0x569a, 0x569d, 0x5699, 0x5970, 0x5b3c, 0x5c69, 0x5c6a, 0x5dc0, 0x5e6d, 0x5e6e, 0x61d8, 0x61df, 0x61ed, 0x61ee, 0x61f1, 0x61ea, 0x61f0, 0x61eb, 0x61d6, 0x61e9, 0x64ff, 0x6504, 0x64fd, 0x64f8, 0x6501, 0x6503, 0x64fc, 0x6594, 0x65db, 0x66da, 0x66db, 0x66d8, 0x6ac5, 0x6ab9, 0x6abd, 0x6ae1, 0x6ac6, 0x6aba, 0x6ab6, 0x6ab7, 0x6ac7, 0x6ab4, 0x6aad, 0x6b5e, 0x6bc9, 0x6c0b, 0x7007, 0x700c, 0x700d, 0x7001, 0x7005, 0x7014, 0x700e, 0x6fff, 0x7000, 0x6ffb, 0x7026, 0x6ffc, 0x6ff7, 0x700a, 0x7201, 0x71ff, 0x71f9, 0x7203, 0x71fd, 0x7376, /* 0xf0 */ 0x74b8, 0x74c0, 0x74b5, 0x74c1, 0x74be, 0x74b6, 0x74bb, 0x74c2, 0x7514, 0x7513, 0x765c, 0x7664, 0x7659, 0x7650, 0x7653, 0x7657, 0x765a, 0x76a6, 0x76bd, 0x76ec, 0x77c2, 0x77ba, 0x78ff, 0x790c, 0x7913, 0x7914, 0x7909, 0x7910, 0x7912, 0x7911, 0x79ad, 0x79ac, 0x7a5f, 0x7c1c, 0x7c29, 0x7c19, 0x7c20, 0x7c1f, 0x7c2d, 0x7c1d, 0x7c26, 0x7c28, 0x7c22, 0x7c25, 0x7c30, 0x7e5c, 0x7e50, 0x7e56, 0x7e63, 0x7e58, 0x7e62, 0x7e5f, 0x7e51, 0x7e60, 0x7e57, 0x7e53, 0x7fb5, 0x7fb3, 0x7ff7, 0x7ff8, 0x8075, 0x81d1, 0x81d2, 0x81d0, 0x825f, 0x825e, 0x85b4, 0x85c6, 0x85c0, 0x85c3, 0x85c2, 0x85b3, 0x85b5, 0x85bd, 0x85c7, 0x85c4, 0x85bf, 0x85cb, 0x85ce, 0x85c8, 0x85c5, 0x85b1, 0x85b6, 0x85d2, 0x8624, 0x85b8, 0x85b7, 0x85be, 0x8669, 0x87e7, 0x87e6, 0x87e2, 0x87db, 0x87eb, 0x87ea, 0x87e5, 0x87df, 0x87f3, 0x87e4, 0x87d4, 0x87dc, 0x87d3, 0x87ed, 0x87d8, 0x87e3, 0x87a4, 0x87d7, 0x87d9, 0x8801, 0x87f4, 0x87e8, 0x87dd, 0x8953, 0x894b, 0x894f, 0x894c, 0x8946, 0x8950, 0x8951, 0x8949, 0x8b2a, 0x8b27, 0x8b23, 0x8b33, 0x8b30, 0x8b35, 0x8b47, 0x8b2f, 0x8b3c, 0x8b3e, 0x8b31, 0x8b25, 0x8b37, 0x8b26, 0x8b36, 0x8b2e, 0x8b24, 0x8b3b, 0x8b3d, 0x8b3a, 0x8c42, 0x8c75, 0x8c99, 0x8c98, 0x8c97, 0x8cfe, 0x8d04, 0x8d02, 0x8d00, 0x8e5c, 0x8e62, 0x8e60, 0x8e57, 0x8e56, 0x8e5e, 0x8e65, 0x8e67, /* 0xf1 */ 0x8e5b, 0x8e5a, 0x8e61, 0x8e5d, 0x8e69, 0x8e54, 0x8f46, 0x8f47, 0x8f48, 0x8f4b, 0x9128, 0x913a, 0x913b, 0x913e, 0x91a8, 0x91a5, 0x91a7, 0x91af, 0x91aa, 0x93b5, 0x938c, 0x9392, 0x93b7, 0x939b, 0x939d, 0x9389, 0x93a7, 0x938e, 0x93aa, 0x939e, 0x93a6, 0x9395, 0x9388, 0x9399, 0x939f, 0x938d, 0x93b1, 0x9391, 0x93b2, 0x93a4, 0x93a8, 0x93b4, 0x93a3, 0x93a5, 0x95d2, 0x95d3, 0x95d1, 0x96b3, 0x96d7, 0x96da, 0x5dc2, 0x96df, 0x96d8, 0x96dd, 0x9723, 0x9722, 0x9725, 0x97ac, 0x97ae, 0x97a8, 0x97ab, 0x97a4, 0x97aa, 0x97a2, 0x97a5, 0x97d7, 0x97d9, 0x97d6, 0x97d8, 0x97fa, 0x9850, 0x9851, 0x9852, 0x98b8, 0x9941, 0x993c, 0x993a, 0x9a0f, 0x9a0b, 0x9a09, 0x9a0d, 0x9a04, 0x9a11, 0x9a0a, 0x9a05, 0x9a07, 0x9a06, 0x9ac0, 0x9adc, 0x9b08, 0x9b04, 0x9b05, 0x9b29, 0x9b35, 0x9b4a, 0x9b4c, 0x9b4b, 0x9bc7, 0x9bc6, 0x9bc3, 0x9bbf, 0x9bc1, 0x9bb5, 0x9bb8, 0x9bd3, 0x9bb6, 0x9bc4, 0x9bb9, 0x9bbd, 0x9d5c, 0x9d53, 0x9d4f, 0x9d4a, 0x9d5b, 0x9d4b, 0x9d59, 0x9d56, 0x9d4c, 0x9d57, 0x9d52, 0x9d54, 0x9d5f, 0x9d58, 0x9d5a, 0x9e8e, 0x9e8c, 0x9edf, 0x9f01, 0x9f00, 0x9f16, 0x9f25, 0x9f2b, 0x9f2a, 0x9f29, 0x9f28, 0x9f4c, 0x9f55, 0x5134, 0x5135, 0x5296, 0x52f7, 0x53b4, 0x56ab, 0x56ad, 0x56a6, 0x56a7, 0x56aa, 0x56ac, 0x58da, 0x58dd, 0x58db, 0x5912, 0x5b3d, 0x5b3e, 0x5b3f, 0x5dc3, 0x5e70, /* 0xf2 */ 0x5fbf, 0x61fb, 0x6507, 0x6510, 0x650d, 0x6509, 0x650c, 0x650e, 0x6584, 0x65de, 0x65dd, 0x66de, 0x6ae7, 0x6ae0, 0x6acc, 0x6ad1, 0x6ad9, 0x6acb, 0x6adf, 0x6adc, 0x6ad0, 0x6aeb, 0x6acf, 0x6acd, 0x6ade, 0x6b60, 0x6bb0, 0x6c0c, 0x7019, 0x7027, 0x7020, 0x7016, 0x702b, 0x7021, 0x7022, 0x7023, 0x7029, 0x7017, 0x7024, 0x701c, 0x702a, 0x720c, 0x720a, 0x7207, 0x7202, 0x7205, 0x72a5, 0x72a6, 0x72a4, 0x72a3, 0x72a1, 0x74cb, 0x74c5, 0x74b7, 0x74c3, 0x7516, 0x7660, 0x77c9, 0x77ca, 0x77c4, 0x77f1, 0x791d, 0x791b, 0x7921, 0x791c, 0x7917, 0x791e, 0x79b0, 0x7a67, 0x7a68, 0x7c33, 0x7c3c, 0x7c39, 0x7c2c, 0x7c3b, 0x7cec, 0x7cea, 0x7e76, 0x7e75, 0x7e78, 0x7e70, 0x7e77, 0x7e6f, 0x7e7a, 0x7e72, 0x7e74, 0x7e68, 0x7f4b, 0x7f4a, 0x7f83, 0x7f86, 0x7fb7, 0x7ffd, 0x7ffe, 0x8078, 0x81d7, 0x81d5, 0x8264, 0x8261, 0x8263, 0x85eb, 0x85f1, 0x85ed, 0x85d9, 0x85e1, 0x85e8, 0x85da, 0x85d7, 0x85ec, 0x85f2, 0x85f8, 0x85d8, 0x85df, 0x85e3, 0x85dc, 0x85d1, 0x85f0, 0x85e6, 0x85ef, 0x85de, 0x85e2, 0x8800, 0x87fa, 0x8803, 0x87f6, 0x87f7, 0x8809, 0x880c, 0x880b, 0x8806, 0x87fc, 0x8808, 0x87ff, 0x880a, 0x8802, 0x8962, 0x895a, 0x895b, 0x8957, 0x8961, 0x895c, 0x8958, 0x895d, 0x8959, 0x8988, 0x89b7, 0x89b6, 0x89f6, 0x8b50, 0x8b48, 0x8b4a, 0x8b40, 0x8b53, 0x8b56, 0x8b54, 0x8b4b, 0x8b55, /* 0xf3 */ 0x8b51, 0x8b42, 0x8b52, 0x8b57, 0x8c43, 0x8c77, 0x8c76, 0x8c9a, 0x8d06, 0x8d07, 0x8d09, 0x8dac, 0x8daa, 0x8dad, 0x8dab, 0x8e6d, 0x8e78, 0x8e73, 0x8e6a, 0x8e6f, 0x8e7b, 0x8ec2, 0x8f52, 0x8f51, 0x8f4f, 0x8f50, 0x8f53, 0x8fb4, 0x9140, 0x913f, 0x91b0, 0x91ad, 0x93de, 0x93c7, 0x93cf, 0x93c2, 0x93da, 0x93d0, 0x93f9, 0x93ec, 0x93cc, 0x93d9, 0x93a9, 0x93e6, 0x93ca, 0x93d4, 0x93ee, 0x93e3, 0x93d5, 0x93c4, 0x93ce, 0x93c0, 0x93d2, 0x93e7, 0x957d, 0x95da, 0x95db, 0x96e1, 0x9729, 0x972b, 0x972c, 0x9728, 0x9726, 0x97b3, 0x97b7, 0x97b6, 0x97dd, 0x97de, 0x97df, 0x985c, 0x9859, 0x985d, 0x9857, 0x98bf, 0x98bd, 0x98bb, 0x98be, 0x9948, 0x9947, 0x9943, 0x99a6, 0x99a7, 0x9a1a, 0x9a15, 0x9a25, 0x9a1d, 0x9a24, 0x9a1b, 0x9a22, 0x9a20, 0x9a27, 0x9a23, 0x9a1e, 0x9a1c, 0x9a14, 0x9ac2, 0x9b0b, 0x9b0a, 0x9b0e, 0x9b0c, 0x9b37, 0x9bea, 0x9beb, 0x9be0, 0x9bde, 0x9be4, 0x9be6, 0x9be2, 0x9bf0, 0x9bd4, 0x9bd7, 0x9bec, 0x9bdc, 0x9bd9, 0x9be5, 0x9bd5, 0x9be1, 0x9bda, 0x9d77, 0x9d81, 0x9d8a, 0x9d84, 0x9d88, 0x9d71, 0x9d80, 0x9d78, 0x9d86, 0x9d8b, 0x9d8c, 0x9d7d, 0x9d6b, 0x9d74, 0x9d75, 0x9d70, 0x9d69, 0x9d85, 0x9d73, 0x9d7b, 0x9d82, 0x9d6f, 0x9d79, 0x9d7f, 0x9d87, 0x9d68, 0x9e94, 0x9e91, 0x9ec0, 0x9efc, 0x9f2d, 0x9f40, 0x9f41, 0x9f4d, 0x9f56, 0x9f57, 0x9f58, 0x5337, 0x56b2, /* 0xf4 */ 0x56b5, 0x56b3, 0x58e3, 0x5b45, 0x5dc6, 0x5dc7, 0x5eee, 0x5eef, 0x5fc0, 0x5fc1, 0x61f9, 0x6517, 0x6516, 0x6515, 0x6513, 0x65df, 0x66e8, 0x66e3, 0x66e4, 0x6af3, 0x6af0, 0x6aea, 0x6ae8, 0x6af9, 0x6af1, 0x6aee, 0x6aef, 0x703c, 0x7035, 0x702f, 0x7037, 0x7034, 0x7031, 0x7042, 0x7038, 0x703f, 0x703a, 0x7039, 0x7040, 0x703b, 0x7033, 0x7041, 0x7213, 0x7214, 0x72a8, 0x737d, 0x737c, 0x74ba, 0x76ab, 0x76aa, 0x76be, 0x76ed, 0x77cc, 0x77ce, 0x77cf, 0x77cd, 0x77f2, 0x7925, 0x7923, 0x7927, 0x7928, 0x7924, 0x7929, 0x79b2, 0x7a6e, 0x7a6c, 0x7a6d, 0x7af7, 0x7c49, 0x7c48, 0x7c4a, 0x7c47, 0x7c45, 0x7cee, 0x7e7b, 0x7e7e, 0x7e81, 0x7e80, 0x7fba, 0x7fff, 0x8079, 0x81db, 0x81d9, 0x820b, 0x8268, 0x8269, 0x8622, 0x85ff, 0x8601, 0x85fe, 0x861b, 0x8600, 0x85f6, 0x8604, 0x8609, 0x8605, 0x860c, 0x85fd, 0x8819, 0x8810, 0x8811, 0x8817, 0x8813, 0x8816, 0x8963, 0x8966, 0x89b9, 0x89f7, 0x8b60, 0x8b6a, 0x8b5d, 0x8b68, 0x8b63, 0x8b65, 0x8b67, 0x8b6d, 0x8dae, 0x8e86, 0x8e88, 0x8e84, 0x8f59, 0x8f56, 0x8f57, 0x8f55, 0x8f58, 0x8f5a, 0x908d, 0x9143, 0x9141, 0x91b7, 0x91b5, 0x91b2, 0x91b3, 0x940b, 0x9413, 0x93fb, 0x9420, 0x940f, 0x9414, 0x93fe, 0x9415, 0x9410, 0x9428, 0x9419, 0x940d, 0x93f5, 0x9400, 0x93f7, 0x9407, 0x940e, 0x9416, 0x9412, 0x93fa, 0x9409, 0x93f8, 0x940a, 0x93ff, /* 0xf5 */ 0x93fc, 0x940c, 0x93f6, 0x9411, 0x9406, 0x95de, 0x95e0, 0x95df, 0x972e, 0x972f, 0x97b9, 0x97bb, 0x97fd, 0x97fe, 0x9860, 0x9862, 0x9863, 0x985f, 0x98c1, 0x98c2, 0x9950, 0x994e, 0x9959, 0x994c, 0x994b, 0x9953, 0x9a32, 0x9a34, 0x9a31, 0x9a2c, 0x9a2a, 0x9a36, 0x9a29, 0x9a2e, 0x9a38, 0x9a2d, 0x9ac7, 0x9aca, 0x9ac6, 0x9b10, 0x9b12, 0x9b11, 0x9c0b, 0x9c08, 0x9bf7, 0x9c05, 0x9c12, 0x9bf8, 0x9c40, 0x9c07, 0x9c0e, 0x9c06, 0x9c17, 0x9c14, 0x9c09, 0x9d9f, 0x9d99, 0x9da4, 0x9d9d, 0x9d92, 0x9d98, 0x9d90, 0x9d9b, 0x9da0, 0x9d94, 0x9d9c, 0x9daa, 0x9d97, 0x9da1, 0x9d9a, 0x9da2, 0x9da8, 0x9d9e, 0x9da3, 0x9dbf, 0x9da9, 0x9d96, 0x9da6, 0x9da7, 0x9e99, 0x9e9b, 0x9e9a, 0x9ee5, 0x9ee4, 0x9ee7, 0x9ee6, 0x9f30, 0x9f2e, 0x9f5b, 0x9f60, 0x9f5e, 0x9f5d, 0x9f59, 0x9f91, 0x513a, 0x5139, 0x5298, 0x5297, 0x56c3, 0x56bd, 0x56be, 0x5b48, 0x5b47, 0x5dcb, 0x5dcf, 0x5ef1, 0x61fd, 0x651b, 0x6b02, 0x6afc, 0x6b03, 0x6af8, 0x6b00, 0x7043, 0x7044, 0x704a, 0x7048, 0x7049, 0x7045, 0x7046, 0x721d, 0x721a, 0x7219, 0x737e, 0x7517, 0x766a, 0x77d0, 0x792d, 0x7931, 0x792f, 0x7c54, 0x7c53, 0x7cf2, 0x7e8a, 0x7e87, 0x7e88, 0x7e8b, 0x7e86, 0x7e8d, 0x7f4d, 0x7fbb, 0x8030, 0x81dd, 0x8618, 0x862a, 0x8626, 0x861f, 0x8623, 0x861c, 0x8619, 0x8627, 0x862e, 0x8621, 0x8620, 0x8629, 0x861e, 0x8625, /* 0xf6 */ 0x8829, 0x881d, 0x881b, 0x8820, 0x8824, 0x881c, 0x882b, 0x884a, 0x896d, 0x8969, 0x896e, 0x896b, 0x89fa, 0x8b79, 0x8b78, 0x8b45, 0x8b7a, 0x8b7b, 0x8d10, 0x8d14, 0x8daf, 0x8e8e, 0x8e8c, 0x8f5e, 0x8f5b, 0x8f5d, 0x9146, 0x9144, 0x9145, 0x91b9, 0x943f, 0x943b, 0x9436, 0x9429, 0x943d, 0x943c, 0x9430, 0x9439, 0x942a, 0x9437, 0x942c, 0x9440, 0x9431, 0x95e5, 0x95e4, 0x95e3, 0x9735, 0x973a, 0x97bf, 0x97e1, 0x9864, 0x98c9, 0x98c6, 0x98c0, 0x9958, 0x9956, 0x9a39, 0x9a3d, 0x9a46, 0x9a44, 0x9a42, 0x9a41, 0x9a3a, 0x9a3f, 0x9acd, 0x9b15, 0x9b17, 0x9b18, 0x9b16, 0x9b3a, 0x9b52, 0x9c2b, 0x9c1d, 0x9c1c, 0x9c2c, 0x9c23, 0x9c28, 0x9c29, 0x9c24, 0x9c21, 0x9db7, 0x9db6, 0x9dbc, 0x9dc1, 0x9dc7, 0x9dca, 0x9dcf, 0x9dbe, 0x9dc5, 0x9dc3, 0x9dbb, 0x9db5, 0x9dce, 0x9db9, 0x9dba, 0x9dac, 0x9dc8, 0x9db1, 0x9dad, 0x9dcc, 0x9db3, 0x9dcd, 0x9db2, 0x9e7a, 0x9e9c, 0x9eeb, 0x9eee, 0x9eed, 0x9f1b, 0x9f18, 0x9f1a, 0x9f31, 0x9f4e, 0x9f65, 0x9f64, 0x9f92, 0x4eb9, 0x56c6, 0x56c5, 0x56cb, 0x5971, 0x5b4b, 0x5b4c, 0x5dd5, 0x5dd1, 0x5ef2, 0x6521, 0x6520, 0x6526, 0x6522, 0x6b0b, 0x6b08, 0x6b09, 0x6c0d, 0x7055, 0x7056, 0x7057, 0x7052, 0x721e, 0x721f, 0x72a9, 0x737f, 0x74d8, 0x74d5, 0x74d9, 0x74d7, 0x766d, 0x76ad, 0x7935, 0x79b4, 0x7a70, 0x7a71, 0x7c57, 0x7c5c, 0x7c59, 0x7c5b, 0x7c5a, /* 0xf7 */ 0x7cf4, 0x7cf1, 0x7e91, 0x7f4f, 0x7f87, 0x81de, 0x826b, 0x8634, 0x8635, 0x8633, 0x862c, 0x8632, 0x8636, 0x882c, 0x8828, 0x8826, 0x882a, 0x8825, 0x8971, 0x89bf, 0x89be, 0x89fb, 0x8b7e, 0x8b84, 0x8b82, 0x8b86, 0x8b85, 0x8b7f, 0x8d15, 0x8e95, 0x8e94, 0x8e9a, 0x8e92, 0x8e90, 0x8e96, 0x8e97, 0x8f60, 0x8f62, 0x9147, 0x944c, 0x9450, 0x944a, 0x944b, 0x944f, 0x9447, 0x9445, 0x9448, 0x9449, 0x9446, 0x973f, 0x97e3, 0x986a, 0x9869, 0x98cb, 0x9954, 0x995b, 0x9a4e, 0x9a53, 0x9a54, 0x9a4c, 0x9a4f, 0x9a48, 0x9a4a, 0x9a49, 0x9a52, 0x9a50, 0x9ad0, 0x9b19, 0x9b2b, 0x9b3b, 0x9b56, 0x9b55, 0x9c46, 0x9c48, 0x9c3f, 0x9c44, 0x9c39, 0x9c33, 0x9c41, 0x9c3c, 0x9c37, 0x9c34, 0x9c32, 0x9c3d, 0x9c36, 0x9ddb, 0x9dd2, 0x9dde, 0x9dda, 0x9dcb, 0x9dd0, 0x9ddc, 0x9dd1, 0x9ddf, 0x9de9, 0x9dd9, 0x9dd8, 0x9dd6, 0x9df5, 0x9dd5, 0x9ddd, 0x9eb6, 0x9ef0, 0x9f35, 0x9f33, 0x9f32, 0x9f42, 0x9f6b, 0x9f95, 0x9fa2, 0x513d, 0x5299, 0x58e8, 0x58e7, 0x5972, 0x5b4d, 0x5dd8, 0x882f, 0x5f4f, 0x6201, 0x6203, 0x6204, 0x6529, 0x6525, 0x6596, 0x66eb, 0x6b11, 0x6b12, 0x6b0f, 0x6bca, 0x705b, 0x705a, 0x7222, 0x7382, 0x7381, 0x7383, 0x7670, 0x77d4, 0x7c67, 0x7c66, 0x7e95, 0x826c, 0x863a, 0x8640, 0x8639, 0x863c, 0x8631, 0x863b, 0x863e, 0x8830, 0x8832, 0x882e, 0x8833, 0x8976, 0x8974, 0x8973, 0x89fe, /* 0xf8 */ 0x8b8c, 0x8b8e, 0x8b8b, 0x8b88, 0x8c45, 0x8d19, 0x8e98, 0x8f64, 0x8f63, 0x91bc, 0x9462, 0x9455, 0x945d, 0x9457, 0x945e, 0x97c4, 0x97c5, 0x9800, 0x9a56, 0x9a59, 0x9b1e, 0x9b1f, 0x9b20, 0x9c52, 0x9c58, 0x9c50, 0x9c4a, 0x9c4d, 0x9c4b, 0x9c55, 0x9c59, 0x9c4c, 0x9c4e, 0x9dfb, 0x9df7, 0x9def, 0x9de3, 0x9deb, 0x9df8, 0x9de4, 0x9df6, 0x9de1, 0x9dee, 0x9de6, 0x9df2, 0x9df0, 0x9de2, 0x9dec, 0x9df4, 0x9df3, 0x9de8, 0x9ded, 0x9ec2, 0x9ed0, 0x9ef2, 0x9ef3, 0x9f06, 0x9f1c, 0x9f38, 0x9f37, 0x9f36, 0x9f43, 0x9f4f, 0x9f71, 0x9f70, 0x9f6e, 0x9f6f, 0x56d3, 0x56cd, 0x5b4e, 0x5c6d, 0x652d, 0x66ed, 0x66ee, 0x6b13, 0x705f, 0x7061, 0x705d, 0x7060, 0x7223, 0x74db, 0x74e5, 0x77d5, 0x7938, 0x79b7, 0x79b6, 0x7c6a, 0x7e97, 0x7f89, 0x826d, 0x8643, 0x8838, 0x8837, 0x8835, 0x884b, 0x8b94, 0x8b95, 0x8e9e, 0x8e9f, 0x8ea0, 0x8e9d, 0x91be, 0x91bd, 0x91c2, 0x946b, 0x9468, 0x9469, 0x96e5, 0x9746, 0x9743, 0x9747, 0x97c7, 0x97e5, 0x9a5e, 0x9ad5, 0x9b59, 0x9c63, 0x9c67, 0x9c66, 0x9c62, 0x9c5e, 0x9c60, 0x9e02, 0x9dfe, 0x9e07, 0x9e03, 0x9e06, 0x9e05, 0x9e00, 0x9e01, 0x9e09, 0x9dff, 0x9dfd, 0x9e04, 0x9ea0, 0x9f1e, 0x9f46, 0x9f74, 0x9f75, 0x9f76, 0x56d4, 0x652e, 0x65b8, 0x6b18, 0x6b19, 0x6b17, 0x6b1a, 0x7062, 0x7226, 0x72aa, 0x77d8, 0x77d9, 0x7939, 0x7c69, 0x7c6b, 0x7cf6, 0x7e9a, /* 0xf9 */ 0x7e98, 0x7e9b, 0x7e99, 0x81e0, 0x81e1, 0x8646, 0x8647, 0x8648, 0x8979, 0x897a, 0x897c, 0x897b, 0x89ff, 0x8b98, 0x8b99, 0x8ea5, 0x8ea4, 0x8ea3, 0x946e, 0x946d, 0x946f, 0x9471, 0x9473, 0x9749, 0x9872, 0x995f, 0x9c68, 0x9c6e, 0x9c6d, 0x9e0b, 0x9e0d, 0x9e10, 0x9e0f, 0x9e12, 0x9e11, 0x9ea1, 0x9ef5, 0x9f09, 0x9f47, 0x9f78, 0x9f7b, 0x9f7a, 0x9f79, 0x571e, 0x7066, 0x7c6f, 0x883c, 0x8db2, 0x8ea6, 0x91c3, 0x9474, 0x9478, 0x9476, 0x9475, 0x9a60, 0x9c74, 0x9c73, 0x9c71, 0x9c75, 0x9e14, 0x9e13, 0x9ef6, 0x9f0a, 0x9fa4, 0x7068, 0x7065, 0x7cf7, 0x866a, 0x883e, 0x883d, 0x883f, 0x8b9e, 0x8c9c, 0x8ea9, 0x8ec9, 0x974b, 0x9873, 0x9874, 0x98cc, 0x9961, 0x99ab, 0x9a64, 0x9a66, 0x9a67, 0x9b24, 0x9e15, 0x9e17, 0x9f48, 0x6207, 0x6b1e, 0x7227, 0x864c, 0x8ea8, 0x9482, 0x9480, 0x9481, 0x9a69, 0x9a68, 0x9b2e, 0x9e19, 0x7229, 0x864b, 0x8b9f, 0x9483, 0x9c79, 0x9eb7, 0x7675, 0x9a6b, 0x9c7a, 0x9e1d, 0x7069, 0x706a, 0x9ea4, 0x9f7e, 0x9f49, 0x9f98, }; static int big5_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c1 = s[0]; if ((c1 >= 0xa1 && c1 <= 0xc7) || (c1 >= 0xc9 && c1 <= 0xf9)) { if (n >= 2) { unsigned char c2 = s[1]; if ((c2 >= 0x40 && c2 < 0x7f) || (c2 >= 0xa1 && c2 < 0xff)) { unsigned int i = 157 * (c1 - 0xa1) + (c2 - (c2 >= 0xa1 ? 0x62 : 0x40)); unsigned short wc = 0xfffd; if (i < 6280) { if (i < 6121) wc = big5_2uni_pagea1[i]; } else { if (i < 13932) wc = big5_2uni_pagec9[i-6280]; } if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 2; } } return RET_ILSEQ; } return RET_TOOFEW(0); } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned short big5_2charset[13703] = { 0xa246, 0xa247, 0xa244, 0xa1b1, 0xa258, 0xa1d3, 0xa150, 0xa1d1, 0xa1d2, 0xa3be, 0xa3bc, 0xa3bd, 0xa3bf, 0xa3bb, 0xa344, 0xa345, 0xa346, 0xa347, 0xa348, 0xa349, 0xa34a, 0xa34b, 0xa34c, 0xa34d, 0xa34e, 0xa34f, 0xa350, 0xa351, 0xa352, 0xa353, 0xa354, 0xa355, 0xa356, 0xa357, 0xa358, 0xa359, 0xa35a, 0xa35b, 0xa35c, 0xa35d, 0xa35e, 0xa35f, 0xa360, 0xa361, 0xa362, 0xa363, 0xa364, 0xa365, 0xa366, 0xa367, 0xa368, 0xa369, 0xa36a, 0xa36b, 0xa36c, 0xa36d, 0xa36e, 0xa36f, 0xa370, 0xa371, 0xa372, 0xa373, 0xc7b3, 0xc7b1, 0xc7b2, 0xc7b4, 0xc7b5, 0xc7b6, 0xc7b7, 0xc7b8, 0xc7b9, 0xc7ba, 0xc7bb, 0xc7bc, 0xc7bd, 0xc7be, 0xc7bf, 0xc7c0, 0xc7c1, 0xc7c2, 0xc7c3, 0xc7c4, 0xc7c5, 0xc7c6, 0xc7c7, 0xc7c8, 0xc7c9, 0xc7ca, 0xc7cb, 0xc7cc, 0xc7cd, 0xc7cf, 0xc7d0, 0xc7d1, 0xc7d2, 0xc7d3, 0xc7d4, 0xc7d5, 0xc7d6, 0xc7d7, 0xc7d8, 0xc7d9, 0xc7da, 0xc7db, 0xc7dc, 0xc7dd, 0xc7de, 0xc7df, 0xc7e0, 0xc7e1, 0xc7e2, 0xc7e3, 0xc7e4, 0xc7e5, 0xc7e6, 0xc7e7, 0xc7e8, 0xc7ce, 0xa156, 0xa158, 0xa1a5, 0xa1a6, 0xa1a7, 0xa1a8, 0xa145, 0xa14c, 0xa14b, 0xa1ac, 0xa1ab, 0xa1b0, 0xa1c2, 0xa24a, 0xa1c1, 0xa24b, 0xa2b9, 0xa2ba, 0xa2bb, 0xa2bc, 0xa2bd, 0xa2be, 0xa2bf, 0xa2c0, 0xa2c1, 0xa2c2, 0xa1f6, 0xa1f4, 0xa1f7, 0xa1f5, 0xa1f8, 0xa1f9, 0xa1fb, 0xa1fa, 0xa1d4, 0xa1db, 0xa1e8, 0xa1e7, 0xa1fd, 0xa1fc, 0xa1e4, 0xa1e5, 0xa1ec, 0xa1ed, 0xa1ef, 0xa1ee, 0xa1e3, 0xa1dc, 0xa1da, 0xa1dd, 0xa1d8, 0xa1d9, 0xa1e6, 0xa1e9, 0xc7e9, 0xc7ea, 0xc7eb, 0xc7ec, 0xc7ed, 0xc7ee, 0xc7ef, 0xc7f0, 0xc7f1, 0xc7f2, 0xc7f3, 0xc7f4, 0xc7f5, 0xc7f6, 0xc7f7, 0xc7f8, 0xc7f9, 0xc7fa, 0xc7fb, 0xc7fc, 0xa277, 0xa278, 0xa27a, 0xa27b, 0xa27c, 0xa27d, 0xa275, 0xa274, 0xa273, 0xa272, 0xa271, 0xa2a4, 0xa2a5, 0xa2a7, 0xa2a6, 0xa27e, 0xa2a1, 0xa2a3, 0xa2a2, 0xa2ac, 0xa2ad, 0xa2ae, 0xa262, 0xa263, 0xa264, 0xa265, 0xa266, 0xa267, 0xa268, 0xa269, 0xa270, 0xa26f, 0xa26e, 0xa26d, 0xa26c, 0xa26b, 0xa26a, 0xa276, 0xa279, 0xa1bd, 0xa1bc, 0xa1b6, 0xa1b5, 0xa1bf, 0xa1be, 0xa1bb, 0xa1ba, 0xa1b3, 0xa1b7, 0xa1b4, 0xa2a8, 0xa2a9, 0xa2ab, 0xa2aa, 0xa1b9, 0xa1b8, 0xa1f3, 0xa1f0, 0xa1f2, 0xa1f1, 0xa140, 0xa142, 0xa143, 0xa1b2, 0xc6a4, 0xa171, 0xa172, 0xa16d, 0xa16e, 0xa175, 0xa176, 0xa179, 0xa17a, 0xa169, 0xa16a, 0xa245, 0xa165, 0xa166, 0xa1a9, 0xa1aa, 0xa2c3, 0xa2c4, 0xa2c5, 0xa2c6, 0xa2c7, 0xa2c8, 0xa2c9, 0xa2ca, 0xa2cb, 0xc6a5, 0xc6a6, 0xc6a7, 0xc6a8, 0xc6a9, 0xc6aa, 0xc6ab, 0xc6ac, 0xc6ad, 0xc6ae, 0xc6af, 0xc6b0, 0xc6b1, 0xc6b2, 0xc6b3, 0xc6b4, 0xc6b5, 0xc6b6, 0xc6b7, 0xc6b8, 0xc6b9, 0xc6ba, 0xc6bb, 0xc6bc, 0xc6bd, 0xc6be, 0xc6bf, 0xc6c0, 0xc6c1, 0xc6c2, 0xc6c3, 0xc6c4, 0xc6c5, 0xc6c6, 0xc6c7, 0xc6c8, 0xc6c9, 0xc6ca, 0xc6cb, 0xc6cc, 0xc6cd, 0xc6ce, 0xc6cf, 0xc6d0, 0xc6d1, 0xc6d2, 0xc6d3, 0xc6d4, 0xc6d5, 0xc6d6, 0xc6d7, 0xc6d8, 0xc6d9, 0xc6da, 0xc6db, 0xc6dc, 0xc6dd, 0xc6de, 0xc6df, 0xc6e0, 0xc6e1, 0xc6e2, 0xc6e3, 0xc6e4, 0xc6e5, 0xc6e6, 0xc6e7, 0xc6e8, 0xc6e9, 0xc6ea, 0xc6eb, 0xc6ec, 0xc6ed, 0xc6ee, 0xc6ef, 0xc6f0, 0xc6f1, 0xc6f2, 0xc6f3, 0xc6f4, 0xc6f5, 0xc6f6, 0xc6f7, 0xc6a2, 0xc6a3, 0xc6f8, 0xc6f9, 0xc6fa, 0xc6fb, 0xc6fc, 0xc6fd, 0xc6fe, 0xc740, 0xc741, 0xc742, 0xc743, 0xc744, 0xc745, 0xc746, 0xc747, 0xc748, 0xc749, 0xc74a, 0xc74b, 0xc74c, 0xc74d, 0xc74e, 0xc74f, 0xc750, 0xc751, 0xc752, 0xc753, 0xc754, 0xc755, 0xc756, 0xc757, 0xc758, 0xc759, 0xc75a, 0xc75b, 0xc75c, 0xc75d, 0xc75e, 0xc75f, 0xc760, 0xc761, 0xc762, 0xc763, 0xc764, 0xc765, 0xc766, 0xc767, 0xc768, 0xc769, 0xc76a, 0xc76b, 0xc76c, 0xc76d, 0xc76e, 0xc76f, 0xc770, 0xc771, 0xc772, 0xc773, 0xc774, 0xc775, 0xc776, 0xc777, 0xc778, 0xc779, 0xc77a, 0xc77b, 0xc77c, 0xc77d, 0xc77e, 0xc7a1, 0xc7a2, 0xc7a3, 0xc7a4, 0xc7a5, 0xc7a6, 0xc7a7, 0xc7a8, 0xc7a9, 0xc7aa, 0xc7ab, 0xc7ac, 0xc7ad, 0xc7ae, 0xc7af, 0xc7b0, 0xc6a1, 0xa374, 0xa375, 0xa376, 0xa377, 0xa378, 0xa379, 0xa37a, 0xa37b, 0xa37c, 0xa37d, 0xa37e, 0xa3a1, 0xa3a2, 0xa3a3, 0xa3a4, 0xa3a5, 0xa3a6, 0xa3a7, 0xa3a8, 0xa3a9, 0xa3aa, 0xa3ab, 0xa3ac, 0xa3ad, 0xa3ae, 0xa3af, 0xa3b0, 0xa3b1, 0xa3b2, 0xa3b3, 0xa3b4, 0xa3b5, 0xa3b6, 0xa3b7, 0xa3b8, 0xa3b9, 0xa3ba, 0xa1c0, 0xa255, 0xa256, 0xa250, 0xa251, 0xa252, 0xa254, 0xa257, 0xa253, 0xa1eb, 0xa1ea, 0xa24f, 0xa440, 0xa442, 0xa443, 0xc945, 0xa456, 0xa454, 0xa457, 0xa455, 0xc946, 0xa4a3, 0xc94f, 0xc94d, 0xa4a2, 0xa4a1, 0xa542, 0xa541, 0xa540, 0xa543, 0xa4fe, 0xa5e0, 0xa5e1, 0xa8c3, 0xa458, 0xa4a4, 0xc950, 0xa4a5, 0xc963, 0xa6ea, 0xcbb1, 0xa459, 0xa4a6, 0xa544, 0xc964, 0xc940, 0xa444, 0xa45b, 0xc947, 0xa45c, 0xa4a7, 0xa545, 0xa547, 0xa546, 0xa5e2, 0xa5e3, 0xa8c4, 0xadbc, 0xa441, 0xc941, 0xa445, 0xa45e, 0xa45d, 0xa5e4, 0xa8c5, 0xb0ae, 0xd44b, 0xb6c3, 0xdcb1, 0xdcb2, 0xa446, 0xa4a9, 0xa8c6, 0xa447, 0xc948, 0xa45f, 0xa4aa, 0xa4ac, 0xc951, 0xa4ad, 0xa4ab, 0xa5e5, 0xa8c7, 0xa8c8, 0xab45, 0xa460, 0xa4ae, 0xa5e6, 0xa5e8, 0xa5e7, 0xa6eb, 0xa8c9, 0xa8ca, 0xab46, 0xab47, 0xadbd, 0xdcb3, 0xf6d6, 0xa448, 0xa4b0, 0xa4af, 0xc952, 0xa4b1, 0xa4b7, 0xa4b2, 0xa4b3, 0xc954, 0xc953, 0xa4b5, 0xa4b6, 0xa4b4, 0xa54a, 0xa54b, 0xa54c, 0xa54d, 0xa549, 0xa550, 0xc96a, 0xc966, 0xc969, 0xa551, 0xa561, 0xc968, 0xa54e, 0xa54f, 0xa548, 0xc965, 0xc967, 0xa5f5, 0xc9b0, 0xa5f2, 0xa5f6, 0xc9ba, 0xc9ae, 0xa5f3, 0xc9b2, 0xa5f4, 0xa5f7, 0xa5e9, 0xc9b1, 0xa5f8, 0xc9b5, 0xc9b9, 0xc9b6, 0xc9b3, 0xa5ea, 0xa5ec, 0xa5f9, 0xa5ee, 0xc9ab, 0xa5f1, 0xa5ef, 0xa5f0, 0xc9bb, 0xc9b8, 0xc9af, 0xa5ed, 0xc9ac, 0xa5eb, 0xc9b4, 0xc9b7, 0xc9ad, 0xca66, 0xa742, 0xa6f4, 0xca67, 0xa6f1, 0xa744, 0xa6f9, 0xa6f8, 0xca5b, 0xa6fc, 0xa6f7, 0xca60, 0xca68, 0xca64, 0xa6fa, 0xa6fd, 0xa6ee, 0xa747, 0xca5d, 0xcbbd, 0xa6ec, 0xa743, 0xa6ed, 0xa6f5, 0xa6f6, 0xca62, 0xca5e, 0xa6fb, 0xa6f3, 0xca5a, 0xa6ef, 0xca65, 0xa745, 0xa748, 0xa6f2, 0xa740, 0xa746, 0xa6f0, 0xca63, 0xa741, 0xca69, 0xca5c, 0xa6fe, 0xca5f, 0xca61, 0xa8d8, 0xcbbf, 0xcbcb, 0xa8d0, 0xcbcc, 0xa8cb, 0xa8d5, 0xa8ce, 0xcbb9, 0xa8d6, 0xcbb8, 0xcbbc, 0xcbc3, 0xcbc1, 0xa8de, 0xa8d9, 0xcbb3, 0xcbb5, 0xa8db, 0xa8cf, 0xcbb6, 0xcbc2, 0xcbc9, 0xa8d4, 0xcbbb, 0xcbb4, 0xa8d3, 0xcbb7, 0xa8d7, 0xcbba, 0xa8d2, 0xa8cd, 0xa8dc, 0xcbc4, 0xa8dd, 0xcbc8, 0xcbc6, 0xcbca, 0xa8da, 0xcbbe, 0xcbb2, 0xcbc0, 0xa8d1, 0xcbc5, 0xa8cc, 0xcbc7, 0xab56, 0xab4a, 0xcde0, 0xcde8, 0xab49, 0xab51, 0xab5d, 0xcdee, 0xcdec, 0xcde7, 0xab4b, 0xcded, 0xcde3, 0xab59, 0xab50, 0xab58, 0xcdde, 0xcdea, 0xcde1, 0xab54, 0xcde2, 0xcddd, 0xab5b, 0xab4e, 0xab57, 0xab4d, 0xcddf, 0xcde4, 0xcdeb, 0xab55, 0xab52, 0xcde6, 0xab5a, 0xcde9, 0xcde5, 0xab4f, 0xab5c, 0xab53, 0xab4c, 0xab48, 0xcdef, 0xadd7, 0xadc1, 0xadd1, 0xadd6, 0xd0d0, 0xd0cf, 0xd0d4, 0xd0d5, 0xadc4, 0xadcd, 0xadda, 0xadce, 0xd0c9, 0xadc7, 0xd0ca, 0xaddc, 0xadd3, 0xadbe, 0xadbf, 0xd0dd, 0xb0bf, 0xadcc, 0xadcb, 0xd0cb, 0xadcf, 0xd45b, 0xadc6, 0xd0d6, 0xadd5, 0xadd4, 0xadca, 0xd0ce, 0xd0d7, 0xd0c8, 0xadc9, 0xd0d8, 0xadd2, 0xd0cc, 0xadc0, 0xadc3, 0xadc2, 0xd0d9, 0xadd0, 0xadc5, 0xadd9, 0xaddb, 0xd0d3, 0xadd8, 0xd0db, 0xd0cd, 0xd0dc, 0xd0d1, 0xd0da, 0xd0d2, 0xadc8, 0xd463, 0xd457, 0xb0b3, 0xd45c, 0xd462, 0xb0b2, 0xd455, 0xb0b6, 0xd459, 0xd452, 0xb0b4, 0xd456, 0xb0b9, 0xb0be, 0xd467, 0xd451, 0xb0ba, 0xd466, 0xb0b5, 0xd458, 0xb0b1, 0xd453, 0xd44f, 0xd45d, 0xd450, 0xd44e, 0xd45a, 0xd460, 0xd461, 0xb0b7, 0xd85b, 0xd45e, 0xd44d, 0xd45f, 0xb0c1, 0xd464, 0xb0c0, 0xd44c, 0xd454, 0xd465, 0xb0bc, 0xb0bb, 0xb0b8, 0xb0bd, 0xb0af, 0xb0b0, 0xb3c8, 0xd85e, 0xd857, 0xb3c5, 0xd85f, 0xd855, 0xd858, 0xb3c4, 0xd859, 0xb3c7, 0xd85d, 0xd853, 0xd852, 0xb3c9, 0xb3ca, 0xb3c6, 0xb3cb, 0xd851, 0xd85c, 0xd85a, 0xd854, 0xb3c3, 0xd856, 0xb6ca, 0xb6c4, 0xdcb7, 0xb6cd, 0xdcbd, 0xdcc0, 0xb6c6, 0xb6c7, 0xdcba, 0xb6c5, 0xdcc3, 0xb6cb, 0xdcc4, 0xdcbf, 0xb6cc, 0xdcb4, 0xb6c9, 0xdcb5, 0xdcbe, 0xdcbc, 0xdcb8, 0xb6c8, 0xdcb6, 0xb6ce, 0xdcbb, 0xdcc2, 0xdcb9, 0xdcc1, 0xb9b6, 0xb9b3, 0xb9b4, 0xe0f9, 0xe0f1, 0xb9b2, 0xb9af, 0xe0f2, 0xb9b1, 0xe0f5, 0xe0f7, 0xe0fe, 0xe0fd, 0xe0f8, 0xb9ae, 0xe0f0, 0xb9ac, 0xe0f3, 0xb9b7, 0xe0f6, 0xe0fa, 0xb9b0, 0xb9ad, 0xe0fc, 0xe0fb, 0xb9b5, 0xe0f4, 0xbbf8, 0xe4ec, 0xe4e9, 0xbbf9, 0xbbf7, 0xe4f0, 0xe4ed, 0xe4e6, 0xbbf6, 0xbbfa, 0xe4e7, 0xbbf5, 0xbbfd, 0xe4ea, 0xe4eb, 0xbbfb, 0xbbfc, 0xe4f1, 0xe4ee, 0xe4ef, 0xbeaa, 0xe8f8, 0xbea7, 0xe8f5, 0xbea9, 0xbeab, 0xe8f6, 0xbea8, 0xe8f7, 0xe8f4, 0xc076, 0xecbd, 0xc077, 0xecbb, 0xecbc, 0xecba, 0xecb9, 0xecbe, 0xc075, 0xefb8, 0xefb9, 0xe4e8, 0xefb7, 0xc078, 0xc35f, 0xf1eb, 0xf1ec, 0xc4d7, 0xc4d8, 0xf5c1, 0xf5c0, 0xc56c, 0xc56b, 0xf7d0, 0xa449, 0xa461, 0xa4b9, 0xa4b8, 0xa553, 0xa552, 0xa5fc, 0xa5fb, 0xa5fd, 0xa5fa, 0xa74a, 0xa749, 0xa74b, 0xa8e0, 0xa8df, 0xa8e1, 0xab5e, 0xa259, 0xd0de, 0xa25a, 0xb0c2, 0xa25c, 0xa25b, 0xd860, 0xa25d, 0xb9b8, 0xa25e, 0xa44a, 0xa4ba, 0xa5fe, 0xa8e2, 0xa44b, 0xa4bd, 0xa4bb, 0xa4bc, 0xa640, 0xa74c, 0xa8e4, 0xa8e3, 0xa8e5, 0xaddd, 0xbeac, 0xc94e, 0xa554, 0xa555, 0xa641, 0xca6a, 0xab60, 0xab5f, 0xd0e0, 0xd0df, 0xb0c3, 0xa4be, 0xc955, 0xcbcd, 0xab61, 0xade0, 0xadde, 0xaddf, 0xbead, 0xa556, 0xa642, 0xc9bc, 0xa74d, 0xa74e, 0xca6b, 0xcbce, 0xa8e6, 0xcbcf, 0xd0e2, 0xd0e3, 0xade3, 0xd0e4, 0xd0e1, 0xade4, 0xade2, 0xade1, 0xd0e5, 0xd468, 0xd861, 0xdcc5, 0xe140, 0xbbfe, 0xbeae, 0xe8f9, 0xa44c, 0xa45a, 0xb0c4, 0xb3cd, 0xb9b9, 0xc942, 0xa4bf, 0xa559, 0xa557, 0xa558, 0xa8e7, 0xa44d, 0xa44e, 0xa462, 0xa4c0, 0xa4c1, 0xa4c2, 0xc9be, 0xa55a, 0xc96b, 0xa646, 0xc9bf, 0xa644, 0xa645, 0xc9bd, 0xa647, 0xa643, 0xca6c, 0xaaec, 0xca6d, 0xca6e, 0xa750, 0xa74f, 0xa753, 0xa751, 0xa752, 0xa8ed, 0xa8ec, 0xcbd4, 0xcbd1, 0xcbd2, 0xcbd0, 0xa8ee, 0xa8ea, 0xa8e9, 0xa8eb, 0xa8e8, 0xa8ef, 0xab63, 0xcdf0, 0xcbd3, 0xab68, 0xcdf1, 0xab64, 0xab67, 0xab66, 0xab65, 0xab62, 0xd0e8, 0xade7, 0xd0eb, 0xade5, 0xd0e7, 0xade8, 0xade6, 0xade9, 0xd0e9, 0xd0ea, 0xd0e6, 0xd0ec, 0xb3d1, 0xb0c5, 0xd469, 0xd46b, 0xd46a, 0xd46c, 0xb0c6, 0xb3ce, 0xb3cf, 0xb3d0, 0xb6d0, 0xdcc7, 0xdcc6, 0xdcc8, 0xdcc9, 0xb6d1, 0xb6cf, 0xe141, 0xe142, 0xb9bb, 0xb9ba, 0xe35a, 0xbc40, 0xbc41, 0xbc42, 0xbc44, 0xe4f2, 0xe4f3, 0xbc43, 0xbeaf, 0xbeb0, 0xf1ed, 0xf5c3, 0xf5c2, 0xf7d1, 0xa44f, 0xa55c, 0xa55b, 0xa648, 0xc9c0, 0xa755, 0xa756, 0xa754, 0xa757, 0xca6f, 0xca70, 0xa8f1, 0xcbd5, 0xa8f0, 0xcdf2, 0xab6c, 0xcdf3, 0xab6b, 0xab69, 0xab6a, 0xd0ed, 0xb0c7, 0xd46e, 0xb0ca, 0xd46d, 0xb1e5, 0xb0c9, 0xb0c8, 0xb3d4, 0xb3d3, 0xb3d2, 0xb6d2, 0xb6d5, 0xb6d6, 0xb6d4, 0xb6d3, 0xe143, 0xe144, 0xe4f5, 0xbc45, 0xe4f4, 0xbeb1, 0xecbf, 0xc079, 0xf1ee, 0xc455, 0xa463, 0xa4c3, 0xc956, 0xa4c4, 0xa4c5, 0xa55d, 0xa55e, 0xa649, 0xca71, 0xcbd6, 0xcbd7, 0xab6d, 0xd0ee, 0xb0cc, 0xb0cb, 0xd863, 0xd862, 0xa450, 0xa4c6, 0xa55f, 0xb0cd, 0xc943, 0xc96c, 0xa560, 0xc9c2, 0xa64b, 0xa64a, 0xc9c1, 0xa758, 0xadea, 0xd46f, 0xb6d7, 0xe145, 0xb9bc, 0xe8fa, 0xf3fd, 0xa4c7, 0xcbd8, 0xcdf4, 0xb0d0, 0xb0ce, 0xb0cf, 0xa451, 0xa464, 0xa2cd, 0xa4ca, 0xa4c9, 0xa4c8, 0xa563, 0xa562, 0xc96d, 0xc9c3, 0xa8f5, 0xa8f2, 0xa8f4, 0xa8f3, 0xab6e, 0xb3d5, 0xa452, 0xa4cb, 0xa565, 0xa564, 0xca72, 0xa8f6, 0xc957, 0xa567, 0xa566, 0xa64c, 0xa64d, 0xca73, 0xa759, 0xa75a, 0xa8f7, 0xa8f8, 0xa8f9, 0xab6f, 0xcdf5, 0xadeb, 0xc944, 0xa4cc, 0xc9c4, 0xca74, 0xca75, 0xcbd9, 0xcbda, 0xcdf7, 0xcdf6, 0xcdf9, 0xcdf8, 0xab70, 0xd470, 0xaded, 0xd0ef, 0xadec, 0xd864, 0xb3d6, 0xd865, 0xe146, 0xb9bd, 0xbc46, 0xf1ef, 0xc958, 0xa568, 0xb0d1, 0xa453, 0xa465, 0xa4ce, 0xa4cd, 0xa4cf, 0xa8fb, 0xa8fa, 0xa8fc, 0xab71, 0xadee, 0xe8fb, 0xc24f, 0xa466, 0xa56a, 0xa579, 0xa574, 0xa56f, 0xa56e, 0xa575, 0xa573, 0xa56c, 0xa57a, 0xa56d, 0xa569, 0xa578, 0xa577, 0xa576, 0xa56b, 0xa572, 0xa571, 0xa57b, 0xa570, 0xa653, 0xa659, 0xa655, 0xa65b, 0xc9c5, 0xa658, 0xa64e, 0xa651, 0xa654, 0xa650, 0xa657, 0xa65a, 0xa64f, 0xa652, 0xa656, 0xa65c, 0xca7e, 0xca7b, 0xa767, 0xca7c, 0xa75b, 0xa75d, 0xa775, 0xa770, 0xcaa5, 0xca7d, 0xa75f, 0xa761, 0xcaa4, 0xa768, 0xca78, 0xa774, 0xa776, 0xa75c, 0xa76d, 0xca76, 0xa773, 0xa764, 0xa76e, 0xa76f, 0xca77, 0xa76c, 0xa76a, 0xa76b, 0xa771, 0xcaa1, 0xa75e, 0xa772, 0xcaa3, 0xa766, 0xa763, 0xca7a, 0xa762, 0xcaa6, 0xa765, 0xa769, 0xa760, 0xcaa2, 0xca79, 0xcbeb, 0xcbea, 0xa94f, 0xcbed, 0xcbef, 0xcbe4, 0xcbe7, 0xcbee, 0xa950, 0xcbe1, 0xcbe5, 0xcbe9, 0xce49, 0xa94b, 0xce4d, 0xa8fd, 0xcbe6, 0xa8fe, 0xa94c, 0xa945, 0xa941, 0xcbe2, 0xa944, 0xa949, 0xa952, 0xcbe3, 0xcbdc, 0xa943, 0xcbdd, 0xcbdf, 0xa946, 0xa948, 0xcbdb, 0xcbe0, 0xa951, 0xa94d, 0xcbe8, 0xa953, 0xa94a, 0xcbde, 0xa947, 0xa942, 0xa940, 0xcbec, 0xa94e, 0xce48, 0xcdfb, 0xce4b, 0xcdfd, 0xab78, 0xaba8, 0xab74, 0xaba7, 0xab7d, 0xaba4, 0xab72, 0xcdfc, 0xce43, 0xaba3, 0xce4f, 0xaba5, 0xab79, 0xce45, 0xce42, 0xab77, 0xcdfa, 0xaba6, 0xce4a, 0xab7c, 0xce4c, 0xaba9, 0xab73, 0xab7e, 0xab7b, 0xce40, 0xaba1, 0xce46, 0xce47, 0xab7a, 0xaba2, 0xab76, 0xab75, 0xcdfe, 0xce44, 0xce4e, 0xd144, 0xadfb, 0xd0f1, 0xd0f6, 0xadf4, 0xae40, 0xd0f4, 0xadef, 0xadf9, 0xadfe, 0xd0fb, 0xadfa, 0xadfd, 0xd0fe, 0xadf5, 0xd0f5, 0xd142, 0xd143, 0xadf7, 0xd141, 0xadf3, 0xae43, 0xd0f8, 0xadf1, 0xd146, 0xd0f9, 0xd0fd, 0xadf6, 0xae42, 0xd0fa, 0xadfc, 0xd140, 0xd147, 0xd4a1, 0xd145, 0xae44, 0xadf0, 0xd0fc, 0xd0f3, 0xadf8, 0xd0f2, 0xd0f7, 0xd0f0, 0xae41, 0xd477, 0xb0e4, 0xd4a7, 0xb0e2, 0xb0df, 0xd47c, 0xb0db, 0xd4a2, 0xb0e6, 0xd476, 0xd47b, 0xd47a, 0xadf2, 0xb0e1, 0xd4a5, 0xd4a8, 0xd473, 0xb3e8, 0xd4a9, 0xb0e7, 0xb0d9, 0xb0d6, 0xd47e, 0xb0d3, 0xd4a6, 0xb0da, 0xd4aa, 0xd474, 0xd4a4, 0xb0dd, 0xd475, 0xd478, 0xd47d, 0xb0de, 0xb0dc, 0xb0e8, 0xb0e3, 0xb0d7, 0xb1d2, 0xb0d8, 0xd479, 0xb0e5, 0xb0e0, 0xd4a3, 0xb0d5, 0xb0d4, 0xd471, 0xd472, 0xd86a, 0xb3d7, 0xb3da, 0xd875, 0xb3ee, 0xd878, 0xb3d8, 0xd871, 0xb3de, 0xb3e4, 0xb5bd, 0xb3e2, 0xd86e, 0xb3ef, 0xb3db, 0xb3e3, 0xd876, 0xdcd7, 0xd87b, 0xd86f, 0xd866, 0xd873, 0xd86d, 0xb3e1, 0xd879, 0xb3dd, 0xb3f1, 0xb3ea, 0xb3df, 0xb3dc, 0xb3e7, 0xd87a, 0xd86c, 0xd872, 0xd874, 0xd868, 0xd877, 0xb3d9, 0xd867, 0xb3e0, 0xb3f0, 0xb3ec, 0xd869, 0xb3e6, 0xb3ed, 0xb3e9, 0xb3e5, 0xd870, 0xb3eb, 0xdcd5, 0xdcd1, 0xdce0, 0xdcca, 0xdcd3, 0xb6e5, 0xb6e6, 0xb6de, 0xdcdc, 0xb6e8, 0xdccf, 0xdcce, 0xdccc, 0xdcde, 0xb6dc, 0xdcd8, 0xdccd, 0xb6df, 0xdcd6, 0xb6da, 0xdcd2, 0xdcd9, 0xdcdb, 0xdcdf, 0xb6e3, 0xdccb, 0xb6dd, 0xdcd0, 0xb6d8, 0xb6e4, 0xdcda, 0xb6e0, 0xb6e1, 0xb6e7, 0xb6db, 0xa25f, 0xb6d9, 0xdcd4, 0xb6e2, 0xdcdd, 0xb9cd, 0xb9c8, 0xe155, 0xe151, 0xe14b, 0xb9c2, 0xb9be, 0xe154, 0xb9bf, 0xe14e, 0xe150, 0xe153, 0xb9c4, 0xb9cb, 0xb9c5, 0xe149, 0xb9c6, 0xb9c7, 0xe14c, 0xb9cc, 0xe14a, 0xe14f, 0xb9c3, 0xe148, 0xb9c9, 0xb9c1, 0xb9c0, 0xe14d, 0xe152, 0xb9ca, 0xe147, 0xbc4d, 0xe547, 0xe544, 0xbc47, 0xbc53, 0xbc54, 0xbc4a, 0xe542, 0xbc4c, 0xe4f9, 0xbc52, 0xe546, 0xbc49, 0xe548, 0xbc48, 0xe543, 0xe545, 0xbc4b, 0xe541, 0xe4fa, 0xe4f7, 0xd86b, 0xe4fd, 0xe4f6, 0xe4fc, 0xe4fb, 0xe4f8, 0xbc4f, 0xbc4e, 0xbc50, 0xe4fe, 0xbeb2, 0xe540, 0xe945, 0xe8fd, 0xbebe, 0xe942, 0xbeb6, 0xbeba, 0xe941, 0xbeb9, 0xbeb5, 0xbeb8, 0xbeb3, 0xbebd, 0xe943, 0xe8fe, 0xbebc, 0xe8fc, 0xbebb, 0xe944, 0xe940, 0xbc51, 0xbebf, 0xe946, 0xbeb7, 0xbeb4, 0xecc6, 0xecc8, 0xc07b, 0xecc9, 0xecc7, 0xecc5, 0xecc4, 0xc07d, 0xecc3, 0xc07e, 0xecc1, 0xecc2, 0xc07a, 0xc0a1, 0xc07c, 0xecc0, 0xc250, 0xefbc, 0xefba, 0xefbf, 0xefbd, 0xefbb, 0xefbe, 0xc360, 0xf1f2, 0xf1f3, 0xc456, 0xf1f4, 0xf1f0, 0xf1f5, 0xf1f1, 0xc251, 0xf3fe, 0xf441, 0xc459, 0xf440, 0xc458, 0xc457, 0xc45a, 0xf5c5, 0xf5c6, 0xc4da, 0xc4d9, 0xc4db, 0xf5c4, 0xf6d8, 0xf6d7, 0xc56d, 0xc56f, 0xc56e, 0xf6d9, 0xc5c8, 0xf8a6, 0xc5f1, 0xf8a5, 0xf8ee, 0xc949, 0xa57d, 0xa57c, 0xa65f, 0xa65e, 0xc9c7, 0xa65d, 0xc9c6, 0xa779, 0xcaa9, 0xcaa8, 0xa777, 0xa77a, 0xcaa7, 0xa778, 0xcbf0, 0xcbf1, 0xa954, 0xabaa, 0xd148, 0xd149, 0xae45, 0xae46, 0xd4ac, 0xb0e9, 0xb0eb, 0xd4ab, 0xb0ea, 0xd87c, 0xb3f2, 0xb6e9, 0xb6ea, 0xdce1, 0xb9cf, 0xb9ce, 0xe549, 0xe948, 0xe947, 0xf96b, 0xa467, 0xc959, 0xc96e, 0xc96f, 0xa662, 0xa666, 0xc9c9, 0xa664, 0xa663, 0xc9c8, 0xa665, 0xa661, 0xa660, 0xc9ca, 0xa7a6, 0xa7a3, 0xa77d, 0xcaaa, 0xcaab, 0xa7a1, 0xcaad, 0xa77b, 0xcaae, 0xcaac, 0xa77e, 0xa7a2, 0xa7a5, 0xa7a4, 0xa77c, 0xcaaf, 0xa959, 0xcbfe, 0xa95b, 0xa95a, 0xcc40, 0xa958, 0xa957, 0xcbf5, 0xcbf4, 0xcbf2, 0xcbf7, 0xcbf6, 0xcbf3, 0xcbfc, 0xcbfd, 0xcbfa, 0xcbf8, 0xa956, 0xcbfb, 0xa95c, 0xcc41, 0xcbf9, 0xabab, 0xa955, 0xabac, 0xce54, 0xce5a, 0xabb2, 0xce58, 0xce5e, 0xce55, 0xce59, 0xce5b, 0xce5d, 0xce57, 0xce56, 0xce51, 0xce52, 0xabad, 0xabaf, 0xabae, 0xce53, 0xce5c, 0xabb1, 0xce50, 0xd153, 0xd152, 0xd157, 0xd14e, 0xd151, 0xd150, 0xd154, 0xd158, 0xae47, 0xae4a, 0xd14f, 0xd155, 0xae49, 0xd14a, 0xabb0, 0xd4ba, 0xd156, 0xd14d, 0xae48, 0xd14c, 0xd4b1, 0xb0ec, 0xb0f0, 0xd4c1, 0xd4af, 0xd4bd, 0xb0f1, 0xd4bf, 0xd4c5, 0xd4c9, 0xd4c0, 0xd4b4, 0xd4bc, 0xd4ca, 0xd4c8, 0xd4be, 0xd4b9, 0xd4b2, 0xd8a6, 0xd4b0, 0xb0f5, 0xd4b7, 0xb0f6, 0xb0f2, 0xd4ad, 0xd4c3, 0xd4b5, 0xd4b3, 0xd4c6, 0xb0f3, 0xd4cc, 0xb0ed, 0xb0ef, 0xd4bb, 0xd4b6, 0xae4b, 0xb0ee, 0xd4b8, 0xd4c7, 0xd4cb, 0xd4c2, 0xd4c4, 0xd4ae, 0xd8a1, 0xd8aa, 0xd8a9, 0xb3fa, 0xd8a2, 0xb3fb, 0xb3f9, 0xd8a4, 0xb3f6, 0xd8a8, 0xd8a3, 0xd8a5, 0xd87d, 0xb3f4, 0xd8b2, 0xd8b1, 0xd8ae, 0xb3f3, 0xb3f7, 0xb3f8, 0xd14b, 0xd8ab, 0xb3f5, 0xb0f4, 0xd8ad, 0xd87e, 0xd8b0, 0xd8af, 0xd8b3, 0xdcef, 0xd8ac, 0xd8a7, 0xdce7, 0xb6f4, 0xb6f7, 0xb6f2, 0xdce6, 0xdcea, 0xdce5, 0xb6ec, 0xb6f6, 0xdce2, 0xb6f0, 0xdce9, 0xb6ee, 0xb6ed, 0xdcec, 0xb6ef, 0xdcee, 0xdceb, 0xb6eb, 0xb6f5, 0xdcf0, 0xdce4, 0xdced, 0xdce3, 0xb6f1, 0xb6f3, 0xdce8, 0xdcf1, 0xe15d, 0xb9d0, 0xe163, 0xb9d5, 0xe15f, 0xe166, 0xe157, 0xb9d7, 0xb9d1, 0xe15c, 0xbc55, 0xe15b, 0xe164, 0xb9d2, 0xb9d6, 0xe15a, 0xe160, 0xe165, 0xe156, 0xb9d4, 0xe15e, 0xe162, 0xe168, 0xe158, 0xe161, 0xb9d3, 0xe167, 0xe159, 0xbc59, 0xe54b, 0xbc57, 0xbc56, 0xe54d, 0xe552, 0xe54e, 0xe551, 0xbc5c, 0xbea5, 0xbc5b, 0xe54a, 0xe550, 0xbc5a, 0xe54f, 0xe54c, 0xbc58, 0xe94d, 0xe94f, 0xe94a, 0xbec1, 0xe94c, 0xbec0, 0xe94e, 0xbec3, 0xe950, 0xbec2, 0xe949, 0xe94b, 0xc0a5, 0xeccc, 0xc0a4, 0xeccd, 0xc0a3, 0xeccb, 0xc0a2, 0xecca, 0xc253, 0xc252, 0xf1f6, 0xf1f8, 0xf1f7, 0xc361, 0xc362, 0xc363, 0xf442, 0xc45b, 0xf7d3, 0xf7d2, 0xc5f2, 0xa468, 0xa4d0, 0xa7a7, 0xce5f, 0xb3fc, 0xb3fd, 0xdcf2, 0xb9d8, 0xe169, 0xe553, 0xc95a, 0xcab0, 0xcc42, 0xce60, 0xd159, 0xae4c, 0xf1f9, 0xc4dc, 0xa469, 0xa57e, 0xc970, 0xa667, 0xa668, 0xa95d, 0xb0f7, 0xb9da, 0xb9db, 0xb9d9, 0xa46a, 0xa4d1, 0xa4d3, 0xa4d2, 0xc95b, 0xa4d4, 0xa5a1, 0xc971, 0xa5a2, 0xa669, 0xa66a, 0xc9cb, 0xa7a8, 0xcab1, 0xa961, 0xcc43, 0xa95f, 0xa960, 0xa95e, 0xd15a, 0xabb6, 0xabb5, 0xabb7, 0xabb4, 0xce61, 0xa962, 0xabb3, 0xae4d, 0xae4e, 0xae4f, 0xd4cd, 0xb3fe, 0xd8b4, 0xb0f8, 0xb6f8, 0xb9dd, 0xb9dc, 0xe16a, 0xbc5d, 0xbec4, 0xefc0, 0xf6da, 0xf7d4, 0xa46b, 0xa5a3, 0xa5a4, 0xc9d1, 0xa66c, 0xa66f, 0xc9cf, 0xc9cd, 0xa66e, 0xc9d0, 0xc9d2, 0xc9cc, 0xa671, 0xa670, 0xa66d, 0xa66b, 0xc9ce, 0xa7b3, 0xa7b0, 0xcab6, 0xcab9, 0xcab8, 0xa7aa, 0xa7b2, 0xa7af, 0xcab5, 0xcab3, 0xa7ae, 0xa7a9, 0xa7ac, 0xcab4, 0xcabb, 0xcab7, 0xa7ad, 0xa7b1, 0xa7b4, 0xcab2, 0xcaba, 0xa7ab, 0xa967, 0xa96f, 0xcc4f, 0xcc48, 0xa970, 0xcc53, 0xcc44, 0xcc4b, 0xa966, 0xcc45, 0xa964, 0xcc4c, 0xcc50, 0xa963, 0xcc51, 0xcc4a, 0xcc4d, 0xa972, 0xa969, 0xcc54, 0xcc52, 0xa96e, 0xa96c, 0xcc49, 0xa96b, 0xcc47, 0xcc46, 0xa96a, 0xa968, 0xa971, 0xa96d, 0xa965, 0xcc4e, 0xabb9, 0xabc0, 0xce6f, 0xabb8, 0xce67, 0xce63, 0xce73, 0xce62, 0xabbb, 0xce6c, 0xabbe, 0xabc1, 0xabbc, 0xce70, 0xabbf, 0xae56, 0xce76, 0xce64, 0xce66, 0xce6d, 0xce71, 0xce75, 0xce72, 0xce6b, 0xce6e, 0xce68, 0xabc3, 0xce6a, 0xce69, 0xce74, 0xabba, 0xce65, 0xabc2, 0xabbd, 0xae5c, 0xd162, 0xae5b, 0xd160, 0xae50, 0xae55, 0xd15f, 0xd15c, 0xd161, 0xae51, 0xd15b, 0xae54, 0xae52, 0xd163, 0xae53, 0xae57, 0xae58, 0xae5a, 0xae59, 0xd15d, 0xd15e, 0xd164, 0xd4d4, 0xb0f9, 0xd8c2, 0xd4d3, 0xd4e6, 0xb140, 0xd4e4, 0xb0fe, 0xb0fa, 0xd4ed, 0xd4dd, 0xd4e0, 0xb143, 0xd4ea, 0xd4e2, 0xb0fb, 0xb144, 0xd4e7, 0xd4e5, 0xd4d6, 0xd4eb, 0xd4df, 0xd4da, 0xd4d0, 0xd4ec, 0xd4dc, 0xd4cf, 0xb142, 0xd4e1, 0xd4ee, 0xd4de, 0xd4d2, 0xd4d7, 0xd4ce, 0xb141, 0xd4db, 0xd4d8, 0xb0fc, 0xd4d1, 0xd4e9, 0xb0fd, 0xd4d9, 0xd4d5, 0xd4e8, 0xb440, 0xd8bb, 0xd8b8, 0xd8c9, 0xd8bd, 0xd8ca, 0xb442, 0xd8c6, 0xd8c3, 0xd8c4, 0xd8c7, 0xd8cb, 0xd4e3, 0xd8cd, 0xdd47, 0xb443, 0xd8ce, 0xd8b6, 0xd8c0, 0xd8c5, 0xb441, 0xb444, 0xd8cc, 0xd8cf, 0xd8ba, 0xd8b7, 0xd8b9, 0xd8be, 0xd8bc, 0xb445, 0xd8c8, 0xd8bf, 0xd8c1, 0xd8b5, 0xdcfa, 0xdcf8, 0xb742, 0xb740, 0xdd43, 0xdcf9, 0xdd44, 0xdd40, 0xdcf7, 0xdd46, 0xdcf6, 0xdcfd, 0xb6fe, 0xb6fd, 0xb6fc, 0xdcfb, 0xdd41, 0xb6f9, 0xb741, 0xdcf4, 0xdcfe, 0xdcf3, 0xdcfc, 0xb6fa, 0xdd42, 0xdcf5, 0xb6fb, 0xdd45, 0xe16e, 0xb9e2, 0xb9e1, 0xb9e3, 0xe17a, 0xe170, 0xe176, 0xe16b, 0xe179, 0xe178, 0xe17c, 0xe175, 0xb9de, 0xe174, 0xb9e4, 0xe16d, 0xb9df, 0xe17b, 0xb9e0, 0xe16f, 0xe172, 0xe177, 0xe171, 0xe16c, 0xe173, 0xe555, 0xbc61, 0xe558, 0xe557, 0xe55a, 0xe55c, 0xbc5f, 0xe556, 0xe554, 0xe55d, 0xe55b, 0xe559, 0xe55f, 0xe55e, 0xbc63, 0xbc5e, 0xbc60, 0xbc62, 0xe560, 0xe957, 0xe956, 0xe955, 0xe958, 0xe951, 0xe952, 0xe95a, 0xe953, 0xbec5, 0xe95c, 0xe95b, 0xe954, 0xecd1, 0xc0a8, 0xeccf, 0xecd4, 0xecd3, 0xe959, 0xc0a7, 0xecd2, 0xecce, 0xecd6, 0xecd5, 0xc0a6, 0xecd0, 0xbec6, 0xc254, 0xefc1, 0xf1fa, 0xf1fb, 0xf1fc, 0xc45c, 0xc45d, 0xf443, 0xf5c8, 0xf5c7, 0xf6db, 0xf6dc, 0xf7d5, 0xf8a7, 0xa46c, 0xa46d, 0xa46e, 0xa4d5, 0xa5a5, 0xc9d3, 0xa672, 0xa673, 0xa7b7, 0xa7b8, 0xa7b6, 0xa7b5, 0xa973, 0xcc55, 0xa975, 0xa974, 0xcc56, 0xabc4, 0xae5d, 0xd165, 0xd4f0, 0xb145, 0xb447, 0xd4ef, 0xb446, 0xb9e5, 0xe17d, 0xbec7, 0xc0a9, 0xecd7, 0xc45e, 0xc570, 0xc972, 0xa5a6, 0xc973, 0xa676, 0xa674, 0xa675, 0xa677, 0xa7ba, 0xa7b9, 0xcabc, 0xa7bb, 0xcabd, 0xcc57, 0xcc58, 0xa976, 0xa978, 0xa97a, 0xa977, 0xa97b, 0xa979, 0xabc8, 0xabc5, 0xabc7, 0xabc9, 0xabc6, 0xd166, 0xce77, 0xd168, 0xd167, 0xae63, 0xae5f, 0xae60, 0xae62, 0xae64, 0xae61, 0xae66, 0xae65, 0xb14a, 0xd4f2, 0xd4f1, 0xb149, 0xb148, 0xb147, 0xb14b, 0xb146, 0xd8d5, 0xd8d2, 0xb449, 0xd8d1, 0xd8d6, 0xb44b, 0xd8d4, 0xb448, 0xb44a, 0xd8d3, 0xdd48, 0xdd49, 0xdd4a, 0xb9e6, 0xb9ee, 0xe17e, 0xb9e8, 0xb9ec, 0xe1a1, 0xb9ed, 0xb9e9, 0xb9ea, 0xb9e7, 0xb9eb, 0xbc66, 0xd8d0, 0xbc67, 0xbc65, 0xbc64, 0xe95d, 0xbec8, 0xecd8, 0xecd9, 0xc364, 0xc45f, 0xa46f, 0xa678, 0xabca, 0xd169, 0xae67, 0xb14e, 0xb14d, 0xb14c, 0xb44c, 0xb44d, 0xd8d7, 0xb9ef, 0xbec9, 0xa470, 0xc95c, 0xa4d6, 0xc974, 0xc9d4, 0xa679, 0xa97c, 0xdd4b, 0xa471, 0xa4d7, 0xc9d5, 0xcabe, 0xcabf, 0xa7bc, 0xd8d8, 0xb44e, 0xdd4c, 0xc0aa, 0xa472, 0xa4a8, 0xa4d8, 0xc975, 0xa5a7, 0xa7c0, 0xa7bf, 0xa7bd, 0xa7be, 0xcc59, 0xa97e, 0xa9a1, 0xcc5a, 0xa97d, 0xabce, 0xce78, 0xabcd, 0xabcb, 0xabcc, 0xae6a, 0xae68, 0xd16b, 0xae69, 0xd16a, 0xae5e, 0xd4f3, 0xb150, 0xb151, 0xb14f, 0xb9f0, 0xe1a2, 0xbc68, 0xbc69, 0xe561, 0xc0ab, 0xefc2, 0xefc3, 0xc4dd, 0xf8a8, 0xc94b, 0xa4d9, 0xa473, 0xc977, 0xc976, 0xa67a, 0xc9d7, 0xc9d8, 0xc9d6, 0xc9d9, 0xcac7, 0xcac2, 0xcac4, 0xcac6, 0xcac3, 0xa7c4, 0xcac0, 0xcac1, 0xa7c1, 0xa7c2, 0xcac5, 0xcac8, 0xa7c3, 0xcac9, 0xcc68, 0xcc62, 0xcc5d, 0xa9a3, 0xcc65, 0xcc63, 0xcc5c, 0xcc69, 0xcc6c, 0xcc67, 0xcc60, 0xa9a5, 0xcc66, 0xa9a6, 0xcc61, 0xcc64, 0xcc5b, 0xcc5f, 0xcc6b, 0xa9a7, 0xa9a8, 0xcc5e, 0xcc6a, 0xa9a2, 0xa9a4, 0xceab, 0xcea4, 0xceaa, 0xcea3, 0xcea5, 0xce7d, 0xce7b, 0xceac, 0xcea9, 0xce79, 0xabd0, 0xcea7, 0xcea8, 0xcea6, 0xce7c, 0xce7a, 0xabcf, 0xcea2, 0xce7e, 0xcea1, 0xcead, 0xae6f, 0xae6e, 0xd16c, 0xae6b, 0xd16e, 0xae70, 0xd16f, 0xae73, 0xae71, 0xd170, 0xceae, 0xd172, 0xae6d, 0xae6c, 0xd16d, 0xd171, 0xae72, 0xb153, 0xb152, 0xd4f5, 0xd4f9, 0xd4fb, 0xb154, 0xd4fe, 0xb158, 0xd541, 0xb15a, 0xb156, 0xb15e, 0xb15b, 0xd4f7, 0xb155, 0xd4f6, 0xd4f4, 0xd543, 0xd4f8, 0xb157, 0xd542, 0xb15c, 0xd4fd, 0xd4fc, 0xb15d, 0xd4fa, 0xb159, 0xd544, 0xd540, 0xd8e7, 0xd8ee, 0xd8e3, 0xb451, 0xd8df, 0xd8ef, 0xd8d9, 0xd8ec, 0xd8ea, 0xd8e4, 0xd8ed, 0xd8e6, 0xd8de, 0xd8f0, 0xd8dc, 0xd8e9, 0xd8da, 0xd8f1, 0xb452, 0xd8eb, 0xdd4f, 0xd8dd, 0xb44f, 0xd8e1, 0xb450, 0xd8e0, 0xd8e5, 0xd8e2, 0xd8e8, 0xdd53, 0xdd56, 0xdd4e, 0xdd50, 0xdd55, 0xdd54, 0xb743, 0xd8db, 0xdd52, 0xb744, 0xdd4d, 0xdd51, 0xe1a9, 0xe1b0, 0xe1a7, 0xe1ae, 0xe1a5, 0xe1ad, 0xe1b1, 0xe1a4, 0xe1a8, 0xe1a3, 0xb9f1, 0xe1a6, 0xb9f2, 0xe1ac, 0xe1ab, 0xe1aa, 0xe1af, 0xe565, 0xe567, 0xbc6b, 0xe568, 0xe563, 0xe562, 0xe56c, 0xe56a, 0xbc6a, 0xe56d, 0xe564, 0xe569, 0xe56b, 0xe566, 0xe961, 0xe966, 0xe960, 0xe965, 0xe95e, 0xe968, 0xe964, 0xe969, 0xe963, 0xe95f, 0xe967, 0xe96a, 0xe962, 0xecda, 0xc0af, 0xc0ad, 0xc0ac, 0xc0ae, 0xefc4, 0xf172, 0xf1fd, 0xf444, 0xf445, 0xc460, 0xf5c9, 0xc4de, 0xf5ca, 0xf6de, 0xc572, 0xc571, 0xf6dd, 0xc5c9, 0xf7d6, 0xa474, 0xa67b, 0xc9da, 0xcaca, 0xa8b5, 0xb15f, 0xa475, 0xa5aa, 0xa5a9, 0xa5a8, 0xa7c5, 0xae74, 0xdd57, 0xa476, 0xa477, 0xa478, 0xa4da, 0xabd1, 0xceaf, 0xb453, 0xa479, 0xc95d, 0xa5ab, 0xa5ac, 0xc978, 0xa67c, 0xcacb, 0xa7c6, 0xcacc, 0xa9ae, 0xcc6e, 0xa9ac, 0xa9ab, 0xcc6d, 0xa9a9, 0xcc6f, 0xa9aa, 0xa9ad, 0xabd2, 0xabd4, 0xceb3, 0xceb0, 0xceb1, 0xceb2, 0xceb4, 0xabd3, 0xd174, 0xd173, 0xae76, 0xae75, 0xb162, 0xd546, 0xb161, 0xb163, 0xb160, 0xb455, 0xd545, 0xb456, 0xd8f3, 0xb457, 0xd8f2, 0xb454, 0xdd5a, 0xdd5c, 0xb745, 0xdd5b, 0xdd59, 0xdd58, 0xe1b4, 0xb9f7, 0xb9f5, 0xb9f6, 0xe1b2, 0xe1b3, 0xb9f3, 0xe571, 0xe56f, 0xbc6d, 0xe570, 0xbc6e, 0xbc6c, 0xb9f4, 0xe96d, 0xe96b, 0xe96c, 0xe56e, 0xecdc, 0xc0b0, 0xecdb, 0xefc5, 0xefc6, 0xe96e, 0xf1fe, 0xa47a, 0xa5ad, 0xa67e, 0xc9db, 0xa67d, 0xa9af, 0xb746, 0xa4db, 0xa5ae, 0xabd5, 0xb458, 0xc979, 0xc97a, 0xc9dc, 0xa7c8, 0xcad0, 0xcace, 0xa7c9, 0xcacd, 0xcacf, 0xcad1, 0xa7c7, 0xa9b3, 0xa9b4, 0xa9b1, 0xa9b0, 0xceb8, 0xa9b2, 0xabd6, 0xceb7, 0xceb9, 0xceb6, 0xceba, 0xabd7, 0xae79, 0xd175, 0xd177, 0xae77, 0xd178, 0xae78, 0xd176, 0xceb5, 0xd547, 0xd54a, 0xd54b, 0xd548, 0xb167, 0xb166, 0xb164, 0xb165, 0xd549, 0xb168, 0xb45a, 0xb45b, 0xb45c, 0xdd5d, 0xdd5f, 0xdd61, 0xb748, 0xb747, 0xb459, 0xdd60, 0xdd5e, 0xe1b8, 0xe1b6, 0xe1bc, 0xb9f8, 0xe1bd, 0xe1ba, 0xb9f9, 0xe1b7, 0xe1b5, 0xe1bb, 0xbc70, 0xe573, 0xe1b9, 0xbc72, 0xe574, 0xbc71, 0xbc74, 0xe575, 0xbc6f, 0xbc73, 0xe973, 0xe971, 0xe970, 0xe972, 0xe96f, 0xc366, 0xf446, 0xf447, 0xf5cb, 0xf6df, 0xc655, 0xa9b5, 0xa7ca, 0xabd8, 0xa47b, 0xa4dc, 0xa5af, 0xc9dd, 0xa7cb, 0xcad2, 0xcebb, 0xabd9, 0xb9fa, 0xa47c, 0xa6a1, 0xb749, 0xa47d, 0xa4dd, 0xa4de, 0xa5b1, 0xa5b0, 0xc9de, 0xa6a2, 0xcad3, 0xa7cc, 0xcc71, 0xcc72, 0xcc73, 0xa9b6, 0xa9b7, 0xcc70, 0xa9b8, 0xabda, 0xcebc, 0xd17a, 0xae7a, 0xd179, 0xb169, 0xd54c, 0xb16a, 0xd54d, 0xb45d, 0xdd62, 0xe1bf, 0xe1be, 0xb9fb, 0xbc75, 0xe576, 0xbeca, 0xe974, 0xc0b1, 0xc573, 0xf7d8, 0xcc74, 0xcebd, 0xb16b, 0xd8f4, 0xb74a, 0xc255, 0xa7ce, 0xa7cd, 0xabdb, 0xd17b, 0xb16d, 0xb343, 0xb16e, 0xb16c, 0xb45e, 0xe1c0, 0xb9fc, 0xbc76, 0xc94c, 0xc9df, 0xcad5, 0xa7cf, 0xcad4, 0xa7d0, 0xa9bc, 0xcc77, 0xcc76, 0xa9bb, 0xa9b9, 0xa9ba, 0xcc75, 0xabdd, 0xcebe, 0xabe0, 0xabdc, 0xabe2, 0xabde, 0xabdf, 0xabe1, 0xae7d, 0xae7c, 0xae7b, 0xd54f, 0xb16f, 0xb172, 0xb170, 0xd54e, 0xb175, 0xb171, 0xd550, 0xb174, 0xb173, 0xd8f6, 0xd8f5, 0xb461, 0xb45f, 0xb460, 0xd8f7, 0xb74b, 0xdd64, 0xb74c, 0xdd63, 0xe577, 0xbc78, 0xe1c1, 0xbc77, 0xb9fd, 0xecde, 0xe975, 0xc0b2, 0xecdd, 0xf240, 0xf448, 0xf449, 0xa4df, 0xa5b2, 0xc97b, 0xa7d2, 0xa7d4, 0xc9e2, 0xcad8, 0xcad7, 0xcad6, 0xc9e1, 0xc9e0, 0xa6a4, 0xa7d3, 0xa7d1, 0xa6a3, 0xa9bd, 0xcc78, 0xa9be, 0xcadd, 0xcadf, 0xcade, 0xcc79, 0xcada, 0xa7d8, 0xa7d6, 0xcad9, 0xcadb, 0xcae1, 0xa7d5, 0xcadc, 0xcae5, 0xa9c0, 0xcae2, 0xa7d7, 0xcae0, 0xcae3, 0xa9bf, 0xa9c1, 0xcae4, 0xccaf, 0xcca2, 0xcc7e, 0xccae, 0xcca9, 0xabe7, 0xa9c2, 0xccaa, 0xccad, 0xabe3, 0xccac, 0xa9c3, 0xa9c8, 0xa9c6, 0xcca3, 0xcc7c, 0xcca5, 0xa9cd, 0xccb0, 0xabe4, 0xcca6, 0xabe5, 0xa9c9, 0xcca8, 0xcecd, 0xabe6, 0xcc7b, 0xa9ca, 0xabe8, 0xa9cb, 0xa9c7, 0xa9cc, 0xcca7, 0xcc7a, 0xccab, 0xa9c4, 0xcc7d, 0xcca4, 0xcca1, 0xa9c5, 0xcebf, 0xcec0, 0xceca, 0xd1a1, 0xcecb, 0xabee, 0xcece, 0xcec4, 0xabed, 0xcec6, 0xcec7, 0xcec9, 0xabe9, 0xaea3, 0xcec5, 0xcec1, 0xaea4, 0xcecf, 0xae7e, 0xd17d, 0xcec8, 0xd17c, 0xcec3, 0xcecc, 0xabec, 0xaea1, 0xabf2, 0xaea2, 0xced0, 0xd17e, 0xabeb, 0xaea6, 0xabf1, 0xabf0, 0xabef, 0xaea5, 0xced1, 0xaea7, 0xabea, 0xcec2, 0xb176, 0xd1a4, 0xd1a6, 0xd1a8, 0xaea8, 0xaeae, 0xd553, 0xd1ac, 0xd1a3, 0xb178, 0xd551, 0xaead, 0xaeab, 0xd1ae, 0xd552, 0xd1a5, 0xaeac, 0xd1a9, 0xaeaf, 0xd1ab, 0xaeaa, 0xd1aa, 0xd1ad, 0xd1a7, 0xaea9, 0xb179, 0xd1a2, 0xb177, 0xb17a, 0xd555, 0xd55e, 0xb464, 0xb17c, 0xb1a3, 0xb465, 0xd560, 0xb1aa, 0xd8f9, 0xd556, 0xb1a2, 0xb1a5, 0xb17e, 0xd554, 0xd562, 0xd565, 0xd949, 0xd563, 0xd8fd, 0xb1a1, 0xb1a8, 0xb1ac, 0xd55d, 0xd8f8, 0xd561, 0xb17b, 0xd8fa, 0xd564, 0xd8fc, 0xd559, 0xb462, 0xd557, 0xd558, 0xb1a7, 0xb1a6, 0xd55b, 0xb1ab, 0xd55f, 0xb1a4, 0xd55c, 0xb1a9, 0xb466, 0xb463, 0xd8fb, 0xd55a, 0xb17d, 0xb46b, 0xb46f, 0xd940, 0xb751, 0xb46d, 0xd944, 0xb471, 0xdd65, 0xd946, 0xb753, 0xb469, 0xb46c, 0xd947, 0xd948, 0xd94e, 0xb473, 0xb754, 0xd94a, 0xd94f, 0xd943, 0xb75e, 0xb755, 0xb472, 0xd941, 0xd950, 0xb75d, 0xb470, 0xb74e, 0xd94d, 0xb474, 0xd945, 0xd8fe, 0xb46a, 0xd942, 0xd94b, 0xb74d, 0xb752, 0xb467, 0xd94c, 0xb750, 0xb468, 0xb75c, 0xe1c3, 0xdd70, 0xdd68, 0xe1c2, 0xdd6c, 0xdd6e, 0xdd6b, 0xb75b, 0xdd6a, 0xb75f, 0xe1d2, 0xb75a, 0xba40, 0xdd71, 0xe1c4, 0xb758, 0xdd69, 0xdd6d, 0xb9fe, 0xb74f, 0xdd66, 0xdd67, 0xba41, 0xb757, 0xb759, 0xb756, 0xdd6f, 0xe1c8, 0xe1c9, 0xe1ce, 0xbc7d, 0xe1d5, 0xba47, 0xba46, 0xe1d0, 0xbc7c, 0xe1c5, 0xba45, 0xe1d4, 0xba43, 0xba44, 0xe1d1, 0xe5aa, 0xbc7a, 0xb46e, 0xe1d3, 0xbca3, 0xe1cb, 0xbc7b, 0xbca2, 0xe1c6, 0xe1ca, 0xe1c7, 0xe1cd, 0xba48, 0xbc79, 0xba42, 0xe57a, 0xe1cf, 0xbca1, 0xbca4, 0xe1cc, 0xbc7e, 0xe579, 0xe57e, 0xbece, 0xe578, 0xe9a3, 0xe5a9, 0xbca8, 0xbca6, 0xbecc, 0xe5a6, 0xe5a2, 0xbcac, 0xe978, 0xbcaa, 0xe5a1, 0xe976, 0xe5a5, 0xe5a8, 0xe57d, 0xbcab, 0xbca5, 0xe977, 0xbecd, 0xe5a7, 0xbca7, 0xbca9, 0xe5a4, 0xbcad, 0xe5a3, 0xe57c, 0xe57b, 0xbecb, 0xe5ab, 0xe97a, 0xece0, 0xbed0, 0xe9a2, 0xe97e, 0xece1, 0xbed1, 0xe9a1, 0xe97c, 0xc0b4, 0xecdf, 0xe979, 0xe97b, 0xc0b5, 0xbed3, 0xc0b3, 0xbed2, 0xc0b7, 0xe97d, 0xbecf, 0xefcf, 0xefc7, 0xece7, 0xefc8, 0xece3, 0xc256, 0xece5, 0xece4, 0xc0b6, 0xece2, 0xece6, 0xefd0, 0xefcc, 0xefce, 0xefc9, 0xefca, 0xefcd, 0xefcb, 0xc367, 0xc36a, 0xc369, 0xc368, 0xc461, 0xf44a, 0xc462, 0xf241, 0xc4df, 0xf5cc, 0xc4e0, 0xc574, 0xc5ca, 0xf7d9, 0xf7da, 0xf7db, 0xf9ba, 0xa4e0, 0xc97c, 0xa5b3, 0xa6a6, 0xa6a7, 0xa6a5, 0xa6a8, 0xa7da, 0xa7d9, 0xccb1, 0xa9cf, 0xa9ce, 0xd1af, 0xb1ad, 0xb1ae, 0xb475, 0xdd72, 0xb760, 0xb761, 0xdd74, 0xdd76, 0xdd75, 0xe1d7, 0xe1d6, 0xba49, 0xe1d8, 0xe5ac, 0xbcae, 0xbed4, 0xc0b8, 0xc257, 0xc0b9, 0xa4e1, 0xcae6, 0xccb2, 0xa9d1, 0xa9d0, 0xa9d2, 0xabf3, 0xced2, 0xced3, 0xd1b0, 0xaeb0, 0xb1af, 0xb476, 0xd951, 0xa4e2, 0xa47e, 0xa4e3, 0xc97d, 0xa5b7, 0xa5b6, 0xa5b4, 0xa5b5, 0xa6ab, 0xc9e9, 0xc9eb, 0xa6aa, 0xc9e3, 0xc9e4, 0xc9ea, 0xc9e6, 0xc9e8, 0xa6a9, 0xc9e5, 0xc9ec, 0xc9e7, 0xa7e1, 0xa7ea, 0xa7e8, 0xcaf0, 0xcaed, 0xcaf5, 0xa7e6, 0xcaf6, 0xa7df, 0xcaf3, 0xa7e5, 0xcaef, 0xcaee, 0xa7e3, 0xcaf4, 0xa7e4, 0xa9d3, 0xa7de, 0xcaf1, 0xcae7, 0xa7db, 0xa7ee, 0xcaec, 0xcaf2, 0xa7e0, 0xa7e2, 0xcae8, 0xcae9, 0xcaea, 0xa7ed, 0xa7e7, 0xa7ec, 0xcaeb, 0xa7eb, 0xa7dd, 0xa7dc, 0xa7e9, 0xa9e1, 0xccbe, 0xccb7, 0xa9dc, 0xa9ef, 0xccb3, 0xccba, 0xccbc, 0xccbf, 0xa9ea, 0xccbb, 0xccb4, 0xa9e8, 0xccb8, 0xccc0, 0xa9d9, 0xccbd, 0xa9e3, 0xa9e2, 0xccb6, 0xa9d7, 0xa9d8, 0xa9d6, 0xa9ee, 0xa9e6, 0xa9e0, 0xa9d4, 0xccb9, 0xa9df, 0xa9d5, 0xa9e7, 0xa9f0, 0xced4, 0xa9e4, 0xccb5, 0xa9da, 0xa9dd, 0xa9de, 0xa9ec, 0xa9ed, 0xa9eb, 0xa9e5, 0xa9e9, 0xa9db, 0xabf4, 0xceda, 0xac41, 0xabf8, 0xabfa, 0xac40, 0xcee6, 0xabfd, 0xd1b1, 0xaeb1, 0xac43, 0xced7, 0xcedf, 0xabfe, 0xcede, 0xcedb, 0xcee3, 0xcee5, 0xabf7, 0xabfb, 0xac42, 0xaeb3, 0xcee0, 0xabf9, 0xac45, 0xced9, 0xabfc, 0xaeb2, 0xabf6, 0xced6, 0xcedd, 0xced5, 0xced8, 0xcedc, 0xd1b2, 0xac44, 0xcee1, 0xcee2, 0xcee4, 0xabf5, 0xaec1, 0xd1be, 0xaebf, 0xaec0, 0xd1b4, 0xd1c4, 0xaeb6, 0xd566, 0xd1c6, 0xd1c0, 0xd1b7, 0xd1c9, 0xd1ba, 0xaebc, 0xd57d, 0xd1bd, 0xaebe, 0xaeb5, 0xd1cb, 0xd1bf, 0xaeb8, 0xd1b8, 0xd1b5, 0xd1b6, 0xaeb9, 0xd1c5, 0xd1cc, 0xaebb, 0xd1bc, 0xd1bb, 0xaec3, 0xaec2, 0xaeb4, 0xaeba, 0xaebd, 0xd1c8, 0xd1c2, 0xaeb7, 0xd1b3, 0xd1ca, 0xd1c1, 0xd1c3, 0xd1c7, 0xd567, 0xb1b7, 0xb1cb, 0xb1ca, 0xb1bf, 0xd579, 0xd575, 0xd572, 0xd5a6, 0xb1ba, 0xb1b2, 0xd577, 0xb4a8, 0xb1b6, 0xd5a1, 0xb1cc, 0xb1c9, 0xd57b, 0xd56a, 0xb1c8, 0xd5a3, 0xd569, 0xb1bd, 0xb1c1, 0xd5a2, 0xd573, 0xb1c2, 0xb1bc, 0xd568, 0xb478, 0xd5a5, 0xd571, 0xb1c7, 0xd574, 0xd5a4, 0xb1c6, 0xd952, 0xb1b3, 0xd56f, 0xb1b8, 0xb1c3, 0xb1be, 0xd578, 0xd56e, 0xd56c, 0xd57e, 0xb1b0, 0xb1c4, 0xb1b4, 0xb477, 0xd57c, 0xb1b5, 0xb1b1, 0xb1c0, 0xb1bb, 0xb1b9, 0xd570, 0xb1c5, 0xd56d, 0xd57a, 0xd576, 0xd954, 0xd953, 0xd56b, 0xd964, 0xb47a, 0xd96a, 0xd959, 0xd967, 0xdd77, 0xb47d, 0xd96b, 0xd96e, 0xb47c, 0xd95c, 0xd96d, 0xd96c, 0xb47e, 0xd955, 0xb479, 0xb4a3, 0xb4a1, 0xd969, 0xd95f, 0xb4a5, 0xd970, 0xd968, 0xd971, 0xb4ad, 0xb4ab, 0xd966, 0xd965, 0xd963, 0xd95d, 0xb4a4, 0xb4a2, 0xd1b9, 0xd956, 0xddb7, 0xd957, 0xb47b, 0xb4aa, 0xdd79, 0xb4a6, 0xb4a7, 0xd958, 0xd96f, 0xdd78, 0xd960, 0xd95b, 0xb4a9, 0xd961, 0xd95e, 0xb4ae, 0xb770, 0xdd7c, 0xddb1, 0xddb6, 0xddaa, 0xb76c, 0xddbb, 0xb769, 0xdd7a, 0xdd7b, 0xb762, 0xb76b, 0xdda4, 0xb76e, 0xb76f, 0xdda5, 0xddb2, 0xddb8, 0xb76a, 0xb764, 0xdda3, 0xdd7d, 0xddba, 0xdda8, 0xdda9, 0xdd7e, 0xddb4, 0xddab, 0xddb5, 0xddad, 0xb765, 0xe1d9, 0xb768, 0xb766, 0xddb9, 0xddb0, 0xddac, 0xdda1, 0xba53, 0xddaf, 0xb76d, 0xdda7, 0xdda6, 0xb767, 0xb763, 0xe1ee, 0xddb3, 0xddae, 0xdda2, 0xe1e9, 0xe1da, 0xe1e5, 0xe1ec, 0xba51, 0xb4ac, 0xe1ea, 0xba4c, 0xba4b, 0xe1f1, 0xe1db, 0xe1e8, 0xe1dc, 0xe1e7, 0xba4f, 0xe1eb, 0xd962, 0xe1f2, 0xe1e3, 0xba52, 0xe5ba, 0xbcaf, 0xe1f0, 0xe1ef, 0xba54, 0xe5ad, 0xbcb0, 0xe5ae, 0xe1df, 0xe1e0, 0xe1dd, 0xe1e2, 0xe1de, 0xe1f3, 0xba4e, 0xbcb1, 0xba50, 0xba55, 0xe1e1, 0xe1ed, 0xe1e6, 0xe5b1, 0xba4a, 0xbcb4, 0xe9aa, 0xe5b6, 0xe5b5, 0xe5b7, 0xe5b4, 0xbcb5, 0xbcbb, 0xbcb8, 0xbcb9, 0xe5af, 0xe5b2, 0xe5bc, 0xbcc1, 0xbcbf, 0xe5b3, 0xd95a, 0xbcb2, 0xe5b9, 0xe5b0, 0xbcc2, 0xe5b8, 0xba4d, 0xbcb7, 0xe1e4, 0xbcba, 0xbcbe, 0xbcc0, 0xbcbd, 0xbcbc, 0xbcb6, 0xe5bb, 0xbcb3, 0xbcc3, 0xbed8, 0xbed9, 0xe9a9, 0xbee2, 0xbedf, 0xbed6, 0xbedd, 0xe9ab, 0xbedb, 0xbed5, 0xbedc, 0xe9a8, 0xc0bb, 0xbed7, 0xbede, 0xc0ba, 0xe9a7, 0xe9a6, 0xbee0, 0xbee1, 0xe9a5, 0xe9a4, 0xc0bc, 0xe9ae, 0xbeda, 0xe9ac, 0xc0bd, 0xc0c2, 0xecea, 0xecec, 0xc0bf, 0xeced, 0xece9, 0xeceb, 0xc0c0, 0xc0c3, 0xece8, 0xc0be, 0xc0c1, 0xc259, 0xe9ad, 0xc258, 0xc25e, 0xefd4, 0xc25c, 0xc25d, 0xefd7, 0xefd3, 0xc25a, 0xefd1, 0xc36b, 0xefd5, 0xefd6, 0xefd2, 0xc25b, 0xf242, 0xf245, 0xf246, 0xf244, 0xf247, 0xc36c, 0xf243, 0xf44e, 0xc464, 0xf44d, 0xf44c, 0xf44b, 0xc463, 0xc465, 0xf5cd, 0xc4e2, 0xc4e1, 0xf6e1, 0xf6e0, 0xf6e3, 0xc5cb, 0xc575, 0xf7dd, 0xf6e2, 0xf7dc, 0xc5cd, 0xc5cc, 0xc5f3, 0xf8a9, 0xf8ef, 0xa4e4, 0xd972, 0xe9af, 0xa6ac, 0xcaf7, 0xa7f1, 0xa7ef, 0xa7f0, 0xccc1, 0xa9f1, 0xac46, 0xcee7, 0xcee8, 0xac47, 0xd1ce, 0xaec4, 0xaec5, 0xd1cd, 0xb1d3, 0xb1cf, 0xd5a7, 0xb1d6, 0xb1d5, 0xb1ce, 0xb1d1, 0xb1d4, 0xb1d0, 0xd976, 0xb1cd, 0xb4af, 0xb4b1, 0xb4b2, 0xd975, 0xd978, 0xb4b0, 0xd973, 0xd977, 0xd974, 0xb771, 0xddbc, 0xba56, 0xe1f4, 0xbee3, 0xbcc4, 0xe5bd, 0xbcc5, 0xbcc6, 0xe5bf, 0xe5be, 0xe5c0, 0xe9b1, 0xe9b0, 0xecef, 0xecee, 0xc0c4, 0xc0c5, 0xf248, 0xa4e5, 0xd979, 0xb4b4, 0xb4b3, 0xddbd, 0xefd8, 0xc4e3, 0xf7de, 0xa4e6, 0xaec6, 0xb1d8, 0xb1d7, 0xd97a, 0xd97b, 0xb772, 0xe1f5, 0xba57, 0xe9b2, 0xa4e7, 0xa5b8, 0xa9f2, 0xccc2, 0xcee9, 0xac48, 0xb1d9, 0xd97c, 0xb4b5, 0xb773, 0xe5c1, 0xe5c2, 0xecf0, 0xc25f, 0xf8f0, 0xa4e8, 0xccc3, 0xa9f3, 0xac49, 0xceea, 0xaec7, 0xd1d2, 0xd1d0, 0xd1d1, 0xaec8, 0xd1cf, 0xb1db, 0xb1dc, 0xd5a8, 0xb1dd, 0xb1da, 0xd97d, 0xd97e, 0xddbe, 0xba59, 0xba58, 0xecf1, 0xefd9, 0xf24a, 0xf249, 0xf44f, 0xc95e, 0xac4a, 0xa4e9, 0xa5b9, 0xa6ae, 0xa6ad, 0xa6af, 0xa6b0, 0xc9ee, 0xc9ed, 0xcaf8, 0xa7f2, 0xcafb, 0xcafa, 0xcaf9, 0xcafc, 0xa9f4, 0xccc9, 0xccc5, 0xccce, 0xa9fb, 0xa9f9, 0xccca, 0xccc6, 0xcccd, 0xa9f8, 0xaa40, 0xccc8, 0xccc4, 0xa9fe, 0xcccb, 0xa9f7, 0xcccc, 0xa9fa, 0xa9fc, 0xccd0, 0xcccf, 0xccc7, 0xa9f6, 0xa9f5, 0xa9fd, 0xceef, 0xcef5, 0xac50, 0xac4d, 0xceec, 0xcef1, 0xac53, 0xac4b, 0xcef0, 0xac4e, 0xac51, 0xcef3, 0xac4c, 0xcef8, 0xac4f, 0xac52, 0xceed, 0xcef2, 0xcef6, 0xceee, 0xceeb, 0xcef7, 0xcef4, 0xaed0, 0xaec9, 0xaecc, 0xaecf, 0xd1d5, 0xaeca, 0xd1d3, 0xaece, 0xaecb, 0xd1d6, 0xaecd, 0xd5ac, 0xb1df, 0xd5ab, 0xd5ad, 0xb1de, 0xb1e3, 0xd1d4, 0xd5aa, 0xd5ae, 0xb1e0, 0xd5a9, 0xb1e2, 0xb1e1, 0xd9a7, 0xd9a2, 0xb4b6, 0xb4ba, 0xb4b7, 0xd9a5, 0xd9a8, 0xb4b8, 0xb4b9, 0xb4be, 0xddc7, 0xd9a6, 0xb4bc, 0xd9a3, 0xd9a1, 0xb4bd, 0xd9a4, 0xb779, 0xddbf, 0xb776, 0xb777, 0xb775, 0xddc4, 0xddc3, 0xddc0, 0xb77b, 0xddc2, 0xb4bb, 0xddc6, 0xddc1, 0xb778, 0xb774, 0xb77a, 0xddc5, 0xba5c, 0xe1f8, 0xe1f7, 0xe1f6, 0xba5a, 0xba5b, 0xe5c5, 0xe5c8, 0xbcc8, 0xbcc7, 0xe5c9, 0xe5c4, 0xbcca, 0xe5c6, 0xbcc9, 0xe5c3, 0xe5c7, 0xbee9, 0xbee6, 0xe9bb, 0xe9ba, 0xe9b9, 0xe9b4, 0xe9b5, 0xbee7, 0xbee4, 0xbee8, 0xe9b3, 0xbee5, 0xe9b6, 0xe9b7, 0xe9bc, 0xe9b8, 0xecf2, 0xc0c7, 0xefdc, 0xc0c6, 0xefda, 0xefdb, 0xc260, 0xc36e, 0xf24b, 0xc36d, 0xf451, 0xf452, 0xc466, 0xf450, 0xc4e4, 0xf7df, 0xc5ce, 0xf8aa, 0xf8ab, 0xa4ea, 0xa6b1, 0xa6b2, 0xa7f3, 0xccd1, 0xac54, 0xaed1, 0xb1e4, 0xb0d2, 0xb4bf, 0xb4c0, 0xb3cc, 0xd9a9, 0xb77c, 0xe1fa, 0xe1f9, 0xa4eb, 0xa6b3, 0xccd2, 0xaa42, 0xaa41, 0xcef9, 0xcefa, 0xd1d7, 0xd1d8, 0xaed2, 0xaed3, 0xaed4, 0xd5af, 0xb1e6, 0xb4c2, 0xb4c1, 0xddc8, 0xdf7a, 0xe1fb, 0xe9bd, 0xc261, 0xc467, 0xa4ec, 0xa5bc, 0xa5bd, 0xa5bb, 0xa5be, 0xa5ba, 0xa6b6, 0xc9f6, 0xa6b5, 0xa6b7, 0xc9f1, 0xc9f0, 0xc9f3, 0xc9f2, 0xc9f5, 0xa6b4, 0xc9ef, 0xc9f4, 0xcafd, 0xa7fd, 0xcafe, 0xcb43, 0xa7fc, 0xcb47, 0xcb42, 0xcb45, 0xa7f5, 0xa7f6, 0xa7f7, 0xa7f8, 0xa840, 0xcb41, 0xa7fa, 0xa841, 0xcb40, 0xcb46, 0xa7f9, 0xcb44, 0xa7fb, 0xa7f4, 0xa7fe, 0xaa57, 0xccd4, 0xaa43, 0xaa4d, 0xaa4e, 0xaa46, 0xaa58, 0xaa48, 0xccdc, 0xaa53, 0xccd7, 0xaa49, 0xcce6, 0xcce7, 0xccdf, 0xccd8, 0xaa56, 0xcce4, 0xaa51, 0xaa4f, 0xcce5, 0xcce3, 0xccdb, 0xccd3, 0xccda, 0xaa4a, 0xaa50, 0xaa44, 0xccde, 0xccdd, 0xccd5, 0xaa52, 0xcce1, 0xccd6, 0xaa55, 0xcce8, 0xaa45, 0xaa4c, 0xccd9, 0xcce2, 0xaa54, 0xaa47, 0xaa4b, 0xcce0, 0xcf5b, 0xac5c, 0xac69, 0xcf56, 0xcf4c, 0xac62, 0xcf4a, 0xac5b, 0xcf45, 0xac65, 0xcf52, 0xcefe, 0xcf41, 0xcf44, 0xcefb, 0xcf51, 0xcf61, 0xac60, 0xcf46, 0xcf58, 0xcefd, 0xcf5f, 0xcf60, 0xcf63, 0xcf5a, 0xcf4b, 0xcf53, 0xac66, 0xac59, 0xac61, 0xac6d, 0xac56, 0xac58, 0xcf43, 0xac6a, 0xac63, 0xcf5d, 0xcf40, 0xac6c, 0xac67, 0xcf49, 0xac6b, 0xcf50, 0xcf48, 0xac64, 0xcf5c, 0xcf54, 0xac5e, 0xcf62, 0xcf47, 0xac5a, 0xcf59, 0xcf4f, 0xac5f, 0xcf55, 0xac57, 0xcefc, 0xac68, 0xaee3, 0xac5d, 0xcf4e, 0xcf4d, 0xcf42, 0xcf5e, 0xcf57, 0xac55, 0xd1ec, 0xaeea, 0xd1ed, 0xd1e1, 0xaedf, 0xaeeb, 0xd1da, 0xd1e3, 0xd1eb, 0xd1d9, 0xd1f4, 0xaed5, 0xd1f3, 0xd1ee, 0xd1ef, 0xaedd, 0xaee8, 0xd1e5, 0xd1e6, 0xd1f0, 0xd1e7, 0xd1e2, 0xd1dc, 0xd1dd, 0xd1ea, 0xd1e4, 0xaed6, 0xaeda, 0xd1f2, 0xd1de, 0xaee6, 0xaee2, 0xaee5, 0xaeec, 0xaedb, 0xaee7, 0xd1e9, 0xaee9, 0xaed8, 0xaed7, 0xd1db, 0xd1df, 0xaee0, 0xd1f1, 0xd1e8, 0xd1e0, 0xaee4, 0xaee1, 0xaed9, 0xaedc, 0xd5c4, 0xd5b4, 0xd5b5, 0xd5b9, 0xd5c8, 0xd5c5, 0xd5be, 0xd5bd, 0xb1ed, 0xd5c1, 0xd5d0, 0xd5b0, 0xd5d1, 0xd5c3, 0xd5d5, 0xd5c9, 0xb1ec, 0xd5c7, 0xb1e7, 0xb1fc, 0xb1f2, 0xb1f6, 0xb1f5, 0xd5b1, 0xd5ce, 0xd5d4, 0xd5cc, 0xd5d3, 0xd5c0, 0xd5b2, 0xd5d2, 0xd5c2, 0xb1ea, 0xb1f7, 0xd5cb, 0xb1f0, 0xd5ca, 0xd5b3, 0xb1f8, 0xb1fa, 0xd5cd, 0xb1fb, 0xb1e9, 0xd5ba, 0xd5cf, 0xb1ef, 0xb1f9, 0xd5bc, 0xd5c6, 0xd5b7, 0xd5bb, 0xb1f4, 0xd5b6, 0xb1e8, 0xb1f1, 0xb1ee, 0xd5bf, 0xaede, 0xd9c0, 0xb1eb, 0xb1f3, 0xd9c3, 0xd9d9, 0xd9ce, 0xb4d6, 0xb4d1, 0xd9bd, 0xb4d2, 0xd9cd, 0xd9c6, 0xd9d3, 0xb4ce, 0xd9ab, 0xd9d5, 0xb4c4, 0xd9b3, 0xb4c7, 0xb4c6, 0xb4d7, 0xd9ad, 0xd9cf, 0xd9d0, 0xb4c9, 0xb4c5, 0xd9bb, 0xb4d0, 0xd9b6, 0xd9d1, 0xb4cc, 0xd9c9, 0xd9d6, 0xd9b0, 0xd9b5, 0xd9af, 0xb4cb, 0xd9c2, 0xddde, 0xd9b1, 0xb4cf, 0xd9ba, 0xd9d2, 0xb4ca, 0xd9b7, 0xd9b4, 0xd9c5, 0xb4cd, 0xb4c3, 0xb4d9, 0xd9c8, 0xd9c7, 0xd9ac, 0xb4c8, 0xd9d4, 0xd9bc, 0xd9be, 0xd9cb, 0xd9ca, 0xd9aa, 0xb4d3, 0xb4d5, 0xd9b2, 0xd9b9, 0xd9c1, 0xb4d4, 0xd9b8, 0xd9c4, 0xd9d7, 0xd9cc, 0xd9d8, 0xd9ae, 0xddf2, 0xb7a6, 0xddf0, 0xdddb, 0xdde0, 0xddd9, 0xddec, 0xddcb, 0xddd2, 0xddea, 0xddf4, 0xdddc, 0xddcf, 0xdde2, 0xdde7, 0xddd3, 0xdde4, 0xddd0, 0xddd7, 0xddd8, 0xb7a8, 0xddeb, 0xdde9, 0xddcc, 0xddee, 0xddef, 0xddf1, 0xb7ac, 0xb7a4, 0xd5b8, 0xddd4, 0xdde6, 0xddd5, 0xb7a1, 0xb7b1, 0xdded, 0xb7af, 0xb7ab, 0xddca, 0xb7a3, 0xddcd, 0xb7b0, 0xdddd, 0xddc9, 0xb7a9, 0xdde1, 0xddd1, 0xb7aa, 0xddda, 0xb77e, 0xb4d8, 0xdde3, 0xd9bf, 0xddce, 0xdde8, 0xb7a5, 0xdde5, 0xb7a2, 0xdddf, 0xb7ad, 0xddd6, 0xddf3, 0xb7a7, 0xdec6, 0xb7ae, 0xe24a, 0xe248, 0xe25e, 0xe246, 0xe258, 0xb77d, 0xba5f, 0xe242, 0xe25d, 0xe247, 0xe255, 0xba64, 0xba5d, 0xe25b, 0xe240, 0xe25a, 0xba6f, 0xe251, 0xe261, 0xba6d, 0xe249, 0xba5e, 0xe24b, 0xe259, 0xba67, 0xe244, 0xba6b, 0xba61, 0xe24d, 0xe243, 0xe1fc, 0xe257, 0xba68, 0xe260, 0xe1fd, 0xba65, 0xe253, 0xba66, 0xe245, 0xe250, 0xe24c, 0xe24e, 0xba60, 0xe25f, 0xba6e, 0xe24f, 0xe262, 0xe1fe, 0xe254, 0xba63, 0xba6c, 0xba6a, 0xe241, 0xe256, 0xba69, 0xba62, 0xe252, 0xe25c, 0xe5d5, 0xe5d1, 0xe5cd, 0xe5e1, 0xe5de, 0xbccd, 0xe5e5, 0xe5d4, 0xbcd8, 0xe5db, 0xe5d0, 0xe5da, 0xbcd5, 0xe5ee, 0xe5eb, 0xe5dd, 0xe5ce, 0xe5e2, 0xe5e4, 0xbcd1, 0xe5d8, 0xe5d3, 0xe5ca, 0xbcce, 0xbcd6, 0xe5e7, 0xbcd7, 0xe5cb, 0xe5ed, 0xe5e0, 0xe5e6, 0xbcd4, 0xe5e3, 0xe5ea, 0xbcd9, 0xbcd3, 0xe5dc, 0xe5cf, 0xe5ef, 0xe5cc, 0xe5e8, 0xbcd0, 0xe5d6, 0xe5d7, 0xbccf, 0xbccc, 0xe5d2, 0xbcd2, 0xbccb, 0xe5e9, 0xe5ec, 0xe5d9, 0xe9ca, 0xe9c2, 0xe9be, 0xbef6, 0xbeeb, 0xbef0, 0xbeec, 0xe9cc, 0xe9d7, 0xbeea, 0xe9c4, 0xe9cd, 0xe5df, 0xe9ce, 0xbef1, 0xe9dd, 0xbef5, 0xbef8, 0xe9c0, 0xbef4, 0xe9db, 0xe9dc, 0xe9d2, 0xe9d1, 0xe9c9, 0xe9d3, 0xe9da, 0xe9d9, 0xbeef, 0xbeed, 0xe9cb, 0xe9c8, 0xe9c5, 0xe9d8, 0xbef7, 0xe9d6, 0xbef3, 0xbef2, 0xe9d0, 0xe9bf, 0xe9c1, 0xe9c3, 0xe9d5, 0xe9cf, 0xbeee, 0xe9c6, 0xe9d4, 0xe9c7, 0xc0cf, 0xed45, 0xc0c8, 0xecf5, 0xed41, 0xc0ca, 0xed48, 0xecfc, 0xecf7, 0xed49, 0xecf3, 0xecfe, 0xc0d1, 0xed44, 0xed4a, 0xecfd, 0xc0c9, 0xed40, 0xecf4, 0xc0d0, 0xed47, 0xecf9, 0xc0cc, 0xecfb, 0xecf8, 0xc0d2, 0xecfa, 0xc0cb, 0xc0ce, 0xed43, 0xecf6, 0xed46, 0xed42, 0xc263, 0xefe7, 0xc268, 0xc269, 0xc262, 0xefe6, 0xefe3, 0xefe4, 0xc266, 0xefde, 0xefe2, 0xc265, 0xefdf, 0xc267, 0xc264, 0xefdd, 0xefe1, 0xefe5, 0xf251, 0xf24e, 0xf257, 0xf256, 0xf254, 0xf24f, 0xc372, 0xf250, 0xc371, 0xc0cd, 0xf253, 0xc370, 0xf258, 0xf252, 0xf24d, 0xefe0, 0xc36f, 0xf24c, 0xf456, 0xf455, 0xf255, 0xc468, 0xf459, 0xf45a, 0xf454, 0xf458, 0xf453, 0xf5d1, 0xf457, 0xc4e7, 0xc4e5, 0xf5cf, 0xf5d2, 0xf5ce, 0xf5d0, 0xc4e6, 0xf6e5, 0xf6e6, 0xc576, 0xf6e4, 0xf7e2, 0xc5cf, 0xf7e0, 0xf7e1, 0xf8ac, 0xc656, 0xf8f3, 0xf8f1, 0xf8f2, 0xf8f4, 0xf9bb, 0xa4ed, 0xa6b8, 0xaa59, 0xcce9, 0xcf64, 0xd1f5, 0xd1f7, 0xd1f6, 0xd1f8, 0xb1fd, 0xd5d7, 0xd1f9, 0xd5d6, 0xd5d8, 0xd5d9, 0xd9da, 0xb4db, 0xd9db, 0xd9dd, 0xb4dc, 0xb4da, 0xd9dc, 0xddfa, 0xddf8, 0xddf7, 0xddf6, 0xddf5, 0xb7b2, 0xddf9, 0xba70, 0xe263, 0xe265, 0xba71, 0xe264, 0xbcdb, 0xbcda, 0xe5f0, 0xe9df, 0xe9de, 0xe9e0, 0xbef9, 0xed4b, 0xc0d3, 0xefe8, 0xc26a, 0xf259, 0xc577, 0xa4ee, 0xa5bf, 0xa6b9, 0xa842, 0xaa5a, 0xaa5b, 0xac6e, 0xd1fa, 0xb7b3, 0xe6d1, 0xbefa, 0xc26b, 0xa4ef, 0xa6ba, 0xcceb, 0xaa5c, 0xccea, 0xcf65, 0xac6f, 0xcf66, 0xac70, 0xd1fc, 0xaeee, 0xaeed, 0xd5de, 0xd5dc, 0xd5dd, 0xd5db, 0xd5da, 0xd9de, 0xd9e1, 0xb4de, 0xd9df, 0xb4dd, 0xd9e0, 0xddfb, 0xe266, 0xe267, 0xe268, 0xe5f3, 0xe5f2, 0xbcdc, 0xe5f1, 0xe5f4, 0xe9e1, 0xe9e2, 0xe9e3, 0xed4c, 0xc0d4, 0xc26c, 0xf25a, 0xc4e8, 0xc95f, 0xac71, 0xcf67, 0xaeef, 0xb1fe, 0xb4df, 0xd9e2, 0xb7b5, 0xb7b4, 0xe269, 0xe26a, 0xbcdd, 0xbcde, 0xe9e5, 0xe9e4, 0xefe9, 0xf7e3, 0xa4f0, 0xc960, 0xa5c0, 0xa843, 0xcb48, 0xac72, 0xb7b6, 0xa4f1, 0xcf68, 0xac73, 0xcf69, 0xc0d5, 0xa4f2, 0xccec, 0xcf6a, 0xd242, 0xd241, 0xd1fe, 0xd1fd, 0xd243, 0xd240, 0xb240, 0xb241, 0xb4e0, 0xd9e3, 0xd9e4, 0xd9e5, 0xde41, 0xde42, 0xde40, 0xddfd, 0xddfe, 0xb7b7, 0xe26b, 0xe5f7, 0xe5f6, 0xe5f5, 0xe5f8, 0xe9e7, 0xe9e6, 0xbefb, 0xe9e8, 0xc0d6, 0xed4d, 0xefea, 0xf25b, 0xf6e7, 0xa4f3, 0xa5c2, 0xa5c1, 0xaa5d, 0xc961, 0xc97e, 0xa6bb, 0xc9f7, 0xcb49, 0xcb4a, 0xaa5e, 0xcced, 0xac74, 0xcf6b, 0xcf6c, 0xaef0, 0xaef4, 0xd244, 0xaef3, 0xaef1, 0xaef2, 0xd5df, 0xb242, 0xb4e3, 0xb4e1, 0xb4e2, 0xd9e6, 0xba72, 0xa4f4, 0xc9a1, 0xa5c3, 0xc9a4, 0xa5c6, 0xc9a3, 0xa5c5, 0xa5c4, 0xa844, 0xc9a2, 0xc9f8, 0xc9fc, 0xc9fe, 0xca40, 0xa6c5, 0xa6c6, 0xc9fb, 0xa6c1, 0xc9f9, 0xc9fd, 0xa6c2, 0xa6bd, 0xa6be, 0xa6c4, 0xc9fa, 0xa6bc, 0xa845, 0xa6bf, 0xa6c0, 0xa6c3, 0xcb5b, 0xcb59, 0xcb4c, 0xa851, 0xcb53, 0xa84c, 0xcb4d, 0xcb55, 0xcb52, 0xa84f, 0xcb51, 0xa856, 0xcb5a, 0xa858, 0xa85a, 0xcb4b, 0xa84d, 0xcb5c, 0xa854, 0xa857, 0xcd45, 0xa847, 0xa85e, 0xa855, 0xcb4e, 0xa84a, 0xa859, 0xcb56, 0xa848, 0xa849, 0xcd43, 0xcb4f, 0xa850, 0xa85b, 0xcb5d, 0xcb50, 0xa84e, 0xa853, 0xccee, 0xa85c, 0xcb57, 0xa852, 0xa85d, 0xa846, 0xcb54, 0xa84b, 0xcb58, 0xcd44, 0xaa6a, 0xaa7a, 0xccf5, 0xaa71, 0xcd4b, 0xaa62, 0xaa65, 0xcd42, 0xccf3, 0xccf7, 0xaa6d, 0xaa6f, 0xccfa, 0xaa76, 0xaa68, 0xaa66, 0xaa67, 0xaa75, 0xcd47, 0xaa70, 0xccf9, 0xccfb, 0xaa6e, 0xaa73, 0xccfc, 0xcd4a, 0xac75, 0xaa79, 0xaa63, 0xcd49, 0xcd4d, 0xccf8, 0xcd4f, 0xcd40, 0xaa6c, 0xccf4, 0xaa6b, 0xaa7d, 0xaa72, 0xccf2, 0xcf75, 0xaa78, 0xaa7c, 0xcd41, 0xcd46, 0xaa7e, 0xaa77, 0xaa69, 0xaa5f, 0xaa64, 0xccf6, 0xaa60, 0xcd4e, 0xccf0, 0xccef, 0xccfd, 0xccf1, 0xaa7b, 0xaef5, 0xaa74, 0xccfe, 0xaa61, 0xaca6, 0xcd4c, 0xcf7c, 0xcfa1, 0xcfa4, 0xcf77, 0xcfa7, 0xcfaa, 0xcfac, 0xcf74, 0xac76, 0xac7b, 0xd249, 0xacad, 0xcfa5, 0xcfad, 0xcf7b, 0xcf73, 0xd264, 0xac7e, 0xcfa2, 0xcf78, 0xcf7a, 0xaca5, 0xcf7d, 0xac7d, 0xcf70, 0xcfa8, 0xcfab, 0xac7a, 0xaca8, 0xcf6d, 0xacaa, 0xac78, 0xacae, 0xcfa9, 0xcf6f, 0xacab, 0xd25e, 0xcd48, 0xac7c, 0xac77, 0xcf76, 0xcf6e, 0xacac, 0xaca4, 0xcfa3, 0xaca9, 0xaca7, 0xcf79, 0xaca1, 0xcf71, 0xaca2, 0xaca3, 0xcf72, 0xcfa6, 0xac79, 0xcf7e, 0xd24c, 0xaefd, 0xaf43, 0xd255, 0xd25b, 0xd257, 0xd24a, 0xd24d, 0xd246, 0xd247, 0xaf4a, 0xaefa, 0xd256, 0xd25f, 0xaf45, 0xaef6, 0xaf40, 0xd24e, 0xaf42, 0xd24f, 0xd259, 0xaf44, 0xd268, 0xd248, 0xaefc, 0xaefb, 0xaf48, 0xd245, 0xd266, 0xd25a, 0xd267, 0xd261, 0xd253, 0xd262, 0xd25c, 0xd265, 0xd263, 0xaf49, 0xd254, 0xaef9, 0xaef8, 0xaf41, 0xaf47, 0xd260, 0xaf46, 0xd251, 0xb243, 0xd269, 0xd250, 0xd24b, 0xaefe, 0xaf4b, 0xaef7, 0xd258, 0xd25d, 0xb265, 0xd5e1, 0xd5e5, 0xb252, 0xb250, 0xb247, 0xd5e3, 0xd5e2, 0xb25b, 0xd5e8, 0xb255, 0xd5fa, 0xd647, 0xb244, 0xd5f7, 0xd5f0, 0xb267, 0xd5e0, 0xd5fc, 0xb264, 0xb258, 0xb263, 0xb24e, 0xd5ec, 0xd5fe, 0xd5f6, 0xb24f, 0xb249, 0xd645, 0xd5fd, 0xd640, 0xb251, 0xb259, 0xd642, 0xd5ea, 0xd5fb, 0xd5ef, 0xd644, 0xb25e, 0xb246, 0xb25c, 0xd5f4, 0xd5f2, 0xd5f3, 0xb253, 0xd5ee, 0xd5ed, 0xb248, 0xd5e7, 0xd646, 0xb24a, 0xd5f1, 0xb268, 0xb262, 0xd5e6, 0xb25f, 0xb25d, 0xb266, 0xd5f8, 0xb261, 0xd252, 0xd5f9, 0xb260, 0xd641, 0xb245, 0xd5f5, 0xb257, 0xd5e9, 0xb256, 0xb254, 0xb24c, 0xb24b, 0xd9e7, 0xd643, 0xd5eb, 0xd9fc, 0xb24d, 0xb541, 0xb25a, 0xb4ee, 0xd9f6, 0xb4fc, 0xd9ea, 0xb4eb, 0xb4e7, 0xda49, 0xb4ed, 0xb4f1, 0xb4ec, 0xb4f5, 0xda4d, 0xda44, 0xd9f1, 0xb4fa, 0xb4f4, 0xd9fd, 0xb4e4, 0xda4a, 0xda43, 0xb4e8, 0xd9f7, 0xb4f7, 0xda55, 0xda56, 0xb4e5, 0xda48, 0xb4f9, 0xd9fb, 0xd9ed, 0xd9ee, 0xb4fd, 0xd9f2, 0xd9f9, 0xd9f3, 0xb4fb, 0xb544, 0xd9ef, 0xd9e8, 0xd9e9, 0xd9eb, 0xb4ea, 0xd9f8, 0xb4f8, 0xb542, 0xd9fa, 0xda53, 0xda4b, 0xb4e6, 0xda51, 0xb4f2, 0xb4f0, 0xda57, 0xb4ef, 0xda41, 0xd9f4, 0xd9fe, 0xb547, 0xda45, 0xda42, 0xd9f0, 0xb543, 0xda4f, 0xda4c, 0xda54, 0xb4e9, 0xda40, 0xb546, 0xda47, 0xb4f3, 0xb4f6, 0xda46, 0xb545, 0xd9f5, 0xd5e4, 0xda50, 0xda4e, 0xda52, 0xd9ec, 0xb540, 0xde61, 0xde60, 0xde46, 0xb7bd, 0xde5f, 0xde49, 0xde4a, 0xb7c7, 0xde68, 0xb7c2, 0xde5e, 0xde43, 0xb7c8, 0xb7be, 0xde52, 0xde48, 0xde4b, 0xde63, 0xb7b8, 0xde6a, 0xde62, 0xb7c1, 0xde57, 0xb7cc, 0xb7cb, 0xb7c5, 0xde69, 0xb7b9, 0xde55, 0xde4c, 0xde59, 0xde65, 0xb7cd, 0xb7bb, 0xde54, 0xde4d, 0xb7c4, 0xb7c3, 0xde50, 0xde5a, 0xde64, 0xde47, 0xde51, 0xb7bc, 0xde5b, 0xb7c9, 0xb7c0, 0xde4e, 0xb7bf, 0xde45, 0xde53, 0xde67, 0xb4fe, 0xbab0, 0xde56, 0xe26c, 0xde58, 0xde66, 0xb7c6, 0xde4f, 0xb7ba, 0xb7ca, 0xbcf0, 0xde44, 0xde5d, 0xde5c, 0xe2aa, 0xbaad, 0xe27d, 0xe2a4, 0xbaa2, 0xe26e, 0xbaaf, 0xba77, 0xe26d, 0xe2b0, 0xbab1, 0xe271, 0xe2a3, 0xe273, 0xe2b3, 0xe2af, 0xba75, 0xbaa1, 0xe653, 0xbaae, 0xba7d, 0xe26f, 0xe2ae, 0xbaa3, 0xe2ab, 0xe2b8, 0xe275, 0xe27e, 0xe2b6, 0xe2ac, 0xba7c, 0xe27c, 0xba76, 0xba74, 0xbaa8, 0xe27a, 0xe277, 0xe278, 0xe2b2, 0xe2b7, 0xe2b5, 0xba7a, 0xe2b9, 0xba7e, 0xbaa7, 0xe270, 0xe5fa, 0xe279, 0xba78, 0xbaac, 0xbaa9, 0xba7b, 0xe2a5, 0xe274, 0xbaaa, 0xe2a7, 0xbaa4, 0xbaa6, 0xba73, 0xe2a9, 0xe2a1, 0xe272, 0xbaa5, 0xe2b1, 0xe2b4, 0xe27b, 0xe2a8, 0xba79, 0xbcdf, 0xe2a6, 0xe5f9, 0xe2ad, 0xe276, 0xe644, 0xe64e, 0xbce2, 0xe64d, 0xe659, 0xbce4, 0xe64b, 0xe64f, 0xbcef, 0xe646, 0xbce7, 0xe652, 0xe9f0, 0xbcf3, 0xbcf2, 0xe654, 0xe643, 0xe65e, 0xbced, 0xbce3, 0xe657, 0xe65b, 0xe660, 0xe655, 0xe649, 0xbce6, 0xbce9, 0xbcf1, 0xbcec, 0xe64c, 0xe2a2, 0xe648, 0xe65f, 0xbce8, 0xbceb, 0xe661, 0xbce0, 0xe656, 0xe5fb, 0xe65c, 0xc0df, 0xe64a, 0xbce1, 0xe645, 0xbce5, 0xe5fc, 0xbaab, 0xe641, 0xe65a, 0xe642, 0xe640, 0xbcea, 0xe658, 0xe5fe, 0xe651, 0xe650, 0xe65d, 0xe647, 0xbcee, 0xe9f3, 0xbf49, 0xbefe, 0xea40, 0xe9eb, 0xbf41, 0xe9f7, 0xbf48, 0xbf43, 0xe9f5, 0xed4f, 0xe9fb, 0xea42, 0xe9fa, 0xe9e9, 0xe9f8, 0xea44, 0xea46, 0xbefd, 0xea45, 0xbf44, 0xbf4a, 0xbf47, 0xe9fe, 0xbf46, 0xe9f9, 0xe9ed, 0xe9f2, 0xe9fd, 0xbf45, 0xbf42, 0xbefc, 0xbf40, 0xe9f1, 0xe5fd, 0xe9ec, 0xe9ef, 0xea41, 0xe9f4, 0xe9ea, 0xed4e, 0xea43, 0xe9ee, 0xe9fc, 0xed51, 0xc0e3, 0xc0d7, 0xc0db, 0xed53, 0xed59, 0xed57, 0xc0d9, 0xc0da, 0xc0e1, 0xed5a, 0xed52, 0xc0dc, 0xed56, 0xed55, 0xed5b, 0xc0e2, 0xc0dd, 0xc0e0, 0xed54, 0xc0e4, 0xc0de, 0xc0e5, 0xc0d8, 0xed58, 0xed50, 0xeff7, 0xc271, 0xeff4, 0xeff6, 0xc26f, 0xeff2, 0xeff3, 0xefee, 0xe9f6, 0xefef, 0xc270, 0xefeb, 0xc26d, 0xeff8, 0xc26e, 0xefec, 0xefed, 0xeff1, 0xc273, 0xc272, 0xeff0, 0xc378, 0xf25f, 0xf265, 0xc379, 0xf25c, 0xc376, 0xc373, 0xf267, 0xc377, 0xc374, 0xf25e, 0xf261, 0xf262, 0xf263, 0xf266, 0xeff5, 0xf25d, 0xc375, 0xf264, 0xf268, 0xf260, 0xf45d, 0xc46a, 0xf460, 0xc46b, 0xf468, 0xf45f, 0xf45c, 0xf45e, 0xf462, 0xf465, 0xf464, 0xf467, 0xf45b, 0xc469, 0xf463, 0xf466, 0xf469, 0xf461, 0xf5d3, 0xf5d4, 0xf5d8, 0xf5d9, 0xf5d6, 0xf5d7, 0xf5d5, 0xc4e9, 0xc578, 0xf6eb, 0xf6e8, 0xf6e9, 0xf6ea, 0xc579, 0xf7e5, 0xf7e4, 0xf8af, 0xc5f4, 0xf8ad, 0xf8b0, 0xf8ae, 0xf8f5, 0xc657, 0xc665, 0xf9a3, 0xf96c, 0xf9a2, 0xf9d0, 0xf9d1, 0xa4f5, 0xa6c7, 0xca41, 0xcb5e, 0xa85f, 0xa862, 0xcb5f, 0xa860, 0xa861, 0xcd58, 0xcd5a, 0xcd55, 0xcd52, 0xcd54, 0xaaa4, 0xaaa2, 0xcd56, 0xaaa3, 0xcd53, 0xcd50, 0xaaa1, 0xcd57, 0xcd51, 0xaaa5, 0xcd59, 0xcfaf, 0xcfb3, 0xacb7, 0xcfb6, 0xacaf, 0xacb2, 0xacb4, 0xacb6, 0xacb3, 0xcfb2, 0xcfb1, 0xacb1, 0xcfb4, 0xcfb5, 0xcfae, 0xacb5, 0xacb0, 0xcfb0, 0xd277, 0xd278, 0xd279, 0xaf50, 0xaf4c, 0xd26e, 0xd276, 0xd27b, 0xaf51, 0xd26c, 0xd272, 0xd26b, 0xd275, 0xd271, 0xaf4d, 0xaf4f, 0xd27a, 0xd26a, 0xd26d, 0xd273, 0xd274, 0xd27c, 0xd270, 0xaf4e, 0xb26d, 0xd64e, 0xd650, 0xd64c, 0xd658, 0xd64a, 0xd657, 0xb269, 0xd648, 0xda5b, 0xd652, 0xb26c, 0xd653, 0xd656, 0xd65a, 0xd64f, 0xd654, 0xb26a, 0xb26b, 0xd659, 0xd64d, 0xd649, 0xd65b, 0xd651, 0xd655, 0xd64b, 0xb548, 0xb549, 0xda65, 0xb54f, 0xda59, 0xda62, 0xda58, 0xb54c, 0xda60, 0xda5e, 0xda5f, 0xb54a, 0xda63, 0xda5c, 0xda5a, 0xb54b, 0xda5d, 0xda61, 0xb54d, 0xda64, 0xde70, 0xde77, 0xde79, 0xdea1, 0xb7da, 0xde6b, 0xb7d2, 0xde7a, 0xb7d7, 0xdea2, 0xb7ce, 0xde7d, 0xde6d, 0xde7e, 0xde6c, 0xb7dc, 0xde78, 0xb7cf, 0xdea3, 0xb7d4, 0xde71, 0xb7d9, 0xde7c, 0xde6f, 0xde76, 0xde72, 0xde6e, 0xb7d1, 0xb7d8, 0xb7d6, 0xb7d3, 0xb7db, 0xb7d0, 0xde75, 0xb7d5, 0xb54e, 0xde7b, 0xde73, 0xde74, 0xe2c1, 0xbab4, 0xe2bd, 0xe2c3, 0xe2bf, 0xbab6, 0xe2be, 0xe2c2, 0xe2ba, 0xe2bc, 0xbab5, 0xe2c0, 0xe2bb, 0xbab7, 0xbab2, 0xe2c4, 0xbab3, 0xe667, 0xe664, 0xe670, 0xe66a, 0xe66c, 0xbcf4, 0xe666, 0xe66e, 0xe66d, 0xe66b, 0xe671, 0xbcf7, 0xe668, 0xe66f, 0xbcf5, 0xe663, 0xe665, 0xbcf6, 0xe662, 0xe672, 0xe669, 0xea4a, 0xbf51, 0xea55, 0xea53, 0xbf4b, 0xea49, 0xea4c, 0xea4d, 0xea48, 0xbf55, 0xbf56, 0xea47, 0xea56, 0xea51, 0xbf4f, 0xbf4c, 0xea50, 0xea4e, 0xbf52, 0xea52, 0xbf4d, 0xbf4e, 0xea4f, 0xbf50, 0xea4b, 0xea54, 0xbf53, 0xea57, 0xea58, 0xbf54, 0xc0e7, 0xc0ee, 0xed5c, 0xed62, 0xed60, 0xc0ea, 0xc0e9, 0xc0e6, 0xed5e, 0xc0ec, 0xc0eb, 0xc0e8, 0xed61, 0xed5d, 0xed5f, 0xc0ed, 0xc277, 0xeffb, 0xc274, 0xc275, 0xeffd, 0xc276, 0xeffa, 0xeff9, 0xf26c, 0xeffc, 0xf26d, 0xc37a, 0xf26b, 0xf26a, 0xf269, 0xc37b, 0xc46c, 0xf46a, 0xf46b, 0xf5dc, 0xf5db, 0xc4ea, 0xf5da, 0xf6ec, 0xf6ed, 0xf7e6, 0xf8b1, 0xf8f6, 0xf9bc, 0xc679, 0xf9c6, 0xa4f6, 0xaaa6, 0xaaa7, 0xacb8, 0xc0ef, 0xa4f7, 0xaaa8, 0xaf52, 0xb7dd, 0xa4f8, 0xb26e, 0xbab8, 0xc962, 0xcfb7, 0xd27d, 0xe2c5, 0xc0f0, 0xa4f9, 0xaaa9, 0xcfb8, 0xcfb9, 0xda66, 0xb550, 0xdea4, 0xb7de, 0xe2c6, 0xbcf8, 0xc37c, 0xa4fa, 0xda67, 0xa4fb, 0xa6c9, 0xca42, 0xa6c8, 0xa865, 0xa864, 0xa863, 0xcb60, 0xaaaa, 0xaaab, 0xcd5b, 0xcfba, 0xcfbd, 0xacba, 0xcfbb, 0xacb9, 0xcfbc, 0xacbb, 0xd2a2, 0xd2a1, 0xd27e, 0xaf53, 0xd65d, 0xd65e, 0xb26f, 0xd65c, 0xd65f, 0xb552, 0xb270, 0xb551, 0xda6b, 0xda6a, 0xda68, 0xda69, 0xda6c, 0xdea6, 0xdea5, 0xdea9, 0xdea8, 0xdea7, 0xbab9, 0xe2c9, 0xe2c8, 0xbaba, 0xe2c7, 0xe673, 0xe674, 0xbcf9, 0xea59, 0xea5a, 0xf272, 0xc37d, 0xf271, 0xf270, 0xf26e, 0xf26f, 0xc4eb, 0xf46c, 0xf6ee, 0xf8f7, 0xa4fc, 0xc9a5, 0xa5c7, 0xc9a6, 0xca43, 0xca44, 0xcb66, 0xcb62, 0xcb61, 0xaaac, 0xcb65, 0xa867, 0xcb63, 0xa866, 0xcb67, 0xcb64, 0xcd5f, 0xcfbe, 0xcd5d, 0xcd64, 0xaaad, 0xaab0, 0xcd65, 0xcd61, 0xcd62, 0xcd5c, 0xaaaf, 0xcd5e, 0xaaae, 0xcd63, 0xcd60, 0xcfc2, 0xacbd, 0xacbe, 0xcfc5, 0xcfbf, 0xcfc4, 0xcfc0, 0xacbc, 0xcfc3, 0xcfc1, 0xd2a8, 0xd2a5, 0xd2a7, 0xaf58, 0xaf57, 0xaf55, 0xd2a4, 0xd2a9, 0xaf54, 0xaf56, 0xd2a6, 0xd667, 0xd2a3, 0xd2aa, 0xd662, 0xd666, 0xd665, 0xda6e, 0xda79, 0xd668, 0xd663, 0xda6d, 0xb274, 0xb273, 0xd661, 0xd664, 0xb275, 0xb272, 0xb271, 0xd660, 0xd669, 0xda70, 0xda77, 0xb554, 0xda76, 0xda73, 0xb556, 0xda75, 0xda6f, 0xda71, 0xda74, 0xda72, 0xb555, 0xda78, 0xb553, 0xb7df, 0xdead, 0xdeac, 0xdeaa, 0xb7e2, 0xb7e1, 0xdeae, 0xdeab, 0xe2ca, 0xbabb, 0xb7e0, 0xdeb0, 0xdeaf, 0xe2cd, 0xe2cb, 0xbcfa, 0xbabc, 0xe2cc, 0xe676, 0xbcfb, 0xe675, 0xe67e, 0xe67d, 0xe67b, 0xe67a, 0xe677, 0xe678, 0xe679, 0xe67c, 0xe6a1, 0xea5f, 0xea5c, 0xea5d, 0xbf57, 0xea5b, 0xea61, 0xea60, 0xea5e, 0xed64, 0xed65, 0xc0f1, 0xc0f2, 0xed63, 0xc279, 0xeffe, 0xc278, 0xc37e, 0xc3a1, 0xc46d, 0xf46e, 0xf46d, 0xf5dd, 0xf6ef, 0xc57a, 0xf7e8, 0xf7e7, 0xf7e9, 0xa5c8, 0xcfc6, 0xaf59, 0xb276, 0xd66a, 0xa5c9, 0xc9a7, 0xa4fd, 0xca45, 0xcb6c, 0xcb6a, 0xcb6b, 0xcb68, 0xa868, 0xcb69, 0xcd6d, 0xaab3, 0xcd6b, 0xcd67, 0xcd6a, 0xcd66, 0xaab5, 0xcd69, 0xaab2, 0xaab1, 0xaab4, 0xcd6c, 0xcd68, 0xacc2, 0xacc5, 0xcfce, 0xcfcd, 0xcfcc, 0xacbf, 0xcfd5, 0xcfcb, 0xacc1, 0xd2af, 0xcfd2, 0xcfd0, 0xacc4, 0xcfc8, 0xcfd3, 0xcfca, 0xcfd4, 0xcfd1, 0xcfc9, 0xacc0, 0xcfd6, 0xcfc7, 0xacc3, 0xd2b4, 0xd2ab, 0xd2b6, 0xd2ae, 0xd2b9, 0xd2ba, 0xd2ac, 0xd2b8, 0xd2b5, 0xd2b3, 0xd2b7, 0xaf5f, 0xaf5d, 0xd2b1, 0xd2ad, 0xd2b0, 0xd2bb, 0xd2b2, 0xaf5e, 0xcfcf, 0xaf5a, 0xaf5c, 0xd678, 0xd66d, 0xd66b, 0xd66c, 0xd673, 0xd674, 0xd670, 0xb27b, 0xd675, 0xd672, 0xd66f, 0xb279, 0xd66e, 0xb277, 0xb27a, 0xd671, 0xd679, 0xaf5b, 0xb278, 0xd677, 0xd676, 0xb27c, 0xda7e, 0xdaa1, 0xb560, 0xdaa7, 0xdaa9, 0xdaa2, 0xb55a, 0xdaa6, 0xdaa5, 0xb55b, 0xb561, 0xb562, 0xdaa8, 0xb558, 0xda7d, 0xda7b, 0xdaa3, 0xda7a, 0xb55f, 0xda7c, 0xdaa4, 0xdaaa, 0xb559, 0xb55e, 0xb55c, 0xb55d, 0xb557, 0xb7e9, 0xdeb7, 0xb7e8, 0xdebb, 0xdeb1, 0xdebc, 0xdeb2, 0xdeb3, 0xdebd, 0xdeba, 0xdeb8, 0xdeb9, 0xdeb5, 0xdeb4, 0xdebe, 0xb7e5, 0xdeb6, 0xb7ea, 0xb7e4, 0xb7eb, 0xb7ec, 0xb7e7, 0xb7e6, 0xe2ce, 0xbabe, 0xbabd, 0xe2d3, 0xbcfc, 0xbabf, 0xbac1, 0xe2d4, 0xb7e3, 0xbac0, 0xe2d0, 0xe2d2, 0xe2cf, 0xe2d1, 0xe6ab, 0xe6aa, 0xe6a7, 0xbd40, 0xea62, 0xbd41, 0xe6a6, 0xbcfe, 0xe6a8, 0xe6a5, 0xe6a2, 0xe6a9, 0xe6a3, 0xe6a4, 0xbcfd, 0xed69, 0xea66, 0xea65, 0xea67, 0xed66, 0xbf5a, 0xea63, 0xbf58, 0xbf5c, 0xbf5b, 0xea64, 0xea68, 0xbf59, 0xed6d, 0xc0f5, 0xc27a, 0xc0f6, 0xc0f3, 0xed6a, 0xed68, 0xed6b, 0xed6e, 0xc0f4, 0xed6c, 0xed67, 0xf042, 0xf045, 0xf275, 0xf040, 0xf46f, 0xf046, 0xc3a2, 0xf044, 0xc27b, 0xf041, 0xf043, 0xf047, 0xf276, 0xf274, 0xc3a3, 0xf273, 0xc46e, 0xc4ed, 0xf6f1, 0xc4ec, 0xf6f3, 0xf6f0, 0xf6f2, 0xc5d0, 0xf8b2, 0xa5ca, 0xcd6e, 0xd2bc, 0xd2bd, 0xb27d, 0xdebf, 0xbf5d, 0xc3a4, 0xc57b, 0xf8b3, 0xa5cb, 0xcd6f, 0xa260, 0xcfd7, 0xcfd8, 0xd2be, 0xd2bf, 0xb27e, 0xb2a1, 0xdaab, 0xdec2, 0xdec1, 0xdec0, 0xe2d5, 0xe2d6, 0xe2d7, 0xbac2, 0xe6ad, 0xe6ac, 0xea69, 0xbf5e, 0xbf5f, 0xed72, 0xed6f, 0xed70, 0xed71, 0xf049, 0xf048, 0xc27c, 0xf277, 0xf5de, 0xa5cc, 0xacc6, 0xb2a2, 0xdec3, 0xa5cd, 0xd2c0, 0xb2a3, 0xb563, 0xb564, 0xa5ce, 0xa5cf, 0xca46, 0xa86a, 0xa869, 0xacc7, 0xcfd9, 0xdaac, 0xa5d0, 0xa5d1, 0xa5d2, 0xa5d3, 0xa86b, 0xa86c, 0xcb6e, 0xcb6d, 0xaab6, 0xcd72, 0xcd70, 0xcd71, 0xcfda, 0xcfdb, 0xaccb, 0xacc9, 0xacca, 0xacc8, 0xaf60, 0xaf64, 0xaf63, 0xd2c1, 0xaf62, 0xaf61, 0xd2c2, 0xb2a6, 0xd67b, 0xd67a, 0xb2a4, 0xb2a5, 0xb566, 0xb565, 0xdaae, 0xdaad, 0xb2a7, 0xb7ed, 0xdec5, 0xb7ee, 0xdec4, 0xe2d8, 0xe6ae, 0xbd42, 0xea6a, 0xed73, 0xc3a6, 0xc3a5, 0xc57c, 0xa5d4, 0xcd73, 0xb2a8, 0xe2d9, 0xbac3, 0xcb6f, 0xcb70, 0xcd74, 0xaab8, 0xaab9, 0xaab7, 0xaccf, 0xacd0, 0xaccd, 0xacce, 0xcfdc, 0xcfdd, 0xaccc, 0xd2c3, 0xaf68, 0xaf69, 0xb2ab, 0xd2c9, 0xaf6e, 0xaf6c, 0xd2ca, 0xd2c5, 0xaf6b, 0xaf6a, 0xaf65, 0xd2c8, 0xd2c7, 0xd2c4, 0xaf6d, 0xd2c6, 0xaf66, 0xaf67, 0xb2ac, 0xd6a1, 0xd6a2, 0xb2ad, 0xd67c, 0xd67e, 0xd6a4, 0xd6a3, 0xd67d, 0xb2a9, 0xb2aa, 0xdab6, 0xb56b, 0xb56a, 0xdab0, 0xb568, 0xdab3, 0xb56c, 0xdab4, 0xb56d, 0xdab1, 0xb567, 0xb569, 0xdab5, 0xdab2, 0xdaaf, 0xded2, 0xdec7, 0xb7f0, 0xb7f3, 0xb7f2, 0xb7f7, 0xb7f6, 0xded3, 0xded1, 0xdeca, 0xdece, 0xdecd, 0xb7f4, 0xded0, 0xdecc, 0xded4, 0xdecb, 0xb7f5, 0xb7ef, 0xb7f1, 0xdec9, 0xe2db, 0xbac7, 0xe2df, 0xbac6, 0xe2dc, 0xbac5, 0xdec8, 0xdecf, 0xe2de, 0xbac8, 0xe2e0, 0xe2dd, 0xe2da, 0xe6b1, 0xe6b5, 0xe6b7, 0xe6b3, 0xe6b2, 0xe6b0, 0xbd45, 0xbd43, 0xbd48, 0xbd49, 0xe6b4, 0xbd46, 0xe6af, 0xbd47, 0xbac4, 0xe6b6, 0xbd44, 0xea6c, 0xea6b, 0xea73, 0xea6d, 0xea72, 0xea6f, 0xbf60, 0xea71, 0xbf61, 0xbf62, 0xea70, 0xea6e, 0xc0f8, 0xed74, 0xc0f7, 0xed77, 0xed75, 0xed76, 0xc0f9, 0xf04d, 0xc2a1, 0xf04e, 0xc27d, 0xf04f, 0xc27e, 0xf04c, 0xf050, 0xf04a, 0xc3a7, 0xf278, 0xc3a8, 0xc46f, 0xf04b, 0xc470, 0xc4ee, 0xf5df, 0xc57e, 0xf6f4, 0xc57d, 0xf7ea, 0xc5f5, 0xc5f6, 0xf9cc, 0xacd1, 0xcfde, 0xb56e, 0xb56f, 0xa5d5, 0xa6ca, 0xca47, 0xcb71, 0xa86d, 0xaaba, 0xacd2, 0xacd3, 0xacd4, 0xd6a6, 0xd2cb, 0xaf6f, 0xb2ae, 0xd6a5, 0xdab8, 0xb571, 0xdab7, 0xb570, 0xded5, 0xbd4a, 0xe6bb, 0xe6b8, 0xe6b9, 0xe6ba, 0xed78, 0xf051, 0xf471, 0xf470, 0xf6f5, 0xa5d6, 0xcd75, 0xaf70, 0xb572, 0xded6, 0xe2e1, 0xbd4b, 0xea74, 0xf052, 0xf472, 0xa5d7, 0xaabb, 0xacd7, 0xcfdf, 0xacd8, 0xacd6, 0xacd5, 0xd2cc, 0xaf71, 0xaf72, 0xaf73, 0xb2b0, 0xd6a7, 0xb2af, 0xdab9, 0xb2b1, 0xb573, 0xded7, 0xb7f8, 0xb7f9, 0xbac9, 0xbaca, 0xbd4c, 0xbf64, 0xea75, 0xbf63, 0xed79, 0xc0fa, 0xf053, 0xf473, 0xa5d8, 0xa86e, 0xcd78, 0xcd77, 0xaabc, 0xcd76, 0xaabd, 0xcd79, 0xcfe5, 0xacdb, 0xacda, 0xcfe7, 0xcfe6, 0xacdf, 0xacde, 0xacd9, 0xcfe1, 0xcfe2, 0xcfe3, 0xace0, 0xcfe0, 0xacdc, 0xcfe4, 0xacdd, 0xd2cf, 0xd2d3, 0xd2d1, 0xd2d0, 0xd2d4, 0xd2d5, 0xd2d6, 0xd2ce, 0xd2cd, 0xaf75, 0xaf76, 0xd2d7, 0xd2d2, 0xd6b0, 0xd2d8, 0xaf77, 0xaf74, 0xd6aa, 0xd6a9, 0xd6ab, 0xd6ac, 0xd6ae, 0xd6ad, 0xd6b2, 0xb2b5, 0xb2b2, 0xb2b6, 0xd6a8, 0xb2b7, 0xd6b1, 0xb2b4, 0xd6af, 0xb2b3, 0xdabc, 0xdabe, 0xdaba, 0xdabb, 0xdabf, 0xdac1, 0xdac2, 0xdabd, 0xdac0, 0xb574, 0xdedb, 0xdee0, 0xded8, 0xdedc, 0xdee1, 0xdedd, 0xb7fa, 0xb843, 0xb7fd, 0xded9, 0xdeda, 0xbace, 0xb846, 0xb7fe, 0xb844, 0xb7fc, 0xdedf, 0xb845, 0xdede, 0xb841, 0xb7fb, 0xb842, 0xdee2, 0xe2e6, 0xe2e8, 0xb840, 0xe2e3, 0xbacc, 0xe2e9, 0xbacd, 0xe2e7, 0xe2e2, 0xe2e5, 0xe2ea, 0xbacb, 0xe2e4, 0xbd4e, 0xe6bf, 0xe6be, 0xbd51, 0xbd4f, 0xe6bc, 0xbd4d, 0xe6bd, 0xbd50, 0xea7d, 0xeaa1, 0xea7e, 0xea76, 0xea7a, 0xea79, 0xea77, 0xbf66, 0xbf67, 0xbf65, 0xea78, 0xea7b, 0xea7c, 0xbf68, 0xc140, 0xeda3, 0xc0fc, 0xed7b, 0xc0fe, 0xc141, 0xc0fd, 0xeda2, 0xed7c, 0xc0fb, 0xeda1, 0xed7a, 0xed7e, 0xed7d, 0xf055, 0xc2a4, 0xc2a5, 0xc2a2, 0xc2a3, 0xf054, 0xf27b, 0xc3a9, 0xf279, 0xf27a, 0xf474, 0xf477, 0xf475, 0xf476, 0xf5e0, 0xc4ef, 0xf7eb, 0xf8b4, 0xc5f7, 0xf8f8, 0xf8f9, 0xc666, 0xa5d9, 0xace1, 0xdac3, 0xdee3, 0xa5da, 0xa86f, 0xaabe, 0xcfe8, 0xcfe9, 0xaf78, 0xdac4, 0xb575, 0xb847, 0xc142, 0xeda4, 0xf27c, 0xf478, 0xa5db, 0xcda1, 0xcd7a, 0xcd7c, 0xcd7e, 0xcd7d, 0xcd7b, 0xaabf, 0xace2, 0xcff2, 0xcfed, 0xcfea, 0xcff1, 0xace4, 0xace5, 0xcff0, 0xcfef, 0xcfee, 0xcfeb, 0xcfec, 0xcff3, 0xace3, 0xaf7c, 0xafa4, 0xafa3, 0xd2e1, 0xd2db, 0xd2d9, 0xafa1, 0xd6b9, 0xaf7a, 0xd2de, 0xd2e2, 0xd2e4, 0xd2e0, 0xd2da, 0xafa2, 0xd2df, 0xd2dd, 0xaf79, 0xd2e5, 0xafa5, 0xd2e3, 0xaf7d, 0xd2dc, 0xaf7e, 0xaf7b, 0xb2b9, 0xd6ba, 0xd6b3, 0xd6b5, 0xd6b7, 0xd6b8, 0xd6b6, 0xb2ba, 0xd6bb, 0xd6b4, 0xdac8, 0xb576, 0xdad0, 0xdac5, 0xdad1, 0xdac6, 0xdac7, 0xdacf, 0xdace, 0xdacb, 0xb2b8, 0xb577, 0xdac9, 0xdacc, 0xb578, 0xdacd, 0xdaca, 0xdeee, 0xdef2, 0xb84e, 0xe2f0, 0xb851, 0xdef0, 0xdeed, 0xdee8, 0xdeea, 0xdeeb, 0xdee4, 0xb84d, 0xb84c, 0xb848, 0xdee7, 0xb84f, 0xb850, 0xdee6, 0xdee9, 0xdef1, 0xb84a, 0xb84b, 0xdeef, 0xdee5, 0xe2f2, 0xbad0, 0xe2f4, 0xdeec, 0xe2f6, 0xbad4, 0xe2f7, 0xe2f3, 0xbad1, 0xe2ef, 0xbad3, 0xe2ec, 0xe2f1, 0xe2f5, 0xe2ee, 0xb849, 0xe2eb, 0xbad2, 0xe2ed, 0xbd54, 0xe6c1, 0xbd58, 0xbd56, 0xbacf, 0xe6c8, 0xe6c9, 0xbd53, 0xe6c7, 0xe6ca, 0xbd55, 0xbd52, 0xe6c3, 0xe6c0, 0xe6c5, 0xe6c2, 0xbd59, 0xe6c4, 0xe6c6, 0xbd57, 0xbf6a, 0xeaa8, 0xeaa2, 0xeaa6, 0xeaac, 0xeaad, 0xeaa9, 0xeaaa, 0xeaa7, 0xeaa4, 0xbf6c, 0xbf69, 0xeaa3, 0xeaa5, 0xbf6b, 0xeaab, 0xc146, 0xedaa, 0xeda5, 0xc145, 0xc143, 0xedac, 0xc144, 0xeda8, 0xeda9, 0xeda6, 0xedad, 0xf056, 0xc147, 0xeda7, 0xedae, 0xedab, 0xf05a, 0xf057, 0xc2a6, 0xf05b, 0xf05d, 0xf05c, 0xf058, 0xf059, 0xf2a3, 0xc3aa, 0xf27e, 0xf2a2, 0xf27d, 0xf2a4, 0xf2a1, 0xf47a, 0xf47d, 0xf479, 0xc471, 0xf47b, 0xf47c, 0xf47e, 0xc472, 0xc474, 0xc473, 0xf5e1, 0xf5e3, 0xf5e2, 0xf6f6, 0xf8b5, 0xf8fa, 0xa5dc, 0xcb72, 0xaac0, 0xcda3, 0xaac1, 0xaac2, 0xcda2, 0xcff8, 0xcff7, 0xace6, 0xace9, 0xace8, 0xace7, 0xcff4, 0xcff6, 0xcff5, 0xd2e8, 0xafa7, 0xd2ec, 0xd2eb, 0xd2ea, 0xd2e6, 0xafa6, 0xafaa, 0xafad, 0xafae, 0xd2e7, 0xd2e9, 0xafac, 0xafab, 0xafa9, 0xafa8, 0xd6c2, 0xd6c0, 0xd6bc, 0xb2bb, 0xd6bd, 0xb2bc, 0xd6be, 0xd6bf, 0xd6c1, 0xb2bd, 0xdad5, 0xdad4, 0xdad3, 0xdad2, 0xdef6, 0xb852, 0xdef3, 0xdef5, 0xb853, 0xb854, 0xdef4, 0xe341, 0xe2f9, 0xe2fa, 0xbad7, 0xbad5, 0xbad6, 0xe343, 0xe342, 0xe2fe, 0xe2fd, 0xe2fc, 0xe2fb, 0xe340, 0xe2f8, 0xe6cb, 0xe6d0, 0xe6ce, 0xe6cd, 0xe6cc, 0xe6cf, 0xeaae, 0xbf6d, 0xc148, 0xedb0, 0xc149, 0xedaf, 0xf05f, 0xf05e, 0xc2a7, 0xf2a5, 0xc3ab, 0xf4a1, 0xc5a1, 0xf6f7, 0xf8b7, 0xf8b6, 0xc9a8, 0xacea, 0xaceb, 0xd6c3, 0xb856, 0xa5dd, 0xa872, 0xa871, 0xa870, 0xcda4, 0xaac4, 0xaac3, 0xacee, 0xcffa, 0xcffd, 0xcffb, 0xacec, 0xaced, 0xcff9, 0xcffc, 0xafb5, 0xd2f3, 0xd2f5, 0xd2f4, 0xafb2, 0xd2ef, 0xafb0, 0xafaf, 0xafb3, 0xafb1, 0xafb4, 0xd2f2, 0xd2ed, 0xd2ee, 0xd2f1, 0xd2f0, 0xd6c6, 0xd6c7, 0xd6c5, 0xd6c4, 0xb2be, 0xb57d, 0xdad6, 0xdad8, 0xdada, 0xb57c, 0xb57a, 0xdad7, 0xb57b, 0xdad9, 0xb579, 0xdf41, 0xdef7, 0xdefa, 0xdefe, 0xb85a, 0xdefc, 0xdefb, 0xdef8, 0xdef9, 0xb858, 0xdf40, 0xb857, 0xb85c, 0xb85b, 0xb859, 0xdefd, 0xe349, 0xe348, 0xe344, 0xbad8, 0xe347, 0xe346, 0xbad9, 0xbd5e, 0xe6d2, 0xbd5f, 0xbd5b, 0xbd5d, 0xbd5a, 0xbd5c, 0xeaaf, 0xbf70, 0xeab1, 0xeab0, 0xe345, 0xbf72, 0xbf71, 0xbf6e, 0xbf6f, 0xedb5, 0xedb3, 0xc14a, 0xedb4, 0xedb6, 0xedb2, 0xedb1, 0xf060, 0xc2aa, 0xc2a8, 0xc2a9, 0xf2a6, 0xf2a7, 0xc3ad, 0xc3ac, 0xf4a3, 0xf4a4, 0xf4a2, 0xf6f8, 0xf6f9, 0xa5de, 0xca48, 0xa873, 0xcda5, 0xaac6, 0xaac5, 0xcda6, 0xd040, 0xacef, 0xcffe, 0xacf0, 0xafb6, 0xd2f8, 0xd2f6, 0xd2fc, 0xafb7, 0xd2f7, 0xd2fb, 0xd2f9, 0xd2fa, 0xd6c8, 0xd6ca, 0xb2bf, 0xd6c9, 0xb2c0, 0xb5a2, 0xb5a1, 0xb57e, 0xdadb, 0xdf44, 0xb85d, 0xb85e, 0xdf43, 0xdf42, 0xe34a, 0xbadb, 0xbada, 0xe34b, 0xe34c, 0xbd61, 0xbd60, 0xeab5, 0xe6d3, 0xe6d5, 0xe6d4, 0xeab4, 0xeab2, 0xeab6, 0xeab3, 0xbf73, 0xedb7, 0xc14b, 0xedb8, 0xedb9, 0xc2ab, 0xc2ac, 0xc475, 0xc5d1, 0xa5df, 0xd041, 0xd2fd, 0xafb8, 0xb3ba, 0xb3b9, 0xb5a4, 0xdadd, 0xb5a3, 0xdadc, 0xdf45, 0xbadc, 0xe34d, 0xbadd, 0xc476, 0xf4a5, 0xa6cb, 0xaac7, 0xcda7, 0xacf2, 0xacf1, 0xd042, 0xd043, 0xd340, 0xd342, 0xafb9, 0xd344, 0xd347, 0xd345, 0xd346, 0xd343, 0xd2fe, 0xafba, 0xd348, 0xd341, 0xd6d3, 0xb2c6, 0xd6dc, 0xb2c3, 0xd6d5, 0xb2c7, 0xb2c1, 0xd6d0, 0xd6dd, 0xd6d1, 0xd6ce, 0xb2c5, 0xb2c2, 0xd6d4, 0xd6d7, 0xb2c4, 0xd6d8, 0xb2c8, 0xd6d9, 0xd6cf, 0xd6d6, 0xd6da, 0xd6d2, 0xd6cd, 0xd6cb, 0xd6db, 0xdadf, 0xdae4, 0xdae0, 0xdae6, 0xb5a7, 0xd6cc, 0xdae1, 0xb5a5, 0xdade, 0xb5ac, 0xdae2, 0xb5ab, 0xdae3, 0xb5ad, 0xb5a8, 0xb5ae, 0xb5a9, 0xb5aa, 0xb5a6, 0xdae5, 0xb861, 0xdf50, 0xdf53, 0xdf47, 0xdf4c, 0xdf46, 0xb863, 0xdf4a, 0xdf48, 0xb862, 0xdf4f, 0xdf4e, 0xdf4b, 0xdf4d, 0xdf49, 0xbae1, 0xdf52, 0xb85f, 0xdf51, 0xe35d, 0xbae8, 0xe358, 0xbae7, 0xe34e, 0xe350, 0xbae0, 0xe355, 0xe354, 0xe357, 0xbae5, 0xe352, 0xe351, 0xbae4, 0xbadf, 0xe353, 0xbae2, 0xe359, 0xe35b, 0xe356, 0xe34f, 0xbae3, 0xbd69, 0xbade, 0xe35c, 0xe6d9, 0xbd62, 0xe6db, 0xbd63, 0xbd65, 0xe6de, 0xe6d6, 0xbae6, 0xe6dc, 0xe6d8, 0xb860, 0xbd68, 0xbd64, 0xbd66, 0xbd67, 0xbf76, 0xe6dd, 0xe6d7, 0xbd6a, 0xe6da, 0xeac0, 0xeabb, 0xeac5, 0xbf74, 0xeabd, 0xbf78, 0xeac3, 0xeaba, 0xeab7, 0xeac6, 0xc151, 0xbf79, 0xeac2, 0xeab8, 0xbf77, 0xeabc, 0xbf7b, 0xeab9, 0xeabe, 0xbf7a, 0xeac1, 0xeac4, 0xedcb, 0xedcc, 0xedbc, 0xedc3, 0xedc1, 0xc14f, 0xedc8, 0xeabf, 0xedbf, 0xedc9, 0xc14e, 0xedbe, 0xedbd, 0xedc7, 0xedc4, 0xedc6, 0xedba, 0xedca, 0xc14c, 0xedc5, 0xedce, 0xedc2, 0xc150, 0xc14d, 0xedc0, 0xedbb, 0xedcd, 0xbf75, 0xf063, 0xf061, 0xf067, 0xc2b0, 0xf065, 0xf064, 0xc2b2, 0xf06a, 0xc2b1, 0xf06b, 0xf068, 0xc2ae, 0xf069, 0xf062, 0xc2af, 0xc2ad, 0xf2ab, 0xf066, 0xf06c, 0xf2a8, 0xc3b2, 0xc3b0, 0xf2aa, 0xf2ac, 0xf2a9, 0xc3b1, 0xc3ae, 0xc3af, 0xc3b3, 0xc478, 0xf4aa, 0xf4a9, 0xf4a7, 0xf4a6, 0xf4a8, 0xc477, 0xc479, 0xc4f0, 0xf5e5, 0xf5e4, 0xf6fa, 0xf6fc, 0xf6fe, 0xf6fd, 0xf6fb, 0xc5a3, 0xc5a2, 0xc5d3, 0xc5d2, 0xc5d4, 0xf7ed, 0xf7ec, 0xf8fb, 0xf8b8, 0xf8fc, 0xc658, 0xc659, 0xf96d, 0xc67e, 0xa6cc, 0xcda8, 0xd045, 0xd046, 0xd044, 0xacf3, 0xd047, 0xd048, 0xd049, 0xd349, 0xd34f, 0xd34d, 0xafbb, 0xd34b, 0xd34c, 0xd34e, 0xd34a, 0xb2c9, 0xd6de, 0xb2cb, 0xd6e0, 0xb2ca, 0xd6df, 0xdae8, 0xb5af, 0xdaea, 0xdae7, 0xd6e1, 0xb5b0, 0xdae9, 0xdf56, 0xb864, 0xdf54, 0xb865, 0xdf55, 0xb866, 0xbae9, 0xe361, 0xe35e, 0xe360, 0xbaea, 0xbaeb, 0xe35f, 0xe6df, 0xe6e0, 0xbd6b, 0xe6e2, 0xe6e1, 0xa261, 0xeaca, 0xeacb, 0xeac7, 0xeac8, 0xbf7c, 0xbf7d, 0xeac9, 0xc157, 0xc153, 0xc158, 0xc154, 0xc156, 0xc152, 0xc155, 0xc2b3, 0xedcf, 0xf2ae, 0xf2ad, 0xf4ab, 0xc47a, 0xc47b, 0xf741, 0xf5e6, 0xf740, 0xf8fd, 0xf9a4, 0xa6cd, 0xa874, 0xcda9, 0xaac8, 0xacf6, 0xd04c, 0xacf4, 0xd04a, 0xacf9, 0xacf5, 0xacfa, 0xacf8, 0xd04b, 0xacf7, 0xafbf, 0xafbe, 0xd35a, 0xafc7, 0xd353, 0xd359, 0xafc3, 0xd352, 0xd358, 0xd356, 0xafc2, 0xafc4, 0xd355, 0xafbd, 0xd354, 0xafc8, 0xafc5, 0xafc9, 0xafc6, 0xd351, 0xd350, 0xd357, 0xafc0, 0xafbc, 0xafc1, 0xd6f0, 0xd6e9, 0xb5b5, 0xd6e8, 0xb2cf, 0xb2d6, 0xb2d3, 0xb2d9, 0xb2d8, 0xb2d4, 0xd6e2, 0xd6e5, 0xd6e4, 0xb2d0, 0xd6e6, 0xd6ef, 0xb2d1, 0xd6e3, 0xd6ec, 0xd6ed, 0xb2d2, 0xd6ea, 0xb2d7, 0xb2cd, 0xb2d5, 0xd6e7, 0xb2cc, 0xd6eb, 0xd6ee, 0xdafb, 0xdaf2, 0xb5b2, 0xdaf9, 0xdaf6, 0xdaee, 0xdaf7, 0xb5b4, 0xdaef, 0xdaeb, 0xb86c, 0xdaf4, 0xb5b1, 0xdafa, 0xb5b8, 0xb5ba, 0xdaed, 0xb5b9, 0xdaf0, 0xb5b3, 0xdaf8, 0xdaf1, 0xdaf5, 0xdaf3, 0xb5b6, 0xdaec, 0xb5bb, 0xb2ce, 0xb5b7, 0xb5bc, 0xb868, 0xdf5d, 0xdf5f, 0xdf61, 0xdf65, 0xdf5b, 0xdf59, 0xb86a, 0xdf60, 0xdf64, 0xdf5c, 0xdf58, 0xdf57, 0xdf62, 0xdf5a, 0xdf5e, 0xb86b, 0xb869, 0xdf66, 0xb867, 0xdf63, 0xe372, 0xbaee, 0xe36a, 0xbd78, 0xe374, 0xbaf1, 0xe378, 0xbaf7, 0xe365, 0xe375, 0xe362, 0xe377, 0xe366, 0xbafe, 0xbafb, 0xe376, 0xe370, 0xbaed, 0xbaf5, 0xbaf4, 0xbaf3, 0xbaf9, 0xe363, 0xbafa, 0xe371, 0xbaf6, 0xbaec, 0xe373, 0xbaef, 0xbaf0, 0xbaf8, 0xe368, 0xe367, 0xe364, 0xe36c, 0xe369, 0xe36d, 0xbafd, 0xe379, 0xbaf2, 0xe36e, 0xe36f, 0xe36b, 0xbafc, 0xe6e7, 0xbd70, 0xbd79, 0xbd75, 0xe6e4, 0xbd72, 0xbd76, 0xe6f0, 0xbd6c, 0xe6e8, 0xbd74, 0xe6eb, 0xe6e6, 0xbd73, 0xbd77, 0xe6e5, 0xbd71, 0xe6ef, 0xbd6e, 0xe6ee, 0xe6ed, 0xbd7a, 0xe572, 0xbd6d, 0xe6ec, 0xe6e3, 0xbd7b, 0xe6ea, 0xbd6f, 0xe6e9, 0xbfa2, 0xbfa7, 0xbf7e, 0xead8, 0xeacf, 0xeadb, 0xead3, 0xead9, 0xbfa8, 0xbfa1, 0xeacc, 0xead2, 0xeadc, 0xead5, 0xeada, 0xeace, 0xead6, 0xbfa3, 0xead4, 0xbfa6, 0xbfa5, 0xead0, 0xead1, 0xeacd, 0xead7, 0xbfa4, 0xeade, 0xeadd, 0xedda, 0xedd6, 0xc15f, 0xedd0, 0xc159, 0xc169, 0xeddc, 0xc161, 0xc15d, 0xedd3, 0xc164, 0xc167, 0xedde, 0xc15c, 0xedd5, 0xc165, 0xede0, 0xeddd, 0xedd1, 0xc160, 0xc15a, 0xc168, 0xedd8, 0xc163, 0xedd2, 0xc15e, 0xeddf, 0xc162, 0xc15b, 0xedd9, 0xc166, 0xedd7, 0xeddb, 0xf06e, 0xf074, 0xc2b9, 0xf077, 0xc2b4, 0xc2b5, 0xf06f, 0xf076, 0xf071, 0xc2ba, 0xc2b7, 0xf06d, 0xc2b6, 0xf073, 0xf075, 0xc2b8, 0xf072, 0xf070, 0xf2b8, 0xc3b7, 0xc3b8, 0xc3b4, 0xc3b5, 0xf2b4, 0xf2b2, 0xf2b6, 0xc3ba, 0xf2b7, 0xf2b0, 0xf2af, 0xf2b3, 0xf2b1, 0xc3b6, 0xf2b5, 0xf4ac, 0xc47e, 0xc47d, 0xf4ad, 0xf4af, 0xf4ae, 0xc4a1, 0xf5eb, 0xf5e8, 0xf5e9, 0xf5e7, 0xf5ea, 0xc4f2, 0xf5ec, 0xc4f1, 0xf742, 0xc5d5, 0xc5d7, 0xf7ee, 0xc5d6, 0xf8b9, 0xf940, 0xf942, 0xf8fe, 0xf941, 0xc66c, 0xa6ce, 0xacfb, 0xd26f, 0xafca, 0xb2da, 0xdafc, 0xdafd, 0xeadf, 0xc16a, 0xede1, 0xc2bb, 0xf2ba, 0xf2b9, 0xc4a2, 0xf5ed, 0xf743, 0xc5f8, 0xca49, 0xaac9, 0xa875, 0xd04d, 0xd360, 0xd35b, 0xd35f, 0xd35d, 0xafcb, 0xd35e, 0xd35c, 0xd6f1, 0xdafe, 0xdb40, 0xdf69, 0xdf6a, 0xb86e, 0xb86f, 0xdf68, 0xdf6b, 0xdf67, 0xb86d, 0xbb40, 0xb870, 0xe37a, 0xbd7c, 0xe6f1, 0xbd7d, 0xbfa9, 0xeae2, 0xeae0, 0xeae1, 0xede4, 0xede3, 0xede2, 0xf2bb, 0xc3b9, 0xf2bc, 0xf744, 0xc5f9, 0xf8ba, 0xa6cf, 0xaacb, 0xaaca, 0xd04f, 0xacfc, 0xd04e, 0xd362, 0xafcc, 0xd6f2, 0xd361, 0xb2dc, 0xd6f5, 0xd6f3, 0xd6f4, 0xb2db, 0xdb42, 0xdb43, 0xdb41, 0xb873, 0xdf6d, 0xdf6c, 0xdf6e, 0xb872, 0xb871, 0xe6f2, 0xe6f4, 0xbd7e, 0xe6f3, 0xeae3, 0xbfaa, 0xf079, 0xf078, 0xc3bb, 0xf2bd, 0xc3bd, 0xc3bc, 0xf4b0, 0xf5ee, 0xc4f3, 0xa6d0, 0xd050, 0xacfd, 0xd365, 0xafce, 0xd364, 0xd363, 0xafcd, 0xd6fb, 0xd6fd, 0xd6f6, 0xd6f7, 0xb2dd, 0xd6f8, 0xb2de, 0xd6fc, 0xd6f9, 0xd6fa, 0xb2df, 0xb5be, 0xb5bf, 0xdb44, 0xdf6f, 0xdf70, 0xe37e, 0xbb43, 0xbb41, 0xbb42, 0xe37b, 0xe37c, 0xe37d, 0xe6f9, 0xe6fa, 0xbda1, 0xe6f7, 0xe6f6, 0xe6f8, 0xe6f5, 0xbfad, 0xeae4, 0xbfab, 0xbfac, 0xede6, 0xc16b, 0xede5, 0xefa8, 0xf07a, 0xf07b, 0xc2bc, 0xc2bd, 0xc16c, 0xf2be, 0xf2bf, 0xf4b1, 0xc4a3, 0xa6d1, 0xa6d2, 0xacfe, 0xaacc, 0xafcf, 0xd051, 0xb5c0, 0xa6d3, 0xad41, 0xd052, 0xd053, 0xad40, 0xad42, 0xa6d4, 0xd054, 0xafd1, 0xd366, 0xafd3, 0xafd0, 0xafd2, 0xd741, 0xb2e0, 0xd740, 0xd6fe, 0xdf71, 0xe3a1, 0xbda2, 0xbfae, 0xeae6, 0xeae5, 0xede7, 0xf5ef, 0xa6d5, 0xcb73, 0xcdaa, 0xad43, 0xd055, 0xd368, 0xafd4, 0xd367, 0xafd5, 0xd743, 0xb2e2, 0xd742, 0xd744, 0xb2e1, 0xdb46, 0xdb47, 0xdb45, 0xb5c1, 0xb874, 0xb875, 0xbb45, 0xe3a3, 0xe3a2, 0xbb44, 0xe6fb, 0xe6fc, 0xeae7, 0xc170, 0xc16f, 0xc16d, 0xc16e, 0xc171, 0xf07c, 0xc2bf, 0xc2be, 0xf2c0, 0xf4b2, 0xc5a5, 0xc5a4, 0xa6d6, 0xd1fb, 0xb877, 0xb5c2, 0xb876, 0xbb46, 0xa6d7, 0xc9a9, 0xa6d8, 0xa6d9, 0xcdab, 0xcb76, 0xcb77, 0xa877, 0xcb74, 0xa876, 0xa879, 0xcb75, 0xa87b, 0xa87a, 0xcb78, 0xa878, 0xaad1, 0xaacf, 0xcdad, 0xaace, 0xaad3, 0xaad5, 0xaad2, 0xcdb0, 0xcdac, 0xaad6, 0xaad0, 0xa87c, 0xaad4, 0xcdaf, 0xcdae, 0xaacd, 0xd05b, 0xad47, 0xad48, 0xd05d, 0xd057, 0xd05a, 0xd063, 0xd061, 0xad49, 0xd067, 0xad4c, 0xd064, 0xd05c, 0xd059, 0xdb49, 0xd062, 0xad44, 0xd065, 0xd056, 0xd05f, 0xad46, 0xad4b, 0xd060, 0xad4f, 0xad4d, 0xd058, 0xad4a, 0xd05e, 0xad4e, 0xad45, 0xd066, 0xafda, 0xafe3, 0xafd8, 0xafd6, 0xd36a, 0xafde, 0xafdb, 0xd36c, 0xafdd, 0xd36b, 0xd369, 0xd36e, 0xafe2, 0xafe0, 0xdb48, 0xd36f, 0xd36d, 0xafd7, 0xafd9, 0xafdc, 0xafdf, 0xafe1, 0xd74e, 0xb2e4, 0xd745, 0xd747, 0xd748, 0xd750, 0xd74c, 0xd74a, 0xd74d, 0xd751, 0xb2e5, 0xb2e9, 0xd746, 0xd74f, 0xb2e7, 0xb2e6, 0xd74b, 0xd749, 0xb2e3, 0xb2e8, 0xb5c8, 0xdb51, 0xdb4f, 0xb5ca, 0xdb4a, 0xdfa1, 0xb5c9, 0xdb4e, 0xdb4b, 0xb5c5, 0xb5cb, 0xdb50, 0xb5c7, 0xdb4d, 0xbb47, 0xb5c6, 0xdb4c, 0xb5cc, 0xb5c4, 0xb5c3, 0xdf77, 0xdf75, 0xdf7b, 0xdf73, 0xdfa2, 0xdf78, 0xdf72, 0xb87b, 0xb8a3, 0xdf7d, 0xdf76, 0xb87e, 0xb87c, 0xdf7e, 0xb879, 0xb878, 0xdf79, 0xb87d, 0xb5cd, 0xdf7c, 0xdf74, 0xb87a, 0xb8a1, 0xb8a2, 0xbb4c, 0xbb48, 0xbb4d, 0xe3a6, 0xe3a5, 0xe3a7, 0xbb4a, 0xe3a4, 0xbb4b, 0xe3aa, 0xe3a9, 0xe3a8, 0xbb49, 0xe741, 0xe744, 0xbda8, 0xe743, 0xbda7, 0xbda3, 0xbda4, 0xbda5, 0xe740, 0xe6fe, 0xbda6, 0xe742, 0xe6fd, 0xeae9, 0xeaf3, 0xbfb1, 0xbfb0, 0xeaed, 0xeaef, 0xeaea, 0xeaee, 0xeae8, 0xeaf1, 0xbfaf, 0xeaf0, 0xeaec, 0xeaf2, 0xeaeb, 0xc174, 0xede8, 0xedee, 0xc178, 0xc17a, 0xc177, 0xc176, 0xc175, 0xc173, 0xede9, 0xedec, 0xc172, 0xeded, 0xc179, 0xedeb, 0xedea, 0xc2c0, 0xc2c1, 0xf0a1, 0xf07d, 0xf07e, 0xf2c2, 0xf2c1, 0xc3be, 0xf4b4, 0xc4a4, 0xf4b3, 0xf5f0, 0xf745, 0xc5a6, 0xf943, 0xf944, 0xc5d8, 0xa6da, 0xaad7, 0xdb52, 0xbb4e, 0xc17b, 0xedef, 0xa6db, 0xafe5, 0xafe4, 0xdb53, 0xeaf4, 0xa6dc, 0xad50, 0xdb54, 0xdb55, 0xdb56, 0xbb4f, 0xbfb2, 0xa6dd, 0xaad8, 0xd068, 0xafe6, 0xd370, 0xb2ea, 0xdb57, 0xb8a4, 0xbb50, 0xbfb3, 0xc17c, 0xc2c2, 0xf4b5, 0xa6de, 0xaad9, 0xafe7, 0xd752, 0xb5ce, 0xbb51, 0xe3ab, 0xe745, 0xa6df, 0xb5cf, 0xdfa3, 0xbb52, 0xa6e0, 0xcdb1, 0xd069, 0xad51, 0xd372, 0xafea, 0xafe8, 0xafe9, 0xafeb, 0xd371, 0xd757, 0xd754, 0xd756, 0xb2eb, 0xb2ed, 0xb2ec, 0xd753, 0xb2ee, 0xd755, 0xdb58, 0xdb59, 0xdb5a, 0xdfa6, 0xdfa7, 0xdfa5, 0xdfa8, 0xb8a5, 0xdfa4, 0xbb53, 0xe74a, 0xe746, 0xe749, 0xe74b, 0xe748, 0xe747, 0xeaf5, 0xeaf6, 0xeaf7, 0xbfb4, 0xbfb5, 0xedf1, 0xedf0, 0xedf2, 0xf0a3, 0xf0a2, 0xf2c4, 0xf2c5, 0xf2c3, 0xc4a5, 0xf4b6, 0xf4b7, 0xf746, 0xf7ef, 0xf8bb, 0xa6e1, 0xa87d, 0xc17d, 0xa6e2, 0xd758, 0xdb5b, 0xc641, 0xca4a, 0xca4b, 0xca4d, 0xa6e3, 0xca4e, 0xca4c, 0xcba2, 0xcba3, 0xcb7b, 0xcba1, 0xa8a1, 0xa8a2, 0xcb7c, 0xcb7a, 0xcb79, 0xcb7d, 0xa87e, 0xcb7e, 0xd06a, 0xcdb6, 0xaadc, 0xcdb5, 0xcdb7, 0xaadb, 0xcdbc, 0xaadf, 0xcdb2, 0xcdc0, 0xcdc6, 0xaae6, 0xcdc3, 0xaae3, 0xcdb9, 0xcdbf, 0xcdc1, 0xcdb4, 0xaae2, 0xaadd, 0xcdba, 0xaae4, 0xaae7, 0xaae1, 0xaada, 0xcdbe, 0xcdb8, 0xcdc5, 0xaae9, 0xaae5, 0xaae0, 0xcdbd, 0xafec, 0xcdbb, 0xaade, 0xaae8, 0xcdb3, 0xcdc2, 0xcdc4, 0xad62, 0xad5c, 0xad64, 0xad61, 0xd071, 0xd074, 0xad5d, 0xd06b, 0xad56, 0xad60, 0xad63, 0xad65, 0xd0a2, 0xd077, 0xad55, 0xd0a1, 0xad59, 0xad57, 0xad52, 0xd06f, 0xd07e, 0xd073, 0xd076, 0xd0a5, 0xad66, 0xd07d, 0xad5e, 0xd078, 0xd0a4, 0xd075, 0xd079, 0xd07c, 0xd06d, 0xd0a3, 0xd07b, 0xd06c, 0xd070, 0xad5f, 0xad5a, 0xad53, 0xad58, 0xad54, 0xad67, 0xd06e, 0xd3a5, 0xad5b, 0xd07a, 0xce41, 0xd3a8, 0xaffa, 0xd376, 0xd3a3, 0xd37d, 0xd3b2, 0xd3aa, 0xd37e, 0xd3a9, 0xd378, 0xd37c, 0xd3b5, 0xaffd, 0xd3ad, 0xd3a4, 0xafed, 0xd3b3, 0xd374, 0xd3ac, 0xaffc, 0xaff7, 0xd373, 0xaff5, 0xaff4, 0xaff9, 0xd3ab, 0xaff1, 0xaff8, 0xd072, 0xdb5c, 0xd3a6, 0xd37a, 0xaffb, 0xd37b, 0xd3a1, 0xaffe, 0xd375, 0xd3af, 0xd3ae, 0xd3b6, 0xaff3, 0xaff0, 0xd3b4, 0xd3b0, 0xd3a7, 0xd3a2, 0xaff6, 0xaff2, 0xd377, 0xafee, 0xd3b1, 0xafef, 0xd379, 0xd75e, 0xd760, 0xd765, 0xd779, 0xb2fc, 0xb2f2, 0xd75d, 0xb2fd, 0xb2fe, 0xd768, 0xd76f, 0xd775, 0xd762, 0xd769, 0xb340, 0xd777, 0xd772, 0xb2fa, 0xb2f8, 0xd76e, 0xd76a, 0xd75c, 0xb2ef, 0xd761, 0xd759, 0xb2f7, 0xb2f9, 0xd766, 0xd763, 0xb2f4, 0xd773, 0xb2f1, 0xd764, 0xd77a, 0xd76c, 0xd76b, 0xb2f0, 0xb2fb, 0xb2f3, 0xd75a, 0xd75f, 0xd770, 0xd776, 0xb341, 0xd75b, 0xd767, 0xd76d, 0xb2f6, 0xd778, 0xd771, 0xd774, 0xb2f5, 0xdb6c, 0xdb60, 0xb5d7, 0xdb7d, 0xdba7, 0xdbaa, 0xb5d5, 0xdb68, 0xdba3, 0xdb69, 0xdb77, 0xb5e2, 0xdb73, 0xb5df, 0xdb74, 0xdb5d, 0xdba4, 0xb5e8, 0xdba1, 0xdb75, 0xdbac, 0xdb70, 0xdfc8, 0xdbaf, 0xb5e6, 0xdb6e, 0xdb7a, 0xb5e9, 0xb5d4, 0xdb72, 0xdbad, 0xdb6b, 0xdb64, 0xdb6f, 0xdb63, 0xdb61, 0xb5d0, 0xdba5, 0xdb6a, 0xdba8, 0xdba9, 0xb5d8, 0xb5dd, 0xb5d9, 0xb5e1, 0xdb7e, 0xb5da, 0xdb76, 0xdb66, 0xb5d2, 0xdb5e, 0xdba2, 0xdbab, 0xdb65, 0xb5e0, 0xdbb0, 0xdb71, 0xdb6d, 0xb5d1, 0xb5e5, 0xdb7c, 0xb5e7, 0xdb78, 0xb5dc, 0xb5d6, 0xb5de, 0xb5d3, 0xb5e4, 0xdb79, 0xdb67, 0xdb7b, 0xdb62, 0xdba6, 0xdbae, 0xdb5f, 0xdfc7, 0xdfdd, 0xb855, 0xdfcc, 0xdfca, 0xdfb5, 0xb8a9, 0xdfc5, 0xdfd9, 0xdfc1, 0xb8b1, 0xdfd8, 0xdfbf, 0xb5e3, 0xdfcf, 0xdfc0, 0xdfd6, 0xb8b0, 0xb8a8, 0xdfaa, 0xdfb2, 0xdfcb, 0xdfc3, 0xdfdc, 0xdfc6, 0xb8b6, 0xdfd7, 0xb8ad, 0xdfc9, 0xdfd1, 0xdfb6, 0xdfd0, 0xdfe1, 0xdfb1, 0xdfd2, 0xdfdf, 0xdfab, 0xb5db, 0xdfb9, 0xdfb8, 0xb8af, 0xdfbc, 0xdfbe, 0xdfcd, 0xdfde, 0xb8b2, 0xb8b3, 0xdfb0, 0xb8ab, 0xdfb4, 0xdfda, 0xb8b4, 0xb8ac, 0xb8ae, 0xb8b5, 0xdfe0, 0xdfd3, 0xdfce, 0xdfbb, 0xdfba, 0xb8aa, 0xdfac, 0xb8a7, 0xdfc4, 0xdfad, 0xdfc2, 0xdfb7, 0xdfdb, 0xb8a6, 0xdfb3, 0xdfaf, 0xdfd5, 0xdfae, 0xbb60, 0xe3d3, 0xe3c2, 0xe3ac, 0xe3ca, 0xbb58, 0xe3bb, 0xe3c5, 0xbb5b, 0xe3be, 0xbb59, 0xe3af, 0xe3cd, 0xe3ae, 0xe3c1, 0xe3ad, 0xe3bf, 0xe3c8, 0xe3c6, 0xe3ba, 0xe3b5, 0xe3b3, 0xe3b4, 0xe3c7, 0xe3d2, 0xe3bc, 0xbb5a, 0xe3b7, 0xe3cb, 0xbb5d, 0xe3b6, 0xe3b0, 0xe3c0, 0xbb61, 0xbb55, 0xbb5e, 0xe3b8, 0xe3b2, 0xbb57, 0xdfd4, 0xbb56, 0xe3c3, 0xbb54, 0xbb63, 0xbb5c, 0xe3c4, 0xe3b9, 0xe3b1, 0xe3cc, 0xe3bd, 0xbb62, 0xe3d0, 0xbb5f, 0xe3cf, 0xe3c9, 0xe3ce, 0xe3d1, 0xe773, 0xe774, 0xe767, 0xe766, 0xe762, 0xbdb4, 0xbdac, 0xe776, 0xe775, 0xdfa9, 0xe75f, 0xe763, 0xe75d, 0xe770, 0xe761, 0xe777, 0xe75a, 0xe758, 0xe764, 0xe76e, 0xe769, 0xbdb6, 0xe74f, 0xe76d, 0xbdb7, 0xdfbd, 0xe75b, 0xe752, 0xe755, 0xe77b, 0xe75c, 0xe753, 0xe751, 0xe74e, 0xbdb0, 0xe765, 0xbdaf, 0xbdb3, 0xe760, 0xe768, 0xbda9, 0xe778, 0xe77c, 0xbdab, 0xe757, 0xe76b, 0xe76f, 0xe754, 0xe779, 0xbdb2, 0xbdb1, 0xe74c, 0xbdb5, 0xe772, 0xe756, 0xe76a, 0xe750, 0xe75e, 0xe759, 0xbdad, 0xbdae, 0xe76c, 0xe77d, 0xe77a, 0xe771, 0xe74d, 0xbdaa, 0xeb49, 0xeb40, 0xeb43, 0xbfbb, 0xeb45, 0xeaf9, 0xeb41, 0xeb47, 0xbfb8, 0xbfbc, 0xbfb6, 0xeafb, 0xeb4c, 0xeb46, 0xeafc, 0xeb55, 0xeb4f, 0xeaf8, 0xee46, 0xeafe, 0xbfb7, 0xeb4a, 0xeb54, 0xbfbf, 0xeb51, 0xeafd, 0xeb44, 0xeb48, 0xeb42, 0xeb56, 0xeb53, 0xeb50, 0xbfb9, 0xbfba, 0xbfbe, 0xeafa, 0xeb57, 0xbfbd, 0xeb4d, 0xeb4b, 0xeb4e, 0xee53, 0xee40, 0xee45, 0xee52, 0xee44, 0xedfb, 0xee41, 0xc1a2, 0xedf4, 0xee4d, 0xee4f, 0xedf3, 0xc1a1, 0xee51, 0xee49, 0xc1a8, 0xee50, 0xee42, 0xc1aa, 0xedf9, 0xeb52, 0xee4a, 0xee47, 0xedf5, 0xee55, 0xc1a4, 0xc1a5, 0xedf7, 0xee48, 0xee54, 0xee4b, 0xedfd, 0xc1a7, 0xc1a3, 0xee4c, 0xedfe, 0xee56, 0xedf8, 0xee43, 0xee4e, 0xedfa, 0xedfc, 0xc2cb, 0xedf6, 0xc1a9, 0xc2c4, 0xc17e, 0xc1a6, 0xc2c8, 0xf0b3, 0xf0a9, 0xf0a4, 0xf0aa, 0xf0b4, 0xf0b8, 0xf0b7, 0xc2ca, 0xc2c9, 0xf0ab, 0xf0b9, 0xf0ae, 0xf0a6, 0xf0a8, 0xf0a7, 0xf0ad, 0xf0b2, 0xf0a5, 0xf0ac, 0xf0b1, 0xc2c7, 0xf0af, 0xc2c5, 0xf0b0, 0xc2c3, 0xc2c6, 0xf2d5, 0xf0b5, 0xc3c2, 0xf2cd, 0xf2d1, 0xf2c9, 0xf2cc, 0xf2d4, 0xc3c0, 0xf2d9, 0xf2d2, 0xf2ca, 0xf2da, 0xf2d3, 0xc3c3, 0xc3c4, 0xf2d7, 0xf2cb, 0xc3bf, 0xc3c1, 0xf2c6, 0xf2ce, 0xf2c8, 0xf2d8, 0xf2d6, 0xf2c7, 0xf2cf, 0xf4be, 0xc3c5, 0xf2d0, 0xc4a7, 0xc4a9, 0xc4a6, 0xf4c3, 0xf4bb, 0xf4b9, 0xf4bd, 0xf4ba, 0xf4bf, 0xf4c1, 0xc4aa, 0xc4ac, 0xf4c0, 0xc4ad, 0xc4ab, 0xf4c2, 0xc4a8, 0xc4f4, 0xf5f1, 0xf5f7, 0xc4f6, 0xf4bc, 0xf5f6, 0xf5fd, 0xf5f4, 0xf5fb, 0xf5fa, 0xf4b8, 0xf5f5, 0xf0b6, 0xf5fe, 0xf5f3, 0xf5f8, 0xf5fc, 0xf5f2, 0xf74a, 0xc4f5, 0xf5f9, 0xf7f4, 0xf74b, 0xf749, 0xf747, 0xf748, 0xf74c, 0xc5d9, 0xf7f2, 0xf7f0, 0xf7f5, 0xf7f3, 0xf7f6, 0xc5da, 0xf7f1, 0xf8bc, 0xf945, 0xf946, 0xf947, 0xf9c7, 0xf9bd, 0xca4f, 0xaaea, 0xad68, 0xd3b8, 0xd3b7, 0xb040, 0xb342, 0xd77c, 0xd77b, 0xb5ea, 0xb8b8, 0xb8b7, 0xb8b9, 0xe3d4, 0xe77e, 0xeb58, 0xeb5a, 0xeb59, 0xc1ab, 0xee57, 0xf0ba, 0xf9a5, 0xa6e4, 0xcdc9, 0xcdca, 0xcdc8, 0xcdc7, 0xaaeb, 0xd0a9, 0xd0a7, 0xd0a6, 0xad69, 0xad6b, 0xad6a, 0xd0a8, 0xd3c4, 0xd3c1, 0xd3bf, 0xb041, 0xd3c2, 0xb046, 0xd3bc, 0xd3cb, 0xd3cd, 0xd3bd, 0xb043, 0xd3ce, 0xd3c9, 0xd3bb, 0xd3c0, 0xd3ca, 0xd3c6, 0xd3c3, 0xb048, 0xd3cc, 0xd3be, 0xd3c7, 0xd3b9, 0xb047, 0xb044, 0xd3c5, 0xd3c8, 0xd3ba, 0xb045, 0xb042, 0xb34c, 0xd7a5, 0xb34b, 0xd7a8, 0xd7ab, 0xb348, 0xb346, 0xd77e, 0xd7a9, 0xd7a7, 0xd7a4, 0xd7ac, 0xd7ad, 0xd7af, 0xd7b0, 0xd77d, 0xb345, 0xd7a2, 0xd7a1, 0xd7ae, 0xb347, 0xd7a3, 0xb349, 0xb344, 0xd7a6, 0xb34d, 0xb34a, 0xd7aa, 0xb5f1, 0xdbbf, 0xdbb4, 0xb5ee, 0xdfe7, 0xdbbd, 0xdbb1, 0xb5ec, 0xdbb6, 0xb5ef, 0xdbba, 0xdbb8, 0xb5f2, 0xb5eb, 0xdbb2, 0xdbb5, 0xb5f0, 0xdbb3, 0xdbbe, 0xdbbc, 0xdbb7, 0xdbb9, 0xdbbb, 0xb5ed, 0xdfe8, 0xdfee, 0xdfe4, 0xdfea, 0xb8ba, 0xdfe6, 0xb8c0, 0xb8bf, 0xb8be, 0xdfed, 0xb8c1, 0xb8c2, 0xdfe3, 0xdff0, 0xb8c3, 0xb8bd, 0xb8bc, 0xdfec, 0xb8c4, 0xdfe2, 0xdfe5, 0xdfef, 0xdfeb, 0xe3f4, 0xe3e9, 0xb8bb, 0xbb6a, 0xe3dd, 0xe3f2, 0xe3de, 0xbb65, 0xe3db, 0xe3e4, 0xe3dc, 0xbb67, 0xe3d6, 0xe3f1, 0xbb68, 0xe3ee, 0xe3ef, 0xe3d7, 0xbb6d, 0xe3e6, 0xe3e0, 0xe3e7, 0xe3da, 0xe3f3, 0xe3eb, 0xe3e5, 0xe3d5, 0xbb69, 0xe3ec, 0xbb6c, 0xe3f0, 0xe3ea, 0xbb66, 0xe3e8, 0xe3e2, 0xbb64, 0xe3d9, 0xe3e1, 0xe3ed, 0xe3df, 0xe3e3, 0xbdc1, 0xdfe9, 0xe7b2, 0xe7bb, 0xe7b1, 0xe7ad, 0xe7aa, 0xbdc2, 0xe7a8, 0xbb6b, 0xe7a1, 0xbdc0, 0xe7a7, 0xbdbf, 0xe7ac, 0xe7a9, 0xe7b9, 0xe7b4, 0xe7ae, 0xe7b3, 0xbdbb, 0xe7ab, 0xe7be, 0xe7a2, 0xe7a3, 0xe7ba, 0xbdbc, 0xe7bf, 0xbdbe, 0xe7c0, 0xe7b0, 0xe3d8, 0xe7b6, 0xe7af, 0xe7b8, 0xe7b5, 0xe7a6, 0xbdb9, 0xe7bd, 0xbdba, 0xe7a4, 0xbdbd, 0xeb64, 0xe7b7, 0xe7bc, 0xeb61, 0xbdb8, 0xbfc0, 0xeb6b, 0xeb67, 0xeb65, 0xeb60, 0xeb6f, 0xbfc4, 0xeb5c, 0xeb68, 0xeb69, 0xeb5f, 0xeb5e, 0xeb6c, 0xeb62, 0xeb5d, 0xeb63, 0xeb6e, 0xeb5b, 0xeb6d, 0xeb6a, 0xbfc2, 0xbfc1, 0xbfc3, 0xeb66, 0xf0cb, 0xee59, 0xc1b1, 0xee5d, 0xee5a, 0xee61, 0xee67, 0xee5c, 0xee70, 0xc1ae, 0xee6a, 0xee5f, 0xee6b, 0xee66, 0xee6d, 0xee5e, 0xc1b3, 0xc1b2, 0xee60, 0xee6e, 0xee58, 0xee6c, 0xc1ac, 0xee64, 0xee63, 0xee68, 0xee5b, 0xc1b0, 0xc1b4, 0xee62, 0xee69, 0xc1b5, 0xee65, 0xc1ad, 0xc1af, 0xf0c7, 0xf0c5, 0xf0cc, 0xf0c9, 0xf0cd, 0xf0be, 0xf0c6, 0xf0d1, 0xee6f, 0xf0c2, 0xc2cf, 0xe7a5, 0xf0bd, 0xf0ca, 0xf0c4, 0xf0c1, 0xf0bc, 0xf0bb, 0xf0d0, 0xf0c0, 0xf0bf, 0xc2cd, 0xf0c8, 0xc2cc, 0xc2ce, 0xf0c3, 0xf0cf, 0xf2de, 0xf2df, 0xc3c9, 0xf2dc, 0xc3c6, 0xf2e4, 0xc3ca, 0xf2e6, 0xf2db, 0xf0ce, 0xf2e8, 0xf2dd, 0xc3c7, 0xf2e3, 0xf2e5, 0xf2e0, 0xf2e7, 0xf2e2, 0xf2e1, 0xc3c8, 0xf4c5, 0xf4c6, 0xf4c8, 0xc4ae, 0xc4af, 0xf4c9, 0xf4c7, 0xf4c4, 0xf642, 0xf645, 0xf641, 0xc4fa, 0xf643, 0xc4f9, 0xc4f8, 0xc4f7, 0xf644, 0xf751, 0xf74f, 0xf74e, 0xf640, 0xf750, 0xf646, 0xf74d, 0xf7f9, 0xf7d7, 0xf7f7, 0xc5db, 0xf7f8, 0xf7fa, 0xf8bf, 0xc5fa, 0xf8be, 0xf8bd, 0xc5fb, 0xc65a, 0xf96e, 0xf9a7, 0xf9a6, 0xf9a8, 0xa6e5, 0xd0aa, 0xd3cf, 0xd3d0, 0xdbc0, 0xf647, 0xf8c0, 0xa6e6, 0xad6c, 0xd0ab, 0xd7b1, 0xb34e, 0xdbc2, 0xdbc1, 0xb5f3, 0xb8c5, 0xe7c1, 0xbdc3, 0xbdc4, 0xbfc5, 0xc5fc, 0xa6e7, 0xd0ac, 0xaaed, 0xd0ae, 0xd0ad, 0xad6d, 0xd3d1, 0xd3d8, 0xb049, 0xd3d6, 0xd3d4, 0xd3db, 0xd3d2, 0xd3d3, 0xb04a, 0xb04e, 0xd3dc, 0xb04d, 0xd3da, 0xd3d7, 0xd3d5, 0xb04b, 0xb04c, 0xd3d9, 0xb350, 0xd7b2, 0xb355, 0xd7c2, 0xb354, 0xd7c4, 0xd7b8, 0xb352, 0xd7c3, 0xd7b3, 0xb353, 0xd7bf, 0xd7bb, 0xd7bd, 0xd7b7, 0xd7be, 0xb34f, 0xd7ba, 0xd7b9, 0xd7b5, 0xd7c0, 0xd7bc, 0xd7b4, 0xd7b6, 0xb351, 0xd7c1, 0xb5f6, 0xdbcd, 0xdbc9, 0xdbcb, 0xdbc6, 0xdbc5, 0xdbc3, 0xdbca, 0xdbcc, 0xdbc8, 0xdbc7, 0xb5f4, 0xb5f5, 0xdbcf, 0xb8cd, 0xdff2, 0xdff8, 0xdff3, 0xdff4, 0xdff9, 0xb8cf, 0xb8c7, 0xb8ce, 0xdff1, 0xdbc4, 0xb8ca, 0xb8c8, 0xdff7, 0xdff6, 0xb8c9, 0xb8cb, 0xdff5, 0xb8c6, 0xb8cc, 0xe3f6, 0xbb74, 0xe442, 0xe441, 0xe3fb, 0xbb76, 0xe440, 0xe3f7, 0xe3f8, 0xbb6e, 0xbb70, 0xe3fd, 0xe3f5, 0xbb72, 0xbb71, 0xe3f9, 0xe3fe, 0xe3fc, 0xbb73, 0xe3fa, 0xdbce, 0xbb6f, 0xe7c2, 0xe7c9, 0xbdc6, 0xe7cd, 0xbdca, 0xe7c5, 0xe7c3, 0xe7cc, 0xbdc5, 0xe7cb, 0xbdc7, 0xbdc8, 0xe7c4, 0xbdc9, 0xe7ca, 0xe7c6, 0xe7c7, 0xe7c8, 0xbb75, 0xeb70, 0xeb7c, 0xbfca, 0xeb77, 0xeb79, 0xbfc8, 0xeb71, 0xeb75, 0xeb78, 0xbfc6, 0xbfc9, 0xeb7b, 0xeb73, 0xeb74, 0xeb7a, 0xeb72, 0xeb76, 0xbfc7, 0xee72, 0xee71, 0xc1b7, 0xee77, 0xc1b9, 0xc1b6, 0xee73, 0xc1ba, 0xee74, 0xee75, 0xee78, 0xc1b8, 0xf0d6, 0xf0d9, 0xf0d3, 0xf0d5, 0xf0d4, 0xf0d7, 0xf0d8, 0xee76, 0xf0d2, 0xc3cd, 0xf2ec, 0xf2ef, 0xf2f1, 0xf2ea, 0xf2eb, 0xf2ee, 0xf2f0, 0xc3ce, 0xc3cc, 0xc3cb, 0xf2ed, 0xf2e9, 0xf4ca, 0xc4b0, 0xf4cb, 0xf649, 0xc4fb, 0xf64b, 0xc4fc, 0xf648, 0xf64a, 0xc5a8, 0xf752, 0xc5a7, 0xf7fd, 0xf7fc, 0xf7fb, 0xf948, 0xf949, 0xf94b, 0xf94a, 0xca50, 0xa6e8, 0xad6e, 0xd7c5, 0xb5f7, 0xdffa, 0xc2d0, 0xf2f2, 0xa8a3, 0xb357, 0xb356, 0xdbd0, 0xb5f8, 0xdbd2, 0xdbd1, 0xdffb, 0xb8d0, 0xe443, 0xe446, 0xe445, 0xe444, 0xe7ce, 0xe7d0, 0xe7cf, 0xbfcc, 0xbfcb, 0xc1bb, 0xee79, 0xee7b, 0xee7a, 0xc2d1, 0xf2f4, 0xf2f3, 0xf4cc, 0xc4b1, 0xc4fd, 0xf754, 0xf753, 0xc65b, 0xa8a4, 0xd0af, 0xad6f, 0xd7c8, 0xd7c6, 0xd7c7, 0xdbd4, 0xdbd5, 0xe043, 0xdbd3, 0xdffc, 0xe041, 0xe040, 0xe042, 0xb8d1, 0xdffe, 0xdffd, 0xe044, 0xe449, 0xe447, 0xe448, 0xe7d3, 0xe7d1, 0xe7d2, 0xeb7d, 0xee7c, 0xee7d, 0xc2d2, 0xf2f5, 0xf4cd, 0xc4b2, 0xf64c, 0xf755, 0xc5a9, 0xf7fe, 0xf94c, 0xa8a5, 0xad71, 0xad72, 0xd0b0, 0xd0b1, 0xad70, 0xb054, 0xb052, 0xb051, 0xb058, 0xb050, 0xb059, 0xd3dd, 0xb056, 0xb053, 0xb057, 0xb055, 0xb04f, 0xb35f, 0xb359, 0xd7cc, 0xb35e, 0xb360, 0xb35a, 0xb35b, 0xd7ca, 0xb358, 0xd7cb, 0xb35d, 0xd7c9, 0xb35c, 0xb644, 0xb646, 0xdbd8, 0xb645, 0xb5f9, 0xb5fd, 0xb8e4, 0xe049, 0xdbda, 0xb5fe, 0xdbdd, 0xdbde, 0xb643, 0xdbe0, 0xdbe2, 0xdbe3, 0xdbd7, 0xdbd6, 0xdbe4, 0xb642, 0xdbe1, 0xdbdf, 0xb640, 0xb5fb, 0xb647, 0xdbdb, 0xdbdc, 0xdbd9, 0xb641, 0xb5fc, 0xb5fa, 0xe048, 0xb8df, 0xb8da, 0xb8d5, 0xb8e5, 0xb8d6, 0xb8d2, 0xb8e1, 0xb8de, 0xb8e0, 0xb8d7, 0xb8dc, 0xb8d3, 0xb8d4, 0xe050, 0xe04d, 0xe045, 0xe04a, 0xb8e2, 0xe051, 0xb8e3, 0xb8d9, 0xe047, 0xe04f, 0xe04b, 0xe04e, 0xe04c, 0xb8dd, 0xe046, 0xb8d8, 0xe44c, 0xbb78, 0xbb7b, 0xe44e, 0xbba5, 0xe44d, 0xbb7d, 0xbdcf, 0xe44f, 0xbba4, 0xe44b, 0xbba6, 0xbb79, 0xb8db, 0xbb7c, 0xbb7a, 0xbb7e, 0xbba2, 0xbb77, 0xbba7, 0xbba3, 0xbba1, 0xe44a, 0xbdd6, 0xbdd2, 0xbdd9, 0xe7d6, 0xbdda, 0xe7e2, 0xe7db, 0xbdcb, 0xe7e3, 0xe7dd, 0xbdd5, 0xe7de, 0xbdd4, 0xe7e1, 0xbdce, 0xe7df, 0xe7d5, 0xbdcd, 0xebaa, 0xbdd3, 0xbdd0, 0xbdd8, 0xe7d4, 0xe7d8, 0xbdcc, 0xe7d7, 0xe7d9, 0xe7da, 0xbdd7, 0xe7dc, 0xe7e0, 0xe7e4, 0xbddb, 0xbfd2, 0xeba5, 0xebab, 0xeba8, 0xeb7e, 0xebac, 0xeba1, 0xeba7, 0xbfcd, 0xbfd3, 0xebad, 0xbfcf, 0xbfd9, 0xbfd4, 0xebaf, 0xeba9, 0xbfd0, 0xeba2, 0xbfda, 0xeba3, 0xeba4, 0xbfdb, 0xbfd8, 0xbdd1, 0xbfce, 0xebb0, 0xbfdc, 0xbfd5, 0xebae, 0xbfd1, 0xbfd6, 0xbfd7, 0xc1c3, 0xeea4, 0xeead, 0xeeaa, 0xeeac, 0xc1c0, 0xeea5, 0xeeab, 0xc1bc, 0xeea7, 0xc1c4, 0xeea3, 0xeea8, 0xeeaf, 0xeba6, 0xeea9, 0xeea2, 0xc1bd, 0xeea1, 0xc1be, 0xeeb0, 0xc1bf, 0xeeae, 0xc1c2, 0xee7e, 0xc1c1, 0xeea6, 0xf0dc, 0xf0ea, 0xf0e5, 0xf0e7, 0xf0db, 0xc2d3, 0xf0da, 0xc2d6, 0xc2d5, 0xf0e9, 0xf0e1, 0xf0de, 0xf0e4, 0xf0dd, 0xf0df, 0xf0e8, 0xf0e6, 0xc2d4, 0xf0ed, 0xf0eb, 0xf0e2, 0xf0ec, 0xf0e3, 0xf2f9, 0xc3cf, 0xf341, 0xf64f, 0xc3d6, 0xf0e0, 0xf2f7, 0xc3d2, 0xf2f8, 0xf2fd, 0xc3d4, 0xc3d5, 0xf2f6, 0xf340, 0xf342, 0xf2fa, 0xf2fc, 0xf2fe, 0xf2fb, 0xf343, 0xc3d1, 0xc3d7, 0xc3d3, 0xc3d0, 0xf4d0, 0xc4b7, 0xf4ce, 0xf4d2, 0xf4d3, 0xc4b5, 0xf4d4, 0xf4d1, 0xf4cf, 0xc4b8, 0xc4b4, 0xf4d5, 0xc4b6, 0xc4b3, 0xc4fe, 0xc540, 0xf64e, 0xf64d, 0xf650, 0xf651, 0xc541, 0xf756, 0xf75b, 0xc5aa, 0xf758, 0xf757, 0xf75a, 0xf759, 0xf843, 0xc5dc, 0xf842, 0xf840, 0xf841, 0xc5fe, 0xc5fd, 0xf8c1, 0xf8c2, 0xc640, 0xf94d, 0xf94e, 0xc667, 0xc66d, 0xf9a9, 0xf9c8, 0xa8a6, 0xd7cd, 0xd7ce, 0xe052, 0xe450, 0xe7e5, 0xc1c6, 0xc1c5, 0xf0ee, 0xf344, 0xf844, 0xa8a7, 0xd3de, 0xb05a, 0xb361, 0xe054, 0xe053, 0xbddc, 0xe7e6, 0xbddd, 0xeeb1, 0xc2d7, 0xc676, 0xa8a8, 0xcdcb, 0xd3df, 0xb362, 0xd7cf, 0xd7d0, 0xdbe5, 0xb648, 0xb8e6, 0xe056, 0xe055, 0xe057, 0xe451, 0xe452, 0xbba8, 0xbfdd, 0xbdde, 0xbfde, 0xeeb5, 0xeeb2, 0xeeb4, 0xeeb3, 0xc1c7, 0xf0ef, 0xf346, 0xf345, 0xcba4, 0xb05c, 0xb05b, 0xd3e0, 0xd7d1, 0xdbe7, 0xdbe6, 0xb649, 0xe059, 0xe05a, 0xe058, 0xb8e8, 0xb8e7, 0xbbaa, 0xbba9, 0xe7e7, 0xebb3, 0xebb1, 0xebb2, 0xbfdf, 0xeeb7, 0xeeb6, 0xf0f2, 0xf0f1, 0xf0f0, 0xf347, 0xf9aa, 0xa8a9, 0xad73, 0xad74, 0xb05d, 0xb05e, 0xd3e2, 0xd3e1, 0xd7d2, 0xb368, 0xb366, 0xb363, 0xb367, 0xb365, 0xb364, 0xb64a, 0xdbea, 0xb8ed, 0xb64c, 0xb651, 0xdbec, 0xb653, 0xb652, 0xb655, 0xdbeb, 0xdbe8, 0xb64f, 0xb64b, 0xb64d, 0xdbe9, 0xb654, 0xb650, 0xb64e, 0xb8ef, 0xb8ee, 0xb8ec, 0xb8f0, 0xb8ea, 0xb8eb, 0xb8e9, 0xe05b, 0xe454, 0xbbac, 0xbbad, 0xbbab, 0xe453, 0xe455, 0xe7ea, 0xe7ec, 0xbde7, 0xe7ed, 0xbde0, 0xe7e9, 0xbddf, 0xbde9, 0xbde5, 0xbde6, 0xbde2, 0xe7e8, 0xbde1, 0xe7ee, 0xe7eb, 0xbde8, 0xbde3, 0xbde4, 0xebb5, 0xebb7, 0xebb6, 0xebb8, 0xbfe0, 0xebb4, 0xc1cb, 0xeeb8, 0xc1c8, 0xc1cc, 0xc1ca, 0xc1c9, 0xf0f3, 0xf0f6, 0xf0f5, 0xf0f4, 0xc2d8, 0xf348, 0xf349, 0xc3d8, 0xf34a, 0xc3d9, 0xc4ba, 0xc4b9, 0xf652, 0xc542, 0xf653, 0xf75c, 0xc5ab, 0xc5ac, 0xf845, 0xc642, 0xa8aa, 0xb36a, 0xb369, 0xe05c, 0xe05d, 0xbbae, 0xebb9, 0xbdea, 0xebba, 0xeeb9, 0xa8ab, 0xd0b2, 0xad76, 0xad75, 0xd3e3, 0xb05f, 0xd3e4, 0xd7d5, 0xd7d4, 0xd7d3, 0xdbee, 0xb658, 0xdbed, 0xb657, 0xdbef, 0xb656, 0xe05f, 0xe062, 0xe060, 0xe061, 0xe065, 0xe05e, 0xe066, 0xe063, 0xe064, 0xbbb0, 0xe456, 0xbbaf, 0xe7f2, 0xe7f0, 0xbdeb, 0xe7ef, 0xe7f1, 0xbdec, 0xebbb, 0xebbc, 0xc1cd, 0xf34c, 0xf34e, 0xf34b, 0xf34d, 0xf4d6, 0xf654, 0xf96f, 0xa8ac, 0xad77, 0xd3e5, 0xd3e7, 0xd3e6, 0xd7d8, 0xb36c, 0xd7d6, 0xb36b, 0xd7d9, 0xd7da, 0xd7d7, 0xdbfb, 0xb660, 0xdbf3, 0xdbf9, 0xb65b, 0xb65e, 0xdbf2, 0xb659, 0xdbf6, 0xe06c, 0xb65d, 0xdbf1, 0xdbf7, 0xdbf4, 0xdbfa, 0xdbf0, 0xdbf8, 0xb65c, 0xb65f, 0xdbf5, 0xb65a, 0xb8f2, 0xe068, 0xb8f1, 0xe06f, 0xe06e, 0xb8f8, 0xb8f9, 0xe070, 0xb8f3, 0xe06d, 0xb8f7, 0xe072, 0xe069, 0xe06b, 0xb8f4, 0xe067, 0xe06a, 0xe071, 0xb8f5, 0xe073, 0xb8f6, 0xbbb1, 0xe45b, 0xe461, 0xe459, 0xe462, 0xe458, 0xe45d, 0xe463, 0xe460, 0xe45f, 0xe45e, 0xe457, 0xe45c, 0xe45a, 0xbdf1, 0xbdee, 0xe7fb, 0xe841, 0xe843, 0xe840, 0xe7f8, 0xe7fa, 0xe845, 0xe842, 0xe7fc, 0xe846, 0xe7f9, 0xe844, 0xbdef, 0xbdf5, 0xbdf3, 0xe7f3, 0xbdf4, 0xbdf0, 0xe7f4, 0xe7f6, 0xe7f5, 0xe7fd, 0xe7fe, 0xbdf2, 0xbded, 0xe7f7, 0xebc6, 0xbfe2, 0xebbd, 0xbfe3, 0xbfe6, 0xebc2, 0xebbf, 0xbfe5, 0xebc3, 0xebc4, 0xebbe, 0xebc7, 0xebc0, 0xebc5, 0xbfe4, 0xbfe1, 0xebc1, 0xeebf, 0xc1d0, 0xc1ce, 0xc1d1, 0xc1cf, 0xeebe, 0xeebb, 0xeeba, 0xeebd, 0xeebc, 0xf145, 0xc2de, 0xf0fb, 0xf0fa, 0xc2d9, 0xf141, 0xf140, 0xf0f7, 0xf143, 0xf0fc, 0xc2dd, 0xf0f9, 0xf142, 0xf0f8, 0xc2da, 0xc2dc, 0xf0fd, 0xc2db, 0xf0fe, 0xf144, 0xf352, 0xc3de, 0xf34f, 0xf353, 0xc3db, 0xf351, 0xc3e0, 0xc3dd, 0xf350, 0xc3df, 0xf354, 0xc3da, 0xc4bc, 0xc4be, 0xf4d9, 0xc4bd, 0xf4d7, 0xc3dc, 0xf4d8, 0xc4bb, 0xc543, 0xc545, 0xf656, 0xc544, 0xf655, 0xf761, 0xc5ad, 0xf760, 0xc5ae, 0xf75e, 0xf75d, 0xf762, 0xf763, 0xf846, 0xf75f, 0xf8c6, 0xf8c3, 0xf8c4, 0xf8c5, 0xc65c, 0xf951, 0xf950, 0xf94f, 0xf970, 0xf9be, 0xf9ab, 0xc66e, 0xa8ad, 0xb060, 0xb8fa, 0xbdf6, 0xebc8, 0xc2df, 0xf355, 0xf9ac, 0xa8ae, 0xaaee, 0xad79, 0xad78, 0xb063, 0xd3e8, 0xb061, 0xd3e9, 0xb062, 0xd7df, 0xd7db, 0xb36d, 0xd7de, 0xd7dd, 0xd7dc, 0xb36e, 0xd7e0, 0xd7e1, 0xdc43, 0xdc41, 0xdc45, 0xdc46, 0xdc4c, 0xdc48, 0xdc4a, 0xdc42, 0xdbfc, 0xdc49, 0xdc4b, 0xdc44, 0xdc47, 0xdbfd, 0xb662, 0xdc40, 0xdbfe, 0xb661, 0xb663, 0xb8fd, 0xe075, 0xe077, 0xe076, 0xe07b, 0xb8fb, 0xe078, 0xe074, 0xe079, 0xe07a, 0xb8fc, 0xb8fe, 0xe07c, 0xe467, 0xe466, 0xe464, 0xe465, 0xbbb3, 0xbbb5, 0xbbb2, 0xbbb4, 0xe84d, 0xe84e, 0xe849, 0xe84a, 0xbdf8, 0xbdfd, 0xbdf7, 0xbdfe, 0xbdf9, 0xe84b, 0xe84c, 0xe848, 0xbe40, 0xbdfb, 0xbdfa, 0xbdfc, 0xe847, 0xebca, 0xbfe8, 0xebcc, 0xbfea, 0xebcf, 0xebcb, 0xebc9, 0xebce, 0xbfe9, 0xebcd, 0xbfe7, 0xc1d3, 0xc1d6, 0xeec1, 0xc1d4, 0xeec0, 0xc1d2, 0xc1d5, 0xf146, 0xf147, 0xf148, 0xc2e0, 0xf149, 0xc2e1, 0xc3e2, 0xf358, 0xf359, 0xf357, 0xf356, 0xf35a, 0xc3e1, 0xf4dd, 0xf4db, 0xf4dc, 0xf4de, 0xf4da, 0xf4df, 0xf658, 0xf659, 0xf657, 0xc546, 0xf764, 0xc5af, 0xf765, 0xf848, 0xf847, 0xa8af, 0xb664, 0xb940, 0xbbb6, 0xbfec, 0xbfeb, 0xc3e3, 0xc47c, 0xc547, 0xa8b0, 0xb064, 0xb941, 0xf35b, 0xcba6, 0xa8b1, 0xa8b4, 0xa8b3, 0xa8b2, 0xcba5, 0xcdcd, 0xcdcf, 0xaaef, 0xaaf1, 0xcdcc, 0xcdce, 0xaaf0, 0xcdd1, 0xcdd0, 0xcdd2, 0xd0b6, 0xd0b4, 0xad7c, 0xd0b3, 0xada3, 0xad7e, 0xad7b, 0xada4, 0xad7d, 0xada2, 0xada1, 0xd0b5, 0xad7a, 0xb06a, 0xd3eb, 0xd3f1, 0xb067, 0xb06e, 0xb069, 0xd3ee, 0xd3f0, 0xb06c, 0xd3ea, 0xd3ed, 0xb068, 0xb065, 0xd3ec, 0xb06b, 0xd3ef, 0xb06d, 0xb066, 0xd7e3, 0xd7e6, 0xb370, 0xb37a, 0xb376, 0xd7e4, 0xb37e, 0xb377, 0xb37c, 0xb372, 0xb36f, 0xb371, 0xb37d, 0xd7e5, 0xb375, 0xb378, 0xb374, 0xb379, 0xd7e7, 0xb37b, 0xb373, 0xd7e2, 0xdc4d, 0xb665, 0xdc4f, 0xb667, 0xb669, 0xdc4e, 0xb666, 0xb66a, 0xb668, 0xb947, 0xe0a3, 0xb94f, 0xe07e, 0xb950, 0xb945, 0xe0a1, 0xb94a, 0xe0a2, 0xb943, 0xb942, 0xb94d, 0xb94c, 0xb94b, 0xb949, 0xb94e, 0xe07d, 0xb944, 0xb946, 0xb948, 0xbbb8, 0xbbbb, 0xbbbf, 0xbbb9, 0xbbbe, 0xbbbc, 0xbbb7, 0xbbbd, 0xbbba, 0xe852, 0xbe43, 0xbe41, 0xe853, 0xbe44, 0xbe42, 0xe851, 0xe850, 0xbff0, 0xe84f, 0xbfee, 0xbfed, 0xebd0, 0xbe45, 0xbfef, 0xebd1, 0xbff2, 0xebd2, 0xbff1, 0xc1d8, 0xeec3, 0xc1d7, 0xc1dc, 0xc1da, 0xc1db, 0xc2e3, 0xc1d9, 0xeec2, 0xebd3, 0xc2e2, 0xc2e4, 0xc3e4, 0xc3e5, 0xf4e0, 0xc5de, 0xc5dd, 0xa8b6, 0xca55, 0xb06f, 0xca52, 0xca53, 0xca51, 0xca54, 0xcbaa, 0xcba7, 0xcbac, 0xcba8, 0xa8b7, 0xa8ba, 0xcba9, 0xa8b9, 0xcbab, 0xa8b8, 0xcdd5, 0xcdd7, 0xaaf4, 0xcdd3, 0xcdd6, 0xcdd4, 0xaaf2, 0xaaf5, 0xaaf3, 0xd0b8, 0xd0bc, 0xd0b9, 0xada7, 0xada8, 0xd0bb, 0xd0bd, 0xd0bf, 0xada5, 0xd0be, 0xada6, 0xd7ee, 0xd0ba, 0xd3f2, 0xd3fb, 0xd3f9, 0xd3f4, 0xd3f5, 0xd3fa, 0xd3fc, 0xb071, 0xd3f7, 0xd3f3, 0xb070, 0xb072, 0xd3f6, 0xd3fd, 0xd3f8, 0xb3a1, 0xd7f1, 0xd7e9, 0xd7ef, 0xd7f0, 0xb3a2, 0xd7e8, 0xd7ea, 0xd0b7, 0xd7ec, 0xd7ed, 0xd7eb, 0xb66c, 0xdc56, 0xebd4, 0xdc57, 0xdc54, 0xb3a3, 0xb66e, 0xdc53, 0xdc59, 0xdc58, 0xb66b, 0xdc5c, 0xdc52, 0xdc5b, 0xdc50, 0xdc5a, 0xdc55, 0xb66d, 0xe0aa, 0xe0a5, 0xe0ab, 0xe0a6, 0xe0a4, 0xe0a7, 0xb951, 0xe0a9, 0xe0a8, 0xb952, 0xbbc1, 0xbbc0, 0xe46e, 0xe471, 0xe469, 0xe46d, 0xbbc2, 0xe46c, 0xe46a, 0xe470, 0xe46b, 0xe468, 0xe46f, 0xe859, 0xbe48, 0xf14a, 0xe856, 0xe857, 0xe855, 0xdc51, 0xbe47, 0xe85a, 0xe854, 0xbe46, 0xbe49, 0xe858, 0xebd5, 0xbff3, 0xebd6, 0xebd7, 0xeec4, 0xc1dd, 0xf14b, 0xf14c, 0xf14d, 0xf35d, 0xf35c, 0xf4e2, 0xf4e1, 0xf65b, 0xf65c, 0xf65a, 0xf766, 0xc5b0, 0xa8bb, 0xadaa, 0xada9, 0xb075, 0xb074, 0xd440, 0xd441, 0xd3fe, 0xb073, 0xd7f5, 0xd7f6, 0xd7f2, 0xb3a4, 0xd7f3, 0xd7f4, 0xdc5f, 0xdc61, 0xdc5d, 0xdc60, 0xb66f, 0xdc5e, 0xb670, 0xdd73, 0xb955, 0xb954, 0xb953, 0xe0ac, 0xe0ad, 0xe473, 0xe475, 0xbbc6, 0xbbc3, 0xbbc5, 0xbbc4, 0xe474, 0xe472, 0xe861, 0xe85e, 0xe85f, 0xbe4d, 0xe860, 0xe85b, 0xe85c, 0xbe4a, 0xbe4b, 0xe85d, 0xbe4c, 0xebdb, 0xebdc, 0xebd9, 0xebda, 0xbff4, 0xebd8, 0xeec8, 0xeec5, 0xeec7, 0xc1e0, 0xeecb, 0xc1df, 0xeec9, 0xeecc, 0xeeca, 0xeec6, 0xc1de, 0xf14f, 0xf150, 0xf14e, 0xf152, 0xc2e5, 0xc2e6, 0xf35f, 0xc3e7, 0xf151, 0xf35e, 0xc3e6, 0xf4e5, 0xf4e6, 0xc4bf, 0xf4e4, 0xf4e3, 0xf65d, 0xc548, 0xf849, 0xf8c8, 0xf8c7, 0xc643, 0xc65d, 0xf8c9, 0xf971, 0xc66f, 0xa8bc, 0xaaf6, 0xb956, 0xc4c0, 0xa8bd, 0xadab, 0xb3a5, 0xb671, 0xc2e7, 0xaaf7, 0xd0c1, 0xd0c0, 0xd442, 0xb078, 0xb076, 0xb07a, 0xd444, 0xb079, 0xb077, 0xd443, 0xb3a8, 0xd7fc, 0xb3a7, 0xb3a9, 0xd842, 0xb3ab, 0xd7fe, 0xd840, 0xd7f7, 0xb3aa, 0xd843, 0xd7f9, 0xd7fa, 0xd7f8, 0xb3a6, 0xd841, 0xd7fb, 0xd7fd, 0xdc6d, 0xdc6c, 0xdc6a, 0xdc62, 0xdc71, 0xdc65, 0xdc6f, 0xdc76, 0xdc6e, 0xb679, 0xb675, 0xdc63, 0xdc69, 0xb677, 0xdc68, 0xb678, 0xb67a, 0xdc6b, 0xb672, 0xb673, 0xdc77, 0xdc75, 0xdc74, 0xdc66, 0xdc72, 0xb676, 0xb674, 0xdc73, 0xdc64, 0xdc67, 0xdc70, 0xe4ba, 0xe0b7, 0xe0b0, 0xe0c3, 0xe0cc, 0xe0b3, 0xb961, 0xe0c0, 0xb957, 0xb959, 0xb965, 0xe0b1, 0xb95a, 0xb95c, 0xb966, 0xb95b, 0xb964, 0xe0b9, 0xe0ae, 0xb962, 0xe0b8, 0xb95e, 0xe0ca, 0xb963, 0xe0c8, 0xe0bc, 0xe0c6, 0xb960, 0xe0af, 0xe0c9, 0xe0c4, 0xe0cb, 0xb958, 0xb967, 0xb95d, 0xe0b5, 0xe0bd, 0xe0c1, 0xe0c5, 0xb95f, 0xe0b4, 0xe0b2, 0xe0be, 0xe0bb, 0xe0ba, 0xe0bf, 0xe0c2, 0xe0c7, 0xe478, 0xbbc7, 0xe4a4, 0xe47a, 0xbbcc, 0xbbd0, 0xe4ad, 0xe4b5, 0xe4a6, 0xbbc8, 0xe4aa, 0xe0b6, 0xbbc9, 0xe4b1, 0xe4b6, 0xe4ae, 0xe4b0, 0xe4b9, 0xe4b2, 0xe47e, 0xe4a9, 0xbbd1, 0xbbcd, 0xe47c, 0xe4ab, 0xbbcb, 0xe4a5, 0xbbca, 0xe4b3, 0xe4a2, 0xe479, 0xbbce, 0xe4b8, 0xe47b, 0xe4af, 0xe4ac, 0xe4a7, 0xe477, 0xe476, 0xe4a1, 0xe4b4, 0xbbcf, 0xe4b7, 0xe47d, 0xe4a3, 0xbe52, 0xbe5a, 0xbe55, 0xe8a4, 0xe8a1, 0xe867, 0xbe50, 0xbe4f, 0xbe56, 0xe865, 0xbe54, 0xe871, 0xe863, 0xe864, 0xbe4e, 0xe8a3, 0xbe58, 0xe874, 0xe879, 0xe873, 0xebee, 0xe86f, 0xe877, 0xe875, 0xe868, 0xe862, 0xe87d, 0xbe57, 0xe87e, 0xe878, 0xe86d, 0xe86b, 0xe866, 0xe86e, 0xe87b, 0xe86a, 0xe87a, 0xe8a2, 0xbe53, 0xe876, 0xe87c, 0xe872, 0xe86c, 0xbe51, 0xe4a8, 0xe870, 0xbe59, 0xe869, 0xebf4, 0xbff7, 0xebf3, 0xebf0, 0xec44, 0xbffb, 0xec41, 0xebf8, 0xec43, 0xebe9, 0xebf6, 0xbffd, 0xebe1, 0xebdf, 0xec42, 0xec40, 0xebfe, 0xebed, 0xebec, 0xebe2, 0xc040, 0xebe8, 0xebf2, 0xebfd, 0xc043, 0xec45, 0xc1e8, 0xc045, 0xbffe, 0xebe6, 0xebef, 0xebde, 0xebe0, 0xbff5, 0xc042, 0xbffa, 0xebe7, 0xebf7, 0xebf1, 0xc041, 0xebdd, 0xc1e3, 0xebf9, 0xebfc, 0xbffc, 0xebeb, 0xc044, 0xbff9, 0xbff8, 0xebf5, 0xebfb, 0xbff6, 0xebe4, 0xebfa, 0xebe5, 0xebea, 0xeed2, 0xeed7, 0xc1e5, 0xc1e7, 0xeedd, 0xc1e1, 0xeeec, 0xeee3, 0xeed8, 0xeed9, 0xeee2, 0xc1ee, 0xeee1, 0xeed1, 0xeee0, 0xeed4, 0xeeed, 0xc1ed, 0xc1eb, 0xeed5, 0xeee8, 0xeeda, 0xeee7, 0xeee9, 0xeed0, 0xc1e6, 0xeeea, 0xeede, 0xc1ea, 0xeedb, 0xc1ec, 0xeee4, 0xc1e4, 0xeed6, 0xeee5, 0xeedf, 0xebe3, 0xeee6, 0xeed3, 0xc1e9, 0xeeeb, 0xc1e2, 0xeece, 0xf160, 0xf159, 0xc2e9, 0xf154, 0xf163, 0xf15b, 0xeedc, 0xf165, 0xf155, 0xc2e8, 0xf15f, 0xc2ea, 0xc2f2, 0xc2f0, 0xf161, 0xc2f1, 0xf157, 0xf158, 0xf15d, 0xf162, 0xeecd, 0xc2eb, 0xf16a, 0xf167, 0xf16b, 0xf15e, 0xf15a, 0xf168, 0xf36a, 0xf15c, 0xc2ee, 0xc2ed, 0xeecf, 0xc2ef, 0xf164, 0xf166, 0xc2ec, 0xf169, 0xf153, 0xf156, 0xf373, 0xf363, 0xc3eb, 0xf371, 0xf361, 0xc3ec, 0xf36c, 0xf368, 0xc3f1, 0xf372, 0xf362, 0xf365, 0xc3e9, 0xf374, 0xf36d, 0xf370, 0xc3ef, 0xc3f4, 0xc3f2, 0xf369, 0xf364, 0xc3ed, 0xc3ee, 0xf360, 0xc3ea, 0xc3e8, 0xc3f0, 0xf36f, 0xc3f3, 0xf36b, 0xf375, 0xc3f5, 0xf367, 0xf36e, 0xf4f3, 0xf542, 0xf4f5, 0xf4fc, 0xf366, 0xf4fa, 0xf4e9, 0xf540, 0xc4c3, 0xf4ed, 0xf4fe, 0xf4f4, 0xc4c2, 0xf544, 0xf4f6, 0xf4fb, 0xf4fd, 0xf4e7, 0xf541, 0xf4f2, 0xf4f7, 0xf4eb, 0xf4ef, 0xf543, 0xf4f9, 0xf4e8, 0xf4ec, 0xf4ee, 0xf4f8, 0xc4c1, 0xf4f1, 0xf4ea, 0xf4f0, 0xf661, 0xf666, 0xc54f, 0xf668, 0xc549, 0xf664, 0xf66a, 0xc54e, 0xc54a, 0xc54b, 0xf660, 0xf667, 0xc54d, 0xf665, 0xc54c, 0xf65f, 0xf663, 0xf662, 0xf65e, 0xf669, 0xc5b1, 0xf76d, 0xf770, 0xf76c, 0xf76e, 0xf76f, 0xf769, 0xf76a, 0xf767, 0xf76b, 0xf768, 0xc5b2, 0xc5b3, 0xf84b, 0xf84d, 0xf84c, 0xf84e, 0xc5e0, 0xf84a, 0xc5df, 0xc5e1, 0xf8cb, 0xf8cc, 0xc644, 0xf8ca, 0xf953, 0xf952, 0xf954, 0xc65f, 0xf955, 0xc65e, 0xf956, 0xf972, 0xf975, 0xf974, 0xc668, 0xf973, 0xc672, 0xc670, 0xc671, 0xc677, 0xf9c0, 0xf9c1, 0xf9bf, 0xf9c9, 0xaaf8, 0xd844, 0xdc78, 0xe8a5, 0xf376, 0xaaf9, 0xadac, 0xb07b, 0xd845, 0xd846, 0xb3ac, 0xb67d, 0xdc7a, 0xdc79, 0xb6a3, 0xb67c, 0xdc7b, 0xb67e, 0xb6a2, 0xb6a1, 0xb67b, 0xb968, 0xe0d0, 0xe0ce, 0xe0cf, 0xe0cd, 0xbbd2, 0xbbd5, 0xbbd7, 0xbbd6, 0xbbd3, 0xbbd4, 0xe8a7, 0xe8a6, 0xbe5b, 0xe8a8, 0xe8a9, 0xbe5c, 0xec4d, 0xec4b, 0xeef3, 0xec49, 0xec4a, 0xc046, 0xec46, 0xec4e, 0xec48, 0xec4c, 0xeeef, 0xeef1, 0xeef2, 0xc1f3, 0xeeee, 0xc1f2, 0xeef0, 0xc1ef, 0xc1f0, 0xc1f1, 0xec47, 0xc2f5, 0xf16e, 0xf16c, 0xf16d, 0xc2f3, 0xc2f6, 0xc2f4, 0xf377, 0xf378, 0xc3f6, 0xf545, 0xf547, 0xf546, 0xc4c4, 0xc550, 0xf66d, 0xf66c, 0xf66b, 0xaafa, 0xc9aa, 0xca58, 0xa6e9, 0xca56, 0xca59, 0xca57, 0xcbae, 0xa8c1, 0xa8c2, 0xcbb0, 0xa8bf, 0xcbaf, 0xcbad, 0xa8c0, 0xa8be, 0xcdd8, 0xcddb, 0xaafd, 0xcdda, 0xcdd9, 0xaafc, 0xaafb, 0xab40, 0xcddc, 0xaafe, 0xd0c6, 0xadae, 0xadaf, 0xadb0, 0xd0c7, 0xd0c3, 0xadad, 0xd0c4, 0xd0c5, 0xd0c2, 0xb0a4, 0xb0a1, 0xd445, 0xb0a2, 0xb0a5, 0xd446, 0xb07e, 0xb07c, 0xb07d, 0xb0a3, 0xb3ad, 0xd849, 0xb3b5, 0xd848, 0xd84b, 0xb3b1, 0xd84a, 0xb6ab, 0xb3af, 0xb3b2, 0xb3ae, 0xb3b3, 0xb3b4, 0xb3b0, 0xd847, 0xb6a7, 0xdc7d, 0xdca3, 0xdca2, 0xb6ac, 0xb6a8, 0xb6a9, 0xdc7c, 0xdc7e, 0xdca1, 0xb6a4, 0xb6a6, 0xb6aa, 0xb6a5, 0xe0d3, 0xe0d1, 0xe0d2, 0xb96a, 0xb96b, 0xe0d4, 0xb969, 0xbbd8, 0xbbda, 0xbbd9, 0xe4bb, 0xe4bc, 0xe8ab, 0xe8aa, 0xc047, 0xc048, 0xec4f, 0xc049, 0xeef6, 0xeef4, 0xeef5, 0xc1f4, 0xf16f, 0xc3f7, 0xc1f5, 0xab41, 0xb0a6, 0xd447, 0xd84c, 0xb3b6, 0xb6ad, 0xdca4, 0xdca6, 0xb6af, 0xb6ae, 0xb6b0, 0xb6b1, 0xdca5, 0xb96e, 0xb96f, 0xb96d, 0xbbdb, 0xb96c, 0xe0d5, 0xbbdc, 0xe8ac, 0xec50, 0xc04a, 0xc1f6, 0xf170, 0xf174, 0xc2f9, 0xf171, 0xc2fa, 0xc2f8, 0xf175, 0xc2fb, 0xf173, 0xf379, 0xc2f7, 0xc3f8, 0xf8cd, 0xab42, 0xb3b8, 0xb3b7, 0xb6b2, 0xdca8, 0xdca7, 0xb6b3, 0xe0d9, 0xb973, 0xb970, 0xe0d8, 0xb972, 0xe0d6, 0xb971, 0xe0d7, 0xe4bd, 0xbbdd, 0xe8af, 0xbe5d, 0xe8ad, 0xbe5e, 0xbe5f, 0xe8ae, 0xbe60, 0xec51, 0xc04e, 0xc04b, 0xc050, 0xec53, 0xc04c, 0xec52, 0xc04f, 0xc04d, 0xeef9, 0xeefb, 0xc1f7, 0xeefa, 0xc1f8, 0xeef8, 0xeef7, 0xf177, 0xf176, 0xc2fc, 0xf178, 0xf37e, 0xc3fa, 0xf37d, 0xf37a, 0xc3f9, 0xf37b, 0xf37c, 0xf548, 0xf549, 0xc4c5, 0xc553, 0xf66e, 0xc551, 0xc552, 0xf66f, 0xc5b4, 0xc5b5, 0xf771, 0xc645, 0xf8cf, 0xc647, 0xf8ce, 0xf8d0, 0xc646, 0xf957, 0xf9ad, 0xab43, 0xb974, 0xe4be, 0xe8b0, 0xc051, 0xc052, 0xab44, 0xbe61, 0xc3fb, 0xadb1, 0xc053, 0xc5e2, 0xadb2, 0xd84d, 0xdca9, 0xdcab, 0xdcaa, 0xe0dd, 0xe0da, 0xb975, 0xb976, 0xe0db, 0xe0dc, 0xe4c0, 0xe4c5, 0xbbde, 0xe4bf, 0xe4c1, 0xe4c8, 0xe4c3, 0xe4c7, 0xe4c4, 0xe4c2, 0xe4c6, 0xbbdf, 0xe8b3, 0xe8b1, 0xbe63, 0xbe62, 0xe8b2, 0xbe64, 0xec56, 0xec55, 0xc054, 0xec54, 0xeefc, 0xeefe, 0xef41, 0xef40, 0xc1f9, 0xeefd, 0xf1a1, 0xc2fd, 0xf17d, 0xf1a2, 0xc2fe, 0xf17b, 0xf17e, 0xf17c, 0xf179, 0xc340, 0xf17a, 0xf3a1, 0xf3a3, 0xf3a2, 0xf54a, 0xf54b, 0xf670, 0xc5b7, 0xc5b6, 0xf84f, 0xf850, 0xc648, 0xf8d1, 0xc669, 0xadb3, 0xb6b4, 0xe4ca, 0xe4c9, 0xe8b5, 0xe8b4, 0xc1fa, 0xef43, 0xef42, 0xf1a5, 0xf1a3, 0xf1a6, 0xf1a4, 0xc3fc, 0xf3a4, 0xf3a5, 0xf3a6, 0xf671, 0xf772, 0xf8d2, 0xadb4, 0xec57, 0xef44, 0xadb5, 0xbbe0, 0xec58, 0xc341, 0xf1a7, 0xc3fd, 0xf54c, 0xf54d, 0xc554, 0xf851, 0xadb6, 0xb3bb, 0xb3bc, 0xd84e, 0xb6b5, 0xb6b6, 0xdcac, 0xb6b7, 0xb97a, 0xb97c, 0xe0df, 0xe0e0, 0xe0de, 0xb977, 0xb978, 0xb97b, 0xb979, 0xe4cb, 0xbbe1, 0xbbe2, 0xe8bc, 0xbe67, 0xe8b7, 0xe8b6, 0xe8bb, 0xbe65, 0xc05b, 0xe8b8, 0xe8bd, 0xe8ba, 0xe8b9, 0xbe66, 0xc059, 0xec5a, 0xc055, 0xec5b, 0xec59, 0xc058, 0xc056, 0xc05a, 0xc057, 0xef45, 0xef4a, 0xef46, 0xef49, 0xc1fb, 0xedd4, 0xef48, 0xef47, 0xc344, 0xc342, 0xc345, 0xc343, 0xf1a8, 0xf1a9, 0xf1aa, 0xc346, 0xf3aa, 0xc440, 0xf3a8, 0xc441, 0xf3a7, 0xf3a9, 0xc3fe, 0xf551, 0xf54e, 0xf54f, 0xf550, 0xf672, 0xc556, 0xc555, 0xf774, 0xf773, 0xc5b8, 0xc5e3, 0xc649, 0xc660, 0xf958, 0xf9ae, 0xf9af, 0xadb7, 0xdcad, 0xe0e1, 0xe4cc, 0xe4cd, 0xbbe3, 0xbbe4, 0xe8be, 0xbe68, 0xc1fc, 0xf1ab, 0xc347, 0xf3ad, 0xc442, 0xf3ac, 0xf3ae, 0xf3ab, 0xf675, 0xf552, 0xf553, 0xc4c6, 0xf674, 0xf673, 0xf775, 0xf9b0, 0xadb8, 0xadb9, 0xb0a7, 0xd448, 0xd84f, 0xb6b8, 0xb6bb, 0xb6b9, 0xdcae, 0xb6bd, 0xb6ba, 0xb6bc, 0xb97e, 0xe0e2, 0xe0e3, 0xe8c0, 0xb97d, 0xb9a1, 0xb9a2, 0xe4cf, 0xe4ce, 0xbbe5, 0xbbe6, 0xe4d0, 0xe8bf, 0xbbe8, 0xbe69, 0xbbe7, 0xc05c, 0xe8c1, 0xbe6b, 0xbe6a, 0xe8c2, 0xe8c5, 0xe8c3, 0xe8c4, 0xbe6c, 0xc061, 0xc05f, 0xc05e, 0xec5d, 0xc060, 0xec5c, 0xef4b, 0xec5e, 0xc05d, 0xec5f, 0xef4e, 0xef4c, 0xef4d, 0xef52, 0xc34b, 0xef51, 0xef54, 0xef53, 0xef50, 0xef4f, 0xc1fd, 0xf1ae, 0xf1ad, 0xc34a, 0xc348, 0xc349, 0xf1ac, 0xf3b1, 0xc443, 0xf3b0, 0xf3af, 0xc444, 0xf558, 0xf557, 0xf555, 0xf554, 0xc4c8, 0xc4c7, 0xf559, 0xf776, 0xc5b9, 0xf677, 0xc557, 0xf676, 0xf556, 0xf777, 0xc5e4, 0xc661, 0xf959, 0xf9b1, 0xadba, 0xd850, 0xef55, 0xadbb, 0xe4d2, 0xe4d1, 0xec60, 0xef57, 0xef56, 0xc34c, 0xf3b2, 0xf3b3, 0xc4c9, 0xf9b2, 0xb0a8, 0xb6bf, 0xb6be, 0xe0e4, 0xe0e6, 0xb9a4, 0xe0e5, 0xb9a3, 0xb9a5, 0xe0e7, 0xe4d4, 0xe4d6, 0xe4d5, 0xe4d8, 0xbbe9, 0xe4d7, 0xe4d3, 0xe4d9, 0xe8cc, 0xe8cf, 0xe8d1, 0xe8c7, 0xe8cb, 0xe8c8, 0xbe6e, 0xbe71, 0xbe73, 0xe8c9, 0xe8ca, 0xbe72, 0xe8cd, 0xe8d0, 0xe8ce, 0xbe74, 0xbe70, 0xe8c6, 0xbe6d, 0xbe6f, 0xc063, 0xec66, 0xec64, 0xec63, 0xec69, 0xec68, 0xec67, 0xec62, 0xc062, 0xec61, 0xec65, 0xc064, 0xef5a, 0xef5e, 0xef5b, 0xef5d, 0xef5c, 0xef59, 0xef5f, 0xef62, 0xef60, 0xef61, 0xc240, 0xc1fe, 0xef58, 0xef63, 0xf1b3, 0xf1b6, 0xf1b8, 0xf1b7, 0xf1b1, 0xf1b5, 0xf1b0, 0xf1b2, 0xc34d, 0xf1af, 0xf1b4, 0xf3c0, 0xf3b5, 0xc445, 0xc446, 0xf3b4, 0xf3b9, 0xf3bf, 0xf3b7, 0xf3be, 0xf3bb, 0xf3ba, 0xf3bd, 0xf3b8, 0xf3b6, 0xf3bc, 0xf560, 0xf55e, 0xc4ca, 0xf55d, 0xf563, 0xf561, 0xc4cb, 0xf55c, 0xf55a, 0xf55b, 0xc4cd, 0xf55f, 0xc4cc, 0xf562, 0xf678, 0xf67e, 0xf679, 0xc55b, 0xf6a1, 0xc55a, 0xf67d, 0xf67c, 0xc559, 0xf67b, 0xc558, 0xf67a, 0xf77d, 0xf7a1, 0xf77e, 0xf77b, 0xc5bb, 0xf778, 0xf77c, 0xf7a3, 0xf7a2, 0xf779, 0xf77a, 0xc5ba, 0xf852, 0xc5e7, 0xf853, 0xc5e5, 0xc5e6, 0xf8d3, 0xc64a, 0xf976, 0xc66a, 0xf9b3, 0xc66b, 0xf9b4, 0xf9b5, 0xf9c3, 0xf9c2, 0xc67a, 0xf9cd, 0xb0a9, 0xe0e9, 0xe0e8, 0xbbea, 0xbbeb, 0xe4da, 0xe8d2, 0xec6c, 0xbe75, 0xc065, 0xec6a, 0xec6d, 0xc066, 0xef64, 0xec6b, 0xf1b9, 0xc34e, 0xf3c1, 0xf566, 0xf564, 0xf565, 0xf6a2, 0xc55c, 0xf7a4, 0xc5ea, 0xc5bc, 0xc5e8, 0xc5e9, 0xf8d4, 0xc662, 0xb0aa, 0xf1ba, 0xd449, 0xb9a6, 0xe4db, 0xbbec, 0xe4dc, 0xe8d4, 0xe8d3, 0xc068, 0xbe76, 0xbe77, 0xe8d7, 0xe8d6, 0xe8d5, 0xec6e, 0xec71, 0xec70, 0xec6f, 0xc067, 0xef68, 0xef66, 0xef65, 0xef67, 0xc34f, 0xf1bc, 0xf1bd, 0xc350, 0xf1bb, 0xf3c3, 0xf3c2, 0xf3c5, 0xc447, 0xf3c4, 0xf567, 0xf569, 0xf568, 0xf6a3, 0xf6a6, 0xf6a4, 0xf6a5, 0xf7a5, 0xc5bd, 0xf854, 0xf855, 0xf856, 0xc64b, 0xc663, 0xf9b6, 0xb0ab, 0xbe78, 0xc069, 0xf1be, 0xf7a6, 0xf9c4, 0xd44a, 0xc67b, 0xb0ac, 0xec72, 0xf1bf, 0xf3c6, 0xf6a7, 0xf7a7, 0xb0ad, 0xe4dd, 0xe4de, 0xbbed, 0xbbee, 0xe8d9, 0xbe7a, 0xbe79, 0xe8d8, 0xef69, 0xf1c0, 0xf1c2, 0xf1c1, 0xc353, 0xc352, 0xc351, 0xc55e, 0xf6a8, 0xc55d, 0xf7a9, 0xf7a8, 0xc64c, 0xf8d5, 0xb3bd, 0xe0ea, 0xe4e1, 0xe4df, 0xe4e0, 0xe8e2, 0xe8dd, 0xe8da, 0xe8e1, 0xe8e3, 0xbe7c, 0xe8e0, 0xe8dc, 0xe8db, 0xe8df, 0xe8de, 0xbe7b, 0xec7d, 0xec78, 0xec76, 0xeca1, 0xec77, 0xec73, 0xec79, 0xec74, 0xef72, 0xec75, 0xeca2, 0xec7c, 0xc06a, 0xec7b, 0xec7a, 0xec7e, 0xef6a, 0xef6d, 0xef6c, 0xef74, 0xef6f, 0xef73, 0xef71, 0xef70, 0xef6e, 0xef6b, 0xc243, 0xc242, 0xc244, 0xc241, 0xef75, 0xf1c8, 0xf1cb, 0xf1c9, 0xf1cd, 0xf1ce, 0xf1c6, 0xc358, 0xf1c7, 0xf1c5, 0xf1cc, 0xf1c4, 0xf1c3, 0xc357, 0xc355, 0xc354, 0xf1ca, 0xf3cf, 0xf3d5, 0xc44a, 0xf3d0, 0xf3d3, 0xf3d7, 0xc44b, 0xf3d2, 0xf3ca, 0xf3c9, 0xf3d6, 0xf3cd, 0xf3cb, 0xf3d4, 0xf3cc, 0xc449, 0xc448, 0xf3c7, 0xf3c8, 0xf3d1, 0xf3ce, 0xf56c, 0xf56f, 0xc356, 0xf56d, 0xf573, 0xf571, 0xf56b, 0xf576, 0xf56a, 0xc4cf, 0xf572, 0xf56e, 0xc4ce, 0xf575, 0xf574, 0xf6ab, 0xf6aa, 0xf6b1, 0xf6ad, 0xf6b0, 0xc560, 0xf6ae, 0xf6af, 0xf6a9, 0xf6ac, 0xc55f, 0xc5bf, 0xf7b4, 0xf7af, 0xf7b3, 0xf7b6, 0xf7b2, 0xf7ae, 0xc5c1, 0xf7b1, 0xf7b5, 0xc5c0, 0xf7ac, 0xf570, 0xf7b0, 0xf7ad, 0xf7aa, 0xf7ab, 0xc5be, 0xf85a, 0xf85c, 0xf85f, 0xf85b, 0xf860, 0xf859, 0xf857, 0xc5eb, 0xf85d, 0xc5ed, 0xc5ec, 0xf858, 0xf85e, 0xf8da, 0xc64d, 0xf8db, 0xf8d9, 0xf8d6, 0xf8d8, 0xf8d7, 0xf95a, 0xf95c, 0xf95b, 0xf979, 0xf978, 0xf977, 0xf97a, 0xc673, 0xc674, 0xf9ca, 0xf9ce, 0xb3be, 0xdcaf, 0xe0ed, 0xb9a7, 0xe0eb, 0xe0ec, 0xe4e2, 0xe4e3, 0xbbf1, 0xbbef, 0xe4e4, 0xbbf0, 0xe8e8, 0xe8eb, 0xe8e5, 0xe8ec, 0xe8e4, 0xe8e6, 0xe8e7, 0xe8ea, 0xbea1, 0xe8ef, 0xe8ee, 0xbe7d, 0xe8e9, 0xe8ed, 0xbe7e, 0xecac, 0xc06f, 0xeca7, 0xc06b, 0xeca4, 0xecaa, 0xecad, 0xc070, 0xeca9, 0xeca6, 0xecae, 0xeca5, 0xecab, 0xc06c, 0xeca3, 0xc06d, 0xc06e, 0xeca8, 0xefa9, 0xef7a, 0xef7b, 0xef7e, 0xef7c, 0xef76, 0xef79, 0xefa5, 0xef7d, 0xc245, 0xefa7, 0xefa4, 0xc246, 0xefa6, 0xef77, 0xefa2, 0xefa3, 0xefa1, 0xf1d2, 0xf1d4, 0xf1d7, 0xf1d1, 0xc359, 0xf1d9, 0xf1d0, 0xf1da, 0xf1d6, 0xf1d8, 0xf1dc, 0xf1d5, 0xf1dd, 0xf1d3, 0xf1cf, 0xc35a, 0xf1db, 0xc35b, 0xc44d, 0xef78, 0xf3f1, 0xf3e8, 0xc44f, 0xf3e4, 0xc450, 0xf3ed, 0xf3e7, 0xf3dd, 0xc44e, 0xf3ea, 0xf3e5, 0xf3e6, 0xf3d8, 0xf3df, 0xf3ee, 0xf3eb, 0xf3e3, 0xf3ef, 0xf3de, 0xf3d9, 0xf3ec, 0xf3db, 0xf3e9, 0xf3e0, 0xf3f0, 0xf3dc, 0xc44c, 0xf3da, 0xf3e1, 0xf3e2, 0xf57d, 0xf57b, 0xf5a2, 0xf5ae, 0xf5a5, 0xf57c, 0xf578, 0xf5a7, 0xf57e, 0xf5a3, 0xf57a, 0xf5aa, 0xf577, 0xf5a1, 0xf5a6, 0xf5a8, 0xf5ab, 0xf579, 0xf5af, 0xf5b0, 0xf5a9, 0xf5ad, 0xf5a4, 0xf6c1, 0xf6c4, 0xc561, 0xf6c3, 0xf6c8, 0xf6c6, 0xc562, 0xf6bd, 0xf6b3, 0xf6b2, 0xc564, 0xf6bf, 0xf6c0, 0xf6bc, 0xf6b4, 0xf6b9, 0xf5ac, 0xf6b5, 0xc563, 0xf6bb, 0xf6ba, 0xf6b6, 0xf6c2, 0xf6b7, 0xf7bb, 0xf6c5, 0xf6c7, 0xf6be, 0xf6b8, 0xf7bc, 0xf7be, 0xf7b8, 0xc5c2, 0xf7c5, 0xf7c3, 0xc5c3, 0xf7c2, 0xf7c1, 0xf7ba, 0xf7b7, 0xf7bd, 0xf7c6, 0xf7b9, 0xf7bf, 0xf869, 0xf86e, 0xf864, 0xf867, 0xc5ee, 0xf86b, 0xf872, 0xf7c0, 0xf865, 0xf86f, 0xf873, 0xf86a, 0xf863, 0xf86d, 0xf86c, 0xf871, 0xf870, 0xf7c4, 0xf868, 0xf862, 0xf866, 0xc64e, 0xc64f, 0xf861, 0xf8e6, 0xf8dd, 0xf8e5, 0xf8e2, 0xf8e3, 0xf8dc, 0xf8df, 0xf8e7, 0xf8e1, 0xf8e0, 0xf8de, 0xf8e4, 0xf95d, 0xf95e, 0xf960, 0xf95f, 0xf962, 0xf961, 0xf97c, 0xf97b, 0xf9b7, 0xf9b8, 0xf9c5, 0xc678, 0xc67c, 0xf9cf, 0xc67d, 0xb3bf, 0xc4d0, 0xf6c9, 0xc650, 0xc651, 0xb3c0, 0xe0ee, 0xb9a8, 0xe8f0, 0xecb0, 0xecb1, 0xecaf, 0xefab, 0xefaa, 0xc247, 0xf1df, 0xefac, 0xf1de, 0xf3f3, 0xc451, 0xc453, 0xf3f2, 0xc452, 0xf5b1, 0xf5b3, 0xf5b2, 0xf6ca, 0xc565, 0xc5ef, 0xf8e8, 0xf963, 0xf9d2, 0xb3c1, 0xe4e5, 0xbea2, 0xecb3, 0xecb2, 0xefad, 0xc454, 0xc4d1, 0xf7c7, 0xf9cb, 0xb3c2, 0xbbf2, 0xbea3, 0xf3f4, 0xf874, 0xb6c0, 0xefae, 0xc664, 0xb6c1, 0xbea4, 0xc248, 0xf875, 0xb6c2, 0xe8f1, 0xc072, 0xecb4, 0xecb5, 0xc071, 0xefaf, 0xc24c, 0xc24a, 0xc24b, 0xc249, 0xf1e0, 0xc35c, 0xf5b5, 0xf5b4, 0xf5b7, 0xf5b6, 0xc4d2, 0xf6cb, 0xf6cd, 0xf6cc, 0xc566, 0xf7c8, 0xf876, 0xf877, 0xc5f0, 0xf964, 0xf97d, 0xc675, 0xdcb0, 0xecb6, 0xefb0, 0xf3f5, 0xe0ef, 0xefb1, 0xf1e2, 0xf1e1, 0xf878, 0xc652, 0xf965, 0xf97e, 0xb9a9, 0xe8f2, 0xe8f3, 0xecb7, 0xb9aa, 0xc35d, 0xf1e3, 0xf6cf, 0xc567, 0xf6d0, 0xf6ce, 0xf879, 0xf8e9, 0xb9ab, 0xefb4, 0xefb3, 0xefb2, 0xf1e4, 0xf1e8, 0xf1e7, 0xf1e6, 0xf1e5, 0xc35e, 0xf3f6, 0xf5b9, 0xc4d3, 0xf5b8, 0xf6d1, 0xf7cb, 0xf7ca, 0xc5c4, 0xf7c9, 0xf87c, 0xf87b, 0xf87a, 0xbbf3, 0xecb8, 0xc24d, 0xf3f7, 0xf3f8, 0xf7cc, 0xf87d, 0xf8ea, 0xf966, 0xf9b9, 0xf9d4, 0xbbf4, 0xc24e, 0xf1e9, 0xf3f9, 0xf6d2, 0xf87e, 0xbea6, 0xefb5, 0xf1ea, 0xf3fa, 0xf3fb, 0xf3fc, 0xf5be, 0xf5ba, 0xc568, 0xf5bd, 0xf5bc, 0xc4d4, 0xf5bb, 0xc4d6, 0xc4d5, 0xf6d4, 0xf6d3, 0xc569, 0xc56a, 0xc5c6, 0xf7cd, 0xc5c5, 0xf8a3, 0xf8a4, 0xf8a2, 0xf8a1, 0xc654, 0xf8eb, 0xf8ec, 0xf8ed, 0xc653, 0xf967, 0xf96a, 0xf969, 0xf968, 0xf9d3, 0xc073, 0xc365, 0xf5bf, 0xf6d5, 0xc5c7, 0xf7ce, 0xf9d5, 0xc074, 0xefb6, 0xf7cf, 0xf9a1, 0xc94a, 0xddfc, 0xa14a, 0xa157, 0xa159, 0xa15b, 0xa15f, 0xa160, 0xa163, 0xa164, 0xa167, 0xa168, 0xa16b, 0xa16c, 0xa16f, 0xa170, 0xa173, 0xa174, 0xa177, 0xa178, 0xa17b, 0xa17c, 0xa1c6, 0xa1c7, 0xa1ca, 0xa1cb, 0xa1c8, 0xa1c9, 0xa15c, 0xa14d, 0xa14f, 0xa151, 0xa152, 0xa153, 0xa154, 0xa17d, 0xa17e, 0xa1a1, 0xa1a2, 0xa1a3, 0xa1a4, 0xa1cc, 0xa1cd, 0xa1ce, 0xa1de, 0xa1df, 0xa1e0, 0xa1e1, 0xa1e2, 0xa24c, 0xa24d, 0xa24e, 0xa149, 0xa1ad, 0xa243, 0xa248, 0xa1ae, 0xa15d, 0xa15e, 0xa1af, 0xa1cf, 0xa141, 0xa1d0, 0xa144, 0xa241, 0xa2af, 0xa2b0, 0xa2b1, 0xa2b2, 0xa2b3, 0xa2b4, 0xa2b5, 0xa2b6, 0xa2b7, 0xa2b8, 0xa147, 0xa146, 0xa1d5, 0xa1d7, 0xa1d6, 0xa148, 0xa249, 0xa2cf, 0xa2d0, 0xa2d1, 0xa2d2, 0xa2d3, 0xa2d4, 0xa2d5, 0xa2d6, 0xa2d7, 0xa2d8, 0xa2d9, 0xa2da, 0xa2db, 0xa2dc, 0xa2dd, 0xa2de, 0xa2df, 0xa2e0, 0xa2e1, 0xa2e2, 0xa2e3, 0xa2e4, 0xa2e5, 0xa2e6, 0xa2e7, 0xa2e8, 0xa242, 0xa1c4, 0xa2e9, 0xa2ea, 0xa2eb, 0xa2ec, 0xa2ed, 0xa2ee, 0xa2ef, 0xa2f0, 0xa2f1, 0xa2f2, 0xa2f3, 0xa2f4, 0xa2f5, 0xa2f6, 0xa2f7, 0xa2f8, 0xa2f9, 0xa2fa, 0xa2fb, 0xa2fc, 0xa2fd, 0xa2fe, 0xa340, 0xa341, 0xa342, 0xa343, 0xa161, 0xa155, 0xa162, 0xa14e, }; static const Summary16 big5_uni2indx_page00[16] = { /* 0x0000 */ { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x00ac }, { 4, 0x0083 }, { 7, 0x0000 }, { 7, 0x0080 }, { 8, 0x0000 }, { 8, 0x0080 }, }; static const Summary16 big5_uni2indx_page02[38] = { /* 0x0200 */ { 9, 0x0000 }, { 9, 0x0000 }, { 9, 0x0000 }, { 9, 0x0000 }, { 9, 0x0000 }, { 9, 0x0000 }, { 9, 0x0000 }, { 9, 0x0000 }, { 9, 0x0000 }, { 9, 0x0000 }, { 9, 0x0000 }, { 9, 0x0000 }, { 9, 0x0e80 }, { 13, 0x0200 }, { 14, 0x0000 }, { 14, 0x0000 }, /* 0x0300 */ { 14, 0x0000 }, { 14, 0x0000 }, { 14, 0x0000 }, { 14, 0x0000 }, { 14, 0x0000 }, { 14, 0x0000 }, { 14, 0x0000 }, { 14, 0x0000 }, { 14, 0x0000 }, { 14, 0xfffe }, { 29, 0x03fb }, { 38, 0xfffe }, { 53, 0x03fb }, { 62, 0x0000 }, { 62, 0x0000 }, { 62, 0x0000 }, /* 0x0400 */ { 62, 0x0002 }, { 63, 0x1ff0 }, { 72, 0xfff8 }, { 85, 0xffff }, { 101, 0xffff }, { 117, 0x0002 }, }; static const Summary16 big5_uni2indx_page20[44] = { /* 0x2000 */ { 118, 0x0000 }, { 118, 0x3318 }, { 124, 0x0064 }, { 127, 0x4824 }, { 131, 0x0000 }, { 131, 0x0000 }, { 131, 0x0000 }, { 131, 0x0000 }, { 131, 0x0000 }, { 131, 0x0000 }, { 131, 0x0000 }, { 131, 0x0000 }, { 131, 0x0000 }, { 131, 0x0000 }, { 131, 0x0000 }, { 131, 0x0000 }, /* 0x2100 */ { 131, 0x0228 }, { 134, 0x0000 }, { 134, 0x0000 }, { 134, 0x0000 }, { 134, 0x0000 }, { 134, 0x0000 }, { 134, 0x03ff }, { 144, 0x0000 }, { 144, 0x0000 }, { 144, 0x03cf }, { 152, 0x0000 }, { 152, 0x0000 }, { 152, 0x0000 }, { 152, 0x0000 }, { 152, 0x0000 }, { 152, 0x0000 }, /* 0x2200 */ { 152, 0x0000 }, { 152, 0xc400 }, { 155, 0x4e29 }, { 162, 0x1030 }, { 165, 0x0000 }, { 165, 0x0004 }, { 166, 0x00c3 }, { 170, 0x0000 }, { 170, 0x0000 }, { 170, 0x0000 }, { 170, 0x0020 }, { 171, 0x8000 }, }; static const Summary16 big5_uni2indx_page24[37] = { /* 0x2400 */ { 172, 0x0000 }, { 172, 0x0000 }, { 172, 0x0000 }, { 172, 0x0000 }, { 172, 0x0000 }, { 172, 0x0000 }, { 172, 0x03ff }, { 182, 0x3ff0 }, { 192, 0x0000 }, { 192, 0x0000 }, { 192, 0x0000 }, { 192, 0x0000 }, { 192, 0x0000 }, { 192, 0x0000 }, { 192, 0x0000 }, { 192, 0x0000 }, /* 0x2500 */ { 192, 0x1005 }, { 195, 0x1111 }, { 199, 0x1010 }, { 201, 0x1010 }, { 203, 0x0000 }, { 203, 0x4001 }, { 205, 0xe402 }, { 210, 0x000f }, { 214, 0xfffe }, { 229, 0x0030 }, { 231, 0x0003 }, { 233, 0x300c }, { 237, 0xc8c0 }, { 242, 0x0000 }, { 242, 0x003c }, { 246, 0x0000 }, /* 0x2600 */ { 246, 0x0260 }, { 249, 0x0000 }, { 249, 0x0000 }, { 249, 0x0000 }, { 249, 0x0007 }, }; static const Summary16 big5_uni2indx_page30[62] = { /* 0x3000 */ { 252, 0xff2f }, { 265, 0x6037 }, { 272, 0x03fe }, { 281, 0x0000 }, { 281, 0xfffe }, { 296, 0xffff }, { 312, 0xffff }, { 328, 0xffff }, { 344, 0xffff }, { 360, 0x600f }, { 366, 0xfffe }, { 381, 0xffff }, { 397, 0xffff }, { 413, 0xffff }, { 429, 0xffff }, { 445, 0x407f }, /* 0x3100 */ { 453, 0xffe0 }, { 464, 0xffff }, { 480, 0x03ff }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, /* 0x3200 */ { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0000 }, { 490, 0x0008 }, { 491, 0x0000 }, { 491, 0x0000 }, { 491, 0x0000 }, { 491, 0x0000 }, { 491, 0x0000 }, /* 0x3300 */ { 491, 0x0000 }, { 491, 0x0000 }, { 491, 0x0000 }, { 491, 0x0000 }, { 491, 0x0000 }, { 491, 0x0000 }, { 491, 0x0000 }, { 491, 0x0000 }, { 491, 0xc000 }, { 493, 0x7000 }, { 496, 0x0002 }, { 497, 0x0000 }, { 497, 0x4010 }, { 499, 0x0026 }, }; static const Summary16 big5_uni2indx_page4e[1307] = { /* 0x4e00 */ { 502, 0xff8b }, { 514, 0xc373 }, { 523, 0x6840 }, { 527, 0x1b0f }, { 535, 0xe9ac }, { 544, 0xf34c }, { 553, 0x0200 }, { 554, 0xc008 }, { 557, 0x795c }, { 566, 0xca3e }, { 575, 0x7976 }, { 585, 0x0648 }, { 589, 0x2fdf }, { 601, 0xf7f0 }, { 612, 0x033a }, { 618, 0xa8ff }, /* 0x4f00 */ { 629, 0xef37 }, { 641, 0x233f }, { 650, 0xb004 }, { 654, 0xfd59 }, { 665, 0xf3ca }, { 675, 0xffff }, { 691, 0xde9f }, { 703, 0xfff9 }, { 717, 0xabff }, { 730, 0x7df7 }, { 743, 0xc000 }, { 745, 0x8eec }, { 754, 0xeebf }, { 767, 0xffdb }, { 781, 0xd003 }, { 786, 0x45fa }, /* 0x5000 */ { 795, 0xfae1 }, { 805, 0xdffe }, { 819, 0xbfef }, { 833, 0x10ab }, { 839, 0xffeb }, { 853, 0xfcaa }, { 863, 0xef3f }, { 876, 0x24fd }, { 885, 0x78ad }, { 894, 0x7f76 }, { 906, 0xf00c }, { 912, 0xedff }, { 926, 0xcff6 }, { 938, 0x2cfa }, { 947, 0xf7f9 }, { 960, 0xeb6b }, /* 0x5100 */ { 971, 0x1ffd }, { 983, 0x95bf }, { 994, 0x6677 }, { 1004, 0xbfbf }, { 1018, 0x3bfb }, { 1030, 0xfeb4 }, { 1041, 0x7bae }, { 1052, 0x11e2 }, { 1058, 0xa681 }, { 1064, 0x41be }, { 1072, 0x1435 }, { 1078, 0x72c3 }, { 1086, 0x7d70 }, { 1095, 0x7191 }, { 1102, 0x0003 }, { 1104, 0x276b }, /* 0x5200 */ { 1113, 0x57cb }, { 1123, 0x70cf }, { 1132, 0x4732 }, { 1139, 0x0def }, { 1149, 0x7eda }, { 1160, 0xfc74 }, { 1170, 0xfe06 }, { 1179, 0xbdb4 }, { 1189, 0x3f9f }, { 1201, 0x8bca }, { 1209, 0x7e49 }, { 1218, 0x5800 }, { 1221, 0x228f }, { 1228, 0xebec }, { 1239, 0x8a5c }, { 1246, 0xddbb }, /* 0x5300 */ { 1258, 0xef60 }, { 1267, 0xb6e7 }, { 1278, 0xa40f }, { 1285, 0xf293 }, { 1294, 0x37bb }, { 1305, 0x549e }, { 1313, 0xd04b }, { 1320, 0x9baf }, { 1331, 0xc414 }, { 1336, 0xf7d4 }, { 1347, 0x30b0 }, { 1352, 0x0a14 }, { 1356, 0x2f08 }, { 1362, 0x88d0 }, { 1367, 0xff7e }, { 1381, 0x192f }, /* 0x5400 */ { 1389, 0xffda }, { 1402, 0xfb07 }, { 1412, 0x7ff1 }, { 1424, 0x7beb }, { 1436, 0xc5ef }, { 1447, 0x0010 }, { 1448, 0x99ff }, { 1460, 0xfdff }, { 1475, 0x79d7 }, { 1486, 0x0567 }, { 1493, 0xffe7 }, { 1507, 0xfdcb }, { 1519, 0xc3ff }, { 1531, 0x4040 }, { 1533, 0x6ff7 }, { 1546, 0xbd8e }, /* 0x5500 */ { 1556, 0xdffa }, { 1569, 0x0497 }, { 1575, 0xf4c0 }, { 1582, 0x5bff }, { 1595, 0xed7b }, { 1607, 0xd0e7 }, { 1616, 0x047e }, { 1623, 0xf8e0 }, { 1631, 0xff9f }, { 1645, 0xb73e }, { 1656, 0x7dfe }, { 1669, 0x882e }, { 1675, 0xfffd }, { 1690, 0xbe7f }, { 1703, 0x83fe }, { 1713, 0xf6c4 }, /* 0x5600 */ { 1722, 0xf357 }, { 1733, 0xb8fd }, { 1744, 0xd680 }, { 1750, 0xef7d }, { 1763, 0x5767 }, { 1773, 0x4788 }, { 1779, 0xff7d }, { 1793, 0xc3df }, { 1804, 0xf0ff }, { 1816, 0x37a9 }, { 1825, 0x7de0 }, { 1834, 0x70fc }, { 1843, 0x3f6f }, { 1855, 0xec9a }, { 1864, 0x4cb3 }, { 1872, 0x8681 }, /* 0x5700 */ { 1877, 0x3f9e }, { 1888, 0xdd5c }, { 1898, 0xf70d }, { 1908, 0x4819 }, { 1913, 0xfea3 }, { 1924, 0x0007 }, { 1927, 0xaf56 }, { 1937, 0x38ff }, { 1948, 0x980d }, { 1954, 0xefb8 }, { 1965, 0x403d }, { 1971, 0xb760 }, { 1979, 0xd8ce }, { 1988, 0x9035 }, { 1994, 0x72bf }, { 2005, 0x3fff }, /* 0x5800 */ { 2019, 0x7ff7 }, { 2033, 0x7a11 }, { 2040, 0xf7bb }, { 2053, 0xabff }, { 2066, 0xff00 }, { 2074, 0x6fbe }, { 2086, 0xa93c }, { 2094, 0xfe72 }, { 2105, 0xcfef }, { 2118, 0xf11b }, { 2127, 0xdb6b }, { 2138, 0xf40a }, { 2145, 0xc3e6 }, { 2154, 0xef7e }, { 2167, 0x9b9c }, { 2176, 0xf610 }, /* 0x5900 */ { 2183, 0xf048 }, { 2189, 0x16f4 }, { 2197, 0xfeb5 }, { 2209, 0x5182 }, { 2214, 0xc7b1 }, { 2223, 0x15bb }, { 2232, 0x6e87 }, { 2241, 0xfbdf }, { 2255, 0xe43f }, { 2265, 0x63cd }, { 2274, 0xc1ff }, { 2285, 0x7e7e }, { 2297, 0xfdeb }, { 2310, 0x7d5f }, { 2322, 0x777b }, { 2334, 0xfcfe }, /* 0x5a00 */ { 2347, 0x960b }, { 2354, 0xdbea }, { 2365, 0x6229 }, { 2371, 0x53e8 }, { 2379, 0x37df }, { 2391, 0xfdef }, { 2405, 0x36f5 }, { 2415, 0xbd81 }, { 2423, 0xdc18 }, { 2430, 0xfcbd }, { 2442, 0xd2e4 }, { 2450, 0xffff }, { 2466, 0x3fd7 }, { 2478, 0xffe0 }, { 2489, 0x7f6f }, { 2502, 0xabf8 }, /* 0x5b00 */ { 2512, 0x9bae }, { 2522, 0x6ed9 }, { 2532, 0xf5fb }, { 2545, 0xf115 }, { 2553, 0x79a9 }, { 2562, 0xbdfb }, { 2575, 0x5a3c }, { 2583, 0xadaf }, { 2594, 0xdbba }, { 2605, 0x1fac }, { 2614, 0x71fc }, { 2624, 0x8379 }, { 2632, 0x7cf7 }, { 2644, 0xc35f }, { 2654, 0xdfff }, { 2669, 0x0567 }, /* 0x5c00 */ { 2676, 0xff9a }, { 2688, 0x8467 }, { 2695, 0x1534 }, { 2701, 0xdf8b }, { 2712, 0xf9f3 }, { 2724, 0x3373 }, { 2733, 0xf7bd }, { 2746, 0x5e1a }, { 2754, 0xbf40 }, { 2762, 0xa03f }, { 2770, 0xffff }, { 2786, 0x01eb }, { 2793, 0xdfc0 }, { 2802, 0xcfdd }, { 2814, 0x7500 }, { 2819, 0xabd3 }, /* 0x5d00 */ { 2829, 0xf8c3 }, { 2838, 0xeed6 }, { 2849, 0x43fd }, { 2859, 0xb7ff }, { 2873, 0x5eaf }, { 2884, 0x4227 }, { 2890, 0x9bac }, { 2899, 0xf686 }, { 2908, 0x27d7 }, { 2918, 0xf6bc }, { 2929, 0xf787 }, { 2940, 0x35b7 }, { 2950, 0xaacd }, { 2959, 0xe176 }, { 2968, 0x49e7 }, { 2977, 0xe29f }, /* 0x5e00 */ { 2987, 0x545c }, { 2994, 0xaff2 }, { 3005, 0x2b3f }, { 3015, 0x61d8 }, { 3022, 0xfc3b }, { 3033, 0xbbb8 }, { 3043, 0xffcf }, { 3057, 0x7b7d }, { 3069, 0xbf95 }, { 3080, 0x1ce0 }, { 3086, 0x7dfd }, { 3099, 0x43ff }, { 3110, 0x5ff6 }, { 3122, 0xfffe }, { 3137, 0xd3ef }, { 3149, 0xc4ce }, /* 0x5f00 */ { 3157, 0x8db6 }, { 3166, 0xadbc }, { 3176, 0x63dc }, { 3185, 0x11eb }, { 3193, 0xdf59 }, { 3204, 0x23d0 }, { 3210, 0xbeb4 }, { 3220, 0xf3db }, { 3232, 0x1fe7 }, { 3243, 0xdbc7 }, { 3254, 0xff63 }, { 3266, 0xfae4 }, { 3276, 0xb22b }, { 3284, 0x63f7 }, { 3295, 0xed3b }, { 3306, 0xadba }, /* 0x6000 */ { 3316, 0xfe01 }, { 3324, 0x7eff }, { 3338, 0xfff7 }, { 3353, 0x02bc }, { 3359, 0x32ff }, { 3370, 0xef39 }, { 3381, 0xfffc }, { 3395, 0x8005 }, { 3398, 0x77fb }, { 3411, 0xbcf5 }, { 3422, 0x010d }, { 3426, 0xfff7 }, { 3441, 0xfffb }, { 3456, 0xbf3a }, { 3467, 0x0057 }, { 3472, 0xdfff }, /* 0x6100 */ { 3487, 0xef7b }, { 3500, 0xbd7d }, { 3512, 0xdb88 }, { 3520, 0xc8d4 }, { 3527, 0xfff3 }, { 3541, 0xed7c }, { 3552, 0x5dee }, { 3563, 0x56ff }, { 3575, 0x7e0d }, { 3584, 0xac5f }, { 3594, 0xff96 }, { 3606, 0xd57f }, { 3618, 0x3fee }, { 3630, 0xc140 }, { 3634, 0x6ff9 }, { 3646, 0xffe7 }, /* 0x6200 */ { 3660, 0x779b }, { 3671, 0x8e77 }, { 3681, 0x6ebf }, { 3693, 0xe45d }, { 3702, 0x6fcf }, { 3714, 0x5f1f }, { 3725, 0xe07f }, { 3735, 0xfedf }, { 3749, 0xd7db }, { 3761, 0x01fe }, { 3769, 0xff00 }, { 3777, 0xfb7b }, { 3790, 0xffd4 }, { 3802, 0x1fdf }, { 3814, 0xf800 }, { 3819, 0xffff }, /* 0x6300 */ { 3835, 0xfb8f }, { 3847, 0x007b }, { 3853, 0xbf00 }, { 3860, 0x7f5c }, { 3871, 0xffff }, { 3887, 0x07f3 }, { 3896, 0xeba0 }, { 3904, 0x3de7 }, { 3915, 0xf7bf }, { 3929, 0xfbd7 }, { 3942, 0xffbf }, { 3957, 0x6003 }, { 3961, 0xfffd }, { 3976, 0xbfed }, { 3989, 0xefbb }, { 4002, 0x027f }, /* 0x6400 */ { 4010, 0xfe40 }, { 4018, 0xddfd }, { 4031, 0xfdff }, { 4046, 0xe2f9 }, { 4056, 0x680b }, { 4062, 0xfb1f }, { 4074, 0xfbe3 }, { 4086, 0xaffd }, { 4099, 0x9fa4 }, { 4108, 0xf7ed }, { 4121, 0x7a7d }, { 4132, 0xf80f }, { 4141, 0xeebe }, { 4153, 0x0fd5 }, { 4162, 0xbb5d }, { 4173, 0xfd9f }, /* 0x6500 */ { 4186, 0xf2db }, { 4197, 0x3bf9 }, { 4208, 0xfe7f }, { 4222, 0xebcc }, { 4232, 0x876a }, { 4240, 0x73fa }, { 4251, 0x95fc }, { 4261, 0x9ffc }, { 4273, 0x109f }, { 4280, 0xfaf7 }, { 4293, 0xddb7 }, { 4305, 0xbbcd }, { 4316, 0xf87e }, { 4327, 0xeccd }, { 4337, 0xf366 }, { 4347, 0x3c3f }, /* 0x6600 */ { 4357, 0xfffd }, { 4372, 0xb03f }, { 4381, 0xe9f7 }, { 4393, 0x067e }, { 4401, 0x96ae }, { 4410, 0xfe06 }, { 4419, 0xd576 }, { 4429, 0x5fd7 }, { 4441, 0x3fd1 }, { 4451, 0xa3f3 }, { 4461, 0xcf07 }, { 4470, 0x6fb7 }, { 4482, 0x9fd1 }, { 4492, 0x7f44 }, { 4501, 0x7b59 }, { 4511, 0xd3dd }, /* 0x6700 */ { 4522, 0xaf3b }, { 4533, 0xa9bd }, { 4543, 0x7dcf }, { 4555, 0xff3a }, { 4567, 0xfbe0 }, { 4577, 0xf6eb }, { 4589, 0xb401 }, { 4594, 0xffff }, { 4610, 0x7afa }, { 4621, 0xb7bf }, { 4634, 0xc000 }, { 4636, 0x0ffd }, { 4647, 0xff7f }, { 4662, 0xff1f }, { 4675, 0xfefc }, { 4688, 0x95ff }, /* 0x6800 */ { 4700, 0x0000 }, { 4700, 0xb5dc }, { 4710, 0xef63 }, { 4721, 0x3f3e }, { 4732, 0xfb7f }, { 4746, 0x001b }, { 4750, 0xe800 }, { 4754, 0xfbf6 }, { 4767, 0x9eef }, { 4779, 0xb8df }, { 4790, 0xff9f }, { 4804, 0x003f }, { 4810, 0x7bd0 }, { 4819, 0xf5ff }, { 4833, 0xdfdb }, { 4846, 0x3fff }, /* 0x6900 */ { 4860, 0xfdf0 }, { 4871, 0x00bf }, { 4878, 0x8420 }, { 4881, 0xbbbd }, { 4893, 0xdf37 }, { 4905, 0xffde }, { 4919, 0xff6d }, { 4932, 0x0ff3 }, { 4942, 0x604c }, { 4947, 0x5efb }, { 4959, 0xfffb }, { 4974, 0xfafb }, { 4987, 0xfe5e }, { 4999, 0x0219 }, { 5003, 0x79f4 }, { 5013, 0xf9de }, /* 0x6a00 */ { 5025, 0xa7f7 }, { 5037, 0xebfa }, { 5049, 0x01eb }, { 5056, 0xff34 }, { 5067, 0xebd3 }, { 5078, 0xef73 }, { 5090, 0xafd7 }, { 5102, 0xc040 }, { 5105, 0x72bb }, { 5115, 0xdcff }, { 5128, 0xf17f }, { 5140, 0x2fd8 }, { 5149, 0xb8ec }, { 5158, 0xfe0b }, { 5168, 0xdda3 }, { 5178, 0x1f0b }, /* 0x6b00 */ { 5186, 0x8f1d }, { 5195, 0x47cf }, { 5205, 0xb12b }, { 5213, 0xffde }, { 5227, 0x7fee }, { 5240, 0xda73 }, { 5250, 0x24ff }, { 5260, 0xcbc4 }, { 5268, 0xf75d }, { 5280, 0xcbf2 }, { 5290, 0xecfd }, { 5302, 0xb4ed }, { 5312, 0xbff9 }, { 5325, 0x4ddd }, { 5335, 0x99dd }, { 5345, 0xfb8d }, /* 0x6c00 */ { 5356, 0xbb7f }, { 5369, 0xaf7b }, { 5381, 0xddfb }, { 5394, 0xc959 }, { 5402, 0xfc4f }, { 5413, 0xfab5 }, { 5424, 0xafe3 }, { 5435, 0x6d5f }, { 5446, 0xffff }, { 5462, 0x3f7d }, { 5474, 0x7800 }, { 5478, 0xffdb }, { 5492, 0xb6ff }, { 5505, 0x7eff }, { 5519, 0xfbaf }, { 5532, 0x022f }, /* 0x6d00 */ { 5538, 0xff9b }, { 5551, 0xefc7 }, { 5563, 0xffa5 }, { 5575, 0xffff }, { 5591, 0x0007 }, { 5594, 0xc700 }, { 5599, 0xf7ff }, { 5614, 0xfff1 }, { 5627, 0x7ffd }, { 5641, 0x01bf }, { 5649, 0xdc00 }, { 5654, 0xfdbc }, { 5666, 0xbff5 }, { 5679, 0xffff }, { 5695, 0xff7f }, { 5710, 0x3eff }, /* 0x6e00 */ { 5723, 0x0029 }, { 5726, 0xbe00 }, { 5732, 0xf9ff }, { 5746, 0xff7f }, { 5761, 0x6efb }, { 5773, 0xfd7e }, { 5786, 0xcbff }, { 5799, 0x039e }, { 5806, 0xe300 }, { 5811, 0xfbdd }, { 5824, 0xccff }, { 5836, 0xf6df }, { 5849, 0xffff }, { 5865, 0x117f }, { 5874, 0xf800 }, { 5879, 0xfbf6 }, /* 0x6f00 */ { 5892, 0xe7ef }, { 5905, 0xd73c }, { 5915, 0xfeef }, { 5929, 0xdfef }, { 5943, 0xc00b }, { 5948, 0xedbf }, { 5961, 0xfedf }, { 5975, 0xfdcd }, { 5987, 0x7bf5 }, { 5999, 0x40fd }, { 6007, 0xffff }, { 6023, 0xb75f }, { 6035, 0xffdf }, { 6050, 0xf930 }, { 6058, 0xfbdf }, { 6072, 0xdc97 }, /* 0x7000 */ { 6082, 0xfef3 }, { 6095, 0xbff2 }, { 6107, 0x8fdf }, { 6119, 0xdfbf }, { 6133, 0x177f }, { 6144, 0xede6 }, { 6155, 0x0f7f }, { 6166, 0x3553 }, { 6174, 0x447c }, { 6181, 0x877e }, { 6191, 0xfa12 }, { 6199, 0x45bb }, { 6208, 0xede0 }, { 6217, 0x779e }, { 6228, 0x8017 }, { 6233, 0xbfd9 }, /* 0x7100 */ { 6245, 0x7e55 }, { 6255, 0xde89 }, { 6264, 0xc16f }, { 6273, 0x0447 }, { 6278, 0x7ade }, { 6289, 0xf75d }, { 6301, 0x57ff }, { 6314, 0x2905 }, { 6319, 0x86f7 }, { 6329, 0xfe95 }, { 6340, 0x97b3 }, { 6350, 0xf32f }, { 6361, 0xcfff }, { 6375, 0x9f75 }, { 6386, 0x71f7 }, { 6397, 0xfb17 }, /* 0x7200 */ { 6408, 0x34ee }, { 6417, 0xee19 }, { 6426, 0x37cc }, { 6435, 0xef61 }, { 6445, 0x9fd6 }, { 6456, 0xef4c }, { 6466, 0xd68f }, { 6476, 0xfbdd }, { 6489, 0x7b73 }, { 6500, 0x6def }, { 6512, 0xd7fe }, { 6525, 0xa431 }, { 6531, 0x5e7f }, { 6543, 0x97d7 }, { 6554, 0x0f5b }, { 6563, 0xffd8 }, /* 0x7300 */ { 6575, 0x9d83 }, { 6583, 0x7bce }, { 6594, 0x22ec }, { 6601, 0xdcff }, { 6614, 0x763d }, { 6624, 0xef87 }, { 6635, 0xdfe7 }, { 6648, 0xfded }, { 6661, 0x4fff }, { 6674, 0xa0fc }, { 6682, 0x3b77 }, { 6693, 0xdbfc }, { 6705, 0x3ded }, { 6716, 0x7fdc }, { 6728, 0x6fa9 }, { 6738, 0xf570 }, /* 0x7400 */ { 6747, 0x3ffb }, { 6760, 0x2c40 }, { 6764, 0xff7f }, { 6779, 0x847f }, { 6788, 0xec57 }, { 6798, 0xdeb7 }, { 6810, 0xe69c }, { 6819, 0xf22f }, { 6829, 0x0feb }, { 6839, 0xd5b5 }, { 6849, 0xafeb }, { 6861, 0xede7 }, { 6873, 0x8c2f }, { 6881, 0xfff0 }, { 6893, 0x537f }, { 6904, 0xe8f0 }, /* 0x7500 */ { 6912, 0xb99d }, { 6922, 0xb5ff }, { 6935, 0xff66 }, { 6947, 0xe78f }, { 6958, 0xd981 }, { 6965, 0xbe10 }, { 6972, 0x9c7c }, { 6981, 0xe3c1 }, { 6989, 0x9cd1 }, { 6997, 0x2733 }, { 7005, 0x0cbc }, { 7012, 0xff6d }, { 7025, 0xfcb7 }, { 7037, 0xefb7 }, { 7050, 0xa0df }, { 7059, 0xffff }, /* 0x7600 */ { 7075, 0xbf0b }, { 7085, 0xfe7b }, { 7098, 0xa3ff }, { 7110, 0x353f }, { 7120, 0x13cc }, { 7127, 0x97cd }, { 7137, 0x7637 }, { 7147, 0xfb27 }, { 7158, 0xcfd6 }, { 7169, 0x7e6c }, { 7179, 0xec50 }, { 7186, 0xed31 }, { 7195, 0x677c }, { 7205, 0xfc1c }, { 7214, 0xf6fa }, { 7226, 0x5fbf }, /* 0x7700 */ { 7239, 0x0fba }, { 7248, 0xae2f }, { 7258, 0xa3ad }, { 7267, 0x7ffe }, { 7281, 0xfcf0 }, { 7291, 0xde74 }, { 7301, 0xffef }, { 7316, 0xf200 }, { 7321, 0xfbbf }, { 7335, 0xfea2 }, { 7345, 0x3daf }, { 7356, 0xbcff }, { 7369, 0xf694 }, { 7378, 0x5fb9 }, { 7389, 0xf3ad }, { 7400, 0x3f8f }, /* 0x7800 */ { 7411, 0xf26c }, { 7420, 0xa01f }, { 7427, 0xffef }, { 7442, 0x01bf }, { 7450, 0x7728 }, { 7458, 0x7005 }, { 7463, 0xff35 }, { 7475, 0xda03 }, { 7482, 0xd2f9 }, { 7492, 0xc7fa }, { 7503, 0x3fbf }, { 7516, 0x5c1d }, { 7524, 0xff3a }, { 7536, 0xec33 }, { 7545, 0xb7af }, { 7557, 0xfe9c }, /* 0x7900 */ { 7568, 0x5236 }, { 7575, 0x7a9f }, { 7586, 0xbffa }, { 7599, 0xe722 }, { 7607, 0x9ff7 }, { 7620, 0xfcff }, { 7634, 0x2fbb }, { 7645, 0xb61d }, { 7654, 0xed06 }, { 7662, 0x1dfd }, { 7673, 0x7dd7 }, { 7685, 0xefdf }, { 7699, 0xeb23 }, { 7708, 0xf166 }, { 7717, 0x7ed9 }, { 7728, 0x0dc0 }, /* 0x7a00 */ { 7733, 0x3d3d }, { 7743, 0xdfbf }, { 7757, 0xc945 }, { 7764, 0xba83 }, { 7772, 0x7dd1 }, { 7782, 0x9dd0 }, { 7790, 0x7b87 }, { 7800, 0xcf73 }, { 7811, 0x9ff3 }, { 7823, 0xc3f5 }, { 7833, 0xdf0d }, { 7843, 0xc5fe }, { 7854, 0x0cb3 }, { 7861, 0x8302 }, { 7865, 0xe879 }, { 7874, 0xaec0 }, /* 0x7b00 */ { 7881, 0xc773 }, { 7891, 0x6f0f }, { 7901, 0xfd7d }, { 7914, 0x093f }, { 7922, 0xfff1 }, { 7935, 0x0157 }, { 7941, 0x62fb }, { 7951, 0x01ff }, { 7960, 0xfdb4 }, { 7971, 0x3bf3 }, { 7982, 0xb013 }, { 7988, 0x43b2 }, { 7995, 0x5ed3 }, { 8005, 0xff30 }, { 8015, 0x0fff }, { 8027, 0xeb9f }, /* 0x7c00 */ { 8039, 0xfeef }, { 8053, 0xf203 }, { 8060, 0x3fef }, { 8073, 0xfb89 }, { 8083, 0x37a9 }, { 8092, 0x9e99 }, { 8101, 0xdef9 }, { 8113, 0xa72c }, { 8121, 0x3733 }, { 8130, 0xc1f6 }, { 8139, 0x812e }, { 8145, 0xfe3e }, { 8157, 0x5d20 }, { 8163, 0xf2f7 }, { 8175, 0xd585 }, { 8183, 0x69d7 }, /* 0x7d00 */ { 8193, 0xffff }, { 8209, 0xffff }, { 8225, 0xdb07 }, { 8234, 0xff6f }, { 8248, 0xc4ff }, { 8259, 0xd97f }, { 8271, 0xefce }, { 8283, 0xbe0f }, { 8293, 0xf17b }, { 8304, 0xf05e }, { 8313, 0xf6cf }, { 8325, 0xffb7 }, { 8339, 0x5ef7 }, { 8351, 0xef84 }, { 8360, 0xd7cb }, { 8371, 0x0edf }, /* 0x7e00 */ { 8381, 0xff08 }, { 8390, 0xfcff }, { 8404, 0xee3f }, { 8416, 0xffff }, { 8432, 0x13ff }, { 8443, 0xd7ff }, { 8457, 0xaf0f }, { 8467, 0x7ffd }, { 8481, 0xbdc7 }, { 8492, 0x1ffa }, { 8503, 0x0000 }, { 8503, 0x0000 }, { 8503, 0x0000 }, { 8503, 0x0000 }, { 8503, 0x0000 }, { 8503, 0x0000 }, /* 0x7f00 */ { 8503, 0x0000 }, { 8503, 0x0000 }, { 8503, 0x0000 }, { 8503, 0xe740 }, { 8510, 0xbd38 }, { 8519, 0xf933 }, { 8529, 0x7feb }, { 8542, 0xfeed }, { 8555, 0x7fe8 }, { 8566, 0x7c76 }, { 8576, 0xb3f7 }, { 8588, 0xffef }, { 8603, 0xfeaf }, { 8616, 0xd8b7 }, { 8626, 0xff6f }, { 8640, 0xfbbf }, /* 0x8000 */ { 8654, 0xf8fb }, { 8666, 0xdbf7 }, { 8679, 0x1752 }, { 8686, 0xe2f9 }, { 8696, 0x85c8 }, { 8702, 0x7547 }, { 8711, 0x9090 }, { 8715, 0xe3ef }, { 8727, 0x9ef4 }, { 8737, 0x3f6d }, { 8748, 0xee2e }, { 8758, 0x0536 }, { 8764, 0xf7bc }, { 8776, 0x7ff3 }, { 8789, 0xa07b }, { 8797, 0x7f3f }, /* 0x8100 */ { 8810, 0x0567 }, { 8817, 0xeb60 }, { 8825, 0xbabe }, { 8836, 0x6601 }, { 8841, 0xfcd8 }, { 8851, 0x583f }, { 8860, 0xcaf7 }, { 8871, 0x87df }, { 8882, 0xbfcd }, { 8894, 0xffa0 }, { 8904, 0x5bcd }, { 8914, 0xfebf }, { 8928, 0xb6fd }, { 8940, 0xefa7 }, { 8952, 0x77ef }, { 8965, 0xdf9c }, /* 0x8200 */ { 8976, 0x3fb7 }, { 8988, 0xf877 }, { 8999, 0x9d27 }, { 9008, 0xb7fc }, { 9020, 0xcab5 }, { 9029, 0xdfef }, { 9043, 0xfb5a }, { 9054, 0xf1b6 }, { 9064, 0xec39 }, { 9073, 0xef1f }, { 9085, 0xfbbf }, { 9099, 0x7ffb }, { 9113, 0x000d }, { 9116, 0xdafe }, { 9128, 0xbdfb }, { 9141, 0x4e7f }, /* 0x8300 */ { 9152, 0x33ff }, { 9164, 0x5ac0 }, { 9170, 0xbff5 }, { 9183, 0x9ffe }, { 9196, 0xffbf }, { 9211, 0x005f }, { 9217, 0x0000 }, { 9217, 0xfdf8 }, { 9229, 0xffca }, { 9241, 0x6ffd }, { 9254, 0xcffd }, { 9267, 0xa001 }, { 9270, 0xdfff }, { 9285, 0xfbf2 }, { 9297, 0xdfbf }, { 9311, 0xff7f }, /* 0x8400 */ { 9326, 0xfeda }, { 9338, 0x080f }, { 9343, 0xba08 }, { 9349, 0xbfff }, { 9364, 0x7afd }, { 9376, 0xeed7 }, { 9388, 0xfbeb }, { 9401, 0x67f9 }, { 9412, 0xe044 }, { 9417, 0xff93 }, { 9429, 0xdf97 }, { 9441, 0x9f57 }, { 9452, 0xfef7 }, { 9466, 0x08df }, { 9474, 0xdf80 }, { 9482, 0xfedf }, /* 0x8500 */ { 9496, 0xffc5 }, { 9508, 0xf7fe }, { 9522, 0xfffb }, { 9537, 0x6803 }, { 9542, 0x67fb }, { 9554, 0x6bfa }, { 9565, 0x7fff }, { 9580, 0x5fe2 }, { 9590, 0xffff }, { 9606, 0xff73 }, { 9619, 0x87df }, { 9630, 0xe7fb }, { 9643, 0xebfd }, { 9656, 0xf7a7 }, { 9668, 0xbf7e }, { 9681, 0xefc7 }, /* 0x8600 */ { 9693, 0x1ef3 }, { 9703, 0xdf82 }, { 9712, 0x76ff }, { 9725, 0xdf7e }, { 9738, 0x79c9 }, { 9747, 0xda7d }, { 9758, 0xefbe }, { 9771, 0x1e9b }, { 9780, 0x7ce0 }, { 9788, 0x77fb }, { 9801, 0x87be }, { 9811, 0xfffb }, { 9826, 0x1bff }, { 9838, 0xffdb }, { 9852, 0x3f5c }, { 9862, 0x4fe0 }, /* 0x8700 */ { 9870, 0x7fff }, { 9885, 0x5f0e }, { 9894, 0x77ff }, { 9908, 0xddbf }, { 9921, 0xf04f }, { 9930, 0xffff }, { 9946, 0xffff }, { 9962, 0x0ff8 }, { 9971, 0xa3be }, { 9981, 0xfddf }, { 9995, 0xfc1c }, { 10004, 0xfffd }, { 10019, 0x1f7d }, { 10030, 0xfb9e }, { 10042, 0xbdff }, { 10056, 0xdedc }, /* 0x8800 */ { 10067, 0x3f6f }, { 10079, 0xbafb }, { 10091, 0xdf7f }, { 10105, 0xfbef }, { 10119, 0x7d1b }, { 10129, 0x2eec }, { 10138, 0xaf8e }, { 10148, 0xf2f7 }, { 10160, 0x7b0f }, { 10170, 0xcfee }, { 10182, 0x1d96 }, { 10190, 0x77c6 }, { 10200, 0x7e07 }, { 10209, 0xfff5 }, { 10223, 0xd982 }, { 10230, 0x7fdf }, /* 0x8900 */ { 10244, 0x5ee6 }, { 10254, 0xc7ff }, { 10267, 0xfeee }, { 10280, 0x79ef }, { 10292, 0x9a56 }, { 10300, 0xffcf }, { 10314, 0xfe5f }, { 10327, 0xde5e }, { 10338, 0x896e }, { 10346, 0xf9e8 }, { 10356, 0xf45e }, { 10366, 0xe6c4 }, { 10374, 0x0001 }, { 10375, 0xbe7c }, { 10386, 0x3b7f }, { 10398, 0xdddf }, /* 0x8a00 */ { 10411, 0xd59d }, { 10421, 0xe9ef }, { 10433, 0x34ac }, { 10440, 0xde53 }, { 10450, 0xf573 }, { 10461, 0x4bf7 }, { 10472, 0x7b4f }, { 10483, 0x9eff }, { 10496, 0xb8fe }, { 10507, 0x476e }, { 10516, 0x0dfb }, { 10526, 0xff45 }, { 10537, 0xabfd }, { 10549, 0xfbfe }, { 10563, 0xe9d7 }, { 10574, 0xddff }, /* 0x8b00 */ { 10588, 0xedf7 }, { 10601, 0x7fff }, { 10616, 0xddfd }, { 10629, 0x7eeb }, { 10641, 0xcfe7 }, { 10653, 0xb7ff }, { 10667, 0xbde9 }, { 10678, 0xef91 }, { 10688, 0x5d75 }, { 10698, 0xd77c }, { 10709, 0x0000 }, { 10709, 0x0000 }, { 10709, 0x0000 }, { 10709, 0x0000 }, { 10709, 0x0000 }, { 10709, 0x0000 }, /* 0x8c00 */ { 10709, 0x0000 }, { 10709, 0x0000 }, { 10709, 0x0000 }, { 10709, 0xfa80 }, { 10716, 0xffee }, { 10730, 0xb4f1 }, { 10739, 0xbf76 }, { 10751, 0x2fef }, { 10763, 0xb677 }, { 10774, 0x77bf }, { 10787, 0x9fbf }, { 10800, 0xfffd }, { 10815, 0x95bf }, { 10826, 0xf6ae }, { 10837, 0x75ff }, { 10850, 0x7f3b }, /* 0x8d00 */ { 10862, 0xa7f5 }, { 10873, 0x0af9 }, { 10881, 0x0000 }, { 10881, 0x0000 }, { 10881, 0x0000 }, { 10881, 0x0000 }, { 10881, 0xfbd0 }, { 10891, 0x2bdd }, { 10901, 0xf633 }, { 10911, 0x9a7f }, { 10922, 0xfdab }, { 10934, 0xd6fc }, { 10945, 0xf9e6 }, { 10956, 0xbfeb }, { 10969, 0xdfdf }, { 10983, 0xf41f }, /* 0x8e00 */ { 10993, 0xa6fd }, { 11004, 0xffff }, { 11020, 0x4aff }, { 11031, 0xf37b }, { 11043, 0x7fb7 }, { 11056, 0xfef9 }, { 11069, 0xb6ff }, { 11082, 0x1d5c }, { 11090, 0x7ff6 }, { 11103, 0xe5ff }, { 11116, 0x1f7b }, { 11127, 0x2404 }, { 11130, 0xbe05 }, { 11138, 0xf99e }, { 11149, 0xdbe3 }, { 11160, 0xdff2 }, /* 0x8f00 */ { 11172, 0x6fef }, { 11185, 0xfdff }, { 11200, 0xd679 }, { 11210, 0xcbfc }, { 11221, 0xebfd }, { 11234, 0xefff }, { 11249, 0x001f }, { 11254, 0x0000 }, { 11254, 0x0000 }, { 11254, 0x9800 }, { 11257, 0xe148 }, { 11263, 0x8017 }, { 11268, 0x6a74 }, { 11276, 0x00fe }, { 11283, 0x6d7f }, { 11295, 0xfdf1 }, /* 0x9000 */ { 11307, 0xb87f }, { 11318, 0xfef3 }, { 11331, 0xe01f }, { 11339, 0xf176 }, { 11349, 0xee96 }, { 11359, 0x7b3f }, { 11371, 0xeb8d }, { 11381, 0xfffd }, { 11396, 0xadff }, { 11409, 0xcbb3 }, { 11419, 0x84ef }, { 11428, 0xe17f }, { 11439, 0x4daa }, { 11447, 0xbff0 }, { 11458, 0xbf3f }, { 11471, 0xfe3f }, /* 0x9100 */ { 11484, 0xebff }, { 11498, 0xffd7 }, { 11512, 0xffdf }, { 11527, 0xcf7f }, { 11540, 0xfffb }, { 11555, 0x85ed }, { 11564, 0xd73f }, { 11576, 0x07bc }, { 11584, 0xaeff }, { 11597, 0xfe0f }, { 11608, 0xfdaf }, { 11621, 0x76bf }, { 11633, 0xfaef }, { 11646, 0x37bb }, { 11657, 0x7fdc }, { 11669, 0xa3ba }, /* 0x9200 */ { 11678, 0xb6ff }, { 11691, 0x56f7 }, { 11702, 0x60f8 }, { 11709, 0xe7df }, { 11722, 0xff61 }, { 11733, 0x4cdf }, { 11743, 0xb0fb }, { 11753, 0xff45 }, { 11764, 0x7ded }, { 11776, 0x3ffa }, { 11788, 0x1fff }, { 11801, 0x18fc }, { 11809, 0xffff }, { 11825, 0xe3af }, { 11836, 0xc7d3 }, { 11846, 0xdf83 }, /* 0x9300 */ { 11856, 0xfb57 }, { 11868, 0xef7d }, { 11881, 0xefff }, { 11896, 0x1378 }, { 11903, 0xfec0 }, { 11912, 0x5ff7 }, { 11925, 0x34bb }, { 11934, 0x5ee3 }, { 11944, 0xf70d }, { 11954, 0xeff6 }, { 11967, 0xd7fe }, { 11980, 0x00bf }, { 11987, 0xf59d }, { 11998, 0xf7f7 }, { 12012, 0x51de }, { 12021, 0xffe0 }, /* 0x9400 */ { 12032, 0xfec9 }, { 12043, 0x037f }, { 12052, 0x5f01 }, { 12059, 0xbfef }, { 12073, 0x9ff1 }, { 12084, 0x60a7 }, { 12091, 0xef1d }, { 12102, 0xf1ff }, { 12115, 0x000f }, { 12119, 0x0000 }, { 12119, 0x0000 }, { 12119, 0x0000 }, { 12119, 0x0000 }, { 12119, 0x0000 }, { 12119, 0x0000 }, { 12119, 0x0000 }, /* 0x9500 */ { 12119, 0x0000 }, { 12119, 0x0000 }, { 12119, 0x0000 }, { 12119, 0x0000 }, { 12119, 0x0000 }, { 12119, 0x0000 }, { 12119, 0x0000 }, { 12119, 0x3c80 }, { 12124, 0xfb4d }, { 12135, 0xd91f }, { 12145, 0x7b3a }, { 12155, 0xfee3 }, { 12167, 0x3fe9 }, { 12178, 0xdc7f }, { 12190, 0x003f }, { 12196, 0x0000 }, /* 0x9600 */ { 12196, 0x0000 }, { 12196, 0x5000 }, { 12198, 0xf51f }, { 12209, 0xbe07 }, { 12218, 0xfc1d }, { 12228, 0xf91b }, { 12238, 0xbc1e }, { 12247, 0x71ff }, { 12259, 0x6ff9 }, { 12271, 0x5bbe }, { 12282, 0x5796 }, { 12291, 0x9b1b }, { 12300, 0x7fff }, { 12315, 0xfffc }, { 12329, 0x872e }, { 12337, 0xafe7 }, /* 0x9700 */ { 12349, 0xebf5 }, { 12361, 0xf34f }, { 12372, 0xdffd }, { 12386, 0xe725 }, { 12395, 0x0bdc }, { 12403, 0x5d44 }, { 12410, 0x5747 }, { 12419, 0xfddd }, { 12432, 0xed3f }, { 12444, 0x7790 }, { 12452, 0x7d7f }, { 12465, 0x8ac8 }, { 12471, 0xfafa }, { 12483, 0xf3f9 }, { 12495, 0x202a }, { 12499, 0xef4b }, /* 0x9800 */ { 12510, 0xf5ff }, { 12524, 0x79cf }, { 12535, 0xabd3 }, { 12545, 0x0ba5 }, { 12552, 0xf77a }, { 12564, 0xfb8f }, { 12576, 0x8ebd }, { 12586, 0x001f }, { 12591, 0x0000 }, { 12591, 0x0000 }, { 12591, 0xf300 }, { 12597, 0xfd4e }, { 12608, 0x1a57 }, { 12616, 0x8800 }, { 12618, 0xaeac }, { 12627, 0x7654 }, /* 0x9900 */ { 12635, 0x17ad }, { 12644, 0xcdff }, { 12657, 0xffb2 }, { 12669, 0xf42f }, { 12679, 0x5baa }, { 12688, 0xdbff }, { 12702, 0x0002 }, { 12703, 0x0000 }, { 12703, 0x0000 }, { 12703, 0x73c0 }, { 12710, 0xf9ea }, { 12721, 0x2e3f }, { 12731, 0xfa8e }, { 12741, 0xbbff }, { 12755, 0x76bc }, { 12765, 0xffd3 }, /* 0x9a00 */ { 12778, 0xeefe }, { 12791, 0x7e72 }, { 12801, 0x7ebd }, { 12813, 0xe7f7 }, { 12826, 0xf77f }, { 12840, 0xcefd }, { 12852, 0x0ff5 }, { 12862, 0x0000 }, { 12862, 0x0000 }, { 12862, 0x0000 }, { 12862, 0xa900 }, { 12866, 0xdb9b }, { 12877, 0xa4c7 }, { 12885, 0x917f }, { 12895, 0xf8ca }, { 12904, 0x7ece }, /* 0x9b00 */ { 12915, 0x7d7a }, { 12926, 0xc7e7 }, { 12937, 0xcbbd }, { 12948, 0xdcae }, { 12958, 0xfd7e }, { 12971, 0x8f76 }, { 12981, 0x91d3 }, { 12989, 0x7cf3 }, { 13000, 0x01e5 }, { 13006, 0x4c2f }, { 13014, 0xed77 }, { 13026, 0xa360 }, { 13032, 0x07db }, { 13041, 0x5ef8 }, { 13051, 0x1df7 }, { 13062, 0x2181 }, /* 0x9c00 */ { 13066, 0x6be0 }, { 13074, 0x309c }, { 13080, 0x3b3a }, { 13089, 0xfade }, { 13101, 0x7f53 }, { 13112, 0xc3f5 }, { 13122, 0x61cd }, { 13130, 0x07ba }, { 13138, 0x0000 }, { 13138, 0x0000 }, { 13138, 0x0000 }, { 13138, 0x0000 }, { 13138, 0x0000 }, { 13138, 0x0000 }, { 13138, 0x26e0 }, { 13144, 0xbefe }, /* 0x9d00 */ { 13157, 0x03f9 }, { 13165, 0xebb5 }, { 13176, 0xe36d }, { 13186, 0xe9cb }, { 13196, 0x9c2f }, { 13205, 0xbfde }, { 13218, 0x9f83 }, { 13227, 0xabbf }, { 13239, 0x1ff7 }, { 13251, 0xffd5 }, { 13264, 0xb7df }, { 13277, 0xdffe }, { 13291, 0xfdae }, { 13303, 0xffef }, { 13318, 0xfb7e }, { 13331, 0xeffd }, /* 0x9e00 */ { 13345, 0xaaff }, { 13357, 0x6ebf }, { 13369, 0x0000 }, { 13369, 0x0000 }, { 13369, 0x0000 }, { 13369, 0x0000 }, { 13369, 0x0000 }, { 13369, 0xb620 }, { 13375, 0x7fcd }, { 13387, 0xbe9e }, { 13398, 0x62b3 }, { 13406, 0x58f1 }, { 13414, 0xf10d }, { 13422, 0xfd7b }, { 13435, 0xe9f1 }, { 13445, 0xbefd }, /* 0x9f00 */ { 13458, 0xc6c3 }, { 13466, 0x5f6d }, { 13477, 0xff3d }, { 13490, 0x69ff }, { 13502, 0xffcf }, { 13516, 0xfbf4 }, { 13528, 0xdcfb }, { 13540, 0x4ff7 }, { 13552, 0x2000 }, { 13553, 0x1137 }, { 13560, 0x0015 }, }; static const Summary16 big5_uni2indx_pagefa[1] = { /* 0xfa00 */ { 13563, 0x3000 }, }; static const Summary16 big5_uni2indx_pagefe[23] = { /* 0xfe00 */ { 13565, 0x0000 }, { 13565, 0x0000 }, { 13565, 0x0000 }, { 13565, 0xfffb }, { 13580, 0xfe1f }, { 13592, 0xfef5 }, { 13605, 0x0e7f }, { 13615, 0x0000 }, { 13615, 0x0000 }, { 13615, 0x0000 }, { 13615, 0x0000 }, { 13615, 0x0000 }, { 13615, 0x0000 }, { 13615, 0x0000 }, { 13615, 0x0000 }, { 13615, 0x0000 }, /* 0xff00 */ { 13615, 0xff7a }, { 13628, 0xffff }, { 13644, 0xffff }, { 13660, 0x97ff }, { 13673, 0xfffe }, { 13688, 0x3fff }, { 13702, 0x0010 }, }; static int big5_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; if (n >= 2) { const Summary16 *summary = NULL; if (wc < 0x0100) summary = &big5_uni2indx_page00[(wc>>4)]; else if (wc >= 0x0200 && wc < 0x0460) summary = &big5_uni2indx_page02[(wc>>4)-0x020]; else if (wc >= 0x2000 && wc < 0x22c0) summary = &big5_uni2indx_page20[(wc>>4)-0x200]; else if (wc >= 0x2400 && wc < 0x2650) summary = &big5_uni2indx_page24[(wc>>4)-0x240]; else if (wc >= 0x3000 && wc < 0x33e0) summary = &big5_uni2indx_page30[(wc>>4)-0x300]; else if (wc >= 0x4e00 && wc < 0x9fb0) summary = &big5_uni2indx_page4e[(wc>>4)-0x4e0]; else if (wc >= 0xfa00 && wc < 0xfa10) summary = &big5_uni2indx_pagefa[(wc>>4)-0xfa0]; else if (wc >= 0xfe00 && wc < 0xff70) summary = &big5_uni2indx_pagefe[(wc>>4)-0xfe0]; if (summary) { unsigned short used = summary->used; unsigned int i = wc & 0x0f; if (used & ((unsigned short) 1 << i)) { unsigned short c; /* Keep in `used' only the bits 0..i-1. */ used &= ((unsigned short) 1 << i) - 1; /* Add `summary->indx' and the number of bits set in `used'. */ used = (used & 0x5555) + ((used & 0xaaaa) >> 1); used = (used & 0x3333) + ((used & 0xcccc) >> 2); used = (used & 0x0f0f) + ((used & 0xf0f0) >> 4); used = (used & 0x00ff) + (used >> 8); c = big5_2charset[summary->indx + used]; r[0] = (c >> 8); r[1] = (c & 0xff); return 2; } } return RET_ILSEQ; } return RET_TOOSMALL; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/cp936ext.h0000644000175000017500000151370615004135251020125 0ustar albrechtalbrecht/* * Character encoding support for the Fast Light Tool Kit (FLTK). * * Copyright 1998-2018 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #if defined(_WIN32) || defined(__APPLE__) /* PORTME: is this really needed? It's huge! */ /* not needed */ #else #ifndef CP936 #ifdef NEED_TOWC static int cp936ext_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { return 0; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static int cp936ext_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)r; (void)wc; (void)n; return 0; } #endif /* NEED_TOMB */ #else /* * CP936EXT */ #ifdef NEED_TOWC static const unsigned short cp936ext_2uni_page81[23766] = { /* 0x81 */ 0x4e02, 0x4e04, 0x4e05, 0x4e06, 0x4e0f, 0x4e12, 0x4e17, 0x4e1f, 0x4e20, 0x4e21, 0x4e23, 0x4e26, 0x4e29, 0x4e2e, 0x4e2f, 0x4e31, 0x4e33, 0x4e35, 0x4e37, 0x4e3c, 0x4e40, 0x4e41, 0x4e42, 0x4e44, 0x4e46, 0x4e4a, 0x4e51, 0x4e55, 0x4e57, 0x4e5a, 0x4e5b, 0x4e62, 0x4e63, 0x4e64, 0x4e65, 0x4e67, 0x4e68, 0x4e6a, 0x4e6b, 0x4e6c, 0x4e6d, 0x4e6e, 0x4e6f, 0x4e72, 0x4e74, 0x4e75, 0x4e76, 0x4e77, 0x4e78, 0x4e79, 0x4e7a, 0x4e7b, 0x4e7c, 0x4e7d, 0x4e7f, 0x4e80, 0x4e81, 0x4e82, 0x4e83, 0x4e84, 0x4e85, 0x4e87, 0x4e8a, 0x4e90, 0x4e96, 0x4e97, 0x4e99, 0x4e9c, 0x4e9d, 0x4e9e, 0x4ea3, 0x4eaa, 0x4eaf, 0x4eb0, 0x4eb1, 0x4eb4, 0x4eb6, 0x4eb7, 0x4eb8, 0x4eb9, 0x4ebc, 0x4ebd, 0x4ebe, 0x4ec8, 0x4ecc, 0x4ecf, 0x4ed0, 0x4ed2, 0x4eda, 0x4edb, 0x4edc, 0x4ee0, 0x4ee2, 0x4ee6, 0x4ee7, 0x4ee9, 0x4eed, 0x4eee, 0x4eef, 0x4ef1, 0x4ef4, 0x4ef8, 0x4ef9, 0x4efa, 0x4efc, 0x4efe, 0x4f00, 0x4f02, 0x4f03, 0x4f04, 0x4f05, 0x4f06, 0x4f07, 0x4f08, 0x4f0b, 0x4f0c, 0x4f12, 0x4f13, 0x4f14, 0x4f15, 0x4f16, 0x4f1c, 0x4f1d, 0x4f21, 0x4f23, 0x4f28, 0x4f29, 0x4f2c, 0x4f2d, 0x4f2e, 0x4f31, 0x4f33, 0x4f35, 0x4f37, 0x4f39, 0x4f3b, 0x4f3e, 0x4f3f, 0x4f40, 0x4f41, 0x4f42, 0x4f44, 0x4f45, 0x4f47, 0x4f48, 0x4f49, 0x4f4a, 0x4f4b, 0x4f4c, 0x4f52, 0x4f54, 0x4f56, 0x4f61, 0x4f62, 0x4f66, 0x4f68, 0x4f6a, 0x4f6b, 0x4f6d, 0x4f6e, 0x4f71, 0x4f72, 0x4f75, 0x4f77, 0x4f78, 0x4f79, 0x4f7a, 0x4f7d, 0x4f80, 0x4f81, 0x4f82, 0x4f85, 0x4f86, 0x4f87, 0x4f8a, 0x4f8c, 0x4f8e, 0x4f90, 0x4f92, 0x4f93, 0x4f95, 0x4f96, 0x4f98, 0x4f99, 0x4f9a, 0x4f9c, 0x4f9e, 0x4f9f, 0x4fa1, 0x4fa2, /* 0x82 */ 0x4fa4, 0x4fab, 0x4fad, 0x4fb0, 0x4fb1, 0x4fb2, 0x4fb3, 0x4fb4, 0x4fb6, 0x4fb7, 0x4fb8, 0x4fb9, 0x4fba, 0x4fbb, 0x4fbc, 0x4fbd, 0x4fbe, 0x4fc0, 0x4fc1, 0x4fc2, 0x4fc6, 0x4fc7, 0x4fc8, 0x4fc9, 0x4fcb, 0x4fcc, 0x4fcd, 0x4fd2, 0x4fd3, 0x4fd4, 0x4fd5, 0x4fd6, 0x4fd9, 0x4fdb, 0x4fe0, 0x4fe2, 0x4fe4, 0x4fe5, 0x4fe7, 0x4feb, 0x4fec, 0x4ff0, 0x4ff2, 0x4ff4, 0x4ff5, 0x4ff6, 0x4ff7, 0x4ff9, 0x4ffb, 0x4ffc, 0x4ffd, 0x4fff, 0x5000, 0x5001, 0x5002, 0x5003, 0x5004, 0x5005, 0x5006, 0x5007, 0x5008, 0x5009, 0x500a, 0x500b, 0x500e, 0x5010, 0x5011, 0x5013, 0x5015, 0x5016, 0x5017, 0x501b, 0x501d, 0x501e, 0x5020, 0x5022, 0x5023, 0x5024, 0x5027, 0x502b, 0x502f, 0x5030, 0x5031, 0x5032, 0x5033, 0x5034, 0x5035, 0x5036, 0x5037, 0x5038, 0x5039, 0x503b, 0x503d, 0x503f, 0x5040, 0x5041, 0x5042, 0x5044, 0x5045, 0x5046, 0x5049, 0x504a, 0x504b, 0x504d, 0x5050, 0x5051, 0x5052, 0x5053, 0x5054, 0x5056, 0x5057, 0x5058, 0x5059, 0x505b, 0x505d, 0x505e, 0x505f, 0x5060, 0x5061, 0x5062, 0x5063, 0x5064, 0x5066, 0x5067, 0x5068, 0x5069, 0x506a, 0x506b, 0x506d, 0x506e, 0x506f, 0x5070, 0x5071, 0x5072, 0x5073, 0x5074, 0x5075, 0x5078, 0x5079, 0x507a, 0x507c, 0x507d, 0x5081, 0x5082, 0x5083, 0x5084, 0x5086, 0x5087, 0x5089, 0x508a, 0x508b, 0x508c, 0x508e, 0x508f, 0x5090, 0x5091, 0x5092, 0x5093, 0x5094, 0x5095, 0x5096, 0x5097, 0x5098, 0x5099, 0x509a, 0x509b, 0x509c, 0x509d, 0x509e, 0x509f, 0x50a0, 0x50a1, 0x50a2, 0x50a4, 0x50a6, 0x50aa, 0x50ab, 0x50ad, 0x50ae, 0x50af, 0x50b0, 0x50b1, 0x50b3, 0x50b4, 0x50b5, 0x50b6, 0x50b7, 0x50b8, 0x50b9, 0x50bc, /* 0x83 */ 0x50bd, 0x50be, 0x50bf, 0x50c0, 0x50c1, 0x50c2, 0x50c3, 0x50c4, 0x50c5, 0x50c6, 0x50c7, 0x50c8, 0x50c9, 0x50ca, 0x50cb, 0x50cc, 0x50cd, 0x50ce, 0x50d0, 0x50d1, 0x50d2, 0x50d3, 0x50d4, 0x50d5, 0x50d7, 0x50d8, 0x50d9, 0x50db, 0x50dc, 0x50dd, 0x50de, 0x50df, 0x50e0, 0x50e1, 0x50e2, 0x50e3, 0x50e4, 0x50e5, 0x50e8, 0x50e9, 0x50ea, 0x50eb, 0x50ef, 0x50f0, 0x50f1, 0x50f2, 0x50f4, 0x50f6, 0x50f7, 0x50f8, 0x50f9, 0x50fa, 0x50fc, 0x50fd, 0x50fe, 0x50ff, 0x5100, 0x5101, 0x5102, 0x5103, 0x5104, 0x5105, 0x5108, 0x5109, 0x510a, 0x510c, 0x510d, 0x510e, 0x510f, 0x5110, 0x5111, 0x5113, 0x5114, 0x5115, 0x5116, 0x5117, 0x5118, 0x5119, 0x511a, 0x511b, 0x511c, 0x511d, 0x511e, 0x511f, 0x5120, 0x5122, 0x5123, 0x5124, 0x5125, 0x5126, 0x5127, 0x5128, 0x5129, 0x512a, 0x512b, 0x512c, 0x512d, 0x512e, 0x512f, 0x5130, 0x5131, 0x5132, 0x5133, 0x5134, 0x5135, 0x5136, 0x5137, 0x5138, 0x5139, 0x513a, 0x513b, 0x513c, 0x513d, 0x513e, 0x5142, 0x5147, 0x514a, 0x514c, 0x514e, 0x514f, 0x5150, 0x5152, 0x5153, 0x5157, 0x5158, 0x5159, 0x515b, 0x515d, 0x515e, 0x515f, 0x5160, 0x5161, 0x5163, 0x5164, 0x5166, 0x5167, 0x5169, 0x516a, 0x516f, 0x5172, 0x517a, 0x517e, 0x517f, 0x5183, 0x5184, 0x5186, 0x5187, 0x518a, 0x518b, 0x518e, 0x518f, 0x5190, 0x5191, 0x5193, 0x5194, 0x5198, 0x519a, 0x519d, 0x519e, 0x519f, 0x51a1, 0x51a3, 0x51a6, 0x51a7, 0x51a8, 0x51a9, 0x51aa, 0x51ad, 0x51ae, 0x51b4, 0x51b8, 0x51b9, 0x51ba, 0x51be, 0x51bf, 0x51c1, 0x51c2, 0x51c3, 0x51c5, 0x51c8, 0x51ca, 0x51cd, 0x51ce, 0x51d0, 0x51d2, 0x51d3, 0x51d4, 0x51d5, 0x51d6, 0x51d7, /* 0x84 */ 0x51d8, 0x51d9, 0x51da, 0x51dc, 0x51de, 0x51df, 0x51e2, 0x51e3, 0x51e5, 0x51e6, 0x51e7, 0x51e8, 0x51e9, 0x51ea, 0x51ec, 0x51ee, 0x51f1, 0x51f2, 0x51f4, 0x51f7, 0x51fe, 0x5204, 0x5205, 0x5209, 0x520b, 0x520c, 0x520f, 0x5210, 0x5213, 0x5214, 0x5215, 0x521c, 0x521e, 0x521f, 0x5221, 0x5222, 0x5223, 0x5225, 0x5226, 0x5227, 0x522a, 0x522c, 0x522f, 0x5231, 0x5232, 0x5234, 0x5235, 0x523c, 0x523e, 0x5244, 0x5245, 0x5246, 0x5247, 0x5248, 0x5249, 0x524b, 0x524e, 0x524f, 0x5252, 0x5253, 0x5255, 0x5257, 0x5258, 0x5259, 0x525a, 0x525b, 0x525d, 0x525f, 0x5260, 0x5262, 0x5263, 0x5264, 0x5266, 0x5268, 0x526b, 0x526c, 0x526d, 0x526e, 0x5270, 0x5271, 0x5273, 0x5274, 0x5275, 0x5276, 0x5277, 0x5278, 0x5279, 0x527a, 0x527b, 0x527c, 0x527e, 0x5280, 0x5283, 0x5284, 0x5285, 0x5286, 0x5287, 0x5289, 0x528a, 0x528b, 0x528c, 0x528d, 0x528e, 0x528f, 0x5291, 0x5292, 0x5294, 0x5295, 0x5296, 0x5297, 0x5298, 0x5299, 0x529a, 0x529c, 0x52a4, 0x52a5, 0x52a6, 0x52a7, 0x52ae, 0x52af, 0x52b0, 0x52b4, 0x52b5, 0x52b6, 0x52b7, 0x52b8, 0x52b9, 0x52ba, 0x52bb, 0x52bc, 0x52bd, 0x52c0, 0x52c1, 0x52c2, 0x52c4, 0x52c5, 0x52c6, 0x52c8, 0x52ca, 0x52cc, 0x52cd, 0x52ce, 0x52cf, 0x52d1, 0x52d3, 0x52d4, 0x52d5, 0x52d7, 0x52d9, 0x52da, 0x52db, 0x52dc, 0x52dd, 0x52de, 0x52e0, 0x52e1, 0x52e2, 0x52e3, 0x52e5, 0x52e6, 0x52e7, 0x52e8, 0x52e9, 0x52ea, 0x52eb, 0x52ec, 0x52ed, 0x52ee, 0x52ef, 0x52f1, 0x52f2, 0x52f3, 0x52f4, 0x52f5, 0x52f6, 0x52f7, 0x52f8, 0x52fb, 0x52fc, 0x52fd, 0x5301, 0x5302, 0x5303, 0x5304, 0x5307, 0x5309, 0x530a, 0x530b, 0x530c, 0x530e, /* 0x85 */ 0x5311, 0x5312, 0x5313, 0x5314, 0x5318, 0x531b, 0x531c, 0x531e, 0x531f, 0x5322, 0x5324, 0x5325, 0x5327, 0x5328, 0x5329, 0x532b, 0x532c, 0x532d, 0x532f, 0x5330, 0x5331, 0x5332, 0x5333, 0x5334, 0x5335, 0x5336, 0x5337, 0x5338, 0x533c, 0x533d, 0x5340, 0x5342, 0x5344, 0x5346, 0x534b, 0x534c, 0x534d, 0x5350, 0x5354, 0x5358, 0x5359, 0x535b, 0x535d, 0x5365, 0x5368, 0x536a, 0x536c, 0x536d, 0x5372, 0x5376, 0x5379, 0x537b, 0x537c, 0x537d, 0x537e, 0x5380, 0x5381, 0x5383, 0x5387, 0x5388, 0x538a, 0x538e, 0x538f, 0x5390, 0x5391, 0x5392, 0x5393, 0x5394, 0x5396, 0x5397, 0x5399, 0x539b, 0x539c, 0x539e, 0x53a0, 0x53a1, 0x53a4, 0x53a7, 0x53aa, 0x53ab, 0x53ac, 0x53ad, 0x53af, 0x53b0, 0x53b1, 0x53b2, 0x53b3, 0x53b4, 0x53b5, 0x53b7, 0x53b8, 0x53b9, 0x53ba, 0x53bc, 0x53bd, 0x53be, 0x53c0, 0x53c3, 0x53c4, 0x53c5, 0x53c6, 0x53c7, 0x53ce, 0x53cf, 0x53d0, 0x53d2, 0x53d3, 0x53d5, 0x53da, 0x53dc, 0x53dd, 0x53de, 0x53e1, 0x53e2, 0x53e7, 0x53f4, 0x53fa, 0x53fe, 0x53ff, 0x5400, 0x5402, 0x5405, 0x5407, 0x540b, 0x5414, 0x5418, 0x5419, 0x541a, 0x541c, 0x5422, 0x5424, 0x5425, 0x542a, 0x5430, 0x5433, 0x5436, 0x5437, 0x543a, 0x543d, 0x543f, 0x5441, 0x5442, 0x5444, 0x5445, 0x5447, 0x5449, 0x544c, 0x544d, 0x544e, 0x544f, 0x5451, 0x545a, 0x545d, 0x545e, 0x545f, 0x5460, 0x5461, 0x5463, 0x5465, 0x5467, 0x5469, 0x546a, 0x546b, 0x546c, 0x546d, 0x546e, 0x546f, 0x5470, 0x5474, 0x5479, 0x547a, 0x547e, 0x547f, 0x5481, 0x5483, 0x5485, 0x5487, 0x5488, 0x5489, 0x548a, 0x548d, 0x5491, 0x5493, 0x5497, 0x5498, 0x549c, 0x549e, 0x549f, 0x54a0, 0x54a1, /* 0x86 */ 0x54a2, 0x54a5, 0x54ae, 0x54b0, 0x54b2, 0x54b5, 0x54b6, 0x54b7, 0x54b9, 0x54ba, 0x54bc, 0x54be, 0x54c3, 0x54c5, 0x54ca, 0x54cb, 0x54d6, 0x54d8, 0x54db, 0x54e0, 0x54e1, 0x54e2, 0x54e3, 0x54e4, 0x54eb, 0x54ec, 0x54ef, 0x54f0, 0x54f1, 0x54f4, 0x54f5, 0x54f6, 0x54f7, 0x54f8, 0x54f9, 0x54fb, 0x54fe, 0x5500, 0x5502, 0x5503, 0x5504, 0x5505, 0x5508, 0x550a, 0x550b, 0x550c, 0x550d, 0x550e, 0x5512, 0x5513, 0x5515, 0x5516, 0x5517, 0x5518, 0x5519, 0x551a, 0x551c, 0x551d, 0x551e, 0x551f, 0x5521, 0x5525, 0x5526, 0x5528, 0x5529, 0x552b, 0x552d, 0x5532, 0x5534, 0x5535, 0x5536, 0x5538, 0x5539, 0x553a, 0x553b, 0x553d, 0x5540, 0x5542, 0x5545, 0x5547, 0x5548, 0x554b, 0x554c, 0x554d, 0x554e, 0x554f, 0x5551, 0x5552, 0x5553, 0x5554, 0x5557, 0x5558, 0x5559, 0x555a, 0x555b, 0x555d, 0x555e, 0x555f, 0x5560, 0x5562, 0x5563, 0x5568, 0x5569, 0x556b, 0x556f, 0x5570, 0x5571, 0x5572, 0x5573, 0x5574, 0x5579, 0x557a, 0x557d, 0x557f, 0x5585, 0x5586, 0x558c, 0x558d, 0x558e, 0x5590, 0x5592, 0x5593, 0x5595, 0x5596, 0x5597, 0x559a, 0x559b, 0x559e, 0x55a0, 0x55a1, 0x55a2, 0x55a3, 0x55a4, 0x55a5, 0x55a6, 0x55a8, 0x55a9, 0x55aa, 0x55ab, 0x55ac, 0x55ad, 0x55ae, 0x55af, 0x55b0, 0x55b2, 0x55b4, 0x55b6, 0x55b8, 0x55ba, 0x55bc, 0x55bf, 0x55c0, 0x55c1, 0x55c2, 0x55c3, 0x55c6, 0x55c7, 0x55c8, 0x55ca, 0x55cb, 0x55ce, 0x55cf, 0x55d0, 0x55d5, 0x55d7, 0x55d8, 0x55d9, 0x55da, 0x55db, 0x55de, 0x55e0, 0x55e2, 0x55e7, 0x55e9, 0x55ed, 0x55ee, 0x55f0, 0x55f1, 0x55f4, 0x55f6, 0x55f8, 0x55f9, 0x55fa, 0x55fb, 0x55fc, 0x55ff, 0x5602, 0x5603, 0x5604, 0x5605, /* 0x87 */ 0x5606, 0x5607, 0x560a, 0x560b, 0x560d, 0x5610, 0x5611, 0x5612, 0x5613, 0x5614, 0x5615, 0x5616, 0x5617, 0x5619, 0x561a, 0x561c, 0x561d, 0x5620, 0x5621, 0x5622, 0x5625, 0x5626, 0x5628, 0x5629, 0x562a, 0x562b, 0x562e, 0x562f, 0x5630, 0x5633, 0x5635, 0x5637, 0x5638, 0x563a, 0x563c, 0x563d, 0x563e, 0x5640, 0x5641, 0x5642, 0x5643, 0x5644, 0x5645, 0x5646, 0x5647, 0x5648, 0x5649, 0x564a, 0x564b, 0x564f, 0x5650, 0x5651, 0x5652, 0x5653, 0x5655, 0x5656, 0x565a, 0x565b, 0x565d, 0x565e, 0x565f, 0x5660, 0x5661, 0x5663, 0x5665, 0x5666, 0x5667, 0x566d, 0x566e, 0x566f, 0x5670, 0x5672, 0x5673, 0x5674, 0x5675, 0x5677, 0x5678, 0x5679, 0x567a, 0x567d, 0x567e, 0x567f, 0x5680, 0x5681, 0x5682, 0x5683, 0x5684, 0x5687, 0x5688, 0x5689, 0x568a, 0x568b, 0x568c, 0x568d, 0x5690, 0x5691, 0x5692, 0x5694, 0x5695, 0x5696, 0x5697, 0x5698, 0x5699, 0x569a, 0x569b, 0x569c, 0x569d, 0x569e, 0x569f, 0x56a0, 0x56a1, 0x56a2, 0x56a4, 0x56a5, 0x56a6, 0x56a7, 0x56a8, 0x56a9, 0x56aa, 0x56ab, 0x56ac, 0x56ad, 0x56ae, 0x56b0, 0x56b1, 0x56b2, 0x56b3, 0x56b4, 0x56b5, 0x56b6, 0x56b8, 0x56b9, 0x56ba, 0x56bb, 0x56bd, 0x56be, 0x56bf, 0x56c0, 0x56c1, 0x56c2, 0x56c3, 0x56c4, 0x56c5, 0x56c6, 0x56c7, 0x56c8, 0x56c9, 0x56cb, 0x56cc, 0x56cd, 0x56ce, 0x56cf, 0x56d0, 0x56d1, 0x56d2, 0x56d3, 0x56d5, 0x56d6, 0x56d8, 0x56d9, 0x56dc, 0x56e3, 0x56e5, 0x56e6, 0x56e7, 0x56e8, 0x56e9, 0x56ea, 0x56ec, 0x56ee, 0x56ef, 0x56f2, 0x56f3, 0x56f6, 0x56f7, 0x56f8, 0x56fb, 0x56fc, 0x5700, 0x5701, 0x5702, 0x5705, 0x5707, 0x570b, 0x570c, 0x570d, 0x570e, 0x570f, 0x5710, 0x5711, /* 0x88 */ 0x5712, 0x5713, 0x5714, 0x5715, 0x5716, 0x5717, 0x5718, 0x5719, 0x571a, 0x571b, 0x571d, 0x571e, 0x5720, 0x5721, 0x5722, 0x5724, 0x5725, 0x5726, 0x5727, 0x572b, 0x5731, 0x5732, 0x5734, 0x5735, 0x5736, 0x5737, 0x5738, 0x573c, 0x573d, 0x573f, 0x5741, 0x5743, 0x5744, 0x5745, 0x5746, 0x5748, 0x5749, 0x574b, 0x5752, 0x5753, 0x5754, 0x5755, 0x5756, 0x5758, 0x5759, 0x5762, 0x5763, 0x5765, 0x5767, 0x576c, 0x576e, 0x5770, 0x5771, 0x5772, 0x5774, 0x5775, 0x5778, 0x5779, 0x577a, 0x577d, 0x577e, 0x577f, 0x5780, 0x5781, 0x5787, 0x5788, 0x5789, 0x578a, 0x578d, 0x578e, 0x578f, 0x5790, 0x5791, 0x5794, 0x5795, 0x5796, 0x5797, 0x5798, 0x5799, 0x579a, 0x579c, 0x579d, 0x579e, 0x579f, 0x57a5, 0x57a8, 0x57aa, 0x57ac, 0x57af, 0x57b0, 0x57b1, 0x57b3, 0x57b5, 0x57b6, 0x57b7, 0x57b9, 0x57ba, 0x57bb, 0x57bc, 0x57bd, 0x57be, 0x57bf, 0x57c0, 0x57c1, 0x57c4, 0x57c5, 0x57c6, 0x57c7, 0x57c8, 0x57c9, 0x57ca, 0x57cc, 0x57cd, 0x57d0, 0x57d1, 0x57d3, 0x57d6, 0x57d7, 0x57db, 0x57dc, 0x57de, 0x57e1, 0x57e2, 0x57e3, 0x57e5, 0x57e6, 0x57e7, 0x57e8, 0x57e9, 0x57ea, 0x57eb, 0x57ec, 0x57ee, 0x57f0, 0x57f1, 0x57f2, 0x57f3, 0x57f5, 0x57f6, 0x57f7, 0x57fb, 0x57fc, 0x57fe, 0x57ff, 0x5801, 0x5803, 0x5804, 0x5805, 0x5808, 0x5809, 0x580a, 0x580c, 0x580e, 0x580f, 0x5810, 0x5812, 0x5813, 0x5814, 0x5816, 0x5817, 0x5818, 0x581a, 0x581b, 0x581c, 0x581d, 0x581f, 0x5822, 0x5823, 0x5825, 0x5826, 0x5827, 0x5828, 0x5829, 0x582b, 0x582c, 0x582d, 0x582e, 0x582f, 0x5831, 0x5832, 0x5833, 0x5834, 0x5836, 0x5837, 0x5838, 0x5839, 0x583a, 0x583b, 0x583c, 0x583d, /* 0x89 */ 0x583e, 0x583f, 0x5840, 0x5841, 0x5842, 0x5843, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849, 0x584a, 0x584b, 0x584e, 0x584f, 0x5850, 0x5852, 0x5853, 0x5855, 0x5856, 0x5857, 0x5859, 0x585a, 0x585b, 0x585c, 0x585d, 0x585f, 0x5860, 0x5861, 0x5862, 0x5863, 0x5864, 0x5866, 0x5867, 0x5868, 0x5869, 0x586a, 0x586d, 0x586e, 0x586f, 0x5870, 0x5871, 0x5872, 0x5873, 0x5874, 0x5875, 0x5876, 0x5877, 0x5878, 0x5879, 0x587a, 0x587b, 0x587c, 0x587d, 0x587f, 0x5882, 0x5884, 0x5886, 0x5887, 0x5888, 0x588a, 0x588b, 0x588c, 0x588d, 0x588e, 0x588f, 0x5890, 0x5891, 0x5894, 0x5895, 0x5896, 0x5897, 0x5898, 0x589b, 0x589c, 0x589d, 0x58a0, 0x58a1, 0x58a2, 0x58a3, 0x58a4, 0x58a5, 0x58a6, 0x58a7, 0x58aa, 0x58ab, 0x58ac, 0x58ad, 0x58ae, 0x58af, 0x58b0, 0x58b1, 0x58b2, 0x58b3, 0x58b4, 0x58b5, 0x58b6, 0x58b7, 0x58b8, 0x58b9, 0x58ba, 0x58bb, 0x58bd, 0x58be, 0x58bf, 0x58c0, 0x58c2, 0x58c3, 0x58c4, 0x58c6, 0x58c7, 0x58c8, 0x58c9, 0x58ca, 0x58cb, 0x58cc, 0x58cd, 0x58ce, 0x58cf, 0x58d0, 0x58d2, 0x58d3, 0x58d4, 0x58d6, 0x58d7, 0x58d8, 0x58d9, 0x58da, 0x58db, 0x58dc, 0x58dd, 0x58de, 0x58df, 0x58e0, 0x58e1, 0x58e2, 0x58e3, 0x58e5, 0x58e6, 0x58e7, 0x58e8, 0x58e9, 0x58ea, 0x58ed, 0x58ef, 0x58f1, 0x58f2, 0x58f4, 0x58f5, 0x58f7, 0x58f8, 0x58fa, 0x58fb, 0x58fc, 0x58fd, 0x58fe, 0x58ff, 0x5900, 0x5901, 0x5903, 0x5905, 0x5906, 0x5908, 0x5909, 0x590a, 0x590b, 0x590c, 0x590e, 0x5910, 0x5911, 0x5912, 0x5913, 0x5917, 0x5918, 0x591b, 0x591d, 0x591e, 0x5920, 0x5921, 0x5922, 0x5923, 0x5926, 0x5928, 0x592c, 0x5930, 0x5932, 0x5933, 0x5935, 0x5936, 0x593b, /* 0x8a */ 0x593d, 0x593e, 0x593f, 0x5940, 0x5943, 0x5945, 0x5946, 0x594a, 0x594c, 0x594d, 0x5950, 0x5952, 0x5953, 0x5959, 0x595b, 0x595c, 0x595d, 0x595e, 0x595f, 0x5961, 0x5963, 0x5964, 0x5966, 0x5967, 0x5968, 0x5969, 0x596a, 0x596b, 0x596c, 0x596d, 0x596e, 0x596f, 0x5970, 0x5971, 0x5972, 0x5975, 0x5977, 0x597a, 0x597b, 0x597c, 0x597e, 0x597f, 0x5980, 0x5985, 0x5989, 0x598b, 0x598c, 0x598e, 0x598f, 0x5990, 0x5991, 0x5994, 0x5995, 0x5998, 0x599a, 0x599b, 0x599c, 0x599d, 0x599f, 0x59a0, 0x59a1, 0x59a2, 0x59a6, 0x59a7, 0x59ac, 0x59ad, 0x59b0, 0x59b1, 0x59b3, 0x59b4, 0x59b5, 0x59b6, 0x59b7, 0x59b8, 0x59ba, 0x59bc, 0x59bd, 0x59bf, 0x59c0, 0x59c1, 0x59c2, 0x59c3, 0x59c4, 0x59c5, 0x59c7, 0x59c8, 0x59c9, 0x59cc, 0x59cd, 0x59ce, 0x59cf, 0x59d5, 0x59d6, 0x59d9, 0x59db, 0x59de, 0x59df, 0x59e0, 0x59e1, 0x59e2, 0x59e4, 0x59e6, 0x59e7, 0x59e9, 0x59ea, 0x59eb, 0x59ed, 0x59ee, 0x59ef, 0x59f0, 0x59f1, 0x59f2, 0x59f3, 0x59f4, 0x59f5, 0x59f6, 0x59f7, 0x59f8, 0x59fa, 0x59fc, 0x59fd, 0x59fe, 0x5a00, 0x5a02, 0x5a0a, 0x5a0b, 0x5a0d, 0x5a0e, 0x5a0f, 0x5a10, 0x5a12, 0x5a14, 0x5a15, 0x5a16, 0x5a17, 0x5a19, 0x5a1a, 0x5a1b, 0x5a1d, 0x5a1e, 0x5a21, 0x5a22, 0x5a24, 0x5a26, 0x5a27, 0x5a28, 0x5a2a, 0x5a2b, 0x5a2c, 0x5a2d, 0x5a2e, 0x5a2f, 0x5a30, 0x5a33, 0x5a35, 0x5a37, 0x5a38, 0x5a39, 0x5a3a, 0x5a3b, 0x5a3d, 0x5a3e, 0x5a3f, 0x5a41, 0x5a42, 0x5a43, 0x5a44, 0x5a45, 0x5a47, 0x5a48, 0x5a4b, 0x5a4c, 0x5a4d, 0x5a4e, 0x5a4f, 0x5a50, 0x5a51, 0x5a52, 0x5a53, 0x5a54, 0x5a56, 0x5a57, 0x5a58, 0x5a59, 0x5a5b, 0x5a5c, 0x5a5d, 0x5a5e, 0x5a5f, 0x5a60, /* 0x8b */ 0x5a61, 0x5a63, 0x5a64, 0x5a65, 0x5a66, 0x5a68, 0x5a69, 0x5a6b, 0x5a6c, 0x5a6d, 0x5a6e, 0x5a6f, 0x5a70, 0x5a71, 0x5a72, 0x5a73, 0x5a78, 0x5a79, 0x5a7b, 0x5a7c, 0x5a7d, 0x5a7e, 0x5a80, 0x5a81, 0x5a82, 0x5a83, 0x5a84, 0x5a85, 0x5a86, 0x5a87, 0x5a88, 0x5a89, 0x5a8a, 0x5a8b, 0x5a8c, 0x5a8d, 0x5a8e, 0x5a8f, 0x5a90, 0x5a91, 0x5a93, 0x5a94, 0x5a95, 0x5a96, 0x5a97, 0x5a98, 0x5a99, 0x5a9c, 0x5a9d, 0x5a9e, 0x5a9f, 0x5aa0, 0x5aa1, 0x5aa2, 0x5aa3, 0x5aa4, 0x5aa5, 0x5aa6, 0x5aa7, 0x5aa8, 0x5aa9, 0x5aab, 0x5aac, 0x5aad, 0x5aae, 0x5aaf, 0x5ab0, 0x5ab1, 0x5ab4, 0x5ab6, 0x5ab7, 0x5ab9, 0x5aba, 0x5abb, 0x5abc, 0x5abd, 0x5abf, 0x5ac0, 0x5ac3, 0x5ac4, 0x5ac5, 0x5ac6, 0x5ac7, 0x5ac8, 0x5aca, 0x5acb, 0x5acd, 0x5ace, 0x5acf, 0x5ad0, 0x5ad1, 0x5ad3, 0x5ad5, 0x5ad7, 0x5ad9, 0x5ada, 0x5adb, 0x5add, 0x5ade, 0x5adf, 0x5ae2, 0x5ae4, 0x5ae5, 0x5ae7, 0x5ae8, 0x5aea, 0x5aec, 0x5aed, 0x5aee, 0x5aef, 0x5af0, 0x5af2, 0x5af3, 0x5af4, 0x5af5, 0x5af6, 0x5af7, 0x5af8, 0x5af9, 0x5afa, 0x5afb, 0x5afc, 0x5afd, 0x5afe, 0x5aff, 0x5b00, 0x5b01, 0x5b02, 0x5b03, 0x5b04, 0x5b05, 0x5b06, 0x5b07, 0x5b08, 0x5b0a, 0x5b0b, 0x5b0c, 0x5b0d, 0x5b0e, 0x5b0f, 0x5b10, 0x5b11, 0x5b12, 0x5b13, 0x5b14, 0x5b15, 0x5b18, 0x5b19, 0x5b1a, 0x5b1b, 0x5b1c, 0x5b1d, 0x5b1e, 0x5b1f, 0x5b20, 0x5b21, 0x5b22, 0x5b23, 0x5b24, 0x5b25, 0x5b26, 0x5b27, 0x5b28, 0x5b29, 0x5b2a, 0x5b2b, 0x5b2c, 0x5b2d, 0x5b2e, 0x5b2f, 0x5b30, 0x5b31, 0x5b33, 0x5b35, 0x5b36, 0x5b38, 0x5b39, 0x5b3a, 0x5b3b, 0x5b3c, 0x5b3d, 0x5b3e, 0x5b3f, 0x5b41, 0x5b42, 0x5b43, 0x5b44, 0x5b45, 0x5b46, 0x5b47, /* 0x8c */ 0x5b48, 0x5b49, 0x5b4a, 0x5b4b, 0x5b4c, 0x5b4d, 0x5b4e, 0x5b4f, 0x5b52, 0x5b56, 0x5b5e, 0x5b60, 0x5b61, 0x5b67, 0x5b68, 0x5b6b, 0x5b6d, 0x5b6e, 0x5b6f, 0x5b72, 0x5b74, 0x5b76, 0x5b77, 0x5b78, 0x5b79, 0x5b7b, 0x5b7c, 0x5b7e, 0x5b7f, 0x5b82, 0x5b86, 0x5b8a, 0x5b8d, 0x5b8e, 0x5b90, 0x5b91, 0x5b92, 0x5b94, 0x5b96, 0x5b9f, 0x5ba7, 0x5ba8, 0x5ba9, 0x5bac, 0x5bad, 0x5bae, 0x5baf, 0x5bb1, 0x5bb2, 0x5bb7, 0x5bba, 0x5bbb, 0x5bbc, 0x5bc0, 0x5bc1, 0x5bc3, 0x5bc8, 0x5bc9, 0x5bca, 0x5bcb, 0x5bcd, 0x5bce, 0x5bcf, 0x5bd1, 0x5bd4, 0x5bd5, 0x5bd6, 0x5bd7, 0x5bd8, 0x5bd9, 0x5bda, 0x5bdb, 0x5bdc, 0x5be0, 0x5be2, 0x5be3, 0x5be6, 0x5be7, 0x5be9, 0x5bea, 0x5beb, 0x5bec, 0x5bed, 0x5bef, 0x5bf1, 0x5bf2, 0x5bf3, 0x5bf4, 0x5bf5, 0x5bf6, 0x5bf7, 0x5bfd, 0x5bfe, 0x5c00, 0x5c02, 0x5c03, 0x5c05, 0x5c07, 0x5c08, 0x5c0b, 0x5c0c, 0x5c0d, 0x5c0e, 0x5c10, 0x5c12, 0x5c13, 0x5c17, 0x5c19, 0x5c1b, 0x5c1e, 0x5c1f, 0x5c20, 0x5c21, 0x5c23, 0x5c26, 0x5c28, 0x5c29, 0x5c2a, 0x5c2b, 0x5c2d, 0x5c2e, 0x5c2f, 0x5c30, 0x5c32, 0x5c33, 0x5c35, 0x5c36, 0x5c37, 0x5c43, 0x5c44, 0x5c46, 0x5c47, 0x5c4c, 0x5c4d, 0x5c52, 0x5c53, 0x5c54, 0x5c56, 0x5c57, 0x5c58, 0x5c5a, 0x5c5b, 0x5c5c, 0x5c5d, 0x5c5f, 0x5c62, 0x5c64, 0x5c67, 0x5c68, 0x5c69, 0x5c6a, 0x5c6b, 0x5c6c, 0x5c6d, 0x5c70, 0x5c72, 0x5c73, 0x5c74, 0x5c75, 0x5c76, 0x5c77, 0x5c78, 0x5c7b, 0x5c7c, 0x5c7d, 0x5c7e, 0x5c80, 0x5c83, 0x5c84, 0x5c85, 0x5c86, 0x5c87, 0x5c89, 0x5c8a, 0x5c8b, 0x5c8e, 0x5c8f, 0x5c92, 0x5c93, 0x5c95, 0x5c9d, 0x5c9e, 0x5c9f, 0x5ca0, 0x5ca1, 0x5ca4, 0x5ca5, 0x5ca6, 0x5ca7, 0x5ca8, /* 0x8d */ 0x5caa, 0x5cae, 0x5caf, 0x5cb0, 0x5cb2, 0x5cb4, 0x5cb6, 0x5cb9, 0x5cba, 0x5cbb, 0x5cbc, 0x5cbe, 0x5cc0, 0x5cc2, 0x5cc3, 0x5cc5, 0x5cc6, 0x5cc7, 0x5cc8, 0x5cc9, 0x5cca, 0x5ccc, 0x5ccd, 0x5cce, 0x5ccf, 0x5cd0, 0x5cd1, 0x5cd3, 0x5cd4, 0x5cd5, 0x5cd6, 0x5cd7, 0x5cd8, 0x5cda, 0x5cdb, 0x5cdc, 0x5cdd, 0x5cde, 0x5cdf, 0x5ce0, 0x5ce2, 0x5ce3, 0x5ce7, 0x5ce9, 0x5ceb, 0x5cec, 0x5cee, 0x5cef, 0x5cf1, 0x5cf2, 0x5cf3, 0x5cf4, 0x5cf5, 0x5cf6, 0x5cf7, 0x5cf8, 0x5cf9, 0x5cfa, 0x5cfc, 0x5cfd, 0x5cfe, 0x5cff, 0x5d00, 0x5d01, 0x5d04, 0x5d05, 0x5d08, 0x5d09, 0x5d0a, 0x5d0b, 0x5d0c, 0x5d0d, 0x5d0f, 0x5d10, 0x5d11, 0x5d12, 0x5d13, 0x5d15, 0x5d17, 0x5d18, 0x5d19, 0x5d1a, 0x5d1c, 0x5d1d, 0x5d1f, 0x5d20, 0x5d21, 0x5d22, 0x5d23, 0x5d25, 0x5d28, 0x5d2a, 0x5d2b, 0x5d2c, 0x5d2f, 0x5d30, 0x5d31, 0x5d32, 0x5d33, 0x5d35, 0x5d36, 0x5d37, 0x5d38, 0x5d39, 0x5d3a, 0x5d3b, 0x5d3c, 0x5d3f, 0x5d40, 0x5d41, 0x5d42, 0x5d43, 0x5d44, 0x5d45, 0x5d46, 0x5d48, 0x5d49, 0x5d4d, 0x5d4e, 0x5d4f, 0x5d50, 0x5d51, 0x5d52, 0x5d53, 0x5d54, 0x5d55, 0x5d56, 0x5d57, 0x5d59, 0x5d5a, 0x5d5c, 0x5d5e, 0x5d5f, 0x5d60, 0x5d61, 0x5d62, 0x5d63, 0x5d64, 0x5d65, 0x5d66, 0x5d67, 0x5d68, 0x5d6a, 0x5d6d, 0x5d6e, 0x5d70, 0x5d71, 0x5d72, 0x5d73, 0x5d75, 0x5d76, 0x5d77, 0x5d78, 0x5d79, 0x5d7a, 0x5d7b, 0x5d7c, 0x5d7d, 0x5d7e, 0x5d7f, 0x5d80, 0x5d81, 0x5d83, 0x5d84, 0x5d85, 0x5d86, 0x5d87, 0x5d88, 0x5d89, 0x5d8a, 0x5d8b, 0x5d8c, 0x5d8d, 0x5d8e, 0x5d8f, 0x5d90, 0x5d91, 0x5d92, 0x5d93, 0x5d94, 0x5d95, 0x5d96, 0x5d97, 0x5d98, 0x5d9a, 0x5d9b, 0x5d9c, 0x5d9e, 0x5d9f, 0x5da0, /* 0x8e */ 0x5da1, 0x5da2, 0x5da3, 0x5da4, 0x5da5, 0x5da6, 0x5da7, 0x5da8, 0x5da9, 0x5daa, 0x5dab, 0x5dac, 0x5dad, 0x5dae, 0x5daf, 0x5db0, 0x5db1, 0x5db2, 0x5db3, 0x5db4, 0x5db5, 0x5db6, 0x5db8, 0x5db9, 0x5dba, 0x5dbb, 0x5dbc, 0x5dbd, 0x5dbe, 0x5dbf, 0x5dc0, 0x5dc1, 0x5dc2, 0x5dc3, 0x5dc4, 0x5dc6, 0x5dc7, 0x5dc8, 0x5dc9, 0x5dca, 0x5dcb, 0x5dcc, 0x5dce, 0x5dcf, 0x5dd0, 0x5dd1, 0x5dd2, 0x5dd3, 0x5dd4, 0x5dd5, 0x5dd6, 0x5dd7, 0x5dd8, 0x5dd9, 0x5dda, 0x5ddc, 0x5ddf, 0x5de0, 0x5de3, 0x5de4, 0x5dea, 0x5dec, 0x5ded, 0x5df0, 0x5df5, 0x5df6, 0x5df8, 0x5df9, 0x5dfa, 0x5dfb, 0x5dfc, 0x5dff, 0x5e00, 0x5e04, 0x5e07, 0x5e09, 0x5e0a, 0x5e0b, 0x5e0d, 0x5e0e, 0x5e12, 0x5e13, 0x5e17, 0x5e1e, 0x5e1f, 0x5e20, 0x5e21, 0x5e22, 0x5e23, 0x5e24, 0x5e25, 0x5e28, 0x5e29, 0x5e2a, 0x5e2b, 0x5e2c, 0x5e2f, 0x5e30, 0x5e32, 0x5e33, 0x5e34, 0x5e35, 0x5e36, 0x5e39, 0x5e3a, 0x5e3e, 0x5e3f, 0x5e40, 0x5e41, 0x5e43, 0x5e46, 0x5e47, 0x5e48, 0x5e49, 0x5e4a, 0x5e4b, 0x5e4d, 0x5e4e, 0x5e4f, 0x5e50, 0x5e51, 0x5e52, 0x5e53, 0x5e56, 0x5e57, 0x5e58, 0x5e59, 0x5e5a, 0x5e5c, 0x5e5d, 0x5e5f, 0x5e60, 0x5e63, 0x5e64, 0x5e65, 0x5e66, 0x5e67, 0x5e68, 0x5e69, 0x5e6a, 0x5e6b, 0x5e6c, 0x5e6d, 0x5e6e, 0x5e6f, 0x5e70, 0x5e71, 0x5e75, 0x5e77, 0x5e79, 0x5e7e, 0x5e81, 0x5e82, 0x5e83, 0x5e85, 0x5e88, 0x5e89, 0x5e8c, 0x5e8d, 0x5e8e, 0x5e92, 0x5e98, 0x5e9b, 0x5e9d, 0x5ea1, 0x5ea2, 0x5ea3, 0x5ea4, 0x5ea8, 0x5ea9, 0x5eaa, 0x5eab, 0x5eac, 0x5eae, 0x5eaf, 0x5eb0, 0x5eb1, 0x5eb2, 0x5eb4, 0x5eba, 0x5ebb, 0x5ebc, 0x5ebd, 0x5ebf, 0x5ec0, 0x5ec1, 0x5ec2, 0x5ec3, 0x5ec4, 0x5ec5, /* 0x8f */ 0x5ec6, 0x5ec7, 0x5ec8, 0x5ecb, 0x5ecc, 0x5ecd, 0x5ece, 0x5ecf, 0x5ed0, 0x5ed4, 0x5ed5, 0x5ed7, 0x5ed8, 0x5ed9, 0x5eda, 0x5edc, 0x5edd, 0x5ede, 0x5edf, 0x5ee0, 0x5ee1, 0x5ee2, 0x5ee3, 0x5ee4, 0x5ee5, 0x5ee6, 0x5ee7, 0x5ee9, 0x5eeb, 0x5eec, 0x5eed, 0x5eee, 0x5eef, 0x5ef0, 0x5ef1, 0x5ef2, 0x5ef3, 0x5ef5, 0x5ef8, 0x5ef9, 0x5efb, 0x5efc, 0x5efd, 0x5f05, 0x5f06, 0x5f07, 0x5f09, 0x5f0c, 0x5f0d, 0x5f0e, 0x5f10, 0x5f12, 0x5f14, 0x5f16, 0x5f19, 0x5f1a, 0x5f1c, 0x5f1d, 0x5f1e, 0x5f21, 0x5f22, 0x5f23, 0x5f24, 0x5f28, 0x5f2b, 0x5f2c, 0x5f2e, 0x5f30, 0x5f32, 0x5f33, 0x5f34, 0x5f35, 0x5f36, 0x5f37, 0x5f38, 0x5f3b, 0x5f3d, 0x5f3e, 0x5f3f, 0x5f41, 0x5f42, 0x5f43, 0x5f44, 0x5f45, 0x5f46, 0x5f47, 0x5f48, 0x5f49, 0x5f4a, 0x5f4b, 0x5f4c, 0x5f4d, 0x5f4e, 0x5f4f, 0x5f51, 0x5f54, 0x5f59, 0x5f5a, 0x5f5b, 0x5f5c, 0x5f5e, 0x5f5f, 0x5f60, 0x5f63, 0x5f65, 0x5f67, 0x5f68, 0x5f6b, 0x5f6e, 0x5f6f, 0x5f72, 0x5f74, 0x5f75, 0x5f76, 0x5f78, 0x5f7a, 0x5f7d, 0x5f7e, 0x5f7f, 0x5f83, 0x5f86, 0x5f8d, 0x5f8e, 0x5f8f, 0x5f91, 0x5f93, 0x5f94, 0x5f96, 0x5f9a, 0x5f9b, 0x5f9d, 0x5f9e, 0x5f9f, 0x5fa0, 0x5fa2, 0x5fa3, 0x5fa4, 0x5fa5, 0x5fa6, 0x5fa7, 0x5fa9, 0x5fab, 0x5fac, 0x5faf, 0x5fb0, 0x5fb1, 0x5fb2, 0x5fb3, 0x5fb4, 0x5fb6, 0x5fb8, 0x5fb9, 0x5fba, 0x5fbb, 0x5fbe, 0x5fbf, 0x5fc0, 0x5fc1, 0x5fc2, 0x5fc7, 0x5fc8, 0x5fca, 0x5fcb, 0x5fce, 0x5fd3, 0x5fd4, 0x5fd5, 0x5fda, 0x5fdb, 0x5fdc, 0x5fde, 0x5fdf, 0x5fe2, 0x5fe3, 0x5fe5, 0x5fe6, 0x5fe8, 0x5fe9, 0x5fec, 0x5fef, 0x5ff0, 0x5ff2, 0x5ff3, 0x5ff4, 0x5ff6, 0x5ff7, 0x5ff9, 0x5ffa, 0x5ffc, 0x6007, /* 0x90 */ 0x6008, 0x6009, 0x600b, 0x600c, 0x6010, 0x6011, 0x6013, 0x6017, 0x6018, 0x601a, 0x601e, 0x601f, 0x6022, 0x6023, 0x6024, 0x602c, 0x602d, 0x602e, 0x6030, 0x6031, 0x6032, 0x6033, 0x6034, 0x6036, 0x6037, 0x6038, 0x6039, 0x603a, 0x603d, 0x603e, 0x6040, 0x6044, 0x6045, 0x6046, 0x6047, 0x6048, 0x6049, 0x604a, 0x604c, 0x604e, 0x604f, 0x6051, 0x6053, 0x6054, 0x6056, 0x6057, 0x6058, 0x605b, 0x605c, 0x605e, 0x605f, 0x6060, 0x6061, 0x6065, 0x6066, 0x606e, 0x6071, 0x6072, 0x6074, 0x6075, 0x6077, 0x607e, 0x6080, 0x6081, 0x6082, 0x6085, 0x6086, 0x6087, 0x6088, 0x608a, 0x608b, 0x608e, 0x608f, 0x6090, 0x6091, 0x6093, 0x6095, 0x6097, 0x6098, 0x6099, 0x609c, 0x609e, 0x60a1, 0x60a2, 0x60a4, 0x60a5, 0x60a7, 0x60a9, 0x60aa, 0x60ae, 0x60b0, 0x60b3, 0x60b5, 0x60b6, 0x60b7, 0x60b9, 0x60ba, 0x60bd, 0x60be, 0x60bf, 0x60c0, 0x60c1, 0x60c2, 0x60c3, 0x60c4, 0x60c7, 0x60c8, 0x60c9, 0x60cc, 0x60cd, 0x60ce, 0x60cf, 0x60d0, 0x60d2, 0x60d3, 0x60d4, 0x60d6, 0x60d7, 0x60d9, 0x60db, 0x60de, 0x60e1, 0x60e2, 0x60e3, 0x60e4, 0x60e5, 0x60ea, 0x60f1, 0x60f2, 0x60f5, 0x60f7, 0x60f8, 0x60fb, 0x60fc, 0x60fd, 0x60fe, 0x60ff, 0x6102, 0x6103, 0x6104, 0x6105, 0x6107, 0x610a, 0x610b, 0x610c, 0x6110, 0x6111, 0x6112, 0x6113, 0x6114, 0x6116, 0x6117, 0x6118, 0x6119, 0x611b, 0x611c, 0x611d, 0x611e, 0x6121, 0x6122, 0x6125, 0x6128, 0x6129, 0x612a, 0x612c, 0x612d, 0x612e, 0x612f, 0x6130, 0x6131, 0x6132, 0x6133, 0x6134, 0x6135, 0x6136, 0x6137, 0x6138, 0x6139, 0x613a, 0x613b, 0x613c, 0x613d, 0x613e, 0x6140, 0x6141, 0x6142, 0x6143, 0x6144, 0x6145, 0x6146, /* 0x91 */ 0x6147, 0x6149, 0x614b, 0x614d, 0x614f, 0x6150, 0x6152, 0x6153, 0x6154, 0x6156, 0x6157, 0x6158, 0x6159, 0x615a, 0x615b, 0x615c, 0x615e, 0x615f, 0x6160, 0x6161, 0x6163, 0x6164, 0x6165, 0x6166, 0x6169, 0x616a, 0x616b, 0x616c, 0x616d, 0x616e, 0x616f, 0x6171, 0x6172, 0x6173, 0x6174, 0x6176, 0x6178, 0x6179, 0x617a, 0x617b, 0x617c, 0x617d, 0x617e, 0x617f, 0x6180, 0x6181, 0x6182, 0x6183, 0x6184, 0x6185, 0x6186, 0x6187, 0x6188, 0x6189, 0x618a, 0x618c, 0x618d, 0x618f, 0x6190, 0x6191, 0x6192, 0x6193, 0x6195, 0x6196, 0x6197, 0x6198, 0x6199, 0x619a, 0x619b, 0x619c, 0x619e, 0x619f, 0x61a0, 0x61a1, 0x61a2, 0x61a3, 0x61a4, 0x61a5, 0x61a6, 0x61aa, 0x61ab, 0x61ad, 0x61ae, 0x61af, 0x61b0, 0x61b1, 0x61b2, 0x61b3, 0x61b4, 0x61b5, 0x61b6, 0x61b8, 0x61b9, 0x61ba, 0x61bb, 0x61bc, 0x61bd, 0x61bf, 0x61c0, 0x61c1, 0x61c3, 0x61c4, 0x61c5, 0x61c6, 0x61c7, 0x61c9, 0x61cc, 0x61cd, 0x61ce, 0x61cf, 0x61d0, 0x61d3, 0x61d5, 0x61d6, 0x61d7, 0x61d8, 0x61d9, 0x61da, 0x61db, 0x61dc, 0x61dd, 0x61de, 0x61df, 0x61e0, 0x61e1, 0x61e2, 0x61e3, 0x61e4, 0x61e5, 0x61e7, 0x61e8, 0x61e9, 0x61ea, 0x61eb, 0x61ec, 0x61ed, 0x61ee, 0x61ef, 0x61f0, 0x61f1, 0x61f2, 0x61f3, 0x61f4, 0x61f6, 0x61f7, 0x61f8, 0x61f9, 0x61fa, 0x61fb, 0x61fc, 0x61fd, 0x61fe, 0x6200, 0x6201, 0x6202, 0x6203, 0x6204, 0x6205, 0x6207, 0x6209, 0x6213, 0x6214, 0x6219, 0x621c, 0x621d, 0x621e, 0x6220, 0x6223, 0x6226, 0x6227, 0x6228, 0x6229, 0x622b, 0x622d, 0x622f, 0x6230, 0x6231, 0x6232, 0x6235, 0x6236, 0x6238, 0x6239, 0x623a, 0x623b, 0x623c, 0x6242, 0x6244, 0x6245, 0x6246, 0x624a, /* 0x92 */ 0x624f, 0x6250, 0x6255, 0x6256, 0x6257, 0x6259, 0x625a, 0x625c, 0x625d, 0x625e, 0x625f, 0x6260, 0x6261, 0x6262, 0x6264, 0x6265, 0x6268, 0x6271, 0x6272, 0x6274, 0x6275, 0x6277, 0x6278, 0x627a, 0x627b, 0x627d, 0x6281, 0x6282, 0x6283, 0x6285, 0x6286, 0x6287, 0x6288, 0x628b, 0x628c, 0x628d, 0x628e, 0x628f, 0x6290, 0x6294, 0x6299, 0x629c, 0x629d, 0x629e, 0x62a3, 0x62a6, 0x62a7, 0x62a9, 0x62aa, 0x62ad, 0x62ae, 0x62af, 0x62b0, 0x62b2, 0x62b3, 0x62b4, 0x62b6, 0x62b7, 0x62b8, 0x62ba, 0x62be, 0x62c0, 0x62c1, 0x62c3, 0x62cb, 0x62cf, 0x62d1, 0x62d5, 0x62dd, 0x62de, 0x62e0, 0x62e1, 0x62e4, 0x62ea, 0x62eb, 0x62f0, 0x62f2, 0x62f5, 0x62f8, 0x62f9, 0x62fa, 0x62fb, 0x6300, 0x6303, 0x6304, 0x6305, 0x6306, 0x630a, 0x630b, 0x630c, 0x630d, 0x630f, 0x6310, 0x6312, 0x6313, 0x6314, 0x6315, 0x6317, 0x6318, 0x6319, 0x631c, 0x6326, 0x6327, 0x6329, 0x632c, 0x632d, 0x632e, 0x6330, 0x6331, 0x6333, 0x6334, 0x6335, 0x6336, 0x6337, 0x6338, 0x633b, 0x633c, 0x633e, 0x633f, 0x6340, 0x6341, 0x6344, 0x6347, 0x6348, 0x634a, 0x6351, 0x6352, 0x6353, 0x6354, 0x6356, 0x6357, 0x6358, 0x6359, 0x635a, 0x635b, 0x635c, 0x635d, 0x6360, 0x6364, 0x6365, 0x6366, 0x6368, 0x636a, 0x636b, 0x636c, 0x636f, 0x6370, 0x6372, 0x6373, 0x6374, 0x6375, 0x6378, 0x6379, 0x637c, 0x637d, 0x637e, 0x637f, 0x6381, 0x6383, 0x6384, 0x6385, 0x6386, 0x638b, 0x638d, 0x6391, 0x6393, 0x6394, 0x6395, 0x6397, 0x6399, 0x639a, 0x639b, 0x639c, 0x639d, 0x639e, 0x639f, 0x63a1, 0x63a4, 0x63a6, 0x63ab, 0x63af, 0x63b1, 0x63b2, 0x63b5, 0x63b6, 0x63b9, 0x63bb, 0x63bd, 0x63bf, 0x63c0, /* 0x93 */ 0x63c1, 0x63c2, 0x63c3, 0x63c5, 0x63c7, 0x63c8, 0x63ca, 0x63cb, 0x63cc, 0x63d1, 0x63d3, 0x63d4, 0x63d5, 0x63d7, 0x63d8, 0x63d9, 0x63da, 0x63db, 0x63dc, 0x63dd, 0x63df, 0x63e2, 0x63e4, 0x63e5, 0x63e6, 0x63e7, 0x63e8, 0x63eb, 0x63ec, 0x63ee, 0x63ef, 0x63f0, 0x63f1, 0x63f3, 0x63f5, 0x63f7, 0x63f9, 0x63fa, 0x63fb, 0x63fc, 0x63fe, 0x6403, 0x6404, 0x6406, 0x6407, 0x6408, 0x6409, 0x640a, 0x640d, 0x640e, 0x6411, 0x6412, 0x6415, 0x6416, 0x6417, 0x6418, 0x6419, 0x641a, 0x641d, 0x641f, 0x6422, 0x6423, 0x6424, 0x6425, 0x6427, 0x6428, 0x6429, 0x642b, 0x642e, 0x642f, 0x6430, 0x6431, 0x6432, 0x6433, 0x6435, 0x6436, 0x6437, 0x6438, 0x6439, 0x643b, 0x643c, 0x643e, 0x6440, 0x6442, 0x6443, 0x6449, 0x644b, 0x644c, 0x644d, 0x644e, 0x644f, 0x6450, 0x6451, 0x6453, 0x6455, 0x6456, 0x6457, 0x6459, 0x645a, 0x645b, 0x645c, 0x645d, 0x645f, 0x6460, 0x6461, 0x6462, 0x6463, 0x6464, 0x6465, 0x6466, 0x6468, 0x646a, 0x646b, 0x646c, 0x646e, 0x646f, 0x6470, 0x6471, 0x6472, 0x6473, 0x6474, 0x6475, 0x6476, 0x6477, 0x647b, 0x647c, 0x647d, 0x647e, 0x647f, 0x6480, 0x6481, 0x6483, 0x6486, 0x6488, 0x6489, 0x648a, 0x648b, 0x648c, 0x648d, 0x648e, 0x648f, 0x6490, 0x6493, 0x6494, 0x6497, 0x6498, 0x649a, 0x649b, 0x649c, 0x649d, 0x649f, 0x64a0, 0x64a1, 0x64a2, 0x64a3, 0x64a5, 0x64a6, 0x64a7, 0x64a8, 0x64aa, 0x64ab, 0x64af, 0x64b1, 0x64b2, 0x64b3, 0x64b4, 0x64b6, 0x64b9, 0x64bb, 0x64bd, 0x64be, 0x64bf, 0x64c1, 0x64c3, 0x64c4, 0x64c6, 0x64c7, 0x64c8, 0x64c9, 0x64ca, 0x64cb, 0x64cc, 0x64cf, 0x64d1, 0x64d3, 0x64d4, 0x64d5, 0x64d6, 0x64d9, 0x64da, /* 0x94 */ 0x64db, 0x64dc, 0x64dd, 0x64df, 0x64e0, 0x64e1, 0x64e3, 0x64e5, 0x64e7, 0x64e8, 0x64e9, 0x64ea, 0x64eb, 0x64ec, 0x64ed, 0x64ee, 0x64ef, 0x64f0, 0x64f1, 0x64f2, 0x64f3, 0x64f4, 0x64f5, 0x64f6, 0x64f7, 0x64f8, 0x64f9, 0x64fa, 0x64fb, 0x64fc, 0x64fd, 0x64fe, 0x64ff, 0x6501, 0x6502, 0x6503, 0x6504, 0x6505, 0x6506, 0x6507, 0x6508, 0x650a, 0x650b, 0x650c, 0x650d, 0x650e, 0x650f, 0x6510, 0x6511, 0x6513, 0x6514, 0x6515, 0x6516, 0x6517, 0x6519, 0x651a, 0x651b, 0x651c, 0x651d, 0x651e, 0x651f, 0x6520, 0x6521, 0x6522, 0x6523, 0x6524, 0x6526, 0x6527, 0x6528, 0x6529, 0x652a, 0x652c, 0x652d, 0x6530, 0x6531, 0x6532, 0x6533, 0x6537, 0x653a, 0x653c, 0x653d, 0x6540, 0x6541, 0x6542, 0x6543, 0x6544, 0x6546, 0x6547, 0x654a, 0x654b, 0x654d, 0x654e, 0x6550, 0x6552, 0x6553, 0x6554, 0x6557, 0x6558, 0x655a, 0x655c, 0x655f, 0x6560, 0x6561, 0x6564, 0x6565, 0x6567, 0x6568, 0x6569, 0x656a, 0x656d, 0x656e, 0x656f, 0x6571, 0x6573, 0x6575, 0x6576, 0x6578, 0x6579, 0x657a, 0x657b, 0x657c, 0x657d, 0x657e, 0x657f, 0x6580, 0x6581, 0x6582, 0x6583, 0x6584, 0x6585, 0x6586, 0x6588, 0x6589, 0x658a, 0x658d, 0x658e, 0x658f, 0x6592, 0x6594, 0x6595, 0x6596, 0x6598, 0x659a, 0x659d, 0x659e, 0x65a0, 0x65a2, 0x65a3, 0x65a6, 0x65a8, 0x65aa, 0x65ac, 0x65ae, 0x65b1, 0x65b2, 0x65b3, 0x65b4, 0x65b5, 0x65b6, 0x65b7, 0x65b8, 0x65ba, 0x65bb, 0x65be, 0x65bf, 0x65c0, 0x65c2, 0x65c7, 0x65c8, 0x65c9, 0x65ca, 0x65cd, 0x65d0, 0x65d1, 0x65d3, 0x65d4, 0x65d5, 0x65d8, 0x65d9, 0x65da, 0x65db, 0x65dc, 0x65dd, 0x65de, 0x65df, 0x65e1, 0x65e3, 0x65e4, 0x65ea, 0x65eb, /* 0x95 */ 0x65f2, 0x65f3, 0x65f4, 0x65f5, 0x65f8, 0x65f9, 0x65fb, 0x65fc, 0x65fd, 0x65fe, 0x65ff, 0x6601, 0x6604, 0x6605, 0x6607, 0x6608, 0x6609, 0x660b, 0x660d, 0x6610, 0x6611, 0x6612, 0x6616, 0x6617, 0x6618, 0x661a, 0x661b, 0x661c, 0x661e, 0x6621, 0x6622, 0x6623, 0x6624, 0x6626, 0x6629, 0x662a, 0x662b, 0x662c, 0x662e, 0x6630, 0x6632, 0x6633, 0x6637, 0x6638, 0x6639, 0x663a, 0x663b, 0x663d, 0x663f, 0x6640, 0x6642, 0x6644, 0x6645, 0x6646, 0x6647, 0x6648, 0x6649, 0x664a, 0x664d, 0x664e, 0x6650, 0x6651, 0x6658, 0x6659, 0x665b, 0x665c, 0x665d, 0x665e, 0x6660, 0x6662, 0x6663, 0x6665, 0x6667, 0x6669, 0x666a, 0x666b, 0x666c, 0x666d, 0x6671, 0x6672, 0x6673, 0x6675, 0x6678, 0x6679, 0x667b, 0x667c, 0x667d, 0x667f, 0x6680, 0x6681, 0x6683, 0x6685, 0x6686, 0x6688, 0x6689, 0x668a, 0x668b, 0x668d, 0x668e, 0x668f, 0x6690, 0x6692, 0x6693, 0x6694, 0x6695, 0x6698, 0x6699, 0x669a, 0x669b, 0x669c, 0x669e, 0x669f, 0x66a0, 0x66a1, 0x66a2, 0x66a3, 0x66a4, 0x66a5, 0x66a6, 0x66a9, 0x66aa, 0x66ab, 0x66ac, 0x66ad, 0x66af, 0x66b0, 0x66b1, 0x66b2, 0x66b3, 0x66b5, 0x66b6, 0x66b7, 0x66b8, 0x66ba, 0x66bb, 0x66bc, 0x66bd, 0x66bf, 0x66c0, 0x66c1, 0x66c2, 0x66c3, 0x66c4, 0x66c5, 0x66c6, 0x66c7, 0x66c8, 0x66c9, 0x66ca, 0x66cb, 0x66cc, 0x66cd, 0x66ce, 0x66cf, 0x66d0, 0x66d1, 0x66d2, 0x66d3, 0x66d4, 0x66d5, 0x66d6, 0x66d7, 0x66d8, 0x66da, 0x66de, 0x66df, 0x66e0, 0x66e1, 0x66e2, 0x66e3, 0x66e4, 0x66e5, 0x66e7, 0x66e8, 0x66ea, 0x66eb, 0x66ec, 0x66ed, 0x66ee, 0x66ef, 0x66f1, 0x66f5, 0x66f6, 0x66f8, 0x66fa, 0x66fb, 0x66fd, 0x6701, 0x6702, 0x6703, /* 0x96 */ 0x6704, 0x6705, 0x6706, 0x6707, 0x670c, 0x670e, 0x670f, 0x6711, 0x6712, 0x6713, 0x6716, 0x6718, 0x6719, 0x671a, 0x671c, 0x671e, 0x6720, 0x6721, 0x6722, 0x6723, 0x6724, 0x6725, 0x6727, 0x6729, 0x672e, 0x6730, 0x6732, 0x6733, 0x6736, 0x6737, 0x6738, 0x6739, 0x673b, 0x673c, 0x673e, 0x673f, 0x6741, 0x6744, 0x6745, 0x6747, 0x674a, 0x674b, 0x674d, 0x6752, 0x6754, 0x6755, 0x6757, 0x6758, 0x6759, 0x675a, 0x675b, 0x675d, 0x6762, 0x6763, 0x6764, 0x6766, 0x6767, 0x676b, 0x676c, 0x676e, 0x6771, 0x6774, 0x6776, 0x6778, 0x6779, 0x677a, 0x677b, 0x677d, 0x6780, 0x6782, 0x6783, 0x6785, 0x6786, 0x6788, 0x678a, 0x678c, 0x678d, 0x678e, 0x678f, 0x6791, 0x6792, 0x6793, 0x6794, 0x6796, 0x6799, 0x679b, 0x679f, 0x67a0, 0x67a1, 0x67a4, 0x67a6, 0x67a9, 0x67ac, 0x67ae, 0x67b1, 0x67b2, 0x67b4, 0x67b9, 0x67ba, 0x67bb, 0x67bc, 0x67bd, 0x67be, 0x67bf, 0x67c0, 0x67c2, 0x67c5, 0x67c6, 0x67c7, 0x67c8, 0x67c9, 0x67ca, 0x67cb, 0x67cc, 0x67cd, 0x67ce, 0x67d5, 0x67d6, 0x67d7, 0x67db, 0x67df, 0x67e1, 0x67e3, 0x67e4, 0x67e6, 0x67e7, 0x67e8, 0x67ea, 0x67eb, 0x67ed, 0x67ee, 0x67f2, 0x67f5, 0x67f6, 0x67f7, 0x67f8, 0x67f9, 0x67fa, 0x67fb, 0x67fc, 0x67fe, 0x6801, 0x6802, 0x6803, 0x6804, 0x6806, 0x680d, 0x6810, 0x6812, 0x6814, 0x6815, 0x6818, 0x6819, 0x681a, 0x681b, 0x681c, 0x681e, 0x681f, 0x6820, 0x6822, 0x6823, 0x6824, 0x6825, 0x6826, 0x6827, 0x6828, 0x682b, 0x682c, 0x682d, 0x682e, 0x682f, 0x6830, 0x6831, 0x6834, 0x6835, 0x6836, 0x683a, 0x683b, 0x683f, 0x6847, 0x684b, 0x684d, 0x684f, 0x6852, 0x6856, 0x6857, 0x6858, 0x6859, 0x685a, 0x685b, /* 0x97 */ 0x685c, 0x685d, 0x685e, 0x685f, 0x686a, 0x686c, 0x686d, 0x686e, 0x686f, 0x6870, 0x6871, 0x6872, 0x6873, 0x6875, 0x6878, 0x6879, 0x687a, 0x687b, 0x687c, 0x687d, 0x687e, 0x687f, 0x6880, 0x6882, 0x6884, 0x6887, 0x6888, 0x6889, 0x688a, 0x688b, 0x688c, 0x688d, 0x688e, 0x6890, 0x6891, 0x6892, 0x6894, 0x6895, 0x6896, 0x6898, 0x6899, 0x689a, 0x689b, 0x689c, 0x689d, 0x689e, 0x689f, 0x68a0, 0x68a1, 0x68a3, 0x68a4, 0x68a5, 0x68a9, 0x68aa, 0x68ab, 0x68ac, 0x68ae, 0x68b1, 0x68b2, 0x68b4, 0x68b6, 0x68b7, 0x68b8, 0x68b9, 0x68ba, 0x68bb, 0x68bc, 0x68bd, 0x68be, 0x68bf, 0x68c1, 0x68c3, 0x68c4, 0x68c5, 0x68c6, 0x68c7, 0x68c8, 0x68ca, 0x68cc, 0x68ce, 0x68cf, 0x68d0, 0x68d1, 0x68d3, 0x68d4, 0x68d6, 0x68d7, 0x68d9, 0x68db, 0x68dc, 0x68dd, 0x68de, 0x68df, 0x68e1, 0x68e2, 0x68e4, 0x68e5, 0x68e6, 0x68e7, 0x68e8, 0x68e9, 0x68ea, 0x68eb, 0x68ec, 0x68ed, 0x68ef, 0x68f2, 0x68f3, 0x68f4, 0x68f6, 0x68f7, 0x68f8, 0x68fb, 0x68fd, 0x68fe, 0x68ff, 0x6900, 0x6902, 0x6903, 0x6904, 0x6906, 0x6907, 0x6908, 0x6909, 0x690a, 0x690c, 0x690f, 0x6911, 0x6913, 0x6914, 0x6915, 0x6916, 0x6917, 0x6918, 0x6919, 0x691a, 0x691b, 0x691c, 0x691d, 0x691e, 0x6921, 0x6922, 0x6923, 0x6925, 0x6926, 0x6927, 0x6928, 0x6929, 0x692a, 0x692b, 0x692c, 0x692e, 0x692f, 0x6931, 0x6932, 0x6933, 0x6935, 0x6936, 0x6937, 0x6938, 0x693a, 0x693b, 0x693c, 0x693e, 0x6940, 0x6941, 0x6943, 0x6944, 0x6945, 0x6946, 0x6947, 0x6948, 0x6949, 0x694a, 0x694b, 0x694c, 0x694d, 0x694e, 0x694f, 0x6950, 0x6951, 0x6952, 0x6953, 0x6955, 0x6956, 0x6958, 0x6959, 0x695b, 0x695c, 0x695f, /* 0x98 */ 0x6961, 0x6962, 0x6964, 0x6965, 0x6967, 0x6968, 0x6969, 0x696a, 0x696c, 0x696d, 0x696f, 0x6970, 0x6972, 0x6973, 0x6974, 0x6975, 0x6976, 0x697a, 0x697b, 0x697d, 0x697e, 0x697f, 0x6981, 0x6983, 0x6985, 0x698a, 0x698b, 0x698c, 0x698e, 0x698f, 0x6990, 0x6991, 0x6992, 0x6993, 0x6996, 0x6997, 0x6999, 0x699a, 0x699d, 0x699e, 0x699f, 0x69a0, 0x69a1, 0x69a2, 0x69a3, 0x69a4, 0x69a5, 0x69a6, 0x69a9, 0x69aa, 0x69ac, 0x69ae, 0x69af, 0x69b0, 0x69b2, 0x69b3, 0x69b5, 0x69b6, 0x69b8, 0x69b9, 0x69ba, 0x69bc, 0x69bd, 0x69be, 0x69bf, 0x69c0, 0x69c2, 0x69c3, 0x69c4, 0x69c5, 0x69c6, 0x69c7, 0x69c8, 0x69c9, 0x69cb, 0x69cd, 0x69cf, 0x69d1, 0x69d2, 0x69d3, 0x69d5, 0x69d6, 0x69d7, 0x69d8, 0x69d9, 0x69da, 0x69dc, 0x69dd, 0x69de, 0x69e1, 0x69e2, 0x69e3, 0x69e4, 0x69e5, 0x69e6, 0x69e7, 0x69e8, 0x69e9, 0x69ea, 0x69eb, 0x69ec, 0x69ee, 0x69ef, 0x69f0, 0x69f1, 0x69f3, 0x69f4, 0x69f5, 0x69f6, 0x69f7, 0x69f8, 0x69f9, 0x69fa, 0x69fb, 0x69fc, 0x69fe, 0x6a00, 0x6a01, 0x6a02, 0x6a03, 0x6a04, 0x6a05, 0x6a06, 0x6a07, 0x6a08, 0x6a09, 0x6a0b, 0x6a0c, 0x6a0d, 0x6a0e, 0x6a0f, 0x6a10, 0x6a11, 0x6a12, 0x6a13, 0x6a14, 0x6a15, 0x6a16, 0x6a19, 0x6a1a, 0x6a1b, 0x6a1c, 0x6a1d, 0x6a1e, 0x6a20, 0x6a22, 0x6a23, 0x6a24, 0x6a25, 0x6a26, 0x6a27, 0x6a29, 0x6a2b, 0x6a2c, 0x6a2d, 0x6a2e, 0x6a30, 0x6a32, 0x6a33, 0x6a34, 0x6a36, 0x6a37, 0x6a38, 0x6a39, 0x6a3a, 0x6a3b, 0x6a3c, 0x6a3f, 0x6a40, 0x6a41, 0x6a42, 0x6a43, 0x6a45, 0x6a46, 0x6a48, 0x6a49, 0x6a4a, 0x6a4b, 0x6a4c, 0x6a4d, 0x6a4e, 0x6a4f, 0x6a51, 0x6a52, 0x6a53, 0x6a54, 0x6a55, 0x6a56, 0x6a57, 0x6a5a, /* 0x99 */ 0x6a5c, 0x6a5d, 0x6a5e, 0x6a5f, 0x6a60, 0x6a62, 0x6a63, 0x6a64, 0x6a66, 0x6a67, 0x6a68, 0x6a69, 0x6a6a, 0x6a6b, 0x6a6c, 0x6a6d, 0x6a6e, 0x6a6f, 0x6a70, 0x6a72, 0x6a73, 0x6a74, 0x6a75, 0x6a76, 0x6a77, 0x6a78, 0x6a7a, 0x6a7b, 0x6a7d, 0x6a7e, 0x6a7f, 0x6a81, 0x6a82, 0x6a83, 0x6a85, 0x6a86, 0x6a87, 0x6a88, 0x6a89, 0x6a8a, 0x6a8b, 0x6a8c, 0x6a8d, 0x6a8f, 0x6a92, 0x6a93, 0x6a94, 0x6a95, 0x6a96, 0x6a98, 0x6a99, 0x6a9a, 0x6a9b, 0x6a9c, 0x6a9d, 0x6a9e, 0x6a9f, 0x6aa1, 0x6aa2, 0x6aa3, 0x6aa4, 0x6aa5, 0x6aa6, 0x6aa7, 0x6aa8, 0x6aaa, 0x6aad, 0x6aae, 0x6aaf, 0x6ab0, 0x6ab1, 0x6ab2, 0x6ab3, 0x6ab4, 0x6ab5, 0x6ab6, 0x6ab7, 0x6ab8, 0x6ab9, 0x6aba, 0x6abb, 0x6abc, 0x6abd, 0x6abe, 0x6abf, 0x6ac0, 0x6ac1, 0x6ac2, 0x6ac3, 0x6ac4, 0x6ac5, 0x6ac6, 0x6ac7, 0x6ac8, 0x6ac9, 0x6aca, 0x6acb, 0x6acc, 0x6acd, 0x6ace, 0x6acf, 0x6ad0, 0x6ad1, 0x6ad2, 0x6ad3, 0x6ad4, 0x6ad5, 0x6ad6, 0x6ad7, 0x6ad8, 0x6ad9, 0x6ada, 0x6adb, 0x6adc, 0x6add, 0x6ade, 0x6adf, 0x6ae0, 0x6ae1, 0x6ae2, 0x6ae3, 0x6ae4, 0x6ae5, 0x6ae6, 0x6ae7, 0x6ae8, 0x6ae9, 0x6aea, 0x6aeb, 0x6aec, 0x6aed, 0x6aee, 0x6aef, 0x6af0, 0x6af1, 0x6af2, 0x6af3, 0x6af4, 0x6af5, 0x6af6, 0x6af7, 0x6af8, 0x6af9, 0x6afa, 0x6afb, 0x6afc, 0x6afd, 0x6afe, 0x6aff, 0x6b00, 0x6b01, 0x6b02, 0x6b03, 0x6b04, 0x6b05, 0x6b06, 0x6b07, 0x6b08, 0x6b09, 0x6b0a, 0x6b0b, 0x6b0c, 0x6b0d, 0x6b0e, 0x6b0f, 0x6b10, 0x6b11, 0x6b12, 0x6b13, 0x6b14, 0x6b15, 0x6b16, 0x6b17, 0x6b18, 0x6b19, 0x6b1a, 0x6b1b, 0x6b1c, 0x6b1d, 0x6b1e, 0x6b1f, 0x6b25, 0x6b26, 0x6b28, 0x6b29, 0x6b2a, 0x6b2b, 0x6b2c, 0x6b2d, 0x6b2e, /* 0x9a */ 0x6b2f, 0x6b30, 0x6b31, 0x6b33, 0x6b34, 0x6b35, 0x6b36, 0x6b38, 0x6b3b, 0x6b3c, 0x6b3d, 0x6b3f, 0x6b40, 0x6b41, 0x6b42, 0x6b44, 0x6b45, 0x6b48, 0x6b4a, 0x6b4b, 0x6b4d, 0x6b4e, 0x6b4f, 0x6b50, 0x6b51, 0x6b52, 0x6b53, 0x6b54, 0x6b55, 0x6b56, 0x6b57, 0x6b58, 0x6b5a, 0x6b5b, 0x6b5c, 0x6b5d, 0x6b5e, 0x6b5f, 0x6b60, 0x6b61, 0x6b68, 0x6b69, 0x6b6b, 0x6b6c, 0x6b6d, 0x6b6e, 0x6b6f, 0x6b70, 0x6b71, 0x6b72, 0x6b73, 0x6b74, 0x6b75, 0x6b76, 0x6b77, 0x6b78, 0x6b7a, 0x6b7d, 0x6b7e, 0x6b7f, 0x6b80, 0x6b85, 0x6b88, 0x6b8c, 0x6b8e, 0x6b8f, 0x6b90, 0x6b91, 0x6b94, 0x6b95, 0x6b97, 0x6b98, 0x6b99, 0x6b9c, 0x6b9d, 0x6b9e, 0x6b9f, 0x6ba0, 0x6ba2, 0x6ba3, 0x6ba4, 0x6ba5, 0x6ba6, 0x6ba7, 0x6ba8, 0x6ba9, 0x6bab, 0x6bac, 0x6bad, 0x6bae, 0x6baf, 0x6bb0, 0x6bb1, 0x6bb2, 0x6bb6, 0x6bb8, 0x6bb9, 0x6bba, 0x6bbb, 0x6bbc, 0x6bbd, 0x6bbe, 0x6bc0, 0x6bc3, 0x6bc4, 0x6bc6, 0x6bc7, 0x6bc8, 0x6bc9, 0x6bca, 0x6bcc, 0x6bce, 0x6bd0, 0x6bd1, 0x6bd8, 0x6bda, 0x6bdc, 0x6bdd, 0x6bde, 0x6bdf, 0x6be0, 0x6be2, 0x6be3, 0x6be4, 0x6be5, 0x6be6, 0x6be7, 0x6be8, 0x6be9, 0x6bec, 0x6bed, 0x6bee, 0x6bf0, 0x6bf1, 0x6bf2, 0x6bf4, 0x6bf6, 0x6bf7, 0x6bf8, 0x6bfa, 0x6bfb, 0x6bfc, 0x6bfe, 0x6bff, 0x6c00, 0x6c01, 0x6c02, 0x6c03, 0x6c04, 0x6c08, 0x6c09, 0x6c0a, 0x6c0b, 0x6c0c, 0x6c0e, 0x6c12, 0x6c17, 0x6c1c, 0x6c1d, 0x6c1e, 0x6c20, 0x6c23, 0x6c25, 0x6c2b, 0x6c2c, 0x6c2d, 0x6c31, 0x6c33, 0x6c36, 0x6c37, 0x6c39, 0x6c3a, 0x6c3b, 0x6c3c, 0x6c3e, 0x6c3f, 0x6c43, 0x6c44, 0x6c45, 0x6c48, 0x6c4b, 0x6c4c, 0x6c4d, 0x6c4e, 0x6c4f, 0x6c51, 0x6c52, 0x6c53, 0x6c56, 0x6c58, /* 0x9b */ 0x6c59, 0x6c5a, 0x6c62, 0x6c63, 0x6c65, 0x6c66, 0x6c67, 0x6c6b, 0x6c6c, 0x6c6d, 0x6c6e, 0x6c6f, 0x6c71, 0x6c73, 0x6c75, 0x6c77, 0x6c78, 0x6c7a, 0x6c7b, 0x6c7c, 0x6c7f, 0x6c80, 0x6c84, 0x6c87, 0x6c8a, 0x6c8b, 0x6c8d, 0x6c8e, 0x6c91, 0x6c92, 0x6c95, 0x6c96, 0x6c97, 0x6c98, 0x6c9a, 0x6c9c, 0x6c9d, 0x6c9e, 0x6ca0, 0x6ca2, 0x6ca8, 0x6cac, 0x6caf, 0x6cb0, 0x6cb4, 0x6cb5, 0x6cb6, 0x6cb7, 0x6cba, 0x6cc0, 0x6cc1, 0x6cc2, 0x6cc3, 0x6cc6, 0x6cc7, 0x6cc8, 0x6ccb, 0x6ccd, 0x6cce, 0x6ccf, 0x6cd1, 0x6cd2, 0x6cd8, 0x6cd9, 0x6cda, 0x6cdc, 0x6cdd, 0x6cdf, 0x6ce4, 0x6ce6, 0x6ce7, 0x6ce9, 0x6cec, 0x6ced, 0x6cf2, 0x6cf4, 0x6cf9, 0x6cff, 0x6d00, 0x6d02, 0x6d03, 0x6d05, 0x6d06, 0x6d08, 0x6d09, 0x6d0a, 0x6d0d, 0x6d0f, 0x6d10, 0x6d11, 0x6d13, 0x6d14, 0x6d15, 0x6d16, 0x6d18, 0x6d1c, 0x6d1d, 0x6d1f, 0x6d20, 0x6d21, 0x6d22, 0x6d23, 0x6d24, 0x6d26, 0x6d28, 0x6d29, 0x6d2c, 0x6d2d, 0x6d2f, 0x6d30, 0x6d34, 0x6d36, 0x6d37, 0x6d38, 0x6d3a, 0x6d3f, 0x6d40, 0x6d42, 0x6d44, 0x6d49, 0x6d4c, 0x6d50, 0x6d55, 0x6d56, 0x6d57, 0x6d58, 0x6d5b, 0x6d5d, 0x6d5f, 0x6d61, 0x6d62, 0x6d64, 0x6d65, 0x6d67, 0x6d68, 0x6d6b, 0x6d6c, 0x6d6d, 0x6d70, 0x6d71, 0x6d72, 0x6d73, 0x6d75, 0x6d76, 0x6d79, 0x6d7a, 0x6d7b, 0x6d7d, 0x6d7e, 0x6d7f, 0x6d80, 0x6d81, 0x6d83, 0x6d84, 0x6d86, 0x6d87, 0x6d8a, 0x6d8b, 0x6d8d, 0x6d8f, 0x6d90, 0x6d92, 0x6d96, 0x6d97, 0x6d98, 0x6d99, 0x6d9a, 0x6d9c, 0x6da2, 0x6da5, 0x6dac, 0x6dad, 0x6db0, 0x6db1, 0x6db3, 0x6db4, 0x6db6, 0x6db7, 0x6db9, 0x6dba, 0x6dbb, 0x6dbc, 0x6dbd, 0x6dbe, 0x6dc1, 0x6dc2, 0x6dc3, 0x6dc8, 0x6dc9, 0x6dca, /* 0x9c */ 0x6dcd, 0x6dce, 0x6dcf, 0x6dd0, 0x6dd2, 0x6dd3, 0x6dd4, 0x6dd5, 0x6dd7, 0x6dda, 0x6ddb, 0x6ddc, 0x6ddf, 0x6de2, 0x6de3, 0x6de5, 0x6de7, 0x6de8, 0x6de9, 0x6dea, 0x6ded, 0x6def, 0x6df0, 0x6df2, 0x6df4, 0x6df5, 0x6df6, 0x6df8, 0x6dfa, 0x6dfd, 0x6dfe, 0x6dff, 0x6e00, 0x6e01, 0x6e02, 0x6e03, 0x6e04, 0x6e06, 0x6e07, 0x6e08, 0x6e09, 0x6e0b, 0x6e0f, 0x6e12, 0x6e13, 0x6e15, 0x6e18, 0x6e19, 0x6e1b, 0x6e1c, 0x6e1e, 0x6e1f, 0x6e22, 0x6e26, 0x6e27, 0x6e28, 0x6e2a, 0x6e2c, 0x6e2e, 0x6e30, 0x6e31, 0x6e33, 0x6e35, 0x6e36, 0x6e37, 0x6e39, 0x6e3b, 0x6e3c, 0x6e3d, 0x6e3e, 0x6e3f, 0x6e40, 0x6e41, 0x6e42, 0x6e45, 0x6e46, 0x6e47, 0x6e48, 0x6e49, 0x6e4a, 0x6e4b, 0x6e4c, 0x6e4f, 0x6e50, 0x6e51, 0x6e52, 0x6e55, 0x6e57, 0x6e59, 0x6e5a, 0x6e5c, 0x6e5d, 0x6e5e, 0x6e60, 0x6e61, 0x6e62, 0x6e63, 0x6e64, 0x6e65, 0x6e66, 0x6e67, 0x6e68, 0x6e69, 0x6e6a, 0x6e6c, 0x6e6d, 0x6e6f, 0x6e70, 0x6e71, 0x6e72, 0x6e73, 0x6e74, 0x6e75, 0x6e76, 0x6e77, 0x6e78, 0x6e79, 0x6e7a, 0x6e7b, 0x6e7c, 0x6e7d, 0x6e80, 0x6e81, 0x6e82, 0x6e84, 0x6e87, 0x6e88, 0x6e8a, 0x6e8b, 0x6e8c, 0x6e8d, 0x6e8e, 0x6e91, 0x6e92, 0x6e93, 0x6e94, 0x6e95, 0x6e96, 0x6e97, 0x6e99, 0x6e9a, 0x6e9b, 0x6e9d, 0x6e9e, 0x6ea0, 0x6ea1, 0x6ea3, 0x6ea4, 0x6ea6, 0x6ea8, 0x6ea9, 0x6eab, 0x6eac, 0x6ead, 0x6eae, 0x6eb0, 0x6eb3, 0x6eb5, 0x6eb8, 0x6eb9, 0x6ebc, 0x6ebe, 0x6ebf, 0x6ec0, 0x6ec3, 0x6ec4, 0x6ec5, 0x6ec6, 0x6ec8, 0x6ec9, 0x6eca, 0x6ecc, 0x6ecd, 0x6ece, 0x6ed0, 0x6ed2, 0x6ed6, 0x6ed8, 0x6ed9, 0x6edb, 0x6edc, 0x6edd, 0x6ee3, 0x6ee7, 0x6eea, 0x6eeb, 0x6eec, 0x6eed, 0x6eee, 0x6eef, /* 0x9d */ 0x6ef0, 0x6ef1, 0x6ef2, 0x6ef3, 0x6ef5, 0x6ef6, 0x6ef7, 0x6ef8, 0x6efa, 0x6efb, 0x6efc, 0x6efd, 0x6efe, 0x6eff, 0x6f00, 0x6f01, 0x6f03, 0x6f04, 0x6f05, 0x6f07, 0x6f08, 0x6f0a, 0x6f0b, 0x6f0c, 0x6f0d, 0x6f0e, 0x6f10, 0x6f11, 0x6f12, 0x6f16, 0x6f17, 0x6f18, 0x6f19, 0x6f1a, 0x6f1b, 0x6f1c, 0x6f1d, 0x6f1e, 0x6f1f, 0x6f21, 0x6f22, 0x6f23, 0x6f25, 0x6f26, 0x6f27, 0x6f28, 0x6f2c, 0x6f2e, 0x6f30, 0x6f32, 0x6f34, 0x6f35, 0x6f37, 0x6f38, 0x6f39, 0x6f3a, 0x6f3b, 0x6f3c, 0x6f3d, 0x6f3f, 0x6f40, 0x6f41, 0x6f42, 0x6f43, 0x6f44, 0x6f45, 0x6f48, 0x6f49, 0x6f4a, 0x6f4c, 0x6f4e, 0x6f4f, 0x6f50, 0x6f51, 0x6f52, 0x6f53, 0x6f54, 0x6f55, 0x6f56, 0x6f57, 0x6f59, 0x6f5a, 0x6f5b, 0x6f5d, 0x6f5f, 0x6f60, 0x6f61, 0x6f63, 0x6f64, 0x6f65, 0x6f67, 0x6f68, 0x6f69, 0x6f6a, 0x6f6b, 0x6f6c, 0x6f6f, 0x6f70, 0x6f71, 0x6f73, 0x6f75, 0x6f76, 0x6f77, 0x6f79, 0x6f7b, 0x6f7d, 0x6f7e, 0x6f7f, 0x6f80, 0x6f81, 0x6f82, 0x6f83, 0x6f85, 0x6f86, 0x6f87, 0x6f8a, 0x6f8b, 0x6f8f, 0x6f90, 0x6f91, 0x6f92, 0x6f93, 0x6f94, 0x6f95, 0x6f96, 0x6f97, 0x6f98, 0x6f99, 0x6f9a, 0x6f9b, 0x6f9d, 0x6f9e, 0x6f9f, 0x6fa0, 0x6fa2, 0x6fa3, 0x6fa4, 0x6fa5, 0x6fa6, 0x6fa8, 0x6fa9, 0x6faa, 0x6fab, 0x6fac, 0x6fad, 0x6fae, 0x6faf, 0x6fb0, 0x6fb1, 0x6fb2, 0x6fb4, 0x6fb5, 0x6fb7, 0x6fb8, 0x6fba, 0x6fbb, 0x6fbc, 0x6fbd, 0x6fbe, 0x6fbf, 0x6fc1, 0x6fc3, 0x6fc4, 0x6fc5, 0x6fc6, 0x6fc7, 0x6fc8, 0x6fca, 0x6fcb, 0x6fcc, 0x6fcd, 0x6fce, 0x6fcf, 0x6fd0, 0x6fd3, 0x6fd4, 0x6fd5, 0x6fd6, 0x6fd7, 0x6fd8, 0x6fd9, 0x6fda, 0x6fdb, 0x6fdc, 0x6fdd, 0x6fdf, 0x6fe2, 0x6fe3, 0x6fe4, 0x6fe5, /* 0x9e */ 0x6fe6, 0x6fe7, 0x6fe8, 0x6fe9, 0x6fea, 0x6feb, 0x6fec, 0x6fed, 0x6ff0, 0x6ff1, 0x6ff2, 0x6ff3, 0x6ff4, 0x6ff5, 0x6ff6, 0x6ff7, 0x6ff8, 0x6ff9, 0x6ffa, 0x6ffb, 0x6ffc, 0x6ffd, 0x6ffe, 0x6fff, 0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x7007, 0x7008, 0x7009, 0x700a, 0x700b, 0x700c, 0x700d, 0x700e, 0x700f, 0x7010, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017, 0x7018, 0x7019, 0x701c, 0x701d, 0x701e, 0x701f, 0x7020, 0x7021, 0x7022, 0x7024, 0x7025, 0x7026, 0x7027, 0x7028, 0x7029, 0x702a, 0x702b, 0x702c, 0x702d, 0x702e, 0x702f, 0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7036, 0x7037, 0x7038, 0x703a, 0x703b, 0x703c, 0x703d, 0x703e, 0x703f, 0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047, 0x7048, 0x7049, 0x704a, 0x704b, 0x704d, 0x704e, 0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7057, 0x7058, 0x7059, 0x705a, 0x705b, 0x705c, 0x705d, 0x705f, 0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067, 0x7068, 0x7069, 0x706a, 0x706e, 0x7071, 0x7072, 0x7073, 0x7074, 0x7077, 0x7079, 0x707a, 0x707b, 0x707d, 0x7081, 0x7082, 0x7083, 0x7084, 0x7086, 0x7087, 0x7088, 0x708b, 0x708c, 0x708d, 0x708f, 0x7090, 0x7091, 0x7093, 0x7097, 0x7098, 0x709a, 0x709b, 0x709e, 0x709f, 0x70a0, 0x70a1, 0x70a2, 0x70a3, 0x70a4, 0x70a5, 0x70a6, 0x70a7, 0x70a8, 0x70a9, 0x70aa, 0x70b0, 0x70b2, 0x70b4, 0x70b5, 0x70b6, 0x70ba, 0x70be, 0x70bf, 0x70c4, 0x70c5, 0x70c6, 0x70c7, 0x70c9, 0x70cb, 0x70cc, 0x70cd, 0x70ce, 0x70cf, 0x70d0, 0x70d1, 0x70d2, 0x70d3, 0x70d4, 0x70d5, 0x70d6, 0x70d7, 0x70da, /* 0x9f */ 0x70dc, 0x70dd, 0x70de, 0x70e0, 0x70e1, 0x70e2, 0x70e3, 0x70e5, 0x70ea, 0x70ee, 0x70f0, 0x70f1, 0x70f2, 0x70f3, 0x70f4, 0x70f5, 0x70f6, 0x70f8, 0x70fa, 0x70fb, 0x70fc, 0x70fe, 0x70ff, 0x7100, 0x7101, 0x7102, 0x7103, 0x7104, 0x7105, 0x7106, 0x7107, 0x7108, 0x710b, 0x710c, 0x710d, 0x710e, 0x710f, 0x7111, 0x7112, 0x7114, 0x7117, 0x711b, 0x711c, 0x711d, 0x711e, 0x711f, 0x7120, 0x7121, 0x7122, 0x7123, 0x7124, 0x7125, 0x7127, 0x7128, 0x7129, 0x712a, 0x712b, 0x712c, 0x712d, 0x712e, 0x7132, 0x7133, 0x7134, 0x7135, 0x7137, 0x7138, 0x7139, 0x713a, 0x713b, 0x713c, 0x713d, 0x713e, 0x713f, 0x7140, 0x7141, 0x7142, 0x7143, 0x7144, 0x7146, 0x7147, 0x7148, 0x7149, 0x714b, 0x714d, 0x714f, 0x7150, 0x7151, 0x7152, 0x7153, 0x7154, 0x7155, 0x7156, 0x7157, 0x7158, 0x7159, 0x715a, 0x715b, 0x715d, 0x715f, 0x7160, 0x7161, 0x7162, 0x7163, 0x7165, 0x7169, 0x716a, 0x716b, 0x716c, 0x716d, 0x716f, 0x7170, 0x7171, 0x7174, 0x7175, 0x7176, 0x7177, 0x7179, 0x717b, 0x717c, 0x717e, 0x717f, 0x7180, 0x7181, 0x7182, 0x7183, 0x7185, 0x7186, 0x7187, 0x7188, 0x7189, 0x718b, 0x718c, 0x718d, 0x718e, 0x7190, 0x7191, 0x7192, 0x7193, 0x7195, 0x7196, 0x7197, 0x719a, 0x719b, 0x719c, 0x719d, 0x719e, 0x71a1, 0x71a2, 0x71a3, 0x71a4, 0x71a5, 0x71a6, 0x71a7, 0x71a9, 0x71aa, 0x71ab, 0x71ad, 0x71ae, 0x71af, 0x71b0, 0x71b1, 0x71b2, 0x71b4, 0x71b6, 0x71b7, 0x71b8, 0x71ba, 0x71bb, 0x71bc, 0x71bd, 0x71be, 0x71bf, 0x71c0, 0x71c1, 0x71c2, 0x71c4, 0x71c5, 0x71c6, 0x71c7, 0x71c8, 0x71c9, 0x71ca, 0x71cb, 0x71cc, 0x71cd, 0x71cf, 0x71d0, 0x71d1, 0x71d2, 0x71d3, /* 0xa0 */ 0x71d6, 0x71d7, 0x71d8, 0x71d9, 0x71da, 0x71db, 0x71dc, 0x71dd, 0x71de, 0x71df, 0x71e1, 0x71e2, 0x71e3, 0x71e4, 0x71e6, 0x71e8, 0x71e9, 0x71ea, 0x71eb, 0x71ec, 0x71ed, 0x71ef, 0x71f0, 0x71f1, 0x71f2, 0x71f3, 0x71f4, 0x71f5, 0x71f6, 0x71f7, 0x71f8, 0x71fa, 0x71fb, 0x71fc, 0x71fd, 0x71fe, 0x71ff, 0x7200, 0x7201, 0x7202, 0x7203, 0x7204, 0x7205, 0x7207, 0x7208, 0x7209, 0x720a, 0x720b, 0x720c, 0x720d, 0x720e, 0x720f, 0x7210, 0x7211, 0x7212, 0x7213, 0x7214, 0x7215, 0x7216, 0x7217, 0x7218, 0x7219, 0x721a, 0x721b, 0x721c, 0x721e, 0x721f, 0x7220, 0x7221, 0x7222, 0x7223, 0x7224, 0x7225, 0x7226, 0x7227, 0x7229, 0x722b, 0x722d, 0x722e, 0x722f, 0x7232, 0x7233, 0x7234, 0x723a, 0x723c, 0x723e, 0x7240, 0x7241, 0x7242, 0x7243, 0x7244, 0x7245, 0x7246, 0x7249, 0x724a, 0x724b, 0x724e, 0x724f, 0x7250, 0x7251, 0x7253, 0x7254, 0x7255, 0x7257, 0x7258, 0x725a, 0x725c, 0x725e, 0x7260, 0x7263, 0x7264, 0x7265, 0x7268, 0x726a, 0x726b, 0x726c, 0x726d, 0x7270, 0x7271, 0x7273, 0x7274, 0x7276, 0x7277, 0x7278, 0x727b, 0x727c, 0x727d, 0x7282, 0x7283, 0x7285, 0x7286, 0x7287, 0x7288, 0x7289, 0x728c, 0x728e, 0x7290, 0x7291, 0x7293, 0x7294, 0x7295, 0x7296, 0x7297, 0x7298, 0x7299, 0x729a, 0x729b, 0x729c, 0x729d, 0x729e, 0x72a0, 0x72a1, 0x72a2, 0x72a3, 0x72a4, 0x72a5, 0x72a6, 0x72a7, 0x72a8, 0x72a9, 0x72aa, 0x72ab, 0x72ae, 0x72b1, 0x72b2, 0x72b3, 0x72b5, 0x72ba, 0x72bb, 0x72bc, 0x72bd, 0x72be, 0x72bf, 0x72c0, 0x72c5, 0x72c6, 0x72c7, 0x72c9, 0x72ca, 0x72cb, 0x72cc, 0x72cf, 0x72d1, 0x72d3, 0x72d4, 0x72d5, 0x72d6, 0x72d8, 0x72da, 0x72db, /* 0xa1 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x3000, 0x3001, 0x3002, 0x00b7, 0x02c9, 0x02c7, 0x00a8, 0x3003, 0x3005, 0x2014, 0xff5e, 0x2016, 0x2026, 0x2018, 0x2019, 0x201c, 0x201d, 0x3014, 0x3015, 0x3008, 0x3009, 0x300a, 0x300b, 0x300c, 0x300d, 0x300e, 0x300f, 0x3016, 0x3017, 0x3010, 0x3011, 0x00b1, 0x00d7, 0x00f7, 0x2236, 0x2227, 0x2228, 0x2211, 0x220f, 0x222a, 0x2229, 0x2208, 0x2237, 0x221a, 0x22a5, 0x2225, 0x2220, 0x2312, 0x2299, 0x222b, 0x222e, 0x2261, 0x224c, 0x2248, 0x223d, 0x221d, 0x2260, 0x226e, 0x226f, 0x2264, 0x2265, 0x221e, 0x2235, 0x2234, 0x2642, 0x2640, 0x00b0, 0x2032, 0x2033, 0x2103, 0xff04, 0x00a4, 0xffe0, 0xffe1, 0x2030, 0x00a7, 0x2116, 0x2606, 0x2605, 0x25cb, 0x25cf, 0x25ce, 0x25c7, 0x25c6, 0x25a1, 0x25a0, 0x25b3, 0x25b2, 0x203b, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, /* 0xa2 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x2488, 0x2489, 0x248a, 0x248b, 0x248c, 0x248d, 0x248e, 0x248f, 0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497, 0x2498, 0x2499, 0x249a, 0x249b, 0x2474, 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, 0x247e, 0x247f, 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487, 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0xfffd, 0xfffd, 0x3220, 0x3221, 0x3222, 0x3223, 0x3224, 0x3225, 0x3226, 0x3227, 0x3228, 0x3229, 0xfffd, 0xfffd, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216a, 0x216b, 0xfffd, 0xfffd, /* 0xa3 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xff01, 0xff02, 0xff03, 0xffe5, 0xff05, 0xff06, 0xff07, 0xff08, 0xff09, 0xff0a, 0xff0b, 0xff0c, 0xff0d, 0xff0e, 0xff0f, 0xff10, 0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, 0xff18, 0xff19, 0xff1a, 0xff1b, 0xff1c, 0xff1d, 0xff1e, 0xff1f, 0xff20, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0xff3b, 0xff3c, 0xff3d, 0xff3e, 0xff3f, 0xff40, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, 0xff58, 0xff59, 0xff5a, 0xff5b, 0xff5c, 0xff5d, 0xffe3, /* 0xa4 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, 0x304a, 0x304b, 0x304c, 0x304d, 0x304e, 0x304f, 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e, 0x305f, 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068, 0x3069, 0x306a, 0x306b, 0x306c, 0x306d, 0x306e, 0x306f, 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, 0x3078, 0x3079, 0x307a, 0x307b, 0x307c, 0x307d, 0x307e, 0x307f, 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087, 0x3088, 0x3089, 0x308a, 0x308b, 0x308c, 0x308d, 0x308e, 0x308f, 0x3090, 0x3091, 0x3092, 0x3093, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xa5 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x30a1, 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9, 0x30aa, 0x30ab, 0x30ac, 0x30ad, 0x30ae, 0x30af, 0x30b0, 0x30b1, 0x30b2, 0x30b3, 0x30b4, 0x30b5, 0x30b6, 0x30b7, 0x30b8, 0x30b9, 0x30ba, 0x30bb, 0x30bc, 0x30bd, 0x30be, 0x30bf, 0x30c0, 0x30c1, 0x30c2, 0x30c3, 0x30c4, 0x30c5, 0x30c6, 0x30c7, 0x30c8, 0x30c9, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d0, 0x30d1, 0x30d2, 0x30d3, 0x30d4, 0x30d5, 0x30d6, 0x30d7, 0x30d8, 0x30d9, 0x30da, 0x30db, 0x30dc, 0x30dd, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ee, 0x30ef, 0x30f0, 0x30f1, 0x30f2, 0x30f3, 0x30f4, 0x30f5, 0x30f6, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xa6 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfe35, 0xfe36, 0xfe39, 0xfe3a, 0xfe3f, 0xfe40, 0xfe3d, 0xfe3e, 0xfe41, 0xfe42, 0xfe43, 0xfe44, 0xfffd, 0xfffd, 0xfe3b, 0xfe3c, 0xfe37, 0xfe38, 0xfe31, 0xfffd, 0xfe33, 0xfe34, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xa7 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xa8 */ 0x02ca, 0x02cb, 0x02d9, 0x2013, 0x2015, 0x2025, 0x2035, 0x2105, 0x2109, 0x2196, 0x2197, 0x2198, 0x2199, 0x2215, 0x221f, 0x2223, 0x2252, 0x2266, 0x2267, 0x22bf, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e, 0x255f, 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x256d, 0x256e, 0x256f, 0x2570, 0x2571, 0x2572, 0x2573, 0x2581, 0x2582, 0x2583, 0x2584, 0x2585, 0x2586, 0x2587, 0x2588, 0x2589, 0x258a, 0x258b, 0x258c, 0x258d, 0x258e, 0x258f, 0x2593, 0x2594, 0x2595, 0x25bc, 0x25bd, 0x25e2, 0x25e3, 0x25e4, 0x25e5, 0x2609, 0x2295, 0x3012, 0x301d, 0x301e, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0101, 0x00e1, 0x01ce, 0x00e0, 0x0113, 0x00e9, 0x011b, 0x00e8, 0x012b, 0x00ed, 0x01d0, 0x00ec, 0x014d, 0x00f3, 0x01d2, 0x00f2, 0x016b, 0x00fa, 0x01d4, 0x00f9, 0x01d6, 0x01d8, 0x01da, 0x01dc, 0x00fc, 0x00ea, 0x0251, 0xfffd, 0x0144, 0x0148, 0xfffd, 0x0261, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x3105, 0x3106, 0x3107, 0x3108, 0x3109, 0x310a, 0x310b, 0x310c, 0x310d, 0x310e, 0x310f, 0x3110, 0x3111, 0x3112, 0x3113, 0x3114, 0x3115, 0x3116, 0x3117, 0x3118, 0x3119, 0x311a, 0x311b, 0x311c, 0x311d, 0x311e, 0x311f, 0x3120, 0x3121, 0x3122, 0x3123, 0x3124, 0x3125, 0x3126, 0x3127, 0x3128, 0x3129, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xa9 */ 0x3021, 0x3022, 0x3023, 0x3024, 0x3025, 0x3026, 0x3027, 0x3028, 0x3029, 0x32a3, 0x338e, 0x338f, 0x339c, 0x339d, 0x339e, 0x33a1, 0x33c4, 0x33ce, 0x33d1, 0x33d2, 0x33d5, 0xfe30, 0xffe2, 0xffe4, 0xfffd, 0x2121, 0x3231, 0xfffd, 0x2010, 0xfffd, 0xfffd, 0xfffd, 0x30fc, 0x309b, 0x309c, 0x30fd, 0x30fe, 0x3006, 0x309d, 0x309e, 0xfe49, 0xfe4a, 0xfe4b, 0xfe4c, 0xfe4d, 0xfe4e, 0xfe4f, 0xfe50, 0xfe51, 0xfe52, 0xfe54, 0xfe55, 0xfe56, 0xfe57, 0xfe59, 0xfe5a, 0xfe5b, 0xfe5c, 0xfe5d, 0xfe5e, 0xfe5f, 0xfe60, 0xfe61, 0xfe62, 0xfe63, 0xfe64, 0xfe65, 0xfe66, 0xfe68, 0xfe69, 0xfe6a, 0xfe6b, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x3007, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x2500, 0x2501, 0x2502, 0x2503, 0x2504, 0x2505, 0x2506, 0x2507, 0x2508, 0x2509, 0x250a, 0x250b, 0x250c, 0x250d, 0x250e, 0x250f, 0x2510, 0x2511, 0x2512, 0x2513, 0x2514, 0x2515, 0x2516, 0x2517, 0x2518, 0x2519, 0x251a, 0x251b, 0x251c, 0x251d, 0x251e, 0x251f, 0x2520, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, 0x2528, 0x2529, 0x252a, 0x252b, 0x252c, 0x252d, 0x252e, 0x252f, 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, 0x2538, 0x2539, 0x253a, 0x253b, 0x253c, 0x253d, 0x253e, 0x253f, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xaa */ 0x72dc, 0x72dd, 0x72df, 0x72e2, 0x72e3, 0x72e4, 0x72e5, 0x72e6, 0x72e7, 0x72ea, 0x72eb, 0x72f5, 0x72f6, 0x72f9, 0x72fd, 0x72fe, 0x72ff, 0x7300, 0x7302, 0x7304, 0x7305, 0x7306, 0x7307, 0x7308, 0x7309, 0x730b, 0x730c, 0x730d, 0x730f, 0x7310, 0x7311, 0x7312, 0x7314, 0x7318, 0x7319, 0x731a, 0x731f, 0x7320, 0x7323, 0x7324, 0x7326, 0x7327, 0x7328, 0x732d, 0x732f, 0x7330, 0x7332, 0x7333, 0x7335, 0x7336, 0x733a, 0x733b, 0x733c, 0x733d, 0x7340, 0x7341, 0x7342, 0x7343, 0x7344, 0x7345, 0x7346, 0x7347, 0x7348, 0x7349, 0x734a, 0x734b, 0x734c, 0x734e, 0x734f, 0x7351, 0x7353, 0x7354, 0x7355, 0x7356, 0x7358, 0x7359, 0x735a, 0x735b, 0x735c, 0x735d, 0x735e, 0x735f, 0x7361, 0x7362, 0x7363, 0x7364, 0x7365, 0x7366, 0x7367, 0x7368, 0x7369, 0x736a, 0x736b, 0x736e, 0x7370, 0x7371, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xab */ 0x7372, 0x7373, 0x7374, 0x7375, 0x7376, 0x7377, 0x7378, 0x7379, 0x737a, 0x737b, 0x737c, 0x737d, 0x737f, 0x7380, 0x7381, 0x7382, 0x7383, 0x7385, 0x7386, 0x7388, 0x738a, 0x738c, 0x738d, 0x738f, 0x7390, 0x7392, 0x7393, 0x7394, 0x7395, 0x7397, 0x7398, 0x7399, 0x739a, 0x739c, 0x739d, 0x739e, 0x73a0, 0x73a1, 0x73a3, 0x73a4, 0x73a5, 0x73a6, 0x73a7, 0x73a8, 0x73aa, 0x73ac, 0x73ad, 0x73b1, 0x73b4, 0x73b5, 0x73b6, 0x73b8, 0x73b9, 0x73bc, 0x73bd, 0x73be, 0x73bf, 0x73c1, 0x73c3, 0x73c4, 0x73c5, 0x73c6, 0x73c7, 0x73cb, 0x73cc, 0x73ce, 0x73d2, 0x73d3, 0x73d4, 0x73d5, 0x73d6, 0x73d7, 0x73d8, 0x73da, 0x73db, 0x73dc, 0x73dd, 0x73df, 0x73e1, 0x73e2, 0x73e3, 0x73e4, 0x73e6, 0x73e8, 0x73ea, 0x73eb, 0x73ec, 0x73ee, 0x73ef, 0x73f0, 0x73f1, 0x73f3, 0x73f4, 0x73f5, 0x73f6, 0x73f7, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xac */ 0x73f8, 0x73f9, 0x73fa, 0x73fb, 0x73fc, 0x73fd, 0x73fe, 0x73ff, 0x7400, 0x7401, 0x7402, 0x7404, 0x7407, 0x7408, 0x740b, 0x740c, 0x740d, 0x740e, 0x7411, 0x7412, 0x7413, 0x7414, 0x7415, 0x7416, 0x7417, 0x7418, 0x7419, 0x741c, 0x741d, 0x741e, 0x741f, 0x7420, 0x7421, 0x7423, 0x7424, 0x7427, 0x7429, 0x742b, 0x742d, 0x742f, 0x7431, 0x7432, 0x7437, 0x7438, 0x7439, 0x743a, 0x743b, 0x743d, 0x743e, 0x743f, 0x7440, 0x7442, 0x7443, 0x7444, 0x7445, 0x7446, 0x7447, 0x7448, 0x7449, 0x744a, 0x744b, 0x744c, 0x744d, 0x744e, 0x744f, 0x7450, 0x7451, 0x7452, 0x7453, 0x7454, 0x7456, 0x7458, 0x745d, 0x7460, 0x7461, 0x7462, 0x7463, 0x7464, 0x7465, 0x7466, 0x7467, 0x7468, 0x7469, 0x746a, 0x746b, 0x746c, 0x746e, 0x746f, 0x7471, 0x7472, 0x7473, 0x7474, 0x7475, 0x7478, 0x7479, 0x747a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xad */ 0x747b, 0x747c, 0x747d, 0x747f, 0x7482, 0x7484, 0x7485, 0x7486, 0x7488, 0x7489, 0x748a, 0x748c, 0x748d, 0x748f, 0x7491, 0x7492, 0x7493, 0x7494, 0x7495, 0x7496, 0x7497, 0x7498, 0x7499, 0x749a, 0x749b, 0x749d, 0x749f, 0x74a0, 0x74a1, 0x74a2, 0x74a3, 0x74a4, 0x74a5, 0x74a6, 0x74aa, 0x74ab, 0x74ac, 0x74ad, 0x74ae, 0x74af, 0x74b0, 0x74b1, 0x74b2, 0x74b3, 0x74b4, 0x74b5, 0x74b6, 0x74b7, 0x74b8, 0x74b9, 0x74bb, 0x74bc, 0x74bd, 0x74be, 0x74bf, 0x74c0, 0x74c1, 0x74c2, 0x74c3, 0x74c4, 0x74c5, 0x74c6, 0x74c7, 0x74c8, 0x74c9, 0x74ca, 0x74cb, 0x74cc, 0x74cd, 0x74ce, 0x74cf, 0x74d0, 0x74d1, 0x74d3, 0x74d4, 0x74d5, 0x74d6, 0x74d7, 0x74d8, 0x74d9, 0x74da, 0x74db, 0x74dd, 0x74df, 0x74e1, 0x74e5, 0x74e7, 0x74e8, 0x74e9, 0x74ea, 0x74eb, 0x74ec, 0x74ed, 0x74f0, 0x74f1, 0x74f2, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xae */ 0x74f3, 0x74f5, 0x74f8, 0x74f9, 0x74fa, 0x74fb, 0x74fc, 0x74fd, 0x74fe, 0x7500, 0x7501, 0x7502, 0x7503, 0x7505, 0x7506, 0x7507, 0x7508, 0x7509, 0x750a, 0x750b, 0x750c, 0x750e, 0x7510, 0x7512, 0x7514, 0x7515, 0x7516, 0x7517, 0x751b, 0x751d, 0x751e, 0x7520, 0x7521, 0x7522, 0x7523, 0x7524, 0x7526, 0x7527, 0x752a, 0x752e, 0x7534, 0x7536, 0x7539, 0x753c, 0x753d, 0x753f, 0x7541, 0x7542, 0x7543, 0x7544, 0x7546, 0x7547, 0x7549, 0x754a, 0x754d, 0x7550, 0x7551, 0x7552, 0x7553, 0x7555, 0x7556, 0x7557, 0x7558, 0x755d, 0x755e, 0x755f, 0x7560, 0x7561, 0x7562, 0x7563, 0x7564, 0x7567, 0x7568, 0x7569, 0x756b, 0x756c, 0x756d, 0x756e, 0x756f, 0x7570, 0x7571, 0x7573, 0x7575, 0x7576, 0x7577, 0x757a, 0x757b, 0x757c, 0x757d, 0x757e, 0x7580, 0x7581, 0x7582, 0x7584, 0x7585, 0x7587, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xaf */ 0x7588, 0x7589, 0x758a, 0x758c, 0x758d, 0x758e, 0x7590, 0x7593, 0x7595, 0x7598, 0x759b, 0x759c, 0x759e, 0x75a2, 0x75a6, 0x75a7, 0x75a8, 0x75a9, 0x75aa, 0x75ad, 0x75b6, 0x75b7, 0x75ba, 0x75bb, 0x75bf, 0x75c0, 0x75c1, 0x75c6, 0x75cb, 0x75cc, 0x75ce, 0x75cf, 0x75d0, 0x75d1, 0x75d3, 0x75d7, 0x75d9, 0x75da, 0x75dc, 0x75dd, 0x75df, 0x75e0, 0x75e1, 0x75e5, 0x75e9, 0x75ec, 0x75ed, 0x75ee, 0x75ef, 0x75f2, 0x75f3, 0x75f5, 0x75f6, 0x75f7, 0x75f8, 0x75fa, 0x75fb, 0x75fd, 0x75fe, 0x7602, 0x7604, 0x7606, 0x7607, 0x7608, 0x7609, 0x760b, 0x760d, 0x760e, 0x760f, 0x7611, 0x7612, 0x7613, 0x7614, 0x7616, 0x761a, 0x761c, 0x761d, 0x761e, 0x7621, 0x7623, 0x7627, 0x7628, 0x762c, 0x762e, 0x762f, 0x7631, 0x7632, 0x7636, 0x7637, 0x7639, 0x763a, 0x763b, 0x763d, 0x7641, 0x7642, 0x7644, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xb0 */ 0x7645, 0x7646, 0x7647, 0x7648, 0x7649, 0x764a, 0x764b, 0x764e, 0x764f, 0x7650, 0x7651, 0x7652, 0x7653, 0x7655, 0x7657, 0x7658, 0x7659, 0x765a, 0x765b, 0x765d, 0x765f, 0x7660, 0x7661, 0x7662, 0x7664, 0x7665, 0x7666, 0x7667, 0x7668, 0x7669, 0x766a, 0x766c, 0x766d, 0x766e, 0x7670, 0x7671, 0x7672, 0x7673, 0x7674, 0x7675, 0x7676, 0x7677, 0x7679, 0x767a, 0x767c, 0x767f, 0x7680, 0x7681, 0x7683, 0x7685, 0x7689, 0x768a, 0x768c, 0x768d, 0x768f, 0x7690, 0x7692, 0x7694, 0x7695, 0x7697, 0x7698, 0x769a, 0x769b, 0x769c, 0x769d, 0x769e, 0x769f, 0x76a0, 0x76a1, 0x76a2, 0x76a3, 0x76a5, 0x76a6, 0x76a7, 0x76a8, 0x76a9, 0x76aa, 0x76ab, 0x76ac, 0x76ad, 0x76af, 0x76b0, 0x76b3, 0x76b5, 0x76b6, 0x76b7, 0x76b8, 0x76b9, 0x76ba, 0x76bb, 0x76bc, 0x76bd, 0x76be, 0x76c0, 0x76c1, 0x76c3, 0x554a, 0x963f, 0x57c3, 0x6328, 0x54ce, 0x5509, 0x54c0, 0x7691, 0x764c, 0x853c, 0x77ee, 0x827e, 0x788d, 0x7231, 0x9698, 0x978d, 0x6c28, 0x5b89, 0x4ffa, 0x6309, 0x6697, 0x5cb8, 0x80fa, 0x6848, 0x80ae, 0x6602, 0x76ce, 0x51f9, 0x6556, 0x71ac, 0x7ff1, 0x8884, 0x50b2, 0x5965, 0x61ca, 0x6fb3, 0x82ad, 0x634c, 0x6252, 0x53ed, 0x5427, 0x7b06, 0x516b, 0x75a4, 0x5df4, 0x62d4, 0x8dcb, 0x9776, 0x628a, 0x8019, 0x575d, 0x9738, 0x7f62, 0x7238, 0x767d, 0x67cf, 0x767e, 0x6446, 0x4f70, 0x8d25, 0x62dc, 0x7a17, 0x6591, 0x73ed, 0x642c, 0x6273, 0x822c, 0x9881, 0x677f, 0x7248, 0x626e, 0x62cc, 0x4f34, 0x74e3, 0x534a, 0x529e, 0x7eca, 0x90a6, 0x5e2e, 0x6886, 0x699c, 0x8180, 0x7ed1, 0x68d2, 0x78c5, 0x868c, 0x9551, 0x508d, 0x8c24, 0x82de, 0x80de, 0x5305, 0x8912, 0x5265, /* 0xb1 */ 0x76c4, 0x76c7, 0x76c9, 0x76cb, 0x76cc, 0x76d3, 0x76d5, 0x76d9, 0x76da, 0x76dc, 0x76dd, 0x76de, 0x76e0, 0x76e1, 0x76e2, 0x76e3, 0x76e4, 0x76e6, 0x76e7, 0x76e8, 0x76e9, 0x76ea, 0x76eb, 0x76ec, 0x76ed, 0x76f0, 0x76f3, 0x76f5, 0x76f6, 0x76f7, 0x76fa, 0x76fb, 0x76fd, 0x76ff, 0x7700, 0x7702, 0x7703, 0x7705, 0x7706, 0x770a, 0x770c, 0x770e, 0x770f, 0x7710, 0x7711, 0x7712, 0x7713, 0x7714, 0x7715, 0x7716, 0x7717, 0x7718, 0x771b, 0x771c, 0x771d, 0x771e, 0x7721, 0x7723, 0x7724, 0x7725, 0x7727, 0x772a, 0x772b, 0x772c, 0x772e, 0x7730, 0x7731, 0x7732, 0x7733, 0x7734, 0x7739, 0x773b, 0x773d, 0x773e, 0x773f, 0x7742, 0x7744, 0x7745, 0x7746, 0x7748, 0x7749, 0x774a, 0x774b, 0x774c, 0x774d, 0x774e, 0x774f, 0x7752, 0x7753, 0x7754, 0x7755, 0x7756, 0x7757, 0x7758, 0x7759, 0x775c, 0x8584, 0x96f9, 0x4fdd, 0x5821, 0x9971, 0x5b9d, 0x62b1, 0x62a5, 0x66b4, 0x8c79, 0x9c8d, 0x7206, 0x676f, 0x7891, 0x60b2, 0x5351, 0x5317, 0x8f88, 0x80cc, 0x8d1d, 0x94a1, 0x500d, 0x72c8, 0x5907, 0x60eb, 0x7119, 0x88ab, 0x5954, 0x82ef, 0x672c, 0x7b28, 0x5d29, 0x7ef7, 0x752d, 0x6cf5, 0x8e66, 0x8ff8, 0x903c, 0x9f3b, 0x6bd4, 0x9119, 0x7b14, 0x5f7c, 0x78a7, 0x84d6, 0x853d, 0x6bd5, 0x6bd9, 0x6bd6, 0x5e01, 0x5e87, 0x75f9, 0x95ed, 0x655d, 0x5f0a, 0x5fc5, 0x8f9f, 0x58c1, 0x81c2, 0x907f, 0x965b, 0x97ad, 0x8fb9, 0x7f16, 0x8d2c, 0x6241, 0x4fbf, 0x53d8, 0x535e, 0x8fa8, 0x8fa9, 0x8fab, 0x904d, 0x6807, 0x5f6a, 0x8198, 0x8868, 0x9cd6, 0x618b, 0x522b, 0x762a, 0x5f6c, 0x658c, 0x6fd2, 0x6ee8, 0x5bbe, 0x6448, 0x5175, 0x51b0, 0x67c4, 0x4e19, 0x79c9, 0x997c, 0x70b3, /* 0xb2 */ 0x775d, 0x775e, 0x775f, 0x7760, 0x7764, 0x7767, 0x7769, 0x776a, 0x776d, 0x776e, 0x776f, 0x7770, 0x7771, 0x7772, 0x7773, 0x7774, 0x7775, 0x7776, 0x7777, 0x7778, 0x777a, 0x777b, 0x777c, 0x7781, 0x7782, 0x7783, 0x7786, 0x7787, 0x7788, 0x7789, 0x778a, 0x778b, 0x778f, 0x7790, 0x7793, 0x7794, 0x7795, 0x7796, 0x7797, 0x7798, 0x7799, 0x779a, 0x779b, 0x779c, 0x779d, 0x779e, 0x77a1, 0x77a3, 0x77a4, 0x77a6, 0x77a8, 0x77ab, 0x77ad, 0x77ae, 0x77af, 0x77b1, 0x77b2, 0x77b4, 0x77b6, 0x77b7, 0x77b8, 0x77b9, 0x77ba, 0x77bc, 0x77be, 0x77c0, 0x77c1, 0x77c2, 0x77c3, 0x77c4, 0x77c5, 0x77c6, 0x77c7, 0x77c8, 0x77c9, 0x77ca, 0x77cb, 0x77cc, 0x77ce, 0x77cf, 0x77d0, 0x77d1, 0x77d2, 0x77d3, 0x77d4, 0x77d5, 0x77d6, 0x77d8, 0x77d9, 0x77da, 0x77dd, 0x77de, 0x77df, 0x77e0, 0x77e1, 0x77e4, 0x75c5, 0x5e76, 0x73bb, 0x83e0, 0x64ad, 0x62e8, 0x94b5, 0x6ce2, 0x535a, 0x52c3, 0x640f, 0x94c2, 0x7b94, 0x4f2f, 0x5e1b, 0x8236, 0x8116, 0x818a, 0x6e24, 0x6cca, 0x9a73, 0x6355, 0x535c, 0x54fa, 0x8865, 0x57e0, 0x4e0d, 0x5e03, 0x6b65, 0x7c3f, 0x90e8, 0x6016, 0x64e6, 0x731c, 0x88c1, 0x6750, 0x624d, 0x8d22, 0x776c, 0x8e29, 0x91c7, 0x5f69, 0x83dc, 0x8521, 0x9910, 0x53c2, 0x8695, 0x6b8b, 0x60ed, 0x60e8, 0x707f, 0x82cd, 0x8231, 0x4ed3, 0x6ca7, 0x85cf, 0x64cd, 0x7cd9, 0x69fd, 0x66f9, 0x8349, 0x5395, 0x7b56, 0x4fa7, 0x518c, 0x6d4b, 0x5c42, 0x8e6d, 0x63d2, 0x53c9, 0x832c, 0x8336, 0x67e5, 0x78b4, 0x643d, 0x5bdf, 0x5c94, 0x5dee, 0x8be7, 0x62c6, 0x67f4, 0x8c7a, 0x6400, 0x63ba, 0x8749, 0x998b, 0x8c17, 0x7f20, 0x94f2, 0x4ea7, 0x9610, 0x98a4, 0x660c, 0x7316, /* 0xb3 */ 0x77e6, 0x77e8, 0x77ea, 0x77ef, 0x77f0, 0x77f1, 0x77f2, 0x77f4, 0x77f5, 0x77f7, 0x77f9, 0x77fa, 0x77fb, 0x77fc, 0x7803, 0x7804, 0x7805, 0x7806, 0x7807, 0x7808, 0x780a, 0x780b, 0x780e, 0x780f, 0x7810, 0x7813, 0x7815, 0x7819, 0x781b, 0x781e, 0x7820, 0x7821, 0x7822, 0x7824, 0x7828, 0x782a, 0x782b, 0x782e, 0x782f, 0x7831, 0x7832, 0x7833, 0x7835, 0x7836, 0x783d, 0x783f, 0x7841, 0x7842, 0x7843, 0x7844, 0x7846, 0x7848, 0x7849, 0x784a, 0x784b, 0x784d, 0x784f, 0x7851, 0x7853, 0x7854, 0x7858, 0x7859, 0x785a, 0x785b, 0x785c, 0x785e, 0x785f, 0x7860, 0x7861, 0x7862, 0x7863, 0x7864, 0x7865, 0x7866, 0x7867, 0x7868, 0x7869, 0x786f, 0x7870, 0x7871, 0x7872, 0x7873, 0x7874, 0x7875, 0x7876, 0x7878, 0x7879, 0x787a, 0x787b, 0x787d, 0x787e, 0x787f, 0x7880, 0x7881, 0x7882, 0x7883, 0x573a, 0x5c1d, 0x5e38, 0x957f, 0x507f, 0x80a0, 0x5382, 0x655e, 0x7545, 0x5531, 0x5021, 0x8d85, 0x6284, 0x949e, 0x671d, 0x5632, 0x6f6e, 0x5de2, 0x5435, 0x7092, 0x8f66, 0x626f, 0x64a4, 0x63a3, 0x5f7b, 0x6f88, 0x90f4, 0x81e3, 0x8fb0, 0x5c18, 0x6668, 0x5ff1, 0x6c89, 0x9648, 0x8d81, 0x886c, 0x6491, 0x79f0, 0x57ce, 0x6a59, 0x6210, 0x5448, 0x4e58, 0x7a0b, 0x60e9, 0x6f84, 0x8bda, 0x627f, 0x901e, 0x9a8b, 0x79e4, 0x5403, 0x75f4, 0x6301, 0x5319, 0x6c60, 0x8fdf, 0x5f1b, 0x9a70, 0x803b, 0x9f7f, 0x4f88, 0x5c3a, 0x8d64, 0x7fc5, 0x65a5, 0x70bd, 0x5145, 0x51b2, 0x866b, 0x5d07, 0x5ba0, 0x62bd, 0x916c, 0x7574, 0x8e0c, 0x7a20, 0x6101, 0x7b79, 0x4ec7, 0x7ef8, 0x7785, 0x4e11, 0x81ed, 0x521d, 0x51fa, 0x6a71, 0x53a8, 0x8e87, 0x9504, 0x96cf, 0x6ec1, 0x9664, 0x695a, /* 0xb4 */ 0x7884, 0x7885, 0x7886, 0x7888, 0x788a, 0x788b, 0x788f, 0x7890, 0x7892, 0x7894, 0x7895, 0x7896, 0x7899, 0x789d, 0x789e, 0x78a0, 0x78a2, 0x78a4, 0x78a6, 0x78a8, 0x78a9, 0x78aa, 0x78ab, 0x78ac, 0x78ad, 0x78ae, 0x78af, 0x78b5, 0x78b6, 0x78b7, 0x78b8, 0x78ba, 0x78bb, 0x78bc, 0x78bd, 0x78bf, 0x78c0, 0x78c2, 0x78c3, 0x78c4, 0x78c6, 0x78c7, 0x78c8, 0x78cc, 0x78cd, 0x78ce, 0x78cf, 0x78d1, 0x78d2, 0x78d3, 0x78d6, 0x78d7, 0x78d8, 0x78da, 0x78db, 0x78dc, 0x78dd, 0x78de, 0x78df, 0x78e0, 0x78e1, 0x78e2, 0x78e3, 0x78e4, 0x78e5, 0x78e6, 0x78e7, 0x78e9, 0x78ea, 0x78eb, 0x78ed, 0x78ee, 0x78ef, 0x78f0, 0x78f1, 0x78f3, 0x78f5, 0x78f6, 0x78f8, 0x78f9, 0x78fb, 0x78fc, 0x78fd, 0x78fe, 0x78ff, 0x7900, 0x7902, 0x7903, 0x7904, 0x7906, 0x7907, 0x7908, 0x7909, 0x790a, 0x790b, 0x790c, 0x7840, 0x50a8, 0x77d7, 0x6410, 0x89e6, 0x5904, 0x63e3, 0x5ddd, 0x7a7f, 0x693d, 0x4f20, 0x8239, 0x5598, 0x4e32, 0x75ae, 0x7a97, 0x5e62, 0x5e8a, 0x95ef, 0x521b, 0x5439, 0x708a, 0x6376, 0x9524, 0x5782, 0x6625, 0x693f, 0x9187, 0x5507, 0x6df3, 0x7eaf, 0x8822, 0x6233, 0x7ef0, 0x75b5, 0x8328, 0x78c1, 0x96cc, 0x8f9e, 0x6148, 0x74f7, 0x8bcd, 0x6b64, 0x523a, 0x8d50, 0x6b21, 0x806a, 0x8471, 0x56f1, 0x5306, 0x4ece, 0x4e1b, 0x51d1, 0x7c97, 0x918b, 0x7c07, 0x4fc3, 0x8e7f, 0x7be1, 0x7a9c, 0x6467, 0x5d14, 0x50ac, 0x8106, 0x7601, 0x7cb9, 0x6dec, 0x7fe0, 0x6751, 0x5b58, 0x5bf8, 0x78cb, 0x64ae, 0x6413, 0x63aa, 0x632b, 0x9519, 0x642d, 0x8fbe, 0x7b54, 0x7629, 0x6253, 0x5927, 0x5446, 0x6b79, 0x50a3, 0x6234, 0x5e26, 0x6b86, 0x4ee3, 0x8d37, 0x888b, 0x5f85, 0x902e, /* 0xb5 */ 0x790d, 0x790e, 0x790f, 0x7910, 0x7911, 0x7912, 0x7914, 0x7915, 0x7916, 0x7917, 0x7918, 0x7919, 0x791a, 0x791b, 0x791c, 0x791d, 0x791f, 0x7920, 0x7921, 0x7922, 0x7923, 0x7925, 0x7926, 0x7927, 0x7928, 0x7929, 0x792a, 0x792b, 0x792c, 0x792d, 0x792e, 0x792f, 0x7930, 0x7931, 0x7932, 0x7933, 0x7935, 0x7936, 0x7937, 0x7938, 0x7939, 0x793d, 0x793f, 0x7942, 0x7943, 0x7944, 0x7945, 0x7947, 0x794a, 0x794b, 0x794c, 0x794d, 0x794e, 0x794f, 0x7950, 0x7951, 0x7952, 0x7954, 0x7955, 0x7958, 0x7959, 0x7961, 0x7963, 0x7964, 0x7966, 0x7969, 0x796a, 0x796b, 0x796c, 0x796e, 0x7970, 0x7971, 0x7972, 0x7973, 0x7974, 0x7975, 0x7976, 0x7979, 0x797b, 0x797c, 0x797d, 0x797e, 0x797f, 0x7982, 0x7983, 0x7986, 0x7987, 0x7988, 0x7989, 0x798b, 0x798c, 0x798d, 0x798e, 0x7990, 0x7991, 0x7992, 0x6020, 0x803d, 0x62c5, 0x4e39, 0x5355, 0x90f8, 0x63b8, 0x80c6, 0x65e6, 0x6c2e, 0x4f46, 0x60ee, 0x6de1, 0x8bde, 0x5f39, 0x86cb, 0x5f53, 0x6321, 0x515a, 0x8361, 0x6863, 0x5200, 0x6363, 0x8e48, 0x5012, 0x5c9b, 0x7977, 0x5bfc, 0x5230, 0x7a3b, 0x60bc, 0x9053, 0x76d7, 0x5fb7, 0x5f97, 0x7684, 0x8e6c, 0x706f, 0x767b, 0x7b49, 0x77aa, 0x51f3, 0x9093, 0x5824, 0x4f4e, 0x6ef4, 0x8fea, 0x654c, 0x7b1b, 0x72c4, 0x6da4, 0x7fdf, 0x5ae1, 0x62b5, 0x5e95, 0x5730, 0x8482, 0x7b2c, 0x5e1d, 0x5f1f, 0x9012, 0x7f14, 0x98a0, 0x6382, 0x6ec7, 0x7898, 0x70b9, 0x5178, 0x975b, 0x57ab, 0x7535, 0x4f43, 0x7538, 0x5e97, 0x60e6, 0x5960, 0x6dc0, 0x6bbf, 0x7889, 0x53fc, 0x96d5, 0x51cb, 0x5201, 0x6389, 0x540a, 0x9493, 0x8c03, 0x8dcc, 0x7239, 0x789f, 0x8776, 0x8fed, 0x8c0d, 0x53e0, /* 0xb6 */ 0x7993, 0x7994, 0x7995, 0x7996, 0x7997, 0x7998, 0x7999, 0x799b, 0x799c, 0x799d, 0x799e, 0x799f, 0x79a0, 0x79a1, 0x79a2, 0x79a3, 0x79a4, 0x79a5, 0x79a6, 0x79a8, 0x79a9, 0x79aa, 0x79ab, 0x79ac, 0x79ad, 0x79ae, 0x79af, 0x79b0, 0x79b1, 0x79b2, 0x79b4, 0x79b5, 0x79b6, 0x79b7, 0x79b8, 0x79bc, 0x79bf, 0x79c2, 0x79c4, 0x79c5, 0x79c7, 0x79c8, 0x79ca, 0x79cc, 0x79ce, 0x79cf, 0x79d0, 0x79d3, 0x79d4, 0x79d6, 0x79d7, 0x79d9, 0x79da, 0x79db, 0x79dc, 0x79dd, 0x79de, 0x79e0, 0x79e1, 0x79e2, 0x79e5, 0x79e8, 0x79ea, 0x79ec, 0x79ee, 0x79f1, 0x79f2, 0x79f3, 0x79f4, 0x79f5, 0x79f6, 0x79f7, 0x79f9, 0x79fa, 0x79fc, 0x79fe, 0x79ff, 0x7a01, 0x7a04, 0x7a05, 0x7a07, 0x7a08, 0x7a09, 0x7a0a, 0x7a0c, 0x7a0f, 0x7a10, 0x7a11, 0x7a12, 0x7a13, 0x7a15, 0x7a16, 0x7a18, 0x7a19, 0x7a1b, 0x7a1c, 0x4e01, 0x76ef, 0x53ee, 0x9489, 0x9876, 0x9f0e, 0x952d, 0x5b9a, 0x8ba2, 0x4e22, 0x4e1c, 0x51ac, 0x8463, 0x61c2, 0x52a8, 0x680b, 0x4f97, 0x606b, 0x51bb, 0x6d1e, 0x515c, 0x6296, 0x6597, 0x9661, 0x8c46, 0x9017, 0x75d8, 0x90fd, 0x7763, 0x6bd2, 0x728a, 0x72ec, 0x8bfb, 0x5835, 0x7779, 0x8d4c, 0x675c, 0x9540, 0x809a, 0x5ea6, 0x6e21, 0x5992, 0x7aef, 0x77ed, 0x953b, 0x6bb5, 0x65ad, 0x7f0e, 0x5806, 0x5151, 0x961f, 0x5bf9, 0x58a9, 0x5428, 0x8e72, 0x6566, 0x987f, 0x56e4, 0x949d, 0x76fe, 0x9041, 0x6387, 0x54c6, 0x591a, 0x593a, 0x579b, 0x8eb2, 0x6735, 0x8dfa, 0x8235, 0x5241, 0x60f0, 0x5815, 0x86fe, 0x5ce8, 0x9e45, 0x4fc4, 0x989d, 0x8bb9, 0x5a25, 0x6076, 0x5384, 0x627c, 0x904f, 0x9102, 0x997f, 0x6069, 0x800c, 0x513f, 0x8033, 0x5c14, 0x9975, 0x6d31, 0x4e8c, /* 0xb7 */ 0x7a1d, 0x7a1f, 0x7a21, 0x7a22, 0x7a24, 0x7a25, 0x7a26, 0x7a27, 0x7a28, 0x7a29, 0x7a2a, 0x7a2b, 0x7a2c, 0x7a2d, 0x7a2e, 0x7a2f, 0x7a30, 0x7a31, 0x7a32, 0x7a34, 0x7a35, 0x7a36, 0x7a38, 0x7a3a, 0x7a3e, 0x7a40, 0x7a41, 0x7a42, 0x7a43, 0x7a44, 0x7a45, 0x7a47, 0x7a48, 0x7a49, 0x7a4a, 0x7a4b, 0x7a4c, 0x7a4d, 0x7a4e, 0x7a4f, 0x7a50, 0x7a52, 0x7a53, 0x7a54, 0x7a55, 0x7a56, 0x7a58, 0x7a59, 0x7a5a, 0x7a5b, 0x7a5c, 0x7a5d, 0x7a5e, 0x7a5f, 0x7a60, 0x7a61, 0x7a62, 0x7a63, 0x7a64, 0x7a65, 0x7a66, 0x7a67, 0x7a68, 0x7a69, 0x7a6a, 0x7a6b, 0x7a6c, 0x7a6d, 0x7a6e, 0x7a6f, 0x7a71, 0x7a72, 0x7a73, 0x7a75, 0x7a7b, 0x7a7c, 0x7a7d, 0x7a7e, 0x7a82, 0x7a85, 0x7a87, 0x7a89, 0x7a8a, 0x7a8b, 0x7a8c, 0x7a8e, 0x7a8f, 0x7a90, 0x7a93, 0x7a94, 0x7a99, 0x7a9a, 0x7a9b, 0x7a9e, 0x7aa1, 0x7aa2, 0x8d30, 0x53d1, 0x7f5a, 0x7b4f, 0x4f10, 0x4e4f, 0x9600, 0x6cd5, 0x73d0, 0x85e9, 0x5e06, 0x756a, 0x7ffb, 0x6a0a, 0x77fe, 0x9492, 0x7e41, 0x51e1, 0x70e6, 0x53cd, 0x8fd4, 0x8303, 0x8d29, 0x72af, 0x996d, 0x6cdb, 0x574a, 0x82b3, 0x65b9, 0x80aa, 0x623f, 0x9632, 0x59a8, 0x4eff, 0x8bbf, 0x7eba, 0x653e, 0x83f2, 0x975e, 0x5561, 0x98de, 0x80a5, 0x532a, 0x8bfd, 0x5420, 0x80ba, 0x5e9f, 0x6cb8, 0x8d39, 0x82ac, 0x915a, 0x5429, 0x6c1b, 0x5206, 0x7eb7, 0x575f, 0x711a, 0x6c7e, 0x7c89, 0x594b, 0x4efd, 0x5fff, 0x6124, 0x7caa, 0x4e30, 0x5c01, 0x67ab, 0x8702, 0x5cf0, 0x950b, 0x98ce, 0x75af, 0x70fd, 0x9022, 0x51af, 0x7f1d, 0x8bbd, 0x5949, 0x51e4, 0x4f5b, 0x5426, 0x592b, 0x6577, 0x80a4, 0x5b75, 0x6276, 0x62c2, 0x8f90, 0x5e45, 0x6c1f, 0x7b26, 0x4f0f, 0x4fd8, 0x670d, /* 0xb8 */ 0x7aa3, 0x7aa4, 0x7aa7, 0x7aa9, 0x7aaa, 0x7aab, 0x7aae, 0x7aaf, 0x7ab0, 0x7ab1, 0x7ab2, 0x7ab4, 0x7ab5, 0x7ab6, 0x7ab7, 0x7ab8, 0x7ab9, 0x7aba, 0x7abb, 0x7abc, 0x7abd, 0x7abe, 0x7ac0, 0x7ac1, 0x7ac2, 0x7ac3, 0x7ac4, 0x7ac5, 0x7ac6, 0x7ac7, 0x7ac8, 0x7ac9, 0x7aca, 0x7acc, 0x7acd, 0x7ace, 0x7acf, 0x7ad0, 0x7ad1, 0x7ad2, 0x7ad3, 0x7ad4, 0x7ad5, 0x7ad7, 0x7ad8, 0x7ada, 0x7adb, 0x7adc, 0x7add, 0x7ae1, 0x7ae2, 0x7ae4, 0x7ae7, 0x7ae8, 0x7ae9, 0x7aea, 0x7aeb, 0x7aec, 0x7aee, 0x7af0, 0x7af1, 0x7af2, 0x7af3, 0x7af4, 0x7af5, 0x7af6, 0x7af7, 0x7af8, 0x7afb, 0x7afc, 0x7afe, 0x7b00, 0x7b01, 0x7b02, 0x7b05, 0x7b07, 0x7b09, 0x7b0c, 0x7b0d, 0x7b0e, 0x7b10, 0x7b12, 0x7b13, 0x7b16, 0x7b17, 0x7b18, 0x7b1a, 0x7b1c, 0x7b1d, 0x7b1f, 0x7b21, 0x7b22, 0x7b23, 0x7b27, 0x7b29, 0x7b2d, 0x6d6e, 0x6daa, 0x798f, 0x88b1, 0x5f17, 0x752b, 0x629a, 0x8f85, 0x4fef, 0x91dc, 0x65a7, 0x812f, 0x8151, 0x5e9c, 0x8150, 0x8d74, 0x526f, 0x8986, 0x8d4b, 0x590d, 0x5085, 0x4ed8, 0x961c, 0x7236, 0x8179, 0x8d1f, 0x5bcc, 0x8ba3, 0x9644, 0x5987, 0x7f1a, 0x5490, 0x5676, 0x560e, 0x8be5, 0x6539, 0x6982, 0x9499, 0x76d6, 0x6e89, 0x5e72, 0x7518, 0x6746, 0x67d1, 0x7aff, 0x809d, 0x8d76, 0x611f, 0x79c6, 0x6562, 0x8d63, 0x5188, 0x521a, 0x94a2, 0x7f38, 0x809b, 0x7eb2, 0x5c97, 0x6e2f, 0x6760, 0x7bd9, 0x768b, 0x9ad8, 0x818f, 0x7f94, 0x7cd5, 0x641e, 0x9550, 0x7a3f, 0x544a, 0x54e5, 0x6b4c, 0x6401, 0x6208, 0x9e3d, 0x80f3, 0x7599, 0x5272, 0x9769, 0x845b, 0x683c, 0x86e4, 0x9601, 0x9694, 0x94ec, 0x4e2a, 0x5404, 0x7ed9, 0x6839, 0x8ddf, 0x8015, 0x66f4, 0x5e9a, 0x7fb9, /* 0xb9 */ 0x7b2f, 0x7b30, 0x7b32, 0x7b34, 0x7b35, 0x7b36, 0x7b37, 0x7b39, 0x7b3b, 0x7b3d, 0x7b3f, 0x7b40, 0x7b41, 0x7b42, 0x7b43, 0x7b44, 0x7b46, 0x7b48, 0x7b4a, 0x7b4d, 0x7b4e, 0x7b53, 0x7b55, 0x7b57, 0x7b59, 0x7b5c, 0x7b5e, 0x7b5f, 0x7b61, 0x7b63, 0x7b64, 0x7b65, 0x7b66, 0x7b67, 0x7b68, 0x7b69, 0x7b6a, 0x7b6b, 0x7b6c, 0x7b6d, 0x7b6f, 0x7b70, 0x7b73, 0x7b74, 0x7b76, 0x7b78, 0x7b7a, 0x7b7c, 0x7b7d, 0x7b7f, 0x7b81, 0x7b82, 0x7b83, 0x7b84, 0x7b86, 0x7b87, 0x7b88, 0x7b89, 0x7b8a, 0x7b8b, 0x7b8c, 0x7b8e, 0x7b8f, 0x7b91, 0x7b92, 0x7b93, 0x7b96, 0x7b98, 0x7b99, 0x7b9a, 0x7b9b, 0x7b9e, 0x7b9f, 0x7ba0, 0x7ba3, 0x7ba4, 0x7ba5, 0x7bae, 0x7baf, 0x7bb0, 0x7bb2, 0x7bb3, 0x7bb5, 0x7bb6, 0x7bb7, 0x7bb9, 0x7bba, 0x7bbb, 0x7bbc, 0x7bbd, 0x7bbe, 0x7bbf, 0x7bc0, 0x7bc2, 0x7bc3, 0x7bc4, 0x57c2, 0x803f, 0x6897, 0x5de5, 0x653b, 0x529f, 0x606d, 0x9f9a, 0x4f9b, 0x8eac, 0x516c, 0x5bab, 0x5f13, 0x5de9, 0x6c5e, 0x62f1, 0x8d21, 0x5171, 0x94a9, 0x52fe, 0x6c9f, 0x82df, 0x72d7, 0x57a2, 0x6784, 0x8d2d, 0x591f, 0x8f9c, 0x83c7, 0x5495, 0x7b8d, 0x4f30, 0x6cbd, 0x5b64, 0x59d1, 0x9f13, 0x53e4, 0x86ca, 0x9aa8, 0x8c37, 0x80a1, 0x6545, 0x987e, 0x56fa, 0x96c7, 0x522e, 0x74dc, 0x5250, 0x5be1, 0x6302, 0x8902, 0x4e56, 0x62d0, 0x602a, 0x68fa, 0x5173, 0x5b98, 0x51a0, 0x89c2, 0x7ba1, 0x9986, 0x7f50, 0x60ef, 0x704c, 0x8d2f, 0x5149, 0x5e7f, 0x901b, 0x7470, 0x89c4, 0x572d, 0x7845, 0x5f52, 0x9f9f, 0x95fa, 0x8f68, 0x9b3c, 0x8be1, 0x7678, 0x6842, 0x67dc, 0x8dea, 0x8d35, 0x523d, 0x8f8a, 0x6eda, 0x68cd, 0x9505, 0x90ed, 0x56fd, 0x679c, 0x88f9, 0x8fc7, 0x54c8, /* 0xba */ 0x7bc5, 0x7bc8, 0x7bc9, 0x7bca, 0x7bcb, 0x7bcd, 0x7bce, 0x7bcf, 0x7bd0, 0x7bd2, 0x7bd4, 0x7bd5, 0x7bd6, 0x7bd7, 0x7bd8, 0x7bdb, 0x7bdc, 0x7bde, 0x7bdf, 0x7be0, 0x7be2, 0x7be3, 0x7be4, 0x7be7, 0x7be8, 0x7be9, 0x7beb, 0x7bec, 0x7bed, 0x7bef, 0x7bf0, 0x7bf2, 0x7bf3, 0x7bf4, 0x7bf5, 0x7bf6, 0x7bf8, 0x7bf9, 0x7bfa, 0x7bfb, 0x7bfd, 0x7bff, 0x7c00, 0x7c01, 0x7c02, 0x7c03, 0x7c04, 0x7c05, 0x7c06, 0x7c08, 0x7c09, 0x7c0a, 0x7c0d, 0x7c0e, 0x7c10, 0x7c11, 0x7c12, 0x7c13, 0x7c14, 0x7c15, 0x7c17, 0x7c18, 0x7c19, 0x7c1a, 0x7c1b, 0x7c1c, 0x7c1d, 0x7c1e, 0x7c20, 0x7c21, 0x7c22, 0x7c23, 0x7c24, 0x7c25, 0x7c28, 0x7c29, 0x7c2b, 0x7c2c, 0x7c2d, 0x7c2e, 0x7c2f, 0x7c30, 0x7c31, 0x7c32, 0x7c33, 0x7c34, 0x7c35, 0x7c36, 0x7c37, 0x7c39, 0x7c3a, 0x7c3b, 0x7c3c, 0x7c3d, 0x7c3e, 0x7c42, 0x9ab8, 0x5b69, 0x6d77, 0x6c26, 0x4ea5, 0x5bb3, 0x9a87, 0x9163, 0x61a8, 0x90af, 0x97e9, 0x542b, 0x6db5, 0x5bd2, 0x51fd, 0x558a, 0x7f55, 0x7ff0, 0x64bc, 0x634d, 0x65f1, 0x61be, 0x608d, 0x710a, 0x6c57, 0x6c49, 0x592f, 0x676d, 0x822a, 0x58d5, 0x568e, 0x8c6a, 0x6beb, 0x90dd, 0x597d, 0x8017, 0x53f7, 0x6d69, 0x5475, 0x559d, 0x8377, 0x83cf, 0x6838, 0x79be, 0x548c, 0x4f55, 0x5408, 0x76d2, 0x8c89, 0x9602, 0x6cb3, 0x6db8, 0x8d6b, 0x8910, 0x9e64, 0x8d3a, 0x563f, 0x9ed1, 0x75d5, 0x5f88, 0x72e0, 0x6068, 0x54fc, 0x4ea8, 0x6a2a, 0x8861, 0x6052, 0x8f70, 0x54c4, 0x70d8, 0x8679, 0x9e3f, 0x6d2a, 0x5b8f, 0x5f18, 0x7ea2, 0x5589, 0x4faf, 0x7334, 0x543c, 0x539a, 0x5019, 0x540e, 0x547c, 0x4e4e, 0x5ffd, 0x745a, 0x58f6, 0x846b, 0x80e1, 0x8774, 0x72d0, 0x7cca, 0x6e56, /* 0xbb */ 0x7c43, 0x7c44, 0x7c45, 0x7c46, 0x7c47, 0x7c48, 0x7c49, 0x7c4a, 0x7c4b, 0x7c4c, 0x7c4e, 0x7c4f, 0x7c50, 0x7c51, 0x7c52, 0x7c53, 0x7c54, 0x7c55, 0x7c56, 0x7c57, 0x7c58, 0x7c59, 0x7c5a, 0x7c5b, 0x7c5c, 0x7c5d, 0x7c5e, 0x7c5f, 0x7c60, 0x7c61, 0x7c62, 0x7c63, 0x7c64, 0x7c65, 0x7c66, 0x7c67, 0x7c68, 0x7c69, 0x7c6a, 0x7c6b, 0x7c6c, 0x7c6d, 0x7c6e, 0x7c6f, 0x7c70, 0x7c71, 0x7c72, 0x7c75, 0x7c76, 0x7c77, 0x7c78, 0x7c79, 0x7c7a, 0x7c7e, 0x7c7f, 0x7c80, 0x7c81, 0x7c82, 0x7c83, 0x7c84, 0x7c85, 0x7c86, 0x7c87, 0x7c88, 0x7c8a, 0x7c8b, 0x7c8c, 0x7c8d, 0x7c8e, 0x7c8f, 0x7c90, 0x7c93, 0x7c94, 0x7c96, 0x7c99, 0x7c9a, 0x7c9b, 0x7ca0, 0x7ca1, 0x7ca3, 0x7ca6, 0x7ca7, 0x7ca8, 0x7ca9, 0x7cab, 0x7cac, 0x7cad, 0x7caf, 0x7cb0, 0x7cb4, 0x7cb5, 0x7cb6, 0x7cb7, 0x7cb8, 0x7cba, 0x7cbb, 0x5f27, 0x864e, 0x552c, 0x62a4, 0x4e92, 0x6caa, 0x6237, 0x82b1, 0x54d7, 0x534e, 0x733e, 0x6ed1, 0x753b, 0x5212, 0x5316, 0x8bdd, 0x69d0, 0x5f8a, 0x6000, 0x6dee, 0x574f, 0x6b22, 0x73af, 0x6853, 0x8fd8, 0x7f13, 0x6362, 0x60a3, 0x5524, 0x75ea, 0x8c62, 0x7115, 0x6da3, 0x5ba6, 0x5e7b, 0x8352, 0x614c, 0x9ec4, 0x78fa, 0x8757, 0x7c27, 0x7687, 0x51f0, 0x60f6, 0x714c, 0x6643, 0x5e4c, 0x604d, 0x8c0e, 0x7070, 0x6325, 0x8f89, 0x5fbd, 0x6062, 0x86d4, 0x56de, 0x6bc1, 0x6094, 0x6167, 0x5349, 0x60e0, 0x6666, 0x8d3f, 0x79fd, 0x4f1a, 0x70e9, 0x6c47, 0x8bb3, 0x8bf2, 0x7ed8, 0x8364, 0x660f, 0x5a5a, 0x9b42, 0x6d51, 0x6df7, 0x8c41, 0x6d3b, 0x4f19, 0x706b, 0x83b7, 0x6216, 0x60d1, 0x970d, 0x8d27, 0x7978, 0x51fb, 0x573e, 0x57fa, 0x673a, 0x7578, 0x7a3d, 0x79ef, 0x7b95, /* 0xbc */ 0x7cbf, 0x7cc0, 0x7cc2, 0x7cc3, 0x7cc4, 0x7cc6, 0x7cc9, 0x7ccb, 0x7cce, 0x7ccf, 0x7cd0, 0x7cd1, 0x7cd2, 0x7cd3, 0x7cd4, 0x7cd8, 0x7cda, 0x7cdb, 0x7cdd, 0x7cde, 0x7ce1, 0x7ce2, 0x7ce3, 0x7ce4, 0x7ce5, 0x7ce6, 0x7ce7, 0x7ce9, 0x7cea, 0x7ceb, 0x7cec, 0x7ced, 0x7cee, 0x7cf0, 0x7cf1, 0x7cf2, 0x7cf3, 0x7cf4, 0x7cf5, 0x7cf6, 0x7cf7, 0x7cf9, 0x7cfa, 0x7cfc, 0x7cfd, 0x7cfe, 0x7cff, 0x7d00, 0x7d01, 0x7d02, 0x7d03, 0x7d04, 0x7d05, 0x7d06, 0x7d07, 0x7d08, 0x7d09, 0x7d0b, 0x7d0c, 0x7d0d, 0x7d0e, 0x7d0f, 0x7d10, 0x7d11, 0x7d12, 0x7d13, 0x7d14, 0x7d15, 0x7d16, 0x7d17, 0x7d18, 0x7d19, 0x7d1a, 0x7d1b, 0x7d1c, 0x7d1d, 0x7d1e, 0x7d1f, 0x7d21, 0x7d23, 0x7d24, 0x7d25, 0x7d26, 0x7d28, 0x7d29, 0x7d2a, 0x7d2c, 0x7d2d, 0x7d2e, 0x7d30, 0x7d31, 0x7d32, 0x7d33, 0x7d34, 0x7d35, 0x7d36, 0x808c, 0x9965, 0x8ff9, 0x6fc0, 0x8ba5, 0x9e21, 0x59ec, 0x7ee9, 0x7f09, 0x5409, 0x6781, 0x68d8, 0x8f91, 0x7c4d, 0x96c6, 0x53ca, 0x6025, 0x75be, 0x6c72, 0x5373, 0x5ac9, 0x7ea7, 0x6324, 0x51e0, 0x810a, 0x5df1, 0x84df, 0x6280, 0x5180, 0x5b63, 0x4f0e, 0x796d, 0x5242, 0x60b8, 0x6d4e, 0x5bc4, 0x5bc2, 0x8ba1, 0x8bb0, 0x65e2, 0x5fcc, 0x9645, 0x5993, 0x7ee7, 0x7eaa, 0x5609, 0x67b7, 0x5939, 0x4f73, 0x5bb6, 0x52a0, 0x835a, 0x988a, 0x8d3e, 0x7532, 0x94be, 0x5047, 0x7a3c, 0x4ef7, 0x67b6, 0x9a7e, 0x5ac1, 0x6b7c, 0x76d1, 0x575a, 0x5c16, 0x7b3a, 0x95f4, 0x714e, 0x517c, 0x80a9, 0x8270, 0x5978, 0x7f04, 0x8327, 0x68c0, 0x67ec, 0x78b1, 0x7877, 0x62e3, 0x6361, 0x7b80, 0x4fed, 0x526a, 0x51cf, 0x8350, 0x69db, 0x9274, 0x8df5, 0x8d31, 0x89c1, 0x952e, 0x7bad, 0x4ef6, /* 0xbd */ 0x7d37, 0x7d38, 0x7d39, 0x7d3a, 0x7d3b, 0x7d3c, 0x7d3d, 0x7d3e, 0x7d3f, 0x7d40, 0x7d41, 0x7d42, 0x7d43, 0x7d44, 0x7d45, 0x7d46, 0x7d47, 0x7d48, 0x7d49, 0x7d4a, 0x7d4b, 0x7d4c, 0x7d4d, 0x7d4e, 0x7d4f, 0x7d50, 0x7d51, 0x7d52, 0x7d53, 0x7d54, 0x7d55, 0x7d56, 0x7d57, 0x7d58, 0x7d59, 0x7d5a, 0x7d5b, 0x7d5c, 0x7d5d, 0x7d5e, 0x7d5f, 0x7d60, 0x7d61, 0x7d62, 0x7d63, 0x7d64, 0x7d65, 0x7d66, 0x7d67, 0x7d68, 0x7d69, 0x7d6a, 0x7d6b, 0x7d6c, 0x7d6d, 0x7d6f, 0x7d70, 0x7d71, 0x7d72, 0x7d73, 0x7d74, 0x7d75, 0x7d76, 0x7d78, 0x7d79, 0x7d7a, 0x7d7b, 0x7d7c, 0x7d7d, 0x7d7e, 0x7d7f, 0x7d80, 0x7d81, 0x7d82, 0x7d83, 0x7d84, 0x7d85, 0x7d86, 0x7d87, 0x7d88, 0x7d89, 0x7d8a, 0x7d8b, 0x7d8c, 0x7d8d, 0x7d8e, 0x7d8f, 0x7d90, 0x7d91, 0x7d92, 0x7d93, 0x7d94, 0x7d95, 0x7d96, 0x7d97, 0x7d98, 0x5065, 0x8230, 0x5251, 0x996f, 0x6e10, 0x6e85, 0x6da7, 0x5efa, 0x50f5, 0x59dc, 0x5c06, 0x6d46, 0x6c5f, 0x7586, 0x848b, 0x6868, 0x5956, 0x8bb2, 0x5320, 0x9171, 0x964d, 0x8549, 0x6912, 0x7901, 0x7126, 0x80f6, 0x4ea4, 0x90ca, 0x6d47, 0x9a84, 0x5a07, 0x56bc, 0x6405, 0x94f0, 0x77eb, 0x4fa5, 0x811a, 0x72e1, 0x89d2, 0x997a, 0x7f34, 0x7ede, 0x527f, 0x6559, 0x9175, 0x8f7f, 0x8f83, 0x53eb, 0x7a96, 0x63ed, 0x63a5, 0x7686, 0x79f8, 0x8857, 0x9636, 0x622a, 0x52ab, 0x8282, 0x6854, 0x6770, 0x6377, 0x776b, 0x7aed, 0x6d01, 0x7ed3, 0x89e3, 0x59d0, 0x6212, 0x85c9, 0x82a5, 0x754c, 0x501f, 0x4ecb, 0x75a5, 0x8beb, 0x5c4a, 0x5dfe, 0x7b4b, 0x65a4, 0x91d1, 0x4eca, 0x6d25, 0x895f, 0x7d27, 0x9526, 0x4ec5, 0x8c28, 0x8fdb, 0x9773, 0x664b, 0x7981, 0x8fd1, 0x70ec, 0x6d78, /* 0xbe */ 0x7d99, 0x7d9a, 0x7d9b, 0x7d9c, 0x7d9d, 0x7d9e, 0x7d9f, 0x7da0, 0x7da1, 0x7da2, 0x7da3, 0x7da4, 0x7da5, 0x7da7, 0x7da8, 0x7da9, 0x7daa, 0x7dab, 0x7dac, 0x7dad, 0x7daf, 0x7db0, 0x7db1, 0x7db2, 0x7db3, 0x7db4, 0x7db5, 0x7db6, 0x7db7, 0x7db8, 0x7db9, 0x7dba, 0x7dbb, 0x7dbc, 0x7dbd, 0x7dbe, 0x7dbf, 0x7dc0, 0x7dc1, 0x7dc2, 0x7dc3, 0x7dc4, 0x7dc5, 0x7dc6, 0x7dc7, 0x7dc8, 0x7dc9, 0x7dca, 0x7dcb, 0x7dcc, 0x7dcd, 0x7dce, 0x7dcf, 0x7dd0, 0x7dd1, 0x7dd2, 0x7dd3, 0x7dd4, 0x7dd5, 0x7dd6, 0x7dd7, 0x7dd8, 0x7dd9, 0x7dda, 0x7ddb, 0x7ddc, 0x7ddd, 0x7dde, 0x7ddf, 0x7de0, 0x7de1, 0x7de2, 0x7de3, 0x7de4, 0x7de5, 0x7de6, 0x7de7, 0x7de8, 0x7de9, 0x7dea, 0x7deb, 0x7dec, 0x7ded, 0x7dee, 0x7def, 0x7df0, 0x7df1, 0x7df2, 0x7df3, 0x7df4, 0x7df5, 0x7df6, 0x7df7, 0x7df8, 0x7df9, 0x7dfa, 0x5c3d, 0x52b2, 0x8346, 0x5162, 0x830e, 0x775b, 0x6676, 0x9cb8, 0x4eac, 0x60ca, 0x7cbe, 0x7cb3, 0x7ecf, 0x4e95, 0x8b66, 0x666f, 0x9888, 0x9759, 0x5883, 0x656c, 0x955c, 0x5f84, 0x75c9, 0x9756, 0x7adf, 0x7ade, 0x51c0, 0x70af, 0x7a98, 0x63ea, 0x7a76, 0x7ea0, 0x7396, 0x97ed, 0x4e45, 0x7078, 0x4e5d, 0x9152, 0x53a9, 0x6551, 0x65e7, 0x81fc, 0x8205, 0x548e, 0x5c31, 0x759a, 0x97a0, 0x62d8, 0x72d9, 0x75bd, 0x5c45, 0x9a79, 0x83ca, 0x5c40, 0x5480, 0x77e9, 0x4e3e, 0x6cae, 0x805a, 0x62d2, 0x636e, 0x5de8, 0x5177, 0x8ddd, 0x8e1e, 0x952f, 0x4ff1, 0x53e5, 0x60e7, 0x70ac, 0x5267, 0x6350, 0x9e43, 0x5a1f, 0x5026, 0x7737, 0x5377, 0x7ee2, 0x6485, 0x652b, 0x6289, 0x6398, 0x5014, 0x7235, 0x89c9, 0x51b3, 0x8bc0, 0x7edd, 0x5747, 0x83cc, 0x94a7, 0x519b, 0x541b, 0x5cfb, /* 0xbf */ 0x7dfb, 0x7dfc, 0x7dfd, 0x7dfe, 0x7dff, 0x7e00, 0x7e01, 0x7e02, 0x7e03, 0x7e04, 0x7e05, 0x7e06, 0x7e07, 0x7e08, 0x7e09, 0x7e0a, 0x7e0b, 0x7e0c, 0x7e0d, 0x7e0e, 0x7e0f, 0x7e10, 0x7e11, 0x7e12, 0x7e13, 0x7e14, 0x7e15, 0x7e16, 0x7e17, 0x7e18, 0x7e19, 0x7e1a, 0x7e1b, 0x7e1c, 0x7e1d, 0x7e1e, 0x7e1f, 0x7e20, 0x7e21, 0x7e22, 0x7e23, 0x7e24, 0x7e25, 0x7e26, 0x7e27, 0x7e28, 0x7e29, 0x7e2a, 0x7e2b, 0x7e2c, 0x7e2d, 0x7e2e, 0x7e2f, 0x7e30, 0x7e31, 0x7e32, 0x7e33, 0x7e34, 0x7e35, 0x7e36, 0x7e37, 0x7e38, 0x7e39, 0x7e3a, 0x7e3c, 0x7e3d, 0x7e3e, 0x7e3f, 0x7e40, 0x7e42, 0x7e43, 0x7e44, 0x7e45, 0x7e46, 0x7e48, 0x7e49, 0x7e4a, 0x7e4b, 0x7e4c, 0x7e4d, 0x7e4e, 0x7e4f, 0x7e50, 0x7e51, 0x7e52, 0x7e53, 0x7e54, 0x7e55, 0x7e56, 0x7e57, 0x7e58, 0x7e59, 0x7e5a, 0x7e5b, 0x7e5c, 0x7e5d, 0x4fca, 0x7ae3, 0x6d5a, 0x90e1, 0x9a8f, 0x5580, 0x5496, 0x5361, 0x54af, 0x5f00, 0x63e9, 0x6977, 0x51ef, 0x6168, 0x520a, 0x582a, 0x52d8, 0x574e, 0x780d, 0x770b, 0x5eb7, 0x6177, 0x7ce0, 0x625b, 0x6297, 0x4ea2, 0x7095, 0x8003, 0x62f7, 0x70e4, 0x9760, 0x5777, 0x82db, 0x67ef, 0x68f5, 0x78d5, 0x9897, 0x79d1, 0x58f3, 0x54b3, 0x53ef, 0x6e34, 0x514b, 0x523b, 0x5ba2, 0x8bfe, 0x80af, 0x5543, 0x57a6, 0x6073, 0x5751, 0x542d, 0x7a7a, 0x6050, 0x5b54, 0x63a7, 0x62a0, 0x53e3, 0x6263, 0x5bc7, 0x67af, 0x54ed, 0x7a9f, 0x82e6, 0x9177, 0x5e93, 0x88e4, 0x5938, 0x57ae, 0x630e, 0x8de8, 0x80ef, 0x5757, 0x7b77, 0x4fa9, 0x5feb, 0x5bbd, 0x6b3e, 0x5321, 0x7b50, 0x72c2, 0x6846, 0x77ff, 0x7736, 0x65f7, 0x51b5, 0x4e8f, 0x76d4, 0x5cbf, 0x7aa5, 0x8475, 0x594e, 0x9b41, 0x5080, /* 0xc0 */ 0x7e5e, 0x7e5f, 0x7e60, 0x7e61, 0x7e62, 0x7e63, 0x7e64, 0x7e65, 0x7e66, 0x7e67, 0x7e68, 0x7e69, 0x7e6a, 0x7e6b, 0x7e6c, 0x7e6d, 0x7e6e, 0x7e6f, 0x7e70, 0x7e71, 0x7e72, 0x7e73, 0x7e74, 0x7e75, 0x7e76, 0x7e77, 0x7e78, 0x7e79, 0x7e7a, 0x7e7b, 0x7e7c, 0x7e7d, 0x7e7e, 0x7e7f, 0x7e80, 0x7e81, 0x7e83, 0x7e84, 0x7e85, 0x7e86, 0x7e87, 0x7e88, 0x7e89, 0x7e8a, 0x7e8b, 0x7e8c, 0x7e8d, 0x7e8e, 0x7e8f, 0x7e90, 0x7e91, 0x7e92, 0x7e93, 0x7e94, 0x7e95, 0x7e96, 0x7e97, 0x7e98, 0x7e99, 0x7e9a, 0x7e9c, 0x7e9d, 0x7e9e, 0x7eae, 0x7eb4, 0x7ebb, 0x7ebc, 0x7ed6, 0x7ee4, 0x7eec, 0x7ef9, 0x7f0a, 0x7f10, 0x7f1e, 0x7f37, 0x7f39, 0x7f3b, 0x7f3c, 0x7f3d, 0x7f3e, 0x7f3f, 0x7f40, 0x7f41, 0x7f43, 0x7f46, 0x7f47, 0x7f48, 0x7f49, 0x7f4a, 0x7f4b, 0x7f4c, 0x7f4d, 0x7f4e, 0x7f4f, 0x7f52, 0x7f53, 0x9988, 0x6127, 0x6e83, 0x5764, 0x6606, 0x6346, 0x56f0, 0x62ec, 0x6269, 0x5ed3, 0x9614, 0x5783, 0x62c9, 0x5587, 0x8721, 0x814a, 0x8fa3, 0x5566, 0x83b1, 0x6765, 0x8d56, 0x84dd, 0x5a6a, 0x680f, 0x62e6, 0x7bee, 0x9611, 0x5170, 0x6f9c, 0x8c30, 0x63fd, 0x89c8, 0x61d2, 0x7f06, 0x70c2, 0x6ee5, 0x7405, 0x6994, 0x72fc, 0x5eca, 0x90ce, 0x6717, 0x6d6a, 0x635e, 0x52b3, 0x7262, 0x8001, 0x4f6c, 0x59e5, 0x916a, 0x70d9, 0x6d9d, 0x52d2, 0x4e50, 0x96f7, 0x956d, 0x857e, 0x78ca, 0x7d2f, 0x5121, 0x5792, 0x64c2, 0x808b, 0x7c7b, 0x6cea, 0x68f1, 0x695e, 0x51b7, 0x5398, 0x68a8, 0x7281, 0x9ece, 0x7bf1, 0x72f8, 0x79bb, 0x6f13, 0x7406, 0x674e, 0x91cc, 0x9ca4, 0x793c, 0x8389, 0x8354, 0x540f, 0x6817, 0x4e3d, 0x5389, 0x52b1, 0x783e, 0x5386, 0x5229, 0x5088, 0x4f8b, 0x4fd0, /* 0xc1 */ 0x7f56, 0x7f59, 0x7f5b, 0x7f5c, 0x7f5d, 0x7f5e, 0x7f60, 0x7f63, 0x7f64, 0x7f65, 0x7f66, 0x7f67, 0x7f6b, 0x7f6c, 0x7f6d, 0x7f6f, 0x7f70, 0x7f73, 0x7f75, 0x7f76, 0x7f77, 0x7f78, 0x7f7a, 0x7f7b, 0x7f7c, 0x7f7d, 0x7f7f, 0x7f80, 0x7f82, 0x7f83, 0x7f84, 0x7f85, 0x7f86, 0x7f87, 0x7f88, 0x7f89, 0x7f8b, 0x7f8d, 0x7f8f, 0x7f90, 0x7f91, 0x7f92, 0x7f93, 0x7f95, 0x7f96, 0x7f97, 0x7f98, 0x7f99, 0x7f9b, 0x7f9c, 0x7fa0, 0x7fa2, 0x7fa3, 0x7fa5, 0x7fa6, 0x7fa8, 0x7fa9, 0x7faa, 0x7fab, 0x7fac, 0x7fad, 0x7fae, 0x7fb1, 0x7fb3, 0x7fb4, 0x7fb5, 0x7fb6, 0x7fb7, 0x7fba, 0x7fbb, 0x7fbe, 0x7fc0, 0x7fc2, 0x7fc3, 0x7fc4, 0x7fc6, 0x7fc7, 0x7fc8, 0x7fc9, 0x7fcb, 0x7fcd, 0x7fcf, 0x7fd0, 0x7fd1, 0x7fd2, 0x7fd3, 0x7fd6, 0x7fd7, 0x7fd9, 0x7fda, 0x7fdb, 0x7fdc, 0x7fdd, 0x7fde, 0x7fe2, 0x7fe3, 0x75e2, 0x7acb, 0x7c92, 0x6ca5, 0x96b6, 0x529b, 0x7483, 0x54e9, 0x4fe9, 0x8054, 0x83b2, 0x8fde, 0x9570, 0x5ec9, 0x601c, 0x6d9f, 0x5e18, 0x655b, 0x8138, 0x94fe, 0x604b, 0x70bc, 0x7ec3, 0x7cae, 0x51c9, 0x6881, 0x7cb1, 0x826f, 0x4e24, 0x8f86, 0x91cf, 0x667e, 0x4eae, 0x8c05, 0x64a9, 0x804a, 0x50da, 0x7597, 0x71ce, 0x5be5, 0x8fbd, 0x6f66, 0x4e86, 0x6482, 0x9563, 0x5ed6, 0x6599, 0x5217, 0x88c2, 0x70c8, 0x52a3, 0x730e, 0x7433, 0x6797, 0x78f7, 0x9716, 0x4e34, 0x90bb, 0x9cde, 0x6dcb, 0x51db, 0x8d41, 0x541d, 0x62ce, 0x73b2, 0x83f1, 0x96f6, 0x9f84, 0x94c3, 0x4f36, 0x7f9a, 0x51cc, 0x7075, 0x9675, 0x5cad, 0x9886, 0x53e6, 0x4ee4, 0x6e9c, 0x7409, 0x69b4, 0x786b, 0x998f, 0x7559, 0x5218, 0x7624, 0x6d41, 0x67f3, 0x516d, 0x9f99, 0x804b, 0x5499, 0x7b3c, 0x7abf, /* 0xc2 */ 0x7fe4, 0x7fe7, 0x7fe8, 0x7fea, 0x7feb, 0x7fec, 0x7fed, 0x7fef, 0x7ff2, 0x7ff4, 0x7ff5, 0x7ff6, 0x7ff7, 0x7ff8, 0x7ff9, 0x7ffa, 0x7ffd, 0x7ffe, 0x7fff, 0x8002, 0x8007, 0x8008, 0x8009, 0x800a, 0x800e, 0x800f, 0x8011, 0x8013, 0x801a, 0x801b, 0x801d, 0x801e, 0x801f, 0x8021, 0x8023, 0x8024, 0x802b, 0x802c, 0x802d, 0x802e, 0x802f, 0x8030, 0x8032, 0x8034, 0x8039, 0x803a, 0x803c, 0x803e, 0x8040, 0x8041, 0x8044, 0x8045, 0x8047, 0x8048, 0x8049, 0x804e, 0x804f, 0x8050, 0x8051, 0x8053, 0x8055, 0x8056, 0x8057, 0x8059, 0x805b, 0x805c, 0x805d, 0x805e, 0x805f, 0x8060, 0x8061, 0x8062, 0x8063, 0x8064, 0x8065, 0x8066, 0x8067, 0x8068, 0x806b, 0x806c, 0x806d, 0x806e, 0x806f, 0x8070, 0x8072, 0x8073, 0x8074, 0x8075, 0x8076, 0x8077, 0x8078, 0x8079, 0x807a, 0x807b, 0x807c, 0x807d, 0x9686, 0x5784, 0x62e2, 0x9647, 0x697c, 0x5a04, 0x6402, 0x7bd3, 0x6f0f, 0x964b, 0x82a6, 0x5362, 0x9885, 0x5e90, 0x7089, 0x63b3, 0x5364, 0x864f, 0x9c81, 0x9e93, 0x788c, 0x9732, 0x8def, 0x8d42, 0x9e7f, 0x6f5e, 0x7984, 0x5f55, 0x9646, 0x622e, 0x9a74, 0x5415, 0x94dd, 0x4fa3, 0x65c5, 0x5c65, 0x5c61, 0x7f15, 0x8651, 0x6c2f, 0x5f8b, 0x7387, 0x6ee4, 0x7eff, 0x5ce6, 0x631b, 0x5b6a, 0x6ee6, 0x5375, 0x4e71, 0x63a0, 0x7565, 0x62a1, 0x8f6e, 0x4f26, 0x4ed1, 0x6ca6, 0x7eb6, 0x8bba, 0x841d, 0x87ba, 0x7f57, 0x903b, 0x9523, 0x7ba9, 0x9aa1, 0x88f8, 0x843d, 0x6d1b, 0x9a86, 0x7edc, 0x5988, 0x9ebb, 0x739b, 0x7801, 0x8682, 0x9a6c, 0x9a82, 0x561b, 0x5417, 0x57cb, 0x4e70, 0x9ea6, 0x5356, 0x8fc8, 0x8109, 0x7792, 0x9992, 0x86ee, 0x6ee1, 0x8513, 0x66fc, 0x6162, 0x6f2b, /* 0xc3 */ 0x807e, 0x8081, 0x8082, 0x8085, 0x8088, 0x808a, 0x808d, 0x808e, 0x808f, 0x8090, 0x8091, 0x8092, 0x8094, 0x8095, 0x8097, 0x8099, 0x809e, 0x80a3, 0x80a6, 0x80a7, 0x80a8, 0x80ac, 0x80b0, 0x80b3, 0x80b5, 0x80b6, 0x80b8, 0x80b9, 0x80bb, 0x80c5, 0x80c7, 0x80c8, 0x80c9, 0x80ca, 0x80cb, 0x80cf, 0x80d0, 0x80d1, 0x80d2, 0x80d3, 0x80d4, 0x80d5, 0x80d8, 0x80df, 0x80e0, 0x80e2, 0x80e3, 0x80e6, 0x80ee, 0x80f5, 0x80f7, 0x80f9, 0x80fb, 0x80fe, 0x80ff, 0x8100, 0x8101, 0x8103, 0x8104, 0x8105, 0x8107, 0x8108, 0x810b, 0x810c, 0x8115, 0x8117, 0x8119, 0x811b, 0x811c, 0x811d, 0x811f, 0x8120, 0x8121, 0x8122, 0x8123, 0x8124, 0x8125, 0x8126, 0x8127, 0x8128, 0x8129, 0x812a, 0x812b, 0x812d, 0x812e, 0x8130, 0x8133, 0x8134, 0x8135, 0x8137, 0x8139, 0x813a, 0x813b, 0x813c, 0x813d, 0x813f, 0x8c29, 0x8292, 0x832b, 0x76f2, 0x6c13, 0x5fd9, 0x83bd, 0x732b, 0x8305, 0x951a, 0x6bdb, 0x77db, 0x94c6, 0x536f, 0x8302, 0x5192, 0x5e3d, 0x8c8c, 0x8d38, 0x4e48, 0x73ab, 0x679a, 0x6885, 0x9176, 0x9709, 0x7164, 0x6ca1, 0x7709, 0x5a92, 0x9541, 0x6bcf, 0x7f8e, 0x6627, 0x5bd0, 0x59b9, 0x5a9a, 0x95e8, 0x95f7, 0x4eec, 0x840c, 0x8499, 0x6aac, 0x76df, 0x9530, 0x731b, 0x68a6, 0x5b5f, 0x772f, 0x919a, 0x9761, 0x7cdc, 0x8ff7, 0x8c1c, 0x5f25, 0x7c73, 0x79d8, 0x89c5, 0x6ccc, 0x871c, 0x5bc6, 0x5e42, 0x68c9, 0x7720, 0x7ef5, 0x5195, 0x514d, 0x52c9, 0x5a29, 0x7f05, 0x9762, 0x82d7, 0x63cf, 0x7784, 0x85d0, 0x79d2, 0x6e3a, 0x5e99, 0x5999, 0x8511, 0x706d, 0x6c11, 0x62bf, 0x76bf, 0x654f, 0x60af, 0x95fd, 0x660e, 0x879f, 0x9e23, 0x94ed, 0x540d, 0x547d, 0x8c2c, 0x6478, /* 0xc4 */ 0x8140, 0x8141, 0x8142, 0x8143, 0x8144, 0x8145, 0x8147, 0x8149, 0x814d, 0x814e, 0x814f, 0x8152, 0x8156, 0x8157, 0x8158, 0x815b, 0x815c, 0x815d, 0x815e, 0x815f, 0x8161, 0x8162, 0x8163, 0x8164, 0x8166, 0x8168, 0x816a, 0x816b, 0x816c, 0x816f, 0x8172, 0x8173, 0x8175, 0x8176, 0x8177, 0x8178, 0x8181, 0x8183, 0x8184, 0x8185, 0x8186, 0x8187, 0x8189, 0x818b, 0x818c, 0x818d, 0x818e, 0x8190, 0x8192, 0x8193, 0x8194, 0x8195, 0x8196, 0x8197, 0x8199, 0x819a, 0x819e, 0x819f, 0x81a0, 0x81a1, 0x81a2, 0x81a4, 0x81a5, 0x81a7, 0x81a9, 0x81ab, 0x81ac, 0x81ad, 0x81ae, 0x81af, 0x81b0, 0x81b1, 0x81b2, 0x81b4, 0x81b5, 0x81b6, 0x81b7, 0x81b8, 0x81b9, 0x81bc, 0x81bd, 0x81be, 0x81bf, 0x81c4, 0x81c5, 0x81c7, 0x81c8, 0x81c9, 0x81cb, 0x81cd, 0x81ce, 0x81cf, 0x81d0, 0x81d1, 0x81d2, 0x81d3, 0x6479, 0x8611, 0x6a21, 0x819c, 0x78e8, 0x6469, 0x9b54, 0x62b9, 0x672b, 0x83ab, 0x58a8, 0x9ed8, 0x6cab, 0x6f20, 0x5bde, 0x964c, 0x8c0b, 0x725f, 0x67d0, 0x62c7, 0x7261, 0x4ea9, 0x59c6, 0x6bcd, 0x5893, 0x66ae, 0x5e55, 0x52df, 0x6155, 0x6728, 0x76ee, 0x7766, 0x7267, 0x7a46, 0x62ff, 0x54ea, 0x5450, 0x94a0, 0x90a3, 0x5a1c, 0x7eb3, 0x6c16, 0x4e43, 0x5976, 0x8010, 0x5948, 0x5357, 0x7537, 0x96be, 0x56ca, 0x6320, 0x8111, 0x607c, 0x95f9, 0x6dd6, 0x5462, 0x9981, 0x5185, 0x5ae9, 0x80fd, 0x59ae, 0x9713, 0x502a, 0x6ce5, 0x5c3c, 0x62df, 0x4f60, 0x533f, 0x817b, 0x9006, 0x6eba, 0x852b, 0x62c8, 0x5e74, 0x78be, 0x64b5, 0x637b, 0x5ff5, 0x5a18, 0x917f, 0x9e1f, 0x5c3f, 0x634f, 0x8042, 0x5b7d, 0x556e, 0x954a, 0x954d, 0x6d85, 0x60a8, 0x67e0, 0x72de, 0x51dd, 0x5b81, /* 0xc5 */ 0x81d4, 0x81d5, 0x81d6, 0x81d7, 0x81d8, 0x81d9, 0x81da, 0x81db, 0x81dc, 0x81dd, 0x81de, 0x81df, 0x81e0, 0x81e1, 0x81e2, 0x81e4, 0x81e5, 0x81e6, 0x81e8, 0x81e9, 0x81eb, 0x81ee, 0x81ef, 0x81f0, 0x81f1, 0x81f2, 0x81f5, 0x81f6, 0x81f7, 0x81f8, 0x81f9, 0x81fa, 0x81fd, 0x81ff, 0x8203, 0x8207, 0x8208, 0x8209, 0x820a, 0x820b, 0x820e, 0x820f, 0x8211, 0x8213, 0x8215, 0x8216, 0x8217, 0x8218, 0x8219, 0x821a, 0x821d, 0x8220, 0x8224, 0x8225, 0x8226, 0x8227, 0x8229, 0x822e, 0x8232, 0x823a, 0x823c, 0x823d, 0x823f, 0x8240, 0x8241, 0x8242, 0x8243, 0x8245, 0x8246, 0x8248, 0x824a, 0x824c, 0x824d, 0x824e, 0x8250, 0x8251, 0x8252, 0x8253, 0x8254, 0x8255, 0x8256, 0x8257, 0x8259, 0x825b, 0x825c, 0x825d, 0x825e, 0x8260, 0x8261, 0x8262, 0x8263, 0x8264, 0x8265, 0x8266, 0x8267, 0x8269, 0x62e7, 0x6cde, 0x725b, 0x626d, 0x94ae, 0x7ebd, 0x8113, 0x6d53, 0x519c, 0x5f04, 0x5974, 0x52aa, 0x6012, 0x5973, 0x6696, 0x8650, 0x759f, 0x632a, 0x61e6, 0x7cef, 0x8bfa, 0x54e6, 0x6b27, 0x9e25, 0x6bb4, 0x85d5, 0x5455, 0x5076, 0x6ca4, 0x556a, 0x8db4, 0x722c, 0x5e15, 0x6015, 0x7436, 0x62cd, 0x6392, 0x724c, 0x5f98, 0x6e43, 0x6d3e, 0x6500, 0x6f58, 0x76d8, 0x78d0, 0x76fc, 0x7554, 0x5224, 0x53db, 0x4e53, 0x5e9e, 0x65c1, 0x802a, 0x80d6, 0x629b, 0x5486, 0x5228, 0x70ae, 0x888d, 0x8dd1, 0x6ce1, 0x5478, 0x80da, 0x57f9, 0x88f4, 0x8d54, 0x966a, 0x914d, 0x4f69, 0x6c9b, 0x55b7, 0x76c6, 0x7830, 0x62a8, 0x70f9, 0x6f8e, 0x5f6d, 0x84ec, 0x68da, 0x787c, 0x7bf7, 0x81a8, 0x670b, 0x9e4f, 0x6367, 0x78b0, 0x576f, 0x7812, 0x9739, 0x6279, 0x62ab, 0x5288, 0x7435, 0x6bd7, /* 0xc6 */ 0x826a, 0x826b, 0x826c, 0x826d, 0x8271, 0x8275, 0x8276, 0x8277, 0x8278, 0x827b, 0x827c, 0x8280, 0x8281, 0x8283, 0x8285, 0x8286, 0x8287, 0x8289, 0x828c, 0x8290, 0x8293, 0x8294, 0x8295, 0x8296, 0x829a, 0x829b, 0x829e, 0x82a0, 0x82a2, 0x82a3, 0x82a7, 0x82b2, 0x82b5, 0x82b6, 0x82ba, 0x82bb, 0x82bc, 0x82bf, 0x82c0, 0x82c2, 0x82c3, 0x82c5, 0x82c6, 0x82c9, 0x82d0, 0x82d6, 0x82d9, 0x82da, 0x82dd, 0x82e2, 0x82e7, 0x82e8, 0x82e9, 0x82ea, 0x82ec, 0x82ed, 0x82ee, 0x82f0, 0x82f2, 0x82f3, 0x82f5, 0x82f6, 0x82f8, 0x82fa, 0x82fc, 0x82fd, 0x82fe, 0x82ff, 0x8300, 0x830a, 0x830b, 0x830d, 0x8310, 0x8312, 0x8313, 0x8316, 0x8318, 0x8319, 0x831d, 0x831e, 0x831f, 0x8320, 0x8321, 0x8322, 0x8323, 0x8324, 0x8325, 0x8326, 0x8329, 0x832a, 0x832e, 0x8330, 0x8332, 0x8337, 0x833b, 0x833d, 0x5564, 0x813e, 0x75b2, 0x76ae, 0x5339, 0x75de, 0x50fb, 0x5c41, 0x8b6c, 0x7bc7, 0x504f, 0x7247, 0x9a97, 0x98d8, 0x6f02, 0x74e2, 0x7968, 0x6487, 0x77a5, 0x62fc, 0x9891, 0x8d2b, 0x54c1, 0x8058, 0x4e52, 0x576a, 0x82f9, 0x840d, 0x5e73, 0x51ed, 0x74f6, 0x8bc4, 0x5c4f, 0x5761, 0x6cfc, 0x9887, 0x5a46, 0x7834, 0x9b44, 0x8feb, 0x7c95, 0x5256, 0x6251, 0x94fa, 0x4ec6, 0x8386, 0x8461, 0x83e9, 0x84b2, 0x57d4, 0x6734, 0x5703, 0x666e, 0x6d66, 0x8c31, 0x66dd, 0x7011, 0x671f, 0x6b3a, 0x6816, 0x621a, 0x59bb, 0x4e03, 0x51c4, 0x6f06, 0x67d2, 0x6c8f, 0x5176, 0x68cb, 0x5947, 0x6b67, 0x7566, 0x5d0e, 0x8110, 0x9f50, 0x65d7, 0x7948, 0x7941, 0x9a91, 0x8d77, 0x5c82, 0x4e5e, 0x4f01, 0x542f, 0x5951, 0x780c, 0x5668, 0x6c14, 0x8fc4, 0x5f03, 0x6c7d, 0x6ce3, 0x8bab, 0x6390, /* 0xc7 */ 0x833e, 0x833f, 0x8341, 0x8342, 0x8344, 0x8345, 0x8348, 0x834a, 0x834b, 0x834c, 0x834d, 0x834e, 0x8353, 0x8355, 0x8356, 0x8357, 0x8358, 0x8359, 0x835d, 0x8362, 0x8370, 0x8371, 0x8372, 0x8373, 0x8374, 0x8375, 0x8376, 0x8379, 0x837a, 0x837e, 0x837f, 0x8380, 0x8381, 0x8382, 0x8383, 0x8384, 0x8387, 0x8388, 0x838a, 0x838b, 0x838c, 0x838d, 0x838f, 0x8390, 0x8391, 0x8394, 0x8395, 0x8396, 0x8397, 0x8399, 0x839a, 0x839d, 0x839f, 0x83a1, 0x83a2, 0x83a3, 0x83a4, 0x83a5, 0x83a6, 0x83a7, 0x83ac, 0x83ad, 0x83ae, 0x83af, 0x83b5, 0x83bb, 0x83be, 0x83bf, 0x83c2, 0x83c3, 0x83c4, 0x83c6, 0x83c8, 0x83c9, 0x83cb, 0x83cd, 0x83ce, 0x83d0, 0x83d1, 0x83d2, 0x83d3, 0x83d5, 0x83d7, 0x83d9, 0x83da, 0x83db, 0x83de, 0x83e2, 0x83e3, 0x83e4, 0x83e6, 0x83e7, 0x83e8, 0x83eb, 0x83ec, 0x83ed, 0x6070, 0x6d3d, 0x7275, 0x6266, 0x948e, 0x94c5, 0x5343, 0x8fc1, 0x7b7e, 0x4edf, 0x8c26, 0x4e7e, 0x9ed4, 0x94b1, 0x94b3, 0x524d, 0x6f5c, 0x9063, 0x6d45, 0x8c34, 0x5811, 0x5d4c, 0x6b20, 0x6b49, 0x67aa, 0x545b, 0x8154, 0x7f8c, 0x5899, 0x8537, 0x5f3a, 0x62a2, 0x6a47, 0x9539, 0x6572, 0x6084, 0x6865, 0x77a7, 0x4e54, 0x4fa8, 0x5de7, 0x9798, 0x64ac, 0x7fd8, 0x5ced, 0x4fcf, 0x7a8d, 0x5207, 0x8304, 0x4e14, 0x602f, 0x7a83, 0x94a6, 0x4fb5, 0x4eb2, 0x79e6, 0x7434, 0x52e4, 0x82b9, 0x64d2, 0x79bd, 0x5bdd, 0x6c81, 0x9752, 0x8f7b, 0x6c22, 0x503e, 0x537f, 0x6e05, 0x64ce, 0x6674, 0x6c30, 0x60c5, 0x9877, 0x8bf7, 0x5e86, 0x743c, 0x7a77, 0x79cb, 0x4e18, 0x90b1, 0x7403, 0x6c42, 0x56da, 0x914b, 0x6cc5, 0x8d8b, 0x533a, 0x86c6, 0x66f2, 0x8eaf, 0x5c48, 0x9a71, 0x6e20, /* 0xc8 */ 0x83ee, 0x83ef, 0x83f3, 0x83f4, 0x83f5, 0x83f6, 0x83f7, 0x83fa, 0x83fb, 0x83fc, 0x83fe, 0x83ff, 0x8400, 0x8402, 0x8405, 0x8407, 0x8408, 0x8409, 0x840a, 0x8410, 0x8412, 0x8413, 0x8414, 0x8415, 0x8416, 0x8417, 0x8419, 0x841a, 0x841b, 0x841e, 0x841f, 0x8420, 0x8421, 0x8422, 0x8423, 0x8429, 0x842a, 0x842b, 0x842c, 0x842d, 0x842e, 0x842f, 0x8430, 0x8432, 0x8433, 0x8434, 0x8435, 0x8436, 0x8437, 0x8439, 0x843a, 0x843b, 0x843e, 0x843f, 0x8440, 0x8441, 0x8442, 0x8443, 0x8444, 0x8445, 0x8447, 0x8448, 0x8449, 0x844a, 0x844b, 0x844c, 0x844d, 0x844e, 0x844f, 0x8450, 0x8452, 0x8453, 0x8454, 0x8455, 0x8456, 0x8458, 0x845d, 0x845e, 0x845f, 0x8460, 0x8462, 0x8464, 0x8465, 0x8466, 0x8467, 0x8468, 0x846a, 0x846e, 0x846f, 0x8470, 0x8472, 0x8474, 0x8477, 0x8479, 0x847b, 0x847c, 0x53d6, 0x5a36, 0x9f8b, 0x8da3, 0x53bb, 0x5708, 0x98a7, 0x6743, 0x919b, 0x6cc9, 0x5168, 0x75ca, 0x62f3, 0x72ac, 0x5238, 0x529d, 0x7f3a, 0x7094, 0x7638, 0x5374, 0x9e4a, 0x69b7, 0x786e, 0x96c0, 0x88d9, 0x7fa4, 0x7136, 0x71c3, 0x5189, 0x67d3, 0x74e4, 0x58e4, 0x6518, 0x56b7, 0x8ba9, 0x9976, 0x6270, 0x7ed5, 0x60f9, 0x70ed, 0x58ec, 0x4ec1, 0x4eba, 0x5fcd, 0x97e7, 0x4efb, 0x8ba4, 0x5203, 0x598a, 0x7eab, 0x6254, 0x4ecd, 0x65e5, 0x620e, 0x8338, 0x84c9, 0x8363, 0x878d, 0x7194, 0x6eb6, 0x5bb9, 0x7ed2, 0x5197, 0x63c9, 0x67d4, 0x8089, 0x8339, 0x8815, 0x5112, 0x5b7a, 0x5982, 0x8fb1, 0x4e73, 0x6c5d, 0x5165, 0x8925, 0x8f6f, 0x962e, 0x854a, 0x745e, 0x9510, 0x95f0, 0x6da6, 0x82e5, 0x5f31, 0x6492, 0x6d12, 0x8428, 0x816e, 0x9cc3, 0x585e, 0x8d5b, 0x4e09, 0x53c1, /* 0xc9 */ 0x847d, 0x847e, 0x847f, 0x8480, 0x8481, 0x8483, 0x8484, 0x8485, 0x8486, 0x848a, 0x848d, 0x848f, 0x8490, 0x8491, 0x8492, 0x8493, 0x8494, 0x8495, 0x8496, 0x8498, 0x849a, 0x849b, 0x849d, 0x849e, 0x849f, 0x84a0, 0x84a2, 0x84a3, 0x84a4, 0x84a5, 0x84a6, 0x84a7, 0x84a8, 0x84a9, 0x84aa, 0x84ab, 0x84ac, 0x84ad, 0x84ae, 0x84b0, 0x84b1, 0x84b3, 0x84b5, 0x84b6, 0x84b7, 0x84bb, 0x84bc, 0x84be, 0x84c0, 0x84c2, 0x84c3, 0x84c5, 0x84c6, 0x84c7, 0x84c8, 0x84cb, 0x84cc, 0x84ce, 0x84cf, 0x84d2, 0x84d4, 0x84d5, 0x84d7, 0x84d8, 0x84d9, 0x84da, 0x84db, 0x84dc, 0x84de, 0x84e1, 0x84e2, 0x84e4, 0x84e7, 0x84e8, 0x84e9, 0x84ea, 0x84eb, 0x84ed, 0x84ee, 0x84ef, 0x84f1, 0x84f2, 0x84f3, 0x84f4, 0x84f5, 0x84f6, 0x84f7, 0x84f8, 0x84f9, 0x84fa, 0x84fb, 0x84fd, 0x84fe, 0x8500, 0x8501, 0x8502, 0x4f1e, 0x6563, 0x6851, 0x55d3, 0x4e27, 0x6414, 0x9a9a, 0x626b, 0x5ac2, 0x745f, 0x8272, 0x6da9, 0x68ee, 0x50e7, 0x838e, 0x7802, 0x6740, 0x5239, 0x6c99, 0x7eb1, 0x50bb, 0x5565, 0x715e, 0x7b5b, 0x6652, 0x73ca, 0x82eb, 0x6749, 0x5c71, 0x5220, 0x717d, 0x886b, 0x95ea, 0x9655, 0x64c5, 0x8d61, 0x81b3, 0x5584, 0x6c55, 0x6247, 0x7f2e, 0x5892, 0x4f24, 0x5546, 0x8d4f, 0x664c, 0x4e0a, 0x5c1a, 0x88f3, 0x68a2, 0x634e, 0x7a0d, 0x70e7, 0x828d, 0x52fa, 0x97f6, 0x5c11, 0x54e8, 0x90b5, 0x7ecd, 0x5962, 0x8d4a, 0x86c7, 0x820c, 0x820d, 0x8d66, 0x6444, 0x5c04, 0x6151, 0x6d89, 0x793e, 0x8bbe, 0x7837, 0x7533, 0x547b, 0x4f38, 0x8eab, 0x6df1, 0x5a20, 0x7ec5, 0x795e, 0x6c88, 0x5ba1, 0x5a76, 0x751a, 0x80be, 0x614e, 0x6e17, 0x58f0, 0x751f, 0x7525, 0x7272, 0x5347, 0x7ef3, /* 0xca */ 0x8503, 0x8504, 0x8505, 0x8506, 0x8507, 0x8508, 0x8509, 0x850a, 0x850b, 0x850d, 0x850e, 0x850f, 0x8510, 0x8512, 0x8514, 0x8515, 0x8516, 0x8518, 0x8519, 0x851b, 0x851c, 0x851d, 0x851e, 0x8520, 0x8522, 0x8523, 0x8524, 0x8525, 0x8526, 0x8527, 0x8528, 0x8529, 0x852a, 0x852d, 0x852e, 0x852f, 0x8530, 0x8531, 0x8532, 0x8533, 0x8534, 0x8535, 0x8536, 0x853e, 0x853f, 0x8540, 0x8541, 0x8542, 0x8544, 0x8545, 0x8546, 0x8547, 0x854b, 0x854c, 0x854d, 0x854e, 0x854f, 0x8550, 0x8551, 0x8552, 0x8553, 0x8554, 0x8555, 0x8557, 0x8558, 0x855a, 0x855b, 0x855c, 0x855d, 0x855f, 0x8560, 0x8561, 0x8562, 0x8563, 0x8565, 0x8566, 0x8567, 0x8569, 0x856a, 0x856b, 0x856c, 0x856d, 0x856e, 0x856f, 0x8570, 0x8571, 0x8573, 0x8575, 0x8576, 0x8577, 0x8578, 0x857c, 0x857d, 0x857f, 0x8580, 0x8581, 0x7701, 0x76db, 0x5269, 0x80dc, 0x5723, 0x5e08, 0x5931, 0x72ee, 0x65bd, 0x6e7f, 0x8bd7, 0x5c38, 0x8671, 0x5341, 0x77f3, 0x62fe, 0x65f6, 0x4ec0, 0x98df, 0x8680, 0x5b9e, 0x8bc6, 0x53f2, 0x77e2, 0x4f7f, 0x5c4e, 0x9a76, 0x59cb, 0x5f0f, 0x793a, 0x58eb, 0x4e16, 0x67ff, 0x4e8b, 0x62ed, 0x8a93, 0x901d, 0x52bf, 0x662f, 0x55dc, 0x566c, 0x9002, 0x4ed5, 0x4f8d, 0x91ca, 0x9970, 0x6c0f, 0x5e02, 0x6043, 0x5ba4, 0x89c6, 0x8bd5, 0x6536, 0x624b, 0x9996, 0x5b88, 0x5bff, 0x6388, 0x552e, 0x53d7, 0x7626, 0x517d, 0x852c, 0x67a2, 0x68b3, 0x6b8a, 0x6292, 0x8f93, 0x53d4, 0x8212, 0x6dd1, 0x758f, 0x4e66, 0x8d4e, 0x5b70, 0x719f, 0x85af, 0x6691, 0x66d9, 0x7f72, 0x8700, 0x9ecd, 0x9f20, 0x5c5e, 0x672f, 0x8ff0, 0x6811, 0x675f, 0x620d, 0x7ad6, 0x5885, 0x5eb6, 0x6570, 0x6f31, /* 0xcb */ 0x8582, 0x8583, 0x8586, 0x8588, 0x8589, 0x858a, 0x858b, 0x858c, 0x858d, 0x858e, 0x8590, 0x8591, 0x8592, 0x8593, 0x8594, 0x8595, 0x8596, 0x8597, 0x8598, 0x8599, 0x859a, 0x859d, 0x859e, 0x859f, 0x85a0, 0x85a1, 0x85a2, 0x85a3, 0x85a5, 0x85a6, 0x85a7, 0x85a9, 0x85ab, 0x85ac, 0x85ad, 0x85b1, 0x85b2, 0x85b3, 0x85b4, 0x85b5, 0x85b6, 0x85b8, 0x85ba, 0x85bb, 0x85bc, 0x85bd, 0x85be, 0x85bf, 0x85c0, 0x85c2, 0x85c3, 0x85c4, 0x85c5, 0x85c6, 0x85c7, 0x85c8, 0x85ca, 0x85cb, 0x85cc, 0x85cd, 0x85ce, 0x85d1, 0x85d2, 0x85d4, 0x85d6, 0x85d7, 0x85d8, 0x85d9, 0x85da, 0x85db, 0x85dd, 0x85de, 0x85df, 0x85e0, 0x85e1, 0x85e2, 0x85e3, 0x85e5, 0x85e6, 0x85e7, 0x85e8, 0x85ea, 0x85eb, 0x85ec, 0x85ed, 0x85ee, 0x85ef, 0x85f0, 0x85f1, 0x85f2, 0x85f3, 0x85f4, 0x85f5, 0x85f6, 0x85f7, 0x85f8, 0x6055, 0x5237, 0x800d, 0x6454, 0x8870, 0x7529, 0x5e05, 0x6813, 0x62f4, 0x971c, 0x53cc, 0x723d, 0x8c01, 0x6c34, 0x7761, 0x7a0e, 0x542e, 0x77ac, 0x987a, 0x821c, 0x8bf4, 0x7855, 0x6714, 0x70c1, 0x65af, 0x6495, 0x5636, 0x601d, 0x79c1, 0x53f8, 0x4e1d, 0x6b7b, 0x8086, 0x5bfa, 0x55e3, 0x56db, 0x4f3a, 0x4f3c, 0x9972, 0x5df3, 0x677e, 0x8038, 0x6002, 0x9882, 0x9001, 0x5b8b, 0x8bbc, 0x8bf5, 0x641c, 0x8258, 0x64de, 0x55fd, 0x82cf, 0x9165, 0x4fd7, 0x7d20, 0x901f, 0x7c9f, 0x50f3, 0x5851, 0x6eaf, 0x5bbf, 0x8bc9, 0x8083, 0x9178, 0x849c, 0x7b97, 0x867d, 0x968b, 0x968f, 0x7ee5, 0x9ad3, 0x788e, 0x5c81, 0x7a57, 0x9042, 0x96a7, 0x795f, 0x5b59, 0x635f, 0x7b0b, 0x84d1, 0x68ad, 0x5506, 0x7f29, 0x7410, 0x7d22, 0x9501, 0x6240, 0x584c, 0x4ed6, 0x5b83, 0x5979, 0x5854, /* 0xcc */ 0x85f9, 0x85fa, 0x85fc, 0x85fd, 0x85fe, 0x8600, 0x8601, 0x8602, 0x8603, 0x8604, 0x8606, 0x8607, 0x8608, 0x8609, 0x860a, 0x860b, 0x860c, 0x860d, 0x860e, 0x860f, 0x8610, 0x8612, 0x8613, 0x8614, 0x8615, 0x8617, 0x8618, 0x8619, 0x861a, 0x861b, 0x861c, 0x861d, 0x861e, 0x861f, 0x8620, 0x8621, 0x8622, 0x8623, 0x8624, 0x8625, 0x8626, 0x8628, 0x862a, 0x862b, 0x862c, 0x862d, 0x862e, 0x862f, 0x8630, 0x8631, 0x8632, 0x8633, 0x8634, 0x8635, 0x8636, 0x8637, 0x8639, 0x863a, 0x863b, 0x863d, 0x863e, 0x863f, 0x8640, 0x8641, 0x8642, 0x8643, 0x8644, 0x8645, 0x8646, 0x8647, 0x8648, 0x8649, 0x864a, 0x864b, 0x864c, 0x8652, 0x8653, 0x8655, 0x8656, 0x8657, 0x8658, 0x8659, 0x865b, 0x865c, 0x865d, 0x865f, 0x8660, 0x8661, 0x8663, 0x8664, 0x8665, 0x8666, 0x8667, 0x8668, 0x8669, 0x866a, 0x736d, 0x631e, 0x8e4b, 0x8e0f, 0x80ce, 0x82d4, 0x62ac, 0x53f0, 0x6cf0, 0x915e, 0x592a, 0x6001, 0x6c70, 0x574d, 0x644a, 0x8d2a, 0x762b, 0x6ee9, 0x575b, 0x6a80, 0x75f0, 0x6f6d, 0x8c2d, 0x8c08, 0x5766, 0x6bef, 0x8892, 0x78b3, 0x63a2, 0x53f9, 0x70ad, 0x6c64, 0x5858, 0x642a, 0x5802, 0x68e0, 0x819b, 0x5510, 0x7cd6, 0x5018, 0x8eba, 0x6dcc, 0x8d9f, 0x70eb, 0x638f, 0x6d9b, 0x6ed4, 0x7ee6, 0x8404, 0x6843, 0x9003, 0x6dd8, 0x9676, 0x8ba8, 0x5957, 0x7279, 0x85e4, 0x817e, 0x75bc, 0x8a8a, 0x68af, 0x5254, 0x8e22, 0x9511, 0x63d0, 0x9898, 0x8e44, 0x557c, 0x4f53, 0x66ff, 0x568f, 0x60d5, 0x6d95, 0x5243, 0x5c49, 0x5929, 0x6dfb, 0x586b, 0x7530, 0x751c, 0x606c, 0x8214, 0x8146, 0x6311, 0x6761, 0x8fe2, 0x773a, 0x8df3, 0x8d34, 0x94c1, 0x5e16, 0x5385, 0x542c, 0x70c3, /* 0xcd */ 0x866d, 0x866f, 0x8670, 0x8672, 0x8673, 0x8674, 0x8675, 0x8676, 0x8677, 0x8678, 0x8683, 0x8684, 0x8685, 0x8686, 0x8687, 0x8688, 0x8689, 0x868e, 0x868f, 0x8690, 0x8691, 0x8692, 0x8694, 0x8696, 0x8697, 0x8698, 0x8699, 0x869a, 0x869b, 0x869e, 0x869f, 0x86a0, 0x86a1, 0x86a2, 0x86a5, 0x86a6, 0x86ab, 0x86ad, 0x86ae, 0x86b2, 0x86b3, 0x86b7, 0x86b8, 0x86b9, 0x86bb, 0x86bc, 0x86bd, 0x86be, 0x86bf, 0x86c1, 0x86c2, 0x86c3, 0x86c5, 0x86c8, 0x86cc, 0x86cd, 0x86d2, 0x86d3, 0x86d5, 0x86d6, 0x86d7, 0x86da, 0x86dc, 0x86dd, 0x86e0, 0x86e1, 0x86e2, 0x86e3, 0x86e5, 0x86e6, 0x86e7, 0x86e8, 0x86ea, 0x86eb, 0x86ec, 0x86ef, 0x86f5, 0x86f6, 0x86f7, 0x86fa, 0x86fb, 0x86fc, 0x86fd, 0x86ff, 0x8701, 0x8704, 0x8705, 0x8706, 0x870b, 0x870c, 0x870e, 0x870f, 0x8710, 0x8711, 0x8714, 0x8716, 0x6c40, 0x5ef7, 0x505c, 0x4ead, 0x5ead, 0x633a, 0x8247, 0x901a, 0x6850, 0x916e, 0x77b3, 0x540c, 0x94dc, 0x5f64, 0x7ae5, 0x6876, 0x6345, 0x7b52, 0x7edf, 0x75db, 0x5077, 0x6295, 0x5934, 0x900f, 0x51f8, 0x79c3, 0x7a81, 0x56fe, 0x5f92, 0x9014, 0x6d82, 0x5c60, 0x571f, 0x5410, 0x5154, 0x6e4d, 0x56e2, 0x63a8, 0x9893, 0x817f, 0x8715, 0x892a, 0x9000, 0x541e, 0x5c6f, 0x81c0, 0x62d6, 0x6258, 0x8131, 0x9e35, 0x9640, 0x9a6e, 0x9a7c, 0x692d, 0x59a5, 0x62d3, 0x553e, 0x6316, 0x54c7, 0x86d9, 0x6d3c, 0x5a03, 0x74e6, 0x889c, 0x6b6a, 0x5916, 0x8c4c, 0x5f2f, 0x6e7e, 0x73a9, 0x987d, 0x4e38, 0x70f7, 0x5b8c, 0x7897, 0x633d, 0x665a, 0x7696, 0x60cb, 0x5b9b, 0x5a49, 0x4e07, 0x8155, 0x6c6a, 0x738b, 0x4ea1, 0x6789, 0x7f51, 0x5f80, 0x65fa, 0x671b, 0x5fd8, 0x5984, 0x5a01, /* 0xce */ 0x8719, 0x871b, 0x871d, 0x871f, 0x8720, 0x8724, 0x8726, 0x8727, 0x8728, 0x872a, 0x872b, 0x872c, 0x872d, 0x872f, 0x8730, 0x8732, 0x8733, 0x8735, 0x8736, 0x8738, 0x8739, 0x873a, 0x873c, 0x873d, 0x8740, 0x8741, 0x8742, 0x8743, 0x8744, 0x8745, 0x8746, 0x874a, 0x874b, 0x874d, 0x874f, 0x8750, 0x8751, 0x8752, 0x8754, 0x8755, 0x8756, 0x8758, 0x875a, 0x875b, 0x875c, 0x875d, 0x875e, 0x875f, 0x8761, 0x8762, 0x8766, 0x8767, 0x8768, 0x8769, 0x876a, 0x876b, 0x876c, 0x876d, 0x876f, 0x8771, 0x8772, 0x8773, 0x8775, 0x8777, 0x8778, 0x8779, 0x877a, 0x877f, 0x8780, 0x8781, 0x8784, 0x8786, 0x8787, 0x8789, 0x878a, 0x878c, 0x878e, 0x878f, 0x8790, 0x8791, 0x8792, 0x8794, 0x8795, 0x8796, 0x8798, 0x8799, 0x879a, 0x879b, 0x879c, 0x879d, 0x879e, 0x87a0, 0x87a1, 0x87a2, 0x87a3, 0x87a4, 0x5dcd, 0x5fae, 0x5371, 0x97e6, 0x8fdd, 0x6845, 0x56f4, 0x552f, 0x60df, 0x4e3a, 0x6f4d, 0x7ef4, 0x82c7, 0x840e, 0x59d4, 0x4f1f, 0x4f2a, 0x5c3e, 0x7eac, 0x672a, 0x851a, 0x5473, 0x754f, 0x80c3, 0x5582, 0x9b4f, 0x4f4d, 0x6e2d, 0x8c13, 0x5c09, 0x6170, 0x536b, 0x761f, 0x6e29, 0x868a, 0x6587, 0x95fb, 0x7eb9, 0x543b, 0x7a33, 0x7d0a, 0x95ee, 0x55e1, 0x7fc1, 0x74ee, 0x631d, 0x8717, 0x6da1, 0x7a9d, 0x6211, 0x65a1, 0x5367, 0x63e1, 0x6c83, 0x5deb, 0x545c, 0x94a8, 0x4e4c, 0x6c61, 0x8bec, 0x5c4b, 0x65e0, 0x829c, 0x68a7, 0x543e, 0x5434, 0x6bcb, 0x6b66, 0x4e94, 0x6342, 0x5348, 0x821e, 0x4f0d, 0x4fae, 0x575e, 0x620a, 0x96fe, 0x6664, 0x7269, 0x52ff, 0x52a1, 0x609f, 0x8bef, 0x6614, 0x7199, 0x6790, 0x897f, 0x7852, 0x77fd, 0x6670, 0x563b, 0x5438, 0x9521, 0x727a, /* 0xcf */ 0x87a5, 0x87a6, 0x87a7, 0x87a9, 0x87aa, 0x87ae, 0x87b0, 0x87b1, 0x87b2, 0x87b4, 0x87b6, 0x87b7, 0x87b8, 0x87b9, 0x87bb, 0x87bc, 0x87be, 0x87bf, 0x87c1, 0x87c2, 0x87c3, 0x87c4, 0x87c5, 0x87c7, 0x87c8, 0x87c9, 0x87cc, 0x87cd, 0x87ce, 0x87cf, 0x87d0, 0x87d4, 0x87d5, 0x87d6, 0x87d7, 0x87d8, 0x87d9, 0x87da, 0x87dc, 0x87dd, 0x87de, 0x87df, 0x87e1, 0x87e2, 0x87e3, 0x87e4, 0x87e6, 0x87e7, 0x87e8, 0x87e9, 0x87eb, 0x87ec, 0x87ed, 0x87ef, 0x87f0, 0x87f1, 0x87f2, 0x87f3, 0x87f4, 0x87f5, 0x87f6, 0x87f7, 0x87f8, 0x87fa, 0x87fb, 0x87fc, 0x87fd, 0x87ff, 0x8800, 0x8801, 0x8802, 0x8804, 0x8805, 0x8806, 0x8807, 0x8808, 0x8809, 0x880b, 0x880c, 0x880d, 0x880e, 0x880f, 0x8810, 0x8811, 0x8812, 0x8814, 0x8817, 0x8818, 0x8819, 0x881a, 0x881c, 0x881d, 0x881e, 0x881f, 0x8820, 0x8823, 0x7a00, 0x606f, 0x5e0c, 0x6089, 0x819d, 0x5915, 0x60dc, 0x7184, 0x70ef, 0x6eaa, 0x6c50, 0x7280, 0x6a84, 0x88ad, 0x5e2d, 0x4e60, 0x5ab3, 0x559c, 0x94e3, 0x6d17, 0x7cfb, 0x9699, 0x620f, 0x7ec6, 0x778e, 0x867e, 0x5323, 0x971e, 0x8f96, 0x6687, 0x5ce1, 0x4fa0, 0x72ed, 0x4e0b, 0x53a6, 0x590f, 0x5413, 0x6380, 0x9528, 0x5148, 0x4ed9, 0x9c9c, 0x7ea4, 0x54b8, 0x8d24, 0x8854, 0x8237, 0x95f2, 0x6d8e, 0x5f26, 0x5acc, 0x663e, 0x9669, 0x73b0, 0x732e, 0x53bf, 0x817a, 0x9985, 0x7fa1, 0x5baa, 0x9677, 0x9650, 0x7ebf, 0x76f8, 0x53a2, 0x9576, 0x9999, 0x7bb1, 0x8944, 0x6e58, 0x4e61, 0x7fd4, 0x7965, 0x8be6, 0x60f3, 0x54cd, 0x4eab, 0x9879, 0x5df7, 0x6a61, 0x50cf, 0x5411, 0x8c61, 0x8427, 0x785d, 0x9704, 0x524a, 0x54ee, 0x56a3, 0x9500, 0x6d88, 0x5bb5, 0x6dc6, 0x6653, /* 0xd0 */ 0x8824, 0x8825, 0x8826, 0x8827, 0x8828, 0x8829, 0x882a, 0x882b, 0x882c, 0x882d, 0x882e, 0x882f, 0x8830, 0x8831, 0x8833, 0x8834, 0x8835, 0x8836, 0x8837, 0x8838, 0x883a, 0x883b, 0x883d, 0x883e, 0x883f, 0x8841, 0x8842, 0x8843, 0x8846, 0x8847, 0x8848, 0x8849, 0x884a, 0x884b, 0x884e, 0x884f, 0x8850, 0x8851, 0x8852, 0x8853, 0x8855, 0x8856, 0x8858, 0x885a, 0x885b, 0x885c, 0x885d, 0x885e, 0x885f, 0x8860, 0x8866, 0x8867, 0x886a, 0x886d, 0x886f, 0x8871, 0x8873, 0x8874, 0x8875, 0x8876, 0x8878, 0x8879, 0x887a, 0x887b, 0x887c, 0x8880, 0x8883, 0x8886, 0x8887, 0x8889, 0x888a, 0x888c, 0x888e, 0x888f, 0x8890, 0x8891, 0x8893, 0x8894, 0x8895, 0x8897, 0x8898, 0x8899, 0x889a, 0x889b, 0x889d, 0x889e, 0x889f, 0x88a0, 0x88a1, 0x88a3, 0x88a5, 0x88a6, 0x88a7, 0x88a8, 0x88a9, 0x88aa, 0x5c0f, 0x5b5d, 0x6821, 0x8096, 0x5578, 0x7b11, 0x6548, 0x6954, 0x4e9b, 0x6b47, 0x874e, 0x978b, 0x534f, 0x631f, 0x643a, 0x90aa, 0x659c, 0x80c1, 0x8c10, 0x5199, 0x68b0, 0x5378, 0x87f9, 0x61c8, 0x6cc4, 0x6cfb, 0x8c22, 0x5c51, 0x85aa, 0x82af, 0x950c, 0x6b23, 0x8f9b, 0x65b0, 0x5ffb, 0x5fc3, 0x4fe1, 0x8845, 0x661f, 0x8165, 0x7329, 0x60fa, 0x5174, 0x5211, 0x578b, 0x5f62, 0x90a2, 0x884c, 0x9192, 0x5e78, 0x674f, 0x6027, 0x59d3, 0x5144, 0x51f6, 0x80f8, 0x5308, 0x6c79, 0x96c4, 0x718a, 0x4f11, 0x4fee, 0x7f9e, 0x673d, 0x55c5, 0x9508, 0x79c0, 0x8896, 0x7ee3, 0x589f, 0x620c, 0x9700, 0x865a, 0x5618, 0x987b, 0x5f90, 0x8bb8, 0x84c4, 0x9157, 0x53d9, 0x65ed, 0x5e8f, 0x755c, 0x6064, 0x7d6e, 0x5a7f, 0x7eea, 0x7eed, 0x8f69, 0x55a7, 0x5ba3, 0x60ac, 0x65cb, 0x7384, /* 0xd1 */ 0x88ac, 0x88ae, 0x88af, 0x88b0, 0x88b2, 0x88b3, 0x88b4, 0x88b5, 0x88b6, 0x88b8, 0x88b9, 0x88ba, 0x88bb, 0x88bd, 0x88be, 0x88bf, 0x88c0, 0x88c3, 0x88c4, 0x88c7, 0x88c8, 0x88ca, 0x88cb, 0x88cc, 0x88cd, 0x88cf, 0x88d0, 0x88d1, 0x88d3, 0x88d6, 0x88d7, 0x88da, 0x88db, 0x88dc, 0x88dd, 0x88de, 0x88e0, 0x88e1, 0x88e6, 0x88e7, 0x88e9, 0x88ea, 0x88eb, 0x88ec, 0x88ed, 0x88ee, 0x88ef, 0x88f2, 0x88f5, 0x88f6, 0x88f7, 0x88fa, 0x88fb, 0x88fd, 0x88ff, 0x8900, 0x8901, 0x8903, 0x8904, 0x8905, 0x8906, 0x8907, 0x8908, 0x8909, 0x890b, 0x890c, 0x890d, 0x890e, 0x890f, 0x8911, 0x8914, 0x8915, 0x8916, 0x8917, 0x8918, 0x891c, 0x891d, 0x891e, 0x891f, 0x8920, 0x8922, 0x8923, 0x8924, 0x8926, 0x8927, 0x8928, 0x8929, 0x892c, 0x892d, 0x892e, 0x892f, 0x8931, 0x8932, 0x8933, 0x8935, 0x8937, 0x9009, 0x7663, 0x7729, 0x7eda, 0x9774, 0x859b, 0x5b66, 0x7a74, 0x96ea, 0x8840, 0x52cb, 0x718f, 0x5faa, 0x65ec, 0x8be2, 0x5bfb, 0x9a6f, 0x5de1, 0x6b89, 0x6c5b, 0x8bad, 0x8baf, 0x900a, 0x8fc5, 0x538b, 0x62bc, 0x9e26, 0x9e2d, 0x5440, 0x4e2b, 0x82bd, 0x7259, 0x869c, 0x5d16, 0x8859, 0x6daf, 0x96c5, 0x54d1, 0x4e9a, 0x8bb6, 0x7109, 0x54bd, 0x9609, 0x70df, 0x6df9, 0x76d0, 0x4e25, 0x7814, 0x8712, 0x5ca9, 0x5ef6, 0x8a00, 0x989c, 0x960e, 0x708e, 0x6cbf, 0x5944, 0x63a9, 0x773c, 0x884d, 0x6f14, 0x8273, 0x5830, 0x71d5, 0x538c, 0x781a, 0x96c1, 0x5501, 0x5f66, 0x7130, 0x5bb4, 0x8c1a, 0x9a8c, 0x6b83, 0x592e, 0x9e2f, 0x79e7, 0x6768, 0x626c, 0x4f6f, 0x75a1, 0x7f8a, 0x6d0b, 0x9633, 0x6c27, 0x4ef0, 0x75d2, 0x517b, 0x6837, 0x6f3e, 0x9080, 0x8170, 0x5996, 0x7476, /* 0xd2 */ 0x8938, 0x8939, 0x893a, 0x893b, 0x893c, 0x893d, 0x893e, 0x893f, 0x8940, 0x8942, 0x8943, 0x8945, 0x8946, 0x8947, 0x8948, 0x8949, 0x894a, 0x894b, 0x894c, 0x894d, 0x894e, 0x894f, 0x8950, 0x8951, 0x8952, 0x8953, 0x8954, 0x8955, 0x8956, 0x8957, 0x8958, 0x8959, 0x895a, 0x895b, 0x895c, 0x895d, 0x8960, 0x8961, 0x8962, 0x8963, 0x8964, 0x8965, 0x8967, 0x8968, 0x8969, 0x896a, 0x896b, 0x896c, 0x896d, 0x896e, 0x896f, 0x8970, 0x8971, 0x8972, 0x8973, 0x8974, 0x8975, 0x8976, 0x8977, 0x8978, 0x8979, 0x897a, 0x897c, 0x897d, 0x897e, 0x8980, 0x8982, 0x8984, 0x8985, 0x8987, 0x8988, 0x8989, 0x898a, 0x898b, 0x898c, 0x898d, 0x898e, 0x898f, 0x8990, 0x8991, 0x8992, 0x8993, 0x8994, 0x8995, 0x8996, 0x8997, 0x8998, 0x8999, 0x899a, 0x899b, 0x899c, 0x899d, 0x899e, 0x899f, 0x89a0, 0x89a1, 0x6447, 0x5c27, 0x9065, 0x7a91, 0x8c23, 0x59da, 0x54ac, 0x8200, 0x836f, 0x8981, 0x8000, 0x6930, 0x564e, 0x8036, 0x7237, 0x91ce, 0x51b6, 0x4e5f, 0x9875, 0x6396, 0x4e1a, 0x53f6, 0x66f3, 0x814b, 0x591c, 0x6db2, 0x4e00, 0x58f9, 0x533b, 0x63d6, 0x94f1, 0x4f9d, 0x4f0a, 0x8863, 0x9890, 0x5937, 0x9057, 0x79fb, 0x4eea, 0x80f0, 0x7591, 0x6c82, 0x5b9c, 0x59e8, 0x5f5d, 0x6905, 0x8681, 0x501a, 0x5df2, 0x4e59, 0x77e3, 0x4ee5, 0x827a, 0x6291, 0x6613, 0x9091, 0x5c79, 0x4ebf, 0x5f79, 0x81c6, 0x9038, 0x8084, 0x75ab, 0x4ea6, 0x88d4, 0x610f, 0x6bc5, 0x5fc6, 0x4e49, 0x76ca, 0x6ea2, 0x8be3, 0x8bae, 0x8c0a, 0x8bd1, 0x5f02, 0x7ffc, 0x7fcc, 0x7ece, 0x8335, 0x836b, 0x56e0, 0x6bb7, 0x97f3, 0x9634, 0x59fb, 0x541f, 0x94f6, 0x6deb, 0x5bc5, 0x996e, 0x5c39, 0x5f15, 0x9690, /* 0xd3 */ 0x89a2, 0x89a3, 0x89a4, 0x89a5, 0x89a6, 0x89a7, 0x89a8, 0x89a9, 0x89aa, 0x89ab, 0x89ac, 0x89ad, 0x89ae, 0x89af, 0x89b0, 0x89b1, 0x89b2, 0x89b3, 0x89b4, 0x89b5, 0x89b6, 0x89b7, 0x89b8, 0x89b9, 0x89ba, 0x89bb, 0x89bc, 0x89bd, 0x89be, 0x89bf, 0x89c0, 0x89c3, 0x89cd, 0x89d3, 0x89d4, 0x89d5, 0x89d7, 0x89d8, 0x89d9, 0x89db, 0x89dd, 0x89df, 0x89e0, 0x89e1, 0x89e2, 0x89e4, 0x89e7, 0x89e8, 0x89e9, 0x89ea, 0x89ec, 0x89ed, 0x89ee, 0x89f0, 0x89f1, 0x89f2, 0x89f4, 0x89f5, 0x89f6, 0x89f7, 0x89f8, 0x89f9, 0x89fa, 0x89fb, 0x89fc, 0x89fd, 0x89fe, 0x89ff, 0x8a01, 0x8a02, 0x8a03, 0x8a04, 0x8a05, 0x8a06, 0x8a08, 0x8a09, 0x8a0a, 0x8a0b, 0x8a0c, 0x8a0d, 0x8a0e, 0x8a0f, 0x8a10, 0x8a11, 0x8a12, 0x8a13, 0x8a14, 0x8a15, 0x8a16, 0x8a17, 0x8a18, 0x8a19, 0x8a1a, 0x8a1b, 0x8a1c, 0x8a1d, 0x5370, 0x82f1, 0x6a31, 0x5a74, 0x9e70, 0x5e94, 0x7f28, 0x83b9, 0x8424, 0x8425, 0x8367, 0x8747, 0x8fce, 0x8d62, 0x76c8, 0x5f71, 0x9896, 0x786c, 0x6620, 0x54df, 0x62e5, 0x4f63, 0x81c3, 0x75c8, 0x5eb8, 0x96cd, 0x8e0a, 0x86f9, 0x548f, 0x6cf3, 0x6d8c, 0x6c38, 0x607f, 0x52c7, 0x7528, 0x5e7d, 0x4f18, 0x60a0, 0x5fe7, 0x5c24, 0x7531, 0x90ae, 0x94c0, 0x72b9, 0x6cb9, 0x6e38, 0x9149, 0x6709, 0x53cb, 0x53f3, 0x4f51, 0x91c9, 0x8bf1, 0x53c8, 0x5e7c, 0x8fc2, 0x6de4, 0x4e8e, 0x76c2, 0x6986, 0x865e, 0x611a, 0x8206, 0x4f59, 0x4fde, 0x903e, 0x9c7c, 0x6109, 0x6e1d, 0x6e14, 0x9685, 0x4e88, 0x5a31, 0x96e8, 0x4e0e, 0x5c7f, 0x79b9, 0x5b87, 0x8bed, 0x7fbd, 0x7389, 0x57df, 0x828b, 0x90c1, 0x5401, 0x9047, 0x55bb, 0x5cea, 0x5fa1, 0x6108, 0x6b32, 0x72f1, 0x80b2, 0x8a89, /* 0xd4 */ 0x8a1e, 0x8a1f, 0x8a20, 0x8a21, 0x8a22, 0x8a23, 0x8a24, 0x8a25, 0x8a26, 0x8a27, 0x8a28, 0x8a29, 0x8a2a, 0x8a2b, 0x8a2c, 0x8a2d, 0x8a2e, 0x8a2f, 0x8a30, 0x8a31, 0x8a32, 0x8a33, 0x8a34, 0x8a35, 0x8a36, 0x8a37, 0x8a38, 0x8a39, 0x8a3a, 0x8a3b, 0x8a3c, 0x8a3d, 0x8a3f, 0x8a40, 0x8a41, 0x8a42, 0x8a43, 0x8a44, 0x8a45, 0x8a46, 0x8a47, 0x8a49, 0x8a4a, 0x8a4b, 0x8a4c, 0x8a4d, 0x8a4e, 0x8a4f, 0x8a50, 0x8a51, 0x8a52, 0x8a53, 0x8a54, 0x8a55, 0x8a56, 0x8a57, 0x8a58, 0x8a59, 0x8a5a, 0x8a5b, 0x8a5c, 0x8a5d, 0x8a5e, 0x8a5f, 0x8a60, 0x8a61, 0x8a62, 0x8a63, 0x8a64, 0x8a65, 0x8a66, 0x8a67, 0x8a68, 0x8a69, 0x8a6a, 0x8a6b, 0x8a6c, 0x8a6d, 0x8a6e, 0x8a6f, 0x8a70, 0x8a71, 0x8a72, 0x8a73, 0x8a74, 0x8a75, 0x8a76, 0x8a77, 0x8a78, 0x8a7a, 0x8a7b, 0x8a7c, 0x8a7d, 0x8a7e, 0x8a7f, 0x8a80, 0x6d74, 0x5bd3, 0x88d5, 0x9884, 0x8c6b, 0x9a6d, 0x9e33, 0x6e0a, 0x51a4, 0x5143, 0x57a3, 0x8881, 0x539f, 0x63f4, 0x8f95, 0x56ed, 0x5458, 0x5706, 0x733f, 0x6e90, 0x7f18, 0x8fdc, 0x82d1, 0x613f, 0x6028, 0x9662, 0x66f0, 0x7ea6, 0x8d8a, 0x8dc3, 0x94a5, 0x5cb3, 0x7ca4, 0x6708, 0x60a6, 0x9605, 0x8018, 0x4e91, 0x90e7, 0x5300, 0x9668, 0x5141, 0x8fd0, 0x8574, 0x915d, 0x6655, 0x97f5, 0x5b55, 0x531d, 0x7838, 0x6742, 0x683d, 0x54c9, 0x707e, 0x5bb0, 0x8f7d, 0x518d, 0x5728, 0x54b1, 0x6512, 0x6682, 0x8d5e, 0x8d43, 0x810f, 0x846c, 0x906d, 0x7cdf, 0x51ff, 0x85fb, 0x67a3, 0x65e9, 0x6fa1, 0x86a4, 0x8e81, 0x566a, 0x9020, 0x7682, 0x7076, 0x71e5, 0x8d23, 0x62e9, 0x5219, 0x6cfd, 0x8d3c, 0x600e, 0x589e, 0x618e, 0x66fe, 0x8d60, 0x624e, 0x55b3, 0x6e23, 0x672d, 0x8f67, /* 0xd5 */ 0x8a81, 0x8a82, 0x8a83, 0x8a84, 0x8a85, 0x8a86, 0x8a87, 0x8a88, 0x8a8b, 0x8a8c, 0x8a8d, 0x8a8e, 0x8a8f, 0x8a90, 0x8a91, 0x8a92, 0x8a94, 0x8a95, 0x8a96, 0x8a97, 0x8a98, 0x8a99, 0x8a9a, 0x8a9b, 0x8a9c, 0x8a9d, 0x8a9e, 0x8a9f, 0x8aa0, 0x8aa1, 0x8aa2, 0x8aa3, 0x8aa4, 0x8aa5, 0x8aa6, 0x8aa7, 0x8aa8, 0x8aa9, 0x8aaa, 0x8aab, 0x8aac, 0x8aad, 0x8aae, 0x8aaf, 0x8ab0, 0x8ab1, 0x8ab2, 0x8ab3, 0x8ab4, 0x8ab5, 0x8ab6, 0x8ab7, 0x8ab8, 0x8ab9, 0x8aba, 0x8abb, 0x8abc, 0x8abd, 0x8abe, 0x8abf, 0x8ac0, 0x8ac1, 0x8ac2, 0x8ac3, 0x8ac4, 0x8ac5, 0x8ac6, 0x8ac7, 0x8ac8, 0x8ac9, 0x8aca, 0x8acb, 0x8acc, 0x8acd, 0x8ace, 0x8acf, 0x8ad0, 0x8ad1, 0x8ad2, 0x8ad3, 0x8ad4, 0x8ad5, 0x8ad6, 0x8ad7, 0x8ad8, 0x8ad9, 0x8ada, 0x8adb, 0x8adc, 0x8add, 0x8ade, 0x8adf, 0x8ae0, 0x8ae1, 0x8ae2, 0x8ae3, 0x94e1, 0x95f8, 0x7728, 0x6805, 0x69a8, 0x548b, 0x4e4d, 0x70b8, 0x8bc8, 0x6458, 0x658b, 0x5b85, 0x7a84, 0x503a, 0x5be8, 0x77bb, 0x6be1, 0x8a79, 0x7c98, 0x6cbe, 0x76cf, 0x65a9, 0x8f97, 0x5d2d, 0x5c55, 0x8638, 0x6808, 0x5360, 0x6218, 0x7ad9, 0x6e5b, 0x7efd, 0x6a1f, 0x7ae0, 0x5f70, 0x6f33, 0x5f20, 0x638c, 0x6da8, 0x6756, 0x4e08, 0x5e10, 0x8d26, 0x4ed7, 0x80c0, 0x7634, 0x969c, 0x62db, 0x662d, 0x627e, 0x6cbc, 0x8d75, 0x7167, 0x7f69, 0x5146, 0x8087, 0x53ec, 0x906e, 0x6298, 0x54f2, 0x86f0, 0x8f99, 0x8005, 0x9517, 0x8517, 0x8fd9, 0x6d59, 0x73cd, 0x659f, 0x771f, 0x7504, 0x7827, 0x81fb, 0x8d1e, 0x9488, 0x4fa6, 0x6795, 0x75b9, 0x8bca, 0x9707, 0x632f, 0x9547, 0x9635, 0x84b8, 0x6323, 0x7741, 0x5f81, 0x72f0, 0x4e89, 0x6014, 0x6574, 0x62ef, 0x6b63, 0x653f, /* 0xd6 */ 0x8ae4, 0x8ae5, 0x8ae6, 0x8ae7, 0x8ae8, 0x8ae9, 0x8aea, 0x8aeb, 0x8aec, 0x8aed, 0x8aee, 0x8aef, 0x8af0, 0x8af1, 0x8af2, 0x8af3, 0x8af4, 0x8af5, 0x8af6, 0x8af7, 0x8af8, 0x8af9, 0x8afa, 0x8afb, 0x8afc, 0x8afd, 0x8afe, 0x8aff, 0x8b00, 0x8b01, 0x8b02, 0x8b03, 0x8b04, 0x8b05, 0x8b06, 0x8b08, 0x8b09, 0x8b0a, 0x8b0b, 0x8b0c, 0x8b0d, 0x8b0e, 0x8b0f, 0x8b10, 0x8b11, 0x8b12, 0x8b13, 0x8b14, 0x8b15, 0x8b16, 0x8b17, 0x8b18, 0x8b19, 0x8b1a, 0x8b1b, 0x8b1c, 0x8b1d, 0x8b1e, 0x8b1f, 0x8b20, 0x8b21, 0x8b22, 0x8b23, 0x8b24, 0x8b25, 0x8b27, 0x8b28, 0x8b29, 0x8b2a, 0x8b2b, 0x8b2c, 0x8b2d, 0x8b2e, 0x8b2f, 0x8b30, 0x8b31, 0x8b32, 0x8b33, 0x8b34, 0x8b35, 0x8b36, 0x8b37, 0x8b38, 0x8b39, 0x8b3a, 0x8b3b, 0x8b3c, 0x8b3d, 0x8b3e, 0x8b3f, 0x8b40, 0x8b41, 0x8b42, 0x8b43, 0x8b44, 0x8b45, 0x5e27, 0x75c7, 0x90d1, 0x8bc1, 0x829d, 0x679d, 0x652f, 0x5431, 0x8718, 0x77e5, 0x80a2, 0x8102, 0x6c41, 0x4e4b, 0x7ec7, 0x804c, 0x76f4, 0x690d, 0x6b96, 0x6267, 0x503c, 0x4f84, 0x5740, 0x6307, 0x6b62, 0x8dbe, 0x53ea, 0x65e8, 0x7eb8, 0x5fd7, 0x631a, 0x63b7, 0x81f3, 0x81f4, 0x7f6e, 0x5e1c, 0x5cd9, 0x5236, 0x667a, 0x79e9, 0x7a1a, 0x8d28, 0x7099, 0x75d4, 0x6ede, 0x6cbb, 0x7a92, 0x4e2d, 0x76c5, 0x5fe0, 0x949f, 0x8877, 0x7ec8, 0x79cd, 0x80bf, 0x91cd, 0x4ef2, 0x4f17, 0x821f, 0x5468, 0x5dde, 0x6d32, 0x8bcc, 0x7ca5, 0x8f74, 0x8098, 0x5e1a, 0x5492, 0x76b1, 0x5b99, 0x663c, 0x9aa4, 0x73e0, 0x682a, 0x86db, 0x6731, 0x732a, 0x8bf8, 0x8bdb, 0x9010, 0x7af9, 0x70db, 0x716e, 0x62c4, 0x77a9, 0x5631, 0x4e3b, 0x8457, 0x67f1, 0x52a9, 0x86c0, 0x8d2e, 0x94f8, 0x7b51, /* 0xd7 */ 0x8b46, 0x8b47, 0x8b48, 0x8b49, 0x8b4a, 0x8b4b, 0x8b4c, 0x8b4d, 0x8b4e, 0x8b4f, 0x8b50, 0x8b51, 0x8b52, 0x8b53, 0x8b54, 0x8b55, 0x8b56, 0x8b57, 0x8b58, 0x8b59, 0x8b5a, 0x8b5b, 0x8b5c, 0x8b5d, 0x8b5e, 0x8b5f, 0x8b60, 0x8b61, 0x8b62, 0x8b63, 0x8b64, 0x8b65, 0x8b67, 0x8b68, 0x8b69, 0x8b6a, 0x8b6b, 0x8b6d, 0x8b6e, 0x8b6f, 0x8b70, 0x8b71, 0x8b72, 0x8b73, 0x8b74, 0x8b75, 0x8b76, 0x8b77, 0x8b78, 0x8b79, 0x8b7a, 0x8b7b, 0x8b7c, 0x8b7d, 0x8b7e, 0x8b7f, 0x8b80, 0x8b81, 0x8b82, 0x8b83, 0x8b84, 0x8b85, 0x8b86, 0x8b87, 0x8b88, 0x8b89, 0x8b8a, 0x8b8b, 0x8b8c, 0x8b8d, 0x8b8e, 0x8b8f, 0x8b90, 0x8b91, 0x8b92, 0x8b93, 0x8b94, 0x8b95, 0x8b96, 0x8b97, 0x8b98, 0x8b99, 0x8b9a, 0x8b9b, 0x8b9c, 0x8b9d, 0x8b9e, 0x8b9f, 0x8bac, 0x8bb1, 0x8bbb, 0x8bc7, 0x8bd0, 0x8bea, 0x8c09, 0x8c1e, 0x4f4f, 0x6ce8, 0x795d, 0x9a7b, 0x6293, 0x722a, 0x62fd, 0x4e13, 0x7816, 0x8f6c, 0x64b0, 0x8d5a, 0x7bc6, 0x6869, 0x5e84, 0x88c5, 0x5986, 0x649e, 0x58ee, 0x72b6, 0x690e, 0x9525, 0x8ffd, 0x8d58, 0x5760, 0x7f00, 0x8c06, 0x51c6, 0x6349, 0x62d9, 0x5353, 0x684c, 0x7422, 0x8301, 0x914c, 0x5544, 0x7740, 0x707c, 0x6d4a, 0x5179, 0x54a8, 0x8d44, 0x59ff, 0x6ecb, 0x6dc4, 0x5b5c, 0x7d2b, 0x4ed4, 0x7c7d, 0x6ed3, 0x5b50, 0x81ea, 0x6e0d, 0x5b57, 0x9b03, 0x68d5, 0x8e2a, 0x5b97, 0x7efc, 0x603b, 0x7eb5, 0x90b9, 0x8d70, 0x594f, 0x63cd, 0x79df, 0x8db3, 0x5352, 0x65cf, 0x7956, 0x8bc5, 0x963b, 0x7ec4, 0x94bb, 0x7e82, 0x5634, 0x9189, 0x6700, 0x7f6a, 0x5c0a, 0x9075, 0x6628, 0x5de6, 0x4f50, 0x67de, 0x505a, 0x4f5c, 0x5750, 0x5ea7, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xd8 */ 0x8c38, 0x8c39, 0x8c3a, 0x8c3b, 0x8c3c, 0x8c3d, 0x8c3e, 0x8c3f, 0x8c40, 0x8c42, 0x8c43, 0x8c44, 0x8c45, 0x8c48, 0x8c4a, 0x8c4b, 0x8c4d, 0x8c4e, 0x8c4f, 0x8c50, 0x8c51, 0x8c52, 0x8c53, 0x8c54, 0x8c56, 0x8c57, 0x8c58, 0x8c59, 0x8c5b, 0x8c5c, 0x8c5d, 0x8c5e, 0x8c5f, 0x8c60, 0x8c63, 0x8c64, 0x8c65, 0x8c66, 0x8c67, 0x8c68, 0x8c69, 0x8c6c, 0x8c6d, 0x8c6e, 0x8c6f, 0x8c70, 0x8c71, 0x8c72, 0x8c74, 0x8c75, 0x8c76, 0x8c77, 0x8c7b, 0x8c7c, 0x8c7d, 0x8c7e, 0x8c7f, 0x8c80, 0x8c81, 0x8c83, 0x8c84, 0x8c86, 0x8c87, 0x8c88, 0x8c8b, 0x8c8d, 0x8c8e, 0x8c8f, 0x8c90, 0x8c91, 0x8c92, 0x8c93, 0x8c95, 0x8c96, 0x8c97, 0x8c99, 0x8c9a, 0x8c9b, 0x8c9c, 0x8c9d, 0x8c9e, 0x8c9f, 0x8ca0, 0x8ca1, 0x8ca2, 0x8ca3, 0x8ca4, 0x8ca5, 0x8ca6, 0x8ca7, 0x8ca8, 0x8ca9, 0x8caa, 0x8cab, 0x8cac, 0x8cad, 0x4e8d, 0x4e0c, 0x5140, 0x4e10, 0x5eff, 0x5345, 0x4e15, 0x4e98, 0x4e1e, 0x9b32, 0x5b6c, 0x5669, 0x4e28, 0x79ba, 0x4e3f, 0x5315, 0x4e47, 0x592d, 0x723b, 0x536e, 0x6c10, 0x56df, 0x80e4, 0x9997, 0x6bd3, 0x777e, 0x9f17, 0x4e36, 0x4e9f, 0x9f10, 0x4e5c, 0x4e69, 0x4e93, 0x8288, 0x5b5b, 0x556c, 0x560f, 0x4ec4, 0x538d, 0x539d, 0x53a3, 0x53a5, 0x53ae, 0x9765, 0x8d5d, 0x531a, 0x53f5, 0x5326, 0x532e, 0x533e, 0x8d5c, 0x5366, 0x5363, 0x5202, 0x5208, 0x520e, 0x522d, 0x5233, 0x523f, 0x5240, 0x524c, 0x525e, 0x5261, 0x525c, 0x84af, 0x527d, 0x5282, 0x5281, 0x5290, 0x5293, 0x5182, 0x7f54, 0x4ebb, 0x4ec3, 0x4ec9, 0x4ec2, 0x4ee8, 0x4ee1, 0x4eeb, 0x4ede, 0x4f1b, 0x4ef3, 0x4f22, 0x4f64, 0x4ef5, 0x4f25, 0x4f27, 0x4f09, 0x4f2b, 0x4f5e, 0x4f67, 0x6538, 0x4f5a, 0x4f5d, /* 0xd9 */ 0x8cae, 0x8caf, 0x8cb0, 0x8cb1, 0x8cb2, 0x8cb3, 0x8cb4, 0x8cb5, 0x8cb6, 0x8cb7, 0x8cb8, 0x8cb9, 0x8cba, 0x8cbb, 0x8cbc, 0x8cbd, 0x8cbe, 0x8cbf, 0x8cc0, 0x8cc1, 0x8cc2, 0x8cc3, 0x8cc4, 0x8cc5, 0x8cc6, 0x8cc7, 0x8cc8, 0x8cc9, 0x8cca, 0x8ccb, 0x8ccc, 0x8ccd, 0x8cce, 0x8ccf, 0x8cd0, 0x8cd1, 0x8cd2, 0x8cd3, 0x8cd4, 0x8cd5, 0x8cd6, 0x8cd7, 0x8cd8, 0x8cd9, 0x8cda, 0x8cdb, 0x8cdc, 0x8cdd, 0x8cde, 0x8cdf, 0x8ce0, 0x8ce1, 0x8ce2, 0x8ce3, 0x8ce4, 0x8ce5, 0x8ce6, 0x8ce7, 0x8ce8, 0x8ce9, 0x8cea, 0x8ceb, 0x8cec, 0x8ced, 0x8cee, 0x8cef, 0x8cf0, 0x8cf1, 0x8cf2, 0x8cf3, 0x8cf4, 0x8cf5, 0x8cf6, 0x8cf7, 0x8cf8, 0x8cf9, 0x8cfa, 0x8cfb, 0x8cfc, 0x8cfd, 0x8cfe, 0x8cff, 0x8d00, 0x8d01, 0x8d02, 0x8d03, 0x8d04, 0x8d05, 0x8d06, 0x8d07, 0x8d08, 0x8d09, 0x8d0a, 0x8d0b, 0x8d0c, 0x8d0d, 0x4f5f, 0x4f57, 0x4f32, 0x4f3d, 0x4f76, 0x4f74, 0x4f91, 0x4f89, 0x4f83, 0x4f8f, 0x4f7e, 0x4f7b, 0x4faa, 0x4f7c, 0x4fac, 0x4f94, 0x4fe6, 0x4fe8, 0x4fea, 0x4fc5, 0x4fda, 0x4fe3, 0x4fdc, 0x4fd1, 0x4fdf, 0x4ff8, 0x5029, 0x504c, 0x4ff3, 0x502c, 0x500f, 0x502e, 0x502d, 0x4ffe, 0x501c, 0x500c, 0x5025, 0x5028, 0x507e, 0x5043, 0x5055, 0x5048, 0x504e, 0x506c, 0x507b, 0x50a5, 0x50a7, 0x50a9, 0x50ba, 0x50d6, 0x5106, 0x50ed, 0x50ec, 0x50e6, 0x50ee, 0x5107, 0x510b, 0x4edd, 0x6c3d, 0x4f58, 0x4f65, 0x4fce, 0x9fa0, 0x6c46, 0x7c74, 0x516e, 0x5dfd, 0x9ec9, 0x9998, 0x5181, 0x5914, 0x52f9, 0x530d, 0x8a07, 0x5310, 0x51eb, 0x5919, 0x5155, 0x4ea0, 0x5156, 0x4eb3, 0x886e, 0x88a4, 0x4eb5, 0x8114, 0x88d2, 0x7980, 0x5b34, 0x8803, 0x7fb8, 0x51ab, 0x51b1, 0x51bd, 0x51bc, /* 0xda */ 0x8d0e, 0x8d0f, 0x8d10, 0x8d11, 0x8d12, 0x8d13, 0x8d14, 0x8d15, 0x8d16, 0x8d17, 0x8d18, 0x8d19, 0x8d1a, 0x8d1b, 0x8d1c, 0x8d20, 0x8d51, 0x8d52, 0x8d57, 0x8d5f, 0x8d65, 0x8d68, 0x8d69, 0x8d6a, 0x8d6c, 0x8d6e, 0x8d6f, 0x8d71, 0x8d72, 0x8d78, 0x8d79, 0x8d7a, 0x8d7b, 0x8d7c, 0x8d7d, 0x8d7e, 0x8d7f, 0x8d80, 0x8d82, 0x8d83, 0x8d86, 0x8d87, 0x8d88, 0x8d89, 0x8d8c, 0x8d8d, 0x8d8e, 0x8d8f, 0x8d90, 0x8d92, 0x8d93, 0x8d95, 0x8d96, 0x8d97, 0x8d98, 0x8d99, 0x8d9a, 0x8d9b, 0x8d9c, 0x8d9d, 0x8d9e, 0x8da0, 0x8da1, 0x8da2, 0x8da4, 0x8da5, 0x8da6, 0x8da7, 0x8da8, 0x8da9, 0x8daa, 0x8dab, 0x8dac, 0x8dad, 0x8dae, 0x8daf, 0x8db0, 0x8db2, 0x8db6, 0x8db7, 0x8db9, 0x8dbb, 0x8dbd, 0x8dc0, 0x8dc1, 0x8dc2, 0x8dc5, 0x8dc7, 0x8dc8, 0x8dc9, 0x8dca, 0x8dcd, 0x8dd0, 0x8dd2, 0x8dd3, 0x8dd4, 0x51c7, 0x5196, 0x51a2, 0x51a5, 0x8ba0, 0x8ba6, 0x8ba7, 0x8baa, 0x8bb4, 0x8bb5, 0x8bb7, 0x8bc2, 0x8bc3, 0x8bcb, 0x8bcf, 0x8bce, 0x8bd2, 0x8bd3, 0x8bd4, 0x8bd6, 0x8bd8, 0x8bd9, 0x8bdc, 0x8bdf, 0x8be0, 0x8be4, 0x8be8, 0x8be9, 0x8bee, 0x8bf0, 0x8bf3, 0x8bf6, 0x8bf9, 0x8bfc, 0x8bff, 0x8c00, 0x8c02, 0x8c04, 0x8c07, 0x8c0c, 0x8c0f, 0x8c11, 0x8c12, 0x8c14, 0x8c15, 0x8c16, 0x8c19, 0x8c1b, 0x8c18, 0x8c1d, 0x8c1f, 0x8c20, 0x8c21, 0x8c25, 0x8c27, 0x8c2a, 0x8c2b, 0x8c2e, 0x8c2f, 0x8c32, 0x8c33, 0x8c35, 0x8c36, 0x5369, 0x537a, 0x961d, 0x9622, 0x9621, 0x9631, 0x962a, 0x963d, 0x963c, 0x9642, 0x9649, 0x9654, 0x965f, 0x9667, 0x966c, 0x9672, 0x9674, 0x9688, 0x968d, 0x9697, 0x96b0, 0x9097, 0x909b, 0x909d, 0x9099, 0x90ac, 0x90a1, 0x90b4, 0x90b3, 0x90b6, 0x90ba, /* 0xdb */ 0x8dd5, 0x8dd8, 0x8dd9, 0x8ddc, 0x8de0, 0x8de1, 0x8de2, 0x8de5, 0x8de6, 0x8de7, 0x8de9, 0x8ded, 0x8dee, 0x8df0, 0x8df1, 0x8df2, 0x8df4, 0x8df6, 0x8dfc, 0x8dfe, 0x8dff, 0x8e00, 0x8e01, 0x8e02, 0x8e03, 0x8e04, 0x8e06, 0x8e07, 0x8e08, 0x8e0b, 0x8e0d, 0x8e0e, 0x8e10, 0x8e11, 0x8e12, 0x8e13, 0x8e15, 0x8e16, 0x8e17, 0x8e18, 0x8e19, 0x8e1a, 0x8e1b, 0x8e1c, 0x8e20, 0x8e21, 0x8e24, 0x8e25, 0x8e26, 0x8e27, 0x8e28, 0x8e2b, 0x8e2d, 0x8e30, 0x8e32, 0x8e33, 0x8e34, 0x8e36, 0x8e37, 0x8e38, 0x8e3b, 0x8e3c, 0x8e3e, 0x8e3f, 0x8e43, 0x8e45, 0x8e46, 0x8e4c, 0x8e4d, 0x8e4e, 0x8e4f, 0x8e50, 0x8e53, 0x8e54, 0x8e55, 0x8e56, 0x8e57, 0x8e58, 0x8e5a, 0x8e5b, 0x8e5c, 0x8e5d, 0x8e5e, 0x8e5f, 0x8e60, 0x8e61, 0x8e62, 0x8e63, 0x8e64, 0x8e65, 0x8e67, 0x8e68, 0x8e6a, 0x8e6b, 0x8e6e, 0x8e71, 0x90b8, 0x90b0, 0x90cf, 0x90c5, 0x90be, 0x90d0, 0x90c4, 0x90c7, 0x90d3, 0x90e6, 0x90e2, 0x90dc, 0x90d7, 0x90db, 0x90eb, 0x90ef, 0x90fe, 0x9104, 0x9122, 0x911e, 0x9123, 0x9131, 0x912f, 0x9139, 0x9143, 0x9146, 0x520d, 0x5942, 0x52a2, 0x52ac, 0x52ad, 0x52be, 0x54ff, 0x52d0, 0x52d6, 0x52f0, 0x53df, 0x71ee, 0x77cd, 0x5ef4, 0x51f5, 0x51fc, 0x9b2f, 0x53b6, 0x5f01, 0x755a, 0x5def, 0x574c, 0x57a9, 0x57a1, 0x587e, 0x58bc, 0x58c5, 0x58d1, 0x5729, 0x572c, 0x572a, 0x5733, 0x5739, 0x572e, 0x572f, 0x575c, 0x573b, 0x5742, 0x5769, 0x5785, 0x576b, 0x5786, 0x577c, 0x577b, 0x5768, 0x576d, 0x5776, 0x5773, 0x57ad, 0x57a4, 0x578c, 0x57b2, 0x57cf, 0x57a7, 0x57b4, 0x5793, 0x57a0, 0x57d5, 0x57d8, 0x57da, 0x57d9, 0x57d2, 0x57b8, 0x57f4, 0x57ef, 0x57f8, 0x57e4, 0x57dd, /* 0xdc */ 0x8e73, 0x8e75, 0x8e77, 0x8e78, 0x8e79, 0x8e7a, 0x8e7b, 0x8e7d, 0x8e7e, 0x8e80, 0x8e82, 0x8e83, 0x8e84, 0x8e86, 0x8e88, 0x8e89, 0x8e8a, 0x8e8b, 0x8e8c, 0x8e8d, 0x8e8e, 0x8e91, 0x8e92, 0x8e93, 0x8e95, 0x8e96, 0x8e97, 0x8e98, 0x8e99, 0x8e9a, 0x8e9b, 0x8e9d, 0x8e9f, 0x8ea0, 0x8ea1, 0x8ea2, 0x8ea3, 0x8ea4, 0x8ea5, 0x8ea6, 0x8ea7, 0x8ea8, 0x8ea9, 0x8eaa, 0x8ead, 0x8eae, 0x8eb0, 0x8eb1, 0x8eb3, 0x8eb4, 0x8eb5, 0x8eb6, 0x8eb7, 0x8eb8, 0x8eb9, 0x8ebb, 0x8ebc, 0x8ebd, 0x8ebe, 0x8ebf, 0x8ec0, 0x8ec1, 0x8ec2, 0x8ec3, 0x8ec4, 0x8ec5, 0x8ec6, 0x8ec7, 0x8ec8, 0x8ec9, 0x8eca, 0x8ecb, 0x8ecc, 0x8ecd, 0x8ecf, 0x8ed0, 0x8ed1, 0x8ed2, 0x8ed3, 0x8ed4, 0x8ed5, 0x8ed6, 0x8ed7, 0x8ed8, 0x8ed9, 0x8eda, 0x8edb, 0x8edc, 0x8edd, 0x8ede, 0x8edf, 0x8ee0, 0x8ee1, 0x8ee2, 0x8ee3, 0x8ee4, 0x580b, 0x580d, 0x57fd, 0x57ed, 0x5800, 0x581e, 0x5819, 0x5844, 0x5820, 0x5865, 0x586c, 0x5881, 0x5889, 0x589a, 0x5880, 0x99a8, 0x9f19, 0x61ff, 0x8279, 0x827d, 0x827f, 0x828f, 0x828a, 0x82a8, 0x8284, 0x828e, 0x8291, 0x8297, 0x8299, 0x82ab, 0x82b8, 0x82be, 0x82b0, 0x82c8, 0x82ca, 0x82e3, 0x8298, 0x82b7, 0x82ae, 0x82cb, 0x82cc, 0x82c1, 0x82a9, 0x82b4, 0x82a1, 0x82aa, 0x829f, 0x82c4, 0x82ce, 0x82a4, 0x82e1, 0x8309, 0x82f7, 0x82e4, 0x830f, 0x8307, 0x82dc, 0x82f4, 0x82d2, 0x82d8, 0x830c, 0x82fb, 0x82d3, 0x8311, 0x831a, 0x8306, 0x8314, 0x8315, 0x82e0, 0x82d5, 0x831c, 0x8351, 0x835b, 0x835c, 0x8308, 0x8392, 0x833c, 0x8334, 0x8331, 0x839b, 0x835e, 0x832f, 0x834f, 0x8347, 0x8343, 0x835f, 0x8340, 0x8317, 0x8360, 0x832d, 0x833a, 0x8333, 0x8366, 0x8365, /* 0xdd */ 0x8ee5, 0x8ee6, 0x8ee7, 0x8ee8, 0x8ee9, 0x8eea, 0x8eeb, 0x8eec, 0x8eed, 0x8eee, 0x8eef, 0x8ef0, 0x8ef1, 0x8ef2, 0x8ef3, 0x8ef4, 0x8ef5, 0x8ef6, 0x8ef7, 0x8ef8, 0x8ef9, 0x8efa, 0x8efb, 0x8efc, 0x8efd, 0x8efe, 0x8eff, 0x8f00, 0x8f01, 0x8f02, 0x8f03, 0x8f04, 0x8f05, 0x8f06, 0x8f07, 0x8f08, 0x8f09, 0x8f0a, 0x8f0b, 0x8f0c, 0x8f0d, 0x8f0e, 0x8f0f, 0x8f10, 0x8f11, 0x8f12, 0x8f13, 0x8f14, 0x8f15, 0x8f16, 0x8f17, 0x8f18, 0x8f19, 0x8f1a, 0x8f1b, 0x8f1c, 0x8f1d, 0x8f1e, 0x8f1f, 0x8f20, 0x8f21, 0x8f22, 0x8f23, 0x8f24, 0x8f25, 0x8f26, 0x8f27, 0x8f28, 0x8f29, 0x8f2a, 0x8f2b, 0x8f2c, 0x8f2d, 0x8f2e, 0x8f2f, 0x8f30, 0x8f31, 0x8f32, 0x8f33, 0x8f34, 0x8f35, 0x8f36, 0x8f37, 0x8f38, 0x8f39, 0x8f3a, 0x8f3b, 0x8f3c, 0x8f3d, 0x8f3e, 0x8f3f, 0x8f40, 0x8f41, 0x8f42, 0x8f43, 0x8f44, 0x8368, 0x831b, 0x8369, 0x836c, 0x836a, 0x836d, 0x836e, 0x83b0, 0x8378, 0x83b3, 0x83b4, 0x83a0, 0x83aa, 0x8393, 0x839c, 0x8385, 0x837c, 0x83b6, 0x83a9, 0x837d, 0x83b8, 0x837b, 0x8398, 0x839e, 0x83a8, 0x83ba, 0x83bc, 0x83c1, 0x8401, 0x83e5, 0x83d8, 0x5807, 0x8418, 0x840b, 0x83dd, 0x83fd, 0x83d6, 0x841c, 0x8438, 0x8411, 0x8406, 0x83d4, 0x83df, 0x840f, 0x8403, 0x83f8, 0x83f9, 0x83ea, 0x83c5, 0x83c0, 0x8426, 0x83f0, 0x83e1, 0x845c, 0x8451, 0x845a, 0x8459, 0x8473, 0x8487, 0x8488, 0x847a, 0x8489, 0x8478, 0x843c, 0x8446, 0x8469, 0x8476, 0x848c, 0x848e, 0x8431, 0x846d, 0x84c1, 0x84cd, 0x84d0, 0x84e6, 0x84bd, 0x84d3, 0x84ca, 0x84bf, 0x84ba, 0x84e0, 0x84a1, 0x84b9, 0x84b4, 0x8497, 0x84e5, 0x84e3, 0x850c, 0x750d, 0x8538, 0x84f0, 0x8539, 0x851f, 0x853a, /* 0xde */ 0x8f45, 0x8f46, 0x8f47, 0x8f48, 0x8f49, 0x8f4a, 0x8f4b, 0x8f4c, 0x8f4d, 0x8f4e, 0x8f4f, 0x8f50, 0x8f51, 0x8f52, 0x8f53, 0x8f54, 0x8f55, 0x8f56, 0x8f57, 0x8f58, 0x8f59, 0x8f5a, 0x8f5b, 0x8f5c, 0x8f5d, 0x8f5e, 0x8f5f, 0x8f60, 0x8f61, 0x8f62, 0x8f63, 0x8f64, 0x8f65, 0x8f6a, 0x8f80, 0x8f8c, 0x8f92, 0x8f9d, 0x8fa0, 0x8fa1, 0x8fa2, 0x8fa4, 0x8fa5, 0x8fa6, 0x8fa7, 0x8faa, 0x8fac, 0x8fad, 0x8fae, 0x8faf, 0x8fb2, 0x8fb3, 0x8fb4, 0x8fb5, 0x8fb7, 0x8fb8, 0x8fba, 0x8fbb, 0x8fbc, 0x8fbf, 0x8fc0, 0x8fc3, 0x8fc6, 0x8fc9, 0x8fca, 0x8fcb, 0x8fcc, 0x8fcd, 0x8fcf, 0x8fd2, 0x8fd6, 0x8fd7, 0x8fda, 0x8fe0, 0x8fe1, 0x8fe3, 0x8fe7, 0x8fec, 0x8fef, 0x8ff1, 0x8ff2, 0x8ff4, 0x8ff5, 0x8ff6, 0x8ffa, 0x8ffb, 0x8ffc, 0x8ffe, 0x8fff, 0x9007, 0x9008, 0x900c, 0x900e, 0x9013, 0x9015, 0x9018, 0x8556, 0x853b, 0x84ff, 0x84fc, 0x8559, 0x8548, 0x8568, 0x8564, 0x855e, 0x857a, 0x77a2, 0x8543, 0x8572, 0x857b, 0x85a4, 0x85a8, 0x8587, 0x858f, 0x8579, 0x85ae, 0x859c, 0x8585, 0x85b9, 0x85b7, 0x85b0, 0x85d3, 0x85c1, 0x85dc, 0x85ff, 0x8627, 0x8605, 0x8629, 0x8616, 0x863c, 0x5efe, 0x5f08, 0x593c, 0x5941, 0x8037, 0x5955, 0x595a, 0x5958, 0x530f, 0x5c22, 0x5c25, 0x5c2c, 0x5c34, 0x624c, 0x626a, 0x629f, 0x62bb, 0x62ca, 0x62da, 0x62d7, 0x62ee, 0x6322, 0x62f6, 0x6339, 0x634b, 0x6343, 0x63ad, 0x63f6, 0x6371, 0x637a, 0x638e, 0x63b4, 0x636d, 0x63ac, 0x638a, 0x6369, 0x63ae, 0x63bc, 0x63f2, 0x63f8, 0x63e0, 0x63ff, 0x63c4, 0x63de, 0x63ce, 0x6452, 0x63c6, 0x63be, 0x6445, 0x6441, 0x640b, 0x641b, 0x6420, 0x640c, 0x6426, 0x6421, 0x645e, 0x6484, 0x646d, 0x6496, /* 0xdf */ 0x9019, 0x901c, 0x9023, 0x9024, 0x9025, 0x9027, 0x9028, 0x9029, 0x902a, 0x902b, 0x902c, 0x9030, 0x9031, 0x9032, 0x9033, 0x9034, 0x9037, 0x9039, 0x903a, 0x903d, 0x903f, 0x9040, 0x9043, 0x9045, 0x9046, 0x9048, 0x9049, 0x904a, 0x904b, 0x904c, 0x904e, 0x9054, 0x9055, 0x9056, 0x9059, 0x905a, 0x905c, 0x905d, 0x905e, 0x905f, 0x9060, 0x9061, 0x9064, 0x9066, 0x9067, 0x9069, 0x906a, 0x906b, 0x906c, 0x906f, 0x9070, 0x9071, 0x9072, 0x9073, 0x9076, 0x9077, 0x9078, 0x9079, 0x907a, 0x907b, 0x907c, 0x907e, 0x9081, 0x9084, 0x9085, 0x9086, 0x9087, 0x9089, 0x908a, 0x908c, 0x908d, 0x908e, 0x908f, 0x9090, 0x9092, 0x9094, 0x9096, 0x9098, 0x909a, 0x909c, 0x909e, 0x909f, 0x90a0, 0x90a4, 0x90a5, 0x90a7, 0x90a8, 0x90a9, 0x90ab, 0x90ad, 0x90b2, 0x90b7, 0x90bc, 0x90bd, 0x90bf, 0x90c0, 0x647a, 0x64b7, 0x64b8, 0x6499, 0x64ba, 0x64c0, 0x64d0, 0x64d7, 0x64e4, 0x64e2, 0x6509, 0x6525, 0x652e, 0x5f0b, 0x5fd2, 0x7519, 0x5f11, 0x535f, 0x53f1, 0x53fd, 0x53e9, 0x53e8, 0x53fb, 0x5412, 0x5416, 0x5406, 0x544b, 0x5452, 0x5453, 0x5454, 0x5456, 0x5443, 0x5421, 0x5457, 0x5459, 0x5423, 0x5432, 0x5482, 0x5494, 0x5477, 0x5471, 0x5464, 0x549a, 0x549b, 0x5484, 0x5476, 0x5466, 0x549d, 0x54d0, 0x54ad, 0x54c2, 0x54b4, 0x54d2, 0x54a7, 0x54a6, 0x54d3, 0x54d4, 0x5472, 0x54a3, 0x54d5, 0x54bb, 0x54bf, 0x54cc, 0x54d9, 0x54da, 0x54dc, 0x54a9, 0x54aa, 0x54a4, 0x54dd, 0x54cf, 0x54de, 0x551b, 0x54e7, 0x5520, 0x54fd, 0x5514, 0x54f3, 0x5522, 0x5523, 0x550f, 0x5511, 0x5527, 0x552a, 0x5567, 0x558f, 0x55b5, 0x5549, 0x556d, 0x5541, 0x5555, 0x553f, 0x5550, 0x553c, /* 0xe0 */ 0x90c2, 0x90c3, 0x90c6, 0x90c8, 0x90c9, 0x90cb, 0x90cc, 0x90cd, 0x90d2, 0x90d4, 0x90d5, 0x90d6, 0x90d8, 0x90d9, 0x90da, 0x90de, 0x90df, 0x90e0, 0x90e3, 0x90e4, 0x90e5, 0x90e9, 0x90ea, 0x90ec, 0x90ee, 0x90f0, 0x90f1, 0x90f2, 0x90f3, 0x90f5, 0x90f6, 0x90f7, 0x90f9, 0x90fa, 0x90fb, 0x90fc, 0x90ff, 0x9100, 0x9101, 0x9103, 0x9105, 0x9106, 0x9107, 0x9108, 0x9109, 0x910a, 0x910b, 0x910c, 0x910d, 0x910e, 0x910f, 0x9110, 0x9111, 0x9112, 0x9113, 0x9114, 0x9115, 0x9116, 0x9117, 0x9118, 0x911a, 0x911b, 0x911c, 0x911d, 0x911f, 0x9120, 0x9121, 0x9124, 0x9125, 0x9126, 0x9127, 0x9128, 0x9129, 0x912a, 0x912b, 0x912c, 0x912d, 0x912e, 0x9130, 0x9132, 0x9133, 0x9134, 0x9135, 0x9136, 0x9137, 0x9138, 0x913a, 0x913b, 0x913c, 0x913d, 0x913e, 0x913f, 0x9140, 0x9141, 0x9142, 0x9144, 0x5537, 0x5556, 0x5575, 0x5576, 0x5577, 0x5533, 0x5530, 0x555c, 0x558b, 0x55d2, 0x5583, 0x55b1, 0x55b9, 0x5588, 0x5581, 0x559f, 0x557e, 0x55d6, 0x5591, 0x557b, 0x55df, 0x55bd, 0x55be, 0x5594, 0x5599, 0x55ea, 0x55f7, 0x55c9, 0x561f, 0x55d1, 0x55eb, 0x55ec, 0x55d4, 0x55e6, 0x55dd, 0x55c4, 0x55ef, 0x55e5, 0x55f2, 0x55f3, 0x55cc, 0x55cd, 0x55e8, 0x55f5, 0x55e4, 0x8f94, 0x561e, 0x5608, 0x560c, 0x5601, 0x5624, 0x5623, 0x55fe, 0x5600, 0x5627, 0x562d, 0x5658, 0x5639, 0x5657, 0x562c, 0x564d, 0x5662, 0x5659, 0x565c, 0x564c, 0x5654, 0x5686, 0x5664, 0x5671, 0x566b, 0x567b, 0x567c, 0x5685, 0x5693, 0x56af, 0x56d4, 0x56d7, 0x56dd, 0x56e1, 0x56f5, 0x56eb, 0x56f9, 0x56ff, 0x5704, 0x570a, 0x5709, 0x571c, 0x5e0f, 0x5e19, 0x5e14, 0x5e11, 0x5e31, 0x5e3b, 0x5e3c, /* 0xe1 */ 0x9145, 0x9147, 0x9148, 0x9151, 0x9153, 0x9154, 0x9155, 0x9156, 0x9158, 0x9159, 0x915b, 0x915c, 0x915f, 0x9160, 0x9166, 0x9167, 0x9168, 0x916b, 0x916d, 0x9173, 0x917a, 0x917b, 0x917c, 0x9180, 0x9181, 0x9182, 0x9183, 0x9184, 0x9186, 0x9188, 0x918a, 0x918e, 0x918f, 0x9193, 0x9194, 0x9195, 0x9196, 0x9197, 0x9198, 0x9199, 0x919c, 0x919d, 0x919e, 0x919f, 0x91a0, 0x91a1, 0x91a4, 0x91a5, 0x91a6, 0x91a7, 0x91a8, 0x91a9, 0x91ab, 0x91ac, 0x91b0, 0x91b1, 0x91b2, 0x91b3, 0x91b6, 0x91b7, 0x91b8, 0x91b9, 0x91bb, 0x91bc, 0x91bd, 0x91be, 0x91bf, 0x91c0, 0x91c1, 0x91c2, 0x91c3, 0x91c4, 0x91c5, 0x91c6, 0x91c8, 0x91cb, 0x91d0, 0x91d2, 0x91d3, 0x91d4, 0x91d5, 0x91d6, 0x91d7, 0x91d8, 0x91d9, 0x91da, 0x91db, 0x91dd, 0x91de, 0x91df, 0x91e0, 0x91e1, 0x91e2, 0x91e3, 0x91e4, 0x91e5, 0x5e37, 0x5e44, 0x5e54, 0x5e5b, 0x5e5e, 0x5e61, 0x5c8c, 0x5c7a, 0x5c8d, 0x5c90, 0x5c96, 0x5c88, 0x5c98, 0x5c99, 0x5c91, 0x5c9a, 0x5c9c, 0x5cb5, 0x5ca2, 0x5cbd, 0x5cac, 0x5cab, 0x5cb1, 0x5ca3, 0x5cc1, 0x5cb7, 0x5cc4, 0x5cd2, 0x5ce4, 0x5ccb, 0x5ce5, 0x5d02, 0x5d03, 0x5d27, 0x5d26, 0x5d2e, 0x5d24, 0x5d1e, 0x5d06, 0x5d1b, 0x5d58, 0x5d3e, 0x5d34, 0x5d3d, 0x5d6c, 0x5d5b, 0x5d6f, 0x5d5d, 0x5d6b, 0x5d4b, 0x5d4a, 0x5d69, 0x5d74, 0x5d82, 0x5d99, 0x5d9d, 0x8c73, 0x5db7, 0x5dc5, 0x5f73, 0x5f77, 0x5f82, 0x5f87, 0x5f89, 0x5f8c, 0x5f95, 0x5f99, 0x5f9c, 0x5fa8, 0x5fad, 0x5fb5, 0x5fbc, 0x8862, 0x5f61, 0x72ad, 0x72b0, 0x72b4, 0x72b7, 0x72b8, 0x72c3, 0x72c1, 0x72ce, 0x72cd, 0x72d2, 0x72e8, 0x72ef, 0x72e9, 0x72f2, 0x72f4, 0x72f7, 0x7301, 0x72f3, 0x7303, 0x72fa, /* 0xe2 */ 0x91e6, 0x91e7, 0x91e8, 0x91e9, 0x91ea, 0x91eb, 0x91ec, 0x91ed, 0x91ee, 0x91ef, 0x91f0, 0x91f1, 0x91f2, 0x91f3, 0x91f4, 0x91f5, 0x91f6, 0x91f7, 0x91f8, 0x91f9, 0x91fa, 0x91fb, 0x91fc, 0x91fd, 0x91fe, 0x91ff, 0x9200, 0x9201, 0x9202, 0x9203, 0x9204, 0x9205, 0x9206, 0x9207, 0x9208, 0x9209, 0x920a, 0x920b, 0x920c, 0x920d, 0x920e, 0x920f, 0x9210, 0x9211, 0x9212, 0x9213, 0x9214, 0x9215, 0x9216, 0x9217, 0x9218, 0x9219, 0x921a, 0x921b, 0x921c, 0x921d, 0x921e, 0x921f, 0x9220, 0x9221, 0x9222, 0x9223, 0x9224, 0x9225, 0x9226, 0x9227, 0x9228, 0x9229, 0x922a, 0x922b, 0x922c, 0x922d, 0x922e, 0x922f, 0x9230, 0x9231, 0x9232, 0x9233, 0x9234, 0x9235, 0x9236, 0x9237, 0x9238, 0x9239, 0x923a, 0x923b, 0x923c, 0x923d, 0x923e, 0x923f, 0x9240, 0x9241, 0x9242, 0x9243, 0x9244, 0x9245, 0x72fb, 0x7317, 0x7313, 0x7321, 0x730a, 0x731e, 0x731d, 0x7315, 0x7322, 0x7339, 0x7325, 0x732c, 0x7338, 0x7331, 0x7350, 0x734d, 0x7357, 0x7360, 0x736c, 0x736f, 0x737e, 0x821b, 0x5925, 0x98e7, 0x5924, 0x5902, 0x9963, 0x9967, 0x9968, 0x9969, 0x996a, 0x996b, 0x996c, 0x9974, 0x9977, 0x997d, 0x9980, 0x9984, 0x9987, 0x998a, 0x998d, 0x9990, 0x9991, 0x9993, 0x9994, 0x9995, 0x5e80, 0x5e91, 0x5e8b, 0x5e96, 0x5ea5, 0x5ea0, 0x5eb9, 0x5eb5, 0x5ebe, 0x5eb3, 0x8d53, 0x5ed2, 0x5ed1, 0x5edb, 0x5ee8, 0x5eea, 0x81ba, 0x5fc4, 0x5fc9, 0x5fd6, 0x5fcf, 0x6003, 0x5fee, 0x6004, 0x5fe1, 0x5fe4, 0x5ffe, 0x6005, 0x6006, 0x5fea, 0x5fed, 0x5ff8, 0x6019, 0x6035, 0x6026, 0x601b, 0x600f, 0x600d, 0x6029, 0x602b, 0x600a, 0x603f, 0x6021, 0x6078, 0x6079, 0x607b, 0x607a, 0x6042, /* 0xe3 */ 0x9246, 0x9247, 0x9248, 0x9249, 0x924a, 0x924b, 0x924c, 0x924d, 0x924e, 0x924f, 0x9250, 0x9251, 0x9252, 0x9253, 0x9254, 0x9255, 0x9256, 0x9257, 0x9258, 0x9259, 0x925a, 0x925b, 0x925c, 0x925d, 0x925e, 0x925f, 0x9260, 0x9261, 0x9262, 0x9263, 0x9264, 0x9265, 0x9266, 0x9267, 0x9268, 0x9269, 0x926a, 0x926b, 0x926c, 0x926d, 0x926e, 0x926f, 0x9270, 0x9271, 0x9272, 0x9273, 0x9275, 0x9276, 0x9277, 0x9278, 0x9279, 0x927a, 0x927b, 0x927c, 0x927d, 0x927e, 0x927f, 0x9280, 0x9281, 0x9282, 0x9283, 0x9284, 0x9285, 0x9286, 0x9287, 0x9288, 0x9289, 0x928a, 0x928b, 0x928c, 0x928d, 0x928f, 0x9290, 0x9291, 0x9292, 0x9293, 0x9294, 0x9295, 0x9296, 0x9297, 0x9298, 0x9299, 0x929a, 0x929b, 0x929c, 0x929d, 0x929e, 0x929f, 0x92a0, 0x92a1, 0x92a2, 0x92a3, 0x92a4, 0x92a5, 0x92a6, 0x92a7, 0x606a, 0x607d, 0x6096, 0x609a, 0x60ad, 0x609d, 0x6083, 0x6092, 0x608c, 0x609b, 0x60ec, 0x60bb, 0x60b1, 0x60dd, 0x60d8, 0x60c6, 0x60da, 0x60b4, 0x6120, 0x6126, 0x6115, 0x6123, 0x60f4, 0x6100, 0x610e, 0x612b, 0x614a, 0x6175, 0x61ac, 0x6194, 0x61a7, 0x61b7, 0x61d4, 0x61f5, 0x5fdd, 0x96b3, 0x95e9, 0x95eb, 0x95f1, 0x95f3, 0x95f5, 0x95f6, 0x95fc, 0x95fe, 0x9603, 0x9604, 0x9606, 0x9608, 0x960a, 0x960b, 0x960c, 0x960d, 0x960f, 0x9612, 0x9615, 0x9616, 0x9617, 0x9619, 0x961a, 0x4e2c, 0x723f, 0x6215, 0x6c35, 0x6c54, 0x6c5c, 0x6c4a, 0x6ca3, 0x6c85, 0x6c90, 0x6c94, 0x6c8c, 0x6c68, 0x6c69, 0x6c74, 0x6c76, 0x6c86, 0x6ca9, 0x6cd0, 0x6cd4, 0x6cad, 0x6cf7, 0x6cf8, 0x6cf1, 0x6cd7, 0x6cb2, 0x6ce0, 0x6cd6, 0x6cfa, 0x6ceb, 0x6cee, 0x6cb1, 0x6cd3, 0x6cef, 0x6cfe, /* 0xe4 */ 0x92a8, 0x92a9, 0x92aa, 0x92ab, 0x92ac, 0x92ad, 0x92af, 0x92b0, 0x92b1, 0x92b2, 0x92b3, 0x92b4, 0x92b5, 0x92b6, 0x92b7, 0x92b8, 0x92b9, 0x92ba, 0x92bb, 0x92bc, 0x92bd, 0x92be, 0x92bf, 0x92c0, 0x92c1, 0x92c2, 0x92c3, 0x92c4, 0x92c5, 0x92c6, 0x92c7, 0x92c9, 0x92ca, 0x92cb, 0x92cc, 0x92cd, 0x92ce, 0x92cf, 0x92d0, 0x92d1, 0x92d2, 0x92d3, 0x92d4, 0x92d5, 0x92d6, 0x92d7, 0x92d8, 0x92d9, 0x92da, 0x92db, 0x92dc, 0x92dd, 0x92de, 0x92df, 0x92e0, 0x92e1, 0x92e2, 0x92e3, 0x92e4, 0x92e5, 0x92e6, 0x92e7, 0x92e8, 0x92e9, 0x92ea, 0x92eb, 0x92ec, 0x92ed, 0x92ee, 0x92ef, 0x92f0, 0x92f1, 0x92f2, 0x92f3, 0x92f4, 0x92f5, 0x92f6, 0x92f7, 0x92f8, 0x92f9, 0x92fa, 0x92fb, 0x92fc, 0x92fd, 0x92fe, 0x92ff, 0x9300, 0x9301, 0x9302, 0x9303, 0x9304, 0x9305, 0x9306, 0x9307, 0x9308, 0x9309, 0x6d39, 0x6d27, 0x6d0c, 0x6d43, 0x6d48, 0x6d07, 0x6d04, 0x6d19, 0x6d0e, 0x6d2b, 0x6d4d, 0x6d2e, 0x6d35, 0x6d1a, 0x6d4f, 0x6d52, 0x6d54, 0x6d33, 0x6d91, 0x6d6f, 0x6d9e, 0x6da0, 0x6d5e, 0x6d93, 0x6d94, 0x6d5c, 0x6d60, 0x6d7c, 0x6d63, 0x6e1a, 0x6dc7, 0x6dc5, 0x6dde, 0x6e0e, 0x6dbf, 0x6de0, 0x6e11, 0x6de6, 0x6ddd, 0x6dd9, 0x6e16, 0x6dab, 0x6e0c, 0x6dae, 0x6e2b, 0x6e6e, 0x6e4e, 0x6e6b, 0x6eb2, 0x6e5f, 0x6e86, 0x6e53, 0x6e54, 0x6e32, 0x6e25, 0x6e44, 0x6edf, 0x6eb1, 0x6e98, 0x6ee0, 0x6f2d, 0x6ee2, 0x6ea5, 0x6ea7, 0x6ebd, 0x6ebb, 0x6eb7, 0x6ed7, 0x6eb4, 0x6ecf, 0x6e8f, 0x6ec2, 0x6e9f, 0x6f62, 0x6f46, 0x6f47, 0x6f24, 0x6f15, 0x6ef9, 0x6f2f, 0x6f36, 0x6f4b, 0x6f74, 0x6f2a, 0x6f09, 0x6f29, 0x6f89, 0x6f8d, 0x6f8c, 0x6f78, 0x6f72, 0x6f7c, 0x6f7a, 0x6fd1, /* 0xe5 */ 0x930a, 0x930b, 0x930c, 0x930d, 0x930e, 0x930f, 0x9310, 0x9311, 0x9312, 0x9313, 0x9314, 0x9315, 0x9316, 0x9317, 0x9318, 0x9319, 0x931a, 0x931b, 0x931c, 0x931d, 0x931e, 0x931f, 0x9320, 0x9321, 0x9322, 0x9323, 0x9324, 0x9325, 0x9326, 0x9327, 0x9328, 0x9329, 0x932a, 0x932b, 0x932c, 0x932d, 0x932e, 0x932f, 0x9330, 0x9331, 0x9332, 0x9333, 0x9334, 0x9335, 0x9336, 0x9337, 0x9338, 0x9339, 0x933a, 0x933b, 0x933c, 0x933d, 0x933f, 0x9340, 0x9341, 0x9342, 0x9343, 0x9344, 0x9345, 0x9346, 0x9347, 0x9348, 0x9349, 0x934a, 0x934b, 0x934c, 0x934d, 0x934e, 0x934f, 0x9350, 0x9351, 0x9352, 0x9353, 0x9354, 0x9355, 0x9356, 0x9357, 0x9358, 0x9359, 0x935a, 0x935b, 0x935c, 0x935d, 0x935e, 0x935f, 0x9360, 0x9361, 0x9362, 0x9363, 0x9364, 0x9365, 0x9366, 0x9367, 0x9368, 0x9369, 0x936b, 0x6fc9, 0x6fa7, 0x6fb9, 0x6fb6, 0x6fc2, 0x6fe1, 0x6fee, 0x6fde, 0x6fe0, 0x6fef, 0x701a, 0x7023, 0x701b, 0x7039, 0x7035, 0x704f, 0x705e, 0x5b80, 0x5b84, 0x5b95, 0x5b93, 0x5ba5, 0x5bb8, 0x752f, 0x9a9e, 0x6434, 0x5be4, 0x5bee, 0x8930, 0x5bf0, 0x8e47, 0x8b07, 0x8fb6, 0x8fd3, 0x8fd5, 0x8fe5, 0x8fee, 0x8fe4, 0x8fe9, 0x8fe6, 0x8ff3, 0x8fe8, 0x9005, 0x9004, 0x900b, 0x9026, 0x9011, 0x900d, 0x9016, 0x9021, 0x9035, 0x9036, 0x902d, 0x902f, 0x9044, 0x9051, 0x9052, 0x9050, 0x9068, 0x9058, 0x9062, 0x905b, 0x66b9, 0x9074, 0x907d, 0x9082, 0x9088, 0x9083, 0x908b, 0x5f50, 0x5f57, 0x5f56, 0x5f58, 0x5c3b, 0x54ab, 0x5c50, 0x5c59, 0x5b71, 0x5c63, 0x5c66, 0x7fbc, 0x5f2a, 0x5f29, 0x5f2d, 0x8274, 0x5f3c, 0x9b3b, 0x5c6e, 0x5981, 0x5983, 0x598d, 0x59a9, 0x59aa, 0x59a3, /* 0xe6 */ 0x936c, 0x936d, 0x936e, 0x936f, 0x9370, 0x9371, 0x9372, 0x9373, 0x9374, 0x9375, 0x9376, 0x9377, 0x9378, 0x9379, 0x937a, 0x937b, 0x937c, 0x937d, 0x937e, 0x937f, 0x9380, 0x9381, 0x9382, 0x9383, 0x9384, 0x9385, 0x9386, 0x9387, 0x9388, 0x9389, 0x938a, 0x938b, 0x938c, 0x938d, 0x938e, 0x9390, 0x9391, 0x9392, 0x9393, 0x9394, 0x9395, 0x9396, 0x9397, 0x9398, 0x9399, 0x939a, 0x939b, 0x939c, 0x939d, 0x939e, 0x939f, 0x93a0, 0x93a1, 0x93a2, 0x93a3, 0x93a4, 0x93a5, 0x93a6, 0x93a7, 0x93a8, 0x93a9, 0x93aa, 0x93ab, 0x93ac, 0x93ad, 0x93ae, 0x93af, 0x93b0, 0x93b1, 0x93b2, 0x93b3, 0x93b4, 0x93b5, 0x93b6, 0x93b7, 0x93b8, 0x93b9, 0x93ba, 0x93bb, 0x93bc, 0x93bd, 0x93be, 0x93bf, 0x93c0, 0x93c1, 0x93c2, 0x93c3, 0x93c4, 0x93c5, 0x93c6, 0x93c7, 0x93c8, 0x93c9, 0x93cb, 0x93cc, 0x93cd, 0x5997, 0x59ca, 0x59ab, 0x599e, 0x59a4, 0x59d2, 0x59b2, 0x59af, 0x59d7, 0x59be, 0x5a05, 0x5a06, 0x59dd, 0x5a08, 0x59e3, 0x59d8, 0x59f9, 0x5a0c, 0x5a09, 0x5a32, 0x5a34, 0x5a11, 0x5a23, 0x5a13, 0x5a40, 0x5a67, 0x5a4a, 0x5a55, 0x5a3c, 0x5a62, 0x5a75, 0x80ec, 0x5aaa, 0x5a9b, 0x5a77, 0x5a7a, 0x5abe, 0x5aeb, 0x5ab2, 0x5ad2, 0x5ad4, 0x5ab8, 0x5ae0, 0x5ae3, 0x5af1, 0x5ad6, 0x5ae6, 0x5ad8, 0x5adc, 0x5b09, 0x5b17, 0x5b16, 0x5b32, 0x5b37, 0x5b40, 0x5c15, 0x5c1c, 0x5b5a, 0x5b65, 0x5b73, 0x5b51, 0x5b53, 0x5b62, 0x9a75, 0x9a77, 0x9a78, 0x9a7a, 0x9a7f, 0x9a7d, 0x9a80, 0x9a81, 0x9a85, 0x9a88, 0x9a8a, 0x9a90, 0x9a92, 0x9a93, 0x9a96, 0x9a98, 0x9a9b, 0x9a9c, 0x9a9d, 0x9a9f, 0x9aa0, 0x9aa2, 0x9aa3, 0x9aa5, 0x9aa7, 0x7e9f, 0x7ea1, 0x7ea3, 0x7ea5, 0x7ea8, 0x7ea9, /* 0xe7 */ 0x93ce, 0x93cf, 0x93d0, 0x93d1, 0x93d2, 0x93d3, 0x93d4, 0x93d5, 0x93d7, 0x93d8, 0x93d9, 0x93da, 0x93db, 0x93dc, 0x93dd, 0x93de, 0x93df, 0x93e0, 0x93e1, 0x93e2, 0x93e3, 0x93e4, 0x93e5, 0x93e6, 0x93e7, 0x93e8, 0x93e9, 0x93ea, 0x93eb, 0x93ec, 0x93ed, 0x93ee, 0x93ef, 0x93f0, 0x93f1, 0x93f2, 0x93f3, 0x93f4, 0x93f5, 0x93f6, 0x93f7, 0x93f8, 0x93f9, 0x93fa, 0x93fb, 0x93fc, 0x93fd, 0x93fe, 0x93ff, 0x9400, 0x9401, 0x9402, 0x9403, 0x9404, 0x9405, 0x9406, 0x9407, 0x9408, 0x9409, 0x940a, 0x940b, 0x940c, 0x940d, 0x940e, 0x940f, 0x9410, 0x9411, 0x9412, 0x9413, 0x9414, 0x9415, 0x9416, 0x9417, 0x9418, 0x9419, 0x941a, 0x941b, 0x941c, 0x941d, 0x941e, 0x941f, 0x9420, 0x9421, 0x9422, 0x9423, 0x9424, 0x9425, 0x9426, 0x9427, 0x9428, 0x9429, 0x942a, 0x942b, 0x942c, 0x942d, 0x942e, 0x7ead, 0x7eb0, 0x7ebe, 0x7ec0, 0x7ec1, 0x7ec2, 0x7ec9, 0x7ecb, 0x7ecc, 0x7ed0, 0x7ed4, 0x7ed7, 0x7edb, 0x7ee0, 0x7ee1, 0x7ee8, 0x7eeb, 0x7eee, 0x7eef, 0x7ef1, 0x7ef2, 0x7f0d, 0x7ef6, 0x7efa, 0x7efb, 0x7efe, 0x7f01, 0x7f02, 0x7f03, 0x7f07, 0x7f08, 0x7f0b, 0x7f0c, 0x7f0f, 0x7f11, 0x7f12, 0x7f17, 0x7f19, 0x7f1c, 0x7f1b, 0x7f1f, 0x7f21, 0x7f22, 0x7f23, 0x7f24, 0x7f25, 0x7f26, 0x7f27, 0x7f2a, 0x7f2b, 0x7f2c, 0x7f2d, 0x7f2f, 0x7f30, 0x7f31, 0x7f32, 0x7f33, 0x7f35, 0x5e7a, 0x757f, 0x5ddb, 0x753e, 0x9095, 0x738e, 0x7391, 0x73ae, 0x73a2, 0x739f, 0x73cf, 0x73c2, 0x73d1, 0x73b7, 0x73b3, 0x73c0, 0x73c9, 0x73c8, 0x73e5, 0x73d9, 0x987c, 0x740a, 0x73e9, 0x73e7, 0x73de, 0x73ba, 0x73f2, 0x740f, 0x742a, 0x745b, 0x7426, 0x7425, 0x7428, 0x7430, 0x742e, 0x742c, /* 0xe8 */ 0x942f, 0x9430, 0x9431, 0x9432, 0x9433, 0x9434, 0x9435, 0x9436, 0x9437, 0x9438, 0x9439, 0x943a, 0x943b, 0x943c, 0x943d, 0x943f, 0x9440, 0x9441, 0x9442, 0x9443, 0x9444, 0x9445, 0x9446, 0x9447, 0x9448, 0x9449, 0x944a, 0x944b, 0x944c, 0x944d, 0x944e, 0x944f, 0x9450, 0x9451, 0x9452, 0x9453, 0x9454, 0x9455, 0x9456, 0x9457, 0x9458, 0x9459, 0x945a, 0x945b, 0x945c, 0x945d, 0x945e, 0x945f, 0x9460, 0x9461, 0x9462, 0x9463, 0x9464, 0x9465, 0x9466, 0x9467, 0x9468, 0x9469, 0x946a, 0x946c, 0x946d, 0x946e, 0x946f, 0x9470, 0x9471, 0x9472, 0x9473, 0x9474, 0x9475, 0x9476, 0x9477, 0x9478, 0x9479, 0x947a, 0x947b, 0x947c, 0x947d, 0x947e, 0x947f, 0x9480, 0x9481, 0x9482, 0x9483, 0x9484, 0x9491, 0x9496, 0x9498, 0x94c7, 0x94cf, 0x94d3, 0x94d4, 0x94da, 0x94e6, 0x94fb, 0x951c, 0x9520, 0x741b, 0x741a, 0x7441, 0x745c, 0x7457, 0x7455, 0x7459, 0x7477, 0x746d, 0x747e, 0x749c, 0x748e, 0x7480, 0x7481, 0x7487, 0x748b, 0x749e, 0x74a8, 0x74a9, 0x7490, 0x74a7, 0x74d2, 0x74ba, 0x97ea, 0x97eb, 0x97ec, 0x674c, 0x6753, 0x675e, 0x6748, 0x6769, 0x67a5, 0x6787, 0x676a, 0x6773, 0x6798, 0x67a7, 0x6775, 0x67a8, 0x679e, 0x67ad, 0x678b, 0x6777, 0x677c, 0x67f0, 0x6809, 0x67d8, 0x680a, 0x67e9, 0x67b0, 0x680c, 0x67d9, 0x67b5, 0x67da, 0x67b3, 0x67dd, 0x6800, 0x67c3, 0x67b8, 0x67e2, 0x680e, 0x67c1, 0x67fd, 0x6832, 0x6833, 0x6860, 0x6861, 0x684e, 0x6862, 0x6844, 0x6864, 0x6883, 0x681d, 0x6855, 0x6866, 0x6841, 0x6867, 0x6840, 0x683e, 0x684a, 0x6849, 0x6829, 0x68b5, 0x688f, 0x6874, 0x6877, 0x6893, 0x686b, 0x68c2, 0x696e, 0x68fc, 0x691f, 0x6920, 0x68f9, /* 0xe9 */ 0x9527, 0x9533, 0x953d, 0x9543, 0x9548, 0x954b, 0x9555, 0x955a, 0x9560, 0x956e, 0x9574, 0x9575, 0x9577, 0x9578, 0x9579, 0x957a, 0x957b, 0x957c, 0x957d, 0x957e, 0x9580, 0x9581, 0x9582, 0x9583, 0x9584, 0x9585, 0x9586, 0x9587, 0x9588, 0x9589, 0x958a, 0x958b, 0x958c, 0x958d, 0x958e, 0x958f, 0x9590, 0x9591, 0x9592, 0x9593, 0x9594, 0x9595, 0x9596, 0x9597, 0x9598, 0x9599, 0x959a, 0x959b, 0x959c, 0x959d, 0x959e, 0x959f, 0x95a0, 0x95a1, 0x95a2, 0x95a3, 0x95a4, 0x95a5, 0x95a6, 0x95a7, 0x95a8, 0x95a9, 0x95aa, 0x95ab, 0x95ac, 0x95ad, 0x95ae, 0x95af, 0x95b0, 0x95b1, 0x95b2, 0x95b3, 0x95b4, 0x95b5, 0x95b6, 0x95b7, 0x95b8, 0x95b9, 0x95ba, 0x95bb, 0x95bc, 0x95bd, 0x95be, 0x95bf, 0x95c0, 0x95c1, 0x95c2, 0x95c3, 0x95c4, 0x95c5, 0x95c6, 0x95c7, 0x95c8, 0x95c9, 0x95ca, 0x95cb, 0x6924, 0x68f0, 0x690b, 0x6901, 0x6957, 0x68e3, 0x6910, 0x6971, 0x6939, 0x6960, 0x6942, 0x695d, 0x6984, 0x696b, 0x6980, 0x6998, 0x6978, 0x6934, 0x69cc, 0x6987, 0x6988, 0x69ce, 0x6989, 0x6966, 0x6963, 0x6979, 0x699b, 0x69a7, 0x69bb, 0x69ab, 0x69ad, 0x69d4, 0x69b1, 0x69c1, 0x69ca, 0x69df, 0x6995, 0x69e0, 0x698d, 0x69ff, 0x6a2f, 0x69ed, 0x6a17, 0x6a18, 0x6a65, 0x69f2, 0x6a44, 0x6a3e, 0x6aa0, 0x6a50, 0x6a5b, 0x6a35, 0x6a8e, 0x6a79, 0x6a3d, 0x6a28, 0x6a58, 0x6a7c, 0x6a91, 0x6a90, 0x6aa9, 0x6a97, 0x6aab, 0x7337, 0x7352, 0x6b81, 0x6b82, 0x6b87, 0x6b84, 0x6b92, 0x6b93, 0x6b8d, 0x6b9a, 0x6b9b, 0x6ba1, 0x6baa, 0x8f6b, 0x8f6d, 0x8f71, 0x8f72, 0x8f73, 0x8f75, 0x8f76, 0x8f78, 0x8f77, 0x8f79, 0x8f7a, 0x8f7c, 0x8f7e, 0x8f81, 0x8f82, 0x8f84, 0x8f87, 0x8f8b, /* 0xea */ 0x95cc, 0x95cd, 0x95ce, 0x95cf, 0x95d0, 0x95d1, 0x95d2, 0x95d3, 0x95d4, 0x95d5, 0x95d6, 0x95d7, 0x95d8, 0x95d9, 0x95da, 0x95db, 0x95dc, 0x95dd, 0x95de, 0x95df, 0x95e0, 0x95e1, 0x95e2, 0x95e3, 0x95e4, 0x95e5, 0x95e6, 0x95e7, 0x95ec, 0x95ff, 0x9607, 0x9613, 0x9618, 0x961b, 0x961e, 0x9620, 0x9623, 0x9624, 0x9625, 0x9626, 0x9627, 0x9628, 0x9629, 0x962b, 0x962c, 0x962d, 0x962f, 0x9630, 0x9637, 0x9638, 0x9639, 0x963a, 0x963e, 0x9641, 0x9643, 0x964a, 0x964e, 0x964f, 0x9651, 0x9652, 0x9653, 0x9656, 0x9657, 0x9658, 0x9659, 0x965a, 0x965c, 0x965d, 0x965e, 0x9660, 0x9663, 0x9665, 0x9666, 0x966b, 0x966d, 0x966e, 0x966f, 0x9670, 0x9671, 0x9673, 0x9678, 0x9679, 0x967a, 0x967b, 0x967c, 0x967d, 0x967e, 0x967f, 0x9680, 0x9681, 0x9682, 0x9683, 0x9684, 0x9687, 0x9689, 0x968a, 0x8f8d, 0x8f8e, 0x8f8f, 0x8f98, 0x8f9a, 0x8ece, 0x620b, 0x6217, 0x621b, 0x621f, 0x6222, 0x6221, 0x6225, 0x6224, 0x622c, 0x81e7, 0x74ef, 0x74f4, 0x74ff, 0x750f, 0x7511, 0x7513, 0x6534, 0x65ee, 0x65ef, 0x65f0, 0x660a, 0x6619, 0x6772, 0x6603, 0x6615, 0x6600, 0x7085, 0x66f7, 0x661d, 0x6634, 0x6631, 0x6636, 0x6635, 0x8006, 0x665f, 0x6654, 0x6641, 0x664f, 0x6656, 0x6661, 0x6657, 0x6677, 0x6684, 0x668c, 0x66a7, 0x669d, 0x66be, 0x66db, 0x66dc, 0x66e6, 0x66e9, 0x8d32, 0x8d33, 0x8d36, 0x8d3b, 0x8d3d, 0x8d40, 0x8d45, 0x8d46, 0x8d48, 0x8d49, 0x8d47, 0x8d4d, 0x8d55, 0x8d59, 0x89c7, 0x89ca, 0x89cb, 0x89cc, 0x89ce, 0x89cf, 0x89d0, 0x89d1, 0x726e, 0x729f, 0x725d, 0x7266, 0x726f, 0x727e, 0x727f, 0x7284, 0x728b, 0x728d, 0x728f, 0x7292, 0x6308, 0x6332, 0x63b0, /* 0xeb */ 0x968c, 0x968e, 0x9691, 0x9692, 0x9693, 0x9695, 0x9696, 0x969a, 0x969b, 0x969d, 0x969e, 0x969f, 0x96a0, 0x96a1, 0x96a2, 0x96a3, 0x96a4, 0x96a5, 0x96a6, 0x96a8, 0x96a9, 0x96aa, 0x96ab, 0x96ac, 0x96ad, 0x96ae, 0x96af, 0x96b1, 0x96b2, 0x96b4, 0x96b5, 0x96b7, 0x96b8, 0x96ba, 0x96bb, 0x96bf, 0x96c2, 0x96c3, 0x96c8, 0x96ca, 0x96cb, 0x96d0, 0x96d1, 0x96d3, 0x96d4, 0x96d6, 0x96d7, 0x96d8, 0x96d9, 0x96da, 0x96db, 0x96dc, 0x96dd, 0x96de, 0x96df, 0x96e1, 0x96e2, 0x96e3, 0x96e4, 0x96e5, 0x96e6, 0x96e7, 0x96eb, 0x96ec, 0x96ed, 0x96ee, 0x96f0, 0x96f1, 0x96f2, 0x96f4, 0x96f5, 0x96f8, 0x96fa, 0x96fb, 0x96fc, 0x96fd, 0x96ff, 0x9702, 0x9703, 0x9705, 0x970a, 0x970b, 0x970c, 0x9710, 0x9711, 0x9712, 0x9714, 0x9715, 0x9717, 0x9718, 0x9719, 0x971a, 0x971b, 0x971d, 0x971f, 0x9720, 0x643f, 0x64d8, 0x8004, 0x6bea, 0x6bf3, 0x6bfd, 0x6bf5, 0x6bf9, 0x6c05, 0x6c07, 0x6c06, 0x6c0d, 0x6c15, 0x6c18, 0x6c19, 0x6c1a, 0x6c21, 0x6c29, 0x6c24, 0x6c2a, 0x6c32, 0x6535, 0x6555, 0x656b, 0x724d, 0x7252, 0x7256, 0x7230, 0x8662, 0x5216, 0x809f, 0x809c, 0x8093, 0x80bc, 0x670a, 0x80bd, 0x80b1, 0x80ab, 0x80ad, 0x80b4, 0x80b7, 0x80e7, 0x80e8, 0x80e9, 0x80ea, 0x80db, 0x80c2, 0x80c4, 0x80d9, 0x80cd, 0x80d7, 0x6710, 0x80dd, 0x80eb, 0x80f1, 0x80f4, 0x80ed, 0x810d, 0x810e, 0x80f2, 0x80fc, 0x6715, 0x8112, 0x8c5a, 0x8136, 0x811e, 0x812c, 0x8118, 0x8132, 0x8148, 0x814c, 0x8153, 0x8174, 0x8159, 0x815a, 0x8171, 0x8160, 0x8169, 0x817c, 0x817d, 0x816d, 0x8167, 0x584d, 0x5ab5, 0x8188, 0x8182, 0x8191, 0x6ed5, 0x81a3, 0x81aa, 0x81cc, 0x6726, 0x81ca, 0x81bb, /* 0xec */ 0x9721, 0x9722, 0x9723, 0x9724, 0x9725, 0x9726, 0x9727, 0x9728, 0x9729, 0x972b, 0x972c, 0x972e, 0x972f, 0x9731, 0x9733, 0x9734, 0x9735, 0x9736, 0x9737, 0x973a, 0x973b, 0x973c, 0x973d, 0x973f, 0x9740, 0x9741, 0x9742, 0x9743, 0x9744, 0x9745, 0x9746, 0x9747, 0x9748, 0x9749, 0x974a, 0x974b, 0x974c, 0x974d, 0x974e, 0x974f, 0x9750, 0x9751, 0x9754, 0x9755, 0x9757, 0x9758, 0x975a, 0x975c, 0x975d, 0x975f, 0x9763, 0x9764, 0x9766, 0x9767, 0x9768, 0x976a, 0x976b, 0x976c, 0x976d, 0x976e, 0x976f, 0x9770, 0x9771, 0x9772, 0x9775, 0x9777, 0x9778, 0x9779, 0x977a, 0x977b, 0x977d, 0x977e, 0x977f, 0x9780, 0x9781, 0x9782, 0x9783, 0x9784, 0x9786, 0x9787, 0x9788, 0x9789, 0x978a, 0x978c, 0x978e, 0x978f, 0x9790, 0x9793, 0x9795, 0x9796, 0x9797, 0x9799, 0x979a, 0x979b, 0x979c, 0x979d, 0x81c1, 0x81a6, 0x6b24, 0x6b37, 0x6b39, 0x6b43, 0x6b46, 0x6b59, 0x98d1, 0x98d2, 0x98d3, 0x98d5, 0x98d9, 0x98da, 0x6bb3, 0x5f40, 0x6bc2, 0x89f3, 0x6590, 0x9f51, 0x6593, 0x65bc, 0x65c6, 0x65c4, 0x65c3, 0x65cc, 0x65ce, 0x65d2, 0x65d6, 0x7080, 0x709c, 0x7096, 0x709d, 0x70bb, 0x70c0, 0x70b7, 0x70ab, 0x70b1, 0x70e8, 0x70ca, 0x7110, 0x7113, 0x7116, 0x712f, 0x7131, 0x7173, 0x715c, 0x7168, 0x7145, 0x7172, 0x714a, 0x7178, 0x717a, 0x7198, 0x71b3, 0x71b5, 0x71a8, 0x71a0, 0x71e0, 0x71d4, 0x71e7, 0x71f9, 0x721d, 0x7228, 0x706c, 0x7118, 0x7166, 0x71b9, 0x623e, 0x623d, 0x6243, 0x6248, 0x6249, 0x793b, 0x7940, 0x7946, 0x7949, 0x795b, 0x795c, 0x7953, 0x795a, 0x7962, 0x7957, 0x7960, 0x796f, 0x7967, 0x797a, 0x7985, 0x798a, 0x799a, 0x79a7, 0x79b3, 0x5fd1, 0x5fd0, /* 0xed */ 0x979e, 0x979f, 0x97a1, 0x97a2, 0x97a4, 0x97a5, 0x97a6, 0x97a7, 0x97a8, 0x97a9, 0x97aa, 0x97ac, 0x97ae, 0x97b0, 0x97b1, 0x97b3, 0x97b5, 0x97b6, 0x97b7, 0x97b8, 0x97b9, 0x97ba, 0x97bb, 0x97bc, 0x97bd, 0x97be, 0x97bf, 0x97c0, 0x97c1, 0x97c2, 0x97c3, 0x97c4, 0x97c5, 0x97c6, 0x97c7, 0x97c8, 0x97c9, 0x97ca, 0x97cb, 0x97cc, 0x97cd, 0x97ce, 0x97cf, 0x97d0, 0x97d1, 0x97d2, 0x97d3, 0x97d4, 0x97d5, 0x97d6, 0x97d7, 0x97d8, 0x97d9, 0x97da, 0x97db, 0x97dc, 0x97dd, 0x97de, 0x97df, 0x97e0, 0x97e1, 0x97e2, 0x97e3, 0x97e4, 0x97e5, 0x97e8, 0x97ee, 0x97ef, 0x97f0, 0x97f1, 0x97f2, 0x97f4, 0x97f7, 0x97f8, 0x97f9, 0x97fa, 0x97fb, 0x97fc, 0x97fd, 0x97fe, 0x97ff, 0x9800, 0x9801, 0x9802, 0x9803, 0x9804, 0x9805, 0x9806, 0x9807, 0x9808, 0x9809, 0x980a, 0x980b, 0x980c, 0x980d, 0x980e, 0x603c, 0x605d, 0x605a, 0x6067, 0x6041, 0x6059, 0x6063, 0x60ab, 0x6106, 0x610d, 0x615d, 0x61a9, 0x619d, 0x61cb, 0x61d1, 0x6206, 0x8080, 0x807f, 0x6c93, 0x6cf6, 0x6dfc, 0x77f6, 0x77f8, 0x7800, 0x7809, 0x7817, 0x7818, 0x7811, 0x65ab, 0x782d, 0x781c, 0x781d, 0x7839, 0x783a, 0x783b, 0x781f, 0x783c, 0x7825, 0x782c, 0x7823, 0x7829, 0x784e, 0x786d, 0x7856, 0x7857, 0x7826, 0x7850, 0x7847, 0x784c, 0x786a, 0x789b, 0x7893, 0x789a, 0x7887, 0x789c, 0x78a1, 0x78a3, 0x78b2, 0x78b9, 0x78a5, 0x78d4, 0x78d9, 0x78c9, 0x78ec, 0x78f2, 0x7905, 0x78f4, 0x7913, 0x7924, 0x791e, 0x7934, 0x9f9b, 0x9ef9, 0x9efb, 0x9efc, 0x76f1, 0x7704, 0x770d, 0x76f9, 0x7707, 0x7708, 0x771a, 0x7722, 0x7719, 0x772d, 0x7726, 0x7735, 0x7738, 0x7750, 0x7751, 0x7747, 0x7743, 0x775a, 0x7768, /* 0xee */ 0x980f, 0x9810, 0x9811, 0x9812, 0x9813, 0x9814, 0x9815, 0x9816, 0x9817, 0x9818, 0x9819, 0x981a, 0x981b, 0x981c, 0x981d, 0x981e, 0x981f, 0x9820, 0x9821, 0x9822, 0x9823, 0x9824, 0x9825, 0x9826, 0x9827, 0x9828, 0x9829, 0x982a, 0x982b, 0x982c, 0x982d, 0x982e, 0x982f, 0x9830, 0x9831, 0x9832, 0x9833, 0x9834, 0x9835, 0x9836, 0x9837, 0x9838, 0x9839, 0x983a, 0x983b, 0x983c, 0x983d, 0x983e, 0x983f, 0x9840, 0x9841, 0x9842, 0x9843, 0x9844, 0x9845, 0x9846, 0x9847, 0x9848, 0x9849, 0x984a, 0x984b, 0x984c, 0x984d, 0x984e, 0x984f, 0x9850, 0x9851, 0x9852, 0x9853, 0x9854, 0x9855, 0x9856, 0x9857, 0x9858, 0x9859, 0x985a, 0x985b, 0x985c, 0x985d, 0x985e, 0x985f, 0x9860, 0x9861, 0x9862, 0x9863, 0x9864, 0x9865, 0x9866, 0x9867, 0x9868, 0x9869, 0x986a, 0x986b, 0x986c, 0x986d, 0x986e, 0x7762, 0x7765, 0x777f, 0x778d, 0x777d, 0x7780, 0x778c, 0x7791, 0x779f, 0x77a0, 0x77b0, 0x77b5, 0x77bd, 0x753a, 0x7540, 0x754e, 0x754b, 0x7548, 0x755b, 0x7572, 0x7579, 0x7583, 0x7f58, 0x7f61, 0x7f5f, 0x8a48, 0x7f68, 0x7f74, 0x7f71, 0x7f79, 0x7f81, 0x7f7e, 0x76cd, 0x76e5, 0x8832, 0x9485, 0x9486, 0x9487, 0x948b, 0x948a, 0x948c, 0x948d, 0x948f, 0x9490, 0x9494, 0x9497, 0x9495, 0x949a, 0x949b, 0x949c, 0x94a3, 0x94a4, 0x94ab, 0x94aa, 0x94ad, 0x94ac, 0x94af, 0x94b0, 0x94b2, 0x94b4, 0x94b6, 0x94b7, 0x94b8, 0x94b9, 0x94ba, 0x94bc, 0x94bd, 0x94bf, 0x94c4, 0x94c8, 0x94c9, 0x94ca, 0x94cb, 0x94cc, 0x94cd, 0x94ce, 0x94d0, 0x94d1, 0x94d2, 0x94d5, 0x94d6, 0x94d7, 0x94d9, 0x94d8, 0x94db, 0x94de, 0x94df, 0x94e0, 0x94e2, 0x94e4, 0x94e5, 0x94e7, 0x94e8, 0x94ea, /* 0xef */ 0x986f, 0x9870, 0x9871, 0x9872, 0x9873, 0x9874, 0x988b, 0x988e, 0x9892, 0x9895, 0x9899, 0x98a3, 0x98a8, 0x98a9, 0x98aa, 0x98ab, 0x98ac, 0x98ad, 0x98ae, 0x98af, 0x98b0, 0x98b1, 0x98b2, 0x98b3, 0x98b4, 0x98b5, 0x98b6, 0x98b7, 0x98b8, 0x98b9, 0x98ba, 0x98bb, 0x98bc, 0x98bd, 0x98be, 0x98bf, 0x98c0, 0x98c1, 0x98c2, 0x98c3, 0x98c4, 0x98c5, 0x98c6, 0x98c7, 0x98c8, 0x98c9, 0x98ca, 0x98cb, 0x98cc, 0x98cd, 0x98cf, 0x98d0, 0x98d4, 0x98d6, 0x98d7, 0x98db, 0x98dc, 0x98dd, 0x98e0, 0x98e1, 0x98e2, 0x98e3, 0x98e4, 0x98e5, 0x98e6, 0x98e9, 0x98ea, 0x98eb, 0x98ec, 0x98ed, 0x98ee, 0x98ef, 0x98f0, 0x98f1, 0x98f2, 0x98f3, 0x98f4, 0x98f5, 0x98f6, 0x98f7, 0x98f8, 0x98f9, 0x98fa, 0x98fb, 0x98fc, 0x98fd, 0x98fe, 0x98ff, 0x9900, 0x9901, 0x9902, 0x9903, 0x9904, 0x9905, 0x9906, 0x9907, 0x94e9, 0x94eb, 0x94ee, 0x94ef, 0x94f3, 0x94f4, 0x94f5, 0x94f7, 0x94f9, 0x94fc, 0x94fd, 0x94ff, 0x9503, 0x9502, 0x9506, 0x9507, 0x9509, 0x950a, 0x950d, 0x950e, 0x950f, 0x9512, 0x9513, 0x9514, 0x9515, 0x9516, 0x9518, 0x951b, 0x951d, 0x951e, 0x951f, 0x9522, 0x952a, 0x952b, 0x9529, 0x952c, 0x9531, 0x9532, 0x9534, 0x9536, 0x9537, 0x9538, 0x953c, 0x953e, 0x953f, 0x9542, 0x9535, 0x9544, 0x9545, 0x9546, 0x9549, 0x954c, 0x954e, 0x954f, 0x9552, 0x9553, 0x9554, 0x9556, 0x9557, 0x9558, 0x9559, 0x955b, 0x955e, 0x955f, 0x955d, 0x9561, 0x9562, 0x9564, 0x9565, 0x9566, 0x9567, 0x9568, 0x9569, 0x956a, 0x956b, 0x956c, 0x956f, 0x9571, 0x9572, 0x9573, 0x953a, 0x77e7, 0x77ec, 0x96c9, 0x79d5, 0x79ed, 0x79e3, 0x79eb, 0x7a06, 0x5d47, 0x7a03, 0x7a02, 0x7a1e, 0x7a14, /* 0xf0 */ 0x9908, 0x9909, 0x990a, 0x990b, 0x990c, 0x990e, 0x990f, 0x9911, 0x9912, 0x9913, 0x9914, 0x9915, 0x9916, 0x9917, 0x9918, 0x9919, 0x991a, 0x991b, 0x991c, 0x991d, 0x991e, 0x991f, 0x9920, 0x9921, 0x9922, 0x9923, 0x9924, 0x9925, 0x9926, 0x9927, 0x9928, 0x9929, 0x992a, 0x992b, 0x992c, 0x992d, 0x992f, 0x9930, 0x9931, 0x9932, 0x9933, 0x9934, 0x9935, 0x9936, 0x9937, 0x9938, 0x9939, 0x993a, 0x993b, 0x993c, 0x993d, 0x993e, 0x993f, 0x9940, 0x9941, 0x9942, 0x9943, 0x9944, 0x9945, 0x9946, 0x9947, 0x9948, 0x9949, 0x994a, 0x994b, 0x994c, 0x994d, 0x994e, 0x994f, 0x9950, 0x9951, 0x9952, 0x9953, 0x9956, 0x9957, 0x9958, 0x9959, 0x995a, 0x995b, 0x995c, 0x995d, 0x995e, 0x995f, 0x9960, 0x9961, 0x9962, 0x9964, 0x9966, 0x9973, 0x9978, 0x9979, 0x997b, 0x997e, 0x9982, 0x9983, 0x9989, 0x7a39, 0x7a37, 0x7a51, 0x9ecf, 0x99a5, 0x7a70, 0x7688, 0x768e, 0x7693, 0x7699, 0x76a4, 0x74de, 0x74e0, 0x752c, 0x9e20, 0x9e22, 0x9e28, 0x9e29, 0x9e2a, 0x9e2b, 0x9e2c, 0x9e32, 0x9e31, 0x9e36, 0x9e38, 0x9e37, 0x9e39, 0x9e3a, 0x9e3e, 0x9e41, 0x9e42, 0x9e44, 0x9e46, 0x9e47, 0x9e48, 0x9e49, 0x9e4b, 0x9e4c, 0x9e4e, 0x9e51, 0x9e55, 0x9e57, 0x9e5a, 0x9e5b, 0x9e5c, 0x9e5e, 0x9e63, 0x9e66, 0x9e67, 0x9e68, 0x9e69, 0x9e6a, 0x9e6b, 0x9e6c, 0x9e71, 0x9e6d, 0x9e73, 0x7592, 0x7594, 0x7596, 0x75a0, 0x759d, 0x75ac, 0x75a3, 0x75b3, 0x75b4, 0x75b8, 0x75c4, 0x75b1, 0x75b0, 0x75c3, 0x75c2, 0x75d6, 0x75cd, 0x75e3, 0x75e8, 0x75e6, 0x75e4, 0x75eb, 0x75e7, 0x7603, 0x75f1, 0x75fc, 0x75ff, 0x7610, 0x7600, 0x7605, 0x760c, 0x7617, 0x760a, 0x7625, 0x7618, 0x7615, 0x7619, /* 0xf1 */ 0x998c, 0x998e, 0x999a, 0x999b, 0x999c, 0x999d, 0x999e, 0x999f, 0x99a0, 0x99a1, 0x99a2, 0x99a3, 0x99a4, 0x99a6, 0x99a7, 0x99a9, 0x99aa, 0x99ab, 0x99ac, 0x99ad, 0x99ae, 0x99af, 0x99b0, 0x99b1, 0x99b2, 0x99b3, 0x99b4, 0x99b5, 0x99b6, 0x99b7, 0x99b8, 0x99b9, 0x99ba, 0x99bb, 0x99bc, 0x99bd, 0x99be, 0x99bf, 0x99c0, 0x99c1, 0x99c2, 0x99c3, 0x99c4, 0x99c5, 0x99c6, 0x99c7, 0x99c8, 0x99c9, 0x99ca, 0x99cb, 0x99cc, 0x99cd, 0x99ce, 0x99cf, 0x99d0, 0x99d1, 0x99d2, 0x99d3, 0x99d4, 0x99d5, 0x99d6, 0x99d7, 0x99d8, 0x99d9, 0x99da, 0x99db, 0x99dc, 0x99dd, 0x99de, 0x99df, 0x99e0, 0x99e1, 0x99e2, 0x99e3, 0x99e4, 0x99e5, 0x99e6, 0x99e7, 0x99e8, 0x99e9, 0x99ea, 0x99eb, 0x99ec, 0x99ed, 0x99ee, 0x99ef, 0x99f0, 0x99f1, 0x99f2, 0x99f3, 0x99f4, 0x99f5, 0x99f6, 0x99f7, 0x99f8, 0x99f9, 0x761b, 0x763c, 0x7622, 0x7620, 0x7640, 0x762d, 0x7630, 0x763f, 0x7635, 0x7643, 0x763e, 0x7633, 0x764d, 0x765e, 0x7654, 0x765c, 0x7656, 0x766b, 0x766f, 0x7fca, 0x7ae6, 0x7a78, 0x7a79, 0x7a80, 0x7a86, 0x7a88, 0x7a95, 0x7aa6, 0x7aa0, 0x7aac, 0x7aa8, 0x7aad, 0x7ab3, 0x8864, 0x8869, 0x8872, 0x887d, 0x887f, 0x8882, 0x88a2, 0x88c6, 0x88b7, 0x88bc, 0x88c9, 0x88e2, 0x88ce, 0x88e3, 0x88e5, 0x88f1, 0x891a, 0x88fc, 0x88e8, 0x88fe, 0x88f0, 0x8921, 0x8919, 0x8913, 0x891b, 0x890a, 0x8934, 0x892b, 0x8936, 0x8941, 0x8966, 0x897b, 0x758b, 0x80e5, 0x76b2, 0x76b4, 0x77dc, 0x8012, 0x8014, 0x8016, 0x801c, 0x8020, 0x8022, 0x8025, 0x8026, 0x8027, 0x8029, 0x8028, 0x8031, 0x800b, 0x8035, 0x8043, 0x8046, 0x804d, 0x8052, 0x8069, 0x8071, 0x8983, 0x9878, 0x9880, 0x9883, /* 0xf2 */ 0x99fa, 0x99fb, 0x99fc, 0x99fd, 0x99fe, 0x99ff, 0x9a00, 0x9a01, 0x9a02, 0x9a03, 0x9a04, 0x9a05, 0x9a06, 0x9a07, 0x9a08, 0x9a09, 0x9a0a, 0x9a0b, 0x9a0c, 0x9a0d, 0x9a0e, 0x9a0f, 0x9a10, 0x9a11, 0x9a12, 0x9a13, 0x9a14, 0x9a15, 0x9a16, 0x9a17, 0x9a18, 0x9a19, 0x9a1a, 0x9a1b, 0x9a1c, 0x9a1d, 0x9a1e, 0x9a1f, 0x9a20, 0x9a21, 0x9a22, 0x9a23, 0x9a24, 0x9a25, 0x9a26, 0x9a27, 0x9a28, 0x9a29, 0x9a2a, 0x9a2b, 0x9a2c, 0x9a2d, 0x9a2e, 0x9a2f, 0x9a30, 0x9a31, 0x9a32, 0x9a33, 0x9a34, 0x9a35, 0x9a36, 0x9a37, 0x9a38, 0x9a39, 0x9a3a, 0x9a3b, 0x9a3c, 0x9a3d, 0x9a3e, 0x9a3f, 0x9a40, 0x9a41, 0x9a42, 0x9a43, 0x9a44, 0x9a45, 0x9a46, 0x9a47, 0x9a48, 0x9a49, 0x9a4a, 0x9a4b, 0x9a4c, 0x9a4d, 0x9a4e, 0x9a4f, 0x9a50, 0x9a51, 0x9a52, 0x9a53, 0x9a54, 0x9a55, 0x9a56, 0x9a57, 0x9a58, 0x9a59, 0x9889, 0x988c, 0x988d, 0x988f, 0x9894, 0x989a, 0x989b, 0x989e, 0x989f, 0x98a1, 0x98a2, 0x98a5, 0x98a6, 0x864d, 0x8654, 0x866c, 0x866e, 0x867f, 0x867a, 0x867c, 0x867b, 0x86a8, 0x868d, 0x868b, 0x86ac, 0x869d, 0x86a7, 0x86a3, 0x86aa, 0x8693, 0x86a9, 0x86b6, 0x86c4, 0x86b5, 0x86ce, 0x86b0, 0x86ba, 0x86b1, 0x86af, 0x86c9, 0x86cf, 0x86b4, 0x86e9, 0x86f1, 0x86f2, 0x86ed, 0x86f3, 0x86d0, 0x8713, 0x86de, 0x86f4, 0x86df, 0x86d8, 0x86d1, 0x8703, 0x8707, 0x86f8, 0x8708, 0x870a, 0x870d, 0x8709, 0x8723, 0x873b, 0x871e, 0x8725, 0x872e, 0x871a, 0x873e, 0x8748, 0x8734, 0x8731, 0x8729, 0x8737, 0x873f, 0x8782, 0x8722, 0x877d, 0x877e, 0x877b, 0x8760, 0x8770, 0x874c, 0x876e, 0x878b, 0x8753, 0x8763, 0x877c, 0x8764, 0x8759, 0x8765, 0x8793, 0x87af, 0x87a8, 0x87d2, /* 0xf3 */ 0x9a5a, 0x9a5b, 0x9a5c, 0x9a5d, 0x9a5e, 0x9a5f, 0x9a60, 0x9a61, 0x9a62, 0x9a63, 0x9a64, 0x9a65, 0x9a66, 0x9a67, 0x9a68, 0x9a69, 0x9a6a, 0x9a6b, 0x9a72, 0x9a83, 0x9a89, 0x9a8d, 0x9a8e, 0x9a94, 0x9a95, 0x9a99, 0x9aa6, 0x9aa9, 0x9aaa, 0x9aab, 0x9aac, 0x9aad, 0x9aae, 0x9aaf, 0x9ab2, 0x9ab3, 0x9ab4, 0x9ab5, 0x9ab9, 0x9abb, 0x9abd, 0x9abe, 0x9abf, 0x9ac3, 0x9ac4, 0x9ac6, 0x9ac7, 0x9ac8, 0x9ac9, 0x9aca, 0x9acd, 0x9ace, 0x9acf, 0x9ad0, 0x9ad2, 0x9ad4, 0x9ad5, 0x9ad6, 0x9ad7, 0x9ad9, 0x9ada, 0x9adb, 0x9adc, 0x9add, 0x9ade, 0x9ae0, 0x9ae2, 0x9ae3, 0x9ae4, 0x9ae5, 0x9ae7, 0x9ae8, 0x9ae9, 0x9aea, 0x9aec, 0x9aee, 0x9af0, 0x9af1, 0x9af2, 0x9af3, 0x9af4, 0x9af5, 0x9af6, 0x9af7, 0x9af8, 0x9afa, 0x9afc, 0x9afd, 0x9afe, 0x9aff, 0x9b00, 0x9b01, 0x9b02, 0x9b04, 0x9b05, 0x9b06, 0x87c6, 0x8788, 0x8785, 0x87ad, 0x8797, 0x8783, 0x87ab, 0x87e5, 0x87ac, 0x87b5, 0x87b3, 0x87cb, 0x87d3, 0x87bd, 0x87d1, 0x87c0, 0x87ca, 0x87db, 0x87ea, 0x87e0, 0x87ee, 0x8816, 0x8813, 0x87fe, 0x880a, 0x881b, 0x8821, 0x8839, 0x883c, 0x7f36, 0x7f42, 0x7f44, 0x7f45, 0x8210, 0x7afa, 0x7afd, 0x7b08, 0x7b03, 0x7b04, 0x7b15, 0x7b0a, 0x7b2b, 0x7b0f, 0x7b47, 0x7b38, 0x7b2a, 0x7b19, 0x7b2e, 0x7b31, 0x7b20, 0x7b25, 0x7b24, 0x7b33, 0x7b3e, 0x7b1e, 0x7b58, 0x7b5a, 0x7b45, 0x7b75, 0x7b4c, 0x7b5d, 0x7b60, 0x7b6e, 0x7b7b, 0x7b62, 0x7b72, 0x7b71, 0x7b90, 0x7ba6, 0x7ba7, 0x7bb8, 0x7bac, 0x7b9d, 0x7ba8, 0x7b85, 0x7baa, 0x7b9c, 0x7ba2, 0x7bab, 0x7bb4, 0x7bd1, 0x7bc1, 0x7bcc, 0x7bdd, 0x7bda, 0x7be5, 0x7be6, 0x7bea, 0x7c0c, 0x7bfe, 0x7bfc, 0x7c0f, 0x7c16, 0x7c0b, /* 0xf4 */ 0x9b07, 0x9b09, 0x9b0a, 0x9b0b, 0x9b0c, 0x9b0d, 0x9b0e, 0x9b10, 0x9b11, 0x9b12, 0x9b14, 0x9b15, 0x9b16, 0x9b17, 0x9b18, 0x9b19, 0x9b1a, 0x9b1b, 0x9b1c, 0x9b1d, 0x9b1e, 0x9b20, 0x9b21, 0x9b22, 0x9b24, 0x9b25, 0x9b26, 0x9b27, 0x9b28, 0x9b29, 0x9b2a, 0x9b2b, 0x9b2c, 0x9b2d, 0x9b2e, 0x9b30, 0x9b31, 0x9b33, 0x9b34, 0x9b35, 0x9b36, 0x9b37, 0x9b38, 0x9b39, 0x9b3a, 0x9b3d, 0x9b3e, 0x9b3f, 0x9b40, 0x9b46, 0x9b4a, 0x9b4b, 0x9b4c, 0x9b4e, 0x9b50, 0x9b52, 0x9b53, 0x9b55, 0x9b56, 0x9b57, 0x9b58, 0x9b59, 0x9b5a, 0x9b5b, 0x9b5c, 0x9b5d, 0x9b5e, 0x9b5f, 0x9b60, 0x9b61, 0x9b62, 0x9b63, 0x9b64, 0x9b65, 0x9b66, 0x9b67, 0x9b68, 0x9b69, 0x9b6a, 0x9b6b, 0x9b6c, 0x9b6d, 0x9b6e, 0x9b6f, 0x9b70, 0x9b71, 0x9b72, 0x9b73, 0x9b74, 0x9b75, 0x9b76, 0x9b77, 0x9b78, 0x9b79, 0x9b7a, 0x9b7b, 0x7c1f, 0x7c2a, 0x7c26, 0x7c38, 0x7c41, 0x7c40, 0x81fe, 0x8201, 0x8202, 0x8204, 0x81ec, 0x8844, 0x8221, 0x8222, 0x8223, 0x822d, 0x822f, 0x8228, 0x822b, 0x8238, 0x823b, 0x8233, 0x8234, 0x823e, 0x8244, 0x8249, 0x824b, 0x824f, 0x825a, 0x825f, 0x8268, 0x887e, 0x8885, 0x8888, 0x88d8, 0x88df, 0x895e, 0x7f9d, 0x7f9f, 0x7fa7, 0x7faf, 0x7fb0, 0x7fb2, 0x7c7c, 0x6549, 0x7c91, 0x7c9d, 0x7c9c, 0x7c9e, 0x7ca2, 0x7cb2, 0x7cbc, 0x7cbd, 0x7cc1, 0x7cc7, 0x7ccc, 0x7ccd, 0x7cc8, 0x7cc5, 0x7cd7, 0x7ce8, 0x826e, 0x66a8, 0x7fbf, 0x7fce, 0x7fd5, 0x7fe5, 0x7fe1, 0x7fe6, 0x7fe9, 0x7fee, 0x7ff3, 0x7cf8, 0x7d77, 0x7da6, 0x7dae, 0x7e47, 0x7e9b, 0x9eb8, 0x9eb4, 0x8d73, 0x8d84, 0x8d94, 0x8d91, 0x8db1, 0x8d67, 0x8d6d, 0x8c47, 0x8c49, 0x914a, 0x9150, 0x914e, 0x914f, 0x9164, /* 0xf5 */ 0x9b7c, 0x9b7d, 0x9b7e, 0x9b7f, 0x9b80, 0x9b81, 0x9b82, 0x9b83, 0x9b84, 0x9b85, 0x9b86, 0x9b87, 0x9b88, 0x9b89, 0x9b8a, 0x9b8b, 0x9b8c, 0x9b8d, 0x9b8e, 0x9b8f, 0x9b90, 0x9b91, 0x9b92, 0x9b93, 0x9b94, 0x9b95, 0x9b96, 0x9b97, 0x9b98, 0x9b99, 0x9b9a, 0x9b9b, 0x9b9c, 0x9b9d, 0x9b9e, 0x9b9f, 0x9ba0, 0x9ba1, 0x9ba2, 0x9ba3, 0x9ba4, 0x9ba5, 0x9ba6, 0x9ba7, 0x9ba8, 0x9ba9, 0x9baa, 0x9bab, 0x9bac, 0x9bad, 0x9bae, 0x9baf, 0x9bb0, 0x9bb1, 0x9bb2, 0x9bb3, 0x9bb4, 0x9bb5, 0x9bb6, 0x9bb7, 0x9bb8, 0x9bb9, 0x9bba, 0x9bbb, 0x9bbc, 0x9bbd, 0x9bbe, 0x9bbf, 0x9bc0, 0x9bc1, 0x9bc2, 0x9bc3, 0x9bc4, 0x9bc5, 0x9bc6, 0x9bc7, 0x9bc8, 0x9bc9, 0x9bca, 0x9bcb, 0x9bcc, 0x9bcd, 0x9bce, 0x9bcf, 0x9bd0, 0x9bd1, 0x9bd2, 0x9bd3, 0x9bd4, 0x9bd5, 0x9bd6, 0x9bd7, 0x9bd8, 0x9bd9, 0x9bda, 0x9bdb, 0x9162, 0x9161, 0x9170, 0x9169, 0x916f, 0x917d, 0x917e, 0x9172, 0x9174, 0x9179, 0x918c, 0x9185, 0x9190, 0x918d, 0x9191, 0x91a2, 0x91a3, 0x91aa, 0x91ad, 0x91ae, 0x91af, 0x91b5, 0x91b4, 0x91ba, 0x8c55, 0x9e7e, 0x8db8, 0x8deb, 0x8e05, 0x8e59, 0x8e69, 0x8db5, 0x8dbf, 0x8dbc, 0x8dba, 0x8dc4, 0x8dd6, 0x8dd7, 0x8dda, 0x8dde, 0x8dce, 0x8dcf, 0x8ddb, 0x8dc6, 0x8dec, 0x8df7, 0x8df8, 0x8de3, 0x8df9, 0x8dfb, 0x8de4, 0x8e09, 0x8dfd, 0x8e14, 0x8e1d, 0x8e1f, 0x8e2c, 0x8e2e, 0x8e23, 0x8e2f, 0x8e3a, 0x8e40, 0x8e39, 0x8e35, 0x8e3d, 0x8e31, 0x8e49, 0x8e41, 0x8e42, 0x8e51, 0x8e52, 0x8e4a, 0x8e70, 0x8e76, 0x8e7c, 0x8e6f, 0x8e74, 0x8e85, 0x8e8f, 0x8e94, 0x8e90, 0x8e9c, 0x8e9e, 0x8c78, 0x8c82, 0x8c8a, 0x8c85, 0x8c98, 0x8c94, 0x659b, 0x89d6, 0x89de, 0x89da, 0x89dc, /* 0xf6 */ 0x9bdc, 0x9bdd, 0x9bde, 0x9bdf, 0x9be0, 0x9be1, 0x9be2, 0x9be3, 0x9be4, 0x9be5, 0x9be6, 0x9be7, 0x9be8, 0x9be9, 0x9bea, 0x9beb, 0x9bec, 0x9bed, 0x9bee, 0x9bef, 0x9bf0, 0x9bf1, 0x9bf2, 0x9bf3, 0x9bf4, 0x9bf5, 0x9bf6, 0x9bf7, 0x9bf8, 0x9bf9, 0x9bfa, 0x9bfb, 0x9bfc, 0x9bfd, 0x9bfe, 0x9bff, 0x9c00, 0x9c01, 0x9c02, 0x9c03, 0x9c04, 0x9c05, 0x9c06, 0x9c07, 0x9c08, 0x9c09, 0x9c0a, 0x9c0b, 0x9c0c, 0x9c0d, 0x9c0e, 0x9c0f, 0x9c10, 0x9c11, 0x9c12, 0x9c13, 0x9c14, 0x9c15, 0x9c16, 0x9c17, 0x9c18, 0x9c19, 0x9c1a, 0x9c1b, 0x9c1c, 0x9c1d, 0x9c1e, 0x9c1f, 0x9c20, 0x9c21, 0x9c22, 0x9c23, 0x9c24, 0x9c25, 0x9c26, 0x9c27, 0x9c28, 0x9c29, 0x9c2a, 0x9c2b, 0x9c2c, 0x9c2d, 0x9c2e, 0x9c2f, 0x9c30, 0x9c31, 0x9c32, 0x9c33, 0x9c34, 0x9c35, 0x9c36, 0x9c37, 0x9c38, 0x9c39, 0x9c3a, 0x9c3b, 0x89e5, 0x89eb, 0x89ef, 0x8a3e, 0x8b26, 0x9753, 0x96e9, 0x96f3, 0x96ef, 0x9706, 0x9701, 0x9708, 0x970f, 0x970e, 0x972a, 0x972d, 0x9730, 0x973e, 0x9f80, 0x9f83, 0x9f85, 0x9f86, 0x9f87, 0x9f88, 0x9f89, 0x9f8a, 0x9f8c, 0x9efe, 0x9f0b, 0x9f0d, 0x96b9, 0x96bc, 0x96bd, 0x96ce, 0x96d2, 0x77bf, 0x96e0, 0x928e, 0x92ae, 0x92c8, 0x933e, 0x936a, 0x93ca, 0x938f, 0x943e, 0x946b, 0x9c7f, 0x9c82, 0x9c85, 0x9c86, 0x9c87, 0x9c88, 0x7a23, 0x9c8b, 0x9c8e, 0x9c90, 0x9c91, 0x9c92, 0x9c94, 0x9c95, 0x9c9a, 0x9c9b, 0x9c9e, 0x9c9f, 0x9ca0, 0x9ca1, 0x9ca2, 0x9ca3, 0x9ca5, 0x9ca6, 0x9ca7, 0x9ca8, 0x9ca9, 0x9cab, 0x9cad, 0x9cae, 0x9cb0, 0x9cb1, 0x9cb2, 0x9cb3, 0x9cb4, 0x9cb5, 0x9cb6, 0x9cb7, 0x9cba, 0x9cbb, 0x9cbc, 0x9cbd, 0x9cc4, 0x9cc5, 0x9cc6, 0x9cc7, 0x9cca, 0x9ccb, /* 0xf7 */ 0x9c3c, 0x9c3d, 0x9c3e, 0x9c3f, 0x9c40, 0x9c41, 0x9c42, 0x9c43, 0x9c44, 0x9c45, 0x9c46, 0x9c47, 0x9c48, 0x9c49, 0x9c4a, 0x9c4b, 0x9c4c, 0x9c4d, 0x9c4e, 0x9c4f, 0x9c50, 0x9c51, 0x9c52, 0x9c53, 0x9c54, 0x9c55, 0x9c56, 0x9c57, 0x9c58, 0x9c59, 0x9c5a, 0x9c5b, 0x9c5c, 0x9c5d, 0x9c5e, 0x9c5f, 0x9c60, 0x9c61, 0x9c62, 0x9c63, 0x9c64, 0x9c65, 0x9c66, 0x9c67, 0x9c68, 0x9c69, 0x9c6a, 0x9c6b, 0x9c6c, 0x9c6d, 0x9c6e, 0x9c6f, 0x9c70, 0x9c71, 0x9c72, 0x9c73, 0x9c74, 0x9c75, 0x9c76, 0x9c77, 0x9c78, 0x9c79, 0x9c7a, 0x9c7b, 0x9c7d, 0x9c7e, 0x9c80, 0x9c83, 0x9c84, 0x9c89, 0x9c8a, 0x9c8c, 0x9c8f, 0x9c93, 0x9c96, 0x9c97, 0x9c98, 0x9c99, 0x9c9d, 0x9caa, 0x9cac, 0x9caf, 0x9cb9, 0x9cbe, 0x9cbf, 0x9cc0, 0x9cc1, 0x9cc2, 0x9cc8, 0x9cc9, 0x9cd1, 0x9cd2, 0x9cda, 0x9cdb, 0x9ce0, 0x9ce1, 0x9ccc, 0x9ccd, 0x9cce, 0x9ccf, 0x9cd0, 0x9cd3, 0x9cd4, 0x9cd5, 0x9cd7, 0x9cd8, 0x9cd9, 0x9cdc, 0x9cdd, 0x9cdf, 0x9ce2, 0x977c, 0x9785, 0x9791, 0x9792, 0x9794, 0x97af, 0x97ab, 0x97a3, 0x97b2, 0x97b4, 0x9ab1, 0x9ab0, 0x9ab7, 0x9e58, 0x9ab6, 0x9aba, 0x9abc, 0x9ac1, 0x9ac0, 0x9ac5, 0x9ac2, 0x9acb, 0x9acc, 0x9ad1, 0x9b45, 0x9b43, 0x9b47, 0x9b49, 0x9b48, 0x9b4d, 0x9b51, 0x98e8, 0x990d, 0x992e, 0x9955, 0x9954, 0x9adf, 0x9ae1, 0x9ae6, 0x9aef, 0x9aeb, 0x9afb, 0x9aed, 0x9af9, 0x9b08, 0x9b0f, 0x9b13, 0x9b1f, 0x9b23, 0x9ebd, 0x9ebe, 0x7e3b, 0x9e82, 0x9e87, 0x9e88, 0x9e8b, 0x9e92, 0x93d6, 0x9e9d, 0x9e9f, 0x9edb, 0x9edc, 0x9edd, 0x9ee0, 0x9edf, 0x9ee2, 0x9ee9, 0x9ee7, 0x9ee5, 0x9eea, 0x9eef, 0x9f22, 0x9f2c, 0x9f2f, 0x9f39, 0x9f37, 0x9f3d, 0x9f3e, 0x9f44, /* 0xf8 */ 0x9ce3, 0x9ce4, 0x9ce5, 0x9ce6, 0x9ce7, 0x9ce8, 0x9ce9, 0x9cea, 0x9ceb, 0x9cec, 0x9ced, 0x9cee, 0x9cef, 0x9cf0, 0x9cf1, 0x9cf2, 0x9cf3, 0x9cf4, 0x9cf5, 0x9cf6, 0x9cf7, 0x9cf8, 0x9cf9, 0x9cfa, 0x9cfb, 0x9cfc, 0x9cfd, 0x9cfe, 0x9cff, 0x9d00, 0x9d01, 0x9d02, 0x9d03, 0x9d04, 0x9d05, 0x9d06, 0x9d07, 0x9d08, 0x9d09, 0x9d0a, 0x9d0b, 0x9d0c, 0x9d0d, 0x9d0e, 0x9d0f, 0x9d10, 0x9d11, 0x9d12, 0x9d13, 0x9d14, 0x9d15, 0x9d16, 0x9d17, 0x9d18, 0x9d19, 0x9d1a, 0x9d1b, 0x9d1c, 0x9d1d, 0x9d1e, 0x9d1f, 0x9d20, 0x9d21, 0x9d22, 0x9d23, 0x9d24, 0x9d25, 0x9d26, 0x9d27, 0x9d28, 0x9d29, 0x9d2a, 0x9d2b, 0x9d2c, 0x9d2d, 0x9d2e, 0x9d2f, 0x9d30, 0x9d31, 0x9d32, 0x9d33, 0x9d34, 0x9d35, 0x9d36, 0x9d37, 0x9d38, 0x9d39, 0x9d3a, 0x9d3b, 0x9d3c, 0x9d3d, 0x9d3e, 0x9d3f, 0x9d40, 0x9d41, 0x9d42, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xf9 */ 0x9d43, 0x9d44, 0x9d45, 0x9d46, 0x9d47, 0x9d48, 0x9d49, 0x9d4a, 0x9d4b, 0x9d4c, 0x9d4d, 0x9d4e, 0x9d4f, 0x9d50, 0x9d51, 0x9d52, 0x9d53, 0x9d54, 0x9d55, 0x9d56, 0x9d57, 0x9d58, 0x9d59, 0x9d5a, 0x9d5b, 0x9d5c, 0x9d5d, 0x9d5e, 0x9d5f, 0x9d60, 0x9d61, 0x9d62, 0x9d63, 0x9d64, 0x9d65, 0x9d66, 0x9d67, 0x9d68, 0x9d69, 0x9d6a, 0x9d6b, 0x9d6c, 0x9d6d, 0x9d6e, 0x9d6f, 0x9d70, 0x9d71, 0x9d72, 0x9d73, 0x9d74, 0x9d75, 0x9d76, 0x9d77, 0x9d78, 0x9d79, 0x9d7a, 0x9d7b, 0x9d7c, 0x9d7d, 0x9d7e, 0x9d7f, 0x9d80, 0x9d81, 0x9d82, 0x9d83, 0x9d84, 0x9d85, 0x9d86, 0x9d87, 0x9d88, 0x9d89, 0x9d8a, 0x9d8b, 0x9d8c, 0x9d8d, 0x9d8e, 0x9d8f, 0x9d90, 0x9d91, 0x9d92, 0x9d93, 0x9d94, 0x9d95, 0x9d96, 0x9d97, 0x9d98, 0x9d99, 0x9d9a, 0x9d9b, 0x9d9c, 0x9d9d, 0x9d9e, 0x9d9f, 0x9da0, 0x9da1, 0x9da2, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xfa */ 0x9da3, 0x9da4, 0x9da5, 0x9da6, 0x9da7, 0x9da8, 0x9da9, 0x9daa, 0x9dab, 0x9dac, 0x9dad, 0x9dae, 0x9daf, 0x9db0, 0x9db1, 0x9db2, 0x9db3, 0x9db4, 0x9db5, 0x9db6, 0x9db7, 0x9db8, 0x9db9, 0x9dba, 0x9dbb, 0x9dbc, 0x9dbd, 0x9dbe, 0x9dbf, 0x9dc0, 0x9dc1, 0x9dc2, 0x9dc3, 0x9dc4, 0x9dc5, 0x9dc6, 0x9dc7, 0x9dc8, 0x9dc9, 0x9dca, 0x9dcb, 0x9dcc, 0x9dcd, 0x9dce, 0x9dcf, 0x9dd0, 0x9dd1, 0x9dd2, 0x9dd3, 0x9dd4, 0x9dd5, 0x9dd6, 0x9dd7, 0x9dd8, 0x9dd9, 0x9dda, 0x9ddb, 0x9ddc, 0x9ddd, 0x9dde, 0x9ddf, 0x9de0, 0x9de1, 0x9de2, 0x9de3, 0x9de4, 0x9de5, 0x9de6, 0x9de7, 0x9de8, 0x9de9, 0x9dea, 0x9deb, 0x9dec, 0x9ded, 0x9dee, 0x9def, 0x9df0, 0x9df1, 0x9df2, 0x9df3, 0x9df4, 0x9df5, 0x9df6, 0x9df7, 0x9df8, 0x9df9, 0x9dfa, 0x9dfb, 0x9dfc, 0x9dfd, 0x9dfe, 0x9dff, 0x9e00, 0x9e01, 0x9e02, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xfb */ 0x9e03, 0x9e04, 0x9e05, 0x9e06, 0x9e07, 0x9e08, 0x9e09, 0x9e0a, 0x9e0b, 0x9e0c, 0x9e0d, 0x9e0e, 0x9e0f, 0x9e10, 0x9e11, 0x9e12, 0x9e13, 0x9e14, 0x9e15, 0x9e16, 0x9e17, 0x9e18, 0x9e19, 0x9e1a, 0x9e1b, 0x9e1c, 0x9e1d, 0x9e1e, 0x9e24, 0x9e27, 0x9e2e, 0x9e30, 0x9e34, 0x9e3b, 0x9e3c, 0x9e40, 0x9e4d, 0x9e50, 0x9e52, 0x9e53, 0x9e54, 0x9e56, 0x9e59, 0x9e5d, 0x9e5f, 0x9e60, 0x9e61, 0x9e62, 0x9e65, 0x9e6e, 0x9e6f, 0x9e72, 0x9e74, 0x9e75, 0x9e76, 0x9e77, 0x9e78, 0x9e79, 0x9e7a, 0x9e7b, 0x9e7c, 0x9e7d, 0x9e80, 0x9e81, 0x9e83, 0x9e84, 0x9e85, 0x9e86, 0x9e89, 0x9e8a, 0x9e8c, 0x9e8d, 0x9e8e, 0x9e8f, 0x9e90, 0x9e91, 0x9e94, 0x9e95, 0x9e96, 0x9e97, 0x9e98, 0x9e99, 0x9e9a, 0x9e9b, 0x9e9c, 0x9e9e, 0x9ea0, 0x9ea1, 0x9ea2, 0x9ea3, 0x9ea4, 0x9ea5, 0x9ea7, 0x9ea8, 0x9ea9, 0x9eaa, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xfc */ 0x9eab, 0x9eac, 0x9ead, 0x9eae, 0x9eaf, 0x9eb0, 0x9eb1, 0x9eb2, 0x9eb3, 0x9eb5, 0x9eb6, 0x9eb7, 0x9eb9, 0x9eba, 0x9ebc, 0x9ebf, 0x9ec0, 0x9ec1, 0x9ec2, 0x9ec3, 0x9ec5, 0x9ec6, 0x9ec7, 0x9ec8, 0x9eca, 0x9ecb, 0x9ecc, 0x9ed0, 0x9ed2, 0x9ed3, 0x9ed5, 0x9ed6, 0x9ed7, 0x9ed9, 0x9eda, 0x9ede, 0x9ee1, 0x9ee3, 0x9ee4, 0x9ee6, 0x9ee8, 0x9eeb, 0x9eec, 0x9eed, 0x9eee, 0x9ef0, 0x9ef1, 0x9ef2, 0x9ef3, 0x9ef4, 0x9ef5, 0x9ef6, 0x9ef7, 0x9ef8, 0x9efa, 0x9efd, 0x9eff, 0x9f00, 0x9f01, 0x9f02, 0x9f03, 0x9f04, 0x9f05, 0x9f06, 0x9f07, 0x9f08, 0x9f09, 0x9f0a, 0x9f0c, 0x9f0f, 0x9f11, 0x9f12, 0x9f14, 0x9f15, 0x9f16, 0x9f18, 0x9f1a, 0x9f1b, 0x9f1c, 0x9f1d, 0x9f1e, 0x9f1f, 0x9f21, 0x9f23, 0x9f24, 0x9f25, 0x9f26, 0x9f27, 0x9f28, 0x9f29, 0x9f2a, 0x9f2b, 0x9f2d, 0x9f2e, 0x9f30, 0x9f31, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xfd */ 0x9f32, 0x9f33, 0x9f34, 0x9f35, 0x9f36, 0x9f38, 0x9f3a, 0x9f3c, 0x9f3f, 0x9f40, 0x9f41, 0x9f42, 0x9f43, 0x9f45, 0x9f46, 0x9f47, 0x9f48, 0x9f49, 0x9f4a, 0x9f4b, 0x9f4c, 0x9f4d, 0x9f4e, 0x9f4f, 0x9f52, 0x9f53, 0x9f54, 0x9f55, 0x9f56, 0x9f57, 0x9f58, 0x9f59, 0x9f5a, 0x9f5b, 0x9f5c, 0x9f5d, 0x9f5e, 0x9f5f, 0x9f60, 0x9f61, 0x9f62, 0x9f63, 0x9f64, 0x9f65, 0x9f66, 0x9f67, 0x9f68, 0x9f69, 0x9f6a, 0x9f6b, 0x9f6c, 0x9f6d, 0x9f6e, 0x9f6f, 0x9f70, 0x9f71, 0x9f72, 0x9f73, 0x9f74, 0x9f75, 0x9f76, 0x9f77, 0x9f78, 0x9f79, 0x9f7a, 0x9f7b, 0x9f7c, 0x9f7d, 0x9f7e, 0x9f81, 0x9f82, 0x9f8d, 0x9f8e, 0x9f8f, 0x9f90, 0x9f91, 0x9f92, 0x9f93, 0x9f94, 0x9f95, 0x9f96, 0x9f97, 0x9f98, 0x9f9c, 0x9f9d, 0x9f9e, 0x9fa1, 0x9fa2, 0x9fa3, 0x9fa4, 0x9fa5, 0xf92c, 0xf979, 0xf995, 0xf9e7, 0xf9f1, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xfe */ 0xfa0c, 0xfa0d, 0xfa0e, 0xfa0f, 0xfa11, 0xfa13, 0xfa14, 0xfa18, 0xfa1f, 0xfa20, 0xfa21, 0xfa23, 0xfa24, 0xfa27, 0xfa28, 0xfa29, }; static int cp936ext_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c1 = s[0]; if ((c1 >= 0x81 && c1 <= 0xfe)) { if (n >= 2) { unsigned char c2 = s[1]; if ((c2 >= 0x40 && c2 < 0x7f) || (c2 >= 0x80 && c2 < 0xff)) { unsigned int i = 190 * (c1 - 0x81) + (c2 - (c2 >= 0x80 ? 0x41 : 0x40)); unsigned short wc = 0xfffd; { if (i < 23766) wc = cp936ext_2uni_page81[i]; } if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 2; } } return RET_ILSEQ; } return RET_TOOFEW(0); } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned short cp936ext_page0014[208] = { 0x0000, 0x0000, 0x0000, 0x0000, 0xa1e8, 0x0000, 0x0000, 0xa1ec, /*0xa0-0xa7*/ 0xa1a7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xa8-0xaf*/ 0xa1e3, 0xa1c0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1a4, /*0xb0-0xb7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xb8-0xbf*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xc0-0xc7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xc8-0xcf*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1c1, /*0xd0-0xd7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xd8-0xdf*/ 0xa8a4, 0xa8a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xe0-0xe7*/ 0xa8a8, 0xa8a6, 0xa8ba, 0x0000, 0xa8ac, 0xa8aa, 0x0000, 0x0000, /*0xe8-0xef*/ 0x0000, 0x0000, 0xa8b0, 0xa8ae, 0x0000, 0x0000, 0x0000, 0xa1c2, /*0xf0-0xf7*/ 0x0000, 0xa8b4, 0xa8b2, 0x0000, 0xa8b9, 0x0000, 0x0000, 0x0000, /*0xf8-0xff*/ /* 0x0100 */ 0x0000, 0xa8a1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x00-0x07*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x08-0x0f*/ 0x0000, 0x0000, 0x0000, 0xa8a5, 0x0000, 0x0000, 0x0000, 0x0000, /*0x10-0x17*/ 0x0000, 0x0000, 0x0000, 0xa8a7, 0x0000, 0x0000, 0x0000, 0x0000, /*0x18-0x1f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x20-0x27*/ 0x0000, 0x0000, 0x0000, 0xa8a9, 0x0000, 0x0000, 0x0000, 0x0000, /*0x28-0x2f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x30-0x37*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x38-0x3f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0xa8bd, 0x0000, 0x0000, 0x0000, /*0x40-0x47*/ 0xa8be, 0x0000, 0x0000, 0x0000, 0x0000, 0xa8ad, 0x0000, 0x0000, /*0x48-0x4f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x50-0x57*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x58-0x5f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x60-0x67*/ 0x0000, 0x0000, 0x0000, 0xa8b1, 0x0000, 0x0000, 0x0000, 0x0000, /*0x68-0x6f*/ }; static const unsigned short cp936ext_page0039[24] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa8a3, 0x0000, /*0xc8-0xcf*/ 0xa8ab, 0x0000, 0xa8af, 0x0000, 0xa8b3, 0x0000, 0xa8b5, 0x0000, /*0xd0-0xd7*/ 0xa8b6, 0x0000, 0xa8b7, 0x0000, 0xa8b8, 0x0000, 0x0000, 0x0000, /*0xd8-0xdf*/ }; static const unsigned short cp936ext_page004a[24] = { 0x0000, 0xa8bb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x50-0x57*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x58-0x5f*/ 0x0000, 0xa8c0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x60-0x67*/ }; static const unsigned short cp936ext_page0058[32] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1a6, /*0xc0-0xc7*/ 0x0000, 0xa1a5, 0xa840, 0xa841, 0x0000, 0x0000, 0x0000, 0x0000, /*0xc8-0xcf*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xd0-0xd7*/ 0x0000, 0xa842, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xd8-0xdf*/ }; static const unsigned short cp936ext_page0072[64] = { 0x0000, 0xa6a1, 0xa6a2, 0xa6a3, 0xa6a4, 0xa6a5, 0xa6a6, 0xa6a7, /*0x90-0x97*/ 0xa6a8, 0xa6a9, 0xa6aa, 0xa6ab, 0xa6ac, 0xa6ad, 0xa6ae, 0xa6af, /*0x98-0x9f*/ 0xa6b0, 0xa6b1, 0x0000, 0xa6b2, 0xa6b3, 0xa6b4, 0xa6b5, 0xa6b6, /*0xa0-0xa7*/ 0xa6b7, 0xa6b8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xa8-0xaf*/ 0x0000, 0xa6c1, 0xa6c2, 0xa6c3, 0xa6c4, 0xa6c5, 0xa6c6, 0xa6c7, /*0xb0-0xb7*/ 0xa6c8, 0xa6c9, 0xa6ca, 0xa6cb, 0xa6cc, 0xa6cd, 0xa6ce, 0xa6cf, /*0xb8-0xbf*/ 0xa6d0, 0xa6d1, 0x0000, 0xa6d2, 0xa6d3, 0xa6d4, 0xa6d5, 0xa6d6, /*0xc0-0xc7*/ 0xa6d7, 0xa6d8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xc8-0xcf*/ }; static const unsigned short cp936ext_page0080[88] = { 0x0000, 0xa7a7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x00-0x07*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x08-0x0f*/ 0xa7a1, 0xa7a2, 0xa7a3, 0xa7a4, 0xa7a5, 0xa7a6, 0xa7a8, 0xa7a9, /*0x10-0x17*/ 0xa7aa, 0xa7ab, 0xa7ac, 0xa7ad, 0xa7ae, 0xa7af, 0xa7b0, 0xa7b1, /*0x18-0x1f*/ 0xa7b2, 0xa7b3, 0xa7b4, 0xa7b5, 0xa7b6, 0xa7b7, 0xa7b8, 0xa7b9, /*0x20-0x27*/ 0xa7ba, 0xa7bb, 0xa7bc, 0xa7bd, 0xa7be, 0xa7bf, 0xa7c0, 0xa7c1, /*0x28-0x2f*/ 0xa7d1, 0xa7d2, 0xa7d3, 0xa7d4, 0xa7d5, 0xa7d6, 0xa7d8, 0xa7d9, /*0x30-0x37*/ 0xa7da, 0xa7db, 0xa7dc, 0xa7dd, 0xa7de, 0xa7df, 0xa7e0, 0xa7e1, /*0x38-0x3f*/ 0xa7e2, 0xa7e3, 0xa7e4, 0xa7e5, 0xa7e6, 0xa7e7, 0xa7e8, 0xa7e9, /*0x40-0x47*/ 0xa7ea, 0xa7eb, 0xa7ec, 0xa7ed, 0xa7ee, 0xa7ef, 0xa7f0, 0xa7f1, /*0x48-0x4f*/ 0x0000, 0xa7d7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x50-0x57*/ }; static const unsigned short cp936ext_page0402[48] = { 0xa95c, 0x0000, 0x0000, 0xa843, 0xa1aa, 0xa844, 0xa1ac, 0x0000, /*0x10-0x17*/ 0xa1ae, 0xa1af, 0x0000, 0x0000, 0xa1b0, 0xa1b1, 0x0000, 0x0000, /*0x18-0x1f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa845, 0xa1ad, 0x0000, /*0x20-0x27*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x28-0x2f*/ 0xa1eb, 0x0000, 0xa1e4, 0xa1e5, 0x0000, 0xa846, 0x0000, 0x0000, /*0x30-0x37*/ 0x0000, 0x0000, 0x0000, 0xa1f9, 0x0000, 0x0000, 0x0000, 0x0000, /*0x38-0x3f*/ }; static const unsigned short cp936ext_page0420[160] = { 0x0000, 0x0000, 0x0000, 0xa1e6, 0x0000, 0xa847, 0x0000, 0x0000, /*0x00-0x07*/ 0x0000, 0xa848, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x08-0x0f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1ed, 0x0000, /*0x10-0x17*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x18-0x1f*/ 0x0000, 0xa959, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x20-0x27*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x28-0x2f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x30-0x37*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x38-0x3f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x40-0x47*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x48-0x4f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x50-0x57*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x58-0x5f*/ 0xa2f1, 0xa2f2, 0xa2f3, 0xa2f4, 0xa2f5, 0xa2f6, 0xa2f7, 0xa2f8, /*0x60-0x67*/ 0xa2f9, 0xa2fa, 0xa2fb, 0xa2fc, 0x0000, 0x0000, 0x0000, 0x0000, /*0x68-0x6f*/ 0xa2a1, 0xa2a2, 0xa2a3, 0xa2a4, 0xa2a5, 0xa2a6, 0xa2a7, 0xa2a8, /*0x70-0x77*/ 0xa2a9, 0xa2aa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x78-0x7f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x80-0x87*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x88-0x8f*/ 0xa1fb, 0xa1fc, 0xa1fa, 0xa1fd, 0x0000, 0x0000, 0xa849, 0xa84a, /*0x90-0x97*/ 0xa84b, 0xa84c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x98-0x9f*/ }; static const unsigned short cp936ext_page0441[184] = { 0xa1ca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1c7, /*0x08-0x0f*/ 0x0000, 0xa1c6, 0x0000, 0x0000, 0x0000, 0xa84d, 0x0000, 0x0000, /*0x10-0x17*/ 0x0000, 0x0000, 0xa1cc, 0x0000, 0x0000, 0xa1d8, 0xa1de, 0xa84e, /*0x18-0x1f*/ 0xa1cf, 0x0000, 0x0000, 0xa84f, 0x0000, 0xa1ce, 0x0000, 0xa1c4, /*0x20-0x27*/ 0xa1c5, 0xa1c9, 0xa1c8, 0xa1d2, 0x0000, 0x0000, 0xa1d3, 0x0000, /*0x28-0x2f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0xa1e0, 0xa1df, 0xa1c3, 0xa1cb, /*0x30-0x37*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1d7, 0x0000, 0x0000, /*0x38-0x3f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x40-0x47*/ 0xa1d6, 0x0000, 0x0000, 0x0000, 0xa1d5, 0x0000, 0x0000, 0x0000, /*0x48-0x4f*/ 0x0000, 0x0000, 0xa850, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x50-0x57*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x58-0x5f*/ 0xa1d9, 0xa1d4, 0x0000, 0x0000, 0xa1dc, 0xa1dd, 0xa851, 0xa852, /*0x60-0x67*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1da, 0xa1db, /*0x68-0x6f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x70-0x77*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x78-0x7f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x80-0x87*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x88-0x8f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa892, 0x0000, 0x0000, /*0x90-0x97*/ 0x0000, 0xa1d1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x98-0x9f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1cd, 0x0000, 0x0000, /*0xa0-0xa7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xa8-0xaf*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xb0-0xb7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa853, /*0xb8-0xbf*/ }; static const unsigned short cp936ext_page048c[64] = { 0xa2d9, 0xa2da, 0xa2db, 0xa2dc, 0xa2dd, 0xa2de, 0xa2df, 0xa2e0, /*0x60-0x67*/ 0xa2e1, 0xa2e2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x68-0x6f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0xa2c5, 0xa2c6, 0xa2c7, 0xa2c8, /*0x70-0x77*/ 0xa2c9, 0xa2ca, 0xa2cb, 0xa2cc, 0xa2cd, 0xa2ce, 0xa2cf, 0xa2d0, /*0x78-0x7f*/ 0xa2d1, 0xa2d2, 0xa2d3, 0xa2d4, 0xa2d5, 0xa2d6, 0xa2d7, 0xa2d8, /*0x80-0x87*/ 0xa2b1, 0xa2b2, 0xa2b3, 0xa2b4, 0xa2b5, 0xa2b6, 0xa2b7, 0xa2b8, /*0x88-0x8f*/ 0xa2b9, 0xa2ba, 0xa2bb, 0xa2bc, 0xa2bd, 0xa2be, 0xa2bf, 0xa2c0, /*0x90-0x97*/ 0xa2c1, 0xa2c2, 0xa2c3, 0xa2c4, 0x0000, 0x0000, 0x0000, 0x0000, /*0x98-0x9f*/ }; static const unsigned short cp936ext_page04a0[232] = { 0xa9a4, 0xa9a5, 0xa9a6, 0xa9a7, 0xa9a8, 0xa9a9, 0xa9aa, 0xa9ab, /*0x00-0x07*/ 0xa9ac, 0xa9ad, 0xa9ae, 0xa9af, 0xa9b0, 0xa9b1, 0xa9b2, 0xa9b3, /*0x08-0x0f*/ 0xa9b4, 0xa9b5, 0xa9b6, 0xa9b7, 0xa9b8, 0xa9b9, 0xa9ba, 0xa9bb, /*0x10-0x17*/ 0xa9bc, 0xa9bd, 0xa9be, 0xa9bf, 0xa9c0, 0xa9c1, 0xa9c2, 0xa9c3, /*0x18-0x1f*/ 0xa9c4, 0xa9c5, 0xa9c6, 0xa9c7, 0xa9c8, 0xa9c9, 0xa9ca, 0xa9cb, /*0x20-0x27*/ 0xa9cc, 0xa9cd, 0xa9ce, 0xa9cf, 0xa9d0, 0xa9d1, 0xa9d2, 0xa9d3, /*0x28-0x2f*/ 0xa9d4, 0xa9d5, 0xa9d6, 0xa9d7, 0xa9d8, 0xa9d9, 0xa9da, 0xa9db, /*0x30-0x37*/ 0xa9dc, 0xa9dd, 0xa9de, 0xa9df, 0xa9e0, 0xa9e1, 0xa9e2, 0xa9e3, /*0x38-0x3f*/ 0xa9e4, 0xa9e5, 0xa9e6, 0xa9e7, 0xa9e8, 0xa9e9, 0xa9ea, 0xa9eb, /*0x40-0x47*/ 0xa9ec, 0xa9ed, 0xa9ee, 0xa9ef, 0x0000, 0x0000, 0x0000, 0x0000, /*0x48-0x4f*/ 0xa854, 0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, /*0x50-0x57*/ 0xa85c, 0xa85d, 0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, /*0x58-0x5f*/ 0xa864, 0xa865, 0xa866, 0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, /*0x60-0x67*/ 0xa86c, 0xa86d, 0xa86e, 0xa86f, 0xa870, 0xa871, 0xa872, 0xa873, /*0x68-0x6f*/ 0xa874, 0xa875, 0xa876, 0xa877, 0x0000, 0x0000, 0x0000, 0x0000, /*0x70-0x77*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x78-0x7f*/ 0x0000, 0xa878, 0xa879, 0xa87a, 0xa87b, 0xa87c, 0xa87d, 0xa87e, /*0x80-0x87*/ 0xa880, 0xa881, 0xa882, 0xa883, 0xa884, 0xa885, 0xa886, 0xa887, /*0x88-0x8f*/ 0x0000, 0x0000, 0x0000, 0xa888, 0xa889, 0xa88a, 0x0000, 0x0000, /*0x90-0x97*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x98-0x9f*/ 0xa1f6, 0xa1f5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xa0-0xa7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xa8-0xaf*/ 0x0000, 0x0000, 0xa1f8, 0xa1f7, 0x0000, 0x0000, 0x0000, 0x0000, /*0xb0-0xb7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0xa88b, 0xa88c, 0x0000, 0x0000, /*0xb8-0xbf*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1f4, 0xa1f3, /*0xc0-0xc7*/ 0x0000, 0x0000, 0x0000, 0xa1f0, 0x0000, 0x0000, 0xa1f2, 0xa1f1, /*0xc8-0xcf*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xd0-0xd7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xd8-0xdf*/ 0x0000, 0x0000, 0xa88d, 0xa88e, 0xa88f, 0xa890, 0x0000, 0x0000, /*0xe0-0xe7*/ }; static const unsigned short cp936ext_page04c0[72] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa1ef, 0xa1ee, 0x0000, /*0x00-0x07*/ 0x0000, 0xa891, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x08-0x0f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x10-0x17*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x18-0x1f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x20-0x27*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x28-0x2f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x30-0x37*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x38-0x3f*/ 0xa1e2, 0x0000, 0xa1e1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x40-0x47*/ }; static const unsigned short cp936ext_page0600[304] = { 0xa1a1, 0xa1a2, 0xa1a3, 0xa1a8, 0x0000, 0xa1a9, 0xa965, 0xa996, /*0x00-0x07*/ 0xa1b4, 0xa1b5, 0xa1b6, 0xa1b7, 0xa1b8, 0xa1b9, 0xa1ba, 0xa1bb, /*0x08-0x0f*/ 0xa1be, 0xa1bf, 0xa893, 0xa1fe, 0xa1b2, 0xa1b3, 0xa1bc, 0xa1bd, /*0x10-0x17*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa894, 0xa895, 0x0000, /*0x18-0x1f*/ 0x0000, 0xa940, 0xa941, 0xa942, 0xa943, 0xa944, 0xa945, 0xa946, /*0x20-0x27*/ 0xa947, 0xa948, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x28-0x2f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x30-0x37*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x38-0x3f*/ 0x0000, 0xa4a1, 0xa4a2, 0xa4a3, 0xa4a4, 0xa4a5, 0xa4a6, 0xa4a7, /*0x40-0x47*/ 0xa4a8, 0xa4a9, 0xa4aa, 0xa4ab, 0xa4ac, 0xa4ad, 0xa4ae, 0xa4af, /*0x48-0x4f*/ 0xa4b0, 0xa4b1, 0xa4b2, 0xa4b3, 0xa4b4, 0xa4b5, 0xa4b6, 0xa4b7, /*0x50-0x57*/ 0xa4b8, 0xa4b9, 0xa4ba, 0xa4bb, 0xa4bc, 0xa4bd, 0xa4be, 0xa4bf, /*0x58-0x5f*/ 0xa4c0, 0xa4c1, 0xa4c2, 0xa4c3, 0xa4c4, 0xa4c5, 0xa4c6, 0xa4c7, /*0x60-0x67*/ 0xa4c8, 0xa4c9, 0xa4ca, 0xa4cb, 0xa4cc, 0xa4cd, 0xa4ce, 0xa4cf, /*0x68-0x6f*/ 0xa4d0, 0xa4d1, 0xa4d2, 0xa4d3, 0xa4d4, 0xa4d5, 0xa4d6, 0xa4d7, /*0x70-0x77*/ 0xa4d8, 0xa4d9, 0xa4da, 0xa4db, 0xa4dc, 0xa4dd, 0xa4de, 0xa4df, /*0x78-0x7f*/ 0xa4e0, 0xa4e1, 0xa4e2, 0xa4e3, 0xa4e4, 0xa4e5, 0xa4e6, 0xa4e7, /*0x80-0x87*/ 0xa4e8, 0xa4e9, 0xa4ea, 0xa4eb, 0xa4ec, 0xa4ed, 0xa4ee, 0xa4ef, /*0x88-0x8f*/ 0xa4f0, 0xa4f1, 0xa4f2, 0xa4f3, 0x0000, 0x0000, 0x0000, 0x0000, /*0x90-0x97*/ 0x0000, 0x0000, 0x0000, 0xa961, 0xa962, 0xa966, 0xa967, 0x0000, /*0x98-0x9f*/ 0x0000, 0xa5a1, 0xa5a2, 0xa5a3, 0xa5a4, 0xa5a5, 0xa5a6, 0xa5a7, /*0xa0-0xa7*/ 0xa5a8, 0xa5a9, 0xa5aa, 0xa5ab, 0xa5ac, 0xa5ad, 0xa5ae, 0xa5af, /*0xa8-0xaf*/ 0xa5b0, 0xa5b1, 0xa5b2, 0xa5b3, 0xa5b4, 0xa5b5, 0xa5b6, 0xa5b7, /*0xb0-0xb7*/ 0xa5b8, 0xa5b9, 0xa5ba, 0xa5bb, 0xa5bc, 0xa5bd, 0xa5be, 0xa5bf, /*0xb8-0xbf*/ 0xa5c0, 0xa5c1, 0xa5c2, 0xa5c3, 0xa5c4, 0xa5c5, 0xa5c6, 0xa5c7, /*0xc0-0xc7*/ 0xa5c8, 0xa5c9, 0xa5ca, 0xa5cb, 0xa5cc, 0xa5cd, 0xa5ce, 0xa5cf, /*0xc8-0xcf*/ 0xa5d0, 0xa5d1, 0xa5d2, 0xa5d3, 0xa5d4, 0xa5d5, 0xa5d6, 0xa5d7, /*0xd0-0xd7*/ 0xa5d8, 0xa5d9, 0xa5da, 0xa5db, 0xa5dc, 0xa5dd, 0xa5de, 0xa5df, /*0xd8-0xdf*/ 0xa5e0, 0xa5e1, 0xa5e2, 0xa5e3, 0xa5e4, 0xa5e5, 0xa5e6, 0xa5e7, /*0xe0-0xe7*/ 0xa5e8, 0xa5e9, 0xa5ea, 0xa5eb, 0xa5ec, 0xa5ed, 0xa5ee, 0xa5ef, /*0xe8-0xef*/ 0xa5f0, 0xa5f1, 0xa5f2, 0xa5f3, 0xa5f4, 0xa5f5, 0xa5f6, 0x0000, /*0xf0-0xf7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0xa960, 0xa963, 0xa964, 0x0000, /*0xf8-0xff*/ /* 0x3100 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa8c5, 0xa8c6, 0xa8c7, /*0x00-0x07*/ 0xa8c8, 0xa8c9, 0xa8ca, 0xa8cb, 0xa8cc, 0xa8cd, 0xa8ce, 0xa8cf, /*0x08-0x0f*/ 0xa8d0, 0xa8d1, 0xa8d2, 0xa8d3, 0xa8d4, 0xa8d5, 0xa8d6, 0xa8d7, /*0x10-0x17*/ 0xa8d8, 0xa8d9, 0xa8da, 0xa8db, 0xa8dc, 0xa8dd, 0xa8de, 0xa8df, /*0x18-0x1f*/ 0xa8e0, 0xa8e1, 0xa8e2, 0xa8e3, 0xa8e4, 0xa8e5, 0xa8e6, 0xa8e7, /*0x20-0x27*/ 0xa8e8, 0xa8e9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x28-0x2f*/ }; static const unsigned short cp936ext_page0644[24] = { 0xa2e5, 0xa2e6, 0xa2e7, 0xa2e8, 0xa2e9, 0xa2ea, 0xa2eb, 0xa2ec, /*0x20-0x27*/ 0xa2ed, 0xa2ee, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x28-0x2f*/ 0x0000, 0xa95a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x30-0x37*/ }; static const unsigned short cp936ext_page0671[80] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa94a, 0xa94b, /*0x88-0x8f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x90-0x97*/ 0x0000, 0x0000, 0x0000, 0x0000, 0xa94c, 0xa94d, 0xa94e, 0x0000, /*0x98-0x9f*/ 0x0000, 0xa94f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xa0-0xa7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xa8-0xaf*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xb0-0xb7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xb8-0xbf*/ 0x0000, 0x0000, 0x0000, 0x0000, 0xa950, 0x0000, 0x0000, 0x0000, /*0xc0-0xc7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa951, 0x0000, /*0xc8-0xcf*/ 0x0000, 0xa952, 0xa953, 0x0000, 0x0000, 0xa954, 0x0000, 0x0000, /*0xd0-0xd7*/ }; static const unsigned short cp936ext_page09c0[20904] = { 0xd2bb, 0xb6a1, 0x8140, 0xc6df, 0x8141, 0x8142, 0x8143, 0xcdf2, /*0x00-0x07*/ 0xd5c9, 0xc8fd, 0xc9cf, 0xcfc2, 0xd8a2, 0xb2bb, 0xd3eb, 0x8144, /*0x08-0x0f*/ 0xd8a4, 0xb3f3, 0x8145, 0xd7a8, 0xc7d2, 0xd8a7, 0xcac0, 0x8146, /*0x10-0x17*/ 0xc7f0, 0xb1fb, 0xd2b5, 0xb4d4, 0xb6ab, 0xcbbf, 0xd8a9, 0x8147, /*0x18-0x1f*/ 0x8148, 0x8149, 0xb6aa, 0x814a, 0xc1bd, 0xd1cf, 0x814b, 0xc9a5, /*0x20-0x27*/ 0xd8ad, 0x814c, 0xb8f6, 0xd1be, 0xe3dc, 0xd6d0, 0x814d, 0x814e, /*0x28-0x2f*/ 0xb7e1, 0x814f, 0xb4ae, 0x8150, 0xc1d9, 0x8151, 0xd8bc, 0x8152, /*0x30-0x37*/ 0xcde8, 0xb5a4, 0xceaa, 0xd6f7, 0x8153, 0xc0f6, 0xbed9, 0xd8af, /*0x38-0x3f*/ 0x8154, 0x8155, 0x8156, 0xc4cb, 0x8157, 0xbec3, 0x8158, 0xd8b1, /*0x40-0x47*/ 0xc3b4, 0xd2e5, 0x8159, 0xd6ae, 0xceda, 0xd5a7, 0xbaf5, 0xb7a6, /*0x48-0x4f*/ 0xc0d6, 0x815a, 0xc6b9, 0xc5d2, 0xc7c7, 0x815b, 0xb9d4, 0x815c, /*0x50-0x57*/ 0xb3cb, 0xd2d2, 0x815d, 0x815e, 0xd8bf, 0xbec5, 0xc6f2, 0xd2b2, /*0x58-0x5f*/ 0xcfb0, 0xcfe7, 0x815f, 0x8160, 0x8161, 0x8162, 0xcae9, 0x8163, /*0x60-0x67*/ 0x8164, 0xd8c0, 0x8165, 0x8166, 0x8167, 0x8168, 0x8169, 0x816a, /*0x68-0x6f*/ 0xc2f2, 0xc2d2, 0x816b, 0xc8e9, 0x816c, 0x816d, 0x816e, 0x816f, /*0x70-0x77*/ 0x8170, 0x8171, 0x8172, 0x8173, 0x8174, 0x8175, 0xc7ac, 0x8176, /*0x78-0x7f*/ 0x8177, 0x8178, 0x8179, 0x817a, 0x817b, 0x817c, 0xc1cb, 0x817d, /*0x80-0x87*/ 0xd3e8, 0xd5f9, 0x817e, 0xcac2, 0xb6fe, 0xd8a1, 0xd3da, 0xbff7, /*0x88-0x8f*/ 0x8180, 0xd4c6, 0xbba5, 0xd8c1, 0xcee5, 0xbeae, 0x8181, 0x8182, /*0x90-0x97*/ 0xd8a8, 0x8183, 0xd1c7, 0xd0a9, 0x8184, 0x8185, 0x8186, 0xd8bd, /*0x98-0x9f*/ 0xd9ef, 0xcdf6, 0xbfba, 0x8187, 0xbdbb, 0xbaa5, 0xd2e0, 0xb2fa, /*0xa0-0xa7*/ 0xbae0, 0xc4b6, 0x8188, 0xcfed, 0xbea9, 0xcda4, 0xc1c1, 0x8189, /*0xa8-0xaf*/ 0x818a, 0x818b, 0xc7d7, 0xd9f1, 0x818c, 0xd9f4, 0x818d, 0x818e, /*0xb0-0xb7*/ 0x818f, 0x8190, 0xc8cb, 0xd8e9, 0x8191, 0x8192, 0x8193, 0xd2da, /*0xb8-0xbf*/ 0xcab2, 0xc8ca, 0xd8ec, 0xd8ea, 0xd8c6, 0xbdf6, 0xc6cd, 0xb3f0, /*0xc0-0xc7*/ 0x8194, 0xd8eb, 0xbdf1, 0xbde9, 0x8195, 0xc8d4, 0xb4d3, 0x8196, /*0xc8-0xcf*/ 0x8197, 0xc2d8, 0x8198, 0xb2d6, 0xd7d0, 0xcacb, 0xcbfb, 0xd5cc, /*0xd0-0xd7*/ 0xb8b6, 0xcfc9, 0x8199, 0x819a, 0x819b, 0xd9da, 0xd8f0, 0xc7aa, /*0xd8-0xdf*/ 0x819c, 0xd8ee, 0x819d, 0xb4fa, 0xc1ee, 0xd2d4, 0x819e, 0x819f, /*0xe0-0xe7*/ 0xd8ed, 0x81a0, 0xd2c7, 0xd8ef, 0xc3c7, 0x81a1, 0x81a2, 0x81a3, /*0xe8-0xef*/ 0xd1f6, 0x81a4, 0xd6d9, 0xd8f2, 0x81a5, 0xd8f5, 0xbcfe, 0xbcdb, /*0xf0-0xf7*/ 0x81a6, 0x81a7, 0x81a8, 0xc8ce, 0x81a9, 0xb7dd, 0x81aa, 0xb7c2, /*0xf8-0xff*/ /* 0x4f00 */ 0x81ab, 0xc6f3, 0x81ac, 0x81ad, 0x81ae, 0x81af, 0x81b0, 0x81b1, /*0x00-0x07*/ 0x81b2, 0xd8f8, 0xd2c1, 0x81b3, 0x81b4, 0xcee9, 0xbcbf, 0xb7fc, /*0x08-0x0f*/ 0xb7a5, 0xd0dd, 0x81b5, 0x81b6, 0x81b7, 0x81b8, 0x81b9, 0xd6da, /*0x10-0x17*/ 0xd3c5, 0xbbef, 0xbbe1, 0xd8f1, 0x81ba, 0x81bb, 0xc9a1, 0xceb0, /*0x18-0x1f*/ 0xb4ab, 0x81bc, 0xd8f3, 0x81bd, 0xc9cb, 0xd8f6, 0xc2d7, 0xd8f7, /*0x20-0x27*/ 0x81be, 0x81bf, 0xceb1, 0xd8f9, 0x81c0, 0x81c1, 0x81c2, 0xb2ae, /*0x28-0x2f*/ 0xb9c0, 0x81c3, 0xd9a3, 0x81c4, 0xb0e9, 0x81c5, 0xc1e6, 0x81c6, /*0x30-0x37*/ 0xc9ec, 0x81c7, 0xcbc5, 0x81c8, 0xcbc6, 0xd9a4, 0x81c9, 0x81ca, /*0x38-0x3f*/ 0x81cb, 0x81cc, 0x81cd, 0xb5e8, 0x81ce, 0x81cf, 0xb5ab, 0x81d0, /*0x40-0x47*/ 0x81d1, 0x81d2, 0x81d3, 0x81d4, 0x81d5, 0xcebb, 0xb5cd, 0xd7a1, /*0x48-0x4f*/ 0xd7f4, 0xd3d3, 0x81d6, 0xcce5, 0x81d7, 0xbace, 0x81d8, 0xd9a2, /*0x50-0x57*/ 0xd9dc, 0xd3e0, 0xd8fd, 0xb7f0, 0xd7f7, 0xd8fe, 0xd8fa, 0xd9a1, /*0x58-0x5f*/ 0xc4e3, 0x81d9, 0x81da, 0xd3b6, 0xd8f4, 0xd9dd, 0x81db, 0xd8fb, /*0x60-0x67*/ 0x81dc, 0xc5e5, 0x81dd, 0x81de, 0xc0d0, 0x81df, 0x81e0, 0xd1f0, /*0x68-0x6f*/ 0xb0db, 0x81e1, 0x81e2, 0xbcd1, 0xd9a6, 0x81e3, 0xd9a5, 0x81e4, /*0x70-0x77*/ 0x81e5, 0x81e6, 0x81e7, 0xd9ac, 0xd9ae, 0x81e8, 0xd9ab, 0xcab9, /*0x78-0x7f*/ 0x81e9, 0x81ea, 0x81eb, 0xd9a9, 0xd6b6, 0x81ec, 0x81ed, 0x81ee, /*0x80-0x87*/ 0xb3de, 0xd9a8, 0x81ef, 0xc0fd, 0x81f0, 0xcacc, 0x81f1, 0xd9aa, /*0x88-0x8f*/ 0x81f2, 0xd9a7, 0x81f3, 0x81f4, 0xd9b0, 0x81f5, 0x81f6, 0xb6b1, /*0x90-0x97*/ 0x81f7, 0x81f8, 0x81f9, 0xb9a9, 0x81fa, 0xd2c0, 0x81fb, 0x81fc, /*0x98-0x9f*/ 0xcfc0, 0x81fd, 0x81fe, 0xc2c2, 0x8240, 0xbdc4, 0xd5ec, 0xb2e0, /*0xa0-0xa7*/ 0xc7c8, 0xbfeb, 0xd9ad, 0x8241, 0xd9af, 0x8242, 0xceea, 0xbaee, /*0xa8-0xaf*/ 0x8243, 0x8244, 0x8245, 0x8246, 0x8247, 0xc7d6, 0x8248, 0x8249, /*0xb0-0xb7*/ 0x824a, 0x824b, 0x824c, 0x824d, 0x824e, 0x824f, 0x8250, 0xb1e3, /*0xb8-0xbf*/ 0x8251, 0x8252, 0x8253, 0xb4d9, 0xb6ed, 0xd9b4, 0x8254, 0x8255, /*0xc0-0xc7*/ 0x8256, 0x8257, 0xbfa1, 0x8258, 0x8259, 0x825a, 0xd9de, 0xc7ce, /*0xc8-0xcf*/ 0xc0fe, 0xd9b8, 0x825b, 0x825c, 0x825d, 0x825e, 0x825f, 0xcbd7, /*0xd0-0xd7*/ 0xb7fd, 0x8260, 0xd9b5, 0x8261, 0xd9b7, 0xb1a3, 0xd3e1, 0xd9b9, /*0xd8-0xdf*/ 0x8262, 0xd0c5, 0x8263, 0xd9b6, 0x8264, 0x8265, 0xd9b1, 0x8266, /*0xe0-0xe7*/ 0xd9b2, 0xc1a9, 0xd9b3, 0x8267, 0x8268, 0xbcf3, 0xd0de, 0xb8a9, /*0xe8-0xef*/ 0x8269, 0xbee3, 0x826a, 0xd9bd, 0x826b, 0x826c, 0x826d, 0x826e, /*0xf0-0xf7*/ 0xd9ba, 0x826f, 0xb0b3, 0x8270, 0x8271, 0x8272, 0xd9c2, 0x8273, /*0xf8-0xff*/ /* 0x5000 */ 0x8274, 0x8275, 0x8276, 0x8277, 0x8278, 0x8279, 0x827a, 0x827b, /*0x00-0x07*/ 0x827c, 0x827d, 0x827e, 0x8280, 0xd9c4, 0xb1b6, 0x8281, 0xd9bf, /*0x08-0x0f*/ 0x8282, 0x8283, 0xb5b9, 0x8284, 0xbef3, 0x8285, 0x8286, 0x8287, /*0x10-0x17*/ 0xccc8, 0xbaf2, 0xd2d0, 0x8288, 0xd9c3, 0x8289, 0x828a, 0xbde8, /*0x18-0x1f*/ 0x828b, 0xb3ab, 0x828c, 0x828d, 0x828e, 0xd9c5, 0xbeeb, 0x828f, /*0x20-0x27*/ 0xd9c6, 0xd9bb, 0xc4df, 0x8290, 0xd9be, 0xd9c1, 0xd9c0, 0x8291, /*0x28-0x2f*/ 0x8292, 0x8293, 0x8294, 0x8295, 0x8296, 0x8297, 0x8298, 0x8299, /*0x30-0x37*/ 0x829a, 0x829b, 0xd5ae, 0x829c, 0xd6b5, 0x829d, 0xc7e3, 0x829e, /*0x38-0x3f*/ 0x829f, 0x82a0, 0x82a1, 0xd9c8, 0x82a2, 0x82a3, 0x82a4, 0xbcd9, /*0x40-0x47*/ 0xd9ca, 0x82a5, 0x82a6, 0x82a7, 0xd9bc, 0x82a8, 0xd9cb, 0xc6ab, /*0x48-0x4f*/ 0x82a9, 0x82aa, 0x82ab, 0x82ac, 0x82ad, 0xd9c9, 0x82ae, 0x82af, /*0x50-0x57*/ 0x82b0, 0x82b1, 0xd7f6, 0x82b2, 0xcda3, 0x82b3, 0x82b4, 0x82b5, /*0x58-0x5f*/ 0x82b6, 0x82b7, 0x82b8, 0x82b9, 0x82ba, 0xbda1, 0x82bb, 0x82bc, /*0x60-0x67*/ 0x82bd, 0x82be, 0x82bf, 0x82c0, 0xd9cc, 0x82c1, 0x82c2, 0x82c3, /*0x68-0x6f*/ 0x82c4, 0x82c5, 0x82c6, 0x82c7, 0x82c8, 0x82c9, 0xc5bc, 0xcdb5, /*0x70-0x77*/ 0x82ca, 0x82cb, 0x82cc, 0xd9cd, 0x82cd, 0x82ce, 0xd9c7, 0xb3a5, /*0x78-0x7f*/ 0xbffe, 0x82cf, 0x82d0, 0x82d1, 0x82d2, 0xb8b5, 0x82d3, 0x82d4, /*0x80-0x87*/ 0xc0fc, 0x82d5, 0x82d6, 0x82d7, 0x82d8, 0xb0f8, 0x82d9, 0x82da, /*0x88-0x8f*/ 0x82db, 0x82dc, 0x82dd, 0x82de, 0x82df, 0x82e0, 0x82e1, 0x82e2, /*0x90-0x97*/ 0x82e3, 0x82e4, 0x82e5, 0x82e6, 0x82e7, 0x82e8, 0x82e9, 0x82ea, /*0x98-0x9f*/ 0x82eb, 0x82ec, 0x82ed, 0xb4f6, 0x82ee, 0xd9ce, 0x82ef, 0xd9cf, /*0xa0-0xa7*/ 0xb4a2, 0xd9d0, 0x82f0, 0x82f1, 0xb4df, 0x82f2, 0x82f3, 0x82f4, /*0xa8-0xaf*/ 0x82f5, 0x82f6, 0xb0c1, 0x82f7, 0x82f8, 0x82f9, 0x82fa, 0x82fb, /*0xb0-0xb7*/ 0x82fc, 0x82fd, 0xd9d1, 0xc9b5, 0x82fe, 0x8340, 0x8341, 0x8342, /*0xb8-0xbf*/ 0x8343, 0x8344, 0x8345, 0x8346, 0x8347, 0x8348, 0x8349, 0x834a, /*0xc0-0xc7*/ 0x834b, 0x834c, 0x834d, 0x834e, 0x834f, 0x8350, 0x8351, 0xcff1, /*0xc8-0xcf*/ 0x8352, 0x8353, 0x8354, 0x8355, 0x8356, 0x8357, 0xd9d2, 0x8358, /*0xd0-0xd7*/ 0x8359, 0x835a, 0xc1c5, 0x835b, 0x835c, 0x835d, 0x835e, 0x835f, /*0xd8-0xdf*/ 0x8360, 0x8361, 0x8362, 0x8363, 0x8364, 0x8365, 0xd9d6, 0xc9ae, /*0xe0-0xe7*/ 0x8366, 0x8367, 0x8368, 0x8369, 0xd9d5, 0xd9d4, 0xd9d7, 0x836a, /*0xe8-0xef*/ 0x836b, 0x836c, 0x836d, 0xcbdb, 0x836e, 0xbda9, 0x836f, 0x8370, /*0xf0-0xf7*/ 0x8371, 0x8372, 0x8373, 0xc6a7, 0x8374, 0x8375, 0x8376, 0x8377, /*0xf8-0xff*/ /* 0x5100 */ 0x8378, 0x8379, 0x837a, 0x837b, 0x837c, 0x837d, 0xd9d3, 0xd9d8, /*0x00-0x07*/ 0x837e, 0x8380, 0x8381, 0xd9d9, 0x8382, 0x8383, 0x8384, 0x8385, /*0x08-0x0f*/ 0x8386, 0x8387, 0xc8e5, 0x8388, 0x8389, 0x838a, 0x838b, 0x838c, /*0x10-0x17*/ 0x838d, 0x838e, 0x838f, 0x8390, 0x8391, 0x8392, 0x8393, 0x8394, /*0x18-0x1f*/ 0x8395, 0xc0dc, 0x8396, 0x8397, 0x8398, 0x8399, 0x839a, 0x839b, /*0x20-0x27*/ 0x839c, 0x839d, 0x839e, 0x839f, 0x83a0, 0x83a1, 0x83a2, 0x83a3, /*0x28-0x2f*/ 0x83a4, 0x83a5, 0x83a6, 0x83a7, 0x83a8, 0x83a9, 0x83aa, 0x83ab, /*0x30-0x37*/ 0x83ac, 0x83ad, 0x83ae, 0x83af, 0x83b0, 0x83b1, 0x83b2, 0xb6f9, /*0x38-0x3f*/ 0xd8a3, 0xd4ca, 0x83b3, 0xd4aa, 0xd0d6, 0xb3e4, 0xd5d7, 0x83b4, /*0x40-0x47*/ 0xcfc8, 0xb9e2, 0x83b5, 0xbfcb, 0x83b6, 0xc3e2, 0x83b7, 0x83b8, /*0x48-0x4f*/ 0x83b9, 0xb6d2, 0x83ba, 0x83bb, 0xcdc3, 0xd9ee, 0xd9f0, 0x83bc, /*0x50-0x57*/ 0x83bd, 0x83be, 0xb5b3, 0x83bf, 0xb6b5, 0x83c0, 0x83c1, 0x83c2, /*0x58-0x5f*/ 0x83c3, 0x83c4, 0xbea4, 0x83c5, 0x83c6, 0xc8eb, 0x83c7, 0x83c8, /*0x60-0x67*/ 0xc8ab, 0x83c9, 0x83ca, 0xb0cb, 0xb9ab, 0xc1f9, 0xd9e2, 0x83cb, /*0x68-0x6f*/ 0xc0bc, 0xb9b2, 0x83cc, 0xb9d8, 0xd0cb, 0xb1f8, 0xc6e4, 0xbedf, /*0x70-0x77*/ 0xb5e4, 0xd7c8, 0x83cd, 0xd1f8, 0xbce6, 0xcade, 0x83ce, 0x83cf, /*0x78-0x7f*/ 0xbcbd, 0xd9e6, 0xd8e7, 0x83d0, 0x83d1, 0xc4da, 0x83d2, 0x83d3, /*0x80-0x87*/ 0xb8d4, 0xc8bd, 0x83d4, 0x83d5, 0xb2e1, 0xd4d9, 0x83d6, 0x83d7, /*0x88-0x8f*/ 0x83d8, 0x83d9, 0xc3b0, 0x83da, 0x83db, 0xc3e1, 0xdaa2, 0xc8df, /*0x90-0x97*/ 0x83dc, 0xd0b4, 0x83dd, 0xbefc, 0xc5a9, 0x83de, 0x83df, 0x83e0, /*0x98-0x9f*/ 0xb9da, 0x83e1, 0xdaa3, 0x83e2, 0xd4a9, 0xdaa4, 0x83e3, 0x83e4, /*0xa0-0xa7*/ 0x83e5, 0x83e6, 0x83e7, 0xd9fb, 0xb6ac, 0x83e8, 0x83e9, 0xb7eb, /*0xa8-0xaf*/ 0xb1f9, 0xd9fc, 0xb3e5, 0xbef6, 0x83ea, 0xbff6, 0xd2b1, 0xc0e4, /*0xb0-0xb7*/ 0x83eb, 0x83ec, 0x83ed, 0xb6b3, 0xd9fe, 0xd9fd, 0x83ee, 0x83ef, /*0xb8-0xbf*/ 0xbebb, 0x83f0, 0x83f1, 0x83f2, 0xc6e0, 0x83f3, 0xd7bc, 0xdaa1, /*0xc0-0xc7*/ 0x83f4, 0xc1b9, 0x83f5, 0xb5f2, 0xc1e8, 0x83f6, 0x83f7, 0xbcf5, /*0xc8-0xcf*/ 0x83f8, 0xb4d5, 0x83f9, 0x83fa, 0x83fb, 0x83fc, 0x83fd, 0x83fe, /*0xd0-0xd7*/ 0x8440, 0x8441, 0x8442, 0xc1dd, 0x8443, 0xc4fd, 0x8444, 0x8445, /*0xd8-0xdf*/ 0xbcb8, 0xb7b2, 0x8446, 0x8447, 0xb7ef, 0x8448, 0x8449, 0x844a, /*0xe0-0xe7*/ 0x844b, 0x844c, 0x844d, 0xd9ec, 0x844e, 0xc6be, 0x844f, 0xbfad, /*0xe8-0xef*/ 0xbbcb, 0x8450, 0x8451, 0xb5ca, 0x8452, 0xdbc9, 0xd0d7, 0x8453, /*0xf0-0xf7*/ 0xcdb9, 0xb0bc, 0xb3f6, 0xbbf7, 0xdbca, 0xbaaf, 0x8454, 0xd4e4, /*0xf8-0xff*/ /* 0x5200 */ 0xb5b6, 0xb5f3, 0xd8d6, 0xc8d0, 0x8455, 0x8456, 0xb7d6, 0xc7d0, /*0x00-0x07*/ 0xd8d7, 0x8457, 0xbfaf, 0x8458, 0x8459, 0xdbbb, 0xd8d8, 0x845a, /*0x08-0x0f*/ 0x845b, 0xd0cc, 0xbbae, 0x845c, 0x845d, 0x845e, 0xebbe, 0xc1d0, /*0x10-0x17*/ 0xc1f5, 0xd4f2, 0xb8d5, 0xb4b4, 0x845f, 0xb3f5, 0x8460, 0x8461, /*0x18-0x1f*/ 0xc9be, 0x8462, 0x8463, 0x8464, 0xc5d0, 0x8465, 0x8466, 0x8467, /*0x20-0x27*/ 0xc5d9, 0xc0fb, 0x8468, 0xb1f0, 0x8469, 0xd8d9, 0xb9ce, 0x846a, /*0x28-0x2f*/ 0xb5bd, 0x846b, 0x846c, 0xd8da, 0x846d, 0x846e, 0xd6c6, 0xcba2, /*0x30-0x37*/ 0xc8af, 0xc9b2, 0xb4cc, 0xbfcc, 0x846f, 0xb9f4, 0x8470, 0xd8db, /*0x38-0x3f*/ 0xd8dc, 0xb6e7, 0xbcc1, 0xccea, 0x8471, 0x8472, 0x8473, 0x8474, /*0x40-0x47*/ 0x8475, 0x8476, 0xcff7, 0x8477, 0xd8dd, 0xc7b0, 0x8478, 0x8479, /*0x48-0x4f*/ 0xb9d0, 0xbda3, 0x847a, 0x847b, 0xccde, 0x847c, 0xc6ca, 0x847d, /*0x50-0x57*/ 0x847e, 0x8480, 0x8481, 0x8482, 0xd8e0, 0x8483, 0xd8de, 0x8484, /*0x58-0x5f*/ 0x8485, 0xd8df, 0x8486, 0x8487, 0x8488, 0xb0fe, 0x8489, 0xbee7, /*0x60-0x67*/ 0x848a, 0xcaa3, 0xbcf4, 0x848b, 0x848c, 0x848d, 0x848e, 0xb8b1, /*0x68-0x6f*/ 0x848f, 0x8490, 0xb8ee, 0x8491, 0x8492, 0x8493, 0x8494, 0x8495, /*0x70-0x77*/ 0x8496, 0x8497, 0x8498, 0x8499, 0x849a, 0xd8e2, 0x849b, 0xbdcb, /*0x78-0x7f*/ 0x849c, 0xd8e4, 0xd8e3, 0x849d, 0x849e, 0x849f, 0x84a0, 0x84a1, /*0x80-0x87*/ 0xc5fc, 0x84a2, 0x84a3, 0x84a4, 0x84a5, 0x84a6, 0x84a7, 0x84a8, /*0x88-0x8f*/ 0xd8e5, 0x84a9, 0x84aa, 0xd8e6, 0x84ab, 0x84ac, 0x84ad, 0x84ae, /*0x90-0x97*/ 0x84af, 0x84b0, 0x84b1, 0xc1a6, 0x84b2, 0xc8b0, 0xb0ec, 0xb9a6, /*0x98-0x9f*/ 0xbcd3, 0xcef1, 0xdbbd, 0xc1d3, 0x84b3, 0x84b4, 0x84b5, 0x84b6, /*0xa0-0xa7*/ 0xb6af, 0xd6fa, 0xc5ac, 0xbdd9, 0xdbbe, 0xdbbf, 0x84b7, 0x84b8, /*0xa8-0xaf*/ 0x84b9, 0xc0f8, 0xbea2, 0xc0cd, 0x84ba, 0x84bb, 0x84bc, 0x84bd, /*0xb0-0xb7*/ 0x84be, 0x84bf, 0x84c0, 0x84c1, 0x84c2, 0x84c3, 0xdbc0, 0xcac6, /*0xb8-0xbf*/ 0x84c4, 0x84c5, 0x84c6, 0xb2aa, 0x84c7, 0x84c8, 0x84c9, 0xd3c2, /*0xc0-0xc7*/ 0x84ca, 0xc3e3, 0x84cb, 0xd1ab, 0x84cc, 0x84cd, 0x84ce, 0x84cf, /*0xc8-0xcf*/ 0xdbc2, 0x84d0, 0xc0d5, 0x84d1, 0x84d2, 0x84d3, 0xdbc3, 0x84d4, /*0xd0-0xd7*/ 0xbfb1, 0x84d5, 0x84d6, 0x84d7, 0x84d8, 0x84d9, 0x84da, 0xc4bc, /*0xd8-0xdf*/ 0x84db, 0x84dc, 0x84dd, 0x84de, 0xc7da, 0x84df, 0x84e0, 0x84e1, /*0xe0-0xe7*/ 0x84e2, 0x84e3, 0x84e4, 0x84e5, 0x84e6, 0x84e7, 0x84e8, 0x84e9, /*0xe8-0xef*/ 0xdbc4, 0x84ea, 0x84eb, 0x84ec, 0x84ed, 0x84ee, 0x84ef, 0x84f0, /*0xf0-0xf7*/ 0x84f1, 0xd9e8, 0xc9d7, 0x84f2, 0x84f3, 0x84f4, 0xb9b4, 0xcef0, /*0xf8-0xff*/ /* 0x5300 */ 0xd4c8, 0x84f5, 0x84f6, 0x84f7, 0x84f8, 0xb0fc, 0xb4d2, 0x84f9, /*0x00-0x07*/ 0xd0d9, 0x84fa, 0x84fb, 0x84fc, 0x84fd, 0xd9e9, 0x84fe, 0xdecb, /*0x08-0x0f*/ 0xd9eb, 0x8540, 0x8541, 0x8542, 0x8543, 0xd8b0, 0xbbaf, 0xb1b1, /*0x10-0x17*/ 0x8544, 0xb3d7, 0xd8ce, 0x8545, 0x8546, 0xd4d1, 0x8547, 0x8548, /*0x18-0x1f*/ 0xbdb3, 0xbfef, 0x8549, 0xcfbb, 0x854a, 0x854b, 0xd8d0, 0x854c, /*0x20-0x27*/ 0x854d, 0x854e, 0xb7cb, 0x854f, 0x8550, 0x8551, 0xd8d1, 0x8552, /*0x28-0x2f*/ 0x8553, 0x8554, 0x8555, 0x8556, 0x8557, 0x8558, 0x8559, 0x855a, /*0x30-0x37*/ 0x855b, 0xc6a5, 0xc7f8, 0xd2bd, 0x855c, 0x855d, 0xd8d2, 0xc4e4, /*0x38-0x3f*/ 0x855e, 0xcaae, 0x855f, 0xc7a7, 0x8560, 0xd8a6, 0x8561, 0xc9fd, /*0x40-0x47*/ 0xcee7, 0xbbdc, 0xb0eb, 0x8562, 0x8563, 0x8564, 0xbbaa, 0xd0ad, /*0x48-0x4f*/ 0x8565, 0xb1b0, 0xd7e4, 0xd7bf, 0x8566, 0xb5a5, 0xc2f4, 0xc4cf, /*0x50-0x57*/ 0x8567, 0x8568, 0xb2a9, 0x8569, 0xb2b7, 0x856a, 0xb1e5, 0xdfb2, /*0x58-0x5f*/ 0xd5bc, 0xbfa8, 0xc2ac, 0xd8d5, 0xc2b1, 0x856b, 0xd8d4, 0xced4, /*0x60-0x67*/ 0x856c, 0xdae0, 0x856d, 0xcec0, 0x856e, 0x856f, 0xd8b4, 0xc3ae, /*0x68-0x6f*/ 0xd3a1, 0xcea3, 0x8570, 0xbcb4, 0xc8b4, 0xc2d1, 0x8571, 0xbeed, /*0x70-0x77*/ 0xd0b6, 0x8572, 0xdae1, 0x8573, 0x8574, 0x8575, 0x8576, 0xc7e4, /*0x78-0x7f*/ 0x8577, 0x8578, 0xb3a7, 0x8579, 0xb6f2, 0xccfc, 0xc0fa, 0x857a, /*0x80-0x87*/ 0x857b, 0xc0f7, 0x857c, 0xd1b9, 0xd1e1, 0xd8c7, 0x857d, 0x857e, /*0x88-0x8f*/ 0x8580, 0x8581, 0x8582, 0x8583, 0x8584, 0xb2de, 0x8585, 0x8586, /*0x90-0x97*/ 0xc0e5, 0x8587, 0xbaf1, 0x8588, 0x8589, 0xd8c8, 0x858a, 0xd4ad, /*0x98-0x9f*/ 0x858b, 0x858c, 0xcfe1, 0xd8c9, 0x858d, 0xd8ca, 0xcfc3, 0x858e, /*0xa0-0xa7*/ 0xb3f8, 0xbec7, 0x858f, 0x8590, 0x8591, 0x8592, 0xd8cb, 0x8593, /*0xa8-0xaf*/ 0x8594, 0x8595, 0x8596, 0x8597, 0x8598, 0x8599, 0xdbcc, 0x859a, /*0xb0-0xb7*/ 0x859b, 0x859c, 0x859d, 0xc8a5, 0x859e, 0x859f, 0x85a0, 0xcfd8, /*0xb8-0xbf*/ 0x85a1, 0xc8fe, 0xb2ce, 0x85a2, 0x85a3, 0x85a4, 0x85a5, 0x85a6, /*0xc0-0xc7*/ 0xd3d6, 0xb2e6, 0xbcb0, 0xd3d1, 0xcbab, 0xb7b4, 0x85a7, 0x85a8, /*0xc8-0xcf*/ 0x85a9, 0xb7a2, 0x85aa, 0x85ab, 0xcae5, 0x85ac, 0xc8a1, 0xcadc, /*0xd0-0xd7*/ 0xb1e4, 0xd0f0, 0x85ad, 0xc5d1, 0x85ae, 0x85af, 0x85b0, 0xdbc5, /*0xd8-0xdf*/ 0xb5fe, 0x85b1, 0x85b2, 0xbfda, 0xb9c5, 0xbee4, 0xc1ed, 0x85b3, /*0xe0-0xe7*/ 0xdfb6, 0xdfb5, 0xd6bb, 0xbdd0, 0xd5d9, 0xb0c8, 0xb6a3, 0xbfc9, /*0xe8-0xef*/ 0xcca8, 0xdfb3, 0xcab7, 0xd3d2, 0x85b4, 0xd8cf, 0xd2b6, 0xbac5, /*0xf0-0xf7*/ 0xcbbe, 0xccbe, 0x85b5, 0xdfb7, 0xb5f0, 0xdfb4, 0x85b6, 0x85b7, /*0xf8-0xff*/ /* 0x5400 */ 0x85b8, 0xd3f5, 0x85b9, 0xb3d4, 0xb8f7, 0x85ba, 0xdfba, 0x85bb, /*0x00-0x07*/ 0xbacf, 0xbcaa, 0xb5f5, 0x85bc, 0xcdac, 0xc3fb, 0xbaf3, 0xc0f4, /*0x08-0x0f*/ 0xcdc2, 0xcff2, 0xdfb8, 0xcfc5, 0x85bd, 0xc2c0, 0xdfb9, 0xc2f0, /*0x10-0x17*/ 0x85be, 0x85bf, 0x85c0, 0xbefd, 0x85c1, 0xc1df, 0xcdcc, 0xd2f7, /*0x18-0x1f*/ 0xb7cd, 0xdfc1, 0x85c2, 0xdfc4, 0x85c3, 0x85c4, 0xb7f1, 0xb0c9, /*0x20-0x27*/ 0xb6d6, 0xb7d4, 0x85c5, 0xbaac, 0xccfd, 0xbfd4, 0xcbb1, 0xc6f4, /*0x28-0x2f*/ 0x85c6, 0xd6a8, 0xdfc5, 0x85c7, 0xcee2, 0xb3b3, 0x85c8, 0x85c9, /*0x30-0x37*/ 0xcefc, 0xb4b5, 0x85ca, 0xcec7, 0xbaf0, 0x85cb, 0xcee1, 0x85cc, /*0x38-0x3f*/ 0xd1bd, 0x85cd, 0x85ce, 0xdfc0, 0x85cf, 0x85d0, 0xb4f4, 0x85d1, /*0x40-0x47*/ 0xb3ca, 0x85d2, 0xb8e6, 0xdfbb, 0x85d3, 0x85d4, 0x85d5, 0x85d6, /*0x48-0x4f*/ 0xc4c5, 0x85d7, 0xdfbc, 0xdfbd, 0xdfbe, 0xc5bb, 0xdfbf, 0xdfc2, /*0x50-0x57*/ 0xd4b1, 0xdfc3, 0x85d8, 0xc7ba, 0xced8, 0x85d9, 0x85da, 0x85db, /*0x58-0x5f*/ 0x85dc, 0x85dd, 0xc4d8, 0x85de, 0xdfca, 0x85df, 0xdfcf, 0x85e0, /*0x60-0x67*/ 0xd6dc, 0x85e1, 0x85e2, 0x85e3, 0x85e4, 0x85e5, 0x85e6, 0x85e7, /*0x68-0x6f*/ 0x85e8, 0xdfc9, 0xdfda, 0xceb6, 0x85e9, 0xbac7, 0xdfce, 0xdfc8, /*0x70-0x77*/ 0xc5de, 0x85ea, 0x85eb, 0xc9eb, 0xbaf4, 0xc3fc, 0x85ec, 0x85ed, /*0x78-0x7f*/ 0xbed7, 0x85ee, 0xdfc6, 0x85ef, 0xdfcd, 0x85f0, 0xc5d8, 0x85f1, /*0x80-0x87*/ 0x85f2, 0x85f3, 0x85f4, 0xd5a6, 0xbacd, 0x85f5, 0xbecc, 0xd3bd, /*0x88-0x8f*/ 0xb8c0, 0x85f6, 0xd6e4, 0x85f7, 0xdfc7, 0xb9be, 0xbfa7, 0x85f8, /*0x90-0x97*/ 0x85f9, 0xc1fc, 0xdfcb, 0xdfcc, 0x85fa, 0xdfd0, 0x85fb, 0x85fc, /*0x98-0x9f*/ 0x85fd, 0x85fe, 0x8640, 0xdfdb, 0xdfe5, 0x8641, 0xdfd7, 0xdfd6, /*0xa0-0xa7*/ 0xd7c9, 0xdfe3, 0xdfe4, 0xe5eb, 0xd2a7, 0xdfd2, 0x8642, 0xbfa9, /*0xa8-0xaf*/ 0x8643, 0xd4db, 0x8644, 0xbfc8, 0xdfd4, 0x8645, 0x8646, 0x8647, /*0xb0-0xb7*/ 0xcfcc, 0x8648, 0x8649, 0xdfdd, 0x864a, 0xd1ca, 0x864b, 0xdfde, /*0xb8-0xbf*/ 0xb0a7, 0xc6b7, 0xdfd3, 0x864c, 0xbae5, 0x864d, 0xb6df, 0xcddb, /*0xc0-0xc7*/ 0xb9fe, 0xd4d5, 0x864e, 0x864f, 0xdfdf, 0xcfec, 0xb0a5, 0xdfe7, /*0xc8-0xcf*/ 0xdfd1, 0xd1c6, 0xdfd5, 0xdfd8, 0xdfd9, 0xdfdc, 0x8650, 0xbba9, /*0xd0-0xd7*/ 0x8651, 0xdfe0, 0xdfe1, 0x8652, 0xdfe2, 0xdfe6, 0xdfe8, 0xd3b4, /*0xd8-0xdf*/ 0x8653, 0x8654, 0x8655, 0x8656, 0x8657, 0xb8e7, 0xc5b6, 0xdfea, /*0xe0-0xe7*/ 0xc9da, 0xc1a8, 0xc4c4, 0x8658, 0x8659, 0xbfde, 0xcff8, 0x865a, /*0xe8-0xef*/ 0x865b, 0x865c, 0xd5dc, 0xdfee, 0x865d, 0x865e, 0x865f, 0x8660, /*0xf0-0xf7*/ 0x8661, 0x8662, 0xb2b8, 0x8663, 0xbadf, 0xdfec, 0x8664, 0xdbc1, /*0xf8-0xff*/ /* 0x5500 */ 0x8665, 0xd1e4, 0x8666, 0x8667, 0x8668, 0x8669, 0xcbf4, 0xb4bd, /*0x00-0x07*/ 0x866a, 0xb0a6, 0x866b, 0x866c, 0x866d, 0x866e, 0x866f, 0xdff1, /*0x08-0x0f*/ 0xccc6, 0xdff2, 0x8670, 0x8671, 0xdfed, 0x8672, 0x8673, 0x8674, /*0x10-0x17*/ 0x8675, 0x8676, 0x8677, 0xdfe9, 0x8678, 0x8679, 0x867a, 0x867b, /*0x18-0x1f*/ 0xdfeb, 0x867c, 0xdfef, 0xdff0, 0xbbbd, 0x867d, 0x867e, 0xdff3, /*0x20-0x27*/ 0x8680, 0x8681, 0xdff4, 0x8682, 0xbba3, 0x8683, 0xcadb, 0xcea8, /*0x28-0x2f*/ 0xe0a7, 0xb3aa, 0x8684, 0xe0a6, 0x8685, 0x8686, 0x8687, 0xe0a1, /*0x30-0x37*/ 0x8688, 0x8689, 0x868a, 0x868b, 0xdffe, 0x868c, 0xcdd9, 0xdffc, /*0x38-0x3f*/ 0x868d, 0xdffa, 0x868e, 0xbfd0, 0xd7c4, 0x868f, 0xc9cc, 0x8690, /*0x40-0x47*/ 0x8691, 0xdff8, 0xb0a1, 0x8692, 0x8693, 0x8694, 0x8695, 0x8696, /*0x48-0x4f*/ 0xdffd, 0x8697, 0x8698, 0x8699, 0x869a, 0xdffb, 0xe0a2, 0x869b, /*0x50-0x57*/ 0x869c, 0x869d, 0x869e, 0x869f, 0xe0a8, 0x86a0, 0x86a1, 0x86a2, /*0x58-0x5f*/ 0x86a3, 0xb7c8, 0x86a4, 0x86a5, 0xc6a1, 0xc9b6, 0xc0b2, 0xdff5, /*0x60-0x67*/ 0x86a6, 0x86a7, 0xc5be, 0x86a8, 0xd8c4, 0xdff9, 0xc4f6, 0x86a9, /*0x68-0x6f*/ 0x86aa, 0x86ab, 0x86ac, 0x86ad, 0x86ae, 0xe0a3, 0xe0a4, 0xe0a5, /*0x70-0x77*/ 0xd0a5, 0x86af, 0x86b0, 0xe0b4, 0xcce4, 0x86b1, 0xe0b1, 0x86b2, /*0x78-0x7f*/ 0xbfa6, 0xe0af, 0xceb9, 0xe0ab, 0xc9c6, 0x86b3, 0x86b4, 0xc0ae, /*0x80-0x87*/ 0xe0ae, 0xbaed, 0xbab0, 0xe0a9, 0x86b5, 0x86b6, 0x86b7, 0xdff6, /*0x88-0x8f*/ 0x86b8, 0xe0b3, 0x86b9, 0x86ba, 0xe0b8, 0x86bb, 0x86bc, 0x86bd, /*0x90-0x97*/ 0xb4ad, 0xe0b9, 0x86be, 0x86bf, 0xcfb2, 0xbac8, 0x86c0, 0xe0b0, /*0x98-0x9f*/ 0x86c1, 0x86c2, 0x86c3, 0x86c4, 0x86c5, 0x86c6, 0x86c7, 0xd0fa, /*0xa0-0xa7*/ 0x86c8, 0x86c9, 0x86ca, 0x86cb, 0x86cc, 0x86cd, 0x86ce, 0x86cf, /*0xa8-0xaf*/ 0x86d0, 0xe0ac, 0x86d1, 0xd4fb, 0x86d2, 0xdff7, 0x86d3, 0xc5e7, /*0xb0-0xb7*/ 0x86d4, 0xe0ad, 0x86d5, 0xd3f7, 0x86d6, 0xe0b6, 0xe0b7, 0x86d7, /*0xb8-0xbf*/ 0x86d8, 0x86d9, 0x86da, 0x86db, 0xe0c4, 0xd0e1, 0x86dc, 0x86dd, /*0xc0-0xc7*/ 0x86de, 0xe0bc, 0x86df, 0x86e0, 0xe0c9, 0xe0ca, 0x86e1, 0x86e2, /*0xc8-0xcf*/ 0x86e3, 0xe0be, 0xe0aa, 0xc9a4, 0xe0c1, 0x86e4, 0xe0b2, 0x86e5, /*0xd0-0xd7*/ 0x86e6, 0x86e7, 0x86e8, 0x86e9, 0xcac8, 0xe0c3, 0x86ea, 0xe0b5, /*0xd8-0xdf*/ 0x86eb, 0xcecb, 0x86ec, 0xcbc3, 0xe0cd, 0xe0c6, 0xe0c2, 0x86ed, /*0xe0-0xe7*/ 0xe0cb, 0x86ee, 0xe0ba, 0xe0bf, 0xe0c0, 0x86ef, 0x86f0, 0xe0c5, /*0xe8-0xef*/ 0x86f1, 0x86f2, 0xe0c7, 0xe0c8, 0x86f3, 0xe0cc, 0x86f4, 0xe0bb, /*0xf0-0xf7*/ 0x86f5, 0x86f6, 0x86f7, 0x86f8, 0x86f9, 0xcbd4, 0xe0d5, 0x86fa, /*0xf8-0xff*/ /* 0x5600 */ 0xe0d6, 0xe0d2, 0x86fb, 0x86fc, 0x86fd, 0x86fe, 0x8740, 0x8741, /*0x00-0x07*/ 0xe0d0, 0xbcce, 0x8742, 0x8743, 0xe0d1, 0x8744, 0xb8c2, 0xd8c5, /*0x08-0x0f*/ 0x8745, 0x8746, 0x8747, 0x8748, 0x8749, 0x874a, 0x874b, 0x874c, /*0x10-0x17*/ 0xd0ea, 0x874d, 0x874e, 0xc2ef, 0x874f, 0x8750, 0xe0cf, 0xe0bd, /*0x18-0x1f*/ 0x8751, 0x8752, 0x8753, 0xe0d4, 0xe0d3, 0x8754, 0x8755, 0xe0d7, /*0x20-0x27*/ 0x8756, 0x8757, 0x8758, 0x8759, 0xe0dc, 0xe0d8, 0x875a, 0x875b, /*0x28-0x2f*/ 0x875c, 0xd6f6, 0xb3b0, 0x875d, 0xd7ec, 0x875e, 0xcbbb, 0x875f, /*0x30-0x37*/ 0x8760, 0xe0da, 0x8761, 0xcefb, 0x8762, 0x8763, 0x8764, 0xbad9, /*0x38-0x3f*/ 0x8765, 0x8766, 0x8767, 0x8768, 0x8769, 0x876a, 0x876b, 0x876c, /*0x40-0x47*/ 0x876d, 0x876e, 0x876f, 0x8770, 0xe0e1, 0xe0dd, 0xd2ad, 0x8771, /*0x48-0x4f*/ 0x8772, 0x8773, 0x8774, 0x8775, 0xe0e2, 0x8776, 0x8777, 0xe0db, /*0x50-0x57*/ 0xe0d9, 0xe0df, 0x8778, 0x8779, 0xe0e0, 0x877a, 0x877b, 0x877c, /*0x58-0x5f*/ 0x877d, 0x877e, 0xe0de, 0x8780, 0xe0e4, 0x8781, 0x8782, 0x8783, /*0x60-0x67*/ 0xc6f7, 0xd8ac, 0xd4eb, 0xe0e6, 0xcac9, 0x8784, 0x8785, 0x8786, /*0x68-0x6f*/ 0x8787, 0xe0e5, 0x8788, 0x8789, 0x878a, 0x878b, 0xb8c1, 0x878c, /*0x70-0x77*/ 0x878d, 0x878e, 0x878f, 0xe0e7, 0xe0e8, 0x8790, 0x8791, 0x8792, /*0x78-0x7f*/ 0x8793, 0x8794, 0x8795, 0x8796, 0x8797, 0xe0e9, 0xe0e3, 0x8798, /*0x80-0x87*/ 0x8799, 0x879a, 0x879b, 0x879c, 0x879d, 0x879e, 0xbabf, 0xcce7, /*0x88-0x8f*/ 0x879f, 0x87a0, 0x87a1, 0xe0ea, 0x87a2, 0x87a3, 0x87a4, 0x87a5, /*0x90-0x97*/ 0x87a6, 0x87a7, 0x87a8, 0x87a9, 0x87aa, 0x87ab, 0x87ac, 0x87ad, /*0x98-0x9f*/ 0x87ae, 0x87af, 0x87b0, 0xcff9, 0x87b1, 0x87b2, 0x87b3, 0x87b4, /*0xa0-0xa7*/ 0x87b5, 0x87b6, 0x87b7, 0x87b8, 0x87b9, 0x87ba, 0x87bb, 0xe0eb, /*0xa8-0xaf*/ 0x87bc, 0x87bd, 0x87be, 0x87bf, 0x87c0, 0x87c1, 0x87c2, 0xc8c2, /*0xb0-0xb7*/ 0x87c3, 0x87c4, 0x87c5, 0x87c6, 0xbdc0, 0x87c7, 0x87c8, 0x87c9, /*0xb8-0xbf*/ 0x87ca, 0x87cb, 0x87cc, 0x87cd, 0x87ce, 0x87cf, 0x87d0, 0x87d1, /*0xc0-0xc7*/ 0x87d2, 0x87d3, 0xc4d2, 0x87d4, 0x87d5, 0x87d6, 0x87d7, 0x87d8, /*0xc8-0xcf*/ 0x87d9, 0x87da, 0x87db, 0x87dc, 0xe0ec, 0x87dd, 0x87de, 0xe0ed, /*0xd0-0xd7*/ 0x87df, 0x87e0, 0xc7f4, 0xcbc4, 0x87e1, 0xe0ee, 0xbbd8, 0xd8b6, /*0xd8-0xdf*/ 0xd2f2, 0xe0ef, 0xcdc5, 0x87e2, 0xb6da, 0x87e3, 0x87e4, 0x87e5, /*0xe0-0xe7*/ 0x87e6, 0x87e7, 0x87e8, 0xe0f1, 0x87e9, 0xd4b0, 0x87ea, 0x87eb, /*0xe8-0xef*/ 0xc0a7, 0xb4d1, 0x87ec, 0x87ed, 0xcea7, 0xe0f0, 0x87ee, 0x87ef, /*0xf0-0xf7*/ 0x87f0, 0xe0f2, 0xb9cc, 0x87f1, 0x87f2, 0xb9fa, 0xcdbc, 0xe0f3, /*0xf8-0xff*/ /* 0x5700 */ 0x87f3, 0x87f4, 0x87f5, 0xc6d4, 0xe0f4, 0x87f6, 0xd4b2, 0x87f7, /*0x00-0x07*/ 0xc8a6, 0xe0f6, 0xe0f5, 0x87f8, 0x87f9, 0x87fa, 0x87fb, 0x87fc, /*0x08-0x0f*/ 0x87fd, 0x87fe, 0x8840, 0x8841, 0x8842, 0x8843, 0x8844, 0x8845, /*0x10-0x17*/ 0x8846, 0x8847, 0x8848, 0x8849, 0xe0f7, 0x884a, 0x884b, 0xcdc1, /*0x18-0x1f*/ 0x884c, 0x884d, 0x884e, 0xcaa5, 0x884f, 0x8850, 0x8851, 0x8852, /*0x20-0x27*/ 0xd4da, 0xdbd7, 0xdbd9, 0x8853, 0xdbd8, 0xb9e7, 0xdbdc, 0xdbdd, /*0x28-0x2f*/ 0xb5d8, 0x8854, 0x8855, 0xdbda, 0x8856, 0x8857, 0x8858, 0x8859, /*0x30-0x37*/ 0x885a, 0xdbdb, 0xb3a1, 0xdbdf, 0x885b, 0x885c, 0xbbf8, 0x885d, /*0x38-0x3f*/ 0xd6b7, 0x885e, 0xdbe0, 0x885f, 0x8860, 0x8861, 0x8862, 0xbef9, /*0x40-0x47*/ 0x8863, 0x8864, 0xb7bb, 0x8865, 0xdbd0, 0xccae, 0xbfb2, 0xbbb5, /*0x48-0x4f*/ 0xd7f8, 0xbfd3, 0x8866, 0x8867, 0x8868, 0x8869, 0x886a, 0xbfe9, /*0x50-0x57*/ 0x886b, 0x886c, 0xbce1, 0xccb3, 0xdbde, 0xb0d3, 0xceeb, 0xb7d8, /*0x58-0x5f*/ 0xd7b9, 0xc6c2, 0x886d, 0x886e, 0xc0a4, 0x886f, 0xccb9, 0x8870, /*0x60-0x67*/ 0xdbe7, 0xdbe1, 0xc6ba, 0xdbe3, 0x8871, 0xdbe8, 0x8872, 0xc5f7, /*0x68-0x6f*/ 0x8873, 0x8874, 0x8875, 0xdbea, 0x8876, 0x8877, 0xdbe9, 0xbfc0, /*0x70-0x77*/ 0x8878, 0x8879, 0x887a, 0xdbe6, 0xdbe5, 0x887b, 0x887c, 0x887d, /*0x78-0x7f*/ 0x887e, 0x8880, 0xb4b9, 0xc0ac, 0xc2a2, 0xdbe2, 0xdbe4, 0x8881, /*0x80-0x87*/ 0x8882, 0x8883, 0x8884, 0xd0cd, 0xdbed, 0x8885, 0x8886, 0x8887, /*0x88-0x8f*/ 0x8888, 0x8889, 0xc0dd, 0xdbf2, 0x888a, 0x888b, 0x888c, 0x888d, /*0x90-0x97*/ 0x888e, 0x888f, 0x8890, 0xb6e2, 0x8891, 0x8892, 0x8893, 0x8894, /*0x98-0x9f*/ 0xdbf3, 0xdbd2, 0xb9b8, 0xd4ab, 0xdbec, 0x8895, 0xbfd1, 0xdbf0, /*0xa0-0xa7*/ 0x8896, 0xdbd1, 0x8897, 0xb5e6, 0x8898, 0xdbeb, 0xbfe5, 0x8899, /*0xa8-0xaf*/ 0x889a, 0x889b, 0xdbee, 0x889c, 0xdbf1, 0x889d, 0x889e, 0x889f, /*0xb0-0xb7*/ 0xdbf9, 0x88a0, 0x88a1, 0x88a2, 0x88a3, 0x88a4, 0x88a5, 0x88a6, /*0xb8-0xbf*/ 0x88a7, 0x88a8, 0xb9a1, 0xb0a3, 0x88a9, 0x88aa, 0x88ab, 0x88ac, /*0xc0-0xc7*/ 0x88ad, 0x88ae, 0x88af, 0xc2f1, 0x88b0, 0x88b1, 0xb3c7, 0xdbef, /*0xc8-0xcf*/ 0x88b2, 0x88b3, 0xdbf8, 0x88b4, 0xc6d2, 0xdbf4, 0x88b5, 0x88b6, /*0xd0-0xd7*/ 0xdbf5, 0xdbf7, 0xdbf6, 0x88b7, 0x88b8, 0xdbfe, 0x88b9, 0xd3f2, /*0xd8-0xdf*/ 0xb2ba, 0x88ba, 0x88bb, 0x88bc, 0xdbfd, 0x88bd, 0x88be, 0x88bf, /*0xe0-0xe7*/ 0x88c0, 0x88c1, 0x88c2, 0x88c3, 0x88c4, 0xdca4, 0x88c5, 0xdbfb, /*0xe8-0xef*/ 0x88c6, 0x88c7, 0x88c8, 0x88c9, 0xdbfa, 0x88ca, 0x88cb, 0x88cc, /*0xf0-0xf7*/ 0xdbfc, 0xc5e0, 0xbbf9, 0x88cd, 0x88ce, 0xdca3, 0x88cf, 0x88d0, /*0xf8-0xff*/ /* 0x5800 */ 0xdca5, 0x88d1, 0xccc3, 0x88d2, 0x88d3, 0x88d4, 0xb6d1, 0xddc0, /*0x00-0x07*/ 0x88d5, 0x88d6, 0x88d7, 0xdca1, 0x88d8, 0xdca2, 0x88d9, 0x88da, /*0x08-0x0f*/ 0x88db, 0xc7b5, 0x88dc, 0x88dd, 0x88de, 0xb6e9, 0x88df, 0x88e0, /*0x10-0x17*/ 0x88e1, 0xdca7, 0x88e2, 0x88e3, 0x88e4, 0x88e5, 0xdca6, 0x88e6, /*0x18-0x1f*/ 0xdca9, 0xb1a4, 0x88e7, 0x88e8, 0xb5cc, 0x88e9, 0x88ea, 0x88eb, /*0x20-0x27*/ 0x88ec, 0x88ed, 0xbfb0, 0x88ee, 0x88ef, 0x88f0, 0x88f1, 0x88f2, /*0x28-0x2f*/ 0xd1df, 0x88f3, 0x88f4, 0x88f5, 0x88f6, 0xb6c2, 0x88f7, 0x88f8, /*0x30-0x37*/ 0x88f9, 0x88fa, 0x88fb, 0x88fc, 0x88fd, 0x88fe, 0x8940, 0x8941, /*0x38-0x3f*/ 0x8942, 0x8943, 0x8944, 0x8945, 0xdca8, 0x8946, 0x8947, 0x8948, /*0x40-0x47*/ 0x8949, 0x894a, 0x894b, 0x894c, 0xcbfa, 0xebf3, 0x894d, 0x894e, /*0x48-0x4f*/ 0x894f, 0xcbdc, 0x8950, 0x8951, 0xcbfe, 0x8952, 0x8953, 0x8954, /*0x50-0x57*/ 0xccc1, 0x8955, 0x8956, 0x8957, 0x8958, 0x8959, 0xc8fb, 0x895a, /*0x58-0x5f*/ 0x895b, 0x895c, 0x895d, 0x895e, 0x895f, 0xdcaa, 0x8960, 0x8961, /*0x60-0x67*/ 0x8962, 0x8963, 0x8964, 0xccee, 0xdcab, 0x8965, 0x8966, 0x8967, /*0x68-0x6f*/ 0x8968, 0x8969, 0x896a, 0x896b, 0x896c, 0x896d, 0x896e, 0x896f, /*0x70-0x77*/ 0x8970, 0x8971, 0x8972, 0x8973, 0x8974, 0x8975, 0xdbd3, 0x8976, /*0x78-0x7f*/ 0xdcaf, 0xdcac, 0x8977, 0xbeb3, 0x8978, 0xcafb, 0x8979, 0x897a, /*0x80-0x87*/ 0x897b, 0xdcad, 0x897c, 0x897d, 0x897e, 0x8980, 0x8981, 0x8982, /*0x88-0x8f*/ 0x8983, 0x8984, 0xc9ca, 0xc4b9, 0x8985, 0x8986, 0x8987, 0x8988, /*0x90-0x97*/ 0x8989, 0xc7bd, 0xdcae, 0x898a, 0x898b, 0x898c, 0xd4f6, 0xd0e6, /*0x98-0x9f*/ 0x898d, 0x898e, 0x898f, 0x8990, 0x8991, 0x8992, 0x8993, 0x8994, /*0xa0-0xa7*/ 0xc4ab, 0xb6d5, 0x8995, 0x8996, 0x8997, 0x8998, 0x8999, 0x899a, /*0xa8-0xaf*/ 0x899b, 0x899c, 0x899d, 0x899e, 0x899f, 0x89a0, 0x89a1, 0x89a2, /*0xb0-0xb7*/ 0x89a3, 0x89a4, 0x89a5, 0x89a6, 0xdbd4, 0x89a7, 0x89a8, 0x89a9, /*0xb8-0xbf*/ 0x89aa, 0xb1da, 0x89ab, 0x89ac, 0x89ad, 0xdbd5, 0x89ae, 0x89af, /*0xc0-0xc7*/ 0x89b0, 0x89b1, 0x89b2, 0x89b3, 0x89b4, 0x89b5, 0x89b6, 0x89b7, /*0xc8-0xcf*/ 0x89b8, 0xdbd6, 0x89b9, 0x89ba, 0x89bb, 0xbabe, 0x89bc, 0x89bd, /*0xd0-0xd7*/ 0x89be, 0x89bf, 0x89c0, 0x89c1, 0x89c2, 0x89c3, 0x89c4, 0x89c5, /*0xd8-0xdf*/ 0x89c6, 0x89c7, 0x89c8, 0x89c9, 0xc8c0, 0x89ca, 0x89cb, 0x89cc, /*0xe0-0xe7*/ 0x89cd, 0x89ce, 0x89cf, 0xcabf, 0xc8c9, 0x89d0, 0xd7b3, 0x89d1, /*0xe8-0xef*/ 0xc9f9, 0x89d2, 0x89d3, 0xbfc7, 0x89d4, 0x89d5, 0xbaf8, 0x89d6, /*0xf0-0xf7*/ 0x89d7, 0xd2bc, 0x89d8, 0x89d9, 0x89da, 0x89db, 0x89dc, 0x89dd, /*0xf8-0xff*/ /* 0x5900 */ 0x89de, 0x89df, 0xe2ba, 0x89e0, 0xb4a6, 0x89e1, 0x89e2, 0xb1b8, /*0x00-0x07*/ 0x89e3, 0x89e4, 0x89e5, 0x89e6, 0x89e7, 0xb8b4, 0x89e8, 0xcfc4, /*0x08-0x0f*/ 0x89e9, 0x89ea, 0x89eb, 0x89ec, 0xd9e7, 0xcfa6, 0xcde2, 0x89ed, /*0x10-0x17*/ 0x89ee, 0xd9ed, 0xb6e0, 0x89ef, 0xd2b9, 0x89f0, 0x89f1, 0xb9bb, /*0x18-0x1f*/ 0x89f2, 0x89f3, 0x89f4, 0x89f5, 0xe2b9, 0xe2b7, 0x89f6, 0xb4f3, /*0x20-0x27*/ 0x89f7, 0xccec, 0xccab, 0xb7f2, 0x89f8, 0xd8b2, 0xd1eb, 0xbabb, /*0x28-0x2f*/ 0x89f9, 0xcaa7, 0x89fa, 0x89fb, 0xcdb7, 0x89fc, 0x89fd, 0xd2c4, /*0x30-0x37*/ 0xbfe4, 0xbcd0, 0xb6e1, 0x89fe, 0xdec5, 0x8a40, 0x8a41, 0x8a42, /*0x38-0x3f*/ 0x8a43, 0xdec6, 0xdbbc, 0x8a44, 0xd1d9, 0x8a45, 0x8a46, 0xc6e6, /*0x40-0x47*/ 0xc4ce, 0xb7ee, 0x8a47, 0xb7dc, 0x8a48, 0x8a49, 0xbffc, 0xd7e0, /*0x48-0x4f*/ 0x8a4a, 0xc6f5, 0x8a4b, 0x8a4c, 0xb1bc, 0xdec8, 0xbdb1, 0xccd7, /*0x50-0x57*/ 0xdeca, 0x8a4d, 0xdec9, 0x8a4e, 0x8a4f, 0x8a50, 0x8a51, 0x8a52, /*0x58-0x5f*/ 0xb5ec, 0x8a53, 0xc9dd, 0x8a54, 0x8a55, 0xb0c2, 0x8a56, 0x8a57, /*0x60-0x67*/ 0x8a58, 0x8a59, 0x8a5a, 0x8a5b, 0x8a5c, 0x8a5d, 0x8a5e, 0x8a5f, /*0x68-0x6f*/ 0x8a60, 0x8a61, 0x8a62, 0xc5ae, 0xc5ab, 0x8a63, 0xc4cc, 0x8a64, /*0x70-0x77*/ 0xbce9, 0xcbfd, 0x8a65, 0x8a66, 0x8a67, 0xbac3, 0x8a68, 0x8a69, /*0x78-0x7f*/ 0x8a6a, 0xe5f9, 0xc8e7, 0xe5fa, 0xcdfd, 0x8a6b, 0xd7b1, 0xb8be, /*0x80-0x87*/ 0xc2e8, 0x8a6c, 0xc8d1, 0x8a6d, 0x8a6e, 0xe5fb, 0x8a6f, 0x8a70, /*0x88-0x8f*/ 0x8a71, 0x8a72, 0xb6ca, 0xbccb, 0x8a73, 0x8a74, 0xd1fd, 0xe6a1, /*0x90-0x97*/ 0x8a75, 0xc3ee, 0x8a76, 0x8a77, 0x8a78, 0x8a79, 0xe6a4, 0x8a7a, /*0x98-0x9f*/ 0x8a7b, 0x8a7c, 0x8a7d, 0xe5fe, 0xe6a5, 0xcdd7, 0x8a7e, 0x8a80, /*0xa0-0xa7*/ 0xb7c1, 0xe5fc, 0xe5fd, 0xe6a3, 0x8a81, 0x8a82, 0xc4dd, 0xe6a8, /*0xa8-0xaf*/ 0x8a83, 0x8a84, 0xe6a7, 0x8a85, 0x8a86, 0x8a87, 0x8a88, 0x8a89, /*0xb0-0xb7*/ 0x8a8a, 0xc3c3, 0x8a8b, 0xc6de, 0x8a8c, 0x8a8d, 0xe6aa, 0x8a8e, /*0xb8-0xbf*/ 0x8a8f, 0x8a90, 0x8a91, 0x8a92, 0x8a93, 0x8a94, 0xc4b7, 0x8a95, /*0xc0-0xc7*/ 0x8a96, 0x8a97, 0xe6a2, 0xcabc, 0x8a98, 0x8a99, 0x8a9a, 0x8a9b, /*0xc8-0xcf*/ 0xbde3, 0xb9c3, 0xe6a6, 0xd0d5, 0xceaf, 0x8a9c, 0x8a9d, 0xe6a9, /*0xd0-0xd7*/ 0xe6b0, 0x8a9e, 0xd2a6, 0x8a9f, 0xbdaa, 0xe6ad, 0x8aa0, 0x8aa1, /*0xd8-0xdf*/ 0x8aa2, 0x8aa3, 0x8aa4, 0xe6af, 0x8aa5, 0xc0d1, 0x8aa6, 0x8aa7, /*0xe0-0xe7*/ 0xd2cc, 0x8aa8, 0x8aa9, 0x8aaa, 0xbca7, 0x8aab, 0x8aac, 0x8aad, /*0xe8-0xef*/ 0x8aae, 0x8aaf, 0x8ab0, 0x8ab1, 0x8ab2, 0x8ab3, 0x8ab4, 0x8ab5, /*0xf0-0xf7*/ 0x8ab6, 0xe6b1, 0x8ab7, 0xd2f6, 0x8ab8, 0x8ab9, 0x8aba, 0xd7cb, /*0xf8-0xff*/ /* 0x5a00 */ 0x8abb, 0xcdfe, 0x8abc, 0xcdde, 0xc2a6, 0xe6ab, 0xe6ac, 0xbdbf, /*0x00-0x07*/ 0xe6ae, 0xe6b3, 0x8abd, 0x8abe, 0xe6b2, 0x8abf, 0x8ac0, 0x8ac1, /*0x08-0x0f*/ 0x8ac2, 0xe6b6, 0x8ac3, 0xe6b8, 0x8ac4, 0x8ac5, 0x8ac6, 0x8ac7, /*0x10-0x17*/ 0xc4ef, 0x8ac8, 0x8ac9, 0x8aca, 0xc4c8, 0x8acb, 0x8acc, 0xbeea, /*0x18-0x1f*/ 0xc9ef, 0x8acd, 0x8ace, 0xe6b7, 0x8acf, 0xb6f0, 0x8ad0, 0x8ad1, /*0x20-0x27*/ 0x8ad2, 0xc3e4, 0x8ad3, 0x8ad4, 0x8ad5, 0x8ad6, 0x8ad7, 0x8ad8, /*0x28-0x2f*/ 0x8ad9, 0xd3e9, 0xe6b4, 0x8ada, 0xe6b5, 0x8adb, 0xc8a2, 0x8adc, /*0x30-0x37*/ 0x8add, 0x8ade, 0x8adf, 0x8ae0, 0xe6bd, 0x8ae1, 0x8ae2, 0x8ae3, /*0x38-0x3f*/ 0xe6b9, 0x8ae4, 0x8ae5, 0x8ae6, 0x8ae7, 0x8ae8, 0xc6c5, 0x8ae9, /*0x40-0x47*/ 0x8aea, 0xcdf1, 0xe6bb, 0x8aeb, 0x8aec, 0x8aed, 0x8aee, 0x8aef, /*0x48-0x4f*/ 0x8af0, 0x8af1, 0x8af2, 0x8af3, 0x8af4, 0xe6bc, 0x8af5, 0x8af6, /*0x50-0x57*/ 0x8af7, 0x8af8, 0xbbe9, 0x8af9, 0x8afa, 0x8afb, 0x8afc, 0x8afd, /*0x58-0x5f*/ 0x8afe, 0x8b40, 0xe6be, 0x8b41, 0x8b42, 0x8b43, 0x8b44, 0xe6ba, /*0x60-0x67*/ 0x8b45, 0x8b46, 0xc0b7, 0x8b47, 0x8b48, 0x8b49, 0x8b4a, 0x8b4b, /*0x68-0x6f*/ 0x8b4c, 0x8b4d, 0x8b4e, 0x8b4f, 0xd3a4, 0xe6bf, 0xc9f4, 0xe6c3, /*0x70-0x77*/ 0x8b50, 0x8b51, 0xe6c4, 0x8b52, 0x8b53, 0x8b54, 0x8b55, 0xd0f6, /*0x78-0x7f*/ 0x8b56, 0x8b57, 0x8b58, 0x8b59, 0x8b5a, 0x8b5b, 0x8b5c, 0x8b5d, /*0x80-0x87*/ 0x8b5e, 0x8b5f, 0x8b60, 0x8b61, 0x8b62, 0x8b63, 0x8b64, 0x8b65, /*0x88-0x8f*/ 0x8b66, 0x8b67, 0xc3bd, 0x8b68, 0x8b69, 0x8b6a, 0x8b6b, 0x8b6c, /*0x90-0x97*/ 0x8b6d, 0x8b6e, 0xc3c4, 0xe6c2, 0x8b6f, 0x8b70, 0x8b71, 0x8b72, /*0x98-0x9f*/ 0x8b73, 0x8b74, 0x8b75, 0x8b76, 0x8b77, 0x8b78, 0x8b79, 0x8b7a, /*0xa0-0xa7*/ 0x8b7b, 0x8b7c, 0xe6c1, 0x8b7d, 0x8b7e, 0x8b80, 0x8b81, 0x8b82, /*0xa8-0xaf*/ 0x8b83, 0x8b84, 0xe6c7, 0xcfb1, 0x8b85, 0xebf4, 0x8b86, 0x8b87, /*0xb0-0xb7*/ 0xe6ca, 0x8b88, 0x8b89, 0x8b8a, 0x8b8b, 0x8b8c, 0xe6c5, 0x8b8d, /*0xb8-0xbf*/ 0x8b8e, 0xbcde, 0xc9a9, 0x8b8f, 0x8b90, 0x8b91, 0x8b92, 0x8b93, /*0xc0-0xc7*/ 0x8b94, 0xbcb5, 0x8b95, 0x8b96, 0xcfd3, 0x8b97, 0x8b98, 0x8b99, /*0xc8-0xcf*/ 0x8b9a, 0x8b9b, 0xe6c8, 0x8b9c, 0xe6c9, 0x8b9d, 0xe6ce, 0x8b9e, /*0xd0-0xd7*/ 0xe6d0, 0x8b9f, 0x8ba0, 0x8ba1, 0xe6d1, 0x8ba2, 0x8ba3, 0x8ba4, /*0xd8-0xdf*/ 0xe6cb, 0xb5d5, 0x8ba5, 0xe6cc, 0x8ba6, 0x8ba7, 0xe6cf, 0x8ba8, /*0xe0-0xe7*/ 0x8ba9, 0xc4db, 0x8baa, 0xe6c6, 0x8bab, 0x8bac, 0x8bad, 0x8bae, /*0xe8-0xef*/ 0x8baf, 0xe6cd, 0x8bb0, 0x8bb1, 0x8bb2, 0x8bb3, 0x8bb4, 0x8bb5, /*0xf0-0xf7*/ 0x8bb6, 0x8bb7, 0x8bb8, 0x8bb9, 0x8bba, 0x8bbb, 0x8bbc, 0x8bbd, /*0xf8-0xff*/ /* 0x5b00 */ 0x8bbe, 0x8bbf, 0x8bc0, 0x8bc1, 0x8bc2, 0x8bc3, 0x8bc4, 0x8bc5, /*0x00-0x07*/ 0x8bc6, 0xe6d2, 0x8bc7, 0x8bc8, 0x8bc9, 0x8bca, 0x8bcb, 0x8bcc, /*0x08-0x0f*/ 0x8bcd, 0x8bce, 0x8bcf, 0x8bd0, 0x8bd1, 0x8bd2, 0xe6d4, 0xe6d3, /*0x10-0x17*/ 0x8bd3, 0x8bd4, 0x8bd5, 0x8bd6, 0x8bd7, 0x8bd8, 0x8bd9, 0x8bda, /*0x18-0x1f*/ 0x8bdb, 0x8bdc, 0x8bdd, 0x8bde, 0x8bdf, 0x8be0, 0x8be1, 0x8be2, /*0x20-0x27*/ 0x8be3, 0x8be4, 0x8be5, 0x8be6, 0x8be7, 0x8be8, 0x8be9, 0x8bea, /*0x28-0x2f*/ 0x8beb, 0x8bec, 0xe6d5, 0x8bed, 0xd9f8, 0x8bee, 0x8bef, 0xe6d6, /*0x30-0x37*/ 0x8bf0, 0x8bf1, 0x8bf2, 0x8bf3, 0x8bf4, 0x8bf5, 0x8bf6, 0x8bf7, /*0x38-0x3f*/ 0xe6d7, 0x8bf8, 0x8bf9, 0x8bfa, 0x8bfb, 0x8bfc, 0x8bfd, 0x8bfe, /*0x40-0x47*/ 0x8c40, 0x8c41, 0x8c42, 0x8c43, 0x8c44, 0x8c45, 0x8c46, 0x8c47, /*0x48-0x4f*/ 0xd7d3, 0xe6dd, 0x8c48, 0xe6de, 0xbfd7, 0xd4d0, 0x8c49, 0xd7d6, /*0x50-0x57*/ 0xb4e6, 0xcbef, 0xe6da, 0xd8c3, 0xd7ce, 0xd0a2, 0x8c4a, 0xc3cf, /*0x58-0x5f*/ 0x8c4b, 0x8c4c, 0xe6df, 0xbcbe, 0xb9c2, 0xe6db, 0xd1a7, 0x8c4d, /*0x60-0x67*/ 0x8c4e, 0xbaa2, 0xc2cf, 0x8c4f, 0xd8ab, 0x8c50, 0x8c51, 0x8c52, /*0x68-0x6f*/ 0xcaeb, 0xe5ee, 0x8c53, 0xe6dc, 0x8c54, 0xb7f5, 0x8c55, 0x8c56, /*0x70-0x77*/ 0x8c57, 0x8c58, 0xc8e6, 0x8c59, 0x8c5a, 0xc4f5, 0x8c5b, 0x8c5c, /*0x78-0x7f*/ 0xe5b2, 0xc4fe, 0x8c5d, 0xcbfc, 0xe5b3, 0xd5ac, 0x8c5e, 0xd3ee, /*0x80-0x87*/ 0xcad8, 0xb0b2, 0x8c5f, 0xcbce, 0xcdea, 0x8c60, 0x8c61, 0xbaea, /*0x88-0x8f*/ 0x8c62, 0x8c63, 0x8c64, 0xe5b5, 0x8c65, 0xe5b4, 0x8c66, 0xd7da, /*0x90-0x97*/ 0xb9d9, 0xd6e6, 0xb6a8, 0xcdf0, 0xd2cb, 0xb1a6, 0xcab5, 0x8c67, /*0x98-0x9f*/ 0xb3e8, 0xc9f3, 0xbfcd, 0xd0fb, 0xcad2, 0xe5b6, 0xbbc2, 0x8c68, /*0xa0-0xa7*/ 0x8c69, 0x8c6a, 0xcfdc, 0xb9ac, 0x8c6b, 0x8c6c, 0x8c6d, 0x8c6e, /*0xa8-0xaf*/ 0xd4d7, 0x8c6f, 0x8c70, 0xbaa6, 0xd1e7, 0xcffc, 0xbcd2, 0x8c71, /*0xb0-0xb7*/ 0xe5b7, 0xc8dd, 0x8c72, 0x8c73, 0x8c74, 0xbfed, 0xb1f6, 0xcbde, /*0xb8-0xbf*/ 0x8c75, 0x8c76, 0xbcc5, 0x8c77, 0xbcc4, 0xd2fa, 0xc3dc, 0xbfdc, /*0xc0-0xc7*/ 0x8c78, 0x8c79, 0x8c7a, 0x8c7b, 0xb8bb, 0x8c7c, 0x8c7d, 0x8c7e, /*0xc8-0xcf*/ 0xc3c2, 0x8c80, 0xbaae, 0xd4a2, 0x8c81, 0x8c82, 0x8c83, 0x8c84, /*0xd0-0xd7*/ 0x8c85, 0x8c86, 0x8c87, 0x8c88, 0x8c89, 0xc7de, 0xc4af, 0xb2ec, /*0xd8-0xdf*/ 0x8c8a, 0xb9d1, 0x8c8b, 0x8c8c, 0xe5bb, 0xc1c8, 0x8c8d, 0x8c8e, /*0xe0-0xe7*/ 0xd5af, 0x8c8f, 0x8c90, 0x8c91, 0x8c92, 0x8c93, 0xe5bc, 0x8c94, /*0xe8-0xef*/ 0xe5be, 0x8c95, 0x8c96, 0x8c97, 0x8c98, 0x8c99, 0x8c9a, 0x8c9b, /*0xf0-0xf7*/ 0xb4e7, 0xb6d4, 0xcbc2, 0xd1b0, 0xb5bc, 0x8c9c, 0x8c9d, 0xcad9, /*0xf8-0xff*/ /* 0x5c00 */ 0x8c9e, 0xb7e2, 0x8c9f, 0x8ca0, 0xc9e4, 0x8ca1, 0xbdab, 0x8ca2, /*0x00-0x07*/ 0x8ca3, 0xcebe, 0xd7f0, 0x8ca4, 0x8ca5, 0x8ca6, 0x8ca7, 0xd0a1, /*0x08-0x0f*/ 0x8ca8, 0xc9d9, 0x8ca9, 0x8caa, 0xb6fb, 0xe6d8, 0xbce2, 0x8cab, /*0x10-0x17*/ 0xb3be, 0x8cac, 0xc9d0, 0x8cad, 0xe6d9, 0xb3a2, 0x8cae, 0x8caf, /*0x18-0x1f*/ 0x8cb0, 0x8cb1, 0xdecc, 0x8cb2, 0xd3c8, 0xdecd, 0x8cb3, 0xd2a2, /*0x20-0x27*/ 0x8cb4, 0x8cb5, 0x8cb6, 0x8cb7, 0xdece, 0x8cb8, 0x8cb9, 0x8cba, /*0x28-0x2f*/ 0x8cbb, 0xbecd, 0x8cbc, 0x8cbd, 0xdecf, 0x8cbe, 0x8cbf, 0x8cc0, /*0x30-0x37*/ 0xcaac, 0xd2fc, 0xb3df, 0xe5ea, 0xc4e1, 0xbea1, 0xceb2, 0xc4f2, /*0x38-0x3f*/ 0xbed6, 0xc6a8, 0xb2e3, 0x8cc1, 0x8cc2, 0xbed3, 0x8cc3, 0x8cc4, /*0x40-0x47*/ 0xc7fc, 0xcceb, 0xbdec, 0xcedd, 0x8cc5, 0x8cc6, 0xcaba, 0xc6c1, /*0x48-0x4f*/ 0xe5ec, 0xd0bc, 0x8cc7, 0x8cc8, 0x8cc9, 0xd5b9, 0x8cca, 0x8ccb, /*0x50-0x57*/ 0x8ccc, 0xe5ed, 0x8ccd, 0x8cce, 0x8ccf, 0x8cd0, 0xcaf4, 0x8cd1, /*0x58-0x5f*/ 0xcdc0, 0xc2c5, 0x8cd2, 0xe5ef, 0x8cd3, 0xc2c4, 0xe5f0, 0x8cd4, /*0x60-0x67*/ 0x8cd5, 0x8cd6, 0x8cd7, 0x8cd8, 0x8cd9, 0x8cda, 0xe5f8, 0xcdcd, /*0x68-0x6f*/ 0x8cdb, 0xc9bd, 0x8cdc, 0x8cdd, 0x8cde, 0x8cdf, 0x8ce0, 0x8ce1, /*0x70-0x77*/ 0x8ce2, 0xd2d9, 0xe1a8, 0x8ce3, 0x8ce4, 0x8ce5, 0x8ce6, 0xd3ec, /*0x78-0x7f*/ 0x8ce7, 0xcbea, 0xc6f1, 0x8ce8, 0x8ce9, 0x8cea, 0x8ceb, 0x8cec, /*0x80-0x87*/ 0xe1ac, 0x8ced, 0x8cee, 0x8cef, 0xe1a7, 0xe1a9, 0x8cf0, 0x8cf1, /*0x88-0x8f*/ 0xe1aa, 0xe1af, 0x8cf2, 0x8cf3, 0xb2ed, 0x8cf4, 0xe1ab, 0xb8da, /*0x90-0x97*/ 0xe1ad, 0xe1ae, 0xe1b0, 0xb5ba, 0xe1b1, 0x8cf5, 0x8cf6, 0x8cf7, /*0x98-0x9f*/ 0x8cf8, 0x8cf9, 0xe1b3, 0xe1b8, 0x8cfa, 0x8cfb, 0x8cfc, 0x8cfd, /*0xa0-0xa7*/ 0x8cfe, 0xd1d2, 0x8d40, 0xe1b6, 0xe1b5, 0xc1eb, 0x8d41, 0x8d42, /*0xa8-0xaf*/ 0x8d43, 0xe1b7, 0x8d44, 0xd4c0, 0x8d45, 0xe1b2, 0x8d46, 0xe1ba, /*0xb0-0xb7*/ 0xb0b6, 0x8d47, 0x8d48, 0x8d49, 0x8d4a, 0xe1b4, 0x8d4b, 0xbff9, /*0xb8-0xbf*/ 0x8d4c, 0xe1b9, 0x8d4d, 0x8d4e, 0xe1bb, 0x8d4f, 0x8d50, 0x8d51, /*0xc0-0xc7*/ 0x8d52, 0x8d53, 0x8d54, 0xe1be, 0x8d55, 0x8d56, 0x8d57, 0x8d58, /*0xc8-0xcf*/ 0x8d59, 0x8d5a, 0xe1bc, 0x8d5b, 0x8d5c, 0x8d5d, 0x8d5e, 0x8d5f, /*0xd0-0xd7*/ 0x8d60, 0xd6c5, 0x8d61, 0x8d62, 0x8d63, 0x8d64, 0x8d65, 0x8d66, /*0xd8-0xdf*/ 0x8d67, 0xcfbf, 0x8d68, 0x8d69, 0xe1bd, 0xe1bf, 0xc2cd, 0x8d6a, /*0xe0-0xe7*/ 0xb6eb, 0x8d6b, 0xd3f8, 0x8d6c, 0x8d6d, 0xc7cd, 0x8d6e, 0x8d6f, /*0xe8-0xef*/ 0xb7e5, 0x8d70, 0x8d71, 0x8d72, 0x8d73, 0x8d74, 0x8d75, 0x8d76, /*0xf0-0xf7*/ 0x8d77, 0x8d78, 0x8d79, 0xbefe, 0x8d7a, 0x8d7b, 0x8d7c, 0x8d7d, /*0xf8-0xff*/ /* 0x5d00 */ 0x8d7e, 0x8d80, 0xe1c0, 0xe1c1, 0x8d81, 0x8d82, 0xe1c7, 0xb3e7, /*0x00-0x07*/ 0x8d83, 0x8d84, 0x8d85, 0x8d86, 0x8d87, 0x8d88, 0xc6e9, 0x8d89, /*0x08-0x0f*/ 0x8d8a, 0x8d8b, 0x8d8c, 0x8d8d, 0xb4de, 0x8d8e, 0xd1c2, 0x8d8f, /*0x10-0x17*/ 0x8d90, 0x8d91, 0x8d92, 0xe1c8, 0x8d93, 0x8d94, 0xe1c6, 0x8d95, /*0x18-0x1f*/ 0x8d96, 0x8d97, 0x8d98, 0x8d99, 0xe1c5, 0x8d9a, 0xe1c3, 0xe1c2, /*0x20-0x27*/ 0x8d9b, 0xb1c0, 0x8d9c, 0x8d9d, 0x8d9e, 0xd5b8, 0xe1c4, 0x8d9f, /*0x28-0x2f*/ 0x8da0, 0x8da1, 0x8da2, 0x8da3, 0xe1cb, 0x8da4, 0x8da5, 0x8da6, /*0x30-0x37*/ 0x8da7, 0x8da8, 0x8da9, 0x8daa, 0x8dab, 0xe1cc, 0xe1ca, 0x8dac, /*0x38-0x3f*/ 0x8dad, 0x8dae, 0x8daf, 0x8db0, 0x8db1, 0x8db2, 0x8db3, 0xeffa, /*0x40-0x47*/ 0x8db4, 0x8db5, 0xe1d3, 0xe1d2, 0xc7b6, 0x8db6, 0x8db7, 0x8db8, /*0x48-0x4f*/ 0x8db9, 0x8dba, 0x8dbb, 0x8dbc, 0x8dbd, 0x8dbe, 0x8dbf, 0x8dc0, /*0x50-0x57*/ 0xe1c9, 0x8dc1, 0x8dc2, 0xe1ce, 0x8dc3, 0xe1d0, 0x8dc4, 0x8dc5, /*0x58-0x5f*/ 0x8dc6, 0x8dc7, 0x8dc8, 0x8dc9, 0x8dca, 0x8dcb, 0x8dcc, 0x8dcd, /*0x60-0x67*/ 0x8dce, 0xe1d4, 0x8dcf, 0xe1d1, 0xe1cd, 0x8dd0, 0x8dd1, 0xe1cf, /*0x68-0x6f*/ 0x8dd2, 0x8dd3, 0x8dd4, 0x8dd5, 0xe1d5, 0x8dd6, 0x8dd7, 0x8dd8, /*0x70-0x77*/ 0x8dd9, 0x8dda, 0x8ddb, 0x8ddc, 0x8ddd, 0x8dde, 0x8ddf, 0x8de0, /*0x78-0x7f*/ 0x8de1, 0x8de2, 0xe1d6, 0x8de3, 0x8de4, 0x8de5, 0x8de6, 0x8de7, /*0x80-0x87*/ 0x8de8, 0x8de9, 0x8dea, 0x8deb, 0x8dec, 0x8ded, 0x8dee, 0x8def, /*0x88-0x8f*/ 0x8df0, 0x8df1, 0x8df2, 0x8df3, 0x8df4, 0x8df5, 0x8df6, 0x8df7, /*0x90-0x97*/ 0x8df8, 0xe1d7, 0x8df9, 0x8dfa, 0x8dfb, 0xe1d8, 0x8dfc, 0x8dfd, /*0x98-0x9f*/ 0x8dfe, 0x8e40, 0x8e41, 0x8e42, 0x8e43, 0x8e44, 0x8e45, 0x8e46, /*0xa0-0xa7*/ 0x8e47, 0x8e48, 0x8e49, 0x8e4a, 0x8e4b, 0x8e4c, 0x8e4d, 0x8e4e, /*0xa8-0xaf*/ 0x8e4f, 0x8e50, 0x8e51, 0x8e52, 0x8e53, 0x8e54, 0x8e55, 0xe1da, /*0xb0-0xb7*/ 0x8e56, 0x8e57, 0x8e58, 0x8e59, 0x8e5a, 0x8e5b, 0x8e5c, 0x8e5d, /*0xb8-0xbf*/ 0x8e5e, 0x8e5f, 0x8e60, 0x8e61, 0x8e62, 0xe1db, 0x8e63, 0x8e64, /*0xc0-0xc7*/ 0x8e65, 0x8e66, 0x8e67, 0x8e68, 0x8e69, 0xcea1, 0x8e6a, 0x8e6b, /*0xc8-0xcf*/ 0x8e6c, 0x8e6d, 0x8e6e, 0x8e6f, 0x8e70, 0x8e71, 0x8e72, 0x8e73, /*0xd0-0xd7*/ 0x8e74, 0x8e75, 0x8e76, 0xe7dd, 0x8e77, 0xb4a8, 0xd6dd, 0x8e78, /*0xd8-0xdf*/ 0x8e79, 0xd1b2, 0xb3b2, 0x8e7a, 0x8e7b, 0xb9a4, 0xd7f3, 0xc7c9, /*0xe0-0xe7*/ 0xbede, 0xb9ae, 0x8e7c, 0xced7, 0x8e7d, 0x8e7e, 0xb2ee, 0xdbcf, /*0xe8-0xef*/ 0x8e80, 0xbcba, 0xd2d1, 0xcbc8, 0xb0cd, 0x8e81, 0x8e82, 0xcfef, /*0xf0-0xf7*/ 0x8e83, 0x8e84, 0x8e85, 0x8e86, 0x8e87, 0xd9e3, 0xbded, 0x8e88, /*0xf8-0xff*/ /* 0x5e00 */ 0x8e89, 0xb1d2, 0xcad0, 0xb2bc, 0x8e8a, 0xcba7, 0xb7ab, 0x8e8b, /*0x00-0x07*/ 0xcaa6, 0x8e8c, 0x8e8d, 0x8e8e, 0xcfa3, 0x8e8f, 0x8e90, 0xe0f8, /*0x08-0x0f*/ 0xd5ca, 0xe0fb, 0x8e91, 0x8e92, 0xe0fa, 0xc5c1, 0xccfb, 0x8e93, /*0x10-0x17*/ 0xc1b1, 0xe0f9, 0xd6e3, 0xb2af, 0xd6c4, 0xb5db, 0x8e94, 0x8e95, /*0x18-0x1f*/ 0x8e96, 0x8e97, 0x8e98, 0x8e99, 0x8e9a, 0x8e9b, 0xb4f8, 0xd6a1, /*0x20-0x27*/ 0x8e9c, 0x8e9d, 0x8e9e, 0x8e9f, 0x8ea0, 0xcfaf, 0xb0ef, 0x8ea1, /*0x28-0x2f*/ 0x8ea2, 0xe0fc, 0x8ea3, 0x8ea4, 0x8ea5, 0x8ea6, 0x8ea7, 0xe1a1, /*0x30-0x37*/ 0xb3a3, 0x8ea8, 0x8ea9, 0xe0fd, 0xe0fe, 0xc3b1, 0x8eaa, 0x8eab, /*0x38-0x3f*/ 0x8eac, 0x8ead, 0xc3dd, 0x8eae, 0xe1a2, 0xb7f9, 0x8eaf, 0x8eb0, /*0x40-0x47*/ 0x8eb1, 0x8eb2, 0x8eb3, 0x8eb4, 0xbbcf, 0x8eb5, 0x8eb6, 0x8eb7, /*0x48-0x4f*/ 0x8eb8, 0x8eb9, 0x8eba, 0x8ebb, 0xe1a3, 0xc4bb, 0x8ebc, 0x8ebd, /*0x50-0x57*/ 0x8ebe, 0x8ebf, 0x8ec0, 0xe1a4, 0x8ec1, 0x8ec2, 0xe1a5, 0x8ec3, /*0x58-0x5f*/ 0x8ec4, 0xe1a6, 0xb4b1, 0x8ec5, 0x8ec6, 0x8ec7, 0x8ec8, 0x8ec9, /*0x60-0x67*/ 0x8eca, 0x8ecb, 0x8ecc, 0x8ecd, 0x8ece, 0x8ecf, 0x8ed0, 0x8ed1, /*0x68-0x6f*/ 0x8ed2, 0x8ed3, 0xb8c9, 0xc6bd, 0xc4ea, 0x8ed4, 0xb2a2, 0x8ed5, /*0x70-0x77*/ 0xd0d2, 0x8ed6, 0xe7db, 0xbbc3, 0xd3d7, 0xd3c4, 0x8ed7, 0xb9e3, /*0x78-0x7f*/ 0xe2cf, 0x8ed8, 0x8ed9, 0x8eda, 0xd7af, 0x8edb, 0xc7ec, 0xb1d3, /*0x80-0x87*/ 0x8edc, 0x8edd, 0xb4b2, 0xe2d1, 0x8ede, 0x8edf, 0x8ee0, 0xd0f2, /*0x88-0x8f*/ 0xc2ae, 0xe2d0, 0x8ee1, 0xbfe2, 0xd3a6, 0xb5d7, 0xe2d2, 0xb5ea, /*0x90-0x97*/ 0x8ee2, 0xc3ed, 0xb8fd, 0x8ee3, 0xb8ae, 0x8ee4, 0xc5d3, 0xb7cf, /*0x98-0x9f*/ 0xe2d4, 0x8ee5, 0x8ee6, 0x8ee7, 0x8ee8, 0xe2d3, 0xb6c8, 0xd7f9, /*0xa0-0xa7*/ 0x8ee9, 0x8eea, 0x8eeb, 0x8eec, 0x8eed, 0xcda5, 0x8eee, 0x8eef, /*0xa8-0xaf*/ 0x8ef0, 0x8ef1, 0x8ef2, 0xe2d8, 0x8ef3, 0xe2d6, 0xcafc, 0xbfb5, /*0xb0-0xb7*/ 0xd3b9, 0xe2d5, 0x8ef4, 0x8ef5, 0x8ef6, 0x8ef7, 0xe2d7, 0x8ef8, /*0xb8-0xbf*/ 0x8ef9, 0x8efa, 0x8efb, 0x8efc, 0x8efd, 0x8efe, 0x8f40, 0x8f41, /*0xc0-0xc7*/ 0x8f42, 0xc1ae, 0xc0c8, 0x8f43, 0x8f44, 0x8f45, 0x8f46, 0x8f47, /*0xc8-0xcf*/ 0x8f48, 0xe2db, 0xe2da, 0xc0aa, 0x8f49, 0x8f4a, 0xc1ce, 0x8f4b, /*0xd0-0xd7*/ 0x8f4c, 0x8f4d, 0x8f4e, 0xe2dc, 0x8f4f, 0x8f50, 0x8f51, 0x8f52, /*0xd8-0xdf*/ 0x8f53, 0x8f54, 0x8f55, 0x8f56, 0x8f57, 0x8f58, 0x8f59, 0x8f5a, /*0xe0-0xe7*/ 0xe2dd, 0x8f5b, 0xe2de, 0x8f5c, 0x8f5d, 0x8f5e, 0x8f5f, 0x8f60, /*0xe8-0xef*/ 0x8f61, 0x8f62, 0x8f63, 0x8f64, 0xdbc8, 0x8f65, 0xd1d3, 0xcda2, /*0xf0-0xf7*/ 0x8f66, 0x8f67, 0xbda8, 0x8f68, 0x8f69, 0x8f6a, 0xdec3, 0xd8a5, /*0xf8-0xff*/ /* 0x5f00 */ 0xbfaa, 0xdbcd, 0xd2ec, 0xc6fa, 0xc5aa, 0x8f6b, 0x8f6c, 0x8f6d, /*0x00-0x07*/ 0xdec4, 0x8f6e, 0xb1d7, 0xdfae, 0x8f6f, 0x8f70, 0x8f71, 0xcabd, /*0x08-0x0f*/ 0x8f72, 0xdfb1, 0x8f73, 0xb9ad, 0x8f74, 0xd2fd, 0x8f75, 0xb8a5, /*0x10-0x17*/ 0xbaeb, 0x8f76, 0x8f77, 0xb3da, 0x8f78, 0x8f79, 0x8f7a, 0xb5dc, /*0x18-0x1f*/ 0xd5c5, 0x8f7b, 0x8f7c, 0x8f7d, 0x8f7e, 0xc3d6, 0xcfd2, 0xbba1, /*0x20-0x27*/ 0x8f80, 0xe5f3, 0xe5f2, 0x8f81, 0x8f82, 0xe5f4, 0x8f83, 0xcde4, /*0x28-0x2f*/ 0x8f84, 0xc8f5, 0x8f85, 0x8f86, 0x8f87, 0x8f88, 0x8f89, 0x8f8a, /*0x30-0x37*/ 0x8f8b, 0xb5af, 0xc7bf, 0x8f8c, 0xe5f6, 0x8f8d, 0x8f8e, 0x8f8f, /*0x38-0x3f*/ 0xecb0, 0x8f90, 0x8f91, 0x8f92, 0x8f93, 0x8f94, 0x8f95, 0x8f96, /*0x40-0x47*/ 0x8f97, 0x8f98, 0x8f99, 0x8f9a, 0x8f9b, 0x8f9c, 0x8f9d, 0x8f9e, /*0x48-0x4f*/ 0xe5e6, 0x8f9f, 0xb9e9, 0xb5b1, 0x8fa0, 0xc2bc, 0xe5e8, 0xe5e7, /*0x50-0x57*/ 0xe5e9, 0x8fa1, 0x8fa2, 0x8fa3, 0x8fa4, 0xd2cd, 0x8fa5, 0x8fa6, /*0x58-0x5f*/ 0x8fa7, 0xe1ea, 0xd0ce, 0x8fa8, 0xcdae, 0x8fa9, 0xd1e5, 0x8faa, /*0x60-0x67*/ 0x8fab, 0xb2ca, 0xb1eb, 0x8fac, 0xb1f2, 0xc5ed, 0x8fad, 0x8fae, /*0x68-0x6f*/ 0xd5c3, 0xd3b0, 0x8faf, 0xe1dc, 0x8fb0, 0x8fb1, 0x8fb2, 0xe1dd, /*0x70-0x77*/ 0x8fb3, 0xd2db, 0x8fb4, 0xb3b9, 0xb1cb, 0x8fb5, 0x8fb6, 0x8fb7, /*0x78-0x7f*/ 0xcdf9, 0xd5f7, 0xe1de, 0x8fb8, 0xbeb6, 0xb4fd, 0x8fb9, 0xe1df, /*0x80-0x87*/ 0xbadc, 0xe1e0, 0xbbb2, 0xc2c9, 0xe1e1, 0x8fba, 0x8fbb, 0x8fbc, /*0x88-0x8f*/ 0xd0ec, 0x8fbd, 0xcdbd, 0x8fbe, 0x8fbf, 0xe1e2, 0x8fc0, 0xb5c3, /*0x90-0x97*/ 0xc5c7, 0xe1e3, 0x8fc1, 0x8fc2, 0xe1e4, 0x8fc3, 0x8fc4, 0x8fc5, /*0x98-0x9f*/ 0x8fc6, 0xd3f9, 0x8fc7, 0x8fc8, 0x8fc9, 0x8fca, 0x8fcb, 0x8fcc, /*0xa0-0xa7*/ 0xe1e5, 0x8fcd, 0xd1ad, 0x8fce, 0x8fcf, 0xe1e6, 0xcea2, 0x8fd0, /*0xa8-0xaf*/ 0x8fd1, 0x8fd2, 0x8fd3, 0x8fd4, 0x8fd5, 0xe1e7, 0x8fd6, 0xb5c2, /*0xb0-0xb7*/ 0x8fd7, 0x8fd8, 0x8fd9, 0x8fda, 0xe1e8, 0xbbd5, 0x8fdb, 0x8fdc, /*0xb8-0xbf*/ 0x8fdd, 0x8fde, 0x8fdf, 0xd0c4, 0xe2e0, 0xb1d8, 0xd2e4, 0x8fe0, /*0xc0-0xc7*/ 0x8fe1, 0xe2e1, 0x8fe2, 0x8fe3, 0xbcc9, 0xc8cc, 0x8fe4, 0xe2e3, /*0xc8-0xcf*/ 0xecfe, 0xecfd, 0xdfaf, 0x8fe5, 0x8fe6, 0x8fe7, 0xe2e2, 0xd6be, /*0xd0-0xd7*/ 0xcdfc, 0xc3a6, 0x8fe8, 0x8fe9, 0x8fea, 0xe3c3, 0x8feb, 0x8fec, /*0xd8-0xdf*/ 0xd6d2, 0xe2e7, 0x8fed, 0x8fee, 0xe2e8, 0x8fef, 0x8ff0, 0xd3c7, /*0xe0-0xe7*/ 0x8ff1, 0x8ff2, 0xe2ec, 0xbfec, 0x8ff3, 0xe2ed, 0xe2e5, 0x8ff4, /*0xe8-0xef*/ 0x8ff5, 0xb3c0, 0x8ff6, 0x8ff7, 0x8ff8, 0xc4ee, 0x8ff9, 0x8ffa, /*0xf0-0xf7*/ 0xe2ee, 0x8ffb, 0x8ffc, 0xd0c3, 0x8ffd, 0xbaf6, 0xe2e9, 0xb7de, /*0xf8-0xff*/ /* 0x6000 */ 0xbbb3, 0xccac, 0xcbcb, 0xe2e4, 0xe2e6, 0xe2ea, 0xe2eb, 0x8ffe, /*0x00-0x07*/ 0x9040, 0x9041, 0xe2f7, 0x9042, 0x9043, 0xe2f4, 0xd4f5, 0xe2f3, /*0x08-0x0f*/ 0x9044, 0x9045, 0xc5ad, 0x9046, 0xd5fa, 0xc5c2, 0xb2c0, 0x9047, /*0x10-0x17*/ 0x9048, 0xe2ef, 0x9049, 0xe2f2, 0xc1af, 0xcbbc, 0x904a, 0x904b, /*0x18-0x1f*/ 0xb5a1, 0xe2f9, 0x904c, 0x904d, 0x904e, 0xbcb1, 0xe2f1, 0xd0d4, /*0x20-0x27*/ 0xd4b9, 0xe2f5, 0xb9d6, 0xe2f6, 0x904f, 0x9050, 0x9051, 0xc7d3, /*0x28-0x2f*/ 0x9052, 0x9053, 0x9054, 0x9055, 0x9056, 0xe2f0, 0x9057, 0x9058, /*0x30-0x37*/ 0x9059, 0x905a, 0x905b, 0xd7dc, 0xeda1, 0x905c, 0x905d, 0xe2f8, /*0x38-0x3f*/ 0x905e, 0xeda5, 0xe2fe, 0xcad1, 0x905f, 0x9060, 0x9061, 0x9062, /*0x40-0x47*/ 0x9063, 0x9064, 0x9065, 0xc1b5, 0x9066, 0xbbd0, 0x9067, 0x9068, /*0x48-0x4f*/ 0xbfd6, 0x9069, 0xbae3, 0x906a, 0x906b, 0xcba1, 0x906c, 0x906d, /*0x50-0x57*/ 0x906e, 0xeda6, 0xeda3, 0x906f, 0x9070, 0xeda2, 0x9071, 0x9072, /*0x58-0x5f*/ 0x9073, 0x9074, 0xbbd6, 0xeda7, 0xd0f4, 0x9075, 0x9076, 0xeda4, /*0x60-0x67*/ 0xbade, 0xb6f7, 0xe3a1, 0xb6b2, 0xccf1, 0xb9a7, 0x9077, 0xcfa2, /*0x68-0x6f*/ 0xc7a1, 0x9078, 0x9079, 0xbfd2, 0x907a, 0x907b, 0xb6f1, 0x907c, /*0x70-0x77*/ 0xe2fa, 0xe2fb, 0xe2fd, 0xe2fc, 0xc4d5, 0xe3a2, 0x907d, 0xd3c1, /*0x78-0x7f*/ 0x907e, 0x9080, 0x9081, 0xe3a7, 0xc7c4, 0x9082, 0x9083, 0x9084, /*0x80-0x87*/ 0x9085, 0xcfa4, 0x9086, 0x9087, 0xe3a9, 0xbab7, 0x9088, 0x9089, /*0x88-0x8f*/ 0x908a, 0x908b, 0xe3a8, 0x908c, 0xbbda, 0x908d, 0xe3a3, 0x908e, /*0x90-0x97*/ 0x908f, 0x9090, 0xe3a4, 0xe3aa, 0x9091, 0xe3a6, 0x9092, 0xcef2, /*0x98-0x9f*/ 0xd3c6, 0x9093, 0x9094, 0xbbbc, 0x9095, 0x9096, 0xd4c3, 0x9097, /*0xa0-0xa7*/ 0xc4fa, 0x9098, 0x9099, 0xeda8, 0xd0fc, 0xe3a5, 0x909a, 0xc3f5, /*0xa8-0xaf*/ 0x909b, 0xe3ad, 0xb1af, 0x909c, 0xe3b2, 0x909d, 0x909e, 0x909f, /*0xb0-0xb7*/ 0xbcc2, 0x90a0, 0x90a1, 0xe3ac, 0xb5bf, 0x90a2, 0x90a3, 0x90a4, /*0xb8-0xbf*/ 0x90a5, 0x90a6, 0x90a7, 0x90a8, 0x90a9, 0xc7e9, 0xe3b0, 0x90aa, /*0xc0-0xc7*/ 0x90ab, 0x90ac, 0xbeaa, 0xcdef, 0x90ad, 0x90ae, 0x90af, 0x90b0, /*0xc8-0xcf*/ 0x90b1, 0xbbf3, 0x90b2, 0x90b3, 0x90b4, 0xcce8, 0x90b5, 0x90b6, /*0xd0-0xd7*/ 0xe3af, 0x90b7, 0xe3b1, 0x90b8, 0xcfa7, 0xe3ae, 0x90b9, 0xcea9, /*0xd8-0xdf*/ 0xbbdd, 0x90ba, 0x90bb, 0x90bc, 0x90bd, 0x90be, 0xb5eb, 0xbee5, /*0xe0-0xe7*/ 0xb2d2, 0xb3cd, 0x90bf, 0xb1b9, 0xe3ab, 0xb2d1, 0xb5ac, 0xb9df, /*0xe8-0xef*/ 0xb6e8, 0x90c0, 0x90c1, 0xcfeb, 0xe3b7, 0x90c2, 0xbbcc, 0x90c3, /*0xf0-0xf7*/ 0x90c4, 0xc8c7, 0xd0ca, 0x90c5, 0x90c6, 0x90c7, 0x90c8, 0x90c9, /*0xf8-0xff*/ /* 0x6100 */ 0xe3b8, 0xb3ee, 0x90ca, 0x90cb, 0x90cc, 0x90cd, 0xeda9, 0x90ce, /*0x00-0x07*/ 0xd3fa, 0xd3e4, 0x90cf, 0x90d0, 0x90d1, 0xedaa, 0xe3b9, 0xd2e2, /*0x08-0x0f*/ 0x90d2, 0x90d3, 0x90d4, 0x90d5, 0x90d6, 0xe3b5, 0x90d7, 0x90d8, /*0x10-0x17*/ 0x90d9, 0x90da, 0xd3de, 0x90db, 0x90dc, 0x90dd, 0x90de, 0xb8d0, /*0x18-0x1f*/ 0xe3b3, 0x90df, 0x90e0, 0xe3b6, 0xb7df, 0x90e1, 0xe3b4, 0xc0a2, /*0x20-0x27*/ 0x90e2, 0x90e3, 0x90e4, 0xe3ba, 0x90e5, 0x90e6, 0x90e7, 0x90e8, /*0x28-0x2f*/ 0x90e9, 0x90ea, 0x90eb, 0x90ec, 0x90ed, 0x90ee, 0x90ef, 0x90f0, /*0x30-0x37*/ 0x90f1, 0x90f2, 0x90f3, 0x90f4, 0x90f5, 0x90f6, 0x90f7, 0xd4b8, /*0x38-0x3f*/ 0x90f8, 0x90f9, 0x90fa, 0x90fb, 0x90fc, 0x90fd, 0x90fe, 0x9140, /*0x40-0x47*/ 0xb4c8, 0x9141, 0xe3bb, 0x9142, 0xbbc5, 0x9143, 0xc9f7, 0x9144, /*0x48-0x4f*/ 0x9145, 0xc9e5, 0x9146, 0x9147, 0x9148, 0xc4bd, 0x9149, 0x914a, /*0x50-0x57*/ 0x914b, 0x914c, 0x914d, 0x914e, 0x914f, 0xedab, 0x9150, 0x9151, /*0x58-0x5f*/ 0x9152, 0x9153, 0xc2fd, 0x9154, 0x9155, 0x9156, 0x9157, 0xbbdb, /*0x60-0x67*/ 0xbfae, 0x9158, 0x9159, 0x915a, 0x915b, 0x915c, 0x915d, 0x915e, /*0x68-0x6f*/ 0xcebf, 0x915f, 0x9160, 0x9161, 0x9162, 0xe3bc, 0x9163, 0xbfb6, /*0x70-0x77*/ 0x9164, 0x9165, 0x9166, 0x9167, 0x9168, 0x9169, 0x916a, 0x916b, /*0x78-0x7f*/ 0x916c, 0x916d, 0x916e, 0x916f, 0x9170, 0x9171, 0x9172, 0x9173, /*0x80-0x87*/ 0x9174, 0x9175, 0x9176, 0xb1ef, 0x9177, 0x9178, 0xd4f7, 0x9179, /*0x88-0x8f*/ 0x917a, 0x917b, 0x917c, 0x917d, 0xe3be, 0x917e, 0x9180, 0x9181, /*0x90-0x97*/ 0x9182, 0x9183, 0x9184, 0x9185, 0x9186, 0xedad, 0x9187, 0x9188, /*0x98-0x9f*/ 0x9189, 0x918a, 0x918b, 0x918c, 0x918d, 0x918e, 0x918f, 0xe3bf, /*0xa0-0xa7*/ 0xbaa9, 0xedac, 0x9190, 0x9191, 0xe3bd, 0x9192, 0x9193, 0x9194, /*0xa8-0xaf*/ 0x9195, 0x9196, 0x9197, 0x9198, 0x9199, 0x919a, 0x919b, 0xe3c0, /*0xb0-0xb7*/ 0x919c, 0x919d, 0x919e, 0x919f, 0x91a0, 0x91a1, 0xbab6, 0x91a2, /*0xb8-0xbf*/ 0x91a3, 0x91a4, 0xb6ae, 0x91a5, 0x91a6, 0x91a7, 0x91a8, 0x91a9, /*0xc0-0xc7*/ 0xd0b8, 0x91aa, 0xb0c3, 0xedae, 0x91ab, 0x91ac, 0x91ad, 0x91ae, /*0xc8-0xcf*/ 0x91af, 0xedaf, 0xc0c1, 0x91b0, 0xe3c1, 0x91b1, 0x91b2, 0x91b3, /*0xd0-0xd7*/ 0x91b4, 0x91b5, 0x91b6, 0x91b7, 0x91b8, 0x91b9, 0x91ba, 0x91bb, /*0xd8-0xdf*/ 0x91bc, 0x91bd, 0x91be, 0x91bf, 0x91c0, 0x91c1, 0xc5b3, 0x91c2, /*0xe0-0xe7*/ 0x91c3, 0x91c4, 0x91c5, 0x91c6, 0x91c7, 0x91c8, 0x91c9, 0x91ca, /*0xe8-0xef*/ 0x91cb, 0x91cc, 0x91cd, 0x91ce, 0x91cf, 0xe3c2, 0x91d0, 0x91d1, /*0xf0-0xf7*/ 0x91d2, 0x91d3, 0x91d4, 0x91d5, 0x91d6, 0x91d7, 0x91d8, 0xdcb2, /*0xf8-0xff*/ /* 0x6200 */ 0x91d9, 0x91da, 0x91db, 0x91dc, 0x91dd, 0x91de, 0xedb0, 0x91df, /*0x00-0x07*/ 0xb8ea, 0x91e0, 0xceec, 0xeaa7, 0xd0e7, 0xcaf9, 0xc8d6, 0xcfb7, /*0x08-0x0f*/ 0xb3c9, 0xced2, 0xbde4, 0x91e1, 0x91e2, 0xe3de, 0xbbf2, 0xeaa8, /*0x10-0x17*/ 0xd5bd, 0x91e3, 0xc6dd, 0xeaa9, 0x91e4, 0x91e5, 0x91e6, 0xeaaa, /*0x18-0x1f*/ 0x91e7, 0xeaac, 0xeaab, 0x91e8, 0xeaae, 0xeaad, 0x91e9, 0x91ea, /*0x20-0x27*/ 0x91eb, 0x91ec, 0xbdd8, 0x91ed, 0xeaaf, 0x91ee, 0xc2be, 0x91ef, /*0x28-0x2f*/ 0x91f0, 0x91f1, 0x91f2, 0xb4c1, 0xb4f7, 0x91f3, 0x91f4, 0xbba7, /*0x30-0x37*/ 0x91f5, 0x91f6, 0x91f7, 0x91f8, 0x91f9, 0xece6, 0xece5, 0xb7bf, /*0x38-0x3f*/ 0xcbf9, 0xb1e2, 0x91fa, 0xece7, 0x91fb, 0x91fc, 0x91fd, 0xc9c8, /*0x40-0x47*/ 0xece8, 0xece9, 0x91fe, 0xcad6, 0xded0, 0xb2c5, 0xd4fa, 0x9240, /*0x48-0x4f*/ 0x9241, 0xc6cb, 0xb0c7, 0xb4f2, 0xc8d3, 0x9242, 0x9243, 0x9244, /*0x50-0x57*/ 0xcdd0, 0x9245, 0x9246, 0xbfb8, 0x9247, 0x9248, 0x9249, 0x924a, /*0x58-0x5f*/ 0x924b, 0x924c, 0x924d, 0xbfdb, 0x924e, 0x924f, 0xc7a4, 0xd6b4, /*0x60-0x67*/ 0x9250, 0xc0a9, 0xded1, 0xc9a8, 0xd1ef, 0xc5a4, 0xb0e7, 0xb3b6, /*0x68-0x6f*/ 0xc8c5, 0x9251, 0x9252, 0xb0e2, 0x9253, 0x9254, 0xb7f6, 0x9255, /*0x70-0x77*/ 0x9256, 0xc5fa, 0x9257, 0x9258, 0xb6f3, 0x9259, 0xd5d2, 0xb3d0, /*0x78-0x7f*/ 0xbcbc, 0x925a, 0x925b, 0x925c, 0xb3ad, 0x925d, 0x925e, 0x925f, /*0x80-0x87*/ 0x9260, 0xbef1, 0xb0d1, 0x9261, 0x9262, 0x9263, 0x9264, 0x9265, /*0x88-0x8f*/ 0x9266, 0xd2d6, 0xcae3, 0xd7a5, 0x9267, 0xcdb6, 0xb6b6, 0xbfb9, /*0x90-0x97*/ 0xd5db, 0x9268, 0xb8a7, 0xc5d7, 0x9269, 0x926a, 0x926b, 0xded2, /*0x98-0x9f*/ 0xbfd9, 0xc2d5, 0xc7c0, 0x926c, 0xbba4, 0xb1a8, 0x926d, 0x926e, /*0xa0-0xa7*/ 0xc5ea, 0x926f, 0x9270, 0xc5fb, 0xcca7, 0x9271, 0x9272, 0x9273, /*0xa8-0xaf*/ 0x9274, 0xb1a7, 0x9275, 0x9276, 0x9277, 0xb5d6, 0x9278, 0x9279, /*0xb0-0xb7*/ 0x927a, 0xc4a8, 0x927b, 0xded3, 0xd1ba, 0xb3e9, 0x927c, 0xc3f2, /*0xb8-0xbf*/ 0x927d, 0x927e, 0xb7f7, 0x9280, 0xd6f4, 0xb5a3, 0xb2f0, 0xc4b4, /*0xc0-0xc7*/ 0xc4e9, 0xc0ad, 0xded4, 0x9281, 0xb0e8, 0xc5c4, 0xc1e0, 0x9282, /*0xc8-0xcf*/ 0xb9d5, 0x9283, 0xbedc, 0xcdd8, 0xb0ce, 0x9284, 0xcdcf, 0xded6, /*0xd0-0xd7*/ 0xbed0, 0xd7be, 0xded5, 0xd5d0, 0xb0dd, 0x9285, 0x9286, 0xc4e2, /*0xd8-0xdf*/ 0x9287, 0x9288, 0xc2a3, 0xbcf0, 0x9289, 0xd3b5, 0xc0b9, 0xc5a1, /*0xe0-0xe7*/ 0xb2a6, 0xd4f1, 0x928a, 0x928b, 0xc0a8, 0xcac3, 0xded7, 0xd5fc, /*0xe8-0xef*/ 0x928c, 0xb9b0, 0x928d, 0xc8ad, 0xcba9, 0x928e, 0xded9, 0xbfbd, /*0xf0-0xf7*/ 0x928f, 0x9290, 0x9291, 0x9292, 0xc6b4, 0xd7a7, 0xcab0, 0xc4c3, /*0xf8-0xff*/ /* 0x6300 */ 0x9293, 0xb3d6, 0xb9d2, 0x9294, 0x9295, 0x9296, 0x9297, 0xd6b8, /*0x00-0x07*/ 0xeafc, 0xb0b4, 0x9298, 0x9299, 0x929a, 0x929b, 0xbfe6, 0x929c, /*0x08-0x0f*/ 0x929d, 0xccf4, 0x929e, 0x929f, 0x92a0, 0x92a1, 0xcdda, 0x92a2, /*0x10-0x17*/ 0x92a3, 0x92a4, 0xd6bf, 0xc2ce, 0x92a5, 0xcece, 0xcca2, 0xd0ae, /*0x18-0x1f*/ 0xc4d3, 0xb5b2, 0xded8, 0xd5f5, 0xbcb7, 0xbbd3, 0x92a6, 0x92a7, /*0x20-0x27*/ 0xb0a4, 0x92a8, 0xc5b2, 0xb4ec, 0x92a9, 0x92aa, 0x92ab, 0xd5f1, /*0x28-0x2f*/ 0x92ac, 0x92ad, 0xeafd, 0x92ae, 0x92af, 0x92b0, 0x92b1, 0x92b2, /*0x30-0x37*/ 0x92b3, 0xdeda, 0xcda6, 0x92b4, 0x92b5, 0xcdec, 0x92b6, 0x92b7, /*0x38-0x3f*/ 0x92b8, 0x92b9, 0xcee6, 0xdedc, 0x92ba, 0xcdb1, 0xc0a6, 0x92bb, /*0x40-0x47*/ 0x92bc, 0xd7bd, 0x92bd, 0xdedb, 0xb0c6, 0xbab4, 0xc9d3, 0xc4f3, /*0x48-0x4f*/ 0xbee8, 0x92be, 0x92bf, 0x92c0, 0x92c1, 0xb2b6, 0x92c2, 0x92c3, /*0x50-0x57*/ 0x92c4, 0x92c5, 0x92c6, 0x92c7, 0x92c8, 0x92c9, 0xc0cc, 0xcbf0, /*0x58-0x5f*/ 0x92ca, 0xbcf1, 0xbbbb, 0xb5b7, 0x92cb, 0x92cc, 0x92cd, 0xc5f5, /*0x60-0x67*/ 0x92ce, 0xdee6, 0x92cf, 0x92d0, 0x92d1, 0xdee3, 0xbedd, 0x92d2, /*0x68-0x6f*/ 0x92d3, 0xdedf, 0x92d4, 0x92d5, 0x92d6, 0x92d7, 0xb4b7, 0xbddd, /*0x70-0x77*/ 0x92d8, 0x92d9, 0xdee0, 0xc4ed, 0x92da, 0x92db, 0x92dc, 0x92dd, /*0x78-0x7f*/ 0xcfc6, 0x92de, 0xb5e0, 0x92df, 0x92e0, 0x92e1, 0x92e2, 0xb6de, /*0x80-0x87*/ 0xcada, 0xb5f4, 0xdee5, 0x92e3, 0xd5c6, 0x92e4, 0xdee1, 0xcccd, /*0x88-0x8f*/ 0xc6fe, 0x92e5, 0xc5c5, 0x92e6, 0x92e7, 0x92e8, 0xd2b4, 0x92e9, /*0x90-0x97*/ 0xbef2, 0x92ea, 0x92eb, 0x92ec, 0x92ed, 0x92ee, 0x92ef, 0x92f0, /*0x98-0x9f*/ 0xc2d3, 0x92f1, 0xccbd, 0xb3b8, 0x92f2, 0xbdd3, 0x92f3, 0xbfd8, /*0xa0-0xa7*/ 0xcdc6, 0xd1da, 0xb4eb, 0x92f4, 0xdee4, 0xdedd, 0xdee7, 0x92f5, /*0xa8-0xaf*/ 0xeafe, 0x92f6, 0x92f7, 0xc2b0, 0xdee2, 0x92f8, 0x92f9, 0xd6c0, /*0xb0-0xb7*/ 0xb5a7, 0x92fa, 0xb2f4, 0x92fb, 0xdee8, 0x92fc, 0xdef2, 0x92fd, /*0xb8-0xbf*/ 0x92fe, 0x9340, 0x9341, 0x9342, 0xdeed, 0x9343, 0xdef1, 0x9344, /*0xc0-0xc7*/ 0x9345, 0xc8e0, 0x9346, 0x9347, 0x9348, 0xd7e1, 0xdeef, 0xc3e8, /*0xc8-0xcf*/ 0xcce1, 0x9349, 0xb2e5, 0x934a, 0x934b, 0x934c, 0xd2be, 0x934d, /*0xd0-0xd7*/ 0x934e, 0x934f, 0x9350, 0x9351, 0x9352, 0x9353, 0xdeee, 0x9354, /*0xd8-0xdf*/ 0xdeeb, 0xced5, 0x9355, 0xb4a7, 0x9356, 0x9357, 0x9358, 0x9359, /*0xe0-0xe7*/ 0x935a, 0xbfab, 0xbebe, 0x935b, 0x935c, 0xbdd2, 0x935d, 0x935e, /*0xe8-0xef*/ 0x935f, 0x9360, 0xdee9, 0x9361, 0xd4ae, 0x9362, 0xdede, 0x9363, /*0xf0-0xf7*/ 0xdeea, 0x9364, 0x9365, 0x9366, 0x9367, 0xc0bf, 0x9368, 0xdeec, /*0xf8-0xff*/ /* 0x6400 */ 0xb2f3, 0xb8e9, 0xc2a7, 0x9369, 0x936a, 0xbdc1, 0x936b, 0x936c, /*0x00-0x07*/ 0x936d, 0x936e, 0x936f, 0xdef5, 0xdef8, 0x9370, 0x9371, 0xb2ab, /*0x08-0x0f*/ 0xb4a4, 0x9372, 0x9373, 0xb4ea, 0xc9a6, 0x9374, 0x9375, 0x9376, /*0x10-0x17*/ 0x9377, 0x9378, 0x9379, 0xdef6, 0xcbd1, 0x937a, 0xb8e3, 0x937b, /*0x18-0x1f*/ 0xdef7, 0xdefa, 0x937c, 0x937d, 0x937e, 0x9380, 0xdef9, 0x9381, /*0x20-0x27*/ 0x9382, 0x9383, 0xccc2, 0x9384, 0xb0e1, 0xb4ee, 0x9385, 0x9386, /*0x28-0x2f*/ 0x9387, 0x9388, 0x9389, 0x938a, 0xe5ba, 0x938b, 0x938c, 0x938d, /*0x30-0x37*/ 0x938e, 0x938f, 0xd0af, 0x9390, 0x9391, 0xb2eb, 0x9392, 0xeba1, /*0x38-0x3f*/ 0x9393, 0xdef4, 0x9394, 0x9395, 0xc9e3, 0xdef3, 0xb0da, 0xd2a1, /*0x40-0x47*/ 0xb1f7, 0x9396, 0xccaf, 0x9397, 0x9398, 0x9399, 0x939a, 0x939b, /*0x48-0x4f*/ 0x939c, 0x939d, 0xdef0, 0x939e, 0xcba4, 0x939f, 0x93a0, 0x93a1, /*0x50-0x57*/ 0xd5aa, 0x93a2, 0x93a3, 0x93a4, 0x93a5, 0x93a6, 0xdefb, 0x93a7, /*0x58-0x5f*/ 0x93a8, 0x93a9, 0x93aa, 0x93ab, 0x93ac, 0x93ad, 0x93ae, 0xb4dd, /*0x60-0x67*/ 0x93af, 0xc4a6, 0x93b0, 0x93b1, 0x93b2, 0xdefd, 0x93b3, 0x93b4, /*0x68-0x6f*/ 0x93b5, 0x93b6, 0x93b7, 0x93b8, 0x93b9, 0x93ba, 0x93bb, 0x93bc, /*0x70-0x77*/ 0xc3fe, 0xc4a1, 0xdfa1, 0x93bd, 0x93be, 0x93bf, 0x93c0, 0x93c1, /*0x78-0x7f*/ 0x93c2, 0x93c3, 0xc1cc, 0x93c4, 0xdefc, 0xbeef, 0x93c5, 0xc6b2, /*0x80-0x87*/ 0x93c6, 0x93c7, 0x93c8, 0x93c9, 0x93ca, 0x93cb, 0x93cc, 0x93cd, /*0x88-0x8f*/ 0x93ce, 0xb3c5, 0xc8f6, 0x93cf, 0x93d0, 0xcbba, 0xdefe, 0x93d1, /*0x90-0x97*/ 0x93d2, 0xdfa4, 0x93d3, 0x93d4, 0x93d5, 0x93d6, 0xd7b2, 0x93d7, /*0x98-0x9f*/ 0x93d8, 0x93d9, 0x93da, 0x93db, 0xb3b7, 0x93dc, 0x93dd, 0x93de, /*0xa0-0xa7*/ 0x93df, 0xc1c3, 0x93e0, 0x93e1, 0xc7cb, 0xb2a5, 0xb4e9, 0x93e2, /*0xa8-0xaf*/ 0xd7ab, 0x93e3, 0x93e4, 0x93e5, 0x93e6, 0xc4ec, 0x93e7, 0xdfa2, /*0xb0-0xb7*/ 0xdfa3, 0x93e8, 0xdfa5, 0x93e9, 0xbab3, 0x93ea, 0x93eb, 0x93ec, /*0xb8-0xbf*/ 0xdfa6, 0x93ed, 0xc0de, 0x93ee, 0x93ef, 0xc9c3, 0x93f0, 0x93f1, /*0xc0-0xc7*/ 0x93f2, 0x93f3, 0x93f4, 0x93f5, 0x93f6, 0xb2d9, 0xc7e6, 0x93f7, /*0xc8-0xcf*/ 0xdfa7, 0x93f8, 0xc7dc, 0x93f9, 0x93fa, 0x93fb, 0x93fc, 0xdfa8, /*0xd0-0xd7*/ 0xeba2, 0x93fd, 0x93fe, 0x9440, 0x9441, 0x9442, 0xcbd3, 0x9443, /*0xd8-0xdf*/ 0x9444, 0x9445, 0xdfaa, 0x9446, 0xdfa9, 0x9447, 0xb2c1, 0x9448, /*0xe0-0xe7*/ 0x9449, 0x944a, 0x944b, 0x944c, 0x944d, 0x944e, 0x944f, 0x9450, /*0xe8-0xef*/ 0x9451, 0x9452, 0x9453, 0x9454, 0x9455, 0x9456, 0x9457, 0x9458, /*0xf0-0xf7*/ 0x9459, 0x945a, 0x945b, 0x945c, 0x945d, 0x945e, 0x945f, 0x9460, /*0xf8-0xff*/ /* 0x6500 */ 0xc5ca, 0x9461, 0x9462, 0x9463, 0x9464, 0x9465, 0x9466, 0x9467, /*0x00-0x07*/ 0x9468, 0xdfab, 0x9469, 0x946a, 0x946b, 0x946c, 0x946d, 0x946e, /*0x08-0x0f*/ 0x946f, 0x9470, 0xd4dc, 0x9471, 0x9472, 0x9473, 0x9474, 0x9475, /*0x10-0x17*/ 0xc8c1, 0x9476, 0x9477, 0x9478, 0x9479, 0x947a, 0x947b, 0x947c, /*0x18-0x1f*/ 0x947d, 0x947e, 0x9480, 0x9481, 0x9482, 0xdfac, 0x9483, 0x9484, /*0x20-0x27*/ 0x9485, 0x9486, 0x9487, 0xbef0, 0x9488, 0x9489, 0xdfad, 0xd6a7, /*0x28-0x2f*/ 0x948a, 0x948b, 0x948c, 0x948d, 0xeab7, 0xebb6, 0xcad5, 0x948e, /*0x30-0x37*/ 0xd8fc, 0xb8c4, 0x948f, 0xb9a5, 0x9490, 0x9491, 0xb7c5, 0xd5fe, /*0x38-0x3f*/ 0x9492, 0x9493, 0x9494, 0x9495, 0x9496, 0xb9ca, 0x9497, 0x9498, /*0x40-0x47*/ 0xd0a7, 0xf4cd, 0x9499, 0x949a, 0xb5d0, 0x949b, 0x949c, 0xc3f4, /*0x48-0x4f*/ 0x949d, 0xbec8, 0x949e, 0x949f, 0x94a0, 0xebb7, 0xb0bd, 0x94a1, /*0x50-0x57*/ 0x94a2, 0xbdcc, 0x94a3, 0xc1b2, 0x94a4, 0xb1d6, 0xb3a8, 0x94a5, /*0x58-0x5f*/ 0x94a6, 0x94a7, 0xb8d2, 0xc9a2, 0x94a8, 0x94a9, 0xb6d8, 0x94aa, /*0x60-0x67*/ 0x94ab, 0x94ac, 0x94ad, 0xebb8, 0xbeb4, 0x94ae, 0x94af, 0x94b0, /*0x68-0x6f*/ 0xcafd, 0x94b1, 0xc7c3, 0x94b2, 0xd5fb, 0x94b3, 0x94b4, 0xb7f3, /*0x70-0x77*/ 0x94b5, 0x94b6, 0x94b7, 0x94b8, 0x94b9, 0x94ba, 0x94bb, 0x94bc, /*0x78-0x7f*/ 0x94bd, 0x94be, 0x94bf, 0x94c0, 0x94c1, 0x94c2, 0x94c3, 0xcec4, /*0x80-0x87*/ 0x94c4, 0x94c5, 0x94c6, 0xd5ab, 0xb1f3, 0x94c7, 0x94c8, 0x94c9, /*0x88-0x8f*/ 0xecb3, 0xb0df, 0x94ca, 0xecb5, 0x94cb, 0x94cc, 0x94cd, 0xb6b7, /*0x90-0x97*/ 0x94ce, 0xc1cf, 0x94cf, 0xf5fa, 0xd0b1, 0x94d0, 0x94d1, 0xd5e5, /*0x98-0x9f*/ 0x94d2, 0xced3, 0x94d3, 0x94d4, 0xbdef, 0xb3e2, 0x94d5, 0xb8ab, /*0xa0-0xa7*/ 0x94d6, 0xd5b6, 0x94d7, 0xedbd, 0x94d8, 0xb6cf, 0x94d9, 0xcbb9, /*0xa8-0xaf*/ 0xd0c2, 0x94da, 0x94db, 0x94dc, 0x94dd, 0x94de, 0x94df, 0x94e0, /*0xb0-0xb7*/ 0x94e1, 0xb7bd, 0x94e2, 0x94e3, 0xecb6, 0xcaa9, 0x94e4, 0x94e5, /*0xb8-0xbf*/ 0x94e6, 0xc5d4, 0x94e7, 0xecb9, 0xecb8, 0xc2c3, 0xecb7, 0x94e8, /*0xc0-0xc7*/ 0x94e9, 0x94ea, 0x94eb, 0xd0fd, 0xecba, 0x94ec, 0xecbb, 0xd7e5, /*0xc8-0xcf*/ 0x94ed, 0x94ee, 0xecbc, 0x94ef, 0x94f0, 0x94f1, 0xecbd, 0xc6ec, /*0xd0-0xd7*/ 0x94f2, 0x94f3, 0x94f4, 0x94f5, 0x94f6, 0x94f7, 0x94f8, 0x94f9, /*0xd8-0xdf*/ 0xcede, 0x94fa, 0xbcc8, 0x94fb, 0x94fc, 0xc8d5, 0xb5a9, 0xbec9, /*0xe0-0xe7*/ 0xd6bc, 0xd4e7, 0x94fd, 0x94fe, 0xd1ae, 0xd0f1, 0xeab8, 0xeab9, /*0xe8-0xef*/ 0xeaba, 0xbab5, 0x9540, 0x9541, 0x9542, 0x9543, 0xcab1, 0xbff5, /*0xf0-0xf7*/ 0x9544, 0x9545, 0xcdfa, 0x9546, 0x9547, 0x9548, 0x9549, 0x954a, /*0xf8-0xff*/ /* 0x6600 */ 0xeac0, 0x954b, 0xb0ba, 0xeabe, 0x954c, 0x954d, 0xc0a5, 0x954e, /*0x00-0x07*/ 0x954f, 0x9550, 0xeabb, 0x9551, 0xb2fd, 0x9552, 0xc3f7, 0xbbe8, /*0x08-0x0f*/ 0x9553, 0x9554, 0x9555, 0xd2d7, 0xcef4, 0xeabf, 0x9556, 0x9557, /*0x10-0x17*/ 0x9558, 0xeabc, 0x9559, 0x955a, 0x955b, 0xeac3, 0x955c, 0xd0c7, /*0x18-0x1f*/ 0xd3b3, 0x955d, 0x955e, 0x955f, 0x9560, 0xb4ba, 0x9561, 0xc3c1, /*0x20-0x27*/ 0xd7f2, 0x9562, 0x9563, 0x9564, 0x9565, 0xd5d1, 0x9566, 0xcac7, /*0x28-0x2f*/ 0x9567, 0xeac5, 0x9568, 0x9569, 0xeac4, 0xeac7, 0xeac6, 0x956a, /*0x30-0x37*/ 0x956b, 0x956c, 0x956d, 0x956e, 0xd6e7, 0x956f, 0xcfd4, 0x9570, /*0x38-0x3f*/ 0x9571, 0xeacb, 0x9572, 0xbbce, 0x9573, 0x9574, 0x9575, 0x9576, /*0x40-0x47*/ 0x9577, 0x9578, 0x9579, 0xbdfa, 0xc9ce, 0x957a, 0x957b, 0xeacc, /*0x48-0x4f*/ 0x957c, 0x957d, 0xc9b9, 0xcffe, 0xeaca, 0xd4ce, 0xeacd, 0xeacf, /*0x50-0x57*/ 0x957e, 0x9580, 0xcded, 0x9581, 0x9582, 0x9583, 0x9584, 0xeac9, /*0x58-0x5f*/ 0x9585, 0xeace, 0x9586, 0x9587, 0xceee, 0x9588, 0xbbde, 0x9589, /*0x60-0x67*/ 0xb3bf, 0x958a, 0x958b, 0x958c, 0x958d, 0x958e, 0xc6d5, 0xbeb0, /*0x68-0x6f*/ 0xcefa, 0x958f, 0x9590, 0x9591, 0xc7e7, 0x9592, 0xbea7, 0xead0, /*0x70-0x77*/ 0x9593, 0x9594, 0xd6c7, 0x9595, 0x9596, 0x9597, 0xc1c0, 0x9598, /*0x78-0x7f*/ 0x9599, 0x959a, 0xd4dd, 0x959b, 0xead1, 0x959c, 0x959d, 0xcfbe, /*0x80-0x87*/ 0x959e, 0x959f, 0x95a0, 0x95a1, 0xead2, 0x95a2, 0x95a3, 0x95a4, /*0x88-0x8f*/ 0x95a5, 0xcaee, 0x95a6, 0x95a7, 0x95a8, 0x95a9, 0xc5af, 0xb0b5, /*0x90-0x97*/ 0x95aa, 0x95ab, 0x95ac, 0x95ad, 0x95ae, 0xead4, 0x95af, 0x95b0, /*0x98-0x9f*/ 0x95b1, 0x95b2, 0x95b3, 0x95b4, 0x95b5, 0x95b6, 0x95b7, 0xead3, /*0xa0-0xa7*/ 0xf4df, 0x95b8, 0x95b9, 0x95ba, 0x95bb, 0x95bc, 0xc4ba, 0x95bd, /*0xa8-0xaf*/ 0x95be, 0x95bf, 0x95c0, 0x95c1, 0xb1a9, 0x95c2, 0x95c3, 0x95c4, /*0xb0-0xb7*/ 0x95c5, 0xe5df, 0x95c6, 0x95c7, 0x95c8, 0x95c9, 0xead5, 0x95ca, /*0xb8-0xbf*/ 0x95cb, 0x95cc, 0x95cd, 0x95ce, 0x95cf, 0x95d0, 0x95d1, 0x95d2, /*0xc0-0xc7*/ 0x95d3, 0x95d4, 0x95d5, 0x95d6, 0x95d7, 0x95d8, 0x95d9, 0x95da, /*0xc8-0xcf*/ 0x95db, 0x95dc, 0x95dd, 0x95de, 0x95df, 0x95e0, 0x95e1, 0x95e2, /*0xd0-0xd7*/ 0x95e3, 0xcaef, 0x95e4, 0xead6, 0xead7, 0xc6d8, 0x95e5, 0x95e6, /*0xd8-0xdf*/ 0x95e7, 0x95e8, 0x95e9, 0x95ea, 0x95eb, 0x95ec, 0xead8, 0x95ed, /*0xe0-0xe7*/ 0x95ee, 0xead9, 0x95ef, 0x95f0, 0x95f1, 0x95f2, 0x95f3, 0x95f4, /*0xe8-0xef*/ 0xd4bb, 0x95f5, 0xc7fa, 0xd2b7, 0xb8fc, 0x95f6, 0x95f7, 0xeac2, /*0xf0-0xf7*/ 0x95f8, 0xb2dc, 0x95f9, 0x95fa, 0xc2fc, 0x95fb, 0xd4f8, 0xcce6, /*0xf8-0xff*/ /* 0x6700 */ 0xd7ee, 0x95fc, 0x95fd, 0x95fe, 0x9640, 0x9641, 0x9642, 0x9643, /*0x00-0x07*/ 0xd4c2, 0xd3d0, 0xebc3, 0xc5f3, 0x9644, 0xb7fe, 0x9645, 0x9646, /*0x08-0x0f*/ 0xebd4, 0x9647, 0x9648, 0x9649, 0xcbb7, 0xebde, 0x964a, 0xc0ca, /*0x10-0x17*/ 0x964b, 0x964c, 0x964d, 0xcdfb, 0x964e, 0xb3af, 0x964f, 0xc6da, /*0x18-0x1f*/ 0x9650, 0x9651, 0x9652, 0x9653, 0x9654, 0x9655, 0xebfc, 0x9656, /*0x20-0x27*/ 0xc4be, 0x9657, 0xceb4, 0xc4a9, 0xb1be, 0xd4fd, 0x9658, 0xcaf5, /*0x28-0x2f*/ 0x9659, 0xd6ec, 0x965a, 0x965b, 0xc6d3, 0xb6e4, 0x965c, 0x965d, /*0x30-0x37*/ 0x965e, 0x965f, 0xbbfa, 0x9660, 0x9661, 0xd0e0, 0x9662, 0x9663, /*0x38-0x3f*/ 0xc9b1, 0x9664, 0xd4d3, 0xc8a8, 0x9665, 0x9666, 0xb8cb, 0x9667, /*0x40-0x47*/ 0xe8be, 0xc9bc, 0x9668, 0x9669, 0xe8bb, 0x966a, 0xc0ee, 0xd0d3, /*0x48-0x4f*/ 0xb2c4, 0xb4e5, 0x966b, 0xe8bc, 0x966c, 0x966d, 0xd5c8, 0x966e, /*0x50-0x57*/ 0x966f, 0x9670, 0x9671, 0x9672, 0xb6c5, 0x9673, 0xe8bd, 0xcaf8, /*0x58-0x5f*/ 0xb8dc, 0xccf5, 0x9674, 0x9675, 0x9676, 0xc0b4, 0x9677, 0x9678, /*0x60-0x67*/ 0xd1ee, 0xe8bf, 0xe8c2, 0x9679, 0x967a, 0xbabc, 0x967b, 0xb1ad, /*0x68-0x6f*/ 0xbddc, 0x967c, 0xeabd, 0xe8c3, 0x967d, 0xe8c6, 0x967e, 0xe8cb, /*0x70-0x77*/ 0x9680, 0x9681, 0x9682, 0x9683, 0xe8cc, 0x9684, 0xcbc9, 0xb0e5, /*0x78-0x7f*/ 0x9685, 0xbcab, 0x9686, 0x9687, 0xb9b9, 0x9688, 0x9689, 0xe8c1, /*0x80-0x87*/ 0x968a, 0xcdf7, 0x968b, 0xe8ca, 0x968c, 0x968d, 0x968e, 0x968f, /*0x88-0x8f*/ 0xcef6, 0x9690, 0x9691, 0x9692, 0x9693, 0xd5ed, 0x9694, 0xc1d6, /*0x90-0x97*/ 0xe8c4, 0x9695, 0xc3b6, 0x9696, 0xb9fb, 0xd6a6, 0xe8c8, 0x9697, /*0x98-0x9f*/ 0x9698, 0x9699, 0xcae0, 0xd4e6, 0x969a, 0xe8c0, 0x969b, 0xe8c5, /*0xa0-0xa7*/ 0xe8c7, 0x969c, 0xc7b9, 0xb7e3, 0x969d, 0xe8c9, 0x969e, 0xbfdd, /*0xa8-0xaf*/ 0xe8d2, 0x969f, 0x96a0, 0xe8d7, 0x96a1, 0xe8d5, 0xbcdc, 0xbccf, /*0xb0-0xb7*/ 0xe8db, 0x96a2, 0x96a3, 0x96a4, 0x96a5, 0x96a6, 0x96a7, 0x96a8, /*0xb8-0xbf*/ 0x96a9, 0xe8de, 0x96aa, 0xe8da, 0xb1fa, 0x96ab, 0x96ac, 0x96ad, /*0xc0-0xc7*/ 0x96ae, 0x96af, 0x96b0, 0x96b1, 0x96b2, 0x96b3, 0x96b4, 0xb0d8, /*0xc8-0xcf*/ 0xc4b3, 0xb8cc, 0xc6e2, 0xc8be, 0xc8e1, 0x96b5, 0x96b6, 0x96b7, /*0xd0-0xd7*/ 0xe8cf, 0xe8d4, 0xe8d6, 0x96b8, 0xb9f1, 0xe8d8, 0xd7f5, 0x96b9, /*0xd8-0xdf*/ 0xc4fb, 0x96ba, 0xe8dc, 0x96bb, 0x96bc, 0xb2e9, 0x96bd, 0x96be, /*0xe0-0xe7*/ 0x96bf, 0xe8d1, 0x96c0, 0x96c1, 0xbced, 0x96c2, 0x96c3, 0xbfc2, /*0xe8-0xef*/ 0xe8cd, 0xd6f9, 0x96c4, 0xc1f8, 0xb2f1, 0x96c5, 0x96c6, 0x96c7, /*0xf0-0xf7*/ 0x96c8, 0x96c9, 0x96ca, 0x96cb, 0x96cc, 0xe8df, 0x96cd, 0xcac1, /*0xf8-0xff*/ /* 0x6800 */ 0xe8d9, 0x96ce, 0x96cf, 0x96d0, 0x96d1, 0xd5a4, 0x96d2, 0xb1ea, /*0x00-0x07*/ 0xd5bb, 0xe8ce, 0xe8d0, 0xb6b0, 0xe8d3, 0x96d3, 0xe8dd, 0xc0b8, /*0x08-0x0f*/ 0x96d4, 0xcaf7, 0x96d5, 0xcba8, 0x96d6, 0x96d7, 0xc6dc, 0xc0f5, /*0x10-0x17*/ 0x96d8, 0x96d9, 0x96da, 0x96db, 0x96dc, 0xe8e9, 0x96dd, 0x96de, /*0x18-0x1f*/ 0x96df, 0xd0a3, 0x96e0, 0x96e1, 0x96e2, 0x96e3, 0x96e4, 0x96e5, /*0x20-0x27*/ 0x96e6, 0xe8f2, 0xd6ea, 0x96e7, 0x96e8, 0x96e9, 0x96ea, 0x96eb, /*0x28-0x2f*/ 0x96ec, 0x96ed, 0xe8e0, 0xe8e1, 0x96ee, 0x96ef, 0x96f0, 0xd1f9, /*0x30-0x37*/ 0xbacb, 0xb8f9, 0x96f1, 0x96f2, 0xb8f1, 0xd4d4, 0xe8ef, 0x96f3, /*0x38-0x3f*/ 0xe8ee, 0xe8ec, 0xb9f0, 0xccd2, 0xe8e6, 0xcea6, 0xbff2, 0x96f4, /*0x40-0x47*/ 0xb0b8, 0xe8f1, 0xe8f0, 0x96f5, 0xd7c0, 0x96f6, 0xe8e4, 0x96f7, /*0x48-0x4f*/ 0xcda9, 0xc9a3, 0x96f8, 0xbbb8, 0xbddb, 0xe8ea, 0x96f9, 0x96fa, /*0x50-0x57*/ 0x96fb, 0x96fc, 0x96fd, 0x96fe, 0x9740, 0x9741, 0x9742, 0x9743, /*0x58-0x5f*/ 0xe8e2, 0xe8e3, 0xe8e5, 0xb5b5, 0xe8e7, 0xc7c5, 0xe8eb, 0xe8ed, /*0x60-0x67*/ 0xbdb0, 0xd7ae, 0x9744, 0xe8f8, 0x9745, 0x9746, 0x9747, 0x9748, /*0x68-0x6f*/ 0x9749, 0x974a, 0x974b, 0x974c, 0xe8f5, 0x974d, 0xcdb0, 0xe8f6, /*0x70-0x77*/ 0x974e, 0x974f, 0x9750, 0x9751, 0x9752, 0x9753, 0x9754, 0x9755, /*0x78-0x7f*/ 0x9756, 0xc1ba, 0x9757, 0xe8e8, 0x9758, 0xc3b7, 0xb0f0, 0x9759, /*0x80-0x87*/ 0x975a, 0x975b, 0x975c, 0x975d, 0x975e, 0x975f, 0x9760, 0xe8f4, /*0x88-0x8f*/ 0x9761, 0x9762, 0x9763, 0xe8f7, 0x9764, 0x9765, 0x9766, 0xb9a3, /*0x90-0x97*/ 0x9767, 0x9768, 0x9769, 0x976a, 0x976b, 0x976c, 0x976d, 0x976e, /*0x98-0x9f*/ 0x976f, 0x9770, 0xc9d2, 0x9771, 0x9772, 0x9773, 0xc3ce, 0xcee0, /*0xa0-0xa7*/ 0xc0e6, 0x9774, 0x9775, 0x9776, 0x9777, 0xcbf3, 0x9778, 0xccdd, /*0xa8-0xaf*/ 0xd0b5, 0x9779, 0x977a, 0xcae1, 0x977b, 0xe8f3, 0x977c, 0x977d, /*0xb0-0xb7*/ 0x977e, 0x9780, 0x9781, 0x9782, 0x9783, 0x9784, 0x9785, 0x9786, /*0xb8-0xbf*/ 0xbcec, 0x9787, 0xe8f9, 0x9788, 0x9789, 0x978a, 0x978b, 0x978c, /*0xc0-0xc7*/ 0x978d, 0xc3de, 0x978e, 0xc6e5, 0x978f, 0xb9f7, 0x9790, 0x9791, /*0xc8-0xcf*/ 0x9792, 0x9793, 0xb0f4, 0x9794, 0x9795, 0xd7d8, 0x9796, 0x9797, /*0xd0-0xd7*/ 0xbcac, 0x9798, 0xc5ef, 0x9799, 0x979a, 0x979b, 0x979c, 0x979d, /*0xd8-0xdf*/ 0xccc4, 0x979e, 0x979f, 0xe9a6, 0x97a0, 0x97a1, 0x97a2, 0x97a3, /*0xe0-0xe7*/ 0x97a4, 0x97a5, 0x97a6, 0x97a7, 0x97a8, 0x97a9, 0xc9ad, 0x97aa, /*0xe8-0xef*/ 0xe9a2, 0xc0e2, 0x97ab, 0x97ac, 0x97ad, 0xbfc3, 0x97ae, 0x97af, /*0xf0-0xf7*/ 0x97b0, 0xe8fe, 0xb9d7, 0x97b1, 0xe8fb, 0x97b2, 0x97b3, 0x97b4, /*0xf8-0xff*/ /* 0x6900 */ 0x97b5, 0xe9a4, 0x97b6, 0x97b7, 0x97b8, 0xd2ce, 0x97b9, 0x97ba, /*0x00-0x07*/ 0x97bb, 0x97bc, 0x97bd, 0xe9a3, 0x97be, 0xd6b2, 0xd7b5, 0x97bf, /*0x08-0x0f*/ 0xe9a7, 0x97c0, 0xbdb7, 0x97c1, 0x97c2, 0x97c3, 0x97c4, 0x97c5, /*0x10-0x17*/ 0x97c6, 0x97c7, 0x97c8, 0x97c9, 0x97ca, 0x97cb, 0x97cc, 0xe8fc, /*0x18-0x1f*/ 0xe8fd, 0x97cd, 0x97ce, 0x97cf, 0xe9a1, 0x97d0, 0x97d1, 0x97d2, /*0x20-0x27*/ 0x97d3, 0x97d4, 0x97d5, 0x97d6, 0x97d7, 0xcdd6, 0x97d8, 0x97d9, /*0x28-0x2f*/ 0xd2ac, 0x97da, 0x97db, 0x97dc, 0xe9b2, 0x97dd, 0x97de, 0x97df, /*0x30-0x37*/ 0x97e0, 0xe9a9, 0x97e1, 0x97e2, 0x97e3, 0xb4aa, 0x97e4, 0xb4bb, /*0x38-0x3f*/ 0x97e5, 0x97e6, 0xe9ab, 0x97e7, 0x97e8, 0x97e9, 0x97ea, 0x97eb, /*0x40-0x47*/ 0x97ec, 0x97ed, 0x97ee, 0x97ef, 0x97f0, 0x97f1, 0x97f2, 0x97f3, /*0x48-0x4f*/ 0x97f4, 0x97f5, 0x97f6, 0x97f7, 0xd0a8, 0x97f8, 0x97f9, 0xe9a5, /*0x50-0x57*/ 0x97fa, 0x97fb, 0xb3fe, 0x97fc, 0x97fd, 0xe9ac, 0xc0e3, 0x97fe, /*0x58-0x5f*/ 0xe9aa, 0x9840, 0x9841, 0xe9b9, 0x9842, 0x9843, 0xe9b8, 0x9844, /*0x60-0x67*/ 0x9845, 0x9846, 0x9847, 0xe9ae, 0x9848, 0x9849, 0xe8fa, 0x984a, /*0x68-0x6f*/ 0x984b, 0xe9a8, 0x984c, 0x984d, 0x984e, 0x984f, 0x9850, 0xbfac, /*0x70-0x77*/ 0xe9b1, 0xe9ba, 0x9851, 0x9852, 0xc2a5, 0x9853, 0x9854, 0x9855, /*0x78-0x7f*/ 0xe9af, 0x9856, 0xb8c5, 0x9857, 0xe9ad, 0x9858, 0xd3dc, 0xe9b4, /*0x80-0x87*/ 0xe9b5, 0xe9b7, 0x9859, 0x985a, 0x985b, 0xe9c7, 0x985c, 0x985d, /*0x88-0x8f*/ 0x985e, 0x985f, 0x9860, 0x9861, 0xc0c6, 0xe9c5, 0x9862, 0x9863, /*0x90-0x97*/ 0xe9b0, 0x9864, 0x9865, 0xe9bb, 0xb0f1, 0x9866, 0x9867, 0x9868, /*0x98-0x9f*/ 0x9869, 0x986a, 0x986b, 0x986c, 0x986d, 0x986e, 0x986f, 0xe9bc, /*0xa0-0xa7*/ 0xd5a5, 0x9870, 0x9871, 0xe9be, 0x9872, 0xe9bf, 0x9873, 0x9874, /*0xa8-0xaf*/ 0x9875, 0xe9c1, 0x9876, 0x9877, 0xc1f1, 0x9878, 0x9879, 0xc8b6, /*0xb0-0xb7*/ 0x987a, 0x987b, 0x987c, 0xe9bd, 0x987d, 0x987e, 0x9880, 0x9881, /*0xb8-0xbf*/ 0x9882, 0xe9c2, 0x9883, 0x9884, 0x9885, 0x9886, 0x9887, 0x9888, /*0xc0-0xc7*/ 0x9889, 0x988a, 0xe9c3, 0x988b, 0xe9b3, 0x988c, 0xe9b6, 0x988d, /*0xc8-0xcf*/ 0xbbb1, 0x988e, 0x988f, 0x9890, 0xe9c0, 0x9891, 0x9892, 0x9893, /*0xd0-0xd7*/ 0x9894, 0x9895, 0x9896, 0xbcf7, 0x9897, 0x9898, 0x9899, 0xe9c4, /*0xd8-0xdf*/ 0xe9c6, 0x989a, 0x989b, 0x989c, 0x989d, 0x989e, 0x989f, 0x98a0, /*0xe0-0xe7*/ 0x98a1, 0x98a2, 0x98a3, 0x98a4, 0x98a5, 0xe9ca, 0x98a6, 0x98a7, /*0xe8-0xef*/ 0x98a8, 0x98a9, 0xe9ce, 0x98aa, 0x98ab, 0x98ac, 0x98ad, 0x98ae, /*0xf0-0xf7*/ 0x98af, 0x98b0, 0x98b1, 0x98b2, 0x98b3, 0xb2db, 0x98b4, 0xe9c8, /*0xf8-0xff*/ /* 0x6a00 */ 0x98b5, 0x98b6, 0x98b7, 0x98b8, 0x98b9, 0x98ba, 0x98bb, 0x98bc, /*0x00-0x07*/ 0x98bd, 0x98be, 0xb7ae, 0x98bf, 0x98c0, 0x98c1, 0x98c2, 0x98c3, /*0x08-0x0f*/ 0x98c4, 0x98c5, 0x98c6, 0x98c7, 0x98c8, 0x98c9, 0x98ca, 0xe9cb, /*0x10-0x17*/ 0xe9cc, 0x98cb, 0x98cc, 0x98cd, 0x98ce, 0x98cf, 0x98d0, 0xd5c1, /*0x18-0x1f*/ 0x98d1, 0xc4a3, 0x98d2, 0x98d3, 0x98d4, 0x98d5, 0x98d6, 0x98d7, /*0x20-0x27*/ 0xe9d8, 0x98d8, 0xbae1, 0x98d9, 0x98da, 0x98db, 0x98dc, 0xe9c9, /*0x28-0x2f*/ 0x98dd, 0xd3a3, 0x98de, 0x98df, 0x98e0, 0xe9d4, 0x98e1, 0x98e2, /*0x30-0x37*/ 0x98e3, 0x98e4, 0x98e5, 0x98e6, 0x98e7, 0xe9d7, 0xe9d0, 0x98e8, /*0x38-0x3f*/ 0x98e9, 0x98ea, 0x98eb, 0x98ec, 0xe9cf, 0x98ed, 0x98ee, 0xc7c1, /*0x40-0x47*/ 0x98ef, 0x98f0, 0x98f1, 0x98f2, 0x98f3, 0x98f4, 0x98f5, 0x98f6, /*0x48-0x4f*/ 0xe9d2, 0x98f7, 0x98f8, 0x98f9, 0x98fa, 0x98fb, 0x98fc, 0x98fd, /*0x50-0x57*/ 0xe9d9, 0xb3c8, 0x98fe, 0xe9d3, 0x9940, 0x9941, 0x9942, 0x9943, /*0x58-0x5f*/ 0x9944, 0xcff0, 0x9945, 0x9946, 0x9947, 0xe9cd, 0x9948, 0x9949, /*0x60-0x67*/ 0x994a, 0x994b, 0x994c, 0x994d, 0x994e, 0x994f, 0x9950, 0x9951, /*0x68-0x6f*/ 0x9952, 0xb3f7, 0x9953, 0x9954, 0x9955, 0x9956, 0x9957, 0x9958, /*0x70-0x77*/ 0x9959, 0xe9d6, 0x995a, 0x995b, 0xe9da, 0x995c, 0x995d, 0x995e, /*0x78-0x7f*/ 0xccb4, 0x995f, 0x9960, 0x9961, 0xcfad, 0x9962, 0x9963, 0x9964, /*0x80-0x87*/ 0x9965, 0x9966, 0x9967, 0x9968, 0x9969, 0x996a, 0xe9d5, 0x996b, /*0x88-0x8f*/ 0xe9dc, 0xe9db, 0x996c, 0x996d, 0x996e, 0x996f, 0x9970, 0xe9de, /*0x90-0x97*/ 0x9971, 0x9972, 0x9973, 0x9974, 0x9975, 0x9976, 0x9977, 0x9978, /*0x98-0x9f*/ 0xe9d1, 0x9979, 0x997a, 0x997b, 0x997c, 0x997d, 0x997e, 0x9980, /*0xa0-0xa7*/ 0x9981, 0xe9dd, 0x9982, 0xe9df, 0xc3ca, 0x9983, 0x9984, 0x9985, /*0xa8-0xaf*/ 0x9986, 0x9987, 0x9988, 0x9989, 0x998a, 0x998b, 0x998c, 0x998d, /*0xb0-0xb7*/ 0x998e, 0x998f, 0x9990, 0x9991, 0x9992, 0x9993, 0x9994, 0x9995, /*0xb8-0xbf*/ 0x9996, 0x9997, 0x9998, 0x9999, 0x999a, 0x999b, 0x999c, 0x999d, /*0xc0-0xc7*/ 0x999e, 0x999f, 0x99a0, 0x99a1, 0x99a2, 0x99a3, 0x99a4, 0x99a5, /*0xc8-0xcf*/ 0x99a6, 0x99a7, 0x99a8, 0x99a9, 0x99aa, 0x99ab, 0x99ac, 0x99ad, /*0xd0-0xd7*/ 0x99ae, 0x99af, 0x99b0, 0x99b1, 0x99b2, 0x99b3, 0x99b4, 0x99b5, /*0xd8-0xdf*/ 0x99b6, 0x99b7, 0x99b8, 0x99b9, 0x99ba, 0x99bb, 0x99bc, 0x99bd, /*0xe0-0xe7*/ 0x99be, 0x99bf, 0x99c0, 0x99c1, 0x99c2, 0x99c3, 0x99c4, 0x99c5, /*0xe8-0xef*/ 0x99c6, 0x99c7, 0x99c8, 0x99c9, 0x99ca, 0x99cb, 0x99cc, 0x99cd, /*0xf0-0xf7*/ 0x99ce, 0x99cf, 0x99d0, 0x99d1, 0x99d2, 0x99d3, 0x99d4, 0x99d5, /*0xf8-0xff*/ /* 0x6b00 */ 0x99d6, 0x99d7, 0x99d8, 0x99d9, 0x99da, 0x99db, 0x99dc, 0x99dd, /*0x00-0x07*/ 0x99de, 0x99df, 0x99e0, 0x99e1, 0x99e2, 0x99e3, 0x99e4, 0x99e5, /*0x08-0x0f*/ 0x99e6, 0x99e7, 0x99e8, 0x99e9, 0x99ea, 0x99eb, 0x99ec, 0x99ed, /*0x10-0x17*/ 0x99ee, 0x99ef, 0x99f0, 0x99f1, 0x99f2, 0x99f3, 0x99f4, 0x99f5, /*0x18-0x1f*/ 0xc7b7, 0xb4ce, 0xbbb6, 0xd0c0, 0xeca3, 0x99f6, 0x99f7, 0xc5b7, /*0x20-0x27*/ 0x99f8, 0x99f9, 0x99fa, 0x99fb, 0x99fc, 0x99fd, 0x99fe, 0x9a40, /*0x28-0x2f*/ 0x9a41, 0x9a42, 0xd3fb, 0x9a43, 0x9a44, 0x9a45, 0x9a46, 0xeca4, /*0x30-0x37*/ 0x9a47, 0xeca5, 0xc6db, 0x9a48, 0x9a49, 0x9a4a, 0xbfee, 0x9a4b, /*0x38-0x3f*/ 0x9a4c, 0x9a4d, 0x9a4e, 0xeca6, 0x9a4f, 0x9a50, 0xeca7, 0xd0aa, /*0x40-0x47*/ 0x9a51, 0xc7b8, 0x9a52, 0x9a53, 0xb8e8, 0x9a54, 0x9a55, 0x9a56, /*0x48-0x4f*/ 0x9a57, 0x9a58, 0x9a59, 0x9a5a, 0x9a5b, 0x9a5c, 0x9a5d, 0x9a5e, /*0x50-0x57*/ 0x9a5f, 0xeca8, 0x9a60, 0x9a61, 0x9a62, 0x9a63, 0x9a64, 0x9a65, /*0x58-0x5f*/ 0x9a66, 0x9a67, 0xd6b9, 0xd5fd, 0xb4cb, 0xb2bd, 0xcee4, 0xc6e7, /*0x60-0x67*/ 0x9a68, 0x9a69, 0xcde1, 0x9a6a, 0x9a6b, 0x9a6c, 0x9a6d, 0x9a6e, /*0x68-0x6f*/ 0x9a6f, 0x9a70, 0x9a71, 0x9a72, 0x9a73, 0x9a74, 0x9a75, 0x9a76, /*0x70-0x77*/ 0x9a77, 0xb4f5, 0x9a78, 0xcbc0, 0xbcdf, 0x9a79, 0x9a7a, 0x9a7b, /*0x78-0x7f*/ 0x9a7c, 0xe9e2, 0xe9e3, 0xd1ea, 0xe9e5, 0x9a7d, 0xb4f9, 0xe9e4, /*0x80-0x87*/ 0x9a7e, 0xd1b3, 0xcae2, 0xb2d0, 0x9a80, 0xe9e8, 0x9a81, 0x9a82, /*0x88-0x8f*/ 0x9a83, 0x9a84, 0xe9e6, 0xe9e7, 0x9a85, 0x9a86, 0xd6b3, 0x9a87, /*0x90-0x97*/ 0x9a88, 0x9a89, 0xe9e9, 0xe9ea, 0x9a8a, 0x9a8b, 0x9a8c, 0x9a8d, /*0x98-0x9f*/ 0x9a8e, 0xe9eb, 0x9a8f, 0x9a90, 0x9a91, 0x9a92, 0x9a93, 0x9a94, /*0xa0-0xa7*/ 0x9a95, 0x9a96, 0xe9ec, 0x9a97, 0x9a98, 0x9a99, 0x9a9a, 0x9a9b, /*0xa8-0xaf*/ 0x9a9c, 0x9a9d, 0x9a9e, 0xecaf, 0xc5b9, 0xb6ce, 0x9a9f, 0xd2f3, /*0xb0-0xb7*/ 0x9aa0, 0x9aa1, 0x9aa2, 0x9aa3, 0x9aa4, 0x9aa5, 0x9aa6, 0xb5ee, /*0xb8-0xbf*/ 0x9aa7, 0xbbd9, 0xecb1, 0x9aa8, 0x9aa9, 0xd2e3, 0x9aaa, 0x9aab, /*0xc0-0xc7*/ 0x9aac, 0x9aad, 0x9aae, 0xcee3, 0x9aaf, 0xc4b8, 0x9ab0, 0xc3bf, /*0xc8-0xcf*/ 0x9ab1, 0x9ab2, 0xb6be, 0xd8b9, 0xb1c8, 0xb1cf, 0xb1d1, 0xc5fe, /*0xd0-0xd7*/ 0x9ab3, 0xb1d0, 0x9ab4, 0xc3ab, 0x9ab5, 0x9ab6, 0x9ab7, 0x9ab8, /*0xd8-0xdf*/ 0x9ab9, 0xd5b1, 0x9aba, 0x9abb, 0x9abc, 0x9abd, 0x9abe, 0x9abf, /*0xe0-0xe7*/ 0x9ac0, 0x9ac1, 0xeba4, 0xbac1, 0x9ac2, 0x9ac3, 0x9ac4, 0xccba, /*0xe8-0xef*/ 0x9ac5, 0x9ac6, 0x9ac7, 0xeba5, 0x9ac8, 0xeba7, 0x9ac9, 0x9aca, /*0xf0-0xf7*/ 0x9acb, 0xeba8, 0x9acc, 0x9acd, 0x9ace, 0xeba6, 0x9acf, 0x9ad0, /*0xf8-0xff*/ /* 0x6c00 */ 0x9ad1, 0x9ad2, 0x9ad3, 0x9ad4, 0x9ad5, 0xeba9, 0xebab, 0xebaa, /*0x00-0x07*/ 0x9ad6, 0x9ad7, 0x9ad8, 0x9ad9, 0x9ada, 0xebac, 0x9adb, 0xcacf, /*0x08-0x0f*/ 0xd8b5, 0xc3f1, 0x9adc, 0xc3a5, 0xc6f8, 0xebad, 0xc4ca, 0x9add, /*0x10-0x17*/ 0xebae, 0xebaf, 0xebb0, 0xb7d5, 0x9ade, 0x9adf, 0x9ae0, 0xb7fa, /*0x18-0x1f*/ 0x9ae1, 0xebb1, 0xc7e2, 0x9ae2, 0xebb3, 0x9ae3, 0xbaa4, 0xd1f5, /*0x20-0x27*/ 0xb0b1, 0xebb2, 0xebb4, 0x9ae4, 0x9ae5, 0x9ae6, 0xb5aa, 0xc2c8, /*0x28-0x2f*/ 0xc7e8, 0x9ae7, 0xebb5, 0x9ae8, 0xcbae, 0xe3df, 0x9ae9, 0x9aea, /*0x30-0x37*/ 0xd3c0, 0x9aeb, 0x9aec, 0x9aed, 0x9aee, 0xd9db, 0x9aef, 0x9af0, /*0x38-0x3f*/ 0xcda1, 0xd6ad, 0xc7f3, 0x9af1, 0x9af2, 0x9af3, 0xd9e0, 0xbbe3, /*0x40-0x47*/ 0x9af4, 0xbaba, 0xe3e2, 0x9af5, 0x9af6, 0x9af7, 0x9af8, 0x9af9, /*0x48-0x4f*/ 0xcfab, 0x9afa, 0x9afb, 0x9afc, 0xe3e0, 0xc9c7, 0x9afd, 0xbab9, /*0x50-0x57*/ 0x9afe, 0x9b40, 0x9b41, 0xd1b4, 0xe3e1, 0xc8ea, 0xb9af, 0xbdad, /*0x58-0x5f*/ 0xb3d8, 0xcedb, 0x9b42, 0x9b43, 0xccc0, 0x9b44, 0x9b45, 0x9b46, /*0x60-0x67*/ 0xe3e8, 0xe3e9, 0xcdf4, 0x9b47, 0x9b48, 0x9b49, 0x9b4a, 0x9b4b, /*0x68-0x6f*/ 0xccad, 0x9b4c, 0xbcb3, 0x9b4d, 0xe3ea, 0x9b4e, 0xe3eb, 0x9b4f, /*0x70-0x77*/ 0x9b50, 0xd0da, 0x9b51, 0x9b52, 0x9b53, 0xc6fb, 0xb7da, 0x9b54, /*0x78-0x7f*/ 0x9b55, 0xc7df, 0xd2ca, 0xced6, 0x9b56, 0xe3e4, 0xe3ec, 0x9b57, /*0x80-0x87*/ 0xc9f2, 0xb3c1, 0x9b58, 0x9b59, 0xe3e7, 0x9b5a, 0x9b5b, 0xc6e3, /*0x88-0x8f*/ 0xe3e5, 0x9b5c, 0x9b5d, 0xedb3, 0xe3e6, 0x9b5e, 0x9b5f, 0x9b60, /*0x90-0x97*/ 0x9b61, 0xc9b3, 0x9b62, 0xc5e6, 0x9b63, 0x9b64, 0x9b65, 0xb9b5, /*0x98-0x9f*/ 0x9b66, 0xc3bb, 0x9b67, 0xe3e3, 0xc5bd, 0xc1a4, 0xc2d9, 0xb2d7, /*0xa0-0xa7*/ 0x9b68, 0xe3ed, 0xbba6, 0xc4ad, 0x9b69, 0xe3f0, 0xbeda, 0x9b6a, /*0xa8-0xaf*/ 0x9b6b, 0xe3fb, 0xe3f5, 0xbad3, 0x9b6c, 0x9b6d, 0x9b6e, 0x9b6f, /*0xb0-0xb7*/ 0xb7d0, 0xd3cd, 0x9b70, 0xd6ce, 0xd5d3, 0xb9c1, 0xd5b4, 0xd1d8, /*0xb8-0xbf*/ 0x9b71, 0x9b72, 0x9b73, 0x9b74, 0xd0b9, 0xc7f6, 0x9b75, 0x9b76, /*0xc0-0xc7*/ 0x9b77, 0xc8aa, 0xb2b4, 0x9b78, 0xc3da, 0x9b79, 0x9b7a, 0x9b7b, /*0xc8-0xcf*/ 0xe3ee, 0x9b7c, 0x9b7d, 0xe3fc, 0xe3ef, 0xb7a8, 0xe3f7, 0xe3f4, /*0xd0-0xd7*/ 0x9b7e, 0x9b80, 0x9b81, 0xb7ba, 0x9b82, 0x9b83, 0xc5a2, 0x9b84, /*0xd8-0xdf*/ 0xe3f6, 0xc5dd, 0xb2a8, 0xc6fc, 0x9b85, 0xc4e0, 0x9b86, 0x9b87, /*0xe0-0xe7*/ 0xd7a2, 0x9b88, 0xc0e1, 0xe3f9, 0x9b89, 0x9b8a, 0xe3fa, 0xe3fd, /*0xe8-0xef*/ 0xcca9, 0xe3f3, 0x9b8b, 0xd3be, 0x9b8c, 0xb1c3, 0xedb4, 0xe3f1, /*0xf0-0xf7*/ 0xe3f2, 0x9b8d, 0xe3f8, 0xd0ba, 0xc6c3, 0xd4f3, 0xe3fe, 0x9b8e, /*0xf8-0xff*/ /* 0x6d00 */ 0x9b8f, 0xbde0, 0x9b90, 0x9b91, 0xe4a7, 0x9b92, 0x9b93, 0xe4a6, /*0x00-0x07*/ 0x9b94, 0x9b95, 0x9b96, 0xd1f3, 0xe4a3, 0x9b97, 0xe4a9, 0x9b98, /*0x08-0x0f*/ 0x9b99, 0x9b9a, 0xc8f7, 0x9b9b, 0x9b9c, 0x9b9d, 0x9b9e, 0xcfb4, /*0x10-0x17*/ 0x9b9f, 0xe4a8, 0xe4ae, 0xc2e5, 0x9ba0, 0x9ba1, 0xb6b4, 0x9ba2, /*0x18-0x1f*/ 0x9ba3, 0x9ba4, 0x9ba5, 0x9ba6, 0x9ba7, 0xbdf2, 0x9ba8, 0xe4a2, /*0x20-0x27*/ 0x9ba9, 0x9baa, 0xbae9, 0xe4aa, 0x9bab, 0x9bac, 0xe4ac, 0x9bad, /*0x28-0x2f*/ 0x9bae, 0xb6fd, 0xd6de, 0xe4b2, 0x9baf, 0xe4ad, 0x9bb0, 0x9bb1, /*0x30-0x37*/ 0x9bb2, 0xe4a1, 0x9bb3, 0xbbee, 0xcddd, 0xc7a2, 0xc5c9, 0x9bb4, /*0x38-0x3f*/ 0x9bb5, 0xc1f7, 0x9bb6, 0xe4a4, 0x9bb7, 0xc7b3, 0xbdac, 0xbdbd, /*0x40-0x47*/ 0xe4a5, 0x9bb8, 0xd7c7, 0xb2e2, 0x9bb9, 0xe4ab, 0xbcc3, 0xe4af, /*0x48-0x4f*/ 0x9bba, 0xbbeb, 0xe4b0, 0xc5a8, 0xe4b1, 0x9bbb, 0x9bbc, 0x9bbd, /*0x50-0x57*/ 0x9bbe, 0xd5e3, 0xbfa3, 0x9bbf, 0xe4ba, 0x9bc0, 0xe4b7, 0x9bc1, /*0x58-0x5f*/ 0xe4bb, 0x9bc2, 0x9bc3, 0xe4bd, 0x9bc4, 0x9bc5, 0xc6d6, 0x9bc6, /*0x60-0x67*/ 0x9bc7, 0xbac6, 0xc0cb, 0x9bc8, 0x9bc9, 0x9bca, 0xb8a1, 0xe4b4, /*0x68-0x6f*/ 0x9bcb, 0x9bcc, 0x9bcd, 0x9bce, 0xd4a1, 0x9bcf, 0x9bd0, 0xbaa3, /*0x70-0x77*/ 0xbdfe, 0x9bd1, 0x9bd2, 0x9bd3, 0xe4bc, 0x9bd4, 0x9bd5, 0x9bd6, /*0x78-0x7f*/ 0x9bd7, 0x9bd8, 0xcdbf, 0x9bd9, 0x9bda, 0xc4f9, 0x9bdb, 0x9bdc, /*0x80-0x87*/ 0xcffb, 0xc9e6, 0x9bdd, 0x9bde, 0xd3bf, 0x9bdf, 0xcfd1, 0x9be0, /*0x88-0x8f*/ 0x9be1, 0xe4b3, 0x9be2, 0xe4b8, 0xe4b9, 0xcce9, 0x9be3, 0x9be4, /*0x90-0x97*/ 0x9be5, 0x9be6, 0x9be7, 0xccce, 0x9be8, 0xc0d4, 0xe4b5, 0xc1b0, /*0x98-0x9f*/ 0xe4b6, 0xced0, 0x9be9, 0xbbc1, 0xb5d3, 0x9bea, 0xc8f3, 0xbda7, /*0xa0-0xa7*/ 0xd5c7, 0xc9ac, 0xb8a2, 0xe4ca, 0x9beb, 0x9bec, 0xe4cc, 0xd1c4, /*0xa8-0xaf*/ 0x9bed, 0x9bee, 0xd2ba, 0x9bef, 0x9bf0, 0xbaad, 0x9bf1, 0x9bf2, /*0xb0-0xb7*/ 0xbad4, 0x9bf3, 0x9bf4, 0x9bf5, 0x9bf6, 0x9bf7, 0x9bf8, 0xe4c3, /*0xb8-0xbf*/ 0xb5ed, 0x9bf9, 0x9bfa, 0x9bfb, 0xd7cd, 0xe4c0, 0xcffd, 0xe4bf, /*0xc0-0xc7*/ 0x9bfc, 0x9bfd, 0x9bfe, 0xc1dc, 0xccca, 0x9c40, 0x9c41, 0x9c42, /*0xc8-0xcf*/ 0x9c43, 0xcae7, 0x9c44, 0x9c45, 0x9c46, 0x9c47, 0xc4d7, 0x9c48, /*0xd0-0xd7*/ 0xccd4, 0xe4c8, 0x9c49, 0x9c4a, 0x9c4b, 0xe4c7, 0xe4c1, 0x9c4c, /*0xd8-0xdf*/ 0xe4c4, 0xb5ad, 0x9c4d, 0x9c4e, 0xd3d9, 0x9c4f, 0xe4c6, 0x9c50, /*0xe0-0xe7*/ 0x9c51, 0x9c52, 0x9c53, 0xd2f9, 0xb4e3, 0x9c54, 0xbbb4, 0x9c55, /*0xe8-0xef*/ 0x9c56, 0xc9ee, 0x9c57, 0xb4be, 0x9c58, 0x9c59, 0x9c5a, 0xbbec, /*0xf0-0xf7*/ 0x9c5b, 0xd1cd, 0x9c5c, 0xcced, 0xedb5, 0x9c5d, 0x9c5e, 0x9c5f, /*0xf8-0xff*/ /* 0x6e00 */ 0x9c60, 0x9c61, 0x9c62, 0x9c63, 0x9c64, 0xc7e5, 0x9c65, 0x9c66, /*0x00-0x07*/ 0x9c67, 0x9c68, 0xd4a8, 0x9c69, 0xe4cb, 0xd7d5, 0xe4c2, 0x9c6a, /*0x08-0x0f*/ 0xbda5, 0xe4c5, 0x9c6b, 0x9c6c, 0xd3e6, 0x9c6d, 0xe4c9, 0xc9f8, /*0x10-0x17*/ 0x9c6e, 0x9c6f, 0xe4be, 0x9c70, 0x9c71, 0xd3e5, 0x9c72, 0x9c73, /*0x18-0x1f*/ 0xc7fe, 0xb6c9, 0x9c74, 0xd4fc, 0xb2b3, 0xe4d7, 0x9c75, 0x9c76, /*0x20-0x27*/ 0x9c77, 0xcec2, 0x9c78, 0xe4cd, 0x9c79, 0xcebc, 0x9c7a, 0xb8db, /*0x28-0x2f*/ 0x9c7b, 0x9c7c, 0xe4d6, 0x9c7d, 0xbfca, 0x9c7e, 0x9c80, 0x9c81, /*0x30-0x37*/ 0xd3ce, 0x9c82, 0xc3ec, 0x9c83, 0x9c84, 0x9c85, 0x9c86, 0x9c87, /*0x38-0x3f*/ 0x9c88, 0x9c89, 0x9c8a, 0xc5c8, 0xe4d8, 0x9c8b, 0x9c8c, 0x9c8d, /*0x40-0x47*/ 0x9c8e, 0x9c8f, 0x9c90, 0x9c91, 0x9c92, 0xcdc4, 0xe4cf, 0x9c93, /*0x48-0x4f*/ 0x9c94, 0x9c95, 0x9c96, 0xe4d4, 0xe4d5, 0x9c97, 0xbafe, 0x9c98, /*0x50-0x57*/ 0xcfe6, 0x9c99, 0x9c9a, 0xd5bf, 0x9c9b, 0x9c9c, 0x9c9d, 0xe4d2, /*0x58-0x5f*/ 0x9c9e, 0x9c9f, 0x9ca0, 0x9ca1, 0x9ca2, 0x9ca3, 0x9ca4, 0x9ca5, /*0x60-0x67*/ 0x9ca6, 0x9ca7, 0x9ca8, 0xe4d0, 0x9ca9, 0x9caa, 0xe4ce, 0x9cab, /*0x68-0x6f*/ 0x9cac, 0x9cad, 0x9cae, 0x9caf, 0x9cb0, 0x9cb1, 0x9cb2, 0x9cb3, /*0x70-0x77*/ 0x9cb4, 0x9cb5, 0x9cb6, 0x9cb7, 0x9cb8, 0x9cb9, 0xcde5, 0xcaaa, /*0x78-0x7f*/ 0x9cba, 0x9cbb, 0x9cbc, 0xc0a3, 0x9cbd, 0xbda6, 0xe4d3, 0x9cbe, /*0x80-0x87*/ 0x9cbf, 0xb8c8, 0x9cc0, 0x9cc1, 0x9cc2, 0x9cc3, 0x9cc4, 0xe4e7, /*0x88-0x8f*/ 0xd4b4, 0x9cc5, 0x9cc6, 0x9cc7, 0x9cc8, 0x9cc9, 0x9cca, 0x9ccb, /*0x90-0x97*/ 0xe4db, 0x9ccc, 0x9ccd, 0x9cce, 0xc1ef, 0x9ccf, 0x9cd0, 0xe4e9, /*0x98-0x9f*/ 0x9cd1, 0x9cd2, 0xd2e7, 0x9cd3, 0x9cd4, 0xe4df, 0x9cd5, 0xe4e0, /*0xa0-0xa7*/ 0x9cd6, 0x9cd7, 0xcfaa, 0x9cd8, 0x9cd9, 0x9cda, 0x9cdb, 0xcbdd, /*0xa8-0xaf*/ 0x9cdc, 0xe4da, 0xe4d1, 0x9cdd, 0xe4e5, 0x9cde, 0xc8dc, 0xe4e3, /*0xb0-0xb7*/ 0x9cdf, 0x9ce0, 0xc4e7, 0xe4e2, 0x9ce1, 0xe4e1, 0x9ce2, 0x9ce3, /*0xb8-0xbf*/ 0x9ce4, 0xb3fc, 0xe4e8, 0x9ce5, 0x9ce6, 0x9ce7, 0x9ce8, 0xb5e1, /*0xc0-0xc7*/ 0x9ce9, 0x9cea, 0x9ceb, 0xd7cc, 0x9cec, 0x9ced, 0x9cee, 0xe4e6, /*0xc8-0xcf*/ 0x9cef, 0xbbac, 0x9cf0, 0xd7d2, 0xcccf, 0xebf8, 0x9cf1, 0xe4e4, /*0xd0-0xd7*/ 0x9cf2, 0x9cf3, 0xb9f6, 0x9cf4, 0x9cf5, 0x9cf6, 0xd6cd, 0xe4d9, /*0xd8-0xdf*/ 0xe4dc, 0xc2fa, 0xe4de, 0x9cf7, 0xc2cb, 0xc0c4, 0xc2d0, 0x9cf8, /*0xe0-0xe7*/ 0xb1f5, 0xccb2, 0x9cf9, 0x9cfa, 0x9cfb, 0x9cfc, 0x9cfd, 0x9cfe, /*0xe8-0xef*/ 0x9d40, 0x9d41, 0x9d42, 0x9d43, 0xb5ce, 0x9d44, 0x9d45, 0x9d46, /*0xf0-0xf7*/ 0x9d47, 0xe4ef, 0x9d48, 0x9d49, 0x9d4a, 0x9d4b, 0x9d4c, 0x9d4d, /*0xf8-0xff*/ /* 0x6f00 */ 0x9d4e, 0x9d4f, 0xc6af, 0x9d50, 0x9d51, 0x9d52, 0xc6e1, 0x9d53, /*0x00-0x07*/ 0x9d54, 0xe4f5, 0x9d55, 0x9d56, 0x9d57, 0x9d58, 0x9d59, 0xc2a9, /*0x08-0x0f*/ 0x9d5a, 0x9d5b, 0x9d5c, 0xc0ec, 0xd1dd, 0xe4ee, 0x9d5d, 0x9d5e, /*0x10-0x17*/ 0x9d5f, 0x9d60, 0x9d61, 0x9d62, 0x9d63, 0x9d64, 0x9d65, 0x9d66, /*0x18-0x1f*/ 0xc4ae, 0x9d67, 0x9d68, 0x9d69, 0xe4ed, 0x9d6a, 0x9d6b, 0x9d6c, /*0x20-0x27*/ 0x9d6d, 0xe4f6, 0xe4f4, 0xc2fe, 0x9d6e, 0xe4dd, 0x9d6f, 0xe4f0, /*0x28-0x2f*/ 0x9d70, 0xcafe, 0x9d71, 0xd5c4, 0x9d72, 0x9d73, 0xe4f1, 0x9d74, /*0x30-0x37*/ 0x9d75, 0x9d76, 0x9d77, 0x9d78, 0x9d79, 0x9d7a, 0xd1fa, 0x9d7b, /*0x38-0x3f*/ 0x9d7c, 0x9d7d, 0x9d7e, 0x9d80, 0x9d81, 0x9d82, 0xe4eb, 0xe4ec, /*0x40-0x47*/ 0x9d83, 0x9d84, 0x9d85, 0xe4f2, 0x9d86, 0xceab, 0x9d87, 0x9d88, /*0x48-0x4f*/ 0x9d89, 0x9d8a, 0x9d8b, 0x9d8c, 0x9d8d, 0x9d8e, 0x9d8f, 0x9d90, /*0x50-0x57*/ 0xc5cb, 0x9d91, 0x9d92, 0x9d93, 0xc7b1, 0x9d94, 0xc2ba, 0x9d95, /*0x58-0x5f*/ 0x9d96, 0x9d97, 0xe4ea, 0x9d98, 0x9d99, 0x9d9a, 0xc1ca, 0x9d9b, /*0x60-0x67*/ 0x9d9c, 0x9d9d, 0x9d9e, 0x9d9f, 0x9da0, 0xccb6, 0xb3b1, 0x9da1, /*0x68-0x6f*/ 0x9da2, 0x9da3, 0xe4fb, 0x9da4, 0xe4f3, 0x9da5, 0x9da6, 0x9da7, /*0x70-0x77*/ 0xe4fa, 0x9da8, 0xe4fd, 0x9da9, 0xe4fc, 0x9daa, 0x9dab, 0x9dac, /*0x78-0x7f*/ 0x9dad, 0x9dae, 0x9daf, 0x9db0, 0xb3ce, 0x9db1, 0x9db2, 0x9db3, /*0x80-0x87*/ 0xb3ba, 0xe4f7, 0x9db4, 0x9db5, 0xe4f9, 0xe4f8, 0xc5ec, 0x9db6, /*0x88-0x8f*/ 0x9db7, 0x9db8, 0x9db9, 0x9dba, 0x9dbb, 0x9dbc, 0x9dbd, 0x9dbe, /*0x90-0x97*/ 0x9dbf, 0x9dc0, 0x9dc1, 0x9dc2, 0xc0bd, 0x9dc3, 0x9dc4, 0x9dc5, /*0x98-0x9f*/ 0x9dc6, 0xd4e8, 0x9dc7, 0x9dc8, 0x9dc9, 0x9dca, 0x9dcb, 0xe5a2, /*0xa0-0xa7*/ 0x9dcc, 0x9dcd, 0x9dce, 0x9dcf, 0x9dd0, 0x9dd1, 0x9dd2, 0x9dd3, /*0xa8-0xaf*/ 0x9dd4, 0x9dd5, 0x9dd6, 0xb0c4, 0x9dd7, 0x9dd8, 0xe5a4, 0x9dd9, /*0xb0-0xb7*/ 0x9dda, 0xe5a3, 0x9ddb, 0x9ddc, 0x9ddd, 0x9dde, 0x9ddf, 0x9de0, /*0xb8-0xbf*/ 0xbca4, 0x9de1, 0xe5a5, 0x9de2, 0x9de3, 0x9de4, 0x9de5, 0x9de6, /*0xc0-0xc7*/ 0x9de7, 0xe5a1, 0x9de8, 0x9de9, 0x9dea, 0x9deb, 0x9dec, 0x9ded, /*0xc8-0xcf*/ 0x9dee, 0xe4fe, 0xb1f4, 0x9def, 0x9df0, 0x9df1, 0x9df2, 0x9df3, /*0xd0-0xd7*/ 0x9df4, 0x9df5, 0x9df6, 0x9df7, 0x9df8, 0x9df9, 0xe5a8, 0x9dfa, /*0xd8-0xdf*/ 0xe5a9, 0xe5a6, 0x9dfb, 0x9dfc, 0x9dfd, 0x9dfe, 0x9e40, 0x9e41, /*0xe0-0xe7*/ 0x9e42, 0x9e43, 0x9e44, 0x9e45, 0x9e46, 0x9e47, 0xe5a7, 0xe5aa, /*0xe8-0xef*/ 0x9e48, 0x9e49, 0x9e4a, 0x9e4b, 0x9e4c, 0x9e4d, 0x9e4e, 0x9e4f, /*0xf0-0xf7*/ 0x9e50, 0x9e51, 0x9e52, 0x9e53, 0x9e54, 0x9e55, 0x9e56, 0x9e57, /*0xf8-0xff*/ /* 0x7000 */ 0x9e58, 0x9e59, 0x9e5a, 0x9e5b, 0x9e5c, 0x9e5d, 0x9e5e, 0x9e5f, /*0x00-0x07*/ 0x9e60, 0x9e61, 0x9e62, 0x9e63, 0x9e64, 0x9e65, 0x9e66, 0x9e67, /*0x08-0x0f*/ 0x9e68, 0xc6d9, 0x9e69, 0x9e6a, 0x9e6b, 0x9e6c, 0x9e6d, 0x9e6e, /*0x10-0x17*/ 0x9e6f, 0x9e70, 0xe5ab, 0xe5ad, 0x9e71, 0x9e72, 0x9e73, 0x9e74, /*0x18-0x1f*/ 0x9e75, 0x9e76, 0x9e77, 0xe5ac, 0x9e78, 0x9e79, 0x9e7a, 0x9e7b, /*0x20-0x27*/ 0x9e7c, 0x9e7d, 0x9e7e, 0x9e80, 0x9e81, 0x9e82, 0x9e83, 0x9e84, /*0x28-0x2f*/ 0x9e85, 0x9e86, 0x9e87, 0x9e88, 0x9e89, 0xe5af, 0x9e8a, 0x9e8b, /*0x30-0x37*/ 0x9e8c, 0xe5ae, 0x9e8d, 0x9e8e, 0x9e8f, 0x9e90, 0x9e91, 0x9e92, /*0x38-0x3f*/ 0x9e93, 0x9e94, 0x9e95, 0x9e96, 0x9e97, 0x9e98, 0x9e99, 0x9e9a, /*0x40-0x47*/ 0x9e9b, 0x9e9c, 0x9e9d, 0x9e9e, 0xb9e0, 0x9e9f, 0x9ea0, 0xe5b0, /*0x48-0x4f*/ 0x9ea1, 0x9ea2, 0x9ea3, 0x9ea4, 0x9ea5, 0x9ea6, 0x9ea7, 0x9ea8, /*0x50-0x57*/ 0x9ea9, 0x9eaa, 0x9eab, 0x9eac, 0x9ead, 0x9eae, 0xe5b1, 0x9eaf, /*0x58-0x5f*/ 0x9eb0, 0x9eb1, 0x9eb2, 0x9eb3, 0x9eb4, 0x9eb5, 0x9eb6, 0x9eb7, /*0x60-0x67*/ 0x9eb8, 0x9eb9, 0x9eba, 0xbbf0, 0xece1, 0xc3f0, 0x9ebb, 0xb5c6, /*0x68-0x6f*/ 0xbbd2, 0x9ebc, 0x9ebd, 0x9ebe, 0x9ebf, 0xc1e9, 0xd4ee, 0x9ec0, /*0x70-0x77*/ 0xbec4, 0x9ec1, 0x9ec2, 0x9ec3, 0xd7c6, 0x9ec4, 0xd4d6, 0xb2d3, /*0x78-0x7f*/ 0xecbe, 0x9ec5, 0x9ec6, 0x9ec7, 0x9ec8, 0xeac1, 0x9ec9, 0x9eca, /*0x80-0x87*/ 0x9ecb, 0xc2af, 0xb4b6, 0x9ecc, 0x9ecd, 0x9ece, 0xd1d7, 0x9ecf, /*0x88-0x8f*/ 0x9ed0, 0x9ed1, 0xb3b4, 0x9ed2, 0xc8b2, 0xbfbb, 0xecc0, 0x9ed3, /*0x90-0x97*/ 0x9ed4, 0xd6cb, 0x9ed5, 0x9ed6, 0xecbf, 0xecc1, 0x9ed7, 0x9ed8, /*0x98-0x9f*/ 0x9ed9, 0x9eda, 0x9edb, 0x9edc, 0x9edd, 0x9ede, 0x9edf, 0x9ee0, /*0xa0-0xa7*/ 0x9ee1, 0x9ee2, 0x9ee3, 0xecc5, 0xbee6, 0xccbf, 0xc5da, 0xbebc, /*0xa8-0xaf*/ 0x9ee4, 0xecc6, 0x9ee5, 0xb1fe, 0x9ee6, 0x9ee7, 0x9ee8, 0xecc4, /*0xb0-0xb7*/ 0xd5a8, 0xb5e3, 0x9ee9, 0xecc2, 0xc1b6, 0xb3e3, 0x9eea, 0x9eeb, /*0xb8-0xbf*/ 0xecc3, 0xcbb8, 0xc0c3, 0xccfe, 0x9eec, 0x9eed, 0x9eee, 0x9eef, /*0xc0-0xc7*/ 0xc1d2, 0x9ef0, 0xecc8, 0x9ef1, 0x9ef2, 0x9ef3, 0x9ef4, 0x9ef5, /*0xc8-0xcf*/ 0x9ef6, 0x9ef7, 0x9ef8, 0x9ef9, 0x9efa, 0x9efb, 0x9efc, 0x9efd, /*0xd0-0xd7*/ 0xbae6, 0xc0d3, 0x9efe, 0xd6f2, 0x9f40, 0x9f41, 0x9f42, 0xd1cc, /*0xd8-0xdf*/ 0x9f43, 0x9f44, 0x9f45, 0x9f46, 0xbfbe, 0x9f47, 0xb7b3, 0xc9d5, /*0xe0-0xe7*/ 0xecc7, 0xbbe2, 0x9f48, 0xcccc, 0xbdfd, 0xc8c8, 0x9f49, 0xcfa9, /*0xe8-0xef*/ 0x9f4a, 0x9f4b, 0x9f4c, 0x9f4d, 0x9f4e, 0x9f4f, 0x9f50, 0xcde9, /*0xf0-0xf7*/ 0x9f51, 0xc5eb, 0x9f52, 0x9f53, 0x9f54, 0xb7e9, 0x9f55, 0x9f56, /*0xf8-0xff*/ /* 0x7100 */ 0x9f57, 0x9f58, 0x9f59, 0x9f5a, 0x9f5b, 0x9f5c, 0x9f5d, 0x9f5e, /*0x00-0x07*/ 0x9f5f, 0xd1c9, 0xbab8, 0x9f60, 0x9f61, 0x9f62, 0x9f63, 0x9f64, /*0x08-0x0f*/ 0xecc9, 0x9f65, 0x9f66, 0xecca, 0x9f67, 0xbbc0, 0xeccb, 0x9f68, /*0x10-0x17*/ 0xece2, 0xb1ba, 0xb7d9, 0x9f69, 0x9f6a, 0x9f6b, 0x9f6c, 0x9f6d, /*0x18-0x1f*/ 0x9f6e, 0x9f6f, 0x9f70, 0x9f71, 0x9f72, 0x9f73, 0xbdb9, 0x9f74, /*0x20-0x27*/ 0x9f75, 0x9f76, 0x9f77, 0x9f78, 0x9f79, 0x9f7a, 0x9f7b, 0xeccc, /*0x28-0x2f*/ 0xd1e6, 0xeccd, 0x9f7c, 0x9f7d, 0x9f7e, 0x9f80, 0xc8bb, 0x9f81, /*0x30-0x37*/ 0x9f82, 0x9f83, 0x9f84, 0x9f85, 0x9f86, 0x9f87, 0x9f88, 0x9f89, /*0x38-0x3f*/ 0x9f8a, 0x9f8b, 0x9f8c, 0x9f8d, 0x9f8e, 0xecd1, 0x9f8f, 0x9f90, /*0x40-0x47*/ 0x9f91, 0x9f92, 0xecd3, 0x9f93, 0xbbcd, 0x9f94, 0xbce5, 0x9f95, /*0x48-0x4f*/ 0x9f96, 0x9f97, 0x9f98, 0x9f99, 0x9f9a, 0x9f9b, 0x9f9c, 0x9f9d, /*0x50-0x57*/ 0x9f9e, 0x9f9f, 0x9fa0, 0x9fa1, 0xeccf, 0x9fa2, 0xc9b7, 0x9fa3, /*0x58-0x5f*/ 0x9fa4, 0x9fa5, 0x9fa6, 0x9fa7, 0xc3ba, 0x9fa8, 0xece3, 0xd5d5, /*0x60-0x67*/ 0xecd0, 0x9fa9, 0x9faa, 0x9fab, 0x9fac, 0x9fad, 0xd6f3, 0x9fae, /*0x68-0x6f*/ 0x9faf, 0x9fb0, 0xecd2, 0xecce, 0x9fb1, 0x9fb2, 0x9fb3, 0x9fb4, /*0x70-0x77*/ 0xecd4, 0x9fb5, 0xecd5, 0x9fb6, 0x9fb7, 0xc9bf, 0x9fb8, 0x9fb9, /*0x78-0x7f*/ 0x9fba, 0x9fbb, 0x9fbc, 0x9fbd, 0xcfa8, 0x9fbe, 0x9fbf, 0x9fc0, /*0x80-0x87*/ 0x9fc1, 0x9fc2, 0xd0dc, 0x9fc3, 0x9fc4, 0x9fc5, 0x9fc6, 0xd1ac, /*0x88-0x8f*/ 0x9fc7, 0x9fc8, 0x9fc9, 0x9fca, 0xc8db, 0x9fcb, 0x9fcc, 0x9fcd, /*0x90-0x97*/ 0xecd6, 0xcef5, 0x9fce, 0x9fcf, 0x9fd0, 0x9fd1, 0x9fd2, 0xcaec, /*0x98-0x9f*/ 0xecda, 0x9fd3, 0x9fd4, 0x9fd5, 0x9fd6, 0x9fd7, 0x9fd8, 0x9fd9, /*0xa0-0xa7*/ 0xecd9, 0x9fda, 0x9fdb, 0x9fdc, 0xb0be, 0x9fdd, 0x9fde, 0x9fdf, /*0xa8-0xaf*/ 0x9fe0, 0x9fe1, 0x9fe2, 0xecd7, 0x9fe3, 0xecd8, 0x9fe4, 0x9fe5, /*0xb0-0xb7*/ 0x9fe6, 0xece4, 0x9fe7, 0x9fe8, 0x9fe9, 0x9fea, 0x9feb, 0x9fec, /*0xb8-0xbf*/ 0x9fed, 0x9fee, 0x9fef, 0xc8bc, 0x9ff0, 0x9ff1, 0x9ff2, 0x9ff3, /*0xc0-0xc7*/ 0x9ff4, 0x9ff5, 0x9ff6, 0x9ff7, 0x9ff8, 0x9ff9, 0xc1c7, 0x9ffa, /*0xc8-0xcf*/ 0x9ffb, 0x9ffc, 0x9ffd, 0x9ffe, 0xecdc, 0xd1e0, 0xa040, 0xa041, /*0xd0-0xd7*/ 0xa042, 0xa043, 0xa044, 0xa045, 0xa046, 0xa047, 0xa048, 0xa049, /*0xd8-0xdf*/ 0xecdb, 0xa04a, 0xa04b, 0xa04c, 0xa04d, 0xd4ef, 0xa04e, 0xecdd, /*0xe0-0xe7*/ 0xa04f, 0xa050, 0xa051, 0xa052, 0xa053, 0xa054, 0xdbc6, 0xa055, /*0xe8-0xef*/ 0xa056, 0xa057, 0xa058, 0xa059, 0xa05a, 0xa05b, 0xa05c, 0xa05d, /*0xf0-0xf7*/ 0xa05e, 0xecde, 0xa05f, 0xa060, 0xa061, 0xa062, 0xa063, 0xa064, /*0xf8-0xff*/ /* 0x7200 */ 0xa065, 0xa066, 0xa067, 0xa068, 0xa069, 0xa06a, 0xb1ac, 0xa06b, /*0x00-0x07*/ 0xa06c, 0xa06d, 0xa06e, 0xa06f, 0xa070, 0xa071, 0xa072, 0xa073, /*0x08-0x0f*/ 0xa074, 0xa075, 0xa076, 0xa077, 0xa078, 0xa079, 0xa07a, 0xa07b, /*0x10-0x17*/ 0xa07c, 0xa07d, 0xa07e, 0xa080, 0xa081, 0xecdf, 0xa082, 0xa083, /*0x18-0x1f*/ 0xa084, 0xa085, 0xa086, 0xa087, 0xa088, 0xa089, 0xa08a, 0xa08b, /*0x20-0x27*/ 0xece0, 0xa08c, 0xd7a6, 0xa08d, 0xc5c0, 0xa08e, 0xa08f, 0xa090, /*0x28-0x2f*/ 0xebbc, 0xb0ae, 0xa091, 0xa092, 0xa093, 0xbef4, 0xb8b8, 0xd2af, /*0x30-0x37*/ 0xb0d6, 0xb5f9, 0xa094, 0xd8b3, 0xa095, 0xcbac, 0xa096, 0xe3dd, /*0x38-0x3f*/ 0xa097, 0xa098, 0xa099, 0xa09a, 0xa09b, 0xa09c, 0xa09d, 0xc6ac, /*0x40-0x47*/ 0xb0e6, 0xa09e, 0xa09f, 0xa0a0, 0xc5c6, 0xebb9, 0xa0a1, 0xa0a2, /*0x48-0x4f*/ 0xa0a3, 0xa0a4, 0xebba, 0xa0a5, 0xa0a6, 0xa0a7, 0xebbb, 0xa0a8, /*0x50-0x57*/ 0xa0a9, 0xd1c0, 0xa0aa, 0xc5a3, 0xa0ab, 0xeaf2, 0xa0ac, 0xc4b2, /*0x58-0x5f*/ 0xa0ad, 0xc4b5, 0xc0ce, 0xa0ae, 0xa0af, 0xa0b0, 0xeaf3, 0xc4c1, /*0x60-0x67*/ 0xa0b1, 0xceef, 0xa0b2, 0xa0b3, 0xa0b4, 0xa0b5, 0xeaf0, 0xeaf4, /*0x68-0x6f*/ 0xa0b6, 0xa0b7, 0xc9fc, 0xa0b8, 0xa0b9, 0xc7a3, 0xa0ba, 0xa0bb, /*0x70-0x77*/ 0xa0bc, 0xccd8, 0xcefe, 0xa0bd, 0xa0be, 0xa0bf, 0xeaf5, 0xeaf6, /*0x78-0x7f*/ 0xcfac, 0xc0e7, 0xa0c0, 0xa0c1, 0xeaf7, 0xa0c2, 0xa0c3, 0xa0c4, /*0x80-0x87*/ 0xa0c5, 0xa0c6, 0xb6bf, 0xeaf8, 0xa0c7, 0xeaf9, 0xa0c8, 0xeafa, /*0x88-0x8f*/ 0xa0c9, 0xa0ca, 0xeafb, 0xa0cb, 0xa0cc, 0xa0cd, 0xa0ce, 0xa0cf, /*0x90-0x97*/ 0xa0d0, 0xa0d1, 0xa0d2, 0xa0d3, 0xa0d4, 0xa0d5, 0xa0d6, 0xeaf1, /*0x98-0x9f*/ 0xa0d7, 0xa0d8, 0xa0d9, 0xa0da, 0xa0db, 0xa0dc, 0xa0dd, 0xa0de, /*0xa0-0xa7*/ 0xa0df, 0xa0e0, 0xa0e1, 0xa0e2, 0xc8ae, 0xe1eb, 0xa0e3, 0xb7b8, /*0xa8-0xaf*/ 0xe1ec, 0xa0e4, 0xa0e5, 0xa0e6, 0xe1ed, 0xa0e7, 0xd7b4, 0xe1ee, /*0xb0-0xb7*/ 0xe1ef, 0xd3cc, 0xa0e8, 0xa0e9, 0xa0ea, 0xa0eb, 0xa0ec, 0xa0ed, /*0xb8-0xbf*/ 0xa0ee, 0xe1f1, 0xbff1, 0xe1f0, 0xb5d2, 0xa0ef, 0xa0f0, 0xa0f1, /*0xc0-0xc7*/ 0xb1b7, 0xa0f2, 0xa0f3, 0xa0f4, 0xa0f5, 0xe1f3, 0xe1f2, 0xa0f6, /*0xc8-0xcf*/ 0xbafc, 0xa0f7, 0xe1f4, 0xa0f8, 0xa0f9, 0xa0fa, 0xa0fb, 0xb9b7, /*0xd0-0xd7*/ 0xa0fc, 0xbed1, 0xa0fd, 0xa0fe, 0xaa40, 0xaa41, 0xc4fc, 0xaa42, /*0xd8-0xdf*/ 0xbadd, 0xbdc6, 0xaa43, 0xaa44, 0xaa45, 0xaa46, 0xaa47, 0xaa48, /*0xe0-0xe7*/ 0xe1f5, 0xe1f7, 0xaa49, 0xaa4a, 0xb6c0, 0xcfc1, 0xcaa8, 0xe1f6, /*0xe8-0xef*/ 0xd5f8, 0xd3fc, 0xe1f8, 0xe1fc, 0xe1f9, 0xaa4b, 0xaa4c, 0xe1fa, /*0xf0-0xf7*/ 0xc0ea, 0xaa4d, 0xe1fe, 0xe2a1, 0xc0c7, 0xaa4e, 0xaa4f, 0xaa50, /*0xf8-0xff*/ /* 0x7300 */ 0xaa51, 0xe1fb, 0xaa52, 0xe1fd, 0xaa53, 0xaa54, 0xaa55, 0xaa56, /*0x00-0x07*/ 0xaa57, 0xaa58, 0xe2a5, 0xaa59, 0xaa5a, 0xaa5b, 0xc1d4, 0xaa5c, /*0x08-0x0f*/ 0xaa5d, 0xaa5e, 0xaa5f, 0xe2a3, 0xaa60, 0xe2a8, 0xb2fe, 0xe2a2, /*0x10-0x17*/ 0xaa61, 0xaa62, 0xaa63, 0xc3cd, 0xb2c2, 0xe2a7, 0xe2a6, 0xaa64, /*0x18-0x1f*/ 0xaa65, 0xe2a4, 0xe2a9, 0xaa66, 0xaa67, 0xe2ab, 0xaa68, 0xaa69, /*0x20-0x27*/ 0xaa6a, 0xd0c9, 0xd6ed, 0xc3a8, 0xe2ac, 0xaa6b, 0xcfd7, 0xaa6c, /*0x28-0x2f*/ 0xaa6d, 0xe2ae, 0xaa6e, 0xaa6f, 0xbaef, 0xaa70, 0xaa71, 0xe9e0, /*0x30-0x37*/ 0xe2ad, 0xe2aa, 0xaa72, 0xaa73, 0xaa74, 0xaa75, 0xbbab, 0xd4b3, /*0x38-0x3f*/ 0xaa76, 0xaa77, 0xaa78, 0xaa79, 0xaa7a, 0xaa7b, 0xaa7c, 0xaa7d, /*0x40-0x47*/ 0xaa7e, 0xaa80, 0xaa81, 0xaa82, 0xaa83, 0xe2b0, 0xaa84, 0xaa85, /*0x48-0x4f*/ 0xe2af, 0xaa86, 0xe9e1, 0xaa87, 0xaa88, 0xaa89, 0xaa8a, 0xe2b1, /*0x50-0x57*/ 0xaa8b, 0xaa8c, 0xaa8d, 0xaa8e, 0xaa8f, 0xaa90, 0xaa91, 0xaa92, /*0x58-0x5f*/ 0xe2b2, 0xaa93, 0xaa94, 0xaa95, 0xaa96, 0xaa97, 0xaa98, 0xaa99, /*0x60-0x67*/ 0xaa9a, 0xaa9b, 0xaa9c, 0xaa9d, 0xe2b3, 0xcca1, 0xaa9e, 0xe2b4, /*0x68-0x6f*/ 0xaa9f, 0xaaa0, 0xab40, 0xab41, 0xab42, 0xab43, 0xab44, 0xab45, /*0x70-0x77*/ 0xab46, 0xab47, 0xab48, 0xab49, 0xab4a, 0xab4b, 0xe2b5, 0xab4c, /*0x78-0x7f*/ 0xab4d, 0xab4e, 0xab4f, 0xab50, 0xd0fe, 0xab51, 0xab52, 0xc2ca, /*0x80-0x87*/ 0xab53, 0xd3f1, 0xab54, 0xcdf5, 0xab55, 0xab56, 0xe7e0, 0xab57, /*0x88-0x8f*/ 0xab58, 0xe7e1, 0xab59, 0xab5a, 0xab5b, 0xab5c, 0xbec1, 0xab5d, /*0x90-0x97*/ 0xab5e, 0xab5f, 0xab60, 0xc2ea, 0xab61, 0xab62, 0xab63, 0xe7e4, /*0x98-0x9f*/ 0xab64, 0xab65, 0xe7e3, 0xab66, 0xab67, 0xab68, 0xab69, 0xab6a, /*0xa0-0xa7*/ 0xab6b, 0xcde6, 0xab6c, 0xc3b5, 0xab6d, 0xab6e, 0xe7e2, 0xbbb7, /*0xa8-0xaf*/ 0xcfd6, 0xab6f, 0xc1e1, 0xe7e9, 0xab70, 0xab71, 0xab72, 0xe7e8, /*0xb0-0xb7*/ 0xab73, 0xab74, 0xe7f4, 0xb2a3, 0xab75, 0xab76, 0xab77, 0xab78, /*0xb8-0xbf*/ 0xe7ea, 0xab79, 0xe7e6, 0xab7a, 0xab7b, 0xab7c, 0xab7d, 0xab7e, /*0xc0-0xc7*/ 0xe7ec, 0xe7eb, 0xc9ba, 0xab80, 0xab81, 0xd5e4, 0xab82, 0xe7e5, /*0xc8-0xcf*/ 0xb7a9, 0xe7e7, 0xab83, 0xab84, 0xab85, 0xab86, 0xab87, 0xab88, /*0xd0-0xd7*/ 0xab89, 0xe7ee, 0xab8a, 0xab8b, 0xab8c, 0xab8d, 0xe7f3, 0xab8e, /*0xd8-0xdf*/ 0xd6e9, 0xab8f, 0xab90, 0xab91, 0xab92, 0xe7ed, 0xab93, 0xe7f2, /*0xe0-0xe7*/ 0xab94, 0xe7f1, 0xab95, 0xab96, 0xab97, 0xb0e0, 0xab98, 0xab99, /*0xe8-0xef*/ 0xab9a, 0xab9b, 0xe7f5, 0xab9c, 0xab9d, 0xab9e, 0xab9f, 0xaba0, /*0xf0-0xf7*/ 0xac40, 0xac41, 0xac42, 0xac43, 0xac44, 0xac45, 0xac46, 0xac47, /*0xf8-0xff*/ /* 0x7400 */ 0xac48, 0xac49, 0xac4a, 0xc7f2, 0xac4b, 0xc0c5, 0xc0ed, 0xac4c, /*0x00-0x07*/ 0xac4d, 0xc1f0, 0xe7f0, 0xac4e, 0xac4f, 0xac50, 0xac51, 0xe7f6, /*0x08-0x0f*/ 0xcbf6, 0xac52, 0xac53, 0xac54, 0xac55, 0xac56, 0xac57, 0xac58, /*0x10-0x17*/ 0xac59, 0xac5a, 0xe8a2, 0xe8a1, 0xac5b, 0xac5c, 0xac5d, 0xac5e, /*0x18-0x1f*/ 0xac5f, 0xac60, 0xd7c1, 0xac61, 0xac62, 0xe7fa, 0xe7f9, 0xac63, /*0x20-0x27*/ 0xe7fb, 0xac64, 0xe7f7, 0xac65, 0xe7fe, 0xac66, 0xe7fd, 0xac67, /*0x28-0x2f*/ 0xe7fc, 0xac68, 0xac69, 0xc1d5, 0xc7d9, 0xc5fd, 0xc5c3, 0xac6a, /*0x30-0x37*/ 0xac6b, 0xac6c, 0xac6d, 0xac6e, 0xc7ed, 0xac6f, 0xac70, 0xac71, /*0x38-0x3f*/ 0xac72, 0xe8a3, 0xac73, 0xac74, 0xac75, 0xac76, 0xac77, 0xac78, /*0x40-0x47*/ 0xac79, 0xac7a, 0xac7b, 0xac7c, 0xac7d, 0xac7e, 0xac80, 0xac81, /*0x48-0x4f*/ 0xac82, 0xac83, 0xac84, 0xac85, 0xac86, 0xe8a6, 0xac87, 0xe8a5, /*0x50-0x57*/ 0xac88, 0xe8a7, 0xbaf7, 0xe7f8, 0xe8a4, 0xac89, 0xc8f0, 0xc9aa, /*0x58-0x5f*/ 0xac8a, 0xac8b, 0xac8c, 0xac8d, 0xac8e, 0xac8f, 0xac90, 0xac91, /*0x60-0x67*/ 0xac92, 0xac93, 0xac94, 0xac95, 0xac96, 0xe8a9, 0xac97, 0xac98, /*0x68-0x6f*/ 0xb9e5, 0xac99, 0xac9a, 0xac9b, 0xac9c, 0xac9d, 0xd1fe, 0xe8a8, /*0x70-0x77*/ 0xac9e, 0xac9f, 0xaca0, 0xad40, 0xad41, 0xad42, 0xe8aa, 0xad43, /*0x78-0x7f*/ 0xe8ad, 0xe8ae, 0xad44, 0xc1a7, 0xad45, 0xad46, 0xad47, 0xe8af, /*0x80-0x87*/ 0xad48, 0xad49, 0xad4a, 0xe8b0, 0xad4b, 0xad4c, 0xe8ac, 0xad4d, /*0x88-0x8f*/ 0xe8b4, 0xad4e, 0xad4f, 0xad50, 0xad51, 0xad52, 0xad53, 0xad54, /*0x90-0x97*/ 0xad55, 0xad56, 0xad57, 0xad58, 0xe8ab, 0xad59, 0xe8b1, 0xad5a, /*0x98-0x9f*/ 0xad5b, 0xad5c, 0xad5d, 0xad5e, 0xad5f, 0xad60, 0xad61, 0xe8b5, /*0xa0-0xa7*/ 0xe8b2, 0xe8b3, 0xad62, 0xad63, 0xad64, 0xad65, 0xad66, 0xad67, /*0xa8-0xaf*/ 0xad68, 0xad69, 0xad6a, 0xad6b, 0xad6c, 0xad6d, 0xad6e, 0xad6f, /*0xb0-0xb7*/ 0xad70, 0xad71, 0xe8b7, 0xad72, 0xad73, 0xad74, 0xad75, 0xad76, /*0xb8-0xbf*/ 0xad77, 0xad78, 0xad79, 0xad7a, 0xad7b, 0xad7c, 0xad7d, 0xad7e, /*0xc0-0xc7*/ 0xad80, 0xad81, 0xad82, 0xad83, 0xad84, 0xad85, 0xad86, 0xad87, /*0xc8-0xcf*/ 0xad88, 0xad89, 0xe8b6, 0xad8a, 0xad8b, 0xad8c, 0xad8d, 0xad8e, /*0xd0-0xd7*/ 0xad8f, 0xad90, 0xad91, 0xad92, 0xb9cf, 0xad93, 0xf0ac, 0xad94, /*0xd8-0xdf*/ 0xf0ad, 0xad95, 0xc6b0, 0xb0ea, 0xc8bf, 0xad96, 0xcddf, 0xad97, /*0xe0-0xe7*/ 0xad98, 0xad99, 0xad9a, 0xad9b, 0xad9c, 0xad9d, 0xcecd, 0xeab1, /*0xe8-0xef*/ 0xad9e, 0xad9f, 0xada0, 0xae40, 0xeab2, 0xae41, 0xc6bf, 0xb4c9, /*0xf0-0xf7*/ 0xae42, 0xae43, 0xae44, 0xae45, 0xae46, 0xae47, 0xae48, 0xeab3, /*0xf8-0xff*/ /* 0x7500 */ 0xae49, 0xae4a, 0xae4b, 0xae4c, 0xd5e7, 0xae4d, 0xae4e, 0xae4f, /*0x00-0x07*/ 0xae50, 0xae51, 0xae52, 0xae53, 0xae54, 0xddf9, 0xae55, 0xeab4, /*0x08-0x0f*/ 0xae56, 0xeab5, 0xae57, 0xeab6, 0xae58, 0xae59, 0xae5a, 0xae5b, /*0x10-0x17*/ 0xb8ca, 0xdfb0, 0xc9f5, 0xae5c, 0xccf0, 0xae5d, 0xae5e, 0xc9fa, /*0x18-0x1f*/ 0xae5f, 0xae60, 0xae61, 0xae62, 0xae63, 0xc9fb, 0xae64, 0xae65, /*0x20-0x27*/ 0xd3c3, 0xcba6, 0xae66, 0xb8a6, 0xf0ae, 0xb1c2, 0xae67, 0xe5b8, /*0x28-0x2f*/ 0xccef, 0xd3c9, 0xbcd7, 0xc9ea, 0xae68, 0xb5e7, 0xae69, 0xc4d0, /*0x30-0x37*/ 0xb5e9, 0xae6a, 0xeeae, 0xbbad, 0xae6b, 0xae6c, 0xe7de, 0xae6d, /*0x38-0x3f*/ 0xeeaf, 0xae6e, 0xae6f, 0xae70, 0xae71, 0xb3a9, 0xae72, 0xae73, /*0x40-0x47*/ 0xeeb2, 0xae74, 0xae75, 0xeeb1, 0xbde7, 0xae76, 0xeeb0, 0xceb7, /*0x48-0x4f*/ 0xae77, 0xae78, 0xae79, 0xae7a, 0xc5cf, 0xae7b, 0xae7c, 0xae7d, /*0x50-0x57*/ 0xae7e, 0xc1f4, 0xdbce, 0xeeb3, 0xd0f3, 0xae80, 0xae81, 0xae82, /*0x58-0x5f*/ 0xae83, 0xae84, 0xae85, 0xae86, 0xae87, 0xc2d4, 0xc6e8, 0xae88, /*0x60-0x67*/ 0xae89, 0xae8a, 0xb7ac, 0xae8b, 0xae8c, 0xae8d, 0xae8e, 0xae8f, /*0x68-0x6f*/ 0xae90, 0xae91, 0xeeb4, 0xae92, 0xb3eb, 0xae93, 0xae94, 0xae95, /*0x70-0x77*/ 0xbbfb, 0xeeb5, 0xae96, 0xae97, 0xae98, 0xae99, 0xae9a, 0xe7dc, /*0x78-0x7f*/ 0xae9b, 0xae9c, 0xae9d, 0xeeb6, 0xae9e, 0xae9f, 0xbdae, 0xaea0, /*0x80-0x87*/ 0xaf40, 0xaf41, 0xaf42, 0xf1e2, 0xaf43, 0xaf44, 0xaf45, 0xcae8, /*0x88-0x8f*/ 0xaf46, 0xd2c9, 0xf0da, 0xaf47, 0xf0db, 0xaf48, 0xf0dc, 0xc1c6, /*0x90-0x97*/ 0xaf49, 0xb8ed, 0xbece, 0xaf4a, 0xaf4b, 0xf0de, 0xaf4c, 0xc5b1, /*0x98-0x9f*/ 0xf0dd, 0xd1f1, 0xaf4d, 0xf0e0, 0xb0cc, 0xbdea, 0xaf4e, 0xaf4f, /*0xa0-0xa7*/ 0xaf50, 0xaf51, 0xaf52, 0xd2df, 0xf0df, 0xaf53, 0xb4af, 0xb7e8, /*0xa8-0xaf*/ 0xf0e6, 0xf0e5, 0xc6a3, 0xf0e1, 0xf0e2, 0xb4c3, 0xaf54, 0xaf55, /*0xb0-0xb7*/ 0xf0e3, 0xd5ee, 0xaf56, 0xaf57, 0xccdb, 0xbed2, 0xbcb2, 0xaf58, /*0xb8-0xbf*/ 0xaf59, 0xaf5a, 0xf0e8, 0xf0e7, 0xf0e4, 0xb2a1, 0xaf5b, 0xd6a2, /*0xc0-0xc7*/ 0xd3b8, 0xbeb7, 0xc8ac, 0xaf5c, 0xaf5d, 0xf0ea, 0xaf5e, 0xaf5f, /*0xc8-0xcf*/ 0xaf60, 0xaf61, 0xd1f7, 0xaf62, 0xd6cc, 0xbadb, 0xf0e9, 0xaf63, /*0xd0-0xd7*/ 0xb6bb, 0xaf64, 0xaf65, 0xcdb4, 0xaf66, 0xaf67, 0xc6a6, 0xaf68, /*0xd8-0xdf*/ 0xaf69, 0xaf6a, 0xc1a1, 0xf0eb, 0xf0ee, 0xaf6b, 0xf0ed, 0xf0f0, /*0xe0-0xe7*/ 0xf0ec, 0xaf6c, 0xbbbe, 0xf0ef, 0xaf6d, 0xaf6e, 0xaf6f, 0xaf70, /*0xe8-0xef*/ 0xccb5, 0xf0f2, 0xaf71, 0xaf72, 0xb3d5, 0xaf73, 0xaf74, 0xaf75, /*0xf0-0xf7*/ 0xaf76, 0xb1d4, 0xaf77, 0xaf78, 0xf0f3, 0xaf79, 0xaf7a, 0xf0f4, /*0xf8-0xff*/ /* 0x7600 */ 0xf0f6, 0xb4e1, 0xaf7b, 0xf0f1, 0xaf7c, 0xf0f7, 0xaf7d, 0xaf7e, /*0x00-0x07*/ 0xaf80, 0xaf81, 0xf0fa, 0xaf82, 0xf0f8, 0xaf83, 0xaf84, 0xaf85, /*0x08-0x0f*/ 0xf0f5, 0xaf86, 0xaf87, 0xaf88, 0xaf89, 0xf0fd, 0xaf8a, 0xf0f9, /*0x10-0x17*/ 0xf0fc, 0xf0fe, 0xaf8b, 0xf1a1, 0xaf8c, 0xaf8d, 0xaf8e, 0xcec1, /*0x18-0x1f*/ 0xf1a4, 0xaf8f, 0xf1a3, 0xaf90, 0xc1f6, 0xf0fb, 0xcadd, 0xaf91, /*0x20-0x27*/ 0xaf92, 0xb4f1, 0xb1f1, 0xccb1, 0xaf93, 0xf1a6, 0xaf94, 0xaf95, /*0x28-0x2f*/ 0xf1a7, 0xaf96, 0xaf97, 0xf1ac, 0xd5ce, 0xf1a9, 0xaf98, 0xaf99, /*0x30-0x37*/ 0xc8b3, 0xaf9a, 0xaf9b, 0xaf9c, 0xf1a2, 0xaf9d, 0xf1ab, 0xf1a8, /*0x38-0x3f*/ 0xf1a5, 0xaf9e, 0xaf9f, 0xf1aa, 0xafa0, 0xb040, 0xb041, 0xb042, /*0x40-0x47*/ 0xb043, 0xb044, 0xb045, 0xb046, 0xb0a9, 0xf1ad, 0xb047, 0xb048, /*0x48-0x4f*/ 0xb049, 0xb04a, 0xb04b, 0xb04c, 0xf1af, 0xb04d, 0xf1b1, 0xb04e, /*0x50-0x57*/ 0xb04f, 0xb050, 0xb051, 0xb052, 0xf1b0, 0xb053, 0xf1ae, 0xb054, /*0x58-0x5f*/ 0xb055, 0xb056, 0xb057, 0xd1a2, 0xb058, 0xb059, 0xb05a, 0xb05b, /*0x60-0x67*/ 0xb05c, 0xb05d, 0xb05e, 0xf1b2, 0xb05f, 0xb060, 0xb061, 0xf1b3, /*0x68-0x6f*/ 0xb062, 0xb063, 0xb064, 0xb065, 0xb066, 0xb067, 0xb068, 0xb069, /*0x70-0x77*/ 0xb9ef, 0xb06a, 0xb06b, 0xb5c7, 0xb06c, 0xb0d7, 0xb0d9, 0xb06d, /*0x78-0x7f*/ 0xb06e, 0xb06f, 0xd4ed, 0xb070, 0xb5c4, 0xb071, 0xbdd4, 0xbbca, /*0x80-0x87*/ 0xf0a7, 0xb072, 0xb073, 0xb8de, 0xb074, 0xb075, 0xf0a8, 0xb076, /*0x88-0x8f*/ 0xb077, 0xb0a8, 0xb078, 0xf0a9, 0xb079, 0xb07a, 0xcdee, 0xb07b, /*0x90-0x97*/ 0xb07c, 0xf0aa, 0xb07d, 0xb07e, 0xb080, 0xb081, 0xb082, 0xb083, /*0x98-0x9f*/ 0xb084, 0xb085, 0xb086, 0xb087, 0xf0ab, 0xb088, 0xb089, 0xb08a, /*0xa0-0xa7*/ 0xb08b, 0xb08c, 0xb08d, 0xb08e, 0xb08f, 0xb090, 0xc6a4, 0xb091, /*0xa8-0xaf*/ 0xb092, 0xd6e5, 0xf1e4, 0xb093, 0xf1e5, 0xb094, 0xb095, 0xb096, /*0xb0-0xb7*/ 0xb097, 0xb098, 0xb099, 0xb09a, 0xb09b, 0xb09c, 0xb09d, 0xc3f3, /*0xb8-0xbf*/ 0xb09e, 0xb09f, 0xd3db, 0xb0a0, 0xb140, 0xd6d1, 0xc5e8, 0xb141, /*0xc0-0xc7*/ 0xd3af, 0xb142, 0xd2e6, 0xb143, 0xb144, 0xeec1, 0xb0bb, 0xd5b5, /*0xc8-0xcf*/ 0xd1ce, 0xbce0, 0xbad0, 0xb145, 0xbff8, 0xb146, 0xb8c7, 0xb5c1, /*0xd0-0xd7*/ 0xc5cc, 0xb147, 0xb148, 0xcaa2, 0xb149, 0xb14a, 0xb14b, 0xc3cb, /*0xd8-0xdf*/ 0xb14c, 0xb14d, 0xb14e, 0xb14f, 0xb150, 0xeec2, 0xb151, 0xb152, /*0xe0-0xe7*/ 0xb153, 0xb154, 0xb155, 0xb156, 0xb157, 0xb158, 0xc4bf, 0xb6a2, /*0xe8-0xef*/ 0xb159, 0xedec, 0xc3a4, 0xb15a, 0xd6b1, 0xb15b, 0xb15c, 0xb15d, /*0xf0-0xf7*/ 0xcfe0, 0xedef, 0xb15e, 0xb15f, 0xc5ce, 0xb160, 0xb6dc, 0xb161, /*0xf8-0xff*/ /* 0x7700 */ 0xb162, 0xcaa1, 0xb163, 0xb164, 0xeded, 0xb165, 0xb166, 0xedf0, /*0x00-0x07*/ 0xedf1, 0xc3bc, 0xb167, 0xbfb4, 0xb168, 0xedee, 0xb169, 0xb16a, /*0x08-0x0f*/ 0xb16b, 0xb16c, 0xb16d, 0xb16e, 0xb16f, 0xb170, 0xb171, 0xb172, /*0x10-0x17*/ 0xb173, 0xedf4, 0xedf2, 0xb174, 0xb175, 0xb176, 0xb177, 0xd5e6, /*0x18-0x1f*/ 0xc3df, 0xb178, 0xedf3, 0xb179, 0xb17a, 0xb17b, 0xedf6, 0xb17c, /*0x20-0x27*/ 0xd5a3, 0xd1a3, 0xb17d, 0xb17e, 0xb180, 0xedf5, 0xb181, 0xc3d0, /*0x28-0x2f*/ 0xb182, 0xb183, 0xb184, 0xb185, 0xb186, 0xedf7, 0xbff4, 0xbeec, /*0x30-0x37*/ 0xedf8, 0xb187, 0xccf7, 0xb188, 0xd1db, 0xb189, 0xb18a, 0xb18b, /*0x38-0x3f*/ 0xd7c5, 0xd5f6, 0xb18c, 0xedfc, 0xb18d, 0xb18e, 0xb18f, 0xedfb, /*0x40-0x47*/ 0xb190, 0xb191, 0xb192, 0xb193, 0xb194, 0xb195, 0xb196, 0xb197, /*0x48-0x4f*/ 0xedf9, 0xedfa, 0xb198, 0xb199, 0xb19a, 0xb19b, 0xb19c, 0xb19d, /*0x50-0x57*/ 0xb19e, 0xb19f, 0xedfd, 0xbea6, 0xb1a0, 0xb240, 0xb241, 0xb242, /*0x58-0x5f*/ 0xb243, 0xcbaf, 0xeea1, 0xb6bd, 0xb244, 0xeea2, 0xc4c0, 0xb245, /*0x60-0x67*/ 0xedfe, 0xb246, 0xb247, 0xbdde, 0xb2c7, 0xb248, 0xb249, 0xb24a, /*0x68-0x6f*/ 0xb24b, 0xb24c, 0xb24d, 0xb24e, 0xb24f, 0xb250, 0xb251, 0xb252, /*0x70-0x77*/ 0xb253, 0xb6c3, 0xb254, 0xb255, 0xb256, 0xeea5, 0xd8ba, 0xeea3, /*0x78-0x7f*/ 0xeea6, 0xb257, 0xb258, 0xb259, 0xc3e9, 0xb3f2, 0xb25a, 0xb25b, /*0x80-0x87*/ 0xb25c, 0xb25d, 0xb25e, 0xb25f, 0xeea7, 0xeea4, 0xcfb9, 0xb260, /*0x88-0x8f*/ 0xb261, 0xeea8, 0xc2f7, 0xb262, 0xb263, 0xb264, 0xb265, 0xb266, /*0x90-0x97*/ 0xb267, 0xb268, 0xb269, 0xb26a, 0xb26b, 0xb26c, 0xb26d, 0xeea9, /*0x98-0x9f*/ 0xeeaa, 0xb26e, 0xdeab, 0xb26f, 0xb270, 0xc6b3, 0xb271, 0xc7c6, /*0xa0-0xa7*/ 0xb272, 0xd6f5, 0xb5c9, 0xb273, 0xcbb2, 0xb274, 0xb275, 0xb276, /*0xa8-0xaf*/ 0xeeab, 0xb277, 0xb278, 0xcdab, 0xb279, 0xeeac, 0xb27a, 0xb27b, /*0xb0-0xb7*/ 0xb27c, 0xb27d, 0xb27e, 0xd5b0, 0xb280, 0xeead, 0xb281, 0xf6c4, /*0xb8-0xbf*/ 0xb282, 0xb283, 0xb284, 0xb285, 0xb286, 0xb287, 0xb288, 0xb289, /*0xc0-0xc7*/ 0xb28a, 0xb28b, 0xb28c, 0xb28d, 0xb28e, 0xdbc7, 0xb28f, 0xb290, /*0xc8-0xcf*/ 0xb291, 0xb292, 0xb293, 0xb294, 0xb295, 0xb296, 0xb297, 0xb4a3, /*0xd0-0xd7*/ 0xb298, 0xb299, 0xb29a, 0xc3ac, 0xf1e6, 0xb29b, 0xb29c, 0xb29d, /*0xd8-0xdf*/ 0xb29e, 0xb29f, 0xcab8, 0xd2d3, 0xb2a0, 0xd6aa, 0xb340, 0xeff2, /*0xe0-0xe7*/ 0xb341, 0xbed8, 0xb342, 0xbdc3, 0xeff3, 0xb6cc, 0xb0ab, 0xb343, /*0xe8-0xef*/ 0xb344, 0xb345, 0xb346, 0xcaaf, 0xb347, 0xb348, 0xedb6, 0xb349, /*0xf0-0xf7*/ 0xedb7, 0xb34a, 0xb34b, 0xb34c, 0xb34d, 0xcef9, 0xb7af, 0xbff3, /*0xf8-0xff*/ /* 0x7800 */ 0xedb8, 0xc2eb, 0xc9b0, 0xb34e, 0xb34f, 0xb350, 0xb351, 0xb352, /*0x00-0x07*/ 0xb353, 0xedb9, 0xb354, 0xb355, 0xc6f6, 0xbfb3, 0xb356, 0xb357, /*0x08-0x0f*/ 0xb358, 0xedbc, 0xc5f8, 0xb359, 0xd1d0, 0xb35a, 0xd7a9, 0xedba, /*0x10-0x17*/ 0xedbb, 0xb35b, 0xd1e2, 0xb35c, 0xedbf, 0xedc0, 0xb35d, 0xedc4, /*0x18-0x1f*/ 0xb35e, 0xb35f, 0xb360, 0xedc8, 0xb361, 0xedc6, 0xedce, 0xd5e8, /*0x20-0x27*/ 0xb362, 0xedc9, 0xb363, 0xb364, 0xedc7, 0xedbe, 0xb365, 0xb366, /*0x28-0x2f*/ 0xc5e9, 0xb367, 0xb368, 0xb369, 0xc6c6, 0xb36a, 0xb36b, 0xc9e9, /*0x30-0x37*/ 0xd4d2, 0xedc1, 0xedc2, 0xedc3, 0xedc5, 0xb36c, 0xc0f9, 0xb36d, /*0x38-0x3f*/ 0xb4a1, 0xb36e, 0xb36f, 0xb370, 0xb371, 0xb9e8, 0xb372, 0xedd0, /*0x40-0x47*/ 0xb373, 0xb374, 0xb375, 0xb376, 0xedd1, 0xb377, 0xedca, 0xb378, /*0x48-0x4f*/ 0xedcf, 0xb379, 0xcef8, 0xb37a, 0xb37b, 0xcbb6, 0xedcc, 0xedcd, /*0x50-0x57*/ 0xb37c, 0xb37d, 0xb37e, 0xb380, 0xb381, 0xcff5, 0xb382, 0xb383, /*0x58-0x5f*/ 0xb384, 0xb385, 0xb386, 0xb387, 0xb388, 0xb389, 0xb38a, 0xb38b, /*0x60-0x67*/ 0xb38c, 0xb38d, 0xedd2, 0xc1f2, 0xd3b2, 0xedcb, 0xc8b7, 0xb38e, /*0x68-0x6f*/ 0xb38f, 0xb390, 0xb391, 0xb392, 0xb393, 0xb394, 0xb395, 0xbcef, /*0x70-0x77*/ 0xb396, 0xb397, 0xb398, 0xb399, 0xc5f0, 0xb39a, 0xb39b, 0xb39c, /*0x78-0x7f*/ 0xb39d, 0xb39e, 0xb39f, 0xb3a0, 0xb440, 0xb441, 0xb442, 0xedd6, /*0x80-0x87*/ 0xb443, 0xb5ef, 0xb444, 0xb445, 0xc2b5, 0xb0ad, 0xcbe9, 0xb446, /*0x88-0x8f*/ 0xb447, 0xb1ae, 0xb448, 0xedd4, 0xb449, 0xb44a, 0xb44b, 0xcdeb, /*0x90-0x97*/ 0xb5e2, 0xb44c, 0xedd5, 0xedd3, 0xedd7, 0xb44d, 0xb44e, 0xb5fa, /*0x98-0x9f*/ 0xb44f, 0xedd8, 0xb450, 0xedd9, 0xb451, 0xeddc, 0xb452, 0xb1cc, /*0xa0-0xa7*/ 0xb453, 0xb454, 0xb455, 0xb456, 0xb457, 0xb458, 0xb459, 0xb45a, /*0xa8-0xaf*/ 0xc5f6, 0xbcee, 0xedda, 0xccbc, 0xb2ea, 0xb45b, 0xb45c, 0xb45d, /*0xb0-0xb7*/ 0xb45e, 0xeddb, 0xb45f, 0xb460, 0xb461, 0xb462, 0xc4eb, 0xb463, /*0xb8-0xbf*/ 0xb464, 0xb4c5, 0xb465, 0xb466, 0xb467, 0xb0f5, 0xb468, 0xb469, /*0xc0-0xc7*/ 0xb46a, 0xeddf, 0xc0da, 0xb4e8, 0xb46b, 0xb46c, 0xb46d, 0xb46e, /*0xc8-0xcf*/ 0xc5cd, 0xb46f, 0xb470, 0xb471, 0xeddd, 0xbfc4, 0xb472, 0xb473, /*0xd0-0xd7*/ 0xb474, 0xedde, 0xb475, 0xb476, 0xb477, 0xb478, 0xb479, 0xb47a, /*0xd8-0xdf*/ 0xb47b, 0xb47c, 0xb47d, 0xb47e, 0xb480, 0xb481, 0xb482, 0xb483, /*0xe0-0xe7*/ 0xc4a5, 0xb484, 0xb485, 0xb486, 0xede0, 0xb487, 0xb488, 0xb489, /*0xe8-0xef*/ 0xb48a, 0xb48b, 0xede1, 0xb48c, 0xede3, 0xb48d, 0xb48e, 0xc1d7, /*0xf0-0xf7*/ 0xb48f, 0xb490, 0xbbc7, 0xb491, 0xb492, 0xb493, 0xb494, 0xb495, /*0xf8-0xff*/ /* 0x7900 */ 0xb496, 0xbdb8, 0xb497, 0xb498, 0xb499, 0xede2, 0xb49a, 0xb49b, /*0x00-0x07*/ 0xb49c, 0xb49d, 0xb49e, 0xb49f, 0xb4a0, 0xb540, 0xb541, 0xb542, /*0x08-0x0f*/ 0xb543, 0xb544, 0xb545, 0xede4, 0xb546, 0xb547, 0xb548, 0xb549, /*0x10-0x17*/ 0xb54a, 0xb54b, 0xb54c, 0xb54d, 0xb54e, 0xb54f, 0xede6, 0xb550, /*0x18-0x1f*/ 0xb551, 0xb552, 0xb553, 0xb554, 0xede5, 0xb555, 0xb556, 0xb557, /*0x20-0x27*/ 0xb558, 0xb559, 0xb55a, 0xb55b, 0xb55c, 0xb55d, 0xb55e, 0xb55f, /*0x28-0x2f*/ 0xb560, 0xb561, 0xb562, 0xb563, 0xede7, 0xb564, 0xb565, 0xb566, /*0x30-0x37*/ 0xb567, 0xb568, 0xcabe, 0xecea, 0xc0f1, 0xb569, 0xc9e7, 0xb56a, /*0x38-0x3f*/ 0xeceb, 0xc6ee, 0xb56b, 0xb56c, 0xb56d, 0xb56e, 0xecec, 0xb56f, /*0x40-0x47*/ 0xc6ed, 0xeced, 0xb570, 0xb571, 0xb572, 0xb573, 0xb574, 0xb575, /*0x48-0x4f*/ 0xb576, 0xb577, 0xb578, 0xecf0, 0xb579, 0xb57a, 0xd7e6, 0xecf3, /*0x50-0x57*/ 0xb57b, 0xb57c, 0xecf1, 0xecee, 0xecef, 0xd7a3, 0xc9f1, 0xcbee, /*0x58-0x5f*/ 0xecf4, 0xb57d, 0xecf2, 0xb57e, 0xb580, 0xcfe9, 0xb581, 0xecf6, /*0x60-0x67*/ 0xc6b1, 0xb582, 0xb583, 0xb584, 0xb585, 0xbcc0, 0xb586, 0xecf5, /*0x68-0x6f*/ 0xb587, 0xb588, 0xb589, 0xb58a, 0xb58b, 0xb58c, 0xb58d, 0xb5bb, /*0x70-0x77*/ 0xbbf6, 0xb58e, 0xecf7, 0xb58f, 0xb590, 0xb591, 0xb592, 0xb593, /*0x78-0x7f*/ 0xd9f7, 0xbdfb, 0xb594, 0xb595, 0xc2bb, 0xecf8, 0xb596, 0xb597, /*0x80-0x87*/ 0xb598, 0xb599, 0xecf9, 0xb59a, 0xb59b, 0xb59c, 0xb59d, 0xb8a3, /*0x88-0x8f*/ 0xb59e, 0xb59f, 0xb5a0, 0xb640, 0xb641, 0xb642, 0xb643, 0xb644, /*0x90-0x97*/ 0xb645, 0xb646, 0xecfa, 0xb647, 0xb648, 0xb649, 0xb64a, 0xb64b, /*0x98-0x9f*/ 0xb64c, 0xb64d, 0xb64e, 0xb64f, 0xb650, 0xb651, 0xb652, 0xecfb, /*0xa0-0xa7*/ 0xb653, 0xb654, 0xb655, 0xb656, 0xb657, 0xb658, 0xb659, 0xb65a, /*0xa8-0xaf*/ 0xb65b, 0xb65c, 0xb65d, 0xecfc, 0xb65e, 0xb65f, 0xb660, 0xb661, /*0xb0-0xb7*/ 0xb662, 0xd3ed, 0xd8ae, 0xc0eb, 0xb663, 0xc7dd, 0xbacc, 0xb664, /*0xb8-0xbf*/ 0xd0e3, 0xcbbd, 0xb665, 0xcdba, 0xb666, 0xb667, 0xb8d1, 0xb668, /*0xc0-0xc7*/ 0xb669, 0xb1fc, 0xb66a, 0xc7ef, 0xb66b, 0xd6d6, 0xb66c, 0xb66d, /*0xc8-0xcf*/ 0xb66e, 0xbfc6, 0xc3eb, 0xb66f, 0xb670, 0xeff5, 0xb671, 0xb672, /*0xd0-0xd7*/ 0xc3d8, 0xb673, 0xb674, 0xb675, 0xb676, 0xb677, 0xb678, 0xd7e2, /*0xd8-0xdf*/ 0xb679, 0xb67a, 0xb67b, 0xeff7, 0xb3d3, 0xb67c, 0xc7d8, 0xd1ed, /*0xe0-0xe7*/ 0xb67d, 0xd6c8, 0xb67e, 0xeff8, 0xb680, 0xeff6, 0xb681, 0xbbfd, /*0xe8-0xef*/ 0xb3c6, 0xb682, 0xb683, 0xb684, 0xb685, 0xb686, 0xb687, 0xb688, /*0xf0-0xf7*/ 0xbdd5, 0xb689, 0xb68a, 0xd2c6, 0xb68b, 0xbbe0, 0xb68c, 0xb68d, /*0xf8-0xff*/ /* 0x7a00 */ 0xcfa1, 0xb68e, 0xeffc, 0xeffb, 0xb68f, 0xb690, 0xeff9, 0xb691, /*0x00-0x07*/ 0xb692, 0xb693, 0xb694, 0xb3cc, 0xb695, 0xc9d4, 0xcbb0, 0xb696, /*0x08-0x0f*/ 0xb697, 0xb698, 0xb699, 0xb69a, 0xeffe, 0xb69b, 0xb69c, 0xb0de, /*0x10-0x17*/ 0xb69d, 0xb69e, 0xd6c9, 0xb69f, 0xb6a0, 0xb740, 0xeffd, 0xb741, /*0x18-0x1f*/ 0xb3ed, 0xb742, 0xb743, 0xf6d5, 0xb744, 0xb745, 0xb746, 0xb747, /*0x20-0x27*/ 0xb748, 0xb749, 0xb74a, 0xb74b, 0xb74c, 0xb74d, 0xb74e, 0xb74f, /*0x28-0x2f*/ 0xb750, 0xb751, 0xb752, 0xcec8, 0xb753, 0xb754, 0xb755, 0xf0a2, /*0x30-0x37*/ 0xb756, 0xf0a1, 0xb757, 0xb5be, 0xbcda, 0xbbfc, 0xb758, 0xb8e5, /*0x38-0x3f*/ 0xb759, 0xb75a, 0xb75b, 0xb75c, 0xb75d, 0xb75e, 0xc4c2, 0xb75f, /*0x40-0x47*/ 0xb760, 0xb761, 0xb762, 0xb763, 0xb764, 0xb765, 0xb766, 0xb767, /*0x48-0x4f*/ 0xb768, 0xf0a3, 0xb769, 0xb76a, 0xb76b, 0xb76c, 0xb76d, 0xcbeb, /*0x50-0x57*/ 0xb76e, 0xb76f, 0xb770, 0xb771, 0xb772, 0xb773, 0xb774, 0xb775, /*0x58-0x5f*/ 0xb776, 0xb777, 0xb778, 0xb779, 0xb77a, 0xb77b, 0xb77c, 0xb77d, /*0x60-0x67*/ 0xb77e, 0xb780, 0xb781, 0xb782, 0xb783, 0xb784, 0xb785, 0xb786, /*0x68-0x6f*/ 0xf0a6, 0xb787, 0xb788, 0xb789, 0xd1a8, 0xb78a, 0xbebf, 0xc7ee, /*0x70-0x77*/ 0xf1b6, 0xf1b7, 0xbfd5, 0xb78b, 0xb78c, 0xb78d, 0xb78e, 0xb4a9, /*0x78-0x7f*/ 0xf1b8, 0xcdbb, 0xb78f, 0xc7d4, 0xd5ad, 0xb790, 0xf1b9, 0xb791, /*0x80-0x87*/ 0xf1ba, 0xb792, 0xb793, 0xb794, 0xb795, 0xc7cf, 0xb796, 0xb797, /*0x88-0x8f*/ 0xb798, 0xd2a4, 0xd6cf, 0xb799, 0xb79a, 0xf1bb, 0xbdd1, 0xb4b0, /*0x90-0x97*/ 0xbebd, 0xb79b, 0xb79c, 0xb79d, 0xb4dc, 0xced1, 0xb79e, 0xbfdf, /*0x98-0x9f*/ 0xf1bd, 0xb79f, 0xb7a0, 0xb840, 0xb841, 0xbffa, 0xf1bc, 0xb842, /*0xa0-0xa7*/ 0xf1bf, 0xb843, 0xb844, 0xb845, 0xf1be, 0xf1c0, 0xb846, 0xb847, /*0xa8-0xaf*/ 0xb848, 0xb849, 0xb84a, 0xf1c1, 0xb84b, 0xb84c, 0xb84d, 0xb84e, /*0xb0-0xb7*/ 0xb84f, 0xb850, 0xb851, 0xb852, 0xb853, 0xb854, 0xb855, 0xc1fe, /*0xb8-0xbf*/ 0xb856, 0xb857, 0xb858, 0xb859, 0xb85a, 0xb85b, 0xb85c, 0xb85d, /*0xc0-0xc7*/ 0xb85e, 0xb85f, 0xb860, 0xc1a2, 0xb861, 0xb862, 0xb863, 0xb864, /*0xc8-0xcf*/ 0xb865, 0xb866, 0xb867, 0xb868, 0xb869, 0xb86a, 0xcafa, 0xb86b, /*0xd0-0xd7*/ 0xb86c, 0xd5be, 0xb86d, 0xb86e, 0xb86f, 0xb870, 0xbeba, 0xbeb9, /*0xd8-0xdf*/ 0xd5c2, 0xb871, 0xb872, 0xbfa2, 0xb873, 0xcdaf, 0xf1b5, 0xb874, /*0xe0-0xe7*/ 0xb875, 0xb876, 0xb877, 0xb878, 0xb879, 0xbddf, 0xb87a, 0xb6cb, /*0xe8-0xef*/ 0xb87b, 0xb87c, 0xb87d, 0xb87e, 0xb880, 0xb881, 0xb882, 0xb883, /*0xf0-0xf7*/ 0xb884, 0xd6f1, 0xf3c3, 0xb885, 0xb886, 0xf3c4, 0xb887, 0xb8cd, /*0xf8-0xff*/ /* 0x7b00 */ 0xb888, 0xb889, 0xb88a, 0xf3c6, 0xf3c7, 0xb88b, 0xb0ca, 0xb88c, /*0x00-0x07*/ 0xf3c5, 0xb88d, 0xf3c9, 0xcbf1, 0xb88e, 0xb88f, 0xb890, 0xf3cb, /*0x08-0x0f*/ 0xb891, 0xd0a6, 0xb892, 0xb893, 0xb1ca, 0xf3c8, 0xb894, 0xb895, /*0x10-0x17*/ 0xb896, 0xf3cf, 0xb897, 0xb5d1, 0xb898, 0xb899, 0xf3d7, 0xb89a, /*0x18-0x1f*/ 0xf3d2, 0xb89b, 0xb89c, 0xb89d, 0xf3d4, 0xf3d3, 0xb7fb, 0xb89e, /*0x20-0x27*/ 0xb1bf, 0xb89f, 0xf3ce, 0xf3ca, 0xb5da, 0xb8a0, 0xf3d0, 0xb940, /*0x28-0x2f*/ 0xb941, 0xf3d1, 0xb942, 0xf3d5, 0xb943, 0xb944, 0xb945, 0xb946, /*0x30-0x37*/ 0xf3cd, 0xb947, 0xbce3, 0xb948, 0xc1fd, 0xb949, 0xf3d6, 0xb94a, /*0x38-0x3f*/ 0xb94b, 0xb94c, 0xb94d, 0xb94e, 0xb94f, 0xf3da, 0xb950, 0xf3cc, /*0x40-0x47*/ 0xb951, 0xb5c8, 0xb952, 0xbdee, 0xf3dc, 0xb953, 0xb954, 0xb7a4, /*0x48-0x4f*/ 0xbff0, 0xd6fe, 0xcdb2, 0xb955, 0xb4f0, 0xb956, 0xb2df, 0xb957, /*0x50-0x57*/ 0xf3d8, 0xb958, 0xf3d9, 0xc9b8, 0xb959, 0xf3dd, 0xb95a, 0xb95b, /*0x58-0x5f*/ 0xf3de, 0xb95c, 0xf3e1, 0xb95d, 0xb95e, 0xb95f, 0xb960, 0xb961, /*0x60-0x67*/ 0xb962, 0xb963, 0xb964, 0xb965, 0xb966, 0xb967, 0xf3df, 0xb968, /*0x68-0x6f*/ 0xb969, 0xf3e3, 0xf3e2, 0xb96a, 0xb96b, 0xf3db, 0xb96c, 0xbfea, /*0x70-0x77*/ 0xb96d, 0xb3ef, 0xb96e, 0xf3e0, 0xb96f, 0xb970, 0xc7a9, 0xb971, /*0x78-0x7f*/ 0xbcf2, 0xb972, 0xb973, 0xb974, 0xb975, 0xf3eb, 0xb976, 0xb977, /*0x80-0x87*/ 0xb978, 0xb979, 0xb97a, 0xb97b, 0xb97c, 0xb9bf, 0xb97d, 0xb97e, /*0x88-0x8f*/ 0xf3e4, 0xb980, 0xb981, 0xb982, 0xb2ad, 0xbbfe, 0xb983, 0xcbe3, /*0x90-0x97*/ 0xb984, 0xb985, 0xb986, 0xb987, 0xf3ed, 0xf3e9, 0xb988, 0xb989, /*0x98-0x9f*/ 0xb98a, 0xb9dc, 0xf3ee, 0xb98b, 0xb98c, 0xb98d, 0xf3e5, 0xf3e6, /*0xa0-0xa7*/ 0xf3ea, 0xc2e1, 0xf3ec, 0xf3ef, 0xf3e8, 0xbcfd, 0xb98e, 0xb98f, /*0xa8-0xaf*/ 0xb990, 0xcfe4, 0xb991, 0xb992, 0xf3f0, 0xb993, 0xb994, 0xb995, /*0xb0-0xb7*/ 0xf3e7, 0xb996, 0xb997, 0xb998, 0xb999, 0xb99a, 0xb99b, 0xb99c, /*0xb8-0xbf*/ 0xb99d, 0xf3f2, 0xb99e, 0xb99f, 0xb9a0, 0xba40, 0xd7ad, 0xc6aa, /*0xc0-0xc7*/ 0xba41, 0xba42, 0xba43, 0xba44, 0xf3f3, 0xba45, 0xba46, 0xba47, /*0xc8-0xcf*/ 0xba48, 0xf3f1, 0xba49, 0xc2a8, 0xba4a, 0xba4b, 0xba4c, 0xba4d, /*0xd0-0xd7*/ 0xba4e, 0xb8dd, 0xf3f5, 0xba4f, 0xba50, 0xf3f4, 0xba51, 0xba52, /*0xd8-0xdf*/ 0xba53, 0xb4db, 0xba54, 0xba55, 0xba56, 0xf3f6, 0xf3f7, 0xba57, /*0xe0-0xe7*/ 0xba58, 0xba59, 0xf3f8, 0xba5a, 0xba5b, 0xba5c, 0xc0ba, 0xba5d, /*0xe8-0xef*/ 0xba5e, 0xc0e9, 0xba5f, 0xba60, 0xba61, 0xba62, 0xba63, 0xc5f1, /*0xf0-0xf7*/ 0xba64, 0xba65, 0xba66, 0xba67, 0xf3fb, 0xba68, 0xf3fa, 0xba69, /*0xf8-0xff*/ /* 0x7c00 */ 0xba6a, 0xba6b, 0xba6c, 0xba6d, 0xba6e, 0xba6f, 0xba70, 0xb4d8, /*0x00-0x07*/ 0xba71, 0xba72, 0xba73, 0xf3fe, 0xf3f9, 0xba74, 0xba75, 0xf3fc, /*0x08-0x0f*/ 0xba76, 0xba77, 0xba78, 0xba79, 0xba7a, 0xba7b, 0xf3fd, 0xba7c, /*0x10-0x17*/ 0xba7d, 0xba7e, 0xba80, 0xba81, 0xba82, 0xba83, 0xba84, 0xf4a1, /*0x18-0x1f*/ 0xba85, 0xba86, 0xba87, 0xba88, 0xba89, 0xba8a, 0xf4a3, 0xbbc9, /*0x20-0x27*/ 0xba8b, 0xba8c, 0xf4a2, 0xba8d, 0xba8e, 0xba8f, 0xba90, 0xba91, /*0x28-0x2f*/ 0xba92, 0xba93, 0xba94, 0xba95, 0xba96, 0xba97, 0xba98, 0xba99, /*0x30-0x37*/ 0xf4a4, 0xba9a, 0xba9b, 0xba9c, 0xba9d, 0xba9e, 0xba9f, 0xb2be, /*0x38-0x3f*/ 0xf4a6, 0xf4a5, 0xbaa0, 0xbb40, 0xbb41, 0xbb42, 0xbb43, 0xbb44, /*0x40-0x47*/ 0xbb45, 0xbb46, 0xbb47, 0xbb48, 0xbb49, 0xbcae, 0xbb4a, 0xbb4b, /*0x48-0x4f*/ 0xbb4c, 0xbb4d, 0xbb4e, 0xbb4f, 0xbb50, 0xbb51, 0xbb52, 0xbb53, /*0x50-0x57*/ 0xbb54, 0xbb55, 0xbb56, 0xbb57, 0xbb58, 0xbb59, 0xbb5a, 0xbb5b, /*0x58-0x5f*/ 0xbb5c, 0xbb5d, 0xbb5e, 0xbb5f, 0xbb60, 0xbb61, 0xbb62, 0xbb63, /*0x60-0x67*/ 0xbb64, 0xbb65, 0xbb66, 0xbb67, 0xbb68, 0xbb69, 0xbb6a, 0xbb6b, /*0x68-0x6f*/ 0xbb6c, 0xbb6d, 0xbb6e, 0xc3d7, 0xd9e1, 0xbb6f, 0xbb70, 0xbb71, /*0x70-0x77*/ 0xbb72, 0xbb73, 0xbb74, 0xc0e0, 0xf4cc, 0xd7d1, 0xbb75, 0xbb76, /*0x78-0x7f*/ 0xbb77, 0xbb78, 0xbb79, 0xbb7a, 0xbb7b, 0xbb7c, 0xbb7d, 0xbb7e, /*0x80-0x87*/ 0xbb80, 0xb7db, 0xbb81, 0xbb82, 0xbb83, 0xbb84, 0xbb85, 0xbb86, /*0x88-0x8f*/ 0xbb87, 0xf4ce, 0xc1a3, 0xbb88, 0xbb89, 0xc6c9, 0xbb8a, 0xb4d6, /*0x90-0x97*/ 0xd5b3, 0xbb8b, 0xbb8c, 0xbb8d, 0xf4d0, 0xf4cf, 0xf4d1, 0xcbda, /*0x98-0x9f*/ 0xbb8e, 0xbb8f, 0xf4d2, 0xbb90, 0xd4c1, 0xd6e0, 0xbb91, 0xbb92, /*0xa0-0xa7*/ 0xbb93, 0xbb94, 0xb7e0, 0xbb95, 0xbb96, 0xbb97, 0xc1b8, 0xbb98, /*0xa8-0xaf*/ 0xbb99, 0xc1bb, 0xf4d3, 0xbeac, 0xbb9a, 0xbb9b, 0xbb9c, 0xbb9d, /*0xb0-0xb7*/ 0xbb9e, 0xb4e2, 0xbb9f, 0xbba0, 0xf4d4, 0xf4d5, 0xbeab, 0xbc40, /*0xb8-0xbf*/ 0xbc41, 0xf4d6, 0xbc42, 0xbc43, 0xbc44, 0xf4db, 0xbc45, 0xf4d7, /*0xc0-0xc7*/ 0xf4da, 0xbc46, 0xbafd, 0xbc47, 0xf4d8, 0xf4d9, 0xbc48, 0xbc49, /*0xc8-0xcf*/ 0xbc4a, 0xbc4b, 0xbc4c, 0xbc4d, 0xbc4e, 0xb8e2, 0xccc7, 0xf4dc, /*0xd0-0xd7*/ 0xbc4f, 0xb2da, 0xbc50, 0xbc51, 0xc3d3, 0xbc52, 0xbc53, 0xd4e3, /*0xd8-0xdf*/ 0xbfb7, 0xbc54, 0xbc55, 0xbc56, 0xbc57, 0xbc58, 0xbc59, 0xbc5a, /*0xe0-0xe7*/ 0xf4dd, 0xbc5b, 0xbc5c, 0xbc5d, 0xbc5e, 0xbc5f, 0xbc60, 0xc5b4, /*0xe8-0xef*/ 0xbc61, 0xbc62, 0xbc63, 0xbc64, 0xbc65, 0xbc66, 0xbc67, 0xbc68, /*0xf0-0xf7*/ 0xf4e9, 0xbc69, 0xbc6a, 0xcfb5, 0xbc6b, 0xbc6c, 0xbc6d, 0xbc6e, /*0xf8-0xff*/ /* 0x7d00 */ 0xbc6f, 0xbc70, 0xbc71, 0xbc72, 0xbc73, 0xbc74, 0xbc75, 0xbc76, /*0x00-0x07*/ 0xbc77, 0xbc78, 0xcec9, 0xbc79, 0xbc7a, 0xbc7b, 0xbc7c, 0xbc7d, /*0x08-0x0f*/ 0xbc7e, 0xbc80, 0xbc81, 0xbc82, 0xbc83, 0xbc84, 0xbc85, 0xbc86, /*0x10-0x17*/ 0xbc87, 0xbc88, 0xbc89, 0xbc8a, 0xbc8b, 0xbc8c, 0xbc8d, 0xbc8e, /*0x18-0x1f*/ 0xcbd8, 0xbc8f, 0xcbf7, 0xbc90, 0xbc91, 0xbc92, 0xbc93, 0xbdf4, /*0x20-0x27*/ 0xbc94, 0xbc95, 0xbc96, 0xd7cf, 0xbc97, 0xbc98, 0xbc99, 0xc0db, /*0x28-0x2f*/ 0xbc9a, 0xbc9b, 0xbc9c, 0xbc9d, 0xbc9e, 0xbc9f, 0xbca0, 0xbd40, /*0x30-0x37*/ 0xbd41, 0xbd42, 0xbd43, 0xbd44, 0xbd45, 0xbd46, 0xbd47, 0xbd48, /*0x38-0x3f*/ 0xbd49, 0xbd4a, 0xbd4b, 0xbd4c, 0xbd4d, 0xbd4e, 0xbd4f, 0xbd50, /*0x40-0x47*/ 0xbd51, 0xbd52, 0xbd53, 0xbd54, 0xbd55, 0xbd56, 0xbd57, 0xbd58, /*0x48-0x4f*/ 0xbd59, 0xbd5a, 0xbd5b, 0xbd5c, 0xbd5d, 0xbd5e, 0xbd5f, 0xbd60, /*0x50-0x57*/ 0xbd61, 0xbd62, 0xbd63, 0xbd64, 0xbd65, 0xbd66, 0xbd67, 0xbd68, /*0x58-0x5f*/ 0xbd69, 0xbd6a, 0xbd6b, 0xbd6c, 0xbd6d, 0xbd6e, 0xbd6f, 0xbd70, /*0x60-0x67*/ 0xbd71, 0xbd72, 0xbd73, 0xbd74, 0xbd75, 0xbd76, 0xd0f5, 0xbd77, /*0x68-0x6f*/ 0xbd78, 0xbd79, 0xbd7a, 0xbd7b, 0xbd7c, 0xbd7d, 0xbd7e, 0xf4ea, /*0x70-0x77*/ 0xbd80, 0xbd81, 0xbd82, 0xbd83, 0xbd84, 0xbd85, 0xbd86, 0xbd87, /*0x78-0x7f*/ 0xbd88, 0xbd89, 0xbd8a, 0xbd8b, 0xbd8c, 0xbd8d, 0xbd8e, 0xbd8f, /*0x80-0x87*/ 0xbd90, 0xbd91, 0xbd92, 0xbd93, 0xbd94, 0xbd95, 0xbd96, 0xbd97, /*0x88-0x8f*/ 0xbd98, 0xbd99, 0xbd9a, 0xbd9b, 0xbd9c, 0xbd9d, 0xbd9e, 0xbd9f, /*0x90-0x97*/ 0xbda0, 0xbe40, 0xbe41, 0xbe42, 0xbe43, 0xbe44, 0xbe45, 0xbe46, /*0x98-0x9f*/ 0xbe47, 0xbe48, 0xbe49, 0xbe4a, 0xbe4b, 0xbe4c, 0xf4eb, 0xbe4d, /*0xa0-0xa7*/ 0xbe4e, 0xbe4f, 0xbe50, 0xbe51, 0xbe52, 0xbe53, 0xf4ec, 0xbe54, /*0xa8-0xaf*/ 0xbe55, 0xbe56, 0xbe57, 0xbe58, 0xbe59, 0xbe5a, 0xbe5b, 0xbe5c, /*0xb0-0xb7*/ 0xbe5d, 0xbe5e, 0xbe5f, 0xbe60, 0xbe61, 0xbe62, 0xbe63, 0xbe64, /*0xb8-0xbf*/ 0xbe65, 0xbe66, 0xbe67, 0xbe68, 0xbe69, 0xbe6a, 0xbe6b, 0xbe6c, /*0xc0-0xc7*/ 0xbe6d, 0xbe6e, 0xbe6f, 0xbe70, 0xbe71, 0xbe72, 0xbe73, 0xbe74, /*0xc8-0xcf*/ 0xbe75, 0xbe76, 0xbe77, 0xbe78, 0xbe79, 0xbe7a, 0xbe7b, 0xbe7c, /*0xd0-0xd7*/ 0xbe7d, 0xbe7e, 0xbe80, 0xbe81, 0xbe82, 0xbe83, 0xbe84, 0xbe85, /*0xd8-0xdf*/ 0xbe86, 0xbe87, 0xbe88, 0xbe89, 0xbe8a, 0xbe8b, 0xbe8c, 0xbe8d, /*0xe0-0xe7*/ 0xbe8e, 0xbe8f, 0xbe90, 0xbe91, 0xbe92, 0xbe93, 0xbe94, 0xbe95, /*0xe8-0xef*/ 0xbe96, 0xbe97, 0xbe98, 0xbe99, 0xbe9a, 0xbe9b, 0xbe9c, 0xbe9d, /*0xf0-0xf7*/ 0xbe9e, 0xbe9f, 0xbea0, 0xbf40, 0xbf41, 0xbf42, 0xbf43, 0xbf44, /*0xf8-0xff*/ /* 0x7e00 */ 0xbf45, 0xbf46, 0xbf47, 0xbf48, 0xbf49, 0xbf4a, 0xbf4b, 0xbf4c, /*0x00-0x07*/ 0xbf4d, 0xbf4e, 0xbf4f, 0xbf50, 0xbf51, 0xbf52, 0xbf53, 0xbf54, /*0x08-0x0f*/ 0xbf55, 0xbf56, 0xbf57, 0xbf58, 0xbf59, 0xbf5a, 0xbf5b, 0xbf5c, /*0x10-0x17*/ 0xbf5d, 0xbf5e, 0xbf5f, 0xbf60, 0xbf61, 0xbf62, 0xbf63, 0xbf64, /*0x18-0x1f*/ 0xbf65, 0xbf66, 0xbf67, 0xbf68, 0xbf69, 0xbf6a, 0xbf6b, 0xbf6c, /*0x20-0x27*/ 0xbf6d, 0xbf6e, 0xbf6f, 0xbf70, 0xbf71, 0xbf72, 0xbf73, 0xbf74, /*0x28-0x2f*/ 0xbf75, 0xbf76, 0xbf77, 0xbf78, 0xbf79, 0xbf7a, 0xbf7b, 0xbf7c, /*0x30-0x37*/ 0xbf7d, 0xbf7e, 0xbf80, 0xf7e3, 0xbf81, 0xbf82, 0xbf83, 0xbf84, /*0x38-0x3f*/ 0xbf85, 0xb7b1, 0xbf86, 0xbf87, 0xbf88, 0xbf89, 0xbf8a, 0xf4ed, /*0x40-0x47*/ 0xbf8b, 0xbf8c, 0xbf8d, 0xbf8e, 0xbf8f, 0xbf90, 0xbf91, 0xbf92, /*0x48-0x4f*/ 0xbf93, 0xbf94, 0xbf95, 0xbf96, 0xbf97, 0xbf98, 0xbf99, 0xbf9a, /*0x50-0x57*/ 0xbf9b, 0xbf9c, 0xbf9d, 0xbf9e, 0xbf9f, 0xbfa0, 0xc040, 0xc041, /*0x58-0x5f*/ 0xc042, 0xc043, 0xc044, 0xc045, 0xc046, 0xc047, 0xc048, 0xc049, /*0x60-0x67*/ 0xc04a, 0xc04b, 0xc04c, 0xc04d, 0xc04e, 0xc04f, 0xc050, 0xc051, /*0x68-0x6f*/ 0xc052, 0xc053, 0xc054, 0xc055, 0xc056, 0xc057, 0xc058, 0xc059, /*0x70-0x77*/ 0xc05a, 0xc05b, 0xc05c, 0xc05d, 0xc05e, 0xc05f, 0xc060, 0xc061, /*0x78-0x7f*/ 0xc062, 0xc063, 0xd7eb, 0xc064, 0xc065, 0xc066, 0xc067, 0xc068, /*0x80-0x87*/ 0xc069, 0xc06a, 0xc06b, 0xc06c, 0xc06d, 0xc06e, 0xc06f, 0xc070, /*0x88-0x8f*/ 0xc071, 0xc072, 0xc073, 0xc074, 0xc075, 0xc076, 0xc077, 0xc078, /*0x90-0x97*/ 0xc079, 0xc07a, 0xc07b, 0xf4ee, 0xc07c, 0xc07d, 0xc07e, 0xe6f9, /*0x98-0x9f*/ 0xbec0, 0xe6fa, 0xbaec, 0xe6fb, 0xcfcb, 0xe6fc, 0xd4bc, 0xbcb6, /*0xa0-0xa7*/ 0xe6fd, 0xe6fe, 0xbccd, 0xc8d2, 0xceb3, 0xe7a1, 0xc080, 0xb4bf, /*0xa8-0xaf*/ 0xe7a2, 0xc9b4, 0xb8d9, 0xc4c9, 0xc081, 0xd7dd, 0xc2da, 0xb7d7, /*0xb0-0xb7*/ 0xd6bd, 0xcec6, 0xb7c4, 0xc082, 0xc083, 0xc5a6, 0xe7a3, 0xcfdf, /*0xb8-0xbf*/ 0xe7a4, 0xe7a5, 0xe7a6, 0xc1b7, 0xd7e9, 0xc9f0, 0xcfb8, 0xd6af, /*0xc0-0xc7*/ 0xd6d5, 0xe7a7, 0xb0ed, 0xe7a8, 0xe7a9, 0xc9dc, 0xd2ef, 0xbead, /*0xc8-0xcf*/ 0xe7aa, 0xb0f3, 0xc8de, 0xbde1, 0xe7ab, 0xc8c6, 0xc084, 0xe7ac, /*0xd0-0xd7*/ 0xbbe6, 0xb8f8, 0xd1a4, 0xe7ad, 0xc2e7, 0xbef8, 0xbdca, 0xcdb3, /*0xd8-0xdf*/ 0xe7ae, 0xe7af, 0xbeee, 0xd0e5, 0xc085, 0xcbe7, 0xccd0, 0xbccc, /*0xe0-0xe7*/ 0xe7b0, 0xbca8, 0xd0f7, 0xe7b1, 0xc086, 0xd0f8, 0xe7b2, 0xe7b3, /*0xe8-0xef*/ 0xb4c2, 0xe7b4, 0xe7b5, 0xc9fe, 0xceac, 0xc3e0, 0xe7b7, 0xb1c1, /*0xf0-0xf7*/ 0xb3f1, 0xc087, 0xe7b8, 0xe7b9, 0xd7db, 0xd5c0, 0xe7ba, 0xc2cc, /*0xf8-0xff*/ /* 0x7f00 */ 0xd7ba, 0xe7bb, 0xe7bc, 0xe7bd, 0xbcea, 0xc3e5, 0xc0c2, 0xe7be, /*0x00-0x07*/ 0xe7bf, 0xbca9, 0xc088, 0xe7c0, 0xe7c1, 0xe7b6, 0xb6d0, 0xe7c2, /*0x08-0x0f*/ 0xc089, 0xe7c3, 0xe7c4, 0xbbba, 0xb5de, 0xc2c6, 0xb1e0, 0xe7c5, /*0x10-0x17*/ 0xd4b5, 0xe7c6, 0xb8bf, 0xe7c8, 0xe7c7, 0xb7ec, 0xc08a, 0xe7c9, /*0x18-0x1f*/ 0xb2f8, 0xe7ca, 0xe7cb, 0xe7cc, 0xe7cd, 0xe7ce, 0xe7cf, 0xe7d0, /*0x20-0x27*/ 0xd3a7, 0xcbf5, 0xe7d1, 0xe7d2, 0xe7d3, 0xe7d4, 0xc9c9, 0xe7d5, /*0x28-0x2f*/ 0xe7d6, 0xe7d7, 0xe7d8, 0xe7d9, 0xbdc9, 0xe7da, 0xf3be, 0xc08b, /*0x30-0x37*/ 0xb8d7, 0xc08c, 0xc8b1, 0xc08d, 0xc08e, 0xc08f, 0xc090, 0xc091, /*0x38-0x3f*/ 0xc092, 0xc093, 0xf3bf, 0xc094, 0xf3c0, 0xf3c1, 0xc095, 0xc096, /*0x40-0x47*/ 0xc097, 0xc098, 0xc099, 0xc09a, 0xc09b, 0xc09c, 0xc09d, 0xc09e, /*0x48-0x4f*/ 0xb9de, 0xcdf8, 0xc09f, 0xc0a0, 0xd8e8, 0xbab1, 0xc140, 0xc2de, /*0x50-0x57*/ 0xeeb7, 0xc141, 0xb7a3, 0xc142, 0xc143, 0xc144, 0xc145, 0xeeb9, /*0x58-0x5f*/ 0xc146, 0xeeb8, 0xb0d5, 0xc147, 0xc148, 0xc149, 0xc14a, 0xc14b, /*0x60-0x67*/ 0xeebb, 0xd5d6, 0xd7ef, 0xc14c, 0xc14d, 0xc14e, 0xd6c3, 0xc14f, /*0x68-0x6f*/ 0xc150, 0xeebd, 0xcaf0, 0xc151, 0xeebc, 0xc152, 0xc153, 0xc154, /*0x70-0x77*/ 0xc155, 0xeebe, 0xc156, 0xc157, 0xc158, 0xc159, 0xeec0, 0xc15a, /*0x78-0x7f*/ 0xc15b, 0xeebf, 0xc15c, 0xc15d, 0xc15e, 0xc15f, 0xc160, 0xc161, /*0x80-0x87*/ 0xc162, 0xc163, 0xd1f2, 0xc164, 0xc7bc, 0xc165, 0xc3c0, 0xc166, /*0x88-0x8f*/ 0xc167, 0xc168, 0xc169, 0xc16a, 0xb8e1, 0xc16b, 0xc16c, 0xc16d, /*0x90-0x97*/ 0xc16e, 0xc16f, 0xc1e7, 0xc170, 0xc171, 0xf4c6, 0xd0df, 0xf4c7, /*0x98-0x9f*/ 0xc172, 0xcfdb, 0xc173, 0xc174, 0xc8ba, 0xc175, 0xc176, 0xf4c8, /*0xa0-0xa7*/ 0xc177, 0xc178, 0xc179, 0xc17a, 0xc17b, 0xc17c, 0xc17d, 0xf4c9, /*0xa8-0xaf*/ 0xf4ca, 0xc17e, 0xf4cb, 0xc180, 0xc181, 0xc182, 0xc183, 0xc184, /*0xb0-0xb7*/ 0xd9fa, 0xb8fe, 0xc185, 0xc186, 0xe5f1, 0xd3f0, 0xc187, 0xf4e0, /*0xb8-0xbf*/ 0xc188, 0xcecc, 0xc189, 0xc18a, 0xc18b, 0xb3e1, 0xc18c, 0xc18d, /*0xc0-0xc7*/ 0xc18e, 0xc18f, 0xf1b4, 0xc190, 0xd2ee, 0xc191, 0xf4e1, 0xc192, /*0xc8-0xcf*/ 0xc193, 0xc194, 0xc195, 0xc196, 0xcfe8, 0xf4e2, 0xc197, 0xc198, /*0xd0-0xd7*/ 0xc7cc, 0xc199, 0xc19a, 0xc19b, 0xc19c, 0xc19d, 0xc19e, 0xb5d4, /*0xd8-0xdf*/ 0xb4e4, 0xf4e4, 0xc19f, 0xc1a0, 0xc240, 0xf4e3, 0xf4e5, 0xc241, /*0xe0-0xe7*/ 0xc242, 0xf4e6, 0xc243, 0xc244, 0xc245, 0xc246, 0xf4e7, 0xc247, /*0xe8-0xef*/ 0xbab2, 0xb0bf, 0xc248, 0xf4e8, 0xc249, 0xc24a, 0xc24b, 0xc24c, /*0xf0-0xf7*/ 0xc24d, 0xc24e, 0xc24f, 0xb7ad, 0xd2ed, 0xc250, 0xc251, 0xc252, /*0xf8-0xff*/ /* 0x8000 */ 0xd2ab, 0xc0cf, 0xc253, 0xbfbc, 0xeba3, 0xd5df, 0xeac8, 0xc254, /*0x00-0x07*/ 0xc255, 0xc256, 0xc257, 0xf1f3, 0xb6f8, 0xcba3, 0xc258, 0xc259, /*0x08-0x0f*/ 0xc4cd, 0xc25a, 0xf1e7, 0xc25b, 0xf1e8, 0xb8fb, 0xf1e9, 0xbac4, /*0x10-0x17*/ 0xd4c5, 0xb0d2, 0xc25c, 0xc25d, 0xf1ea, 0xc25e, 0xc25f, 0xc260, /*0x18-0x1f*/ 0xf1eb, 0xc261, 0xf1ec, 0xc262, 0xc263, 0xf1ed, 0xf1ee, 0xf1ef, /*0x20-0x27*/ 0xf1f1, 0xf1f0, 0xc5d5, 0xc264, 0xc265, 0xc266, 0xc267, 0xc268, /*0x28-0x2f*/ 0xc269, 0xf1f2, 0xc26a, 0xb6fa, 0xc26b, 0xf1f4, 0xd2ae, 0xdec7, /*0x30-0x37*/ 0xcbca, 0xc26c, 0xc26d, 0xb3dc, 0xc26e, 0xb5a2, 0xc26f, 0xb9a2, /*0x38-0x3f*/ 0xc270, 0xc271, 0xc4f4, 0xf1f5, 0xc272, 0xc273, 0xf1f6, 0xc274, /*0x40-0x47*/ 0xc275, 0xc276, 0xc1c4, 0xc1fb, 0xd6b0, 0xf1f7, 0xc277, 0xc278, /*0x48-0x4f*/ 0xc279, 0xc27a, 0xf1f8, 0xc27b, 0xc1aa, 0xc27c, 0xc27d, 0xc27e, /*0x50-0x57*/ 0xc6b8, 0xc280, 0xbedb, 0xc281, 0xc282, 0xc283, 0xc284, 0xc285, /*0x58-0x5f*/ 0xc286, 0xc287, 0xc288, 0xc289, 0xc28a, 0xc28b, 0xc28c, 0xc28d, /*0x60-0x67*/ 0xc28e, 0xf1f9, 0xb4cf, 0xc28f, 0xc290, 0xc291, 0xc292, 0xc293, /*0x68-0x6f*/ 0xc294, 0xf1fa, 0xc295, 0xc296, 0xc297, 0xc298, 0xc299, 0xc29a, /*0x70-0x77*/ 0xc29b, 0xc29c, 0xc29d, 0xc29e, 0xc29f, 0xc2a0, 0xc340, 0xedb2, /*0x78-0x7f*/ 0xedb1, 0xc341, 0xc342, 0xcbe0, 0xd2de, 0xc343, 0xcbc1, 0xd5d8, /*0x80-0x87*/ 0xc344, 0xc8e2, 0xc345, 0xc0df, 0xbca1, 0xc346, 0xc347, 0xc348, /*0x88-0x8f*/ 0xc349, 0xc34a, 0xc34b, 0xebc1, 0xc34c, 0xc34d, 0xd0a4, 0xc34e, /*0x90-0x97*/ 0xd6e2, 0xc34f, 0xb6c7, 0xb8d8, 0xebc0, 0xb8ce, 0xc350, 0xebbf, /*0x98-0x9f*/ 0xb3a6, 0xb9c9, 0xd6ab, 0xc351, 0xb7f4, 0xb7ca, 0xc352, 0xc353, /*0xa0-0xa7*/ 0xc354, 0xbce7, 0xb7be, 0xebc6, 0xc355, 0xebc7, 0xb0b9, 0xbfcf, /*0xa8-0xaf*/ 0xc356, 0xebc5, 0xd3fd, 0xc357, 0xebc8, 0xc358, 0xc359, 0xebc9, /*0xb0-0xb7*/ 0xc35a, 0xc35b, 0xb7ce, 0xc35c, 0xebc2, 0xebc4, 0xc9f6, 0xd6d7, /*0xb8-0xbf*/ 0xd5cd, 0xd0b2, 0xebcf, 0xceb8, 0xebd0, 0xc35d, 0xb5a8, 0xc35e, /*0xc0-0xc7*/ 0xc35f, 0xc360, 0xc361, 0xc362, 0xb1b3, 0xebd2, 0xcca5, 0xc363, /*0xc8-0xcf*/ 0xc364, 0xc365, 0xc366, 0xc367, 0xc368, 0xc369, 0xc5d6, 0xebd3, /*0xd0-0xd7*/ 0xc36a, 0xebd1, 0xc5df, 0xebce, 0xcaa4, 0xebd5, 0xb0fb, 0xc36b, /*0xd8-0xdf*/ 0xc36c, 0xbafa, 0xc36d, 0xc36e, 0xd8b7, 0xf1e3, 0xc36f, 0xebca, /*0xe0-0xe7*/ 0xebcb, 0xebcc, 0xebcd, 0xebd6, 0xe6c0, 0xebd9, 0xc370, 0xbfe8, /*0xe8-0xef*/ 0xd2c8, 0xebd7, 0xebdc, 0xb8ec, 0xebd8, 0xc371, 0xbdba, 0xc372, /*0xf0-0xf7*/ 0xd0d8, 0xc373, 0xb0b7, 0xc374, 0xebdd, 0xc4dc, 0xc375, 0xc376, /*0xf8-0xff*/ /* 0x8100 */ 0xc377, 0xc378, 0xd6ac, 0xc379, 0xc37a, 0xc37b, 0xb4e0, 0xc37c, /*0x00-0x07*/ 0xc37d, 0xc2f6, 0xbcb9, 0xc37e, 0xc380, 0xebda, 0xebdb, 0xd4e0, /*0x08-0x0f*/ 0xc6ea, 0xc4d4, 0xebdf, 0xc5a7, 0xd9f5, 0xc381, 0xb2b1, 0xc382, /*0x10-0x17*/ 0xebe4, 0xc383, 0xbdc5, 0xc384, 0xc385, 0xc386, 0xebe2, 0xc387, /*0x18-0x1f*/ 0xc388, 0xc389, 0xc38a, 0xc38b, 0xc38c, 0xc38d, 0xc38e, 0xc38f, /*0x20-0x27*/ 0xc390, 0xc391, 0xc392, 0xc393, 0xebe3, 0xc394, 0xc395, 0xb8ac, /*0x28-0x2f*/ 0xc396, 0xcdd1, 0xebe5, 0xc397, 0xc398, 0xc399, 0xebe1, 0xc39a, /*0x30-0x37*/ 0xc1b3, 0xc39b, 0xc39c, 0xc39d, 0xc39e, 0xc39f, 0xc6a2, 0xc3a0, /*0x38-0x3f*/ 0xc440, 0xc441, 0xc442, 0xc443, 0xc444, 0xc445, 0xccf3, 0xc446, /*0x40-0x47*/ 0xebe6, 0xc447, 0xc0b0, 0xd2b8, 0xebe7, 0xc448, 0xc449, 0xc44a, /*0x48-0x4f*/ 0xb8af, 0xb8ad, 0xc44b, 0xebe8, 0xc7bb, 0xcdf3, 0xc44c, 0xc44d, /*0x50-0x57*/ 0xc44e, 0xebea, 0xebeb, 0xc44f, 0xc450, 0xc451, 0xc452, 0xc453, /*0x58-0x5f*/ 0xebed, 0xc454, 0xc455, 0xc456, 0xc457, 0xd0c8, 0xc458, 0xebf2, /*0x60-0x67*/ 0xc459, 0xebee, 0xc45a, 0xc45b, 0xc45c, 0xebf1, 0xc8f9, 0xc45d, /*0x68-0x6f*/ 0xd1fc, 0xebec, 0xc45e, 0xc45f, 0xebe9, 0xc460, 0xc461, 0xc462, /*0x70-0x77*/ 0xc463, 0xb8b9, 0xcfd9, 0xc4e5, 0xebef, 0xebf0, 0xccda, 0xcdc8, /*0x78-0x7f*/ 0xb0f2, 0xc464, 0xebf6, 0xc465, 0xc466, 0xc467, 0xc468, 0xc469, /*0x80-0x87*/ 0xebf5, 0xc46a, 0xb2b2, 0xc46b, 0xc46c, 0xc46d, 0xc46e, 0xb8e0, /*0x88-0x8f*/ 0xc46f, 0xebf7, 0xc470, 0xc471, 0xc472, 0xc473, 0xc474, 0xc475, /*0x90-0x97*/ 0xb1ec, 0xc476, 0xc477, 0xccc5, 0xc4a4, 0xcfa5, 0xc478, 0xc479, /*0x98-0x9f*/ 0xc47a, 0xc47b, 0xc47c, 0xebf9, 0xc47d, 0xc47e, 0xeca2, 0xc480, /*0xa0-0xa7*/ 0xc5f2, 0xc481, 0xebfa, 0xc482, 0xc483, 0xc484, 0xc485, 0xc486, /*0xa8-0xaf*/ 0xc487, 0xc488, 0xc489, 0xc9c5, 0xc48a, 0xc48b, 0xc48c, 0xc48d, /*0xb0-0xb7*/ 0xc48e, 0xc48f, 0xe2df, 0xebfe, 0xc490, 0xc491, 0xc492, 0xc493, /*0xb8-0xbf*/ 0xcdce, 0xeca1, 0xb1db, 0xd3b7, 0xc494, 0xc495, 0xd2dc, 0xc496, /*0xc0-0xc7*/ 0xc497, 0xc498, 0xebfd, 0xc499, 0xebfb, 0xc49a, 0xc49b, 0xc49c, /*0xc8-0xcf*/ 0xc49d, 0xc49e, 0xc49f, 0xc4a0, 0xc540, 0xc541, 0xc542, 0xc543, /*0xd0-0xd7*/ 0xc544, 0xc545, 0xc546, 0xc547, 0xc548, 0xc549, 0xc54a, 0xc54b, /*0xd8-0xdf*/ 0xc54c, 0xc54d, 0xc54e, 0xb3bc, 0xc54f, 0xc550, 0xc551, 0xeab0, /*0xe0-0xe7*/ 0xc552, 0xc553, 0xd7d4, 0xc554, 0xf4ab, 0xb3f4, 0xc555, 0xc556, /*0xe8-0xef*/ 0xc557, 0xc558, 0xc559, 0xd6c1, 0xd6c2, 0xc55a, 0xc55b, 0xc55c, /*0xf0-0xf7*/ 0xc55d, 0xc55e, 0xc55f, 0xd5e9, 0xbeca, 0xc560, 0xf4a7, 0xc561, /*0xf8-0xff*/ /* 0x8200 */ 0xd2a8, 0xf4a8, 0xf4a9, 0xc562, 0xf4aa, 0xbecb, 0xd3df, 0xc563, /*0x00-0x07*/ 0xc564, 0xc565, 0xc566, 0xc567, 0xc9e0, 0xc9e1, 0xc568, 0xc569, /*0x08-0x0f*/ 0xf3c2, 0xc56a, 0xcae6, 0xc56b, 0xccf2, 0xc56c, 0xc56d, 0xc56e, /*0x10-0x17*/ 0xc56f, 0xc570, 0xc571, 0xe2b6, 0xcbb4, 0xc572, 0xcee8, 0xd6db, /*0x18-0x1f*/ 0xc573, 0xf4ad, 0xf4ae, 0xf4af, 0xc574, 0xc575, 0xc576, 0xc577, /*0x20-0x27*/ 0xf4b2, 0xc578, 0xbabd, 0xf4b3, 0xb0e3, 0xf4b0, 0xc579, 0xf4b1, /*0x28-0x2f*/ 0xbda2, 0xb2d5, 0xc57a, 0xf4b6, 0xf4b7, 0xb6e6, 0xb2b0, 0xcfcf, /*0x30-0x37*/ 0xf4b4, 0xb4ac, 0xc57b, 0xf4b5, 0xc57c, 0xc57d, 0xf4b8, 0xc57e, /*0x38-0x3f*/ 0xc580, 0xc581, 0xc582, 0xc583, 0xf4b9, 0xc584, 0xc585, 0xcda7, /*0x40-0x47*/ 0xc586, 0xf4ba, 0xc587, 0xf4bb, 0xc588, 0xc589, 0xc58a, 0xf4bc, /*0x48-0x4f*/ 0xc58b, 0xc58c, 0xc58d, 0xc58e, 0xc58f, 0xc590, 0xc591, 0xc592, /*0x50-0x57*/ 0xcbd2, 0xc593, 0xf4bd, 0xc594, 0xc595, 0xc596, 0xc597, 0xf4be, /*0x58-0x5f*/ 0xc598, 0xc599, 0xc59a, 0xc59b, 0xc59c, 0xc59d, 0xc59e, 0xc59f, /*0x60-0x67*/ 0xf4bf, 0xc5a0, 0xc640, 0xc641, 0xc642, 0xc643, 0xf4de, 0xc1bc, /*0x68-0x6f*/ 0xbce8, 0xc644, 0xc9ab, 0xd1de, 0xe5f5, 0xc645, 0xc646, 0xc647, /*0x70-0x77*/ 0xc648, 0xdcb3, 0xd2d5, 0xc649, 0xc64a, 0xdcb4, 0xb0ac, 0xdcb5, /*0x78-0x7f*/ 0xc64b, 0xc64c, 0xbdda, 0xc64d, 0xdcb9, 0xc64e, 0xc64f, 0xc650, /*0x80-0x87*/ 0xd8c2, 0xc651, 0xdcb7, 0xd3f3, 0xc652, 0xc9d6, 0xdcba, 0xdcb6, /*0x88-0x8f*/ 0xc653, 0xdcbb, 0xc3a2, 0xc654, 0xc655, 0xc656, 0xc657, 0xdcbc, /*0x90-0x97*/ 0xdcc5, 0xdcbd, 0xc658, 0xc659, 0xcedf, 0xd6a5, 0xc65a, 0xdccf, /*0x98-0x9f*/ 0xc65b, 0xdccd, 0xc65c, 0xc65d, 0xdcd2, 0xbde6, 0xc2ab, 0xc65e, /*0xa0-0xa7*/ 0xdcb8, 0xdccb, 0xdcce, 0xdcbe, 0xb7d2, 0xb0c5, 0xdcc7, 0xd0be, /*0xa8-0xaf*/ 0xdcc1, 0xbba8, 0xc65f, 0xb7bc, 0xdccc, 0xc660, 0xc661, 0xdcc6, /*0xb0-0xb7*/ 0xdcbf, 0xc7db, 0xc662, 0xc663, 0xc664, 0xd1bf, 0xdcc0, 0xc665, /*0xb8-0xbf*/ 0xc666, 0xdcca, 0xc667, 0xc668, 0xdcd0, 0xc669, 0xc66a, 0xcead, /*0xc0-0xc7*/ 0xdcc2, 0xc66b, 0xdcc3, 0xdcc8, 0xdcc9, 0xb2d4, 0xdcd1, 0xcbd5, /*0xc8-0xcf*/ 0xc66c, 0xd4b7, 0xdcdb, 0xdcdf, 0xcca6, 0xdce6, 0xc66d, 0xc3e7, /*0xd0-0xd7*/ 0xdcdc, 0xc66e, 0xc66f, 0xbfc1, 0xdcd9, 0xc670, 0xb0fa, 0xb9b6, /*0xd8-0xdf*/ 0xdce5, 0xdcd3, 0xc671, 0xdcc4, 0xdcd6, 0xc8f4, 0xbfe0, 0xc672, /*0xe0-0xe7*/ 0xc673, 0xc674, 0xc675, 0xc9bb, 0xc676, 0xc677, 0xc678, 0xb1bd, /*0xe8-0xef*/ 0xc679, 0xd3a2, 0xc67a, 0xc67b, 0xdcda, 0xc67c, 0xc67d, 0xdcd5, /*0xf0-0xf7*/ 0xc67e, 0xc6bb, 0xc680, 0xdcde, 0xc681, 0xc682, 0xc683, 0xc684, /*0xf8-0xff*/ /* 0x8300 */ 0xc685, 0xd7c2, 0xc3af, 0xb7b6, 0xc7d1, 0xc3a9, 0xdce2, 0xdcd8, /*0x00-0x07*/ 0xdceb, 0xdcd4, 0xc686, 0xc687, 0xdcdd, 0xc688, 0xbea5, 0xdcd7, /*0x08-0x0f*/ 0xc689, 0xdce0, 0xc68a, 0xc68b, 0xdce3, 0xdce4, 0xc68c, 0xdcf8, /*0x10-0x17*/ 0xc68d, 0xc68e, 0xdce1, 0xdda2, 0xdce7, 0xc68f, 0xc690, 0xc691, /*0x18-0x1f*/ 0xc692, 0xc693, 0xc694, 0xc695, 0xc696, 0xc697, 0xc698, 0xbceb, /*0x20-0x27*/ 0xb4c4, 0xc699, 0xc69a, 0xc3a3, 0xb2e7, 0xdcfa, 0xc69b, 0xdcf2, /*0x28-0x2f*/ 0xc69c, 0xdcef, 0xc69d, 0xdcfc, 0xdcee, 0xd2f0, 0xb2e8, 0xc69e, /*0x30-0x37*/ 0xc8d7, 0xc8e3, 0xdcfb, 0xc69f, 0xdced, 0xc6a0, 0xc740, 0xc741, /*0x38-0x3f*/ 0xdcf7, 0xc742, 0xc743, 0xdcf5, 0xc744, 0xc745, 0xbea3, 0xdcf4, /*0x40-0x47*/ 0xc746, 0xb2dd, 0xc747, 0xc748, 0xc749, 0xc74a, 0xc74b, 0xdcf3, /*0x48-0x4f*/ 0xbcf6, 0xdce8, 0xbbc4, 0xc74c, 0xc0f3, 0xc74d, 0xc74e, 0xc74f, /*0x50-0x57*/ 0xc750, 0xc751, 0xbcd4, 0xdce9, 0xdcea, 0xc752, 0xdcf1, 0xdcf6, /*0x58-0x5f*/ 0xdcf9, 0xb5b4, 0xc753, 0xc8d9, 0xbbe7, 0xdcfe, 0xdcfd, 0xd3ab, /*0x60-0x67*/ 0xdda1, 0xdda3, 0xdda5, 0xd2f1, 0xdda4, 0xdda6, 0xdda7, 0xd2a9, /*0x68-0x6f*/ 0xc754, 0xc755, 0xc756, 0xc757, 0xc758, 0xc759, 0xc75a, 0xbac9, /*0x70-0x77*/ 0xdda9, 0xc75b, 0xc75c, 0xddb6, 0xddb1, 0xddb4, 0xc75d, 0xc75e, /*0x78-0x7f*/ 0xc75f, 0xc760, 0xc761, 0xc762, 0xc763, 0xddb0, 0xc6ce, 0xc764, /*0x80-0x87*/ 0xc765, 0xc0f2, 0xc766, 0xc767, 0xc768, 0xc769, 0xc9af, 0xc76a, /*0x88-0x8f*/ 0xc76b, 0xc76c, 0xdcec, 0xddae, 0xc76d, 0xc76e, 0xc76f, 0xc770, /*0x90-0x97*/ 0xddb7, 0xc771, 0xc772, 0xdcf0, 0xddaf, 0xc773, 0xddb8, 0xc774, /*0x98-0x9f*/ 0xddac, 0xc775, 0xc776, 0xc777, 0xc778, 0xc779, 0xc77a, 0xc77b, /*0xa0-0xa7*/ 0xddb9, 0xddb3, 0xddad, 0xc4aa, 0xc77c, 0xc77d, 0xc77e, 0xc780, /*0xa8-0xaf*/ 0xdda8, 0xc0b3, 0xc1ab, 0xddaa, 0xddab, 0xc781, 0xddb2, 0xbbf1, /*0xb0-0xb7*/ 0xddb5, 0xd3a8, 0xddba, 0xc782, 0xddbb, 0xc3a7, 0xc783, 0xc784, /*0xb8-0xbf*/ 0xddd2, 0xddbc, 0xc785, 0xc786, 0xc787, 0xddd1, 0xc788, 0xb9bd, /*0xc0-0xc7*/ 0xc789, 0xc78a, 0xbed5, 0xc78b, 0xbefa, 0xc78c, 0xc78d, 0xbaca, /*0xc8-0xcf*/ 0xc78e, 0xc78f, 0xc790, 0xc791, 0xddca, 0xc792, 0xddc5, 0xc793, /*0xd0-0xd7*/ 0xddbf, 0xc794, 0xc795, 0xc796, 0xb2cb, 0xddc3, 0xc797, 0xddcb, /*0xd8-0xdf*/ 0xb2a4, 0xddd5, 0xc798, 0xc799, 0xc79a, 0xddbe, 0xc79b, 0xc79c, /*0xe0-0xe7*/ 0xc79d, 0xc6d0, 0xddd0, 0xc79e, 0xc79f, 0xc7a0, 0xc840, 0xc841, /*0xe8-0xef*/ 0xddd4, 0xc1e2, 0xb7c6, 0xc842, 0xc843, 0xc844, 0xc845, 0xc846, /*0xf0-0xf7*/ 0xddce, 0xddcf, 0xc847, 0xc848, 0xc849, 0xddc4, 0xc84a, 0xc84b, /*0xf8-0xff*/ /* 0x8400 */ 0xc84c, 0xddbd, 0xc84d, 0xddcd, 0xccd1, 0xc84e, 0xddc9, 0xc84f, /*0x00-0x07*/ 0xc850, 0xc851, 0xc852, 0xddc2, 0xc3c8, 0xc6bc, 0xceae, 0xddcc, /*0x08-0x0f*/ 0xc853, 0xddc8, 0xc854, 0xc855, 0xc856, 0xc857, 0xc858, 0xc859, /*0x10-0x17*/ 0xddc1, 0xc85a, 0xc85b, 0xc85c, 0xddc6, 0xc2dc, 0xc85d, 0xc85e, /*0x18-0x1f*/ 0xc85f, 0xc860, 0xc861, 0xc862, 0xd3a9, 0xd3aa, 0xddd3, 0xcff4, /*0x20-0x27*/ 0xc8f8, 0xc863, 0xc864, 0xc865, 0xc866, 0xc867, 0xc868, 0xc869, /*0x28-0x2f*/ 0xc86a, 0xdde6, 0xc86b, 0xc86c, 0xc86d, 0xc86e, 0xc86f, 0xc870, /*0x30-0x37*/ 0xddc7, 0xc871, 0xc872, 0xc873, 0xdde0, 0xc2e4, 0xc874, 0xc875, /*0x38-0x3f*/ 0xc876, 0xc877, 0xc878, 0xc879, 0xc87a, 0xc87b, 0xdde1, 0xc87c, /*0x40-0x47*/ 0xc87d, 0xc87e, 0xc880, 0xc881, 0xc882, 0xc883, 0xc884, 0xc885, /*0x48-0x4f*/ 0xc886, 0xddd7, 0xc887, 0xc888, 0xc889, 0xc88a, 0xc88b, 0xd6f8, /*0x50-0x57*/ 0xc88c, 0xddd9, 0xddd8, 0xb8f0, 0xddd6, 0xc88d, 0xc88e, 0xc88f, /*0x58-0x5f*/ 0xc890, 0xc6cf, 0xc891, 0xb6ad, 0xc892, 0xc893, 0xc894, 0xc895, /*0x60-0x67*/ 0xc896, 0xdde2, 0xc897, 0xbaf9, 0xd4e1, 0xdde7, 0xc898, 0xc899, /*0x68-0x6f*/ 0xc89a, 0xb4d0, 0xc89b, 0xddda, 0xc89c, 0xbffb, 0xdde3, 0xc89d, /*0x70-0x77*/ 0xdddf, 0xc89e, 0xdddd, 0xc89f, 0xc8a0, 0xc940, 0xc941, 0xc942, /*0x78-0x7f*/ 0xc943, 0xc944, 0xb5d9, 0xc945, 0xc946, 0xc947, 0xc948, 0xdddb, /*0x80-0x87*/ 0xdddc, 0xddde, 0xc949, 0xbdaf, 0xdde4, 0xc94a, 0xdde5, 0xc94b, /*0x88-0x8f*/ 0xc94c, 0xc94d, 0xc94e, 0xc94f, 0xc950, 0xc951, 0xc952, 0xddf5, /*0x90-0x97*/ 0xc953, 0xc3c9, 0xc954, 0xc955, 0xcbe2, 0xc956, 0xc957, 0xc958, /*0x98-0x9f*/ 0xc959, 0xddf2, 0xc95a, 0xc95b, 0xc95c, 0xc95d, 0xc95e, 0xc95f, /*0xa0-0xa7*/ 0xc960, 0xc961, 0xc962, 0xc963, 0xc964, 0xc965, 0xc966, 0xd8e1, /*0xa8-0xaf*/ 0xc967, 0xc968, 0xc6d1, 0xc969, 0xddf4, 0xc96a, 0xc96b, 0xc96c, /*0xb0-0xb7*/ 0xd5f4, 0xddf3, 0xddf0, 0xc96d, 0xc96e, 0xddec, 0xc96f, 0xddef, /*0xb8-0xbf*/ 0xc970, 0xdde8, 0xc971, 0xc972, 0xd0ee, 0xc973, 0xc974, 0xc975, /*0xc0-0xc7*/ 0xc976, 0xc8d8, 0xddee, 0xc977, 0xc978, 0xdde9, 0xc979, 0xc97a, /*0xc8-0xcf*/ 0xddea, 0xcbf2, 0xc97b, 0xdded, 0xc97c, 0xc97d, 0xb1cd, 0xc97e, /*0xd0-0xd7*/ 0xc980, 0xc981, 0xc982, 0xc983, 0xc984, 0xc0b6, 0xc985, 0xbcbb, /*0xd8-0xdf*/ 0xddf1, 0xc986, 0xc987, 0xddf7, 0xc988, 0xddf6, 0xddeb, 0xc989, /*0xe0-0xe7*/ 0xc98a, 0xc98b, 0xc98c, 0xc98d, 0xc5ee, 0xc98e, 0xc98f, 0xc990, /*0xe8-0xef*/ 0xddfb, 0xc991, 0xc992, 0xc993, 0xc994, 0xc995, 0xc996, 0xc997, /*0xf0-0xf7*/ 0xc998, 0xc999, 0xc99a, 0xc99b, 0xdea4, 0xc99c, 0xc99d, 0xdea3, /*0xf8-0xff*/ /* 0x8500 */ 0xc99e, 0xc99f, 0xc9a0, 0xca40, 0xca41, 0xca42, 0xca43, 0xca44, /*0x00-0x07*/ 0xca45, 0xca46, 0xca47, 0xca48, 0xddf8, 0xca49, 0xca4a, 0xca4b, /*0x08-0x0f*/ 0xca4c, 0xc3ef, 0xca4d, 0xc2fb, 0xca4e, 0xca4f, 0xca50, 0xd5e1, /*0x10-0x17*/ 0xca51, 0xca52, 0xceb5, 0xca53, 0xca54, 0xca55, 0xca56, 0xddfd, /*0x18-0x1f*/ 0xca57, 0xb2cc, 0xca58, 0xca59, 0xca5a, 0xca5b, 0xca5c, 0xca5d, /*0x20-0x27*/ 0xca5e, 0xca5f, 0xca60, 0xc4e8, 0xcadf, 0xca61, 0xca62, 0xca63, /*0x28-0x2f*/ 0xca64, 0xca65, 0xca66, 0xca67, 0xca68, 0xca69, 0xca6a, 0xc7be, /*0x30-0x37*/ 0xddfa, 0xddfc, 0xddfe, 0xdea2, 0xb0aa, 0xb1ce, 0xca6b, 0xca6c, /*0x38-0x3f*/ 0xca6d, 0xca6e, 0xca6f, 0xdeac, 0xca70, 0xca71, 0xca72, 0xca73, /*0x40-0x47*/ 0xdea6, 0xbdb6, 0xc8ef, 0xca74, 0xca75, 0xca76, 0xca77, 0xca78, /*0x48-0x4f*/ 0xca79, 0xca7a, 0xca7b, 0xca7c, 0xca7d, 0xca7e, 0xdea1, 0xca80, /*0x50-0x57*/ 0xca81, 0xdea5, 0xca82, 0xca83, 0xca84, 0xca85, 0xdea9, 0xca86, /*0x58-0x5f*/ 0xca87, 0xca88, 0xca89, 0xca8a, 0xdea8, 0xca8b, 0xca8c, 0xca8d, /*0x60-0x67*/ 0xdea7, 0xca8e, 0xca8f, 0xca90, 0xca91, 0xca92, 0xca93, 0xca94, /*0x68-0x6f*/ 0xca95, 0xca96, 0xdead, 0xca97, 0xd4cc, 0xca98, 0xca99, 0xca9a, /*0x70-0x77*/ 0xca9b, 0xdeb3, 0xdeaa, 0xdeae, 0xca9c, 0xca9d, 0xc0d9, 0xca9e, /*0x78-0x7f*/ 0xca9f, 0xcaa0, 0xcb40, 0xcb41, 0xb1a1, 0xdeb6, 0xcb42, 0xdeb1, /*0x80-0x87*/ 0xcb43, 0xcb44, 0xcb45, 0xcb46, 0xcb47, 0xcb48, 0xcb49, 0xdeb2, /*0x88-0x8f*/ 0xcb4a, 0xcb4b, 0xcb4c, 0xcb4d, 0xcb4e, 0xcb4f, 0xcb50, 0xcb51, /*0x90-0x97*/ 0xcb52, 0xcb53, 0xcb54, 0xd1a6, 0xdeb5, 0xcb55, 0xcb56, 0xcb57, /*0x98-0x9f*/ 0xcb58, 0xcb59, 0xcb5a, 0xcb5b, 0xdeaf, 0xcb5c, 0xcb5d, 0xcb5e, /*0xa0-0xa7*/ 0xdeb0, 0xcb5f, 0xd0bd, 0xcb60, 0xcb61, 0xcb62, 0xdeb4, 0xcaed, /*0xa8-0xaf*/ 0xdeb9, 0xcb63, 0xcb64, 0xcb65, 0xcb66, 0xcb67, 0xcb68, 0xdeb8, /*0xb0-0xb7*/ 0xcb69, 0xdeb7, 0xcb6a, 0xcb6b, 0xcb6c, 0xcb6d, 0xcb6e, 0xcb6f, /*0xb8-0xbf*/ 0xcb70, 0xdebb, 0xcb71, 0xcb72, 0xcb73, 0xcb74, 0xcb75, 0xcb76, /*0xc0-0xc7*/ 0xcb77, 0xbde5, 0xcb78, 0xcb79, 0xcb7a, 0xcb7b, 0xcb7c, 0xb2d8, /*0xc8-0xcf*/ 0xc3ea, 0xcb7d, 0xcb7e, 0xdeba, 0xcb80, 0xc5ba, 0xcb81, 0xcb82, /*0xd0-0xd7*/ 0xcb83, 0xcb84, 0xcb85, 0xcb86, 0xdebc, 0xcb87, 0xcb88, 0xcb89, /*0xd8-0xdf*/ 0xcb8a, 0xcb8b, 0xcb8c, 0xcb8d, 0xccd9, 0xcb8e, 0xcb8f, 0xcb90, /*0xe0-0xe7*/ 0xcb91, 0xb7aa, 0xcb92, 0xcb93, 0xcb94, 0xcb95, 0xcb96, 0xcb97, /*0xe8-0xef*/ 0xcb98, 0xcb99, 0xcb9a, 0xcb9b, 0xcb9c, 0xcb9d, 0xcb9e, 0xcb9f, /*0xf0-0xf7*/ 0xcba0, 0xcc40, 0xcc41, 0xd4e5, 0xcc42, 0xcc43, 0xcc44, 0xdebd, /*0xf8-0xff*/ /* 0x8600 */ 0xcc45, 0xcc46, 0xcc47, 0xcc48, 0xcc49, 0xdebf, 0xcc4a, 0xcc4b, /*0x00-0x07*/ 0xcc4c, 0xcc4d, 0xcc4e, 0xcc4f, 0xcc50, 0xcc51, 0xcc52, 0xcc53, /*0x08-0x0f*/ 0xcc54, 0xc4a2, 0xcc55, 0xcc56, 0xcc57, 0xcc58, 0xdec1, 0xcc59, /*0x10-0x17*/ 0xcc5a, 0xcc5b, 0xcc5c, 0xcc5d, 0xcc5e, 0xcc5f, 0xcc60, 0xcc61, /*0x18-0x1f*/ 0xcc62, 0xcc63, 0xcc64, 0xcc65, 0xcc66, 0xcc67, 0xcc68, 0xdebe, /*0x20-0x27*/ 0xcc69, 0xdec0, 0xcc6a, 0xcc6b, 0xcc6c, 0xcc6d, 0xcc6e, 0xcc6f, /*0x28-0x2f*/ 0xcc70, 0xcc71, 0xcc72, 0xcc73, 0xcc74, 0xcc75, 0xcc76, 0xcc77, /*0x30-0x37*/ 0xd5ba, 0xcc78, 0xcc79, 0xcc7a, 0xdec2, 0xcc7b, 0xcc7c, 0xcc7d, /*0x38-0x3f*/ 0xcc7e, 0xcc80, 0xcc81, 0xcc82, 0xcc83, 0xcc84, 0xcc85, 0xcc86, /*0x40-0x47*/ 0xcc87, 0xcc88, 0xcc89, 0xcc8a, 0xcc8b, 0xf2ae, 0xbba2, 0xc2b2, /*0x48-0x4f*/ 0xc5b0, 0xc2c7, 0xcc8c, 0xcc8d, 0xf2af, 0xcc8e, 0xcc8f, 0xcc90, /*0x50-0x57*/ 0xcc91, 0xcc92, 0xd0e9, 0xcc93, 0xcc94, 0xcc95, 0xd3dd, 0xcc96, /*0x58-0x5f*/ 0xcc97, 0xcc98, 0xebbd, 0xcc99, 0xcc9a, 0xcc9b, 0xcc9c, 0xcc9d, /*0x60-0x67*/ 0xcc9e, 0xcc9f, 0xcca0, 0xb3e6, 0xf2b0, 0xcd40, 0xf2b1, 0xcd41, /*0x68-0x6f*/ 0xcd42, 0xcaad, 0xcd43, 0xcd44, 0xcd45, 0xcd46, 0xcd47, 0xcd48, /*0x70-0x77*/ 0xcd49, 0xbae7, 0xf2b3, 0xf2b5, 0xf2b4, 0xcbe4, 0xcfba, 0xf2b2, /*0x78-0x7f*/ 0xcab4, 0xd2cf, 0xc2ec, 0xcd4a, 0xcd4b, 0xcd4c, 0xcd4d, 0xcd4e, /*0x80-0x87*/ 0xcd4f, 0xcd50, 0xcec3, 0xf2b8, 0xb0f6, 0xf2b7, 0xcd51, 0xcd52, /*0x88-0x8f*/ 0xcd53, 0xcd54, 0xcd55, 0xf2be, 0xcd56, 0xb2cf, 0xcd57, 0xcd58, /*0x90-0x97*/ 0xcd59, 0xcd5a, 0xcd5b, 0xcd5c, 0xd1c1, 0xf2ba, 0xcd5d, 0xcd5e, /*0x98-0x9f*/ 0xcd5f, 0xcd60, 0xcd61, 0xf2bc, 0xd4e9, 0xcd62, 0xcd63, 0xf2bb, /*0xa0-0xa7*/ 0xf2b6, 0xf2bf, 0xf2bd, 0xcd64, 0xf2b9, 0xcd65, 0xcd66, 0xf2c7, /*0xa8-0xaf*/ 0xf2c4, 0xf2c6, 0xcd67, 0xcd68, 0xf2ca, 0xf2c2, 0xf2c0, 0xcd69, /*0xb0-0xb7*/ 0xcd6a, 0xcd6b, 0xf2c5, 0xcd6c, 0xcd6d, 0xcd6e, 0xcd6f, 0xcd70, /*0xb8-0xbf*/ 0xd6fb, 0xcd71, 0xcd72, 0xcd73, 0xf2c1, 0xcd74, 0xc7f9, 0xc9df, /*0xc0-0xc7*/ 0xcd75, 0xf2c8, 0xb9c6, 0xb5b0, 0xcd76, 0xcd77, 0xf2c3, 0xf2c9, /*0xc8-0xcf*/ 0xf2d0, 0xf2d6, 0xcd78, 0xcd79, 0xbbd7, 0xcd7a, 0xcd7b, 0xcd7c, /*0xd0-0xd7*/ 0xf2d5, 0xcddc, 0xcd7d, 0xd6eb, 0xcd7e, 0xcd80, 0xf2d2, 0xf2d4, /*0xd8-0xdf*/ 0xcd81, 0xcd82, 0xcd83, 0xcd84, 0xb8f2, 0xcd85, 0xcd86, 0xcd87, /*0xe0-0xe7*/ 0xcd88, 0xf2cb, 0xcd89, 0xcd8a, 0xcd8b, 0xf2ce, 0xc2f9, 0xcd8c, /*0xe8-0xef*/ 0xd5dd, 0xf2cc, 0xf2cd, 0xf2cf, 0xf2d3, 0xcd8d, 0xcd8e, 0xcd8f, /*0xf0-0xf7*/ 0xf2d9, 0xd3bc, 0xcd90, 0xcd91, 0xcd92, 0xcd93, 0xb6ea, 0xcd94, /*0xf8-0xff*/ /* 0x8700 */ 0xcaf1, 0xcd95, 0xb7e4, 0xf2d7, 0xcd96, 0xcd97, 0xcd98, 0xf2d8, /*0x00-0x07*/ 0xf2da, 0xf2dd, 0xf2db, 0xcd99, 0xcd9a, 0xf2dc, 0xcd9b, 0xcd9c, /*0x08-0x0f*/ 0xcd9d, 0xcd9e, 0xd1d1, 0xf2d1, 0xcd9f, 0xcdc9, 0xcda0, 0xcecf, /*0x10-0x17*/ 0xd6a9, 0xce40, 0xf2e3, 0xce41, 0xc3db, 0xce42, 0xf2e0, 0xce43, /*0x18-0x1f*/ 0xce44, 0xc0af, 0xf2ec, 0xf2de, 0xce45, 0xf2e1, 0xce46, 0xce47, /*0x20-0x27*/ 0xce48, 0xf2e8, 0xce49, 0xce4a, 0xce4b, 0xce4c, 0xf2e2, 0xce4d, /*0x28-0x2f*/ 0xce4e, 0xf2e7, 0xce4f, 0xce50, 0xf2e6, 0xce51, 0xce52, 0xf2e9, /*0x30-0x37*/ 0xce53, 0xce54, 0xce55, 0xf2df, 0xce56, 0xce57, 0xf2e4, 0xf2ea, /*0x38-0x3f*/ 0xce58, 0xce59, 0xce5a, 0xce5b, 0xce5c, 0xce5d, 0xce5e, 0xd3ac, /*0x40-0x47*/ 0xf2e5, 0xb2f5, 0xce5f, 0xce60, 0xf2f2, 0xce61, 0xd0ab, 0xce62, /*0x48-0x4f*/ 0xce63, 0xce64, 0xce65, 0xf2f5, 0xce66, 0xce67, 0xce68, 0xbbc8, /*0x50-0x57*/ 0xce69, 0xf2f9, 0xce6a, 0xce6b, 0xce6c, 0xce6d, 0xce6e, 0xce6f, /*0x58-0x5f*/ 0xf2f0, 0xce70, 0xce71, 0xf2f6, 0xf2f8, 0xf2fa, 0xce72, 0xce73, /*0x60-0x67*/ 0xce74, 0xce75, 0xce76, 0xce77, 0xce78, 0xce79, 0xf2f3, 0xce7a, /*0x68-0x6f*/ 0xf2f1, 0xce7b, 0xce7c, 0xce7d, 0xbafb, 0xce7e, 0xb5fb, 0xce80, /*0x70-0x77*/ 0xce81, 0xce82, 0xce83, 0xf2ef, 0xf2f7, 0xf2ed, 0xf2ee, 0xce84, /*0x78-0x7f*/ 0xce85, 0xce86, 0xf2eb, 0xf3a6, 0xce87, 0xf3a3, 0xce88, 0xce89, /*0x80-0x87*/ 0xf3a2, 0xce8a, 0xce8b, 0xf2f4, 0xce8c, 0xc8da, 0xce8d, 0xce8e, /*0x88-0x8f*/ 0xce8f, 0xce90, 0xce91, 0xf2fb, 0xce92, 0xce93, 0xce94, 0xf3a5, /*0x90-0x97*/ 0xce95, 0xce96, 0xce97, 0xce98, 0xce99, 0xce9a, 0xce9b, 0xc3f8, /*0x98-0x9f*/ 0xce9c, 0xce9d, 0xce9e, 0xce9f, 0xcea0, 0xcf40, 0xcf41, 0xcf42, /*0xa0-0xa7*/ 0xf2fd, 0xcf43, 0xcf44, 0xf3a7, 0xf3a9, 0xf3a4, 0xcf45, 0xf2fc, /*0xa8-0xaf*/ 0xcf46, 0xcf47, 0xcf48, 0xf3ab, 0xcf49, 0xf3aa, 0xcf4a, 0xcf4b, /*0xb0-0xb7*/ 0xcf4c, 0xcf4d, 0xc2dd, 0xcf4e, 0xcf4f, 0xf3ae, 0xcf50, 0xcf51, /*0xb8-0xbf*/ 0xf3b0, 0xcf52, 0xcf53, 0xcf54, 0xcf55, 0xcf56, 0xf3a1, 0xcf57, /*0xc0-0xc7*/ 0xcf58, 0xcf59, 0xf3b1, 0xf3ac, 0xcf5a, 0xcf5b, 0xcf5c, 0xcf5d, /*0xc8-0xcf*/ 0xcf5e, 0xf3af, 0xf2fe, 0xf3ad, 0xcf5f, 0xcf60, 0xcf61, 0xcf62, /*0xd0-0xd7*/ 0xcf63, 0xcf64, 0xcf65, 0xf3b2, 0xcf66, 0xcf67, 0xcf68, 0xcf69, /*0xd8-0xdf*/ 0xf3b4, 0xcf6a, 0xcf6b, 0xcf6c, 0xcf6d, 0xf3a8, 0xcf6e, 0xcf6f, /*0xe0-0xe7*/ 0xcf70, 0xcf71, 0xf3b3, 0xcf72, 0xcf73, 0xcf74, 0xf3b5, 0xcf75, /*0xe8-0xef*/ 0xcf76, 0xcf77, 0xcf78, 0xcf79, 0xcf7a, 0xcf7b, 0xcf7c, 0xcf7d, /*0xf0-0xf7*/ 0xcf7e, 0xd0b7, 0xcf80, 0xcf81, 0xcf82, 0xcf83, 0xf3b8, 0xcf84, /*0xf8-0xff*/ /* 0x8800 */ 0xcf85, 0xcf86, 0xcf87, 0xd9f9, 0xcf88, 0xcf89, 0xcf8a, 0xcf8b, /*0x00-0x07*/ 0xcf8c, 0xcf8d, 0xf3b9, 0xcf8e, 0xcf8f, 0xcf90, 0xcf91, 0xcf92, /*0x08-0x0f*/ 0xcf93, 0xcf94, 0xcf95, 0xf3b7, 0xcf96, 0xc8e4, 0xf3b6, 0xcf97, /*0x10-0x17*/ 0xcf98, 0xcf99, 0xcf9a, 0xf3ba, 0xcf9b, 0xcf9c, 0xcf9d, 0xcf9e, /*0x18-0x1f*/ 0xcf9f, 0xf3bb, 0xb4c0, 0xcfa0, 0xd040, 0xd041, 0xd042, 0xd043, /*0x20-0x27*/ 0xd044, 0xd045, 0xd046, 0xd047, 0xd048, 0xd049, 0xd04a, 0xd04b, /*0x28-0x2f*/ 0xd04c, 0xd04d, 0xeec3, 0xd04e, 0xd04f, 0xd050, 0xd051, 0xd052, /*0x30-0x37*/ 0xd053, 0xf3bc, 0xd054, 0xd055, 0xf3bd, 0xd056, 0xd057, 0xd058, /*0x38-0x3f*/ 0xd1aa, 0xd059, 0xd05a, 0xd05b, 0xf4ac, 0xd0c6, 0xd05c, 0xd05d, /*0x40-0x47*/ 0xd05e, 0xd05f, 0xd060, 0xd061, 0xd0d0, 0xd1dc, 0xd062, 0xd063, /*0x48-0x4f*/ 0xd064, 0xd065, 0xd066, 0xd067, 0xcfce, 0xd068, 0xd069, 0xbdd6, /*0x50-0x57*/ 0xd06a, 0xd1c3, 0xd06b, 0xd06c, 0xd06d, 0xd06e, 0xd06f, 0xd070, /*0x58-0x5f*/ 0xd071, 0xbae2, 0xe1e9, 0xd2c2, 0xf1c2, 0xb2b9, 0xd072, 0xd073, /*0x60-0x67*/ 0xb1ed, 0xf1c3, 0xd074, 0xc9c0, 0xb3c4, 0xd075, 0xd9f2, 0xd076, /*0x68-0x6f*/ 0xcba5, 0xd077, 0xf1c4, 0xd078, 0xd079, 0xd07a, 0xd07b, 0xd6d4, /*0x70-0x77*/ 0xd07c, 0xd07d, 0xd07e, 0xd080, 0xd081, 0xf1c5, 0xf4c0, 0xf1c6, /*0x78-0x7f*/ 0xd082, 0xd4ac, 0xf1c7, 0xd083, 0xb0c0, 0xf4c1, 0xd084, 0xd085, /*0x80-0x87*/ 0xf4c2, 0xd086, 0xd087, 0xb4fc, 0xd088, 0xc5db, 0xd089, 0xd08a, /*0x88-0x8f*/ 0xd08b, 0xd08c, 0xccbb, 0xd08d, 0xd08e, 0xd08f, 0xd0e4, 0xd090, /*0x90-0x97*/ 0xd091, 0xd092, 0xd093, 0xd094, 0xcde0, 0xd095, 0xd096, 0xd097, /*0x98-0x9f*/ 0xd098, 0xd099, 0xf1c8, 0xd09a, 0xd9f3, 0xd09b, 0xd09c, 0xd09d, /*0xa0-0xa7*/ 0xd09e, 0xd09f, 0xd0a0, 0xb1bb, 0xd140, 0xcfae, 0xd141, 0xd142, /*0xa8-0xaf*/ 0xd143, 0xb8a4, 0xd144, 0xd145, 0xd146, 0xd147, 0xd148, 0xf1ca, /*0xb0-0xb7*/ 0xd149, 0xd14a, 0xd14b, 0xd14c, 0xf1cb, 0xd14d, 0xd14e, 0xd14f, /*0xb8-0xbf*/ 0xd150, 0xb2c3, 0xc1d1, 0xd151, 0xd152, 0xd7b0, 0xf1c9, 0xd153, /*0xc0-0xc7*/ 0xd154, 0xf1cc, 0xd155, 0xd156, 0xd157, 0xd158, 0xf1ce, 0xd159, /*0xc8-0xcf*/ 0xd15a, 0xd15b, 0xd9f6, 0xd15c, 0xd2e1, 0xd4a3, 0xd15d, 0xd15e, /*0xd0-0xd7*/ 0xf4c3, 0xc8b9, 0xd15f, 0xd160, 0xd161, 0xd162, 0xd163, 0xf4c4, /*0xd8-0xdf*/ 0xd164, 0xd165, 0xf1cd, 0xf1cf, 0xbfe3, 0xf1d0, 0xd166, 0xd167, /*0xe0-0xe7*/ 0xf1d4, 0xd168, 0xd169, 0xd16a, 0xd16b, 0xd16c, 0xd16d, 0xd16e, /*0xe8-0xef*/ 0xf1d6, 0xf1d1, 0xd16f, 0xc9d1, 0xc5e1, 0xd170, 0xd171, 0xd172, /*0xf0-0xf7*/ 0xc2e3, 0xb9fc, 0xd173, 0xd174, 0xf1d3, 0xd175, 0xf1d5, 0xd176, /*0xf8-0xff*/ /* 0x8900 */ 0xd177, 0xd178, 0xb9d3, 0xd179, 0xd17a, 0xd17b, 0xd17c, 0xd17d, /*0x00-0x07*/ 0xd17e, 0xd180, 0xf1db, 0xd181, 0xd182, 0xd183, 0xd184, 0xd185, /*0x08-0x0f*/ 0xbad6, 0xd186, 0xb0fd, 0xf1d9, 0xd187, 0xd188, 0xd189, 0xd18a, /*0x10-0x17*/ 0xd18b, 0xf1d8, 0xf1d2, 0xf1da, 0xd18c, 0xd18d, 0xd18e, 0xd18f, /*0x18-0x1f*/ 0xd190, 0xf1d7, 0xd191, 0xd192, 0xd193, 0xc8ec, 0xd194, 0xd195, /*0x20-0x27*/ 0xd196, 0xd197, 0xcdca, 0xf1dd, 0xd198, 0xd199, 0xd19a, 0xd19b, /*0x28-0x2f*/ 0xe5bd, 0xd19c, 0xd19d, 0xd19e, 0xf1dc, 0xd19f, 0xf1de, 0xd1a0, /*0x30-0x37*/ 0xd240, 0xd241, 0xd242, 0xd243, 0xd244, 0xd245, 0xd246, 0xd247, /*0x38-0x3f*/ 0xd248, 0xf1df, 0xd249, 0xd24a, 0xcfe5, 0xd24b, 0xd24c, 0xd24d, /*0x40-0x47*/ 0xd24e, 0xd24f, 0xd250, 0xd251, 0xd252, 0xd253, 0xd254, 0xd255, /*0x48-0x4f*/ 0xd256, 0xd257, 0xd258, 0xd259, 0xd25a, 0xd25b, 0xd25c, 0xd25d, /*0x50-0x57*/ 0xd25e, 0xd25f, 0xd260, 0xd261, 0xd262, 0xd263, 0xf4c5, 0xbdf3, /*0x58-0x5f*/ 0xd264, 0xd265, 0xd266, 0xd267, 0xd268, 0xd269, 0xf1e0, 0xd26a, /*0x60-0x67*/ 0xd26b, 0xd26c, 0xd26d, 0xd26e, 0xd26f, 0xd270, 0xd271, 0xd272, /*0x68-0x6f*/ 0xd273, 0xd274, 0xd275, 0xd276, 0xd277, 0xd278, 0xd279, 0xd27a, /*0x70-0x77*/ 0xd27b, 0xd27c, 0xd27d, 0xf1e1, 0xd27e, 0xd280, 0xd281, 0xcef7, /*0x78-0x7f*/ 0xd282, 0xd2aa, 0xd283, 0xf1fb, 0xd284, 0xd285, 0xb8b2, 0xd286, /*0x80-0x87*/ 0xd287, 0xd288, 0xd289, 0xd28a, 0xd28b, 0xd28c, 0xd28d, 0xd28e, /*0x88-0x8f*/ 0xd28f, 0xd290, 0xd291, 0xd292, 0xd293, 0xd294, 0xd295, 0xd296, /*0x90-0x97*/ 0xd297, 0xd298, 0xd299, 0xd29a, 0xd29b, 0xd29c, 0xd29d, 0xd29e, /*0x98-0x9f*/ 0xd29f, 0xd2a0, 0xd340, 0xd341, 0xd342, 0xd343, 0xd344, 0xd345, /*0xa0-0xa7*/ 0xd346, 0xd347, 0xd348, 0xd349, 0xd34a, 0xd34b, 0xd34c, 0xd34d, /*0xa8-0xaf*/ 0xd34e, 0xd34f, 0xd350, 0xd351, 0xd352, 0xd353, 0xd354, 0xd355, /*0xb0-0xb7*/ 0xd356, 0xd357, 0xd358, 0xd359, 0xd35a, 0xd35b, 0xd35c, 0xd35d, /*0xb8-0xbf*/ 0xd35e, 0xbcfb, 0xb9db, 0xd35f, 0xb9e6, 0xc3d9, 0xcad3, 0xeae8, /*0xc0-0xc7*/ 0xc0c0, 0xbef5, 0xeae9, 0xeaea, 0xeaeb, 0xd360, 0xeaec, 0xeaed, /*0xc8-0xcf*/ 0xeaee, 0xeaef, 0xbdc7, 0xd361, 0xd362, 0xd363, 0xf5fb, 0xd364, /*0xd0-0xd7*/ 0xd365, 0xd366, 0xf5fd, 0xd367, 0xf5fe, 0xd368, 0xf5fc, 0xd369, /*0xd8-0xdf*/ 0xd36a, 0xd36b, 0xd36c, 0xbde2, 0xd36d, 0xf6a1, 0xb4a5, 0xd36e, /*0xe0-0xe7*/ 0xd36f, 0xd370, 0xd371, 0xf6a2, 0xd372, 0xd373, 0xd374, 0xf6a3, /*0xe8-0xef*/ 0xd375, 0xd376, 0xd377, 0xecb2, 0xd378, 0xd379, 0xd37a, 0xd37b, /*0xf0-0xf7*/ 0xd37c, 0xd37d, 0xd37e, 0xd380, 0xd381, 0xd382, 0xd383, 0xd384, /*0xf8-0xff*/ /* 0x8a00 */ 0xd1d4, 0xd385, 0xd386, 0xd387, 0xd388, 0xd389, 0xd38a, 0xd9ea, /*0x00-0x07*/ 0xd38b, 0xd38c, 0xd38d, 0xd38e, 0xd38f, 0xd390, 0xd391, 0xd392, /*0x08-0x0f*/ 0xd393, 0xd394, 0xd395, 0xd396, 0xd397, 0xd398, 0xd399, 0xd39a, /*0x10-0x17*/ 0xd39b, 0xd39c, 0xd39d, 0xd39e, 0xd39f, 0xd3a0, 0xd440, 0xd441, /*0x18-0x1f*/ 0xd442, 0xd443, 0xd444, 0xd445, 0xd446, 0xd447, 0xd448, 0xd449, /*0x20-0x27*/ 0xd44a, 0xd44b, 0xd44c, 0xd44d, 0xd44e, 0xd44f, 0xd450, 0xd451, /*0x28-0x2f*/ 0xd452, 0xd453, 0xd454, 0xd455, 0xd456, 0xd457, 0xd458, 0xd459, /*0x30-0x37*/ 0xd45a, 0xd45b, 0xd45c, 0xd45d, 0xd45e, 0xd45f, 0xf6a4, 0xd460, /*0x38-0x3f*/ 0xd461, 0xd462, 0xd463, 0xd464, 0xd465, 0xd466, 0xd467, 0xd468, /*0x40-0x47*/ 0xeeba, 0xd469, 0xd46a, 0xd46b, 0xd46c, 0xd46d, 0xd46e, 0xd46f, /*0x48-0x4f*/ 0xd470, 0xd471, 0xd472, 0xd473, 0xd474, 0xd475, 0xd476, 0xd477, /*0x50-0x57*/ 0xd478, 0xd479, 0xd47a, 0xd47b, 0xd47c, 0xd47d, 0xd47e, 0xd480, /*0x58-0x5f*/ 0xd481, 0xd482, 0xd483, 0xd484, 0xd485, 0xd486, 0xd487, 0xd488, /*0x60-0x67*/ 0xd489, 0xd48a, 0xd48b, 0xd48c, 0xd48d, 0xd48e, 0xd48f, 0xd490, /*0x68-0x6f*/ 0xd491, 0xd492, 0xd493, 0xd494, 0xd495, 0xd496, 0xd497, 0xd498, /*0x70-0x77*/ 0xd499, 0xd5b2, 0xd49a, 0xd49b, 0xd49c, 0xd49d, 0xd49e, 0xd49f, /*0x78-0x7f*/ 0xd4a0, 0xd540, 0xd541, 0xd542, 0xd543, 0xd544, 0xd545, 0xd546, /*0x80-0x87*/ 0xd547, 0xd3fe, 0xccdc, 0xd548, 0xd549, 0xd54a, 0xd54b, 0xd54c, /*0x88-0x8f*/ 0xd54d, 0xd54e, 0xd54f, 0xcac4, 0xd550, 0xd551, 0xd552, 0xd553, /*0x90-0x97*/ 0xd554, 0xd555, 0xd556, 0xd557, 0xd558, 0xd559, 0xd55a, 0xd55b, /*0x98-0x9f*/ 0xd55c, 0xd55d, 0xd55e, 0xd55f, 0xd560, 0xd561, 0xd562, 0xd563, /*0xa0-0xa7*/ 0xd564, 0xd565, 0xd566, 0xd567, 0xd568, 0xd569, 0xd56a, 0xd56b, /*0xa8-0xaf*/ 0xd56c, 0xd56d, 0xd56e, 0xd56f, 0xd570, 0xd571, 0xd572, 0xd573, /*0xb0-0xb7*/ 0xd574, 0xd575, 0xd576, 0xd577, 0xd578, 0xd579, 0xd57a, 0xd57b, /*0xb8-0xbf*/ 0xd57c, 0xd57d, 0xd57e, 0xd580, 0xd581, 0xd582, 0xd583, 0xd584, /*0xc0-0xc7*/ 0xd585, 0xd586, 0xd587, 0xd588, 0xd589, 0xd58a, 0xd58b, 0xd58c, /*0xc8-0xcf*/ 0xd58d, 0xd58e, 0xd58f, 0xd590, 0xd591, 0xd592, 0xd593, 0xd594, /*0xd0-0xd7*/ 0xd595, 0xd596, 0xd597, 0xd598, 0xd599, 0xd59a, 0xd59b, 0xd59c, /*0xd8-0xdf*/ 0xd59d, 0xd59e, 0xd59f, 0xd5a0, 0xd640, 0xd641, 0xd642, 0xd643, /*0xe0-0xe7*/ 0xd644, 0xd645, 0xd646, 0xd647, 0xd648, 0xd649, 0xd64a, 0xd64b, /*0xe8-0xef*/ 0xd64c, 0xd64d, 0xd64e, 0xd64f, 0xd650, 0xd651, 0xd652, 0xd653, /*0xf0-0xf7*/ 0xd654, 0xd655, 0xd656, 0xd657, 0xd658, 0xd659, 0xd65a, 0xd65b, /*0xf8-0xff*/ /* 0x8b00 */ 0xd65c, 0xd65d, 0xd65e, 0xd65f, 0xd660, 0xd661, 0xd662, 0xe5c0, /*0x00-0x07*/ 0xd663, 0xd664, 0xd665, 0xd666, 0xd667, 0xd668, 0xd669, 0xd66a, /*0x08-0x0f*/ 0xd66b, 0xd66c, 0xd66d, 0xd66e, 0xd66f, 0xd670, 0xd671, 0xd672, /*0x10-0x17*/ 0xd673, 0xd674, 0xd675, 0xd676, 0xd677, 0xd678, 0xd679, 0xd67a, /*0x18-0x1f*/ 0xd67b, 0xd67c, 0xd67d, 0xd67e, 0xd680, 0xd681, 0xf6a5, 0xd682, /*0x20-0x27*/ 0xd683, 0xd684, 0xd685, 0xd686, 0xd687, 0xd688, 0xd689, 0xd68a, /*0x28-0x2f*/ 0xd68b, 0xd68c, 0xd68d, 0xd68e, 0xd68f, 0xd690, 0xd691, 0xd692, /*0x30-0x37*/ 0xd693, 0xd694, 0xd695, 0xd696, 0xd697, 0xd698, 0xd699, 0xd69a, /*0x38-0x3f*/ 0xd69b, 0xd69c, 0xd69d, 0xd69e, 0xd69f, 0xd6a0, 0xd740, 0xd741, /*0x40-0x47*/ 0xd742, 0xd743, 0xd744, 0xd745, 0xd746, 0xd747, 0xd748, 0xd749, /*0x48-0x4f*/ 0xd74a, 0xd74b, 0xd74c, 0xd74d, 0xd74e, 0xd74f, 0xd750, 0xd751, /*0x50-0x57*/ 0xd752, 0xd753, 0xd754, 0xd755, 0xd756, 0xd757, 0xd758, 0xd759, /*0x58-0x5f*/ 0xd75a, 0xd75b, 0xd75c, 0xd75d, 0xd75e, 0xd75f, 0xbeaf, 0xd760, /*0x60-0x67*/ 0xd761, 0xd762, 0xd763, 0xd764, 0xc6a9, 0xd765, 0xd766, 0xd767, /*0x68-0x6f*/ 0xd768, 0xd769, 0xd76a, 0xd76b, 0xd76c, 0xd76d, 0xd76e, 0xd76f, /*0x70-0x77*/ 0xd770, 0xd771, 0xd772, 0xd773, 0xd774, 0xd775, 0xd776, 0xd777, /*0x78-0x7f*/ 0xd778, 0xd779, 0xd77a, 0xd77b, 0xd77c, 0xd77d, 0xd77e, 0xd780, /*0x80-0x87*/ 0xd781, 0xd782, 0xd783, 0xd784, 0xd785, 0xd786, 0xd787, 0xd788, /*0x88-0x8f*/ 0xd789, 0xd78a, 0xd78b, 0xd78c, 0xd78d, 0xd78e, 0xd78f, 0xd790, /*0x90-0x97*/ 0xd791, 0xd792, 0xd793, 0xd794, 0xd795, 0xd796, 0xd797, 0xd798, /*0x98-0x9f*/ 0xdaa5, 0xbcc6, 0xb6a9, 0xb8bc, 0xc8cf, 0xbca5, 0xdaa6, 0xdaa7, /*0xa0-0xa7*/ 0xccd6, 0xc8c3, 0xdaa8, 0xc6fd, 0xd799, 0xd1b5, 0xd2e9, 0xd1b6, /*0xa8-0xaf*/ 0xbcc7, 0xd79a, 0xbdb2, 0xbbe4, 0xdaa9, 0xdaaa, 0xd1c8, 0xdaab, /*0xb0-0xb7*/ 0xd0ed, 0xb6ef, 0xc2db, 0xd79b, 0xcbcf, 0xb7ed, 0xc9e8, 0xb7c3, /*0xb8-0xbf*/ 0xbef7, 0xd6a4, 0xdaac, 0xdaad, 0xc6c0, 0xd7e7, 0xcab6, 0xd79c, /*0xc0-0xc7*/ 0xd5a9, 0xcbdf, 0xd5ef, 0xdaae, 0xd6df, 0xb4ca, 0xdab0, 0xdaaf, /*0xc8-0xcf*/ 0xd79d, 0xd2eb, 0xdab1, 0xdab2, 0xdab3, 0xcad4, 0xdab4, 0xcaab, /*0xd0-0xd7*/ 0xdab5, 0xdab6, 0xb3cf, 0xd6ef, 0xdab7, 0xbbb0, 0xb5ae, 0xdab8, /*0xd8-0xdf*/ 0xdab9, 0xb9ee, 0xd1af, 0xd2e8, 0xdaba, 0xb8c3, 0xcfea, 0xb2ef, /*0xe0-0xe7*/ 0xdabb, 0xdabc, 0xd79e, 0xbdeb, 0xcedc, 0xd3ef, 0xdabd, 0xcef3, /*0xe8-0xef*/ 0xdabe, 0xd3d5, 0xbbe5, 0xdabf, 0xcbb5, 0xcbd0, 0xdac0, 0xc7eb, /*0xf0-0xf7*/ 0xd6ee, 0xdac1, 0xc5b5, 0xb6c1, 0xdac2, 0xb7cc, 0xbfce, 0xdac3, /*0xf8-0xff*/ /* 0x8c00 */ 0xdac4, 0xcbad, 0xdac5, 0xb5f7, 0xdac6, 0xc1c2, 0xd7bb, 0xdac7, /*0x00-0x07*/ 0xccb8, 0xd79f, 0xd2ea, 0xc4b1, 0xdac8, 0xb5fd, 0xbbd1, 0xdac9, /*0x08-0x0f*/ 0xd0b3, 0xdaca, 0xdacb, 0xcebd, 0xdacc, 0xdacd, 0xdace, 0xb2f7, /*0x10-0x17*/ 0xdad1, 0xdacf, 0xd1e8, 0xdad0, 0xc3d5, 0xdad2, 0xd7a0, 0xdad3, /*0x18-0x1f*/ 0xdad4, 0xdad5, 0xd0bb, 0xd2a5, 0xb0f9, 0xdad6, 0xc7ab, 0xdad7, /*0x20-0x27*/ 0xbdf7, 0xc3a1, 0xdad8, 0xdad9, 0xc3fd, 0xccb7, 0xdada, 0xdadb, /*0x28-0x2f*/ 0xc0be, 0xc6d7, 0xdadc, 0xdadd, 0xc7b4, 0xdade, 0xdadf, 0xb9c8, /*0x30-0x37*/ 0xd840, 0xd841, 0xd842, 0xd843, 0xd844, 0xd845, 0xd846, 0xd847, /*0x38-0x3f*/ 0xd848, 0xbbed, 0xd849, 0xd84a, 0xd84b, 0xd84c, 0xb6b9, 0xf4f8, /*0x40-0x47*/ 0xd84d, 0xf4f9, 0xd84e, 0xd84f, 0xcde3, 0xd850, 0xd851, 0xd852, /*0x48-0x4f*/ 0xd853, 0xd854, 0xd855, 0xd856, 0xd857, 0xf5b9, 0xd858, 0xd859, /*0x50-0x57*/ 0xd85a, 0xd85b, 0xebe0, 0xd85c, 0xd85d, 0xd85e, 0xd85f, 0xd860, /*0x58-0x5f*/ 0xd861, 0xcff3, 0xbbbf, 0xd862, 0xd863, 0xd864, 0xd865, 0xd866, /*0x60-0x67*/ 0xd867, 0xd868, 0xbac0, 0xd4a5, 0xd869, 0xd86a, 0xd86b, 0xd86c, /*0x68-0x6f*/ 0xd86d, 0xd86e, 0xd86f, 0xe1d9, 0xd870, 0xd871, 0xd872, 0xd873, /*0x70-0x77*/ 0xf5f4, 0xb1aa, 0xb2f2, 0xd874, 0xd875, 0xd876, 0xd877, 0xd878, /*0x78-0x7f*/ 0xd879, 0xd87a, 0xf5f5, 0xd87b, 0xd87c, 0xf5f7, 0xd87d, 0xd87e, /*0x80-0x87*/ 0xd880, 0xbad1, 0xf5f6, 0xd881, 0xc3b2, 0xd882, 0xd883, 0xd884, /*0x88-0x8f*/ 0xd885, 0xd886, 0xd887, 0xd888, 0xf5f9, 0xd889, 0xd88a, 0xd88b, /*0x90-0x97*/ 0xf5f8, 0xd88c, 0xd88d, 0xd88e, 0xd88f, 0xd890, 0xd891, 0xd892, /*0x98-0x9f*/ 0xd893, 0xd894, 0xd895, 0xd896, 0xd897, 0xd898, 0xd899, 0xd89a, /*0xa0-0xa7*/ 0xd89b, 0xd89c, 0xd89d, 0xd89e, 0xd89f, 0xd8a0, 0xd940, 0xd941, /*0xa8-0xaf*/ 0xd942, 0xd943, 0xd944, 0xd945, 0xd946, 0xd947, 0xd948, 0xd949, /*0xb0-0xb7*/ 0xd94a, 0xd94b, 0xd94c, 0xd94d, 0xd94e, 0xd94f, 0xd950, 0xd951, /*0xb8-0xbf*/ 0xd952, 0xd953, 0xd954, 0xd955, 0xd956, 0xd957, 0xd958, 0xd959, /*0xc0-0xc7*/ 0xd95a, 0xd95b, 0xd95c, 0xd95d, 0xd95e, 0xd95f, 0xd960, 0xd961, /*0xc8-0xcf*/ 0xd962, 0xd963, 0xd964, 0xd965, 0xd966, 0xd967, 0xd968, 0xd969, /*0xd0-0xd7*/ 0xd96a, 0xd96b, 0xd96c, 0xd96d, 0xd96e, 0xd96f, 0xd970, 0xd971, /*0xd8-0xdf*/ 0xd972, 0xd973, 0xd974, 0xd975, 0xd976, 0xd977, 0xd978, 0xd979, /*0xe0-0xe7*/ 0xd97a, 0xd97b, 0xd97c, 0xd97d, 0xd97e, 0xd980, 0xd981, 0xd982, /*0xe8-0xef*/ 0xd983, 0xd984, 0xd985, 0xd986, 0xd987, 0xd988, 0xd989, 0xd98a, /*0xf0-0xf7*/ 0xd98b, 0xd98c, 0xd98d, 0xd98e, 0xd98f, 0xd990, 0xd991, 0xd992, /*0xf8-0xff*/ /* 0x8d00 */ 0xd993, 0xd994, 0xd995, 0xd996, 0xd997, 0xd998, 0xd999, 0xd99a, /*0x00-0x07*/ 0xd99b, 0xd99c, 0xd99d, 0xd99e, 0xd99f, 0xd9a0, 0xda40, 0xda41, /*0x08-0x0f*/ 0xda42, 0xda43, 0xda44, 0xda45, 0xda46, 0xda47, 0xda48, 0xda49, /*0x10-0x17*/ 0xda4a, 0xda4b, 0xda4c, 0xda4d, 0xda4e, 0xb1b4, 0xd5ea, 0xb8ba, /*0x18-0x1f*/ 0xda4f, 0xb9b1, 0xb2c6, 0xd4f0, 0xcfcd, 0xb0dc, 0xd5cb, 0xbbf5, /*0x20-0x27*/ 0xd6ca, 0xb7b7, 0xccb0, 0xc6b6, 0xb1e1, 0xb9ba, 0xd6fc, 0xb9e1, /*0x28-0x2f*/ 0xb7a1, 0xbcfa, 0xeada, 0xeadb, 0xccf9, 0xb9f3, 0xeadc, 0xb4fb, /*0x30-0x37*/ 0xc3b3, 0xb7d1, 0xbad8, 0xeadd, 0xd4f4, 0xeade, 0xbcd6, 0xbbdf, /*0x38-0x3f*/ 0xeadf, 0xc1de, 0xc2b8, 0xd4df, 0xd7ca, 0xeae0, 0xeae1, 0xeae4, /*0x40-0x47*/ 0xeae2, 0xeae3, 0xc9de, 0xb8b3, 0xb6c4, 0xeae5, 0xcaea, 0xc9cd, /*0x48-0x4f*/ 0xb4cd, 0xda50, 0xda51, 0xe2d9, 0xc5e2, 0xeae6, 0xc0b5, 0xda52, /*0x50-0x57*/ 0xd7b8, 0xeae7, 0xd7ac, 0xc8fc, 0xd8d3, 0xd8cd, 0xd4de, 0xda53, /*0x58-0x5f*/ 0xd4f9, 0xc9c4, 0xd3ae, 0xb8d3, 0xb3e0, 0xda54, 0xc9e2, 0xf4f6, /*0x60-0x67*/ 0xda55, 0xda56, 0xda57, 0xbad5, 0xda58, 0xf4f7, 0xda59, 0xda5a, /*0x68-0x6f*/ 0xd7df, 0xda5b, 0xda5c, 0xf4f1, 0xb8b0, 0xd5d4, 0xb8cf, 0xc6f0, /*0x70-0x77*/ 0xda5d, 0xda5e, 0xda5f, 0xda60, 0xda61, 0xda62, 0xda63, 0xda64, /*0x78-0x7f*/ 0xda65, 0xb3c3, 0xda66, 0xda67, 0xf4f2, 0xb3ac, 0xda68, 0xda69, /*0x80-0x87*/ 0xda6a, 0xda6b, 0xd4bd, 0xc7f7, 0xda6c, 0xda6d, 0xda6e, 0xda6f, /*0x88-0x8f*/ 0xda70, 0xf4f4, 0xda71, 0xda72, 0xf4f3, 0xda73, 0xda74, 0xda75, /*0x90-0x97*/ 0xda76, 0xda77, 0xda78, 0xda79, 0xda7a, 0xda7b, 0xda7c, 0xcccb, /*0x98-0x9f*/ 0xda7d, 0xda7e, 0xda80, 0xc8a4, 0xda81, 0xda82, 0xda83, 0xda84, /*0xa0-0xa7*/ 0xda85, 0xda86, 0xda87, 0xda88, 0xda89, 0xda8a, 0xda8b, 0xda8c, /*0xa8-0xaf*/ 0xda8d, 0xf4f5, 0xda8e, 0xd7e3, 0xc5bf, 0xf5c0, 0xda8f, 0xda90, /*0xb0-0xb7*/ 0xf5bb, 0xda91, 0xf5c3, 0xda92, 0xf5c2, 0xda93, 0xd6ba, 0xf5c1, /*0xb8-0xbf*/ 0xda94, 0xda95, 0xda96, 0xd4be, 0xf5c4, 0xda97, 0xf5cc, 0xda98, /*0xc0-0xc7*/ 0xda99, 0xda9a, 0xda9b, 0xb0cf, 0xb5f8, 0xda9c, 0xf5c9, 0xf5ca, /*0xc8-0xcf*/ 0xda9d, 0xc5dc, 0xda9e, 0xda9f, 0xdaa0, 0xdb40, 0xf5c5, 0xf5c6, /*0xd0-0xd7*/ 0xdb41, 0xdb42, 0xf5c7, 0xf5cb, 0xdb43, 0xbee0, 0xf5c8, 0xb8fa, /*0xd8-0xdf*/ 0xdb44, 0xdb45, 0xdb46, 0xf5d0, 0xf5d3, 0xdb47, 0xdb48, 0xdb49, /*0xe0-0xe7*/ 0xbfe7, 0xdb4a, 0xb9f2, 0xf5bc, 0xf5cd, 0xdb4b, 0xdb4c, 0xc2b7, /*0xe8-0xef*/ 0xdb4d, 0xdb4e, 0xdb4f, 0xccf8, 0xdb50, 0xbcf9, 0xdb51, 0xf5ce, /*0xf0-0xf7*/ 0xf5cf, 0xf5d1, 0xb6e5, 0xf5d2, 0xdb52, 0xf5d5, 0xdb53, 0xdb54, /*0xf8-0xff*/ /* 0x8e00 */ 0xdb55, 0xdb56, 0xdb57, 0xdb58, 0xdb59, 0xf5bd, 0xdb5a, 0xdb5b, /*0x00-0x07*/ 0xdb5c, 0xf5d4, 0xd3bb, 0xdb5d, 0xb3ec, 0xdb5e, 0xdb5f, 0xcca4, /*0x08-0x0f*/ 0xdb60, 0xdb61, 0xdb62, 0xdb63, 0xf5d6, 0xdb64, 0xdb65, 0xdb66, /*0x10-0x17*/ 0xdb67, 0xdb68, 0xdb69, 0xdb6a, 0xdb6b, 0xf5d7, 0xbee1, 0xf5d8, /*0x18-0x1f*/ 0xdb6c, 0xdb6d, 0xccdf, 0xf5db, 0xdb6e, 0xdb6f, 0xdb70, 0xdb71, /*0x20-0x27*/ 0xdb72, 0xb2c8, 0xd7d9, 0xdb73, 0xf5d9, 0xdb74, 0xf5da, 0xf5dc, /*0x28-0x2f*/ 0xdb75, 0xf5e2, 0xdb76, 0xdb77, 0xdb78, 0xf5e0, 0xdb79, 0xdb7a, /*0x30-0x37*/ 0xdb7b, 0xf5df, 0xf5dd, 0xdb7c, 0xdb7d, 0xf5e1, 0xdb7e, 0xdb80, /*0x38-0x3f*/ 0xf5de, 0xf5e4, 0xf5e5, 0xdb81, 0xcce3, 0xdb82, 0xdb83, 0xe5bf, /*0x40-0x47*/ 0xb5b8, 0xf5e3, 0xf5e8, 0xcca3, 0xdb84, 0xdb85, 0xdb86, 0xdb87, /*0x48-0x4f*/ 0xdb88, 0xf5e6, 0xf5e7, 0xdb89, 0xdb8a, 0xdb8b, 0xdb8c, 0xdb8d, /*0x50-0x57*/ 0xdb8e, 0xf5be, 0xdb8f, 0xdb90, 0xdb91, 0xdb92, 0xdb93, 0xdb94, /*0x58-0x5f*/ 0xdb95, 0xdb96, 0xdb97, 0xdb98, 0xdb99, 0xdb9a, 0xb1c4, 0xdb9b, /*0x60-0x67*/ 0xdb9c, 0xf5bf, 0xdb9d, 0xdb9e, 0xb5c5, 0xb2e4, 0xdb9f, 0xf5ec, /*0x68-0x6f*/ 0xf5e9, 0xdba0, 0xb6d7, 0xdc40, 0xf5ed, 0xdc41, 0xf5ea, 0xdc42, /*0x70-0x77*/ 0xdc43, 0xdc44, 0xdc45, 0xdc46, 0xf5eb, 0xdc47, 0xdc48, 0xb4da, /*0x78-0x7f*/ 0xdc49, 0xd4ea, 0xdc4a, 0xdc4b, 0xdc4c, 0xf5ee, 0xdc4d, 0xb3f9, /*0x80-0x87*/ 0xdc4e, 0xdc4f, 0xdc50, 0xdc51, 0xdc52, 0xdc53, 0xdc54, 0xf5ef, /*0x88-0x8f*/ 0xf5f1, 0xdc55, 0xdc56, 0xdc57, 0xf5f0, 0xdc58, 0xdc59, 0xdc5a, /*0x90-0x97*/ 0xdc5b, 0xdc5c, 0xdc5d, 0xdc5e, 0xf5f2, 0xdc5f, 0xf5f3, 0xdc60, /*0x98-0x9f*/ 0xdc61, 0xdc62, 0xdc63, 0xdc64, 0xdc65, 0xdc66, 0xdc67, 0xdc68, /*0xa0-0xa7*/ 0xdc69, 0xdc6a, 0xdc6b, 0xc9ed, 0xb9aa, 0xdc6c, 0xdc6d, 0xc7fb, /*0xa8-0xaf*/ 0xdc6e, 0xdc6f, 0xb6e3, 0xdc70, 0xdc71, 0xdc72, 0xdc73, 0xdc74, /*0xb0-0xb7*/ 0xdc75, 0xdc76, 0xccc9, 0xdc77, 0xdc78, 0xdc79, 0xdc7a, 0xdc7b, /*0xb8-0xbf*/ 0xdc7c, 0xdc7d, 0xdc7e, 0xdc80, 0xdc81, 0xdc82, 0xdc83, 0xdc84, /*0xc0-0xc7*/ 0xdc85, 0xdc86, 0xdc87, 0xdc88, 0xdc89, 0xdc8a, 0xeaa6, 0xdc8b, /*0xc8-0xcf*/ 0xdc8c, 0xdc8d, 0xdc8e, 0xdc8f, 0xdc90, 0xdc91, 0xdc92, 0xdc93, /*0xd0-0xd7*/ 0xdc94, 0xdc95, 0xdc96, 0xdc97, 0xdc98, 0xdc99, 0xdc9a, 0xdc9b, /*0xd8-0xdf*/ 0xdc9c, 0xdc9d, 0xdc9e, 0xdc9f, 0xdca0, 0xdd40, 0xdd41, 0xdd42, /*0xe0-0xe7*/ 0xdd43, 0xdd44, 0xdd45, 0xdd46, 0xdd47, 0xdd48, 0xdd49, 0xdd4a, /*0xe8-0xef*/ 0xdd4b, 0xdd4c, 0xdd4d, 0xdd4e, 0xdd4f, 0xdd50, 0xdd51, 0xdd52, /*0xf0-0xf7*/ 0xdd53, 0xdd54, 0xdd55, 0xdd56, 0xdd57, 0xdd58, 0xdd59, 0xdd5a, /*0xf8-0xff*/ /* 0x8f00 */ 0xdd5b, 0xdd5c, 0xdd5d, 0xdd5e, 0xdd5f, 0xdd60, 0xdd61, 0xdd62, /*0x00-0x07*/ 0xdd63, 0xdd64, 0xdd65, 0xdd66, 0xdd67, 0xdd68, 0xdd69, 0xdd6a, /*0x08-0x0f*/ 0xdd6b, 0xdd6c, 0xdd6d, 0xdd6e, 0xdd6f, 0xdd70, 0xdd71, 0xdd72, /*0x10-0x17*/ 0xdd73, 0xdd74, 0xdd75, 0xdd76, 0xdd77, 0xdd78, 0xdd79, 0xdd7a, /*0x18-0x1f*/ 0xdd7b, 0xdd7c, 0xdd7d, 0xdd7e, 0xdd80, 0xdd81, 0xdd82, 0xdd83, /*0x20-0x27*/ 0xdd84, 0xdd85, 0xdd86, 0xdd87, 0xdd88, 0xdd89, 0xdd8a, 0xdd8b, /*0x28-0x2f*/ 0xdd8c, 0xdd8d, 0xdd8e, 0xdd8f, 0xdd90, 0xdd91, 0xdd92, 0xdd93, /*0x30-0x37*/ 0xdd94, 0xdd95, 0xdd96, 0xdd97, 0xdd98, 0xdd99, 0xdd9a, 0xdd9b, /*0x38-0x3f*/ 0xdd9c, 0xdd9d, 0xdd9e, 0xdd9f, 0xdda0, 0xde40, 0xde41, 0xde42, /*0x40-0x47*/ 0xde43, 0xde44, 0xde45, 0xde46, 0xde47, 0xde48, 0xde49, 0xde4a, /*0x48-0x4f*/ 0xde4b, 0xde4c, 0xde4d, 0xde4e, 0xde4f, 0xde50, 0xde51, 0xde52, /*0x50-0x57*/ 0xde53, 0xde54, 0xde55, 0xde56, 0xde57, 0xde58, 0xde59, 0xde5a, /*0x58-0x5f*/ 0xde5b, 0xde5c, 0xde5d, 0xde5e, 0xde5f, 0xde60, 0xb3b5, 0xd4fe, /*0x60-0x67*/ 0xb9ec, 0xd0f9, 0xde61, 0xe9ed, 0xd7aa, 0xe9ee, 0xc2d6, 0xc8ed, /*0x68-0x6f*/ 0xbae4, 0xe9ef, 0xe9f0, 0xe9f1, 0xd6e1, 0xe9f2, 0xe9f3, 0xe9f5, /*0x70-0x77*/ 0xe9f4, 0xe9f6, 0xe9f7, 0xc7e1, 0xe9f8, 0xd4d8, 0xe9f9, 0xbdce, /*0x78-0x7f*/ 0xde62, 0xe9fa, 0xe9fb, 0xbdcf, 0xe9fc, 0xb8a8, 0xc1be, 0xe9fd, /*0x80-0x87*/ 0xb1b2, 0xbbd4, 0xb9f5, 0xe9fe, 0xde63, 0xeaa1, 0xeaa2, 0xeaa3, /*0x88-0x8f*/ 0xb7f8, 0xbcad, 0xde64, 0xcae4, 0xe0ce, 0xd4af, 0xcfbd, 0xd5b7, /*0x90-0x97*/ 0xeaa4, 0xd5de, 0xeaa5, 0xd0c1, 0xb9bc, 0xde65, 0xb4c7, 0xb1d9, /*0x98-0x9f*/ 0xde66, 0xde67, 0xde68, 0xc0b1, 0xde69, 0xde6a, 0xde6b, 0xde6c, /*0xa0-0xa7*/ 0xb1e6, 0xb1e7, 0xde6d, 0xb1e8, 0xde6e, 0xde6f, 0xde70, 0xde71, /*0xa8-0xaf*/ 0xb3bd, 0xc8e8, 0xde72, 0xde73, 0xde74, 0xde75, 0xe5c1, 0xde76, /*0xb0-0xb7*/ 0xde77, 0xb1df, 0xde78, 0xde79, 0xde7a, 0xc1c9, 0xb4ef, 0xde7b, /*0xb8-0xbf*/ 0xde7c, 0xc7a8, 0xd3d8, 0xde7d, 0xc6f9, 0xd1b8, 0xde7e, 0xb9fd, /*0xc0-0xc7*/ 0xc2f5, 0xde80, 0xde81, 0xde82, 0xde83, 0xde84, 0xd3ad, 0xde85, /*0xc8-0xcf*/ 0xd4cb, 0xbdfc, 0xde86, 0xe5c2, 0xb7b5, 0xe5c3, 0xde87, 0xde88, /*0xd0-0xd7*/ 0xbbb9, 0xd5e2, 0xde89, 0xbdf8, 0xd4b6, 0xcea5, 0xc1ac, 0xb3d9, /*0xd8-0xdf*/ 0xde8a, 0xde8b, 0xccf6, 0xde8c, 0xe5c6, 0xe5c4, 0xe5c8, 0xde8d, /*0xe0-0xe7*/ 0xe5ca, 0xe5c7, 0xb5cf, 0xc6c8, 0xde8e, 0xb5fc, 0xe5c5, 0xde8f, /*0xe8-0xef*/ 0xcaf6, 0xde90, 0xde91, 0xe5c9, 0xde92, 0xde93, 0xde94, 0xc3d4, /*0xf0-0xf7*/ 0xb1c5, 0xbca3, 0xde95, 0xde96, 0xde97, 0xd7b7, 0xde98, 0xde99, /*0xf8-0xff*/ /* 0x9000 */ 0xcdcb, 0xcbcd, 0xcaca, 0xccd3, 0xe5cc, 0xe5cb, 0xc4e6, 0xde9a, /*0x00-0x07*/ 0xde9b, 0xd1a1, 0xd1b7, 0xe5cd, 0xde9c, 0xe5d0, 0xde9d, 0xcdb8, /*0x08-0x0f*/ 0xd6f0, 0xe5cf, 0xb5dd, 0xde9e, 0xcdbe, 0xde9f, 0xe5d1, 0xb6ba, /*0x10-0x17*/ 0xdea0, 0xdf40, 0xcda8, 0xb9e4, 0xdf41, 0xcac5, 0xb3d1, 0xcbd9, /*0x18-0x1f*/ 0xd4ec, 0xe5d2, 0xb7ea, 0xdf42, 0xdf43, 0xdf44, 0xe5ce, 0xdf45, /*0x20-0x27*/ 0xdf46, 0xdf47, 0xdf48, 0xdf49, 0xdf4a, 0xe5d5, 0xb4fe, 0xe5d6, /*0x28-0x2f*/ 0xdf4b, 0xdf4c, 0xdf4d, 0xdf4e, 0xdf4f, 0xe5d3, 0xe5d4, 0xdf50, /*0x30-0x37*/ 0xd2dd, 0xdf51, 0xdf52, 0xc2df, 0xb1c6, 0xdf53, 0xd3e2, 0xdf54, /*0x38-0x3f*/ 0xdf55, 0xb6dd, 0xcbec, 0xdf56, 0xe5d7, 0xdf57, 0xdf58, 0xd3f6, /*0x40-0x47*/ 0xdf59, 0xdf5a, 0xdf5b, 0xdf5c, 0xdf5d, 0xb1e9, 0xdf5e, 0xb6f4, /*0x48-0x4f*/ 0xe5da, 0xe5d8, 0xe5d9, 0xb5c0, 0xdf5f, 0xdf60, 0xdf61, 0xd2c5, /*0x50-0x57*/ 0xe5dc, 0xdf62, 0xdf63, 0xe5de, 0xdf64, 0xdf65, 0xdf66, 0xdf67, /*0x58-0x5f*/ 0xdf68, 0xdf69, 0xe5dd, 0xc7b2, 0xdf6a, 0xd2a3, 0xdf6b, 0xdf6c, /*0x60-0x67*/ 0xe5db, 0xdf6d, 0xdf6e, 0xdf6f, 0xdf70, 0xd4e2, 0xd5da, 0xdf71, /*0x68-0x6f*/ 0xdf72, 0xdf73, 0xdf74, 0xdf75, 0xe5e0, 0xd7f1, 0xdf76, 0xdf77, /*0x70-0x77*/ 0xdf78, 0xdf79, 0xdf7a, 0xdf7b, 0xdf7c, 0xe5e1, 0xdf7d, 0xb1dc, /*0x78-0x7f*/ 0xd1fb, 0xdf7e, 0xe5e2, 0xe5e4, 0xdf80, 0xdf81, 0xdf82, 0xdf83, /*0x80-0x87*/ 0xe5e3, 0xdf84, 0xdf85, 0xe5e5, 0xdf86, 0xdf87, 0xdf88, 0xdf89, /*0x88-0x8f*/ 0xdf8a, 0xd2d8, 0xdf8b, 0xb5cb, 0xdf8c, 0xe7df, 0xdf8d, 0xdaf5, /*0x90-0x97*/ 0xdf8e, 0xdaf8, 0xdf8f, 0xdaf6, 0xdf90, 0xdaf7, 0xdf91, 0xdf92, /*0x98-0x9f*/ 0xdf93, 0xdafa, 0xd0cf, 0xc4c7, 0xdf94, 0xdf95, 0xb0ee, 0xdf96, /*0xa0-0xa7*/ 0xdf97, 0xdf98, 0xd0b0, 0xdf99, 0xdaf9, 0xdf9a, 0xd3ca, 0xbaaa, /*0xa8-0xaf*/ 0xdba2, 0xc7f1, 0xdf9b, 0xdafc, 0xdafb, 0xc9db, 0xdafd, 0xdf9c, /*0xb0-0xb7*/ 0xdba1, 0xd7de, 0xdafe, 0xc1da, 0xdf9d, 0xdf9e, 0xdba5, 0xdf9f, /*0xb8-0xbf*/ 0xdfa0, 0xd3f4, 0xe040, 0xe041, 0xdba7, 0xdba4, 0xe042, 0xdba8, /*0xc0-0xc7*/ 0xe043, 0xe044, 0xbdbc, 0xe045, 0xe046, 0xe047, 0xc0c9, 0xdba3, /*0xc8-0xcf*/ 0xdba6, 0xd6a3, 0xe048, 0xdba9, 0xe049, 0xe04a, 0xe04b, 0xdbad, /*0xd0-0xd7*/ 0xe04c, 0xe04d, 0xe04e, 0xdbae, 0xdbac, 0xbac2, 0xe04f, 0xe050, /*0xd8-0xdf*/ 0xe051, 0xbfa4, 0xdbab, 0xe052, 0xe053, 0xe054, 0xdbaa, 0xd4c7, /*0xe0-0xe7*/ 0xb2bf, 0xe055, 0xe056, 0xdbaf, 0xe057, 0xb9f9, 0xe058, 0xdbb0, /*0xe8-0xef*/ 0xe059, 0xe05a, 0xe05b, 0xe05c, 0xb3bb, 0xe05d, 0xe05e, 0xe05f, /*0xf0-0xf7*/ 0xb5a6, 0xe060, 0xe061, 0xe062, 0xe063, 0xb6bc, 0xdbb1, 0xe064, /*0xf8-0xff*/ /* 0x9100 */ 0xe065, 0xe066, 0xb6f5, 0xe067, 0xdbb2, 0xe068, 0xe069, 0xe06a, /*0x00-0x07*/ 0xe06b, 0xe06c, 0xe06d, 0xe06e, 0xe06f, 0xe070, 0xe071, 0xe072, /*0x08-0x0f*/ 0xe073, 0xe074, 0xe075, 0xe076, 0xe077, 0xe078, 0xe079, 0xe07a, /*0x10-0x17*/ 0xe07b, 0xb1c9, 0xe07c, 0xe07d, 0xe07e, 0xe080, 0xdbb4, 0xe081, /*0x18-0x1f*/ 0xe082, 0xe083, 0xdbb3, 0xdbb5, 0xe084, 0xe085, 0xe086, 0xe087, /*0x20-0x27*/ 0xe088, 0xe089, 0xe08a, 0xe08b, 0xe08c, 0xe08d, 0xe08e, 0xdbb7, /*0x28-0x2f*/ 0xe08f, 0xdbb6, 0xe090, 0xe091, 0xe092, 0xe093, 0xe094, 0xe095, /*0x30-0x37*/ 0xe096, 0xdbb8, 0xe097, 0xe098, 0xe099, 0xe09a, 0xe09b, 0xe09c, /*0x38-0x3f*/ 0xe09d, 0xe09e, 0xe09f, 0xdbb9, 0xe0a0, 0xe140, 0xdbba, 0xe141, /*0x40-0x47*/ 0xe142, 0xd3cf, 0xf4fa, 0xc7f5, 0xd7c3, 0xc5e4, 0xf4fc, 0xf4fd, /*0x48-0x4f*/ 0xf4fb, 0xe143, 0xbec6, 0xe144, 0xe145, 0xe146, 0xe147, 0xd0ef, /*0x50-0x57*/ 0xe148, 0xe149, 0xb7d3, 0xe14a, 0xe14b, 0xd4cd, 0xccaa, 0xe14c, /*0x58-0x5f*/ 0xe14d, 0xf5a2, 0xf5a1, 0xbaa8, 0xf4fe, 0xcbd6, 0xe14e, 0xe14f, /*0x60-0x67*/ 0xe150, 0xf5a4, 0xc0d2, 0xe151, 0xb3ea, 0xe152, 0xcdaa, 0xf5a5, /*0x68-0x6f*/ 0xf5a3, 0xbdb4, 0xf5a8, 0xe153, 0xf5a9, 0xbdcd, 0xc3b8, 0xbfe1, /*0x70-0x77*/ 0xcbe1, 0xf5aa, 0xe154, 0xe155, 0xe156, 0xf5a6, 0xf5a7, 0xc4f0, /*0x78-0x7f*/ 0xe157, 0xe158, 0xe159, 0xe15a, 0xe15b, 0xf5ac, 0xe15c, 0xb4bc, /*0x80-0x87*/ 0xe15d, 0xd7ed, 0xe15e, 0xb4d7, 0xf5ab, 0xf5ae, 0xe15f, 0xe160, /*0x88-0x8f*/ 0xf5ad, 0xf5af, 0xd0d1, 0xe161, 0xe162, 0xe163, 0xe164, 0xe165, /*0x90-0x97*/ 0xe166, 0xe167, 0xc3d1, 0xc8a9, 0xe168, 0xe169, 0xe16a, 0xe16b, /*0x98-0x9f*/ 0xe16c, 0xe16d, 0xf5b0, 0xf5b1, 0xe16e, 0xe16f, 0xe170, 0xe171, /*0xa0-0xa7*/ 0xe172, 0xe173, 0xf5b2, 0xe174, 0xe175, 0xf5b3, 0xf5b4, 0xf5b5, /*0xa8-0xaf*/ 0xe176, 0xe177, 0xe178, 0xe179, 0xf5b7, 0xf5b6, 0xe17a, 0xe17b, /*0xb0-0xb7*/ 0xe17c, 0xe17d, 0xf5b8, 0xe17e, 0xe180, 0xe181, 0xe182, 0xe183, /*0xb8-0xbf*/ 0xe184, 0xe185, 0xe186, 0xe187, 0xe188, 0xe189, 0xe18a, 0xb2c9, /*0xc0-0xc7*/ 0xe18b, 0xd3d4, 0xcacd, 0xe18c, 0xc0ef, 0xd6d8, 0xd2b0, 0xc1bf, /*0xc8-0xcf*/ 0xe18d, 0xbdf0, 0xe18e, 0xe18f, 0xe190, 0xe191, 0xe192, 0xe193, /*0xd0-0xd7*/ 0xe194, 0xe195, 0xe196, 0xe197, 0xb8aa, 0xe198, 0xe199, 0xe19a, /*0xd8-0xdf*/ 0xe19b, 0xe19c, 0xe19d, 0xe19e, 0xe19f, 0xe1a0, 0xe240, 0xe241, /*0xe0-0xe7*/ 0xe242, 0xe243, 0xe244, 0xe245, 0xe246, 0xe247, 0xe248, 0xe249, /*0xe8-0xef*/ 0xe24a, 0xe24b, 0xe24c, 0xe24d, 0xe24e, 0xe24f, 0xe250, 0xe251, /*0xf0-0xf7*/ 0xe252, 0xe253, 0xe254, 0xe255, 0xe256, 0xe257, 0xe258, 0xe259, /*0xf8-0xff*/ /* 0x9200 */ 0xe25a, 0xe25b, 0xe25c, 0xe25d, 0xe25e, 0xe25f, 0xe260, 0xe261, /*0x00-0x07*/ 0xe262, 0xe263, 0xe264, 0xe265, 0xe266, 0xe267, 0xe268, 0xe269, /*0x08-0x0f*/ 0xe26a, 0xe26b, 0xe26c, 0xe26d, 0xe26e, 0xe26f, 0xe270, 0xe271, /*0x10-0x17*/ 0xe272, 0xe273, 0xe274, 0xe275, 0xe276, 0xe277, 0xe278, 0xe279, /*0x18-0x1f*/ 0xe27a, 0xe27b, 0xe27c, 0xe27d, 0xe27e, 0xe280, 0xe281, 0xe282, /*0x20-0x27*/ 0xe283, 0xe284, 0xe285, 0xe286, 0xe287, 0xe288, 0xe289, 0xe28a, /*0x28-0x2f*/ 0xe28b, 0xe28c, 0xe28d, 0xe28e, 0xe28f, 0xe290, 0xe291, 0xe292, /*0x30-0x37*/ 0xe293, 0xe294, 0xe295, 0xe296, 0xe297, 0xe298, 0xe299, 0xe29a, /*0x38-0x3f*/ 0xe29b, 0xe29c, 0xe29d, 0xe29e, 0xe29f, 0xe2a0, 0xe340, 0xe341, /*0x40-0x47*/ 0xe342, 0xe343, 0xe344, 0xe345, 0xe346, 0xe347, 0xe348, 0xe349, /*0x48-0x4f*/ 0xe34a, 0xe34b, 0xe34c, 0xe34d, 0xe34e, 0xe34f, 0xe350, 0xe351, /*0x50-0x57*/ 0xe352, 0xe353, 0xe354, 0xe355, 0xe356, 0xe357, 0xe358, 0xe359, /*0x58-0x5f*/ 0xe35a, 0xe35b, 0xe35c, 0xe35d, 0xe35e, 0xe35f, 0xe360, 0xe361, /*0x60-0x67*/ 0xe362, 0xe363, 0xe364, 0xe365, 0xe366, 0xe367, 0xe368, 0xe369, /*0x68-0x6f*/ 0xe36a, 0xe36b, 0xe36c, 0xe36d, 0xbcf8, 0xe36e, 0xe36f, 0xe370, /*0x70-0x77*/ 0xe371, 0xe372, 0xe373, 0xe374, 0xe375, 0xe376, 0xe377, 0xe378, /*0x78-0x7f*/ 0xe379, 0xe37a, 0xe37b, 0xe37c, 0xe37d, 0xe37e, 0xe380, 0xe381, /*0x80-0x87*/ 0xe382, 0xe383, 0xe384, 0xe385, 0xe386, 0xe387, 0xf6c6, 0xe388, /*0x88-0x8f*/ 0xe389, 0xe38a, 0xe38b, 0xe38c, 0xe38d, 0xe38e, 0xe38f, 0xe390, /*0x90-0x97*/ 0xe391, 0xe392, 0xe393, 0xe394, 0xe395, 0xe396, 0xe397, 0xe398, /*0x98-0x9f*/ 0xe399, 0xe39a, 0xe39b, 0xe39c, 0xe39d, 0xe39e, 0xe39f, 0xe3a0, /*0xa0-0xa7*/ 0xe440, 0xe441, 0xe442, 0xe443, 0xe444, 0xe445, 0xf6c7, 0xe446, /*0xa8-0xaf*/ 0xe447, 0xe448, 0xe449, 0xe44a, 0xe44b, 0xe44c, 0xe44d, 0xe44e, /*0xb0-0xb7*/ 0xe44f, 0xe450, 0xe451, 0xe452, 0xe453, 0xe454, 0xe455, 0xe456, /*0xb8-0xbf*/ 0xe457, 0xe458, 0xe459, 0xe45a, 0xe45b, 0xe45c, 0xe45d, 0xe45e, /*0xc0-0xc7*/ 0xf6c8, 0xe45f, 0xe460, 0xe461, 0xe462, 0xe463, 0xe464, 0xe465, /*0xc8-0xcf*/ 0xe466, 0xe467, 0xe468, 0xe469, 0xe46a, 0xe46b, 0xe46c, 0xe46d, /*0xd0-0xd7*/ 0xe46e, 0xe46f, 0xe470, 0xe471, 0xe472, 0xe473, 0xe474, 0xe475, /*0xd8-0xdf*/ 0xe476, 0xe477, 0xe478, 0xe479, 0xe47a, 0xe47b, 0xe47c, 0xe47d, /*0xe0-0xe7*/ 0xe47e, 0xe480, 0xe481, 0xe482, 0xe483, 0xe484, 0xe485, 0xe486, /*0xe8-0xef*/ 0xe487, 0xe488, 0xe489, 0xe48a, 0xe48b, 0xe48c, 0xe48d, 0xe48e, /*0xf0-0xf7*/ 0xe48f, 0xe490, 0xe491, 0xe492, 0xe493, 0xe494, 0xe495, 0xe496, /*0xf8-0xff*/ /* 0x9300 */ 0xe497, 0xe498, 0xe499, 0xe49a, 0xe49b, 0xe49c, 0xe49d, 0xe49e, /*0x00-0x07*/ 0xe49f, 0xe4a0, 0xe540, 0xe541, 0xe542, 0xe543, 0xe544, 0xe545, /*0x08-0x0f*/ 0xe546, 0xe547, 0xe548, 0xe549, 0xe54a, 0xe54b, 0xe54c, 0xe54d, /*0x10-0x17*/ 0xe54e, 0xe54f, 0xe550, 0xe551, 0xe552, 0xe553, 0xe554, 0xe555, /*0x18-0x1f*/ 0xe556, 0xe557, 0xe558, 0xe559, 0xe55a, 0xe55b, 0xe55c, 0xe55d, /*0x20-0x27*/ 0xe55e, 0xe55f, 0xe560, 0xe561, 0xe562, 0xe563, 0xe564, 0xe565, /*0x28-0x2f*/ 0xe566, 0xe567, 0xe568, 0xe569, 0xe56a, 0xe56b, 0xe56c, 0xe56d, /*0x30-0x37*/ 0xe56e, 0xe56f, 0xe570, 0xe571, 0xe572, 0xe573, 0xf6c9, 0xe574, /*0x38-0x3f*/ 0xe575, 0xe576, 0xe577, 0xe578, 0xe579, 0xe57a, 0xe57b, 0xe57c, /*0x40-0x47*/ 0xe57d, 0xe57e, 0xe580, 0xe581, 0xe582, 0xe583, 0xe584, 0xe585, /*0x48-0x4f*/ 0xe586, 0xe587, 0xe588, 0xe589, 0xe58a, 0xe58b, 0xe58c, 0xe58d, /*0x50-0x57*/ 0xe58e, 0xe58f, 0xe590, 0xe591, 0xe592, 0xe593, 0xe594, 0xe595, /*0x58-0x5f*/ 0xe596, 0xe597, 0xe598, 0xe599, 0xe59a, 0xe59b, 0xe59c, 0xe59d, /*0x60-0x67*/ 0xe59e, 0xe59f, 0xf6ca, 0xe5a0, 0xe640, 0xe641, 0xe642, 0xe643, /*0x68-0x6f*/ 0xe644, 0xe645, 0xe646, 0xe647, 0xe648, 0xe649, 0xe64a, 0xe64b, /*0x70-0x77*/ 0xe64c, 0xe64d, 0xe64e, 0xe64f, 0xe650, 0xe651, 0xe652, 0xe653, /*0x78-0x7f*/ 0xe654, 0xe655, 0xe656, 0xe657, 0xe658, 0xe659, 0xe65a, 0xe65b, /*0x80-0x87*/ 0xe65c, 0xe65d, 0xe65e, 0xe65f, 0xe660, 0xe661, 0xe662, 0xf6cc, /*0x88-0x8f*/ 0xe663, 0xe664, 0xe665, 0xe666, 0xe667, 0xe668, 0xe669, 0xe66a, /*0x90-0x97*/ 0xe66b, 0xe66c, 0xe66d, 0xe66e, 0xe66f, 0xe670, 0xe671, 0xe672, /*0x98-0x9f*/ 0xe673, 0xe674, 0xe675, 0xe676, 0xe677, 0xe678, 0xe679, 0xe67a, /*0xa0-0xa7*/ 0xe67b, 0xe67c, 0xe67d, 0xe67e, 0xe680, 0xe681, 0xe682, 0xe683, /*0xa8-0xaf*/ 0xe684, 0xe685, 0xe686, 0xe687, 0xe688, 0xe689, 0xe68a, 0xe68b, /*0xb0-0xb7*/ 0xe68c, 0xe68d, 0xe68e, 0xe68f, 0xe690, 0xe691, 0xe692, 0xe693, /*0xb8-0xbf*/ 0xe694, 0xe695, 0xe696, 0xe697, 0xe698, 0xe699, 0xe69a, 0xe69b, /*0xc0-0xc7*/ 0xe69c, 0xe69d, 0xf6cb, 0xe69e, 0xe69f, 0xe6a0, 0xe740, 0xe741, /*0xc8-0xcf*/ 0xe742, 0xe743, 0xe744, 0xe745, 0xe746, 0xe747, 0xf7e9, 0xe748, /*0xd0-0xd7*/ 0xe749, 0xe74a, 0xe74b, 0xe74c, 0xe74d, 0xe74e, 0xe74f, 0xe750, /*0xd8-0xdf*/ 0xe751, 0xe752, 0xe753, 0xe754, 0xe755, 0xe756, 0xe757, 0xe758, /*0xe0-0xe7*/ 0xe759, 0xe75a, 0xe75b, 0xe75c, 0xe75d, 0xe75e, 0xe75f, 0xe760, /*0xe8-0xef*/ 0xe761, 0xe762, 0xe763, 0xe764, 0xe765, 0xe766, 0xe767, 0xe768, /*0xf0-0xf7*/ 0xe769, 0xe76a, 0xe76b, 0xe76c, 0xe76d, 0xe76e, 0xe76f, 0xe770, /*0xf8-0xff*/ /* 0x9400 */ 0xe771, 0xe772, 0xe773, 0xe774, 0xe775, 0xe776, 0xe777, 0xe778, /*0x00-0x07*/ 0xe779, 0xe77a, 0xe77b, 0xe77c, 0xe77d, 0xe77e, 0xe780, 0xe781, /*0x08-0x0f*/ 0xe782, 0xe783, 0xe784, 0xe785, 0xe786, 0xe787, 0xe788, 0xe789, /*0x10-0x17*/ 0xe78a, 0xe78b, 0xe78c, 0xe78d, 0xe78e, 0xe78f, 0xe790, 0xe791, /*0x18-0x1f*/ 0xe792, 0xe793, 0xe794, 0xe795, 0xe796, 0xe797, 0xe798, 0xe799, /*0x20-0x27*/ 0xe79a, 0xe79b, 0xe79c, 0xe79d, 0xe79e, 0xe79f, 0xe7a0, 0xe840, /*0x28-0x2f*/ 0xe841, 0xe842, 0xe843, 0xe844, 0xe845, 0xe846, 0xe847, 0xe848, /*0x30-0x37*/ 0xe849, 0xe84a, 0xe84b, 0xe84c, 0xe84d, 0xe84e, 0xf6cd, 0xe84f, /*0x38-0x3f*/ 0xe850, 0xe851, 0xe852, 0xe853, 0xe854, 0xe855, 0xe856, 0xe857, /*0x40-0x47*/ 0xe858, 0xe859, 0xe85a, 0xe85b, 0xe85c, 0xe85d, 0xe85e, 0xe85f, /*0x48-0x4f*/ 0xe860, 0xe861, 0xe862, 0xe863, 0xe864, 0xe865, 0xe866, 0xe867, /*0x50-0x57*/ 0xe868, 0xe869, 0xe86a, 0xe86b, 0xe86c, 0xe86d, 0xe86e, 0xe86f, /*0x58-0x5f*/ 0xe870, 0xe871, 0xe872, 0xe873, 0xe874, 0xe875, 0xe876, 0xe877, /*0x60-0x67*/ 0xe878, 0xe879, 0xe87a, 0xf6ce, 0xe87b, 0xe87c, 0xe87d, 0xe87e, /*0x68-0x6f*/ 0xe880, 0xe881, 0xe882, 0xe883, 0xe884, 0xe885, 0xe886, 0xe887, /*0x70-0x77*/ 0xe888, 0xe889, 0xe88a, 0xe88b, 0xe88c, 0xe88d, 0xe88e, 0xe88f, /*0x78-0x7f*/ 0xe890, 0xe891, 0xe892, 0xe893, 0xe894, 0xeec4, 0xeec5, 0xeec6, /*0x80-0x87*/ 0xd5eb, 0xb6a4, 0xeec8, 0xeec7, 0xeec9, 0xeeca, 0xc7a5, 0xeecb, /*0x88-0x8f*/ 0xeecc, 0xe895, 0xb7b0, 0xb5f6, 0xeecd, 0xeecf, 0xe896, 0xeece, /*0x90-0x97*/ 0xe897, 0xb8c6, 0xeed0, 0xeed1, 0xeed2, 0xb6db, 0xb3ae, 0xd6d3, /*0x98-0x9f*/ 0xc4c6, 0xb1b5, 0xb8d6, 0xeed3, 0xeed4, 0xd4bf, 0xc7d5, 0xbefb, /*0xa0-0xa7*/ 0xced9, 0xb9b3, 0xeed6, 0xeed5, 0xeed8, 0xeed7, 0xc5a5, 0xeed9, /*0xa8-0xaf*/ 0xeeda, 0xc7ae, 0xeedb, 0xc7af, 0xeedc, 0xb2a7, 0xeedd, 0xeede, /*0xb0-0xb7*/ 0xeedf, 0xeee0, 0xeee1, 0xd7ea, 0xeee2, 0xeee3, 0xbcd8, 0xeee4, /*0xb8-0xbf*/ 0xd3cb, 0xccfa, 0xb2ac, 0xc1e5, 0xeee5, 0xc7a6, 0xc3ad, 0xe898, /*0xc0-0xc7*/ 0xeee6, 0xeee7, 0xeee8, 0xeee9, 0xeeea, 0xeeeb, 0xeeec, 0xe899, /*0xc8-0xcf*/ 0xeeed, 0xeeee, 0xeeef, 0xe89a, 0xe89b, 0xeef0, 0xeef1, 0xeef2, /*0xd0-0xd7*/ 0xeef4, 0xeef3, 0xe89c, 0xeef5, 0xcdad, 0xc2c1, 0xeef6, 0xeef7, /*0xd8-0xdf*/ 0xeef8, 0xd5a1, 0xeef9, 0xcfb3, 0xeefa, 0xeefb, 0xe89d, 0xeefc, /*0xe0-0xe7*/ 0xeefd, 0xefa1, 0xeefe, 0xefa2, 0xb8f5, 0xc3fa, 0xefa3, 0xefa4, /*0xe8-0xef*/ 0xbdc2, 0xd2bf, 0xb2f9, 0xefa5, 0xefa6, 0xefa7, 0xd2f8, 0xefa8, /*0xf0-0xf7*/ 0xd6fd, 0xefa9, 0xc6cc, 0xe89e, 0xefaa, 0xefab, 0xc1b4, 0xefac, /*0xf8-0xff*/ /* 0x9500 */ 0xcffa, 0xcbf8, 0xefae, 0xefad, 0xb3fa, 0xb9f8, 0xefaf, 0xefb0, /*0x00-0x07*/ 0xd0e2, 0xefb1, 0xefb2, 0xb7e6, 0xd0bf, 0xefb3, 0xefb4, 0xefb5, /*0x08-0x0f*/ 0xc8f1, 0xcce0, 0xefb6, 0xefb7, 0xefb8, 0xefb9, 0xefba, 0xd5e0, /*0x10-0x17*/ 0xefbb, 0xb4ed, 0xc3aa, 0xefbc, 0xe89f, 0xefbd, 0xefbe, 0xefbf, /*0x18-0x1f*/ 0xe8a0, 0xcefd, 0xefc0, 0xc2e0, 0xb4b8, 0xd7b6, 0xbdf5, 0xe940, /*0x20-0x27*/ 0xcfc7, 0xefc3, 0xefc1, 0xefc2, 0xefc4, 0xb6a7, 0xbcfc, 0xbee2, /*0x28-0x2f*/ 0xc3cc, 0xefc5, 0xefc6, 0xe941, 0xefc7, 0xefcf, 0xefc8, 0xefc9, /*0x30-0x37*/ 0xefca, 0xc7c2, 0xeff1, 0xb6cd, 0xefcb, 0xe942, 0xefcc, 0xefcd, /*0x38-0x3f*/ 0xb6c6, 0xc3be, 0xefce, 0xe943, 0xefd0, 0xefd1, 0xefd2, 0xd5f2, /*0x40-0x47*/ 0xe944, 0xefd3, 0xc4f7, 0xe945, 0xefd4, 0xc4f8, 0xefd5, 0xefd6, /*0x48-0x4f*/ 0xb8e4, 0xb0f7, 0xefd7, 0xefd8, 0xefd9, 0xe946, 0xefda, 0xefdb, /*0x50-0x57*/ 0xefdc, 0xefdd, 0xe947, 0xefde, 0xbeb5, 0xefe1, 0xefdf, 0xefe0, /*0x58-0x5f*/ 0xe948, 0xefe2, 0xefe3, 0xc1cd, 0xefe4, 0xefe5, 0xefe6, 0xefe7, /*0x60-0x67*/ 0xefe8, 0xefe9, 0xefea, 0xefeb, 0xefec, 0xc0d8, 0xe949, 0xefed, /*0x68-0x6f*/ 0xc1ad, 0xefee, 0xefef, 0xeff0, 0xe94a, 0xe94b, 0xcfe2, 0xe94c, /*0x70-0x77*/ 0xe94d, 0xe94e, 0xe94f, 0xe950, 0xe951, 0xe952, 0xe953, 0xb3a4, /*0x78-0x7f*/ 0xe954, 0xe955, 0xe956, 0xe957, 0xe958, 0xe959, 0xe95a, 0xe95b, /*0x80-0x87*/ 0xe95c, 0xe95d, 0xe95e, 0xe95f, 0xe960, 0xe961, 0xe962, 0xe963, /*0x88-0x8f*/ 0xe964, 0xe965, 0xe966, 0xe967, 0xe968, 0xe969, 0xe96a, 0xe96b, /*0x90-0x97*/ 0xe96c, 0xe96d, 0xe96e, 0xe96f, 0xe970, 0xe971, 0xe972, 0xe973, /*0x98-0x9f*/ 0xe974, 0xe975, 0xe976, 0xe977, 0xe978, 0xe979, 0xe97a, 0xe97b, /*0xa0-0xa7*/ 0xe97c, 0xe97d, 0xe97e, 0xe980, 0xe981, 0xe982, 0xe983, 0xe984, /*0xa8-0xaf*/ 0xe985, 0xe986, 0xe987, 0xe988, 0xe989, 0xe98a, 0xe98b, 0xe98c, /*0xb0-0xb7*/ 0xe98d, 0xe98e, 0xe98f, 0xe990, 0xe991, 0xe992, 0xe993, 0xe994, /*0xb8-0xbf*/ 0xe995, 0xe996, 0xe997, 0xe998, 0xe999, 0xe99a, 0xe99b, 0xe99c, /*0xc0-0xc7*/ 0xe99d, 0xe99e, 0xe99f, 0xe9a0, 0xea40, 0xea41, 0xea42, 0xea43, /*0xc8-0xcf*/ 0xea44, 0xea45, 0xea46, 0xea47, 0xea48, 0xea49, 0xea4a, 0xea4b, /*0xd0-0xd7*/ 0xea4c, 0xea4d, 0xea4e, 0xea4f, 0xea50, 0xea51, 0xea52, 0xea53, /*0xd8-0xdf*/ 0xea54, 0xea55, 0xea56, 0xea57, 0xea58, 0xea59, 0xea5a, 0xea5b, /*0xe0-0xe7*/ 0xc3c5, 0xe3c5, 0xc9c1, 0xe3c6, 0xea5c, 0xb1d5, 0xceca, 0xb4b3, /*0xe8-0xef*/ 0xc8f2, 0xe3c7, 0xcfd0, 0xe3c8, 0xbce4, 0xe3c9, 0xe3ca, 0xc3c6, /*0xf0-0xf7*/ 0xd5a2, 0xc4d6, 0xb9eb, 0xcec5, 0xe3cb, 0xc3f6, 0xe3cc, 0xea5d, /*0xf8-0xff*/ /* 0x9600 */ 0xb7a7, 0xb8f3, 0xbad2, 0xe3cd, 0xe3ce, 0xd4c4, 0xe3cf, 0xea5e, /*0x00-0x07*/ 0xe3d0, 0xd1cb, 0xe3d1, 0xe3d2, 0xe3d3, 0xe3d4, 0xd1d6, 0xe3d5, /*0x08-0x0f*/ 0xb2fb, 0xc0bb, 0xe3d6, 0xea5f, 0xc0ab, 0xe3d7, 0xe3d8, 0xe3d9, /*0x10-0x17*/ 0xea60, 0xe3da, 0xe3db, 0xea61, 0xb8b7, 0xdae2, 0xea62, 0xb6d3, /*0x18-0x1f*/ 0xea63, 0xdae4, 0xdae3, 0xea64, 0xea65, 0xea66, 0xea67, 0xea68, /*0x20-0x27*/ 0xea69, 0xea6a, 0xdae6, 0xea6b, 0xea6c, 0xea6d, 0xc8ee, 0xea6e, /*0x28-0x2f*/ 0xea6f, 0xdae5, 0xb7c0, 0xd1f4, 0xd2f5, 0xd5f3, 0xbdd7, 0xea70, /*0x30-0x37*/ 0xea71, 0xea72, 0xea73, 0xd7e8, 0xdae8, 0xdae7, 0xea74, 0xb0a2, /*0x38-0x3f*/ 0xcdd3, 0xea75, 0xdae9, 0xea76, 0xb8bd, 0xbcca, 0xc2bd, 0xc2a4, /*0x40-0x47*/ 0xb3c2, 0xdaea, 0xea77, 0xc2aa, 0xc4b0, 0xbdb5, 0xea78, 0xea79, /*0x48-0x4f*/ 0xcfde, 0xea7a, 0xea7b, 0xea7c, 0xdaeb, 0xc9c2, 0xea7d, 0xea7e, /*0x50-0x57*/ 0xea80, 0xea81, 0xea82, 0xb1dd, 0xea83, 0xea84, 0xea85, 0xdaec, /*0x58-0x5f*/ 0xea86, 0xb6b8, 0xd4ba, 0xea87, 0xb3fd, 0xea88, 0xea89, 0xdaed, /*0x60-0x67*/ 0xd4c9, 0xcfd5, 0xc5e3, 0xea8a, 0xdaee, 0xea8b, 0xea8c, 0xea8d, /*0x68-0x6f*/ 0xea8e, 0xea8f, 0xdaef, 0xea90, 0xdaf0, 0xc1ea, 0xccd5, 0xcfdd, /*0x70-0x77*/ 0xea91, 0xea92, 0xea93, 0xea94, 0xea95, 0xea96, 0xea97, 0xea98, /*0x78-0x7f*/ 0xea99, 0xea9a, 0xea9b, 0xea9c, 0xea9d, 0xd3e7, 0xc2a1, 0xea9e, /*0x80-0x87*/ 0xdaf1, 0xea9f, 0xeaa0, 0xcbe5, 0xeb40, 0xdaf2, 0xeb41, 0xcbe6, /*0x88-0x8f*/ 0xd2fe, 0xeb42, 0xeb43, 0xeb44, 0xb8f4, 0xeb45, 0xeb46, 0xdaf3, /*0x90-0x97*/ 0xb0af, 0xcfb6, 0xeb47, 0xeb48, 0xd5cf, 0xeb49, 0xeb4a, 0xeb4b, /*0x98-0x9f*/ 0xeb4c, 0xeb4d, 0xeb4e, 0xeb4f, 0xeb50, 0xeb51, 0xeb52, 0xcbed, /*0xa0-0xa7*/ 0xeb53, 0xeb54, 0xeb55, 0xeb56, 0xeb57, 0xeb58, 0xeb59, 0xeb5a, /*0xa8-0xaf*/ 0xdaf4, 0xeb5b, 0xeb5c, 0xe3c4, 0xeb5d, 0xeb5e, 0xc1a5, 0xeb5f, /*0xb0-0xb7*/ 0xeb60, 0xf6bf, 0xeb61, 0xeb62, 0xf6c0, 0xf6c1, 0xc4d1, 0xeb63, /*0xb8-0xbf*/ 0xc8b8, 0xd1e3, 0xeb64, 0xeb65, 0xd0db, 0xd1c5, 0xbcaf, 0xb9cd, /*0xc0-0xc7*/ 0xeb66, 0xeff4, 0xeb67, 0xeb68, 0xb4c6, 0xd3ba, 0xf6c2, 0xb3fb, /*0xc8-0xcf*/ 0xeb69, 0xeb6a, 0xf6c3, 0xeb6b, 0xeb6c, 0xb5f1, 0xeb6d, 0xeb6e, /*0xd0-0xd7*/ 0xeb6f, 0xeb70, 0xeb71, 0xeb72, 0xeb73, 0xeb74, 0xeb75, 0xeb76, /*0xd8-0xdf*/ 0xf6c5, 0xeb77, 0xeb78, 0xeb79, 0xeb7a, 0xeb7b, 0xeb7c, 0xeb7d, /*0xe0-0xe7*/ 0xd3ea, 0xf6a7, 0xd1a9, 0xeb7e, 0xeb80, 0xeb81, 0xeb82, 0xf6a9, /*0xe8-0xef*/ 0xeb83, 0xeb84, 0xeb85, 0xf6a8, 0xeb86, 0xeb87, 0xc1e3, 0xc0d7, /*0xf0-0xf7*/ 0xeb88, 0xb1a2, 0xeb89, 0xeb8a, 0xeb8b, 0xeb8c, 0xceed, 0xeb8d, /*0xf8-0xff*/ /* 0x9700 */ 0xd0e8, 0xf6ab, 0xeb8e, 0xeb8f, 0xcff6, 0xeb90, 0xf6aa, 0xd5f0, /*0x00-0x07*/ 0xf6ac, 0xc3b9, 0xeb91, 0xeb92, 0xeb93, 0xbbf4, 0xf6ae, 0xf6ad, /*0x08-0x0f*/ 0xeb94, 0xeb95, 0xeb96, 0xc4de, 0xeb97, 0xeb98, 0xc1d8, 0xeb99, /*0x10-0x17*/ 0xeb9a, 0xeb9b, 0xeb9c, 0xeb9d, 0xcbaa, 0xeb9e, 0xcfbc, 0xeb9f, /*0x18-0x1f*/ 0xeba0, 0xec40, 0xec41, 0xec42, 0xec43, 0xec44, 0xec45, 0xec46, /*0x20-0x27*/ 0xec47, 0xec48, 0xf6af, 0xec49, 0xec4a, 0xf6b0, 0xec4b, 0xec4c, /*0x28-0x2f*/ 0xf6b1, 0xec4d, 0xc2b6, 0xec4e, 0xec4f, 0xec50, 0xec51, 0xec52, /*0x30-0x37*/ 0xb0d4, 0xc5f9, 0xec53, 0xec54, 0xec55, 0xec56, 0xf6b2, 0xec57, /*0x38-0x3f*/ 0xec58, 0xec59, 0xec5a, 0xec5b, 0xec5c, 0xec5d, 0xec5e, 0xec5f, /*0x40-0x47*/ 0xec60, 0xec61, 0xec62, 0xec63, 0xec64, 0xec65, 0xec66, 0xec67, /*0x48-0x4f*/ 0xec68, 0xec69, 0xc7e0, 0xf6a6, 0xec6a, 0xec6b, 0xbeb8, 0xec6c, /*0x50-0x57*/ 0xec6d, 0xbeb2, 0xec6e, 0xb5e5, 0xec6f, 0xec70, 0xb7c7, 0xec71, /*0x58-0x5f*/ 0xbfbf, 0xc3d2, 0xc3e6, 0xec72, 0xec73, 0xd8cc, 0xec74, 0xec75, /*0x60-0x67*/ 0xec76, 0xb8ef, 0xec77, 0xec78, 0xec79, 0xec7a, 0xec7b, 0xec7c, /*0x68-0x6f*/ 0xec7d, 0xec7e, 0xec80, 0xbdf9, 0xd1a5, 0xec81, 0xb0d0, 0xec82, /*0x70-0x77*/ 0xec83, 0xec84, 0xec85, 0xec86, 0xf7b0, 0xec87, 0xec88, 0xec89, /*0x78-0x7f*/ 0xec8a, 0xec8b, 0xec8c, 0xec8d, 0xec8e, 0xf7b1, 0xec8f, 0xec90, /*0x80-0x87*/ 0xec91, 0xec92, 0xec93, 0xd0ac, 0xec94, 0xb0b0, 0xec95, 0xec96, /*0x88-0x8f*/ 0xec97, 0xf7b2, 0xf7b3, 0xec98, 0xf7b4, 0xec99, 0xec9a, 0xec9b, /*0x90-0x97*/ 0xc7ca, 0xec9c, 0xec9d, 0xec9e, 0xec9f, 0xeca0, 0xed40, 0xed41, /*0x98-0x9f*/ 0xbecf, 0xed42, 0xed43, 0xf7b7, 0xed44, 0xed45, 0xed46, 0xed47, /*0xa0-0xa7*/ 0xed48, 0xed49, 0xed4a, 0xf7b6, 0xed4b, 0xb1de, 0xed4c, 0xf7b5, /*0xa8-0xaf*/ 0xed4d, 0xed4e, 0xf7b8, 0xed4f, 0xf7b9, 0xed50, 0xed51, 0xed52, /*0xb0-0xb7*/ 0xed53, 0xed54, 0xed55, 0xed56, 0xed57, 0xed58, 0xed59, 0xed5a, /*0xb8-0xbf*/ 0xed5b, 0xed5c, 0xed5d, 0xed5e, 0xed5f, 0xed60, 0xed61, 0xed62, /*0xc0-0xc7*/ 0xed63, 0xed64, 0xed65, 0xed66, 0xed67, 0xed68, 0xed69, 0xed6a, /*0xc8-0xcf*/ 0xed6b, 0xed6c, 0xed6d, 0xed6e, 0xed6f, 0xed70, 0xed71, 0xed72, /*0xd0-0xd7*/ 0xed73, 0xed74, 0xed75, 0xed76, 0xed77, 0xed78, 0xed79, 0xed7a, /*0xd8-0xdf*/ 0xed7b, 0xed7c, 0xed7d, 0xed7e, 0xed80, 0xed81, 0xcea4, 0xc8cd, /*0xe0-0xe7*/ 0xed82, 0xbaab, 0xe8b8, 0xe8b9, 0xe8ba, 0xbec2, 0xed83, 0xed84, /*0xe8-0xef*/ 0xed85, 0xed86, 0xed87, 0xd2f4, 0xed88, 0xd4cf, 0xc9d8, 0xed89, /*0xf0-0xf7*/ 0xed8a, 0xed8b, 0xed8c, 0xed8d, 0xed8e, 0xed8f, 0xed90, 0xed91, /*0xf8-0xff*/ /* 0x9800 */ 0xed92, 0xed93, 0xed94, 0xed95, 0xed96, 0xed97, 0xed98, 0xed99, /*0x00-0x07*/ 0xed9a, 0xed9b, 0xed9c, 0xed9d, 0xed9e, 0xed9f, 0xeda0, 0xee40, /*0x08-0x0f*/ 0xee41, 0xee42, 0xee43, 0xee44, 0xee45, 0xee46, 0xee47, 0xee48, /*0x10-0x17*/ 0xee49, 0xee4a, 0xee4b, 0xee4c, 0xee4d, 0xee4e, 0xee4f, 0xee50, /*0x18-0x1f*/ 0xee51, 0xee52, 0xee53, 0xee54, 0xee55, 0xee56, 0xee57, 0xee58, /*0x20-0x27*/ 0xee59, 0xee5a, 0xee5b, 0xee5c, 0xee5d, 0xee5e, 0xee5f, 0xee60, /*0x28-0x2f*/ 0xee61, 0xee62, 0xee63, 0xee64, 0xee65, 0xee66, 0xee67, 0xee68, /*0x30-0x37*/ 0xee69, 0xee6a, 0xee6b, 0xee6c, 0xee6d, 0xee6e, 0xee6f, 0xee70, /*0x38-0x3f*/ 0xee71, 0xee72, 0xee73, 0xee74, 0xee75, 0xee76, 0xee77, 0xee78, /*0x40-0x47*/ 0xee79, 0xee7a, 0xee7b, 0xee7c, 0xee7d, 0xee7e, 0xee80, 0xee81, /*0x48-0x4f*/ 0xee82, 0xee83, 0xee84, 0xee85, 0xee86, 0xee87, 0xee88, 0xee89, /*0x50-0x57*/ 0xee8a, 0xee8b, 0xee8c, 0xee8d, 0xee8e, 0xee8f, 0xee90, 0xee91, /*0x58-0x5f*/ 0xee92, 0xee93, 0xee94, 0xee95, 0xee96, 0xee97, 0xee98, 0xee99, /*0x60-0x67*/ 0xee9a, 0xee9b, 0xee9c, 0xee9d, 0xee9e, 0xee9f, 0xeea0, 0xef40, /*0x68-0x6f*/ 0xef41, 0xef42, 0xef43, 0xef44, 0xef45, 0xd2b3, 0xb6a5, 0xc7ea, /*0x70-0x77*/ 0xf1fc, 0xcfee, 0xcbb3, 0xd0eb, 0xe7ef, 0xcde7, 0xb9cb, 0xb6d9, /*0x78-0x7f*/ 0xf1fd, 0xb0e4, 0xcbcc, 0xf1fe, 0xd4a4, 0xc2ad, 0xc1ec, 0xc6c4, /*0x80-0x87*/ 0xbeb1, 0xf2a1, 0xbcd5, 0xef46, 0xf2a2, 0xf2a3, 0xef47, 0xf2a4, /*0x88-0x8f*/ 0xd2c3, 0xc6b5, 0xef48, 0xcdc7, 0xf2a5, 0xef49, 0xd3b1, 0xbfc5, /*0x90-0x97*/ 0xcce2, 0xef4a, 0xf2a6, 0xf2a7, 0xd1d5, 0xb6ee, 0xf2a8, 0xf2a9, /*0x98-0x9f*/ 0xb5df, 0xf2aa, 0xf2ab, 0xef4b, 0xb2fc, 0xf2ac, 0xf2ad, 0xc8a7, /*0xa0-0xa7*/ 0xef4c, 0xef4d, 0xef4e, 0xef4f, 0xef50, 0xef51, 0xef52, 0xef53, /*0xa8-0xaf*/ 0xef54, 0xef55, 0xef56, 0xef57, 0xef58, 0xef59, 0xef5a, 0xef5b, /*0xb0-0xb7*/ 0xef5c, 0xef5d, 0xef5e, 0xef5f, 0xef60, 0xef61, 0xef62, 0xef63, /*0xb8-0xbf*/ 0xef64, 0xef65, 0xef66, 0xef67, 0xef68, 0xef69, 0xef6a, 0xef6b, /*0xc0-0xc7*/ 0xef6c, 0xef6d, 0xef6e, 0xef6f, 0xef70, 0xef71, 0xb7e7, 0xef72, /*0xc8-0xcf*/ 0xef73, 0xeca9, 0xecaa, 0xecab, 0xef74, 0xecac, 0xef75, 0xef76, /*0xd0-0xd7*/ 0xc6ae, 0xecad, 0xecae, 0xef77, 0xef78, 0xef79, 0xb7c9, 0xcab3, /*0xd8-0xdf*/ 0xef7a, 0xef7b, 0xef7c, 0xef7d, 0xef7e, 0xef80, 0xef81, 0xe2b8, /*0xe0-0xe7*/ 0xf7cf, 0xef82, 0xef83, 0xef84, 0xef85, 0xef86, 0xef87, 0xef88, /*0xe8-0xef*/ 0xef89, 0xef8a, 0xef8b, 0xef8c, 0xef8d, 0xef8e, 0xef8f, 0xef90, /*0xf0-0xf7*/ 0xef91, 0xef92, 0xef93, 0xef94, 0xef95, 0xef96, 0xef97, 0xef98, /*0xf8-0xff*/ /* 0x9900 */ 0xef99, 0xef9a, 0xef9b, 0xef9c, 0xef9d, 0xef9e, 0xef9f, 0xefa0, /*0x00-0x07*/ 0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf7d0, 0xf045, 0xf046, /*0x08-0x0f*/ 0xb2cd, 0xf047, 0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, /*0x10-0x17*/ 0xf04e, 0xf04f, 0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, /*0x18-0x1f*/ 0xf056, 0xf057, 0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, /*0x20-0x27*/ 0xf05e, 0xf05f, 0xf060, 0xf061, 0xf062, 0xf063, 0xf7d1, 0xf064, /*0x28-0x2f*/ 0xf065, 0xf066, 0xf067, 0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, /*0x30-0x37*/ 0xf06d, 0xf06e, 0xf06f, 0xf070, 0xf071, 0xf072, 0xf073, 0xf074, /*0x38-0x3f*/ 0xf075, 0xf076, 0xf077, 0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, /*0x40-0x47*/ 0xf07d, 0xf07e, 0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, /*0x48-0x4f*/ 0xf086, 0xf087, 0xf088, 0xf089, 0xf7d3, 0xf7d2, 0xf08a, 0xf08b, /*0x50-0x57*/ 0xf08c, 0xf08d, 0xf08e, 0xf08f, 0xf090, 0xf091, 0xf092, 0xf093, /*0x58-0x5f*/ 0xf094, 0xf095, 0xf096, 0xe2bb, 0xf097, 0xbca2, 0xf098, 0xe2bc, /*0x60-0x67*/ 0xe2bd, 0xe2be, 0xe2bf, 0xe2c0, 0xe2c1, 0xb7b9, 0xd2fb, 0xbda4, /*0x68-0x6f*/ 0xcace, 0xb1a5, 0xcbc7, 0xf099, 0xe2c2, 0xb6fc, 0xc8c4, 0xe2c3, /*0x70-0x77*/ 0xf09a, 0xf09b, 0xbdc8, 0xf09c, 0xb1fd, 0xe2c4, 0xf09d, 0xb6f6, /*0x78-0x7f*/ 0xe2c5, 0xc4d9, 0xf09e, 0xf09f, 0xe2c6, 0xcfda, 0xb9dd, 0xe2c7, /*0x80-0x87*/ 0xc0a1, 0xf0a0, 0xe2c8, 0xb2f6, 0xf140, 0xe2c9, 0xf141, 0xc1f3, /*0x88-0x8f*/ 0xe2ca, 0xe2cb, 0xc2f8, 0xe2cc, 0xe2cd, 0xe2ce, 0xcad7, 0xd8b8, /*0x90-0x97*/ 0xd9e5, 0xcfe3, 0xf142, 0xf143, 0xf144, 0xf145, 0xf146, 0xf147, /*0x98-0x9f*/ 0xf148, 0xf149, 0xf14a, 0xf14b, 0xf14c, 0xf0a5, 0xf14d, 0xf14e, /*0xa0-0xa7*/ 0xdcb0, 0xf14f, 0xf150, 0xf151, 0xf152, 0xf153, 0xf154, 0xf155, /*0xa8-0xaf*/ 0xf156, 0xf157, 0xf158, 0xf159, 0xf15a, 0xf15b, 0xf15c, 0xf15d, /*0xb0-0xb7*/ 0xf15e, 0xf15f, 0xf160, 0xf161, 0xf162, 0xf163, 0xf164, 0xf165, /*0xb8-0xbf*/ 0xf166, 0xf167, 0xf168, 0xf169, 0xf16a, 0xf16b, 0xf16c, 0xf16d, /*0xc0-0xc7*/ 0xf16e, 0xf16f, 0xf170, 0xf171, 0xf172, 0xf173, 0xf174, 0xf175, /*0xc8-0xcf*/ 0xf176, 0xf177, 0xf178, 0xf179, 0xf17a, 0xf17b, 0xf17c, 0xf17d, /*0xd0-0xd7*/ 0xf17e, 0xf180, 0xf181, 0xf182, 0xf183, 0xf184, 0xf185, 0xf186, /*0xd8-0xdf*/ 0xf187, 0xf188, 0xf189, 0xf18a, 0xf18b, 0xf18c, 0xf18d, 0xf18e, /*0xe0-0xe7*/ 0xf18f, 0xf190, 0xf191, 0xf192, 0xf193, 0xf194, 0xf195, 0xf196, /*0xe8-0xef*/ 0xf197, 0xf198, 0xf199, 0xf19a, 0xf19b, 0xf19c, 0xf19d, 0xf19e, /*0xf0-0xf7*/ 0xf19f, 0xf1a0, 0xf240, 0xf241, 0xf242, 0xf243, 0xf244, 0xf245, /*0xf8-0xff*/ /* 0x9a00 */ 0xf246, 0xf247, 0xf248, 0xf249, 0xf24a, 0xf24b, 0xf24c, 0xf24d, /*0x00-0x07*/ 0xf24e, 0xf24f, 0xf250, 0xf251, 0xf252, 0xf253, 0xf254, 0xf255, /*0x08-0x0f*/ 0xf256, 0xf257, 0xf258, 0xf259, 0xf25a, 0xf25b, 0xf25c, 0xf25d, /*0x10-0x17*/ 0xf25e, 0xf25f, 0xf260, 0xf261, 0xf262, 0xf263, 0xf264, 0xf265, /*0x18-0x1f*/ 0xf266, 0xf267, 0xf268, 0xf269, 0xf26a, 0xf26b, 0xf26c, 0xf26d, /*0x20-0x27*/ 0xf26e, 0xf26f, 0xf270, 0xf271, 0xf272, 0xf273, 0xf274, 0xf275, /*0x28-0x2f*/ 0xf276, 0xf277, 0xf278, 0xf279, 0xf27a, 0xf27b, 0xf27c, 0xf27d, /*0x30-0x37*/ 0xf27e, 0xf280, 0xf281, 0xf282, 0xf283, 0xf284, 0xf285, 0xf286, /*0x38-0x3f*/ 0xf287, 0xf288, 0xf289, 0xf28a, 0xf28b, 0xf28c, 0xf28d, 0xf28e, /*0x40-0x47*/ 0xf28f, 0xf290, 0xf291, 0xf292, 0xf293, 0xf294, 0xf295, 0xf296, /*0x48-0x4f*/ 0xf297, 0xf298, 0xf299, 0xf29a, 0xf29b, 0xf29c, 0xf29d, 0xf29e, /*0x50-0x57*/ 0xf29f, 0xf2a0, 0xf340, 0xf341, 0xf342, 0xf343, 0xf344, 0xf345, /*0x58-0x5f*/ 0xf346, 0xf347, 0xf348, 0xf349, 0xf34a, 0xf34b, 0xf34c, 0xf34d, /*0x60-0x67*/ 0xf34e, 0xf34f, 0xf350, 0xf351, 0xc2ed, 0xd4a6, 0xcdd4, 0xd1b1, /*0x68-0x6f*/ 0xb3db, 0xc7fd, 0xf352, 0xb2b5, 0xc2bf, 0xe6e0, 0xcabb, 0xe6e1, /*0x70-0x77*/ 0xe6e2, 0xbed4, 0xe6e3, 0xd7a4, 0xcdd5, 0xe6e5, 0xbcdd, 0xe6e4, /*0x78-0x7f*/ 0xe6e6, 0xe6e7, 0xc2ee, 0xf353, 0xbdbe, 0xe6e8, 0xc2e6, 0xbaa7, /*0x80-0x87*/ 0xe6e9, 0xf354, 0xe6ea, 0xb3d2, 0xd1e9, 0xf355, 0xf356, 0xbfa5, /*0x88-0x8f*/ 0xe6eb, 0xc6ef, 0xe6ec, 0xe6ed, 0xf357, 0xf358, 0xe6ee, 0xc6ad, /*0x90-0x97*/ 0xe6ef, 0xf359, 0xc9a7, 0xe6f0, 0xe6f1, 0xe6f2, 0xe5b9, 0xe6f3, /*0x98-0x9f*/ 0xe6f4, 0xc2e2, 0xe6f5, 0xe6f6, 0xd6e8, 0xe6f7, 0xf35a, 0xe6f8, /*0xa0-0xa7*/ 0xb9c7, 0xf35b, 0xf35c, 0xf35d, 0xf35e, 0xf35f, 0xf360, 0xf361, /*0xa8-0xaf*/ 0xf7bb, 0xf7ba, 0xf362, 0xf363, 0xf364, 0xf365, 0xf7be, 0xf7bc, /*0xb0-0xb7*/ 0xbaa1, 0xf366, 0xf7bf, 0xf367, 0xf7c0, 0xf368, 0xf369, 0xf36a, /*0xb8-0xbf*/ 0xf7c2, 0xf7c1, 0xf7c4, 0xf36b, 0xf36c, 0xf7c3, 0xf36d, 0xf36e, /*0xc0-0xc7*/ 0xf36f, 0xf370, 0xf371, 0xf7c5, 0xf7c6, 0xf372, 0xf373, 0xf374, /*0xc8-0xcf*/ 0xf375, 0xf7c7, 0xf376, 0xcbe8, 0xf377, 0xf378, 0xf379, 0xf37a, /*0xd0-0xd7*/ 0xb8df, 0xf37b, 0xf37c, 0xf37d, 0xf37e, 0xf380, 0xf381, 0xf7d4, /*0xd8-0xdf*/ 0xf382, 0xf7d5, 0xf383, 0xf384, 0xf385, 0xf386, 0xf7d6, 0xf387, /*0xe0-0xe7*/ 0xf388, 0xf389, 0xf38a, 0xf7d8, 0xf38b, 0xf7da, 0xf38c, 0xf7d7, /*0xe8-0xef*/ 0xf38d, 0xf38e, 0xf38f, 0xf390, 0xf391, 0xf392, 0xf393, 0xf394, /*0xf0-0xf7*/ 0xf395, 0xf7db, 0xf396, 0xf7d9, 0xf397, 0xf398, 0xf399, 0xf39a, /*0xf8-0xff*/ /* 0x9b00 */ 0xf39b, 0xf39c, 0xf39d, 0xd7d7, 0xf39e, 0xf39f, 0xf3a0, 0xf440, /*0x00-0x07*/ 0xf7dc, 0xf441, 0xf442, 0xf443, 0xf444, 0xf445, 0xf446, 0xf7dd, /*0x08-0x0f*/ 0xf447, 0xf448, 0xf449, 0xf7de, 0xf44a, 0xf44b, 0xf44c, 0xf44d, /*0x10-0x17*/ 0xf44e, 0xf44f, 0xf450, 0xf451, 0xf452, 0xf453, 0xf454, 0xf7df, /*0x18-0x1f*/ 0xf455, 0xf456, 0xf457, 0xf7e0, 0xf458, 0xf459, 0xf45a, 0xf45b, /*0x20-0x27*/ 0xf45c, 0xf45d, 0xf45e, 0xf45f, 0xf460, 0xf461, 0xf462, 0xdbcb, /*0x28-0x2f*/ 0xf463, 0xf464, 0xd8aa, 0xf465, 0xf466, 0xf467, 0xf468, 0xf469, /*0x30-0x37*/ 0xf46a, 0xf46b, 0xf46c, 0xe5f7, 0xb9ed, 0xf46d, 0xf46e, 0xf46f, /*0x38-0x3f*/ 0xf470, 0xbffd, 0xbbea, 0xf7c9, 0xc6c7, 0xf7c8, 0xf471, 0xf7ca, /*0x40-0x47*/ 0xf7cc, 0xf7cb, 0xf472, 0xf473, 0xf474, 0xf7cd, 0xf475, 0xceba, /*0x48-0x4f*/ 0xf476, 0xf7ce, 0xf477, 0xf478, 0xc4a7, 0xf479, 0xf47a, 0xf47b, /*0x50-0x57*/ 0xf47c, 0xf47d, 0xf47e, 0xf480, 0xf481, 0xf482, 0xf483, 0xf484, /*0x58-0x5f*/ 0xf485, 0xf486, 0xf487, 0xf488, 0xf489, 0xf48a, 0xf48b, 0xf48c, /*0x60-0x67*/ 0xf48d, 0xf48e, 0xf48f, 0xf490, 0xf491, 0xf492, 0xf493, 0xf494, /*0x68-0x6f*/ 0xf495, 0xf496, 0xf497, 0xf498, 0xf499, 0xf49a, 0xf49b, 0xf49c, /*0x70-0x77*/ 0xf49d, 0xf49e, 0xf49f, 0xf4a0, 0xf540, 0xf541, 0xf542, 0xf543, /*0x78-0x7f*/ 0xf544, 0xf545, 0xf546, 0xf547, 0xf548, 0xf549, 0xf54a, 0xf54b, /*0x80-0x87*/ 0xf54c, 0xf54d, 0xf54e, 0xf54f, 0xf550, 0xf551, 0xf552, 0xf553, /*0x88-0x8f*/ 0xf554, 0xf555, 0xf556, 0xf557, 0xf558, 0xf559, 0xf55a, 0xf55b, /*0x90-0x97*/ 0xf55c, 0xf55d, 0xf55e, 0xf55f, 0xf560, 0xf561, 0xf562, 0xf563, /*0x98-0x9f*/ 0xf564, 0xf565, 0xf566, 0xf567, 0xf568, 0xf569, 0xf56a, 0xf56b, /*0xa0-0xa7*/ 0xf56c, 0xf56d, 0xf56e, 0xf56f, 0xf570, 0xf571, 0xf572, 0xf573, /*0xa8-0xaf*/ 0xf574, 0xf575, 0xf576, 0xf577, 0xf578, 0xf579, 0xf57a, 0xf57b, /*0xb0-0xb7*/ 0xf57c, 0xf57d, 0xf57e, 0xf580, 0xf581, 0xf582, 0xf583, 0xf584, /*0xb8-0xbf*/ 0xf585, 0xf586, 0xf587, 0xf588, 0xf589, 0xf58a, 0xf58b, 0xf58c, /*0xc0-0xc7*/ 0xf58d, 0xf58e, 0xf58f, 0xf590, 0xf591, 0xf592, 0xf593, 0xf594, /*0xc8-0xcf*/ 0xf595, 0xf596, 0xf597, 0xf598, 0xf599, 0xf59a, 0xf59b, 0xf59c, /*0xd0-0xd7*/ 0xf59d, 0xf59e, 0xf59f, 0xf5a0, 0xf640, 0xf641, 0xf642, 0xf643, /*0xd8-0xdf*/ 0xf644, 0xf645, 0xf646, 0xf647, 0xf648, 0xf649, 0xf64a, 0xf64b, /*0xe0-0xe7*/ 0xf64c, 0xf64d, 0xf64e, 0xf64f, 0xf650, 0xf651, 0xf652, 0xf653, /*0xe8-0xef*/ 0xf654, 0xf655, 0xf656, 0xf657, 0xf658, 0xf659, 0xf65a, 0xf65b, /*0xf0-0xf7*/ 0xf65c, 0xf65d, 0xf65e, 0xf65f, 0xf660, 0xf661, 0xf662, 0xf663, /*0xf8-0xff*/ /* 0x9c00 */ 0xf664, 0xf665, 0xf666, 0xf667, 0xf668, 0xf669, 0xf66a, 0xf66b, /*0x00-0x07*/ 0xf66c, 0xf66d, 0xf66e, 0xf66f, 0xf670, 0xf671, 0xf672, 0xf673, /*0x08-0x0f*/ 0xf674, 0xf675, 0xf676, 0xf677, 0xf678, 0xf679, 0xf67a, 0xf67b, /*0x10-0x17*/ 0xf67c, 0xf67d, 0xf67e, 0xf680, 0xf681, 0xf682, 0xf683, 0xf684, /*0x18-0x1f*/ 0xf685, 0xf686, 0xf687, 0xf688, 0xf689, 0xf68a, 0xf68b, 0xf68c, /*0x20-0x27*/ 0xf68d, 0xf68e, 0xf68f, 0xf690, 0xf691, 0xf692, 0xf693, 0xf694, /*0x28-0x2f*/ 0xf695, 0xf696, 0xf697, 0xf698, 0xf699, 0xf69a, 0xf69b, 0xf69c, /*0x30-0x37*/ 0xf69d, 0xf69e, 0xf69f, 0xf6a0, 0xf740, 0xf741, 0xf742, 0xf743, /*0x38-0x3f*/ 0xf744, 0xf745, 0xf746, 0xf747, 0xf748, 0xf749, 0xf74a, 0xf74b, /*0x40-0x47*/ 0xf74c, 0xf74d, 0xf74e, 0xf74f, 0xf750, 0xf751, 0xf752, 0xf753, /*0x48-0x4f*/ 0xf754, 0xf755, 0xf756, 0xf757, 0xf758, 0xf759, 0xf75a, 0xf75b, /*0x50-0x57*/ 0xf75c, 0xf75d, 0xf75e, 0xf75f, 0xf760, 0xf761, 0xf762, 0xf763, /*0x58-0x5f*/ 0xf764, 0xf765, 0xf766, 0xf767, 0xf768, 0xf769, 0xf76a, 0xf76b, /*0x60-0x67*/ 0xf76c, 0xf76d, 0xf76e, 0xf76f, 0xf770, 0xf771, 0xf772, 0xf773, /*0x68-0x6f*/ 0xf774, 0xf775, 0xf776, 0xf777, 0xf778, 0xf779, 0xf77a, 0xf77b, /*0x70-0x77*/ 0xf77c, 0xf77d, 0xf77e, 0xf780, 0xd3e3, 0xf781, 0xf782, 0xf6cf, /*0x78-0x7f*/ 0xf783, 0xc2b3, 0xf6d0, 0xf784, 0xf785, 0xf6d1, 0xf6d2, 0xf6d3, /*0x80-0x87*/ 0xf6d4, 0xf786, 0xf787, 0xf6d6, 0xf788, 0xb1ab, 0xf6d7, 0xf789, /*0x88-0x8f*/ 0xf6d8, 0xf6d9, 0xf6da, 0xf78a, 0xf6db, 0xf6dc, 0xf78b, 0xf78c, /*0x90-0x97*/ 0xf78d, 0xf78e, 0xf6dd, 0xf6de, 0xcfca, 0xf78f, 0xf6df, 0xf6e0, /*0x98-0x9f*/ 0xf6e1, 0xf6e2, 0xf6e3, 0xf6e4, 0xc0f0, 0xf6e5, 0xf6e6, 0xf6e7, /*0xa0-0xa7*/ 0xf6e8, 0xf6e9, 0xf790, 0xf6ea, 0xf791, 0xf6eb, 0xf6ec, 0xf792, /*0xa8-0xaf*/ 0xf6ed, 0xf6ee, 0xf6ef, 0xf6f0, 0xf6f1, 0xf6f2, 0xf6f3, 0xf6f4, /*0xb0-0xb7*/ 0xbea8, 0xf793, 0xf6f5, 0xf6f6, 0xf6f7, 0xf6f8, 0xf794, 0xf795, /*0xb8-0xbf*/ 0xf796, 0xf797, 0xf798, 0xc8fa, 0xf6f9, 0xf6fa, 0xf6fb, 0xf6fc, /*0xc0-0xc7*/ 0xf799, 0xf79a, 0xf6fd, 0xf6fe, 0xf7a1, 0xf7a2, 0xf7a3, 0xf7a4, /*0xc8-0xcf*/ 0xf7a5, 0xf79b, 0xf79c, 0xf7a6, 0xf7a7, 0xf7a8, 0xb1ee, 0xf7a9, /*0xd0-0xd7*/ 0xf7aa, 0xf7ab, 0xf79d, 0xf79e, 0xf7ac, 0xf7ad, 0xc1db, 0xf7ae, /*0xd8-0xdf*/ 0xf79f, 0xf7a0, 0xf7af, 0xf840, 0xf841, 0xf842, 0xf843, 0xf844, /*0xe0-0xe7*/ 0xf845, 0xf846, 0xf847, 0xf848, 0xf849, 0xf84a, 0xf84b, 0xf84c, /*0xe8-0xef*/ 0xf84d, 0xf84e, 0xf84f, 0xf850, 0xf851, 0xf852, 0xf853, 0xf854, /*0xf0-0xf7*/ 0xf855, 0xf856, 0xf857, 0xf858, 0xf859, 0xf85a, 0xf85b, 0xf85c, /*0xf8-0xff*/ /* 0x9d00 */ 0xf85d, 0xf85e, 0xf85f, 0xf860, 0xf861, 0xf862, 0xf863, 0xf864, /*0x00-0x07*/ 0xf865, 0xf866, 0xf867, 0xf868, 0xf869, 0xf86a, 0xf86b, 0xf86c, /*0x08-0x0f*/ 0xf86d, 0xf86e, 0xf86f, 0xf870, 0xf871, 0xf872, 0xf873, 0xf874, /*0x10-0x17*/ 0xf875, 0xf876, 0xf877, 0xf878, 0xf879, 0xf87a, 0xf87b, 0xf87c, /*0x18-0x1f*/ 0xf87d, 0xf87e, 0xf880, 0xf881, 0xf882, 0xf883, 0xf884, 0xf885, /*0x20-0x27*/ 0xf886, 0xf887, 0xf888, 0xf889, 0xf88a, 0xf88b, 0xf88c, 0xf88d, /*0x28-0x2f*/ 0xf88e, 0xf88f, 0xf890, 0xf891, 0xf892, 0xf893, 0xf894, 0xf895, /*0x30-0x37*/ 0xf896, 0xf897, 0xf898, 0xf899, 0xf89a, 0xf89b, 0xf89c, 0xf89d, /*0x38-0x3f*/ 0xf89e, 0xf89f, 0xf8a0, 0xf940, 0xf941, 0xf942, 0xf943, 0xf944, /*0x40-0x47*/ 0xf945, 0xf946, 0xf947, 0xf948, 0xf949, 0xf94a, 0xf94b, 0xf94c, /*0x48-0x4f*/ 0xf94d, 0xf94e, 0xf94f, 0xf950, 0xf951, 0xf952, 0xf953, 0xf954, /*0x50-0x57*/ 0xf955, 0xf956, 0xf957, 0xf958, 0xf959, 0xf95a, 0xf95b, 0xf95c, /*0x58-0x5f*/ 0xf95d, 0xf95e, 0xf95f, 0xf960, 0xf961, 0xf962, 0xf963, 0xf964, /*0x60-0x67*/ 0xf965, 0xf966, 0xf967, 0xf968, 0xf969, 0xf96a, 0xf96b, 0xf96c, /*0x68-0x6f*/ 0xf96d, 0xf96e, 0xf96f, 0xf970, 0xf971, 0xf972, 0xf973, 0xf974, /*0x70-0x77*/ 0xf975, 0xf976, 0xf977, 0xf978, 0xf979, 0xf97a, 0xf97b, 0xf97c, /*0x78-0x7f*/ 0xf97d, 0xf97e, 0xf980, 0xf981, 0xf982, 0xf983, 0xf984, 0xf985, /*0x80-0x87*/ 0xf986, 0xf987, 0xf988, 0xf989, 0xf98a, 0xf98b, 0xf98c, 0xf98d, /*0x88-0x8f*/ 0xf98e, 0xf98f, 0xf990, 0xf991, 0xf992, 0xf993, 0xf994, 0xf995, /*0x90-0x97*/ 0xf996, 0xf997, 0xf998, 0xf999, 0xf99a, 0xf99b, 0xf99c, 0xf99d, /*0x98-0x9f*/ 0xf99e, 0xf99f, 0xf9a0, 0xfa40, 0xfa41, 0xfa42, 0xfa43, 0xfa44, /*0xa0-0xa7*/ 0xfa45, 0xfa46, 0xfa47, 0xfa48, 0xfa49, 0xfa4a, 0xfa4b, 0xfa4c, /*0xa8-0xaf*/ 0xfa4d, 0xfa4e, 0xfa4f, 0xfa50, 0xfa51, 0xfa52, 0xfa53, 0xfa54, /*0xb0-0xb7*/ 0xfa55, 0xfa56, 0xfa57, 0xfa58, 0xfa59, 0xfa5a, 0xfa5b, 0xfa5c, /*0xb8-0xbf*/ 0xfa5d, 0xfa5e, 0xfa5f, 0xfa60, 0xfa61, 0xfa62, 0xfa63, 0xfa64, /*0xc0-0xc7*/ 0xfa65, 0xfa66, 0xfa67, 0xfa68, 0xfa69, 0xfa6a, 0xfa6b, 0xfa6c, /*0xc8-0xcf*/ 0xfa6d, 0xfa6e, 0xfa6f, 0xfa70, 0xfa71, 0xfa72, 0xfa73, 0xfa74, /*0xd0-0xd7*/ 0xfa75, 0xfa76, 0xfa77, 0xfa78, 0xfa79, 0xfa7a, 0xfa7b, 0xfa7c, /*0xd8-0xdf*/ 0xfa7d, 0xfa7e, 0xfa80, 0xfa81, 0xfa82, 0xfa83, 0xfa84, 0xfa85, /*0xe0-0xe7*/ 0xfa86, 0xfa87, 0xfa88, 0xfa89, 0xfa8a, 0xfa8b, 0xfa8c, 0xfa8d, /*0xe8-0xef*/ 0xfa8e, 0xfa8f, 0xfa90, 0xfa91, 0xfa92, 0xfa93, 0xfa94, 0xfa95, /*0xf0-0xf7*/ 0xfa96, 0xfa97, 0xfa98, 0xfa99, 0xfa9a, 0xfa9b, 0xfa9c, 0xfa9d, /*0xf8-0xff*/ /* 0x9e00 */ 0xfa9e, 0xfa9f, 0xfaa0, 0xfb40, 0xfb41, 0xfb42, 0xfb43, 0xfb44, /*0x00-0x07*/ 0xfb45, 0xfb46, 0xfb47, 0xfb48, 0xfb49, 0xfb4a, 0xfb4b, 0xfb4c, /*0x08-0x0f*/ 0xfb4d, 0xfb4e, 0xfb4f, 0xfb50, 0xfb51, 0xfb52, 0xfb53, 0xfb54, /*0x10-0x17*/ 0xfb55, 0xfb56, 0xfb57, 0xfb58, 0xfb59, 0xfb5a, 0xfb5b, 0xc4f1, /*0x18-0x1f*/ 0xf0af, 0xbca6, 0xf0b0, 0xc3f9, 0xfb5c, 0xc5b8, 0xd1bb, 0xfb5d, /*0x20-0x27*/ 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xd1bc, 0xfb5e, 0xd1ec, /*0x28-0x2f*/ 0xfb5f, 0xf0b7, 0xf0b6, 0xd4a7, 0xfb60, 0xcdd2, 0xf0b8, 0xf0ba, /*0x30-0x37*/ 0xf0b9, 0xf0bb, 0xf0bc, 0xfb61, 0xfb62, 0xb8eb, 0xf0bd, 0xbae8, /*0x38-0x3f*/ 0xfb63, 0xf0be, 0xf0bf, 0xbee9, 0xf0c0, 0xb6ec, 0xf0c1, 0xf0c2, /*0x40-0x47*/ 0xf0c3, 0xf0c4, 0xc8b5, 0xf0c5, 0xf0c6, 0xfb64, 0xf0c7, 0xc5f4, /*0x48-0x4f*/ 0xfb65, 0xf0c8, 0xfb66, 0xfb67, 0xfb68, 0xf0c9, 0xfb69, 0xf0ca, /*0x50-0x57*/ 0xf7bd, 0xfb6a, 0xf0cb, 0xf0cc, 0xf0cd, 0xfb6b, 0xf0ce, 0xfb6c, /*0x58-0x5f*/ 0xfb6d, 0xfb6e, 0xfb6f, 0xf0cf, 0xbad7, 0xfb70, 0xf0d0, 0xf0d1, /*0x60-0x67*/ 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d8, 0xfb71, 0xfb72, /*0x68-0x6f*/ 0xd3a5, 0xf0d7, 0xfb73, 0xf0d9, 0xfb74, 0xfb75, 0xfb76, 0xfb77, /*0x70-0x77*/ 0xfb78, 0xfb79, 0xfb7a, 0xfb7b, 0xfb7c, 0xfb7d, 0xf5ba, 0xc2b9, /*0x78-0x7f*/ 0xfb7e, 0xfb80, 0xf7e4, 0xfb81, 0xfb82, 0xfb83, 0xfb84, 0xf7e5, /*0x80-0x87*/ 0xf7e6, 0xfb85, 0xfb86, 0xf7e7, 0xfb87, 0xfb88, 0xfb89, 0xfb8a, /*0x88-0x8f*/ 0xfb8b, 0xfb8c, 0xf7e8, 0xc2b4, 0xfb8d, 0xfb8e, 0xfb8f, 0xfb90, /*0x90-0x97*/ 0xfb91, 0xfb92, 0xfb93, 0xfb94, 0xfb95, 0xf7ea, 0xfb96, 0xf7eb, /*0x98-0x9f*/ 0xfb97, 0xfb98, 0xfb99, 0xfb9a, 0xfb9b, 0xfb9c, 0xc2f3, 0xfb9d, /*0xa0-0xa7*/ 0xfb9e, 0xfb9f, 0xfba0, 0xfc40, 0xfc41, 0xfc42, 0xfc43, 0xfc44, /*0xa8-0xaf*/ 0xfc45, 0xfc46, 0xfc47, 0xfc48, 0xf4f0, 0xfc49, 0xfc4a, 0xfc4b, /*0xb0-0xb7*/ 0xf4ef, 0xfc4c, 0xfc4d, 0xc2e9, 0xfc4e, 0xf7e1, 0xf7e2, 0xfc4f, /*0xb8-0xbf*/ 0xfc50, 0xfc51, 0xfc52, 0xfc53, 0xbbc6, 0xfc54, 0xfc55, 0xfc56, /*0xc0-0xc7*/ 0xfc57, 0xd9e4, 0xfc58, 0xfc59, 0xfc5a, 0xcaf2, 0xc0e8, 0xf0a4, /*0xc8-0xcf*/ 0xfc5b, 0xbada, 0xfc5c, 0xfc5d, 0xc7ad, 0xfc5e, 0xfc5f, 0xfc60, /*0xd0-0xd7*/ 0xc4ac, 0xfc61, 0xfc62, 0xf7ec, 0xf7ed, 0xf7ee, 0xfc63, 0xf7f0, /*0xd8-0xdf*/ 0xf7ef, 0xfc64, 0xf7f1, 0xfc65, 0xfc66, 0xf7f4, 0xfc67, 0xf7f3, /*0xe0-0xe7*/ 0xfc68, 0xf7f2, 0xf7f5, 0xfc69, 0xfc6a, 0xfc6b, 0xfc6c, 0xf7f6, /*0xe8-0xef*/ 0xfc6d, 0xfc6e, 0xfc6f, 0xfc70, 0xfc71, 0xfc72, 0xfc73, 0xfc74, /*0xf0-0xf7*/ 0xfc75, 0xede9, 0xfc76, 0xedea, 0xedeb, 0xfc77, 0xf6bc, 0xfc78, /*0xf8-0xff*/ /* 0x9f00 */ 0xfc79, 0xfc7a, 0xfc7b, 0xfc7c, 0xfc7d, 0xfc7e, 0xfc80, 0xfc81, /*0x00-0x07*/ 0xfc82, 0xfc83, 0xfc84, 0xf6bd, 0xfc85, 0xf6be, 0xb6a6, 0xfc86, /*0x08-0x0f*/ 0xd8be, 0xfc87, 0xfc88, 0xb9c4, 0xfc89, 0xfc8a, 0xfc8b, 0xd8bb, /*0x10-0x17*/ 0xfc8c, 0xdcb1, 0xfc8d, 0xfc8e, 0xfc8f, 0xfc90, 0xfc91, 0xfc92, /*0x18-0x1f*/ 0xcaf3, 0xfc93, 0xf7f7, 0xfc94, 0xfc95, 0xfc96, 0xfc97, 0xfc98, /*0x20-0x27*/ 0xfc99, 0xfc9a, 0xfc9b, 0xfc9c, 0xf7f8, 0xfc9d, 0xfc9e, 0xf7f9, /*0x28-0x2f*/ 0xfc9f, 0xfca0, 0xfd40, 0xfd41, 0xfd42, 0xfd43, 0xfd44, 0xf7fb, /*0x30-0x37*/ 0xfd45, 0xf7fa, 0xfd46, 0xb1c7, 0xfd47, 0xf7fc, 0xf7fd, 0xfd48, /*0x38-0x3f*/ 0xfd49, 0xfd4a, 0xfd4b, 0xfd4c, 0xf7fe, 0xfd4d, 0xfd4e, 0xfd4f, /*0x40-0x47*/ 0xfd50, 0xfd51, 0xfd52, 0xfd53, 0xfd54, 0xfd55, 0xfd56, 0xfd57, /*0x48-0x4f*/ 0xc6eb, 0xecb4, 0xfd58, 0xfd59, 0xfd5a, 0xfd5b, 0xfd5c, 0xfd5d, /*0x50-0x57*/ 0xfd5e, 0xfd5f, 0xfd60, 0xfd61, 0xfd62, 0xfd63, 0xfd64, 0xfd65, /*0x58-0x5f*/ 0xfd66, 0xfd67, 0xfd68, 0xfd69, 0xfd6a, 0xfd6b, 0xfd6c, 0xfd6d, /*0x60-0x67*/ 0xfd6e, 0xfd6f, 0xfd70, 0xfd71, 0xfd72, 0xfd73, 0xfd74, 0xfd75, /*0x68-0x6f*/ 0xfd76, 0xfd77, 0xfd78, 0xfd79, 0xfd7a, 0xfd7b, 0xfd7c, 0xfd7d, /*0x70-0x77*/ 0xfd7e, 0xfd80, 0xfd81, 0xfd82, 0xfd83, 0xfd84, 0xfd85, 0xb3dd, /*0x78-0x7f*/ 0xf6b3, 0xfd86, 0xfd87, 0xf6b4, 0xc1e4, 0xf6b5, 0xf6b6, 0xf6b7, /*0x80-0x87*/ 0xf6b8, 0xf6b9, 0xf6ba, 0xc8a3, 0xf6bb, 0xfd88, 0xfd89, 0xfd8a, /*0x88-0x8f*/ 0xfd8b, 0xfd8c, 0xfd8d, 0xfd8e, 0xfd8f, 0xfd90, 0xfd91, 0xfd92, /*0x90-0x97*/ 0xfd93, 0xc1fa, 0xb9a8, 0xede8, 0xfd94, 0xfd95, 0xfd96, 0xb9ea, /*0x98-0x9f*/ 0xd9df, 0xfd97, 0xfd98, 0xfd99, 0xfd9a, 0xfd9b, 0x0000, 0x0000, /*0xa0-0xa7*/ }; static const unsigned short cp936ext_page1f2f[32] = { 0x0000, 0xfd9d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x78-0x7f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x80-0x87*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x88-0x8f*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfd9e, 0x0000, 0x0000, /*0x90-0x97*/ }; static const unsigned short cp936ext_page1f3c[24] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfd9f, /*0xe0-0xe7*/ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xe8-0xef*/ 0x0000, 0xfda0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0xf0-0xf7*/ }; static const unsigned short cp936ext_page1f41[40] = { 0x0000, 0x0000, 0x0000, 0x0000, 0xfe40, 0xfe41, 0xfe42, 0xfe43, /*0x08-0x0f*/ 0x0000, 0xfe44, 0x0000, 0xfe45, 0xfe46, 0x0000, 0x0000, 0x0000, /*0x10-0x17*/ 0xfe47, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xfe48, /*0x18-0x1f*/ 0xfe49, 0xfe4a, 0x0000, 0xfe4b, 0xfe4c, 0x0000, 0x0000, 0xfe4d, /*0x20-0x27*/ 0xfe4e, 0xfe4f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x28-0x2f*/ }; static const unsigned short cp936ext_page1fc6[64] = { 0xa955, 0xa6f2, 0x0000, 0xa6f4, 0xa6f5, 0xa6e0, 0xa6e1, 0xa6f0, /*0x30-0x37*/ 0xa6f1, 0xa6e2, 0xa6e3, 0xa6ee, 0xa6ef, 0xa6e6, 0xa6e7, 0xa6e4, /*0x38-0x3f*/ 0xa6e5, 0xa6e8, 0xa6e9, 0xa6ea, 0xa6eb, 0x0000, 0x0000, 0x0000, /*0x40-0x47*/ 0x0000, 0xa968, 0xa969, 0xa96a, 0xa96b, 0xa96c, 0xa96d, 0xa96e, /*0x48-0x4f*/ 0xa96f, 0xa970, 0xa971, 0x0000, 0xa972, 0xa973, 0xa974, 0xa975, /*0x50-0x57*/ 0x0000, 0xa976, 0xa977, 0xa978, 0xa979, 0xa97a, 0xa97b, 0xa97c, /*0x58-0x5f*/ 0xa97d, 0xa97e, 0xa980, 0xa981, 0xa982, 0xa983, 0xa984, 0x0000, /*0x60-0x67*/ 0xa985, 0xa986, 0xa987, 0xa988, 0x0000, 0x0000, 0x0000, 0x0000, /*0x68-0x6f*/ }; static const unsigned short cp936ext_page1fe0[96] = { 0x0000, 0xa3a1, 0xa3a2, 0xa3a3, 0xa1e7, 0xa3a5, 0xa3a6, 0xa3a7, /*0x00-0x07*/ 0xa3a8, 0xa3a9, 0xa3aa, 0xa3ab, 0xa3ac, 0xa3ad, 0xa3ae, 0xa3af, /*0x08-0x0f*/ 0xa3b0, 0xa3b1, 0xa3b2, 0xa3b3, 0xa3b4, 0xa3b5, 0xa3b6, 0xa3b7, /*0x10-0x17*/ 0xa3b8, 0xa3b9, 0xa3ba, 0xa3bb, 0xa3bc, 0xa3bd, 0xa3be, 0xa3bf, /*0x18-0x1f*/ 0xa3c0, 0xa3c1, 0xa3c2, 0xa3c3, 0xa3c4, 0xa3c5, 0xa3c6, 0xa3c7, /*0x20-0x27*/ 0xa3c8, 0xa3c9, 0xa3ca, 0xa3cb, 0xa3cc, 0xa3cd, 0xa3ce, 0xa3cf, /*0x28-0x2f*/ 0xa3d0, 0xa3d1, 0xa3d2, 0xa3d3, 0xa3d4, 0xa3d5, 0xa3d6, 0xa3d7, /*0x30-0x37*/ 0xa3d8, 0xa3d9, 0xa3da, 0xa3db, 0xa3dc, 0xa3dd, 0xa3de, 0xa3df, /*0x38-0x3f*/ 0xa3e0, 0xa3e1, 0xa3e2, 0xa3e3, 0xa3e4, 0xa3e5, 0xa3e6, 0xa3e7, /*0x40-0x47*/ 0xa3e8, 0xa3e9, 0xa3ea, 0xa3eb, 0xa3ec, 0xa3ed, 0xa3ee, 0xa3ef, /*0x48-0x4f*/ 0xa3f0, 0xa3f1, 0xa3f2, 0xa3f3, 0xa3f4, 0xa3f5, 0xa3f6, 0xa3f7, /*0x50-0x57*/ 0xa3f8, 0xa3f9, 0xa3fa, 0xa3fb, 0xa3fc, 0xa3fd, 0xa1ab, 0x0000, /*0x58-0x5f*/ }; static const unsigned short cp936ext_page1ffc[8] = { 0xa1e9, 0xa1ea, 0xa956, 0xa3fe, 0xa957, 0xa3a4, 0x0000, 0x0000, /*0xe0-0xe7*/ }; static int cp936ext_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { if (n >= 2) { unsigned short c = 0; if (wc >= 0x00a0 && wc < 0x0170) c = cp936ext_page0014[wc-0x00a0]; else if (wc >= 0x01c8 && wc < 0x01e0) c = cp936ext_page0039[wc-0x01c8]; else if (wc >= 0x0250 && wc < 0x0268) c = cp936ext_page004a[wc-0x0250]; else if (wc >= 0x02c0 && wc < 0x02e0) c = cp936ext_page0058[wc-0x02c0]; else if (wc >= 0x0390 && wc < 0x03d0) c = cp936ext_page0072[wc-0x0390]; else if (wc >= 0x0400 && wc < 0x0458) c = cp936ext_page0080[wc-0x0400]; else if (wc >= 0x2010 && wc < 0x2040) c = cp936ext_page0402[wc-0x2010]; else if (wc >= 0x2100 && wc < 0x21a0) c = cp936ext_page0420[wc-0x2100]; else if (wc >= 0x2208 && wc < 0x22c0) c = cp936ext_page0441[wc-0x2208]; else if (wc == 0x2312) c = 0xa1d0; else if (wc >= 0x2460 && wc < 0x24a0) c = cp936ext_page048c[wc-0x2460]; else if (wc >= 0x2500 && wc < 0x25e8) c = cp936ext_page04a0[wc-0x2500]; else if (wc >= 0x2600 && wc < 0x2648) c = cp936ext_page04c0[wc-0x2600]; else if (wc >= 0x3000 && wc < 0x3130) c = cp936ext_page0600[wc-0x3000]; else if (wc >= 0x3220 && wc < 0x3238) c = cp936ext_page0644[wc-0x3220]; else if (wc == 0x32a3) c = 0xa949; else if (wc >= 0x3388 && wc < 0x33d8) c = cp936ext_page0671[wc-0x3388]; else if (wc >= 0x4e00 && wc < 0x9fa8) c = cp936ext_page09c0[wc-0x4e00]; else if (wc == 0xf92c) c = 0xfd9c; else if (wc >= 0xf978 && wc < 0xf998) c = cp936ext_page1f2f[wc-0xf978]; else if (wc >= 0xf9e0 && wc < 0xf9f8) c = cp936ext_page1f3c[wc-0xf9e0]; else if (wc >= 0xfa08 && wc < 0xfa30) c = cp936ext_page1f41[wc-0xfa08]; else if (wc >= 0xfe30 && wc < 0xfe70) c = cp936ext_page1fc6[wc-0xfe30]; else if (wc >= 0xff00 && wc < 0xff60) c = cp936ext_page1fe0[wc-0xff00]; else if (wc >= 0xffe0 && wc < 0xffe8) c = cp936ext_page1ffc[wc-0xffe0]; if (c != 0) { r[0] = (c >> 8); r[1] = (c & 0xff); return 2; } return RET_ILSEQ; } return RET_TOOSMALL; } #endif /* NEED_TOMB */ #endif /* CP936 */ #endif /* _WIN32 || __APPLE__ */ /* PORTME: Unicode stuff */ fltk-1.4.3/src/xutf8/lcUniConv/iso8859_5.h0000644000175000017500000000536715004135251020112 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_5.h,v 1.3 2000/11/29 17:40:32 dawes Exp $ */ /* * ISO-8859-5 */ #ifdef NEED_TOWC static const unsigned short iso8859_5_2uni[96] = { /* 0xa0 */ 0x00a0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x00ad, 0x040e, 0x040f, /* 0xb0 */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, /* 0xc0 */ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, /* 0xd0 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, /* 0xe0 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, /* 0xf0 */ 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x00a7, 0x045e, 0x045f, }; static int iso8859_5_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) iso8859_5_2uni[c-0xa0]; return 1; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_5_page00[16] = { 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, /* 0xa0-0xa7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */ }; static const unsigned char iso8859_5_page04[96] = { 0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x00-0x07 */ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0x00, 0xae, 0xaf, /* 0x08-0x0f */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x10-0x17 */ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0x18-0x1f */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x20-0x27 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x28-0x2f */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x30-0x37 */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0x38-0x3f */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x40-0x47 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x48-0x4f */ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x50-0x57 */ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0xfe, 0xff, /* 0x58-0x5f */ }; static int iso8859_5_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00b0) c = iso8859_5_page00[wc-0x00a0]; else if (wc >= 0x0400 && wc < 0x0460) c = iso8859_5_page04[wc-0x0400]; else if (wc == 0x2116) c = 0xf0; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/iso8859_9.h0000644000175000017500000000454015004135251020106 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_9.h,v 1.3 2000/11/29 17:40:32 dawes Exp $ */ /* * ISO-8859-9 */ #ifdef NEED_TOWC static const unsigned short iso8859_9_2uni[48] = { /* 0xd0 */ 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, /* 0xe0 */ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* 0xf0 */ 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, }; static int iso8859_9_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c >= 0xd0) *pwc = (ucs4_t) iso8859_9_2uni[c-0xd0]; else *pwc = (ucs4_t) c; return 1; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_9_page00[48] = { 0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0xff, /* 0xf8-0xff */ }; static const unsigned char iso8859_9_page01[72] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xf0, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0xdd, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xfe, /* 0x58-0x5f */ }; static int iso8859_9_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x00d0) { *r = wc; return 1; } else if (wc >= 0x00d0 && wc < 0x0100) c = iso8859_9_page00[wc-0x00d0]; else if (wc >= 0x0118 && wc < 0x0160) c = iso8859_9_page01[wc-0x0118]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/iso8859_7.h0000644000175000017500000000610615004135251020104 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_7.h,v 1.3 2000/11/29 17:40:32 dawes Exp $ */ /* * ISO-8859-7 */ #ifdef NEED_TOWC static const unsigned short iso8859_7_2uni[96] = { /* 0xa0 */ 0x00a0, 0x2018, 0x2019, 0x00a3, 0xfffd, 0xfffd, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0xfffd, 0x00ab, 0x00ac, 0x00ad, 0xfffd, 0x2015, /* 0xb0 */ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x0385, 0x0386, 0x00b7, 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f, /* 0xc0 */ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, /* 0xd0 */ 0x03a0, 0x03a1, 0xfffd, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, /* 0xe0 */ 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, /* 0xf0 */ 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0xfffd, }; static int iso8859_7_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) { *pwc = (ucs4_t) c; return 1; } else { unsigned short wc = iso8859_7_2uni[c-0xa0]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_7_page00[32] = { 0xa0, 0x00, 0x00, 0xa3, 0x00, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */ 0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0x00, 0x00, /* 0xa8-0xaf */ 0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0x00, 0x00, 0xb7, /* 0xb0-0xb7 */ 0x00, 0x00, 0x00, 0xbb, 0x00, 0xbd, 0x00, 0x00, /* 0xb8-0xbf */ }; static const unsigned char iso8859_7_page03[80] = { 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb5, 0xb6, 0x00, /* 0x80-0x87 */ 0xb8, 0xb9, 0xba, 0x00, 0xbc, 0x00, 0xbe, 0xbf, /* 0x88-0x8f */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x90-0x97 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x98-0x9f */ 0xd0, 0xd1, 0x00, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xa0-0xa7 */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xa8-0xaf */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xb0-0xb7 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xb8-0xbf */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xc0-0xc7 */ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00, /* 0xc8-0xcf */ }; static const unsigned char iso8859_7_page20[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, /* 0x10-0x17 */ 0xa1, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ }; static int iso8859_7_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00c0) c = iso8859_7_page00[wc-0x00a0]; else if (wc >= 0x0380 && wc < 0x03d0) c = iso8859_7_page03[wc-0x0380]; else if (wc >= 0x2010 && wc < 0x2020) c = iso8859_7_page20[wc-0x2010]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/ascii.h0000644000175000017500000000067115004135251017617 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/ascii.h,v 1.3 2000/11/29 17:40:28 dawes Exp $ */ /* * ASCII */ static int ascii_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x80) { *pwc = (ucs4_t) c; return 1; } return RET_ILSEQ; } static int ascii_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { if (wc < 0x0080) { *r = wc; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/utf8.h0000644000175000017500000000616115004135251017415 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/utf8.h,v 1.3 2000/11/28 18:50:07 dawes Exp $ */ /* * UTF-8 */ /* Specification: RFC 2279 */ static int utf8_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = s[0]; if (c < 0x80) { *pwc = c; return 1; } else if (c < 0xc2) { return RET_ILSEQ; } else if (c < 0xe0) { if (n < 2) return RET_TOOFEW(0); if (!((s[1] ^ 0x80) < 0x40)) return RET_ILSEQ; *pwc = ((ucs4_t) (c & 0x1f) << 6) | (ucs4_t) (s[1] ^ 0x80); return 2; } else if (c < 0xf0) { if (n < 3) return RET_TOOFEW(0); if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (c >= 0xe1 || s[1] >= 0xa0))) return RET_ILSEQ; *pwc = ((ucs4_t) (c & 0x0f) << 12) | ((ucs4_t) (s[1] ^ 0x80) << 6) | (ucs4_t) (s[2] ^ 0x80); return 3; } else if (c < 0xf8) { if (n < 4) return RET_TOOFEW(0); if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (c >= 0xf1 || s[1] >= 0x90))) return RET_ILSEQ; *pwc = ((ucs4_t) (c & 0x07) << 18) | ((ucs4_t) (s[1] ^ 0x80) << 12) | ((ucs4_t) (s[2] ^ 0x80) << 6) | (ucs4_t) (s[3] ^ 0x80); return 4; } else if (c < 0xfc) { if (n < 5) return RET_TOOFEW(0); if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 && (c >= 0xf9 || s[1] >= 0x88))) return RET_ILSEQ; *pwc = ((ucs4_t) (c & 0x03) << 24) | ((ucs4_t) (s[1] ^ 0x80) << 18) | ((ucs4_t) (s[2] ^ 0x80) << 12) | ((ucs4_t) (s[3] ^ 0x80) << 6) | (ucs4_t) (s[4] ^ 0x80); return 5; } else if (c < 0xfe) { if (n < 6) return RET_TOOFEW(0); if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 && (s[5] ^ 0x80) < 0x40 && (c >= 0xfd || s[1] >= 0x84))) return RET_ILSEQ; *pwc = ((ucs4_t) (c & 0x01) << 30) | ((ucs4_t) (s[1] ^ 0x80) << 24) | ((ucs4_t) (s[2] ^ 0x80) << 18) | ((ucs4_t) (s[3] ^ 0x80) << 12) | ((ucs4_t) (s[4] ^ 0x80) << 6) | (ucs4_t) (s[5] ^ 0x80); return 6; } else return RET_ILSEQ; } static int utf8_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) /* n == 0 is acceptable */ { int count; if (wc < 0x80) count = 1; else if (wc < 0x800) count = 2; else if (wc < 0x10000) count = 3; else if (wc < 0x200000) count = 4; else if (wc < 0x4000000) count = 5; else if (wc <= 0x7fffffff) count = 6; else return RET_ILSEQ; if (n < count) return RET_TOOSMALL; switch (count) { /* note: code falls through cases! */ case 6: r[5] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x4000000; case 5: r[4] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x200000; case 4: r[3] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x10000; case 3: r[2] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x800; case 2: r[1] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0xc0; case 1: r[0] = wc; } return count; } fltk-1.4.3/src/xutf8/lcUniConv/ksc5601.h0000644000175000017500000055211215004135251017625 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/ksc5601.h,v 1.5 2003/05/27 22:26:34 tsi Exp $ */ /* * KSC5601.1987-0 */ #ifdef NEED_TOWC static const unsigned short ksc5601_2uni_page21[1115] = { /* 0x21 */ 0x3000, 0x3001, 0x3002, 0x00b7, 0x2025, 0x2026, 0x00a8, 0x3003, 0x00ad, 0x2015, 0x2225, 0xff3c, 0x223c, 0x2018, 0x2019, 0x201c, 0x201d, 0x3014, 0x3015, 0x3008, 0x3009, 0x300a, 0x300b, 0x300c, 0x300d, 0x300e, 0x300f, 0x3010, 0x3011, 0x00b1, 0x00d7, 0x00f7, 0x2260, 0x2264, 0x2265, 0x221e, 0x2234, 0x00b0, 0x2032, 0x2033, 0x2103, 0x212b, 0xffe0, 0xffe1, 0xffe5, 0x2642, 0x2640, 0x2220, 0x22a5, 0x2312, 0x2202, 0x2207, 0x2261, 0x2252, 0x00a7, 0x203b, 0x2606, 0x2605, 0x25cb, 0x25cf, 0x25ce, 0x25c7, 0x25c6, 0x25a1, 0x25a0, 0x25b3, 0x25b2, 0x25bd, 0x25bc, 0x2192, 0x2190, 0x2191, 0x2193, 0x2194, 0x3013, 0x226a, 0x226b, 0x221a, 0x223d, 0x221d, 0x2235, 0x222b, 0x222c, 0x2208, 0x220b, 0x2286, 0x2287, 0x2282, 0x2283, 0x222a, 0x2229, 0x2227, 0x2228, 0xffe2, /* 0x22 */ 0x21d2, 0x21d4, 0x2200, 0x2203, 0x00b4, 0xff5e, 0x02c7, 0x02d8, 0x02dd, 0x02da, 0x02d9, 0x00b8, 0x02db, 0x00a1, 0x00bf, 0x02d0, 0x222e, 0x2211, 0x220f, 0x00a4, 0x2109, 0x2030, 0x25c1, 0x25c0, 0x25b7, 0x25b6, 0x2664, 0x2660, 0x2661, 0x2665, 0x2667, 0x2663, 0x2299, 0x25c8, 0x25a3, 0x25d0, 0x25d1, 0x2592, 0x25a4, 0x25a5, 0x25a8, 0x25a7, 0x25a6, 0x25a9, 0x2668, 0x260f, 0x260e, 0x261c, 0x261e, 0x00b6, 0x2020, 0x2021, 0x2195, 0x2197, 0x2199, 0x2196, 0x2198, 0x266d, 0x2669, 0x266a, 0x266c, 0x327f, 0x321c, 0x2116, 0x33c7, 0x2122, 0x33c2, 0x33d8, 0x2121, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x23 */ 0xff01, 0xff02, 0xff03, 0xff04, 0xff05, 0xff06, 0xff07, 0xff08, 0xff09, 0xff0a, 0xff0b, 0xff0c, 0xff0d, 0xff0e, 0xff0f, 0xff10, 0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, 0xff18, 0xff19, 0xff1a, 0xff1b, 0xff1c, 0xff1d, 0xff1e, 0xff1f, 0xff20, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0xff3b, 0xffe6, 0xff3d, 0xff3e, 0xff3f, 0xff40, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, 0xff58, 0xff59, 0xff5a, 0xff5b, 0xff5c, 0xff5d, 0xffe3, /* 0x24 */ 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f, 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147, 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160, 0x3161, 0x3162, 0x3163, 0x3164, 0x3165, 0x3166, 0x3167, 0x3168, 0x3169, 0x316a, 0x316b, 0x316c, 0x316d, 0x316e, 0x316f, 0x3170, 0x3171, 0x3172, 0x3173, 0x3174, 0x3175, 0x3176, 0x3177, 0x3178, 0x3179, 0x317a, 0x317b, 0x317c, 0x317d, 0x317e, 0x317f, 0x3180, 0x3181, 0x3182, 0x3183, 0x3184, 0x3185, 0x3186, 0x3187, 0x3188, 0x3189, 0x318a, 0x318b, 0x318c, 0x318d, 0x318e, /* 0x25 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x26 */ 0x2500, 0x2502, 0x250c, 0x2510, 0x2518, 0x2514, 0x251c, 0x252c, 0x2524, 0x2534, 0x253c, 0x2501, 0x2503, 0x250f, 0x2513, 0x251b, 0x2517, 0x2523, 0x2533, 0x252b, 0x253b, 0x254b, 0x2520, 0x252f, 0x2528, 0x2537, 0x253f, 0x251d, 0x2530, 0x2525, 0x2538, 0x2542, 0x2512, 0x2511, 0x251a, 0x2519, 0x2516, 0x2515, 0x250e, 0x250d, 0x251e, 0x251f, 0x2521, 0x2522, 0x2526, 0x2527, 0x2529, 0x252a, 0x252d, 0x252e, 0x2531, 0x2532, 0x2535, 0x2536, 0x2539, 0x253a, 0x253d, 0x253e, 0x2540, 0x2541, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x27 */ 0x3395, 0x3396, 0x3397, 0x2113, 0x3398, 0x33c4, 0x33a3, 0x33a4, 0x33a5, 0x33a6, 0x3399, 0x339a, 0x339b, 0x339c, 0x339d, 0x339e, 0x339f, 0x33a0, 0x33a1, 0x33a2, 0x33ca, 0x338d, 0x338e, 0x338f, 0x33cf, 0x3388, 0x3389, 0x33c8, 0x33a7, 0x33a8, 0x33b0, 0x33b1, 0x33b2, 0x33b3, 0x33b4, 0x33b5, 0x33b6, 0x33b7, 0x33b8, 0x33b9, 0x3380, 0x3381, 0x3382, 0x3383, 0x3384, 0x33ba, 0x33bb, 0x33bc, 0x33bd, 0x33be, 0x33bf, 0x3390, 0x3391, 0x3392, 0x3393, 0x3394, 0x2126, 0x33c0, 0x33c1, 0x338a, 0x338b, 0x338c, 0x33d6, 0x33c5, 0x33ad, 0x33ae, 0x33af, 0x33db, 0x33a9, 0x33aa, 0x33ab, 0x33ac, 0x33dd, 0x33d0, 0x33d3, 0x33c3, 0x33c9, 0x33dc, 0x33c6, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x28 */ 0x00c6, 0x00d0, 0x00aa, 0x0126, 0xfffd, 0x0132, 0xfffd, 0x013f, 0x0141, 0x00d8, 0x0152, 0x00ba, 0x00de, 0x0166, 0x014a, 0xfffd, 0x3260, 0x3261, 0x3262, 0x3263, 0x3264, 0x3265, 0x3266, 0x3267, 0x3268, 0x3269, 0x326a, 0x326b, 0x326c, 0x326d, 0x326e, 0x326f, 0x3270, 0x3271, 0x3272, 0x3273, 0x3274, 0x3275, 0x3276, 0x3277, 0x3278, 0x3279, 0x327a, 0x327b, 0x24d0, 0x24d1, 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, 0x24d8, 0x24d9, 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, 0x24e0, 0x24e1, 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, 0x24e8, 0x24e9, 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x00bd, 0x2153, 0x2154, 0x00bc, 0x00be, 0x215b, 0x215c, 0x215d, 0x215e, /* 0x29 */ 0x00e6, 0x0111, 0x00f0, 0x0127, 0x0131, 0x0133, 0x0138, 0x0140, 0x0142, 0x00f8, 0x0153, 0x00df, 0x00fe, 0x0167, 0x014b, 0x0149, 0x3200, 0x3201, 0x3202, 0x3203, 0x3204, 0x3205, 0x3206, 0x3207, 0x3208, 0x3209, 0x320a, 0x320b, 0x320c, 0x320d, 0x320e, 0x320f, 0x3210, 0x3211, 0x3212, 0x3213, 0x3214, 0x3215, 0x3216, 0x3217, 0x3218, 0x3219, 0x321a, 0x321b, 0x249c, 0x249d, 0x249e, 0x249f, 0x24a0, 0x24a1, 0x24a2, 0x24a3, 0x24a4, 0x24a5, 0x24a6, 0x24a7, 0x24a8, 0x24a9, 0x24aa, 0x24ab, 0x24ac, 0x24ad, 0x24ae, 0x24af, 0x24b0, 0x24b1, 0x24b2, 0x24b3, 0x24b4, 0x24b5, 0x2474, 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, 0x247e, 0x247f, 0x2480, 0x2481, 0x2482, 0x00b9, 0x00b2, 0x00b3, 0x2074, 0x207f, 0x2081, 0x2082, 0x2083, 0x2084, /* 0x2a */ 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, 0x304a, 0x304b, 0x304c, 0x304d, 0x304e, 0x304f, 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e, 0x305f, 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068, 0x3069, 0x306a, 0x306b, 0x306c, 0x306d, 0x306e, 0x306f, 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, 0x3078, 0x3079, 0x307a, 0x307b, 0x307c, 0x307d, 0x307e, 0x307f, 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087, 0x3088, 0x3089, 0x308a, 0x308b, 0x308c, 0x308d, 0x308e, 0x308f, 0x3090, 0x3091, 0x3092, 0x3093, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x2b */ 0x30a1, 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9, 0x30aa, 0x30ab, 0x30ac, 0x30ad, 0x30ae, 0x30af, 0x30b0, 0x30b1, 0x30b2, 0x30b3, 0x30b4, 0x30b5, 0x30b6, 0x30b7, 0x30b8, 0x30b9, 0x30ba, 0x30bb, 0x30bc, 0x30bd, 0x30be, 0x30bf, 0x30c0, 0x30c1, 0x30c2, 0x30c3, 0x30c4, 0x30c5, 0x30c6, 0x30c7, 0x30c8, 0x30c9, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d0, 0x30d1, 0x30d2, 0x30d3, 0x30d4, 0x30d5, 0x30d6, 0x30d7, 0x30d8, 0x30d9, 0x30da, 0x30db, 0x30dc, 0x30dd, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ee, 0x30ef, 0x30f0, 0x30f1, 0x30f2, 0x30f3, 0x30f4, 0x30f5, 0x30f6, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x2c */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, }; static const unsigned short ksc5601_2uni_page30[2350] = { /* 0x30 */ 0xac00, 0xac01, 0xac04, 0xac07, 0xac08, 0xac09, 0xac0a, 0xac10, 0xac11, 0xac12, 0xac13, 0xac14, 0xac15, 0xac16, 0xac17, 0xac19, 0xac1a, 0xac1b, 0xac1c, 0xac1d, 0xac20, 0xac24, 0xac2c, 0xac2d, 0xac2f, 0xac30, 0xac31, 0xac38, 0xac39, 0xac3c, 0xac40, 0xac4b, 0xac4d, 0xac54, 0xac58, 0xac5c, 0xac70, 0xac71, 0xac74, 0xac77, 0xac78, 0xac7a, 0xac80, 0xac81, 0xac83, 0xac84, 0xac85, 0xac86, 0xac89, 0xac8a, 0xac8b, 0xac8c, 0xac90, 0xac94, 0xac9c, 0xac9d, 0xac9f, 0xaca0, 0xaca1, 0xaca8, 0xaca9, 0xacaa, 0xacac, 0xacaf, 0xacb0, 0xacb8, 0xacb9, 0xacbb, 0xacbc, 0xacbd, 0xacc1, 0xacc4, 0xacc8, 0xaccc, 0xacd5, 0xacd7, 0xace0, 0xace1, 0xace4, 0xace7, 0xace8, 0xacea, 0xacec, 0xacef, 0xacf0, 0xacf1, 0xacf3, 0xacf5, 0xacf6, 0xacfc, 0xacfd, 0xad00, 0xad04, 0xad06, /* 0x31 */ 0xad0c, 0xad0d, 0xad0f, 0xad11, 0xad18, 0xad1c, 0xad20, 0xad29, 0xad2c, 0xad2d, 0xad34, 0xad35, 0xad38, 0xad3c, 0xad44, 0xad45, 0xad47, 0xad49, 0xad50, 0xad54, 0xad58, 0xad61, 0xad63, 0xad6c, 0xad6d, 0xad70, 0xad73, 0xad74, 0xad75, 0xad76, 0xad7b, 0xad7c, 0xad7d, 0xad7f, 0xad81, 0xad82, 0xad88, 0xad89, 0xad8c, 0xad90, 0xad9c, 0xad9d, 0xada4, 0xadb7, 0xadc0, 0xadc1, 0xadc4, 0xadc8, 0xadd0, 0xadd1, 0xadd3, 0xaddc, 0xade0, 0xade4, 0xadf8, 0xadf9, 0xadfc, 0xadff, 0xae00, 0xae01, 0xae08, 0xae09, 0xae0b, 0xae0d, 0xae14, 0xae30, 0xae31, 0xae34, 0xae37, 0xae38, 0xae3a, 0xae40, 0xae41, 0xae43, 0xae45, 0xae46, 0xae4a, 0xae4c, 0xae4d, 0xae4e, 0xae50, 0xae54, 0xae56, 0xae5c, 0xae5d, 0xae5f, 0xae60, 0xae61, 0xae65, 0xae68, 0xae69, 0xae6c, 0xae70, 0xae78, /* 0x32 */ 0xae79, 0xae7b, 0xae7c, 0xae7d, 0xae84, 0xae85, 0xae8c, 0xaebc, 0xaebd, 0xaebe, 0xaec0, 0xaec4, 0xaecc, 0xaecd, 0xaecf, 0xaed0, 0xaed1, 0xaed8, 0xaed9, 0xaedc, 0xaee8, 0xaeeb, 0xaeed, 0xaef4, 0xaef8, 0xaefc, 0xaf07, 0xaf08, 0xaf0d, 0xaf10, 0xaf2c, 0xaf2d, 0xaf30, 0xaf32, 0xaf34, 0xaf3c, 0xaf3d, 0xaf3f, 0xaf41, 0xaf42, 0xaf43, 0xaf48, 0xaf49, 0xaf50, 0xaf5c, 0xaf5d, 0xaf64, 0xaf65, 0xaf79, 0xaf80, 0xaf84, 0xaf88, 0xaf90, 0xaf91, 0xaf95, 0xaf9c, 0xafb8, 0xafb9, 0xafbc, 0xafc0, 0xafc7, 0xafc8, 0xafc9, 0xafcb, 0xafcd, 0xafce, 0xafd4, 0xafdc, 0xafe8, 0xafe9, 0xaff0, 0xaff1, 0xaff4, 0xaff8, 0xb000, 0xb001, 0xb004, 0xb00c, 0xb010, 0xb014, 0xb01c, 0xb01d, 0xb028, 0xb044, 0xb045, 0xb048, 0xb04a, 0xb04c, 0xb04e, 0xb053, 0xb054, 0xb055, 0xb057, 0xb059, /* 0x33 */ 0xb05d, 0xb07c, 0xb07d, 0xb080, 0xb084, 0xb08c, 0xb08d, 0xb08f, 0xb091, 0xb098, 0xb099, 0xb09a, 0xb09c, 0xb09f, 0xb0a0, 0xb0a1, 0xb0a2, 0xb0a8, 0xb0a9, 0xb0ab, 0xb0ac, 0xb0ad, 0xb0ae, 0xb0af, 0xb0b1, 0xb0b3, 0xb0b4, 0xb0b5, 0xb0b8, 0xb0bc, 0xb0c4, 0xb0c5, 0xb0c7, 0xb0c8, 0xb0c9, 0xb0d0, 0xb0d1, 0xb0d4, 0xb0d8, 0xb0e0, 0xb0e5, 0xb108, 0xb109, 0xb10b, 0xb10c, 0xb110, 0xb112, 0xb113, 0xb118, 0xb119, 0xb11b, 0xb11c, 0xb11d, 0xb123, 0xb124, 0xb125, 0xb128, 0xb12c, 0xb134, 0xb135, 0xb137, 0xb138, 0xb139, 0xb140, 0xb141, 0xb144, 0xb148, 0xb150, 0xb151, 0xb154, 0xb155, 0xb158, 0xb15c, 0xb160, 0xb178, 0xb179, 0xb17c, 0xb180, 0xb182, 0xb188, 0xb189, 0xb18b, 0xb18d, 0xb192, 0xb193, 0xb194, 0xb198, 0xb19c, 0xb1a8, 0xb1cc, 0xb1d0, 0xb1d4, 0xb1dc, 0xb1dd, /* 0x34 */ 0xb1df, 0xb1e8, 0xb1e9, 0xb1ec, 0xb1f0, 0xb1f9, 0xb1fb, 0xb1fd, 0xb204, 0xb205, 0xb208, 0xb20b, 0xb20c, 0xb214, 0xb215, 0xb217, 0xb219, 0xb220, 0xb234, 0xb23c, 0xb258, 0xb25c, 0xb260, 0xb268, 0xb269, 0xb274, 0xb275, 0xb27c, 0xb284, 0xb285, 0xb289, 0xb290, 0xb291, 0xb294, 0xb298, 0xb299, 0xb29a, 0xb2a0, 0xb2a1, 0xb2a3, 0xb2a5, 0xb2a6, 0xb2aa, 0xb2ac, 0xb2b0, 0xb2b4, 0xb2c8, 0xb2c9, 0xb2cc, 0xb2d0, 0xb2d2, 0xb2d8, 0xb2d9, 0xb2db, 0xb2dd, 0xb2e2, 0xb2e4, 0xb2e5, 0xb2e6, 0xb2e8, 0xb2eb, 0xb2ec, 0xb2ed, 0xb2ee, 0xb2ef, 0xb2f3, 0xb2f4, 0xb2f5, 0xb2f7, 0xb2f8, 0xb2f9, 0xb2fa, 0xb2fb, 0xb2ff, 0xb300, 0xb301, 0xb304, 0xb308, 0xb310, 0xb311, 0xb313, 0xb314, 0xb315, 0xb31c, 0xb354, 0xb355, 0xb356, 0xb358, 0xb35b, 0xb35c, 0xb35e, 0xb35f, 0xb364, 0xb365, /* 0x35 */ 0xb367, 0xb369, 0xb36b, 0xb36e, 0xb370, 0xb371, 0xb374, 0xb378, 0xb380, 0xb381, 0xb383, 0xb384, 0xb385, 0xb38c, 0xb390, 0xb394, 0xb3a0, 0xb3a1, 0xb3a8, 0xb3ac, 0xb3c4, 0xb3c5, 0xb3c8, 0xb3cb, 0xb3cc, 0xb3ce, 0xb3d0, 0xb3d4, 0xb3d5, 0xb3d7, 0xb3d9, 0xb3db, 0xb3dd, 0xb3e0, 0xb3e4, 0xb3e8, 0xb3fc, 0xb410, 0xb418, 0xb41c, 0xb420, 0xb428, 0xb429, 0xb42b, 0xb434, 0xb450, 0xb451, 0xb454, 0xb458, 0xb460, 0xb461, 0xb463, 0xb465, 0xb46c, 0xb480, 0xb488, 0xb49d, 0xb4a4, 0xb4a8, 0xb4ac, 0xb4b5, 0xb4b7, 0xb4b9, 0xb4c0, 0xb4c4, 0xb4c8, 0xb4d0, 0xb4d5, 0xb4dc, 0xb4dd, 0xb4e0, 0xb4e3, 0xb4e4, 0xb4e6, 0xb4ec, 0xb4ed, 0xb4ef, 0xb4f1, 0xb4f8, 0xb514, 0xb515, 0xb518, 0xb51b, 0xb51c, 0xb524, 0xb525, 0xb527, 0xb528, 0xb529, 0xb52a, 0xb530, 0xb531, 0xb534, 0xb538, /* 0x36 */ 0xb540, 0xb541, 0xb543, 0xb544, 0xb545, 0xb54b, 0xb54c, 0xb54d, 0xb550, 0xb554, 0xb55c, 0xb55d, 0xb55f, 0xb560, 0xb561, 0xb5a0, 0xb5a1, 0xb5a4, 0xb5a8, 0xb5aa, 0xb5ab, 0xb5b0, 0xb5b1, 0xb5b3, 0xb5b4, 0xb5b5, 0xb5bb, 0xb5bc, 0xb5bd, 0xb5c0, 0xb5c4, 0xb5cc, 0xb5cd, 0xb5cf, 0xb5d0, 0xb5d1, 0xb5d8, 0xb5ec, 0xb610, 0xb611, 0xb614, 0xb618, 0xb625, 0xb62c, 0xb634, 0xb648, 0xb664, 0xb668, 0xb69c, 0xb69d, 0xb6a0, 0xb6a4, 0xb6ab, 0xb6ac, 0xb6b1, 0xb6d4, 0xb6f0, 0xb6f4, 0xb6f8, 0xb700, 0xb701, 0xb705, 0xb728, 0xb729, 0xb72c, 0xb72f, 0xb730, 0xb738, 0xb739, 0xb73b, 0xb744, 0xb748, 0xb74c, 0xb754, 0xb755, 0xb760, 0xb764, 0xb768, 0xb770, 0xb771, 0xb773, 0xb775, 0xb77c, 0xb77d, 0xb780, 0xb784, 0xb78c, 0xb78d, 0xb78f, 0xb790, 0xb791, 0xb792, 0xb796, 0xb797, /* 0x37 */ 0xb798, 0xb799, 0xb79c, 0xb7a0, 0xb7a8, 0xb7a9, 0xb7ab, 0xb7ac, 0xb7ad, 0xb7b4, 0xb7b5, 0xb7b8, 0xb7c7, 0xb7c9, 0xb7ec, 0xb7ed, 0xb7f0, 0xb7f4, 0xb7fc, 0xb7fd, 0xb7ff, 0xb800, 0xb801, 0xb807, 0xb808, 0xb809, 0xb80c, 0xb810, 0xb818, 0xb819, 0xb81b, 0xb81d, 0xb824, 0xb825, 0xb828, 0xb82c, 0xb834, 0xb835, 0xb837, 0xb838, 0xb839, 0xb840, 0xb844, 0xb851, 0xb853, 0xb85c, 0xb85d, 0xb860, 0xb864, 0xb86c, 0xb86d, 0xb86f, 0xb871, 0xb878, 0xb87c, 0xb88d, 0xb8a8, 0xb8b0, 0xb8b4, 0xb8b8, 0xb8c0, 0xb8c1, 0xb8c3, 0xb8c5, 0xb8cc, 0xb8d0, 0xb8d4, 0xb8dd, 0xb8df, 0xb8e1, 0xb8e8, 0xb8e9, 0xb8ec, 0xb8f0, 0xb8f8, 0xb8f9, 0xb8fb, 0xb8fd, 0xb904, 0xb918, 0xb920, 0xb93c, 0xb93d, 0xb940, 0xb944, 0xb94c, 0xb94f, 0xb951, 0xb958, 0xb959, 0xb95c, 0xb960, 0xb968, 0xb969, /* 0x38 */ 0xb96b, 0xb96d, 0xb974, 0xb975, 0xb978, 0xb97c, 0xb984, 0xb985, 0xb987, 0xb989, 0xb98a, 0xb98d, 0xb98e, 0xb9ac, 0xb9ad, 0xb9b0, 0xb9b4, 0xb9bc, 0xb9bd, 0xb9bf, 0xb9c1, 0xb9c8, 0xb9c9, 0xb9cc, 0xb9ce, 0xb9cf, 0xb9d0, 0xb9d1, 0xb9d2, 0xb9d8, 0xb9d9, 0xb9db, 0xb9dd, 0xb9de, 0xb9e1, 0xb9e3, 0xb9e4, 0xb9e5, 0xb9e8, 0xb9ec, 0xb9f4, 0xb9f5, 0xb9f7, 0xb9f8, 0xb9f9, 0xb9fa, 0xba00, 0xba01, 0xba08, 0xba15, 0xba38, 0xba39, 0xba3c, 0xba40, 0xba42, 0xba48, 0xba49, 0xba4b, 0xba4d, 0xba4e, 0xba53, 0xba54, 0xba55, 0xba58, 0xba5c, 0xba64, 0xba65, 0xba67, 0xba68, 0xba69, 0xba70, 0xba71, 0xba74, 0xba78, 0xba83, 0xba84, 0xba85, 0xba87, 0xba8c, 0xbaa8, 0xbaa9, 0xbaab, 0xbaac, 0xbab0, 0xbab2, 0xbab8, 0xbab9, 0xbabb, 0xbabd, 0xbac4, 0xbac8, 0xbad8, 0xbad9, 0xbafc, /* 0x39 */ 0xbb00, 0xbb04, 0xbb0d, 0xbb0f, 0xbb11, 0xbb18, 0xbb1c, 0xbb20, 0xbb29, 0xbb2b, 0xbb34, 0xbb35, 0xbb36, 0xbb38, 0xbb3b, 0xbb3c, 0xbb3d, 0xbb3e, 0xbb44, 0xbb45, 0xbb47, 0xbb49, 0xbb4d, 0xbb4f, 0xbb50, 0xbb54, 0xbb58, 0xbb61, 0xbb63, 0xbb6c, 0xbb88, 0xbb8c, 0xbb90, 0xbba4, 0xbba8, 0xbbac, 0xbbb4, 0xbbb7, 0xbbc0, 0xbbc4, 0xbbc8, 0xbbd0, 0xbbd3, 0xbbf8, 0xbbf9, 0xbbfc, 0xbbff, 0xbc00, 0xbc02, 0xbc08, 0xbc09, 0xbc0b, 0xbc0c, 0xbc0d, 0xbc0f, 0xbc11, 0xbc14, 0xbc15, 0xbc16, 0xbc17, 0xbc18, 0xbc1b, 0xbc1c, 0xbc1d, 0xbc1e, 0xbc1f, 0xbc24, 0xbc25, 0xbc27, 0xbc29, 0xbc2d, 0xbc30, 0xbc31, 0xbc34, 0xbc38, 0xbc40, 0xbc41, 0xbc43, 0xbc44, 0xbc45, 0xbc49, 0xbc4c, 0xbc4d, 0xbc50, 0xbc5d, 0xbc84, 0xbc85, 0xbc88, 0xbc8b, 0xbc8c, 0xbc8e, 0xbc94, 0xbc95, 0xbc97, /* 0x3a */ 0xbc99, 0xbc9a, 0xbca0, 0xbca1, 0xbca4, 0xbca7, 0xbca8, 0xbcb0, 0xbcb1, 0xbcb3, 0xbcb4, 0xbcb5, 0xbcbc, 0xbcbd, 0xbcc0, 0xbcc4, 0xbccd, 0xbccf, 0xbcd0, 0xbcd1, 0xbcd5, 0xbcd8, 0xbcdc, 0xbcf4, 0xbcf5, 0xbcf6, 0xbcf8, 0xbcfc, 0xbd04, 0xbd05, 0xbd07, 0xbd09, 0xbd10, 0xbd14, 0xbd24, 0xbd2c, 0xbd40, 0xbd48, 0xbd49, 0xbd4c, 0xbd50, 0xbd58, 0xbd59, 0xbd64, 0xbd68, 0xbd80, 0xbd81, 0xbd84, 0xbd87, 0xbd88, 0xbd89, 0xbd8a, 0xbd90, 0xbd91, 0xbd93, 0xbd95, 0xbd99, 0xbd9a, 0xbd9c, 0xbda4, 0xbdb0, 0xbdb8, 0xbdd4, 0xbdd5, 0xbdd8, 0xbddc, 0xbde9, 0xbdf0, 0xbdf4, 0xbdf8, 0xbe00, 0xbe03, 0xbe05, 0xbe0c, 0xbe0d, 0xbe10, 0xbe14, 0xbe1c, 0xbe1d, 0xbe1f, 0xbe44, 0xbe45, 0xbe48, 0xbe4c, 0xbe4e, 0xbe54, 0xbe55, 0xbe57, 0xbe59, 0xbe5a, 0xbe5b, 0xbe60, 0xbe61, 0xbe64, /* 0x3b */ 0xbe68, 0xbe6a, 0xbe70, 0xbe71, 0xbe73, 0xbe74, 0xbe75, 0xbe7b, 0xbe7c, 0xbe7d, 0xbe80, 0xbe84, 0xbe8c, 0xbe8d, 0xbe8f, 0xbe90, 0xbe91, 0xbe98, 0xbe99, 0xbea8, 0xbed0, 0xbed1, 0xbed4, 0xbed7, 0xbed8, 0xbee0, 0xbee3, 0xbee4, 0xbee5, 0xbeec, 0xbf01, 0xbf08, 0xbf09, 0xbf18, 0xbf19, 0xbf1b, 0xbf1c, 0xbf1d, 0xbf40, 0xbf41, 0xbf44, 0xbf48, 0xbf50, 0xbf51, 0xbf55, 0xbf94, 0xbfb0, 0xbfc5, 0xbfcc, 0xbfcd, 0xbfd0, 0xbfd4, 0xbfdc, 0xbfdf, 0xbfe1, 0xc03c, 0xc051, 0xc058, 0xc05c, 0xc060, 0xc068, 0xc069, 0xc090, 0xc091, 0xc094, 0xc098, 0xc0a0, 0xc0a1, 0xc0a3, 0xc0a5, 0xc0ac, 0xc0ad, 0xc0af, 0xc0b0, 0xc0b3, 0xc0b4, 0xc0b5, 0xc0b6, 0xc0bc, 0xc0bd, 0xc0bf, 0xc0c0, 0xc0c1, 0xc0c5, 0xc0c8, 0xc0c9, 0xc0cc, 0xc0d0, 0xc0d8, 0xc0d9, 0xc0db, 0xc0dc, 0xc0dd, 0xc0e4, /* 0x3c */ 0xc0e5, 0xc0e8, 0xc0ec, 0xc0f4, 0xc0f5, 0xc0f7, 0xc0f9, 0xc100, 0xc104, 0xc108, 0xc110, 0xc115, 0xc11c, 0xc11d, 0xc11e, 0xc11f, 0xc120, 0xc123, 0xc124, 0xc126, 0xc127, 0xc12c, 0xc12d, 0xc12f, 0xc130, 0xc131, 0xc136, 0xc138, 0xc139, 0xc13c, 0xc140, 0xc148, 0xc149, 0xc14b, 0xc14c, 0xc14d, 0xc154, 0xc155, 0xc158, 0xc15c, 0xc164, 0xc165, 0xc167, 0xc168, 0xc169, 0xc170, 0xc174, 0xc178, 0xc185, 0xc18c, 0xc18d, 0xc18e, 0xc190, 0xc194, 0xc196, 0xc19c, 0xc19d, 0xc19f, 0xc1a1, 0xc1a5, 0xc1a8, 0xc1a9, 0xc1ac, 0xc1b0, 0xc1bd, 0xc1c4, 0xc1c8, 0xc1cc, 0xc1d4, 0xc1d7, 0xc1d8, 0xc1e0, 0xc1e4, 0xc1e8, 0xc1f0, 0xc1f1, 0xc1f3, 0xc1fc, 0xc1fd, 0xc200, 0xc204, 0xc20c, 0xc20d, 0xc20f, 0xc211, 0xc218, 0xc219, 0xc21c, 0xc21f, 0xc220, 0xc228, 0xc229, 0xc22b, 0xc22d, /* 0x3d */ 0xc22f, 0xc231, 0xc232, 0xc234, 0xc248, 0xc250, 0xc251, 0xc254, 0xc258, 0xc260, 0xc265, 0xc26c, 0xc26d, 0xc270, 0xc274, 0xc27c, 0xc27d, 0xc27f, 0xc281, 0xc288, 0xc289, 0xc290, 0xc298, 0xc29b, 0xc29d, 0xc2a4, 0xc2a5, 0xc2a8, 0xc2ac, 0xc2ad, 0xc2b4, 0xc2b5, 0xc2b7, 0xc2b9, 0xc2dc, 0xc2dd, 0xc2e0, 0xc2e3, 0xc2e4, 0xc2eb, 0xc2ec, 0xc2ed, 0xc2ef, 0xc2f1, 0xc2f6, 0xc2f8, 0xc2f9, 0xc2fb, 0xc2fc, 0xc300, 0xc308, 0xc309, 0xc30c, 0xc30d, 0xc313, 0xc314, 0xc315, 0xc318, 0xc31c, 0xc324, 0xc325, 0xc328, 0xc329, 0xc345, 0xc368, 0xc369, 0xc36c, 0xc370, 0xc372, 0xc378, 0xc379, 0xc37c, 0xc37d, 0xc384, 0xc388, 0xc38c, 0xc3c0, 0xc3d8, 0xc3d9, 0xc3dc, 0xc3df, 0xc3e0, 0xc3e2, 0xc3e8, 0xc3e9, 0xc3ed, 0xc3f4, 0xc3f5, 0xc3f8, 0xc408, 0xc410, 0xc424, 0xc42c, 0xc430, /* 0x3e */ 0xc434, 0xc43c, 0xc43d, 0xc448, 0xc464, 0xc465, 0xc468, 0xc46c, 0xc474, 0xc475, 0xc479, 0xc480, 0xc494, 0xc49c, 0xc4b8, 0xc4bc, 0xc4e9, 0xc4f0, 0xc4f1, 0xc4f4, 0xc4f8, 0xc4fa, 0xc4ff, 0xc500, 0xc501, 0xc50c, 0xc510, 0xc514, 0xc51c, 0xc528, 0xc529, 0xc52c, 0xc530, 0xc538, 0xc539, 0xc53b, 0xc53d, 0xc544, 0xc545, 0xc548, 0xc549, 0xc54a, 0xc54c, 0xc54d, 0xc54e, 0xc553, 0xc554, 0xc555, 0xc557, 0xc558, 0xc559, 0xc55d, 0xc55e, 0xc560, 0xc561, 0xc564, 0xc568, 0xc570, 0xc571, 0xc573, 0xc574, 0xc575, 0xc57c, 0xc57d, 0xc580, 0xc584, 0xc587, 0xc58c, 0xc58d, 0xc58f, 0xc591, 0xc595, 0xc597, 0xc598, 0xc59c, 0xc5a0, 0xc5a9, 0xc5b4, 0xc5b5, 0xc5b8, 0xc5b9, 0xc5bb, 0xc5bc, 0xc5bd, 0xc5be, 0xc5c4, 0xc5c5, 0xc5c6, 0xc5c7, 0xc5c8, 0xc5c9, 0xc5ca, 0xc5cc, 0xc5ce, /* 0x3f */ 0xc5d0, 0xc5d1, 0xc5d4, 0xc5d8, 0xc5e0, 0xc5e1, 0xc5e3, 0xc5e5, 0xc5ec, 0xc5ed, 0xc5ee, 0xc5f0, 0xc5f4, 0xc5f6, 0xc5f7, 0xc5fc, 0xc5fd, 0xc5fe, 0xc5ff, 0xc600, 0xc601, 0xc605, 0xc606, 0xc607, 0xc608, 0xc60c, 0xc610, 0xc618, 0xc619, 0xc61b, 0xc61c, 0xc624, 0xc625, 0xc628, 0xc62c, 0xc62d, 0xc62e, 0xc630, 0xc633, 0xc634, 0xc635, 0xc637, 0xc639, 0xc63b, 0xc640, 0xc641, 0xc644, 0xc648, 0xc650, 0xc651, 0xc653, 0xc654, 0xc655, 0xc65c, 0xc65d, 0xc660, 0xc66c, 0xc66f, 0xc671, 0xc678, 0xc679, 0xc67c, 0xc680, 0xc688, 0xc689, 0xc68b, 0xc68d, 0xc694, 0xc695, 0xc698, 0xc69c, 0xc6a4, 0xc6a5, 0xc6a7, 0xc6a9, 0xc6b0, 0xc6b1, 0xc6b4, 0xc6b8, 0xc6b9, 0xc6ba, 0xc6c0, 0xc6c1, 0xc6c3, 0xc6c5, 0xc6cc, 0xc6cd, 0xc6d0, 0xc6d4, 0xc6dc, 0xc6dd, 0xc6e0, 0xc6e1, 0xc6e8, /* 0x40 */ 0xc6e9, 0xc6ec, 0xc6f0, 0xc6f8, 0xc6f9, 0xc6fd, 0xc704, 0xc705, 0xc708, 0xc70c, 0xc714, 0xc715, 0xc717, 0xc719, 0xc720, 0xc721, 0xc724, 0xc728, 0xc730, 0xc731, 0xc733, 0xc735, 0xc737, 0xc73c, 0xc73d, 0xc740, 0xc744, 0xc74a, 0xc74c, 0xc74d, 0xc74f, 0xc751, 0xc752, 0xc753, 0xc754, 0xc755, 0xc756, 0xc757, 0xc758, 0xc75c, 0xc760, 0xc768, 0xc76b, 0xc774, 0xc775, 0xc778, 0xc77c, 0xc77d, 0xc77e, 0xc783, 0xc784, 0xc785, 0xc787, 0xc788, 0xc789, 0xc78a, 0xc78e, 0xc790, 0xc791, 0xc794, 0xc796, 0xc797, 0xc798, 0xc79a, 0xc7a0, 0xc7a1, 0xc7a3, 0xc7a4, 0xc7a5, 0xc7a6, 0xc7ac, 0xc7ad, 0xc7b0, 0xc7b4, 0xc7bc, 0xc7bd, 0xc7bf, 0xc7c0, 0xc7c1, 0xc7c8, 0xc7c9, 0xc7cc, 0xc7ce, 0xc7d0, 0xc7d8, 0xc7dd, 0xc7e4, 0xc7e8, 0xc7ec, 0xc800, 0xc801, 0xc804, 0xc808, 0xc80a, /* 0x41 */ 0xc810, 0xc811, 0xc813, 0xc815, 0xc816, 0xc81c, 0xc81d, 0xc820, 0xc824, 0xc82c, 0xc82d, 0xc82f, 0xc831, 0xc838, 0xc83c, 0xc840, 0xc848, 0xc849, 0xc84c, 0xc84d, 0xc854, 0xc870, 0xc871, 0xc874, 0xc878, 0xc87a, 0xc880, 0xc881, 0xc883, 0xc885, 0xc886, 0xc887, 0xc88b, 0xc88c, 0xc88d, 0xc894, 0xc89d, 0xc89f, 0xc8a1, 0xc8a8, 0xc8bc, 0xc8bd, 0xc8c4, 0xc8c8, 0xc8cc, 0xc8d4, 0xc8d5, 0xc8d7, 0xc8d9, 0xc8e0, 0xc8e1, 0xc8e4, 0xc8f5, 0xc8fc, 0xc8fd, 0xc900, 0xc904, 0xc905, 0xc906, 0xc90c, 0xc90d, 0xc90f, 0xc911, 0xc918, 0xc92c, 0xc934, 0xc950, 0xc951, 0xc954, 0xc958, 0xc960, 0xc961, 0xc963, 0xc96c, 0xc970, 0xc974, 0xc97c, 0xc988, 0xc989, 0xc98c, 0xc990, 0xc998, 0xc999, 0xc99b, 0xc99d, 0xc9c0, 0xc9c1, 0xc9c4, 0xc9c7, 0xc9c8, 0xc9ca, 0xc9d0, 0xc9d1, 0xc9d3, /* 0x42 */ 0xc9d5, 0xc9d6, 0xc9d9, 0xc9da, 0xc9dc, 0xc9dd, 0xc9e0, 0xc9e2, 0xc9e4, 0xc9e7, 0xc9ec, 0xc9ed, 0xc9ef, 0xc9f0, 0xc9f1, 0xc9f8, 0xc9f9, 0xc9fc, 0xca00, 0xca08, 0xca09, 0xca0b, 0xca0c, 0xca0d, 0xca14, 0xca18, 0xca29, 0xca4c, 0xca4d, 0xca50, 0xca54, 0xca5c, 0xca5d, 0xca5f, 0xca60, 0xca61, 0xca68, 0xca7d, 0xca84, 0xca98, 0xcabc, 0xcabd, 0xcac0, 0xcac4, 0xcacc, 0xcacd, 0xcacf, 0xcad1, 0xcad3, 0xcad8, 0xcad9, 0xcae0, 0xcaec, 0xcaf4, 0xcb08, 0xcb10, 0xcb14, 0xcb18, 0xcb20, 0xcb21, 0xcb41, 0xcb48, 0xcb49, 0xcb4c, 0xcb50, 0xcb58, 0xcb59, 0xcb5d, 0xcb64, 0xcb78, 0xcb79, 0xcb9c, 0xcbb8, 0xcbd4, 0xcbe4, 0xcbe7, 0xcbe9, 0xcc0c, 0xcc0d, 0xcc10, 0xcc14, 0xcc1c, 0xcc1d, 0xcc21, 0xcc22, 0xcc27, 0xcc28, 0xcc29, 0xcc2c, 0xcc2e, 0xcc30, 0xcc38, 0xcc39, 0xcc3b, /* 0x43 */ 0xcc3c, 0xcc3d, 0xcc3e, 0xcc44, 0xcc45, 0xcc48, 0xcc4c, 0xcc54, 0xcc55, 0xcc57, 0xcc58, 0xcc59, 0xcc60, 0xcc64, 0xcc66, 0xcc68, 0xcc70, 0xcc75, 0xcc98, 0xcc99, 0xcc9c, 0xcca0, 0xcca8, 0xcca9, 0xccab, 0xccac, 0xccad, 0xccb4, 0xccb5, 0xccb8, 0xccbc, 0xccc4, 0xccc5, 0xccc7, 0xccc9, 0xccd0, 0xccd4, 0xcce4, 0xccec, 0xccf0, 0xcd01, 0xcd08, 0xcd09, 0xcd0c, 0xcd10, 0xcd18, 0xcd19, 0xcd1b, 0xcd1d, 0xcd24, 0xcd28, 0xcd2c, 0xcd39, 0xcd5c, 0xcd60, 0xcd64, 0xcd6c, 0xcd6d, 0xcd6f, 0xcd71, 0xcd78, 0xcd88, 0xcd94, 0xcd95, 0xcd98, 0xcd9c, 0xcda4, 0xcda5, 0xcda7, 0xcda9, 0xcdb0, 0xcdc4, 0xcdcc, 0xcdd0, 0xcde8, 0xcdec, 0xcdf0, 0xcdf8, 0xcdf9, 0xcdfb, 0xcdfd, 0xce04, 0xce08, 0xce0c, 0xce14, 0xce19, 0xce20, 0xce21, 0xce24, 0xce28, 0xce30, 0xce31, 0xce33, 0xce35, /* 0x44 */ 0xce58, 0xce59, 0xce5c, 0xce5f, 0xce60, 0xce61, 0xce68, 0xce69, 0xce6b, 0xce6d, 0xce74, 0xce75, 0xce78, 0xce7c, 0xce84, 0xce85, 0xce87, 0xce89, 0xce90, 0xce91, 0xce94, 0xce98, 0xcea0, 0xcea1, 0xcea3, 0xcea4, 0xcea5, 0xceac, 0xcead, 0xcec1, 0xcee4, 0xcee5, 0xcee8, 0xceeb, 0xceec, 0xcef4, 0xcef5, 0xcef7, 0xcef8, 0xcef9, 0xcf00, 0xcf01, 0xcf04, 0xcf08, 0xcf10, 0xcf11, 0xcf13, 0xcf15, 0xcf1c, 0xcf20, 0xcf24, 0xcf2c, 0xcf2d, 0xcf2f, 0xcf30, 0xcf31, 0xcf38, 0xcf54, 0xcf55, 0xcf58, 0xcf5c, 0xcf64, 0xcf65, 0xcf67, 0xcf69, 0xcf70, 0xcf71, 0xcf74, 0xcf78, 0xcf80, 0xcf85, 0xcf8c, 0xcfa1, 0xcfa8, 0xcfb0, 0xcfc4, 0xcfe0, 0xcfe1, 0xcfe4, 0xcfe8, 0xcff0, 0xcff1, 0xcff3, 0xcff5, 0xcffc, 0xd000, 0xd004, 0xd011, 0xd018, 0xd02d, 0xd034, 0xd035, 0xd038, 0xd03c, /* 0x45 */ 0xd044, 0xd045, 0xd047, 0xd049, 0xd050, 0xd054, 0xd058, 0xd060, 0xd06c, 0xd06d, 0xd070, 0xd074, 0xd07c, 0xd07d, 0xd081, 0xd0a4, 0xd0a5, 0xd0a8, 0xd0ac, 0xd0b4, 0xd0b5, 0xd0b7, 0xd0b9, 0xd0c0, 0xd0c1, 0xd0c4, 0xd0c8, 0xd0c9, 0xd0d0, 0xd0d1, 0xd0d3, 0xd0d4, 0xd0d5, 0xd0dc, 0xd0dd, 0xd0e0, 0xd0e4, 0xd0ec, 0xd0ed, 0xd0ef, 0xd0f0, 0xd0f1, 0xd0f8, 0xd10d, 0xd130, 0xd131, 0xd134, 0xd138, 0xd13a, 0xd140, 0xd141, 0xd143, 0xd144, 0xd145, 0xd14c, 0xd14d, 0xd150, 0xd154, 0xd15c, 0xd15d, 0xd15f, 0xd161, 0xd168, 0xd16c, 0xd17c, 0xd184, 0xd188, 0xd1a0, 0xd1a1, 0xd1a4, 0xd1a8, 0xd1b0, 0xd1b1, 0xd1b3, 0xd1b5, 0xd1ba, 0xd1bc, 0xd1c0, 0xd1d8, 0xd1f4, 0xd1f8, 0xd207, 0xd209, 0xd210, 0xd22c, 0xd22d, 0xd230, 0xd234, 0xd23c, 0xd23d, 0xd23f, 0xd241, 0xd248, 0xd25c, /* 0x46 */ 0xd264, 0xd280, 0xd281, 0xd284, 0xd288, 0xd290, 0xd291, 0xd295, 0xd29c, 0xd2a0, 0xd2a4, 0xd2ac, 0xd2b1, 0xd2b8, 0xd2b9, 0xd2bc, 0xd2bf, 0xd2c0, 0xd2c2, 0xd2c8, 0xd2c9, 0xd2cb, 0xd2d4, 0xd2d8, 0xd2dc, 0xd2e4, 0xd2e5, 0xd2f0, 0xd2f1, 0xd2f4, 0xd2f8, 0xd300, 0xd301, 0xd303, 0xd305, 0xd30c, 0xd30d, 0xd30e, 0xd310, 0xd314, 0xd316, 0xd31c, 0xd31d, 0xd31f, 0xd320, 0xd321, 0xd325, 0xd328, 0xd329, 0xd32c, 0xd330, 0xd338, 0xd339, 0xd33b, 0xd33c, 0xd33d, 0xd344, 0xd345, 0xd37c, 0xd37d, 0xd380, 0xd384, 0xd38c, 0xd38d, 0xd38f, 0xd390, 0xd391, 0xd398, 0xd399, 0xd39c, 0xd3a0, 0xd3a8, 0xd3a9, 0xd3ab, 0xd3ad, 0xd3b4, 0xd3b8, 0xd3bc, 0xd3c4, 0xd3c5, 0xd3c8, 0xd3c9, 0xd3d0, 0xd3d8, 0xd3e1, 0xd3e3, 0xd3ec, 0xd3ed, 0xd3f0, 0xd3f4, 0xd3fc, 0xd3fd, 0xd3ff, 0xd401, /* 0x47 */ 0xd408, 0xd41d, 0xd440, 0xd444, 0xd45c, 0xd460, 0xd464, 0xd46d, 0xd46f, 0xd478, 0xd479, 0xd47c, 0xd47f, 0xd480, 0xd482, 0xd488, 0xd489, 0xd48b, 0xd48d, 0xd494, 0xd4a9, 0xd4cc, 0xd4d0, 0xd4d4, 0xd4dc, 0xd4df, 0xd4e8, 0xd4ec, 0xd4f0, 0xd4f8, 0xd4fb, 0xd4fd, 0xd504, 0xd508, 0xd50c, 0xd514, 0xd515, 0xd517, 0xd53c, 0xd53d, 0xd540, 0xd544, 0xd54c, 0xd54d, 0xd54f, 0xd551, 0xd558, 0xd559, 0xd55c, 0xd560, 0xd565, 0xd568, 0xd569, 0xd56b, 0xd56d, 0xd574, 0xd575, 0xd578, 0xd57c, 0xd584, 0xd585, 0xd587, 0xd588, 0xd589, 0xd590, 0xd5a5, 0xd5c8, 0xd5c9, 0xd5cc, 0xd5d0, 0xd5d2, 0xd5d8, 0xd5d9, 0xd5db, 0xd5dd, 0xd5e4, 0xd5e5, 0xd5e8, 0xd5ec, 0xd5f4, 0xd5f5, 0xd5f7, 0xd5f9, 0xd600, 0xd601, 0xd604, 0xd608, 0xd610, 0xd611, 0xd613, 0xd614, 0xd615, 0xd61c, 0xd620, /* 0x48 */ 0xd624, 0xd62d, 0xd638, 0xd639, 0xd63c, 0xd640, 0xd645, 0xd648, 0xd649, 0xd64b, 0xd64d, 0xd651, 0xd654, 0xd655, 0xd658, 0xd65c, 0xd667, 0xd669, 0xd670, 0xd671, 0xd674, 0xd683, 0xd685, 0xd68c, 0xd68d, 0xd690, 0xd694, 0xd69d, 0xd69f, 0xd6a1, 0xd6a8, 0xd6ac, 0xd6b0, 0xd6b9, 0xd6bb, 0xd6c4, 0xd6c5, 0xd6c8, 0xd6cc, 0xd6d1, 0xd6d4, 0xd6d7, 0xd6d9, 0xd6e0, 0xd6e4, 0xd6e8, 0xd6f0, 0xd6f5, 0xd6fc, 0xd6fd, 0xd700, 0xd704, 0xd711, 0xd718, 0xd719, 0xd71c, 0xd720, 0xd728, 0xd729, 0xd72b, 0xd72d, 0xd734, 0xd735, 0xd738, 0xd73c, 0xd744, 0xd747, 0xd749, 0xd750, 0xd751, 0xd754, 0xd756, 0xd757, 0xd758, 0xd759, 0xd760, 0xd761, 0xd763, 0xd765, 0xd769, 0xd76c, 0xd770, 0xd774, 0xd77c, 0xd77d, 0xd781, 0xd788, 0xd789, 0xd78c, 0xd790, 0xd798, 0xd799, 0xd79b, 0xd79d, }; static const unsigned short ksc5601_2uni_page4a[4888] = { /* 0x4a */ 0x4f3d, 0x4f73, 0x5047, 0x50f9, 0x52a0, 0x53ef, 0x5475, 0x54e5, 0x5609, 0x5ac1, 0x5bb6, 0x6687, 0x67b6, 0x67b7, 0x67ef, 0x6b4c, 0x73c2, 0x75c2, 0x7a3c, 0x82db, 0x8304, 0x8857, 0x8888, 0x8a36, 0x8cc8, 0x8dcf, 0x8efb, 0x8fe6, 0x99d5, 0x523b, 0x5374, 0x5404, 0x606a, 0x6164, 0x6bbc, 0x73cf, 0x811a, 0x89ba, 0x89d2, 0x95a3, 0x4f83, 0x520a, 0x58be, 0x5978, 0x59e6, 0x5e72, 0x5e79, 0x61c7, 0x63c0, 0x6746, 0x67ec, 0x687f, 0x6f97, 0x764e, 0x770b, 0x78f5, 0x7a08, 0x7aff, 0x7c21, 0x809d, 0x826e, 0x8271, 0x8aeb, 0x9593, 0x4e6b, 0x559d, 0x66f7, 0x6e34, 0x78a3, 0x7aed, 0x845b, 0x8910, 0x874e, 0x97a8, 0x52d8, 0x574e, 0x582a, 0x5d4c, 0x611f, 0x61be, 0x6221, 0x6562, 0x67d1, 0x6a44, 0x6e1b, 0x7518, 0x75b3, 0x76e3, 0x77b0, 0x7d3a, 0x90af, 0x9451, 0x9452, 0x9f95, /* 0x4b */ 0x5323, 0x5cac, 0x7532, 0x80db, 0x9240, 0x9598, 0x525b, 0x5808, 0x59dc, 0x5ca1, 0x5d17, 0x5eb7, 0x5f3a, 0x5f4a, 0x6177, 0x6c5f, 0x757a, 0x7586, 0x7ce0, 0x7d73, 0x7db1, 0x7f8c, 0x8154, 0x8221, 0x8591, 0x8941, 0x8b1b, 0x92fc, 0x964d, 0x9c47, 0x4ecb, 0x4ef7, 0x500b, 0x51f1, 0x584f, 0x6137, 0x613e, 0x6168, 0x6539, 0x69ea, 0x6f11, 0x75a5, 0x7686, 0x76d6, 0x7b87, 0x82a5, 0x84cb, 0xf900, 0x93a7, 0x958b, 0x5580, 0x5ba2, 0x5751, 0xf901, 0x7cb3, 0x7fb9, 0x91b5, 0x5028, 0x53bb, 0x5c45, 0x5de8, 0x62d2, 0x636e, 0x64da, 0x64e7, 0x6e20, 0x70ac, 0x795b, 0x8ddd, 0x8e1e, 0xf902, 0x907d, 0x9245, 0x92f8, 0x4e7e, 0x4ef6, 0x5065, 0x5dfe, 0x5efa, 0x6106, 0x6957, 0x8171, 0x8654, 0x8e47, 0x9375, 0x9a2b, 0x4e5e, 0x5091, 0x6770, 0x6840, 0x5109, 0x528d, 0x5292, 0x6aa2, /* 0x4c */ 0x77bc, 0x9210, 0x9ed4, 0x52ab, 0x602f, 0x8ff2, 0x5048, 0x61a9, 0x63ed, 0x64ca, 0x683c, 0x6a84, 0x6fc0, 0x8188, 0x89a1, 0x9694, 0x5805, 0x727d, 0x72ac, 0x7504, 0x7d79, 0x7e6d, 0x80a9, 0x898b, 0x8b74, 0x9063, 0x9d51, 0x6289, 0x6c7a, 0x6f54, 0x7d50, 0x7f3a, 0x8a23, 0x517c, 0x614a, 0x7b9d, 0x8b19, 0x9257, 0x938c, 0x4eac, 0x4fd3, 0x501e, 0x50be, 0x5106, 0x52c1, 0x52cd, 0x537f, 0x5770, 0x5883, 0x5e9a, 0x5f91, 0x6176, 0x61ac, 0x64ce, 0x656c, 0x666f, 0x66bb, 0x66f4, 0x6897, 0x6d87, 0x7085, 0x70f1, 0x749f, 0x74a5, 0x74ca, 0x75d9, 0x786c, 0x78ec, 0x7adf, 0x7af6, 0x7d45, 0x7d93, 0x8015, 0x803f, 0x811b, 0x8396, 0x8b66, 0x8f15, 0x9015, 0x93e1, 0x9803, 0x9838, 0x9a5a, 0x9be8, 0x4fc2, 0x5553, 0x583a, 0x5951, 0x5b63, 0x5c46, 0x60b8, 0x6212, 0x6842, 0x68b0, /* 0x4d */ 0x68e8, 0x6eaa, 0x754c, 0x7678, 0x78ce, 0x7a3d, 0x7cfb, 0x7e6b, 0x7e7c, 0x8a08, 0x8aa1, 0x8c3f, 0x968e, 0x9dc4, 0x53e4, 0x53e9, 0x544a, 0x5471, 0x56fa, 0x59d1, 0x5b64, 0x5c3b, 0x5eab, 0x62f7, 0x6537, 0x6545, 0x6572, 0x66a0, 0x67af, 0x69c1, 0x6cbd, 0x75fc, 0x7690, 0x777e, 0x7a3f, 0x7f94, 0x8003, 0x80a1, 0x818f, 0x82e6, 0x82fd, 0x83f0, 0x85c1, 0x8831, 0x88b4, 0x8aa5, 0xf903, 0x8f9c, 0x932e, 0x96c7, 0x9867, 0x9ad8, 0x9f13, 0x54ed, 0x659b, 0x66f2, 0x688f, 0x7a40, 0x8c37, 0x9d60, 0x56f0, 0x5764, 0x5d11, 0x6606, 0x68b1, 0x68cd, 0x6efe, 0x7428, 0x889e, 0x9be4, 0x6c68, 0xf904, 0x9aa8, 0x4f9b, 0x516c, 0x5171, 0x529f, 0x5b54, 0x5de5, 0x6050, 0x606d, 0x62f1, 0x63a7, 0x653b, 0x73d9, 0x7a7a, 0x86a3, 0x8ca2, 0x978f, 0x4e32, 0x5be1, 0x6208, 0x679c, 0x74dc, /* 0x4e */ 0x79d1, 0x83d3, 0x8a87, 0x8ab2, 0x8de8, 0x904e, 0x934b, 0x9846, 0x5ed3, 0x69e8, 0x85ff, 0x90ed, 0xf905, 0x51a0, 0x5b98, 0x5bec, 0x6163, 0x68fa, 0x6b3e, 0x704c, 0x742f, 0x74d8, 0x7ba1, 0x7f50, 0x83c5, 0x89c0, 0x8cab, 0x95dc, 0x9928, 0x522e, 0x605d, 0x62ec, 0x9002, 0x4f8a, 0x5149, 0x5321, 0x58d9, 0x5ee3, 0x66e0, 0x6d38, 0x709a, 0x72c2, 0x73d6, 0x7b50, 0x80f1, 0x945b, 0x5366, 0x639b, 0x7f6b, 0x4e56, 0x5080, 0x584a, 0x58de, 0x602a, 0x6127, 0x62d0, 0x69d0, 0x9b41, 0x5b8f, 0x7d18, 0x80b1, 0x8f5f, 0x4ea4, 0x50d1, 0x54ac, 0x55ac, 0x5b0c, 0x5da0, 0x5de7, 0x652a, 0x654e, 0x6821, 0x6a4b, 0x72e1, 0x768e, 0x77ef, 0x7d5e, 0x7ff9, 0x81a0, 0x854e, 0x86df, 0x8f03, 0x8f4e, 0x90ca, 0x9903, 0x9a55, 0x9bab, 0x4e18, 0x4e45, 0x4e5d, 0x4ec7, 0x4ff1, 0x5177, 0x52fe, /* 0x4f */ 0x5340, 0x53e3, 0x53e5, 0x548e, 0x5614, 0x5775, 0x57a2, 0x5bc7, 0x5d87, 0x5ed0, 0x61fc, 0x62d8, 0x6551, 0x67b8, 0x67e9, 0x69cb, 0x6b50, 0x6bc6, 0x6bec, 0x6c42, 0x6e9d, 0x7078, 0x72d7, 0x7396, 0x7403, 0x77bf, 0x77e9, 0x7a76, 0x7d7f, 0x8009, 0x81fc, 0x8205, 0x820a, 0x82df, 0x8862, 0x8b33, 0x8cfc, 0x8ec0, 0x9011, 0x90b1, 0x9264, 0x92b6, 0x99d2, 0x9a45, 0x9ce9, 0x9dd7, 0x9f9c, 0x570b, 0x5c40, 0x83ca, 0x97a0, 0x97ab, 0x9eb4, 0x541b, 0x7a98, 0x7fa4, 0x88d9, 0x8ecd, 0x90e1, 0x5800, 0x5c48, 0x6398, 0x7a9f, 0x5bae, 0x5f13, 0x7a79, 0x7aae, 0x828e, 0x8eac, 0x5026, 0x5238, 0x52f8, 0x5377, 0x5708, 0x62f3, 0x6372, 0x6b0a, 0x6dc3, 0x7737, 0x53a5, 0x7357, 0x8568, 0x8e76, 0x95d5, 0x673a, 0x6ac3, 0x6f70, 0x8a6d, 0x8ecc, 0x994b, 0xf906, 0x6677, 0x6b78, 0x8cb4, /* 0x50 */ 0x9b3c, 0xf907, 0x53eb, 0x572d, 0x594e, 0x63c6, 0x69fb, 0x73ea, 0x7845, 0x7aba, 0x7ac5, 0x7cfe, 0x8475, 0x898f, 0x8d73, 0x9035, 0x95a8, 0x52fb, 0x5747, 0x7547, 0x7b60, 0x83cc, 0x921e, 0xf908, 0x6a58, 0x514b, 0x524b, 0x5287, 0x621f, 0x68d8, 0x6975, 0x9699, 0x50c5, 0x52a4, 0x52e4, 0x61c3, 0x65a4, 0x6839, 0x69ff, 0x747e, 0x7b4b, 0x82b9, 0x83eb, 0x89b2, 0x8b39, 0x8fd1, 0x9949, 0xf909, 0x4eca, 0x5997, 0x64d2, 0x6611, 0x6a8e, 0x7434, 0x7981, 0x79bd, 0x82a9, 0x887e, 0x887f, 0x895f, 0xf90a, 0x9326, 0x4f0b, 0x53ca, 0x6025, 0x6271, 0x6c72, 0x7d1a, 0x7d66, 0x4e98, 0x5162, 0x77dc, 0x80af, 0x4f01, 0x4f0e, 0x5176, 0x5180, 0x55dc, 0x5668, 0x573b, 0x57fa, 0x57fc, 0x5914, 0x5947, 0x5993, 0x5bc4, 0x5c90, 0x5d0e, 0x5df1, 0x5e7e, 0x5fcc, 0x6280, 0x65d7, 0x65e3, /* 0x51 */ 0x671e, 0x671f, 0x675e, 0x68cb, 0x68c4, 0x6a5f, 0x6b3a, 0x6c23, 0x6c7d, 0x6c82, 0x6dc7, 0x7398, 0x7426, 0x742a, 0x7482, 0x74a3, 0x7578, 0x757f, 0x7881, 0x78ef, 0x7941, 0x7947, 0x7948, 0x797a, 0x7b95, 0x7d00, 0x7dba, 0x7f88, 0x8006, 0x802d, 0x808c, 0x8a18, 0x8b4f, 0x8c48, 0x8d77, 0x9321, 0x9324, 0x98e2, 0x9951, 0x9a0e, 0x9a0f, 0x9a65, 0x9e92, 0x7dca, 0x4f76, 0x5409, 0x62ee, 0x6854, 0x91d1, 0x55ab, 0x513a, 0xf90b, 0xf90c, 0x5a1c, 0x61e6, 0xf90d, 0x62cf, 0x62ff, 0xf90e, 0xf90f, 0xf910, 0xf911, 0xf912, 0xf913, 0x90a3, 0xf914, 0xf915, 0xf916, 0xf917, 0xf918, 0x8afe, 0xf919, 0xf91a, 0xf91b, 0xf91c, 0x6696, 0xf91d, 0x7156, 0xf91e, 0xf91f, 0x96e3, 0xf920, 0x634f, 0x637a, 0x5357, 0xf921, 0x678f, 0x6960, 0x6e73, 0xf922, 0x7537, 0xf923, 0xf924, 0xf925, /* 0x52 */ 0x7d0d, 0xf926, 0xf927, 0x8872, 0x56ca, 0x5a18, 0xf928, 0xf929, 0xf92a, 0xf92b, 0xf92c, 0x4e43, 0xf92d, 0x5167, 0x5948, 0x67f0, 0x8010, 0xf92e, 0x5973, 0x5e74, 0x649a, 0x79ca, 0x5ff5, 0x606c, 0x62c8, 0x637b, 0x5be7, 0x5bd7, 0x52aa, 0xf92f, 0x5974, 0x5f29, 0x6012, 0xf930, 0xf931, 0xf932, 0x7459, 0xf933, 0xf934, 0xf935, 0xf936, 0xf937, 0xf938, 0x99d1, 0xf939, 0xf93a, 0xf93b, 0xf93c, 0xf93d, 0xf93e, 0xf93f, 0xf940, 0xf941, 0xf942, 0xf943, 0x6fc3, 0xf944, 0xf945, 0x81bf, 0x8fb2, 0x60f1, 0xf946, 0xf947, 0x8166, 0xf948, 0xf949, 0x5c3f, 0xf94a, 0xf94b, 0xf94c, 0xf94d, 0xf94e, 0xf94f, 0xf950, 0xf951, 0x5ae9, 0x8a25, 0x677b, 0x7d10, 0xf952, 0xf953, 0xf954, 0xf955, 0xf956, 0xf957, 0x80fd, 0xf958, 0xf959, 0x5c3c, 0x6ce5, 0x533f, 0x6eba, 0x591a, 0x8336, /* 0x53 */ 0x4e39, 0x4eb6, 0x4f46, 0x55ae, 0x5718, 0x58c7, 0x5f56, 0x65b7, 0x65e6, 0x6a80, 0x6bb5, 0x6e4d, 0x77ed, 0x7aef, 0x7c1e, 0x7dde, 0x86cb, 0x8892, 0x9132, 0x935b, 0x64bb, 0x6fbe, 0x737a, 0x75b8, 0x9054, 0x5556, 0x574d, 0x61ba, 0x64d4, 0x66c7, 0x6de1, 0x6e5b, 0x6f6d, 0x6fb9, 0x75f0, 0x8043, 0x81bd, 0x8541, 0x8983, 0x8ac7, 0x8b5a, 0x931f, 0x6c93, 0x7553, 0x7b54, 0x8e0f, 0x905d, 0x5510, 0x5802, 0x5858, 0x5e62, 0x6207, 0x649e, 0x68e0, 0x7576, 0x7cd6, 0x87b3, 0x9ee8, 0x4ee3, 0x5788, 0x576e, 0x5927, 0x5c0d, 0x5cb1, 0x5e36, 0x5f85, 0x6234, 0x64e1, 0x73b3, 0x81fa, 0x888b, 0x8cb8, 0x968a, 0x9edb, 0x5b85, 0x5fb7, 0x60b3, 0x5012, 0x5200, 0x5230, 0x5716, 0x5835, 0x5857, 0x5c0e, 0x5c60, 0x5cf6, 0x5d8b, 0x5ea6, 0x5f92, 0x60bc, 0x6311, 0x6389, 0x6417, 0x6843, /* 0x54 */ 0x68f9, 0x6ac2, 0x6dd8, 0x6e21, 0x6ed4, 0x6fe4, 0x71fe, 0x76dc, 0x7779, 0x79b1, 0x7a3b, 0x8404, 0x89a9, 0x8ced, 0x8df3, 0x8e48, 0x9003, 0x9014, 0x9053, 0x90fd, 0x934d, 0x9676, 0x97dc, 0x6bd2, 0x7006, 0x7258, 0x72a2, 0x7368, 0x7763, 0x79bf, 0x7be4, 0x7e9b, 0x8b80, 0x58a9, 0x60c7, 0x6566, 0x65fd, 0x66be, 0x6c8c, 0x711e, 0x71c9, 0x8c5a, 0x9813, 0x4e6d, 0x7a81, 0x4edd, 0x51ac, 0x51cd, 0x52d5, 0x540c, 0x61a7, 0x6771, 0x6850, 0x68df, 0x6d1e, 0x6f7c, 0x75bc, 0x77b3, 0x7ae5, 0x80f4, 0x8463, 0x9285, 0x515c, 0x6597, 0x675c, 0x6793, 0x75d8, 0x7ac7, 0x8373, 0xf95a, 0x8c46, 0x9017, 0x982d, 0x5c6f, 0x81c0, 0x829a, 0x9041, 0x906f, 0x920d, 0x5f97, 0x5d9d, 0x6a59, 0x71c8, 0x767b, 0x7b49, 0x85e4, 0x8b04, 0x9127, 0x9a30, 0x5587, 0x61f6, 0xf95b, 0x7669, 0x7f85, /* 0x55 */ 0x863f, 0x87ba, 0x88f8, 0x908f, 0xf95c, 0x6d1b, 0x70d9, 0x73de, 0x7d61, 0x843d, 0xf95d, 0x916a, 0x99f1, 0xf95e, 0x4e82, 0x5375, 0x6b04, 0x6b12, 0x703e, 0x721b, 0x862d, 0x9e1e, 0x524c, 0x8fa3, 0x5d50, 0x64e5, 0x652c, 0x6b16, 0x6feb, 0x7c43, 0x7e9c, 0x85cd, 0x8964, 0x89bd, 0x62c9, 0x81d8, 0x881f, 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x7405, 0x746f, 0x8782, 0x90de, 0x4f86, 0x5d0d, 0x5fa0, 0x840a, 0x51b7, 0x63a0, 0x7565, 0x4eae, 0x5006, 0x5169, 0x51c9, 0x6881, 0x6a11, 0x7cae, 0x7cb1, 0x7ce7, 0x826f, 0x8ad2, 0x8f1b, 0x91cf, 0x4fb6, 0x5137, 0x52f5, 0x5442, 0x5eec, 0x616e, 0x623e, 0x65c5, 0x6ada, 0x6ffe, 0x792a, 0x85dc, 0x8823, 0x95ad, 0x9a62, 0x9a6a, 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x701d, 0x792b, 0x8f62, 0x9742, 0x6190, 0x6200, 0x6523, 0x6f23, /* 0x56 */ 0x7149, 0x7489, 0x7df4, 0x806f, 0x84ee, 0x8f26, 0x9023, 0x934a, 0x51bd, 0x5217, 0x52a3, 0x6d0c, 0x70c8, 0x88c2, 0x5ec9, 0x6582, 0x6bae, 0x6fc2, 0x7c3e, 0x7375, 0x4ee4, 0x4f36, 0x56f9, 0xf95f, 0x5cba, 0x5dba, 0x601c, 0x73b2, 0x7b2d, 0x7f9a, 0x7fce, 0x8046, 0x901e, 0x9234, 0x96f6, 0x9748, 0x9818, 0x9f61, 0x4f8b, 0x6fa7, 0x79ae, 0x91b4, 0x96b7, 0x52de, 0xf960, 0x6488, 0x64c4, 0x6ad3, 0x6f5e, 0x7018, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def, 0x8f05, 0x9732, 0x9b6f, 0x9dfa, 0x9e75, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304, 0x9e7f, 0x9e93, 0x8ad6, 0x58df, 0x5f04, 0x6727, 0x7027, 0x74cf, 0x7c60, 0x807e, 0x5121, 0x7028, 0x7262, 0x78ca, 0x8cc2, 0x8cda, 0x8cf4, 0x96f7, 0x4e86, 0x50da, 0x5bee, 0x5ed6, 0x6599, 0x71ce, 0x7642, 0x77ad, 0x804a, 0x84fc, /* 0x57 */ 0x907c, 0x9b27, 0x9f8d, 0x58d8, 0x5a41, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x763b, 0x7d2f, 0x7e37, 0x851e, 0x8938, 0x93e4, 0x964b, 0x5289, 0x65d2, 0x67f3, 0x69b4, 0x6d41, 0x6e9c, 0x700f, 0x7409, 0x7460, 0x7559, 0x7624, 0x786b, 0x8b2c, 0x985e, 0x516d, 0x622e, 0x9678, 0x4f96, 0x502b, 0x5d19, 0x6dea, 0x7db8, 0x8f2a, 0x5f8b, 0x6144, 0x6817, 0xf961, 0x9686, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x695e, 0x7a1c, 0x7dbe, 0x83f1, 0x9675, 0x4fda, 0x5229, 0x5398, 0x540f, 0x550e, 0x5c65, 0x60a7, 0x674e, 0x68a8, 0x6d6c, 0x7281, 0x72f8, 0x7406, 0x7483, 0xf962, 0x75e2, 0x7c6c, 0x7f79, 0x7fb8, 0x8389, 0x88cf, 0x88e1, 0x91cc, 0x91d0, 0x96e2, 0x9bc9, 0x541d, 0x6f7e, 0x71d0, 0x7498, 0x85fa, 0x8eaa, 0x96a3, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x7433, 0x81e8, 0x9716, 0x782c, /* 0x58 */ 0x7acb, 0x7b20, 0x7c92, 0x6469, 0x746a, 0x75f2, 0x78bc, 0x78e8, 0x99ac, 0x9b54, 0x9ebb, 0x5bde, 0x5e55, 0x6f20, 0x819c, 0x83ab, 0x9088, 0x4e07, 0x534d, 0x5a29, 0x5dd2, 0x5f4e, 0x6162, 0x633d, 0x6669, 0x66fc, 0x6eff, 0x6f2b, 0x7063, 0x779e, 0x842c, 0x8513, 0x883b, 0x8f13, 0x9945, 0x9c3b, 0x551c, 0x62b9, 0x672b, 0x6cab, 0x8309, 0x896a, 0x977a, 0x4ea1, 0x5984, 0x5fd8, 0x5fd9, 0x671b, 0x7db2, 0x7f54, 0x8292, 0x832b, 0x83bd, 0x8f1e, 0x9099, 0x57cb, 0x59b9, 0x5a92, 0x5bd0, 0x6627, 0x679a, 0x6885, 0x6bcf, 0x7164, 0x7f75, 0x8cb7, 0x8ce3, 0x9081, 0x9b45, 0x8108, 0x8c8a, 0x964c, 0x9a40, 0x9ea5, 0x5b5f, 0x6c13, 0x731b, 0x76f2, 0x76df, 0x840c, 0x51aa, 0x8993, 0x514d, 0x5195, 0x52c9, 0x68c9, 0x6c94, 0x7704, 0x7720, 0x7dbf, 0x7dec, 0x9762, 0x9eb5, 0x6ec5, /* 0x59 */ 0x8511, 0x51a5, 0x540d, 0x547d, 0x660e, 0x669d, 0x6927, 0x6e9f, 0x76bf, 0x7791, 0x8317, 0x84c2, 0x879f, 0x9169, 0x9298, 0x9cf4, 0x8882, 0x4fae, 0x5192, 0x52df, 0x59c6, 0x5e3d, 0x6155, 0x6478, 0x6479, 0x66ae, 0x67d0, 0x6a21, 0x6bcd, 0x6bdb, 0x725f, 0x7261, 0x7441, 0x7738, 0x77db, 0x8017, 0x82bc, 0x8305, 0x8b00, 0x8b28, 0x8c8c, 0x6728, 0x6c90, 0x7267, 0x76ee, 0x7766, 0x7a46, 0x9da9, 0x6b7f, 0x6c92, 0x5922, 0x6726, 0x8499, 0x536f, 0x5893, 0x5999, 0x5edf, 0x63cf, 0x6634, 0x6773, 0x6e3a, 0x732b, 0x7ad7, 0x82d7, 0x9328, 0x52d9, 0x5deb, 0x61ae, 0x61cb, 0x620a, 0x62c7, 0x64ab, 0x65e0, 0x6959, 0x6b66, 0x6bcb, 0x7121, 0x73f7, 0x755d, 0x7e46, 0x821e, 0x8302, 0x856a, 0x8aa3, 0x8cbf, 0x9727, 0x9d61, 0x58a8, 0x9ed8, 0x5011, 0x520e, 0x543b, 0x554f, 0x6587, /* 0x5a */ 0x6c76, 0x7d0a, 0x7d0b, 0x805e, 0x868a, 0x9580, 0x96ef, 0x52ff, 0x6c95, 0x7269, 0x5473, 0x5a9a, 0x5c3e, 0x5d4b, 0x5f4c, 0x5fae, 0x672a, 0x68b6, 0x6963, 0x6e3c, 0x6e44, 0x7709, 0x7c73, 0x7f8e, 0x8587, 0x8b0e, 0x8ff7, 0x9761, 0x9ef4, 0x5cb7, 0x60b6, 0x610d, 0x61ab, 0x654f, 0x65fb, 0x65fc, 0x6c11, 0x6cef, 0x739f, 0x73c9, 0x7de1, 0x9594, 0x5bc6, 0x871c, 0x8b10, 0x525d, 0x535a, 0x62cd, 0x640f, 0x64b2, 0x6734, 0x6a38, 0x6cca, 0x73c0, 0x749e, 0x7b94, 0x7c95, 0x7e1b, 0x818a, 0x8236, 0x8584, 0x8feb, 0x96f9, 0x99c1, 0x4f34, 0x534a, 0x53cd, 0x53db, 0x62cc, 0x642c, 0x6500, 0x6591, 0x69c3, 0x6cee, 0x6f58, 0x73ed, 0x7554, 0x7622, 0x76e4, 0x76fc, 0x78d0, 0x78fb, 0x792c, 0x7d46, 0x822c, 0x87e0, 0x8fd4, 0x9812, 0x98ef, 0x52c3, 0x62d4, 0x64a5, 0x6e24, 0x6f51, /* 0x5b */ 0x767c, 0x8dcb, 0x91b1, 0x9262, 0x9aee, 0x9b43, 0x5023, 0x508d, 0x574a, 0x59a8, 0x5c28, 0x5e47, 0x5f77, 0x623f, 0x653e, 0x65b9, 0x65c1, 0x6609, 0x678b, 0x699c, 0x6ec2, 0x78c5, 0x7d21, 0x80aa, 0x8180, 0x822b, 0x82b3, 0x84a1, 0x868c, 0x8a2a, 0x8b17, 0x90a6, 0x9632, 0x9f90, 0x500d, 0x4ff3, 0xf963, 0x57f9, 0x5f98, 0x62dc, 0x6392, 0x676f, 0x6e43, 0x7119, 0x76c3, 0x80cc, 0x80da, 0x88f4, 0x88f5, 0x8919, 0x8ce0, 0x8f29, 0x914d, 0x966a, 0x4f2f, 0x4f70, 0x5e1b, 0x67cf, 0x6822, 0x767d, 0x767e, 0x9b44, 0x5e61, 0x6a0a, 0x7169, 0x71d4, 0x756a, 0xf964, 0x7e41, 0x8543, 0x85e9, 0x98dc, 0x4f10, 0x7b4f, 0x7f70, 0x95a5, 0x51e1, 0x5e06, 0x68b5, 0x6c3e, 0x6c4e, 0x6cdb, 0x72af, 0x7bc4, 0x8303, 0x6cd5, 0x743a, 0x50fb, 0x5288, 0x58c1, 0x64d8, 0x6a97, 0x74a7, 0x7656, /* 0x5c */ 0x78a7, 0x8617, 0x95e2, 0x9739, 0xf965, 0x535e, 0x5f01, 0x8b8a, 0x8fa8, 0x8faf, 0x908a, 0x5225, 0x77a5, 0x9c49, 0x9f08, 0x4e19, 0x5002, 0x5175, 0x5c5b, 0x5e77, 0x661e, 0x663a, 0x67c4, 0x68c5, 0x70b3, 0x7501, 0x75c5, 0x79c9, 0x7add, 0x8f27, 0x9920, 0x9a08, 0x4fdd, 0x5821, 0x5831, 0x5bf6, 0x666e, 0x6b65, 0x6d11, 0x6e7a, 0x6f7d, 0x73e4, 0x752b, 0x83e9, 0x88dc, 0x8913, 0x8b5c, 0x8f14, 0x4f0f, 0x50d5, 0x5310, 0x535c, 0x5b93, 0x5fa9, 0x670d, 0x798f, 0x8179, 0x832f, 0x8514, 0x8907, 0x8986, 0x8f39, 0x8f3b, 0x99a5, 0x9c12, 0x672c, 0x4e76, 0x4ff8, 0x5949, 0x5c01, 0x5cef, 0x5cf0, 0x6367, 0x68d2, 0x70fd, 0x71a2, 0x742b, 0x7e2b, 0x84ec, 0x8702, 0x9022, 0x92d2, 0x9cf3, 0x4e0d, 0x4ed8, 0x4fef, 0x5085, 0x5256, 0x526f, 0x5426, 0x5490, 0x57e0, 0x592b, 0x5a66, /* 0x5d */ 0x5b5a, 0x5b75, 0x5bcc, 0x5e9c, 0xf966, 0x6276, 0x6577, 0x65a7, 0x6d6e, 0x6ea5, 0x7236, 0x7b26, 0x7c3f, 0x7f36, 0x8150, 0x8151, 0x819a, 0x8240, 0x8299, 0x83a9, 0x8a03, 0x8ca0, 0x8ce6, 0x8cfb, 0x8d74, 0x8dba, 0x90e8, 0x91dc, 0x961c, 0x9644, 0x99d9, 0x9ce7, 0x5317, 0x5206, 0x5429, 0x5674, 0x58b3, 0x5954, 0x596e, 0x5fff, 0x61a4, 0x626e, 0x6610, 0x6c7e, 0x711a, 0x76c6, 0x7c89, 0x7cde, 0x7d1b, 0x82ac, 0x8cc1, 0x96f0, 0xf967, 0x4f5b, 0x5f17, 0x5f7f, 0x62c2, 0x5d29, 0x670b, 0x68da, 0x787c, 0x7e43, 0x9d6c, 0x4e15, 0x5099, 0x5315, 0x532a, 0x5351, 0x5983, 0x5a62, 0x5e87, 0x60b2, 0x618a, 0x6249, 0x6279, 0x6590, 0x6787, 0x69a7, 0x6bd4, 0x6bd6, 0x6bd7, 0x6bd8, 0x6cb8, 0xf968, 0x7435, 0x75fa, 0x7812, 0x7891, 0x79d5, 0x79d8, 0x7c83, 0x7dcb, 0x7fe1, 0x80a5, /* 0x5e */ 0x813e, 0x81c2, 0x83f2, 0x871a, 0x88e8, 0x8ab9, 0x8b6c, 0x8cbb, 0x9119, 0x975e, 0x98db, 0x9f3b, 0x56ac, 0x5b2a, 0x5f6c, 0x658c, 0x6ab3, 0x6baf, 0x6d5c, 0x6ff1, 0x7015, 0x725d, 0x73ad, 0x8ca7, 0x8cd3, 0x983b, 0x6191, 0x6c37, 0x8058, 0x9a01, 0x4e4d, 0x4e8b, 0x4e9b, 0x4ed5, 0x4f3a, 0x4f3c, 0x4f7f, 0x4fdf, 0x50ff, 0x53f2, 0x53f8, 0x5506, 0x55e3, 0x56db, 0x58eb, 0x5962, 0x5a11, 0x5beb, 0x5bfa, 0x5c04, 0x5df3, 0x5e2b, 0x5f99, 0x601d, 0x6368, 0x659c, 0x65af, 0x67f6, 0x67fb, 0x68ad, 0x6b7b, 0x6c99, 0x6cd7, 0x6e23, 0x7009, 0x7345, 0x7802, 0x793e, 0x7940, 0x7960, 0x79c1, 0x7be9, 0x7d17, 0x7d72, 0x8086, 0x820d, 0x838e, 0x84d1, 0x86c7, 0x88df, 0x8a50, 0x8a5e, 0x8b1d, 0x8cdc, 0x8d66, 0x8fad, 0x90aa, 0x98fc, 0x99df, 0x9e9d, 0x524a, 0xf969, 0x6714, 0xf96a, /* 0x5f */ 0x5098, 0x522a, 0x5c71, 0x6563, 0x6c55, 0x73ca, 0x7523, 0x759d, 0x7b97, 0x849c, 0x9178, 0x9730, 0x4e77, 0x6492, 0x6bba, 0x715e, 0x85a9, 0x4e09, 0xf96b, 0x6749, 0x68ee, 0x6e17, 0x829f, 0x8518, 0x886b, 0x63f7, 0x6f81, 0x9212, 0x98af, 0x4e0a, 0x50b7, 0x50cf, 0x511f, 0x5546, 0x55aa, 0x5617, 0x5b40, 0x5c19, 0x5ce0, 0x5e38, 0x5e8a, 0x5ea0, 0x5ec2, 0x60f3, 0x6851, 0x6a61, 0x6e58, 0x723d, 0x7240, 0x72c0, 0x76f8, 0x7965, 0x7bb1, 0x7fd4, 0x88f3, 0x89f4, 0x8a73, 0x8c61, 0x8cde, 0x971c, 0x585e, 0x74bd, 0x8cfd, 0x55c7, 0xf96c, 0x7a61, 0x7d22, 0x8272, 0x7272, 0x751f, 0x7525, 0xf96d, 0x7b19, 0x5885, 0x58fb, 0x5dbc, 0x5e8f, 0x5eb6, 0x5f90, 0x6055, 0x6292, 0x637f, 0x654d, 0x6691, 0x66d9, 0x66f8, 0x6816, 0x68f2, 0x7280, 0x745e, 0x7b6e, 0x7d6e, 0x7dd6, 0x7f72, /* 0x60 */ 0x80e5, 0x8212, 0x85af, 0x897f, 0x8a93, 0x901d, 0x92e4, 0x9ecd, 0x9f20, 0x5915, 0x596d, 0x5e2d, 0x60dc, 0x6614, 0x6673, 0x6790, 0x6c50, 0x6dc5, 0x6f5f, 0x77f3, 0x78a9, 0x84c6, 0x91cb, 0x932b, 0x4ed9, 0x50ca, 0x5148, 0x5584, 0x5b0b, 0x5ba3, 0x6247, 0x657e, 0x65cb, 0x6e32, 0x717d, 0x7401, 0x7444, 0x7487, 0x74bf, 0x766c, 0x79aa, 0x7dda, 0x7e55, 0x7fa8, 0x817a, 0x81b3, 0x8239, 0x861a, 0x87ec, 0x8a75, 0x8de3, 0x9078, 0x9291, 0x9425, 0x994d, 0x9bae, 0x5368, 0x5c51, 0x6954, 0x6cc4, 0x6d29, 0x6e2b, 0x820c, 0x859b, 0x893b, 0x8a2d, 0x8aaa, 0x96ea, 0x9f67, 0x5261, 0x66b9, 0x6bb2, 0x7e96, 0x87fe, 0x8d0d, 0x9583, 0x965d, 0x651d, 0x6d89, 0x71ee, 0xf96e, 0x57ce, 0x59d3, 0x5bac, 0x6027, 0x60fa, 0x6210, 0x661f, 0x665f, 0x7329, 0x73f9, 0x76db, 0x7701, 0x7b6c, /* 0x61 */ 0x8056, 0x8072, 0x8165, 0x8aa0, 0x9192, 0x4e16, 0x52e2, 0x6b72, 0x6d17, 0x7a05, 0x7b39, 0x7d30, 0xf96f, 0x8cb0, 0x53ec, 0x562f, 0x5851, 0x5bb5, 0x5c0f, 0x5c11, 0x5de2, 0x6240, 0x6383, 0x6414, 0x662d, 0x68b3, 0x6cbc, 0x6d88, 0x6eaf, 0x701f, 0x70a4, 0x71d2, 0x7526, 0x758f, 0x758e, 0x7619, 0x7b11, 0x7be0, 0x7c2b, 0x7d20, 0x7d39, 0x852c, 0x856d, 0x8607, 0x8a34, 0x900d, 0x9061, 0x90b5, 0x92b7, 0x97f6, 0x9a37, 0x4fd7, 0x5c6c, 0x675f, 0x6d91, 0x7c9f, 0x7e8c, 0x8b16, 0x8d16, 0x901f, 0x5b6b, 0x5dfd, 0x640d, 0x84c0, 0x905c, 0x98e1, 0x7387, 0x5b8b, 0x609a, 0x677e, 0x6dde, 0x8a1f, 0x8aa6, 0x9001, 0x980c, 0x5237, 0xf970, 0x7051, 0x788e, 0x9396, 0x8870, 0x91d7, 0x4fee, 0x53d7, 0x55fd, 0x56da, 0x5782, 0x58fd, 0x5ac2, 0x5b88, 0x5cab, 0x5cc0, 0x5e25, 0x6101, /* 0x62 */ 0x620d, 0x624b, 0x6388, 0x641c, 0x6536, 0x6578, 0x6a39, 0x6b8a, 0x6c34, 0x6d19, 0x6f31, 0x71e7, 0x72e9, 0x7378, 0x7407, 0x74b2, 0x7626, 0x7761, 0x79c0, 0x7a57, 0x7aea, 0x7cb9, 0x7d8f, 0x7dac, 0x7e61, 0x7f9e, 0x8129, 0x8331, 0x8490, 0x84da, 0x85ea, 0x8896, 0x8ab0, 0x8b90, 0x8f38, 0x9042, 0x9083, 0x916c, 0x9296, 0x92b9, 0x968b, 0x96a7, 0x96a8, 0x96d6, 0x9700, 0x9808, 0x9996, 0x9ad3, 0x9b1a, 0x53d4, 0x587e, 0x5919, 0x5b70, 0x5bbf, 0x6dd1, 0x6f5a, 0x719f, 0x7421, 0x74b9, 0x8085, 0x83fd, 0x5de1, 0x5f87, 0x5faa, 0x6042, 0x65ec, 0x6812, 0x696f, 0x6a53, 0x6b89, 0x6d35, 0x6df3, 0x73e3, 0x76fe, 0x77ac, 0x7b4d, 0x7d14, 0x8123, 0x821c, 0x8340, 0x84f4, 0x8563, 0x8a62, 0x8ac4, 0x9187, 0x931e, 0x9806, 0x99b4, 0x620c, 0x8853, 0x8ff0, 0x9265, 0x5d07, 0x5d27, /* 0x63 */ 0x5d69, 0x745f, 0x819d, 0x8768, 0x6fd5, 0x62fe, 0x7fd2, 0x8936, 0x8972, 0x4e1e, 0x4e58, 0x50e7, 0x52dd, 0x5347, 0x627f, 0x6607, 0x7e69, 0x8805, 0x965e, 0x4f8d, 0x5319, 0x5636, 0x59cb, 0x5aa4, 0x5c38, 0x5c4e, 0x5c4d, 0x5e02, 0x5f11, 0x6043, 0x65bd, 0x662f, 0x6642, 0x67be, 0x67f4, 0x731c, 0x77e2, 0x793a, 0x7fc5, 0x8494, 0x84cd, 0x8996, 0x8a66, 0x8a69, 0x8ae1, 0x8c55, 0x8c7a, 0x57f4, 0x5bd4, 0x5f0f, 0x606f, 0x62ed, 0x690d, 0x6b96, 0x6e5c, 0x7184, 0x7bd2, 0x8755, 0x8b58, 0x8efe, 0x98df, 0x98fe, 0x4f38, 0x4f81, 0x4fe1, 0x547b, 0x5a20, 0x5bb8, 0x613c, 0x65b0, 0x6668, 0x71fc, 0x7533, 0x795e, 0x7d33, 0x814e, 0x81e3, 0x8398, 0x85aa, 0x85ce, 0x8703, 0x8a0a, 0x8eab, 0x8f9b, 0xf971, 0x8fc5, 0x5931, 0x5ba4, 0x5be6, 0x6089, 0x5be9, 0x5c0b, 0x5fc3, 0x6c81, /* 0x64 */ 0xf972, 0x6df1, 0x700b, 0x751a, 0x82af, 0x8af6, 0x4ec0, 0x5341, 0xf973, 0x96d9, 0x6c0f, 0x4e9e, 0x4fc4, 0x5152, 0x555e, 0x5a25, 0x5ce8, 0x6211, 0x7259, 0x82bd, 0x83aa, 0x86fe, 0x8859, 0x8a1d, 0x963f, 0x96c5, 0x9913, 0x9d09, 0x9d5d, 0x580a, 0x5cb3, 0x5dbd, 0x5e44, 0x60e1, 0x6115, 0x63e1, 0x6a02, 0x6e25, 0x9102, 0x9354, 0x984e, 0x9c10, 0x9f77, 0x5b89, 0x5cb8, 0x6309, 0x664f, 0x6848, 0x773c, 0x96c1, 0x978d, 0x9854, 0x9b9f, 0x65a1, 0x8b01, 0x8ecb, 0x95bc, 0x5535, 0x5ca9, 0x5dd6, 0x5eb5, 0x6697, 0x764c, 0x83f4, 0x95c7, 0x58d3, 0x62bc, 0x72ce, 0x9d28, 0x4ef0, 0x592e, 0x600f, 0x663b, 0x6b83, 0x79e7, 0x9d26, 0x5393, 0x54c0, 0x57c3, 0x5d16, 0x611b, 0x66d6, 0x6daf, 0x788d, 0x827e, 0x9698, 0x9744, 0x5384, 0x627c, 0x6396, 0x6db2, 0x7e0a, 0x814b, 0x984d, /* 0x65 */ 0x6afb, 0x7f4c, 0x9daf, 0x9e1a, 0x4e5f, 0x503b, 0x51b6, 0x591c, 0x60f9, 0x63f6, 0x6930, 0x723a, 0x8036, 0xf974, 0x91ce, 0x5f31, 0xf975, 0xf976, 0x7d04, 0x82e5, 0x846f, 0x84bb, 0x85e5, 0x8e8d, 0xf977, 0x4f6f, 0xf978, 0xf979, 0x58e4, 0x5b43, 0x6059, 0x63da, 0x6518, 0x656d, 0x6698, 0xf97a, 0x694a, 0x6a23, 0x6d0b, 0x7001, 0x716c, 0x75d2, 0x760d, 0x79b3, 0x7a70, 0xf97b, 0x7f8a, 0xf97c, 0x8944, 0xf97d, 0x8b93, 0x91c0, 0x967d, 0xf97e, 0x990a, 0x5704, 0x5fa1, 0x65bc, 0x6f01, 0x7600, 0x79a6, 0x8a9e, 0x99ad, 0x9b5a, 0x9f6c, 0x5104, 0x61b6, 0x6291, 0x6a8d, 0x81c6, 0x5043, 0x5830, 0x5f66, 0x7109, 0x8a00, 0x8afa, 0x5b7c, 0x8616, 0x4ffa, 0x513c, 0x56b4, 0x5944, 0x63a9, 0x6df9, 0x5daa, 0x696d, 0x5186, 0x4e88, 0x4f59, 0xf97f, 0xf980, 0xf981, 0x5982, 0xf982, /* 0x66 */ 0xf983, 0x6b5f, 0x6c5d, 0xf984, 0x74b5, 0x7916, 0xf985, 0x8207, 0x8245, 0x8339, 0x8f3f, 0x8f5d, 0xf986, 0x9918, 0xf987, 0xf988, 0xf989, 0x4ea6, 0xf98a, 0x57df, 0x5f79, 0x6613, 0xf98b, 0xf98c, 0x75ab, 0x7e79, 0x8b6f, 0xf98d, 0x9006, 0x9a5b, 0x56a5, 0x5827, 0x59f8, 0x5a1f, 0x5bb4, 0xf98e, 0x5ef6, 0xf98f, 0xf990, 0x6350, 0x633b, 0xf991, 0x693d, 0x6c87, 0x6cbf, 0x6d8e, 0x6d93, 0x6df5, 0x6f14, 0xf992, 0x70df, 0x7136, 0x7159, 0xf993, 0x71c3, 0x71d5, 0xf994, 0x784f, 0x786f, 0xf995, 0x7b75, 0x7de3, 0xf996, 0x7e2f, 0xf997, 0x884d, 0x8edf, 0xf998, 0xf999, 0xf99a, 0x925b, 0xf99b, 0x9cf6, 0xf99c, 0xf99d, 0xf99e, 0x6085, 0x6d85, 0xf99f, 0x71b1, 0xf9a0, 0xf9a1, 0x95b1, 0x53ad, 0xf9a2, 0xf9a3, 0xf9a4, 0x67d3, 0xf9a5, 0x708e, 0x7130, 0x7430, 0x8276, 0x82d2, /* 0x67 */ 0xf9a6, 0x95bb, 0x9ae5, 0x9e7d, 0x66c4, 0xf9a7, 0x71c1, 0x8449, 0xf9a8, 0xf9a9, 0x584b, 0xf9aa, 0xf9ab, 0x5db8, 0x5f71, 0xf9ac, 0x6620, 0x668e, 0x6979, 0x69ae, 0x6c38, 0x6cf3, 0x6e36, 0x6f41, 0x6fda, 0x701b, 0x702f, 0x7150, 0x71df, 0x7370, 0xf9ad, 0x745b, 0xf9ae, 0x74d4, 0x76c8, 0x7a4e, 0x7e93, 0xf9af, 0xf9b0, 0x82f1, 0x8a60, 0x8fce, 0xf9b1, 0x9348, 0xf9b2, 0x9719, 0xf9b3, 0xf9b4, 0x4e42, 0x502a, 0xf9b5, 0x5208, 0x53e1, 0x66f3, 0x6c6d, 0x6fca, 0x730a, 0x777f, 0x7a62, 0x82ae, 0x85dd, 0x8602, 0xf9b6, 0x88d4, 0x8a63, 0x8b7d, 0x8c6b, 0xf9b7, 0x92b3, 0xf9b8, 0x9713, 0x9810, 0x4e94, 0x4f0d, 0x4fc9, 0x50b2, 0x5348, 0x543e, 0x5433, 0x55da, 0x5862, 0x58ba, 0x5967, 0x5a1b, 0x5be4, 0x609f, 0xf9b9, 0x61ca, 0x6556, 0x65ff, 0x6664, 0x68a7, 0x6c5a, 0x6fb3, /* 0x68 */ 0x70cf, 0x71ac, 0x7352, 0x7b7d, 0x8708, 0x8aa4, 0x9c32, 0x9f07, 0x5c4b, 0x6c83, 0x7344, 0x7389, 0x923a, 0x6eab, 0x7465, 0x761f, 0x7a69, 0x7e15, 0x860a, 0x5140, 0x58c5, 0x64c1, 0x74ee, 0x7515, 0x7670, 0x7fc1, 0x9095, 0x96cd, 0x9954, 0x6e26, 0x74e6, 0x7aa9, 0x7aaa, 0x81e5, 0x86d9, 0x8778, 0x8a1b, 0x5a49, 0x5b8c, 0x5b9b, 0x68a1, 0x6900, 0x6d63, 0x73a9, 0x7413, 0x742c, 0x7897, 0x7de9, 0x7feb, 0x8118, 0x8155, 0x839e, 0x8c4c, 0x962e, 0x9811, 0x66f0, 0x5f80, 0x65fa, 0x6789, 0x6c6a, 0x738b, 0x502d, 0x5a03, 0x6b6a, 0x77ee, 0x5916, 0x5d6c, 0x5dcd, 0x7325, 0x754f, 0xf9ba, 0xf9bb, 0x50e5, 0x51f9, 0x582f, 0x592d, 0x5996, 0x59da, 0x5be5, 0xf9bc, 0xf9bd, 0x5da2, 0x62d7, 0x6416, 0x6493, 0x64fe, 0xf9be, 0x66dc, 0xf9bf, 0x6a48, 0xf9c0, 0x71ff, 0x7464, 0xf9c1, /* 0x69 */ 0x7a88, 0x7aaf, 0x7e47, 0x7e5e, 0x8000, 0x8170, 0xf9c2, 0x87ef, 0x8981, 0x8b20, 0x9059, 0xf9c3, 0x9080, 0x9952, 0x617e, 0x6b32, 0x6d74, 0x7e1f, 0x8925, 0x8fb1, 0x4fd1, 0x50ad, 0x5197, 0x52c7, 0x57c7, 0x5889, 0x5bb9, 0x5eb8, 0x6142, 0x6995, 0x6d8c, 0x6e67, 0x6eb6, 0x7194, 0x7462, 0x7528, 0x752c, 0x8073, 0x8338, 0x84c9, 0x8e0a, 0x9394, 0x93de, 0xf9c4, 0x4e8e, 0x4f51, 0x5076, 0x512a, 0x53c8, 0x53cb, 0x53f3, 0x5b87, 0x5bd3, 0x5c24, 0x611a, 0x6182, 0x65f4, 0x725b, 0x7397, 0x7440, 0x76c2, 0x7950, 0x7991, 0x79b9, 0x7d06, 0x7fbd, 0x828b, 0x85d5, 0x865e, 0x8fc2, 0x9047, 0x90f5, 0x91ea, 0x9685, 0x96e8, 0x96e9, 0x52d6, 0x5f67, 0x65ed, 0x6631, 0x682f, 0x715c, 0x7a36, 0x90c1, 0x980a, 0x4e91, 0xf9c5, 0x6a52, 0x6b9e, 0x6f90, 0x7189, 0x8018, 0x82b8, 0x8553, /* 0x6a */ 0x904b, 0x9695, 0x96f2, 0x97fb, 0x851a, 0x9b31, 0x4e90, 0x718a, 0x96c4, 0x5143, 0x539f, 0x54e1, 0x5713, 0x5712, 0x57a3, 0x5a9b, 0x5ac4, 0x5bc3, 0x6028, 0x613f, 0x63f4, 0x6c85, 0x6d39, 0x6e72, 0x6e90, 0x7230, 0x733f, 0x7457, 0x82d1, 0x8881, 0x8f45, 0x9060, 0xf9c6, 0x9662, 0x9858, 0x9d1b, 0x6708, 0x8d8a, 0x925e, 0x4f4d, 0x5049, 0x50de, 0x5371, 0x570d, 0x59d4, 0x5a01, 0x5c09, 0x6170, 0x6690, 0x6e2d, 0x7232, 0x744b, 0x7def, 0x80c3, 0x840e, 0x8466, 0x853f, 0x875f, 0x885b, 0x8918, 0x8b02, 0x9055, 0x97cb, 0x9b4f, 0x4e73, 0x4f91, 0x5112, 0x516a, 0xf9c7, 0x552f, 0x55a9, 0x5b7a, 0x5ba5, 0x5e7c, 0x5e7d, 0x5ebe, 0x60a0, 0x60df, 0x6108, 0x6109, 0x63c4, 0x6538, 0x6709, 0xf9c8, 0x67d4, 0x67da, 0xf9c9, 0x6961, 0x6962, 0x6cb9, 0x6d27, 0xf9ca, 0x6e38, 0xf9cb, /* 0x6b */ 0x6fe1, 0x7336, 0x7337, 0xf9cc, 0x745c, 0x7531, 0xf9cd, 0x7652, 0xf9ce, 0xf9cf, 0x7dad, 0x81fe, 0x8438, 0x88d5, 0x8a98, 0x8adb, 0x8aed, 0x8e30, 0x8e42, 0x904a, 0x903e, 0x907a, 0x9149, 0x91c9, 0x936e, 0xf9d0, 0xf9d1, 0x5809, 0xf9d2, 0x6bd3, 0x8089, 0x80b2, 0xf9d3, 0xf9d4, 0x5141, 0x596b, 0x5c39, 0xf9d5, 0xf9d6, 0x6f64, 0x73a7, 0x80e4, 0x8d07, 0xf9d7, 0x9217, 0x958f, 0xf9d8, 0xf9d9, 0xf9da, 0xf9db, 0x807f, 0x620e, 0x701c, 0x7d68, 0x878d, 0xf9dc, 0x57a0, 0x6069, 0x6147, 0x6bb7, 0x8abe, 0x9280, 0x96b1, 0x4e59, 0x541f, 0x6deb, 0x852d, 0x9670, 0x97f3, 0x98ee, 0x63d6, 0x6ce3, 0x9091, 0x51dd, 0x61c9, 0x81ba, 0x9df9, 0x4f9d, 0x501a, 0x5100, 0x5b9c, 0x610f, 0x61ff, 0x64ec, 0x6905, 0x6bc5, 0x7591, 0x77e3, 0x7fa9, 0x8264, 0x858f, 0x87fb, 0x8863, 0x8abc, /* 0x6c */ 0x8b70, 0x91ab, 0x4e8c, 0x4ee5, 0x4f0a, 0xf9dd, 0xf9de, 0x5937, 0x59e8, 0xf9df, 0x5df2, 0x5f1b, 0x5f5b, 0x6021, 0xf9e0, 0xf9e1, 0xf9e2, 0xf9e3, 0x723e, 0x73e5, 0xf9e4, 0x7570, 0x75cd, 0xf9e5, 0x79fb, 0xf9e6, 0x800c, 0x8033, 0x8084, 0x82e1, 0x8351, 0xf9e7, 0xf9e8, 0x8cbd, 0x8cb3, 0x9087, 0xf9e9, 0xf9ea, 0x98f4, 0x990c, 0xf9eb, 0xf9ec, 0x7037, 0x76ca, 0x7fca, 0x7fcc, 0x7ffc, 0x8b1a, 0x4eba, 0x4ec1, 0x5203, 0x5370, 0xf9ed, 0x54bd, 0x56e0, 0x59fb, 0x5bc5, 0x5f15, 0x5fcd, 0x6e6e, 0xf9ee, 0xf9ef, 0x7d6a, 0x8335, 0xf9f0, 0x8693, 0x8a8d, 0xf9f1, 0x976d, 0x9777, 0xf9f2, 0xf9f3, 0x4e00, 0x4f5a, 0x4f7e, 0x58f9, 0x65e5, 0x6ea2, 0x9038, 0x93b0, 0x99b9, 0x4efb, 0x58ec, 0x598a, 0x59d9, 0x6041, 0xf9f4, 0xf9f5, 0x7a14, 0xf9f6, 0x834f, 0x8cc3, 0x5165, 0x5344, /* 0x6d */ 0xf9f7, 0xf9f8, 0xf9f9, 0x4ecd, 0x5269, 0x5b55, 0x82bf, 0x4ed4, 0x523a, 0x54a8, 0x59c9, 0x59ff, 0x5b50, 0x5b57, 0x5b5c, 0x6063, 0x6148, 0x6ecb, 0x7099, 0x716e, 0x7386, 0x74f7, 0x75b5, 0x78c1, 0x7d2b, 0x8005, 0x81ea, 0x8328, 0x8517, 0x85c9, 0x8aee, 0x8cc7, 0x96cc, 0x4f5c, 0x52fa, 0x56bc, 0x65ab, 0x6628, 0x707c, 0x70b8, 0x7235, 0x7dbd, 0x828d, 0x914c, 0x96c0, 0x9d72, 0x5b71, 0x68e7, 0x6b98, 0x6f7a, 0x76de, 0x5c91, 0x66ab, 0x6f5b, 0x7bb4, 0x7c2a, 0x8836, 0x96dc, 0x4e08, 0x4ed7, 0x5320, 0x5834, 0x58bb, 0x58ef, 0x596c, 0x5c07, 0x5e33, 0x5e84, 0x5f35, 0x638c, 0x66b2, 0x6756, 0x6a1f, 0x6aa3, 0x6b0c, 0x6f3f, 0x7246, 0xf9fa, 0x7350, 0x748b, 0x7ae0, 0x7ca7, 0x8178, 0x81df, 0x81e7, 0x838a, 0x846c, 0x8523, 0x8594, 0x85cf, 0x88dd, 0x8d13, 0x91ac, 0x9577, /* 0x6e */ 0x969c, 0x518d, 0x54c9, 0x5728, 0x5bb0, 0x624d, 0x6750, 0x683d, 0x6893, 0x6e3d, 0x6ed3, 0x707d, 0x7e21, 0x88c1, 0x8ca1, 0x8f09, 0x9f4b, 0x9f4e, 0x722d, 0x7b8f, 0x8acd, 0x931a, 0x4f47, 0x4f4e, 0x5132, 0x5480, 0x59d0, 0x5e95, 0x62b5, 0x6775, 0x696e, 0x6a17, 0x6cae, 0x6e1a, 0x72d9, 0x732a, 0x75bd, 0x7bb8, 0x7d35, 0x82e7, 0x83f9, 0x8457, 0x85f7, 0x8a5b, 0x8caf, 0x8e87, 0x9019, 0x90b8, 0x96ce, 0x9f5f, 0x52e3, 0x540a, 0x5ae1, 0x5bc2, 0x6458, 0x6575, 0x6ef4, 0x72c4, 0xf9fb, 0x7684, 0x7a4d, 0x7b1b, 0x7c4d, 0x7e3e, 0x7fdf, 0x837b, 0x8b2b, 0x8cca, 0x8d64, 0x8de1, 0x8e5f, 0x8fea, 0x8ff9, 0x9069, 0x93d1, 0x4f43, 0x4f7a, 0x50b3, 0x5168, 0x5178, 0x524d, 0x526a, 0x5861, 0x587c, 0x5960, 0x5c08, 0x5c55, 0x5edb, 0x609b, 0x6230, 0x6813, 0x6bbf, 0x6c08, 0x6fb1, /* 0x6f */ 0x714e, 0x7420, 0x7530, 0x7538, 0x7551, 0x7672, 0x7b4c, 0x7b8b, 0x7bad, 0x7bc6, 0x7e8f, 0x8a6e, 0x8f3e, 0x8f49, 0x923f, 0x9293, 0x9322, 0x942b, 0x96fb, 0x985a, 0x986b, 0x991e, 0x5207, 0x622a, 0x6298, 0x6d59, 0x7664, 0x7aca, 0x7bc0, 0x7d76, 0x5360, 0x5cbe, 0x5e97, 0x6f38, 0x70b9, 0x7c98, 0x9711, 0x9b8e, 0x9ede, 0x63a5, 0x647a, 0x8776, 0x4e01, 0x4e95, 0x4ead, 0x505c, 0x5075, 0x5448, 0x59c3, 0x5b9a, 0x5e40, 0x5ead, 0x5ef7, 0x5f81, 0x60c5, 0x633a, 0x653f, 0x6574, 0x65cc, 0x6676, 0x6678, 0x67fe, 0x6968, 0x6a89, 0x6b63, 0x6c40, 0x6dc0, 0x6de8, 0x6e1f, 0x6e5e, 0x701e, 0x70a1, 0x738e, 0x73fd, 0x753a, 0x775b, 0x7887, 0x798e, 0x7a0b, 0x7a7d, 0x7cbe, 0x7d8e, 0x8247, 0x8a02, 0x8aea, 0x8c9e, 0x912d, 0x914a, 0x91d8, 0x9266, 0x92cc, 0x9320, 0x9706, 0x9756, /* 0x70 */ 0x975c, 0x9802, 0x9f0e, 0x5236, 0x5291, 0x557c, 0x5824, 0x5e1d, 0x5f1f, 0x608c, 0x63d0, 0x68af, 0x6fdf, 0x796d, 0x7b2c, 0x81cd, 0x85ba, 0x88fd, 0x8af8, 0x8e44, 0x918d, 0x9664, 0x969b, 0x973d, 0x984c, 0x9f4a, 0x4fce, 0x5146, 0x51cb, 0x52a9, 0x5632, 0x5f14, 0x5f6b, 0x63aa, 0x64cd, 0x65e9, 0x6641, 0x66fa, 0x66f9, 0x671d, 0x689d, 0x68d7, 0x69fd, 0x6f15, 0x6f6e, 0x7167, 0x71e5, 0x722a, 0x74aa, 0x773a, 0x7956, 0x795a, 0x79df, 0x7a20, 0x7a95, 0x7c97, 0x7cdf, 0x7d44, 0x7e70, 0x8087, 0x85fb, 0x86a4, 0x8a54, 0x8abf, 0x8d99, 0x8e81, 0x9020, 0x906d, 0x91e3, 0x963b, 0x96d5, 0x9ce5, 0x65cf, 0x7c07, 0x8db3, 0x93c3, 0x5b58, 0x5c0a, 0x5352, 0x62d9, 0x731d, 0x5027, 0x5b97, 0x5f9e, 0x60b0, 0x616b, 0x68d5, 0x6dd9, 0x742e, 0x7a2e, 0x7d42, 0x7d9c, 0x7e31, 0x816b, /* 0x71 */ 0x8e2a, 0x8e35, 0x937e, 0x9418, 0x4f50, 0x5750, 0x5de6, 0x5ea7, 0x632b, 0x7f6a, 0x4e3b, 0x4f4f, 0x4f8f, 0x505a, 0x59dd, 0x80c4, 0x546a, 0x5468, 0x55fe, 0x594f, 0x5b99, 0x5dde, 0x5eda, 0x665d, 0x6731, 0x67f1, 0x682a, 0x6ce8, 0x6d32, 0x6e4a, 0x6f8d, 0x70b7, 0x73e0, 0x7587, 0x7c4c, 0x7d02, 0x7d2c, 0x7da2, 0x821f, 0x86db, 0x8a3b, 0x8a85, 0x8d70, 0x8e8a, 0x8f33, 0x9031, 0x914e, 0x9152, 0x9444, 0x99d0, 0x7af9, 0x7ca5, 0x4fca, 0x5101, 0x51c6, 0x57c8, 0x5bef, 0x5cfb, 0x6659, 0x6a3d, 0x6d5a, 0x6e96, 0x6fec, 0x710c, 0x756f, 0x7ae3, 0x8822, 0x9021, 0x9075, 0x96cb, 0x99ff, 0x8301, 0x4e2d, 0x4ef2, 0x8846, 0x91cd, 0x537d, 0x6adb, 0x696b, 0x6c41, 0x847a, 0x589e, 0x618e, 0x66fe, 0x62ef, 0x70dd, 0x7511, 0x75c7, 0x7e52, 0x84b8, 0x8b49, 0x8d08, 0x4e4b, 0x53ea, /* 0x72 */ 0x54ab, 0x5730, 0x5740, 0x5fd7, 0x6301, 0x6307, 0x646f, 0x652f, 0x65e8, 0x667a, 0x679d, 0x67b3, 0x6b62, 0x6c60, 0x6c9a, 0x6f2c, 0x77e5, 0x7825, 0x7949, 0x7957, 0x7d19, 0x80a2, 0x8102, 0x81f3, 0x829d, 0x82b7, 0x8718, 0x8a8c, 0xf9fc, 0x8d04, 0x8dbe, 0x9072, 0x76f4, 0x7a19, 0x7a37, 0x7e54, 0x8077, 0x5507, 0x55d4, 0x5875, 0x632f, 0x6422, 0x6649, 0x664b, 0x686d, 0x699b, 0x6b84, 0x6d25, 0x6eb1, 0x73cd, 0x7468, 0x74a1, 0x755b, 0x75b9, 0x76e1, 0x771e, 0x778b, 0x79e6, 0x7e09, 0x7e1d, 0x81fb, 0x852f, 0x8897, 0x8a3a, 0x8cd1, 0x8eeb, 0x8fb0, 0x9032, 0x93ad, 0x9663, 0x9673, 0x9707, 0x4f84, 0x53f1, 0x59ea, 0x5ac9, 0x5e19, 0x684e, 0x74c6, 0x75be, 0x79e9, 0x7a92, 0x81a3, 0x86ed, 0x8cea, 0x8dcc, 0x8fed, 0x659f, 0x6715, 0xf9fd, 0x57f7, 0x6f57, 0x7ddd, 0x8f2f, /* 0x73 */ 0x93f6, 0x96c6, 0x5fb5, 0x61f2, 0x6f84, 0x4e14, 0x4f98, 0x501f, 0x53c9, 0x55df, 0x5d6f, 0x5dee, 0x6b21, 0x6b64, 0x78cb, 0x7b9a, 0xf9fe, 0x8e49, 0x8eca, 0x906e, 0x6349, 0x643e, 0x7740, 0x7a84, 0x932f, 0x947f, 0x9f6a, 0x64b0, 0x6faf, 0x71e6, 0x74a8, 0x74da, 0x7ac4, 0x7c12, 0x7e82, 0x7cb2, 0x7e98, 0x8b9a, 0x8d0a, 0x947d, 0x9910, 0x994c, 0x5239, 0x5bdf, 0x64e6, 0x672d, 0x7d2e, 0x50ed, 0x53c3, 0x5879, 0x6158, 0x6159, 0x61fa, 0x65ac, 0x7ad9, 0x8b92, 0x8b96, 0x5009, 0x5021, 0x5275, 0x5531, 0x5a3c, 0x5ee0, 0x5f70, 0x6134, 0x655e, 0x660c, 0x6636, 0x66a2, 0x69cd, 0x6ec4, 0x6f32, 0x7316, 0x7621, 0x7a93, 0x8139, 0x8259, 0x83d6, 0x84bc, 0x50b5, 0x57f0, 0x5bc0, 0x5be8, 0x5f69, 0x63a1, 0x7826, 0x7db5, 0x83dc, 0x8521, 0x91c7, 0x91f5, 0x518a, 0x67f5, 0x7b56, /* 0x74 */ 0x8cac, 0x51c4, 0x59bb, 0x60bd, 0x8655, 0x501c, 0xf9ff, 0x5254, 0x5c3a, 0x617d, 0x621a, 0x62d3, 0x64f2, 0x65a5, 0x6ecc, 0x7620, 0x810a, 0x8e60, 0x965f, 0x96bb, 0x4edf, 0x5343, 0x5598, 0x5929, 0x5ddd, 0x64c5, 0x6cc9, 0x6dfa, 0x7394, 0x7a7f, 0x821b, 0x85a6, 0x8ce4, 0x8e10, 0x9077, 0x91e7, 0x95e1, 0x9621, 0x97c6, 0x51f8, 0x54f2, 0x5586, 0x5fb9, 0x64a4, 0x6f88, 0x7db4, 0x8f1f, 0x8f4d, 0x9435, 0x50c9, 0x5c16, 0x6cbe, 0x6dfb, 0x751b, 0x77bb, 0x7c3d, 0x7c64, 0x8a79, 0x8ac2, 0x581e, 0x59be, 0x5e16, 0x6377, 0x7252, 0x758a, 0x776b, 0x8adc, 0x8cbc, 0x8f12, 0x5ef3, 0x6674, 0x6df8, 0x807d, 0x83c1, 0x8acb, 0x9751, 0x9bd6, 0xfa00, 0x5243, 0x66ff, 0x6d95, 0x6eef, 0x7de0, 0x8ae6, 0x902e, 0x905e, 0x9ad4, 0x521d, 0x527f, 0x54e8, 0x6194, 0x6284, 0x62db, 0x68a2, /* 0x75 */ 0x6912, 0x695a, 0x6a35, 0x7092, 0x7126, 0x785d, 0x7901, 0x790e, 0x79d2, 0x7a0d, 0x8096, 0x8278, 0x82d5, 0x8349, 0x8549, 0x8c82, 0x8d85, 0x9162, 0x918b, 0x91ae, 0x4fc3, 0x56d1, 0x71ed, 0x77d7, 0x8700, 0x89f8, 0x5bf8, 0x5fd6, 0x6751, 0x90a8, 0x53e2, 0x585a, 0x5bf5, 0x60a4, 0x6181, 0x6460, 0x7e3d, 0x8070, 0x8525, 0x9283, 0x64ae, 0x50ac, 0x5d14, 0x6700, 0x589c, 0x62bd, 0x63a8, 0x690e, 0x6978, 0x6a1e, 0x6e6b, 0x76ba, 0x79cb, 0x82bb, 0x8429, 0x8acf, 0x8da8, 0x8ffd, 0x9112, 0x914b, 0x919c, 0x9310, 0x9318, 0x939a, 0x96db, 0x9a36, 0x9c0d, 0x4e11, 0x755c, 0x795d, 0x7afa, 0x7b51, 0x7bc9, 0x7e2e, 0x84c4, 0x8e59, 0x8e74, 0x8ef8, 0x9010, 0x6625, 0x693f, 0x7443, 0x51fa, 0x672e, 0x9edc, 0x5145, 0x5fe0, 0x6c96, 0x87f2, 0x885d, 0x8877, 0x60b4, 0x81b5, 0x8403, /* 0x76 */ 0x8d05, 0x53d6, 0x5439, 0x5634, 0x5a36, 0x5c31, 0x708a, 0x7fe0, 0x805a, 0x8106, 0x81ed, 0x8da3, 0x9189, 0x9a5f, 0x9df2, 0x5074, 0x4ec4, 0x53a0, 0x60fb, 0x6e2c, 0x5c64, 0x4f88, 0x5024, 0x55e4, 0x5cd9, 0x5e5f, 0x6065, 0x6894, 0x6cbb, 0x6dc4, 0x71be, 0x75d4, 0x75f4, 0x7661, 0x7a1a, 0x7a49, 0x7dc7, 0x7dfb, 0x7f6e, 0x81f4, 0x86a9, 0x8f1c, 0x96c9, 0x99b3, 0x9f52, 0x5247, 0x52c5, 0x98ed, 0x89aa, 0x4e03, 0x67d2, 0x6f06, 0x4fb5, 0x5be2, 0x6795, 0x6c88, 0x6d78, 0x741b, 0x7827, 0x91dd, 0x937c, 0x87c4, 0x79e4, 0x7a31, 0x5feb, 0x4ed6, 0x54a4, 0x553e, 0x58ae, 0x59a5, 0x60f0, 0x6253, 0x62d6, 0x6736, 0x6955, 0x8235, 0x9640, 0x99b1, 0x99dd, 0x502c, 0x5353, 0x5544, 0x577c, 0xfa01, 0x6258, 0xfa02, 0x64e2, 0x666b, 0x67dd, 0x6fc1, 0x6fef, 0x7422, 0x7438, 0x8a17, /* 0x77 */ 0x9438, 0x5451, 0x5606, 0x5766, 0x5f48, 0x619a, 0x6b4e, 0x7058, 0x70ad, 0x7dbb, 0x8a95, 0x596a, 0x812b, 0x63a2, 0x7708, 0x803d, 0x8caa, 0x5854, 0x642d, 0x69bb, 0x5b95, 0x5e11, 0x6e6f, 0xfa03, 0x8569, 0x514c, 0x53f0, 0x592a, 0x6020, 0x614b, 0x6b86, 0x6c70, 0x6cf0, 0x7b1e, 0x80ce, 0x82d4, 0x8dc6, 0x90b0, 0x98b1, 0xfa04, 0x64c7, 0x6fa4, 0x6491, 0x6504, 0x514e, 0x5410, 0x571f, 0x8a0e, 0x615f, 0x6876, 0xfa05, 0x75db, 0x7b52, 0x7d71, 0x901a, 0x5806, 0x69cc, 0x817f, 0x892a, 0x9000, 0x9839, 0x5078, 0x5957, 0x59ac, 0x6295, 0x900f, 0x9b2a, 0x615d, 0x7279, 0x95d6, 0x5761, 0x5a46, 0x5df4, 0x628a, 0x64ad, 0x64fa, 0x6777, 0x6ce2, 0x6d3e, 0x722c, 0x7436, 0x7834, 0x7f77, 0x82ad, 0x8ddb, 0x9817, 0x5224, 0x5742, 0x677f, 0x7248, 0x74e3, 0x8ca9, 0x8fa6, 0x9211, /* 0x78 */ 0x962a, 0x516b, 0x53ed, 0x634c, 0x4f69, 0x5504, 0x6096, 0x6557, 0x6c9b, 0x6d7f, 0x724c, 0x72fd, 0x7a17, 0x8987, 0x8c9d, 0x5f6d, 0x6f8e, 0x70f9, 0x81a8, 0x610e, 0x4fbf, 0x504f, 0x6241, 0x7247, 0x7bc7, 0x7de8, 0x7fe9, 0x904d, 0x97ad, 0x9a19, 0x8cb6, 0x576a, 0x5e73, 0x67b0, 0x840d, 0x8a55, 0x5420, 0x5b16, 0x5e63, 0x5ee2, 0x5f0a, 0x6583, 0x80ba, 0x853d, 0x9589, 0x965b, 0x4f48, 0x5305, 0x530d, 0x530f, 0x5486, 0x54fa, 0x5703, 0x5e03, 0x6016, 0x629b, 0x62b1, 0x6355, 0xfa06, 0x6ce1, 0x6d66, 0x75b1, 0x7832, 0x80de, 0x812f, 0x82de, 0x8461, 0x84b2, 0x888d, 0x8912, 0x900b, 0x92ea, 0x98fd, 0x9b91, 0x5e45, 0x66b4, 0x66dd, 0x7011, 0x7206, 0xfa07, 0x4ff5, 0x527d, 0x5f6a, 0x6153, 0x6753, 0x6a19, 0x6f02, 0x74e2, 0x7968, 0x8868, 0x8c79, 0x98c7, 0x98c4, 0x9a43, /* 0x79 */ 0x54c1, 0x7a1f, 0x6953, 0x8af7, 0x8c4a, 0x98a8, 0x99ae, 0x5f7c, 0x62ab, 0x75b2, 0x76ae, 0x88ab, 0x907f, 0x9642, 0x5339, 0x5f3c, 0x5fc5, 0x6ccc, 0x73cc, 0x7562, 0x758b, 0x7b46, 0x82fe, 0x999d, 0x4e4f, 0x903c, 0x4e0b, 0x4f55, 0x53a6, 0x590f, 0x5ec8, 0x6630, 0x6cb3, 0x7455, 0x8377, 0x8766, 0x8cc0, 0x9050, 0x971e, 0x9c15, 0x58d1, 0x5b78, 0x8650, 0x8b14, 0x9db4, 0x5bd2, 0x6068, 0x608d, 0x65f1, 0x6c57, 0x6f22, 0x6fa3, 0x701a, 0x7f55, 0x7ff0, 0x9591, 0x9592, 0x9650, 0x97d3, 0x5272, 0x8f44, 0x51fd, 0x542b, 0x54b8, 0x5563, 0x558a, 0x6abb, 0x6db5, 0x7dd8, 0x8266, 0x929c, 0x9677, 0x9e79, 0x5408, 0x54c8, 0x76d2, 0x86e4, 0x95a4, 0x95d4, 0x965c, 0x4ea2, 0x4f09, 0x59ee, 0x5ae6, 0x5df7, 0x6052, 0x6297, 0x676d, 0x6841, 0x6c86, 0x6e2f, 0x7f38, 0x809b, 0x822a, /* 0x7a */ 0xfa08, 0xfa09, 0x9805, 0x4ea5, 0x5055, 0x54b3, 0x5793, 0x595a, 0x5b69, 0x5bb3, 0x61c8, 0x6977, 0x6d77, 0x7023, 0x87f9, 0x89e3, 0x8a72, 0x8ae7, 0x9082, 0x99ed, 0x9ab8, 0x52be, 0x6838, 0x5016, 0x5e78, 0x674f, 0x8347, 0x884c, 0x4eab, 0x5411, 0x56ae, 0x73e6, 0x9115, 0x97ff, 0x9909, 0x9957, 0x9999, 0x5653, 0x589f, 0x865b, 0x8a31, 0x61b2, 0x6af6, 0x737b, 0x8ed2, 0x6b47, 0x96aa, 0x9a57, 0x5955, 0x7200, 0x8d6b, 0x9769, 0x4fd4, 0x5cf4, 0x5f26, 0x61f8, 0x665b, 0x6ceb, 0x70ab, 0x7384, 0x73b9, 0x73fe, 0x7729, 0x774d, 0x7d43, 0x7d62, 0x7e23, 0x8237, 0x8852, 0xfa0a, 0x8ce2, 0x9249, 0x986f, 0x5b51, 0x7a74, 0x8840, 0x9801, 0x5acc, 0x4fe0, 0x5354, 0x593e, 0x5cfd, 0x633e, 0x6d79, 0x72f9, 0x8105, 0x8107, 0x83a2, 0x92cf, 0x9830, 0x4ea8, 0x5144, 0x5211, 0x578b, /* 0x7b */ 0x5f62, 0x6cc2, 0x6ece, 0x7005, 0x7050, 0x70af, 0x7192, 0x73e9, 0x7469, 0x834a, 0x87a2, 0x8861, 0x9008, 0x90a2, 0x93a3, 0x99a8, 0x516e, 0x5f57, 0x60e0, 0x6167, 0x66b3, 0x8559, 0x8e4a, 0x91af, 0x978b, 0x4e4e, 0x4e92, 0x547c, 0x58d5, 0x58fa, 0x597d, 0x5cb5, 0x5f27, 0x6236, 0x6248, 0x660a, 0x6667, 0x6beb, 0x6d69, 0x6dcf, 0x6e56, 0x6ef8, 0x6f94, 0x6fe0, 0x6fe9, 0x705d, 0x72d0, 0x7425, 0x745a, 0x74e0, 0x7693, 0x795c, 0x7cca, 0x7e1e, 0x80e1, 0x82a6, 0x846b, 0x84bf, 0x864e, 0x865f, 0x8774, 0x8b77, 0x8c6a, 0x93ac, 0x9800, 0x9865, 0x60d1, 0x6216, 0x9177, 0x5a5a, 0x660f, 0x6df7, 0x6e3e, 0x743f, 0x9b42, 0x5ffd, 0x60da, 0x7b0f, 0x54c4, 0x5f18, 0x6c5e, 0x6cd3, 0x6d2a, 0x70d8, 0x7d05, 0x8679, 0x8a0c, 0x9d3b, 0x5316, 0x548c, 0x5b05, 0x6a3a, 0x706b, 0x7575, /* 0x7c */ 0x798d, 0x79be, 0x82b1, 0x83ef, 0x8a71, 0x8b41, 0x8ca8, 0x9774, 0xfa0b, 0x64f4, 0x652b, 0x78ba, 0x78bb, 0x7a6b, 0x4e38, 0x559a, 0x5950, 0x5ba6, 0x5e7b, 0x60a3, 0x63db, 0x6b61, 0x6665, 0x6853, 0x6e19, 0x7165, 0x74b0, 0x7d08, 0x9084, 0x9a69, 0x9c25, 0x6d3b, 0x6ed1, 0x733e, 0x8c41, 0x95ca, 0x51f0, 0x5e4c, 0x5fa8, 0x604d, 0x60f6, 0x6130, 0x614c, 0x6643, 0x6644, 0x69a5, 0x6cc1, 0x6e5f, 0x6ec9, 0x6f62, 0x714c, 0x749c, 0x7687, 0x7bc1, 0x7c27, 0x8352, 0x8757, 0x9051, 0x968d, 0x9ec3, 0x532f, 0x56de, 0x5efb, 0x5f8a, 0x6062, 0x6094, 0x61f7, 0x6666, 0x6703, 0x6a9c, 0x6dee, 0x6fae, 0x7070, 0x736a, 0x7e6a, 0x81be, 0x8334, 0x86d4, 0x8aa8, 0x8cc4, 0x5283, 0x7372, 0x5b96, 0x6a6b, 0x9404, 0x54ee, 0x5686, 0x5b5d, 0x6548, 0x6585, 0x66c9, 0x689f, 0x6d8d, 0x6dc6, /* 0x7d */ 0x723b, 0x80b4, 0x9175, 0x9a4d, 0x4faf, 0x5019, 0x539a, 0x540e, 0x543c, 0x5589, 0x55c5, 0x5e3f, 0x5f8c, 0x673d, 0x7166, 0x73dd, 0x9005, 0x52db, 0x52f3, 0x5864, 0x58ce, 0x7104, 0x718f, 0x71fb, 0x85b0, 0x8a13, 0x6688, 0x85a8, 0x55a7, 0x6684, 0x714a, 0x8431, 0x5349, 0x5599, 0x6bc1, 0x5f59, 0x5fbd, 0x63ee, 0x6689, 0x7147, 0x8af1, 0x8f1d, 0x9ebe, 0x4f11, 0x643a, 0x70cb, 0x7566, 0x8667, 0x6064, 0x8b4e, 0x9df8, 0x5147, 0x51f6, 0x5308, 0x6d36, 0x80f8, 0x9ed1, 0x6615, 0x6b23, 0x7098, 0x75d5, 0x5403, 0x5c79, 0x7d07, 0x8a16, 0x6b20, 0x6b3d, 0x6b46, 0x5438, 0x6070, 0x6d3d, 0x7fd5, 0x8208, 0x50d6, 0x51de, 0x559c, 0x566b, 0x56cd, 0x59ec, 0x5b09, 0x5e0c, 0x6199, 0x6198, 0x6231, 0x665e, 0x66e6, 0x7199, 0x71b9, 0x71ba, 0x72a7, 0x79a7, 0x7a00, 0x7fb2, 0x8a70, }; static int ksc5601_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c1 = (s[0] & 0x7F); if ((c1 >= 0x21 && c1 <= 0x2c) || (c1 >= 0x30 && c1 <= 0x48) || (c1 >= 0x4a && c1 <= 0x7d)) { if (n >= 2) { unsigned char c2 = (s[1] & 0x7F); if (c2 >= 0x21 && c2 < 0x7f) { unsigned int i = 94 * (c1 - 0x21) + (c2 - 0x21); unsigned short wc = 0xfffd; if (i < 1410) { if (i < 1115) wc = ksc5601_2uni_page21[i]; } else if (i < 3854) { if (i < 3760) wc = ksc5601_2uni_page30[i-1410]; } else { if (i < 8742) wc = ksc5601_2uni_page4a[i-3854]; } if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 2; } } return RET_ILSEQ; } return RET_TOOFEW(0); } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned short ksc5601_2charset[8224] = { 0x222e, 0x2234, 0x2157, 0x2127, 0x2823, 0x2129, 0x2146, 0x213e, 0x2977, 0x2978, 0x2225, 0x2252, 0x2124, 0x222c, 0x2976, 0x282c, 0x2879, 0x2876, 0x287a, 0x222f, 0x2821, 0x2822, 0x213f, 0x282a, 0x282d, 0x292c, 0x2921, 0x2923, 0x2140, 0x292a, 0x292d, 0x2922, 0x2824, 0x2924, 0x2925, 0x2826, 0x2926, 0x2927, 0x2828, 0x2928, 0x2829, 0x2929, 0x2930, 0x282f, 0x292f, 0x282b, 0x292b, 0x282e, 0x292e, 0x2227, 0x2230, 0x2228, 0x222b, 0x222a, 0x222d, 0x2229, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d, 0x254e, 0x254f, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, 0x2558, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x256d, 0x256e, 0x256f, 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0x2577, 0x2578, 0x2c27, 0x2c21, 0x2c22, 0x2c23, 0x2c24, 0x2c25, 0x2c26, 0x2c28, 0x2c29, 0x2c2a, 0x2c2b, 0x2c2c, 0x2c2d, 0x2c2e, 0x2c2f, 0x2c30, 0x2c31, 0x2c32, 0x2c33, 0x2c34, 0x2c35, 0x2c36, 0x2c37, 0x2c38, 0x2c39, 0x2c3a, 0x2c3b, 0x2c3c, 0x2c3d, 0x2c3e, 0x2c3f, 0x2c40, 0x2c41, 0x2c51, 0x2c52, 0x2c53, 0x2c54, 0x2c55, 0x2c56, 0x2c58, 0x2c59, 0x2c5a, 0x2c5b, 0x2c5c, 0x2c5d, 0x2c5e, 0x2c5f, 0x2c60, 0x2c61, 0x2c62, 0x2c63, 0x2c64, 0x2c65, 0x2c66, 0x2c67, 0x2c68, 0x2c69, 0x2c6a, 0x2c6b, 0x2c6c, 0x2c6d, 0x2c6e, 0x2c6f, 0x2c70, 0x2c71, 0x2c57, 0x212a, 0x212e, 0x212f, 0x2130, 0x2131, 0x2253, 0x2254, 0x2125, 0x2126, 0x2236, 0x2147, 0x2148, 0x2158, 0x2979, 0x297a, 0x297b, 0x297c, 0x297d, 0x297e, 0x2149, 0x2235, 0x2724, 0x2260, 0x2265, 0x2262, 0x2759, 0x214a, 0x2877, 0x2878, 0x287b, 0x287c, 0x287d, 0x287e, 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, 0x2538, 0x2539, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, 0x2528, 0x2529, 0x252a, 0x2167, 0x2168, 0x2166, 0x2169, 0x216a, 0x2255, 0x2258, 0x2256, 0x2259, 0x2257, 0x2221, 0x2222, 0x2223, 0x2153, 0x2224, 0x2154, 0x2174, 0x2175, 0x2233, 0x2232, 0x216e, 0x2170, 0x2144, 0x2150, 0x212b, 0x217c, 0x217d, 0x217b, 0x217a, 0x2172, 0x2173, 0x2231, 0x2145, 0x2171, 0x212d, 0x216f, 0x2156, 0x2141, 0x2155, 0x2142, 0x2143, 0x216c, 0x216d, 0x2178, 0x2179, 0x2176, 0x2177, 0x2241, 0x2151, 0x2152, 0x2867, 0x2868, 0x2869, 0x286a, 0x286b, 0x286c, 0x286d, 0x286e, 0x286f, 0x2870, 0x2871, 0x2872, 0x2873, 0x2874, 0x2875, 0x2967, 0x2968, 0x2969, 0x296a, 0x296b, 0x296c, 0x296d, 0x296e, 0x296f, 0x2970, 0x2971, 0x2972, 0x2973, 0x2974, 0x2975, 0x294d, 0x294e, 0x294f, 0x2950, 0x2951, 0x2952, 0x2953, 0x2954, 0x2955, 0x2956, 0x2957, 0x2958, 0x2959, 0x295a, 0x295b, 0x295c, 0x295d, 0x295e, 0x295f, 0x2960, 0x2961, 0x2962, 0x2963, 0x2964, 0x2965, 0x2966, 0x284d, 0x284e, 0x284f, 0x2850, 0x2851, 0x2852, 0x2853, 0x2854, 0x2855, 0x2856, 0x2857, 0x2858, 0x2859, 0x285a, 0x285b, 0x285c, 0x285d, 0x285e, 0x285f, 0x2860, 0x2861, 0x2862, 0x2863, 0x2864, 0x2865, 0x2866, 0x2621, 0x262c, 0x2622, 0x262d, 0x2623, 0x2648, 0x2647, 0x262e, 0x2624, 0x2642, 0x2641, 0x262f, 0x2626, 0x2646, 0x2645, 0x2631, 0x2625, 0x2644, 0x2643, 0x2630, 0x2627, 0x263c, 0x2649, 0x264a, 0x2637, 0x264b, 0x264c, 0x2632, 0x2629, 0x263e, 0x264d, 0x264e, 0x2639, 0x264f, 0x2650, 0x2634, 0x2628, 0x2651, 0x2652, 0x2638, 0x263d, 0x2653, 0x2654, 0x2633, 0x262a, 0x2655, 0x2656, 0x263a, 0x263f, 0x2657, 0x2658, 0x2635, 0x262b, 0x2659, 0x265a, 0x263b, 0x265b, 0x265c, 0x2640, 0x265d, 0x265e, 0x265f, 0x2660, 0x2661, 0x2662, 0x2663, 0x2664, 0x2636, 0x2246, 0x2161, 0x2160, 0x2243, 0x2247, 0x2248, 0x224b, 0x224a, 0x2249, 0x224c, 0x2163, 0x2162, 0x223a, 0x2239, 0x2165, 0x2164, 0x2238, 0x2237, 0x215f, 0x215e, 0x2242, 0x215b, 0x215d, 0x215c, 0x2244, 0x2245, 0x215a, 0x2159, 0x224f, 0x224e, 0x2250, 0x2251, 0x214f, 0x214e, 0x223c, 0x223d, 0x2240, 0x223b, 0x223e, 0x223f, 0x224d, 0x225b, 0x225c, 0x225d, 0x225a, 0x2121, 0x2122, 0x2123, 0x2128, 0x2134, 0x2135, 0x2136, 0x2137, 0x2138, 0x2139, 0x213a, 0x213b, 0x213c, 0x213d, 0x216b, 0x2132, 0x2133, 0x2a21, 0x2a22, 0x2a23, 0x2a24, 0x2a25, 0x2a26, 0x2a27, 0x2a28, 0x2a29, 0x2a2a, 0x2a2b, 0x2a2c, 0x2a2d, 0x2a2e, 0x2a2f, 0x2a30, 0x2a31, 0x2a32, 0x2a33, 0x2a34, 0x2a35, 0x2a36, 0x2a37, 0x2a38, 0x2a39, 0x2a3a, 0x2a3b, 0x2a3c, 0x2a3d, 0x2a3e, 0x2a3f, 0x2a40, 0x2a41, 0x2a42, 0x2a43, 0x2a44, 0x2a45, 0x2a46, 0x2a47, 0x2a48, 0x2a49, 0x2a4a, 0x2a4b, 0x2a4c, 0x2a4d, 0x2a4e, 0x2a4f, 0x2a50, 0x2a51, 0x2a52, 0x2a53, 0x2a54, 0x2a55, 0x2a56, 0x2a57, 0x2a58, 0x2a59, 0x2a5a, 0x2a5b, 0x2a5c, 0x2a5d, 0x2a5e, 0x2a5f, 0x2a60, 0x2a61, 0x2a62, 0x2a63, 0x2a64, 0x2a65, 0x2a66, 0x2a67, 0x2a68, 0x2a69, 0x2a6a, 0x2a6b, 0x2a6c, 0x2a6d, 0x2a6e, 0x2a6f, 0x2a70, 0x2a71, 0x2a72, 0x2a73, 0x2b21, 0x2b22, 0x2b23, 0x2b24, 0x2b25, 0x2b26, 0x2b27, 0x2b28, 0x2b29, 0x2b2a, 0x2b2b, 0x2b2c, 0x2b2d, 0x2b2e, 0x2b2f, 0x2b30, 0x2b31, 0x2b32, 0x2b33, 0x2b34, 0x2b35, 0x2b36, 0x2b37, 0x2b38, 0x2b39, 0x2b3a, 0x2b3b, 0x2b3c, 0x2b3d, 0x2b3e, 0x2b3f, 0x2b40, 0x2b41, 0x2b42, 0x2b43, 0x2b44, 0x2b45, 0x2b46, 0x2b47, 0x2b48, 0x2b49, 0x2b4a, 0x2b4b, 0x2b4c, 0x2b4d, 0x2b4e, 0x2b4f, 0x2b50, 0x2b51, 0x2b52, 0x2b53, 0x2b54, 0x2b55, 0x2b56, 0x2b57, 0x2b58, 0x2b59, 0x2b5a, 0x2b5b, 0x2b5c, 0x2b5d, 0x2b5e, 0x2b5f, 0x2b60, 0x2b61, 0x2b62, 0x2b63, 0x2b64, 0x2b65, 0x2b66, 0x2b67, 0x2b68, 0x2b69, 0x2b6a, 0x2b6b, 0x2b6c, 0x2b6d, 0x2b6e, 0x2b6f, 0x2b70, 0x2b71, 0x2b72, 0x2b73, 0x2b74, 0x2b75, 0x2b76, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427, 0x2428, 0x2429, 0x242a, 0x242b, 0x242c, 0x242d, 0x242e, 0x242f, 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, 0x2438, 0x2439, 0x243a, 0x243b, 0x243c, 0x243d, 0x243e, 0x243f, 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, 0x2448, 0x2449, 0x244a, 0x244b, 0x244c, 0x244d, 0x244e, 0x244f, 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, 0x2458, 0x2459, 0x245a, 0x245b, 0x245c, 0x245d, 0x245e, 0x245f, 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x246f, 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 0x247a, 0x247b, 0x247c, 0x247d, 0x247e, 0x2931, 0x2932, 0x2933, 0x2934, 0x2935, 0x2936, 0x2937, 0x2938, 0x2939, 0x293a, 0x293b, 0x293c, 0x293d, 0x293e, 0x293f, 0x2940, 0x2941, 0x2942, 0x2943, 0x2944, 0x2945, 0x2946, 0x2947, 0x2948, 0x2949, 0x294a, 0x294b, 0x294c, 0x225f, 0x2831, 0x2832, 0x2833, 0x2834, 0x2835, 0x2836, 0x2837, 0x2838, 0x2839, 0x283a, 0x283b, 0x283c, 0x283d, 0x283e, 0x283f, 0x2840, 0x2841, 0x2842, 0x2843, 0x2844, 0x2845, 0x2846, 0x2847, 0x2848, 0x2849, 0x284a, 0x284b, 0x284c, 0x225e, 0x2749, 0x274a, 0x274b, 0x274c, 0x274d, 0x273a, 0x273b, 0x275c, 0x275d, 0x275e, 0x2736, 0x2737, 0x2738, 0x2754, 0x2755, 0x2756, 0x2757, 0x2758, 0x2721, 0x2722, 0x2723, 0x2725, 0x272b, 0x272c, 0x272d, 0x272e, 0x272f, 0x2730, 0x2731, 0x2732, 0x2733, 0x2734, 0x2727, 0x2728, 0x2729, 0x272a, 0x273d, 0x273e, 0x2765, 0x2766, 0x2767, 0x2768, 0x2761, 0x2762, 0x2763, 0x273f, 0x2740, 0x2741, 0x2742, 0x2743, 0x2744, 0x2745, 0x2746, 0x2747, 0x2748, 0x274e, 0x274f, 0x2750, 0x2751, 0x2752, 0x2753, 0x275a, 0x275b, 0x2263, 0x276c, 0x2726, 0x2760, 0x276f, 0x2261, 0x273c, 0x276d, 0x2735, 0x2739, 0x276a, 0x276b, 0x275f, 0x2264, 0x2764, 0x276e, 0x2769, 0x6c69, 0x6f4b, 0x7652, 0x5832, 0x6d5b, 0x5f32, 0x5f3e, 0x793b, 0x5c74, 0x7564, 0x7326, 0x5d60, 0x6126, 0x4e78, 0x5c30, 0x632a, 0x7169, 0x4d7a, 0x7c2f, 0x5321, 0x712b, 0x6751, 0x522c, 0x4e79, 0x717d, 0x5e3f, 0x7b3a, 0x7939, 0x4e52, 0x632b, 0x6b60, 0x4e7a, 0x4b77, 0x6525, 0x4a61, 0x544c, 0x6a61, 0x5c63, 0x5f2d, 0x4b6b, 0x552f, 0x5675, 0x6578, 0x5e40, 0x6c23, 0x694d, 0x6a27, 0x6976, 0x7b3b, 0x6769, 0x6f4c, 0x5066, 0x5e41, 0x642c, 0x584c, 0x7971, 0x4e5f, 0x7a24, 0x6632, 0x7a7b, 0x7a3d, 0x4c48, 0x6f4d, 0x5555, 0x5322, 0x6c51, 0x6427, 0x6c52, 0x7631, 0x4e7b, 0x5051, 0x4b3f, 0x6d24, 0x6d28, 0x5e42, 0x7662, 0x6d5c, 0x5c75, 0x6039, 0x544e, 0x7435, 0x535b, 0x5635, 0x6c24, 0x6466, 0x716a, 0x4b6c, 0x4b40, 0x6c72, 0x506a, 0x7972, 0x6c25, 0x505f, 0x676a, 0x506b, 0x5c51, 0x5b69, 0x7d4c, 0x5b57, 0x5a61, 0x5636, 0x635f, 0x5e43, 0x5e44, 0x4a21, 0x6e6c, 0x5323, 0x6e37, 0x784f, 0x6a48, 0x6e38, 0x712c, 0x7125, 0x694e, 0x793c, 0x6579, 0x6c6a, 0x5d56, 0x6d42, 0x7825, 0x653a, 0x5b58, 0x4a22, 0x514d, 0x6e6d, 0x6c6b, 0x5e45, 0x6360, 0x4a49, 0x7269, 0x554e, 0x7636, 0x4e42, 0x5647, 0x6334, 0x712d, 0x6a62, 0x5742, 0x7327, 0x4d6a, 0x6b6e, 0x5932, 0x7d25, 0x7655, 0x5562, 0x7835, 0x4c75, 0x7535, 0x642d, 0x676b, 0x7155, 0x703b, 0x6935, 0x4c49, 0x7a55, 0x6154, 0x5756, 0x5c41, 0x5e46, 0x7a6f, 0x6361, 0x6173, 0x5c76, 0x4e7c, 0x5b44, 0x7871, 0x5c64, 0x656f, 0x5c31, 0x5556, 0x735a, 0x4b41, 0x5b43, 0x597a, 0x536e, 0x7a38, 0x7d26, 0x6b6f, 0x7426, 0x4c4a, 0x7328, 0x735b, 0x5b27, 0x7637, 0x4f66, 0x7072, 0x4b5a, 0x6752, 0x5743, 0x7670, 0x685e, 0x6526, 0x6567, 0x4a23, 0x4c27, 0x6a49, 0x7836, 0x7a25, 0x712e, 0x6f4e, 0x4b6d, 0x7630, 0x6f4f, 0x694f, 0x775e, 0x4e53, 0x5c77, 0x5b28, 0x4b78, 0x5f21, 0x5d61, 0x754a, 0x6936, 0x676c, 0x6e6e, 0x7370, 0x5f3f, 0x4c4b, 0x5041, 0x7452, 0x603a, 0x5f40, 0x4e60, 0x5c52, 0x7d6a, 0x5676, 0x6a4a, 0x6869, 0x632c, 0x7350, 0x4a24, 0x5b78, 0x5e47, 0x6b70, 0x7156, 0x6562, 0x4c4c, 0x4b7b, 0x6a63, 0x5f41, 0x566d, 0x6950, 0x6e39, 0x5563, 0x5153, 0x6570, 0x6834, 0x6b43, 0x6a2a, 0x7a7c, 0x7576, 0x703c, 0x7d54, 0x603b, 0x4e43, 0x503a, 0x773a, 0x5873, 0x774d, 0x642e, 0x545f, 0x5067, 0x6c7d, 0x522e, 0x6e6f, 0x5557, 0x6a64, 0x7822, 0x4d6b, 0x573f, 0x7b31, 0x4d6c, 0x5c32, 0x506c, 0x4e7d, 0x6e70, 0x4c42, 0x506d, 0x6577, 0x737c, 0x6e22, 0x5933, 0x5874, 0x6937, 0x4e2e, 0x5922, 0x5871, 0x544f, 0x6527, 0x5552, 0x5629, 0x7422, 0x7157, 0x5558, 0x703d, 0x5750, 0x5450, 0x574f, 0x6b6a, 0x7d6b, 0x5b6d, 0x7c45, 0x4b42, 0x7d55, 0x7448, 0x686a, 0x7573, 0x795e, 0x536f, 0x6c53, 0x5d42, 0x6f37, 0x6754, 0x4a4a, 0x597b, 0x7a7d, 0x562a, 0x7478, 0x7777, 0x5c2c, 0x5757, 0x5f22, 0x4e3e, 0x5370, 0x7024, 0x616c, 0x4f67, 0x734b, 0x6d29, 0x4a3e, 0x746f, 0x764e, 0x5e7b, 0x503b, 0x5537, 0x6e71, 0x7428, 0x5c78, 0x4b27, 0x5a4e, 0x6066, 0x6d25, 0x6e72, 0x5c79, 0x795c, 0x735c, 0x7872, 0x7479, 0x7c71, 0x503c, 0x5b79, 0x5731, 0x4b7c, 0x7025, 0x4b7d, 0x5574, 0x4d6d, 0x4a25, 0x562b, 0x5042, 0x703e, 0x523d, 0x4c24, 0x7a36, 0x4c4d, 0x5a7a, 0x764f, 0x6938, 0x5875, 0x4c4e, 0x574d, 0x5451, 0x696d, 0x4a6b, 0x5962, 0x7d32, 0x632d, 0x564c, 0x5934, 0x6127, 0x6e53, 0x5043, 0x7d33, 0x5564, 0x4f68, 0x6d43, 0x5032, 0x4e7e, 0x5a28, 0x7850, 0x7d56, 0x7851, 0x7852, 0x5c53, 0x5d62, 0x7b79, 0x5d41, 0x6335, 0x6d5d, 0x4e44, 0x4b21, 0x5d63, 0x7c5d, 0x792f, 0x527b, 0x4f21, 0x6428, 0x7436, 0x6c7e, 0x632e, 0x676d, 0x7d41, 0x5a62, 0x5833, 0x5d64, 0x706f, 0x7671, 0x7a70, 0x5175, 0x5a4f, 0x5c54, 0x5c26, 0x6f3f, 0x4e4f, 0x6059, 0x5956, 0x6c54, 0x6a4b, 0x4a3f, 0x5530, 0x4f69, 0x716d, 0x4c4f, 0x6478, 0x646d, 0x5758, 0x7d27, 0x6a2b, 0x7632, 0x4f70, 0x793d, 0x6674, 0x4b5b, 0x7351, 0x6951, 0x7329, 0x5060, 0x6952, 0x5a63, 0x6252, 0x7622, 0x6174, 0x5a64, 0x6755, 0x753f, 0x4f22, 0x4d2f, 0x4f23, 0x4d30, 0x717e, 0x5023, 0x612f, 0x7823, 0x4a26, 0x773b, 0x726a, 0x5e48, 0x6953, 0x5e49, 0x7d5e, 0x4a40, 0x796a, 0x514e, 0x6e54, 0x5452, 0x5923, 0x7d28, 0x5759, 0x774e, 0x7a3e, 0x4f56, 0x5770, 0x6b61, 0x7845, 0x5c7a, 0x5d43, 0x795f, 0x676f, 0x7d65, 0x7623, 0x597c, 0x7d29, 0x676e, 0x5565, 0x6f50, 0x4d31, 0x7722, 0x7132, 0x7131, 0x4d32, 0x5a2b, 0x4a27, 0x6362, 0x7b3c, 0x5924, 0x6e3a, 0x7853, 0x7b7a, 0x4f24, 0x5c7b, 0x7663, 0x6d2a, 0x7221, 0x4e61, 0x7a26, 0x7960, 0x6c56, 0x646e, 0x7921, 0x7b6f, 0x796b, 0x6e23, 0x6a2c, 0x4a28, 0x747a, 0x4d56, 0x7c76, 0x7449, 0x7854, 0x7826, 0x5e4a, 0x7246, 0x575a, 0x5350, 0x5845, 0x6a66, 0x735d, 0x645a, 0x7664, 0x7672, 0x5f42, 0x597d, 0x4c76, 0x533a, 0x642f, 0x7961, 0x7026, 0x4b53, 0x603c, 0x744a, 0x547a, 0x7d2a, 0x7962, 0x7437, 0x7d42, 0x7c30, 0x7d6c, 0x4a62, 0x7d3d, 0x6a67, 0x5f43, 0x5152, 0x4e62, 0x5324, 0x7d2b, 0x5f60, 0x7247, 0x6770, 0x506e, 0x732a, 0x5e4b, 0x7638, 0x6175, 0x7133, 0x7723, 0x4a29, 0x4f25, 0x5f44, 0x6130, 0x703f, 0x7624, 0x6336, 0x7a46, 0x506f, 0x7d6d, 0x5d44, 0x7c77, 0x663f, 0x5e2d, 0x7a3f, 0x6571, 0x6d44, 0x5225, 0x7d6e, 0x7536, 0x6176, 0x5e4c, 0x7c5e, 0x6c57, 0x4d5d, 0x5637, 0x4d33, 0x7855, 0x6558, 0x4f6a, 0x4f50, 0x6a4c, 0x6a2e, 0x6a2d, 0x5371, 0x5325, 0x774f, 0x6e24, 0x5024, 0x7222, 0x5070, 0x7223, 0x7778, 0x5033, 0x5b29, 0x533b, 0x4a6c, 0x7126, 0x4b55, 0x7767, 0x4d5e, 0x7724, 0x7840, 0x535d, 0x4c50, 0x4f26, 0x7673, 0x6177, 0x535c, 0x7a7e, 0x7a27, 0x6b59, 0x4f27, 0x6a2f, 0x646f, 0x6939, 0x7158, 0x5858, 0x6072, 0x6634, 0x5c7c, 0x7371, 0x6350, 0x727b, 0x5b46, 0x5071, 0x5072, 0x4f5c, 0x5351, 0x4c31, 0x7758, 0x4b28, 0x6b3c, 0x643e, 0x745c, 0x5c42, 0x7027, 0x6640, 0x4a6d, 0x686b, 0x6568, 0x5c43, 0x6d5e, 0x5372, 0x4c77, 0x4e54, 0x672b, 0x4b43, 0x6131, 0x7732, 0x5373, 0x5352, 0x7540, 0x5f5d, 0x6e73, 0x6771, 0x7d34, 0x7248, 0x7352, 0x6e74, 0x6253, 0x4c51, 0x5f6a, 0x693a, 0x5957, 0x754d, 0x7172, 0x7a47, 0x5978, 0x5442, 0x7665, 0x5d45, 0x6772, 0x6d5f, 0x4a4b, 0x5b7a, 0x6835, 0x5326, 0x7d35, 0x7949, 0x6462, 0x7b3d, 0x5724, 0x4e45, 0x4e55, 0x5666, 0x653d, 0x5e4d, 0x6c73, 0x6d60, 0x6c6c, 0x7b3e, 0x5f6b, 0x6178, 0x793e, 0x5073, 0x602a, 0x6862, 0x6254, 0x527d, 0x6528, 0x5953, 0x535e, 0x7438, 0x773c, 0x5c7d, 0x686c, 0x6467, 0x6377, 0x6c28, 0x7a71, 0x6572, 0x5074, 0x522f, 0x5c65, 0x5025, 0x7134, 0x7c31, 0x4c78, 0x5d46, 0x7a51, 0x775f, 0x7a28, 0x6e75, 0x5e4e, 0x6773, 0x772c, 0x6b44, 0x6d61, 0x602b, 0x5d47, 0x5233, 0x523f, 0x4a4c, 0x7b3f, 0x657d, 0x5d65, 0x584d, 0x6c74, 0x5075, 0x686d, 0x5052, 0x5958, 0x7666, 0x5b2a, 0x7760, 0x5859, 0x7423, 0x745d, 0x6f51, 0x5935, 0x6d2b, 0x6337, 0x6e3b, 0x4d34, 0x6073, 0x6a4d, 0x6c75, 0x686e, 0x4b29, 0x712f, 0x4a4d, 0x6c29, 0x726b, 0x7d6f, 0x7973, 0x6641, 0x6c58, 0x6d2c, 0x6a4e, 0x685f, 0x5e4f, 0x5226, 0x6774, 0x5156, 0x6642, 0x6363, 0x6430, 0x5834, 0x7625, 0x735e, 0x5725, 0x7768, 0x6846, 0x7b66, 0x5d66, 0x5c7e, 0x585a, 0x5a2c, 0x6a30, 0x6338, 0x4a2a, 0x6179, 0x6a31, 0x726c, 0x7a6e, 0x6e55, 0x7974, 0x526c, 0x7b7b, 0x7d70, 0x603d, 0x4e63, 0x7846, 0x5e2e, 0x5f45, 0x653e, 0x6d2d, 0x7a6a, 0x4d6e, 0x6d26, 0x6d2e, 0x706d, 0x5d21, 0x6d2f, 0x7c78, 0x586b, 0x4c79, 0x4d35, 0x7a29, 0x615d, 0x6255, 0x6d4f, 0x5d22, 0x794a, 0x6a68, 0x656d, 0x536b, 0x6954, 0x617a, 0x644c, 0x6164, 0x6847, 0x4e5b, 0x5c55, 0x7735, 0x7c73, 0x7073, 0x4e2f, 0x7135, 0x6f52, 0x6848, 0x6b71, 0x4b54, 0x603e, 0x6378, 0x6a69, 0x7c32, 0x6074, 0x4f60, 0x6e25, 0x7a2a, 0x6643, 0x6132, 0x4a2b, 0x6364, 0x693b, 0x6256, 0x7372, 0x6e56, 0x6a32, 0x5076, 0x6c59, 0x5a4b, 0x4f28, 0x5d23, 0x585b, 0x794e, 0x6955, 0x6351, 0x523c, 0x582c, 0x734c, 0x4d7b, 0x7656, 0x6775, 0x686f, 0x6379, 0x523b, 0x7373, 0x637b, 0x5e50, 0x4e30, 0x5677, 0x7159, 0x7541, 0x5c44, 0x753b, 0x5e51, 0x5c66, 0x5e52, 0x6d62, 0x6e76, 0x6a4f, 0x706e, 0x637c, 0x535f, 0x5374, 0x6133, 0x6134, 0x7453, 0x5f46, 0x6956, 0x5b2b, 0x7626, 0x6339, 0x6b45, 0x7429, 0x4d36, 0x5279, 0x5a2d, 0x5263, 0x4f51, 0x4b5c, 0x4c7a, 0x4f5d, 0x6829, 0x633b, 0x633a, 0x605a, 0x6e77, 0x5c33, 0x5375, 0x5726, 0x7635, 0x575b, 0x6155, 0x546a, 0x5f23, 0x7d5f, 0x5077, 0x6d54, 0x4b2a, 0x645b, 0x617b, 0x4b22, 0x5360, 0x643f, 0x7b40, 0x5a3e, 0x644d, 0x5639, 0x6f40, 0x617c, 0x7639, 0x5f47, 0x6431, 0x5c67, 0x5c68, 0x7a56, 0x5376, 0x715a, 0x7a72, 0x627d, 0x554f, 0x5078, 0x4d5f, 0x754b, 0x6470, 0x4b2b, 0x5744, 0x627e, 0x5d5a, 0x5a2e, 0x4a6e, 0x5539, 0x6321, 0x6863, 0x732b, 0x4f29, 0x5377, 0x5471, 0x4e64, 0x6872, 0x6575, 0x672e, 0x563a, 0x5f6c, 0x6440, 0x6864, 0x5835, 0x645c, 0x7439, 0x7136, 0x625e, 0x6135, 0x4d6f, 0x7127, 0x4e65, 0x4b5d, 0x5963, 0x732c, 0x5079, 0x6c2b, 0x5e53, 0x7769, 0x7975, 0x615e, 0x4b6e, 0x633c, 0x7856, 0x5b6e, 0x7d71, 0x7736, 0x745e, 0x726d, 0x5b59, 0x7028, 0x617d, 0x5e54, 0x602c, 0x6d63, 0x5361, 0x5f48, 0x5936, 0x7d2c, 0x6f53, 0x6441, 0x786b, 0x5b2c, 0x7c46, 0x582d, 0x763a, 0x5b5f, 0x5353, 0x7847, 0x4a4e, 0x7841, 0x5234, 0x5c34, 0x7a39, 0x4a4f, 0x7c33, 0x6a6a, 0x6a6b, 0x507a, 0x6d64, 0x5d67, 0x5f49, 0x5f6d, 0x6e3c, 0x6f41, 0x4c52, 0x5d24, 0x5f4a, 0x5378, 0x7128, 0x4d37, 0x6f54, 0x645d, 0x5f6e, 0x4b2c, 0x693c, 0x6a6c, 0x5f4b, 0x793f, 0x562f, 0x5546, 0x4f2a, 0x4e29, 0x5678, 0x7137, 0x6e78, 0x5959, 0x735f, 0x7848, 0x4e46, 0x5566, 0x7466, 0x6645, 0x6f55, 0x4b6f, 0x7c5f, 0x5c27, 0x5667, 0x7849, 0x6352, 0x633d, 0x4f61, 0x7040, 0x6c5a, 0x5d57, 0x7b70, 0x6c2c, 0x7029, 0x7a57, 0x7b41, 0x5240, 0x6530, 0x6d65, 0x4b2d, 0x7930, 0x7725, 0x4b2e, 0x5a2f, 0x5836, 0x5327, 0x7b32, 0x7d44, 0x6c2d, 0x7b21, 0x6569, 0x696e, 0x7374, 0x7873, 0x7041, 0x5e2f, 0x7830, 0x7360, 0x672f, 0x5b2d, 0x6635, 0x7928, 0x5d58, 0x6859, 0x6f56, 0x5362, 0x625f, 0x7c60, 0x5748, 0x7d2d, 0x5f6f, 0x4c53, 0x5379, 0x5470, 0x5b47, 0x5e55, 0x7074, 0x5550, 0x6559, 0x7c47, 0x5c56, 0x6260, 0x5a30, 0x7323, 0x536c, 0x744b, 0x7d45, 0x637d, 0x7931, 0x507b, 0x6c5b, 0x753c, 0x7224, 0x584e, 0x584f, 0x7577, 0x7661, 0x5237, 0x7b6c, 0x5d48, 0x6468, 0x5241, 0x7857, 0x563b, 0x5e56, 0x773d, 0x6c2e, 0x5061, 0x6075, 0x6a33, 0x4e56, 0x4c25, 0x6c76, 0x6261, 0x633e, 0x7c48, 0x4d70, 0x7976, 0x5f70, 0x653f, 0x4e3f, 0x7c61, 0x6d30, 0x7d51, 0x763b, 0x794f, 0x6b5a, 0x4a41, 0x5238, 0x4d71, 0x6353, 0x7d66, 0x666d, 0x637a, 0x702a, 0x7950, 0x7c62, 0x7827, 0x6165, 0x6e79, 0x6776, 0x6a6d, 0x7c34, 0x7542, 0x575c, 0x7075, 0x5d68, 0x536d, 0x757c, 0x5a3f, 0x4c7b, 0x537a, 0x7424, 0x6f57, 0x5443, 0x7b63, 0x7b6d, 0x602d, 0x6a6e, 0x7b33, 0x6442, 0x7667, 0x525d, 0x5f4c, 0x7c49, 0x6529, 0x6076, 0x7633, 0x617e, 0x4b70, 0x6a6f, 0x6a70, 0x5a40, 0x7834, 0x6b72, 0x6443, 0x6957, 0x6471, 0x4a6f, 0x4e57, 0x7c4a, 0x7361, 0x4b44, 0x6365, 0x4b45, 0x6a34, 0x693d, 0x5749, 0x6b5b, 0x6d31, 0x4c43, 0x773e, 0x7c4b, 0x7874, 0x5937, 0x7353, 0x7354, 0x7764, 0x7751, 0x5837, 0x4e31, 0x4a42, 0x7b34, 0x4b46, 0x7076, 0x5567, 0x6a50, 0x4c54, 0x4b2f, 0x742a, 0x692f, 0x7543, 0x6958, 0x5d69, 0x7173, 0x557b, 0x5e3b, 0x747b, 0x7d73, 0x7d72, 0x7726, 0x5d49, 0x5453, 0x4c28, 0x5a41, 0x4c55, 0x5964, 0x7a4a, 0x6563, 0x533c, 0x4a70, 0x5044, 0x4a50, 0x7a2b, 0x6b6b, 0x6778, 0x5965, 0x5157, 0x7324, 0x547b, 0x7c63, 0x7a58, 0x7355, 0x4f2b, 0x6b73, 0x557c, 0x5354, 0x4d7c, 0x5966, 0x6279, 0x6221, 0x6b54, 0x6077, 0x6432, 0x4c7c, 0x7b64, 0x742b, 0x503d, 0x4a71, 0x6f38, 0x5740, 0x6e7a, 0x7d74, 0x5363, 0x7b42, 0x5568, 0x5b2e, 0x6136, 0x7837, 0x603f, 0x7b43, 0x5d6a, 0x6222, 0x6e26, 0x7668, 0x7675, 0x5d4a, 0x5062, 0x5d26, 0x5d6b, 0x6479, 0x632f, 0x507c, 0x747c, 0x4c3c, 0x776a, 0x6564, 0x5f71, 0x7761, 0x7977, 0x6f39, 0x7858, 0x7929, 0x7859, 0x6e3d, 0x5846, 0x6463, 0x754e, 0x5d59, 0x5967, 0x5239, 0x5543, 0x5a65, 0x5a50, 0x5159, 0x4e58, 0x4b5e, 0x742c, 0x5a7b, 0x7669, 0x6873, 0x4f2c, 0x7070, 0x747d, 0x5b48, 0x4e40, 0x6354, 0x514f, 0x7175, 0x4d72, 0x4f6b, 0x4d38, 0x6326, 0x515a, 0x7225, 0x7226, 0x644e, 0x537b, 0x7129, 0x7249, 0x6f58, 0x6649, 0x5838, 0x7a73, 0x7335, 0x7824, 0x5173, 0x6648, 0x785a, 0x5c69, 0x5e57, 0x4b5f, 0x4f6c, 0x745f, 0x5174, 0x523a, 0x5f72, 0x6137, 0x6223, 0x537c, 0x6d66, 0x5b49, 0x647a, 0x4f5e, 0x4e50, 0x5553, 0x7375, 0x772e, 0x6f48, 0x4d73, 0x754f, 0x6573, 0x7042, 0x4a51, 0x6a71, 0x5026, 0x595a, 0x702b, 0x6b67, 0x6540, 0x7c35, 0x6444, 0x4c29, 0x7d46, 0x6a35, 0x652a, 0x5f3a, 0x615f, 0x5a51, 0x6138, 0x6874, 0x537d, 0x6224, 0x724a, 0x5a66, 0x7733, 0x7d4d, 0x7336, 0x6e57, 0x7544, 0x5824, 0x7227, 0x5938, 0x5939, 0x6f49, 0x564e, 0x774b, 0x5f2e, 0x6875, 0x5235, 0x5355, 0x744c, 0x5a7c, 0x5968, 0x776b, 0x7549, 0x733c, 0x5a52, 0x5335, 0x6836, 0x564f, 0x743a, 0x7749, 0x4c2a, 0x7043, 0x4c56, 0x5053, 0x533d, 0x5b7b, 0x4b60, 0x5364, 0x7677, 0x553a, 0x734d, 0x4b61, 0x6b74, 0x742d, 0x7c2a, 0x776c, 0x6876, 0x5a67, 0x774c, 0x6541, 0x606e, 0x557d, 0x4e66, 0x7c2b, 0x553b, 0x7228, 0x6225, 0x4d39, 0x6a72, 0x4b47, 0x4d74, 0x5b2f, 0x6f59, 0x4d3a, 0x7c79, 0x5f73, 0x4e67, 0x5a42, 0x4f2d, 0x6779, 0x7828, 0x7362, 0x4a72, 0x5f24, 0x5444, 0x4c57, 0x6542, 0x4d3b, 0x6f5a, 0x6e58, 0x5d27, 0x6226, 0x6040, 0x5630, 0x784a, 0x7c7a, 0x597e, 0x5e30, 0x5d6c, 0x5a68, 0x5460, 0x5679, 0x4d57, 0x5e58, 0x7278, 0x6456, 0x5045, 0x742e, 0x5d28, 0x6d45, 0x7356, 0x5e59, 0x6366, 0x5328, 0x5b30, 0x655a, 0x633f, 0x5b31, 0x5569, 0x6041, 0x6f5b, 0x7069, 0x5732, 0x507d, 0x5969, 0x507e, 0x6c6d, 0x5329, 0x7229, 0x7044, 0x6262, 0x696f, 0x7951, 0x6959, 0x685a, 0x5a43, 0x5a44, 0x5445, 0x677a, 0x4d60, 0x6330, 0x5b32, 0x7b44, 0x7363, 0x5925, 0x7b67, 0x5d4b, 0x5054, 0x6636, 0x602e, 0x7d5a, 0x5c35, 0x6078, 0x6731, 0x7570, 0x585c, 0x6d46, 0x6139, 0x6340, 0x7940, 0x6970, 0x595b, 0x7364, 0x5c36, 0x6469, 0x7045, 0x6341, 0x7c4c, 0x7c4d, 0x724b, 0x724c, 0x644f, 0x715b, 0x7a59, 0x7138, 0x7d75, 0x6079, 0x677b, 0x7c37, 0x7c64, 0x7b45, 0x6367, 0x5839, 0x7678, 0x5c45, 0x4c58, 0x602f, 0x7467, 0x6f5c, 0x4f7c, 0x6f5d, 0x722a, 0x7d3e, 0x4a2c, 0x7d3b, 0x7d47, 0x6732, 0x6a51, 0x5f74, 0x516c, 0x645e, 0x6543, 0x5926, 0x4d3c, 0x7365, 0x6d55, 0x593a, 0x6d67, 0x7b35, 0x786c, 0x6067, 0x4c59, 0x5446, 0x6725, 0x5575, 0x533e, 0x7c7b, 0x6472, 0x5f75, 0x6878, 0x786d, 0x4e47, 0x7d76, 0x6858, 0x4d58, 0x6756, 0x4c5a, 0x4a63, 0x5f76, 0x7047, 0x7046, 0x583a, 0x7174, 0x7470, 0x754c, 0x7c65, 0x6a45, 0x6a73, 0x5d5b, 0x5c57, 0x5e7d, 0x7279, 0x5547, 0x5850, 0x7048, 0x5121, 0x5122, 0x5954, 0x5668, 0x594a, 0x5a31, 0x5847, 0x5c62, 0x734e, 0x7574, 0x7139, 0x5a53, 0x766a, 0x4f75, 0x7d2e, 0x4a52, 0x5f34, 0x575d, 0x7a3a, 0x6e27, 0x753d, 0x7875, 0x6d68, 0x5461, 0x5123, 0x6156, 0x7978, 0x5b4a, 0x4b79, 0x5454, 0x595c, 0x6e3e, 0x776d, 0x526e, 0x6166, 0x7779, 0x5d6d, 0x685b, 0x5b33, 0x5177, 0x6030, 0x5462, 0x7657, 0x5779, 0x585d, 0x4d7d, 0x722b, 0x4d3d, 0x7842, 0x722c, 0x4a2d, 0x4a2e, 0x4f2e, 0x6342, 0x5c37, 0x5b5a, 0x593b, 0x4a73, 0x7653, 0x6678, 0x6a75, 0x6a76, 0x7679, 0x4f2f, 0x4a53, 0x4a2f, 0x5230, 0x713a, 0x5733, 0x6343, 0x737d, 0x5e5a, 0x5e5b, 0x6f5e, 0x6263, 0x6e7b, 0x5f77, 0x574a, 0x4e68, 0x5b5b, 0x713b, 0x6971, 0x7a37, 0x5046, 0x4c2b, 0x6e28, 0x4b7a, 0x7979, 0x4c7d, 0x537e, 0x6450, 0x726e, 0x5455, 0x5f4d, 0x7c38, 0x5150, 0x724d, 0x7752, 0x4a54, 0x5559, 0x585e, 0x4d59, 0x6e29, 0x763c, 0x4c5b, 0x7049, 0x7c7c, 0x6849, 0x747e, 0x677c, 0x575e, 0x5e5c, 0x702c, 0x4c7e, 0x4d61, 0x613a, 0x5b6f, 0x5a32, 0x5125, 0x5c38, 0x5876, 0x5124, 0x4d62, 0x5c6a, 0x7077, 0x704a, 0x503e, 0x5d5c, 0x5456, 0x5356, 0x6d50, 0x4d21, 0x5f35, 0x5f78, 0x5421, 0x4e32, 0x684a, 0x6b75, 0x6355, 0x7550, 0x7521, 0x5927, 0x652b, 0x664b, 0x7571, 0x6545, 0x7923, 0x605b, 0x766b, 0x4b71, 0x596a, 0x7522, 0x5751, 0x5178, 0x6a78, 0x6a79, 0x5a33, 0x6f5f, 0x716f, 0x6576, 0x6e3f, 0x6264, 0x503f, 0x7a2c, 0x7551, 0x6733, 0x693e, 0x724e, 0x5b34, 0x7c4e, 0x5d6e, 0x6734, 0x5734, 0x7734, 0x4d3e, 0x5a69, 0x4f30, 0x7759, 0x7366, 0x4e59, 0x4e2a, 0x4b48, 0x5027, 0x704b, 0x5047, 0x6445, 0x5b60, 0x555a, 0x5727, 0x6e40, 0x7876, 0x7552, 0x6d69, 0x593c, 0x6546, 0x7523, 0x5a54, 0x6227, 0x7b7c, 0x715c, 0x4a74, 0x687a, 0x4e69, 0x6978, 0x6265, 0x5039, 0x5472, 0x5126, 0x5f4e, 0x7c74, 0x532a, 0x4c2c, 0x6f60, 0x6565, 0x5055, 0x5b7c, 0x7c66, 0x4b7e, 0x6d6a, 0x5e31, 0x7963, 0x5422, 0x4f76, 0x5650, 0x556a, 0x716e, 0x7a4b, 0x6521, 0x5531, 0x4f6d, 0x6d6b, 0x5532, 0x553c, 0x7d62, 0x732d, 0x7d5b, 0x6930, 0x5127, 0x7d63, 0x4e33, 0x7d64, 0x7a4e, 0x4a30, 0x7727, 0x4f31, 0x6622, 0x7c36, 0x722d, 0x6f61, 0x732e, 0x5c46, 0x596b, 0x6860, 0x6128, 0x5576, 0x4f7d, 0x5e5d, 0x5951, 0x646a, 0x724f, 0x773f, 0x6266, 0x6228, 0x6356, 0x6d51, 0x6979, 0x5631, 0x5e32, 0x6068, 0x532b, 0x6b5c, 0x5f2f, 0x4a43, 0x6e7c, 0x7d43, 0x6b76, 0x4f32, 0x596c, 0x593d, 0x585f, 0x5438, 0x6b3e, 0x5d6f, 0x5d70, 0x5d71, 0x5d72, 0x593e, 0x7b46, 0x4f33, 0x6e7d, 0x642b, 0x5a45, 0x586c, 0x5128, 0x6229, 0x5e3c, 0x6735, 0x5b70, 0x6f62, 0x7170, 0x4f34, 0x5b71, 0x6031, 0x5f25, 0x7952, 0x677d, 0x6623, 0x7b71, 0x4b30, 0x722e, 0x4d67, 0x685c, 0x6757, 0x7740, 0x5063, 0x5a21, 0x4c3d, 0x5129, 0x5d4c, 0x637e, 0x512a, 0x682a, 0x6a36, 0x797a, 0x664c, 0x7658, 0x5447, 0x594b, 0x5952, 0x534b, 0x5877, 0x5a29, 0x7578, 0x5e5e, 0x722f, 0x7829, 0x5848, 0x6e41, 0x7941, 0x5d73, 0x6a7a, 0x763d, 0x613b, 0x4d3f, 0x7454, 0x664d, 0x7c4f, 0x7b22, 0x605c, 0x743b, 0x5a55, 0x7932, 0x7b72, 0x5b76, 0x5e5f, 0x5b72, 0x785c, 0x776e, 0x6b68, 0x527a, 0x713c, 0x7a5a, 0x5a6a, 0x5a46, 0x7741, 0x6736, 0x6547, 0x562c, 0x5c47, 0x6129, 0x622a, 0x5526, 0x5457, 0x7250, 0x6a7b, 0x605d, 0x7b73, 0x713d, 0x6267, 0x7d57, 0x4e48, 0x6a37, 0x7c40, 0x7d67, 0x776f, 0x5735, 0x6f3a, 0x715d, 0x5e33, 0x684b, 0x785d, 0x7b47, 0x5548, 0x575f, 0x5d29, 0x6931, 0x7a2d, 0x7659, 0x7a74, 0x782a, 0x666e, 0x4c5c, 0x613c, 0x606f, 0x693f, 0x7c7d, 0x664e, 0x6157, 0x664f, 0x7471, 0x6473, 0x647b, 0x7964, 0x6f63, 0x4f6e, 0x763e, 0x6032, 0x7c7e, 0x512b, 0x577a, 0x7b48, 0x6257, 0x5423, 0x7078, 0x5728, 0x6167, 0x533f, 0x6f64, 0x5745, 0x6b62, 0x7c67, 0x6422, 0x6268, 0x6650, 0x7b68, 0x7468, 0x6574, 0x743c, 0x7455, 0x5f36, 0x7c39, 0x6e42, 0x4a75, 0x6f65, 0x4b62, 0x5424, 0x5e60, 0x5a7d, 0x6446, 0x683e, 0x605e, 0x7634, 0x6a52, 0x797b, 0x6042, 0x4a64, 0x6737, 0x6a7d, 0x595d, 0x5a34, 0x6e2a, 0x7b69, 0x5b4b, 0x5a35, 0x713e, 0x532c, 0x7b49, 0x5f4f, 0x5340, 0x6357, 0x6f66, 0x7c50, 0x6940, 0x7553, 0x6c5c, 0x7737, 0x6a38, 0x5179, 0x5c48, 0x6a39, 0x715e, 0x5736, 0x4f35, 0x5928, 0x6c6e, 0x5d2a, 0x4d22, 0x682e, 0x613d, 0x7251, 0x6941, 0x527c, 0x5b35, 0x7367, 0x587e, 0x7c51, 0x6d32, 0x742f, 0x7b23, 0x7c41, 0x6e2b, 0x5425, 0x7472, 0x6e59, 0x7b4a, 0x4d63, 0x583b, 0x655b, 0x7877, 0x7654, 0x5729, 0x4b49, 0x6651, 0x704c, 0x582e, 0x7953, 0x557e, 0x583c, 0x7230, 0x622b, 0x7368, 0x6f42, 0x6d6c, 0x6738, 0x5a7e, 0x4c3e, 0x727c, 0x5a6b, 0x6258, 0x6d56, 0x5651, 0x6033, 0x7c52, 0x6b48, 0x5341, 0x704d, 0x4f77, 0x6d52, 0x5458, 0x5c49, 0x5771, 0x5f3b, 0x7325, 0x744d, 0x713f, 0x7831, 0x697a, 0x7b4b, 0x4a55, 0x7954, 0x774a, 0x5648, 0x7c68, 0x733d, 0x6e7e, 0x677e, 0x5342, 0x5336, 0x4c2d, 0x767a, 0x5632, 0x5258, 0x6758, 0x6325, 0x6739, 0x702d, 0x7b4c, 0x6b21, 0x5426, 0x7b4d, 0x553d, 0x715f, 0x767b, 0x5e34, 0x556b, 0x6548, 0x7b24, 0x5439, 0x5e61, 0x6423, 0x5737, 0x786e, 0x5e35, 0x5652, 0x7955, 0x673a, 0x6b55, 0x5577, 0x6f67, 0x613e, 0x7a2e, 0x5669, 0x566e, 0x673b, 0x6c4b, 0x5533, 0x4e34, 0x7b25, 0x616e, 0x7728, 0x7b4e, 0x583d, 0x7b7d, 0x7c69, 0x4f36, 0x6d47, 0x6e2c, 0x4c5d, 0x7627, 0x667a, 0x7524, 0x7d5c, 0x6d33, 0x4e49, 0x6f68, 0x613f, 0x7a5b, 0x4b63, 0x7729, 0x7b26, 0x5c39, 0x7140, 0x6d48, 0x6f43, 0x562d, 0x7d4e, 0x6821, 0x7b74, 0x5527, 0x7176, 0x6653, 0x4c5e, 0x7832, 0x5c6b, 0x7d36, 0x656a, 0x7160, 0x5b4c, 0x5d4d, 0x5448, 0x596d, 0x7525, 0x667b, 0x6654, 0x7d48, 0x5621, 0x7d3f, 0x7c53, 0x6f21, 0x673c, 0x516e, 0x6655, 0x6972, 0x5f30, 0x5860, 0x7c3a, 0x7d2f, 0x704e, 0x5b61, 0x6549, 0x6d34, 0x6043, 0x6358, 0x697b, 0x6a28, 0x7d37, 0x7b27, 0x6942, 0x7d77, 0x6259, 0x5c6c, 0x6822, 0x6670, 0x7d78, 0x7d79, 0x763f, 0x6727, 0x6657, 0x5473, 0x5449, 0x567a, 0x5772, 0x6140, 0x5b62, 0x6658, 0x673d, 0x704f, 0x733e, 0x622c, 0x7537, 0x6070, 0x7d38, 0x6368, 0x5427, 0x687c, 0x7a52, 0x786f, 0x5653, 0x5534, 0x7050, 0x7770, 0x6e33, 0x6a3a, 0x6a53, 0x6d49, 0x5d2b, 0x652c, 0x7d21, 0x5f50, 0x6c33, 0x5f51, 0x6d6d, 0x7838, 0x777a, 0x782b, 0x7460, 0x543a, 0x6433, 0x695a, 0x5e36, 0x593f, 0x5940, 0x566f, 0x594c, 0x5a2a, 0x5f65, 0x7765, 0x4c32, 0x5f79, 0x5760, 0x543b, 0x7d7a, 0x4c33, 0x5b73, 0x5f52, 0x4e4a, 0x6e5a, 0x6464, 0x7b4f, 0x4f37, 0x6e43, 0x4e6a, 0x622d, 0x5761, 0x7a75, 0x5549, 0x782c, 0x6759, 0x7369, 0x586d, 0x6344, 0x7071, 0x6865, 0x607a, 0x6e44, 0x595e, 0x6b22, 0x6b23, 0x7c42, 0x6a3b, 0x682b, 0x5e62, 0x6d6f, 0x6823, 0x4f71, 0x543c, 0x7c6a, 0x673e, 0x7c72, 0x5634, 0x622e, 0x5337, 0x7a4c, 0x7a5c, 0x6d35, 0x6163, 0x682c, 0x685d, 0x6f69, 0x743d, 0x4f38, 0x695b, 0x512c, 0x5a47, 0x6b49, 0x684c, 0x5e37, 0x563c, 0x5365, 0x7a5d, 0x5a56, 0x4a31, 0x5a48, 0x5f26, 0x7933, 0x7252, 0x4a44, 0x4e4b, 0x4d75, 0x7d30, 0x5528, 0x7141, 0x6269, 0x5c4a, 0x6c34, 0x7a40, 0x7b28, 0x5028, 0x5a6c, 0x596e, 0x607b, 0x6f6a, 0x7a5e, 0x6044, 0x4f39, 0x554a, 0x5762, 0x622f, 0x5738, 0x684d, 0x765a, 0x6f22, 0x625a, 0x767c, 0x7b50, 0x512d, 0x4d64, 0x512e, 0x5c6d, 0x684e, 0x7079, 0x4e35, 0x667c, 0x577b, 0x5056, 0x5d75, 0x7771, 0x767d, 0x5b77, 0x7b6a, 0x695c, 0x5941, 0x7572, 0x6045, 0x6a54, 0x7942, 0x6a3c, 0x5245, 0x7b51, 0x6740, 0x6b25, 0x5f7a, 0x6322, 0x5739, 0x6943, 0x687d, 0x682f, 0x7253, 0x7b29, 0x5825, 0x554b, 0x5048, 0x512f, 0x5763, 0x6046, 0x5622, 0x6d70, 0x5773, 0x7c54, 0x5a57, 0x4c5f, 0x7254, 0x5130, 0x4c60, 0x5b7d, 0x733f, 0x7051, 0x7c3b, 0x6230, 0x6625, 0x625b, 0x5f5e, 0x6047, 0x726f, 0x4c61, 0x566a, 0x6742, 0x4e36, 0x7340, 0x4d7e, 0x7b52, 0x7878, 0x777b, 0x683f, 0x6837, 0x6d36, 0x5c3a, 0x4c34, 0x7177, 0x6838, 0x4a76, 0x6424, 0x7456, 0x5f66, 0x5f27, 0x5f67, 0x6141, 0x6944, 0x5c4b, 0x6945, 0x6f23, 0x6b26, 0x4b23, 0x6369, 0x517b, 0x6f24, 0x6f6b, 0x5034, 0x4d23, 0x6866, 0x6f25, 0x534c, 0x5a6d, 0x573a, 0x7255, 0x7565, 0x596f, 0x7934, 0x5554, 0x7d4f, 0x5b63, 0x7161, 0x6c36, 0x7b7e, 0x5357, 0x5131, 0x4b31, 0x5132, 0x4b32, 0x7142, 0x7461, 0x7935, 0x6143, 0x6142, 0x6b77, 0x5f28, 0x4b4a, 0x6639, 0x785e, 0x792a, 0x4a77, 0x6d37, 0x5338, 0x7256, 0x5459, 0x6e45, 0x7270, 0x4a32, 0x5c3b, 0x7178, 0x6c37, 0x654a, 0x7640, 0x7d5d, 0x5463, 0x4c62, 0x7754, 0x5765, 0x5343, 0x5826, 0x7641, 0x5d76, 0x4d40, 0x655c, 0x654b, 0x6144, 0x6830, 0x7430, 0x736a, 0x5a6e, 0x573b, 0x6231, 0x572a, 0x567b, 0x645f, 0x4a56, 0x6b28, 0x5b7e, 0x7642, 0x6f3b, 0x547d, 0x6048, 0x6839, 0x6f26, 0x4d24, 0x5474, 0x5b21, 0x5b5c, 0x5b5d, 0x6e5c, 0x4b4b, 0x7c55, 0x4e6b, 0x4d41, 0x7b53, 0x792b, 0x7554, 0x5929, 0x695d, 0x5b4d, 0x5d4e, 0x6743, 0x6c4c, 0x796c, 0x4b4c, 0x607c, 0x5428, 0x6d53, 0x586f, 0x7257, 0x4a78, 0x5a6f, 0x5654, 0x594d, 0x586e, 0x7241, 0x5f53, 0x5a70, 0x626a, 0x607d, 0x5878, 0x772f, 0x5a36, 0x4a57, 0x7258, 0x5879, 0x7a5f, 0x4f6f, 0x5942, 0x7052, 0x6451, 0x7337, 0x7a60, 0x6f6c, 0x6232, 0x543d, 0x594e, 0x7462, 0x5429, 0x4d42, 0x675a, 0x7259, 0x592a, 0x583e, 0x5c2d, 0x626b, 0x567c, 0x4a79, 0x545a, 0x7457, 0x4c21, 0x4f3a, 0x7538, 0x5943, 0x5068, 0x6345, 0x6b78, 0x7231, 0x4f3b, 0x532d, 0x6861, 0x4e6c, 0x6034, 0x5e63, 0x5d77, 0x7232, 0x7376, 0x765b, 0x577e, 0x785f, 0x7772, 0x5029, 0x665a, 0x7526, 0x573c, 0x4c63, 0x665b, 0x5d5d, 0x5133, 0x6f6d, 0x565e, 0x6474, 0x616f, 0x5d78, 0x684f, 0x4a65, 0x5c21, 0x6035, 0x7c2c, 0x7c2d, 0x5827, 0x6d38, 0x5b36, 0x5670, 0x732f, 0x4d25, 0x5a71, 0x5828, 0x4c64, 0x5134, 0x4a58, 0x5a72, 0x7527, 0x7528, 0x6626, 0x556c, 0x5578, 0x5a73, 0x6346, 0x5e64, 0x5e65, 0x5135, 0x5136, 0x5137, 0x7233, 0x695e, 0x7053, 0x7234, 0x7054, 0x4b64, 0x7b54, 0x7566, 0x636a, 0x5e66, 0x5f54, 0x7879, 0x702e, 0x5138, 0x565f, 0x5057, 0x7c21, 0x6f6e, 0x5c58, 0x695f, 0x655d, 0x7d7b, 0x6049, 0x5649, 0x542a, 0x654c, 0x6960, 0x5058, 0x7c22, 0x543e, 0x6233, 0x5e67, 0x5c3c, 0x5236, 0x7555, 0x4e21, 0x7529, 0x5d79, 0x5d7a, 0x7055, 0x765f, 0x725a, 0x646b, 0x7271, 0x6c39, 0x7d7c, 0x612a, 0x4a59, 0x6f6f, 0x752a, 0x6c79, 0x782d, 0x7242, 0x7643, 0x5752, 0x7922, 0x7056, 0x707a, 0x7660, 0x6973, 0x7243, 0x542b, 0x4a33, 0x4d26, 0x4d43, 0x4d5a, 0x594f, 0x7644, 0x6e5d, 0x6744, 0x6234, 0x5f62, 0x675b, 0x6831, 0x7c2e, 0x654d, 0x7a6b, 0x4f3c, 0x4f62, 0x4d76, 0x6f70, 0x743e, 0x544d, 0x7338, 0x6921, 0x7272, 0x736b, 0x7057, 0x4f57, 0x4f5f, 0x6840, 0x6841, 0x4f63, 0x6922, 0x502a, 0x7341, 0x502b, 0x5464, 0x6f3c, 0x5821, 0x595f, 0x7357, 0x5c3d, 0x4c65, 0x6d71, 0x7162, 0x545b, 0x6235, 0x4a66, 0x532e, 0x4c66, 0x7153, 0x7567, 0x4a5a, 0x7b6e, 0x6145, 0x5f69, 0x6e5e, 0x7742, 0x5822, 0x5d2c, 0x702f, 0x563d, 0x612b, 0x7936, 0x5475, 0x5049, 0x6f27, 0x626c, 0x5b6a, 0x4e4c, 0x7568, 0x7755, 0x534d, 0x737e, 0x5035, 0x607e, 0x5f7b, 0x665d, 0x6824, 0x4b4d, 0x6f28, 0x6e34, 0x5a58, 0x5139, 0x5f29, 0x7330, 0x4c44, 0x4e37, 0x6f29, 0x5f55, 0x6d57, 0x6e46, 0x6f3d, 0x7c56, 0x5b74, 0x6f2a, 0x7839, 0x7569, 0x6359, 0x6146, 0x543f, 0x5e68, 0x706a, 0x7342, 0x532f, 0x4a5b, 0x7c57, 0x6d58, 0x6147, 0x7458, 0x5633, 0x5d2d, 0x553e, 0x7143, 0x6e5f, 0x566b, 0x7459, 0x5766, 0x5a37, 0x5d7b, 0x5d4f, 0x5823, 0x5a59, 0x7058, 0x6f44, 0x6158, 0x7154, 0x6d72, 0x555b, 0x555c, 0x7344, 0x4b57, 0x6236, 0x6f71, 0x7b55, 0x5358, 0x5d50, 0x7059, 0x4b33, 0x555d, 0x4d27, 0x502c, 0x513a, 0x7144, 0x6533, 0x7b75, 0x6961, 0x7d60, 0x7c3c, 0x5a22, 0x5a23, 0x5221, 0x526f, 0x626d, 0x5e69, 0x4e5c, 0x7235, 0x5064, 0x5d51, 0x6148, 0x5b37, 0x5f63, 0x6d39, 0x7145, 0x734f, 0x572b, 0x612c, 0x636b, 0x6e47, 0x6149, 0x4a7a, 0x707b, 0x7a61, 0x705a, 0x4c67, 0x5a74, 0x4c3f, 0x4e6d, 0x5529, 0x7a62, 0x5065, 0x6b56, 0x6c5f, 0x5f7c, 0x7756, 0x5e6a, 0x4b34, 0x6f3e, 0x4c35, 0x4f3d, 0x6f72, 0x6237, 0x4c68, 0x707c, 0x5660, 0x7146, 0x6238, 0x6b2b, 0x4b35, 0x5851, 0x744e, 0x7377, 0x5746, 0x513b, 0x772a, 0x6d4a, 0x5753, 0x587a, 0x7645, 0x514c, 0x5d7c, 0x5f7d, 0x7965, 0x604a, 0x727d, 0x5330, 0x7473, 0x5a49, 0x665e, 0x783a, 0x6850, 0x587b, 0x6a55, 0x5623, 0x7646, 0x725b, 0x647c, 0x6832, 0x5a5a, 0x725c, 0x7b56, 0x6932, 0x6e2d, 0x7a63, 0x5c6e, 0x756a, 0x6660, 0x707d, 0x572c, 0x7545, 0x6e60, 0x5b65, 0x5d5e, 0x5970, 0x6923, 0x7179, 0x7244, 0x604b, 0x6924, 0x6239, 0x6331, 0x7c6b, 0x4d28, 0x4c36, 0x705b, 0x663a, 0x4d29, 0x7343, 0x6159, 0x6f2b, 0x6745, 0x6069, 0x7345, 0x5440, 0x553f, 0x5d2e, 0x797c, 0x4c40, 0x6522, 0x4e38, 0x5852, 0x7956, 0x712a, 0x4e51, 0x7647, 0x5b6b, 0x5f7e, 0x5861, 0x7773, 0x5767, 0x547e, 0x513c, 0x654f, 0x4b36, 0x5a38, 0x4d44, 0x563e, 0x623a, 0x4f58, 0x604c, 0x6b79, 0x7d7d, 0x5768, 0x4b58, 0x6962, 0x683a, 0x6347, 0x6c4d, 0x6c4e, 0x563f, 0x6327, 0x5f56, 0x7d68, 0x6e61, 0x7628, 0x5d7d, 0x783b, 0x6851, 0x7957, 0x4e6e, 0x6c4f, 0x6925, 0x5655, 0x4d45, 0x6d3a, 0x513d, 0x4f3e, 0x6c3b, 0x5231, 0x4c69, 0x5944, 0x697c, 0x513e, 0x6c3c, 0x652d, 0x7730, 0x4c6a, 0x5344, 0x5640, 0x567d, 0x6121, 0x5e3d, 0x7629, 0x5a24, 0x5624, 0x7546, 0x6122, 0x6946, 0x7245, 0x7469, 0x566c, 0x6b53, 0x6c3d, 0x625c, 0x5e6b, 0x705c, 0x6b3f, 0x574e, 0x513f, 0x752b, 0x797d, 0x4a5c, 0x4d46, 0x7236, 0x5d7e, 0x4c37, 0x5b38, 0x5069, 0x4e5d, 0x6b40, 0x7d22, 0x784b, 0x6a56, 0x7130, 0x5b4e, 0x7743, 0x5b4f, 0x4b24, 0x7860, 0x7b57, 0x6b4a, 0x6021, 0x4e4d, 0x545c, 0x7d58, 0x5276, 0x7237, 0x7a76, 0x762a, 0x7a77, 0x5866, 0x7431, 0x6852, 0x4a45, 0x4c6b, 0x626e, 0x623b, 0x772d, 0x7861, 0x736c, 0x5e21, 0x647d, 0x636c, 0x5d2f, 0x5d30, 0x4b37, 0x6853, 0x6123, 0x5260, 0x707e, 0x6926, 0x4b72, 0x6d73, 0x5c59, 0x604d, 0x775a, 0x5b39, 0x4c2e, 0x5a5b, 0x4d47, 0x5d31, 0x582f, 0x6323, 0x4e6f, 0x7273, 0x7833, 0x604e, 0x757d, 0x6b6c, 0x5345, 0x7c6c, 0x525b, 0x546b, 0x5e22, 0x6566, 0x7030, 0x5544, 0x6d74, 0x636d, 0x6842, 0x6d75, 0x577c, 0x6d3b, 0x762b, 0x7238, 0x7648, 0x5366, 0x725d, 0x4f3f, 0x6b2c, 0x4f40, 0x6628, 0x7d69, 0x4f41, 0x605f, 0x5e6c, 0x6022, 0x743f, 0x626f, 0x5971, 0x7147, 0x4b38, 0x797e, 0x5b3a, 0x5a75, 0x766c, 0x5a5c, 0x7a64, 0x604f, 0x5d32, 0x6629, 0x6f73, 0x736d, 0x6b7a, 0x7966, 0x4a5d, 0x555e, 0x4a5e, 0x5f64, 0x667d, 0x752c, 0x6475, 0x6963, 0x6d4b, 0x4f64, 0x5853, 0x5d33, 0x546c, 0x7239, 0x5f37, 0x4b4e, 0x7b58, 0x5059, 0x5d52, 0x7774, 0x675c, 0x6425, 0x7c23, 0x5b3b, 0x723a, 0x697d, 0x504a, 0x7556, 0x5945, 0x6434, 0x6d27, 0x6a3d, 0x667e, 0x7744, 0x752d, 0x5960, 0x4a34, 0x7862, 0x4f42, 0x6c3e, 0x6534, 0x4d48, 0x6e48, 0x6748, 0x4d49, 0x7937, 0x7168, 0x5972, 0x5b75, 0x4a35, 0x5946, 0x5849, 0x592b, 0x6d3c, 0x5854, 0x5c5a, 0x623c, 0x7c6d, 0x6c60, 0x527e, 0x6947, 0x662a, 0x6270, 0x7a3b, 0x752e, 0x7b2a, 0x6c7b, 0x6c3f, 0x7c58, 0x5465, 0x7943, 0x6e62, 0x5769, 0x6d76, 0x5e6d, 0x4c6c, 0x636e, 0x6854, 0x7a78, 0x5d34, 0x6435, 0x5830, 0x5855, 0x746a, 0x4e39, 0x5661, 0x4f52, 0x5036, 0x4e22, 0x736e, 0x7378, 0x5c4c, 0x504b, 0x7c24, 0x4d4a, 0x5754, 0x5e23, 0x6460, 0x6e49, 0x625d, 0x757e, 0x542c, 0x5551, 0x5870, 0x7843, 0x6a57, 0x7557, 0x583f, 0x7d40, 0x6b2d, 0x552a, 0x6728, 0x6e4a, 0x4a67, 0x7863, 0x545d, 0x6a58, 0x7b59, 0x6d77, 0x6535, 0x502d, 0x7171, 0x623d, 0x6348, 0x5955, 0x5f2a, 0x5b3c, 0x7864, 0x717a, 0x6536, 0x736f, 0x7b5a, 0x6160, 0x592c, 0x756b, 0x6036, 0x6948, 0x4b4f, 0x6349, 0x5e6e, 0x623e, 0x5c6f, 0x5625, 0x6271, 0x567e, 0x5921, 0x5840, 0x5c5b, 0x6d3d, 0x5f38, 0x6a25, 0x572d, 0x7379, 0x6d78, 0x7547, 0x614a, 0x6b63, 0x725e, 0x784c, 0x6a59, 0x5346, 0x5b66, 0x752f, 0x4e70, 0x697e, 0x7b36, 0x6272, 0x4f72, 0x7739, 0x5973, 0x614b, 0x5a5d, 0x5a39, 0x6b7b, 0x4b39, 0x6d79, 0x6060, 0x7440, 0x7d3c, 0x5f31, 0x636f, 0x6023, 0x7d39, 0x7031, 0x4d4b, 0x6d3e, 0x5540, 0x6370, 0x6d7a, 0x6964, 0x556d, 0x675d, 0x5476, 0x6537, 0x5b67, 0x623f, 0x6e4b, 0x5774, 0x705d, 0x4e2b, 0x675e, 0x5656, 0x614c, 0x6833, 0x656e, 0x5c22, 0x6050, 0x5535, 0x5521, 0x7b5b, 0x794b, 0x4b73, 0x7425, 0x7a48, 0x5657, 0x6965, 0x7b5c, 0x7d50, 0x7b76, 0x5a25, 0x5b3d, 0x6c62, 0x4d77, 0x705e, 0x7649, 0x5e6f, 0x5331, 0x7c6e, 0x6843, 0x7148, 0x4e71, 0x796d, 0x7274, 0x6436, 0x7539, 0x5c70, 0x6371, 0x6825, 0x723b, 0x5e24, 0x5a4c, 0x4a69, 0x635a, 0x7c59, 0x6a5a, 0x7944, 0x6324, 0x7b5d, 0x6f4a, 0x6844, 0x554c, 0x6b57, 0x592d, 0x7b2b, 0x5359, 0x5522, 0x765e, 0x5a76, 0x6051, 0x6928, 0x7579, 0x7a2f, 0x6b7c, 0x606a, 0x6332, 0x5545, 0x7163, 0x556e, 0x4d4c, 0x6d59, 0x5841, 0x7a6c, 0x716b, 0x7a3c, 0x6662, 0x7a65, 0x627a, 0x4a36, 0x6437, 0x6a5b, 0x757a, 0x7b2c, 0x4f43, 0x6b7d, 0x787a, 0x5f39, 0x6171, 0x5224, 0x757b, 0x505a, 0x505b, 0x6a3e, 0x5931, 0x4a37, 0x5367, 0x7865, 0x5332, 0x6240, 0x725f, 0x4d65, 0x792c, 0x4d4d, 0x6e2e, 0x562e, 0x576a, 0x6760, 0x6b2e, 0x4f59, 0x5c4d, 0x6d7b, 0x5e70, 0x576b, 0x5e25, 0x5f57, 0x5b50, 0x5b51, 0x5523, 0x7032, 0x5c5c, 0x4a68, 0x7866, 0x5c4e, 0x6a5c, 0x5b52, 0x6933, 0x775b, 0x6328, 0x572e, 0x6061, 0x4b3a, 0x6551, 0x505c, 0x5541, 0x584a, 0x6329, 0x6024, 0x6929, 0x5347, 0x5c5d, 0x782e, 0x4c38, 0x502e, 0x5872, 0x634a, 0x4c2f, 0x542d, 0x7651, 0x504c, 0x4a46, 0x5542, 0x4e3a, 0x4a47, 0x7a30, 0x5f58, 0x753a, 0x656b, 0x6f74, 0x5d35, 0x4d2a, 0x6372, 0x7b77, 0x7750, 0x7d3a, 0x7d61, 0x767e, 0x5140, 0x6845, 0x6438, 0x6168, 0x4c41, 0x526d, 0x5b3e, 0x6062, 0x7a49, 0x614d, 0x4a38, 0x7260, 0x7149, 0x5e71, 0x705f, 0x7844, 0x6e4c, 0x5e72, 0x6749, 0x6273, 0x6761, 0x634b, 0x634c, 0x4f78, 0x6f2c, 0x7d7e, 0x7c25, 0x7a31, 0x5f59, 0x6052, 0x745a, 0x714a, 0x4e23, 0x723c, 0x6c63, 0x6025, 0x772b, 0x6b2f, 0x655e, 0x6124, 0x4d2b, 0x5974, 0x6826, 0x4d4e, 0x6169, 0x7c6f, 0x6063, 0x6241, 0x4e24, 0x5e26, 0x6b7e, 0x6b5d, 0x7060, 0x745b, 0x6274, 0x5348, 0x746b, 0x6e35, 0x7558, 0x555f, 0x5665, 0x6b30, 0x7463, 0x634d, 0x7474, 0x7a32, 0x6f75, 0x4a5f, 0x6b31, 0x6d3f, 0x7d49, 0x6426, 0x7924, 0x7033, 0x656c, 0x5167, 0x5947, 0x6457, 0x6a5d, 0x5477, 0x5a3a, 0x5a4d, 0x794c, 0x615a, 0x5b3f, 0x4c45, 0x6c50, 0x4b3b, 0x5e73, 0x692a, 0x5948, 0x6e63, 0x573d, 0x4f44, 0x504d, 0x7c26, 0x717b, 0x7d52, 0x5141, 0x635b, 0x5349, 0x5c4f, 0x4c6d, 0x5e27, 0x663b, 0x6c21, 0x4c39, 0x7b5e, 0x6762, 0x5441, 0x5c28, 0x6242, 0x7358, 0x6553, 0x7359, 0x7346, 0x4d5b, 0x4d2c, 0x7c43, 0x5467, 0x5142, 0x7925, 0x6855, 0x634e, 0x544a, 0x5f5a, 0x7b5f, 0x6763, 0x787b, 0x634f, 0x7530, 0x5867, 0x5949, 0x782f, 0x6f76, 0x5d36, 0x6e2f, 0x4d78, 0x5e38, 0x7c27, 0x777c, 0x7731, 0x4e3b, 0x7421, 0x6e4d, 0x612e, 0x6c43, 0x4f7e, 0x783f, 0x5862, 0x5368, 0x5e28, 0x7464, 0x6c42, 0x5975, 0x7945, 0x5d53, 0x5671, 0x6c7c, 0x7c70, 0x6d40, 0x4a39, 0x6e64, 0x7261, 0x5e39, 0x5672, 0x5e74, 0x5f5b, 0x5b53, 0x7a67, 0x5863, 0x7441, 0x5d37, 0x7275, 0x542e, 0x5673, 0x5d38, 0x4f45, 0x5f5f, 0x723e, 0x7621, 0x6b4b, 0x717c, 0x7347, 0x606b, 0x6d7c, 0x615b, 0x6e65, 0x5e75, 0x7a53, 0x714b, 0x502f, 0x5d39, 0x5143, 0x7531, 0x6a46, 0x7061, 0x762c, 0x7559, 0x706b, 0x5d3a, 0x723f, 0x7745, 0x5b22, 0x7276, 0x4a3a, 0x7775, 0x4b65, 0x6e66, 0x6053, 0x4e25, 0x5658, 0x542f, 0x6949, 0x534e, 0x7442, 0x4b66, 0x7121, 0x6b32, 0x7122, 0x6b33, 0x7034, 0x4b74, 0x5430, 0x7332, 0x7b37, 0x756c, 0x6e67, 0x7432, 0x756d, 0x4f73, 0x7062, 0x6e4e, 0x714c, 0x6538, 0x5775, 0x6373, 0x4f65, 0x4f46, 0x7333, 0x6458, 0x4f79, 0x4f5a, 0x7a4d, 0x6663, 0x7262, 0x756e, 0x4a3b, 0x635c, 0x4e72, 0x5659, 0x6e30, 0x7465, 0x5842, 0x5c50, 0x4c6e, 0x5560, 0x764a, 0x7d4a, 0x5856, 0x744f, 0x5626, 0x5c3e, 0x5b54, 0x5747, 0x727e, 0x714d, 0x6243, 0x5c5e, 0x5c5f, 0x6f2d, 0x662b, 0x795d, 0x6a3f, 0x6f2e, 0x7450, 0x4e73, 0x662c, 0x4e5e, 0x5579, 0x6374, 0x4d50, 0x5538, 0x777d, 0x5c29, 0x5e76, 0x5c2a, 0x7263, 0x6934, 0x525c, 0x6966, 0x6376, 0x674a, 0x504e, 0x5a77, 0x4a3c, 0x6e68, 0x5a5e, 0x7277, 0x627b, 0x4c26, 0x5a3b, 0x6e69, 0x755a, 0x775c, 0x616a, 0x4e41, 0x5431, 0x7d31, 0x663d, 0x7b2d, 0x7867, 0x614e, 0x7762, 0x756f, 0x4f47, 0x5432, 0x4c6f, 0x5468, 0x6e4f, 0x7757, 0x6026, 0x5641, 0x615c, 0x7063, 0x7164, 0x5c71, 0x5627, 0x7475, 0x714e, 0x7264, 0x5030, 0x6c6f, 0x793a, 0x6b35, 0x546d, 0x6244, 0x6967, 0x6b34, 0x6a21, 0x783c, 0x4e26, 0x7946, 0x7c5a, 0x5433, 0x5339, 0x6a5e, 0x692b, 0x6161, 0x534f, 0x7476, 0x6a40, 0x614f, 0x4c3a, 0x6e6a, 0x7064, 0x7334, 0x546e, 0x7240, 0x7165, 0x7443, 0x6054, 0x6b36, 0x5721, 0x4b68, 0x792d, 0x692d, 0x5864, 0x7a33, 0x6245, 0x7c3d, 0x6c44, 0x5831, 0x5c2b, 0x5524, 0x6b69, 0x683b, 0x5857, 0x7b2e, 0x5161, 0x5b40, 0x753e, 0x5e77, 0x4a7b, 0x7746, 0x4f48, 0x6150, 0x6e50, 0x6974, 0x4e74, 0x554d, 0x4f5b, 0x5d3b, 0x4e2c, 0x6968, 0x5434, 0x6447, 0x755b, 0x7a41, 0x5e29, 0x5478, 0x6f77, 0x5333, 0x6b37, 0x6f78, 0x755c, 0x6d4c, 0x5b55, 0x714f, 0x7150, 0x7532, 0x592e, 0x552c, 0x6246, 0x7d23, 0x7b65, 0x5f2b, 0x6275, 0x762d, 0x7533, 0x7035, 0x6125, 0x755d, 0x6c22, 0x6d7d, 0x7534, 0x7b38, 0x5b23, 0x564a, 0x4b59, 0x6554, 0x737a, 0x6b38, 0x6037, 0x576c, 0x716c, 0x652f, 0x5561, 0x576d, 0x5151, 0x6172, 0x6f79, 0x5d3c, 0x765c, 0x7065, 0x7444, 0x6969, 0x737b, 0x546f, 0x4c22, 0x777e, 0x5f3c, 0x6b4d, 0x5037, 0x5642, 0x682d, 0x6f2f, 0x4b25, 0x4b69, 0x7a68, 0x4c46, 0x6667, 0x6a47, 0x5b24, 0x4f49, 0x627c, 0x6f7a, 0x6b5e, 0x7548, 0x545e, 0x6055, 0x6f30, 0x6247, 0x592f, 0x7967, 0x6765, 0x4f4a, 0x6151, 0x6248, 0x6f7b, 0x7a79, 0x5c72, 0x6027, 0x7868, 0x4b6a, 0x4b3c, 0x5662, 0x755e, 0x755f, 0x6e36, 0x6276, 0x534a, 0x6f7c, 0x5144, 0x6f31, 0x5145, 0x505e, 0x5961, 0x6038, 0x4d51, 0x7339, 0x674c, 0x5628, 0x4e27, 0x5435, 0x6448, 0x5334, 0x6b39, 0x4b75, 0x765d, 0x7123, 0x4c47, 0x694a, 0x6170, 0x7560, 0x7b2f, 0x4b51, 0x7b60, 0x7265, 0x6c70, 0x706c, 0x6e6b, 0x694b, 0x4c70, 0x572f, 0x7321, 0x7c75, 0x7124, 0x6056, 0x6f32, 0x7451, 0x7721, 0x7151, 0x4a7c, 0x4a7d, 0x4e4e, 0x7348, 0x733a, 0x6d7e, 0x5a26, 0x606c, 0x784d, 0x4b52, 0x6b4e, 0x7958, 0x7959, 0x4a60, 0x5a4a, 0x4b26, 0x4a48, 0x796e, 0x5b6c, 0x5031, 0x556f, 0x6673, 0x6722, 0x6459, 0x6461, 0x7c44, 0x796f, 0x4f74, 0x7766, 0x4e3c, 0x7445, 0x5c23, 0x5d3d, 0x7446, 0x7821, 0x6856, 0x5b41, 0x7066, 0x6439, 0x766d, 0x792e, 0x5d3e, 0x5730, 0x5868, 0x4b3d, 0x795a, 0x784e, 0x7970, 0x606d, 0x6333, 0x7433, 0x6a42, 0x7266, 0x7036, 0x5b56, 0x6b64, 0x7267, 0x5755, 0x5436, 0x7968, 0x5741, 0x6555, 0x696a, 0x574c, 0x5369, 0x6249, 0x7c5b, 0x4d2d, 0x4c30, 0x6a22, 0x6476, 0x5040, 0x7037, 0x6e21, 0x5776, 0x624a, 0x624b, 0x7a4f, 0x6b5f, 0x564b, 0x7434, 0x6d4d, 0x6452, 0x6a29, 0x643a, 0x7322, 0x4d52, 0x764b, 0x7166, 0x6d41, 0x683c, 0x6e51, 0x7067, 0x624c, 0x642a, 0x7561, 0x6d5a, 0x576e, 0x5171, 0x696b, 0x696c, 0x6064, 0x5a27, 0x5d54, 0x6a23, 0x5643, 0x5674, 0x5a5f, 0x6f33, 0x624d, 0x6f7d, 0x7268, 0x6f45, 0x6767, 0x577d, 0x674e, 0x5f5c, 0x7947, 0x5976, 0x5f2c, 0x565a, 0x5c24, 0x7038, 0x557a, 0x6477, 0x5644, 0x746c, 0x6f7e, 0x7021, 0x5e2a, 0x5a3c, 0x587c, 0x7a54, 0x6c65, 0x7c28, 0x6c66, 0x584b, 0x7b39, 0x6453, 0x4d79, 0x4f53, 0x4a6a, 0x4f54, 0x783d, 0x7447, 0x6a5f, 0x795b, 0x5437, 0x6b65, 0x6152, 0x6a24, 0x7a42, 0x7b61, 0x7a6d, 0x7022, 0x4c71, 0x7a23, 0x6277, 0x624e, 0x6975, 0x616b, 0x6768, 0x6857, 0x5a78, 0x544b, 0x7776, 0x5645, 0x5469, 0x7a7a, 0x4c72, 0x775d, 0x5e3a, 0x4e28, 0x7039, 0x647e, 0x6449, 0x6454, 0x6a43, 0x6f34, 0x573e, 0x7b62, 0x4d53, 0x6f35, 0x7a69, 0x7926, 0x5f3d, 0x7747, 0x787d, 0x787c, 0x5e2b, 0x5b68, 0x635d, 0x6162, 0x5146, 0x7650, 0x6b66, 0x5a79, 0x6c47, 0x5e78, 0x7869, 0x635e, 0x4e75, 0x7a43, 0x6557, 0x6c48, 0x7349, 0x643b, 0x662e, 0x6f36, 0x5c3f, 0x4e3d, 0x5843, 0x504f, 0x4f7a, 0x734a, 0x6057, 0x5147, 0x692e, 0x683d, 0x7a44, 0x624f, 0x7a45, 0x7938, 0x5c60, 0x7b30, 0x5829, 0x655f, 0x7927, 0x766e, 0x764c, 0x6278, 0x6c71, 0x5a60, 0x7152, 0x524c, 0x4f4b, 0x4a3d, 0x5d3f, 0x766f, 0x5e79, 0x7a34, 0x552d, 0x7167, 0x5e3e, 0x5c40, 0x5148, 0x5149, 0x783e, 0x4b76, 0x5479, 0x7562, 0x6153, 0x5869, 0x787e, 0x4f4c, 0x7d24, 0x4e76, 0x7a50, 0x4c73, 0x663e, 0x762e, 0x5570, 0x514a, 0x7c3e, 0x5571, 0x4d69, 0x7a35, 0x6250, 0x7477, 0x4d54, 0x6723, 0x5b25, 0x6251, 0x5722, 0x7763, 0x6a26, 0x5021, 0x4e5a, 0x7b6b, 0x5b26, 0x5b5e, 0x5865, 0x6a60, 0x582a, 0x6560, 0x565b, 0x6f46, 0x786a, 0x6455, 0x4e77, 0x6058, 0x576f, 0x746d, 0x4d66, 0x4c74, 0x7563, 0x644a, 0x5c61, 0x7948, 0x7c3f, 0x6827, 0x5844, 0x4b3e, 0x5c2e, 0x5777, 0x7068, 0x5d40, 0x4f4d, 0x5c73, 0x5930, 0x6669, 0x643c, 0x6a44, 0x646c, 0x6465, 0x7b78, 0x4c3b, 0x643d, 0x4d5c, 0x5977, 0x5d5f, 0x6d4e, 0x5950, 0x6523, 0x794d, 0x4d2e, 0x4f4e, 0x762f, 0x7d53, 0x6b6d, 0x565c, 0x6524, 0x5536, 0x565d, 0x7969, 0x6724, 0x5663, 0x514b, 0x5664, 0x5572, 0x5e7a, 0x5778, 0x586a, 0x4f55, 0x587d, 0x582b, 0x7d4b, 0x7c5c, 0x6028, 0x5573, 0x7d59, 0x4c23, 0x5979, 0x536a, 0x7575, 0x6f47, 0x535a, 0x5a3d, 0x6828, 0x5c2f, 0x7023, 0x4d55, 0x6029, 0x5e2c, 0x703a, 0x6e31, 0x6e32, 0x764d, 0x6e52, 0x5646, 0x6065, 0x733b, 0x6561, 0x644b, 0x5723, 0x5b42, 0x4a7e, 0x4f4f, 0x3021, 0x3022, 0x3023, 0x3024, 0x3025, 0x3026, 0x3027, 0x3028, 0x3029, 0x302a, 0x302b, 0x302c, 0x302d, 0x302e, 0x302f, 0x3030, 0x3031, 0x3032, 0x3033, 0x3034, 0x3035, 0x3036, 0x3037, 0x3038, 0x3039, 0x303a, 0x303b, 0x303c, 0x303d, 0x303e, 0x303f, 0x3040, 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, 0x304a, 0x304b, 0x304c, 0x304d, 0x304e, 0x304f, 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e, 0x305f, 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068, 0x3069, 0x306a, 0x306b, 0x306c, 0x306d, 0x306e, 0x306f, 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, 0x3078, 0x3079, 0x307a, 0x307b, 0x307c, 0x307d, 0x307e, 0x3121, 0x3122, 0x3123, 0x3124, 0x3125, 0x3126, 0x3127, 0x3128, 0x3129, 0x312a, 0x312b, 0x312c, 0x312d, 0x312e, 0x312f, 0x3130, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f, 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147, 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160, 0x3161, 0x3162, 0x3163, 0x3164, 0x3165, 0x3166, 0x3167, 0x3168, 0x3169, 0x316a, 0x316b, 0x316c, 0x316d, 0x316e, 0x316f, 0x3170, 0x3171, 0x3172, 0x3173, 0x3174, 0x3175, 0x3176, 0x3177, 0x3178, 0x3179, 0x317a, 0x317b, 0x317c, 0x317d, 0x317e, 0x3221, 0x3222, 0x3223, 0x3224, 0x3225, 0x3226, 0x3227, 0x3228, 0x3229, 0x322a, 0x322b, 0x322c, 0x322d, 0x322e, 0x322f, 0x3230, 0x3231, 0x3232, 0x3233, 0x3234, 0x3235, 0x3236, 0x3237, 0x3238, 0x3239, 0x323a, 0x323b, 0x323c, 0x323d, 0x323e, 0x323f, 0x3240, 0x3241, 0x3242, 0x3243, 0x3244, 0x3245, 0x3246, 0x3247, 0x3248, 0x3249, 0x324a, 0x324b, 0x324c, 0x324d, 0x324e, 0x324f, 0x3250, 0x3251, 0x3252, 0x3253, 0x3254, 0x3255, 0x3256, 0x3257, 0x3258, 0x3259, 0x325a, 0x325b, 0x325c, 0x325d, 0x325e, 0x325f, 0x3260, 0x3261, 0x3262, 0x3263, 0x3264, 0x3265, 0x3266, 0x3267, 0x3268, 0x3269, 0x326a, 0x326b, 0x326c, 0x326d, 0x326e, 0x326f, 0x3270, 0x3271, 0x3272, 0x3273, 0x3274, 0x3275, 0x3276, 0x3277, 0x3278, 0x3279, 0x327a, 0x327b, 0x327c, 0x327d, 0x327e, 0x3321, 0x3322, 0x3323, 0x3324, 0x3325, 0x3326, 0x3327, 0x3328, 0x3329, 0x332a, 0x332b, 0x332c, 0x332d, 0x332e, 0x332f, 0x3330, 0x3331, 0x3332, 0x3333, 0x3334, 0x3335, 0x3336, 0x3337, 0x3338, 0x3339, 0x333a, 0x333b, 0x333c, 0x333d, 0x333e, 0x333f, 0x3340, 0x3341, 0x3342, 0x3343, 0x3344, 0x3345, 0x3346, 0x3347, 0x3348, 0x3349, 0x334a, 0x334b, 0x334c, 0x334d, 0x334e, 0x334f, 0x3350, 0x3351, 0x3352, 0x3353, 0x3354, 0x3355, 0x3356, 0x3357, 0x3358, 0x3359, 0x335a, 0x335b, 0x335c, 0x335d, 0x335e, 0x335f, 0x3360, 0x3361, 0x3362, 0x3363, 0x3364, 0x3365, 0x3366, 0x3367, 0x3368, 0x3369, 0x336a, 0x336b, 0x336c, 0x336d, 0x336e, 0x336f, 0x3370, 0x3371, 0x3372, 0x3373, 0x3374, 0x3375, 0x3376, 0x3377, 0x3378, 0x3379, 0x337a, 0x337b, 0x337c, 0x337d, 0x337e, 0x3421, 0x3422, 0x3423, 0x3424, 0x3425, 0x3426, 0x3427, 0x3428, 0x3429, 0x342a, 0x342b, 0x342c, 0x342d, 0x342e, 0x342f, 0x3430, 0x3431, 0x3432, 0x3433, 0x3434, 0x3435, 0x3436, 0x3437, 0x3438, 0x3439, 0x343a, 0x343b, 0x343c, 0x343d, 0x343e, 0x343f, 0x3440, 0x3441, 0x3442, 0x3443, 0x3444, 0x3445, 0x3446, 0x3447, 0x3448, 0x3449, 0x344a, 0x344b, 0x344c, 0x344d, 0x344e, 0x344f, 0x3450, 0x3451, 0x3452, 0x3453, 0x3454, 0x3455, 0x3456, 0x3457, 0x3458, 0x3459, 0x345a, 0x345b, 0x345c, 0x345d, 0x345e, 0x345f, 0x3460, 0x3461, 0x3462, 0x3463, 0x3464, 0x3465, 0x3466, 0x3467, 0x3468, 0x3469, 0x346a, 0x346b, 0x346c, 0x346d, 0x346e, 0x346f, 0x3470, 0x3471, 0x3472, 0x3473, 0x3474, 0x3475, 0x3476, 0x3477, 0x3478, 0x3479, 0x347a, 0x347b, 0x347c, 0x347d, 0x347e, 0x3521, 0x3522, 0x3523, 0x3524, 0x3525, 0x3526, 0x3527, 0x3528, 0x3529, 0x352a, 0x352b, 0x352c, 0x352d, 0x352e, 0x352f, 0x3530, 0x3531, 0x3532, 0x3533, 0x3534, 0x3535, 0x3536, 0x3537, 0x3538, 0x3539, 0x353a, 0x353b, 0x353c, 0x353d, 0x353e, 0x353f, 0x3540, 0x3541, 0x3542, 0x3543, 0x3544, 0x3545, 0x3546, 0x3547, 0x3548, 0x3549, 0x354a, 0x354b, 0x354c, 0x354d, 0x354e, 0x354f, 0x3550, 0x3551, 0x3552, 0x3553, 0x3554, 0x3555, 0x3556, 0x3557, 0x3558, 0x3559, 0x355a, 0x355b, 0x355c, 0x355d, 0x355e, 0x355f, 0x3560, 0x3561, 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567, 0x3568, 0x3569, 0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f, 0x3570, 0x3571, 0x3572, 0x3573, 0x3574, 0x3575, 0x3576, 0x3577, 0x3578, 0x3579, 0x357a, 0x357b, 0x357c, 0x357d, 0x357e, 0x3621, 0x3622, 0x3623, 0x3624, 0x3625, 0x3626, 0x3627, 0x3628, 0x3629, 0x362a, 0x362b, 0x362c, 0x362d, 0x362e, 0x362f, 0x3630, 0x3631, 0x3632, 0x3633, 0x3634, 0x3635, 0x3636, 0x3637, 0x3638, 0x3639, 0x363a, 0x363b, 0x363c, 0x363d, 0x363e, 0x363f, 0x3640, 0x3641, 0x3642, 0x3643, 0x3644, 0x3645, 0x3646, 0x3647, 0x3648, 0x3649, 0x364a, 0x364b, 0x364c, 0x364d, 0x364e, 0x364f, 0x3650, 0x3651, 0x3652, 0x3653, 0x3654, 0x3655, 0x3656, 0x3657, 0x3658, 0x3659, 0x365a, 0x365b, 0x365c, 0x365d, 0x365e, 0x365f, 0x3660, 0x3661, 0x3662, 0x3663, 0x3664, 0x3665, 0x3666, 0x3667, 0x3668, 0x3669, 0x366a, 0x366b, 0x366c, 0x366d, 0x366e, 0x366f, 0x3670, 0x3671, 0x3672, 0x3673, 0x3674, 0x3675, 0x3676, 0x3677, 0x3678, 0x3679, 0x367a, 0x367b, 0x367c, 0x367d, 0x367e, 0x3721, 0x3722, 0x3723, 0x3724, 0x3725, 0x3726, 0x3727, 0x3728, 0x3729, 0x372a, 0x372b, 0x372c, 0x372d, 0x372e, 0x372f, 0x3730, 0x3731, 0x3732, 0x3733, 0x3734, 0x3735, 0x3736, 0x3737, 0x3738, 0x3739, 0x373a, 0x373b, 0x373c, 0x373d, 0x373e, 0x373f, 0x3740, 0x3741, 0x3742, 0x3743, 0x3744, 0x3745, 0x3746, 0x3747, 0x3748, 0x3749, 0x374a, 0x374b, 0x374c, 0x374d, 0x374e, 0x374f, 0x3750, 0x3751, 0x3752, 0x3753, 0x3754, 0x3755, 0x3756, 0x3757, 0x3758, 0x3759, 0x375a, 0x375b, 0x375c, 0x375d, 0x375e, 0x375f, 0x3760, 0x3761, 0x3762, 0x3763, 0x3764, 0x3765, 0x3766, 0x3767, 0x3768, 0x3769, 0x376a, 0x376b, 0x376c, 0x376d, 0x376e, 0x376f, 0x3770, 0x3771, 0x3772, 0x3773, 0x3774, 0x3775, 0x3776, 0x3777, 0x3778, 0x3779, 0x377a, 0x377b, 0x377c, 0x377d, 0x377e, 0x3821, 0x3822, 0x3823, 0x3824, 0x3825, 0x3826, 0x3827, 0x3828, 0x3829, 0x382a, 0x382b, 0x382c, 0x382d, 0x382e, 0x382f, 0x3830, 0x3831, 0x3832, 0x3833, 0x3834, 0x3835, 0x3836, 0x3837, 0x3838, 0x3839, 0x383a, 0x383b, 0x383c, 0x383d, 0x383e, 0x383f, 0x3840, 0x3841, 0x3842, 0x3843, 0x3844, 0x3845, 0x3846, 0x3847, 0x3848, 0x3849, 0x384a, 0x384b, 0x384c, 0x384d, 0x384e, 0x384f, 0x3850, 0x3851, 0x3852, 0x3853, 0x3854, 0x3855, 0x3856, 0x3857, 0x3858, 0x3859, 0x385a, 0x385b, 0x385c, 0x385d, 0x385e, 0x385f, 0x3860, 0x3861, 0x3862, 0x3863, 0x3864, 0x3865, 0x3866, 0x3867, 0x3868, 0x3869, 0x386a, 0x386b, 0x386c, 0x386d, 0x386e, 0x386f, 0x3870, 0x3871, 0x3872, 0x3873, 0x3874, 0x3875, 0x3876, 0x3877, 0x3878, 0x3879, 0x387a, 0x387b, 0x387c, 0x387d, 0x387e, 0x3921, 0x3922, 0x3923, 0x3924, 0x3925, 0x3926, 0x3927, 0x3928, 0x3929, 0x392a, 0x392b, 0x392c, 0x392d, 0x392e, 0x392f, 0x3930, 0x3931, 0x3932, 0x3933, 0x3934, 0x3935, 0x3936, 0x3937, 0x3938, 0x3939, 0x393a, 0x393b, 0x393c, 0x393d, 0x393e, 0x393f, 0x3940, 0x3941, 0x3942, 0x3943, 0x3944, 0x3945, 0x3946, 0x3947, 0x3948, 0x3949, 0x394a, 0x394b, 0x394c, 0x394d, 0x394e, 0x394f, 0x3950, 0x3951, 0x3952, 0x3953, 0x3954, 0x3955, 0x3956, 0x3957, 0x3958, 0x3959, 0x395a, 0x395b, 0x395c, 0x395d, 0x395e, 0x395f, 0x3960, 0x3961, 0x3962, 0x3963, 0x3964, 0x3965, 0x3966, 0x3967, 0x3968, 0x3969, 0x396a, 0x396b, 0x396c, 0x396d, 0x396e, 0x396f, 0x3970, 0x3971, 0x3972, 0x3973, 0x3974, 0x3975, 0x3976, 0x3977, 0x3978, 0x3979, 0x397a, 0x397b, 0x397c, 0x397d, 0x397e, 0x3a21, 0x3a22, 0x3a23, 0x3a24, 0x3a25, 0x3a26, 0x3a27, 0x3a28, 0x3a29, 0x3a2a, 0x3a2b, 0x3a2c, 0x3a2d, 0x3a2e, 0x3a2f, 0x3a30, 0x3a31, 0x3a32, 0x3a33, 0x3a34, 0x3a35, 0x3a36, 0x3a37, 0x3a38, 0x3a39, 0x3a3a, 0x3a3b, 0x3a3c, 0x3a3d, 0x3a3e, 0x3a3f, 0x3a40, 0x3a41, 0x3a42, 0x3a43, 0x3a44, 0x3a45, 0x3a46, 0x3a47, 0x3a48, 0x3a49, 0x3a4a, 0x3a4b, 0x3a4c, 0x3a4d, 0x3a4e, 0x3a4f, 0x3a50, 0x3a51, 0x3a52, 0x3a53, 0x3a54, 0x3a55, 0x3a56, 0x3a57, 0x3a58, 0x3a59, 0x3a5a, 0x3a5b, 0x3a5c, 0x3a5d, 0x3a5e, 0x3a5f, 0x3a60, 0x3a61, 0x3a62, 0x3a63, 0x3a64, 0x3a65, 0x3a66, 0x3a67, 0x3a68, 0x3a69, 0x3a6a, 0x3a6b, 0x3a6c, 0x3a6d, 0x3a6e, 0x3a6f, 0x3a70, 0x3a71, 0x3a72, 0x3a73, 0x3a74, 0x3a75, 0x3a76, 0x3a77, 0x3a78, 0x3a79, 0x3a7a, 0x3a7b, 0x3a7c, 0x3a7d, 0x3a7e, 0x3b21, 0x3b22, 0x3b23, 0x3b24, 0x3b25, 0x3b26, 0x3b27, 0x3b28, 0x3b29, 0x3b2a, 0x3b2b, 0x3b2c, 0x3b2d, 0x3b2e, 0x3b2f, 0x3b30, 0x3b31, 0x3b32, 0x3b33, 0x3b34, 0x3b35, 0x3b36, 0x3b37, 0x3b38, 0x3b39, 0x3b3a, 0x3b3b, 0x3b3c, 0x3b3d, 0x3b3e, 0x3b3f, 0x3b40, 0x3b41, 0x3b42, 0x3b43, 0x3b44, 0x3b45, 0x3b46, 0x3b47, 0x3b48, 0x3b49, 0x3b4a, 0x3b4b, 0x3b4c, 0x3b4d, 0x3b4e, 0x3b4f, 0x3b50, 0x3b51, 0x3b52, 0x3b53, 0x3b54, 0x3b55, 0x3b56, 0x3b57, 0x3b58, 0x3b59, 0x3b5a, 0x3b5b, 0x3b5c, 0x3b5d, 0x3b5e, 0x3b5f, 0x3b60, 0x3b61, 0x3b62, 0x3b63, 0x3b64, 0x3b65, 0x3b66, 0x3b67, 0x3b68, 0x3b69, 0x3b6a, 0x3b6b, 0x3b6c, 0x3b6d, 0x3b6e, 0x3b6f, 0x3b70, 0x3b71, 0x3b72, 0x3b73, 0x3b74, 0x3b75, 0x3b76, 0x3b77, 0x3b78, 0x3b79, 0x3b7a, 0x3b7b, 0x3b7c, 0x3b7d, 0x3b7e, 0x3c21, 0x3c22, 0x3c23, 0x3c24, 0x3c25, 0x3c26, 0x3c27, 0x3c28, 0x3c29, 0x3c2a, 0x3c2b, 0x3c2c, 0x3c2d, 0x3c2e, 0x3c2f, 0x3c30, 0x3c31, 0x3c32, 0x3c33, 0x3c34, 0x3c35, 0x3c36, 0x3c37, 0x3c38, 0x3c39, 0x3c3a, 0x3c3b, 0x3c3c, 0x3c3d, 0x3c3e, 0x3c3f, 0x3c40, 0x3c41, 0x3c42, 0x3c43, 0x3c44, 0x3c45, 0x3c46, 0x3c47, 0x3c48, 0x3c49, 0x3c4a, 0x3c4b, 0x3c4c, 0x3c4d, 0x3c4e, 0x3c4f, 0x3c50, 0x3c51, 0x3c52, 0x3c53, 0x3c54, 0x3c55, 0x3c56, 0x3c57, 0x3c58, 0x3c59, 0x3c5a, 0x3c5b, 0x3c5c, 0x3c5d, 0x3c5e, 0x3c5f, 0x3c60, 0x3c61, 0x3c62, 0x3c63, 0x3c64, 0x3c65, 0x3c66, 0x3c67, 0x3c68, 0x3c69, 0x3c6a, 0x3c6b, 0x3c6c, 0x3c6d, 0x3c6e, 0x3c6f, 0x3c70, 0x3c71, 0x3c72, 0x3c73, 0x3c74, 0x3c75, 0x3c76, 0x3c77, 0x3c78, 0x3c79, 0x3c7a, 0x3c7b, 0x3c7c, 0x3c7d, 0x3c7e, 0x3d21, 0x3d22, 0x3d23, 0x3d24, 0x3d25, 0x3d26, 0x3d27, 0x3d28, 0x3d29, 0x3d2a, 0x3d2b, 0x3d2c, 0x3d2d, 0x3d2e, 0x3d2f, 0x3d30, 0x3d31, 0x3d32, 0x3d33, 0x3d34, 0x3d35, 0x3d36, 0x3d37, 0x3d38, 0x3d39, 0x3d3a, 0x3d3b, 0x3d3c, 0x3d3d, 0x3d3e, 0x3d3f, 0x3d40, 0x3d41, 0x3d42, 0x3d43, 0x3d44, 0x3d45, 0x3d46, 0x3d47, 0x3d48, 0x3d49, 0x3d4a, 0x3d4b, 0x3d4c, 0x3d4d, 0x3d4e, 0x3d4f, 0x3d50, 0x3d51, 0x3d52, 0x3d53, 0x3d54, 0x3d55, 0x3d56, 0x3d57, 0x3d58, 0x3d59, 0x3d5a, 0x3d5b, 0x3d5c, 0x3d5d, 0x3d5e, 0x3d5f, 0x3d60, 0x3d61, 0x3d62, 0x3d63, 0x3d64, 0x3d65, 0x3d66, 0x3d67, 0x3d68, 0x3d69, 0x3d6a, 0x3d6b, 0x3d6c, 0x3d6d, 0x3d6e, 0x3d6f, 0x3d70, 0x3d71, 0x3d72, 0x3d73, 0x3d74, 0x3d75, 0x3d76, 0x3d77, 0x3d78, 0x3d79, 0x3d7a, 0x3d7b, 0x3d7c, 0x3d7d, 0x3d7e, 0x3e21, 0x3e22, 0x3e23, 0x3e24, 0x3e25, 0x3e26, 0x3e27, 0x3e28, 0x3e29, 0x3e2a, 0x3e2b, 0x3e2c, 0x3e2d, 0x3e2e, 0x3e2f, 0x3e30, 0x3e31, 0x3e32, 0x3e33, 0x3e34, 0x3e35, 0x3e36, 0x3e37, 0x3e38, 0x3e39, 0x3e3a, 0x3e3b, 0x3e3c, 0x3e3d, 0x3e3e, 0x3e3f, 0x3e40, 0x3e41, 0x3e42, 0x3e43, 0x3e44, 0x3e45, 0x3e46, 0x3e47, 0x3e48, 0x3e49, 0x3e4a, 0x3e4b, 0x3e4c, 0x3e4d, 0x3e4e, 0x3e4f, 0x3e50, 0x3e51, 0x3e52, 0x3e53, 0x3e54, 0x3e55, 0x3e56, 0x3e57, 0x3e58, 0x3e59, 0x3e5a, 0x3e5b, 0x3e5c, 0x3e5d, 0x3e5e, 0x3e5f, 0x3e60, 0x3e61, 0x3e62, 0x3e63, 0x3e64, 0x3e65, 0x3e66, 0x3e67, 0x3e68, 0x3e69, 0x3e6a, 0x3e6b, 0x3e6c, 0x3e6d, 0x3e6e, 0x3e6f, 0x3e70, 0x3e71, 0x3e72, 0x3e73, 0x3e74, 0x3e75, 0x3e76, 0x3e77, 0x3e78, 0x3e79, 0x3e7a, 0x3e7b, 0x3e7c, 0x3e7d, 0x3e7e, 0x3f21, 0x3f22, 0x3f23, 0x3f24, 0x3f25, 0x3f26, 0x3f27, 0x3f28, 0x3f29, 0x3f2a, 0x3f2b, 0x3f2c, 0x3f2d, 0x3f2e, 0x3f2f, 0x3f30, 0x3f31, 0x3f32, 0x3f33, 0x3f34, 0x3f35, 0x3f36, 0x3f37, 0x3f38, 0x3f39, 0x3f3a, 0x3f3b, 0x3f3c, 0x3f3d, 0x3f3e, 0x3f3f, 0x3f40, 0x3f41, 0x3f42, 0x3f43, 0x3f44, 0x3f45, 0x3f46, 0x3f47, 0x3f48, 0x3f49, 0x3f4a, 0x3f4b, 0x3f4c, 0x3f4d, 0x3f4e, 0x3f4f, 0x3f50, 0x3f51, 0x3f52, 0x3f53, 0x3f54, 0x3f55, 0x3f56, 0x3f57, 0x3f58, 0x3f59, 0x3f5a, 0x3f5b, 0x3f5c, 0x3f5d, 0x3f5e, 0x3f5f, 0x3f60, 0x3f61, 0x3f62, 0x3f63, 0x3f64, 0x3f65, 0x3f66, 0x3f67, 0x3f68, 0x3f69, 0x3f6a, 0x3f6b, 0x3f6c, 0x3f6d, 0x3f6e, 0x3f6f, 0x3f70, 0x3f71, 0x3f72, 0x3f73, 0x3f74, 0x3f75, 0x3f76, 0x3f77, 0x3f78, 0x3f79, 0x3f7a, 0x3f7b, 0x3f7c, 0x3f7d, 0x3f7e, 0x4021, 0x4022, 0x4023, 0x4024, 0x4025, 0x4026, 0x4027, 0x4028, 0x4029, 0x402a, 0x402b, 0x402c, 0x402d, 0x402e, 0x402f, 0x4030, 0x4031, 0x4032, 0x4033, 0x4034, 0x4035, 0x4036, 0x4037, 0x4038, 0x4039, 0x403a, 0x403b, 0x403c, 0x403d, 0x403e, 0x403f, 0x4040, 0x4041, 0x4042, 0x4043, 0x4044, 0x4045, 0x4046, 0x4047, 0x4048, 0x4049, 0x404a, 0x404b, 0x404c, 0x404d, 0x404e, 0x404f, 0x4050, 0x4051, 0x4052, 0x4053, 0x4054, 0x4055, 0x4056, 0x4057, 0x4058, 0x4059, 0x405a, 0x405b, 0x405c, 0x405d, 0x405e, 0x405f, 0x4060, 0x4061, 0x4062, 0x4063, 0x4064, 0x4065, 0x4066, 0x4067, 0x4068, 0x4069, 0x406a, 0x406b, 0x406c, 0x406d, 0x406e, 0x406f, 0x4070, 0x4071, 0x4072, 0x4073, 0x4074, 0x4075, 0x4076, 0x4077, 0x4078, 0x4079, 0x407a, 0x407b, 0x407c, 0x407d, 0x407e, 0x4121, 0x4122, 0x4123, 0x4124, 0x4125, 0x4126, 0x4127, 0x4128, 0x4129, 0x412a, 0x412b, 0x412c, 0x412d, 0x412e, 0x412f, 0x4130, 0x4131, 0x4132, 0x4133, 0x4134, 0x4135, 0x4136, 0x4137, 0x4138, 0x4139, 0x413a, 0x413b, 0x413c, 0x413d, 0x413e, 0x413f, 0x4140, 0x4141, 0x4142, 0x4143, 0x4144, 0x4145, 0x4146, 0x4147, 0x4148, 0x4149, 0x414a, 0x414b, 0x414c, 0x414d, 0x414e, 0x414f, 0x4150, 0x4151, 0x4152, 0x4153, 0x4154, 0x4155, 0x4156, 0x4157, 0x4158, 0x4159, 0x415a, 0x415b, 0x415c, 0x415d, 0x415e, 0x415f, 0x4160, 0x4161, 0x4162, 0x4163, 0x4164, 0x4165, 0x4166, 0x4167, 0x4168, 0x4169, 0x416a, 0x416b, 0x416c, 0x416d, 0x416e, 0x416f, 0x4170, 0x4171, 0x4172, 0x4173, 0x4174, 0x4175, 0x4176, 0x4177, 0x4178, 0x4179, 0x417a, 0x417b, 0x417c, 0x417d, 0x417e, 0x4221, 0x4222, 0x4223, 0x4224, 0x4225, 0x4226, 0x4227, 0x4228, 0x4229, 0x422a, 0x422b, 0x422c, 0x422d, 0x422e, 0x422f, 0x4230, 0x4231, 0x4232, 0x4233, 0x4234, 0x4235, 0x4236, 0x4237, 0x4238, 0x4239, 0x423a, 0x423b, 0x423c, 0x423d, 0x423e, 0x423f, 0x4240, 0x4241, 0x4242, 0x4243, 0x4244, 0x4245, 0x4246, 0x4247, 0x4248, 0x4249, 0x424a, 0x424b, 0x424c, 0x424d, 0x424e, 0x424f, 0x4250, 0x4251, 0x4252, 0x4253, 0x4254, 0x4255, 0x4256, 0x4257, 0x4258, 0x4259, 0x425a, 0x425b, 0x425c, 0x425d, 0x425e, 0x425f, 0x4260, 0x4261, 0x4262, 0x4263, 0x4264, 0x4265, 0x4266, 0x4267, 0x4268, 0x4269, 0x426a, 0x426b, 0x426c, 0x426d, 0x426e, 0x426f, 0x4270, 0x4271, 0x4272, 0x4273, 0x4274, 0x4275, 0x4276, 0x4277, 0x4278, 0x4279, 0x427a, 0x427b, 0x427c, 0x427d, 0x427e, 0x4321, 0x4322, 0x4323, 0x4324, 0x4325, 0x4326, 0x4327, 0x4328, 0x4329, 0x432a, 0x432b, 0x432c, 0x432d, 0x432e, 0x432f, 0x4330, 0x4331, 0x4332, 0x4333, 0x4334, 0x4335, 0x4336, 0x4337, 0x4338, 0x4339, 0x433a, 0x433b, 0x433c, 0x433d, 0x433e, 0x433f, 0x4340, 0x4341, 0x4342, 0x4343, 0x4344, 0x4345, 0x4346, 0x4347, 0x4348, 0x4349, 0x434a, 0x434b, 0x434c, 0x434d, 0x434e, 0x434f, 0x4350, 0x4351, 0x4352, 0x4353, 0x4354, 0x4355, 0x4356, 0x4357, 0x4358, 0x4359, 0x435a, 0x435b, 0x435c, 0x435d, 0x435e, 0x435f, 0x4360, 0x4361, 0x4362, 0x4363, 0x4364, 0x4365, 0x4366, 0x4367, 0x4368, 0x4369, 0x436a, 0x436b, 0x436c, 0x436d, 0x436e, 0x436f, 0x4370, 0x4371, 0x4372, 0x4373, 0x4374, 0x4375, 0x4376, 0x4377, 0x4378, 0x4379, 0x437a, 0x437b, 0x437c, 0x437d, 0x437e, 0x4421, 0x4422, 0x4423, 0x4424, 0x4425, 0x4426, 0x4427, 0x4428, 0x4429, 0x442a, 0x442b, 0x442c, 0x442d, 0x442e, 0x442f, 0x4430, 0x4431, 0x4432, 0x4433, 0x4434, 0x4435, 0x4436, 0x4437, 0x4438, 0x4439, 0x443a, 0x443b, 0x443c, 0x443d, 0x443e, 0x443f, 0x4440, 0x4441, 0x4442, 0x4443, 0x4444, 0x4445, 0x4446, 0x4447, 0x4448, 0x4449, 0x444a, 0x444b, 0x444c, 0x444d, 0x444e, 0x444f, 0x4450, 0x4451, 0x4452, 0x4453, 0x4454, 0x4455, 0x4456, 0x4457, 0x4458, 0x4459, 0x445a, 0x445b, 0x445c, 0x445d, 0x445e, 0x445f, 0x4460, 0x4461, 0x4462, 0x4463, 0x4464, 0x4465, 0x4466, 0x4467, 0x4468, 0x4469, 0x446a, 0x446b, 0x446c, 0x446d, 0x446e, 0x446f, 0x4470, 0x4471, 0x4472, 0x4473, 0x4474, 0x4475, 0x4476, 0x4477, 0x4478, 0x4479, 0x447a, 0x447b, 0x447c, 0x447d, 0x447e, 0x4521, 0x4522, 0x4523, 0x4524, 0x4525, 0x4526, 0x4527, 0x4528, 0x4529, 0x452a, 0x452b, 0x452c, 0x452d, 0x452e, 0x452f, 0x4530, 0x4531, 0x4532, 0x4533, 0x4534, 0x4535, 0x4536, 0x4537, 0x4538, 0x4539, 0x453a, 0x453b, 0x453c, 0x453d, 0x453e, 0x453f, 0x4540, 0x4541, 0x4542, 0x4543, 0x4544, 0x4545, 0x4546, 0x4547, 0x4548, 0x4549, 0x454a, 0x454b, 0x454c, 0x454d, 0x454e, 0x454f, 0x4550, 0x4551, 0x4552, 0x4553, 0x4554, 0x4555, 0x4556, 0x4557, 0x4558, 0x4559, 0x455a, 0x455b, 0x455c, 0x455d, 0x455e, 0x455f, 0x4560, 0x4561, 0x4562, 0x4563, 0x4564, 0x4565, 0x4566, 0x4567, 0x4568, 0x4569, 0x456a, 0x456b, 0x456c, 0x456d, 0x456e, 0x456f, 0x4570, 0x4571, 0x4572, 0x4573, 0x4574, 0x4575, 0x4576, 0x4577, 0x4578, 0x4579, 0x457a, 0x457b, 0x457c, 0x457d, 0x457e, 0x4621, 0x4622, 0x4623, 0x4624, 0x4625, 0x4626, 0x4627, 0x4628, 0x4629, 0x462a, 0x462b, 0x462c, 0x462d, 0x462e, 0x462f, 0x4630, 0x4631, 0x4632, 0x4633, 0x4634, 0x4635, 0x4636, 0x4637, 0x4638, 0x4639, 0x463a, 0x463b, 0x463c, 0x463d, 0x463e, 0x463f, 0x4640, 0x4641, 0x4642, 0x4643, 0x4644, 0x4645, 0x4646, 0x4647, 0x4648, 0x4649, 0x464a, 0x464b, 0x464c, 0x464d, 0x464e, 0x464f, 0x4650, 0x4651, 0x4652, 0x4653, 0x4654, 0x4655, 0x4656, 0x4657, 0x4658, 0x4659, 0x465a, 0x465b, 0x465c, 0x465d, 0x465e, 0x465f, 0x4660, 0x4661, 0x4662, 0x4663, 0x4664, 0x4665, 0x4666, 0x4667, 0x4668, 0x4669, 0x466a, 0x466b, 0x466c, 0x466d, 0x466e, 0x466f, 0x4670, 0x4671, 0x4672, 0x4673, 0x4674, 0x4675, 0x4676, 0x4677, 0x4678, 0x4679, 0x467a, 0x467b, 0x467c, 0x467d, 0x467e, 0x4721, 0x4722, 0x4723, 0x4724, 0x4725, 0x4726, 0x4727, 0x4728, 0x4729, 0x472a, 0x472b, 0x472c, 0x472d, 0x472e, 0x472f, 0x4730, 0x4731, 0x4732, 0x4733, 0x4734, 0x4735, 0x4736, 0x4737, 0x4738, 0x4739, 0x473a, 0x473b, 0x473c, 0x473d, 0x473e, 0x473f, 0x4740, 0x4741, 0x4742, 0x4743, 0x4744, 0x4745, 0x4746, 0x4747, 0x4748, 0x4749, 0x474a, 0x474b, 0x474c, 0x474d, 0x474e, 0x474f, 0x4750, 0x4751, 0x4752, 0x4753, 0x4754, 0x4755, 0x4756, 0x4757, 0x4758, 0x4759, 0x475a, 0x475b, 0x475c, 0x475d, 0x475e, 0x475f, 0x4760, 0x4761, 0x4762, 0x4763, 0x4764, 0x4765, 0x4766, 0x4767, 0x4768, 0x4769, 0x476a, 0x476b, 0x476c, 0x476d, 0x476e, 0x476f, 0x4770, 0x4771, 0x4772, 0x4773, 0x4774, 0x4775, 0x4776, 0x4777, 0x4778, 0x4779, 0x477a, 0x477b, 0x477c, 0x477d, 0x477e, 0x4821, 0x4822, 0x4823, 0x4824, 0x4825, 0x4826, 0x4827, 0x4828, 0x4829, 0x482a, 0x482b, 0x482c, 0x482d, 0x482e, 0x482f, 0x4830, 0x4831, 0x4832, 0x4833, 0x4834, 0x4835, 0x4836, 0x4837, 0x4838, 0x4839, 0x483a, 0x483b, 0x483c, 0x483d, 0x483e, 0x483f, 0x4840, 0x4841, 0x4842, 0x4843, 0x4844, 0x4845, 0x4846, 0x4847, 0x4848, 0x4849, 0x484a, 0x484b, 0x484c, 0x484d, 0x484e, 0x484f, 0x4850, 0x4851, 0x4852, 0x4853, 0x4854, 0x4855, 0x4856, 0x4857, 0x4858, 0x4859, 0x485a, 0x485b, 0x485c, 0x485d, 0x485e, 0x485f, 0x4860, 0x4861, 0x4862, 0x4863, 0x4864, 0x4865, 0x4866, 0x4867, 0x4868, 0x4869, 0x486a, 0x486b, 0x486c, 0x486d, 0x486e, 0x486f, 0x4870, 0x4871, 0x4872, 0x4873, 0x4874, 0x4875, 0x4876, 0x4877, 0x4878, 0x4879, 0x487a, 0x487b, 0x487c, 0x487d, 0x487e, 0x4b50, 0x4b56, 0x4b67, 0x4d4f, 0x4d68, 0x4e2d, 0x4f7b, 0x5022, 0x5038, 0x5050, 0x505d, 0x5154, 0x5155, 0x5158, 0x515b, 0x515c, 0x515d, 0x515e, 0x515f, 0x5160, 0x5162, 0x5163, 0x5164, 0x5165, 0x5166, 0x5168, 0x5169, 0x516a, 0x516b, 0x516d, 0x516f, 0x5170, 0x5172, 0x5176, 0x517a, 0x517c, 0x517d, 0x517e, 0x5222, 0x5223, 0x5227, 0x5228, 0x5229, 0x522a, 0x522b, 0x522d, 0x5232, 0x523e, 0x5242, 0x5243, 0x5244, 0x5246, 0x5247, 0x5248, 0x5249, 0x524a, 0x524b, 0x524d, 0x524e, 0x524f, 0x5250, 0x5251, 0x5252, 0x5253, 0x5254, 0x5255, 0x5256, 0x5257, 0x5259, 0x525a, 0x525e, 0x525f, 0x5261, 0x5262, 0x5264, 0x5265, 0x5266, 0x5267, 0x5268, 0x5269, 0x526a, 0x526b, 0x5270, 0x5271, 0x5272, 0x5273, 0x5274, 0x5275, 0x5277, 0x5278, 0x5466, 0x547c, 0x5525, 0x552b, 0x552e, 0x5638, 0x564d, 0x574b, 0x5764, 0x5b45, 0x5b64, 0x5c25, 0x5d25, 0x5d55, 0x5d74, 0x5e7c, 0x5e7e, 0x5f33, 0x5f61, 0x5f68, 0x6071, 0x612d, 0x616d, 0x6375, 0x6421, 0x6429, 0x652e, 0x6531, 0x6532, 0x6539, 0x653b, 0x653c, 0x6544, 0x654e, 0x6550, 0x6552, 0x6556, 0x657a, 0x657b, 0x657c, 0x657e, 0x6621, 0x6624, 0x6627, 0x662d, 0x662f, 0x6630, 0x6631, 0x6633, 0x6637, 0x6638, 0x663c, 0x6644, 0x6646, 0x6647, 0x664a, 0x6652, 0x6656, 0x6659, 0x665c, 0x665f, 0x6661, 0x6664, 0x6665, 0x6666, 0x6668, 0x666a, 0x666b, 0x666c, 0x666f, 0x6671, 0x6672, 0x6675, 0x6676, 0x6677, 0x6679, 0x6721, 0x6726, 0x6729, 0x672a, 0x672c, 0x672d, 0x6730, 0x673f, 0x6741, 0x6746, 0x6747, 0x674b, 0x674d, 0x674f, 0x6750, 0x6753, 0x675f, 0x6764, 0x6766, 0x6777, 0x6867, 0x6868, 0x6870, 0x6871, 0x6877, 0x6879, 0x687b, 0x687e, 0x6927, 0x692c, 0x694c, 0x6977, 0x6a41, 0x6a65, 0x6a74, 0x6a77, 0x6a7c, 0x6a7e, 0x6b24, 0x6b27, 0x6b29, 0x6b2a, 0x6b3a, 0x6b3b, 0x6b3d, 0x6b41, 0x6b42, 0x6b46, 0x6b47, 0x6b4c, 0x6b4f, 0x6b50, 0x6b51, 0x6b52, 0x6b58, 0x6c26, 0x6c27, 0x6c2a, 0x6c2f, 0x6c30, 0x6c31, 0x6c32, 0x6c35, 0x6c38, 0x6c3a, 0x6c40, 0x6c41, 0x6c45, 0x6c46, 0x6c49, 0x6c4a, 0x6c55, 0x6c5d, 0x6c5e, 0x6c61, 0x6c64, 0x6c67, 0x6c68, 0x6c77, 0x6c78, 0x6c7a, 0x6d21, 0x6d22, 0x6d23, 0x6d6e, 0x6e5b, 0x723d, 0x727a, 0x7331, 0x7427, 0x746e, 0x7674, 0x7676, 0x7738, 0x7748, 0x7753, 0x785b, 0x7870, 0x7a21, 0x7a22, 0x7a66, 0x7c29, 0x2321, 0x2322, 0x2323, 0x2324, 0x2325, 0x2326, 0x2327, 0x2328, 0x2329, 0x232a, 0x232b, 0x232c, 0x232d, 0x232e, 0x232f, 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337, 0x2338, 0x2339, 0x233a, 0x233b, 0x233c, 0x233d, 0x233e, 0x233f, 0x2340, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347, 0x2348, 0x2349, 0x234a, 0x234b, 0x234c, 0x234d, 0x234e, 0x234f, 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357, 0x2358, 0x2359, 0x235a, 0x235b, 0x212c, 0x235d, 0x235e, 0x235f, 0x2360, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367, 0x2368, 0x2369, 0x236a, 0x236b, 0x236c, 0x236d, 0x236e, 0x236f, 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377, 0x2378, 0x2379, 0x237a, 0x237b, 0x237c, 0x237d, 0x2226, 0x214b, 0x214c, 0x217e, 0x237e, 0x214d, 0x235c, }; static const Summary16 ksc5601_uni2indx_page00[70] = { /* 0x0000 */ { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x2592 }, { 6, 0xf7df }, { 20, 0x0040 }, { 21, 0xc181 }, { 26, 0x0040 }, { 27, 0x4181 }, /* 0x0100 */ { 31, 0x0000 }, { 31, 0x0002 }, { 32, 0x00c0 }, { 34, 0x810e }, { 39, 0x0e07 }, { 45, 0x000c }, { 47, 0x00c0 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, /* 0x0200 */ { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0000 }, { 49, 0x0080 }, { 50, 0x2f01 }, { 56, 0x0000 }, { 56, 0x0000 }, /* 0x0300 */ { 56, 0x0000 }, { 56, 0x0000 }, { 56, 0x0000 }, { 56, 0x0000 }, { 56, 0x0000 }, { 56, 0x0000 }, { 56, 0x0000 }, { 56, 0x0000 }, { 56, 0x0000 }, { 56, 0xfffe }, { 71, 0x03fb }, { 80, 0xfffe }, { 95, 0x03fb }, { 104, 0x0000 }, { 104, 0x0000 }, { 104, 0x0000 }, /* 0x0400 */ { 104, 0x0002 }, { 105, 0xffff }, { 121, 0xffff }, { 137, 0xffff }, { 153, 0xffff }, { 169, 0x0002 }, }; static const Summary16 ksc5601_uni2indx_page20[103] = { /* 0x2000 */ { 170, 0x0000 }, { 170, 0x3320 }, { 175, 0x0063 }, { 179, 0x080d }, { 183, 0x0000 }, { 183, 0x0000 }, { 183, 0x0000 }, { 183, 0x8010 }, { 185, 0x001e }, { 189, 0x0000 }, { 189, 0x0000 }, { 189, 0x0000 }, { 189, 0x0000 }, { 189, 0x0000 }, { 189, 0x0000 }, { 189, 0x0000 }, /* 0x2100 */ { 189, 0x0208 }, { 191, 0x0048 }, { 193, 0x0846 }, { 197, 0x0000 }, { 197, 0x0000 }, { 197, 0x7818 }, { 203, 0x03ff }, { 213, 0x03ff }, { 223, 0x0000 }, { 223, 0x03ff }, { 233, 0x0000 }, { 233, 0x0000 }, { 233, 0x0000 }, { 233, 0x0014 }, { 235, 0x0000 }, { 235, 0x0000 }, /* 0x2200 */ { 235, 0x898d }, { 242, 0x6402 }, { 246, 0x5fa1 }, { 255, 0x3030 }, { 259, 0x0000 }, { 259, 0x0004 }, { 260, 0x0c33 }, { 266, 0x0000 }, { 266, 0x00cc }, { 270, 0x0200 }, { 271, 0x0020 }, { 272, 0x0000 }, { 272, 0x0000 }, { 272, 0x0000 }, { 272, 0x0000 }, { 272, 0x0000 }, /* 0x2300 */ { 272, 0x0000 }, { 272, 0x0004 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, /* 0x2400 */ { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x0000 }, { 273, 0x7fff }, { 288, 0xfff0 }, { 300, 0x0007 }, { 303, 0xf000 }, { 307, 0xffff }, { 323, 0x003f }, { 329, 0x0000 }, { 329, 0xffff }, { 345, 0x03ff }, { 355, 0x0000 }, /* 0x2500 */ { 355, 0xf00f }, { 363, 0xffff }, { 379, 0xffff }, { 395, 0xffff }, { 411, 0x0fff }, { 423, 0x0000 }, { 423, 0x0000 }, { 423, 0x0000 }, { 423, 0x0000 }, { 423, 0x0004 }, { 424, 0x03fb }, { 433, 0x30cc }, { 439, 0xc9c3 }, { 447, 0x0003 }, { 449, 0x0000 }, { 449, 0x0000 }, /* 0x2600 */ { 449, 0xc060 }, { 453, 0x5000 }, { 455, 0x0000 }, { 455, 0x0000 }, { 455, 0x0005 }, { 457, 0x0000 }, { 457, 0x37bb }, }; static const Summary16 ksc5601_uni2indx_page30[62] = { /* 0x3000 */ { 468, 0xff0f }, { 480, 0x003b }, { 485, 0x0000 }, { 485, 0x0000 }, { 485, 0xfffe }, { 500, 0xffff }, { 516, 0xffff }, { 532, 0xffff }, { 548, 0xffff }, { 564, 0x000f }, { 568, 0xfffe }, { 583, 0xffff }, { 599, 0xffff }, { 615, 0xffff }, { 631, 0xffff }, { 647, 0x007f }, /* 0x3100 */ { 654, 0x0000 }, { 654, 0x0000 }, { 654, 0x0000 }, { 654, 0xfffe }, { 669, 0xffff }, { 685, 0xffff }, { 701, 0xffff }, { 717, 0xffff }, { 733, 0x7fff }, { 748, 0x0000 }, { 748, 0x0000 }, { 748, 0x0000 }, { 748, 0x0000 }, { 748, 0x0000 }, { 748, 0x0000 }, { 748, 0x0000 }, /* 0x3200 */ { 748, 0xffff }, { 764, 0x1fff }, { 777, 0x0000 }, { 777, 0x0000 }, { 777, 0x0000 }, { 777, 0x0000 }, { 777, 0xffff }, { 793, 0x8fff }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, /* 0x3300 */ { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0x0000 }, { 806, 0xff1f }, { 819, 0xffff }, { 835, 0xffff }, { 851, 0xffff }, { 867, 0x87ff }, { 879, 0x3949 }, }; static const Summary16 ksc5601_uni2indx_page4e[1306] = { /* 0x4e00 */ { 886, 0x2f8b }, { 895, 0x4372 }, { 902, 0x2000 }, { 903, 0x0b04 }, { 907, 0xe82c }, { 914, 0xe340 }, { 920, 0x2800 }, { 922, 0x40c8 }, { 926, 0x5944 }, { 932, 0x4937 }, { 940, 0x7976 }, { 950, 0x0440 }, { 952, 0x2c93 }, { 959, 0xa3f0 }, { 967, 0x0038 }, { 970, 0x08c5 }, /* 0x4f00 */ { 975, 0xee02 }, { 982, 0x0003 }, { 984, 0x8000 }, { 985, 0x3550 }, { 991, 0xe1c8 }, { 998, 0x1e23 }, { 1005, 0x8200 }, { 1007, 0xc449 }, { 1013, 0xad5a }, { 1022, 0x2942 }, { 1027, 0xc000 }, { 1029, 0x8060 }, { 1032, 0x461c }, { 1038, 0xa49a }, { 1045, 0xc003 }, { 1049, 0x052a }, /* 0x5000 */ { 1054, 0x2a44 }, { 1059, 0xd646 }, { 1067, 0x3dda }, { 1077, 0x0800 }, { 1078, 0x8388 }, { 1083, 0x1420 }, { 1086, 0x0020 }, { 1087, 0x0170 }, { 1091, 0x2021 }, { 1094, 0x0302 }, { 1097, 0x3000 }, { 1099, 0x40ac }, { 1104, 0x8620 }, { 1108, 0x4462 }, { 1113, 0x20a0 }, { 1116, 0x8a00 }, /* 0x5100 */ { 1119, 0x0253 }, { 1124, 0x8004 }, { 1126, 0x0402 }, { 1128, 0x1484 }, { 1132, 0x7bfb }, { 1145, 0x1004 }, { 1147, 0x7fa4 }, { 1157, 0x11e2 }, { 1163, 0x2441 }, { 1167, 0x00a4 }, { 1170, 0x1421 }, { 1174, 0x20c0 }, { 1177, 0x3a50 }, { 1183, 0x7000 }, { 1186, 0x0002 }, { 1187, 0x2743 }, /* 0x5200 */ { 1194, 0x45c9 }, { 1201, 0x2082 }, { 1204, 0x4630 }, { 1209, 0x0fc1 }, { 1216, 0x3c88 }, { 1222, 0x2850 }, { 1226, 0x8602 }, { 1230, 0xa024 }, { 1234, 0x2388 }, { 1239, 0x8806 }, { 1243, 0x0e19 }, { 1249, 0x4000 }, { 1250, 0x22aa }, { 1256, 0xeb64 }, { 1265, 0x001c }, { 1268, 0xcd28 }, /* 0x5300 */ { 1275, 0xa120 }, { 1279, 0x02e1 }, { 1284, 0x840b }, { 1289, 0x8200 }, { 1291, 0x279b }, { 1300, 0x549e }, { 1308, 0x8141 }, { 1312, 0xa0b3 }, { 1319, 0x0010 }, { 1320, 0x8508 }, { 1324, 0x2061 }, { 1328, 0x0800 }, { 1329, 0x2f08 }, { 1335, 0x08d0 }, { 1339, 0xbe3e }, { 1350, 0x010f }, /* 0x5400 */ { 1355, 0xf718 }, { 1364, 0xa803 }, { 1369, 0x0a41 }, { 1373, 0x5b08 }, { 1379, 0x0504 }, { 1382, 0x0002 }, { 1383, 0x0500 }, { 1385, 0x382a }, { 1391, 0x5041 }, { 1395, 0x0001 }, { 1396, 0x1910 }, { 1400, 0x2108 }, { 1403, 0x0313 }, { 1408, 0x0000 }, { 1408, 0x6122 }, { 1413, 0x0404 }, /* 0x5500 */ { 1415, 0x40d0 }, { 1419, 0x1001 }, { 1421, 0x8000 }, { 1422, 0x4022 }, { 1425, 0x8050 }, { 1428, 0x4048 }, { 1431, 0x0008 }, { 1432, 0x1000 }, { 1433, 0x06d1 }, { 1439, 0x3700 }, { 1444, 0x5e80 }, { 1450, 0x0000 }, { 1450, 0x00a0 }, { 1452, 0x9410 }, { 1456, 0x0018 }, { 1458, 0x6000 }, /* 0x5600 */ { 1460, 0x0240 }, { 1462, 0x0090 }, { 1464, 0x8000 }, { 1465, 0x0054 }, { 1468, 0x0000 }, { 1468, 0x0008 }, { 1469, 0x0900 }, { 1471, 0x0010 }, { 1472, 0x0040 }, { 1473, 0x0000 }, { 1473, 0x5020 }, { 1476, 0x1010 }, { 1478, 0x2400 }, { 1480, 0x4c02 }, { 1484, 0x0001 }, { 1485, 0x0601 }, /* 0x5700 */ { 1488, 0x2918 }, { 1493, 0x814c }, { 1498, 0x2100 }, { 1500, 0x0801 }, { 1502, 0x6485 }, { 1508, 0x0003 }, { 1510, 0x4452 }, { 1515, 0x1021 }, { 1518, 0x0904 }, { 1521, 0x0008 }, { 1522, 0x000d }, { 1525, 0x0000 }, { 1525, 0x4988 }, { 1530, 0x8000 }, { 1531, 0x0001 }, { 1532, 0x1691 }, /* 0x5800 */ { 1538, 0x0765 }, { 1545, 0x4000 }, { 1546, 0x8492 }, { 1551, 0x0433 }, { 1556, 0x8c00 }, { 1559, 0x4592 }, { 1565, 0x0016 }, { 1568, 0x5220 }, { 1572, 0x0228 }, { 1575, 0xd008 }, { 1579, 0x4300 }, { 1582, 0x4c08 }, { 1586, 0x40a2 }, { 1590, 0xc32a }, { 1597, 0x9810 }, { 1601, 0x2e00 }, /* 0x5900 */ { 1605, 0x8000 }, { 1606, 0x1670 }, { 1612, 0x6e84 }, { 1619, 0x4082 }, { 1622, 0xc390 }, { 1628, 0x04b3 }, { 1634, 0x7c85 }, { 1642, 0x2118 }, { 1646, 0x041c }, { 1650, 0x02c8 }, { 1654, 0x1120 }, { 1657, 0x4a00 }, { 1660, 0x0a48 }, { 1664, 0x361b }, { 1672, 0x5540 }, { 1677, 0x8900 }, /* 0x5a00 */ { 1680, 0x000a }, { 1682, 0x9902 }, { 1687, 0x0221 }, { 1690, 0x1040 }, { 1692, 0x0242 }, { 1695, 0x0400 }, { 1696, 0x0044 }, { 1698, 0x0000 }, { 1698, 0x0000 }, { 1698, 0x0c04 }, { 1701, 0x0010 }, { 1702, 0x0000 }, { 1702, 0x1216 }, { 1707, 0x0000 }, { 1707, 0x0242 }, { 1710, 0x0000 }, /* 0x5b00 */ { 1710, 0x1a20 }, { 1714, 0x0040 }, { 1715, 0x0400 }, { 1716, 0x0000 }, { 1716, 0x0009 }, { 1718, 0xb5b3 }, { 1728, 0x0a18 }, { 1732, 0x1523 }, { 1738, 0x9ba0 }, { 1745, 0x1fe8 }, { 1754, 0x507c }, { 1761, 0x8379 }, { 1769, 0x10fd }, { 1777, 0xc09d }, { 1784, 0xdbf6 }, { 1796, 0x0560 }, /* 0x5c00 */ { 1800, 0xef92 }, { 1810, 0x0242 }, { 1813, 0x0110 }, { 1815, 0xdf02 }, { 1823, 0x6961 }, { 1830, 0x0822 }, { 1833, 0x9035 }, { 1839, 0x0202 }, { 1841, 0x0000 }, { 1841, 0x0003 }, { 1843, 0x1a02 }, { 1847, 0x45aa }, { 1854, 0x0001 }, { 1855, 0x0200 }, { 1856, 0x8101 }, { 1859, 0x2851 }, /* 0x5d00 */ { 1864, 0x6080 }, { 1867, 0x02d2 }, { 1872, 0x0280 }, { 1874, 0x0000 }, { 1874, 0x1800 }, { 1876, 0x0001 }, { 1877, 0x9200 }, { 1880, 0x0000 }, { 1880, 0x0880 }, { 1882, 0x2000 }, { 1883, 0x0405 }, { 1886, 0x3500 }, { 1890, 0x2000 }, { 1891, 0x6044 }, { 1895, 0x49e6 }, { 1903, 0x609e }, /* 0x5e00 */ { 1910, 0x104c }, { 1914, 0x2a42 }, { 1919, 0x2820 }, { 1922, 0xa148 }, { 1927, 0x10b1 }, { 1932, 0x8020 }, { 1934, 0x000e }, { 1937, 0x7b9c }, { 1947, 0x8490 }, { 1951, 0x14a0 }, { 1955, 0x28c1 }, { 1960, 0x41e0 }, { 1965, 0x0704 }, { 1969, 0x8c49 }, { 1975, 0x100d }, { 1979, 0x0cc8 }, /* 0x5f00 */ { 1984, 0x8412 }, { 1988, 0x89ba }, { 1996, 0x02c0 }, { 1999, 0x1422 }, { 2003, 0x5500 }, { 2007, 0x0ac0 }, { 2011, 0x3ec4 }, { 2019, 0x9283 }, { 2025, 0x1ca3 }, { 2032, 0x4387 }, { 2039, 0x4703 }, { 2045, 0x22a0 }, { 2049, 0x3028 }, { 2053, 0x03c0 }, { 2057, 0x0801 }, { 2059, 0xa020 }, /* 0x6000 */ { 2062, 0x8000 }, { 2063, 0x3044 }, { 2067, 0x85a3 }, { 2074, 0x0000 }, { 2074, 0x200e }, { 2078, 0x2225 }, { 2083, 0xb73c }, { 2093, 0x0001 }, { 2094, 0x3220 }, { 2098, 0x8c50 }, { 2103, 0x0099 }, { 2107, 0x315d }, { 2115, 0x00a0 }, { 2117, 0x9402 }, { 2121, 0x0003 }, { 2123, 0x0e4b }, /* 0x6100 */ { 2130, 0xe342 }, { 2137, 0x8c20 }, { 2141, 0x0080 }, { 2142, 0xd091 }, { 2148, 0x1d94 }, { 2155, 0xa328 }, { 2161, 0x499c }, { 2168, 0x60c1 }, { 2173, 0x4406 }, { 2177, 0x0713 }, { 2183, 0x5a90 }, { 2189, 0x4444 }, { 2193, 0x0f88 }, { 2199, 0x0000 }, { 2199, 0x0040 }, { 2200, 0x95c4 }, /* 0x6200 */ { 2207, 0x7581 }, { 2214, 0x8447 }, { 2220, 0x4402 }, { 2223, 0xc053 }, { 2229, 0x2b83 }, { 2236, 0x0108 }, { 2238, 0x4000 }, { 2239, 0x9242 }, { 2244, 0x0611 }, { 2248, 0x09a6 }, { 2254, 0x0800 }, { 2255, 0x3222 }, { 2260, 0xb384 }, { 2267, 0x1bdd }, { 2277, 0xf000 }, { 2281, 0xc08a }, /* 0x6300 */ { 2286, 0x0282 }, { 2289, 0x0002 }, { 2290, 0x8800 }, { 2292, 0x6c00 }, { 2296, 0x9200 }, { 2299, 0x0021 }, { 2301, 0x4180 }, { 2304, 0x8c84 }, { 2309, 0x1308 }, { 2313, 0x0944 }, { 2317, 0x07a7 }, { 2325, 0x0000 }, { 2325, 0x8051 }, { 2329, 0x0c41 }, { 2333, 0x6002 }, { 2336, 0x00d0 }, /* 0x6400 */ { 2339, 0xa000 }, { 2341, 0x10d0 }, { 2345, 0x3004 }, { 2348, 0x4400 }, { 2350, 0x0000 }, { 2350, 0x0100 }, { 2351, 0x8201 }, { 2354, 0x0700 }, { 2357, 0x0100 }, { 2358, 0x440e }, { 2363, 0x6830 }, { 2368, 0x0805 }, { 2371, 0x64b2 }, { 2378, 0x0514 }, { 2382, 0x10e6 }, { 2388, 0x4414 }, /* 0x6500 */ { 2392, 0x0011 }, { 2394, 0x2100 }, { 2396, 0x9c08 }, { 2401, 0xcbc0 }, { 2408, 0xe120 }, { 2413, 0x40c2 }, { 2417, 0x304c }, { 2422, 0x41b4 }, { 2428, 0x10ac }, { 2433, 0x9a83 }, { 2440, 0x98b2 }, { 2447, 0x3281 }, { 2452, 0x9822 }, { 2457, 0x0084 }, { 2459, 0x3369 }, { 2467, 0xbc12 }, /* 0x6600 */ { 2474, 0xd6c0 }, { 2481, 0xc03b }, { 2488, 0xa1a1 }, { 2494, 0x0c53 }, { 2500, 0x8a1e }, { 2507, 0xea00 }, { 2512, 0xcbf0 }, { 2521, 0x05d8 }, { 2527, 0x4390 }, { 2532, 0x21c3 }, { 2538, 0x4805 }, { 2542, 0x4a1c }, { 2548, 0x02d0 }, { 2552, 0x3240 }, { 2556, 0x0041 }, { 2558, 0xd79d }, /* 0x6700 */ { 2569, 0x2b09 }, { 2575, 0xe8b0 }, { 2582, 0x7dc0 }, { 2590, 0x2452 }, { 2595, 0xc240 }, { 2599, 0xd04b }, { 2606, 0xa000 }, { 2608, 0xc8ab }, { 2616, 0x8a80 }, { 2620, 0x34a9 }, { 2627, 0x8000 }, { 2628, 0x41c9 }, { 2634, 0x8010 }, { 2636, 0x241f }, { 2643, 0x9200 }, { 2646, 0x487b }, /* 0x6800 */ { 2654, 0x0000 }, { 2654, 0x00cc }, { 2658, 0x8406 }, { 2662, 0x3300 }, { 2666, 0x410f }, { 2672, 0x001b }, { 2676, 0x2000 }, { 2677, 0x8040 }, { 2679, 0x8022 }, { 2682, 0xa098 }, { 2687, 0xa186 }, { 2693, 0x006b }, { 2698, 0x2a30 }, { 2703, 0x85a4 }, { 2709, 0x4181 }, { 2713, 0x0604 }, /* 0x6900 */ { 2716, 0x6021 }, { 2720, 0x0004 }, { 2721, 0x0080 }, { 2722, 0xa001 }, { 2725, 0x0400 }, { 2726, 0x46b8 }, { 2733, 0xe90f }, { 2742, 0x03a0 }, { 2746, 0x0000 }, { 2746, 0x1820 }, { 2749, 0x40a0 }, { 2752, 0x0810 }, { 2754, 0x380a }, { 2759, 0x0001 }, { 2760, 0x0500 }, { 2762, 0xa800 }, /* 0x6a00 */ { 2765, 0x0404 }, { 2767, 0xc28a }, { 2773, 0x000a }, { 2775, 0x2720 }, { 2780, 0x0910 }, { 2783, 0x830c }, { 2788, 0x0802 }, { 2790, 0x0000 }, { 2790, 0x6211 }, { 2795, 0x1080 }, { 2797, 0x000c }, { 2799, 0x0808 }, { 2801, 0x000c }, { 2803, 0x0c08 }, { 2806, 0x0000 }, { 2806, 0x0840 }, /* 0x6b00 */ { 2808, 0x1410 }, { 2811, 0x0044 }, { 2813, 0x000b }, { 2816, 0x6404 }, { 2820, 0x50c0 }, { 2824, 0x8001 }, { 2826, 0x047e }, { 2833, 0x8984 }, { 2838, 0x0658 }, { 2843, 0x4140 }, { 2846, 0xc000 }, { 2848, 0x94a4 }, { 2854, 0xa862 }, { 2860, 0x09dc }, { 2867, 0x1800 }, { 2869, 0x0000 }, /* 0x6c00 */ { 2869, 0x8100 }, { 2871, 0x000a }, { 2873, 0x0008 }, { 2874, 0x4190 }, { 2878, 0x4007 }, { 2882, 0xe4a1 }, { 2889, 0x2501 }, { 2893, 0x6445 }, { 2899, 0x11ee }, { 2907, 0x0e7d }, { 2916, 0x4800 }, { 2918, 0xfb08 }, { 2926, 0x1616 }, { 2932, 0x08a8 }, { 2936, 0xc92e }, { 2944, 0x0009 }, /* 0x6d00 */ { 2946, 0x1800 }, { 2948, 0x4a82 }, { 2953, 0x06a0 }, { 2957, 0x6b64 }, { 2965, 0x0002 }, { 2966, 0x1600 }, { 2969, 0x5648 }, { 2975, 0x8390 }, { 2980, 0x73a0 }, { 2987, 0x002a }, { 2990, 0x8000 }, { 2991, 0x0024 }, { 2993, 0x88f9 }, { 3001, 0x4702 }, { 3006, 0x4d02 }, { 3011, 0x0faa }, /* 0x6e00 */ { 3019, 0x0000 }, { 3019, 0x8e80 }, { 3024, 0xb87b }, { 3034, 0x7554 }, { 3042, 0x2418 }, { 3046, 0xd940 }, { 3052, 0xc880 }, { 3056, 0x040c }, { 3059, 0x0000 }, { 3059, 0xb041 }, { 3064, 0x8c24 }, { 3069, 0x0442 }, { 3072, 0x5a34 }, { 3079, 0x001a }, { 3082, 0x8000 }, { 3083, 0xc110 }, /* 0x6f00 */ { 3087, 0x8046 }, { 3091, 0x0032 }, { 3094, 0x180d }, { 3099, 0x8106 }, { 3103, 0x0002 }, { 3104, 0xcd92 }, { 3112, 0x6014 }, { 3116, 0x7401 }, { 3121, 0x6112 }, { 3126, 0x0091 }, { 3129, 0xc098 }, { 3134, 0x420a }, { 3138, 0x040f }, { 3143, 0x8420 }, { 3146, 0x9a13 }, { 3153, 0x4002 }, /* 0x7000 */ { 3155, 0x8a62 }, { 3161, 0xfd22 }, { 3170, 0x8188 }, { 3174, 0x4080 }, { 3176, 0x1000 }, { 3177, 0x2103 }, { 3181, 0x0808 }, { 3183, 0x3101 }, { 3187, 0x4420 }, { 3190, 0x0704 }, { 3194, 0xb812 }, { 3200, 0x0388 }, { 3204, 0x8900 }, { 3207, 0xa300 }, { 3211, 0x0000 }, { 3211, 0x2202 }, /* 0x7100 */ { 3214, 0x1210 }, { 3217, 0x4600 }, { 3220, 0x0042 }, { 3222, 0x0041 }, { 3224, 0x5680 }, { 3229, 0x5241 }, { 3234, 0x52f0 }, { 3241, 0x2000 }, { 3242, 0x8610 }, { 3246, 0x8214 }, { 3250, 0x1004 }, { 3252, 0x4602 }, { 3256, 0x430a }, { 3261, 0x8035 }, { 3266, 0x60e0 }, { 3271, 0xd800 }, /* 0x7200 */ { 3275, 0x0041 }, { 3277, 0x0801 }, { 3279, 0x3400 }, { 3282, 0x6c65 }, { 3290, 0x11c1 }, { 3295, 0xab04 }, { 3301, 0x0286 }, { 3305, 0x2204 }, { 3308, 0x0003 }, { 3310, 0x0000 }, { 3310, 0x9084 }, { 3314, 0x0000 }, { 3314, 0x4015 }, { 3318, 0x0281 }, { 3321, 0x0202 }, { 3323, 0x3300 }, /* 0x7300 */ { 3327, 0x0400 }, { 3328, 0x3840 }, { 3332, 0x0e20 }, { 3336, 0xc0c0 }, { 3340, 0x0030 }, { 3342, 0x0085 }, { 3345, 0x0500 }, { 3347, 0x0d25 }, { 3353, 0x4ad0 }, { 3359, 0x81d0 }, { 3364, 0x2280 }, { 3367, 0x020c }, { 3370, 0xb605 }, { 3377, 0x6240 }, { 3381, 0x2679 }, { 3389, 0x6280 }, /* 0x7400 */ { 3393, 0x02ea }, { 3399, 0x0808 }, { 3401, 0xdd67 }, { 3412, 0x8579 }, { 3420, 0x081b }, { 3425, 0xdea0 }, { 3433, 0x8735 }, { 3441, 0x4000 }, { 3442, 0x0a8c }, { 3447, 0xd100 }, { 3451, 0x05aa }, { 3457, 0xa225 }, { 3463, 0x8440 }, { 3466, 0x1510 }, { 3470, 0x404d }, { 3475, 0x0080 }, /* 0x7500 */ { 3476, 0x0012 }, { 3478, 0x8d22 }, { 3484, 0x1968 }, { 3490, 0x058f }, { 3497, 0x9080 }, { 3500, 0x3a1a }, { 3507, 0x8464 }, { 3512, 0x8561 }, { 3518, 0xccc0 }, { 3524, 0x2002 }, { 3526, 0x0820 }, { 3528, 0x732e }, { 3537, 0x20a4 }, { 3541, 0x0b34 }, { 3547, 0x0004 }, { 3548, 0x1415 }, /* 0x7600 */ { 3553, 0x2001 }, { 3555, 0x8200 }, { 3557, 0x0057 }, { 3562, 0x0800 }, { 3563, 0x5004 }, { 3566, 0x0044 }, { 3568, 0x1212 }, { 3572, 0x7905 }, { 3579, 0x40d0 }, { 3583, 0x0009 }, { 3585, 0x4000 }, { 3586, 0x8400 }, { 3588, 0x054c }, { 3593, 0xd844 }, { 3599, 0x409a }, { 3604, 0x5114 }, /* 0x7700 */ { 3609, 0x0b12 }, { 3614, 0x4000 }, { 3615, 0x0201 }, { 3617, 0x1580 }, { 3621, 0x2001 }, { 3623, 0x0800 }, { 3624, 0x084a }, { 3628, 0xc200 }, { 3631, 0x0800 }, { 3632, 0x4002 }, { 3634, 0x3020 }, { 3637, 0x9809 }, { 3642, 0x0000 }, { 3642, 0x1880 }, { 3645, 0xe22c }, { 3652, 0x0008 }, /* 0x7800 */ { 3653, 0x0004 }, { 3654, 0x0004 }, { 3655, 0x10e0 }, { 3659, 0x0014 }, { 3661, 0x8020 }, { 3663, 0x2000 }, { 3664, 0x9800 }, { 3667, 0x1000 }, { 3668, 0x7082 }, { 3673, 0x0082 }, { 3675, 0x0288 }, { 3678, 0x1c00 }, { 3681, 0x4c22 }, { 3686, 0x0001 }, { 3687, 0x9100 }, { 3690, 0x0820 }, /* 0x7900 */ { 3692, 0x4002 }, { 3694, 0x0040 }, { 3695, 0x1c00 }, { 3698, 0x4400 }, { 3700, 0x0383 }, { 3705, 0x7cc1 }, { 3713, 0x2121 }, { 3717, 0x8400 }, { 3719, 0xe002 }, { 3723, 0x0002 }, { 3724, 0x44c0 }, { 3728, 0xe20a }, { 3734, 0x0e03 }, { 3739, 0x8126 }, { 3744, 0x02d0 }, { 3748, 0x0800 }, /* 0x7a00 */ { 3749, 0x2921 }, { 3754, 0x9690 }, { 3760, 0x4001 }, { 3762, 0xb8c2 }, { 3769, 0x6241 }, { 3774, 0x0080 }, { 3775, 0x0a06 }, { 3779, 0xa651 }, { 3786, 0x0112 }, { 3789, 0x812c }, { 3794, 0xc600 }, { 3798, 0x0400 }, { 3799, 0x0cb0 }, { 3804, 0xa280 }, { 3808, 0xa429 }, { 3814, 0x8640 }, /* 0x7b00 */ { 3818, 0x8000 }, { 3819, 0x4a02 }, { 3823, 0x3041 }, { 3827, 0x0200 }, { 3828, 0xba40 }, { 3834, 0x0057 }, { 3839, 0x5001 }, { 3842, 0x2020 }, { 3844, 0x8880 }, { 3847, 0x24b0 }, { 3852, 0x2002 }, { 3854, 0x0112 }, { 3857, 0x02d3 }, { 3863, 0x0004 }, { 3864, 0x0211 }, { 3867, 0x0000 }, /* 0x7c00 */ { 3867, 0x0080 }, { 3868, 0x4004 }, { 3870, 0x0c82 }, { 3874, 0xe000 }, { 3877, 0x3008 }, { 3880, 0x0000 }, { 3880, 0x1011 }, { 3883, 0x0008 }, { 3884, 0x0208 }, { 3886, 0x81a4 }, { 3891, 0x40a0 }, { 3894, 0x420e }, { 3899, 0x0400 }, { 3900, 0xc040 }, { 3903, 0x0081 }, { 3905, 0x4800 }, /* 0x7d00 */ { 3907, 0x2df5 }, { 3917, 0x0f91 }, { 3924, 0xd807 }, { 3931, 0x0629 }, { 3936, 0x007c }, { 3941, 0x4001 }, { 3943, 0x4546 }, { 3949, 0x824e }, { 3955, 0xc000 }, { 3957, 0x1008 }, { 3959, 0x3005 }, { 3963, 0xed36 }, { 3973, 0x0c80 }, { 3976, 0x6540 }, { 3981, 0x930b }, { 3988, 0x0810 }, /* 0x7e00 */ { 3990, 0x0600 }, { 3992, 0xe820 }, { 3997, 0xc80a }, { 4002, 0x6082 }, { 4006, 0x00ca }, { 4010, 0x4034 }, { 4014, 0x2e02 }, { 4019, 0x1201 }, { 4022, 0x9004 }, { 4025, 0x1948 }, { 4030, 0x0000 }, { 4030, 0x0000 }, { 4030, 0x0000 }, { 4030, 0x0000 }, { 4030, 0x0000 }, { 4030, 0x0000 }, /* 0x7f00 */ { 4030, 0x0000 }, { 4030, 0x0000 }, { 4030, 0x0000 }, { 4030, 0x0540 }, { 4033, 0x1000 }, { 4034, 0x0031 }, { 4037, 0x4c00 }, { 4040, 0x02a5 }, { 4045, 0x5520 }, { 4050, 0x4410 }, { 4053, 0x0310 }, { 4056, 0x2304 }, { 4060, 0x5422 }, { 4065, 0x8034 }, { 4069, 0x0a03 }, { 4073, 0x1201 }, /* 0x8000 */ { 4076, 0x126b }, { 4083, 0x01a1 }, { 4087, 0x2000 }, { 4088, 0xa048 }, { 4092, 0x0448 }, { 4095, 0x4540 }, { 4099, 0x8000 }, { 4100, 0xe08d }, { 4107, 0x1af0 }, { 4114, 0x2840 }, { 4117, 0x8626 }, { 4123, 0x0416 }, { 4127, 0x5018 }, { 4131, 0x4c00 }, { 4134, 0x0032 }, { 4137, 0x2112 }, /* 0x8100 */ { 4141, 0x05e4 }, { 4147, 0x0d00 }, { 4150, 0x8a08 }, { 4154, 0x4200 }, { 4156, 0x4800 }, { 4158, 0x0033 }, { 4162, 0x0860 }, { 4165, 0x8703 }, { 4171, 0x8501 }, { 4175, 0x3400 }, { 4178, 0x0109 }, { 4181, 0xe428 }, { 4187, 0x2045 }, { 4191, 0x8100 }, { 4193, 0x25a8 }, { 4199, 0x5c18 }, /* 0x8200 */ { 4205, 0x35a0 }, { 4211, 0xd804 }, { 4216, 0x1c02 }, { 4220, 0x02e0 }, { 4224, 0x00a1 }, { 4227, 0x0200 }, { 4228, 0xc050 }, { 4232, 0x4146 }, { 4237, 0x6800 }, { 4240, 0xa604 }, { 4245, 0xf260 }, { 4252, 0xbb8a }, { 4261, 0x0000 }, { 4261, 0xc8b6 }, { 4269, 0x00e2 }, { 4273, 0x6002 }, /* 0x8300 */ { 4276, 0x023e }, { 4282, 0x0080 }, { 4283, 0x8900 }, { 4286, 0x0372 }, { 4292, 0x8681 }, { 4297, 0x0006 }, { 4299, 0x0000 }, { 4299, 0x0888 }, { 4302, 0x4600 }, { 4305, 0x4140 }, { 4308, 0x0e04 }, { 4312, 0x2000 }, { 4313, 0x1622 }, { 4318, 0x1048 }, { 4321, 0x8a00 }, { 4324, 0x2217 }, /* 0x8400 */ { 4330, 0x7418 }, { 4336, 0x0000 }, { 4336, 0x1200 }, { 4338, 0x2102 }, { 4341, 0x0200 }, { 4342, 0x0880 }, { 4344, 0x984a }, { 4350, 0x0420 }, { 4352, 0x0000 }, { 4352, 0x1211 }, { 4356, 0x0002 }, { 4357, 0x9904 }, { 4362, 0x2a55 }, { 4369, 0x0402 }, { 4371, 0x5000 }, { 4373, 0x1010 }, /* 0x8500 */ { 4375, 0x0000 }, { 4375, 0x459a }, { 4382, 0xb02a }, { 4388, 0xa000 }, { 4390, 0x420a }, { 4394, 0x0208 }, { 4396, 0x2708 }, { 4401, 0x0000 }, { 4401, 0x8090 }, { 4404, 0x0812 }, { 4407, 0x8740 }, { 4412, 0x0401 }, { 4414, 0xe202 }, { 4419, 0x3020 }, { 4422, 0x0630 }, { 4426, 0x8c80 }, /* 0x8600 */ { 4430, 0x04c4 }, { 4434, 0x04c0 }, { 4437, 0x2000 }, { 4438, 0x8000 }, { 4439, 0x4000 }, { 4440, 0xd831 }, { 4447, 0x0080 }, { 4448, 0x0200 }, { 4449, 0x1400 }, { 4451, 0x0008 }, { 4452, 0x0218 }, { 4455, 0x0000 }, { 4455, 0x0880 }, { 4457, 0x8a10 }, { 4461, 0x2010 }, { 4463, 0x4000 }, /* 0x8700 */ { 4464, 0x010d }, { 4468, 0x1500 }, { 4471, 0x0000 }, { 4471, 0x0000 }, { 4471, 0x4000 }, { 4472, 0x80a0 }, { 4475, 0x0140 }, { 4477, 0x0150 }, { 4480, 0x2004 }, { 4482, 0x8000 }, { 4483, 0x0004 }, { 4484, 0x0408 }, { 4486, 0x0010 }, { 4487, 0x0000 }, { 4487, 0x9001 }, { 4490, 0x4a04 }, /* 0x8800 */ { 4494, 0x0020 }, { 4495, 0x8000 }, { 4496, 0x000c }, { 4498, 0x0842 }, { 4501, 0x3041 }, { 4505, 0x2a8c }, { 4511, 0x090e }, { 4516, 0xc085 }, { 4521, 0x2906 }, { 4526, 0x40c4 }, { 4530, 0x0800 }, { 4531, 0x0010 }, { 4532, 0x8006 }, { 4535, 0xb230 }, { 4541, 0x0102 }, { 4543, 0x2138 }, /* 0x8900 */ { 4548, 0x0080 }, { 4549, 0x030d }, { 4554, 0x0420 }, { 4556, 0x0940 }, { 4559, 0x0012 }, { 4561, 0x8000 }, { 4562, 0x0410 }, { 4564, 0x8004 }, { 4566, 0x88ca }, { 4572, 0x0048 }, { 4574, 0x0602 }, { 4577, 0x2404 }, { 4580, 0x0001 }, { 4581, 0x0004 }, { 4582, 0x0008 }, { 4583, 0x0110 }, /* 0x8a00 */ { 4585, 0x550d }, { 4592, 0xa9c8 }, { 4599, 0x2428 }, { 4603, 0x0c52 }, { 4608, 0x0000 }, { 4608, 0x4831 }, { 4613, 0x624d }, { 4620, 0x022f }, { 4626, 0x30a0 }, { 4630, 0x4128 }, { 4634, 0x057b }, { 4642, 0xd205 }, { 4648, 0xa894 }, { 4654, 0x1844 }, { 4658, 0x6cc2 }, { 4665, 0x45c2 }, /* 0x8b00 */ { 4671, 0x4017 }, { 4676, 0x2ed1 }, { 4684, 0x1901 }, { 4688, 0x0208 }, { 4690, 0xc202 }, { 4694, 0x1500 }, { 4697, 0x9040 }, { 4700, 0x2091 }, { 4704, 0x0401 }, { 4706, 0x044d }, { 4711, 0x0000 }, { 4711, 0x0000 }, { 4711, 0x0000 }, { 4711, 0x0000 }, { 4711, 0x0000 }, { 4711, 0x0000 }, /* 0x8c00 */ { 4711, 0x0000 }, { 4711, 0x0000 }, { 4711, 0x0000 }, { 4711, 0x8080 }, { 4713, 0x1542 }, { 4718, 0x0420 }, { 4720, 0x0c02 }, { 4723, 0x0600 }, { 4725, 0x1404 }, { 4728, 0x6000 }, { 4730, 0x9f87 }, { 4740, 0xb9d9 }, { 4750, 0x059f }, { 4758, 0x540a }, { 4763, 0x245d }, { 4770, 0x3810 }, /* 0x8d00 */ { 4774, 0x25b0 }, { 4780, 0x0048 }, { 4782, 0x0000 }, { 4782, 0x0000 }, { 4782, 0x0000 }, { 4782, 0x0000 }, { 4782, 0x0850 }, { 4785, 0x0099 }, { 4789, 0x0420 }, { 4791, 0x0200 }, { 4792, 0x0108 }, { 4794, 0x4408 }, { 4797, 0x9840 }, { 4801, 0x2800 }, { 4803, 0x810a }, { 4807, 0x0008 }, /* 0x8e00 */ { 4808, 0x8400 }, { 4810, 0x4001 }, { 4812, 0x0400 }, { 4813, 0x0021 }, { 4815, 0x0794 }, { 4821, 0x8200 }, { 4823, 0x0001 }, { 4824, 0x0050 }, { 4826, 0x2482 }, { 4830, 0x0000 }, { 4830, 0x1c00 }, { 4833, 0x0000 }, { 4833, 0x3c01 }, { 4838, 0x8004 }, { 4840, 0x0800 }, { 4841, 0x4900 }, /* 0x8f00 */ { 4844, 0x0228 }, { 4847, 0xf83c }, { 4856, 0x86c0 }, { 4861, 0xcb08 }, { 4867, 0x6230 }, { 4872, 0xa000 }, { 4874, 0x0004 }, { 4875, 0x0000 }, { 4875, 0x0000 }, { 4875, 0x1800 }, { 4877, 0xa148 }, { 4882, 0x0007 }, { 4885, 0x4024 }, { 4888, 0x0012 }, { 4890, 0x2c40 }, { 4894, 0x2285 }, /* 0x9000 */ { 4899, 0xa96f }, { 4909, 0xe6b3 }, { 4919, 0x400f }, { 4924, 0x5126 }, { 4930, 0x6c86 }, { 4937, 0x723b }, { 4946, 0xe20b }, { 4953, 0xb5a4 }, { 4961, 0x859f }, { 4970, 0x0222 }, { 4973, 0x854c }, { 4979, 0x0123 }, { 4983, 0x0402 }, { 4985, 0x4000 }, { 4986, 0x2102 }, { 4989, 0x2020 }, /* 0x9100 */ { 4991, 0x0004 }, { 4992, 0x0224 }, { 4995, 0x2080 }, { 4997, 0x0004 }, { 4998, 0x7e00 }, { 5004, 0x0004 }, { 5005, 0x1604 }, { 5009, 0x01a0 }, { 5012, 0x2a80 }, { 5016, 0x1004 }, { 5018, 0xd800 }, { 5022, 0x0032 }, { 5025, 0xfa81 }, { 5033, 0x3183 }, { 5039, 0x0488 }, { 5042, 0x0020 }, /* 0x9200 */ { 5043, 0x2000 }, { 5044, 0x4087 }, { 5049, 0x0000 }, { 5049, 0x8410 }, { 5052, 0x0221 }, { 5055, 0x4880 }, { 5058, 0x0074 }, { 5062, 0x0000 }, { 5062, 0x0029 }, { 5065, 0x114a }, { 5070, 0x0000 }, { 5070, 0x02c8 }, { 5074, 0x9000 }, { 5076, 0x0004 }, { 5077, 0x0410 }, { 5079, 0x1100 }, /* 0x9300 */ { 5081, 0x0010 }, { 5082, 0xc501 }, { 5087, 0xc957 }, { 5096, 0x0000 }, { 5096, 0x2d00 }, { 5100, 0x0810 }, { 5102, 0x4000 }, { 5103, 0x5020 }, { 5106, 0x1000 }, { 5107, 0x0450 }, { 5110, 0x3088 }, { 5114, 0x0001 }, { 5115, 0x0008 }, { 5116, 0x4002 }, { 5118, 0x0012 }, { 5120, 0x0040 }, /* 0x9400 */ { 5121, 0x0010 }, { 5122, 0x0100 }, { 5123, 0x0820 }, { 5125, 0x0120 }, { 5127, 0x0010 }, { 5128, 0x0806 }, { 5131, 0x0000 }, { 5131, 0xa000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, /* 0x9500 */ { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0000 }, { 5133, 0x0080 }, { 5134, 0x8a09 }, { 5139, 0x011e }, { 5144, 0x2138 }, { 5149, 0x1802 }, { 5152, 0x0480 }, { 5154, 0x1070 }, { 5158, 0x0006 }, { 5160, 0x0000 }, /* 0x9600 */ { 5160, 0x0000 }, { 5160, 0x1000 }, { 5161, 0x4402 }, { 5164, 0x8804 }, { 5167, 0x3815 }, { 5173, 0xf801 }, { 5179, 0x041c }, { 5183, 0x21e9 }, { 5190, 0x6c60 }, { 5196, 0x1b30 }, { 5202, 0x0588 }, { 5206, 0x0882 }, { 5209, 0x7af3 }, { 5220, 0x1a60 }, { 5225, 0x870c }, { 5231, 0x0ac5 }, /* 0x9700 */ { 5237, 0x00c1 }, { 5240, 0x524a }, { 5246, 0x0080 }, { 5247, 0x2205 }, { 5251, 0x0114 }, { 5254, 0x5042 }, { 5258, 0x2206 }, { 5262, 0x0490 }, { 5265, 0xa800 }, { 5268, 0x0000 }, { 5268, 0x2901 }, { 5272, 0x0000 }, { 5272, 0x0840 }, { 5274, 0x1008 }, { 5276, 0x0000 }, { 5276, 0x8848 }, /* 0x9800 */ { 5280, 0x156f }, { 5289, 0x018f }, { 5295, 0x2000 }, { 5296, 0x0b01 }, { 5300, 0x7040 }, { 5304, 0x4510 }, { 5308, 0x88a0 }, { 5312, 0x0000 }, { 5312, 0x0000 }, { 5312, 0x0000 }, { 5312, 0x8100 }, { 5314, 0x0002 }, { 5315, 0x0090 }, { 5317, 0x9800 }, { 5320, 0xe006 }, { 5325, 0x7010 }, /* 0x9900 */ { 5329, 0x1608 }, { 5333, 0x4109 }, { 5337, 0x0101 }, { 5339, 0x0000 }, { 5339, 0x3a20 }, { 5344, 0x0096 }, { 5348, 0x0000 }, { 5348, 0x0000 }, { 5348, 0x0000 }, { 5348, 0x2240 }, { 5351, 0x7120 }, { 5356, 0x021a }, { 5360, 0x0002 }, { 5361, 0xa227 }, { 5368, 0x2000 }, { 5369, 0x8002 }, /* 0x9a00 */ { 5371, 0xc102 }, { 5375, 0x0200 }, { 5376, 0x0800 }, { 5377, 0x00c1 }, { 5380, 0x2029 }, { 5384, 0x8ca0 }, { 5389, 0x0624 }, { 5393, 0x0000 }, { 5393, 0x0000 }, { 5393, 0x0000 }, { 5393, 0x0100 }, { 5394, 0x0100 }, { 5395, 0x0000 }, { 5395, 0x0118 }, { 5398, 0x4020 }, { 5400, 0x0000 }, /* 0x9b00 */ { 5400, 0x0000 }, { 5400, 0x0400 }, { 5401, 0x0480 }, { 5403, 0x1002 }, { 5405, 0x803e }, { 5411, 0x0410 }, { 5413, 0x8000 }, { 5414, 0x0000 }, { 5414, 0x4000 }, { 5415, 0x8002 }, { 5417, 0x4800 }, { 5419, 0x0000 }, { 5419, 0x0200 }, { 5420, 0x0040 }, { 5421, 0x0110 }, { 5423, 0x0000 }, /* 0x9c00 */ { 5423, 0x2000 }, { 5424, 0x0025 }, { 5427, 0x0020 }, { 5428, 0x0804 }, { 5430, 0x0280 }, { 5432, 0x0080 }, { 5433, 0x0000 }, { 5433, 0x0000 }, { 5433, 0x0000 }, { 5433, 0x0000 }, { 5433, 0x0000 }, { 5433, 0x0000 }, { 5433, 0x0000 }, { 5433, 0x0000 }, { 5433, 0x02a0 }, { 5436, 0x0058 }, /* 0x9d00 */ { 5439, 0x0200 }, { 5440, 0x0800 }, { 5441, 0x0140 }, { 5443, 0x0800 }, { 5444, 0x0000 }, { 5444, 0x2002 }, { 5446, 0x1003 }, { 5449, 0x0004 }, { 5450, 0x0000 }, { 5450, 0x0000 }, { 5450, 0x8200 }, { 5452, 0x0010 }, { 5453, 0x0010 }, { 5454, 0x0080 }, { 5455, 0x0000 }, { 5455, 0x0704 }, /* 0x9e00 */ { 5459, 0x0000 }, { 5459, 0x4400 }, { 5461, 0x0000 }, { 5461, 0x0000 }, { 5461, 0x0000 }, { 5461, 0x0000 }, { 5461, 0x0000 }, { 5461, 0xa220 }, { 5465, 0x0000 }, { 5465, 0xa08c }, { 5470, 0x0020 }, { 5471, 0x4830 }, { 5475, 0x6008 }, { 5478, 0x5912 }, { 5484, 0x0100 }, { 5485, 0x0010 }, /* 0x9f00 */ { 5486, 0x4180 }, { 5489, 0x0008 }, { 5490, 0x0001 }, { 5491, 0x0800 }, { 5492, 0x4c00 }, { 5495, 0x8004 }, { 5497, 0x1482 }, { 5501, 0x0080 }, { 5502, 0x2000 }, { 5503, 0x1021 }, }; static const Summary16 ksc5601_uni2indx_pageac[698] = { /* 0xac00 */ { 5506, 0x0793 }, { 5513, 0x3eff }, { 5526, 0xb011 }, { 5531, 0x1303 }, { 5536, 0x2801 }, { 5539, 0x1110 }, { 5542, 0x0000 }, { 5542, 0x0593 }, { 5548, 0x1e7b }, { 5558, 0xb011 }, { 5563, 0x9703 }, { 5570, 0x3b01 }, { 5576, 0x1112 }, { 5580, 0x00a0 }, { 5582, 0x9593 }, { 5590, 0x306b }, /* 0xad00 */ { 5597, 0xb051 }, { 5603, 0x1102 }, { 5606, 0x3201 }, { 5610, 0x1130 }, { 5614, 0x02b0 }, { 5618, 0x0111 }, { 5621, 0x300a }, { 5625, 0xb879 }, { 5634, 0x1306 }, { 5639, 0x3001 }, { 5642, 0x0010 }, { 5643, 0x0080 }, { 5644, 0x0113 }, { 5648, 0x100b }, { 5652, 0x0011 }, { 5654, 0x9300 }, /* 0xae00 */ { 5658, 0x2b03 }, { 5664, 0x0010 }, { 5665, 0x0000 }, { 5665, 0x0593 }, { 5671, 0x746b }, { 5680, 0xb051 }, { 5686, 0x1323 }, { 5692, 0x3b01 }, { 5698, 0x1030 }, { 5701, 0x0000 }, { 5701, 0x0000 }, { 5701, 0x7000 }, { 5704, 0xb011 }, { 5709, 0x1303 }, { 5714, 0x2900 }, { 5717, 0x1110 }, /* 0xaf00 */ { 5720, 0x2180 }, { 5723, 0x0001 }, { 5724, 0x3000 }, { 5726, 0xb015 }, { 5732, 0x030e }, { 5737, 0x3001 }, { 5740, 0x0030 }, { 5742, 0x0200 }, { 5743, 0x0111 }, { 5746, 0x1023 }, { 5750, 0x0000 }, { 5750, 0x1300 }, { 5753, 0x6b81 }, { 5760, 0x1010 }, { 5762, 0x0300 }, { 5764, 0x0113 }, /* 0xb000 */ { 5768, 0x1013 }, { 5772, 0x3011 }, { 5776, 0x0100 }, { 5777, 0x0000 }, { 5777, 0x5530 }, { 5783, 0x22b8 }, { 5789, 0x0000 }, { 5789, 0x3000 }, { 5791, 0xb011 }, { 5796, 0x9702 }, { 5802, 0xfb07 }, { 5812, 0x113a }, { 5818, 0x03b0 }, { 5823, 0x0113 }, { 5827, 0x0021 }, { 5829, 0x0000 }, /* 0xb100 */ { 5829, 0x1b00 }, { 5833, 0x3b0d }, { 5841, 0x1138 }, { 5846, 0x03b0 }, { 5851, 0x0113 }, { 5855, 0x1133 }, { 5861, 0x0001 }, { 5862, 0x1300 }, { 5865, 0x2b05 }, { 5871, 0x111c }, { 5876, 0x0100 }, { 5877, 0x0000 }, { 5877, 0x1000 }, { 5878, 0xb011 }, { 5883, 0x1300 }, { 5886, 0x2a01 }, /* 0xb200 */ { 5890, 0x1930 }, { 5895, 0x02b0 }, { 5899, 0x0001 }, { 5900, 0x1010 }, { 5902, 0x0000 }, { 5902, 0x1100 }, { 5904, 0x0301 }, { 5907, 0x1030 }, { 5910, 0x0230 }, { 5913, 0x0713 }, { 5919, 0x146b }, { 5926, 0x0011 }, { 5928, 0x1300 }, { 5931, 0x2b05 }, { 5937, 0xf974 }, { 5947, 0x8fb8 }, /* 0xb300 */ { 5956, 0x0113 }, { 5960, 0x103b }, { 5966, 0x0000 }, { 5966, 0x0000 }, { 5966, 0x0000 }, { 5966, 0xd970 }, { 5974, 0x4ab0 }, { 5980, 0x0113 }, { 5984, 0x103b }, { 5990, 0x0011 }, { 5992, 0x1103 }, { 5996, 0x0000 }, { 5996, 0x5930 }, { 6002, 0x2ab1 }, { 6009, 0x0111 }, { 6012, 0x1000 }, /* 0xb400 */ { 6013, 0x0000 }, { 6013, 0x1101 }, { 6016, 0x0b01 }, { 6020, 0x0010 }, { 6021, 0x0000 }, { 6021, 0x0113 }, { 6025, 0x102b }, { 6030, 0x0000 }, { 6030, 0x0101 }, { 6032, 0x2000 }, { 6033, 0x1110 }, { 6036, 0x02a0 }, { 6039, 0x0111 }, { 6042, 0x3021 }, { 6046, 0xb059 }, { 6053, 0x0102 }, /* 0xb500 */ { 6055, 0x0000 }, { 6055, 0x1930 }, { 6060, 0x07b0 }, { 6066, 0x0113 }, { 6070, 0x383b }, { 6078, 0xb011 }, { 6083, 0x0003 }, { 6085, 0x0000 }, { 6085, 0x0000 }, { 6085, 0x0000 }, { 6085, 0x0d13 }, { 6091, 0x383b }, { 6099, 0xb011 }, { 6104, 0x0103 }, { 6107, 0x1000 }, { 6108, 0x0000 }, /* 0xb600 */ { 6108, 0x0000 }, { 6108, 0x0113 }, { 6112, 0x1020 }, { 6114, 0x0010 }, { 6115, 0x0100 }, { 6116, 0x0000 }, { 6116, 0x0110 }, { 6118, 0x0000 }, { 6118, 0x0000 }, { 6118, 0x3000 }, { 6120, 0x1811 }, { 6124, 0x0002 }, { 6125, 0x0000 }, { 6125, 0x0010 }, { 6126, 0x0000 }, { 6126, 0x0111 }, /* 0xb700 */ { 6129, 0x0023 }, { 6132, 0x0000 }, { 6132, 0x9300 }, { 6136, 0x0b01 }, { 6140, 0x1110 }, { 6143, 0x0030 }, { 6145, 0x0111 }, { 6148, 0x302b }, { 6154, 0xb011 }, { 6159, 0x13c7 }, { 6167, 0x3b01 }, { 6173, 0x0130 }, { 6176, 0x0280 }, { 6178, 0x0000 }, { 6178, 0x3000 }, { 6180, 0xb011 }, /* 0xb800 */ { 6185, 0x1383 }, { 6191, 0x2b01 }, { 6196, 0x1130 }, { 6200, 0x03b0 }, { 6205, 0x0011 }, { 6207, 0x300a }, { 6211, 0xb011 }, { 6216, 0x1102 }, { 6219, 0x2000 }, { 6220, 0x0000 }, { 6220, 0x0100 }, { 6221, 0x0111 }, { 6224, 0x102b }, { 6229, 0xa011 }, { 6233, 0x1302 }, { 6237, 0x2b01 }, /* 0xb900 */ { 6242, 0x0010 }, { 6243, 0x0100 }, { 6244, 0x0001 }, { 6245, 0x3000 }, { 6247, 0x9011 }, { 6251, 0x1302 }, { 6255, 0x2b01 }, { 6260, 0x1130 }, { 6264, 0x66b0 }, { 6271, 0x0000 }, { 6271, 0x3000 }, { 6273, 0xb011 }, { 6278, 0xd302 }, { 6284, 0x6b07 }, { 6292, 0x113a }, { 6298, 0x07b0 }, /* 0xba00 */ { 6304, 0x0103 }, { 6307, 0x0020 }, { 6308, 0x0000 }, { 6308, 0x1300 }, { 6311, 0x6b05 }, { 6318, 0x1138 }, { 6323, 0x03b0 }, { 6328, 0x0113 }, { 6332, 0x10b8 }, { 6337, 0x0000 }, { 6337, 0x1b00 }, { 6341, 0x2b05 }, { 6347, 0x0110 }, { 6349, 0x0300 }, { 6351, 0x0000 }, { 6351, 0x1000 }, /* 0xbb00 */ { 6352, 0xa011 }, { 6356, 0x1102 }, { 6359, 0x0a01 }, { 6362, 0x7970 }, { 6370, 0xa2b0 }, { 6376, 0x0111 }, { 6379, 0x100a }, { 6382, 0x0000 }, { 6382, 0x1100 }, { 6384, 0x0001 }, { 6385, 0x1110 }, { 6388, 0x0090 }, { 6390, 0x0111 }, { 6393, 0x0009 }, { 6395, 0x0000 }, { 6395, 0x9300 }, /* 0xbc00 */ { 6399, 0xbb05 }, { 6407, 0xf9f2 }, { 6418, 0x22b0 }, { 6423, 0x0113 }, { 6427, 0x323b }, { 6435, 0x2001 }, { 6437, 0x0000 }, { 6437, 0x0000 }, { 6437, 0x5930 }, { 6443, 0x06b0 }, { 6448, 0x0193 }, { 6453, 0x303b }, { 6460, 0xa011 }, { 6464, 0x1123 }, { 6469, 0x0000 }, { 6469, 0x1170 }, /* 0xbd00 */ { 6474, 0x02b0 }, { 6478, 0x0011 }, { 6480, 0x1010 }, { 6482, 0x0000 }, { 6482, 0x1301 }, { 6486, 0x0301 }, { 6489, 0x0110 }, { 6491, 0x0000 }, { 6491, 0x0793 }, { 6498, 0x162b }, { 6505, 0x0010 }, { 6506, 0x0101 }, { 6508, 0x0000 }, { 6508, 0x1130 }, { 6512, 0x0200 }, { 6513, 0x0111 }, /* 0xbe00 */ { 6516, 0x3029 }, { 6521, 0xb011 }, { 6526, 0x0000 }, { 6526, 0x0000 }, { 6526, 0x5130 }, { 6531, 0x0eb0 }, { 6537, 0x0513 }, { 6542, 0x383b }, { 6550, 0xb011 }, { 6555, 0x0303 }, { 6559, 0x0100 }, { 6560, 0x0000 }, { 6560, 0x0000 }, { 6560, 0x0193 }, { 6565, 0x1039 }, { 6570, 0x0000 }, /* 0xbf00 */ { 6570, 0x0302 }, { 6573, 0x3b00 }, { 6578, 0x0000 }, { 6578, 0x0000 }, { 6578, 0x0113 }, { 6582, 0x0023 }, { 6585, 0x0000 }, { 6585, 0x0000 }, { 6585, 0x0000 }, { 6585, 0x0010 }, { 6586, 0x0000 }, { 6586, 0x0001 }, { 6587, 0x3020 }, { 6590, 0x9011 }, { 6594, 0x0002 }, { 6595, 0x0000 }, /* 0xc000 */ { 6595, 0x0000 }, { 6595, 0x0000 }, { 6595, 0x0000 }, { 6595, 0x1000 }, { 6596, 0x0000 }, { 6596, 0x1102 }, { 6599, 0x0301 }, { 6602, 0x0000 }, { 6602, 0x0000 }, { 6602, 0x0113 }, { 6606, 0xb02b }, { 6613, 0xb079 }, { 6621, 0x1323 }, { 6627, 0x3b01 }, { 6633, 0x1130 }, { 6637, 0x02b0 }, /* 0xc100 */ { 6641, 0x0111 }, { 6644, 0xf021 }, { 6650, 0xb0d9 }, { 6658, 0x1343 }, { 6664, 0x3b01 }, { 6670, 0x1130 }, { 6674, 0x03b0 }, { 6679, 0x0111 }, { 6682, 0x7020 }, { 6686, 0xb051 }, { 6692, 0x1322 }, { 6697, 0x2001 }, { 6699, 0x1110 }, { 6702, 0x0190 }, { 6705, 0x0111 }, { 6708, 0x300b }, /* 0xc200 */ { 6713, 0xb011 }, { 6718, 0x9302 }, { 6723, 0xab01 }, { 6729, 0x0016 }, { 6732, 0x0100 }, { 6733, 0x0113 }, { 6737, 0x3021 }, { 6741, 0xb011 }, { 6746, 0x0302 }, { 6749, 0x2901 }, { 6753, 0x3130 }, { 6758, 0x02b0 }, { 6762, 0x0000 }, { 6762, 0x3000 }, { 6764, 0xb819 }, { 6771, 0x1b42 }, /* 0xc300 */ { 6777, 0x3301 }, { 6782, 0x1138 }, { 6787, 0x0330 }, { 6791, 0x0000 }, { 6791, 0x0020 }, { 6792, 0x0000 }, { 6792, 0x1300 }, { 6795, 0x3305 }, { 6801, 0x1110 }, { 6804, 0x0000 }, { 6804, 0x0000 }, { 6804, 0x0000 }, { 6804, 0x0001 }, { 6805, 0x9300 }, { 6809, 0x2305 }, { 6814, 0x0130 }, /* 0xc400 */ { 6817, 0x0100 }, { 6818, 0x0001 }, { 6819, 0x1010 }, { 6821, 0x3011 }, { 6825, 0x0100 }, { 6826, 0x0000 }, { 6826, 0x1130 }, { 6830, 0x0230 }, { 6833, 0x0001 }, { 6834, 0x1010 }, { 6836, 0x0000 }, { 6836, 0x1100 }, { 6838, 0x0000 }, { 6838, 0x0000 }, { 6838, 0x0200 }, { 6839, 0x8513 }, /* 0xc500 */ { 6845, 0x1003 }, { 6848, 0x1011 }, { 6851, 0x1300 }, { 6854, 0x2b01 }, { 6859, 0x7730 }, { 6867, 0x63b8 }, { 6875, 0x0113 }, { 6879, 0x303b }, { 6886, 0xb091 }, { 6892, 0x11a2 }, { 6897, 0x0201 }, { 6899, 0x7b30 }, { 6907, 0x57f0 }, { 6916, 0x0113 }, { 6920, 0x702b }, { 6927, 0xf0d1 }, /* 0xc600 */ { 6935, 0x11e3 }, { 6942, 0x1b01 }, { 6947, 0x7130 }, { 6953, 0x0ab9 }, { 6960, 0x0113 }, { 6964, 0x303b }, { 6971, 0x9001 }, { 6974, 0x1302 }, { 6978, 0x2b01 }, { 6983, 0x1130 }, { 6987, 0x02b0 }, { 6991, 0x0713 }, { 6997, 0x302b }, { 7003, 0x3011 }, { 7007, 0x1303 }, { 7012, 0x2301 }, /* 0xc700 */ { 7016, 0x1130 }, { 7020, 0x02b0 }, { 7024, 0x0113 }, { 7028, 0x30ab }, { 7035, 0xb411 }, { 7041, 0x11fe }, { 7050, 0x0901 }, { 7053, 0x7130 }, { 7059, 0x47b8 }, { 7067, 0x05d3 }, { 7074, 0x307b }, { 7082, 0xb011 }, { 7087, 0x5303 }, { 7093, 0x2101 }, { 7096, 0x1110 }, { 7099, 0x0000 }, /* 0xc800 */ { 7099, 0x0513 }, { 7104, 0x306b }, { 7111, 0xb011 }, { 7116, 0x1102 }, { 7119, 0x3301 }, { 7124, 0x0010 }, { 7125, 0x0000 }, { 7125, 0x0513 }, { 7130, 0x38eb }, { 7139, 0xa010 }, { 7142, 0x0102 }, { 7144, 0x3000 }, { 7146, 0x1110 }, { 7149, 0x02b0 }, { 7153, 0x0013 }, { 7156, 0x3020 }, /* 0xc900 */ { 7159, 0xb071 }, { 7166, 0x0102 }, { 7168, 0x1000 }, { 7169, 0x0010 }, { 7170, 0x0000 }, { 7170, 0x0113 }, { 7174, 0x100b }, { 7178, 0x1011 }, { 7181, 0x1300 }, { 7184, 0x2b01 }, { 7189, 0x0000 }, { 7189, 0x0000 }, { 7189, 0x0593 }, { 7195, 0x366b }, { 7204, 0xb095 }, { 7211, 0x1303 }, /* 0xca00 */ { 7216, 0x3b01 }, { 7222, 0x0110 }, { 7224, 0x0200 }, { 7225, 0x0000 }, { 7225, 0x3000 }, { 7227, 0xb011 }, { 7232, 0x0103 }, { 7235, 0x2000 }, { 7236, 0x0010 }, { 7237, 0x0100 }, { 7238, 0x0000 }, { 7238, 0x3000 }, { 7240, 0xb011 }, { 7245, 0x030a }, { 7249, 0x1001 }, { 7251, 0x0010 }, /* 0xcb00 */ { 7252, 0x0100 }, { 7253, 0x0111 }, { 7256, 0x0003 }, { 7258, 0x0000 }, { 7258, 0x1302 }, { 7262, 0x2301 }, { 7266, 0x0010 }, { 7267, 0x0300 }, { 7269, 0x0000 }, { 7269, 0x1000 }, { 7270, 0x0000 }, { 7270, 0x0100 }, { 7271, 0x0000 }, { 7271, 0x0010 }, { 7272, 0x0290 }, { 7275, 0x0000 }, /* 0xcc00 */ { 7275, 0x3000 }, { 7277, 0x3011 }, { 7281, 0x5386 }, { 7288, 0x7b01 }, { 7295, 0x1130 }, { 7299, 0x03b0 }, { 7304, 0x0151 }, { 7308, 0x0021 }, { 7310, 0x0000 }, { 7310, 0x1300 }, { 7313, 0x3b01 }, { 7319, 0x1130 }, { 7323, 0x02b0 }, { 7327, 0x0011 }, { 7329, 0x1010 }, { 7331, 0x0001 }, /* 0xcd00 */ { 7332, 0x1302 }, { 7336, 0x2b01 }, { 7341, 0x1110 }, { 7344, 0x0200 }, { 7345, 0x0000 }, { 7345, 0x1000 }, { 7346, 0xb011 }, { 7351, 0x0102 }, { 7353, 0x0100 }, { 7354, 0x1130 }, { 7358, 0x02b0 }, { 7362, 0x0001 }, { 7363, 0x1010 }, { 7365, 0x0001 }, { 7366, 0x1100 }, { 7368, 0x2b01 }, /* 0xce00 */ { 7373, 0x1110 }, { 7376, 0x0210 }, { 7378, 0x0113 }, { 7382, 0x002b }, { 7386, 0x0000 }, { 7386, 0x9300 }, { 7390, 0x2b03 }, { 7396, 0x1130 }, { 7400, 0x02b0 }, { 7404, 0x0113 }, { 7408, 0x303b }, { 7415, 0x0000 }, { 7415, 0x0002 }, { 7416, 0x0000 }, { 7416, 0x1930 }, { 7421, 0x03b0 }, /* 0xcf00 */ { 7426, 0x0113 }, { 7430, 0x102b }, { 7435, 0xb011 }, { 7440, 0x0103 }, { 7443, 0x0000 }, { 7443, 0x1130 }, { 7447, 0x02b0 }, { 7451, 0x0113 }, { 7455, 0x1021 }, { 7458, 0x0000 }, { 7458, 0x0102 }, { 7460, 0x0001 }, { 7461, 0x0010 }, { 7462, 0x0000 }, { 7462, 0x0113 }, { 7466, 0x102b }, /* 0xd000 */ { 7471, 0x0011 }, { 7473, 0x0102 }, { 7475, 0x2000 }, { 7476, 0x1130 }, { 7480, 0x02b0 }, { 7484, 0x0111 }, { 7487, 0x3001 }, { 7490, 0x3011 }, { 7494, 0x0002 }, { 7495, 0x0000 }, { 7495, 0x1130 }, { 7499, 0x02b0 }, { 7503, 0x0313 }, { 7508, 0x303b }, { 7515, 0xb011 }, { 7520, 0x0103 }, /* 0xd100 */ { 7523, 0x2000 }, { 7524, 0x0000 }, { 7524, 0x0000 }, { 7524, 0x0513 }, { 7529, 0x303b }, { 7536, 0xb011 }, { 7541, 0x1102 }, { 7544, 0x1000 }, { 7545, 0x0110 }, { 7547, 0x0000 }, { 7547, 0x0113 }, { 7551, 0x142b }, { 7557, 0x0001 }, { 7558, 0x0100 }, { 7559, 0x0000 }, { 7559, 0x0110 }, /* 0xd200 */ { 7561, 0x0280 }, { 7563, 0x0001 }, { 7564, 0x3000 }, { 7566, 0xb011 }, { 7571, 0x0102 }, { 7573, 0x1000 }, { 7574, 0x0010 }, { 7575, 0x0000 }, { 7575, 0x0113 }, { 7579, 0x1023 }, { 7583, 0x1011 }, { 7586, 0x9302 }, { 7591, 0x0b05 }, { 7596, 0x1110 }, { 7599, 0x0030 }, { 7601, 0x0113 }, /* 0xd300 */ { 7605, 0x702b }, { 7612, 0xb051 }, { 7618, 0x1323 }, { 7624, 0x3b01 }, { 7630, 0x0030 }, { 7632, 0x0000 }, { 7632, 0x0000 }, { 7632, 0x3000 }, { 7634, 0xb011 }, { 7639, 0x1303 }, { 7644, 0x2b01 }, { 7649, 0x1110 }, { 7652, 0x0330 }, { 7656, 0x0101 }, { 7658, 0x300a }, { 7662, 0xb011 }, /* 0xd400 */ { 7667, 0x0102 }, { 7669, 0x2000 }, { 7670, 0x0000 }, { 7670, 0x0000 }, { 7670, 0x0011 }, { 7672, 0x1000 }, { 7673, 0xa011 }, { 7677, 0x9300 }, { 7681, 0x2b05 }, { 7687, 0x0010 }, { 7688, 0x0200 }, { 7689, 0x0000 }, { 7689, 0x1000 }, { 7690, 0x9011 }, { 7694, 0x1100 }, { 7696, 0x2901 }, /* 0xd500 */ { 7700, 0x1110 }, { 7703, 0x00b0 }, { 7706, 0x0000 }, { 7706, 0x3000 }, { 7708, 0xb011 }, { 7713, 0x1302 }, { 7717, 0x2b21 }, { 7723, 0x1130 }, { 7727, 0x03b0 }, { 7732, 0x0001 }, { 7733, 0x0020 }, { 7734, 0x0000 }, { 7734, 0x1300 }, { 7737, 0x2b05 }, { 7743, 0x1130 }, { 7747, 0x02b0 }, /* 0xd600 */ { 7751, 0x0113 }, { 7755, 0x103b }, { 7761, 0x2011 }, { 7764, 0x1300 }, { 7767, 0x2b21 }, { 7773, 0x1132 }, { 7778, 0x0280 }, { 7780, 0x0013 }, { 7783, 0x3028 }, { 7787, 0xa011 }, { 7791, 0x1102 }, { 7794, 0x0a01 }, { 7797, 0x1130 }, { 7801, 0x0292 }, { 7805, 0x0111 }, { 7808, 0x3021 }, /* 0xd700 */ { 7812, 0x0011 }, { 7814, 0x1302 }, { 7818, 0x2b01 }, { 7823, 0x1130 }, { 7827, 0x0290 }, { 7830, 0x03d3 }, { 7837, 0x122b }, { 7843, 0x3011 }, { 7847, 0x1302 }, { 7851, 0x2b01 }, }; static const Summary16 ksc5601_uni2indx_pagef9[17] = { /* 0xf900 */ { 7856, 0xffff }, { 7872, 0xffff }, { 7888, 0xffff }, { 7904, 0xffff }, { 7920, 0xffff }, { 7936, 0xffff }, { 7952, 0xffff }, { 7968, 0xffff }, { 7984, 0xffff }, { 8000, 0xffff }, { 8016, 0xffff }, { 8032, 0xffff }, { 8048, 0xffff }, { 8064, 0xffff }, { 8080, 0xffff }, { 8096, 0xffff }, /* 0xfa00 */ { 8112, 0x0fff }, }; static const Summary16 ksc5601_uni2indx_pageff[15] = { /* 0xff00 */ { 8124, 0xfffe }, { 8139, 0xffff }, { 8155, 0xffff }, { 8171, 0xffff }, { 8187, 0xffff }, { 8203, 0x7fff }, { 8218, 0x0000 }, { 8218, 0x0000 }, { 8218, 0x0000 }, { 8218, 0x0000 }, { 8218, 0x0000 }, { 8218, 0x0000 }, { 8218, 0x0000 }, { 8218, 0x0000 }, { 8218, 0x006f }, }; static int ksc5601_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; if (n >= 2) { const Summary16 *summary = NULL; if (wc < 0x0460) summary = &ksc5601_uni2indx_page00[(wc>>4)]; else if (wc >= 0x2000 && wc < 0x2670) summary = &ksc5601_uni2indx_page20[(wc>>4)-0x200]; else if (wc >= 0x3000 && wc < 0x33e0) summary = &ksc5601_uni2indx_page30[(wc>>4)-0x300]; else if (wc >= 0x4e00 && wc < 0x9fa0) summary = &ksc5601_uni2indx_page4e[(wc>>4)-0x4e0]; else if (wc >= 0xac00 && wc < 0xd7a0) summary = &ksc5601_uni2indx_pageac[(wc>>4)-0xac0]; else if (wc >= 0xf900 && wc < 0xfa10) summary = &ksc5601_uni2indx_pagef9[(wc>>4)-0xf90]; else if (wc >= 0xff00 && wc < 0xfff0) summary = &ksc5601_uni2indx_pageff[(wc>>4)-0xff0]; if (summary) { unsigned short used = summary->used; unsigned int i = wc & 0x0f; if (used & ((unsigned short) 1 << i)) { unsigned short c; /* Keep in `used' only the bits 0..i-1. */ used &= ((unsigned short) 1 << i) - 1; /* Add `summary->indx' and the number of bits set in `used'. */ used = (used & 0x5555) + ((used & 0xaaaa) >> 1); used = (used & 0x3333) + ((used & 0xcccc) >> 2); used = (used & 0x0f0f) + ((used & 0xf0f0) >> 4); used = (used & 0x00ff) + (used >> 8); c = ksc5601_2charset[summary->indx + used]; r[0] = (c >> 8); r[1] = (c & 0xff); return 2; } } return RET_ILSEQ; } return RET_TOOSMALL; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/jisx0212.h0000644000175000017500000040360115004135251020011 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/jisx0212.h,v 1.5 2003/05/27 22:26:31 tsi Exp $ */ /* * JISX0212.1990-0 */ #ifdef NEED_TOWC static const unsigned short jisx0212_2uni_page22[81] = { /* 0x22 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x02d8, 0x02c7, 0x00b8, 0x02d9, 0x02dd, 0x00af, 0x02db, 0x02da, 0x007e, 0x0384, 0x0385, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x00a1, 0x00a6, 0x00bf, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x00ba, 0x00aa, 0x00a9, 0x00ae, 0x2122, 0x00a4, 0x2116, }; static const unsigned short jisx0212_2uni_page26[188] = { /* 0x26 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0xfffd, 0x038c, 0xfffd, 0x038e, 0x03ab, 0xfffd, 0x038f, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, 0x03c2, 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0xfffd, 0xfffd, /* 0x27 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040e, 0x040f, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045e, 0x045f, }; static const unsigned short jisx0212_2uni_page29[275] = { /* 0x29 */ 0x00c6, 0x0110, 0xfffd, 0x0126, 0xfffd, 0x0132, 0xfffd, 0x0141, 0x013f, 0xfffd, 0x014a, 0x00d8, 0x0152, 0xfffd, 0x0166, 0x00de, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x00e6, 0x0111, 0x00f0, 0x0127, 0x0131, 0x0133, 0x0138, 0x0142, 0x0140, 0x0149, 0x014b, 0x00f8, 0x0153, 0x00df, 0x0167, 0x00fe, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x2a */ 0x00c1, 0x00c0, 0x00c4, 0x00c2, 0x0102, 0x01cd, 0x0100, 0x0104, 0x00c5, 0x00c3, 0x0106, 0x0108, 0x010c, 0x00c7, 0x010a, 0x010e, 0x00c9, 0x00c8, 0x00cb, 0x00ca, 0x011a, 0x0116, 0x0112, 0x0118, 0xfffd, 0x011c, 0x011e, 0x0122, 0x0120, 0x0124, 0x00cd, 0x00cc, 0x00cf, 0x00ce, 0x01cf, 0x0130, 0x012a, 0x012e, 0x0128, 0x0134, 0x0136, 0x0139, 0x013d, 0x013b, 0x0143, 0x0147, 0x0145, 0x00d1, 0x00d3, 0x00d2, 0x00d6, 0x00d4, 0x01d1, 0x0150, 0x014c, 0x00d5, 0x0154, 0x0158, 0x0156, 0x015a, 0x015c, 0x0160, 0x015e, 0x0164, 0x0162, 0x00da, 0x00d9, 0x00dc, 0x00db, 0x016c, 0x01d3, 0x0170, 0x016a, 0x0172, 0x016e, 0x0168, 0x01d7, 0x01db, 0x01d9, 0x01d5, 0x0174, 0x00dd, 0x0178, 0x0176, 0x0179, 0x017d, 0x017b, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x2b */ 0x00e1, 0x00e0, 0x00e4, 0x00e2, 0x0103, 0x01ce, 0x0101, 0x0105, 0x00e5, 0x00e3, 0x0107, 0x0109, 0x010d, 0x00e7, 0x010b, 0x010f, 0x00e9, 0x00e8, 0x00eb, 0x00ea, 0x011b, 0x0117, 0x0113, 0x0119, 0x01f5, 0x011d, 0x011f, 0xfffd, 0x0121, 0x0125, 0x00ed, 0x00ec, 0x00ef, 0x00ee, 0x01d0, 0xfffd, 0x012b, 0x012f, 0x0129, 0x0135, 0x0137, 0x013a, 0x013e, 0x013c, 0x0144, 0x0148, 0x0146, 0x00f1, 0x00f3, 0x00f2, 0x00f6, 0x00f4, 0x01d2, 0x0151, 0x014d, 0x00f5, 0x0155, 0x0159, 0x0157, 0x015b, 0x015d, 0x0161, 0x015f, 0x0165, 0x0163, 0x00fa, 0x00f9, 0x00fc, 0x00fb, 0x016d, 0x01d4, 0x0171, 0x016b, 0x0173, 0x016f, 0x0169, 0x01d8, 0x01dc, 0x01da, 0x01d6, 0x0175, 0x00fd, 0x00ff, 0x0177, 0x017a, 0x017e, 0x017c, }; static const unsigned short jisx0212_2uni_page30[5801] = { /* 0x30 */ 0x4e02, 0x4e04, 0x4e05, 0x4e0c, 0x4e12, 0x4e1f, 0x4e23, 0x4e24, 0x4e28, 0x4e2b, 0x4e2e, 0x4e2f, 0x4e30, 0x4e35, 0x4e40, 0x4e41, 0x4e44, 0x4e47, 0x4e51, 0x4e5a, 0x4e5c, 0x4e63, 0x4e68, 0x4e69, 0x4e74, 0x4e75, 0x4e79, 0x4e7f, 0x4e8d, 0x4e96, 0x4e97, 0x4e9d, 0x4eaf, 0x4eb9, 0x4ec3, 0x4ed0, 0x4eda, 0x4edb, 0x4ee0, 0x4ee1, 0x4ee2, 0x4ee8, 0x4eef, 0x4ef1, 0x4ef3, 0x4ef5, 0x4efd, 0x4efe, 0x4eff, 0x4f00, 0x4f02, 0x4f03, 0x4f08, 0x4f0b, 0x4f0c, 0x4f12, 0x4f15, 0x4f16, 0x4f17, 0x4f19, 0x4f2e, 0x4f31, 0x4f60, 0x4f33, 0x4f35, 0x4f37, 0x4f39, 0x4f3b, 0x4f3e, 0x4f40, 0x4f42, 0x4f48, 0x4f49, 0x4f4b, 0x4f4c, 0x4f52, 0x4f54, 0x4f56, 0x4f58, 0x4f5f, 0x4f63, 0x4f6a, 0x4f6c, 0x4f6e, 0x4f71, 0x4f77, 0x4f78, 0x4f79, 0x4f7a, 0x4f7d, 0x4f7e, 0x4f81, 0x4f82, 0x4f84, /* 0x31 */ 0x4f85, 0x4f89, 0x4f8a, 0x4f8c, 0x4f8e, 0x4f90, 0x4f92, 0x4f93, 0x4f94, 0x4f97, 0x4f99, 0x4f9a, 0x4f9e, 0x4f9f, 0x4fb2, 0x4fb7, 0x4fb9, 0x4fbb, 0x4fbc, 0x4fbd, 0x4fbe, 0x4fc0, 0x4fc1, 0x4fc5, 0x4fc6, 0x4fc8, 0x4fc9, 0x4fcb, 0x4fcc, 0x4fcd, 0x4fcf, 0x4fd2, 0x4fdc, 0x4fe0, 0x4fe2, 0x4ff0, 0x4ff2, 0x4ffc, 0x4ffd, 0x4fff, 0x5000, 0x5001, 0x5004, 0x5007, 0x500a, 0x500c, 0x500e, 0x5010, 0x5013, 0x5017, 0x5018, 0x501b, 0x501c, 0x501d, 0x501e, 0x5022, 0x5027, 0x502e, 0x5030, 0x5032, 0x5033, 0x5035, 0x5040, 0x5041, 0x5042, 0x5045, 0x5046, 0x504a, 0x504c, 0x504e, 0x5051, 0x5052, 0x5053, 0x5057, 0x5059, 0x505f, 0x5060, 0x5062, 0x5063, 0x5066, 0x5067, 0x506a, 0x506d, 0x5070, 0x5071, 0x503b, 0x5081, 0x5083, 0x5084, 0x5086, 0x508a, 0x508e, 0x508f, 0x5090, /* 0x32 */ 0x5092, 0x5093, 0x5094, 0x5096, 0x509b, 0x509c, 0x509e, 0x509f, 0x50a0, 0x50a1, 0x50a2, 0x50aa, 0x50af, 0x50b0, 0x50b9, 0x50ba, 0x50bd, 0x50c0, 0x50c3, 0x50c4, 0x50c7, 0x50cc, 0x50ce, 0x50d0, 0x50d3, 0x50d4, 0x50d8, 0x50dc, 0x50dd, 0x50df, 0x50e2, 0x50e4, 0x50e6, 0x50e8, 0x50e9, 0x50ef, 0x50f1, 0x50f6, 0x50fa, 0x50fe, 0x5103, 0x5106, 0x5107, 0x5108, 0x510b, 0x510c, 0x510d, 0x510e, 0x50f2, 0x5110, 0x5117, 0x5119, 0x511b, 0x511c, 0x511d, 0x511e, 0x5123, 0x5127, 0x5128, 0x512c, 0x512d, 0x512f, 0x5131, 0x5133, 0x5134, 0x5135, 0x5138, 0x5139, 0x5142, 0x514a, 0x514f, 0x5153, 0x5155, 0x5157, 0x5158, 0x515f, 0x5164, 0x5166, 0x517e, 0x5183, 0x5184, 0x518b, 0x518e, 0x5198, 0x519d, 0x51a1, 0x51a3, 0x51ad, 0x51b8, 0x51ba, 0x51bc, 0x51be, 0x51bf, 0x51c2, /* 0x33 */ 0x51c8, 0x51cf, 0x51d1, 0x51d2, 0x51d3, 0x51d5, 0x51d8, 0x51de, 0x51e2, 0x51e5, 0x51ee, 0x51f2, 0x51f3, 0x51f4, 0x51f7, 0x5201, 0x5202, 0x5205, 0x5212, 0x5213, 0x5215, 0x5216, 0x5218, 0x5222, 0x5228, 0x5231, 0x5232, 0x5235, 0x523c, 0x5245, 0x5249, 0x5255, 0x5257, 0x5258, 0x525a, 0x525c, 0x525f, 0x5260, 0x5261, 0x5266, 0x526e, 0x5277, 0x5278, 0x5279, 0x5280, 0x5282, 0x5285, 0x528a, 0x528c, 0x5293, 0x5295, 0x5296, 0x5297, 0x5298, 0x529a, 0x529c, 0x52a4, 0x52a5, 0x52a6, 0x52a7, 0x52af, 0x52b0, 0x52b6, 0x52b7, 0x52b8, 0x52ba, 0x52bb, 0x52bd, 0x52c0, 0x52c4, 0x52c6, 0x52c8, 0x52cc, 0x52cf, 0x52d1, 0x52d4, 0x52d6, 0x52db, 0x52dc, 0x52e1, 0x52e5, 0x52e8, 0x52e9, 0x52ea, 0x52ec, 0x52f0, 0x52f1, 0x52f4, 0x52f6, 0x52f7, 0x5300, 0x5303, 0x530a, 0x530b, /* 0x34 */ 0x530c, 0x5311, 0x5313, 0x5318, 0x531b, 0x531c, 0x531e, 0x531f, 0x5325, 0x5327, 0x5328, 0x5329, 0x532b, 0x532c, 0x532d, 0x5330, 0x5332, 0x5335, 0x533c, 0x533d, 0x533e, 0x5342, 0x534c, 0x534b, 0x5359, 0x535b, 0x5361, 0x5363, 0x5365, 0x536c, 0x536d, 0x5372, 0x5379, 0x537e, 0x5383, 0x5387, 0x5388, 0x538e, 0x5393, 0x5394, 0x5399, 0x539d, 0x53a1, 0x53a4, 0x53aa, 0x53ab, 0x53af, 0x53b2, 0x53b4, 0x53b5, 0x53b7, 0x53b8, 0x53ba, 0x53bd, 0x53c0, 0x53c5, 0x53cf, 0x53d2, 0x53d3, 0x53d5, 0x53da, 0x53dd, 0x53de, 0x53e0, 0x53e6, 0x53e7, 0x53f5, 0x5402, 0x5413, 0x541a, 0x5421, 0x5427, 0x5428, 0x542a, 0x542f, 0x5431, 0x5434, 0x5435, 0x5443, 0x5444, 0x5447, 0x544d, 0x544f, 0x545e, 0x5462, 0x5464, 0x5466, 0x5467, 0x5469, 0x546b, 0x546d, 0x546e, 0x5474, 0x547f, /* 0x35 */ 0x5481, 0x5483, 0x5485, 0x5488, 0x5489, 0x548d, 0x5491, 0x5495, 0x5496, 0x549c, 0x549f, 0x54a1, 0x54a6, 0x54a7, 0x54a9, 0x54aa, 0x54ad, 0x54ae, 0x54b1, 0x54b7, 0x54b9, 0x54ba, 0x54bb, 0x54bf, 0x54c6, 0x54ca, 0x54cd, 0x54ce, 0x54e0, 0x54ea, 0x54ec, 0x54ef, 0x54f6, 0x54fc, 0x54fe, 0x54ff, 0x5500, 0x5501, 0x5505, 0x5508, 0x5509, 0x550c, 0x550d, 0x550e, 0x5515, 0x552a, 0x552b, 0x5532, 0x5535, 0x5536, 0x553b, 0x553c, 0x553d, 0x5541, 0x5547, 0x5549, 0x554a, 0x554d, 0x5550, 0x5551, 0x5558, 0x555a, 0x555b, 0x555e, 0x5560, 0x5561, 0x5564, 0x5566, 0x557f, 0x5581, 0x5582, 0x5586, 0x5588, 0x558e, 0x558f, 0x5591, 0x5592, 0x5593, 0x5594, 0x5597, 0x55a3, 0x55a4, 0x55ad, 0x55b2, 0x55bf, 0x55c1, 0x55c3, 0x55c6, 0x55c9, 0x55cb, 0x55cc, 0x55ce, 0x55d1, 0x55d2, /* 0x36 */ 0x55d3, 0x55d7, 0x55d8, 0x55db, 0x55de, 0x55e2, 0x55e9, 0x55f6, 0x55ff, 0x5605, 0x5608, 0x560a, 0x560d, 0x560e, 0x560f, 0x5610, 0x5611, 0x5612, 0x5619, 0x562c, 0x5630, 0x5633, 0x5635, 0x5637, 0x5639, 0x563b, 0x563c, 0x563d, 0x563f, 0x5640, 0x5641, 0x5643, 0x5644, 0x5646, 0x5649, 0x564b, 0x564d, 0x564f, 0x5654, 0x565e, 0x5660, 0x5661, 0x5662, 0x5663, 0x5666, 0x5669, 0x566d, 0x566f, 0x5671, 0x5672, 0x5675, 0x5684, 0x5685, 0x5688, 0x568b, 0x568c, 0x5695, 0x5699, 0x569a, 0x569d, 0x569e, 0x569f, 0x56a6, 0x56a7, 0x56a8, 0x56a9, 0x56ab, 0x56ac, 0x56ad, 0x56b1, 0x56b3, 0x56b7, 0x56be, 0x56c5, 0x56c9, 0x56ca, 0x56cb, 0x56cf, 0x56d0, 0x56cc, 0x56cd, 0x56d9, 0x56dc, 0x56dd, 0x56df, 0x56e1, 0x56e4, 0x56e5, 0x56e6, 0x56e7, 0x56e8, 0x56f1, 0x56eb, 0x56ed, /* 0x37 */ 0x56f6, 0x56f7, 0x5701, 0x5702, 0x5707, 0x570a, 0x570c, 0x5711, 0x5715, 0x571a, 0x571b, 0x571d, 0x5720, 0x5722, 0x5723, 0x5724, 0x5725, 0x5729, 0x572a, 0x572c, 0x572e, 0x572f, 0x5733, 0x5734, 0x573d, 0x573e, 0x573f, 0x5745, 0x5746, 0x574c, 0x574d, 0x5752, 0x5762, 0x5765, 0x5767, 0x5768, 0x576b, 0x576d, 0x576e, 0x576f, 0x5770, 0x5771, 0x5773, 0x5774, 0x5775, 0x5777, 0x5779, 0x577a, 0x577b, 0x577c, 0x577e, 0x5781, 0x5783, 0x578c, 0x5794, 0x5797, 0x5799, 0x579a, 0x579c, 0x579d, 0x579e, 0x579f, 0x57a1, 0x5795, 0x57a7, 0x57a8, 0x57a9, 0x57ac, 0x57b8, 0x57bd, 0x57c7, 0x57c8, 0x57cc, 0x57cf, 0x57d5, 0x57dd, 0x57de, 0x57e4, 0x57e6, 0x57e7, 0x57e9, 0x57ed, 0x57f0, 0x57f5, 0x57f6, 0x57f8, 0x57fd, 0x57fe, 0x57ff, 0x5803, 0x5804, 0x5808, 0x5809, 0x57e1, /* 0x38 */ 0x580c, 0x580d, 0x581b, 0x581e, 0x581f, 0x5820, 0x5826, 0x5827, 0x582d, 0x5832, 0x5839, 0x583f, 0x5849, 0x584c, 0x584d, 0x584f, 0x5850, 0x5855, 0x585f, 0x5861, 0x5864, 0x5867, 0x5868, 0x5878, 0x587c, 0x587f, 0x5880, 0x5881, 0x5887, 0x5888, 0x5889, 0x588a, 0x588c, 0x588d, 0x588f, 0x5890, 0x5894, 0x5896, 0x589d, 0x58a0, 0x58a1, 0x58a2, 0x58a6, 0x58a9, 0x58b1, 0x58b2, 0x58c4, 0x58bc, 0x58c2, 0x58c8, 0x58cd, 0x58ce, 0x58d0, 0x58d2, 0x58d4, 0x58d6, 0x58da, 0x58dd, 0x58e1, 0x58e2, 0x58e9, 0x58f3, 0x5905, 0x5906, 0x590b, 0x590c, 0x5912, 0x5913, 0x5914, 0x8641, 0x591d, 0x5921, 0x5923, 0x5924, 0x5928, 0x592f, 0x5930, 0x5933, 0x5935, 0x5936, 0x593f, 0x5943, 0x5946, 0x5952, 0x5953, 0x5959, 0x595b, 0x595d, 0x595e, 0x595f, 0x5961, 0x5963, 0x596b, 0x596d, /* 0x39 */ 0x596f, 0x5972, 0x5975, 0x5976, 0x5979, 0x597b, 0x597c, 0x598b, 0x598c, 0x598e, 0x5992, 0x5995, 0x5997, 0x599f, 0x59a4, 0x59a7, 0x59ad, 0x59ae, 0x59af, 0x59b0, 0x59b3, 0x59b7, 0x59ba, 0x59bc, 0x59c1, 0x59c3, 0x59c4, 0x59c8, 0x59ca, 0x59cd, 0x59d2, 0x59dd, 0x59de, 0x59df, 0x59e3, 0x59e4, 0x59e7, 0x59ee, 0x59ef, 0x59f1, 0x59f2, 0x59f4, 0x59f7, 0x5a00, 0x5a04, 0x5a0c, 0x5a0d, 0x5a0e, 0x5a12, 0x5a13, 0x5a1e, 0x5a23, 0x5a24, 0x5a27, 0x5a28, 0x5a2a, 0x5a2d, 0x5a30, 0x5a44, 0x5a45, 0x5a47, 0x5a48, 0x5a4c, 0x5a50, 0x5a55, 0x5a5e, 0x5a63, 0x5a65, 0x5a67, 0x5a6d, 0x5a77, 0x5a7a, 0x5a7b, 0x5a7e, 0x5a8b, 0x5a90, 0x5a93, 0x5a96, 0x5a99, 0x5a9c, 0x5a9e, 0x5a9f, 0x5aa0, 0x5aa2, 0x5aa7, 0x5aac, 0x5ab1, 0x5ab2, 0x5ab3, 0x5ab5, 0x5ab8, 0x5aba, 0x5abb, 0x5abf, /* 0x3a */ 0x5ac4, 0x5ac6, 0x5ac8, 0x5acf, 0x5ada, 0x5adc, 0x5ae0, 0x5ae5, 0x5aea, 0x5aee, 0x5af5, 0x5af6, 0x5afd, 0x5b00, 0x5b01, 0x5b08, 0x5b17, 0x5b34, 0x5b19, 0x5b1b, 0x5b1d, 0x5b21, 0x5b25, 0x5b2d, 0x5b38, 0x5b41, 0x5b4b, 0x5b4c, 0x5b52, 0x5b56, 0x5b5e, 0x5b68, 0x5b6e, 0x5b6f, 0x5b7c, 0x5b7d, 0x5b7e, 0x5b7f, 0x5b81, 0x5b84, 0x5b86, 0x5b8a, 0x5b8e, 0x5b90, 0x5b91, 0x5b93, 0x5b94, 0x5b96, 0x5ba8, 0x5ba9, 0x5bac, 0x5bad, 0x5baf, 0x5bb1, 0x5bb2, 0x5bb7, 0x5bba, 0x5bbc, 0x5bc0, 0x5bc1, 0x5bcd, 0x5bcf, 0x5bd6, 0x5bd7, 0x5bd8, 0x5bd9, 0x5bda, 0x5be0, 0x5bef, 0x5bf1, 0x5bf4, 0x5bfd, 0x5c0c, 0x5c17, 0x5c1e, 0x5c1f, 0x5c23, 0x5c26, 0x5c29, 0x5c2b, 0x5c2c, 0x5c2e, 0x5c30, 0x5c32, 0x5c35, 0x5c36, 0x5c59, 0x5c5a, 0x5c5c, 0x5c62, 0x5c63, 0x5c67, 0x5c68, 0x5c69, /* 0x3b */ 0x5c6d, 0x5c70, 0x5c74, 0x5c75, 0x5c7a, 0x5c7b, 0x5c7c, 0x5c7d, 0x5c87, 0x5c88, 0x5c8a, 0x5c8f, 0x5c92, 0x5c9d, 0x5c9f, 0x5ca0, 0x5ca2, 0x5ca3, 0x5ca6, 0x5caa, 0x5cb2, 0x5cb4, 0x5cb5, 0x5cba, 0x5cc9, 0x5ccb, 0x5cd2, 0x5cdd, 0x5cd7, 0x5cee, 0x5cf1, 0x5cf2, 0x5cf4, 0x5d01, 0x5d06, 0x5d0d, 0x5d12, 0x5d2b, 0x5d23, 0x5d24, 0x5d26, 0x5d27, 0x5d31, 0x5d34, 0x5d39, 0x5d3d, 0x5d3f, 0x5d42, 0x5d43, 0x5d46, 0x5d48, 0x5d55, 0x5d51, 0x5d59, 0x5d4a, 0x5d5f, 0x5d60, 0x5d61, 0x5d62, 0x5d64, 0x5d6a, 0x5d6d, 0x5d70, 0x5d79, 0x5d7a, 0x5d7e, 0x5d7f, 0x5d81, 0x5d83, 0x5d88, 0x5d8a, 0x5d92, 0x5d93, 0x5d94, 0x5d95, 0x5d99, 0x5d9b, 0x5d9f, 0x5da0, 0x5da7, 0x5dab, 0x5db0, 0x5db4, 0x5db8, 0x5db9, 0x5dc3, 0x5dc7, 0x5dcb, 0x5dd0, 0x5dce, 0x5dd8, 0x5dd9, 0x5de0, 0x5de4, /* 0x3c */ 0x5de9, 0x5df8, 0x5df9, 0x5e00, 0x5e07, 0x5e0d, 0x5e12, 0x5e14, 0x5e15, 0x5e18, 0x5e1f, 0x5e20, 0x5e2e, 0x5e28, 0x5e32, 0x5e35, 0x5e3e, 0x5e4b, 0x5e50, 0x5e49, 0x5e51, 0x5e56, 0x5e58, 0x5e5b, 0x5e5c, 0x5e5e, 0x5e68, 0x5e6a, 0x5e6b, 0x5e6c, 0x5e6d, 0x5e6e, 0x5e70, 0x5e80, 0x5e8b, 0x5e8e, 0x5ea2, 0x5ea4, 0x5ea5, 0x5ea8, 0x5eaa, 0x5eac, 0x5eb1, 0x5eb3, 0x5ebd, 0x5ebe, 0x5ebf, 0x5ec6, 0x5ecc, 0x5ecb, 0x5ece, 0x5ed1, 0x5ed2, 0x5ed4, 0x5ed5, 0x5edc, 0x5ede, 0x5ee5, 0x5eeb, 0x5f02, 0x5f06, 0x5f07, 0x5f08, 0x5f0e, 0x5f19, 0x5f1c, 0x5f1d, 0x5f21, 0x5f22, 0x5f23, 0x5f24, 0x5f28, 0x5f2b, 0x5f2c, 0x5f2e, 0x5f30, 0x5f34, 0x5f36, 0x5f3b, 0x5f3d, 0x5f3f, 0x5f40, 0x5f44, 0x5f45, 0x5f47, 0x5f4d, 0x5f50, 0x5f54, 0x5f58, 0x5f5b, 0x5f60, 0x5f63, 0x5f64, 0x5f67, /* 0x3d */ 0x5f6f, 0x5f72, 0x5f74, 0x5f75, 0x5f78, 0x5f7a, 0x5f7d, 0x5f7e, 0x5f89, 0x5f8d, 0x5f8f, 0x5f96, 0x5f9c, 0x5f9d, 0x5fa2, 0x5fa7, 0x5fab, 0x5fa4, 0x5fac, 0x5faf, 0x5fb0, 0x5fb1, 0x5fb8, 0x5fc4, 0x5fc7, 0x5fc8, 0x5fc9, 0x5fcb, 0x5fd0, 0x5fd1, 0x5fd2, 0x5fd3, 0x5fd4, 0x5fde, 0x5fe1, 0x5fe2, 0x5fe8, 0x5fe9, 0x5fea, 0x5fec, 0x5fed, 0x5fee, 0x5fef, 0x5ff2, 0x5ff3, 0x5ff6, 0x5ffa, 0x5ffc, 0x6007, 0x600a, 0x600d, 0x6013, 0x6014, 0x6017, 0x6018, 0x601a, 0x601f, 0x6024, 0x602d, 0x6033, 0x6035, 0x6040, 0x6047, 0x6048, 0x6049, 0x604c, 0x6051, 0x6054, 0x6056, 0x6057, 0x605d, 0x6061, 0x6067, 0x6071, 0x607e, 0x607f, 0x6082, 0x6086, 0x6088, 0x608a, 0x608e, 0x6091, 0x6093, 0x6095, 0x6098, 0x609d, 0x609e, 0x60a2, 0x60a4, 0x60a5, 0x60a8, 0x60b0, 0x60b1, 0x60b7, /* 0x3e */ 0x60bb, 0x60be, 0x60c2, 0x60c4, 0x60c8, 0x60c9, 0x60ca, 0x60cb, 0x60ce, 0x60cf, 0x60d4, 0x60d5, 0x60d9, 0x60db, 0x60dd, 0x60de, 0x60e2, 0x60e5, 0x60f2, 0x60f5, 0x60f8, 0x60fc, 0x60fd, 0x6102, 0x6107, 0x610a, 0x610c, 0x6110, 0x6111, 0x6112, 0x6113, 0x6114, 0x6116, 0x6117, 0x6119, 0x611c, 0x611e, 0x6122, 0x612a, 0x612b, 0x6130, 0x6131, 0x6135, 0x6136, 0x6137, 0x6139, 0x6141, 0x6145, 0x6146, 0x6149, 0x615e, 0x6160, 0x616c, 0x6172, 0x6178, 0x617b, 0x617c, 0x617f, 0x6180, 0x6181, 0x6183, 0x6184, 0x618b, 0x618d, 0x6192, 0x6193, 0x6197, 0x6198, 0x619c, 0x619d, 0x619f, 0x61a0, 0x61a5, 0x61a8, 0x61aa, 0x61ad, 0x61b8, 0x61b9, 0x61bc, 0x61c0, 0x61c1, 0x61c2, 0x61ce, 0x61cf, 0x61d5, 0x61dc, 0x61dd, 0x61de, 0x61df, 0x61e1, 0x61e2, 0x61e7, 0x61e9, 0x61e5, /* 0x3f */ 0x61ec, 0x61ed, 0x61ef, 0x6201, 0x6203, 0x6204, 0x6207, 0x6213, 0x6215, 0x621c, 0x6220, 0x6222, 0x6223, 0x6227, 0x6229, 0x622b, 0x6239, 0x623d, 0x6242, 0x6243, 0x6244, 0x6246, 0x624c, 0x6250, 0x6251, 0x6252, 0x6254, 0x6256, 0x625a, 0x625c, 0x6264, 0x626d, 0x626f, 0x6273, 0x627a, 0x627d, 0x628d, 0x628e, 0x628f, 0x6290, 0x62a6, 0x62a8, 0x62b3, 0x62b6, 0x62b7, 0x62ba, 0x62be, 0x62bf, 0x62c4, 0x62ce, 0x62d5, 0x62d6, 0x62da, 0x62ea, 0x62f2, 0x62f4, 0x62fc, 0x62fd, 0x6303, 0x6304, 0x630a, 0x630b, 0x630d, 0x6310, 0x6313, 0x6316, 0x6318, 0x6329, 0x632a, 0x632d, 0x6335, 0x6336, 0x6339, 0x633c, 0x6341, 0x6342, 0x6343, 0x6344, 0x6346, 0x634a, 0x634b, 0x634e, 0x6352, 0x6353, 0x6354, 0x6358, 0x635b, 0x6365, 0x6366, 0x636c, 0x636d, 0x6371, 0x6374, 0x6375, /* 0x40 */ 0x6378, 0x637c, 0x637d, 0x637f, 0x6382, 0x6384, 0x6387, 0x638a, 0x6390, 0x6394, 0x6395, 0x6399, 0x639a, 0x639e, 0x63a4, 0x63a6, 0x63ad, 0x63ae, 0x63af, 0x63bd, 0x63c1, 0x63c5, 0x63c8, 0x63ce, 0x63d1, 0x63d3, 0x63d4, 0x63d5, 0x63dc, 0x63e0, 0x63e5, 0x63ea, 0x63ec, 0x63f2, 0x63f3, 0x63f5, 0x63f8, 0x63f9, 0x6409, 0x640a, 0x6410, 0x6412, 0x6414, 0x6418, 0x641e, 0x6420, 0x6422, 0x6424, 0x6425, 0x6429, 0x642a, 0x642f, 0x6430, 0x6435, 0x643d, 0x643f, 0x644b, 0x644f, 0x6451, 0x6452, 0x6453, 0x6454, 0x645a, 0x645b, 0x645c, 0x645d, 0x645f, 0x6460, 0x6461, 0x6463, 0x646d, 0x6473, 0x6474, 0x647b, 0x647d, 0x6485, 0x6487, 0x648f, 0x6490, 0x6491, 0x6498, 0x6499, 0x649b, 0x649d, 0x649f, 0x64a1, 0x64a3, 0x64a6, 0x64a8, 0x64ac, 0x64b3, 0x64bd, 0x64be, 0x64bf, /* 0x41 */ 0x64c4, 0x64c9, 0x64ca, 0x64cb, 0x64cc, 0x64ce, 0x64d0, 0x64d1, 0x64d5, 0x64d7, 0x64e4, 0x64e5, 0x64e9, 0x64ea, 0x64ed, 0x64f0, 0x64f5, 0x64f7, 0x64fb, 0x64ff, 0x6501, 0x6504, 0x6508, 0x6509, 0x650a, 0x650f, 0x6513, 0x6514, 0x6516, 0x6519, 0x651b, 0x651e, 0x651f, 0x6522, 0x6526, 0x6529, 0x652e, 0x6531, 0x653a, 0x653c, 0x653d, 0x6543, 0x6547, 0x6549, 0x6550, 0x6552, 0x6554, 0x655f, 0x6560, 0x6567, 0x656b, 0x657a, 0x657d, 0x6581, 0x6585, 0x658a, 0x6592, 0x6595, 0x6598, 0x659d, 0x65a0, 0x65a3, 0x65a6, 0x65ae, 0x65b2, 0x65b3, 0x65b4, 0x65bf, 0x65c2, 0x65c8, 0x65c9, 0x65ce, 0x65d0, 0x65d4, 0x65d6, 0x65d8, 0x65df, 0x65f0, 0x65f2, 0x65f4, 0x65f5, 0x65f9, 0x65fe, 0x65ff, 0x6600, 0x6604, 0x6608, 0x6609, 0x660d, 0x6611, 0x6612, 0x6615, 0x6616, 0x661d, /* 0x42 */ 0x661e, 0x6621, 0x6622, 0x6623, 0x6624, 0x6626, 0x6629, 0x662a, 0x662b, 0x662c, 0x662e, 0x6630, 0x6631, 0x6633, 0x6639, 0x6637, 0x6640, 0x6645, 0x6646, 0x664a, 0x664c, 0x6651, 0x664e, 0x6657, 0x6658, 0x6659, 0x665b, 0x665c, 0x6660, 0x6661, 0x66fb, 0x666a, 0x666b, 0x666c, 0x667e, 0x6673, 0x6675, 0x667f, 0x6677, 0x6678, 0x6679, 0x667b, 0x6680, 0x667c, 0x668b, 0x668c, 0x668d, 0x6690, 0x6692, 0x6699, 0x669a, 0x669b, 0x669c, 0x669f, 0x66a0, 0x66a4, 0x66ad, 0x66b1, 0x66b2, 0x66b5, 0x66bb, 0x66bf, 0x66c0, 0x66c2, 0x66c3, 0x66c8, 0x66cc, 0x66ce, 0x66cf, 0x66d4, 0x66db, 0x66df, 0x66e8, 0x66eb, 0x66ec, 0x66ee, 0x66fa, 0x6705, 0x6707, 0x670e, 0x6713, 0x6719, 0x671c, 0x6720, 0x6722, 0x6733, 0x673e, 0x6745, 0x6747, 0x6748, 0x674c, 0x6754, 0x6755, 0x675d, /* 0x43 */ 0x6766, 0x676c, 0x676e, 0x6774, 0x6776, 0x677b, 0x6781, 0x6784, 0x678e, 0x678f, 0x6791, 0x6793, 0x6796, 0x6798, 0x6799, 0x679b, 0x67b0, 0x67b1, 0x67b2, 0x67b5, 0x67bb, 0x67bc, 0x67bd, 0x67f9, 0x67c0, 0x67c2, 0x67c3, 0x67c5, 0x67c8, 0x67c9, 0x67d2, 0x67d7, 0x67d9, 0x67dc, 0x67e1, 0x67e6, 0x67f0, 0x67f2, 0x67f6, 0x67f7, 0x6852, 0x6814, 0x6819, 0x681d, 0x681f, 0x6828, 0x6827, 0x682c, 0x682d, 0x682f, 0x6830, 0x6831, 0x6833, 0x683b, 0x683f, 0x6844, 0x6845, 0x684a, 0x684c, 0x6855, 0x6857, 0x6858, 0x685b, 0x686b, 0x686e, 0x686f, 0x6870, 0x6871, 0x6872, 0x6875, 0x6879, 0x687a, 0x687b, 0x687c, 0x6882, 0x6884, 0x6886, 0x6888, 0x6896, 0x6898, 0x689a, 0x689c, 0x68a1, 0x68a3, 0x68a5, 0x68a9, 0x68aa, 0x68ae, 0x68b2, 0x68bb, 0x68c5, 0x68c8, 0x68cc, 0x68cf, /* 0x44 */ 0x68d0, 0x68d1, 0x68d3, 0x68d6, 0x68d9, 0x68dc, 0x68dd, 0x68e5, 0x68e8, 0x68ea, 0x68eb, 0x68ec, 0x68ed, 0x68f0, 0x68f1, 0x68f5, 0x68f6, 0x68fb, 0x68fc, 0x68fd, 0x6906, 0x6909, 0x690a, 0x6910, 0x6911, 0x6913, 0x6916, 0x6917, 0x6931, 0x6933, 0x6935, 0x6938, 0x693b, 0x6942, 0x6945, 0x6949, 0x694e, 0x6957, 0x695b, 0x6963, 0x6964, 0x6965, 0x6966, 0x6968, 0x6969, 0x696c, 0x6970, 0x6971, 0x6972, 0x697a, 0x697b, 0x697f, 0x6980, 0x698d, 0x6992, 0x6996, 0x6998, 0x69a1, 0x69a5, 0x69a6, 0x69a8, 0x69ab, 0x69ad, 0x69af, 0x69b7, 0x69b8, 0x69ba, 0x69bc, 0x69c5, 0x69c8, 0x69d1, 0x69d6, 0x69d7, 0x69e2, 0x69e5, 0x69ee, 0x69ef, 0x69f1, 0x69f3, 0x69f5, 0x69fe, 0x6a00, 0x6a01, 0x6a03, 0x6a0f, 0x6a11, 0x6a15, 0x6a1a, 0x6a1d, 0x6a20, 0x6a24, 0x6a28, 0x6a30, 0x6a32, /* 0x45 */ 0x6a34, 0x6a37, 0x6a3b, 0x6a3e, 0x6a3f, 0x6a45, 0x6a46, 0x6a49, 0x6a4a, 0x6a4e, 0x6a50, 0x6a51, 0x6a52, 0x6a55, 0x6a56, 0x6a5b, 0x6a64, 0x6a67, 0x6a6a, 0x6a71, 0x6a73, 0x6a7e, 0x6a81, 0x6a83, 0x6a86, 0x6a87, 0x6a89, 0x6a8b, 0x6a91, 0x6a9b, 0x6a9d, 0x6a9e, 0x6a9f, 0x6aa5, 0x6aab, 0x6aaf, 0x6ab0, 0x6ab1, 0x6ab4, 0x6abd, 0x6abe, 0x6abf, 0x6ac6, 0x6ac9, 0x6ac8, 0x6acc, 0x6ad0, 0x6ad4, 0x6ad5, 0x6ad6, 0x6adc, 0x6add, 0x6ae4, 0x6ae7, 0x6aec, 0x6af0, 0x6af1, 0x6af2, 0x6afc, 0x6afd, 0x6b02, 0x6b03, 0x6b06, 0x6b07, 0x6b09, 0x6b0f, 0x6b10, 0x6b11, 0x6b17, 0x6b1b, 0x6b1e, 0x6b24, 0x6b28, 0x6b2b, 0x6b2c, 0x6b2f, 0x6b35, 0x6b36, 0x6b3b, 0x6b3f, 0x6b46, 0x6b4a, 0x6b4d, 0x6b52, 0x6b56, 0x6b58, 0x6b5d, 0x6b60, 0x6b67, 0x6b6b, 0x6b6e, 0x6b70, 0x6b75, 0x6b7d, /* 0x46 */ 0x6b7e, 0x6b82, 0x6b85, 0x6b97, 0x6b9b, 0x6b9f, 0x6ba0, 0x6ba2, 0x6ba3, 0x6ba8, 0x6ba9, 0x6bac, 0x6bad, 0x6bae, 0x6bb0, 0x6bb8, 0x6bb9, 0x6bbd, 0x6bbe, 0x6bc3, 0x6bc4, 0x6bc9, 0x6bcc, 0x6bd6, 0x6bda, 0x6be1, 0x6be3, 0x6be6, 0x6be7, 0x6bee, 0x6bf1, 0x6bf7, 0x6bf9, 0x6bff, 0x6c02, 0x6c04, 0x6c05, 0x6c09, 0x6c0d, 0x6c0e, 0x6c10, 0x6c12, 0x6c19, 0x6c1f, 0x6c26, 0x6c27, 0x6c28, 0x6c2c, 0x6c2e, 0x6c33, 0x6c35, 0x6c36, 0x6c3a, 0x6c3b, 0x6c3f, 0x6c4a, 0x6c4b, 0x6c4d, 0x6c4f, 0x6c52, 0x6c54, 0x6c59, 0x6c5b, 0x6c5c, 0x6c6b, 0x6c6d, 0x6c6f, 0x6c74, 0x6c76, 0x6c78, 0x6c79, 0x6c7b, 0x6c85, 0x6c86, 0x6c87, 0x6c89, 0x6c94, 0x6c95, 0x6c97, 0x6c98, 0x6c9c, 0x6c9f, 0x6cb0, 0x6cb2, 0x6cb4, 0x6cc2, 0x6cc6, 0x6ccd, 0x6ccf, 0x6cd0, 0x6cd1, 0x6cd2, 0x6cd4, 0x6cd6, /* 0x47 */ 0x6cda, 0x6cdc, 0x6ce0, 0x6ce7, 0x6ce9, 0x6ceb, 0x6cec, 0x6cee, 0x6cf2, 0x6cf4, 0x6d04, 0x6d07, 0x6d0a, 0x6d0e, 0x6d0f, 0x6d11, 0x6d13, 0x6d1a, 0x6d26, 0x6d27, 0x6d28, 0x6c67, 0x6d2e, 0x6d2f, 0x6d31, 0x6d39, 0x6d3c, 0x6d3f, 0x6d57, 0x6d5e, 0x6d5f, 0x6d61, 0x6d65, 0x6d67, 0x6d6f, 0x6d70, 0x6d7c, 0x6d82, 0x6d87, 0x6d91, 0x6d92, 0x6d94, 0x6d96, 0x6d97, 0x6d98, 0x6daa, 0x6dac, 0x6db4, 0x6db7, 0x6db9, 0x6dbd, 0x6dbf, 0x6dc4, 0x6dc8, 0x6dca, 0x6dce, 0x6dcf, 0x6dd6, 0x6ddb, 0x6ddd, 0x6ddf, 0x6de0, 0x6de2, 0x6de5, 0x6de9, 0x6def, 0x6df0, 0x6df4, 0x6df6, 0x6dfc, 0x6e00, 0x6e04, 0x6e1e, 0x6e22, 0x6e27, 0x6e32, 0x6e36, 0x6e39, 0x6e3b, 0x6e3c, 0x6e44, 0x6e45, 0x6e48, 0x6e49, 0x6e4b, 0x6e4f, 0x6e51, 0x6e52, 0x6e53, 0x6e54, 0x6e57, 0x6e5c, 0x6e5d, 0x6e5e, /* 0x48 */ 0x6e62, 0x6e63, 0x6e68, 0x6e73, 0x6e7b, 0x6e7d, 0x6e8d, 0x6e93, 0x6e99, 0x6ea0, 0x6ea7, 0x6ead, 0x6eae, 0x6eb1, 0x6eb3, 0x6ebb, 0x6ebf, 0x6ec0, 0x6ec1, 0x6ec3, 0x6ec7, 0x6ec8, 0x6eca, 0x6ecd, 0x6ece, 0x6ecf, 0x6eeb, 0x6eed, 0x6eee, 0x6ef9, 0x6efb, 0x6efd, 0x6f04, 0x6f08, 0x6f0a, 0x6f0c, 0x6f0d, 0x6f16, 0x6f18, 0x6f1a, 0x6f1b, 0x6f26, 0x6f29, 0x6f2a, 0x6f2f, 0x6f30, 0x6f33, 0x6f36, 0x6f3b, 0x6f3c, 0x6f2d, 0x6f4f, 0x6f51, 0x6f52, 0x6f53, 0x6f57, 0x6f59, 0x6f5a, 0x6f5d, 0x6f5e, 0x6f61, 0x6f62, 0x6f68, 0x6f6c, 0x6f7d, 0x6f7e, 0x6f83, 0x6f87, 0x6f88, 0x6f8b, 0x6f8c, 0x6f8d, 0x6f90, 0x6f92, 0x6f93, 0x6f94, 0x6f96, 0x6f9a, 0x6f9f, 0x6fa0, 0x6fa5, 0x6fa6, 0x6fa7, 0x6fa8, 0x6fae, 0x6faf, 0x6fb0, 0x6fb5, 0x6fb6, 0x6fbc, 0x6fc5, 0x6fc7, 0x6fc8, 0x6fca, /* 0x49 */ 0x6fda, 0x6fde, 0x6fe8, 0x6fe9, 0x6ff0, 0x6ff5, 0x6ff9, 0x6ffc, 0x6ffd, 0x7000, 0x7005, 0x7006, 0x7007, 0x700d, 0x7017, 0x7020, 0x7023, 0x702f, 0x7034, 0x7037, 0x7039, 0x703c, 0x7043, 0x7044, 0x7048, 0x7049, 0x704a, 0x704b, 0x7054, 0x7055, 0x705d, 0x705e, 0x704e, 0x7064, 0x7065, 0x706c, 0x706e, 0x7075, 0x7076, 0x707e, 0x7081, 0x7085, 0x7086, 0x7094, 0x7095, 0x7096, 0x7097, 0x7098, 0x709b, 0x70a4, 0x70ab, 0x70b0, 0x70b1, 0x70b4, 0x70b7, 0x70ca, 0x70d1, 0x70d3, 0x70d4, 0x70d5, 0x70d6, 0x70d8, 0x70dc, 0x70e4, 0x70fa, 0x7103, 0x7104, 0x7105, 0x7106, 0x7107, 0x710b, 0x710c, 0x710f, 0x711e, 0x7120, 0x712b, 0x712d, 0x712f, 0x7130, 0x7131, 0x7138, 0x7141, 0x7145, 0x7146, 0x7147, 0x714a, 0x714b, 0x7150, 0x7152, 0x7157, 0x715a, 0x715c, 0x715e, 0x7160, /* 0x4a */ 0x7168, 0x7179, 0x7180, 0x7185, 0x7187, 0x718c, 0x7192, 0x719a, 0x719b, 0x71a0, 0x71a2, 0x71af, 0x71b0, 0x71b2, 0x71b3, 0x71ba, 0x71bf, 0x71c0, 0x71c1, 0x71c4, 0x71cb, 0x71cc, 0x71d3, 0x71d6, 0x71d9, 0x71da, 0x71dc, 0x71f8, 0x71fe, 0x7200, 0x7207, 0x7208, 0x7209, 0x7213, 0x7217, 0x721a, 0x721d, 0x721f, 0x7224, 0x722b, 0x722f, 0x7234, 0x7238, 0x7239, 0x7241, 0x7242, 0x7243, 0x7245, 0x724e, 0x724f, 0x7250, 0x7253, 0x7255, 0x7256, 0x725a, 0x725c, 0x725e, 0x7260, 0x7263, 0x7268, 0x726b, 0x726e, 0x726f, 0x7271, 0x7277, 0x7278, 0x727b, 0x727c, 0x727f, 0x7284, 0x7289, 0x728d, 0x728e, 0x7293, 0x729b, 0x72a8, 0x72ad, 0x72ae, 0x72b1, 0x72b4, 0x72be, 0x72c1, 0x72c7, 0x72c9, 0x72cc, 0x72d5, 0x72d6, 0x72d8, 0x72df, 0x72e5, 0x72f3, 0x72f4, 0x72fa, 0x72fb, /* 0x4b */ 0x72fe, 0x7302, 0x7304, 0x7305, 0x7307, 0x730b, 0x730d, 0x7312, 0x7313, 0x7318, 0x7319, 0x731e, 0x7322, 0x7324, 0x7327, 0x7328, 0x732c, 0x7331, 0x7332, 0x7335, 0x733a, 0x733b, 0x733d, 0x7343, 0x734d, 0x7350, 0x7352, 0x7356, 0x7358, 0x735d, 0x735e, 0x735f, 0x7360, 0x7366, 0x7367, 0x7369, 0x736b, 0x736c, 0x736e, 0x736f, 0x7371, 0x7377, 0x7379, 0x737c, 0x7380, 0x7381, 0x7383, 0x7385, 0x7386, 0x738e, 0x7390, 0x7393, 0x7395, 0x7397, 0x7398, 0x739c, 0x739e, 0x739f, 0x73a0, 0x73a2, 0x73a5, 0x73a6, 0x73aa, 0x73ab, 0x73ad, 0x73b5, 0x73b7, 0x73b9, 0x73bc, 0x73bd, 0x73bf, 0x73c5, 0x73c6, 0x73c9, 0x73cb, 0x73cc, 0x73cf, 0x73d2, 0x73d3, 0x73d6, 0x73d9, 0x73dd, 0x73e1, 0x73e3, 0x73e6, 0x73e7, 0x73e9, 0x73f4, 0x73f5, 0x73f7, 0x73f9, 0x73fa, 0x73fb, 0x73fd, /* 0x4c */ 0x73ff, 0x7400, 0x7401, 0x7404, 0x7407, 0x740a, 0x7411, 0x741a, 0x741b, 0x7424, 0x7426, 0x7428, 0x7429, 0x742a, 0x742b, 0x742c, 0x742d, 0x742e, 0x742f, 0x7430, 0x7431, 0x7439, 0x7440, 0x7443, 0x7444, 0x7446, 0x7447, 0x744b, 0x744d, 0x7451, 0x7452, 0x7457, 0x745d, 0x7462, 0x7466, 0x7467, 0x7468, 0x746b, 0x746d, 0x746e, 0x7471, 0x7472, 0x7480, 0x7481, 0x7485, 0x7486, 0x7487, 0x7489, 0x748f, 0x7490, 0x7491, 0x7492, 0x7498, 0x7499, 0x749a, 0x749c, 0x749f, 0x74a0, 0x74a1, 0x74a3, 0x74a6, 0x74a8, 0x74a9, 0x74aa, 0x74ab, 0x74ae, 0x74af, 0x74b1, 0x74b2, 0x74b5, 0x74b9, 0x74bb, 0x74bf, 0x74c8, 0x74c9, 0x74cc, 0x74d0, 0x74d3, 0x74d8, 0x74da, 0x74db, 0x74de, 0x74df, 0x74e4, 0x74e8, 0x74ea, 0x74eb, 0x74ef, 0x74f4, 0x74fa, 0x74fb, 0x74fc, 0x74ff, 0x7506, /* 0x4d */ 0x7512, 0x7516, 0x7517, 0x7520, 0x7521, 0x7524, 0x7527, 0x7529, 0x752a, 0x752f, 0x7536, 0x7539, 0x753d, 0x753e, 0x753f, 0x7540, 0x7543, 0x7547, 0x7548, 0x754e, 0x7550, 0x7552, 0x7557, 0x755e, 0x755f, 0x7561, 0x756f, 0x7571, 0x7579, 0x757a, 0x757b, 0x757c, 0x757d, 0x757e, 0x7581, 0x7585, 0x7590, 0x7592, 0x7593, 0x7595, 0x7599, 0x759c, 0x75a2, 0x75a4, 0x75b4, 0x75ba, 0x75bf, 0x75c0, 0x75c1, 0x75c4, 0x75c6, 0x75cc, 0x75ce, 0x75cf, 0x75d7, 0x75dc, 0x75df, 0x75e0, 0x75e1, 0x75e4, 0x75e7, 0x75ec, 0x75ee, 0x75ef, 0x75f1, 0x75f9, 0x7600, 0x7602, 0x7603, 0x7604, 0x7607, 0x7608, 0x760a, 0x760c, 0x760f, 0x7612, 0x7613, 0x7615, 0x7616, 0x7619, 0x761b, 0x761c, 0x761d, 0x761e, 0x7623, 0x7625, 0x7626, 0x7629, 0x762d, 0x7632, 0x7633, 0x7635, 0x7638, 0x7639, /* 0x4e */ 0x763a, 0x763c, 0x764a, 0x7640, 0x7641, 0x7643, 0x7644, 0x7645, 0x7649, 0x764b, 0x7655, 0x7659, 0x765f, 0x7664, 0x7665, 0x766d, 0x766e, 0x766f, 0x7671, 0x7674, 0x7681, 0x7685, 0x768c, 0x768d, 0x7695, 0x769b, 0x769c, 0x769d, 0x769f, 0x76a0, 0x76a2, 0x76a3, 0x76a4, 0x76a5, 0x76a6, 0x76a7, 0x76a8, 0x76aa, 0x76ad, 0x76bd, 0x76c1, 0x76c5, 0x76c9, 0x76cb, 0x76cc, 0x76ce, 0x76d4, 0x76d9, 0x76e0, 0x76e6, 0x76e8, 0x76ec, 0x76f0, 0x76f1, 0x76f6, 0x76f9, 0x76fc, 0x7700, 0x7706, 0x770a, 0x770e, 0x7712, 0x7714, 0x7715, 0x7717, 0x7719, 0x771a, 0x771c, 0x7722, 0x7728, 0x772d, 0x772e, 0x772f, 0x7734, 0x7735, 0x7736, 0x7739, 0x773d, 0x773e, 0x7742, 0x7745, 0x7746, 0x774a, 0x774d, 0x774e, 0x774f, 0x7752, 0x7756, 0x7757, 0x775c, 0x775e, 0x775f, 0x7760, 0x7762, /* 0x4f */ 0x7764, 0x7767, 0x776a, 0x776c, 0x7770, 0x7772, 0x7773, 0x7774, 0x777a, 0x777d, 0x7780, 0x7784, 0x778c, 0x778d, 0x7794, 0x7795, 0x7796, 0x779a, 0x779f, 0x77a2, 0x77a7, 0x77aa, 0x77ae, 0x77af, 0x77b1, 0x77b5, 0x77be, 0x77c3, 0x77c9, 0x77d1, 0x77d2, 0x77d5, 0x77d9, 0x77de, 0x77df, 0x77e0, 0x77e4, 0x77e6, 0x77ea, 0x77ec, 0x77f0, 0x77f1, 0x77f4, 0x77f8, 0x77fb, 0x7805, 0x7806, 0x7809, 0x780d, 0x780e, 0x7811, 0x781d, 0x7821, 0x7822, 0x7823, 0x782d, 0x782e, 0x7830, 0x7835, 0x7837, 0x7843, 0x7844, 0x7847, 0x7848, 0x784c, 0x784e, 0x7852, 0x785c, 0x785e, 0x7860, 0x7861, 0x7863, 0x7864, 0x7868, 0x786a, 0x786e, 0x787a, 0x787e, 0x788a, 0x788f, 0x7894, 0x7898, 0x78a1, 0x789d, 0x789e, 0x789f, 0x78a4, 0x78a8, 0x78ac, 0x78ad, 0x78b0, 0x78b1, 0x78b2, 0x78b3, /* 0x50 */ 0x78bb, 0x78bd, 0x78bf, 0x78c7, 0x78c8, 0x78c9, 0x78cc, 0x78ce, 0x78d2, 0x78d3, 0x78d5, 0x78d6, 0x78e4, 0x78db, 0x78df, 0x78e0, 0x78e1, 0x78e6, 0x78ea, 0x78f2, 0x78f3, 0x7900, 0x78f6, 0x78f7, 0x78fa, 0x78fb, 0x78ff, 0x7906, 0x790c, 0x7910, 0x791a, 0x791c, 0x791e, 0x791f, 0x7920, 0x7925, 0x7927, 0x7929, 0x792d, 0x7931, 0x7934, 0x7935, 0x793b, 0x793d, 0x793f, 0x7944, 0x7945, 0x7946, 0x794a, 0x794b, 0x794f, 0x7951, 0x7954, 0x7958, 0x795b, 0x795c, 0x7967, 0x7969, 0x796b, 0x7972, 0x7979, 0x797b, 0x797c, 0x797e, 0x798b, 0x798c, 0x7991, 0x7993, 0x7994, 0x7995, 0x7996, 0x7998, 0x799b, 0x799c, 0x79a1, 0x79a8, 0x79a9, 0x79ab, 0x79af, 0x79b1, 0x79b4, 0x79b8, 0x79bb, 0x79c2, 0x79c4, 0x79c7, 0x79c8, 0x79ca, 0x79cf, 0x79d4, 0x79d6, 0x79da, 0x79dd, 0x79de, /* 0x51 */ 0x79e0, 0x79e2, 0x79e5, 0x79ea, 0x79eb, 0x79ed, 0x79f1, 0x79f8, 0x79fc, 0x7a02, 0x7a03, 0x7a07, 0x7a09, 0x7a0a, 0x7a0c, 0x7a11, 0x7a15, 0x7a1b, 0x7a1e, 0x7a21, 0x7a27, 0x7a2b, 0x7a2d, 0x7a2f, 0x7a30, 0x7a34, 0x7a35, 0x7a38, 0x7a39, 0x7a3a, 0x7a44, 0x7a45, 0x7a47, 0x7a48, 0x7a4c, 0x7a55, 0x7a56, 0x7a59, 0x7a5c, 0x7a5d, 0x7a5f, 0x7a60, 0x7a65, 0x7a67, 0x7a6a, 0x7a6d, 0x7a75, 0x7a78, 0x7a7e, 0x7a80, 0x7a82, 0x7a85, 0x7a86, 0x7a8a, 0x7a8b, 0x7a90, 0x7a91, 0x7a94, 0x7a9e, 0x7aa0, 0x7aa3, 0x7aac, 0x7ab3, 0x7ab5, 0x7ab9, 0x7abb, 0x7abc, 0x7ac6, 0x7ac9, 0x7acc, 0x7ace, 0x7ad1, 0x7adb, 0x7ae8, 0x7ae9, 0x7aeb, 0x7aec, 0x7af1, 0x7af4, 0x7afb, 0x7afd, 0x7afe, 0x7b07, 0x7b14, 0x7b1f, 0x7b23, 0x7b27, 0x7b29, 0x7b2a, 0x7b2b, 0x7b2d, 0x7b2e, 0x7b2f, 0x7b30, /* 0x52 */ 0x7b31, 0x7b34, 0x7b3d, 0x7b3f, 0x7b40, 0x7b41, 0x7b47, 0x7b4e, 0x7b55, 0x7b60, 0x7b64, 0x7b66, 0x7b69, 0x7b6a, 0x7b6d, 0x7b6f, 0x7b72, 0x7b73, 0x7b77, 0x7b84, 0x7b89, 0x7b8e, 0x7b90, 0x7b91, 0x7b96, 0x7b9b, 0x7b9e, 0x7ba0, 0x7ba5, 0x7bac, 0x7baf, 0x7bb0, 0x7bb2, 0x7bb5, 0x7bb6, 0x7bba, 0x7bbb, 0x7bbc, 0x7bbd, 0x7bc2, 0x7bc5, 0x7bc8, 0x7bca, 0x7bd4, 0x7bd6, 0x7bd7, 0x7bd9, 0x7bda, 0x7bdb, 0x7be8, 0x7bea, 0x7bf2, 0x7bf4, 0x7bf5, 0x7bf8, 0x7bf9, 0x7bfa, 0x7bfc, 0x7bfe, 0x7c01, 0x7c02, 0x7c03, 0x7c04, 0x7c06, 0x7c09, 0x7c0b, 0x7c0c, 0x7c0e, 0x7c0f, 0x7c19, 0x7c1b, 0x7c20, 0x7c25, 0x7c26, 0x7c28, 0x7c2c, 0x7c31, 0x7c33, 0x7c34, 0x7c36, 0x7c39, 0x7c3a, 0x7c46, 0x7c4a, 0x7c55, 0x7c51, 0x7c52, 0x7c53, 0x7c59, 0x7c5a, 0x7c5b, 0x7c5c, 0x7c5d, 0x7c5e, /* 0x53 */ 0x7c61, 0x7c63, 0x7c67, 0x7c69, 0x7c6d, 0x7c6e, 0x7c70, 0x7c72, 0x7c79, 0x7c7c, 0x7c7d, 0x7c86, 0x7c87, 0x7c8f, 0x7c94, 0x7c9e, 0x7ca0, 0x7ca6, 0x7cb0, 0x7cb6, 0x7cb7, 0x7cba, 0x7cbb, 0x7cbc, 0x7cbf, 0x7cc4, 0x7cc7, 0x7cc8, 0x7cc9, 0x7ccd, 0x7ccf, 0x7cd3, 0x7cd4, 0x7cd5, 0x7cd7, 0x7cd9, 0x7cda, 0x7cdd, 0x7ce6, 0x7ce9, 0x7ceb, 0x7cf5, 0x7d03, 0x7d07, 0x7d08, 0x7d09, 0x7d0f, 0x7d11, 0x7d12, 0x7d13, 0x7d16, 0x7d1d, 0x7d1e, 0x7d23, 0x7d26, 0x7d2a, 0x7d2d, 0x7d31, 0x7d3c, 0x7d3d, 0x7d3e, 0x7d40, 0x7d41, 0x7d47, 0x7d48, 0x7d4d, 0x7d51, 0x7d53, 0x7d57, 0x7d59, 0x7d5a, 0x7d5c, 0x7d5d, 0x7d65, 0x7d67, 0x7d6a, 0x7d70, 0x7d78, 0x7d7a, 0x7d7b, 0x7d7f, 0x7d81, 0x7d82, 0x7d83, 0x7d85, 0x7d86, 0x7d88, 0x7d8b, 0x7d8c, 0x7d8d, 0x7d91, 0x7d96, 0x7d97, 0x7d9d, /* 0x54 */ 0x7d9e, 0x7da6, 0x7da7, 0x7daa, 0x7db3, 0x7db6, 0x7db7, 0x7db9, 0x7dc2, 0x7dc3, 0x7dc4, 0x7dc5, 0x7dc6, 0x7dcc, 0x7dcd, 0x7dce, 0x7dd7, 0x7dd9, 0x7e00, 0x7de2, 0x7de5, 0x7de6, 0x7dea, 0x7deb, 0x7ded, 0x7df1, 0x7df5, 0x7df6, 0x7df9, 0x7dfa, 0x7e08, 0x7e10, 0x7e11, 0x7e15, 0x7e17, 0x7e1c, 0x7e1d, 0x7e20, 0x7e27, 0x7e28, 0x7e2c, 0x7e2d, 0x7e2f, 0x7e33, 0x7e36, 0x7e3f, 0x7e44, 0x7e45, 0x7e47, 0x7e4e, 0x7e50, 0x7e52, 0x7e58, 0x7e5f, 0x7e61, 0x7e62, 0x7e65, 0x7e6b, 0x7e6e, 0x7e6f, 0x7e73, 0x7e78, 0x7e7e, 0x7e81, 0x7e86, 0x7e87, 0x7e8a, 0x7e8d, 0x7e91, 0x7e95, 0x7e98, 0x7e9a, 0x7e9d, 0x7e9e, 0x7f3c, 0x7f3b, 0x7f3d, 0x7f3e, 0x7f3f, 0x7f43, 0x7f44, 0x7f47, 0x7f4f, 0x7f52, 0x7f53, 0x7f5b, 0x7f5c, 0x7f5d, 0x7f61, 0x7f63, 0x7f64, 0x7f65, 0x7f66, 0x7f6d, /* 0x55 */ 0x7f71, 0x7f7d, 0x7f7e, 0x7f7f, 0x7f80, 0x7f8b, 0x7f8d, 0x7f8f, 0x7f90, 0x7f91, 0x7f96, 0x7f97, 0x7f9c, 0x7fa1, 0x7fa2, 0x7fa6, 0x7faa, 0x7fad, 0x7fb4, 0x7fbc, 0x7fbf, 0x7fc0, 0x7fc3, 0x7fc8, 0x7fce, 0x7fcf, 0x7fdb, 0x7fdf, 0x7fe3, 0x7fe5, 0x7fe8, 0x7fec, 0x7fee, 0x7fef, 0x7ff2, 0x7ffa, 0x7ffd, 0x7ffe, 0x7fff, 0x8007, 0x8008, 0x800a, 0x800d, 0x800e, 0x800f, 0x8011, 0x8013, 0x8014, 0x8016, 0x801d, 0x801e, 0x801f, 0x8020, 0x8024, 0x8026, 0x802c, 0x802e, 0x8030, 0x8034, 0x8035, 0x8037, 0x8039, 0x803a, 0x803c, 0x803e, 0x8040, 0x8044, 0x8060, 0x8064, 0x8066, 0x806d, 0x8071, 0x8075, 0x8081, 0x8088, 0x808e, 0x809c, 0x809e, 0x80a6, 0x80a7, 0x80ab, 0x80b8, 0x80b9, 0x80c8, 0x80cd, 0x80cf, 0x80d2, 0x80d4, 0x80d5, 0x80d7, 0x80d8, 0x80e0, 0x80ed, 0x80ee, /* 0x56 */ 0x80f0, 0x80f2, 0x80f3, 0x80f6, 0x80f9, 0x80fa, 0x80fe, 0x8103, 0x810b, 0x8116, 0x8117, 0x8118, 0x811c, 0x811e, 0x8120, 0x8124, 0x8127, 0x812c, 0x8130, 0x8135, 0x813a, 0x813c, 0x8145, 0x8147, 0x814a, 0x814c, 0x8152, 0x8157, 0x8160, 0x8161, 0x8167, 0x8168, 0x8169, 0x816d, 0x816f, 0x8177, 0x8181, 0x8190, 0x8184, 0x8185, 0x8186, 0x818b, 0x818e, 0x8196, 0x8198, 0x819b, 0x819e, 0x81a2, 0x81ae, 0x81b2, 0x81b4, 0x81bb, 0x81cb, 0x81c3, 0x81c5, 0x81ca, 0x81ce, 0x81cf, 0x81d5, 0x81d7, 0x81db, 0x81dd, 0x81de, 0x81e1, 0x81e4, 0x81eb, 0x81ec, 0x81f0, 0x81f1, 0x81f2, 0x81f5, 0x81f6, 0x81f8, 0x81f9, 0x81fd, 0x81ff, 0x8200, 0x8203, 0x820f, 0x8213, 0x8214, 0x8219, 0x821a, 0x821d, 0x8221, 0x8222, 0x8228, 0x8232, 0x8234, 0x823a, 0x8243, 0x8244, 0x8245, 0x8246, /* 0x57 */ 0x824b, 0x824e, 0x824f, 0x8251, 0x8256, 0x825c, 0x8260, 0x8263, 0x8267, 0x826d, 0x8274, 0x827b, 0x827d, 0x827f, 0x8280, 0x8281, 0x8283, 0x8284, 0x8287, 0x8289, 0x828a, 0x828e, 0x8291, 0x8294, 0x8296, 0x8298, 0x829a, 0x829b, 0x82a0, 0x82a1, 0x82a3, 0x82a4, 0x82a7, 0x82a8, 0x82a9, 0x82aa, 0x82ae, 0x82b0, 0x82b2, 0x82b4, 0x82b7, 0x82ba, 0x82bc, 0x82be, 0x82bf, 0x82c6, 0x82d0, 0x82d5, 0x82da, 0x82e0, 0x82e2, 0x82e4, 0x82e8, 0x82ea, 0x82ed, 0x82ef, 0x82f6, 0x82f7, 0x82fd, 0x82fe, 0x8300, 0x8301, 0x8307, 0x8308, 0x830a, 0x830b, 0x8354, 0x831b, 0x831d, 0x831e, 0x831f, 0x8321, 0x8322, 0x832c, 0x832d, 0x832e, 0x8330, 0x8333, 0x8337, 0x833a, 0x833c, 0x833d, 0x8342, 0x8343, 0x8344, 0x8347, 0x834d, 0x834e, 0x8351, 0x8355, 0x8356, 0x8357, 0x8370, 0x8378, /* 0x58 */ 0x837d, 0x837f, 0x8380, 0x8382, 0x8384, 0x8386, 0x838d, 0x8392, 0x8394, 0x8395, 0x8398, 0x8399, 0x839b, 0x839c, 0x839d, 0x83a6, 0x83a7, 0x83a9, 0x83ac, 0x83be, 0x83bf, 0x83c0, 0x83c7, 0x83c9, 0x83cf, 0x83d0, 0x83d1, 0x83d4, 0x83dd, 0x8353, 0x83e8, 0x83ea, 0x83f6, 0x83f8, 0x83f9, 0x83fc, 0x8401, 0x8406, 0x840a, 0x840f, 0x8411, 0x8415, 0x8419, 0x83ad, 0x842f, 0x8439, 0x8445, 0x8447, 0x8448, 0x844a, 0x844d, 0x844f, 0x8451, 0x8452, 0x8456, 0x8458, 0x8459, 0x845a, 0x845c, 0x8460, 0x8464, 0x8465, 0x8467, 0x846a, 0x8470, 0x8473, 0x8474, 0x8476, 0x8478, 0x847c, 0x847d, 0x8481, 0x8485, 0x8492, 0x8493, 0x8495, 0x849e, 0x84a6, 0x84a8, 0x84a9, 0x84aa, 0x84af, 0x84b1, 0x84b4, 0x84ba, 0x84bd, 0x84be, 0x84c0, 0x84c2, 0x84c7, 0x84c8, 0x84cc, 0x84cf, 0x84d3, /* 0x59 */ 0x84dc, 0x84e7, 0x84ea, 0x84ef, 0x84f0, 0x84f1, 0x84f2, 0x84f7, 0x8532, 0x84fa, 0x84fb, 0x84fd, 0x8502, 0x8503, 0x8507, 0x850c, 0x850e, 0x8510, 0x851c, 0x851e, 0x8522, 0x8523, 0x8524, 0x8525, 0x8527, 0x852a, 0x852b, 0x852f, 0x8533, 0x8534, 0x8536, 0x853f, 0x8546, 0x854f, 0x8550, 0x8551, 0x8552, 0x8553, 0x8556, 0x8559, 0x855c, 0x855d, 0x855e, 0x855f, 0x8560, 0x8561, 0x8562, 0x8564, 0x856b, 0x856f, 0x8579, 0x857a, 0x857b, 0x857d, 0x857f, 0x8581, 0x8585, 0x8586, 0x8589, 0x858b, 0x858c, 0x858f, 0x8593, 0x8598, 0x859d, 0x859f, 0x85a0, 0x85a2, 0x85a5, 0x85a7, 0x85b4, 0x85b6, 0x85b7, 0x85b8, 0x85bc, 0x85bd, 0x85be, 0x85bf, 0x85c2, 0x85c7, 0x85ca, 0x85cb, 0x85ce, 0x85ad, 0x85d8, 0x85da, 0x85df, 0x85e0, 0x85e6, 0x85e8, 0x85ed, 0x85f3, 0x85f6, 0x85fc, /* 0x5a */ 0x85ff, 0x8600, 0x8604, 0x8605, 0x860d, 0x860e, 0x8610, 0x8611, 0x8612, 0x8618, 0x8619, 0x861b, 0x861e, 0x8621, 0x8627, 0x8629, 0x8636, 0x8638, 0x863a, 0x863c, 0x863d, 0x8640, 0x8642, 0x8646, 0x8652, 0x8653, 0x8656, 0x8657, 0x8658, 0x8659, 0x865d, 0x8660, 0x8661, 0x8662, 0x8663, 0x8664, 0x8669, 0x866c, 0x866f, 0x8675, 0x8676, 0x8677, 0x867a, 0x868d, 0x8691, 0x8696, 0x8698, 0x869a, 0x869c, 0x86a1, 0x86a6, 0x86a7, 0x86a8, 0x86ad, 0x86b1, 0x86b3, 0x86b4, 0x86b5, 0x86b7, 0x86b8, 0x86b9, 0x86bf, 0x86c0, 0x86c1, 0x86c3, 0x86c5, 0x86d1, 0x86d2, 0x86d5, 0x86d7, 0x86da, 0x86dc, 0x86e0, 0x86e3, 0x86e5, 0x86e7, 0x8688, 0x86fa, 0x86fc, 0x86fd, 0x8704, 0x8705, 0x8707, 0x870b, 0x870e, 0x870f, 0x8710, 0x8713, 0x8714, 0x8719, 0x871e, 0x871f, 0x8721, 0x8723, /* 0x5b */ 0x8728, 0x872e, 0x872f, 0x8731, 0x8732, 0x8739, 0x873a, 0x873c, 0x873d, 0x873e, 0x8740, 0x8743, 0x8745, 0x874d, 0x8758, 0x875d, 0x8761, 0x8764, 0x8765, 0x876f, 0x8771, 0x8772, 0x877b, 0x8783, 0x8784, 0x8785, 0x8786, 0x8787, 0x8788, 0x8789, 0x878b, 0x878c, 0x8790, 0x8793, 0x8795, 0x8797, 0x8798, 0x8799, 0x879e, 0x87a0, 0x87a3, 0x87a7, 0x87ac, 0x87ad, 0x87ae, 0x87b1, 0x87b5, 0x87be, 0x87bf, 0x87c1, 0x87c8, 0x87c9, 0x87ca, 0x87ce, 0x87d5, 0x87d6, 0x87d9, 0x87da, 0x87dc, 0x87df, 0x87e2, 0x87e3, 0x87e4, 0x87ea, 0x87eb, 0x87ed, 0x87f1, 0x87f3, 0x87f8, 0x87fa, 0x87ff, 0x8801, 0x8803, 0x8806, 0x8809, 0x880a, 0x880b, 0x8810, 0x8819, 0x8812, 0x8813, 0x8814, 0x8818, 0x881a, 0x881b, 0x881c, 0x881e, 0x881f, 0x8828, 0x882d, 0x882e, 0x8830, 0x8832, 0x8835, /* 0x5c */ 0x883a, 0x883c, 0x8841, 0x8843, 0x8845, 0x8848, 0x8849, 0x884a, 0x884b, 0x884e, 0x8851, 0x8855, 0x8856, 0x8858, 0x885a, 0x885c, 0x885f, 0x8860, 0x8864, 0x8869, 0x8871, 0x8879, 0x887b, 0x8880, 0x8898, 0x889a, 0x889b, 0x889c, 0x889f, 0x88a0, 0x88a8, 0x88aa, 0x88ba, 0x88bd, 0x88be, 0x88c0, 0x88ca, 0x88cb, 0x88cc, 0x88cd, 0x88ce, 0x88d1, 0x88d2, 0x88d3, 0x88db, 0x88de, 0x88e7, 0x88ef, 0x88f0, 0x88f1, 0x88f5, 0x88f7, 0x8901, 0x8906, 0x890d, 0x890e, 0x890f, 0x8915, 0x8916, 0x8918, 0x8919, 0x891a, 0x891c, 0x8920, 0x8926, 0x8927, 0x8928, 0x8930, 0x8931, 0x8932, 0x8935, 0x8939, 0x893a, 0x893e, 0x8940, 0x8942, 0x8945, 0x8946, 0x8949, 0x894f, 0x8952, 0x8957, 0x895a, 0x895b, 0x895c, 0x8961, 0x8962, 0x8963, 0x896b, 0x896e, 0x8970, 0x8973, 0x8975, 0x897a, /* 0x5d */ 0x897b, 0x897c, 0x897d, 0x8989, 0x898d, 0x8990, 0x8994, 0x8995, 0x899b, 0x899c, 0x899f, 0x89a0, 0x89a5, 0x89b0, 0x89b4, 0x89b5, 0x89b6, 0x89b7, 0x89bc, 0x89d4, 0x89d5, 0x89d6, 0x89d7, 0x89d8, 0x89e5, 0x89e9, 0x89eb, 0x89ed, 0x89f1, 0x89f3, 0x89f6, 0x89f9, 0x89fd, 0x89ff, 0x8a04, 0x8a05, 0x8a07, 0x8a0f, 0x8a11, 0x8a12, 0x8a14, 0x8a15, 0x8a1e, 0x8a20, 0x8a22, 0x8a24, 0x8a26, 0x8a2b, 0x8a2c, 0x8a2f, 0x8a35, 0x8a37, 0x8a3d, 0x8a3e, 0x8a40, 0x8a43, 0x8a45, 0x8a47, 0x8a49, 0x8a4d, 0x8a4e, 0x8a53, 0x8a56, 0x8a57, 0x8a58, 0x8a5c, 0x8a5d, 0x8a61, 0x8a65, 0x8a67, 0x8a75, 0x8a76, 0x8a77, 0x8a79, 0x8a7a, 0x8a7b, 0x8a7e, 0x8a7f, 0x8a80, 0x8a83, 0x8a86, 0x8a8b, 0x8a8f, 0x8a90, 0x8a92, 0x8a96, 0x8a97, 0x8a99, 0x8a9f, 0x8aa7, 0x8aa9, 0x8aae, 0x8aaf, 0x8ab3, /* 0x5e */ 0x8ab6, 0x8ab7, 0x8abb, 0x8abe, 0x8ac3, 0x8ac6, 0x8ac8, 0x8ac9, 0x8aca, 0x8ad1, 0x8ad3, 0x8ad4, 0x8ad5, 0x8ad7, 0x8add, 0x8adf, 0x8aec, 0x8af0, 0x8af4, 0x8af5, 0x8af6, 0x8afc, 0x8aff, 0x8b05, 0x8b06, 0x8b0b, 0x8b11, 0x8b1c, 0x8b1e, 0x8b1f, 0x8b0a, 0x8b2d, 0x8b30, 0x8b37, 0x8b3c, 0x8b42, 0x8b43, 0x8b44, 0x8b45, 0x8b46, 0x8b48, 0x8b52, 0x8b53, 0x8b54, 0x8b59, 0x8b4d, 0x8b5e, 0x8b63, 0x8b6d, 0x8b76, 0x8b78, 0x8b79, 0x8b7c, 0x8b7e, 0x8b81, 0x8b84, 0x8b85, 0x8b8b, 0x8b8d, 0x8b8f, 0x8b94, 0x8b95, 0x8b9c, 0x8b9e, 0x8b9f, 0x8c38, 0x8c39, 0x8c3d, 0x8c3e, 0x8c45, 0x8c47, 0x8c49, 0x8c4b, 0x8c4f, 0x8c51, 0x8c53, 0x8c54, 0x8c57, 0x8c58, 0x8c5b, 0x8c5d, 0x8c59, 0x8c63, 0x8c64, 0x8c66, 0x8c68, 0x8c69, 0x8c6d, 0x8c73, 0x8c75, 0x8c76, 0x8c7b, 0x8c7e, 0x8c86, /* 0x5f */ 0x8c87, 0x8c8b, 0x8c90, 0x8c92, 0x8c93, 0x8c99, 0x8c9b, 0x8c9c, 0x8ca4, 0x8cb9, 0x8cba, 0x8cc5, 0x8cc6, 0x8cc9, 0x8ccb, 0x8ccf, 0x8cd6, 0x8cd5, 0x8cd9, 0x8cdd, 0x8ce1, 0x8ce8, 0x8cec, 0x8cef, 0x8cf0, 0x8cf2, 0x8cf5, 0x8cf7, 0x8cf8, 0x8cfe, 0x8cff, 0x8d01, 0x8d03, 0x8d09, 0x8d12, 0x8d17, 0x8d1b, 0x8d65, 0x8d69, 0x8d6c, 0x8d6e, 0x8d7f, 0x8d82, 0x8d84, 0x8d88, 0x8d8d, 0x8d90, 0x8d91, 0x8d95, 0x8d9e, 0x8d9f, 0x8da0, 0x8da6, 0x8dab, 0x8dac, 0x8daf, 0x8db2, 0x8db5, 0x8db7, 0x8db9, 0x8dbb, 0x8dc0, 0x8dc5, 0x8dc6, 0x8dc7, 0x8dc8, 0x8dca, 0x8dce, 0x8dd1, 0x8dd4, 0x8dd5, 0x8dd7, 0x8dd9, 0x8de4, 0x8de5, 0x8de7, 0x8dec, 0x8df0, 0x8dbc, 0x8df1, 0x8df2, 0x8df4, 0x8dfd, 0x8e01, 0x8e04, 0x8e05, 0x8e06, 0x8e0b, 0x8e11, 0x8e14, 0x8e16, 0x8e20, 0x8e21, 0x8e22, /* 0x60 */ 0x8e23, 0x8e26, 0x8e27, 0x8e31, 0x8e33, 0x8e36, 0x8e37, 0x8e38, 0x8e39, 0x8e3d, 0x8e40, 0x8e41, 0x8e4b, 0x8e4d, 0x8e4e, 0x8e4f, 0x8e54, 0x8e5b, 0x8e5c, 0x8e5d, 0x8e5e, 0x8e61, 0x8e62, 0x8e69, 0x8e6c, 0x8e6d, 0x8e6f, 0x8e70, 0x8e71, 0x8e79, 0x8e7a, 0x8e7b, 0x8e82, 0x8e83, 0x8e89, 0x8e90, 0x8e92, 0x8e95, 0x8e9a, 0x8e9b, 0x8e9d, 0x8e9e, 0x8ea2, 0x8ea7, 0x8ea9, 0x8ead, 0x8eae, 0x8eb3, 0x8eb5, 0x8eba, 0x8ebb, 0x8ec0, 0x8ec1, 0x8ec3, 0x8ec4, 0x8ec7, 0x8ecf, 0x8ed1, 0x8ed4, 0x8edc, 0x8ee8, 0x8eee, 0x8ef0, 0x8ef1, 0x8ef7, 0x8ef9, 0x8efa, 0x8eed, 0x8f00, 0x8f02, 0x8f07, 0x8f08, 0x8f0f, 0x8f10, 0x8f16, 0x8f17, 0x8f18, 0x8f1e, 0x8f20, 0x8f21, 0x8f23, 0x8f25, 0x8f27, 0x8f28, 0x8f2c, 0x8f2d, 0x8f2e, 0x8f34, 0x8f35, 0x8f36, 0x8f37, 0x8f3a, 0x8f40, 0x8f41, /* 0x61 */ 0x8f43, 0x8f47, 0x8f4f, 0x8f51, 0x8f52, 0x8f53, 0x8f54, 0x8f55, 0x8f58, 0x8f5d, 0x8f5e, 0x8f65, 0x8f9d, 0x8fa0, 0x8fa1, 0x8fa4, 0x8fa5, 0x8fa6, 0x8fb5, 0x8fb6, 0x8fb8, 0x8fbe, 0x8fc0, 0x8fc1, 0x8fc6, 0x8fca, 0x8fcb, 0x8fcd, 0x8fd0, 0x8fd2, 0x8fd3, 0x8fd5, 0x8fe0, 0x8fe3, 0x8fe4, 0x8fe8, 0x8fee, 0x8ff1, 0x8ff5, 0x8ff6, 0x8ffb, 0x8ffe, 0x9002, 0x9004, 0x9008, 0x900c, 0x9018, 0x901b, 0x9028, 0x9029, 0x902f, 0x902a, 0x902c, 0x902d, 0x9033, 0x9034, 0x9037, 0x903f, 0x9043, 0x9044, 0x904c, 0x905b, 0x905d, 0x9062, 0x9066, 0x9067, 0x906c, 0x9070, 0x9074, 0x9079, 0x9085, 0x9088, 0x908b, 0x908c, 0x908e, 0x9090, 0x9095, 0x9097, 0x9098, 0x9099, 0x909b, 0x90a0, 0x90a1, 0x90a2, 0x90a5, 0x90b0, 0x90b2, 0x90b3, 0x90b4, 0x90b6, 0x90bd, 0x90cc, 0x90be, 0x90c3, /* 0x62 */ 0x90c4, 0x90c5, 0x90c7, 0x90c8, 0x90d5, 0x90d7, 0x90d8, 0x90d9, 0x90dc, 0x90dd, 0x90df, 0x90e5, 0x90d2, 0x90f6, 0x90eb, 0x90ef, 0x90f0, 0x90f4, 0x90fe, 0x90ff, 0x9100, 0x9104, 0x9105, 0x9106, 0x9108, 0x910d, 0x9110, 0x9114, 0x9116, 0x9117, 0x9118, 0x911a, 0x911c, 0x911e, 0x9120, 0x9125, 0x9122, 0x9123, 0x9127, 0x9129, 0x912e, 0x912f, 0x9131, 0x9134, 0x9136, 0x9137, 0x9139, 0x913a, 0x913c, 0x913d, 0x9143, 0x9147, 0x9148, 0x914f, 0x9153, 0x9157, 0x9159, 0x915a, 0x915b, 0x9161, 0x9164, 0x9167, 0x916d, 0x9174, 0x9179, 0x917a, 0x917b, 0x9181, 0x9183, 0x9185, 0x9186, 0x918a, 0x918e, 0x9191, 0x9193, 0x9194, 0x9195, 0x9198, 0x919e, 0x91a1, 0x91a6, 0x91a8, 0x91ac, 0x91ad, 0x91ae, 0x91b0, 0x91b1, 0x91b2, 0x91b3, 0x91b6, 0x91bb, 0x91bc, 0x91bd, 0x91bf, /* 0x63 */ 0x91c2, 0x91c3, 0x91c5, 0x91d3, 0x91d4, 0x91d7, 0x91d9, 0x91da, 0x91de, 0x91e4, 0x91e5, 0x91e9, 0x91ea, 0x91ec, 0x91ed, 0x91ee, 0x91ef, 0x91f0, 0x91f1, 0x91f7, 0x91f9, 0x91fb, 0x91fd, 0x9200, 0x9201, 0x9204, 0x9205, 0x9206, 0x9207, 0x9209, 0x920a, 0x920c, 0x9210, 0x9212, 0x9213, 0x9216, 0x9218, 0x921c, 0x921d, 0x9223, 0x9224, 0x9225, 0x9226, 0x9228, 0x922e, 0x922f, 0x9230, 0x9233, 0x9235, 0x9236, 0x9238, 0x9239, 0x923a, 0x923c, 0x923e, 0x9240, 0x9242, 0x9243, 0x9246, 0x9247, 0x924a, 0x924d, 0x924e, 0x924f, 0x9251, 0x9258, 0x9259, 0x925c, 0x925d, 0x9260, 0x9261, 0x9265, 0x9267, 0x9268, 0x9269, 0x926e, 0x926f, 0x9270, 0x9275, 0x9276, 0x9277, 0x9278, 0x9279, 0x927b, 0x927c, 0x927d, 0x927f, 0x9288, 0x9289, 0x928a, 0x928d, 0x928e, 0x9292, 0x9297, /* 0x64 */ 0x9299, 0x929f, 0x92a0, 0x92a4, 0x92a5, 0x92a7, 0x92a8, 0x92ab, 0x92af, 0x92b2, 0x92b6, 0x92b8, 0x92ba, 0x92bb, 0x92bc, 0x92bd, 0x92bf, 0x92c0, 0x92c1, 0x92c2, 0x92c3, 0x92c5, 0x92c6, 0x92c7, 0x92c8, 0x92cb, 0x92cc, 0x92cd, 0x92ce, 0x92d0, 0x92d3, 0x92d5, 0x92d7, 0x92d8, 0x92d9, 0x92dc, 0x92dd, 0x92df, 0x92e0, 0x92e1, 0x92e3, 0x92e5, 0x92e7, 0x92e8, 0x92ec, 0x92ee, 0x92f0, 0x92f9, 0x92fb, 0x92ff, 0x9300, 0x9302, 0x9308, 0x930d, 0x9311, 0x9314, 0x9315, 0x931c, 0x931d, 0x931e, 0x931f, 0x9321, 0x9324, 0x9325, 0x9327, 0x9329, 0x932a, 0x9333, 0x9334, 0x9336, 0x9337, 0x9347, 0x9348, 0x9349, 0x9350, 0x9351, 0x9352, 0x9355, 0x9357, 0x9358, 0x935a, 0x935e, 0x9364, 0x9365, 0x9367, 0x9369, 0x936a, 0x936d, 0x936f, 0x9370, 0x9371, 0x9373, 0x9374, 0x9376, /* 0x65 */ 0x937a, 0x937d, 0x937f, 0x9380, 0x9381, 0x9382, 0x9388, 0x938a, 0x938b, 0x938d, 0x938f, 0x9392, 0x9395, 0x9398, 0x939b, 0x939e, 0x93a1, 0x93a3, 0x93a4, 0x93a6, 0x93a8, 0x93ab, 0x93b4, 0x93b5, 0x93b6, 0x93ba, 0x93a9, 0x93c1, 0x93c4, 0x93c5, 0x93c6, 0x93c7, 0x93c9, 0x93ca, 0x93cb, 0x93cc, 0x93cd, 0x93d3, 0x93d9, 0x93dc, 0x93de, 0x93df, 0x93e2, 0x93e6, 0x93e7, 0x93f9, 0x93f7, 0x93f8, 0x93fa, 0x93fb, 0x93fd, 0x9401, 0x9402, 0x9404, 0x9408, 0x9409, 0x940d, 0x940e, 0x940f, 0x9415, 0x9416, 0x9417, 0x941f, 0x942e, 0x942f, 0x9431, 0x9432, 0x9433, 0x9434, 0x943b, 0x943f, 0x943d, 0x9443, 0x9445, 0x9448, 0x944a, 0x944c, 0x9455, 0x9459, 0x945c, 0x945f, 0x9461, 0x9463, 0x9468, 0x946b, 0x946d, 0x946e, 0x946f, 0x9471, 0x9472, 0x9484, 0x9483, 0x9578, 0x9579, /* 0x66 */ 0x957e, 0x9584, 0x9588, 0x958c, 0x958d, 0x958e, 0x959d, 0x959e, 0x959f, 0x95a1, 0x95a6, 0x95a9, 0x95ab, 0x95ac, 0x95b4, 0x95b6, 0x95ba, 0x95bd, 0x95bf, 0x95c6, 0x95c8, 0x95c9, 0x95cb, 0x95d0, 0x95d1, 0x95d2, 0x95d3, 0x95d9, 0x95da, 0x95dd, 0x95de, 0x95df, 0x95e0, 0x95e4, 0x95e6, 0x961d, 0x961e, 0x9622, 0x9624, 0x9625, 0x9626, 0x962c, 0x9631, 0x9633, 0x9637, 0x9638, 0x9639, 0x963a, 0x963c, 0x963d, 0x9641, 0x9652, 0x9654, 0x9656, 0x9657, 0x9658, 0x9661, 0x966e, 0x9674, 0x967b, 0x967c, 0x967e, 0x967f, 0x9681, 0x9682, 0x9683, 0x9684, 0x9689, 0x9691, 0x9696, 0x969a, 0x969d, 0x969f, 0x96a4, 0x96a5, 0x96a6, 0x96a9, 0x96ae, 0x96af, 0x96b3, 0x96ba, 0x96ca, 0x96d2, 0x5db2, 0x96d8, 0x96da, 0x96dd, 0x96de, 0x96df, 0x96e9, 0x96ef, 0x96f1, 0x96fa, 0x9702, /* 0x67 */ 0x9703, 0x9705, 0x9709, 0x971a, 0x971b, 0x971d, 0x9721, 0x9722, 0x9723, 0x9728, 0x9731, 0x9733, 0x9741, 0x9743, 0x974a, 0x974e, 0x974f, 0x9755, 0x9757, 0x9758, 0x975a, 0x975b, 0x9763, 0x9767, 0x976a, 0x976e, 0x9773, 0x9776, 0x9777, 0x9778, 0x977b, 0x977d, 0x977f, 0x9780, 0x9789, 0x9795, 0x9796, 0x9797, 0x9799, 0x979a, 0x979e, 0x979f, 0x97a2, 0x97ac, 0x97ae, 0x97b1, 0x97b2, 0x97b5, 0x97b6, 0x97b8, 0x97b9, 0x97ba, 0x97bc, 0x97be, 0x97bf, 0x97c1, 0x97c4, 0x97c5, 0x97c7, 0x97c9, 0x97ca, 0x97cc, 0x97cd, 0x97ce, 0x97d0, 0x97d1, 0x97d4, 0x97d7, 0x97d8, 0x97d9, 0x97dd, 0x97de, 0x97e0, 0x97db, 0x97e1, 0x97e4, 0x97ef, 0x97f1, 0x97f4, 0x97f7, 0x97f8, 0x97fa, 0x9807, 0x980a, 0x9819, 0x980d, 0x980e, 0x9814, 0x9816, 0x981c, 0x981e, 0x9820, 0x9823, 0x9826, /* 0x68 */ 0x982b, 0x982e, 0x982f, 0x9830, 0x9832, 0x9833, 0x9835, 0x9825, 0x983e, 0x9844, 0x9847, 0x984a, 0x9851, 0x9852, 0x9853, 0x9856, 0x9857, 0x9859, 0x985a, 0x9862, 0x9863, 0x9865, 0x9866, 0x986a, 0x986c, 0x98ab, 0x98ad, 0x98ae, 0x98b0, 0x98b4, 0x98b7, 0x98b8, 0x98ba, 0x98bb, 0x98bf, 0x98c2, 0x98c5, 0x98c8, 0x98cc, 0x98e1, 0x98e3, 0x98e5, 0x98e6, 0x98e7, 0x98ea, 0x98f3, 0x98f6, 0x9902, 0x9907, 0x9908, 0x9911, 0x9915, 0x9916, 0x9917, 0x991a, 0x991b, 0x991c, 0x991f, 0x9922, 0x9926, 0x9927, 0x992b, 0x9931, 0x9932, 0x9933, 0x9934, 0x9935, 0x9939, 0x993a, 0x993b, 0x993c, 0x9940, 0x9941, 0x9946, 0x9947, 0x9948, 0x994d, 0x994e, 0x9954, 0x9958, 0x9959, 0x995b, 0x995c, 0x995e, 0x995f, 0x9960, 0x999b, 0x999d, 0x999f, 0x99a6, 0x99b0, 0x99b1, 0x99b2, 0x99b5, /* 0x69 */ 0x99b9, 0x99ba, 0x99bd, 0x99bf, 0x99c3, 0x99c9, 0x99d3, 0x99d4, 0x99d9, 0x99da, 0x99dc, 0x99de, 0x99e7, 0x99ea, 0x99eb, 0x99ec, 0x99f0, 0x99f4, 0x99f5, 0x99f9, 0x99fd, 0x99fe, 0x9a02, 0x9a03, 0x9a04, 0x9a0b, 0x9a0c, 0x9a10, 0x9a11, 0x9a16, 0x9a1e, 0x9a20, 0x9a22, 0x9a23, 0x9a24, 0x9a27, 0x9a2d, 0x9a2e, 0x9a33, 0x9a35, 0x9a36, 0x9a38, 0x9a47, 0x9a41, 0x9a44, 0x9a4a, 0x9a4b, 0x9a4c, 0x9a4e, 0x9a51, 0x9a54, 0x9a56, 0x9a5d, 0x9aaa, 0x9aac, 0x9aae, 0x9aaf, 0x9ab2, 0x9ab4, 0x9ab5, 0x9ab6, 0x9ab9, 0x9abb, 0x9abe, 0x9abf, 0x9ac1, 0x9ac3, 0x9ac6, 0x9ac8, 0x9ace, 0x9ad0, 0x9ad2, 0x9ad5, 0x9ad6, 0x9ad7, 0x9adb, 0x9adc, 0x9ae0, 0x9ae4, 0x9ae5, 0x9ae7, 0x9ae9, 0x9aec, 0x9af2, 0x9af3, 0x9af5, 0x9af9, 0x9afa, 0x9afd, 0x9aff, 0x9b00, 0x9b01, 0x9b02, 0x9b03, /* 0x6a */ 0x9b04, 0x9b05, 0x9b08, 0x9b09, 0x9b0b, 0x9b0c, 0x9b0d, 0x9b0e, 0x9b10, 0x9b12, 0x9b16, 0x9b19, 0x9b1b, 0x9b1c, 0x9b20, 0x9b26, 0x9b2b, 0x9b2d, 0x9b33, 0x9b34, 0x9b35, 0x9b37, 0x9b39, 0x9b3a, 0x9b3d, 0x9b48, 0x9b4b, 0x9b4c, 0x9b55, 0x9b56, 0x9b57, 0x9b5b, 0x9b5e, 0x9b61, 0x9b63, 0x9b65, 0x9b66, 0x9b68, 0x9b6a, 0x9b6b, 0x9b6c, 0x9b6d, 0x9b6e, 0x9b73, 0x9b75, 0x9b77, 0x9b78, 0x9b79, 0x9b7f, 0x9b80, 0x9b84, 0x9b85, 0x9b86, 0x9b87, 0x9b89, 0x9b8a, 0x9b8b, 0x9b8d, 0x9b8f, 0x9b90, 0x9b94, 0x9b9a, 0x9b9d, 0x9b9e, 0x9ba6, 0x9ba7, 0x9ba9, 0x9bac, 0x9bb0, 0x9bb1, 0x9bb2, 0x9bb7, 0x9bb8, 0x9bbb, 0x9bbc, 0x9bbe, 0x9bbf, 0x9bc1, 0x9bc7, 0x9bc8, 0x9bce, 0x9bd0, 0x9bd7, 0x9bd8, 0x9bdd, 0x9bdf, 0x9be5, 0x9be7, 0x9bea, 0x9beb, 0x9bef, 0x9bf3, 0x9bf7, 0x9bf8, /* 0x6b */ 0x9bf9, 0x9bfa, 0x9bfd, 0x9bff, 0x9c00, 0x9c02, 0x9c0b, 0x9c0f, 0x9c11, 0x9c16, 0x9c18, 0x9c19, 0x9c1a, 0x9c1c, 0x9c1e, 0x9c22, 0x9c23, 0x9c26, 0x9c27, 0x9c28, 0x9c29, 0x9c2a, 0x9c31, 0x9c35, 0x9c36, 0x9c37, 0x9c3d, 0x9c41, 0x9c43, 0x9c44, 0x9c45, 0x9c49, 0x9c4a, 0x9c4e, 0x9c4f, 0x9c50, 0x9c53, 0x9c54, 0x9c56, 0x9c58, 0x9c5b, 0x9c5d, 0x9c5e, 0x9c5f, 0x9c63, 0x9c69, 0x9c6a, 0x9c5c, 0x9c6b, 0x9c68, 0x9c6e, 0x9c70, 0x9c72, 0x9c75, 0x9c77, 0x9c7b, 0x9ce6, 0x9cf2, 0x9cf7, 0x9cf9, 0x9d0b, 0x9d02, 0x9d11, 0x9d17, 0x9d18, 0x9d1c, 0x9d1d, 0x9d1e, 0x9d2f, 0x9d30, 0x9d32, 0x9d33, 0x9d34, 0x9d3a, 0x9d3c, 0x9d45, 0x9d3d, 0x9d42, 0x9d43, 0x9d47, 0x9d4a, 0x9d53, 0x9d54, 0x9d5f, 0x9d63, 0x9d62, 0x9d65, 0x9d69, 0x9d6a, 0x9d6b, 0x9d70, 0x9d76, 0x9d77, 0x9d7b, /* 0x6c */ 0x9d7c, 0x9d7e, 0x9d83, 0x9d84, 0x9d86, 0x9d8a, 0x9d8d, 0x9d8e, 0x9d92, 0x9d93, 0x9d95, 0x9d96, 0x9d97, 0x9d98, 0x9da1, 0x9daa, 0x9dac, 0x9dae, 0x9db1, 0x9db5, 0x9db9, 0x9dbc, 0x9dbf, 0x9dc3, 0x9dc7, 0x9dc9, 0x9dca, 0x9dd4, 0x9dd5, 0x9dd6, 0x9dd7, 0x9dda, 0x9dde, 0x9ddf, 0x9de0, 0x9de5, 0x9de7, 0x9de9, 0x9deb, 0x9dee, 0x9df0, 0x9df3, 0x9df4, 0x9dfe, 0x9e0a, 0x9e02, 0x9e07, 0x9e0e, 0x9e10, 0x9e11, 0x9e12, 0x9e15, 0x9e16, 0x9e19, 0x9e1c, 0x9e1d, 0x9e7a, 0x9e7b, 0x9e7c, 0x9e80, 0x9e82, 0x9e83, 0x9e84, 0x9e85, 0x9e87, 0x9e8e, 0x9e8f, 0x9e96, 0x9e98, 0x9e9b, 0x9e9e, 0x9ea4, 0x9ea8, 0x9eac, 0x9eae, 0x9eaf, 0x9eb0, 0x9eb3, 0x9eb4, 0x9eb5, 0x9ec6, 0x9ec8, 0x9ecb, 0x9ed5, 0x9edf, 0x9ee4, 0x9ee7, 0x9eec, 0x9eed, 0x9eee, 0x9ef0, 0x9ef1, 0x9ef2, 0x9ef5, /* 0x6d */ 0x9ef8, 0x9eff, 0x9f02, 0x9f03, 0x9f09, 0x9f0f, 0x9f10, 0x9f11, 0x9f12, 0x9f14, 0x9f16, 0x9f17, 0x9f19, 0x9f1a, 0x9f1b, 0x9f1f, 0x9f22, 0x9f26, 0x9f2a, 0x9f2b, 0x9f2f, 0x9f31, 0x9f32, 0x9f34, 0x9f37, 0x9f39, 0x9f3a, 0x9f3c, 0x9f3d, 0x9f3f, 0x9f41, 0x9f43, 0x9f44, 0x9f45, 0x9f46, 0x9f47, 0x9f53, 0x9f55, 0x9f56, 0x9f57, 0x9f58, 0x9f5a, 0x9f5d, 0x9f5e, 0x9f68, 0x9f69, 0x9f6d, 0x9f6e, 0x9f6f, 0x9f70, 0x9f71, 0x9f73, 0x9f75, 0x9f7a, 0x9f7d, 0x9f8f, 0x9f90, 0x9f91, 0x9f92, 0x9f94, 0x9f96, 0x9f97, 0x9f9e, 0x9fa1, 0x9fa2, 0x9fa3, 0x9fa5, }; static int jisx0212_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c1 = (s[0] & 0x7F); if ((c1 == 0x22) || (c1 >= 0x26 && c1 <= 0x27) || (c1 >= 0x29 && c1 <= 0x2b) || (c1 >= 0x30 && c1 <= 0x6d)) { if (n >= 2) { unsigned char c2 = (s[1] & 0x7F); if (c2 >= 0x21 && c2 < 0x7f) { unsigned int i = 94 * (c1 - 0x21) + (c2 - 0x21); unsigned short wc = 0xfffd; if (i < 470) { if (i < 175) wc = jisx0212_2uni_page22[i-94]; } else if (i < 752) { if (i < 658) wc = jisx0212_2uni_page26[i-470]; } else if (i < 1410) { if (i < 1027) wc = jisx0212_2uni_page29[i-752]; } else { if (i < 7211) wc = jisx0212_2uni_page30[i-1410]; } if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 2; } } return RET_ILSEQ; } return RET_TOOFEW(0); } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned short jisx0212_2charset[6067] = { 0x2237, 0x2242, 0x2270, 0x2243, 0x226d, 0x226c, 0x226e, 0x2234, 0x2231, 0x226b, 0x2244, 0x2a22, 0x2a21, 0x2a24, 0x2a2a, 0x2a23, 0x2a29, 0x2921, 0x2a2e, 0x2a32, 0x2a31, 0x2a34, 0x2a33, 0x2a40, 0x2a3f, 0x2a42, 0x2a41, 0x2a50, 0x2a52, 0x2a51, 0x2a54, 0x2a58, 0x2a53, 0x292c, 0x2a63, 0x2a62, 0x2a65, 0x2a64, 0x2a72, 0x2930, 0x294e, 0x2b22, 0x2b21, 0x2b24, 0x2b2a, 0x2b23, 0x2b29, 0x2941, 0x2b2e, 0x2b32, 0x2b31, 0x2b34, 0x2b33, 0x2b40, 0x2b3f, 0x2b42, 0x2b41, 0x2943, 0x2b50, 0x2b52, 0x2b51, 0x2b54, 0x2b58, 0x2b53, 0x294c, 0x2b63, 0x2b62, 0x2b65, 0x2b64, 0x2b72, 0x2950, 0x2b73, 0x2a27, 0x2b27, 0x2a25, 0x2b25, 0x2a28, 0x2b28, 0x2a2b, 0x2b2b, 0x2a2c, 0x2b2c, 0x2a2f, 0x2b2f, 0x2a2d, 0x2b2d, 0x2a30, 0x2b30, 0x2922, 0x2942, 0x2a37, 0x2b37, 0x2a36, 0x2b36, 0x2a38, 0x2b38, 0x2a35, 0x2b35, 0x2a3a, 0x2b3a, 0x2a3b, 0x2b3b, 0x2a3d, 0x2b3d, 0x2a3c, 0x2a3e, 0x2b3e, 0x2924, 0x2944, 0x2a47, 0x2b47, 0x2a45, 0x2b45, 0x2a46, 0x2b46, 0x2a44, 0x2945, 0x2926, 0x2946, 0x2a48, 0x2b48, 0x2a49, 0x2b49, 0x2947, 0x2a4a, 0x2b4a, 0x2a4c, 0x2b4c, 0x2a4b, 0x2b4b, 0x2929, 0x2949, 0x2928, 0x2948, 0x2a4d, 0x2b4d, 0x2a4f, 0x2b4f, 0x2a4e, 0x2b4e, 0x294a, 0x292b, 0x294b, 0x2a57, 0x2b57, 0x2a56, 0x2b56, 0x292d, 0x294d, 0x2a59, 0x2b59, 0x2a5b, 0x2b5b, 0x2a5a, 0x2b5a, 0x2a5c, 0x2b5c, 0x2a5d, 0x2b5d, 0x2a5f, 0x2b5f, 0x2a5e, 0x2b5e, 0x2a61, 0x2b61, 0x2a60, 0x2b60, 0x292f, 0x294f, 0x2a6c, 0x2b6c, 0x2a69, 0x2b69, 0x2a66, 0x2b66, 0x2a6b, 0x2b6b, 0x2a68, 0x2b68, 0x2a6a, 0x2b6a, 0x2a71, 0x2b71, 0x2a74, 0x2b74, 0x2a73, 0x2a75, 0x2b75, 0x2a77, 0x2b77, 0x2a76, 0x2b76, 0x2a26, 0x2b26, 0x2a43, 0x2b43, 0x2a55, 0x2b55, 0x2a67, 0x2b67, 0x2a70, 0x2b70, 0x2a6d, 0x2b6d, 0x2a6f, 0x2b6f, 0x2a6e, 0x2b6e, 0x2b39, 0x2230, 0x222f, 0x2232, 0x2236, 0x2235, 0x2233, 0x2238, 0x2239, 0x2661, 0x2662, 0x2663, 0x2664, 0x2667, 0x2669, 0x266c, 0x2676, 0x2665, 0x266a, 0x2671, 0x2672, 0x2673, 0x2674, 0x267b, 0x2678, 0x2675, 0x267a, 0x2677, 0x2679, 0x267c, 0x2742, 0x2743, 0x2744, 0x2745, 0x2746, 0x2747, 0x2748, 0x2749, 0x274a, 0x274b, 0x274c, 0x274d, 0x274e, 0x2772, 0x2773, 0x2774, 0x2775, 0x2776, 0x2777, 0x2778, 0x2779, 0x277a, 0x277b, 0x277c, 0x277d, 0x277e, 0x2271, 0x226f, 0x3021, 0x3022, 0x3023, 0x3024, 0x3025, 0x3026, 0x3027, 0x3028, 0x3029, 0x302a, 0x302b, 0x302c, 0x302d, 0x302e, 0x302f, 0x3030, 0x3031, 0x3032, 0x3033, 0x3034, 0x3035, 0x3036, 0x3037, 0x3038, 0x3039, 0x303a, 0x303b, 0x303c, 0x303d, 0x303e, 0x303f, 0x3040, 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, 0x304a, 0x304b, 0x304c, 0x304d, 0x304e, 0x304f, 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e, 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068, 0x3069, 0x306a, 0x306b, 0x306c, 0x306d, 0x306e, 0x306f, 0x3070, 0x305f, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, 0x3078, 0x3079, 0x307a, 0x307b, 0x307c, 0x307d, 0x307e, 0x3121, 0x3122, 0x3123, 0x3124, 0x3125, 0x3126, 0x3127, 0x3128, 0x3129, 0x312a, 0x312b, 0x312c, 0x312d, 0x312e, 0x312f, 0x3130, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f, 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147, 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x3176, 0x315f, 0x3160, 0x3161, 0x3162, 0x3163, 0x3164, 0x3165, 0x3166, 0x3167, 0x3168, 0x3169, 0x316a, 0x316b, 0x316c, 0x316d, 0x316e, 0x316f, 0x3170, 0x3171, 0x3172, 0x3173, 0x3174, 0x3175, 0x3177, 0x3178, 0x3179, 0x317a, 0x317b, 0x317c, 0x317d, 0x317e, 0x3221, 0x3222, 0x3223, 0x3224, 0x3225, 0x3226, 0x3227, 0x3228, 0x3229, 0x322a, 0x322b, 0x322c, 0x322d, 0x322e, 0x322f, 0x3230, 0x3231, 0x3232, 0x3233, 0x3234, 0x3235, 0x3236, 0x3237, 0x3238, 0x3239, 0x323a, 0x323b, 0x323c, 0x323d, 0x323e, 0x323f, 0x3240, 0x3241, 0x3242, 0x3243, 0x3244, 0x3245, 0x3251, 0x3246, 0x3247, 0x3248, 0x3249, 0x324a, 0x324b, 0x324c, 0x324d, 0x324e, 0x324f, 0x3250, 0x3252, 0x3253, 0x3254, 0x3255, 0x3256, 0x3257, 0x3258, 0x3259, 0x325a, 0x325b, 0x325c, 0x325d, 0x325e, 0x325f, 0x3260, 0x3261, 0x3262, 0x3263, 0x3264, 0x3265, 0x3266, 0x3267, 0x3268, 0x3269, 0x326a, 0x326b, 0x326c, 0x326d, 0x326e, 0x326f, 0x3270, 0x3271, 0x3272, 0x3273, 0x3274, 0x3275, 0x3276, 0x3277, 0x3278, 0x3279, 0x327a, 0x327b, 0x327c, 0x327d, 0x327e, 0x3321, 0x3322, 0x3323, 0x3324, 0x3325, 0x3326, 0x3327, 0x3328, 0x3329, 0x332a, 0x332b, 0x332c, 0x332d, 0x332e, 0x332f, 0x3330, 0x3331, 0x3332, 0x3333, 0x3334, 0x3335, 0x3336, 0x3337, 0x3338, 0x3339, 0x333a, 0x333b, 0x333c, 0x333d, 0x333e, 0x333f, 0x3340, 0x3341, 0x3342, 0x3343, 0x3344, 0x3345, 0x3346, 0x3347, 0x3348, 0x3349, 0x334a, 0x334b, 0x334c, 0x334d, 0x334e, 0x334f, 0x3350, 0x3351, 0x3352, 0x3353, 0x3354, 0x3355, 0x3356, 0x3357, 0x3358, 0x3359, 0x335a, 0x335b, 0x335c, 0x335d, 0x335e, 0x335f, 0x3360, 0x3361, 0x3362, 0x3363, 0x3364, 0x3365, 0x3366, 0x3367, 0x3368, 0x3369, 0x336a, 0x336b, 0x336c, 0x336d, 0x336e, 0x336f, 0x3370, 0x3371, 0x3372, 0x3373, 0x3374, 0x3375, 0x3376, 0x3377, 0x3378, 0x3379, 0x337a, 0x337b, 0x337c, 0x337d, 0x337e, 0x3421, 0x3422, 0x3423, 0x3424, 0x3425, 0x3426, 0x3427, 0x3428, 0x3429, 0x342a, 0x342b, 0x342c, 0x342d, 0x342e, 0x342f, 0x3430, 0x3431, 0x3432, 0x3433, 0x3434, 0x3435, 0x3436, 0x3438, 0x3437, 0x3439, 0x343a, 0x343b, 0x343c, 0x343d, 0x343e, 0x343f, 0x3440, 0x3441, 0x3442, 0x3443, 0x3444, 0x3445, 0x3446, 0x3447, 0x3448, 0x3449, 0x344a, 0x344b, 0x344c, 0x344d, 0x344e, 0x344f, 0x3450, 0x3451, 0x3452, 0x3453, 0x3454, 0x3455, 0x3456, 0x3457, 0x3458, 0x3459, 0x345a, 0x345b, 0x345c, 0x345d, 0x345e, 0x345f, 0x3460, 0x3461, 0x3462, 0x3463, 0x3464, 0x3465, 0x3466, 0x3467, 0x3468, 0x3469, 0x346a, 0x346b, 0x346c, 0x346d, 0x346e, 0x346f, 0x3470, 0x3471, 0x3472, 0x3473, 0x3474, 0x3475, 0x3476, 0x3477, 0x3478, 0x3479, 0x347a, 0x347b, 0x347c, 0x347d, 0x347e, 0x3521, 0x3522, 0x3523, 0x3524, 0x3525, 0x3526, 0x3527, 0x3528, 0x3529, 0x352a, 0x352b, 0x352c, 0x352d, 0x352e, 0x352f, 0x3530, 0x3531, 0x3532, 0x3533, 0x3534, 0x3535, 0x3536, 0x3537, 0x3538, 0x3539, 0x353a, 0x353b, 0x353c, 0x353d, 0x353e, 0x353f, 0x3540, 0x3541, 0x3542, 0x3543, 0x3544, 0x3545, 0x3546, 0x3547, 0x3548, 0x3549, 0x354a, 0x354b, 0x354c, 0x354d, 0x354e, 0x354f, 0x3550, 0x3551, 0x3552, 0x3553, 0x3554, 0x3555, 0x3556, 0x3557, 0x3558, 0x3559, 0x355a, 0x355b, 0x355c, 0x355d, 0x355e, 0x355f, 0x3560, 0x3561, 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567, 0x3568, 0x3569, 0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f, 0x3570, 0x3571, 0x3572, 0x3573, 0x3574, 0x3575, 0x3576, 0x3577, 0x3578, 0x3579, 0x357a, 0x357b, 0x357c, 0x357d, 0x357e, 0x3621, 0x3622, 0x3623, 0x3624, 0x3625, 0x3626, 0x3627, 0x3628, 0x3629, 0x362a, 0x362b, 0x362c, 0x362d, 0x362e, 0x362f, 0x3630, 0x3631, 0x3632, 0x3633, 0x3634, 0x3635, 0x3636, 0x3637, 0x3638, 0x3639, 0x363a, 0x363b, 0x363c, 0x363d, 0x363e, 0x363f, 0x3640, 0x3641, 0x3642, 0x3643, 0x3644, 0x3645, 0x3646, 0x3647, 0x3648, 0x3649, 0x364a, 0x364b, 0x364c, 0x364d, 0x364e, 0x364f, 0x3650, 0x3651, 0x3652, 0x3653, 0x3654, 0x3655, 0x3656, 0x3657, 0x3658, 0x3659, 0x365a, 0x365b, 0x365c, 0x365d, 0x365e, 0x365f, 0x3660, 0x3661, 0x3662, 0x3663, 0x3664, 0x3665, 0x3666, 0x3667, 0x3668, 0x3669, 0x366a, 0x366b, 0x366c, 0x366d, 0x3670, 0x3671, 0x366e, 0x366f, 0x3672, 0x3673, 0x3674, 0x3675, 0x3676, 0x3677, 0x3678, 0x3679, 0x367a, 0x367b, 0x367d, 0x367e, 0x367c, 0x3721, 0x3722, 0x3723, 0x3724, 0x3725, 0x3726, 0x3727, 0x3728, 0x3729, 0x372a, 0x372b, 0x372c, 0x372d, 0x372e, 0x372f, 0x3730, 0x3731, 0x3732, 0x3733, 0x3734, 0x3735, 0x3736, 0x3737, 0x3738, 0x3739, 0x373a, 0x373b, 0x373c, 0x373d, 0x373e, 0x373f, 0x3740, 0x3741, 0x3742, 0x3743, 0x3744, 0x3745, 0x3746, 0x3747, 0x3748, 0x3749, 0x374a, 0x374b, 0x374c, 0x374d, 0x374e, 0x374f, 0x3750, 0x3751, 0x3752, 0x3753, 0x3754, 0x3755, 0x3756, 0x3757, 0x3760, 0x3758, 0x3759, 0x375a, 0x375b, 0x375c, 0x375d, 0x375e, 0x375f, 0x3761, 0x3762, 0x3763, 0x3764, 0x3765, 0x3766, 0x3767, 0x3768, 0x3769, 0x376a, 0x376b, 0x376c, 0x376d, 0x377e, 0x376e, 0x376f, 0x3770, 0x3771, 0x3772, 0x3773, 0x3774, 0x3775, 0x3776, 0x3777, 0x3778, 0x3779, 0x377a, 0x377b, 0x377c, 0x377d, 0x3821, 0x3822, 0x3823, 0x3824, 0x3825, 0x3826, 0x3827, 0x3828, 0x3829, 0x382a, 0x382b, 0x382c, 0x382d, 0x382e, 0x382f, 0x3830, 0x3831, 0x3832, 0x3833, 0x3834, 0x3835, 0x3836, 0x3837, 0x3838, 0x3839, 0x383a, 0x383b, 0x383c, 0x383d, 0x383e, 0x383f, 0x3840, 0x3841, 0x3842, 0x3843, 0x3844, 0x3845, 0x3846, 0x3847, 0x3848, 0x3849, 0x384a, 0x384b, 0x384c, 0x384d, 0x384e, 0x3850, 0x3851, 0x384f, 0x3852, 0x3853, 0x3854, 0x3855, 0x3856, 0x3857, 0x3858, 0x3859, 0x385a, 0x385b, 0x385c, 0x385d, 0x385e, 0x385f, 0x3860, 0x3861, 0x3862, 0x3863, 0x3864, 0x3865, 0x3867, 0x3868, 0x3869, 0x386a, 0x386b, 0x386c, 0x386d, 0x386e, 0x386f, 0x3870, 0x3871, 0x3872, 0x3873, 0x3874, 0x3875, 0x3876, 0x3877, 0x3878, 0x3879, 0x387a, 0x387b, 0x387c, 0x387d, 0x387e, 0x3921, 0x3922, 0x3923, 0x3924, 0x3925, 0x3926, 0x3927, 0x3928, 0x3929, 0x392a, 0x392b, 0x392c, 0x392d, 0x392e, 0x392f, 0x3930, 0x3931, 0x3932, 0x3933, 0x3934, 0x3935, 0x3936, 0x3937, 0x3938, 0x3939, 0x393a, 0x393b, 0x393c, 0x393d, 0x393e, 0x393f, 0x3940, 0x3941, 0x3942, 0x3943, 0x3944, 0x3945, 0x3946, 0x3947, 0x3948, 0x3949, 0x394a, 0x394b, 0x394c, 0x394d, 0x394e, 0x394f, 0x3950, 0x3951, 0x3952, 0x3953, 0x3954, 0x3955, 0x3956, 0x3957, 0x3958, 0x3959, 0x395a, 0x395b, 0x395c, 0x395d, 0x395e, 0x395f, 0x3960, 0x3961, 0x3962, 0x3963, 0x3964, 0x3965, 0x3966, 0x3967, 0x3968, 0x3969, 0x396a, 0x396b, 0x396c, 0x396d, 0x396e, 0x396f, 0x3970, 0x3971, 0x3972, 0x3973, 0x3974, 0x3975, 0x3976, 0x3977, 0x3978, 0x3979, 0x397a, 0x397b, 0x397c, 0x397d, 0x397e, 0x3a21, 0x3a22, 0x3a23, 0x3a24, 0x3a25, 0x3a26, 0x3a27, 0x3a28, 0x3a29, 0x3a2a, 0x3a2b, 0x3a2c, 0x3a2d, 0x3a2e, 0x3a2f, 0x3a30, 0x3a31, 0x3a33, 0x3a34, 0x3a35, 0x3a36, 0x3a37, 0x3a38, 0x3a32, 0x3a39, 0x3a3a, 0x3a3b, 0x3a3c, 0x3a3d, 0x3a3e, 0x3a3f, 0x3a40, 0x3a41, 0x3a42, 0x3a43, 0x3a44, 0x3a45, 0x3a46, 0x3a47, 0x3a48, 0x3a49, 0x3a4a, 0x3a4b, 0x3a4c, 0x3a4d, 0x3a4e, 0x3a4f, 0x3a50, 0x3a51, 0x3a52, 0x3a53, 0x3a54, 0x3a55, 0x3a56, 0x3a57, 0x3a58, 0x3a59, 0x3a5a, 0x3a5b, 0x3a5c, 0x3a5d, 0x3a5e, 0x3a5f, 0x3a60, 0x3a61, 0x3a62, 0x3a63, 0x3a64, 0x3a65, 0x3a66, 0x3a67, 0x3a68, 0x3a69, 0x3a6a, 0x3a6b, 0x3a6c, 0x3a6d, 0x3a6e, 0x3a6f, 0x3a70, 0x3a71, 0x3a72, 0x3a73, 0x3a74, 0x3a75, 0x3a76, 0x3a77, 0x3a78, 0x3a79, 0x3a7a, 0x3a7b, 0x3a7c, 0x3a7d, 0x3a7e, 0x3b21, 0x3b22, 0x3b23, 0x3b24, 0x3b25, 0x3b26, 0x3b27, 0x3b28, 0x3b29, 0x3b2a, 0x3b2b, 0x3b2c, 0x3b2d, 0x3b2e, 0x3b2f, 0x3b30, 0x3b31, 0x3b32, 0x3b33, 0x3b34, 0x3b35, 0x3b36, 0x3b37, 0x3b38, 0x3b39, 0x3b3a, 0x3b3b, 0x3b3d, 0x3b3c, 0x3b3e, 0x3b3f, 0x3b40, 0x3b41, 0x3b42, 0x3b43, 0x3b44, 0x3b45, 0x3b47, 0x3b48, 0x3b49, 0x3b4a, 0x3b46, 0x3b4b, 0x3b4c, 0x3b4d, 0x3b4e, 0x3b4f, 0x3b50, 0x3b51, 0x3b52, 0x3b53, 0x3b57, 0x3b55, 0x3b54, 0x3b56, 0x3b58, 0x3b59, 0x3b5a, 0x3b5b, 0x3b5c, 0x3b5d, 0x3b5e, 0x3b5f, 0x3b60, 0x3b61, 0x3b62, 0x3b63, 0x3b64, 0x3b65, 0x3b66, 0x3b67, 0x3b68, 0x3b69, 0x3b6a, 0x3b6b, 0x3b6c, 0x3b6d, 0x3b6e, 0x3b6f, 0x3b70, 0x3b71, 0x3b72, 0x6674, 0x3b73, 0x3b74, 0x3b75, 0x3b76, 0x3b77, 0x3b78, 0x3b7a, 0x3b79, 0x3b7b, 0x3b7c, 0x3b7d, 0x3b7e, 0x3c21, 0x3c22, 0x3c23, 0x3c24, 0x3c25, 0x3c26, 0x3c27, 0x3c28, 0x3c29, 0x3c2a, 0x3c2b, 0x3c2c, 0x3c2e, 0x3c2d, 0x3c2f, 0x3c30, 0x3c31, 0x3c34, 0x3c32, 0x3c33, 0x3c35, 0x3c36, 0x3c37, 0x3c38, 0x3c39, 0x3c3a, 0x3c3b, 0x3c3c, 0x3c3d, 0x3c3e, 0x3c3f, 0x3c40, 0x3c41, 0x3c42, 0x3c43, 0x3c44, 0x3c45, 0x3c46, 0x3c47, 0x3c48, 0x3c49, 0x3c4a, 0x3c4b, 0x3c4c, 0x3c4d, 0x3c4e, 0x3c4f, 0x3c50, 0x3c52, 0x3c51, 0x3c53, 0x3c54, 0x3c55, 0x3c56, 0x3c57, 0x3c58, 0x3c59, 0x3c5a, 0x3c5b, 0x3c5c, 0x3c5d, 0x3c5e, 0x3c5f, 0x3c60, 0x3c61, 0x3c62, 0x3c63, 0x3c64, 0x3c65, 0x3c66, 0x3c67, 0x3c68, 0x3c69, 0x3c6a, 0x3c6b, 0x3c6c, 0x3c6d, 0x3c6e, 0x3c6f, 0x3c70, 0x3c71, 0x3c72, 0x3c73, 0x3c74, 0x3c75, 0x3c76, 0x3c77, 0x3c78, 0x3c79, 0x3c7a, 0x3c7b, 0x3c7c, 0x3c7d, 0x3c7e, 0x3d21, 0x3d22, 0x3d23, 0x3d24, 0x3d25, 0x3d26, 0x3d27, 0x3d28, 0x3d29, 0x3d2a, 0x3d2b, 0x3d2c, 0x3d2d, 0x3d2e, 0x3d2f, 0x3d32, 0x3d30, 0x3d31, 0x3d33, 0x3d34, 0x3d35, 0x3d36, 0x3d37, 0x3d38, 0x3d39, 0x3d3a, 0x3d3b, 0x3d3c, 0x3d3d, 0x3d3e, 0x3d3f, 0x3d40, 0x3d41, 0x3d42, 0x3d43, 0x3d44, 0x3d45, 0x3d46, 0x3d47, 0x3d48, 0x3d49, 0x3d4a, 0x3d4b, 0x3d4c, 0x3d4d, 0x3d4e, 0x3d4f, 0x3d50, 0x3d51, 0x3d52, 0x3d53, 0x3d54, 0x3d55, 0x3d56, 0x3d57, 0x3d58, 0x3d59, 0x3d5a, 0x3d5b, 0x3d5c, 0x3d5d, 0x3d5e, 0x3d5f, 0x3d60, 0x3d61, 0x3d62, 0x3d63, 0x3d64, 0x3d65, 0x3d66, 0x3d67, 0x3d68, 0x3d69, 0x3d6a, 0x3d6b, 0x3d6c, 0x3d6d, 0x3d6e, 0x3d6f, 0x3d70, 0x3d71, 0x3d72, 0x3d73, 0x3d74, 0x3d75, 0x3d76, 0x3d77, 0x3d78, 0x3d79, 0x3d7a, 0x3d7b, 0x3d7c, 0x3d7d, 0x3d7e, 0x3e21, 0x3e22, 0x3e23, 0x3e24, 0x3e25, 0x3e26, 0x3e27, 0x3e28, 0x3e29, 0x3e2a, 0x3e2b, 0x3e2c, 0x3e2d, 0x3e2e, 0x3e2f, 0x3e30, 0x3e31, 0x3e32, 0x3e33, 0x3e34, 0x3e35, 0x3e36, 0x3e37, 0x3e38, 0x3e39, 0x3e3a, 0x3e3b, 0x3e3c, 0x3e3d, 0x3e3e, 0x3e3f, 0x3e40, 0x3e41, 0x3e42, 0x3e43, 0x3e44, 0x3e45, 0x3e46, 0x3e47, 0x3e48, 0x3e49, 0x3e4a, 0x3e4b, 0x3e4c, 0x3e4d, 0x3e4e, 0x3e4f, 0x3e50, 0x3e51, 0x3e52, 0x3e53, 0x3e54, 0x3e55, 0x3e56, 0x3e57, 0x3e58, 0x3e59, 0x3e5a, 0x3e5b, 0x3e5c, 0x3e5d, 0x3e5e, 0x3e5f, 0x3e60, 0x3e61, 0x3e62, 0x3e63, 0x3e64, 0x3e65, 0x3e66, 0x3e67, 0x3e68, 0x3e69, 0x3e6a, 0x3e6b, 0x3e6c, 0x3e6d, 0x3e6e, 0x3e6f, 0x3e70, 0x3e71, 0x3e72, 0x3e73, 0x3e74, 0x3e75, 0x3e76, 0x3e77, 0x3e78, 0x3e79, 0x3e7a, 0x3e7b, 0x3e7e, 0x3e7c, 0x3e7d, 0x3f21, 0x3f22, 0x3f23, 0x3f24, 0x3f25, 0x3f26, 0x3f27, 0x3f28, 0x3f29, 0x3f2a, 0x3f2b, 0x3f2c, 0x3f2d, 0x3f2e, 0x3f2f, 0x3f30, 0x3f31, 0x3f32, 0x3f33, 0x3f34, 0x3f35, 0x3f36, 0x3f37, 0x3f38, 0x3f39, 0x3f3a, 0x3f3b, 0x3f3c, 0x3f3d, 0x3f3e, 0x3f3f, 0x3f40, 0x3f41, 0x3f42, 0x3f43, 0x3f44, 0x3f45, 0x3f46, 0x3f47, 0x3f48, 0x3f49, 0x3f4a, 0x3f4b, 0x3f4c, 0x3f4d, 0x3f4e, 0x3f4f, 0x3f50, 0x3f51, 0x3f52, 0x3f53, 0x3f54, 0x3f55, 0x3f56, 0x3f57, 0x3f58, 0x3f59, 0x3f5a, 0x3f5b, 0x3f5c, 0x3f5d, 0x3f5e, 0x3f5f, 0x3f60, 0x3f61, 0x3f62, 0x3f63, 0x3f64, 0x3f65, 0x3f66, 0x3f67, 0x3f68, 0x3f69, 0x3f6a, 0x3f6b, 0x3f6c, 0x3f6d, 0x3f6e, 0x3f6f, 0x3f70, 0x3f71, 0x3f72, 0x3f73, 0x3f74, 0x3f75, 0x3f76, 0x3f77, 0x3f78, 0x3f79, 0x3f7a, 0x3f7b, 0x3f7c, 0x3f7d, 0x3f7e, 0x4021, 0x4022, 0x4023, 0x4024, 0x4025, 0x4026, 0x4027, 0x4028, 0x4029, 0x402a, 0x402b, 0x402c, 0x402d, 0x402e, 0x402f, 0x4030, 0x4031, 0x4032, 0x4033, 0x4034, 0x4035, 0x4036, 0x4037, 0x4038, 0x4039, 0x403a, 0x403b, 0x403c, 0x403d, 0x403e, 0x403f, 0x4040, 0x4041, 0x4042, 0x4043, 0x4044, 0x4045, 0x4046, 0x4047, 0x4048, 0x4049, 0x404a, 0x404b, 0x404c, 0x404d, 0x404e, 0x404f, 0x4050, 0x4051, 0x4052, 0x4053, 0x4054, 0x4055, 0x4056, 0x4057, 0x4058, 0x4059, 0x405a, 0x405b, 0x405c, 0x405d, 0x405e, 0x405f, 0x4060, 0x4061, 0x4062, 0x4063, 0x4064, 0x4065, 0x4066, 0x4067, 0x4068, 0x4069, 0x406a, 0x406b, 0x406c, 0x406d, 0x406e, 0x406f, 0x4070, 0x4071, 0x4072, 0x4073, 0x4074, 0x4075, 0x4076, 0x4077, 0x4078, 0x4079, 0x407a, 0x407b, 0x407c, 0x407d, 0x407e, 0x4121, 0x4122, 0x4123, 0x4124, 0x4125, 0x4126, 0x4127, 0x4128, 0x4129, 0x412a, 0x412b, 0x412c, 0x412d, 0x412e, 0x412f, 0x4130, 0x4131, 0x4132, 0x4133, 0x4134, 0x4135, 0x4136, 0x4137, 0x4138, 0x4139, 0x413a, 0x413b, 0x413c, 0x413d, 0x413e, 0x413f, 0x4140, 0x4141, 0x4142, 0x4143, 0x4144, 0x4145, 0x4146, 0x4147, 0x4148, 0x4149, 0x414a, 0x414b, 0x414c, 0x414d, 0x414e, 0x414f, 0x4150, 0x4151, 0x4152, 0x4153, 0x4154, 0x4155, 0x4156, 0x4157, 0x4158, 0x4159, 0x415a, 0x415b, 0x415c, 0x415d, 0x415e, 0x415f, 0x4160, 0x4161, 0x4162, 0x4163, 0x4164, 0x4165, 0x4166, 0x4167, 0x4168, 0x4169, 0x416a, 0x416b, 0x416c, 0x416d, 0x416e, 0x416f, 0x4170, 0x4171, 0x4172, 0x4173, 0x4174, 0x4175, 0x4176, 0x4177, 0x4178, 0x4179, 0x417a, 0x417b, 0x417c, 0x417d, 0x417e, 0x4221, 0x4222, 0x4223, 0x4224, 0x4225, 0x4226, 0x4227, 0x4228, 0x4229, 0x422a, 0x422b, 0x422c, 0x422d, 0x422e, 0x4230, 0x422f, 0x4231, 0x4232, 0x4233, 0x4234, 0x4235, 0x4237, 0x4236, 0x4238, 0x4239, 0x423a, 0x423b, 0x423c, 0x423d, 0x423e, 0x4240, 0x4241, 0x4242, 0x4244, 0x4245, 0x4247, 0x4248, 0x4249, 0x424a, 0x424c, 0x4243, 0x4246, 0x424b, 0x424d, 0x424e, 0x424f, 0x4250, 0x4251, 0x4252, 0x4253, 0x4254, 0x4255, 0x4256, 0x4257, 0x4258, 0x4259, 0x425a, 0x425b, 0x425c, 0x425d, 0x425e, 0x425f, 0x4260, 0x4261, 0x4262, 0x4263, 0x4264, 0x4265, 0x4266, 0x4267, 0x4268, 0x4269, 0x426a, 0x426b, 0x426c, 0x426d, 0x423f, 0x426e, 0x426f, 0x4270, 0x4271, 0x4272, 0x4273, 0x4274, 0x4275, 0x4276, 0x4277, 0x4278, 0x4279, 0x427a, 0x427b, 0x427c, 0x427d, 0x427e, 0x4321, 0x4322, 0x4323, 0x4324, 0x4325, 0x4326, 0x4327, 0x4328, 0x4329, 0x432a, 0x432b, 0x432c, 0x432d, 0x432e, 0x432f, 0x4330, 0x4331, 0x4332, 0x4333, 0x4334, 0x4335, 0x4336, 0x4337, 0x4339, 0x433a, 0x433b, 0x433c, 0x433d, 0x433e, 0x433f, 0x4340, 0x4341, 0x4342, 0x4343, 0x4344, 0x4345, 0x4346, 0x4347, 0x4348, 0x4338, 0x434a, 0x434b, 0x434c, 0x434d, 0x434f, 0x434e, 0x4350, 0x4351, 0x4352, 0x4353, 0x4354, 0x4355, 0x4356, 0x4357, 0x4358, 0x4359, 0x435a, 0x435b, 0x4349, 0x435c, 0x435d, 0x435e, 0x435f, 0x4360, 0x4361, 0x4362, 0x4363, 0x4364, 0x4365, 0x4366, 0x4367, 0x4368, 0x4369, 0x436a, 0x436b, 0x436c, 0x436d, 0x436e, 0x436f, 0x4370, 0x4371, 0x4372, 0x4373, 0x4374, 0x4375, 0x4376, 0x4377, 0x4378, 0x4379, 0x437a, 0x437b, 0x437c, 0x437d, 0x437e, 0x4421, 0x4422, 0x4423, 0x4424, 0x4425, 0x4426, 0x4427, 0x4428, 0x4429, 0x442a, 0x442b, 0x442c, 0x442d, 0x442e, 0x442f, 0x4430, 0x4431, 0x4432, 0x4433, 0x4434, 0x4435, 0x4436, 0x4437, 0x4438, 0x4439, 0x443a, 0x443b, 0x443c, 0x443d, 0x443e, 0x443f, 0x4440, 0x4441, 0x4442, 0x4443, 0x4444, 0x4445, 0x4446, 0x4447, 0x4448, 0x4449, 0x444a, 0x444b, 0x444c, 0x444d, 0x444e, 0x444f, 0x4450, 0x4451, 0x4452, 0x4453, 0x4454, 0x4455, 0x4456, 0x4457, 0x4458, 0x4459, 0x445a, 0x445b, 0x445c, 0x445d, 0x445e, 0x445f, 0x4460, 0x4461, 0x4462, 0x4463, 0x4464, 0x4465, 0x4466, 0x4467, 0x4468, 0x4469, 0x446a, 0x446b, 0x446c, 0x446d, 0x446e, 0x446f, 0x4470, 0x4471, 0x4472, 0x4473, 0x4474, 0x4475, 0x4476, 0x4477, 0x4478, 0x4479, 0x447a, 0x447b, 0x447c, 0x447d, 0x447e, 0x4521, 0x4522, 0x4523, 0x4524, 0x4525, 0x4526, 0x4527, 0x4528, 0x4529, 0x452a, 0x452b, 0x452c, 0x452d, 0x452e, 0x452f, 0x4530, 0x4531, 0x4532, 0x4533, 0x4534, 0x4535, 0x4536, 0x4537, 0x4538, 0x4539, 0x453a, 0x453b, 0x453c, 0x453d, 0x453e, 0x453f, 0x4540, 0x4541, 0x4542, 0x4543, 0x4544, 0x4545, 0x4546, 0x4547, 0x4548, 0x4549, 0x454a, 0x454b, 0x454d, 0x454c, 0x454e, 0x454f, 0x4550, 0x4551, 0x4552, 0x4553, 0x4554, 0x4555, 0x4556, 0x4557, 0x4558, 0x4559, 0x455a, 0x455b, 0x455c, 0x455d, 0x455e, 0x455f, 0x4560, 0x4561, 0x4562, 0x4563, 0x4564, 0x4565, 0x4566, 0x4567, 0x4568, 0x4569, 0x456a, 0x456b, 0x456c, 0x456d, 0x456e, 0x456f, 0x4570, 0x4571, 0x4572, 0x4573, 0x4574, 0x4575, 0x4576, 0x4577, 0x4578, 0x4579, 0x457a, 0x457b, 0x457c, 0x457d, 0x457e, 0x4621, 0x4622, 0x4623, 0x4624, 0x4625, 0x4626, 0x4627, 0x4628, 0x4629, 0x462a, 0x462b, 0x462c, 0x462d, 0x462e, 0x462f, 0x4630, 0x4631, 0x4632, 0x4633, 0x4634, 0x4635, 0x4636, 0x4637, 0x4638, 0x4639, 0x463a, 0x463b, 0x463c, 0x463d, 0x463e, 0x463f, 0x4640, 0x4641, 0x4642, 0x4643, 0x4644, 0x4645, 0x4646, 0x4647, 0x4648, 0x4649, 0x464a, 0x464b, 0x464c, 0x464d, 0x464e, 0x464f, 0x4650, 0x4651, 0x4652, 0x4653, 0x4654, 0x4655, 0x4656, 0x4657, 0x4658, 0x4659, 0x465a, 0x465b, 0x465c, 0x465d, 0x465e, 0x465f, 0x4660, 0x4736, 0x4661, 0x4662, 0x4663, 0x4664, 0x4665, 0x4666, 0x4667, 0x4668, 0x4669, 0x466a, 0x466b, 0x466c, 0x466d, 0x466e, 0x466f, 0x4670, 0x4671, 0x4672, 0x4673, 0x4674, 0x4675, 0x4676, 0x4677, 0x4678, 0x4679, 0x467a, 0x467b, 0x467c, 0x467d, 0x467e, 0x4721, 0x4722, 0x4723, 0x4724, 0x4725, 0x4726, 0x4727, 0x4728, 0x4729, 0x472a, 0x472b, 0x472c, 0x472d, 0x472e, 0x472f, 0x4730, 0x4731, 0x4732, 0x4733, 0x4734, 0x4735, 0x4737, 0x4738, 0x4739, 0x473a, 0x473b, 0x473c, 0x473d, 0x473e, 0x473f, 0x4740, 0x4741, 0x4742, 0x4743, 0x4744, 0x4745, 0x4746, 0x4747, 0x4748, 0x4749, 0x474a, 0x474b, 0x474c, 0x474d, 0x474e, 0x474f, 0x4750, 0x4751, 0x4752, 0x4753, 0x4754, 0x4755, 0x4756, 0x4757, 0x4758, 0x4759, 0x475a, 0x475b, 0x475c, 0x475d, 0x475e, 0x475f, 0x4760, 0x4761, 0x4762, 0x4763, 0x4764, 0x4765, 0x4766, 0x4767, 0x4768, 0x4769, 0x476a, 0x476b, 0x476c, 0x476d, 0x476e, 0x476f, 0x4770, 0x4771, 0x4772, 0x4773, 0x4774, 0x4775, 0x4776, 0x4777, 0x4778, 0x4779, 0x477a, 0x477b, 0x477c, 0x477d, 0x477e, 0x4821, 0x4822, 0x4823, 0x4824, 0x4825, 0x4826, 0x4827, 0x4828, 0x4829, 0x482a, 0x482b, 0x482c, 0x482d, 0x482e, 0x482f, 0x4830, 0x4831, 0x4832, 0x4833, 0x4834, 0x4835, 0x4836, 0x4837, 0x4838, 0x4839, 0x483a, 0x483b, 0x483c, 0x483d, 0x483e, 0x483f, 0x4840, 0x4841, 0x4842, 0x4843, 0x4844, 0x4845, 0x4846, 0x4847, 0x4848, 0x4849, 0x484a, 0x484b, 0x484c, 0x4853, 0x484d, 0x484e, 0x484f, 0x4850, 0x4851, 0x4852, 0x4854, 0x4855, 0x4856, 0x4857, 0x4858, 0x4859, 0x485a, 0x485b, 0x485c, 0x485d, 0x485e, 0x485f, 0x4860, 0x4861, 0x4862, 0x4863, 0x4864, 0x4865, 0x4866, 0x4867, 0x4868, 0x4869, 0x486a, 0x486b, 0x486c, 0x486d, 0x486e, 0x486f, 0x4870, 0x4871, 0x4872, 0x4873, 0x4874, 0x4875, 0x4876, 0x4877, 0x4878, 0x4879, 0x487a, 0x487b, 0x487c, 0x487d, 0x487e, 0x4921, 0x4922, 0x4923, 0x4924, 0x4925, 0x4926, 0x4927, 0x4928, 0x4929, 0x492a, 0x492b, 0x492c, 0x492d, 0x492e, 0x492f, 0x4930, 0x4931, 0x4932, 0x4933, 0x4934, 0x4935, 0x4936, 0x4937, 0x4938, 0x4939, 0x493a, 0x493b, 0x493c, 0x4941, 0x493d, 0x493e, 0x493f, 0x4940, 0x4942, 0x4943, 0x4944, 0x4945, 0x4946, 0x4947, 0x4948, 0x4949, 0x494a, 0x494b, 0x494c, 0x494d, 0x494e, 0x494f, 0x4950, 0x4951, 0x4952, 0x4953, 0x4954, 0x4955, 0x4956, 0x4957, 0x4958, 0x4959, 0x495a, 0x495b, 0x495c, 0x495d, 0x495e, 0x495f, 0x4960, 0x4961, 0x4962, 0x4963, 0x4964, 0x4965, 0x4966, 0x4967, 0x4968, 0x4969, 0x496a, 0x496b, 0x496c, 0x496d, 0x496e, 0x496f, 0x4970, 0x4971, 0x4972, 0x4973, 0x4974, 0x4975, 0x4976, 0x4977, 0x4978, 0x4979, 0x497a, 0x497b, 0x497c, 0x497d, 0x497e, 0x4a21, 0x4a22, 0x4a23, 0x4a24, 0x4a25, 0x4a26, 0x4a27, 0x4a28, 0x4a29, 0x4a2a, 0x4a2b, 0x4a2c, 0x4a2d, 0x4a2e, 0x4a2f, 0x4a30, 0x4a31, 0x4a32, 0x4a33, 0x4a34, 0x4a35, 0x4a36, 0x4a37, 0x4a38, 0x4a39, 0x4a3a, 0x4a3b, 0x4a3c, 0x4a3d, 0x4a3e, 0x4a3f, 0x4a40, 0x4a41, 0x4a42, 0x4a43, 0x4a44, 0x4a45, 0x4a46, 0x4a47, 0x4a48, 0x4a49, 0x4a4a, 0x4a4b, 0x4a4c, 0x4a4d, 0x4a4e, 0x4a4f, 0x4a50, 0x4a51, 0x4a52, 0x4a53, 0x4a54, 0x4a55, 0x4a56, 0x4a57, 0x4a58, 0x4a59, 0x4a5a, 0x4a5b, 0x4a5c, 0x4a5d, 0x4a5e, 0x4a5f, 0x4a60, 0x4a61, 0x4a62, 0x4a63, 0x4a64, 0x4a65, 0x4a66, 0x4a67, 0x4a68, 0x4a69, 0x4a6a, 0x4a6b, 0x4a6c, 0x4a6d, 0x4a6e, 0x4a6f, 0x4a70, 0x4a71, 0x4a72, 0x4a73, 0x4a74, 0x4a75, 0x4a76, 0x4a77, 0x4a78, 0x4a79, 0x4a7a, 0x4a7b, 0x4a7c, 0x4a7d, 0x4a7e, 0x4b21, 0x4b22, 0x4b23, 0x4b24, 0x4b25, 0x4b26, 0x4b27, 0x4b28, 0x4b29, 0x4b2a, 0x4b2b, 0x4b2c, 0x4b2d, 0x4b2e, 0x4b2f, 0x4b30, 0x4b31, 0x4b32, 0x4b33, 0x4b34, 0x4b35, 0x4b36, 0x4b37, 0x4b38, 0x4b39, 0x4b3a, 0x4b3b, 0x4b3c, 0x4b3d, 0x4b3e, 0x4b3f, 0x4b40, 0x4b41, 0x4b42, 0x4b43, 0x4b44, 0x4b45, 0x4b46, 0x4b47, 0x4b48, 0x4b49, 0x4b4a, 0x4b4b, 0x4b4c, 0x4b4d, 0x4b4e, 0x4b4f, 0x4b50, 0x4b51, 0x4b52, 0x4b53, 0x4b54, 0x4b55, 0x4b56, 0x4b57, 0x4b58, 0x4b59, 0x4b5a, 0x4b5b, 0x4b5c, 0x4b5d, 0x4b5e, 0x4b5f, 0x4b60, 0x4b61, 0x4b62, 0x4b63, 0x4b64, 0x4b65, 0x4b66, 0x4b67, 0x4b68, 0x4b69, 0x4b6a, 0x4b6b, 0x4b6c, 0x4b6d, 0x4b6e, 0x4b6f, 0x4b70, 0x4b71, 0x4b72, 0x4b73, 0x4b74, 0x4b75, 0x4b76, 0x4b77, 0x4b78, 0x4b79, 0x4b7a, 0x4b7b, 0x4b7c, 0x4b7d, 0x4b7e, 0x4c21, 0x4c22, 0x4c23, 0x4c24, 0x4c25, 0x4c26, 0x4c27, 0x4c28, 0x4c29, 0x4c2a, 0x4c2b, 0x4c2c, 0x4c2d, 0x4c2e, 0x4c2f, 0x4c30, 0x4c31, 0x4c32, 0x4c33, 0x4c34, 0x4c35, 0x4c36, 0x4c37, 0x4c38, 0x4c39, 0x4c3a, 0x4c3b, 0x4c3c, 0x4c3d, 0x4c3e, 0x4c3f, 0x4c40, 0x4c41, 0x4c42, 0x4c43, 0x4c44, 0x4c45, 0x4c46, 0x4c47, 0x4c48, 0x4c49, 0x4c4a, 0x4c4b, 0x4c4c, 0x4c4d, 0x4c4e, 0x4c4f, 0x4c50, 0x4c51, 0x4c52, 0x4c53, 0x4c54, 0x4c55, 0x4c56, 0x4c57, 0x4c58, 0x4c59, 0x4c5a, 0x4c5b, 0x4c5c, 0x4c5d, 0x4c5e, 0x4c5f, 0x4c60, 0x4c61, 0x4c62, 0x4c63, 0x4c64, 0x4c65, 0x4c66, 0x4c67, 0x4c68, 0x4c69, 0x4c6a, 0x4c6b, 0x4c6c, 0x4c6d, 0x4c6e, 0x4c6f, 0x4c70, 0x4c71, 0x4c72, 0x4c73, 0x4c74, 0x4c75, 0x4c76, 0x4c77, 0x4c78, 0x4c79, 0x4c7a, 0x4c7b, 0x4c7c, 0x4c7d, 0x4c7e, 0x4d21, 0x4d22, 0x4d23, 0x4d24, 0x4d25, 0x4d26, 0x4d27, 0x4d28, 0x4d29, 0x4d2a, 0x4d2b, 0x4d2c, 0x4d2d, 0x4d2e, 0x4d2f, 0x4d30, 0x4d31, 0x4d32, 0x4d33, 0x4d34, 0x4d35, 0x4d36, 0x4d37, 0x4d38, 0x4d39, 0x4d3a, 0x4d3b, 0x4d3c, 0x4d3d, 0x4d3e, 0x4d3f, 0x4d40, 0x4d41, 0x4d42, 0x4d43, 0x4d44, 0x4d45, 0x4d46, 0x4d47, 0x4d48, 0x4d49, 0x4d4a, 0x4d4b, 0x4d4c, 0x4d4d, 0x4d4e, 0x4d4f, 0x4d50, 0x4d51, 0x4d52, 0x4d53, 0x4d54, 0x4d55, 0x4d56, 0x4d57, 0x4d58, 0x4d59, 0x4d5a, 0x4d5b, 0x4d5c, 0x4d5d, 0x4d5e, 0x4d5f, 0x4d60, 0x4d61, 0x4d62, 0x4d63, 0x4d64, 0x4d65, 0x4d66, 0x4d67, 0x4d68, 0x4d69, 0x4d6a, 0x4d6b, 0x4d6c, 0x4d6d, 0x4d6e, 0x4d6f, 0x4d70, 0x4d71, 0x4d72, 0x4d73, 0x4d74, 0x4d75, 0x4d76, 0x4d77, 0x4d78, 0x4d79, 0x4d7a, 0x4d7b, 0x4d7c, 0x4d7d, 0x4d7e, 0x4e21, 0x4e22, 0x4e24, 0x4e25, 0x4e26, 0x4e27, 0x4e28, 0x4e29, 0x4e23, 0x4e2a, 0x4e2b, 0x4e2c, 0x4e2d, 0x4e2e, 0x4e2f, 0x4e30, 0x4e31, 0x4e32, 0x4e33, 0x4e34, 0x4e35, 0x4e36, 0x4e37, 0x4e38, 0x4e39, 0x4e3a, 0x4e3b, 0x4e3c, 0x4e3d, 0x4e3e, 0x4e3f, 0x4e40, 0x4e41, 0x4e42, 0x4e43, 0x4e44, 0x4e45, 0x4e46, 0x4e47, 0x4e48, 0x4e49, 0x4e4a, 0x4e4b, 0x4e4c, 0x4e4d, 0x4e4e, 0x4e4f, 0x4e50, 0x4e51, 0x4e52, 0x4e53, 0x4e54, 0x4e55, 0x4e56, 0x4e57, 0x4e58, 0x4e59, 0x4e5a, 0x4e5b, 0x4e5c, 0x4e5d, 0x4e5e, 0x4e5f, 0x4e60, 0x4e61, 0x4e62, 0x4e63, 0x4e64, 0x4e65, 0x4e66, 0x4e67, 0x4e68, 0x4e69, 0x4e6a, 0x4e6b, 0x4e6c, 0x4e6d, 0x4e6e, 0x4e6f, 0x4e70, 0x4e71, 0x4e72, 0x4e73, 0x4e74, 0x4e75, 0x4e76, 0x4e77, 0x4e78, 0x4e79, 0x4e7a, 0x4e7b, 0x4e7c, 0x4e7d, 0x4e7e, 0x4f21, 0x4f22, 0x4f23, 0x4f24, 0x4f25, 0x4f26, 0x4f27, 0x4f28, 0x4f29, 0x4f2a, 0x4f2b, 0x4f2c, 0x4f2d, 0x4f2e, 0x4f2f, 0x4f30, 0x4f31, 0x4f32, 0x4f33, 0x4f34, 0x4f35, 0x4f36, 0x4f37, 0x4f38, 0x4f39, 0x4f3a, 0x4f3b, 0x4f3c, 0x4f3d, 0x4f3e, 0x4f3f, 0x4f40, 0x4f41, 0x4f42, 0x4f43, 0x4f44, 0x4f45, 0x4f46, 0x4f47, 0x4f48, 0x4f49, 0x4f4a, 0x4f4b, 0x4f4c, 0x4f4d, 0x4f4e, 0x4f4f, 0x4f50, 0x4f51, 0x4f52, 0x4f53, 0x4f54, 0x4f55, 0x4f56, 0x4f57, 0x4f58, 0x4f59, 0x4f5a, 0x4f5b, 0x4f5c, 0x4f5d, 0x4f5e, 0x4f5f, 0x4f60, 0x4f61, 0x4f62, 0x4f63, 0x4f64, 0x4f65, 0x4f66, 0x4f67, 0x4f68, 0x4f69, 0x4f6a, 0x4f6b, 0x4f6c, 0x4f6d, 0x4f6e, 0x4f6f, 0x4f70, 0x4f71, 0x4f72, 0x4f74, 0x4f75, 0x4f76, 0x4f73, 0x4f77, 0x4f78, 0x4f79, 0x4f7a, 0x4f7b, 0x4f7c, 0x4f7d, 0x4f7e, 0x5021, 0x5022, 0x5023, 0x5024, 0x5025, 0x5026, 0x5027, 0x5028, 0x5029, 0x502a, 0x502b, 0x502c, 0x502e, 0x502f, 0x5030, 0x5031, 0x502d, 0x5032, 0x5033, 0x5034, 0x5035, 0x5037, 0x5038, 0x5039, 0x503a, 0x503b, 0x5036, 0x503c, 0x503d, 0x503e, 0x503f, 0x5040, 0x5041, 0x5042, 0x5043, 0x5044, 0x5045, 0x5046, 0x5047, 0x5048, 0x5049, 0x504a, 0x504b, 0x504c, 0x504d, 0x504e, 0x504f, 0x5050, 0x5051, 0x5052, 0x5053, 0x5054, 0x5055, 0x5056, 0x5057, 0x5058, 0x5059, 0x505a, 0x505b, 0x505c, 0x505d, 0x505e, 0x505f, 0x5060, 0x5061, 0x5062, 0x5063, 0x5064, 0x5065, 0x5066, 0x5067, 0x5068, 0x5069, 0x506a, 0x506b, 0x506c, 0x506d, 0x506e, 0x506f, 0x5070, 0x5071, 0x5072, 0x5073, 0x5074, 0x5075, 0x5076, 0x5077, 0x5078, 0x5079, 0x507a, 0x507b, 0x507c, 0x507d, 0x507e, 0x5121, 0x5122, 0x5123, 0x5124, 0x5125, 0x5126, 0x5127, 0x5128, 0x5129, 0x512a, 0x512b, 0x512c, 0x512d, 0x512e, 0x512f, 0x5130, 0x5131, 0x5132, 0x5133, 0x5134, 0x5135, 0x5136, 0x5137, 0x5138, 0x5139, 0x513a, 0x513b, 0x513c, 0x513d, 0x513e, 0x513f, 0x5140, 0x5141, 0x5142, 0x5143, 0x5144, 0x5145, 0x5146, 0x5147, 0x5148, 0x5149, 0x514a, 0x514b, 0x514c, 0x514d, 0x514e, 0x514f, 0x5150, 0x5151, 0x5152, 0x5153, 0x5154, 0x5155, 0x5156, 0x5157, 0x5158, 0x5159, 0x515a, 0x515b, 0x515c, 0x515d, 0x515e, 0x515f, 0x5160, 0x5161, 0x5162, 0x5163, 0x5164, 0x5165, 0x5166, 0x5167, 0x5168, 0x5169, 0x516a, 0x516b, 0x516c, 0x516d, 0x516e, 0x516f, 0x5170, 0x5171, 0x5172, 0x5173, 0x5174, 0x5175, 0x5176, 0x5177, 0x5178, 0x5179, 0x517a, 0x517b, 0x517c, 0x517d, 0x517e, 0x5221, 0x5222, 0x5223, 0x5224, 0x5225, 0x5226, 0x5227, 0x5228, 0x5229, 0x522a, 0x522b, 0x522c, 0x522d, 0x522e, 0x522f, 0x5230, 0x5231, 0x5232, 0x5233, 0x5234, 0x5235, 0x5236, 0x5237, 0x5238, 0x5239, 0x523a, 0x523b, 0x523c, 0x523d, 0x523e, 0x523f, 0x5240, 0x5241, 0x5242, 0x5243, 0x5244, 0x5245, 0x5246, 0x5247, 0x5248, 0x5249, 0x524a, 0x524b, 0x524c, 0x524d, 0x524e, 0x524f, 0x5250, 0x5251, 0x5252, 0x5253, 0x5254, 0x5255, 0x5256, 0x5257, 0x5258, 0x5259, 0x525a, 0x525b, 0x525c, 0x525d, 0x525e, 0x525f, 0x5260, 0x5261, 0x5262, 0x5263, 0x5264, 0x5265, 0x5266, 0x5267, 0x5268, 0x5269, 0x526a, 0x526b, 0x526c, 0x526d, 0x526e, 0x526f, 0x5270, 0x5271, 0x5272, 0x5273, 0x5274, 0x5276, 0x5277, 0x5278, 0x5275, 0x5279, 0x527a, 0x527b, 0x527c, 0x527d, 0x527e, 0x5321, 0x5322, 0x5323, 0x5324, 0x5325, 0x5326, 0x5327, 0x5328, 0x5329, 0x532a, 0x532b, 0x532c, 0x532d, 0x532e, 0x532f, 0x5330, 0x5331, 0x5332, 0x5333, 0x5334, 0x5335, 0x5336, 0x5337, 0x5338, 0x5339, 0x533a, 0x533b, 0x533c, 0x533d, 0x533e, 0x533f, 0x5340, 0x5341, 0x5342, 0x5343, 0x5344, 0x5345, 0x5346, 0x5347, 0x5348, 0x5349, 0x534a, 0x534b, 0x534c, 0x534d, 0x534e, 0x534f, 0x5350, 0x5351, 0x5352, 0x5353, 0x5354, 0x5355, 0x5356, 0x5357, 0x5358, 0x5359, 0x535a, 0x535b, 0x535c, 0x535d, 0x535e, 0x535f, 0x5360, 0x5361, 0x5362, 0x5363, 0x5364, 0x5365, 0x5366, 0x5367, 0x5368, 0x5369, 0x536a, 0x536b, 0x536c, 0x536d, 0x536e, 0x536f, 0x5370, 0x5371, 0x5372, 0x5373, 0x5374, 0x5375, 0x5376, 0x5377, 0x5378, 0x5379, 0x537a, 0x537b, 0x537c, 0x537d, 0x537e, 0x5421, 0x5422, 0x5423, 0x5424, 0x5425, 0x5426, 0x5427, 0x5428, 0x5429, 0x542a, 0x542b, 0x542c, 0x542d, 0x542e, 0x542f, 0x5430, 0x5431, 0x5432, 0x5434, 0x5435, 0x5436, 0x5437, 0x5438, 0x5439, 0x543a, 0x543b, 0x543c, 0x543d, 0x543e, 0x5433, 0x543f, 0x5440, 0x5441, 0x5442, 0x5443, 0x5444, 0x5445, 0x5446, 0x5447, 0x5448, 0x5449, 0x544a, 0x544b, 0x544c, 0x544d, 0x544e, 0x544f, 0x5450, 0x5451, 0x5452, 0x5453, 0x5454, 0x5455, 0x5456, 0x5457, 0x5458, 0x5459, 0x545a, 0x545b, 0x545c, 0x545d, 0x545e, 0x545f, 0x5460, 0x5461, 0x5462, 0x5463, 0x5464, 0x5465, 0x5466, 0x5467, 0x5468, 0x5469, 0x546a, 0x546c, 0x546b, 0x546d, 0x546e, 0x546f, 0x5470, 0x5471, 0x5472, 0x5473, 0x5474, 0x5475, 0x5476, 0x5477, 0x5478, 0x5479, 0x547a, 0x547b, 0x547c, 0x547d, 0x547e, 0x5521, 0x5522, 0x5523, 0x5524, 0x5525, 0x5526, 0x5527, 0x5528, 0x5529, 0x552a, 0x552b, 0x552c, 0x552d, 0x552e, 0x552f, 0x5530, 0x5531, 0x5532, 0x5533, 0x5534, 0x5535, 0x5536, 0x5537, 0x5538, 0x5539, 0x553a, 0x553b, 0x553c, 0x553d, 0x553e, 0x553f, 0x5540, 0x5541, 0x5542, 0x5543, 0x5544, 0x5545, 0x5546, 0x5547, 0x5548, 0x5549, 0x554a, 0x554b, 0x554c, 0x554d, 0x554e, 0x554f, 0x5550, 0x5551, 0x5552, 0x5553, 0x5554, 0x5555, 0x5556, 0x5557, 0x5558, 0x5559, 0x555a, 0x555b, 0x555c, 0x555d, 0x555e, 0x555f, 0x5560, 0x5561, 0x5562, 0x5563, 0x5564, 0x5565, 0x5566, 0x5567, 0x5568, 0x5569, 0x556a, 0x556b, 0x556c, 0x556d, 0x556e, 0x556f, 0x5570, 0x5571, 0x5572, 0x5573, 0x5574, 0x5575, 0x5576, 0x5577, 0x5578, 0x5579, 0x557a, 0x557b, 0x557c, 0x557d, 0x557e, 0x5621, 0x5622, 0x5623, 0x5624, 0x5625, 0x5626, 0x5627, 0x5628, 0x5629, 0x562a, 0x562b, 0x562c, 0x562d, 0x562e, 0x562f, 0x5630, 0x5631, 0x5632, 0x5633, 0x5634, 0x5635, 0x5636, 0x5637, 0x5638, 0x5639, 0x563a, 0x563b, 0x563c, 0x563d, 0x563e, 0x563f, 0x5640, 0x5641, 0x5642, 0x5643, 0x5644, 0x5645, 0x5647, 0x5648, 0x5649, 0x564a, 0x564b, 0x5646, 0x564c, 0x564d, 0x564e, 0x564f, 0x5650, 0x5651, 0x5652, 0x5653, 0x5654, 0x5656, 0x5657, 0x5658, 0x5655, 0x5659, 0x565a, 0x565b, 0x565c, 0x565d, 0x565e, 0x565f, 0x5660, 0x5661, 0x5662, 0x5663, 0x5664, 0x5665, 0x5666, 0x5667, 0x5668, 0x5669, 0x566a, 0x566b, 0x566c, 0x566d, 0x566e, 0x566f, 0x5670, 0x5671, 0x5672, 0x5673, 0x5674, 0x5675, 0x5676, 0x5677, 0x5678, 0x5679, 0x567a, 0x567b, 0x567c, 0x567d, 0x567e, 0x5721, 0x5722, 0x5723, 0x5724, 0x5725, 0x5726, 0x5727, 0x5728, 0x5729, 0x572a, 0x572b, 0x572c, 0x572d, 0x572e, 0x572f, 0x5730, 0x5731, 0x5732, 0x5733, 0x5734, 0x5735, 0x5736, 0x5737, 0x5738, 0x5739, 0x573a, 0x573b, 0x573c, 0x573d, 0x573e, 0x573f, 0x5740, 0x5741, 0x5742, 0x5743, 0x5744, 0x5745, 0x5746, 0x5747, 0x5748, 0x5749, 0x574a, 0x574b, 0x574c, 0x574d, 0x574e, 0x574f, 0x5750, 0x5751, 0x5752, 0x5753, 0x5754, 0x5755, 0x5756, 0x5757, 0x5758, 0x5759, 0x575a, 0x575b, 0x575c, 0x575d, 0x575e, 0x575f, 0x5760, 0x5761, 0x5762, 0x5764, 0x5765, 0x5766, 0x5767, 0x5768, 0x5769, 0x576a, 0x576b, 0x576c, 0x576d, 0x576e, 0x576f, 0x5770, 0x5771, 0x5772, 0x5773, 0x5774, 0x5775, 0x5776, 0x5777, 0x5778, 0x5779, 0x583e, 0x5763, 0x577a, 0x577b, 0x577c, 0x577d, 0x577e, 0x5821, 0x5822, 0x5823, 0x5824, 0x5825, 0x5826, 0x5827, 0x5828, 0x5829, 0x582a, 0x582b, 0x582c, 0x582d, 0x582e, 0x582f, 0x5830, 0x5831, 0x5832, 0x5833, 0x584c, 0x5834, 0x5835, 0x5836, 0x5837, 0x5838, 0x5839, 0x583a, 0x583b, 0x583c, 0x583d, 0x583f, 0x5840, 0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849, 0x584a, 0x584b, 0x584d, 0x584e, 0x584f, 0x5850, 0x5851, 0x5852, 0x5853, 0x5854, 0x5855, 0x5856, 0x5857, 0x5858, 0x5859, 0x585a, 0x585b, 0x585c, 0x585d, 0x585e, 0x585f, 0x5860, 0x5861, 0x5862, 0x5863, 0x5864, 0x5865, 0x5866, 0x5867, 0x5868, 0x5869, 0x586a, 0x586b, 0x586c, 0x586d, 0x586e, 0x586f, 0x5870, 0x5871, 0x5872, 0x5873, 0x5874, 0x5875, 0x5876, 0x5877, 0x5878, 0x5879, 0x587a, 0x587b, 0x587c, 0x587d, 0x587e, 0x5921, 0x5922, 0x5923, 0x5924, 0x5925, 0x5926, 0x5927, 0x5928, 0x592a, 0x592b, 0x592c, 0x592d, 0x592e, 0x592f, 0x5930, 0x5931, 0x5932, 0x5933, 0x5934, 0x5935, 0x5936, 0x5937, 0x5938, 0x5939, 0x593a, 0x593b, 0x593c, 0x5929, 0x593d, 0x593e, 0x593f, 0x5940, 0x5941, 0x5942, 0x5943, 0x5944, 0x5945, 0x5946, 0x5947, 0x5948, 0x5949, 0x594a, 0x594b, 0x594c, 0x594d, 0x594e, 0x594f, 0x5950, 0x5951, 0x5952, 0x5953, 0x5954, 0x5955, 0x5956, 0x5957, 0x5958, 0x5959, 0x595a, 0x595b, 0x595c, 0x595d, 0x595e, 0x595f, 0x5960, 0x5961, 0x5962, 0x5963, 0x5964, 0x5965, 0x5966, 0x5974, 0x5967, 0x5968, 0x5969, 0x596a, 0x596b, 0x596c, 0x596d, 0x596e, 0x596f, 0x5970, 0x5971, 0x5972, 0x5973, 0x5975, 0x5976, 0x5977, 0x5978, 0x5979, 0x597a, 0x597b, 0x597c, 0x597d, 0x597e, 0x5a21, 0x5a22, 0x5a23, 0x5a24, 0x5a25, 0x5a26, 0x5a27, 0x5a28, 0x5a29, 0x5a2a, 0x5a2b, 0x5a2c, 0x5a2d, 0x5a2e, 0x5a2f, 0x5a30, 0x5a31, 0x5a32, 0x5a33, 0x5a34, 0x5a35, 0x5a36, 0x3866, 0x5a37, 0x5a38, 0x5a39, 0x5a3a, 0x5a3b, 0x5a3c, 0x5a3d, 0x5a3e, 0x5a3f, 0x5a40, 0x5a41, 0x5a42, 0x5a43, 0x5a44, 0x5a45, 0x5a46, 0x5a47, 0x5a48, 0x5a49, 0x5a4a, 0x5a4b, 0x5a6d, 0x5a4c, 0x5a4d, 0x5a4e, 0x5a4f, 0x5a50, 0x5a51, 0x5a52, 0x5a53, 0x5a54, 0x5a55, 0x5a56, 0x5a57, 0x5a58, 0x5a59, 0x5a5a, 0x5a5b, 0x5a5c, 0x5a5d, 0x5a5e, 0x5a5f, 0x5a60, 0x5a61, 0x5a62, 0x5a63, 0x5a64, 0x5a65, 0x5a66, 0x5a67, 0x5a68, 0x5a69, 0x5a6a, 0x5a6b, 0x5a6c, 0x5a6e, 0x5a6f, 0x5a70, 0x5a71, 0x5a72, 0x5a73, 0x5a74, 0x5a75, 0x5a76, 0x5a77, 0x5a78, 0x5a79, 0x5a7a, 0x5a7b, 0x5a7c, 0x5a7d, 0x5a7e, 0x5b21, 0x5b22, 0x5b23, 0x5b24, 0x5b25, 0x5b26, 0x5b27, 0x5b28, 0x5b29, 0x5b2a, 0x5b2b, 0x5b2c, 0x5b2d, 0x5b2e, 0x5b2f, 0x5b30, 0x5b31, 0x5b32, 0x5b33, 0x5b34, 0x5b35, 0x5b36, 0x5b37, 0x5b38, 0x5b39, 0x5b3a, 0x5b3b, 0x5b3c, 0x5b3d, 0x5b3e, 0x5b3f, 0x5b40, 0x5b41, 0x5b42, 0x5b43, 0x5b44, 0x5b45, 0x5b46, 0x5b47, 0x5b48, 0x5b49, 0x5b4a, 0x5b4b, 0x5b4c, 0x5b4d, 0x5b4e, 0x5b4f, 0x5b50, 0x5b51, 0x5b52, 0x5b53, 0x5b54, 0x5b55, 0x5b56, 0x5b57, 0x5b58, 0x5b59, 0x5b5a, 0x5b5b, 0x5b5c, 0x5b5d, 0x5b5e, 0x5b5f, 0x5b60, 0x5b61, 0x5b62, 0x5b63, 0x5b64, 0x5b65, 0x5b66, 0x5b67, 0x5b68, 0x5b69, 0x5b6a, 0x5b6b, 0x5b6c, 0x5b6d, 0x5b6e, 0x5b70, 0x5b71, 0x5b72, 0x5b73, 0x5b6f, 0x5b74, 0x5b75, 0x5b76, 0x5b77, 0x5b78, 0x5b79, 0x5b7a, 0x5b7b, 0x5b7c, 0x5b7d, 0x5b7e, 0x5c21, 0x5c22, 0x5c23, 0x5c24, 0x5c25, 0x5c26, 0x5c27, 0x5c28, 0x5c29, 0x5c2a, 0x5c2b, 0x5c2c, 0x5c2d, 0x5c2e, 0x5c2f, 0x5c30, 0x5c31, 0x5c32, 0x5c33, 0x5c34, 0x5c35, 0x5c36, 0x5c37, 0x5c38, 0x5c39, 0x5c3a, 0x5c3b, 0x5c3c, 0x5c3d, 0x5c3e, 0x5c3f, 0x5c40, 0x5c41, 0x5c42, 0x5c43, 0x5c44, 0x5c45, 0x5c46, 0x5c47, 0x5c48, 0x5c49, 0x5c4a, 0x5c4b, 0x5c4c, 0x5c4d, 0x5c4e, 0x5c4f, 0x5c50, 0x5c51, 0x5c52, 0x5c53, 0x5c54, 0x5c55, 0x5c56, 0x5c57, 0x5c58, 0x5c59, 0x5c5a, 0x5c5b, 0x5c5c, 0x5c5d, 0x5c5e, 0x5c5f, 0x5c60, 0x5c61, 0x5c62, 0x5c63, 0x5c64, 0x5c65, 0x5c66, 0x5c67, 0x5c68, 0x5c69, 0x5c6a, 0x5c6b, 0x5c6c, 0x5c6d, 0x5c6e, 0x5c6f, 0x5c70, 0x5c71, 0x5c72, 0x5c73, 0x5c74, 0x5c75, 0x5c76, 0x5c77, 0x5c78, 0x5c79, 0x5c7a, 0x5c7b, 0x5c7c, 0x5c7d, 0x5c7e, 0x5d21, 0x5d22, 0x5d23, 0x5d24, 0x5d25, 0x5d26, 0x5d27, 0x5d28, 0x5d29, 0x5d2a, 0x5d2b, 0x5d2c, 0x5d2d, 0x5d2e, 0x5d2f, 0x5d30, 0x5d31, 0x5d32, 0x5d33, 0x5d34, 0x5d35, 0x5d36, 0x5d37, 0x5d38, 0x5d39, 0x5d3a, 0x5d3b, 0x5d3c, 0x5d3d, 0x5d3e, 0x5d3f, 0x5d40, 0x5d41, 0x5d42, 0x5d43, 0x5d44, 0x5d45, 0x5d46, 0x5d47, 0x5d48, 0x5d49, 0x5d4a, 0x5d4b, 0x5d4c, 0x5d4d, 0x5d4e, 0x5d4f, 0x5d50, 0x5d51, 0x5d52, 0x5d53, 0x5d54, 0x5d55, 0x5d56, 0x5d57, 0x5d58, 0x5d59, 0x5d5a, 0x5d5b, 0x5d5c, 0x5d5d, 0x5d5e, 0x5d5f, 0x5d60, 0x5d61, 0x5d62, 0x5d63, 0x5d64, 0x5d65, 0x5d66, 0x5d67, 0x5d68, 0x5d69, 0x5d6a, 0x5d6b, 0x5d6c, 0x5d6d, 0x5d6e, 0x5d6f, 0x5d70, 0x5d71, 0x5d72, 0x5d73, 0x5d74, 0x5d75, 0x5d76, 0x5d77, 0x5d78, 0x5d79, 0x5d7a, 0x5d7b, 0x5d7c, 0x5d7d, 0x5d7e, 0x5e21, 0x5e22, 0x5e23, 0x5e24, 0x5e25, 0x5e26, 0x5e27, 0x5e28, 0x5e29, 0x5e2a, 0x5e2b, 0x5e2c, 0x5e2d, 0x5e2e, 0x5e2f, 0x5e30, 0x5e31, 0x5e32, 0x5e33, 0x5e34, 0x5e35, 0x5e36, 0x5e37, 0x5e38, 0x5e39, 0x5e3f, 0x5e3a, 0x5e3b, 0x5e3c, 0x5e3d, 0x5e3e, 0x5e40, 0x5e41, 0x5e42, 0x5e43, 0x5e44, 0x5e45, 0x5e46, 0x5e47, 0x5e48, 0x5e49, 0x5e4e, 0x5e4a, 0x5e4b, 0x5e4c, 0x5e4d, 0x5e4f, 0x5e50, 0x5e51, 0x5e52, 0x5e53, 0x5e54, 0x5e55, 0x5e56, 0x5e57, 0x5e58, 0x5e59, 0x5e5a, 0x5e5b, 0x5e5c, 0x5e5d, 0x5e5e, 0x5e5f, 0x5e60, 0x5e61, 0x5e62, 0x5e63, 0x5e64, 0x5e65, 0x5e66, 0x5e67, 0x5e68, 0x5e69, 0x5e6a, 0x5e6b, 0x5e6c, 0x5e6d, 0x5e6e, 0x5e6f, 0x5e72, 0x5e70, 0x5e71, 0x5e73, 0x5e74, 0x5e75, 0x5e76, 0x5e77, 0x5e78, 0x5e79, 0x5e7a, 0x5e7b, 0x5e7c, 0x5e7d, 0x5e7e, 0x5f21, 0x5f22, 0x5f23, 0x5f24, 0x5f25, 0x5f26, 0x5f27, 0x5f28, 0x5f29, 0x5f2a, 0x5f2b, 0x5f2c, 0x5f2d, 0x5f2e, 0x5f2f, 0x5f30, 0x5f32, 0x5f31, 0x5f33, 0x5f34, 0x5f35, 0x5f36, 0x5f37, 0x5f38, 0x5f39, 0x5f3a, 0x5f3b, 0x5f3c, 0x5f3d, 0x5f3e, 0x5f3f, 0x5f40, 0x5f41, 0x5f42, 0x5f43, 0x5f44, 0x5f45, 0x5f46, 0x5f47, 0x5f48, 0x5f49, 0x5f4a, 0x5f4b, 0x5f4c, 0x5f4d, 0x5f4e, 0x5f4f, 0x5f50, 0x5f51, 0x5f52, 0x5f53, 0x5f54, 0x5f55, 0x5f56, 0x5f57, 0x5f58, 0x5f59, 0x5f5a, 0x5f5b, 0x5f5c, 0x5f5d, 0x5f6f, 0x5f5e, 0x5f5f, 0x5f60, 0x5f61, 0x5f62, 0x5f63, 0x5f64, 0x5f65, 0x5f66, 0x5f67, 0x5f68, 0x5f69, 0x5f6a, 0x5f6b, 0x5f6c, 0x5f6d, 0x5f6e, 0x5f70, 0x5f71, 0x5f72, 0x5f73, 0x5f74, 0x5f75, 0x5f76, 0x5f77, 0x5f78, 0x5f79, 0x5f7a, 0x5f7b, 0x5f7c, 0x5f7d, 0x5f7e, 0x6021, 0x6022, 0x6023, 0x6024, 0x6025, 0x6026, 0x6027, 0x6028, 0x6029, 0x602a, 0x602b, 0x602c, 0x602d, 0x602e, 0x602f, 0x6030, 0x6031, 0x6032, 0x6033, 0x6034, 0x6035, 0x6036, 0x6037, 0x6038, 0x6039, 0x603a, 0x603b, 0x603c, 0x603d, 0x603e, 0x603f, 0x6040, 0x6041, 0x6042, 0x6043, 0x6044, 0x6045, 0x6046, 0x6047, 0x6048, 0x6049, 0x604a, 0x604b, 0x604c, 0x604d, 0x604e, 0x604f, 0x6050, 0x6051, 0x6052, 0x6053, 0x6054, 0x6055, 0x6056, 0x6057, 0x6058, 0x6059, 0x605a, 0x605b, 0x605c, 0x605d, 0x6064, 0x605e, 0x605f, 0x6060, 0x6061, 0x6062, 0x6063, 0x6065, 0x6066, 0x6067, 0x6068, 0x6069, 0x606a, 0x606b, 0x606c, 0x606d, 0x606e, 0x606f, 0x6070, 0x6071, 0x6072, 0x6073, 0x6074, 0x6075, 0x6076, 0x6077, 0x6078, 0x6079, 0x607a, 0x607b, 0x607c, 0x607d, 0x607e, 0x6121, 0x6122, 0x6123, 0x6124, 0x6125, 0x6126, 0x6127, 0x6128, 0x6129, 0x612a, 0x612b, 0x612c, 0x612d, 0x612e, 0x612f, 0x6130, 0x6131, 0x6132, 0x6133, 0x6134, 0x6135, 0x6136, 0x6137, 0x6138, 0x6139, 0x613a, 0x613b, 0x613c, 0x613d, 0x613e, 0x613f, 0x6140, 0x6141, 0x6142, 0x6143, 0x6144, 0x6145, 0x6146, 0x6147, 0x6148, 0x6149, 0x614a, 0x614b, 0x614c, 0x614d, 0x614e, 0x614f, 0x6150, 0x6151, 0x6152, 0x6154, 0x6155, 0x6156, 0x6153, 0x6157, 0x6158, 0x6159, 0x615a, 0x615b, 0x615c, 0x615d, 0x615e, 0x615f, 0x6160, 0x6161, 0x6162, 0x6163, 0x6164, 0x6165, 0x6166, 0x6167, 0x6168, 0x6169, 0x616a, 0x616b, 0x616c, 0x616d, 0x616e, 0x616f, 0x6170, 0x6171, 0x6172, 0x6173, 0x6174, 0x6175, 0x6176, 0x6177, 0x6178, 0x6179, 0x617a, 0x617b, 0x617d, 0x617e, 0x6221, 0x6222, 0x6223, 0x6224, 0x617c, 0x622d, 0x6225, 0x6226, 0x6227, 0x6228, 0x6229, 0x622a, 0x622b, 0x622c, 0x622f, 0x6230, 0x6231, 0x6232, 0x622e, 0x6233, 0x6234, 0x6235, 0x6236, 0x6237, 0x6238, 0x6239, 0x623a, 0x623b, 0x623c, 0x623d, 0x623e, 0x623f, 0x6240, 0x6241, 0x6242, 0x6243, 0x6245, 0x6246, 0x6244, 0x6247, 0x6248, 0x6249, 0x624a, 0x624b, 0x624c, 0x624d, 0x624e, 0x624f, 0x6250, 0x6251, 0x6252, 0x6253, 0x6254, 0x6255, 0x6256, 0x6257, 0x6258, 0x6259, 0x625a, 0x625b, 0x625c, 0x625d, 0x625e, 0x625f, 0x6260, 0x6261, 0x6262, 0x6263, 0x6264, 0x6265, 0x6266, 0x6267, 0x6268, 0x6269, 0x626a, 0x626b, 0x626c, 0x626d, 0x626e, 0x626f, 0x6270, 0x6271, 0x6272, 0x6273, 0x6274, 0x6275, 0x6276, 0x6277, 0x6278, 0x6279, 0x627a, 0x627b, 0x627c, 0x627d, 0x627e, 0x6321, 0x6322, 0x6323, 0x6324, 0x6325, 0x6326, 0x6327, 0x6328, 0x6329, 0x632a, 0x632b, 0x632c, 0x632d, 0x632e, 0x632f, 0x6330, 0x6331, 0x6332, 0x6333, 0x6334, 0x6335, 0x6336, 0x6337, 0x6338, 0x6339, 0x633a, 0x633b, 0x633c, 0x633d, 0x633e, 0x633f, 0x6340, 0x6341, 0x6342, 0x6343, 0x6344, 0x6345, 0x6346, 0x6347, 0x6348, 0x6349, 0x634a, 0x634b, 0x634c, 0x634d, 0x634e, 0x634f, 0x6350, 0x6351, 0x6352, 0x6353, 0x6354, 0x6355, 0x6356, 0x6357, 0x6358, 0x6359, 0x635a, 0x635b, 0x635c, 0x635d, 0x635e, 0x635f, 0x6360, 0x6361, 0x6362, 0x6363, 0x6364, 0x6365, 0x6366, 0x6367, 0x6368, 0x6369, 0x636a, 0x636b, 0x636c, 0x636d, 0x636e, 0x636f, 0x6370, 0x6371, 0x6372, 0x6373, 0x6374, 0x6375, 0x6376, 0x6377, 0x6378, 0x6379, 0x637a, 0x637b, 0x637c, 0x637d, 0x637e, 0x6421, 0x6422, 0x6423, 0x6424, 0x6425, 0x6426, 0x6427, 0x6428, 0x6429, 0x642a, 0x642b, 0x642c, 0x642d, 0x642e, 0x642f, 0x6430, 0x6431, 0x6432, 0x6433, 0x6434, 0x6435, 0x6436, 0x6437, 0x6438, 0x6439, 0x643a, 0x643b, 0x643c, 0x643d, 0x643e, 0x643f, 0x6440, 0x6441, 0x6442, 0x6443, 0x6444, 0x6445, 0x6446, 0x6447, 0x6448, 0x6449, 0x644a, 0x644b, 0x644c, 0x644d, 0x644e, 0x644f, 0x6450, 0x6451, 0x6452, 0x6453, 0x6454, 0x6455, 0x6456, 0x6457, 0x6458, 0x6459, 0x645a, 0x645b, 0x645c, 0x645d, 0x645e, 0x645f, 0x6460, 0x6461, 0x6462, 0x6463, 0x6464, 0x6465, 0x6466, 0x6467, 0x6468, 0x6469, 0x646a, 0x646b, 0x646c, 0x646d, 0x646e, 0x646f, 0x6470, 0x6471, 0x6472, 0x6473, 0x6474, 0x6475, 0x6476, 0x6477, 0x6478, 0x6479, 0x647a, 0x647b, 0x647c, 0x647d, 0x647e, 0x6521, 0x6522, 0x6523, 0x6524, 0x6525, 0x6526, 0x6527, 0x6528, 0x6529, 0x652a, 0x652b, 0x652c, 0x652d, 0x652e, 0x652f, 0x6530, 0x6531, 0x6532, 0x6533, 0x6534, 0x6535, 0x653b, 0x6536, 0x6537, 0x6538, 0x6539, 0x653a, 0x653c, 0x653d, 0x653e, 0x653f, 0x6540, 0x6541, 0x6542, 0x6543, 0x6544, 0x6545, 0x6546, 0x6547, 0x6548, 0x6549, 0x654a, 0x654b, 0x654c, 0x654d, 0x654f, 0x6550, 0x654e, 0x6551, 0x6552, 0x6553, 0x6554, 0x6555, 0x6556, 0x6557, 0x6558, 0x6559, 0x655a, 0x655b, 0x655c, 0x655d, 0x655e, 0x655f, 0x6560, 0x6561, 0x6562, 0x6563, 0x6564, 0x6565, 0x6566, 0x6568, 0x6567, 0x6569, 0x656a, 0x656b, 0x656c, 0x656d, 0x656e, 0x656f, 0x6570, 0x6571, 0x6572, 0x6573, 0x6574, 0x6575, 0x6576, 0x6577, 0x6578, 0x6579, 0x657a, 0x657c, 0x657b, 0x657d, 0x657e, 0x6621, 0x6622, 0x6623, 0x6624, 0x6625, 0x6626, 0x6627, 0x6628, 0x6629, 0x662a, 0x662b, 0x662c, 0x662d, 0x662e, 0x662f, 0x6630, 0x6631, 0x6632, 0x6633, 0x6634, 0x6635, 0x6636, 0x6637, 0x6638, 0x6639, 0x663a, 0x663b, 0x663c, 0x663d, 0x663e, 0x663f, 0x6640, 0x6641, 0x6642, 0x6643, 0x6644, 0x6645, 0x6646, 0x6647, 0x6648, 0x6649, 0x664a, 0x664b, 0x664c, 0x664d, 0x664e, 0x664f, 0x6650, 0x6651, 0x6652, 0x6653, 0x6654, 0x6655, 0x6656, 0x6657, 0x6658, 0x6659, 0x665a, 0x665b, 0x665c, 0x665d, 0x665e, 0x665f, 0x6660, 0x6661, 0x6662, 0x6663, 0x6664, 0x6665, 0x6666, 0x6667, 0x6668, 0x6669, 0x666a, 0x666b, 0x666c, 0x666d, 0x666e, 0x666f, 0x6670, 0x6671, 0x6672, 0x6673, 0x6675, 0x6676, 0x6677, 0x6678, 0x6679, 0x667a, 0x667b, 0x667c, 0x667d, 0x667e, 0x6721, 0x6722, 0x6723, 0x6724, 0x6725, 0x6726, 0x6727, 0x6728, 0x6729, 0x672a, 0x672b, 0x672c, 0x672d, 0x672e, 0x672f, 0x6730, 0x6731, 0x6732, 0x6733, 0x6734, 0x6735, 0x6736, 0x6737, 0x6738, 0x6739, 0x673a, 0x673b, 0x673c, 0x673d, 0x673e, 0x673f, 0x6740, 0x6741, 0x6742, 0x6743, 0x6744, 0x6745, 0x6746, 0x6747, 0x6748, 0x6749, 0x674a, 0x674b, 0x674c, 0x674d, 0x674e, 0x674f, 0x6750, 0x6751, 0x6752, 0x6753, 0x6754, 0x6755, 0x6756, 0x6757, 0x6758, 0x6759, 0x675a, 0x675b, 0x675c, 0x675d, 0x675e, 0x675f, 0x6760, 0x6761, 0x6762, 0x6763, 0x6764, 0x6765, 0x6766, 0x676a, 0x6767, 0x6768, 0x6769, 0x676b, 0x676c, 0x676d, 0x676e, 0x676f, 0x6770, 0x6771, 0x6772, 0x6773, 0x6774, 0x6776, 0x6777, 0x6778, 0x6779, 0x6775, 0x677a, 0x677b, 0x677c, 0x677d, 0x6828, 0x677e, 0x6821, 0x6822, 0x6823, 0x6824, 0x6825, 0x6826, 0x6827, 0x6829, 0x682a, 0x682b, 0x682c, 0x682d, 0x682e, 0x682f, 0x6830, 0x6831, 0x6832, 0x6833, 0x6834, 0x6835, 0x6836, 0x6837, 0x6838, 0x6839, 0x683a, 0x683b, 0x683c, 0x683d, 0x683e, 0x683f, 0x6840, 0x6841, 0x6842, 0x6843, 0x6844, 0x6845, 0x6846, 0x6847, 0x6848, 0x6849, 0x684a, 0x684b, 0x684c, 0x684d, 0x684e, 0x684f, 0x6850, 0x6851, 0x6852, 0x6853, 0x6854, 0x6855, 0x6856, 0x6857, 0x6858, 0x6859, 0x685a, 0x685b, 0x685c, 0x685d, 0x685e, 0x685f, 0x6860, 0x6861, 0x6862, 0x6863, 0x6864, 0x6865, 0x6866, 0x6867, 0x6868, 0x6869, 0x686a, 0x686b, 0x686c, 0x686d, 0x686e, 0x686f, 0x6870, 0x6871, 0x6872, 0x6873, 0x6874, 0x6875, 0x6876, 0x6877, 0x6878, 0x6879, 0x687a, 0x687b, 0x687c, 0x687d, 0x687e, 0x6921, 0x6922, 0x6923, 0x6924, 0x6925, 0x6926, 0x6927, 0x6928, 0x6929, 0x692a, 0x692b, 0x692c, 0x692d, 0x692e, 0x692f, 0x6930, 0x6931, 0x6932, 0x6933, 0x6934, 0x6935, 0x6936, 0x6937, 0x6938, 0x6939, 0x693a, 0x693b, 0x693c, 0x693d, 0x693e, 0x693f, 0x6940, 0x6941, 0x6942, 0x6943, 0x6944, 0x6945, 0x6946, 0x6947, 0x6948, 0x6949, 0x694a, 0x694c, 0x694d, 0x694b, 0x694e, 0x694f, 0x6950, 0x6951, 0x6952, 0x6953, 0x6954, 0x6955, 0x6956, 0x6957, 0x6958, 0x6959, 0x695a, 0x695b, 0x695c, 0x695d, 0x695e, 0x695f, 0x6960, 0x6961, 0x6962, 0x6963, 0x6964, 0x6965, 0x6966, 0x6967, 0x6968, 0x6969, 0x696a, 0x696b, 0x696c, 0x696d, 0x696e, 0x696f, 0x6970, 0x6971, 0x6972, 0x6973, 0x6974, 0x6975, 0x6976, 0x6977, 0x6978, 0x6979, 0x697a, 0x697b, 0x697c, 0x697d, 0x697e, 0x6a21, 0x6a22, 0x6a23, 0x6a24, 0x6a25, 0x6a26, 0x6a27, 0x6a28, 0x6a29, 0x6a2a, 0x6a2b, 0x6a2c, 0x6a2d, 0x6a2e, 0x6a2f, 0x6a30, 0x6a31, 0x6a32, 0x6a33, 0x6a34, 0x6a35, 0x6a36, 0x6a37, 0x6a38, 0x6a39, 0x6a3a, 0x6a3b, 0x6a3c, 0x6a3d, 0x6a3e, 0x6a3f, 0x6a40, 0x6a41, 0x6a42, 0x6a43, 0x6a44, 0x6a45, 0x6a46, 0x6a47, 0x6a48, 0x6a49, 0x6a4a, 0x6a4b, 0x6a4c, 0x6a4d, 0x6a4e, 0x6a4f, 0x6a50, 0x6a51, 0x6a52, 0x6a53, 0x6a54, 0x6a55, 0x6a56, 0x6a57, 0x6a58, 0x6a59, 0x6a5a, 0x6a5b, 0x6a5c, 0x6a5d, 0x6a5e, 0x6a5f, 0x6a60, 0x6a61, 0x6a62, 0x6a63, 0x6a64, 0x6a65, 0x6a66, 0x6a67, 0x6a68, 0x6a69, 0x6a6a, 0x6a6b, 0x6a6c, 0x6a6d, 0x6a6e, 0x6a6f, 0x6a70, 0x6a71, 0x6a72, 0x6a73, 0x6a74, 0x6a75, 0x6a76, 0x6a77, 0x6a78, 0x6a79, 0x6a7a, 0x6a7b, 0x6a7c, 0x6a7d, 0x6a7e, 0x6b21, 0x6b22, 0x6b23, 0x6b24, 0x6b25, 0x6b26, 0x6b27, 0x6b28, 0x6b29, 0x6b2a, 0x6b2b, 0x6b2c, 0x6b2d, 0x6b2e, 0x6b2f, 0x6b30, 0x6b31, 0x6b32, 0x6b33, 0x6b34, 0x6b35, 0x6b36, 0x6b37, 0x6b38, 0x6b39, 0x6b3a, 0x6b3b, 0x6b3c, 0x6b3d, 0x6b3e, 0x6b3f, 0x6b40, 0x6b41, 0x6b42, 0x6b43, 0x6b44, 0x6b45, 0x6b46, 0x6b47, 0x6b48, 0x6b49, 0x6b50, 0x6b4a, 0x6b4b, 0x6b4c, 0x6b4d, 0x6b52, 0x6b4e, 0x6b4f, 0x6b51, 0x6b53, 0x6b54, 0x6b55, 0x6b56, 0x6b57, 0x6b58, 0x6b59, 0x6b5a, 0x6b5b, 0x6b5c, 0x6b5e, 0x6b5d, 0x6b5f, 0x6b60, 0x6b61, 0x6b62, 0x6b63, 0x6b64, 0x6b65, 0x6b66, 0x6b67, 0x6b68, 0x6b69, 0x6b6a, 0x6b6b, 0x6b6d, 0x6b6e, 0x6b6f, 0x6b6c, 0x6b70, 0x6b71, 0x6b72, 0x6b73, 0x6b74, 0x6b76, 0x6b75, 0x6b77, 0x6b78, 0x6b79, 0x6b7a, 0x6b7b, 0x6b7c, 0x6b7d, 0x6b7e, 0x6c21, 0x6c22, 0x6c23, 0x6c24, 0x6c25, 0x6c26, 0x6c27, 0x6c28, 0x6c29, 0x6c2a, 0x6c2b, 0x6c2c, 0x6c2d, 0x6c2e, 0x6c2f, 0x6c30, 0x6c31, 0x6c32, 0x6c33, 0x6c34, 0x6c35, 0x6c36, 0x6c37, 0x6c38, 0x6c39, 0x6c3a, 0x6c3b, 0x6c3c, 0x6c3d, 0x6c3e, 0x6c3f, 0x6c40, 0x6c41, 0x6c42, 0x6c43, 0x6c44, 0x6c45, 0x6c46, 0x6c47, 0x6c48, 0x6c49, 0x6c4a, 0x6c4b, 0x6c4c, 0x6c4e, 0x6c4f, 0x6c4d, 0x6c50, 0x6c51, 0x6c52, 0x6c53, 0x6c54, 0x6c55, 0x6c56, 0x6c57, 0x6c58, 0x6c59, 0x6c5a, 0x6c5b, 0x6c5c, 0x6c5d, 0x6c5e, 0x6c5f, 0x6c60, 0x6c61, 0x6c62, 0x6c63, 0x6c64, 0x6c65, 0x6c66, 0x6c67, 0x6c68, 0x6c69, 0x6c6a, 0x6c6b, 0x6c6c, 0x6c6d, 0x6c6e, 0x6c6f, 0x6c70, 0x6c71, 0x6c72, 0x6c73, 0x6c74, 0x6c75, 0x6c76, 0x6c77, 0x6c78, 0x6c79, 0x6c7a, 0x6c7b, 0x6c7c, 0x6c7d, 0x6c7e, 0x6d21, 0x6d22, 0x6d23, 0x6d24, 0x6d25, 0x6d26, 0x6d27, 0x6d28, 0x6d29, 0x6d2a, 0x6d2b, 0x6d2c, 0x6d2d, 0x6d2e, 0x6d2f, 0x6d30, 0x6d31, 0x6d32, 0x6d33, 0x6d34, 0x6d35, 0x6d36, 0x6d37, 0x6d38, 0x6d39, 0x6d3a, 0x6d3b, 0x6d3c, 0x6d3d, 0x6d3e, 0x6d3f, 0x6d40, 0x6d41, 0x6d42, 0x6d43, 0x6d44, 0x6d45, 0x6d46, 0x6d47, 0x6d48, 0x6d49, 0x6d4a, 0x6d4b, 0x6d4c, 0x6d4d, 0x6d4e, 0x6d4f, 0x6d50, 0x6d51, 0x6d52, 0x6d53, 0x6d54, 0x6d55, 0x6d56, 0x6d57, 0x6d58, 0x6d59, 0x6d5a, 0x6d5b, 0x6d5c, 0x6d5d, 0x6d5e, 0x6d5f, 0x6d60, 0x6d61, 0x6d62, 0x6d63, }; static const Summary16 jisx0212_uni2indx_page00[70] = { /* 0x0000 */ { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x4000 }, { 1, 0x0000 }, { 1, 0x0000 }, { 1, 0xc652 }, { 8, 0x8500 }, { 11, 0xffff }, { 27, 0xff7e }, { 41, 0xffff }, { 57, 0xff7f }, /* 0x0100 */ { 72, 0xffff }, { 88, 0xffcf }, { 102, 0xcff7 }, { 115, 0xffff }, { 131, 0x3fff }, { 145, 0xffff }, { 161, 0xffff }, { 177, 0x7fff }, { 192, 0x0000 }, { 192, 0x0000 }, { 192, 0x0000 }, { 192, 0x0000 }, { 192, 0xe000 }, { 195, 0x1fff }, { 208, 0x0000 }, { 208, 0x0020 }, /* 0x0200 */ { 209, 0x0000 }, { 209, 0x0000 }, { 209, 0x0000 }, { 209, 0x0000 }, { 209, 0x0000 }, { 209, 0x0000 }, { 209, 0x0000 }, { 209, 0x0000 }, { 209, 0x0000 }, { 209, 0x0000 }, { 209, 0x0000 }, { 209, 0x0000 }, { 209, 0x0080 }, { 210, 0x2f00 }, { 215, 0x0000 }, { 215, 0x0000 }, /* 0x0300 */ { 215, 0x0000 }, { 215, 0x0000 }, { 215, 0x0000 }, { 215, 0x0000 }, { 215, 0x0000 }, { 215, 0x0000 }, { 215, 0x0000 }, { 215, 0x0000 }, { 215, 0xd770 }, { 224, 0x0001 }, { 225, 0xfc00 }, { 231, 0x0001 }, { 232, 0x7c04 }, { 238, 0x0000 }, { 238, 0x0000 }, { 238, 0x0000 }, /* 0x0400 */ { 238, 0xdffc }, { 251, 0x0000 }, { 251, 0x0000 }, { 251, 0x0000 }, { 251, 0x0000 }, { 251, 0xdffc }, }; static const Summary16 jisx0212_uni2indx_page21[3] = { /* 0x2100 */ { 264, 0x0000 }, { 264, 0x0040 }, { 265, 0x0004 }, }; static const Summary16 jisx0212_uni2indx_page4e[1307] = { /* 0x4e00 */ { 266, 0x1034 }, { 270, 0x8004 }, { 272, 0xc918 }, { 278, 0x0021 }, { 280, 0x0093 }, { 284, 0x1402 }, { 287, 0x0308 }, { 290, 0x8230 }, { 294, 0x2000 }, { 295, 0x20c0 }, { 298, 0x8000 }, { 299, 0x0200 }, { 300, 0x0008 }, { 301, 0x0c01 }, { 304, 0x8107 }, { 309, 0xe02a }, /* 0x4f00 */ { 315, 0x190d }, { 321, 0x02e4 }, { 326, 0x4000 }, { 327, 0x4aaa }, { 334, 0x1b05 }, { 340, 0x8154 }, { 345, 0x5409 }, { 350, 0x6782 }, { 357, 0x5636 }, { 365, 0xc69d }, { 374, 0x0000 }, { 374, 0x7a84 }, { 381, 0xbb63 }, { 391, 0x1004 }, { 393, 0x0005 }, { 395, 0xb005 }, /* 0x5000 */ { 400, 0x5493 }, { 407, 0x7989 }, { 415, 0x4084 }, { 418, 0x082d }, { 423, 0x5467 }, { 431, 0x828e }, { 437, 0x24cd }, { 444, 0x0003 }, { 446, 0xc45a }, { 453, 0xd85d }, { 462, 0x8407 }, { 467, 0x2601 }, { 471, 0x5099 }, { 477, 0xb119 }, { 484, 0x8354 }, { 490, 0x4446 }, /* 0x5100 */ { 495, 0x79c8 }, { 503, 0x7a81 }, { 510, 0xb188 }, { 516, 0x033a }, { 522, 0x8404 }, { 525, 0x81a8 }, { 530, 0x0050 }, { 532, 0x4000 }, { 533, 0x4818 }, { 537, 0x2100 }, { 539, 0x200a }, { 542, 0xd500 }, { 547, 0x8104 }, { 550, 0x412e }, { 556, 0x4024 }, { 559, 0x009c }, /* 0x5200 */ { 563, 0x0026 }, { 566, 0x016c }, { 571, 0x0104 }, { 573, 0x1026 }, { 577, 0x0220 }, { 579, 0x95a0 }, { 585, 0x4043 }, { 589, 0x0380 }, { 592, 0x1425 }, { 597, 0x15e8 }, { 604, 0x80f0 }, { 609, 0x2dc1 }, { 616, 0x9151 }, { 622, 0x1852 }, { 627, 0x1722 }, { 633, 0x00d3 }, /* 0x5300 */ { 638, 0x1c09 }, { 643, 0xd90a }, { 650, 0x3ba0 }, { 657, 0x7025 }, { 663, 0x1804 }, { 666, 0x0a00 }, { 668, 0x302a }, { 673, 0x4204 }, { 676, 0x4188 }, { 680, 0x2218 }, { 684, 0x8c12 }, { 689, 0x25b4 }, { 696, 0x8021 }, { 699, 0x642c }, { 705, 0x00c1 }, { 708, 0x0020 }, /* 0x5400 */ { 709, 0x0004 }, { 710, 0x0408 }, { 712, 0x8582 }, { 717, 0x0032 }, { 720, 0xa098 }, { 725, 0x4000 }, { 726, 0x6ad4 }, { 734, 0x8010 }, { 736, 0x232a }, { 742, 0x9062 }, { 747, 0x66c2 }, { 754, 0x8e82 }, { 760, 0x6440 }, { 764, 0x0000 }, { 764, 0x9401 }, { 768, 0xd040 }, /* 0x5500 */ { 772, 0x7323 }, { 780, 0x0020 }, { 781, 0x0c00 }, { 783, 0x3864 }, { 789, 0x2682 }, { 794, 0x4d03 }, { 800, 0x0053 }, { 804, 0x8000 }, { 805, 0xc146 }, { 811, 0x009e }, { 816, 0x2018 }, { 819, 0x8004 }, { 821, 0x5a4a }, { 828, 0x498e }, { 835, 0x0204 }, { 837, 0x8040 }, /* 0x5600 */ { 839, 0xe520 }, { 845, 0x0207 }, { 849, 0x1000 }, { 850, 0xbaa9 }, { 859, 0xaa5b }, { 868, 0x4010 }, { 870, 0xa24f }, { 878, 0x0026 }, { 881, 0x1930 }, { 886, 0xe620 }, { 892, 0x3bc0 }, { 899, 0x408a }, { 903, 0xbe20 }, { 910, 0xb201 }, { 915, 0x29f2 }, { 923, 0x00c2 }, /* 0x5700 */ { 926, 0x1486 }, { 931, 0x2c22 }, { 936, 0xd63d }, { 946, 0xe018 }, { 951, 0x3060 }, { 955, 0x0004 }, { 956, 0xe9a4 }, { 964, 0x5ebb }, { 975, 0x100a }, { 978, 0xf6b0 }, { 987, 0x1382 }, { 992, 0x2100 }, { 994, 0x9180 }, { 998, 0x6020 }, { 1001, 0x22d2 }, { 1007, 0xe161 }, /* 0x5800 */ { 1014, 0x3318 }, { 1020, 0xc800 }, { 1023, 0x20c1 }, { 1027, 0x8204 }, { 1030, 0xb200 }, { 1034, 0x8021 }, { 1037, 0x0192 }, { 1041, 0x9100 }, { 1044, 0xb783 }, { 1053, 0x2051 }, { 1057, 0x0247 }, { 1062, 0x1006 }, { 1065, 0x6114 }, { 1070, 0x2455 }, { 1076, 0x0206 }, { 1079, 0x0008 }, /* 0x5900 */ { 1080, 0x1860 }, { 1084, 0x201c }, { 1088, 0x811a }, { 1093, 0x8069 }, { 1098, 0x0048 }, { 1100, 0xea0c }, { 1107, 0xa80a }, { 1112, 0x1a64 }, { 1118, 0x5800 }, { 1121, 0x80a4 }, { 1125, 0xe090 }, { 1130, 0x1489 }, { 1135, 0x251a }, { 1141, 0xe004 }, { 1145, 0xc098 }, { 1150, 0x0096 }, /* 0x5a00 */ { 1154, 0x7011 }, { 1159, 0x400c }, { 1162, 0x2598 }, { 1168, 0x0001 }, { 1169, 0x11b0 }, { 1174, 0x4021 }, { 1177, 0x20a8 }, { 1181, 0x4c80 }, { 1185, 0x0800 }, { 1186, 0xd249 }, { 1193, 0x1085 }, { 1197, 0x8d2e }, { 1205, 0x8150 }, { 1209, 0x1400 }, { 1211, 0x4421 }, { 1215, 0x2060 }, /* 0x5b00 */ { 1218, 0x0103 }, { 1221, 0x2a80 }, { 1225, 0x2022 }, { 1228, 0x0110 }, { 1230, 0x1802 }, { 1233, 0x4044 }, { 1236, 0xc100 }, { 1239, 0xf000 }, { 1243, 0x4452 }, { 1248, 0x005b }, { 1253, 0xb300 }, { 1258, 0x1486 }, { 1263, 0xa003 }, { 1267, 0x07c0 }, { 1272, 0x8001 }, { 1274, 0x2012 }, /* 0x5c00 */ { 1277, 0x1000 }, { 1278, 0xc080 }, { 1281, 0x5a48 }, { 1287, 0x0065 }, { 1291, 0x0000 }, { 1291, 0x1600 }, { 1294, 0x238c }, { 1300, 0x3c31 }, { 1307, 0x8580 }, { 1311, 0xa004 }, { 1314, 0x044d }, { 1319, 0x0434 }, { 1323, 0x0a00 }, { 1325, 0x2084 }, { 1328, 0x4000 }, { 1329, 0x0016 }, /* 0x5d00 */ { 1332, 0x2042 }, { 1335, 0x0004 }, { 1336, 0x08d8 }, { 1341, 0xa212 }, { 1346, 0x054c }, { 1351, 0x8222 }, { 1355, 0x2417 }, { 1361, 0xc601 }, { 1366, 0x050a }, { 1370, 0x8a3c }, { 1377, 0x0881 }, { 1380, 0x0315 }, { 1385, 0x4888 }, { 1389, 0x0301 }, { 1392, 0x0211 }, { 1395, 0x0300 }, /* 0x5e00 */ { 1397, 0x2081 }, { 1400, 0x8134 }, { 1405, 0x4101 }, { 1408, 0x4024 }, { 1411, 0x0a00 }, { 1413, 0x5943 }, { 1420, 0x7d00 }, { 1426, 0x0001 }, { 1427, 0x4801 }, { 1430, 0x0000 }, { 1430, 0x1534 }, { 1436, 0xe00a }, { 1441, 0x5840 }, { 1445, 0x5036 }, { 1451, 0x0820 }, { 1453, 0x0000 }, /* 0x5f00 */ { 1453, 0x41c4 }, { 1458, 0x3200 }, { 1461, 0x591e }, { 1469, 0xa851 }, { 1475, 0x20b1 }, { 1480, 0x0911 }, { 1484, 0x8099 }, { 1489, 0x6534 }, { 1496, 0xa200 }, { 1499, 0x3040 }, { 1502, 0x9894 }, { 1508, 0x0103 }, { 1511, 0x0b90 }, { 1516, 0x401f }, { 1522, 0xf706 }, { 1531, 0x144c }, /* 0x6000 */ { 1536, 0x2480 }, { 1539, 0x8598 }, { 1545, 0x2010 }, { 1547, 0x0028 }, { 1549, 0x1381 }, { 1554, 0x20d2 }, { 1559, 0x0082 }, { 1561, 0xc002 }, { 1564, 0x4544 }, { 1569, 0x612a }, { 1575, 0x0134 }, { 1579, 0x4883 }, { 1584, 0xcf14 }, { 1592, 0x6a30 }, { 1598, 0x0024 }, { 1600, 0x3124 }, /* 0x6100 */ { 1605, 0x1484 }, { 1609, 0x52df }, { 1619, 0x0c04 }, { 1622, 0x02e3 }, { 1628, 0x0262 }, { 1632, 0x4000 }, { 1633, 0x1001 }, { 1635, 0x9904 }, { 1640, 0x281b }, { 1646, 0xb18c }, { 1653, 0x2521 }, { 1658, 0x1300 }, { 1661, 0xc007 }, { 1666, 0xf020 }, { 1671, 0xb2a6 }, { 1679, 0x0000 }, /* 0x6200 */ { 1679, 0x009a }, { 1683, 0x1028 }, { 1686, 0x0a8d }, { 1692, 0x2200 }, { 1694, 0x105c }, { 1699, 0x1457 }, { 1706, 0xa010 }, { 1709, 0x2408 }, { 1712, 0xe000 }, { 1715, 0x0001 }, { 1716, 0x0140 }, { 1718, 0xc4c8 }, { 1724, 0x4010 }, { 1726, 0x0460 }, { 1729, 0x0400 }, { 1730, 0x3014 }, /* 0x6300 */ { 1734, 0x2c18 }, { 1739, 0x0149 }, { 1743, 0x2600 }, { 1746, 0x1260 }, { 1750, 0x4c5e }, { 1758, 0x091c }, { 1763, 0x3060 }, { 1767, 0xb132 }, { 1774, 0x0494 }, { 1778, 0x4631 }, { 1784, 0xe050 }, { 1789, 0x2000 }, { 1790, 0x4122 }, { 1794, 0x103a }, { 1799, 0x1421 }, { 1803, 0x032c }, /* 0x6400 */ { 1808, 0x0600 }, { 1810, 0x4115 }, { 1815, 0x8635 }, { 1822, 0xa021 }, { 1826, 0x8800 }, { 1828, 0xbc1e }, { 1837, 0x200b }, { 1841, 0x2818 }, { 1845, 0x80a0 }, { 1848, 0xab03 }, { 1855, 0x114a }, { 1860, 0xe008 }, { 1864, 0x5e10 }, { 1870, 0x00a3 }, { 1874, 0x2630 }, { 1879, 0x88a1 }, /* 0x6500 */ { 1884, 0x8712 }, { 1890, 0xca58 }, { 1897, 0x4244 }, { 1901, 0x3402 }, { 1905, 0x0288 }, { 1908, 0x8015 }, { 1912, 0x0881 }, { 1915, 0x2400 }, { 1917, 0x0422 }, { 1920, 0x2124 }, { 1924, 0x4049 }, { 1928, 0x801c }, { 1932, 0x4304 }, { 1936, 0x8151 }, { 1941, 0x0000 }, { 1941, 0xc235 }, /* 0x6600 */ { 1948, 0x2311 }, { 1953, 0x6066 }, { 1959, 0x5e5e }, { 1969, 0x028b }, { 1974, 0x5461 }, { 1980, 0x1b82 }, { 1986, 0x1c03 }, { 1991, 0xdba8 }, { 2000, 0x3801 }, { 2004, 0x9e05 }, { 2011, 0x2011 }, { 2014, 0x8826 }, { 2019, 0xd10d }, { 2026, 0x8810 }, { 2029, 0x5900 }, { 2033, 0x0c00 }, /* 0x6700 */ { 2035, 0x40a0 }, { 2038, 0x1208 }, { 2041, 0x0005 }, { 2043, 0x4008 }, { 2045, 0x11a0 }, { 2049, 0x2030 }, { 2052, 0x5040 }, { 2055, 0x0850 }, { 2058, 0xc012 }, { 2062, 0x0b4a }, { 2068, 0x0000 }, { 2068, 0x3827 }, { 2075, 0x032d }, { 2081, 0x1284 }, { 2085, 0x0042 }, { 2087, 0x02c5 }, /* 0x6800 */ { 2092, 0x0000 }, { 2092, 0xa210 }, { 2096, 0xb180 }, { 2101, 0x880b }, { 2106, 0x1430 }, { 2110, 0x09a4 }, { 2115, 0xc800 }, { 2118, 0x1e27 }, { 2126, 0x0154 }, { 2130, 0x1540 }, { 2134, 0x462a }, { 2140, 0x0804 }, { 2142, 0x9120 }, { 2146, 0x324b }, { 2153, 0x3d20 }, { 2159, 0x3863 }, /* 0x6900 */ { 2166, 0x0640 }, { 2169, 0x00cb }, { 2174, 0x0000 }, { 2174, 0x092a }, { 2179, 0x4224 }, { 2183, 0x0880 }, { 2185, 0x1378 }, { 2192, 0x8c07 }, { 2198, 0x2001 }, { 2200, 0x0144 }, { 2203, 0xa962 }, { 2210, 0x1580 }, { 2214, 0x0120 }, { 2216, 0x00c2 }, { 2219, 0xc024 }, { 2223, 0x402a }, /* 0x6a00 */ { 2227, 0x800b }, { 2231, 0x2422 }, { 2235, 0x0111 }, { 2238, 0xc895 }, { 2245, 0x4660 }, { 2250, 0x0867 }, { 2256, 0x0490 }, { 2259, 0x400a }, { 2262, 0x0aca }, { 2268, 0xe802 }, { 2273, 0x8820 }, { 2276, 0xe013 }, { 2282, 0x1340 }, { 2286, 0x3071 }, { 2292, 0x1090 }, { 2295, 0x3007 }, /* 0x6b00 */ { 2300, 0x82cc }, { 2306, 0x4883 }, { 2311, 0x9910 }, { 2316, 0x8860 }, { 2320, 0x2440 }, { 2323, 0x2144 }, { 2327, 0x4881 }, { 2331, 0x6021 }, { 2335, 0x0024 }, { 2337, 0x8880 }, { 2340, 0x730d }, { 2348, 0x6301 }, { 2353, 0x1218 }, { 2357, 0x0440 }, { 2359, 0x40ca }, { 2364, 0x8282 }, /* 0x6c00 */ { 2368, 0x6234 }, { 2374, 0x8205 }, { 2378, 0x51c0 }, { 2383, 0x8c68 }, { 2389, 0xac00 }, { 2393, 0x1a14 }, { 2398, 0xa880 }, { 2402, 0x0b50 }, { 2407, 0x02e0 }, { 2411, 0x91b0 }, { 2417, 0x0000 }, { 2417, 0x0015 }, { 2420, 0xa044 }, { 2424, 0x1457 }, { 2431, 0x5a81 }, { 2437, 0x0014 }, /* 0x6d00 */ { 2439, 0xc490 }, { 2444, 0x040a }, { 2447, 0xc1c0 }, { 2452, 0x9202 }, { 2456, 0x0000 }, { 2456, 0xc080 }, { 2459, 0x80a2 }, { 2463, 0x1001 }, { 2465, 0x0084 }, { 2467, 0x01d6 }, { 2473, 0x1400 }, { 2475, 0xa290 }, { 2480, 0xc510 }, { 2485, 0xa840 }, { 2489, 0x8225 }, { 2494, 0x1051 }, /* 0x6e00 */ { 2498, 0x0011 }, { 2500, 0x4000 }, { 2501, 0x0084 }, { 2503, 0x1a44 }, { 2508, 0x8b30 }, { 2514, 0x709e }, { 2522, 0x010c }, { 2525, 0x2808 }, { 2528, 0x2000 }, { 2529, 0x0208 }, { 2531, 0x6081 }, { 2535, 0x880a }, { 2539, 0xe58b }, { 2548, 0x0000 }, { 2548, 0x6800 }, { 2551, 0x2a00 }, /* 0x6f00 */ { 2554, 0x3510 }, { 2559, 0x0d40 }, { 2563, 0xa640 }, { 2568, 0x1849 }, { 2573, 0x8000 }, { 2574, 0x668e }, { 2582, 0x1106 }, { 2586, 0x6000 }, { 2588, 0x3988 }, { 2594, 0x845d }, { 2601, 0xc1e1 }, { 2608, 0x1061 }, { 2612, 0x05a0 }, { 2616, 0x4400 }, { 2618, 0x0300 }, { 2620, 0x3221 }, /* 0x7000 */ { 2625, 0x20e1 }, { 2630, 0x0080 }, { 2631, 0x8009 }, { 2634, 0x1290 }, { 2638, 0x4f18 }, { 2645, 0x6030 }, { 2649, 0x5030 }, { 2653, 0x4060 }, { 2656, 0x0062 }, { 2659, 0x09f0 }, { 2665, 0x0810 }, { 2667, 0x0093 }, { 2671, 0x0400 }, { 2672, 0x117a }, { 2679, 0x0010 }, { 2680, 0x0400 }, /* 0x7100 */ { 2681, 0x98f8 }, { 2689, 0x4000 }, { 2690, 0xa801 }, { 2694, 0x0103 }, { 2697, 0x0ce2 }, { 2703, 0x5485 }, { 2709, 0x0101 }, { 2711, 0x0200 }, { 2712, 0x10a1 }, { 2716, 0x0c04 }, { 2719, 0x8005 }, { 2722, 0x840d }, { 2727, 0x1813 }, { 2732, 0x1648 }, { 2737, 0x0000 }, { 2737, 0x4100 }, /* 0x7200 */ { 2739, 0x0381 }, { 2743, 0xa488 }, { 2748, 0x8810 }, { 2751, 0x0310 }, { 2754, 0xc02e }, { 2760, 0x5469 }, { 2767, 0xc909 }, { 2773, 0x9982 }, { 2779, 0x6210 }, { 2783, 0x0808 }, { 2785, 0x6100 }, { 2788, 0x4012 }, { 2791, 0x1282 }, { 2795, 0x8160 }, { 2799, 0x0020 }, { 2800, 0x4c18 }, /* 0x7300 */ { 2805, 0x28b4 }, { 2811, 0x430c }, { 2816, 0x1194 }, { 2821, 0x2c26 }, { 2827, 0x2008 }, { 2829, 0xe145 }, { 2836, 0xdac1 }, { 2844, 0x1282 }, { 2848, 0x406b }, { 2854, 0xd1a9 }, { 2862, 0x2c65 }, { 2869, 0xb2a0 }, { 2875, 0x9a60 }, { 2881, 0x224c }, { 2886, 0x02ca }, { 2891, 0xaeb0 }, /* 0x7400 */ { 2899, 0x0493 }, { 2904, 0x0c02 }, { 2907, 0xff50 }, { 2917, 0x0203 }, { 2920, 0x28d9 }, { 2927, 0x2086 }, { 2931, 0x69c4 }, { 2938, 0x0006 }, { 2940, 0x82e3 }, { 2947, 0x9707 }, { 2955, 0xcf4b }, { 2965, 0x8a26 }, { 2971, 0x1300 }, { 2974, 0xcd09 }, { 2981, 0x8d10 }, { 2986, 0x9c10 }, /* 0x7500 */ { 2991, 0x0040 }, { 2992, 0x00c4 }, { 2995, 0x8693 }, { 3002, 0xe240 }, { 3007, 0x4189 }, { 3012, 0xc085 }, { 3017, 0x8002 }, { 3019, 0x7e02 }, { 3026, 0x0022 }, { 3028, 0x122d }, { 3034, 0x0014 }, { 3036, 0x8410 }, { 3039, 0xd053 }, { 3046, 0x9080 }, { 3049, 0xd093 }, { 3056, 0x0202 }, /* 0x7600 */ { 3058, 0x959d }, { 3067, 0x7a6c }, { 3076, 0x2268 }, { 3081, 0x172c }, { 3088, 0x0e3b }, { 3096, 0x8220 }, { 3099, 0xe030 }, { 3104, 0x0012 }, { 3106, 0x3022 }, { 3110, 0xb820 }, { 3115, 0x25fd }, { 3125, 0x2000 }, { 3126, 0x5a22 }, { 3132, 0x0210 }, { 3134, 0x1141 }, { 3138, 0x1243 }, /* 0x7700 */ { 3143, 0x4441 }, { 3147, 0x16b4 }, { 3154, 0xe104 }, { 3159, 0x6270 }, { 3165, 0xe464 }, { 3172, 0xd0c4 }, { 3178, 0x1495 }, { 3184, 0x241d }, { 3190, 0x3011 }, { 3194, 0x8470 }, { 3199, 0xc484 }, { 3204, 0x4022 }, { 3207, 0x0208 }, { 3209, 0xc226 }, { 3215, 0x1451 }, { 3220, 0x0913 }, /* 0x7800 */ { 3225, 0x6260 }, { 3230, 0x2002 }, { 3232, 0x600e }, { 3237, 0x00a1 }, { 3240, 0x5198 }, { 3246, 0x5004 }, { 3249, 0x451b }, { 3256, 0x4400 }, { 3258, 0x8400 }, { 3260, 0xe110 }, { 3265, 0x3112 }, { 3270, 0xa80f }, { 3277, 0x5380 }, { 3282, 0x886c }, { 3288, 0x0453 }, { 3293, 0x8ccc }, /* 0x7900 */ { 3300, 0x1041 }, { 3303, 0xd401 }, { 3308, 0x22a1 }, { 3313, 0xa832 }, { 3319, 0x8c70 }, { 3325, 0x1912 }, { 3330, 0x0a80 }, { 3333, 0x5a04 }, { 3338, 0x1800 }, { 3340, 0x197a }, { 3348, 0x8b02 }, { 3353, 0x0912 }, { 3357, 0x8594 }, { 3363, 0x6450 }, { 3368, 0x2c25 }, { 3374, 0x1102 }, /* 0x7a00 */ { 3377, 0x168c }, { 3383, 0x4822 }, { 3387, 0xa882 }, { 3392, 0x0731 }, { 3398, 0x11b0 }, { 3403, 0xb260 }, { 3409, 0x24a1 }, { 3414, 0x4120 }, { 3417, 0x0c65 }, { 3423, 0x4013 }, { 3427, 0x1009 }, { 3430, 0x1a28 }, { 3435, 0x5240 }, { 3439, 0x0802 }, { 3441, 0x1b00 }, { 3445, 0x6812 }, /* 0x7b00 */ { 3450, 0x0080 }, { 3451, 0x8010 }, { 3453, 0xee88 }, { 3461, 0xa013 }, { 3466, 0x4083 }, { 3470, 0x0020 }, { 3471, 0xa651 }, { 3478, 0x008c }, { 3481, 0x4210 }, { 3484, 0x4843 }, { 3489, 0x9021 }, { 3493, 0x3c65 }, { 3501, 0x0524 }, { 3505, 0x0ed0 }, { 3511, 0x0500 }, { 3513, 0x5734 }, /* 0x7c00 */ { 3521, 0xda5e }, { 3531, 0x0a00 }, { 3533, 0x1161 }, { 3538, 0x065a }, { 3544, 0x0440 }, { 3546, 0x7e2e }, { 3556, 0x628a }, { 3562, 0x3205 }, { 3567, 0x80c0 }, { 3570, 0x4010 }, { 3572, 0x0041 }, { 3574, 0x9cc1 }, { 3581, 0xa390 }, { 3587, 0x26b8 }, { 3594, 0x0a40 }, { 3597, 0x0020 }, /* 0x7d00 */ { 3598, 0x8388 }, { 3603, 0x604e }, { 3609, 0x2448 }, { 3613, 0x7002 }, { 3617, 0x2183 }, { 3622, 0x368a }, { 3629, 0x04a0 }, { 3632, 0x8d01 }, { 3637, 0x396e }, { 3646, 0x60c2 }, { 3651, 0x04c0 }, { 3654, 0x02c8 }, { 3658, 0x707c }, { 3666, 0x0280 }, { 3668, 0x2c64 }, { 3674, 0x0662 }, /* 0x7e00 */ { 3679, 0x0101 }, { 3681, 0x30a3 }, { 3687, 0xb181 }, { 3693, 0x8048 }, { 3696, 0x40b0 }, { 3700, 0x8105 }, { 3704, 0xc826 }, { 3710, 0x4108 }, { 3713, 0x24c2 }, { 3718, 0x6522 }, { 3724, 0x0000 }, { 3724, 0x0000 }, { 3724, 0x0000 }, { 3724, 0x0000 }, { 3724, 0x0000 }, { 3724, 0x0000 }, /* 0x7f00 */ { 3724, 0x0000 }, { 3724, 0x0000 }, { 3724, 0x0000 }, { 3724, 0xf800 }, { 3729, 0x8098 }, { 3733, 0x380c }, { 3738, 0x207a }, { 3744, 0xe002 }, { 3748, 0xa801 }, { 3752, 0x10c3 }, { 3757, 0x2446 }, { 3762, 0x9010 }, { 3765, 0xc109 }, { 3770, 0x8800 }, { 3772, 0xd128 }, { 3778, 0xe404 }, /* 0x8000 */ { 3783, 0xe580 }, { 3789, 0xe05a }, { 3796, 0x5051 }, { 3801, 0x56b1 }, { 3809, 0x0011 }, { 3811, 0x0000 }, { 3811, 0x2051 }, { 3815, 0x0022 }, { 3817, 0x4102 }, { 3820, 0x5000 }, { 3822, 0x08c0 }, { 3825, 0x0300 }, { 3827, 0xa100 }, { 3830, 0x01b4 }, { 3835, 0x6001 }, { 3838, 0x464d }, /* 0x8100 */ { 3845, 0x0808 }, { 3847, 0x51c0 }, { 3852, 0x1091 }, { 3856, 0x1421 }, { 3860, 0x14a0 }, { 3864, 0x0084 }, { 3866, 0xa383 }, { 3873, 0x0080 }, { 3874, 0x4872 }, { 3880, 0x4941 }, { 3885, 0x4004 }, { 3887, 0x0814 }, { 3890, 0xcc28 }, { 3896, 0x68a0 }, { 3901, 0x1812 }, { 3905, 0xa367 }, /* 0x8200 */ { 3914, 0x8009 }, { 3917, 0x2618 }, { 3922, 0x0106 }, { 3925, 0x0414 }, { 3928, 0xc878 }, { 3935, 0x1042 }, { 3938, 0x2089 }, { 3942, 0xa810 }, { 3946, 0x469b }, { 3954, 0x0d52 }, { 3960, 0x479b }, { 3969, 0xd495 }, { 3977, 0x0040 }, { 3978, 0x0421 }, { 3981, 0xa515 }, { 3988, 0x60c0 }, /* 0x8300 */ { 3992, 0x0d83 }, { 3998, 0xe800 }, { 4002, 0x7006 }, { 4007, 0x3489 }, { 4013, 0x609c }, { 4019, 0x00fa }, { 4025, 0x0000 }, { 4025, 0xa101 }, { 4029, 0x2055 }, { 4034, 0x3b34 }, { 4042, 0x32c0 }, { 4047, 0xc000 }, { 4049, 0x8281 }, { 4053, 0x2013 }, { 4057, 0x0500 }, { 4059, 0x1340 }, /* 0x8400 */ { 4063, 0x8442 }, { 4067, 0x0222 }, { 4070, 0x8000 }, { 4071, 0x0200 }, { 4072, 0xa5a0 }, { 4078, 0x1746 }, { 4085, 0x04b1 }, { 4090, 0x3159 }, { 4097, 0x0022 }, { 4099, 0x402c }, { 4103, 0x8740 }, { 4108, 0x6412 }, { 4113, 0x9185 }, { 4119, 0x1008 }, { 4121, 0x8480 }, { 4124, 0x2c87 }, /* 0x8500 */ { 4131, 0x508c }, { 4136, 0x5001 }, { 4139, 0x8cbc }, { 4147, 0x805c }, { 4152, 0x8040 }, { 4154, 0xf24f }, { 4164, 0x8817 }, { 4170, 0xae00 }, { 4175, 0x9a62 }, { 4182, 0xa108 }, { 4186, 0x20a5 }, { 4191, 0xf1d0 }, { 4199, 0x4c84 }, { 4204, 0x8500 }, { 4207, 0x2141 }, { 4211, 0x9048 }, /* 0x8600 */ { 4215, 0x6031 }, { 4220, 0x4b07 }, { 4227, 0x0282 }, { 4230, 0x3540 }, { 4235, 0x0047 }, { 4239, 0x23cc }, { 4246, 0x921f }, { 4254, 0x04e0 }, { 4258, 0x2100 }, { 4260, 0x1542 }, { 4265, 0x21c2 }, { 4270, 0x83ba }, { 4278, 0x002b }, { 4282, 0x14a6 }, { 4288, 0x00a9 }, { 4292, 0x3400 }, /* 0x8700 */ { 4295, 0xc8b0 }, { 4301, 0xc219 }, { 4307, 0xc10a }, { 4312, 0x7606 }, { 4319, 0x2029 }, { 4323, 0x2100 }, { 4325, 0x8032 }, { 4329, 0x0806 }, { 4332, 0x1bf8 }, { 4341, 0x43a9 }, { 4348, 0x7089 }, { 4354, 0xc022 }, { 4358, 0x4702 }, { 4363, 0x9660 }, { 4369, 0x2c1c }, { 4375, 0x850a }, /* 0x8800 */ { 4380, 0x0e4a }, { 4386, 0xdf1d }, { 4397, 0x6100 }, { 4400, 0x1425 }, { 4405, 0x4f2a }, { 4413, 0x9562 }, { 4420, 0x0211 }, { 4423, 0x0a02 }, { 4426, 0x0001 }, { 4427, 0x9d00 }, { 4432, 0x0501 }, { 4435, 0x6400 }, { 4438, 0x7c01 }, { 4444, 0x480e }, { 4449, 0x8080 }, { 4451, 0x00a3 }, /* 0x8900 */ { 4455, 0xe042 }, { 4460, 0x1760 }, { 4466, 0x01c1 }, { 4470, 0x4627 }, { 4477, 0x8265 }, { 4483, 0x1c84 }, { 4488, 0x480e }, { 4493, 0x3c29 }, { 4500, 0x2200 }, { 4502, 0x9831 }, { 4508, 0x0021 }, { 4510, 0x10f1 }, { 4516, 0x0000 }, { 4516, 0x01f0 }, { 4521, 0x2a20 }, { 4525, 0xa24a }, /* 0x8a00 */ { 4531, 0x80b0 }, { 4535, 0x4036 }, { 4540, 0x9855 }, { 4547, 0x60a0 }, { 4551, 0x62a9 }, { 4558, 0x31c8 }, { 4564, 0x00a2 }, { 4567, 0xcee0 }, { 4575, 0x8849 }, { 4580, 0x82c5 }, { 4586, 0xc280 }, { 4590, 0x48c8 }, { 4595, 0x0748 }, { 4600, 0xa0ba }, { 4607, 0x1000 }, { 4608, 0x9071 }, /* 0x8b00 */ { 4614, 0x0c60 }, { 4618, 0xd002 }, { 4622, 0x2000 }, { 4623, 0x1081 }, { 4626, 0x217c }, { 4633, 0x421c }, { 4638, 0x2008 }, { 4640, 0x5340 }, { 4645, 0xa832 }, { 4651, 0xd030 }, { 4656, 0x0000 }, { 4656, 0x0000 }, { 4656, 0x0000 }, { 4656, 0x0000 }, { 4656, 0x0000 }, { 4656, 0x0000 }, /* 0x8c00 */ { 4656, 0x0000 }, { 4656, 0x0000 }, { 4656, 0x0000 }, { 4656, 0x6300 }, { 4660, 0x8aa0 }, { 4665, 0x2b9a }, { 4673, 0x2358 }, { 4679, 0x4868 }, { 4684, 0x08c0 }, { 4687, 0x1a0d }, { 4693, 0x0010 }, { 4694, 0x0600 }, { 4696, 0x8a60 }, { 4701, 0x2260 }, { 4705, 0x9102 }, { 4709, 0xc1a5 }, /* 0x8d00 */ { 4716, 0x020a }, { 4719, 0x0884 }, { 4722, 0x0000 }, { 4722, 0x0000 }, { 4722, 0x0000 }, { 4722, 0x0000 }, { 4722, 0x5220 }, { 4726, 0x8000 }, { 4727, 0x2114 }, { 4731, 0xc023 }, { 4736, 0x9841 }, { 4741, 0x1aa4 }, { 4747, 0x45e1 }, { 4754, 0x02b2 }, { 4759, 0x10b0 }, { 4763, 0x2017 }, /* 0x8e00 */ { 4768, 0x0872 }, { 4773, 0x0052 }, { 4776, 0x00cf }, { 4782, 0x23ca }, { 4789, 0xe803 }, { 4795, 0x7810 }, { 4800, 0xb206 }, { 4806, 0x0e03 }, { 4811, 0x020c }, { 4814, 0x6c25 }, { 4821, 0x6284 }, { 4826, 0x0c28 }, { 4830, 0x809b }, { 4836, 0x1012 }, { 4839, 0x6100 }, { 4842, 0x0683 }, /* 0x8f00 */ { 4847, 0x8185 }, { 4852, 0x41c1 }, { 4857, 0x71ab }, { 4866, 0x04f0 }, { 4871, 0x808b }, { 4876, 0x613e }, { 4884, 0x0020 }, { 4885, 0x0000 }, { 4885, 0x0000 }, { 4885, 0x2000 }, { 4886, 0x0073 }, { 4891, 0x4160 }, { 4895, 0x2c43 }, { 4901, 0x002d }, { 4905, 0x4119 }, { 4910, 0x4862 }, /* 0x9000 */ { 4915, 0x1114 }, { 4919, 0x0900 }, { 4921, 0xb700 }, { 4927, 0x8098 }, { 4931, 0x1018 }, { 4934, 0x2800 }, { 4936, 0x10c4 }, { 4940, 0x0211 }, { 4943, 0x5920 }, { 4948, 0x0ba1 }, { 4954, 0x0027 }, { 4958, 0x605d }, { 4965, 0x11b8 }, { 4971, 0xb3a4 }, { 4979, 0x8820 }, { 4982, 0xc051 }, /* 0x9100 */ { 4987, 0x2171 }, { 4993, 0x55d1 }, { 5001, 0xc2ad }, { 5009, 0x36d2 }, { 5017, 0x8188 }, { 5021, 0x0e88 }, { 5026, 0x2092 }, { 5030, 0x0e10 }, { 5034, 0x446a }, { 5040, 0x413a }, { 5046, 0x7142 }, { 5052, 0xb84f }, { 5061, 0x002c }, { 5064, 0x4698 }, { 5070, 0xf630 }, { 5078, 0x2a83 }, /* 0x9200 */ { 5084, 0x16f3 }, { 5093, 0x314d }, { 5100, 0xc178 }, { 5107, 0x5769 }, { 5116, 0xe4cd }, { 5125, 0x3302 }, { 5130, 0xc3a3 }, { 5138, 0xbbe1 }, { 5148, 0x6700 }, { 5153, 0x8284 }, { 5157, 0x89b1 }, { 5164, 0xbd44 }, { 5172, 0x79ef }, { 5184, 0xb3a9 }, { 5193, 0x51ab }, { 5201, 0x8a01 }, /* 0x9300 */ { 5205, 0x2105 }, { 5209, 0xf032 }, { 5216, 0x06b2 }, { 5222, 0x00d8 }, { 5226, 0x0380 }, { 5229, 0x45a7 }, { 5237, 0xa6b0 }, { 5244, 0xa45b }, { 5252, 0xad07 }, { 5260, 0x4924 }, { 5265, 0x0b5a }, { 5272, 0x0470 }, { 5276, 0x3ef2 }, { 5286, 0xd208 }, { 5291, 0x00c4 }, { 5294, 0x2f80 }, /* 0x9400 */ { 5300, 0xe316 }, { 5308, 0x80e0 }, { 5312, 0xc000 }, { 5314, 0xa81e }, { 5321, 0x1528 }, { 5326, 0x9220 }, { 5330, 0xe90a }, { 5337, 0x0006 }, { 5339, 0x0018 }, { 5341, 0x0000 }, { 5341, 0x0000 }, { 5341, 0x0000 }, { 5341, 0x0000 }, { 5341, 0x0000 }, { 5341, 0x0000 }, { 5341, 0x0000 }, /* 0x9500 */ { 5341, 0x0000 }, { 5341, 0x0000 }, { 5341, 0x0000 }, { 5341, 0x0000 }, { 5341, 0x0000 }, { 5341, 0x0000 }, { 5341, 0x0000 }, { 5341, 0x4300 }, { 5344, 0x7110 }, { 5349, 0xe000 }, { 5352, 0x1a42 }, { 5357, 0xa450 }, { 5362, 0x0b40 }, { 5366, 0xe60f }, { 5375, 0x0051 }, { 5378, 0x0000 }, /* 0x9600 */ { 5378, 0x0000 }, { 5378, 0x6000 }, { 5380, 0x1074 }, { 5385, 0x378a }, { 5393, 0x0002 }, { 5394, 0x01d4 }, { 5399, 0x4002 }, { 5401, 0xd810 }, { 5406, 0x021e }, { 5411, 0xa442 }, { 5416, 0xc270 }, { 5422, 0x0408 }, { 5424, 0x0400 }, { 5425, 0xe504 }, { 5431, 0x8200 }, { 5433, 0x0402 }, /* 0x9700 */ { 5435, 0x022c }, { 5439, 0x2c00 }, { 5442, 0x010e }, { 5446, 0x000a }, { 5448, 0xc40a }, { 5453, 0x0da0 }, { 5458, 0x4488 }, { 5462, 0xa9c8 }, { 5469, 0x0201 }, { 5471, 0xc6e0 }, { 5478, 0x5004 }, { 5481, 0xd766 }, { 5491, 0x76b2 }, { 5500, 0x6b93 }, { 5509, 0x8013 }, { 5513, 0x0592 }, /* 0x9800 */ { 5518, 0x6480 }, { 5522, 0x5250 }, { 5527, 0xc869 }, { 5534, 0x402d }, { 5539, 0x0490 }, { 5542, 0x06ce }, { 5549, 0x146c }, { 5555, 0x0000 }, { 5555, 0x0000 }, { 5555, 0x0000 }, { 5555, 0x6800 }, { 5558, 0x8d91 }, { 5565, 0x1124 }, { 5569, 0x0000 }, { 5569, 0x04ea }, { 5575, 0x0048 }, /* 0x9900 */ { 5577, 0x0184 }, { 5580, 0x9ce2 }, { 5588, 0x08c4 }, { 5592, 0x1e3e }, { 5601, 0x61c3 }, { 5608, 0xdb10 }, { 5615, 0x0001 }, { 5616, 0x0000 }, { 5616, 0x0000 }, { 5616, 0xa800 }, { 5619, 0x0040 }, { 5620, 0xa627 }, { 5628, 0x0208 }, { 5630, 0x5618 }, { 5636, 0x1c80 }, { 5640, 0x6231 }, /* 0x9a00 */ { 5646, 0x181c }, { 5651, 0x4043 }, { 5655, 0x609d }, { 5662, 0x0168 }, { 5666, 0x5c92 }, { 5673, 0x2052 }, { 5677, 0x0000 }, { 5677, 0x0000 }, { 5677, 0x0000 }, { 5677, 0x0000 }, { 5677, 0xd400 }, { 5681, 0xca74 }, { 5689, 0x414a }, { 5694, 0x18e5 }, { 5701, 0x12b1 }, { 5707, 0xa62c }, /* 0x9b00 */ { 5714, 0x7b3f }, { 5726, 0x1a45 }, { 5732, 0x2841 }, { 5736, 0x26b8 }, { 5743, 0x1900 }, { 5746, 0x48e0 }, { 5751, 0x7d6a }, { 5761, 0x83a8 }, { 5767, 0xaef1 }, { 5777, 0x6411 }, { 5782, 0x12c0 }, { 5786, 0xd987 }, { 5795, 0x4182 }, { 5799, 0xa181 }, { 5804, 0x8ca0 }, { 5809, 0xa788 }, /* 0x9c00 */ { 5816, 0x8805 }, { 5820, 0x5742 }, { 5827, 0x07cc }, { 5834, 0x20e2 }, { 5839, 0xc63a }, { 5847, 0xf959 }, { 5857, 0x4f08 }, { 5863, 0x08a5 }, { 5868, 0x0000 }, { 5868, 0x0000 }, { 5868, 0x0000 }, { 5868, 0x0000 }, { 5868, 0x0000 }, { 5868, 0x0000 }, { 5868, 0x0040 }, { 5869, 0x0284 }, /* 0x9d00 */ { 5872, 0x0804 }, { 5874, 0x7182 }, { 5880, 0x8000 }, { 5881, 0x341d }, { 5888, 0x04ac }, { 5893, 0x8018 }, { 5896, 0x0e2c }, { 5902, 0x58c1 }, { 5908, 0x6458 }, { 5914, 0x01ec }, { 5920, 0x5402 }, { 5924, 0x9222 }, { 5929, 0x0688 }, { 5933, 0xc4f0 }, { 5940, 0x4aa1 }, { 5946, 0x4019 }, /* 0x9e00 */ { 5950, 0x4484 }, { 5954, 0x3267 }, { 5962, 0x0000 }, { 5962, 0x0000 }, { 5962, 0x0000 }, { 5962, 0x0000 }, { 5962, 0x0000 }, { 5962, 0x1c00 }, { 5965, 0xc0bd }, { 5973, 0x4940 }, { 5977, 0xd110 }, { 5982, 0x0039 }, { 5986, 0x0940 }, { 5989, 0x8020 }, { 5991, 0x7090 }, { 5996, 0x8127 }, /* 0x9f00 */ { 6002, 0x820c }, { 6006, 0x8ed7 }, { 6016, 0x8c44 }, { 6021, 0xb696 }, { 6030, 0x00fa }, { 6036, 0x65e8 }, { 6044, 0xe300 }, { 6049, 0x242b }, { 6055, 0x8000 }, { 6056, 0x40d7 }, { 6063, 0x002e }, }; static int jisx0212_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; if (n >= 2) { const Summary16 *summary = NULL; if (wc < 0x0460) summary = &jisx0212_uni2indx_page00[(wc>>4)]; else if (wc >= 0x2100 && wc < 0x2130) summary = &jisx0212_uni2indx_page21[(wc>>4)-0x210]; else if (wc >= 0x4e00 && wc < 0x9fb0) summary = &jisx0212_uni2indx_page4e[(wc>>4)-0x4e0]; if (summary) { unsigned short used = summary->used; unsigned int i = wc & 0x0f; if (used & ((unsigned short) 1 << i)) { unsigned short c; /* Keep in `used' only the bits 0..i-1. */ used &= ((unsigned short) 1 << i) - 1; /* Add `summary->indx' and the number of bits set in `used'. */ used = (used & 0x5555) + ((used & 0xaaaa) >> 1); used = (used & 0x3333) + ((used & 0xcccc) >> 2); used = (used & 0x0f0f) + ((used & 0xf0f0) >> 4); used = (used & 0x00ff) + (used >> 8); c = jisx0212_2charset[summary->indx + used]; r[0] = (c >> 8); r[1] = (c & 0xff); return 2; } } return RET_ILSEQ; } return RET_TOOSMALL; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/iso8859_15.h0000644000175000017500000000376615004135251020174 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_15.h,v 1.3 2000/11/29 17:40:31 dawes Exp $ */ /* * ISO-8859-15 */ #ifdef NEED_TOWC static const unsigned short iso8859_15_2uni[32] = { /* 0xa0 */ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0160, 0x00a7, 0x0161, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, /* 0xb0 */ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x017d, 0x00b5, 0x00b6, 0x00b7, 0x017e, 0x00b9, 0x00ba, 0x00bb, 0x0152, 0x0153, 0x0178, 0x00bf, }; static int iso8859_15_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c >= 0xa0 && c < 0xc0) *pwc = (ucs4_t) iso8859_15_2uni[c-0xa0]; else *pwc = (ucs4_t) c; return 1; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_15_page00[32] = { 0xa0, 0xa1, 0xa2, 0xa3, 0x00, 0xa5, 0x00, 0xa7, /* 0xa0-0xa7 */ 0x00, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */ 0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */ 0x00, 0xb9, 0xba, 0xbb, 0x00, 0x00, 0x00, 0xbf, /* 0xb8-0xbf */ }; static const unsigned char iso8859_15_page01[48] = { 0x00, 0x00, 0xbc, 0xbd, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0xa6, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0xbe, 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb8, 0x00, /* 0x78-0x7f */ }; static int iso8859_15_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00c0) c = iso8859_15_page00[wc-0x00a0]; else if (wc >= 0x00c0 && wc < 0x0100) c = wc; else if (wc >= 0x0150 && wc < 0x0180) c = iso8859_15_page01[wc-0x0150]; else if (wc == 0x20ac) c = 0xa4; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/jisx0208.h0000644000175000017500000044015115004135251020017 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/jisx0208.h,v 1.6 2003/05/27 22:26:31 tsi Exp $ */ /* * JISX0208.1990-0 */ #ifdef NEED_TOWC static const unsigned short jisx0208_2uni_page21[690] = { /* 0x21 */ 0x3000, 0x3001, 0x3002, 0xff0c, 0xff0e, 0x30fb, 0xff1a, 0xff1b, 0xff1f, 0xff01, 0x309b, 0x309c, 0x00b4, 0xff40, 0x00a8, 0xff3e, 0xffe3, 0xff3f, 0x30fd, 0x30fe, 0x309d, 0x309e, 0x3003, 0x4edd, 0x3005, 0x3006, 0x3007, 0x30fc, 0x2015, 0x2010, 0xff0f, 0xff3c, 0x301c, 0x2016, 0xff5c, 0x2026, 0x2025, 0x2018, 0x2019, 0x201c, 0x201d, 0xff08, 0xff09, 0x3014, 0x3015, 0xff3b, 0xff3d, 0xff5b, 0xff5d, 0x3008, 0x3009, 0x300a, 0x300b, 0x300c, 0x300d, 0x300e, 0x300f, 0x3010, 0x3011, 0xff0b, 0x2212, 0x00b1, 0x00d7, 0x00f7, 0xff1d, 0x2260, 0xff1c, 0xff1e, 0x2266, 0x2267, 0x221e, 0x2234, 0x2642, 0x2640, 0x00b0, 0x2032, 0x2033, 0x2103, 0xffe5, 0xff04, 0x00a2, 0x00a3, 0xff05, 0xff03, 0xff06, 0xff0a, 0xff20, 0x00a7, 0x2606, 0x2605, 0x25cb, 0x25cf, 0x25ce, 0x25c7, /* 0x22 */ 0x25c6, 0x25a1, 0x25a0, 0x25b3, 0x25b2, 0x25bd, 0x25bc, 0x203b, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x2208, 0x220b, 0x2286, 0x2287, 0x2282, 0x2283, 0x222a, 0x2229, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x2227, 0x2228, 0x00ac, 0x21d2, 0x21d4, 0x2200, 0x2203, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x2220, 0x22a5, 0x2312, 0x2202, 0x2207, 0x2261, 0x2252, 0x226a, 0x226b, 0x221a, 0x223d, 0x221d, 0x2235, 0x222b, 0x222c, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x212b, 0x2030, 0x266f, 0x266d, 0x266a, 0x2020, 0x2021, 0x00b6, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x25ef, /* 0x23 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xff10, 0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, 0xff18, 0xff19, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 0xff39, 0xff3a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, 0xff58, 0xff59, 0xff5a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x24 */ 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, 0x304a, 0x304b, 0x304c, 0x304d, 0x304e, 0x304f, 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e, 0x305f, 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068, 0x3069, 0x306a, 0x306b, 0x306c, 0x306d, 0x306e, 0x306f, 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, 0x3078, 0x3079, 0x307a, 0x307b, 0x307c, 0x307d, 0x307e, 0x307f, 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087, 0x3088, 0x3089, 0x308a, 0x308b, 0x308c, 0x308d, 0x308e, 0x308f, 0x3090, 0x3091, 0x3092, 0x3093, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x25 */ 0x30a1, 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9, 0x30aa, 0x30ab, 0x30ac, 0x30ad, 0x30ae, 0x30af, 0x30b0, 0x30b1, 0x30b2, 0x30b3, 0x30b4, 0x30b5, 0x30b6, 0x30b7, 0x30b8, 0x30b9, 0x30ba, 0x30bb, 0x30bc, 0x30bd, 0x30be, 0x30bf, 0x30c0, 0x30c1, 0x30c2, 0x30c3, 0x30c4, 0x30c5, 0x30c6, 0x30c7, 0x30c8, 0x30c9, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d0, 0x30d1, 0x30d2, 0x30d3, 0x30d4, 0x30d5, 0x30d6, 0x30d7, 0x30d8, 0x30d9, 0x30da, 0x30db, 0x30dc, 0x30dd, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ee, 0x30ef, 0x30f0, 0x30f1, 0x30f2, 0x30f3, 0x30f4, 0x30f5, 0x30f6, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x26 */ 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x27 */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x28 */ 0x2500, 0x2502, 0x250c, 0x2510, 0x2518, 0x2514, 0x251c, 0x252c, 0x2524, 0x2534, 0x253c, 0x2501, 0x2503, 0x250f, 0x2513, 0x251b, 0x2517, 0x2523, 0x2533, 0x252b, 0x253b, 0x254b, 0x2520, 0x252f, 0x2528, 0x2537, 0x253f, 0x251d, 0x2530, 0x2525, 0x2538, 0x2542, }; static const unsigned short jisx0208_2uni_page30[6398] = { /* 0x30 */ 0x4e9c, 0x5516, 0x5a03, 0x963f, 0x54c0, 0x611b, 0x6328, 0x59f6, 0x9022, 0x8475, 0x831c, 0x7a50, 0x60aa, 0x63e1, 0x6e25, 0x65ed, 0x8466, 0x82a6, 0x9bf5, 0x6893, 0x5727, 0x65a1, 0x6271, 0x5b9b, 0x59d0, 0x867b, 0x98f4, 0x7d62, 0x7dbe, 0x9b8e, 0x6216, 0x7c9f, 0x88b7, 0x5b89, 0x5eb5, 0x6309, 0x6697, 0x6848, 0x95c7, 0x978d, 0x674f, 0x4ee5, 0x4f0a, 0x4f4d, 0x4f9d, 0x5049, 0x56f2, 0x5937, 0x59d4, 0x5a01, 0x5c09, 0x60df, 0x610f, 0x6170, 0x6613, 0x6905, 0x70ba, 0x754f, 0x7570, 0x79fb, 0x7dad, 0x7def, 0x80c3, 0x840e, 0x8863, 0x8b02, 0x9055, 0x907a, 0x533b, 0x4e95, 0x4ea5, 0x57df, 0x80b2, 0x90c1, 0x78ef, 0x4e00, 0x58f1, 0x6ea2, 0x9038, 0x7a32, 0x8328, 0x828b, 0x9c2f, 0x5141, 0x5370, 0x54bd, 0x54e1, 0x56e0, 0x59fb, 0x5f15, 0x98f2, 0x6deb, 0x80e4, 0x852d, /* 0x31 */ 0x9662, 0x9670, 0x96a0, 0x97fb, 0x540b, 0x53f3, 0x5b87, 0x70cf, 0x7fbd, 0x8fc2, 0x96e8, 0x536f, 0x9d5c, 0x7aba, 0x4e11, 0x7893, 0x81fc, 0x6e26, 0x5618, 0x5504, 0x6b1d, 0x851a, 0x9c3b, 0x59e5, 0x53a9, 0x6d66, 0x74dc, 0x958f, 0x5642, 0x4e91, 0x904b, 0x96f2, 0x834f, 0x990c, 0x53e1, 0x55b6, 0x5b30, 0x5f71, 0x6620, 0x66f3, 0x6804, 0x6c38, 0x6cf3, 0x6d29, 0x745b, 0x76c8, 0x7a4e, 0x9834, 0x82f1, 0x885b, 0x8a60, 0x92ed, 0x6db2, 0x75ab, 0x76ca, 0x99c5, 0x60a6, 0x8b01, 0x8d8a, 0x95b2, 0x698e, 0x53ad, 0x5186, 0x5712, 0x5830, 0x5944, 0x5bb4, 0x5ef6, 0x6028, 0x63a9, 0x63f4, 0x6cbf, 0x6f14, 0x708e, 0x7114, 0x7159, 0x71d5, 0x733f, 0x7e01, 0x8276, 0x82d1, 0x8597, 0x9060, 0x925b, 0x9d1b, 0x5869, 0x65bc, 0x6c5a, 0x7525, 0x51f9, 0x592e, 0x5965, 0x5f80, 0x5fdc, /* 0x32 */ 0x62bc, 0x65fa, 0x6a2a, 0x6b27, 0x6bb4, 0x738b, 0x7fc1, 0x8956, 0x9d2c, 0x9d0e, 0x9ec4, 0x5ca1, 0x6c96, 0x837b, 0x5104, 0x5c4b, 0x61b6, 0x81c6, 0x6876, 0x7261, 0x4e59, 0x4ffa, 0x5378, 0x6069, 0x6e29, 0x7a4f, 0x97f3, 0x4e0b, 0x5316, 0x4eee, 0x4f55, 0x4f3d, 0x4fa1, 0x4f73, 0x52a0, 0x53ef, 0x5609, 0x590f, 0x5ac1, 0x5bb6, 0x5be1, 0x79d1, 0x6687, 0x679c, 0x67b6, 0x6b4c, 0x6cb3, 0x706b, 0x73c2, 0x798d, 0x79be, 0x7a3c, 0x7b87, 0x82b1, 0x82db, 0x8304, 0x8377, 0x83ef, 0x83d3, 0x8766, 0x8ab2, 0x5629, 0x8ca8, 0x8fe6, 0x904e, 0x971e, 0x868a, 0x4fc4, 0x5ce8, 0x6211, 0x7259, 0x753b, 0x81e5, 0x82bd, 0x86fe, 0x8cc0, 0x96c5, 0x9913, 0x99d5, 0x4ecb, 0x4f1a, 0x89e3, 0x56de, 0x584a, 0x58ca, 0x5efb, 0x5feb, 0x602a, 0x6094, 0x6062, 0x61d0, 0x6212, 0x62d0, 0x6539, /* 0x33 */ 0x9b41, 0x6666, 0x68b0, 0x6d77, 0x7070, 0x754c, 0x7686, 0x7d75, 0x82a5, 0x87f9, 0x958b, 0x968e, 0x8c9d, 0x51f1, 0x52be, 0x5916, 0x54b3, 0x5bb3, 0x5d16, 0x6168, 0x6982, 0x6daf, 0x788d, 0x84cb, 0x8857, 0x8a72, 0x93a7, 0x9ab8, 0x6d6c, 0x99a8, 0x86d9, 0x57a3, 0x67ff, 0x86ce, 0x920e, 0x5283, 0x5687, 0x5404, 0x5ed3, 0x62e1, 0x64b9, 0x683c, 0x6838, 0x6bbb, 0x7372, 0x78ba, 0x7a6b, 0x899a, 0x89d2, 0x8d6b, 0x8f03, 0x90ed, 0x95a3, 0x9694, 0x9769, 0x5b66, 0x5cb3, 0x697d, 0x984d, 0x984e, 0x639b, 0x7b20, 0x6a2b, 0x6a7f, 0x68b6, 0x9c0d, 0x6f5f, 0x5272, 0x559d, 0x6070, 0x62ec, 0x6d3b, 0x6e07, 0x6ed1, 0x845b, 0x8910, 0x8f44, 0x4e14, 0x9c39, 0x53f6, 0x691b, 0x6a3a, 0x9784, 0x682a, 0x515c, 0x7ac3, 0x84b2, 0x91dc, 0x938c, 0x565b, 0x9d28, 0x6822, 0x8305, 0x8431, /* 0x34 */ 0x7ca5, 0x5208, 0x82c5, 0x74e6, 0x4e7e, 0x4f83, 0x51a0, 0x5bd2, 0x520a, 0x52d8, 0x52e7, 0x5dfb, 0x559a, 0x582a, 0x59e6, 0x5b8c, 0x5b98, 0x5bdb, 0x5e72, 0x5e79, 0x60a3, 0x611f, 0x6163, 0x61be, 0x63db, 0x6562, 0x67d1, 0x6853, 0x68fa, 0x6b3e, 0x6b53, 0x6c57, 0x6f22, 0x6f97, 0x6f45, 0x74b0, 0x7518, 0x76e3, 0x770b, 0x7aff, 0x7ba1, 0x7c21, 0x7de9, 0x7f36, 0x7ff0, 0x809d, 0x8266, 0x839e, 0x89b3, 0x8acc, 0x8cab, 0x9084, 0x9451, 0x9593, 0x9591, 0x95a2, 0x9665, 0x97d3, 0x9928, 0x8218, 0x4e38, 0x542b, 0x5cb8, 0x5dcc, 0x73a9, 0x764c, 0x773c, 0x5ca9, 0x7feb, 0x8d0b, 0x96c1, 0x9811, 0x9854, 0x9858, 0x4f01, 0x4f0e, 0x5371, 0x559c, 0x5668, 0x57fa, 0x5947, 0x5b09, 0x5bc4, 0x5c90, 0x5e0c, 0x5e7e, 0x5fcc, 0x63ee, 0x673a, 0x65d7, 0x65e2, 0x671f, 0x68cb, 0x68c4, /* 0x35 */ 0x6a5f, 0x5e30, 0x6bc5, 0x6c17, 0x6c7d, 0x757f, 0x7948, 0x5b63, 0x7a00, 0x7d00, 0x5fbd, 0x898f, 0x8a18, 0x8cb4, 0x8d77, 0x8ecc, 0x8f1d, 0x98e2, 0x9a0e, 0x9b3c, 0x4e80, 0x507d, 0x5100, 0x5993, 0x5b9c, 0x622f, 0x6280, 0x64ec, 0x6b3a, 0x72a0, 0x7591, 0x7947, 0x7fa9, 0x87fb, 0x8abc, 0x8b70, 0x63ac, 0x83ca, 0x97a0, 0x5409, 0x5403, 0x55ab, 0x6854, 0x6a58, 0x8a70, 0x7827, 0x6775, 0x9ecd, 0x5374, 0x5ba2, 0x811a, 0x8650, 0x9006, 0x4e18, 0x4e45, 0x4ec7, 0x4f11, 0x53ca, 0x5438, 0x5bae, 0x5f13, 0x6025, 0x6551, 0x673d, 0x6c42, 0x6c72, 0x6ce3, 0x7078, 0x7403, 0x7a76, 0x7aae, 0x7b08, 0x7d1a, 0x7cfe, 0x7d66, 0x65e7, 0x725b, 0x53bb, 0x5c45, 0x5de8, 0x62d2, 0x62e0, 0x6319, 0x6e20, 0x865a, 0x8a31, 0x8ddd, 0x92f8, 0x6f01, 0x79a6, 0x9b5a, 0x4ea8, 0x4eab, 0x4eac, /* 0x36 */ 0x4f9b, 0x4fa0, 0x50d1, 0x5147, 0x7af6, 0x5171, 0x51f6, 0x5354, 0x5321, 0x537f, 0x53eb, 0x55ac, 0x5883, 0x5ce1, 0x5f37, 0x5f4a, 0x602f, 0x6050, 0x606d, 0x631f, 0x6559, 0x6a4b, 0x6cc1, 0x72c2, 0x72ed, 0x77ef, 0x80f8, 0x8105, 0x8208, 0x854e, 0x90f7, 0x93e1, 0x97ff, 0x9957, 0x9a5a, 0x4ef0, 0x51dd, 0x5c2d, 0x6681, 0x696d, 0x5c40, 0x66f2, 0x6975, 0x7389, 0x6850, 0x7c81, 0x50c5, 0x52e4, 0x5747, 0x5dfe, 0x9326, 0x65a4, 0x6b23, 0x6b3d, 0x7434, 0x7981, 0x79bd, 0x7b4b, 0x7dca, 0x82b9, 0x83cc, 0x887f, 0x895f, 0x8b39, 0x8fd1, 0x91d1, 0x541f, 0x9280, 0x4e5d, 0x5036, 0x53e5, 0x533a, 0x72d7, 0x7396, 0x77e9, 0x82e6, 0x8eaf, 0x99c6, 0x99c8, 0x99d2, 0x5177, 0x611a, 0x865e, 0x55b0, 0x7a7a, 0x5076, 0x5bd3, 0x9047, 0x9685, 0x4e32, 0x6adb, 0x91e7, 0x5c51, 0x5c48, /* 0x37 */ 0x6398, 0x7a9f, 0x6c93, 0x9774, 0x8f61, 0x7aaa, 0x718a, 0x9688, 0x7c82, 0x6817, 0x7e70, 0x6851, 0x936c, 0x52f2, 0x541b, 0x85ab, 0x8a13, 0x7fa4, 0x8ecd, 0x90e1, 0x5366, 0x8888, 0x7941, 0x4fc2, 0x50be, 0x5211, 0x5144, 0x5553, 0x572d, 0x73ea, 0x578b, 0x5951, 0x5f62, 0x5f84, 0x6075, 0x6176, 0x6167, 0x61a9, 0x63b2, 0x643a, 0x656c, 0x666f, 0x6842, 0x6e13, 0x7566, 0x7a3d, 0x7cfb, 0x7d4c, 0x7d99, 0x7e4b, 0x7f6b, 0x830e, 0x834a, 0x86cd, 0x8a08, 0x8a63, 0x8b66, 0x8efd, 0x981a, 0x9d8f, 0x82b8, 0x8fce, 0x9be8, 0x5287, 0x621f, 0x6483, 0x6fc0, 0x9699, 0x6841, 0x5091, 0x6b20, 0x6c7a, 0x6f54, 0x7a74, 0x7d50, 0x8840, 0x8a23, 0x6708, 0x4ef6, 0x5039, 0x5026, 0x5065, 0x517c, 0x5238, 0x5263, 0x55a7, 0x570f, 0x5805, 0x5acc, 0x5efa, 0x61b2, 0x61f8, 0x62f3, 0x6372, /* 0x38 */ 0x691c, 0x6a29, 0x727d, 0x72ac, 0x732e, 0x7814, 0x786f, 0x7d79, 0x770c, 0x80a9, 0x898b, 0x8b19, 0x8ce2, 0x8ed2, 0x9063, 0x9375, 0x967a, 0x9855, 0x9a13, 0x9e78, 0x5143, 0x539f, 0x53b3, 0x5e7b, 0x5f26, 0x6e1b, 0x6e90, 0x7384, 0x73fe, 0x7d43, 0x8237, 0x8a00, 0x8afa, 0x9650, 0x4e4e, 0x500b, 0x53e4, 0x547c, 0x56fa, 0x59d1, 0x5b64, 0x5df1, 0x5eab, 0x5f27, 0x6238, 0x6545, 0x67af, 0x6e56, 0x72d0, 0x7cca, 0x88b4, 0x80a1, 0x80e1, 0x83f0, 0x864e, 0x8a87, 0x8de8, 0x9237, 0x96c7, 0x9867, 0x9f13, 0x4e94, 0x4e92, 0x4f0d, 0x5348, 0x5449, 0x543e, 0x5a2f, 0x5f8c, 0x5fa1, 0x609f, 0x68a7, 0x6a8e, 0x745a, 0x7881, 0x8a9e, 0x8aa4, 0x8b77, 0x9190, 0x4e5e, 0x9bc9, 0x4ea4, 0x4f7c, 0x4faf, 0x5019, 0x5016, 0x5149, 0x516c, 0x529f, 0x52b9, 0x52fe, 0x539a, 0x53e3, 0x5411, /* 0x39 */ 0x540e, 0x5589, 0x5751, 0x57a2, 0x597d, 0x5b54, 0x5b5d, 0x5b8f, 0x5de5, 0x5de7, 0x5df7, 0x5e78, 0x5e83, 0x5e9a, 0x5eb7, 0x5f18, 0x6052, 0x614c, 0x6297, 0x62d8, 0x63a7, 0x653b, 0x6602, 0x6643, 0x66f4, 0x676d, 0x6821, 0x6897, 0x69cb, 0x6c5f, 0x6d2a, 0x6d69, 0x6e2f, 0x6e9d, 0x7532, 0x7687, 0x786c, 0x7a3f, 0x7ce0, 0x7d05, 0x7d18, 0x7d5e, 0x7db1, 0x8015, 0x8003, 0x80af, 0x80b1, 0x8154, 0x818f, 0x822a, 0x8352, 0x884c, 0x8861, 0x8b1b, 0x8ca2, 0x8cfc, 0x90ca, 0x9175, 0x9271, 0x783f, 0x92fc, 0x95a4, 0x964d, 0x9805, 0x9999, 0x9ad8, 0x9d3b, 0x525b, 0x52ab, 0x53f7, 0x5408, 0x58d5, 0x62f7, 0x6fe0, 0x8c6a, 0x8f5f, 0x9eb9, 0x514b, 0x523b, 0x544a, 0x56fd, 0x7a40, 0x9177, 0x9d60, 0x9ed2, 0x7344, 0x6f09, 0x8170, 0x7511, 0x5ffd, 0x60da, 0x9aa8, 0x72db, 0x8fbc, /* 0x3a */ 0x6b64, 0x9803, 0x4eca, 0x56f0, 0x5764, 0x58be, 0x5a5a, 0x6068, 0x61c7, 0x660f, 0x6606, 0x6839, 0x68b1, 0x6df7, 0x75d5, 0x7d3a, 0x826e, 0x9b42, 0x4e9b, 0x4f50, 0x53c9, 0x5506, 0x5d6f, 0x5de6, 0x5dee, 0x67fb, 0x6c99, 0x7473, 0x7802, 0x8a50, 0x9396, 0x88df, 0x5750, 0x5ea7, 0x632b, 0x50b5, 0x50ac, 0x518d, 0x6700, 0x54c9, 0x585e, 0x59bb, 0x5bb0, 0x5f69, 0x624d, 0x63a1, 0x683d, 0x6b73, 0x6e08, 0x707d, 0x91c7, 0x7280, 0x7815, 0x7826, 0x796d, 0x658e, 0x7d30, 0x83dc, 0x88c1, 0x8f09, 0x969b, 0x5264, 0x5728, 0x6750, 0x7f6a, 0x8ca1, 0x51b4, 0x5742, 0x962a, 0x583a, 0x698a, 0x80b4, 0x54b2, 0x5d0e, 0x57fc, 0x7895, 0x9dfa, 0x4f5c, 0x524a, 0x548b, 0x643e, 0x6628, 0x6714, 0x67f5, 0x7a84, 0x7b56, 0x7d22, 0x932f, 0x685c, 0x9bad, 0x7b39, 0x5319, 0x518a, 0x5237, /* 0x3b */ 0x5bdf, 0x62f6, 0x64ae, 0x64e6, 0x672d, 0x6bba, 0x85a9, 0x96d1, 0x7690, 0x9bd6, 0x634c, 0x9306, 0x9bab, 0x76bf, 0x6652, 0x4e09, 0x5098, 0x53c2, 0x5c71, 0x60e8, 0x6492, 0x6563, 0x685f, 0x71e6, 0x73ca, 0x7523, 0x7b97, 0x7e82, 0x8695, 0x8b83, 0x8cdb, 0x9178, 0x9910, 0x65ac, 0x66ab, 0x6b8b, 0x4ed5, 0x4ed4, 0x4f3a, 0x4f7f, 0x523a, 0x53f8, 0x53f2, 0x55e3, 0x56db, 0x58eb, 0x59cb, 0x59c9, 0x59ff, 0x5b50, 0x5c4d, 0x5e02, 0x5e2b, 0x5fd7, 0x601d, 0x6307, 0x652f, 0x5b5c, 0x65af, 0x65bd, 0x65e8, 0x679d, 0x6b62, 0x6b7b, 0x6c0f, 0x7345, 0x7949, 0x79c1, 0x7cf8, 0x7d19, 0x7d2b, 0x80a2, 0x8102, 0x81f3, 0x8996, 0x8a5e, 0x8a69, 0x8a66, 0x8a8c, 0x8aee, 0x8cc7, 0x8cdc, 0x96cc, 0x98fc, 0x6b6f, 0x4e8b, 0x4f3c, 0x4f8d, 0x5150, 0x5b57, 0x5bfa, 0x6148, 0x6301, 0x6642, /* 0x3c */ 0x6b21, 0x6ecb, 0x6cbb, 0x723e, 0x74bd, 0x75d4, 0x78c1, 0x793a, 0x800c, 0x8033, 0x81ea, 0x8494, 0x8f9e, 0x6c50, 0x9e7f, 0x5f0f, 0x8b58, 0x9d2b, 0x7afa, 0x8ef8, 0x5b8d, 0x96eb, 0x4e03, 0x53f1, 0x57f7, 0x5931, 0x5ac9, 0x5ba4, 0x6089, 0x6e7f, 0x6f06, 0x75be, 0x8cea, 0x5b9f, 0x8500, 0x7be0, 0x5072, 0x67f4, 0x829d, 0x5c61, 0x854a, 0x7e1e, 0x820e, 0x5199, 0x5c04, 0x6368, 0x8d66, 0x659c, 0x716e, 0x793e, 0x7d17, 0x8005, 0x8b1d, 0x8eca, 0x906e, 0x86c7, 0x90aa, 0x501f, 0x52fa, 0x5c3a, 0x6753, 0x707c, 0x7235, 0x914c, 0x91c8, 0x932b, 0x82e5, 0x5bc2, 0x5f31, 0x60f9, 0x4e3b, 0x53d6, 0x5b88, 0x624b, 0x6731, 0x6b8a, 0x72e9, 0x73e0, 0x7a2e, 0x816b, 0x8da3, 0x9152, 0x9996, 0x5112, 0x53d7, 0x546a, 0x5bff, 0x6388, 0x6a39, 0x7dac, 0x9700, 0x56da, 0x53ce, 0x5468, /* 0x3d */ 0x5b97, 0x5c31, 0x5dde, 0x4fee, 0x6101, 0x62fe, 0x6d32, 0x79c0, 0x79cb, 0x7d42, 0x7e4d, 0x7fd2, 0x81ed, 0x821f, 0x8490, 0x8846, 0x8972, 0x8b90, 0x8e74, 0x8f2f, 0x9031, 0x914b, 0x916c, 0x96c6, 0x919c, 0x4ec0, 0x4f4f, 0x5145, 0x5341, 0x5f93, 0x620e, 0x67d4, 0x6c41, 0x6e0b, 0x7363, 0x7e26, 0x91cd, 0x9283, 0x53d4, 0x5919, 0x5bbf, 0x6dd1, 0x795d, 0x7e2e, 0x7c9b, 0x587e, 0x719f, 0x51fa, 0x8853, 0x8ff0, 0x4fca, 0x5cfb, 0x6625, 0x77ac, 0x7ae3, 0x821c, 0x99ff, 0x51c6, 0x5faa, 0x65ec, 0x696f, 0x6b89, 0x6df3, 0x6e96, 0x6f64, 0x76fe, 0x7d14, 0x5de1, 0x9075, 0x9187, 0x9806, 0x51e6, 0x521d, 0x6240, 0x6691, 0x66d9, 0x6e1a, 0x5eb6, 0x7dd2, 0x7f72, 0x66f8, 0x85af, 0x85f7, 0x8af8, 0x52a9, 0x53d9, 0x5973, 0x5e8f, 0x5f90, 0x6055, 0x92e4, 0x9664, 0x50b7, 0x511f, /* 0x3e */ 0x52dd, 0x5320, 0x5347, 0x53ec, 0x54e8, 0x5546, 0x5531, 0x5617, 0x5968, 0x59be, 0x5a3c, 0x5bb5, 0x5c06, 0x5c0f, 0x5c11, 0x5c1a, 0x5e84, 0x5e8a, 0x5ee0, 0x5f70, 0x627f, 0x6284, 0x62db, 0x638c, 0x6377, 0x6607, 0x660c, 0x662d, 0x6676, 0x677e, 0x68a2, 0x6a1f, 0x6a35, 0x6cbc, 0x6d88, 0x6e09, 0x6e58, 0x713c, 0x7126, 0x7167, 0x75c7, 0x7701, 0x785d, 0x7901, 0x7965, 0x79f0, 0x7ae0, 0x7b11, 0x7ca7, 0x7d39, 0x8096, 0x83d6, 0x848b, 0x8549, 0x885d, 0x88f3, 0x8a1f, 0x8a3c, 0x8a54, 0x8a73, 0x8c61, 0x8cde, 0x91a4, 0x9266, 0x937e, 0x9418, 0x969c, 0x9798, 0x4e0a, 0x4e08, 0x4e1e, 0x4e57, 0x5197, 0x5270, 0x57ce, 0x5834, 0x58cc, 0x5b22, 0x5e38, 0x60c5, 0x64fe, 0x6761, 0x6756, 0x6d44, 0x72b6, 0x7573, 0x7a63, 0x84b8, 0x8b72, 0x91b8, 0x9320, 0x5631, 0x57f4, 0x98fe, /* 0x3f */ 0x62ed, 0x690d, 0x6b96, 0x71ed, 0x7e54, 0x8077, 0x8272, 0x89e6, 0x98df, 0x8755, 0x8fb1, 0x5c3b, 0x4f38, 0x4fe1, 0x4fb5, 0x5507, 0x5a20, 0x5bdd, 0x5be9, 0x5fc3, 0x614e, 0x632f, 0x65b0, 0x664b, 0x68ee, 0x699b, 0x6d78, 0x6df1, 0x7533, 0x75b9, 0x771f, 0x795e, 0x79e6, 0x7d33, 0x81e3, 0x82af, 0x85aa, 0x89aa, 0x8a3a, 0x8eab, 0x8f9b, 0x9032, 0x91dd, 0x9707, 0x4eba, 0x4ec1, 0x5203, 0x5875, 0x58ec, 0x5c0b, 0x751a, 0x5c3d, 0x814e, 0x8a0a, 0x8fc5, 0x9663, 0x976d, 0x7b25, 0x8acf, 0x9808, 0x9162, 0x56f3, 0x53a8, 0x9017, 0x5439, 0x5782, 0x5e25, 0x63a8, 0x6c34, 0x708a, 0x7761, 0x7c8b, 0x7fe0, 0x8870, 0x9042, 0x9154, 0x9310, 0x9318, 0x968f, 0x745e, 0x9ac4, 0x5d07, 0x5d69, 0x6570, 0x67a2, 0x8da8, 0x96db, 0x636e, 0x6749, 0x6919, 0x83c5, 0x9817, 0x96c0, 0x88fe, /* 0x40 */ 0x6f84, 0x647a, 0x5bf8, 0x4e16, 0x702c, 0x755d, 0x662f, 0x51c4, 0x5236, 0x52e2, 0x59d3, 0x5f81, 0x6027, 0x6210, 0x653f, 0x6574, 0x661f, 0x6674, 0x68f2, 0x6816, 0x6b63, 0x6e05, 0x7272, 0x751f, 0x76db, 0x7cbe, 0x8056, 0x58f0, 0x88fd, 0x897f, 0x8aa0, 0x8a93, 0x8acb, 0x901d, 0x9192, 0x9752, 0x9759, 0x6589, 0x7a0e, 0x8106, 0x96bb, 0x5e2d, 0x60dc, 0x621a, 0x65a5, 0x6614, 0x6790, 0x77f3, 0x7a4d, 0x7c4d, 0x7e3e, 0x810a, 0x8cac, 0x8d64, 0x8de1, 0x8e5f, 0x78a9, 0x5207, 0x62d9, 0x63a5, 0x6442, 0x6298, 0x8a2d, 0x7a83, 0x7bc0, 0x8aac, 0x96ea, 0x7d76, 0x820c, 0x8749, 0x4ed9, 0x5148, 0x5343, 0x5360, 0x5ba3, 0x5c02, 0x5c16, 0x5ddd, 0x6226, 0x6247, 0x64b0, 0x6813, 0x6834, 0x6cc9, 0x6d45, 0x6d17, 0x67d3, 0x6f5c, 0x714e, 0x717d, 0x65cb, 0x7a7f, 0x7bad, 0x7dda, /* 0x41 */ 0x7e4a, 0x7fa8, 0x817a, 0x821b, 0x8239, 0x85a6, 0x8a6e, 0x8cce, 0x8df5, 0x9078, 0x9077, 0x92ad, 0x9291, 0x9583, 0x9bae, 0x524d, 0x5584, 0x6f38, 0x7136, 0x5168, 0x7985, 0x7e55, 0x81b3, 0x7cce, 0x564c, 0x5851, 0x5ca8, 0x63aa, 0x66fe, 0x66fd, 0x695a, 0x72d9, 0x758f, 0x758e, 0x790e, 0x7956, 0x79df, 0x7c97, 0x7d20, 0x7d44, 0x8607, 0x8a34, 0x963b, 0x9061, 0x9f20, 0x50e7, 0x5275, 0x53cc, 0x53e2, 0x5009, 0x55aa, 0x58ee, 0x594f, 0x723d, 0x5b8b, 0x5c64, 0x531d, 0x60e3, 0x60f3, 0x635c, 0x6383, 0x633f, 0x63bb, 0x64cd, 0x65e9, 0x66f9, 0x5de3, 0x69cd, 0x69fd, 0x6f15, 0x71e5, 0x4e89, 0x75e9, 0x76f8, 0x7a93, 0x7cdf, 0x7dcf, 0x7d9c, 0x8061, 0x8349, 0x8358, 0x846c, 0x84bc, 0x85fb, 0x88c5, 0x8d70, 0x9001, 0x906d, 0x9397, 0x971c, 0x9a12, 0x50cf, 0x5897, 0x618e, /* 0x42 */ 0x81d3, 0x8535, 0x8d08, 0x9020, 0x4fc3, 0x5074, 0x5247, 0x5373, 0x606f, 0x6349, 0x675f, 0x6e2c, 0x8db3, 0x901f, 0x4fd7, 0x5c5e, 0x8cca, 0x65cf, 0x7d9a, 0x5352, 0x8896, 0x5176, 0x63c3, 0x5b58, 0x5b6b, 0x5c0a, 0x640d, 0x6751, 0x905c, 0x4ed6, 0x591a, 0x592a, 0x6c70, 0x8a51, 0x553e, 0x5815, 0x59a5, 0x60f0, 0x6253, 0x67c1, 0x8235, 0x6955, 0x9640, 0x99c4, 0x9a28, 0x4f53, 0x5806, 0x5bfe, 0x8010, 0x5cb1, 0x5e2f, 0x5f85, 0x6020, 0x614b, 0x6234, 0x66ff, 0x6cf0, 0x6ede, 0x80ce, 0x817f, 0x82d4, 0x888b, 0x8cb8, 0x9000, 0x902e, 0x968a, 0x9edb, 0x9bdb, 0x4ee3, 0x53f0, 0x5927, 0x7b2c, 0x918d, 0x984c, 0x9df9, 0x6edd, 0x7027, 0x5353, 0x5544, 0x5b85, 0x6258, 0x629e, 0x62d3, 0x6ca2, 0x6fef, 0x7422, 0x8a17, 0x9438, 0x6fc1, 0x8afe, 0x8338, 0x51e7, 0x86f8, 0x53ea, /* 0x43 */ 0x53e9, 0x4f46, 0x9054, 0x8fb0, 0x596a, 0x8131, 0x5dfd, 0x7aea, 0x8fbf, 0x68da, 0x8c37, 0x72f8, 0x9c48, 0x6a3d, 0x8ab0, 0x4e39, 0x5358, 0x5606, 0x5766, 0x62c5, 0x63a2, 0x65e6, 0x6b4e, 0x6de1, 0x6e5b, 0x70ad, 0x77ed, 0x7aef, 0x7baa, 0x7dbb, 0x803d, 0x80c6, 0x86cb, 0x8a95, 0x935b, 0x56e3, 0x58c7, 0x5f3e, 0x65ad, 0x6696, 0x6a80, 0x6bb5, 0x7537, 0x8ac7, 0x5024, 0x77e5, 0x5730, 0x5f1b, 0x6065, 0x667a, 0x6c60, 0x75f4, 0x7a1a, 0x7f6e, 0x81f4, 0x8718, 0x9045, 0x99b3, 0x7bc9, 0x755c, 0x7af9, 0x7b51, 0x84c4, 0x9010, 0x79e9, 0x7a92, 0x8336, 0x5ae1, 0x7740, 0x4e2d, 0x4ef2, 0x5b99, 0x5fe0, 0x62bd, 0x663c, 0x67f1, 0x6ce8, 0x866b, 0x8877, 0x8a3b, 0x914e, 0x92f3, 0x99d0, 0x6a17, 0x7026, 0x732a, 0x82e7, 0x8457, 0x8caf, 0x4e01, 0x5146, 0x51cb, 0x558b, 0x5bf5, /* 0x44 */ 0x5e16, 0x5e33, 0x5e81, 0x5f14, 0x5f35, 0x5f6b, 0x5fb4, 0x61f2, 0x6311, 0x66a2, 0x671d, 0x6f6e, 0x7252, 0x753a, 0x773a, 0x8074, 0x8139, 0x8178, 0x8776, 0x8abf, 0x8adc, 0x8d85, 0x8df3, 0x929a, 0x9577, 0x9802, 0x9ce5, 0x52c5, 0x6357, 0x76f4, 0x6715, 0x6c88, 0x73cd, 0x8cc3, 0x93ae, 0x9673, 0x6d25, 0x589c, 0x690e, 0x69cc, 0x8ffd, 0x939a, 0x75db, 0x901a, 0x585a, 0x6802, 0x63b4, 0x69fb, 0x4f43, 0x6f2c, 0x67d8, 0x8fbb, 0x8526, 0x7db4, 0x9354, 0x693f, 0x6f70, 0x576a, 0x58f7, 0x5b2c, 0x7d2c, 0x722a, 0x540a, 0x91e3, 0x9db4, 0x4ead, 0x4f4e, 0x505c, 0x5075, 0x5243, 0x8c9e, 0x5448, 0x5824, 0x5b9a, 0x5e1d, 0x5e95, 0x5ead, 0x5ef7, 0x5f1f, 0x608c, 0x62b5, 0x633a, 0x63d0, 0x68af, 0x6c40, 0x7887, 0x798e, 0x7a0b, 0x7de0, 0x8247, 0x8a02, 0x8ae6, 0x8e44, 0x9013, /* 0x45 */ 0x90b8, 0x912d, 0x91d8, 0x9f0e, 0x6ce5, 0x6458, 0x64e2, 0x6575, 0x6ef4, 0x7684, 0x7b1b, 0x9069, 0x93d1, 0x6eba, 0x54f2, 0x5fb9, 0x64a4, 0x8f4d, 0x8fed, 0x9244, 0x5178, 0x586b, 0x5929, 0x5c55, 0x5e97, 0x6dfb, 0x7e8f, 0x751c, 0x8cbc, 0x8ee2, 0x985b, 0x70b9, 0x4f1d, 0x6bbf, 0x6fb1, 0x7530, 0x96fb, 0x514e, 0x5410, 0x5835, 0x5857, 0x59ac, 0x5c60, 0x5f92, 0x6597, 0x675c, 0x6e21, 0x767b, 0x83df, 0x8ced, 0x9014, 0x90fd, 0x934d, 0x7825, 0x783a, 0x52aa, 0x5ea6, 0x571f, 0x5974, 0x6012, 0x5012, 0x515a, 0x51ac, 0x51cd, 0x5200, 0x5510, 0x5854, 0x5858, 0x5957, 0x5b95, 0x5cf6, 0x5d8b, 0x60bc, 0x6295, 0x642d, 0x6771, 0x6843, 0x68bc, 0x68df, 0x76d7, 0x6dd8, 0x6e6f, 0x6d9b, 0x706f, 0x71c8, 0x5f53, 0x75d8, 0x7977, 0x7b49, 0x7b54, 0x7b52, 0x7cd6, 0x7d71, 0x5230, /* 0x46 */ 0x8463, 0x8569, 0x85e4, 0x8a0e, 0x8b04, 0x8c46, 0x8e0f, 0x9003, 0x900f, 0x9419, 0x9676, 0x982d, 0x9a30, 0x95d8, 0x50cd, 0x52d5, 0x540c, 0x5802, 0x5c0e, 0x61a7, 0x649e, 0x6d1e, 0x77b3, 0x7ae5, 0x80f4, 0x8404, 0x9053, 0x9285, 0x5ce0, 0x9d07, 0x533f, 0x5f97, 0x5fb3, 0x6d9c, 0x7279, 0x7763, 0x79bf, 0x7be4, 0x6bd2, 0x72ec, 0x8aad, 0x6803, 0x6a61, 0x51f8, 0x7a81, 0x6934, 0x5c4a, 0x9cf6, 0x82eb, 0x5bc5, 0x9149, 0x701e, 0x5678, 0x5c6f, 0x60c7, 0x6566, 0x6c8c, 0x8c5a, 0x9041, 0x9813, 0x5451, 0x66c7, 0x920d, 0x5948, 0x90a3, 0x5185, 0x4e4d, 0x51ea, 0x8599, 0x8b0e, 0x7058, 0x637a, 0x934b, 0x6962, 0x99b4, 0x7e04, 0x7577, 0x5357, 0x6960, 0x8edf, 0x96e3, 0x6c5d, 0x4e8c, 0x5c3c, 0x5f10, 0x8fe9, 0x5302, 0x8cd1, 0x8089, 0x8679, 0x5eff, 0x65e5, 0x4e73, 0x5165, /* 0x47 */ 0x5982, 0x5c3f, 0x97ee, 0x4efb, 0x598a, 0x5fcd, 0x8a8d, 0x6fe1, 0x79b0, 0x7962, 0x5be7, 0x8471, 0x732b, 0x71b1, 0x5e74, 0x5ff5, 0x637b, 0x649a, 0x71c3, 0x7c98, 0x4e43, 0x5efc, 0x4e4b, 0x57dc, 0x56a2, 0x60a9, 0x6fc3, 0x7d0d, 0x80fd, 0x8133, 0x81bf, 0x8fb2, 0x8997, 0x86a4, 0x5df4, 0x628a, 0x64ad, 0x8987, 0x6777, 0x6ce2, 0x6d3e, 0x7436, 0x7834, 0x5a46, 0x7f75, 0x82ad, 0x99ac, 0x4ff3, 0x5ec3, 0x62dd, 0x6392, 0x6557, 0x676f, 0x76c3, 0x724c, 0x80cc, 0x80ba, 0x8f29, 0x914d, 0x500d, 0x57f9, 0x5a92, 0x6885, 0x6973, 0x7164, 0x72fd, 0x8cb7, 0x58f2, 0x8ce0, 0x966a, 0x9019, 0x877f, 0x79e4, 0x77e7, 0x8429, 0x4f2f, 0x5265, 0x535a, 0x62cd, 0x67cf, 0x6cca, 0x767d, 0x7b94, 0x7c95, 0x8236, 0x8584, 0x8feb, 0x66dd, 0x6f20, 0x7206, 0x7e1b, 0x83ab, 0x99c1, 0x9ea6, /* 0x48 */ 0x51fd, 0x7bb1, 0x7872, 0x7bb8, 0x8087, 0x7b48, 0x6ae8, 0x5e61, 0x808c, 0x7551, 0x7560, 0x516b, 0x9262, 0x6e8c, 0x767a, 0x9197, 0x9aea, 0x4f10, 0x7f70, 0x629c, 0x7b4f, 0x95a5, 0x9ce9, 0x567a, 0x5859, 0x86e4, 0x96bc, 0x4f34, 0x5224, 0x534a, 0x53cd, 0x53db, 0x5e06, 0x642c, 0x6591, 0x677f, 0x6c3e, 0x6c4e, 0x7248, 0x72af, 0x73ed, 0x7554, 0x7e41, 0x822c, 0x85e9, 0x8ca9, 0x7bc4, 0x91c6, 0x7169, 0x9812, 0x98ef, 0x633d, 0x6669, 0x756a, 0x76e4, 0x78d0, 0x8543, 0x86ee, 0x532a, 0x5351, 0x5426, 0x5983, 0x5e87, 0x5f7c, 0x60b2, 0x6249, 0x6279, 0x62ab, 0x6590, 0x6bd4, 0x6ccc, 0x75b2, 0x76ae, 0x7891, 0x79d8, 0x7dcb, 0x7f77, 0x80a5, 0x88ab, 0x8ab9, 0x8cbb, 0x907f, 0x975e, 0x98db, 0x6a0b, 0x7c38, 0x5099, 0x5c3e, 0x5fae, 0x6787, 0x6bd8, 0x7435, 0x7709, 0x7f8e, /* 0x49 */ 0x9f3b, 0x67ca, 0x7a17, 0x5339, 0x758b, 0x9aed, 0x5f66, 0x819d, 0x83f1, 0x8098, 0x5f3c, 0x5fc5, 0x7562, 0x7b46, 0x903c, 0x6867, 0x59eb, 0x5a9b, 0x7d10, 0x767e, 0x8b2c, 0x4ff5, 0x5f6a, 0x6a19, 0x6c37, 0x6f02, 0x74e2, 0x7968, 0x8868, 0x8a55, 0x8c79, 0x5edf, 0x63cf, 0x75c5, 0x79d2, 0x82d7, 0x9328, 0x92f2, 0x849c, 0x86ed, 0x9c2d, 0x54c1, 0x5f6c, 0x658c, 0x6d5c, 0x7015, 0x8ca7, 0x8cd3, 0x983b, 0x654f, 0x74f6, 0x4e0d, 0x4ed8, 0x57e0, 0x592b, 0x5a66, 0x5bcc, 0x51a8, 0x5e03, 0x5e9c, 0x6016, 0x6276, 0x6577, 0x65a7, 0x666e, 0x6d6e, 0x7236, 0x7b26, 0x8150, 0x819a, 0x8299, 0x8b5c, 0x8ca0, 0x8ce6, 0x8d74, 0x961c, 0x9644, 0x4fae, 0x64ab, 0x6b66, 0x821e, 0x8461, 0x856a, 0x90e8, 0x5c01, 0x6953, 0x98a8, 0x847a, 0x8557, 0x4f0f, 0x526f, 0x5fa9, 0x5e45, 0x670d, /* 0x4a */ 0x798f, 0x8179, 0x8907, 0x8986, 0x6df5, 0x5f17, 0x6255, 0x6cb8, 0x4ecf, 0x7269, 0x9b92, 0x5206, 0x543b, 0x5674, 0x58b3, 0x61a4, 0x626e, 0x711a, 0x596e, 0x7c89, 0x7cde, 0x7d1b, 0x96f0, 0x6587, 0x805e, 0x4e19, 0x4f75, 0x5175, 0x5840, 0x5e63, 0x5e73, 0x5f0a, 0x67c4, 0x4e26, 0x853d, 0x9589, 0x965b, 0x7c73, 0x9801, 0x50fb, 0x58c1, 0x7656, 0x78a7, 0x5225, 0x77a5, 0x8511, 0x7b86, 0x504f, 0x5909, 0x7247, 0x7bc7, 0x7de8, 0x8fba, 0x8fd4, 0x904d, 0x4fbf, 0x52c9, 0x5a29, 0x5f01, 0x97ad, 0x4fdd, 0x8217, 0x92ea, 0x5703, 0x6355, 0x6b69, 0x752b, 0x88dc, 0x8f14, 0x7a42, 0x52df, 0x5893, 0x6155, 0x620a, 0x66ae, 0x6bcd, 0x7c3f, 0x83e9, 0x5023, 0x4ff8, 0x5305, 0x5446, 0x5831, 0x5949, 0x5b9d, 0x5cf0, 0x5cef, 0x5d29, 0x5e96, 0x62b1, 0x6367, 0x653e, 0x65b9, 0x670b, /* 0x4b */ 0x6cd5, 0x6ce1, 0x70f9, 0x7832, 0x7e2b, 0x80de, 0x82b3, 0x840c, 0x84ec, 0x8702, 0x8912, 0x8a2a, 0x8c4a, 0x90a6, 0x92d2, 0x98fd, 0x9cf3, 0x9d6c, 0x4e4f, 0x4ea1, 0x508d, 0x5256, 0x574a, 0x59a8, 0x5e3d, 0x5fd8, 0x5fd9, 0x623f, 0x66b4, 0x671b, 0x67d0, 0x68d2, 0x5192, 0x7d21, 0x80aa, 0x81a8, 0x8b00, 0x8c8c, 0x8cbf, 0x927e, 0x9632, 0x5420, 0x982c, 0x5317, 0x50d5, 0x535c, 0x58a8, 0x64b2, 0x6734, 0x7267, 0x7766, 0x7a46, 0x91e6, 0x52c3, 0x6ca1, 0x6b86, 0x5800, 0x5e4c, 0x5954, 0x672c, 0x7ffb, 0x51e1, 0x76c6, 0x6469, 0x78e8, 0x9b54, 0x9ebb, 0x57cb, 0x59b9, 0x6627, 0x679a, 0x6bce, 0x54e9, 0x69d9, 0x5e55, 0x819c, 0x6795, 0x9baa, 0x67fe, 0x9c52, 0x685d, 0x4ea6, 0x4fe3, 0x53c8, 0x62b9, 0x672b, 0x6cab, 0x8fc4, 0x4fad, 0x7e6d, 0x9ebf, 0x4e07, 0x6162, 0x6e80, /* 0x4c */ 0x6f2b, 0x8513, 0x5473, 0x672a, 0x9b45, 0x5df3, 0x7b95, 0x5cac, 0x5bc6, 0x871c, 0x6e4a, 0x84d1, 0x7a14, 0x8108, 0x5999, 0x7c8d, 0x6c11, 0x7720, 0x52d9, 0x5922, 0x7121, 0x725f, 0x77db, 0x9727, 0x9d61, 0x690b, 0x5a7f, 0x5a18, 0x51a5, 0x540d, 0x547d, 0x660e, 0x76df, 0x8ff7, 0x9298, 0x9cf4, 0x59ea, 0x725d, 0x6ec5, 0x514d, 0x68c9, 0x7dbf, 0x7dec, 0x9762, 0x9eba, 0x6478, 0x6a21, 0x8302, 0x5984, 0x5b5f, 0x6bdb, 0x731b, 0x76f2, 0x7db2, 0x8017, 0x8499, 0x5132, 0x6728, 0x9ed9, 0x76ee, 0x6762, 0x52ff, 0x9905, 0x5c24, 0x623b, 0x7c7e, 0x8cb0, 0x554f, 0x60b6, 0x7d0b, 0x9580, 0x5301, 0x4e5f, 0x51b6, 0x591c, 0x723a, 0x8036, 0x91ce, 0x5f25, 0x77e2, 0x5384, 0x5f79, 0x7d04, 0x85ac, 0x8a33, 0x8e8d, 0x9756, 0x67f3, 0x85ae, 0x9453, 0x6109, 0x6108, 0x6cb9, 0x7652, /* 0x4d */ 0x8aed, 0x8f38, 0x552f, 0x4f51, 0x512a, 0x52c7, 0x53cb, 0x5ba5, 0x5e7d, 0x60a0, 0x6182, 0x63d6, 0x6709, 0x67da, 0x6e67, 0x6d8c, 0x7336, 0x7337, 0x7531, 0x7950, 0x88d5, 0x8a98, 0x904a, 0x9091, 0x90f5, 0x96c4, 0x878d, 0x5915, 0x4e88, 0x4f59, 0x4e0e, 0x8a89, 0x8f3f, 0x9810, 0x50ad, 0x5e7c, 0x5996, 0x5bb9, 0x5eb8, 0x63da, 0x63fa, 0x64c1, 0x66dc, 0x694a, 0x69d8, 0x6d0b, 0x6eb6, 0x7194, 0x7528, 0x7aaf, 0x7f8a, 0x8000, 0x8449, 0x84c9, 0x8981, 0x8b21, 0x8e0a, 0x9065, 0x967d, 0x990a, 0x617e, 0x6291, 0x6b32, 0x6c83, 0x6d74, 0x7fcc, 0x7ffc, 0x6dc0, 0x7f85, 0x87ba, 0x88f8, 0x6765, 0x83b1, 0x983c, 0x96f7, 0x6d1b, 0x7d61, 0x843d, 0x916a, 0x4e71, 0x5375, 0x5d50, 0x6b04, 0x6feb, 0x85cd, 0x862d, 0x89a7, 0x5229, 0x540f, 0x5c65, 0x674e, 0x68a8, 0x7406, 0x7483, /* 0x4e */ 0x75e2, 0x88cf, 0x88e1, 0x91cc, 0x96e2, 0x9678, 0x5f8b, 0x7387, 0x7acb, 0x844e, 0x63a0, 0x7565, 0x5289, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7c92, 0x9686, 0x7adc, 0x9f8d, 0x4fb6, 0x616e, 0x65c5, 0x865c, 0x4e86, 0x4eae, 0x50da, 0x4e21, 0x51cc, 0x5bee, 0x6599, 0x6881, 0x6dbc, 0x731f, 0x7642, 0x77ad, 0x7a1c, 0x7ce7, 0x826f, 0x8ad2, 0x907c, 0x91cf, 0x9675, 0x9818, 0x529b, 0x7dd1, 0x502b, 0x5398, 0x6797, 0x6dcb, 0x71d0, 0x7433, 0x81e8, 0x8f2a, 0x96a3, 0x9c57, 0x9e9f, 0x7460, 0x5841, 0x6d99, 0x7d2f, 0x985e, 0x4ee4, 0x4f36, 0x4f8b, 0x51b7, 0x52b1, 0x5dba, 0x601c, 0x73b2, 0x793c, 0x82d3, 0x9234, 0x96b7, 0x96f6, 0x970a, 0x9e97, 0x9f62, 0x66a6, 0x6b74, 0x5217, 0x52a3, 0x70c8, 0x88c2, 0x5ec9, 0x604b, 0x6190, 0x6f23, 0x7149, 0x7c3e, 0x7df4, 0x806f, /* 0x4f */ 0x84ee, 0x9023, 0x932c, 0x5442, 0x9b6f, 0x6ad3, 0x7089, 0x8cc2, 0x8def, 0x9732, 0x52b4, 0x5a41, 0x5eca, 0x5f04, 0x6717, 0x697c, 0x6994, 0x6d6a, 0x6f0f, 0x7262, 0x72fc, 0x7bed, 0x8001, 0x807e, 0x874b, 0x90ce, 0x516d, 0x9e93, 0x7984, 0x808b, 0x9332, 0x8ad6, 0x502d, 0x548c, 0x8a71, 0x6b6a, 0x8cc4, 0x8107, 0x60d1, 0x67a0, 0x9df2, 0x4e99, 0x4e98, 0x9c10, 0x8a6b, 0x85c1, 0x8568, 0x6900, 0x6e7e, 0x7897, 0x8155, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0x50 */ 0x5f0c, 0x4e10, 0x4e15, 0x4e2a, 0x4e31, 0x4e36, 0x4e3c, 0x4e3f, 0x4e42, 0x4e56, 0x4e58, 0x4e82, 0x4e85, 0x8c6b, 0x4e8a, 0x8212, 0x5f0d, 0x4e8e, 0x4e9e, 0x4e9f, 0x4ea0, 0x4ea2, 0x4eb0, 0x4eb3, 0x4eb6, 0x4ece, 0x4ecd, 0x4ec4, 0x4ec6, 0x4ec2, 0x4ed7, 0x4ede, 0x4eed, 0x4edf, 0x4ef7, 0x4f09, 0x4f5a, 0x4f30, 0x4f5b, 0x4f5d, 0x4f57, 0x4f47, 0x4f76, 0x4f88, 0x4f8f, 0x4f98, 0x4f7b, 0x4f69, 0x4f70, 0x4f91, 0x4f6f, 0x4f86, 0x4f96, 0x5118, 0x4fd4, 0x4fdf, 0x4fce, 0x4fd8, 0x4fdb, 0x4fd1, 0x4fda, 0x4fd0, 0x4fe4, 0x4fe5, 0x501a, 0x5028, 0x5014, 0x502a, 0x5025, 0x5005, 0x4f1c, 0x4ff6, 0x5021, 0x5029, 0x502c, 0x4ffe, 0x4fef, 0x5011, 0x5006, 0x5043, 0x5047, 0x6703, 0x5055, 0x5050, 0x5048, 0x505a, 0x5056, 0x506c, 0x5078, 0x5080, 0x509a, 0x5085, 0x50b4, 0x50b2, /* 0x51 */ 0x50c9, 0x50ca, 0x50b3, 0x50c2, 0x50d6, 0x50de, 0x50e5, 0x50ed, 0x50e3, 0x50ee, 0x50f9, 0x50f5, 0x5109, 0x5101, 0x5102, 0x5116, 0x5115, 0x5114, 0x511a, 0x5121, 0x513a, 0x5137, 0x513c, 0x513b, 0x513f, 0x5140, 0x5152, 0x514c, 0x5154, 0x5162, 0x7af8, 0x5169, 0x516a, 0x516e, 0x5180, 0x5182, 0x56d8, 0x518c, 0x5189, 0x518f, 0x5191, 0x5193, 0x5195, 0x5196, 0x51a4, 0x51a6, 0x51a2, 0x51a9, 0x51aa, 0x51ab, 0x51b3, 0x51b1, 0x51b2, 0x51b0, 0x51b5, 0x51bd, 0x51c5, 0x51c9, 0x51db, 0x51e0, 0x8655, 0x51e9, 0x51ed, 0x51f0, 0x51f5, 0x51fe, 0x5204, 0x520b, 0x5214, 0x520e, 0x5227, 0x522a, 0x522e, 0x5233, 0x5239, 0x524f, 0x5244, 0x524b, 0x524c, 0x525e, 0x5254, 0x526a, 0x5274, 0x5269, 0x5273, 0x527f, 0x527d, 0x528d, 0x5294, 0x5292, 0x5271, 0x5288, 0x5291, 0x8fa8, /* 0x52 */ 0x8fa7, 0x52ac, 0x52ad, 0x52bc, 0x52b5, 0x52c1, 0x52cd, 0x52d7, 0x52de, 0x52e3, 0x52e6, 0x98ed, 0x52e0, 0x52f3, 0x52f5, 0x52f8, 0x52f9, 0x5306, 0x5308, 0x7538, 0x530d, 0x5310, 0x530f, 0x5315, 0x531a, 0x5323, 0x532f, 0x5331, 0x5333, 0x5338, 0x5340, 0x5346, 0x5345, 0x4e17, 0x5349, 0x534d, 0x51d6, 0x535e, 0x5369, 0x536e, 0x5918, 0x537b, 0x5377, 0x5382, 0x5396, 0x53a0, 0x53a6, 0x53a5, 0x53ae, 0x53b0, 0x53b6, 0x53c3, 0x7c12, 0x96d9, 0x53df, 0x66fc, 0x71ee, 0x53ee, 0x53e8, 0x53ed, 0x53fa, 0x5401, 0x543d, 0x5440, 0x542c, 0x542d, 0x543c, 0x542e, 0x5436, 0x5429, 0x541d, 0x544e, 0x548f, 0x5475, 0x548e, 0x545f, 0x5471, 0x5477, 0x5470, 0x5492, 0x547b, 0x5480, 0x5476, 0x5484, 0x5490, 0x5486, 0x54c7, 0x54a2, 0x54b8, 0x54a5, 0x54ac, 0x54c4, 0x54c8, 0x54a8, /* 0x53 */ 0x54ab, 0x54c2, 0x54a4, 0x54be, 0x54bc, 0x54d8, 0x54e5, 0x54e6, 0x550f, 0x5514, 0x54fd, 0x54ee, 0x54ed, 0x54fa, 0x54e2, 0x5539, 0x5540, 0x5563, 0x554c, 0x552e, 0x555c, 0x5545, 0x5556, 0x5557, 0x5538, 0x5533, 0x555d, 0x5599, 0x5580, 0x54af, 0x558a, 0x559f, 0x557b, 0x557e, 0x5598, 0x559e, 0x55ae, 0x557c, 0x5583, 0x55a9, 0x5587, 0x55a8, 0x55da, 0x55c5, 0x55df, 0x55c4, 0x55dc, 0x55e4, 0x55d4, 0x5614, 0x55f7, 0x5616, 0x55fe, 0x55fd, 0x561b, 0x55f9, 0x564e, 0x5650, 0x71df, 0x5634, 0x5636, 0x5632, 0x5638, 0x566b, 0x5664, 0x562f, 0x566c, 0x566a, 0x5686, 0x5680, 0x568a, 0x56a0, 0x5694, 0x568f, 0x56a5, 0x56ae, 0x56b6, 0x56b4, 0x56c2, 0x56bc, 0x56c1, 0x56c3, 0x56c0, 0x56c8, 0x56ce, 0x56d1, 0x56d3, 0x56d7, 0x56ee, 0x56f9, 0x5700, 0x56ff, 0x5704, 0x5709, /* 0x54 */ 0x5708, 0x570b, 0x570d, 0x5713, 0x5718, 0x5716, 0x55c7, 0x571c, 0x5726, 0x5737, 0x5738, 0x574e, 0x573b, 0x5740, 0x574f, 0x5769, 0x57c0, 0x5788, 0x5761, 0x577f, 0x5789, 0x5793, 0x57a0, 0x57b3, 0x57a4, 0x57aa, 0x57b0, 0x57c3, 0x57c6, 0x57d4, 0x57d2, 0x57d3, 0x580a, 0x57d6, 0x57e3, 0x580b, 0x5819, 0x581d, 0x5872, 0x5821, 0x5862, 0x584b, 0x5870, 0x6bc0, 0x5852, 0x583d, 0x5879, 0x5885, 0x58b9, 0x589f, 0x58ab, 0x58ba, 0x58de, 0x58bb, 0x58b8, 0x58ae, 0x58c5, 0x58d3, 0x58d1, 0x58d7, 0x58d9, 0x58d8, 0x58e5, 0x58dc, 0x58e4, 0x58df, 0x58ef, 0x58fa, 0x58f9, 0x58fb, 0x58fc, 0x58fd, 0x5902, 0x590a, 0x5910, 0x591b, 0x68a6, 0x5925, 0x592c, 0x592d, 0x5932, 0x5938, 0x593e, 0x7ad2, 0x5955, 0x5950, 0x594e, 0x595a, 0x5958, 0x5962, 0x5960, 0x5967, 0x596c, 0x5969, /* 0x55 */ 0x5978, 0x5981, 0x599d, 0x4f5e, 0x4fab, 0x59a3, 0x59b2, 0x59c6, 0x59e8, 0x59dc, 0x598d, 0x59d9, 0x59da, 0x5a25, 0x5a1f, 0x5a11, 0x5a1c, 0x5a09, 0x5a1a, 0x5a40, 0x5a6c, 0x5a49, 0x5a35, 0x5a36, 0x5a62, 0x5a6a, 0x5a9a, 0x5abc, 0x5abe, 0x5acb, 0x5ac2, 0x5abd, 0x5ae3, 0x5ad7, 0x5ae6, 0x5ae9, 0x5ad6, 0x5afa, 0x5afb, 0x5b0c, 0x5b0b, 0x5b16, 0x5b32, 0x5ad0, 0x5b2a, 0x5b36, 0x5b3e, 0x5b43, 0x5b45, 0x5b40, 0x5b51, 0x5b55, 0x5b5a, 0x5b5b, 0x5b65, 0x5b69, 0x5b70, 0x5b73, 0x5b75, 0x5b78, 0x6588, 0x5b7a, 0x5b80, 0x5b83, 0x5ba6, 0x5bb8, 0x5bc3, 0x5bc7, 0x5bc9, 0x5bd4, 0x5bd0, 0x5be4, 0x5be6, 0x5be2, 0x5bde, 0x5be5, 0x5beb, 0x5bf0, 0x5bf6, 0x5bf3, 0x5c05, 0x5c07, 0x5c08, 0x5c0d, 0x5c13, 0x5c20, 0x5c22, 0x5c28, 0x5c38, 0x5c39, 0x5c41, 0x5c46, 0x5c4e, 0x5c53, /* 0x56 */ 0x5c50, 0x5c4f, 0x5b71, 0x5c6c, 0x5c6e, 0x4e62, 0x5c76, 0x5c79, 0x5c8c, 0x5c91, 0x5c94, 0x599b, 0x5cab, 0x5cbb, 0x5cb6, 0x5cbc, 0x5cb7, 0x5cc5, 0x5cbe, 0x5cc7, 0x5cd9, 0x5ce9, 0x5cfd, 0x5cfa, 0x5ced, 0x5d8c, 0x5cea, 0x5d0b, 0x5d15, 0x5d17, 0x5d5c, 0x5d1f, 0x5d1b, 0x5d11, 0x5d14, 0x5d22, 0x5d1a, 0x5d19, 0x5d18, 0x5d4c, 0x5d52, 0x5d4e, 0x5d4b, 0x5d6c, 0x5d73, 0x5d76, 0x5d87, 0x5d84, 0x5d82, 0x5da2, 0x5d9d, 0x5dac, 0x5dae, 0x5dbd, 0x5d90, 0x5db7, 0x5dbc, 0x5dc9, 0x5dcd, 0x5dd3, 0x5dd2, 0x5dd6, 0x5ddb, 0x5deb, 0x5df2, 0x5df5, 0x5e0b, 0x5e1a, 0x5e19, 0x5e11, 0x5e1b, 0x5e36, 0x5e37, 0x5e44, 0x5e43, 0x5e40, 0x5e4e, 0x5e57, 0x5e54, 0x5e5f, 0x5e62, 0x5e64, 0x5e47, 0x5e75, 0x5e76, 0x5e7a, 0x9ebc, 0x5e7f, 0x5ea0, 0x5ec1, 0x5ec2, 0x5ec8, 0x5ed0, 0x5ecf, /* 0x57 */ 0x5ed6, 0x5ee3, 0x5edd, 0x5eda, 0x5edb, 0x5ee2, 0x5ee1, 0x5ee8, 0x5ee9, 0x5eec, 0x5ef1, 0x5ef3, 0x5ef0, 0x5ef4, 0x5ef8, 0x5efe, 0x5f03, 0x5f09, 0x5f5d, 0x5f5c, 0x5f0b, 0x5f11, 0x5f16, 0x5f29, 0x5f2d, 0x5f38, 0x5f41, 0x5f48, 0x5f4c, 0x5f4e, 0x5f2f, 0x5f51, 0x5f56, 0x5f57, 0x5f59, 0x5f61, 0x5f6d, 0x5f73, 0x5f77, 0x5f83, 0x5f82, 0x5f7f, 0x5f8a, 0x5f88, 0x5f91, 0x5f87, 0x5f9e, 0x5f99, 0x5f98, 0x5fa0, 0x5fa8, 0x5fad, 0x5fbc, 0x5fd6, 0x5ffb, 0x5fe4, 0x5ff8, 0x5ff1, 0x5fdd, 0x60b3, 0x5fff, 0x6021, 0x6060, 0x6019, 0x6010, 0x6029, 0x600e, 0x6031, 0x601b, 0x6015, 0x602b, 0x6026, 0x600f, 0x603a, 0x605a, 0x6041, 0x606a, 0x6077, 0x605f, 0x604a, 0x6046, 0x604d, 0x6063, 0x6043, 0x6064, 0x6042, 0x606c, 0x606b, 0x6059, 0x6081, 0x608d, 0x60e7, 0x6083, 0x609a, /* 0x58 */ 0x6084, 0x609b, 0x6096, 0x6097, 0x6092, 0x60a7, 0x608b, 0x60e1, 0x60b8, 0x60e0, 0x60d3, 0x60b4, 0x5ff0, 0x60bd, 0x60c6, 0x60b5, 0x60d8, 0x614d, 0x6115, 0x6106, 0x60f6, 0x60f7, 0x6100, 0x60f4, 0x60fa, 0x6103, 0x6121, 0x60fb, 0x60f1, 0x610d, 0x610e, 0x6147, 0x613e, 0x6128, 0x6127, 0x614a, 0x613f, 0x613c, 0x612c, 0x6134, 0x613d, 0x6142, 0x6144, 0x6173, 0x6177, 0x6158, 0x6159, 0x615a, 0x616b, 0x6174, 0x616f, 0x6165, 0x6171, 0x615f, 0x615d, 0x6153, 0x6175, 0x6199, 0x6196, 0x6187, 0x61ac, 0x6194, 0x619a, 0x618a, 0x6191, 0x61ab, 0x61ae, 0x61cc, 0x61ca, 0x61c9, 0x61f7, 0x61c8, 0x61c3, 0x61c6, 0x61ba, 0x61cb, 0x7f79, 0x61cd, 0x61e6, 0x61e3, 0x61f6, 0x61fa, 0x61f4, 0x61ff, 0x61fd, 0x61fc, 0x61fe, 0x6200, 0x6208, 0x6209, 0x620d, 0x620c, 0x6214, 0x621b, /* 0x59 */ 0x621e, 0x6221, 0x622a, 0x622e, 0x6230, 0x6232, 0x6233, 0x6241, 0x624e, 0x625e, 0x6263, 0x625b, 0x6260, 0x6268, 0x627c, 0x6282, 0x6289, 0x627e, 0x6292, 0x6293, 0x6296, 0x62d4, 0x6283, 0x6294, 0x62d7, 0x62d1, 0x62bb, 0x62cf, 0x62ff, 0x62c6, 0x64d4, 0x62c8, 0x62dc, 0x62cc, 0x62ca, 0x62c2, 0x62c7, 0x629b, 0x62c9, 0x630c, 0x62ee, 0x62f1, 0x6327, 0x6302, 0x6308, 0x62ef, 0x62f5, 0x6350, 0x633e, 0x634d, 0x641c, 0x634f, 0x6396, 0x638e, 0x6380, 0x63ab, 0x6376, 0x63a3, 0x638f, 0x6389, 0x639f, 0x63b5, 0x636b, 0x6369, 0x63be, 0x63e9, 0x63c0, 0x63c6, 0x63e3, 0x63c9, 0x63d2, 0x63f6, 0x63c4, 0x6416, 0x6434, 0x6406, 0x6413, 0x6426, 0x6436, 0x651d, 0x6417, 0x6428, 0x640f, 0x6467, 0x646f, 0x6476, 0x644e, 0x652a, 0x6495, 0x6493, 0x64a5, 0x64a9, 0x6488, 0x64bc, /* 0x5a */ 0x64da, 0x64d2, 0x64c5, 0x64c7, 0x64bb, 0x64d8, 0x64c2, 0x64f1, 0x64e7, 0x8209, 0x64e0, 0x64e1, 0x62ac, 0x64e3, 0x64ef, 0x652c, 0x64f6, 0x64f4, 0x64f2, 0x64fa, 0x6500, 0x64fd, 0x6518, 0x651c, 0x6505, 0x6524, 0x6523, 0x652b, 0x6534, 0x6535, 0x6537, 0x6536, 0x6538, 0x754b, 0x6548, 0x6556, 0x6555, 0x654d, 0x6558, 0x655e, 0x655d, 0x6572, 0x6578, 0x6582, 0x6583, 0x8b8a, 0x659b, 0x659f, 0x65ab, 0x65b7, 0x65c3, 0x65c6, 0x65c1, 0x65c4, 0x65cc, 0x65d2, 0x65db, 0x65d9, 0x65e0, 0x65e1, 0x65f1, 0x6772, 0x660a, 0x6603, 0x65fb, 0x6773, 0x6635, 0x6636, 0x6634, 0x661c, 0x664f, 0x6644, 0x6649, 0x6641, 0x665e, 0x665d, 0x6664, 0x6667, 0x6668, 0x665f, 0x6662, 0x6670, 0x6683, 0x6688, 0x668e, 0x6689, 0x6684, 0x6698, 0x669d, 0x66c1, 0x66b9, 0x66c9, 0x66be, 0x66bc, /* 0x5b */ 0x66c4, 0x66b8, 0x66d6, 0x66da, 0x66e0, 0x663f, 0x66e6, 0x66e9, 0x66f0, 0x66f5, 0x66f7, 0x670f, 0x6716, 0x671e, 0x6726, 0x6727, 0x9738, 0x672e, 0x673f, 0x6736, 0x6741, 0x6738, 0x6737, 0x6746, 0x675e, 0x6760, 0x6759, 0x6763, 0x6764, 0x6789, 0x6770, 0x67a9, 0x677c, 0x676a, 0x678c, 0x678b, 0x67a6, 0x67a1, 0x6785, 0x67b7, 0x67ef, 0x67b4, 0x67ec, 0x67b3, 0x67e9, 0x67b8, 0x67e4, 0x67de, 0x67dd, 0x67e2, 0x67ee, 0x67b9, 0x67ce, 0x67c6, 0x67e7, 0x6a9c, 0x681e, 0x6846, 0x6829, 0x6840, 0x684d, 0x6832, 0x684e, 0x68b3, 0x682b, 0x6859, 0x6863, 0x6877, 0x687f, 0x689f, 0x688f, 0x68ad, 0x6894, 0x689d, 0x689b, 0x6883, 0x6aae, 0x68b9, 0x6874, 0x68b5, 0x68a0, 0x68ba, 0x690f, 0x688d, 0x687e, 0x6901, 0x68ca, 0x6908, 0x68d8, 0x6922, 0x6926, 0x68e1, 0x690c, 0x68cd, /* 0x5c */ 0x68d4, 0x68e7, 0x68d5, 0x6936, 0x6912, 0x6904, 0x68d7, 0x68e3, 0x6925, 0x68f9, 0x68e0, 0x68ef, 0x6928, 0x692a, 0x691a, 0x6923, 0x6921, 0x68c6, 0x6979, 0x6977, 0x695c, 0x6978, 0x696b, 0x6954, 0x697e, 0x696e, 0x6939, 0x6974, 0x693d, 0x6959, 0x6930, 0x6961, 0x695e, 0x695d, 0x6981, 0x696a, 0x69b2, 0x69ae, 0x69d0, 0x69bf, 0x69c1, 0x69d3, 0x69be, 0x69ce, 0x5be8, 0x69ca, 0x69dd, 0x69bb, 0x69c3, 0x69a7, 0x6a2e, 0x6991, 0x69a0, 0x699c, 0x6995, 0x69b4, 0x69de, 0x69e8, 0x6a02, 0x6a1b, 0x69ff, 0x6b0a, 0x69f9, 0x69f2, 0x69e7, 0x6a05, 0x69b1, 0x6a1e, 0x69ed, 0x6a14, 0x69eb, 0x6a0a, 0x6a12, 0x6ac1, 0x6a23, 0x6a13, 0x6a44, 0x6a0c, 0x6a72, 0x6a36, 0x6a78, 0x6a47, 0x6a62, 0x6a59, 0x6a66, 0x6a48, 0x6a38, 0x6a22, 0x6a90, 0x6a8d, 0x6aa0, 0x6a84, 0x6aa2, 0x6aa3, /* 0x5d */ 0x6a97, 0x8617, 0x6abb, 0x6ac3, 0x6ac2, 0x6ab8, 0x6ab3, 0x6aac, 0x6ade, 0x6ad1, 0x6adf, 0x6aaa, 0x6ada, 0x6aea, 0x6afb, 0x6b05, 0x8616, 0x6afa, 0x6b12, 0x6b16, 0x9b31, 0x6b1f, 0x6b38, 0x6b37, 0x76dc, 0x6b39, 0x98ee, 0x6b47, 0x6b43, 0x6b49, 0x6b50, 0x6b59, 0x6b54, 0x6b5b, 0x6b5f, 0x6b61, 0x6b78, 0x6b79, 0x6b7f, 0x6b80, 0x6b84, 0x6b83, 0x6b8d, 0x6b98, 0x6b95, 0x6b9e, 0x6ba4, 0x6baa, 0x6bab, 0x6baf, 0x6bb2, 0x6bb1, 0x6bb3, 0x6bb7, 0x6bbc, 0x6bc6, 0x6bcb, 0x6bd3, 0x6bdf, 0x6bec, 0x6beb, 0x6bf3, 0x6bef, 0x9ebe, 0x6c08, 0x6c13, 0x6c14, 0x6c1b, 0x6c24, 0x6c23, 0x6c5e, 0x6c55, 0x6c62, 0x6c6a, 0x6c82, 0x6c8d, 0x6c9a, 0x6c81, 0x6c9b, 0x6c7e, 0x6c68, 0x6c73, 0x6c92, 0x6c90, 0x6cc4, 0x6cf1, 0x6cd3, 0x6cbd, 0x6cd7, 0x6cc5, 0x6cdd, 0x6cae, 0x6cb1, 0x6cbe, /* 0x5e */ 0x6cba, 0x6cdb, 0x6cef, 0x6cd9, 0x6cea, 0x6d1f, 0x884d, 0x6d36, 0x6d2b, 0x6d3d, 0x6d38, 0x6d19, 0x6d35, 0x6d33, 0x6d12, 0x6d0c, 0x6d63, 0x6d93, 0x6d64, 0x6d5a, 0x6d79, 0x6d59, 0x6d8e, 0x6d95, 0x6fe4, 0x6d85, 0x6df9, 0x6e15, 0x6e0a, 0x6db5, 0x6dc7, 0x6de6, 0x6db8, 0x6dc6, 0x6dec, 0x6dde, 0x6dcc, 0x6de8, 0x6dd2, 0x6dc5, 0x6dfa, 0x6dd9, 0x6de4, 0x6dd5, 0x6dea, 0x6dee, 0x6e2d, 0x6e6e, 0x6e2e, 0x6e19, 0x6e72, 0x6e5f, 0x6e3e, 0x6e23, 0x6e6b, 0x6e2b, 0x6e76, 0x6e4d, 0x6e1f, 0x6e43, 0x6e3a, 0x6e4e, 0x6e24, 0x6eff, 0x6e1d, 0x6e38, 0x6e82, 0x6eaa, 0x6e98, 0x6ec9, 0x6eb7, 0x6ed3, 0x6ebd, 0x6eaf, 0x6ec4, 0x6eb2, 0x6ed4, 0x6ed5, 0x6e8f, 0x6ea5, 0x6ec2, 0x6e9f, 0x6f41, 0x6f11, 0x704c, 0x6eec, 0x6ef8, 0x6efe, 0x6f3f, 0x6ef2, 0x6f31, 0x6eef, 0x6f32, 0x6ecc, /* 0x5f */ 0x6f3e, 0x6f13, 0x6ef7, 0x6f86, 0x6f7a, 0x6f78, 0x6f81, 0x6f80, 0x6f6f, 0x6f5b, 0x6ff3, 0x6f6d, 0x6f82, 0x6f7c, 0x6f58, 0x6f8e, 0x6f91, 0x6fc2, 0x6f66, 0x6fb3, 0x6fa3, 0x6fa1, 0x6fa4, 0x6fb9, 0x6fc6, 0x6faa, 0x6fdf, 0x6fd5, 0x6fec, 0x6fd4, 0x6fd8, 0x6ff1, 0x6fee, 0x6fdb, 0x7009, 0x700b, 0x6ffa, 0x7011, 0x7001, 0x700f, 0x6ffe, 0x701b, 0x701a, 0x6f74, 0x701d, 0x7018, 0x701f, 0x7030, 0x703e, 0x7032, 0x7051, 0x7063, 0x7099, 0x7092, 0x70af, 0x70f1, 0x70ac, 0x70b8, 0x70b3, 0x70ae, 0x70df, 0x70cb, 0x70dd, 0x70d9, 0x7109, 0x70fd, 0x711c, 0x7119, 0x7165, 0x7155, 0x7188, 0x7166, 0x7162, 0x714c, 0x7156, 0x716c, 0x718f, 0x71fb, 0x7184, 0x7195, 0x71a8, 0x71ac, 0x71d7, 0x71b9, 0x71be, 0x71d2, 0x71c9, 0x71d4, 0x71ce, 0x71e0, 0x71ec, 0x71e7, 0x71f5, 0x71fc, /* 0x60 */ 0x71f9, 0x71ff, 0x720d, 0x7210, 0x721b, 0x7228, 0x722d, 0x722c, 0x7230, 0x7232, 0x723b, 0x723c, 0x723f, 0x7240, 0x7246, 0x724b, 0x7258, 0x7274, 0x727e, 0x7282, 0x7281, 0x7287, 0x7292, 0x7296, 0x72a2, 0x72a7, 0x72b9, 0x72b2, 0x72c3, 0x72c6, 0x72c4, 0x72ce, 0x72d2, 0x72e2, 0x72e0, 0x72e1, 0x72f9, 0x72f7, 0x500f, 0x7317, 0x730a, 0x731c, 0x7316, 0x731d, 0x7334, 0x732f, 0x7329, 0x7325, 0x733e, 0x734e, 0x734f, 0x9ed8, 0x7357, 0x736a, 0x7368, 0x7370, 0x7378, 0x7375, 0x737b, 0x737a, 0x73c8, 0x73b3, 0x73ce, 0x73bb, 0x73c0, 0x73e5, 0x73ee, 0x73de, 0x74a2, 0x7405, 0x746f, 0x7425, 0x73f8, 0x7432, 0x743a, 0x7455, 0x743f, 0x745f, 0x7459, 0x7441, 0x745c, 0x7469, 0x7470, 0x7463, 0x746a, 0x7476, 0x747e, 0x748b, 0x749e, 0x74a7, 0x74ca, 0x74cf, 0x74d4, 0x73f1, /* 0x61 */ 0x74e0, 0x74e3, 0x74e7, 0x74e9, 0x74ee, 0x74f2, 0x74f0, 0x74f1, 0x74f8, 0x74f7, 0x7504, 0x7503, 0x7505, 0x750c, 0x750e, 0x750d, 0x7515, 0x7513, 0x751e, 0x7526, 0x752c, 0x753c, 0x7544, 0x754d, 0x754a, 0x7549, 0x755b, 0x7546, 0x755a, 0x7569, 0x7564, 0x7567, 0x756b, 0x756d, 0x7578, 0x7576, 0x7586, 0x7587, 0x7574, 0x758a, 0x7589, 0x7582, 0x7594, 0x759a, 0x759d, 0x75a5, 0x75a3, 0x75c2, 0x75b3, 0x75c3, 0x75b5, 0x75bd, 0x75b8, 0x75bc, 0x75b1, 0x75cd, 0x75ca, 0x75d2, 0x75d9, 0x75e3, 0x75de, 0x75fe, 0x75ff, 0x75fc, 0x7601, 0x75f0, 0x75fa, 0x75f2, 0x75f3, 0x760b, 0x760d, 0x7609, 0x761f, 0x7627, 0x7620, 0x7621, 0x7622, 0x7624, 0x7634, 0x7630, 0x763b, 0x7647, 0x7648, 0x7646, 0x765c, 0x7658, 0x7661, 0x7662, 0x7668, 0x7669, 0x766a, 0x7667, 0x766c, 0x7670, /* 0x62 */ 0x7672, 0x7676, 0x7678, 0x767c, 0x7680, 0x7683, 0x7688, 0x768b, 0x768e, 0x7696, 0x7693, 0x7699, 0x769a, 0x76b0, 0x76b4, 0x76b8, 0x76b9, 0x76ba, 0x76c2, 0x76cd, 0x76d6, 0x76d2, 0x76de, 0x76e1, 0x76e5, 0x76e7, 0x76ea, 0x862f, 0x76fb, 0x7708, 0x7707, 0x7704, 0x7729, 0x7724, 0x771e, 0x7725, 0x7726, 0x771b, 0x7737, 0x7738, 0x7747, 0x775a, 0x7768, 0x776b, 0x775b, 0x7765, 0x777f, 0x777e, 0x7779, 0x778e, 0x778b, 0x7791, 0x77a0, 0x779e, 0x77b0, 0x77b6, 0x77b9, 0x77bf, 0x77bc, 0x77bd, 0x77bb, 0x77c7, 0x77cd, 0x77d7, 0x77da, 0x77dc, 0x77e3, 0x77ee, 0x77fc, 0x780c, 0x7812, 0x7926, 0x7820, 0x792a, 0x7845, 0x788e, 0x7874, 0x7886, 0x787c, 0x789a, 0x788c, 0x78a3, 0x78b5, 0x78aa, 0x78af, 0x78d1, 0x78c6, 0x78cb, 0x78d4, 0x78be, 0x78bc, 0x78c5, 0x78ca, 0x78ec, /* 0x63 */ 0x78e7, 0x78da, 0x78fd, 0x78f4, 0x7907, 0x7912, 0x7911, 0x7919, 0x792c, 0x792b, 0x7940, 0x7960, 0x7957, 0x795f, 0x795a, 0x7955, 0x7953, 0x797a, 0x797f, 0x798a, 0x799d, 0x79a7, 0x9f4b, 0x79aa, 0x79ae, 0x79b3, 0x79b9, 0x79ba, 0x79c9, 0x79d5, 0x79e7, 0x79ec, 0x79e1, 0x79e3, 0x7a08, 0x7a0d, 0x7a18, 0x7a19, 0x7a20, 0x7a1f, 0x7980, 0x7a31, 0x7a3b, 0x7a3e, 0x7a37, 0x7a43, 0x7a57, 0x7a49, 0x7a61, 0x7a62, 0x7a69, 0x9f9d, 0x7a70, 0x7a79, 0x7a7d, 0x7a88, 0x7a97, 0x7a95, 0x7a98, 0x7a96, 0x7aa9, 0x7ac8, 0x7ab0, 0x7ab6, 0x7ac5, 0x7ac4, 0x7abf, 0x9083, 0x7ac7, 0x7aca, 0x7acd, 0x7acf, 0x7ad5, 0x7ad3, 0x7ad9, 0x7ada, 0x7add, 0x7ae1, 0x7ae2, 0x7ae6, 0x7aed, 0x7af0, 0x7b02, 0x7b0f, 0x7b0a, 0x7b06, 0x7b33, 0x7b18, 0x7b19, 0x7b1e, 0x7b35, 0x7b28, 0x7b36, 0x7b50, /* 0x64 */ 0x7b7a, 0x7b04, 0x7b4d, 0x7b0b, 0x7b4c, 0x7b45, 0x7b75, 0x7b65, 0x7b74, 0x7b67, 0x7b70, 0x7b71, 0x7b6c, 0x7b6e, 0x7b9d, 0x7b98, 0x7b9f, 0x7b8d, 0x7b9c, 0x7b9a, 0x7b8b, 0x7b92, 0x7b8f, 0x7b5d, 0x7b99, 0x7bcb, 0x7bc1, 0x7bcc, 0x7bcf, 0x7bb4, 0x7bc6, 0x7bdd, 0x7be9, 0x7c11, 0x7c14, 0x7be6, 0x7be5, 0x7c60, 0x7c00, 0x7c07, 0x7c13, 0x7bf3, 0x7bf7, 0x7c17, 0x7c0d, 0x7bf6, 0x7c23, 0x7c27, 0x7c2a, 0x7c1f, 0x7c37, 0x7c2b, 0x7c3d, 0x7c4c, 0x7c43, 0x7c54, 0x7c4f, 0x7c40, 0x7c50, 0x7c58, 0x7c5f, 0x7c64, 0x7c56, 0x7c65, 0x7c6c, 0x7c75, 0x7c83, 0x7c90, 0x7ca4, 0x7cad, 0x7ca2, 0x7cab, 0x7ca1, 0x7ca8, 0x7cb3, 0x7cb2, 0x7cb1, 0x7cae, 0x7cb9, 0x7cbd, 0x7cc0, 0x7cc5, 0x7cc2, 0x7cd8, 0x7cd2, 0x7cdc, 0x7ce2, 0x9b3b, 0x7cef, 0x7cf2, 0x7cf4, 0x7cf6, 0x7cfa, 0x7d06, /* 0x65 */ 0x7d02, 0x7d1c, 0x7d15, 0x7d0a, 0x7d45, 0x7d4b, 0x7d2e, 0x7d32, 0x7d3f, 0x7d35, 0x7d46, 0x7d73, 0x7d56, 0x7d4e, 0x7d72, 0x7d68, 0x7d6e, 0x7d4f, 0x7d63, 0x7d93, 0x7d89, 0x7d5b, 0x7d8f, 0x7d7d, 0x7d9b, 0x7dba, 0x7dae, 0x7da3, 0x7db5, 0x7dc7, 0x7dbd, 0x7dab, 0x7e3d, 0x7da2, 0x7daf, 0x7ddc, 0x7db8, 0x7d9f, 0x7db0, 0x7dd8, 0x7ddd, 0x7de4, 0x7dde, 0x7dfb, 0x7df2, 0x7de1, 0x7e05, 0x7e0a, 0x7e23, 0x7e21, 0x7e12, 0x7e31, 0x7e1f, 0x7e09, 0x7e0b, 0x7e22, 0x7e46, 0x7e66, 0x7e3b, 0x7e35, 0x7e39, 0x7e43, 0x7e37, 0x7e32, 0x7e3a, 0x7e67, 0x7e5d, 0x7e56, 0x7e5e, 0x7e59, 0x7e5a, 0x7e79, 0x7e6a, 0x7e69, 0x7e7c, 0x7e7b, 0x7e83, 0x7dd5, 0x7e7d, 0x8fae, 0x7e7f, 0x7e88, 0x7e89, 0x7e8c, 0x7e92, 0x7e90, 0x7e93, 0x7e94, 0x7e96, 0x7e8e, 0x7e9b, 0x7e9c, 0x7f38, 0x7f3a, /* 0x66 */ 0x7f45, 0x7f4c, 0x7f4d, 0x7f4e, 0x7f50, 0x7f51, 0x7f55, 0x7f54, 0x7f58, 0x7f5f, 0x7f60, 0x7f68, 0x7f69, 0x7f67, 0x7f78, 0x7f82, 0x7f86, 0x7f83, 0x7f88, 0x7f87, 0x7f8c, 0x7f94, 0x7f9e, 0x7f9d, 0x7f9a, 0x7fa3, 0x7faf, 0x7fb2, 0x7fb9, 0x7fae, 0x7fb6, 0x7fb8, 0x8b71, 0x7fc5, 0x7fc6, 0x7fca, 0x7fd5, 0x7fd4, 0x7fe1, 0x7fe6, 0x7fe9, 0x7ff3, 0x7ff9, 0x98dc, 0x8006, 0x8004, 0x800b, 0x8012, 0x8018, 0x8019, 0x801c, 0x8021, 0x8028, 0x803f, 0x803b, 0x804a, 0x8046, 0x8052, 0x8058, 0x805a, 0x805f, 0x8062, 0x8068, 0x8073, 0x8072, 0x8070, 0x8076, 0x8079, 0x807d, 0x807f, 0x8084, 0x8086, 0x8085, 0x809b, 0x8093, 0x809a, 0x80ad, 0x5190, 0x80ac, 0x80db, 0x80e5, 0x80d9, 0x80dd, 0x80c4, 0x80da, 0x80d6, 0x8109, 0x80ef, 0x80f1, 0x811b, 0x8129, 0x8123, 0x812f, 0x814b, /* 0x67 */ 0x968b, 0x8146, 0x813e, 0x8153, 0x8151, 0x80fc, 0x8171, 0x816e, 0x8165, 0x8166, 0x8174, 0x8183, 0x8188, 0x818a, 0x8180, 0x8182, 0x81a0, 0x8195, 0x81a4, 0x81a3, 0x815f, 0x8193, 0x81a9, 0x81b0, 0x81b5, 0x81be, 0x81b8, 0x81bd, 0x81c0, 0x81c2, 0x81ba, 0x81c9, 0x81cd, 0x81d1, 0x81d9, 0x81d8, 0x81c8, 0x81da, 0x81df, 0x81e0, 0x81e7, 0x81fa, 0x81fb, 0x81fe, 0x8201, 0x8202, 0x8205, 0x8207, 0x820a, 0x820d, 0x8210, 0x8216, 0x8229, 0x822b, 0x8238, 0x8233, 0x8240, 0x8259, 0x8258, 0x825d, 0x825a, 0x825f, 0x8264, 0x8262, 0x8268, 0x826a, 0x826b, 0x822e, 0x8271, 0x8277, 0x8278, 0x827e, 0x828d, 0x8292, 0x82ab, 0x829f, 0x82bb, 0x82ac, 0x82e1, 0x82e3, 0x82df, 0x82d2, 0x82f4, 0x82f3, 0x82fa, 0x8393, 0x8303, 0x82fb, 0x82f9, 0x82de, 0x8306, 0x82dc, 0x8309, 0x82d9, /* 0x68 */ 0x8335, 0x8334, 0x8316, 0x8332, 0x8331, 0x8340, 0x8339, 0x8350, 0x8345, 0x832f, 0x832b, 0x8317, 0x8318, 0x8385, 0x839a, 0x83aa, 0x839f, 0x83a2, 0x8396, 0x8323, 0x838e, 0x8387, 0x838a, 0x837c, 0x83b5, 0x8373, 0x8375, 0x83a0, 0x8389, 0x83a8, 0x83f4, 0x8413, 0x83eb, 0x83ce, 0x83fd, 0x8403, 0x83d8, 0x840b, 0x83c1, 0x83f7, 0x8407, 0x83e0, 0x83f2, 0x840d, 0x8422, 0x8420, 0x83bd, 0x8438, 0x8506, 0x83fb, 0x846d, 0x842a, 0x843c, 0x855a, 0x8484, 0x8477, 0x846b, 0x84ad, 0x846e, 0x8482, 0x8469, 0x8446, 0x842c, 0x846f, 0x8479, 0x8435, 0x84ca, 0x8462, 0x84b9, 0x84bf, 0x849f, 0x84d9, 0x84cd, 0x84bb, 0x84da, 0x84d0, 0x84c1, 0x84c6, 0x84d6, 0x84a1, 0x8521, 0x84ff, 0x84f4, 0x8517, 0x8518, 0x852c, 0x851f, 0x8515, 0x8514, 0x84fc, 0x8540, 0x8563, 0x8558, 0x8548, /* 0x69 */ 0x8541, 0x8602, 0x854b, 0x8555, 0x8580, 0x85a4, 0x8588, 0x8591, 0x858a, 0x85a8, 0x856d, 0x8594, 0x859b, 0x85ea, 0x8587, 0x859c, 0x8577, 0x857e, 0x8590, 0x85c9, 0x85ba, 0x85cf, 0x85b9, 0x85d0, 0x85d5, 0x85dd, 0x85e5, 0x85dc, 0x85f9, 0x860a, 0x8613, 0x860b, 0x85fe, 0x85fa, 0x8606, 0x8622, 0x861a, 0x8630, 0x863f, 0x864d, 0x4e55, 0x8654, 0x865f, 0x8667, 0x8671, 0x8693, 0x86a3, 0x86a9, 0x86aa, 0x868b, 0x868c, 0x86b6, 0x86af, 0x86c4, 0x86c6, 0x86b0, 0x86c9, 0x8823, 0x86ab, 0x86d4, 0x86de, 0x86e9, 0x86ec, 0x86df, 0x86db, 0x86ef, 0x8712, 0x8706, 0x8708, 0x8700, 0x8703, 0x86fb, 0x8711, 0x8709, 0x870d, 0x86f9, 0x870a, 0x8734, 0x873f, 0x8737, 0x873b, 0x8725, 0x8729, 0x871a, 0x8760, 0x875f, 0x8778, 0x874c, 0x874e, 0x8774, 0x8757, 0x8768, 0x876e, 0x8759, /* 0x6a */ 0x8753, 0x8763, 0x876a, 0x8805, 0x87a2, 0x879f, 0x8782, 0x87af, 0x87cb, 0x87bd, 0x87c0, 0x87d0, 0x96d6, 0x87ab, 0x87c4, 0x87b3, 0x87c7, 0x87c6, 0x87bb, 0x87ef, 0x87f2, 0x87e0, 0x880f, 0x880d, 0x87fe, 0x87f6, 0x87f7, 0x880e, 0x87d2, 0x8811, 0x8816, 0x8815, 0x8822, 0x8821, 0x8831, 0x8836, 0x8839, 0x8827, 0x883b, 0x8844, 0x8842, 0x8852, 0x8859, 0x885e, 0x8862, 0x886b, 0x8881, 0x887e, 0x889e, 0x8875, 0x887d, 0x88b5, 0x8872, 0x8882, 0x8897, 0x8892, 0x88ae, 0x8899, 0x88a2, 0x888d, 0x88a4, 0x88b0, 0x88bf, 0x88b1, 0x88c3, 0x88c4, 0x88d4, 0x88d8, 0x88d9, 0x88dd, 0x88f9, 0x8902, 0x88fc, 0x88f4, 0x88e8, 0x88f2, 0x8904, 0x890c, 0x890a, 0x8913, 0x8943, 0x891e, 0x8925, 0x892a, 0x892b, 0x8941, 0x8944, 0x893b, 0x8936, 0x8938, 0x894c, 0x891d, 0x8960, 0x895e, /* 0x6b */ 0x8966, 0x8964, 0x896d, 0x896a, 0x896f, 0x8974, 0x8977, 0x897e, 0x8983, 0x8988, 0x898a, 0x8993, 0x8998, 0x89a1, 0x89a9, 0x89a6, 0x89ac, 0x89af, 0x89b2, 0x89ba, 0x89bd, 0x89bf, 0x89c0, 0x89da, 0x89dc, 0x89dd, 0x89e7, 0x89f4, 0x89f8, 0x8a03, 0x8a16, 0x8a10, 0x8a0c, 0x8a1b, 0x8a1d, 0x8a25, 0x8a36, 0x8a41, 0x8a5b, 0x8a52, 0x8a46, 0x8a48, 0x8a7c, 0x8a6d, 0x8a6c, 0x8a62, 0x8a85, 0x8a82, 0x8a84, 0x8aa8, 0x8aa1, 0x8a91, 0x8aa5, 0x8aa6, 0x8a9a, 0x8aa3, 0x8ac4, 0x8acd, 0x8ac2, 0x8ada, 0x8aeb, 0x8af3, 0x8ae7, 0x8ae4, 0x8af1, 0x8b14, 0x8ae0, 0x8ae2, 0x8af7, 0x8ade, 0x8adb, 0x8b0c, 0x8b07, 0x8b1a, 0x8ae1, 0x8b16, 0x8b10, 0x8b17, 0x8b20, 0x8b33, 0x97ab, 0x8b26, 0x8b2b, 0x8b3e, 0x8b28, 0x8b41, 0x8b4c, 0x8b4f, 0x8b4e, 0x8b49, 0x8b56, 0x8b5b, 0x8b5a, 0x8b6b, /* 0x6c */ 0x8b5f, 0x8b6c, 0x8b6f, 0x8b74, 0x8b7d, 0x8b80, 0x8b8c, 0x8b8e, 0x8b92, 0x8b93, 0x8b96, 0x8b99, 0x8b9a, 0x8c3a, 0x8c41, 0x8c3f, 0x8c48, 0x8c4c, 0x8c4e, 0x8c50, 0x8c55, 0x8c62, 0x8c6c, 0x8c78, 0x8c7a, 0x8c82, 0x8c89, 0x8c85, 0x8c8a, 0x8c8d, 0x8c8e, 0x8c94, 0x8c7c, 0x8c98, 0x621d, 0x8cad, 0x8caa, 0x8cbd, 0x8cb2, 0x8cb3, 0x8cae, 0x8cb6, 0x8cc8, 0x8cc1, 0x8ce4, 0x8ce3, 0x8cda, 0x8cfd, 0x8cfa, 0x8cfb, 0x8d04, 0x8d05, 0x8d0a, 0x8d07, 0x8d0f, 0x8d0d, 0x8d10, 0x9f4e, 0x8d13, 0x8ccd, 0x8d14, 0x8d16, 0x8d67, 0x8d6d, 0x8d71, 0x8d73, 0x8d81, 0x8d99, 0x8dc2, 0x8dbe, 0x8dba, 0x8dcf, 0x8dda, 0x8dd6, 0x8dcc, 0x8ddb, 0x8dcb, 0x8dea, 0x8deb, 0x8ddf, 0x8de3, 0x8dfc, 0x8e08, 0x8e09, 0x8dff, 0x8e1d, 0x8e1e, 0x8e10, 0x8e1f, 0x8e42, 0x8e35, 0x8e30, 0x8e34, 0x8e4a, /* 0x6d */ 0x8e47, 0x8e49, 0x8e4c, 0x8e50, 0x8e48, 0x8e59, 0x8e64, 0x8e60, 0x8e2a, 0x8e63, 0x8e55, 0x8e76, 0x8e72, 0x8e7c, 0x8e81, 0x8e87, 0x8e85, 0x8e84, 0x8e8b, 0x8e8a, 0x8e93, 0x8e91, 0x8e94, 0x8e99, 0x8eaa, 0x8ea1, 0x8eac, 0x8eb0, 0x8ec6, 0x8eb1, 0x8ebe, 0x8ec5, 0x8ec8, 0x8ecb, 0x8edb, 0x8ee3, 0x8efc, 0x8efb, 0x8eeb, 0x8efe, 0x8f0a, 0x8f05, 0x8f15, 0x8f12, 0x8f19, 0x8f13, 0x8f1c, 0x8f1f, 0x8f1b, 0x8f0c, 0x8f26, 0x8f33, 0x8f3b, 0x8f39, 0x8f45, 0x8f42, 0x8f3e, 0x8f4c, 0x8f49, 0x8f46, 0x8f4e, 0x8f57, 0x8f5c, 0x8f62, 0x8f63, 0x8f64, 0x8f9c, 0x8f9f, 0x8fa3, 0x8fad, 0x8faf, 0x8fb7, 0x8fda, 0x8fe5, 0x8fe2, 0x8fea, 0x8fef, 0x9087, 0x8ff4, 0x9005, 0x8ff9, 0x8ffa, 0x9011, 0x9015, 0x9021, 0x900d, 0x901e, 0x9016, 0x900b, 0x9027, 0x9036, 0x9035, 0x9039, 0x8ff8, /* 0x6e */ 0x904f, 0x9050, 0x9051, 0x9052, 0x900e, 0x9049, 0x903e, 0x9056, 0x9058, 0x905e, 0x9068, 0x906f, 0x9076, 0x96a8, 0x9072, 0x9082, 0x907d, 0x9081, 0x9080, 0x908a, 0x9089, 0x908f, 0x90a8, 0x90af, 0x90b1, 0x90b5, 0x90e2, 0x90e4, 0x6248, 0x90db, 0x9102, 0x9112, 0x9119, 0x9132, 0x9130, 0x914a, 0x9156, 0x9158, 0x9163, 0x9165, 0x9169, 0x9173, 0x9172, 0x918b, 0x9189, 0x9182, 0x91a2, 0x91ab, 0x91af, 0x91aa, 0x91b5, 0x91b4, 0x91ba, 0x91c0, 0x91c1, 0x91c9, 0x91cb, 0x91d0, 0x91d6, 0x91df, 0x91e1, 0x91db, 0x91fc, 0x91f5, 0x91f6, 0x921e, 0x91ff, 0x9214, 0x922c, 0x9215, 0x9211, 0x925e, 0x9257, 0x9245, 0x9249, 0x9264, 0x9248, 0x9295, 0x923f, 0x924b, 0x9250, 0x929c, 0x9296, 0x9293, 0x929b, 0x925a, 0x92cf, 0x92b9, 0x92b7, 0x92e9, 0x930f, 0x92fa, 0x9344, 0x932e, /* 0x6f */ 0x9319, 0x9322, 0x931a, 0x9323, 0x933a, 0x9335, 0x933b, 0x935c, 0x9360, 0x937c, 0x936e, 0x9356, 0x93b0, 0x93ac, 0x93ad, 0x9394, 0x93b9, 0x93d6, 0x93d7, 0x93e8, 0x93e5, 0x93d8, 0x93c3, 0x93dd, 0x93d0, 0x93c8, 0x93e4, 0x941a, 0x9414, 0x9413, 0x9403, 0x9407, 0x9410, 0x9436, 0x942b, 0x9435, 0x9421, 0x943a, 0x9441, 0x9452, 0x9444, 0x945b, 0x9460, 0x9462, 0x945e, 0x946a, 0x9229, 0x9470, 0x9475, 0x9477, 0x947d, 0x945a, 0x947c, 0x947e, 0x9481, 0x947f, 0x9582, 0x9587, 0x958a, 0x9594, 0x9596, 0x9598, 0x9599, 0x95a0, 0x95a8, 0x95a7, 0x95ad, 0x95bc, 0x95bb, 0x95b9, 0x95be, 0x95ca, 0x6ff6, 0x95c3, 0x95cd, 0x95cc, 0x95d5, 0x95d4, 0x95d6, 0x95dc, 0x95e1, 0x95e5, 0x95e2, 0x9621, 0x9628, 0x962e, 0x962f, 0x9642, 0x964c, 0x964f, 0x964b, 0x9677, 0x965c, 0x965e, /* 0x70 */ 0x965d, 0x965f, 0x9666, 0x9672, 0x966c, 0x968d, 0x9698, 0x9695, 0x9697, 0x96aa, 0x96a7, 0x96b1, 0x96b2, 0x96b0, 0x96b4, 0x96b6, 0x96b8, 0x96b9, 0x96ce, 0x96cb, 0x96c9, 0x96cd, 0x894d, 0x96dc, 0x970d, 0x96d5, 0x96f9, 0x9704, 0x9706, 0x9708, 0x9713, 0x970e, 0x9711, 0x970f, 0x9716, 0x9719, 0x9724, 0x972a, 0x9730, 0x9739, 0x973d, 0x973e, 0x9744, 0x9746, 0x9748, 0x9742, 0x9749, 0x975c, 0x9760, 0x9764, 0x9766, 0x9768, 0x52d2, 0x976b, 0x9771, 0x9779, 0x9785, 0x977c, 0x9781, 0x977a, 0x9786, 0x978b, 0x978f, 0x9790, 0x979c, 0x97a8, 0x97a6, 0x97a3, 0x97b3, 0x97b4, 0x97c3, 0x97c6, 0x97c8, 0x97cb, 0x97dc, 0x97ed, 0x9f4f, 0x97f2, 0x7adf, 0x97f6, 0x97f5, 0x980f, 0x980c, 0x9838, 0x9824, 0x9821, 0x9837, 0x983d, 0x9846, 0x984f, 0x984b, 0x986b, 0x986f, 0x9870, /* 0x71 */ 0x9871, 0x9874, 0x9873, 0x98aa, 0x98af, 0x98b1, 0x98b6, 0x98c4, 0x98c3, 0x98c6, 0x98e9, 0x98eb, 0x9903, 0x9909, 0x9912, 0x9914, 0x9918, 0x9921, 0x991d, 0x991e, 0x9924, 0x9920, 0x992c, 0x992e, 0x993d, 0x993e, 0x9942, 0x9949, 0x9945, 0x9950, 0x994b, 0x9951, 0x9952, 0x994c, 0x9955, 0x9997, 0x9998, 0x99a5, 0x99ad, 0x99ae, 0x99bc, 0x99df, 0x99db, 0x99dd, 0x99d8, 0x99d1, 0x99ed, 0x99ee, 0x99f1, 0x99f2, 0x99fb, 0x99f8, 0x9a01, 0x9a0f, 0x9a05, 0x99e2, 0x9a19, 0x9a2b, 0x9a37, 0x9a45, 0x9a42, 0x9a40, 0x9a43, 0x9a3e, 0x9a55, 0x9a4d, 0x9a5b, 0x9a57, 0x9a5f, 0x9a62, 0x9a65, 0x9a64, 0x9a69, 0x9a6b, 0x9a6a, 0x9aad, 0x9ab0, 0x9abc, 0x9ac0, 0x9acf, 0x9ad1, 0x9ad3, 0x9ad4, 0x9ade, 0x9adf, 0x9ae2, 0x9ae3, 0x9ae6, 0x9aef, 0x9aeb, 0x9aee, 0x9af4, 0x9af1, 0x9af7, /* 0x72 */ 0x9afb, 0x9b06, 0x9b18, 0x9b1a, 0x9b1f, 0x9b22, 0x9b23, 0x9b25, 0x9b27, 0x9b28, 0x9b29, 0x9b2a, 0x9b2e, 0x9b2f, 0x9b32, 0x9b44, 0x9b43, 0x9b4f, 0x9b4d, 0x9b4e, 0x9b51, 0x9b58, 0x9b74, 0x9b93, 0x9b83, 0x9b91, 0x9b96, 0x9b97, 0x9b9f, 0x9ba0, 0x9ba8, 0x9bb4, 0x9bc0, 0x9bca, 0x9bb9, 0x9bc6, 0x9bcf, 0x9bd1, 0x9bd2, 0x9be3, 0x9be2, 0x9be4, 0x9bd4, 0x9be1, 0x9c3a, 0x9bf2, 0x9bf1, 0x9bf0, 0x9c15, 0x9c14, 0x9c09, 0x9c13, 0x9c0c, 0x9c06, 0x9c08, 0x9c12, 0x9c0a, 0x9c04, 0x9c2e, 0x9c1b, 0x9c25, 0x9c24, 0x9c21, 0x9c30, 0x9c47, 0x9c32, 0x9c46, 0x9c3e, 0x9c5a, 0x9c60, 0x9c67, 0x9c76, 0x9c78, 0x9ce7, 0x9cec, 0x9cf0, 0x9d09, 0x9d08, 0x9ceb, 0x9d03, 0x9d06, 0x9d2a, 0x9d26, 0x9daf, 0x9d23, 0x9d1f, 0x9d44, 0x9d15, 0x9d12, 0x9d41, 0x9d3f, 0x9d3e, 0x9d46, 0x9d48, /* 0x73 */ 0x9d5d, 0x9d5e, 0x9d64, 0x9d51, 0x9d50, 0x9d59, 0x9d72, 0x9d89, 0x9d87, 0x9dab, 0x9d6f, 0x9d7a, 0x9d9a, 0x9da4, 0x9da9, 0x9db2, 0x9dc4, 0x9dc1, 0x9dbb, 0x9db8, 0x9dba, 0x9dc6, 0x9dcf, 0x9dc2, 0x9dd9, 0x9dd3, 0x9df8, 0x9de6, 0x9ded, 0x9def, 0x9dfd, 0x9e1a, 0x9e1b, 0x9e1e, 0x9e75, 0x9e79, 0x9e7d, 0x9e81, 0x9e88, 0x9e8b, 0x9e8c, 0x9e92, 0x9e95, 0x9e91, 0x9e9d, 0x9ea5, 0x9ea9, 0x9eb8, 0x9eaa, 0x9ead, 0x9761, 0x9ecc, 0x9ece, 0x9ecf, 0x9ed0, 0x9ed4, 0x9edc, 0x9ede, 0x9edd, 0x9ee0, 0x9ee5, 0x9ee8, 0x9eef, 0x9ef4, 0x9ef6, 0x9ef7, 0x9ef9, 0x9efb, 0x9efc, 0x9efd, 0x9f07, 0x9f08, 0x76b7, 0x9f15, 0x9f21, 0x9f2c, 0x9f3e, 0x9f4a, 0x9f52, 0x9f54, 0x9f63, 0x9f5f, 0x9f60, 0x9f61, 0x9f66, 0x9f67, 0x9f6c, 0x9f6a, 0x9f77, 0x9f72, 0x9f76, 0x9f95, 0x9f9c, 0x9fa0, /* 0x74 */ 0x582f, 0x69c7, 0x9059, 0x7464, 0x51dc, 0x7199, }; static int jisx0208_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c1 = (s[0] & 0x7F); if ((c1 >= 0x21 && c1 <= 0x28) || (c1 >= 0x30 && c1 <= 0x74)) { if (n >= 2) { unsigned char c2 = (s[1] & 0x7F); if (c2 >= 0x21 && c2 < 0x7f) { unsigned int i = 94 * (c1 - 0x21) + (c2 - 0x21); unsigned short wc = 0xfffd; if (i < 1410) { if (i < 690) wc = jisx0208_2uni_page21[i]; } else { if (i < 7808) wc = jisx0208_2uni_page30[i-1410]; } if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 2; } } return RET_ILSEQ; } return RET_TOOFEW(0); } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned short jisx0208_2charset[6879] = { 0x2140, 0x2171, 0x2172, 0x2178, 0x212f, 0x224c, 0x216b, 0x215e, 0x212d, 0x2279, 0x215f, 0x2160, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, 0x2627, 0x2628, 0x2629, 0x262a, 0x262b, 0x262c, 0x262d, 0x262e, 0x262f, 0x2630, 0x2631, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636, 0x2637, 0x2638, 0x2641, 0x2642, 0x2643, 0x2644, 0x2645, 0x2646, 0x2647, 0x2648, 0x2649, 0x264a, 0x264b, 0x264c, 0x264d, 0x264e, 0x264f, 0x2650, 0x2651, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656, 0x2657, 0x2658, 0x2727, 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2728, 0x2729, 0x272a, 0x272b, 0x272c, 0x272d, 0x272e, 0x272f, 0x2730, 0x2731, 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737, 0x2738, 0x2739, 0x273a, 0x273b, 0x273c, 0x273d, 0x273e, 0x273f, 0x2740, 0x2741, 0x2751, 0x2752, 0x2753, 0x2754, 0x2755, 0x2756, 0x2758, 0x2759, 0x275a, 0x275b, 0x275c, 0x275d, 0x275e, 0x275f, 0x2760, 0x2761, 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x2768, 0x2769, 0x276a, 0x276b, 0x276c, 0x276d, 0x276e, 0x276f, 0x2770, 0x2771, 0x2757, 0x213e, 0x213d, 0x2142, 0x2146, 0x2147, 0x2148, 0x2149, 0x2277, 0x2278, 0x2145, 0x2144, 0x2273, 0x216c, 0x216d, 0x2228, 0x216e, 0x2272, 0x222b, 0x222c, 0x222a, 0x222d, 0x224d, 0x224e, 0x224f, 0x225f, 0x2250, 0x2260, 0x223a, 0x223b, 0x215d, 0x2265, 0x2267, 0x2167, 0x225c, 0x224a, 0x224b, 0x2241, 0x2240, 0x2269, 0x226a, 0x2168, 0x2268, 0x2266, 0x2262, 0x2162, 0x2261, 0x2165, 0x2166, 0x2263, 0x2264, 0x223e, 0x223f, 0x223c, 0x223d, 0x225d, 0x225e, 0x2821, 0x282c, 0x2822, 0x282d, 0x2823, 0x282e, 0x2824, 0x282f, 0x2826, 0x2831, 0x2825, 0x2830, 0x2827, 0x283c, 0x2837, 0x2832, 0x2829, 0x283e, 0x2839, 0x2834, 0x2828, 0x2838, 0x283d, 0x2833, 0x282a, 0x283a, 0x283f, 0x2835, 0x282b, 0x283b, 0x2840, 0x2836, 0x2223, 0x2222, 0x2225, 0x2224, 0x2227, 0x2226, 0x2221, 0x217e, 0x217b, 0x217d, 0x217c, 0x227e, 0x217a, 0x2179, 0x216a, 0x2169, 0x2276, 0x2275, 0x2274, 0x2121, 0x2122, 0x2123, 0x2137, 0x2139, 0x213a, 0x213b, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, 0x215b, 0x2229, 0x222e, 0x214c, 0x214d, 0x2141, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427, 0x2428, 0x2429, 0x242a, 0x242b, 0x242c, 0x242d, 0x242e, 0x242f, 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, 0x2438, 0x2439, 0x243a, 0x243b, 0x243c, 0x243d, 0x243e, 0x243f, 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, 0x2448, 0x2449, 0x244a, 0x244b, 0x244c, 0x244d, 0x244e, 0x244f, 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, 0x2458, 0x2459, 0x245a, 0x245b, 0x245c, 0x245d, 0x245e, 0x245f, 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x246a, 0x246b, 0x246c, 0x246d, 0x246e, 0x246f, 0x2470, 0x2471, 0x2472, 0x2473, 0x212b, 0x212c, 0x2135, 0x2136, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, 0x2528, 0x2529, 0x252a, 0x252b, 0x252c, 0x252d, 0x252e, 0x252f, 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, 0x2538, 0x2539, 0x253a, 0x253b, 0x253c, 0x253d, 0x253e, 0x253f, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d, 0x254e, 0x254f, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e, 0x255f, 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x256d, 0x256e, 0x256f, 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0x2126, 0x213c, 0x2133, 0x2134, 0x306c, 0x437a, 0x3c37, 0x4b7c, 0x3e66, 0x3b30, 0x3e65, 0x323c, 0x4954, 0x4d3f, 0x5022, 0x312f, 0x336e, 0x5023, 0x4024, 0x5242, 0x3556, 0x4a3a, 0x3e67, 0x4e3e, 0x4a42, 0x5024, 0x4366, 0x5025, 0x367a, 0x5026, 0x345d, 0x4330, 0x3c67, 0x5027, 0x5028, 0x5029, 0x4735, 0x3557, 0x4737, 0x4663, 0x3843, 0x4b33, 0x6949, 0x502a, 0x3e68, 0x502b, 0x3235, 0x3665, 0x3870, 0x4c69, 0x5626, 0x4d70, 0x467d, 0x3425, 0x3535, 0x502c, 0x502d, 0x4e3b, 0x4d3d, 0x4168, 0x502f, 0x3b76, 0x4673, 0x5032, 0x313e, 0x385f, 0x385e, 0x3066, 0x4f4b, 0x4f4a, 0x3a33, 0x3021, 0x5033, 0x5034, 0x5035, 0x4b34, 0x5036, 0x3872, 0x3067, 0x4b72, 0x357c, 0x357d, 0x357e, 0x4462, 0x4e3c, 0x5037, 0x5038, 0x5039, 0x3f4d, 0x3d3a, 0x3f4e, 0x503e, 0x503c, 0x503d, 0x3558, 0x3a23, 0x3270, 0x503b, 0x503a, 0x4a29, 0x3b46, 0x3b45, 0x423e, 0x503f, 0x4955, 0x4067, 0x2138, 0x5040, 0x5042, 0x4265, 0x4e61, 0x304a, 0x5041, 0x323e, 0x3644, 0x4367, 0x376f, 0x5043, 0x4724, 0x346b, 0x5044, 0x304b, 0x3860, 0x346c, 0x497a, 0x4832, 0x3559, 0x3271, 0x5067, 0x4541, 0x476c, 0x5046, 0x483c, 0x4e62, 0x3f2d, 0x3b47, 0x3b77, 0x3240, 0x4451, 0x4322, 0x504a, 0x304c, 0x4463, 0x3d3b, 0x3a34, 0x4d24, 0x424e, 0x323f, 0x5049, 0x4d3e, 0x5045, 0x5047, 0x3a6e, 0x5048, 0x5524, 0x5050, 0x5053, 0x5051, 0x3242, 0x4a3b, 0x504b, 0x504f, 0x3873, 0x3b48, 0x3426, 0x5054, 0x504c, 0x4e63, 0x3b78, 0x504d, 0x5052, 0x5055, 0x504e, 0x3621, 0x304d, 0x3622, 0x3241, 0x5525, 0x4b79, 0x496e, 0x3874, 0x3f2f, 0x4e37, 0x4a58, 0x3738, 0x4225, 0x3264, 0x3d53, 0x5059, 0x505e, 0x505c, 0x5057, 0x422f, 0x505a, 0x505d, 0x505b, 0x4a5d, 0x5058, 0x3f2e, 0x4b73, 0x505f, 0x5060, 0x3d24, 0x506d, 0x4750, 0x4936, 0x5068, 0x4a70, 0x3236, 0x506c, 0x5066, 0x506f, 0x4152, 0x3844, 0x475c, 0x6047, 0x506e, 0x455d, 0x5063, 0x3876, 0x3875, 0x5061, 0x3c5a, 0x5069, 0x4a6f, 0x434d, 0x5065, 0x3771, 0x5062, 0x506a, 0x5064, 0x4e51, 0x506b, 0x4f41, 0x3666, 0x3770, 0x5070, 0x5071, 0x5075, 0x304e, 0x4a50, 0x5074, 0x5073, 0x5077, 0x5076, 0x4464, 0x3772, 0x5078, 0x3c45, 0x4226, 0x4465, 0x3676, 0x5079, 0x3536, 0x507a, 0x507c, 0x4b35, 0x3766, 0x3b31, 0x4877, 0x507b, 0x3a45, 0x4d43, 0x507e, 0x5123, 0x507d, 0x3a44, 0x3d7d, 0x3739, 0x5124, 0x364f, 0x5121, 0x5122, 0x462f, 0x417c, 0x3623, 0x4b4d, 0x5125, 0x4e3d, 0x5126, 0x5129, 0x5127, 0x414e, 0x5128, 0x512a, 0x512c, 0x512b, 0x4a48, 0x3537, 0x512e, 0x512f, 0x322f, 0x512d, 0x3c74, 0x5132, 0x5131, 0x5130, 0x5056, 0x5133, 0x3d7e, 0x5134, 0x4d25, 0x4c59, 0x5136, 0x5135, 0x5138, 0x5137, 0x5139, 0x513a, 0x3074, 0x3835, 0x373b, 0x3d3c, 0x437b, 0x3624, 0x4068, 0x3877, 0x396e, 0x513c, 0x4c48, 0x4546, 0x3b79, 0x513b, 0x513d, 0x455e, 0x3375, 0x513e, 0x467e, 0x4134, 0x5140, 0x5141, 0x482c, 0x3878, 0x4f3b, 0x5142, 0x3626, 0x4a3c, 0x4236, 0x3671, 0x4535, 0x3773, 0x5143, 0x5144, 0x4662, 0x315f, 0x5147, 0x3a7d, 0x5146, 0x3a46, 0x5148, 0x666e, 0x5149, 0x4b41, 0x514a, 0x514b, 0x514c, 0x3e69, 0x3c4c, 0x3427, 0x514f, 0x514d, 0x4c3d, 0x514e, 0x495a, 0x5150, 0x5151, 0x5152, 0x455f, 0x5156, 0x5154, 0x5155, 0x5153, 0x3a63, 0x5157, 0x4c6a, 0x4e64, 0x5158, 0x4028, 0x5159, 0x3d5a, 0x515a, 0x437c, 0x4e3f, 0x4560, 0x5245, 0x515b, 0x7425, 0x3645, 0x515c, 0x4b5e, 0x3d68, 0x427c, 0x515e, 0x4664, 0x515f, 0x5160, 0x332e, 0x5161, 0x3627, 0x464c, 0x317a, 0x3d50, 0x4821, 0x5162, 0x4561, 0x3f4f, 0x5163, 0x4a2c, 0x405a, 0x3422, 0x3429, 0x5164, 0x5166, 0x373a, 0x5165, 0x4e73, 0x3d69, 0x483d, 0x4a4c, 0x5167, 0x4d78, 0x5168, 0x5169, 0x457e, 0x516a, 0x4029, 0x3a7e, 0x3774, 0x516b, 0x3b49, 0x396f, 0x4466, 0x516d, 0x4227, 0x3a6f, 0x516e, 0x516f, 0x4130, 0x516c, 0x5171, 0x4b36, 0x3964, 0x5170, 0x3775, 0x3a5e, 0x476d, 0x5174, 0x5172, 0x497b, 0x3e6a, 0x517b, 0x3364, 0x5175, 0x5173, 0x414f, 0x5177, 0x5176, 0x3344, 0x3760, 0x517c, 0x4e2d, 0x5178, 0x517d, 0x517a, 0x5179, 0x4e4f, 0x3879, 0x3243, 0x4e74, 0x3d75, 0x4558, 0x3965, 0x5222, 0x5223, 0x4e65, 0x4f2b, 0x5225, 0x387a, 0x5224, 0x332f, 0x5226, 0x4b56, 0x443c, 0x4d26, 0x4a59, 0x5227, 0x7055, 0x4630, 0x5228, 0x342a, 0x4c33, 0x3e21, 0x5229, 0x4a67, 0x522d, 0x402a, 0x522a, 0x3650, 0x522b, 0x342b, 0x372e, 0x522e, 0x522f, 0x5230, 0x5231, 0x3c5b, 0x387b, 0x4c5e, 0x4c68, 0x4677, 0x4a71, 0x5232, 0x5233, 0x5235, 0x5237, 0x5236, 0x5238, 0x323d, 0x4b4c, 0x3a7c, 0x5239, 0x4159, 0x3e22, 0x3629, 0x523a, 0x485b, 0x523b, 0x523c, 0x523d, 0x523e, 0x4924, 0x3668, 0x3065, 0x463f, 0x523f, 0x3d3d, 0x4069, 0x5241, 0x5240, 0x3e23, 0x3861, 0x5243, 0x483e, 0x5244, 0x485c, 0x4234, 0x426e, 0x3628, 0x466e, 0x4331, 0x476e, 0x4b4e, 0x5246, 0x406a, 0x3735, 0x5247, 0x5248, 0x312c, 0x3075, 0x346d, 0x4228, 0x3551, 0x4d71, 0x524b, 0x3237, 0x524a, 0x362a, 0x524c, 0x4c71, 0x524d, 0x4e52, 0x387c, 0x3836, 0x524e, 0x5250, 0x524f, 0x3f5f, 0x3139, 0x315e, 0x5251, 0x5252, 0x3837, 0x5253, 0x356e, 0x3b32, 0x5254, 0x4b74, 0x3a35, 0x355a, 0x4d27, 0x4150, 0x483f, 0x3c7d, 0x3d47, 0x3c68, 0x3c75, 0x3d76, 0x4840, 0x5257, 0x3143, 0x4151, 0x387d, 0x3845, 0x3667, 0x525b, 0x4321, 0x427e, 0x362b, 0x3e24, 0x525c, 0x525a, 0x3244, 0x4266, 0x3c38, 0x3b4b, 0x3126, 0x3370, 0x3966, 0x3b4a, 0x525d, 0x525e, 0x3549, 0x3346, 0x3967, 0x3548, 0x445f, 0x3125, 0x4631, 0x4c3e, 0x3921, 0x4d79, 0x4547, 0x387e, 0x372f, 0x5267, 0x3663, 0x4b4a, 0x485d, 0x5266, 0x345e, 0x5261, 0x5262, 0x5264, 0x5265, 0x355b, 0x3f61, 0x4a2d, 0x5263, 0x525f, 0x3863, 0x5260, 0x4f24, 0x4a72, 0x4468, 0x3862, 0x3970, 0x5268, 0x465d, 0x526c, 0x3c7e, 0x3c76, 0x526f, 0x526d, 0x4c23, 0x526a, 0x5273, 0x526e, 0x5271, 0x3846, 0x4c3f, 0x5272, 0x5274, 0x5276, 0x3a70, 0x4f42, 0x526b, 0x5269, 0x5275, 0x5270, 0x5278, 0x5323, 0x527a, 0x527e, 0x5321, 0x527b, 0x533e, 0x3a69, 0x3331, 0x5279, 0x5325, 0x3076, 0x5324, 0x3025, 0x494a, 0x5322, 0x527c, 0x5277, 0x527d, 0x3a48, 0x5326, 0x3077, 0x532f, 0x5327, 0x5328, 0x3e25, 0x4b69, 0x532d, 0x532c, 0x452f, 0x532e, 0x532b, 0x3134, 0x3a36, 0x3f30, 0x5329, 0x4562, 0x532a, 0x3022, 0x5334, 0x4d23, 0x3e27, 0x533a, 0x5339, 0x5330, 0x4243, 0x5331, 0x426f, 0x5336, 0x3e26, 0x5333, 0x4c64, 0x373c, 0x5337, 0x5338, 0x5335, 0x533b, 0x5332, 0x5341, 0x5346, 0x5342, 0x533d, 0x5347, 0x4131, 0x5349, 0x3922, 0x533f, 0x437d, 0x5343, 0x533c, 0x342d, 0x346e, 0x3365, 0x5344, 0x5340, 0x3776, 0x534a, 0x5348, 0x4153, 0x354a, 0x362c, 0x5345, 0x3674, 0x3144, 0x534e, 0x534c, 0x5427, 0x5351, 0x534b, 0x534f, 0x534d, 0x3b4c, 0x5350, 0x5353, 0x5358, 0x5356, 0x5355, 0x4332, 0x3245, 0x5352, 0x5354, 0x3e28, 0x3133, 0x5357, 0x325e, 0x5362, 0x3e7c, 0x535e, 0x535c, 0x535d, 0x535f, 0x313d, 0x4139, 0x5359, 0x535a, 0x337a, 0x5361, 0x346f, 0x5364, 0x5360, 0x5363, 0x4a2e, 0x4655, 0x4838, 0x5366, 0x5365, 0x3345, 0x5367, 0x536a, 0x5369, 0x5368, 0x4739, 0x536b, 0x536c, 0x536e, 0x536d, 0x5370, 0x5373, 0x5371, 0x536f, 0x5372, 0x5374, 0x5375, 0x5376, 0x5377, 0x5378, 0x5145, 0x3c7c, 0x3b4d, 0x3273, 0x3078, 0x4344, 0x5379, 0x3a24, 0x304f, 0x3f5e, 0x537a, 0x3847, 0x3971, 0x537c, 0x537b, 0x4a60, 0x537d, 0x5421, 0x537e, 0x5422, 0x5423, 0x3777, 0x3160, 0x5424, 0x5426, 0x5425, 0x5428, 0x455a, 0x5429, 0x3035, 0x3a5f, 0x373d, 0x434f, 0x542a, 0x542b, 0x542d, 0x542e, 0x3a64, 0x3651, 0x4b37, 0x542c, 0x542f, 0x3a41, 0x3923, 0x5433, 0x3a25, 0x4333, 0x5430, 0x445a, 0x5434, 0x3f62, 0x5432, 0x5435, 0x373f, 0x5436, 0x5437, 0x3924, 0x3340, 0x5439, 0x543a, 0x543b, 0x5438, 0x5431, 0x543c, 0x543d, 0x4b64, 0x3e6b, 0x543f, 0x5440, 0x543e, 0x5442, 0x4738, 0x3068, 0x4956, 0x5443, 0x3e7d, 0x3c39, 0x475d, 0x3470, 0x3a6b, 0x4b59, 0x4632, 0x3778, 0x424f, 0x5441, 0x5444, 0x4244, 0x5445, 0x5446, 0x5448, 0x4469, 0x342e, 0x7421, 0x3161, 0x4a73, 0x3e6c, 0x4548, 0x3a66, 0x544e, 0x4a3d, 0x4e5d, 0x3274, 0x544a, 0x413a, 0x544d, 0x4563, 0x4549, 0x4564, 0x4839, 0x444d, 0x3a49, 0x5449, 0x3176, 0x4536, 0x544b, 0x5447, 0x3f50, 0x544f, 0x3d4e, 0x362d, 0x5450, 0x4a68, 0x417d, 0x4446, 0x5452, 0x4b4f, 0x5453, 0x5458, 0x4a2f, 0x5457, 0x5451, 0x5454, 0x5456, 0x3a26, 0x4a49, 0x5459, 0x4345, 0x3275, 0x3e6d, 0x545b, 0x545a, 0x3968, 0x545c, 0x545e, 0x545d, 0x5460, 0x5455, 0x5462, 0x5461, 0x545f, 0x3b4e, 0x3f51, 0x4154, 0x5463, 0x403c, 0x306d, 0x4764, 0x445b, 0x5465, 0x5464, 0x5466, 0x5467, 0x5468, 0x5469, 0x4a51, 0x546a, 0x3246, 0x546b, 0x4d3c, 0x3330, 0x5249, 0x3d48, 0x423f, 0x546c, 0x4c6b, 0x4c34, 0x546e, 0x4267, 0x4537, 0x4240, 0x4957, 0x546f, 0x5470, 0x317b, 0x3c3a, 0x5471, 0x3050, 0x5472, 0x5473, 0x3162, 0x3471, 0x4660, 0x4a74, 0x5477, 0x4155, 0x5476, 0x3740, 0x4b5b, 0x5475, 0x4565, 0x5479, 0x5478, 0x547b, 0x547a, 0x317c, 0x547c, 0x3e29, 0x547e, 0x4325, 0x547d, 0x4a33, 0x3d77, 0x455b, 0x5521, 0x3925, 0x5522, 0x4721, 0x485e, 0x4c51, 0x4725, 0x552b, 0x3538, 0x4d45, 0x4c2f, 0x562c, 0x5523, 0x5526, 0x4245, 0x4b38, 0x454a, 0x5527, 0x4b65, 0x3a4a, 0x3e2a, 0x5528, 0x3b50, 0x3b4f, 0x3039, 0x3848, 0x402b, 0x3051, 0x552c, 0x552d, 0x552a, 0x3138, 0x342f, 0x5529, 0x4c45, 0x4931, 0x3028, 0x3079, 0x3b51, 0x3052, 0x3023, 0x5532, 0x5530, 0x4c3c, 0x5533, 0x5531, 0x552f, 0x3f31, 0x552e, 0x4a5a, 0x3864, 0x5537, 0x5538, 0x3e2b, 0x5534, 0x4f2c, 0x474c, 0x5536, 0x3a27, 0x5539, 0x4958, 0x553a, 0x5535, 0x4c3b, 0x475e, 0x553b, 0x4932, 0x553c, 0x5540, 0x553d, 0x3247, 0x553f, 0x3c3b, 0x553e, 0x3779, 0x554c, 0x5545, 0x5542, 0x4364, 0x5541, 0x5543, 0x5544, 0x5546, 0x5547, 0x3472, 0x5549, 0x5548, 0x554a, 0x3e6e, 0x554d, 0x445c, 0x3145, 0x554b, 0x554e, 0x554f, 0x5552, 0x5550, 0x5551, 0x3b52, 0x5553, 0x3926, 0x5554, 0x3b7a, 0x4238, 0x5555, 0x5556, 0x3b5a, 0x3927, 0x4c52, 0x3528, 0x3849, 0x5557, 0x3358, 0x5558, 0x4239, 0x5559, 0x5623, 0x555a, 0x555b, 0x555c, 0x555e, 0x555f, 0x5560, 0x4270, 0x3127, 0x3c69, 0x3042, 0x4157, 0x3430, 0x3c35, 0x3928, 0x4566, 0x3d21, 0x3431, 0x4368, 0x446a, 0x3038, 0x3539, 0x4a75, 0x3c42, 0x3552, 0x406b, 0x3c3c, 0x4d28, 0x5561, 0x355c, 0x3a4b, 0x3332, 0x3163, 0x3e2c, 0x3248, 0x5562, 0x4d46, 0x3d49, 0x3c64, 0x5563, 0x3473, 0x4652, 0x4c29, 0x5564, 0x5565, 0x4959, 0x5567, 0x3428, 0x3677, 0x5566, 0x3432, 0x3f32, 0x556b, 0x3b21, 0x3249, 0x556a, 0x5568, 0x556c, 0x5569, 0x472b, 0x5c4d, 0x3f33, 0x556d, 0x4e40, 0x556e, 0x5570, 0x437e, 0x556f, 0x4023, 0x3b7b, 0x4250, 0x3c77, 0x4975, 0x406c, 0x3c4d, 0x5571, 0x3e2d, 0x5572, 0x5573, 0x3053, 0x423a, 0x3f52, 0x5574, 0x4633, 0x3e2e, 0x3e2f, 0x5575, 0x406d, 0x3e30, 0x5576, 0x5577, 0x4c60, 0x5578, 0x3646, 0x3d22, 0x5579, 0x557a, 0x3c5c, 0x3f2c, 0x4674, 0x3f54, 0x4878, 0x4722, 0x3649, 0x557b, 0x356f, 0x557c, 0x367e, 0x464f, 0x3230, 0x3b53, 0x557d, 0x5622, 0x5621, 0x367d, 0x557e, 0x4538, 0x4230, 0x454b, 0x3c48, 0x4158, 0x4d7a, 0x5624, 0x5625, 0x4656, 0x3b33, 0x5627, 0x5628, 0x5629, 0x3474, 0x562a, 0x562b, 0x322c, 0x413b, 0x3464, 0x562d, 0x4c28, 0x4252, 0x3359, 0x562f, 0x5631, 0x345f, 0x562e, 0x5630, 0x5633, 0x5632, 0x5634, 0x5635, 0x463d, 0x362e, 0x3265, 0x5636, 0x563b, 0x5639, 0x4a77, 0x4a76, 0x4567, 0x5638, 0x3d54, 0x5637, 0x3f72, 0x563c, 0x3a6a, 0x5642, 0x5643, 0x563d, 0x3333, 0x563e, 0x5647, 0x5646, 0x5645, 0x5641, 0x5640, 0x5644, 0x4a78, 0x564b, 0x5648, 0x564a, 0x4d72, 0x5649, 0x563f, 0x3f73, 0x564c, 0x3a37, 0x564d, 0x564e, 0x5651, 0x5650, 0x564f, 0x4568, 0x563a, 0x5657, 0x5653, 0x5652, 0x5654, 0x5655, 0x5658, 0x4e66, 0x5659, 0x5656, 0x565a, 0x3460, 0x565b, 0x565d, 0x565c, 0x565e, 0x565f, 0x406e, 0x3d23, 0x3d64, 0x4163, 0x3929, 0x3a38, 0x392a, 0x3570, 0x5660, 0x3a39, 0x384a, 0x5661, 0x4c26, 0x4743, 0x5662, 0x392b, 0x342c, 0x4327, 0x3652, 0x3b54, 0x495b, 0x4841, 0x5663, 0x3475, 0x5666, 0x4421, 0x5665, 0x5664, 0x5667, 0x446b, 0x3f63, 0x3b55, 0x404a, 0x4253, 0x3522, 0x4422, 0x5668, 0x5669, 0x3e6f, 0x4b39, 0x566c, 0x566b, 0x566a, 0x497d, 0x5673, 0x4b5a, 0x566d, 0x566f, 0x4b6b, 0x566e, 0x5670, 0x4828, 0x5671, 0x4a3e, 0x5672, 0x3433, 0x4a3f, 0x472f, 0x5674, 0x5675, 0x392c, 0x3434, 0x5676, 0x3838, 0x4d44, 0x4d29, 0x3476, 0x5678, 0x4423, 0x392d, 0x3e31, 0x485f, 0x3e32, 0x3d78, 0x446c, 0x4a79, 0x4539, 0x392e, 0x495c, 0x5679, 0x4559, 0x3a42, 0x384b, 0x446d, 0x3043, 0x3d6e, 0x392f, 0x4d47, 0x567a, 0x567b, 0x4751, 0x567c, 0x4e77, 0x4f2d, 0x567e, 0x567d, 0x3347, 0x5721, 0x5724, 0x5725, 0x5723, 0x4940, 0x3e33, 0x5727, 0x5726, 0x5722, 0x5728, 0x5729, 0x572a, 0x572d, 0x572b, 0x572c, 0x572e, 0x3164, 0x446e, 0x572f, 0x377a, 0x3276, 0x4736, 0x5730, 0x467b, 0x4a5b, 0x5731, 0x4f2e, 0x5732, 0x4a40, 0x5735, 0x5021, 0x5031, 0x3c30, 0x4675, 0x5736, 0x355d, 0x4424, 0x307a, 0x5737, 0x4a26, 0x3930, 0x4350, 0x446f, 0x4c6f, 0x3839, 0x384c, 0x5738, 0x5739, 0x573f, 0x3c65, 0x4425, 0x362f, 0x573a, 0x492b, 0x4346, 0x573b, 0x573c, 0x3630, 0x573d, 0x573e, 0x5740, 0x4576, 0x5741, 0x5742, 0x5743, 0x5734, 0x5733, 0x5744, 0x3741, 0x4927, 0x3a4c, 0x4937, 0x4426, 0x494b, 0x5745, 0x3e34, 0x3146, 0x5746, 0x5747, 0x4c72, 0x4860, 0x574a, 0x317d, 0x402c, 0x5749, 0x5748, 0x3742, 0x4254, 0x574e, 0x574c, 0x574b, 0x4e27, 0x3865, 0x3d79, 0x574d, 0x454c, 0x3d3e, 0x4640, 0x5751, 0x5750, 0x574f, 0x5752, 0x3866, 0x5753, 0x497c, 0x3d5b, 0x5754, 0x4879, 0x4641, 0x4427, 0x4530, 0x5755, 0x352b, 0x3f34, 0x492c, 0x3477, 0x4726, 0x5756, 0x3b56, 0x4b3a, 0x4b3b, 0x317e, 0x575b, 0x4369, 0x5758, 0x3277, 0x582d, 0x575a, 0x4730, 0x5759, 0x5757, 0x397a, 0x575d, 0x5763, 0x5769, 0x5761, 0x455c, 0x5766, 0x495d, 0x5760, 0x5765, 0x4e67, 0x3b57, 0x4255, 0x575e, 0x355e, 0x5768, 0x402d, 0x3165, 0x5762, 0x3278, 0x5767, 0x3631, 0x5764, 0x576a, 0x576c, 0x5776, 0x5774, 0x5771, 0x5770, 0x4e78, 0x5772, 0x3632, 0x3931, 0x3d7a, 0x5779, 0x576b, 0x576f, 0x575f, 0x327a, 0x5773, 0x5775, 0x4351, 0x3a28, 0x3238, 0x576d, 0x5778, 0x5777, 0x3633, 0x4229, 0x3366, 0x3743, 0x576e, 0x577a, 0x577d, 0x5821, 0x3c3d, 0x5827, 0x4470, 0x577b, 0x5825, 0x3279, 0x5823, 0x5824, 0x577e, 0x5822, 0x3867, 0x4d2a, 0x3435, 0x3159, 0x5826, 0x473a, 0x302d, 0x4861, 0x575c, 0x582c, 0x5830, 0x4c65, 0x5829, 0x4569, 0x582e, 0x3e70, 0x582f, 0x4657, 0x4f47, 0x582b, 0x5831, 0x397b, 0x404b, 0x3054, 0x582a, 0x5828, 0x415a, 0x577c, 0x3b34, 0x4246, 0x583d, 0x415b, 0x5838, 0x5835, 0x5836, 0x3c66, 0x5839, 0x583c, 0x5837, 0x3d25, 0x583a, 0x5834, 0x4c7c, 0x4c7b, 0x583e, 0x583f, 0x3055, 0x5833, 0x3672, 0x3026, 0x3436, 0x583b, 0x5843, 0x5842, 0x5847, 0x5848, 0x5846, 0x5849, 0x5841, 0x5845, 0x584a, 0x584b, 0x5840, 0x3b7c, 0x5844, 0x4256, 0x3932, 0x5832, 0x3f35, 0x5858, 0x4a69, 0x584e, 0x584f, 0x5850, 0x5857, 0x5856, 0x4b7d, 0x3437, 0x5854, 0x3745, 0x3334, 0x5851, 0x4e38, 0x5853, 0x3056, 0x5855, 0x584c, 0x5852, 0x5859, 0x3744, 0x584d, 0x4d5d, 0x4d2b, 0x585c, 0x5860, 0x417e, 0x4e79, 0x5861, 0x585e, 0x585b, 0x585a, 0x585f, 0x4a30, 0x4634, 0x3746, 0x5862, 0x585d, 0x5863, 0x377b, 0x3231, 0x586b, 0x3438, 0x5869, 0x586a, 0x3a29, 0x5868, 0x5866, 0x5865, 0x586c, 0x5864, 0x586e, 0x327b, 0x5870, 0x586f, 0x4428, 0x5873, 0x5871, 0x5867, 0x377c, 0x5872, 0x5876, 0x5875, 0x5877, 0x5874, 0x5878, 0x5879, 0x587a, 0x4a6a, 0x587c, 0x587b, 0x3d3f, 0x402e, 0x3266, 0x327c, 0x587d, 0x303f, 0x404c, 0x587e, 0x6c43, 0x5921, 0x3761, 0x5922, 0x406f, 0x5923, 0x5924, 0x353a, 0x5925, 0x5926, 0x5927, 0x4257, 0x384d, 0x4c61, 0x4b3c, 0x3d6a, 0x5928, 0x4070, 0x6e3d, 0x4862, 0x3c6a, 0x3a4d, 0x5929, 0x4247, 0x4a27, 0x4271, 0x592c, 0x592a, 0x592d, 0x592b, 0x592e, 0x4a31, 0x3037, 0x495e, 0x4863, 0x592f, 0x5932, 0x3e35, 0x353b, 0x5930, 0x5937, 0x3e36, 0x5931, 0x4744, 0x4d5e, 0x5933, 0x5934, 0x5938, 0x456a, 0x5935, 0x3933, 0x405e, 0x5946, 0x4834, 0x4272, 0x4864, 0x5a2d, 0x4a7a, 0x4471, 0x4b75, 0x593b, 0x3221, 0x436a, 0x5944, 0x4334, 0x593e, 0x5945, 0x5940, 0x5947, 0x5943, 0x5942, 0x476f, 0x593c, 0x327d, 0x593a, 0x3571, 0x4273, 0x5936, 0x5939, 0x3934, 0x405b, 0x3e37, 0x5941, 0x4752, 0x3572, 0x3348, 0x3367, 0x3f21, 0x5949, 0x594e, 0x594a, 0x377d, 0x594f, 0x3b22, 0x3969, 0x3d26, 0x593d, 0x3b7d, 0x594c, 0x3b58, 0x594d, 0x3044, 0x5948, 0x4429, 0x3573, 0x3634, 0x594b, 0x3027, 0x3a43, 0x3f36, 0x4472, 0x4854, 0x5951, 0x415e, 0x422a, 0x3b2b, 0x5952, 0x5954, 0x5950, 0x4a61, 0x443d, 0x415c, 0x4a7b, 0x3c4e, 0x5960, 0x595f, 0x3f78, 0x377e, 0x5959, 0x3e39, 0x4668, 0x4731, 0x5957, 0x415d, 0x3c78, 0x595c, 0x3e38, 0x5956, 0x595b, 0x4753, 0x5955, 0x3721, 0x335d, 0x595d, 0x4e2b, 0x3a4e, 0x4335, 0x595a, 0x405c, 0x3935, 0x3f64, 0x3166, 0x413c, 0x5958, 0x3545, 0x3747, 0x444f, 0x595e, 0x415f, 0x5961, 0x5963, 0x4237, 0x5969, 0x5964, 0x5966, 0x4941, 0x4473, 0x5967, 0x4d2c, 0x4d48, 0x3439, 0x302e, 0x5965, 0x5962, 0x3478, 0x3167, 0x5968, 0x4d49, 0x596c, 0x423b, 0x5973, 0x596d, 0x596a, 0x5971, 0x5953, 0x596e, 0x5972, 0x4842, 0x456b, 0x596b, 0x596f, 0x3748, 0x3a71, 0x405d, 0x5977, 0x4526, 0x5974, 0x4b60, 0x5975, 0x5976, 0x4c4e, 0x4022, 0x3762, 0x597d, 0x3b35, 0x597a, 0x5979, 0x4732, 0x4635, 0x4531, 0x597b, 0x597c, 0x496f, 0x4745, 0x3b23, 0x4071, 0x4b50, 0x3349, 0x5a25, 0x597e, 0x4d4a, 0x5a27, 0x5a23, 0x5a24, 0x4160, 0x5a22, 0x593f, 0x5a26, 0x5a21, 0x5a2b, 0x5a2c, 0x4527, 0x5a2e, 0x3b24, 0x5a29, 0x353c, 0x5a2f, 0x5a28, 0x5a33, 0x5a32, 0x5a31, 0x5a34, 0x5a36, 0x3e71, 0x5a35, 0x5a39, 0x5a37, 0x5a38, 0x5970, 0x5a3b, 0x5a3a, 0x5978, 0x5a3c, 0x5a30, 0x3b59, 0x5a3d, 0x5a3e, 0x5a40, 0x5a3f, 0x5a41, 0x327e, 0x3936, 0x4a7c, 0x402f, 0x384e, 0x5a43, 0x5a46, 0x4952, 0x355f, 0x5a45, 0x5a44, 0x4754, 0x5a47, 0x3635, 0x5a49, 0x5a48, 0x343a, 0x3b36, 0x4658, 0x3749, 0x3f74, 0x5a4a, 0x4030, 0x4528, 0x495f, 0x5a4b, 0x5a4c, 0x5a4d, 0x4a38, 0x555d, 0x4046, 0x494c, 0x3a58, 0x4865, 0x4843, 0x454d, 0x4e41, 0x5a4f, 0x3c50, 0x5a50, 0x3036, 0x3654, 0x404d, 0x4960, 0x5a51, 0x3b42, 0x4347, 0x3b5b, 0x3f37, 0x5a52, 0x4a7d, 0x3177, 0x3b5c, 0x5a55, 0x5a53, 0x5a56, 0x4e39, 0x5a54, 0x407b, 0x5a57, 0x4232, 0x5a58, 0x347a, 0x5a5a, 0x5a59, 0x5a5b, 0x5a5c, 0x347b, 0x467c, 0x4336, 0x356c, 0x3b5d, 0x4161, 0x3d5c, 0x3030, 0x5a5d, 0x3222, 0x5a61, 0x3937, 0x5a60, 0x3a2b, 0x3e3a, 0x5a5f, 0x3e3b, 0x4c40, 0x3a2a, 0x3057, 0x404e, 0x5a66, 0x4031, 0x3147, 0x3d55, 0x4b66, 0x3a72, 0x3e3c, 0x4027, 0x5a65, 0x5a63, 0x5a64, 0x436b, 0x5b26, 0x5a6a, 0x3b7e, 0x3938, 0x5a68, 0x5a69, 0x3f38, 0x5a67, 0x3b2f, 0x5a6c, 0x5a6b, 0x5a70, 0x5a71, 0x5a6d, 0x3322, 0x5a6e, 0x5a6f, 0x4855, 0x4961, 0x374a, 0x5a72, 0x4032, 0x3e3d, 0x4352, 0x3647, 0x5a73, 0x5a77, 0x324b, 0x5a74, 0x5a76, 0x5a75, 0x3d6b, 0x4348, 0x3045, 0x5a78, 0x5a79, 0x442a, 0x4e71, 0x3b43, 0x4a6b, 0x4b3d, 0x5b22, 0x5a7b, 0x5a7e, 0x5a7d, 0x5a7a, 0x5b21, 0x465e, 0x5a7c, 0x5b23, 0x3d6c, 0x5b24, 0x4d4b, 0x4778, 0x5b25, 0x5b27, 0x5b28, 0x5b29, 0x364a, 0x3148, 0x3939, 0x5b2a, 0x5b2b, 0x3d71, 0x4162, 0x5258, 0x413e, 0x413d, 0x4258, 0x3a47, 0x5072, 0x376e, 0x4d2d, 0x4a7e, 0x497e, 0x5b2c, 0x3a73, 0x443f, 0x5b2d, 0x4f2f, 0x4b3e, 0x442b, 0x5b2e, 0x347c, 0x5b2f, 0x5b30, 0x4c5a, 0x4c24, 0x4b76, 0x4b5c, 0x3b25, 0x5b32, 0x3c6b, 0x4b51, 0x5b34, 0x5b37, 0x5b36, 0x3479, 0x3560, 0x5b33, 0x5b35, 0x5b38, 0x3f79, 0x4d7b, 0x3049, 0x3a60, 0x423c, 0x3c5d, 0x3e73, 0x5b3b, 0x454e, 0x5b39, 0x422b, 0x5b3a, 0x3e72, 0x4c5d, 0x5b3c, 0x5b3d, 0x4d68, 0x5b42, 0x393a, 0x4755, 0x5b3f, 0x456c, 0x5a5e, 0x5a62, 0x354f, 0x4747, 0x5b41, 0x3e3e, 0x4844, 0x5b47, 0x487a, 0x5b3e, 0x5b44, 0x5b43, 0x404f, 0x4b6d, 0x4e53, 0x4b67, 0x324c, 0x3b5e, 0x4f48, 0x5b46, 0x3f75, 0x5b45, 0x5b40, 0x384f, 0x5b4c, 0x5b4a, 0x324d, 0x5b48, 0x5b4e, 0x5b54, 0x4248, 0x4a41, 0x5b56, 0x4922, 0x5b55, 0x4770, 0x4b3f, 0x343b, 0x4077, 0x3d40, 0x4453, 0x4d2e, 0x5b51, 0x5b50, 0x5b52, 0x5b4f, 0x5b57, 0x5b4d, 0x5b4b, 0x5b53, 0x5b49, 0x436c, 0x4c78, 0x3c46, 0x3a74, 0x3a3a, 0x4b6f, 0x3341, 0x444e, 0x464a, 0x3149, 0x4072, 0x4034, 0x372a, 0x5b59, 0x393b, 0x337c, 0x5b5b, 0x3374, 0x5b61, 0x5b5e, 0x4073, 0x334b, 0x3a2c, 0x334a, 0x3a4f, 0x5b5c, 0x3765, 0x374b, 0x456d, 0x5b5a, 0x3046, 0x5b5d, 0x5b5f, 0x364d, 0x372c, 0x343c, 0x354b, 0x5b62, 0x3a79, 0x4b71, 0x3b37, 0x5b63, 0x4930, 0x5b6f, 0x3233, 0x5b64, 0x5b75, 0x5b65, 0x4e42, 0x5b6c, 0x475f, 0x5b74, 0x5b67, 0x3034, 0x5b69, 0x393c, 0x5b6b, 0x5b6a, 0x5b66, 0x5b71, 0x3e3f, 0x546d, 0x3868, 0x4d7c, 0x5b68, 0x4474, 0x3323, 0x3a2d, 0x5b60, 0x5b70, 0x3361, 0x5b6e, 0x5b72, 0x456e, 0x347e, 0x5c32, 0x4c49, 0x5b77, 0x347d, 0x5b7e, 0x4b40, 0x5c21, 0x5c23, 0x5c27, 0x5b79, 0x432a, 0x456f, 0x5c2b, 0x5b7c, 0x5c28, 0x5c22, 0x3f39, 0x5c2c, 0x4033, 0x5c2a, 0x343d, 0x4f50, 0x5b76, 0x5c26, 0x3058, 0x5b78, 0x4c3a, 0x5b7d, 0x3f22, 0x4447, 0x5b73, 0x5c25, 0x3f7a, 0x5c2f, 0x3371, 0x3821, 0x5c31, 0x5b7a, 0x5c30, 0x5c29, 0x5b7b, 0x5c2d, 0x5c2e, 0x5c3f, 0x464e, 0x5c24, 0x5c3b, 0x5c3d, 0x4458, 0x4d4c, 0x4976, 0x5c38, 0x424a, 0x5c3e, 0x413f, 0x5c35, 0x5c42, 0x5c41, 0x466f, 0x5c40, 0x466a, 0x5c44, 0x5c37, 0x3648, 0x5c3a, 0x3d5d, 0x4760, 0x5c3c, 0x364b, 0x5c34, 0x5c36, 0x5c33, 0x4f30, 0x335a, 0x5c39, 0x5c43, 0x3335, 0x3a67, 0x315d, 0x5c54, 0x4f31, 0x5c57, 0x3f3a, 0x5c56, 0x5c55, 0x5c52, 0x5c46, 0x5c63, 0x5c45, 0x5c58, 0x5c50, 0x5c4b, 0x5c48, 0x5c49, 0x5c51, 0x7422, 0x5c4e, 0x393d, 0x4448, 0x4164, 0x5c4c, 0x5c47, 0x5c4a, 0x4d4d, 0x4b6a, 0x5c4f, 0x5c59, 0x5c61, 0x5c5a, 0x5c67, 0x5c65, 0x5c60, 0x5c5f, 0x4450, 0x4165, 0x5c5d, 0x5c5b, 0x5c62, 0x5c68, 0x4875, 0x5c6e, 0x5c69, 0x5c6c, 0x5c66, 0x4374, 0x4938, 0x5c5c, 0x5c64, 0x3e40, 0x4c4f, 0x5c78, 0x5c6b, 0x3822, 0x3223, 0x335f, 0x5c53, 0x3e41, 0x5c70, 0x5c77, 0x3c79, 0x3372, 0x432e, 0x5c6d, 0x5c72, 0x5c76, 0x3636, 0x354c, 0x5c74, 0x3521, 0x464b, 0x5c73, 0x5c75, 0x5c6f, 0x5c71, 0x3360, 0x4349, 0x5c7c, 0x5c7a, 0x3869, 0x5c79, 0x5d21, 0x5b58, 0x5c7b, 0x5c7d, 0x5c7e, 0x5d2c, 0x5d28, 0x5b6d, 0x5d27, 0x5d26, 0x5d23, 0x5c6a, 0x5d25, 0x5d24, 0x5d2a, 0x4f26, 0x5d2d, 0x367b, 0x5d29, 0x5d2b, 0x4827, 0x5d2e, 0x5d32, 0x5d2f, 0x4d73, 0x5d30, 0x5c5e, 0x5d33, 0x5d34, 0x3135, 0x5d36, 0x3767, 0x3c21, 0x3655, 0x3224, 0x4d5f, 0x5d38, 0x5d37, 0x5d3a, 0x353d, 0x3656, 0x343e, 0x5d3d, 0x5d3c, 0x5d3e, 0x324e, 0x4337, 0x5d3f, 0x343f, 0x5d41, 0x5d40, 0x5d42, 0x5d43, 0x5d44, 0x3b5f, 0x4035, 0x3a21, 0x4970, 0x4a62, 0x4f44, 0x3b75, 0x3a50, 0x4e72, 0x5d45, 0x5d46, 0x3b60, 0x5d47, 0x5d48, 0x5d4a, 0x5d49, 0x4b58, 0x3d5e, 0x3c6c, 0x3b44, 0x5d4b, 0x5d4d, 0x3f23, 0x5d4c, 0x5d4e, 0x5d4f, 0x5d50, 0x5d51, 0x5d52, 0x5d54, 0x5d53, 0x5d55, 0x3225, 0x434a, 0x5d56, 0x3b26, 0x334c, 0x5d57, 0x4542, 0x544c, 0x3523, 0x5d58, 0x5d59, 0x4a6c, 0x4b68, 0x4647, 0x5d5a, 0x4866, 0x487b, 0x4c53, 0x5d5b, 0x5d5d, 0x5d5c, 0x5d5f, 0x5d5e, 0x5d61, 0x3b61, 0x4c31, 0x5d62, 0x5d63, 0x3524, 0x5d64, 0x5d66, 0x5d65, 0x3f65, 0x4939, 0x314a, 0x4845, 0x4475, 0x3d41, 0x3561, 0x4846, 0x3c2e, 0x5d68, 0x3440, 0x3178, 0x4672, 0x5d67, 0x393e, 0x4353, 0x5d69, 0x5d71, 0x5d6a, 0x4241, 0x3562, 0x5d72, 0x3768, 0x3525, 0x5d70, 0x5d6e, 0x5d6b, 0x4d60, 0x4440, 0x4659, 0x5d6c, 0x5d74, 0x5d73, 0x3723, 0x322d, 0x3a3b, 0x5d6d, 0x5d6f, 0x4b57, 0x4274, 0x4b77, 0x5d7c, 0x5d7d, 0x324f, 0x4a28, 0x4c7d, 0x5e21, 0x3c23, 0x3e42, 0x5d78, 0x5d7e, 0x3168, 0x3637, 0x5d75, 0x5d7a, 0x4074, 0x4771, 0x4867, 0x5d77, 0x4b21, 0x5d79, 0x5e24, 0x5e22, 0x5d7b, 0x4b22, 0x4748, 0x3563, 0x4525, 0x436d, 0x5e25, 0x5e23, 0x4259, 0x5d76, 0x314b, 0x4d4e, 0x5e30, 0x5e2f, 0x4076, 0x5e2c, 0x4d6c, 0x4636, 0x5e26, 0x4445, 0x314c, 0x393f, 0x5e29, 0x3d27, 0x5e2e, 0x5e2d, 0x5e28, 0x5e2b, 0x3368, 0x5e2a, 0x4749, 0x4e2e, 0x3e74, 0x4075, 0x5e36, 0x5e34, 0x494d, 0x5e31, 0x5e33, 0x313a, 0x3940, 0x4f32, 0x333d, 0x4962, 0x4d61, 0x3324, 0x3f3b, 0x5e35, 0x5e3a, 0x3e43, 0x4d30, 0x5e37, 0x5e32, 0x5e38, 0x4e5e, 0x4573, 0x4642, 0x3336, 0x3155, 0x5e3e, 0x5e41, 0x4e43, 0x4d64, 0x5e48, 0x5e42, 0x5e3f, 0x4e54, 0x5e45, 0x3d4a, 0x5e47, 0x5e4c, 0x4571, 0x5e4a, 0x5e44, 0x4338, 0x5e4b, 0x5e40, 0x5e46, 0x5e4d, 0x307c, 0x5e43, 0x5e4e, 0x3f3c, 0x3d5f, 0x4a25, 0x3a2e, 0x5e3b, 0x5e49, 0x453a, 0x4036, 0x3369, 0x3a51, 0x3e44, 0x5e3d, 0x3d42, 0x374c, 0x5e3c, 0x5e52, 0x3d6d, 0x383a, 0x5e61, 0x5e5b, 0x3574, 0x454f, 0x5e56, 0x5e5f, 0x302f, 0x3132, 0x3239, 0x5e58, 0x422c, 0x5e4f, 0x5e51, 0x3941, 0x5e62, 0x5e5d, 0x5e55, 0x5e5c, 0x4c2b, 0x5e5a, 0x5e5e, 0x3850, 0x3e45, 0x4339, 0x5e54, 0x4d2f, 0x5e57, 0x5e50, 0x4572, 0x5e53, 0x5e59, 0x4f51, 0x3c3e, 0x4b7e, 0x5e63, 0x482e, 0x5e6f, 0x383b, 0x3d60, 0x5e65, 0x4e2f, 0x3942, 0x5e72, 0x306e, 0x5e70, 0x5e64, 0x5e6a, 0x5e6c, 0x4d4f, 0x5e67, 0x452e, 0x5e69, 0x5e71, 0x5e6b, 0x4c47, 0x5e66, 0x3c22, 0x5e7e, 0x336a, 0x5e68, 0x5e6d, 0x5e6e, 0x426c, 0x425a, 0x5e76, 0x5e7c, 0x5e7a, 0x4529, 0x5f23, 0x5e77, 0x5e78, 0x5e60, 0x3579, 0x493a, 0x3c3f, 0x3977, 0x4f33, 0x5e74, 0x5f22, 0x3169, 0x4166, 0x4779, 0x3441, 0x4e7a, 0x4c21, 0x4452, 0x5e7b, 0x5e7d, 0x4132, 0x5f21, 0x5e79, 0x5e73, 0x3443, 0x3769, 0x5f2f, 0x5f2a, 0x4078, 0x3363, 0x3d61, 0x5f33, 0x5f2c, 0x442c, 0x5f29, 0x4459, 0x5f4c, 0x5f26, 0x5f25, 0x5f2e, 0x5f28, 0x5f27, 0x5f2d, 0x4021, 0x5f24, 0x5f30, 0x5f31, 0x3442, 0x5f36, 0x5f35, 0x5f37, 0x5f3a, 0x4543, 0x5f34, 0x5f38, 0x3763, 0x4279, 0x5f32, 0x473b, 0x5f39, 0x5f3e, 0x5f3c, 0x5f3f, 0x5f42, 0x5f3b, 0x396a, 0x4728, 0x5e39, 0x4d74, 0x5f3d, 0x5f41, 0x4275, 0x5f40, 0x5f2b, 0x6f69, 0x5f45, 0x5f49, 0x5f47, 0x5f43, 0x5f44, 0x5f48, 0x5f46, 0x494e, 0x5f4e, 0x5f4b, 0x5f4a, 0x5f4d, 0x4654, 0x5f4f, 0x4375, 0x426d, 0x4025, 0x5f50, 0x5f52, 0x5f51, 0x5e75, 0x5f53, 0x4667, 0x5f54, 0x3250, 0x4574, 0x3325, 0x3564, 0x3c5e, 0x3a52, 0x4f27, 0x3f66, 0x316a, 0x5f56, 0x5f55, 0x5f59, 0x433a, 0x5f5c, 0x5f57, 0x5f5b, 0x5f5a, 0x4540, 0x3059, 0x4e75, 0x5f5e, 0x3128, 0x5f60, 0x5f5f, 0x5f5d, 0x5f58, 0x4b23, 0x5f62, 0x5f61, 0x316b, 0x5f64, 0x4a32, 0x5f63, 0x4c35, 0x3e47, 0x4133, 0x3e46, 0x4e7b, 0x5f6a, 0x4079, 0x5f66, 0x5f6b, 0x316c, 0x5f69, 0x4761, 0x5f65, 0x5f68, 0x3e48, 0x4851, 0x5f6c, 0x3c51, 0x407a, 0x5f6f, 0x5f67, 0x3727, 0x5f6d, 0x4d50, 0x5f70, 0x7426, 0x3d4f, 0x5f71, 0x5f72, 0x472e, 0x5f74, 0x5f75, 0x4733, 0x4575, 0x5f77, 0x5f79, 0x4e55, 0x5f76, 0x5f78, 0x316d, 0x5f73, 0x535b, 0x5f7a, 0x4167, 0x3b38, 0x5f7c, 0x5f7b, 0x3f24, 0x5259, 0x5f7d, 0x6021, 0x5f6e, 0x5f7e, 0x6022, 0x477a, 0x6023, 0x6024, 0x6025, 0x6026, 0x445e, 0x6028, 0x6027, 0x6029, 0x602a, 0x3c5f, 0x4963, 0x4c6c, 0x602b, 0x602c, 0x4156, 0x3c24, 0x602d, 0x602e, 0x602f, 0x4a52, 0x4847, 0x6030, 0x4757, 0x442d, 0x6031, 0x3267, 0x356d, 0x4c46, 0x4c36, 0x3234, 0x4f34, 0x4b52, 0x4a2a, 0x4037, 0x6032, 0x4643, 0x3823, 0x6033, 0x3a54, 0x6035, 0x6034, 0x6036, 0x6037, 0x6038, 0x353e, 0x6039, 0x603a, 0x3824, 0x4848, 0x603c, 0x3e75, 0x603b, 0x3638, 0x603d, 0x603f, 0x603e, 0x6040, 0x3851, 0x6041, 0x3669, 0x4140, 0x397d, 0x6043, 0x6044, 0x6042, 0x3c6d, 0x4648, 0x3639, 0x6046, 0x432c, 0x6045, 0x4f35, 0x4762, 0x6049, 0x604b, 0x6048, 0x4c54, 0x604a, 0x604c, 0x4e44, 0x6050, 0x604f, 0x4376, 0x472d, 0x3825, 0x604e, 0x604d, 0x4d31, 0x4d32, 0x6051, 0x316e, 0x3976, 0x3b62, 0x6052, 0x6053, 0x6055, 0x3d43, 0x6057, 0x6056, 0x6058, 0x334d, 0x605a, 0x6059, 0x605c, 0x605b, 0x383c, 0x4e28, 0x364c, 0x3226, 0x366a, 0x3461, 0x4e68, 0x605e, 0x6060, 0x6061, 0x3251, 0x605d, 0x3b39, 0x4441, 0x605f, 0x6064, 0x3c6e, 0x6062, 0x373e, 0x4849, 0x6063, 0x607e, 0x6069, 0x383d, 0x3565, 0x6066, 0x4d7d, 0x4e30, 0x4276, 0x6068, 0x606a, 0x4e56, 0x3657, 0x487c, 0x474a, 0x606b, 0x606d, 0x6070, 0x606c, 0x606f, 0x386a, 0x314d, 0x6071, 0x3f70, 0x606e, 0x4e5c, 0x6074, 0x7424, 0x6072, 0x6075, 0x6067, 0x6073, 0x3a3c, 0x6076, 0x6077, 0x4d7e, 0x6078, 0x6079, 0x6065, 0x607a, 0x3444, 0x3c25, 0x607b, 0x607c, 0x607d, 0x313b, 0x6121, 0x493b, 0x6122, 0x3424, 0x6123, 0x6124, 0x6125, 0x6127, 0x6128, 0x6126, 0x4953, 0x612a, 0x6129, 0x612c, 0x612b, 0x612d, 0x612e, 0x6130, 0x612f, 0x3979, 0x6132, 0x6131, 0x3445, 0x3f53, 0x453c, 0x6133, 0x4038, 0x3b3a, 0x3179, 0x6134, 0x4d51, 0x4a63, 0x6135, 0x4544, 0x4d33, 0x3943, 0x3f3d, 0x434b, 0x5234, 0x442e, 0x3268, 0x6136, 0x6137, 0x613c, 0x613a, 0x6139, 0x5a42, 0x3326, 0x6138, 0x305a, 0x482a, 0x484a, 0x4e31, 0x613d, 0x613b, 0x435c, 0x4026, 0x482b, 0x492d, 0x613f, 0x4e2c, 0x374d, 0x6140, 0x613e, 0x4856, 0x6141, 0x6142, 0x305b, 0x3e76, 0x6147, 0x6144, 0x466d, 0x6143, 0x3526, 0x614a, 0x6145, 0x6146, 0x6149, 0x6148, 0x4925, 0x4142, 0x4141, 0x353f, 0x614b, 0x614c, 0x614d, 0x614f, 0x614e, 0x3156, 0x6157, 0x4868, 0x6151, 0x6153, 0x6155, 0x3f3e, 0x6156, 0x6154, 0x3c40, 0x6150, 0x6152, 0x4942, 0x3e49, 0x6159, 0x6158, 0x615a, 0x3c26, 0x3a2f, 0x4577, 0x615b, 0x444b, 0x615d, 0x4e21, 0x615c, 0x4169, 0x6162, 0x6164, 0x6165, 0x4354, 0x6163, 0x6160, 0x615e, 0x615f, 0x6161, 0x6168, 0x6166, 0x6167, 0x6169, 0x616b, 0x616c, 0x616d, 0x616e, 0x616a, 0x6170, 0x616f, 0x6171, 0x4e45, 0x6174, 0x6172, 0x6173, 0x3462, 0x4c7e, 0x4a4a, 0x6176, 0x6175, 0x6177, 0x6178, 0x617c, 0x6179, 0x617a, 0x617b, 0x617d, 0x617e, 0x6221, 0x6222, 0x6223, 0x482f, 0x4550, 0x6224, 0x4772, 0x4934, 0x6225, 0x6226, 0x452a, 0x3327, 0x3944, 0x6227, 0x6228, 0x6229, 0x3b29, 0x622b, 0x622a, 0x622c, 0x622d, 0x4869, 0x622e, 0x622f, 0x7369, 0x6230, 0x6231, 0x6232, 0x3b2e, 0x6233, 0x4756, 0x4b5f, 0x314e, 0x3157, 0x6234, 0x6236, 0x6235, 0x4570, 0x4039, 0x5d39, 0x6237, 0x4c41, 0x6238, 0x3446, 0x4857, 0x6239, 0x623a, 0x623b, 0x4c5c, 0x4c55, 0x443e, 0x416a, 0x623d, 0x3d62, 0x3e4a, 0x6240, 0x623f, 0x623e, 0x487d, 0x3447, 0x3829, 0x6246, 0x6243, 0x3f3f, 0x4c32, 0x6242, 0x6244, 0x6245, 0x6241, 0x6247, 0x6248, 0x442f, 0x3463, 0x4365, 0x6249, 0x624a, 0x624d, 0x3f67, 0x4644, 0x624e, 0x4b53, 0x624b, 0x624c, 0x6251, 0x6250, 0x624f, 0x6253, 0x6252, 0x6254, 0x6256, 0x6255, 0x4a4d, 0x3d56, 0x4e46, 0x6257, 0x4637, 0x6258, 0x6259, 0x625d, 0x625b, 0x625c, 0x625a, 0x625e, 0x625f, 0x6260, 0x6261, 0x4c37, 0x6262, 0x4c70, 0x6263, 0x434e, 0x476a, 0x366b, 0x433b, 0x6264, 0x363a, 0x4050, 0x6265, 0x3a3d, 0x6266, 0x6267, 0x3826, 0x3a55, 0x6269, 0x4556, 0x3a56, 0x354e, 0x4b24, 0x474b, 0x4557, 0x395c, 0x626b, 0x3e4b, 0x4e32, 0x3945, 0x3827, 0x4823, 0x626d, 0x626f, 0x386b, 0x626e, 0x4476, 0x6271, 0x3337, 0x626c, 0x486a, 0x3130, 0x3a6c, 0x4f52, 0x6270, 0x6272, 0x4a4b, 0x4059, 0x6274, 0x6275, 0x6273, 0x334e, 0x627b, 0x627a, 0x3c27, 0x627c, 0x6277, 0x627d, 0x6278, 0x4858, 0x6276, 0x6279, 0x6322, 0x6321, 0x4b61, 0x627e, 0x306b, 0x6324, 0x6323, 0x3e4c, 0x6325, 0x4143, 0x6327, 0x6326, 0x6328, 0x6268, 0x626a, 0x632a, 0x6329, 0x3c28, 0x4e69, 0x3c52, 0x632b, 0x3737, 0x3540, 0x3527, 0x3b63, 0x4d34, 0x6331, 0x6330, 0x4144, 0x632d, 0x632f, 0x3d4b, 0x3f40, 0x632e, 0x632c, 0x472a, 0x3e4d, 0x493c, 0x3a57, 0x4578, 0x6332, 0x6333, 0x6349, 0x3658, 0x4f3d, 0x4135, 0x6334, 0x3252, 0x4477, 0x4a21, 0x6335, 0x357a, 0x6336, 0x6338, 0x6339, 0x4729, 0x633a, 0x633b, 0x633c, 0x3659, 0x3253, 0x4645, 0x3d28, 0x3b64, 0x633d, 0x3d29, 0x324a, 0x4943, 0x633e, 0x486b, 0x4145, 0x6341, 0x6342, 0x4769, 0x3f41, 0x633f, 0x4361, 0x6340, 0x3e4e, 0x305c, 0x3529, 0x6343, 0x4478, 0x6344, 0x4047, 0x4c2d, 0x4923, 0x6345, 0x6346, 0x4355, 0x4e47, 0x6348, 0x6347, 0x3c6f, 0x634a, 0x3070, 0x634d, 0x634b, 0x3254, 0x374e, 0x634c, 0x3946, 0x3972, 0x4a66, 0x634e, 0x4b54, 0x6350, 0x4051, 0x314f, 0x323a, 0x302c, 0x634f, 0x6351, 0x6352, 0x3e77, 0x6353, 0x334f, 0x6355, 0x376a, 0x3566, 0x6356, 0x3675, 0x6357, 0x407c, 0x464d, 0x4060, 0x3a75, 0x6358, 0x4362, 0x416b, 0x635a, 0x635c, 0x6359, 0x635b, 0x3722, 0x635d, 0x3726, 0x3567, 0x4d52, 0x635f, 0x6360, 0x312e, 0x6363, 0x3376, 0x6362, 0x6361, 0x6365, 0x635e, 0x6366, 0x4e29, 0x6367, 0x6368, 0x5474, 0x636a, 0x6369, 0x636b, 0x636c, 0x4e35, 0x636d, 0x706f, 0x3e4f, 0x636e, 0x636f, 0x3d57, 0x4638, 0x6370, 0x4328, 0x6371, 0x433c, 0x6372, 0x3625, 0x513f, 0x435d, 0x3c33, 0x3448, 0x6373, 0x6422, 0x6376, 0x3568, 0x6375, 0x6424, 0x6374, 0x3e50, 0x6378, 0x6379, 0x452b, 0x637a, 0x335e, 0x3f5a, 0x4964, 0x637c, 0x4268, 0x6377, 0x637b, 0x637d, 0x3a7b, 0x6426, 0x492e, 0x4826, 0x4579, 0x365a, 0x6425, 0x6423, 0x4835, 0x637e, 0x435e, 0x457b, 0x457a, 0x3a76, 0x6438, 0x6428, 0x642a, 0x642d, 0x642e, 0x642b, 0x642c, 0x6429, 0x6427, 0x6421, 0x4a4f, 0x3255, 0x6435, 0x6432, 0x6437, 0x6436, 0x4773, 0x4c27, 0x3b3b, 0x6430, 0x6439, 0x6434, 0x6433, 0x642f, 0x6431, 0x3449, 0x433d, 0x407d, 0x4822, 0x643e, 0x4824, 0x4061, 0x643b, 0x484f, 0x643f, 0x4a53, 0x435b, 0x643a, 0x643c, 0x643d, 0x6440, 0x3c44, 0x4646, 0x6445, 0x6444, 0x6441, 0x4f36, 0x644a, 0x644e, 0x644b, 0x6447, 0x6448, 0x644d, 0x6442, 0x5255, 0x6449, 0x6443, 0x644c, 0x6452, 0x344a, 0x644f, 0x6450, 0x6451, 0x6454, 0x6453, 0x4876, 0x6455, 0x4e7c, 0x4a6d, 0x645a, 0x6457, 0x6456, 0x4052, 0x6459, 0x645b, 0x6458, 0x645f, 0x645c, 0x645d, 0x6446, 0x645e, 0x6460, 0x6461, 0x4a46, 0x6462, 0x4c62, 0x364e, 0x3729, 0x6463, 0x4a34, 0x3f68, 0x4c30, 0x6464, 0x4e33, 0x4774, 0x4146, 0x4734, 0x3d4d, 0x3040, 0x6469, 0x6467, 0x6465, 0x3421, 0x3e51, 0x646a, 0x6468, 0x6466, 0x646e, 0x646d, 0x646c, 0x646b, 0x646f, 0x6470, 0x403a, 0x6471, 0x6473, 0x6472, 0x3852, 0x4138, 0x6475, 0x457c, 0x6474, 0x6476, 0x4a35, 0x416c, 0x3947, 0x6477, 0x4e48, 0x6479, 0x647a, 0x647b, 0x647c, 0x3b65, 0x647d, 0x374f, 0x356a, 0x352a, 0x6521, 0x4c73, 0x3948, 0x647e, 0x6524, 0x4c66, 0x473c, 0x4933, 0x3d63, 0x6523, 0x3c53, 0x3949, 0x3b66, 0x3569, 0x4a36, 0x6522, 0x4147, 0x4b42, 0x3a77, 0x3b67, 0x445d, 0x6527, 0x4e5f, 0x3a59, 0x6528, 0x3f42, 0x652a, 0x3e52, 0x3a30, 0x6529, 0x3d2a, 0x383e, 0x4148, 0x6525, 0x652b, 0x6526, 0x3750, 0x652e, 0x6532, 0x376b, 0x652d, 0x6536, 0x394a, 0x4d6d, 0x303c, 0x6533, 0x356b, 0x6530, 0x6531, 0x457d, 0x652f, 0x652c, 0x3328, 0x4064, 0x3828, 0x6538, 0x6535, 0x6537, 0x6534, 0x3751, 0x4233, 0x6539, 0x416e, 0x6546, 0x6542, 0x653c, 0x6540, 0x3c7a, 0x305d, 0x653b, 0x6543, 0x6547, 0x394b, 0x4c56, 0x4456, 0x653d, 0x6545, 0x653a, 0x433e, 0x653f, 0x303d, 0x4c4a, 0x653e, 0x365b, 0x486c, 0x416d, 0x4e50, 0x3d6f, 0x656e, 0x6548, 0x407e, 0x6544, 0x6549, 0x654b, 0x4479, 0x654e, 0x654a, 0x4a54, 0x344b, 0x4c4b, 0x305e, 0x654d, 0x4e7d, 0x654c, 0x316f, 0x466c, 0x654f, 0x6556, 0x6550, 0x6557, 0x6553, 0x477b, 0x3c4a, 0x6555, 0x6552, 0x6558, 0x6551, 0x3d44, 0x4b25, 0x3d4c, 0x6554, 0x6560, 0x655c, 0x655f, 0x655d, 0x6561, 0x655b, 0x6541, 0x4053, 0x484b, 0x655e, 0x6559, 0x4121, 0x3752, 0x3d2b, 0x3f25, 0x4136, 0x6564, 0x6566, 0x6567, 0x6563, 0x6565, 0x655a, 0x6562, 0x656a, 0x6569, 0x4b7a, 0x372b, 0x6568, 0x656c, 0x656b, 0x656f, 0x6571, 0x3b3c, 0x656d, 0x6572, 0x6573, 0x6574, 0x657a, 0x453b, 0x6576, 0x6575, 0x6577, 0x6578, 0x6579, 0x657b, 0x657c, 0x344c, 0x657d, 0x657e, 0x6621, 0x6622, 0x6623, 0x6624, 0x6625, 0x6626, 0x6628, 0x6627, 0x6629, 0x662a, 0x662b, 0x662e, 0x662c, 0x662d, 0x3a61, 0x3753, 0x4356, 0x4833, 0x3d70, 0x474d, 0x486d, 0x662f, 0x586d, 0x6630, 0x6632, 0x4d65, 0x6631, 0x6634, 0x6633, 0x4d53, 0x6635, 0x487e, 0x6636, 0x6639, 0x6638, 0x6637, 0x663a, 0x3732, 0x4122, 0x3541, 0x663e, 0x663b, 0x663c, 0x663f, 0x6640, 0x663d, 0x3129, 0x3227, 0x6642, 0x6643, 0x6644, 0x4d62, 0x3d2c, 0x6646, 0x6645, 0x3f69, 0x6647, 0x6648, 0x6649, 0x3465, 0x344d, 0x664a, 0x664b, 0x4b5d, 0x4d63, 0x4d54, 0x4f37, 0x394d, 0x664e, 0x3c54, 0x664d, 0x664f, 0x3c29, 0x4251, 0x6650, 0x394c, 0x4c57, 0x6651, 0x6652, 0x6653, 0x6654, 0x6655, 0x3c2a, 0x4c6d, 0x6657, 0x433f, 0x6656, 0x6659, 0x6658, 0x665a, 0x403b, 0x665b, 0x665c, 0x4a39, 0x665d, 0x416f, 0x665e, 0x665f, 0x4e7e, 0x6662, 0x6661, 0x6660, 0x4430, 0x6663, 0x3f26, 0x6664, 0x6665, 0x4f38, 0x6666, 0x6667, 0x6669, 0x6668, 0x4825, 0x4679, 0x4f3e, 0x4829, 0x666b, 0x3e53, 0x492a, 0x666c, 0x666a, 0x344e, 0x3854, 0x3b68, 0x486e, 0x382a, 0x4b43, 0x666f, 0x666d, 0x394e, 0x394f, 0x3069, 0x3a68, 0x4759, 0x305f, 0x6674, 0x4340, 0x4758, 0x425b, 0x6676, 0x6672, 0x6675, 0x6670, 0x6673, 0x4b26, 0x3855, 0x307d, 0x6671, 0x6678, 0x6679, 0x4639, 0x363b, 0x6726, 0x473d, 0x3b69, 0x363c, 0x4048, 0x4f46, 0x4c2e, 0x6677, 0x4054, 0x3553, 0x667a, 0x667c, 0x667b, 0x667d, 0x4326, 0x473e, 0x4431, 0x6723, 0x6722, 0x667e, 0x3f55, 0x4965, 0x6725, 0x6724, 0x3950, 0x4f53, 0x6735, 0x6729, 0x672a, 0x3c70, 0x6728, 0x3978, 0x6727, 0x672b, 0x4432, 0x4a22, 0x4123, 0x425c, 0x672f, 0x6730, 0x672c, 0x672d, 0x672e, 0x3951, 0x6736, 0x6732, 0x4966, 0x4b6c, 0x4928, 0x6731, 0x6734, 0x6733, 0x4b44, 0x6737, 0x6738, 0x4137, 0x6739, 0x673b, 0x673f, 0x673c, 0x673a, 0x473f, 0x673d, 0x673e, 0x3232, 0x6745, 0x6740, 0x6741, 0x6742, 0x4221, 0x6744, 0x6743, 0x6746, 0x6747, 0x6748, 0x3f43, 0x3269, 0x6749, 0x4e57, 0x3c2b, 0x3d2d, 0x3b6a, 0x4357, 0x674a, 0x674b, 0x3131, 0x674c, 0x674d, 0x674e, 0x674f, 0x6750, 0x363d, 0x5a2a, 0x6751, 0x4065, 0x6752, 0x3c4b, 0x6753, 0x5030, 0x6754, 0x4a5e, 0x345c, 0x4124, 0x3d58, 0x4971, 0x3d2e, 0x6755, 0x3952, 0x6756, 0x484c, 0x6764, 0x6758, 0x4249, 0x4775, 0x383f, 0x6757, 0x4125, 0x6759, 0x447a, 0x675b, 0x675a, 0x675d, 0x675c, 0x675e, 0x6760, 0x675f, 0x344f, 0x6761, 0x6762, 0x6763, 0x3a31, 0x4e49, 0x6765, 0x3f27, 0x3170, 0x6766, 0x6767, 0x6768, 0x3072, 0x6769, 0x676a, 0x4967, 0x3c47, 0x676c, 0x3329, 0x3032, 0x676b, 0x676e, 0x474e, 0x3f44, 0x3256, 0x4b27, 0x375d, 0x365c, 0x676d, 0x326a, 0x3423, 0x3171, 0x6772, 0x4e6a, 0x425d, 0x4944, 0x677e, 0x3257, 0x677c, 0x677a, 0x6771, 0x676f, 0x6770, 0x3c63, 0x366c, 0x4377, 0x4651, 0x3151, 0x6774, 0x6773, 0x6779, 0x6775, 0x6778, 0x4c50, 0x6777, 0x3258, 0x337d, 0x677b, 0x677d, 0x3754, 0x6823, 0x682c, 0x682d, 0x302b, 0x6834, 0x3071, 0x682b, 0x682a, 0x6825, 0x6824, 0x6822, 0x6821, 0x4363, 0x427b, 0x6827, 0x6826, 0x6829, 0x4170, 0x3755, 0x3141, 0x6828, 0x3953, 0x4171, 0x683a, 0x683b, 0x3259, 0x322e, 0x6838, 0x682e, 0x6836, 0x683d, 0x6837, 0x6835, 0x6776, 0x6833, 0x682f, 0x3450, 0x6831, 0x683c, 0x6832, 0x683e, 0x6830, 0x477c, 0x4d69, 0x6839, 0x684f, 0x6847, 0x3f7b, 0x3546, 0x365d, 0x6842, 0x325b, 0x3e54, 0x6845, 0x3a5a, 0x4551, 0x684a, 0x4a6e, 0x6841, 0x325a, 0x3856, 0x4929, 0x684b, 0x683f, 0x6848, 0x6852, 0x6843, 0x6844, 0x463a, 0x6849, 0x6846, 0x4b28, 0x684c, 0x3060, 0x6840, 0x684e, 0x684d, 0x476b, 0x6854, 0x685f, 0x337e, 0x6862, 0x6850, 0x6855, 0x4d6e, 0x685e, 0x4d55, 0x4e2a, 0x4378, 0x336b, 0x4972, 0x6864, 0x4621, 0x3031, 0x685d, 0x6859, 0x4172, 0x6853, 0x685b, 0x6860, 0x472c, 0x302a, 0x6858, 0x6861, 0x4978, 0x685c, 0x6857, 0x3e55, 0x3d2f, 0x3c2c, 0x4c58, 0x4947, 0x6867, 0x6870, 0x685a, 0x3377, 0x3e78, 0x6865, 0x686a, 0x4173, 0x6866, 0x686d, 0x435f, 0x686e, 0x4d56, 0x6863, 0x3338, 0x6869, 0x686c, 0x4c2c, 0x686f, 0x6868, 0x686b, 0x4b29, 0x4f21, 0x6873, 0x687a, 0x6872, 0x3c43, 0x6851, 0x4a4e, 0x4c22, 0x6879, 0x6878, 0x6874, 0x6875, 0x3136, 0x6877, 0x6871, 0x4455, 0x6876, 0x307e, 0x4222, 0x4a43, 0x687b, 0x6921, 0x4859, 0x687e, 0x3e56, 0x3c49, 0x6923, 0x363e, 0x6924, 0x4979, 0x687d, 0x6856, 0x687c, 0x4f4f, 0x4622, 0x4973, 0x692b, 0x6931, 0x6932, 0x6925, 0x4776, 0x692f, 0x6927, 0x6929, 0x6933, 0x6928, 0x692c, 0x3172, 0x4665, 0x692d, 0x6930, 0x6926, 0x4126, 0x692a, 0x3b27, 0x3f45, 0x3730, 0x4c74, 0x4c79, 0x3d72, 0x6937, 0x6935, 0x4f4e, 0x6934, 0x4d75, 0x6936, 0x6938, 0x6939, 0x693c, 0x693a, 0x4623, 0x693b, 0x484d, 0x692e, 0x3d73, 0x693d, 0x6942, 0x4174, 0x6941, 0x6922, 0x6943, 0x4149, 0x693e, 0x6940, 0x693f, 0x5d31, 0x5d22, 0x6945, 0x6944, 0x4d76, 0x623c, 0x6946, 0x6947, 0x6948, 0x3857, 0x3554, 0x694a, 0x515d, 0x3575, 0x4e3a, 0x3673, 0x694b, 0x694c, 0x436e, 0x694d, 0x467a, 0x303a, 0x3263, 0x6952, 0x6953, 0x694e, 0x3b3d, 0x694f, 0x4742, 0x6950, 0x6951, 0x695b, 0x6955, 0x6958, 0x6954, 0x6956, 0x6957, 0x3c58, 0x6959, 0x4341, 0x3756, 0x3342, 0x695c, 0x333f, 0x6961, 0x695d, 0x6960, 0x483a, 0x695e, 0x695f, 0x4948, 0x485a, 0x6962, 0x427d, 0x696c, 0x6968, 0x326b, 0x6966, 0x4b2a, 0x6967, 0x6964, 0x6965, 0x696a, 0x696d, 0x696b, 0x6969, 0x6963, 0x4358, 0x6974, 0x4c2a, 0x6972, 0x6973, 0x696e, 0x6970, 0x6971, 0x696f, 0x4066, 0x4f39, 0x6978, 0x6979, 0x6a21, 0x3f2a, 0x697b, 0x697e, 0x6976, 0x6975, 0x6a22, 0x325c, 0x697c, 0x6a23, 0x697d, 0x697a, 0x4433, 0x6977, 0x4768, 0x6a27, 0x4d3b, 0x6a26, 0x6a25, 0x6a2e, 0x6a28, 0x6a30, 0x4d66, 0x6a33, 0x6a2a, 0x6a2b, 0x6a2f, 0x6a32, 0x6a31, 0x6a29, 0x6a2c, 0x6a3d, 0x6a36, 0x6a34, 0x6a35, 0x6a3a, 0x6a3b, 0x332a, 0x3542, 0x6a39, 0x6a24, 0x6a38, 0x6a3c, 0x6a37, 0x6a3e, 0x6a40, 0x6a3f, 0x6a42, 0x6a41, 0x695a, 0x6a46, 0x6a43, 0x6a44, 0x6a45, 0x6a47, 0x376c, 0x6a49, 0x6a48, 0x3d30, 0x3954, 0x5e27, 0x6a4a, 0x3d51, 0x3339, 0x6a4b, 0x3152, 0x3e57, 0x6a4c, 0x3955, 0x6a4d, 0x3061, 0x493d, 0x6a4e, 0x3f6a, 0x6a55, 0x6a52, 0x436f, 0x6a53, 0x6a50, 0x365e, 0x6a4f, 0x6a56, 0x3736, 0x425e, 0x6a5c, 0x6a58, 0x4235, 0x6a57, 0x6a5a, 0x6a51, 0x6a5b, 0x6a5d, 0x486f, 0x6a59, 0x6a5e, 0x6a60, 0x3853, 0x6a54, 0x3041, 0x6a5f, 0x3a5b, 0x4e76, 0x6a61, 0x6a62, 0x4175, 0x4e22, 0x6a63, 0x4d35, 0x6a64, 0x6a65, 0x4a64, 0x6a66, 0x3a40, 0x4e23, 0x6a6b, 0x6a6c, 0x3e58, 0x6a6a, 0x4d67, 0x6a67, 0x6a69, 0x403d, 0x3f7e, 0x6a68, 0x6a6d, 0x4a23, 0x6a6f, 0x6a6e, 0x336c, 0x4b2b, 0x6a70, 0x6a7c, 0x6a72, 0x6a73, 0x6a74, 0x6a75, 0x6a79, 0x6a7a, 0x6a78, 0x6a76, 0x6a71, 0x6a77, 0x6a7b, 0x7037, 0x3228, 0x6a7e, 0x365f, 0x6a7d, 0x6b22, 0x6b21, 0x6b24, 0x6b23, 0x6b25, 0x3d31, 0x6b26, 0x6b27, 0x6b28, 0x403e, 0x4d57, 0x6b29, 0x4a24, 0x4746, 0x6b2a, 0x6b2b, 0x382b, 0x352c, 0x6b2c, 0x3b6b, 0x4741, 0x6b2d, 0x3350, 0x6b2e, 0x6b30, 0x4d77, 0x6b2f, 0x3f46, 0x6b31, 0x6b32, 0x6b33, 0x3451, 0x6b34, 0x6b35, 0x6b36, 0x6b37, 0x3351, 0x6b38, 0x6b39, 0x6b3a, 0x3272, 0x3f28, 0x6b3b, 0x6b3c, 0x6b3d, 0x3840, 0x447b, 0x6b3e, 0x3757, 0x3f56, 0x6b41, 0x4624, 0x6b40, 0x3731, 0x6b3f, 0x4277, 0x352d, 0x6b42, 0x6b43, 0x3e59, 0x376d, 0x6b44, 0x4b2c, 0x405f, 0x3576, 0x4c75, 0x414a, 0x6b45, 0x3f47, 0x4370, 0x3e5a, 0x6b46, 0x6b49, 0x6b4a, 0x3a3e, 0x4242, 0x6b48, 0x3e5b, 0x493e, 0x6b47, 0x3b6c, 0x3153, 0x6b4e, 0x3758, 0x3b6e, 0x3b6d, 0x4f4d, 0x6b4d, 0x6b4c, 0x4127, 0x354d, 0x4f43, 0x333a, 0x3e5c, 0x6b4b, 0x6b50, 0x6b51, 0x6b4f, 0x3858, 0x4d40, 0x3b6f, 0x4727, 0x6b54, 0x4040, 0x4342, 0x4d36, 0x6b57, 0x386c, 0x403f, 0x6b53, 0x6b58, 0x386d, 0x6b55, 0x6b56, 0x6b52, 0x4062, 0x4649, 0x432f, 0x325d, 0x4870, 0x3543, 0x4434, 0x6b5b, 0x6b59, 0x434c, 0x4041, 0x3452, 0x6b5a, 0x3f5b, 0x4e4a, 0x4f40, 0x6b5c, 0x6b67, 0x4435, 0x6b66, 0x6b63, 0x6b6b, 0x6b64, 0x6b60, 0x447c, 0x6b5f, 0x6b5d, 0x4d21, 0x3b70, 0x6b61, 0x6b5e, 0x6b65, 0x3d74, 0x3841, 0x427a, 0x4b45, 0x315a, 0x3062, 0x4625, 0x6b69, 0x6b68, 0x4666, 0x6b6d, 0x6b62, 0x6b6c, 0x6b6e, 0x382c, 0x6b6a, 0x3956, 0x3c55, 0x6b6f, 0x4d58, 0x6b72, 0x6b75, 0x6b73, 0x4935, 0x6b70, 0x3660, 0x6b74, 0x6b76, 0x6b7a, 0x6b77, 0x6b79, 0x6b78, 0x6b7b, 0x3c31, 0x6b7d, 0x6b7c, 0x4968, 0x6c21, 0x3759, 0x6b7e, 0x6c22, 0x6c23, 0x3544, 0x6641, 0x3e79, 0x6c24, 0x386e, 0x6c25, 0x6c26, 0x3b3e, 0x5a4e, 0x6c27, 0x6c28, 0x3d32, 0x6c29, 0x6c2a, 0x6c2b, 0x6c2c, 0x6c2d, 0x432b, 0x6c2e, 0x6c30, 0x6c2f, 0x4626, 0x6c31, 0x4b2d, 0x6c32, 0x6c33, 0x6c34, 0x6c35, 0x465a, 0x3e5d, 0x6c36, 0x396b, 0x502e, 0x6c37, 0x6c38, 0x493f, 0x6c39, 0x6c41, 0x6c3a, 0x6c3c, 0x6c3b, 0x6c3d, 0x4b46, 0x6c3e, 0x6c3f, 0x6c40, 0x6c42, 0x332d, 0x4467, 0x4969, 0x3a62, 0x3957, 0x494f, 0x325f, 0x484e, 0x6c45, 0x3453, 0x4055, 0x6c44, 0x6c49, 0x4379, 0x4c63, 0x6c47, 0x6c48, 0x352e, 0x6c4a, 0x4763, 0x425f, 0x4871, 0x453d, 0x6c46, 0x4b47, 0x326c, 0x6c4c, 0x4f28, 0x4442, 0x4f45, 0x3b71, 0x6c4b, 0x4231, 0x6c5c, 0x4128, 0x4678, 0x4950, 0x6c4f, 0x3b3f, 0x3b72, 0x3e5e, 0x4765, 0x382d, 0x6c4e, 0x6c4d, 0x496a, 0x3c41, 0x4552, 0x6c51, 0x6c52, 0x3958, 0x6c50, 0x6c53, 0x6c54, 0x6c56, 0x4223, 0x6c55, 0x3466, 0x6c58, 0x6c57, 0x6c59, 0x6c5b, 0x6c5d, 0x6c5e, 0x4056, 0x3c4f, 0x6c5f, 0x3352, 0x6c60, 0x4176, 0x6c61, 0x6c62, 0x496b, 0x352f, 0x6c63, 0x4436, 0x315b, 0x6c64, 0x3c71, 0x3f76, 0x422d, 0x6c67, 0x6c66, 0x6c65, 0x6c6d, 0x6c6b, 0x6c68, 0x6c6a, 0x6c69, 0x6c6c, 0x3577, 0x6c70, 0x4057, 0x6c71, 0x3859, 0x6c6e, 0x6c6f, 0x4f29, 0x4437, 0x4129, 0x6c72, 0x6c75, 0x6c73, 0x6c74, 0x4d59, 0x4627, 0x6c78, 0x6c76, 0x6c77, 0x6c79, 0x6d29, 0x6c7c, 0x6c7d, 0x6c7b, 0x6c7a, 0x447d, 0x6d21, 0x6d25, 0x6d22, 0x6c7e, 0x6d23, 0x6d24, 0x6d2b, 0x6d26, 0x4058, 0x6d28, 0x6d2a, 0x6d27, 0x6d2d, 0x3d33, 0x6d2c, 0x6d2e, 0x6d2f, 0x6d32, 0x6d31, 0x6d30, 0x6d34, 0x6d33, 0x4c76, 0x6d36, 0x6d35, 0x6d37, 0x6d38, 0x6d3a, 0x6d39, 0x3f48, 0x6d3b, 0x366d, 0x6d3c, 0x6d3e, 0x6d3f, 0x6d40, 0x6d3d, 0x6d41, 0x3c56, 0x6d42, 0x3530, 0x3733, 0x382e, 0x6d43, 0x4670, 0x453e, 0x6d44, 0x6d47, 0x3c34, 0x6d46, 0x6d45, 0x375a, 0x6d48, 0x3353, 0x6d4a, 0x3a5c, 0x6d49, 0x6d52, 0x6d4c, 0x6d4e, 0x4a65, 0x6d4b, 0x6d4d, 0x6d51, 0x6d4f, 0x3531, 0x6d50, 0x6d53, 0x475a, 0x4e58, 0x3d34, 0x6d54, 0x4d22, 0x6d56, 0x6d55, 0x6d59, 0x4d41, 0x6d58, 0x336d, 0x6d57, 0x6d5c, 0x6d5b, 0x6d5a, 0x4532, 0x6d5d, 0x6d5e, 0x6d5f, 0x396c, 0x3725, 0x6d60, 0x6d61, 0x6d62, 0x3f49, 0x6d63, 0x3c2d, 0x6d64, 0x6d65, 0x5221, 0x517e, 0x6d66, 0x6570, 0x6d67, 0x4324, 0x3f2b, 0x4740, 0x6d68, 0x4a55, 0x4454, 0x397e, 0x4329, 0x312a, 0x4b78, 0x3f57, 0x375e, 0x3661, 0x4a56, 0x6d69, 0x6d6b, 0x6d6a, 0x3260, 0x4676, 0x6d6c, 0x4777, 0x4533, 0x6d6d, 0x3d52, 0x6d6f, 0x4c42, 0x6d7e, 0x6d71, 0x6d72, 0x4449, 0x4260, 0x4177, 0x4628, 0x6d70, 0x3555, 0x6d79, 0x6d76, 0x6e25, 0x4629, 0x4360, 0x6d73, 0x447e, 0x4553, 0x6d74, 0x6d78, 0x3f60, 0x4767, 0x444c, 0x4042, 0x6d77, 0x422e, 0x4224, 0x6d75, 0x3029, 0x4f22, 0x6d7a, 0x4261, 0x3d35, 0x3f4a, 0x6d7c, 0x6d7b, 0x306f, 0x6d7d, 0x492f, 0x6e27, 0x465b, 0x3f6b, 0x4359, 0x3678, 0x6e26, 0x4d37, 0x313f, 0x4a57, 0x3261, 0x6e21, 0x6e22, 0x6e23, 0x6e24, 0x463b, 0x4323, 0x3063, 0x6e28, 0x6e29, 0x7423, 0x423d, 0x6e2a, 0x3173, 0x414c, 0x382f, 0x4d5a, 0x6e2b, 0x452c, 0x4178, 0x3c57, 0x6e2c, 0x6e2f, 0x3d65, 0x6e2d, 0x412b, 0x412a, 0x3064, 0x4e4b, 0x6e31, 0x4872, 0x6e33, 0x6e32, 0x6e30, 0x6364, 0x3454, 0x6d6e, 0x6e35, 0x6e34, 0x6e36, 0x4d38, 0x4661, 0x4b2e, 0x6e37, 0x3c59, 0x6e38, 0x6e39, 0x6e3a, 0x4521, 0x306a, 0x3959, 0x4f3a, 0x6e3e, 0x3734, 0x6e3b, 0x6e3c, 0x4974, 0x3354, 0x4d39, 0x363f, 0x4554, 0x6e3f, 0x6e40, 0x6e41, 0x4522, 0x6e43, 0x6e42, 0x4653, 0x6e44, 0x3d36, 0x3c60, 0x475b, 0x4371, 0x3c72, 0x3f6c, 0x6e45, 0x6e46, 0x3f5d, 0x6e47, 0x6e48, 0x6e49, 0x4d6f, 0x3d37, 0x6e4b, 0x6e4a, 0x395a, 0x3973, 0x3b40, 0x6e4e, 0x3d66, 0x6e4d, 0x6e4c, 0x4269, 0x386f, 0x4043, 0x4830, 0x3d39, 0x6e4f, 0x3e5f, 0x6e52, 0x6e50, 0x6e51, 0x6e54, 0x6e53, 0x3e7a, 0x6e55, 0x6e56, 0x6e57, 0x4850, 0x3a53, 0x3c61, 0x6e58, 0x6e59, 0x4e24, 0x3d45, 0x4c6e, 0x4e4c, 0x6e5a, 0x3662, 0x6e5b, 0x4523, 0x6e5e, 0x3378, 0x3f4b, 0x6e5c, 0x6e5d, 0x4460, 0x4b55, 0x367c, 0x6e60, 0x6e61, 0x6e5f, 0x6e63, 0x465f, 0x3343, 0x6e67, 0x6e64, 0x6e66, 0x6e62, 0x6f4f, 0x6e65, 0x4e6b, 0x385a, 0x6e6f, 0x4534, 0x6e6a, 0x6e6d, 0x6e6b, 0x6e70, 0x6e71, 0x6e69, 0x6e76, 0x3174, 0x6e68, 0x482d, 0x6e6c, 0x3e60, 0x395b, 0x4b48, 0x3664, 0x3d46, 0x463c, 0x412d, 0x6e74, 0x6e6e, 0x6e73, 0x4c43, 0x4438, 0x6e75, 0x6e72, 0x412c, 0x6e79, 0x6e78, 0x6e77, 0x4b2f, 0x3d7b, 0x6e7a, 0x4a5f, 0x3154, 0x4946, 0x4372, 0x3578, 0x6e7c, 0x395d, 0x3b2c, 0x6e7b, 0x3f6d, 0x3f6e, 0x6f21, 0x6f23, 0x3e7b, 0x6f22, 0x6f24, 0x3653, 0x4945, 0x3c62, 0x4f23, 0x6e7e, 0x3a78, 0x4f3f, 0x6f26, 0x6f25, 0x6f27, 0x6e7d, 0x4669, 0x4555, 0x4457, 0x6f2c, 0x4343, 0x6f28, 0x6f29, 0x372d, 0x6f2b, 0x3830, 0x6f2a, 0x3e61, 0x3379, 0x6f30, 0x3a3f, 0x4179, 0x444a, 0x333b, 0x6f2e, 0x6f2f, 0x4443, 0x6f2d, 0x6f31, 0x6f37, 0x6f3a, 0x6f39, 0x452d, 0x6f32, 0x6f33, 0x6f36, 0x6f38, 0x3640, 0x6f3b, 0x6f35, 0x6f34, 0x6f3f, 0x6f40, 0x6f41, 0x6f3e, 0x6f3d, 0x3e62, 0x462a, 0x6f3c, 0x6f45, 0x6f43, 0x6f44, 0x6f42, 0x4278, 0x6f46, 0x6f47, 0x6f49, 0x3455, 0x6f48, 0x4c7a, 0x6f54, 0x6f4a, 0x6f4d, 0x6f4b, 0x6f4c, 0x6f4e, 0x6f50, 0x6f51, 0x6f52, 0x6f55, 0x6f53, 0x6f56, 0x6f58, 0x6f57, 0x4439, 0x4c67, 0x6f59, 0x412e, 0x6f5a, 0x4a44, 0x6f5b, 0x332b, 0x313c, 0x3457, 0x3456, 0x6f5c, 0x6f5d, 0x6f5e, 0x6f5f, 0x6f60, 0x3458, 0x3355, 0x395e, 0x4836, 0x6f62, 0x6f61, 0x6f63, 0x315c, 0x6f66, 0x6f65, 0x6f64, 0x6f67, 0x6f6a, 0x3047, 0x6f68, 0x6f6c, 0x6f6b, 0x6f6e, 0x6f6d, 0x6f6f, 0x462e, 0x6f70, 0x6f71, 0x6f73, 0x6f72, 0x496c, 0x6f74, 0x6f75, 0x3a65, 0x6f76, 0x6f77, 0x4b49, 0x414b, 0x3024, 0x424b, 0x6f78, 0x496d, 0x6f7b, 0x6f79, 0x395f, 0x6f7a, 0x3842, 0x4a45, 0x6f7d, 0x7021, 0x6f7e, 0x7022, 0x3121, 0x3f58, 0x3d7c, 0x3459, 0x7023, 0x4766, 0x7025, 0x3122, 0x7024, 0x4444, 0x4e4d, 0x462b, 0x6f7c, 0x4e26, 0x3831, 0x4d5b, 0x3679, 0x4e34, 0x3728, 0x4262, 0x6721, 0x7026, 0x332c, 0x3f6f, 0x3356, 0x7028, 0x7029, 0x7027, 0x3764, 0x3a5d, 0x3e63, 0x3123, 0x4e59, 0x702b, 0x6e2e, 0x702a, 0x702e, 0x702c, 0x702d, 0x702f, 0x7030, 0x4e6c, 0x7031, 0x7032, 0x4049, 0x483b, 0x3f7d, 0x3467, 0x4d3a, 0x326d, 0x3d38, 0x385b, 0x7035, 0x7034, 0x3b73, 0x7036, 0x7033, 0x3b28, 0x703a, 0x6a2d, 0x5256, 0x3f77, 0x7038, 0x4e25, 0x4671, 0x312b, 0x4063, 0x3c36, 0x4a37, 0x3140, 0x4e6d, 0x4d6b, 0x703b, 0x4545, 0x3c7b, 0x703c, 0x703d, 0x3f4c, 0x703e, 0x4e6e, 0x7039, 0x7040, 0x7042, 0x7041, 0x703f, 0x7043, 0x7044, 0x417a, 0x3262, 0x7045, 0x4c38, 0x7046, 0x7047, 0x4f2a, 0x5b31, 0x7048, 0x7049, 0x704a, 0x704e, 0x704b, 0x704c, 0x704d, 0x704f, 0x4044, 0x4c77, 0x4045, 0x7050, 0x4873, 0x7051, 0x7353, 0x4c4c, 0x7052, 0x7053, 0x7054, 0x3357, 0x7056, 0x3f59, 0x7057, 0x3724, 0x7058, 0x705c, 0x705a, 0x705b, 0x3373, 0x7059, 0x705d, 0x705e, 0x3048, 0x705f, 0x7060, 0x3e64, 0x7061, 0x3547, 0x7064, 0x7063, 0x7062, 0x6b71, 0x4a5c, 0x7065, 0x7066, 0x7067, 0x7068, 0x7069, 0x706a, 0x345a, 0x706b, 0x706c, 0x4723, 0x706e, 0x323b, 0x7071, 0x7070, 0x3124, 0x3641, 0x4a47, 0x443a, 0x3a22, 0x3960, 0x3d67, 0x3f5c, 0x7073, 0x7072, 0x4d42, 0x3468, 0x4852, 0x465c, 0x3f7c, 0x4e4e, 0x375b, 0x7076, 0x7075, 0x4b4b, 0x462c, 0x3150, 0x7077, 0x7074, 0x4951, 0x4d6a, 0x7078, 0x7079, 0x707b, 0x426a, 0x335b, 0x335c, 0x707a, 0x3469, 0x3832, 0x346a, 0x453f, 0x4e60, 0x385c, 0x707c, 0x707d, 0x707e, 0x7121, 0x7123, 0x7122, 0x4977, 0x7124, 0x7125, 0x7126, 0x7127, 0x7129, 0x7128, 0x712a, 0x4874, 0x664c, 0x3f29, 0x3532, 0x712b, 0x712c, 0x522c, 0x5d3b, 0x4853, 0x307b, 0x303b, 0x3b74, 0x4b30, 0x3e7e, 0x712d, 0x4c5f, 0x712e, 0x4d5c, 0x3142, 0x3b41, 0x712f, 0x326e, 0x7130, 0x7131, 0x7133, 0x7134, 0x7136, 0x7132, 0x7135, 0x345b, 0x7137, 0x7138, 0x7139, 0x713a, 0x713b, 0x713d, 0x713c, 0x713f, 0x7142, 0x713e, 0x7140, 0x7141, 0x7143, 0x3642, 0x3c73, 0x7144, 0x7145, 0x3961, 0x7146, 0x333e, 0x474f, 0x7147, 0x7148, 0x435a, 0x466b, 0x7149, 0x477d, 0x424c, 0x3158, 0x366e, 0x366f, 0x4373, 0x714e, 0x3670, 0x326f, 0x714d, 0x714b, 0x714c, 0x714a, 0x7158, 0x714f, 0x7150, 0x7151, 0x7152, 0x7154, 0x7153, 0x3d59, 0x7155, 0x7157, 0x3533, 0x7156, 0x417b, 0x3833, 0x7159, 0x424d, 0x715a, 0x462d, 0x715b, 0x7160, 0x715e, 0x715d, 0x715f, 0x715c, 0x7162, 0x7161, 0x7164, 0x3643, 0x7163, 0x7165, 0x7166, 0x7168, 0x7167, 0x7169, 0x716b, 0x716a, 0x397c, 0x716c, 0x716d, 0x333c, 0x716e, 0x716f, 0x3f71, 0x7170, 0x7171, 0x7172, 0x7173, 0x3962, 0x7174, 0x7175, 0x7176, 0x7177, 0x7178, 0x4831, 0x717a, 0x4926, 0x717b, 0x7179, 0x717d, 0x717c, 0x717e, 0x7221, 0x7222, 0x7223, 0x7224, 0x7225, 0x7226, 0x7227, 0x7228, 0x7229, 0x722a, 0x722b, 0x722c, 0x722d, 0x722e, 0x5d35, 0x722f, 0x6478, 0x3534, 0x3321, 0x3a32, 0x7231, 0x7230, 0x4c25, 0x7233, 0x7234, 0x7232, 0x7235, 0x4b62, 0x7236, 0x357b, 0x4f25, 0x7237, 0x7239, 0x303e, 0x723a, 0x4a2b, 0x7238, 0x723b, 0x723c, 0x723d, 0x723e, 0x723f, 0x4b6e, 0x3b2d, 0x3a7a, 0x412f, 0x7240, 0x7243, 0x7241, 0x7244, 0x3871, 0x7242, 0x7245, 0x7246, 0x7247, 0x724b, 0x3b2a, 0x4264, 0x724c, 0x7249, 0x7248, 0x724a, 0x375f, 0x7250, 0x724f, 0x724e, 0x3033, 0x725a, 0x7256, 0x7257, 0x7253, 0x7259, 0x7255, 0x3362, 0x4f4c, 0x7258, 0x7254, 0x7252, 0x7251, 0x725c, 0x725f, 0x725e, 0x725d, 0x4949, 0x725b, 0x3073, 0x7260, 0x7262, 0x336f, 0x724d, 0x3137, 0x7264, 0x7263, 0x7261, 0x432d, 0x4b70, 0x4e5a, 0x7265, 0x7266, 0x7267, 0x7268, 0x7269, 0x443b, 0x726a, 0x4837, 0x726f, 0x726b, 0x726c, 0x4b31, 0x4c44, 0x4650, 0x7270, 0x7271, 0x463e, 0x726e, 0x726d, 0x322a, 0x7279, 0x7278, 0x3175, 0x7276, 0x7275, 0x7273, 0x337b, 0x7272, 0x3c32, 0x3229, 0x3963, 0x727c, 0x727b, 0x727a, 0x7277, 0x727d, 0x727e, 0x7325, 0x7324, 0x7326, 0x312d, 0x7321, 0x7322, 0x3974, 0x4c39, 0x7323, 0x4b32, 0x732b, 0x7327, 0x732c, 0x7329, 0x7328, 0x375c, 0x732d, 0x732e, 0x732f, 0x732a, 0x7274, 0x7330, 0x4461, 0x7334, 0x7335, 0x7333, 0x7332, 0x7338, 0x7331, 0x7336, 0x7337, 0x733a, 0x7339, 0x733c, 0x733d, 0x733e, 0x4f49, 0x733b, 0x426b, 0x3a6d, 0x733f, 0x7340, 0x7341, 0x7342, 0x7343, 0x3834, 0x7344, 0x7345, 0x3c2f, 0x7346, 0x7347, 0x7348, 0x7349, 0x734c, 0x734a, 0x4f3c, 0x734b, 0x4e6f, 0x734d, 0x4e5b, 0x734e, 0x477e, 0x734f, 0x7351, 0x7352, 0x7350, 0x396d, 0x4c4d, 0x4b63, 0x5677, 0x5d60, 0x4b7b, 0x322b, 0x7354, 0x3550, 0x7355, 0x7356, 0x7357, 0x3975, 0x7358, 0x6054, 0x4c5b, 0x4263, 0x7359, 0x735b, 0x735a, 0x735c, 0x735d, 0x735e, 0x735f, 0x7360, 0x7361, 0x7362, 0x7363, 0x7364, 0x7365, 0x7366, 0x7367, 0x7368, 0x4524, 0x385d, 0x736a, 0x414d, 0x736b, 0x736c, 0x4921, 0x736d, 0x736e, 0x6337, 0x6c5a, 0x706d, 0x736f, 0x7370, 0x7372, 0x7373, 0x7374, 0x4e70, 0x7371, 0x7375, 0x7376, 0x7378, 0x7377, 0x737a, 0x737b, 0x7379, 0x4e36, 0x737c, 0x737d, 0x6354, 0x737e, 0x212a, 0x2174, 0x2170, 0x2173, 0x2175, 0x214a, 0x214b, 0x2176, 0x215c, 0x2124, 0x2125, 0x213f, 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337, 0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, 0x2129, 0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347, 0x2348, 0x2349, 0x234a, 0x234b, 0x234c, 0x234d, 0x234e, 0x234f, 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357, 0x2358, 0x2359, 0x235a, 0x214e, 0x214f, 0x2130, 0x2132, 0x212e, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367, 0x2368, 0x2369, 0x236a, 0x236b, 0x236c, 0x236d, 0x236e, 0x236f, 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377, 0x2378, 0x2379, 0x237a, 0x2150, 0x2143, 0x2151, 0x2131, 0x216f, }; static const Summary16 jisx0208_uni2indx_page00[16] = { /* 0x0000 */ { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x0000 }, { 0, 0x1000 }, { 1, 0x0000 }, { 1, 0x0000 }, { 1, 0x0000 }, { 1, 0x0000 }, { 1, 0x118c }, { 6, 0x0053 }, { 10, 0x0000 }, { 10, 0x0080 }, { 11, 0x0000 }, { 11, 0x0080 }, }; static const Summary16 jisx0208_uni2indx_page03[22] = { /* 0x0300 */ { 12, 0x0000 }, { 12, 0x0000 }, { 12, 0x0000 }, { 12, 0x0000 }, { 12, 0x0000 }, { 12, 0x0000 }, { 12, 0x0000 }, { 12, 0x0000 }, { 12, 0x0000 }, { 12, 0xfffe }, { 27, 0x03fb }, { 36, 0xfffe }, { 51, 0x03fb }, { 60, 0x0000 }, { 60, 0x0000 }, { 60, 0x0000 }, /* 0x0400 */ { 60, 0x0002 }, { 61, 0xffff }, { 77, 0xffff }, { 93, 0xffff }, { 109, 0xffff }, { 125, 0x0002 }, }; static const Summary16 jisx0208_uni2indx_page20[50] = { /* 0x2000 */ { 126, 0x0000 }, { 126, 0x3361 }, { 133, 0x0063 }, { 137, 0x080d }, { 141, 0x0000 }, { 141, 0x0000 }, { 141, 0x0000 }, { 141, 0x0000 }, { 141, 0x0000 }, { 141, 0x0000 }, { 141, 0x0000 }, { 141, 0x0000 }, { 141, 0x0000 }, { 141, 0x0000 }, { 141, 0x0000 }, { 141, 0x0000 }, /* 0x2100 */ { 141, 0x0008 }, { 142, 0x0000 }, { 142, 0x0800 }, { 143, 0x0000 }, { 143, 0x0000 }, { 143, 0x0000 }, { 143, 0x0000 }, { 143, 0x0000 }, { 143, 0x0000 }, { 143, 0x000f }, { 147, 0x0000 }, { 147, 0x0000 }, { 147, 0x0000 }, { 147, 0x0014 }, { 149, 0x0000 }, { 149, 0x0000 }, /* 0x2200 */ { 149, 0x098d }, { 155, 0x6404 }, { 159, 0x1f81 }, { 166, 0x2030 }, { 169, 0x0000 }, { 169, 0x0004 }, { 170, 0x0cc3 }, { 176, 0x0000 }, { 176, 0x00cc }, { 180, 0x0000 }, { 180, 0x0020 }, { 181, 0x0000 }, { 181, 0x0000 }, { 181, 0x0000 }, { 181, 0x0000 }, { 181, 0x0000 }, /* 0x2300 */ { 181, 0x0000 }, { 181, 0x0004 }, }; static const Summary16 jisx0208_uni2indx_page25[23] = { /* 0x2500 */ { 182, 0x900f }, { 188, 0x3999 }, { 196, 0x9939 }, { 204, 0x9999 }, { 212, 0x0804 }, { 214, 0x0000 }, { 214, 0x0000 }, { 214, 0x0000 }, { 214, 0x0000 }, { 214, 0x0000 }, { 214, 0x0003 }, { 216, 0x300c }, { 220, 0xc8c0 }, { 225, 0x0000 }, { 225, 0x8000 }, { 226, 0x0000 }, /* 0x2600 */ { 226, 0x0060 }, { 228, 0x0000 }, { 228, 0x0000 }, { 228, 0x0000 }, { 228, 0x0005 }, { 230, 0x0000 }, { 230, 0xa400 }, }; static const Summary16 jisx0208_uni2indx_page30[16] = { /* 0x3000 */ { 233, 0xffef }, { 248, 0x103f }, { 255, 0x0000 }, { 255, 0x0000 }, { 255, 0xfffe }, { 270, 0xffff }, { 286, 0xffff }, { 302, 0xffff }, { 318, 0xffff }, { 334, 0x780f }, { 342, 0xfffe }, { 357, 0xffff }, { 373, 0xffff }, { 389, 0xffff }, { 405, 0xffff }, { 421, 0x787f }, }; static const Summary16 jisx0208_uni2indx_page4e[1307] = { /* 0x4e00 */ { 432, 0x6f8b }, { 442, 0x43f3 }, { 451, 0x2442 }, { 455, 0x9b46 }, { 463, 0xe82c }, { 470, 0xe3e0 }, { 478, 0x0004 }, { 479, 0x400a }, { 482, 0x5f65 }, { 492, 0xdb36 }, { 502, 0x7977 }, { 513, 0x0449 }, { 517, 0xecd7 }, { 528, 0xe3f0 }, { 537, 0x6038 }, { 542, 0x08c5 }, /* 0x4f00 */ { 547, 0xe602 }, { 553, 0x3403 }, { 558, 0x8000 }, { 559, 0x3551 }, { 566, 0xe0c8 }, { 572, 0x7eab }, { 583, 0x8200 }, { 585, 0x9869 }, { 592, 0xa948 }, { 598, 0x2942 }, { 603, 0xe803 }, { 609, 0x8060 }, { 612, 0x441c }, { 617, 0xad93 }, { 626, 0xc03a }, { 632, 0x4568 }, /* 0x5000 */ { 638, 0xaa60 }, { 644, 0x8656 }, { 651, 0x3f7a }, { 662, 0x0240 }, { 664, 0x8388 }, { 669, 0x1461 }, { 674, 0x1020 }, { 676, 0x2174 }, { 682, 0x2021 }, { 685, 0x0702 }, { 689, 0x3000 }, { 691, 0x40bc }, { 697, 0xa624 }, { 703, 0x4462 }, { 708, 0x60a8 }, { 713, 0x0a20 }, /* 0x5100 */ { 716, 0x0217 }, { 721, 0x8574 }, { 728, 0x0402 }, { 730, 0x9c84 }, { 736, 0x7bfb }, { 749, 0x1415 }, { 754, 0x7f24 }, { 763, 0x11e2 }, { 769, 0xb665 }, { 778, 0x02ef }, { 786, 0x1f75 }, { 796, 0x20ff }, { 805, 0x3a70 }, { 812, 0x3840 }, { 816, 0x26c3 }, { 823, 0x6763 }, /* 0x5200 */ { 832, 0x4dd9 }, { 841, 0x2092 }, { 845, 0x46b0 }, { 851, 0x0fc9 }, { 859, 0xbc98 }, { 867, 0x4850 }, { 871, 0x8638 }, { 877, 0xa03f }, { 885, 0x2388 }, { 890, 0x8816 }, { 895, 0x3e09 }, { 902, 0x5232 }, { 908, 0x22aa }, { 914, 0xe3a4 }, { 922, 0x00dd }, { 928, 0xc72c }, /* 0x5300 */ { 936, 0xa166 }, { 943, 0x26e1 }, { 950, 0x840b }, { 955, 0x8f0a }, { 962, 0x27eb }, { 972, 0x559e }, { 981, 0xc241 }, { 986, 0x89bb }, { 995, 0x0014 }, { 997, 0x8540 }, { 1001, 0x6361 }, { 1008, 0x0849 }, { 1012, 0x7f0c }, { 1021, 0x8ad0 }, { 1027, 0xff3e }, { 1040, 0x05cf }, /* 0x5400 */ { 1048, 0xff1a }, { 1059, 0xa803 }, { 1064, 0x7a41 }, { 1071, 0x7b40 }, { 1078, 0x4745 }, { 1085, 0x8002 }, { 1087, 0x0500 }, { 1089, 0x38eb }, { 1098, 0xd851 }, { 1105, 0x0005 }, { 1107, 0x9934 }, { 1114, 0x710c }, { 1120, 0x0397 }, { 1127, 0x0100 }, { 1128, 0x6366 }, { 1136, 0x2404 }, /* 0x5500 */ { 1139, 0x80d0 }, { 1143, 0x0051 }, { 1146, 0xc000 }, { 1148, 0x430a }, { 1153, 0x9071 }, { 1159, 0x30c8 }, { 1164, 0x0008 }, { 1165, 0x5800 }, { 1168, 0x0e99 }, { 1175, 0xf700 }, { 1182, 0x5f80 }, { 1189, 0x0041 }, { 1191, 0x00b0 }, { 1194, 0x9410 }, { 1198, 0x0018 }, { 1200, 0x6280 }, /* 0x5600 */ { 1204, 0x0240 }, { 1206, 0x09d0 }, { 1211, 0x8200 }, { 1213, 0x0156 }, { 1218, 0x5004 }, { 1221, 0x0801 }, { 1223, 0x1d10 }, { 1228, 0x0510 }, { 1231, 0x84c1 }, { 1236, 0x0010 }, { 1237, 0x4025 }, { 1241, 0x1050 }, { 1244, 0x410f }, { 1250, 0x4d8a }, { 1257, 0x4009 }, { 1260, 0xa60d }, /* 0x5700 */ { 1267, 0xab19 }, { 1275, 0x914c }, { 1281, 0x21c0 }, { 1285, 0x0981 }, { 1289, 0xc485 }, { 1295, 0x0003 }, { 1297, 0x0652 }, { 1302, 0x8000 }, { 1303, 0x0b04 }, { 1307, 0x0008 }, { 1308, 0x041d }, { 1313, 0x0009 }, { 1315, 0x4849 }, { 1320, 0x905c }, { 1326, 0x0009 }, { 1328, 0x1690 }, /* 0x5800 */ { 1333, 0x0c65 }, { 1339, 0x2220 }, { 1342, 0x8412 }, { 1346, 0x2433 }, { 1352, 0x0c03 }, { 1356, 0x4796 }, { 1364, 0x0a04 }, { 1367, 0x4225 }, { 1372, 0x0028 }, { 1374, 0x9088 }, { 1378, 0x4900 }, { 1381, 0x4f08 }, { 1387, 0x14a2 }, { 1392, 0xd3aa }, { 1401, 0xd830 }, { 1407, 0x3e87 }, /* 0x5900 */ { 1416, 0x8604 }, { 1420, 0x1f61 }, { 1428, 0x7ea4 }, { 1437, 0x4186 }, { 1442, 0xc390 }, { 1448, 0x05b3 }, { 1455, 0x57a5 }, { 1464, 0x2118 }, { 1468, 0x241e }, { 1474, 0x2a48 }, { 1479, 0x1128 }, { 1483, 0x4a04 }, { 1487, 0x0a40 }, { 1490, 0x161b }, { 1497, 0x0d60 }, { 1502, 0x8840 }, /* 0x5a00 */ { 1505, 0x020a }, { 1508, 0x9502 }, { 1513, 0x8221 }, { 1517, 0x1060 }, { 1520, 0x0243 }, { 1524, 0x0400 }, { 1525, 0x1444 }, { 1529, 0x8000 }, { 1530, 0x0000 }, { 1530, 0x0c04 }, { 1533, 0x0000 }, { 1533, 0x7000 }, { 1536, 0x1a06 }, { 1541, 0x00c1 }, { 1544, 0x024a }, { 1548, 0x0c00 }, /* 0x5b00 */ { 1550, 0x1a00 }, { 1553, 0x0040 }, { 1554, 0x1404 }, { 1557, 0x4045 }, { 1561, 0x0029 }, { 1564, 0xbdb3 }, { 1575, 0x0a78 }, { 1581, 0x052b }, { 1587, 0xbba9 }, { 1597, 0xbfa0 }, { 1606, 0x407c }, { 1612, 0x8379 }, { 1620, 0x12fc }, { 1628, 0xe81d }, { 1636, 0x4bf6 }, { 1646, 0xc569 }, /* 0x5c00 */ { 1654, 0xeff6 }, { 1667, 0x044a }, { 1671, 0x2115 }, { 1676, 0xff02 }, { 1685, 0xed63 }, { 1695, 0x402b }, { 1700, 0xd033 }, { 1707, 0x0242 }, { 1710, 0x1000 }, { 1711, 0x0013 }, { 1714, 0x1b02 }, { 1719, 0x59ca }, { 1727, 0x00a0 }, { 1729, 0x0200 }, { 1730, 0xa703 }, { 1737, 0x2c41 }, /* 0x5d00 */ { 1742, 0x4880 }, { 1745, 0x8ff2 }, { 1755, 0x0204 }, { 1757, 0x0000 }, { 1757, 0x5800 }, { 1760, 0x1005 }, { 1763, 0x9200 }, { 1766, 0x0048 }, { 1768, 0x1894 }, { 1773, 0x2001 }, { 1775, 0x5004 }, { 1778, 0x3480 }, { 1782, 0x3200 }, { 1785, 0x684c }, { 1791, 0x49ea }, { 1799, 0x68be }, /* 0x5e00 */ { 1808, 0x184c }, { 1813, 0x2e42 }, { 1819, 0xa820 }, { 1823, 0x21c9 }, { 1829, 0x50b9 }, { 1836, 0x80b0 }, { 1840, 0x001e }, { 1844, 0xff7c }, { 1857, 0x849a }, { 1863, 0x14e0 }, { 1868, 0x28c1 }, { 1873, 0x01e0 }, { 1877, 0x870e }, { 1884, 0xac49 }, { 1891, 0x130f }, { 1898, 0xdddb }, /* 0x5f00 */ { 1910, 0xbe1a }, { 1919, 0x89fb }, { 1929, 0xa2e0 }, { 1935, 0x51a2 }, { 1941, 0x5502 }, { 1946, 0x32ca }, { 1953, 0x3e46 }, { 1961, 0x928b }, { 1968, 0x1dbf }, { 1979, 0x438f }, { 1987, 0x6703 }, { 1994, 0x3218 }, { 1999, 0x3028 }, { 2003, 0x33c0 }, { 2009, 0x0811 }, { 2012, 0xa923 }, /* 0x6000 */ { 2019, 0xc000 }, { 2021, 0x3a65 }, { 2029, 0x8fe3 }, { 2039, 0x0402 }, { 2041, 0x2c4e }, { 2048, 0x8625 }, { 2054, 0xbf3d }, { 2066, 0x00a1 }, { 2069, 0x3a1a }, { 2076, 0x8cd4 }, { 2083, 0x06c9 }, { 2089, 0x317c }, { 2097, 0x00e0 }, { 2100, 0x950a }, { 2106, 0x018b }, { 2111, 0x0edb }, /* 0x6100 */ { 2120, 0xe34b }, { 2129, 0x8c20 }, { 2133, 0x1182 }, { 2137, 0xf010 }, { 2142, 0x7d94 }, { 2151, 0xa728 }, { 2158, 0xc9ac }, { 2166, 0x40fb }, { 2174, 0x4484 }, { 2178, 0x0653 }, { 2184, 0x5a90 }, { 2190, 0x4444 }, { 2194, 0x3fc8 }, { 2203, 0x0001 }, { 2204, 0x0048 }, { 2206, 0xf5d4 }, /* 0x6200 */ { 2216, 0x7701 }, { 2223, 0xec57 }, { 2233, 0xc442 }, { 2238, 0x891d }, { 2245, 0x6b83 }, { 2253, 0x4928 }, { 2258, 0x4109 }, { 2262, 0xd242 }, { 2268, 0x061d }, { 2274, 0x59fe }, { 2285, 0x1800 }, { 2287, 0x3a22 }, { 2293, 0xb7e4 }, { 2303, 0x3b9f }, { 2314, 0xf003 }, { 2320, 0xc0ea }, /* 0x6300 */ { 2327, 0x1386 }, { 2333, 0x8202 }, { 2336, 0x8980 }, { 2340, 0xe400 }, { 2344, 0xb200 }, { 2348, 0x10a1 }, { 2352, 0x4b80 }, { 2357, 0x0cc4 }, { 2362, 0xd309 }, { 2369, 0x8944 }, { 2374, 0x1faf }, { 2385, 0x4834 }, { 2390, 0x8259 }, { 2396, 0x0c45 }, { 2401, 0x420a }, { 2405, 0x0450 }, /* 0x6400 */ { 2408, 0xa040 }, { 2411, 0x10c8 }, { 2415, 0x3140 }, { 2419, 0x4450 }, { 2423, 0x4004 }, { 2425, 0x0100 }, { 2426, 0x8280 }, { 2429, 0x0540 }, { 2432, 0x0108 }, { 2434, 0x442c }, { 2439, 0x6a30 }, { 2445, 0x1a05 }, { 2450, 0x20a6 }, { 2455, 0x0514 }, { 2459, 0x90cf }, { 2467, 0x6456 }, /* 0x6500 */ { 2474, 0x0021 }, { 2476, 0x3100 }, { 2479, 0x9c18 }, { 2485, 0xcbf0 }, { 2494, 0xa120 }, { 2498, 0x63e2 }, { 2506, 0x104c }, { 2510, 0x01b5 }, { 2516, 0x538c }, { 2523, 0x9a83 }, { 2530, 0xb8b2 }, { 2538, 0x3281 }, { 2543, 0x987a }, { 2551, 0x0a84 }, { 2555, 0x33e7 }, { 2565, 0x0c02 }, /* 0x6600 */ { 2568, 0xd4cc }, { 2576, 0x9018 }, { 2580, 0xa1a1 }, { 2586, 0x9070 }, { 2591, 0x8a1e }, { 2598, 0xe004 }, { 2602, 0xc3d4 }, { 2610, 0x0451 }, { 2614, 0x439a }, { 2621, 0x21c2 }, { 2626, 0x4844 }, { 2630, 0x5310 }, { 2635, 0x0292 }, { 2639, 0x3640 }, { 2644, 0x0241 }, { 2647, 0xf3bd }, /* 0x6700 */ { 2659, 0xab09 }, { 2666, 0xe8f0 }, { 2674, 0x7dc0 }, { 2682, 0xa5d2 }, { 2690, 0xc242 }, { 2695, 0xd24b }, { 2703, 0xa43f }, { 2712, 0xd0af }, { 2721, 0x1aa0 }, { 2726, 0x34a1 }, { 2732, 0x8247 }, { 2738, 0x03d8 }, { 2744, 0xc452 }, { 2750, 0x651b }, { 2758, 0xd294 }, { 2765, 0xc83a }, /* 0x6800 */ { 2772, 0x001c }, { 2775, 0x40c8 }, { 2779, 0x0e06 }, { 2784, 0x3314 }, { 2790, 0x614f }, { 2798, 0xb21b }, { 2806, 0x0088 }, { 2808, 0xc0d0 }, { 2813, 0xa02a }, { 2818, 0xa898 }, { 2824, 0xa1c5 }, { 2831, 0x166b }, { 2839, 0x2e50 }, { 2845, 0x85b4 }, { 2852, 0xc08b }, { 2858, 0x0604 }, /* 0x6900 */ { 2861, 0xf933 }, { 2871, 0x1e04 }, { 2876, 0x056e }, { 2883, 0xa251 }, { 2889, 0x0400 }, { 2890, 0x7638 }, { 2898, 0xec07 }, { 2906, 0x73b8 }, { 2915, 0x4406 }, { 2919, 0x1832 }, { 2924, 0x4081 }, { 2927, 0xc816 }, { 2933, 0x7c8a }, { 2941, 0x6309 }, { 2947, 0x2980 }, { 2951, 0xaa04 }, /* 0x6a00 */ { 2956, 0x1c24 }, { 2961, 0xca9c }, { 2969, 0x4e0e }, { 2976, 0x2760 }, { 2982, 0x0990 }, { 2986, 0x8300 }, { 2989, 0x0046 }, { 2992, 0x8104 }, { 2995, 0x6011 }, { 2999, 0x1081 }, { 3002, 0x540d }, { 3008, 0x0908 }, { 3011, 0x000e }, { 3014, 0xcc0a }, { 3020, 0x0500 }, { 3022, 0x0c00 }, /* 0x6b00 */ { 3024, 0x0430 }, { 3027, 0xa044 }, { 3031, 0x008b }, { 3035, 0x6784 }, { 3042, 0x5288 }, { 3047, 0x8a19 }, { 3053, 0x865e }, { 3061, 0x8b18 }, { 3067, 0x2e59 }, { 3075, 0x4160 }, { 3079, 0x8c10 }, { 3083, 0x9cbe }, { 3093, 0x6861 }, { 3099, 0x891c }, { 3105, 0x9800 }, { 3108, 0x0008 }, /* 0x6c00 */ { 3109, 0x8100 }, { 3111, 0x089a }, { 3116, 0x0018 }, { 3118, 0x4190 }, { 3122, 0x4007 }, { 3126, 0xe4a1 }, { 3133, 0x0505 }, { 3137, 0x640d }, { 3143, 0x310e }, { 3149, 0x0e4d }, { 3156, 0x4806 }, { 3160, 0xff0a }, { 3170, 0x1632 }, { 3176, 0x2aa8 }, { 3182, 0x852e }, { 3189, 0x000b }, /* 0x6d00 */ { 3192, 0x1800 }, { 3194, 0xca84 }, { 3200, 0x0e20 }, { 3204, 0x696c }, { 3212, 0x0032 }, { 3215, 0x1600 }, { 3218, 0x5658 }, { 3225, 0x0390 }, { 3229, 0x5120 }, { 3233, 0x1a28 }, { 3238, 0x8000 }, { 3239, 0x1124 }, { 3243, 0x18e1 }, { 3249, 0x4326 }, { 3255, 0x5d52 }, { 3263, 0x0eaa }, /* 0x6e00 */ { 3270, 0x0fa0 }, { 3276, 0xae28 }, { 3283, 0xfa7b }, { 3295, 0x4500 }, { 3298, 0x6408 }, { 3302, 0x8940 }, { 3306, 0xc880 }, { 3310, 0xc044 }, { 3314, 0x9005 }, { 3318, 0xb141 }, { 3324, 0x8424 }, { 3328, 0x24c4 }, { 3333, 0x1a34 }, { 3339, 0x603a }, { 3345, 0x9000 }, { 3347, 0xc194 }, /* 0x6f00 */ { 3353, 0x8246 }, { 3358, 0x003a }, { 3362, 0x180d }, { 3367, 0xc106 }, { 3372, 0x0022 }, { 3374, 0x9910 }, { 3379, 0xe050 }, { 3384, 0x1511 }, { 3389, 0x4057 }, { 3395, 0x0082 }, { 3397, 0x041a }, { 3401, 0x020a }, { 3404, 0x004f }, { 3409, 0x8930 }, { 3414, 0xd813 }, { 3421, 0x444a }, /* 0x7000 */ { 3426, 0x8a02 }, { 3430, 0xed22 }, { 3438, 0x10c0 }, { 3441, 0x4005 }, { 3444, 0x1000 }, { 3445, 0x0102 }, { 3447, 0x8808 }, { 3450, 0x3101 }, { 3454, 0x4600 }, { 3457, 0x0204 }, { 3459, 0xf000 }, { 3463, 0x0708 }, { 3467, 0x8900 }, { 3470, 0xa200 }, { 3473, 0x0000 }, { 3473, 0x2202 }, /* 0x7100 */ { 3476, 0x0200 }, { 3477, 0x1610 }, { 3481, 0x0042 }, { 3483, 0x1040 }, { 3485, 0x5200 }, { 3488, 0x0260 }, { 3491, 0x52f4 }, { 3499, 0x2000 }, { 3500, 0x8510 }, { 3504, 0x8230 }, { 3508, 0x1100 }, { 3510, 0x4202 }, { 3513, 0x4308 }, { 3517, 0x80b5 }, { 3523, 0x70e1 }, { 3530, 0x9a20 }, /* 0x7200 */ { 3535, 0x2040 }, { 3537, 0x0801 }, { 3539, 0x3500 }, { 3543, 0xfc65 }, { 3553, 0x19c1 }, { 3559, 0xab04 }, { 3565, 0x0286 }, { 3569, 0x6214 }, { 3574, 0x0087 }, { 3578, 0x0044 }, { 3580, 0x9085 }, { 3585, 0x0244 }, { 3588, 0x405c }, { 3593, 0x0a85 }, { 3598, 0x3207 }, { 3604, 0x3380 }, /* 0x7300 */ { 3609, 0x0400 }, { 3610, 0xb8c0 }, { 3616, 0xce20 }, { 3622, 0xc0d0 }, { 3627, 0xc030 }, { 3631, 0x0080 }, { 3632, 0x0508 }, { 3635, 0x0d25 }, { 3641, 0x0a90 }, { 3645, 0x0040 }, { 3646, 0x0200 }, { 3647, 0x080c }, { 3650, 0x6505 }, { 3656, 0x4000 }, { 3657, 0x6421 }, { 3662, 0x4102 }, /* 0x7400 */ { 3665, 0x0268 }, { 3669, 0x0000 }, { 3669, 0x0024 }, { 3671, 0x847c }, { 3678, 0x0002 }, { 3679, 0xde20 }, { 3686, 0x8619 }, { 3692, 0x4049 }, { 3696, 0x0808 }, { 3698, 0x4000 }, { 3699, 0x0084 }, { 3701, 0x2001 }, { 3703, 0x8400 }, { 3705, 0x1010 }, { 3707, 0x42cd }, { 3714, 0x01c7 }, /* 0x7500 */ { 3720, 0x7038 }, { 3726, 0xd52a }, { 3734, 0x1968 }, { 3740, 0x1d8f }, { 3749, 0xbe50 }, { 3757, 0x3e12 }, { 3764, 0x2ef5 }, { 3774, 0x81d9 }, { 3781, 0xcec4 }, { 3789, 0x2412 }, { 3793, 0x0828 }, { 3796, 0x732e }, { 3805, 0x24ac }, { 3811, 0x4b34 }, { 3818, 0x020c }, { 3821, 0xd41d }, /* 0x7600 */ { 3829, 0x2a02 }, { 3833, 0x8000 }, { 3834, 0x0097 }, { 3839, 0x0811 }, { 3842, 0x11c4 }, { 3847, 0x1144 }, { 3851, 0x1786 }, { 3858, 0x7d45 }, { 3867, 0x49d9 }, { 3875, 0x0649 }, { 3880, 0x4000 }, { 3881, 0x8791 }, { 3888, 0x254c }, { 3894, 0xd8c4 }, { 3901, 0x44ba }, { 3908, 0x4914 }, /* 0x7700 */ { 3913, 0x1b92 }, { 3920, 0xc800 }, { 3923, 0x0271 }, { 3928, 0x1580 }, { 3932, 0x0081 }, { 3934, 0x0c00 }, { 3936, 0x096a }, { 3942, 0xc200 }, { 3945, 0x4800 }, { 3947, 0x4002 }, { 3949, 0x3021 }, { 3953, 0xba49 }, { 3961, 0x2080 }, { 3963, 0x1c80 }, { 3967, 0xe2ac }, { 3975, 0x1008 }, /* 0x7800 */ { 3977, 0x1004 }, { 3979, 0x0034 }, { 3982, 0x00e1 }, { 3986, 0x8414 }, { 3990, 0x0020 }, { 3991, 0x2000 }, { 3992, 0x9800 }, { 3995, 0x1014 }, { 3998, 0x70c2 }, { 4004, 0x04aa }, { 4009, 0x8688 }, { 4014, 0x5420 }, { 4018, 0x0c62 }, { 4023, 0x0413 }, { 4027, 0x9180 }, { 4031, 0x2010 }, /* 0x7900 */ { 4033, 0x4082 }, { 4036, 0x0206 }, { 4039, 0x1c40 }, { 4043, 0x5400 }, { 4046, 0x0383 }, { 4051, 0xe4e9 }, { 4060, 0x2125 }, { 4065, 0x8480 }, { 4068, 0xe433 }, { 4076, 0x2000 }, { 4077, 0x44c0 }, { 4081, 0xe609 }, { 4088, 0x0a03 }, { 4092, 0x8126 }, { 4097, 0x12da }, { 4104, 0x0801 }, /* 0x7a00 */ { 4106, 0x6901 }, { 4111, 0x9790 }, { 4118, 0x4001 }, { 4120, 0xf886 }, { 4128, 0xe24d }, { 4136, 0x0081 }, { 4138, 0x0a0e }, { 4143, 0xa651 }, { 4150, 0x011a }, { 4154, 0x81ec }, { 4161, 0xc600 }, { 4165, 0x8441 }, { 4169, 0xadb8 }, { 4178, 0xb62c }, { 4186, 0xa46f }, { 4195, 0x8741 }, /* 0x7b00 */ { 4201, 0x8d54 }, { 4208, 0x4b02 }, { 4213, 0x1161 }, { 4218, 0x0268 }, { 4222, 0xbb60 }, { 4230, 0x2057 }, { 4236, 0x50a0 }, { 4240, 0x0433 }, { 4245, 0xa8c0 }, { 4250, 0xb7b4 }, { 4260, 0x2402 }, { 4263, 0x0112 }, { 4266, 0x9ad3 }, { 4275, 0x2000 }, { 4276, 0x2271 }, { 4282, 0x00c8 }, /* 0x7c00 */ { 4285, 0x2081 }, { 4288, 0x809e }, { 4294, 0x0c8a }, { 4299, 0xe180 }, { 4304, 0xb009 }, { 4309, 0x8151 }, { 4314, 0x1031 }, { 4318, 0x4028 }, { 4321, 0x2a0e }, { 4327, 0x89a5 }, { 4334, 0x69b6 }, { 4343, 0x620e }, { 4349, 0x4425 }, { 4354, 0xd144 }, { 4360, 0x8085 }, { 4364, 0x4d54 }, /* 0x7d00 */ { 4371, 0x2c75 }, { 4379, 0x1fb1 }, { 4388, 0xd807 }, { 4395, 0x862d }, { 4402, 0xd87c }, { 4411, 0x4841 }, { 4415, 0x414e }, { 4421, 0x226e }, { 4428, 0x8200 }, { 4430, 0x9e08 }, { 4436, 0xf80c }, { 4443, 0xed37 }, { 4454, 0x8c80 }, { 4458, 0x7526 }, { 4466, 0x9313 }, { 4473, 0x0814 }, /* 0x7e00 */ { 4476, 0x0e32 }, { 4482, 0xc804 }, { 4486, 0x484e }, { 4492, 0x6ea6 }, { 4501, 0x2c4a }, { 4507, 0x6670 }, { 4514, 0x26c0 }, { 4519, 0xba01 }, { 4525, 0xd30c }, { 4532, 0x185d }, { 4539, 0x0000 }, { 4539, 0x0000 }, { 4539, 0x0000 }, { 4539, 0x0000 }, { 4539, 0x0000 }, { 4539, 0x0000 }, /* 0x7f00 */ { 4539, 0x0000 }, { 4539, 0x0000 }, { 4539, 0x0000 }, { 4539, 0x0540 }, { 4542, 0x7020 }, { 4546, 0x8133 }, { 4552, 0x4f81 }, { 4559, 0x03a5 }, { 4565, 0x55ec }, { 4574, 0x6410 }, { 4578, 0xc318 }, { 4584, 0x2344 }, { 4589, 0x1462 }, { 4594, 0x0034 }, { 4597, 0x0a43 }, { 4602, 0x1a09 }, /* 0x8000 */ { 4607, 0x187b }, { 4615, 0x13a5 }, { 4622, 0x0102 }, { 4624, 0xa848 }, { 4629, 0x0440 }, { 4631, 0xc544 }, { 4637, 0x8106 }, { 4641, 0xe2dd }, { 4651, 0x1af0 }, { 4658, 0x2d48 }, { 4664, 0xb626 }, { 4672, 0x0416 }, { 4676, 0x5058 }, { 4681, 0x6e40 }, { 4687, 0x8032 }, { 4691, 0x3112 }, /* 0x8100 */ { 4696, 0x07e4 }, { 4703, 0x0c00 }, { 4705, 0x8208 }, { 4708, 0x420a }, { 4712, 0x4840 }, { 4715, 0x803b }, { 4721, 0x4860 }, { 4725, 0x8713 }, { 4732, 0x850d }, { 4738, 0x3428 }, { 4743, 0x0319 }, { 4748, 0xe529 }, { 4756, 0x2345 }, { 4762, 0x870a }, { 4768, 0x25a9 }, { 4775, 0x5c18 }, /* 0x8200 */ { 4781, 0x77a6 }, { 4791, 0xd9c5 }, { 4800, 0x5e00 }, { 4805, 0x03e8 }, { 4811, 0x0081 }, { 4813, 0xa700 }, { 4818, 0xcd54 }, { 4826, 0x41c6 }, { 4832, 0x2800 }, { 4834, 0xa204 }, { 4838, 0xb860 }, { 4844, 0x2b0a }, { 4850, 0x0020 }, { 4851, 0xda9e }, { 4861, 0x08ea }, { 4867, 0x0e1a }, /* 0x8300 */ { 4873, 0x427c }, { 4880, 0x11c0 }, { 4884, 0x8908 }, { 4888, 0x0376 }, { 4895, 0x8621 }, { 4900, 0x0105 }, { 4903, 0x0000 }, { 4903, 0x18a8 }, { 4908, 0x46a0 }, { 4913, 0xc448 }, { 4918, 0x0d05 }, { 4923, 0x2022 }, { 4926, 0x5422 }, { 4931, 0x9148 }, { 4936, 0x8a01 }, { 4940, 0x2897 }, /* 0x8400 */ { 4947, 0x7898 }, { 4954, 0x0008 }, { 4955, 0x1605 }, { 4960, 0x3122 }, { 4965, 0x4240 }, { 4968, 0x0880 }, { 4970, 0xfa4e }, { 4980, 0x06a2 }, { 4985, 0x0814 }, { 4988, 0x9211 }, { 4993, 0x2002 }, { 4995, 0x9b04 }, { 5001, 0x2e52 }, { 5008, 0x0643 }, { 5013, 0x5000 }, { 5015, 0x9010 }, /* 0x8500 */ { 5018, 0x0041 }, { 5020, 0x85ba }, { 5028, 0x3042 }, { 5032, 0x2020 }, { 5034, 0x4f0b }, { 5042, 0x05a0 }, { 5046, 0x2708 }, { 5051, 0x4080 }, { 5053, 0x0591 }, { 5058, 0x1a93 }, { 5065, 0xdf50 }, { 5074, 0x0600 }, { 5076, 0xa202 }, { 5080, 0x3021 }, { 5084, 0x0630 }, { 5088, 0x4e80 }, /* 0x8600 */ { 5093, 0x0cc4 }, { 5098, 0x04c8 }, { 5102, 0xa004 }, { 5105, 0x8001 }, { 5107, 0x6000 }, { 5109, 0xd431 }, { 5116, 0x0880 }, { 5118, 0x0a02 }, { 5121, 0x1c00 }, { 5124, 0x0028 }, { 5126, 0x8e18 }, { 5132, 0x0041 }, { 5134, 0x6ad0 }, { 5141, 0xca10 }, { 5146, 0xf210 }, { 5152, 0x4b00 }, /* 0x8700 */ { 5156, 0x274d }, { 5164, 0x1506 }, { 5169, 0x0220 }, { 5171, 0x8890 }, { 5175, 0x5a00 }, { 5179, 0x82a8 }, { 5184, 0x4549 }, { 5190, 0x8150 }, { 5194, 0x2004 }, { 5196, 0x8000 }, { 5197, 0x8804 }, { 5200, 0x2c08 }, { 5204, 0x08d1 }, { 5209, 0x0005 }, { 5211, 0x8001 }, { 5213, 0x4ac4 }, /* 0x8800 */ { 5219, 0xe020 }, { 5223, 0x0062 }, { 5226, 0x008e }, { 5230, 0x0a42 }, { 5234, 0x3055 }, { 5240, 0x6a8c }, { 5247, 0x090e }, { 5252, 0xe0a5 }, { 5259, 0x2906 }, { 5264, 0x42c4 }, { 5269, 0x4814 }, { 5273, 0x80b3 }, { 5279, 0x803e }, { 5285, 0xb330 }, { 5292, 0x0102 }, { 5294, 0x731c }, /* 0x8900 */ { 5302, 0x1494 }, { 5307, 0x600d }, { 5312, 0x0c20 }, { 5315, 0x0940 }, { 5318, 0x301a }, { 5323, 0xc040 }, { 5326, 0xa451 }, { 5332, 0xc094 }, { 5337, 0x8dca }, { 5345, 0x05c8 }, { 5350, 0x96c2 }, { 5357, 0xa40c }, { 5362, 0x0001 }, { 5363, 0x3404 }, { 5367, 0x00c8 }, { 5370, 0x0110 }, /* 0x8a00 */ { 5372, 0x550d }, { 5379, 0xa9c9 }, { 5387, 0x2428 }, { 5391, 0x1c5a }, { 5398, 0x0142 }, { 5401, 0x4837 }, { 5408, 0x7a4d }, { 5417, 0x100f }, { 5422, 0x32b4 }, { 5429, 0x452a }, { 5435, 0x317b }, { 5444, 0x9205 }, { 5449, 0xb894 }, { 5456, 0x5c44 }, { 5462, 0x68d7 }, { 5471, 0x458a }, /* 0x8b00 */ { 5477, 0x5097 }, { 5484, 0x2ed1 }, { 5492, 0x1943 }, { 5498, 0x4208 }, { 5501, 0xd202 }, { 5506, 0x9d40 }, { 5512, 0x9840 }, { 5516, 0x2097 }, { 5522, 0x5409 }, { 5527, 0x064d }, { 5533, 0x0000 }, { 5533, 0x0000 }, { 5533, 0x0000 }, { 5533, 0x0000 }, { 5533, 0x0000 }, { 5533, 0x0000 }, /* 0x8c00 */ { 5533, 0x0000 }, { 5533, 0x0000 }, { 5533, 0x0000 }, { 5533, 0x8480 }, { 5536, 0x5542 }, { 5542, 0x0421 }, { 5545, 0x1c06 }, { 5550, 0x1700 }, { 5554, 0x7624 }, { 5561, 0x6110 }, { 5565, 0xff87 }, { 5577, 0xb9dd }, { 5588, 0x659f }, { 5598, 0x5c0a }, { 5604, 0x245d }, { 5611, 0x3c00 }, /* 0x8d00 */ { 5615, 0xadb0 }, { 5623, 0x0059 }, { 5627, 0x0000 }, { 5627, 0x0000 }, { 5627, 0x0000 }, { 5627, 0x0000 }, { 5627, 0x28d0 }, { 5632, 0x009b }, { 5637, 0x0422 }, { 5640, 0x0200 }, { 5641, 0x0108 }, { 5643, 0x4408 }, { 5646, 0x9804 }, { 5650, 0xac40 }, { 5655, 0x8d0a }, { 5661, 0x9028 }, /* 0x8e00 */ { 5665, 0x8700 }, { 5669, 0xe001 }, { 5673, 0x0400 }, { 5674, 0x0031 }, { 5677, 0x1794 }, { 5684, 0x8221 }, { 5688, 0x0019 }, { 5691, 0x1054 }, { 5695, 0x2cb2 }, { 5702, 0x021a }, { 5706, 0x9c02 }, { 5711, 0x4003 }, { 5714, 0x3d60 }, { 5721, 0x8804 }, { 5724, 0x080c }, { 5727, 0x7900 }, /* 0x8f00 */ { 5732, 0x1628 }, { 5737, 0xba3c }, { 5746, 0x8640 }, { 5750, 0xcb08 }, { 5756, 0x7274 }, { 5764, 0x9080 }, { 5767, 0x001e }, { 5771, 0x0000 }, { 5771, 0x0000 }, { 5771, 0xd800 }, { 5775, 0xe188 }, { 5781, 0x9c87 }, { 5789, 0x4034 }, { 5793, 0x0412 }, { 5796, 0xae64 }, { 5804, 0x2791 }, /* 0x9000 */ { 5811, 0xe86b }, { 5820, 0xe6fb }, { 5832, 0x408f }, { 5838, 0x5366 }, { 5846, 0xeea6 }, { 5856, 0x537f }, { 5867, 0xe32b }, { 5876, 0xb5e4 }, { 5885, 0x869f }, { 5894, 0x0002 }, { 5895, 0x8548 }, { 5900, 0x0122 }, { 5903, 0x4402 }, { 5906, 0x0800 }, { 5907, 0x2116 }, { 5912, 0x20a0 }, /* 0x9100 */ { 5915, 0x0004 }, { 5916, 0x0204 }, { 5918, 0x2000 }, { 5919, 0x0005 }, { 5921, 0x7e00 }, { 5927, 0x0154 }, { 5931, 0x162c }, { 5937, 0x01ac }, { 5942, 0x2a84 }, { 5947, 0x1085 }, { 5951, 0x8c14 }, { 5956, 0x0530 }, { 5960, 0xfbc3 }, { 5971, 0xb943 }, { 5979, 0x00ca }, { 5983, 0x9060 }, /* 0x9200 */ { 5987, 0x6000 }, { 5989, 0x4032 }, { 5993, 0x1200 }, { 5995, 0x8090 }, { 5998, 0x0b30 }, { 6003, 0x4c81 }, { 6008, 0x0054 }, { 6011, 0x4002 }, { 6013, 0x0029 }, { 6016, 0x1d6a }, { 6024, 0x2000 }, { 6025, 0x0280 }, { 6027, 0x8000 }, { 6028, 0x0004 }, { 6029, 0x2610 }, { 6033, 0x150c }, /* 0x9300 */ { 6038, 0x8040 }, { 6040, 0x0701 }, { 6044, 0xd94d }, { 6053, 0x0c24 }, { 6057, 0x2810 }, { 6060, 0x1850 }, { 6064, 0x5001 }, { 6067, 0x5020 }, { 6070, 0x1000 }, { 6071, 0x04d0 }, { 6075, 0x7080 }, { 6079, 0x0201 }, { 6081, 0x0108 }, { 6083, 0x21c3 }, { 6089, 0x0132 }, { 6093, 0x0000 }, /* 0x9400 */ { 6093, 0x0088 }, { 6095, 0x0719 }, { 6101, 0x0802 }, { 6103, 0x0560 }, { 6107, 0x0012 }, { 6109, 0x4c0e }, { 6115, 0x0405 }, { 6118, 0xf0a1 }, { 6125, 0x0002 }, { 6126, 0x0000 }, { 6126, 0x0000 }, { 6126, 0x0000 }, { 6126, 0x0000 }, { 6126, 0x0000 }, { 6126, 0x0000 }, { 6126, 0x0000 }, /* 0x9500 */ { 6126, 0x0000 }, { 6126, 0x0000 }, { 6126, 0x0000 }, { 6126, 0x0000 }, { 6126, 0x0000 }, { 6126, 0x0000 }, { 6126, 0x0000 }, { 6126, 0x0080 }, { 6127, 0x8e8d }, { 6135, 0x035a }, { 6141, 0x21bd }, { 6149, 0x5a04 }, { 6154, 0x3488 }, { 6159, 0x1170 }, { 6164, 0x0026 }, { 6167, 0x0000 }, /* 0x9600 */ { 6167, 0x0000 }, { 6167, 0x1000 }, { 6168, 0xc502 }, { 6173, 0x8804 }, { 6176, 0xb815 }, { 6183, 0xf801 }, { 6189, 0x147c }, { 6196, 0x25ed }, { 6205, 0xed60 }, { 6213, 0x1bb0 }, { 6220, 0x0589 }, { 6225, 0x1bd7 }, { 6235, 0x7af3 }, { 6246, 0x1a62 }, { 6252, 0x0d0c }, { 6257, 0x0ac5 }, /* 0x9700 */ { 6263, 0xe5d1 }, { 6272, 0x524a }, { 6278, 0x0490 }, { 6281, 0x6305 }, { 6287, 0x0354 }, { 6292, 0x5244 }, { 6297, 0x2b57 }, { 6306, 0x1612 }, { 6311, 0xa872 }, { 6318, 0x1101 }, { 6321, 0x2949 }, { 6327, 0x0018 }, { 6329, 0x0948 }, { 6333, 0x1008 }, { 6335, 0x6000 }, { 6337, 0x886c }, /* 0x9800 */ { 6343, 0x916e }, { 6351, 0x058f }, { 6358, 0x3012 }, { 6362, 0x3990 }, { 6368, 0xf840 }, { 6374, 0x4930 }, { 6379, 0x8880 }, { 6382, 0x001b }, { 6386, 0x0000 }, { 6386, 0x0000 }, { 6386, 0x8500 }, { 6389, 0x0042 }, { 6391, 0x0058 }, { 6394, 0x9800 }, { 6397, 0xea04 }, { 6403, 0x7014 }, /* 0x9900 */ { 6408, 0x1628 }, { 6413, 0x611d }, { 6420, 0x5113 }, { 6426, 0x6000 }, { 6428, 0x1a24 }, { 6433, 0x00a7 }, { 6438, 0x0000 }, { 6438, 0x0000 }, { 6438, 0x0000 }, { 6438, 0x03c0 }, { 6442, 0x7120 }, { 6447, 0x1018 }, { 6450, 0x0172 }, { 6455, 0xa927 }, { 6463, 0x6004 }, { 6466, 0x8906 }, /* 0x9a00 */ { 6471, 0xc022 }, { 6475, 0x020c }, { 6478, 0x0900 }, { 6480, 0x4081 }, { 6483, 0x202d }, { 6488, 0x8ca0 }, { 6493, 0x0e34 }, { 6499, 0x0000 }, { 6499, 0x0000 }, { 6499, 0x0000 }, { 6499, 0x2100 }, { 6501, 0x1101 }, { 6504, 0x8011 }, { 6507, 0xc11a }, { 6513, 0xec4c }, { 6521, 0x0892 }, /* 0x9b00 */ { 6525, 0x0040 }, { 6526, 0x8500 }, { 6529, 0xc7ac }, { 6538, 0x1806 }, { 6542, 0xe03e }, { 6550, 0x0512 }, { 6554, 0x8000 }, { 6555, 0x0010 }, { 6556, 0x4008 }, { 6558, 0x80ce }, { 6564, 0x6d01 }, { 6570, 0x0210 }, { 6572, 0x8641 }, { 6577, 0x0856 }, { 6582, 0x011e }, { 6587, 0x0027 }, /* 0x9c00 */ { 6591, 0x3750 }, { 6598, 0x083d }, { 6604, 0xe032 }, { 6610, 0x4e05 }, { 6616, 0x01c0 }, { 6619, 0x0484 }, { 6622, 0x0081 }, { 6624, 0x0140 }, { 6626, 0x0000 }, { 6626, 0x0000 }, { 6626, 0x0000 }, { 6626, 0x0000 }, { 6626, 0x0000 }, { 6626, 0x0000 }, { 6626, 0x1aa0 }, { 6631, 0x0059 }, /* 0x9d00 */ { 6635, 0x43c8 }, { 6641, 0x8824 }, { 6645, 0x1d48 }, { 6651, 0xc800 }, { 6654, 0x0152 }, { 6658, 0x7203 }, { 6664, 0x9013 }, { 6669, 0x0404 }, { 6671, 0x8280 }, { 6674, 0x0400 }, { 6675, 0x8a10 }, { 6679, 0x0d14 }, { 6684, 0x8056 }, { 6689, 0x0208 }, { 6691, 0xa040 }, { 6694, 0x2704 }, /* 0x9e00 */ { 6699, 0x0000 }, { 6699, 0x4c00 }, { 6702, 0x0000 }, { 6702, 0x0000 }, { 6702, 0x0000 }, { 6702, 0x0000 }, { 6702, 0x0000 }, { 6702, 0xa320 }, { 6707, 0x1902 }, { 6711, 0xa0ae }, { 6718, 0x2660 }, { 6723, 0xdf00 }, { 6730, 0xf010 }, { 6735, 0x7b15 }, { 6744, 0x8121 }, { 6748, 0x3ad0 }, /* 0x9f00 */ { 6755, 0x4180 }, { 6758, 0x0028 }, { 6760, 0x1003 }, { 6763, 0x4800 }, { 6765, 0xcc00 }, { 6769, 0x8014 }, { 6772, 0x14cf }, { 6780, 0x00c4 }, { 6783, 0x2000 }, { 6784, 0x3020 }, { 6787, 0x0001 }, }; static const Summary16 jisx0208_uni2indx_pageff[15] = { /* 0xff00 */ { 6788, 0xdf7a }, { 6800, 0xffff }, { 6816, 0xffff }, { 6832, 0xefff }, { 6847, 0xffff }, { 6863, 0x3fff }, { 6877, 0x0000 }, { 6877, 0x0000 }, { 6877, 0x0000 }, { 6877, 0x0000 }, { 6877, 0x0000 }, { 6877, 0x0000 }, { 6877, 0x0000 }, { 6877, 0x0000 }, { 6877, 0x0028 }, }; static int jisx0208_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; if (n >= 2) { const Summary16 *summary = NULL; if (wc < 0x0100) summary = &jisx0208_uni2indx_page00[(wc>>4)]; else if (wc >= 0x0300 && wc < 0x0460) summary = &jisx0208_uni2indx_page03[(wc>>4)-0x030]; else if (wc >= 0x2000 && wc < 0x2320) summary = &jisx0208_uni2indx_page20[(wc>>4)-0x200]; else if (wc >= 0x2500 && wc < 0x2670) summary = &jisx0208_uni2indx_page25[(wc>>4)-0x250]; else if (wc >= 0x3000 && wc < 0x3100) summary = &jisx0208_uni2indx_page30[(wc>>4)-0x300]; else if (wc >= 0x4e00 && wc < 0x9fb0) summary = &jisx0208_uni2indx_page4e[(wc>>4)-0x4e0]; else if (wc >= 0xff00 && wc < 0xfff0) summary = &jisx0208_uni2indx_pageff[(wc>>4)-0xff0]; if (summary) { unsigned short used = summary->used; unsigned int i = wc & 0x0f; if (used & ((unsigned short) 1 << i)) { unsigned short c; /* Keep in `used' only the bits 0..i-1. */ used &= ((unsigned short) 1 << i) - 1; /* Add `summary->indx' and the number of bits set in `used'. */ used = (used & 0x5555) + ((used & 0xaaaa) >> 1); used = (used & 0x3333) + ((used & 0xcccc) >> 2); used = (used & 0x0f0f) + ((used & 0xf0f0) >> 4); used = (used & 0x00ff) + (used >> 8); c = jisx0208_2charset[summary->indx + used]; r[0] = (c >> 8); r[1] = (c & 0xff); return 2; } } return RET_ILSEQ; } return RET_TOOSMALL; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/tcvn.h0000644000175000017500000001357315004135251017506 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/tcvn.h,v 1.3 2000/11/29 17:40:35 dawes Exp $ */ /* * TCVN-5712 */ static const unsigned short tcvn_2uni_1[32] = { /* 0x00 */ 0x0000, 0x00da, 0x1ee4, 0x0003, 0x1eea, 0x1eec, 0x1eee, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, /* 0x10 */ 0x0010, 0x1ee8, 0x1ef0, 0x1ef2, 0x1ef6, 0x1ef8, 0x00dd, 0x1ef4, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, }; static const unsigned short tcvn_2uni_2[128] = { /* 0x80 */ 0x00c0, 0x1ea2, 0x00c3, 0x00c1, 0x1ea0, 0x1eb6, 0x1eac, 0x00c8, 0x1eba, 0x1ebc, 0x00c9, 0x1eb8, 0x1ec6, 0x00cc, 0x1ec8, 0x0128, /* 0x90 */ 0x00cd, 0x1eca, 0x00d2, 0x1ece, 0x00d5, 0x00d3, 0x1ecc, 0x1ed8, 0x1edc, 0x1ede, 0x1ee0, 0x1eda, 0x1ee2, 0x00d9, 0x1ee6, 0x0168, /* 0xa0 */ 0x00a0, 0x0102, 0x00c2, 0x00ca, 0x00d4, 0x01a0, 0x01af, 0x0110, 0x0103, 0x00e2, 0x00ea, 0x00f4, 0x01a1, 0x01b0, 0x0111, 0x1eb0, /* 0xb0 */ 0x0300, 0x0309, 0x0303, 0x0301, 0x0323, 0x00e0, 0x1ea3, 0x00e3, 0x00e1, 0x1ea1, 0x1eb2, 0x1eb1, 0x1eb3, 0x1eb5, 0x1eaf, 0x1eb4, /* 0xc0 */ 0x1eae, 0x1ea6, 0x1ea8, 0x1eaa, 0x1ea4, 0x1ec0, 0x1eb7, 0x1ea7, 0x1ea9, 0x1eab, 0x1ea5, 0x1ead, 0x00e8, 0x1ec2, 0x1ebb, 0x1ebd, /* 0xd0 */ 0x00e9, 0x1eb9, 0x1ec1, 0x1ec3, 0x1ec5, 0x1ebf, 0x1ec7, 0x00ec, 0x1ec9, 0x1ec4, 0x1ebe, 0x1ed2, 0x0129, 0x00ed, 0x1ecb, 0x00f2, /* 0xe0 */ 0x1ed4, 0x1ecf, 0x00f5, 0x00f3, 0x1ecd, 0x1ed3, 0x1ed5, 0x1ed7, 0x1ed1, 0x1ed9, 0x1edd, 0x1edf, 0x1ee1, 0x1edb, 0x1ee3, 0x00f9, /* 0xf0 */ 0x1ed6, 0x1ee7, 0x0169, 0x00fa, 0x1ee5, 0x1eeb, 0x1eed, 0x1eef, 0x1ee9, 0x1ef1, 0x1ef3, 0x1ef7, 0x1ef9, 0x00fd, 0x1ef5, 0x1ed0, }; static int tcvn_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0x20) *pwc = (ucs4_t) tcvn_2uni_1[c]; else if (c < 0x80) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) tcvn_2uni_2[c-0x80]; return 1; } static const unsigned char tcvn_page00[96+184] = { 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ 0x80, 0x83, 0xa2, 0x82, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */ 0x87, 0x8a, 0xa3, 0x00, 0x8d, 0x90, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x92, 0x95, 0xa4, 0x94, 0x00, 0x00, /* 0xd0-0xd7 */ 0x00, 0x9d, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, /* 0xd8-0xdf */ 0xb5, 0xb8, 0xa9, 0xb7, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */ 0xcc, 0xd0, 0xaa, 0x00, 0xd7, 0xdd, 0x00, 0x00, /* 0xe8-0xef */ 0x00, 0x00, 0xdf, 0xe3, 0xab, 0xe2, 0x00, 0x00, /* 0xf0-0xf7 */ 0x00, 0xef, 0xf3, 0x00, 0x00, 0xfd, 0x00, 0x00, /* 0xf8-0xff */ /* 0x0100 */ 0x00, 0x00, 0xa1, 0xa8, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0xa7, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0x8f, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x9f, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */ 0xa5, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, /* 0xa8-0xaf */ 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ }; static const unsigned char tcvn_page03[40] = { 0xb0, 0xb3, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */ 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ }; static const unsigned char tcvn_page1e[96] = { 0x84, 0xb9, 0x81, 0xb6, 0xc4, 0xca, 0xc1, 0xc7, /* 0xa0-0xa7 */ 0xc2, 0xc8, 0xc3, 0xc9, 0x86, 0xcb, 0xc0, 0xbe, /* 0xa8-0xaf */ 0xaf, 0xbb, 0xba, 0xbc, 0xbf, 0xbd, 0x85, 0xc6, /* 0xb0-0xb7 */ 0x8b, 0xd1, 0x88, 0xce, 0x89, 0xcf, 0xda, 0xd5, /* 0xb8-0xbf */ 0xc5, 0xd2, 0xcd, 0xd3, 0xd9, 0xd4, 0x8c, 0xd6, /* 0xc0-0xc7 */ 0x8e, 0xd8, 0x91, 0xde, 0x96, 0xe4, 0x93, 0xe1, /* 0xc8-0xcf */ 0xff, 0xe8, 0xdb, 0xe5, 0xe0, 0xe6, 0xf0, 0xe7, /* 0xd0-0xd7 */ 0x97, 0xe9, 0x9b, 0xed, 0x98, 0xea, 0x99, 0xeb, /* 0xd8-0xdf */ 0x9a, 0xec, 0x9c, 0xee, 0x02, 0xf4, 0x9e, 0xf1, /* 0xe0-0xe7 */ 0x11, 0xf8, 0x04, 0xf5, 0x05, 0xf6, 0x06, 0xf7, /* 0xe8-0xef */ 0x12, 0xf9, 0x13, 0xfa, 0x17, 0xfe, 0x14, 0xfb, /* 0xf0-0xf7 */ 0x15, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */ }; static int tcvn_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x0080 && (wc >= 0x0020 || (0x00fe0076 & (1 << wc)) == 0)) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x01b8) c = tcvn_page00[wc-0x00a0]; else if (wc >= 0x0300 && wc < 0x0328) c = tcvn_page03[wc-0x0300]; else if (wc >= 0x1ea0 && wc < 0x1f00) c = tcvn_page1e[wc-0x1ea0]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/COPYRIGHT0000644000175000017500000000344015004135251017646 0ustar albrechtalbrechtThis notice applies to the files in this directory. They are taken from the libiconv-1.1 package, which is covered by the LGPL license. The files in this directory have been placed under the following copyright, with permission from the Free Software Foundation. Copyright (c) 1999-2000 Free Software Foundation, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FREE SOFTWARE FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the Free Software Foundation shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the Free Software Foundation. Notes: 1. This copyright applies only to the files in this directory, and not to the remaining files in libiconv. 2. The Free Software Foundation does not encourage the use of the above license for newly written software. fltk-1.4.3/src/xutf8/lcUniConv/iso8859_1.h0000644000175000017500000000063415004135251020076 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_1.h,v 1.3 2000/11/29 17:40:30 dawes Exp $ */ /* * ISO-8859-1 */ static int iso8859_1_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; *pwc = (ucs4_t) c; return 1; } static int iso8859_1_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { if (wc < 0x0100) { *r = wc; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/xutf8/lcUniConv/iso8859_6.h0000644000175000017500000000527215004135251020106 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_6.h,v 1.3 2000/11/29 17:40:32 dawes Exp $ */ /* * ISO-8859-6 */ #ifdef NEED_TOWC static const unsigned short iso8859_6_2uni[96] = { /* 0xa0 */ 0x00a0, 0xfffd, 0xfffd, 0xfffd, 0x00a4, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x060c, 0x00ad, 0xfffd, 0xfffd, /* 0xb0 */ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x061b, 0xfffd, 0xfffd, 0xfffd, 0x061f, /* 0xc0 */ 0xfffd, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, /* 0xd0 */ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, /* 0xe0 */ 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, /* 0xf0 */ 0x0650, 0x0651, 0x0652, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, }; static int iso8859_6_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) { *pwc = (ucs4_t) c; return 1; } else { unsigned short wc = iso8859_6_2uni[c-0xa0]; if (wc != 0xfffd) { *pwc = (ucs4_t) wc; return 1; } } return RET_ILSEQ; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_6_page00[16] = { 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */ }; static const unsigned char iso8859_6_page06[80] = { 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, /* 0x08-0x0f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xbf, /* 0x18-0x1f */ 0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x20-0x27 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x28-0x2f */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x30-0x37 */ 0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x40-0x47 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x48-0x4f */ 0xf0, 0xf1, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ }; static int iso8859_6_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x00b0) c = iso8859_6_page00[wc-0x00a0]; else if (wc >= 0x0608 && wc < 0x0658) c = iso8859_6_page06[wc-0x0608]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/8bit_tab_to_h.c0000644000175000017500000004115215004135251021226 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/8bit_tab_to_h.c,v 1.3 2001/02/09 00:02:54 dawes Exp $ */ /* * Generates an 8-bit character set table from a .TXT table as found on * ftp.unicode.org or from a table containing the 256 Unicode values as * hexadecimal integers. * Examples: * * ./8bit_tab_to_h ISO-8859-1 iso8859_1 < tab8859_1 * ./8bit_tab_to_h ISO-8859-2 iso8859_2 < tab8859_2 * ./8bit_tab_to_h ISO-8859-3 iso8859_3 < tab8859_3 * ./8bit_tab_to_h ISO-8859-4 iso8859_4 < tab8859_4 * ./8bit_tab_to_h ISO-8859-5 iso8859_5 < tab8859_5 * ./8bit_tab_to_h ISO-8859-6 iso8859_6 < tab8859_6 * ./8bit_tab_to_h ISO-8859-7 iso8859_7 < tab8859_7 * ./8bit_tab_to_h ISO-8859-8 iso8859_8 < tab8859_8 * ./8bit_tab_to_h ISO-8859-9 iso8859_9 < tab8859_9 * ./8bit_tab_to_h ISO-8859-10 iso8859_10 < tab8859_10 * ./8bit_tab_to_h ISO-8859-14 iso8859_14 < tab8859_14 * ./8bit_tab_to_h ISO-8859-15 iso8859_15 < tab8859_15 * ./8bit_tab_to_h JISX0201.1976-0 jisx0201 < jis0201 * ./8bit_tab_to_h TIS620-0 tis620 < tabtis620 * ./8bit_tab_to_h KOI8-R koi8_r < tabkoi8_r * ./8bit_tab_to_h KOI8-U koi8_u < tabkoi8_u * ./8bit_tab_to_h ARMSCII-8 armscii_8 < tabarmscii_8 * ./8bit_tab_to_h CP1133 cp1133 < tabibm_cp1133 * ./8bit_tab_to_h MULELAO-1 mulelao < tabmulelao_1 * ./8bit_tab_to_h VISCII1.1-1 viscii1 < tabviscii * ./8bit_tab_to_h TCVN-5712 tcvn < tabtcvn * ./8bit_tab_to_h GEORGIAN-ACADEMY georgian_ac < tabgeorgian_academy * ./8bit_tab_to_h GEORGIAN-PS georgian_ps < tabgeorgian_ps * * ./8bit_tab_to_h ISO-8859-1 iso8859_1 < 8859-1.TXT * ./8bit_tab_to_h ISO-8859-2 iso8859_2 < 8859-2.TXT * ./8bit_tab_to_h ISO-8859-3 iso8859_3 < 8859-3.TXT * ./8bit_tab_to_h ISO-8859-4 iso8859_4 < 8859-4.TXT * ./8bit_tab_to_h ISO-8859-5 iso8859_5 < 8859-5.TXT * ./8bit_tab_to_h ISO-8859-6 iso8859_6 < 8859-6.TXT * ./8bit_tab_to_h ISO-8859-7 iso8859_7 < 8859-7.TXT * ./8bit_tab_to_h ISO-8859-8 iso8859_8 < 8859-8.TXT * ./8bit_tab_to_h ISO-8859-9 iso8859_9 < 8859-9.TXT * ./8bit_tab_to_h ISO-8859-10 iso8859_10 < 8859-10.TXT * ./8bit_tab_to_h ISO-8859-14 iso8859_14 < 8859-14.TXT * ./8bit_tab_to_h ISO-8859-15 iso8859_15 < 8859-15.TXT * ./8bit_tab_to_h JISX0201.1976-0 jisx0201 < JIS0201.TXT * ./8bit_tab_to_h KOI8-R koi8_r < KOI8-R.TXT */ #include #include #include #include int main (int argc, char *argv[]) { const char* charsetname; const char* c_charsetname; const char* filename; const char* directory; int charset2uni[0x100]; if (argc != 3 && argc != 4 && argc != 5) exit(1); charsetname = argv[1]; c_charsetname = argv[2]; if (argc > 3) { filename = argv[3]; } else { char* s = (char*) malloc(strlen(c_charsetname)+strlen(".h")+1); strcpy(s,c_charsetname); strcat(s,".h"); filename = s; } directory = (argc > 4 ? argv[4] : ""); fprintf(stderr, "Creating %s%s\n", directory, filename); { int i, c; c = getc(stdin); ungetc(c,stdin); if (c == '#') { /* Read a unicode.org style .TXT file. */ for (i = 0; i < 0x100; i++) charset2uni[i] = 0xfffd; for (;;) { c = getc(stdin); if (c == EOF) break; if (c == '\n' || c == ' ' || c == '\t') continue; if (c == '#') { do { c = getc(stdin); } while (!(c == EOF || c == '\n')); continue; } ungetc(c,stdin); if (scanf("0x%x", &i) != 1 || !(i >= 0 && i < 0x100)) exit(1); do { c = getc(stdin); } while (c == ' ' || c == '\t'); if (c != EOF) ungetc(c,stdin); if (c == '\n' || c == '#') continue; if (scanf("0x%x", &charset2uni[i]) != 1) exit(1); } } else { /* Read a table of hexadecimal Unicode values. */ for (i = 0; i < 0x100; i++) { if (scanf("%x", &charset2uni[i]) != 1) exit(1); if (charset2uni[i] < 0 || charset2uni[i] == 0xffff) charset2uni[i] = 0xfffd; } if (scanf("%x", &i) != EOF) exit(1); } } /* Write the output file. */ { FILE* f; { char* fname = malloc(strlen(directory)+strlen(filename)+1); strcpy(fname,directory); strcat(fname,filename); f = fopen(fname,"w"); if (f == NULL) exit(1); } fprintf(f, "\n"); fprintf(f, "/*\n"); fprintf(f, " * %s\n", charsetname); fprintf(f, " */\n"); fprintf(f, "\n"); { int i, i1, i2, i3; int line[16]; int tableno; struct { int minline; int maxline; } tables[16]; bool some_invalid; bool final_ret_reached; for (i1 = 0; i1 < 16; i1++) { bool all_invalid = true; bool all_identity = true; for (i2 = 0; i2 < 16; i2++) { i = 16*i1+i2; if (charset2uni[i] != 0xfffd) all_invalid = false; if (charset2uni[i] != i) all_identity = false; } if (all_invalid) line[i1] = -2; else if (all_identity) line[i1] = -1; else line[i1] = 0; } tableno = 0; for (i1 = 0; i1 < 16; i1++) { if (line[i1] >= 0) { if (i1 > 0 && tableno > 0 && line[i1-1] == tableno-1) { line[i1] = tableno-1; tables[tableno-1].maxline = i1; } else { tableno++; line[i1] = tableno-1; tables[tableno-1].minline = tables[tableno-1].maxline = i1; } } } some_invalid = false; for (i = 0; i < 0x100; i++) if (charset2uni[i] == 0xfffd) some_invalid = true; if (tableno > 0) { int t; for (t = 0; t < tableno; t++) { fprintf(f, "static const unsigned short %s_2uni", c_charsetname); if (tableno > 1) fprintf(f, "_%d", t+1); fprintf(f, "[%d] = {\n", 16*(tables[t].maxline-tables[t].minline+1)); for (i1 = tables[t].minline; i1 <= tables[t].maxline; i1++) { fprintf(f, " /* 0x%02x */\n", 16*i1); for (i2 = 0; i2 < 2; i2++) { fprintf(f, " "); for (i3 = 0; i3 < 8; i3++) { i = 16*i1+8*i2+i3; fprintf(f, " 0x%04x,", charset2uni[i]); } fprintf(f, "\n"); } } fprintf(f, "};\n"); } fprintf(f, "\n"); } final_ret_reached = false; fprintf(f, "static int\n%s_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n)\n", c_charsetname); fprintf(f, "{\n"); fprintf(f, " unsigned char c = *s;\n"); if (some_invalid) { for (i1 = 0; i1 < 16;) { int t = line[i1]; const char* indent; for (i2 = i1; i2 < 16 && line[i2] == t; i2++); indent = (i1 == 0 && i2 == 16 ? " " : " "); if (i1 == 0) { if (i2 == 16) { } else { fprintf(f, " if (c < 0x%02x) {\n", 16*i2); } } else { if (i2 == 16) { fprintf(f, " else {\n"); } else { fprintf(f, " else if (c < 0x%02x) {\n", 16*i2); } } if (t == -2) { final_ret_reached = true; } else if (t == -1) { fprintf(f, "%s*pwc = (ucs4_t) c;\n", indent); fprintf(f, "%sreturn 1;\n", indent); } else { fprintf(f, "%s", indent); some_invalid = false; for (i = 16*i1; i < 16*i2; i++) if (charset2uni[i] == 0xfffd) some_invalid = true; if (some_invalid) fprintf(f, "unsigned short wc = "); else fprintf(f, "*pwc = (ucs4_t) "); fprintf(f, "%s_2uni", c_charsetname); if (tableno > 1) fprintf(f, "_%d", t+1); fprintf(f, "[c"); if (tables[t].minline > 0) fprintf(f, "-0x%02x", 16*tables[t].minline); fprintf(f, "];\n"); if (some_invalid) { fprintf(f, "%sif (wc != 0xfffd) {\n", indent); fprintf(f, "%s *pwc = (ucs4_t) wc;\n", indent); fprintf(f, "%s return 1;\n", indent); fprintf(f, "%s}\n", indent); final_ret_reached = true; } else { fprintf(f, "%sreturn 1;\n", indent); } } if (!(i1 == 0 && i2 == 16)) fprintf(f, " }\n"); i1 = i2; } if (final_ret_reached) fprintf(f, " return RET_ILSEQ;\n"); } else { for (i1 = 0; i1 < 16;) { int t = line[i1]; for (i2 = i1; i2 < 16 && line[i2] == t; i2++); if (i1 == 0) { if (i2 == 16) { fprintf(f, " "); } else { fprintf(f, " if (c < 0x%02x)\n ", 16*i2); } } else { if (i2 == 16) { fprintf(f, " else\n "); } else { fprintf(f, " else if (c < 0x%02x)\n ", 16*i2); } } if (t == -1) fprintf(f, "*pwc = (ucs4_t) c;\n"); else { fprintf(f, "*pwc = (ucs4_t) %s_2uni", c_charsetname); if (tableno > 1) fprintf(f, "_%d", t+1); fprintf(f, "[c"); if (tables[t].minline > 0) fprintf(f, "-0x%02x", 16*tables[t].minline); fprintf(f, "];\n"); } i1 = i2; } fprintf(f, " return 1;\n"); } fprintf(f, "}\n"); } fprintf(f, "\n"); { int uni2charset[0x10000]; bool pages[0x100]; int line[0x2000]; int tableno; struct { int minline; int maxline; int usecount; const char* suffix; } tables[0x2000]; bool need_c; bool fix_0000; int i, j, p, j1, j2, t; for (j = 0; j < 0x10000; j++) uni2charset[j] = 0; for (p = 0; p < 0x100; p++) pages[p] = false; for (i = 0; i < 0x100; i++) { j = charset2uni[i]; if (j != 0xfffd) { uni2charset[j] = i; pages[j>>8] = true; } } for (j1 = 0; j1 < 0x2000; j1++) { bool all_invalid = true; bool all_identity = true; for (j2 = 0; j2 < 8; j2++) { j = 8*j1+j2; if (uni2charset[j] != 0) all_invalid = false; if (uni2charset[j] != j) all_identity = false; } if (all_invalid) line[j1] = -2; else if (all_identity) line[j1] = -1; else line[j1] = 0; } tableno = 0; for (j1 = 0; j1 < 0x2000; j1++) { if (line[j1] >= 0) { if (tableno > 0 && ((j1 > 0 && line[j1-1] == tableno-1) || ((tables[tableno-1].maxline >> 5) == (j1 >> 5) && j1 - tables[tableno-1].maxline <= 8))) { line[j1] = tableno-1; tables[tableno-1].maxline = j1; } else { tableno++; line[j1] = tableno-1; tables[tableno-1].minline = tables[tableno-1].maxline = j1; } } } for (t = 0; t < tableno; t++) { tables[t].usecount = 0; j1 = 8*tables[t].minline; j2 = 8*(tables[t].maxline+1); for (j = j1; j < j2; j++) if (uni2charset[j] != 0) tables[t].usecount++; } for (t = 0, p = -1, i = 0; t < tableno; t++) { if (tables[t].usecount > 1) { char* s; if (p == tables[t].minline >> 5) { s = (char*) malloc(5+1); sprintf(s, "%02x_%d", p, ++i); } else { p = tables[t].minline >> 5; s = (char*) malloc(2+1); sprintf(s, "%02x", p); } tables[t].suffix = s; } else tables[t].suffix = NULL; } { p = -1; for (t = 0; t < tableno; t++) if (tables[t].usecount > 1) { p = 0; fprintf(f, "static const unsigned char %s_page%s[%d] = {\n", c_charsetname, tables[t].suffix, 8*(tables[t].maxline-tables[t].minline+1)); for (j1 = tables[t].minline; j1 <= tables[t].maxline; j1++) { if ((j1 % 0x20) == 0 && j1 > tables[t].minline) fprintf(f, " /* 0x%04x */\n", 8*j1); fprintf(f, " "); for (j2 = 0; j2 < 8; j2++) { j = 8*j1+j2; fprintf(f, " 0x%02x,", uni2charset[j]); } fprintf(f, " /* 0x%02x-0x%02x */\n", 8*(j1 % 0x20), 8*(j1 % 0x20)+7); } fprintf(f, "};\n"); } if (p >= 0) fprintf(f, "\n"); } need_c = false; for (j1 = 0; j1 < 0x2000;) { t = line[j1]; for (j2 = j1; j2 < 0x2000 && line[j2] == t; j2++); if (t >= 0) j2 = tables[t].maxline+1; if (!(t == -2 || (t == -1 && j1 == 0))) need_c = true; j1 = j2; } fix_0000 = false; fprintf(f, "static int\n%s_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n)\n", c_charsetname); fprintf(f, "{\n"); if (need_c) fprintf(f, " unsigned char c = 0;\n"); for (j1 = 0; j1 < 0x2000;) { t = line[j1]; for (j2 = j1; j2 < 0x2000 && line[j2] == t; j2++); if (t >= 0) { if (j1 != tables[t].minline) abort(); if (j2 > tables[t].maxline+1) abort(); j2 = tables[t].maxline+1; } if (t == -2) { } else { if (j1 == 0) fprintf(f, " "); else fprintf(f, " else "); if (t >= 0 && tables[t].usecount == 0) abort(); if (t >= 0 && tables[t].usecount == 1) { if (j2 != j1+1) abort(); for (j = 8*j1; j < 8*j2; j++) if (uni2charset[j] != 0) { fprintf(f, "if (wc == 0x%04x)\n c = 0x%02x;\n", j, uni2charset[j]); break; } } else { if (j1 == 0) { fprintf(f, "if (wc < 0x%04x)", 8*j2); } else { fprintf(f, "if (wc >= 0x%04x && wc < 0x%04x)", 8*j1, 8*j2); } if (t == -1) { if (j1 == 0) /* If wc == 0, the function must return 1, not -1. */ fprintf(f, " {\n *r = wc;\n return 1;\n }\n"); else fprintf(f, "\n c = wc;\n"); } else { fprintf(f, "\n c = %s_page%s[wc", c_charsetname, tables[t].suffix); if (tables[t].minline > 0) fprintf(f, "-0x%04x", 8*j1); fprintf(f, "];\n"); if (j1 == 0 && uni2charset[0] == 0) /* If wc == 0, the function must return 1, not -1. */ fix_0000 = true; } } } j1 = j2; } if (need_c) { if (fix_0000) fprintf(f, " if (c != 0 || wc == 0) {\n"); else fprintf(f, " if (c != 0) {\n"); fprintf(f, " *r = c;\n"); fprintf(f, " return 1;\n"); fprintf(f, " }\n"); } fprintf(f, " return RET_ILSEQ;\n"); fprintf(f, "}\n"); } if (ferror(f) || fclose(f)) exit(1); } #if 0 int i1, i2, i3, i1_min, i1_max, j1, j2; i1_min = 16; i1_max = -1; for (i1 = 0; i1 < 16; i1++) for (i2 = 0; i2 < 16; i2++) if (charset2uni[16*i1+i2] != 0xfffd) { if (i1_min > i1) i1_min = i1; if (i1_max < i1) i1_max = i1; } printf("static const unsigned short %s_2uni[%d] = {\n", name, 16*(i1_max-i1_min+1)); for (i1 = i1_min; i1 <= i1_max; i1++) { printf(" /""* 0x%02x *""/\n", 16*i1); for (i2 = 0; i2 < 2; i2++) { printf(" "); for (i3 = 0; i3 < 8; i3++) { if (i3 > 0) printf(" "); printf("0x%04x,", charset2uni[16*i1+8*i2+i3]); } printf("\n"); } } printf("};\n"); printf("\n"); for (p = 0; p < 0x100; p++) pages[p] = 0; for (i = 0; i < 0x100; i++) if (charset2uni[i] != 0xfffd) pages[charset2uni[i]>>8] = 1; for (p = 0; p < 0x100; p++) if (pages[p]) { int j1_min = 32; int j1_max = -1; for (j1 = 0; j1 < 32; j1++) for (j2 = 0; j2 < 8; j2++) if (uni2charset[256*p+8*j1+j2] != 0) { if (j1_min > j1) j1_min = j1; if (j1_max < j1) j1_max = j1; } printf("static const unsigned char %s_page%02x[%d] = {\n", name, p, 8*(j1_max-j1_min+1)); for (j1 = j1_min; j1 <= j1_max; j1++) { printf(" "); for (j2 = 0; j2 < 8; j2++) printf("0x%02x, ", uni2charset[256*p+8*j1+j2]); printf("/""* 0x%02x-0x%02x *""/\n", 8*j1, 8*j1+7); } printf("};\n"); } printf("\n"); } #endif exit(0); } fltk-1.4.3/src/xutf8/lcUniConv/iso8859_4.h0000644000175000017500000000760415004135251020105 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/iso8859_4.h,v 1.3 2000/11/29 17:40:31 dawes Exp $ */ /* * ISO-8859-4 */ #ifdef NEED_TOWC static const unsigned short iso8859_4_2uni[96] = { /* 0xa0 */ 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, /* 0xb0 */ 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, /* 0xc0 */ 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, /* 0xd0 */ 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, /* 0xe0 */ 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, /* 0xf0 */ 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9, }; static int iso8859_4_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c < 0xa0) *pwc = (ucs4_t) c; else *pwc = (ucs4_t) iso8859_4_2uni[c-0xa0]; return 1; } #endif /* NEED_TOWC */ #ifdef NEED_TOMB static const unsigned char iso8859_4_page00[224] = { 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */ 0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0xaf, /* 0xa8-0xaf */ 0xb0, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ 0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0x00, /* 0xc0-0xc7 */ 0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */ 0xd8, 0x00, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */ 0x00, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0x00, /* 0xe0-0xe7 */ 0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0x00, /* 0xe8-0xef */ 0x00, 0x00, 0x00, 0x00, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */ 0xf8, 0x00, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */ /* 0x0100 */ 0xc0, 0xe0, 0x00, 0x00, 0xa1, 0xb1, 0x00, 0x00, /* 0x00-0x07 */ 0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00, /* 0x08-0x0f */ 0xd0, 0xf0, 0xaa, 0xba, 0x00, 0x00, 0xcc, 0xec, /* 0x10-0x17 */ 0xca, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */ 0x00, 0x00, 0xab, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */ 0xa5, 0xb5, 0xcf, 0xef, 0x00, 0x00, 0xc7, 0xe7, /* 0x28-0x2f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf3, /* 0x30-0x37 */ 0xa2, 0x00, 0x00, 0xa6, 0xb6, 0x00, 0x00, 0x00, /* 0x38-0x3f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf1, 0x00, /* 0x40-0x47 */ 0x00, 0x00, 0xbd, 0xbf, 0xd2, 0xf2, 0x00, 0x00, /* 0x48-0x4f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0xb3, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0xa9, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xac, 0xbc, /* 0x60-0x67 */ 0xdd, 0xfd, 0xde, 0xfe, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0xd9, 0xf9, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xbe, 0x00, /* 0x78-0x7f */ }; static const unsigned char iso8859_4_page02[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ 0x00, 0xff, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ }; static int iso8859_4_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { (void)conv; (void)n; unsigned char c = 0; if (wc < 0x00a0) { *r = wc; return 1; } else if (wc >= 0x00a0 && wc < 0x0180) c = iso8859_4_page00[wc-0x00a0]; else if (wc >= 0x02c0 && wc < 0x02e0) c = iso8859_4_page02[wc-0x02c0]; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } #endif /* NEED_TOMB */ fltk-1.4.3/src/xutf8/lcUniConv/georgian_ps.h0000644000175000017500000000774715004135251021037 0ustar albrechtalbrecht/* $XFree86: xc/lib/X11/lcUniConv/georgian_ps.h,v 1.3 2000/11/29 17:40:29 dawes Exp $ */ /* * GEORGIAN-PS */ static const unsigned short georgian_ps_2uni_1[32] = { /* 0x80 */ 0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 0x90 */ 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, }; static const unsigned short georgian_ps_2uni_2[39] = { /* 0xc0 */ 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10f1, 0x10d7, 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10f2, 0x10dd, /* 0xd0 */ 0x10de, 0x10df, 0x10e0, 0x10e1, 0x10e2, 0x10f3, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, /* 0xe0 */ 0x10ed, 0x10ee, 0x10f4, 0x10ef, 0x10f0, 0x10f5, }; static int georgian_ps_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n) { unsigned char c = *s; if (c >= 0x80 && c < 0xa0) *pwc = (ucs4_t) georgian_ps_2uni_1[c-0x80]; else if (c >= 0xc0 && c < 0xe6) *pwc = (ucs4_t) georgian_ps_2uni_2[c-0xc0]; else *pwc = (ucs4_t) c; return 1; } static const unsigned char georgian_ps_page00[32] = { 0x80, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */ 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */ }; static const unsigned char georgian_ps_page01[72] = { 0x00, 0x00, 0x8c, 0x9c, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */ 0x8a, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */ 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ }; static const unsigned char georgian_ps_page02[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, /* 0xc0-0xc7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ }; static const unsigned char georgian_ps_page10[40] = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc8, /* 0xd0-0xd7 */ 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xcf, 0xd0, 0xd1, /* 0xd8-0xdf */ 0xd2, 0xd3, 0xd4, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, /* 0xe0-0xe7 */ 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe3, /* 0xe8-0xef */ 0xe4, 0xc7, 0xce, 0xd5, 0xe2, 0xe5, 0x00, 0x00, /* 0xf0-0xf7 */ }; static const unsigned char georgian_ps_page20[48] = { 0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */ 0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */ 0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */ 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */ 0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */ }; static int georgian_ps_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n) { unsigned char c = 0; if (wc < 0x0080) { *r = wc; return 1; } else if (wc >= 0x0080 && wc < 0x00a0) c = georgian_ps_page00[wc-0x0080]; else if ((wc >= 0x00a0 && wc < 0x00c0) || (wc >= 0x00e6 && wc < 0x0100)) c = wc; else if (wc >= 0x0150 && wc < 0x0198) c = georgian_ps_page01[wc-0x0150]; else if (wc >= 0x02c0 && wc < 0x02e0) c = georgian_ps_page02[wc-0x02c0]; else if (wc >= 0x10d0 && wc < 0x10f8) c = georgian_ps_page10[wc-0x10d0]; else if (wc >= 0x2010 && wc < 0x2040) c = georgian_ps_page20[wc-0x2010]; else if (wc == 0x2122) c = 0x99; if (c != 0) { *r = c; return 1; } return RET_ILSEQ; } fltk-1.4.3/src/Fl_Shared_Image.cxx0000644000175000017500000005114415004135251017056 0ustar albrechtalbrecht// // Shared image code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include "flstring.h" #include #include #include #include #include #include // // Global class vars... // Fl_Shared_Image **Fl_Shared_Image::images_ = 0; // Shared images int Fl_Shared_Image::num_images_ = 0; // Number of shared images int Fl_Shared_Image::alloc_images_ = 0; // Allocated shared images Fl_Shared_Handler *Fl_Shared_Image::handlers_ = 0;// Additional format handlers int Fl_Shared_Image::num_handlers_ = 0; // Number of format handlers int Fl_Shared_Image::alloc_handlers_ = 0; // Allocated format handlers // // Typedef the C API sort function type the only way I know how... // extern "C" { typedef int (*compare_func_t)(const void *, const void *); } /** Returns the Fl_Shared_Image* array. \return a pointer to an array of shared image pointers, sorted by name and size \see Fl_Shared_Image::num_images() */ Fl_Shared_Image **Fl_Shared_Image::images() { return images_; } /** Number of shared images in their various cached sizes. \return number of entries in the array \see Fl_Shared_Image::images() */ int Fl_Shared_Image::num_images() { return num_images_; } /** Compares two shared images. The order of comparison is: -# Image name, usually the filename used to load it -# Image width -# Image height Binary search in a sorted array works only if we search for the same parameters that were also used for sorting. No special cases are possible here. Fl_Shared_Image::find() requires a search for an element with a matching name and the original_ flags set. This is not implemented via binary search, but by a simple run of the array inside Fl_Shared_Image::find(). \param[in] i0, i1 image pointer pointer for sorting \returns Whether the images match or their relative sort order (see text). \retval 0 the images match \retval <0 Image \p i0 is \e less than image \p i1 \retval >0 Image \p i0 is \e greater than image \p i1 */ int Fl_Shared_Image::compare(Fl_Shared_Image **i0, // I - First image Fl_Shared_Image **i1) { // I - Second image int i = strcmp((*i0)->name(), (*i1)->name()); if (i) { return i; } else if ((*i0)->data_w() != (*i1)->data_w()) { return (*i0)->data_w() - (*i1)->data_w(); } else { return (*i0)->data_h() - (*i1)->data_h(); } } /** Creates an empty shared image. The constructors create a new shared image record in the image cache. The constructors are protected and cannot be used directly from a program. Use the get() method instead. */ Fl_Shared_Image::Fl_Shared_Image() : Fl_Image(0,0,0) { name_ = 0; refcount_ = 1; original_ = 0; image_ = 0; alloc_image_ = 0; } /** Creates a shared image from its filename and its corresponding Fl_Image* img. The constructors create a new shared image record in the image cache. The constructors are protected and cannot be used directly from a program. Use the get() method instead. \param[in] n filename or pool name of the image, must be unique among shared images \param[in] img the image that is made available using the name */ Fl_Shared_Image::Fl_Shared_Image(const char *n, Fl_Image *img) : Fl_Image(0,0,0) { name_ = new char[strlen(n) + 1]; strcpy((char *)name_, n); refcount_ = 1; image_ = img; alloc_image_ = !img; original_ = 1; if (!img) reload(); else update(); } /** Adds a shared image to the image pool. This \b protected method adds an image to the pool, an ordered list of shared images. The pool is searched for a matching image whenever one is requested, for instance with Fl_Shared_Image::get() or Fl_Shared_Image::find(). This method does not increase or decrease reference counts! */ void Fl_Shared_Image::add() { Fl_Shared_Image **temp; // New image pointer array... if (num_images_ >= alloc_images_) { // Allocate more memory... temp = new Fl_Shared_Image *[alloc_images_ + 32]; if (alloc_images_) { memcpy(temp, images_, alloc_images_ * sizeof(Fl_Shared_Image *)); delete[] images_; } images_ = temp; alloc_images_ += 32; } images_[num_images_] = this; num_images_ ++; if (num_images_ > 1) { qsort(images_, num_images_, sizeof(Fl_Shared_Image *), (compare_func_t)compare); } } /** Update the dimensions of the shared images. Internal method to synchronize shared image data with the actual image data. */ void Fl_Shared_Image::update() { if (image_) { int W = w(), H = h(); w(image_->data_w()); h(image_->data_h()); d(image_->d()); data(image_->data(), image_->count()); if (W && H) scale(W, H, 0, 1); } } /** The destructor frees all memory and server resources that are used by the image. The destructor is protected and cannot be used directly from a program. Use the Fl_Shared_Image::release() method instead. */ Fl_Shared_Image::~Fl_Shared_Image() { if (name_) delete[] (char *)name_; if (alloc_image_) delete image_; } /** Releases and possibly destroys (if refcount <= 0) a shared image. In the latter case, it will reorganize the shared image array so that no hole will occur. */ void Fl_Shared_Image::release() { int i; // Looping var... Fl_Shared_Image *the_original = NULL; #ifdef SHIM_DEBUG printf("----> Fl_Shared_Image::release() %d %s %d %d\n", original_, name_, w(), h()); print_pool(); #endif if (refcount_ <= 0) return; // assert(refcount_>0); refcount_ --; if (refcount_ > 0) return; // If this image is not the original, find the original image and make sure // to delete its reference counter as well at the end of this method. if (!original()) { Fl_Shared_Image *o = find(name()); if (o) { if (o->original() && o!=this && o->refcount_>1) the_original = o; // mark to release later o->release(); // release from find() operation } } for (i = 0; i < num_images_; i ++) { if (images_[i] == this) { num_images_ --; if (i < num_images_) { memmove(images_ + i, images_ + i + 1, (num_images_ - i) * sizeof(Fl_Shared_Image *)); } break; } } delete this; if (num_images_ == 0 && images_) { delete[] images_; images_ = 0; alloc_images_ = 0; } #ifdef SHIM_DEBUG printf("<---- Fl_Shared_Image::release() %d %s %d %d\n", original_, name_, w(), h()); print_pool(); printf("\n"); #endif // Release one reference count in the original image as well. if (the_original) the_original->release(); } /** Reloads the shared image from disk. */ void Fl_Shared_Image::reload() { // Load image from disk... int i; // Looping var int count = 0; // number of bytes read from image header FILE *fp; // File pointer uchar header[64]; // Buffer for auto-detecting files Fl_Image *img; // New image if (!name_) return; if ((fp = fl_fopen(name_, "rb")) != NULL) { count = (int)fread(header, 1, sizeof(header), fp); fclose(fp); if (count == 0) return; } else { return; } // Load the image as appropriate... if (count >= 7 && memcmp(header, "#define", 7) == 0) // XBM file img = new Fl_XBM_Image(name_); else if (count >= 9 && memcmp(header, "/* XPM */", 9) == 0) // XPM file img = new Fl_XPM_Image(name_); else { // Not a standard format; try an image handler... for (i = 0, img = 0; i < num_handlers_; i ++) { img = (handlers_[i])(name_, header, count); if (img) break; } } if (img) { if (alloc_image_) delete image_; alloc_image_ = 1; image_ = img; int W = w(); int H = h(); update(); // Make sure the reloaded image gets the same drawing size as the existing one. if (W) scale(W, H, 0, 1); } } /** Create a resized copy of the image and wrap it into the share image class. This function is usually followed by a call to `returned_image->add() to add the image to the pool, and `this->refcounter_++` to make sure that the original shared image keeps a reference to the copy. Don't call this function if an image of the given size is already in the pool. \param[in] W, H new image size \return a new shared image pointer that is not yet in the pool */ Fl_Shared_Image * Fl_Shared_Image::copy_(int W, int H) const { Fl_Image *temp_image; // New image file Fl_Shared_Image *temp_shared; // New shared image // Make a copy of the image we're sharing... if (!image_) temp_image = 0; else temp_image = image_->copy(W, H); // Then make a new shared image... temp_shared = new Fl_Shared_Image(); temp_shared->name_ = new char[strlen(name_) + 1]; strcpy((char *)temp_shared->name_, name_); temp_shared->refcount_ = 1; temp_shared->image_ = temp_image; temp_shared->alloc_image_ = 1; temp_shared->update(); return temp_shared; } /** Return a shared image of this image with the requested size. This is the same as calling `Fl_Shared_Image::get(this->name(), W, H)`. If a shared image of the desired size already exists in the shared image pool, the existing image is returned and no copy is made. But the reference counter is incremented. When the image is no longer used, call `Fl_Shared_Image::release()`. To get a copy of the image data, call `this->image()->copy(W, H)` instead. \param[in] W, H size of requested image \return pointer to an `Fl_Shared_Image` that can be safely cast, or NULL if the image can't be found and can't be created. */ Fl_Image *Fl_Shared_Image::copy(int W, int H) const { if (name_) // should always be set return Fl_Shared_Image::get(name_, W, H); else return NULL; } /** Increments the reference counter and returns a pointer to itself. When the image is no longer used, call `Fl_Shared_Image::release()`. To get a copy of the image data, call `this->image()->copy()` instead. \return pointer to an `Fl_Shared_Image` that can be safely cast */ Fl_Image *Fl_Shared_Image::copy() { refcount_++; return this; } Fl_Image *Fl_Shared_Image::copy() const { if (name_) // should always be set return Fl_Shared_Image::get(name_); else return NULL; } /** Averages the colors in the image with the provided FLTK color value. This method changes the pixel data of this specific image. \note It does not change any of the resized copies of this image, nor does it necessarily apply the color changes if this image is resized later. \param[in] c blend with this color \param[in] i blend fraction \see Fl_Image::color_average(Fl_Color c, float i) */ void Fl_Shared_Image::color_average(Fl_Color c, float i) { if (!image_) return; image_->color_average(c, i); update(); } /** Convert the image to gray scale. This method changes the pixel data of this specific image. \note It does not change any of the resized copies of this image, nor does it necessarily apply the color changes if this image is resized later. \see Fl_Image::desaturate() */ void Fl_Shared_Image::desaturate() { if (!image_) return; image_->desaturate(); update(); } /** Draw this image to the current graphics context. \param[in] X, Y, W, H draw at this position and size \param[in] cx, cy image origin */ void Fl_Shared_Image::draw(int X, int Y, int W, int H, int cx, int cy) { if (!image_) { Fl_Image::draw(X, Y, W, H, cx, cy); return; } // transiently set the drawing size of image_ to that of the shared image int width = image_->w(), height = image_->h(); image_->scale(w(), h(), 0, 1); image_->draw(X, Y, W, H, cx, cy); image_->scale(width, height, 0, 1); } /** Remove the cached device specific image data. \see Fl_Image::uncache() */ void Fl_Shared_Image::uncache() { if (image_) image_->uncache(); } /** Finds a shared image from its name and size specifications. This uses a binary search in the image cache. If the image \p name exists with the exact width \p W and height \p H, then it is returned. If \p W == 0 and the image \p name exists with another size, then the \b original image with that \p name is returned. In either case the refcount of the returned image is increased. The found image should be released with Fl_Shared_Image::release() when no longer needed. An image is marked \p original if it was directly loaded from a file or from memory as opposed to copied and resized images. This comparison is used in Fl_Shared_Image::find() to find an image that matches the requested one or to find the position where a new image should be entered into the sorted list of shared images. It is used in two steps by Fl_Shared_Image::add(): -# search with exact width and height -# if not found, search again with width = 0 (and height = 0) The first step will only return a match if the image exists with the same width and height. The second step will match if there is an image marked \p original with the same name, regardless of width and height. */ Fl_Shared_Image* Fl_Shared_Image::find(const char *name, int W, int H) { if (num_images_) { if (W) { Fl_Shared_Image *key; // Image key Fl_Shared_Image **match; // Matching image key = new Fl_Shared_Image(); key->name_ = new char[strlen(name) + 1]; strcpy((char *)key->name_, name); key->w(W); key->h(H); match = (Fl_Shared_Image **)bsearch(&key, images_, num_images_, sizeof(Fl_Shared_Image *), (compare_func_t)compare); delete key; if (match) { (*match)->refcount_ ++; return *match; } } else { // if no width was given we need to find the original. The list is sorted // by name, width, and height, but we need to find the item by name with // the original_ flags set, no matter how wide, so binary search does not // work here. int i; for (i = 0; i < num_images_; ++i) { // If there are thousands of images and running the array becomes // inefficient, we can hand implement a binary search by name, and then // search back and forth from that location for the member with the // original_ flag set. Fl_Shared_Image *img = images_[i]; if (img->original_ && img->name_ && (strcmp(img->name_, name) == 0)) { img->refcount_++; return img; } } } } return NULL; } /** Find or load an image that can be shared by multiple widgets. If the image exists with the requested size, this image will be returned. If the image exists, but only with another size, then a new copy with the requested size (width \p W and height \p H) will be created as a resized copy of the original image. The new image is added to the internal list of shared images. If the image does not yet exist, then a new image of the proper dimension is created from the filename \p name. The original image from filename \p name is always added to the list of shared images in its original size. If the requested size differs, then the resized copy with width \p W and height \p H is also added to the list of shared images. \note If the sizes differ, then \e two images are created as mentioned above. This is intentional so the original image is cached and preserved. If you request the same image with another size later, then the \b original image will be found, copied, resized, and returned. Shared JPEG and PNG images can also be created from memory by using their named memory access constructor. You should release() the image when you're done with it. \param name name of the image \param W, H desired size \return the image at the requested size, or NULL if the image could not be found or generated \see Fl_Shared_Image::find(const char *name, int W, int H) \see Fl_Shared_Image::release() \see Fl_JPEG_Image::Fl_JPEG_Image(const char *name, const unsigned char *data) \see Fl_PNG_Image::Fl_PNG_Image (const char *name_png, const unsigned char *buffer, int maxsize) */ Fl_Shared_Image* Fl_Shared_Image::get(const char *name, int W, int H) { Fl_Shared_Image *temp; bool temp_referenced = false; // Find an image by the requested size // ::find() increments the ref count for us if ((temp = find(name, W, H)) != NULL) return temp; // Find the original image, size does not matter temp = find(name); if (temp) { temp_referenced = true; } else { // No original found, so we generate it by loading the file temp = new Fl_Shared_Image(name); // We can't load the file or create the image, so return fail if (!temp->image_) { delete temp; return NULL; } // Add the new image to the pool, refcount is already at 1 temp->add(); } // At this point, temp is an original image // But if the size is wrong, generate a resized copy if ((temp->w() != W || temp->h() != H) && W && H) { // Generate a copy with the new size, the copy gets refcount 1 Fl_Shared_Image *new_temp = temp->copy_(W, H); if (!new_temp) return NULL; // Also increment the refcount of the original image if (!temp_referenced) temp->refcount_++; // add the newly created image to the pool and return it new_temp->add(); return new_temp; } return temp; } /** Builds a shared image from a pre-existing Fl_RGB_Image. \param[in] rgb an Fl_RGB_Image used to build a new shared image. \param[in] own_it 1 if the shared image should delete \p rgb when it is itself deleted, 0 otherwise \version 1.3.4 */ Fl_Shared_Image *Fl_Shared_Image::get(Fl_RGB_Image *rgb, int own_it) { Fl_Shared_Image *shared = new Fl_Shared_Image(Fl_Preferences::newUUID(), rgb); shared->alloc_image_ = own_it; shared->add(); return shared; } /** Adds a shared image handler, which is basically a test function for adding new image formats. This function will be called when an Fl_Shared_Image is to be loaded (for instance with Fl_Shared_Image::get()) and the image type is not known to FLTK. All registered image handlers will be called in the order of registration. You should always call fl_register_images() before adding your own handlers - unless you need to override a known image file type which should be rare. \see Fl_Shared_Handler for more information of the function you need to define. */ void Fl_Shared_Image::add_handler(Fl_Shared_Handler f) { int i; // Looping var... Fl_Shared_Handler *temp; // New image handler array... // First see if we have already added the handler... for (i = 0; i < num_handlers_; i ++) { if (handlers_[i] == f) return; } if (num_handlers_ >= alloc_handlers_) { // Allocate more memory... temp = new Fl_Shared_Handler [alloc_handlers_ + 32]; if (alloc_handlers_) { memcpy(temp, handlers_, alloc_handlers_ * sizeof(Fl_Shared_Handler)); delete[] handlers_; } handlers_ = temp; alloc_handlers_ += 32; } handlers_[num_handlers_] = f; num_handlers_ ++; } /** Removes a shared image handler. */ void Fl_Shared_Image::remove_handler(Fl_Shared_Handler f) { int i; // Looping var... // First see if the handler has been added... for (i = 0; i < num_handlers_; i ++) { if (handlers_[i] == f) break; } if (i >= num_handlers_) return; // OK, remove the handler from the array... num_handlers_ --; if (i < num_handlers_) { // Shift later handlers down 1... memmove(handlers_ + i, handlers_ + i + 1, (num_handlers_ - i) * sizeof(Fl_Shared_Handler )); } } #ifdef SHIM_DEBUG /** Print the contents of the shared image pool. */ void Fl_Shared_Image::print_pool() { printf("Fl_Shared_Image: %d images stored in a pool of %d\n", num_images_, alloc_images_); for (int i=0; irefcount_, img->original_ ? 'O' : '_', img->w(), img->h(), img->name() ); } } #endif fltk-1.4.3/src/Fl_Progress.cxx0000644000175000017500000000532515004135251016352 0ustar albrechtalbrecht// // Progress bar widget routines. // // Copyright 2000-2010 by Michael Sweet. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // Fl_Progress::draw() - Draw the check button. // Fl_Progress::Fl_Progress() - Construct a Fl_Progress widget. // // // Include necessary header files... // #include #include #include // // Fl_Progress is a progress bar widget based off Fl_Widget that shows a // standard progress bar... // // // 'Fl_Progress::draw()' - Draw the progress bar. // /** Draws the progress bar. */ void Fl_Progress::draw() { int progress; // Size of progress bar... int bx, by, bw, bh; // Box areas... int tx, tw; // Temporary X + width // Get the box borders... bx = Fl::box_dx(box()); by = Fl::box_dy(box()); bw = Fl::box_dw(box()); bh = Fl::box_dh(box()); tx = x() + bx; tw = w() - bw; // Draw the progress bar... if (maximum_ > minimum_) progress = (int)(w() * (value_ - minimum_) / (maximum_ - minimum_) + 0.5f); else progress = 0; // Draw the box and label... if (progress > 0) { Fl_Color c = labelcolor(); labelcolor(fl_contrast(labelcolor(), selection_color())); fl_push_clip(x(), y(), progress + bx, h()); draw_box(box(), x(), y(), w(), h(), active_r() ? selection_color() : fl_inactive(selection_color())); draw_label(tx, y() + by, tw, h() - bh); fl_pop_clip(); labelcolor(c); if (progressNote on resizable(Fl_Widget &w): The "resizable" child widget (which should be invisible) limits where the borders can be dragged to. All dragging will be limited inside the resizable widget's borders. If you don't set it, it will be possible to drag the borders right to the edges of the Fl_Tile widget, and thus resize objects on the edges to zero width or height. When the entire Fl_Tile widget is resized, the resizable() widget will keep its border distance to all borders the same (this is normal resize behavior), so that you can effectively set a border width that will never change. To ensure correct event delivery to all child widgets the resizable() widget must be the first child of the Fl_Tile widget group. Otherwise some events (e.g. FL_MOVE and FL_ENTER) might be consumed by the resizable() widget so that they are lost for widgets covered (overlapped) by the resizable() widget. \note You can still resize widgets \b inside the resizable() to zero width and/or height, i.e. box \b 2b above to zero width and box \b 3a to zero height. \see void Fl_Group::resizable(Fl_Widget &w) Example for resizable with 20 pixel border distance: \code int dx = 20, dy = dx; Fl_Tile tile(50,50,300,300); // create resizable() box first Fl_Box r(tile.x()+dx,tile.y()+dy,tile.w()-2*dx,tile.h()-2*dy); tile.resizable(r); // ... create widgets inside tile (see test/tile.cxx) ... tile.end(); \endcode See also the complete example program in test/tile.cxx. */ #include #include #include #include static Fl_Cursor Fl_Tile_cursors[4] = { FL_CURSOR_DEFAULT, // 0 normal FL_CURSOR_WE, // 1 drag horizontally FL_CURSOR_NS, // 2 drag vertically FL_CURSOR_MOVE // 3 move intersection }; static int fl_min(int a, int b) { return ab ? a : b; } /** Request for children to change their layout. drag_intersection requests that all children with the left edge at old_l to shrink to new_l towards the right side of the tile. If the child can not shrink by that amount, it will ask all other children that touch its right side to shrink by the remainder (recursion). new_l will return the the maximum possible value while maintaining minimum width for all children involved. request_shrink_r asks children to shrink toward the left, so that their right edge is as close as possible to new_r. request_shrink_t and request_shrink_b provide the same functionality for vertical resizing. \param[in] old_l shrink all children with this current left edge \param[inout] new_l try to shrink to this coordinate, return the maximum possible shrinkage \param[inout] final_size if not NULL, write the new position and size of all affected children into this list of Fl_Rect */ void Fl_Tile::request_shrink_l(int old_l, int &new_l, Fl_Rect *final_size) { Fl_Rect *p = bounds(); int min_l = new_l; for (int i=0; ix() == old_l) { if (ri->w() == 0) { if (final_size) final_size[i].x(new_l); } else { // first, try to shrink int min_w = size_range_[i].minw; int may_l = fl_min(new_l, ri->r()-min_w); // enforce minimum width int new_l_right = ri->r(); // if that is not sufficient, try to move if (may_l < new_l) { int missing_w = new_l - may_l; new_l_right = ri->r() + missing_w; request_shrink_l(ri->r(), new_l_right, NULL); new_l_right = fl_min(new_l_right, p->r()); if (final_size) { request_shrink_l(ri->r(), new_l_right, final_size); request_grow_r(ri->r(), new_l_right, final_size); } min_l = fl_min(min_l, new_l_right - min_w); } if (final_size) { final_size[i].x(new_l); final_size[i].w(new_l_right-new_l); } } } } new_l = min_l; } /** Request for children to change their layout. \see Fl_Tile::request_shrink_l(int old_l, int &new_l, Fl_Rect *final_size) \param[in] old_r shrink all children with this current right edge toward the left edge of this tile \param[inout] new_r try to shrink to this coordinate, return the maximum possible shrinkage \param[inout] final_size if not NULL, write the new position and size of all affected children into this list of Fl_Rect */ void Fl_Tile::request_shrink_r(int old_r, int &new_r, Fl_Rect *final_size) { Fl_Rect *p = bounds(); int min_r = new_r; for (int i=0; ir() == old_r) { if (ri->w() == 0) { if (final_size) final_size[i].x(new_r); } else { // first, try to shrink int min_w = size_range_[i].minw; int may_r = fl_max(new_r, ri->x()+min_w); // enforce minimum width int new_r_left = ri->x(); // if that is not sufficient, try to move if (may_r > new_r) { int missing_w = may_r - new_r; new_r_left = ri->x() - missing_w; request_shrink_r(ri->x(), new_r_left, NULL); new_r_left = fl_max(new_r_left, p->x()); if (final_size) { request_shrink_r(ri->x(), new_r_left, final_size); request_grow_l(ri->x(), new_r_left, final_size); } min_r = fl_max(min_r, new_r_left + min_w); } if (final_size) { final_size[i].x(new_r_left); final_size[i].w(new_r-new_r_left); } } } } new_r = min_r; } /** Request for children to change their layout. \see Fl_Tile::request_shrink_l(int old_l, int &new_l, Fl_Rect *final_size) \param[in] old_t shrink all children with this current top edge toward the bottom edge of this tile \param[inout] new_t try to shrink to this coordinate, return the maximum possible shrinkage \param[inout] final_size if not NULL, write the new position and size of all affected children into this list of Fl_Rect */ void Fl_Tile::request_shrink_t(int old_t, int &new_t, Fl_Rect *final_size) { Fl_Rect *p = bounds(); int min_y = new_t; for (int i=0; iy() == old_t) { if (ri->h() == 0) { if (final_size) final_size[i].y(new_t); } else { // first, try to shrink int min_h = size_range_[i].minh; int may_y = fl_min(new_t, ri->b()-min_h); // enforce minimum height int new_y_below = ri->b(); // if that is not sufficient, try to move if (may_y < new_t) { int missing_h = new_t - may_y; new_y_below = ri->b() + missing_h; request_shrink_t(ri->b(), new_y_below, NULL); new_y_below = fl_min(new_y_below, p->b()); if (final_size) { request_shrink_t(ri->b(), new_y_below, final_size); request_grow_b(ri->b(), new_y_below, final_size); } min_y = fl_min(min_y, new_y_below - min_h); } if (final_size) { final_size[i].y(new_t); final_size[i].h(new_y_below-new_t); } } } } new_t = min_y; } /** Request for children to change their layout. \see Fl_Tile::request_shrink_l(int old_l, int &new_l, Fl_Rect *final_size) \param[in] old_b shrink all children with this current bottoom edge toward the top edge of this tile \param[inout] new_b try to shrink to this coordinate, return the maximum possible shrinkage \param[inout] final_size if not NULL, write the new position and size of all affected children into this list of Fl_Rect */ void Fl_Tile::request_shrink_b(int old_b, int &new_b, Fl_Rect *final_size) { Fl_Rect *p = bounds(); int min_b = new_b; for (int i=0; ib() == old_b) { if (ri->h() == 0) { if (final_size) final_size[i].y(new_b); } else { // first, try to shrink int min_h = size_range_[i].minh; int may_b = fl_max(new_b, ri->y()+min_h); // enforce minimum height int new_b_above = ri->y(); // if that is not sufficient, try to move if (may_b > new_b) { int missing_h = may_b - new_b; new_b_above = ri->y() - missing_h; request_shrink_b(ri->y(), new_b_above, NULL); new_b_above = fl_max(new_b_above, p->y()); if (final_size) { request_shrink_b(ri->y(), new_b_above, final_size); request_grow_t(ri->y(), new_b_above, final_size); } min_b = fl_max(min_b, new_b_above + min_h); } if (final_size) { final_size[i].y(new_b_above); final_size[i].h(new_b-new_b_above); } } } } new_b = min_b; } /** Request for children to change their layout. \param[in] old_l grow all children with this current left edge toward the left edge of this tile \param[inout] new_l try to grow to this coordinate, return the maximum possible growth (currently maxw is ignored, so we always grow to new_l) \param[inout] final_size write the new position and size of all affected children into this list of Fl_Rect */ void Fl_Tile::request_grow_l(int old_l, int &new_l, Fl_Rect *final_size) { Fl_Rect *p = bounds(); for (int i=0; ix() == old_l) { final_size[i].w(final_size[i].r() - new_l); final_size[i].x(new_l); } } } /** Request for children to change their layout. \param[in] old_r grow all children with this current right edge toward the right edge of this tile \param[inout] new_r try to grow to this coordinate, return the maximum possible growth (currently maxw is ignored, so we always grow to new_r) \param[inout] final_size write the new position and size of all affected children into this list of Fl_Rect */ void Fl_Tile::request_grow_r(int old_r, int &new_r, Fl_Rect *final_size) { Fl_Rect *p = bounds(); for (int i=0; ir() == old_r) { final_size[i].r(new_r); } } } /** Request for children to change their layout. \param[in] old_t grow all children with this current top edge toward the top edge of this tile \param[inout] new_t try to grow to this coordinate, return the maximum possible growth (currently maxh is ignored, so we always grow to new_t) \param[inout] final_size write the new position and size of all affected children into this list of Fl_Rect */ void Fl_Tile::request_grow_t(int old_t, int &new_t, Fl_Rect *final_size) { Fl_Rect *p = bounds(); for (int i=0; iy() == old_t) { final_size[i].h(final_size[i].b() - new_t); final_size[i].y(new_t); } } } /** Request for children to change their layout. \param[in] old_b grow all children with this current bottom edge toward the bottom edge of this tile \param[inout] new_b try to grow to this coordinate, return the maximum possible growth (currently maxh is ignored, so we always grow to new_b) \param[inout] final_size write the new position and size of all affected children into this list of Fl_Rect */ void Fl_Tile::request_grow_b(int old_b, int &new_b, Fl_Rect *final_size) { Fl_Rect *p = bounds(); for (int i=0; ib() == old_b) { final_size[i].b(new_b); } } } /** Drags the intersection at (\p oldx,\p oldy) to (\p newx,\p newy). This redraws all the necessary children. If no size ranges are set, the new intersection position is limited to the size of the tile group. The resizable() option is not taken into account here. If size ranges are set, the actual new position of the intersection will depend on the size range of every individual child. No child will be smaller than their minw and minh. After the new position is found, move_intersection() will call init_sizes(). The resizable() range is ignored. \param[in] oldx, oldy move the intersection at this coordinate, pass zero to disable drag in that direction. \param[in] newx, newy move the intersection as close to this new coordinate as possible */ void Fl_Tile::move_intersection(int oldx, int oldy, int newx, int newy) { if (size_range_) { drag_intersection(oldx, oldy, newx, newy); init_sizes(); } else { Fl_Widget*const* a = array(); Fl_Rect *p = bounds(); p += 2; // skip group & resizable's saved size for (int i=children(); i--; p++) { Fl_Widget* o = *a++; if (o == resizable()) continue; int X = o->x(); int R = X+o->w(); if (oldx) { int t = p->x(); if (t == oldx || (t>oldx && Xnewx) ) X = newx; t = p->r(); if (t == oldx || (t>oldx && Rnewx) ) R = newx; } int Y = o->y(); int B = Y+o->h(); if (oldy) { int t = p->y(); if (t == oldy || (t>oldy && Ynewy) ) Y = newy; t = p->b(); if (t == oldy || (t>oldy && Bnewy) ) B = newy; } o->damage_resize(X,Y,R-X,B-Y); } } } /** Drags the intersection at (\p oldx,\p oldy) to (\p newx,\p newy). \see Fl_Tile::move_intersection(int oldx, int oldy, int newx, int newy) , but this method does not call init_sizes() and is used for interactive children layout using the mouse. \param[in] oldx, oldy move the intersection at this coordinate, pass zero to disable drag in that direction. \param[in] newx, newy move the intersection as close to this new coordinate as possible */ void Fl_Tile::drag_intersection(int oldx, int oldy, int newx, int newy) { if (size_range_) { int i; Fl_Rect *p = bounds(); Fl_Rect *final_size = new Fl_Rect[children()]; for (i = 0; i < children(); i++) { final_size[i] = p[i+2]; } // apply changes in x and y intersection recursively to all children if ((oldy != 0) && (oldy != newy)) { if (newy <= oldy) { // user moves intersection up int new_y = newy; request_shrink_b(oldy, new_y, NULL); // updates new_y to the topmost possible request_shrink_b(oldy, new_y, final_size); // now update all children touching above request_grow_t(oldy, new_y, final_size); // now update all children touching below } if (newy > oldy) { // user moves intersection down int new_y = newy; request_shrink_t(oldy, new_y, NULL); // updates new_b to the bottommost possible request_shrink_t(oldy, new_y, final_size); // now update all children touching below request_grow_b(oldy, new_y, final_size); // now update all children touching above } } if ((oldx != 0) && (oldx != newx)) { if (newx <= oldx) { // user moves intersection left int new_x = newx; request_shrink_r(oldx, new_x, NULL); // updates new_x to the leftmost possible request_shrink_r(oldx, new_x, final_size); // now shring all children touching to the left request_grow_l(oldx, new_x, final_size); // now grow all children touching to the right } if (newx > oldx) { // user moves intersection right int new_x = newx; request_shrink_l(oldx, new_x, NULL); // updates new_x to the rightmost possible request_shrink_l(oldx, new_x, final_size); // now shrink all children touching on the right request_grow_r(oldx, new_x, final_size); // now grow all children touching on th eleft } } // resize all children that have changed in size for (i = 0; i < children(); i++) { Fl_Rect &r = final_size[i]; child(i)->damage_resize(r.x(), r.y(), r.w(), r.h()); } delete[] final_size; } else { move_intersection(oldx, oldy, newx, newy); } } /** Resizes the Fl_Tile widget and its children. Fl_Tile implements its own resize() method. It does not use Fl_Group::resize() to resize itself and its children. In size_range mode, the child marked resizable() is resized first. Only if its minimum size is reached, other widgets in the tile will resize too. In classic mode or when no resizable child is set, enlarging works by moving the lower-right corner and resizing the bottom and right border widgets accordingly. Shrinking the Fl_Tile works in the opposite way by shrinking the bottom and right border widgets, unless they are reduced to zero width or height, resp. or to their minimal sizes defined by the resizable() widget. In this case other widgets will be shrunk as well. See the Fl_Tile class documentation about how the resizable() works. */ void Fl_Tile::resize(int X,int Y,int W,int H) { if (size_range_) { // -- handle size_range style resizing int dx = X - x(); int dy = Y - y(); int dw = w() - W; int dh = h() - H; // -- if the size does not change, Group resize will suffice if ((dw==0) && (dh==0)) { Fl_Group::resize(X, Y, W, H); init_sizes(); redraw(); return; } // -- if the position changes, move all widgets first if ((dx!=0) || (dy!=0)) { for (int i = 0; i < children(); i++) { Fl_Widget *c = child(i); c->position(c->x()+dx, c->y()+dy); } } // check the current bounding box of all children init_sizes(); Fl_Rect *p = bounds(); int bbr = X, bbb = Y; for (int i = 0; i < children(); i++) { // find the current bounding box bbr = fl_max(bbr, p[i+2].r()); bbb = fl_max(bbb, p[i+2].b()); } // fix the dw to the maximum difference possible int r2 = X+W; request_shrink_r(bbr, r2, NULL); dw = bbr - r2; // fix the dh to the maximum difference possible int b2 = Y+H; request_shrink_b(bbb, b2, NULL); dh = bbb - b2; // perform the actual resize within a safe range if ((dw!=0) || (dh!=0)) { Fl_Widget *r = resizable(); // Find the target right and bottom position of the resizable child. int trr = 0, trb = 0; if (r) { trr = r->x() + r->w() - dw; trb = r->y() + r->h() - dh; } // Grow width and/or height of tile and adjust all children as needed. if ((dw < 0) && (dh < 0)) { move_intersection(bbr, bbb, bbr-dw, bbb-dh); } else if (dw < 0) { move_intersection(bbr, bbb, bbr-dw, bbb); } else if (dh < 0) { move_intersection(bbr, bbb, bbr, bbb-dh); } // Fix the resizable child, trying to keep its size plus all other // widgets within their limits. if (r) { int rr = r->x() + r->w(), rb = r->y() + r->h(); move_intersection(rr, rb, trr, trb); } // Shrink width and/or height of tile and adjust all children as needed. if ((dw > 0) && (dh > 0)) { move_intersection(bbr, bbb, bbr-dw, bbb-dh); } else if (dw > 0) { move_intersection(bbr, bbb, bbr-dw, bbb); } else if (dh > 0) { move_intersection(bbr, bbb, bbr, bbb-dh); } init_sizes(); } // resize the tile itself if (Fl_Window::is_a_rescale()) Fl_Group::resize(X, Y, W, H); else Fl_Widget::resize(X, Y, W, H); return; } // remember how much to move the child widgets: int dx = X-x(); int dy = Y-y(); int dw = W-w(); int dh = H-h(); Fl_Rect *p = bounds(); // resize this (skip the Fl_Group resize): Fl_Widget::resize(X,Y,W,H); // find bottom-right corner of resizable: int OR = p[1].r(); // old right border int NR = X+W-(p[0].r()-OR); // new right border int OB = p[1].b(); // old bottom border int NB = Y+H-(p[0].b()-OB); // new bottom border // move everything to be on correct side of new resizable: Fl_Widget*const* a = array(); p += 2; for (int i=children(); i--; p++) { Fl_Widget* o = *a++; int xx = o->x()+dx; int R = xx+o->w(); if (p->x() >= OR) xx += dw; else if (xx > NR) xx = NR; if (p->r() >= OR) R += dw; else if (R > NR) R = NR; int yy = o->y()+dy; int B = yy+o->h(); if (p->y() >= OB) yy += dh; else if (yy > NB) yy = NB; if (p->b() >= OB) B += dh; else if (B > NB) B = NB; o->resize(xx,yy,R-xx,B-yy); // do *not* call o->redraw() here! If you do, and the tile is inside a // scroll, it'll set the damage areas wrong for all children! } } /** Set one of four cursors used for dragging etc… Fl_Tile uses an array of four cursors that are set depending on user actions: - 0: normal cursor - 1: horizontal dragging - 2: vertical dragging - 3: dragging an intersection This method sets the window cursor for the given index \p n. */ void Fl_Tile::set_cursor(int n) { if (n < 0 || n > 3) n = 0; // check array index if (cursor_ == n) return; // nothing to do cursor_ = n; // store the cursor index if (window()) window()->cursor(cursor(n)); } #define DRAGH 1 #define DRAGV 2 #define GRABAREA 4 int Fl_Tile::handle(int event) { static int sdrag; static int sdx, sdy; static int sx, sy; int mx = Fl::event_x(); int my = Fl::event_y(); switch (event) { case FL_MOVE: case FL_ENTER: case FL_PUSH: // don't potentially change the mouse cursor if inactive: if (!active()) break; // will cascade inherited handle() { int mindx = 100; int mindy = 100; int oldx = 0; int oldy = 0; Fl_Widget*const* a = array(); Fl_Rect *q = bounds(); Fl_Rect *p = q+2; for (int i=children(); i--; p++) { Fl_Widget* o = *a++; if (!size_range_ && o == resizable()) continue; if (p->r() < q->r() && o->y()<=my+GRABAREA && o->y()+o->h()>=my-GRABAREA) { int t = mx - (o->x()+o->w()); if (abs(t) < mindx) { sdx = t; mindx = abs(t); oldx = p->r(); } } if (p->b() < q->b() && o->x()<=mx+GRABAREA && o->x()+o->w()>=mx-GRABAREA) { int t = my - (o->y()+o->h()); if (abs(t) < mindy) { sdy = t; mindy = abs(t); oldy = p->b(); } } } sdrag = 0; sx = sy = 0; if (mindx <= GRABAREA) {sdrag = DRAGH; sx = oldx;} if (mindy <= GRABAREA) {sdrag |= DRAGV; sy = oldy;} set_cursor(sdrag); if (sdrag) return 1; return Fl_Group::handle(event); } case FL_LEAVE: set_cursor(0); // set default cursor break; case FL_DRAG: // This is necessary if CONSOLIDATE_MOTION in Fl_x.cxx is turned off: // if (damage()) return 1; // don't fall behind case FL_RELEASE: { if (!sdrag) break; Fl_Widget* r = resizable(); if (size_range_ || !r) r = this; int newx; if (sdrag&DRAGH) { newx = Fl::event_x()-sdx; if (newx < r->x()) newx = r->x(); else if (newx > r->x()+r->w()) newx = r->x()+r->w(); } else newx = sx; int newy; if (sdrag&DRAGV) { newy = Fl::event_y()-sdy; if (newy < r->y()) newy = r->y(); else if (newy > r->y()+r->h()) newy = r->y()+r->h(); } else { newy = sy; } if (event == FL_DRAG) { drag_intersection(sx, sy, newx, newy); set_changed(); do_callback(FL_REASON_DRAGGED); } else { move_intersection(sx, sy, newx, newy); do_callback(FL_REASON_CHANGED); } return 1; } // case FL_RELEASE } // switch() return Fl_Group::handle(event); } /** Insert a new entry in the size range list. */ int Fl_Tile::on_insert(Fl_Widget *candidate, int index) { if (size_range_) { if (index >= size_range_capacity_) { size_range_capacity_ = (index+8) & ~7; // allocate in steps of 8 size_range_ = (Size_Range*)::realloc(size_range_, sizeof(Size_Range)*size_range_capacity_); } if (index < size_range_size_) memmove(size_range_+index+1, size_range_+index, sizeof(Size_Range)*(size_range_size_-index)); size_range_size_++; size_range_[index].minw = default_min_w_; size_range_[index].minh = default_min_h_; size_range_[index].maxw = 0x7FFFFFFF; size_range_[index].maxh = 0x7FFFFFFF; /* INTMAX_MAX */ } return index; } /** Move the entry in the size range list. */ int Fl_Tile::on_move(int oldIndex, int newIndex) { if (size_range_) { int delta = newIndex - oldIndex; if (delta) { Size_Range size_bak = size_range_[oldIndex]; if (delta > 0) memmove(size_range_+oldIndex, size_range_+oldIndex+1, sizeof(Size_Range)*delta); else memmove(size_range_+newIndex+1, size_range_+newIndex, sizeof(Size_Range)*-delta); size_range_[newIndex] = size_bak; } } return newIndex; } /** Remove the entry from the size range list. */ void Fl_Tile::on_remove(int index) { if (size_range_) { int num_trailing = size_range_size_-index-1; if ((index >= 0) && (index < size_range_size_) && (num_trailing > 0)) memmove(size_range_+index, size_range_+index+1, sizeof(Size_Range)*num_trailing); size_range_size_--; } } /** Set the allowed size range for the child at the given index. Fl_Tile currently supports only the minimal width and height setting. \param[in] index set the range for the child at this index \param[in] minw, minh minimum width and height for that child \param[in] maxw, maxh maximum size, defaults to infinite, currently ignored */ void Fl_Tile::size_range(int index, int minw, int minh, int maxw, int maxh) { if (!size_range_) init_size_range(); if ((index >= 0) && (index < children())) { size_range_[index].minw = minw; size_range_[index].minh = minh; size_range_[index].maxw = maxw; size_range_[index].maxh = maxh; } } /** Set the allowed size range for the give child widget. Fl_Tile currently supports only the minimal width and height setting. \param[in] w set the range for this child widget \param[in] minw, minh minimum width and height for that child \param[in] maxw, maxh maximum size, defaults to infinite, currently ignored */ void Fl_Tile::size_range(Fl_Widget *w , int minw, int minh, int maxw, int maxh) { int index = find(w); if ((index >= 0) && (index < children())) size_range(index, minw, minh, maxw, maxh); } /** Initialize the size range mode of Fl_Tile and set the default minimum width and height. The default minimum width and height is the size of the mouse pointer grab area at about 4 pixel units. \param[in] default_min_w, default_min_h default size range for widgets that don't have an individual range assigned */ void Fl_Tile::init_size_range(int default_min_w, int default_min_h) { if (default_min_w > 0) default_min_w_ = default_min_w; if (default_min_h > 0) default_min_h_ = default_min_h; if (!size_range_) { size_range_size_ = children(); size_range_capacity_ = (size_range_size_+8) & ~7; // allocate in steps of 8 size_range_ = (Size_Range*)::realloc(size_range_, sizeof(Size_Range)*size_range_capacity_); for (int i=0; ialso deletes all the children. This allows a whole tree to be deleted at once, without having to keep a pointer to all the children in the user code. A kludge has been done so the Fl_Tile and all of its children can be automatic (local) variables, but you must declare the Fl_Tile first, so that it is destroyed last. \see class Fl_Group */ Fl_Tile::Fl_Tile(int X,int Y,int W,int H,const char*L) : Fl_Group(X,Y,W,H,L), cursor_(0), cursors_(Fl_Tile_cursors), size_range_(NULL), size_range_size_(0), size_range_capacity_(0), default_min_w_(GRABAREA), default_min_h_(GRABAREA) { } /** Destructor. */ Fl_Tile::~Fl_Tile() { if (size_range_) ::free(size_range_); } fltk-1.4.3/src/fl_rect.cxx0000644000175000017500000000305715004135251015543 0ustar albrechtalbrecht// // Rectangle drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file fl_rect.cxx \brief Drawing and clipping routines for rectangles. */ // These routines from fl_draw.H are used by the standard boxtypes // and thus are always linked into an fltk program. // Also all fl_clip routines, since they are always linked in so // that minimal update works. #include #include // ----------------------------------------------------------------------------- // all driver code is now in drivers/XXX/Fl_XXX_Graphics_Driver_xyz.cxx // ----------------------------------------------------------------------------- /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** see fl_restore_clip() */ void Fl_Graphics_Driver::restore_clip() { fl_clip_state_number++; } /** see fl_clip_region(Fl_Region) */ void Fl_Graphics_Driver::clip_region(Fl_Region r) { Fl_Region oldr = rstack[rstackptr]; if (oldr) XDestroyRegion(oldr); rstack[rstackptr] = r; restore_clip(); } /** see fl_clip_region(void) */ Fl_Region Fl_Graphics_Driver::clip_region() { return rstack[rstackptr]; } /** \} \endcond */ fltk-1.4.3/src/Fl_Input.cxx0000644000175000017500000006750115004135251015651 0ustar albrechtalbrecht// // Input widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // This is the "user interface", it decodes user actions into what to // do to the text. See also Fl_Input_.cxx, where the text is actually // manipulated (and some ui, in particular the mouse, is done...). // In theory you can replace this code with another subclass to change // the keybindings. #include #include #include #include #include #include "Fl_System_Driver.H" #include "Fl_Screen_Driver.H" #include #include #include #include "flstring.h" // this #includes "" ! #include #include #include #include #include #include #include #ifdef HAVE_LOCALE_H # include #endif /** [this text may be customized at run-time] */ const char *Fl_Input::cut_menu_text = "Cut"; /** [this text may be customized at run-time] */ const char *Fl_Input::copy_menu_text = "Copy"; /** [this text may be customized at run-time] */ const char *Fl_Input::paste_menu_text = "Paste"; static Fl_Menu_Item rmb_menu[] = { { NULL, 0, NULL, (void*)1 }, { NULL, 0, NULL, (void*)2 }, { NULL, 0, NULL, (void*)3 }, { NULL } }; void Fl_Input::draw() { if (input_type() == FL_HIDDEN_INPUT) return; Fl_Boxtype b = box(); if (damage() & FL_DAMAGE_ALL) draw_box(b, color()); Fl_Input_::drawtext(x()+Fl::box_dx(b), y()+Fl::box_dy(b), w()-Fl::box_dw(b), h()-Fl::box_dh(b)); } // kludge so shift causes selection to extend: int Fl_Input::shift_position(int p) { return insert_position(p, Fl::event_state(FL_SHIFT) ? mark() : p); } int Fl_Input::shift_up_down_position(int p) { return up_down_position(p, Fl::event_state(FL_SHIFT)); } // Old text from FLTK 1.1 for reference: // If you define NORMAL_INPUT_MOVE as zero you will get the peculiar fltk // behavior where moving off the end of an input field will move the // cursor into the next field: // define it as 1 to prevent cursor movement from going to next field: // // Note: this has been replaced by Fl::option(Fl::OPTION_ARROW_FOCUS) // in FLTK 1.3. This option has "inverted" values: // 1 = Arrow keys move focus (previously 0) // 0 = Arrow keys don't move focus (previously 1) // Hence we define ... // #define NORMAL_INPUT_MOVE (Fl::option(Fl::OPTION_ARROW_FOCUS) ? 0 : 1) #define ctrl(x) ((x)^0x40) // List of characters that are legal in a floating point input field. // This text string is created at run-time to take the current locale // into account (for example, continental Europe uses a comma instead // of a decimal point). For back compatibility reasons, we always // allow the decimal point. #ifdef HAVE_LOCALECONV static const char *standard_fp_chars = ".eE+-"; static const char *legal_fp_chars = 0L; #else static const char *legal_fp_chars = ".eE+-"; #endif // Move cursor up specified #lines // If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation. // int Fl_Input::kf_lines_up(int repeat_num) { int i = insert_position(); if (!line_start(i)) { //UNNEEDED if (input_type()==FL_MULTILINE_INPUT && !Fl::option(Fl::OPTION_ARROW_FOCUS)) return 1; return NORMAL_INPUT_MOVE; } while(repeat_num--) { i = line_start(i); if (!i) break; i--; } shift_up_down_position(line_start(i)); return 1; } // Move cursor down specified #lines // If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation. // int Fl_Input::kf_lines_down(int repeat_num) { int i = insert_position(); if (line_end(i) >= size()) { //UNNEEDED if (input_type()==FL_MULTILINE_INPUT && !Fl::option(Fl::OPTION_ARROW_FOCUS)) return 1; return NORMAL_INPUT_MOVE; } while (repeat_num--) { i = line_end(i); if (i >= size()) break; i++; } shift_up_down_position(i); return 1; } // Move up a page int Fl_Input::kf_page_up() { return kf_lines_up(linesPerPage()); } // Move down a page int Fl_Input::kf_page_down() { return kf_lines_down(linesPerPage()); } // Toggle insert mode int Fl_Input::kf_insert_toggle() { if (readonly()) { fl_beep(); return 1; } return 1; // \todo: needs insert mode } // Delete word right int Fl_Input::kf_delete_word_right() { if (readonly()) { fl_beep(); return 1; } if (mark() != insert_position()) return cut(); cut(insert_position(), word_end(insert_position())); return 1; } // Delete word left int Fl_Input::kf_delete_word_left() { if (readonly()) { fl_beep(); return 1; } if (mark() != insert_position()) return cut(); cut(word_start(insert_position()), insert_position()); return 1; } // Delete to start of line int Fl_Input::kf_delete_sol() { if (readonly()) { fl_beep(); return 1; } if (mark() != insert_position()) return cut(); cut(line_start(insert_position()), insert_position()); return 1; } // Delete to end of line int Fl_Input::kf_delete_eol() { if (readonly()) { fl_beep(); return 1; } if (mark() != insert_position()) return cut(); cut(insert_position(), line_end(insert_position())); return 1; } int Fl_Input::kf_delete_char_right() { if (readonly()) { fl_beep(); return 1; } if (mark() != insert_position()) cut(); else cut(1); return 1; } int Fl_Input::kf_delete_char_left() { if (readonly()) { fl_beep(); return 1; } if (mark() != insert_position()) cut(); else cut(-1); return 1; } // Move cursor to start of line int Fl_Input::kf_move_sol() { return shift_position(line_start(insert_position())) + NORMAL_INPUT_MOVE; } // Move cursor to end of line int Fl_Input::kf_move_eol() { return shift_position(line_end(insert_position())) + NORMAL_INPUT_MOVE; } // Clear to end of line int Fl_Input::kf_clear_eol() { if (readonly()) { fl_beep(); return 1; } if (insert_position()>=size()) return 0; int i = line_end(insert_position()); if (i == insert_position() && i < size()) i++; cut(insert_position(), i); return copy_cuts(); } // Move cursor one character to the left // If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation. // int Fl_Input::kf_move_char_left() { int i = shift_position(insert_position()-1) + NORMAL_INPUT_MOVE; return Fl::option(Fl::OPTION_ARROW_FOCUS) ? i : 1; } // Move cursor one character to the right // If OPTION_ARROW_FOCUS is disabled, return 1 to prevent focus navigation. // int Fl_Input::kf_move_char_right() { int i = shift_position(insert_position()+1) + NORMAL_INPUT_MOVE; return Fl::option(Fl::OPTION_ARROW_FOCUS) ? i : 1; } // Move cursor word-left int Fl_Input::kf_move_word_left() { shift_position(word_start(insert_position())); return 1; } // Move cursor word-right int Fl_Input::kf_move_word_right() { shift_position(word_end(insert_position())); return 1; } // Move cursor up one line and to the start of line (paragraph up) int Fl_Input::kf_move_up_and_sol() { if (line_start(insert_position())==insert_position() && insert_position()>0) return shift_position(line_start(insert_position()-1)) + NORMAL_INPUT_MOVE; else return shift_position(line_start(insert_position())) + NORMAL_INPUT_MOVE; } // Move cursor down one line and to the end of line (paragraph down) int Fl_Input::kf_move_down_and_eol() { if (line_end(insert_position())==insert_position() && insert_position()decimal_point) len += strlen(lc->decimal_point); if (lc->mon_decimal_point) len += strlen(lc->mon_decimal_point); if (lc->positive_sign) len += strlen(lc->positive_sign); if (lc->negative_sign) len += strlen(lc->negative_sign); } // the following line is not a true memory leak because the array is only // allocated once if required, and automatically freed when the program quits char *chars = (char*)malloc(len+1); legal_fp_chars = chars; strcpy(chars, standard_fp_chars); if (lc) { if (lc->decimal_point) strcat(chars, lc->decimal_point); if (lc->mon_decimal_point) strcat(chars, lc->mon_decimal_point); if (lc->positive_sign) strcat(chars, lc->positive_sign); if (lc->negative_sign) strcat(chars, lc->negative_sign); } } #endif // HAVE_LOCALECONV // find the insert position int ip = insert_position()= '0' && ascii <= '9') || (ip==1 && index(0)=='0' && (ascii=='x' || ascii == 'X')) || (ip>1 && index(0)=='0' && (index(1)=='x'||index(1)=='X') && ((ascii>='A'&& ascii<='F') || (ascii>='a'&& ascii<='f'))) || (input_type()==FL_FLOAT_INPUT && ascii && strchr(legal_fp_chars, ascii))) { if (readonly()) fl_beep(); else replace(insert_position(), mark(), &ascii, 1); } return 1; } if (del || Fl::event_length()) { if (readonly()) fl_beep(); else replace(insert_position(), del ? insert_position()-del : mark(), Fl::event_text(), Fl::event_length()); } if (Fl::screen_driver()->has_marked_text() && Fl::compose_state) { this->mark( this->insert_position() - Fl::compose_state ); } return 1; } int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT); unsigned int shift = Fl::event_state() & FL_SHIFT; unsigned int multiline = (input_type() == FL_MULTILINE_INPUT) ? 1 : 0; // // The following lists apps that support these keypresses. // Prefixes: '!' indicates NOT supported, '?' indicates un-verified. // // HIG=Human Interface Guide, // TE=TextEdit.app, SA=Safari.app, WOX=MS Word/OSX -- OSX 10.4.x // NP=Notepad, WP=WordPad, WOW=MS Word/Windows -- WinXP // GE=gedit, KE=kedit -- Ubuntu8.04 // OF=old FLTK behavior (<=1.1.10) // // Example: (NP,WP,!WO) means supported in notepad + wordpad, but NOT word. // // handle keypresses that can have a platform-dependent processing int retval = Fl::screen_driver()->input_widget_handle_key(Fl::event_key(), mods, shift, this); if (retval >= 0) return retval; switch (Fl::event_key()) { case FL_Insert: // Note: Mac has no "Insert" key; it's the "Help" key. // This keypress is apparently not possible on macs. // if (mods==0 && shift) return kf_paste(); // Shift-Insert (WP,NP,WOW,GE,KE,OF) if (mods==0) return kf_insert_toggle(); // Insert (Standard) if (mods==FL_CTRL) return kf_copy(); // Ctrl-Insert (WP,NP,WOW,GE,KE,OF) return 0; // ignore other combos, pass to parent case FL_Enter: case FL_KP_Enter: if (when() & FL_WHEN_ENTER_KEY) { insert_position(size(), 0); maybe_do_callback(FL_REASON_ENTER_KEY); return 1; } else if (multiline && !readonly()) { return replace(insert_position(), mark(), "\n", 1); } return 0; // reserved for shortcuts case FL_Tab: // Handle special case for multiline input with 'old tab behavior'; // tab handled as a normal insertable character. // if (mods==0 && !shift // Tab? && !tab_nav() // old tab behavior enabled? && multiline) { // multiline input? break; // insert tab character } if (mods==0) return 0; // Tab, Shift-Tab? nav focus (Standard/OSX-HIG) return 0; // ignore other combos, pass to parent case 'a': if (mods==FL_COMMAND) return kf_select_all(); // Ctrl-A, Mac:Meta-A (Standard/OSX-HIG) break; // handle other combos elsewhere case 'c': if (mods==FL_COMMAND) return kf_copy(); // Ctrl-C, Mac:Meta-C (Standard/OSX-HIG) break; // handle other combos elsewhere case 'v': if (mods==FL_COMMAND) return kf_paste(); // Ctrl-V, Mac:Meta-V (Standard/OSX-HIG) break; // handle other combos elsewhere case 'x': if (mods==FL_COMMAND) return kf_copy_cut(); // Ctrl-X, Mac:Meta-X (Standard/OSX-HIG) break; case 'z': if (mods==FL_COMMAND && !shift) { // Ctrl-Z, Mac:Meta-Z (Standard/OSX-HIG) if (!kf_undo()) fl_beep(); return 1; } if (mods==FL_COMMAND && shift) { // Shift-Ctrl-Z, Mac:Shift-Meta-Z (Standard/OSX-HIG) if (!kf_redo()) fl_beep(); return 1; } break; // handle other combos elsewhere } switch (ascii) { case ctrl('H'): return kf_delete_char_left(); // Ctrl-H (!WP,!NP,!WOW,!WOX,TE,SA,GE,KE,OF) case ctrl('I'): // Ctrl-I (literal Tab) (!WP,NP,!WOW,!GE,KE,OF) case ctrl('J'): // Ctrl-J (literal Line Feed/Enter) (Standard) case ctrl('L'): // Ctrl-L (literal Form Feed) (Standard) case ctrl('M'): // Ctrl-M (literal Cr) (Standard) if (readonly()) { fl_beep(); return 1; } // insert a few selected control characters literally: if (input_type() != FL_FLOAT_INPUT && input_type() != FL_INT_INPUT) return replace(insert_position(), mark(), &ascii, 1); break; } return 0; // ignored } /** \internal Simple function that determines if a character is a whitespace. \todo This function is not UTF-8-aware. */ static int fltk__isspace(char c) { return (c&128 || isspace(c)); } /** Handle right mouse button down events. \return 1 */ int Fl_Input::handle_rmb() { if (Fl::event_button() == FL_RIGHT_MOUSE) { // on right mouse button, pop up a Cut/Copy/Paste menu int newpos, oldpos = insert_position(), oldmark = mark(); Fl_Boxtype b = box(); Fl_Input_::handle_mouse(x()+Fl::box_dx(b), y()+Fl::box_dy(b), w()-Fl::box_dw(b), h()-Fl::box_dh(b), 0); newpos = insert_position(); if ( ((oldpos < newpos) && (oldmark > newpos)) || ((oldmark < newpos) && (oldpos > newpos)) || (type() == FL_SECRET_INPUT)) { // if the user clicked inside an existing selection, keep // the selection insert_position(oldpos, oldmark); } else { if ((index(newpos) == 0) || (index(newpos) == '\n')) { // if clicked to the right of the line or text end, clear the // selection and set the cursor at the end of the line insert_position(newpos, newpos); } else if (fltk__isspace(index(newpos))) { // if clicked into a whitespace, select the entire whitespace oldpos = newpos; while (oldpos > 0 && fltk__isspace(index(oldpos-1))) oldpos--; oldmark = newpos+1; while (oldmark < size() && fltk__isspace(index(oldmark))) oldmark++; insert_position(oldpos, oldmark); } else { // if clicked on a word, select the entire word insert_position(word_start(newpos), word_end(newpos)); } } // keep the menu labels current rmb_menu[0].label(Fl_Input::cut_menu_text); rmb_menu[1].label(Fl_Input::copy_menu_text); rmb_menu[2].label(Fl_Input::paste_menu_text); // give only the menu options that make sense if (readonly()) { rmb_menu[0].deactivate(); // cut rmb_menu[2].deactivate(); // paste } else { rmb_menu[0].activate(); // cut rmb_menu[2].activate(); // paste } // pop up the menu fl_cursor(FL_CURSOR_DEFAULT); const Fl_Menu_Item *mi = rmb_menu->popup(Fl::event_x(), Fl::event_y()); if (mi) switch (mi->argument()) { case 1: if (type() != FL_SECRET_INPUT) kf_copy_cut(); break; case 2: if (type() != FL_SECRET_INPUT) kf_copy(); break; case 3: kf_paste(); break; } } return 1; } int Fl_Input::handle(int event) { static int dnd_save_position, dnd_save_mark, drag_start = -1, newpos; static Fl_Widget *dnd_save_focus = NULL; switch (event) { case FL_UNFOCUS: if (Fl::screen_driver()->has_marked_text() && Fl::compose_state) { this->mark( this->insert_position() ); fl_reset_spot(); } break; case FL_FOCUS: switch (Fl::event_key()) { case FL_Right: insert_position(0); break; case FL_Left: insert_position(size()); break; case FL_Down: up_down_position(0); break; case FL_Up: up_down_position(line_start(size())); break; case FL_Tab: insert_position(size(),0); break; default: insert_position(insert_position(),mark());// turns off the saved up/down arrow position break; } break; case FL_KEYBOARD: // Handle special case for multiline input with 'old tab behavior' // where tab is entered as a character: make sure user attempt to 'tab over' // widget doesn't destroy the field, replacing it with a tab character. // if (Fl::event_key() == FL_Tab // Tab key? && !Fl::event_state(FL_SHIFT) // no shift? && !tab_nav() // with tab navigation disabled? && input_type() == FL_MULTILINE_INPUT // with a multiline input? && size() > 0 // non-empty field? && ((mark()==0 && insert_position()==size()) || (insert_position()==0 && mark()==size()))) {// while entire field selected? // Set cursor to the end of the selection... if (mark() > insert_position()) insert_position(mark()); else insert_position(insert_position()); return (1); } else { if (active_r() && window() && this == Fl::belowmouse()) window()->cursor(FL_CURSOR_NONE); return handle_key(); } //NOTREACHED case FL_PUSH: if (Fl::dnd_text_ops() && (Fl::event_button() != FL_RIGHT_MOUSE)) { int oldpos = insert_position(), oldmark = mark(); Fl_Boxtype b = box(); Fl_Input_::handle_mouse(x()+Fl::box_dx(b), y()+Fl::box_dy(b), w()-Fl::box_dw(b), h()-Fl::box_dh(b), 0); newpos = insert_position(); insert_position( oldpos, oldmark ); if (Fl::focus()==this && !Fl::event_state(FL_SHIFT) && input_type()!=FL_SECRET_INPUT && ( (newpos >= mark() && newpos < insert_position()) || (newpos >= insert_position() && newpos < mark()) ) ) { // user clicked in the selection, may be trying to drag drag_start = newpos; return 1; } drag_start = -1; } if (Fl::focus() != this) { Fl::focus(this); handle(FL_FOCUS); } if (Fl::event_button() == FL_RIGHT_MOUSE) { return handle_rmb(); } break; case FL_DRAG: if (Fl::dnd_text_ops()) { if (drag_start >= 0) { if (Fl::event_is_click()) return 1; // debounce the mouse // save the position because sometimes we don't get DND_ENTER: dnd_save_position = insert_position(); dnd_save_mark = mark(); dnd_save_focus = this; // drag the data: copy(0); Fl::screen_driver()->dnd(1); return 1; } } break; case FL_RELEASE: if (Fl::event_button() == FL_MIDDLE_MOUSE) { Fl::event_is_click(0); // stop double click from picking a word Fl::paste(*this, 0); } else if (Fl::event_button() == FL_RIGHT_MOUSE) { return 1; } else if (!Fl::event_is_click()) { // copy drag-selected text to the clipboard. copy(0); } else if (Fl::event_is_click() && drag_start >= 0) { // user clicked in the field and wants to reset the cursor position... insert_position(drag_start, drag_start); drag_start = -1; } else if (Fl::event_clicks()) { // user double or triple clicked to select word or whole text copy(0); } // For output widgets, do the callback so the app knows the user // did something with the mouse... if (readonly()) do_callback(FL_REASON_RELEASED); return 1; case FL_DND_ENTER: Fl::belowmouse(this); // send the leave events first if (dnd_save_focus != this) { dnd_save_position = insert_position(); dnd_save_mark = mark(); dnd_save_focus = Fl::focus(); Fl::focus(this); handle(FL_FOCUS); } // fall through: case FL_DND_DRAG: //int p = mouse_position(X, Y, W, H); #ifdef DND_OUT_XXXX if (Fl::focus()==this && (p>=dnd_save_position && p<=dnd_save_mark || p>=dnd_save_mark && p<=dnd_save_position)) { position(dnd_save_position, dnd_save_mark); return 0; } #endif { Fl_Boxtype b = box(); Fl_Input_::handle_mouse(x()+Fl::box_dx(b), y()+Fl::box_dy(b), w()-Fl::box_dw(b), h()-Fl::box_dh(b), 0); } return 1; case FL_DND_LEAVE: insert_position(dnd_save_position, dnd_save_mark); #ifdef DND_OUT_XXXX if (!focused()) #endif if (dnd_save_focus && dnd_save_focus != this) { Fl::focus(dnd_save_focus); handle(FL_UNFOCUS); } Fl::first_window()->cursor(FL_CURSOR_MOVE); dnd_save_focus = NULL; return 1; case FL_DND_RELEASE: if (dnd_save_focus == this) { // if the dragged text comes from the same widget if (!readonly()) { // remove the selected text int old_position = insert_position(); if (dnd_save_mark > dnd_save_position) { int tmp = dnd_save_mark; dnd_save_mark = dnd_save_position; dnd_save_position = tmp; } replace(dnd_save_mark, dnd_save_position, NULL, 0); if (old_position > dnd_save_position) insert_position(old_position - (dnd_save_position - dnd_save_mark)); else insert_position(old_position); } // !readonly() } // from the same widget else if (dnd_save_focus) { dnd_save_focus->handle(FL_UNFOCUS); } dnd_save_focus = NULL; take_focus(); return 1; /* TODO: this will scroll the area, but stop if the cursor would become invisible. That clipping happens in drawtext(). Do we change the clipping or should we move the cursor (ouch)? case FL_MOUSEWHEEL: if (Fl::e_dy > 0) { yscroll( yscroll() - Fl::e_dy*15 ); } else if (Fl::e_dy < 0) { yscroll( yscroll() - Fl::e_dy*15 ); } return 1; */ } Fl_Boxtype b = box(); return Fl_Input_::handletext(event, x()+Fl::box_dx(b), y()+Fl::box_dy(b), w()-Fl::box_dw(b), h()-Fl::box_dh(b)); } /** Creates a new Fl_Input widget using the given position, size, and label string. The default boxtype is FL_DOWN_BOX. */ Fl_Input::Fl_Input(int X, int Y, int W, int H, const char *l) : Fl_Input_(X, Y, W, H, l) { } Fl_Float_Input::Fl_Float_Input(int X,int Y,int W,int H,const char *l) : Fl_Input(X,Y,W,H,l) { type(FL_FLOAT_INPUT); clear_flag(MAC_USE_ACCENTS_MENU); } Fl_Int_Input::Fl_Int_Input(int X,int Y,int W,int H,const char *l) : Fl_Input(X,Y,W,H,l) { type(FL_INT_INPUT); clear_flag(MAC_USE_ACCENTS_MENU); } Fl_Multiline_Input::Fl_Multiline_Input(int X,int Y,int W,int H,const char *l) : Fl_Input(X,Y,W,H,l) { type(FL_MULTILINE_INPUT); } Fl_Output::Fl_Output(int X,int Y,int W,int H, const char *l) : Fl_Input(X, Y, W, H, l) { type(FL_NORMAL_OUTPUT); clear_flag(NEEDS_KEYBOARD); } Fl_Multiline_Output::Fl_Multiline_Output(int X,int Y,int W,int H,const char *l) : Fl_Output(X,Y,W,H,l) { type(FL_MULTILINE_OUTPUT); clear_flag(NEEDS_KEYBOARD); } Fl_Secret_Input::Fl_Secret_Input(int X,int Y,int W,int H,const char *l) : Fl_Input(X,Y,W,H,l) { type(FL_SECRET_INPUT); clear_flag(MAC_USE_ACCENTS_MENU); } int Fl_Secret_Input::handle(int event) { int retval = Fl_Input::handle(event); if (event == FL_KEYBOARD && Fl::screen_driver()->has_marked_text() && Fl::compose_state) { this->mark( this->insert_position() ); // don't underline marked text } return retval; } fltk-1.4.3/src/Fl_Return_Button.cxx0000644000175000017500000000347315004135251017362 0ustar albrechtalbrecht// // Return button widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include int fl_return_arrow(int x, int y, int w, int h) { int size = w; if (h # define MAXWINDOWS 32 static Fl_Glut_Window *windows[MAXWINDOWS+1]; static void (*glut_idle_func)() = 0; // global glut idle function // The current GLUT window, may be NULL. See also STR #3458. Fl_Glut_Window *glut_window; int glut_menu; void (*glut_menustate_function)(int); void (*glut_menustatus_function)(int,int,int); static void default_reshape(int w, int h) {glViewport(0,0,w,h);} static void default_display() {} void Fl_Glut_Window::make_current() { glut_window = this; if (shown()) Fl_Gl_Window::make_current(); } static int indraw; void Fl_Glut_Window::draw() { glut_window = this; indraw = 1; if (!valid()) {reshape(pixel_w(),pixel_h()); valid(1);} display(); if (children()) { Fl_Gl_Window::draw(); // Draw FLTK child widgets } indraw = 0; } void glutSwapBuffers() { if (!indraw && glut_window) glut_window->swap_buffers(); } void Fl_Glut_Window::draw_overlay() { glut_window = this; if (!valid()) {reshape(pixel_w(),pixel_h()); valid(1);} overlaydisplay(); } static void domenu(int, int, int); int Fl_Glut_Window::handle(int event) { make_current(); int ex = Fl::event_x(); int ey = Fl::event_y(); float factor = pixels_per_unit(); ex = int(ex * factor + 0.5f); ey = int(ey * factor + 0.5f); int button; switch (event) { case FL_PUSH: if (keyboard || special) Fl::focus(this); button = Fl::event_button()-1; if (button<0) button = 0; if (button>2) button = 2; if (menu[button]) {domenu(menu[button],ex,ey); return 1;} mouse_down |= 1< 0) {if (mouse) mouse(4,GLUT_DOWN,ex,ey); --button;} return 1; case FL_RELEASE: for (button = 0; button < 3; button++) if (mouse_down & (1< FL_F && k <= FL_F_Last) k -= FL_F; special(k,ex,ey); return 1; } break; } case FL_HIDE: if (visibility) visibility(GLUT_NOT_VISIBLE); break; case FL_SHOW: if (visibility) visibility(GLUT_VISIBLE); break; } return Fl_Gl_Window::handle(event); } static int glut_mode = GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH; void Fl_Glut_Window::_init() { for (number=1; numberresizable(W); if (initargc) { W->show(initargc,initargv); initargc = 0; } else { W->show(); } W->valid(0); W->context_valid(0); W->make_current(); // some platforms (e.g., macOS 10.9) draw the window while show() runs // but the window's draw function is not yet set when this function runs W->redraw(); return W->number; } int glutCreateSubWindow(int win, int x, int y, int w, int h) { Fl_Glut_Window *W = new Fl_Glut_Window(x,y,w,h,0); windows[win]->add(W); if (windows[win]->shown()) { W->show(); W->make_current(); W->redraw(); } return W->number; } /** Destroys the glut window, first unregister it from the glut windows list */ Fl_Glut_Window::~Fl_Glut_Window() { if (glut_window == this) glut_window = 0; windows[number] = 0; } void glutDestroyWindow(int win) { // should destroy children!!! delete windows[win]; } void glutPostWindowRedisplay(int win) { windows[win]->redraw(); } void glutSetWindow(int win) { windows[win]->make_current(); } //////////////////////////////////////////////////////////////// #include struct menu { void (*cb)(int); Fl_Menu_Item *m; int size; int alloc; }; #define MAXMENUS 32 static menu menus[MAXMENUS+1]; static void domenu(int n, int ex, int ey) { glut_menu = n; menu *m = &menus[n]; if (glut_menustate_function) glut_menustate_function(1); if (glut_menustatus_function) glut_menustatus_function(1,ex,ey); const Fl_Menu_Item* g = m->m->popup(Fl::event_x(), Fl::event_y(), 0); if (g && g->callback_) ((void (*)(int))(g->callback_))(int(g->argument())); if (glut_menustatus_function) glut_menustatus_function(0,ex,ey); if (glut_menustate_function) glut_menustate_function(0); } int glutCreateMenu(void (*cb)(int)) { int i; for (i=1; icb = cb; return glut_menu = i; } void glutDestroyMenu(int n) { menu *m = &menus[n]; delete[] m->m; m->m = 0; m->cb = 0; m->size = m->alloc = 0; } static Fl_Menu_Item* additem(menu *m) { if (m->size+1 >= m->alloc) { m->alloc = m->size*2+10; Fl_Menu_Item* nm = new Fl_Menu_Item[m->alloc]; for (int i=0; isize; i++) nm[i] = m->m[i]; delete[] m->m; m->m = nm; } int n = m->size++; m->m[n+1].text = 0; Fl_Menu_Item* i = &(m->m[n]); i->shortcut_ = 0; i->flags = 0; i->labeltype_ = i->labelfont_ = i->labelsize_ = i->labelcolor_ = 0; return i; } void glutAddMenuEntry(const char *label, int value) { menu *m = &menus[glut_menu]; Fl_Menu_Item* i = additem(m); i->text = label; i->callback_ = (Fl_Callback*)(m->cb); i->argument(value); } void glutAddSubMenu(char *label, int submenu) { menu *m = &menus[glut_menu]; Fl_Menu_Item* i = additem(m); i->text = label; i->callback_ = 0; i->user_data_ = (void *)(menus[submenu].m); i->flags = FL_PUP_SUBMENU; } void glutChangeToMenuEntry(int item, char *label, int value) { menu *m = &menus[glut_menu]; Fl_Menu_Item* i = &m->m[item-1]; i->text = label; i->callback_ = (Fl_Callback*)(m->cb); i->argument(value); i->flags = 0; } void glutChangeToSubMenu(int item, char *label, int submenu) { menu *m = &menus[glut_menu]; Fl_Menu_Item* i = &m->m[item-1]; i->text = label; i->callback_ = 0; i->user_data_ = (void *)(menus[submenu].m); i->flags = FL_PUP_SUBMENU; } void glutRemoveMenuItem(int item) { menu *m = &menus[glut_menu]; if (item > m->size || item < 1) return; for (int i = item-1; i <= m->size; i++) m->m[i] = m->m[i+1]; m->size--; } //////////////////////////////////////////////////////////////// int glutGet(GLenum type) { switch (type) { case GLUT_RETURN_ZERO: return 0; case GLUT_WINDOW_X: return glut_window ? glut_window->x() : 0; case GLUT_WINDOW_Y: return glut_window ? glut_window->y() : 0; case GLUT_WINDOW_WIDTH: return glut_window ? glut_window->pixel_w() : 0; case GLUT_WINDOW_HEIGHT: return glut_window ? glut_window->pixel_h() : 0; case GLUT_WINDOW_PARENT: if (glut_window && glut_window->parent()) return ((Fl_Glut_Window *)(glut_window->parent()))->number; else return 0; //case GLUT_WINDOW_NUM_CHILDREN: //case GLUT_WINDOW_CURSOR: return case GLUT_SCREEN_WIDTH: return Fl::w(); case GLUT_SCREEN_HEIGHT: return Fl::h(); //case GLUT_SCREEN_WIDTH_MM: //case GLUT_SCREEN_HEIGHT_MM: case GLUT_MENU_NUM_ITEMS: return menus[glut_menu].size; case GLUT_DISPLAY_MODE_POSSIBLE: return Fl_Gl_Window::can_do(glut_mode); case GLUT_INIT_WINDOW_X: return initx; case GLUT_INIT_WINDOW_Y: return inity; case GLUT_INIT_WINDOW_WIDTH: return initw; case GLUT_INIT_WINDOW_HEIGHT: return inith; case GLUT_INIT_DISPLAY_MODE: return glut_mode; case GLUT_ELAPSED_TIME: if (!glut_starttime_set) { glut_starttime = Fl::now(); glut_starttime_set = 1; } return (int)(Fl::seconds_since(glut_starttime)*1000.0); // milliseconds case GLUT_WINDOW_BUFFER_SIZE: if (glutGet(GLUT_WINDOW_RGBA)) return glutGet(GLUT_WINDOW_RED_SIZE)+ glutGet(GLUT_WINDOW_GREEN_SIZE)+ glutGet(GLUT_WINDOW_BLUE_SIZE)+ glutGet(GLUT_WINDOW_ALPHA_SIZE); else return glutGet(GLUT_WINDOW_COLORMAP_SIZE); case GLUT_VERSION: return 20400; default: {GLint p; glGetIntegerv(type, &p); return p;} } } int glutLayerGet(GLenum type) { switch (type) { case GLUT_OVERLAY_POSSIBLE: return glut_window ? glut_window->can_do_overlay() : 0; //case GLUT_LAYER_IN_USE: //case GLUT_HAS_OVERLAY: case GLUT_TRANSPARENT_INDEX: return 0; // true for SGI case GLUT_NORMAL_DAMAGED: return glut_window ? glut_window->damage() : 0; case GLUT_OVERLAY_DAMAGED: return 1; // kind of works... default: return 0; } } int glutDeviceGet(GLenum type) { switch (type) { case GLUT_HAS_KEYBOARD : return 1; case GLUT_HAS_MOUSE : return 1; case GLUT_NUM_MOUSE_BUTTONS : return 3; default : return 0; } } // Get extension function address... GLUTproc glutGetProcAddress(const char *procName) { return (GLUTproc)Fl_Gl_Window_Driver::global()->GetProcAddress(procName); } // Parse the GL_EXTENSIONS string to see if the named extension is // supported. // // This code was copied from FreeGLUT 2.4.0 which carries the // following notice: // // Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. int glutExtensionSupported( const char* extension ) { if (!extension || strchr(extension, ' ')) return 0; const char *extensions, *start; const int len = (int)strlen(extension); start = extensions = (const char *) glGetString(GL_EXTENSIONS); if (!extensions) return 0; for (;;) { const char *p = strstr(extensions, extension); if (!p) return 0; /* not found */ /* check that the match isn't a super string */ if ((p == start || p[-1] == ' ') && (p[len] == ' ' || p[len] == 0)) return 1; /* skip the false match and continue */ extensions = p + len; } } // Add a mechanism to handle adding/removing the glut idle function // without depending on the (deprecated) set_idle method. void glutIdleFunc(void (*f)()) { // no change if(glut_idle_func == f) return; // remove current idle if(glut_idle_func) Fl::remove_idle((void (*)(void *))glut_idle_func); // install new idle func - if one was passed if(f) Fl::add_idle((void (*)(void *))f); // record new idle func - even if it is NULL glut_idle_func = f; } // glutIdleFunc #endif // HAVE_GL fltk-1.4.3/src/Fl_Timeout.h0000644000175000017500000001202215004135251015611 0ustar albrechtalbrecht// // Header for timeout support functions for the Fast Light Tool Kit (FLTK). // // Author: Albrecht Schlosser // Copyright 2021-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _src_Fl_Timeout_h_ #define _src_Fl_Timeout_h_ #include #define FL_TIMEOUT_DEBUG 0 // 1 = include debugging features, 0 = no /** \file Fl_Timeout handling. This file contains implementations of: - Fl::add_timeout() - Fl::repeat_timeout() - Fl::has_timeout() - Fl::remove_timeout() - Fl::remove_next_timeout() and related methods of class Fl_Timeout. */ /** The internal class Fl_Timeout handles all timeout related functions. All code is platform independent except retrieving a timestamp which requires calling a system driver function and potentially results in different timer resolutions (from milliseconds to microseconds). Related user documentation: - \ref Fl_Timeout_Handler - Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *data) - Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data) - Fl::has_timeout(Fl_Timeout_Handler cb, void *data) - Fl::remove_timeout(Fl_Timeout_Handler cb, void *data) - Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return) */ class Fl_Timeout { protected: Fl_Timeout *next; // ** Link to next timeout Fl_Timeout_Handler callback; // the user's callback void *data; // the user's callback data double time; // delay until timeout int skip; // skip "new" (inserted) timers (issue #450) // constructor Fl_Timeout() { next = 0; callback = 0; data = 0; time = 0; skip = 0; } // destructor ~Fl_Timeout() {} // get a new timer entry from the pool or allocate a new one static Fl_Timeout *get(double time, Fl_Timeout_Handler cb, void *data); // insert this timer into the active timer queue, sorted by expiration time void insert(); // remove this timer from the active timer queue and // add it to the "current" timer stack void make_current(); // remove this timer from the current timer stack and // add it to the list of free timers void release(); /** Get the timer's delay in seconds. */ double delay() { return time; } /** Set the timer's delay in seconds. */ void delay(double t) { time = t; } public: // Returns whether the given timeout is active. static int has_timeout(Fl_Timeout_Handler cb, void *data); // Add or remove timeouts static void add_timeout(double time, Fl_Timeout_Handler cb, void *data); static void repeat_timeout(double time, Fl_Timeout_Handler cb, void *data); static void remove_timeout(Fl_Timeout_Handler cb, void *data); static int remove_next_timeout(Fl_Timeout_Handler cb, void *data = NULL, void **data_return = NULL); // Elapse timeouts, i.e. calculate new delay time of all timers. // This does not call the timer callbacks. static void elapse_timeouts(); // Elapse timeouts and call timer callbacks. static void do_timeouts(); // Return the delay in seconds until the next timer expires. static double time_to_wait(double ttw); #if FL_TIMEOUT_DEBUG // Write some statistics to stdout static void debug(int level = 1); #endif protected: static Fl_Timeout *current(); /** List of active timeouts. These timeouts can be triggered when due, which calls their callbacks. The lifetime of a timeout: - active, in this queue - callback running, in queue \p current_timeout - done, in list of free timeouts, ready to be reused. */ static Fl_Timeout *first_timeout; /** List of free timeouts after use. Timeouts can be reused many times. */ static Fl_Timeout *free_timeout; /** The list of current timeouts is used to store the timeout whose callback is called while the callback is executed. This is used like a stack, the current timeout is pushed to the front of the list and once the callback is finished, that timeout is removed and entered into the free list. Background: Fl::repeat_timeout() needs to know which timeout triggered it and the exact schedule time and/or the delay of that timeout, i.e. how long the scheduled time was missed before the callback was called. A static, global variable is not sufficient since the user code can call other functions, e.g. dialogs, that run a nested event loop which can run another timeout callback. Hence this list of "current" timeouts is used like a stack (last in, first out). \see Fl_Timeout::push() Member function (method) */ static Fl_Timeout *current_timeout; // list of "current" timeouts }; // class Fl_Timeout #endif // _src_Fl_Timeout_h_ fltk-1.4.3/src/print_panel.h0000644000175000017500000000221115004135251016054 0ustar albrechtalbrecht// // Print panel for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // This is a temporary file. It is only for development and will // probably be removed later. // #ifndef print_panel_h #define print_panel_h #include #include #include #include #include #include #include #include #include #include #include #include enum printing_style {SystemV, BSD}; static Fl_Double_Window* make_print_panel(); static void print_cb(Fl_Return_Button *, void *); static printing_style print_load(); static void print_update_status(); #endif fltk-1.4.3/src/fl_ask.cxx0000644000175000017500000005645615004135251015377 0ustar albrechtalbrecht// // Standard dialog functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \addtogroup group_comdlg @{ */ /** \file fl_ask.cxx \brief Utility functions for common dialogs. This file defines the functions - fl_alert() - fl_beep() - fl_message() - fl_ask() - fl_choice() - fl_input() - fl_input_str() - fl_password() - fl_password_str() and some more functions to change their behavior (positioning, window title, and more). Since FLTK 1.4.0 a big part of these functions is implemented in class Fl_Message. */ #include #include #include #include "flstring.h" #include "Fl_Screen_Driver.H" #include #include "Fl_Message.h" // intentionally "hidden" in src/... #include #include // static, configurable variables Fl_Font fl_message_font_ = FL_HELVETICA; Fl_Fontsize fl_message_size_ = -1; // pointers you can use to change FLTK to another language: const char *fl_no = "No"; ///< string pointer used in common dialogs, you can change it to another language const char *fl_yes = "Yes"; ///< string pointer used in common dialogs, you can change it to another language const char *fl_ok = "OK"; ///< string pointer used in common dialogs, you can change it to another language const char *fl_cancel = "Cancel"; ///< string pointer used in common dialogs, you can change it to another language const char *fl_close = "Close"; ///< string pointer used in common dialogs, you can change it to another language // fltk functions: /** Emits a system beep. This function is platform specific. Depending on the input \p type a different sound may be played or the system speaker may beep with a different volume. On X the system speaker is used which may not work at all on newer systems that don't have a speaker. Since 1.4.0 \c FL_BEEP_DEFAULT and other types honor the system or user settings whereas \c FL_BEEP_ERROR uses 100% volume. This may be changed in a future version. On Wayland an ASCII \p BEL (0x07) is output to stderr. On Windows the \c MessageBeep() function is used to play different sounds depending on the \p type argument. On macOS the system beep function \c NSBeep() is used for \c FL_BEEP_DEFAULT and \c FL_BEEP_ERROR. Other types are ignored. On other platforms the behavior is undefined and may change in the future. \param[in] type The beep type from the \ref Fl_Beep enumeration (optional) \code #include \endcode */ void fl_beep(int type) { Fl::screen_driver()->beep(type); } /** Shows an information message dialog box. \code #include \endcode \param[in] fmt can be used as an sprintf-like format and variables for the message text */ void fl_message(const char *fmt, ...) { Fl_Message msg("i"); va_list ap; va_start(ap, fmt); msg.innards(fmt, ap, 0, fl_close, 0); va_end(ap); } /** Shows an alert message dialog box. \code #include \endcode \param[in] fmt can be used as an sprintf-like format and variables for the message text */ void fl_alert(const char *fmt, ...) { Fl_Message msg("!"); va_list ap; va_start(ap, fmt); msg.innards(fmt, ap, 0, fl_close, 0); va_end(ap); } /** Shows a dialog displaying the \p fmt message, this dialog features 2 yes/no buttons. \code #include \endcode \param[in] fmt can be used as an sprintf-like format and variables for the message text \retval 0 if the no button is selected \retval 1 if yes is selected \deprecated fl_ask() is deprecated since it uses "Yes" and "No" for the buttons which does not conform to the current FLTK Human Interface Guidelines. Use fl_choice() with the appropriate verbs instead. */ int fl_ask(const char *fmt, ...) { Fl_Message msg("?"); va_list ap; va_start(ap, fmt); int r = msg.innards(fmt, ap, fl_no, fl_yes, 0); va_end(ap); return r; } /** Shows a dialog displaying the printf style \p fmt message. This dialog features up to 3 customizable choice buttons which are specified in order of *right-to-left* in the dialog, e.g. \image html fl_choice_left_middle_right.png \image latex fl_choice_left_middle_right.png "fl_choice() button ordering" width=4cm \code #include \endcode Three choices with printf() style formatting: \image html fl_choice_three_fmt.png \image latex fl_choice_three_fmt.png "fl_choice() three choices with printf formatting" width=4cm \code int num_msgs = GetNumberOfMessages(); switch ( fl_choice("What to do with %d messages?", "Send", "Save", "Delete", num_msgs) ) { case 0: .. // Send case 1: .. // Save (default) case 2: .. // Delete .. } \endcode Three choice example: \image html fl_choice_three.png \image latex fl_choice_three.png "fl_choice() three choices" width=4cm \code switch ( fl_choice("How many bedrooms?", "Zero", "One", "Two") ) { case 0: .. // "Zero" case 1: .. // "One" (default) case 2: .. // "Two" } \endcode Two choice example: \image html fl_choice_two.png \image latex fl_choice_two.png "fl_choice() two choices" width=4cm \code switch ( fl_choice("Empty trash?", "Yes", "No", 0) ) { case 0: .. // Yes case 1: .. // No (default) } \endcode One choice example: \image html fl_choice_one.png \image latex fl_choice_one.png "fl_choice() one choice" width=4cm \code fl_choice("All hope is lost.", "OK", 0, 0); // "OK" default \endcode \param[in] fmt can be used as an sprintf-like format and variables for the message text \param[in] b0 text label for right button 0 \param[in] b1 text label for middle button 1 (can be 0) \param[in] b2 text label for left button 2 (can be 0) \retval 0 if the button with \p b0 text is pushed or the user pressed the \c Escape key or clicked the window close button \retval 1 if the button with \p b1 text is pushed or the user pressed the \c Return key \retval 2 if the button with \p b2 text is pushed */ int fl_choice(const char *fmt, const char *b0, const char *b1, const char *b2, ...) { Fl_Message msg("?"); va_list ap; va_start(ap, b2); int r = msg.innards(fmt, ap, b0, b1, b2); va_end(ap); return r; } /** Shows a dialog displaying the printf style \p fmt message. This function is like fl_choice() but returns \c -1 if the dialog window was closed by pressing the \c Escape key or the window close button rather than pushing one of the dialog buttons. \see fl_choice() \param[in] fmt can be used as an sprintf-like format and variables for the message text \param[in] b0 text label for right button 0 \param[in] b1 text label for middle button 1 (can be 0) \param[in] b2 text label for left button 2 (can be 0) \retval -3 reserved, FLTK 1.3 only: another dialog is still open (not possible in 1.4) \retval -2 if the dialog was closed by pushing the window close button \retval -1 if the dialog was closed by hitting Escape \retval 0 if the button with \p b0 text is pushed \retval 1 if the button with \p b1 text is pushed \retval 2 if the button with \p b2 text is pushed */ int fl_choice_n(const char *fmt, const char *b0, const char *b1, const char *b2, ...) { Fl_Message msg("?"); va_list ap; va_start(ap, b2); int r = msg.innards(fmt, ap, b0, b1, b2); va_end(ap); if (msg.window_closed() != 0) return msg.window_closed(); return r; } /** Gets the Fl_Box icon container of the current default dialog used in many common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), fl_password(). The return value cannot be Null. The object pointed to is an Fl_Box widget. The returned pointer (Fl_Widget *) can be safely cast to an Fl_Box* pointer. \note You can set some attributes of this \b default icon box. These attributes are sticky, i.e. they will be used in all subsequent common dialogs unless overridden by specific "one shot" variables. Setting any attribute except those mentioned below causes undefined behavior. Supported icon attributes: - box() - labelfont() - labelsize() - color() - labelcolor() - image() - align() The icon size can not be changed. If you set an image() you should scale it to the available size, i.e. \p w() and \p h() of the icon box. \code #include \endcode */ Fl_Widget *fl_message_icon() { return Fl_Message::message_icon(); } /** Shows an input dialog displaying the \p fmt message with variable arguments. Returns the string in an internally allocated buffer that may be changed later. You \b must copy the string immediately after return from this method - at least before the next execution of the event loop. \code #include \endcode \param[in] fmt can be used as an sprintf-like format and variables for the message text \param[in] defstr defines the default returned string if no text is entered \return the user string input if OK was pushed \retval NULL if Cancel was pushed or the window was closed by the user */ const char *fl_input(const char *fmt, const char *defstr, ...) { Fl_Message msg("?"); va_list ap; va_start(ap, defstr); const char *r = msg.input_innards(fmt, ap, defstr, FL_NORMAL_INPUT, 0, false); va_end(ap); return r; } /** Shows an input dialog displaying the \p fmt message with variable arguments. This is the same as const char *fl_input(const char *fmt, const char *defstr, ...) except that it has an additional parameter to limit the number of characters the user can input. Returns the string in an internally allocated buffer that may be changed later. You \b must copy the string immediately after return from this method - at least before the next execution of the event loop. \code #include \endcode \param[in] maxchar maximum number of characters the user can input (UTF-8 aware) \param[in] fmt can be used as an sprintf-like format and variables for the message text \param[in] defstr defines the default returned string if no text is entered \return the user string input if OK was pushed \retval NULL if Cancel was pushed or the window was closed by the user */ const char *fl_input(int maxchar, const char *fmt, const char *defstr, ...) { Fl_Message msg("?"); if (maxchar < 0) maxchar = 0; va_list ap; va_start(ap, defstr); const char *r = msg.input_innards(fmt, ap, defstr, FL_NORMAL_INPUT, maxchar, false); va_end(ap); return r; } #if (FLTK_USE_STD) /** Shows an input dialog displaying the \p fmt message with variable arguments. Like fl_input(), but this method has the additional argument \p maxchar that limits the number of \b characters that can be input. Since the string is encoded in UTF-8 it is possible that the number of bytes in the string is larger than \p maxchar. Other than the deprecated fl_input() method w/o the \p maxchar argument, this one returns the string in an std::string object that must be released after use. This can be a local/automatic variable. The \p ret variable is set to 0 if the user clicked OK, and to a negative value if the user canceled the dialog. If the dialog was canceled, the returned string will be empty. \code #include \endcode Example: \code { int ret; std::string str = fl_input_str(ret, 0, "Enter text:", ""); if (ret < 0) printf("Text input was canceled.\n"); else printf("Text is: '%s'\n", str.c_str()); } // (str goes out of scope) \endcode \param[out] ret 0 if user clicked OK, negative if dialog was canceled \param[in] maxchar input size limit in characters (not bytes), use 0 for no limit \param[in] fmt can be used as an sprintf-like format and variables for the message text \param[in] defstr defines the default returned string if no text is entered \return the user string input if OK was clicked which can be empty \return an empty string and set \p ret to a negative value if the user canceled the dialog \since 1.4.0 */ std::string fl_input_str(int &ret, int maxchar, const char *fmt, const char *defstr, ...) { Fl_Message msg("?"); if (maxchar < 0) maxchar = 0; va_list ap; va_start(ap, defstr); const char *r = msg.input_innards(fmt, ap, defstr, FL_NORMAL_INPUT, maxchar, true); va_end(ap); ret = (r == NULL) ? -1 : 0; return (r == NULL) ? std::string("") : std::string(r); } /** Shows an input dialog displaying the \p fmt message with variable arguments. \note No information is given if the user canceled the dialog or clicked OK. \see fl_input_str(int &ret, int maxchar, const char *label, const char *deflt = 0, ...) */ std::string fl_input_str(int maxchar, const char *fmt, const char *defstr, ...) { Fl_Message msg("?"); if (maxchar < 0) maxchar = 0; va_list ap; va_start(ap, defstr); const char *r = msg.input_innards(fmt, ap, defstr, FL_NORMAL_INPUT, maxchar, true); va_end(ap); return (r == NULL) ? std::string("") : std::string(r); } #endif // FLTK_USE_STD /** Shows an input dialog displaying the \p fmt message with variable arguments. Like fl_input() except the input text is not shown, '*' or similar replacement characters are displayed instead. \code #include \endcode \param[in] fmt can be used as an sprintf-like format and variables for the message text \param[in] defstr defines the default returned string if no text is entered \return the user string input if OK was pushed \retval NULL if Cancel was pushed or the window was closed by the user */ const char *fl_password(const char *fmt, const char *defstr, ...) { Fl_Message msg("?"); va_list ap; va_start(ap, defstr); const char *r = msg.input_innards(fmt, ap, defstr, FL_SECRET_INPUT, 0, false); va_end(ap); return r; } /** Shows an input dialog displaying the \p fmt message with variable arguments. Like fl_input() except the input text is not shown, '*' or similar replacement characters are displayed instead. \code #include \endcode \param[in] maxchar input lenght limit in chars, 0 = no limit \param[in] fmt can be used as an sprintf-like format and variables for the message text \param[in] defstr defines the default returned string if no text is entered \return the user string input if OK was pushed \retval NULL if Cancel was pushed or the window was closed by the user */ const char *fl_password(int maxchar, const char *fmt, const char *defstr, ...) { Fl_Message msg("?"); if (maxchar < 0) maxchar = 0; va_list ap; va_start(ap, defstr); const char *r = msg.input_innards(fmt, ap, defstr, FL_SECRET_INPUT, maxchar, false); va_end(ap); return r; } #if (FLTK_USE_STD) /** Shows an input dialog displaying the \p fmt message with variable arguments. Like fl_input_str() except the input text is not shown, '*' or similar replacement characters are displayed instead. Other than the fl_password() method w/o the \p maxchar argument, this one returns the string in an std::string object that must be released after use. This can be a local/automatic variable. For an example see fl_input_str() \code #include \endcode \param[out] ret 0 if user clicked OK, negative if dialog was canceled \param[in] maxchar input size limit in characters (not bytes), use 0 for no limit \param[in] fmt can be used as an sprintf-like format and variables for the message text \param[in] defstr defines the default returned string if no text is entered \return the user string input if OK was clicked which can be empty \return an empty string and set \p ret to a negative value if the user canceled the dialog \since 1.4.0 */ std::string fl_password_str(int &ret, int maxchar, const char *fmt, const char *defstr, ...) { Fl_Message msg("?"); if (maxchar < 0) maxchar = 0; va_list ap; va_start(ap, defstr); const char *r = msg.input_innards(fmt, ap, defstr, FL_SECRET_INPUT, maxchar, true); va_end(ap); ret = (r == NULL) ? -1 : 0; return (r == NULL) ? std::string("") : std::string(r); } /** Shows an input dialog displaying the \p fmt message with variable arguments. \note No information is given if the user canceled the dialog or clicked OK. \see fl_password_str(int &ret, int maxchar, const char *label, const char *deflt = 0, ...) */ std::string fl_password_str(int maxchar, const char *fmt, const char *defstr, ...) { Fl_Message msg("?"); if (maxchar < 0) maxchar = 0; va_list ap; va_start(ap, defstr); const char *r = msg.input_innards(fmt, ap, defstr, FL_SECRET_INPUT, maxchar, true); va_end(ap); return (r == NULL) ? std::string("") : std::string(r); } #endif // FLTK_USE_STD /** Sets the preferred position for the message box used in many common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), fl_password(). The position set with this method overrides the hotspot setting, i.e. setting a position has higher priority than the hotspot mode set by fl_message_hotspot(int). The preferred position set by any of the fl_message_position() variants affects only the next call of one of the common dialogs. The preferred position is reset to 0 (unset) as soon as the dialog is shown. If the optional argument \p center is non-zero (true) the message box will be centered at the given coordinates rather than using the X/Y position as the window position (top left corner). \code #include \endcode \param[in] x Preferred X position \param[in] y Preferred Y position \param[in] center 1 = centered, 0 = absolute \see int fl_message_position(int *x, int *y) */ void fl_message_position(const int x, const int y, const int center) { Fl_Message::message_position(x, y, center); } /** Sets the preferred position for the message box used in many common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), fl_password(). The message box will be centered over the given widget or window extensions. Everything else is like fl_message_position(int, int, int) with argument 'center' set to 1. \code #include \endcode \param[in] widget Widget or window to position the message box over. \see int fl_message_position(int x, int y, int center) */ void fl_message_position(Fl_Widget *widget) { Fl_Message::message_position(widget); } /** Gets the preferred position for the message box used in many common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), fl_password(). \code #include \endcode The position set with this method overrides the hotspot setting, i.e. setting a position has higher priority than the hotspot mode set by fl_message_hotspot(int). The preferred position set by any of the fl_message_position() variants affects only the next call of one of the common dialogs. The preferred position is reset to 0 (unset) as soon as the dialog is shown. \param[out] x Preferred X position, returns -1 if not set \param[out] y Preferred Y position, returns -1 if not set \returns whether position is currently set or not \retval 0 position is not set (hotspot may be enabled or not) \retval 1 position is set (window position) \retval 2 position is set (message box centered) \see fl_message_hotspot() \see fl_message_hotspot(int) \see fl_message_position(int, int) \see fl_message_position(const int x, const int y, const int center) \see fl_message_position(Fl_Widget *) */ int fl_message_position(int *x, int *y) { return Fl_Message::message_position(x, y); } /** Sets whether or not to move the message box used in many common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), fl_password() to follow the mouse pointer. The default is \e enabled, so that the default button is the hotspot and appears at the mouse position. \code #include \endcode \param[in] enable non-zero enables hotspot behavior, 0 disables hotspot */ void fl_message_hotspot(int enable) { Fl_Message::message_hotspot(enable); } /** Gets whether or not to move the message box used in many common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), fl_password() to follow the mouse pointer. This is a permanent setting. It remains active and affects the window position unless overridden by an explicit positioning request by means of one of the fl_message_position() variants. \code #include \endcode \return 0 if disabled, non-zero otherwise \see void fl_message_hotspot(int) \see int fl_message_position(int *x, int *y) \see void fl_message_position(Fl_Widget *) \see fl_message_position() */ int fl_message_hotspot() { return Fl_Message::message_hotspot(); } /** Sets the title of the dialog window used in many common dialogs. This window \p title will be used in the next call of one of the common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), fl_password(). The \p title string is copied internally, so that you can use a local variable or free the string immediately after this call. It applies only to the \b next call of one of the common dialogs and will be reset to an empty title (the default for all dialogs) after that call. \code #include \endcode \param[in] title window label, string copied internally */ void fl_message_title(const char *title) { Fl_Message::message_title(title); } /** Sets the default title of the dialog window used in many common dialogs. This window \p title will be used in all subsequent calls of one of the common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), fl_password(), unless a specific title has been set with fl_message_title(const char *title). The default is no title. You can override the default title for a single dialog with fl_message_title(const char *title). The \p title string is copied internally, so that you can use a local variable or free the string immediately after this call. \code #include \endcode \param[in] title default window label, string copied internally */ void fl_message_title_default(const char *title) { Fl_Message::message_title_default(title); } /** Sets the icon label of the dialog window used in many common dialogs. This icon label will be used in the next call of one of the common dialogs like fl_message(), fl_alert(), fl_ask(), fl_choice(), fl_input(), fl_password(). The label \p str is stored internally as a reference, it must be in scope until the dialog function (e.g. fl_choice) is called. It applies only to the \b next call of one of the common dialogs and will be reset after that call so the next dialog will use its default label unless set again. \note This label string must be short, usually only one character so it fits in the icon box. You can use any valid UTF-8 character, e.g. the Euro sign ("€") which is three bytes in UTF-8 encoding. \code #include \endcode \param[in] str icon label */ void fl_message_icon_label(const char *str) { Fl_Message::icon_label(str); } /** @} */ fltk-1.4.3/src/flstring.h0000644000175000017500000000554015004135251015401 0ustar albrechtalbrecht/* * Common string header file for the Fast Light Tool Kit (FLTK). * Internal use only (see "important note" below). * * Copyright 1998-2020 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * Important note: this header file includes '' ! * * This header MUST NOT be included in public headers (i.e. in 'FL/') and * SHOULD NOT be included in test and demo programs (i.e. in 'test/' or * 'examples/') because it includes ''. */ #ifndef flstring_h # define flstring_h # include # include # include # include # include # ifdef HAVE_STRINGS_H # include # endif /* HAVE_STRINGS_H */ # include # include /* * Apparently Unixware defines "index" to strchr (!) rather than * providing a proper entry point or not providing the (obsolete) * BSD function. Make sure index is not defined... */ # ifdef index # undef index # endif /* index */ /* * Visual C++ 2005 incorrectly displays a warning about the use of * POSIX APIs on Windows, which is supposed to be POSIX compliant... * Some of these functions are also defined in ISO C99... */ # if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__) # define strcasecmp(s,t) _stricmp((s), (t)) # define strncasecmp(s,t,n) _strnicmp((s), (t), (n)) # endif /* _WIN32 && ... */ # ifdef __cplusplus extern "C" { # endif /* __cplusplus */ FL_EXPORT extern int fl_snprintf(char *, size_t, const char *, ...); # ifndef HAVE_SNPRINTF # define snprintf fl_snprintf # endif /* !HAVE_SNPRINTF */ FL_EXPORT extern int fl_vsnprintf(char *, size_t, const char *, va_list ap); # ifndef HAVE_VSNPRINTF # define vsnprintf fl_vsnprintf # endif /* !HAVE_VSNPRINTF */ /* * strlcpy() and strlcat() are some really useful BSD string functions * that work the way strncpy() and strncat() *should* have worked. */ FL_EXPORT extern size_t fl_strlcat(char *, const char *, size_t); # ifndef HAVE_STRLCAT # define strlcat fl_strlcat # endif /* !HAVE_STRLCAT */ /* promoted to */ /* FL_EXPORT extern size_t fl_strlcpy(char *, const char *, size_t); */ # ifndef HAVE_STRLCPY # define strlcpy fl_strlcpy # endif /* !HAVE_STRLCPY */ /* * Locale independent ASCII string compare function, * does not introduce locale issues as with strcasecmp() */ FL_EXPORT extern int fl_ascii_strcasecmp(const char *s, const char *t); # ifdef __cplusplus } # endif /* __cplusplus */ #endif /* !flstring_h */ fltk-1.4.3/src/fl_set_font.cxx0000644000175000017500000000551615004135251016431 0ustar albrechtalbrecht// // Font utilities for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Add a font to the internal table. // Also see fl_set_fonts.cxx which adds all possible fonts. #include #include #include #include "Fl_Screen_Driver.H" #include "flstring.h" #include struct Fl_Fontdesc; extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table static int table_size; /** Changes a face. \param fnum The font number to be assigned a new face \param name Name of the font to assign. The string pointer is simply stored, the string is not copied, so the string must be in static memory. The exact name to be used depends on the platform : \li Windows, X11, Xft: use the family name prefixed by one character to indicate the desired font variant. Characters ' ', 'I', 'B', 'P' denote plain, italic, bold, and bold-italic variants, respectively. For example, string \c "IGabriola" is to be used to denote the "Gabriola italic" font. The \c "Oblique" suffix, in whatever case, is to be treated as \c "italic", that is, prefix the family name with \c 'I'. \li Other platforms, i.e., X11 + Pango, Wayland, macOS: use the full font name as returned by function Fl::get_font_name() or as listed by applications test/fonts or test/utf8. No prefix is to be added. */ void Fl::set_font(Fl_Font fnum, const char* name) { Fl_Graphics_Driver &d = Fl_Graphics_Driver::default_driver(); unsigned width = d.font_desc_size(); if (!fl_fonts) fl_fonts = d.calc_fl_fonts(); while (fnum >= table_size) { int i = table_size; if (!i) { // don't realloc the built-in table table_size = 2*FL_FREE_FONT; i = FL_FREE_FONT; Fl_Fontdesc* t = (Fl_Fontdesc*)malloc(table_size*width); memcpy(t, fl_fonts, FL_FREE_FONT*width); fl_fonts = t; } else { table_size = 2*table_size; fl_fonts=(Fl_Fontdesc*)realloc(fl_fonts, table_size*width); } for (; i < table_size; i++) { memset((char*)fl_fonts + i * width, 0, width); } } d.font_name(fnum, name); d.font(-1, 0); } /** Copies one face to another. */ void Fl::set_font(Fl_Font fnum, Fl_Font from) { Fl::set_font(fnum, get_font(from)); } /** Gets the string for this face. This string is different for each face. Under X this value is passed to XListFonts to get all the sizes of this face. */ const char* Fl::get_font(Fl_Font fnum) { return Fl_Graphics_Driver::default_driver().font_name(fnum); } fltk-1.4.3/src/fastarrow.h0000644000175000017500000000046115004135251015556 0ustar albrechtalbrecht#define fastarrow_width 16 #define fastarrow_height 16 static const unsigned char fastarrow_bits[] = { 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xfc, 0x03, 0xff, 0xff, 0xfc, 0x03, 0xe0, 0x07, 0x00, 0x07, 0xe0, 0x00, 0xe0, 0x07, 0xc0, 0x3f, 0xff, 0xff, 0xc0, 0x3f, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00}; fltk-1.4.3/src/Fl_Native_File_Chooser_Kdialog.cxx0000644000175000017500000002275715004135251022057 0ustar albrechtalbrecht// // FLTK native file chooser widget : KDE version // // Copyright 2021-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include #include #include "Fl_Native_File_Chooser_Kdialog.H" #include "Fl_Window_Driver.H" #include "Fl_System_Driver.H" #include "drivers/Unix/Fl_Unix_Screen_Driver.H" #include #include #include #include /* Fl_Kdialog_Native_File_Chooser_Driver : file chooser based on the "kdialog" command */ bool Fl_Kdialog_Native_File_Chooser_Driver::did_find_kdialog = false; bool Fl_Kdialog_Native_File_Chooser_Driver::have_looked_for_kdialog = false; Fl_Kdialog_Native_File_Chooser_Driver::Fl_Kdialog_Native_File_Chooser_Driver(int val) : Fl_Native_File_Chooser_FLTK_Driver(val) { _tpathnames = 0; _pathnames = NULL; _directory = NULL; _preset_file = NULL; _title = NULL; } Fl_Kdialog_Native_File_Chooser_Driver::~Fl_Kdialog_Native_File_Chooser_Driver() { for (int i = 0; i < _tpathnames; i++) delete[] _pathnames[i]; delete[] _pathnames; if (_preset_file) free(_preset_file); if (_directory) free(_directory); if (_title) free(_title); } void Fl_Kdialog_Native_File_Chooser_Driver::fnfc_fd_cb(int fd, Fl_Kdialog_Native_File_Chooser_Driver::fnfc_pipe_struct *data) { char tmp[FL_PATH_MAX]; int l = read(fd, tmp, sizeof(tmp)-1); if (l > 0) { tmp[l] = 0; data->all_files = Fl_Native_File_Chooser_Driver::strapp(data->all_files, tmp); } else { data->fd = -1; } } static int fnfc_dispatch(int /*event*/, Fl_Window* /*win*/) { return 0; } void Fl_Kdialog_Native_File_Chooser_Driver::build_command(Fl_String& command) { const char *option; switch (_btype) { case Fl_Native_File_Chooser::BROWSE_DIRECTORY: option = "--getexistingdirectory"; break; case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: option = "--getsavefilename"; break; case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: option = "--multiple --getopenfilename --separate-output"; break; default: option = "--getopenfilename"; } // Build preset char preset[FL_PATH_MAX] = ""; if (_preset_file) { if (_directory) strcpy(preset, _directory); else Fl::system_driver()->getcwd(preset, FL_PATH_MAX); strcat(preset, "/"); strcat(preset, _preset_file); } // Build command command = "kdialog"; if (_title) { Fl_String quoted_title = _title; shell_quote(quoted_title); command += " --title "; command += quoted_title; } command += " "; command += option; command += " "; command += preset; if (_parsedfilt) { Fl_String quoted_filt = _parsedfilt; shell_quote(quoted_filt); // NOTE: orig code used double quoting -erco 1/10/24 command += " "; command += quoted_filt; } command += " 2> /dev/null"; // get rid of stderr // printf("command = %s\n", command.c_str()); } int Fl_Kdialog_Native_File_Chooser_Driver::show() { if (_btype == Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY) { // BROWSE_MULTI_DIRECTORY is not supported by kdialog, run GTK chooser instead Fl_Native_File_Chooser fnfc(Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY); fnfc.title( title() ); fnfc.directory(directory()); fnfc.preset_file(preset_file()); fnfc.filter(filter()); fnfc.options(options()); int retval = fnfc.show(); for (int i = 0; i < _tpathnames; i++) delete[] _pathnames[i]; delete[] _pathnames; _pathnames = NULL; _tpathnames = fnfc.count(); if (_tpathnames && retval == 0) { _pathnames = new char*[_tpathnames]; for (int i = 0; i < _tpathnames; i++) { _pathnames[i] = new char[strlen(fnfc.filename(i))+1]; strcpy(_pathnames[i], fnfc.filename(i)); } } return retval; } Fl_String command; build_command(command); //fprintf(stderr, "DEBUG: POPEN: %s\n", command.c_str()); FILE *pipe = popen(command.c_str(), "r"); fnfc_pipe_struct data; data.all_files = NULL; if (pipe) { data.fd = fileno(pipe); Fl::add_fd(data.fd, FL_READ, (Fl_FD_Handler)fnfc_fd_cb, &data); Fl_Event_Dispatch old_dispatch = Fl::event_dispatch(); // prevent FLTK from processing any event Fl::event_dispatch(fnfc_dispatch); void *control = ((Fl_Unix_Screen_Driver*)Fl::screen_driver())->control_maximize_button(NULL); // run event loop until pipe finishes while (data.fd >= 0) Fl::wait(); Fl::remove_fd(fileno(pipe)); pclose(pipe); // return to previous event processing by FLTK Fl::event_dispatch(old_dispatch); if (control) ((Fl_Unix_Screen_Driver*)Fl::screen_driver())->control_maximize_button(control); if (data.all_files) { // process text received from pipe if (data.all_files[strlen(data.all_files)-1] == '\n') data.all_files[strlen(data.all_files)-1] = 0; for (int i = 0; i < _tpathnames; i++) delete[] _pathnames[i]; delete[] _pathnames; char *p = data.all_files; int count = 1; while ((p = strchr(p+1, '\n'))) count++; _pathnames = new char*[count]; _tpathnames = 0; char *q = strtok(data.all_files, "\n"); while (q) { _pathnames[_tpathnames] = new char[strlen(q)+1]; strcpy(_pathnames[_tpathnames], q); _tpathnames++; q = strtok(NULL, "\n"); } } } if (!pipe) return -1; return (data.all_files == NULL ? 1 : 0); } const char *Fl_Kdialog_Native_File_Chooser_Driver::filename() const { return _tpathnames >= 1 ? _pathnames[0] : NULL; } const char *Fl_Kdialog_Native_File_Chooser_Driver::filename (int i) const { return _tpathnames > i ? _pathnames[i] : NULL; } const char *Fl_Kdialog_Native_File_Chooser_Driver::filter() const { return _filter; } int Fl_Kdialog_Native_File_Chooser_Driver::filters() const { return (_nfilters ? _nfilters - 1 : 0); } int Fl_Kdialog_Native_File_Chooser_Driver::count() const { return _tpathnames; } char *Fl_Kdialog_Native_File_Chooser_Driver::parse_filter(const char *f) { //In: "*.H\n" or "*.H" Out: "(*.H)" //In: "Headers\t*.H\n" Out: "Headers (*.H)" //In: "Headers\t*.{H,h}\n" Out: "Headers (*.H *.h)" const char *p = strchr(f, '\t'); if (!p) p = f - 1; const char *q = strchr(f, '\n'); if (!q) q = f + strlen(f); const char *r = strchr(f, '{'); char *developed = NULL; if (r) { // with {} if (r <= p) return NULL; char *lead = new char[r-p]; memcpy(lead, p+1, (r-p)-1); lead[(r-p)-1] = 0; const char *r2 = strchr(r, '}'); if (!r2 || r2 == r + 1) return NULL; char *ends = new char[r2-r]; memcpy(ends, r+1, (r2-r)-1); ends[(r2-r)-1] = 0; char *ptr; char *part = strtok_r(ends, ",", &ptr); while (part) { developed = strapp(developed, lead); developed = strapp(developed, part); developed = strapp(developed, " "); part = strtok_r(NULL, ",", &ptr); } if (developed[strlen(developed)-1] == ' ') developed[strlen(developed)-1] = 0; delete[] lead; delete[] ends; } int lout = (p>f?p-f:0) + 2 + (r?strlen(developed):((q-p)-1)) + 2; char *out = new char[lout]; *out = 0; if (p > f) {memcpy(out, f, p-f); out[p-f] = 0; } strcat(out, " ("); if (r) { strcpy(out+strlen(out), developed); strfree(developed); } else memcpy(out+strlen(out), p+1, (q-p)); strcat(out, ")"); //puts(out); return out; } void Fl_Kdialog_Native_File_Chooser_Driver::filter(const char *f) { _parsedfilt = strfree(_parsedfilt); // clear previous parsed filter (if any) _nfilters = 0; if (!f) return; _filter = new char[strlen(f) + 1]; strcpy(_filter, f); char *f2 = strdup(f); char *ptr; char *part = strtok_r(f2, "\n", &ptr); while (part) { char *p = parse_filter(part); if (p) { _parsedfilt = strapp(_parsedfilt, p); _parsedfilt = strapp(_parsedfilt, "\n"); delete[] p; _nfilters++; } part = strtok_r(NULL, "\n", &ptr); } free(f2); _parsedfilt = strapp(_parsedfilt, "All files (*)"); _nfilters++; //puts(_parsedfilt); } void Fl_Kdialog_Native_File_Chooser_Driver::preset_file(const char *val) { if (_preset_file) free(_preset_file); _preset_file = strdup(val); } const char *Fl_Kdialog_Native_File_Chooser_Driver::preset_file() const { return _preset_file; } void Fl_Kdialog_Native_File_Chooser_Driver::directory(const char *val) { if (_directory) free(_directory); _directory = strdup(val); } const char *Fl_Kdialog_Native_File_Chooser_Driver::directory() const { return _directory; } void Fl_Kdialog_Native_File_Chooser_Driver::title(const char *val) { if (_title) free(_title); _title = strdup(val); } const char *Fl_Kdialog_Native_File_Chooser_Driver::title() const { return _title; } // Add shell quotes around string 's'. // Handles quoting embedded quotes. // void Fl_Kdialog_Native_File_Chooser_Driver::shell_quote(Fl_String& s) { Fl_String out = "'"; // leading quote for (int t=0; t #include #include #include /** The constructors create a new tiled image containing the specified image. Use a width and height of 0 to tile the whole window/widget. \note Due to implementation constraints in FLTK 1.3.3 and later width and height of 0 may not work as expected when used as background image in widgets other than windows. You may need to center and clip the image (label) and set the label type to FL_NORMAL_LABEL. Doing so will let the tiled image fill the whole widget as its background image. Other combinations of label flags may or may not work. \code #include "bg.xpm" Fl_Pixmap *bg_xpm = new Fl_Pixmap(bg_xpm); Fl_Tiled_Image *bg_tiled = new Fl_Tiled_Image(bg_xpm,0,0); Fl_Box *box = new Fl_Box(40,40,300,100,""); box->box(FL_UP_BOX); box->labeltype(FL_NORMAL_LABEL); box->align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_CLIP); box->image(bg_tiled); \endcode \note Setting an image (label) for a window may not work as expected due to implementation constraints in FLTK 1.3.x and maybe later. The reason is the way Fl::scheme() initializes the window's label type and image. A possible workaround is to use another Fl_Group as the only child widget and to set the background image for this group as described above. \todo Fix Fl_Tiled_Image as background image for widgets and windows and fix the implementation of Fl::scheme(const char *). */ Fl_Tiled_Image::Fl_Tiled_Image(Fl_Image *i, // I - Image to tile int W, // I - Width of tiled area int H) : // I - Height of tiled area Fl_Image(W,H,0) { image_ = i; alloc_image_ = 0; // giving to the tiled image the screen size may fail with multiscreen // configurations, so we leave it with w = h = 0 (STR #3106) // if (W == 0) w(Fl::w()); // if (H == 0) h(Fl::h()); } /** The destructor frees all memory and server resources that are used by the tiled image. */ Fl_Tiled_Image::~Fl_Tiled_Image() { if (alloc_image_) delete image_; } // // 'Fl_Tiled_Image::copy()' - Copy and resize a tiled image... // Fl_Image * // O - New image Fl_Tiled_Image::copy(int W, // I - New width int H) const { // I - New height return new Fl_Tiled_Image(image_, W, H); } // // 'Fl_Tiled_Image::color_average()' - Blend colors... // void Fl_Tiled_Image::color_average(Fl_Color c, // I - Color to blend with float i) { // I - Blend fraction if (!alloc_image_) { int W = image_->w(), H = image_->h(); image_ = image_->copy(image_->data_w(), image_->data_h()); image_->scale(W, H, 0, 1); alloc_image_ = 1; } image_->color_average(c, i); } // // 'Fl_Tiled_Image::desaturate()' - Convert the image to grayscale... // void Fl_Tiled_Image::desaturate() { if (!alloc_image_) { int W = image_->w(), H = image_->h(); image_ = image_->copy(image_->data_w(), image_->data_h()); image_->scale(W, H, 0, 1); alloc_image_ = 1; } image_->desaturate(); } // // 'Fl_Tiled_Image::draw()' - Draw a tiled image. // /** Draws a tiled image. Tiled images can be used as background images for widgets and windows. However, due to implementation constraints, you must take care when setting label types and alignment flags. Only certain combinations work as expected, others may yield unexpected results and undefined behavior. This draw method can draw multiple copies of one image in an area given by \p X, \p Y, \p W, \p H. The optional arguments \p cx and \p cy can be used to crop the image starting at offsets (cx, cy). \p cx and \p cy must be \>= 0 (negative values are ignored). If one of the values is greater than the image width or height resp. (\p cx \>= image()->w() or \p cy \>= image()->h()) nothing is drawn, because the resulting image would be empty. After calculating the resulting image size the image is drawn as often as necessary to fill the given area, starting at the top left corner. If both \p W and \p H are 0 the image is repeated as often as necessary to fill the entire window, unless there is a valid clip region. If you want to fill only one particular widget's background, then you should either set a clip region in your draw() method or use the label alignment flags \p FL_ALIGN_INSIDE|FL_ALIGN_CLIP to make sure the image is clipped. This may be improved in a later version of the library. */ void Fl_Tiled_Image::draw(int X, // I - Starting X position int Y, // I - Starting Y position int W, // I - Width of area to be filled int H, // I - Height of area to be filled int cx, // I - "Source" X position int cy) { // I - "Source" Y position int iw = image_->w(); // effective image width int ih = image_->h(); // effective image height if (!iw || !ih) return; if (cx >= iw || cy >= ih) return; if (cx < 0) cx = 0; // ignore negative values if (cy < 0) cy = 0; // W and H null means the image is potentially as large as the current window // or widget. The latter can not be checked here, hence we use the whole // window as well and rely on appropriate clipping. See comments above. // This should be fixed! (AlbrechtS, 01 Mar 2015) if (W == 0 && H == 0 && Fl_Window::current()) { W = Fl_Window::current()->w(); H = Fl_Window::current()->h(); X = Y = 0; } if (W == 0 || H == 0) return; fl_push_clip(X, Y, W, H); if (cx > 0) iw -= cx; // crop image if (cy > 0) ih -= cy; for (int yy = Y; yy < Y+H; yy += ih) { if (fl_not_clipped(X,yy,W,ih)) { for (int xx = X; xx < X+W; xx += iw) { if (fl_not_clipped(xx,yy,iw,ih)) { image_->draw(xx,yy,iw,ih,cx,cy); } } } } fl_pop_clip(); } fltk-1.4.3/src/fl_round_box.cxx0000644000175000017500000001074015004135251016602 0ustar albrechtalbrecht// // Round box drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Box drawing code for an obscure box type. // These box types are in separate files so they are not linked // in if not used. #include #include // A compiler from a certain very large software company will not compile // the function pointer assignment due to the name conflict with fl_arc. // This function is to fix that: static void fl_arc_i(int x,int y,int w,int h,double a1,double a2) { fl_arc(x,y,w,h,a1,a2); } enum {UPPER_LEFT, LOWER_RIGHT, CLOSED, FILL}; static void draw(int which, int x,int y,int w,int h, int inset, Fl_Color color) { if (inset*2 >= w) inset = (w-1)/2; if (inset*2 >= h) inset = (h-1)/2; x += inset; y += inset; w -= 2*inset; h -= 2*inset; int d = w <= h ? w : h; if (d <= 1) return; fl_color(color); void (*f)(int,int,int,int,double,double); f = (which==FILL) ? fl_pie : fl_arc_i; if (which >= CLOSED) { if (w == h) f(x, y, d, d, 0, 360); else { f(x+w-d, y, d, d, w<=h ? 0 : -90, w<=h ? 180 : 90); f(x, y+h-d, d, d, w<=h ? 180 : 90, w<=h ? 360 : 270); } } else if (which == UPPER_LEFT) { if (w == h) f(x, y, d, d, 45, 225); else { f(x+w-d, y, d, d, 45, w<=h ? 180 : 90); f(x, y+h-d, d, d, w<=h ? 180 : 90, 225); } } else { // LOWER_RIGHT if (w == h) f(x, y, d, d, 225, 405); else { f(x, y+h-d, d, d, 225, w<=h ? 360 : 270); f(x+w-d, y, d, d, w<=h ? 360 : 270, 360+45); } } if (which == FILL) { if (w < h) fl_rectf(x, y+d/2, w, h-(d&-2)+1); else if (w > h) fl_rectf(x+d/2, y, w-(d&-2)+1, h); } else { if (w < h) { if (which != UPPER_LEFT) fl_yxline(x+w-1, y+d/2-1, y+h-d/2+1); if (which != LOWER_RIGHT) fl_yxline(x, y+d/2-1, y+h-d/2+1); } else if (w > h) { if (which != UPPER_LEFT) fl_xyline(x+d/2-1, y+h-1, x+w-d/2+1); if (which != LOWER_RIGHT) fl_xyline(x+d/2-1, y, x+w-d/2+1); } } } extern const uchar* fl_gray_ramp(); void fl_round_down_box(int x, int y, int w, int h, Fl_Color bgcolor) { const uchar *g = fl_gray_ramp(); draw(FILL, x, y, w, h, 2, Fl::box_color(bgcolor)); draw(UPPER_LEFT, x+1, y, w-2, h, 0, (Fl_Color)g[(int)'N']); draw(UPPER_LEFT, x+1, y, w-2, h, 1, (Fl_Color)g[(int)'H']); draw(UPPER_LEFT, x, y, w, h, 0, (Fl_Color)g[(int)'N']); draw(UPPER_LEFT, x, y, w, h, 1, (Fl_Color)g[(int)'H']); draw(LOWER_RIGHT, x, y, w, h, 0, (Fl_Color)g[(int)'S']); draw(LOWER_RIGHT, x+1, y, w-2, h, 0, (Fl_Color)g[(int)'U']); draw(LOWER_RIGHT, x, y, w, h, 1, (Fl_Color)g[(int)'U']); draw(LOWER_RIGHT, x+1, y, w-2, h, 1, (Fl_Color)g[(int)'W']); draw(CLOSED, x, y, w, h, 2, (Fl_Color)g[(int)'A']); } void fl_round_up_box(int x, int y, int w, int h, Fl_Color bgcolor) { const uchar *g = fl_gray_ramp(); draw(FILL, x, y, w, h, 2, Fl::box_color(bgcolor)); draw(LOWER_RIGHT, x+1, y, w-2, h, 0, (Fl_Color)g[(int)'H']); draw(LOWER_RIGHT, x+1, y, w-2, h, 1, (Fl_Color)g[(int)'N']); draw(LOWER_RIGHT, x, y, w, h, 1, (Fl_Color)g[(int)'H']); draw(LOWER_RIGHT, x, y, w, h, 2, (Fl_Color)g[(int)'N']); draw(UPPER_LEFT, x, y, w, h, 2, (Fl_Color)g[(int)'U']); draw(UPPER_LEFT, x+1, y, w-2, h, 1, (Fl_Color)g[(int)'S']); draw(UPPER_LEFT, x, y, w, h, 1, (Fl_Color)g[(int)'W']); draw(UPPER_LEFT, x+1, y, w-2, h, 0, (Fl_Color)g[(int)'U']); draw(CLOSED, x, y, w, h, 0, (Fl_Color)g[(int)'A']); } void fl_round_focus(Fl_Boxtype bt, int x, int y, int w, int h, Fl_Color fg, Fl_Color bg) { x += Fl::box_dx(bt); y += Fl::box_dy(bt); w -= Fl::box_dw(bt); h -= Fl::box_dh(bt); Fl_Color savecolor = fl_color(); fl_line_style(FL_DOT); draw(CLOSED, x, y, w, h, 0, fl_contrast(fg, bg)); fl_line_style(FL_SOLID); fl_color(savecolor); } extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*, Fl_Box_Draw_Focus_F* =NULL); Fl_Boxtype fl_define_FL_ROUND_UP_BOX() { fl_internal_boxtype(_FL_ROUND_DOWN_BOX, fl_round_down_box, fl_round_focus); fl_internal_boxtype(_FL_ROUND_UP_BOX, fl_round_up_box, fl_round_focus); return _FL_ROUND_UP_BOX; } fltk-1.4.3/src/Fl_Check_Button.cxx0000644000175000017500000000323015004135251017107 0ustar albrechtalbrecht// // Check button widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include /** \class Fl_Check_Button \brief A button with a "checkmark" to show its status. \image html Fl_Check_Button.png \image latex Fl_Check_Button.png "Fl_Check_Button" width=4cm Buttons generate callbacks when they are clicked by the user. You control exactly when and how by changing the values for type() and when(). The Fl_Check_Button subclass displays its "ON" state by showing a "checkmark" rather than drawing itself pushed in. */ /** Creates a new Fl_Check_Button widget using the given position, size, and label string. The default box type is FL_NO_BOX, which draws the label w/o a box right of the checkmark. The selection_color() sets the color of the checkmark. Default is FL_FOREGROUND_COLOR (usually black). You can use down_box() to change the box type of the checkmark. Default is FL_DOWN_BOX. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Check_Button::Fl_Check_Button(int X, int Y, int W, int H, const char *L) : Fl_Light_Button(X, Y, W, H, L) { box(FL_NO_BOX); down_box(FL_DOWN_BOX); selection_color(FL_FOREGROUND_COLOR); } fltk-1.4.3/src/Fl_Tree_Item_Array.cxx0000644000175000017500000002172015004135251017556 0ustar albrechtalbrecht// #include #include #include #include #include ////////////////////// // Fl_Tree_Item_Array.cxx ////////////////////// // // Fl_Tree -- This file is part of the Fl_Tree widget for FLTK // Copyright (C) 2009-2010 by Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /// Constructor; creates an empty array. /// /// The optional 'chunksize' can be specified to optimize /// memory allocation for potentially large arrays. Default chunksize is 10. /// Fl_Tree_Item_Array::Fl_Tree_Item_Array(int new_chunksize) { _items = 0; _total = 0; _size = 0; _flags = 0; _chunksize = new_chunksize; } /// Destructor. Calls each item's destructor, destroys internal _items array. Fl_Tree_Item_Array::~Fl_Tree_Item_Array() { clear(); } /// Copy constructor. Makes new copy of array, with new instances of each item. Fl_Tree_Item_Array::Fl_Tree_Item_Array(const Fl_Tree_Item_Array* o) { _items = (Fl_Tree_Item**)malloc(o->_size * sizeof(Fl_Tree_Item*)); _total = 0; _size = o->_size; _chunksize = o->_chunksize; _flags = o->_flags; for ( int t=0; t_total; t++ ) { if ( _flags & MANAGE_ITEM ) { _items[t] = new Fl_Tree_Item(o->_items[t]); // make new copy of item ++_total; _items[t]->update_prev_next(t); // update uses _total's current value } else { _items[t] = o->_items[t]; // copy ptr only ++_total; } } } /// Clear the entire array. /// /// Each item will be deleted (destructors will be called), /// and the array will be cleared. total() will return 0. /// void Fl_Tree_Item_Array::clear() { if ( _items ) { for ( int t=0; t<_total; t++ ) { if ( _flags & MANAGE_ITEM ) { delete _items[t]; _items[t] = 0; } } free((void*)_items); _items = 0; } _total = _size = 0; } // Internal: Enlarge the items array. // // Adjusts size/items memory allocation as needed. // Does NOT change total. // void Fl_Tree_Item_Array::enlarge(int count) { int newtotal = _total + count; // new total if ( newtotal >= _size ) { // more than we have allocated? if ( (newtotal/150) > _chunksize ) _chunksize *= 10; // Increase size of array int newsize = _size + _chunksize; Fl_Tree_Item **newitems = (Fl_Tree_Item**)malloc(newsize * sizeof(Fl_Tree_Item*)); if ( _items ) { // Copy old array -> new, delete old memmove(newitems, _items, _size * sizeof(Fl_Tree_Item*)); free((void*)_items); _items = 0; } // Adjust items/sizeitems _items = newitems; _size = newsize; } } /// Insert an item at index position \p pos. /// /// Handles enlarging array if needed, total increased by 1. /// If \p pos \>= total(), the item is appended to the array. /// If \p pos \< 0, the item is prepended (works like pos == 0). /// void Fl_Tree_Item_Array::insert(int pos, Fl_Tree_Item *new_item) { if (pos < 0) pos = 0; else if (pos > _total) pos = _total; enlarge(1); // printf("*** POS=%d TOTAL-1=%d NITEMS=%d\n", pos, _total-1, (_total-pos)); if ( pos <= (_total - 1) ) { // need to move memory around? int nitems = _total - pos; memmove(&_items[pos+1], &_items[pos], sizeof(Fl_Tree_Item*) * nitems); } _items[pos] = new_item; _total++; if ( _flags & MANAGE_ITEM ) { _items[pos]->update_prev_next(pos); // adjust item's prev/next and its neighbors } } /// Add an item* to the end of the array. /// /// Assumes the item was created with 'new', and will remain /// allocated.. Fl_Tree_Item_Array will handle calling the /// item's destructor when the array is cleared or the item remove()'ed. /// void Fl_Tree_Item_Array::add(Fl_Tree_Item *val) { insert(_total, val); } /// Replace the item at \p index with \p newitem. /// /// Old item at index position will be destroyed, /// and the new item will take it's place, and stitched into the linked list. /// void Fl_Tree_Item_Array::replace(int index, Fl_Tree_Item *newitem) { if ( _items[index] ) { // delete if non-zero if ( _flags & MANAGE_ITEM ) // Destroy old item delete _items[index]; } _items[index] = newitem; // install new item if ( _flags & MANAGE_ITEM ) { // Restitch into linked list _items[index]->update_prev_next(index); } } /// Remove the item at \param[in] index from the array. /// /// The item will be delete'd (if non-NULL), so its destructor will be called. /// void Fl_Tree_Item_Array::remove(int index) { if ( _items[index] ) { // delete if non-zero if ( _flags & MANAGE_ITEM ) delete _items[index]; } _items[index] = 0; _total--; for ( int i=index; i<_total; i++ ) { // reshuffle the array _items[i] = _items[i+1]; } if ( _flags & MANAGE_ITEM ) { if ( index < _total ) { // removed item not last? _items[index]->update_prev_next(index); // update next item's prev/next and neighbors } else if ( ((index-1) >= 0) && // removed item IS last? ((index-1) < _total)) { _items[index-1]->update_prev_next(index-1);// update prev item's prev/next and neighbors } } } /// Remove the item from the array. /// /// \returns 0 if removed, or -1 if the item was not in the array. /// int Fl_Tree_Item_Array::remove(Fl_Tree_Item *item) { for ( int t=0; t<_total; t++ ) { if ( item == _items[t] ) { remove(t); return(0); } } return(-1); } /// Swap the two items at index positions \p ax and \p bx. void Fl_Tree_Item_Array::swap(int ax, int bx) { Fl_Tree_Item *asave = _items[ax]; _items[ax] = _items[bx]; _items[bx] = asave; if ( _flags & MANAGE_ITEM ) { // Adjust prev/next ptrs _items[ax]->update_prev_next(ax); _items[bx]->update_prev_next(bx); } } /// Move item at 'from' to new position 'to' in the array. /// Due to how the moving an item shuffles the array around, /// a positional 'move' implies things that may not be obvious: /// - When 'from' moved lower in tree, appears BELOW item that was at 'to'. /// - When 'from' moved higher in tree, appears ABOVE item that was at 'to'. /// /// \returns 0 on success, -1 on range error (e.g. if \p 'to' or \p 'from' out of range) /// int Fl_Tree_Item_Array::move(int to, int from) { if ( from == to ) return 0; // nop if ( to<0 || to>=_total || from<0 || from>=_total ) return -1; Fl_Tree_Item *item = _items[from]; // Remove item.. if ( from < to ) for ( int t=from; tto && t>0; t-- ) _items[t] = _items[t-1]; // Move to new position _items[to] = item; // Update all children for ( int r=0; r<_total; r++ ) // XXX: excessive to do all children, _items[r]->update_prev_next(r); // XXX: but avoids weird boundary issues return 0; } /// Deparent item at \p 'pos' from our list of children. /// Similar to a remove() without the destruction of the item. /// This creates an orphaned item (still allocated, has no parent) /// which soon after is typically reparented elsewhere. /// /// \returns 0 on success, -1 on error (e.g. if \p 'pos' out of range) /// int Fl_Tree_Item_Array::deparent(int pos) { if ( pos>=_total || pos<0 ) return -1; // Save item being deparented, and its two nearest siblings Fl_Tree_Item *item = _items[pos]; Fl_Tree_Item *prev = item->prev_sibling(); Fl_Tree_Item *next = item->next_sibling(); // Remove from parent's list of children _total -= 1; for ( int t=pos; t<_total; t++ ) _items[t] = _items[t+1]; // delete, no destroy // Now an orphan: remove association with old parent and siblings item->update_prev_next(-1); // become an orphan // Adjust bereaved siblings if ( prev ) prev->update_prev_next(pos-1); if ( next ) next->update_prev_next(pos); return 0; } /// Reparent specified item as a child of ourself. /// Typically 'newchild' was recently orphaned with deparent(). /// /// \returns 0 on success, -1 on error (e.g. if \p 'pos' out of range) /// int Fl_Tree_Item_Array::reparent(Fl_Tree_Item *item, Fl_Tree_Item* newparent, int pos) { if ( pos<0 || pos>_total ) return -1; // Add item to new parent enlarge(1); _total += 1; for ( int t=_total-1; t>pos; --t ) // shuffle array to make room for new entry _items[t] = _items[t-1]; _items[pos] = item; // insert new entry // Attach to new parent and siblings _items[pos]->parent(newparent); // reparent (update_prev_next() needs this) _items[pos]->update_prev_next(pos); // find new siblings return 0; } fltk-1.4.3/src/fl_dnd_x.cxx0000644000175000017500000001666315004135251015711 0ustar albrechtalbrecht// // Drag & Drop code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Note: this file contains platform specific code and will therefore // not be processed by doxygen (see Doxyfile.in). #include #include #include #include "flstring.h" #include "drivers/X11/Fl_X11_Screen_Driver.H" #include "Fl_Window_Driver.H" extern Atom fl_XdndAware; extern Atom fl_XdndSelection; extern Atom fl_XdndEnter; extern Atom fl_XdndTypeList; extern Atom fl_XdndPosition; extern Atom fl_XdndLeave; extern Atom fl_XdndDrop; extern Atom fl_XdndStatus; extern Atom fl_XdndActionCopy; extern Atom fl_XdndFinished; extern Atom fl_XdndURIList; extern Atom fl_XaUtf8String; extern char fl_i_own_selection[2]; extern char *fl_selection_buffer[2]; extern void fl_sendClientMessage(Window window, Atom message, unsigned long d0, unsigned long d1=0, unsigned long d2=0, unsigned long d3=0, unsigned long d4=0); // return version # of Xdnd this window supports. Also change the // window to the proxy if it uses a proxy: static int dnd_aware(Window& window) { Atom actual; int format; unsigned long count, remaining; unsigned char *data = 0; XGetWindowProperty(fl_display, window, fl_XdndAware, 0, 4, False, XA_ATOM, &actual, &format, &count, &remaining, &data); int ret = 0; if (actual == XA_ATOM && format==32 && count && data) ret = int(*(Atom*)data); if (data) { XFree(data); data = 0; } return ret; } static int grabfunc(int event) { if (event == FL_RELEASE) Fl::pushed(0); return 0; } extern int (*fl_local_grab)(int); // in Fl.cxx // send an event to an fltk window belonging to this program: static int local_handle(int event, Fl_Window* window) { fl_local_grab = 0; Fl::e_x = Fl::e_x_root-window->x(); Fl::e_y = Fl::e_y_root-window->y(); int ret = Fl::handle(event,window); fl_local_grab = grabfunc; return ret; } int Fl_X11_Screen_Driver::dnd(int unused) { Fl_Window *source_fl_win = Fl::first_window(); Fl::first_window()->cursor(FL_CURSOR_MOVE); Window source_window = fl_xid(Fl::first_window()); fl_local_grab = grabfunc; Window target_window = 0; Fl_Window* local_window = 0; int dndversion = 4; int dest_x, dest_y; XSetSelectionOwner(fl_display, fl_XdndSelection, source_window, fl_event_time); while (Fl::pushed()) { // figure out what window we are pointing at: Window new_window = 0; int new_version = 0; Fl_Window* new_local_window = 0; for (Window child = RootWindow(fl_display, fl_screen);;) { Window root; unsigned int junk3; XQueryPointer(fl_display, child, &root, &child, &Fl::e_x_root, &Fl::e_y_root, &dest_x, &dest_y, &junk3); if (!child) { if (!new_window && (new_version = dnd_aware(root))) new_window = root; break; } new_window = child; if ((new_local_window = fl_find(child))) break; if ((new_version = dnd_aware(new_window))) break; } #if USE_XFT if (new_local_window) { float s = Fl::screen_driver()->scale(Fl_Window_Driver::driver(new_local_window)->screen_num()); Fl::e_x_root /= s; Fl::e_y_root /= s; } #endif if (new_window != target_window) { if (local_window) { local_handle(FL_DND_LEAVE, local_window); } else if (dndversion) { fl_sendClientMessage(target_window, fl_XdndLeave, source_window); } dndversion = new_version; target_window = new_window; local_window = new_local_window; if (local_window) { local_handle(FL_DND_ENTER, local_window); } else if (dndversion) { // Send an X-DND message to the target window. In order to // support dragging of files/URLs as well as arbitrary text, // we look at the selection buffer - if the buffer starts // with a common URI scheme, does not contain spaces, and // contains at least one CR LF, then we flag the data as // both a URI list (MIME media type "text/uri-list") and // plain text. Otherwise, we just say it is plain text. if ((!strncmp(fl_selection_buffer[0], "file:///", 8) || !strncmp(fl_selection_buffer[0], "ftp://", 6) || !strncmp(fl_selection_buffer[0], "http://", 7) || !strncmp(fl_selection_buffer[0], "https://", 8) || !strncmp(fl_selection_buffer[0], "ipp://", 6) || !strncmp(fl_selection_buffer[0], "ldap:", 5) || !strncmp(fl_selection_buffer[0], "mailto:", 7) || !strncmp(fl_selection_buffer[0], "news:", 5) || !strncmp(fl_selection_buffer[0], "smb://", 6)) && !strchr(fl_selection_buffer[0], ' ') && strstr(fl_selection_buffer[0], "\r\n")) { // Send file/URI list... fl_sendClientMessage(target_window, fl_XdndEnter, source_window, dndversion<<24, fl_XdndURIList, fl_XaUtf8String, XA_STRING); } else { // Send plain text... fl_sendClientMessage(target_window, fl_XdndEnter, source_window, dndversion<<24, fl_XaUtf8String, XA_STRING, 0); } } } if (local_window) { local_handle(FL_DND_DRAG, local_window); } else if (dndversion) { int exroot = Fl::e_x_root, eyroot = Fl::e_y_root; #if USE_XFT Fl_Window *target = fl_find(target_window); if (target) { float s = Fl::screen_driver()->scale(Fl_Window_Driver::driver(target)->screen_num()); exroot *= s; eyroot *= s; } #endif fl_sendClientMessage(target_window, fl_XdndPosition, source_window, 0, (exroot<<16)|eyroot, fl_event_time, fl_XdndActionCopy); } Fl::wait(); } if (local_window) { fl_i_own_selection[0] = 1; if (local_handle(FL_DND_RELEASE, local_window)) Fl::paste(*Fl::belowmouse(), 0); } else if (dndversion) { fl_sendClientMessage(target_window, fl_XdndDrop, source_window, 0, fl_event_time); } else if (target_window) { // fake a drop by clicking the middle mouse button: XButtonEvent msg; msg.type = ButtonPress; msg.window = target_window; msg.root = RootWindow(fl_display, fl_screen); msg.subwindow = 0; msg.time = fl_event_time+1; msg.x = dest_x; msg.y = dest_y; float s = 1; #if USE_XFT Fl_Window *target = fl_find(target_window); if (target) s = Fl::screen_driver()->scale(Fl_Window_Driver::driver(target)->screen_num()); #endif msg.x_root = Fl::e_x_root * s; msg.y_root = Fl::e_y_root * s; msg.state = 0x0; msg.button = Button2; XSendEvent(fl_display, target_window, False, 0L, (XEvent*)&msg); msg.time++; msg.state = 0x200; msg.type = ButtonRelease; XSendEvent(fl_display, target_window, False, 0L, (XEvent*)&msg); } fl_local_grab = 0; Fl::handle(FL_RELEASE, source_fl_win); source_fl_win->cursor(FL_CURSOR_DEFAULT); return 1; } fltk-1.4.3/src/print_panel.cxx0000644000175000017500000005546715004135251016454 0ustar albrechtalbrecht// // Print panel for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // This file is "work in progress". The main parts have been copied // from fluid's print_panel{.fl|.h|.cxx} and hand-edited to produce // a working version w/o global variables. The intention is to move // all static variables into an own class, and to name this class // Fl_Printer_Chooser or similar... // // Todo: // // - Currently preferences can't be saved, and there are options that // are not yet used for printing. // - This file can only be used as an include file in Fl_PS_Printer.cxx // - The use of static variables should be avoided. // - Probably much more ... // #include "print_panel.h" #include #include #include "../src/flstring.h" #include #include #include static Fl_Double_Window *print_panel=(Fl_Double_Window *)0; static Fl_Group *print_panel_controls=(Fl_Group *)0; static Fl_Choice *print_choice=(Fl_Choice *)0; static Fl_Button *print_properties=(Fl_Button *)0; static Fl_Box *print_status=(Fl_Box *)0; static Fl_Round_Button *print_all=(Fl_Round_Button *)0; static Fl_Round_Button *print_pages=(Fl_Round_Button *)0; static Fl_Round_Button *print_selection=(Fl_Round_Button *)0; static Fl_Check_Button *print_collate_button=(Fl_Check_Button *)0; static Fl_Group *print_collate_group[2]={(Fl_Group *)0}; static Fl_Progress *print_progress=(Fl_Progress *)0; static Fl_Double_Window *print_properties_panel=(Fl_Double_Window *)0; static Fl_Choice *print_page_size=(Fl_Choice *)0; static Fl_Int_Input *print_from=(Fl_Int_Input *)0; static Fl_Int_Input *print_to=(Fl_Int_Input *)0; static Fl_Spinner *print_copies=(Fl_Spinner *)0; static int print_start = 0; // 1 if print_okay has been clicked static void cb_print_choice(Fl_Choice*, void*) { print_update_status(); } static void cb_print_properties(Fl_Button*, void*) { print_properties_panel->show(); } static void cb_print_all(Fl_Round_Button*, void*) { print_from->deactivate(); print_to->deactivate(); } static void cb_print_pages(Fl_Round_Button*, void*) { print_from->activate(); print_to->activate(); } static void cb_print_selection(Fl_Round_Button*, void*) { print_from->deactivate(); print_to->deactivate(); } static void cb_print_copies(Fl_Spinner*, void*) { if (print_copies->value() == 1) { print_collate_button->deactivate(); print_collate_group[0]->deactivate(); print_collate_group[1]->deactivate(); } else { /* print_collate_button->activate(); // TODO: manage collate options print_collate_group[0]->activate(); print_collate_group[1]->activate(); */ }; } static void cb_print_collate_button(Fl_Check_Button*, void*) { int i = print_collate_button->value() != 0; print_collate_group[i]->show(); print_collate_group[1 - i]->hide(); } static void cb_Cancel(Fl_Button*, void*) { print_start = 0; print_panel->hide(); } static void cb_print_properties_panel(Fl_Double_Window*, void*) { print_properties_panel->hide(); print_update_status(); } static const Fl_Menu_Item menu_print_page_size[] = { {"Letter", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"A4", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Legal", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Executive", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"A3", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"A5", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"B5", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Com10", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"DL", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Tabloid", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0} }; #include static const char * const idata_print_color[] = { "24 24 17 1", " \tc None", ".\tc #FFFF00", "+\tc #C8FF00", "@\tc #00FF00", "#\tc #FFC800", "$\tc #FF0000", "%\tc #00FFFF", "&\tc #000000", "*\tc #FF00FF", "=\tc #00FFC8", "-\tc #FF00C8", ";\tc #00C800", ">\tc #C80000", ",\tc #0000C8", "\'\tc #0000FF", ")\tc #00C8FF", "!\tc #C800FF", " ...... ", " .......... ", " ............ ", " .............. ", " .............. ", " ................ ", " ................ ", " ................ ", " +@@@@@@+#$$$$$$# ", " %@@@@@@@&&$$$$$$$* ", " %%@@@@@@&&&&$$$$$$** ", " %%%=@@@@&&&&&&$$$$-*** ", " %%%%@@@;&&&&&&>$$$**** ", "%%%%%%@@&&&&&&&&$$******", "%%%%%%%@&&&&&&&&$*******", "%%%%%%%%,&&&&&&,********", "%%%%%%%%\'\'\'\'\'\'\'\'********", "%%%%%%%%\'\'\'\'\'\'\'\'********", "%%%%%%%%\'\'\'\'\'\'\'\'********", " %%%%%%%)\'\'\'\'\'\'!******* ", " %%%%%%%%\'\'\'\'\'\'******** ", " %%%%%%%%\'\'\'\'******** ", " %%%%%%%%\'\'******** ", " %%%%%% ****** " }; static Fl_Pixmap image_print_color(idata_print_color); static const char * const idata_print_gray[] = { "24 24 17 1", " \tc None", ".\tc #E3E3E3", "+\tc #D2D2D2", "@\tc #969696", "#\tc #C2C2C2", "$\tc #4C4C4C", "%\tc #B2B2B2", "&\tc #000000", "*\tc #696969", "=\tc #ACACAC", "-\tc #626262", ";\tc #767676", ">\tc #3C3C3C", ",\tc #161616", "\'\tc #1C1C1C", ")\tc #929292", "!\tc #585858", " ...... ", " .......... ", " ............ ", " .............. ", " .............. ", " ................ ", " ................ ", " ................ ", " +@@@@@@+#$$$$$$# ", " %@@@@@@@&&$$$$$$$* ", " %%@@@@@@&&&&$$$$$$** ", " %%%=@@@@&&&&&&$$$$-*** ", " %%%%@@@;&&&&&&>$$$**** ", "%%%%%%@@&&&&&&&&$$******", "%%%%%%%@&&&&&&&&$*******", "%%%%%%%%,&&&&&&,********", "%%%%%%%%\'\'\'\'\'\'\'\'********", "%%%%%%%%\'\'\'\'\'\'\'\'********", "%%%%%%%%\'\'\'\'\'\'\'\'********", " %%%%%%%)\'\'\'\'\'\'!******* ", " %%%%%%%%\'\'\'\'\'\'******** ", " %%%%%%%%\'\'\'\'******** ", " %%%%%%%%\'\'******** ", " %%%%%% ****** " }; static Fl_Pixmap image_print_gray(idata_print_gray); static Fl_Button *print_output_mode[4]={(Fl_Button *)0}; static void cb_Save(Fl_Return_Button*, void*) { print_properties_panel->hide(); char name[1024]; int val; const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); Fl_Preferences print_prefs(Fl_Preferences::CORE_USER, "fltk.org", "printers"); snprintf(name, sizeof(name), "%s/page_size", printer == NULL ? "" : printer); print_prefs.set(name, print_page_size->value()); snprintf(name, sizeof(name), "%s/output_mode", printer == NULL ? "" : printer); for (val = 0; val < 4; val ++) { if (print_output_mode[val]->value()) break; } print_prefs.set(name, val); } static void cb_Cancel1(Fl_Button*, void*) { print_properties_panel->hide(); print_update_status(); } static void cb_Use(Fl_Button*, void*) { print_properties_panel->hide(); } Fl_Double_Window* make_print_panel() { { print_panel = new Fl_Double_Window(465, 235, Fl_Printer::dialog_title); { print_panel_controls = new Fl_Group(10, 10, 447, 216); { print_choice = new Fl_Choice(133, 10, 181, 25, Fl_Printer::dialog_printer); print_choice->down_box(FL_BORDER_BOX); print_choice->labelfont(1); print_choice->callback((Fl_Callback*)cb_print_choice); print_choice->when(FL_WHEN_CHANGED); } // Fl_Choice* print_choice { print_properties = new Fl_Button(314, 10, 115, 25, Fl_Printer::dialog_properties); print_properties->callback((Fl_Callback*)cb_print_properties); } // Fl_Button* print_properties { print_status = new Fl_Box(0, 41, print_panel_controls->w(), 17, "printer/job status"); print_status->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE|FL_ALIGN_LEFT)); } // Fl_Box* print_status { Fl_Group* o = new Fl_Group(10, 86, 227, 105, Fl_Printer::dialog_range); o->box(FL_THIN_DOWN_BOX); o->labelfont(1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); { print_all = new Fl_Round_Button(20, 96, 38, 25, Fl_Printer::dialog_all); print_all->type(102); print_all->down_box(FL_ROUND_DOWN_BOX); print_all->value(1); print_all->callback((Fl_Callback*)cb_print_all); } // Fl_Round_Button* print_all { print_pages = new Fl_Round_Button(20, 126, 64, 25, Fl_Printer::dialog_pages); print_pages->type(102); print_pages->down_box(FL_ROUND_DOWN_BOX); print_pages->callback((Fl_Callback*)cb_print_pages); } // Fl_Round_Button* print_pages { print_selection = new Fl_Round_Button(20, 156, 82, 25, "Selection"); print_selection->type(102); print_selection->down_box(FL_ROUND_DOWN_BOX); print_selection->callback((Fl_Callback*)cb_print_selection); } // Fl_Round_Button* print_selection { print_from = new Fl_Int_Input(136, 126, 28, 25, Fl_Printer::dialog_from); print_from->type(2); print_from->textfont(4); print_from->deactivate(); } // Fl_Int_Input* print_from { print_to = new Fl_Int_Input(199, 126, 28, 25, Fl_Printer::dialog_to); print_to->type(2); print_to->textfont(4); print_to->deactivate(); } // Fl_Int_Input* print_to o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(247, 86, 210, 105, Fl_Printer::dialog_copies); o->box(FL_THIN_DOWN_BOX); o->labelfont(1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); { print_copies = new Fl_Spinner(321, 96, 45, 25, Fl_Printer::dialog_copyNo); print_copies->callback((Fl_Callback*)cb_print_copies); print_copies->when(FL_WHEN_CHANGED); } // Fl_Spinner* print_copies { print_collate_button = new Fl_Check_Button(376, 96, 64, 25, "Collate"); print_collate_button->down_box(FL_DOWN_BOX); print_collate_button->callback((Fl_Callback*)cb_print_collate_button); print_collate_button->when(FL_WHEN_CHANGED); print_collate_button->deactivate(); } // Fl_Check_Button* print_collate_button { print_collate_group[0] = new Fl_Group(257, 131, 191, 50); print_collate_group[0]->deactivate(); { Fl_Box* o = new Fl_Box(287, 141, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(272, 136, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(257, 131, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(352, 141, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(337, 136, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(322, 131, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(417, 141, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(402, 136, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o { Fl_Box* o = new Fl_Box(387, 131, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); o->deactivate(); } // Fl_Box* o print_collate_group[0]->end(); } // Fl_Group* print_collate_group[0] { print_collate_group[1] = new Fl_Group(257, 131, 191, 50); print_collate_group[1]->hide(); print_collate_group[1]->deactivate(); { Fl_Box* o = new Fl_Box(287, 141, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(272, 136, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(257, 131, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(352, 141, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(337, 136, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(322, 131, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(417, 141, 30, 40, "3"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(402, 136, 30, 40, "2"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o { Fl_Box* o = new Fl_Box(387, 131, 30, 40, "1"); o->box(FL_BORDER_BOX); o->color(FL_BACKGROUND2_COLOR); o->labelsize(11); o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); } // Fl_Box* o print_collate_group[1]->end(); } // Fl_Group* print_collate_group[1] o->end(); } // Fl_Group* o { Fl_Return_Button* o = new Fl_Return_Button(279, 201, 100, 25, Fl_Printer::dialog_print_button); o->callback((Fl_Callback*)print_cb); } // Fl_Return_Button* o { Fl_Button* o = new Fl_Button(389, 201, 68, 25, Fl_Printer::dialog_cancel_button); o->callback((Fl_Callback*)cb_Cancel); } // Fl_Button* o print_panel_controls->end(); } // Fl_Group* print_panel_controls { print_progress = new Fl_Progress(10, 203, 289, 21); print_progress->selection_color((Fl_Color)4); print_progress->hide(); } // Fl_Progress* print_progress print_panel->set_modal(); print_panel->end(); } // Fl_Double_Window* print_panel { print_properties_panel = new Fl_Double_Window(290, 130, Fl_Printer::property_title); print_properties_panel->callback((Fl_Callback*)cb_print_properties_panel); { print_page_size = new Fl_Choice(150, 10, 80, 25, Fl_Printer::property_pagesize); print_page_size->down_box(FL_BORDER_BOX); print_page_size->labelfont(FL_HELVETICA); print_page_size->menu(menu_print_page_size); } // Fl_Choice* print_page_size { Fl_Group* o = new Fl_Group(110, 45, 170, 40, Fl_Printer::property_mode); o->labelfont(FL_HELVETICA); o->align(Fl_Align(FL_ALIGN_LEFT)); { print_output_mode[0] = new Fl_Button(110, 45, 30, 40); print_output_mode[0]->type(102); print_output_mode[0]->box(FL_BORDER_BOX); print_output_mode[0]->down_box(FL_BORDER_BOX); print_output_mode[0]->value(1); print_output_mode[0]->color(FL_BACKGROUND2_COLOR); print_output_mode[0]->selection_color(FL_FOREGROUND_COLOR); print_output_mode[0]->image(image_print_color); } // Fl_Button* print_output_mode[0] { print_output_mode[1] = new Fl_Button(150, 50, 40, 30); print_output_mode[1]->type(102); print_output_mode[1]->box(FL_BORDER_BOX); print_output_mode[1]->down_box(FL_BORDER_BOX); print_output_mode[1]->color(FL_BACKGROUND2_COLOR); print_output_mode[1]->selection_color(FL_FOREGROUND_COLOR); print_output_mode[1]->image(image_print_color); } // Fl_Button* print_output_mode[1] { print_output_mode[2] = new Fl_Button(200, 45, 30, 40); print_output_mode[2]->type(102); print_output_mode[2]->box(FL_BORDER_BOX); print_output_mode[2]->down_box(FL_BORDER_BOX); print_output_mode[2]->color(FL_BACKGROUND2_COLOR); print_output_mode[2]->selection_color(FL_FOREGROUND_COLOR); print_output_mode[2]->image(image_print_gray); } // Fl_Button* print_output_mode[2] { print_output_mode[3] = new Fl_Button(240, 50, 40, 30); print_output_mode[3]->type(102); print_output_mode[3]->box(FL_BORDER_BOX); print_output_mode[3]->down_box(FL_BORDER_BOX); print_output_mode[3]->color(FL_BACKGROUND2_COLOR); print_output_mode[3]->selection_color(FL_FOREGROUND_COLOR); print_output_mode[3]->image(image_print_gray); } // Fl_Button* print_output_mode[3] o->end(); } // Fl_Group* o { Fl_Return_Button* o = new Fl_Return_Button(93, 95, 99, 25, Fl_Printer::property_save); o->callback((Fl_Callback*)cb_Save); } // Fl_Return_Button* o { Fl_Button* o = new Fl_Button(202, 95, 78, 25, Fl_Printer::property_cancel); o->callback((Fl_Callback*)cb_Cancel1); } // Fl_Button* o { Fl_Button* o = new Fl_Button(10, 95, 73, 25, Fl_Printer::property_use); o->callback((Fl_Callback*)cb_Use); } // Fl_Button* o print_properties_panel->set_modal(); print_properties_panel->end(); } // Fl_Double_Window* print_properties_panel return print_properties_panel; } void print_cb(Fl_Return_Button *, void *) { print_start = 1; print_panel->hide(); } printing_style print_load() { // return whether SystemV or BSD printing style is used FILE *lpstat; char line[1024], name[1024], *nptr, qname[2048], *qptr, defname[1024], *p; int i; printing_style style = SystemV; if (print_choice->size() > 1) { for (i = 1; print_choice->text(i); i ++) { free(print_choice->menu()[i].user_data()); } } print_choice->clear(); print_choice->add(Fl_Printer::dialog_print_to_file, 0, 0, 0, FL_MENU_DIVIDER); print_choice->value(0); print_start = 0; defname[0] = '\0'; // get names of all printers and of default one if ((lpstat = popen("LC_MESSAGES=C LANG=C /bin/sh -c '(lpstat -p -d ) 2>&-'", "r")) != NULL) { // try first with SystemV printing system while (fgets(line, sizeof(line), lpstat)) { if (!strncmp(line, "printer ", 8) && sscanf(line + 8, "%s", name) == 1) { for (nptr = name, qptr = qname; *nptr; *qptr++ = *nptr++) { if (*nptr == '/') *qptr++ = '\\'; } *qptr = '\0'; print_choice->add(qname, 0, 0, (void *)fl_strdup(name), 0); } else if (!strncmp(line, "system default destination: ", 28)) { if (sscanf(line + 28, "%s", defname) != 1) defname[0] = '\0'; } } pclose(lpstat); } if (print_choice->size() == 2 && (lpstat = fopen("/etc/printcap", "r"))) { // try next with BSD printing system while (fgets(line, sizeof(line),lpstat)) { // get names of all known printers if (*line == '#' || (p = strchr(line, '|')) == NULL) continue; *p = 0; print_choice->add(line, 0, 0, (void *)fl_strdup(line), 0); style = BSD; *p = '|'; while (1) { p = line + strlen(line) - 1; if (*p == '\n' && p > line) p--; if (*p != '\\') break; if (fgets(line, sizeof(line),lpstat)==0) { /* ignore */ } } } fclose(lpstat); p = fl_getenv("PRINTER"); // get name of default printer if (p == NULL) p = (char*)"lp"; strcpy(defname, p); } if (print_choice->size() > 2) print_choice->value(1); if (defname[0]) { // select default printer in menu for (i = 1; print_choice->text(i); i ++) { if (!strcmp((char *)print_choice->menu()[i].user_data(), defname)) { print_choice->value(i); break; } } } print_update_status(); return style; } // print_load() void print_update_status() { FILE *lpstat; char command[1024]; static char status[1024]; const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); status[0] = 0; if (print_choice->value()) { strcpy(status, "printer status unavailable"); snprintf(command, sizeof(command), "/bin/sh -c \"(lpstat -p '%s' ) 2>&-\" ", printer); // try first with SystemV printing system if ((lpstat = popen(command, "r")) != NULL) { if (fgets(status, sizeof(status), lpstat) == 0) { // if no reply pclose(lpstat); snprintf(command, sizeof(command), "lpq -P%s 2>&-", printer); // try next with BSD printing system if ((lpstat = popen(command, "r")) != NULL) { if (fgets(status, sizeof(status), lpstat)==0) { /* ignore */ } } } pclose(lpstat); } } print_status->label(status); char name[1024]; int val; Fl_Preferences print_prefs(Fl_Preferences::CORE_USER, "fltk.org", "printers"); snprintf(name, sizeof(name), "%s/page_size", printer == NULL ? "" : printer); print_prefs.get(name, val, 1); print_page_size->value(val); snprintf(name, sizeof(name), "%s/output_mode", printer == NULL ? "" : printer); print_prefs.get(name, val, 0); print_output_mode[val]->setonly(); } fltk-1.4.3/src/Fl_File_Icon.cxx0000644000175000017500000002530315004135251016373 0ustar albrechtalbrecht// // Fl_File_Icon routines. // // KDE icon code donated by Maarten De Boer. // // Copyright 1999-2010 by Michael Sweet. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // Fl_File_Icon::Fl_File_Icon() - Create a new file icon. // Fl_File_Icon::~Fl_File_Icon() - Remove a file icon. // Fl_File_Icon::add() - Add data to an icon. // Fl_File_Icon::find() - Find an icon based upon a given file. // Fl_File_Icon::draw() - Draw an icon. // Fl_File_Icon::label() - Set the widgets label to an icon. // Fl_File_Icon::labeltype() - Draw the icon label. // // // Include necessary header files... // #include #include #include #include "flstring.h" #include #include "Fl_System_Driver.H" #include #include #include #include // // Icon cache... // Fl_File_Icon *Fl_File_Icon::first_ = (Fl_File_Icon *)0; // Registers the FL_ICON_LABEL drawing function Fl_Labeltype fl_define_FL_ICON_LABEL() { Fl::set_labeltype(_FL_ICON_LABEL, Fl_File_Icon::labeltype, 0); return _FL_ICON_LABEL; } /** Creates a new Fl_File_Icon with the specified information. \param[in] p filename pattern \param[in] t file type \param[in] nd number of data values \param[in] d data values */ Fl_File_Icon::Fl_File_Icon(const char *p, /* I - Filename pattern */ int t, /* I - File type */ int nd, /* I - Number of data values */ short *d) /* I - Data values */ { // Initialize the pattern and type... pattern_ = p; type_ = t; // Copy icon data as needed... if (nd) { num_data_ = nd; alloc_data_ = nd + 1; data_ = (short *)calloc(sizeof(short), nd + 1); memcpy(data_, d, nd * sizeof(short)); } else { num_data_ = 0; alloc_data_ = 0; } // And add the icon to the list of icons... next_ = first_; first_ = this; } /** The destructor destroys the icon and frees all memory that has been allocated for it. */ Fl_File_Icon::~Fl_File_Icon() { Fl_File_Icon *current, // Current icon in list *prev; // Previous icon in list // Find the icon in the list... for (current = first_, prev = (Fl_File_Icon *)0; current != this && current != (Fl_File_Icon *)0; prev = current, current = current->next_) {/*empty*/} // Remove the icon from the list as needed... if (current) { if (prev) prev->next_ = current->next_; else first_ = current->next_; } // Free any memory used... if (alloc_data_) free(data_); } /** Adds a keyword value to the icon array, returning a pointer to it. \param[in] d data value */ short * // O - Pointer to new data value Fl_File_Icon::add(short d) // I - Data to add { short *dptr; // Pointer to new data value // Allocate/reallocate memory as needed if ((num_data_ + 1) >= alloc_data_) { alloc_data_ += 128; if (alloc_data_ == 128) dptr = (short *)malloc(sizeof(short) * alloc_data_); else dptr = (short *)realloc(data_, sizeof(short) * alloc_data_); if (dptr == NULL) return (NULL); data_ = dptr; } // Store the new data value and return data_[num_data_++] = d; data_[num_data_] = END; return (data_ + num_data_ - 1); } /** Finds an icon that matches the given filename and file type. \param[in] filename name of file \param[in] filetype enumerated file type \return matching file icon or NULL */ Fl_File_Icon * // O - Matching file icon or NULL Fl_File_Icon::find(const char *filename,// I - Name of file */ int filetype) // I - Enumerated file type { Fl_File_Icon *current; // Current file in list const char *name; // Base name of filename // Get file information if needed... if (filetype == ANY) { filetype = Fl::system_driver()->file_type(filename); } // Look at the base name in the filename name = fl_filename_name(filename); // Loop through the available file types and return any match that // is found... for (current = first_; current != (Fl_File_Icon *)0; current = current->next_) if ((current->type_ == filetype || current->type_ == ANY) && (fl_filename_match(filename, current->pattern_) || fl_filename_match(name, current->pattern_))) break; // Return the match (if any)... return (current); } /** Draws an icon in the indicated area. \param[in] x, y, w, h position and size \param[in] ic icon color \param[in] active status, default is active [non-zero] */ void Fl_File_Icon::draw(int x, // I - Upper-lefthand X int y, // I - Upper-lefthand Y int w, // I - Width of bounding box int h, // I - Height of bounding box Fl_Color ic, // I - Icon color... int active) // I - Active or inactive? { Fl_Color c, // Current color oc; // Outline color short *d, // Pointer to data *dend; // End of data... short *prim; // Pointer to start of primitive... double scale; // Scale of icon // Don't try to draw a NULL array! if (num_data_ == 0) return; // Setup the transform matrix as needed... scale = w < h ? w : h; fl_push_matrix(); fl_translate((float)x + 0.5 * ((float)w - scale), (float)y + 0.5 * ((float)h + scale)); fl_scale(scale, -scale); // Loop through the array until we see an unmatched END... d = data_; dend = data_ + num_data_; prim = NULL; c = ic; if (active) fl_color(c); else fl_color(fl_inactive(c)); while (d < dend) switch (*d) { case END : if (prim) switch (*prim) { case LINE : fl_end_line(); break; case CLOSEDLINE : fl_end_loop(); break; case POLYGON : fl_end_complex_polygon(); break; case OUTLINEPOLYGON : fl_end_complex_polygon(); oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) | ((unsigned short *)prim)[2]); if (active) { if (oc == FL_ICON_COLOR) fl_color(ic); else fl_color(oc); } else { if (oc == FL_ICON_COLOR) fl_color(fl_inactive(ic)); else fl_color(fl_inactive(oc)); } fl_begin_loop(); prim += 3; while (*prim == VERTEX) { fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001); prim += 3; } fl_end_loop(); fl_color(c); break; } prim = NULL; d ++; break; case COLOR : c = (Fl_Color)((((unsigned short *)d)[1] << 16) | ((unsigned short *)d)[2]); if (c == FL_ICON_COLOR) c = ic; if (!active) c = fl_inactive(c); fl_color(c); d += 3; break; case LINE : prim = d; d ++; fl_begin_line(); break; case CLOSEDLINE : prim = d; d ++; fl_begin_loop(); break; case POLYGON : prim = d; d ++; fl_begin_complex_polygon(); break; case OUTLINEPOLYGON : prim = d; d += 3; fl_begin_complex_polygon(); break; case VERTEX : if (prim) fl_vertex(d[1] * 0.0001, d[2] * 0.0001); d += 3; break; default : // Ignore invalid data... d ++; } // If we still have an open primitive, close it... if (prim) switch (*prim) { case LINE : fl_end_line(); break; case CLOSEDLINE : fl_end_loop(); break; case POLYGON : fl_end_polygon(); break; case OUTLINEPOLYGON : fl_end_polygon(); oc = (Fl_Color)((((unsigned short *)prim)[1] << 16) | ((unsigned short *)prim)[2]); if (active) { if (oc == FL_ICON_COLOR) fl_color(ic); else fl_color(oc); } else { if (oc == FL_ICON_COLOR) fl_color(fl_inactive(ic)); else fl_color(fl_inactive(oc)); } fl_begin_loop(); prim += 3; while (*prim == VERTEX) { fl_vertex(prim[1] * 0.0001, prim[2] * 0.0001); prim += 3; } fl_end_loop(); fl_color(c); break; } // Restore the transform matrix fl_pop_matrix(); } /** Applies the icon to the widget, registering the Fl_File_Icon label type as needed. \param[in] w widget for which this icon will become the label */ void Fl_File_Icon::label(Fl_Widget *w) // I - Widget to label { w->label(FL_ICON_LABEL, (const char*)this); } /** Draw the icon label. \param[in] o label data \param[in] x, y, w, h position and size of label \param[in] a label alignment [not used] */ void Fl_File_Icon::labeltype(const Fl_Label *o, // I - Label data int x, // I - X position of label int y, // I - Y position of label int w, // I - Width of label int h, // I - Height of label Fl_Align a) // I - Label alignment (not used) { Fl_File_Icon *icon; // Pointer to icon data (void)a; icon = (Fl_File_Icon *)(o->value); if (icon) icon->draw(x, y, w, h, (Fl_Color)(o->color)); } fltk-1.4.3/src/Fl_Menu_Bar.cxx0000644000175000017500000000343615004135251016237 0ustar albrechtalbrecht// // Menu bar widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include void Fl_Menu_Bar::draw() { draw_box(); if (!menu() || !menu()->text) return; const Fl_Menu_Item* m; int X = x()+6; for (m=menu()->first(); m->text; m = m->next()) { int W = m->measure(0,this) + 16; m->draw(X, y(), W, h(), this); X += W; if (m->flags & FL_MENU_DIVIDER) { int y1 = y() + Fl::box_dy(box()); int y2 = y1 + h() - Fl::box_dh(box()) - 1; // Draw a vertical divider between menus... fl_color(FL_DARK3); fl_yxline(X - 6, y1, y2); fl_color(FL_LIGHT3); fl_yxline(X - 5, y1, y2); } } } int Fl_Menu_Bar::handle(int event) { const Fl_Menu_Item* v; if (menu() && menu()->text) switch (event) { case FL_ENTER: case FL_LEAVE: return 1; case FL_PUSH: v = 0; J1: v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1); picked(v); return 1; case FL_SHORTCUT: if (visible_r()) { v = menu()->find_shortcut(0, true); if (v && v->submenu()) goto J1; } return test_shortcut() != 0; } return 0; } Fl_Menu_Bar::Fl_Menu_Bar(int X, int Y, int W, int H,const char *l) : Fl_Menu_(X,Y,W,H,l) { } void Fl_Menu_Bar::play_menu(const Fl_Menu_Item *v) { if (v) { v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1); picked(v); } } fltk-1.4.3/src/Fl_XColor.H0000644000175000017500000000210715004135251015334 0ustar albrechtalbrecht// // X-specific color definitions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_DOXYGEN #include #include // one of these for each color in fltk's "colormap": // if overlays are enabled, another one for the overlay struct Fl_XColor { unsigned char r,g,b; // actual color used by X unsigned char mapped; // true when XAllocColor done unsigned long pixel; // the X pixel to use }; extern Fl_XColor fl_xmap[/*overlay*/][256]; // mask & shifts to produce xcolor for truecolor visuals: extern unsigned char fl_redmask, fl_greenmask, fl_bluemask; extern int fl_redshift, fl_greenshift, fl_blueshift, fl_extrashift; #endif // FL_DOXYGEN fltk-1.4.3/src/fl_gleam.cxx0000644000175000017500000001516115004135251015672 0ustar albrechtalbrecht// // "Gleam" scheme box drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // These box types provide a sort of Clearlooks Glossy scheme // for FLTK. // // Copyright 2001-2005 by Colin Jones. // // Modified 2012-2013 by Edmanuel Torres // This is a new version of the fl_gleam. The gradients are on the top // and the bottom, the text area looks like in the classic FLTK way. // #include #include /* Implementation notes: All box types have 2 pixel wide borders, there is no distinction of "thin" box types, hence Fl::box_dx() = Fl::box_dy() = 2, Fl::box_dw() = Fl::box_dh() = 4 for all box types. All coordinates of function calls (x, y, w, h) describe the full box size with borders, i.e. the original box coordinates. The interior (background) of the box is drawn with reduced size. This is adjusted only in function shade_rect_top_bottom(). Note: There is one pixel "leaking" out of the box border at each corner which is currently not drawn in a full box redraw. */ // Standard box drawing code static void gleam_color(Fl_Color c) { Fl::set_box_color(c); } /* Draw the shaded background of the box. This is called before the box frame (border) is drawn. The interior of the box (shaded background) should be inset by two pixels, hence width and height should be reduced by 4 (border size). Since not all pixels of the border are drawn (border lines are shorter by one or two pixels on each side) setting other offsets (+1, -2 instead of +2, -4) would leak the box background color instead of the parent widget's background color. Note: the original implementation was maybe equivalent to using +1 and -2 for offset and width, respectively instead of +2 and -4. It is not clear whether this was intended or by accident. */ static void shade_rect_top_bottom(int x, int y, int w, int h, Fl_Color fg1, Fl_Color fg2, float th) { // calculate background size w/o borders x += 2; y += 2; w -= 4; h -= 4; // draw the shiny background using maximum limits int h_top = ((h/2) < (20) ? (h/2) : (20)); // min(h/2, 20); int h_bottom = ((h/6) < (15) ? (h/6) : (15)); // min(h/6, 15); int h_flat = h - h_top - h_bottom; float step_size_top = h_top > 1 ? (0.999f/float(h_top)) : 1; float step_size_bottom = h_bottom > 1 ? (0.999f/float(h_bottom)) : 1; // draw the gradient at the top of the widget float k = 1; for (int i = 0; i < h_top; i++, k -= step_size_top) { gleam_color(fl_color_average(fl_color_average(fg1, fg2, th), fg1, k)); fl_xyline(x, y+i, x+w-1); } // draw a "flat" rectangle in the middle area of the box gleam_color(fg1); fl_rectf(x, y + h_top, w, h_flat); // draw the gradient at the bottom of the widget k = 1; for (int i = 0; i < h_bottom; i++, k -= step_size_bottom) { gleam_color(fl_color_average(fg1, fl_color_average(fg1, fg2, th), k)); fl_xyline(x, y+h_top+h_flat+i, x+w-1); } } // See shade_rect_top_bottom() static void shade_rect_top_bottom_up(int x, int y, int w, int h, Fl_Color bc, float th) { shade_rect_top_bottom(x, y, w, h, bc, FL_WHITE, th); } // See shade_rect_top_bottom() static void shade_rect_top_bottom_down(int x, int y, int w, int h, Fl_Color bc, float th) { shade_rect_top_bottom(x, y, w, h, bc, FL_BLACK, th); } // Draw box borders. Color arguments: // - fg1: outer border line (left, right, top, bottom) // - fg2: inner border line (left, right) // - lc : inner border line (top, bottom) static void frame_rect(int x, int y, int w, int h, Fl_Color fg1, Fl_Color fg2, Fl_Color lc) { // outer border line: gleam_color(fg1); fl_xyline(x+1, y, x+w-2); // top fl_yxline(x+w-1, y+1, y+h-2); // right fl_xyline(x+1, y+h-1, x+w-2); // bottom fl_yxline(x, y+1, y+h-2); // left // inner border line (left, right): gleam_color(fg2); fl_yxline(x+1, y+2, y+h-3); // left fl_yxline(x+w-2, y+2, y+h-3); // right // inner border line (top, bottom): gleam_color(lc); fl_xyline(x+2, y+1, x+w-3); // top fl_xyline(x+2, y+h-2, x+w-3); // bottom } // Draw box borders with different colors (up/down effect). static void frame_rect_up(int x, int y, int w, int h, Fl_Color bc, Fl_Color lc, float th1, float th2) { frame_rect(x, y, w, h, fl_color_average(fl_darker(bc), FL_BLACK, th1), fl_color_average(bc, FL_WHITE, th2), lc); } static void frame_rect_down(int x, int y, int w, int h, Fl_Color bc, Fl_Color lc, float th1, float th2) { frame_rect(x,y,w,h,fl_color_average(bc, FL_WHITE, th1), fl_color_average(FL_BLACK, bc, th2), lc); } // Draw the different box types. These are the actual box drawing functions. static void up_frame(int x, int y, int w, int h, Fl_Color c) { frame_rect_up(x, y, w, h, c, fl_color_average(c, FL_WHITE, .25f), .55f, .05f); } static void up_box(int x, int y, int w, int h, Fl_Color c) { shade_rect_top_bottom_up(x, y, w, h, c, .15f); frame_rect_up(x, y, w, h, c, fl_color_average(c, FL_WHITE, .05f), .15f, .05f); } static void thin_up_box(int x, int y, int w, int h, Fl_Color c) { shade_rect_top_bottom_up(x, y, w, h, c, .25f); frame_rect_up(x, y, w, h, c, fl_color_average(c, FL_WHITE, .45f), .25f, .15f); } static void down_frame(int x, int y, int w, int h, Fl_Color c) { frame_rect_down(x, y, w, h, fl_darker(c), fl_darker(c), .25f, .95f); } static void down_box(int x, int y, int w, int h, Fl_Color c) { shade_rect_top_bottom_down(x, y, w, h, c, .65f); frame_rect_down(x, y, w, h, c, fl_color_average(c, FL_BLACK, .05f), .05f, .95f); } static void thin_down_box(int x, int y, int w, int h, Fl_Color c) { shade_rect_top_bottom_down(x, y, w, h, c, .85f); frame_rect_down(x, y, w, h, c, fl_color_average(c, FL_BLACK, .45f), .35f, 0.85f); } extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*, Fl_Box_Draw_Focus_F* =NULL); Fl_Boxtype fl_define_FL_GLEAM_UP_BOX() { fl_internal_boxtype(_FL_GLEAM_UP_BOX, up_box); fl_internal_boxtype(_FL_GLEAM_DOWN_BOX, down_box); fl_internal_boxtype(_FL_GLEAM_UP_FRAME, up_frame); fl_internal_boxtype(_FL_GLEAM_DOWN_FRAME, down_frame); fl_internal_boxtype(_FL_GLEAM_THIN_UP_BOX, thin_up_box); fl_internal_boxtype(_FL_GLEAM_THIN_DOWN_BOX, thin_down_box); fl_internal_boxtype(_FL_GLEAM_ROUND_UP_BOX, up_box); fl_internal_boxtype(_FL_GLEAM_ROUND_DOWN_BOX, down_box); return _FL_GLEAM_UP_BOX; } fltk-1.4.3/src/fl_cursor_none.xpm0000644000175000017500000000056415004135251017144 0ustar albrechtalbrecht/* XPM */ static const char * const fl_cursor_none_xpm[] = { "15 15 1 1", " c None", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}; fltk-1.4.3/src/Fl_SVG_Image.cxx0000644000175000017500000003024215004135251016303 0ustar albrechtalbrecht// // SVG image code for the Fast Light Tool Kit (FLTK). // // Copyright 2017-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if defined(FLTK_USE_SVG) || defined(FL_DOXYGEN) #include #include #include #include #include #include "Fl_Screen_Driver.H" #include "Fl_System_Driver.H" #include #include #include "../nanosvg/nanosvg.h" #include "../nanosvg/nanosvgrast.h" #if defined(HAVE_LIBZ) #include #endif /** Load an SVG image from a file. This constructor loads the SVG image from a .svg or .svgz file. The reader recognizes if the data is compressed, and decompresses it if zlib is available (HAVE_LIBZ). \param filename the filename for a .svg or .svgz file */ Fl_SVG_Image::Fl_SVG_Image(const char *filename) : Fl_RGB_Image(NULL, 0, 0, 4) { init_(filename, NULL, 0); } /** Load an SVG image from memory. This constructor loads the SVG image from a block of memory. This version is commonly used for uncompressed text data, but the reader recognizes if the data is compressed, and decompresses it if zlib is available (HAVE_LIBZ). \param sharedname if not \c NULL, a shared image will be generated with this name \param svg_data a pointer to the memory location of the SVG image data \note In-memory SVG data is parsed by the object constructor and is no longer needed after construction. */ Fl_SVG_Image::Fl_SVG_Image(const char *sharedname, const char *svg_data) : Fl_RGB_Image(NULL, 0, 0, 4) { init_(sharedname, (const unsigned char*)svg_data, 0); } /** Load an SVG image from memory. This constructor loads the SVG image from a block of memory. This version is commonly used for compressed binary data, but the reader recognizes if the data is uncompressed, and reads it as a text block. \param name if not \c NULL, a shared image will be generated with this name \param svg_data a pointer to the memory location of the SVG image data \param length of \p svg_data or \c 0 if the length is unknown. This will protect memory outside of the \p svg_data array from illegal read operations for compressed SVG data \note In-memory SVG data is parsed by the object constructor and is no longer needed after construction. */ Fl_SVG_Image::Fl_SVG_Image(const char *name, const unsigned char *svg_data, size_t length) : Fl_RGB_Image(NULL, 0, 0, 4) { init_(name, svg_data, length); } // private constructor Fl_SVG_Image::Fl_SVG_Image(const Fl_SVG_Image *source) : Fl_RGB_Image(NULL, 0, 0, 4) { counted_svg_image_ = source->counted_svg_image_; counted_svg_image_->ref_count++; to_desaturate_ = false; average_weight_ = 1; proportional = true; w(source->w()); h(source->h()); rasterized_ = false; raster_w_ = raster_h_ = 0; } /** The destructor frees all memory and server resources that are used by the SVG image. */ Fl_SVG_Image::~Fl_SVG_Image() { if ( --counted_svg_image_->ref_count <= 0) { nsvgDelete(counted_svg_image_->svg_image); delete counted_svg_image_; } } float Fl_SVG_Image::svg_scaling_(int W, int H) { float f1 = float(W) / int(counted_svg_image_->svg_image->width+0.5); float f2 = float(H) / int(counted_svg_image_->svg_image->height+0.5); return (f1 < f2) ? f1 : f2; } #if defined(HAVE_LIBZ) // Decompress gzip data in memory #define CHUNK_SIZE (2048) static int svg_inflate(uchar *src, size_t src_length, uchar *&dst, size_t &dst_length) { // allocate space for decompressed data in chunks typedef struct Chunk { Chunk() { next = NULL; } struct Chunk *next; uchar data[CHUNK_SIZE]; } Chunk; Chunk *first = NULL; Chunk *chunk = NULL, *next_chunk; z_stream stream = { }; int err = Z_OK; dst = 0; dst_length = 0; stream.next_in = (z_const Bytef *)src; stream.avail_in = 0; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; stream.opaque = (voidpf)0; // initialize zlib for inflating compressed data err = inflateInit2(&stream, 31); if (err != Z_OK) return err; gz_header header = { }; err = inflateGetHeader(&stream, &header); if (err != Z_OK) return err; stream.avail_out = 0; stream.avail_in = (uInt)(src_length ? src_length : -1); // inflate into as many chunks as needed do { if (stream.avail_out == 0) { next_chunk = new Chunk; if (!first) first = next_chunk; else chunk->next = next_chunk; chunk = next_chunk; stream.avail_out = CHUNK_SIZE; stream.next_out = chunk->data; } err = inflate(&stream, Z_NO_FLUSH); } while (err == Z_OK); inflateEnd(&stream); // copy chunk data into a new continuous data block if (err == Z_STREAM_END) { size_t nn = dst_length = stream.total_out; dst = (uchar*)malloc(dst_length+1); // leave room for a trailing NUL uchar *d = dst; chunk = first; while (chunk && nn>0) { size_t n = nn > CHUNK_SIZE ? CHUNK_SIZE : nn; memcpy(d, chunk->data, n); d += n; nn -= n; chunk = chunk->next; } } // delete all the chunks that we allocated chunk = first; while (chunk) { next_chunk = chunk->next; delete chunk; chunk = next_chunk; } return (err == Z_STREAM_END) ? Z_OK : (err == Z_NEED_DICT) ? Z_DATA_ERROR : ((err == Z_BUF_ERROR) && stream.avail_out) ? Z_DATA_ERROR : err; } #endif // defined(HAVE_LIBZ) void Fl_SVG_Image::init_(const char *name, const unsigned char *in_data, size_t length) { counted_svg_image_ = new counted_NSVGimage; counted_svg_image_->svg_image = NULL; counted_svg_image_->ref_count = 1; to_desaturate_ = false; average_weight_ = 1; proportional = true; // yes, this is a const cast to avoid duplicating user supplied data uchar *data = const_cast(in_data); // 🤨 careful with this, don't overwrite user supplied data in nsvgParse() // this is to make it clear what we are doing const char *sharedname = data ? name : NULL; const char *filename = data ? NULL : name; // prepare with error data, so we can just return if an error occurs d(-1); ld(ERR_FORMAT); rasterized_ = false; raster_w_ = raster_h_ = 0; // if we are reading from a file, just read the entire file into a memory block if (!data) { FILE *f = fl_fopen(filename, "rb"); if (f) { fseek(f, 0, SEEK_END); length = ftell(f); fseek(f, 0, SEEK_SET); data = (uchar*)malloc(length+1); if (data) { if (fread((void*)data, 1, length, f) == length) { data[length] = 0; } else { free((void*)data); data = NULL; } } fclose(f); } if (!data) return; } // now if our data is compressed, we use zlib to infalte it if (length==0 || length>10) { if (data[0] == 0x1f && data[1] == 0x8b) { #if defined(HAVE_LIBZ) // this is gzip compressed data, so we decompress it and preplace the data array uchar *uncompressed_data = NULL; size_t uncompressed_data_length = 0; int err = svg_inflate(data, length, uncompressed_data, uncompressed_data_length); if (err == Z_OK) { // replace compressed data with uncompressed data if (in_data == NULL) free(data); length = (size_t)uncompressed_data_length; data = (uchar*)uncompressed_data; data[length] = 0; } else { if (in_data != data) free(data); return; } #else if (in_data != data) free(data); return; #endif // HAVE_LIBZ } } // now our SVG data should be in text format in `data`, terminated by a NUL // nsvgParse is destructive, so if in_data was set, we must duplicate the data first! if (in_data == data) { if (length) { data = (uchar*)malloc(length+1); memcpy(data, in_data, length); data[length] = 0; } else { data = (uchar*)fl_strdup((char*)in_data); } } counted_svg_image_->svg_image = nsvgParse((char*)data, "px", 96); if (in_data != data) free(data); if (counted_svg_image_->svg_image->width != 0 && counted_svg_image_->svg_image->height != 0) { w(int(counted_svg_image_->svg_image->width + 0.5)); h(int(counted_svg_image_->svg_image->height + 0.5)); d(4); ld(0); } if (sharedname && w() && h()) { Fl_Shared_Image *si = new Fl_Shared_Image(sharedname, this); si->add(); } } void Fl_SVG_Image::rasterize_(int W, int H) { static NSVGrasterizer *rasterizer = nsvgCreateRasterizer(); double fx, fy; if (proportional) { fx = svg_scaling_(W, H); fy = fx; } else { fx = (double)W / counted_svg_image_->svg_image->width; fy = (double)H / counted_svg_image_->svg_image->height; } array = new uchar[W*H*4]; nsvgRasterizeXY(rasterizer, counted_svg_image_->svg_image, 0, 0, float(fx), float(fy), (uchar* )array, W, H, W*4); alloc_array = 1; data((const char * const *)&array, 1); d(4); if (to_desaturate_) Fl_RGB_Image::desaturate(); if (average_weight_ < 1) Fl_RGB_Image::color_average(average_color_, average_weight_); rasterized_ = true; raster_w_ = W; raster_h_ = H; } Fl_Image *Fl_SVG_Image::copy(int W, int H) const { Fl_SVG_Image *svg2 = new Fl_SVG_Image(this); svg2->to_desaturate_ = to_desaturate_; svg2->average_weight_ = average_weight_; svg2->average_color_ = average_color_; svg2->proportional = proportional; svg2->w(W); svg2->h(H); return svg2; } /** Have the svg data (re-)rasterized using the given \p width and \p height values. By default, the resulting image w() and h() will be close to \p width and \p height while preserving the width/height ratio of the SVG data. If \ref proportional was set to \c false, the image is rasterized to the exact \c width and \c height values. In both cases, data_w() and data_h() values are set to w() and h(), respectively. */ void Fl_SVG_Image::resize(int width, int height) { if (ld() < 0 || width <= 0 || height <= 0) { return; } int w1 = width, h1 = height; if (proportional) { float f = svg_scaling_(width, height); w1 = int( counted_svg_image_->svg_image->width*f + 0.5 ); h1 = int( counted_svg_image_->svg_image->height*f + 0.5 ); } w(w1); h(h1); if (rasterized_ && w1 == raster_w_ && h1 == raster_h_) return; if (array) { delete[] array; array = NULL; } uncache(); rasterize_(w1, h1); } void Fl_SVG_Image::cache_size_(int &width, int &height) { if (proportional) { // Keep the rasterized image proportional to its source-level width and height // while maintaining it large enough to allow image tiling. float f = counted_svg_image_->svg_image->width / counted_svg_image_->svg_image->height; if (height * f >= width) width = int(height * f + 0.5); else height = int(width/f + 0.5); } } void Fl_SVG_Image::draw(int X, int Y, int W, int H, int cx, int cy) { /* There may be several pixels per FLTK unit in an area of size w() x h() of the display. This occurs, e.g., with Apple retina displays and when the display is rescaled. The SVG is rasterized to the area dimension in pixels. The image is then drawn scaled to its size expressed in FLTK units. With this procedure, the SVG image is drawn using the full resolution of the display. */ int w1 = w(), h1 = h(); int f = fl_graphics_driver->has_feature(Fl_Graphics_Driver::PRINTER) ? 2 : 1; int w2 = f*w(), h2 = f*h(); fl_graphics_driver->cache_size(this, w2, h2); resize(w2, h2); scale(w1, h1, 0, 1); Fl_RGB_Image::draw(X, Y, W, H, cx, cy); } void Fl_SVG_Image::desaturate() { to_desaturate_ = true; Fl_RGB_Image::desaturate(); } void Fl_SVG_Image::color_average(Fl_Color c, float i) { average_color_ = c; average_weight_ = i; Fl_RGB_Image::color_average(c, i); } /** Makes sure the object is fully initialized. This function rasterizes the SVG image, and consequently initializes its \ref array member, if that was not done before. */ void Fl_SVG_Image::normalize() { if (!array) resize(w(), h()); } #endif // FLTK_USE_SVG fltk-1.4.3/src/gl_draw.cxx0000644000175000017500000005433715004135251015553 0ustar albrechtalbrecht// // OpenGL text drawing support routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Functions from // See also Fl_Gl_Window and gl_start.cxx /* Note about implementing GL text support for a new platform 1) if the GL_EXT_texture_rectangle (a.k.a. GL_ARB_texture_rectangle) GL extension is available, no platform-specific code is needed, besides support for fl_draw() and Fl_Image_Surface for the platform. 2) if the GL_EXT_texture_rectangle GL extension is not available, a rudimentary support through GLUT is obtained without any platform-specific code. 3) A more elaborate support can be obtained implementing get_list(), gl_bitmap_font() and draw_string_legacy() for the platform's Fl_XXX_Gl_Window_Driver. */ #include #if HAVE_GL || defined(FL_DOXYGEN) #include #include #include #include #include // for ceil() #include "Fl_Gl_Window_Driver.H" #include #if HAVE_GL_GLU_H # include // for gluUnProject() #endif #include // for glutStrokeString() and glutStrokeLength() #include #ifndef GL_TEXTURE_RECTANGLE_ARB # define GL_TEXTURE_RECTANGLE_ARB 0x84F5 #endif /** Returns the current font's height */ int gl_height() {return fl_height();} /** Returns the current font's descent */ int gl_descent() {return fl_descent();} /** Returns the width of the string in the current fnt */ double gl_width(const char* s) {return fl_width(s);} /** Returns the width of n characters of the string in the current font */ double gl_width(const char* s, int n) {return fl_width(s,n);} /** Returns the width of the character in the current font */ double gl_width(uchar c) {return fl_width(c);} static Fl_Font_Descriptor *gl_fontsize; static int has_texture_rectangle = 0; // true means GL_EXT_texture_rectangle is available extern float gl_start_scale; // in gl_start.cxx /** Sets the current OpenGL font to the same font as calling fl_font(). \see Fl::draw_GL_text_with_textures(int val) */ void gl_font(int fontid, int size) { static bool once = true; if (once) { once = false; if (Fl::draw_GL_text_with_textures()) { int gl_version_major; sscanf((const char *)glGetString(GL_VERSION), "%d", &gl_version_major); //printf("gl_version_major=%d\n", gl_version_major); if (gl_version_major >= 3) { has_texture_rectangle = true; } else { const char *extensions = (const char*)glGetString(GL_EXTENSIONS); if (extensions) { // For the font texture pile to work, we need a texture rectangle extension, so check for // one here. First we check for GL_EXT_texture_rectangle and if that fails we try // for GL_ARB_texture_rectangle instead. If that also fails, we fall back to the // legacy methods used by fltk-1.3 and earlier. has_texture_rectangle = (strstr(extensions, "GL_EXT_texture_rectangle") != NULL || strstr(extensions, "GL_ARB_texture_rectangle") != NULL); } } Fl::draw_GL_text_with_textures(has_texture_rectangle); } } fl_font(fontid, size); Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor(); if (!has_texture_rectangle) Fl_Gl_Window_Driver::global()->gl_bitmap_font(fl_fontsize); gl_fontsize = fl_fontsize; } void gl_remove_displaylist_fonts() { // clear variables used mostly in fl_font fl_graphics_driver->font(0, 0); for (int j = 0 ; j < FL_FREE_FONT ; ++j) { Fl_Font_Descriptor *prevDesc = 0L, *nextDesc = 0L; Fl_Font_Descriptor *&firstDesc = *Fl_Gl_Window_Driver::global()->fontnum_to_fontdescriptor(j); for (Fl_Font_Descriptor *desc = firstDesc; desc; desc = nextDesc) { nextDesc = desc->next; if(desc->listbase) { // remove descriptor from a single-linked list if(desc == firstDesc) { firstDesc = desc->next; } else if (prevDesc) { // prevDesc should not be NULL, but this test will make static analysis shut up prevDesc->next = desc->next; } // It would be nice if this next line was in a destructor somewhere glDeleteLists(desc->listbase, Fl_Gl_Window_Driver::global()->genlistsize()); delete desc; } else { prevDesc = desc; } } } } /** Draws an array of n characters of the string in the current font at the current position. \see gl_texture_pile_height(int) */ void gl_draw(const char* str, int n) { if (n > 0) { if (has_texture_rectangle) Fl_Gl_Window_Driver::draw_string_with_texture(str, n); else Fl_Gl_Window_Driver::global()->draw_string_legacy(str, n); } } /** Draws n characters of the string in the current font at the given position \see gl_texture_pile_height(int) */ void gl_draw(const char* str, int n, int x, int y) { glRasterPos2i(x, y); gl_draw(str, n); } /** Draws n characters of the string in the current font at the given position \see gl_texture_pile_height(int) */ void gl_draw(const char* str, int n, float x, float y) { glRasterPos2f(x, y); gl_draw(str, n); } /** Draws a nul-terminated string in the current font at the current position \see gl_texture_pile_height(int) */ void gl_draw(const char* str) { gl_draw(str, (int)strlen(str)); } /** Draws a nul-terminated string in the current font at the given position \see gl_texture_pile_height(int) */ void gl_draw(const char* str, int x, int y) { gl_draw(str, (int)strlen(str), x, y); } /** Draws a nul-terminated string in the current font at the given position \see gl_texture_pile_height(int) */ void gl_draw(const char* str, float x, float y) { gl_draw(str, (int)strlen(str), x, y); } static void gl_draw_invert(const char* str, int n, int x, int y) { glRasterPos2i(x, -y); gl_draw(str, n); } /** Draws a string formatted into a box, with newlines and tabs expanded, other control characters changed to ^X. and aligned with the edges or center. Exactly the same output as fl_draw(). */ void gl_draw( const char* str, // the (multi-line) string int x, int y, int w, int h, // bounding box Fl_Align align) { fl_draw(str, x, -y-h, w, h, align, gl_draw_invert, NULL, 0); } /** Measure how wide and tall the string will be when drawn by the gl_draw() function */ void gl_measure(const char* str, int& x, int& y) { fl_measure(str,x,y,0); } /** Outlines the given rectangle with the current color. If Fl_Gl_Window::ortho() has been called, then the rectangle will exactly fill the given pixel rectangle. */ void gl_rect(int x, int y, int w, int h) { if (w < 0) {w = -w; x = x-w;} if (h < 0) {h = -h; y = y-h;} glBegin(GL_LINE_LOOP); int r = x+w-1, b = y+h-1; glVertex2i(r, b); glVertex2i(r, y); glVertex2i(x, y); glVertex2i(x, b); glEnd(); } /** Fills the given rectangle with the current color. \see gl_rect(int x, int y, int w, int h) */ void gl_rectf(int x,int y,int w,int h) { glRecti(x,y,x+w,y+h); } void gl_draw_image(const uchar* b, int x, int y, int w, int h, int d, int ld) { if (!ld) ld = w*d; GLint row_length; glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); // get current row length glPixelStorei(GL_UNPACK_ROW_LENGTH, ld/d); glRasterPos2i(x,y); glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b); glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); // restore row length } /** Sets the curent OpenGL color to an FLTK color. For color-index modes it will use fl_xpixel(c), which is only right if the window uses the default colormap! */ void gl_color(Fl_Color i) { if (Fl_Gl_Window_Driver::global()->overlay_color(i)) return; uchar red, green, blue; Fl::get_color(i, red, green, blue); glColor3ub(red, green, blue); } #if ! defined(FL_DOXYGEN) // do not want too much of the gl_texture_fifo internals in the documentation /* Implement the gl_texture_fifo mechanism: Strings to be drawn are memorized in a fifo pile (which max size can be increased calling gl_texture_pile_height(int)). Each pile element contains the string, the font, the GUI scale, and an image of the string in the form of a GL texture. Strings are drawn in 2 steps: 1) compute the texture for that string if it was not computed before; 2) draw the texture using the current GL color. */ // manages a fifo pile of pre-computed string textures class gl_texture_fifo { friend class Fl_Gl_Window_Driver; private: typedef struct { // information for a pre-computed texture GLuint texName; // its name char *utf8; //its text Fl_Font_Descriptor *fdesc; // its font float scale; // scaling factor of the GUI int str_len; // the length of the utf8 text } data; data *fifo; // array of pile elements int size_; // pile height int current; // the oldest texture to have entered the pile int last; // pile top int textures_generated; // true after glGenTextures has been called void display_texture(int rank); int compute_texture(const char* str, int n); int already_known(const char *str, int n); public: gl_texture_fifo(int max = 100); // 100 = default height of texture pile inline int size(void) {return size_; } ~gl_texture_fifo(void); }; gl_texture_fifo::gl_texture_fifo(int max) { size_ = max; last = current = -1; textures_generated = 0; fifo = (data*)calloc(size_, sizeof(data)); } gl_texture_fifo::~gl_texture_fifo() { for (int i = 0; i < size_; i++) { if (fifo[i].utf8) free(fifo[i].utf8); if (textures_generated) glDeleteTextures(1, &fifo[i].texName); } free(fifo); } // returns rank of pre-computed texture for a string if it exists int gl_texture_fifo::already_known(const char *str, int n) { int rank; for ( rank = 0; rank <= last; rank++) { if ((fifo[rank].str_len == n) && (fifo[rank].fdesc == gl_fontsize) && (fifo[rank].scale == Fl_Gl_Window_Driver::gl_scale) && (memcmp(str, fifo[rank].utf8, n) == 0)) { return rank; } } return -1; // means no texture exists yet for that string } static gl_texture_fifo *gl_fifo = NULL; // points to the texture pile class instance // Cross-platform implementation of the texture mechanism for text rendering // using textures with the alpha channel only. // displays a pre-computed texture on the GL scene void gl_texture_fifo::display_texture(int rank) { // GL_TRANSFORM_BIT for GL_PROJECTION and GL_MODELVIEW // GL_ENABLE_BIT for GL_DEPTH_TEST, GL_LIGHTING // GL_TEXTURE_BIT for GL_TEXTURE_RECTANGLE_ARB // GL_COLOR_BUFFER_BIT for GL_BLEND and glBlendFunc, glPushAttrib(GL_TRANSFORM_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); //setup matrices glMatrixMode (GL_PROJECTION); glPushMatrix(); glLoadIdentity (); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glLoadIdentity (); float winw = Fl_Gl_Window_Driver::gl_scale * Fl_Window::current()->w(); float winh = Fl_Gl_Window_Driver::gl_scale * Fl_Window::current()->h(); glDisable (GL_DEPTH_TEST); // ensure text is not removed by depth buffer test. glEnable (GL_BLEND); // for text fading glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_LIGHTING); GLfloat pos[4]; glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); if (gl_start_scale != 1) { // using gl_start() / gl_finish() pos[0] /= gl_start_scale; pos[1] /= gl_start_scale; } float R = 2; glScalef (R/winw, R/winh, 1.0f); glTranslatef (-winw/R, -winh/R, 0.0f); glEnable (GL_TEXTURE_RECTANGLE_ARB); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[rank].texName); GLint width, height; glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_HEIGHT, &height); //write the texture on screen glBegin (GL_QUADS); float ox = pos[0]; float oy = pos[1] + height - Fl_Gl_Window_Driver::gl_scale * fl_descent(); glTexCoord2f (0.0f, 0.0f); // draw lower left in world coordinates glVertex2f (ox, oy); glTexCoord2f (0.0f, (GLfloat)height); // draw upper left in world coordinates glVertex2f (ox, oy - height); glTexCoord2f ((GLfloat)width, (GLfloat)height); // draw upper right in world coordinates glVertex2f (ox + width, oy - height); glTexCoord2f ((GLfloat)width, 0.0f); // draw lower right in world coordinates glVertex2f (ox + width, oy); glEnd (); // reset original matrices glPopMatrix(); // GL_MODELVIEW glMatrixMode (GL_PROJECTION); glPopMatrix(); glPopAttrib(); // GL_TRANSFORM_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT #if HAVE_GL_GLU_H //set the raster position to end of string pos[0] += width; GLdouble modelmat[16]; glGetDoublev (GL_MODELVIEW_MATRIX, modelmat); GLdouble projmat[16]; glGetDoublev (GL_PROJECTION_MATRIX, projmat); GLdouble objX, objY, objZ; GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); gluUnProject(pos[0], pos[1], pos[2], modelmat, projmat, viewport, &objX, &objY, &objZ); if (gl_start_scale != 1) { // using gl_start() / gl_finish() objX *= gl_start_scale; objY *= gl_start_scale; } glRasterPos2d(objX, objY); #endif // HAVE_GL_GLU_H } // display_texture // pre-computes a string texture int gl_texture_fifo::compute_texture(const char* str, int n) { current = (current + 1) % size_; if (current > last) last = current; if ( fifo[current].utf8 ) free(fifo[current].utf8); fifo[current].utf8 = (char *)malloc(n + 1); memcpy(fifo[current].utf8, str, n); fifo[current].utf8[n] = 0; fifo[current].str_len = n; // record length of text in utf8 Fl_Fontsize fs = fl_size(); float s = fl_graphics_driver->scale(); fl_graphics_driver->Fl_Graphics_Driver::scale(1); // temporarily remove scaling factor fl_font(fl_font(), int(fs * Fl_Gl_Window_Driver::gl_scale)); // the font size to use in the GL scene int w = (int)ceil( fl_width(fifo[current].utf8, n) ); w = ((w + 3) / 4) * 4; // make w a multiple of 4 int h = fl_height(); fl_graphics_driver->Fl_Graphics_Driver::scale(s); // re-install scaling factor fl_font(fl_font(), fs); fs = int(fs * Fl_Gl_Window_Driver::gl_scale); fifo[current].scale = Fl_Gl_Window_Driver::gl_scale; fifo[current].fdesc = gl_fontsize; char *alpha_buf = Fl_Gl_Window_Driver::global()->alpha_mask_for_string(str, n, w, h, fs); // save GL parameters GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT GLint row_length, alignment; glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); // put the bitmap in an alpha-component-only texture glPushAttrib(GL_TEXTURE_BIT); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[current].texName); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glPixelStorei(GL_UNPACK_ROW_LENGTH, w); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // GL_ALPHA8 is defined in GL/gl.h of X11 and of MinGW32 and of MinGW64 and of OpenGL.framework for MacOS glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_ALPHA8, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_buf); /* For the record: texture construction if an alpha-only-texture is not possible glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, w, h, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, rgba_buf); and also, replace GL_SRC_ALPHA by GL_ONE in glBlendFunc() call of display_texture() */ delete[] alpha_buf; // free the buffer now we have copied it into the GL texture glPopAttrib(); // restore saved GL parameters glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); return current; } #endif // ! defined(FL_DOXYGEN) /** Returns the current maximum height of the pile of pre-computed string textures. The default value is 100 \see Fl::draw_GL_text_with_textures(int) */ int gl_texture_pile_height(void) { if (! gl_fifo) gl_fifo = new gl_texture_fifo(); return gl_fifo->size(); } /** To call after GL operations that may invalidate textures used to draw text in GL scenes (e.g., switch between FL_DOUBLE / FL_SINGLE modes). */ void gl_texture_reset() { if (gl_fifo) gl_texture_pile_height(gl_texture_pile_height()); } /** Changes the maximum height of the pile of pre-computed string textures Strings that are often re-displayed can be processed much faster if this pile is set high enough to hold all of them. \param max Maximum height of the texture pile \see Fl::draw_GL_text_with_textures(int) */ void gl_texture_pile_height(int max) { if (gl_fifo) delete gl_fifo; gl_fifo = new gl_texture_fifo(max); } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ void Fl_Gl_Window_Driver::draw_string_legacy(const char* str, int n) { draw_string_legacy_glut(str, n); } /** draws a utf8 string using an OpenGL texture */ void Fl_Gl_Window_Driver::draw_string_with_texture(const char* str, int n) { // Check if the raster pos is valid. // If it's not, then drawing it results in undefined behaviour (#1006, #1007). GLint valid; glGetIntegerv(GL_CURRENT_RASTER_POSITION_VALID, &valid); if (!valid) return; Fl_Gl_Window *gwin = Fl_Window::current()->as_gl_window(); gl_scale = (gwin ? gwin->pixels_per_unit() : 1); if (!gl_fifo) gl_fifo = new gl_texture_fifo(); if (!gl_fifo->textures_generated) { if (has_texture_rectangle) for (int i = 0; i < gl_fifo->size_; i++) glGenTextures(1, &(gl_fifo->fifo[i].texName)); gl_fifo->textures_generated = 1; } int index = gl_fifo->already_known(str, n); if (index == -1) { index = gl_fifo->compute_texture(str, n); } gl_fifo->display_texture(index); } char *Fl_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, int w, int h, Fl_Fontsize fs) { // write str to a bitmap that is just big enough // create an Fl_Image_Surface object Fl_Image_Surface *image_surface = new Fl_Image_Surface(w, h); Fl_Font fnt = fl_font(); // get the current font // direct all further graphics requests to the image Fl_Surface_Device::push_current(image_surface); // fill the background with black, which we will interpret as transparent fl_color(0,0,0); fl_rectf(0, 0, w, h); // set up the text colour as white, which we will interpret as opaque fl_color(255,255,255); // Fix the font scaling fl_font (fnt, fs); // resize "fltk" font to current GL view scaling int desc = fl_descent(); // Render the text to the buffer fl_draw(str, n, 0, h - desc); // get the resulting image Fl_RGB_Image* image = image_surface->image(); // direct graphics requests back to previous state Fl_Surface_Device::pop_current(); delete image_surface; // This gives us an RGB rendering of the text. We build an alpha channel from that. char *alpha_buf = new char [w * h]; for (int idx = 0; idx < w * h; ++idx) { // Fake up the alpha component using the green component's value alpha_buf[idx] = image->array[idx * 3 + 1]; } delete image; return alpha_buf; } // platform-independent, no-texture GL text drawing procedure // when Fl_XXX_Gl_Window_Driver::get_list() and gl_bitmap_font() are implemented void Fl_Gl_Window_Driver::draw_string_legacy_get_list(const char* str, int n) { static unsigned short *buf = NULL; static unsigned l = 0; unsigned wn = fl_utf8toUtf16(str, n, buf, l); if (wn >= l) { buf = (unsigned short*) realloc(buf, sizeof(unsigned short) * (wn + 1)); l = wn + 1; wn = fl_utf8toUtf16(str, n, buf, l); } int size = 0; if (gl_start_scale != 1) { // using gl_start() / gl_finish() size = fl_graphics_driver->font_descriptor()->size; gl_font(fl_font(), Fl_Fontsize(size * gl_start_scale)); } for (unsigned i = 0; i < wn; i++) { unsigned int r; r = (buf[i] & 0xFC00) >> 10; get_list(gl_fontsize, r); } glCallLists(wn, GL_UNSIGNED_SHORT, buf); if (gl_start_scale != 1) { // using gl_start() / gl_finish() gl_font(fl_font(), size); } } /* Platform-independent, no-texture, GL text drawing procedure when there's no OS support whatsoever: glutStrokeString() is used to draw text. It's possible to vary text size, but not text font, and only ASCII characters can be drawn. */ void Fl_Gl_Window_Driver::draw_string_legacy_glut(const char* str, int n) { uchar *str_nul = new uchar[n + 1]; int m = 0; for (int i = 0; i < n; i++) { if ((uchar)str[i] < 128) str_nul[m++] = str[i]; } str_nul[m] = 0; n = m; Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); fl_graphics_driver->font_descriptor(gl_fontsize); Fl_Gl_Window *gwin = Fl_Window::current()->as_gl_window(); gl_scale = (gwin ? gwin->pixels_per_unit() : 1); float ratio = float(fl_width((char*)str_nul, n) * gl_scale/glutStrokeLength(GLUT_STROKE_ROMAN, str_nul)); Fl_Surface_Device::pop_current(); //setup matrices GLint matrixMode; glGetIntegerv (GL_MATRIX_MODE, &matrixMode); glMatrixMode (GL_PROJECTION); glPushMatrix(); glLoadIdentity (); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glLoadIdentity (); float winw = gl_scale * Fl_Window::current()->w(); float winh = gl_scale * Fl_Window::current()->h(); GLfloat pos[4]; glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); if (gl_start_scale != 1) { // using gl_start() / gl_finish() pos[0] /= gl_start_scale; pos[1] /= gl_start_scale; } float R = 2 * ratio; glScalef (R/winw, R/winh, 1.0f); glTranslatef (-winw/R, -winh/R, 0.0f); glTranslatef(pos[0]*2/R, pos[1]*2/R, 0.0); glutStrokeString(GLUT_STROKE_ROMAN, str_nul); float width = float(fl_width((char*)str_nul)); delete[] str_nul; glPopAttrib(); // reset original matrices glPopMatrix(); // GL_MODELVIEW glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (matrixMode); #if HAVE_GL_GLU_H //set the raster position to end of string pos[0] += width; GLdouble modelmat[16]; glGetDoublev (GL_MODELVIEW_MATRIX, modelmat); GLdouble projmat[16]; glGetDoublev (GL_PROJECTION_MATRIX, projmat); GLdouble objX, objY, objZ; GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); gluUnProject(pos[0], pos[1], pos[2], modelmat, projmat, viewport, &objX, &objY, &objZ); if (gl_start_scale != 1) { // using gl_start() / gl_finish() objX *= gl_start_scale; objY *= gl_start_scale; } glRasterPos2d(objX, objY); #endif // HAVE_GL_GLU_H } /** \} \endcond */ #endif // HAVE_GL || defined(FL_DOXYGEN) fltk-1.4.3/src/Fl_Browser.cxx0000644000175000017500000007306115004135251016173 0ustar albrechtalbrecht// // Browser widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include "flstring.h" #include #include #include #include #include // I modified this from the original Forms data to use a linked list // so that the number of items in the browser and size of those items // is unlimited. The only problem is that the old browser used an // index number to identify a line, and it is slow to convert from/to // a pointer. I use a cache of the last match to try to speed this up. // Also added the ability to "hide" a line. This sets its height to // zero, so the Fl_Browser_ cannot pick it. #define SELECTED 1 #define NOTDISPLAYED 2 // WARNING: // Fl_File_Chooser.cxx also has a definition of this structure (FL_BLINE). // Changes to FL_BLINE *must* be reflected in Fl_File_Chooser.cxx as well. // This hack in Fl_File_Chooser should be solved. // struct FL_BLINE { // data is in a linked list of these FL_BLINE* prev; FL_BLINE* next; void* data; Fl_Image* icon; short length; // sizeof(txt)-1, may be longer than string char flags; // selected, displayed char txt[1]; // start of allocated array }; /** Returns the very first item in the list. Example of use: \code // Walk the browser from beginning to end for ( void *i=item_first(); i; i=item_next(i) ) { printf("item label='%s'\n", item_text(i)); } \endcode \returns The first item, or NULL if list is empty. \see item_first(), item_last(), item_next(), item_prev() */ void* Fl_Browser::item_first() const {return first;} /** Returns the next item after \p item. \param[in] item The 'current' item \returns The next item after \p item, or NULL if there are none after this one. \see item_first(), item_last(), item_next(), item_prev() */ void* Fl_Browser::item_next(void* item) const {return ((FL_BLINE*)item)->next;} /** Returns the previous item before \p item. \param[in] item The 'current' item \returns The previous item before \p item, or NULL if there are none before this one. \see item_first(), item_last(), item_next(), item_prev() */ void* Fl_Browser::item_prev(void* item) const {return ((FL_BLINE*)item)->prev;} /** Returns the very last item in the list. Example of use: \code // Walk the browser in reverse, from end to start for ( void *i=item_last(); i; i=item_prev(i) ) { printf("item label='%s'\n", item_text(i)); } \endcode \returns The last item, or NULL if list is empty. \see item_first(), item_last(), item_next(), item_prev() */ void* Fl_Browser::item_last() const {return last;} /** See if \p item is selected. \param[in] item The item whose selection state is to be checked. \returns 1 if selected, 0 if not. \see select(), selected(), value(), item_select(), item_selected() */ int Fl_Browser::item_selected(void* item) const { return ((FL_BLINE*)item)->flags&SELECTED; } /** Change the selection state of \p item to the value \p val. \param[in] item The item to be changed. \param[in] val The new selection state: 1 selects, 0 de-selects. \see select(), selected(), value(), item_select(), item_selected() */ void Fl_Browser::item_select(void *item, int val) { if (val) ((FL_BLINE*)item)->flags |= SELECTED; else ((FL_BLINE*)item)->flags &= ~SELECTED; } /** Returns the label text for \p item. \param[in] item The item whose label text is returned. \returns The item's text string. (Can be NULL) */ const char *Fl_Browser::item_text(void *item) const { return ((FL_BLINE*)item)->txt; } /** Returns the item for specified \p line. Note: This call is slow. It's fine for e.g. responding to user clicks, but slow if called often, such as in a tight sorting loop. Finding an item 'by line' involves a linear lookup on the internal linked list. The performance hit can be significant if the browser's contents is large, and the method is called often (e.g. during a sort). If you're writing a subclass, use the protected methods item_first(), item_next(), etc. to access the internal linked list more efficiently. \param[in] line The line number of the item to return. (1 based) \retval item that was found. \retval NULL if line is out of range. \see item_at(), find_line(), lineno() */ FL_BLINE* Fl_Browser::find_line(int line) const { int n; FL_BLINE* l; if (line == cacheline) return cache; if (cacheline && line > (cacheline/2) && line < ((cacheline+lines)/2)) { n = cacheline; l = cache; } else if (line <= (lines/2)) { n = 1; l = first; } else { n = lines; l = last; } for (; n < line && l; n++) l = l->next; for (; n > line && l; n--) l = l->prev; ((Fl_Browser*)this)->cacheline = line; ((Fl_Browser*)this)->cache = l; return l; } /** Returns line number corresponding to \p item, or zero if not found. Caveat: See efficiency note in find_line(). \param[in] item The item to be found \returns The line number of the item, or 0 if not found. \see item_at(), find_line(), lineno() */ int Fl_Browser::lineno(void *item) const { FL_BLINE* l = (FL_BLINE*)item; if (!l) return 0; if (l == cache) return cacheline; if (l == first) return 1; if (l == last) return lines; if (!cache) { ((Fl_Browser*)this)->cache = first; ((Fl_Browser*)this)->cacheline = 1; } // assume it is near cache, search both directions: FL_BLINE* b = cache->prev; int bnum = cacheline-1; FL_BLINE* f = cache->next; int fnum = cacheline+1; int n = 0; for (;;) { if (b == l) {n = bnum; break;} if (f == l) {n = fnum; break;} if (b) {b = b->prev; bnum--;} if (f) {f = f->next; fnum++;} } ((Fl_Browser*)this)->cache = l; ((Fl_Browser*)this)->cacheline = n; return n; } /** Removes the item at the specified \p line. Caveat: See efficiency note in find_line(). You must call redraw() to make any changes visible. \param[in] line The line number to be removed. (1 based) Must be in range! \returns Pointer to browser item that was removed (and is no longer valid). \see add(), insert(), remove(), swap(int,int), clear() */ FL_BLINE* Fl_Browser::_remove(int line) { FL_BLINE* ttt = find_line(line); deleting(ttt); cacheline = line-1; cache = ttt->prev; lines--; full_height_ -= item_height(ttt) + linespacing(); if (ttt->prev) ttt->prev->next = ttt->next; else first = ttt->next; if (ttt->next) ttt->next->prev = ttt->prev; else last = ttt->prev; return(ttt); } /** Remove entry for given \p line number, making the browser one line shorter. You must call redraw() to make any changes visible. \param[in] line Line to be removed. (1 based) \n If \p line is out of range, no action is taken. \see add(), insert(), remove(), swap(int,int), clear() */ void Fl_Browser::remove(int line) { if (line < 1 || line > lines) return; free(_remove(line)); } /** Insert specified \p item above \p line. If \p line > size() then the line is added to the end. Caveat: See efficiency note in find_line(). \param[in] line The new line will be inserted above this line (1 based). \param[in] item The item to be added. */ void Fl_Browser::insert(int line, FL_BLINE* item) { if (!first) { item->prev = item->next = 0; first = last = item; } else if (line <= 1) { inserting(first, item); item->prev = 0; item->next = first; item->next->prev = item; first = item; } else if (line > lines) { item->prev = last; item->prev->next = item; item->next = 0; last = item; } else { FL_BLINE* n = find_line(line); inserting(n, item); item->next = n; item->prev = n->prev; item->prev->next = item; n->prev = item; } cacheline = line; cache = item; lines++; full_height_ += item_height(item) + linespacing(); redraw_line(item); } /** Insert a new entry whose label is \p newtext \e above given \p line, optional data \p d. Text may contain format characters; see format_char() for details. \p newtext is copied using the strdup() function, and can be NULL to make a blank line. The optional void * argument \p d will be the data() of the new item. \param[in] line Line position for insert. (1 based) \n If \p line > size(), the entry will be added at the end. \param[in] newtext The label text for the new line. \param[in] d Optional pointer to user data to be associated with the new line. */ void Fl_Browser::insert(int line, const char* newtext, void* d) { if (!newtext) newtext = ""; // STR #3269 int l = (int) strlen(newtext); FL_BLINE* t = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l); t->length = (short)l; t->flags = 0; strcpy(t->txt, newtext); t->data = d; t->icon = 0; insert(line, t); } /** Line \p from is removed and reinserted at \p to. Note: \p to is calculated \e after line \p from gets removed. \param[in] to Destination line number (calculated \e after line \p from is removed) \param[in] from Line number of item to be moved */ void Fl_Browser::move(int to, int from) { if (from < 1 || from > lines) return; insert(to, _remove(from)); } /** Sets the text for the specified \p line to \p newtext. Text may contain format characters; see format_char() for details. \p newtext is copied using the strdup() function, and can be NULL to make a blank line. Does nothing if \p line is out of range. \param[in] line The line of the item whose text will be changed. (1 based) \param[in] newtext The new string to be assigned to the item. */ void Fl_Browser::text(int line, const char* newtext) { if (line < 1 || line > lines) return; FL_BLINE* t = find_line(line); if (!newtext) newtext = ""; // STR #3269 int l = (int) strlen(newtext); if (l > t->length) { FL_BLINE* n = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l); replacing(t, n); cache = n; n->data = t->data; n->icon = t->icon; n->length = (short)l; n->flags = t->flags; n->prev = t->prev; if (n->prev) n->prev->next = n; else first = n; n->next = t->next; if (n->next) n->next->prev = n; else last = n; free(t); t = n; } strcpy(t->txt, newtext); redraw_line(t); } /** Sets the user data for specified \p line to \p d. Does nothing if \p line is out of range. \param[in] line The line of the item whose data() is to be changed. (1 based) \param[in] d The new data to be assigned to the item. (can be NULL) */ void Fl_Browser::data(int line, void* d) { if (line < 1 || line > lines) return; find_line(line)->data = d; } /** Returns height of \p item in pixels. This takes into account embedded \@ codes within the text() label. \param[in] item The item whose height is returned. \returns The height of the item in pixels. \see item_height(), item_width(),\n incr_height(), full_height() */ int Fl_Browser::item_height(void *item) const { FL_BLINE* l = (FL_BLINE*)item; if (l->flags & NOTDISPLAYED) return 0; int hmax = 2; // use 2 to insure we don't return a zero! if (!l->txt[0]) { // For blank lines set the height to exactly 1 line! fl_font(textfont(), textsize()); int hh = fl_height(); if (hh > hmax) hmax = hh; } else { const int* i = column_widths(); // do each column separately as they may all set different fonts: for (char* str = l->txt; str && *str; str++) { Fl_Font font = textfont(); // default font int tsize = textsize(); // default size if ( format_char() ) { // can be NULL while (*str==format_char() && *str++ && *str!=format_char()) { switch (*str++) { case 'l': case 'L': tsize = 24; break; case 'm': case 'M': tsize = 18; break; case 's': tsize = 11; break; case 'b': font = (Fl_Font)(font|FL_BOLD); break; case 'i': font = (Fl_Font)(font|FL_ITALIC); break; case 'f': case 't': font = FL_COURIER; break; case 'B': case 'C': while (isdigit(*str & 255)) str++; break; // skip a color number case 'F': font = (Fl_Font)strtol(str,&str,10); break; case 'S': tsize = (int)strtol(str,&str,10); break; case '.': goto END_FORMAT; } } } END_FORMAT: char* ptr = str; if (ptr && *i++) str = strchr(str, column_char()); else str = NULL; if((!str && *ptr) || (str && ptr < str) || hmax == 2) { fl_font(font, tsize); int hh = fl_height(); if (hh > hmax) hmax = hh; } if (!str || !*str) break; } } if (l->icon && (l->icon->h()+2)>hmax) { hmax = l->icon->h() + 2; // leave 2px above/below } return hmax; // previous version returned hmax+2! } /** Returns width of \p item in pixels. This takes into account embedded \@ codes within the text() label. \param[in] item The item whose width is returned. \returns The width of the item in pixels. \see item_height(), item_width(),\n incr_height(), full_height() */ int Fl_Browser::item_width(void *item) const { FL_BLINE* l=(FL_BLINE*)item; char* str = l->txt; const int* i = column_widths(); int ww = 0; while (*i) { // add up all tab-separated fields char* e; e = strchr(str, column_char()); if (!e) break; // last one occupied by text str = e+1; ww += *i++; } // OK, we gotta parse the string and find the string width... int tsize = textsize(); Fl_Font font = textfont(); int done = 0; if ( format_char() ) { // can be NULL while (*str == format_char_ && str[1] && str[1] != format_char_) { str ++; switch (*str++) { case 'l': case 'L': tsize = 24; break; case 'm': case 'M': tsize = 18; break; case 's': tsize = 11; break; case 'b': font = (Fl_Font)(font|FL_BOLD); break; case 'i': font = (Fl_Font)(font|FL_ITALIC); break; case 'f': case 't': font = FL_COURIER; break; case 'B': case 'C': while (isdigit(*str & 255)) str++; break; // skip a color number case 'F': font = (Fl_Font)strtol(str, &str, 10); break; case 'S': tsize = (int)strtol(str, &str, 10); break; case '.': done = 1; break; } if (done) break; } if (*str == format_char_ && str[1]) str ++; } if (ww==0 && l->icon) ww = l->icon->w(); fl_font(font, tsize); return ww + int(fl_width(str)) + 6; } /** The height of the entire list of all visible() items in pixels. This returns the accumulated height of *all* the items in the browser that are not hidden with hide(), including items scrolled off screen. \returns The accumulated size of all the visible items in pixels. \see item_height(), item_width(),\n incr_height(), full_height() */ int Fl_Browser::full_height() const { return full_height_; } /** The default 'average' item height (including inter-item spacing) in pixels. This currently returns textsize() + 2. \returns The value in pixels. \see item_height(), item_width(),\n incr_height(), full_height() */ int Fl_Browser::incr_height() const { return textsize() + 2 + linespacing(); } /** Draws \p item at the position specified by \p X \p Y \p W \p H. The \p W and \p H values are used for clipping. Should only be called within the context of an FLTK draw(). \param[in] item The item to be drawn \param[in] X,Y,W,H position and size. */ void Fl_Browser::item_draw(void* item, int X, int Y, int W, int H) const { FL_BLINE* l = (FL_BLINE*)item; char* str = l->txt; const int* i = column_widths(); bool firstLoop = true; // for icon while (W > 6) { // do each tab-separated field int w1 = W; // width for this field char* e = 0; // pointer to end of field or null if none if (*i) { // find end of field and temporarily replace with 0 e = strchr(str, column_char()); if (e) {*e = 0; w1 = *i++;} } // Icon drawing code if (firstLoop) { firstLoop = false; if (l->icon) { l->icon->draw(X+2,Y+1); // leave 2px left, 1px above int iconw = l->icon->w()+2; X += iconw; W -= iconw; w1 -= iconw; } } int tsize = textsize(); Fl_Font font = textfont(); Fl_Color lcol = textcolor(); Fl_Align talign = FL_ALIGN_LEFT; // check for all the @-lines recognized by XForms: // #if defined(__GNUC__) // #warning FIXME This maybe needs to be more UTF-8 aware now...? // #endif /*__GNUC__*/ if ( format_char() ) { // can be NULL while (*str == format_char() && *++str && *str != format_char()) { switch (*str++) { case 'l': case 'L': tsize = 24; break; case 'm': case 'M': tsize = 18; break; case 's': tsize = 11; break; case 'b': font = (Fl_Font)(font|FL_BOLD); break; case 'i': font = (Fl_Font)(font|FL_ITALIC); break; case 'f': case 't': font = FL_COURIER; break; case 'c': talign = FL_ALIGN_CENTER; break; case 'r': talign = FL_ALIGN_RIGHT; break; case 'B': if (!(l->flags & SELECTED)) { fl_color((Fl_Color)strtoul(str, &str, 10)); fl_rectf(X, Y, w1, H); } else while (isdigit(*str & 255)) str++; // skip digits break; case 'C': lcol = (Fl_Color)strtoul(str, &str, 10); break; case 'F': font = (Fl_Font)strtol(str, &str, 10); break; case 'N': lcol = FL_INACTIVE_COLOR; break; case 'S': tsize = (int)strtol(str, &str, 10); break; case '-': fl_color(FL_DARK3); fl_line(X+3, Y+H/2, X+w1-3, Y+H/2); fl_color(FL_LIGHT3); fl_line(X+3, Y+H/2+1, X+w1-3, Y+H/2+1); break; case 'u': case '_': fl_color(lcol); fl_line(X+3, Y+H-1, X+w1-3, Y+H-1); break; case '.': goto BREAK; } } } BREAK: fl_font(font, tsize); if (l->flags & SELECTED) lcol = fl_contrast(lcol, selection_color()); if (!active_r()) lcol = fl_inactive(lcol); fl_color(lcol); fl_draw(str, X+3, Y, w1-6, H, e ? Fl_Align(talign|FL_ALIGN_CLIP) : talign, 0, 0); if (!e) break; // no more fields... *e = column_char(); // put the separator back X += w1; W -= w1; str = e+1; } } static const int no_columns[1] = {0}; /** The constructor makes an empty browser. \param[in] X,Y,W,H position and size. \param[in] L label string, may be NULL. */ Fl_Browser::Fl_Browser(int X, int Y, int W, int H, const char *L) : Fl_Browser_(X, Y, W, H, L) { column_widths_ = no_columns; lines = 0; full_height_ = 0; cacheline = 0; format_char_ = '@'; column_char_ = '\t'; first = last = cache = 0; } /** Updates the browser so that \p line is shown at position \p pos. \param[in] line line number. (1 based) \param[in] pos position. \see topline(), middleline(), bottomline() */ void Fl_Browser::lineposition(int line, Fl_Line_Position pos) { if (line<1) line = 1; if (line>lines) line = lines; int p = 0; FL_BLINE* l; for (l=first; l && line>1; l = l->next) { line--; p += item_height(l) + linespacing(); } if (l && (pos == BOTTOM)) p += item_height(l) + linespacing(); int final = p, X, Y, W, H; bbox(X, Y, W, H); switch(pos) { case TOP: break; case BOTTOM: final -= H; break; case MIDDLE: final -= H/2; break; } if (final > (full_height() - H)) final = full_height() -H; vposition(final); } /** Returns the line that is currently visible at the top of the browser. If there is no vertical scrollbar then this will always return 1. \returns The lineno() of the top() of the browser. */ int Fl_Browser::topline() const { return lineno(top()); } /** Sets the default text size (in pixels) for the lines in the browser to \p newSize. This method recalculates all item heights and caches the total height internally for optimization of later item changes. This can be slow if there are many items in the browser. It returns immediately (w/o recalculation) if \p newSize equals the current textsize(). You \e may need to call redraw() to see the effect and to have the scrollbar positions recalculated. You should set the text size \e before populating the browser with items unless you really need to \e change the size later. */ void Fl_Browser::textsize(Fl_Fontsize newSize) { if (newSize == textsize()) return; // avoid recalculation Fl_Browser_::textsize(newSize); new_list(); full_height_ = 0; if (lines == 0) return; for (FL_BLINE* itm=(FL_BLINE *)item_first(); itm; itm=(FL_BLINE *)item_next(itm)) { full_height_ += item_height(itm) + linespacing(); } } /** Removes all the lines in the browser. \see add(), insert(), remove(), swap(int,int), clear() */ void Fl_Browser::clear() { for (FL_BLINE* l = first; l;) { FL_BLINE* n = l->next; free(l); l = n; } full_height_ = 0; first = 0; last = 0; lines = 0; new_list(); } /** Adds a new line to the end of the browser. The text string \p newtext may contain format characters; see format_char() for details. \p newtext is copied using the strdup() function, and can be NULL to make a blank line. The optional void* argument \p d will be the data() for the new item. \param[in] newtext The label text used for the added item \param[in] d Optional user data() for the item (0 if unspecified) \see add(), insert(), remove(), swap(int,int), clear() */ void Fl_Browser::add(const char* newtext, void* d) { insert(lines+1, newtext, d); //Fl_Browser_::display(last); } /** Returns the label text for the specified \p line. Return value can be NULL if \p line is out of range or unset. The parameter \p line is 1 based. \param[in] line The line number of the item whose text is returned. (1 based) \returns The text string (can be NULL) */ const char* Fl_Browser::text(int line) const { if (line < 1 || line > lines) return 0; return find_line(line)->txt; } /** Returns the user data() for specified \p line. Return value can be NULL if \p line is out of range or no user data() was defined. The parameter \p line is 1 based (1 will be the first item in the list). \param[in] line The line number of the item whose data() is returned. (1 based) \returns The user data pointer (can be NULL) */ void* Fl_Browser::data(int line) const { if (line < 1 || line > lines) return 0; return find_line(line)->data; } /** Sets the selection state of the item at \p line to the value \p val. If \p val is not specified, the default is 1 (selects the item). \param[in] line The line number of the item to be changed. (1 based) \param[in] val The new selection state (1=select, 0=de-select). \returns 1 if the state changed, 0 if not. \see select(), selected(), value(), item_select(), item_selected() */ int Fl_Browser::select(int line, int val) { if (line < 1 || line > lines) return 0; return Fl_Browser_::select(find_line(line), val); } /** Returns 1 if specified \p line is selected, 0 if not. \param[in] line The line being checked (1 based) \returns 1 if item selected, 0 if not. \see select(), selected(), value(), item_select(), item_selected() */ int Fl_Browser::selected(int line) const { if (line < 1 || line > lines) return 0; return find_line(line)->flags & SELECTED; } /** Makes \p line visible, and available for selection by user. Opposite of hide(int). This changes the full_height() if the state was changed. redraw() is called automatically if a change occurred. \param[in] line The line to be shown. (1 based) \see show(int), hide(int), display(), visible(), make_visible() */ void Fl_Browser::show(int line) { FL_BLINE* t = find_line(line); if (t->flags & NOTDISPLAYED) { t->flags &= ~NOTDISPLAYED; full_height_ += item_height(t) + linespacing(); if (Fl_Browser_::displayed(t)) redraw(); } } /** Makes \p line invisible, preventing selection by the user. The line can still be selected under program control. This changes the full_height() if the state was changed. When a line is made invisible, lines below it are moved up in the display. redraw() is called automatically if a change occurred. \param[in] line The line to be hidden. (1 based) \see show(int), hide(int), display(), visible(), make_visible() */ void Fl_Browser::hide(int line) { FL_BLINE* t = find_line(line); if (!(t->flags & NOTDISPLAYED)) { full_height_ -= item_height(t) + linespacing(); t->flags |= NOTDISPLAYED; if (Fl_Browser_::displayed(t)) redraw(); } } /** For back compatibility. This calls show(line) if \p val is true, and hide(line) otherwise. If \p val is not specified, the default is 1 (makes the line visible). \see show(int), hide(int), display(), visible(), make_visible() */ void Fl_Browser::display(int line, int val) { if (line < 1 || line > lines) return; if (val) show(line); else hide(line); } /** Returns non-zero if the specified \p line is visible, 0 if hidden. Use show(int), hide(int), or make_visible(int) to change an item's visible state. \param[in] line The line in the browser to be tested. (1 based) \see show(int), hide(int), display(), visible(), make_visible() */ int Fl_Browser::visible(int line) const { if (line < 1 || line > lines) return 0; return !(find_line(line)->flags&NOTDISPLAYED); } /** Returns the line number of the currently selected line, or 0 if none selected. \returns The line number of current selection, or 0 if none selected. \see select(), selected(), value(), item_select(), item_selected() */ int Fl_Browser::value() const { return lineno(selection()); } /** Swap the two items \p a and \p b. Uses swapping() to ensure list updates correctly. \param[in] a,b The two items to be swapped. \see swap(int,int), item_swap() */ void Fl_Browser::swap(FL_BLINE *a, FL_BLINE *b) { if ( a == b || !a || !b) return; // nothing to do swapping(a, b); FL_BLINE *aprev = a->prev; FL_BLINE *anext = a->next; FL_BLINE *bprev = b->prev; FL_BLINE *bnext = b->next; if ( b->prev == a ) { // A ADJACENT TO B if ( aprev ) aprev->next = b; else first = b; b->next = a; a->next = bnext; b->prev = aprev; a->prev = b; if ( bnext ) bnext->prev = a; else last = a; } else if ( a->prev == b ) { // B ADJACENT TO A if ( bprev ) bprev->next = a; else first = a; a->next = b; b->next = anext; a->prev = bprev; b->prev = a; if ( anext ) anext->prev = b; else last = b; } else { // A AND B NOT ADJACENT // handle prev's b->prev = aprev; if ( anext ) anext->prev = b; else last = b; a->prev = bprev; if ( bnext ) bnext->prev = a; else last = a; // handle next's if ( aprev ) aprev->next = b; else first = b; b->next = anext; if ( bprev ) bprev->next = a; else first = a; a->next = bnext; } // Disable cache -- we played around with positions cacheline = 0; cache = 0; } /** Swaps two browser lines \p a and \p b. You must call redraw() to make any changes visible. \param[in] a,b The two lines to be swapped. (both 1 based) \see swap(int,int), item_swap() */ void Fl_Browser::swap(int a, int b) { if (a < 1 || a > lines || b < 1 || b > lines) return; FL_BLINE* ai = find_line(a); FL_BLINE* bi = find_line(b); swap(ai,bi); } /** Set the image icon for \p line to the value \p icon. Caller is responsible for keeping the icon allocated. The \p line is automatically redrawn. \param[in] line The line to be modified. If out of range, nothing is done. \param[in] icon The image icon to be assigned to the \p line. If NULL, any previous icon is removed. */ void Fl_Browser::icon(int line, Fl_Image* icon) { if (line<1 || line > lines) return; FL_BLINE* bl = find_line(line); int old_h = bl->icon ? bl->icon->h()+2 : 0; // init with *old* icon height bl->icon = 0; // remove icon, if any int th = item_height(bl); // height of text only int new_h = icon ? icon->h()+2 : 0; // init with *new* icon height if (th > old_h) old_h = th; if (th > new_h) new_h = th; int dh = new_h - old_h; full_height_ += dh; // do this *always* bl->icon = icon; // set new icon if (dh>0) { redraw(); // icon larger than item? must redraw widget } else { redraw_line(bl); // icon same or smaller? can redraw just this line } replacing(bl,bl); // recalc Fl_Browser_::max_width et al } /** Returns the icon currently defined for \p line. If no icon is defined, NULL is returned. \param[in] line The line whose icon is returned. \returns The icon defined, or NULL if none. */ Fl_Image* Fl_Browser::icon(int line) const { FL_BLINE* l = find_line(line); return(l ? l->icon : NULL); } /** Removes the icon for \p line. It's ok to remove an icon if none has been defined. \param[in] line The line whose icon is to be removed. */ void Fl_Browser::remove_icon(int line) { icon(line,0); } Fl_Hold_Browser::Fl_Hold_Browser(int X,int Y,int W,int H,const char *L) : Fl_Browser(X,Y,W,H,L) { type(FL_HOLD_BROWSER); } Fl_Multi_Browser::Fl_Multi_Browser(int X,int Y,int W,int H,const char *L) : Fl_Browser(X,Y,W,H,L) { type(FL_MULTI_BROWSER); } Fl_Select_Browser::Fl_Select_Browser(int X,int Y,int W,int H,const char *L) : Fl_Browser(X,Y,W,H,L) { type(FL_SELECT_BROWSER); } fltk-1.4.3/src/new.xbm0000644000175000017500000000043115004135251014673 0ustar albrechtalbrecht#define new_width 16 #define new_height 16 static unsigned char new_bits[] = { 0x00, 0x00, 0x78, 0x00, 0x84, 0x00, 0x02, 0x01, 0x01, 0xfe, 0x01, 0x80, 0x31, 0x80, 0x31, 0x80, 0xfd, 0x80, 0xfd, 0x80, 0x31, 0x80, 0x31, 0x80, 0x01, 0x80, 0x01, 0x80, 0xff, 0xff, 0x00, 0x00}; fltk-1.4.3/src/Fl_Clock.cxx0000644000175000017500000001625415004135251015604 0ustar albrechtalbrecht// // Clock widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2017 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include "Fl_System_Driver.H" #include #include #include // Original clock display written by Paul Haeberli at SGI. // Modifications by Mark Overmars for Forms // Further changes by Bill Spitzak for fltk const float hourhand[4][2] = {{-0.5f, 0}, {0, 1.5f}, {0.5f, 0}, {0, -7.0f}}; const float minhand[4][2] = {{-0.5f, 0}, {0, 1.5f}, {0.5f, 0}, {0, -11.5f}}; const float sechand[4][2] = {{-0.1f, 0}, {0, 2.0f}, {0.1f, 0}, {0, -11.5f}}; static void drawhand(double ang,const float v[][2],Fl_Color fill,Fl_Color line) { fl_push_matrix(); fl_rotate(ang); fl_color(fill); fl_begin_polygon(); int i; for (i=0; i<4; i++) fl_vertex(v[i][0],v[i][1]); fl_end_polygon(); fl_color(line); fl_begin_loop(); for (i=0; i<4; i++) fl_vertex(v[i][0],v[i][1]); fl_end_loop(); fl_pop_matrix(); } void Fl_Clock_Output::drawhands(Fl_Color fill, Fl_Color line) { if (!active_r()) { fill = fl_inactive(fill); line = fl_inactive(line); } drawhand(-360*(hour()+minute()/60.0)/12, hourhand, fill, line); drawhand(-360*(minute()+second()/60.0)/60, minhand, fill, line); drawhand(-360*(second()/60.0), sechand, fill, line); } static void rect(double x, double y, double w, double h) { double r = x+w; double t = y+h; fl_begin_polygon(); fl_vertex(x, y); fl_vertex(r, y); fl_vertex(r, t); fl_vertex(x, t); fl_end_polygon(); } /** Draw clock with the given position and size. \param[in] X, Y, W, H position and size */ void Fl_Clock_Output::draw(int X, int Y, int W, int H) { Fl_Color box_color = type()==FL_ROUND_CLOCK ? FL_GRAY : color(); draw_box(box(), X, Y, W, H, box_color); fl_push_matrix(); fl_translate(X+W/2.0-.5, Y+H/2.0-.5); fl_scale((W-1)/28.0, (H-1)/28.0); if (type() == FL_ROUND_CLOCK) { fl_color(active_r() ? color() : fl_inactive(color())); fl_begin_polygon(); fl_circle(0,0,14); fl_end_polygon(); fl_color(active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR)); fl_begin_loop(); fl_circle(0,0,14); fl_end_loop(); } // draw the shadows: if (shadow_) { Fl_Color shadow_color = fl_color_average(box_color, FL_BLACK, 0.5); fl_push_matrix(); fl_translate(0.60, 0.60); drawhands(shadow_color, shadow_color); fl_pop_matrix(); } // draw the tick marks: fl_push_matrix(); fl_color(active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR)); for (int i=0; i<12; i++) { if (i==6) rect(-0.5, 9, 1, 2); else if (i==3 || i==0 || i== 9) rect(-0.5, 9.5, 1, 1); else rect(-0.25, 9.5, .5, 1); fl_rotate(-30); } fl_pop_matrix(); // draw the hands: drawhands(selection_color(), FL_FOREGROUND_COLOR); // color was 54 fl_pop_matrix(); } /** Draw clock with current position and size. */ void Fl_Clock_Output::draw() { draw(x(), y(), w(), h()); draw_label(); } /** Set the displayed time. Set the time in hours, minutes, and seconds. \param[in] H, m, s displayed time \see hour(), minute(), second() */ void Fl_Clock_Output::value(int H, int m, int s) { if (H!=hour_ || m!=minute_ || s!=second_) { hour_ = H; minute_ = m; second_ = s; value_ = (H * 60 + m) * 60 + s; damage(FL_DAMAGE_CHILD); } } /** Set the displayed time. Set the time in seconds since the UNIX epoch (January 1, 1970). \param[in] v seconds since epoch \see value() */ void Fl_Clock_Output::value(ulong v) { value_ = v; struct tm *timeofday; // Some platforms, notably Windows, now use a 64-bit time_t value... time_t vv = (time_t)v; timeofday = localtime(&vv); value(timeofday->tm_hour, timeofday->tm_min, timeofday->tm_sec); } /** Create a new Fl_Clock_Output widget with the given position, size and label. The default clock type is \c FL_SQUARE_CLOCK and the default boxtype is \c FL_UP_BOX. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Clock_Output::Fl_Clock_Output(int X, int Y, int W, int H, const char *L) : Fl_Widget(X, Y, W, H, L) { box(FL_UP_BOX); selection_color(fl_gray_ramp(5)); align(FL_ALIGN_BOTTOM); hour_ = 0; minute_ = 0; second_ = 0; value_ = 0; shadow_ = 1; } //////////////////////////////////////////////////////////////// /** Create an Fl_Clock widget using the given position, size, and label string. The default clock type is FL_SQUARE_CLOCK and the default boxtype is \c FL_UP_BOX. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Clock::Fl_Clock(int X, int Y, int W, int H, const char *L) : Fl_Clock_Output(X, Y, W, H, L) {} /** Create an Fl_Clock widget using the given clock type \p t, position, size, and label string. The default clock type \p t is \c FL_SQUARE_CLOCK. You can set the clock type to FL_ROUND_CLOCK or any other valid clock type. See Fl_Clock_Output widget for applicable values. The default boxtype is \c FL_UP_BOX for \c FL_SQUARE_CLOCK and \c FL_NO_BOX for \c FL_ROUND_CLOCK, if set by the constructor. If you change the clock type with type() later you should also set the boxtype with box(). \param[in] t type of clock: FL_ROUND_CLOCK or FL_SQUARE_CLOCK (0) \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label \see class Fl_Clock_Output */ Fl_Clock::Fl_Clock(uchar t, int X, int Y, int W, int H, const char *L) : Fl_Clock_Output(X, Y, W, H, L) { type(t); box(t==FL_ROUND_CLOCK ? FL_NO_BOX : FL_UP_BOX); } static void tick(void *v) { time_t sec; int usec; Fl::system_driver()->gettime(&sec, &usec); double delta = (1000000 - usec)/1000000.; // time till next second // if current time is just before full second, show that full second // and wait one more second (STR 3516) if (delta < 0.1) { delta += 1.0; sec++; } ((Fl_Clock*)v)->value((ulong)sec); Fl::add_timeout(delta, tick, v); } int Fl_Clock::handle(int event) { switch (event) { case FL_SHOW: tick(this); break; case FL_HIDE: Fl::remove_timeout(tick, this); break; } return Fl_Clock_Output::handle(event); } /** The destructor removes the clock. */ Fl_Clock::~Fl_Clock() { Fl::remove_timeout(tick, this); } /** Create an Fl_Round_Clock widget using the given position, size, and label string. The clock type is \c FL_ROUND_CLOCK and the boxtype is \c FL_NO_BOX. This construcktor is the same as Fl_Clock(FL_ROUND_CLOCK, X, Y, W, H, L). \see Fl_Clock(uchar, int, int, int, int, const char *) \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Round_Clock::Fl_Round_Clock(int X,int Y,int W,int H, const char *L) : Fl_Clock(X, Y, W, H, L) { type(FL_ROUND_CLOCK); box(FL_NO_BOX); } fltk-1.4.3/src/filename_list.cxx0000644000175000017500000000642315004135251016740 0ustar albrechtalbrecht// // Filename list routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Wrapper for scandir with const-correct function prototypes. #include #include #include "Fl_System_Driver.H" #include #include "flstring.h" #include int fl_alphasort(struct dirent **a, struct dirent **b) { return strcmp((*a)->d_name, (*b)->d_name); } int fl_casealphasort(struct dirent **a, struct dirent **b) { return strcasecmp((*a)->d_name, (*b)->d_name); } /** Portable and const-correct wrapper for the scandir() function. For each file in that directory a "dirent" structure is created. The only portable thing about a dirent is that dirent.d_name is the nul-terminated file name. A pointers array to these dirent's is created and a pointer to the array is returned in *list. The number of entries is given as a return value. If there is an error reading the directory a number less than zero is returned, and errno has the reason; errno does not work under Windows. \b Include: \code #include \endcode \param[in] d the name of the directory to list. It does not matter if it has a trailing slash. \param[out] list table containing the resulting directory listing \param[in] sort sorting functor: - fl_alphasort: The files are sorted in ascending alphabetical order; upper and lowercase letters are compared according to their ASCII ordering uppercase before lowercase. - fl_casealphasort: The files are sorted in ascending alphabetical order; upper and lowercase letters are compared equally case is not significant. - fl_casenumericsort: The files are sorted in ascending "alphanumeric" order, where an attempt is made to put unpadded numbers in consecutive order; upper and lowercase letters are compared equally case is not significant. - fl_numericsort: The files are sorted in ascending "alphanumeric" order, where an attempt is made to put unpadded numbers in consecutive order; upper and lowercase letters are compared according to their ASCII ordering - uppercase before lowercase. \return the number of entries if no error, a negative value otherwise. \todo should support returning OS error messages */ int fl_filename_list(const char *d, dirent ***list, Fl_File_Sort_F *sort) { return Fl::system_driver()->filename_list(d, list, sort, NULL, 0); } /** \brief Free the list of filenames that is generated by fl_filename_list(). Free everything that was allocated by a previous call to fl_filename_list(). Use the return values as parameters for this function. \param[in,out] list table containing the resulting directory listing \param[in] n number of entries in the list */ void fl_filename_free_list(struct dirent ***list, int n) { if (n<0) return; int i; for (i = 0; i < n; i ++) { if ((*list)[i]) free((*list)[i]); } free(*list); *list = 0; } fltk-1.4.3/src/Fl_Double_Window.cxx0000644000175000017500000000367515004135251017315 0ustar albrechtalbrecht// // Double-buffered window code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Double_Window implementation. */ #include #include #include #include #include "Fl_Window_Driver.H" // On systems that support double buffering "naturally" the base // Fl_Window class will probably do double-buffer and this subclass // does nothing. Fl_Double_Window::Fl_Double_Window(int W, int H, const char *l) : Fl_Window(W, H, l) { type(FL_DOUBLE_WINDOW); } Fl_Double_Window::Fl_Double_Window(int X, int Y, int W, int H, const char *l) : Fl_Window(X,Y,W,H,l) { type(FL_DOUBLE_WINDOW); } void Fl_Double_Window::show() { Fl_Window::show(); } void Fl_Double_Window::resize(int X,int Y,int W,int H) { int ow = w(); int oh = h(); Fl_Window::resize(X,Y,W,H); Fl_X *myi = Fl_X::flx(this); if (myi && Fl_Window_Driver::driver(this)->other_xid && (ow < w() || oh < h() || is_a_rescale())) Fl_Window_Driver::driver(this)->destroy_double_buffer(); } void Fl_Double_Window::hide() { Fl_X *myi = Fl_X::flx(this); if (myi && Fl_Window_Driver::driver(this)->other_xid) { Fl_Window_Driver::driver(this)->destroy_double_buffer(); } Fl_Window::hide(); } void Fl_Double_Window::flush() { Fl_Window_Driver::driver(this)->flush_double(); } /** The destructor also deletes all the children. This allows a whole tree to be deleted at once, without having to keep a pointer to all the children in the user code. */ Fl_Double_Window::~Fl_Double_Window() { hide(); } fltk-1.4.3/src/fl_engraved_label.cxx0000644000175000017500000000630615004135251017540 0ustar albrechtalbrecht// // Engraved label drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2011 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Drawing code for XForms style engraved & embossed labels #include #include #include // data[] is dx, dy, color triples static void innards(const char *str, int len, int X, int Y, const int data[][3], int n) { Fl_Color c = fl_color(); for (int i = 0; i < n; i++) { fl_color((Fl_Color)(i < n-1 ? data[i][2] : c)); fl_draw(str, len, X+data[i][0], Y+data[i][1]); } fl_color(c); } static void dispatch(const Fl_Label* o, int x, int y, int w, int h, Fl_Align align, void (*callthis)(const char*,int,int,int)) { if ((!o->value || !*(o->value)) && !o->image) return; if (w && h && !fl_not_clipped(x, y, w, h) && (align & FL_ALIGN_INSIDE)) return; if (align & FL_ALIGN_CLIP) fl_push_clip(x, y, w, h); fl_font(o->font, o->size); fl_color((Fl_Color)o->color); fl_draw(o->value, x, y, w, h, align, callthis, o->image, 1, o->spacing); if (align & FL_ALIGN_CLIP) fl_pop_clip(); } // Draw text with shadow static void fl_shadow_label_draw(const char *str, int len, int x, int y) { static const int data[2][3] = {{2,2,FL_DARK3},{0,0,0}}; innards(str, len, x, y, data, 2); } // Implement shadowed text label type static void fl_shadow_label( const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align) { dispatch(o, X, Y, W, H, align, fl_shadow_label_draw); } // Draw text engraved static void fl_engraved_label_draw(const char *str, int len, int x, int y) { static const int data[7][3] = { {1,0,FL_LIGHT3},{1,1,FL_LIGHT3},{0,1,FL_LIGHT3}, {-1,0,FL_DARK3},{-1,-1,FL_DARK3},{0,-1,FL_DARK3}, {0,0,0}}; innards(str, len, x, y, data, 7); } // Implement engraved text label type static void fl_engraved_label( const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align) { dispatch(o, X, Y, W, H, align, fl_engraved_label_draw); } // Draw text embossed static void fl_embossed_label_draw(const char *str, int len, int x, int y) { static const int data[7][3] = { {-1,0,FL_LIGHT3},{-1,-1,FL_LIGHT3},{0,-1,FL_LIGHT3}, {1,0,FL_DARK3},{1,1,FL_DARK3},{0,1,FL_DARK3}, {0,0,0}}; innards(str, len, x, y, data, 7); } // Implement embossed text label type static void fl_embossed_label( const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align) { dispatch(o, X, Y, W, H, align, fl_embossed_label_draw); } Fl_Labeltype fl_define_FL_SHADOW_LABEL() { Fl::set_labeltype(_FL_SHADOW_LABEL, fl_shadow_label, 0); return _FL_SHADOW_LABEL; } Fl_Labeltype fl_define_FL_ENGRAVED_LABEL() { Fl::set_labeltype(_FL_ENGRAVED_LABEL, fl_engraved_label, 0); return _FL_ENGRAVED_LABEL; } Fl_Labeltype fl_define_FL_EMBOSSED_LABEL() { Fl::set_labeltype(_FL_EMBOSSED_LABEL, fl_embossed_label, 0); return _FL_EMBOSSED_LABEL; } fltk-1.4.3/src/Fl_Roller.cxx0000644000175000017500000001256715004135251016013 0ustar albrechtalbrecht// // Roller widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Rapid-App style knob #include #include #include #include int Fl_Roller::handle(int event) { static int ipos; int newpos = horizontal() ? Fl::event_x() : Fl::event_y(); switch (event) { case FL_PUSH: if (Fl::visible_focus()) { Fl::focus(this); redraw(); } handle_push(); ipos = newpos; return 1; case FL_DRAG: handle_drag(clamp(round(increment(previous_value(),newpos-ipos)))); return 1; case FL_RELEASE: handle_release(); return 1; case FL_MOUSEWHEEL : if (Fl::belowmouse()==this) { if (horizontal()) { if (Fl::e_dx!=0) { handle_drag(clamp(round(increment(value(),-Fl::e_dx)))); } } else { if (Fl::e_dy!=0) { handle_drag(clamp(round(increment(value(),-Fl::e_dy)))); } } return 1; } else { return 0; } case FL_KEYBOARD : switch (Fl::event_key()) { case FL_Up: if (horizontal()) return 0; handle_drag(clamp(increment(value(),-1))); return 1; case FL_Down: if (horizontal()) return 0; handle_drag(clamp(increment(value(),1))); return 1; case FL_Left: if (!horizontal()) return 0; handle_drag(clamp(increment(value(),-1))); return 1; case FL_Right: if (!horizontal()) return 0; handle_drag(clamp(increment(value(),1))); return 1; default: return 0; } // break not required because of switch... case FL_FOCUS : case FL_UNFOCUS : if (Fl::visible_focus()) { redraw(); return 1; } else return 0; case FL_ENTER : case FL_LEAVE : return 1; default: return 0; } } void Fl_Roller::draw() { if (damage()&FL_DAMAGE_ALL) draw_box(); int X = x()+Fl::box_dx(box()); int Y = y()+Fl::box_dy(box()); int W = w()-Fl::box_dw(box())-1; int H = h()-Fl::box_dh(box())-1; if (W<=0 || H <=0) return; int offset = step() ? int(value()/step()) : 0; const double ARC = 1.5; // 1/2 the number of radians visible const double delta = .2; // radians per knurl if (horizontal()) { // horizontal one // draw shaded ends of wheel: int h1 = W/4+1; // distance from end that shading starts fl_color(color()); fl_rectf(X+h1,Y,W-2*h1,H); for (int i=0; h1; i++) { fl_color((Fl_Color)(FL_GRAY-i-1)); int h2 = FL_GRAY-i-1 > FL_DARK3 ? 2*h1/3+1 : 0; fl_rectf(X+h2,Y,h1-h2,H); fl_rectf(X+W-h1,Y,h1-h2,H); h1 = h2; } if (active_r()) { // draw ridges: double junk; for (double yy = -ARC+modf(offset*sin(ARC)/(W/2)/delta,&junk)*delta;; yy += delta) { int yy1 = int((sin(yy)/sin(ARC)+1)*W/2); if (yy1 <= 0) continue; else if (yy1 >= W-1) break; fl_color(FL_DARK3); fl_yxline(X+yy1,Y+1,Y+H-1); if (yy < 0) yy1--; else yy1++; fl_color(FL_LIGHT1);fl_yxline(X+yy1,Y+1,Y+H-1); } // draw edges: h1 = W/8+1; // distance from end the color inverts fl_color(FL_DARK2); fl_xyline(X+h1,Y+H-1,X+W-h1); fl_color(FL_DARK3); fl_yxline(X,Y+H,Y,X+h1); fl_xyline(X+W-h1,Y,X+W); fl_color(FL_LIGHT2); fl_xyline(X+h1,Y-1,X+W-h1); fl_yxline(X+W,Y,Y+H,X+W-h1); fl_xyline(X+h1,Y+H,X); } } else { // vertical one // draw shaded ends of wheel: int h1 = H/4+1; // distance from end that shading starts fl_color(color()); fl_rectf(X,Y+h1,W,H-2*h1); for (int i=0; h1; i++) { fl_color((Fl_Color)(FL_GRAY-i-1)); int h2 = FL_GRAY-i-1 > FL_DARK3 ? 2*h1/3+1 : 0; fl_rectf(X,Y+h2,W,h1-h2); fl_rectf(X,Y+H-h1,W,h1-h2); h1 = h2; } if (active_r()) { // draw ridges: double junk; for (double yy = -ARC+modf(offset*sin(ARC)/(H/2)/delta,&junk)*delta; ; yy += delta) { int yy1 = int((sin(yy)/sin(ARC)+1)*H/2); if (yy1 <= 0) continue; else if (yy1 >= H-1) break; fl_color(FL_DARK3); fl_xyline(X+1,Y+yy1,X+W-1); if (yy < 0) yy1--; else yy1++; fl_color(FL_LIGHT1);fl_xyline(X+1,Y+yy1,X+W-1); } // draw edges: h1 = H/8+1; // distance from end the color inverts fl_color(FL_DARK2); fl_yxline(X+W-1,Y+h1,Y+H-h1); fl_color(FL_DARK3); fl_xyline(X+W,Y,X,Y+h1); fl_yxline(X,Y+H-h1,Y+H); fl_color(FL_LIGHT2); fl_yxline(X,Y+h1,Y+H-h1); fl_xyline(X,Y+H,X+W,Y+H-h1); fl_yxline(X+W,Y+h1,Y); } } if (Fl::focus() == this) draw_focus(FL_THIN_UP_FRAME, x(), y(), w(), h()); } /** Creates a new Fl_Roller widget using the given position, size, and label string. The default boxtype is FL_NO_BOX.

Inherited destructor destroys the valuator. */ Fl_Roller::Fl_Roller(int X,int Y,int W,int H,const char* L) : Fl_Valuator(X,Y,W,H,L) { box(FL_UP_BOX); step(1,1000); } fltk-1.4.3/src/fl_write_png.cxx0000644000175000017500000001147115004135251016603 0ustar albrechtalbrecht// // Fl_PNG_Image support functions for the Fast Light Tool Kit (FLTK). // // Copyright 2005-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include // fl_fopen() #include #include // hack to restore "configure --enable-x11" on macOS ≥ 11 // PNG library include files extern "C" { #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) #include #ifdef HAVE_PNG_H #include #else #include #endif // HAVE_PNG_H #endif // HAVE_LIBPNG && HAVE_LIBZ } // extern "C" /** \file fl_write_png.cxx PNG image support functions. */ /** Write an RGB(A) image to a PNG image file. This is a very basic and restricted function to create a PNG image file from an RGB image (Fl_RGB_Image). The image data must be aligned w/o gaps, i.e. ld() \b MUST be zero or equal to data_w() * data_h(). The image file is always written with the original image size data_w() and data_h(), even if the image has been scaled. Image depth 1 (gray), 2 (gray + alpha channel), 3 (RGB) and 4 (RGBA) are supported. \note Currently there is no error handling except for errors when opening the file. This may be changed in the future. \param[in] filename Output filename, extension should be '.png' \param[in] img RGB image to be written \return success (0) or error code: negative values are errors \retval 0 success, file has been written \retval -1 png or zlib library not available \retval -2 file open error \see fl_write_png(const char *, int, int, int, const unsigned char *) */ int fl_write_png(const char *filename, Fl_RGB_Image *img) { return fl_write_png(filename, img->data()[0], img->data_w(), img->data_h(), img->d(), img->ld()); } /** Write raw image data to a PNG image file. \see fl_write_png(const char *filename, const char *pixels, int w, int h, int d, int ld) */ int fl_write_png(const char *filename, const unsigned char *pixels, int w, int h, int d, int ld) { return fl_write_png(filename, (const char *)pixels, w, h, d, ld); } /** Write raw image data to a PNG image file. This is a very basic and restricted function to create a PNG image file from raw image data, e.g. a screenshot. The image data must be aligned w/o gaps after each row (ld = 0 or ld = w * d) or \p ld must be the total length of each row, i.e. w * d + gapsize. If ld == 0 then ld = w * d is assumed. The total data size must be (w * d + gapsize) * h = ld' * h where ld' = w * d if ld == 0. For further restrictions and return values please see fl_write_png(const char *filename, Fl_RGB_Image *img). \param[in] filename Output filename, extension should be '.png' \param[in] pixels Image data \param[in] w Image data width \param[in] h Image data height \param[in] d Image depth: 1 = GRAY, 2 = GRAY + alpha, 3 = RGB, 4 = RGBA \param[in] ld Line delta: default (0) = w * d \return success (0) or error code, see ... \see fl_write_png(const char *filename, Fl_RGB_Image *img) */ int fl_write_png(const char *filename, const char *pixels, int w, int h, int d, int ld) { #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) FILE *fp; int color_type; if ((fp = fl_fopen(filename, "wb")) == NULL) { return -2; } switch (d) { case 1: color_type = PNG_COLOR_TYPE_GRAY; break; case 2: color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; case 3: color_type = PNG_COLOR_TYPE_RGB; break; case 4: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break; default: color_type = PNG_COLOR_TYPE_RGB; } if (ld == 0) ld = w * d; png_structp pptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); png_infop iptr = png_create_info_struct(pptr); png_bytep ptr = (png_bytep)pixels; png_init_io(pptr, fp); png_set_IHDR(pptr, iptr, w, h, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_sRGB(pptr, iptr, PNG_sRGB_INTENT_PERCEPTUAL); png_write_info(pptr, iptr); for (int i = 0; i < h; i++, ptr += ld) { png_write_row(pptr, ptr); } png_write_end(pptr, iptr); png_destroy_write_struct(&pptr, &iptr); fclose(fp); return 0; #else return -1; #endif } fltk-1.4.3/src/Fl_BMP_Image.cxx0000644000175000017500000003676515004135251016302 0ustar albrechtalbrecht// // Fl_BMP_Image class for the Fast Light Tool Kit (FLTK). // // Copyright 2011-2022 by Bill Spitzak and others. // Copyright 1997-2010 by Easy Software Products. // Image support by Matthias Melcher, Copyright 2000-2009. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // Include necessary header files... // #include #include "Fl_Image_Reader.h" #include #include #include #include // // BMP definitions... // #ifndef BI_RGB # define BI_RGB 0 // No compression - straight BGR data # define BI_RLE8 1 // 8-bit run-length compression # define BI_RLE4 2 // 4-bit run-length compression # define BI_BITFIELDS 3 // RGB bitmap with RGB masks #endif // !BI_RGB /** This constructor loads the named BMP image from the given BMP filename. The destructor frees all memory and server resources that are used by the image. Use Fl_Image::fail() to check if Fl_BMP_Image failed to load. fail() returns ERR_FILE_ACCESS if the file could not be opened or read, ERR_FORMAT if the BMP format could not be decoded, and ERR_NO_IMAGE if the image could not be loaded for another reason. \param[in] filename a full path and name pointing to a BMP file. \see Fl_BMP_Image::Fl_BMP_Image(const char* imagename, const unsigned char *data, const long length = -1); */ Fl_BMP_Image::Fl_BMP_Image(const char *filename) // I - File to read : Fl_RGB_Image(0,0,0) { Fl_Image_Reader rdr; if (rdr.open(filename) == -1) { ld(ERR_FILE_ACCESS); } else { load_bmp_(rdr); } } /** This constructor loads a BMP image from memory. Construct an image from a block of memory inside the application. Fluid offers "binary data" chunks as a great way to add image data into the C++ source code. \p imagename can be NULL. If a name is given, the image is added to the list of shared images and will be available by that name. The destructor frees all memory and server resources that are used by the image. The (new and optional) third parameter \p length \b should be used so buffer overruns (i.e. truncated images) can be checked. See note below. If \p length is not used - it defaults to -1 (unlimited size) - buffer overruns will not be checked. \note The optional parameter \p length is available since FLTK 1.4.0. Not using it is deprecated and old code should be modified to use it. This parameter will likely become mandatory in a future FLTK version. Use Fl_Image::fail() to check if Fl_BMP_Image failed to load. fail() returns ERR_FILE_ACCESS if the image could not be read from memory, ERR_FORMAT if the BMP format could not be decoded, and ERR_NO_IMAGE if the image could not be loaded for another reason. \param[in] imagename A name given to this image or NULL \param[in] data Pointer to the start of the BMP image in memory. \param[in] length Length of the BMP image in memory. \see Fl_BMP_Image::Fl_BMP_Image(const char *filename) \see Fl_Shared_Image */ Fl_BMP_Image::Fl_BMP_Image(const char *imagename, const unsigned char *data, const long length) : Fl_RGB_Image(0,0,0) { Fl_Image_Reader rdr; int retval = (length < 0 ? rdr.open(imagename, data) : rdr.open(imagename, data, (size_t)length)); if (retval == -1) { ld(ERR_FILE_ACCESS); } else { load_bmp_(rdr); } } /* This macro can be used to check for end of file (EOF) or other read errors. In case of an error or EOF an error message is issued and the image loading is terminated with error code ERR_FORMAT. */ #define CHECK_ERROR \ if (rdr.error()) { \ Fl::error("[%d] Fl_BMP_Image: %s - unexpected EOF or read error at offset %ld", \ __LINE__, rdr.name(), rdr.tell()); \ ld(ERR_FORMAT); \ return; \ } /* This method reads BMP image data and creates an RGB or RGBA image. The BMP format supports only 1 bit for alpha. To avoid code duplication, we use an Fl_Image_Reader that reads data from either a file or from memory. */ void Fl_BMP_Image::load_bmp_(Fl_Image_Reader &rdr, int ico_height, int ico_width) { int info_size, // Size of info header width, // Width of image (pixels) height, // Height of image (pixels) depth, // Depth of image (bits) bDepth = 3, // Depth of image (bytes) compression, // Type of compression colors_used, // Number of colors used x, y, // Looping vars color, // Color of RLE pixel repcount, // Number of times to repeat temp, // Temporary color align, // Alignment bytes dataSize, // number of bytes in image data set row_order, // 1 = normal; -1 = flipped row order start_y, // Beginning Y end_y; // Ending Y long offbits = 0; // Offset to image data uchar bit, // Bit in image byte; // Byte in image uchar *ptr; // Pointer into pixels uchar colormap[256][3]; // Colormap uchar havemask; // Single bit mask follows image data int use_5_6_5; // Use 5:6:5 for R:G:B channels in 16 bit images // Implementation notes: Reader is already open at this point. // Use local variables (width, height) until image is complete // so we can easily use CHECK_ERROR to return with ld(ERR_FORMAT). // We use CHECK_ERROR only at some essential points. w(0); h(0); d(0); ld(0); // make sure these are all zero // Get the header... if (ico_height < 1) { byte = rdr.read_byte(); // Check "BM" sync chars bit = rdr.read_byte(); if (byte != 'B' || bit != 'M') { ld(ERR_FORMAT); return; } rdr.read_dword(); // Skip size rdr.read_word(); // Skip reserved stuff rdr.read_word(); offbits = (long)rdr.read_dword();// Read offset to image data } // Then the bitmap information... info_size = rdr.read_dword(); CHECK_ERROR // printf("offbits = %ld, info_size = %d\n", offbits, info_size); havemask = 0; row_order = -1; use_5_6_5 = 0; if (info_size < 40) { // Old Windows/OS2 BMP header... width = rdr.read_word(); height = rdr.read_word(); rdr.read_word(); depth = rdr.read_word(); compression = BI_RGB; colors_used = 0; repcount = info_size - 12; } else { if (ico_height > 0 && ico_width > 0) { rdr.read_long(); rdr.read_long(); width = ico_width; height = ico_height; } else { // New BMP header... width = rdr.read_long(); w(width); // If the height is negative, the row order is flipped temp = rdr.read_long(); if (temp < 0) row_order = 1; height = abs(temp); } rdr.read_word(); depth = rdr.read_word(); compression = rdr.read_dword(); dataSize = rdr.read_dword(); rdr.read_long(); rdr.read_long(); colors_used = rdr.read_dword(); rdr.read_dword(); repcount = info_size - 40; if (!compression && depth >= 8 && width > 32/depth) { int Bpp = depth/8; int maskSize = (((width*Bpp+3)&~3)*height) + (((((width+7)/8)+3)&~3)*height); if (maskSize == 2*dataSize) { havemask = 1; height = height/2; bDepth = 4; } } } CHECK_ERROR // printf("width =%4d, height =%4d, depth = %2d, compression = %d, colors_used = %3d, repcount = %2d, row_order = %2d\n", // width, height, depth, compression, colors_used, repcount, row_order); // Skip remaining header bytes... if (repcount > 0) rdr.skip(repcount); CHECK_ERROR // Check header data... if (!width || !height || !depth) { ld(ERR_FORMAT); return; } // Get colormap... if (colors_used == 0 && depth <= 8) colors_used = 1 << depth; for (int i = 0; i < colors_used; i++) { // Read BGR color... colormap[i][0] = rdr.read_byte(); colormap[i][1] = rdr.read_byte(); colormap[i][2] = rdr.read_byte(); // Skip pad byte for new BMP files... if (info_size > 12) rdr.read_byte(); } CHECK_ERROR // Read first dword of colormap. It tells us if 5:5:5 or 5:6:5 for 16 bit if (depth == 16) use_5_6_5 = (rdr.read_dword() == 0xf800); // Set byte depth for RGBA images if (depth == 32) bDepth = 4; // Setup image and buffers... if (offbits) rdr.seek((unsigned int)offbits); CHECK_ERROR if (((size_t)width) * height * bDepth > max_size() ) { Fl::warning("BMP file \"%s\" is too large!\n", rdr.name()); ld(ERR_FORMAT); return; } array = new uchar[width * height * bDepth]; alloc_array = 1; // Read the image data... color = 0; repcount = 0; align = 0; byte = 0; temp = 0; if (row_order < 0) { start_y = height - 1; end_y = -1; } else { start_y = 0; end_y = height; } for (y = start_y; y != end_y; y += row_order) { ptr = (uchar *)array + y * width * bDepth; switch (depth) { case 1 : // Bitmap for (x = width, bit = 128; x > 0; x --) { if (bit == 128) byte = rdr.read_byte(); if (byte & bit) { *ptr++ = colormap[1][2]; *ptr++ = colormap[1][1]; *ptr++ = colormap[1][0]; } else { *ptr++ = colormap[0][2]; *ptr++ = colormap[0][1]; *ptr++ = colormap[0][0]; } if (bit > 1) bit >>= 1; else bit = 128; } // Read remaining bytes to align to 32 bits... for (temp = (width + 7) / 8; temp & 3; temp ++) { rdr.read_byte(); } break; case 4 : // 16-color for (x = width, bit = 0xf0; x > 0; x --) { // Get a new repcount as needed... if (repcount == 0) { if (compression != BI_RLE4) { repcount = 2; color = -1; } else { while (align > 0) { align --; rdr.read_byte(); } if ((repcount = rdr.read_byte()) == 0) { if ((repcount = rdr.read_byte()) == 0) { // End of line... x ++; continue; } else if (repcount == 1) { // End of image... break; } else if (repcount == 2) { // Delta... repcount = rdr.read_byte() * rdr.read_byte() * width; color = 0; } else { // Absolute... color = -1; align = ((4 - (repcount & 3)) / 2) & 1; } } else { color = rdr.read_byte(); } } } // Get a new color as needed... repcount --; // Extract the next pixel... if (bit == 0xf0) { // Get the next color byte as needed... if (color < 0) temp = rdr.read_byte(); else temp = color; // Copy the color value... *ptr++ = colormap[(temp >> 4) & 15][2]; *ptr++ = colormap[(temp >> 4) & 15][1]; *ptr++ = colormap[(temp >> 4) & 15][0]; bit = 0x0f; } else { bit = 0xf0; // Copy the color value... *ptr++ = colormap[temp & 15][2]; *ptr++ = colormap[temp & 15][1]; *ptr++ = colormap[temp & 15][0]; } } CHECK_ERROR if (!compression) { // Read remaining bytes to align to 32 bits... for (temp = (width + 1) / 2; temp & 3; temp ++) { rdr.read_byte(); } } break; case 8 : // 256-color for (x = width; x > 0; x --) { // Get a new repcount as needed... if (compression != BI_RLE8) { repcount = 1; color = -1; } if (repcount == 0) { while (align > 0) { align --; rdr.read_byte(); } CHECK_ERROR if ((repcount = rdr.read_byte()) == 0) { if ((repcount = rdr.read_byte()) == 0) { // End of line... x ++; continue; } else if (repcount == 1) { // End of image... break; } else if (repcount == 2) { // Delta... repcount = rdr.read_byte() * rdr.read_byte() * width; color = 0; } else { // Absolute... color = -1; align = (2 - (repcount & 1)) & 1; } } else { color = rdr.read_byte(); } } CHECK_ERROR // Get a new color as needed... if (color < 0) temp = rdr.read_byte(); else temp = color; repcount --; // Copy the color value... *ptr++ = colormap[temp][2]; *ptr++ = colormap[temp][1]; *ptr++ = colormap[temp][0]; if (havemask) ptr++; } if (!compression) { // Read remaining bytes to align to 32 bits... for (temp = width; temp & 3; temp ++) { rdr.read_byte(); } } break; case 16 : // 16-bit 5:5:5 or 5:6:5 RGB for (x = width; x > 0; x --, ptr += bDepth) { uchar b = rdr.read_byte(), a = rdr.read_byte() ; if (use_5_6_5) { ptr[2] = (uchar)(( b << 3 ) & 0xf8); ptr[1] = (uchar)(((a << 5) & 0xe0) | ((b >> 3) & 0x1c)); ptr[0] = (uchar)(a & 0xf8); } else { ptr[2] = (uchar)((b << 3) & 0xf8); ptr[1] = (uchar)(((a << 6) & 0xc0) | ((b >> 2) & 0x38)); ptr[0] = (uchar)((a<<1) & 0xf8); } } // Read remaining bytes to align to 32 bits... for (temp = width * 2; temp & 3; temp ++) { rdr.read_byte(); } break; case 24 : // 24-bit RGB for (x = width; x > 0; x --, ptr += bDepth) { ptr[2] = rdr.read_byte(); ptr[1] = rdr.read_byte(); ptr[0] = rdr.read_byte(); } // Read remaining bytes to align to 32 bits... for (temp = width * 3; temp & 3; temp ++) { rdr.read_byte(); } break; case 32 : // 32-bit RGBA for (x = width; x > 0; x --, ptr += bDepth) { ptr[2] = rdr.read_byte(); ptr[1] = rdr.read_byte(); ptr[0] = rdr.read_byte(); ptr[3] = rdr.read_byte(); } break; } CHECK_ERROR } if (havemask) { for (y = height - 1; y >= 0; y --) { ptr = (uchar *)array + y * width * bDepth + 3; for (x = width, bit = 128; x > 0; x --, ptr += bDepth) { if (bit == 128) byte = rdr.read_byte(); if (byte & bit) *ptr = 0; else *ptr = 255; if (bit > 1) bit >>= 1; else bit = 128; } // Read remaining bytes to align to 32 bits... for (temp = (width + 7) / 8; temp & 3; temp ++) rdr.read_byte(); } } CHECK_ERROR // Success: set image attributes and return // File is closed when returning... w(width); h(height); d(bDepth); ld(0); } // load_bmp_() fltk-1.4.3/src/allfiles.xbm0000644000175000017500000000045015004135251015676 0ustar albrechtalbrecht#define allfiles_width 16 #define allfiles_height 16 static unsigned char allfiles_bits[] = { 0xfc, 0x3f, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0x84, 0x21, 0xa4, 0x25, 0xc4, 0x23, 0xf4, 0x2f, 0xf4, 0x2f, 0xc4, 0x23, 0xa4, 0x25, 0x84, 0x21, 0x04, 0x20, 0x04, 0x20, 0x04, 0x20, 0xfc, 0x3f}; fltk-1.4.3/src/gl_start.cxx0000644000175000017500000000714715004135251015750 0ustar albrechtalbrecht// // OpenGL context routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // You MUST use gl_visual() to select the default visual before doing // show() of any windows. Mesa will crash if you try to use a visual // not returned by glxChooseVisual. // This does not work with Fl_Double_Window's! It will try to draw // into the front buffer. Depending on the system this will either // crash or do nothing (when pixmaps are being used as back buffer // and GL is being done by hardware), work correctly (when GL is done // with software, such as Mesa), or draw into the front buffer and // be erased when the buffers are swapped (when double buffer hardware // is being used) #include #if HAVE_GL #include #include #include #include class Fl_Gl_Choice; #include #include "Fl_Gl_Window_Driver.H" /** \cond DriverDev \addtogroup DriverDeveloper \{ */ GLContext Fl_Gl_Window_Driver::gl_start_context; /** \} \endcond */ static int clip_state_number=-1; static int pw, ph; float gl_start_scale = 1; static Fl_Gl_Choice* gl_choice = NULL; /** Creates an OpenGL context */ void gl_start() { gl_start_scale = Fl_Display_Device::display_device()->driver()->scale(); if (!Fl_Gl_Window_Driver::gl_start_context) { if (!gl_choice) Fl::gl_visual(0); Fl_Gl_Window_Driver::gl_start_context = Fl_Gl_Window_Driver::global()->create_gl_context(Fl_Window::current(), gl_choice); } Fl_Gl_Window_Driver::global()->set_gl_context(Fl_Window::current(), Fl_Gl_Window_Driver::gl_start_context); Fl_Gl_Window_Driver::global()->gl_start(); if (pw != int(Fl_Window::current()->w() * gl_start_scale) || ph != int(Fl_Window::current()->h() * gl_start_scale)) { pw = int(Fl_Window::current()->w() * gl_start_scale); ph = int(Fl_Window::current()->h() * gl_start_scale); glLoadIdentity(); glViewport(0, 0, pw, ph); glOrtho(0, Fl_Window::current()->w(), 0, Fl_Window::current()->h(), -1, 1); glDrawBuffer(GL_FRONT); } if (clip_state_number != fl_graphics_driver->fl_clip_state_number) { clip_state_number = fl_graphics_driver->fl_clip_state_number; int x = 0, y = 0, w = 0, h = 0; if (fl_clip_box(0, 0, Fl_Window::current()->w(), Fl_Window::current()->h(), x, y, w, h)) { fl_clip_region(Fl_Graphics_Driver::default_driver().XRectangleRegion(x,y,w,h)); glScissor(int(x*gl_start_scale), int((Fl_Window::current()->h()-(y+h))*gl_start_scale), int(w*gl_start_scale), int(h*gl_start_scale)); glEnable(GL_SCISSOR_TEST); } else { glDisable(GL_SCISSOR_TEST); } } Fl_Display_Device::display_device()->driver()->scale(1); } /** Releases an OpenGL context */ void gl_finish() { glFlush(); Fl_Gl_Window_Driver::global()->waitGL(); Fl_Display_Device::display_device()->driver()->scale(gl_start_scale); gl_start_scale = 1; } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ void Fl_Gl_Window_Driver::gl_visual(Fl_Gl_Choice *c) { gl_choice = c; } int Fl::gl_visual(int mode, int *alist) { Fl_Gl_Choice *c = Fl_Gl_Window_Driver::global()->find(mode,alist); if (!c) return 0; Fl_Gl_Window_Driver::global()->gl_visual(c); return 1; } /** \} \endcond */ #endif // HAVE_GL fltk-1.4.3/src/cgdebug.h0000644000175000017500000001105115004135251015143 0ustar albrechtalbrecht// // OS X Core Graphics debugging help for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // This file allows easier debugging of Mac OS X Core Graphics // code. This file is normally not included into any FLTK builds, // but since it has proven to be tremendously useful in debugging // the FLTK port to "Quartz", I decided to add this file in case // more bugs show up. // // This header is activated by adding the following // line to "config.h" // #include "src/cgdebug.h" // // Running "./configure" will remove this line from "config.h". // // When used erreanously, Core Graphics prints warnings to // stderr. This is helpful, however it is not possible to // associate a line number or source file with the warning message. // This headr file outputs a trace of CG calls, interweaveing // them with CG warnings. // // Matthias #ifndef CGDEBUG #define CGDEBUG #include #include //+BitmapContextCreate //+BitmapContextGetData // ClipCGContextToRegion // QDBeginCGContext // QDEndCGContext //+AddArc //+AddLineToPoint // ClipToRect // ClosePath //+ConcatCTM //+DrawImage // FillPath // FillRect // Flush //+GetCTM // MoveToPoint //+Release // RestoreGState // SaveGState //+ScaleCTM //+SetLineCap //+SetLineDash //+SetLineJoin //+SetLineWidth //+SetRGBFillColor //+SetRGBStrokeColor //+SetShouldAntialias //+SetTextMatrix //+StrokePath //+TranslateCTM inline OSStatus dbgLocation(const char *file, int line) { fprintf(stderr, "%s:%d ", file, line); return 0; } inline OSStatus dbgEndl() { fprintf(stderr, "\n"); return 0; } inline void dbgCGContextClipToRect(CGContextRef a, CGRect b) { CGContextClipToRect(a, b); } #define CGContextClipToRect(a, b) { \ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \ dbgCGContextClipToRect(a, b); \ fprintf(stderr, "\n"); } inline void dbgCGContextFillRect(CGContextRef a, CGRect b) { CGContextFillRect(a, b); } #define CGContextFillRect(a, b) { \ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \ dbgCGContextFillRect(a, b); \ fprintf(stderr, "\n"); } inline OSStatus dbgQDEndCGContext(CGrafPtr a, CGContextRef *b) { return QDEndCGContext(a, b); } #define QDEndCGContext(a, b) ( \ dbgLocation(__FILE__, __LINE__) + \ dbgQDEndCGContext(a, b) + \ dbgEndl() ) inline OSStatus dbgQDBeginCGContext(CGrafPtr a, CGContextRef *b) { return QDBeginCGContext(a, b); } #define QDBeginCGContext(a, b) ( \ dbgLocation(__FILE__, __LINE__) + \ dbgQDBeginCGContext(a, b) + \ dbgEndl() ) inline void dbgClipCGContextToRegion(CGContextRef a, const Rect *b, RgnHandle c) { ClipCGContextToRegion(a, b, c); } #define ClipCGContextToRegion(a, b, c) { \ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \ dbgClipCGContextToRegion(a, b, c); \ fprintf(stderr, "\n"); } inline void dbgCGContextMoveToPoint(CGContextRef context, float x, float y) { CGContextMoveToPoint(context, x, y); } #define CGContextMoveToPoint(a, b, c) { \ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \ dbgCGContextMoveToPoint(a, b, c); \ fprintf(stderr, "\n"); } inline void dbgCGContextFillPath(CGContextRef context) { CGContextFillPath(context); } #define CGContextFillPath(a) { \ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \ dbgCGContextFillPath(a); \ fprintf(stderr, "\n"); } inline void dbgCGContextClosePath(CGContextRef context) { CGContextClosePath(context); } #define CGContextClosePath(a) { \ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \ dbgCGContextClosePath(a); \ fprintf(stderr, "\n"); } inline void dbgCGContextFlush(CGContextRef context) { CGContextFlush(context); } #define CGContextFlush(a) { \ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \ dbgCGContextFlush(a); \ fprintf(stderr, "\n"); } inline void dbgCGContextSaveGState(CGContextRef context) { CGContextSaveGState(context); } #define CGContextSaveGState(a) { \ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \ dbgCGContextSaveGState(a); \ fprintf(stderr, "\n"); } inline void dbgCGContextRestoreGState(CGContextRef context) { CGContextRestoreGState(context); } #define CGContextRestoreGState(a) { \ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \ dbgCGContextRestoreGState(a); \ fprintf(stderr, "\n"); } #endif fltk-1.4.3/src/fl_oxy.h0000644000175000017500000000160015004135251015042 0ustar albrechtalbrecht// // "Oxy" Scheme drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 2011 by Dmitrij K. aka "kdiman" // Copyright 2012-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please report all bugs and problems on the following page: // // https://www.fltk.org/str.php // #ifndef fl_oxy_h #define fl_oxy_h #include // draw an arrow GUI element for the 'oxy' scheme // // bb bounding box // t arrow type // o orientation // c arrow color extern FL_EXPORT void oxy_arrow(Fl_Rect bb, Fl_Arrow_Type t, Fl_Orientation o, Fl_Color col); #endif // fl_oxy_h fltk-1.4.3/src/Fl_Device.cxx0000644000175000017500000002012515004135251015740 0ustar albrechtalbrecht// // implementation of classes Fl_Surface_Device and Fl_Display_Device for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include /* Inheritance diagram. +- Fl_Surface_Device: any kind of surface that we can draw onto -> uses an Fl_Graphics_Driver | +- Fl_Display_Device: some kind of video device (one object per app) +- Fl_OpenGL_Display_Device: supports adding FLTK child widgets to an Fl_Gl_Window +- Fl_Widget_Surface: any FLTK widget can be drawn to it | +- Fl_Copy_Surface: draw into the clipboard (in vectorial form if the platform supports it) +- Fl_Copy_Surface_Driver: helper class interfacing FLTK with draw-to-clipboard operations | +- Fl_..._Copy_Surface_Driver: platform-specific implementation of Fl_Copy_Surface_Driver +- Fl_Image_Surface: draw into an RGB Image +- Fl_Image_Surface_Driver: helper class interfacing FLTK with draw-to-image operations | +- Fl_..._Image_Surface_Driver: platform-specific implementation of Fl_Image_Surface_Driver +- Fl_EPS_File_Surface: draw into an Encapsulated PostScript (.eps) file +- Fl_SVG_File_Surface: draw into a Scalable Vector Graphics (.svg) file +- Fl_Paged_Device: output to a page-structured surface | +- Fl_Printer: user can instantiate this to gain access to a printer +- Fl_WinAPI_Printer_Driver: Windows-specific helper class interfacing FLTK with print operations +- Fl_Cocoa_Printer_Driver: macOS-specific helper class interfacing FLTK with print operations +- Fl_PostScript_File_Device: draw into a PostScript file | +- Fl_Posix_Printer_Driver: Fl_Printer uses that under Posix platforms +- Fl_GTK_Printer_Driver: Fl_Printer uses that under Posix+GTK platforms +- Fl_PDF_File_Surface: draw into a PDF file +- Fl_PDF_GDI_File_Surface: Windows-specific helper class interfacing FLTK with PDF operations +- Fl_PDF_Pango_File_Surface: Linux/Unix-specific helper class interfacing FLTK with PDF operations +- Fl_PDF_Cocoa_File_Surface: macOS-specific helper class interfacing FLTK with PDF operations +- Fl_Graphics_Driver -> directed to an Fl_Surface_Device object | +- Fl_PostScript_Graphics_Driver: platform-independent graphics driver for PostScript/EPS drawing +- Fl_SVG_Graphics_Driver: platform-independent graphics driver for Scalable Vector Graphics drawing +- Fl_Quartz_Graphics_Driver: platform-specific graphics driver (MacOS) +- Fl_Quartz_Printer_Graphics_Driver: MacOS-specific, for drawing to printers +- Fl_Scalable_Graphics_Driver: helper class to support GUI scaling +- Fl_Xlib_Graphics_Driver: X11-specific graphics driver +- Fl_GDI_Graphics_Driver: Windows-specific graphics driver +- Fl_GDIplus_Graphics_Driver: overrides oblique lines, arcs and circles +- Fl_GDI_Printer_Graphics_Driver: overrides a few member functions especially for output to printer +- Fl_Cairo_Graphics_Driver: full FLTK drawing API based on Cairo and Pango +- Fl_Wayland_Graphics_Driver: Wayland-specific graphics driver +- Fl_X11_Cairo_Graphics_Driver: used by X11 leg of hybrid Wayland/X11 platform +- Fl_PostScript_Graphics_Driver: for PostScript drawing with X11+Pango platform +- Fl_OpenGL_Graphics_Driver: draw to an Fl_Gl_Window */ /** Make this surface the current drawing surface. This surface will receive all future graphics requests. Since FLTK 1.4.0 the preferred API to change the current drawing surface is Fl_Surface_Device::push_current( ) / Fl_Surface_Device::pop_current(). \note It is recommended to use this function only as follows : - The current drawing surface is the display; - make current another surface, e.g., an Fl_Printer or an Fl_Image_Surface object, calling set_current() on this object; - draw to that surface; - make the display current again with Fl_Display_Device::display_device()->set_current();\n don't do any other call to set_current() before this one. Other scenarios of drawing surface changes should be performed via Fl_Surface_Device::push_current() and Fl_Surface_Device::pop_current(). */ void Fl_Surface_Device::set_current(void) { if (surface_) surface_->end_current(); fl_graphics_driver = pGraphicsDriver; surface_ = this; pGraphicsDriver->global_gc(); driver()->set_current_(); } Fl_Surface_Device* Fl_Surface_Device::surface_; // the current target surface of graphics operations /** Is this surface the current drawing surface? */ bool Fl_Surface_Device::is_current() { return surface_ == this; } Fl_Surface_Device::~Fl_Surface_Device() { if (surface_ == this) surface_ = NULL; } /** A constructor that sets the graphics driver used by the display */ Fl_Display_Device::Fl_Display_Device(Fl_Graphics_Driver *graphics_driver) : Fl_Surface_Device(graphics_driver) { this->set_current(); } /** Returns a pointer to the unique display device */ Fl_Display_Device *Fl_Display_Device::display_device() { static Fl_Display_Device *display = new Fl_Display_Device(Fl_Graphics_Driver::newMainGraphicsDriver()); return display; } Fl_Surface_Device *Fl_Surface_Device::default_surface() { return Fl_Display_Device::display_device(); } static unsigned int surface_stack_height = 0; static Fl_Surface_Device *surface_stack[16]; /** Pushes \p new_current on top of the stack of current drawing surfaces, and makes it current. \p new_current will receive all future graphics requests. Any call to push_current() must be matched by a subsequent call to Fl_Surface_Device::pop_current(). The max height of this stack is 16. \version 1.4.0 */ void Fl_Surface_Device::push_current(Fl_Surface_Device *new_current) { if (surface_stack_height < sizeof(surface_stack)/sizeof(void*)) { surface_stack[surface_stack_height++] = surface(); } else { fprintf(stderr, "FLTK Fl_Surface_Device::push_current Stack overflow error\n"); } new_current->set_current(); } /** Removes the top element from the current drawing surface stack, and makes the new top element current. \return A pointer to the new current drawing surface. \see Fl_Surface_Device::push_current(Fl_Surface_Device *) \version 1.4.0 */ Fl_Surface_Device *Fl_Surface_Device::pop_current() { if (surface_stack_height > 0) surface_stack[--surface_stack_height]->set_current(); return surface_; } Fl_Device_Plugin *Fl_Device_Plugin::opengl_plugin() { static Fl_Device_Plugin *pi = NULL; if (!pi) { Fl_Plugin_Manager pm("fltk:device"); pi = (Fl_Device_Plugin*)pm.plugin("opengl.device.fltk.org"); } return pi; } #if !defined(FL_NO_PRINT_SUPPORT) #include Fl_PDF_File_Surface::Fl_PDF_File_Surface() { platform_surface_ = new_platform_pdf_surface_(&out_filename_); driver(platform_surface_->driver()); } Fl_PDF_File_Surface::~Fl_PDF_File_Surface() { delete platform_surface_; } /** Localizable text of the "PDF document settings" dialog */ const char * Fl_PDF_File_Surface::format_dialog_title = "PDF document settings"; /** Localizable text of the "PDF document settings" dialog */ const char * Fl_PDF_File_Surface::format_dialog_page_size = "Page Size:"; /** Localizable text of the "PDF document settings" dialog */ const char * Fl_PDF_File_Surface::format_dialog_default = "Set as default"; /** Localizable text of the "PDF document settings" dialog */ const char * Fl_PDF_File_Surface::format_dialog_orientation = "Orientation:"; #endif // !defined(FL_NO_PRINT_SUPPORT) fltk-1.4.3/src/fl_string_functions.cxx0000644000175000017500000000313415004135251020200 0ustar albrechtalbrecht/* * Platform agnostic string portability functions for the Fast Light Tool Kit (FLTK). * * Copyright 2020 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #include #include // strdup/_strdup #include "Fl_System_Driver.H" /** Cross platform interface to POSIX function strdup(). The fl_strdup() function returns a pointer to a new string which is a duplicate of the string 's'. Memory for the new string is obtained with malloc(3), and can be freed with free(3). Implementation: - POSIX: strdup() - WinAPI: _strdup() */ char *fl_strdup(const char *s) { return Fl::system_driver()->strdup(s); } /* * 'fl_strlcpy()' - Safely copy two strings. */ size_t /* O - Length of string */ fl_strlcpy(char *dst, /* O - Destination string */ const char *src, /* I - Source string */ size_t size) { /* I - Size of destination string buffer */ size_t srclen; /* Length of source string */ /* * Figure out how much room is needed... */ size --; srclen = strlen(src); /* * Copy the appropriate amount... */ if (srclen > size) srclen = size; memcpy(dst, src, srclen); dst[srclen] = '\0'; return (srclen); } fltk-1.4.3/src/fl_color.cxx0000644000175000017500000001125715004135251015725 0ustar albrechtalbrecht// // Color functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file fl_color.cxx \brief Color handling */ // Implementation of fl_color(i), fl_color(r,g,b). #include #include #include // fl_cmap needs to be defined globally (here) and is used in the device // specific graphics drivers. It is required to 'FL_EXPORT' this symbol // to be able to build the shared FLTK libraries. FL_EXPORT unsigned fl_cmap[256] = { #include "fl_cmap.h" // this is a file produced by "cmap.cxx": }; // ----------------------------------------------------------------------------- // all driver code is now in drivers/XXX/Fl_XXX_Graphics_Driver_xyz.cxx // ----------------------------------------------------------------------------- /** \addtogroup fl_attributes \{ */ /** Returns the RGB value(s) for the given FLTK color index. This form returns the RGB values packed in a 32-bit unsigned integer with the red value in the upper 8 bits, the green value in the next 8 bits, and the blue value in bits 8-15. The lower 8 bits will always be 0. */ unsigned Fl::get_color(Fl_Color i) { if (i & 0xffffff00) return (i); else return fl_cmap[i]; } /** Sets an entry in the fl_color index table. You can set it to any 8-bit RGB color. The color is not allocated until fl_color(i) is used. */ void Fl::set_color(Fl_Color i, uchar red, uchar green, uchar blue) { Fl::set_color((Fl_Color)(i & 255), ((unsigned)red<<24)+((unsigned)green<<16)+((unsigned)blue<<8)); } /** Sets an entry in the fl_color index table. You can set it to any 8-bit RGBA color. \note The color transparency is effective under the Wayland, hybrid Wayland/X11 and macOS platforms, whereas it has no effect under the X11 and Windows platforms. It's also effective for widgets added to an Fl_Gl_Window. \version 1.4 */ void Fl::set_color(Fl_Color i, uchar red, uchar green, uchar blue, uchar alpha) { Fl::set_color((Fl_Color)(i & 255), ((unsigned)red<<24) |((unsigned)green<<16) |((unsigned)blue<<8) |(alpha^0xff)); } void Fl::set_color(Fl_Color i, unsigned c) { Fl_Graphics_Driver::default_driver().set_color(i, c); } void Fl::free_color(Fl_Color i, int overlay) { Fl_Graphics_Driver::default_driver().free_color(i, overlay); } /** Returns the RGB value(s) for the given FLTK color index. This form returns the red, green, and blue values separately in referenced variables. \see unsigned get_color(Fl_Color c) */ void Fl::get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue) { unsigned c; if (i & 0xffffff00) c = (unsigned)i; else c = fl_cmap[i]; red = uchar(c>>24); green = uchar(c>>16); blue = uchar(c>>8); } /** Returns the RGBA value(s) for the given FLTK color index. This form returns the red, green, blue, and alpha values separately in referenced variables. \see unsigned get_color(Fl_Color c) */ void Fl::get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue, uchar &alpha) { unsigned c; if (i & 0xffffff00) c = (unsigned)i; else c = fl_cmap[i]; red = uchar(c>>24); green = uchar(c>>16); blue = uchar(c>>8); alpha = uchar(c^0x000000ff); } /** Returns the weighted average color between the two given colors. The red, green and blue values are averages using the following formula: \code color = color1 * weight + color2 * (1 - weight) \endcode Thus, a \p weight value of 1.0 will return the first color, while a value of 0.0 will return the second color. \param[in] color1, color2 boundary colors \param[in] weight weighting factor */ Fl_Color fl_color_average(Fl_Color color1, Fl_Color color2, float weight) { unsigned rgb1; unsigned rgb2; uchar r, g, b; if (color1 & 0xffffff00) rgb1 = color1; else rgb1 = fl_cmap[color1 & 255]; if (color2 & 0xffffff00) rgb2 = color2; else rgb2 = fl_cmap[color2 & 255]; r = (uchar)(((uchar)(rgb1>>24))*weight + ((uchar)(rgb2>>24))*(1-weight)); g = (uchar)(((uchar)(rgb1>>16))*weight + ((uchar)(rgb2>>16))*(1-weight)); b = (uchar)(((uchar)(rgb1>>8))*weight + ((uchar)(rgb2>>8))*(1-weight)); return fl_rgb_color(r, g, b); } /** Returns the inactive, dimmed version of the given color. */ Fl_Color fl_inactive(Fl_Color c) { return fl_color_average(c, FL_GRAY, .33f); } /** \} */ fltk-1.4.3/src/print_button.cxx0000644000175000017500000001444415004135251016656 0ustar albrechtalbrecht// // "Print Window" functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Notes: This function must be activated by defining the preprocessor macro // USE_PRINT_BUTTON on the commandline. // // Although this function is compiled on all platforms it is only used by // platform specific code of fl_open_display() on Linux (X11) and Windows. // macOS uses the "Print front window" menu in the application menu. // // The environment variable FLTK_PRINT_BUTTON can be defined to control the // creation of the sometimes annoying print button feature at runtime if it // has been compiled in (see above): // // - FLTK_PRINT_BUTTON undefined: like 1 below (default) // // - FLTK_PRINT_BUTTON = 0 : print front window disabled for this program // - FLTK_PRINT_BUTTON = 1 : window shown at startup // - FLTK_PRINT_BUTTON = 2 : window not shown, shortcut available to show // - FLTK_PRINT_BUTTON = 3 : window shown at startup, shortcut available // // If options 2 or 3 are used the shortcut can be used to show the window // if it was not shown (2) or accidentally closed (3). // // Currently the shortcut can't be configured and is always ALT+SHIFT+'s'. // Todo: make the shortcut configurable. #include "print_button.h" #include #include #include #ifdef USE_PRINT_BUTTON #include #include #include #include #include #include // define the optional rotation of print output in degrees to test it // #define ROTATE 20.0 // Global variables to simplify and clarify the code: static Fl_Window *print_window = 0; // "print front window" dialog window static Fl_Check_Button *deco_button = 0; // window decoration button // The button callback does the job for both printing and copying to the // clipboard. The callback is called with 'mode' == (int)(data). // 1: print window // 2: copy window to clipboard // else: see 2. static void output_cb(Fl_Widget * /*unused*/, void *data) { print_window->hide(); Fl_Window *win = Fl::first_window(); // if no (other) window exists we return silently w/o showing the // print window again (which ends the program) if (!win) return; fl_print_or_copy_window(win, deco_button->value(), fl_int(data)); print_window->show(); } // Global event handler for screenshot (ctrl/alt/command + s) // This pops up the "Print front window" dialog if it had been closed static int shortcut_handler(int event) { // global shortcut handler // required key and keyboard states for shortcut // (should be configurable) const int key = 's'; // global shortcut key const int state = FL_ALT | FL_SHIFT; // | FL_CTRL | FL_COMMAND; if (print_window && (event == FL_SHORTCUT || event == FL_KEYBOARD) && ((Fl::event_state() & state) == state) && (Fl::event_key() == key)) { print_window->show(); return 1; } return 0; } // create and initialize the "Print/copy front window" dialog window int fl_create_print_window() { static int first = 1; if (!first) return 0; first = 0; int val = 1; const char *print_button = fl_getenv("FLTK_PRINT_BUTTON"); if (print_button) val = atoi(print_button); if (val) { // prevent becoming a subwindow Fl_Group *cg = Fl_Group::current(); Fl_Group::current(0); print_window = new Fl_Window( 0, 0, 200, 110, "FLTK screenshot"); Fl_Button *bp = new Fl_Button(10, 10, 180, 30, "Print front window"); Fl_Button *bc = new Fl_Button(10, 40, 180, 30, "Copy front window"); deco_button = new Fl_Check_Button(10, 70, 180, 30, "Window decoration"); bp->callback(output_cb, (void *)1); bc->callback(output_cb, (void *)2); print_window->end(); if (val & 1) print_window->show(); // reset saved current group Fl_Group::current(cg); if (val & 2) Fl::add_handler(shortcut_handler); } return 1; } #else // USE_PRINT_BUTTON not defined int fl_create_print_window() { return 0; } #endif // USE_PRINT_BUTTON /* undocumented function: Print a window or copy its contents to the clipboard. win The window to process grab_decoration true means the window titlebar is processed too mode 1 means print, other means copy */ int fl_print_or_copy_window(Fl_Window *win, bool grab_decoration, int mode) { if (!win) return 0; int ww = grab_decoration ? win->decorated_w() : win->w(); int wh = grab_decoration ? win->decorated_h() : win->h(); if (mode == 1) { // print window // exchange the 2 constructors below to test class Fl_PostScript_File_Device Fl_Printer printer; //Fl_PostScript_File_Device printer; int w, h; if (printer.begin_job(1)) { // fail or cancel return 1; } if (printer.begin_page()) { // fail or cancel return 1; } printer.printable_rect(&w, &h); // scale the printer device so that the window fits on the page float scale = 1; if (ww > w || wh > h) { scale = (float)w / ww; if ((float)h / wh < scale) scale = (float)h / wh; printer.scale(scale, scale); printer.printable_rect(&w, &h); } #ifdef ROTATE printer.scale(scale * 0.8, scale * 0.8); printer.printable_rect(&w, &h); printer.origin(w / 2, h / 2); printer.rotate(ROTATE); printer.print_widget(win, -win->w() / 2, -win->h() / 2); #else printer.origin(w / 2, h / 2); if (grab_decoration) printer.draw_decorated_window(win, -ww / 2, -wh / 2); else printer.draw(win, -ww / 2, -wh / 2); #endif printer.end_page(); printer.end_job(); } else { // copy window to clipboard Fl_Copy_Surface *surf = new Fl_Copy_Surface(ww, wh); if (grab_decoration) surf->draw_decorated_window(win); // draw the window content else surf->draw(win); // draw the window content delete surf; // put the window on the clipboard } // print | copy return 0; } fltk-1.4.3/src/Fl_Native_File_Chooser.cxx0000644000175000017500000002240215004135251020410 0ustar albrechtalbrecht// // FLTK native OS file chooser widget // // Copyright 2004 Greg Ercolano. // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include /** Localizable message */ const char *Fl_Native_File_Chooser::file_exists_message = "File exists. Are you sure you want to overwrite?"; /** Destructor. Deallocates any resources allocated to this widget. */ Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { delete platform_fnfc; } /** Sets the current Fl_Native_File_Chooser::Type of browser. */ void Fl_Native_File_Chooser::type(int t) { if (platform_fnfc) platform_fnfc->type(t); } /** Gets the current Fl_Native_File_Chooser::Type of browser. */ int Fl_Native_File_Chooser::type() const { return platform_fnfc->type(); } /** Sets the platform specific chooser options to \p val. \p val is expected to be one or more Fl_Native_File_Chooser::Option flags ORed together. Some platforms have OS-specific functions that can be enabled/disabled via this method.

\code Flag Description Win Mac Other -------------- ----------------------------------------------- ------- ------- ------- NEW_FOLDER Shows the 'New Folder' button. Ignored Used Used PREVIEW Enables the 'Preview' mode by default. Ignored Ignored Used SAVEAS_CONFIRM Confirm dialog if BROWSE_SAVE_FILE file exists. Used Used Used USE_FILTER_EXT Chooser filter presets the output file extension. Ignored Used Used (GTK) \endcode */ void Fl_Native_File_Chooser::options(int o) { if (platform_fnfc) platform_fnfc->options(o); } /** Gets the platform specific Fl_Native_File_Chooser::Option flags. */ int Fl_Native_File_Chooser::options() const { return platform_fnfc->options(); } /** Returns the number of filenames (or directory names) the user selected.

\b Example: \code if ( fnfc->show() == 0 ) { // Print all filenames user selected for (int n=0; ncount(); n++ ) { printf("%d) '%s'\n", n, fnfc->filename(n)); } } \endcode */ int Fl_Native_File_Chooser::count() const { return platform_fnfc->count(); } /** Return the filename the user chose. Use this if only expecting a single filename. If more than one filename is expected, use filename(int) instead. Return value may be "" if no filename was chosen (eg. user cancelled). */ const char *Fl_Native_File_Chooser::filename() const { return platform_fnfc->filename(); } /** Return one of the filenames the user selected. Use count() to determine how many filenames the user selected.

\b Example: \code if ( fnfc->show() == 0 ) { // Print all filenames user selected for (int n=0; ncount(); n++ ) { printf("%d) '%s'\n", n, fnfc->filename(n)); } } \endcode */ const char *Fl_Native_File_Chooser::filename(int i) const { return platform_fnfc->filename(i); } /** Preset the directory the browser will show when opened. If \p val is NULL, or no directory is specified, the chooser will attempt to use the last non-cancelled folder. */ void Fl_Native_File_Chooser::directory(const char *val) { if (platform_fnfc) platform_fnfc->directory(val); } /** Returns the current preset directory() value. */ const char *Fl_Native_File_Chooser::directory() const { return platform_fnfc->directory(); } /** Set the title of the file chooser's dialog window. Can be NULL if no title desired. The default title varies according to the platform, so you are advised to set the title explicitly. */ void Fl_Native_File_Chooser::title(const char *t) { if (platform_fnfc) platform_fnfc->title(t); } /** Get the title of the file chooser's dialog window. Return value may be NULL if no title was set. */ const char* Fl_Native_File_Chooser::title() const { return platform_fnfc->title(); } /** Returns the filter string last set. Can be NULL if no filter was set. */ const char *Fl_Native_File_Chooser::filter() const { return platform_fnfc->filter(); } /** Sets the filename filters used for browsing. The default is NULL, which browses all files.

The filter string can be any of:

- A single wildcard (eg. "*.txt") - Multiple wildcards (eg. "*.{cxx,h,H}") - A descriptive name followed by a "\t" and a wildcard (eg. "Text Files\t*.txt") - A list of separate wildcards with a "\n" between each (eg. "*.{cxx,H}\n*.txt") - A list of descriptive names and wildcards (eg. "C++ Files\t*.{cxx,H}\nTxt Files\t*.txt")

The format of each filter is a wildcard, or an optional user description followed by '\\t' and the wildcard.

On most platforms, each filter is available to the user via a pulldown menu in the file chooser. The 'All Files' option is always available to the user. */ void Fl_Native_File_Chooser::filter(const char *f) { if (platform_fnfc) platform_fnfc->filter(f); } /** Gets how many filters were available, not including "All Files" */ int Fl_Native_File_Chooser::filters() const { return platform_fnfc->filters(); } /** Sets which filter will be initially selected. The first filter is indexed as 0. If filter_value() == filters(), then "All Files" was chosen. If filter_value() > filters(), then a custom filter was set. Some "native" file choosers don't support this way to set the initial filter type, particularly the system dialog based browsers: - kdialog (KDE system dialog) - zenity (another system dialog based chooser). Note: this list may not be complete. As far as we know these dialogs use the \b first item in the list of filter values as the initial filter presented to the user. \see filter(const char *f) */ void Fl_Native_File_Chooser::filter_value(int i) { platform_fnfc->filter_value(i); } /** Returns which filter value was last selected by the user. This is only valid if the chooser returns success and if the particular file chooser supports it. Otherwise the value is not changed. Some "native" file choosers don't support returning the filter selection by the user, particularly the system dialog based browsers: - kdialog (KDE system dialog) - zenity (another system dialog based chooser). Note: this list may not be complete. These system file chooser dialogs don't return the filter value chosen by the user. \see filter(const char *f) */ int Fl_Native_File_Chooser::filter_value() const { return platform_fnfc->filter_value(); } /** Sets the default filename for the chooser. Use directory() to set the default directory. Mainly used to preset the filename for save dialogs, and on most platforms can be used for opening files as well. */ void Fl_Native_File_Chooser::preset_file(const char*f) { if (platform_fnfc) platform_fnfc->preset_file(f); } /** Get the preset filename. */ const char* Fl_Native_File_Chooser::preset_file() const { return platform_fnfc->preset_file(); } /** Returns a system dependent error message for the last method that failed. This message should at least be flagged to the user in a dialog box, or to some kind of error log. Contents will be valid only for methods that document errmsg() will have info on failures. */ const char *Fl_Native_File_Chooser::errmsg() const { return platform_fnfc->errmsg(); } /** Post the chooser's dialog. Blocks until dialog has been completed or cancelled. \returns - 0 -- user picked a file - 1 -- user cancelled - -1 -- failed; errmsg() has reason */ int Fl_Native_File_Chooser::show() { return platform_fnfc ? platform_fnfc->show() : 1; } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ // COPY A STRING WITH 'new' // Value can be NULL // char *Fl_Native_File_Chooser_Driver::strnew(const char *val) { if ( val == NULL ) return(NULL); char *s = new char[strlen(val)+1]; strcpy(s, val); return(s); } // FREE STRING CREATED WITH strnew(), NULLS OUT STRING // Value can be NULL // char *Fl_Native_File_Chooser_Driver::strfree(char *val) { if ( val ) delete [] val; return(NULL); } // 'DYNAMICALLY' APPEND ONE STRING TO ANOTHER // Returns newly allocated string, or NULL // if s && val == NULL. // 's' can be NULL; returns a strnew(val). // 'val' can be NULL; s is returned unmodified. // // Usage: // char *s = strnew("foo"); // s = "foo" // s = strapp(s, "bar"); // s = "foobar" // char *Fl_Native_File_Chooser_Driver::strapp(char *s, const char *val) { if ( ! val ) { return(s); // Nothing to append? return s } if ( ! s ) { return(strnew(val)); // New string? return copy of val } char *news = new char[strlen(s)+strlen(val)+1]; strcpy(news, s); strcat(news, val); delete [] s; // delete old string return(news); // return new copy } // APPEND A CHARACTER TO A STRING // This does NOT allocate space for the new character. // void Fl_Native_File_Chooser_Driver::chrcat(char *s, char c) { char tmp[2] = { c, '\0' }; strcat(s, tmp); } /** \} \endcond */ fltk-1.4.3/src/fl_plastic.cxx0000644000175000017500000002553115004135251016246 0ustar albrechtalbrecht// // "Plastic" drawing routines for the Fast Light Tool Kit (FLTK). // // These box types provide a cross between Aqua and KDE buttons; kindof // like translucent plastic buttons... // // Copyright 2001-2010 by Michael Sweet. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Box drawing code for an obscure box type. // These box types are in separate files so they are not linked // in if not used. #include #include #include "flstring.h" // // Uncomment the following line to restore the old plastic box type // appearance. // //#define USE_OLD_PLASTIC_BOX #define USE_OLD_PLASTIC_COLOR extern const uchar *fl_gray_ramp(); inline Fl_Color shade_color(uchar gc, Fl_Color bc) { #ifdef USE_OLD_PLASTIC_COLOR return fl_color_average((Fl_Color)gc, bc, 0.75f); #else unsigned grgb = Fl::get_color((Fl_Color)gc), brgb = Fl::get_color(bc); int red, green, blue, gray; gray = ((grgb >> 24) & 255); red = gray * ((brgb >> 24) & 255) / 255 + gray * gray / 510; gray = ((grgb >> 16) & 255); green = gray * ((brgb >> 16) & 255) / 255 + gray * gray / 510; gray = ((grgb >> 8) & 255); blue = gray * ((brgb >> 8) & 255) / 255 + gray * gray / 510; if (red > 255) red = 255; if (green > 255) green = 255; if (blue > 255) blue = 255; if (Fl::draw_box_active()) return fl_rgb_color(red, green, blue); else return fl_color_average(FL_GRAY, fl_rgb_color(red, green, blue), 0.75f); #endif // USE_OLD_PLASTIC_COLOR } static void frame_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) { const uchar *g = fl_gray_ramp(); int b = ((int) strlen(c)) / 4 + 1; for (x += b, y += b, w -= 2 * b, h -= 2 * b; b > 1; b --) { // Draw lines around the perimeter of the button, 4 colors per // circuit. fl_color(shade_color(g[(int)*c++], bc)); fl_line(x, y + h + b, x + w - 1, y + h + b, x + w + b - 1, y + h); fl_color(shade_color(g[(int)*c++], bc)); fl_line(x + w + b - 1, y + h, x + w + b - 1, y, x + w - 1, y - b); fl_color(shade_color(g[(int)*c++], bc)); fl_line(x + w - 1, y - b, x, y - b, x - b, y); fl_color(shade_color(g[(int)*c++], bc)); fl_line(x - b, y, x - b, y + h, x, y + h + b); } } static void frame_round(int x, int y, int w, int h, const char *c, Fl_Color bc) { const uchar *g = fl_gray_ramp(); size_t b = strlen(c) / 4 + 1; if (w==h) { for (; b > 1; b --, x ++, y ++, w -= 2, h -= 2) { fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x, y, w, h, 45.0, 135.0); fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x, y, w, h, 315.0, 405.0); fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x, y, w, h, 225.0, 315.0); fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x, y, w, h, 135.0, 225.0); } } else if (w>h) { int d = h/2; for (; b > 1; d--, b --, x ++, y ++, w -= 2, h -= 2) { fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x, y, h, h, 90.0, 135.0); fl_xyline(x+d, y, x+w-d); fl_arc(x+w-h, y, h, h, 45.0, 90.0); fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x+w-h, y, h, h, 315.0, 405.0); fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x+w-h, y, h, h, 270.0, 315.0); fl_xyline(x+d, y+h-1, x+w-d); fl_arc(x, y, h, h, 225.0, 270.0); fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x, y, h, h, 135.0, 225.0); } } else if (w 1; d--, b --, x ++, y ++, w -= 2, h -= 2) { fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x, y, w, w, 45.0, 135.0); fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x, y, w, w, 0.0, 45.0); fl_yxline(x+w-1, y+d, y+h-d); fl_arc(x, y+h-w, w, w, 315.0, 360.0); fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x, y+h-w, w, w, 225.0, 315.0); fl_color(shade_color(g[(int)*c++], bc)); fl_arc(x, y+h-w, w, w, 180.0, 225.0); fl_yxline(x, y+d, y+h-d); fl_arc(x, y, w, w, 135.0, 180.0); } } } static void shade_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) { const uchar *g = fl_gray_ramp(); int i, j; int clen = (int) strlen(c) - 1; int chalf = clen / 2; int cstep = 1; if (h < (w * 2)) { // Horizontal shading... if (clen >= h) cstep = 2; for (i = 0, j = 0; j < chalf; i ++, j += cstep) { // Draw the top line and points... fl_color(shade_color(g[(int)c[i]], bc)); fl_xyline(x + 1, y + i, x + w - 2); fl_color(shade_color(g[c[i] - 2], bc)); fl_point(x, y + i + 1); fl_point(x + w - 1, y + i + 1); // Draw the bottom line and points... fl_color(shade_color(g[(int)c[clen - i]], bc)); fl_xyline(x + 1, y + h - i, x + w - 2); fl_color(shade_color(g[c[clen - i] - 2], bc)); fl_point(x, y + h - i); fl_point(x + w - 1, y + h - i); } // Draw the interior and sides... i = chalf / cstep; fl_color(shade_color(g[(int)c[chalf]], bc)); fl_rectf(x + 1, y + i, w - 2, h - 2 * i + 1); fl_color(shade_color(g[c[chalf] - 2], bc)); fl_yxline(x, y + i, y + h - i); fl_yxline(x + w - 1, y + i, y + h - i); } else { // Vertical shading... if (clen >= w) cstep = 2; for (i = 0, j = 0; j < chalf; i ++, j += cstep) { // Draw the left line and points... fl_color(shade_color(g[(int)c[i]], bc)); fl_yxline(x + i, y + 1, y + h - 1); fl_color(shade_color(g[c[i] - 2], bc)); fl_point(x + i + 1, y); fl_point(x + i + 1, y + h); // Draw the right line and points... fl_color(shade_color(g[(int)c[clen - i]], bc)); fl_yxline(x + w - 1 - i, y + 1, y + h - 1); fl_color(shade_color(g[c[clen - i] - 2], bc)); fl_point(x + w - 2 - i, y); fl_point(x + w - 2 - i, y + h); } // Draw the interior, top, and bottom... i = chalf / cstep; fl_color(shade_color(g[(int)c[chalf]], bc)); fl_rectf(x + i, y + 1, w - 2 * i, h - 1); fl_color(shade_color(g[c[chalf] - 2], bc)); fl_xyline(x + i, y, x + w - i); fl_xyline(x + i, y + h, x + w - i); } } static void shade_round(int x, int y, int w, int h, const char *c, Fl_Color bc) { const uchar *g = fl_gray_ramp(); int i; int clen = (int) (strlen(c) - 1); int chalf = clen / 2; if (w>h) { int d = h/2; const int na = 8; for (i=0; i 1) { fl_xyline(x+1, y, x+w-2); fl_xyline(x+1, y+h-1, x+w-2); } if (h > 1) { fl_yxline(x, y+1, y+h-2); fl_yxline(x+w-1, y+1, y+h-2); } } static void thin_up_box(int x, int y, int w, int h, Fl_Color c) { #ifdef USE_OLD_PLASTIC_BOX shade_rect(x + 2, y + 2, w - 4, h - 5, "RVQNOPQRSTUVWVQ", c); up_frame(x, y, w, h, c); #else if (w > 4 && h > 4) { shade_rect(x + 1, y + 1, w - 2, h - 3, "RQOQSUWQ", c); frame_rect(x, y, w, h - 1, "IJLM", c); } else { narrow_thin_box(x, y, w, h, c); } #endif // USE_OLD_PLASTIC_BOX } static void up_box(int x, int y, int w, int h, Fl_Color c) { #ifdef USE_OLD_PLASTIC_BOX shade_rect(x + 2, y + 2, w - 4, h - 5, "RVQNOPQRSTUVWVQ", c); up_frame(x, y, w, h, c); #else if (w > 8 && h > 8) { shade_rect(x + 1, y + 1, w - 2, h - 3, "RVQNOPQRSTUVWVQ", c); frame_rect(x, y, w, h - 1, "IJLM", c); } else { thin_up_box(x, y, w, h, c); } #endif // USE_OLD_PLASTIC_BOX } static void up_round(int x, int y, int w, int h, Fl_Color c) { shade_round(x, y, w, h, "RVQNOPQRSTUVWVQ", c); frame_round(x, y, w, h, "IJLM", c); } static void down_frame(int x, int y, int w, int h, Fl_Color c) { frame_rect(x, y, w, h - 1, "LLLLTTRR", c); } static void down_box(int x, int y, int w, int h, Fl_Color c) { if (w > 6 && h > 6) { shade_rect(x + 2, y + 2, w - 4, h - 5, "STUVWWWVT", c); down_frame(x, y, w, h, c); } else { narrow_thin_box(x, y, w, h, c); } } static void down_round(int x, int y, int w, int h, Fl_Color c) { shade_round(x, y, w, h, "STUVWWWVT", c); frame_round(x, y, w, h, "IJLM", c); } extern void fl_round_focus(Fl_Boxtype bt, int x, int y, int w, int h, Fl_Color fg, Fl_Color bg); extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*, Fl_Box_Draw_Focus_F* =NULL); Fl_Boxtype fl_define_FL_PLASTIC_UP_BOX() { fl_internal_boxtype(_FL_PLASTIC_UP_BOX, up_box); fl_internal_boxtype(_FL_PLASTIC_DOWN_BOX, down_box); fl_internal_boxtype(_FL_PLASTIC_UP_FRAME, up_frame); fl_internal_boxtype(_FL_PLASTIC_DOWN_FRAME, down_frame); fl_internal_boxtype(_FL_PLASTIC_THIN_UP_BOX, thin_up_box); fl_internal_boxtype(_FL_PLASTIC_THIN_DOWN_BOX, down_box); fl_internal_boxtype(_FL_PLASTIC_ROUND_UP_BOX, up_round, fl_round_focus); fl_internal_boxtype(_FL_PLASTIC_ROUND_DOWN_BOX, down_round, fl_round_focus); return _FL_PLASTIC_UP_BOX; } fltk-1.4.3/src/fl_cursor_wait.xpm0000644000175000017500000000075615004135251017154 0ustar albrechtalbrecht/* XPM */ static const char * const fl_cursor_wait_xpm[] = { /* width height ncolors chars_per_pixel */ "13 18 3 1", /* colors */ " c None", ". c #FFFFFF", "B c #000000", /* pixels */ " ........ ", " .BBBBBB. ", " .BBBBBB. ", " .BBBBBB. ", " .BBBBBB. ", " .B......B. ", ".B....B...B. ", ".B....B...B. ", ".B....B...BB.", ".B.BBBB...BB.", ".B........B. ", ".B........B. ", " .B......B. ", " .BBBBBB. ", " .BBBBBB. ", " .BBBBBB. ", " .BBBBBB. ", " ........ ", }; fltk-1.4.3/src/forms_bitmap.cxx0000644000175000017500000000223015004135251016577 0ustar albrechtalbrecht// // Forms compatible bitmap function for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include /** Creates a bitmap widget from a box type, position, size and optional label specification */ Fl_FormsBitmap::Fl_FormsBitmap( Fl_Boxtype t, int X, int Y, int W, int H, const char* l) : Fl_Widget(X, Y, W, H, l) { box(t); b = 0; color(FL_BLACK); align(FL_ALIGN_BOTTOM); } /** Sets a new bitmap bits with size W,H. Deletes the previous one.*/ void Fl_FormsBitmap::set(int W, int H, const uchar *bits) { delete b; bitmap(new Fl_Bitmap(bits, W, H)); } /** Draws the bitmap and its associated box. */ void Fl_FormsBitmap::draw() { draw_box(box(), selection_color()); if (b) {fl_color(color()); b->draw(x(), y(), w(), h());} draw_label(); } fltk-1.4.3/src/fl_encoding_mac_roman.cxx0000644000175000017500000000752515004135251020414 0ustar albrechtalbrecht// // Convert Mac Roman encoded text to the local encoding. // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "Fl_System_Driver.H" #include #include #include #include "flstring.h" /** \cond DriverDev \addtogroup DriverDeveloper \{ */ // These function assume a western code page. // // Windows and X11 render text in ISO or Latin-1 for western settings. The // lookup tables below will convert all common character codes and replace // unknown characters with an upsidedown question mark. // This table converts Windows-1252/Latin 1 into MacRoman encoding static uchar latin2roman[128] = { 0xdb, 0xc0, 0xe2, 0xc4, 0xe3, 0xc9, 0xa0, 0xe0, 0xf6, 0xe4, 0xc0, 0xdc, 0xce, 0xc0, 0xc0, 0xc0, 0xc0, 0xd4, 0xd5, 0xd2, 0xd3, 0xa5, 0xd0, 0xd1, 0xf7, 0xaa, 0xc0, 0xdd, 0xcf, 0xc0, 0xc0, 0xd9, 0xca, 0xc1, 0xa2, 0xa3, 0xc0, 0xb4, 0xc0, 0xa4, 0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0xc0, 0xa8, 0xf8, 0xa1, 0xb1, 0xc0, 0xc0, 0xab, 0xb5, 0xa6, 0xe1, 0xfc, 0xc0, 0xbc, 0xc8, 0xc0, 0xc0, 0xc0, 0xc0, 0xcb, 0xe7, 0xe5, 0xcc, 0x80, 0x81, 0xae, 0x82, 0xe9, 0x83, 0xe6, 0xe8, 0xed, 0xea, 0xeb, 0xec, 0xc0, 0x84, 0xf1, 0xee, 0xef, 0xcd, 0x85, 0xc0, 0xaf, 0xf4, 0xf2, 0xf3, 0x86, 0xc0, 0xc0, 0xa7, 0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d, 0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95, 0xc0, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6, 0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 0xc0, 0xc0, 0xd8 }; // This table converts MacRoman into Windows-1252/Latin 1 static uchar roman2latin[128] = { 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, 0x86, 0xb0, 0xa2, 0xa3, 0xa7, 0x95, 0xb6, 0xdf, 0xae, 0xa9, 0x99, 0xb4, 0xa8, 0xbf, 0xc6, 0xd8, 0xbf, 0xb1, 0xbf, 0xbf, 0xa5, 0xb5, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xaa, 0xba, 0xbf, 0xe6, 0xf8, 0xbf, 0xa1, 0xac, 0xbf, 0x83, 0xbf, 0xbf, 0xab, 0xbb, 0x85, 0xa0, 0xc0, 0xc3, 0xd5, 0x8c, 0x9c, 0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xf7, 0xbf, 0xff, 0x9f, 0xbf, 0x80, 0x8b, 0x9b, 0xbf, 0xbf, 0x87, 0xb7, 0x82, 0x84, 0x89, 0xc2, 0xca, 0xc1, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4, 0xbf, 0xd2, 0xda, 0xdb, 0xd9, 0xbf, 0x88, 0x98, 0xaf, 0xbf, 0xbf, 0xbf, 0xb8, 0xbf, 0xbf, 0xbf }; static char *buf = 0; static int n_buf = 0; const char *Fl_System_Driver::local_to_mac_roman(const char *t, int n) { if (n==-1) n = (int) strlen(t); if (n<=n_buf) { n_buf = (n + 257) & 0x7fffff00; if (buf) free(buf); buf = (char*)malloc(n_buf); } const uchar *src = (const uchar*)t; uchar *dst = (uchar*)buf; for ( ; n>0; n--) { uchar c = *src; if (c>127) *dst = latin2roman[c-128]; else *dst = c; } //*dst = 0; // this would be wrong! return buf; } const char *Fl_System_Driver::mac_roman_to_local(const char *t, int n) { if (n==-1) n = (int) strlen(t); if (n<=n_buf) { n_buf = (n + 257) & 0x7fffff00; if (buf) free(buf); buf = (char*)malloc(n_buf); } const uchar *src = (const uchar*)t; uchar *dst = (uchar*)buf; for ( ; n>0; n--) { uchar c = *src++; if (c>127) *dst++ = roman2latin[c-128]; else *dst++ = c; } //*dst = 0; // this would be wrong return buf; } /** \} \endcond */ const char *fl_local_to_mac_roman(const char *t, int n) { return Fl::system_driver()->local_to_mac_roman(t, n); } const char *fl_mac_roman_to_local(const char *t, int n) { return Fl::system_driver()->mac_roman_to_local(t, n); } fltk-1.4.3/src/flstring.c0000644000175000017500000000363215004135251015374 0ustar albrechtalbrecht/* * BSD string functions for the Fast Light Tool Kit (FLTK). * * Copyright 1998-2010 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #include "flstring.h" /* * 'fl_strlcat()' - Safely concatenate two strings. */ size_t /* O - Length of string */ fl_strlcat(char *dst, /* O - Destination string */ const char *src, /* I - Source string */ size_t size) { /* I - Size of destination string buffer */ size_t srclen; /* Length of source string */ size_t dstlen; /* Length of destination string */ /* * Figure out how much room is left... */ dstlen = strlen(dst); size -= dstlen + 1; if (!size) return (dstlen); /* No room, return immediately... */ /* * Figure out how much room is needed... */ srclen = strlen(src); /* * Copy the appropriate amount... */ if (srclen > size) srclen = size; memcpy(dst + dstlen, src, srclen); dst[dstlen + srclen] = '\0'; return (dstlen + srclen); } #define C_RANGE(c,l,r) ( (c) >= (l) && (c) <= (r) ) /** * locale independent ascii oriented case cmp * returns 0 if string successfully compare, -1 if st */ int fl_ascii_strcasecmp(const char *s, const char *t) { if (!s || !t) return (s==t ? 0 : (!s ? -1 : +1)); for(;*s && *t; s++,t++) { if (*s == *t) continue; if (*s < *t) { if ( (*s+0x20)!=*t || !C_RANGE(*s,'A','Z') ) return -1; } else { /* (*s > *t) */ if ( (*s-0x20)!=*t || !C_RANGE(*s,'a','z') ) return +1; } } return (*s==*t) ? 0 : (*t ? -1 : +1); } fltk-1.4.3/src/print_button.h0000644000175000017500000000174115004135251016277 0ustar albrechtalbrecht// // Header for "Print Window" functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef _SRC_FL_PRINT_BUTTON_H_ #define _SRC_FL_PRINT_BUTTON_H_ #include // These are all internal functions, do not FL_EXPORT these functions! // These functions are mplemented in src/print_button.cxx // Create and initialize the "Print/copy front window" dialog window int fl_create_print_window(); // Print a window or copy its contents to the clipboard. int fl_print_or_copy_window(Fl_Window *win, bool grab_decoration, int mode); #endif // _SRC_FL_PRINT_BUTTON_H_ fltk-1.4.3/src/Xutf8.h0000644000175000017500000000741115004135251014566 0ustar albrechtalbrecht/* * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2010 by O'ksi'D. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #if ! ( defined(_Xutf8_h) || defined(FL_DOXYGEN) ) #define _Xutf8_h # ifdef __cplusplus extern "C" { # endif #include #include #include #include #include typedef struct { int nb_font; char **font_name_list; int *encodings; XFontStruct **fonts; Font fid; int ascent; int descent; int *ranges; } XUtf8FontStruct; XUtf8FontStruct * XCreateUtf8FontStruct ( Display *dpy, const char *base_font_name_list); void XUtf8DrawString( Display *display, Drawable d, XUtf8FontStruct *font_set, GC gc, int x, int y, const char *string, int num_bytes); void XUtf8_measure_extents( Display *display, Drawable d, XUtf8FontStruct *font_set, GC gc, int *xx, int *yy, int *ww, int *hh, const char *string, int num_bytes); void XUtf8DrawRtlString( Display *display, Drawable d, XUtf8FontStruct *font_set, GC gc, int x, int y, const char *string, int num_bytes); void XUtf8DrawImageString( Display *display, Drawable d, XUtf8FontStruct *font_set, GC gc, int x, int y, const char *string, int num_bytes); int XUtf8TextWidth( XUtf8FontStruct *font_set, const char *string, int num_bytes); int XUtf8UcsWidth( XUtf8FontStruct *font_set, unsigned int ucs); FL_EXPORT int fl_XGetUtf8FontAndGlyph( XUtf8FontStruct *font_set, unsigned int ucs, XFontStruct **fnt, unsigned short *id); void XFreeUtf8FontStruct( Display *dpy, XUtf8FontStruct *font_set); int XConvertUtf8ToUcs( const unsigned char *buf, int len, unsigned int *ucs); int XConvertUcsToUtf8( unsigned int ucs, char *buf); int XUtf8CharByteLen( const unsigned char *buf, int len); int XCountUtf8Char( const unsigned char *buf, int len); int XFastConvertUtf8ToUcs( const unsigned char *buf, int len, unsigned int *ucs); long XKeysymToUcs( KeySym keysym); #ifdef X_HAVE_UTF8_STRING #define XUtf8LookupString Xutf8LookupString #else int XUtf8LookupString( XIC ic, XKeyPressedEvent* event, char* buffer_return, int bytes_buffer, KeySym* keysym, Status* status_return); #endif # ifdef __cplusplus } # endif #endif fltk-1.4.3/src/fl_cursor_nesw.xpm0000644000175000017500000000141215004135251017152 0ustar albrechtalbrecht/* XPM */ static const char * const fl_cursor_nesw_xpm[] = { "15 15 28 1", " c None", ". c #FFFFFF", "+ c #767676", "@ c #000000", "# c #4E4E4E", "$ c #0C0C0C", "% c #494949", "& c #4D4D4D", "* c #1B1B1B", "= c #515151", "- c #646464", "; c #363636", "> c #6A6A6A", ", c #545454", "' c #585858", ") c #242424", "! c #797979", "~ c #2E2E2E", "{ c #444444", "] c #3B3B3B", "^ c #0A0A0A", "/ c #595959", "( c #F7F7F7", "_ c #080808", ": c #6B6B6B", "< c #FDFDFD", "[ c #FCFCFC", "} c #FEFEFE", " ..........", " .+@@@@@@.", " .#@@@@@.", " .$@@@@.", " .%@@@@@.", ". .&@@@*@@.", ".. .=@@@-.;@.", ".>. .,@@@'. .).", ".@!.'@@@#. ..", ".@@~@@@{. .", ".@@@@@]. ", ".@@@@^. ", ".@@@@@/( ", ".______:( ", "<[[[[[[[[} "}; fltk-1.4.3/src/Fl_get_key_win32.cxx0000644000175000017500000000702415004135251017215 0ustar albrechtalbrecht// // Windows keyboard state routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Note: this file contains platform specific code and will therefore // not be processed by doxygen (see Doxyfile.in). // Return the current state of a key. Keys are named by fltk symbols, // which are actually X keysyms. So this has to translate to Windows // VK_x symbols. #include "drivers/WinAPI/Fl_WinAPI_Screen_Driver.H" #include // Convert an FLTK (X) keysym to a Windows VK symbol: // See also the inverse converter in Fl_win32.cxx // This table is in numeric order by FLTK symbol order for binary search: static const struct {unsigned short vk, fltk;} vktab[] = { {VK_SPACE, ' '}, {'1', '!'}, {0xde, '\"'}, {'3', '#'}, {'4', '$'}, {'5', '%'}, {'7', '&'}, {0xde, '\''}, {'9', '('}, {'0', ')'}, {'8', '*'}, {0xbb, '+'}, {0xbc, ','}, {0xbd, '-'}, {0xbe, '.'}, {0xbf, '/'}, {0xba, ':'}, {0xba, ';'}, {0xbc, '<'}, {0xbb, '='}, {0xbe, '>'}, {0xbf, '?'}, {'2', '@'}, {0xdb, '['}, {0xdc, '\\'}, {0xdd, ']'}, {'6', '^'}, {0xbd, '_'}, {0xc0, '`'}, {0xdb, '{'}, {0xdc, '|'}, {0xdd, '}'}, {0xc0, '~'}, {VK_BACK, FL_BackSpace}, {VK_TAB, FL_Tab}, {VK_CLEAR, 0xff0b/*XK_Clear*/}, {0xe2 /*VK_OEM_102*/, FL_Iso_Key}, {VK_RETURN, FL_Enter}, {VK_PAUSE, FL_Pause}, {VK_SCROLL, FL_Scroll_Lock}, {VK_ESCAPE, FL_Escape}, {VK_HOME, FL_Home}, {VK_LEFT, FL_Left}, {VK_UP, FL_Up}, {VK_RIGHT, FL_Right}, {VK_DOWN, FL_Down}, {VK_PRIOR, FL_Page_Up}, {VK_NEXT, FL_Page_Down}, {VK_END, FL_End}, {VK_SNAPSHOT, FL_Print}, {VK_INSERT, FL_Insert}, {VK_APPS, FL_Menu}, {VK_NUMLOCK, FL_Num_Lock}, //{VK_???, FL_KP_Enter}, {VK_MULTIPLY, FL_KP+'*'}, {VK_ADD, FL_KP+'+'}, {VK_SUBTRACT, FL_KP+'-'}, {VK_DECIMAL, FL_KP+'.'}, {VK_DIVIDE, FL_KP+'/'}, {VK_LSHIFT, FL_Shift_L}, {VK_RSHIFT, FL_Shift_R}, {VK_LCONTROL, FL_Control_L}, {VK_RCONTROL, FL_Control_R}, {VK_CAPITAL, FL_Caps_Lock}, {VK_LWIN, FL_Meta_L}, {VK_RWIN, FL_Meta_R}, {VK_LMENU, FL_Alt_L}, {VK_RMENU, FL_Alt_R}, {VK_DELETE, FL_Delete} }; static int fltk2ms(int fltk) { if (fltk >= '0' && fltk <= '9') return fltk; if (fltk >= 'A' && fltk <= 'Z') return fltk; if (fltk >= 'a' && fltk <= 'z') return fltk-('a'-'A'); if (fltk > FL_F && fltk <= FL_F+16) return fltk-(FL_F-(VK_F1-1)); if (fltk >= FL_KP+'0' && fltk<=FL_KP+'9') return fltk-(FL_KP+'0'-VK_NUMPAD0); int a = 0; int b = sizeof(vktab)/sizeof(*vktab); while (a < b) { int c = (a+b)/2; if (vktab[c].fltk == fltk) return vktab[c].vk; if (vktab[c].fltk < fltk) a = c+1; else b = c; } return 0; } int Fl_WinAPI_Screen_Driver::event_key(int k) { return GetKeyState(fltk2ms(k))&~1; } int Fl_WinAPI_Screen_Driver::get_key(int k) { uchar foo[256]; GetKeyboardState(foo); return foo[fltk2ms(k)]&~1; } fltk-1.4.3/src/ns.xbm0000644000175000017500000000047415004135251014531 0ustar albrechtalbrecht#define ns_width 16 #define ns_height 16 #define ns_x_hot 8 #define ns_y_hot 8 static unsigned char ns_bits[] = { 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00}; fltk-1.4.3/src/slowarrow.h0000644000175000017500000000046115004135251015605 0ustar albrechtalbrecht#define slowarrow_width 16 #define slowarrow_height 16 static const unsigned char slowarrow_bits[] = { 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x0f, 0x60, 0x00, 0x60, 0x00, 0x40, 0x02, 0x40, 0x02, 0x00, 0x06, 0x00, 0x06, 0xf0, 0x0f, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02}; fltk-1.4.3/src/dump_compose.c0000644000175000017500000000142015004135251016227 0ustar albrechtalbrecht/* write out the documentation for the compose key */ /* copy the string from Fl_Input.C */ static const char* const compose_pairs = " ! @ # $ y=| & : c a <<~ - r _ * +-2 3 ' u p . , 1 o >>141234? " "A`A'A^A~A:A*AEC,E`E'E^E:I`I'I^I:D-N~O`O'O^O~O:x O/U`U'U^U:Y'DDss" "a`a'a^a~a:a*aec,e`e'e^e:i`i'i^i:d-n~o`o'o^o~o:-:o/u`u'u^u:y'ddy:"; #include int main() { int x,y; for (x = 0; x<16; x++) { for (y = 0; y<6; y++) { const char *p = compose_pairs + (16*y+x)*2; if (p[1] == ' ') printf("%c    %c\n", p[0],(p-compose_pairs)/2+0xA0); else printf("%c%c   %c\n", p[0],p[1],(p-compose_pairs)/2+0xA0); } printf(""); } return 0; } fltk-1.4.3/src/CMakeLists.txt0000644000175000017500000007231515004135251016144 0ustar albrechtalbrecht# # CMakeLists.txt to build the FLTK library using CMake (www.cmake.org) # # Copyright 1998-2025 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # # Local macro to check existence of a required file with warning message # # In: FILENAME (string): File to search # Out: WARN (string): *Name* of a variable that is set to true if NOT found # # Set variable ${WARN} to FALSE before calling this macro macro(fl_check_required_file WARN FILENAME) if(NOT EXISTS ${FILENAME}) message("*** Required file not found: ${FILENAME} ***") set(${WARN} TRUE) endif() endmacro(fl_check_required_file WARN FILENAME) set(CPPFILES Fl.cxx Fl_Adjuster.cxx Fl_Bitmap.cxx Fl_Browser.cxx Fl_Browser_.cxx Fl_Browser_load.cxx Fl_Box.cxx Fl_Button.cxx Fl_Chart.cxx Fl_Check_Browser.cxx Fl_Check_Button.cxx Fl_Choice.cxx Fl_Clock.cxx Fl_Color_Chooser.cxx Fl_Copy_Surface.cxx Fl_Counter.cxx Fl_Device.cxx Fl_Dial.cxx Fl_Double_Window.cxx Fl_File_Browser.cxx Fl_File_Chooser.cxx Fl_File_Chooser2.cxx Fl_File_Icon.cxx Fl_File_Input.cxx Fl_Flex.cxx Fl_Graphics_Driver.cxx Fl_Grid.cxx Fl_Group.cxx Fl_Help_View.cxx Fl_Image.cxx Fl_Image_Surface.cxx Fl_Input.cxx Fl_Input_.cxx Fl_Input_Choice.cxx Fl_Int_Vector.cxx Fl_Light_Button.cxx Fl_Menu.cxx Fl_Menu_.cxx Fl_Menu_Bar.cxx Fl_Menu_Button.cxx Fl_Menu_Window.cxx Fl_Menu_add.cxx Fl_Menu_global.cxx Fl_Message.cxx Fl_Multi_Label.cxx Fl_Native_File_Chooser.cxx Fl_Overlay_Window.cxx Fl_Pack.cxx Fl_Paged_Device.cxx Fl_Pixmap.cxx Fl_Positioner.cxx Fl_Preferences.cxx Fl_Printer.cxx Fl_Progress.cxx Fl_Repeat_Button.cxx Fl_Return_Button.cxx Fl_Roller.cxx Fl_Round_Button.cxx Fl_Scheme.cxx Fl_Scheme_Choice.cxx Fl_Screen_Driver.cxx Fl_Scroll.cxx Fl_Scrollbar.cxx Fl_Shared_Image.cxx Fl_Shortcut_Button.cxx Fl_Single_Window.cxx Fl_Slider.cxx Fl_Spinner.cxx Fl_String.cxx Fl_Sys_Menu_Bar.cxx Fl_System_Driver.cxx Fl_Table.cxx Fl_Table_Row.cxx Fl_Tabs.cxx Fl_Terminal.cxx Fl_Text_Buffer.cxx Fl_Text_Display.cxx Fl_Text_Editor.cxx Fl_Tile.cxx Fl_Tiled_Image.cxx Fl_Timeout.cxx Fl_Tooltip.cxx Fl_Tree.cxx Fl_Tree_Item_Array.cxx Fl_Tree_Item.cxx Fl_Tree_Prefs.cxx Fl_Valuator.cxx Fl_Value_Input.cxx Fl_Value_Output.cxx Fl_Value_Slider.cxx Fl_Widget.cxx Fl_Widget_Surface.cxx Fl_Window.cxx Fl_Window_Driver.cxx Fl_Window_fullscreen.cxx Fl_Window_hotspot.cxx Fl_Window_iconize.cxx Fl_Wizard.cxx Fl_XBM_Image.cxx Fl_XPM_Image.cxx Fl_abort.cxx Fl_add_idle.cxx Fl_arg.cxx Fl_compose.cxx Fl_display.cxx Fl_get_system_colors.cxx Fl_grab.cxx Fl_lock.cxx Fl_own_colormap.cxx Fl_visual.cxx filename_absolute.cxx filename_expand.cxx filename_ext.cxx filename_isdir.cxx filename_list.cxx filename_match.cxx filename_setext.cxx fl_arc.cxx fl_ask.cxx fl_boxtype.cxx fl_color.cxx fl_contrast.cxx fl_cursor.cxx fl_curve.cxx fl_diamond_box.cxx fl_draw.cxx fl_draw_arrow.cxx fl_draw_pixmap.cxx fl_encoding_latin1.cxx fl_encoding_mac_roman.cxx fl_engraved_label.cxx fl_file_dir.cxx fl_font.cxx fl_gleam.cxx fl_gtk.cxx fl_labeltype.cxx fl_open_uri.cxx fl_oval_box.cxx fl_overlay.cxx fl_oxy.cxx fl_plastic.cxx fl_read_image.cxx fl_rect.cxx fl_round_box.cxx fl_rounded_box.cxx fl_set_font.cxx fl_scroll_area.cxx fl_shadow_box.cxx fl_shortcut.cxx fl_show_colormap.cxx fl_string_functions.cxx fl_symbols.cxx fl_utf8.cxx fl_vertex.cxx print_button.cxx screen_xywh.cxx ) if(FLTK_HAVE_CAIRO) # FLTK_OPTION_CAIRO_WINDOW or FLTK_OPTION_CAIRO_EXT list(APPEND CPPFILES Fl_Cairo.cxx) endif() # find all header files in source directory file(GLOB HEADER_FILES "../FL/*.[hH]" ) # add generated header files in build directory list(APPEND HEADER_FILES ${CMAKE_CURRENT_BINARY_DIR}/../FL/fl_config.h ${CMAKE_CURRENT_BINARY_DIR}/../config.h ) set(GL_HEADER_FILES) # FIXME: not (yet?) defined if(FLTK_USE_X11 AND NOT FLTK_OPTION_PRINT_SUPPORT) set(PSFILES) else() set(PSFILES drivers/PostScript/Fl_PostScript.cxx drivers/PostScript/Fl_PostScript_image.cxx ) endif(FLTK_USE_X11 AND NOT FLTK_OPTION_PRINT_SUPPORT) set(DRIVER_FILES) if(FLTK_USE_X11 AND NOT FLTK_BACKEND_WAYLAND) # X11 (including APPLE with X11) set(DRIVER_FILES drivers/Posix/Fl_Posix_Printer_Driver.cxx drivers/X11/Fl_X11_Screen_Driver.cxx drivers/X11/Fl_X11_Window_Driver.cxx drivers/Posix/Fl_Posix_System_Driver.cxx drivers/Unix/Fl_Unix_System_Driver.cxx drivers/Unix/Fl_Unix_Screen_Driver.cxx drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx drivers/X11/fl_X11_platform_init.cxx Fl_x.cxx fl_dnd_x.cxx Fl_Native_File_Chooser_FLTK.cxx Fl_Native_File_Chooser_GTK.cxx Fl_get_key.cxx ) list(APPEND DRIVER_FILES Fl_Native_File_Chooser_Kdialog.cxx Fl_Native_File_Chooser_Zenity.cxx) if(FLTK_USE_CAIRO) list(APPEND DRIVER_FILES drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.cxx ) else() if(USE_XFT) list(APPEND DRIVER_FILES drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx ) if(USE_PANGO) list(APPEND DRIVER_FILES drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx) endif(USE_PANGO) else() list(APPEND DRIVER_FILES drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx ) endif(USE_XFT) list(APPEND DRIVER_FILES drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx drivers/Xlib/Fl_Xlib_Graphics_Driver_color.cxx drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx ) endif(FLTK_USE_CAIRO) set(DRIVER_HEADER_FILES drivers/Posix/Fl_Posix_System_Driver.H drivers/X11/Fl_X11_Screen_Driver.H drivers/X11/Fl_X11_Window_Driver.H drivers/Xlib/Fl_Xlib_Graphics_Driver.H drivers/Xlib/Fl_Font.H drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H drivers/Unix/Fl_Unix_System_Driver.H ) if(FLTK_USE_CAIRO) set(DRIVER_HEADER_FILES ${DRIVER_HEADER_FILES} drivers/Cairo/Fl_Cairo_Graphics_Driver.H drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.H ) elseif(USE_PANGO) set(DRIVER_HEADER_FILES ${DRIVER_HEADER_FILES} drivers/Cairo/Fl_Cairo_Graphics_Driver.H ) endif(FLTK_USE_CAIRO) elseif(FLTK_BACKEND_WAYLAND) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_CURRENT_BINARY_DIR}") set(DRIVER_FILES drivers/Posix/Fl_Posix_System_Driver.cxx drivers/Posix/Fl_Posix_Printer_Driver.cxx drivers/Unix/Fl_Unix_Screen_Driver.cxx drivers/Wayland/Fl_Wayland_Screen_Driver.cxx drivers/Wayland/Fl_Wayland_Window_Driver.cxx drivers/Unix/Fl_Unix_System_Driver.cxx drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx drivers/Wayland/fl_wayland_clipboard_dnd.cxx drivers/Wayland/fl_wayland_platform_init.cxx drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx Fl_Native_File_Chooser_FLTK.cxx Fl_Native_File_Chooser_GTK.cxx ) list(APPEND DRIVER_FILES Fl_Native_File_Chooser_Kdialog.cxx Fl_Native_File_Chooser_Zenity.cxx) if(FLTK_USE_X11) list(APPEND DRIVER_FILES drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.cxx drivers/X11/Fl_X11_Screen_Driver.cxx drivers/X11/Fl_X11_Window_Driver.cxx drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx Fl_x.cxx fl_dnd_x.cxx Fl_get_key.cxx ) endif(FLTK_USE_X11) set(DRIVER_HEADER_FILES drivers/Posix/Fl_Posix_System_Driver.H drivers/Wayland/Fl_Wayland_Screen_Driver.H drivers/Wayland/Fl_Wayland_Window_Driver.H drivers/Wayland/Fl_Wayland_Graphics_Driver.H drivers/Cairo/Fl_Cairo_Graphics_Driver.H drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.H drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.H drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H drivers/Unix/Fl_Unix_System_Driver.H ) elseif(APPLE) # Apple Quartz set(DRIVER_FILES drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx drivers/Quartz/Fl_Quartz_Graphics_Driver_color.cxx drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx drivers/Quartz/Fl_Quartz_Graphics_Driver_vertex.cxx drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx drivers/Quartz/Fl_Quartz_Graphics_Driver_arci.cxx drivers/Quartz/Fl_Quartz_Graphics_Driver_line_style.cxx drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx drivers/Posix/Fl_Posix_System_Driver.cxx drivers/Darwin/Fl_Darwin_System_Driver.cxx Fl_get_key_mac.cxx drivers/Darwin/fl_macOS_platform_init.cxx ) set(DRIVER_HEADER_FILES drivers/Posix/Fl_Posix_System_Driver.H drivers/Darwin/Fl_Darwin_System_Driver.H drivers/Cocoa/Fl_Cocoa_Screen_Driver.H drivers/Cocoa/Fl_Cocoa_Window_Driver.H drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H drivers/Quartz/Fl_Quartz_Graphics_Driver.H drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.H drivers/Quartz/Fl_Font.H drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H ) else() # Windows (GDI) set(DRIVER_FILES drivers/WinAPI/Fl_WinAPI_System_Driver.cxx drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx drivers/GDI/Fl_GDI_Graphics_Driver.cxx drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx Fl_win32.cxx fl_dnd_win32.cxx Fl_Native_File_Chooser_WIN32.cxx Fl_get_key_win32.cxx drivers/WinAPI/fl_WinAPI_platform_init.cxx ) set(DRIVER_HEADER_FILES drivers/WinAPI/Fl_WinAPI_System_Driver.H drivers/WinAPI/Fl_WinAPI_Screen_Driver.H drivers/WinAPI/Fl_WinAPI_Window_Driver.H drivers/GDI/Fl_GDI_Graphics_Driver.H drivers/GDI/Fl_Font.H drivers/GDI/Fl_GDI_Copy_Surface_Driver.H drivers/GDI/Fl_GDI_Image_Surface_Driver.H ) endif(FLTK_USE_X11 AND NOT FLTK_BACKEND_WAYLAND) source_group("Header Files" FILES ${HEADER_FILES}) source_group("Driver Source Files" FILES ${DRIVER_FILES}) source_group("Driver Header Files" FILES ${DRIVER_HEADER_FILES}) set(CPPFILES ${CPPFILES} ${DRIVER_FILES} ) if(FLTK_BUILD_FORMS) set(FORMS_FILES forms_compatibility.cxx forms_bitmap.cxx forms_free.cxx forms_fselect.cxx forms_pixmap.cxx forms_timer.cxx ) else() set(FORMS_FILES "") endif() set(GLCPPFILES Fl_Gl_Choice.cxx Fl_Gl_Device_Plugin.cxx Fl_Gl_Overlay.cxx Fl_Gl_Window.cxx freeglut_geometry.cxx freeglut_stroke_mono_roman.cxx freeglut_stroke_roman.cxx freeglut_teapot.cxx gl_draw.cxx gl_start.cxx glut_compatibility.cxx glut_font.cxx ) set(GL_DRIVER_FILES drivers/OpenGL/Fl_OpenGL_Display_Device.cxx # the following file doesn't contribute any code: # drivers/OpenGL/Fl_OpenGL_Graphics_Driver.cxx drivers/OpenGL/Fl_OpenGL_Graphics_Driver_arci.cxx drivers/OpenGL/Fl_OpenGL_Graphics_Driver_color.cxx drivers/OpenGL/Fl_OpenGL_Graphics_Driver_font.cxx drivers/OpenGL/Fl_OpenGL_Graphics_Driver_line_style.cxx drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.cxx drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.cxx ) if(FLTK_BACKEND_WAYLAND) set(GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx) set(GL_DRIVER_HEADER_FILES drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H) if(FLTK_USE_X11) list(APPEND GL_DRIVER_FILES drivers/X11/Fl_X11_Gl_Window_Driver.cxx) list(APPEND GL_DRIVER_HEADER_FILES drivers/X11/Fl_X11_Gl_Window_Driver.H) endif(FLTK_USE_X11) elseif(FLTK_USE_X11) set(GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/X11/Fl_X11_Gl_Window_Driver.cxx) set(GL_DRIVER_HEADER_FILES drivers/X11/Fl_X11_Gl_Window_Driver.H) elseif(APPLE) set(GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.mm) set(GL_DRIVER_HEADER_FILES drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H) elseif(WIN32) set(GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx) set(GL_DRIVER_HEADER_FILES drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H) endif(FLTK_BACKEND_WAYLAND) set(GL_DRIVER_HEADER_FILES ${GL_DRIVER_FILES} drivers/OpenGL/Fl_OpenGL_Display_Device.H drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H ) source_group("Driver Header Files" FILES ${GL_DRIVER_HEADER_FILES}) source_group("Driver Source Files" FILES ${GL_DRIVER_FILES}) set(GLCPPFILES ${GLCPPFILES} ${GL_DRIVER_FILES} ) set(IMGCPPFILES fl_images_core.cxx fl_write_png.cxx Fl_BMP_Image.cxx Fl_File_Icon2.cxx Fl_GIF_Image.cxx Fl_Anim_GIF_Image.cxx Fl_Help_Dialog.cxx Fl_ICO_Image.cxx Fl_JPEG_Image.cxx Fl_PNG_Image.cxx Fl_PNM_Image.cxx Fl_Image_Reader.cxx Fl_SVG_Image.cxx nanosvg.cxx drivers/SVG/Fl_SVG_File_Surface.cxx ) set(CFILES flstring.c numericsort.c vsnprintf.c xutf8/is_right2left.c xutf8/is_spacing.c xutf8/case.c ) if(FLTK_USE_X11) list(APPEND CFILES xutf8/keysym2Ucs.c scandir_posix.c ) if(NOT USE_XFT) list(APPEND CFILES xutf8/utf8Utils.c xutf8/utf8Wrap.c xutf8/utf8Input.c ) endif(NOT USE_XFT) endif(FLTK_USE_X11) if(FLTK_BACKEND_WAYLAND) pkg_check_modules(DBUS IMPORTED_TARGET dbus-1) set(IDIRS "${CMAKE_CURRENT_BINARY_DIR}") set(CDEFS "_GNU_SOURCE;HAVE_MEMFD_CREATE;HAVE_MKOSTEMP;HAVE_POSIX_FALLOCATE") set(COPTS "-fPIC") if(DBUS_FOUND) set(CDEFS "${CDEFS};HAS_DBUS") set(IDIRS "${IDIRS};${DBUS_INCLUDE_DIRS}") endif(DBUS_FOUND) if(USE_SYSTEM_LIBDECOR) set(CDEFS "${CDEFS};USE_SYSTEM_LIBDECOR;LIBDECOR_PLUGIN_DIR=${LIBDECOR_PLUGIN_DIR}") if(GTK_FOUND) set(CDEFS "${CDEFS};HAVE_GTK") endif(GTK_FOUND) set_source_files_properties( ${FLTK_SOURCE_DIR}/libdecor/build/fl_libdecor-plugins.c ${FLTK_SOURCE_DIR}/libdecor/src/os-compatibility.c ${FLTK_SOURCE_DIR}/libdecor/src/desktop-settings.c PROPERTIES COMPILE_DEFINITIONS "${CDEFS}" INCLUDE_DIRECTORIES "${IDIRS}" COMPILE_OPTIONS "${COPTS}" ) else() set(IDIRS "${IDIRS};${FLTK_SOURCE_DIR}/libdecor/src" "${FLTK_SOURCE_DIR}/libdecor/src/plugins") set(CDEFS "${CDEFS};USE_SYSTEM_LIBDECOR=0;LIBDECOR_PLUGIN_API_VERSION=1" "LIBDECOR_PLUGIN_DIR=\"\"") if(GTK_FOUND AND FLTK_USE_LIBDECOR_GTK) set(CDEFS "${CDEFS};HAVE_GTK") endif(GTK_FOUND AND FLTK_USE_LIBDECOR_GTK) set_source_files_properties( ${FLTK_SOURCE_DIR}/libdecor/build/fl_libdecor.c ${FLTK_SOURCE_DIR}/libdecor/build/fl_libdecor-plugins.c ${FLTK_SOURCE_DIR}/libdecor/src/os-compatibility.c ${FLTK_SOURCE_DIR}/libdecor/src/desktop-settings.c PROPERTIES COMPILE_DEFINITIONS "${CDEFS}" INCLUDE_DIRECTORIES "${IDIRS}" COMPILE_OPTIONS "${COPTS}" ) endif(USE_SYSTEM_LIBDECOR) set_source_files_properties( ${FLTK_SOURCE_DIR}/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx ${FLTK_SOURCE_DIR}/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx PROPERTIES COMPILE_DEFINITIONS "USE_SYSTEM_LIBDECOR=${USE_SYSTEM_LIBDECOR}" ) list(APPEND CFILES scandir_posix.c ../libdecor/src/desktop-settings.c ../libdecor/src/os-compatibility.c ../libdecor/build/fl_libdecor-plugins.c ) if(FLTK_USE_X11) list(APPEND CFILES xutf8/keysym2Ucs.c) endif(FLTK_USE_X11) if(NOT USE_SYSTEM_LIBDECOR) list(APPEND CFILES ../libdecor/build/fl_libdecor.c ../libdecor/src/plugins/common/libdecor-cairo-blur.c ) endif(NOT USE_SYSTEM_LIBDECOR) endif(FLTK_BACKEND_WAYLAND) if(WIN32) list(APPEND CFILES scandir_win32.c ) endif(WIN32) if(APPLE AND NOT FLTK_BACKEND_X11) set(MMFILES Fl_cocoa.mm drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm Fl_Native_File_Chooser_MAC.mm Fl_MacOS_Sys_Menu_Bar.mm ) else() set(MMFILES) endif() ####################################################################### # prepare source files for shared and static FLTK libraries set(SHARED_FILES ${CPPFILES} ${MMFILES} ${CFILES} ${PSFILES}) list(APPEND SHARED_FILES ${HEADER_FILES} ${DRIVER_HEADER_FILES}) set(STATIC_FILES ${SHARED_FILES}) # Visual Studio (MSVC) is known to need WinMain() and maybe BORLAND # needs it as well, hence we include it on all Windows platforms. # The GNU compilers (MinGW, MSYS2, Cygwin) disable compilation inside # the source file which is what we finally want and need. if(WIN32) list(APPEND STATIC_FILES fl_call_main.c) endif() ####################################################################### # # Prepare optional libs for shared and static FLTK libraries. # # Notes: # - 'OPTIONAL_LIBS' is a CMake 'list' but must not contain arbitrary # CMake targets because these targets would be propagated to # consumer projects. The macro below simplifies adding link # libraries of such targets to 'OPTIONAL_LIBS'. # - 'OPTIONAL_INCLUDES' is a similar CMake list that defines additional # include directories. # # This macro appends link libraries to 'OPTIONAL_LIBS' and include # directories to 'OPTIONAL_INCLUDES'. # # Input: # 'targets' may be a CMake list of targets or a single target. # It must be quoted if multiple targets are to be added in # one call (see examples below). # ####################################################################### set(OPTIONAL_LIBS) set(OPTIONAL_INCLUDES) macro(append_optional_libs targets) foreach(_target ${targets}) get_target_property(_link_libraries ${_target} INTERFACE_LINK_LIBRARIES) if(_link_libraries) list(APPEND OPTIONAL_LIBS ${_link_libraries}) endif() get_target_property(_include_dirs ${_target} INTERFACE_INCLUDE_DIRECTORIES) if(_include_dirs) list(APPEND OPTIONAL_INCLUDES ${_include_dirs}) endif() endforeach() unset(_target) unset(_link_libraries) unset(_include_dirs) endmacro() # Add the required properties for ${OPTIONAL_LIBS} to the given target. # Note: we must use 'PUBLIC', see GitHub Issue #1173 macro(add_optional_libs target) target_link_libraries (${target} PUBLIC ${OPTIONAL_LIBS}) target_include_directories(${target} PUBLIC ${OPTIONAL_INCLUDES}) endmacro() # Build the list of optional libs if(LIB_dl) list(APPEND OPTIONAL_LIBS ${LIB_dl}) endif(LIB_dl) if(USE_THREADS) list(APPEND OPTIONAL_LIBS ${CMAKE_THREAD_LIBS_INIT}) endif(USE_THREADS) if(FLTK_USE_X11) list(APPEND OPTIONAL_LIBS ${X11_LIBRARIES}) list(APPEND OPTIONAL_INCLUDES ${X11_INCLUDE_DIR}) endif(FLTK_USE_X11) if(WIN32) list(APPEND OPTIONAL_LIBS comctl32 ws2_32) if(USE_GDIPLUS) list(APPEND OPTIONAL_LIBS gdiplus) endif() endif(WIN32) if(HAVE_XINERAMA) list(APPEND OPTIONAL_LIBS ${X11_Xinerama_LIB}) endif(HAVE_XINERAMA) if(HAVE_XFIXES) list(APPEND OPTIONAL_LIBS ${X11_Xfixes_LIB}) endif(HAVE_XFIXES) if(HAVE_XCURSOR) list(APPEND OPTIONAL_LIBS ${X11_Xcursor_LIB}) endif(HAVE_XCURSOR) if(HAVE_XRENDER) list(APPEND OPTIONAL_LIBS ${X11_Xrender_LIB}) endif(HAVE_XRENDER) if(USE_PANGO) list(APPEND OPTIONAL_LIBS ${HAVE_LIB_PANGO}) append_optional_libs(PkgConfig::PANGOCAIRO) list(APPEND OPTIONAL_LIBS ${HAVE_LIB_GOBJECT}) if(USE_PANGOXFT) append_optional_libs(PkgConfig::PANGOXFT) endif(USE_PANGOXFT) endif(USE_PANGO) if(USE_XFT) list(APPEND OPTIONAL_LIBS ${X11_Xft_LIB}) if(LIB_fontconfig) list(APPEND OPTIONAL_LIBS ${LIB_fontconfig}) endif(LIB_fontconfig) endif(USE_XFT) if(UNIX AND FLTK_BACKEND_WAYLAND) pkg_get_variable(PROTOCOLS wayland-protocols pkgdatadir) # replace "//" with "/" string(REPLACE "//" "/" PROTOCOLS ${PROTOCOLS}) # The following variable is used for finding required files and to terminate # the build if one or more files are not found. For user convenience # the build is terminated after *all* files have been checked. set(STOP_REQUIRED FALSE) set(INFILE ${PROTOCOLS}/stable/xdg-shell/xdg-shell.xml) fl_check_required_file(STOP_REQUIRED ${INFILE}) add_custom_command( OUTPUT xdg-shell-protocol.c xdg-shell-client-protocol.h COMMAND wayland-scanner private-code ${INFILE} xdg-shell-protocol.c COMMAND wayland-scanner client-header ${INFILE} xdg-shell-client-protocol.h DEPENDS ${INFILE} VERBATIM ) list(APPEND STATIC_FILES "xdg-shell-protocol.c") list(APPEND SHARED_FILES "xdg-shell-protocol.c") if(NOT USE_SYSTEM_LIBDECOR) set(INFILE ${PROTOCOLS}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml) fl_check_required_file(STOP_REQUIRED ${INFILE}) add_custom_command( OUTPUT xdg-decoration-protocol.c xdg-decoration-client-protocol.h COMMAND wayland-scanner private-code ${INFILE} xdg-decoration-protocol.c COMMAND wayland-scanner client-header ${INFILE} xdg-decoration-client-protocol.h DEPENDS ${INFILE} VERBATIM ) list(APPEND STATIC_FILES "xdg-decoration-protocol.c") list(APPEND SHARED_FILES "xdg-decoration-protocol.c") endif(NOT USE_SYSTEM_LIBDECOR) set(INFILE ${FLTK_SOURCE_DIR}/libdecor/build/gtk-shell.xml) add_custom_command( OUTPUT gtk-shell-protocol.c gtk-shell-client-protocol.h COMMAND wayland-scanner private-code ${INFILE} gtk-shell-protocol.c COMMAND wayland-scanner client-header ${INFILE} gtk-shell-client-protocol.h DEPENDS ${INFILE} VERBATIM ) list(APPEND STATIC_FILES "gtk-shell-protocol.c") list(APPEND SHARED_FILES "gtk-shell-protocol.c") set(INFILE ${PROTOCOLS}/unstable/text-input/text-input-unstable-v3.xml) fl_check_required_file(STOP_REQUIRED ${INFILE}) add_custom_command( OUTPUT text-input-protocol.c text-input-client-protocol.h COMMAND wayland-scanner private-code ${INFILE} text-input-protocol.c COMMAND wayland-scanner client-header ${INFILE} text-input-client-protocol.h DEPENDS ${INFILE} VERBATIM ) list(APPEND STATIC_FILES "text-input-protocol.c") list(APPEND SHARED_FILES "text-input-protocol.c") if(STOP_REQUIRED) message(FATAL_ERROR "*** Terminating: one or more required file(s) were not found. ***") endif() if(FLTK_USE_GL) append_optional_libs("PkgConfig::WLD_EGL;PkgConfig::PKG_EGL") endif(FLTK_USE_GL) if(USE_SYSTEM_LIBDECOR) append_optional_libs(PkgConfig::SYSTEM_LIBDECOR) elseif(GTK_FOUND AND FLTK_USE_LIBDECOR_GTK) append_optional_libs(PkgConfig::GTK) endif() append_optional_libs("PkgConfig::WLDCURSOR;PkgConfig::WLDCLIENT;PkgConfig::XKBCOMMON") if(DBUS_FOUND) append_optional_libs(PkgConfig::DBUS) endif() endif(UNIX AND FLTK_BACKEND_WAYLAND) list(REMOVE_DUPLICATES OPTIONAL_LIBS) list(REMOVE_DUPLICATES OPTIONAL_INCLUDES) ####################################################################### fl_add_library(fltk STATIC "${STATIC_FILES}") add_optional_libs(fltk) ####################################################################### if(FLTK_BUILD_FORMS) fl_add_library(fltk_forms STATIC "${FORMS_FILES}") target_link_libraries(fltk_forms PUBLIC fltk::fltk) endif() ####################################################################### if(0) message(STATUS "---------------------- fltk_images -----------------------") fl_debug_var(FLTK_JPEG_LIBRARIES) fl_debug_var(FLTK_PNG_LIBRARIES) fl_debug_var(FLTK_ZLIB_LIBRARIES) fl_debug_var(FLTK_IMAGE_LIBRARIES) message(STATUS "---------------------- fltk_images -----------------------") endif() fl_add_library(fltk_images STATIC "${IMGCPPFILES}") target_link_libraries(fltk_images PUBLIC fltk::fltk) target_link_libraries(fltk_images PRIVATE ${FLTK_IMAGE_LIBRARIES}) if(FLTK_USE_BUNDLED_JPEG) target_include_directories(fltk_images PUBLIC $ $) endif() if(FLTK_USE_BUNDLED_PNG) target_include_directories(fltk_images PUBLIC $ $) endif() if(FLTK_USE_BUNDLED_ZLIB) target_include_directories(fltk_images PUBLIC $ $) endif() ####################################################################### if(FLTK_USE_GL) fl_add_library(fltk_gl STATIC "${GLCPPFILES};${GL_HEADER_FILES};${GL_DRIVER_HEADER_FILES}") target_link_libraries(fltk_gl PUBLIC ${OPENGL_LIBRARIES} fltk::fltk) target_include_directories(fltk_gl PUBLIC ${OPENGL_INCLUDE_DIR} ${OPENGL_INCLUDE_DIRS}) # Add "optional libs" (FIXME: this can be optimized, we don't need *all* these libs here) add_optional_libs(fltk_gl) if(FLTK_OPENGL_GLU_INCLUDE_DIR) target_include_directories(fltk_gl PUBLIC ${FLTK_OPENGL_GLU_INCLUDE_DIR}) endif() endif(FLTK_USE_GL) ####################################################################### # Build shared libraries (optional) ####################################################################### # Shared libraries, part 1: everything except Visual Studio (MSVC) ####################################################################### if(FLTK_BUILD_SHARED_LIBS AND NOT MSVC) fl_add_library(fltk SHARED "${SHARED_FILES}") add_optional_libs(fltk-shared) ################################################################### if(FLTK_BUILD_FORMS) fl_add_library(fltk_forms SHARED "${FORMS_FILES}") target_link_libraries(fltk_forms-shared PUBLIC fltk::fltk-shared) endif() ################################################################### fl_add_library(fltk_images SHARED "${IMGCPPFILES}") target_link_libraries(fltk_images-shared PUBLIC fltk::fltk-shared) target_link_libraries(fltk_images PUBLIC ${FLTK_JPEG_LIBRARIES}) target_link_libraries(fltk_images PUBLIC ${FLTK_PNG_LIBRARIES}) target_link_libraries(fltk_images PUBLIC ${FLTK_IMAGE_LIBRARIES}) if(FLTK_USE_BUNDLED_JPEG) target_include_directories(fltk_images-shared PUBLIC $ # $ ) endif() if(FLTK_USE_BUNDLED_JPEG) target_link_libraries(fltk_images-shared PUBLIC fltk::jpeg-shared) else() target_link_libraries(fltk_images-shared PUBLIC ${JPEG_LIBRARIES}) endif() if(FLTK_USE_BUNDLED_PNG) target_link_libraries(fltk_images-shared PUBLIC fltk::png-shared) else() target_link_libraries(fltk_images-shared PUBLIC ${PNG_LIBRARIES}) endif() ################################################################### if(FLTK_USE_GL) fl_add_library(fltk_gl SHARED "${GLCPPFILES};${GL_HEADER_FILES};${GL_DRIVER_HEADER_FILES}") target_link_libraries(fltk_gl-shared PUBLIC ${OPENGL_LIBRARIES} fltk::fltk-shared) target_include_directories(fltk_gl-shared PUBLIC ${OPENGL_INCLUDE_DIR} ${OPENGL_INCLUDE_DIRS}) # Add "optional libs" (FIXME: this can be optimized, we don't need *all* these libs here) add_optional_libs(fltk_gl-shared) if(FLTK_OPENGL_GLU_INCLUDE_DIR) target_include_directories(fltk_gl-shared PUBLIC ${FLTK_OPENGL_GLU_INCLUDE_DIR}) endif() endif(FLTK_USE_GL) endif(FLTK_BUILD_SHARED_LIBS AND NOT MSVC) ####################################################################### # Shared libraries, part 2: Visual Studio (MSVC) ####################################################################### # Note to devs: As of June 2020 we can't build separate shared libs # (DLL's) under Windows with Visual Studio (MSVC) but we can build one # big DLL that comprises all FLTK and optional PNG, JPEG, and ZLIB libs. # The reason is the common DLL linkage (FL_EXPORT) for all libs. This # might be changed in the future but it would require a lot of work. # AlbrechtS if(FLTK_BUILD_SHARED_LIBS AND MSVC) set(SOURCES ${SHARED_FILES} ${FORMS_FILES} ${IMGCPPFILES}) if(OPENGL_FOUND) list(APPEND SOURCES ${GLCPPFILES} ${GL_HEADER_FILES} ${GL_DRIVER_HEADER_FILES}) endif(OPENGL_FOUND) fl_add_library(fltk SHARED "${SOURCES}") add_optional_libs(fltk-shared) if(FLTK_USE_BUNDLED_JPEG) target_link_libraries(fltk-shared PUBLIC fltk::jpeg-shared) else() target_link_libraries(fltk-shared PUBLIC ${FLTK_JPEG_LIBRARIES}) endif() if(FLTK_USE_BUNDLED_PNG) target_link_libraries(fltk-shared PUBLIC fltk::png-shared) else() target_link_libraries(fltk-shared PUBLIC ${FLTK_PNG_LIBRARIES}) endif() if(OPENGL_FOUND) target_link_libraries(fltk-shared PUBLIC ${OPENGL_LIBRARIES}) target_include_directories(fltk-shared PUBLIC ${OPENGL_INCLUDE_DIR} ${OPENGL_INCLUDE_DIRS}) if(FLTK_OPENGL_GLU_INCLUDE_DIR) target_include_directories(fltk-shared PUBLIC ${FLTK_OPENGL_GLU_INCLUDE_DIR}) endif() endif(OPENGL_FOUND) endif(FLTK_BUILD_SHARED_LIBS AND MSVC) ####################################################################### set(FLTK_LIBRARIES ${FLTK_LIBRARIES} PARENT_SCOPE) set(FLTK_LIBRARIES_SHARED ${FLTK_LIBRARIES_SHARED} PARENT_SCOPE) fltk-1.4.3/src/Fl_System_Driver.cxx0000644000175000017500000002374415004135251017352 0ustar albrechtalbrecht// // A base class for platform specific system calls. // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \defgroup DriverDeveloper Driver Developer Documentation \{ */ #include "Fl_System_Driver.H" #include #include "Fl_Timeout.h" #include #include #include #include #include #include #include "flstring.h" #include int Fl_System_Driver::command_key = 0; int Fl_System_Driver::control_key = 0; int fl_command_modifier() { if (!Fl_System_Driver::command_key) Fl::system_driver(); return Fl_System_Driver::command_key; } int fl_control_modifier() { if (!Fl_System_Driver::control_key) Fl::system_driver(); return Fl_System_Driver::control_key; } Fl_System_Driver::Fl_System_Driver() { command_key = FL_CTRL; control_key = FL_META; } Fl_System_Driver::~Fl_System_Driver() { } void Fl_System_Driver::warning(const char* format, ...) { va_list args; va_start(args, format); Fl::system_driver()->warning(format, args); va_end(args); } void Fl_System_Driver::warning(const char* format, va_list args) { vfprintf(stderr, format, args); fputc('\n', stderr); fflush(stderr); } void Fl_System_Driver::error(const char* format, ...) { va_list args; va_start(args, format); Fl::system_driver()->error(format, args); va_end(args); } void Fl_System_Driver::error(const char *format, va_list args) { vfprintf(stderr, format, args); fputc('\n', stderr); fflush(stderr); } void Fl_System_Driver::fatal(const char* format, ...) { va_list args; va_start(args, format); Fl::system_driver()->fatal(format, args); va_end(args); } void Fl_System_Driver::fatal(const char *format, va_list args) { vfprintf(stderr, format, args); fputc('\n', stderr); fflush(stderr); exit(1); } unsigned Fl_System_Driver::utf8towc(const char* src, unsigned srclen, wchar_t* dst, unsigned dstlen) { const char* p = src; const char* e = src+srclen; unsigned count = 0; if (dstlen) for (;;) { if (p >= e) { dst[count] = 0; return count; } if (!(*p & 0x80)) { /* ascii */ dst[count] = *p++; } else { int len; unsigned ucs = fl_utf8decode(p,e,&len); p += len; dst[count] = (wchar_t)ucs; } if (++count == dstlen) {dst[count-1] = 0; break;} } /* we filled dst, measure the rest: */ while (p < e) { if (!(*p & 0x80)) p++; else { int len; fl_utf8decode(p,e,&len); p += len; } ++count; } return count; } unsigned Fl_System_Driver::utf8fromwc(char* dst, unsigned dstlen, const wchar_t* src, unsigned srclen) { unsigned i = 0; unsigned count = 0; if (dstlen) for (;;) { unsigned ucs; if (i >= srclen) {dst[count] = 0; return count;} ucs = src[i++]; if (ucs < 0x80U) { dst[count++] = ucs; if (count >= dstlen) {dst[count-1] = 0; break;} } else if (ucs < 0x800U) { /* 2 bytes */ if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;} dst[count++] = 0xc0 | (ucs >> 6); dst[count++] = 0x80 | (ucs & 0x3F); } else if (ucs >= 0x10000) { if (ucs > 0x10ffff) { ucs = 0xfffd; goto J1; } if (count+4 >= dstlen) {dst[count] = 0; count += 4; break;} dst[count++] = 0xf0 | (ucs >> 18); dst[count++] = 0x80 | ((ucs >> 12) & 0x3F); dst[count++] = 0x80 | ((ucs >> 6) & 0x3F); dst[count++] = 0x80 | (ucs & 0x3F); } else { J1: /* all others are 3 bytes: */ if (count+3 >= dstlen) {dst[count] = 0; count += 3; break;} dst[count++] = 0xe0 | (ucs >> 12); dst[count++] = 0x80 | ((ucs >> 6) & 0x3F); dst[count++] = 0x80 | (ucs & 0x3F); } } /* we filled dst, measure the rest: */ while (i < srclen) { unsigned ucs = src[i++]; if (ucs < 0x80U) { count++; } else if (ucs < 0x800U) { /* 2 bytes */ count += 2; } else if (ucs >= 0x10000 && ucs <= 0x10ffff) { count += 4; } else { count += 3; } } return count; } unsigned Fl_System_Driver::utf8to_mb(const char* src, unsigned srclen, char* dst, unsigned dstlen) { wchar_t lbuf[1024]; wchar_t* buf = lbuf; unsigned length = fl_utf8towc(src, srclen, buf, 1024); int ret; // note: wcstombs() returns unsigned(length) or unsigned(-1) if (length >= 1024) { buf = (wchar_t*)(malloc((length+1)*sizeof(wchar_t))); fl_utf8towc(src, srclen, buf, length+1); } if (dstlen) { ret = (int)wcstombs(dst, buf, dstlen); if (ret >= (int)dstlen-1) ret = (int)wcstombs(0,buf,0); } else { ret = (int)wcstombs(0,buf,0); } if (buf != lbuf) free(buf); if (ret >= 0) return (unsigned)ret; // on any errors we return the UTF-8 as raw text... if (srclen < dstlen) { memcpy(dst, src, srclen); dst[srclen] = 0; } else { // Buffer insufficent or buffer query } return srclen; } unsigned Fl_System_Driver::utf8from_mb(char* dst, unsigned dstlen, const char* src, unsigned srclen) { wchar_t lbuf[1024]; wchar_t* buf = lbuf; int length; unsigned ret; length = (int)mbstowcs(buf, src, 1024); if (length >= 1024) { length = (int)mbstowcs(0, src, 0)+1; buf = (wchar_t*)(malloc(length*sizeof(wchar_t))); mbstowcs(buf, src, length); } if (length >= 0) { ret = fl_utf8fromwc(dst, dstlen, buf, length); if (buf != lbuf) free(buf); return ret; } // errors in conversion return the UTF-8 unchanged if (srclen < dstlen) { memcpy(dst, src, srclen); dst[srclen] = 0; } else { // Buffer insufficent or buffer query } return srclen; } int Fl_System_Driver::clocale_vprintf(FILE *output, const char *format, va_list args) { return vfprintf(output, format, args); } int Fl_System_Driver::clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args) { return 0; // overridden in platform drivers } int Fl_System_Driver::clocale_vsscanf(const char *input, const char *format, va_list args) { return 0; // overridden in platform drivers } int Fl_System_Driver::filename_expand(char *to,int tolen, const char *from) { char *temp = new char[tolen]; strlcpy(temp,from, tolen); char *start = temp; char *end = temp+strlen(temp); int ret = 0; for (char *a=temp; a= tolen) end += tolen - (end+1-e+t); memmove(a+t, e, end+1-e); end = a+t+(end-e); *end = '\0'; memcpy(a, value, t); ret++; } else { a = e+1; } } strlcpy(to, start, tolen); delete[] temp; return ret; } int Fl_System_Driver::file_browser_load_directory(const char *directory, char *filename, size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort, char *errmsg, int errmsg_sz) { return filename_list(directory, pfiles, sort, errmsg, errmsg_sz); } int Fl_System_Driver::file_type(const char *filename) { return Fl_File_Icon::ANY; } void Fl_System_Driver::add_fd(int fd, int when, Fl_FD_Handler cb, void *d) { // nothing to do, reimplement in driver if needed } void Fl_System_Driver::add_fd(int fd, Fl_FD_Handler cb, void *d) { // nothing to do, reimplement in driver if needed } void Fl_System_Driver::remove_fd(int fd, int when) { // nothing to do, reimplement in driver if needed } void Fl_System_Driver::remove_fd(int fd) { // nothing to do, reimplement in driver if needed } FILE *Fl_System_Driver::fopen(const char* f, const char *mode) { return ::fopen(f, mode); } void Fl_System_Driver::open_callback(void (*)(const char *)) { } // Get elapsed time since Jan 1st, 1970. void Fl_System_Driver::gettime(time_t *sec, int *usec) { *sec = time(NULL); *usec = 0; } /** Execute platform independent parts of Fl::wait(double). Platform drivers \b MUST override this virtual method to do their own stuff and call this base class method to run the platform independent wait functions. Overridden methods will typically call this method early and perform platform-specific operations after that in order to work with the \p time_to_wait value possibly modified by this method. However, some platform drivers may need to do extra stuff before calling this method, for instance setting up a memory pool on macOS. \param[in] time_to_wait max time to wait \return new (max) time to wait after elapsing timeouts */ double Fl_System_Driver::wait(double time_to_wait) { // delete all widgets that were listed during callbacks Fl::do_widget_deletion(); Fl_Timeout::do_timeouts(); Fl::run_checks(); Fl::run_idle(); // the idle function may turn off idle, we can then wait, // or it leaves Fl::idle active and we set time_to_wait to 0 if (Fl::idle) { time_to_wait = 0.0; } else { // limit time by next timer interval time_to_wait = Fl_Timeout::time_to_wait(time_to_wait); } return time_to_wait; } /** \} \endcond */ fltk-1.4.3/src/Fl_Text_Display.cxx0000644000175000017500000045663715004135251017177 0ustar albrechtalbrecht// // Copyright 2001-2022 by Bill Spitzak and others. // Original code Copyright Mark Edel. Permission to distribute under // the LGPL for the FLTK library granted by Mark Edel. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // TODO: rendering of the "optional hyphen" // TODO: font background color control via style buffer #include #include #include #include // fl_strdup() #include "flstring.h" #include #include #include #include #include #include #include #include #include #include #include "Fl_Screen_Driver.H" #undef min #undef max // #define DEBUG // #define DEBUG2 #define LINENUM_LEFT_OF_VSCROLL // uncomment this line ... // ... if you want the line numbers to be drawn left of the vertical // scrollbar (only if the vertical scrollbar is aligned left). // This is the default. // If not defined and the vertical scrollbar is aligned left, then the // scrollbar is positioned at the left border and the line numbers are // drawn between the scrollbar (left) and the text area (right). // If the vertical scrollbar is aligned right, then the line number // position is not affected by this definition. // Text area margins. Left & right margins should be at least 3 so that // there is some room for the overhanging parts of the cursor! #define TOP_MARGIN 1 #define BOTTOM_MARGIN 1 #define LEFT_MARGIN 3 #define RIGHT_MARGIN 3 #define NO_HINT -1 /* Masks for text drawing methods. These are or'd together to form an integer which describes what drawing calls to use to draw a string */ #define FILL_MASK 0x0100 #define SECONDARY_MASK 0x0200 #define PRIMARY_MASK 0x0400 #define HIGHLIGHT_MASK 0x0800 #define BG_ONLY_MASK 0x1000 #define TEXT_ONLY_MASK 0x2000 #define STYLE_LOOKUP_MASK 0xff /* Maximum displayable line length (how many characters will fit across the widest window). This amount of memory is temporarily allocated from the stack in the draw_vline() method for drawing strings */ #define MAX_DISP_LINE_LEN 1000 static int max( int i1, int i2 ); static int min( int i1, int i2 ); static int countlines( const char *string ); /* The variables below are used in a timer event to allow smooth scrolling of the text area when the pointer has left the area. */ static int scroll_direction = 0; static int scroll_amount = 0; static int scroll_y = 0; static int scroll_x = 0; static Fl_Menu_Item rmb_menu[] = { { NULL, 0, NULL, (void*)1 }, { NULL, 0, NULL, (void*)2 }, { NULL, 0, NULL, (void*)3 }, { NULL } }; // CET - FIXME #define TMPFONTWIDTH 6 /** \brief Creates a new text display widget. \param X, Y, W, H position and size of widget \param l label text, defaults to none */ Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l) : Fl_Group(X, Y, W, H, l) { #define VISIBLE_LINES_INIT 1 // allow compiler to remove unused code (PR #582) // Member initialization: same order as declared in .H file // Any Fl_Text_Display methods should only be called /after/ all // members initialized; avoids methods referencing uninitialized values. // damage_range1_start = damage_range1_end = -1; damage_range2_start = damage_range2_end = -1; mCursorPos = 0; mCursorOn = 0; mCursorOldY = -100; mCursorToHint = NO_HINT; mCursorStyle = NORMAL_CURSOR; mCursorPreferredXPos = -1; mNVisibleLines = VISIBLE_LINES_INIT; mNBufferLines = 0; mBuffer = NULL; mStyleBuffer = NULL; mFirstChar = 0; mLastChar = 0; mContinuousWrap = 0; mWrapMarginPix = 0; mLineStarts = new int[mNVisibleLines]; #if VISIBLE_LINES_INIT > 1 { // Note: this code is unused unless mNVisibleLines is ever initialized > 1 for (int i=1; icallback((Fl_Callback*)h_scrollbar_cb, this); mHScrollBar->type(FL_HORIZONTAL); mVScrollBar = new Fl_Scrollbar(0,0,1,1); mVScrollBar->callback((Fl_Callback*)v_scrollbar_cb, this); display_needs_recalc_ = false; scrollbar_width_ = 0; // 0: default from Fl::scrollbar_size() scrollbar_align_ = FL_ALIGN_BOTTOM_RIGHT; dragPos = 0; dragType = DRAG_CHAR; dragging = 0; display_insert_position_hint = 0; text_area.x = 0; text_area.y = 0; text_area.w = 0; text_area.h = 0; shortcut_ = 0; textfont_ = FL_HELVETICA; // textfont() textsize_ = FL_NORMAL_SIZE; // textsize() textcolor_ = FL_FOREGROUND_COLOR; // textcolor() grammar_underline_color_ = FL_BLUE; spelling_underline_color_ = FL_RED; secondary_selection_color_ = FL_GRAY; mLineNumLeft = 0; // XXX: UNUSED mLineNumWidth = 0; linenumber_font_ = FL_HELVETICA; linenumber_size_ = FL_NORMAL_SIZE; linenumber_fgcolor_ = FL_INACTIVE_COLOR; linenumber_bgcolor_ = 53; // ~90% gray linenumber_align_ = FL_ALIGN_RIGHT; linenumber_format_ = fl_strdup("%d"); // Method calls -- only AFTER all members initialized color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR); box(FL_DOWN_FRAME); set_flag(SHORTCUT_LABEL); clear_flag(NEEDS_KEYBOARD); end(); } /** Free a text display and release its associated memory. \note The text buffer that the text display displays is a separate entity and is not freed, nor are the style buffer or style table. \see Fl_Text_Display::buffer(Fl_Text_Buffer* buf) */ Fl_Text_Display::~Fl_Text_Display() { if (scroll_direction) { Fl::remove_timeout(scroll_timer_cb, this); scroll_direction = 0; } if (mBuffer) { mBuffer->remove_modify_callback(buffer_modified_cb, this); mBuffer->remove_predelete_callback(buffer_predelete_cb, this); } if (mLineStarts) delete[] mLineStarts; if (linenumber_format_) { free((void*)linenumber_format_); linenumber_format_ = 0; } } /** Set width of screen area for line numbers. Use to also enable/disable line numbers. A value of 0 disables line numbering, values >0 enable the line number display. \param width The new width of the area for line numbers to appear, in pixels. 0 disables line numbers (default) */ void Fl_Text_Display::linenumber_width(int width) { if (width < 0) return; mLineNumWidth = width; display_needs_recalc(); // recalc line#s // resize(x(), y(), w(), h()); if (width > 0) reset_absolute_top_line_number(); } /** Return the screen area width provided for line numbers. */ int Fl_Text_Display::linenumber_width() const { return mLineNumWidth; } /** Set the font used for line numbers (if enabled). \version 1.3.3 */ void Fl_Text_Display::linenumber_font(Fl_Font val) { linenumber_font_ = val; } /** Return the font used for line numbers (if enabled). */ Fl_Font Fl_Text_Display::linenumber_font() const { return linenumber_font_; } /** Set the font size used for line numbers (if enabled). \version 1.3.3 */ void Fl_Text_Display::linenumber_size(Fl_Fontsize val) { linenumber_size_ = val; } /** Return the font size used for line numbers (if enabled). */ Fl_Fontsize Fl_Text_Display::linenumber_size() const { return linenumber_size_; } /** Set the foreground color used for line numbers (if enabled). \version 1.3.3 */ void Fl_Text_Display::linenumber_fgcolor(Fl_Color val) { linenumber_fgcolor_ = val; } /** Return the foreground color used for line numbers (if enabled). */ Fl_Color Fl_Text_Display::linenumber_fgcolor() const { return linenumber_fgcolor_; } /** Set the background color used for line numbers (if enabled). \version 1.3.3 */ void Fl_Text_Display::linenumber_bgcolor(Fl_Color val) { linenumber_bgcolor_ = val; } /** Returns the background color used for line numbers (if enabled). */ Fl_Color Fl_Text_Display::linenumber_bgcolor() const { return linenumber_bgcolor_; } /** Set alignment for line numbers (if enabled). Valid values are FL_ALIGN_LEFT, FL_ALIGN_CENTER or FL_ALIGN_RIGHT. \version 1.3.3 */ void Fl_Text_Display::linenumber_align(Fl_Align val) { linenumber_align_ = val; } /** Returns the alignment used for line numbers (if enabled). */ Fl_Align Fl_Text_Display::linenumber_align() const { return linenumber_align_; } /** Sets the printf() style format string used for line numbers. Default is "%d" for normal unpadded decimal integers. An internal copy of \p val is allocated and managed; it is automatically freed whenever a new value is assigned, or when the widget is destroyed. The value of \p val must \a not be NULL. Example values: - "%d" -- For normal line numbers without padding (Default) - "%03d" -- For 000 padding - "%x" -- For hexadecimal line numbers - "%o" -- For octal line numbers \version 1.3.3 */ void Fl_Text_Display::linenumber_format(const char* val) { if ( linenumber_format_ ) free((void*)linenumber_format_); linenumber_format_ = val ? fl_strdup(val) : 0; } /** Returns the line number printf() format string. */ const char* Fl_Text_Display::linenumber_format() const { return linenumber_format_; } /** Attach a text buffer to display, replacing the current buffer (if any). Multiple text widgets can be associated with the same text buffer. \note The caller is responsible for the old (replaced) buffer (if any). This method does not delete the old buffer. \param buf attach this text buffer */ void Fl_Text_Display::buffer( Fl_Text_Buffer *buf ) { /* If the text display is already displaying a buffer, clear it off of the display and remove our callback from it */ if ( buf == mBuffer) return; if ( mBuffer != 0 ) { // we must provide a copy of the buffer that we are deleting! char *deletedText = mBuffer->text(); buffer_modified_cb( 0, 0, mBuffer->length(), 0, deletedText, this ); free(deletedText); mNBufferLines = 0; mBuffer->remove_modify_callback( buffer_modified_cb, this ); mBuffer->remove_predelete_callback( buffer_predelete_cb, this ); } /* Add the buffer to the display, and attach a callback to the buffer for receiving modification information when the buffer contents change */ mBuffer = buf; if (mBuffer) { mBuffer->add_modify_callback( buffer_modified_cb, this ); mBuffer->add_predelete_callback( buffer_predelete_cb, this ); /* Update the display */ buffer_modified_cb( 0, buf->length(), 0, 0, 0, this ); } /* Resize the widget to update the screen... */ display_needs_recalc(); // resize(x(), y(), w(), h()); } /** \brief Attach (or remove) highlight information in text display and redisplay. Highlighting information consists of a style buffer which parallels the normal text buffer, but codes font and color information for the display; a style table which translates style buffer codes (indexed by buffer character - 'A') into fonts and colors; and a callback mechanism for as-needed highlighting, triggered by a style buffer entry of "unfinishedStyle". Style buffer can trigger additional redisplay during a normal buffer modification if the buffer contains a primary Fl_Text_Selection (see extend_range_for_styles() for more information on this protocol). Style buffers, tables and their associated memory are managed by the caller. Styles are ranged from 65 ('A') to 126. \note Style information in the style buffer must have the same byte offset as the corresponding character in the text buffer. UTF-8 characters can have a maximum length of four bytes. Style information must take this into account and fill the unused bytes with 0. See `fl_utf8len()`. Text: "*g* r ü *n*" , where normal style is 'A', and bold is 'B' \code Text Buffer(hex): 67 72 c3 bc 6e : gr..n Style Buffer(hex): 42 41 41 00 42 : BAA.B \endcode \param styleBuffer this buffer works in parallel to the text buffer. For every character in the text buffer, the style buffer has a byte at the same offset that contains an index into an array of possible styles. \param styleTable a list of styles indexed by the style buffer \param nStyles number of styles in the style table \param unfinishedStyle if this style is found, the callback below is called \param unfinishedHighlightCB if a character with an unfinished style is found, this callback will be called \param cbArg an optional argument for the callback above, usually a pointer to the Text Display. \see Fl_Text_Display::style_buffer() */ void Fl_Text_Display::highlight_data(Fl_Text_Buffer *styleBuffer, const Style_Table_Entry *styleTable, int nStyles, char unfinishedStyle, Unfinished_Style_Cb unfinishedHighlightCB, void *cbArg ) { mStyleBuffer = styleBuffer; mStyleTable = styleTable; mNStyles = nStyles; mUnfinishedStyle = unfinishedStyle; mUnfinishedHighlightCB = unfinishedHighlightCB; mHighlightCBArg = cbArg; mColumnScale = 0; if (mStyleBuffer) mStyleBuffer->canUndo(0); damage(FL_DAMAGE_EXPOSE); } /** \brief Find the longest line of all visible lines. \return the width of the longest visible line in pixels */ int Fl_Text_Display::longest_vline() const { int longest = 0; for (int i = 0; i < mNVisibleLines; i++) longest = max(longest, measure_vline(i)); return longest; } /** \brief Change the size of the displayed text area. Calling this function will trigger a recalculation of all visible lines and of all scrollbar sizes. \param X, Y, W, H new position and size of this widget */ void Fl_Text_Display::resize(int X, int Y, int W, int H) { #ifdef DEBUG2 printf("\n"); printf("Fl_Text_Display::resize(X=%d, Y=%d, W=%d, H=%d)\n", X, Y, W, H); printf(" current size(x=%d, y=%d, w=%d, h=%d)\n", x(), y(), w(), h()); printf(" box_d* size(x=%d, y=%d, w=%d, h=%d)\n", Fl::box_dx(box()),Fl::box_dy(box()),Fl::box_dw(box()),Fl::box_dh(box())); printf(" text_area size(x=%d, y=%d, w=%d, h=%d)\n", text_area.x, text_area.y, text_area.w, text_area.h); printf(" mContinuousWrap=%d, mWrapMarginPix=%d\n", mContinuousWrap, mWrapMarginPix); fflush(stdout); #endif // DEBUG2 Fl_Widget::resize(X,Y,W,H); mColumnScale = 0; // force recomputation of the width of a column when display is rescaled display_needs_recalc(); } /** Schedule a recalc_display() to be done on next draw(). Call this from methods that might be called repeatedly, to defers potentially CPU intensive recalc_display() until it's actually needed just before draw(). */ void Fl_Text_Display::display_needs_recalc() { display_needs_recalc_ = true; redraw(); // ensure draw() gets called } /** Recalculate the display's visible lines and scrollbar sizes. Beware calling this directly may cause a lot of CPU if called repeatedly (issue 300). Better to call display_needs_recalc() to flag a recalc to be done during next draw(). */ void Fl_Text_Display::recalc_display() { if (!buffer()) return; // Make sure the display is opened. Fl_Display_Device::display_device(); // did we have scrollbars initially? unsigned int hscrollbarvisible = mHScrollBar->visible(); unsigned int vscrollbarvisible = mVScrollBar->visible(); int scrollsize = scrollbar_width_ ? scrollbar_width_ : Fl::scrollbar_size(); int X = x() + Fl::box_dx(box()); int Y = y() + Fl::box_dy(box()); int W = w() - Fl::box_dw(box()); int H = h() - Fl::box_dh(box()); text_area.x = X + LEFT_MARGIN + mLineNumWidth; text_area.y = Y + TOP_MARGIN; text_area.w = W - LEFT_MARGIN - RIGHT_MARGIN - mLineNumWidth; text_area.h = H - TOP_MARGIN - BOTTOM_MARGIN; // Find the new maximum font height for this text display int i; for (i = 0, mMaxsize = fl_height(textfont(), textsize()); i < mNStyles; i++) mMaxsize = max(mMaxsize, fl_height(mStyleTable[i].font, mStyleTable[i].size)); // try without scrollbars first mVScrollBar->clear_visible(); mHScrollBar->clear_visible(); // Optimization: if the number of lines in the buffer does not fit in // the display area, then we need a vertical scrollbar regardless of // word wrapping. If we switch it on here, this saves one line counting // run in wrap mode in the loop below ("... again ..."). This is important // for large buffers that suffer from slow calculations of character width // to determine line wrapping. // Note: active since Oct 25, 2017: commit eb772d027d (svn r12526) // force _first_ calculation in loop (STR #3412) int oldTAWidth = -1; // was: text_area.w (before STR #3412) if (mContinuousWrap && !mWrapMarginPix) { int nvlines = (text_area.h + mMaxsize - 1) / mMaxsize; int nlines = buffer()->count_lines(0,buffer()->length()); if (nvlines < 1) nvlines = 1; if (nlines >= nvlines-1) { mVScrollBar->set_visible(); // we need a vertical scrollbar text_area.w -= scrollsize; } } // End of optimization, see comment above. for (int again = 1; again;) { again = 0; /* In continuous wrap mode, a change in width affects the total number of lines in the buffer, and can leave the top line number incorrect, and the top character no longer pointing at a valid line start */ #ifdef DEBUG2 printf("*** again ... text_area.w = %d, oldTAWidth = %d, diff = %d\n", text_area.w, oldTAWidth, text_area.w - oldTAWidth); #endif // DEBUG2 if (mContinuousWrap && !mWrapMarginPix && text_area.w != oldTAWidth) { int oldFirstChar = mFirstChar; mFirstChar = line_start(mFirstChar); mTopLineNum = count_lines(0, mFirstChar, true)+1; mNBufferLines = mTopLineNum-1 + count_lines(mFirstChar, buffer()->length(), true); absolute_top_line_number(oldFirstChar); #ifdef DEBUG2 printf(" mNBufferLines=%d\n", mNBufferLines); #endif // DEBUG2 } oldTAWidth = text_area.w; /* reallocate and update the line starts array, which may have changed size and / or contents. */ int nvlines = (text_area.h + mMaxsize - 1) / mMaxsize; if (nvlines < 1) nvlines = 1; if (mNVisibleLines != nvlines) { mNVisibleLines = nvlines; if (mLineStarts) delete[] mLineStarts; mLineStarts = new int [mNVisibleLines]; } calc_line_starts(0, mNVisibleLines); calc_last_char(); // figure the scrollbars if (scrollsize) { /* Decide if the vertical scrollbar needs to be visible */ if (!mVScrollBar->visible() && scrollbar_align() & (FL_ALIGN_LEFT|FL_ALIGN_RIGHT) && mNBufferLines >= mNVisibleLines - ((mContinuousWrap && mWrapMarginPix) ? 0 : 1)) { mVScrollBar->set_visible(); text_area.w -= scrollsize; again = 1; } /* Decide if the horizontal scrollbar needs to be visible. If the text wraps at the right edge, do not draw a horizontal scrollbar. Otherwise, if there is a vertical scrollbar, a horizontal is always created too. This is because the alternatives are unattractive: * Dynamically creating a horizontal scrollbar based on the currently visible lines is what the original nedit does, but it always wastes space for the scrollbar even when it's not used. Since the FLTK widget dynamically allocates the space for the scrollbar and rearranges the widget to make room for it, this would create a very visually displeasing "bounce" effect when the vertical scrollbar is dragged. Trust me, I tried it and it looks really bad. * The other alternative would be to keep track of what the longest line in the entire buffer is and base the scrollbar on that. I didn't do this because I didn't see any easy way to do that using the nedit code and this could involve a lengthy calculation for large buffers. If an efficient and non-costly way of doing this can be found, this might be a way to go. */ /* WAS: Suggestion: Try turning the horizontal scrollbar on when you first see a line that is too wide in the window, but then don't turn it off (ie mix both of your solutions). */ if (!mHScrollBar->visible() && scrollbar_align() & (FL_ALIGN_TOP|FL_ALIGN_BOTTOM) && (mVScrollBar->visible() || longest_vline() > text_area.w)) { char wrap_at_bounds = mContinuousWrap && (mWrapMarginPixset_visible(); text_area.h -= scrollsize; again = 1; // loop again to see if we now need vert. & recalc sizes } } } } // (... again ...) // Calculate text area position, dependent on scrollbars and line numbers. // Note: width and height have been calculated above. text_area.x = X + mLineNumWidth + LEFT_MARGIN; if (mVScrollBar->visible() && scrollbar_align() & FL_ALIGN_LEFT) text_area.x += scrollsize; text_area.y = Y + TOP_MARGIN; if (mHScrollBar->visible() && scrollbar_align() & FL_ALIGN_TOP) text_area.y += scrollsize; // position and resize scrollbars if (mVScrollBar->visible()) { if (scrollbar_align() & FL_ALIGN_LEFT) { #ifdef LINENUM_LEFT_OF_VSCROLL mVScrollBar->resize(text_area.x - LEFT_MARGIN - scrollsize, text_area.y - TOP_MARGIN, scrollsize, text_area.h + TOP_MARGIN + BOTTOM_MARGIN); #else mVScrollBar->resize(X, text_area.y - TOP_MARGIN, scrollsize, text_area.h + TOP_MARGIN + BOTTOM_MARGIN); #endif } else { mVScrollBar->resize(X+W-scrollsize, text_area.y - TOP_MARGIN, scrollsize, text_area.h + TOP_MARGIN + BOTTOM_MARGIN); } } if (mHScrollBar->visible()) { if (scrollbar_align() & FL_ALIGN_TOP) { mHScrollBar->resize(text_area.x - LEFT_MARGIN, Y, text_area.w + LEFT_MARGIN + RIGHT_MARGIN, scrollsize); } else { mHScrollBar->resize(text_area.x - LEFT_MARGIN, Y + H - scrollsize, text_area.w + LEFT_MARGIN + RIGHT_MARGIN, scrollsize); } } // user request to change viewport if (mTopLineNumHint != mTopLineNum || mHorizOffsetHint != mHorizOffset) scroll_(mTopLineNumHint, mHorizOffsetHint); // everything will fit in the viewport if ((mNBufferLines+1 < mNVisibleLines) || (mBuffer == NULL) || (mBuffer->length() == 0)) { scroll_(1, mHorizOffset); /* if empty lines become visible, there may be an opportunity to display more text by scrolling down */ } else { while ( mNVisibleLines>=2 && (mLineStarts[mNVisibleLines-2]==-1) && scroll_(mTopLineNum-1, mHorizOffset)) { } } // user request to display insert position if (display_insert_position_hint) display_insert(); // in case horizontal offset is now greater than longest line int maxhoffset = max(0, longest_vline()-text_area.w); if (mHorizOffset > maxhoffset) scroll_(mTopLineNumHint, maxhoffset); mTopLineNumHint = mTopLineNum; mHorizOffsetHint = mHorizOffset; display_insert_position_hint = 0; if (mContinuousWrap || hscrollbarvisible != mHScrollBar->visible() || vscrollbarvisible != mVScrollBar->visible()) redraw(); update_v_scrollbar(); update_h_scrollbar(); } /** \brief Refresh a rectangle of the text display. \param left, top are in coordinates of the text drawing window. \param width, height size in pixels */ void Fl_Text_Display::draw_text( int left, int top, int width, int height ) { int fontHeight, firstLine, lastLine, line; /* find the line number range of the display */ fontHeight = mMaxsize ? mMaxsize : textsize_; firstLine = ( top - text_area.y - fontHeight + 1 ) / fontHeight; lastLine = ( top + height - text_area.y ) / fontHeight + 1; fl_push_clip( left, top, width, height ); /* draw the lines */ for ( line = firstLine; line <= lastLine; line++ ) draw_vline( line, left, left + width, 0, INT_MAX ); fl_pop_clip(); } /** \brief Marks text from start to end as needing a redraw. This function will trigger a damage event and later a redraw of parts of the widget. \param startpos index of first character needing redraw \param endpos index after last character needing redraw */ void Fl_Text_Display::redisplay_range(int startpos, int endpos) { IS_UTF8_ALIGNED2(buffer(), startpos) IS_UTF8_ALIGNED2(buffer(), endpos) if (damage_range1_start == -1 && damage_range1_end == -1) { damage_range1_start = startpos; damage_range1_end = endpos; } else if ((startpos >= damage_range1_start && startpos <= damage_range1_end) || (endpos >= damage_range1_start && endpos <= damage_range1_end)) { damage_range1_start = min(damage_range1_start, startpos); damage_range1_end = max(damage_range1_end, endpos); } else if (damage_range2_start == -1 && damage_range2_end == -1) { damage_range2_start = startpos; damage_range2_end = endpos; } else { damage_range2_start = min(damage_range2_start, startpos); damage_range2_end = max(damage_range2_end, endpos); } damage(FL_DAMAGE_SCROLL); } /** \brief Draw a range of text. Refresh all of the text between buffer positions \p startpos and \p endpos not including the character at the position \p endpos. If \p endpos points beyond the end of the buffer, refresh the whole display after \p startpos, including blank lines which are not technically part of any range of characters. \param startpos index of first character to draw \param endpos index after last character to draw */ void Fl_Text_Display::draw_range(int startpos, int endpos) { startpos = buffer()->utf8_align(startpos); endpos = buffer()->utf8_align(endpos); int i, startLine, lastLine, startIndex, endIndex; /* If the range is outside of the displayed text, just return */ if ( endpos < mFirstChar || ( startpos > mLastChar && !empty_vlines() ) ) return; /* Clean up the starting and ending values */ if ( startpos < 0 ) startpos = 0; if ( startpos > mBuffer->length() ) startpos = mBuffer->length(); if ( endpos < 0 ) endpos = 0; if ( endpos > mBuffer->length() ) endpos = mBuffer->length(); /* Get the starting and ending lines */ if ( startpos < mFirstChar ) startpos = mFirstChar; if ( !position_to_line( startpos, &startLine ) ) startLine = mNVisibleLines - 1; if ( endpos >= mLastChar ) { lastLine = mNVisibleLines - 1; } else { if ( !position_to_line( endpos, &lastLine ) ) { /* shouldn't happen */ lastLine = mNVisibleLines - 1; } } /* Get the starting and ending positions within the lines */ startIndex = mLineStarts[ startLine ] == -1 ? 0 : startpos - mLineStarts[ startLine ]; if ( endpos >= mLastChar ) endIndex = INT_MAX; else if ( mLineStarts[ lastLine ] == -1 ) endIndex = 0; else endIndex = endpos - mLineStarts[ lastLine ]; /* If the starting and ending lines are the same, redisplay the single line between "start" and "end" */ if ( startLine == lastLine ) { draw_vline( startLine, 0, INT_MAX, startIndex, endIndex ); return; } /* Redisplay the first line from "start" */ draw_vline( startLine, 0, INT_MAX, startIndex, INT_MAX ); /* Redisplay the lines in between at their full width */ for ( i = startLine + 1; i < lastLine; i++ ) draw_vline( i, 0, INT_MAX, 0, INT_MAX ); /* Redisplay the last line to "end" */ draw_vline( lastLine, 0, INT_MAX, 0, endIndex ); } /** \brief Sets the position of the text insertion cursor for text display. Moves the insertion cursor in front of the character at \p newPos. This function may trigger a redraw. \param newPos new caret position */ void Fl_Text_Display::insert_position( int newPos ) { IS_UTF8_ALIGNED2(buffer(), newPos) /* make sure new position is ok, do nothing if it hasn't changed */ if ( newPos == mCursorPos ) return; if ( newPos < 0 ) newPos = 0; if ( newPos > mBuffer->length() ) newPos = mBuffer->length(); /* cursor movement cancels vertical cursor motion column */ mCursorPreferredXPos = -1; /* erase the cursor at its previous position */ redisplay_range(buffer()->prev_char_clipped(mCursorPos), buffer()->next_char(mCursorPos)); mCursorPos = newPos; /* draw cursor at its new position */ redisplay_range(buffer()->prev_char_clipped(mCursorPos), buffer()->next_char(mCursorPos)); } /** \brief Shows the text cursor. This function may trigger a redraw. \param b show(1) or hide(0) the text cursor (caret). */ void Fl_Text_Display::show_cursor(int b) { mCursorOn = b; if (!buffer()) return; redisplay_range(buffer()->prev_char_clipped(mCursorPos), buffer()->next_char(mCursorPos)); } /** \brief Sets the text cursor style. Sets the text cursor style to one of the following: \li Fl_Text_Display::NORMAL_CURSOR - Shows an I beam. \li Fl_Text_Display::CARET_CURSOR - Shows a caret under the text. \li Fl_Text_Display::DIM_CURSOR - Shows a dimmed I beam. \li Fl_Text_Display::BLOCK_CURSOR - Shows an unfilled box around the current character. \li Fl_Text_Display::HEAVY_CURSOR - Shows a thick I beam. This call also switches the cursor on and may trigger a redraw. \param style new cursor style */ void Fl_Text_Display::cursor_style(int style) { mCursorStyle = style; if (mCursorOn) show_cursor(); } /** \brief Set the new text wrap mode. If \p wrap mode is not zero, this call enables automatic word wrapping at column \p wrapMargin. Word-wrapping does not change the text buffer itself, only the way the text is displayed. Different Text Displays can have different wrap modes, even if they share the same Text Buffer. Valid wrap modes are: - WRAP_NONE : don't wrap text at all - WRAP_AT_COLUMN : wrap text at the given text column - WRAP_AT_PIXEL : wrap text at a pixel position - WRAP_AT_BOUNDS : wrap text so that it fits into the widget width \param wrap new wrap mode (see above) \param wrapMargin in WRAP_AT_COLUMN mode, text will wrap at the n'th character. For variable width fonts, an average character width is calculated. The column width is calculated using the current textfont or the first style when this function is called. If the font size changes, this function must be called again. In WRAP_AT_PIXEL mode, this is the pixel position. */ void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) { switch (wrap) { case WRAP_NONE: mWrapMarginPix = 0; mContinuousWrap = 0; break; case WRAP_AT_COLUMN: default: mWrapMarginPix = int(col_to_x(wrapMargin)); mContinuousWrap = 1; break; case WRAP_AT_PIXEL: mWrapMarginPix = wrapMargin; mContinuousWrap = 1; break; case WRAP_AT_BOUNDS: mWrapMarginPix = 0; mContinuousWrap = 1; break; } if (buffer()) { /* wrapping can change the total number of lines, re-count */ mNBufferLines = count_lines(0, buffer()->length(), true); /* changing wrap margins or changing from wrapped mode to non-wrapped can leave the character at the top no longer at a line start, and/or change the line number */ mFirstChar = line_start(mFirstChar); mTopLineNum = count_lines(0, mFirstChar, true) + 1; reset_absolute_top_line_number(); /* update the line starts array */ calc_line_starts(0, mNVisibleLines); calc_last_char(); } else { // No buffer, so just clear the state info for later... mNBufferLines = 0; mFirstChar = 0; mTopLineNum = 1; mAbsTopLineNum = 1; // changed from 0 to 1 -- LZA / STR#2621 } display_needs_recalc(); // resize(x(), y(), w(), h()); } /** \brief Inserts "text" at the current cursor location. This has the same effect as inserting the text into the buffer using insert(insert_position(),text) and then moving the insert position after the newly inserted text, except that it's optimized to do less redrawing. \param text new text in UTF-8 encoding. */ void Fl_Text_Display::insert(const char* text) { IS_UTF8_ALIGNED2(buffer(), mCursorPos) IS_UTF8_ALIGNED(text) int pos = mCursorPos; mCursorToHint = (int) (pos + strlen( text )); mBuffer->insert( pos, text ); mCursorToHint = NO_HINT; } /** \brief Replaces text at the current insert position. \param text new text in UTF-8 encoding \todo Unicode? Find out exactly what we do here and simplify. */ void Fl_Text_Display::overstrike(const char* text) { IS_UTF8_ALIGNED2(buffer(), mCursorPos) IS_UTF8_ALIGNED(text) int startPos = mCursorPos; Fl_Text_Buffer *buf = mBuffer; int lineStart = buf->line_start( startPos ); int textLen = (int) strlen( text ); int i, p, endPos, indent, startIndent, endIndent; const char *c; unsigned int ch; char *paddedText = NULL; /* determine how many displayed character positions are covered */ startIndent = mBuffer->count_displayed_characters( lineStart, startPos ); indent = startIndent; for ( c = text; *c != '\0'; c += fl_utf8len1(*c) ) indent++; endIndent = indent; /* find which characters to remove, and if necessary generate additional padding to make up for removed control characters at the end */ indent = startIndent; for ( p = startPos; ; p = buf->next_char(p) ) { if ( p == buf->length() ) break; ch = buf->char_at( p ); if ( ch == '\n' ) break; indent++; if ( indent == endIndent ) { p = buf->next_char(p); break; } else if ( indent > endIndent ) { if ( ch != '\t' ) { p = buf->next_char(p); paddedText = new char [ textLen + FL_TEXT_MAX_EXP_CHAR_LEN + 1 ]; strcpy( paddedText, text ); for ( i = 0; i < indent - endIndent; i++ ) paddedText[ textLen + i ] = ' '; paddedText[ textLen + i ] = '\0'; } break; } } endPos = p; mCursorToHint = startPos + textLen; buf->replace( startPos, endPos, paddedText == NULL ? text : paddedText ); mCursorToHint = NO_HINT; if ( paddedText != NULL ) delete [] paddedText; } /** \brief Convert a character index into a pixel position. Translate a buffer text position to the XY location where the top left of the cursor would be positioned to point to that character. Returns 0 if the position is not displayed because it is \e \b vertically out of view. If the position is horizontally out of view, returns the X coordinate where the position would be if it were visible. \param pos character index \param[out] X, Y pixel position of character on screen \return 0 if character vertically out of view, X & Y positions otherwise */ int Fl_Text_Display::position_to_xy( int pos, int* X, int* Y ) const { IS_UTF8_ALIGNED2(buffer(), pos) int lineStartPos, fontHeight; int visLineNum; /* If position is not displayed, return false */ if ((pos < mFirstChar) || (pos > mLastChar && !empty_vlines()) || (pos > buffer()->length()) ) { // STR #3231 return (*X=*Y=0); // make sure X & Y are set when it is out of view } /* Calculate Y coordinate */ if (!position_to_line(pos, &visLineNum) || visLineNum < 0 || visLineNum > mNBufferLines) { return (*X=*Y=0); // make sure X & Y are set when it is out of view } fontHeight = mMaxsize; *Y = text_area.y + visLineNum * fontHeight; /* Get the text, length, and buffer position of the line. If the position is beyond the end of the buffer and should be at the first position on the first empty line, don't try to get or scan the text */ lineStartPos = mLineStarts[visLineNum]; if ( lineStartPos == -1 ) { *X = text_area.x - mHorizOffset; return 1; } *X = text_area.x + handle_vline(GET_WIDTH, lineStartPos, pos-lineStartPos, 0, 0, 0, 0, 0, 0) - mHorizOffset; return 1; } /** \brief Find the line and column number of position \p pos. This only works for displayed lines. If the line is not displayed, the function returns 0 (without the mLineStarts array it could turn in to very long calculation involving scanning large amounts of text in the buffer). If continuous wrap mode is on, returns the absolute line number (as opposed to the wrapped line number which is used for scrolling). \param pos character index \param[out] lineNum absolute (unwrapped) line number \param[out] column character offset to the beginning of the line \return 0 if \p pos is off screen, line number otherwise \todo a column number makes little sense in the UTF-8/variable font width environment. We will have to further define what exactly we want to return. Please check the functions that call this particular function. */ int Fl_Text_Display::position_to_linecol( int pos, int* lineNum, int* column ) const { IS_UTF8_ALIGNED2(buffer(), pos) int retVal; /* In continuous wrap mode, the absolute (non-wrapped) line count is maintained separately, as needed. Only return it if we're actually keeping track of it and pos is in the displayed text */ if (mContinuousWrap) { if (!maintaining_absolute_top_line_number() || pos < mFirstChar || pos > mLastChar) return 0; *lineNum = mAbsTopLineNum + buffer()->count_lines(mFirstChar, pos); *column = buffer()->count_displayed_characters(buffer()->line_start(pos), pos); return 1; } retVal = position_to_line( pos, lineNum ); if ( retVal ) { *column = mBuffer->count_displayed_characters( mLineStarts[ *lineNum ], pos ); *lineNum += mTopLineNum; } return retVal; } /** \brief Check if a pixel position is within the primary selection. \param X, Y pixel position to test \return 1 if position (X, Y) is inside of the primary Fl_Text_Selection */ int Fl_Text_Display::in_selection( int X, int Y ) const { int pos = xy_to_position( X, Y, CHARACTER_POS ); IS_UTF8_ALIGNED2(buffer(), pos) Fl_Text_Buffer *buf = mBuffer; return buf->primary_selection()->includes(pos); } /** \brief Nobody knows what this function does. Correct a column number based on an unconstrained position (as returned by TextDXYToUnconstrainedPosition) to be relative to the last actual newline in the buffer before the row and column position given, rather than the last line start created by line wrapping. This is an adapter for rectangular selections and code written before continuous wrap mode, which thinks that the unconstrained column is the number of characters from the last newline. Obviously this is time consuming, because it invloves character re-counting. \param row \param column \return something unknown \todo What does this do and how is it useful? Column numbers mean little in this context. Which functions depend on this one? Function TextDXYToUnconstrainedPosition does not exist (nedit port?) \todo Unicode? */ int Fl_Text_Display::wrapped_column(int row, int column) const { int lineStart, dispLineStart; if (!mContinuousWrap || row < 0 || row > mNVisibleLines) return column; dispLineStart = mLineStarts[row]; if (dispLineStart == -1) return column; lineStart = buffer()->line_start(dispLineStart); return column + buffer()->count_displayed_characters(lineStart, dispLineStart); } /** \brief Nobody knows what this function does. Correct a row number from an unconstrained position (as returned by TextDXYToUnconstrainedPosition) to a straight number of newlines from the top line of the display. Because rectangular selections are based on newlines, rather than display wrapping, and anywhere a rectangular selection needs a row, it needs it in terms of un-wrapped lines. \param row \return something unknown \todo What does this do and how is it useful? Column numbers mean little in this context. Which functions depend on this one? Function TextDXYToUnconstrainedPosition does not exist (nedit port?) */ int Fl_Text_Display::wrapped_row(int row) const { if (!mContinuousWrap || row < 0 || row > mNVisibleLines) return row; return buffer()->count_lines(mFirstChar, mLineStarts[row]); } /** \brief Scroll the display to bring insertion cursor into view. Note: it would be nice to be able to do this without counting lines twice (scroll_() counts them too) and/or to count from the most efficient starting point, but the efficiency of this routine is not as important to the overall performance of the text display. */ void Fl_Text_Display::display_insert() { int hOffset, topLine, X, Y; hOffset = mHorizOffset; topLine = mTopLineNum; if (insert_position() < mFirstChar) { topLine -= count_lines(insert_position(), mFirstChar, false); } else if (mNVisibleLines>=2 && mLineStarts[mNVisibleLines-2] != -1) { int lastChar = line_end(mLineStarts[mNVisibleLines-2],true); if (insert_position() >= lastChar) topLine += count_lines(lastChar - (wrap_uses_character(mLastChar) ? 0 : 1), insert_position(), false); } /* Find the new setting for horizontal offset (this is a bit ungraceful). If the line is visible, just use PositionToXY to get the position to scroll to, otherwise, do the vertical scrolling first, then the horizontal */ if (!position_to_xy( mCursorPos, &X, &Y )) { scroll_(topLine, hOffset); if (!position_to_xy( mCursorPos, &X, &Y )) { #ifdef DEBUG printf ("*** display_insert/position_to_xy # GIVE UP !\n"); fflush(stdout); #endif // DEBUG return; /* Give up, it's not worth it (but why does it fail?) */ } } if (X > text_area.x + text_area.w) hOffset += X-(text_area.x + text_area.w); else if (X < text_area.x) hOffset += X-text_area.x; /* Do the scroll */ if (topLine != mTopLineNum || hOffset != mHorizOffset) scroll_(topLine, hOffset); } /** \brief Scrolls the text buffer to show the current insert position. This function triggers a complete recalculation, ending in a call to Fl_Text_Display::display_insert() */ void Fl_Text_Display::show_insert_position() { display_insert_position_hint = 1; display_needs_recalc(); // resize(x(), y(), w(), h()); } /* Cursor movement functions */ /** \brief Moves the current insert position right one character. \return 1 if the cursor moved, 0 if the end of the text was reached */ int Fl_Text_Display::move_right() { if ( mCursorPos >= mBuffer->length() ) return 0; int p = insert_position(); int q = buffer()->next_char(p); insert_position(q); return 1; } /** \brief Moves the current insert position left one character. \return 1 if the cursor moved, 0 if the beginning of the text was reached */ int Fl_Text_Display::move_left() { if ( mCursorPos <= 0 ) return 0; int p = insert_position(); int q = buffer()->prev_char_clipped(p); insert_position(q); return 1; } /** \brief Moves the current insert position up one line. \return 1 if the cursor moved, 0 if the beginning of the text was reached */ int Fl_Text_Display::move_up() { int lineStartPos, xPos, prevLineStartPos, newPos, visLineNum; /* Find the position of the start of the line. Use the line starts array if possible */ if ( position_to_line( mCursorPos, &visLineNum ) ) lineStartPos = mLineStarts[ visLineNum ]; else { lineStartPos = line_start( mCursorPos ); visLineNum = -1; } if ( lineStartPos == 0 ) return 0; /* Decide what column to move to, if there's a preferred column use that */ if (mCursorPreferredXPos >= 0) xPos = mCursorPreferredXPos; else xPos = handle_vline(GET_WIDTH, lineStartPos, mCursorPos-lineStartPos, 0, 0, 0, 0, 0, INT_MAX); /* count forward from the start of the previous line to reach the column */ if ( visLineNum != -1 && visLineNum != 0 ) prevLineStartPos = mLineStarts[ visLineNum - 1 ]; else prevLineStartPos = rewind_lines( lineStartPos, 1 ); int lineEnd = line_end(prevLineStartPos, true); newPos = handle_vline(FIND_INDEX_FROM_ZERO, prevLineStartPos, lineEnd-prevLineStartPos, 0, 0, 0, 0, 0, xPos); /* move the cursor */ insert_position( newPos ); /* if a preferred column wasn't aleady established, establish it */ mCursorPreferredXPos = xPos; return 1; } /** \brief Moves the current insert position down one line. \return 1 if the cursor moved, 0 if the beginning of the text was reached */ int Fl_Text_Display::move_down() { int lineStartPos, xPos, newPos, visLineNum; if ( mCursorPos == mBuffer->length() ) return 0; if ( position_to_line( mCursorPos, &visLineNum ) ) lineStartPos = mLineStarts[ visLineNum ]; else { lineStartPos = line_start( mCursorPos ); visLineNum = -1; } if (mCursorPreferredXPos >= 0) { xPos = mCursorPreferredXPos; } else { xPos = handle_vline(GET_WIDTH, lineStartPos, mCursorPos-lineStartPos, 0, 0, 0, 0, 0, INT_MAX); } int nextLineStartPos = skip_lines( lineStartPos, 1, true ); int lineEnd = line_end(nextLineStartPos, true); newPos = handle_vline(FIND_INDEX_FROM_ZERO, nextLineStartPos, lineEnd-nextLineStartPos, 0, 0, 0, 0, 0, xPos); insert_position( newPos ); mCursorPreferredXPos = xPos; return 1; } /** \brief Count the number of lines between two positions. Same as Fl_Text_Buffer::count_lines(), but takes into account wrapping if wrapping is turned on. If the caller knows that \p startPos is at a line start, it can pass \p startPosIsLineStart as True to make the call more efficient by avoiding the additional step of scanning back to the last newline. \param startPos index to first character \param endPos index after last character \param startPosIsLineStart avoid scanning back to the line start \return number of lines */ int Fl_Text_Display::count_lines(int startPos, int endPos, bool startPosIsLineStart) const { IS_UTF8_ALIGNED2(buffer(), startPos) IS_UTF8_ALIGNED2(buffer(), endPos) int retLines, retPos, retLineStart, retLineEnd; #ifdef DEBUG printf("Fl_Text_Display::count_lines(startPos=%d, endPos=%d, startPosIsLineStart=%d\n", startPos, endPos, startPosIsLineStart); #endif // DEBUG /* If we're not wrapping use simple (and more efficient) Fl_Text_Buffer::count_lines() */ if (!mContinuousWrap) return buffer()->count_lines(startPos, endPos); /* Correctly counting wrapped lines is very slow. We have to query the length of every segment of text for every line change and style change and find potential soft line breaks. Most of the resulting information is needed for calculating the vertical scroll bar size. After a certain text length, the scroll bar size is no longer very precise anyway, so we optimize line count for all lines but the visible ones (plus minus a few lines for rounding). The optimized code is several magnitudes faster and makes scrolling and window resizing of long texts quite responsive. There is a slight but IMHO tollerable drawback: when walking huge files using arrow up and down, the text display sometimes jumps 2 or 3 lines instead of 1, but the overall buffer stays intact as well as the scroll position. */ if (buffer()->length() > 16384) { // Optimized line counting int nLines = 0; int firstVisibleChar = buffer()->rewind_lines(mFirstChar, 3); int lastVisibleChar = buffer()->skip_lines(mLastChar, 3); // Calculate the averga number of characters up to a soft line break if (mColumnScale==0.0) x_to_col(1.0); int avgCharsPerLine = mWrapMarginPix; if (!avgCharsPerLine) avgCharsPerLine = text_area.w; avgCharsPerLine = (int)(avgCharsPerLine / mColumnScale) + 1; // first segment, lines up to display, count fast if (startPos < firstVisibleChar) { int tmpEnd = endPosestimate_lines(startPos, tmpEnd, avgCharsPerLine); startPos = tmpEnd; } // second segement, count displayed liens if (startPos < endPos && startPos < mLastChar) { // Precisse line counting only for visible text: int tmpEnd = endPos= lastVisibleChar) { nLines += buffer()->estimate_lines(startPos, endPos, avgCharsPerLine); } return nLines; } else { // Precise line counting only for small text buffer sizes: wrapped_line_counter(buffer(), startPos, endPos, INT_MAX, startPosIsLineStart, 0, &retPos, &retLines, &retLineStart, &retLineEnd); #ifdef DEBUG printf(" # after WLC: retPos=%d, retLines=%d, retLineStart=%d, retLineEnd=%d\n", retPos, retLines, retLineStart, retLineEnd); #endif // DEBUG return retLines; } } /** \brief Skip a number of lines forward. Same as Fl_Text_Buffer::skip_lines(startPos, nLines), but takes into account line breaks when wrapping is turned on. If the caller knows that \p startPos is at a line start, it can pass \p startPosIsLineStart as True to make the call more efficient by avoiding the additional step of scanning back to the last newline. \param startPos index to starting character \param nLines number of lines to skip ahead \param startPosIsLineStart avoid scanning back to the line start \return new position as index */ int Fl_Text_Display::skip_lines(int startPos, int nLines, bool startPosIsLineStart) { IS_UTF8_ALIGNED2(buffer(), startPos) int retLines, retPos, retLineStart, retLineEnd; /* if we're not wrapping use more efficient skip_lines(startPos, nLines) */ if (!mContinuousWrap) return buffer()->skip_lines(startPos, nLines); /* wrappedLineCounter can't handle the 0 lines case */ if (nLines == 0) return startPos; /* use the common line counting routine to count forward */ wrapped_line_counter(buffer(), startPos, buffer()->length(), nLines, startPosIsLineStart, 0, &retPos, &retLines, &retLineStart, &retLineEnd); IS_UTF8_ALIGNED2(buffer(), retPos) return retPos; } /** \brief Returns the end of a line. Same as buffer()->line_end(startPos), but takes into account line breaks when wrapping is turned on. If the caller knows that \p startPos is at a line start, it can pass \p startPosIsLineStart as True to make the call more efficient by avoiding the additional step of scanning back to the last newline. Note that the definition of the end of a line is less clear when continuous wrap is on. With continuous wrap off, it's just a pointer to the newline that ends the line. When it's on, it's the character beyond the last \b displayable character on the line, where a whitespace character which has been "converted" to a newline for wrapping is not considered displayable. Also note that a line can be wrapped at a non-whitespace character if the line had no whitespace. In this case, this routine returns a pointer to the start of the next line. This is also consistent with the model used by visLineLength. \param startPos index to starting character \param startPosIsLineStart avoid scanning back to the line start \return new position as index */ int Fl_Text_Display::line_end(int startPos, bool startPosIsLineStart) const { IS_UTF8_ALIGNED2(buffer(), startPos) int retLines, retPos, retLineStart, retLineEnd; /* If we're not wrapping use more efficient buffer()->line_end(startPos) */ if (!mContinuousWrap) return buffer()->line_end(startPos); if (startPos == buffer()->length()) return startPos; wrapped_line_counter(buffer(), startPos, buffer()->length(), 1, startPosIsLineStart, 0, &retPos, &retLines, &retLineStart, &retLineEnd); IS_UTF8_ALIGNED2(buffer(), retLineEnd) return retLineEnd; } /** \brief Return the beginning of a line. Same as buffer()->line_start(pos), but returns the character after last wrap point rather than the last newline. \param pos index to starting character \return new position as index */ int Fl_Text_Display::line_start(int pos) const { IS_UTF8_ALIGNED2(buffer(), pos) int retLines, retPos, retLineStart, retLineEnd; /* If we're not wrapping, use the more efficient buffer()->line_start(pos) */ if (!mContinuousWrap) return buffer()->line_start(pos); wrapped_line_counter(buffer(), buffer()->line_start(pos), pos, INT_MAX, true, 0, &retPos, &retLines, &retLineStart, &retLineEnd); IS_UTF8_ALIGNED2(buffer(), retLineStart) return retLineStart; } /** \brief Skip a number of lines back. Same as buffer()->rewind_lines(startPos, nLines), but takes into account line breaks when wrapping is turned on. \param startPos index to starting character \param nLines number of lines to skip back \return new position as index */ int Fl_Text_Display::rewind_lines(int startPos, int nLines) { IS_UTF8_ALIGNED2(buffer(), startPos) Fl_Text_Buffer *buf = buffer(); int pos, lineStart, retLines, retPos, retLineStart, retLineEnd; /* If we're not wrapping, use the more efficient Fl_Text_Buffer::rewind_lines(startPos, nLines) */ if (!mContinuousWrap) return buf->rewind_lines(startPos, nLines); pos = startPos; for (;;) { lineStart = buf->line_start(pos); wrapped_line_counter(buf, lineStart, pos, INT_MAX, true, 0, &retPos, &retLines, &retLineStart, &retLineEnd, false); if (retLines > nLines) return skip_lines(lineStart, retLines-nLines, true); nLines -= retLines; pos = lineStart - 1; if (pos < 0) return 0; nLines -= 1; } } /** \brief Moves the current insert position right one word. */ void Fl_Text_Display::next_word() { int pos = insert_position(); while (pos < buffer()->length() && !buffer()->is_word_separator(pos)) { pos = buffer()->next_char(pos); } while (pos < buffer()->length() && buffer()->is_word_separator(pos)) { pos = buffer()->next_char(pos); } insert_position( pos ); } /** \brief Moves the current insert position left one word. */ void Fl_Text_Display::previous_word() { int pos = insert_position(); if (pos==0) return; pos = buffer()->prev_char(pos); while (pos && buffer()->is_word_separator(pos)) { pos = buffer()->prev_char(pos); } while (pos && !buffer()->is_word_separator(pos)) { pos = buffer()->prev_char(pos); } if (buffer()->is_word_separator(pos)) { pos = buffer()->next_char(pos); } insert_position( pos ); } /** \brief This is called before any characters are deleted. Callback attached to the text buffer to receive delete information before the modifications are actually made. This callback can be used to adjust the display or update other setting. It is not advisable to change any buffers or text in this callback, or line counting may get out of sync. \param pos starting index of deletion \param nDeleted number of bytes we will delete (must be UTF-8 aligned!) \param cbArg "this" pointer for static callback function */ void Fl_Text_Display::buffer_predelete_cb(int pos, int nDeleted, void *cbArg) { Fl_Text_Display *textD = (Fl_Text_Display *)cbArg; if (textD->mContinuousWrap) { /* Note: we must perform this measurement, even if there is not a single character deleted; the number of "deleted" lines is the number of visual lines spanned by the real line in which the modification takes place. Also, a modification of the tab distance requires the same kind of calculations in advance, even if the font width is "fixed", because when the width of the tab characters changes, the layout of the text may be completely different. */ IS_UTF8_ALIGNED2(textD->buffer(), pos) textD->measure_deleted_lines(pos, nDeleted); } else { textD->mSuppressResync = 0; /* Probably not needed, but just in case */ } } /** \brief This is called whenever the buffer is modified. Callback attached to the text buffer to receive modification information. This callback can be used to adjust the display or update other setting. It is not advisable to change any buffers or text in this callback, or line counting may get out of sync. \param pos starting index of modification \param nInserted number of bytes we inserted (must be UTF-8 aligned!) \param nDeleted number of bytes deleted (must be UTF-8 aligned!) \param nRestyled ?? \param deletedText this is what was removed, must not be NULL if nDeleted is set \param cbArg "this" pointer for static callback function */ void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted, int nRestyled, const char *deletedText, void *cbArg ) { int linesInserted, linesDeleted, startDispPos, endDispPos; Fl_Text_Display *textD = ( Fl_Text_Display * ) cbArg; Fl_Text_Buffer *buf = textD->mBuffer; int oldFirstChar = textD->mFirstChar; int scrolled, origCursorPos = textD->mCursorPos; int wrapModStart = 0, wrapModEnd = 0; IS_UTF8_ALIGNED2(buf, pos) IS_UTF8_ALIGNED2(buf, oldFirstChar) /* buffer modification cancels vertical cursor motion column */ if ( nInserted != 0 || nDeleted != 0 ) textD->mCursorPreferredXPos = -1; /* Count the number of lines inserted and deleted, and in the case of continuous wrap mode, how much has changed */ if (textD->mContinuousWrap) { textD->find_wrap_range(deletedText, pos, nInserted, nDeleted, &wrapModStart, &wrapModEnd, &linesInserted, &linesDeleted); } else { linesInserted = nInserted == 0 ? 0 : buf->count_lines( pos, pos + nInserted ); linesDeleted = nDeleted == 0 ? 0 : countlines( deletedText ); } /* Update the line starts and mTopLineNum */ if ( nInserted != 0 || nDeleted != 0 ) { if (textD->mContinuousWrap) { textD->update_line_starts( wrapModStart, wrapModEnd-wrapModStart, nDeleted + pos-wrapModStart + (wrapModEnd-(pos+nInserted)), linesInserted, linesDeleted, &scrolled ); } else { textD->update_line_starts( pos, nInserted, nDeleted, linesInserted, linesDeleted, &scrolled ); } } else scrolled = 0; /* If we're counting non-wrapped lines as well, maintain the absolute (non-wrapped) line number of the text displayed */ if (textD->maintaining_absolute_top_line_number() && (nInserted != 0 || nDeleted != 0)) { if (deletedText && (pos + nDeleted < oldFirstChar)) textD->mAbsTopLineNum += buf->count_lines(pos, pos + nInserted) - countlines(deletedText); else if (pos < oldFirstChar) textD->reset_absolute_top_line_number(); } /* Update the line count for the whole buffer */ textD->mNBufferLines += linesInserted - linesDeleted; /* Update the cursor position */ if ( textD->mCursorToHint != NO_HINT ) { textD->mCursorPos = textD->mCursorToHint; textD->mCursorToHint = NO_HINT; } else if ( textD->mCursorPos > pos ) { if ( textD->mCursorPos < pos + nDeleted ) textD->mCursorPos = pos; else textD->mCursorPos += nInserted - nDeleted; } // refigure scrollbars & stuff textD->display_needs_recalc(); // textD->resize(textD->x(), textD->y(), textD->w(), textD->h()); // don't need to do anything else if not visible? if (!textD->visible_r()) return; /* If the changes caused scrolling, re-paint everything and we're done. */ if ( scrolled ) { textD->damage(FL_DAMAGE_EXPOSE); if ( textD->mStyleBuffer ) /* See comments in extend_range_for_styles() */ textD->mStyleBuffer->primary_selection()->selected(0); return; } /* If the changes didn't cause scrolling, decide the range of characters that need to be re-painted. Also if the cursor position moved, be sure that the redisplay range covers the old cursor position so the old cursor gets erased, and erase the bits of the cursor which extend beyond the left and right edges of the text. */ startDispPos = textD->mContinuousWrap ? wrapModStart : pos; IS_UTF8_ALIGNED2(buf, startDispPos) if ( origCursorPos == startDispPos && textD->mCursorPos != startDispPos ) startDispPos = min( startDispPos, buf->prev_char_clipped(origCursorPos) ); IS_UTF8_ALIGNED2(buf, startDispPos) if ( linesInserted == linesDeleted ) { if ( nInserted == 0 && nDeleted == 0 ) endDispPos = pos + nRestyled; else { if (textD->mContinuousWrap) endDispPos = wrapModEnd; else endDispPos = buf->next_char(buf->line_end( pos + nInserted )); // CET - FIXME if ( origCursorPos >= startDispPos && // ( origCursorPos <= endDispPos || endDispPos == buf->length() ) ) } if (linesInserted > 1) { // textD->draw_line_numbers(false); // can't do this b/c not called from virtual draw(); textD->damage(FL_DAMAGE_EXPOSE); } } else { endDispPos = buf->next_char(textD->mLastChar); // CET - FIXME if ( origCursorPos >= pos ) /* If more than one line is inserted/deleted, a line break may have been inserted or removed in between, and the line numbers may have changed. If only one line is altered, line numbers cannot be affected (the insertion or removal of a line break always results in at least two lines being redrawn). */ // Call draw_line_numbers() here to ensure line# is drawn // when hitting enter for new line -- LZA / STR #2621 //textD->draw_line_numbers(true); // no, can't call this here, not in draw() context -- ERCO / STR#2621 //textD->damage(::FL_DAMAGE_EXPOSE); } IS_UTF8_ALIGNED2(buf, startDispPos) IS_UTF8_ALIGNED2(buf, endDispPos) /* If there is a style buffer, check if the modification caused additional changes that need to be redisplayed. (Redisplaying separately would cause double-redraw on almost every modification involving styled text). Extend the redraw range to incorporate style changes */ if ( textD->mStyleBuffer ) textD->extend_range_for_styles( &startDispPos, &endDispPos ); IS_UTF8_ALIGNED2(buf, startDispPos) IS_UTF8_ALIGNED2(buf, endDispPos) /* Redisplay computed range */ textD->redisplay_range( startDispPos, endDispPos ); } /* Line Numbering Methods */ /** \brief Line numbering stuff, currently unused. In continuous wrap mode, internal line numbers are calculated after wrapping. A separate non-wrapped line count is maintained when line numbering is turned on. There is some performance cost to maintaining this line count, so normally absolute line numbers are not tracked if line numbering is off. This routine allows callers to specify that they still want this line count maintained (for use via Fl_Text_Display::position_to_linecol()). More specifically, this allows the line number reported in the statistics line to be calibrated in absolute lines, rather than post-wrapped lines. */ void Fl_Text_Display::maintain_absolute_top_line_number(int state) { mNeedAbsTopLineNum = state; reset_absolute_top_line_number(); } /** Returns the absolute (non-wrapped) line number of the first line displayed. Returns 0 if the absolute top line number is not being maintained. */ int Fl_Text_Display::get_absolute_top_line_number() const { if (!mContinuousWrap) return mTopLineNum; if (maintaining_absolute_top_line_number()) return mAbsTopLineNum; return 0; } /** Re-calculate absolute top line number for a change in scroll position. Does nothing if the absolute top line number is not being maintained. */ void Fl_Text_Display::absolute_top_line_number(int oldFirstChar) { if (maintaining_absolute_top_line_number() && buffer()) { if (mFirstChar < oldFirstChar) mAbsTopLineNum -= buffer()->count_lines(mFirstChar, oldFirstChar); else mAbsTopLineNum += buffer()->count_lines(oldFirstChar, mFirstChar); } } /** Returns true if a separate absolute top line number is being maintained. The absolute top line number is used for displaying line numbers in continuous wrap mode or showing in the statistics line (the latter is currently not available in FLTK). */ int Fl_Text_Display::maintaining_absolute_top_line_number() const { return mContinuousWrap && (mLineNumWidth != 0 || mNeedAbsTopLineNum); } /** Reestablish the absolute (non-wrapped) top line number. Count lines from the beginning of the buffer to reestablish the absolute (non-wrapped) top line number. If mode is not continuous wrap, or the number is not being maintained, does nothing. */ void Fl_Text_Display::reset_absolute_top_line_number() { mAbsTopLineNum = 1; absolute_top_line_number(0); } /** Convert a position index into a line number offset. Find the line number of position \p pos relative to the first line of displayed text, counting from 0 to visible lines - 1. The line number is returned in \p lineNum. Returns 0 if the line is not displayed. In this case \p lineNum is 0 as well. Returns 1 if the line is displayed. In this case \p lineNum is the relative line number. \param[in] pos byte position in buffer \param[out] lineNum relative line number of byte \p pos in buffer \returns whether the character at byte position \p pos is currently displayed \retval 0 \p pos is not displayed; \p lineNum is invalid (zero) \retval 1 \p pos is displayed; \p lineNum is valid */ int Fl_Text_Display::position_to_line( int pos, int *lineNum ) const { IS_UTF8_ALIGNED2(buffer(), pos) int i; *lineNum = 0; if ( pos < mFirstChar ) return 0; if ( pos > mLastChar ) { if ( empty_vlines() ) { if ( mLastChar < mBuffer->length() ) { if ( !position_to_line( mLastChar, lineNum ) ) { Fl::error("Fl_Text_Display::position_to_line(): Consistency check ptvl failed"); return 0; } return ++( *lineNum ) <= mNVisibleLines - 1; } else { position_to_line( buffer()->prev_char_clipped(mLastChar), lineNum ); return 1; } } return 0; } for ( i = mNVisibleLines - 1; i >= 0; i-- ) { if ( mLineStarts[ i ] != -1 && pos >= mLineStarts[ i ] ) { *lineNum = i; return 1; } } return 0; /* probably never be reached */ } /** Universal pixel machine. We use a single function that handles all line layout, measuring, and drawing \li draw a text range \li return the width of a text range in pixels \li return the index of a character that is at a pixel position \param[in] mode DRAW_LINE, GET_WIDTH, FIND_INDEX, FIND_INDEX_FROM_ZERO, or FIND_CURSOR_INDEX \param[in] lineStartPos index of first character \param[in] lineLen size of string in bytes \param[in] leftChar, rightChar \param[in] Y drawing position \param[in] bottomClip, leftClip, rightClip stop work when we reach the clipped area. rightClip is the X position that we search in FIND_INDEX. \retval DRAW_LINE index of last drawn character \retval GET_WIDTH width in pixels of text segment if we would draw it \retval FIND_INDEX index of character at given x position in window coordinates \retval FIND_INDEX_FROM_ZERO index of character at given x position without scrolling and widget offsets \todo we need to handle hidden hyphens and tabs here! \todo we handle all styles and selections \todo we must provide code to get pixel positions of the middle of a character as well */ int Fl_Text_Display::handle_vline( int mode, int lineStartPos, int lineLen, int leftChar, int rightChar, int Y, int bottomClip, int leftClip, int rightClip) const { IS_UTF8_ALIGNED2(buffer(), lineStartPos) /* STR #2531 The variables startStyle and styleX seem to introduce some additional complexity. They were required to fix STR #2531 in which a horizontal character wiggle could be observed when drag-selecting text. This was caused by native drawing an measuring routines that support kerning (inter-character spacing, the width of 'T' plus the width of 'e' is greater than the width of 'Te', because advanced typesetting moves the 'e' slightly to the left below the 'T'). To acommodate this, FLTK uses slightly different routines for a true style change vs. a change in highlighting only. */ int i, X, startIndex, startStyle, style, charStyle; char *lineStr; double startX, styleX; if ( lineStartPos == -1 ) { lineStr = NULL; } else { lineStr = mBuffer->text_range( lineStartPos, lineStartPos + lineLen ); } // STR #2788 int cursor_pos = 0; if (mode==FIND_CURSOR_INDEX) { mode = FIND_INDEX; cursor_pos = 1; } if (mode==GET_WIDTH) { X = 0; } else if (mode==FIND_INDEX_FROM_ZERO) { X = 0; mode = FIND_INDEX; } else { X = text_area.x - mHorizOffset; } // In DRAW_LINE mode, the first iteration of the loop will draw all // backgrounds. The second iteration will draw the text, so that text // overlapping background color changes will not be clipped. for (int loop=1; loop<=2; loop++) { int mask = (loop==1) ? BG_ONLY_MASK : TEXT_ONLY_MASK; startX = X; startIndex = 0; if (!lineStr) { // just clear the background if (mode==DRAW_LINE) { style = position_style(lineStartPos, lineLen, -1); if (loop==1) draw_string( style|BG_ONLY_MASK, text_area.x, Y, text_area.x+text_area.w, lineStr, lineLen ); } if (mode==FIND_INDEX) { IS_UTF8_ALIGNED2(buffer(), lineStartPos) return lineStartPos; } return 0; } char currChar = 0, prevChar = 0; styleX = startX; startStyle = startIndex; // draw the line style = position_style(lineStartPos, lineLen, 0); for (i=0; itab_distance()); double xAbs = (mode==GET_WIDTH) ? startX : startX+mHorizOffset-text_area.x; w = ((int(xAbs/tab)+1)*tab) - xAbs; styleX = startX+w; startStyle = i; if (mode==DRAW_LINE && loop==1) draw_string( style|BG_ONLY_MASK, int(startX), Y, int(startX+w), 0, 0 ); if (mode==FIND_INDEX && startX+w>rightClip) { // find x pos inside block free(lineStr); if (cursor_pos && (startX+w/2rightClip) { // find x pos inside block int di; if (startIndex!=startStyle) { di = find_x(lineStr+startStyle, i-startStyle, style, -int(rightClip-styleX)); // STR #2788 di = lineStartPos + startStyle + di; } else { di = find_x(lineStr+startIndex, i-startIndex, style, -int(rightClip-startX)); // STR #2788 di = lineStartPos + startIndex + di; } free(lineStr); IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di)) return di; } if ( (style&0xff)!=(charStyle&0xff)) { startStyle = i; styleX = startX+w; } } style = charStyle; startX += w; startIndex = i; } i += len; prevChar = currChar; } double w = 0; if (currChar=='\t') { // draw a single Tab space double tab = col_to_x(mBuffer->tab_distance()); double xAbs = (mode==GET_WIDTH) ? startX : startX+mHorizOffset-text_area.x; w = ((int(xAbs/tab)+1)*tab) - xAbs; if (mode==DRAW_LINE && loop==1) draw_string( style|BG_ONLY_MASK, int(startX), Y, int(startX+w), 0, 0 ); if (mode==FIND_INDEX) { // find x pos inside block free(lineStr); if (cursor_pos) // STR #2788 return lineStartPos + startIndex + ( rightClip-startX>w/2 ? 1 : 0 ); // STR #2788 return lineStartPos + startIndex + ( rightClip-startX>w ? 1 : 0 ); } } else { w = string_width( lineStr+startIndex, i-startIndex, style ); if (mode==DRAW_LINE) { // STR 2531 if (startIndex!=startStyle) { fl_push_clip(int(startX), Y, int(w)+1, mMaxsize); draw_string( style|mask, int(styleX), Y, int(startX+w), lineStr+startStyle, i-startStyle ); fl_pop_clip(); } else { draw_string( style|mask, int(startX), Y, int(startX+w), lineStr+startIndex, i-startIndex ); } } if (mode==FIND_INDEX) { // find x pos inside block int di; if (startIndex!=startStyle) { di = find_x(lineStr+startStyle, i-startStyle, style, -int(rightClip-styleX)); // STR #2788 di = lineStartPos + startStyle + di; } else { di = find_x(lineStr+startIndex, i-startIndex, style, -int(rightClip-startX)); // STR #2788 di = lineStartPos + startIndex + di; } free(lineStr); IS_UTF8_ALIGNED2(buffer(), (lineStartPos+startIndex+di)) return di; } } if (mode==GET_WIDTH) { free(lineStr); return int(startX+w); } // clear the rest of the line startX += w; style = position_style(lineStartPos, lineLen, i); if (mode==DRAW_LINE && loop==1) draw_string( style|BG_ONLY_MASK, int(startX), Y, text_area.x+text_area.w, lineStr, lineLen ); } free(lineStr); IS_UTF8_ALIGNED2(buffer(), (lineStartPos+lineLen)) return lineStartPos + lineLen; } /** \brief Find the index of the character that lies at the given x position / closest cursor position. \param s UTF-8 text string \param len length of string \param style index into style lookup table \param x position in pixels - negative returns closest cursor position \return index into buffer */ int Fl_Text_Display::find_x(const char *s, int len, int style, int x) const { IS_UTF8_ALIGNED(s) int cursor_pos = x<0; // STR #2788 x = x<0 ? -x : x; // STR #2788 // TODO: use binary search which may be quicker. int i = 0; int last_w = 0; // STR #2788 while (ix) { if (cursor_pos && (w-x < x-last_w)) return i+cl; // STR #2788 return i; } last_w = w; // STR #2788 i += cl; } return len; } /** \brief Draw a single line of text. Draw the text on a single line represented by \p visLineNum (the number of lines down from the top of the display), limited by \p leftClip and \p rightClip window coordinates and \p leftCharIndex and \p rightCharIndex character positions (not including the character at position \p rightCharIndex). \param visLineNum index of line in the visible line number lookup \param leftClip, rightClip pixel position of clipped area \param leftCharIndex, rightCharIndex index into line of segment that we want to draw */ void Fl_Text_Display::draw_vline(int visLineNum, int leftClip, int rightClip, int leftCharIndex, int rightCharIndex) { int Y, lineStartPos, lineLen, fontHeight; // printf("draw_vline(visLineNum=%d, leftClip=%d, rightClip=%d, leftCharIndex=%d, rightCharIndex=%d)\n", // visLineNum, leftClip, rightClip, leftCharIndex, rightCharIndex); // printf("nNVisibleLines=%d\n", mNVisibleLines); /* If line is not displayed, skip it */ if ( visLineNum < 0 || visLineNum >= mNVisibleLines ) return; /* Calculate Y coordinate of the string to draw */ fontHeight = mMaxsize; Y = text_area.y + visLineNum * fontHeight; /* Get the text, length, and buffer position of the line to display */ lineStartPos = mLineStarts[ visLineNum ]; if ( lineStartPos == -1 ) { lineLen = 0; } else { lineLen = vline_length( visLineNum ); } /* Shrink the clipping range to the active display area */ leftClip = max( text_area.x, leftClip ); rightClip = min( rightClip, text_area.x + text_area.w ); handle_vline(DRAW_LINE, lineStartPos, lineLen, leftCharIndex, rightCharIndex, Y, Y+fontHeight, leftClip, rightClip); return; } /** \brief Draw a text segment in a single style. Draw a string or blank area according to parameter \p style, using the appropriate colors and drawing method for that style, with top left corner at \p X, \p Y. If style says to draw text, use \p string as source of characters, and draw \p nChars, if style is FILL, erase rectangle where text would have drawn from \p X to \p toX and from \p Y to the maximum y extent of the current font(s). \param style index into style lookup table \param X, Y drawing origin \param toX rightmost position if this is a fill operation \param string text if this is a drawing operation \param nChars number of characters to draw */ void Fl_Text_Display::draw_string(int style, int X, int Y, int toX, const char *string, int nChars) const { IS_UTF8_ALIGNED(string) const Style_Table_Entry *styleRec = NULL; /* Draw blank area rather than text, if that was the request */ if ( style & FILL_MASK ) { if (style & TEXT_ONLY_MASK) return; clear_rect( style, X, Y, toX - X, mMaxsize ); return; } /* Set font, color, and gc depending on style. For normal text, GCs for normal drawing, or drawing within a Fl_Text_Selection or highlight are pre-allocated and pre-configured. For syntax highlighting, GCs are configured here, on the fly. */ Fl_Font font = textfont(); int fsize = textsize(); Fl_Color foreground; Fl_Color background; Fl_Color bgbasecolor; if ( style & STYLE_LOOKUP_MASK ) { int si = (style & STYLE_LOOKUP_MASK) - 'A'; if (si < 0) si = 0; else if (si >= mNStyles) si = mNStyles - 1; styleRec = mStyleTable + si; font = styleRec->font; fsize = styleRec->size; bgbasecolor = (styleRec->attr&ATTR_BGCOLOR) ? styleRec->bgcolor : color(); if (style & PRIMARY_MASK) { if (Fl::focus() == (Fl_Widget*)this) { if (Fl::screen_driver()->has_marked_text() && Fl::compose_state) { background = bgbasecolor; // Mac OS: underline marked text } else { background = selection_color(); } } else { background = fl_color_average(bgbasecolor, selection_color(), 0.4f); } } else if (style & HIGHLIGHT_MASK) { if (Fl::focus() == (Fl_Widget*)this) { background = fl_color_average(bgbasecolor, selection_color(), 0.5f); } else { background = fl_color_average(bgbasecolor, selection_color(), 0.6f); } } else if (style & SECONDARY_MASK) { if (Fl::focus() == (Fl_Widget*)this) { background = fl_color_average(bgbasecolor, secondary_selection_color(), 0.5f); } else { background = fl_color_average(bgbasecolor, secondary_selection_color(), 0.6f); } } else { background = bgbasecolor; } foreground = (style & PRIMARY_MASK) ? fl_contrast(styleRec->color, background) : styleRec->color; } else if (style & PRIMARY_MASK) { if (Fl::focus() == (Fl_Widget*)this) { background = selection_color(); } else { background = fl_color_average(color(), selection_color(), 0.4f); } foreground = fl_contrast(textcolor(), background); } else if (style & HIGHLIGHT_MASK) { if (Fl::focus() == (Fl_Widget*)this) { background = fl_color_average(color(), selection_color(), 0.5f); } else { background = fl_color_average(color(), selection_color(), 0.6f); } foreground = fl_contrast(textcolor(), background); } else if (style & SECONDARY_MASK) { if (Fl::focus() == (Fl_Widget*)this) { background = secondary_selection_color(); } else { background = fl_color_average(color(), secondary_selection_color(), 0.4f); } foreground = fl_contrast(textcolor(), background); } else { foreground = textcolor(); background = color(); } if ( !active_r() ) { foreground = fl_inactive(foreground); background = fl_inactive(background); } if (!(style & TEXT_ONLY_MASK)) { fl_color( background ); fl_rectf( X, Y, toX - X, mMaxsize ); } if (!(style & BG_ONLY_MASK)) { fl_color( foreground ); fl_font( font, fsize ); int baseline = Y + mMaxsize - fl_descent(); // Make sure antialiased ÄÖÜ do not leak on line above: // on X11+Xft the antialiased part of characters such as ÄÖÜ leak on the bottom pixel of the line above static int can_leak = Fl::screen_driver()->text_display_can_leak(); // Clip top and bottom only. Add margin to avoid clipping horizontally if (can_leak) fl_push_clip(x(), Y, w(), mMaxsize); fl_draw( string, nChars, X, baseline); if (styleRec) { if (styleRec->attr & ATTR_LINES_MASK) { int pitch = fsize/7; int prevAA = fl_antialias(); fl_antialias(1); switch (styleRec->attr & ATTR_LINES_MASK) { case ATTR_UNDERLINE: fl_color(foreground); fl_line_style(FL_SOLID, pitch); goto DRAW_UNDERLINE; break; case ATTR_GRAMMAR: fl_color(grammar_underline_color()); goto DRAW_DOTTED_UNDERLINE; case ATTR_SPELLING: fl_color(spelling_underline_color()); DRAW_DOTTED_UNDERLINE: fl_line_style(FL_DOT, pitch); DRAW_UNDERLINE: fl_xyline(X, baseline + fl_descent()/2, toX); break; case ATTR_STRIKE_THROUGH: fl_color(foreground); fl_line_style(FL_SOLID, pitch); fl_xyline(X, baseline - (fl_height()-fl_descent())/3, toX); break; } fl_line_style(FL_SOLID, 1); fl_antialias(prevAA); } } if (Fl::screen_driver()->has_marked_text() && Fl::compose_state && (style & PRIMARY_MASK)) { fl_color( fl_color_average(foreground, background, 0.6f) ); fl_line(X, Y + mMaxsize - 1, X + (int)fl_width(string, nChars), Y + mMaxsize - 1); } if (can_leak) fl_pop_clip(); } // CET - FIXME /* If any space around the character remains unfilled (due to use of different sized fonts for highlighting), fill in above or below to erase previously drawn characters */ /* if (fs->ascent < mAscent) clear_rect( style, X, Y, toX - X, mAscent - fs->ascent); if (fs->descent < mDescent) clear_rect( style, X, Y + mAscent + fs->descent, toX - x, mDescent - fs->descent); */ /* Underline if style is secondary Fl_Text_Selection */ /* if (style & SECONDARY_MASK) XDrawLine(XtDisplay(mW), XtWindow(mW), gc, x, y + mAscent, toX - 1, Y + fs->ascent); */ } /** \brief Clear a rectangle with the appropriate background color for \p style. \param style index into style table \param X, Y, width, height size and position of background area */ void Fl_Text_Display::clear_rect(int style, int X, int Y, int width, int height) const { /* A width of zero means "clear to end of window" to XClearArea */ if ( width == 0 ) return; Fl_Color bgbasecolor = color(); if ( style & STYLE_LOOKUP_MASK ) { int si = (style & STYLE_LOOKUP_MASK) - 'A'; if (si < 0) si = 0; else if (si >= mNStyles) si = mNStyles - 1; const Style_Table_Entry *styleRec = mStyleTable + si; if (styleRec->attr&ATTR_BGCOLOR_EXT_) bgbasecolor = styleRec->bgcolor; } Fl_Color c; if (style & PRIMARY_MASK) { if (Fl::focus()==(Fl_Widget*)this) { c = selection_color(); } else { c = fl_color_average(bgbasecolor, selection_color(), 0.4f); } } else if (style & HIGHLIGHT_MASK) { if (Fl::focus()==(Fl_Widget*)this) { c = fl_color_average(bgbasecolor, selection_color(), 0.5f); } else { c = fl_color_average(bgbasecolor, selection_color(), 0.6f); } } else { c = bgbasecolor; } fl_color(active_r() ? c : fl_inactive(c)); fl_rectf( X, Y, width, height ); } /** \brief Draw a cursor with top center at \p X, \p Y. \param X, Y cursor position in pixels */ void Fl_Text_Display::draw_cursor( int X, int Y ) { typedef struct { int x1, y1, x2, y2; } Segment; Segment segs[ 5 ]; int left, right, cursorWidth, midY; // int fontWidth = mFontStruct->min_bounds.width, nSegs = 0; int fontWidth = TMPFONTWIDTH; // CET - FIXME int nSegs = 0; int fontHeight = mMaxsize; int bot = Y + fontHeight - 1; if ( X < text_area.x - 1 || X > text_area.x + text_area.w ) return; /* For cursors other than the block, make them around 2/3 of a character width, rounded to an even number of pixels so that X will draw an odd number centered on the stem at x. */ cursorWidth = 4; //(fontWidth/3) * 2; left = X - cursorWidth / 2; right = left + cursorWidth; /* Create segments and draw cursor */ if ( mCursorStyle == CARET_CURSOR ) { midY = bot - fontHeight / 5; segs[ 0 ].x1 = left; segs[ 0 ].y1 = bot; segs[ 0 ].x2 = X; segs[ 0 ].y2 = midY; segs[ 1 ].x1 = X; segs[ 1 ].y1 = midY; segs[ 1 ].x2 = right; segs[ 1 ].y2 = bot; segs[ 2 ].x1 = left; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = midY - 1; segs[ 3 ].x1 = X; segs[ 3 ].y1 = midY - 1; segs[ 3 ].x2 = right; segs[ 3 ].y2 = bot; nSegs = 4; } else if ( mCursorStyle == NORMAL_CURSOR ) { segs[ 0 ].x1 = left; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = right; segs[ 0 ].y2 = Y; segs[ 1 ].x1 = X; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = X; segs[ 1 ].y2 = bot; segs[ 2 ].x1 = left; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = right; segs[ 2 ].y2 = bot; nSegs = 3; } else if ( mCursorStyle == HEAVY_CURSOR ) { segs[ 0 ].x1 = X - 1; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = X - 1; segs[ 0 ].y2 = bot; segs[ 1 ].x1 = X; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = X; segs[ 1 ].y2 = bot; segs[ 2 ].x1 = X + 1; segs[ 2 ].y1 = Y; segs[ 2 ].x2 = X + 1; segs[ 2 ].y2 = bot; segs[ 3 ].x1 = left; segs[ 3 ].y1 = Y; segs[ 3 ].x2 = right; segs[ 3 ].y2 = Y; segs[ 4 ].x1 = left; segs[ 4 ].y1 = bot; segs[ 4 ].x2 = right; segs[ 4 ].y2 = bot; nSegs = 5; } else if ( mCursorStyle == DIM_CURSOR ) { midY = Y + fontHeight / 2; segs[ 0 ].x1 = X; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = X; segs[ 0 ].y2 = Y; segs[ 1 ].x1 = X; segs[ 1 ].y1 = midY; segs[ 1 ].x2 = X; segs[ 1 ].y2 = midY; segs[ 2 ].x1 = X; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = bot; nSegs = 3; } else if ( mCursorStyle == BLOCK_CURSOR ) { right = X + fontWidth; segs[ 0 ].x1 = X; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = right; segs[ 0 ].y2 = Y; segs[ 1 ].x1 = right; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = right; segs[ 1 ].y2 = bot; segs[ 2 ].x1 = right; segs[ 2 ].y1 = bot; segs[ 2 ].x2 = X; segs[ 2 ].y2 = bot; segs[ 3 ].x1 = X; segs[ 3 ].y1 = bot; segs[ 3 ].x2 = X; segs[ 3 ].y2 = Y; nSegs = 4; } else if ( mCursorStyle == SIMPLE_CURSOR ){ segs[ 0 ].x1 = X; segs[ 0 ].y1 = Y; segs[ 0 ].x2 = X; segs[ 0 ].y2 = bot; segs[ 1 ].x1 = X+1; segs[ 1 ].y1 = Y; segs[ 1 ].x2 = X+1; segs[ 1 ].y2 = bot; nSegs = 2; } fl_color( mCursor_color ); for ( int k = 0; k < nSegs; k++ ) { fl_line( segs[ k ].x1, segs[ k ].y1, segs[ k ].x2, segs[ k ].y2 ); } //fix issue #270 if (Fl::focus() == this) { fl_set_spot(textfont(), textsize(), X, bot, text_area.w, text_area.h, window()); } } /** \brief Find the correct style for a character. Determine the drawing method to use to draw a specific character from "buf". \p lineStartPos gives the character index where the line begins, \p lineIndex, the number of characters past the beginning of the line, and \p lineLen the number of displayed characters past the beginning of the line. Passing \p lineStartPos of -1 returns the drawing style for "no text". Why not just: position_style(pos)? Because style applies to blank areas of the window beyond the text boundaries, and because this routine must also decide whether a position is inside of a rectangular Fl_Text_Selection, and do so efficiently, without re-counting character positions from the start of the line. Note that style is a somewhat incorrect name, drawing method would be more appropriate. If lineIndex is pointing to the last character in a line, and the second to last character has the ATTR_BGCOLOR_EXT set, the background color will extend into the remaining line. \param lineStartPos beginning of this line \param lineLen number of bytes in line \param lineIndex position of character within line \return style for the given character */ int Fl_Text_Display::position_style( int lineStartPos, int lineLen, int lineIndex) const { IS_UTF8_ALIGNED2(buffer(), lineStartPos) Fl_Text_Buffer * buf = mBuffer; Fl_Text_Buffer *styleBuf = mStyleBuffer; int pos, style = 0; if ( lineStartPos == -1 || buf == NULL ) return FILL_MASK; pos = lineStartPos + min( lineIndex, lineLen ); if ( styleBuf && lineIndex==lineLen && lineLen>0) { style = ( unsigned char ) styleBuf->byte_at( pos-1 ); if (style == mUnfinishedStyle && mUnfinishedHighlightCB) { (mUnfinishedHighlightCB)( pos, mHighlightCBArg); style = (unsigned char) styleBuf->byte_at( pos); } int si = (style & STYLE_LOOKUP_MASK) - 'A'; if (si < 0) si = 0; else if (si >= mNStyles) si = mNStyles - 1; const Style_Table_Entry *styleRec = mStyleTable + si; if ((styleRec->attr&ATTR_BGCOLOR_EXT_)==0) style = FILL_MASK; } else if ( lineIndex >= lineLen ) { style = FILL_MASK; } else if ( styleBuf != NULL ) { style = ( unsigned char ) styleBuf->byte_at( pos ); if (style == mUnfinishedStyle && mUnfinishedHighlightCB) { /* encountered "unfinished" style, trigger parsing */ (mUnfinishedHighlightCB)( pos, mHighlightCBArg); style = (unsigned char) styleBuf->byte_at( pos); } } if (buf->primary_selection()->includes(pos)) style |= PRIMARY_MASK; if (buf->highlight_selection()->includes(pos)) style |= HIGHLIGHT_MASK; if (buf->secondary_selection()->includes(pos)) style |= SECONDARY_MASK; return style; } /** \brief Find the width of a string in the font of a particular style. \param string the text \param length number of bytes in string \param style index into style table \return width of text segment in pixels */ double Fl_Text_Display::string_width( const char *string, int length, int style ) const { IS_UTF8_ALIGNED(string) Fl_Font font; Fl_Fontsize fsize; if ( mNStyles && (style & STYLE_LOOKUP_MASK) ) { int si = (style & STYLE_LOOKUP_MASK) - 'A'; if (si < 0) si = 0; else if (si >= mNStyles) si = mNStyles - 1; font = mStyleTable[si].font; fsize = mStyleTable[si].size; } else { font = textfont(); fsize = textsize(); } fl_font( font, fsize ); return fl_width( string, length ); } /** \brief Translate a pixel position into a character index. Translate window coordinates to the nearest (insert cursor or character cell) text position. The parameter \p posType specifies how to interpret the position: CURSOR_POS means translate the coordinates to the nearest cursor position, and CHARACTER_POS means return the position of the character closest to (\p X, \p Y). \param X, Y pixel position \param posType CURSOR_POS or CHARACTER_POS \return index into text buffer */ int Fl_Text_Display::xy_to_position( int X, int Y, int posType ) const { int lineStart, lineLen, fontHeight; int visLineNum; /* Find the visible line number corresponding to the Y coordinate */ fontHeight = mMaxsize; visLineNum = ( Y - text_area.y ) / fontHeight; if ( visLineNum < 0 ) return mFirstChar; if ( visLineNum >= mNVisibleLines ) visLineNum = mNVisibleLines - 1; /* Find the position at the start of the line */ lineStart = mLineStarts[ visLineNum ]; /* If the line start was empty, return the last position in the buffer */ if ( lineStart == -1 ) return mBuffer->length(); /* Get the line text and its length */ lineLen = vline_length( visLineNum ); int mode = (posType == CURSOR_POS) ? FIND_CURSOR_INDEX : FIND_INDEX; // STR #2788 return handle_vline(mode, lineStart, lineLen, 0, 0, 0, 0, text_area.x, X); } /** \brief Translate pixel coordinates into row and column. Translate window coordinates to the nearest row and column number for positioning the cursor. This, of course, makes no sense when the font is proportional, since there are no absolute columns. The parameter posType specifies how to interpret the position: CURSOR_POS means translate the coordinates to the nearest position between characters, and CHARACTER_POS means translate the position to the nearest character cell. \param X, Y pixel coordinates \param[out] row, column neares row and column \param posType CURSOR_POS or CHARACTER_POS */ void Fl_Text_Display::xy_to_rowcol( int X, int Y, int *row, int *column, int posType ) const { int fontHeight = mMaxsize; int fontWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width; /* Find the visible line number corresponding to the Y coordinate */ *row = ( Y - text_area.y ) / fontHeight; if ( *row < 0 ) *row = 0; if ( *row >= mNVisibleLines ) *row = mNVisibleLines - 1; *column = ( ( X - text_area.x ) + mHorizOffset + ( posType == CURSOR_POS ? fontWidth / 2 : 0 ) ) / fontWidth; if ( *column < 0 ) * column = 0; } /** \brief Offset line start counters for a new vertical scroll position. Offset the line starts array, mTopLineNum, mFirstChar and lastChar, for a new vertical scroll position given by newTopLineNum. If any currently displayed lines will still be visible, salvage the line starts values, otherwise, count lines from the nearest known line start (start or end of buffer, or the closest value in the mLineStarts array) \param newTopLineNum index into buffer */ void Fl_Text_Display::offset_line_starts( int newTopLineNum ) { int oldTopLineNum = mTopLineNum; int oldFirstChar = mFirstChar; int lineDelta = newTopLineNum - oldTopLineNum; int nVisLines = mNVisibleLines; int *lineStarts = mLineStarts; int i, lastLineNum; Fl_Text_Buffer *buf = mBuffer; /* If there was no offset, nothing needs to be changed */ if ( lineDelta == 0 ) return; /* Find the new value for mFirstChar by counting lines from the nearest known line start (start or end of buffer, or the closest value in the lineStarts array) */ lastLineNum = oldTopLineNum + nVisLines - 1; if ( newTopLineNum < oldTopLineNum && newTopLineNum < -lineDelta ) { mFirstChar = skip_lines( 0, newTopLineNum - 1, true ); } else if ( newTopLineNum < oldTopLineNum ) { mFirstChar = rewind_lines( mFirstChar, -lineDelta ); } else if ( newTopLineNum < lastLineNum ) { mFirstChar = lineStarts[ newTopLineNum - oldTopLineNum ]; } else if ( newTopLineNum - lastLineNum < mNBufferLines - newTopLineNum ) { mFirstChar = skip_lines( lineStarts[ nVisLines - 1 ], newTopLineNum - lastLineNum, true ); } else { mFirstChar = rewind_lines( buf->length(), mNBufferLines - newTopLineNum + 1 ); } /* Fill in the line starts array */ if ( lineDelta < 0 && -lineDelta < nVisLines ) { for ( i = nVisLines - 1; i >= -lineDelta; i-- ) lineStarts[ i ] = lineStarts[ i + lineDelta ]; calc_line_starts( 0, -lineDelta ); } else if ( lineDelta > 0 && lineDelta < nVisLines ) { for ( i = 0; i < nVisLines - lineDelta; i++ ) lineStarts[ i ] = lineStarts[ i + lineDelta ]; calc_line_starts( nVisLines - lineDelta, nVisLines - 1 ); } else calc_line_starts( 0, nVisLines ); /* Set lastChar and mTopLineNum */ calc_last_char(); mTopLineNum = newTopLineNum; /* If we're numbering lines or being asked to maintain an absolute line number, re-calculate the absolute line number */ absolute_top_line_number(oldFirstChar); } /** \brief Update line start arrays and variables. Update the line starts array, mTopLineNum, mFirstChar and lastChar for this text display after a modification to the text buffer, given by the position \p pos where the change began, and the numbers of characters and lines inserted and deleted. \param pos index into buffer of recent changes \param charsInserted number of bytes(!) inserted \param charsDeleted number of bytes(!) deleted \param linesInserted number of lines \param linesDeleted number of lines \param[out] scrolled set to 1 if the text display needs to be scrolled */ void Fl_Text_Display::update_line_starts(int pos, int charsInserted, int charsDeleted, int linesInserted, int linesDeleted, int *scrolled ) { IS_UTF8_ALIGNED2(buffer(), pos) int *lineStarts = mLineStarts; int i, lineOfPos, lineOfEnd, nVisLines = mNVisibleLines; int charDelta = charsInserted - charsDeleted; int lineDelta = linesInserted - linesDeleted; /* If all of the changes were before the displayed text, the display doesn't change, just update the top line num and offset the line start entries and first and last characters */ if ( pos + charsDeleted < mFirstChar ) { mTopLineNum += lineDelta; for ( i = 0; i < nVisLines && lineStarts[i] != -1; i++ ) lineStarts[ i ] += charDelta; mFirstChar += charDelta; mLastChar += charDelta; *scrolled = 0; return; } /* The change began before the beginning of the displayed text, but part or all of the displayed text was deleted */ if ( pos < mFirstChar ) { /* If some text remains in the window, anchor on that */ if ( position_to_line( pos + charsDeleted, &lineOfEnd ) && ++lineOfEnd < nVisLines && lineStarts[ lineOfEnd ] != -1 ) { mTopLineNum = max( 1, mTopLineNum + lineDelta ); mFirstChar = rewind_lines(lineStarts[ lineOfEnd ] + charDelta, lineOfEnd ); /* Otherwise anchor on original line number and recount everything */ } else { if ( mTopLineNum > mNBufferLines + lineDelta ) { mTopLineNum = 1; mFirstChar = 0; } else mFirstChar = skip_lines( 0, mTopLineNum - 1, true ); } calc_line_starts( 0, nVisLines - 1 ); /* calculate lastChar by finding the end of the last displayed line */ calc_last_char(); *scrolled = 1; return; } /* If the change was in the middle of the displayed text (it usually is), salvage as much of the line starts array as possible by moving and offsetting the entries after the changed area, and re-counting the added lines or the lines beyond the salvaged part of the line starts array */ if ( pos <= mLastChar ) { /* find line on which the change began */ position_to_line( pos, &lineOfPos ); /* salvage line starts after the changed area */ if ( lineDelta == 0 ) { for ( i = lineOfPos + 1; i < nVisLines && lineStarts[ i ] != -1; i++ ) lineStarts[ i ] += charDelta; } else if ( lineDelta > 0 ) { for ( i = nVisLines - 1; i >= lineOfPos + lineDelta + 1; i-- ) lineStarts[ i ] = lineStarts[ i - lineDelta ] + ( lineStarts[ i - lineDelta ] == -1 ? 0 : charDelta ); } else /* (lineDelta < 0) */ { for ( i = max( 0, lineOfPos + 1 ); i < nVisLines + lineDelta; i++ ) lineStarts[ i ] = lineStarts[ i - lineDelta ] + ( lineStarts[ i - lineDelta ] == -1 ? 0 : charDelta ); } /* fill in the missing line starts */ if ( linesInserted >= 0 ) calc_line_starts( lineOfPos + 1, lineOfPos + linesInserted ); if ( lineDelta < 0 ) calc_line_starts( nVisLines + lineDelta, nVisLines ); /* calculate lastChar by finding the end of the last displayed line */ calc_last_char(); *scrolled = 0; return; } /* Change was past the end of the displayed text, but displayable by virtue of being an insert at the end of the buffer into visible blank lines */ if ( empty_vlines() ) { position_to_line( pos, &lineOfPos ); calc_line_starts( lineOfPos, lineOfPos + linesInserted ); calc_last_char(); *scrolled = 0; return; } /* Change was beyond the end of the buffer and not visible, do nothing */ *scrolled = 0; } /** \brief Update the line starts array. Scan through the text in the Text Display's buffer and recalculate the line starts array values beginning at index "startLine" and continuing through (including) "endLine". It assumes that the line starts entry preceding "startLine" (or mFirstChar if startLine is 0) is good, and re-counts newlines to fill in the requested entries. Out of range values for "startLine" and "endLine" are acceptable. \param startLine, endLine range of lines to scan as line numbers */ void Fl_Text_Display::calc_line_starts( int startLine, int endLine ) { int startPos, bufLen = mBuffer->length(); int line, lineEnd, nextLineStart, nVis = mNVisibleLines; int *lineStarts = mLineStarts; /* Clean up (possibly) messy input parameters */ if ( endLine < 0 ) endLine = 0; if ( endLine >= nVis ) endLine = nVis - 1; if ( startLine < 0 ) startLine = 0; if ( startLine >= nVis ) startLine = nVis - 1; if ( startLine > endLine ) return; /* Find the last known good line number -> position mapping */ if ( startLine == 0 ) { lineStarts[ 0 ] = mFirstChar; startLine = 1; } startPos = lineStarts[ startLine - 1 ]; /* If the starting position is already past the end of the text, fill in -1's (means no text on line) and return */ if ( startPos == -1 ) { for ( line = startLine; line <= endLine; line++ ) lineStarts[ line ] = -1; return; } /* Loop searching for ends of lines and storing the positions of the start of the next line in lineStarts */ for ( line = startLine; line <= endLine; line++ ) { find_line_end(startPos, true, &lineEnd, &nextLineStart); startPos = nextLineStart; if ( startPos >= bufLen ) { /* If the buffer ends with a newline or line break, put buf->length() in the next line start position (instead of a -1 which is the normal marker for an empty line) to indicate that the cursor may safely be displayed there */ if ( line == 0 || ( lineStarts[ line - 1 ] != bufLen && lineEnd != nextLineStart ) ) { lineStarts[ line ] = bufLen; line++; } break; } lineStarts[ line ] = startPos; } /* Set any entries beyond the end of the text to -1 */ for ( ; line <= endLine; line++ ) lineStarts[ line ] = -1; } /** \brief Update last display character index. Given a Fl_Text_Display with a complete, up-to-date lineStarts array, update the lastChar entry to point to the last buffer position displayed. */ void Fl_Text_Display::calc_last_char() { int i; for (i = mNVisibleLines - 1; i >= 0 && mLineStarts[i] == -1; i--) ; mLastChar = i < 0 ? 0 : line_end(mLineStarts[i], true); } /** \brief Scrolls the current buffer to start at the specified line and column. \param topLineNum top line number \param horizOffset column number \todo Column numbers make little sense here. */ void Fl_Text_Display::scroll(int topLineNum, int horizOffset) { mTopLineNumHint = topLineNum; mHorizOffsetHint = horizOffset; display_needs_recalc(); // resize(x(), y(), w(), h()); } /** \brief Scrolls the current buffer to start at the specified line and column. \param topLineNum top line number \param horizOffset in pixels \return 0 if nothing changed, 1 if we scrolled */ int Fl_Text_Display::scroll_(int topLineNum, int horizOffset) { /* Limit the requested scroll position to allowable values */ if (topLineNum > mNBufferLines + 3 - mNVisibleLines) topLineNum = mNBufferLines + 3 - mNVisibleLines; if (topLineNum < 1) topLineNum = 1; if (horizOffset > longest_vline() - text_area.w) horizOffset = longest_vline() - text_area.w; if (horizOffset < 0) horizOffset = 0; /* Do nothing if scroll position hasn't actually changed or there's no window to draw in yet */ if (mHorizOffset == horizOffset && mTopLineNum == topLineNum) return 0; /* If the vertical scroll position has changed, update the line starts array and related counters in the text display */ offset_line_starts(topLineNum); /* Just setting mHorizOffset is enough information for redisplay */ mHorizOffset = horizOffset; // redraw all text damage(FL_DAMAGE_EXPOSE); return 1; } /** \brief Update vertical scrollbar. Update the minimum, maximum, slider size, page increment, and value for the vertical scrollbar. */ void Fl_Text_Display::update_v_scrollbar() { /* The vertical scrollbar value and slider size directly represent the top line number, and the number of visible lines respectively. The scroll bar maximum value is chosen to generally represent the size of the whole buffer, with minor adjustments to keep the scrollbar widget happy */ #ifdef DEBUG printf("Fl_Text_Display::update_v_scrollbar():\n" " mTopLineNum=%d, mNVisibleLines=%d, mNBufferLines=%d\n", mTopLineNum, mNVisibleLines, mNBufferLines); #endif // DEBUG mVScrollBar->value(mTopLineNum, mNVisibleLines, 1, mNBufferLines+1+ ((mContinuousWrap && mWrapMarginPix) ? 0 : 1)); mVScrollBar->linesize(3); } /** \brief Update horizontal scrollbar. Update the minimum, maximum, slider size, page increment, and value for the horizontal scrollbar. */ void Fl_Text_Display::update_h_scrollbar() { int sliderMax = max(longest_vline(), text_area.w + mHorizOffset); mHScrollBar->value( mHorizOffset, text_area.w, 0, sliderMax ); } /** \brief Callback for drag or valueChanged on vertical scrollbar. */ void Fl_Text_Display::v_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) { if (b->value() == textD->mTopLineNum) return; textD->scroll(b->value(), textD->mHorizOffset); } /** \brief Callback for drag or valueChanged on horizontal scrollbar. */ void Fl_Text_Display::h_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) { if (b->value() == textD->mHorizOffset) return; textD->scroll(textD->mTopLineNum, b->value()); } /** \brief Refresh the line number area. \param clearAll -- (currently unused) If False, only draws the line number text, does not clear the area behind it. If True, clears the area and redraws the text. Use False to avoid a 'flash' for single buffered windows. */ // This draw_line_numbers() method based on patch from // http://www.mail-archive.com/fltk-dev@easysw.com/msg06376.html // altered to support line numbers right alignment. -LZA / STR #2621 // void Fl_Text_Display::draw_line_numbers(bool /*clearAll*/) { int Y, line, visLine, lineStart; char lineNumString[16]; int lineHeight = mMaxsize; int isactive = active_r() ? 1 : 0; // Don't draw if lineNumWidth == 0 (line numbers are hidden), // or widget is not yet realized if (mLineNumWidth <= 0 || !visible_r()) return; // Make sure we set the correct clipping range for line numbers. // Take scrollbars and positions into account. int hscroll_h = mHScrollBar->visible() ? mHScrollBar->h() : 0; int xoff = Fl::box_dx(box()); int yoff = text_area.y - y(); #ifndef LINENUM_LEFT_OF_VSCROLL int vscroll_w = mVScrollBar->visible() ? mVScrollBar->w() : 0; if (scrollbar_align() & FL_ALIGN_LEFT) xoff += vscroll_w; #endif Fl_Color fgcolor = isactive ? linenumber_fgcolor() : fl_inactive(linenumber_fgcolor()); Fl_Color bgcolor = isactive ? linenumber_bgcolor() : fl_inactive(linenumber_bgcolor()); fl_push_clip(x() + xoff, y() + Fl::box_dy(box()), mLineNumWidth, h() - Fl::box_dh(box())); { // Set background color for line number area -- LZA / STR# 2621 // Erase background fl_color(bgcolor); fl_rectf(x()+xoff, y(), mLineNumWidth, h()); // Draw separator line //fl_color(180,180,180); //fl_line(x()+mLineNumWidth-1, y(), x()+mLineNumWidth-1, y()+h()); // Draw line number text fl_font(linenumber_font(), linenumber_size()); Y = y() + yoff; line = get_absolute_top_line_number(); // set font color for line numbers fl_color(fgcolor); for (visLine=0; visLine < mNVisibleLines; visLine++) { lineStart = mLineStarts[visLine]; if (lineStart != -1 && (lineStart==0 || buffer()->char_at(lineStart-1)=='\n')) { snprintf(lineNumString, sizeof(lineNumString), linenumber_format(), line); int xx = x() + xoff + 3, yy = Y, ww = mLineNumWidth - (3*2), hh = lineHeight; fl_draw(lineNumString, xx, yy, ww, hh, linenumber_align(), 0, 0); //DEBUG fl_rect(xx, yy, ww, hh); line++; } else { if (visLine == 0) line++; } Y += lineHeight; } } // fill the void area to the left of the horizontal scrollbar that exists // above or beneath the line number display (when on) with background color fl_color(FL_BACKGROUND_COLOR); if (scrollbar_align() & FL_ALIGN_TOP) fl_rectf(x() + xoff, y() + Fl::box_dy(box()), mLineNumWidth, hscroll_h); else fl_rectf(x() + xoff, y() + h() - hscroll_h - Fl::box_dy(box()), mLineNumWidth, hscroll_h + Fl::box_dy(box())); fl_pop_clip(); } static int max( int i1, int i2 ) { return i1 >= i2 ? i1 : i2; } static int min( int i1, int i2 ) { return i1 <= i2 ? i1 : i2; } /** Count the number of newlines in a null-terminated text string; */ static int countlines( const char *string ) { IS_UTF8_ALIGNED(string) const char * c; int lineCount = 0; if (!string) return 0; for ( c = string; *c != '\0'; c++ ) if ( *c == '\n' ) lineCount++; return lineCount; } /** \brief Returns the width in pixels of the displayed line pointed to by "visLineNum". \param visLineNum index into visible lines array \return width of line in pixels */ int Fl_Text_Display::measure_vline( int visLineNum ) const { int lineLen = vline_length( visLineNum ); int lineStartPos = mLineStarts[ visLineNum ]; if (lineStartPos < 0 || lineLen == 0) return 0; return handle_vline(GET_WIDTH, lineStartPos, lineLen, 0, 0, 0, 0, 0, 0); } /** \brief Return true if there are lines visible with no corresponding buffer text. \return 1 if there are empty lines */ int Fl_Text_Display::empty_vlines() const { return (mNVisibleLines > 0) && (mLineStarts[ mNVisibleLines - 1 ] == -1); } /** \brief Count number of bytes in a visible line. Return the length of a line (number of bytes) by examining entries in the line starts array rather than by scanning for newlines. \param visLineNum index of line in visible line array \return number of bytes in this line */ int Fl_Text_Display::vline_length( int visLineNum ) const { int nextLineStart, lineStartPos; if (visLineNum < 0 || visLineNum >= mNVisibleLines) return (0); lineStartPos = mLineStarts[ visLineNum ]; if ( lineStartPos == -1 ) return 0; if ( visLineNum + 1 >= mNVisibleLines ) return mLastChar - lineStartPos; nextLineStart = mLineStarts[ visLineNum + 1 ]; if ( nextLineStart == -1 ) return mLastChar - lineStartPos; int nextLineStartMinus1 = buffer()->prev_char(nextLineStart); if (wrap_uses_character(nextLineStartMinus1)) return nextLineStartMinus1 - lineStartPos; return nextLineStart - lineStartPos; } /** \brief Wrapping calculations. When continuous wrap is on, and the user inserts or deletes characters, wrapping can happen before and beyond the changed position. This routine finds the extent of the changes, and counts the deleted and inserted lines over that range. It also attempts to minimize the size of the range to what has to be counted and re-displayed, so the results can be useful both for delimiting where the line starts need to be recalculated, and for deciding what part of the text to redisplay. \param deletedText \param pos \param nInserted \param nDeleted \param modRangeStart \param modRangeEnd \param linesInserted \param linesDeleted */ void Fl_Text_Display::find_wrap_range(const char *deletedText, int pos, int nInserted, int nDeleted, int *modRangeStart, int *modRangeEnd, int *linesInserted, int *linesDeleted) { IS_UTF8_ALIGNED(deletedText) IS_UTF8_ALIGNED2(buffer(), pos) int length, retPos, retLines, retLineStart, retLineEnd; Fl_Text_Buffer *deletedTextBuf, *buf = buffer(); int nVisLines = mNVisibleLines; int *lineStarts = mLineStarts; int countFrom, countTo, lineStart, adjLineStart, i; int visLineNum = 0, nLines = 0; /* ** Determine where to begin searching: either the previous newline, or ** if possible, limit to the start of the (original) previous displayed ** line, using information from the existing line starts array */ if (pos >= mFirstChar && pos <= mLastChar) { for (i=nVisLines-1; i>0; i--) { if (lineStarts[i] != -1 && pos >= lineStarts[i]) { break; } } if (i > 0) { countFrom = lineStarts[i-1]; visLineNum = i-1; } else { countFrom = buf->line_start(pos); } } else { countFrom = buf->line_start(pos); } IS_UTF8_ALIGNED2(buf, countFrom) /* ** Move forward through the (new) text one line at a time, counting ** displayed lines, and looking for either a real newline, or for the ** line starts to re-sync with the original line starts array */ lineStart = countFrom; *modRangeStart = countFrom; for (;;) { /* advance to the next line. If the line ended in a real newline or the end of the buffer, that's far enough */ wrapped_line_counter(buf, lineStart, buf->length(), 1, true, 0, &retPos, &retLines, &retLineStart, &retLineEnd); if (retPos >= buf->length()) { countTo = buf->length(); *modRangeEnd = countTo; if (retPos != retLineEnd) nLines++; break; } else { lineStart = retPos; } nLines++; if (lineStart > pos + nInserted && buf->char_at(buf->prev_char(lineStart)) == '\n') { countTo = lineStart; *modRangeEnd = lineStart; break; } /* Don't try to resync in continuous wrap mode with non-fixed font sizes; it would result in a chicken-and-egg dependency between the calculations for the inserted and the deleted lines. If we're in that mode, the number of deleted lines is calculated in advance, without resynchronization, so we shouldn't resynchronize for the inserted lines either. */ if (mSuppressResync) continue; /* check for synchronization with the original line starts array before pos, if so, the modified range can begin later */ if (lineStart <= pos) { while (visLineNumprev_char(lineStarts[visLineNum+1])); else *modRangeStart = countFrom; } else *modRangeStart = min(*modRangeStart, buf->prev_char(lineStart)); } /* check for synchronization with the original line starts array after pos, if so, the modified range can end early */ else if (lineStart > pos + nInserted) { adjLineStart = lineStart - nInserted + nDeleted; while (visLineNumcopy(buffer(), countFrom, pos, 0); if (nDeleted != 0) deletedTextBuf->insert(pos-countFrom, deletedText); deletedTextBuf->copy(buffer(), pos+nInserted, countTo, pos-countFrom+nDeleted); /* Note that we need to take into account an offset for the style buffer: the deletedTextBuf can be out of sync with the style buffer. */ wrapped_line_counter(deletedTextBuf, 0, length, INT_MAX, true, countFrom, &retPos, &retLines, &retLineStart, &retLineEnd, false); delete deletedTextBuf; *linesDeleted = retLines; mSuppressResync = 0; } /** \brief Wrapping calculations. This is a stripped-down version of the findWrapRange() function above, intended to be used to calculate the number of "deleted" lines during a buffer modification. It is called _before_ the modification takes place. This function should only be called in continuous wrap mode with a non-fixed font width. In that case, it is impossible to calculate the number of deleted lines, because the necessary style information is no longer available _after_ the modification. In other cases, we can still perform the calculation afterwards (possibly even more efficiently). \param pos \param nDeleted */ void Fl_Text_Display::measure_deleted_lines(int pos, int nDeleted) { IS_UTF8_ALIGNED2(buffer(), pos) int retPos, retLines, retLineStart, retLineEnd; Fl_Text_Buffer *buf = buffer(); int nVisLines = mNVisibleLines; int *lineStarts = mLineStarts; int countFrom, lineStart; int nLines = 0, i; /* ** Determine where to begin searching: either the previous newline, or ** if possible, limit to the start of the (original) previous displayed ** line, using information from the existing line starts array */ if (pos >= mFirstChar && pos <= mLastChar) { for (i=nVisLines-1; i>0; i--) if (lineStarts[i] != -1 && pos >= lineStarts[i]) break; if (i > 0) { countFrom = lineStarts[i-1]; } else countFrom = buf->line_start(pos); } else countFrom = buf->line_start(pos); /* ** Move forward through the (new) text one line at a time, counting ** displayed lines, and looking for either a real newline, or for the ** line starts to re-sync with the original line starts array */ lineStart = countFrom; for (;;) { /* advance to the next line. If the line ended in a real newline or the end of the buffer, that's far enough */ wrapped_line_counter(buf, lineStart, buf->length(), 1, true, 0, &retPos, &retLines, &retLineStart, &retLineEnd); if (retPos >= buf->length()) { if (retPos != retLineEnd) nLines++; break; } else lineStart = retPos; nLines++; if (lineStart > pos + nDeleted && buf->char_at(lineStart-1) == '\n') { break; } /* Unlike in the findWrapRange() function above, we don't try to resync with the line starts, because we don't know the length of the inserted text yet, nor the updated style information. Because of that, we also shouldn't resync with the line starts after the modification either, because we must perform the calculations for the deleted and inserted lines in the same way. This can result in some unnecessary recalculation and redrawing overhead, and therefore we should only use this two-phase mode of calculation when it's really needed (continuous wrap + variable font width). */ } mNLinesDeleted = nLines; mSuppressResync = 1; } /** \brief Wrapping calculations. Count forward from startPos to either maxPos or maxLines (whichever is reached first), and return all relevant positions and line count. The provided textBuffer may differ from the actual text buffer of the widget. In that case it must be a (partial) copy of the actual text buffer and the styleBufOffset argument must indicate the starting position of the copy, to take into account the correct style information. \param[in] buf The text buffer to operate on \param[in] startPos Starting index position into the buffer \param[in] maxPos Maximum index position into the buffer we'll reach \param[in] maxLines Maximum number of lines we'll reach \param[in] startPosIsLineStart Flag indicating if startPos is start of line. (If set, prevents our having to find the line start) \param[in] styleBufOffset Offset index position into style buffer. \param[out] retPos Position where counting ended. When counting lines, the position returned is the start of the line "maxLines" lines beyond "startPos". \param[out] retLines Number of line breaks counted \param[out] retLineStart Start of the line where counting ended \param[out] retLineEnd End position of the last line traversed \param[out] countLastLineMissingNewLine */ void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, int maxPos, int maxLines, bool startPosIsLineStart, int styleBufOffset, int *retPos, int *retLines, int *retLineStart, int *retLineEnd, bool countLastLineMissingNewLine) const { IS_UTF8_ALIGNED2(buf, startPos) IS_UTF8_ALIGNED2(buf, maxPos) int lineStart, newLineStart = 0, b, p, colNum, wrapMarginPix; int i, foundBreak; double width; int nLines = 0; unsigned int c; /* Set the wrap margin to the wrap column or the view width */ if (mWrapMarginPix != 0) { wrapMarginPix = mWrapMarginPix; } else { wrapMarginPix = text_area.w; } /* Find the start of the line if the start pos is not marked as a line start. */ if (startPosIsLineStart) lineStart = startPos; else lineStart = line_start(startPos); /* ** Loop until position exceeds maxPos or line count exceeds maxLines. ** (actually, continues beyond maxPos to end of line containing maxPos, ** in case later characters cause a word wrap back before maxPos) */ colNum = 0; width = 0; for (p=lineStart; plength(); p=buf->next_char(p)) { c = buf->char_at(p); // UCS-4 /* If the character was a newline, count the line and start over, otherwise, add it to the width and column counts */ if (c == '\n') { if (p >= maxPos) { *retPos = maxPos; *retLines = nLines; *retLineStart = lineStart; *retLineEnd = maxPos; return; } nLines++; int p1 = buf->next_char(p); if (nLines >= maxLines) { *retPos = p1; *retLines = nLines; *retLineStart = p1; *retLineEnd = p; return; } lineStart = p1; colNum = 0; width = 0; } else { const char *s = buf->address(p); colNum++; // FIXME: it is not a good idea to simply add character widths because on // some platforms, the width is a floating point value and depends on the // previous character as well. width += measure_proportional_character(s, (int)width, p+styleBufOffset); } /* If character exceeded wrap margin, find the break point and wrap there */ if (width > wrapMarginPix) { foundBreak = false; for (b=p; b>=lineStart; b=buf->prev_char(b)) { c = buf->char_at(b); if (c == '\t' || c == ' ') { newLineStart = buf->next_char(b); colNum = 0; width = 0; int iMax = buf->next_char(p); for (i=buf->next_char(b); inext_char(i)) { width += measure_proportional_character(buf->address(i), (int)width, i+styleBufOffset); colNum++; } foundBreak = true; break; } } if (bnext_char(lineStart)); colNum++; if (b >= buf->length()) { // STR #2730 width = 0; } else { const char *s = buf->address(b); width = measure_proportional_character(s, 0, p+styleBufOffset); } } if (p >= maxPos) { *retPos = maxPos; *retLines = maxPos < newLineStart ? nLines : nLines + 1; *retLineStart = maxPos < newLineStart ? lineStart : newLineStart; *retLineEnd = maxPos; return; } nLines++; if (nLines >= maxLines) { *retPos = foundBreak ? buf->next_char(b) : max(p, buf->next_char(lineStart)); *retLines = nLines; *retLineStart = lineStart; *retLineEnd = foundBreak ? b : p; return; } lineStart = newLineStart; } } /* reached end of buffer before reaching pos or line target */ *retPos = buf->length(); *retLines = nLines; if (countLastLineMissingNewLine && colNum > 0) *retLines = buf->next_char(*retLines); *retLineStart = lineStart; *retLineEnd = buf->length(); } /** \brief Wrapping calculations. Measure the width in pixels of the first character of string "s" at a particular column "colNum" and buffer position "pos". This is for measuring characters in proportional or mixed-width highlighting fonts. A note about proportional and mixed-width fonts: the mixed width and proportional font code in nedit does not get much use in general editing, because nedit doesn't allow per-language-mode fonts, and editing programs in a proportional font is usually a bad idea, so very few users would choose a proportional font as a default. There are still probably mixed- width syntax highlighting cases where things don't redraw properly for insertion/deletion, though static display and wrapping and resizing should now be solid because they are now used for online help display. \param s text string \param xPix x pixel position needed for calculating tab widths \param pos offset within string \return width of character in pixels */ double Fl_Text_Display::measure_proportional_character(const char *s, int xPix, int pos) const { IS_UTF8_ALIGNED(s) if (*s=='\t') { int tab = (int)col_to_x(mBuffer->tab_distance()); return (((xPix/tab)+1)*tab) - xPix; } int charLen = fl_utf8len1(*s), style = 0; if (mStyleBuffer) { style = mStyleBuffer->byte_at(pos); } return string_width(s, charLen, style); } /** \brief Finds both the end of the current line and the start of the next line. Why? In continuous wrap mode, if you need to know both, figuring out one from the other can be expensive or error prone. The problem comes when there's a trailing space or tab just before the end of the buffer. To translate an end of line value to or from the next lines start value, you need to know whether the trailing space or tab is being used as a line break or just a normal character, and to find that out would otherwise require counting all the way back to the beginning of the line. \param startPos \param startPosIsLineStart \param[out] lineEnd \param[out] nextLineStart */ void Fl_Text_Display::find_line_end(int startPos, bool startPosIsLineStart, int *lineEnd, int *nextLineStart) const { IS_UTF8_ALIGNED2(buffer(), startPos) int retLines, retLineStart; /* if we're not wrapping use more efficient Fl_Text_Buffer::line_end() */ if (!mContinuousWrap) { int le = buffer()->line_end(startPos); int ls = buffer()->next_char(le); *lineEnd = le; *nextLineStart = min(buffer()->length(), ls); return; } /* use the wrapped line counter routine to count forward one line */ wrapped_line_counter(buffer(), startPos, buffer()->length(), 1, startPosIsLineStart, 0, nextLineStart, &retLines, &retLineStart, lineEnd); } /** \brief Check if the line break is caused by a newline or by line wrapping. Line breaks in continuous wrap mode usually happen at newlines (\\n) or whitespace. This line-terminating character is not included in line width measurements and has a special status as a non-visible character. However, lines with no whitespace are wrapped without the benefit of a line terminating character, and this distinction causes endless trouble with all of the text display code which was originally written without continuous wrap mode and always expects to wrap at a newline character. Given the position of the end of the line, as returned by Fl_Text_Display::line_end() or Fl_Text_Buffer::line_end(), this returns true if there is a line terminating character, and false if there's not. On the last character in the buffer, this function can't tell for certain whether a trailing space was used as a wrap point, and just guesses that it wasn't. So if an exact accounting is necessary, don't use this function. \param lineEndPos index of character where the line wraps \return 1 if a \\n character causes the line wrap */ int Fl_Text_Display::wrap_uses_character(int lineEndPos) const { IS_UTF8_ALIGNED2(buffer(), lineEndPos) unsigned int c; if (!mContinuousWrap || lineEndPos == buffer()->length()) return 1; c = buffer()->char_at(lineEndPos); return c == '\n' || ((c == '\t' || c == ' ') && lineEndPos + 1 < buffer()->length()); } /** \brief I don't know what this does! Extend the range of a redraw request (from *start to *end) with additional redraw requests resulting from changes to the attached style buffer (which contains auxiliary information for coloring or styling text). \param startpos ?? \param endpos ?? \todo Unicode? */ void Fl_Text_Display::extend_range_for_styles( int *startpos, int *endpos ) { IS_UTF8_ALIGNED2(buffer(), (*startpos)) IS_UTF8_ALIGNED2(buffer(), (*endpos)) Fl_Text_Selection * sel = mStyleBuffer->primary_selection(); int extended = 0; /* The peculiar protocol used here is that modifications to the style buffer are marked by selecting them with the buffer's primary Fl_Text_Selection. The style buffer is usually modified in response to a modify callback on the text buffer BEFORE Fl_Text_Display.c's modify callback, so that it can keep the style buffer in step with the text buffer. The style-update callback can't just call for a redraw, because Fl_Text_Display hasn't processed the original text changes yet. Anyhow, to minimize redrawing and to avoid the complexity of scheduling redraws later, this simple protocol tells the text display's buffer modify callback to extend its redraw range to show the text color/and font changes as well. */ if ( sel->selected() ) { if ( sel->start() < *startpos ) { *startpos = sel->start(); // somewhere while deleting, alignment is lost. We do this just to be sure. *startpos = buffer()->utf8_align(*startpos); IS_UTF8_ALIGNED2(buffer(), (*startpos)) extended = 1; } if ( sel->end() > *endpos ) { *endpos = sel->end(); *endpos = buffer()->utf8_align(*endpos); IS_UTF8_ALIGNED2(buffer(), (*endpos)) extended = 1; } } /* If the Fl_Text_Selection was extended due to a style change, and some of the fonts don't match in spacing, extend redraw area to end of line to redraw characters exposed by possible font size changes */ if ( extended ) *endpos = mBuffer->line_end( *endpos ) + 1; IS_UTF8_ALIGNED2(buffer(), (*endpos)) } /** \brief Draw the widget. This function tries to limit drawing to smaller areas if possible. */ void Fl_Text_Display::draw(void) { // don't even try if there is no associated text buffer! if (!buffer()) { draw_box(); return; } // recalc if needed -- issue #300 if (display_needs_recalc_ || (damage() & FL_DAMAGE_ALL)) { display_needs_recalc_ = false; recalc_display(); } fl_push_clip(x(),y(),w(),h()); // prevent drawing outside widget area // background color -- change if inactive Fl_Color bgcolor = active_r() ? color() : fl_inactive(color()); // draw the non-text, non-scrollbar areas. if (damage() & FL_DAMAGE_ALL) { recalc_display(); // printf("drawing all (box = %d)\n", box()); if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // if to printer, draw the background fl_rectf(text_area.x, text_area.y, text_area.w, text_area.h, bgcolor); } // draw the box() draw_box(box(), x(), y(), w(), h(), bgcolor); // left margin fl_rectf(text_area.x-LEFT_MARGIN, text_area.y-TOP_MARGIN, LEFT_MARGIN, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, bgcolor); // right margin fl_rectf(text_area.x+text_area.w, text_area.y-TOP_MARGIN, RIGHT_MARGIN, text_area.h+TOP_MARGIN+BOTTOM_MARGIN, bgcolor); // top margin fl_rectf(text_area.x, text_area.y-TOP_MARGIN, text_area.w, TOP_MARGIN, bgcolor); // bottom margin fl_rectf(text_area.x, text_area.y+text_area.h, text_area.w, BOTTOM_MARGIN, bgcolor); // draw that little box in the corner of the scrollbars if (mVScrollBar->visible() && mHScrollBar->visible()) fl_rectf(mVScrollBar->x(), mHScrollBar->y(), mVScrollBar->w(), mHScrollBar->h(), FL_BACKGROUND_COLOR); } else if (damage() & (FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)) { // printf("blanking previous cursor extrusions at Y: %d\n", mCursorOldY); // CET - FIXME - save old cursor position instead and just draw side needed? fl_push_clip(text_area.x-LEFT_MARGIN, text_area.y, text_area.w+LEFT_MARGIN+RIGHT_MARGIN, text_area.h); fl_rectf(text_area.x-LEFT_MARGIN, mCursorOldY, LEFT_MARGIN, mMaxsize, bgcolor); fl_rectf(text_area.x+text_area.w, mCursorOldY, RIGHT_MARGIN, mMaxsize, bgcolor); fl_pop_clip(); } // draw the scrollbars if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_CHILD)) { mVScrollBar->damage(FL_DAMAGE_ALL); mHScrollBar->damage(FL_DAMAGE_ALL); } update_child(*mVScrollBar); update_child(*mHScrollBar); // draw all of the text if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_EXPOSE)) { //printf("drawing all text\n"); int X = 0, Y = 0, W = 0, H = 0; if (fl_clip_box(text_area.x, text_area.y, text_area.w, text_area.h, X, Y, W, H)) { // Draw text using the intersected clipping box... // (this sets the clipping internally) draw_text(X, Y, W, H); } else { // Draw the whole area... draw_text(text_area.x, text_area.y, text_area.w, text_area.h); } } else if (damage() & FL_DAMAGE_SCROLL) { // draw some lines of text fl_push_clip(text_area.x, text_area.y, text_area.w, text_area.h); //printf("drawing text from %d to %d\n", damage_range1_start, damage_range1_end); draw_range(damage_range1_start, damage_range1_end); if (damage_range2_end != -1) { //printf("drawing text from %d to %d\n", damage_range2_start, damage_range2_end); draw_range(damage_range2_start, damage_range2_end); } damage_range1_start = damage_range1_end = -1; damage_range2_start = damage_range2_end = -1; fl_pop_clip(); } // draw the text cursor int start, end; int has_selection = buffer()->selection_position(&start, &end); if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE) && ( (Fl::screen_driver()->has_marked_text() && Fl::compose_state) || (!has_selection) || mCursorPos < start || mCursorPos > end) && mCursorOn && Fl::focus() == (Fl_Widget*)this ) { fl_push_clip(text_area.x-LEFT_MARGIN, text_area.y, text_area.w+LEFT_MARGIN+RIGHT_MARGIN, text_area.h); int X = 0, Y = 0; if (position_to_xy(mCursorPos, &X, &Y)) { draw_cursor(X, Y); mCursorOldY = Y; } // else puts("position_to_xy() failed - unable to draw cursor!"); //printf("drew cursor at pos: %d (%d,%d)\n", mCursorPos, X, Y); fl_pop_clip(); } // Important to do this at end of this method, otherwise line numbers // will not scroll with the text edit area draw_line_numbers(true); fl_pop_clip(); } // GitHub Issue #196: internal selection and visible selection can run out of // sync, giving the user unexpected keyboard selection. The code block below // captures that and fixes it. // - set pos to the drag target postion or -1 if we don't know // - if pos is -1, and key is not -1, key can be set to indicate a direction // (e.g. FL_Left) // return 0 if nothing changed, return 1 if dragPos or mCursorPos were modified int fl_text_drag_prepare(int pos, int key, Fl_Text_Display* d) { if (d->buffer()->selected()) { int start, end; d->buffer()->selection_position(&start, &end); if ( (d->dragPos!=start || d->mCursorPos!=end) && (d->dragPos!=end || d->mCursorPos!=start) ) { if (pos!=-1) { if (posmCursorPos = start; d->dragPos = end; } else { d->mCursorPos = end; d->dragPos = start; } } else if (key!=-1) { switch (key) { case FL_Home: case FL_Left: case FL_Up: case FL_Page_Up: d->dragPos = end; d->mCursorPos = start; break; default: d->dragPos = start; d->mCursorPos = end; break; } } else { d->dragPos = start; d->mCursorPos = end; } return 1; } } return 0; } // this processes drag events due to mouse for Fl_Text_Display and // also drags due to cursor movement with shift held down for // Fl_Text_Editor void fl_text_drag_me(int pos, Fl_Text_Display* d) { if (d->dragType == Fl_Text_Display::DRAG_CHAR) { if (pos >= d->dragPos) { d->buffer()->select(d->dragPos, pos); } else { d->buffer()->select(pos, d->dragPos); } d->insert_position(pos); } else if (d->dragType == Fl_Text_Display::DRAG_WORD) { if (pos >= d->dragPos) { d->insert_position(d->word_end(pos)); d->buffer()->select(d->word_start(d->dragPos), d->word_end(pos)); } else { d->insert_position(d->word_start(pos)); d->buffer()->select(d->word_start(pos), d->word_end(d->dragPos)); } } else if (d->dragType == Fl_Text_Display::DRAG_LINE) { if (pos >= d->dragPos) { d->insert_position(d->buffer()->line_end(pos)+1); d->buffer()->select(d->buffer()->line_start(d->dragPos), d->buffer()->line_end(pos)+1); } else { d->insert_position(d->buffer()->line_start(pos)); d->buffer()->select(d->buffer()->line_start(pos), d->buffer()->line_end(d->dragPos)+1); } } } /** \brief Timer callback for scroll events. This timer event scrolls the text view proportionally to how far the mouse pointer has left the text area. This allows for smooth scrolling without "wiggeling" the mouse. */ void Fl_Text_Display::scroll_timer_cb(void *user_data) { Fl_Text_Display *w = (Fl_Text_Display*)user_data; int pos; switch (scroll_direction) { case 1: // mouse is to the right, scroll left w->scroll(w->mTopLineNum, w->mHorizOffset + scroll_amount); pos = w->xy_to_position(w->text_area.x + w->text_area.w, scroll_y, CURSOR_POS); break; case 2: // mouse is to the left, scroll right w->scroll(w->mTopLineNum, w->mHorizOffset + scroll_amount); pos = w->xy_to_position(w->text_area.x, scroll_y, CURSOR_POS); break; case 3: // mouse is above, scroll down w->scroll(w->mTopLineNum + scroll_amount, w->mHorizOffset); pos = w->xy_to_position(scroll_x, w->text_area.y, CURSOR_POS); break; case 4: // mouse is below, scroll up w->scroll(w->mTopLineNum + scroll_amount, w->mHorizOffset); pos = w->xy_to_position(scroll_x, w->text_area.y + w->text_area.h, CURSOR_POS); break; default: return; } fl_text_drag_me(pos, w); Fl::repeat_timeout(.1, scroll_timer_cb, user_data); } /** Handle right mouse button down events. \return 0 for no op, 1 to cut, 2 to copy, 3 to paste */ int Fl_Text_Display::handle_rmb(int readonly) { Fl_Text_Buffer *txtbuf = buffer(); int newpos = xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS); int oldpos = txtbuf->primary_selection()->start(); int oldmark = txtbuf->primary_selection()->end(); if ( ((oldpos < newpos) && (oldmark > newpos)) || ((oldmark < newpos) && (oldpos > newpos)) || (type() == FL_SECRET_INPUT)) { // if the user clicked inside an existing selection, keep // the selection } else { if ((txtbuf->char_at(newpos) == 0) || (txtbuf->char_at(newpos) == '\n')) { // if clicked to the right of the line or text end, clear the // selection and set the cursor at the end of the line txtbuf->select(newpos, newpos); } else { // if clicked on a word, select the entire word txtbuf->select(txtbuf->word_start(newpos), txtbuf->word_end(newpos)); } } // keep the menu labels current rmb_menu[0].label(Fl_Input::cut_menu_text); rmb_menu[1].label(Fl_Input::copy_menu_text); rmb_menu[2].label(Fl_Input::paste_menu_text); // give only the menu options that make sense if (readonly) { rmb_menu[0].deactivate(); // cut rmb_menu[2].deactivate(); // paste } else { rmb_menu[0].activate(); // cut rmb_menu[2].activate(); // paste } // pop up the menu fl_cursor(FL_CURSOR_DEFAULT); const Fl_Menu_Item *mi = rmb_menu->popup(Fl::event_x(), Fl::event_y()); if (mi) return (int)mi->argument(); return 0; } /** \brief Event handling. */ int Fl_Text_Display::handle(int event) { if (!buffer()) return 0; // This isn't very elegant! if (!Fl::event_inside(text_area.x, text_area.y, text_area.w, text_area.h) && !dragging && event != FL_LEAVE && event != FL_ENTER && event != FL_MOVE && event != FL_FOCUS && event != FL_UNFOCUS && event != FL_KEYBOARD && event != FL_KEYUP && event != FL_MOUSEWHEEL) { return Fl_Group::handle(event); } switch (event) { case FL_ENTER: case FL_MOVE: if (active_r()) { if (Fl::event_inside(text_area.x, text_area.y, text_area.w, text_area.h)) window()->cursor(FL_CURSOR_INSERT); else window()->cursor(FL_CURSOR_DEFAULT); return 1; } else { return 0; } case FL_LEAVE: case FL_HIDE: if (active_r() && window()) { window()->cursor(FL_CURSOR_DEFAULT); return 1; } else { return 0; } case FL_PUSH: { if (active_r() && window()) { if (Fl::event_inside(text_area.x, text_area.y, text_area.w, text_area.h)) window()->cursor(FL_CURSOR_INSERT); else window()->cursor(FL_CURSOR_DEFAULT); } if (Fl::focus() != this) { Fl::focus(this); handle(FL_FOCUS); } if (Fl_Group::handle(event)) return 1; if (Fl::event_button() == FL_RIGHT_MOUSE) { switch (handle_rmb(1)) { case 2: { if (!buffer()->selected()) break; const char *copy = buffer()->selection_text(); if (*copy) Fl::copy(copy, (int) strlen(copy), 1); free((void*)copy); show_insert_position(); break; } } return 1; } if (Fl::event_state()&FL_SHIFT) { if (buffer()->primary_selection()->selected()) { int pos = xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS); fl_text_drag_prepare(pos, -1, this); } else { dragPos = insert_position(); } return handle(FL_DRAG); } dragging = 1; int pos = xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS); dragPos = pos; if (buffer()->primary_selection()->includes(pos)) { dragType = DRAG_START_DND; return 1; } dragType = Fl::event_clicks(); if (dragType == DRAG_CHAR) { buffer()->unselect(); // Fl::copy("", 0, 0); /* removed for STR 2668 */ } else if (dragType == DRAG_WORD) { buffer()->select(word_start(pos), word_end(pos)); dragPos = word_start(pos); } if (buffer()->primary_selection()->selected()) insert_position(buffer()->primary_selection()->end()); else insert_position(pos); show_insert_position(); return 1; } case FL_DRAG: { if (dragType==DRAG_NONE) return 1; if (dragType==DRAG_START_DND) { if (!Fl::event_is_click() && Fl::dnd_text_ops()) { const char* copy = buffer()->selection_text(); Fl::copy(copy, (int)strlen(copy)); Fl::screen_driver()->dnd(1); free((void*)copy); } return 1; } int X = Fl::event_x(), Y = Fl::event_y(), pos = insert_position(); // if we leave the text_area, we start a timer event // that will take care of scrolling and selecting if (Y < text_area.y) { scroll_x = X; scroll_amount = (Y - text_area.y) / 5 - 1; if (!scroll_direction) { Fl::add_timeout(.01, scroll_timer_cb, this); } scroll_direction = 3; } else if (Y >= text_area.y+text_area.h) { scroll_x = X; scroll_amount = (Y - text_area.y - text_area.h) / 5 + 1; if (!scroll_direction) { Fl::add_timeout(.01, scroll_timer_cb, this); } scroll_direction = 4; } else if (X < text_area.x) { scroll_y = Y; scroll_amount = (X - text_area.x) / 2 - 1; if (!scroll_direction) { Fl::add_timeout(.01, scroll_timer_cb, this); } scroll_direction = 2; } else if (X >= text_area.x+text_area.w) { scroll_y = Y; scroll_amount = (X - text_area.x - text_area.w) / 2 + 1; if (!scroll_direction) { Fl::add_timeout(.01, scroll_timer_cb, this); } scroll_direction = 1; } else { if (scroll_direction) { Fl::remove_timeout(scroll_timer_cb, this); scroll_direction = 0; } pos = xy_to_position(X, Y, CURSOR_POS); } fl_text_drag_me(pos, this); return 1; } case FL_RELEASE: { if (Fl::event_is_click() && (! Fl::event_clicks()) && buffer()->primary_selection()->includes(dragPos) && !(Fl::event_state()&FL_SHIFT) ) { buffer()->unselect(); // clicking in the selection: unselect and move cursor insert_position(dragPos); dragType = DRAG_CHAR; return 1; } else if (Fl::event_clicks() == DRAG_LINE && Fl::event_button() == FL_LEFT_MOUSE) { buffer()->select(buffer()->line_start(dragPos), buffer()->next_char(buffer()->line_end(dragPos))); dragPos = line_start(dragPos); dragType = DRAG_CHAR; } else { dragging = 0; if (scroll_direction) { Fl::remove_timeout(scroll_timer_cb, this); scroll_direction = 0; } // convert from WORD or LINE selection to CHAR /*if (insert_position() >= dragPos) dragPos = buffer()->primary_selection()->start(); else dragPos = buffer()->primary_selection()->end();*/ dragType = DRAG_CHAR; } const char* copy = buffer()->selection_text(); if (*copy) Fl::copy(copy, (int) strlen(copy), 0); free((void*)copy); return 1; } case FL_MOUSEWHEEL: if (Fl::e_dy && mVScrollBar->visible()) { // Issue #879 Fl_Scrollbar *vs = mVScrollBar; if ((Fl::e_dy < 0) && (vs->value() == int(vs->minimum()))) return 0; // hit top? ignore if ((Fl::e_dy > 0) && (vs->value() == int(vs->maximum()))) return 0; // hit bot? ignore return vs->handle(event); } else if (Fl::e_dx && mHScrollBar->visible()) { // Issue #879 Fl_Scrollbar *hs = mHScrollBar; if ((Fl::e_dx < 0) && (hs->value() == int(hs->minimum()))) return 0; // hit left? ignore if ((Fl::e_dx > 0) && (hs->value() == int(hs->maximum()))) return 0; // hit right? ignore return hs->handle(event); } return 0; case FL_UNFOCUS: if (active_r() && window()) window()->cursor(FL_CURSOR_DEFAULT); case FL_FOCUS: if (buffer()->selected()) { int start, end; if (buffer()->selection_position(&start, &end)) redisplay_range(start, end); } if (buffer()->secondary_selected()) { int start, end; if (buffer()->secondary_selection_position(&start, &end)) redisplay_range(start, end); } if (buffer()->highlight()) { int start, end; if (buffer()->highlight_position(&start, &end)) redisplay_range(start, end); } return 1; case FL_KEYBOARD: // Copy? if ((Fl::event_state()&(FL_CTRL|FL_COMMAND)) && Fl::event_key()=='c') { if (!buffer()->selected()) return 1; const char *copy = buffer()->selection_text(); if (*copy) Fl::copy(copy, (int) strlen(copy), 1); free((void*)copy); return 1; } // Select all ? if ((Fl::event_state()&(FL_CTRL|FL_COMMAND)) && Fl::event_key()=='a') { buffer()->select(0,buffer()->length()); const char *copy = buffer()->selection_text(); if (*copy) Fl::copy(copy, (int) strlen(copy), 0); free((void*)copy); return 1; } if (mVScrollBar->handle(event)) return 1; if (mHScrollBar->handle(event)) return 1; break; case FL_SHORTCUT: if (!(shortcut() ? Fl::test_shortcut(shortcut()) : test_shortcut())) return 0; if (Fl::visible_focus() && handle(FL_FOCUS)) { Fl::focus(this); return 1; } break; } return 0; } /* Convert an x pixel position into a column number. The width of a column is calculated as the average width of a few representative characters, giving a good estimate for proportional fonts. This method does not take the possition of the scroll bars into account. \param[in] x offset to the left edge of the text in FLTK units. \return approximation to the corresponding text column \see col_to_x() */ double Fl_Text_Display::x_to_col(double x) const { if (!mColumnScale) { mColumnScale = string_width("Mitg", 4, 'A') / 4.0; } return (x/mColumnScale)+0.5; } /** Convert a column number into an x pixel position. \see x_to_col() */ double Fl_Text_Display::col_to_x(double col) const { if (!mColumnScale) { // recalculate column scale value x_to_col(0); } return col*mColumnScale; } fltk-1.4.3/src/Fl_Window.cxx0000644000175000017500000010462315004135251016016 0ustar albrechtalbrecht// // Window widget class for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // The Fl_Window is a window in the fltk library. // This is the system-independent portions. The huge amount of // crap you need to do to communicate with X is in Fl_x.cxx, the // equivalent (but totally different) crap for Windows is in Fl_win32.cxx #include #include #include #include "Fl_Window_Driver.H" #include "Fl_Screen_Driver.H" #include #include #include #include #include #include #include "flstring.h" char *Fl_Window::default_xclass_ = 0L; char Fl_Window::show_next_window_iconic_ = 0; Fl_Window *Fl_Window::current_; void Fl_Window::_Fl_Window() { cursor_default = FL_CURSOR_DEFAULT; type(FL_WINDOW); box(FL_FLAT_BOX); if (Fl::scheme_bg_) { labeltype(FL_NORMAL_LABEL); align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); image(Fl::scheme_bg_); } else { labeltype(FL_NO_LABEL); } flx_ = 0; xclass_ = 0; iconlabel_ = 0; resizable(0); size_range_set_ = 0; minw_ = maxw_ = minh_ = maxh_ = 0; no_fullscreen_x = 0; no_fullscreen_y = 0; no_fullscreen_w = w(); no_fullscreen_h = h(); fullscreen_screen_top = -1; fullscreen_screen_bottom = -1; fullscreen_screen_left = -1; fullscreen_screen_right = -1; callback((Fl_Callback*)default_callback); } Fl_Window::Fl_Window(int X,int Y,int W, int H, const char *l) : Fl_Group(X, Y, W, H, l) { pWindowDriver = Fl_Window_Driver::newWindowDriver(this); _Fl_Window(); set_flag(FORCE_POSITION); if (!parent()) clear_visible(); } Fl_Window::Fl_Window(int W, int H, const char *l) : // fix common user error of a missing end() with current(0): Fl_Group((Fl_Group::current(0),0), 0, W, H, l) { pWindowDriver = Fl_Window_Driver::newWindowDriver(this); _Fl_Window(); clear_visible(); } Fl_Window::~Fl_Window() { hide(); if (xclass_) { free(xclass_); } free_icons(); delete pWindowDriver; } /** Returns a pointer to the nearest parent window up the widget hierarchy. This will return sub-windows if there are any, or the parent window if there's no sub-windows. If this widget IS the top-level window, NULL is returned. \retval NULL if no window is associated with this widget. \note for an Fl_Window widget, this returns its parent window (if any), not this window. \see top_window() */ Fl_Window *Fl_Widget::window() const { for (Fl_Widget *o = parent(); o; o = o->parent()) if (o->type() >= FL_WINDOW) return (Fl_Window*)o; return 0; } /** Returns a pointer to the top-level window for the widget. In other words, the 'window manager window' that contains this widget. This method differs from window() in that it won't return sub-windows (if there are any). \returns the top-level window, or NULL if no top-level window is associated with this widget. \see window() */ Fl_Window *Fl_Widget::top_window() const { const Fl_Widget *w = this; while (w->parent()) { w = w->parent(); } // walk up the widget hierarchy to top-level item return const_cast(w)->as_window(); // return if window, or NULL if not } /** Finds the x/y offset of the current widget relative to the top-level window. \param[out] xoff,yoff Returns the x/y offset \returns the top-level window (or NULL for a widget that's not in any window) */ Fl_Window* Fl_Widget::top_window_offset(int& xoff, int& yoff) const { xoff = yoff = 0; const Fl_Widget *w = this; while (w && w->window()) { xoff += w->x(); // accumulate offsets yoff += w->y(); w = w->window(); // walk up window hierarchy } return w ? const_cast(w)->as_window() : NULL; } /** Gets the x position of the window on the screen */ int Fl_Window::x_root() const { Fl_Window *p = window(); if (p) return p->x_root() + x(); return x(); } /** Gets the y position of the window on the screen */ int Fl_Window::y_root() const { Fl_Window *p = window(); if (p) return p->y_root() + y(); return y(); } void Fl_Window::label(const char *name) { label(name, iconlabel()); // platform dependent } /** Sets the window titlebar label to a copy of a character string */ void Fl_Window::copy_label(const char *a) { Fl_Widget::copy_label(a); label(label(), iconlabel()); // platform dependent } void Fl_Window::iconlabel(const char *iname) { label(label(), iname); // platform dependent } // the Fl::atclose pointer is provided for back compatibility. You // can now just change the callback for the window instead. /** Default callback for window widgets. It hides the window and then calls the default widget callback. */ void Fl::default_atclose(Fl_Window* window, void* v) { window->hide(); Fl_Widget::default_callback(window, v); // put on Fl::read_queue() } /** Back compatibility: default window callback handler \see Fl::set_atclose() */ void (*Fl::atclose)(Fl_Window*, void*) = default_atclose; /** Back compatibility: Sets the default callback v for win to call on close event */ void Fl_Window::default_callback(Fl_Window* win, void* v) { Fl::atclose(win, v); } /** Returns the last window that was made current. \see Fl_Window::make_current() */ Fl_Window *Fl_Window::current() { return current_; } /** Returns the default xclass. \see Fl_Window::default_xclass(const char *) */ const char *Fl_Window::default_xclass() { if (default_xclass_) { return default_xclass_; } else { return "FLTK"; } } /** Sets the default window xclass. The default xclass is used for all windows that don't have their own xclass set before show() is called. You can change the default xclass whenever you want, but this only affects windows that are created (and shown) after this call. The given string \p xc is copied. You can use a local variable or free the string immediately after this call. If you don't call this, the default xclass for all windows will be "FLTK". You can reset the default xclass by specifying NULL for \p xc. If you call Fl_Window::xclass(const char *) for any window, then this also sets the default xclass, unless it has been set before. \param[in] xc default xclass for all windows subsequently created \see Fl_Window::xclass(const char *) */ void Fl_Window::default_xclass(const char *xc) { if (default_xclass_) { free(default_xclass_); default_xclass_ = 0L; } if (xc) { default_xclass_ = fl_strdup(xc); } } /** Sets the xclass for this window. A string used to tell the system what type of window this is. Mostly this identifies the picture to draw in the icon. This only works if called \e before calling show(). Under X, this is turned into a XA_WM_CLASS pair by truncating at the first non-alphanumeric character and capitalizing the first character, and the second one if the first is 'x'. Thus "foo" turns into "foo, Foo", and "xprog.1" turns into "xprog, XProg". Under Microsoft Windows, this string is used as the name of the WNDCLASS structure, though it is not clear if this can have any visible effect. \since FLTK 1.3 the passed string is copied. You can use a local variable or free the string immediately after this call. Note that FLTK 1.1 stores the \e pointer without copying the string. If the default xclass has not yet been set, this also sets the default xclass for all windows created subsequently. \see Fl_Window::default_xclass(const char *) */ void Fl_Window::xclass(const char *xc) { if (xclass_) { free(xclass_); xclass_ = 0L; } if (xc) { xclass_ = fl_strdup(xc); if (!default_xclass_) { default_xclass(xc); } } } /** Returns the xclass for this window, or a default. \see Fl_Window::default_xclass(const char *) \see Fl_Window::xclass(const char *) */ const char *Fl_Window::xclass() const { if (xclass_) { return xclass_; } else { return default_xclass(); } } /** Sets a single default window icon. If \p icon is NULL the current default icons are removed. \param[in] icon default icon for all windows subsequently created or NULL \see Fl_Window::default_icons(const Fl_RGB_Image *[], int) \see Fl_Window::icon(const Fl_RGB_Image *) \see Fl_Window::icons(const Fl_RGB_Image *[], int) \note See \ref osissues_wayland_window_icon for the Wayland platform. */ void Fl_Window::default_icon(const Fl_RGB_Image *icon) { if (icon) default_icons(&icon, 1); else default_icons(&icon, 0); } /** Sets the default window icons. The default icons are used for all windows that don't have their own icons set before show() is called. You can change the default icons whenever you want, but this only affects windows that are created (and shown) after this call. The given images in \p icons are copied. You can use a local variable or free the images immediately after this call. \param[in] icons default icons for all windows subsequently created \param[in] count number of images in \p icons. Set to 0 to remove the current default icons \see Fl_Window::default_icon(const Fl_RGB_Image *) \see Fl_Window::icon(const Fl_RGB_Image *) \see Fl_Window::icons(const Fl_RGB_Image *[], int) \note See \ref osissues_wayland_window_icon for the Wayland platform. */ void Fl_Window::default_icons(const Fl_RGB_Image *icons[], int count) { Fl::screen_driver()->open_display(); Fl::screen_driver()->default_icons(icons, count); } /** Sets or resets a single window icon. A window icon \e can be changed while the window is shown, but this \e may be platform and/or window manager dependent. To be sure that the window displays the correct window icon you should always set the icon before the window is shown. If a window icon has not been set for a particular window, then the default window icon (see links below) or the system default icon will be used. This method makes an internal copy of the \p icon pixel buffer, so once set, the Fl_RGB_Image instance can be freed by the caller. \param[in] icon icon for this window, NULL to reset window icon. \see Fl_Window::default_icon(const Fl_RGB_Image *) \see Fl_Window::default_icons(const Fl_RGB_Image *[], int) \see Fl_Window::icons(const Fl_RGB_Image *[], int) \note See \ref osissues_wayland_window_icon for the Wayland platform. */ void Fl_Window::icon(const Fl_RGB_Image *icon) { if (icon) icons(&icon, 1); else icons(&icon, 0); } /** Sets the window icons. You may set multiple window icons with different sizes. Dependent on the platform and system settings the best (or the first) icon will be chosen. The given images in \p icons are copied. You can use a local variable or free the images immediately after this call. If \p count is zero, current icons are removed. If \p count is greater than zero (must not be negative), then \p icons[] must contain at least \p count valid image pointers (not NULL). Otherwise the behavior is undefined. \param[in] icons icons for this window \param[in] count number of images in \p icons. Set to 0 to remove the current icons \see Fl_Window::default_icon(const Fl_RGB_Image *) \see Fl_Window::default_icons(const Fl_RGB_Image *[], int) \see Fl_Window::icon(const Fl_RGB_Image *) \note See \ref osissues_wayland_window_icon for the Wayland platform. */ void Fl_Window::icons(const Fl_RGB_Image *icons[], int count) { pWindowDriver->icons(icons, count); } /** Gets the current icon window target dependent data. \deprecated in 1.3.3 */ const void *Fl_Window::icon() const { return pWindowDriver->icon(); } /** Platform-specific method to set the window icon usable on Windows and X11 only. See \ref osissues_x_icon for its use under X11, and \ref osissues_icon_windows under Windows. \deprecated in 1.3.3 in favor of platform-independent methods Fl_Window::icon(const Fl_RGB_Image *icon) and Fl_Window::icons(const Fl_RGB_Image *icons[], int count). */ void Fl_Window::icon(const void * ic) { pWindowDriver->icon(ic); } /** Deletes all icons previously attached to the window. \see Fl_Window::icons(const Fl_RGB_Image *icons[], int count) */ void Fl_Window::free_icons() { pWindowDriver->free_icons(); } /** Waits for the window to be displayed after calling show(). Fl_Window::show() is not guaranteed to show and draw the window on all platforms immediately. Instead this is done in the background; particularly on X11 it will take a few messages (client server roundtrips) to display the window. Usually this small delay doesn't matter, but in some cases you may want to have the window instantiated and displayed synchronously. Currently (as of FLTK 1.3.4) this method has an effect on X11 and Mac OS. On Windows, show() is always synchronous. The effect of show() varies with versions of Mac OS X: early versions have the window appear on the screen when show() returns, later versions don't. If you want to write portable code and need this synchronous show() feature, add win->wait_for_expose() on all platforms, and FLTK will just do the right thing. This method can be used for displaying splash screens before calling Fl::run() or for having exact control over which window has the focus after calling show(). If the window is not shown(), this method does nothing. \note Depending on the platform and window manager wait_for_expose() may not guarantee that the window is fully drawn when it is called. Under X11 it may only make sure that the window is \b mapped, i.e. the internal (OS dependent) window object was created (and maybe shown on the desktop as an empty frame or something like that). You may need to call Fl::flush() after wait_for_expose() to make sure the window and all its widgets are drawn and thus visible. \note FLTK does the best it can do to make sure that all widgets get drawn if you call wait_for_expose() and Fl::flush(). However, dependent on the window manager it can not be guaranteed that this does always happen synchronously. The only guaranteed behavior that all widgets are eventually drawn is if the FLTK event loop is run continuously, for instance with Fl::run(). \see virtual void Fl_Window::show() Example code for displaying a window before calling Fl::run() \code Fl_Double_Window win = new Fl_Double_Window(...); // do more window initialization here ... win->show(); // show window win->wait_for_expose(); // wait, until displayed Fl::flush(); // make sure everything gets drawn // do more initialization work that needs some time here ... Fl::run(); // start FLTK event loop \endcode Note that the window will not be responsive until the event loop is started with Fl::run(). */ void Fl_Window::wait_for_expose() { pWindowDriver->wait_for_expose(); } int Fl_Window::decorated_w() const { return pWindowDriver->decorated_w(); } int Fl_Window::decorated_h() const { return pWindowDriver->decorated_h(); } void Fl_Window::flush() { if (!shown()) return; make_current(); fl_clip_region(flx_->region); flx_->region = 0; draw(); } void Fl_Window::draw() { Fl_Window *save_current = current_; bool to_display = Fl_Display_Device::display_device()->is_current(); if (!to_display) current_ = this; // so drawing of background Fl_Tiled_Image is correct pWindowDriver->draw_begin(); // The following is similar to Fl_Group::draw(), but ... // // - draws the box at (0,0), i.e. with x=0 and y=0 instead of x() and y() // - does NOT draw the label (text) // - draws the image only if FL_ALIGN_INSIDE is set // // Note: The label (text) of top level windows is drawn in the title bar. // Other windows do not draw their labels at all, unless drawn by their // parent widgets or by special draw() methods (derived classes). if (damage() & ~FL_DAMAGE_CHILD) { // draw the entire thing draw_box(box(),0,0,w(),h(),color()); // draw box with x/y = 0 draw_backdrop(); } draw_children(); pWindowDriver->draw_end(); if (!to_display) current_ = save_current; } /** Draw the background image if one is set and is aligned inside. */ void Fl_Window::draw_backdrop() { if (image() && (align() & FL_ALIGN_INSIDE)) { // draw the image only Fl_Label l1; memset(&l1,0,sizeof(l1)); l1.align_ = align(); l1.image = image(); if (!active_r() && l1.image && l1.deimage) l1.image = l1.deimage; l1.type = labeltype(); l1.h_margin_ = l1.v_margin_ = l1.spacing = 0; l1.draw(0,0,w(),h(),align()); } } void Fl_Window::make_current() { pWindowDriver->make_current(); current_ = this; } void Fl_Window::label(const char *name, const char *mininame) { Fl_Widget::label(name); iconlabel_ = mininame; pWindowDriver->label(name, mininame); } void Fl_Window::show() { image(Fl::scheme_bg_); if (Fl::scheme_bg_) { labeltype(FL_NORMAL_LABEL); align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); } else { labeltype(FL_NO_LABEL); } Fl_Tooltip::exit(this); if (!shown()) default_size_range(); pWindowDriver->show(); } void Fl_Window::resize(int X,int Y,int W,int H) { pWindowDriver->resize(X, Y, W, H); } void Fl_Window::hide() { pWindowDriver->hide(); } // FL_SHOW and FL_HIDE are called whenever the visibility of this widget // or any parent changes. We must correctly map/unmap the system's window. // For top-level windows it is assumed the window has already been // mapped or unmapped!!! This is because this should only happen when // Fl_Window::show() or Fl_Window::hide() is called, or in response to // iconize/deiconize events from the system. int Fl_Window::handle(int ev) { if (parent()) { switch (ev) { case FL_SHOW: if (!shown()) show(); else { pWindowDriver->map(); } break; case FL_HIDE: if (shown()) { // Find what really turned invisible, if it was a parent window // we do nothing. We need to avoid unnecessary unmap calls // because they cause the display to blink when the parent is // remapped. However if this or any intermediate non-window // widget has really had hide() called directly on it, we must // unmap because when the parent window is remapped we don't // want to reappear. if (visible()) { Fl_Widget* p = parent(); for (; p && p->visible(); p = p->parent()) { /* empty*/ } if (p && p->as_window()) break; // don't do the unmap } pWindowDriver->unmap(); } break; } } return Fl_Group::handle(ev); } /** Sets the allowable range to which the user can resize this window. We recommend to call size_range() if you have a resizable() widget in a main window, and to call it after setting the resizable() and before show()'ing the window for best cross platform compatibility. If this function is \b not called, FLTK tries to figure out the range when the window is shown. Please see the protected method default_size_range() for details. It is undefined what happens if the current window size does not fit in the constraints passed to size_range(). \note This only works for top-level windows and the exact behavior can be platform specific. To work correctly across all platforms size_range() must be called after setting the resizable() widget of the window and before the window is show()'n. Calling size_range() after the window has been shown may work on some but not all platforms. If you need to change the size_range() after the window has been shown, then you should consider to hide() and show() the window again, i.e. call hide(), size_range(), and show() in this order. Typical usage: call \code size_range(minWidth, minHeight); \endcode after setting the resizable widget and before calling show(). This ensures that the window cannot be resized smaller than the given values by user interaction. \c maxWidth and \c maxHeight might be useful in some special cases but less frequently used. The other optional parameters \c deltaX, \c deltaY, and \c aspectRatio are not recommended because they may not work on all platforms and may even under X11 not be supported by all Window Managers. \param[in] minWidth,minHeight The smallest the window can be. Either value must be greater than 0. \param[in] maxWidth,maxHeight The largest the window can be. If either is equal to the minimum then you cannot resize in that direction. If either is zero then FLTK picks a maximum size in that direction such that the window will fill the screen. \param[in] deltaX,deltaY These are size increments. The window will be constrained to widths of minWidth + N * deltaX, where N is any non-negative integer. If these are less or equal to 1 they are ignored (this is always ignored on Windows). \param[in] aspectRatio A flag that indicates that the window should preserve its aspect ratio. This only works if both the maximum and minimum have the same aspect ratio (ignored on Windows and by many X window managers). */ void Fl_Window::size_range(int minWidth, int minHeight, int maxWidth, int maxHeight, int deltaX, int deltaY, int aspectRatio) { minw_ = minWidth; minh_ = minHeight; maxw_ = maxWidth; maxh_ = maxHeight; dw_ = deltaX; dh_ = deltaY; aspect_ = aspectRatio; size_range_set_ = 1; pWindowDriver->size_range(); // platform specific stuff } /** Gets the allowable range to which the user can resize this window. \param[out] minWidth, minHeight, maxWidth, maxHeight, deltaX, deltaY, aspectRatio are all pointers to integers that will receive the current respective value during the call. Every pointer can be NULL if that value is not needed. \retval 0 if size range not set \retval 1 if the size range was explicitly set by a call to Fl_Window::size_range() or has been calculated \see Fl_Window::size_range(int minWidth, int minHeight, int maxWidth, int maxHeight, int deltaX, int deltaY, int aspectRatio) \since 1.4.0 */ uchar Fl_Window::get_size_range(int *minWidth, int *minHeight, int *maxWidth, int *maxHeight, int *deltaX, int *deltaY, int *aspectRatio) { if (minWidth) *minWidth = minw_; if (minHeight) *minHeight = minh_; if (maxWidth) *maxWidth = maxw_; if (maxHeight) *maxHeight = maxh_; if (deltaX) *deltaX = dw_; if (deltaY) *deltaY = dh_; if (aspectRatio) *aspectRatio = aspect_; return size_range_set_; } /** Protected method to calculate the default size range of a window. This method is called internally prior to showing a window to ensure that the window's size range values are calculated if a resizable() widget has been set but size_range() has not been called explicitly. This method does nothing if size_range() has been called before. Otherwise FLTK tries to figure out the window's size range from the setting of the window's resizable() widget as follows and roughly in the given order. -# If resizable() is NULL (this is the default) then the window cannot be resized and the resize border and max-size control will not be displayed for the window. -# If either dimension of resizable() is zero, then the window cannot resize in that direction. -# The resizable() widget is clipped to the window area. -# The non-resizable portion of the window is calculated as the difference of the window's size and the clipped resizable() widget's size. -# If either dimension of the clipped resizable() widget is greater than 100, then 100 is considered its minimum width/height. This allows the resizable widget to shrink below its original size. -# Finally the minimum width/height of the window is set to the non-resizable portion plus the width/height of the resizable() widget as calculated above. In simple words: - It is assumed that the resizable() widget can be indefinitely enlarged and/or shrunk to a minimum width/height of 100 unless it is smaller than that, which is then considered the minimum. - The window's size_range() minimum values are set to the sum of the non-resizable portion of the window and the previously calculated minimum size of the resizable() widget. Examples: \code Fl_Window win(400, 400); win.resizable(win); // win.size_range(100, 100, 0, 0); \endcode The minimum size of the resizable is 100, hence the minimum size of the total window is also 100 in both directions. \code Fl_Window win(400, 400); Fl_Box box(20, 20, 360, 360); win.resizable(box); // win.size_range(140, 140, 0, 0); \endcode The calculated minimum width and height would be 20 + 100 + 20 in both dimensions. \code Fl_Window win(400, 400); Fl_Box box(200, 0, 500, 300); // note: width 500 too large: clipped win.resizable(box); // win.size_range(300, 200, 0, 0); \endcode The width of the resizable is clipped to 200, hence the minimum size of the total window is also 200 (fix) + 100 (min. resizable) in x direction. The minimum value in y direction is 100 (resizable) + 100 (fixed part). The calculation is based on clipping the resizable widget to the window area to prevent programming errors and the assumption that the resizable widget can be shrunk to 100x100 or its original size, whichever is smaller. If this is not what you want, please use Fl_Window::size_range() explicitly so you can set any appropriate range. \since 1.4.0 */ void Fl_Window::default_size_range() { if (size_range_set_) return; if (!resizable()) { size_range(w(), h(), w(), h()); return; } // Calculate default size range depending on the resizable() widget Fl_Widget *r = resizable(); int maxw = 0; int maxh = 0; // Clip the resizable() widget to the window int L = (r == this ? 0 : r->x()); int R = L + r->w(); if (R < 0 || L > w()) R = L; // outside the window else { if (L < 0) L = 0; if (R > w()) R = w(); } int rw = R - L; int T = (r == this ? 0 : r->y()); int B = T + r->h(); if (B < 0 || T > h()) B = T; // outside the window else { if (T < 0) T = 0; if (B > h()) B = h(); } int rh = B - T; // Calculate the non-resizable part of the window (STR 3352) // before reducing the size of the resizable widget ! int minw = w() - rw; int minh = h() - rh; // Limit the resizable dimensions to 100x100 according to the docs. // This makes the resizable widget shrinkable, otherwise it would // only be able to grow (issue #392) if (rw > 100) rw = 100; if (rh > 100) rh = 100; // Add the clipped resizable() width/height so we have at least // the non-resizable part + the clipped resizable() size minw += rw; minh += rh; // Disable resizing in the respective directions if any dimension // of the resizable widget is zero (see docs) if (r->w() == 0) minw = maxw = w(); if (r->h() == 0) minh = maxh = h(); // Finally set the size range size_range(minw, minh, maxw, maxh); } /** Protected method to determine whether a window is resizable. If size_range() has not yet been called this method calculates the default size range values by calling default_size_range(). This method is for internal use only. The returned value is a bit mask and non-zero if the window is resizable in at least one direction. \return non-zero if the window is resizable \retval 0 the window is not resizable \retval 1 the window is resizable in horizontal direction (w) \retval 2 the window is resizable in vertical direction (h) \retval 3 the window is resizable in both directions (w and h) \see default_size_range() \since 1.4.0 */ int Fl_Window::is_resizable() { default_size_range(); int ret = 0; if (minw_ != maxw_) ret |= 1; if (minh_ != maxh_) ret |= 2; return ret; } /** The number of the screen containing the mapped window. This method returns the screen number (0 .. n) of the window if it is shown, otherwise the result value is undefined. \note The return value is undefined before the window is shown and if the window has been hidden after it was previously shown. To position a window on a particular screen, use Fl_Window::screen_num(int) \b before you show() it. \return screen number of the window if it is shown \see Fl_Window::screen_num(int) \since 1.4.0 */ int Fl_Window::screen_num() { return pWindowDriver->screen_num(); } /** Set the number of the screen where to map the window. Call this and set also the window's desired x/y position before show()'ing the window. This can be necessary if a system has several screens with distinct scaling factors because the window's x() and y() may not suffice to uniquely identify one screen. Consider a system with two screens where the left screen is A pixels wide and has a scaling factor of 1 whereas the right screen has a scaling factor of 2. For the sake of simplicity, consider only the X coordinate of the window. FLTK coordinates translate directly to pixel coordinates on the left screen, whereas FLTK coordinates multiplied by 2 correspond to pixel coordinates on the right screen. Consequently, FLTK coordinates between A/2 + 1 and A-1 can map to both screens. Therefore both the window coordinates and the screen number are necessary to uniquely identify where a window is to be mapped. The valid range of \p screen_num is 0 .. Fl::screen_count() - 1. This method does nothing if - the window is already shown() or - the given screen number is out of range. \param[in] screen_num screen number where the window is to be mapped \see Fl_Window::screen_num() \see Fl::screen_count() \since 1.4.0 */ void Fl_Window::screen_num(int screen_num) { if (!shown() && screen_num >= 0 && screen_num < Fl::screen_count()) pWindowDriver->screen_num(screen_num); } /** Assigns a non-rectangular shape to the window. This function gives an arbitrary shape (not just a rectangular region) to an Fl_Window. An Fl_Image of any dimension can be used as mask; it is rescaled to the window's dimension as needed. The layout and widgets inside are unaware of the mask shape, and most will act as though the window's rectangular bounding box is available to them. It is up to you to make sure they adhere to the bounds of their masking shape. The \p img argument can be an Fl_Bitmap, Fl_Pixmap, Fl_RGB_Image or Fl_Shared_Image: \li With Fl_Bitmap or Fl_Pixmap, the shaped window covers the image part where bitmap bits equal one, or where the pixmap is not fully transparent. \li With an Fl_RGB_Image with an alpha channel (depths 2 or 4), the shaped window covers the image part that is not fully transparent. \li With an Fl_RGB_Image of depth 1 (gray-scale) or 3 (RGB), the shaped window covers the non-black image part. \li With an Fl_Shared_Image, the shape is determined by rules above applied to the underlying image. The shared image should not have been scaled through Fl_Image::scale(). Platform details: \li On the unix/linux platform, the SHAPE extension of the X server is required. This function does control the shape of Fl_Gl_Window instances. \li On the Windows platform, this function does nothing with class Fl_Gl_Window. \li On the Mac platform, OS version 10.4 or above is required. An 8-bit shape-mask is used when \p img is an Fl_RGB_Image: with depths 2 or 4, the image alpha channel becomes the shape mask such that areas with alpha = 0 are out of the shaped window; with depths 1 or 3, white and black are in and out of the shaped window, respectively, and other colors give intermediate masking scores. This function does nothing with class Fl_Gl_Window. The window borders and caption created by the window system are turned off by default. They can be re-enabled by calling Fl_Window::border(1). A usage example is found at example/shapedwindow.cxx. \version 1.3.3 */ void Fl_Window::shape(const Fl_Image* img) {pWindowDriver->shape(img);} /** Set the window's shape with an Fl_Image. \see void shape(const Fl_Image* img) */ void Fl_Window::shape(const Fl_Image& img) {pWindowDriver->shape(&img);} /** Returns the image controlling the window shape or NULL. \since 1.4.0 */ const Fl_Image* Fl_Window::shape() {return pWindowDriver->shape();} /** Returns true when a window is being rescaled. \since 1.4.0 */ bool Fl_Window::is_a_rescale() {return Fl_Window_Driver::is_a_rescale_;} /** Returns a platform-specific identification of a shown window, or 0 if not shown. \note This identification may differ from the platform-specific reference of an Fl_Window object used by functions fl_x11_xid(), fl_mac_xid(), fl_x11_find(), and fl_mac_find(). - X11 platform: the window's XID. - macOS platform: The window number of the window’s window device. - other platforms: 0. \since 1.4.0 */ fl_uintptr_t Fl_Window::os_id() { return pWindowDriver->os_id();} /** Maximizes a top-level window to its current screen. This function is effective only with a show()'n, resizable, top-level window. Bordered and borderless windows can be used. Fullscreen windows can't be used. \see Fl_Window::un_maximize(), Fl_Window::maximize_active() \since 1.4.0 */ void Fl_Window::maximize() { if (!shown() || parent() || !is_resizable() || maximize_active() || fullscreen_active()) return; set_flag(MAXIMIZED); pWindowDriver->maximize(); } /** Returns a previously maximized top-level window to its previous size. \see Fl_Window::maximize() \since 1.4.0 */ void Fl_Window::un_maximize() { if (!shown() || parent() || !is_resizable() || !maximize_active() || fullscreen_active()) return; clear_flag(MAXIMIZED); pWindowDriver->un_maximize(); } void Fl_Window::is_maximized_(bool b) { if (b) set_flag(MAXIMIZED); else clear_flag(MAXIMIZED); } /** Allow this subwindow to expand outside the area of its parent window. This is presently implemented only for the Wayland platform to help support window docking. \since 1.4.0 */ void Fl_Window::allow_expand_outside_parent() { if (parent()) pWindowDriver->allow_expand_outside_parent(); } fltk-1.4.3/src/Fl_x.cxx0000644000175000017500000034014115004135251015013 0ustar albrechtalbrecht// // X specific code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Note: this file contains platform specific code and will therefore // not be processed by doxygen (see Doxyfile.in). # ifndef FLTK_CONSOLIDATE_MOTION # define FLTK_CONSOLIDATE_MOTION 0 # endif /**** Define this if your keyboard lacks a backspace key... ****/ /* #define BACKSPACE_HACK 1 */ # include # include # include # include "Fl_Window_Driver.H" # include # include # include # include # include # include # include # include # include # include # include "flstring.h" # include "drivers/X11/Fl_X11_Screen_Driver.H" # include "drivers/X11/Fl_X11_Window_Driver.H" # include "drivers/Unix/Fl_Unix_System_Driver.H" #if FLTK_USE_CAIRO # include "drivers/Cairo/Fl_X11_Cairo_Graphics_Driver.H" #else # include "drivers/Xlib/Fl_Xlib_Graphics_Driver.H" #endif # include "print_button.h" # include # include # include # include # include # include # include # include # include "Xutf8.h" #if FLTK_USE_CAIRO # include # include #endif // FLTK_USE_CAIRO #define USE_XRANDR (HAVE_DLSYM && HAVE_DLFCN_H) // means attempt to dynamically load libXrandr.so #if USE_XRANDR #include #define RRScreenChangeNotifyMask (1L << 0) // from X11/extensions/Xrandr.h #define RRScreenChangeNotify 0 // from X11/extensions/Xrandr.h typedef int (*XRRUpdateConfiguration_type)(XEvent *event); static XRRUpdateConfiguration_type XRRUpdateConfiguration_f; static int randrEventBase; // base of RandR-defined events #endif # if HAVE_XFIXES # include static int xfixes_event_base = 0; static bool have_xfixes = false; # endif # include # if HAVE_XCURSOR # include # endif # if HAVE_XRENDER # include # endif # if USE_POLL # include # else # define POLLIN 1 # endif /* USE_POLL */ extern Fl_Widget *fl_selection_requestor; static void open_display_i(Display *d); // open display (internal) extern int fl_send_system_handlers(void *e); #if FLTK_CONSOLIDATE_MOTION static Fl_Window* send_motion; extern Fl_Window* fl_xmousewin; #endif static bool in_a_window; // true if in any of our windows, even destroyed ones static void do_queued_events() { in_a_window = true; while (XEventsQueued(fl_display,QueuedAfterReading)) { XEvent xevent; XNextEvent(fl_display, &xevent); if (fl_send_system_handlers(&xevent)) continue; fl_handle(xevent); } // we send FL_LEAVE only if the mouse did not enter some other window: if (!in_a_window) Fl::handle(FL_LEAVE, 0); #if FLTK_CONSOLIDATE_MOTION else if (send_motion && send_motion == fl_xmousewin) { send_motion = 0; Fl::handle(FL_MOVE, fl_xmousewin); } #endif } // This is never called with time_to_wait < 0.0: // It should return negative on error, 0 if nothing happens before // timeout, and >0 if any callbacks were done. int Fl_X11_Screen_Driver::poll_or_select_with_delay(double time_to_wait) { // OpenGL and other broken libraries call XEventsQueued // unnecessarily and thus cause the file descriptor to not be ready, // so we must check for already-read events: if (fl_display && XQLength(fl_display)) {do_queued_events(); return 1;} return Fl_Unix_Screen_Driver::poll_or_select_with_delay(time_to_wait); } // just like Fl_X11_Screen_Driver::poll_or_select_with_delay(0.0) except no callbacks are done: int Fl_X11_Screen_Driver::poll_or_select() { if (XQLength(fl_display)) return 1; return Fl_Unix_Screen_Driver::poll_or_select(); } // replace \r\n by \n static void convert_crlf(unsigned char *string, long& len) { unsigned char *a, *b; a = b = string; while (*a) { if (*a == '\r' && a[1] == '\n') { a++; len--; } else *b++ = *a++; } *b = 0; } //////////////////////////////////////////////////////////////// Display *fl_display; Display *fl_x11_display() { return fl_display; } Window fl_message_window = 0; int fl_screen; XVisualInfo *fl_visual; Colormap fl_colormap; static XRectangle status_area; static Atom WM_DELETE_WINDOW; static Atom WM_PROTOCOLS; static Atom fl_MOTIF_WM_HINTS; static Atom TARGETS; static Atom CLIPBOARD; static Atom TIMESTAMP; static Atom PRIMARY_TIMESTAMP; static Atom CLIPBOARD_TIMESTAMP; Atom fl_XdndAware; Atom fl_XdndSelection; Atom fl_XdndEnter; Atom fl_XdndTypeList; Atom fl_XdndPosition; Atom fl_XdndLeave; Atom fl_XdndDrop; Atom fl_XdndStatus; Atom fl_XdndActionCopy; Atom fl_XdndFinished; Atom fl_XdndURIList; static Atom fl_Xatextplainutf; static Atom fl_Xatextplainutf2; // STR#2930 static Atom fl_Xatextplain; static Atom fl_XaText; static Atom fl_XaCompoundText; Atom fl_XaUtf8String; static Atom fl_XaTextUriList; static Atom fl_XaImageBmp; static Atom fl_XaImagePNG; static Atom fl_INCR; static Atom fl_NET_WM_PID; static Atom fl_NET_WM_NAME; // utf8 aware window label static Atom fl_NET_WM_ICON_NAME; // utf8 aware window icon name static Atom fl_NET_SUPPORTING_WM_CHECK; static Atom fl_NET_WM_STATE; static Atom fl_NET_WM_STATE_FULLSCREEN; static Atom fl_NET_WM_STATE_MAXIMIZED_VERT; static Atom fl_NET_WM_STATE_MAXIMIZED_HORZ; static Atom fl_NET_WM_FULLSCREEN_MONITORS; Atom fl_NET_WORKAREA; static Atom fl_NET_WM_ICON; static Atom fl_NET_ACTIVE_WINDOW; /* Debug: translate Atom (number) to name: enable (1) if used below */ #if (0) static void debug_atom_name(const char *fun, int line, Atom atom) { char *name = XGetAtomName(fl_display, atom); fprintf(stderr, "[%s:%d] debug_atom_name (%4lu) = %s\n", fun, line, atom, name); XFree(name); } #endif /* Find the best target in a list of available copy/paste or dnd targets. This function searches all available targets [avail, na] by comparing these with an ordered list of suitable targets [targets, nt]. The size of the list of available targets is determined by 'na'. The list of suitable targets must be ordered by preference with the best target first. This ensures that we always find our preferred target, no matter how the list of available targets is ordered. The list size is max. 'nt' entries but can also be terminated by a zero (0) entry. The list of suitable targets is provided by FLTK (see below); the list of available targets is provided by the data source program. Returns: (Atom) the "best target" or 0 (zero) if no target matches. */ static Atom find_target(Atom *targets, int nt, Atom *avail, int na) { Atom retval = 0; Atom mt, at; int i = 0, m = 0; #if (0) // Debug fprintf(stderr, "find_target: looking for:\n"); for (i = 0; i < nt; i++) debug_atom_name(" find_target", i, targets[i]); for (i = 0; i < na; i++) debug_atom_name(" available ", i, avail[i]); #endif // Debug int n = nt; for (i = 0; i < na; i++) { // search all available targets at = avail[i]; // search only *better* targets: m < n ! for (m = 0; m < n; m++) { // try to match usable targets mt = targets[m]; if (!mt) break; // end of list if (mt == at) { n = m; retval = mt; break; } } if (n == 0) break; // found the *best* target (0) } // debug_atom_name("find_target: FOUND", n, retval); return retval; } /* Find a suitable target for text insertion in a list of available targets. */ static Atom find_target_text(Atom *avail, int na) { static Atom text_targets[] = { fl_XaUtf8String, // "UTF8_STRING" fl_Xatextplainutf2, // "text/plain;charset=utf-8" (correct: lowercase) fl_Xatextplainutf, // "text/plain;charset=UTF-8" (non-standard: compat.) fl_Xatextplain, // "text/plain" XA_STRING, // "STRING" fl_XaText, // "TEXT" fl_XaCompoundText, // "COMPOUND_TEXT" fl_XaTextUriList, // "text/uri-list" (e.g. file manager) (Atom)0 // list terminator (optional, but don't remove) }; static int nt = sizeof(text_targets) / sizeof(Atom) - 1; // list size w/o terminator return find_target(text_targets, nt, avail, na); } /* Find a suitable target for image insertion in a list of available targets. */ static Atom find_target_image(Atom *avail, int na) { static Atom image_targets[] = { fl_XaImageBmp, // "image/bmp" fl_XaImagePNG, // "image/png" (Atom)0 // list terminator (optional, but don't remove) }; static int ni = sizeof(image_targets) / sizeof(Atom) - 1; // list size w/o terminator return find_target(image_targets, ni, avail, na); } /* X defines 32-bit-entities to have a format value of max. 32, although sizeof(atom) can be 8 (64 bits) on a 64-bit OS. See also fl_open_display() for sizeof(atom) < 4. Used for XChangeProperty (see STR #2419). */ static int atom_bits = 32; static void fd_callback(int,void *) { do_queued_events(); } extern "C" { static int io_error_handler(Display*) { Fl::fatal("X I/O error"); return 0; } static int xerror_handler(Display* d, XErrorEvent* e) { char buf1[128], buf2[128]; snprintf(buf1, 128, "XRequest.%d", e->request_code); XGetErrorDatabaseText(d,"",buf1,buf1,buf2,128); XGetErrorText(d, e->error_code, buf1, 128); Fl::warning("%s: %s 0x%lx", buf2, buf1, e->resourceid); return 0; } } extern char *fl_get_font_xfld(int fnum, int size); void Fl_X11_Screen_Driver::new_ic() { XVaNestedList preedit_attr = NULL; XVaNestedList status_attr = NULL; static XFontSet fs = NULL; char *fnt; char **missing_list = 0; int missing_count = 0; char *def_string; static XRectangle spot; int predit = 0; int sarea = 0; XIMStyles* xim_styles = NULL; #if USE_XFT #if defined(__GNUC__) // FIXME: warning XFT support here #endif /*__GNUC__*/ if (!fs) { fnt = (char*)"-misc-fixed-*"; fs = XCreateFontSet(fl_display, fnt, &missing_list, &missing_count, &def_string); } #else if (!fs) { bool must_free_fnt = true; fnt = fl_get_font_xfld(0, 14); if (!fnt) {fnt = (char*)"-misc-fixed-*";must_free_fnt=false;} fs = XCreateFontSet(fl_display, fnt, &missing_list, &missing_count, &def_string); if (must_free_fnt) free(fnt); } #endif if (missing_list) XFreeStringList(missing_list); preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, XNFontSet, fs, NULL); status_attr = XVaCreateNestedList(0, XNAreaNeeded, &status_area, XNFontSet, fs, NULL); if (!XGetIMValues(xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL)) { int i; XIMStyle *style; for (i = 0, style = xim_styles->supported_styles; i < xim_styles->count_styles; i++, style++) { if (*style == (XIMPreeditPosition | XIMStatusArea)) { sarea = 1; predit = 1; } else if (*style == (XIMPreeditPosition | XIMStatusNothing)) { predit = 1; } } } XFree(xim_styles); if (sarea) { xim_ic = XCreateIC(xim_im, XNInputStyle, (XIMPreeditPosition | XIMStatusArea), XNPreeditAttributes, preedit_attr, XNStatusAttributes, status_attr, NULL); } if (!xim_ic && predit) { xim_ic = XCreateIC(xim_im, XNInputStyle, (XIMPreeditPosition | XIMStatusNothing), XNPreeditAttributes, preedit_attr, NULL); } XFree(preedit_attr); XFree(status_attr); if (!xim_ic) { Fl_X11_Screen_Driver::fl_is_over_the_spot = 0; xim_ic = XCreateIC(xim_im, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), NULL); } else { Fl_X11_Screen_Driver::fl_is_over_the_spot = 1; status_attr = XVaCreateNestedList(0, XNAreaNeeded, &status_area, NULL); XGetICValues(xim_ic, XNStatusAttributes, status_attr, NULL); XFree(status_attr); } } void Fl_X11_Screen_Driver::set_status(int x, int y, int w, int h) { XVaNestedList status_attr; status_area.x = x; status_area.y = y; status_area.width = w; status_area.height = h; if (!xim_ic) return; status_attr = XVaCreateNestedList(0, XNArea, &status_area, NULL); XSetICValues(xim_ic, XNStatusAttributes, status_attr, NULL); XFree(status_attr); } void Fl_X11_Screen_Driver::init_xim() { static int xim_warning = 2; if (xim_warning > 0) xim_warning--; //XIMStyle *style; XIMStyles *xim_styles; if (!fl_display) return; if (xim_im) return; xim_im = XOpenIM(fl_display, NULL, NULL, NULL); xim_styles = NULL; xim_ic = NULL; if (xim_im) { XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL); } else { if (xim_warning) Fl::warning("XOpenIM() failed"); // if xim_styles is allocated, free it now if (xim_styles) XFree(xim_styles); return; } if (xim_styles && xim_styles->count_styles) { Fl_X11_Screen_Driver::new_ic(); } else { if (xim_warning) Fl::warning("No XIM style found"); XCloseIM(xim_im); xim_im = NULL; // if xim_styles is allocated, free it now if (xim_styles) XFree(xim_styles); return; } if (!xim_ic) { if (xim_warning) Fl::warning("XCreateIC() failed"); XCloseIM(xim_im); xim_im = NULL; } // if xim_styles is still allocated, free it now if(xim_styles) XFree(xim_styles); } void Fl_X11_Screen_Driver::xim_activate(Window xid) { if (!xim_im) return; // If the focused window has changed, then use the brute force method // of completely recreating the input context. if (xim_win != xid) { xim_deactivate(); Fl_X11_Screen_Driver::new_ic(); xim_win = xid; XSetICValues(xim_ic, XNFocusWindow, xim_win, XNClientWindow, xim_win, NULL); } Fl_X11_Screen_Driver *driver = (Fl_X11_Screen_Driver*)Fl::screen_driver(); driver->set_spot(fl_spotf, fl_spots, fl_spot.x, fl_spot.y, fl_spot.width, fl_spot.height, NULL); } void Fl_X11_Screen_Driver::xim_deactivate(void) { if (!xim_ic) return; XDestroyIC(xim_ic); xim_ic = NULL; xim_win = 0; } void Fl_X11_Screen_Driver::enable_im() { Fl_Window *win; win = Fl::first_window(); if (win && win->shown()) { xim_activate(fl_xid(win)); XSetICFocus(xim_ic); } else { new_ic(); } } void Fl_X11_Screen_Driver::disable_im() { xim_deactivate(); } static void delayed_create_print_window(void *) { Fl::remove_check(delayed_create_print_window); fl_create_print_window(); } void Fl_X11_Screen_Driver::open_display_platform() { static Display *d = NULL; if (d) return; setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); XSetIOErrorHandler(io_error_handler); XSetErrorHandler(xerror_handler); d = (fl_display ? fl_display : XOpenDisplay(0)); if (!d) { Fl::fatal("Can't open display: %s", XDisplayName(0)); // does not return return; // silence static code analyzer } open_display_i(d); // the unique GC used by all X windows GC gc = XCreateGC(fl_display, RootWindow(fl_display, fl_screen), 0, 0); Fl_Graphics_Driver::default_driver().gc(gc); Fl::add_check(delayed_create_print_window); } void open_display_i(Display* d) { fl_display = d; WM_DELETE_WINDOW = XInternAtom(d, "WM_DELETE_WINDOW", 0); WM_PROTOCOLS = XInternAtom(d, "WM_PROTOCOLS", 0); fl_MOTIF_WM_HINTS = XInternAtom(d, "_MOTIF_WM_HINTS", 0); TARGETS = XInternAtom(d, "TARGETS", 0); CLIPBOARD = XInternAtom(d, "CLIPBOARD", 0); TIMESTAMP = XInternAtom(d, "TIMESTAMP", 0); PRIMARY_TIMESTAMP = XInternAtom(d, "PRIMARY_TIMESTAMP", 0); CLIPBOARD_TIMESTAMP = XInternAtom(d, "CLIPBOARD_TIMESTAMP", 0); fl_XdndAware = XInternAtom(d, "XdndAware", 0); fl_XdndSelection = XInternAtom(d, "XdndSelection", 0); fl_XdndEnter = XInternAtom(d, "XdndEnter", 0); fl_XdndTypeList = XInternAtom(d, "XdndTypeList", 0); fl_XdndPosition = XInternAtom(d, "XdndPosition", 0); fl_XdndLeave = XInternAtom(d, "XdndLeave", 0); fl_XdndDrop = XInternAtom(d, "XdndDrop", 0); fl_XdndStatus = XInternAtom(d, "XdndStatus", 0); fl_XdndActionCopy = XInternAtom(d, "XdndActionCopy", 0); fl_XdndFinished = XInternAtom(d, "XdndFinished", 0); fl_XdndURIList = XInternAtom(d, "text/uri-list", 0); fl_Xatextplainutf = XInternAtom(d, "text/plain;charset=UTF-8",0); fl_Xatextplainutf2 = XInternAtom(d, "text/plain;charset=utf-8",0); // Firefox/Thunderbird needs this - See STR#2930 fl_Xatextplain = XInternAtom(d, "text/plain", 0); fl_XaText = XInternAtom(d, "TEXT", 0); fl_XaCompoundText = XInternAtom(d, "COMPOUND_TEXT", 0); fl_XaUtf8String = XInternAtom(d, "UTF8_STRING", 0); fl_XaTextUriList = XInternAtom(d, "text/uri-list", 0); fl_XaImageBmp = XInternAtom(d, "image/bmp", 0); fl_XaImagePNG = XInternAtom(d, "image/png", 0); fl_INCR = XInternAtom(d, "INCR", 0); fl_NET_WM_PID = XInternAtom(d, "_NET_WM_PID", 0); fl_NET_WM_NAME = XInternAtom(d, "_NET_WM_NAME", 0); fl_NET_WM_ICON_NAME = XInternAtom(d, "_NET_WM_ICON_NAME", 0); fl_NET_SUPPORTING_WM_CHECK = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", 0); fl_NET_WM_STATE = XInternAtom(d, "_NET_WM_STATE", 0); fl_NET_WM_STATE_FULLSCREEN = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", 0); fl_NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(d, "_NET_WM_STATE_MAXIMIZED_VERT", 0); fl_NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(d, "_NET_WM_STATE_MAXIMIZED_HORZ", 0); fl_NET_WM_FULLSCREEN_MONITORS = XInternAtom(d, "_NET_WM_FULLSCREEN_MONITORS", 0); fl_NET_WORKAREA = XInternAtom(d, "_NET_WORKAREA", 0); fl_NET_WM_ICON = XInternAtom(d, "_NET_WM_ICON", 0); fl_NET_ACTIVE_WINDOW = XInternAtom(d, "_NET_ACTIVE_WINDOW", 0); if (sizeof(Atom) < 4) atom_bits = sizeof(Atom) * 8; Fl::add_fd(ConnectionNumber(d), POLLIN, fd_callback); fl_screen = DefaultScreen(d); fl_message_window = XCreateSimpleWindow(d, RootWindow(d,fl_screen), 0,0,1,1,0, 0, 0); // construct an XVisualInfo that matches the default Visual: XVisualInfo templt; int num; templt.visualid = XVisualIDFromVisual(DefaultVisual(d, fl_screen)); fl_visual = XGetVisualInfo(d, VisualIDMask, &templt, &num); fl_colormap = DefaultColormap(d, fl_screen); Fl_X11_Screen_Driver::init_xim(); #if !USE_COLORMAP Fl::visual(FL_RGB); #endif #if HAVE_XFIXES int error_base; if (XFixesQueryExtension(fl_display, &xfixes_event_base, &error_base)) have_xfixes = true; else have_xfixes = false; #endif #if USE_XRANDR void *libxrandr_addr = Fl_Posix_System_Driver::dlopen_or_dlsym("libXrandr"); if (libxrandr_addr) { int error_base; typedef Bool (*XRRQueryExtension_type)(Display*, int*, int*); typedef void (*XRRSelectInput_type)(Display*, Window, int); XRRQueryExtension_type XRRQueryExtension_f = (XRRQueryExtension_type)dlsym(libxrandr_addr, "XRRQueryExtension"); XRRSelectInput_type XRRSelectInput_f = (XRRSelectInput_type)dlsym(libxrandr_addr, "XRRSelectInput"); XRRUpdateConfiguration_f = (XRRUpdateConfiguration_type)dlsym(libxrandr_addr, "XRRUpdateConfiguration"); if (XRRQueryExtension_f && XRRSelectInput_f && XRRQueryExtension_f(d, &randrEventBase, &error_base)) XRRSelectInput_f(d, RootWindow(d, fl_screen), RRScreenChangeNotifyMask); else XRRUpdateConfiguration_f = NULL; } #endif // Listen for changes to _NET_WORKAREA XSelectInput(d, RootWindow(d, fl_screen), PropertyChangeMask); } void Fl_X11_Screen_Driver::close_display() { Fl::remove_fd(ConnectionNumber(fl_display)); XCloseDisplay(fl_display); } int Fl_X11_Screen_Driver::get_mouse_unscaled(int &mx, int &my) { open_display(); Window root = RootWindow(fl_display, fl_screen); Window c; int cx,cy; unsigned int mask; XQueryPointer(fl_display, root, &root, &c, &mx, &my, &cx, &cy, &mask); #if USE_XFT int screen = screen_num_unscaled(mx, my); return screen >= 0 ? screen : 0; #else return screen_num(mx, my); #endif } int Fl_X11_Screen_Driver::get_mouse(int &xx, int &yy) { int snum = get_mouse_unscaled(xx, yy); float s = scale(snum); xx = xx/s; yy = yy/s; return snum; } //////////////////////////////////////////////////////////////// // Code used for paste and DnD into the program: char *fl_selection_buffer[2]; int fl_selection_length[2]; const char * fl_selection_type[2]; int fl_selection_buffer_length[2]; char fl_i_own_selection[2] = {0,0}; // Call this when a "paste" operation happens: void Fl_X11_Screen_Driver::paste(Fl_Widget &receiver, int clipboard, const char *type) { if (fl_i_own_selection[clipboard]) { // We already have it, do it quickly without window server. if (type == Fl::clipboard_plain_text && fl_selection_type[clipboard] == type) { // Notice that the text is clobbered if set_selection is // called in response to FL_PASTE! // However, for now, we only paste text in this function Fl::e_text = fl_selection_buffer[clipboard]; Fl::e_length = fl_selection_length[clipboard]; if (!Fl::e_text) Fl::e_text = (char *)""; } else if (clipboard == 1 && type == Fl::clipboard_image && fl_selection_type[1] == type) { Fl::e_clipboard_data = Fl_Unix_System_Driver::own_bmp_to_RGB(fl_selection_buffer[1]); Fl::e_clipboard_type = Fl::clipboard_image; } else return; int retval = receiver.handle(FL_PASTE); if (retval == 0 && type == Fl::clipboard_image) { delete (Fl_RGB_Image*)Fl::e_clipboard_data; Fl::e_clipboard_data = NULL; } return; } // otherwise get the window server to return it: fl_selection_requestor = &receiver; Atom property = clipboard ? CLIPBOARD : XA_PRIMARY; Fl::e_clipboard_type = type; XConvertSelection(fl_display, property, TARGETS, property, fl_xid(Fl::first_window()), fl_event_time); } int Fl_X11_Screen_Driver::clipboard_contains(const char *type) { if (fl_i_own_selection[1]) { return fl_selection_type[1] == type; } XEvent event; Atom actual; int format; unsigned long count, remaining, i = 0; unsigned char* portion = NULL; Fl_Window *win = Fl::first_window(); if (!win || !fl_xid(win)) return 0; win->wait_for_expose(); XConvertSelection(fl_display, CLIPBOARD, TARGETS, CLIPBOARD, fl_xid(win), CurrentTime); XFlush(fl_display); // FIXME: The following loop may ignore up to 20 events! (AlbrechtS) do { XNextEvent(fl_display, &event); if (event.type == SelectionNotify && event.xselection.property == None) return 0; i++; } while (i < 20 && event.type != SelectionNotify); if (i >= 20) return 0; XGetWindowProperty(fl_display, event.xselection.requestor, event.xselection.property, 0, 4000, 0, 0, &actual, &format, &count, &remaining, &portion); if (actual != XA_ATOM) return 0; Atom t = (Atom)0; if (strcmp(type, Fl::clipboard_plain_text) == 0) t = find_target_text((Atom*)portion, count); else if (strcmp(type, Fl::clipboard_image) == 0) t = find_target_image((Atom*)portion, count); XFree(portion); return (t ? 1 : 0); } static Window fl_dnd_source_window; static Atom *fl_dnd_source_types; // null-terminated list of data types being supplied static Atom fl_dnd_type; static Atom fl_dnd_source_action; static Atom fl_dnd_action; void fl_sendClientMessage(Window window, Atom message, unsigned long d0, unsigned long d1=0, unsigned long d2=0, unsigned long d3=0, unsigned long d4=0) { XEvent e; e.xany.type = ClientMessage; e.xany.window = window; e.xclient.message_type = message; e.xclient.format = 32; e.xclient.data.l[0] = (long)d0; e.xclient.data.l[1] = (long)d1; e.xclient.data.l[2] = (long)d2; e.xclient.data.l[3] = (long)d3; e.xclient.data.l[4] = (long)d4; XSendEvent(fl_display, window, 0, 0, &e); } /* Get window property value (32 bit format) Returns zero on success, -1 on error 'data' should be freed with XFree() using this pattern: unsigned long *data = 0; if (0 == get_xwinprop(....., &nitems, &data) ) { ..success.. } else { ..fail.. } if ( data ) { XFree(data); data=0; } Note: 'data' can be non-zero, even if the return value is -1 (error) and should hence be XFree'd *after* the if/else statement, as described above. */ static int get_xwinprop(Window wnd, Atom prop, long max_length, unsigned long *nitems, unsigned long **data) { Atom actual; int format; unsigned long bytes_after; if (Success != XGetWindowProperty(fl_display, wnd, prop, 0, max_length, False, AnyPropertyType, &actual, &format, nitems, &bytes_after, (unsigned char**)data)) { return -1; } if (actual == None || format != 32) { return -1; } return 0; } //////////////////////////////////////////////////////////////// // Code for copying to clipboard and DnD out of the program: // See Fl::copy() for possible values of the destination (argument clipboard) // See also Fl::selection_to_clipboard() void Fl_X11_Screen_Driver::copy(const char *stuff, int len, int clipboard, const char *type) { if (!stuff || len<0) return; // if selection_to_clipboard is enabled *and* destination is 0 (selection buffer), // then copy to both (STR 3229) if (clipboard == 0 && Fl::selection_to_clipboard()) clipboard = 2; if (clipboard >= 2) { copy(stuff, len, 1, type); // copy to clipboard first (this is a recursion!) clipboard = 0; // ... and then to selection buffer: fall through } if (len+1 > fl_selection_buffer_length[clipboard]) { delete[] fl_selection_buffer[clipboard]; fl_selection_buffer[clipboard] = new char[len+100]; fl_selection_buffer_length[clipboard] = len+100; } memcpy(fl_selection_buffer[clipboard], stuff, len); fl_selection_buffer[clipboard][len] = 0; // needed for direct paste fl_selection_length[clipboard] = len; fl_i_own_selection[clipboard] = 1; fl_selection_type[clipboard] = Fl::clipboard_plain_text; Atom property = clipboard ? CLIPBOARD : XA_PRIMARY; XSetSelectionOwner(fl_display, property, fl_message_window, fl_event_time); } // takes a raw RGB image and puts it in the copy/paste buffer void Fl_X11_Screen_Driver::copy_image(const unsigned char *data, int W, int H, int clipboard){ if (!data || W <= 0 || H <= 0) return; delete[] fl_selection_buffer[clipboard]; fl_selection_buffer[clipboard] = (char *) Fl_Unix_System_Driver::create_bmp(data,W,H,&fl_selection_length[clipboard]); fl_selection_buffer_length[clipboard] = fl_selection_length[clipboard]; fl_i_own_selection[clipboard] = 1; fl_selection_type[clipboard] = Fl::clipboard_image; Atom property = clipboard ? CLIPBOARD : XA_PRIMARY; XSetSelectionOwner(fl_display, property, fl_message_window, fl_event_time); } //////////////////////////////////////////////////////////////// // Code for tracking clipboard changes: static Time primary_timestamp = (Time)-1; static Time clipboard_timestamp = (Time)-1; extern bool fl_clipboard_notify_empty(void); extern void fl_trigger_clipboard_notify(int source); static void poll_clipboard_owner(void) { Window xid; #if HAVE_XFIXES // No polling needed with Xfixes if (have_xfixes) return; #endif // No one is interested, so no point polling if (fl_clipboard_notify_empty()) return; // We need a window for this to work if (!Fl::first_window()) return; xid = fl_xid(Fl::first_window()); if (!xid) return; // Request an update of the selection time for both the primary and // clipboard selections. Magic continues when we get a SelectionNotify. if (!fl_i_own_selection[0]) XConvertSelection(fl_display, XA_PRIMARY, TIMESTAMP, PRIMARY_TIMESTAMP, xid, fl_event_time); if (!fl_i_own_selection[1]) XConvertSelection(fl_display, CLIPBOARD, TIMESTAMP, CLIPBOARD_TIMESTAMP, xid, fl_event_time); } static void clipboard_timeout(void *data) { // No one is interested, so stop polling if (fl_clipboard_notify_empty()) return; poll_clipboard_owner(); Fl::repeat_timeout(0.5, clipboard_timeout); } static void handle_clipboard_timestamp(int clipboard, Time time) { Time *timestamp; timestamp = clipboard ? &clipboard_timestamp : &primary_timestamp; #if HAVE_XFIXES if (!have_xfixes) #endif { // Initial scan, just store the value if (*timestamp == (Time)-1) { *timestamp = time; return; } } // Same selection if (time == *timestamp) return; *timestamp = time; // The clipboard change is the event that caused us to request // the clipboard data, so use that time as the latest event. if (time > fl_event_time) fl_event_time = time; // Something happened! Let's tell someone! fl_trigger_clipboard_notify(clipboard); } void Fl_X11_Screen_Driver::clipboard_notify_change() { // Reset the timestamps if we've going idle so that you don't // get a bogus immediate trigger next time they're activated. if (fl_clipboard_notify_empty()) { primary_timestamp = (Time)-1; clipboard_timestamp = (Time)-1; } else { #if HAVE_XFIXES if (!have_xfixes) #endif { poll_clipboard_owner(); if (!Fl::has_timeout(clipboard_timeout)) Fl::add_timeout(0.5, clipboard_timeout); } } } //////////////////////////////////////////////////////////////// const XEvent* fl_xevent; // the current x event ulong fl_event_time; // the last timestamp from an x event char fl_key_vector[32]; // used by Fl::get_key() // Record event mouse position and state from an XEvent: static int px, py; static ulong ptime; // Citation from XButtonEvent and XKeyEvent docs: // "The state member is set to indicate the logical state of the pointer buttons // and modifier keys just prior to the event, which is the bitwise inclusive OR // of one or more of the button or modifier key masks: // Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask, // ShiftMask, LockMask, ControlMask, // Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask." // // Actual values in Debian Bookworm as of July 2024 (pseudo code): // static int states[] = { // ShiftMask, LockMask, ControlMask, // 1<<0 .. 1<<2 // Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask, // 1<<3 .. 1<<7 // Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask // 1<<8 .. 1<<12 // }; // // Note: some more (undefined?) state bits *may* be set if the user uses a keyboard // other than the primary one (the top-most in keyboard settings). Therefore we must // take care not to use these undefined bits (found by accident). // These undefined bits are ignored and not set in Fl::event_state(), otherwise we // might overwrite other valid bits (since FLTK 1.4.0, Sep 2024 or later). // See definition of FL_BUTTONS in FL/Enumerations.H: // there are only five "sticky" mouse buttons as of Sep 27, 2024. static unsigned int xbutton_state = 0; // extended button state (back, forward) // Define the state bits we're interested in for Fl::event_state(). // Note that we ignore Button4Mask and Button5Mask (vertical scroll wheel). // X11 doesn't define masks for Button6 and Button7 (horizontal scroll wheel) // and any higher button numbers. static const unsigned int event_state_mask = ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | Button1Mask | Button2Mask | Button3Mask; static void set_event_xy(Fl_Window *win) { # if FLTK_CONSOLIDATE_MOTION send_motion = 0; # endif float s = 1; #if USE_XFT s = Fl::screen_driver()->scale(Fl_Window_Driver::driver(win)->screen_num()); #endif Fl::e_x_root = fl_xevent->xbutton.x_root/s; Fl::e_x = fl_xevent->xbutton.x/s; Fl::e_y_root = fl_xevent->xbutton.y_root/s; Fl::e_y = fl_xevent->xbutton.y/s; Fl::e_state = ((fl_xevent->xbutton.state & event_state_mask) << 16) | xbutton_state; fl_event_time = fl_xevent->xbutton.time; # ifdef __sgi // get the meta key off PC keyboards: if (fl_key_vector[18]&0x18) Fl::e_state |= FL_META; # endif // turn off is_click if enough time or mouse movement has passed: if (abs(Fl::e_x_root-px)+abs(Fl::e_y_root-py) > 3 || fl_event_time >= ptime+1000) Fl::e_is_click = 0; } // if this is same event as last && is_click, increment click count: static inline void checkdouble() { if (Fl::e_is_click == Fl::e_keysym) Fl::e_clicks++; else { Fl::e_clicks = 0; Fl::e_is_click = Fl::e_keysym; } px = Fl::e_x_root; py = Fl::e_y_root; ptime = fl_event_time; } static Fl_Window* resize_bug_fix; //////////////////////////////////////////////////////////////// static char unknown[] = ""; const int unknown_len = 10; extern "C" { static int xerror = 0; static int ignoreXEvents(Display *display, XErrorEvent *event) { xerror = 1; return 0; } static XErrorHandler catchXExceptions() { xerror = 0; return ignoreXEvents; } static int wasXExceptionRaised() { return xerror; } } // extern "C" static bool getNextEvent(XEvent *event_return) { time_t t = time(NULL); while (!XPending(fl_display)) { if (time(NULL) - t > 10.0) { // fprintf(stderr,"Error: The XNextEvent never came...\n"); return false; } } XNextEvent(fl_display, event_return); return true; } static long getIncrData(uchar* &data, const XSelectionEvent& selevent, size_t lower_bound) { // fprintf(stderr,"Incremental transfer starting due to INCR property\n"); // fprintf(stderr, "[getIncrData:%d] lower_bound [in ] =%10ld\n", __LINE__, lower_bound); const size_t alloc_min = 4 * 1024 * 1024; // min. initial allocation const size_t alloc_max = 200 * 1024 * 1024; // max. initial allocation const size_t alloc_inc = 4 * 1024 * 1024; // (min.) increase if necessary size_t total = 0; size_t data_size = lower_bound + 1; if (data_size < alloc_min) { data_size = alloc_min; } else if (data_size > alloc_max) { data_size = alloc_max; } // fprintf(stderr, "[getIncrData:%d] initial alloc. =%10ld\n", __LINE__, data_size); XEvent event; XDeleteProperty(fl_display, selevent.requestor, selevent.property); data = (uchar*)realloc(data, data_size); if (!data) { // fprintf(stderr, "[getIncrData:%d] realloc() FAILED, size = %ld\n", __LINE__, data_size); Fl::fatal("Clipboard data transfer failed, size %ld is too large.", data_size); } for (;;) { if (!getNextEvent(&event)) { // This is unexpected but may happen if the sender (clipboard owner) no longer sends data // fprintf(stderr, "[getIncrData:%d] Failed to get next event (timeout) *** break! ***\n", __LINE__); break; } if (event.type == PropertyNotify) { if (event.xproperty.state != PropertyNewValue) continue; // ignore PropertyDelete Atom actual_type; int actual_format; unsigned long nitems; unsigned long bytes_after; unsigned char* prop = 0; long offset = 0; size_t num_bytes = 0; // size_t slice_size = 0; do { XGetWindowProperty(fl_display, selevent.requestor, selevent.property, offset, 70000, True, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop); num_bytes = nitems * (actual_format / 8); offset += num_bytes/4; // slice_size += num_bytes; if (total + num_bytes + bytes_after + 1 > data_size) { data_size += alloc_inc; if (total + num_bytes + bytes_after + 1 > data_size) data_size = total + num_bytes + bytes_after + 1; // printf(" -- realloc(%9ld), total=%10ld, num_bytes=%7ld, bytes_after=%7ld (%7ld), required=%10ld\n", // data_size, total, num_bytes, bytes_after, num_bytes + bytes_after, total + num_bytes + bytes_after + 1); data = (uchar*)realloc(data, data_size); if (!data) { // fprintf(stderr, "[getIncrData():%d] realloc() FAILED, size = %ld\n", __LINE__, data_size); Fl::fatal("Clipboard data transfer failed, size %ld is too large.", data_size); } } memcpy(data + total, prop, num_bytes); total += num_bytes; if (prop) XFree(prop); } while (bytes_after != 0); // fprintf(stderr,"INCR data size:%ld\n", slice_size); if (num_bytes == 0) break; } else { // Unexpected next event. At this point we're handling the INCR protocol and can't deal with // *some* other events due to potential recursions. We *could* call fl_handle(event) to handle // *selected* other events but for the time being we ignore all other events! // Handling the INCR protocol for very large data may take some time and multiple events. // Interleaving "other" events are possible, for instance the KeyRelease event of the // ctrl/v key pressed to insert the clipboard. This solution is not perfect but it can // handle the INCR protocol with very large selections in most cases, although with potential // side effects because other events may be ignored. // See GitHub Issue #451: "Segfault if using very large selections". // Note: the "fix" for Issue #451 is basically to use 'continue' rather than 'break' // Debug: // fprintf(stderr, // "[getIncrData:%d] getNextEvent() returned %d, not PropertyNotify (%d). Event ignored.\n", // __LINE__, event.type, PropertyNotify); continue; } } XDeleteProperty(fl_display, selevent.requestor, selevent.property); // fprintf(stderr, "[getIncrData:%d] total data [out] =%10ld\n", __LINE__, (long)total); return (long)total; } /* Internal function to reduce "deprecated" warnings for XKeycodeToKeysym(). This way we get at most one warning. The option to use XkbKeycodeToKeysym() instead would not help much - see STR #2913 for more information. Update (Jan 31, 2020): disable "deprecated declaration" warnings in this function for GCC >= 4.6 and clang (all versions) to get rid of these warnings at least for current GCC and clang compilers. Note: '#pragma GCC diagnostic push' needs at least GCC 4.6. */ #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif static KeySym fl_KeycodeToKeysym(Display *d, KeyCode k, unsigned i) { return XKeycodeToKeysym(d, k, i); } #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)) #pragma GCC diagnostic pop #endif #ifdef __clang__ #pragma clang diagnostic pop #endif #if USE_XRANDR static void react_to_screen_reconfiguration() { #if USE_XFT // memorize previous screen sizes and scales int old_count = Fl::screen_count(); int (*sizes)[4] = new int[old_count][4]; float *scales = new float[old_count]; for (int screen = 0; screen < old_count; screen++) { Fl::screen_xywh(sizes[screen][0], sizes[screen][1], sizes[screen][2], sizes[screen][3], screen); scales[screen] = Fl::screen_scale(screen); } #endif // USE_XFT Fl::call_screen_init(); // compute new screen sizes #if USE_XFT // detect whether screen sizes were unchanged bool nochange = (old_count == Fl::screen_count()); if (nochange) { for (int screen = 0; screen < old_count; screen++) { int X,Y,W,H; Fl::screen_xywh(X,Y,W,H, screen); X /= scales[screen]; Y /= scales[screen]; W /= scales[screen]; H /= scales[screen]; if (X != sizes[screen][0] || Y != sizes[screen][1] || W != sizes[screen][2] || H != sizes[screen][3]) { nochange = false; break; } } } delete[] sizes; if (nochange || (old_count == 1 && Fl::screen_count() == 1)) { // screen sizes did not change or single screen: re-use previous screen scale values for (int screen = 0; screen < old_count; screen++) Fl::screen_driver()->scale(screen, scales[screen]); } else { Fl::screen_driver()->use_startup_scale_factor(); float new_scale = Fl::screen_driver()->scale(0); for (int screen = 0; screen < Fl::screen_count(); screen++) { Fl::screen_driver()->scale(screen, 1); Fl::screen_driver()->rescale_all_windows_from_screen(screen, new_scale, 1); } } delete[] scales; #endif // USE_XFT } #endif // USE_XRANDR #if USE_XFT static void after_display_rescale(float *p_current_xft_dpi) { Display *new_dpy = XOpenDisplay(XDisplayString(fl_display)); if (!new_dpy) return; char *s = XGetDefault(new_dpy, "Xft", "dpi"); float dpi; if (s && sscanf(s, "%f", &dpi) == 1) { //printf("%s previous=%g dpi=%g \n", s, *p_current_xft_dpi, dpi); if (fabs(dpi - *p_current_xft_dpi) > 0.1) { *p_current_xft_dpi = dpi; float f = dpi / 96.; for (int i = 0; i < Fl::screen_count(); i++) Fl::screen_driver()->rescale_all_windows_from_screen(i, f, f); } } XCloseDisplay(new_dpy); } #endif // USE_XFT static Window *xid_vector = NULL; // list of FLTK-created xid's (see issue #935) static int xid_vector_size = 0; static int xid_vector_count = 0; static void add_xid_vector(Window xid) { if (xid_vector_count >= xid_vector_size) { xid_vector_size += 10; xid_vector = (Window*)realloc(xid_vector, xid_vector_size * sizeof(Window)); } xid_vector[xid_vector_count++] = xid; } static bool remove_xid_vector(Window xid) { for (int pos = xid_vector_count - 1; pos >= 0; pos--) { if (xid_vector[pos] == xid) { if (pos != --xid_vector_count) xid_vector[pos] = xid_vector[xid_vector_count]; return true; } } return false; } int fl_handle(const XEvent& thisevent) { XEvent xevent = thisevent; fl_xevent = &thisevent; Window xid = xevent.xany.window; // For each DestroyNotify event, determine whether an FLTK-created window // is being destroyed (see issue #935). bool xid_is_from_fltk_win = false; if (xevent.type == DestroyNotify) { xid_is_from_fltk_win = remove_xid_vector(xid); } // The following if statement is limited to cases when event DestroyNotify // concerns a non-FLTK window. Thus, the possibly slow call to XOpenIM() // is not performed when an FLTK-created window is closed. This fixes issue #935. if (Fl_X11_Screen_Driver::xim_ic && xevent.type == DestroyNotify && xid != Fl_X11_Screen_Driver::xim_win && !fl_find(xid) && !xid_is_from_fltk_win) { // When using menus or tooltips: xid is a just hidden top-level FLTK win, xim_win is non-FLTK; // after XIM crash: xid is non-FLTK. // Trigger XIM crash under Debian: kill process containing "ibus-daemon" // Restart XIM after triggered crash: "ibus-daemon --panel disable --xim &" XIM xim_im; xim_im = XOpenIM(fl_display, NULL, NULL, NULL); if (!xim_im) { /* XIM server has crashed */ XSetLocaleModifiers(""); Fl_X11_Screen_Driver::xim_im = NULL; Fl_X11_Screen_Driver::init_xim(); } else { XCloseIM(xim_im); // see STR 2185 for comment } return 0; } if (Fl_X11_Screen_Driver::xim_ic && (xevent.type == FocusIn)) Fl_X11_Screen_Driver::xim_activate(xid); if (Fl_X11_Screen_Driver::xim_ic && XFilterEvent((XEvent *)&xevent, 0)) return(1); #if USE_XRANDR if( XRRUpdateConfiguration_f && xevent.type == randrEventBase + RRScreenChangeNotify) { XRRUpdateConfiguration_f(&xevent); react_to_screen_reconfiguration(); Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL); } #endif // USE_XRANDR if (xevent.type == PropertyNotify && xevent.xproperty.atom == fl_NET_WORKAREA) { Fl_X11_Screen_Driver *d = (Fl_X11_Screen_Driver*)Fl::screen_driver(); d->init_workarea(); #if USE_XFT after_display_rescale(&(d->current_xft_dpi)); #endif // USE_XFT } switch (xevent.type) { case KeymapNotify: memcpy(fl_key_vector, xevent.xkeymap.key_vector, 32); return 0; case MappingNotify: XRefreshKeyboardMapping((XMappingEvent*)&xevent.xmapping); return 0; case SelectionNotify: { static unsigned char* sn_buffer = 0; if (sn_buffer) { free(sn_buffer); sn_buffer = 0; } long bytesread = 0; if (fl_xevent->xselection.property) for (;;) { // The Xdnd code pastes 64K chunks together, possibly to avoid // bugs in X servers, or maybe to avoid an extra round-trip to // get the property length. I copy this here: Atom actual; int format; unsigned long count, remaining; unsigned char* portion = NULL; if (XGetWindowProperty(fl_display, fl_xevent->xselection.requestor, fl_xevent->xselection.property, bytesread/4, 65536, 1, AnyPropertyType, &actual, &format, &count, &remaining, &portion)) break; // quit on error if ((fl_xevent->xselection.property == PRIMARY_TIMESTAMP) || (fl_xevent->xselection.property == CLIPBOARD_TIMESTAMP)) { if (portion && format == 32 && count == 1) { Time t = *(unsigned int*)portion; if (fl_xevent->xselection.property == CLIPBOARD_TIMESTAMP) handle_clipboard_timestamp(1, t); else handle_clipboard_timestamp(0, t); } XFree(portion); return true; } if (actual == TARGETS || actual == XA_ATOM) { Atom type; if (Fl::e_clipboard_type == Fl::clipboard_image) { // searching for image data type = find_target_image((Atom *)portion, count); } else { // searching for text data. *FIXME* - there may be other data types! type = find_target_text((Atom *)portion, count); } XFree(portion); if (!type) { // not found if (Fl::e_clipboard_type == Fl::clipboard_image) return true; else type = fl_XaUtf8String; // text: try this anyway (was: XA_STRING) } // not found Atom property = xevent.xselection.property; XConvertSelection(fl_display, property, type, property, fl_xid(Fl::first_window()), fl_event_time); if (type == fl_XaImageBmp) { Fl::e_clipboard_type = Fl::clipboard_image; } else if (type == fl_XaImagePNG) { Fl::e_clipboard_type = Fl::clipboard_image; } else { Fl::e_clipboard_type = Fl::clipboard_plain_text; } return true; } if (actual == fl_INCR) { // From ICCCM: "The contents of the INCR property will be an integer, which // represents a lower bound on the number of bytes of data in the selection." // // However, some X clients don't set the integer ("lower bound") in the INCR // property, hence 'count' below is zero and we must not access '*portion'. // Debug: #if (0) fprintf(stderr, "[fl_handle(SelectionNotify/INCR):%d] actual=%ld (INCR), format=%d, count=%ld, remaining=%ld", __LINE__, actual, format, count, remaining); if (portion && count > 0) { fprintf(stderr, ", portion=%p (%ld)", portion, *(long*)portion); } fprintf(stderr, "\n"); #endif size_t lower_bound = 0; if (portion && count > 0) { lower_bound = *(unsigned long *)portion; } bytesread = getIncrData(sn_buffer, xevent.xselection, lower_bound); XFree(portion); break; } // Make sure we got something sane... if ((portion == NULL) || (format != 8) || (count == 0)) { if (portion) XFree(portion); return true; } sn_buffer = (unsigned char*)realloc(sn_buffer, bytesread+count+remaining+1); memcpy(sn_buffer + bytesread, portion, count); XFree(portion); bytesread += count; // Cannot trust data to be null terminated sn_buffer[bytesread] = '\0'; if (!remaining) break; } if (sn_buffer && Fl::e_clipboard_type == Fl::clipboard_plain_text) { sn_buffer[bytesread] = 0; convert_crlf(sn_buffer, bytesread); } if (!fl_selection_requestor) return 0; if (Fl::e_clipboard_type == Fl::clipboard_image) { if (bytesread == 0) return 0; static char tmp_fname[21]; static Fl_Shared_Image *shared = 0; strcpy(tmp_fname, "/tmp/clipboardXXXXXX"); int fd = mkstemp(tmp_fname); if (fd == -1) return 0; uchar *p = sn_buffer; ssize_t towrite = bytesread, written; while (towrite) { written = write(fd, p, towrite); p += written; towrite -= written; } close(fd); free(sn_buffer); sn_buffer = 0; shared = Fl_Shared_Image::get(tmp_fname); fl_unlink(tmp_fname); if (!shared) return 0; uchar *rgb = new uchar[shared->w() * shared->h() * shared->d()]; memcpy(rgb, shared->data()[0], shared->w() * shared->h() * shared->d()); Fl_RGB_Image *image = new Fl_RGB_Image(rgb, shared->w(), shared->h(), shared->d()); shared->release(); image->alloc_array = 1; Fl::e_clipboard_data = (void*)image; } else if (Fl::e_clipboard_type == Fl::clipboard_plain_text) { Fl::e_text = sn_buffer ? (char*)sn_buffer : (char *)""; Fl::e_length = bytesread; } int old_event = Fl::e_number; int retval = fl_selection_requestor->handle(Fl::e_number = FL_PASTE); if (!retval && Fl::e_clipboard_type == Fl::clipboard_image) { delete (Fl_RGB_Image*)Fl::e_clipboard_data; Fl::e_clipboard_data = NULL; } Fl::e_number = old_event; // Detect if this paste is due to Xdnd by the property name (I use // XA_SECONDARY for that) and send an XdndFinished message. // This has to be delayed until now rather than sending it immediately // after calling XConvertSelection because we need to send the success // status (retval) and the performed action to the sender - at least // since XDND protocol version 5 (see docs). // [FIXME: is the condition below really correct?] if (fl_xevent->xselection.property == XA_SECONDARY && fl_dnd_source_window) { fl_sendClientMessage(fl_dnd_source_window, // send to window fl_XdndFinished, // XdndFinished message fl_xevent->xselection.requestor, // data.l[0] target window retval ? 1 : 0, // data.l[1] Bit 0: 1 = success retval ? fl_dnd_action : None); // data.l[2] action performed fl_dnd_source_window = 0; // don't send a second time } return 1; } // SelectionNotify case SelectionClear: { int clipboard = fl_xevent->xselectionclear.selection == CLIPBOARD; fl_i_own_selection[clipboard] = 0; poll_clipboard_owner(); return 1; } case SelectionRequest: { XSelectionEvent e; e.type = SelectionNotify; e.requestor = fl_xevent->xselectionrequest.requestor; e.selection = fl_xevent->xselectionrequest.selection; int clipboard = e.selection == CLIPBOARD; e.target = fl_xevent->xselectionrequest.target; e.time = fl_xevent->xselectionrequest.time; e.property = fl_xevent->xselectionrequest.property; if (fl_selection_type[clipboard] == Fl::clipboard_plain_text) { if (e.target == TARGETS) { Atom a[3] = {fl_XaUtf8String, XA_STRING, fl_XaText}; XChangeProperty(fl_display, e.requestor, e.property, XA_ATOM, atom_bits, 0, (unsigned char*)a, 3); } else { if (fl_selection_length[clipboard]) { // data available if (e.target == fl_XaUtf8String || e.target == XA_STRING || e.target == fl_XaCompoundText || e.target == fl_XaText || e.target == fl_Xatextplain || e.target == fl_Xatextplainutf || e.target == fl_Xatextplainutf2) { // clobber the target type, this seems to make some applications // behave that insist on asking for XA_TEXT instead of UTF8_STRING // Does not change XA_STRING as that breaks xclipboard. if (e.target != XA_STRING) e.target = fl_XaUtf8String; XChangeProperty(fl_display, e.requestor, e.property, e.target, 8, 0, (unsigned char *)fl_selection_buffer[clipboard], fl_selection_length[clipboard]); } } else { // no data available e.property = 0; } } } else { // image in clipboard if (e.target == TARGETS) { Atom a[1] = {fl_XaImageBmp}; XChangeProperty(fl_display, e.requestor, e.property, XA_ATOM, atom_bits, 0, (unsigned char*)a, 1); } else { if (e.target == fl_XaImageBmp && fl_selection_length[clipboard]) { XChangeProperty(fl_display, e.requestor, e.property, e.target, 8, 0, (unsigned char *)fl_selection_buffer[clipboard], fl_selection_length[clipboard]); } else { e.property = 0; } } } XSendEvent(fl_display, e.requestor, 0, 0, (XEvent *)&e); return 1; } // SelectionRequest // events where interesting window id is in a different place: case CirculateNotify: case CirculateRequest: case ConfigureNotify: case ConfigureRequest: case CreateNotify: case DestroyNotify: case GravityNotify: case MapNotify: case MapRequest: case ReparentNotify: case UnmapNotify: xid = xevent.xmaprequest.window; break; } // switch (xevent.type) int event = 0; Fl_Window* window = fl_find(xid); if (window) switch (xevent.type) { case DestroyNotify: { // an X11 window was closed externally from the program Fl::handle(FL_CLOSE, window); Fl_X* X = Fl_X::flx(window); if (X) { // indicates the FLTK window was not closed X->xid = (Window)0; // indicates the X11 window was already destroyed window->hide(); int oldx = window->x(), oldy = window->y(); window->position(0, 0); window->position(oldx, oldy); window->show(); // recreate the X11 window in support of the FLTK window } return 1; } case ClientMessage: { Atom message = fl_xevent->xclient.message_type; const long* data = fl_xevent->xclient.data.l; if ((Atom)(data[0]) == WM_DELETE_WINDOW) { event = FL_CLOSE; } else if (message == fl_XdndEnter) { /* Excerpt from the XDND protocol at https://www.freedesktop.org/wiki/Specifications/XDND/ : - data.l[0] contains the XID of the source window. - data.l[1]: Bit 0 is set if the source supports more than three data types. The high byte contains the protocol version to use (minimum of the source's and target's highest supported versions). The rest of the bits are reserved for future use. - data.l[2,3,4] contain the first three types that the source supports. Unused slots are set to None. The ordering is arbitrary. If the Source supports more than three data types, bit 0 of data.l[1] is set. This tells the Target to check the property XdndTypeList on the Source window for the list of available types. This property should contain all the available types. BUT wayland gnome apps (e.g., gnome-text-editor) set bit 0 of data.l[1] even though their source supports 2 data types (UTF8 text + a gnome-specific type) and put None (==0) in each of data.l[2,3,4]. The same gnome apps run in X11 mode (GDK_BACKEND=x11) clear bit 0 of data.l[1] and support only UTF8 text announced in data.l[2]. FLTK wayland apps set bit 0 of data.l[1] and support only UTF8 text. Overall, the correct procedure is if (bit 0 of data.l[1] is set) { get the XdndTypeList property use all the data types it returns which can be in any number ≥ 1 } else { the source supports 1, 2 or 3 data types available at data.l[2,3,4] } */ #if FLTK_CONSOLIDATE_MOTION fl_xmousewin = window; #endif // FLTK_CONSOLIDATE_MOTION in_a_window = true; fl_dnd_source_window = data[0]; // version number is data[1]>>24 // fprintf(stderr, "XdndEnter, version %ld\n", data[1] >> 24); if (data[1]&1) { // get list of data types: Atom actual; int format; unsigned long count, remaining; unsigned char *cm_buffer = 0; XGetWindowProperty(fl_display, fl_dnd_source_window, fl_XdndTypeList, 0, 0x8000000L, False, XA_ATOM, &actual, &format, &count, &remaining, &cm_buffer); if (actual != XA_ATOM || format != 32 || count <= 0 || !cm_buffer) { if ( cm_buffer ) { XFree(cm_buffer); cm_buffer = 0; } goto FAILED; } delete [] fl_dnd_source_types; fl_dnd_source_types = new Atom[count+1]; for (unsigned i = 0; i < count; i++) { fl_dnd_source_types[i] = ((Atom*)cm_buffer)[i]; } fl_dnd_source_types[count] = 0; XFree(cm_buffer); cm_buffer = 0; } else { FAILED: // less than four data types, or if the above messes up: if (!fl_dnd_source_types) fl_dnd_source_types = new Atom[4]; fl_dnd_source_types[0] = data[2]; fl_dnd_source_types[1] = data[3]; fl_dnd_source_types[2] = data[4]; fl_dnd_source_types[3] = 0; } // Pick the "best" source (text) type... // *FIXME* what if we don't find a suitable type? (see below: first type?) // *FIXME* count (zero terminated) dnd sources (must be at least 1) int dnd_sources; for (dnd_sources = 0; fl_dnd_source_types[dnd_sources]; dnd_sources++) { // empty } fl_dnd_type = find_target_text(fl_dnd_source_types, dnd_sources); if (!fl_dnd_type) // not found: pick first type fl_dnd_type = fl_dnd_source_types[0]; event = FL_DND_ENTER; Fl::e_text = unknown; Fl::e_length = unknown_len; break; } else if (message == fl_XdndPosition) { #if FLTK_CONSOLIDATE_MOTION fl_xmousewin = window; #endif // FLTK_CONSOLIDATE_MOTION in_a_window = true; fl_dnd_source_window = data[0]; float s = 1; #if USE_XFT if (window) s = Fl::screen_driver()->scale(Fl_Window_Driver::driver(window)->screen_num()); #endif Fl::e_x_root = (data[2]>>16)/s; Fl::e_y_root = (data[2]&0xFFFF)/s; if (window) { Fl::e_x = Fl::e_x_root-window->x(); Fl::e_y = Fl::e_y_root-window->y(); } fl_event_time = data[3]; fl_dnd_source_action = data[4]; fl_dnd_action = fl_XdndActionCopy; Fl::e_text = unknown; Fl::e_length = unknown_len; int accept = Fl::handle(FL_DND_DRAG, window); fl_sendClientMessage(data[0], fl_XdndStatus, fl_xevent->xclient.window, accept ? 1 : 0, 0, // used for xy rectangle to not send position inside 0, // used for width+height of rectangle accept ? fl_dnd_action : None); return 1; } else if (message == fl_XdndLeave) { fl_dnd_source_window = 0; // don't send a finished message to it event = FL_DND_LEAVE; Fl::e_text = unknown; Fl::e_length = unknown_len; break; } else if (message == fl_XdndDrop) { #if FLTK_CONSOLIDATE_MOTION fl_xmousewin = window; #endif // FLTK_CONSOLIDATE_MOTION in_a_window = true; fl_dnd_source_window = data[0]; fl_event_time = data[2]; Window to_window = fl_xevent->xclient.window; Fl::e_text = unknown; Fl::e_length = unknown_len; if (Fl::handle(FL_DND_RELEASE, window)) { fl_selection_requestor = Fl::belowmouse(); Fl::e_clipboard_type = Fl::clipboard_plain_text; XConvertSelection(fl_display, fl_XdndSelection, fl_dnd_type, XA_SECONDARY, to_window, fl_event_time); } else { // Send the finished message if I refuse the drop. // It is not clear whether I can just send finished always, // or if I have to wait for the SelectionNotify event as the // code is currently doing. fl_sendClientMessage(fl_dnd_source_window, fl_XdndFinished, to_window); fl_dnd_source_window = 0; } return 1; } break; } // case ClientMessage case UnmapNotify: event = FL_HIDE; break; case Expose: Fl_Window_Driver::driver(window)->wait_for_expose_value = 0; # if 0 // try to keep windows on top even if WM_TRANSIENT_FOR does not work: // opaque move/resize window managers do not like this, so I disabled it. if (Fl::first_window()->non_modal() && window != Fl::first_window()) Fl::first_window()->show(); # endif case GraphicsExpose: { #if USE_XFT int ns = Fl_Window_Driver::driver(window)->screen_num(); float s = Fl::screen_driver()->scale(ns); window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x/s, xevent.xexpose.y/s, xevent.xexpose.width/s + 2, xevent.xexpose.height/s + 2); #else window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x, xevent.xexpose.y, xevent.xexpose.width, xevent.xexpose.height); #endif } return 1; case FocusIn: if (Fl_X11_Screen_Driver::xim_ic) XSetICFocus(Fl_X11_Screen_Driver::xim_ic); event = FL_FOCUS; // If the user has toggled from another application to this one, // then it's a good time to check for clipboard changes. poll_clipboard_owner(); break; case FocusOut: if (Fl_X11_Screen_Driver::xim_ic) XUnsetICFocus(Fl_X11_Screen_Driver::xim_ic); event = FL_UNFOCUS; break; case KeyPress: case KeyRelease: { KEYPRESS: int keycode = xevent.xkey.keycode; fl_key_vector[keycode/8] |= (1 << (keycode%8)); static char *kp_buffer = NULL; static int kp_buffer_len = 0; KeySym keysym; if (kp_buffer_len == 0) { kp_buffer_len = 4096; kp_buffer = (char*) malloc(kp_buffer_len); } if (xevent.type == KeyPress) { event = FL_KEYDOWN; int len; if (Fl_X11_Screen_Driver::xim_ic) { Status status; len = XUtf8LookupString(Fl_X11_Screen_Driver::xim_ic, (XKeyPressedEvent *)&xevent.xkey, kp_buffer, kp_buffer_len, &keysym, &status); while (status == XBufferOverflow && kp_buffer_len < 50000) { kp_buffer_len = kp_buffer_len * 5 + 1; kp_buffer = (char*)realloc(kp_buffer, kp_buffer_len); len = XUtf8LookupString(Fl_X11_Screen_Driver::xim_ic, (XKeyPressedEvent *)&xevent.xkey, kp_buffer, kp_buffer_len, &keysym, &status); } keysym = fl_KeycodeToKeysym(fl_display, keycode, 0); } else { //static XComposeStatus compose; len = XLookupString((XKeyEvent*)&(xevent.xkey), kp_buffer, kp_buffer_len, &keysym, 0/*&compose*/); if (keysym && keysym < 0x400) { // a character in latin-1,2,3,4 sets // force it to type a character (not sure if this ever is needed): // if (!len) {kp_buffer[0] = char(keysym); len = 1;} len = fl_utf8encode(XKeysymToUcs(keysym), kp_buffer); if (len < 1) len = 1; // ignore all effects of shift on the keysyms, which makes it a lot // easier to program shortcuts and is Windoze-compatible: keysym = fl_KeycodeToKeysym(fl_display, keycode, 0); } } kp_buffer[len] = 0; Fl::e_text = kp_buffer; Fl::e_length = len; } else { // Stupid X sends fake key-up events when a repeating key is held // down, probably due to some back compatibility problem. Fortunately // we can detect this because the repeating KeyPress event is in // the queue, get it and execute it instead: // Bool XkbSetDetectableAutoRepeat ( display, detectable, supported_rtrn ) // Display * display ; // Bool detectable ; // Bool * supported_rtrn ; // ...would be the easy way to correct this issue. Unfortunately, this call is also // broken on many Unix distros including Ubuntu and Solaris (as of Dec 2009) // Bogus KeyUp events are generated by repeated KeyDown events. One // necessary condition is an identical key event pending right after // the bogus KeyUp. // The new code introduced Dec 2009 differs in that it only checks the very // next event in the queue, not the entire queue of events. // This function wrongly detects a repeat key if a software keyboard // sends a burst of events containing two consecutive equal keys. However, // in every non-gaming situation, this is no problem because both KeyPress // events will cause the expected behavior. XEvent peekevent; if (XPending(fl_display)) { XPeekEvent(fl_display, &peekevent); if ( (peekevent.type == KeyPress) // must be a KeyPress event && (peekevent.xkey.keycode == xevent.xkey.keycode) // must be the same key && (peekevent.xkey.time == xevent.xkey.time) // must be sent at the exact same time ) { XNextEvent(fl_display, &xevent); goto KEYPRESS; } } event = FL_KEYUP; fl_key_vector[keycode/8] &= ~(1 << (keycode%8)); // keyup events just get the unshifted keysym: keysym = fl_KeycodeToKeysym(fl_display, keycode, 0); } # ifdef __sgi // You can plug a microsoft keyboard into an sgi but the extra shift // keys are not translated. Make them translate like XFree86 does: if (!keysym) switch(keycode) { case 147: keysym = FL_Meta_L; break; case 148: keysym = FL_Meta_R; break; case 149: keysym = FL_Menu; break; } # endif # ifdef BACKSPACE_HACK // Attempt to fix keyboards that send "delete" for the key in the // upper-right corner of the main keyboard. But it appears that // very few of these remain? static int got_backspace = 0; if (!got_backspace) { if (keysym == FL_Delete) keysym = FL_BackSpace; else if (keysym == FL_BackSpace) got_backspace = 1; } # endif // For the first few years, there wasn't a good consensus on what the // Windows keys should be mapped to for X11. So we need to help out a // bit and map all variants to the same FLTK key... switch (keysym) { case XK_Meta_L: case XK_Hyper_L: case XK_Super_L: keysym = FL_Meta_L; break; case XK_Meta_R: case XK_Hyper_R: case XK_Super_R: keysym = FL_Meta_R; break; } // Convert the multimedia keys to safer, portable values switch (keysym) { // XF names come from X11/XF86keysym.h case 0x1008FF11: // XF86XK_AudioLowerVolume: keysym = FL_Volume_Down; break; case 0x1008FF12: // XF86XK_AudioMute: keysym = FL_Volume_Mute; break; case 0x1008FF13: // XF86XK_AudioRaiseVolume: keysym = FL_Volume_Up; break; case 0x1008FF14: // XF86XK_AudioPlay: keysym = FL_Media_Play; break; case 0x1008FF15: // XF86XK_AudioStop: keysym = FL_Media_Stop; break; case 0x1008FF16: // XF86XK_AudioPrev: keysym = FL_Media_Prev; break; case 0x1008FF17: // XF86XK_AudioNext: keysym = FL_Media_Next; break; case 0x1008FF18: // XF86XK_HomePage: keysym = FL_Home_Page; break; case 0x1008FF19: // XF86XK_Mail: keysym = FL_Mail; break; case 0x1008FF1B: // XF86XK_Search: keysym = FL_Search; break; case 0x1008FF26: // XF86XK_Back: keysym = FL_Back; break; case 0x1008FF27: // XF86XK_Forward: keysym = FL_Forward; break; case 0x1008FF28: // XF86XK_Stop: keysym = FL_Stop; break; case 0x1008FF29: // XF86XK_Refresh: keysym = FL_Refresh; break; case 0x1008FF2F: // XF86XK_Sleep: keysym = FL_Sleep; break; case 0x1008FF30: // XF86XK_Favorites: keysym = FL_Favorites; break; } // Special processing for number keys == keycodes 10-19 // necessary to support keyboard layouts with digits in uppercase : if (keycode >= 10 && keycode <= 18) { keysym = '1' + (keycode - 10); } else if (keycode == 19) { keysym = '0'; } // We have to get rid of the XK_KP_function keys, because they are // not produced on Windoze and thus case statements tend not to check // for them. There are 15 of these in the range 0xff91 ... 0xff9f if (keysym >= 0xff91 && keysym <= 0xff9f) { // Map keypad keysym to character or keysym depending on // numlock state... unsigned long keysym1 = fl_KeycodeToKeysym(fl_display, keycode, 1); if (keysym1 <= 0x7f || (keysym1 > 0xff9f && keysym1 <= FL_KP_Last)) Fl::e_original_keysym = (int)(keysym1 | FL_KP); if ((xevent.xkey.state & Mod2Mask) && (keysym1 <= 0x7f || (keysym1 > 0xff9f && keysym1 <= FL_KP_Last))) { // Store ASCII numeric keypad value... keysym = keysym1 | FL_KP; kp_buffer[0] = char(keysym1) & 0x7F; // len = 1; } else { // Map keypad to special key... static const unsigned short table[15] = { FL_F+1, FL_F+2, FL_F+3, FL_F+4, FL_Home, FL_Left, FL_Up, FL_Right, FL_Down, FL_Page_Up, FL_Page_Down, FL_End, 0xff0b/*XK_Clear*/, FL_Insert, FL_Delete}; keysym = table[keysym-0xff91]; } } else { // Store this so we can later know if the KP was used Fl::e_original_keysym = (int)keysym; } Fl::e_keysym = int(keysym); // replace XK_ISO_Left_Tab (Shift-TAB) with FL_Tab (modifier flags are set correctly by X11) if (Fl::e_keysym == 0xfe20) Fl::e_keysym = FL_Tab; set_event_xy(window); Fl::e_is_click = 0; } break; // Mouse button "press" event: // --------------------------- // X11 uses special conventions for mouse "button" numbers: // 1-3: standard mouse buttons left, middle, right in this order // 4-5: scroll wheel up, down - not reflected in Fl::event_state() // 6-7: scroll wheel left, right - not reflected in Fl::event_state() // 8-9: side buttons back, forward - mapped to 4-5, see below // Since X11 pseudo button numbers 4-7 are useless for Fl::event_state() we map // real button numbers 8 and 9 to 4 and 5, respectively in FLTK's button numbers // and in the event state (Fl::event_state()). // Variable `xbutton_state` is used internally to store the status of the extra // mouse buttons 4 (back) and 5 (forward) since X11 doesn't keep their status. case ButtonPress: { int mb = xevent.xbutton.button; // mouse button if (mb < 1 || mb > 9) return 0; // unknown or unsupported button, ignore // FIXME(?): here we set some event related variables although we *might* // ignore an event sent by X because we don't know or want it. This may lead to // inconsistencies in Fl::event_key(), Fl::event_state() and more (see set_event_xy). // For now we ignore this fact though, it's likely that it never happens. // Albrecht, Sep 27, 2024 Fl::e_keysym = 0; // init: not used (zero) for scroll wheel events set_event_xy(window); Fl::e_dx = Fl::e_dy = 0; if (mb == Button4 && !Fl::event_shift()) { Fl::e_dy = -1; // up event = FL_MOUSEWHEEL; } else if (mb == Button5 && !Fl::event_shift()) { Fl::e_dy = +1; // down event = FL_MOUSEWHEEL; } else if (mb == 6 || (mb == Button4 && Fl::event_shift())) { Fl::e_dx = -1; // left event = FL_MOUSEWHEEL; } else if (mb == 7 || (mb == Button5 && Fl::event_shift())) { Fl::e_dx = +1; // right event = FL_MOUSEWHEEL; } else if (mb < 4 || mb > 7) { // real mouse *buttons*, not scroll wheel if (mb > 7) // 8 = back, 9 = forward mb -= 4; // map to 4 and 5, resp. Fl::e_keysym = FL_Button + mb; Fl::e_state |= (FL_BUTTON1 << (mb-1)); // set button state if (mb == 4) xbutton_state |= FL_BUTTON4; // save extra button state internally if (mb == 5) xbutton_state |= FL_BUTTON5; // save extra button state internally event = FL_PUSH; checkdouble(); } else { // unknown button or shift combination return 0; } #if FLTK_CONSOLIDATE_MOTION fl_xmousewin = window; #endif // FLTK_CONSOLIDATE_MOTION in_a_window = true; break; } // ButtonPress // Mouse button release event: for details see ButtonPress above case ButtonRelease: { int mb = xevent.xbutton.button; // mouse button switch (mb) { // figure out which real button this is case 1: // left case 2: // middle case 3: // right break; // continue case 8: // side button 1 (back) case 9: // side button 2 (forward) mb -= 4; // map to 4 and 5, respectively break; // continue default: // unknown button or scroll wheel: return 0; // don't send FL_RELEASE event } Fl::e_keysym = FL_Button + mb; // == FL_BUTTON1 .. FL_BUTTON5 set_event_xy(window); Fl::e_state &= ~(FL_BUTTON1 << (mb-1)); if (mb == 4) xbutton_state &= ~FL_BUTTON4; // clear internal button state if (mb == 5) xbutton_state &= ~FL_BUTTON5; // clear internal button state event = FL_RELEASE; #if FLTK_CONSOLIDATE_MOTION fl_xmousewin = window; #endif // FLTK_CONSOLIDATE_MOTION in_a_window = true; break; } // ButtonRelease case PropertyNotify: if (xevent.xproperty.atom == fl_NET_WM_STATE) { int fullscreen_state = 0; int maximize_state = 0; if (xevent.xproperty.state != PropertyDelete) { unsigned long nitems; unsigned long *words = 0; if (0 == get_xwinprop(xid, fl_NET_WM_STATE, 64, &nitems, &words) ) { for (unsigned long item = 0; item < nitems; item++) { if (words[item] == fl_NET_WM_STATE_FULLSCREEN) { fullscreen_state = 1; } if (words[item] == fl_NET_WM_STATE_MAXIMIZED_HORZ) { maximize_state = 1; } } } if ( words ) { XFree(words); words = 0; } } Fl_Window_Driver::driver(window)->is_maximized(maximize_state); if (window->fullscreen_active() && !fullscreen_state) { window->_clear_fullscreen(); event = FL_FULLSCREEN; } if (!window->fullscreen_active() && fullscreen_state) { window->_set_fullscreen(); event = FL_FULLSCREEN; } } break; case MotionNotify: set_event_xy(window); in_a_window = true; # if FLTK_CONSOLIDATE_MOTION send_motion = fl_xmousewin = window; return 0; # else event = FL_MOVE; break; # endif case EnterNotify: if (xevent.xcrossing.detail == NotifyInferior) break; // XInstallColormap(fl_display, Fl_X::flx(window)->colormap); set_event_xy(window); Fl::e_state = xevent.xcrossing.state << 16; event = FL_ENTER; #if FLTK_CONSOLIDATE_MOTION fl_xmousewin = window; #endif // FLTK_CONSOLIDATE_MOTION in_a_window = true; { XIMStyles *xim_styles = NULL; if(!Fl_X11_Screen_Driver::xim_im || XGetIMValues(Fl_X11_Screen_Driver::xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL)) { Fl_X11_Screen_Driver::init_xim(); } if (xim_styles) XFree(xim_styles); } break; case LeaveNotify: if (xevent.xcrossing.detail == NotifyInferior) break; set_event_xy(window); Fl::e_state = xevent.xcrossing.state << 16; #if FLTK_CONSOLIDATE_MOTION fl_xmousewin = 0; #endif // FLTK_CONSOLIDATE_MOTION in_a_window = false; // make do_queued_events produce FL_LEAVE event return 0; // We cannot rely on the x,y position in the configure notify event. // I now think this is an unavoidable problem with X: it is impossible // for a window manager to prevent the "real" notify event from being // sent when it resizes the contents, even though it can send an // artificial event with the correct position afterwards (and some // window managers do not send this fake event anyway) // So anyway, do a round trip to find the correct x,y: case MapNotify: event = FL_SHOW; case ConfigureNotify: { if (window->parent()) break; // ignore child windows // figure out where OS really put window XWindowAttributes actual; XGetWindowAttributes(fl_display, fl_xid(window), &actual); Window cr; int X, Y, W = actual.width, H = actual.height; XTranslateCoordinates(fl_display, fl_xid(window), actual.root, 0, 0, &X, &Y, &cr); #if USE_XFT // detect when window centre changes screen Fl_X11_Screen_Driver *d = (Fl_X11_Screen_Driver*)Fl::screen_driver(); Fl_X11_Window_Driver *wd = Fl_X11_Window_Driver::driver(window); int olds = wd->screen_num(); int num = d->screen_num_unscaled(X+ actual.width/2, Y +actual.height/2); if (num == -1) num = olds; float s = d->scale(num); if (num != olds) { if (s != d->scale(olds) && !Fl_X11_Window_Driver::data_for_resize_window_between_screens_.busy && window->user_data() != &Fl_X11_Screen_Driver::transient_scale_display) { Fl_X11_Window_Driver::data_for_resize_window_between_screens_.busy = true; Fl_X11_Window_Driver::data_for_resize_window_between_screens_.screen = num; // resize_after_screen_change() works also if called here, but calling it // a second later gives a more pleasant user experience when moving windows between distinct screens Fl::add_timeout(1, Fl_X11_Window_Driver::resize_after_screen_change, window); } else if (!Fl_X11_Window_Driver::data_for_resize_window_between_screens_.busy) wd->screen_num(num); } else if (Fl_X11_Window_Driver::data_for_resize_window_between_screens_.busy) { Fl::remove_timeout(Fl_X11_Window_Driver::resize_after_screen_change, window); Fl_X11_Window_Driver::data_for_resize_window_between_screens_.busy = false; } #else // ! USE_XFT Fl_Window_Driver::driver(window)->screen_num( Fl::screen_num(X, Y, W, H) ); #endif // USE_XFT // tell Fl_Window about it and set flag to prevent echoing: resize_bug_fix = window; #if USE_XFT if (!Fl_X11_Window_Driver::data_for_resize_window_between_screens_.busy && ( ceil(W/s) != window->w() || ceil(H/s) != window->h() ) ) { window->resize(rint(X/s), rint(Y/s), ceil(W/s), ceil(H/s)); } else { window->position(rint(X/s), rint(Y/s)); } #else window->resize(X, Y, W, H); #endif break; // allow add_handler to do something too } case ReparentNotify: { int xpos, ypos; Window junk; // on some systems, the ReparentNotify event is not handled as we would expect. XErrorHandler oldHandler = XSetErrorHandler(catchXExceptions()); //ReparentNotify gives the new position of the window relative to //the new parent. FLTK cares about the position on the root window. XTranslateCoordinates(fl_display, xevent.xreparent.parent, XRootWindow(fl_display, fl_screen), xevent.xreparent.x, xevent.xreparent.y, &xpos, &ypos, &junk); XSetErrorHandler(oldHandler); // tell Fl_Window about it and set flag to prevent echoing: if ( !wasXExceptionRaised() ) { resize_bug_fix = window; #if USE_XFT int ns = Fl_Window_Driver::driver(window)->screen_num(); float s = Fl::screen_driver()->scale(ns); #else float s = 1; #endif window->position(rint(xpos/s), rint(ypos/s)); } break; } // ReparentNotify } // if (window) switch (xevent.type) #if HAVE_XFIXES switch (xevent.type - xfixes_event_base) { case XFixesSelectionNotify: { // Someone feeding us bogus events? if (!have_xfixes) return true; XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)&xevent; if ((selection_notify->selection == XA_PRIMARY) && !fl_i_own_selection[0]) handle_clipboard_timestamp(0, selection_notify->selection_timestamp); else if ((selection_notify->selection == CLIPBOARD) && !fl_i_own_selection[1]) handle_clipboard_timestamp(1, selection_notify->selection_timestamp); return true; } } #endif return Fl::handle(event, window); } //////////////////////////////////////////////////////////////// void Fl_X11_Window_Driver::resize(int X,int Y,int W,int H) { int is_a_rescale = Fl_Window::is_a_rescale(); int is_a_move = (X != x() || Y != y() || is_a_rescale); int is_a_resize = (W != w() || H != h() || is_a_rescale); int resize_from_program = (pWindow != resize_bug_fix); if (!resize_from_program) resize_bug_fix = 0; if (is_a_move && resize_from_program) force_position(1); else if (!is_a_resize && !is_a_move) return; if (is_a_resize) { if (pWindow->as_double_window() && pWindow->parent()) { if (W < 1) W = 1; if (H < 1) H = 1; } pWindow->Fl_Group::resize(X,Y,W,H); if (shown()) { #if FLTK_USE_CAIRO if (!pWindow->as_gl_window() && cairo_) { float s = Fl::screen_driver()->scale(screen_num()); cairo_xlib_surface_set_size(cairo_get_target(cairo_), (W>0 ? int(W*s) : 1), (H>0 ? int(H*s) : 1)); } #endif pWindow->redraw(); } } else { x(X); y(Y); if (Fl_X11_Screen_Driver::xim_win && Fl::focus()) { // Force the Input Method auxiliary window to move too. Fl::focus()->handle(FL_FOCUS); fl_set_spot(fl_font(), fl_size(), Fl::focus()->x(), Fl::focus()->y() + fl_size(), Fl::focus()->w(), Fl::focus()->h(), NULL); } } if (is_a_rescale) size_range(); if (resize_from_program && shown()) { float s = Fl::screen_driver()->scale(screen_num()); if (is_a_resize) { if (!is_resizable()) pWindow->size_range(w(),h(),w(),h()); if (is_a_move) { XMoveResizeWindow(fl_display, fl_xid(pWindow), rint(X*s), rint(Y*s), W>0 ? W*s : 1, H>0 ? H*s : 1); } else { XResizeWindow(fl_display, fl_xid(pWindow), W>0 ? W*s : 1, H>0 ? H*s : 1); } } else XMoveWindow(fl_display, fl_xid(pWindow), rint(X*s), rint(Y*s)); } } //////////////////////////////////////////////////////////////// #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ #define _NET_WM_STATE_ADD 1 /* add/set property */ #define _NET_WM_STATE_TOGGLE 2 /* toggle property */ static void send_wm_event(Window wnd, Atom message, unsigned long d0, unsigned long d1=0, unsigned long d2=0, unsigned long d3=0, unsigned long d4=0) { XEvent e; e.xany.type = ClientMessage; e.xany.window = wnd; e.xclient.message_type = message; e.xclient.format = 32; e.xclient.data.l[0] = d0; e.xclient.data.l[1] = d1; e.xclient.data.l[2] = d2; e.xclient.data.l[3] = d3; e.xclient.data.l[4] = d4; XSendEvent(fl_display, RootWindow(fl_display, fl_screen), 0, SubstructureNotifyMask | SubstructureRedirectMask, &e); } static void send_wm_state_event(Window wnd, int add, Atom prop) { send_wm_event(wnd, fl_NET_WM_STATE, add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE, prop); } int Fl_X11_Screen_Driver::ewmh_supported() { static int result = -1; if (result == -1) { fl_open_display(); result = 0; unsigned long nitems; unsigned long *words = 0; if (0 == get_xwinprop(XRootWindow(fl_display, fl_screen), fl_NET_SUPPORTING_WM_CHECK, 64, &nitems, &words) && nitems == 1) { Window child = words[0]; if ( words ) { XFree(words); words = 0; } if (0 == get_xwinprop(child, fl_NET_SUPPORTING_WM_CHECK, 64, &nitems, &words) ) { if ( nitems == 1) result = (child == words[0]); } } if ( words ) { XFree(words); words = 0; } } return result; } #if HAVE_XRENDER && (!FLTK_USE_CAIRO) static int xrender_supported() { int nop1, nop2; fl_open_display(); return XRenderQueryExtension(fl_display, &nop1, &nop2); } #endif #if ! FLTK_USE_CAIRO char Fl_Xlib_Graphics_Driver::can_do_alpha_blending() { #if HAVE_XRENDER static char result = (char)xrender_supported(); return result; #else return 0; #endif } #endif extern Fl_Window *fl_xfocus; void Fl_X11_Window_Driver::activate_window() { Window w = fl_xid(pWindow); if (!Fl_X11_Screen_Driver::ewmh_supported()) return; Window prev = 0; if (fl_xfocus) { Fl_X *x = Fl_X::flx(fl_xfocus); if (!x) return; prev = x->xid; } send_wm_event(w, fl_NET_ACTIVE_WINDOW, 1, // source: 1 = application fl_event_time, // time of client's last user activity (STR 3396) prev); // previously active window } /* Change an existing window to fullscreen */ void Fl_X11_Window_Driver::fullscreen_on() { pWindow->_set_fullscreen(); if (Fl_X11_Screen_Driver::ewmh_supported()) { int top, bottom, left, right; top = fullscreen_screen_top(); bottom = fullscreen_screen_bottom(); left = fullscreen_screen_left(); right = fullscreen_screen_right(); if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) { top = screen_num(); bottom = top; left = top; right = top; } send_wm_event(fl_xid(pWindow), fl_NET_WM_FULLSCREEN_MONITORS, top, bottom, left, right); send_wm_state_event(fl_xid(pWindow), 1, fl_NET_WM_STATE_FULLSCREEN); } else { hide(); show(); /* We want to grab the window, not a widget, so we cannot use Fl::grab */ XGrabKeyboard(fl_display, fl_xid(pWindow), 1, GrabModeAsync, GrabModeAsync, fl_event_time); Fl::handle(FL_FULLSCREEN, pWindow); } } void Fl_X11_Window_Driver::fullscreen_off(int X, int Y, int W, int H) { pWindow->_clear_fullscreen(); if (Fl_X11_Screen_Driver::ewmh_supported()) { send_wm_state_event(fl_xid(pWindow), 0, fl_NET_WM_STATE_FULLSCREEN); } else { /* The grab will be lost when the window is destroyed */ hide(); resize(X,Y,W,H); show(); Fl::handle(FL_FULLSCREEN, pWindow); } } void Fl_X11_Window_Driver::maximize() { if (Fl_X11_Screen_Driver::ewmh_supported()) { send_wm_event(fl_xid(pWindow), fl_NET_WM_STATE, _NET_WM_STATE_ADD, fl_NET_WM_STATE_MAXIMIZED_VERT, fl_NET_WM_STATE_MAXIMIZED_HORZ); } else { Fl_Window_Driver::maximize(); } } void Fl_X11_Window_Driver::un_maximize() { if (Fl_X11_Screen_Driver::ewmh_supported()) { send_wm_event(fl_xid(pWindow), fl_NET_WM_STATE, _NET_WM_STATE_REMOVE, fl_NET_WM_STATE_MAXIMIZED_VERT, fl_NET_WM_STATE_MAXIMIZED_HORZ); } else { Fl_Window_Driver::un_maximize(); } } //////////////////////////////////////////////////////////////// // A subclass of Fl_Window may call this to associate an X window it // creates with the Fl_Window: void fl_fix_focus(); // in Fl.cxx Fl_X* Fl_X::set_xid(Fl_Window* win, Window winxid) { if (!win->parent()) add_xid_vector(winxid); // store xid's of top-level FLTK windows Fl_X *xp = new Fl_X; xp->xid = winxid; Fl_Window_Driver::driver(win)->other_xid = 0; xp->w = win; win->flx_ = xp; xp->next = Fl_X::first; xp->region = 0; Fl_Window_Driver::driver(win)->wait_for_expose_value = 1; Fl_X::first = xp; if (win->modal()) {Fl::modal_ = win; fl_fix_focus();} return xp; } // More commonly a subclass calls this, because it hides the really // ugly parts of X and sets all the stuff for a window that is set // normally. The global variables like fl_show_iconic are so that // subclasses of *that* class may change the behavior... int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR static const int childEventMask = ExposureMask; static const int XEventMask = ExposureMask|StructureNotifyMask |KeyPressMask|KeyReleaseMask|KeymapStateMask|FocusChangeMask |ButtonPressMask|ButtonReleaseMask |EnterWindowMask|LeaveWindowMask |PropertyChangeMask |PointerMotionMask; void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) { Fl_Group::current(0); // get rid of very common user bug: forgot end() int X = win->x(); int Y = win->y(); int W = win->w(); if (W <= 0) W = 1; // X don't like zero... int H = win->h(); if (H <= 0) H = 1; // X don't like zero... if (!win->parent() && !Fl::grab()) { // center windows in case window manager does not do anything: #ifdef FL_CENTER_WINDOWS if (!win->force_position()) { win->x(X = scr_x+(scr_w-W)/2); win->y(Y = scr_y+(scr_h-H)/2); } #endif // FL_CENTER_WINDOWS // force the window to be on-screen. Usually the X window manager // does this, but a few don't, so we do it here for consistency: int scr_x, scr_y, scr_w, scr_h; Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y, W, H); if (win->border()) { // ensure border is on screen: // (assume extremely minimal dimensions for this border) const int top = 20; const int left = 1; const int right = 1; const int bottom = 1; if (X+W+right > scr_x+scr_w) X = scr_x+scr_w-right-W; if (X-left < scr_x) X = scr_x+left; if (Y+H+bottom > scr_y+scr_h) Y = scr_y+scr_h-bottom-H; if (Y-top < scr_y) Y = scr_y+top; } // now insure contents are on-screen (more important than border): if (X+W > scr_x+scr_w) X = scr_x+scr_w-W; if (X < scr_x) X = scr_x; if (Y+H > scr_y+scr_h) Y = scr_y+scr_h-H; if (Y < scr_y) Y = scr_y; } // if the window is a subwindow and our parent is not mapped yet, we // mark this window visible, so that mapping the parent at a later // point in time will call this function again to finally map the subwindow. if (win->parent() && !Fl_X::flx(win->window())) { win->set_visible(); return; } // Compute which screen(s) we should be on if we want to go fullscreen int fullscreen_top, fullscreen_bottom, fullscreen_left, fullscreen_right; fullscreen_top = win->fullscreen_screen_top; fullscreen_bottom = win->fullscreen_screen_bottom; fullscreen_left = win->fullscreen_screen_left; fullscreen_right = win->fullscreen_screen_right; if ((fullscreen_top < 0) || (fullscreen_bottom < 0) || (fullscreen_left < 0) || (fullscreen_right < 0)) { fullscreen_top = Fl::screen_num(X, Y, W, H); fullscreen_bottom = fullscreen_top; fullscreen_left = fullscreen_top; fullscreen_right = fullscreen_top; } ulong root = win->parent() ? fl_xid(win->window()) : RootWindow(fl_display, fl_screen); XSetWindowAttributes attr; int mask = CWBorderPixel|CWColormap|CWEventMask|CWBitGravity; attr.event_mask = win->parent() ? childEventMask : XEventMask; attr.colormap = colormap; attr.border_pixel = 0; attr.bit_gravity = 0; // StaticGravity; if (win->override()) { attr.override_redirect = 1; attr.save_under = 1; mask |= CWOverrideRedirect | CWSaveUnder; } else attr.override_redirect = 0; if (Fl::grab()) { attr.save_under = 1; mask |= CWSaveUnder; if (!win->border()) {attr.override_redirect = 1; mask |= CWOverrideRedirect;} } // For the non-EWMH fullscreen case, we cannot use the code above, // since we do not want save_under, do not want to turn off the // border, and cannot grab without an existing window. Besides, // there is no clear_override(). if (win->fullscreen_active() && !Fl_X11_Screen_Driver::ewmh_supported()) { int sx, sy, sw, sh; attr.override_redirect = 1; mask |= CWOverrideRedirect; Fl::screen_xywh(sx, sy, sw, sh, fullscreen_left); X = sx; Fl::screen_xywh(sx, sy, sw, sh, fullscreen_right); W = sx + sw - X; Fl::screen_xywh(sx, sy, sw, sh, fullscreen_top); Y = sy; Fl::screen_xywh(sx, sy, sw, sh, fullscreen_bottom); H = sy + sh - Y; } #ifdef ENABLE_BOXCHEAT if (fl_background_pixel >= 0) { attr.background_pixel = fl_background_pixel; fl_background_pixel = -1; mask |= CWBackPixel; } #endif // (ENABLE_BOXCHEAT) float s = 1; #if USE_XFT //compute adequate screen where to put the window int nscreen = 0; if (win->parent()) { nscreen = Fl_Window_Driver::driver(win->top_window())->screen_num(); } else if (win->force_position() && Fl_X11_Window_Driver::driver(win)->screen_num_ >= 0) { nscreen = Fl_Window_Driver::driver(win)->screen_num(); } else { Fl_Window *hint = Fl::first_window(); if (hint) { nscreen = Fl_Window_Driver::driver(hint->top_window())->screen_num(); } } Fl_X11_Window_Driver::driver(win)->screen_num(nscreen); s = Fl::screen_driver()->scale(nscreen); // if (!win->parent()) printf("win creation on screen #%d\n", nscreen); #endif Fl_X* xp = set_xid(win, XCreateWindow(fl_display, root, rint(X*s), rint(Y*s), W*s, H*s, 0, // borderwidth visual->depth, InputOutput, visual->visual, mask, &attr)); int showit = 1; // Set WM_CLIENT_MACHINE and WM_LOCALE_NAME XSetWMProperties(fl_display, xp->xid, NULL, NULL, NULL, 0, NULL, NULL, NULL); // Set _NET_WM_PID long pid; pid = getpid(); XChangeProperty(fl_display, xp->xid, fl_NET_WM_PID, XA_CARDINAL, 32, 0, (unsigned char *)&pid, 1); if (!win->parent() && !attr.override_redirect) { // Communicate all kinds 'o junk to the X Window Manager: win->label(win->label(), win->iconlabel()); XChangeProperty(fl_display, xp->xid, WM_PROTOCOLS, XA_ATOM, 32, 0, (uchar*)&WM_DELETE_WINDOW, 1); // send size limits and border: Fl_X11_Window_Driver::driver(win)->sendxjunk(); // set the class property, which controls the icon used: if (win->xclass()) { char buffer[1024]; const char *xclass = win->xclass(); const int len = strlen(xclass); // duplicate the xclass string for use as XA_WM_CLASS strcpy(buffer, xclass); strcpy(buffer + len + 1, xclass); // create the capitalized version: buffer[len + 1] = toupper(buffer[len + 1]); if (buffer[len + 1] == 'X') buffer[len + 2] = toupper(buffer[len + 2]); XChangeProperty(fl_display, xp->xid, XA_WM_CLASS, XA_STRING, 8, 0, (unsigned char *)buffer, len * 2 + 2); } if (win->non_modal() && xp->next && !fl_disable_transient_for) { // find some other window to be "transient for": Fl_Window* wp = xp->next->w; while (wp->parent()) wp = wp->window(); XSetTransientForHint(fl_display, xp->xid, fl_xid(wp)); if (!wp->visible()) showit = 0; // guess that wm will not show it if (win->modal()) { Atom net_wm_state = XInternAtom (fl_display, "_NET_WM_STATE", 0); Atom net_wm_state_skip_taskbar = XInternAtom (fl_display, "_NET_WM_STATE_MODAL", 0); XChangeProperty (fl_display, xp->xid, net_wm_state, XA_ATOM, 32, PropModeAppend, (unsigned char*) &net_wm_state_skip_taskbar, 1); } } // Make sure that borderless windows do not show in the task bar if (!win->border()) { Atom net_wm_state = XInternAtom (fl_display, "_NET_WM_STATE", 0); Atom net_wm_state_skip_taskbar = XInternAtom (fl_display, "_NET_WM_STATE_SKIP_TASKBAR", 0); XChangeProperty (fl_display, xp->xid, net_wm_state, XA_ATOM, 32, PropModeAppend, (unsigned char*) &net_wm_state_skip_taskbar, 1); } // If asked for, create fullscreen if (win->fullscreen_active() && Fl_X11_Screen_Driver::ewmh_supported()) { unsigned long data[4]; data[0] = fullscreen_top; data[1] = fullscreen_bottom; data[2] = fullscreen_left; data[3] = fullscreen_right; XChangeProperty (fl_display, xp->xid, fl_NET_WM_FULLSCREEN_MONITORS, XA_ATOM, 32, PropModeReplace, (unsigned char*) data, 4); XChangeProperty (fl_display, xp->xid, fl_NET_WM_STATE, XA_ATOM, 32, PropModeAppend, (unsigned char*) &fl_NET_WM_STATE_FULLSCREEN, 1); } // Make it receptive to DnD: Atom version = 5; // max. XDND protocol version we understand XChangeProperty(fl_display, xp->xid, fl_XdndAware, XA_ATOM, sizeof(int)*8, 0, (unsigned char*)&version, 1); XWMHints *hints = XAllocWMHints(); hints->input = True; hints->flags = InputHint; if (Fl_Window::show_next_window_iconic()) { hints->flags |= StateHint; hints->initial_state = IconicState; Fl_Window::show_next_window_iconic(0); showit = 0; } if (Fl_X11_Window_Driver::driver(win)->icon_ && Fl_X11_Window_Driver::driver(win)->icon_->legacy_icon) { hints->icon_pixmap = (Pixmap)Fl_X11_Window_Driver::driver(win)->icon_->legacy_icon; hints->flags |= IconPixmapHint; } XSetWMHints(fl_display, xp->xid, hints); XFree(hints); Fl_X11_Window_Driver::driver(win)->set_icons(); } // set the window type for menu and tooltip windows to avoid animations (compiz) if (win->menu_window() || win->tooltip_window()) { Atom net_wm_type = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE", False); Atom net_wm_type_kind = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_MENU", False); XChangeProperty(fl_display, xp->xid, net_wm_type, XA_ATOM, 32, PropModeReplace, (unsigned char*)&net_wm_type_kind, 1); } #if HAVE_XFIXES // register for clipboard change notifications if (have_xfixes && !win->parent()) { XFixesSelectSelectionInput(fl_display, xp->xid, XA_PRIMARY, XFixesSetSelectionOwnerNotifyMask); XFixesSelectSelectionInput(fl_display, xp->xid, CLIPBOARD, XFixesSetSelectionOwnerNotifyMask); } #endif if (win->shape()) { Fl_X11_Window_Driver::driver(win)->combine_mask(); } XMapWindow(fl_display, xp->xid); if (showit) { win->set_visible(); int old_event = Fl::e_number; win->handle(Fl::e_number = FL_SHOW); // get child windows to appear Fl::e_number = old_event; win->redraw(); } // non-EWMH fullscreen case, need grab if (win->fullscreen_active() && !Fl_X11_Screen_Driver::ewmh_supported()) { XGrabKeyboard(fl_display, xp->xid, 1, GrabModeAsync, GrabModeAsync, fl_event_time); } } //////////////////////////////////////////////////////////////// // Send X window stuff that can be changed over time: void Fl_X11_Window_Driver::sendxjunk() { Fl_Window *w = pWindow; if (w->parent() || w->override()) return; // it's not a window manager window! XSizeHints *hints = XAllocSizeHints(); // memset(&hints, 0, sizeof(hints)); jreiser suggestion to fix purify? float s = Fl::screen_driver()->scale(screen_num()); int minw, minh, maxw, maxh, dw, dh, aspect; pWindow->get_size_range(&minw, &minh, &maxw, &maxh, &dw, &dh, &aspect); hints->min_width = s * minw; hints->min_height = s * minh; hints->max_width = s * maxw; hints->max_height = s * maxh; if (int(s) == s) { // use win size increment value only if scale is an integer. Is it possible to do better? hints->width_inc = s * dw; hints->height_inc = s * dh; } else { hints->width_inc = 0; hints->height_inc = 0; } hints->win_gravity = StaticGravity; // see the file /usr/include/X11/Xm/MwmUtil.h: // fill all fields to avoid bugs in kwm and perhaps other window managers: // 0, MWM_FUNC_ALL, MWM_DECOR_ALL long prop[5] = {0, 1, 1, 0, 0}; if (hints->min_width != hints->max_width || hints->min_height != hints->max_height) { // resizable hints->flags = PMinSize|PWinGravity; if (hints->max_width >= hints->min_width || hints->max_height >= hints->min_height) { hints->flags = PMinSize|PMaxSize|PWinGravity; // unfortunately we can't set just one maximum size. Guess a // value for the other one. Some window managers will make the // window fit on screen when maximized, others will put it off screen: if (hints->max_width < hints->min_width) hints->max_width = Fl::w()*s; if (hints->max_height < hints->min_height) hints->max_height = Fl::h()*s; } if (hints->width_inc && hints->height_inc) hints->flags |= PResizeInc; if (aspect) { // stupid X! It could insist that the corner go on the // straight line between min and max... hints->min_aspect.x = hints->max_aspect.x = hints->min_width; hints->min_aspect.y = hints->max_aspect.y = hints->min_height; hints->flags |= PAspect; } } else { // not resizable: hints->flags = PMinSize|PMaxSize|PWinGravity; prop[0] = 1; // MWM_HINTS_FUNCTIONS prop[1] = 1|2|16; // MWM_FUNC_ALL | MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE } if (force_position()) { hints->flags |= USPosition; hints->x = s*w->x(); hints->y = s*w->y(); } if (!w->border()) { prop[0] |= 2; // MWM_HINTS_DECORATIONS prop[2] = 0; // no decorations } XSetWMNormalHints(fl_display, fl_xid(w), hints); XChangeProperty(fl_display, fl_xid(w), fl_MOTIF_WM_HINTS, fl_MOTIF_WM_HINTS, 32, 0, (unsigned char *)prop, 5); XFree(hints); } //////////////////////////////////////////////////////////////// static unsigned long *default_net_wm_icons = 0L; static size_t default_net_wm_icons_size = 0; // Note: icons[] *must* contain at least valid image pointers (!NULL), // but: *may* be 0 static void icons_to_property(const Fl_RGB_Image *icons[], int count, unsigned long **property, size_t *len) { size_t sz; unsigned long *data; sz = 0; for (int i = 0;i < count;i++) sz += 2 + icons[i]->data_w() * icons[i]->data_h(); // FIXME: Might want to sort the icons *property = data = new unsigned long[sz]; *len = sz; for (int i = 0;i < count;i++) { const Fl_RGB_Image *image; image = icons[i]; bool need_delete = false; if (image->w() != image->data_w() || image->h() != image->data_h()) { image = (Fl_RGB_Image*)image->copy(); need_delete = true; } data[0] = image->data_w(); data[1] = image->data_h(); data += 2; const int extra_data = image->ld() ? (image->ld() - image->data_w() * image->d()) : 0; const uchar *in = (const uchar*)*image->data(); for (int y = 0; y < image->data_h(); y++) { for (int x = 0; x < image->data_w(); x++) { switch (image->d()) { case 1: *data = ( 0xff<<24) | (in[0]<<16) | (in[0]<<8) | in[0]; break; case 2: *data = (in[1]<<24) | (in[0]<<16) | (in[0]<<8) | in[0]; break; case 3: *data = ( 0xff<<24) | (in[0]<<16) | (in[1]<<8) | in[2]; break; case 4: *data = (in[3]<<24) | (in[0]<<16) | (in[1]<<8) | in[2]; break; } in += image->d(); data++; } in += extra_data; } if (need_delete) delete image; } } void Fl_X11_Screen_Driver::default_icons(const Fl_RGB_Image *icons[], int count) { if (default_net_wm_icons) { delete [] default_net_wm_icons; default_net_wm_icons = 0L; default_net_wm_icons_size = 0; } if (count > 0) icons_to_property(icons, count, &default_net_wm_icons, &default_net_wm_icons_size); } void Fl_X11_Window_Driver::set_icons() { unsigned long *net_wm_icons; size_t net_wm_icons_size; if (icon_ && icon_->count) { icons_to_property((const Fl_RGB_Image **)icon_->icons, icon_->count, &net_wm_icons, &net_wm_icons_size); } else { net_wm_icons = default_net_wm_icons; net_wm_icons_size = default_net_wm_icons_size; } XChangeProperty (fl_display, fl_xid(pWindow), fl_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, (unsigned char*) net_wm_icons, net_wm_icons_size); if (icon_ && icon_->count) { delete [] net_wm_icons; net_wm_icons = 0L; net_wm_icons_size = 0; } } //////////////////////////////////////////////////////////////// #if ! HAVE_XCURSOR static void cache_pixmap_cursor(Fl_Cursor c, Cursor& cursor, Fl_Window *pWindow, Cursor& result) { if (cursor != None) { // already cached? result = cursor; return; } #define CURSORSIZE 16 #define HOTXY 7 static struct TableEntry { uchar bits[CURSORSIZE*CURSORSIZE/8]; uchar mask[CURSORSIZE*CURSORSIZE/8]; Cursor cursor; } table[] = { {{ // FL_CURSOR_NWSE 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00, 0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, { 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}}, {{ // FL_CURSOR_NESW 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x17, 0x80, 0x03, 0xc0, 0x01, 0xe8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f, 0x80, 0x3f, 0xc0, 0x37, 0xec, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0}, {0}} // FL_CURSOR_NONE & unknown }; Cursor xc = None; if (c >= FL_CURSOR_NWSE) { TableEntry *q = (c > FL_CURSOR_NESW) ? table+2 : table+(c-FL_CURSOR_NWSE); if (!(q->cursor)) { XColor dummy = { 0 }; Pixmap p = XCreateBitmapFromData(fl_display, RootWindow(fl_display, fl_screen), (const char*)(q->bits), CURSORSIZE, CURSORSIZE); Pixmap m = XCreateBitmapFromData(fl_display, RootWindow(fl_display, fl_screen), (const char*)(q->mask), CURSORSIZE, CURSORSIZE); q->cursor = XCreatePixmapCursor(fl_display, p,m,&dummy, &dummy, HOTXY, HOTXY); XFreePixmap(fl_display, m); XFreePixmap(fl_display, p); } xc = q->cursor; } XColor fgc; uchar r,g,b; // hardcoded colors (legacy) Fl_Color fg = FL_WHITE; Fl_Color bg = FL_BLACK; Fl::get_color(fg,r,g,b); fgc.red = r<<8; fgc.green = g<<8; fgc.blue = b<<8; XColor bgc; Fl::get_color(bg,r,g,b); bgc.red = r<<8; bgc.green = g<<8; bgc.blue = b<<8; XRecolorCursor(fl_display, xc, &fgc, &bgc); result = xc; } #endif // ! HAVE_XCURSOR int Fl_X11_Window_Driver::set_cursor(Fl_Cursor c) { /* The cursors are cached, because creating one takes 0.5ms including opening, reading, and closing theme files. They are kept until program exit by design, which valgrind will note as reachable. */ static Cursor xc_arrow = None; static Cursor xc_cross = None; static Cursor xc_wait = None; static Cursor xc_insert = None; static Cursor xc_hand = None; static Cursor xc_help = None; static Cursor xc_move = None; static Cursor xc_ns = None; static Cursor xc_we = None; static Cursor xc_ne = None; static Cursor xc_n = None; static Cursor xc_nw = None; static Cursor xc_e = None; static Cursor xc_w = None; static Cursor xc_se = None; static Cursor xc_s = None; static Cursor xc_sw = None; #if ! HAVE_XCURSOR static Cursor xc_nwse = None; static Cursor xc_nesw = None; static Cursor xc_none = None; #endif // ! HAVE_XCURSOR Cursor xc; #define cache_cursor(name, var) if (var == None) { \ var = XCreateFontCursor(fl_display, name); \ } \ xc = var switch (c) { case FL_CURSOR_ARROW: cache_cursor(XC_left_ptr, xc_arrow); break; case FL_CURSOR_CROSS: cache_cursor(XC_tcross, xc_cross); break; case FL_CURSOR_WAIT: cache_cursor(XC_watch, xc_wait); break; case FL_CURSOR_INSERT: cache_cursor(XC_xterm, xc_insert); break; case FL_CURSOR_HAND: cache_cursor(XC_hand2, xc_hand); break; case FL_CURSOR_HELP: cache_cursor(XC_question_arrow, xc_help); break; case FL_CURSOR_MOVE: cache_cursor(XC_fleur, xc_move); break; case FL_CURSOR_NS: cache_cursor(XC_sb_v_double_arrow, xc_ns); break; case FL_CURSOR_WE: cache_cursor(XC_sb_h_double_arrow, xc_we); break; case FL_CURSOR_NE: cache_cursor(XC_top_right_corner, xc_ne); break; case FL_CURSOR_N: cache_cursor(XC_top_side, xc_n); break; case FL_CURSOR_NW: cache_cursor(XC_top_left_corner, xc_nw); break; case FL_CURSOR_E: cache_cursor(XC_right_side, xc_e); break; case FL_CURSOR_W: cache_cursor(XC_left_side, xc_w); break; case FL_CURSOR_SE: cache_cursor(XC_bottom_right_corner, xc_se); break; case FL_CURSOR_S: cache_cursor(XC_bottom_side, xc_s); break; case FL_CURSOR_SW: cache_cursor(XC_bottom_left_corner, xc_sw); break; #if ! HAVE_XCURSOR case FL_CURSOR_NWSE: cache_pixmap_cursor(c, xc_nwse, pWindow, xc); break; case FL_CURSOR_NESW: cache_pixmap_cursor(c, xc_nesw, pWindow, xc); break; case FL_CURSOR_NONE: cache_pixmap_cursor(c, xc_none, pWindow, xc); break; #endif // ! HAVE_XCURSOR default: return 0; } #undef cache_cursor XDefineCursor(fl_display, fl_xid(pWindow), xc); return 1; } int Fl_X11_Window_Driver::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { #if ! HAVE_XCURSOR return 0; #else XcursorImage *cursor; Cursor xc; if ((hotx < 0) || (hotx >= image->w())) return 0; if ((hoty < 0) || (hoty >= image->h())) return 0; cursor = XcursorImageCreate(image->w(), image->h()); if (!cursor) return 0; image = (Fl_RGB_Image*)image->copy(); const int extra_data = image->ld() ? (image->ld()-image->w()*image->d()) : 0; const uchar *i = (const uchar*)*image->data(); XcursorPixel *o = cursor->pixels; for (int y = 0;y < image->h();y++) { for (int x = 0;x < image->w();x++) { uchar r, g, b, a; switch (image->d()) { case 1: r = g = b = i[0]; a = 0xff; break; case 2: r = g = b = i[0]; a = i[1]; break; case 3: r = i[0]; g = i[1]; b = i[2]; a = 0xff; break; case 4: r = i[0]; g = i[1]; b = i[2]; a = i[3]; break; default: return 0; } // Alpha needs to be pre-multiplied for X11 r = (uchar)((unsigned)r * a / 255); g = (uchar)((unsigned)g * a / 255); b = (uchar)((unsigned)b * a / 255); *o = (a<<24) | (r<<16) | (g<<8) | b; i += image->d(); o++; } i += extra_data; } cursor->xhot = hotx; cursor->yhot = hoty; xc = XcursorImageLoadCursor(fl_display, cursor); XDefineCursor(fl_display, fl_xid(pWindow), xc); XFreeCursor(fl_display, xc); XcursorImageDestroy(cursor); delete image; return 1; #endif } //////////////////////////////////////////////////////////////// void Fl_X11_Window_Driver::label(const char *name, const char *iname) { if (shown() && !parent()) { if (!name) name = ""; int namelen = strlen(name); if (!iname) iname = fl_filename_name(name); int inamelen = strlen(iname); Window win = fl_xid(pWindow); XChangeProperty(fl_display, win, fl_NET_WM_NAME, fl_XaUtf8String, 8, 0, (uchar*)name, namelen); // utf8 XChangeProperty(fl_display, win, XA_WM_NAME, XA_STRING, 8, 0, (uchar*)name, namelen); // non-utf8 XChangeProperty(fl_display, win, fl_NET_WM_ICON_NAME, fl_XaUtf8String, 8, 0, (uchar*)iname, inamelen); // utf8 XChangeProperty(fl_display, win, XA_WM_ICON_NAME, XA_STRING, 8, 0, (uchar*)iname, inamelen); // non-utf8 } } //////////////////////////////////////////////////////////////// // Implement the virtual functions for the base Fl_Window class: void Fl_X11_Window_Driver::show() { if (!shown()) { fl_open_display(); #ifdef ENABLE_BOXCHEAT // Don't set background pixel for double-buffered windows... if (pWindow->type() != FL_DOUBLE_WINDOW && can_boxcheat(pWindow->box())) { fl_background_pixel = int(fl_xpixel(pWindow->color())); } #endif // (ENABLE_BOXCHEAT) makeWindow(); } else { XMapRaised(fl_display, fl_xid(pWindow)); } } fltk-1.4.3/src/Fl_Native_File_Chooser_Zenity.H0000644000175000017500000000206315004135251021340 0ustar albrechtalbrecht// // FLTK native file chooser widget : Zenity version // // Copyright 2021-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef FL_ZENITY_NATIVE_FILE_CHOOSER_H #define FL_ZENITY_NATIVE_FILE_CHOOSER_H 1 /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include "Fl_Native_File_Chooser_Kdialog.H" class Fl_Zenity_Native_File_Chooser_Driver : public Fl_Kdialog_Native_File_Chooser_Driver { friend class Fl_Native_File_Chooser; static bool did_find_zenity; static bool have_looked_for_zenity; Fl_Zenity_Native_File_Chooser_Driver(int val); void append_filter(Fl_String& command); void build_command(Fl_String& command) FL_OVERRIDE; }; /** \} \endcond */ #endif // FL_ZENITY_NATIVE_FILE_CHOOSER_H fltk-1.4.3/src/mediumarrow.h0000644000175000017500000000046715004135251016107 0ustar albrechtalbrecht#define mediumarrow_width 16 #define mediumarrow_height 16 static const unsigned char mediumarrow_bits[] = { 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 0x00, 0xfc, 0x3f, 0x78, 0x00, 0x70, 0x00, 0x60, 0x02, 0x40, 0x06, 0x00, 0x0e, 0x00, 0x1e, 0xfc, 0x3f, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x02}; fltk-1.4.3/src/fl_draw.cxx0000644000175000017500000006324415004135251015547 0ustar albrechtalbrecht// // Label drawing code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Implementation of fl_draw(const char*,int,int,int,int,Fl_Align) // Used to draw all the labels and text, this routine: // Word wraps the labels to fit into their bounding box. // Breaks them into lines at the newlines. // Expands all unprintable characters to ^X or \nnn notation // Aligns them against the inside of the box. #include #include #include #include #include // fl_open_display() #include "flstring.h" #include "fl_oxy.h" #include #include #include char fl_draw_shortcut; // set by fl_labeltypes.cxx static char* underline_at; /* Extract the part of text that fits into the given maximum width. If called with maxbuf==0, use an internally allocated buffer and enlarge it as needed. Otherwise, use buf as buffer but don't go beyond its length of maxbuf. \param[in] from input text, can contain '\n' and single or double '\@' characters \param[out] buf buffer for the output text segment \param[in] maxbuf size of the buffer, or 0 to use the internal buffer allocated in this function \param[in] maxw maximum width in pixels of the output text \param[out] n number of characters in the output text segment \param[out] width actual width in pixels of the output text \param[in] wrap if true, wrap at maxw, else wrap at newlines \param[in] draw_symbols if true, double '\@' characters are escaped into a single '@' \return pointer to the next character in the input text */ static const char* expand_text_(const char* from, char*& buf, int maxbuf, double maxw, int& n, double &width, int wrap, int draw_symbols) { // Reset underline_at to null underline_at = NULL; // Initialize the total width to 0 double w = 0; // Check if the caller wants to use the internal buffer static int l_local_buff = 500; static char *local_buf = (char*)malloc(l_local_buff); // initial buffer allocation // Calculate the end pointer of the buffer char* e; if (maxbuf == 0) { buf = local_buf; e = buf + l_local_buff - 4; } else { e = buf+(maxbuf-4); } // Initialize the output pointer to the buffer char* o = buf; // Initialize the word end pointer that points into the `out` buffer char* word_end = o; // Initialize the word start pointer that points into the `from` buffer const char* word_start = from; // Iterate over the input text const char* p = from; for (;; p++) { int c = *p & 255; // Check for end of line, space, or '\n' if (!c || c == ' ' || c == '\n') { // Check for word wrap if (word_start < p && wrap) { // Calculate the new width double newwidth = w + fl_width(word_end, (int) (o-word_end) ); // Check if the new width exceeds the maximum width if (word_end > buf && int(newwidth) > maxw) { // break before this word o = word_end; p = word_start; break; } // Update the word end pointer word_end = o; w = newwidth; } // Check for end of line if (!c) break; else if (c == '\n') {p++; break;} // Update the word start pointer word_start = p+1; } // Check if the buffer needs to be enlarged if (o > e) { if (maxbuf) break; // don't overflow buffer l_local_buff += int(o - e) + 200; // enlarge buffer size_t delta_o = (o - local_buf); size_t delta_end = (word_end - local_buf); local_buf = (char*)realloc(local_buf, l_local_buff); buf = local_buf; e = local_buf + l_local_buff - 4; // update pointers to buffer content o = local_buf + delta_o; word_end = local_buf + delta_end; } // Process the character based on its type if (c == '\t') { // Process tab character for (c = fl_utf_nb_char((uchar*)buf, (int) (o-buf) )%8; c<8 && o (str + 1) && p[-1] != '@') { strlcpy(symbol[1], p, sizeof(symbol[1])); symwidth[1] = (w < h ? w : h); } } // Width and height of both symbols combined symtotal = symwidth[0] + symwidth[1]; // Image width if image is to the left or right of the text, else 0 imgtotal = (img && (align&FL_ALIGN_IMAGE_NEXT_TO_TEXT)) ? img->w() + spacing : 0; int strw = 0; // Width of text only without symbols int strh; // Height of text only without symbols // Count how many lines and put the last one into the buffer: if (str) { for (p = str, lines=0; p;) { e = expand_text_(p, linebuf, 0, w - symtotal - imgtotal, buflen, width, align&FL_ALIGN_WRAP, draw_symbols); if (strwh() + spacing : 0; // Height of image if image is above or below text int imgw[2] = {0, 0}; // Width of image on the left and right side of the text symoffset = 0; // Figure out vertical position of the first line of text or top image if (align & FL_ALIGN_BOTTOM) { ypos = y+h-(lines-1)*height-imgh; } else if (align & FL_ALIGN_TOP) { ypos = y+height; } else { ypos = y+(h-lines*height-imgh)/2+height; } // Draw the image if located *above* the text if (img && imgvert && !(align & FL_ALIGN_TEXT_OVER_IMAGE)) { if (img->w() > symoffset) symoffset = img->w(); if (align & FL_ALIGN_LEFT) { xpos = x + symwidth[0]; } else if (align & FL_ALIGN_RIGHT) { xpos = x + w - img->w() - symwidth[1]; } else { xpos = x + (w - img->w() - symtotal) / 2 + symwidth[0]; } img->draw(xpos, ypos - height); ypos += img->h() + spacing; } // Draw the image if either on the *left* or *right* side of the text if (img && !imgvert) { if (align & FL_ALIGN_TEXT_OVER_IMAGE) { // Image is to the right of the text imgw[1] = img->w() + spacing; // Find the horizontal position of the image if (align & FL_ALIGN_LEFT) { xpos = x + symwidth[0] + strw + 1; } else if (align & FL_ALIGN_RIGHT) { xpos = x + w - symwidth[1] - imgw[1] + 1; } else { xpos = x + (w - strw - symtotal - imgw[1]) / 2 + symwidth[0] + strw + 1; } xpos += spacing; } else { // Image is to the left of the text imgw[0] = img->w() + spacing; // Find the horizontal position of the image if (align & FL_ALIGN_LEFT) { xpos = x + symwidth[0] - 1; } else if (align & FL_ALIGN_RIGHT) { xpos = x + w - symwidth[1] - strw - imgw[0] - 1; } else { xpos = x + (w - strw - symtotal - imgw[0]) / 2 - 1; } } // Find the vertical position of the image int yimg; if (align & FL_ALIGN_TOP) { yimg = ypos - height; } else if (align & FL_ALIGN_BOTTOM) { yimg = ypos - height + strh - img->h() - 1; } else { yimg = ypos - height + (strh - img->h() - 1) / 2; } // Draw the image img->draw(xpos, yimg); } // Now draw all the text lines if (str) { int desc = fl_descent(); for (p=str; ; ypos += height) { if (lines>1) { e = expand_text_(p, linebuf, 0, w - symtotal - imgtotal, buflen, width, align&FL_ALIGN_WRAP, draw_symbols); } else { e = ""; } if (width > symoffset) symoffset = (int)(width + 0.5); if (align & FL_ALIGN_LEFT) { xpos = x + symwidth[0] + imgw[0]; } else if (align & FL_ALIGN_RIGHT) { xpos = x + w - (int)(width + .5) - symwidth[1] - imgw[1]; } else { xpos = x + (w - (int)(width + .5) - symtotal - imgw[0] - imgw[1]) / 2 + symwidth[0] + imgw[0]; } callthis(linebuf,buflen,xpos,ypos-desc); if (underline_at && underline_at >= linebuf && underline_at < (linebuf + buflen)) callthis("_",1,xpos+int(fl_width(linebuf,(int) (underline_at-linebuf))),ypos-desc); if (!*e || (*e == '@' && e[1] != '@')) break; p = e; } } // Draw the image if the image is *below* the text if (img && imgvert && (align & FL_ALIGN_TEXT_OVER_IMAGE)) { if (img->w() > symoffset) symoffset = img->w(); if (align & FL_ALIGN_LEFT) { xpos = x + symwidth[0]; } else if (align & FL_ALIGN_RIGHT) { xpos = x + w - img->w() - symwidth[1]; } else { xpos = x + (w - img->w() - symtotal) / 2 + symwidth[0]; } img->draw(xpos, ypos + spacing); } // Draw the symbols, if any... if (symwidth[0]) { // Draw the leading symbol to the left of the text if (align & FL_ALIGN_LEFT) { xpos = x; } else if (align & FL_ALIGN_RIGHT) { xpos = x + w - symtotal - symoffset; } else { xpos = x + (w - symoffset - symtotal) / 2; } if (align & FL_ALIGN_BOTTOM) { ypos = y + h - symwidth[0]; } else if (align & FL_ALIGN_TOP) { ypos = y; } else { ypos = y + (h - symwidth[0]) / 2; } fl_draw_symbol(symbol[0], xpos, ypos, symwidth[0], symwidth[0], fl_color()); } if (symwidth[1]) { // Draw the trailing symbol to the right of the text if (align & FL_ALIGN_LEFT) { xpos = x + symoffset + symwidth[0]; } else if (align & FL_ALIGN_RIGHT) { xpos = x + w - symwidth[1]; } else { xpos = x + (w - symoffset - symtotal) / 2 + symoffset + symwidth[0]; } if (align & FL_ALIGN_BOTTOM) { ypos = y + h - symwidth[1]; } else if (align & FL_ALIGN_TOP) { ypos = y; } else { ypos = y + (h - symwidth[1]) / 2; } fl_draw_symbol(symbol[1], xpos, ypos, symwidth[1], symwidth[1], fl_color()); } } // Caution: put the documentation next to the function's declaration in fl_draw.H for Doxygen // to see default argument values. void fl_draw( const char* str, int x, int y, int w, int h, Fl_Align align, Fl_Image* img, int draw_symbols, int spacing) { if ((!str || !*str) && !img) return; if (w && h && !fl_not_clipped(x, y, w, h) && (align & FL_ALIGN_INSIDE)) return; if (align & FL_ALIGN_CLIP) fl_push_clip(x, y, w, h); fl_draw(str, x, y, w, h, align, fl_draw, img, draw_symbols, spacing); if (align & FL_ALIGN_CLIP) fl_pop_clip(); } /** Measure how wide and tall the string will be when printed by the fl_draw() function with \p align parameter. If the incoming \p w is non-zero it will wrap to that width. The \ref drawing_fl_font "current font" is used to do the width/height calculations, so unless its value is known at the time fl_measure() is called, it is advised to first set the current font with fl_font(). With event-driven GUI programming you can never be sure which widget was exposed and redrawn last, nor which font it used. If you have not called fl_font() explicitly in your own code, the width and height may be set to unexpected values, even zero! \b Note: In the general use case, it's a common error to forget to set \p w to 0 before calling fl_measure() when wrap behavior isn't needed. \param[in] str nul-terminated string \param[in,out] w call with w=0, or with the prefered width for word wrapping, returns with the width of the string in current font \param[out] h height of string in current font \param[in] draw_symbols non-zero to enable @@symbol handling [default=1] \code // Example: Common use case for fl_measure() const char *s = "This is a test"; int wi=0, hi=0; // initialize to zero before calling fl_measure() fl_font(FL_HELVETICA, 14); // set current font face/size to be used for measuring fl_measure(s, wi, hi); // returns pixel width/height of string in current font \endcode */ void fl_measure(const char* str, int& w, int& h, int draw_symbols) { if (!str || !*str) {w = 0; h = 0; return;} h = fl_height(); char *linebuf = NULL; const char* p; const char* e; int buflen; int lines; double width=0; int W = 0; int symwidth[2], symtotal; symwidth[0] = 0; // size of symbol at beginning of string (if any) symwidth[1] = 0; // size of symbol at end of string (if any) if (draw_symbols) { // Symbol at beginning of string? const char *sym2 = (str[0]=='@' && str[1]=='@') ? str+2 : str; // sym2 check will skip leading @@ if (str[0] == '@' && str[1] != '@') { while (*str && !isspace(*str)) { ++str; } // skip over symbol if (isspace(*str)) ++str; // skip over trailing space sym2 = str; // sym2 check will skip leading symbol symwidth[0] = h; } // Symbol at end of string? if ((p=strchr(sym2,'@')) != NULL && p[1] != '@') { symwidth[1] = h; } } symtotal = symwidth[0] + symwidth[1]; for (p = str, lines=0; p;) { // e = expand(p, linebuf, w - symtotal, buflen, width, w != 0, draw_symbols); e = expand_text_(p, linebuf, 0, w - symtotal, buflen, width, w != 0, draw_symbols); if ((int)ceil(width) > W) W = (int)ceil(width); lines++; if (!*e || (*e == '@' && e[1] != '@' && draw_symbols)) break; p = e; } if ((symwidth[0] || symwidth[1]) && lines) { if (symwidth[0]) symwidth[0] = lines * fl_height(); if (symwidth[1]) symwidth[1] = lines * fl_height(); } symtotal = symwidth[0] + symwidth[1]; w = W + symtotal; h = lines*h; } /** Sets the current font, which is then used in various drawing routines. You may call this outside a draw context if necessary to measure text, for instance by calling fl_width(), fl_measure(), or fl_text_extents(), but on X this will open the display. The font is identified by a \p face and a \p size. The size of the font is measured in pixels and not "points". Lines should be spaced \p size pixels apart or more. */ void fl_font(Fl_Font face, Fl_Fontsize fsize) { if (!fl_graphics_driver) fl_open_display(); fl_graphics_driver->font(face, fsize); } /** This function returns the actual height of the specified \p font and \p size. Normally the font height should always be 'size', but with the advent of XFT, there are (currently) complexities that seem to only be solved by asking the font what its actual font height is. (See STR#2115) This function was originally undocumented in 1.1.x, and was used only by Fl_Text_Display. We're now documenting it in 1.3.x so that apps that need precise height info can get it with this function. \returns the height of the font in pixels. \todo In the future, when the XFT issues are resolved, this function should simply return the 'size' value. */ int fl_height(int font, int size) { if ( font == fl_font() && size == fl_size() ) return(fl_height()); int tf = fl_font(), ts = fl_size(); // save fl_font(font,size); int height = fl_height(); fl_font(tf,ts); // restore return(height); } /** Removes any GUI scaling factor in subsequent drawing operations. This must be matched by a later call to fl_restore_scale(). This function can be used to transiently perform drawing operations that are not rescaled by the current value of the GUI scaling factor. It's not supported to call fl_push_clip() while transiently removing scaling. \return The GUI scaling factor value that was in place when the function started. */ float fl_override_scale() { return fl_graphics_driver->override_scale(); } /** Restores the GUI scaling factor in subsequent drawing operations. \param s Value returned by a previous call to fl_override_scale(). */ void fl_restore_scale(float s) { fl_graphics_driver->restore_scale(s); } /** Draw a check mark inside the given bounding box. The check mark is allowed to fill the entire box but the algorithm used makes sure that a 1-pixel border is kept free if the box is large enough. You need to calculate margins for box borders etc. yourself. The check mark size is limited (minimum and maximum size) and the check mark is always centered in the given box. \note If the box is too small (bad GUI design) the check mark will be drawn over the box borders. This is intentional for better user experience. Otherwise users might not be able to recognize if a box is checked. The size limits are implementation details and may be changed at any time. \param[in] bb rectangle that defines the bounding box \param[in] col Fl_Color to draw the check mark \since 1.4.0 */ void fl_draw_check(Fl_Rect bb, Fl_Color col) { const int md = 6; // max. d1 value: 3 * md + 1 pixels wide int tx = bb.x(); int ty = bb.y(); int tw = bb.w(); int th = bb.h(); int lh = 3; // line height 3 means 4 pixels int d1, d2; Fl_Color saved_color = fl_color(); // make sure there's a free 1-pixel border if the area is large enough if (tw > 10) { tx++; tw -= 2; } if (th > 10) { ty++; th -= 2; } // calculate d1, the width and height of the left part of the check mark d1 = tw / 3; d2 = 2 * d1; if (d1 > md) { d1 = md; d2 = 2 * d1; } // make sure the height fits if (d2 + lh + 1 > th) { d2 = th - lh - 1; d1 = (d2+1) / 2; } // check minimal size (box too small) if (d1 < 2) { d1 = 2; d2 = 4; } // reduce line height (width) for small sizes if (d1 < 3) lh = 2; tw = d1 + d2 + 1; // total width th = d2 + lh + 1; // total height tx = bb.x() + (bb.w() - tw + 1) / 2; // x position (centered) ty = bb.y() + (bb.h() - th + 1) / 2; // y position (centered) // Set DEBUG_FRAME to 1 - 3 for debugging (0 otherwise) // Bit 1 set: draws a green background (the entire given box) // Bit 2 set: draws a red frame around the check mark (the bounding box) // The background (1) can be used to test correct positioning by the widget code #define DEBUG_FRAME (0) #if (DEBUG_FRAME) if (DEBUG_FRAME & 1) { // 1 = background fl_color(0x88dd8800); fl_rectf(bb.x(), bb.y(), bb.w(), bb.h()); } if (DEBUG_FRAME & 2) { // 2 = bounding box fl_color(0xff000000); fl_rect(tx, ty, tw, th); } #endif // draw the check mark fl_color(col); fl_begin_complex_polygon(); ty += d2 - d1; // upper border of check mark: left to right fl_vertex(tx, ty); fl_vertex(tx + d1, ty + d1); fl_vertex(tx + d1 + d2, ty + d1 - d2); ty += lh; // lower border of check mark: right to left fl_vertex(tx + d1 + d2, ty + d1 - d2); fl_vertex(tx + d1, ty + d1); fl_vertex(tx, ty); fl_end_complex_polygon(); fl_color(saved_color); } // fl_draw_check() /** Draw a potentially small, filled circle using a given color. This function draws a filled circle bounded by rectangle (x, y, d, d) using color \p color This function is the same as fl_pie(x, y, d, d, 0, 360) except with some systems that don't draw small circles well. In that situation, the circle diameter \p d is converted from FLTK units to pixels and this function approximates a filled circle by drawing several filled rectangles if the converted diameter is ≤ 6 pixels. The current drawing color fl_color() is preserved across the call. \param[in] x,y coordinates of top left of the bounding box \param[in] d diameter == width and height of the bounding box in FLTK units \param[in] color the color used to draw the circle \since 1.4.0 */ void fl_draw_circle(int x, int y, int d, Fl_Color color) { #define DEBUG_DRAW_CIRCLE (0) // bit 1 = draw bounding box (green) #if (DEBUG_DRAW_CIRCLE & 0) Fl_Color current = fl_color(); fl_rectf(x, y, d, d, FL_GREEN); fl_color(current); #endif fl_graphics_driver->draw_circle(x, y, d, color); } /** Draw a round check mark (circle) of a radio button. This draws only the round "radio button mark", it does not draw the (also typically round) box of the radio button. Call this only if the radio button is \c ON. This method draws a scheme specific "circle" with a particular light effect if the scheme is gtk+. For all other schemes this function draws a simple, small circle. The \c color must be chosen by the caller so it has enough contrast with the background. The bounding box of the circle is the rectangle (x, y, d, d). The current drawing color fl_color() is preserved across the call. \param[in] x,y coordinates of top left of the bounding box \param[in] d diameter == width and height of the bounding box in FLTK units \param[in] color the base color used to draw the circle \since 1.4.0 */ void fl_draw_radio(int x, int y, int d, Fl_Color color) { Fl_Color current = fl_color(); #if (0) // DEBUG: draw bounding box fl_color(fl_lighter(FL_RED)); fl_rectf(x, y, d, d); #endif if (Fl::is_scheme("gtk+")) { fl_color(color); fl_pie(x, y, d, d, 0.0, 360.0); Fl_Color icol = fl_color_average(FL_WHITE, color, 0.2f); fl_draw_circle(x + 2, y + 2, d - 4, icol); fl_color(fl_color_average(FL_WHITE, color, 0.5)); fl_arc(x + 1, y + 1, d - 1, d - 1, 60.0, 180.0); } else { fl_draw_circle(x + 1, y + 1, d - 2, color); } fl_color(current); } fltk-1.4.3/src/screen_xywh.cxx0000644000175000017500000001400315004135251016454 0ustar albrechtalbrecht// // Screen/monitor bounding box API for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "Fl_Screen_Driver.H" #include #ifndef FL_DOXYGEN void Fl::call_screen_init() { screen_driver()->init(); } #endif /** Returns the leftmost x coordinate of the main screen work area. */ int Fl::x() { return screen_driver()->x(); } /** Returns the topmost y coordinate of the main screen work area. */ int Fl::y() { return screen_driver()->y(); } /** Returns the width in pixels of the main screen work area. */ int Fl::w() { return screen_driver()->w(); } /** Returns the height in pixels of the main screen work area. */ int Fl::h() { return screen_driver()->h(); } /** Gets the total count of available screens. \note Screen numbers range from 0 to Fl::screen_count() - 1 in the FLTK API. */ int Fl::screen_count() { return screen_driver()->screen_count(); } /** Gets the bounding box of a screen that contains the specified screen position \p mx, \p my \param[out] X,Y,W,H the corresponding screen bounding box \param[in] mx, my the absolute screen position */ void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) { screen_driver()->screen_xywh(X, Y, W, H, mx, my); } /** Gets the bounding box of the work area of a screen that contains the specified screen position \p mx, \p my \param[out] X,Y,W,H the work area bounding box \param[in] mx, my the absolute screen position \see void screen_work_area(int &x, int &y, int &w, int &h, int n) */ void Fl::screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my) { screen_driver()->screen_work_area(X, Y, W, H, mx, my); } /** Gets the bounding box of the work area of the given screen. \param[out] X,Y,W,H the work area bounding box \param[in] n the screen number (0 to Fl::screen_count() - 1) \see void screen_xywh(int &x, int &y, int &w, int &h, int mx, int my) \note Under X11, the screen work area is given values that differ from that screen's bounding box only if the system contains a single screen. Under Wayland, a screen work area is always equal to that screen's bounding box. \note Like all quantities accessible via public APIs of FLTK, values of \p X,Y,W,H are given in FLTK units, that is, in drawing units divided by the scaling factor of screen \p n. */ void Fl::screen_work_area(int &X, int &Y, int &W, int &H, int n) { screen_driver()->screen_work_area(X, Y, W, H, n); } /** Gets the screen bounding rect for the given screen. Under Windows, Mac OS X, and X11 + the Gnome desktop, screen #0 contains the menubar/taskbar \param[out] X,Y,W,H the corresponding screen bounding box \param[in] n the screen number (0 to Fl::screen_count() - 1) \note Like all quantities accessible via public APIs of FLTK, values of \p X,Y,W,H are given in FLTK units, that is, in drawing units divided by the scaling factor of screen \p n. \see void screen_xywh(int &x, int &y, int &w, int &h, int mx, int my) */ void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int n) { screen_driver()->screen_xywh(X, Y, W, H, n); } /** Gets the screen bounding rect for the screen which intersects the most with the rectangle defined by \p mx, \p my, \p mw, \p mh. \param[out] X,Y,W,H the corresponding screen bounding box \param[in] mx, my, mw, mh the rectangle to search for intersection with \see void screen_xywh(int &X, int &Y, int &W, int &H, int n) */ void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh) { screen_driver()->screen_xywh(X, Y, W, H, mx, my, mw, mh); } /** Gets the screen number of a screen that contains the specified screen position \p x, \p y. \param[in] x, y the absolute screen position \return a screen number ∈ [0 , Fl::screen_count()-1] \attention When the running system contains screens with different scaling factors, this API may become ambiguous because a given value pair (\p x, \p y) may belong to distinct screens. In that situation other APIs should be preferred, e.g. Fl_Window::screen_num() and Fl::screen_scale(int). */ int Fl::screen_num(int x, int y) { return screen_driver()->screen_num(x, y); } /** Gets the screen number of the screen which intersects the most with the rectangle defined by \p x, \p y, \p w, \p h. \param[in] x, y, w, h the rectangle to search for intersection with \return a screen number ∈ [0 , Fl::screen_count()-1] */ int Fl::screen_num(int x, int y, int w, int h) { return screen_driver()->screen_num(x, y, w, h); } /** Gets the screen resolution in dots-per-inch for the given screen. \param[out] h, v horizontal and vertical resolution \param[in] n the screen number (0 to Fl::screen_count() - 1) \see void screen_xywh(int &x, int &y, int &w, int &h, int mx, int my) */ void Fl::screen_dpi(float &h, float &v, int n) { screen_driver()->screen_dpi(h, v, n); } /** Gets the bounding box of a screen that contains the mouse pointer. \param[out] X,Y,W,H the corresponding screen bounding box \see void screen_xywh(int &x, int &y, int &w, int &h, int mx, int my) */ void Fl::screen_xywh(int &X, int &Y, int &W, int &H) { int mx, my; int nscreen = Fl::screen_driver()->get_mouse(mx, my); Fl::screen_driver()->screen_xywh(X, Y, W, H, nscreen); } /** Gets the bounding box of the work area of the screen that contains the mouse pointer. \param[out] X,Y,W,H the work area bounding box \see void screen_work_area(int &x, int &y, int &w, int &h, int n) */ void Fl::screen_work_area(int &X, int &Y, int &W, int &H) { int mx, my; int nscreen = Fl::screen_driver()->get_mouse(mx, my); Fl::screen_driver()->screen_work_area(X, Y, W, H, nscreen); } fltk-1.4.3/src/Fl_Gl_Overlay.cxx0000644000175000017500000000373415004135251016613 0ustar albrechtalbrecht// // OpenGL overlay code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if HAVE_GL #include #include #include #include "Fl_Gl_Window_Driver.H" #include /** Returns true if the hardware overlay is possible. If this is false, FLTK will try to simulate the overlay, with significant loss of update speed. Calling this will cause FLTK to open the display. */ int Fl_Gl_Window::can_do_overlay() { return pGlWindowDriver->can_do_overlay(); } /** * @cond DriverDev * @addtogroup DriverDeveloper * @{ */ void Fl_Gl_Window_Driver::make_overlay(void *&o) { o = pWindow; } /** * @} * @endcond */ /** Causes draw_overlay() to be called at a later time. Initially the overlay is clear. If you want the window to display something in the overlay when it first appears, you must call this immediately after you show() your window. */ void Fl_Gl_Window::redraw_overlay() { if (!shown()) return; pGlWindowDriver->make_overlay(overlay); pGlWindowDriver->redraw_overlay(); } /** Selects the OpenGL context for the widget's overlay. This method is called automatically prior to the draw_overlay() method being called and can also be used to implement feedback and/or selection within the handle() method. */ void Fl_Gl_Window::make_overlay_current() { pGlWindowDriver->make_overlay(overlay); pGlWindowDriver->make_overlay_current(); } /** Hides the window if it is not this window, does nothing in Windows. */ void Fl_Gl_Window::hide_overlay() { pGlWindowDriver->hide_overlay(); } #endif // HAVE_GL fltk-1.4.3/src/Fl_Scroll.cxx0000644000175000017500000004620615004135251016007 0ustar albrechtalbrecht// // Fl_Scroll widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include /** Clear all but the scrollbars... */ void Fl_Scroll::clear() { // Note: the scrollbars are removed from the group before calling // Fl_Group::clear() to take advantage of the optimized widget removal // and deletion. Finally they are added to Fl_Scroll's group again. This // is MUCH faster than removing the widgets one by one (STR #2409). remove(hscrollbar); // remove last child first remove(scrollbar); Fl_Group::clear(); add(scrollbar); add(hscrollbar); } /** The destructor also deletes all the children. \see Fl_Group::~Fl_Group() */ Fl_Scroll::~Fl_Scroll() { remove(hscrollbar); // remove last child first remove(scrollbar); Fl_Group::clear(); } /** Ensure the scrollbars are the last children. When Fl_Scroll is instantiated the first child of the Fl_Group is the vertical scrollbar \p scrollbar and the second child is the horizontal scrollbar \p hscrollbar. These two widgets must always be the last two widgets and in this order to guarantee the correct drawing order and event delivery. Since FLTK 1.4.0 the new method on_insert() modifies the insert position of other children if it would be after the scrollbars. \internal If everything works as intended this method does no longer do anything because the scrollbars will always be in the correct places. */ void Fl_Scroll::fix_scrollbar_order() { Fl_Widget** a = (Fl_Widget**)array(); if (children() > 1 && (a[children()-2] != &scrollbar || a[children()-1] != &hscrollbar)) { int i, j; for (i = j = 0; j < children(); j++) { if (a[j] != &hscrollbar && a[j] != &scrollbar) a[i++] = a[j]; } a[i++] = &scrollbar; a[i++] = &hscrollbar; } } /** Change insert position of a child before it is added. Fix insert position if the new child is planned to be inserted after the scrollbars. We can assume that the scrollbars are always the last two children! Fl_Group calls this when a new widget is added. We return the new index if the new widget would be added after the scrollbars. \param[in] candidate the candidate will be added to the child array_ after this method returns. \param[in] index add the child at this position in the array_ \return index to position the child as planned \return a new index to force the child to a different position \return -1 to keep the group from adding the candidate \version 1.4.0 \see Fl_Group::on_insert(Fl_Widget *candidate, int index) */ int Fl_Scroll::on_insert(Fl_Widget *candidate, int index) { if (children() > 1 && index > children() - 2 && candidate != &scrollbar && candidate != &hscrollbar) { index = children() - 2; } return index; } /** Change new position of a child before it is moved. Fix new position if the new child is planned to be moved after the scrollbars. We can assume that the scrollbars are always the last two children! Fl_Group calls this when a widget is moved within the list of children. We return a new index if the widget would be moved after the scrollbars. \param old_index the current index of the child that will be moved \param new_index the new index of the child \return new index, possibly corrected to avoid last two scrollbar entries */ int Fl_Scroll::on_move(int old_index, int new_index) { return on_insert(child(old_index), new_index); } /** Removes the widget at \p index from the group and deletes it. This method does nothing if \p index is out of bounds or if Fl_Group::child(index) is one of the scrollbars. \param[in] index index of child to be removed \returns success (0) or error code \retval 0 success \retval 1 index out of range \retval 2 widget not allowed to be removed (see note) \see Fl_Group::delete_child(int index) \since FLTK 1.4.0 */ int Fl_Scroll::delete_child(int index) { if (index < 0 || index >= children()) return 1; Fl_Widget *w = child(index); if (w == &scrollbar || w == &hscrollbar) return 2; // can't delete scrollbars return Fl_Group::delete_child(index); } // Draw widget's background and children within a specific clip region // So widget can just redraw damaged parts. // void Fl_Scroll::draw_clip(void* v,int X, int Y, int W, int H) { fl_push_clip(X,Y,W,H); Fl_Scroll* s = (Fl_Scroll*)v; // erase background as needed... switch (s->box()) { case FL_NO_BOX : case FL_UP_FRAME : case FL_DOWN_FRAME : case FL_THIN_UP_FRAME : case FL_THIN_DOWN_FRAME : case FL_ENGRAVED_FRAME : case FL_EMBOSSED_FRAME : case FL_BORDER_FRAME : case _FL_SHADOW_FRAME : case _FL_ROUNDED_FRAME : case _FL_OVAL_FRAME : case _FL_PLASTIC_UP_FRAME : case _FL_PLASTIC_DOWN_FRAME : if (s->parent() == (Fl_Group *)s->window() && Fl::scheme_bg_) { Fl::scheme_bg_->draw(X-(X%((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->w()), Y-(Y%((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->h()), W+((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->w(), H+((Fl_Tiled_Image *)Fl::scheme_bg_)->image()->h()); break; } default : if (s->active_r()) fl_color(s->color()); else fl_color(fl_inactive(s->color())); fl_rectf(X,Y,W,H); break; } Fl_Widget*const* a = s->array(); for (int i=s->children()-2; i--;) { Fl_Widget& o = **a++; s->draw_child(o); s->draw_outside_label(o); } fl_pop_clip(); } /** Calculate visibility/size/position of scrollbars, find children's bounding box. The \p si parameter will be filled with data from the calculations. Derived classes can make use of this call to figure out the scrolling area eg. during resize() handling. This method does not change the scrollbars or their visibility. It calculates the scrollbar positions and visibility as they \b should be, according to the positions and sizes of the children. You may need to call redraw() to make sure the widget gets updated. \param[inout] si -- ScrollInfo structure, filled with data \see bbox() */ void Fl_Scroll::recalc_scrollbars(ScrollInfo &si) const { // inner box of widget (excluding scrollbars) si.innerbox.x = x() + Fl::box_dx(box()); si.innerbox.y = y() + Fl::box_dy(box()); si.innerbox.w = w() - Fl::box_dw(box()); si.innerbox.h = h() - Fl::box_dh(box()); // accumulate a bounding box for all the children si.child.l = si.innerbox.x; si.child.r = si.innerbox.x; si.child.b = si.innerbox.y; si.child.t = si.innerbox.y; int first = 1; Fl_Widget*const* a = array(); for (int i=children(); i--;) { Fl_Widget* o = *a++; if ( o==&scrollbar || o==&hscrollbar || o->visible()==0 ) continue; if ( first ) { first = 0; si.child.l = o->x(); si.child.r = o->x()+o->w(); si.child.b = o->y()+o->h(); si.child.t = o->y(); } else { if (o->x() < si.child.l) si.child.l = o->x(); if (o->y() < si.child.t) si.child.t = o->y(); if (o->x()+o->w() > si.child.r) si.child.r = o->x()+o->w(); if (o->y()+o->h() > si.child.b) si.child.b = o->y()+o->h(); } } // Turn the scrollbars on and off as necessary. // See if children would fit if we had no scrollbars... { int X = si.innerbox.x; int Y = si.innerbox.y; int W = si.innerbox.w; int H = si.innerbox.h; si.scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size(); si.vneeded = 0; si.hneeded = 0; if (type() & VERTICAL) { if ((type() & ALWAYS_ON) || si.child.t < Y || si.child.b > Y+H) { si.vneeded = 1; W -= si.scrollsize; if (scrollbar.align() & FL_ALIGN_LEFT) X += si.scrollsize; } } if (type() & HORIZONTAL) { if ((type() & ALWAYS_ON) || si.child.l < X || si.child.r > X+W) { si.hneeded = 1; H -= si.scrollsize; if (scrollbar.align() & FL_ALIGN_TOP) Y += si.scrollsize; // recheck vertical since we added a horizontal scrollbar if (!si.vneeded && (type() & VERTICAL)) { if ((type() & ALWAYS_ON) || si.child.t < Y || si.child.b > Y+H) { si.vneeded = 1; W -= si.scrollsize; if (scrollbar.align() & FL_ALIGN_LEFT) X += si.scrollsize; } } } } si.innerchild.x = X; si.innerchild.y = Y; si.innerchild.w = W; si.innerchild.h = H; } // calculate hor scrollbar position si.hscroll.x = si.innerchild.x; si.hscroll.y = (scrollbar.align() & FL_ALIGN_TOP) ? si.innerbox.y : si.innerbox.y + si.innerbox.h - si.scrollsize; si.hscroll.w = si.innerchild.w; si.hscroll.h = si.scrollsize; // calculate ver scrollbar position si.vscroll.x = (scrollbar.align() & FL_ALIGN_LEFT) ? si.innerbox.x : si.innerbox.x + si.innerbox.w - si.scrollsize; si.vscroll.y = si.innerchild.y; si.vscroll.w = si.scrollsize; si.vscroll.h = si.innerchild.h; // calculate h/v scrollbar values (pos/size/first/total) si.hscroll.pos = si.innerchild.x - si.child.l; si.hscroll.size = si.innerchild.w; si.hscroll.first = 0; si.hscroll.total = si.child.r - si.child.l; if ( si.hscroll.pos < 0 ) { si.hscroll.total += (-si.hscroll.pos); si.hscroll.first = si.hscroll.pos; } si.vscroll.pos = si.innerchild.y - si.child.t; si.vscroll.size = si.innerchild.h; si.vscroll.first = 0; si.vscroll.total = si.child.b - si.child.t; if ( si.vscroll.pos < 0 ) { si.vscroll.total += (-si.vscroll.pos); si.vscroll.first = si.vscroll.pos; } // printf("DEBUG --- ScrollInfo ---\n"); // printf("DEBUG scrollsize: %d\n", si.scrollsize); // printf("DEBUG hneeded, vneeded: %d %d\n", si.hneeded, si.vneeded); // printf("DEBUG innerbox.x, si.innerbox.y, si.innerbox.w,si.innerbox.h); // printf("DEBUG innerchild.xywh: %d %d %d %d\n", si.innerchild.x, si.innerchild.y, si.innerchild.w, si.innerchild.h); // printf("DEBUG child lrbt: %d %d %d %d\n", si.child.l, si.child.r, si.child.b, si.child.t); // printf("DEBUG hscroll xywh: %d %d %d %d\n", si.hscroll.x, si.hscroll.y, si.hscroll.w, si.hscroll.h); // printf("DEBUG vscroll xywh: %d %d %d %d\n", si.vscroll.x, si.vscroll.y, si.vscroll.w, si.vscroll.h); // printf("DEBUG horz scroll vals: %d %d %d %d\n", si.hscroll.pos, si.hscroll.size, si.hscroll.first, si.hscroll.total); // printf("DEBUG vert scroll vals: %d %d %d %d\n", si.vscroll.pos, si.vscroll.size, si.vscroll.first, si.vscroll.total); // printf("DEBUG \n"); } /** Returns the bounding box for the interior of the scrolling area, inside the scrollbars. This method does not change the scrollbars or their visibility. First the scrollbar positions and visibility are calculated as they \b should be, according to the positions and sizes of the children. Then the bounding box is calculated. You may need to call redraw() to make sure the widget gets updated. \see recalc_scrollbars() */ void Fl_Scroll::bbox(int& X, int& Y, int& W, int& H) const { ScrollInfo si; recalc_scrollbars(si); X = si.innerchild.x; Y = si.innerchild.y; W = si.innerchild.w; H = si.innerchild.h; } void Fl_Scroll::draw() { fix_scrollbar_order(); int X,Y,W,H; bbox(X,Y,W,H); uchar d = damage(); // See: https://github.com/fltk/fltk/issues/1149#issuecomment-2511135611 float scale = Fl_Surface_Device::surface()->driver()->scale(); if ((d & FL_DAMAGE_ALL) || scale != int(scale)) { // full redraw draw_box(box(),x(),y(),w(),h(),color()); draw_clip(this, X, Y, W, H); } else { if (d & FL_DAMAGE_SCROLL) { // scroll the contents: fl_scroll(X, Y, W, H, oldx-xposition_, oldy-yposition_, draw_clip, this); // Erase the background as needed... Fl_Widget*const* a = array(); int L, R, T, B; L = 999999; R = 0; T = 999999; B = 0; for (int i=children()-2; i--; a++) { if ((*a)->x() < L) L = (*a)->x(); if (((*a)->x() + (*a)->w()) > R) R = (*a)->x() + (*a)->w(); if ((*a)->y() < T) T = (*a)->y(); if (((*a)->y() + (*a)->h()) > B) B = (*a)->y() + (*a)->h(); } if (L > X) draw_clip(this, X, Y, L - X, H); if (R < (X + W)) draw_clip(this, R, Y, X + W - R, H); if (T > Y) draw_clip(this, X, Y, W, T - Y); if (B < (Y + H)) draw_clip(this, X, B, W, Y + H - B); } if (d & FL_DAMAGE_CHILD) { // draw damaged children fl_push_clip(X, Y, W, H); Fl_Widget*const* a = array(); for (int i=children()-2; i--;) update_child(**a++); fl_pop_clip(); } } // Calculate where scrollbars should go, and draw them { ScrollInfo si; recalc_scrollbars(si); // Now that we know what's needed, make it so. if (si.vneeded && !scrollbar.visible()) { scrollbar.set_visible(); d = FL_DAMAGE_ALL; } else if (!si.vneeded && scrollbar.visible()) { scrollbar.clear_visible(); draw_clip(this, si.vscroll.x, si.vscroll.y, si.vscroll.w, si.vscroll.h); d = FL_DAMAGE_ALL; } if (si.hneeded && !hscrollbar.visible()) { hscrollbar.set_visible(); d = FL_DAMAGE_ALL; } else if (!si.hneeded && hscrollbar.visible()) { hscrollbar.clear_visible(); draw_clip(this, si.hscroll.x, si.hscroll.y, si.hscroll.w, si.hscroll.h); d = FL_DAMAGE_ALL; } else if ( hscrollbar.h() != si.scrollsize || scrollbar.w() != si.scrollsize ) { // scrollsize changed d = FL_DAMAGE_ALL; } scrollbar.resize(si.vscroll.x, si.vscroll.y, si.vscroll.w, si.vscroll.h); oldy = yposition_ = si.vscroll.pos; // si.innerchild.y - si.child.t; scrollbar.value(si.vscroll.pos, si.vscroll.size, si.vscroll.first, si.vscroll.total); hscrollbar.resize(si.hscroll.x, si.hscroll.y, si.hscroll.w, si.hscroll.h); oldx = xposition_ = si.hscroll.pos; // si.innerchild.x - si.child.l; hscrollbar.value(si.hscroll.pos, si.hscroll.size, si.hscroll.first, si.hscroll.total); } // draw the scrollbars: if ((d & FL_DAMAGE_ALL) || scale != int(scale)) { draw_child(scrollbar); draw_child(hscrollbar); if (scrollbar.visible() && hscrollbar.visible()) { // fill in the little box in the corner fl_color(color()); fl_rectf(scrollbar.x(), hscrollbar.y(), scrollbar.w(), hscrollbar.h()); } } else { update_child(scrollbar); update_child(hscrollbar); } } /** Resizes the Fl_Scroll widget and moves its children if necessary. The Fl_Scroll widget first resizes itself, and then it moves all its children if (and only if) the Fl_Scroll widget has been moved. The children are moved by the same amount as the Fl_Scroll widget has been moved, hence all children keep their relative positions. \note Fl_Scroll::resize() does \b not call Fl_Group::resize(), and child widgets are \b not resized. Since children of an Fl_Scroll are not resized, the resizable() widget is ignored (if it is set). The scrollbars are moved to their proper positions, as given by Fl_Scroll::scrollbar.align(), and switched on or off as necessary. \note Due to current (FLTK 1.3.x) implementation constraints some of this may effectively be postponed until the Fl_Scroll is drawn the next time. This may change in a future release. \sa Fl_Group::resizable() \sa Fl_Widget::resize(int,int,int,int) */ void Fl_Scroll::resize(int X, int Y, int W, int H) { int dx = X-x(), dy = Y-y(); int dw = W-w(), dh = H-h(); Fl_Widget::resize(X,Y,W,H); // resize _before_ moving children around fix_scrollbar_order(); // move all the children: Fl_Widget*const* a = array(); for (int i=children()-2; i--;) { Fl_Widget* o = *a++; o->position(o->x()+dx, o->y()+dy); } if (dw==0 && dh==0) { char pad = ( scrollbar.visible() && hscrollbar.visible() ); char al = ( (scrollbar.align() & FL_ALIGN_LEFT) != 0 ); char at = ( (scrollbar.align() & FL_ALIGN_TOP) !=0 ); scrollbar.position(al?X:X+W-scrollbar.w(), (at&&pad)?Y+hscrollbar.h():Y); hscrollbar.position((al&&pad)?X+scrollbar.w():X, at?Y:Y+H-hscrollbar.h()); } else { // FIXME recalculation of scrollbars needs to be moved out of "draw()" (STR #1895) redraw(); // need full recalculation of scrollbars } } /** Moves the contents of the scroll group to a new position. This is like moving the scrollbars of the Fl_Scroll around. For instance: \code Fl_Scroll scroll (10,10,200,200); Fl_Box b1 ( 10, 10,50,50,"b1"); // relative (x,y) = (0,0) Fl_Box b2 ( 60, 60,50,50,"b2"); // relative (x,y) = (50,50) Fl_Box b3 ( 60,110,50,50,"b3"); // relative (x,y) = (50,100) // populate scroll with more children ... scroll.end(); scroll.scroll_to(50,100); \endcode will move the logical origin of the internal scroll area to (-50,-100) relative to the origin of the Fl_Scroll (10,10), i.e. Fl_Box b3 will be visible in the top left corner of the scroll area. */ void Fl_Scroll::scroll_to(int X, int Y) { int dx = xposition_-X; int dy = yposition_-Y; if (!dx && !dy) return; xposition_ = X; yposition_ = Y; Fl_Widget*const* a = array(); for (int i=children(); i--;) { Fl_Widget* o = *a++; if (o == &hscrollbar || o == &scrollbar) continue; o->position(o->x()+dx, o->y()+dy); } if (parent() == (Fl_Group *)window() && Fl::scheme_bg_) damage(FL_DAMAGE_ALL); else damage(FL_DAMAGE_SCROLL); } void Fl_Scroll::hscrollbar_cb(Fl_Widget* o, void*) { Fl_Scroll* s = (Fl_Scroll*)(o->parent()); s->scroll_to(int(((Fl_Scrollbar*)o)->value()), s->yposition()); } void Fl_Scroll::scrollbar_cb(Fl_Widget* o, void*) { Fl_Scroll* s = (Fl_Scroll*)(o->parent()); s->scroll_to(s->xposition(), int(((Fl_Scrollbar*)o)->value())); } /** Creates a new Fl_Scroll widget using the given position, size, and label string. The default boxtype is FL_NO_BOX. The destructor also deletes all the children. This allows a whole tree to be deleted at once, without having to keep a pointer to all the children in the user code. A kludge has been done so the Fl_Scroll and all of its children can be automatic (local) variables, but you must declare the Fl_Scroll first, so that it is destroyed last. */ Fl_Scroll::Fl_Scroll(int X, int Y, int W, int H, const char *L) : Fl_Group(X, Y, W, H, L), scrollbar(X+W-Fl::scrollbar_size(),Y, Fl::scrollbar_size(),H-Fl::scrollbar_size()), hscrollbar(X,Y+H-Fl::scrollbar_size(), W-Fl::scrollbar_size(),Fl::scrollbar_size()) { type(BOTH); xposition_ = oldx = 0; yposition_ = oldy = 0; scrollbar_size_ = 0; hscrollbar.type(FL_HORIZONTAL); hscrollbar.callback(hscrollbar_cb); scrollbar.callback(scrollbar_cb); } int Fl_Scroll::handle(int event) { fix_scrollbar_order(); return Fl_Group::handle(event); } fltk-1.4.3/src/Fl_Counter.cxx0000644000175000017500000001576215004135251016173 0ustar albrechtalbrecht// // Counter widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include // This struct describes the four arrow boxes struct arrow_box { int width; Fl_Arrow_Type arrow_type; Fl_Boxtype boxtype; Fl_Orientation orientation; arrow_box() { // constructor width = 0; boxtype = FL_NO_BOX; orientation = FL_ORIENT_RIGHT; arrow_type = FL_ARROW_SINGLE; } }; /** Compute sizes (widths) of arrow boxes. This method computes the two sizes of the arrow boxes of Fl_Counter. You can override it in a subclass if you want to draw fancy arrows or change the layout. However, the basic layout is fixed and can't be changed w/o overriding the draw() and handle() methods. Basic layout: \code +------+-----+-------------+-----+------+ | << | < | value | > | >> | +------+-----+-------------+-----+------+ \endcode The returned value \p w2 should be zero if the counter type() is FL_SIMPLE_COUNTER. \param[out] w1 width of single arrow box \param[out] w2 width of double arrow box */ void Fl_Counter::arrow_widths(int &w1, int &w2) { if (type() == FL_SIMPLE_COUNTER) { w1 = w() * 20/100; w2 = 0; } else { w1 = w() * 13/100; w2 = w() * 17/100; } // limit arrow box sizes to reserve more space for the text box if (w1 > 13) w1 = 13; if (w2 > 24) w2 = 24; } void Fl_Counter::draw() { struct arrow_box ab[4]; // text box setup Fl_Boxtype tbt = box(); if (tbt == FL_UP_BOX) tbt = FL_DOWN_BOX; if (tbt == FL_THIN_UP_BOX) tbt = FL_THIN_DOWN_BOX; // arrow boxes for (int i = 0; i < 4; i++) { if (mouseobj_ == i + 1) ab[i].boxtype = fl_down(box()); else ab[i].boxtype = box(); } ab[0].arrow_type = ab[3].arrow_type = FL_ARROW_DOUBLE; // first and last arrow ab[0].orientation = ab[1].orientation = FL_ORIENT_LEFT; // left arrows int w1 = 0, w2 = 0; arrow_widths(w1, w2); if (type() == FL_SIMPLE_COUNTER) w2 = 0; ab[0].width = ab[3].width = w2; // double arrows ab[1].width = ab[2].width = w1; // single arrows int tw = w() - 2 * (w1 + w2); // text box width int tx = x() + w1 + w2; // text box position // printf("w() = %3d, w1 = %3d, w2 = %3d, tw = %3d\n", w(), w1, w2, tw); // always draw text box and text draw_box(tbt, tx, y(), tw, h(), FL_BACKGROUND2_COLOR); fl_font(textfont(), textsize()); fl_color(active_r() ? textcolor() : fl_inactive(textcolor())); char str[128]; format(str); fl_draw(str, tx, y(), tw, h(), FL_ALIGN_CENTER); if (Fl::focus() == this) draw_focus(tbt, tx, y(), tw, h()); if (!(damage()&FL_DAMAGE_ALL)) return; // only need to redraw text Fl_Color arrow_color; if (active_r()) arrow_color = labelcolor(); else arrow_color = fl_inactive(labelcolor()); // draw arrow boxes int xo = x(); for (int i = 0; i < 4; i++) { if (ab[i].width > 0) { draw_box(ab[i].boxtype, xo, y(), ab[i].width, h(), color()); Fl_Rect bb(xo, y(), ab[i].width, h(), ab[i].boxtype); fl_draw_arrow(bb, ab[i].arrow_type, ab[i].orientation, arrow_color); xo += ab[i].width; } if (i == 1) xo += tw; } } // draw() void Fl_Counter::increment_cb() { if (!mouseobj_) return; double v = value(); switch (mouseobj_) { case 1: v -= lstep_; break; case 2: v = increment(v, -1); break; case 3: v = increment(v, 1); break; case 4: v += lstep_; break; } handle_drag(clamp(round(v))); } #define INITIALREPEAT .5 #define REPEAT .1 void Fl_Counter::repeat_callback(void* v) { Fl_Counter* b = (Fl_Counter*)v; int buttons = Fl::event_state() & FL_BUTTONS; // any mouse button pressed int focus = (Fl::focus() == b); // the widget has focus if (b->mouseobj_ && buttons && focus) { Fl::add_timeout(REPEAT, repeat_callback, b); b->increment_cb(); } } int Fl_Counter::calc_mouseobj() { if (type() == FL_NORMAL_COUNTER) { int W = w()*15/100; if (Fl::event_inside(x(), y(), W, h())) return 1; if (Fl::event_inside(x()+W, y(), W, h())) return 2; if (Fl::event_inside(x()+w()-2*W, y(), W, h())) return 3; if (Fl::event_inside(x()+w()-W, y(), W, h())) return 4; } else { int W = w()*20/100; if (Fl::event_inside(x(), y(), W, h())) return 2; if (Fl::event_inside(x()+w()-W, y(), W, h())) return 3; } return -1; } int Fl_Counter::handle(int event) { int i; switch (event) { case FL_RELEASE: if (mouseobj_) { Fl::remove_timeout(repeat_callback, this); mouseobj_ = 0; redraw(); } handle_release(); return 1; case FL_PUSH: if (Fl::visible_focus()) Fl::focus(this); { Fl_Widget_Tracker wp(this); handle_push(); if (wp.deleted()) return 1; } case FL_DRAG: i = calc_mouseobj(); if (i != mouseobj_) { Fl::remove_timeout(repeat_callback, this); mouseobj_ = (uchar)i; if (i > 0) Fl::add_timeout(INITIALREPEAT, repeat_callback, this); Fl_Widget_Tracker wp(this); increment_cb(); if (wp.deleted()) return 1; redraw(); } return 1; case FL_MOUSEWHEEL: handle_drag(clamp(increment(value(),(Fl::event_dy() - Fl::event_dx()) / 2 ))); return 1; case FL_KEYBOARD : switch (Fl::event_key()) { case FL_Left: handle_drag(clamp(increment(value(),-1))); return 1; case FL_Right: handle_drag(clamp(increment(value(),1))); return 1; default: return 0; } // break not required because of switch... case FL_UNFOCUS : mouseobj_ = 0; /* FALLTHROUGH */ case FL_FOCUS : if (Fl::visible_focus()) { redraw(); return 1; } else return 0; case FL_ENTER : /* FALLTHROUGH */ case FL_LEAVE : return 1; default: return 0; } } /** Destroys the valuator. */ Fl_Counter::~Fl_Counter() { Fl::remove_timeout(repeat_callback, this); } /** Creates a new Fl_Counter widget using the given position, size, and label string. The default type is FL_NORMAL_COUNTER. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Counter::Fl_Counter(int X, int Y, int W, int H, const char* L) : Fl_Valuator(X, Y, W, H, L) { box(FL_UP_BOX); selection_color(FL_INACTIVE_COLOR); // was FL_BLUE align(FL_ALIGN_BOTTOM); bounds(-1000000.0, 1000000.0); Fl_Valuator::step(1, 10); lstep_ = 1.0; mouseobj_ = 0; textfont_ = FL_HELVETICA; textsize_ = FL_NORMAL_SIZE; textcolor_ = FL_FOREGROUND_COLOR; } Fl_Simple_Counter::Fl_Simple_Counter(int X,int Y,int W,int H, const char *L) : Fl_Counter(X,Y,W,H,L) { type(FL_SIMPLE_COUNTER); } fltk-1.4.3/src/Fl.cxx0000644000175000017500000023137215004135251014471 0ustar albrechtalbrecht// // Main event handling code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file src/Fl.cxx Implementation of the member functions of class Fl. */ #include #include #include "Fl_Screen_Driver.H" #include "Fl_Window_Driver.H" #include "Fl_System_Driver.H" #include "Fl_Timeout.h" #include #include #include #include #include #include "flstring.h" #if defined(DEBUG) || defined(DEBUG_WATCH) # include #endif // DEBUG || DEBUG_WATCH // // Globals... // Fl_Widget *fl_selection_requestor; #ifndef FL_DOXYGEN Fl_Widget *Fl::belowmouse_, *Fl::pushed_, *Fl::focus_, *Fl::selection_owner_; int Fl::damage_, Fl::e_number, Fl::e_x, Fl::e_y, Fl::e_x_root, Fl::e_y_root, Fl::e_dx, Fl::e_dy, Fl::e_state, Fl::e_clicks, Fl::e_is_click, Fl::e_keysym, Fl::e_original_keysym, Fl::scrollbar_size_ = 16, Fl::menu_linespacing_ = 4; // 4: was a local macro in Fl_Menu.cxx called "LEADING" char *Fl::e_text = (char *)""; int Fl::e_length; const char *Fl::e_clipboard_type = ""; void *Fl::e_clipboard_data = NULL; Fl_Event_Dispatch Fl::e_dispatch = 0; Fl_Callback_Reason Fl::callback_reason_ = FL_REASON_UNKNOWN; unsigned char Fl::options_[] = { 0, 0 }; unsigned char Fl::options_read_ = 0; int Fl::selection_to_clipboard_ = 0; Fl_Window *fl_xfocus = NULL; // which window X thinks has focus Fl_Window *fl_xmousewin; // which window X thinks has FL_ENTER Fl_Window *Fl::grab_; // most recent Fl::grab() Fl_Window *Fl::modal_; // topmost modal() window #endif // FL_DOXYGEN char const * const Fl::clipboard_plain_text = "text/plain"; char const * const Fl::clipboard_image = "image"; // // Drivers // /** Returns a pointer to the unique Fl_Screen_Driver object of the platform */ Fl_Screen_Driver *Fl::screen_driver() { static Fl_Screen_Driver* screen_driver_ = Fl_Screen_Driver::newScreenDriver(); return screen_driver_; } /** Returns a pointer to the unique Fl_System_Driver object of the platform */ Fl_System_Driver *Fl::system_driver() { if (!Fl_Screen_Driver::system_driver) { Fl_Screen_Driver::system_driver = Fl_System_Driver::newSystemDriver(); } return Fl_Screen_Driver::system_driver; } // // 'Fl::version()' - Return the API version number... // /** Returns the compiled-in value of the FL_VERSION constant. This is useful for checking the version of a shared library. \deprecated Use int Fl::api_version() instead. */ double Fl::version() { return FL_VERSION; } /** Returns the compiled-in value of the FL_API_VERSION constant. This is useful for checking the version of a shared library. */ int Fl::api_version() { return FL_API_VERSION; } /** Returns the compiled-in value of the FL_ABI_VERSION constant. This is useful for checking the version of a shared library. */ int Fl::abi_version() { return FL_ABI_VERSION; } /** Gets the default scrollbar size used by Fl_Browser_, Fl_Help_View, Fl_Scroll, and Fl_Text_Display widgets. \returns The default size for widget scrollbars, in pixels. */ int Fl::scrollbar_size() { return scrollbar_size_; } /** Sets the default scrollbar size that is used by the Fl_Browser_, Fl_Help_View, Fl_Scroll, and Fl_Text_Display widgets. \param[in] W The new default size for widget scrollbars, in pixels. */ void Fl::scrollbar_size(int W) { scrollbar_size_ = W; } /** Gets the default line spacing used by menus. \returns The default line spacing, in pixels. \since 1.4.0 */ int Fl::menu_linespacing() { return menu_linespacing_; } /** Sets the default line spacing used by menus. Default is 4. \param[in] H The new default line spacing between menu items, in pixels. \since 1.4.0 */ void Fl::menu_linespacing(int H) { menu_linespacing_ = H; } /** Returns whether or not the mouse event is inside the given rectangle. Returns non-zero if the current Fl::event_x() and Fl::event_y() put it inside the given arbitrary bounding box. You should always call this rather than doing your own comparison so you are consistent about edge effects. To find out, whether the event is inside a child widget of the current window, you can use Fl::event_inside(const Fl_Widget *). \param[in] xx,yy,ww,hh bounding box \return non-zero, if mouse event is inside */ int Fl::event_inside(int xx,int yy,int ww,int hh) /*const*/ { int mx = e_x - xx; int my = e_y - yy; return (mx >= 0 && mx < ww && my >= 0 && my < hh); } /** Returns whether or not the mouse event is inside a given child widget. Returns non-zero if the current Fl::event_x() and Fl::event_y() put it inside the given child widget's bounding box. This method can only be used to check whether the mouse event is inside a \b child widget of the window that handles the event, and there must not be an intermediate subwindow (i.e. the widget must not be inside a subwindow of the current window). However, it is valid if the widget is inside a nested Fl_Group. You must not use it with the window itself as the \p o argument in a window's handle() method. \note The mentioned restrictions are necessary, because this method does not transform coordinates of child widgets, and thus the given widget \p o must be within the \e same window that is handling the current event. Otherwise the results are undefined. You should always call this rather than doing your own comparison so you are consistent about edge effects. \see Fl::event_inside(int, int, int, int) \param[in] o child widget to be tested \return non-zero, if mouse event is inside the widget */ int Fl::event_inside(const Fl_Widget *o) /*const*/ { int mx = e_x - o->x(); int my = e_y - o->y(); return (mx >= 0 && mx < o->w() && my >= 0 && my < o->h()); } // // Cross-platform timer support // // User (doxygen) documentation is in this file but the implementation // of all functions is in class Fl_Timeout in Fl_Timeout.cxx. /** Adds a one-shot timeout callback. The callback function \p cb will be called by Fl::wait() at \p time seconds after this function is called. The callback function must have the signature \ref Fl_Timeout_Handler. The optional \p data argument is passed to the callback (default: NULL). The timer is removed from the timer queue before the callback function is called. It is safe to reschedule the timeout inside the callback function. You can have multiple timeout callbacks, even the same timeout callback with different timeout values and/or different \p data values. They are all considered different timer objects. To remove a timeout while it is active (pending) use Fl::remove_timeout(). If you need more accurate, repeated timeouts, use Fl::repeat_timeout() to reschedule the subsequent timeouts. Please see Fl::repeat_timeout() for an example. Since version 1.4, a timeout can be started from a child thread under the condition that the call to Fl::add_timeout is wrapped in Fl::lock() and Fl::unlock(). \param[in] time delta time in seconds until the timer expires \param[in] cb callback function \param[in] data optional user data (default: \p NULL) \see Fl_Timeout_Handler \see Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data) \see Fl::remove_timeout(Fl_Timeout_Handler cb, void *data) \see Fl::has_timeout(Fl_Timeout_Handler cb, void *data) */ void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *data) { Fl_Timeout::add_timeout(time, cb, data); } /** Repeats a timeout callback from the expiration of the previous timeout, allowing for more accurate timing. You should call this method only inside a timeout callback of the same or a logically related timer from whose expiration time the new timeout shall be scheduled. Otherwise the timing accuracy can't be improved and the exact behavior is undefined. If you call this outside a timeout callback the behavior is the same as Fl::add_timeout(). Example: The following code will print "TICK" each second on stdout with a fair degree of accuracy: \code #include #include #include void callback(void *) { printf("TICK\n"); Fl::repeat_timeout(1.0, callback); // retrigger timeout } int main() { Fl_Window win(100, 100); win.show(); Fl::add_timeout(1.0, callback); // set up first timeout return Fl::run(); } \endcode \param[in] time delta time in seconds until the timer expires \param[in] cb callback function \param[in] data optional user data (default: \p NULL) */ void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data) { Fl_Timeout::repeat_timeout(time, cb, data); } /** Returns true if the timeout exists and has not been called yet. Both arguments \p cb and \p data must match with at least one timer in the queue of active timers to return true (1). \note It is a known inconsistency that Fl::has_timeout() does not use the \p data argument as a wildcard (match all) if it is zero (NULL) which Fl::remove_timeout() does. This is so for backwards compatibility with FLTK 1.3.x. Therefore using 0 (zero, NULL) as the timeout \p data value is discouraged unless you're sure that you don't need to use Fl::has_timeout(callback, (void *)0); or Fl::remove_timeout(callback, (void *)0);. \param[in] cb Timer callback \param[in] data User data \returns whether the timer was found in the queue \retval 0 not found \retval 1 found */ int Fl::has_timeout(Fl_Timeout_Handler cb, void *data) { return Fl_Timeout::has_timeout(cb, data); } /** Remove one or more matching timeout callbacks from the timer queue. This method removes \b all matching timeouts, not just the first one. If the \p data argument is \p NULL (the default!) only the callback \p cb must match, i.e. all timer entries with this callback are removed. It is harmless to remove a timeout callback that no longer exists. If you want to remove only the next matching timeout you can use Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return) (available since FLTK 1.4.0). \param[in] cb Timer callback to be removed (must match) \param[in] data Wildcard if NULL (default), must match otherwise \see Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return) */ void Fl::remove_timeout(Fl_Timeout_Handler cb, void *data) { Fl_Timeout::remove_timeout(cb, data); } /** Remove the next matching timeout callback and return its \p data pointer. This method removes only the next matching timeout and returns in \p data_return (if non-NULL) the \p data member given when the timeout was scheduled. This method is useful if you remove a timeout before it is scheduled and you need to get and use its data value, for instance to free() or delete the data associated with the timeout. This method returns non-zero if a matching timeout was found and zero if no timeout matched the request. If the return value is \c N \> 1 then there are N - 1 more matching timeouts pending. If you need to remove all timeouts with a particular callback \p cb you must repeat this call until it returns 1 (all timeouts removed) or zero (no matching timeout), whichever occurs first. \param[in] cb Timer callback to be removed (must match) \param[in] data Wildcard if NULL, must match otherwise \param[inout] data_return Pointer to (void *) to receive the data value \return non-zero if a timer was found and removed \retval 0 no matching timer was found \retval 1 the last matching timeout was found and removed \retval N>1 a matching timeout was removed and there are \n (N - 1) matching timeouts pending \see Fl::remove_timeout(Fl_Timeout_Handler cb, void *data) \since 1.4.0 */ int Fl::remove_next_timeout(Fl_Timeout_Handler cb, void *data, void **data_return) { return Fl_Timeout::remove_next_timeout(cb, data, data_return); } //////////////////////////////////////////////////////////////// // Checks are just stored in a list. They are called in the reverse // order that they were added (this may change in the future). // This is a bit messy because I want to allow checks to be added, // removed, and have wait() called from inside them. To do this // next_check points at the next unprocessed one for the outermost // call to Fl::wait(). struct Check { void (*cb)(void*); void* arg; Check* next; }; static Check *first_check, *next_check, *free_check; /** FLTK will call this callback just before it flushes the display and waits for events. This is different than an idle callback because it is only called once, then FLTK calls the system and tells it not to return until an event happens. This can be used by code that wants to monitor the application's state, such as to keep a display up to date. The advantage of using a check callback is that it is called only when no events are pending. If events are coming in quickly, whole blocks of them will be processed before this is called once. This can save significant time and avoid the application falling behind the events. Sample code: \code bool state_changed; // anything that changes the display turns this on void callback(void*) { if (!state_changed) return; state_changed = false; do_expensive_calculation(); widget->redraw(); } main() { Fl::add_check(callback); return Fl::run(); } \endcode */ void Fl::add_check(Fl_Timeout_Handler cb, void *argp) { Check* t = free_check; if (t) free_check = t->next; else t = new Check; t->cb = cb; t->arg = argp; t->next = first_check; if (next_check == first_check) next_check = t; first_check = t; } /** Removes a check callback. It is harmless to remove a check callback that no longer exists. */ void Fl::remove_check(Fl_Timeout_Handler cb, void *argp) { for (Check** p = &first_check; *p;) { Check* t = *p; if (t->cb == cb && t->arg == argp) { if (next_check == t) next_check = t->next; *p = t->next; t->next = free_check; free_check = t; } else { p = &(t->next); } } } /** Returns 1 if the check exists and has not been called yet, 0 otherwise. */ int Fl::has_check(Fl_Timeout_Handler cb, void *argp) { for (Check** p = &first_check; *p;) { Check* t = *p; if (t->cb == cb && t->arg == argp) { return 1; } else { p = &(t->next); } } return 0; } void Fl::run_checks() { // checks are a bit messy so that add/remove and wait may be called // from inside them without causing an infinite loop: if (next_check == first_check) { while (next_check) { Check* checkp = next_check; next_check = checkp->next; (checkp->cb)(checkp->arg); } next_check = first_check; } } //////////////////////////////////////////////////////////////// // Clipboard notifications struct Clipboard_Notify { Fl_Clipboard_Notify_Handler handler; void *data; struct Clipboard_Notify *next; }; static struct Clipboard_Notify *clip_notify_list = NULL; void Fl::add_clipboard_notify(Fl_Clipboard_Notify_Handler h, void *data) { struct Clipboard_Notify *node; remove_clipboard_notify(h); node = new Clipboard_Notify; node->handler = h; node->data = data; node->next = clip_notify_list; clip_notify_list = node; Fl::screen_driver()->clipboard_notify_change(); } void Fl::remove_clipboard_notify(Fl_Clipboard_Notify_Handler h) { struct Clipboard_Notify *node, **prev; node = clip_notify_list; prev = &clip_notify_list; while (node != NULL) { if (node->handler == h) { *prev = node->next; delete node; Fl::screen_driver()->clipboard_notify_change(); return; } prev = &node->next; node = node->next; } } bool fl_clipboard_notify_empty(void) { return clip_notify_list == NULL; } void fl_trigger_clipboard_notify(int source) { struct Clipboard_Notify *node, *next; node = clip_notify_list; while (node != NULL) { next = node->next; node->handler(source, node->data); node = next; } } //////////////////////////////////////////////////////////////// // idle/wait/run/check/ready: void (*Fl::idle)(); // see Fl::add_idle.cxx for the add/remove functions /* Private, undocumented method to run idle callbacks. FLTK guarantees that idle callbacks will never be called recursively, i.e. while an idle callback is being executed. This method should (must) be the only way to run idle callbacks to ensure that the `in_idle' flag is respected. Idle callbacks are executed whenever Fl::wait() is called and no events are waiting to be serviced. If Fl::idle is set (non-NULL) this points at a function that executes the first idle callback and appends it to the end of the list of idle callbacks. For details see static function call_idle() in Fl_add_idle.cxx. If it is NULL then no idle callbacks are active and Fl::run_idle() returns immediately. Note: idle callbacks can be queued in nested FLTK event loops like ``` while (win->shown()) Fl::wait(); ``` if an event (timeout or button click etc.) handler calls Fl::add_idle() or even in Fl::flush() if a draw() method calls Fl::add_idle(). */ void Fl::run_idle() { static char in_idle; if (Fl::idle && !in_idle) { in_idle = 1; Fl::idle(); in_idle = 0; } } /** Waits a maximum of \p time_to_wait seconds or until "something happens". See Fl::wait() for the description of operations performed when "something happens". \return Always 1 on Windows. Otherwise, it is positive if an event or fd happens before the time elapsed. It is zero if nothing happens. It is negative if an error occurs (this will happen on X11 if a signal happens). */ double Fl::wait(double time_to_wait) { return system_driver()->wait(time_to_wait); } #define FOREVER 1e20 /** Calls Fl::wait()repeatedly as long as any windows are displayed. When all the windows are closed it returns zero (supposedly it would return non-zero on any errors, but FLTK calls exit directly for these). A normal program will end main() with return Fl::run();. \note Fl::run() and Fl::wait() (but not Fl::wait(double)) both return when all FLTK windows are closed. Therefore, a MacOS FLTK application possessing Fl_Sys_Menu_Bar items able to create new windows and expected to keep running without any open window cannot use these two functions. One solution is to run the event loop as follows: \code while (!Fl::program_should_quit()) Fl::wait(1e20); \endcode */ int Fl::run() { while (Fl_X::first) wait(FOREVER); return 0; } /** Waits until "something happens" and then returns. Call this repeatedly to "run" your program. You can also check what happened each time after this returns, which is quite useful for managing program state. What this really does is call all idle callbacks, all elapsed timeouts, call Fl::flush() to get the screen to update, and then wait some time (zero if there are idle callbacks, the shortest of all pending timeouts, or infinity), for any events from the user or any Fl::add_fd() callbacks. It then handles the events and calls the callbacks and then returns. \return non-zero if there are any visible windows - this may change in future versions of FLTK. */ int Fl::wait() { if (!Fl_X::first) return 0; wait(FOREVER); return Fl_X::first != 0; // return true if there is a window } /** Same as Fl::wait(0). Calling this during a big calculation will keep the screen up to date and the interface responsive: \code while (!calculation_done()) { calculate(); Fl::check(); if (user_hit_abort_button()) break; } \endcode This returns non-zero if any windows are displayed, and 0 if no windows are displayed (this is likely to change in future versions of FLTK). */ int Fl::check() { wait(0.0); return Fl_X::first != 0; // return true if there is a window } /** This is similar to Fl::check() except this does \e not call Fl::flush() or any callbacks, which is useful if your program is in a state where such callbacks are illegal. This returns true if Fl::check() would do anything (it will continue to return true until you call Fl::check() or Fl::wait()). \code while (!calculation_done()) { calculate(); if (Fl::ready()) { do_expensive_cleanup(); Fl::check(); if (user_hit_abort_button()) break; } } \endcode */ int Fl::ready() { return system_driver()->ready(); } /** Hide all visible windows to make FLTK leave Fl::run(). Fl:run() will run as long as there are visible windows. Call Fl::hide_all_windows() to hide (close) all currently shown (visible) windows, effectively terminating the Fl::run() loop. \see Fl::run() \since 1.4.0 */ void Fl::hide_all_windows() { while (Fl::first_window()) { Fl::first_window()->hide(); } } int Fl::program_should_quit_ = 0; //////////////////////////////////////////////////////////////// // Window list management: #ifndef FL_DOXYGEN Fl_X* Fl_X::first; #endif /** Returns the Fl_Window that corresponds to the given window reference, or \c NULL if not found. \deprecated Kept in the X11, Windows, and macOS platforms for compatibility with FLTK versions before 1.4. Please use fl_x11_find(Window), fl_wl_find(struct wld_window*), fl_win32_find(HWND) or fl_mac_find(FLWindow*) with FLTK 1.4.0 and above. */ Fl_Window* fl_find(Window xid) { return Fl_Window_Driver::find((fl_uintptr_t)xid); } /** Returns the first top-level window in the list of shown() windows. If a modal() window is shown this is the top-most modal window, otherwise it is the most recent window to get an event. */ Fl_Window* Fl::first_window() { Fl_X* i = Fl_X::first; return i ? i->w : 0; } /** Returns the next top-level window in the list of shown() windows. You can use this call to iterate through all the windows that are shown(). \param[in] window must be shown and not NULL */ Fl_Window* Fl::next_window(const Fl_Window* window) { Fl_X* i = window ? Fl_X::flx(window) : 0; if (!i) { Fl::error("Fl::next_window() failed: window (%p) not shown.", window); return 0; } i = i->next; return i ? i->w : 0; } /** Sets the window that is returned by first_window(). The window is removed from wherever it is in the list and inserted at the top. This is not done if Fl::modal() is on or if the window is not shown(). Because the first window is used to set the "parent" of modal windows, this is often useful. */ void Fl::first_window(Fl_Window* window) { if (!window || !window->shown()) return; Fl_Window_Driver::find( Fl_X::flx(window)->xid ); } /** Redraws all widgets. */ void Fl::redraw() { for (Fl_X* i = Fl_X::first; i; i = i->next) i->w->redraw(); } /** Causes all the windows that need it to be redrawn and graphics forced out through the pipes. This is what wait() does before looking for events. Note: in multi-threaded applications you should only call Fl::flush() from the main thread. If a child thread needs to trigger a redraw event, it should instead call Fl::awake() to get the main thread to process the event queue. */ void Fl::flush() { if (damage()) { damage_ = 0; for (Fl_X* i = Fl_X::first; i; i = i->next) { Fl_Window* wi = i->w; if (Fl_Window_Driver::driver(wi)->wait_for_expose_value) {damage_ = 1; continue;} if (!wi->visible_r()) continue; if (wi->damage()) { Fl_Window_Driver::driver(wi)->flush(); wi->clear_damage(); } // destroy damage regions for windows that don't use them: if (i->region) { fl_graphics_driver->XDestroyRegion(i->region); i->region = 0; } } } screen_driver()->flush(); } //////////////////////////////////////////////////////////////// // Event handlers: struct handler_link { int (*handle)(int); handler_link *next; }; static handler_link *handlers = 0; /** Install a function to parse unrecognized events. If FLTK cannot figure out what to do with an event, it calls each of these functions (most recent first) until one of them returns non-zero. If none of them returns non-zero then the event is ignored. Events that cause this to be called are: - \ref FL_SHORTCUT events that are not recognized by any widget. This lets you provide global shortcut keys. - \ref FL_SCREEN_CONFIGURATION_CHANGED events. Under X11, this event requires the libXrandr.so shared library to be loadable at run-time and the X server to implement the RandR extension. - \ref FL_ZOOM_EVENT events. - System events that FLTK does not recognize. See fl_xevent. - \e Some other events when the widget FLTK selected returns zero from its handle() method. Exactly which ones may change in future versions, however. \see Fl::remove_handler(Fl_Event_Handler) \see Fl::event_dispatch(Fl_Event_Dispatch d) \see Fl::handle(int, Fl_Window*) */ void Fl::add_handler(Fl_Event_Handler ha) { handler_link *l = new handler_link; l->handle = ha; l->next = handlers; handlers = l; } /** Returns the last function installed by a call to Fl::add_handler(). \since 1.4.0 */ Fl_Event_Handler Fl::last_handler() { return handlers ? handlers->handle : NULL; } /** Install a function to parse unrecognized events with less priority than another function. Install function \p ha to handle unrecognized events giving it the priority just lower than that of function \p before which was previously installed. \see Fl::add_handler(Fl_Event_Handler) \see Fl::last_handler() \since 1.4.0 */ void Fl::add_handler(Fl_Event_Handler ha, Fl_Event_Handler before) { if (!before) return Fl::add_handler(ha); handler_link *l = handlers; while (l) { if (l->handle == before) { handler_link *p = l->next, *q = new handler_link; q->handle = ha; q->next = p; l->next = q; return; } l = l->next; } } /** Removes a previously added event handler. \see Fl::handle(int, Fl_Window*) */ void Fl::remove_handler(Fl_Event_Handler ha) { handler_link *l, *p; // Search for the handler in the list... for (l = handlers, p = 0; l && l->handle != ha; p = l, l = l->next) { /* empty */ } if (l) { // Found it, so remove it from the list... if (p) p->next = l->next; else handlers = l->next; // And free the record... delete l; } } int (*fl_local_grab)(int); // used by fl_dnd.cxx static int send_handlers(int e) { for (const handler_link *hl = handlers; hl; hl = hl->next) if (hl->handle(e)) return 1; return 0; } //////////////////////////////////////////////////////////////// // System event handlers: struct system_handler_link { Fl_System_Handler handle; void *data; system_handler_link *next; }; static system_handler_link *sys_handlers = 0; /** \brief Install a function to intercept system events. FLTK calls each of these functions as soon as a new system event is received. The processing will stop at the first function to return non-zero. If all functions return zero then the event is passed on for normal handling by FLTK. Each function will be called with a pointer to the system event as the first argument and \p data as the second argument. The system event pointer will always be void *, but will point to different objects depending on the platform: - X11: XEvent - Windows: MSG - OS X: NSEvent - Wayland: NULL (FLTK runs the event handler(s) just before calling \e wl_display_dispatch()) \param ha The event handler function to register \param data User data to include on each call \see Fl::remove_system_handler(Fl_System_Handler) */ void Fl::add_system_handler(Fl_System_Handler ha, void *data) { system_handler_link *l = new system_handler_link; l->handle = ha; l->data = data; l->next = sys_handlers; sys_handlers = l; } /** Removes a previously added system event handler. \param ha The event handler function to remove \see Fl::add_system_handler(Fl_System_Handler) */ void Fl::remove_system_handler(Fl_System_Handler ha) { system_handler_link *l, *p; // Search for the handler in the list... for (l = sys_handlers, p = 0; l && l->handle != ha; p = l, l = l->next) { /* empty */ } if (l) { // Found it, so remove it from the list... if (p) p->next = l->next; else sys_handlers = l->next; // And free the record... delete l; } } int fl_send_system_handlers(void *e) { for (const system_handler_link *hl = sys_handlers; hl; hl = hl->next) { if (hl->handle(e, hl->data)) return 1; } return 0; } //////////////////////////////////////////////////////////////// Fl_Widget* fl_oldfocus; // kludge for Fl_Group... /** Sets the widget that will receive FL_KEYBOARD events. Use this function inside the \c handle(int) member function of a widget of yours to give focus to the widget, for example when it receives the FL_FOCUS or the FL_PUSH event. Otherwise, use Fl_Widget::take_focus() to give focus to a widget; If you change Fl::focus(), the previous widget and all parents (that don't contain the new widget) are sent FL_UNFOCUS events. Changing the focus does \e not send FL_FOCUS to this or any widget, because sending FL_FOCUS is supposed to \e test if the widget wants the focus (by it returning non-zero from handle()). Since FLTK 1.4.0 widgets can set the NEEDS_KEYBOARD flag to indicate that a keyboard is essential for the widget to function. Touchscreen devices will be sent a request to show an on-screen keyboard if no hardware keyboard is connected. \see Fl_Widget::take_focus() \see Fl_Widget::needs_keyboard() const \see Fl_Widget::needs_keyboard(bool) */ void Fl::focus(Fl_Widget *o) { if (grab()) return; // don't do anything while grab is on // request an on-screen keyboard on touch screen devices if needed Fl_Widget *prevFocus = Fl::focus(); char hideKeyboard = (prevFocus && prevFocus->needs_keyboard()); char showKeyboard = (o && o->needs_keyboard()); if (hideKeyboard && !showKeyboard) Fl::screen_driver()->release_keyboard(); if (showKeyboard && !hideKeyboard) Fl::screen_driver()->request_keyboard(); if (o && !o->visible_focus()) return; Fl_Widget *p = focus_; if (o != p) { Fl::compose_reset(); focus_ = o; // make sure that fl_xfocus is set to the top level window // of this widget, or fl_fix_focus will clear our focus again if (o) { Fl_Window *win = 0, *w1 = o->as_window(); if (!w1) w1 = o->window(); while (w1) { win=w1; w1=win->window(); } if (win) { if (fl_xfocus != win) { Fl_Window_Driver::driver(win)->take_focus(); fl_xfocus = win; } } } // take focus from the old focused window fl_oldfocus = 0; int old_event = e_number; e_number = FL_UNFOCUS; for (; p; p = p->parent()) { p->handle(FL_UNFOCUS); fl_oldfocus = p; } e_number = old_event; } } static char dnd_flag = 0; // make 'belowmouse' send DND_LEAVE instead of LEAVE /** Sets the widget that is below the mouse. This is for highlighting buttons. It is not used to send FL_PUSH or FL_MOVE directly, for several obscure reasons, but those events typically go to this widget. This is also the first widget tried for FL_SHORTCUT events. If you change the belowmouse widget, the previous one and all parents (that don't contain the new widget) are sent FL_LEAVE events. Changing this does \e not send FL_ENTER to this or any widget, because sending FL_ENTER is supposed to \e test if the widget wants the mouse (by it returning non-zero from handle()). */ void Fl::belowmouse(Fl_Widget *o) { if (grab()) return; // don't do anything while grab is on Fl_Widget *p = belowmouse_; if (o != p) { belowmouse_ = o; int old_event = e_number; e_number = dnd_flag ? FL_DND_LEAVE : FL_LEAVE; for (; p && !p->contains(o); p = p->parent()) { p->handle(e_number); } e_number = old_event; } } /** Sets the widget that is being pushed. FL_DRAG or FL_RELEASE (and any more FL_PUSH) events will be sent to this widget. If you change the pushed widget, the previous one and all parents (that don't contain the new widget) are sent FL_RELEASE events. Changing this does \e not send FL_PUSH to this or any widget, because sending FL_PUSH is supposed to \e test if the widget wants the mouse (by it returning non-zero from handle()). */ void Fl::pushed(Fl_Widget *o) { pushed_ = o; } static void nothing(Fl_Widget *) {} void (*Fl_Tooltip::enter)(Fl_Widget *) = nothing; void (*Fl_Tooltip::exit)(Fl_Widget *) = nothing; // Update modal(), focus() and other state according to system state, // and send FL_ENTER, FL_LEAVE, FL_FOCUS, and/or FL_UNFOCUS events. // This is the only function that produces these events in response // to system activity. // This is called whenever a window is added or hidden, and whenever // X says the focus or mouse window have changed. void fl_fix_focus() { #ifdef DEBUG puts("fl_fix_focus();"); #endif // DEBUG if (Fl::grab()) return; // don't do anything while grab is on. // set focus based on Fl::modal() and fl_xfocus Fl_Widget* w = fl_xfocus; if (w) { int saved = Fl::e_keysym; if (Fl::e_keysym < (FL_Button + FL_LEFT_MOUSE) || Fl::e_keysym > (FL_Button + FL_RIGHT_MOUSE)) Fl::e_keysym = 0; // make sure widgets don't think a keystroke moved focus while (w->parent()) w = w->parent(); if (Fl::modal()) w = Fl::modal(); if (!w->contains(Fl::focus())) if (!w->take_focus()) Fl::focus(w); Fl::e_keysym = saved; } else Fl::focus(0); // MRS: Originally we checked the button state, but a user reported that it // broke click-to-focus in FLWM?!? // if (!(Fl::event_state() & 0x7f00000 /*FL_BUTTONS*/)) { if (!Fl::pushed()) { // set belowmouse based on Fl::modal() and fl_xmousewin: w = fl_xmousewin; if (w) { if (Fl::modal()) w = Fl::modal(); if (!w->contains(Fl::belowmouse())) { int old_event = Fl::e_number; w->handle(Fl::e_number = FL_ENTER); Fl::e_number = old_event; if (!w->contains(Fl::belowmouse())) Fl::belowmouse(w); } else { // send a FL_MOVE event so the enter/leave state is up to date Fl::e_x = Fl::e_x_root - fl_xmousewin->x(); Fl::e_y = Fl::e_y_root - fl_xmousewin->y(); int old_event = Fl::e_number; w->handle(Fl::e_number = FL_MOVE); Fl::e_number = old_event; } } else { Fl::belowmouse(0); Fl_Tooltip::enter(0); } } } // This function is called by ~Fl_Widget() and by Fl_Widget::deactivate() // and by Fl_Widget::hide(). It indicates that the widget does not want // to receive any more events, and also removes all global variables that // point at the widget. // I changed this from the 1.0.1 behavior, the older version could send // FL_LEAVE or FL_UNFOCUS events to the widget. This appears to not be // desirable behavior and caused flwm to crash. void fl_throw_focus(Fl_Widget *o) { #ifdef DEBUG printf("fl_throw_focus(o=%p)\n", o); #endif // DEBUG if (o->contains(Fl::pushed())) Fl::pushed_ = 0; if (o->contains(fl_selection_requestor)) fl_selection_requestor = 0; if (o->contains(Fl::belowmouse())) Fl::belowmouse_ = 0; if (o->contains(Fl::focus())) Fl::focus_ = 0; if (o == fl_xfocus) fl_xfocus = 0; if (o == Fl_Tooltip::current()) Fl_Tooltip::current(0); if (o == fl_xmousewin) fl_xmousewin = 0; Fl_Tooltip::exit(o); fl_fix_focus(); } //////////////////////////////////////////////////////////////// // Find the first active_r() widget, starting at the widget wi and // walking up the widget hierarchy to the top level window. // // In other words: find_active() returns an active group that contains // the inactive widget and all inactive parent groups. // // This is used to send FL_SHORTCUT events to the Fl::belowmouse() widget // in case the target widget itself is !active_r(). In this case the event // is sent to the first active_r() parent. // // This prevents sending events to inactive widgets that might get the // input focus otherwise. The search is fast and light and avoids calling // !active_r() multiple times. // See STR #3216. // // Returns: first active_r() widget "above" the widget wi or NULL if // no widget is active. May return the top level window. static Fl_Widget *find_active(Fl_Widget *wi) { Fl_Widget *found = 0; for (; wi; wi = wi->parent()) { if (wi->active()) { if (!found) found = wi; } else found = 0; } return found; } //////////////////////////////////////////////////////////////// // Call to->handle(), but first replace the mouse x/y with the correct // values to account for nested windows. 'window' is the outermost // window the event was posted to by the system: static int send_event(int event, Fl_Widget* to, Fl_Window* window) { int dx, dy; int old_event = Fl::e_number; if (window) { dx = window->x(); dy = window->y(); } else { dx = dy = 0; } for (const Fl_Widget* w = to; w; w = w->parent()) { if (w->type() >= FL_WINDOW) { dx -= w->x(); dy -= w->y(); } } int save_x = Fl::e_x; Fl::e_x += dx; int save_y = Fl::e_y; Fl::e_y += dy; int ret = to->handle(Fl::e_number = event); Fl::e_number = old_event; Fl::e_y = save_y; Fl::e_x = save_x; return ret; } /** Give the reason for calling a callback. \return the reason for the current callback \see Fl_Widget::when(), Fl_Widget::do_callback(), Fl_Widget::callback() \since 1.4.0 */ Fl_Callback_Reason Fl::callback_reason() { return callback_reason_; } /** \brief Set a new event dispatch function. The event dispatch function is called after native events are converted to FLTK events, but before they are handled by FLTK. If the dispatch function Fl_Event_Dispatch \p d is set, it is up to the dispatch function to call Fl::handle_(int, Fl_Window*) or to ignore the event. The dispatch function itself must return 0 if it ignored the event, or non-zero if it used the event. If you call Fl::handle_(), then this will return the correct value. The event dispatch can be used to handle exceptions in FLTK events and callbacks before they reach the native event handler: \code int myHandler(int e, Fl_Window *w) { try { return Fl::handle_(e, w); } catch () { ... } } main() { Fl::event_dispatch(myHandler); ... Fl::run(); } \endcode \param d new dispatch function, or NULL \see Fl::add_handler(Fl_Event_Handler) \see Fl::handle(int, Fl_Window*) \see Fl::handle_(int, Fl_Window*) */ void Fl::event_dispatch(Fl_Event_Dispatch d) { e_dispatch = d; } /** \brief Return the current event dispatch function. */ Fl_Event_Dispatch Fl::event_dispatch() { return e_dispatch; } /** \brief Handle events from the window system. This is called from the native event dispatch after native events have been converted to FLTK notation. This function calls Fl::handle_(int, Fl_Window*) unless the user sets a dispatch function. If a user dispatch function is set, the user must make sure that Fl::handle_() is called, or the event will be ignored. \param e the event type (Fl::event_number() is not yet set) \param window the window that caused this event \return 0 if the event was not handled \see Fl::add_handler(Fl_Event_Handler) \see Fl::event_dispatch(Fl_Event_Dispatch) */ int Fl::handle(int e, Fl_Window* window) { if (e_dispatch) { return e_dispatch(e, window); } else { return handle_(e, window); } } /** \brief Handle events from the window system. This function is called from the native event dispatch, unless the user sets another dispatch function. In that case, the user dispatch function must decide when to call Fl::handle_(int, Fl_Window*) Callbacks can set \p FL_REASON_CLOSED and \p FL_REASON_CANCELLED. \param e the event type (Fl::event_number() is not yet set) \param window the window that caused this event \return 0 if the event was not handled \see Fl::event_dispatch(Fl_Event_Dispatch) */ int Fl::handle_(int e, Fl_Window* window) { e_number = e; if (fl_local_grab) return fl_local_grab(e); Fl_Widget* wi = window; switch (e) { case FL_CLOSE: if ( grab() || (modal() && window != modal()) ) return 0; wi->do_callback(FL_REASON_CLOSED); return 1; case FL_SHOW: wi->Fl_Widget::show(); // this calls Fl_Widget::show(), not Fl_Window::show() return 1; case FL_HIDE: wi->Fl_Widget::hide(); // this calls Fl_Widget::hide(), not Fl_Window::hide() return 1; case FL_PUSH: #ifdef DEBUG printf("Fl::handle(e=%d, window=%p);\n", e, window); #endif // DEBUG if (grab()) wi = grab(); else if (modal() && wi != modal()) return 0; pushed_ = wi; Fl_Tooltip::current(wi); if (send_event(e, wi, window)) return 1; // raise windows that are clicked on: window->show(); return 1; case FL_DND_ENTER: case FL_DND_DRAG: dnd_flag = 1; break; case FL_DND_LEAVE: dnd_flag = 1; belowmouse(0); dnd_flag = 0; return 1; case FL_DND_RELEASE: wi = belowmouse(); break; case FL_MOVE: case FL_DRAG: fl_xmousewin = window; // this should already be set, but just in case. if (pushed()) { wi = pushed(); if (grab()) wi = grab(); e_number = e = FL_DRAG; break; } if (modal() && wi != modal()) wi = 0; if (grab()) wi = grab(); { int ret; Fl_Widget* pbm = belowmouse(); ret = (wi && send_event(e, wi, window)); if (pbm != belowmouse()) { #ifdef DEBUG printf("Fl::handle(e=%d, window=%p) -- Fl_Tooltip::enter(%p);\n", e, window, belowmouse()); #endif // DEBUG Fl_Tooltip::enter(belowmouse()); } return ret; } case FL_RELEASE: { // Mouse drag release mode - Jul 14, 2023, Albrecht-S (WIP): // 0 = old: *first* mouse button release ("up") turns drag mode off // 1 = new: *last* mouse button release ("up") turns drag mode off // The latter enables dragging with two or more pressed mouse buttons // and to continue dragging (i.e. sending FL_DRAG) until the *last* // mouse button is released. // See fltk.general, thread started on Jul 12, 2023 // "Is handling simultaneous Left-click and Right-click drags supported?" static const int drag_release = 1; // should be 1 => new behavior since Jul 2023 // Implementation notes: // (1) Mode 1 (new): only if *all* mouse buttons have been released, the // Fl::pushed_ widget is reset to 0 (NULL) so subsequent system "move" // events are no longer sent as FL_DRAG events. // (2) Mode 0 (old): Fl::pushed_ was reset on the *first* mouse button release. // (3) The constant 'drag_release' should be removed once the new mode has been // confirmed to work correctly and no side effects have been observed. // Hint: remove condition "!drag_release || " twice (below). // printf("FL_RELEASE: window=%p, pushed() = %p, grab() = %p, modal() = %p, drag_release = %d, buttons = 0x%x\n", // window, pushed(), grab(), modal(), drag_release, Fl::event_buttons()>>24); if (grab()) { wi = grab(); if (!drag_release || !Fl::event_buttons()) pushed_ = 0; // must be zero before callback is done! } else if (pushed()) { wi = pushed(); if (!drag_release || !Fl::event_buttons()) pushed_ = 0; // must be zero before callback is done! } else if (modal() && wi != modal()) return 0; int r = send_event(e, wi, window); fl_fix_focus(); return r; } case FL_UNFOCUS: window = 0; // FALLTHROUGH case FL_FOCUS: fl_xfocus = window; fl_fix_focus(); return 1; case FL_KEYUP: // Send the key-up to the current focus widget. This is not // always the same widget that received the corresponding // FL_KEYBOARD event because focus may have changed. // Sending the KEYUP to the right KEYDOWN is possible, but // would require that we track the KEYDOWN for every possible // key stroke (users may hold down multiple keys!) and then // make sure that the widget still exists before sending // a KEYUP there. I believe that the current solution is // "close enough". for (wi = grab() ? grab() : focus(); wi; wi = wi->parent()) { if (send_event(FL_KEYUP, wi, window)) return 1; } return 0; case FL_KEYBOARD: #ifdef DEBUG printf("Fl::handle(e=%d, window=%p);\n", e, window); #endif // DEBUG Fl_Tooltip::enter((Fl_Widget*)0); fl_xfocus = window; // this should not happen! But maybe it does: // Try it as keystroke, sending it to focus and all parents: for (wi = grab() ? grab() : focus(); wi; wi = wi->parent()) { if (send_event(FL_KEYBOARD, wi, window)) return 1; } // recursive call to try shortcut: if (handle(FL_SHORTCUT, window)) return 1; // and then try a shortcut with the case of the text swapped, by // changing the text and falling through to FL_SHORTCUT case: { unsigned char* c = (unsigned char*)event_text(); // cast away const if (!isalpha(*c)) return 0; *c = isupper(*c) ? tolower(*c) : toupper(*c); } e_number = e = FL_SHORTCUT; case FL_SHORTCUT: if (grab()) {wi = grab(); break;} // send it to grab window // Try it as shortcut, sending to mouse widget and all parents: wi = find_active(belowmouse()); // STR #3216 if (!wi) { wi = modal(); if (!wi) wi = window; } else if (wi->window() != first_window()) { if (send_event(FL_SHORTCUT, first_window(), first_window())) return 1; } for (; wi; wi = wi->parent()) { if (send_event(FL_SHORTCUT, wi, wi->window())) return 1; } // try using add_handle() functions: if (send_handlers(FL_SHORTCUT)) return 1; // make Escape key close windows: if (event_key()==FL_Escape) { wi = modal(); if (!wi) wi = window; wi->do_callback(FL_REASON_CANCELLED); return 1; } return 0; case FL_ENTER: #ifdef DEBUG printf("Fl::handle(e=%d, window=%p);\n", e, window); #endif // DEBUG fl_xmousewin = window; fl_fix_focus(); Fl_Tooltip::enter(belowmouse()); return 1; case FL_LEAVE: #ifdef DEBUG printf("Fl::handle(e=%d, window=%p);\n", e, window); #endif // DEBUG if (!pushed_) { belowmouse(0); Fl_Tooltip::enter(0); } if (window == fl_xmousewin) {fl_xmousewin = 0; fl_fix_focus();} return 1; case FL_MOUSEWHEEL: fl_xfocus = window; // this should not happen! But maybe it does: // Try sending it to the "grab" first if (grab() && grab()!=modal() && grab()!=window) { if (send_event(FL_MOUSEWHEEL, grab(), window)) return 1; } // Now try sending it to the "modal" window if (modal()) { send_event(FL_MOUSEWHEEL, modal(), window); return 1; } // Finally try sending it to the window, the event occurred in if (send_event(FL_MOUSEWHEEL, window, window->top_window())) return 1; default: break; } if (wi && send_event(e, wi, window)) { dnd_flag = 0; return 1; } dnd_flag = 0; return send_handlers(e); } //////////////////////////////////////////////////////////////// // Back compatibility cut & paste functions for fltk 1.1 only: /** Back-compatibility only: The single-argument call can be used to move the selection to another widget or to set the owner to NULL, without changing the actual text of the selection. FL_SELECTIONCLEAR is sent to the previous selection owner, if any. Copying the buffer every time the selection is changed is obviously wasteful, especially for large selections. An interface will probably be added in a future version to allow the selection to be made by a callback function. The current interface will be emulated on top of this. */ void Fl::selection_owner(Fl_Widget *owner) {selection_owner_ = owner;} /** Changes the current selection. The block of text is copied to an internal buffer by FLTK (be careful if doing this in response to an FL_PASTE as this \e may be the same buffer returned by event_text()). The selection_owner() widget is set to the passed owner. */ void Fl::selection(Fl_Widget &owner, const char* text, int len) { selection_owner_ = &owner; Fl::copy(text, len, 0); } /** Backward compatibility only. This calls Fl::paste(receiver, 0); \see Fl::paste(Fl_Widget &receiver, int clipboard, const char* type) */ void Fl::paste(Fl_Widget &receiver) { Fl::screen_driver()->paste(receiver, 0, Fl::clipboard_plain_text); } void Fl::paste(Fl_Widget &receiver, int clipboard, const char *type) { Fl::screen_driver()->paste(receiver, clipboard, type); } //////////////////////////////////////////////////////////////// void Fl_Widget::redraw() { damage(FL_DAMAGE_ALL); } void Fl_Widget::redraw_label() { if (window()) { if (box() == FL_NO_BOX) { // Widgets with the FL_NO_BOX boxtype need a parent to // redraw, since it is responsible for redrawing the // background... int X = x() > 0 ? x() - 1 : 0; int Y = y() > 0 ? y() - 1 : 0; window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2); } if (align() && !(align() & FL_ALIGN_INSIDE) && window()->shown()) { // If the label is not inside the widget, compute the location of // the label and redraw the window within that bounding box... int W = 0, H = 0; label_.measure(W, H); W += 5; // Add a little to the size of the label to cover overflow H += 5; // FIXME: // This assumes that measure() returns the correct outline, which it does // not in all possible cases of alignment combined with image and symbols. switch (align() & 0x0f) { case FL_ALIGN_TOP_LEFT: window()->damage(FL_DAMAGE_EXPOSE, x(), y()-H, W, H); break; case FL_ALIGN_TOP: window()->damage(FL_DAMAGE_EXPOSE, x()+(w()-W)/2, y()-H, W, H); break; case FL_ALIGN_TOP_RIGHT: window()->damage(FL_DAMAGE_EXPOSE, x()+w()-W, y()-H, W, H); break; case FL_ALIGN_LEFT_TOP: window()->damage(FL_DAMAGE_EXPOSE, x()-W, y(), W, H); break; case FL_ALIGN_RIGHT_TOP: window()->damage(FL_DAMAGE_EXPOSE, x()+w(), y(), W, H); break; case FL_ALIGN_LEFT: window()->damage(FL_DAMAGE_EXPOSE, x()-W, y()+(h()-H)/2, W, H); break; case FL_ALIGN_RIGHT: window()->damage(FL_DAMAGE_EXPOSE, x()+w(), y()+(h()-H)/2, W, H); break; case FL_ALIGN_LEFT_BOTTOM: window()->damage(FL_DAMAGE_EXPOSE, x()-W, y()+h()-H, W, H); break; case FL_ALIGN_RIGHT_BOTTOM: window()->damage(FL_DAMAGE_EXPOSE, x()+w(), y()+h()-H, W, H); break; case FL_ALIGN_BOTTOM_LEFT: window()->damage(FL_DAMAGE_EXPOSE, x(), y()+h(), W, H); break; case FL_ALIGN_BOTTOM: window()->damage(FL_DAMAGE_EXPOSE, x()+(w()-W)/2, y()+h(), W, H); break; case FL_ALIGN_BOTTOM_RIGHT: window()->damage(FL_DAMAGE_EXPOSE, x()+w()-W, y()+h(), W, H); break; default: window()->damage(FL_DAMAGE_ALL); break; } } else { // The label is inside the widget, so just redraw the widget itself... damage(FL_DAMAGE_ALL); } } } void Fl_Widget::damage(uchar fl) { if (type() < FL_WINDOW) { // damage only the rectangle covered by a child widget: damage(fl, x(), y(), w(), h()); } else { // damage entire window by deleting the region: Fl_X* i = Fl_X::flx((Fl_Window*)this); if (!i) return; // window not mapped, so ignore it if (i->region) { fl_graphics_driver->XDestroyRegion(i->region); i->region = 0; } damage_ |= fl; Fl::damage(FL_DAMAGE_CHILD); } } void Fl_Widget::damage(uchar fl, int X, int Y, int W, int H) { Fl_Widget* wi = this; // mark all parent widgets between this and window with FL_DAMAGE_CHILD: while (wi->type() < FL_WINDOW) { wi->damage_ |= fl; wi = wi->parent(); if (!wi) return; fl = FL_DAMAGE_CHILD; } Fl_X* i = Fl_X::flx((Fl_Window*)wi); if (!i) return; // window not mapped, so ignore it // clip the damage to the window and quit if none: if (X < 0) {W += X; X = 0;} if (Y < 0) {H += Y; Y = 0;} if (W > wi->w()-X) W = wi->w()-X; if (H > wi->h()-Y) H = wi->h()-Y; if (W <= 0 || H <= 0) return; if (!X && !Y && W==wi->w() && H==wi->h()) { // if damage covers entire window delete region: wi->damage(fl); return; } if (wi->damage()) { // if we already have damage we must merge with existing region: if (i->region) { fl_graphics_driver->add_rectangle_to_region(i->region, X, Y, W, H); } wi->damage_ |= fl; } else { // create a new region: if (i->region) fl_graphics_driver->XDestroyRegion(i->region); i->region = fl_graphics_driver->XRectangleRegion(X,Y,W,H); wi->damage_ = fl; } Fl::damage(FL_DAMAGE_CHILD); } // // The following methods allow callbacks to schedule the deletion of // widgets at "safe" times. // static int num_dwidgets = 0, alloc_dwidgets = 0; static Fl_Widget **dwidgets = 0; /** Schedules a widget for deletion at the next call to the event loop. Use this method to delete a widget inside a callback function. To avoid early deletion of widgets, this function should be called toward the end of a callback and only after any call to the event loop (Fl::wait(), Fl::flush(), Fl::check(), fl_ask(), etc.). When deleting groups or windows, you must only delete the group or window widget and not the individual child widgets. \since FLTK 1.3.4 the widget will be hidden immediately, but the actual destruction will be delayed until the event loop is finished. Up to FLTK 1.3.3 windows wouldn't be hidden before the event loop was done, hence you had to hide() a window in your window close callback if you called Fl::delete_widget() to destroy (and hide) the window. \since FLTK 1.3.0 it is not necessary to remove widgets from their parent groups or windows before calling this, because it will be done in the widget's destructor, but it is not a failure to do this nevertheless. \note In FLTK 1.1 you \b must remove widgets from their parent group (or window) before deleting them. \see Fl_Widget::~Fl_Widget() */ void Fl::delete_widget(Fl_Widget *wi) { if (!wi) return; // if the widget is shown(), hide() it (FLTK 1.3.4) if (wi->visible_r()) wi->hide(); Fl_Window *win = wi->as_window(); if (win && win->shown()) win->hide(); // case of iconified window // don't add the same widget twice to the widget delete list for (int i = 0; i < num_dwidgets; i++) { if (dwidgets[i]==wi) return; } if (num_dwidgets >= alloc_dwidgets) { Fl_Widget **temp; temp = new Fl_Widget *[alloc_dwidgets + 10]; if (alloc_dwidgets) { memcpy(temp, dwidgets, alloc_dwidgets * sizeof(Fl_Widget *)); delete[] dwidgets; } dwidgets = temp; alloc_dwidgets += 10; } dwidgets[num_dwidgets] = wi; num_dwidgets ++; } /** Deletes widgets previously scheduled for deletion. This is for internal use only. You should never call this directly. Fl::do_widget_deletion() is called from the FLTK event loop or whenever you call Fl::wait(). The previously scheduled widgets are deleted in the same order they were scheduled by calling Fl::delete_widget(). \see Fl::delete_widget(Fl_Widget *wi) */ void Fl::do_widget_deletion() { if (!num_dwidgets) return; for (int i = 0; i < num_dwidgets; i ++) delete dwidgets[i]; num_dwidgets = 0; } static Fl_Widget ***widget_watch = 0; static int num_widget_watch = 0; static int max_widget_watch = 0; /** Adds a widget pointer to the widget watch list. \note Internal use only, please use class Fl_Widget_Tracker instead. This can be used, if it is possible that a widget might be deleted during a callback or similar function. The widget pointer must be added to the watch list before calling the callback. After the callback the widget pointer can be queried, if it is NULL. \e If it is NULL, then the widget has been deleted during the callback and must not be accessed anymore. If the widget pointer is \e not NULL, then the widget has not been deleted and can be accessed safely. After accessing the widget, the widget pointer must be released from the watch list by calling Fl::release_widget_pointer(). Example for a button that is clicked (from its handle() method): \code Fl_Widget *wp = this; // save 'this' in a pointer variable Fl::watch_widget_pointer(wp); // add the pointer to the watch list set_changed(); // set the changed flag do_callback(); // call the callback if (!wp) { // the widget has been deleted // DO NOT ACCESS THE DELETED WIDGET ! } else { // the widget still exists clear_changed(); // reset the changed flag } Fl::release_widget_pointer(wp); // remove the pointer from the watch list \endcode This works, because all widgets call Fl::clear_widget_pointer() in their destructors. \see Fl::release_widget_pointer() \see Fl::clear_widget_pointer() An easier and more convenient method to control widget deletion during callbacks is to use the class Fl_Widget_Tracker with a local (automatic) variable. \see class Fl_Widget_Tracker */ void Fl::watch_widget_pointer(Fl_Widget *&w) { Fl_Widget **wp = &w; int i; for (i=0; i %8p\n", num_widget_watch,num_widget_watch,wp,*wp); fflush(stdout); #endif // DEBUG_WATCH } /** Releases a widget pointer from the watch list. This is used to remove a widget pointer that has been added to the watch list with Fl::watch_widget_pointer(), when it is not needed anymore. \note Internal use only, please use class Fl_Widget_Tracker instead. \see Fl::watch_widget_pointer() */ void Fl::release_widget_pointer(Fl_Widget *&w) { Fl_Widget **wp = &w; int i,j=0; for (i=0; i %8p\n", i+1, num_widget_watch, wp, *wp); } #endif //DEBUG_WATCH } num_widget_watch = j; #ifdef DEBUG_WATCH printf (" num_widget_watch = %d\n\n",num_widget_watch); fflush(stdout); #endif // DEBUG_WATCH return; } /** Clears a widget pointer \e in the watch list. This is called when a widget is destroyed (by its destructor). You should never call this directly. \note Internal use only ! This method searches the widget watch list for pointers to the widget and clears each pointer that points to it. Widget pointers can be added to the widget watch list by calling Fl::watch_widget_pointer() or by using the helper class Fl_Widget_Tracker (recommended). \see Fl::watch_widget_pointer() \see class Fl_Widget_Tracker */ void Fl::clear_widget_pointer(Fl_Widget const *w) { if (w==0L) return; int i; for (i=0; i= 0 ) Fl_Preferences prefs(Fl_Preferences::CORE_USER, "fltk.org", "fltk"); Fl_Preferences opt_prefs(prefs, "options"); opt_prefs.get("ArrowFocus", tmp, -1); if (tmp >= 0) options_[OPTION_ARROW_FOCUS] = tmp; //opt_prefs.get("NativeFilechooser", tmp, -1); //if (tmp >= 0) options_[OPTION_NATIVE_FILECHOOSER] = tmp; //opt_prefs.get("FilechooserPreview", tmp, -1); //if (tmp >= 0) options_[OPTION_FILECHOOSER_PREVIEW] = tmp; opt_prefs.get("VisibleFocus", tmp, -1); if (tmp >= 0) options_[OPTION_VISIBLE_FOCUS] = tmp; opt_prefs.get("DNDText", tmp, -1); if (tmp >= 0) options_[OPTION_DND_TEXT] = tmp; opt_prefs.get("ShowTooltips", tmp, -1); if (tmp >= 0) options_[OPTION_SHOW_TOOLTIPS] = tmp; opt_prefs.get("FNFCUsesGTK", tmp, -1); if (tmp >= 0) options_[OPTION_FNFC_USES_GTK] = tmp; opt_prefs.get("PrintUsesGTK", tmp, -1); if (tmp >= 0) options_[OPTION_PRINTER_USES_GTK] = tmp; opt_prefs.get("ShowZoomFactor", tmp, -1); if (tmp >= 0) options_[OPTION_SHOW_SCALING] = tmp; opt_prefs.get("UseZenity", tmp, -1); if (tmp >= 0) options_[OPTION_FNFC_USES_ZENITY] = tmp; opt_prefs.get("UseKdialog", tmp, -1); if (tmp >= 0) options_[OPTION_FNFC_USES_KDIALOG] = tmp; opt_prefs.get("SimpleZoomShortcut", tmp, -1); if (tmp >= 0) options_[OPTION_SIMPLE_ZOOM_SHORTCUT] = tmp; } { // now, if the developer has registered this app, we could ask for per-application preferences } options_read_ = 1; } if (opt<0 || opt>=OPTION_LAST) return false; return (bool)(options_[opt]!=0); } /** Override an option while the application is running. Apps can override the machine settings and the user settings by calling `Fl::option(option, bool)`. The override takes effect immediately for this option for all widgets in the app for the life time of the app. The override is not saved anywhere, and relaunching the app will restore the old settings. Example: \code Fl::option(Fl::OPTION_ARROW_FOCUS, true); // on Fl::option(Fl::OPTION_ARROW_FOCUS, false); // off \endcode \param opt which option \param val set to true or false \see enum Fl::Fl_Option \see bool Fl::option(Fl_Option) */ void Fl::option(Fl_Option opt, bool val) { if (opt<0 || opt>=OPTION_LAST) return; if (!options_read_) { // make sure that the options_ array is filled in option(opt); } options_[opt] = val; } // Helper class Fl_Widget_Tracker /** The constructor adds a widget to the watch list. */ Fl_Widget_Tracker::Fl_Widget_Tracker(Fl_Widget *wi) { wp_ = wi; Fl::watch_widget_pointer(wp_); // add pointer to watch list } /** The destructor removes a widget from the watch list. */ Fl_Widget_Tracker::~Fl_Widget_Tracker() { Fl::release_widget_pointer(wp_); // remove pointer from watch list } int Fl::use_high_res_GL_ = 0; int Fl::draw_GL_text_with_textures_ = 1; int Fl::dnd() { return Fl::screen_driver()->dnd(); } int Fl::event_key(int k) { return screen_driver()->event_key(k); } int Fl::get_key(int k) { return screen_driver()->get_key(k); } void Fl::get_mouse(int &x, int &y) { Fl::screen_driver()->get_mouse(x, y); } const char * fl_filename_name(const char *name) { return Fl::system_driver()->filename_name(name); } void Fl::copy(const char *stuff, int len, int clipboard, const char *type) { Fl::screen_driver()->copy(stuff, len, clipboard, type); } int Fl::clipboard_contains(const char *type) { return Fl::screen_driver()->clipboard_contains(type); } /** Adds file descriptor fd to listen to. When the fd becomes ready for reading Fl::wait() will call the callback and then return. The callback is passed the fd and the arbitrary void* argument. This version takes a when bitfield, with the bits FL_READ, FL_WRITE, and FL_EXCEPT defined, to indicate when the callback should be done. There can only be one callback of each type for a file descriptor. Fl::remove_fd() gets rid of all the callbacks for a given file descriptor. Under UNIX/Linux/macOS any file descriptor can be monitored (files, devices, pipes, sockets, etc.). Due to limitations in Microsoft Windows, Windows applications can only monitor sockets. Under macOS, Fl::add_fd() opens the display if that's not been done before. */ void Fl::add_fd(int fd, int when, Fl_FD_Handler cb, void *d) { Fl::system_driver()->add_fd(fd, when, cb, d); } /** Adds file descriptor fd to listen to. See Fl::add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0) for details */ void Fl::add_fd(int fd, Fl_FD_Handler cb, void *d) { Fl::system_driver()->add_fd(fd, cb, d); } void Fl::remove_fd(int fd, int when) { Fl::system_driver()->remove_fd(fd, when); } void Fl::remove_fd(int fd) { Fl::system_driver()->remove_fd(fd); } /** Enables the system input methods facilities. This is the default. \see disable_im() */ void Fl::enable_im() { Fl::screen_driver()->enable_im(); } /** Disables the system input methods facilities. \see enable_im() */ void Fl::disable_im() { Fl::screen_driver()->disable_im(); } /** Opens the display. Automatically called by the library when the first window is show()'n. Does nothing if the display is already open. \note Requires \#include */ void fl_open_display() { Fl::screen_driver()->open_display(); } /** Closes the connection to the windowing system when that's possible. You do \e not need to call this to exit, and in fact it is faster to not do so. It may be useful to call this if you want your program to continue without a GUI. You cannot open the display again, and cannot call any FLTK functions. \note Requires \#include */ void fl_close_display() { Fl::screen_driver()->close_display(); } #ifdef FL_DOXYGEN /** Prevent the FLTK library from using its Wayland backend and force it to use its X11 backend. Put this declaration somewhere in your source code outside the body of any function: \code FL_EXPORT bool fl_disable_wayland = true; \endcode This declaration makes sure that source code developed for FLTK 1.3, including X11-specific code, will build and run with FLTK 1.4 and its Wayland platform with a single line source code level change. This declaration has no effect on non-Wayland platforms. Don't add this declaration if you want the Wayland backend to be used when it's available. \note Please see also chapter 2.1 of README.Wayland.txt for further information on how to build your application to ensure that this declaration is effective. \since 1.4.0 */ FL_EXPORT bool fl_disable_wayland = true; #endif // FL_DOXYGEN FL_EXPORT Window fl_xid_(const Fl_Window *w) { Fl_X *temp = Fl_X::flx(w); return temp ? (Window)temp->xid : 0; } /** \addtogroup group_macosx \{ */ /** Register a function called for each file dropped onto an application icon. This function is effective only on the Mac OS X platform. \c cb will be called with a single Unix-style file name and path. If multiple files were dropped, \c cb will be called multiple times. This function should be called before \c fl_open_display() is called, either directly or indirectly (this happens at the first \c show() of a window), to be effective for files dropped on the application icon at launch time. It can also be called at any point to change the function used to open dropped files. A call with a NULL argument, after a previous call, makes the app ignore files dropped later. */ void fl_open_callback(void (*cb)(const char *)) { Fl::system_driver()->open_callback(cb); } /** @} */ Fl_Font Fl::set_fonts(const char* xstarname) { return Fl_Graphics_Driver::default_driver().set_fonts(xstarname); } const char* Fl::get_font_name(Fl_Font fnum, int* ap) { return Fl_Graphics_Driver::default_driver().get_font_name(fnum, ap); } int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { return Fl_Graphics_Driver::default_driver().get_font_sizes(fnum, sizep); } /** Gets the GUI scaling factor of screen number \p n. The valid range of \p n is 0 .. Fl::screen_count() - 1. The return value is \c 1.0 if screen scaling is not supported or \p n is outside the valid range. \return Current screen scaling factor (default: \c 1.0) \see Fl::screen_count() \see Fl::screen_scaling_supported() \since 1.4.0 */ float Fl::screen_scale(int n) { if (!Fl::screen_scaling_supported() || n < 0 || n >= Fl::screen_count()) return 1.; return Fl::screen_driver()->scale(n); } /** Sets the GUI scaling factor of screen number \p n. The valid range of \p n is 0 .. Fl::screen_count() - 1. This method does nothing if \p n is out of range or screen scaling is not supported by this platform. Otherwise it also sets the scaling factor of all windows mapped to screen number \p n or all screens, depending on the type of screen scaling support on the platform. \param[in] n screen number \param[in] factor scaling factor of screen \p n \see Fl::screen_scaling_supported() \since 1.4.0 */ void Fl::screen_scale(int n, float factor) { Fl_Screen_Driver::APP_SCALING_CAPABILITY capability = Fl::screen_driver()->rescalable(); if (!capability || n < 0 || n >= Fl::screen_count()) return; if (capability == Fl_Screen_Driver::SYSTEMWIDE_APP_SCALING) { for (int s = 0; s < Fl::screen_count(); s++) { Fl::screen_driver()->rescale_all_windows_from_screen(s, factor, factor); } } else Fl::screen_driver()->rescale_all_windows_from_screen(n, factor, factor); } /** Returns whether scaling factors are supported by this platform. \retval 0 scaling factors are not supported by this platform \retval 1 a single scaling factor is shared by all screens \retval 2 each screen can have its own scaling factor \see Fl::screen_scale(int) \since 1.4.0 */ int Fl::screen_scaling_supported() { return Fl::screen_driver()->rescalable(); } /** Controls the possibility to scale all windows by ctrl/+/-/0/ or cmd/+/-/0/. This function \b should be called before fl_open_display() runs. If it is not called, the default is to handle these keys for window scaling. \note This function can currently only be used to switch the internal handler \b off, i.e. \p value must be 0 (zero) - all other values result in undefined behavior and are reserved for future extension. \param value 0 to stop recognition of ctrl/+/-/0/ (or cmd/+/-/0/ under macOS) keys as window scaling. \since 1.4.0 */ void Fl::keyboard_screen_scaling(int value) { Fl_Screen_Driver::keyboard_screen_scaling = value; } /** Run a command line on the computer */ int Fl::system(const char *command) { return Fl::system_driver()->system(command); } // Pointers you can use to change FLTK to another language. // Note: Similar pointers are defined in FL/fl_ask.H and src/fl_ask.cxx FL_EXPORT const char* fl_local_shift = Fl::system_driver()->shift_name(); FL_EXPORT const char* fl_local_meta = Fl::system_driver()->meta_name(); FL_EXPORT const char* fl_local_alt = Fl::system_driver()->alt_name(); FL_EXPORT const char* fl_local_ctrl = Fl::system_driver()->control_name(); /** Convert Windows commandline arguments to UTF-8. \note This function does nothing on other (non-Windows) platforms, hence you may call it on all platforms or only on Windows by using platform specific code like '\#ifdef _WIN32' etc. - it's your choice. Calling it on other platforms returns quickly w/o wasting much CPU time. This function must be called on Windows platforms in \c main() before the array \c argv is used if your program uses any commandline argument strings (these should be UTF-8 encoded). This applies also to standard FLTK commandline arguments like "-name" (class name) and "-title" (window title in the title bar). Unfortunately Windows \b neither provides commandline arguments in UTF-8 encoding \b nor as Windows "Wide Character" strings in the standard \c main() and/or the Windows specific \c WinMain() function. On Windows platforms (no matter which build system) this function calls a Windows specific function to retrieve commandline arguments as Windows "Wide Character" strings, converts these strings to an internally allocated buffer (or multiple buffers) and returns the result in \c argv. For implementation details please refer to the source code; however these details may be changed in the future. Note that \c argv is provided by reference so it can be overwritten. In the recommended simple form the function overwrites the variable \c argv and allocates a new array of strings pointed to by \c argv. You may use this form on all platforms and it is as simple as adding one line to old programs to make them work with international (UTF-8) commandline arguments. \code int main(int argc, char **argv) { Fl::args_to_utf8(argc, argv); // add this line // ... use argc and argv, e.g. for commandline parsing window->show(argc, argv); return Fl::run(); } \endcode For an example see 'examples/howto-parse-args.cxx' in the FLTK sources. If you want to retain the original \c argc and \c argv variables the following slightly longer and more complicated code works as well on all platforms. \code int main(int argc, char **argv) { char **argvn = argv; // must copy argv to work on all platforms int argcn = Fl::args_to_utf8(argc, argvn); // ... use argcn and argvn, e.g. for commandline parsing window->show(argcn, argvn); return Fl::run(); } \endcode \param[in] argc used only on non-Windows platforms \param[out] argv modified only on Windows platforms \returns argument count (always the same as argc) \since 1.4.0 \internal This function must not open the display, otherwise commandline processing (e.g. by fluid) would open the display. OTOH calling it when the display is opened wouldn't work either for the same reasons ('fluid -c' doesn't open the display). */ int Fl::args_to_utf8(int argc, char ** &argv) { return Fl::system_driver()->args_to_utf8(argc, argv); } fltk-1.4.3/src/Fl_Cairo.cxx0000644000175000017500000001726715004135251015613 0ustar albrechtalbrecht// // Special Cairo support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // This file implements the FLTK Cairo Window support (since 1.3.x): // // - ./configure --enable-cairo and/or --enable-cairoext // - cmake -D FLTK_OPTION_CAIRO_WINDOW and/or -D FLTK_OPTION_CAIRO_EXT // // Preprocessor macro FLTK_HAVE_CAIRO is defined for both options. // Preprocessor macro FLTK_HAVE_CAIRO_EXT is defined only for "cairoext". // Both macros are defined in 'FL/fl_config.h'. #include // includes #ifdef FLTK_HAVE_CAIRO // Define USE_MAC_OS for convenience (below). We use macOS specific features // if USE_MAC_OS is defined, otherwise we're using X11 (XQuartz) on macOS #if defined __APPLE__ && !defined(FLTK_USE_X11) #define USE_MAC_OS #include #endif #include #include // Cairo is currently supported for the following platforms: // Windows, macOS (Apple Quartz), X11, Wayland #if defined(_WIN32) // Windows # include #elif defined(FLTK_USE_WAYLAND) // Wayland or hybrid # include "../src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H" # include "../src/drivers/Wayland/Fl_Wayland_Window_Driver.H" # if defined(FLTK_USE_X11) # include # else static void *fl_gc = NULL; # endif #elif defined(FLTK_USE_X11) // X11 # include #elif defined(__APPLE__) // macOS # include #else # error Cairo is not supported on this platform. #endif // static initialization Fl_Cairo_State Fl::cairo_state_; ///< current Cairo context information // Fl_Cairo_State void Fl_Cairo_State::autolink(bool b) { #ifdef FLTK_HAVE_CAIROEXT autolink_ = b; #else Fl::fatal("In Fl::autolink(bool): Cairo autolink() feature is only " "available with CMake FLTK_OPTION_CAIRO_EXT " "or the enable-cairoext configure option.\n" "Quitting now."); #endif } /** Provides a Cairo context for window \a wi. This is needed in a draw() override if Fl::cairo_autolink_context() returns false, which is the default. The cairo_context() does not need to be freed as it is freed every time a new Cairo context is created. When the program terminates, a call to Fl::cairo_make_current(0) will destroy any residual context. \note A new Cairo context is not always re-created when this method is used. In particular, if the current graphical context and the current window didn't change between two calls, the previous gc is internally kept, thus optimizing the drawing performances. Also, after this call, Fl::cairo_cc() is adequately updated with this Cairo context. \note Only available when configure has the --enable-cairo option \return The valid cairo_t *cairo context associated to this window. \retval NULL if \a wi is NULL or maybe with GL windows under Wayland */ cairo_t *Fl::cairo_make_current(Fl_Window *wi) { if (!wi) return NULL; cairo_t *cairo_ctxt; #if defined(FLTK_USE_WAYLAND) if (fl_wl_display()) { // true means using wayland backend struct wld_window *xid = fl_wl_xid(wi); if (!xid->buffer) return NULL; // this may happen with GL windows cairo_ctxt = xid->buffer->draw_buffer.cairo_; cairo_state_.cc(cairo_ctxt, false); return cairo_ctxt; } #endif if (fl_gc == 0) { // means remove current cc Fl::cairo_cc(0); // destroy any previous cc cairo_state_.window(0); return 0; } // don't re-create a context if it's the same gc/window combination if (fl_gc == Fl::cairo_state_.gc() && fl_xid(wi) == (Window)Fl::cairo_state_.window()) return Fl::cairo_cc(); cairo_state_.window((void *)fl_xid(wi)); // Scale the Cairo context appropriately. This is platform dependent #if !defined(USE_MAC_OS) float scale = Fl::screen_scale(wi->screen_num()); // get the screen scaling factor #endif #if defined(FLTK_USE_X11) cairo_ctxt = Fl::cairo_make_current(0, wi->w() * scale, wi->h() * scale); #else // on macOS, scaling is done before by Fl_Window::make_current(), on Windows, the size is not used cairo_ctxt = Fl::cairo_make_current(fl_gc, wi->w(), wi->h()); #endif #if !defined(USE_MAC_OS) cairo_scale(cairo_ctxt, scale, scale); #endif return cairo_ctxt; } /* Creates transparently a cairo_surface_t object. gc is an HDC context in Windows, a CGContext* in Quartz, and a display on X11 (not used on this platform) */ static cairo_surface_t *cairo_create_surface(void *gc, int W, int H) { #if defined(FLTK_USE_X11) return cairo_xlib_surface_create(fl_display, fl_window, fl_visual->visual, W, H); #elif defined(FLTK_USE_WAYLAND) return NULL; #elif defined(_WIN32) return cairo_win32_surface_create((HDC)gc); #elif defined(__APPLE__) return cairo_quartz_surface_create_for_cg_context((CGContextRef)gc, W, H); #else #error Cairo is not supported on this platform. #endif } /** Creates a Cairo context from a \a gc only, gets its window size or offscreen size if fl_window is null. \note Only available if CMake FLTK_OPTION_CAIRO_WINDOW is enabled or configure has the --enable-cairo option. */ cairo_t *Fl::cairo_make_current(void *gc) { int W = 0, H = 0; #if defined(FLTK_USE_X11) || defined(FLTK_USE_WAYLAND) // FIXME X11 get W,H // gc will be the window handle here // # warning FIXME get W,H for cairo_make_current(void*) #elif defined(__APPLE__) if (fl_window) { W = Fl_Window::current()->w(); H = Fl_Window::current()->h(); } else { W = CGBitmapContextGetWidth(fl_gc); H = CGBitmapContextGetHeight(fl_gc); } #elif defined(_WIN32) // we don't need any W,H for Windows #else #error Cairo is not supported on this platform. #endif if (!gc) { Fl::cairo_cc(0); cairo_state_.gc(0); // keep track for next time return 0; } if (gc == Fl::cairo_state_.gc() && fl_window == (Window)Fl::cairo_state_.window() && cairo_state_.cc() != 0) return Fl::cairo_cc(); cairo_state_.gc(fl_gc); // keep track for next time cairo_surface_t *s = cairo_create_surface(gc, W, H); cairo_t *c = cairo_create(s); cairo_surface_destroy(s); cairo_state_.cc(c); return c; } /** Creates a Cairo context from a \p gc and the given size. \note Only available if CMake FLTK_OPTION_CAIRO_WINDOW is enabled or configure has the --enable-cairo option. */ cairo_t *Fl::cairo_make_current(void *gc, int W, int H) { if (gc == Fl::cairo_state_.gc() && fl_window == (Window)Fl::cairo_state_.window() && cairo_state_.cc() != 0) // no need to create a cc, just return that one return cairo_state_.cc(); // we need to (re-)create a fresh cc ... cairo_state_.gc(gc); // keep track for next time cairo_surface_t *s = cairo_create_surface(gc, W, H); #if defined(USE_MAC_OS) && defined(FLTK_HAVE_CAIROEXT) CGAffineTransform at = CGContextGetCTM((CGContextRef)gc); CGContextSaveGState((CGContextRef)gc); CGContextConcatCTM((CGContextRef)gc, CGAffineTransformInvert(at)); #endif cairo_t *c = cairo_create(s); #if defined(USE_MAC_OS) && defined(FLTK_HAVE_CAIROEXT) CGContextRestoreGState((CGContextRef)gc); #endif cairo_state_.cc(c); // and purge any previously owned context cairo_surface_destroy(s); return c; } // Silence compiler warning if none of the Cairo options has been configured #else FL_EXPORT int fltk_cairo_dummy() { return 1; } #endif // FLTK_HAVE_CAIRO fltk-1.4.3/src/Fl_compose.cxx0000644000175000017500000000705115004135251016211 0ustar albrechtalbrecht// // Character compose processing for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_compose.cxx Utility functions to support text input. */ #include #include "Fl_Screen_Driver.H" #ifndef FL_DOXYGEN int Fl::compose_state = 0; #endif /** Any text editing widget should call this for each FL_KEYBOARD event. Use of this function is very simple.

If true is returned, then it has modified the Fl::event_text() and Fl::event_length() to a set of bytes to insert (it may be of zero length!). It will also set the "del" parameter to the number of bytes to the left of the cursor to delete, this is used to delete the results of the previous call to Fl::compose().

If false is returned, the keys should be treated as function keys, and del is set to zero. You could insert the text anyways, if you don't know what else to do.

Text editing widgets can preferentially call fl_set_spot() to indicate the window coordinates of the bottom of the current insertion point and the line height. This way, auxiliary windows that help choosing among alternative characters with some text input methods appear just below or above the insertion point. If widgets don't do that, such auxiliary windows appear at the widget's bottom.

On some platforms, text input can involve marked text, that is, temporary text replaced by other text during the input process. This occurs, e.g., under Wayland or macOS when using dead keys or when entering CJK characters. Text editing widgets should preferentially signal marked text, usually underlining it. Widgets can use int Fl::compose_state after having called Fl::compose(int&) to obtain the length in bytes of marked text that always finishes at the current insertion point. Widgets should also call void fl_reset_spot() when processing FL_UNFOCUS events. The Fl_Input and Fl_Text_Editor widgets underline marked text. If none of this is done by a user-defined text editing widget, text input will work, but will not signal to the user what text is marked.

Finally, text editing widgets should call set_flag(MAC_USE_ACCENTS_MENU); in their constructor if they want to use, on the macOS platform, the feature introduced with Mac OS 10.7 "Lion" where pressing and holding certain keys on the keyboard opens a diacritic marks popup window. \note For compatibility with FLTK 1.3, text editing widgets can call Fl::insertion_point_location(int x, int y, int height) and Fl::reset_marked_text() only under the macOS platform to indicate/reset the coordinates of the current insertion point. This is deprecated in version 1.4 because redundant with the platform-independent fl_set_spot() and fl_reset_spot() functions. */ int Fl::compose(int& del) { return Fl::screen_driver()->compose(del); } /** If the user moves the cursor, be sure to call Fl::compose_reset(). The next call to Fl::compose() will start out in an initial state. In particular it will not set "del" to non-zero. This call is very fast so it is ok to call it many times and in many places. */ void Fl::compose_reset() { Fl::screen_driver()->compose_reset(); } fltk-1.4.3/src/Fl_Image_Reader.cxx0000644000175000017500000001065415004135251017053 0ustar albrechtalbrecht// // Internal (Image) Reader class for the Fast Light Tool Kit (FLTK). // // Copyright 2020-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // Include necessary header files... // #include "Fl_Image_Reader.h" #include #include #include #include /* This internal (undocumented) class reads data chunks from a file or from memory in LSB-first byte order. This class is used in Fl_GIF_Image and Fl_BMP_Image to avoid code duplication and may be extended to be used in similar cases. Future options might be to read data in MSB-first byte order or to add more methods. */ // Initialize the reader to access the file system, filename is copied // and stored. int Fl_Image_Reader::open(const char *filename) { if (!filename) return -1; name_ = fl_strdup(filename); if ((file_ = fl_fopen(filename, "rb")) == NULL) { return -1; } is_file_ = 1; return 0; } // Initialize the reader for memory access, name is copied and stored. int Fl_Image_Reader::open(const char *imagename, const unsigned char *data, const size_t datasize) { if (imagename) name_ = fl_strdup(imagename); if (data) { start_ = data_ = data; is_data_ = 1; end_ = start_ + datasize; return 0; } return -1; } // Initialize the reader for memory access, name is copied and stored. // Deprecated, DO NOT USE! Buffer overruns will not be checked! // Please use instead: // Fl_Image_Reader::open(const char *imagename, const unsigned char *data, const size_t datasize) int Fl_Image_Reader::open(const char *imagename, const unsigned char *data) { if (imagename) name_ = fl_strdup(imagename); if (data) { start_ = data_ = data; is_data_ = 1; return 0; } return -1; } // Close and destroy the reader Fl_Image_Reader::~Fl_Image_Reader() { if (is_file_ && file_) { fclose(file_); } if (name_) free(name_); } // Read a single byte from memory or a file uchar Fl_Image_Reader::read_byte() { if (error()) // don't read after read error or EOF return 0; if (is_file_) { int ret = getc(file_); if (ret < 0) { if (feof(file_)) error_ = 1; else if (ferror(file_)) error_ = 2; else error_ = 3; // unknown error return 0; } return ret; } else if (is_data_) { if (data_ < end_) return *data_++; error_ = 1; // EOF return 0; } error_ = 3; // undefined mode return 0; } // Read a 16-bit unsigned integer, LSB-first unsigned short Fl_Image_Reader::read_word() { unsigned char b0, b1; // Bytes from file or memory b0 = read_byte(); b1 = read_byte(); if (error()) return 0; return ((b1 << 8) | b0); } // Read a 32-bit unsigned integer, LSB-first unsigned int Fl_Image_Reader::read_dword() { unsigned char b0, b1, b2, b3; // Bytes from file or memory b0 = read_byte(); b1 = read_byte(); b2 = read_byte(); b3 = read_byte(); if (error()) return 0; return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0); } // Move the current read position to a byte offset from the beginning // of the file or the original start address in memory. // This method clears the error flag if the position is valid. // If reading from memory and (start_ + n) overflows, then the result is undefined. void Fl_Image_Reader::seek(unsigned int n) { error_ = 0; if (is_file_) { int ret = fseek(file_, n, SEEK_SET); if (ret < 0) error_ = 2; // read / position error return; } else if (is_data_) { if (start_ + n <= end_) data_ = start_ + n; else error_ = 2; // read / position error return; } // unknown mode (not initialized ?) error_ = 3; } // Get the current read position as a byte offset from the // beginning of the file or the original start address in memory. // This method does neither affect the error flag nor is it affected // by the current error status. If reading from a file, this may // return -1 or any error code from ftell(). long Fl_Image_Reader::tell() const { if (is_file_) { return ftell(file_); } else if (is_data_) { return long(data_ - start_); } return 0; } fltk-1.4.3/src/Fl_Dial.cxx0000644000175000017500000001126415004135251015416 0ustar albrechtalbrecht// // Circular dial widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include // All angles are measured with 0 to the right and counter-clockwise /** Draws dial at given position and size. \param[in] X, Y, W, H position and size */ void Fl_Dial::draw(int X, int Y, int W, int H) { if (damage()&FL_DAMAGE_ALL) draw_box(box(), X, Y, W, H, color()); X += Fl::box_dx(box()); Y += Fl::box_dy(box()); W -= Fl::box_dw(box()); H -= Fl::box_dh(box()); double angle = (a2-a1)*(value()-minimum())/(maximum()-minimum()) + a1; if (type() == FL_FILL_DIAL) { // foo: draw this nicely in certain round box types int foo = (box() > _FL_ROUND_UP_BOX && Fl::box_dx(box())); if (foo) {X--; Y--; W+=2; H+=2;} if (active_r()) fl_color(color()); else fl_color(fl_inactive(color())); fl_pie(X, Y, W, H, 270-a1, angle > a1 ? 360+270-angle : 270-360-angle); if (active_r()) fl_color(selection_color()); else fl_color(fl_inactive(selection_color())); fl_pie(X, Y, W, H, 270-angle, 270-a1); if (foo) { if (active_r()) fl_color(FL_FOREGROUND_COLOR); else fl_color(fl_inactive(FL_FOREGROUND_COLOR)); fl_arc(X, Y, W, H, 0, 360); } return; } if (!(damage()&FL_DAMAGE_ALL)) { if (active_r()) fl_color(color()); else fl_color(fl_inactive(color())); fl_pie(X+1, Y+1, W-2, H-2, 0, 360); } fl_push_matrix(); fl_translate(X+W/2-.5, Y+H/2-.5); fl_scale(W-1, H-1); fl_rotate(45-angle); if (active_r()) fl_color(selection_color()); else fl_color(fl_inactive(selection_color())); if (type()) { // FL_LINE_DIAL fl_begin_polygon(); fl_vertex(0.0, 0.0); fl_vertex(-0.04, 0.0); fl_vertex(-0.25, 0.25); fl_vertex(0.0, 0.04); fl_end_polygon(); if (active_r()) fl_color(FL_FOREGROUND_COLOR); else fl_color(fl_inactive(FL_FOREGROUND_COLOR)); fl_begin_loop(); fl_vertex(0.0, 0.0); fl_vertex(-0.04, 0.0); fl_vertex(-0.25, 0.25); fl_vertex(0.0, 0.04); fl_end_loop(); } else { fl_begin_polygon(); fl_circle(-0.20, 0.20, 0.07); fl_end_polygon(); if (active_r()) fl_color(FL_FOREGROUND_COLOR); else fl_color(fl_inactive(FL_FOREGROUND_COLOR)); fl_begin_loop(); fl_circle(-0.20, 0.20, 0.07); fl_end_loop(); } fl_pop_matrix(); } /** Draws dial at current position and size. */ void Fl_Dial::draw() { draw(x(), y(), w(), h()); draw_label(); } /** Allows subclasses to handle event based on given position and size. \param[in] event, X, Y, W, H event to handle, related position and size. */ int Fl_Dial::handle(int event, int X, int Y, int W, int H) { switch (event) { case FL_PUSH: handle_push(); /* FALLTHROUGH */ case FL_DRAG: { int mx = (Fl::event_x()-X-W/2)*H; int my = (Fl::event_y()-Y-H/2)*W; if (!mx && !my) return 1; double angle = 270-atan2((float)-my, (float)mx)*180/M_PI; double oldangle = (a2-a1)*(value()-minimum())/(maximum()-minimum()) + a1; while (angle < oldangle-180) angle += 360; while (angle > oldangle+180) angle -= 360; double val; if ((a1= a1)) { val = minimum(); } else if ((a1= a2) : (angle <= a2)) { val = maximum(); } else { val = minimum() + (maximum()-minimum())*(angle-a1)/(a2-a1); } handle_drag(clamp(round(val))); return 1; } /* NOTREACHED */ case FL_RELEASE: handle_release(); return 1; case FL_ENTER: /* FALLTHROUGH */ case FL_LEAVE: return 1; default: return 0; } } /** Allow subclasses to handle event based on current position and size. */ int Fl_Dial::handle(int e) { return handle(e, x(), y(), w(), h()); } Fl_Dial::Fl_Dial(int X, int Y, int W, int H, const char* l) /** Creates a new Fl_Dial widget using the given position, size, and label string. The default type is FL_NORMAL_DIAL. */ : Fl_Valuator(X, Y, W, H, l) { box(FL_OVAL_BOX); selection_color(FL_INACTIVE_COLOR); // was 37 a1 = 45; a2 = 315; } Fl_Fill_Dial::Fl_Fill_Dial(int X,int Y,int W,int H, const char *L) : Fl_Dial(X,Y,W,H,L) { type(FL_FILL_DIAL); } Fl_Line_Dial::Fl_Line_Dial(int X,int Y,int W,int H, const char *L) : Fl_Dial(X,Y,W,H,L) { type(FL_LINE_DIAL); } fltk-1.4.3/src/fl_images_core.cxx0000644000175000017500000001202415004135251017055 0ustar albrechtalbrecht// // FLTK images library core. // // Copyright 1997-2010 by Easy Software Products. // Copyright 2011-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // fl_register_images() - Register the image formats. // fl_check_images() - Check for a supported image format. // // // Include necessary header files... // #include #include #include #include #include #include #include #include #include #include #include #include #include "flstring.h" #if defined(HAVE_LIBZ) #include #endif // // Define a simple global image registration function that registers // the extra image formats that aren't part of the core FLTK library. // static Fl_Image *fl_check_images(const char *name, uchar *header, int headerlen); /** \brief Register the known image formats. This function is provided in the fltk_images library and registers all of the "extra" image file formats known to FLTK that are not part of the core FLTK library. You may add your own image formats with Fl_Shared_Image::add_handler(). */ void fl_register_images() { Fl_Shared_Image::add_handler(fl_check_images); Fl_Image::register_images_done = true; } // // 'fl_check_images()' - Check for a supported image format. // // returns 0 (NULL) if is less than 6 because: // (1) some of the comparisons would otherwise access undefined data // (2) there's no valid image file with less than 6 bytes // // Note 1: The number 6 above may be changed if necessary as long as // condition (2) holds. // // Note 2: The provided buffer

MUST NOT be overwritten by any // check function because subsequently called check functions need // the original image header data.
should be const! Fl_Image * // O - Image, if found fl_check_images(const char *name, // I - Filename uchar *header, // I - Header data from file int headerlen) { // I - Amount of data in header if (headerlen < 6) // not a valid image return 0; // GIF if (memcmp(header, "GIF87a", 6) == 0 || memcmp(header, "GIF89a", 6) == 0) // GIF file return Fl_GIF_Image::animate ? new Fl_Anim_GIF_Image(name) : new Fl_GIF_Image(name); // BMP if (memcmp(header, "BM", 2) == 0) // BMP file return new Fl_BMP_Image(name); if (memcmp(header, "\0\0\1\0", 4) == 0 && header[5] == 0) // ICO file return new Fl_ICO_Image(name); // PNM if (header[0] == 'P' && header[1] >= '1' && header[1] <= '7') // Portable anymap return new Fl_PNM_Image(name); // PNG #ifdef HAVE_LIBPNG if (memcmp(header, "\211PNG", 4) == 0)// PNG file return new Fl_PNG_Image(name); #endif // HAVE_LIBPNG // JPEG #ifdef HAVE_LIBJPEG if (memcmp(header, "\377\330\377", 3) == 0 && // Start-of-Image header[3] >= 0xc0 && header[3] <= 0xfe) // APPn .. comment for JPEG file return new Fl_JPEG_Image(name); #endif // HAVE_LIBJPEG // SVG or SVGZ (gzip'ed SVG) #ifdef FLTK_USE_SVG uchar header2[64]; // buffer for decompression uchar *buf = header; // original header data int count = headerlen; // original header data size // Note: variables 'buf' and 'count' may be overwritten subsequently // if the image data is gzip'ed *and* we can decompress the data # if defined(HAVE_LIBZ) if (header[0] == 0x1f && header[1] == 0x8b) { // gzip'ed data int fd = fl_open_ext(name, 1, 0); if (fd < 0) return NULL; gzFile gzf = gzdopen(fd, "r"); if (gzf) { count = gzread(gzf, header2, (int)sizeof(header2)); gzclose(gzf); buf = header2; // decompressed data } } // gzip'ed data # endif // HAVE_LIBZ // Check if we have a UTF-8 BOM in the first three bytes (issue #247). // If yes we need at least 5 more bytes to recognize the signature. // Note: BOM (Byte Order Mark) in UTF-8 is not recommended but allowed. if (count >= 8) { const uchar bom[3] = { 0xef, 0xbb, 0xbf }; if (memcmp(buf, bom, 3) == 0) { buf += 3; count -= 3; } } // Check svg or xml signature while (count && isspace(buf[0])) { buf++; count--; } if ((count >= 5 && (memcmp(buf, "w() && image->h()) return image; delete image; } #endif // FLTK_USE_SVG // unknown image format return 0; } fltk-1.4.3/src/Fl_Window_hotspot.cxx0000644000175000017500000000326215004135251017573 0ustar albrechtalbrecht// // Common hotspot routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "Fl_Window_Driver.H" void Fl_Window::hotspot(int X, int Y, int offscreen) { int mx,my; // Update the screen position based on the mouse position. Fl::get_mouse(mx,my); X = mx-X; Y = my-Y; // If offscreen is 0 (the default), make sure that the window // stays on the screen, if possible. if (!offscreen) { int scr_x, scr_y, scr_w, scr_h; Fl::screen_work_area(scr_x, scr_y, scr_w, scr_h); int top = 0; int left = 0; int right = 0; int bottom = 0; if (border()) { pWindowDriver->decoration_sizes(&top, &left, &right, &bottom); } // now ensure contents are on-screen (more important than border): if (X+w()+right > scr_w+scr_x) X = scr_w+scr_x-right-w(); if (X-left < scr_x) X = left + scr_x; if (Y+h()+bottom > scr_h+scr_y) Y = scr_h+scr_y-bottom-h(); if (Y-top < scr_y) Y = top + scr_y; // make sure that we will force this position if (X==x()) x(X-1); } position(X,Y); } void Fl_Window::hotspot(const Fl_Widget *o, int offscreen) { int X = o->w()/2; int Y = o->h()/2; while (o != this && o) { X += o->x(); Y += o->y(); o = o->window(); } hotspot(X,Y,offscreen); } fltk-1.4.3/src/Fl_Input_Choice.cxx0000644000175000017500000003150615004135251017117 0ustar albrechtalbrecht// // An input/chooser widget. // ______________ ____ // | || __ | // | input area || \/ | // |______________||____| // // Copyright 1998-2024 by Bill Spitzak and others. // Copyright 2004 by Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* \file Fl_Input_Choice widget . */ #include #include #include /** \class Fl_Input_Choice \brief A combination of the input widget and a menu button. \image html input_choice.png \image latex input_choice.png "Fl_Input_Choice widget" width=12cm The user can either type into the input area, or use the menu button chooser on the right to choose an item which loads the input area with the selected text. The application can directly access both the internal Fl_Input and Fl_Menu_Button widgets respectively using the input() and menubutton() accessor methods. The default behavior is to invoke the Fl_Input_Choice::callback() if the user changes the input field's contents, either by typing, pasting, or clicking a different item in the choice menu. The callback can determine if an item was picked vs. typing into the input field by checking the value of menubutton()->changed(), which will be: - 1: the user picked a different item in the choice menu - 0: the user typed or pasted directly into the input field \par Example Use of Fl_Input_Choice \code #include #include #include #include // Fl_Input_Choice callback() void choice_cb(Fl_Widget *w, void *userdata) { // Show info about the picked item Fl_Input_Choice *choice = (Fl_Input_Choice*)w; printf("*** Choice Callback:\n"); printf(" widget's text value='%s'\n", choice->value()); // normally all you need // Access the menu via menubutton().. const Fl_Menu_Item *item = choice->menubutton()->mvalue(); printf(" item label()='%s'\n", item ? item->label() : "(No item)"); printf(" item value()=%d\n", choice->menubutton()->value()); printf(" input value()='%s'\n", choice->input()->value()); printf(" The user %s\n", choice->menubutton()->changed() ? "picked a menu item" : "typed text"); } int main() { Fl_Double_Window win(200,100,"Input Choice"); win.begin(); Fl_Input_Choice choice(10,10,100,30); choice.callback(choice_cb, 0); choice.add("Red"); choice.add("Orange"); choice.add("Yellow"); //choice.value("Red"); // uncomment to make "Red" default win.end(); win.show(); return Fl::run(); } \endcode \par Subclassing Example One can subclass Fl_Input_Choice to override the virtual methods inp_x/y/w/h() and menu_x/y/w/h() to take control of the internal Fl_Input and Fl_Menu_Button widget positioning. In this example, input and menubutton's positions are swapped: \code #include #include #include class MyInputChoice : public Fl_Input_Choice { protected: virtual int inp_x() const { return x() + Fl::box_dx(box()) + menu_w(); } // override to reposition virtual int menu_x() const { return x() + Fl::box_dx(box()); } // override to reposition public: MyInputChoice(int X,int Y,int W,int H,const char*L=0) : Fl_Input_Choice(X,Y,W,H,L) { resize(X,Y,W,H); // necessary for ctor to trigger our overrides } }; int main(int argc, char **argv) { Fl_Window *win = new Fl_Window(400,300); MyInputChoice *mychoice = new MyInputChoice(150,40,150,25,"Right Align Input"); mychoice->add("Aaa"); mychoice->add("Bbb"); mychoice->add("Ccc"); win->end(); win->resizable(win); win->show(); return Fl::run(); } \endcode */ /** Constructor for private menu button. */ Fl_Input_Choice::InputMenuButton::InputMenuButton(int x,int y,int w,int h,const char*l) :Fl_Menu_Button(x,y,w,h,l) { box(FL_UP_BOX); } /** Draws the private menu button. */ void Fl_Input_Choice::InputMenuButton::draw() { if (!box()) return; // Draw box for default scheme only // For all other schemes, let parent group's box show through // if (!Fl::scheme()) draw_box(pressed_menu_button_ == this ? fl_down(box()) : box(), color()); if (Fl::focus() == this) { int woff = Fl::scheme() ? 2 : 1; // helps center focus box draw_focus(FL_UP_BOX, x(), y(), w()+woff, h(), color()); } // draw the arrow (choice button) Fl_Color arrow_color = active_r() ? labelcolor() : fl_inactive(labelcolor()); fl_draw_arrow(Fl_Rect(x(), y(), w(), h()), FL_ARROW_CHOICE, FL_ORIENT_NONE, arrow_color); } // Make pulldown menu appear under entire width of widget const Fl_Menu_Item* Fl_Input_Choice::InputMenuButton::popup() { menu_end(); redraw(); Fl_Widget_Tracker mb(this); // Make menu appear under entire width of Fl_Input_Choice parent group const Fl_Menu_Item *m = menu()->pulldown(parent()->x(), y(), parent()->w(), h(), 0, this); picked(m); if (mb.exists()) redraw(); return m; } // Invokes our popup() method to ensure pulldown menu appears full width under widget // (This is the same handle() code in Fl_Menu_Button and Fl_Choice) // int Fl_Input_Choice::InputMenuButton::handle(int e) { if (!menu() || !menu()->text) return 0; switch (e) { case FL_ENTER: /* FALLTHROUGH */ case FL_LEAVE: return (box() && !type()) ? 1 : 0; case FL_PUSH: if (!box()) { if (Fl::event_button() != 3) return 0; } else if (type()) { if (!(type() & (1 << (Fl::event_button()-1)))) return 0; } if (Fl::visible_focus()) Fl::focus(this); popup(); return 1; case FL_KEYBOARD: if (!box()) return 0; if (Fl::event_key() == ' ' && !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) { popup(); return 1; } else return 0; case FL_SHORTCUT: if (Fl_Widget::test_shortcut()) {popup(); return 1;} return test_shortcut() != 0; case FL_FOCUS: /* FALLTHROUGH */ case FL_UNFOCUS: if (box() && Fl::visible_focus()) { redraw(); return 1; } default: return 0; } } /** Callback for the Fl_Input_Choice menu. */ void Fl_Input_Choice::menu_cb(Fl_Widget*, void *data) { Fl_Input_Choice *o=(Fl_Input_Choice *)data; Fl_Widget_Tracker wp(o); const Fl_Menu_Item *item = o->menubutton()->mvalue(); if (item && item->flags & (FL_SUBMENU|FL_SUBMENU_POINTER)) return; // ignore submenus if (!strcmp(o->inp_->value(), o->menu_->text())) { o->Fl_Widget::clear_changed(); if (o->when() & FL_WHEN_NOT_CHANGED) o->do_callback(FL_REASON_RESELECTED); } else { o->inp_->value(o->menu_->text()); o->inp_->set_changed(); o->Fl_Widget::set_changed(); if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE)) o->do_callback(FL_REASON_CHANGED); } if (wp.deleted()) return; if (o->callback() != default_callback) { o->Fl_Widget::clear_changed(); o->inp_->clear_changed(); } } /** Callback for the Fl_Input_Choice input field. */ void Fl_Input_Choice::inp_cb(Fl_Widget*, void *data) { Fl_Input_Choice *o=(Fl_Input_Choice *)data; Fl_Widget_Tracker wp(o); if (o->inp_->changed()) { o->Fl_Widget::set_changed(); if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE)) o->do_callback(FL_REASON_CHANGED); } else { o->Fl_Widget::clear_changed(); if (o->when() & FL_WHEN_NOT_CHANGED) o->do_callback(FL_REASON_RESELECTED); } if (wp.deleted()) return; if (o->callback() != default_callback) o->Fl_Widget::clear_changed(); } /** Creates a new Fl_Input_Choice widget using the given position, size, and label string. Inherited destructor destroys the widget and any values associated with it. */ Fl_Input_Choice::Fl_Input_Choice(int X, int Y, int W, int H, const char *L) : Fl_Group(X,Y,W,H,L) { Fl_Group::box(FL_DOWN_BOX); align(FL_ALIGN_LEFT); // default like Fl_Input inp_ = new Fl_Input(inp_x(), inp_y(), inp_w(), inp_h()); inp_->callback(inp_cb, (void*)this); inp_->box(FL_FLAT_BOX); // cosmetic inp_->when(FL_WHEN_CHANGED|FL_WHEN_NOT_CHANGED); menu_ = new InputMenuButton(menu_x(), menu_y(), menu_w(), menu_h()); menu_->callback(menu_cb, (void*)this); end(); } /** Resizes the Fl_Input_Choice widget. */ void Fl_Input_Choice::resize(int X, int Y, int W, int H) { Fl_Group::resize(X,Y,W,H); inp_->resize(inp_x(), inp_y(), inp_w(), inp_h()); menu_->resize(menu_x(), menu_y(), menu_w(), menu_h()); } /** Chooses item# \p val in the menu, and sets the Fl_Input text field to that value. Any previous text is cleared. \see void value(const char *val) */ void Fl_Input_Choice::value(int val) { menu_->value(val); inp_->value(menu_->text(val)); } /** Sets the changed() state of both input and menu button widgets to the specified value. */ void Fl_Input_Choice::set_changed() { inp_->set_changed(); // no need to call Fl_Widget::set_changed() } /** Clears the changed() state of both input and menu button widgets. */ void Fl_Input_Choice::clear_changed() { inp_->clear_changed(); Fl_Widget::clear_changed(); } /** Updates the menubutton with the string value in Fl_Input. If the string value currently in Fl_Input matches one of the menu items in menubutton(), that menu item will become the current item selected. Call this method after setting value(const char*) if you need the menubutton() to be synchronized with the Fl_Input field. \code // Add items choice->add(".25"); choice->add(".50"); choice->add("1.0"); choice->add("2.0"); choice->add("4.0"); choice->value("1.0"); // sets Fl_Input to "1.0" choice->update_menubutton(); // cause menubutton to reflect this value too // (returns 1 if match was found, 0 if not) // Verify menubutton()'s value. printf("menu button choice index=%d, value=%s\n", choice->menubutton()->value(), // would be -1 if update not done choice->menubutton()->text()); // would be NULL if update not done \endcode \returns 1 if a matching menuitem was found and value set, 0 if not. \version 1.4.0 */ int Fl_Input_Choice::update_menubutton() { // Find item in menu for ( int i=0; isize(); i++ ) { const Fl_Menu_Item &item = menu_->menu()[i]; if (item.flags & (FL_SUBMENU|FL_SUBMENU_POINTER)) continue; // ignore submenus const char *name = menu_->text(i); if ( name && strcmp(name, inp_->value()) == 0) { menu_->value(i); return 1; } } return 0; // not found } void Fl_Input_Choice::draw() { // This is copied from Fl_Choice::draw() and customized Fl_Boxtype btype = Fl::scheme() ? FL_UP_BOX // non-default uses up box : FL_DOWN_BOX; // default scheme uses down box int dx = Fl::box_dx(btype); int dy = Fl::box_dy(btype); // From "original" code: modify the box color *only* for the default scheme. // This is weird (why?). I believe we should either make sure that the text // color contrasts well when the text is rendered *or* we should do this for // *all* schemes. Anyway, adapting the old code... (Albrecht) // Fl_Color box_color = color(); if (!Fl::scheme()) { // default scheme only, see comment above if (fl_contrast(textcolor(), FL_BACKGROUND2_COLOR) == textcolor()) box_color = FL_BACKGROUND2_COLOR; else box_color = fl_lighter(color()); } // Draw the widget box draw_box(btype, box_color); // Draw menu button draw_child(*menu_); // Draw vertical divider lines for: gtk+, gleam, oxy // // Scheme: Box or divider line // ---------------------------------------- // Default (None): Arrow box (FL_UP_BOX) // gtk+, gleam, oxy: Divider line // else: Nothing - Fl_Group::box() shows through // int woff = 0; if (Fl::is_scheme("gtk+") || Fl::is_scheme("gleam") || Fl::is_scheme("oxy")) { // draw the vertical divider line int x1 = menu_x() - dx; int y1 = y() + dy; int y2 = y() + h() - dy; fl_color(fl_darker(color())); fl_yxline(x1+0, y1, y2); fl_color(fl_lighter(color())); fl_yxline(x1+1, y1, y2); woff = 2; // prevent Fl_Input from overdrawing divider } // Draw the input field fl_push_clip(inp_x(), inp_y(), inp_w() - woff, inp_h()); draw_child(*inp_); fl_pop_clip(); // Widget's label draw_label(); } fltk-1.4.3/src/Fl_Value_Slider.cxx0000644000175000017500000000456015004135251017124 0ustar albrechtalbrecht// // Value Slider widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include /** Creates a new Fl_Value_Slider widget using the given position, size, and label string. The default boxtype is FL_DOWN_BOX. */ Fl_Value_Slider::Fl_Value_Slider(int X, int Y, int W, int H, const char*l) : Fl_Slider(X,Y,W,H,l) { step(1,100); textfont_ = FL_HELVETICA; textsize_ = 10; textcolor_ = FL_FOREGROUND_COLOR; value_width_ = 35; value_height_ = 25; } void Fl_Value_Slider::draw() { int sxx = x(), syy = y(), sww = w(), shh = h(); int bxx = x(), byy = y(), bww = w(), bhh = h(); if (horizontal()) { bww = value_width(); sxx += value_width(); sww -= value_width(); } else { syy += value_height(); bhh = value_height(); shh -= value_height(); } if (damage() & FL_DAMAGE_ALL) draw_box(box(), sxx, syy, sww, shh, color()); Fl_Slider::draw(sxx+Fl::box_dx(box()), syy+Fl::box_dy(box()), sww-Fl::box_dw(box()), shh-Fl::box_dh(box())); draw_box(box(),bxx,byy,bww,bhh,color()); char buf[128]; format(buf); fl_font(textfont(), textsize()); fl_color(active_r() ? textcolor() : fl_inactive(textcolor())); fl_draw(buf, bxx, byy, bww, bhh, FL_ALIGN_CLIP); } int Fl_Value_Slider::handle(int event) { if (event == FL_PUSH && Fl::visible_focus()) { Fl::focus(this); redraw(); } int sxx = x(), syy = y(), sww = w(), shh = h(); if (horizontal()) { sxx += value_width(); sww -= value_width(); } else { syy += value_height(); shh -= value_height(); } return Fl_Slider::handle(event, sxx + Fl::box_dx(box()), syy + Fl::box_dy(box()), sww - Fl::box_dw(box()), shh - Fl::box_dh(box())); } Fl_Hor_Value_Slider::Fl_Hor_Value_Slider(int X,int Y,int W,int H,const char *l) : Fl_Value_Slider(X,Y,W,H,l) { type(FL_HOR_SLIDER); } fltk-1.4.3/src/Fl_Check_Browser.cxx0000644000175000017500000001771415004135251017273 0ustar albrechtalbrecht// // Fl_Check_Browser implementation for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "flstring.h" #include #include // fl_strdup() #include /* This uses a cache for faster access when you're scanning the list either forwards or backwards. */ Fl_Check_Browser::cb_item *Fl_Check_Browser::find_item(int n) const { int i = n; cb_item *p = first; if (n <= 0 || n > nitems_ || p == 0) { return 0; } if (n == cached_item) { p = cache; n = 1; } else if (n == cached_item + 1) { p = cache->next; n = 1; } else if (n == cached_item - 1) { p = cache->prev; n = 1; } while (--n) { p = p->next; } /* Cast to not const and cache it. */ ((Fl_Check_Browser *)this)->cache = p; ((Fl_Check_Browser *)this)->cached_item = i; return p; } int Fl_Check_Browser::lineno(cb_item *p0) const { cb_item *p = first; if (p == 0) { return 0; } int i = 1; while (p) { if (p == p0) { return i; } i++; p = p->next; } return 0; } /** The constructor makes an empty browser. */ Fl_Check_Browser::Fl_Check_Browser(int X, int Y, int W, int H, const char *l) : Fl_Browser_(X, Y, W, H, l) { type(FL_SELECT_BROWSER); when(FL_WHEN_NEVER); first = last = 0; nitems_ = nchecked_ = 0; cached_item = -1; } void *Fl_Check_Browser::item_first() const { return first; } void *Fl_Check_Browser::item_next(void *l) const { return ((cb_item *)l)->next; } void *Fl_Check_Browser::item_prev(void *l) const { return ((cb_item *)l)->prev; } int Fl_Check_Browser::item_height(void *) const { return textsize() + 2; } const char *Fl_Check_Browser::item_text(void *item) const { cb_item *i = (cb_item *)item; return i->text; } void *Fl_Check_Browser::item_at(int index) const { // note: index is 1-based if (index < 1 || index > nitems()) return 0L; cb_item *item = (cb_item *)item_first(); for (int i = 1; i < index; i++) item = (cb_item *)(item_next(item)); return (void *)item; } void Fl_Check_Browser::item_swap(int ia, int ib) { item_swap(item_at(ia), item_at(ib)); } void Fl_Check_Browser::item_swap(void *a, void *b) { cb_item *ia = (cb_item *)a; cb_item *ib = (cb_item *)b; cb_item *a_next = ia->next; cb_item *a_prev = ia->prev; cb_item *b_next = ib->next; cb_item *b_prev = ib->prev; if (a_next == ib) { // p - a - b - n => p - b - a - n if (a_prev) a_prev->next = ib; if (b_next) b_next->prev = ia; ib->prev = a_prev; ib->next = ia; ia->prev = ib; ia->next = b_next; } else if (a_prev == ib) { // p - b - a - n => p - a - b - n if (b_prev) b_prev->next = ia; if (a_next) a_next->prev = ib; ia->prev = b_prev; ia->next = ib; ib->prev = ia; ib->next = a_next; } else { // x - a - y - b - z => x - b - y - a - z if (a_prev) a_prev->next = ib; if (a_next) a_next->prev = ib; ia->next = b_next; ia->prev = b_prev; if (b_prev) b_prev->next = ia; if (b_next) b_next->prev = ia; ib->next = a_next; ib->prev = a_prev; } if (first == ia) first = ib; if (last == ia) last = ib; // invalidate item cache cached_item = -1; cache = 0L; } #define CHECK_SIZE (textsize()-2) int Fl_Check_Browser::item_width(void *v) const { fl_font(textfont(), textsize()); return int(fl_width(((cb_item *)v)->text)) + CHECK_SIZE + 8; } void Fl_Check_Browser::item_draw(void *v, int X, int Y, int, int H) const { Y += (H - item_height(v)) / 2; cb_item *i = (cb_item *)v; char *s = i->text; int tsize = textsize(); Fl_Color col = active_r() ? textcolor() : fl_inactive(textcolor()); int cy = Y + (tsize + 1 - CHECK_SIZE) / 2; X += 2; // draw the check mark box (always) fl_color(active_r() ? FL_FOREGROUND_COLOR : fl_inactive(FL_FOREGROUND_COLOR)); fl_loop(X, cy, X, cy + CHECK_SIZE, X + CHECK_SIZE, cy + CHECK_SIZE, X + CHECK_SIZE, cy); // draw the check mark if (i->checked) { fl_draw_check(Fl_Rect(X + 1, cy + 1, CHECK_SIZE - 1, CHECK_SIZE - 1), fl_color()); } // draw the item text fl_font(textfont(), tsize); if (i->selected) { col = fl_contrast(col, selection_color()); } fl_color(col); fl_draw(s, X + CHECK_SIZE + 8, Y + tsize - 1); } void Fl_Check_Browser::item_select(void *v, int state) { cb_item *i = (cb_item *)v; if (state) { if (i->checked) { i->checked = 0; nchecked_--; } else { i->checked = 1; nchecked_++; } } } int Fl_Check_Browser::item_selected(void *v) const { cb_item *i = (cb_item *)v; return i->selected; } /** Add a new unchecked line to the end of the browser. \see add(char *s, int b) */ int Fl_Check_Browser::add(char *s) { return (add(s, 0)); } /** Add a new line to the end of the browser. The text is copied using the strdup() function. It may also be NULL to make a blank line. It can set the item checked if \p b is not 0. */ int Fl_Check_Browser::add(char *s, int b) { cb_item *p = (cb_item *)malloc(sizeof(cb_item)); p->next = 0; p->prev = 0; p->checked = b; p->selected = 0; p->text = fl_strdup(s ? s : ""); if (b) { nchecked_++; } if (last == 0) { first = last = p; } else { last->next = p; p->prev = last; last = p; } nitems_++; return (nitems_); } /** Remove line n and make the browser one line shorter. Returns the number of lines left in the browser. */ int Fl_Check_Browser::remove(int item) { cb_item *p = find_item(item); // line at item exists if (p) { // tell the Browser_ what we will do deleting(p); // fix checked count if (p->checked) --nchecked_; // remove the node if (p->prev) p->prev->next = p->next; else first = p->next; if (p->next) p->next->prev = p->prev; else last = p->prev; free(p->text); free(p); --nitems_; cached_item = -1; } return (nitems_); } /** Remove every item from the browser.*/ void Fl_Check_Browser::clear() { cb_item *p = first; cb_item *next; if (!p) return; new_list(); do { next = p->next; free(p->text); free(p); p = next; } while (p); first = last = 0; nitems_ = nchecked_ = 0; cached_item = -1; } /** Gets the current status of item item. */ int Fl_Check_Browser::checked(int i) const { cb_item *p = find_item(i); if (p) return p->checked; return 0; } /** Sets the check status of item item to b. */ void Fl_Check_Browser::checked(int i, int b) { cb_item *p = find_item(i); if (p && (p->checked ^ b)) { p->checked = b; if (b) { nchecked_++; } else { nchecked_--; } redraw(); } } /** Returns the index of the currently selected item.*/ int Fl_Check_Browser::value() const { return lineno((cb_item *)selection()); } /** Return a pointer to an internal buffer holding item item's text.*/ char *Fl_Check_Browser::text(int i) const { cb_item *p = find_item(i); if (p) return p->text; return 0; } /** Sets all the items checked.*/ void Fl_Check_Browser::check_all() { cb_item *p; nchecked_ = nitems_; for (p = first; p; p = p->next) { p->checked = 1; } redraw(); } /** Sets all the items unchecked.*/ void Fl_Check_Browser::check_none() { cb_item *p; nchecked_ = 0; for (p = first; p; p = p->next) { p->checked = 0; } redraw(); } int Fl_Check_Browser::handle(int event) { if (event == FL_PUSH) { int X, Y, W, H; bbox(X, Y, W, H); if (Fl::event_inside(X, Y, W, H)) { deselect(); } } return Fl_Browser_::handle(event); } fltk-1.4.3/src/fl_boxtype.cxx0000644000175000017500000004414615004135251016304 0ustar albrechtalbrecht// // Box drawing code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file fl_boxtype.cxx \brief Drawing code for common box types. */ // Box drawing code for the common box types and the table of // boxtypes. Other box types are in separate files so they are not // linked in if not used. #include #include #include #include //////////////////////////////////////////////////////////////// static const uchar active_ramp[24] = { FL_GRAY_RAMP+0, FL_GRAY_RAMP+1, FL_GRAY_RAMP+2, FL_GRAY_RAMP+3, FL_GRAY_RAMP+4, FL_GRAY_RAMP+5, FL_GRAY_RAMP+6, FL_GRAY_RAMP+7, FL_GRAY_RAMP+8, FL_GRAY_RAMP+9, FL_GRAY_RAMP+10,FL_GRAY_RAMP+11, FL_GRAY_RAMP+12,FL_GRAY_RAMP+13,FL_GRAY_RAMP+14,FL_GRAY_RAMP+15, FL_GRAY_RAMP+16,FL_GRAY_RAMP+17,FL_GRAY_RAMP+18,FL_GRAY_RAMP+19, FL_GRAY_RAMP+20,FL_GRAY_RAMP+21,FL_GRAY_RAMP+22,FL_GRAY_RAMP+23}; static const uchar inactive_ramp[24] = { 43, 43, 44, 44, 44, 45, 45, 46, 46, 46, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 51, 51, 52, 52}; static int draw_it_active = 1; int Fl::box_border_radius_max_ = 15; int Fl::box_shadow_width_ = 3; /** Determines if the currently drawn box is active or inactive. If inactive, the box color should be changed to the inactive color. \see Fl::box_color(Fl_Color c) */ int Fl::draw_box_active() { return draw_it_active; } // Note: the pointer that is returned by this function works only with indexes // between 65 ('A') and including 88 ('X'). const uchar *fl_gray_ramp() {return (static_cast(draw_it_active?active_ramp:inactive_ramp))-'A';} /** Gets the drawing color to be used for the background of a box. This method is only useful inside box drawing code. It returns the color to be used, either fl_inactive(c) if the widget is !active_r() or \p c otherwise. */ Fl_Color Fl::box_color(Fl_Color c) { return (draw_it_active ? c : fl_inactive(c)); } /** Sets the drawing color for the box that is currently drawn. This method sets the current drawing color fl_color() depending on the widget's state to either \p c or fl_inactive(c). It should be used whenever a box background is drawn in the box (type) drawing code instead of calling fl_color(Fl_Color bg) with the background color \p bg, usually Fl_Widget::color(). This method is only useful inside box drawing code. Whenever a box is drawn with one of the standard box drawing methods, a static variable is set depending on the widget's current state - if the widget is !active_r() then the internal variable is false (0), otherwise it is true (1). This is faster than calling Fl_Widget::active_r() because the state is cached. \see Fl::draw_box_active() \see Fl::box_color(Fl_Color) */ void Fl::set_box_color(Fl_Color c) { fl_color(box_color(c)); } /** Draws a series of line segments around the given box. The string \p s must contain groups of 4 letters which specify one of 24 standard grayscale values, where 'A' is black and 'X' is white. The order of each set of 4 characters is: top, left, bottom, right. The result of calling fl_frame() with a string that is not a multiple of 4 characters in length is undefined. The only difference between this function and fl_frame2() is the order of the line segments. \param[in] s sets of 4 grayscale values in top, left, bottom, right order \param[in] x, y, w, h position and size */ void fl_frame(const char* s, int x, int y, int w, int h) { const uchar *g = fl_gray_ramp(); if (h > 0 && w > 0) for (;*s;) { // draw top line: fl_color(g[(int)*s++]); fl_xyline(x, y, x+w-1); y++; if (--h <= 0) break; // draw left line: fl_color(g[(int)*s++]); fl_yxline(x, y+h-1, y); x++; if (--w <= 0) break; // draw bottom line: fl_color(g[(int)*s++]); fl_xyline(x, y+h-1, x+w-1); if (--h <= 0) break; // draw right line: fl_color(g[(int)*s++]); fl_yxline(x+w-1, y+h-1, y); if (--w <= 0) break; } } /** Draws a series of line segments around the given box. The string \p s must contain groups of 4 letters which specify one of 24 standard grayscale values, where 'A' is black and 'X' is white. The order of each set of 4 characters is: bottom, right, top, left. The result of calling fl_frame2() with a string that is not a multiple of 4 characters in length is undefined. The only difference between this function and fl_frame() is the order of the line segments. \param[in] s sets of 4 grayscale values in bottom, right, top, left order \param[in] x, y, w, h position and size */ void fl_frame2(const char* s, int x, int y, int w, int h) { const uchar *g = fl_gray_ramp(); if (h > 0 && w > 0) for (;*s;) { // draw bottom line: fl_color(g[(int)*s++]); fl_xyline(x, y+h-1, x+w-1); if (--h <= 0) break; // draw right line: fl_color(g[(int)*s++]); fl_yxline(x+w-1, y+h-1, y); if (--w <= 0) break; // draw top line: fl_color(g[(int)*s++]); fl_xyline(x, y, x+w-1); y++; if (--h <= 0) break; // draw left line: fl_color(g[(int)*s++]); fl_yxline(x, y+h-1, y); x++; if (--w <= 0) break; } } /** Draws a box of type FL_NO_BOX */ void fl_no_box(int, int, int, int, Fl_Color) {} /** Draws a box of type FL_FLAT_BOX */ void fl_flat_box(int x, int y, int w, int h, Fl_Color c) { fl_rectf(x, y, w, h, Fl::box_color(c)); } /** Draws a frame of type FL_THIN_DOWN_FRAME */ void fl_thin_down_frame(int x, int y, int w, int h, Fl_Color) { fl_frame2("WWHH",x,y,w,h); } /** Draws a box of type FL_THIN_DOWN_BOX */ void fl_thin_down_box(int x, int y, int w, int h, Fl_Color c) { fl_thin_down_frame(x,y,w,h,c); Fl::set_box_color(c); fl_rectf(x+1, y+1, w-2, h-2); } /** Draws a frame of type FL_THIN_UP_FRAME */ void fl_thin_up_frame(int x, int y, int w, int h, Fl_Color) { fl_frame2("HHWW",x,y,w,h); } /** Draws a box of type FL_THIN_UP_BOX */ void fl_thin_up_box(int x, int y, int w, int h, Fl_Color c) { fl_thin_up_frame(x,y,w,h,c); Fl::set_box_color(c); fl_rectf(x+1, y+1, w-2, h-2); } /** Draws a frame of type FL_UP_FRAME */ void fl_up_frame(int x, int y, int w, int h, Fl_Color) { #if BORDER_WIDTH == 1 fl_frame2("HHWW",x,y,w,h); #else #if BORDER_WIDTH == 2 fl_frame2("AAWWMMTT",x,y,w,h); #else fl_frame("AAAAWWJJUTNN",x,y,w,h); #endif #endif } #define D1 BORDER_WIDTH #define D2 (BORDER_WIDTH+BORDER_WIDTH) /** Draws a box of type FL_UP_BOX */ void fl_up_box(int x, int y, int w, int h, Fl_Color c) { fl_up_frame(x,y,w,h,c); Fl::set_box_color(c); fl_rectf(x+D1, y+D1, w-D2, h-D2); } /** Draws a frame of type FL_DOWN_FRAME */ void fl_down_frame(int x, int y, int w, int h, Fl_Color) { #if BORDER_WIDTH == 1 fl_frame2("WWHH",x,y,w,h); #else #if BORDER_WIDTH == 2 fl_frame2("WWMMPPAA",x,y,w,h); #else fl_frame("NNTUJJWWAAAA",x,y,w,h); #endif #endif } /** Draws a box of type FL_DOWN_BOX */ void fl_down_box(int x, int y, int w, int h, Fl_Color c) { fl_down_frame(x,y,w,h,c); Fl::set_box_color(c); fl_rectf(x+D1, y+D1, w-D2, h-D2); } /** Draws a frame of type FL_ENGRAVED_FRAME */ void fl_engraved_frame(int x, int y, int w, int h, Fl_Color) { fl_frame("HHWWWWHH",x,y,w,h); } /** Draws a box of type FL_ENGRAVED_BOX */ void fl_engraved_box(int x, int y, int w, int h, Fl_Color c) { fl_engraved_frame(x,y,w,h,c); Fl::set_box_color(c); fl_rectf(x+2, y+2, w-4, h-4); } /** Draws a frame of type FL_EMBOSSED_FRAME */ void fl_embossed_frame(int x, int y, int w, int h, Fl_Color) { fl_frame("WWHHHHWW",x,y,w,h); } /** Draws a box of type FL_EMBOSSED_BOX */ void fl_embossed_box(int x, int y, int w, int h, Fl_Color c) { fl_embossed_frame(x,y,w,h,c); Fl::set_box_color(c); fl_rectf(x+2, y+2, w-4, h-4); } /** Draws a bounded rectangle with a given position, size and color. Equivalent to drawing a box of type FL_BORDER_BOX. */ void fl_rectbound(int x, int y, int w, int h, Fl_Color bgcolor) { // New algorithm (see Discussion #1089): // 1) draw with adequate bg color a filled rectangle that covers also the rectangle border // 2) draw with adequate border color the rectangle border overwriting what was drawn at 1) Fl::set_box_color(bgcolor); fl_rectf(x, y, w, h); Fl::set_box_color(FL_BLACK); fl_rect(x, y, w, h); } #define fl_border_box fl_rectbound /**< allow consistent naming */ /** Draws a frame of type FL_BORDER_FRAME. */ void fl_border_frame(int x, int y, int w, int h, Fl_Color c) { Fl::set_box_color(c); fl_rect(x, y, w, h); } //////////////////////////////////////////////////////////////// static struct { Fl_Box_Draw_F *f; uchar dx, dy, dw, dh; int set; Fl_Box_Draw_Focus_F *ff; } fl_box_table[FL_MAX_BOXTYPE+1] = { // must match list in Enumerations.H!!! {fl_no_box, 0,0,0,0,1}, {fl_flat_box, 0,0,0,0,1}, // FL_FLAT_BOX {fl_up_box, D1,D1,D2,D2,1}, {fl_down_box, D1,D1,D2,D2,1}, {fl_up_frame, D1,D1,D2,D2,1}, {fl_down_frame, D1,D1,D2,D2,1}, {fl_thin_up_box, 1,1,2,2,1}, {fl_thin_down_box, 1,1,2,2,1}, {fl_thin_up_frame, 1,1,2,2,1}, {fl_thin_down_frame, 1,1,2,2,1}, {fl_engraved_box, 2,2,4,4,1}, {fl_embossed_box, 2,2,4,4,1}, {fl_engraved_frame, 2,2,4,4,1}, {fl_embossed_frame, 2,2,4,4,1}, {fl_border_box, 1,1,2,2,1}, {fl_border_box, 1,1,5,5,0}, // _FL_SHADOW_BOX {fl_border_frame, 1,1,2,2,1}, {fl_border_frame, 1,1,5,5,0}, // _FL_SHADOW_FRAME {fl_border_box, 1,1,2,2,0}, // _FL_ROUNDED_BOX {fl_border_box, 1,1,2,2,0}, // _FL_RSHADOW_BOX {fl_border_frame, 1,1,2,2,0}, // _FL_ROUNDED_FRAME {fl_flat_box, 0,0,0,0,0}, // _FL_RFLAT_BOX {fl_up_box, 3,3,6,6,0}, // _FL_ROUND_UP_BOX {fl_down_box, 3,3,6,6,0}, // _FL_ROUND_DOWN_BOX {fl_up_box, 0,0,0,0,0}, // _FL_DIAMOND_UP_BOX {fl_down_box, 0,0,0,0,0}, // _FL_DIAMOND_DOWN_BOX {fl_border_box, 1,1,2,2,0}, // _FL_OVAL_BOX {fl_border_box, 1,1,2,2,0}, // _FL_OVAL_SHADOW_BOX {fl_border_frame, 1,1,2,2,0}, // _FL_OVAL_FRAME {fl_flat_box, 0,0,0,0,0}, // _FL_OVAL_FLAT_BOX {fl_up_box, 2,2,4,4,0}, // _FL_PLASTIC_UP_BOX {fl_down_box, 2,2,4,4,0}, // _FL_PLASTIC_DOWN_BOX {fl_up_frame, 2,2,4,4,0}, // _FL_PLASTIC_UP_FRAME {fl_down_frame, 2,2,4,4,0}, // _FL_PLASTIC_DOWN_FRAME {fl_up_box, 2,2,4,4,0}, // _FL_PLASTIC_THIN_UP_BOX {fl_down_box, 2,2,4,4,0}, // _FL_PLASTIC_THIN_DOWN_BOX {fl_up_box, 2,2,4,4,0}, // _FL_PLASTIC_ROUND_UP_BOX {fl_down_box, 2,2,4,4,0}, // _FL_PLASTIC_ROUND_DOWN_BOX {fl_up_box, 2,2,4,4,0}, // _FL_GTK_UP_BOX {fl_down_box, 2,2,4,4,0}, // _FL_GTK_DOWN_BOX {fl_up_frame, 2,2,4,4,0}, // _FL_GTK_UP_FRAME {fl_down_frame, 2,2,4,4,0}, // _FL_GTK_DOWN_FRAME {fl_up_frame, 1,1,2,2,0}, // _FL_GTK_THIN_UP_FRAME {fl_down_frame, 1,1,2,2,0}, // _FL_GTK_THIN_DOWN_FRAME {fl_up_box, 1,1,2,2,0}, // _FL_GTK_THIN_ROUND_UP_BOX {fl_down_box, 1,1,2,2,0}, // _FL_GTK_THIN_ROUND_DOWN_BOX {fl_up_box, 2,2,4,4,0}, // _FL_GTK_ROUND_UP_BOX {fl_down_box, 2,2,4,4,0}, // _FL_GTK_ROUND_DOWN_BOX {fl_up_box, 2,2,4,4,0}, // _FL_GLEAM_UP_BOX {fl_down_box, 2,2,4,4,0}, // _FL_GLEAM_DOWN_BOX {fl_up_frame, 2,2,4,4,0}, // _FL_GLEAM_UP_FRAME {fl_down_frame, 2,2,4,4,0}, // _FL_GLEAM_DOWN_FRAME {fl_up_box, 2,2,4,4,0}, // _FL_GLEAM_THIN_UP_BOX {fl_down_box, 2,2,4,4,0}, // _FL_GLEAM_THIN_DOWN_BOX {fl_up_box, 2,2,4,4,0}, // _FL_GLEAM_ROUND_UP_BOX {fl_down_box, 2,2,4,4,0}, // _FL_GLEAM_ROUND_DOWN_BOX {fl_up_box, 2,2,4,4,0}, // _FL_OXY_UP_BOX, {fl_down_box, 2,2,4,4,0}, // _FL_OXY_DOWN_BOX, {fl_up_frame, 2,2,4,4,0}, // _FL_OXY_UP_FRAME, {fl_down_frame, 2,2,4,4,0}, // _FL_OXY_DOWN_FRAME, {fl_thin_up_box, 1,1,2,2,0}, // _FL_OXY_THIN_UP_BOX, {fl_thin_down_box, 1,1,2,2,0}, // _FL_OXY_THIN_DOWN_BOX, {fl_thin_up_frame, 1,1,2,2,0}, // _FL_OXY_THIN_UP_FRAME, {fl_thin_down_frame, 1,1,2,2,0}, // _FL_OXY_THIN_DOWN_FRAME, {fl_up_box, 2,2,4,4,0}, // _FL_OXY_ROUND_UP_BOX, {fl_down_box, 2,2,4,4,0}, // _FL_OXY_ROUND_DOWN_BOX, {fl_up_box, 2,2,4,4,0}, // _FL_OXY_BUTTON_UP_BOX, {fl_down_box, 2,2,4,4,0}, // _FL_OXY_BUTTON_DOWN_BOX, {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+0 {fl_down_box, 3,3,6,6,0}, // FL_FREE_BOX+1 {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+2 {fl_down_box, 3,3,6,6,0}, // FL_FREE_BOX+3 {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+4 {fl_down_box, 3,3,6,6,0}, // FL_FREE_BOX+5 {fl_up_box, 3,3,6,6,0}, // FL_FREE_BOX+6 {fl_down_box, 3,3,6,6,0} // FL_FREE_BOX+7 }; /** Returns the X offset for the given boxtype. \see box_dy() */ int Fl::box_dx(Fl_Boxtype t) {return fl_box_table[t].dx;} /** Returns the Y offset for the given boxtype. These functions return the offset values necessary for a given boxtype, useful for computing the area inside a box's borders, to prevent overdrawing the borders. For instance, in the case of a boxtype like FL_DOWN_BOX where the border width might be 2 pixels all around, the above functions would return 2, 2, 4, and 4 for box_dx, box_dy, box_dw, and box_dh respectively. An example to compute the area inside a widget's box(): \code int X = yourwidget->x() + Fl::box_dx(yourwidget->box()); int Y = yourwidget->y() + Fl::box_dy(yourwidget->box()); int W = yourwidget->w() - Fl::box_dw(yourwidget->box()); int H = yourwidget->h() - Fl::box_dh(yourwidget->box()); \endcode These functions are mainly useful in the draw() code for deriving custom widgets, where one wants to avoid drawing over the widget's own border box(). */ int Fl::box_dy(Fl_Boxtype t) {return fl_box_table[t].dy;} /** Returns the width offset for the given boxtype. \see box_dy(). */ int Fl::box_dw(Fl_Boxtype t) {return fl_box_table[t].dw;} /** Returns the height offset for the given boxtype. \see box_dy(). */ int Fl::box_dh(Fl_Boxtype t) {return fl_box_table[t].dh;} /** Sets the drawing function for a given box type. \param[in] t box type \param[in] f box drawing function \param[in] ff optional box focus rectangle drawing function */ void fl_internal_boxtype(Fl_Boxtype t, Fl_Box_Draw_F* f, Fl_Box_Draw_Focus_F* ff) { if (!fl_box_table[t].set) { fl_box_table[t].f = f; fl_box_table[t].ff = ff; fl_box_table[t].set = 1; } } /** Gets the current box drawing function for the specified box type. */ Fl_Box_Draw_F *Fl::get_boxtype(Fl_Boxtype t) { return fl_box_table[t].f; } /** Sets the function to call to draw a specific box type. \param[in] t index of the box type between 0 (FL_NO_BOX) and up to and including FL_MAX_BOXTYPE \param[in] f callback function that draws the box \param[in] dx, dy top left frame width, distance in pixels to box contents \param[in] dw, dh left plus right frame width, top plus bottom frame width \param[in] ff optional callback that draws the box focus, defaults to a rectangle, inset by dx, dy, dw, dh */ void Fl::set_boxtype(Fl_Boxtype t, Fl_Box_Draw_F* f, uchar dx, uchar dy, uchar dw, uchar dh, Fl_Box_Draw_Focus_F* ff) { fl_box_table[t].f = f; fl_box_table[t].set = 1; fl_box_table[t].dx = dx; fl_box_table[t].dy = dy; fl_box_table[t].dw = dw; fl_box_table[t].dh = dh; fl_box_table[t].ff = ff; } /** Copies the from boxtype. */ void Fl::set_boxtype(Fl_Boxtype to, Fl_Boxtype from) { fl_box_table[to] = fl_box_table[from]; } /** Draws a box using given type, position, size and color. \param[in] t box type \param[in] x, y, w, h position and size \param[in] c color */ void fl_draw_box(Fl_Boxtype t, int x, int y, int w, int h, Fl_Color c) { if (t && fl_box_table[t].f) fl_box_table[t].f(x,y,w,h,c); } /** Draws the focus rectangle inside a box using given type, position, size and color. Boxes can set their own focus drawing callback. The focus frame does not need to be a rectangle at all, but should fit inside the shape of the box. \param[in] bt box type \param[in] x, y, w, h position and size \param[in] fg, bg foreground and background color */ void fl_draw_box_focus(Fl_Boxtype bt, int x, int y, int w, int h, Fl_Color fg, Fl_Color bg) { if (!Fl::visible_focus()) return; if ((bt >= 0) && (bt <= FL_MAX_BOXTYPE) && (fl_box_table[bt].ff)) { fl_box_table[bt].ff(bt, x, y, w, h, fg, bg); return; } switch (bt) { case FL_DOWN_BOX: case FL_DOWN_FRAME: case FL_THIN_DOWN_BOX: case FL_THIN_DOWN_FRAME: x++; y++; default: break; } x += Fl::box_dx(bt); y += Fl::box_dy(bt); w -= Fl::box_dw(bt)+1; h -= Fl::box_dh(bt)+1; Fl_Color savecolor = fl_color(); fl_color(fl_contrast(fg, bg)); fl_focus_rect(x, y, w, h); fl_color(savecolor); } /** Draws the widget box according its box style */ void Fl_Widget::draw_box() const { if (box_) draw_box((Fl_Boxtype)box_, x_, y_, w_, h_, color_); draw_backdrop(); } /** If FL_ALIGN_IMAGE_BACKDROP is set, the image or deimage will be drawn */ void Fl_Widget::draw_backdrop() const { if (align() & FL_ALIGN_IMAGE_BACKDROP) { const Fl_Image *img = image(); // if there is no image, we will not draw the deimage either if (img && deimage() && !active_r()) img = deimage(); if (img) ((Fl_Image*)img)->draw(x_+(w_-img->w())/2, y_+(h_-img->h())/2); } } /** Draws a box of type t, of color c at the widget's position and size. */ void Fl_Widget::draw_box(Fl_Boxtype t, Fl_Color c) const { draw_box(t, x_, y_, w_, h_, c); } /** Draws a box of type t, of color c at the position X,Y and size W,H. */ void Fl_Widget::draw_box(Fl_Boxtype t, int X, int Y, int W, int H, Fl_Color c) const { draw_it_active = active_r(); fl_box_table[t].f(X, Y, W, H, c); draw_it_active = 1; } fltk-1.4.3/src/fl_read_image.cxx0000644000175000017500000000757115004135251016670 0ustar albrechtalbrecht// // X11 image reading routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include "Fl_Screen_Driver.H" /** Reads an RGB(A) image from the current window or off-screen buffer. \param[in] p pixel buffer, or NULL to allocate one \param[in] X,Y position of top-left of image to read \param[in] w,h width and height of image to read \param[in] alpha alpha value for image (0 for none) \returns pointer to pixel buffer, or NULL if allocation failed. The \p p argument points to a buffer that can hold the image and must be at least \p w*h*3 bytes when reading RGB images, or \p w*h*4 bytes when reading RGBA images. If NULL, fl_read_image() will create an array of the proper size which can be freed using delete[]. The \p alpha parameter controls whether an alpha channel is created and the value that is placed in the alpha channel. If 0, no alpha channel is generated. \see fl_capture_window() */ uchar *fl_read_image(uchar *p, int X, int Y, int w, int h, int alpha) { uchar *image_data = NULL; Fl_RGB_Image *img; // Under macOS and Wayland, fl_window == 0 when an Fl_Image_Surface is the current drawing // surface. Otherwise, fl_window corresponds to a mapped Fl_Window. // Under X11 and windows, fl_window is an offscreen buffer when an Fl_Image_Surface // is the current drawing or when fl_read_image() is called inside the draw() of // an Fl_Double_Window. if (fl_find(fl_window) == 0) { // read from offscreen buffer or buffer of an Fl_Double_Window img = Fl::screen_driver()->read_win_rectangle(X, Y, w, h, 0); if (!img) { return NULL; } img->alloc_array = 1; } else { img = Fl_Screen_Driver::traverse_to_gl_subwindows(Fl_Window::current(), X, Y, w, h, NULL); } int depth = alpha ? 4 : 3; if (img && img->d() != depth) { uchar *data = new uchar[img->w() * img->h() * depth]; if (depth == 4) memset(data, alpha, img->w() * img->h() * depth); uchar *d = data; const uchar *q; int ld = img->ld() ? img->ld() : img->w() * img->d(); for (int r = 0; r < img->h(); r++) { q = img->array + r * ld; for (int c = 0; c < img->w(); c++) { d[0] = q[0]; d[1] = q[1]; d[2] = q[2]; d += depth; q += img->d(); } } Fl_RGB_Image *img2 = new Fl_RGB_Image(data, img->w(), img->h(), depth); img2->alloc_array = 1; delete img; img = img2; } if (img) { if (img->w() != w || img->h() != h) { Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w, h); delete img; img = img2; } img->alloc_array = 0; image_data = (uchar*)img->array; delete img; } if (p && image_data) { memcpy(p, image_data, w * h * depth); delete[] image_data; image_data = p; } return image_data; } /** Captures the content of a rectangular zone of a mapped window. \param win a mapped Fl_Window (derived types including Fl_Gl_Window are also possible) \param x,y,w,h window area to be captured. Intersecting sub-windows are captured too. \return The captured pixels as an Fl_RGB_Image. The raw and drawing sizes of the image can differ. Returns NULL when capture was not successful. The image depth may differ between platforms. \version 1.4 */ Fl_RGB_Image *fl_capture_window(Fl_Window *win, int x, int y, int w, int h) { Fl_RGB_Image *rgb = NULL; if (win->shown()) { rgb = Fl_Screen_Driver::traverse_to_gl_subwindows(win, x, y, w, h, NULL); if (rgb) rgb->scale(w, h, 0, 1); } return rgb; } fltk-1.4.3/src/fl_curve.cxx0000644000175000017500000000531215004135251015726 0ustar albrechtalbrecht// // Bézier curve functions for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file fl_curve.cxx \brief Utility for drawing Bézier curves, adding the points to the current fl_begin/fl_vertex/fl_end path. Incremental math implementation: I very much doubt this is optimal! From Foley/vanDam page 511. If anybody has a better algorithm, please send it! */ #include #include /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** see fl_curve() */ void Fl_Graphics_Driver::curve(double X0, double Y0, double X1, double Y1, double X2, double Y2, double X3, double Y3) { double x = fl_transform_x(X0,Y0); double y = fl_transform_y(X0,Y0); // draw point 0: fl_transformed_vertex(x,y); double x1 = fl_transform_x(X1,Y1); double y1 = fl_transform_y(X1,Y1); double x2 = fl_transform_x(X2,Y2); double y2 = fl_transform_y(X2,Y2); double x3 = fl_transform_x(X3,Y3); double y3 = fl_transform_y(X3,Y3); // find the area: double a = fabs((x-x2)*(y3-y1)-(y-y2)*(x3-x1)); double b = fabs((x-x3)*(y2-y1)-(y-y3)*(x2-x1)); if (b > a) a = b; // use that to guess at the number of segments: int nSeg = int(sqrt(a)/4); if (nSeg > 1) { if (nSeg > 100) nSeg = 100; // make huge curves not hang forever if (nSeg < 9) nSeg = 9; // make tiny curevs look bearable double e = 1.0/nSeg; // calculate the coefficients of 3rd order equation: double xa = (x3-3*x2+3*x1-x); double xb = 3*(x2-2*x1+x); double xc = 3*(x1-x); // calculate the forward differences: double dx1 = ((xa*e+xb)*e+xc)*e; double dx3 = 6*xa*e*e*e; double dx2 = dx3 + 2*xb*e*e; // calculate the coefficients of 3rd order equation: double ya = (y3-3*y2+3*y1-y); double yb = 3*(y2-2*y1+y); double yc = 3*(y1-y); // calculate the forward differences: double dy1 = ((ya*e+yb)*e+yc)*e; double dy3 = 6*ya*e*e*e; double dy2 = dy3 + 2*yb*e*e; // draw points 1 .. nSeg-2: for (int i=2; i #include #include "drivers/Cocoa/Fl_MacOS_Sys_Menu_Bar_Driver.H" #include "flstring.h" #include #include #include #include "Fl_System_Driver.H" #import // keep this after include of Fl_MacOS_Sys_Menu_Bar_Driver.H because of check() conflict typedef const Fl_Menu_Item *pFl_Menu_Item; static Fl_Menu_Bar *custom_menu; static NSString *localized_Window = nil; static char *remove_ampersand(const char *s); extern void (*fl_lock_function)(); extern void (*fl_unlock_function)(); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 static void previous_tab_cb(Fl_Widget *, void *data); static void next_tab_cb(Fl_Widget *, void *data); static void move_tab_cb(Fl_Widget *, void *data); static void merge_all_windows_cb(Fl_Widget *, void *data); #endif #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13 const NSInteger NSControlStateValueOn = NSOnState; const NSInteger NSControlStateValueOff = NSOffState; #endif #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 const NSUInteger NSEventModifierFlagCommand = NSCommandKeyMask; const NSUInteger NSEventModifierFlagOption = NSAlternateKeyMask; const NSUInteger NSEventModifierFlagControl = NSControlKeyMask; const NSUInteger NSEventModifierFlagShift = NSShiftKeyMask; #endif void Fl_MacOS_Sys_Menu_Bar_Driver::draw() { bar->deactivate(); // prevent Fl_Sys_Menu_Bar object from receiving events } Fl_MacOS_Sys_Menu_Bar_Driver* Fl_MacOS_Sys_Menu_Bar_Driver::driver() { static Fl_MacOS_Sys_Menu_Bar_Driver *once = new Fl_MacOS_Sys_Menu_Bar_Driver(); if (driver_ != once) { if (driver_) { once->bar = driver_->bar; delete driver_; } driver_ = once; if (driver_->bar) driver_->update(); } return once; } /* Class FLMenuItem, derived from NSMenuItem, associates any item of the macOS system menu with a corresponding Fl_Menu_Item as follows: - if the system item's tag is >= 0, fl_sys_menu_bar->menu() + tag is the address of the relevant Fl_Menu_Item; - otherwise, the system item's representedObject is the Fl_Menu_Item's address. This allows the MacOS system menu to use the same Fl_Menu_Item's as those used by FLTK menus, the address of which can be relocated by the FLTK menu logic. The "representedObject" is used for non-relocatable Fl_Menu_Item's associated to FL_SUBMENU_POINTER. Sending the getFlItem message to a macOS system menu item (of class FLMenuItem) returns the address of the relevant Fl_Menu_Item. */ // Apple App Menu const char *Fl_Mac_App_Menu::about = "About %@"; const char *Fl_Mac_App_Menu::print = "Print Front Window & Titlebar"; const char *Fl_Mac_App_Menu::print_no_titlebar = "Print Front Window"; const char *Fl_Mac_App_Menu::toggle_print_titlebar = "Toggle printing of titlebar"; const char *Fl_Mac_App_Menu::services = "Services"; const char *Fl_Mac_App_Menu::hide = "Hide %@"; const char *Fl_Mac_App_Menu::hide_others = "Hide Others"; const char *Fl_Mac_App_Menu::show = "Show All"; const char *Fl_Mac_App_Menu::quit = "Quit %@"; @interface FLMenuItem : NSMenuItem { } - (const Fl_Menu_Item*) getFlItem; - (void) itemCallback:(Fl_Menu_*)menu; - (void) doCallback; - (void) customCallback; - (void) directCallback; - (void) setKeyEquivalentModifierMask:(int)value; - (void) setFltkShortcut:(int)key; + (int) addNewItem:(const Fl_Menu_Item*)mitem menu:(NSMenu*)menu action:(SEL)selector; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 - (BOOL)validateMenuItem:(NSMenuItem *)item; #endif @end @implementation FLMenuItem - (const Fl_Menu_Item*) getFlItem // returns the Fl_Menu_Item corresponding to this system menu item { NSInteger tag = [self tag]; if (tag >= 0) return fl_sys_menu_bar->menu() + tag; return *(const Fl_Menu_Item**)[(NSData*)[self representedObject] bytes]; } - (void) itemCallback:(Fl_Menu_*)menu { const Fl_Menu_Item *item = [self getFlItem]; menu->picked(item); Fl::flush(); if ( item->flags & FL_MENU_TOGGLE ) { // update the menu toggle symbol [self setState:(item->value() ? NSControlStateValueOn : NSControlStateValueOff)]; } else if ( item->flags & FL_MENU_RADIO ) { // update the menu radio symbols NSMenu* this_menu = [self menu]; NSInteger flRank = [this_menu indexOfItem:self]; NSInteger last = [this_menu numberOfItems] - 1; int from = (int)flRank; while(from > 0) { if ([[this_menu itemAtIndex:from-1] isSeparatorItem]) break; item = [(FLMenuItem*)[this_menu itemAtIndex:from-1] getFlItem]; if ( !(item->flags & FL_MENU_RADIO) ) break; from--; } int to = (int)flRank; while (to < last) { if ([[this_menu itemAtIndex:to+1] isSeparatorItem]) break; item = [(FLMenuItem*)[this_menu itemAtIndex:to+1] getFlItem]; if (!(item->flags & FL_MENU_RADIO)) break; to++; } for(int i = from; i <= to; i++) { NSMenuItem *nsitem = [this_menu itemAtIndex:i]; [nsitem setState:(nsitem != self ? NSControlStateValueOff : NSControlStateValueOn)]; } } } - (void) doCallback { fl_lock_function(); [self itemCallback:fl_sys_menu_bar]; fl_unlock_function(); } - (void) customCallback { fl_lock_function(); [self itemCallback:custom_menu]; fl_unlock_function(); } - (void) directCallback { fl_lock_function(); Fl_Menu_Item *item = (Fl_Menu_Item *)[(NSData*)[self representedObject] bytes]; if ( item && item->callback() ) item->do_callback(NULL); fl_unlock_function(); } - (void) setKeyEquivalentModifierMask:(int)value { NSUInteger macMod = 0; if ( value & FL_META ) macMod = NSEventModifierFlagCommand; if ( value & FL_SHIFT || (value > 0 && value < 127 && isupper(value)) ) macMod |= NSEventModifierFlagShift; if ( value & FL_ALT ) macMod |= NSEventModifierFlagOption; if ( value & FL_CTRL ) macMod |= NSEventModifierFlagControl; [super setKeyEquivalentModifierMask:macMod]; } - (void) setFltkShortcut:(int)key { // Separate key and modifier int mod = key; mod &= ~FL_KEY_MASK; // modifier(s) key &= FL_KEY_MASK; // key unichar mac_key = (unichar)key; if ( (key >= (FL_F+1)) && (key <= FL_F_Last) ) { // Handle function keys int fkey_num = (key - FL_F); // 1,2.. mac_key = NSF1FunctionKey + fkey_num - 1; } else if (key == FL_Escape) { mac_key = 27; } else if (key == FL_Tab) { mac_key = NSTabCharacter; } else if (key == FL_Enter) { mac_key = 0x0d; } else if (key == FL_BackSpace) { mac_key = NSBackspaceCharacter; } else if (key == FL_Delete) { mac_key = NSDeleteCharacter; } else if (key == FL_Up) { mac_key = NSUpArrowFunctionKey; } else if (key == FL_Down) { mac_key = NSDownArrowFunctionKey; } else if (key == FL_Left) { mac_key = NSLeftArrowFunctionKey; } else if (key == FL_Right) { mac_key = NSRightArrowFunctionKey; } else if (key == FL_Page_Up) { mac_key = NSPageUpFunctionKey; } else if (key == FL_Page_Down) { mac_key = NSPageDownFunctionKey; } else if (key == FL_KP_Enter) { mac_key = 0x2324; // "⌤" U+2324 } else if (key == FL_Home) { mac_key = NSHomeFunctionKey; } else if (key == FL_End) { mac_key = NSEndFunctionKey; } [self setKeyEquivalent:[NSString stringWithCharacters:&mac_key length:1]]; [self setKeyEquivalentModifierMask:mod]; } + (int) addNewItem:(const Fl_Menu_Item*)mitem menu:(NSMenu*)menu action:(SEL)selector { char *name = remove_ampersand(mitem->label()); NSString *title = NSLocalizedString([NSString stringWithUTF8String:name], nil); free(name); FLMenuItem *item = [[FLMenuItem alloc] initWithTitle:title action:selector keyEquivalent:@""]; // >= 0 if mitem is in the menu items of fl_sys_menu_bar, -1 if not NSInteger index = (fl_sys_menu_bar ? fl_sys_menu_bar->find_index(mitem) : -1); [item setTag:index]; if (index < 0) { NSData *pointer = [[NSData alloc] initWithBytes:&mitem length:sizeof(Fl_Menu_Item*)]; [item setRepresentedObject:pointer]; [pointer release];//pointer will dealloc each time item dealloc's } [menu addItem:item]; [item setTarget:item]; int retval = (int)[menu indexOfItem:item]; [item release]; return retval; } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 - (BOOL)validateMenuItem:(NSMenuItem *)item { // return YES for all but items of the Window menu if (fl_mac_os_version < 101200 || Fl_Sys_Menu_Bar::window_menu_style() <= Fl_Sys_Menu_Bar::tabbing_mode_none || [item hasSubmenu]) return YES; NSString *title = [[item parentItem] title]; // 10.6 if (!title || !localized_Window || [title compare:localized_Window] != NSOrderedSame) return YES; const Fl_Menu_Item *flitem = [(FLMenuItem*)item getFlItem]; Fl_Callback *item_cb = flitem->callback(); if (item_cb == previous_tab_cb || item_cb == next_tab_cb || item_cb == move_tab_cb) { // is the current window tabbed? Fl_Window *win = Fl::first_window(); NSWindow *main = win ? (NSWindow*)fl_xid(win) : nil; return (main && [main tabbedWindows] != nil); } else if (item_cb == merge_all_windows_cb) { // is there any untabbed, tabbable window? int total = 0, untabbed = 0; while ((++flitem)->label()) { total++; NSWindow *nsw = (NSWindow*)fl_xid( (Fl_Window*)flitem->user_data() ); if (![nsw tabbedWindows] && [nsw tabbingMode] != NSWindowTabbingModeDisallowed) { untabbed++; } } return (untabbed > 0 && total >= 2); } return YES; } #endif @end void Fl_MacOS_Sys_Menu_Bar_Driver::about( Fl_Callback *cb, void *user_data) { Fl_Menu_Item aboutItem; memset(&aboutItem, 0, sizeof(Fl_Menu_Item)); aboutItem.callback(cb); aboutItem.user_data(user_data); NSMenu *appleMenu = [[[NSApp mainMenu] itemAtIndex:0] submenu]; CFStringRef cfname = CFStringCreateCopy(NULL, (CFStringRef)[[appleMenu itemAtIndex:0] title]); [appleMenu removeItemAtIndex:0]; FLMenuItem *item = [[[FLMenuItem alloc] initWithTitle:(NSString*)cfname action:@selector(directCallback) keyEquivalent:@""] autorelease]; NSData *pointer = [NSData dataWithBytes:&aboutItem length:sizeof(Fl_Menu_Item)]; [item setRepresentedObject:pointer]; [appleMenu insertItem:item atIndex:0]; CFRelease(cfname); [item setTarget:item]; } /* * Set a shortcut for an Apple menu item using the FLTK shortcut descriptor. */ static void setMenuShortcut( NSMenu* mh, int miCnt, const Fl_Menu_Item *m ) { if ( !m->shortcut_ ) return; if ( m->flags & FL_SUBMENU ) return; if ( m->flags & FL_SUBMENU_POINTER ) return; FLMenuItem* menuItem = (FLMenuItem*)[mh itemAtIndex:miCnt]; [menuItem setFltkShortcut:(m->shortcut_)]; } /* * Set the Toggle and Radio flag based on FLTK flags */ static void setMenuFlags( NSMenu* mh, int miCnt, const Fl_Menu_Item *m ) { if ( m->flags & FL_MENU_TOGGLE ) { NSMenuItem *menuItem = [mh itemAtIndex:miCnt]; [menuItem setState:(m->flags & FL_MENU_VALUE ? NSControlStateValueOn : NSControlStateValueOff)]; } else if ( m->flags & FL_MENU_RADIO ) { NSMenuItem *menuItem = [mh itemAtIndex:miCnt]; [menuItem setState:(m->flags & FL_MENU_VALUE ? NSControlStateValueOn : NSControlStateValueOff)]; } } static char *remove_ampersand(const char *s) { char *ret = fl_strdup(s); const char *p = s; char *q = ret; while(*p != 0) { if (p[0]=='&') { if (p[1]=='&') { *q++ = '&'; p+=2; } else { p++; } } else { *q++ = *p++; } } *q = 0; return ret; } /* * create a sub menu for a specific menu handle */ static void createSubMenu( NSMenu *mh, pFl_Menu_Item &mm, const Fl_Menu_Item *mitem, SEL selector) { NSMenu *submenu; int miCnt, flags; if (mitem) { NSMenuItem *menuItem; char *ts = remove_ampersand(mitem->text); NSString *title = NSLocalizedString([NSString stringWithUTF8String:ts], nil); free(ts); submenu = [[NSMenu alloc] initWithTitle:(NSString*)title]; [submenu setAutoenablesItems:NO]; int cnt; cnt = (int)[mh numberOfItems]; cnt--; menuItem = [mh itemAtIndex:cnt]; [menuItem setSubmenu:submenu]; [submenu release]; } else submenu = mh; while ( mm->text ) { if (!mm->visible() ) { // skip invisible items and submenus mm = mm->next(0); continue; } miCnt = [FLMenuItem addNewItem:mm menu:submenu action:( (mm->flags & (FL_SUBMENU+FL_SUBMENU_POINTER) && !mm->callback()) ? nil : selector) ]; setMenuFlags( submenu, miCnt, mm ); setMenuShortcut( submenu, miCnt, mm ); if (mitem && (mm->flags & FL_MENU_INACTIVE || mitem->flags & FL_MENU_INACTIVE)) { NSMenuItem *item = [submenu itemAtIndex:miCnt]; [item setEnabled:NO]; } flags = mm->flags; if ( mm->flags & FL_SUBMENU ) { mm++; createSubMenu( submenu, mm, mm - 1, selector); } else if ( mm->flags & FL_SUBMENU_POINTER ) { const Fl_Menu_Item *smm = (Fl_Menu_Item*)mm->user_data_; createSubMenu( submenu, smm, mm, selector); } if ( flags & FL_MENU_DIVIDER ) { [submenu addItem:[NSMenuItem separatorItem]]; } mm++; } } /* * convert a complete Fl_Menu_Item array into a series of menus in the top menu bar * ALL PREVIOUS SYSTEM MENUS, EXCEPT THE APPLICATION MENU, ARE REPLACED BY THE NEW DATA */ static void convertToMenuBar(const Fl_Menu_Item *mm) { NSMenu *fl_system_menu = [NSApp mainMenu]; int count;//first, delete all existing system menus count = (int)[fl_system_menu numberOfItems]; for(int i = count - 1; i > 0; i--) { [fl_system_menu removeItem:[fl_system_menu itemAtIndex:i]]; } if (mm) createSubMenu(fl_system_menu, mm, NULL, @selector(doCallback)); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 if (localized_Window) { NSMenuItem *item = [fl_system_menu itemWithTitle:localized_Window]; if (item) [[item submenu] setAutoenablesItems:YES]; } #endif } void Fl_MacOS_Sys_Menu_Bar_Driver::update() { convertToMenuBar(bar->Fl_Menu_::menu()); } static int process_sys_menu_shortcuts(int event) { if (event != FL_SHORTCUT || !fl_sys_menu_bar || Fl::modal()) return 0; // is the last event the shortcut of an item of the fl_sys_menu_bar menu ? const Fl_Menu_Item *item = fl_sys_menu_bar->menu()->test_shortcut(); if (!item) return 0; if (item->visible()) // have the system menu process the shortcut, highlighting the corresponding menu [[NSApp mainMenu] performKeyEquivalent:[NSApp currentEvent]]; else // have FLTK process the shortcut associated to an invisible Fl_Menu_Item fl_sys_menu_bar->picked(item); return 1; } Fl_MacOS_Sys_Menu_Bar_Driver::Fl_MacOS_Sys_Menu_Bar_Driver() : Fl_Sys_Menu_Bar_Driver() { window_menu_items = NULL; first_window_menu_item = 0; Fl::add_handler(process_sys_menu_shortcuts); } Fl_MacOS_Sys_Menu_Bar_Driver::~Fl_MacOS_Sys_Menu_Bar_Driver() { Fl::remove_handler(process_sys_menu_shortcuts); } void Fl_MacOS_Sys_Menu_Bar_Driver::menu(const Fl_Menu_Item *m) { fl_open_display(); bar->Fl_Menu_Bar::menu( m ); convertToMenuBar(m); } void Fl_MacOS_Sys_Menu_Bar_Driver::clear() { bar->Fl_Menu_::clear(); convertToMenuBar(NULL); } int Fl_MacOS_Sys_Menu_Bar_Driver::clear_submenu(int index) { int retval = bar->Fl_Menu_::clear_submenu(index); if (retval != -1) update(); return retval; } void Fl_MacOS_Sys_Menu_Bar_Driver::remove(int index) { bar->Fl_Menu_::remove(index); update(); } void Fl_MacOS_Sys_Menu_Bar_Driver::replace(int index, const char *name) { bar->Fl_Menu_::replace(index, name); update(); } void Fl_MacOS_Sys_Menu_Bar_Driver::mode(int i, int fl) { bar->Fl_Menu_::mode(i, fl); update(); } void Fl_MacOS_Sys_Menu_Bar_Driver::shortcut (int i, int s) { bar->Fl_Menu_Bar::shortcut(i, s); update(); } void Fl_MacOS_Sys_Menu_Bar_Driver::setonly (Fl_Menu_Item *item) { bar->Fl_Menu_::setonly(item); update(); } int Fl_MacOS_Sys_Menu_Bar_Driver::add(const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) { fl_open_display(); int index = bar->Fl_Menu_::add(label, shortcut, cb, user_data, flags); update(); return index; } int Fl_MacOS_Sys_Menu_Bar_Driver::add(const char* str) { fl_open_display(); int index = bar->Fl_Menu_::add(str); update(); return index; } int Fl_MacOS_Sys_Menu_Bar_Driver::insert(int index, const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) { fl_open_display(); int menu_index = bar->Fl_Menu_::insert(index, label, shortcut, cb, user_data, flags); update(); return menu_index; } /** \class Fl_Mac_App_Menu Mac OS-specific class allowing to customize and localize the application menu. The public class attributes are used to build the application menu. They can be localized at run time to any UTF-8 text by placing instructions such as this before fl_open_display() gets called: \verbatim Fl_Mac_App_Menu::print = "Imprimer la fenêtre"; \endverbatim \see \ref osissues_macos for another way to localization. */ void Fl_Mac_App_Menu::custom_application_menu_items(const Fl_Menu_Item *m) { fl_open_display(); // create the system menu, if needed custom_menu = new Fl_Menu_Bar(0,0,0,0); custom_menu->menu(m); NSMenu *menu = [[[NSApp mainMenu] itemAtIndex:0] submenu]; // the application menu NSInteger to_index; if ([[menu itemAtIndex:2] action] != @selector(printPanel)) { // the 'Print' item was removed [menu insertItem:[NSMenuItem separatorItem] atIndex:1]; to_index = 2; } else to_index = 5; // after the "Print Front Window/Toggle" items and the separator NSInteger count = [menu numberOfItems]; createSubMenu(menu, m, NULL, @selector(customCallback)); // add new items at end of application menu NSInteger count2 = [menu numberOfItems]; for (NSInteger i = count; i < count2; i++) { // move new items to their desired position in application menu NSMenuItem *item = [menu itemAtIndex:i]; [item retain]; [menu removeItemAtIndex:i]; [menu insertItem:item atIndex:to_index++]; [item release]; } } static void minimize_win_cb(Fl_Widget *, void *data) { [[NSApp mainWindow] miniaturize:nil]; } static void window_menu_cb(Fl_Widget *, void *data) { if (data) ((Fl_Window*)data)->show(); } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 static void previous_tab_cb(Fl_Widget *, void *data) { [[NSApp mainWindow] selectPreviousTab:nil]; } static void next_tab_cb(Fl_Widget *, void *data) { [[NSApp mainWindow] selectNextTab:nil]; } static void move_tab_cb(Fl_Widget *, void *data) { [[NSApp mainWindow] moveTabToNewWindow:nil]; } static void merge_all_windows_cb(Fl_Widget *, void *) { Fl_Window *first = Fl::first_window(); while (first && (first->parent() || !first->border())) first = Fl::next_window(first); if (first) { [(NSWindow*)fl_xid(first) mergeAllWindows:nil]; } } #endif static bool window_menu_installed = false; static int window_menu_items_count = 0; void Fl_MacOS_Sys_Menu_Bar_Driver::create_window_menu(void) { if (window_menu_style() == Fl_Sys_Menu_Bar::no_window_menu) return; if (window_menu_installed) return; window_menu_installed = true; int rank = 0; if (fl_sys_menu_bar && fl_sys_menu_bar->menu()) { if (fl_sys_menu_bar->find_index("Window") >= 0) { // there's already a "Window" menu -> don't create another window_menu_style_ = Fl_Sys_Menu_Bar::no_window_menu; return; } // put the Window menu last in menu bar or before Help if it's present const Fl_Menu_Item *item = fl_sys_menu_bar->menu(); while (item->label() && strcmp(item->label(), "Help") != 0) { item = item->next(); } rank = fl_sys_menu_bar->find_index(item); } else if (!fl_sys_menu_bar) { fl_open_display(); new Fl_Sys_Menu_Bar(0,0,0,0); } if (!window_menu_items_count) { window_menu_items_count = 6; window_menu_items = (Fl_Menu_Item*)calloc(window_menu_items_count, sizeof(Fl_Menu_Item)); } rank = fl_sys_menu_bar->Fl_Menu_::insert(rank, "Window", 0, NULL, window_menu_items, FL_SUBMENU_POINTER); localized_Window = NSLocalizedString(@"Window", nil); window_menu_items[0].label("Minimize"); window_menu_items[0].callback(minimize_win_cb); window_menu_items[0].shortcut(FL_COMMAND+'m'); window_menu_items[0].flags = FL_MENU_DIVIDER; first_window_menu_item = 1; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 if (fl_mac_os_version >= 101200 && window_menu_style() != Fl_Sys_Menu_Bar::tabbing_mode_none) { window_menu_items[1].label("Show Previous Tab"); window_menu_items[1].callback(previous_tab_cb); window_menu_items[1].shortcut(FL_SHIFT+FL_CTRL+0x9); window_menu_items[2].label("Show Next Tab"); window_menu_items[2].callback(next_tab_cb); window_menu_items[2].shortcut(FL_CTRL+0x9); window_menu_items[3].label("Move Tab To New Window"); window_menu_items[3].callback(move_tab_cb); window_menu_items[4].label("Merge All Windows"); window_menu_items[4].callback(merge_all_windows_cb); window_menu_items[4].flags = FL_MENU_DIVIDER; first_window_menu_item = 5; } #endif fl_sys_menu_bar->menu_end(); fl_sys_menu_bar->update(); } void Fl_MacOS_Sys_Menu_Bar_Driver::new_window(Fl_Window *win) { if (!window_menu_style() || !win->label()) return; int index = window_menu_items->size() - 1; if (index >= window_menu_items_count - 1) { window_menu_items_count += 5; window_menu_items = (Fl_Menu_Item*)realloc(window_menu_items, window_menu_items_count * sizeof(Fl_Menu_Item)); Fl_Menu_Item *item = (Fl_Menu_Item*)fl_sys_menu_bar->find_item("Window"); item->user_data(window_menu_items); } const char *p = win->iconlabel() ? win->iconlabel() : win->label(); window_menu_items[index].label(p); window_menu_items[index].callback(window_menu_cb); window_menu_items[index].user_data(win); window_menu_items[index].flags = FL_MENU_RADIO; window_menu_items[index+1].label(NULL); window_menu_items[index].setonly(); fl_sys_menu_bar->update(); } void Fl_MacOS_Sys_Menu_Bar_Driver::remove_window(Fl_Window *win) { if (!window_menu_style()) return; int index = first_window_menu_item; if (index < 1) return; while (true) { Fl_Menu_Item *item = window_menu_items + index; if (!item->label()) return; if (item->user_data() == win) { bool doit = item->value(); int count = window_menu_items->size(); if (count - index - 1 > 0) memmove(item, item + 1, (count - index - 1)*sizeof(Fl_Menu_Item)); memset(window_menu_items + count - 2, 0, sizeof(Fl_Menu_Item)); if (doit) { // select Fl::first_window() in Window menu item = window_menu_items + first_window_menu_item; while (item->label() && item->user_data() != Fl::first_window()) item++; if (item->label()) { ((Fl_Window*)item->user_data())->show(); item->setonly(); } } bar->update(); break; } index++; } } void Fl_MacOS_Sys_Menu_Bar_Driver::rename_window(Fl_Window *win) { if (!window_menu_style()) return; int index = first_window_menu_item; if (index < 1) return; while (true) { Fl_Menu_Item *item = window_menu_items + index; if (!item->label()) return; if (item->user_data() == win) { item->label(win->iconlabel() ? win->iconlabel() : win->label()); bar->update(); return; } index++; } } void fl_mac_set_about(Fl_Callback *cb, void *user_data, int shortcut) { Fl_Sys_Menu_Bar::about(cb, user_data); } void Fl_MacOS_Sys_Menu_Bar_Driver::play_menu(const Fl_Menu_Item *item) { // Use the accessibility interface to programmatically open a menu of the system menubar CFArrayRef children = NULL; CFIndex count = 0; AXUIElementRef element; char *label = remove_ampersand(item->label()); NSString *mac_name = NSLocalizedString([NSString stringWithUTF8String:label], nil); free(label); AXUIElementRef appElement = AXUIElementCreateApplication(getpid()); AXUIElementRef menu_bar = NULL; AXError error = AXUIElementCopyAttributeValue(appElement, kAXMenuBarAttribute, (CFTypeRef *)&menu_bar); if (!error) error = AXUIElementGetAttributeValueCount(menu_bar, kAXChildrenAttribute, &count); if (!error) error = AXUIElementCopyAttributeValues(menu_bar, kAXChildrenAttribute, 0, count, &children); if (!error) { NSEnumerator *enumerator = [(NSArray*)children objectEnumerator]; [enumerator nextObject]; // skip Apple menu [enumerator nextObject]; // skip application menu bool need_more = true; while (need_more && (element = (AXUIElementRef)[enumerator nextObject]) != nil) { CFTypeRef title = NULL; need_more = ( AXUIElementCopyAttributeValue(element, kAXTitleAttribute, &title) == 0 ); if (need_more && [(NSString*)title isEqualToString:mac_name]) { AXUIElementPerformAction(element, kAXPressAction); need_more = false; } if (title) CFRelease(title); } } if (menu_bar) CFRelease(menu_bar); if (children) CFRelease(children); CFRelease(appElement); } #endif /* __APPLE__ */ fltk-1.4.3/src/fl_cursor.cxx0000644000175000017500000001164115004135251016121 0ustar albrechtalbrecht// // Mouse cursor support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Change the current cursor. // Under X the cursor is attached to the X window. I tried to hide // this and pretend that changing the cursor is a drawing function. // This avoids a field in the Fl_Window, and I suspect is more // portable to other systems. #include #include #include #include #include #include "Fl_Window_Driver.H" #include #include "fl_cursor_wait.xpm" #include "fl_cursor_help.xpm" #include "fl_cursor_nwse.xpm" #include "fl_cursor_nesw.xpm" #include "fl_cursor_none.xpm" /** Sets the cursor for the current window to the specified shape and colors. The cursors are defined in the header file. */ void fl_cursor(Fl_Cursor c) { if (Fl::first_window()) Fl::first_window()->cursor(c); } /* For back compatibility only. */ void fl_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) { fl_cursor(c); } /** Sets the default window cursor. This is the cursor that will be used after the mouse pointer leaves a widget with a custom cursor set. \see cursor(const Fl_RGB_Image*, int, int), default_cursor() */ void Fl_Window::default_cursor(Fl_Cursor c) { cursor_default = c; cursor(c); } static void fallback_cursor(Fl_Window *w, Fl_Cursor c) { const char **xpm; int hotx, hoty; // The standard arrow is our final fallback, so something is broken // if we get called back here with that as an argument. if (c == FL_CURSOR_ARROW) return; switch (c) { case FL_CURSOR_WAIT: xpm = (const char**)fl_cursor_wait_xpm; hotx = 7; hoty = 9; break; case FL_CURSOR_HELP: xpm = (const char**)fl_cursor_help_xpm; hotx = 1; hoty = 3; break; case FL_CURSOR_NWSE: xpm = (const char**)fl_cursor_nwse_xpm; hotx = 7; hoty = 7; break; case FL_CURSOR_NESW: xpm = (const char**)fl_cursor_nesw_xpm; hotx = 7; hoty = 7; break; case FL_CURSOR_NONE: xpm = (const char**)fl_cursor_none_xpm; hotx = 0; hoty = 0; break; default: w->cursor(FL_CURSOR_ARROW); return; } Fl_Pixmap pxm(xpm); Fl_RGB_Image image(&pxm); w->cursor(&image, hotx, hoty); } /** Changes the cursor for this window. The window must be show()'n for this function to have any effect. This always calls the system. If you are changing the cursor a lot you may want to keep track of how you set it in a static variable and call this only if the new cursor is different. The type Fl_Cursor is an enumeration defined in . \see cursor(const Fl_RGB_Image*, int, int), default_cursor() */ void Fl_Window::cursor(Fl_Cursor c) { int ret; // the cursor must be set for the top level window, not for subwindows Fl_Window *w = window(), *toplevel = this; while (w) { toplevel = w; w = w->window(); } if (toplevel != this) { toplevel->cursor(c); return; } if (c == FL_CURSOR_DEFAULT) c = cursor_default; if (!flx_) return; ret = pWindowDriver->set_cursor(c); if (ret) return; fallback_cursor(this, c); } /** Changes the cursor for this window using the provided image as cursor's shape. The window must be show()'n for this function to have any effect. This always calls the system. If you are changing the cursor a lot you may want to keep track of how you set it in a static variable and call this only if the new cursor is different. The default cursor will be used if the provided image cannot be used as a cursor. \param image Sets the cursor size and shape \param hotx,hoty Sets the cursor's active location relatively to top-left of \c image when clicking \see cursor(Fl_Cursor), default_cursor() */ void Fl_Window::cursor(const Fl_RGB_Image *image, int hotx, int hoty) { int ret; // the cursor must be set for the top level window, not for subwindows Fl_Window *w = window(), *toplevel = this; while (w) { toplevel = w; w = w->window(); } if (toplevel != this) { toplevel->cursor(image, hotx, hoty); return; } if (!flx_) return; ret = pWindowDriver->set_cursor(image, hotx, hoty); if (ret) return; cursor(FL_CURSOR_DEFAULT); } /** For back compatibility only. Same as Fl_Window::cursor(Fl_Cursor) */ void Fl_Window::cursor(Fl_Cursor c, Fl_Color, Fl_Color) { cursor(c); } /** For back compatibility only. same as Fl_Window::default_cursor(Fl_Cursor) */ void Fl_Window::default_cursor(Fl_Cursor c, Fl_Color, Fl_Color) { default_cursor(c); } fltk-1.4.3/src/freeglut_stroke_mono_roman.cxx0000644000175000017500000014122215004135251021552 0ustar albrechtalbrecht/* * freeglut_stroke_mono_roman.c * * freeglut Monospace Roman stroke font definition * * Copyright (c) 1999-2010 Pawel W. Olszta. All Rights Reserved. * Written by Pawel W. Olszta, * Creation date: Thu Dec 16 1999 * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* This file has been automatically generated by the genstroke utility. */ #include /* char: 0x20 */ static const Fl_Glut_StrokeStrip ch32st[] = { { 0, 0 } }; static const Fl_Glut_StrokeChar ch32 = {104.762f,0,ch32st}; /* char: 0x21 */ static const Fl_Glut_StrokeVertex ch33st0[] = { {52.381f,100.0f}, {52.381f,33.3333f} }; static const Fl_Glut_StrokeVertex ch33st1[] = { {52.381f,9.5238f}, {47.6191f,4.7619f}, {52.381f,0.0f}, {57.1429f,4.7619f}, {52.381f,9.5238f} }; static const Fl_Glut_StrokeStrip ch33st[] = { {2,ch33st0}, {5,ch33st1} }; static const Fl_Glut_StrokeChar ch33 = {104.762f,2,ch33st}; /* char: 0x22 */ static const Fl_Glut_StrokeVertex ch34st0[] = { {33.3334f,100.0f}, {33.3334f,66.6667f} }; static const Fl_Glut_StrokeVertex ch34st1[] = { {71.4286f,100.0f}, {71.4286f,66.6667f} }; static const Fl_Glut_StrokeStrip ch34st[] = { {2,ch34st0}, {2,ch34st1} }; static const Fl_Glut_StrokeChar ch34 = {104.762f,2,ch34st}; /* char: 0x23 */ static const Fl_Glut_StrokeVertex ch35st0[] = { {54.7619f,119.048f}, {21.4286f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch35st1[] = { {83.3334f,119.048f}, {50.0f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch35st2[] = { {21.4286f,57.1429f}, {88.0952f,57.1429f} }; static const Fl_Glut_StrokeVertex ch35st3[] = { {16.6667f,28.5714f}, {83.3334f,28.5714f} }; static const Fl_Glut_StrokeStrip ch35st[] = { {2,ch35st0}, {2,ch35st1}, {2,ch35st2}, {2,ch35st3} }; static const Fl_Glut_StrokeChar ch35 = {104.762f,4,ch35st}; /* char: 0x24 */ static const Fl_Glut_StrokeVertex ch36st0[] = { {42.8571f,119.048f}, {42.8571f,-19.0476f} }; static const Fl_Glut_StrokeVertex ch36st1[] = { {61.9047f,119.048f}, {61.9047f,-19.0476f} }; static const Fl_Glut_StrokeVertex ch36st2[] = { {85.7143f,85.7143f}, {76.1905f,95.2381f}, {61.9047f,100.0f}, {42.8571f,100.0f}, {28.5714f,95.2381f}, {19.0476f,85.7143f}, {19.0476f,76.1905f}, {23.8095f,66.6667f}, {28.5714f,61.9048f}, {38.0952f,57.1429f}, {66.6666f,47.619f}, {76.1905f,42.8571f}, {80.9524f,38.0952f}, {85.7143f,28.5714f}, {85.7143f,14.2857f}, {76.1905f,4.7619f}, {61.9047f,0.0f}, {42.8571f,0.0f}, {28.5714f,4.7619f}, {19.0476f,14.2857f} }; static const Fl_Glut_StrokeStrip ch36st[] = { {2,ch36st0}, {2,ch36st1}, {20,ch36st2} }; static const Fl_Glut_StrokeChar ch36 = {104.762f,3,ch36st}; /* char: 0x25 */ static const Fl_Glut_StrokeVertex ch37st0[] = { {95.2381f,100.0f}, {9.5238f,0.0f} }; static const Fl_Glut_StrokeVertex ch37st1[] = { {33.3333f,100.0f}, {42.8571f,90.4762f}, {42.8571f,80.9524f}, {38.0952f,71.4286f}, {28.5714f,66.6667f}, {19.0476f,66.6667f}, {9.5238f,76.1905f}, {9.5238f,85.7143f}, {14.2857f,95.2381f}, {23.8095f,100.0f}, {33.3333f,100.0f}, {42.8571f,95.2381f}, {57.1428f,90.4762f}, {71.4286f,90.4762f}, {85.7143f,95.2381f}, {95.2381f,100.0f} }; static const Fl_Glut_StrokeVertex ch37st2[] = { {76.1905f,33.3333f}, {66.6667f,28.5714f}, {61.9048f,19.0476f}, {61.9048f,9.5238f}, {71.4286f,0.0f}, {80.9524f,0.0f}, {90.4762f,4.7619f}, {95.2381f,14.2857f}, {95.2381f,23.8095f}, {85.7143f,33.3333f}, {76.1905f,33.3333f} }; static const Fl_Glut_StrokeStrip ch37st[] = { {2,ch37st0}, {16,ch37st1}, {11,ch37st2} }; static const Fl_Glut_StrokeChar ch37 = {104.762f,3,ch37st}; /* char: 0x26 */ static const Fl_Glut_StrokeVertex ch38st0[] = { {100.0f,57.1429f}, {100.0f,61.9048f}, {95.2381f,66.6667f}, {90.4762f,66.6667f}, {85.7143f,61.9048f}, {80.9524f,52.381f}, {71.4286f,28.5714f}, {61.9048f,14.2857f}, {52.3809f,4.7619f}, {42.8571f,0.0f}, {23.8095f,0.0f}, {14.2857f,4.7619f}, {9.5238f,9.5238f}, {4.7619f,19.0476f}, {4.7619f,28.5714f}, {9.5238f,38.0952f}, {14.2857f,42.8571f}, {47.619f,61.9048f}, {52.3809f,66.6667f}, {57.1429f,76.1905f}, {57.1429f,85.7143f}, {52.3809f,95.2381f}, {42.8571f,100.0f}, {33.3333f,95.2381f}, {28.5714f,85.7143f}, {28.5714f,76.1905f}, {33.3333f,61.9048f}, {42.8571f,47.619f}, {66.6667f,14.2857f}, {76.1905f,4.7619f}, {85.7143f,0.0f}, {95.2381f,0.0f}, {100.0f,4.7619f}, {100.0f,9.5238f} }; static const Fl_Glut_StrokeStrip ch38st[] = { {34,ch38st0} }; static const Fl_Glut_StrokeChar ch38 = {104.762f,1,ch38st}; /* char: 0x27 */ static const Fl_Glut_StrokeVertex ch39st0[] = { {52.381f,100.0f}, {52.381f,66.6667f} }; static const Fl_Glut_StrokeStrip ch39st[] = { {2,ch39st0} }; static const Fl_Glut_StrokeChar ch39 = {104.762f,1,ch39st}; /* char: 0x28 */ static const Fl_Glut_StrokeVertex ch40st0[] = { {69.0476f,119.048f}, {59.5238f,109.524f}, {50.0f,95.2381f}, {40.4762f,76.1905f}, {35.7143f,52.381f}, {35.7143f,33.3333f}, {40.4762f,9.5238f}, {50.0f,-9.5238f}, {59.5238f,-23.8095f}, {69.0476f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch40st[] = { {10,ch40st0} }; static const Fl_Glut_StrokeChar ch40 = {104.762f,1,ch40st}; /* char: 0x29 */ static const Fl_Glut_StrokeVertex ch41st0[] = { {35.7143f,119.048f}, {45.2381f,109.524f}, {54.7619f,95.2381f}, {64.2857f,76.1905f}, {69.0476f,52.381f}, {69.0476f,33.3333f}, {64.2857f,9.5238f}, {54.7619f,-9.5238f}, {45.2381f,-23.8095f}, {35.7143f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch41st[] = { {10,ch41st0} }; static const Fl_Glut_StrokeChar ch41 = {104.762f,1,ch41st}; /* char: 0x2a */ static const Fl_Glut_StrokeVertex ch42st0[] = { {52.381f,71.4286f}, {52.381f,14.2857f} }; static const Fl_Glut_StrokeVertex ch42st1[] = { {28.5715f,57.1429f}, {76.1905f,28.5714f} }; static const Fl_Glut_StrokeVertex ch42st2[] = { {76.1905f,57.1429f}, {28.5715f,28.5714f} }; static const Fl_Glut_StrokeStrip ch42st[] = { {2,ch42st0}, {2,ch42st1}, {2,ch42st2} }; static const Fl_Glut_StrokeChar ch42 = {104.762f,3,ch42st}; /* char: 0x2b */ static const Fl_Glut_StrokeVertex ch43st0[] = { {52.3809f,85.7143f}, {52.3809f,0.0f} }; static const Fl_Glut_StrokeVertex ch43st1[] = { {9.5238f,42.8571f}, {95.2381f,42.8571f} }; static const Fl_Glut_StrokeStrip ch43st[] = { {2,ch43st0}, {2,ch43st1} }; static const Fl_Glut_StrokeChar ch43 = {104.762f,2,ch43st}; /* char: 0x2c */ static const Fl_Glut_StrokeVertex ch44st0[] = { {57.1429f,4.7619f}, {52.381f,0.0f}, {47.6191f,4.7619f}, {52.381f,9.5238f}, {57.1429f,4.7619f}, {57.1429f,-4.7619f}, {52.381f,-14.2857f}, {47.6191f,-19.0476f} }; static const Fl_Glut_StrokeStrip ch44st[] = { {8,ch44st0} }; static const Fl_Glut_StrokeChar ch44 = {104.762f,1,ch44st}; /* char: 0x2d */ static const Fl_Glut_StrokeVertex ch45st0[] = { {9.5238f,42.8571f}, {95.2381f,42.8571f} }; static const Fl_Glut_StrokeStrip ch45st[] = { {2,ch45st0} }; static const Fl_Glut_StrokeChar ch45 = {104.762f,1,ch45st}; /* char: 0x2e */ static const Fl_Glut_StrokeVertex ch46st0[] = { {52.381f,9.5238f}, {47.6191f,4.7619f}, {52.381f,0.0f}, {57.1429f,4.7619f}, {52.381f,9.5238f} }; static const Fl_Glut_StrokeStrip ch46st[] = { {5,ch46st0} }; static const Fl_Glut_StrokeChar ch46 = {104.762f,1,ch46st}; /* char: 0x2f */ static const Fl_Glut_StrokeVertex ch47st0[] = { {19.0476f,-14.2857f}, {85.7143f,100.0f} }; static const Fl_Glut_StrokeStrip ch47st[] = { {2,ch47st0} }; static const Fl_Glut_StrokeChar ch47 = {104.762f,1,ch47st}; /* char: 0x30 */ static const Fl_Glut_StrokeVertex ch48st0[] = { {47.619f,100.0f}, {33.3333f,95.2381f}, {23.8095f,80.9524f}, {19.0476f,57.1429f}, {19.0476f,42.8571f}, {23.8095f,19.0476f}, {33.3333f,4.7619f}, {47.619f,0.0f}, {57.1428f,0.0f}, {71.4286f,4.7619f}, {80.9524f,19.0476f}, {85.7143f,42.8571f}, {85.7143f,57.1429f}, {80.9524f,80.9524f}, {71.4286f,95.2381f}, {57.1428f,100.0f}, {47.619f,100.0f} }; static const Fl_Glut_StrokeStrip ch48st[] = { {17,ch48st0} }; static const Fl_Glut_StrokeChar ch48 = {104.762f,1,ch48st}; /* char: 0x31 */ static const Fl_Glut_StrokeVertex ch49st0[] = { {40.4762f,80.9524f}, {50.0f,85.7143f}, {64.2857f,100.0f}, {64.2857f,0.0f} }; static const Fl_Glut_StrokeStrip ch49st[] = { {4,ch49st0} }; static const Fl_Glut_StrokeChar ch49 = {104.762f,1,ch49st}; /* char: 0x32 */ static const Fl_Glut_StrokeVertex ch50st0[] = { {23.8095f,76.1905f}, {23.8095f,80.9524f}, {28.5714f,90.4762f}, {33.3333f,95.2381f}, {42.8571f,100.0f}, {61.9047f,100.0f}, {71.4286f,95.2381f}, {76.1905f,90.4762f}, {80.9524f,80.9524f}, {80.9524f,71.4286f}, {76.1905f,61.9048f}, {66.6666f,47.619f}, {19.0476f,0.0f}, {85.7143f,0.0f} }; static const Fl_Glut_StrokeStrip ch50st[] = { {14,ch50st0} }; static const Fl_Glut_StrokeChar ch50 = {104.762f,1,ch50st}; /* char: 0x33 */ static const Fl_Glut_StrokeVertex ch51st0[] = { {28.5714f,100.0f}, {80.9524f,100.0f}, {52.3809f,61.9048f}, {66.6666f,61.9048f}, {76.1905f,57.1429f}, {80.9524f,52.381f}, {85.7143f,38.0952f}, {85.7143f,28.5714f}, {80.9524f,14.2857f}, {71.4286f,4.7619f}, {57.1428f,0.0f}, {42.8571f,0.0f}, {28.5714f,4.7619f}, {23.8095f,9.5238f}, {19.0476f,19.0476f} }; static const Fl_Glut_StrokeStrip ch51st[] = { {15,ch51st0} }; static const Fl_Glut_StrokeChar ch51 = {104.762f,1,ch51st}; /* char: 0x34 */ static const Fl_Glut_StrokeVertex ch52st0[] = { {64.2857f,100.0f}, {16.6667f,33.3333f}, {88.0952f,33.3333f} }; static const Fl_Glut_StrokeVertex ch52st1[] = { {64.2857f,100.0f}, {64.2857f,0.0f} }; static const Fl_Glut_StrokeStrip ch52st[] = { {3,ch52st0}, {2,ch52st1} }; static const Fl_Glut_StrokeChar ch52 = {104.762f,2,ch52st}; /* char: 0x35 */ static const Fl_Glut_StrokeVertex ch53st0[] = { {76.1905f,100.0f}, {28.5714f,100.0f}, {23.8095f,57.1429f}, {28.5714f,61.9048f}, {42.8571f,66.6667f}, {57.1428f,66.6667f}, {71.4286f,61.9048f}, {80.9524f,52.381f}, {85.7143f,38.0952f}, {85.7143f,28.5714f}, {80.9524f,14.2857f}, {71.4286f,4.7619f}, {57.1428f,0.0f}, {42.8571f,0.0f}, {28.5714f,4.7619f}, {23.8095f,9.5238f}, {19.0476f,19.0476f} }; static const Fl_Glut_StrokeStrip ch53st[] = { {17,ch53st0} }; static const Fl_Glut_StrokeChar ch53 = {104.762f,1,ch53st}; /* char: 0x36 */ static const Fl_Glut_StrokeVertex ch54st0[] = { {78.5714f,85.7143f}, {73.8096f,95.2381f}, {59.5238f,100.0f}, {50.0f,100.0f}, {35.7143f,95.2381f}, {26.1905f,80.9524f}, {21.4286f,57.1429f}, {21.4286f,33.3333f}, {26.1905f,14.2857f}, {35.7143f,4.7619f}, {50.0f,0.0f}, {54.7619f,0.0f}, {69.0476f,4.7619f}, {78.5714f,14.2857f}, {83.3334f,28.5714f}, {83.3334f,33.3333f}, {78.5714f,47.619f}, {69.0476f,57.1429f}, {54.7619f,61.9048f}, {50.0f,61.9048f}, {35.7143f,57.1429f}, {26.1905f,47.619f}, {21.4286f,33.3333f} }; static const Fl_Glut_StrokeStrip ch54st[] = { {23,ch54st0} }; static const Fl_Glut_StrokeChar ch54 = {104.762f,1,ch54st}; /* char: 0x37 */ static const Fl_Glut_StrokeVertex ch55st0[] = { {85.7143f,100.0f}, {38.0952f,0.0f} }; static const Fl_Glut_StrokeVertex ch55st1[] = { {19.0476f,100.0f}, {85.7143f,100.0f} }; static const Fl_Glut_StrokeStrip ch55st[] = { {2,ch55st0}, {2,ch55st1} }; static const Fl_Glut_StrokeChar ch55 = {104.762f,2,ch55st}; /* char: 0x38 */ static const Fl_Glut_StrokeVertex ch56st0[] = { {42.8571f,100.0f}, {28.5714f,95.2381f}, {23.8095f,85.7143f}, {23.8095f,76.1905f}, {28.5714f,66.6667f}, {38.0952f,61.9048f}, {57.1428f,57.1429f}, {71.4286f,52.381f}, {80.9524f,42.8571f}, {85.7143f,33.3333f}, {85.7143f,19.0476f}, {80.9524f,9.5238f}, {76.1905f,4.7619f}, {61.9047f,0.0f}, {42.8571f,0.0f}, {28.5714f,4.7619f}, {23.8095f,9.5238f}, {19.0476f,19.0476f}, {19.0476f,33.3333f}, {23.8095f,42.8571f}, {33.3333f,52.381f}, {47.619f,57.1429f}, {66.6666f,61.9048f}, {76.1905f,66.6667f}, {80.9524f,76.1905f}, {80.9524f,85.7143f}, {76.1905f,95.2381f}, {61.9047f,100.0f}, {42.8571f,100.0f} }; static const Fl_Glut_StrokeStrip ch56st[] = { {29,ch56st0} }; static const Fl_Glut_StrokeChar ch56 = {104.762f,1,ch56st}; /* char: 0x39 */ static const Fl_Glut_StrokeVertex ch57st0[] = { {83.3334f,66.6667f}, {78.5714f,52.381f}, {69.0476f,42.8571f}, {54.7619f,38.0952f}, {50.0f,38.0952f}, {35.7143f,42.8571f}, {26.1905f,52.381f}, {21.4286f,66.6667f}, {21.4286f,71.4286f}, {26.1905f,85.7143f}, {35.7143f,95.2381f}, {50.0f,100.0f}, {54.7619f,100.0f}, {69.0476f,95.2381f}, {78.5714f,85.7143f}, {83.3334f,66.6667f}, {83.3334f,42.8571f}, {78.5714f,19.0476f}, {69.0476f,4.7619f}, {54.7619f,0.0f}, {45.2381f,0.0f}, {30.9524f,4.7619f}, {26.1905f,14.2857f} }; static const Fl_Glut_StrokeStrip ch57st[] = { {23,ch57st0} }; static const Fl_Glut_StrokeChar ch57 = {104.762f,1,ch57st}; /* char: 0x3a */ static const Fl_Glut_StrokeVertex ch58st0[] = { {52.381f,66.6667f}, {47.6191f,61.9048f}, {52.381f,57.1429f}, {57.1429f,61.9048f}, {52.381f,66.6667f} }; static const Fl_Glut_StrokeVertex ch58st1[] = { {52.381f,9.5238f}, {47.6191f,4.7619f}, {52.381f,0.0f}, {57.1429f,4.7619f}, {52.381f,9.5238f} }; static const Fl_Glut_StrokeStrip ch58st[] = { {5,ch58st0}, {5,ch58st1} }; static const Fl_Glut_StrokeChar ch58 = {104.762f,2,ch58st}; /* char: 0x3b */ static const Fl_Glut_StrokeVertex ch59st0[] = { {52.381f,66.6667f}, {47.6191f,61.9048f}, {52.381f,57.1429f}, {57.1429f,61.9048f}, {52.381f,66.6667f} }; static const Fl_Glut_StrokeVertex ch59st1[] = { {57.1429f,4.7619f}, {52.381f,0.0f}, {47.6191f,4.7619f}, {52.381f,9.5238f}, {57.1429f,4.7619f}, {57.1429f,-4.7619f}, {52.381f,-14.2857f}, {47.6191f,-19.0476f} }; static const Fl_Glut_StrokeStrip ch59st[] = { {5,ch59st0}, {8,ch59st1} }; static const Fl_Glut_StrokeChar ch59 = {104.762f,2,ch59st}; /* char: 0x3c */ static const Fl_Glut_StrokeVertex ch60st0[] = { {90.4762f,85.7143f}, {14.2857f,42.8571f}, {90.4762f,0.0f} }; static const Fl_Glut_StrokeStrip ch60st[] = { {3,ch60st0} }; static const Fl_Glut_StrokeChar ch60 = {104.762f,1,ch60st}; /* char: 0x3d */ static const Fl_Glut_StrokeVertex ch61st0[] = { {9.5238f,57.1429f}, {95.2381f,57.1429f} }; static const Fl_Glut_StrokeVertex ch61st1[] = { {9.5238f,28.5714f}, {95.2381f,28.5714f} }; static const Fl_Glut_StrokeStrip ch61st[] = { {2,ch61st0}, {2,ch61st1} }; static const Fl_Glut_StrokeChar ch61 = {104.762f,2,ch61st}; /* char: 0x3e */ static const Fl_Glut_StrokeVertex ch62st0[] = { {14.2857f,85.7143f}, {90.4762f,42.8571f}, {14.2857f,0.0f} }; static const Fl_Glut_StrokeStrip ch62st[] = { {3,ch62st0} }; static const Fl_Glut_StrokeChar ch62 = {104.762f,1,ch62st}; /* char: 0x3f */ static const Fl_Glut_StrokeVertex ch63st0[] = { {23.8095f,76.1905f}, {23.8095f,80.9524f}, {28.5714f,90.4762f}, {33.3333f,95.2381f}, {42.8571f,100.0f}, {61.9047f,100.0f}, {71.4285f,95.2381f}, {76.1905f,90.4762f}, {80.9524f,80.9524f}, {80.9524f,71.4286f}, {76.1905f,61.9048f}, {71.4285f,57.1429f}, {52.3809f,47.619f}, {52.3809f,33.3333f} }; static const Fl_Glut_StrokeVertex ch63st1[] = { {52.3809f,9.5238f}, {47.619f,4.7619f}, {52.3809f,0.0f}, {57.1428f,4.7619f}, {52.3809f,9.5238f} }; static const Fl_Glut_StrokeStrip ch63st[] = { {14,ch63st0}, {5,ch63st1} }; static const Fl_Glut_StrokeChar ch63 = {104.762f,2,ch63st}; /* char: 0x40 */ static const Fl_Glut_StrokeVertex ch64st0[] = { {64.2857f,52.381f}, {54.7619f,57.1429f}, {45.2381f,57.1429f}, {40.4762f,47.619f}, {40.4762f,42.8571f}, {45.2381f,33.3333f}, {54.7619f,33.3333f}, {64.2857f,38.0952f} }; static const Fl_Glut_StrokeVertex ch64st1[] = { {64.2857f,57.1429f}, {64.2857f,38.0952f}, {69.0476f,33.3333f}, {78.5714f,33.3333f}, {83.3334f,42.8571f}, {83.3334f,47.619f}, {78.5714f,61.9048f}, {69.0476f,71.4286f}, {54.7619f,76.1905f}, {50.0f,76.1905f}, {35.7143f,71.4286f}, {26.1905f,61.9048f}, {21.4286f,47.619f}, {21.4286f,42.8571f}, {26.1905f,28.5714f}, {35.7143f,19.0476f}, {50.0f,14.2857f}, {54.7619f,14.2857f}, {69.0476f,19.0476f} }; static const Fl_Glut_StrokeStrip ch64st[] = { {8,ch64st0}, {19,ch64st1} }; static const Fl_Glut_StrokeChar ch64 = {104.762f,2,ch64st}; /* char: 0x41 */ static const Fl_Glut_StrokeVertex ch65st0[] = { {52.3809f,100.0f}, {14.2857f,0.0f} }; static const Fl_Glut_StrokeVertex ch65st1[] = { {52.3809f,100.0f}, {90.4762f,0.0f} }; static const Fl_Glut_StrokeVertex ch65st2[] = { {28.5714f,33.3333f}, {76.1905f,33.3333f} }; static const Fl_Glut_StrokeStrip ch65st[] = { {2,ch65st0}, {2,ch65st1}, {2,ch65st2} }; static const Fl_Glut_StrokeChar ch65 = {104.762f,3,ch65st}; /* char: 0x42 */ static const Fl_Glut_StrokeVertex ch66st0[] = { {19.0476f,100.0f}, {19.0476f,0.0f} }; static const Fl_Glut_StrokeVertex ch66st1[] = { {19.0476f,100.0f}, {61.9047f,100.0f}, {76.1905f,95.2381f}, {80.9524f,90.4762f}, {85.7143f,80.9524f}, {85.7143f,71.4286f}, {80.9524f,61.9048f}, {76.1905f,57.1429f}, {61.9047f,52.381f} }; static const Fl_Glut_StrokeVertex ch66st2[] = { {19.0476f,52.381f}, {61.9047f,52.381f}, {76.1905f,47.619f}, {80.9524f,42.8571f}, {85.7143f,33.3333f}, {85.7143f,19.0476f}, {80.9524f,9.5238f}, {76.1905f,4.7619f}, {61.9047f,0.0f}, {19.0476f,0.0f} }; static const Fl_Glut_StrokeStrip ch66st[] = { {2,ch66st0}, {9,ch66st1}, {10,ch66st2} }; static const Fl_Glut_StrokeChar ch66 = {104.762f,3,ch66st}; /* char: 0x43 */ static const Fl_Glut_StrokeVertex ch67st0[] = { {88.0952f,76.1905f}, {83.3334f,85.7143f}, {73.8096f,95.2381f}, {64.2857f,100.0f}, {45.2381f,100.0f}, {35.7143f,95.2381f}, {26.1905f,85.7143f}, {21.4286f,76.1905f}, {16.6667f,61.9048f}, {16.6667f,38.0952f}, {21.4286f,23.8095f}, {26.1905f,14.2857f}, {35.7143f,4.7619f}, {45.2381f,0.0f}, {64.2857f,0.0f}, {73.8096f,4.7619f}, {83.3334f,14.2857f}, {88.0952f,23.8095f} }; static const Fl_Glut_StrokeStrip ch67st[] = { {18,ch67st0} }; static const Fl_Glut_StrokeChar ch67 = {104.762f,1,ch67st}; /* char: 0x44 */ static const Fl_Glut_StrokeVertex ch68st0[] = { {19.0476f,100.0f}, {19.0476f,0.0f} }; static const Fl_Glut_StrokeVertex ch68st1[] = { {19.0476f,100.0f}, {52.3809f,100.0f}, {66.6666f,95.2381f}, {76.1905f,85.7143f}, {80.9524f,76.1905f}, {85.7143f,61.9048f}, {85.7143f,38.0952f}, {80.9524f,23.8095f}, {76.1905f,14.2857f}, {66.6666f,4.7619f}, {52.3809f,0.0f}, {19.0476f,0.0f} }; static const Fl_Glut_StrokeStrip ch68st[] = { {2,ch68st0}, {12,ch68st1} }; static const Fl_Glut_StrokeChar ch68 = {104.762f,2,ch68st}; /* char: 0x45 */ static const Fl_Glut_StrokeVertex ch69st0[] = { {21.4286f,100.0f}, {21.4286f,0.0f} }; static const Fl_Glut_StrokeVertex ch69st1[] = { {21.4286f,100.0f}, {83.3334f,100.0f} }; static const Fl_Glut_StrokeVertex ch69st2[] = { {21.4286f,52.381f}, {59.5238f,52.381f} }; static const Fl_Glut_StrokeVertex ch69st3[] = { {21.4286f,0.0f}, {83.3334f,0.0f} }; static const Fl_Glut_StrokeStrip ch69st[] = { {2,ch69st0}, {2,ch69st1}, {2,ch69st2}, {2,ch69st3} }; static const Fl_Glut_StrokeChar ch69 = {104.762f,4,ch69st}; /* char: 0x46 */ static const Fl_Glut_StrokeVertex ch70st0[] = { {21.4286f,100.0f}, {21.4286f,0.0f} }; static const Fl_Glut_StrokeVertex ch70st1[] = { {21.4286f,100.0f}, {83.3334f,100.0f} }; static const Fl_Glut_StrokeVertex ch70st2[] = { {21.4286f,52.381f}, {59.5238f,52.381f} }; static const Fl_Glut_StrokeStrip ch70st[] = { {2,ch70st0}, {2,ch70st1}, {2,ch70st2} }; static const Fl_Glut_StrokeChar ch70 = {104.762f,3,ch70st}; /* char: 0x47 */ static const Fl_Glut_StrokeVertex ch71st0[] = { {88.0952f,76.1905f}, {83.3334f,85.7143f}, {73.8096f,95.2381f}, {64.2857f,100.0f}, {45.2381f,100.0f}, {35.7143f,95.2381f}, {26.1905f,85.7143f}, {21.4286f,76.1905f}, {16.6667f,61.9048f}, {16.6667f,38.0952f}, {21.4286f,23.8095f}, {26.1905f,14.2857f}, {35.7143f,4.7619f}, {45.2381f,0.0f}, {64.2857f,0.0f}, {73.8096f,4.7619f}, {83.3334f,14.2857f}, {88.0952f,23.8095f}, {88.0952f,38.0952f} }; static const Fl_Glut_StrokeVertex ch71st1[] = { {64.2857f,38.0952f}, {88.0952f,38.0952f} }; static const Fl_Glut_StrokeStrip ch71st[] = { {19,ch71st0}, {2,ch71st1} }; static const Fl_Glut_StrokeChar ch71 = {104.762f,2,ch71st}; /* char: 0x48 */ static const Fl_Glut_StrokeVertex ch72st0[] = { {19.0476f,100.0f}, {19.0476f,0.0f} }; static const Fl_Glut_StrokeVertex ch72st1[] = { {85.7143f,100.0f}, {85.7143f,0.0f} }; static const Fl_Glut_StrokeVertex ch72st2[] = { {19.0476f,52.381f}, {85.7143f,52.381f} }; static const Fl_Glut_StrokeStrip ch72st[] = { {2,ch72st0}, {2,ch72st1}, {2,ch72st2} }; static const Fl_Glut_StrokeChar ch72 = {104.762f,3,ch72st}; /* char: 0x49 */ static const Fl_Glut_StrokeVertex ch73st0[] = { {52.381f,100.0f}, {52.381f,0.0f} }; static const Fl_Glut_StrokeStrip ch73st[] = { {2,ch73st0} }; static const Fl_Glut_StrokeChar ch73 = {104.762f,1,ch73st}; /* char: 0x4a */ static const Fl_Glut_StrokeVertex ch74st0[] = { {76.1905f,100.0f}, {76.1905f,23.8095f}, {71.4286f,9.5238f}, {66.6667f,4.7619f}, {57.1429f,0.0f}, {47.6191f,0.0f}, {38.0953f,4.7619f}, {33.3334f,9.5238f}, {28.5715f,23.8095f}, {28.5715f,33.3333f} }; static const Fl_Glut_StrokeStrip ch74st[] = { {10,ch74st0} }; static const Fl_Glut_StrokeChar ch74 = {104.762f,1,ch74st}; /* char: 0x4b */ static const Fl_Glut_StrokeVertex ch75st0[] = { {19.0476f,100.0f}, {19.0476f,0.0f} }; static const Fl_Glut_StrokeVertex ch75st1[] = { {85.7143f,100.0f}, {19.0476f,33.3333f} }; static const Fl_Glut_StrokeVertex ch75st2[] = { {42.8571f,57.1429f}, {85.7143f,0.0f} }; static const Fl_Glut_StrokeStrip ch75st[] = { {2,ch75st0}, {2,ch75st1}, {2,ch75st2} }; static const Fl_Glut_StrokeChar ch75 = {104.762f,3,ch75st}; /* char: 0x4c */ static const Fl_Glut_StrokeVertex ch76st0[] = { {23.8095f,100.0f}, {23.8095f,0.0f} }; static const Fl_Glut_StrokeVertex ch76st1[] = { {23.8095f,0.0f}, {80.9524f,0.0f} }; static const Fl_Glut_StrokeStrip ch76st[] = { {2,ch76st0}, {2,ch76st1} }; static const Fl_Glut_StrokeChar ch76 = {104.762f,2,ch76st}; /* char: 0x4d */ static const Fl_Glut_StrokeVertex ch77st0[] = { {14.2857f,100.0f}, {14.2857f,0.0f} }; static const Fl_Glut_StrokeVertex ch77st1[] = { {14.2857f,100.0f}, {52.3809f,0.0f} }; static const Fl_Glut_StrokeVertex ch77st2[] = { {90.4762f,100.0f}, {52.3809f,0.0f} }; static const Fl_Glut_StrokeVertex ch77st3[] = { {90.4762f,100.0f}, {90.4762f,0.0f} }; static const Fl_Glut_StrokeStrip ch77st[] = { {2,ch77st0}, {2,ch77st1}, {2,ch77st2}, {2,ch77st3} }; static const Fl_Glut_StrokeChar ch77 = {104.762f,4,ch77st}; /* char: 0x4e */ static const Fl_Glut_StrokeVertex ch78st0[] = { {19.0476f,100.0f}, {19.0476f,0.0f} }; static const Fl_Glut_StrokeVertex ch78st1[] = { {19.0476f,100.0f}, {85.7143f,0.0f} }; static const Fl_Glut_StrokeVertex ch78st2[] = { {85.7143f,100.0f}, {85.7143f,0.0f} }; static const Fl_Glut_StrokeStrip ch78st[] = { {2,ch78st0}, {2,ch78st1}, {2,ch78st2} }; static const Fl_Glut_StrokeChar ch78 = {104.762f,3,ch78st}; /* char: 0x4f */ static const Fl_Glut_StrokeVertex ch79st0[] = { {42.8571f,100.0f}, {33.3333f,95.2381f}, {23.8095f,85.7143f}, {19.0476f,76.1905f}, {14.2857f,61.9048f}, {14.2857f,38.0952f}, {19.0476f,23.8095f}, {23.8095f,14.2857f}, {33.3333f,4.7619f}, {42.8571f,0.0f}, {61.9047f,0.0f}, {71.4286f,4.7619f}, {80.9524f,14.2857f}, {85.7143f,23.8095f}, {90.4762f,38.0952f}, {90.4762f,61.9048f}, {85.7143f,76.1905f}, {80.9524f,85.7143f}, {71.4286f,95.2381f}, {61.9047f,100.0f}, {42.8571f,100.0f} }; static const Fl_Glut_StrokeStrip ch79st[] = { {21,ch79st0} }; static const Fl_Glut_StrokeChar ch79 = {104.762f,1,ch79st}; /* char: 0x50 */ static const Fl_Glut_StrokeVertex ch80st0[] = { {19.0476f,100.0f}, {19.0476f,0.0f} }; static const Fl_Glut_StrokeVertex ch80st1[] = { {19.0476f,100.0f}, {61.9047f,100.0f}, {76.1905f,95.2381f}, {80.9524f,90.4762f}, {85.7143f,80.9524f}, {85.7143f,66.6667f}, {80.9524f,57.1429f}, {76.1905f,52.381f}, {61.9047f,47.619f}, {19.0476f,47.619f} }; static const Fl_Glut_StrokeStrip ch80st[] = { {2,ch80st0}, {10,ch80st1} }; static const Fl_Glut_StrokeChar ch80 = {104.762f,2,ch80st}; /* char: 0x51 */ static const Fl_Glut_StrokeVertex ch81st0[] = { {42.8571f,100.0f}, {33.3333f,95.2381f}, {23.8095f,85.7143f}, {19.0476f,76.1905f}, {14.2857f,61.9048f}, {14.2857f,38.0952f}, {19.0476f,23.8095f}, {23.8095f,14.2857f}, {33.3333f,4.7619f}, {42.8571f,0.0f}, {61.9047f,0.0f}, {71.4286f,4.7619f}, {80.9524f,14.2857f}, {85.7143f,23.8095f}, {90.4762f,38.0952f}, {90.4762f,61.9048f}, {85.7143f,76.1905f}, {80.9524f,85.7143f}, {71.4286f,95.2381f}, {61.9047f,100.0f}, {42.8571f,100.0f} }; static const Fl_Glut_StrokeVertex ch81st1[] = { {57.1428f,19.0476f}, {85.7143f,-9.5238f} }; static const Fl_Glut_StrokeStrip ch81st[] = { {21,ch81st0}, {2,ch81st1} }; static const Fl_Glut_StrokeChar ch81 = {104.762f,2,ch81st}; /* char: 0x52 */ static const Fl_Glut_StrokeVertex ch82st0[] = { {19.0476f,100.0f}, {19.0476f,0.0f} }; static const Fl_Glut_StrokeVertex ch82st1[] = { {19.0476f,100.0f}, {61.9047f,100.0f}, {76.1905f,95.2381f}, {80.9524f,90.4762f}, {85.7143f,80.9524f}, {85.7143f,71.4286f}, {80.9524f,61.9048f}, {76.1905f,57.1429f}, {61.9047f,52.381f}, {19.0476f,52.381f} }; static const Fl_Glut_StrokeVertex ch82st2[] = { {52.3809f,52.381f}, {85.7143f,0.0f} }; static const Fl_Glut_StrokeStrip ch82st[] = { {2,ch82st0}, {10,ch82st1}, {2,ch82st2} }; static const Fl_Glut_StrokeChar ch82 = {104.762f,3,ch82st}; /* char: 0x53 */ static const Fl_Glut_StrokeVertex ch83st0[] = { {85.7143f,85.7143f}, {76.1905f,95.2381f}, {61.9047f,100.0f}, {42.8571f,100.0f}, {28.5714f,95.2381f}, {19.0476f,85.7143f}, {19.0476f,76.1905f}, {23.8095f,66.6667f}, {28.5714f,61.9048f}, {38.0952f,57.1429f}, {66.6666f,47.619f}, {76.1905f,42.8571f}, {80.9524f,38.0952f}, {85.7143f,28.5714f}, {85.7143f,14.2857f}, {76.1905f,4.7619f}, {61.9047f,0.0f}, {42.8571f,0.0f}, {28.5714f,4.7619f}, {19.0476f,14.2857f} }; static const Fl_Glut_StrokeStrip ch83st[] = { {20,ch83st0} }; static const Fl_Glut_StrokeChar ch83 = {104.762f,1,ch83st}; /* char: 0x54 */ static const Fl_Glut_StrokeVertex ch84st0[] = { {52.3809f,100.0f}, {52.3809f,0.0f} }; static const Fl_Glut_StrokeVertex ch84st1[] = { {19.0476f,100.0f}, {85.7143f,100.0f} }; static const Fl_Glut_StrokeStrip ch84st[] = { {2,ch84st0}, {2,ch84st1} }; static const Fl_Glut_StrokeChar ch84 = {104.762f,2,ch84st}; /* char: 0x55 */ static const Fl_Glut_StrokeVertex ch85st0[] = { {19.0476f,100.0f}, {19.0476f,28.5714f}, {23.8095f,14.2857f}, {33.3333f,4.7619f}, {47.619f,0.0f}, {57.1428f,0.0f}, {71.4286f,4.7619f}, {80.9524f,14.2857f}, {85.7143f,28.5714f}, {85.7143f,100.0f} }; static const Fl_Glut_StrokeStrip ch85st[] = { {10,ch85st0} }; static const Fl_Glut_StrokeChar ch85 = {104.762f,1,ch85st}; /* char: 0x56 */ static const Fl_Glut_StrokeVertex ch86st0[] = { {14.2857f,100.0f}, {52.3809f,0.0f} }; static const Fl_Glut_StrokeVertex ch86st1[] = { {90.4762f,100.0f}, {52.3809f,0.0f} }; static const Fl_Glut_StrokeStrip ch86st[] = { {2,ch86st0}, {2,ch86st1} }; static const Fl_Glut_StrokeChar ch86 = {104.762f,2,ch86st}; /* char: 0x57 */ static const Fl_Glut_StrokeVertex ch87st0[] = { {4.7619f,100.0f}, {28.5714f,0.0f} }; static const Fl_Glut_StrokeVertex ch87st1[] = { {52.3809f,100.0f}, {28.5714f,0.0f} }; static const Fl_Glut_StrokeVertex ch87st2[] = { {52.3809f,100.0f}, {76.1905f,0.0f} }; static const Fl_Glut_StrokeVertex ch87st3[] = { {100.0f,100.0f}, {76.1905f,0.0f} }; static const Fl_Glut_StrokeStrip ch87st[] = { {2,ch87st0}, {2,ch87st1}, {2,ch87st2}, {2,ch87st3} }; static const Fl_Glut_StrokeChar ch87 = {104.762f,4,ch87st}; /* char: 0x58 */ static const Fl_Glut_StrokeVertex ch88st0[] = { {19.0476f,100.0f}, {85.7143f,0.0f} }; static const Fl_Glut_StrokeVertex ch88st1[] = { {85.7143f,100.0f}, {19.0476f,0.0f} }; static const Fl_Glut_StrokeStrip ch88st[] = { {2,ch88st0}, {2,ch88st1} }; static const Fl_Glut_StrokeChar ch88 = {104.762f,2,ch88st}; /* char: 0x59 */ static const Fl_Glut_StrokeVertex ch89st0[] = { {14.2857f,100.0f}, {52.3809f,52.381f}, {52.3809f,0.0f} }; static const Fl_Glut_StrokeVertex ch89st1[] = { {90.4762f,100.0f}, {52.3809f,52.381f} }; static const Fl_Glut_StrokeStrip ch89st[] = { {3,ch89st0}, {2,ch89st1} }; static const Fl_Glut_StrokeChar ch89 = {104.762f,2,ch89st}; /* char: 0x5a */ static const Fl_Glut_StrokeVertex ch90st0[] = { {85.7143f,100.0f}, {19.0476f,0.0f} }; static const Fl_Glut_StrokeVertex ch90st1[] = { {19.0476f,100.0f}, {85.7143f,100.0f} }; static const Fl_Glut_StrokeVertex ch90st2[] = { {19.0476f,0.0f}, {85.7143f,0.0f} }; static const Fl_Glut_StrokeStrip ch90st[] = { {2,ch90st0}, {2,ch90st1}, {2,ch90st2} }; static const Fl_Glut_StrokeChar ch90 = {104.762f,3,ch90st}; /* char: 0x5b */ static const Fl_Glut_StrokeVertex ch91st0[] = { {35.7143f,119.048f}, {35.7143f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch91st1[] = { {40.4762f,119.048f}, {40.4762f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch91st2[] = { {35.7143f,119.048f}, {69.0476f,119.048f} }; static const Fl_Glut_StrokeVertex ch91st3[] = { {35.7143f,-33.3333f}, {69.0476f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch91st[] = { {2,ch91st0}, {2,ch91st1}, {2,ch91st2}, {2,ch91st3} }; static const Fl_Glut_StrokeChar ch91 = {104.762f,4,ch91st}; /* char: 0x5c */ static const Fl_Glut_StrokeVertex ch92st0[] = { {19.0476f,100.0f}, {85.7143f,-14.2857f} }; static const Fl_Glut_StrokeStrip ch92st[] = { {2,ch92st0} }; static const Fl_Glut_StrokeChar ch92 = {104.762f,1,ch92st}; /* char: 0x5d */ static const Fl_Glut_StrokeVertex ch93st0[] = { {64.2857f,119.048f}, {64.2857f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch93st1[] = { {69.0476f,119.048f}, {69.0476f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch93st2[] = { {35.7143f,119.048f}, {69.0476f,119.048f} }; static const Fl_Glut_StrokeVertex ch93st3[] = { {35.7143f,-33.3333f}, {69.0476f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch93st[] = { {2,ch93st0}, {2,ch93st1}, {2,ch93st2}, {2,ch93st3} }; static const Fl_Glut_StrokeChar ch93 = {104.762f,4,ch93st}; /* char: 0x5e */ static const Fl_Glut_StrokeVertex ch94st0[] = { {52.3809f,109.524f}, {14.2857f,42.8571f} }; static const Fl_Glut_StrokeVertex ch94st1[] = { {52.3809f,109.524f}, {90.4762f,42.8571f} }; static const Fl_Glut_StrokeStrip ch94st[] = { {2,ch94st0}, {2,ch94st1} }; static const Fl_Glut_StrokeChar ch94 = {104.762f,2,ch94st}; /* char: 0x5f */ static const Fl_Glut_StrokeVertex ch95st0[] = { {0,-33.3333f}, {104.762f,-33.3333f}, {104.762f,-28.5714f}, {0,-28.5714f}, {0,-33.3333f} }; static const Fl_Glut_StrokeStrip ch95st[] = { {5,ch95st0} }; static const Fl_Glut_StrokeChar ch95 = {104.762f,1,ch95st}; /* char: 0x60 */ static const Fl_Glut_StrokeVertex ch96st0[] = { {42.8572f,100.0f}, {66.6667f,71.4286f} }; static const Fl_Glut_StrokeVertex ch96st1[] = { {42.8572f,100.0f}, {38.0953f,95.2381f}, {66.6667f,71.4286f} }; static const Fl_Glut_StrokeStrip ch96st[] = { {2,ch96st0}, {3,ch96st1} }; static const Fl_Glut_StrokeChar ch96 = {104.762f,2,ch96st}; /* char: 0x61 */ static const Fl_Glut_StrokeVertex ch97st0[] = { {80.9524f,66.6667f}, {80.9524f,0.0f} }; static const Fl_Glut_StrokeVertex ch97st1[] = { {80.9524f,52.381f}, {71.4285f,61.9048f}, {61.9047f,66.6667f}, {47.619f,66.6667f}, {38.0952f,61.9048f}, {28.5714f,52.381f}, {23.8095f,38.0952f}, {23.8095f,28.5714f}, {28.5714f,14.2857f}, {38.0952f,4.7619f}, {47.619f,0.0f}, {61.9047f,0.0f}, {71.4285f,4.7619f}, {80.9524f,14.2857f} }; static const Fl_Glut_StrokeStrip ch97st[] = { {2,ch97st0}, {14,ch97st1} }; static const Fl_Glut_StrokeChar ch97 = {104.762f,2,ch97st}; /* char: 0x62 */ static const Fl_Glut_StrokeVertex ch98st0[] = { {23.8095f,100.0f}, {23.8095f,0.0f} }; static const Fl_Glut_StrokeVertex ch98st1[] = { {23.8095f,52.381f}, {33.3333f,61.9048f}, {42.8571f,66.6667f}, {57.1428f,66.6667f}, {66.6666f,61.9048f}, {76.1905f,52.381f}, {80.9524f,38.0952f}, {80.9524f,28.5714f}, {76.1905f,14.2857f}, {66.6666f,4.7619f}, {57.1428f,0.0f}, {42.8571f,0.0f}, {33.3333f,4.7619f}, {23.8095f,14.2857f} }; static const Fl_Glut_StrokeStrip ch98st[] = { {2,ch98st0}, {14,ch98st1} }; static const Fl_Glut_StrokeChar ch98 = {104.762f,2,ch98st}; /* char: 0x63 */ static const Fl_Glut_StrokeVertex ch99st0[] = { {80.9524f,52.381f}, {71.4285f,61.9048f}, {61.9047f,66.6667f}, {47.619f,66.6667f}, {38.0952f,61.9048f}, {28.5714f,52.381f}, {23.8095f,38.0952f}, {23.8095f,28.5714f}, {28.5714f,14.2857f}, {38.0952f,4.7619f}, {47.619f,0.0f}, {61.9047f,0.0f}, {71.4285f,4.7619f}, {80.9524f,14.2857f} }; static const Fl_Glut_StrokeStrip ch99st[] = { {14,ch99st0} }; static const Fl_Glut_StrokeChar ch99 = {104.762f,1,ch99st}; /* char: 0x64 */ static const Fl_Glut_StrokeVertex ch100st0[] = { {80.9524f,100.0f}, {80.9524f,0.0f} }; static const Fl_Glut_StrokeVertex ch100st1[] = { {80.9524f,52.381f}, {71.4285f,61.9048f}, {61.9047f,66.6667f}, {47.619f,66.6667f}, {38.0952f,61.9048f}, {28.5714f,52.381f}, {23.8095f,38.0952f}, {23.8095f,28.5714f}, {28.5714f,14.2857f}, {38.0952f,4.7619f}, {47.619f,0.0f}, {61.9047f,0.0f}, {71.4285f,4.7619f}, {80.9524f,14.2857f} }; static const Fl_Glut_StrokeStrip ch100st[] = { {2,ch100st0}, {14,ch100st1} }; static const Fl_Glut_StrokeChar ch100 = {104.762f,2,ch100st}; /* char: 0x65 */ static const Fl_Glut_StrokeVertex ch101st0[] = { {23.8095f,38.0952f}, {80.9524f,38.0952f}, {80.9524f,47.619f}, {76.1905f,57.1429f}, {71.4285f,61.9048f}, {61.9047f,66.6667f}, {47.619f,66.6667f}, {38.0952f,61.9048f}, {28.5714f,52.381f}, {23.8095f,38.0952f}, {23.8095f,28.5714f}, {28.5714f,14.2857f}, {38.0952f,4.7619f}, {47.619f,0.0f}, {61.9047f,0.0f}, {71.4285f,4.7619f}, {80.9524f,14.2857f} }; static const Fl_Glut_StrokeStrip ch101st[] = { {17,ch101st0} }; static const Fl_Glut_StrokeChar ch101 = {104.762f,1,ch101st}; /* char: 0x66 */ static const Fl_Glut_StrokeVertex ch102st0[] = { {71.4286f,100.0f}, {61.9048f,100.0f}, {52.381f,95.2381f}, {47.6191f,80.9524f}, {47.6191f,0.0f} }; static const Fl_Glut_StrokeVertex ch102st1[] = { {33.3334f,66.6667f}, {66.6667f,66.6667f} }; static const Fl_Glut_StrokeStrip ch102st[] = { {5,ch102st0}, {2,ch102st1} }; static const Fl_Glut_StrokeChar ch102 = {104.762f,2,ch102st}; /* char: 0x67 */ static const Fl_Glut_StrokeVertex ch103st0[] = { {80.9524f,66.6667f}, {80.9524f,-9.5238f}, {76.1905f,-23.8095f}, {71.4285f,-28.5714f}, {61.9047f,-33.3333f}, {47.619f,-33.3333f}, {38.0952f,-28.5714f} }; static const Fl_Glut_StrokeVertex ch103st1[] = { {80.9524f,52.381f}, {71.4285f,61.9048f}, {61.9047f,66.6667f}, {47.619f,66.6667f}, {38.0952f,61.9048f}, {28.5714f,52.381f}, {23.8095f,38.0952f}, {23.8095f,28.5714f}, {28.5714f,14.2857f}, {38.0952f,4.7619f}, {47.619f,0.0f}, {61.9047f,0.0f}, {71.4285f,4.7619f}, {80.9524f,14.2857f} }; static const Fl_Glut_StrokeStrip ch103st[] = { {7,ch103st0}, {14,ch103st1} }; static const Fl_Glut_StrokeChar ch103 = {104.762f,2,ch103st}; /* char: 0x68 */ static const Fl_Glut_StrokeVertex ch104st0[] = { {26.1905f,100.0f}, {26.1905f,0.0f} }; static const Fl_Glut_StrokeVertex ch104st1[] = { {26.1905f,47.619f}, {40.4762f,61.9048f}, {50.0f,66.6667f}, {64.2857f,66.6667f}, {73.8095f,61.9048f}, {78.5715f,47.619f}, {78.5715f,0.0f} }; static const Fl_Glut_StrokeStrip ch104st[] = { {2,ch104st0}, {7,ch104st1} }; static const Fl_Glut_StrokeChar ch104 = {104.762f,2,ch104st}; /* char: 0x69 */ static const Fl_Glut_StrokeVertex ch105st0[] = { {47.6191f,100.0f}, {52.381f,95.2381f}, {57.1429f,100.0f}, {52.381f,104.762f}, {47.6191f,100.0f} }; static const Fl_Glut_StrokeVertex ch105st1[] = { {52.381f,66.6667f}, {52.381f,0.0f} }; static const Fl_Glut_StrokeStrip ch105st[] = { {5,ch105st0}, {2,ch105st1} }; static const Fl_Glut_StrokeChar ch105 = {104.762f,2,ch105st}; /* char: 0x6a */ static const Fl_Glut_StrokeVertex ch106st0[] = { {57.1429f,100.0f}, {61.9048f,95.2381f}, {66.6667f,100.0f}, {61.9048f,104.762f}, {57.1429f,100.0f} }; static const Fl_Glut_StrokeVertex ch106st1[] = { {61.9048f,66.6667f}, {61.9048f,-14.2857f}, {57.1429f,-28.5714f}, {47.6191f,-33.3333f}, {38.0953f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch106st[] = { {5,ch106st0}, {5,ch106st1} }; static const Fl_Glut_StrokeChar ch106 = {104.762f,2,ch106st}; /* char: 0x6b */ static const Fl_Glut_StrokeVertex ch107st0[] = { {26.1905f,100.0f}, {26.1905f,0.0f} }; static const Fl_Glut_StrokeVertex ch107st1[] = { {73.8095f,66.6667f}, {26.1905f,19.0476f} }; static const Fl_Glut_StrokeVertex ch107st2[] = { {45.2381f,38.0952f}, {78.5715f,0.0f} }; static const Fl_Glut_StrokeStrip ch107st[] = { {2,ch107st0}, {2,ch107st1}, {2,ch107st2} }; static const Fl_Glut_StrokeChar ch107 = {104.762f,3,ch107st}; /* char: 0x6c */ static const Fl_Glut_StrokeVertex ch108st0[] = { {52.381f,100.0f}, {52.381f,0.0f} }; static const Fl_Glut_StrokeStrip ch108st[] = { {2,ch108st0} }; static const Fl_Glut_StrokeChar ch108 = {104.762f,1,ch108st}; /* char: 0x6d */ static const Fl_Glut_StrokeVertex ch109st0[] = { {0,66.6667f}, {0,0.0f} }; static const Fl_Glut_StrokeVertex ch109st1[] = { {0,47.619f}, {14.2857f,61.9048f}, {23.8095f,66.6667f}, {38.0952f,66.6667f}, {47.619f,61.9048f}, {52.381f,47.619f}, {52.381f,0.0f} }; static const Fl_Glut_StrokeVertex ch109st2[] = { {52.381f,47.619f}, {66.6667f,61.9048f}, {76.1905f,66.6667f}, {90.4762f,66.6667f}, {100.0f,61.9048f}, {104.762f,47.619f}, {104.762f,0.0f} }; static const Fl_Glut_StrokeStrip ch109st[] = { {2,ch109st0}, {7,ch109st1}, {7,ch109st2} }; static const Fl_Glut_StrokeChar ch109 = {104.762f,3,ch109st}; /* char: 0x6e */ static const Fl_Glut_StrokeVertex ch110st0[] = { {26.1905f,66.6667f}, {26.1905f,0.0f} }; static const Fl_Glut_StrokeVertex ch110st1[] = { {26.1905f,47.619f}, {40.4762f,61.9048f}, {50.0f,66.6667f}, {64.2857f,66.6667f}, {73.8095f,61.9048f}, {78.5715f,47.619f}, {78.5715f,0.0f} }; static const Fl_Glut_StrokeStrip ch110st[] = { {2,ch110st0}, {7,ch110st1} }; static const Fl_Glut_StrokeChar ch110 = {104.762f,2,ch110st}; /* char: 0x6f */ static const Fl_Glut_StrokeVertex ch111st0[] = { {45.2381f,66.6667f}, {35.7143f,61.9048f}, {26.1905f,52.381f}, {21.4286f,38.0952f}, {21.4286f,28.5714f}, {26.1905f,14.2857f}, {35.7143f,4.7619f}, {45.2381f,0.0f}, {59.5238f,0.0f}, {69.0476f,4.7619f}, {78.5714f,14.2857f}, {83.3334f,28.5714f}, {83.3334f,38.0952f}, {78.5714f,52.381f}, {69.0476f,61.9048f}, {59.5238f,66.6667f}, {45.2381f,66.6667f} }; static const Fl_Glut_StrokeStrip ch111st[] = { {17,ch111st0} }; static const Fl_Glut_StrokeChar ch111 = {104.762f,1,ch111st}; /* char: 0x70 */ static const Fl_Glut_StrokeVertex ch112st0[] = { {23.8095f,66.6667f}, {23.8095f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch112st1[] = { {23.8095f,52.381f}, {33.3333f,61.9048f}, {42.8571f,66.6667f}, {57.1428f,66.6667f}, {66.6666f,61.9048f}, {76.1905f,52.381f}, {80.9524f,38.0952f}, {80.9524f,28.5714f}, {76.1905f,14.2857f}, {66.6666f,4.7619f}, {57.1428f,0.0f}, {42.8571f,0.0f}, {33.3333f,4.7619f}, {23.8095f,14.2857f} }; static const Fl_Glut_StrokeStrip ch112st[] = { {2,ch112st0}, {14,ch112st1} }; static const Fl_Glut_StrokeChar ch112 = {104.762f,2,ch112st}; /* char: 0x71 */ static const Fl_Glut_StrokeVertex ch113st0[] = { {80.9524f,66.6667f}, {80.9524f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch113st1[] = { {80.9524f,52.381f}, {71.4285f,61.9048f}, {61.9047f,66.6667f}, {47.619f,66.6667f}, {38.0952f,61.9048f}, {28.5714f,52.381f}, {23.8095f,38.0952f}, {23.8095f,28.5714f}, {28.5714f,14.2857f}, {38.0952f,4.7619f}, {47.619f,0.0f}, {61.9047f,0.0f}, {71.4285f,4.7619f}, {80.9524f,14.2857f} }; static const Fl_Glut_StrokeStrip ch113st[] = { {2,ch113st0}, {14,ch113st1} }; static const Fl_Glut_StrokeChar ch113 = {104.762f,2,ch113st}; /* char: 0x72 */ static const Fl_Glut_StrokeVertex ch114st0[] = { {33.3334f,66.6667f}, {33.3334f,0.0f} }; static const Fl_Glut_StrokeVertex ch114st1[] = { {33.3334f,38.0952f}, {38.0953f,52.381f}, {47.6191f,61.9048f}, {57.1429f,66.6667f}, {71.4286f,66.6667f} }; static const Fl_Glut_StrokeStrip ch114st[] = { {2,ch114st0}, {5,ch114st1} }; static const Fl_Glut_StrokeChar ch114 = {104.762f,2,ch114st}; /* char: 0x73 */ static const Fl_Glut_StrokeVertex ch115st0[] = { {78.5715f,52.381f}, {73.8095f,61.9048f}, {59.5238f,66.6667f}, {45.2381f,66.6667f}, {30.9524f,61.9048f}, {26.1905f,52.381f}, {30.9524f,42.8571f}, {40.4762f,38.0952f}, {64.2857f,33.3333f}, {73.8095f,28.5714f}, {78.5715f,19.0476f}, {78.5715f,14.2857f}, {73.8095f,4.7619f}, {59.5238f,0.0f}, {45.2381f,0.0f}, {30.9524f,4.7619f}, {26.1905f,14.2857f} }; static const Fl_Glut_StrokeStrip ch115st[] = { {17,ch115st0} }; static const Fl_Glut_StrokeChar ch115 = {104.762f,1,ch115st}; /* char: 0x74 */ static const Fl_Glut_StrokeVertex ch116st0[] = { {47.6191f,100.0f}, {47.6191f,19.0476f}, {52.381f,4.7619f}, {61.9048f,0.0f}, {71.4286f,0.0f} }; static const Fl_Glut_StrokeVertex ch116st1[] = { {33.3334f,66.6667f}, {66.6667f,66.6667f} }; static const Fl_Glut_StrokeStrip ch116st[] = { {5,ch116st0}, {2,ch116st1} }; static const Fl_Glut_StrokeChar ch116 = {104.762f,2,ch116st}; /* char: 0x75 */ static const Fl_Glut_StrokeVertex ch117st0[] = { {26.1905f,66.6667f}, {26.1905f,19.0476f}, {30.9524f,4.7619f}, {40.4762f,0.0f}, {54.7619f,0.0f}, {64.2857f,4.7619f}, {78.5715f,19.0476f} }; static const Fl_Glut_StrokeVertex ch117st1[] = { {78.5715f,66.6667f}, {78.5715f,0.0f} }; static const Fl_Glut_StrokeStrip ch117st[] = { {7,ch117st0}, {2,ch117st1} }; static const Fl_Glut_StrokeChar ch117 = {104.762f,2,ch117st}; /* char: 0x76 */ static const Fl_Glut_StrokeVertex ch118st0[] = { {23.8095f,66.6667f}, {52.3809f,0.0f} }; static const Fl_Glut_StrokeVertex ch118st1[] = { {80.9524f,66.6667f}, {52.3809f,0.0f} }; static const Fl_Glut_StrokeStrip ch118st[] = { {2,ch118st0}, {2,ch118st1} }; static const Fl_Glut_StrokeChar ch118 = {104.762f,2,ch118st}; /* char: 0x77 */ static const Fl_Glut_StrokeVertex ch119st0[] = { {14.2857f,66.6667f}, {33.3333f,0.0f} }; static const Fl_Glut_StrokeVertex ch119st1[] = { {52.3809f,66.6667f}, {33.3333f,0.0f} }; static const Fl_Glut_StrokeVertex ch119st2[] = { {52.3809f,66.6667f}, {71.4286f,0.0f} }; static const Fl_Glut_StrokeVertex ch119st3[] = { {90.4762f,66.6667f}, {71.4286f,0.0f} }; static const Fl_Glut_StrokeStrip ch119st[] = { {2,ch119st0}, {2,ch119st1}, {2,ch119st2}, {2,ch119st3} }; static const Fl_Glut_StrokeChar ch119 = {104.762f,4,ch119st}; /* char: 0x78 */ static const Fl_Glut_StrokeVertex ch120st0[] = { {26.1905f,66.6667f}, {78.5715f,0.0f} }; static const Fl_Glut_StrokeVertex ch120st1[] = { {78.5715f,66.6667f}, {26.1905f,0.0f} }; static const Fl_Glut_StrokeStrip ch120st[] = { {2,ch120st0}, {2,ch120st1} }; static const Fl_Glut_StrokeChar ch120 = {104.762f,2,ch120st}; /* char: 0x79 */ static const Fl_Glut_StrokeVertex ch121st0[] = { {26.1905f,66.6667f}, {54.7619f,0.0f} }; static const Fl_Glut_StrokeVertex ch121st1[] = { {83.3334f,66.6667f}, {54.7619f,0.0f}, {45.2381f,-19.0476f}, {35.7143f,-28.5714f}, {26.1905f,-33.3333f}, {21.4286f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch121st[] = { {2,ch121st0}, {6,ch121st1} }; static const Fl_Glut_StrokeChar ch121 = {104.762f,2,ch121st}; /* char: 0x7a */ static const Fl_Glut_StrokeVertex ch122st0[] = { {78.5715f,66.6667f}, {26.1905f,0.0f} }; static const Fl_Glut_StrokeVertex ch122st1[] = { {26.1905f,66.6667f}, {78.5715f,66.6667f} }; static const Fl_Glut_StrokeVertex ch122st2[] = { {26.1905f,0.0f}, {78.5715f,0.0f} }; static const Fl_Glut_StrokeStrip ch122st[] = { {2,ch122st0}, {2,ch122st1}, {2,ch122st2} }; static const Fl_Glut_StrokeChar ch122 = {104.762f,3,ch122st}; /* char: 0x7b */ static const Fl_Glut_StrokeVertex ch123st0[] = { {64.2857f,119.048f}, {54.7619f,114.286f}, {50.0f,109.524f}, {45.2381f,100.0f}, {45.2381f,90.4762f}, {50.0f,80.9524f}, {54.7619f,76.1905f}, {59.5238f,66.6667f}, {59.5238f,57.1429f}, {50.0f,47.619f} }; static const Fl_Glut_StrokeVertex ch123st1[] = { {54.7619f,114.286f}, {50.0f,104.762f}, {50.0f,95.2381f}, {54.7619f,85.7143f}, {59.5238f,80.9524f}, {64.2857f,71.4286f}, {64.2857f,61.9048f}, {59.5238f,52.381f}, {40.4762f,42.8571f}, {59.5238f,33.3333f}, {64.2857f,23.8095f}, {64.2857f,14.2857f}, {59.5238f,4.7619f}, {54.7619f,0.0f}, {50.0f,-9.5238f}, {50.0f,-19.0476f}, {54.7619f,-28.5714f} }; static const Fl_Glut_StrokeVertex ch123st2[] = { {50.0f,38.0952f}, {59.5238f,28.5714f}, {59.5238f,19.0476f}, {54.7619f,9.5238f}, {50.0f,4.7619f}, {45.2381f,-4.7619f}, {45.2381f,-14.2857f}, {50.0f,-23.8095f}, {54.7619f,-28.5714f}, {64.2857f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch123st[] = { {10,ch123st0}, {17,ch123st1}, {10,ch123st2} }; static const Fl_Glut_StrokeChar ch123 = {104.762f,3,ch123st}; /* char: 0x7c */ static const Fl_Glut_StrokeVertex ch124st0[] = { {52.381f,119.048f}, {52.381f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch124st[] = { {2,ch124st0} }; static const Fl_Glut_StrokeChar ch124 = {104.762f,1,ch124st}; /* char: 0x7d */ static const Fl_Glut_StrokeVertex ch125st0[] = { {40.4762f,119.048f}, {50.0f,114.286f}, {54.7619f,109.524f}, {59.5238f,100.0f}, {59.5238f,90.4762f}, {54.7619f,80.9524f}, {50.0f,76.1905f}, {45.2381f,66.6667f}, {45.2381f,57.1429f}, {54.7619f,47.619f} }; static const Fl_Glut_StrokeVertex ch125st1[] = { {50.0f,114.286f}, {54.7619f,104.762f}, {54.7619f,95.2381f}, {50.0f,85.7143f}, {45.2381f,80.9524f}, {40.4762f,71.4286f}, {40.4762f,61.9048f}, {45.2381f,52.381f}, {64.2857f,42.8571f}, {45.2381f,33.3333f}, {40.4762f,23.8095f}, {40.4762f,14.2857f}, {45.2381f,4.7619f}, {50.0f,0.0f}, {54.7619f,-9.5238f}, {54.7619f,-19.0476f}, {50.0f,-28.5714f} }; static const Fl_Glut_StrokeVertex ch125st2[] = { {54.7619f,38.0952f}, {45.2381f,28.5714f}, {45.2381f,19.0476f}, {50.0f,9.5238f}, {54.7619f,4.7619f}, {59.5238f,-4.7619f}, {59.5238f,-14.2857f}, {54.7619f,-23.8095f}, {50.0f,-28.5714f}, {40.4762f,-33.3333f} }; static const Fl_Glut_StrokeStrip ch125st[] = { {10,ch125st0}, {17,ch125st1}, {10,ch125st2} }; static const Fl_Glut_StrokeChar ch125 = {104.762f,3,ch125st}; /* char: 0x7e */ static const Fl_Glut_StrokeVertex ch126st0[] = { {9.5238f,28.5714f}, {9.5238f,38.0952f}, {14.2857f,52.381f}, {23.8095f,57.1429f}, {33.3333f,57.1429f}, {42.8571f,52.381f}, {61.9048f,38.0952f}, {71.4286f,33.3333f}, {80.9524f,33.3333f}, {90.4762f,38.0952f}, {95.2381f,47.619f} }; static const Fl_Glut_StrokeVertex ch126st1[] = { {9.5238f,38.0952f}, {14.2857f,47.619f}, {23.8095f,52.381f}, {33.3333f,52.381f}, {42.8571f,47.619f}, {61.9048f,33.3333f}, {71.4286f,28.5714f}, {80.9524f,28.5714f}, {90.4762f,33.3333f}, {95.2381f,47.619f}, {95.2381f,57.1429f} }; static const Fl_Glut_StrokeStrip ch126st[] = { {11,ch126st0}, {11,ch126st1} }; static const Fl_Glut_StrokeChar ch126 = {104.762f,2,ch126st}; /* char: 0x7f */ static const Fl_Glut_StrokeVertex ch127st0[] = { {71.4286f,100.0f}, {33.3333f,-33.3333f} }; static const Fl_Glut_StrokeVertex ch127st1[] = { {47.619f,66.6667f}, {33.3333f,61.9048f}, {23.8095f,52.381f}, {19.0476f,38.0952f}, {19.0476f,23.8095f}, {23.8095f,14.2857f}, {33.3333f,4.7619f}, {47.619f,0.0f}, {57.1428f,0.0f}, {71.4286f,4.7619f}, {80.9524f,14.2857f}, {85.7143f,28.5714f}, {85.7143f,42.8571f}, {80.9524f,52.381f}, {71.4286f,61.9048f}, {57.1428f,66.6667f}, {47.619f,66.6667f} }; static const Fl_Glut_StrokeStrip ch127st[] = { {2,ch127st0}, {17,ch127st1} }; static const Fl_Glut_StrokeChar ch127 = {104.762f,2,ch127st}; static const Fl_Glut_StrokeChar *chars[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &ch32, &ch33, &ch34, &ch35, &ch36, &ch37, &ch38, &ch39, &ch40, &ch41, &ch42, &ch43, &ch44, &ch45, &ch46, &ch47, &ch48, &ch49, &ch50, &ch51, &ch52, &ch53, &ch54, &ch55, &ch56, &ch57, &ch58, &ch59, &ch60, &ch61, &ch62, &ch63, &ch64, &ch65, &ch66, &ch67, &ch68, &ch69, &ch70, &ch71, &ch72, &ch73, &ch74, &ch75, &ch76, &ch77, &ch78, &ch79, &ch80, &ch81, &ch82, &ch83, &ch84, &ch85, &ch86, &ch87, &ch88, &ch89, &ch90, &ch91, &ch92, &ch93, &ch94, &ch95, &ch96, &ch97, &ch98, &ch99, &ch100, &ch101, &ch102, &ch103, &ch104, &ch105, &ch106, &ch107, &ch108, &ch109, &ch110, &ch111, &ch112, &ch113, &ch114, &ch115, &ch116, &ch117, &ch118, &ch119, &ch120, &ch121, &ch122, &ch123, &ch124, &ch125, &ch126, &ch127 }; Fl_Glut_StrokeFont glutStrokeMonoRoman = {(char *)"MonoRoman",128,152.381f,chars}; fltk-1.4.3/src/Fl_Button.cxx0000644000175000017500000002303215004135251016014 0ustar albrechtalbrecht// // Button widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include Fl_Widget_Tracker *Fl_Button::key_release_tracker = 0; // There are a lot of subclasses, named Fl_*_Button. Some of // them are implemented by setting the type() value and testing it // here. This includes Fl_Radio_Button and Fl_Toggle_Button /** Sets the current value of the button. A non-zero value sets the button to 1 (ON), and zero sets it to 0 (OFF). \param[in] v button value. \see set(), clear() */ int Fl_Button::value(int v) { v = v ? 1 : 0; oldval = v; clear_changed(); if (value_ != v) { value_ = v; if (box()) redraw(); else redraw_label(); return 1; } else { return 0; } } /** Turns on this button and turns off all other radio buttons in the group (calling \c value(1) or \c set() does not do this). */ void Fl_Button::setonly() { // set this radio button on, turn others off value(1); Fl_Group* g = parent(); Fl_Widget*const* a = g->array(); for (int i = g->children(); i--;) { Fl_Widget* o = *a++; if (o != this && o->type()==FL_RADIO_BUTTON) ((Fl_Button*)o)->value(0); } } void Fl_Button::draw() { if (type() == FL_HIDDEN_BUTTON) return; Fl_Color col = value() ? selection_color() : color(); Fl_Boxtype bt = value() ? (down_box()?down_box():fl_down(box())) : box(); if (compact_ && parent()) { Fl_Widget *p = parent(); int px, py, pw = p->w(), ph = p->h(); if (p->as_window()) { px = 0; py = 0; } else { px = p->x(); py = p->y(); } fl_push_clip(x(), y(), w(), h()); draw_box(bt, px, py, pw, ph, col); fl_pop_clip(); const int hh = 5, ww = 5; Fl_Color divider_color = fl_gray_ramp(FL_NUM_GRAY/3); if (!active_r()) divider_color = fl_inactive(divider_color); if (x()+w() != px+pw) { fl_color(divider_color); fl_yxline(x()+w()-1, y()+hh, y()+h()-1-hh); } if (y()+h() != py+ph) { fl_color(divider_color); fl_xyline(x()+ww, y()+h()-1, x()+w()-1-ww); } } else { draw_box(bt, col); } draw_backdrop(); if (labeltype() == FL_NORMAL_LABEL && value()) { Fl_Color c = labelcolor(); labelcolor(fl_contrast(c, col)); draw_label(); labelcolor(c); } else draw_label(); if (Fl::focus() == this) draw_focus(); } int Fl_Button::handle(int event) { int newval; switch (event) { case FL_ENTER: /* FALLTHROUGH */ case FL_LEAVE: // if ((value_?selection_color():color())==FL_GRAY) redraw(); return 1; case FL_PUSH: if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); /* FALLTHROUGH */ case FL_DRAG: if (Fl::event_inside(this)) { if (type() == FL_RADIO_BUTTON) newval = 1; else newval = !oldval; } else { clear_changed(); newval = oldval; } if (newval != value_) { value_ = newval; set_changed(); if (box() && (fl_box(box())==box())) redraw(); else redraw_label(); if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED); } return 1; case FL_RELEASE: if (value_ == oldval) { if (when() & FL_WHEN_NOT_CHANGED) do_callback(FL_REASON_SELECTED); return 1; } if (type() == FL_RADIO_BUTTON) { setonly(); set_changed(); } else if (type() == FL_TOGGLE_BUTTON) { oldval = value_; set_changed(); } else { value(oldval); set_changed(); if (when() & FL_WHEN_CHANGED) { Fl_Widget_Tracker wp(this); do_callback(FL_REASON_CHANGED); if (wp.deleted()) return 1; } } if (when() & FL_WHEN_RELEASE) do_callback(FL_REASON_RELEASED); return 1; case FL_SHORTCUT: if (!(shortcut() ? Fl::test_shortcut(shortcut()) : test_shortcut())) return 0; if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); goto triggered_by_keyboard; case FL_FOCUS : case FL_UNFOCUS : if (Fl::visible_focus()) { if (box() == FL_NO_BOX) { // Widgets with the FL_NO_BOX boxtype need a parent to // redraw, since it is responsible for redrawing the // background... int X = x() > 0 ? x() - 1 : 0; int Y = y() > 0 ? y() - 1 : 0; if (window()) window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2); } else { if (box() && (fl_box(box())==box())) redraw(); else redraw_label(); } return 1; } else return 0; /* NOTREACHED */ case FL_KEYBOARD : if (Fl::focus() == this && Fl::event_key() == ' ' && !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) { triggered_by_keyboard: // from FL_SHORTCUT if (type() == FL_RADIO_BUTTON) { if (!value_) { setonly(); set_changed(); if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED); else if (when() & FL_WHEN_RELEASE) do_callback(FL_REASON_RELEASED); } else { if (when() & FL_WHEN_NOT_CHANGED) do_callback(FL_REASON_SELECTED); } } else if (type() == FL_TOGGLE_BUTTON) { value(!value()); set_changed(); if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED); else if (when() & FL_WHEN_RELEASE) do_callback(FL_REASON_RELEASED); } else { simulate_key_action(); if (when() & FL_WHEN_CHANGED) { set_changed(); Fl_Widget_Tracker wp(this); do_callback(FL_REASON_CHANGED); if (wp.deleted()) return 1; set_changed(); do_callback(FL_REASON_RELEASED); } else if (when() & FL_WHEN_RELEASE) { set_changed(); do_callback(FL_REASON_RELEASED); } } return 1; } /* FALLTHROUGH */ default: return 0; } } void Fl_Button::simulate_key_action() { if (key_release_tracker) { Fl::remove_timeout(key_release_timeout, key_release_tracker); key_release_timeout(key_release_tracker); } value(1); redraw(); key_release_tracker = new Fl_Widget_Tracker(this); Fl::add_timeout(0.15, key_release_timeout, key_release_tracker); } void Fl_Button::key_release_timeout(void *d) { Fl_Widget_Tracker *wt = (Fl_Widget_Tracker*)d; if (!wt) return; if (wt==key_release_tracker) key_release_tracker = 0L; Fl_Button *btn = (Fl_Button*)wt->widget(); if (btn) { btn->value(0); btn->redraw(); } delete wt; } /** The constructor creates the button using the given position, size, and label. The default box type is box(FL_UP_BOX). You can control how the button is drawn when ON by setting down_box(). The default is FL_NO_BOX (0) which will select an appropriate box type using the normal (OFF) box type by using fl_down(box()). Derived classes may handle this differently. A button may request callbacks with \p when() \p FL_WHEN_CHANGED, \p FL_WHEN_NOT_CHANGED, and \p FL_WHEN_RELEASE, triggering the callback reasons \p FL_REASON_CHANGED, \p FL_REASON_SELECTED, and \p FL_REASON_DESELECTED. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Button::Fl_Button(int X, int Y, int W, int H, const char *L) : Fl_Widget(X,Y,W,H,L), shortcut_(0), value_(0), oldval(0), down_box_(FL_NO_BOX), compact_(0) { box(FL_UP_BOX); set_flag(SHORTCUT_LABEL); } /** The constructor creates the button using the given position, size, and label. The Button type() is set to FL_RADIO_BUTTON. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Radio_Button::Fl_Radio_Button(int X,int Y,int W,int H,const char *L) : Fl_Button(X, Y, W, H, L) { type(FL_RADIO_BUTTON); } /** The constructor creates the button using the given position, size, and label. The Button type() is set to FL_TOGGLE_BUTTON. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_Toggle_Button::Fl_Toggle_Button(int X,int Y,int W,int H,const char *L) : Fl_Button(X,Y,W,H,L) { type(FL_TOGGLE_BUTTON); } /** Decide if buttons should be rendered in compact mode. \image html compact_buttons_gtk.png "compact button keypad using GTK+ Scheme" \image latex compact_buttons_gtk.png "compact button keypad using GTK+ Scheme" width=4cm \image html compact_buttons_gleam.png "compact buttons in Gleam" \image latex compact_buttons_gleam.png "compact buttons in Gleam" width=4cm In compact mode, the button's surrounding border is altered to visually signal that multiple buttons are functionally linked together. To ensure the correct rendering of buttons in compact mode, all buttons must be part of the same group, positioned close to each other, and aligned with the edges of the group. Any button outlines not in contact with the parent group's outline will be displayed as separators. \param[in] v switch compact mode on (1) or off (0) */ void Fl_Button::compact(uchar v) { compact_ = v; } fltk-1.4.3/src/Fl_Tree_Prefs.cxx0000644000175000017500000000756015004135251016607 0ustar albrechtalbrecht// ////////////////////// // Fl_Tree_Prefs.cxx ////////////////////// // // Fl_Tree -- This file is part of the Fl_Tree widget for FLTK // Copyright (C) 2009-2010 by Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_System_Driver.H" #include #include #include #include /** \cond DriverDev \addtogroup DriverDeveloper \{ */ // Draw non-OS specific Fl_Tree open/close icons // ┌───┐ ┌───┐ // │ + │ │ - │ // └───┘ └───┘ void Fl_System_Driver::tree_draw_expando_button(int x, int y, bool state, bool active) { fl_rectf(x, y, 11, 11, active ? FL_BACKGROUND2_COLOR : fl_inactive(FL_BACKGROUND2_COLOR)); // fill fl_rect(x, y, 11, 11, FL_INACTIVE_COLOR); // outline fl_color(active ? FL_FOREGROUND_COLOR : FL_INACTIVE_COLOR); fl_line(x + 3, y + 5, x + 7, y + 5); // horiz line if (state) fl_line(x + 5, y + 3, x + 5, y + 7); // vert line } int Fl_System_Driver::tree_connector_style() { return FL_TREE_CONNECTOR_DOTTED; } /** \} \endcond */ /// Sets the default icon to be used as the 'open' icon /// when items are add()ed to the tree. /// This overrides the built in default '[+]' icon. /// /// \param[in] val -- The new image, or zero to use the default [+] icon. /// void Fl_Tree_Prefs::openicon(Fl_Image *val) { _openimage = val ? val : 0; // Update deactivated version of icon.. if ( _opendeimage ) delete _opendeimage; if ( _openimage ) { _opendeimage = _openimage->copy(); _opendeimage->inactive(); } else { _opendeimage = 0; } } /// Sets the icon to be used as the 'close' icon. /// This overrides the built in default '[-]' icon. /// /// \param[in] val -- The new image, or zero to use the default [-] icon. /// void Fl_Tree_Prefs::closeicon(Fl_Image *val) { _closeimage = val ? val : 0; // Update deactivated version of icon.. if ( _closedeimage ) delete _closedeimage; if ( _closeimage ) { _closedeimage = _closeimage->copy(); _closedeimage->inactive(); } else { _closedeimage = 0; } } /// Fl_Tree_Prefs constructor Fl_Tree_Prefs::Fl_Tree_Prefs() { _labelfont = FL_HELVETICA; _labelsize = FL_NORMAL_SIZE; _marginleft = 6; _margintop = 3; _marginbottom = 20; _openchild_marginbottom = 0; _usericonmarginleft = 3; _labelmarginleft = 3; _widgetmarginleft = 3; _linespacing = 0; _labelfgcolor = FL_FOREGROUND_COLOR; _labelbgcolor = 0xffffffff; // we use this as 'transparent' _connectorcolor = FL_INACTIVE_COLOR; _connectorstyle = (Fl_Tree_Connector)Fl::system_driver()->tree_connector_style(); _openimage = 0; _closeimage = 0; _userimage = 0; _opendeimage = 0; _closedeimage = 0; _userdeimage = 0; _showcollapse = 1; _showroot = 1; _connectorwidth = 17; _sortorder = FL_TREE_SORT_NONE; _selectbox = FL_THIN_UP_BOX; _selectmode = FL_TREE_SELECT_SINGLE; _itemreselectmode = FL_TREE_SELECTABLE_ONCE; _itemdrawmode = FL_TREE_ITEM_DRAW_DEFAULT; _itemdrawcallback = 0; _itemdrawuserdata = 0; } /// Fl_Tree_Prefs destructor Fl_Tree_Prefs::~Fl_Tree_Prefs() { if ( _opendeimage ) delete _opendeimage; if ( _closedeimage ) delete _closedeimage; if ( _userdeimage ) delete _userdeimage; } fltk-1.4.3/src/Fl_win32.cxx0000644000175000017500000030042615004135251015510 0ustar albrechtalbrecht// // Windows-specific code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Note: this file contains platform specific code and will therefore // not be processed by doxygen (see Doxyfile.in). // This file contains Windows-specific code for FLTK which is always linked // in. Search other files for "_WIN32" or filenames ending in _win32.cxx // for other system-specific code. /* We require Windows 2000 features (e.g. VK definitions) */ # if !defined(WINVER) || (WINVER < 0x0500) # ifdef WINVER # undef WINVER # endif # define WINVER 0x0500 # endif # if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) # ifdef _WIN32_WINNT # undef _WIN32_WINNT # endif # define _WIN32_WINNT 0x0500 # endif // recent versions of MinGW warn: "Please include winsock2.h before windows.h" #if !defined(__CYGWIN__) # include #endif #include #include #include // Some versions of MinGW now require us to explicitly include winerror to get S_OK defined #include #include // for ceil() and round() void fl_free_fonts(void); void fl_release_dc(HWND, HDC); void fl_cleanup_dc_list(void); #include #include #include #include "Fl_Window_Driver.H" #include "Fl_Screen_Driver.H" #include "Fl_Timeout.h" #include "print_button.h" #include // for fl_graphics_driver #include "drivers/WinAPI/Fl_WinAPI_Window_Driver.H" #include "drivers/WinAPI/Fl_WinAPI_System_Driver.H" #include "drivers/WinAPI/Fl_WinAPI_Screen_Driver.H" #include "drivers/GDI/Fl_GDI_Graphics_Driver.H" #include #include #include #include #include #include #include #include #include "flstring.h" #include "drivers/GDI/Fl_Font.H" #include #include #include #include #include #ifdef __CYGWIN__ # include # include #endif #if !defined(NO_TRACK_MOUSE) # include // TrackMouseEvent #endif #if defined(__GNUC__) # include #endif // old versions of MinGW lack definition of GET_XBUTTON_WPARAM: #ifndef GET_XBUTTON_WPARAM #define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam)) #endif static bool is_dpi_aware = false; extern bool fl_clipboard_notify_empty(void); extern void fl_trigger_clipboard_notify(int source); extern HBRUSH fl_brush_action(int action); extern void fl_cleanup_pens(void); // MSVC 2010 can't find round() although is included above, // which is surprising because ceil() works fine. // We could (should?) probably add configure/CMake feature tests for // round() and ceil() rather than depending on MSVC version numbers. // AlbrechtS, 02/2010 - Note: we don't know about MSVC 2012 - 2015, see // https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros #if defined(_MSC_VER) && _MSC_VER <= 1600 #define round(A) int((A) + 0.5) #endif // _MSC_VER <= 1600 // Internal functions static void fl_clipboard_notify_target(HWND wnd); static void fl_clipboard_notify_untarget(HWND wnd); // Internal variables static HWND clipboard_wnd = 0; static HWND next_clipboard_wnd = 0; static bool initial_clipboard = true; // dynamic wsock dll handling api: #if defined(__CYGWIN__) && !defined(SOCKET) # define SOCKET int #endif /* Dynamic linking of imm32.dll This library is only needed for a hand full (four ATM) functions relating to international text rendering and locales. Dynamically loading reduces initial size and link dependencies. */ static HMODULE s_imm_module = 0; typedef BOOL(WINAPI *flTypeImmAssociateContextEx)(HWND, HIMC, DWORD); static flTypeImmAssociateContextEx flImmAssociateContextEx = 0; typedef HIMC(WINAPI *flTypeImmGetContext)(HWND); static flTypeImmGetContext flImmGetContext = 0; typedef BOOL(WINAPI *flTypeImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM); static flTypeImmSetCompositionWindow flImmSetCompositionWindow = 0; typedef BOOL(WINAPI *flTypeImmReleaseContext)(HWND, HIMC); static flTypeImmReleaseContext flImmReleaseContext = 0; static void get_imm_module() { s_imm_module = LoadLibrary("IMM32.DLL"); if (!s_imm_module) Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n" "Please check your input method manager library accessibility."); flImmAssociateContextEx = (flTypeImmAssociateContextEx)GetProcAddress(s_imm_module, "ImmAssociateContextEx"); flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext"); flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow"); flImmReleaseContext = (flTypeImmReleaseContext)GetProcAddress(s_imm_module, "ImmReleaseContext"); } // USE_TRACK_MOUSE - define NO_TRACK_MOUSE if you don't have // TrackMouseEvent()... // // Now (Dec. 2008) we can assume that current Cygwin/MinGW versions // support the TrackMouseEvent() function, but WinCE obviously doesn't // support it (STR 2095). Therefore, USE_TRACK_MOUSE is enabled by // default, but you can disable it by defining NO_TRACK_MOUSE. // // TrackMouseEvent is only used to support window leave notifications // under Windows. It can be used to get FL_LEAVE events, when the // mouse leaves the _main_ application window (FLTK detects subwindow // leave events by using normal move events). // // Implementation note: If the mouse cursor leaves one subwindow and // enters another window, then Windows sends a WM_MOUSEMOVE message to // the new window before it sends a WM_MOUSELEAVE message to the old // (just left) window. We save the current mouse window in a static variable, // and if we get a WM_MOUSELEAVE event for the current mouse window, this // means that the top level window has been left (otherwise we would have // got another WM_MOUSEMOVE message before). // #define NO_TRACK_MOUSE #if !defined(NO_TRACK_MOUSE) # define USE_TRACK_MOUSE #endif // NO_TRACK_MOUSE static Fl_Window *track_mouse_win = 0; // current TrackMouseEvent() window // USE_CAPTURE_MOUSE_WIN - this must be defined for TrackMouseEvent to work // correctly with subwindows - otherwise a single mouse click and release // (without a move) would generate phantom leave events. // This defines, if the current mouse window (maybe a subwindow) or the // main window should get mouse events after pushing (and holding) a mouse // button, i.e. when dragging the mouse. This is done by calling SetCapture // (see below). #ifdef USE_TRACK_MOUSE #define USE_CAPTURE_MOUSE_WIN #endif // USE_TRACK_MOUSE // // WM_SYNCPAINT is an "undocumented" message, which is finally defined in // VC++ 6.0. // #ifndef WM_SYNCPAINT # define WM_SYNCPAINT 0x0088 #endif #ifndef WM_MOUSELEAVE # define WM_MOUSELEAVE 0x02a3 #endif #ifndef WM_MOUSEWHEEL # define WM_MOUSEWHEEL 0x020a #endif #ifndef WHEEL_DELTA # define WHEEL_DELTA 120 // according to MSDN. #endif // This is only defined on Vista and upwards... #ifndef WM_MOUSEHWHEEL # define WM_MOUSEHWHEEL 0x020E #endif #ifndef SM_CXPADDEDBORDER # define SM_CXPADDEDBORDER (92) // STR #3061 #endif // https://msdn.microsoft.com/en-us/library/windows/desktop/dn312083(v=vs.85).aspx #ifndef WM_DPICHANGED # define WM_DPICHANGED 0x02E0 #endif // // WM_FLSELECT is the user-defined message that we get when one of // the sockets has pending data, etc. // #define WM_FLSELECT (WM_APP + 1) // WM_APP is used for hide-window //////////////////////////////////////////////////////////////// // interface to poll/select call: // fd's are only implemented for sockets. Microsoft Windows does not // have a unified IO system, so it doesn't support select() on files, // devices, or pipes... // // Microsoft provides the Berkeley select() call and an asynchronous // select function that sends a Windows message when the select condition // exists. However, we don't try to use the asynchronous WSAAsyncSelect() // any more for good reasons (see above). // // A.S. Dec 2009: We got reports that current winsock2.h files define // POLLIN, POLLOUT, and POLLERR with conflicting values WRT what we // used before (STR #2301). Therefore we must not use these values // for our internal purposes, but use FL_READ, FL_WRITE, and // FL_EXCEPT, as defined for use in Fl::add_fd(). // static int maxfd = 0; static fd_set fdsets[3]; extern IDropTarget *flIDropTarget; static int nfds = 0; static int fd_array_size = 0; static struct FD { int fd; short events; void (*cb)(FL_SOCKET, void *); // keep socket api opaque at this level to reduce multiplatform deps headaches void *arg; } *fd = 0; extern unsigned int fl_codepage; void Fl_WinAPI_System_Driver::add_fd(int n, int events, void (*cb)(FL_SOCKET, void *), void *v) { remove_fd(n, events); int i = nfds++; if (i >= fd_array_size) { fd_array_size = 2 * fd_array_size + 1; fd = (FD *)realloc(fd, fd_array_size * sizeof(FD)); } fd[i].fd = n; fd[i].events = (short)events; fd[i].cb = cb; fd[i].arg = v; if (events & FL_READ) FD_SET((unsigned)n, &fdsets[0]); if (events & FL_WRITE) FD_SET((unsigned)n, &fdsets[1]); if (events & FL_EXCEPT) FD_SET((unsigned)n, &fdsets[2]); if (n > maxfd) maxfd = n; } void Fl_WinAPI_System_Driver::add_fd(int fd, void (*cb)(FL_SOCKET, void *), void *v) { add_fd(fd, FL_READ, cb, v); } void Fl_WinAPI_System_Driver::remove_fd(int n, int events) { int i, j; for (i = j = 0; i < nfds; i++) { if (fd[i].fd == n) { short e = fd[i].events & ~events; if (!e) continue; // if no events left, delete this fd fd[i].events = e; } // move it down in the array if necessary: if (j < i) { fd[j] = fd[i]; } j++; } nfds = j; if (events & FL_READ) FD_CLR(unsigned(n), &fdsets[0]); if (events & FL_WRITE) FD_CLR(unsigned(n), &fdsets[1]); if (events & FL_EXCEPT) FD_CLR(unsigned(n), &fdsets[2]); } void Fl_WinAPI_System_Driver::remove_fd(int n) { remove_fd(n, -1); } // these pointers are set by the Fl::lock() function: static void nothing() {} void (*fl_lock_function)() = nothing; void (*fl_unlock_function)() = nothing; static void *thread_message_; void *Fl_WinAPI_System_Driver::thread_message() { void *r = thread_message_; thread_message_ = 0; return r; } extern int fl_send_system_handlers(void *e); MSG fl_msg; // A local helper function to flush any pending callback requests // from the awake ring-buffer static void process_awake_handler_requests(void) { Fl_Awake_Handler func; void *data; while (Fl::get_awake_handler_(func, data) == 0) { func(data); } } // This is never called with time_to_wait < 0.0. // It *should* return negative on error, 0 if nothing happens before // timeout, and >0 if any callbacks were done. This version // always returns 1. double Fl_WinAPI_System_Driver::wait(double time_to_wait) { time_to_wait = Fl_System_Driver::wait(time_to_wait); int have_message = 0; if (nfds) { // For Windows we need to poll for socket input FIRST, since // the event queue is not something we can select() on... timeval t; t.tv_sec = 0; t.tv_usec = 0; fd_set fdt[3]; memcpy(fdt, fdsets, sizeof fdt); // one shot faster fdt init if (select(maxfd + 1, &fdt[0], &fdt[1], &fdt[2], &t)) { // We got something - do the callback! for (int i = 0; i < nfds; i++) { SOCKET f = fd[i].fd; short revents = 0; if (FD_ISSET(f, &fdt[0])) revents |= FL_READ; if (FD_ISSET(f, &fdt[1])) revents |= FL_WRITE; if (FD_ISSET(f, &fdt[2])) revents |= FL_EXCEPT; if (fd[i].events & revents) fd[i].cb(f, fd[i].arg); } time_to_wait = 0.0; // just peek for any messages } else { // we need to check them periodically, so set a short timeout: if (time_to_wait > .001) time_to_wait = .001; } } if (Fl::idle || Fl::damage()) time_to_wait = 0.0; // if there are no more windows and this timer is set // to FOREVER, continue through or look up indefinitely if (!Fl::first_window() && time_to_wait == 1e20) time_to_wait = 0.0; fl_unlock_function(); time_to_wait = (time_to_wait > 10000 ? 10000 : time_to_wait); time_to_wait = Fl_Timeout::time_to_wait(time_to_wait); int t_msec = (int)(time_to_wait * 1000.0 + 0.5); MsgWaitForMultipleObjects(0, NULL, FALSE, t_msec, QS_ALLINPUT); fl_lock_function(); // Execute the message we got, and all other pending messages: // have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE); while ((have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE)) > 0) { if (fl_send_system_handlers(&fl_msg)) continue; // Let applications treat WM_QUIT identical to SIGTERM on *nix if (fl_msg.message == WM_QUIT) raise(SIGTERM); if (fl_msg.message == fl_wake_msg) { // Used for awaking wait() from another thread thread_message_ = (void *)fl_msg.wParam; process_awake_handler_requests(); } TranslateMessage(&fl_msg); DispatchMessageW(&fl_msg); } // The following conditional test: !Fl_System_Driver::awake_ring_empty() // equivalent to: // (Fl::awake_ring_head_ != Fl::awake_ring_tail_) // is a workaround / fix for STR #3143. This works, but a better solution // would be to understand why the PostThreadMessage() messages are not // seen by the main window if it is being dragged/ resized at the time. // If a worker thread posts an awake callback to the ring buffer // whilst the main window is unresponsive (if a drag or resize operation // is in progress) we may miss the PostThreadMessage(). So here, we check if // there is anything pending in the awake ring buffer and if so process // it. This is not strictly thread safe (for speed it compares the head // and tail indices without first locking the ring buffer) but is intended // only as a fall-back recovery mechanism if the awake processing stalls. // If the test erroneously returns true (may happen if we test the indices // whilst they are being modified) we will call process_awake_handler_requests() // unnecessarily, but this has no harmful consequences so is safe to do. // Note also that if we miss the PostThreadMessage(), then thread_message_ // will not be updated, so this is not a perfect solution, but it does // recover and process any pending awake callbacks. // Normally the ring buffer head and tail indices will match and this // comparison will do nothing. Addresses STR #3143 if (!Fl_System_Driver::awake_ring_empty()) { process_awake_handler_requests(); } Fl::flush(); // This should return 0 if only timer events were handled: return 1; } // just like Fl_WinAPI_System_Driver::wait(0.0) except no callbacks are done: int Fl_WinAPI_System_Driver::ready() { if (PeekMessage(&fl_msg, NULL, 0, 0, PM_NOREMOVE)) return 1; if (!nfds) return 0; timeval t; t.tv_sec = 0; t.tv_usec = 0; fd_set fdt[3]; memcpy(fdt, fdsets, sizeof fdt); return select(0, &fdt[0], &fdt[1], &fdt[2], &t); } static void delayed_create_print_window(void *) { Fl::remove_check(delayed_create_print_window); fl_create_print_window(); } void Fl_WinAPI_Screen_Driver::open_display_platform() { static char beenHereDoneThat = 0; if (beenHereDoneThat) return; beenHereDoneThat = 1; // test whether DpiAwareness has been set before via a manifest /*enum PROCESS_DPI_AWARENESS { // in shellscalingapi.h from Window 8.1 PROCESS_DPI_UNAWARE, PROCESS_SYSTEM_DPI_AWARE, PROCESS_PER_MONITOR_DPI_AWARE };*/ typedef HRESULT(WINAPI * GetProcessDpiAwareness_type)(HANDLE, int *); GetProcessDpiAwareness_type fl_GetProcessDpiAwareness = (GetProcessDpiAwareness_type)GetProcAddress(LoadLibrary("Shcore.DLL"), "GetProcessDpiAwareness"); int awareness; if (!fl_GetProcessDpiAwareness || fl_GetProcessDpiAwareness(NULL, &awareness) != S_OK) { awareness = 0; //corresponds to PROCESS_DPI_UNAWARE; } if (awareness == 2 /*PROCESS_PER_MONITOR_DPI_AWARE*/) is_dpi_aware = true; if (awareness == 0 /*PROCESS_DPI_UNAWARE*/) { // DpiAwareness has not been set via a manifest typedef void *fl_DPI_AWARENESS_CONTEXT; typedef BOOL(WINAPI * SetProcessDpiAwarenessContext_type)(fl_DPI_AWARENESS_CONTEXT); SetProcessDpiAwarenessContext_type fl_SetProcessDpiAwarenessContext = (SetProcessDpiAwarenessContext_type)GetProcAddress(LoadLibrary("User32.DLL"), "SetProcessDpiAwarenessContext"); if (fl_SetProcessDpiAwarenessContext) { const fl_DPI_AWARENESS_CONTEXT fl_DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = (fl_DPI_AWARENESS_CONTEXT)(-4); is_dpi_aware = fl_SetProcessDpiAwarenessContext(fl_DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); } if (!is_dpi_aware) { typedef HRESULT(WINAPI * SetProcessDpiAwareness_type)(int); SetProcessDpiAwareness_type fl_SetProcessDpiAwareness = (SetProcessDpiAwareness_type)GetProcAddress(LoadLibrary("Shcore.DLL"), "SetProcessDpiAwareness"); if (fl_SetProcessDpiAwareness) { const int fl_PROCESS_PER_MONITOR_DPI_AWARE = 2; if (fl_SetProcessDpiAwareness(fl_PROCESS_PER_MONITOR_DPI_AWARE) == S_OK) is_dpi_aware = true; } } } OleInitialize(0L); get_imm_module(); Fl::add_check(delayed_create_print_window); } void Fl_WinAPI_Screen_Driver::update_scaling_capability() { scaling_capability = SYSTEMWIDE_APP_SCALING; for (int ns = 1; ns < screen_count(); ns++) { if (scale(ns) != scale(0)) { scaling_capability = PER_SCREEN_APP_SCALING; break; } } } void Fl_WinAPI_Screen_Driver::desktop_scale_factor() { typedef HRESULT(WINAPI * GetDpiForMonitor_type)(HMONITOR, int, UINT *, UINT *); typedef HMONITOR(WINAPI * MonitorFromRect_type)(LPCRECT, DWORD); GetDpiForMonitor_type fl_GetDpiForMonitor = NULL; MonitorFromRect_type fl_MonitorFromRect = NULL; if (is_dpi_aware) { fl_GetDpiForMonitor = (GetDpiForMonitor_type)GetProcAddress(LoadLibrary("Shcore.DLL"), "GetDpiForMonitor"); if (fl_GetDpiForMonitor) fl_MonitorFromRect = (MonitorFromRect_type)GetProcAddress(LoadLibrary("User32.DLL"), "MonitorFromRect"); } for (int ns = 0; ns < screen_count(); ns++) { UINT dpiX, dpiY; HRESULT r = E_INVALIDARG; if (fl_GetDpiForMonitor && fl_MonitorFromRect) { HMONITOR hm = fl_MonitorFromRect(&screens[ns], MONITOR_DEFAULTTONEAREST); r = fl_GetDpiForMonitor(hm, 0, &dpiX, &dpiY); } if (r != S_OK) { dpiX = dpiY = 96; } dpi[ns][0] = float(dpiX); dpi[ns][1] = float(dpiY); scale(ns, dpiX / 96.f); // fprintf(LOG, "desktop_scale_factor ns=%d factor=%.2f dpi=%.1f\n", ns, scale(ns), dpi[ns][0]); } update_scaling_capability(); } class Fl_Win32_At_Exit { public: Fl_Win32_At_Exit() {} ~Fl_Win32_At_Exit() { fl_free_fonts(); // do some Windows cleanup fl_cleanup_pens(); OleUninitialize(); if (fl_graphics_driver) fl_brush_action(1); fl_cleanup_dc_list(); // This is actually too late in the cleanup process to remove the // clipboard notifications, but we have no earlier hook so we try // to work around it anyway. if (clipboard_wnd != NULL) fl_clipboard_notify_untarget(clipboard_wnd); #if USE_GDIPLUS Fl_GDIplus_Graphics_Driver::shutdown(); #endif } }; static Fl_Win32_At_Exit win32_at_exit; static char im_enabled = 1; void Fl_WinAPI_Screen_Driver::enable_im() { open_display(); Fl_X *i = Fl_X::first; while (i) { flImmAssociateContextEx((HWND)i->xid, 0, IACE_DEFAULT); i = i->next; } im_enabled = 1; } void Fl_WinAPI_Screen_Driver::disable_im() { open_display(); Fl_X *i = Fl_X::first; while (i) { flImmAssociateContextEx((HWND)i->xid, 0, 0); i = i->next; } im_enabled = 0; } void Fl_WinAPI_Screen_Driver::set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) { if (!win) return; Fl_Window* tw = win->top_window(); if (!tw->shown()) return; HIMC himc = flImmGetContext(fl_xid(tw)); if (himc) { COMPOSITIONFORM cfs; float s = Fl_Graphics_Driver::default_driver().scale(); cfs.dwStyle = CFS_POINT; cfs.ptCurrentPos.x = int(X * s); cfs.ptCurrentPos.y = int(Y * s) - int(tw->labelsize() * s); // Attempt to have temporary text entered by input method use scaled font. // Does good, but still not always effective. Fl_GDI_Font_Descriptor *desc = (Fl_GDI_Font_Descriptor*)Fl_Graphics_Driver::default_driver().font_descriptor(); if (desc) SelectObject((HDC)Fl_Graphics_Driver::default_driver().gc(), desc->fid); MapWindowPoints(fl_xid(win), fl_xid(tw), &cfs.ptCurrentPos, 1); flImmSetCompositionWindow(himc, &cfs); flImmReleaseContext(fl_xid(tw), himc); } } //////////////////////////////////////////////////////////////// int Fl_WinAPI_Screen_Driver::get_mouse_unscaled(int &mx, int &my) { POINT p; GetCursorPos(&p); mx = p.x; my = p.y; int screen = screen_num_unscaled(mx, my); return screen >= 0 ? screen : 0; } int Fl_WinAPI_Screen_Driver::get_mouse(int &x, int &y) { int n = get_mouse_unscaled(x, y); float s = scale(n); x = int(x / s); y = int(y / s); return n; } //////////////////////////////////////////////////////////////// // code used for selections: char *fl_selection_buffer[2]; int fl_selection_length[2]; int fl_selection_buffer_length[2]; char fl_i_own_selection[2]; UINT fl_get_lcid_codepage(LCID id) { char buf[8]; buf[GetLocaleInfo(id, LOCALE_IDEFAULTANSICODEPAGE, buf, 8)] = 0; return atol(buf); } // Convert \n -> \r\n class Lf2CrlfConvert { char *out; int outlen; public: Lf2CrlfConvert(const char *in, int inlen) { outlen = 0; const char *i; char *o; int lencount; // Predict size of \r\n conversion buffer for (i = in, lencount = inlen; lencount > 0; lencount--) { if (*i == '\r' && *(i + 1) == '\n' && lencount >= 2) { // leave \r\n untranslated i += 2; outlen += 2; lencount--; } else if (*i == '\n') { // \n by itself? leave room to insert \r i++; outlen += 2; } else { ++i; ++outlen; } } // Alloc conversion buffer + NULL out = new char[outlen + 1]; // Handle \n -> \r\n conversion for (i = in, o = out, lencount = inlen; lencount > 0; lencount--) { if (*i == '\r' && *(i + 1) == '\n' && lencount >= 2) { // leave \r\n untranslated *o++ = *i++; *o++ = *i++; lencount--; } else if (*i == '\n') { // \n by itself? insert \r *o++ = '\r'; *o++ = *i++; } else { *o++ = *i++; } } *o++ = 0; } ~Lf2CrlfConvert() { delete[] out; } int GetLength() const { return (outlen); } const char *GetValue() const { return (out); } }; void fl_update_clipboard(void) { Fl_Window *w1 = Fl::first_window(); if (!w1) return; HWND hwnd = fl_xid(w1); if (!OpenClipboard(hwnd)) return; EmptyClipboard(); int utf16_len = fl_utf8toUtf16(fl_selection_buffer[1], fl_selection_length[1], 0, 0); HGLOBAL hMem = GlobalAlloc(GHND, utf16_len * 2 + 2); // moveable and zero'ed mem alloc. LPVOID memLock = GlobalLock(hMem); fl_utf8toUtf16(fl_selection_buffer[1], fl_selection_length[1], (unsigned short *)memLock, utf16_len + 1); GlobalUnlock(hMem); SetClipboardData(CF_UNICODETEXT, hMem); CloseClipboard(); // In case Windows managed to lob of a WM_DESTROYCLIPBOARD during // the above. fl_i_own_selection[1] = 1; } // call this when you create a selection: void Fl_WinAPI_Screen_Driver::copy(const char *stuff, int len, int clipboard, const char *type) { if (!stuff || len < 0) return; if (clipboard >= 2) clipboard = 1; // Only on X11 do multiple clipboards make sense. // Convert \n -> \r\n (for old apps like Notepad, DOS) Lf2CrlfConvert buf(stuff, len); len = buf.GetLength(); stuff = buf.GetValue(); if (len + 1 > fl_selection_buffer_length[clipboard]) { delete[] fl_selection_buffer[clipboard]; fl_selection_buffer[clipboard] = new char[len + 100]; fl_selection_buffer_length[clipboard] = len + 100; } memcpy(fl_selection_buffer[clipboard], stuff, len); fl_selection_buffer[clipboard][len] = 0; // needed for direct paste fl_selection_length[clipboard] = len; fl_i_own_selection[clipboard] = 1; if (clipboard) fl_update_clipboard(); } // Call this when a "paste" operation happens: void Fl_WinAPI_Screen_Driver::paste(Fl_Widget &receiver, int clipboard, const char *type) { if (!clipboard || (fl_i_own_selection[clipboard] && strcmp(type, Fl::clipboard_plain_text) == 0)) { // We already have it, do it quickly without window server. // Notice that the text is clobbered if set_selection is // called in response to FL_PASTE! char *i = fl_selection_buffer[clipboard]; if (i == 0L) { Fl::e_text = 0; return; } char *clip_text = new char[fl_selection_length[clipboard] + 1]; char *o = clip_text; while (*i) { // Convert \r\n -> \n if (*i == '\r' && *(i + 1) == '\n') i++; else *o++ = *i++; } *o = 0; Fl::e_text = clip_text; Fl::e_length = (int)(o - Fl::e_text); Fl::e_clipboard_type = Fl::clipboard_plain_text; receiver.handle(FL_PASTE); // this may change Fl::e_text delete[] clip_text; Fl::e_text = 0; } else if (clipboard) { HANDLE h; if (!OpenClipboard(NULL)) return; if (strcmp(type, Fl::clipboard_plain_text) == 0) { // we want plain text from clipboard if ((h = GetClipboardData(CF_UNICODETEXT))) { // there's text in the clipboard wchar_t *memLock = (wchar_t *)GlobalLock(h); size_t utf16_len = wcslen(memLock); char *clip_text = new char[utf16_len * 4 + 1]; unsigned utf8_len = fl_utf8fromwc(clip_text, (unsigned)(utf16_len * 4), memLock, (unsigned)utf16_len); *(clip_text + utf8_len) = 0; GlobalUnlock(h); LPSTR a, b; a = b = clip_text; while (*a) { // strip the CRLF pairs ($%$#@^) if (*a == '\r' && a[1] == '\n') a++; else *b++ = *a++; } *b = 0; Fl::e_text = clip_text; Fl::e_length = (int)(b - Fl::e_text); Fl::e_clipboard_type = Fl::clipboard_plain_text; // indicates that the paste event is for plain UTF8 text receiver.handle(FL_PASTE); // send the FL_PASTE event to the widget. May change Fl::e_text delete[] clip_text; Fl::e_text = 0; } } else if (strcmp(type, Fl::clipboard_image) == 0) { // we want an image from clipboard uchar *rgb = NULL; Fl_RGB_Image *image = NULL; int width = 0, height = 0, depth = 0; if ((h = GetClipboardData(CF_DIB))) { // if there's a DIB in clipboard LPBITMAPINFO lpBI = (LPBITMAPINFO)GlobalLock(h); width = lpBI->bmiHeader.biWidth; // bitmap width & height height = lpBI->bmiHeader.biHeight; // is < 0 for top-down DIB if ((lpBI->bmiHeader.biBitCount == 24 || lpBI->bmiHeader.biBitCount == 32) && lpBI->bmiHeader.biCompression == BI_RGB && lpBI->bmiHeader.biClrUsed == 0) { // direct use of the DIB data if it's RGB or RGBA int linewidth; // row length depth = lpBI->bmiHeader.biBitCount / 8; // 3 or 4 if (depth == 3) linewidth = 4 * ((3 * width + 3) / 4); // row length: series of groups of 3 bytes, rounded to multiple of 4 bytes else linewidth = 4 * width; rgb = new uchar[width * abs(height) * depth]; // will hold the image data uchar *p = rgb, *r, rr, gg, bb; int step = (height > 0 ? -1 : +1); int from = (height > 0 ? height-1 : 0); int to = (height > 0 ? 0 : -height-1); for (int i = from; (height > 0 ? i>=to : i <=to); i += step) {// for each row, from last to first r = (uchar *)(lpBI->bmiColors) + i * linewidth; // beginning of pixel data for the ith row for (int j = 0; j < width; j++) { // for each pixel in a row bb = *r++; // BGR is in DIB gg = *r++; rr = *r++; *p++ = rr; // we want RGB *p++ = gg; *p++ = bb; if (depth == 4) *p++ = *r++; // copy alpha if present } } } else { // the system will decode a complex DIB void *pDIBBits = (void *)(lpBI->bmiColors + 256); if (lpBI->bmiHeader.biCompression == BI_BITFIELDS) pDIBBits = (void *)(lpBI->bmiColors + 3); else if (lpBI->bmiHeader.biClrUsed > 0) pDIBBits = (void *)(lpBI->bmiColors + lpBI->bmiHeader.biClrUsed); Fl_Image_Surface *surf = new Fl_Image_Surface(width, abs(height)); Fl_Surface_Device::push_current(surf); SetDIBitsToDevice((HDC)fl_graphics_driver->gc(), 0, 0, width, abs(height), 0, 0, 0, abs(height), pDIBBits, lpBI, DIB_RGB_COLORS); rgb = fl_read_image(NULL, 0, 0, width, abs(height)); depth = 3; Fl_Surface_Device::pop_current(); delete surf; } GlobalUnlock(h); } else if ((h = GetClipboardData(CF_ENHMETAFILE))) { // if there's an enhanced metafile in clipboard ENHMETAHEADER header; GetEnhMetaFileHeader((HENHMETAFILE)h, sizeof(header), &header); // get structure containing metafile dimensions width = (header.rclFrame.right - header.rclFrame.left + 1); // in .01 mm units height = (header.rclFrame.bottom - header.rclFrame.top + 1); HDC hdc = GetDC(NULL); // get unit correspondance between .01 mm and screen pixels int hmm = GetDeviceCaps(hdc, HORZSIZE); int hdots = GetDeviceCaps(hdc, HORZRES); ReleaseDC(NULL, hdc); float factor = (100.f * hmm) / hdots; float scaling = Fl::screen_driver()->scale(Fl_Window_Driver::driver(receiver.top_window())->screen_num()); if (!Fl_Window::current()) { Fl_GDI_Graphics_Driver *d = (Fl_GDI_Graphics_Driver*)&Fl_Graphics_Driver::default_driver(); d->scale(scaling);// may run early at app startup before Fl_Window::make_current() scales d } width = int(width / (scaling * factor)); // convert to screen pixel unit height = int(height / (scaling * factor)); RECT rect = {0, 0, width, height}; Fl_Image_Surface *surf = new Fl_Image_Surface(width, height, 1); Fl_Surface_Device::push_current(surf); fl_color(FL_WHITE); // draw white background fl_rectf(0, 0, width, height); rect.right = LONG(rect.right * scaling); // apply scaling to the metafile draw operation rect.bottom = LONG(rect.bottom * scaling); PlayEnhMetaFile((HDC)fl_graphics_driver->gc(), (HENHMETAFILE)h, &rect); // draw metafile to offscreen buffer image = surf->image(); Fl_Surface_Device::pop_current(); delete surf; } if (rgb || image) { if (!image) { image = new Fl_RGB_Image(rgb, width, abs(height), depth); // create new image from pixel data image->alloc_array = 1; } Fl::e_clipboard_data = image; Fl::e_clipboard_type = Fl::clipboard_image; // indicates that the paste event is for image data int done = receiver.handle(FL_PASTE); // send FL_PASTE event to widget Fl::e_clipboard_type = ""; if (done == 0) { // if widget did not handle the event, delete the image Fl::e_clipboard_data = NULL; delete image; } } } CloseClipboard(); } } int Fl_WinAPI_Screen_Driver::clipboard_contains(const char *type) { int retval = 0; if (!OpenClipboard(NULL)) return 0; if (strcmp(type, Fl::clipboard_plain_text) == 0 || type[0] == 0) { retval = IsClipboardFormatAvailable(CF_UNICODETEXT); } else if (strcmp(type, Fl::clipboard_image) == 0) { retval = IsClipboardFormatAvailable(CF_DIB) || IsClipboardFormatAvailable(CF_ENHMETAFILE); } CloseClipboard(); return retval; } static void fl_clipboard_notify_target(HWND wnd) { if (clipboard_wnd) return; // We get one fake WM_DRAWCLIPBOARD immediately, which we therefore // need to ignore. initial_clipboard = true; clipboard_wnd = wnd; next_clipboard_wnd = SetClipboardViewer(wnd); } static void fl_clipboard_notify_untarget(HWND wnd) { if (wnd != clipboard_wnd) return; // We might be called late in the cleanup where Windows has already // implicitly destroyed our clipboard window. At that point we need // to do some extra work to manually repair the clipboard chain. if (IsWindow(wnd)) ChangeClipboardChain(wnd, next_clipboard_wnd); else { HWND tmp, head; tmp = CreateWindow("STATIC", "Temporary FLTK Clipboard Window", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); if (tmp == NULL) return; head = SetClipboardViewer(tmp); if (head == NULL) ChangeClipboardChain(tmp, next_clipboard_wnd); else { SendMessage(head, WM_CHANGECBCHAIN, (WPARAM)wnd, (LPARAM)next_clipboard_wnd); ChangeClipboardChain(tmp, head); } DestroyWindow(tmp); } clipboard_wnd = next_clipboard_wnd = 0; } void fl_clipboard_notify_retarget(HWND wnd) { // The given window is getting destroyed. If it's part of the // clipboard chain then we need to unregister it and find a // replacement window. if (wnd != clipboard_wnd) return; fl_clipboard_notify_untarget(wnd); if (Fl::first_window()) fl_clipboard_notify_target(fl_xid(Fl::first_window())); } void Fl_WinAPI_Screen_Driver::clipboard_notify_change() { // untarget clipboard monitor if no handlers are registered if (clipboard_wnd != NULL && fl_clipboard_notify_empty()) { fl_clipboard_notify_untarget(clipboard_wnd); return; } // if there are clipboard notify handlers but no window targeted // target first window if available if (clipboard_wnd == NULL && Fl::first_window()) fl_clipboard_notify_target(fl_xid(Fl::first_window())); } //////////////////////////////////////////////////////////////// void fl_get_codepage() { HKL hkl = GetKeyboardLayout(0); TCHAR ld[8]; GetLocaleInfo(LOWORD(hkl), LOCALE_IDEFAULTANSICODEPAGE, ld, 6); DWORD ccp = atol(ld); fl_codepage = ccp; } HWND fl_capture; static int mouse_event(Fl_Window *window, int what, int button, WPARAM wParam, LPARAM lParam) { static int px, py, pmx, pmy; POINT pt; float scale = Fl::screen_driver()->scale(window->screen_num()); Fl::e_x = pt.x = (signed short)LOWORD(lParam); Fl::e_y = pt.y = (signed short)HIWORD(lParam); Fl::e_x = int(Fl::e_x / scale); Fl::e_y = int(Fl::e_y / scale); ClientToScreen(fl_xid(window), &pt); Fl::e_x_root = int(pt.x / scale); Fl::e_y_root = int(pt.y / scale); #ifdef USE_CAPTURE_MOUSE_WIN Fl_Window *mouse_window = window; // save "mouse window" #endif while (window->parent()) { Fl::e_x += window->x(); Fl::e_y += window->y(); window = window->window(); } ulong state = Fl::e_state & 0xff0000; // keep shift key states #if 0 // mouse event reports some shift flags, perhaps save them? if (wParam & MK_SHIFT) state |= FL_SHIFT; if (wParam & MK_CONTROL) state |= FL_CTRL; #endif if (wParam & MK_LBUTTON) state |= FL_BUTTON1; // left if (wParam & MK_MBUTTON) state |= FL_BUTTON2; // right if (wParam & MK_RBUTTON) state |= FL_BUTTON3; // middle if (wParam & MK_XBUTTON1) state |= FL_BUTTON4; // side button 1 (back) if (wParam & MK_XBUTTON2) state |= FL_BUTTON5; // side button 2 (forward) Fl::e_state = state; switch (what) { case 1: // double-click if (Fl::e_is_click) { Fl::e_clicks++; goto J1; } case 0: // single-click Fl::e_clicks = 0; J1: #ifdef USE_CAPTURE_MOUSE_WIN if (!fl_capture) SetCapture(fl_xid(mouse_window)); // use mouse window #else if (!fl_capture) SetCapture(fl_xid(window)); // use main window #endif Fl::e_keysym = FL_Button + button; Fl::e_is_click = 1; px = pmx = Fl::e_x_root; py = pmy = Fl::e_y_root; return Fl::handle(FL_PUSH, window); case 2: // release: if (!fl_capture) ReleaseCapture(); Fl::e_keysym = FL_Button + button; return Fl::handle(FL_RELEASE, window); case 3: // move: default: // avoid compiler warning // Windows produces extra events even if the mouse does not move, ignore em: if (Fl::e_x_root == pmx && Fl::e_y_root == pmy) return 1; pmx = Fl::e_x_root; pmy = Fl::e_y_root; if (abs(Fl::e_x_root - px) > 5 || abs(Fl::e_y_root - py) > 5) Fl::e_is_click = 0; return Fl::handle(FL_MOVE, window); } } // Convert a Windows VK_x to an FLTK (X) Keysym: // See also the inverse converter in Fl_get_key_win32.cxx // This table is in numeric order by VK: static const struct { unsigned short vk, fltk, extended; } vktab[] = { {VK_BACK, FL_BackSpace}, {VK_TAB, FL_Tab}, {VK_CLEAR, FL_KP+'5', 0xff0b/*XK_Clear*/}, {VK_RETURN, FL_Enter, FL_KP_Enter}, {VK_SHIFT, FL_Shift_L, FL_Shift_R}, {VK_CONTROL, FL_Control_L, FL_Control_R}, {VK_MENU, FL_Alt_L, FL_Alt_R}, {VK_PAUSE, FL_Pause}, {VK_CAPITAL, FL_Caps_Lock}, {VK_ESCAPE, FL_Escape}, {VK_SPACE, ' '}, {VK_PRIOR, FL_KP+'9', FL_Page_Up}, {VK_NEXT, FL_KP+'3', FL_Page_Down}, {VK_END, FL_KP+'1', FL_End}, {VK_HOME, FL_KP+'7', FL_Home}, {VK_LEFT, FL_KP+'4', FL_Left}, {VK_UP, FL_KP+'8', FL_Up}, {VK_RIGHT, FL_KP+'6', FL_Right}, {VK_DOWN, FL_KP+'2', FL_Down}, {VK_SNAPSHOT, FL_Print}, // does not work on NT {VK_INSERT, FL_KP+'0', FL_Insert}, {VK_DELETE, FL_KP+'.', FL_Delete}, {VK_LWIN, FL_Meta_L}, {VK_RWIN, FL_Meta_R}, {VK_APPS, FL_Menu}, {VK_SLEEP, FL_Sleep}, {VK_MULTIPLY, FL_KP+'*'}, {VK_ADD, FL_KP+'+'}, {VK_SUBTRACT, FL_KP+'-'}, {VK_DECIMAL, FL_KP+'.'}, {VK_DIVIDE, FL_KP+'/'}, {VK_NUMLOCK, FL_Num_Lock}, {VK_SCROLL, FL_Scroll_Lock}, #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500) {VK_BROWSER_BACK, FL_Back}, {VK_BROWSER_FORWARD, FL_Forward}, {VK_BROWSER_REFRESH, FL_Refresh}, {VK_BROWSER_STOP, FL_Stop}, {VK_BROWSER_SEARCH, FL_Search}, {VK_BROWSER_FAVORITES, FL_Favorites}, {VK_BROWSER_HOME, FL_Home_Page}, {VK_VOLUME_MUTE, FL_Volume_Mute}, {VK_VOLUME_DOWN, FL_Volume_Down}, {VK_VOLUME_UP, FL_Volume_Up}, {VK_MEDIA_NEXT_TRACK, FL_Media_Next}, {VK_MEDIA_PREV_TRACK, FL_Media_Prev}, {VK_MEDIA_STOP, FL_Media_Stop}, {VK_MEDIA_PLAY_PAUSE, FL_Media_Play}, {VK_LAUNCH_MAIL, FL_Mail}, #endif {0xba, ';'}, {0xbb, '='}, // 0xbb == VK_OEM_PLUS (see #1086) {0xbc, ','}, {0xbd, '-'}, {0xbe, '.'}, {0xbf, '/'}, {0xc0, '`'}, {0xdb, '['}, {0xdc, '\\'}, {0xdd, ']'}, {0xde, '\''}, {VK_OEM_102, FL_Iso_Key} }; static int ms2fltk(WPARAM vk, int extended) { static unsigned short vklut[256]; static unsigned short extendedlut[256]; if (!vklut[1]) { // init the table unsigned int i; for (i = 0; i < 256; i++) vklut[i] = tolower(i); for (i = VK_F1; i <= VK_F16; i++) vklut[i] = i + (FL_F - (VK_F1 - 1)); for (i = VK_NUMPAD0; i <= VK_NUMPAD9; i++) vklut[i] = i + (FL_KP + '0' - VK_NUMPAD0); for (i = 0; i < sizeof(vktab) / sizeof(*vktab); i++) { vklut[vktab[i].vk] = vktab[i].fltk; extendedlut[vktab[i].vk] = vktab[i].extended; } for (i = 0; i < 256; i++) if (!extendedlut[i]) extendedlut[i] = vklut[i]; } return extended ? extendedlut[vk] : vklut[vk]; } #if USE_COLORMAP extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx #endif static Fl_Window *resize_bug_fix; extern void fl_save_pen(void); extern void fl_restore_pen(void); static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Copy the message to fl_msg so add_handler code can see it. // It is already there if this is called by DispatchMessage, // but not if Windows calls this directly. fl_msg.hwnd = hWnd; fl_msg.message = uMsg; fl_msg.wParam = wParam; fl_msg.lParam = lParam; // fl_msg.time = ??? // fl_msg.pt = ??? // fl_msg.lPrivate = ??? Fl_Window *window = fl_find(hWnd); float scale = (window ? Fl::screen_driver()->scale(Fl_Window_Driver::driver(window)->screen_num()) : 1); if (window) { switch (uMsg) { case WM_DPICHANGED: { // 0x02E0, after display re-scaling and followed by WM_DISPLAYCHANGE if (is_dpi_aware && !Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy) { RECT r, *lParam_rect = (RECT*)lParam; Fl_WinAPI_Screen_Driver *sd = (Fl_WinAPI_Screen_Driver*)Fl::screen_driver(); int centerX = (lParam_rect->left + lParam_rect->right)/2; int centerY = (lParam_rect->top + lParam_rect->bottom)/2; int ns = sd->screen_num_unscaled(centerX, centerY); int old_ns = Fl_Window_Driver::driver(window)->screen_num(); if (sd->dpi[ns][0] != HIWORD(wParam) && ns == old_ns) { // change DPI of a screen sd->dpi[ns][0] = sd->dpi[ns][1] = HIWORD(wParam); float f = HIWORD(wParam) / 96.f; GetClientRect(hWnd, &r); float old_f = float(r.right) / window->w(); Fl::screen_driver()->scale(ns, f); Fl_Window_Driver::driver(window)->resize_after_scale_change(ns, old_f, f); sd->update_scaling_capability(); } else if (ns != old_ns) { // jump window with Windows+Shift+L|R-arrow to other screen with other DPI float scale = Fl::screen_driver()->scale(ns); int bt, bx, by; Fl_WinAPI_Window_Driver *wdr = (Fl_WinAPI_Window_Driver*)Fl_Window_Driver::driver(window); wdr->border_width_title_bar_height(bx, by, bt); window->position(int(round(lParam_rect->left/scale)), int(round((lParam_rect->top + bt)/scale))); wdr->resize_after_scale_change(ns, scale, scale); } } return 0; } case WM_QUIT: // this should not happen? Fl::fatal("WM_QUIT message"); case WM_CLOSE: // user clicked close box Fl::handle(FL_CLOSE, window); return 0; case WM_SYNCPAINT: case WM_NCPAINT: case WM_ERASEBKGND: // Andreas Weitl - WM_SYNCPAINT needs to be passed to DefWindowProc // so that Windows can generate the proper paint messages... // Similarly, WM_NCPAINT and WM_ERASEBKGND need this, too... break; case WM_PAINT: { HRGN R, R2; Fl_X *i = Fl_X::flx(window); Fl_Window_Driver::driver(window)->wait_for_expose_value = 0; char redraw_whole_window = false; if (!i->region && window->damage()) { // Redraw the whole window... i->region = CreateRectRgn(0, 0, window->w(), window->h()); redraw_whole_window = true; } // We need to merge Windows' damage into FLTK's damage. R = CreateRectRgn(0, 0, 0, 0); int r = GetUpdateRgn(hWnd, R, 0); if (r == NULLREGION && !redraw_whole_window) { DeleteObject(R); break; } // convert i->region in FLTK units to R2 in drawing units R2 = Fl_GDI_Graphics_Driver::scale_region((HRGN)i->region, scale, NULL); RECT r_box; if (scale != 1 && GetRgnBox(R, &r_box) != NULLREGION) { // add de-scaled update region to i->region in FLTK units r_box.left = LONG(r_box.left / scale); r_box.right = LONG(r_box.right / scale); r_box.top = LONG(r_box.top / scale); r_box.bottom = LONG(r_box.bottom / scale); HRGN R3 = CreateRectRgn(r_box.left, r_box.top, r_box.right + 1, r_box.bottom + 1); if (!i->region) i->region = R3; else { CombineRgn((HRGN)i->region, (HRGN)i->region, R3, RGN_OR); DeleteObject(R3); } } if (R2) { // Also tell Windows that we are drawing someplace else as well... CombineRgn(R2, R2, R, RGN_OR); DeleteObject(R); } else { R2 = R; } if (window->type() == FL_DOUBLE_WINDOW) ValidateRgn(hWnd, 0); else { ValidateRgn(hWnd, R2); } if (scale != 1) DeleteObject(R2); window->clear_damage((uchar)(window->damage() | FL_DAMAGE_EXPOSE)); // These next two statements should not be here, so that all update // is deferred until Fl::flush() is called during idle. However Windows // apparently is very unhappy if we don't obey it and draw right now. // Very annoying! fl_GetDC(hWnd); // Make sure we have a DC for this window... fl_save_pen(); Fl_Window_Driver::driver(window)->flush(); fl_restore_pen(); window->clear_damage(); return 0; } // case WM_PAINT case WM_LBUTTONDOWN: mouse_event(window, 0, 1, wParam, lParam); return 0; case WM_LBUTTONDBLCLK: mouse_event(window, 1, 1, wParam, lParam); return 0; case WM_LBUTTONUP: mouse_event(window, 2, 1, wParam, lParam); return 0; case WM_MBUTTONDOWN: mouse_event(window, 0, 2, wParam, lParam); return 0; case WM_MBUTTONDBLCLK: mouse_event(window, 1, 2, wParam, lParam); return 0; case WM_MBUTTONUP: mouse_event(window, 2, 2, wParam, lParam); return 0; case WM_RBUTTONDOWN: mouse_event(window, 0, 3, wParam, lParam); return 0; case WM_RBUTTONDBLCLK: mouse_event(window, 1, 3, wParam, lParam); return 0; case WM_RBUTTONUP: mouse_event(window, 2, 3, wParam, lParam); return 0; case WM_XBUTTONDOWN: { int xbutton = GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? 4 : 5; mouse_event(window, 0, xbutton, wParam, lParam); return 0; } case WM_XBUTTONDBLCLK: { int xbutton = GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? 4 : 5; mouse_event(window, 1, xbutton, wParam, lParam); return 0; } case WM_XBUTTONUP: { int xbutton = GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? 4 : 5; mouse_event(window, 2, xbutton, wParam, lParam); return 0; } case WM_MOUSEMOVE: #ifdef USE_TRACK_MOUSE if (track_mouse_win != window) { TRACKMOUSEEVENT tme; tme.cbSize = sizeof(TRACKMOUSEEVENT); tme.dwFlags = TME_LEAVE; tme.hwndTrack = hWnd; _TrackMouseEvent(&tme); track_mouse_win = window; } #endif // USE_TRACK_MOUSE mouse_event(window, 3, 0, wParam, lParam); return 0; case WM_MOUSELEAVE: if (track_mouse_win == window) { // we left the top level window ! Fl_Window *tw = window; while (tw->parent()) // find top level window tw = tw->window(); Fl::belowmouse(0); Fl::handle(FL_LEAVE, tw); } track_mouse_win = 0; // force TrackMouseEvent() restart break; case WM_SETFOCUS: if ((Fl::modal_) && (Fl::modal_ != window)) { SetFocus(fl_xid(Fl::modal_)); return 0; } Fl::handle(FL_FOCUS, window); break; case WM_KILLFOCUS: if (Fl::grab() && (Fl::grab() != window) && Fl::grab()->menu_window()) { // simulate click at remote location (see issue #1166) mouse_event(Fl::grab(), 0, 1, MK_LBUTTON, MAKELPARAM(100000, 0)); } Fl::handle(FL_UNFOCUS, window); Fl::flush(); // it never returns to main loop when deactivated... break; case WM_SHOWWINDOW: if (!window->parent()) { Fl::handle(wParam ? FL_SHOW : FL_HIDE, window); } break; case WM_ACTIVATEAPP: // From eric@vfx.sel.sony.com, we should process WM_ACTIVATEAPP // messages to restore the correct state of the shift/ctrl/alt/lock // keys... Added control, shift, alt, and meta keys, and changed // to use GetAsyncKeyState and do it when wParam is 1 // (that means we have focus...) if (wParam) { ulong state = 0; if (GetAsyncKeyState(VK_CAPITAL)) state |= FL_CAPS_LOCK; if (GetAsyncKeyState(VK_NUMLOCK)) state |= FL_NUM_LOCK; if (GetAsyncKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK; if (GetAsyncKeyState(VK_CONTROL) & ~1) state |= FL_CTRL; if (GetAsyncKeyState(VK_SHIFT) & ~1) state |= FL_SHIFT; if (GetAsyncKeyState(VK_MENU)) state |= FL_ALT; if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & ~1) state |= FL_META; Fl::e_state = state; return 0; } break; case WM_INPUTLANGCHANGE: fl_get_codepage(); break; case WM_IME_COMPOSITION: // if (!fl_is_nt4() && lParam & GCS_RESULTCLAUSE) { // HIMC himc = ImmGetContext(hWnd); // wlen = ImmGetCompositionStringW(himc, GCS_RESULTSTR, // wbuf, sizeof(wbuf)) / sizeof(short); // if (wlen < 0) wlen = 0; // wbuf[wlen] = 0; // ImmReleaseContext(hWnd, himc); // } break; case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_KEYUP: case WM_SYSKEYUP: // save the keysym until we figure out the characters: Fl::e_keysym = Fl::e_original_keysym = ms2fltk(wParam, lParam & (1 << 24)); // Kludge to allow recognizing ctrl+'-' on keyboards with digits in uppercase positions (e.g. French) if (Fl::e_keysym == '6' && (VkKeyScanA('-') & 0xff) == '6') { Fl::e_keysym = '-'; } // See if TranslateMessage turned it into a WM_*CHAR message: if (PeekMessageW(&fl_msg, hWnd, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) { uMsg = fl_msg.message; wParam = fl_msg.wParam; lParam = fl_msg.lParam; } // FALLTHROUGH ... case WM_DEADCHAR: case WM_SYSDEADCHAR: case WM_CHAR: case WM_SYSCHAR: { ulong state = Fl::e_state & 0xff000000; // keep the mouse button state // if GetKeyState is expensive we might want to comment some of these out: if (GetKeyState(VK_SHIFT) & ~1) state |= FL_SHIFT; if (GetKeyState(VK_CAPITAL)) state |= FL_CAPS_LOCK; if (GetKeyState(VK_CONTROL) & ~1) state |= FL_CTRL; // Alt gets reported for the Alt-GR switch on non-English keyboards. // so we need to check the event as well to get it right: if ((lParam & (1 << 29)) // same as GetKeyState(VK_MENU) && uMsg != WM_CHAR) state |= FL_ALT; if (GetKeyState(VK_NUMLOCK)) state |= FL_NUM_LOCK; if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & ~1) { // Windows bug? GetKeyState returns garbage if the user hit the // meta key to pop up start menu. Sigh. if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & ~1) state |= FL_META; } if (GetKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK; Fl::e_state = state; static char buffer[1024]; if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) { wchar_t u = (wchar_t)wParam; Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1); buffer[Fl::e_length] = 0; } else if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) { if (state & FL_NUM_LOCK) { // Convert to regular keypress... buffer[0] = Fl::e_keysym - FL_KP; Fl::e_length = 1; } else { // Convert to special keypress... buffer[0] = 0; Fl::e_length = 0; switch (Fl::e_keysym) { case FL_KP + '0': Fl::e_keysym = FL_Insert; break; case FL_KP + '1': Fl::e_keysym = FL_End; break; case FL_KP + '2': Fl::e_keysym = FL_Down; break; case FL_KP + '3': Fl::e_keysym = FL_Page_Down; break; case FL_KP + '4': Fl::e_keysym = FL_Left; break; case FL_KP + '6': Fl::e_keysym = FL_Right; break; case FL_KP + '7': Fl::e_keysym = FL_Home; break; case FL_KP + '8': Fl::e_keysym = FL_Up; break; case FL_KP + '9': Fl::e_keysym = FL_Page_Up; break; case FL_KP + '.': Fl::e_keysym = FL_Delete; break; case FL_KP + '/': case FL_KP + '*': case FL_KP + '-': case FL_KP + '+': buffer[0] = Fl::e_keysym - FL_KP; Fl::e_length = 1; break; } } } else if ((lParam & (1 << 31)) == 0) { #ifdef FLTK_PREVIEW_DEAD_KEYS if ((lParam & (1 << 24)) == 0) { // clear if dead key (always?) wchar_t u = (wchar_t)wParam; Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1); buffer[Fl::e_length] = 0; } else { // set if "extended key" (never printable?) buffer[0] = 0; Fl::e_length = 0; } #else buffer[0] = 0; Fl::e_length = 0; #endif } Fl::e_text = buffer; // Kludge to process the +-containing key in cross-platform way when used with Ctrl /* Table of how Windows processes the '+'-containing key by keyboard layout key virtual content key keyboard layout =|+ 0xbb US/UK/Fr/Arabic/Chinese/Hebrew/Brazil/Russian/Vietnam/Japan/Korean/Persian +|* 0xbb German/Spanish/Italy/Greek/Portugal +|? 0xbb Swedish/Finish/Norway +|± 0xbb Dutch 1|+ '1' Swiss/Luxemburg 3|+ '3' Hungarian 4|+ '4' Turkish */ if ((Fl::e_state & FL_CTRL) && !(GetAsyncKeyState(VK_MENU) >> 15)) { // extra processing necessary only when Ctrl is down and Alt is up int vk_plus_key = (VkKeyScanA('+') & 0xff); // virtual key of '+'-containing key bool plus_shift_pos = ((VkKeyScanA('+') & 0x100) != 0); // true means '+' in shifted position int plus_other_char; // the other char on same key as '+' if (plus_shift_pos) plus_other_char = ms2fltk(vk_plus_key, 0); else if ((VkKeyScanA('*') & 0xff) == vk_plus_key) plus_other_char = '*'; // German else if ((VkKeyScanA('?') & 0xff) == vk_plus_key) plus_other_char = '?'; // Swedish else if ((VkKeyScanW(L'±') & 0xff) == vk_plus_key) plus_other_char = L'±'; // Dutch else plus_other_char = '='; // fallback //fprintf(stderr, "plus_shift_pos=%d plus_other_char='%c' vk+=0x%x\n", plus_shift_pos, // plus_other_char, vk_plus_key); if ( (vk_plus_key == 0xbb && Fl::e_keysym == '=') || // the '+'-containing key is down (plus_shift_pos && Fl::e_keysym == plus_other_char) ) { Fl::e_keysym = (plus_shift_pos ? plus_other_char : '+'); static char plus_other_char_utf8[4]; int lutf8 = fl_utf8encode(plus_other_char, plus_other_char_utf8); plus_other_char_utf8[lutf8] = 0; if (plus_shift_pos) { Fl::e_text = ( (Fl::e_state & FL_SHIFT) ? (char*)"+" : plus_other_char_utf8 ); } else { Fl::e_text = ( (Fl::e_state & FL_SHIFT) ? plus_other_char_utf8 : (char*)"+" ); } Fl::e_length = (int)strlen(Fl::e_text); } } // end of processing of the +-containing key if (lParam & (1 << 31)) { // key up events. if (Fl::handle(FL_KEYUP, window)) return 0; break; } while (window->parent()) window = window->window(); if (Fl::handle(FL_KEYBOARD, window)) { if (uMsg == WM_DEADCHAR || uMsg == WM_SYSDEADCHAR) Fl::compose_state = 1; return 0; } break; // WM_KEYDOWN ... WM_SYSKEYUP, WM_DEADCHAR ... WM_SYSCHAR } // case WM_DEADCHAR ... WM_SYSCHAR case WM_MOUSEWHEEL: { static int delta = 0; // running total of all vertical mousewheel motion delta += (SHORT)(HIWORD(wParam)); int dy = -delta / WHEEL_DELTA; delta += dy * WHEEL_DELTA; if (dy == 0) // nothing to do return 0; if (Fl::event_shift()) { // shift key pressed: send horizontal mousewheel event Fl::e_dx = dy; Fl::e_dy = 0; } else { // shift key not pressed (normal behavior): send vertical mousewheel event Fl::e_dx = 0; Fl::e_dy = dy; } Fl::handle(FL_MOUSEWHEEL, window); return 0; } case WM_MOUSEHWHEEL: { static int delta = 0; // running total of all horizontal mousewheel motion delta += (SHORT)(HIWORD(wParam)); int dx = delta / WHEEL_DELTA; delta -= dx * WHEEL_DELTA; if (dx == 0) // nothing to do return 0; if (Fl::event_shift()) { // shift key pressed: send *vertical* mousewheel event Fl::e_dx = 0; Fl::e_dy = dx; } else { // shift key not pressed (normal behavior): send horizontal mousewheel event Fl::e_dx = dx; Fl::e_dy = 0; } Fl::handle(FL_MOUSEWHEEL, window); return 0; } case WM_GETMINMAXINFO: Fl_WinAPI_Window_Driver::driver(window)->set_minmax((LPMINMAXINFO)lParam); break; case WM_SIZE: if (!window->parent()) { Fl_Window_Driver::driver(window)->is_maximized(wParam == SIZE_MAXIMIZED); if (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXHIDE) { Fl::handle(FL_HIDE, window); } else { Fl::handle(FL_SHOW, window); resize_bug_fix = window; window->size(int(ceil(LOWORD(lParam) / scale)), int(ceil(HIWORD(lParam) / scale))); // fprintf(LOG,"WM_SIZE size(%.0f,%.0f) graph(%d,%d) s=%.2f\n", // ceil(LOWORD(lParam)/scale),ceil(HIWORD(lParam)/scale), // LOWORD(lParam),HIWORD(lParam),scale); } } break; case WM_MOVE: { if (IsIconic(hWnd)) { break; } resize_bug_fix = window; int nx = LOWORD(lParam); int ny = HIWORD(lParam); if (nx & 0x8000) nx -= 65536; if (ny & 0x8000) ny -= 65536; // fprintf(LOG,"WM_MOVE position(%d,%d) s=%.2f\n",int(nx/scale),int(ny/scale),scale); // detect when window centre changes screen Fl_WinAPI_Screen_Driver *sd = (Fl_WinAPI_Screen_Driver *)Fl::screen_driver(); Fl_WinAPI_Window_Driver *wd = Fl_WinAPI_Window_Driver::driver(window); int olds = wd->screen_num(); // Issue #1097: when a fullscreen window is restored to its size, it receives first a WM_MOVE // and then a WM_SIZE, so it still has its fullscreen size at the WM_MOVE event, which defeats // using window->w()|h() to compute the center of the (small) window. We detect this situation // with condition: !window->fullscreen_active() && *wd->no_fullscreen_w() // and use *wd->no_fullscreen_w()|h() instead of window->w()|h(). int trueW = window->w(), trueH = window->h(); if (!window->fullscreen_active() && *wd->no_fullscreen_w()) { trueW = *wd->no_fullscreen_w(); trueH = *wd->no_fullscreen_h(); } int news = sd->screen_num_unscaled(nx + int(trueW * scale / 2), ny + int(trueH * scale / 2)); if (news == -1) news = olds; float s = sd->scale(news); // fprintf(LOG,"WM_MOVE olds=%d(%.2f) news=%d(%.2f) busy=%d\n",olds, // sd->scale(olds),news, s, // Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy); // fflush(LOG); if (!window->parent()) { if (olds != news) { if (s != sd->scale(olds) && !Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy && window->user_data() != &Fl_WinAPI_Screen_Driver::transient_scale_display) { Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy = true; Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.screen = news; Fl::add_timeout(1, Fl_WinAPI_Window_Driver::resize_after_screen_change, window); } else if (!Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy) wd->screen_num(news); } else if (Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy) { Fl::remove_timeout(Fl_WinAPI_Window_Driver::resize_after_screen_change, window); Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_.busy = false; } } window->position(int(round(nx/scale)), int(round(ny/scale))); break; } // case WM_MOVE case WM_SETCURSOR: if (LOWORD(lParam) == HTCLIENT) { while (window->parent()) window = window->window(); SetCursor(Fl_WinAPI_Window_Driver::driver(window)->cursor); return 0; } break; #if USE_COLORMAP case WM_QUERYNEWPALETTE: fl_GetDC(hWnd); if (fl_select_palette()) InvalidateRect(hWnd, NULL, FALSE); break; case WM_PALETTECHANGED: if ((HWND)wParam != hWnd && fl_select_palette()) UpdateColors(fl_GetDC(hWnd)); break; case WM_CREATE: fl_GetDC(hWnd); fl_select_palette(); break; #endif case WM_DESTROYCLIPBOARD: fl_i_own_selection[1] = 0; return 1; case WM_DISPLAYCHANGE: {// when screen configuration (number, size, position) changes Fl::call_screen_init(); Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL); return 0; } case WM_CHANGECBCHAIN: if ((hWnd == clipboard_wnd) && (next_clipboard_wnd == (HWND)wParam)) next_clipboard_wnd = (HWND)lParam; else SendMessage(next_clipboard_wnd, WM_CHANGECBCHAIN, wParam, lParam); return 0; case WM_DRAWCLIPBOARD: // When the clipboard moves between two FLTK windows, // fl_i_own_selection will temporarily be false as we are // processing this message. Hence the need to use fl_find(). if (!initial_clipboard && !fl_find(GetClipboardOwner())) fl_trigger_clipboard_notify(1); initial_clipboard = false; if (next_clipboard_wnd) SendMessage(next_clipboard_wnd, WM_DRAWCLIPBOARD, wParam, lParam); return 0; default: if (Fl::handle(0, 0)) return 0; break; } // switch (uMsg) } // if (window) return DefWindowProcW(hWnd, uMsg, wParam, lParam); } /* Implementation note about the API to get the dimensions of the top/left borders and the title bar Function fake_X_wm() below is used before calling CreateWindowExW() to create a window and before calling SetWindowPos(). Both of these Windows functions need the window size including borders and title bar. Function fake_X_wm() uses AdjustWindowRectExForDpi() or AdjustWindowRectEx() to get the sizes of borders and title bar. The gotten values don't always match what is seen on the display, but they are the **required** values so the subsequent calls to CreateWindowExW() or SetWindowPos() correctly size the window. The Windows doc of AdjustWindowRectExForDpi/AdjustWindowRectEx makes this very clear: Calculates the required size of the window rectangle, based on the desired size of the client rectangle [and the provided DPI]. This window rectangle can then be passed to the CreateWindowEx function to create a window with a client area of the desired size. Conversely, Fl_WinAPI_Window_Driver::border_width_title_bar_height() is used to get the true sizes of borders and title bar of a mapped window. The correct API for that is DwmGetWindowAttribute(). */ // ///////////////////////////////////////////////////////////////// // This function gets the dimensions of the top/left borders and // the title bar, if there is one, based on the FL_BORDER, FL_MODAL // and FL_NONMODAL flags, and on the window's size range. // It returns the following values: // // value | border | title bar // 0 | none | no // 1 | fix | yes // 2 | size | yes int Fl_WinAPI_Window_Driver::fake_X_wm(int &X, int &Y, int &bt, int &bx, int &by, DWORD style, DWORD styleEx) { const Fl_Window *w = pWindow; int W = 0, H = 0, xoff = 0, yoff = 0, dx = 0, dy = 0; int ret = bx = by = bt = 0; int fallback = 1; float s = Fl::screen_driver()->scale(screen_num()); int minw, minh, maxw, maxh; pWindow->get_size_range(&minw, &minh, &maxw, &maxh, NULL, NULL, NULL); if (!w->parent()) { if (fl_xid(w) || style) { // The block below calculates the window borders by requesting the // required decorated window rectangle for a desired client rectangle. // If any part of the function above fails, we will drop to a // fallback to get the best guess which is always available. if (!style) { HWND hwnd = fl_xid(w); // request the style flags of this window, as Windows sees them style = GetWindowLong(hwnd, GWL_STYLE); styleEx = GetWindowLong(hwnd, GWL_EXSTYLE); } RECT r; int drawingX, drawingY; // drawing coordinates of window top-left r.left = drawingX = int(round(w->x() * s)); r.top = drawingY = int(round(w->y() * s)); r.right = drawingX + int(w->w() * s); r.bottom = drawingY + int(w->h() * s); // get the decoration rectangle for the desired client rectangle typedef BOOL(WINAPI* AdjustWindowRectExForDpi_type)(LPRECT, DWORD, BOOL, DWORD, UINT); static AdjustWindowRectExForDpi_type fl_AdjustWindowRectExForDpi = (AdjustWindowRectExForDpi_type)GetProcAddress(LoadLibrary("User32.DLL"), "AdjustWindowRectExForDpi"); BOOL ok; if (is_dpi_aware && fl_AdjustWindowRectExForDpi) { Fl_WinAPI_Screen_Driver *sd = (Fl_WinAPI_Screen_Driver*)Fl::screen_driver(); UINT dpi = UINT(sd->dpi[screen_num()][0]); ok = fl_AdjustWindowRectExForDpi(&r, style, FALSE, styleEx, dpi); } else ok = AdjustWindowRectEx(&r, style, FALSE, styleEx); if (ok) { X = r.left; Y = r.top; W = r.right - r.left; H = r.bottom - r.top; bx = drawingX - r.left; by = r.bottom - int(drawingY + w->h() * s); // height of the bottom frame bt = drawingY - r.top - by; // height of top caption bar xoff = bx; yoff = by + bt; dx = W - int(w->w() * s); dy = H - int(w->h() * s); if (maxw != minw || maxh != minh) ret = 2; else ret = 1; fallback = 0; } } } // This is the original (pre 1.1.7) routine to calculate window border sizes. if (fallback) { if (w->border() && !w->parent()) { if (maxw != minw || maxh != minh) { ret = 2; bx = GetSystemMetrics(SM_CXSIZEFRAME); by = GetSystemMetrics(SM_CYSIZEFRAME); } else { ret = 1; int padding = GetSystemMetrics(SM_CXPADDEDBORDER); NONCLIENTMETRICS ncm; ncm.cbSize = sizeof(NONCLIENTMETRICS); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0); bx = GetSystemMetrics(SM_CXFIXEDFRAME) + (padding ? padding + ncm.iBorderWidth : 0); by = GetSystemMetrics(SM_CYFIXEDFRAME) + (padding ? padding + ncm.iBorderWidth : 0); } bt = GetSystemMetrics(SM_CYCAPTION); } // The coordinates of the whole window, including non-client area xoff = bx; yoff = by + bt; dx = 2 * bx; dy = 2 * by + bt; X = w->x() - xoff; Y = w->y() - yoff; W = w->w() + dx; H = w->h() + dy; } // Proceed to positioning the window fully inside the screen, if possible // Find screen that contains most of the window // FIXME: this ought to be the "work area" instead of the entire screen ! int scr_x = 0, scr_y = 0, scr_w = 0, scr_h = 0; int ns = Fl::screen_num(int(round(X / s)), int(round(Y / s)), int(W / s), int(H / s)); ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->screen_xywh_unscaled(scr_x, scr_y, scr_w, scr_h, ns); // Make border's lower right corner visible if (scr_x + scr_w < X + W) X = scr_x + scr_w - W; if (scr_y + scr_h < Y + H) Y = scr_y + scr_h - H; // Make border's upper left corner visible if (X < scr_x) X = scr_x; if (Y < scr_y) Y = scr_y; // Make client area's lower right corner visible if (scr_x + scr_w < X + dx + w->w()) X = scr_x + scr_w - int(w->w() * s) - dx; if (scr_y + scr_h < Y + dy + w->h()) Y = scr_y + scr_h - int(w->h() * s) - dy; // Make client area's upper left corner visible if (X + xoff < scr_x) X = scr_x - xoff; if (Y + yoff < scr_y) Y = scr_y - yoff; // Return the client area's top left corner in (X,Y) X += xoff; Y += yoff; if (w->fullscreen_active()) { bx = by = bt = 0; } return ret; } //////////////////////////////////////////////////////////////// static void delayed_fullscreen(Fl_Window *win) { Fl::remove_check((Fl_Timeout_Handler)delayed_fullscreen, win); win->fullscreen_off(); win->fullscreen(); } static void delayed_maximize(Fl_Window *win) { Fl::remove_check((Fl_Timeout_Handler)delayed_maximize, win); win->un_maximize(); win->maximize(); } void Fl_WinAPI_Window_Driver::resize(int X, int Y, int W, int H) { //fprintf(stderr, "resize w()=%d W=%d h()=%d H=%d\n",pWindow->w(), W,pWindow->h(), H); if (Fl_Window::is_a_rescale() && pWindow->fullscreen_active()) { Fl::add_check((Fl_Timeout_Handler)delayed_fullscreen, pWindow); } else if (Fl_Window::is_a_rescale() && pWindow->maximize_active()) { Fl::add_check((Fl_Timeout_Handler)delayed_maximize, pWindow); } UINT flags = SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER; int is_a_resize = (W != w() || H != h() || Fl_Window::is_a_rescale()); int resize_from_program = (pWindow != resize_bug_fix); if (!resize_from_program) resize_bug_fix = 0; if (X != x() || Y != y() || Fl_Window::is_a_rescale()) { force_position(1); } else { if (!is_a_resize) return; flags |= SWP_NOMOVE; } if (is_a_resize) { if (resize_from_program && shown()) { // don't obey "resize from program" when window is maximized WINDOWPLACEMENT wplace; wplace.length = sizeof(WINDOWPLACEMENT); BOOL ok = GetWindowPlacement(fl_xid(pWindow), &wplace); if (ok && wplace.showCmd == SW_SHOWMAXIMIZED) return; } pWindow->Fl_Group::resize(X, Y, W, H); if (visible_r()) { pWindow->redraw(); // only wait for exposure if this window has a size - a window // with no width or height will never get an exposure event Fl_X *i = Fl_X::flx(pWindow); if (i && W > 0 && H > 0) wait_for_expose_value = 1; } } else { x(X); y(Y); flags |= SWP_NOSIZE; } if (!border()) flags |= SWP_NOACTIVATE; if (resize_from_program && shown()) { int dummy_x, dummy_y, bt, bx, by; // compute window position and size in scaled units float s = Fl::screen_driver()->scale(screen_num()); int scaledX = int(round(X * s)), scaledY = int(round(Y * s)), scaledW = int(W * s), scaledH = int(H * s); // Ignore window managing when resizing, so that windows (and more // specifically menus) can be moved offscreen. if (fake_X_wm(dummy_x, dummy_y, bt, bx, by)) { scaledX -= bx; scaledY -= by + bt; scaledW += 2 * bx; scaledH += 2 * by + bt; } // avoid zero size windows. A zero sized window on Win32 // will cause continouly new redraw events. if (scaledW <= 0) scaledW = 1; if (scaledH <= 0) scaledH = 1; SetWindowPos(fl_xid(pWindow), 0, scaledX, scaledY, scaledW, scaledH, flags); } } //////////////////////////////////////////////////////////////// /* This silly little class remembers the name of all window classes we register to avoid double registration. It has the added bonus of freeing everything on application close as well. */ class NameList { public: NameList() { name = (char **)malloc(sizeof(char **)); NName = 1; nName = 0; } ~NameList() { int i; for (i = 0; i < nName; i++) free(name[i]); if (name) free(name); } void add_name(const char *n) { if (NName == nName) { NName += 5; name = (char **)realloc(name, NName * sizeof(char *)); } name[nName++] = fl_strdup(n); } char has_name(const char *n) { int i; for (i = 0; i < nName; i++) { if (strcmp(name[i], n) == 0) return 1; } return 0; } private: char **name; int nName, NName; }; void fl_fix_focus(); // in Fl.cxx UINT fl_wake_msg = 0; int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR void Fl_WinAPI_Window_Driver::makeWindow() { Fl_Group::current(0); // get rid of very common user bug: forgot end() fl_open_display(); // if the window is a subwindow and our parent is not mapped yet, we // mark this window visible, so that mapping the parent at a later // point in time will call this function again to finally map the subwindow. Fl_Window *w = pWindow; if (w->parent() && !Fl_X::flx(w->window())) { w->set_visible(); return; } static NameList class_name_list; static const char *first_class_name = 0L; const char *class_name = w->xclass(); if (!class_name) class_name = first_class_name; // reuse first class name used if (!class_name) class_name = "FLTK"; // default to create a "FLTK" WNDCLASS if (!first_class_name) { first_class_name = class_name; } wchar_t class_namew[100]; // (limited) buffer for Windows class name // convert UTF-8 class_name to wchar_t for RegisterClassExW and CreateWindowExW fl_utf8toUtf16(class_name, (unsigned)strlen(class_name), // in (unsigned short *)class_namew, // out (unsigned)sizeof(class_namew) / sizeof(wchar_t)); // max. size if (!class_name_list.has_name(class_name)) { WNDCLASSEXW wcw; memset(&wcw, 0, sizeof(wcw)); wcw.cbSize = sizeof(WNDCLASSEXW); // Documentation states a device context consumes about 800 bytes // of memory... so who cares? If 800 bytes per window is what it // takes to speed things up, I'm game. wcw.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; wcw.lpfnWndProc = (WNDPROC)WndProc; wcw.cbClsExtra = wcw.cbWndExtra = 0; wcw.hInstance = fl_display; if (!w->icon() && !icon_->count) w->icon((void *)LoadIcon(NULL, IDI_APPLICATION)); wcw.hIcon = wcw.hIconSm = (HICON)w->icon(); wcw.hCursor = LoadCursor(NULL, IDC_ARROW); wcw.hbrBackground = NULL; wcw.lpszMenuName = NULL; wcw.lpszClassName = class_namew; RegisterClassExW(&wcw); class_name_list.add_name(class_name); } const wchar_t *message_namew = L"FLTK::ThreadWakeup"; if (!fl_wake_msg) fl_wake_msg = RegisterWindowMessageW(message_namew); HWND parent; DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; DWORD styleEx = WS_EX_LEFT; // compute adequate screen where to put the window int nscreen = 0; if (w->parent()) { nscreen = Fl_Window_Driver::driver(w->top_window())->screen_num(); } else if (Fl_Window_Driver::driver(w)->force_position() && Fl_WinAPI_Window_Driver::driver(w)->screen_num_ >= 0) { nscreen = Fl_Window_Driver::driver(w)->screen_num(); } else { Fl_Window *hint = Fl::first_window(); if (hint) { nscreen = Fl_Window_Driver::driver(hint->top_window())->screen_num(); } else { int mx, my; nscreen = Fl::screen_driver()->get_mouse(mx, my); } } Fl_Window_Driver::driver(w)->screen_num(nscreen); float s = Fl::screen_driver()->scale(nscreen); int xp = int(round(w->x() * s)); // these are in graphical units int yp = int(round(w->y() * s)); int wp = int(w->w() * s); int hp = int(w->h() * s); int showit = 1; if (w->parent()) { style |= WS_CHILD; styleEx |= WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT; parent = fl_xid(w->window()); } else { // top level window styleEx |= WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT; int wintype = 0; if (w->border()) { if (is_resizable()) wintype = 2; else wintype = 1; } switch (wintype) { // No border (used for menus) case 0: style |= WS_POPUP; styleEx |= WS_EX_TOOLWINDOW; break; // Thin border and title bar case 1: style |= WS_DLGFRAME | WS_CAPTION; if (!w->modal()) style |= WS_SYSMENU | WS_MINIMIZEBOX; break; // Thick, resizable border and title bar, with maximize button case 2: style |= WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_CAPTION; if (!w->modal()) style |= WS_MINIMIZEBOX; break; } int xwm = xp, ywm = yp, bt, bx, by; // these are in graphical units fake_X_wm(xwm, ywm, bt, bx, by, style, styleEx); if (by + bt) { wp += 2 * bx; hp += 2 * by + bt; } if (!force_position()) { xp = yp = CW_USEDEFAULT; } else { if (!Fl::grab()) { xp = xwm; yp = ywm; x(int(round(xp / s))); y(int(round(yp / s))); } xp -= bx; yp -= by + bt; } parent = 0; if (w->non_modal() && Fl_X::first && !fl_disable_transient_for) { // find some other window to be "transient for": Fl_Window *w = Fl_X::first->w; while (w->parent()) w = w->window(); parent = fl_xid(w); if (!w->visible()) showit = 0; // https://www.fltk.org/str.php?L1115 // Mike added the code below to fix issues with tooltips that unfortunately // he does not specify in detail. After extensive testing, I can't see // how this fixes things, but I do see how a window opened by a timer will // link that window to the current popup, which is wrong. // Matt, Apr 30th, 2023 // } else if (Fl::grab()) { // parent = fl_xid(Fl::grab()); } } Fl_X *x = new Fl_X; other_xid = 0; x->w = w; flx(x); x->region = 0; Fl_WinAPI_Window_Driver::driver(w)->private_dc = 0; cursor = LoadCursor(NULL, IDC_ARROW); custom_cursor = 0; if (!fl_codepage) fl_get_codepage(); WCHAR *lab = NULL; if (w->label()) { size_t l = strlen(w->label()); unsigned wlen = fl_utf8toUtf16(w->label(), (unsigned)l, NULL, 0); // Pass NULL to query length wlen++; lab = (WCHAR *)malloc(sizeof(WCHAR) * wlen); wlen = fl_utf8toUtf16(w->label(), (unsigned)l, (unsigned short *)lab, wlen); lab[wlen] = 0; } x->xid = (fl_uintptr_t)CreateWindowExW(styleEx, class_namew, lab, style, xp, yp, wp, hp, parent, NULL, // menu fl_display, NULL // creation parameters ); if (lab) free(lab); x->next = Fl_X::first; Fl_X::first = x; set_icons(); if (w->fullscreen_active()) { /* We need to make sure that the fullscreen is created on the default monitor, ie the desktop where the shortcut is located etc. This requires that CreateWindow is called with CW_USEDEFAULT for x and y. We can then use GetWindowRect to determine which monitor the window was placed on. */ RECT rect; GetWindowRect((HWND)x->xid, &rect); make_fullscreen(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); } // Setup clipboard monitor target if there are registered handlers and // no window is targeted. if (!fl_clipboard_notify_empty() && clipboard_wnd == NULL) fl_clipboard_notify_target((HWND)x->xid); wait_for_expose_value = ((wp == 0 || hp == 0) && !w->border() && !w->parent() ? 0 : 1); // issue #985 if (show_iconic()) { showit = 0; show_iconic(0); } if (showit) { w->set_visible(); int old_event = Fl::e_number; w->handle(Fl::e_number = FL_SHOW); // get child windows to appear Fl::e_number = old_event; w->redraw(); // force draw to happen } // Needs to be done before ShowWindow() to get the correct behavior // when we get WM_SETFOCUS. if (w->modal()) { Fl::modal_ = w; fl_fix_focus(); } // If we've captured the mouse, we don't want to activate any // other windows from the code, or we lose the capture. ShowWindow((HWND)x->xid, !showit ? SW_SHOWMINNOACTIVE : (Fl::grab() || (styleEx & WS_EX_TOOLWINDOW)) ? SW_SHOWNOACTIVATE : SW_SHOWNORMAL); // Register all windows for potential drag'n'drop operations RegisterDragDrop((HWND)x->xid, flIDropTarget); if (!im_enabled) flImmAssociateContextEx((HWND)x->xid, 0, 0); } //////////////////////////////////////////////////////////////// HINSTANCE fl_display = GetModuleHandle(NULL); HINSTANCE fl_win32_display() { return fl_display; } void Fl_WinAPI_Window_Driver::set_minmax(LPMINMAXINFO minmax) { int td, wd, hd, dummy_x, dummy_y; fake_X_wm(dummy_x, dummy_y, td, wd, hd); wd *= 2; hd *= 2; hd += td; int minw, minh, maxw, maxh; pWindow->get_size_range(&minw, &minh, &maxw, &maxh, NULL, NULL, NULL); float s = Fl::screen_driver()->scale(screen_num()); minmax->ptMinTrackSize.x = LONG(s * minw) + wd; minmax->ptMinTrackSize.y = LONG(s * minh) + hd; if (maxw) { minmax->ptMaxTrackSize.x = LONG(s * maxw) + wd; minmax->ptMaxSize.x = LONG(s * maxw) + wd; } if (maxh) { minmax->ptMaxTrackSize.y = LONG(s * maxh) + hd; minmax->ptMaxSize.y = LONG(s * maxh) + hd; } } //////////////////////////////////////////////////////////////// // returns pointer to the filename, or null if name ends with '/' const char *Fl_WinAPI_System_Driver::filename_name(const char *name) { const char *p, *q; if (!name) return (0); q = name; if (q[0] && q[1] == ':') q += 2; // skip leading drive letter for (p = q; *p; p++) { if (*p == '/' || *p == '\\') q = p + 1; } return q; } //////////////////////////////////////////////////////////////// static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon, int hotx, int hoty) { BITMAPV5HEADER bi; HBITMAP bitmap, mask; DWORD *bits; HICON icon; if (!is_icon) { if ((hotx < 0) || (hotx >= image->data_w())) return NULL; if ((hoty < 0) || (hoty >= image->data_h())) return NULL; } memset(&bi, 0, sizeof(BITMAPV5HEADER)); bi.bV5Size = sizeof(BITMAPV5HEADER); bi.bV5Width = image->data_w(); bi.bV5Height = -image->data_h(); // Negative for top-down bi.bV5Planes = 1; bi.bV5BitCount = 32; bi.bV5Compression = BI_BITFIELDS; bi.bV5RedMask = 0x00FF0000; bi.bV5GreenMask = 0x0000FF00; bi.bV5BlueMask = 0x000000FF; bi.bV5AlphaMask = 0xFF000000; HDC hdc; hdc = GetDC(NULL); bitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&bits, NULL, 0); ReleaseDC(NULL, hdc); if (bits == NULL) return NULL; const uchar *i = (const uchar *)*image->data(); const int extra_data = image->ld() ? (image->ld() - image->data_w() * image->d()) : 0; for (int y = 0; y < image->data_h(); y++) { for (int x = 0; x < image->data_w(); x++) { switch (image->d()) { case 1: *bits = (0xff << 24) | (i[0] << 16) | (i[0] << 8) | i[0]; break; case 2: *bits = (i[1] << 24) | (i[0] << 16) | (i[0] << 8) | i[0]; break; case 3: *bits = (0xff << 24) | (i[0] << 16) | (i[1] << 8) | i[2]; break; case 4: *bits = (i[3] << 24) | (i[0] << 16) | (i[1] << 8) | i[2]; break; } i += image->d(); bits++; } i += extra_data; } // A mask bitmap is still needed even though it isn't used mask = CreateBitmap(image->data_w(), image->data_h(), 1, 1, NULL); if (mask == NULL) { DeleteObject(bitmap); return NULL; } ICONINFO ii; ii.fIcon = is_icon; ii.xHotspot = hotx; ii.yHotspot = hoty; ii.hbmMask = mask; ii.hbmColor = bitmap; icon = CreateIconIndirect(&ii); DeleteObject(bitmap); DeleteObject(mask); return icon; } //////////////////////////////////////////////////////////////// static HICON default_big_icon = NULL; static HICON default_small_icon = NULL; static const Fl_RGB_Image *find_best_icon(int ideal_width, const Fl_RGB_Image *icons[], int count) { const Fl_RGB_Image *best; best = NULL; for (int i = 0; i < count; i++) { if (best == NULL) best = icons[i]; else { if (best->w() < ideal_width) { if (icons[i]->w() > best->w()) best = icons[i]; } else { if ((icons[i]->w() >= ideal_width) && (icons[i]->w() < best->w())) best = icons[i]; } } } return best; } void Fl_WinAPI_Screen_Driver::default_icons(const Fl_RGB_Image *icons[], int count) { const Fl_RGB_Image *best_big, *best_small; if (default_big_icon != NULL) DestroyIcon(default_big_icon); if (default_small_icon != NULL) DestroyIcon(default_small_icon); default_big_icon = NULL; default_small_icon = NULL; best_big = find_best_icon(GetSystemMetrics(SM_CXICON), icons, count); best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON), icons, count); bool need_delete; if (best_big != NULL) { need_delete = false; if (best_big->w() != best_big->data_w() || best_big->h() != best_big->data_h()) { best_big = (Fl_RGB_Image *)best_big->copy(); need_delete = true; } default_big_icon = image_to_icon(best_big, true, 0, 0); if (need_delete) delete best_big; } if (best_small != NULL) { need_delete = false; if (best_small->w() != best_small->data_w() || best_small->h() != best_small->data_h()) { best_small = (Fl_RGB_Image *)best_small->copy(); need_delete = true; } default_small_icon = image_to_icon(best_small, true, 0, 0); if (need_delete) delete best_small; } } void Fl_Window::icons(HICON big_icon, HICON small_icon) { free_icons(); if (big_icon != NULL) Fl_WinAPI_Window_Driver::driver(this)->icon_->big_icon = CopyIcon(big_icon); if (small_icon != NULL) Fl_WinAPI_Window_Driver::driver(this)->icon_->small_icon = CopyIcon(small_icon); if (Fl_X::flx(this)) Fl_WinAPI_Window_Driver::driver(this)->set_icons(); } void Fl_Window::default_icons(HICON big_icon, HICON small_icon) { if (default_big_icon != NULL) DestroyIcon(default_big_icon); if (default_small_icon != NULL) DestroyIcon(default_small_icon); default_big_icon = NULL; default_small_icon = NULL; if (big_icon != NULL) default_big_icon = CopyIcon(big_icon); if (small_icon != NULL) default_small_icon = CopyIcon(small_icon); } void Fl_WinAPI_Window_Driver::set_icons() { HICON big_icon, small_icon; // Windows doesn't copy the icons, so we have to "leak" them when // setting, and clean up when we change to some other icons. big_icon = (HICON)SendMessage(fl_xid(pWindow), WM_GETICON, ICON_BIG, 0); if ((big_icon != NULL) && (big_icon != default_big_icon)) DestroyIcon(big_icon); small_icon = (HICON)SendMessage(fl_xid(pWindow), WM_GETICON, ICON_SMALL, 0); if ((small_icon != NULL) && (small_icon != default_small_icon)) DestroyIcon(small_icon); big_icon = NULL; small_icon = NULL; if (icon_->count) { const Fl_RGB_Image *best_big, *best_small; best_big = find_best_icon(GetSystemMetrics(SM_CXICON), (const Fl_RGB_Image **)icon_->icons, icon_->count); best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON), (const Fl_RGB_Image **)icon_->icons, icon_->count); if (best_big != NULL) big_icon = image_to_icon(best_big, true, 0, 0); if (best_small != NULL) small_icon = image_to_icon(best_small, true, 0, 0); } else { if ((icon_->big_icon != NULL) || (icon_->small_icon != NULL)) { big_icon = icon_->big_icon; small_icon = icon_->small_icon; } else { big_icon = default_big_icon; small_icon = default_small_icon; } } SendMessage(fl_xid(pWindow), WM_SETICON, ICON_BIG, (LPARAM)big_icon); SendMessage(fl_xid(pWindow), WM_SETICON, ICON_SMALL, (LPARAM)small_icon); } //////////////////////////////////////////////////////////////// #ifndef IDC_HAND #define IDC_HAND MAKEINTRESOURCE(32649) #endif // !IDC_HAND int Fl_WinAPI_Window_Driver::set_cursor(Fl_Cursor c) { LPSTR n; HCURSOR new_cursor; if (c == FL_CURSOR_NONE) new_cursor = NULL; else { switch (c) { case FL_CURSOR_ARROW: n = IDC_ARROW; break; case FL_CURSOR_CROSS: n = IDC_CROSS; break; case FL_CURSOR_WAIT: n = IDC_WAIT; break; case FL_CURSOR_INSERT: n = IDC_IBEAM; break; case FL_CURSOR_HAND: n = IDC_HAND; break; case FL_CURSOR_HELP: n = IDC_HELP; break; case FL_CURSOR_MOVE: n = IDC_SIZEALL; break; case FL_CURSOR_N: case FL_CURSOR_S: // FIXME: Should probably have fallbacks for these instead case FL_CURSOR_NS: n = IDC_SIZENS; break; case FL_CURSOR_NE: case FL_CURSOR_SW: // FIXME: Dito. case FL_CURSOR_NESW: n = IDC_SIZENESW; break; case FL_CURSOR_E: case FL_CURSOR_W: // FIXME: Dito. case FL_CURSOR_WE: n = IDC_SIZEWE; break; case FL_CURSOR_SE: case FL_CURSOR_NW: // FIXME: Dito. case FL_CURSOR_NWSE: n = IDC_SIZENWSE; break; default: return 0; } new_cursor = LoadCursor(NULL, n); if (new_cursor == NULL) return 0; } if ((cursor != NULL) && custom_cursor) DestroyIcon(cursor); cursor = new_cursor; custom_cursor = 0; SetCursor(cursor); return 1; } int Fl_WinAPI_Window_Driver::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { HCURSOR new_cursor; Fl_RGB_Image *scaled_image = (Fl_RGB_Image*)image->copy(); new_cursor = image_to_icon(scaled_image, false, hotx, hoty); delete scaled_image; if (new_cursor == NULL) return 0; if ((cursor != NULL) && custom_cursor) DestroyIcon(cursor); cursor = new_cursor; custom_cursor = 1; SetCursor(cursor); return 1; } //////////////////////////////////////////////////////////////// // Implement the virtual functions for the base Fl_Window class: void Fl_WinAPI_Window_Driver::show() { if (!shown()) { makeWindow(); } else { // Once again, we would lose the capture if we activated the window. Fl_X *i = Fl_X::flx(pWindow); if (IsIconic((HWND)i->xid)) OpenIcon((HWND)i->xid); if (!fl_capture) BringWindowToTop((HWND)i->xid); // ShowWindow(i->xid,fl_capture?SW_SHOWNOACTIVATE:SW_RESTORE); } } // the current context // the current window handle, initially set to -1 so we can correctly // allocate fl_GetDC(0) HWND fl_window = NULL; // Here we ensure only one GetDC is ever in place. HDC fl_GetDC(HWND w) { HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc(); if (gc) { if (w == fl_window && fl_window != NULL) return gc; if (fl_window) fl_release_dc(fl_window, gc); // ReleaseDC } gc = GetDC(w); Fl_Graphics_Driver::default_driver().gc(gc); fl_save_dc(w, gc); fl_window = w; // calling GetDC seems to always reset these: (?) SetTextAlign(gc, TA_BASELINE | TA_LEFT); SetBkMode(gc, TRANSPARENT); return gc; } /* Make sure that all allocated fonts are released. This works only if Fl::run() is allowed to exit by closing all windows. Calling 'exit(int)' will not automatically free any fonts. */ void fl_free_fonts(void) { // remove the Fl_Font_Descriptor chains int i; Fl_Fontdesc *s; Fl_Font_Descriptor *f; Fl_Font_Descriptor *ff; for (i = 0; i < FL_FREE_FONT; i++) { s = fl_fonts + i; for (f = s->first; f; f = ff) { ff = f->next; delete (Fl_GDI_Font_Descriptor*)f; s->first = ff; } } } /////////////////////////////////////////////////////////////////////// // // The following routines help fix a problem with the leaking of Windows // Device Context (DC) objects. The 'proper' protocol is for a program to // acquire a DC, save its state, do the modifications needed for drawing, // perform the drawing, restore the initial state, and release the DC. In // FLTK, the save and restore steps have previously been omitted and DCs are // not properly released, leading to a great number of DC leaks. As some // Windows "OSs" will hang when any process exceeds roughly 10,000 GDI objects, // it is important to control GDI leaks, which are much more important than memory // leaks. The following struct, global variable, and routines help implement // the above protocol for those cases where the GetDC and RestoreDC are not in // the same routine. For each GetDC, fl_save_dc is used to create an entry in // a linked list that saves the window handle, the DC handle, and the initial // state. When the DC is to be released, 'fl_release_dc' is called. It restores // the initial state and releases the DC. When the program exits, 'fl_cleanup_dc_list' // frees any remaining nodes in the list. struct Win_DC_List { // linked list HWND window; // window handle HDC dc; // device context handle int saved_dc; // initial state of DC Win_DC_List *next; // pointer to next item }; static Win_DC_List *win_DC_list = 0; void fl_save_dc(HWND w, HDC dc) { Win_DC_List *t; t = new Win_DC_List; t->window = w; t->dc = dc; t->saved_dc = SaveDC(dc); if (win_DC_list) t->next = win_DC_list; else t->next = NULL; win_DC_list = t; } void fl_release_dc(HWND w, HDC dc) { Win_DC_List *t = win_DC_list; Win_DC_List *prev = 0; if (!t) return; do { if (t->dc == dc) { RestoreDC(dc, t->saved_dc); ReleaseDC(w, dc); if (!prev) { win_DC_list = t->next; // delete first item } else { prev->next = t->next; // one in the middle } delete (t); return; } prev = t; t = t->next; } while (t); } void fl_cleanup_dc_list(void) { // clean up the list Win_DC_List *t = win_DC_list; if (!t) return; do { RestoreDC(t->dc, t->saved_dc); ReleaseDC(t->window, t->dc); win_DC_list = t->next; delete (t); t = win_DC_list; } while (t); } /* Returns images of the captures of the window title-bar, and the left, bottom and right window borders. This function exploits a feature of Fl_WinAPI_Screen_Driver::read_win_rectangle() which, when fl_gc is set to the screen device context, captures the window decoration. */ void Fl_WinAPI_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image *&top, Fl_RGB_Image *&left, Fl_RGB_Image *&bottom, Fl_RGB_Image *&right) { top = left = bottom = right = NULL; if (!shown() || parent() || !border() || !visible()) return; int wsides, hbottom, bt; float scaling = Fl::screen_driver()->scale(screen_num()); RECT r = border_width_title_bar_height(wsides, hbottom, bt); int htop = bt + hbottom; Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); pWindow->show(); while (Fl::ready()) Fl::check(); HDC save_gc = (HDC)fl_graphics_driver->gc(); fl_graphics_driver->gc(GetDC(NULL)); int ww = int(w() * scaling) + 2 * wsides; wsides = int(wsides / scaling); if (wsides < 1) wsides = 1; ww = int(ww / scaling); if (wsides <= 1) ww = w() + 2 * wsides; // capture the 4 window sides from screen int offset = r.left < 0 ? -r.left : 0; Fl_WinAPI_Screen_Driver *dr = (Fl_WinAPI_Screen_Driver *)Fl::screen_driver(); if (htop && r.right - r.left > offset) { top = dr->read_win_rectangle_unscaled(r.left+offset, r.top, r.right - r.left-offset, htop, 0); if (scaling != 1 && top) top->scale(ww, int(htop / scaling), 0, 1); } if (wsides) { left = dr->read_win_rectangle_unscaled(r.left + offset, r.top + htop, wsides, int(h() * scaling), 0); right = dr->read_win_rectangle_unscaled(r.right - wsides, r.top + htop, wsides, int(h() * scaling), 0); bottom = dr->read_win_rectangle_unscaled(r.left+offset, r.bottom - hbottom, ww, hbottom, 0); if (scaling != 1) { if (left) left->scale(wsides, h(), 0, 1); if (right) right->scale(wsides, h(), 0, 1); if (bottom) bottom->scale(ww, hbottom, 0, 1); } } ReleaseDC(NULL, (HDC)fl_graphics_driver->gc()); fl_graphics_driver->gc(save_gc); Fl_Surface_Device::pop_current(); } fltk-1.4.3/src/forms_pixmap.cxx0000644000175000017500000000233015004135251016622 0ustar albrechtalbrecht// // Forms pixmap drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include /** Creates a new Fl_FormsPixmap widget using the given box type, position, size and label string. \param[in] t box type \param[in] X, Y, W, H position and size \param[in] L widget label, default is no label */ Fl_FormsPixmap::Fl_FormsPixmap( Fl_Boxtype t, int X, int Y, int W, int H, const char* L) : Fl_Widget(X, Y, W, H, L) { box(t); b = 0; color(FL_BLACK); align(FL_ALIGN_BOTTOM); } /** Set/create the internal pixmap using raw data. \param[in] bits raw data */ void Fl_FormsPixmap::set(char*const* bits) { delete b; b = new Fl_Pixmap(bits); } void Fl_FormsPixmap::draw() { draw_box(box(), selection_color()); if (b) {fl_color(color()); b->draw(x(), y(), w(), h());} draw_label(); } fltk-1.4.3/src/Fl_Gl_Choice.cxx0000644000175000017500000000524715004135251016365 0ustar albrechtalbrecht// // OpenGL visual selection code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if HAVE_GL /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include #include "Fl_Gl_Choice.H" #include #include "Fl_Gl_Window_Driver.H" #include #include #ifndef GL_CURRENT_PROGRAM // from glew.h in Windows, glext.h in Unix, not used by FLTK's macOS platform # define GL_CURRENT_PROGRAM 0x8B8D #endif typedef void (*glUseProgram_type)(GLint); static glUseProgram_type glUseProgram_f = NULL; GLContext *Fl_Gl_Window_Driver::context_list = 0; int Fl_Gl_Window_Driver::nContext = 0; static int NContext = 0; void Fl_Gl_Window_Driver::add_context(GLContext ctx) { if (!ctx) return; if (nContext==NContext) { if (!NContext) NContext = 8; NContext *= 2; context_list = (GLContext*)realloc( context_list, NContext*sizeof(GLContext)); } context_list[nContext++] = ctx; } void Fl_Gl_Window_Driver::del_context(GLContext ctx) { int i; for (i=0; inext) if (g->mode == m && g->alist == alistp) return g; return NULL; } /** \} \endcond */ #endif // HAVE_GL fltk-1.4.3/src/Fl_Graphics_Driver.cxx0000644000175000017500000011654715004135251017632 0ustar albrechtalbrecht// // Fl_Graphics_Driver class for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2025 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Graphics_Driver.cxx \brief Implementation of class Fl_Graphics_Driver. */ #include // for HAVE_GL #include /** Points to the driver that currently receives all graphics requests */ FL_EXPORT Fl_Graphics_Driver *fl_graphics_driver; /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include "Fl_Screen_Driver.H" #include #include // for fabs(), sqrt() #include // for fl_open_display() #include const Fl_Graphics_Driver::matrix Fl_Graphics_Driver::m0 = {1, 0, 0, 1, 0, 0}; /** Used by the Windows platform to print Fl_Pixmap objects. */ unsigned Fl_Graphics_Driver::need_pixmap_bg_color = 0; extern unsigned fl_cmap[256]; // defined in fl_color.cxx /** Constructor */ Fl_Graphics_Driver::Fl_Graphics_Driver() { font_ = 0; size_ = 0; color_ = FL_BLACK; sptr=0; rstackptr=0; rstack[0] = NULL; fl_clip_state_number=0; m = m0; font_descriptor_ = NULL; scale_ = 1; p_size = 0; xpoint = NULL; what = NONE; n = 0; } /** Destructor */ Fl_Graphics_Driver::~Fl_Graphics_Driver() { if (xpoint) free(xpoint); } /** Return the graphics driver used when drawing to the platform's display */ Fl_Graphics_Driver &Fl_Graphics_Driver::default_driver() { static Fl_Graphics_Driver *pMainDriver = Fl_Display_Device::display_device()->driver(); return *pMainDriver; } /** see fl_text_extents() */ void Fl_Graphics_Driver::text_extents(const char*t, int nChars, int& dx, int& dy, int& w, int& h) { w = (int)width(t, nChars); h = - height(); dx = 0; dy = descent(); } /** see fl_focus_rect() */ void Fl_Graphics_Driver::focus_rect(int x, int y, int w, int h) { line_style(FL_DOT); rect(x, y, w, h); line_style(FL_SOLID); } /** see fl_copy_offscreen() */ void Fl_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) { // This platform-independent version can be used by any graphics driver, // noticeably the PostScript driver. // More efficient platform-specific implementations exist for other graphics drivers. Fl_Image_Surface *surface = NULL; int px_width = w, px_height = h; Fl::screen_driver()->offscreen_size(pixmap, px_width, px_height); Fl_Surface_Device *current = Fl_Surface_Device::surface(); fl_begin_offscreen(pixmap); // does nothing if pixmap was not created by fl_create_offscreen() float s = 1; if (current == Fl_Surface_Device::surface()) {// pixmap was not created by fl_create_offscreen() // happens, e.g., when drawing images under Windows surface = new Fl_Image_Surface(px_width, px_height, 0, pixmap); Fl_Surface_Device::push_current(surface); } else { // pixmap was created by fl_create_offscreen() Fl_Image_Surface *imgs = (Fl_Image_Surface*)Fl_Surface_Device::surface(); int sw, sh; imgs->printable_rect(&sw, &sh); s = px_width / float(sw); } int px = srcx, py = srcy, pw = w, ph = h; if (px < 0) {px = 0; pw += srcx; x -= srcx;} if (py < 0) {py = 0; ph += srcy; y -= srcy;} if (px + pw > px_width/s) {pw = int(px_width/s) - px;} if (py + ph > px_height/s) {ph = int(px_height/s) - py;} uchar *img = fl_read_image(NULL, px, py, pw, ph, 0); if (surface) { Fl_Surface_Device::pop_current(); delete surface; } else fl_end_offscreen(); if (img) { fl_draw_image(img, x, y, pw, ph, 3, 0); delete[] img; } } /** Sets the value of the fl_gc global variable when it changes */ void Fl_Graphics_Driver::global_gc() { // nothing to do, reimplement in driver if needed } /** see Fl::set_color(Fl_Color, unsigned) */ void Fl_Graphics_Driver::set_color(Fl_Color i, unsigned c) { fl_cmap[i] = c; } /** see Fl::free_color(Fl_Color, int) */ void Fl_Graphics_Driver::free_color(Fl_Color i, int overlay) { // nothing to do, reimplement in driver if needed } /** Add a rectangle to an Fl_Region */ void Fl_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h) { // nothing to do, reimplement in driver if needed } /** Create a rectangular Fl_Region */ Fl_Region Fl_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) { // nothing to do, reimplement in driver if needed return 0; } /** Delete an Fl_Region */ void Fl_Graphics_Driver::XDestroyRegion(Fl_Region r) { // nothing to do, reimplement in driver if needed } /** Helper function for image drawing by platform-specific graphics drivers */ int Fl_Graphics_Driver::start_image(Fl_Image *img, int XP, int YP, int WP, int HP, int &cx, int &cy, int &X, int &Y, int &W, int &H) { // account for current clip region (faster on Irix): clip_box(XP,YP,WP,HP,X,Y,W,H); cx += X-XP; cy += Y-YP; // clip the box down to the size of image, quit if empty: if (cx < 0) {W += cx; X -= cx; cx = 0;} if (cx+W > img->w()) W = img->w()-cx; if (W <= 0) return 1; if (cy < 0) {H += cy; Y -= cy; cy = 0;} if (cy+H > img->h()) H = img->h()-cy; if (H <= 0) return 1; return 0; } /** Support function for image drawing */ void Fl_Graphics_Driver::uncache_pixmap(fl_uintptr_t p) { } void Fl_Graphics_Driver::set_current_() { } /** Support for Fl::set_font() */ unsigned Fl_Graphics_Driver::font_desc_size() { return (unsigned)sizeof(Fl_Fontdesc); } /** Converts \p width and \p height from FLTK units to drawing units. The conversion performed consists in multiplying \p width and \p height by scale() and in slightly modifying that to help support tiled images. */ void Fl_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height) { // Image tiling may require to convert the floating value of width * scale() or // height * scale() to a larger integer value to avoid undrawn space between adjacent images. float s = scale(), fs = width * s; width = (fs - int(fs) < 0.001 ? int(fs) : int((width+1) * s)); fs = height * s; height = (fs - int(fs) < 0.001 ? int(fs) : int((height+1) * s)); cache_size_finalize(img, width, height); } void Fl_Graphics_Driver::cache_size_finalize(Fl_Image *img, int &width, int &height) { if (img) img->cache_size_(width, height); } /** Draws an Fl_Pixmap object using this graphics driver. Specifies a bounding box for the image, with the origin (upper left-hand corner) of the image offset by the cx and cy arguments. */ void Fl_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; if (Fl_Graphics_Driver::start_image(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; } // to allow rescale at runtime int w2=pxm->w(), h2=pxm->h(); cache_size(pxm, w2, h2); // after this, w2 x h2 is size of desired cached image int *pw, *ph; cache_w_h(pxm, pw, ph); // after this, *pw x *ph is current size of cached form of bitmap if (*id(pxm) && (*pw != w2 || *ph != h2)) { pxm->uncache(); } if (!*id(pxm)) { if (pxm->data_w() != w2 || pxm->data_h() != h2) { // build a scaled id_ & mask_ for pxm Fl_Pixmap *pxm2 = (Fl_Pixmap*)pxm->copy(w2, h2); cache(pxm2); *id(pxm) = *id(pxm2); *id(pxm2) = 0; *pw = w2; *ph = h2; // memorize size of cached form of pixmap *mask(pxm) = *mask(pxm2); *mask(pxm2) = 0; delete pxm2; } else cache(pxm); } // draw pxm using its scaled id_ & pixmap_ draw_fixed(pxm, X, Y, W, H, cx, cy); } /** Draws an Fl_Bitmap object using this graphics driver. Specifies a bounding box for the image, with the origin (upper left-hand corner) of the image offset by the cx and cy arguments. */ void Fl_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; if (Fl_Graphics_Driver::start_image(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; } int w2 = bm->w(), h2 = bm->h(); cache_size(bm, w2, h2); // after this, w2 x h2 is size of desired cached image int *pw, *ph; cache_w_h(bm, pw, ph); // after this, *pw x *ph is current size of cached form of bitmap if (*id(bm) && (*pw != w2 || *ph != h2)) { bm->uncache(); } if (!*id(bm)) { if (bm->data_w() != w2 || bm->data_h() != h2) { // build a scaled id_ for bm Fl_Bitmap *bm2 = (Fl_Bitmap*)bm->copy(w2, h2); cache(bm2); *id(bm) = *id(bm2); *id(bm2) = 0; *pw = w2; *ph = h2; // memorize size of cached form of bitmap delete bm2; } else cache(bm); } // draw bm using its scaled id_ draw_fixed(bm, X, Y, W, H, cx, cy); } /** Draws an Fl_RGB_Image object using this graphics driver. Specifies a bounding box for the image, with the origin (upper left-hand corner) of the image offset by the cx and cy arguments. */ void Fl_Graphics_Driver::draw_rgb(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { // Don't draw an empty image... if (!img->d() || !img->array) { Fl_Graphics_Driver::draw_empty(img, XP, YP); return; } if (start_image(img, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) { return; } int need_scaled_drawing = ( fabs(img->w() - img->data_w()/scale())/img->w() > 0.05 || fabs(img->h() - img->data_h()/scale())/img->h() > 0.05 ); // to allow rescale at runtime int w2, h2, *pw, *ph; if (need_scaled_drawing) { w2 = img->w(); h2 = img->h(); cache_size(img, w2, h2); } else { w2 = img->data_w(); h2 = img->data_h(); } // after this, w2 x h2 is desired cached image size cache_w_h(img, pw, ph); // after this, *pw x *ph is current size of cached image if (*id(img) && (w2 != *pw || h2 != *ph )) { img->uncache(); } if (!*id(img) && need_scaled_drawing) { // build and draw a scaled id_ for img Fl_RGB_Scaling keep = Fl_Image::RGB_scaling(); Fl_Image::RGB_scaling(Fl_Image::scaling_algorithm()); Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w2, h2); Fl_Image::RGB_scaling(keep); cache(img2); draw_fixed(img2, XP, YP, WP, HP, cx, cy); *id(img) = *id(img2); *mask(img) = *mask(img2); *id(img2) = 0; *mask(img2) = 0; *pw = w2; *ph = h2; delete img2; } else { // draw img using its scaled id_ if (!*id(img)) cache(img); draw_fixed(img, XP, YP, WP, HP, cx, cy); } } /** Accessor to private member function of Fl_Image_Surface */ Fl_Offscreen Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(Fl_Image_Surface* surface) { Fl_Offscreen off = surface->get_offscreen_before_delete_(); delete surface; return off; } void Fl_Graphics_Driver::xyline(int x, int y, int x1) { line(x, y, x1, y); } void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2) { xyline(x, y, x1); yxline(x1, y, y2); } void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { xyline(x, y, x1); yxline(x1, y, y2); xyline(x1, y2, x3); } void Fl_Graphics_Driver::yxline(int x, int y, int y1) { line(x, y, x, y1); } void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2) { yxline(x, y, y1); xyline(x, y1, x2); } void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { yxline(x, y, y1); xyline(x, y1, x2); yxline(x2, y1, y3); } void Fl_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { line(x, y, x1, y1); line(x1, y1, x2, y2); } void Fl_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { line(x0, y0, x1, y1); line(x1, y1, x2, y2); line(x2, y2, x0, y0); } void Fl_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { line(x0, y0, x1, y1); line(x1, y1, x2, y2); line(x2, y2, x3, y3); line(x3, y3, x0, y0); } void Fl_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { polygon(x0, y0, x1, y1, x3, y3); polygon(x1, y1, x2, y2, x3, y3); } void Fl_Graphics_Driver::push_no_clip() { if (rstackptr < region_stack_max) rstack[++rstackptr] = 0; else Fl::warning("Fl_Graphics_Driver::push_no_clip: clip stack overflow!\n"); restore_clip(); } void Fl_Graphics_Driver::pop_clip() { if (rstackptr > 0) { Fl_Region oldr = rstack[rstackptr--]; if (oldr) XDestroyRegion(oldr); } else Fl::warning("Fl_Graphics_Driver::pop_clip: clip stack underflow!\n"); restore_clip(); } /** Sets the current value of the scaling factor */ void Fl_Graphics_Driver::scale(float f) { scale_ = f; } /** Return whether the graphics driver can do alpha blending */ char Fl_Graphics_Driver::can_do_alpha_blending() { return 0; } void Fl_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) {} void Fl_Graphics_Driver::draw_fixed(Fl_Bitmap *bm,int XP, int YP, int WP, int HP, int cx, int cy) {} void Fl_Graphics_Driver::draw_fixed(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) {} void Fl_Graphics_Driver::make_unused_color_(unsigned char &r, unsigned char &g, unsigned char &b, int color_count, void **data) {} /** Support function for Fl_Pixmap drawing */ void Fl_Graphics_Driver::cache(Fl_Pixmap *img) { } /** Support function for Fl_Bitmap drawing */ void Fl_Graphics_Driver::cache(Fl_Bitmap *img) { } /** Support function for Fl_RGB_Image drawing */ void Fl_Graphics_Driver::cache(Fl_RGB_Image *img) { } /** Support function for Fl_RGB_Image drawing */ void Fl_Graphics_Driver::uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) { } /** see fl_draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L) */ void Fl_Graphics_Driver::draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L) {} /** see fl_draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L) */ void Fl_Graphics_Driver::draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L) {} /** see fl_draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) */ void Fl_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {} /** see fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) */ void Fl_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {} typedef struct { const uchar *buf; int D_in; int D_out; int L; } image_data; static void scan_cb(image_data *data, int x, int y, int w, uchar *buffer) { const uchar *from = data->buf + y * data->L + data->D_in * x; while (w-- > 0) { memcpy(buffer, from, data->D_out); buffer += data->D_out; from += data->D_in; } } /* used only by inline fl_draw_image() */ void Fl_Graphics_Driver::draw_image_general_(const uchar *buf, int X, int Y, int W, int H, int D, int L) { const bool alpha = !!(abs(D) & FL_IMAGE_WITH_ALPHA); int d_corrected, d_out; if (alpha) { d_corrected = D ^ FL_IMAGE_WITH_ALPHA; d_out = 4; } else { d_corrected = D; d_out = 3; } if (abs(d_corrected) > d_out) { image_data data; data.buf = buf; data.D_in = d_corrected; data.D_out = d_out; data.L = (L ? L : W * d_corrected); if (alpha) d_out |= FL_IMAGE_WITH_ALPHA; fl_graphics_driver->draw_image((Fl_Draw_Image_Cb)scan_cb, &data, X, Y, W, H, d_out); } else fl_graphics_driver->draw_image(buf, X, Y, W, H, D, L); } /* used only by inline fl_draw_image_mono() */ void Fl_Graphics_Driver::draw_image_mono_general_(const uchar *buf, int X, int Y, int W, int H, int D, int L) { if (abs(D) > 1) { image_data data; data.buf = buf; data.D_in = D; data.D_out = 1; data.L = (L ? L : W * D); fl_graphics_driver->draw_image_mono((Fl_Draw_Image_Cb)scan_cb, &data, X, Y, W, H, 1); } else fl_graphics_driver->draw_image_mono(buf, X, Y, W, H, D, L); } /** Support function for image drawing */ void Fl_Graphics_Driver::delete_bitmask(fl_uintptr_t /*bm*/) {} /** see fl_point() */ void Fl_Graphics_Driver::point(int x, int y) {} /** see fl_rect() */ void Fl_Graphics_Driver::rect(int x, int y, int w, int h) {} /** see fl_rectf() */ void Fl_Graphics_Driver::rectf(int x, int y, int w, int h) {} void Fl_Graphics_Driver::_rbox(int fill, int x, int y, int w, int h, int r) { static double lut[] = { 0.0, 0.07612, 0.29289, 0.61732, 1.0}; if (r == 5) r = 4; // use only even sizes for small corners (STR #2943) if (r == 7) r = 8; // note: 8 is better than 6 (really) double xd = x, yd = y, rd = (x+w-1), bd = (y+h-1); double rr = r; if (fill) begin_polygon(); else begin_loop(); // top left transformed_vertex(xd+lut[0]*rr, yd+lut[4]*rr); transformed_vertex(xd+lut[1]*rr, yd+lut[3]*rr); transformed_vertex(xd+lut[2]*rr, yd+lut[2]*rr); transformed_vertex(xd+lut[3]*rr, yd+lut[1]*rr); transformed_vertex(xd+lut[4]*rr, yd+lut[0]*rr); // top right transformed_vertex(rd-lut[4]*rr, yd+lut[0]*rr); transformed_vertex(rd-lut[3]*rr, yd+lut[1]*rr); transformed_vertex(rd-lut[2]*rr, yd+lut[2]*rr); transformed_vertex(rd-lut[1]*rr, yd+lut[3]*rr); transformed_vertex(rd-lut[0]*rr, yd+lut[4]*rr); // bottom right transformed_vertex(rd-lut[0]*rr, bd-lut[4]*rr); transformed_vertex(rd-lut[1]*rr, bd-lut[3]*rr); transformed_vertex(rd-lut[2]*rr, bd-lut[2]*rr); transformed_vertex(rd-lut[3]*rr, bd-lut[1]*rr); transformed_vertex(rd-lut[4]*rr, bd-lut[0]*rr); // bottom left transformed_vertex(xd+lut[4]*rr, bd-lut[0]*rr); transformed_vertex(xd+lut[3]*rr, bd-lut[1]*rr); transformed_vertex(xd+lut[2]*rr, bd-lut[2]*rr); transformed_vertex(xd+lut[1]*rr, bd-lut[3]*rr); transformed_vertex(xd+lut[0]*rr, bd-lut[4]*rr); if (fill) fl_end_polygon(); else fl_end_loop(); } /** see fl_rounded_rect() */ void Fl_Graphics_Driver::rounded_rect(int x, int y, int w, int h, int r) { _rbox(0, x, y, w, h, r); } /** see fl_rounded_rectf() */ void Fl_Graphics_Driver::rounded_rectf(int x, int y, int w, int h, int r) { _rbox(1, x, y, w, h, r); } void Fl_Graphics_Driver::colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { color(r, g, b); rectf(x, y, w, h); } /** see fl_line(int, int, int, int) */ void Fl_Graphics_Driver::line(int x, int y, int x1, int y1) {} /** see fl_polygon(int, int, int, int, int, int) */ void Fl_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {} /** see fl_push_clip() */ void Fl_Graphics_Driver::push_clip(int x, int y, int w, int h) {} /** Default graphics driver implementation of fl_clip_box(). This default implementation is sufficient for a graphics driver that does not support clipping. Drivers that support clipping must override this virtual method. It returns - in (X, Y, W, H) the same values as given in (x, y, w, h) respectively - 0 (zero) as the function return value which means that \b nothing was clipped. \returns 0 (zero) - nothing was clipped \see fl_clip_box() */ int Fl_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) { X = x; Y = y; W = w; H = h; return 0; } /** see fl_not_clipped() */ int Fl_Graphics_Driver::not_clipped(int x, int y, int w, int h) {return 1;} /** see fl_begin_complex_polygon() */ void Fl_Graphics_Driver::begin_complex_polygon() { begin_polygon(); gap_ = 0; } /** see fl_transformed_vertex() */ void Fl_Graphics_Driver::transformed_vertex(double xf, double yf) { transformed_vertex0(float(xf), float(yf)); } /** see fl_vertex() */ void Fl_Graphics_Driver::vertex(double x, double y) { transformed_vertex(x*m.a + y*m.c + m.x, x*m.b + y*m.d + m.y); } /** see fl_end_points() */ void Fl_Graphics_Driver::end_points() {} /** see fl_end_line() */ void Fl_Graphics_Driver::end_line() {} void Fl_Graphics_Driver::fixloop() { // remove equal points from closed path while (n>2 && xpoint[n-1].x == xpoint[0].x && xpoint[n-1].y == xpoint[0].y) n--; } /** see fl_end_loop() */ void Fl_Graphics_Driver::end_loop() { fixloop(); if (n>2) transformed_vertex(xpoint[0].x, xpoint[0].y); end_line(); } /** see fl_end_polygon() */ void Fl_Graphics_Driver::end_polygon() {} /** see fl_end_complex_polygon() */ void Fl_Graphics_Driver::end_complex_polygon() {} /** see fl_gap() */ void Fl_Graphics_Driver::gap() { while (n>gap_+2 && xpoint[n-1].x == xpoint[gap_].x && xpoint[n-1].y == xpoint[gap_].y) n--; if (n > gap_+2) { transformed_vertex(xpoint[gap_].x, xpoint[gap_].y); gap_ = n; } else { n = gap_; } } /** see fl_circle() */ void Fl_Graphics_Driver::circle(double x, double y, double r) {} /** see fl_arc(int x, int y, int w, int h, double a1, double a2) */ void Fl_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) {} /** see fl_pie() */ void Fl_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) {} /** see fl_draw_circle() */ void Fl_Graphics_Driver::draw_circle(int x, int y, int d, Fl_Color c) { Fl_Color current_c = color(); if (c != current_c) color(c); pie(x, y, d, d, 0., 360.); if (c != current_c) color(current_c); } /** see fl_line_style() */ void Fl_Graphics_Driver::line_style(int style, int width, char* dashes) {} /** see fl_color(Fl_Color) */ void Fl_Graphics_Driver::color(Fl_Color c) { color_ = c; } /** see fl_color(void) */ Fl_Color Fl_Graphics_Driver::color() { return color_; } /** see fl_color(uchar, uchar, uchar) */ void Fl_Graphics_Driver::color(uchar r, uchar g, uchar b) {} /** see fl_draw(const char *str, int n, int x, int y) */ void Fl_Graphics_Driver::draw(const char *str, int nChars, int x, int y) {} /** Draw the first \p n bytes of the string \p str starting at position \p x , \p y */ void Fl_Graphics_Driver::draw(const char *str, int nChars, float x, float y) { draw(str, nChars, (int)(x+0.5), (int)(y+0.5)); } /** see fl_draw(int angle, const char *str, int n, int x, int y) */ void Fl_Graphics_Driver::draw(int angle, const char *str, int nChars, int x, int y) { draw(str, nChars, x, y); } /** see fl_rtl_draw(const char *str, int n, int x, int y) */ void Fl_Graphics_Driver::rtl_draw(const char *str, int nChars, int x, int y) { draw(str, nChars, x, y); } /** Returns non-zero if the graphics driver possesses the \p feature */ int Fl_Graphics_Driver::has_feature(driver_feature feature) { return 0; } /** see fl_font(Fl_Font, Fl_Fontsize) */ void Fl_Graphics_Driver::font(Fl_Font face, Fl_Fontsize fsize) {font_ = face; size_ = fsize;} /** see fl_font(void) */ Fl_Font Fl_Graphics_Driver::font() {return font_; } /** Return the current font size */ Fl_Fontsize Fl_Graphics_Driver::size() {return size_; } /** Compute the width of the first \p n bytes of the string \p str if drawn with current font */ double Fl_Graphics_Driver::width(const char *str, int nChars) { return 0; } /** Compute the width of Unicode character \p c if drawn with current font */ double Fl_Graphics_Driver::width(unsigned int c) { char buf[4]; return width(buf, fl_utf8encode (c, buf)); } /** Return the current line height */ int Fl_Graphics_Driver::height() { return size(); } /** Return the current line descent */ int Fl_Graphics_Driver::descent() { return 0; } /** Sets the value of the driver-specific graphics context. */ void Fl_Graphics_Driver::gc(void*) {} /** Returns the driver-specific graphics context, of NULL if there's none. */ void *Fl_Graphics_Driver::gc(void) {return NULL;} /** Support for pixmap drawing */ uchar **Fl_Graphics_Driver::mask_bitmap() { return 0; } /** Support for PostScript drawing */ float Fl_Graphics_Driver::scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) { return float(s); } /** Support for PostScript drawing */ float Fl_Graphics_Driver::scale_bitmap_for_PostScript() { return 2; } /** Support for Fl::get_font_name() */ const char* Fl_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) {return NULL;} /** Support for Fl::get_font_sizes() */ int Fl_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {return 0;} /** Support for Fl::set_fonts() */ Fl_Font Fl_Graphics_Driver::set_fonts(const char *name) {return 0;} /** Some platforms may need to implement this to support fonts */ Fl_Fontdesc* Fl_Graphics_Driver::calc_fl_fonts(void) {return NULL;} /** Support for Fl::get_font() */ const char *Fl_Graphics_Driver::font_name(int num) {return NULL;} /** Support for Fl::set_font() */ void Fl_Graphics_Driver::font_name(int num, const char *name) {} /** Support function for fl_overlay_rect() and scaled GUI.*/ void Fl_Graphics_Driver::overlay_rect(int x, int y, int w , int h) { loop(x, y, x+w-1, y, x+w-1, y+h-1, x, y+h-1); } float Fl_Graphics_Driver::override_scale() { return scale();} void Fl_Graphics_Driver::restore_scale(float) { } void Fl_Graphics_Driver::transformed_vertex0(float x, float y) { if (!n || x != xpoint[n-1].x || y != xpoint[n-1].y) { if (n >= p_size) { p_size = xpoint ? 2*p_size : 16; xpoint = (XPOINT*)realloc((void*)xpoint, p_size*sizeof(*xpoint)); } xpoint[n].x = x; xpoint[n].y = y; n++; } } void Fl_Graphics_Driver::antialias(int state) {} int Fl_Graphics_Driver::antialias() { return 0; } /** \} \endcond */ #ifndef FL_DOXYGEN Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) { next = 0; # if HAVE_GL listbase = 0; # endif // OpenGL needs those for its font handling size = Size; } Fl_Scalable_Graphics_Driver::Fl_Scalable_Graphics_Driver() : Fl_Graphics_Driver() { line_width_ = 0; fontsize_ = -1; #if FL_ABI_VERSION >= 10403 // Issue #1214 is_solid_ = true; #endif } void Fl_Scalable_Graphics_Driver::rect(int x, int y, int w, int h) { if (w > 0 && h > 0) { int s = (int)scale(); int d = s / 2; rect_unscaled(this->floor(x) + d, this->floor(y) + d, this->floor(x + w) - this->floor(x) - s, this->floor(y + h) - this->floor(y) - s); } } // This function aims to compute accurately int(x * s) in // presence of rounding errors existing with floating point numbers // and that sometimes differ between 32 and 64 bits. int Fl_Scalable_Graphics_Driver::floor(int x, float s) { if (s == 1) return x; int retval = int(abs(x) * s + 0.001f); return (x >= 0 ? retval : -retval); } void Fl_Scalable_Graphics_Driver::rectf(int x, int y, int w, int h) { if (w <= 0 || h <= 0) return; rectf_unscaled(this->floor(x), this->floor(y), this->floor(x + w) - this->floor(x), this->floor(y + h) - this->floor(y)); } void Fl_Scalable_Graphics_Driver::point(int x, int y) { rectf(x, y, 1, 1); } void Fl_Scalable_Graphics_Driver::line(int x, int y, int x1, int y1) { if (y == y1) xyline(x, y, x1); else if (x == x1) yxline(x, y, y1); else line_unscaled(this->floor(x), this->floor(y), this->floor(x1), this->floor(y1)); } void Fl_Scalable_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { line_unscaled(this->floor(x), this->floor(y), this->floor(x1), this->floor(y1), this->floor(x2), this->floor(y2)); } void Fl_Scalable_Graphics_Driver::xyline(int x, int y, int x1) { if (y < 0) return; float s = scale(); int s_int = int(s); int xx = (x < x1 ? x : x1); int xx1 = (x < x1 ? x1 : x); if (s != s_int && line_width_ <= s_int) { int lwidth = this->floor((y+1)) - this->floor(y); #if FL_ABI_VERSION >= 10403 // Issue #1214 bool need_change_width = (lwidth != s_int && is_solid_); #else bool need_change_width = (lwidth != s_int); #endif void *data = NULL; if (need_change_width) data = change_pen_width(lwidth); xyline_unscaled(this->floor(xx), this->floor(y) + int(lwidth/2.f), this->floor(xx1+1)-1); if (need_change_width) reset_pen_width(data); } else { y = this->floor(y); if (line_width_ <= s_int) y += int(s/2.f); else y += s_int/2; xyline_unscaled(this->floor(xx), y, this->floor(xx1+1) - 1); } } void Fl_Scalable_Graphics_Driver::yxline(int x, int y, int y1) { if (x < 0) return; float s = scale(); int s_int = int(s); int yy = (y < y1 ? y : y1); int yy1 = (y < y1 ? y1 : y); if (s != s_int && line_width_ <= s_int) { int lwidth = (this->floor((x+1)) - this->floor(x)); #if FL_ABI_VERSION >= 10403 // Issue #1214 bool need_change_width = (lwidth != s_int && is_solid_); #else bool need_change_width = (lwidth != s_int); #endif void *data = NULL; if (need_change_width) data = change_pen_width(lwidth); yxline_unscaled(this->floor(x) + int(lwidth/2.f), this->floor(yy), this->floor(yy1+1) - 1); if (need_change_width) reset_pen_width(data); } else { x = this->floor(x); if (line_width_ <= s_int) x += int(s/2.f); else x += s_int/2; yxline_unscaled(x, this->floor(yy), this->floor(yy1+1) - 1); } } void *Fl_Scalable_Graphics_Driver::change_pen_width(int lwidth) {return NULL;} void Fl_Scalable_Graphics_Driver::reset_pen_width(void *data){} void Fl_Scalable_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { loop_unscaled(floor(x0), floor(y0), floor(x1), floor(y1), floor(x2), floor(y2)); } void Fl_Scalable_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { int X, Y, W, H; if (x0 == x3 && x1 == x2 && y0 == y1 && y3 == y2) { // rectangular loop X = x0 > x1 ? x1 : x0; Y = y0 > y3 ? y3 : y0; W = abs(x0 - x1); H = abs(y0 - y3); rect(X, Y, W + 1, H + 1); } else if (x0 == x1 && y1 == y2 && x2 == x3 && y3 == y0) { // rectangular loop also X = x0 > x3 ? x3 : x0; Y = y0 > y1 ? y1 : y0; W = abs(x0 - x3); H = abs(y0 - y1); rect(X, Y, W + 1, H + 1); } else { loop_unscaled(floor(x0), floor(y0), floor(x1), floor(y1), floor(x2), floor(y2), floor(x3), floor(y3)); } } void Fl_Scalable_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { polygon_unscaled(floor(x0), floor(y0), floor(x1), floor(y1), floor(x2), floor(y2)); } void Fl_Scalable_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { polygon_unscaled(floor(x0), floor(y0), floor(x1), floor(y1), floor(x2), floor(y2), floor(x3), floor(y3)); } void Fl_Scalable_Graphics_Driver::circle(double x, double y, double r) { double xt = transform_x(x,y); double yt = transform_y(x,y); double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a)); double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d)); ellipse_unscaled(xt*scale(), yt*scale(), rx*scale(), ry*scale()); } void Fl_Scalable_Graphics_Driver::font(Fl_Font face, Fl_Fontsize size) { if (!font_descriptor()) fl_open_display(); // to catch the correct initial value of scale_ font_unscaled(face, Fl_Fontsize(size * scale())); fontsize_ = size; } Fl_Font Fl_Scalable_Graphics_Driver::font() { return Fl_Graphics_Driver::font(); } double Fl_Scalable_Graphics_Driver::width(const char *str, int n) { return width_unscaled(str, n)/scale(); } double Fl_Scalable_Graphics_Driver::width(unsigned int c) { return width_unscaled(c)/scale(); } Fl_Fontsize Fl_Scalable_Graphics_Driver::size() { if (!font_descriptor() ) return -1; return fontsize_; } void Fl_Scalable_Graphics_Driver::text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h) { text_extents_unscaled(str, n, dx, dy, w, h); dx = int(dx / scale()); dy = int(dy / scale()); w = int(w / scale()); h = int(h / scale()); } int Fl_Scalable_Graphics_Driver::height() { return int(height_unscaled()/scale()); } int Fl_Scalable_Graphics_Driver::descent() { return int(descent_unscaled()/scale()); } void Fl_Scalable_Graphics_Driver::draw(const char *str, int n, int x, int y) { if (!size_ || !font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE); Fl_Region r2 = scale_clip(scale()); draw_unscaled(str, n, floor(x), floor(y)); unscale_clip(r2); } void Fl_Scalable_Graphics_Driver::draw(const char *str, int n, float x, float y) { Fl_Graphics_Driver::draw(str, n, x, y); } void Fl_Scalable_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) { if (!size_ || !font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE); Fl_Region r2 = scale_clip(scale()); draw_unscaled(angle, str, n, floor(x), floor(y)); unscale_clip(r2); } void Fl_Scalable_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) { rtl_draw_unscaled(str, n, int(x * scale()), int(y * scale())); } void Fl_Scalable_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) { float s = scale(); int xx = floor(x) + int((s-1)/2); int yy = floor(y) + int((s-1)/2); w = floor(x+w) - xx - 1 + line_width_/2 - int(s-1); h = floor(y+h) - yy - 1 + line_width_/2 - int(s-1); arc_unscaled(xx, yy, w, h, a1, a2); } void Fl_Scalable_Graphics_Driver::arc(double x, double y, double r, double start, double end) { Fl_Graphics_Driver::arc(x, y, r, start, end); } void Fl_Scalable_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) { int xx = floor(x) - 1; int yy = floor(y) - 1; w = floor(x+w) - xx; h = floor(y+h) - yy; pie_unscaled(xx, yy, w, h, a1, a2); } void Fl_Scalable_Graphics_Driver::draw_circle(int x0, int y0, int d, Fl_Color c) { Fl_Color saved = color(); color(c); // make circles nice on scaled display float s = scale(); int scaled_d = (s > 1.0) ? (int)(d * s) : d; // draw the circle switch (scaled_d) { // Larger circles draw fine... default: pie(x0, y0, d, d, 0.0, 360.0); break; // Small circles don't draw well on many systems... case 6: rectf(x0 + 2, y0, d - 4, d); rectf(x0 + 1, y0 + 1, d - 2, d - 2); rectf(x0, y0 + 2, d, d - 4); break; case 5: case 4: case 3: rectf(x0 + 1, y0, d - 2, d); rectf(x0, y0 + 1, d, d - 2); break; case 2: case 1: rectf(x0, y0, d, d); break; } color(saved); } void Fl_Scalable_Graphics_Driver::line_style(int style, int width, char* dashes) { if (width == 0) line_width_ = int(scale() < 2 ? 0 : scale()); else line_width_ = int(width>0 ? width*scale() : -width*scale()); #if FL_ABI_VERSION >= 10403 // Issue #1214 is_solid_ = ((style & 0xff) == FL_SOLID && (!dashes || !*dashes)); #endif line_style_unscaled(style, line_width_, dashes); } /* read the image data from a pointer or with a callback, scale it, and draw it */ void Fl_Scalable_Graphics_Driver::draw_image_rescale(void *buf, Fl_Draw_Image_Cb cb, int X, int Y, int W, int H, int D, int L, bool mono) { int aD = abs(D); if (L == 0) L = W*aD; int depth = mono ? (aD%2==0?2:1) : aD; uchar *tmp_buf = new uchar[W*H*depth]; if (cb) { for (int i = 0; i < H; i++) { cb(buf, 0, i, W, tmp_buf + i * W * depth); } } else { uchar *q, *p = tmp_buf; for (int i = 0; i < H; i++) { q = (uchar*)buf + i * L; for (int j = 0; j < W; j++) { memcpy(p, q, depth); p += depth; q += D; } } } Fl_RGB_Image *rgb = new Fl_RGB_Image(tmp_buf, W, H, depth); rgb->alloc_array = 1; Fl_RGB_Scaling keep = Fl_Image::RGB_scaling(); Fl_Image::RGB_scaling(Fl_Image::scaling_algorithm()); Fl_RGB_Image *scaled_rgb = (Fl_RGB_Image*)rgb->copy(floor(X+W)-floor(X), floor(Y+H)-floor(Y)); Fl_Image::RGB_scaling(keep); delete rgb; if (scaled_rgb) { Fl_Region r2 = scale_clip(scale()); draw_image_unscaled(scaled_rgb->array, floor(X), floor(Y), scaled_rgb->w(), scaled_rgb->h(), depth); unscale_clip(r2); delete scaled_rgb; } } void Fl_Scalable_Graphics_Driver::draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L) { if (scale() == 1) { draw_image_unscaled(buf, X,Y,W,H,D,L); } else { draw_image_rescale((void*)buf, NULL, X, Y, W, H, D, L, false); } } void Fl_Scalable_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) { if (scale() == 1) { draw_image_unscaled(cb, data, X,Y,W,H,D); } else { draw_image_rescale(data, cb, X, Y, W, H, D, 0, false); } } void Fl_Scalable_Graphics_Driver::draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L) { if (scale() == 1) { draw_image_mono_unscaled(buf, X,Y,W,H,D,L); } else { draw_image_rescale((void*)buf, NULL, X, Y, W, H, D, L, true); } } void Fl_Scalable_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) { if (scale() == 1) { draw_image_mono_unscaled(cb, data, X,Y,W,H,D); } else { draw_image_rescale(data, cb, X, Y, W, H, D, 0, true); } } void Fl_Scalable_Graphics_Driver::transformed_vertex(double xf, double yf) { transformed_vertex0(float(xf * scale()), float(yf * scale())); } void Fl_Scalable_Graphics_Driver::vertex(double x,double y) { transformed_vertex0(float((x*m.a + y*m.c + m.x) * scale()), float((x*m.b + y*m.d + m.y) * scale())); } void Fl_Scalable_Graphics_Driver::unscale_clip(Fl_Region r) { if (r) { if (rstack[rstackptr]) XDestroyRegion(rstack[rstackptr]); rstack[rstackptr] = r; } } Fl_Region Fl_Scalable_Graphics_Driver::scale_clip(float f) { return 0; } void Fl_Scalable_Graphics_Driver::point_unscaled(float x, float y) {} void Fl_Scalable_Graphics_Driver::rect_unscaled(int x, int y, int w, int h) {} void Fl_Scalable_Graphics_Driver::rectf_unscaled(int x, int y, int w, int h) {} void Fl_Scalable_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1) {} void Fl_Scalable_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1, int x2, int y2) {} void Fl_Scalable_Graphics_Driver::xyline_unscaled(int x, int y, int x1) {} void Fl_Scalable_Graphics_Driver::yxline_unscaled(int x, int y, int y1) {} void Fl_Scalable_Graphics_Driver::loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) {} void Fl_Scalable_Graphics_Driver::loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {} void Fl_Scalable_Graphics_Driver::polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) {} void Fl_Scalable_Graphics_Driver::polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {} void Fl_Scalable_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) {} void Fl_Scalable_Graphics_Driver::font_unscaled(Fl_Font face, Fl_Fontsize size) {} double Fl_Scalable_Graphics_Driver::width_unscaled(const char *str, int n) { return 0.0; } double Fl_Scalable_Graphics_Driver::width_unscaled(unsigned int c) { return 0.0; } Fl_Fontsize Fl_Scalable_Graphics_Driver::size_unscaled() { return 0; } void Fl_Scalable_Graphics_Driver::text_extents_unscaled(const char *str, int n, int &dx, int &dy, int &w, int &h) {} int Fl_Scalable_Graphics_Driver::height_unscaled() { return 0; } int Fl_Scalable_Graphics_Driver::descent_unscaled() { return 0; } void Fl_Scalable_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y) {} void Fl_Scalable_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) {} void Fl_Scalable_Graphics_Driver::rtl_draw_unscaled(const char* str, int n, int x, int y) {} void Fl_Scalable_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) {} void Fl_Scalable_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1, double a2) {} void Fl_Scalable_Graphics_Driver::line_style_unscaled(int style, int width, char* dashes) {} void Fl_Scalable_Graphics_Driver::draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D, int L) {} void Fl_Scalable_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {} void Fl_Scalable_Graphics_Driver::draw_image_mono_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l) {} void Fl_Scalable_Graphics_Driver::draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {} float Fl_Scalable_Graphics_Driver::override_scale() { float s = scale(); if (s != 1.f) { scale(1.f); } return s; } void Fl_Scalable_Graphics_Driver::restore_scale(float s) { if (s != 1.f) { scale(s); } } #endif fltk-1.4.3/src/Fl_Overlay_Window.cxx0000644000175000017500000000377315004135251017523 0ustar albrechtalbrecht// // Overlay window code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // A window using double-buffering and able to draw an overlay // on top of that. Uses the hardware to draw the overlay if // possible, otherwise it just draws in the front buffer. #include #include #include "Fl_Window_Driver.H" Fl_Overlay_Window::Fl_Overlay_Window(int W, int H, const char *l) : Fl_Double_Window(W,H,l) { overlay_ = 0; image(0); } Fl_Overlay_Window::Fl_Overlay_Window(int X, int Y, int W, int H, const char *l) : Fl_Double_Window(X,Y,W,H,l) { overlay_ = 0; image(0); } void Fl_Overlay_Window::show() { Fl_Double_Window::show(); if (overlay_ && overlay_ != this) overlay_->show(); } void Fl_Overlay_Window::hide() { Fl_Double_Window::hide(); } void Fl_Overlay_Window::flush() { Fl_Window_Driver::driver(this)->flush_overlay(); } void Fl_Overlay_Window::resize(int X, int Y, int W, int H) { Fl_Double_Window::resize(X,Y,W,H); if (overlay_ && overlay_!=this) overlay_->resize(0,0,w(),h()); } /** Destroys the window and all child widgets. */ Fl_Overlay_Window::~Fl_Overlay_Window() { hide(); // delete overlay; this is done by ~Fl_Group } int Fl_Overlay_Window::can_do_overlay() { return Fl_Window_Driver::driver(this)->can_do_overlay(); } /** Call this to indicate that the overlay data has changed and needs to be redrawn. The overlay will be clear until the first time this is called, so if you want an initial display you must call this after calling show(). */ void Fl_Overlay_Window::redraw_overlay() { Fl_Window_Driver::driver(this)->redraw_overlay(); } fltk-1.4.3/src/Fl_Help_Dialog.cxx0000644000175000017500000001730315004135251016714 0ustar albrechtalbrecht// // Fl_Help_Dialog dialog for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // ======================================================================== // DO NOT EDIT FL/Fl_Help_Dialog.H and src/Fl_Help_Dialog.cxx !!! // ======================================================================== // Please use fluid to change src/Fl_Help_Dialog.fl interactively // and then use fluid to "write code" or edit and use fluid -c . // ======================================================================== // // generated by Fast Light User Interface Designer (fluid) version 1.0403 #include "../FL/Fl_Help_Dialog.H" #include #include "flstring.h" #include void Fl_Help_Dialog::cb_back__i(Fl_Button*, void*) { if (index_ > 0) index_ --; if (index_ == 0) back_->deactivate(); forward_->activate(); int l = line_[index_]; if (strcmp(view_->filename(), file_[index_]) != 0) view_->load(file_[index_]); view_->topline(l); } void Fl_Help_Dialog::cb_back_(Fl_Button* o, void* v) { ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_back__i(o,v); } void Fl_Help_Dialog::cb_forward__i(Fl_Button*, void*) { if (index_ < max_) index_ ++; if (index_ >= max_) forward_->deactivate(); back_->activate(); int l = view_->topline(); if (strcmp(view_->filename(), file_[index_]) != 0) view_->load(file_[index_]); view_->topline(l); } void Fl_Help_Dialog::cb_forward_(Fl_Button* o, void* v) { ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_forward__i(o,v); } void Fl_Help_Dialog::cb_smaller__i(Fl_Button*, void*) { if (view_->textsize() > 8) view_->textsize(view_->textsize() - 2); if (view_->textsize() <= 8) smaller_->deactivate(); larger_->activate(); } void Fl_Help_Dialog::cb_smaller_(Fl_Button* o, void* v) { ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_smaller__i(o,v); } void Fl_Help_Dialog::cb_larger__i(Fl_Button*, void*) { if (view_->textsize() < 18) view_->textsize(view_->textsize() + 2); if (view_->textsize() >= 18) larger_->deactivate(); smaller_->activate(); } void Fl_Help_Dialog::cb_larger_(Fl_Button* o, void* v) { ((Fl_Help_Dialog*)(o->parent()->parent()->user_data()))->cb_larger__i(o,v); } void Fl_Help_Dialog::cb_find__i(Fl_Input*, void*) { find_pos_ = view_->find(find_->value(), find_pos_); } void Fl_Help_Dialog::cb_find_(Fl_Input* o, void* v) { ((Fl_Help_Dialog*)(o->parent()->parent()->parent()->user_data()))->cb_find__i(o,v); } void Fl_Help_Dialog::cb_view__i(Fl_Help_View*, void*) { if (view_->filename()) { if (view_->changed()) { index_ ++; if (index_ >= 100) { memmove(line_, line_ + 10, sizeof(line_[0]) * 90); memmove(file_, file_ + 10, sizeof(file_[0]) * 90); index_ -= 10; } max_ = index_; strlcpy(file_[index_], view_->filename(),sizeof(file_[0])); line_[index_] = view_->topline(); if (index_ > 0) back_->activate(); else back_->deactivate(); forward_->deactivate(); window_->label(view_->title()); } else // if ! view_->changed() { strlcpy(file_[index_], view_->filename(), sizeof(file_[0])); line_[index_] = view_->topline(); } } else { // if ! view_->filename() index_ = 0; // hitting an internal page will disable the back/fwd buffer file_[index_][0] = 0; // unnamed internal page line_[index_] = view_->topline(); back_->deactivate(); forward_->deactivate(); } } void Fl_Help_Dialog::cb_view_(Fl_Help_View* o, void* v) { ((Fl_Help_Dialog*)(o->parent()->user_data()))->cb_view__i(o,v); } Fl_Help_Dialog::Fl_Help_Dialog() { { window_ = new Fl_Double_Window(530, 385, "Help Dialog"); window_->user_data((void*)(this)); { Fl_Group* o = new Fl_Group(10, 10, 511, 25); { back_ = new Fl_Button(10, 10, 25, 25, "@<-"); back_->tooltip("Show the previous help page."); back_->shortcut(0xff51); back_->labelcolor((Fl_Color)2); back_->callback((Fl_Callback*)cb_back_); } // Fl_Button* back_ { forward_ = new Fl_Button(45, 10, 25, 25, "@->"); forward_->tooltip("Show the next help page."); forward_->shortcut(0xff53); forward_->labelcolor((Fl_Color)2); forward_->callback((Fl_Callback*)cb_forward_); } // Fl_Button* forward_ { smaller_ = new Fl_Button(80, 10, 25, 25, "F"); smaller_->tooltip("Make the help text smaller."); smaller_->labelfont(1); smaller_->labelsize(10); smaller_->callback((Fl_Callback*)cb_smaller_); } // Fl_Button* smaller_ { larger_ = new Fl_Button(115, 10, 25, 25, "F"); larger_->tooltip("Make the help text larger."); larger_->labelfont(1); larger_->labelsize(16); larger_->callback((Fl_Callback*)cb_larger_); } // Fl_Button* larger_ { Fl_Group* o = new Fl_Group(350, 10, 171, 25); o->box(FL_DOWN_BOX); o->color(FL_BACKGROUND2_COLOR); { find_ = new Fl_Input(375, 12, 143, 21, "@search"); find_->tooltip("find text in document"); find_->box(FL_FLAT_BOX); find_->labelsize(13); find_->textfont(4); find_->callback((Fl_Callback*)cb_find_); find_->when(FL_WHEN_ENTER_KEY_ALWAYS); } // Fl_Input* find_ o->end(); } // Fl_Group* o { Fl_Box* o = new Fl_Box(150, 10, 190, 25); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { view_ = new Fl_Help_View(10, 45, 510, 330); view_->box(FL_DOWN_BOX); view_->callback((Fl_Callback*)cb_view_); Fl_Group::current()->resizable(view_); } // Fl_Help_View* view_ window_->size_range(260, 150); window_->end(); } // Fl_Double_Window* window_ back_->deactivate(); forward_->deactivate(); index_ = -1; max_ = 0; find_pos_ = 0; fl_register_images(); } Fl_Help_Dialog::~Fl_Help_Dialog() { delete window_; } int Fl_Help_Dialog::h() { return (window_->h()); } void Fl_Help_Dialog::hide() { window_->hide(); } int Fl_Help_Dialog::load(const char *f) { view_->set_changed(); int ret = view_->load(f); window_->label(view_->title()); return ret; } void Fl_Help_Dialog::position(int xx, int yy) { window_->position(xx, yy); } void Fl_Help_Dialog::resize(int xx, int yy, int ww, int hh) { window_->resize(xx, yy, ww, hh); } void Fl_Help_Dialog::show() { window_->show(); } void Fl_Help_Dialog::show(int argc, char **argv) { window_->show(argc, argv); } void Fl_Help_Dialog::textsize(Fl_Fontsize s) { view_->textsize(s); if (s <= 8) smaller_->deactivate(); else smaller_->activate(); if (s >= 18) larger_->deactivate(); else larger_->activate(); } Fl_Fontsize Fl_Help_Dialog::textsize() { return (view_->textsize()); } void Fl_Help_Dialog::topline(const char *n) { view_->topline(n); } void Fl_Help_Dialog::topline(int n) { view_->topline(n); } void Fl_Help_Dialog::value(const char *f) { view_->set_changed(); view_->value(f); window_->label(view_->title()); } const char * Fl_Help_Dialog::value() const { return view_->value(); } int Fl_Help_Dialog::visible() { return (window_->visible()); } int Fl_Help_Dialog::w() { return (window_->w()); } int Fl_Help_Dialog::x() { return (window_->x()); } int Fl_Help_Dialog::y() { return (window_->y()); } fltk-1.4.3/src/Fl_Slider.cxx0000644000175000017500000002471315004135251015772 0ustar albrechtalbrecht// // Slider widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2015 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include #include #include #include "flstring.h" void Fl_Slider::_Fl_Slider() { slider_size_ = 0; slider_ = 0; // FL_UP_BOX; } /** Creates a new Fl_Slider widget using the given position, size, and label string. The default boxtype is FL_DOWN_BOX. */ Fl_Slider::Fl_Slider(int X, int Y, int W, int H, const char* L) : Fl_Valuator(X, Y, W, H, L) { box(FL_DOWN_BOX); _Fl_Slider(); } /** Creates a new Fl_Slider widget using the given type, position, size, and label string. */ Fl_Slider::Fl_Slider(uchar t, int X, int Y, int W, int H, const char* L) : Fl_Valuator(X, Y, W, H, L) { type(t); box(t==FL_HOR_NICE_SLIDER || t==FL_VERT_NICE_SLIDER ? FL_FLAT_BOX : FL_DOWN_BOX); _Fl_Slider(); } void Fl_Slider::slider_size(double v) { if (v < 0) v = 0; if (v > 1) v = 1; if (slider_size_ != float(v)) { slider_size_ = float(v); damage(FL_DAMAGE_EXPOSE); } } /** Sets the minimum (a) and maximum (b) values for the valuator widget. if at least one of the values is changed, a partial redraw is asked. */ void Fl_Slider::bounds(double a, double b) { if (minimum() != a || maximum() != b) { Fl_Valuator::bounds(a, b); damage(FL_DAMAGE_EXPOSE); } } /** Sets the size and position of the sliding knob in the box. \param[in] pos position of first line displayed \param[in] size size of window in lines \param[in] first number of first line \param[in] total total number of lines Returns Fl_Valuator::value(p) */ int Fl_Slider::scrollvalue(int pos, int size, int first, int total) { step(1, 1); if (pos+size > first+total) total = pos+size-first; slider_size(size >= total ? 1.0 : double(size)/double(total)); bounds(first, total-size+first); return value(pos); } // All slider interaction is done as though the slider ranges from // zero to one, and the left (bottom) edge of the slider is at the // given position. Since when the slider is all the way to the // right (top) the left (bottom) edge is not all the way over, a // position on the widget itself covers a wider range than 0-1, // actually it ranges from 0 to 1/(1-size). void Fl_Slider::draw_bg(int X, int Y, int W, int H) { fl_push_clip(X, Y, W, H); draw_box(); fl_pop_clip(); Fl_Color black = active_r() ? FL_FOREGROUND_COLOR : FL_INACTIVE_COLOR; if (type() == FL_VERT_NICE_SLIDER) { draw_box(FL_THIN_DOWN_BOX, X+W/2-2, Y, 4, H, black); } else if (type() == FL_HOR_NICE_SLIDER) { draw_box(FL_THIN_DOWN_BOX, X, Y+H/2-2, W, 4, black); } } void Fl_Slider::draw(int X, int Y, int W, int H) { double val; if (minimum() == maximum()) val = 0.5; else { val = (value()-minimum())/(maximum()-minimum()); if (val > 1.0) val = 1.0; else if (val < 0.0) val = 0.0; } int ww = (horizontal() ? W : H); int xx, S; if (type()==FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) { S = int(val*ww+.5); if (minimum()>maximum()) {S = ww-S; xx = ww-S;} else xx = 0; } else { S = int(slider_size_*ww+.5); int T = (horizontal() ? H : W)/2+1; if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4; if (S < T) S = T; xx = int(val*(ww-S)+.5); } int xsl, ysl, wsl, hsl; if (horizontal()) { xsl = X+xx; wsl = S; ysl = Y; hsl = H; } else { ysl = Y+xx; hsl = S; xsl = X; wsl = W; } draw_bg(X, Y, W, H); Fl_Boxtype box1 = slider(); if (!box1) {box1 = (Fl_Boxtype)(box()&-2); if (!box1) box1 = FL_UP_BOX;} if (type() == FL_VERT_NICE_SLIDER) { draw_box(box1, xsl, ysl, wsl, hsl, FL_GRAY); int d = (hsl-4)/2; draw_box(FL_THIN_DOWN_BOX, xsl+2, ysl+d, wsl-4, hsl-2*d,selection_color()); } else if (type() == FL_HOR_NICE_SLIDER) { draw_box(box1, xsl, ysl, wsl, hsl, FL_GRAY); int d = (wsl-4)/2; draw_box(FL_THIN_DOWN_BOX, xsl+d, ysl+2, wsl-2*d, hsl-4,selection_color()); } else { if (wsl>0 && hsl>0) draw_box(box1, xsl, ysl, wsl, hsl, selection_color()); if (type() != FL_HOR_FILL_SLIDER && type() != FL_VERT_FILL_SLIDER && Fl::is_scheme("gtk+")) { if (W>H && wsl>(hsl+8)) { // Draw horizontal grippers int yy, hh; hh = hsl-8; xx = xsl+(wsl-hsl-4)/2; yy = ysl+3; fl_color(fl_darker(selection_color())); fl_line(xx, yy+hh, xx+hh, yy); fl_line(xx+6, yy+hh, xx+hh+6, yy); fl_line(xx+12, yy+hh, xx+hh+12, yy); xx++; fl_color(fl_lighter(selection_color())); fl_line(xx, yy+hh, xx+hh, yy); fl_line(xx+6, yy+hh, xx+hh+6, yy); fl_line(xx+12, yy+hh, xx+hh+12, yy); } else if (H>W && hsl>(wsl+8)) { // Draw vertical grippers int yy; xx = xsl+4; ww = wsl-8; yy = ysl+(hsl-wsl-4)/2; fl_color(fl_darker(selection_color())); fl_line(xx, yy+ww, xx+ww, yy); fl_line(xx, yy+ww+6, xx+ww, yy+6); fl_line(xx, yy+ww+12, xx+ww, yy+12); yy++; fl_color(fl_lighter(selection_color())); fl_line(xx, yy+ww, xx+ww, yy); fl_line(xx, yy+ww+6, xx+ww, yy+6); fl_line(xx, yy+ww+12, xx+ww, yy+12); } } } draw_label(xsl, ysl, wsl, hsl); if (Fl::focus() == this) { if (type() == FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) draw_focus(); else draw_focus(box1, xsl, ysl, wsl, hsl); } } void Fl_Slider::draw() { if (damage()&FL_DAMAGE_ALL) draw_box(); draw(x()+Fl::box_dx(box()), y()+Fl::box_dy(box()), w()-Fl::box_dw(box()), h()-Fl::box_dh(box())); } int Fl_Slider::handle(int event, int X, int Y, int W, int H) { // Fl_Widget_Tracker wp(this); switch (event) { case FL_PUSH: { Fl_Widget_Tracker wp(this); if (!Fl::event_inside(X, Y, W, H)) return 0; handle_push(); if (wp.deleted()) return 1; } // fall through ... case FL_DRAG: { double val; if (minimum() == maximum()) val = 0.5; else { val = (value()-minimum())/(maximum()-minimum()); if (val > 1.0) val = 1.0; else if (val < 0.0) val = 0.0; } int ww = (horizontal() ? W : H); int mx = (horizontal() ? Fl::event_x()-X : Fl::event_y()-Y); int S; static int offcenter; if (type() == FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) { S = 0; if (event == FL_PUSH) { int xx = int(val*ww+.5); offcenter = mx-xx; if (offcenter < -10 || offcenter > 10) offcenter = 0; else return 1; } } else { S = int(slider_size_*ww+.5); if (S >= ww) return 0; int T = (horizontal() ? H : W)/2+1; if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4; if (S < T) S = T; if (event == FL_PUSH) { int xx = int(val*(ww-S)+.5); offcenter = mx-xx; if (offcenter < 0) offcenter = 0; else if (offcenter > S) offcenter = S; else return 1; } } int xx = mx-offcenter; double v = 0; char tryAgain = 1; while (tryAgain) { tryAgain = 0; if (xx < 0) { xx = 0; offcenter = mx; if (offcenter < 0) offcenter = 0; } else if (xx > (ww-S)) { xx = ww-S; offcenter = mx-xx; if (offcenter > S) offcenter = S; } v = round(xx*(maximum()-minimum())/(ww-S) + minimum()); // make sure a click outside the sliderbar moves it: if (event == FL_PUSH && v == value()) { offcenter = S/2; event = FL_DRAG; tryAgain = 1; } } handle_drag(clamp(v)); } return 1; case FL_RELEASE: handle_release(); return 1; case FL_KEYBOARD: { Fl_Widget_Tracker wp(this); switch (Fl::event_key()) { case FL_Up: if (horizontal()) return 0; handle_push(); if (wp.deleted()) return 1; handle_drag(clamp(increment(value(),-1))); if (wp.deleted()) return 1; handle_release(); return 1; case FL_Down: if (horizontal()) return 0; handle_push(); if (wp.deleted()) return 1; handle_drag(clamp(increment(value(),1))); if (wp.deleted()) return 1; handle_release(); return 1; case FL_Left: if (!horizontal()) return 0; handle_push(); if (wp.deleted()) return 1; handle_drag(clamp(increment(value(),-1))); if (wp.deleted()) return 1; handle_release(); return 1; case FL_Right: if (!horizontal()) return 0; handle_push(); if (wp.deleted()) return 1; handle_drag(clamp(increment(value(),1))); if (wp.deleted()) return 1; handle_release(); return 1; default: return 0; } } // break not required because of switch... case FL_FOCUS : case FL_UNFOCUS : if (Fl::visible_focus()) { redraw(); return 1; } else return 0; case FL_ENTER : case FL_LEAVE : return 1; default: return 0; } } int Fl_Slider::handle(int event) { if (event == FL_PUSH && Fl::visible_focus()) { Fl::focus(this); redraw(); } return handle(event, x()+Fl::box_dx(box()), y()+Fl::box_dy(box()), w()-Fl::box_dw(box()), h()-Fl::box_dh(box())); } Fl_Fill_Slider::Fl_Fill_Slider(int X,int Y,int W,int H,const char *L) : Fl_Slider(X,Y,W,H,L) { type(FL_VERT_FILL_SLIDER); } Fl_Hor_Slider::Fl_Hor_Slider(int X,int Y,int W,int H,const char *l) : Fl_Slider(X,Y,W,H,l) { type(FL_HOR_SLIDER); } Fl_Hor_Fill_Slider::Fl_Hor_Fill_Slider(int X,int Y,int W,int H,const char *L) : Fl_Slider(X,Y,W,H,L) { type(FL_HOR_FILL_SLIDER); } Fl_Hor_Nice_Slider::Fl_Hor_Nice_Slider(int X,int Y,int W,int H,const char *L) : Fl_Slider(X,Y,W,H,L) { type(FL_HOR_NICE_SLIDER); box(FL_FLAT_BOX); } Fl_Nice_Slider::Fl_Nice_Slider(int X,int Y,int W,int H,const char *L) : Fl_Slider(X,Y,W,H,L) { type(FL_VERT_NICE_SLIDER); box(FL_FLAT_BOX); } fltk-1.4.3/src/Fl_File_Input.cxx0000644000175000017500000001665515004135251016614 0ustar albrechtalbrecht// // File_Input header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // Original version Copyright 1998 by Curtis Edwards. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include "Fl_System_Driver.H" #include #include #include #include #include #include "flstring.h" // // Height of directory buttons... // #define DIR_HEIGHT 10 // // Redraw bit for directory bar... // #define FL_DAMAGE_BAR 0x10 /** Creates a new Fl_File_Input widget using the given position, size, and label string. The default boxtype is FL_DOWN_BOX. \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ Fl_File_Input::Fl_File_Input(int X, int Y, int W, int H, const char *L) : Fl_Input(X, Y, W, H, L) { buttons_[0] = 0; ok_entry_ = 1; pressed_ = -1; down_box(FL_UP_BOX); } /** Draw directory buttons. */ void Fl_File_Input::draw_buttons() { int i, // Looping var X; // Current X position if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) { update_buttons(); } for (X = 0, i = 0; buttons_[i]; i ++) { if ((X + buttons_[i]) > xscroll()) { if (X < xscroll()) { draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), x(), y(), X + buttons_[i] - xscroll(), DIR_HEIGHT, FL_GRAY); } else if ((X + buttons_[i] - xscroll()) > w()) { draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT, FL_GRAY); } else { draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), x() + X - xscroll(), y(), buttons_[i], DIR_HEIGHT, FL_GRAY); } } X += buttons_[i]; } if (X < w()) { draw_box(pressed_ == i ? fl_down(down_box()) : down_box(), x() + X - xscroll(), y(), w() - X + xscroll(), DIR_HEIGHT, FL_GRAY); } } /** Update the sizes of the directory buttons. */ void Fl_File_Input::update_buttons() { int i; // Looping var const char *start, // Start of path component *end; // End of path component // puts("update_buttons()"); // Set the current font & size... fl_font(textfont(), textsize()); // Loop through the value string, setting widths... for (i = 0, start = value(); start && i < (int)(sizeof(buttons_) / sizeof(buttons_[0]) - 1); start = end, i ++) { // printf(" start = \"%s\"\n", start); if ((end = Fl::system_driver()->next_dir_sep(start)) == NULL) break; end ++; buttons_[i] = (short)fl_width(start, (int) (end - start)); if (!i) buttons_[i] += Fl::box_dx(box()) + 6; } // printf(" found %d components/buttons...\n", i); buttons_[i] = 0; } /** Sets the value of the widget given a new string value and its length. Returns non 0 on success. \param[in] str new string value \param[in] len lengh of value */ int // O - TRUE on success Fl_File_Input::value(const char *str, // I - New string value int len) { // I - Length of value damage(FL_DAMAGE_BAR); return Fl_Input::value(str,len); } /** Sets the value of the widget given a new string value. Returns non 0 on success. \param[in] str new string value */ int // O - TRUE on success Fl_File_Input::value(const char *str) { // I - New string value damage(FL_DAMAGE_BAR); return Fl_Input::value(str); } /** Draws the file input widget */ void Fl_File_Input::draw() { Fl_Boxtype b = box(); if (damage() & (FL_DAMAGE_BAR | FL_DAMAGE_ALL)) draw_buttons(); // this flag keeps Fl_Input_::drawtext from drawing a bogus box! char must_trick_fl_input_ = Fl::focus()!=this && !size() && !(damage()&FL_DAMAGE_ALL); if ((damage() & FL_DAMAGE_ALL) || must_trick_fl_input_) draw_box(b,x(),y()+DIR_HEIGHT,w(),h()-DIR_HEIGHT,color()); if (!must_trick_fl_input_) Fl_Input_::drawtext(x()+Fl::box_dx(b)+3, y()+Fl::box_dy(b)+DIR_HEIGHT, w()-Fl::box_dw(b)-6, h()-Fl::box_dh(b)-DIR_HEIGHT); } /** Handle events in the widget. Return non zero if event is handled. \param[in] event */ int // O - TRUE if we handled event Fl_File_Input::handle(int event) // I - Event { // printf("handle(event = %d)\n", event); static char inButtonBar = 0; switch (event) { case FL_MOVE : case FL_ENTER : if (active_r()) { if (Fl::event_y() < (y() + DIR_HEIGHT)) window()->cursor(FL_CURSOR_DEFAULT); else window()->cursor(FL_CURSOR_INSERT); } return 1; case FL_PUSH : inButtonBar = (Fl::event_y() < (y() + DIR_HEIGHT)); case FL_RELEASE : case FL_DRAG : if (inButtonBar) return handle_button(event); else return Fl_Input::handle(event); default : { Fl_Widget_Tracker wp(this); if (Fl_Input::handle(event)) { if (wp.exists()) damage(FL_DAMAGE_BAR); return 1; } } return 0; } } /** Handles button events in the widget. Return non zero if event is handled. \param[in] event */ int // O - TRUE if we handled event Fl_File_Input::handle_button(int event) // I - Event { int i, // Looping var X; // Current X position char *start, // Start of path component *end; // End of path component char newvalue[FL_PATH_MAX]; // New value // Figure out which button is being pressed... for (X = 0, i = 0; buttons_[i]; i ++) { X += buttons_[i]; if (X > xscroll() && Fl::event_x() < (x() + X - xscroll())) break; } // printf("handle_button(event = %d), button = %d\n", event, i); // Redraw the directory bar... if (event == FL_RELEASE) pressed_ = -1; else pressed_ = (short)i; window()->make_current(); draw_buttons(); // Return immediately if the user is clicking on the last button or // has not released the mouse button... if (!buttons_[i] || event != FL_RELEASE) return 1; // Figure out where to truncate the path... strlcpy(newvalue, value(), sizeof(newvalue)); for (start = newvalue, end = start; start && i >= 0; start = end, i --) { // printf(" start = \"%s\"\n", start); if ((end = (char*)Fl::system_driver()->next_dir_sep(start)) == NULL) break; end ++; } if (i < 0) { // Found the end; truncate the value and update the buttons... *start = '\0'; value(newvalue, (int) (start - newvalue) ); // Then do the callbacks, if necessary... set_changed(); if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE) ) do_callback(FL_REASON_CHANGED); } return 1; } fltk-1.4.3/src/Fl_Int_Vector.H0000644000175000017500000001061315004135251016203 0ustar albrechtalbrecht// // An STL-ish vector without templates for the Fast Light Tool Kit (FLTK). // // Copyright 2002 by Greg Ercolano. // Copyright 2022-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #ifndef Fl_Int_Vector_H #define Fl_Int_Vector_H /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include /** \file src/Fl_Int_Vector.H An STL-ish vector implemented without templates. */ /** An STL-ish vector without templates. Handles dynamic memory management of an integer array, and allows array elements to be accessed with zero based indexing: v[0], v[1].. Common use: \code #include #include "Fl_Int_Vector.H" int main() { Fl_Int_Vector v; // Create an array of values 11,22,33: v.push_back(11); // add first element v.push_back(22); // add second element v.push_back(33); // add third element // Assignment by subscript v[1] = 222; // changes 2nd element from 22 to 222 // Loop through printing the values for ( unsigned int i=0; i in the next version after 1.4.x. - Add other std::vector methods like erase(), etc. - Make memory blocking size flexible, and add related methods like capacity(), reserve(), shrink_to_fit(), etc. - Add non-std methods that are nevertheless needed, e.g. insert(index,val), delete(index), delete(start, end), swap(a_idx,b_idx) */ class FL_EXPORT Fl_Int_Vector { int *arr_; unsigned int size_; /** Initialize internals. Private: For use internally by the class's ctors only. */ void init() { arr_ = 0; size_ = 0; } void copy(int *newarr, unsigned int newsize); public: /** Create an empty vector of integers. */ Fl_Int_Vector() { init(); } ~Fl_Int_Vector(); /** Copy constructor. */ Fl_Int_Vector(Fl_Int_Vector &o) { init(); copy(o.arr_, o.size_); } /** Assignment operator. Similar to the copy constructor, creates a separate copy of the source array, freeing any previous contents in the current integer array. */ Fl_Int_Vector &operator=(Fl_Int_Vector &o) { init(); copy(o.arr_, o.size_); return *this; } /** Access the specified integer element at index position \p x. \warning No range checking is done on \p x, which must be less than size(). */ int operator[](int x) const { return arr_[x]; } /** Access the specified integer element at index position \p x as a reference. This allows assignment by index through the returned reference, e.g. arr[1] = 222; where arr[1] ends up being a reference to ptr[1], and then 222 is assigned to that ref. \warning No range checking is done on \p x, which must be less than size(). */ int &operator[](int x) { return arr_[x]; } /** Return the number of integer elements in the array. */ unsigned int size() const { return size_; } void size(unsigned int count); /** Removes the last element the last element and returns its value. \warning You must not call pop_back() if the array is empty, i.e. if (size() == 0). \todo Internals should maybe assert(size_ != 0) */ int pop_back() { int tmp = arr_[size_ - 1]; size_--; return tmp; } /** Appends \p val to the array, enlarging the array by one. */ void push_back(int val) { unsigned int x = size_; size(size_ + 1); arr_[x] = val; } /** Return the last element in the array. \warning You must not call back() if the array is empty, i.e. if (size() == 0). \todo Internals should maybe assert(size_ != 0) */ int back() const { return arr_[size_ - 1]; } /** Checks if array has no elements. Same as a test for (size() == 0). */ bool empty() const { return (size_ == 0) ? true : false; } }; /** \} \endcond */ #endif // Fl_Int_Vector_H fltk-1.4.3/src/Fl_Gl_Device_Plugin.cxx0000644000175000017500000000335215004135251017703 0ustar albrechtalbrecht// // implementation of class Fl_Gl_Device_Plugin for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include "Fl_Gl_Window_Driver.H" /** This class will make sure that OpenGL printing/screen capture is available if fltk_gl was linked to the program */ class Fl_Gl_Device_Plugin : public Fl_Device_Plugin { public: Fl_Gl_Device_Plugin() : Fl_Device_Plugin(name()) { } const char *name() FL_OVERRIDE { return "opengl.device.fltk.org"; } int print(Fl_Widget *w) FL_OVERRIDE { Fl_Gl_Window *glw = w->as_gl_window(); if (!glw) return 0; Fl_RGB_Image *img = Fl_Gl_Window_Driver::driver(glw)->capture_gl_rectangle(0, 0, glw->w(), glw->h()); img->scale(glw->w(), glw->h()); img->draw(0, 0); delete img; return 1; } Fl_RGB_Image* rectangle_capture(Fl_Widget *widget, int x, int y, int w, int h) FL_OVERRIDE { Fl_Gl_Window *glw = widget->as_gl_window(); if (!glw) return NULL; return Fl_Gl_Window_Driver::driver(glw)->capture_gl_rectangle(x, y, w, h); } }; static Fl_Gl_Device_Plugin Gl_Device_Plugin; // The purpose of this variable, used in Fl_Gl_Window.cxx, is only to force this file to be loaded // whenever Fl_Gl_Window.cxx is loaded, that is, whenever fltk_gl is. FL_EXPORT int fl_gl_load_plugin = 0; fltk-1.4.3/src/filename_isdir.cxx0000644000175000017500000000425615004135251017101 0ustar albrechtalbrecht// // Directory detection routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Used by fl_file_chooser #include "flstring.h" #include "Fl_System_Driver.H" #include #include #include /** Determines if a file exists and is a directory from its filename. \code #include [..] fl_filename_isdir("/etc"); // returns non-zero fl_filename_isdir("/etc/hosts"); // returns 0 \endcode \param[in] n the filename to parse \return non zero if file exists and is a directory, zero otherwise */ int fl_filename_isdir(const char* n) { return Fl::system_driver()->filename_isdir(n); } /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** filename_isdir_quick() is a private function that checks for a trailing slash and assumes that the passed name is a directory if it finds one. This function is used by Fl_File_Browser and Fl_File_Chooser to avoid extra stat() calls, but is not supported outside of FLTK... */ int Fl_System_Driver::filename_isdir_quick(const char* n) { // Do a quick optimization for filenames with a trailing slash... if (*n && n[strlen(n) - 1] == '/') return 1; return filename_isdir(n); } // TODO: This should probably handle errors better (like permission denied) -erco int Fl_System_Driver::filename_isdir(const char* n) { struct stat s; char fn[FL_PATH_MAX]; int length; length = (int) strlen(n); // Matt: Just in case, we strip the slash for other operating // systems as well, avoid bugs by sloppy implementations // of "stat". if (length > 1 && n[length - 1] == '/') { length --; memcpy(fn, n, length); fn[length] = '\0'; n = fn; } return !stat(n, &s) && (s.st_mode & S_IFDIR); } /** \} \endcond */ fltk-1.4.3/src/Fl_Tabs.cxx0000644000175000017500000011712115004135251015435 0ustar albrechtalbrecht// // Tab widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // This is the "file card tabs" interface to allow you to put lots and lots // of buttons and switches in a panel, as popularized by many toolkits. // Each child widget is a card, and its label() is printed on the card tab. // Clicking the tab makes that card visible. #include #include #include #include #include #include #include #include #define BORDER 2 #define OV_BORDER 2 #define EXTRASPACE 10 #define SELECTION_BORDER 5 #define EXTRAGAP 2 #define MARGIN 20 enum {LEFT, RIGHT, SELECTED}; static int fl_min(int a, int b) { return a < b ? a : b; } /** Make sure that we redraw all tabs when new children are added. */ int Fl_Tabs::on_insert(Fl_Widget* candidate, int index) { redraw_tabs(); return Fl_Group::on_insert(candidate, index); } /** Make sure that we redraw all tabs when children are moved. */ int Fl_Tabs::on_move(int a, int b) { redraw_tabs(); return Fl_Group::on_move(a, b); } /** Make sure that we redraw all tabs when new children are removed. */ void Fl_Tabs::on_remove(int index) { redraw_tabs(); if (child(index)->visible()) { if (index+10) value(child(index-1)); } if (children()==1) damage(FL_DAMAGE_ALL); Fl_Group::on_remove(index); } /** Make sure that we redraw all tabs when the widget size changes. */ void Fl_Tabs::resize(int X, int Y, int W, int H) { redraw_tabs(); Fl_Group::resize(X, Y, W, H); } /** Ensure proper placement of selected tab. */ void Fl_Tabs::show() { Fl::damage(FL_DAMAGE_SCROLL); Fl_Group::show(); } /** Calculate tab positions and widths. This protected method calculates the horizontal display positions and widths of all tabs. If the number of children \c 'nc' (see below) is \> 0 three internal arrays are allocated, otherwise the arrays are free'd and the pointers are set to NULL. Note that the first array is larger (nc+1). - tab_pos[nc+1] : The left edges of each tab plus a fake left edge for a tab past the right-hand one. - tab_width[nc] : The width of each tab - tab_flags[nc] : Flags, bit 0 is set if the tab is compressed If needed, these arrays are (re)allocated. These positions are actually of the left edge of the slope. They are either separated by the correct distance or by EXTRASPACE or by zero. In OVERFLOW_COMPRESS mode, tab positions and widths are compressed to make the entire tabs bar fit into the width of Fl_Tabs while keeping the selected tab fully visible. In other overflow modes, the tabs area may be dragged horizontally using \ref tab_offset. The tab_pos array is not adjusted to the horizontal offset, but starts at this->x() plus the box's left margin. The protected variable `tab_count` is set to the currently allocated size, i.e. the number of children (`nc`). \returns Index of the selected item \retval -1 If the number of children is 0 (zero). \note Return values in 1.3 were not documented. Return values before Sep 2023 were documented as 1 based index and 0 if there were no children. This was actually never the case. It always returned a 0 based index and the (useless) value of also 0 if there were no children. The current version returns -1 if there are no children. \note For this method to work, only a single child should be selected. Calling the method \ref value() before calling \ref tab_positions() will ensure that exactly one child is selected and return a pointer to that child. \see clear_tab_positions() */ int Fl_Tabs::tab_positions() { const int nc = children(); if (nc != tab_count) { clear_tab_positions(); if (nc) { tab_pos = (int*)malloc((nc+1)*sizeof(int)); tab_width = (int*)malloc((nc)*sizeof(int)); tab_flags = (int*)malloc((nc)*sizeof(int)); } tab_count = nc; } if (nc == 0) return -1; int selected = 0; Fl_Widget*const* a = array(); int i; char prev_draw_shortcut = fl_draw_shortcut; fl_draw_shortcut = 1; int l = tab_pos[0] = Fl::box_dx(box()); for (i=0; ivisible()) selected = i; int wt = 0; int ht = 0; Fl_Labeltype ot = o->labeltype(); Fl_Align oa = o->align(); if (ot == FL_NO_LABEL) { o->labeltype(FL_NORMAL_LABEL); } o->align(tab_align()); o->measure_label(wt,ht); o->labeltype(ot); o->align(oa); if (o->when() & FL_WHEN_CLOSED) wt += labelsize()/2 + EXTRAGAP; tab_width[i] = wt + EXTRASPACE; tab_pos[i+1] = tab_pos[i] + tab_width[i] + BORDER; tab_flags[i] = 0; } fl_draw_shortcut = prev_draw_shortcut; if (overflow_type == OVERFLOW_COMPRESS) { int r = w() - Fl::box_dw(box());; if ( (nc > 1) && (tab_pos[nc] > r) ) { int wdt = r - l; // extreme case: the selected tab is wider than Fl_Tabs itself int available = wdt - tab_width[selected]; if (available <= 8*nc) { // if the current tab is so huge that it doesn't fit Fl_Tabs, we make // shrink all other tabs to 8 pixels and give the selected tab the rest for (i = 0; i < nc; i++) { if (i < selected) { tab_pos[i] = l + 8*i; tab_flags[i] |= 1; } else if (i>selected) { tab_pos[i] = r - (nc-i)*8; tab_flags[i] |= 1; } else { tab_pos[i] = l + 8*i;; tab_flags[i] &= ~1; } tab_pos[nc] = r; } } else { // This method tries to keep as many visible tabs to the left and right // of the selected tab. All other tabs are compressed until they are // no smaller than 8 pixels. // Overlap to the left and right of the selection is proportional // to the left and right total tabs widths. // The dynamic of this method is really nice to watch: start FLUID and // edit test/tabs. Select any tab and change the label to make the tab // wider and smaller. All other tabs will move nicely to make room for // the bigger label. Even if two tabs are each wider than Fl_Tabs. int overflow = tab_pos[nc] - r; int left_total = tab_pos[selected] - l; int right_total = tab_pos[nc] - tab_pos[selected+1]; int left_overflow = left_total+right_total ? overflow * left_total / (left_total+right_total) : overflow; int right_overflow = overflow - left_overflow; // now clip the left tabs until we compensated overflow on the left int xdelta = 0; // accumulate the tab x correction for (i=0; i 0) { // do we still need to compensate? tw -= left_overflow; // try to compensate everything if (tw < 8) tw = 8; // but keep a minimum width of 8 int wdelta = tab_width[i] - tw; // how many pixels did we actually take? left_overflow -= wdelta; // remove that and keep the remaining overflow xdelta += wdelta; // accumulate amount of pixel shift if (wdelta > 16) tab_flags[i] |= 1; // remove the close button if we overlap too much } tab_pos[i+1] -= xdelta; // fix the overlap by moving the tab on the right } // and clip the right tabs until we compensated overflow on the right xdelta = 0; for (i=nc-1; i>selected; i--) { int tw = tab_width[i]; if (right_overflow > 0) { tw -= right_overflow; if (tw < 8) tw = 8; int wdelta = tab_width[i] - tw; right_overflow -= wdelta; xdelta += wdelta; // with the close button on the left, overlapping gets more confusing, // so remove the button sooner if (wdelta > 4) tab_flags[i] |= 1; } tab_pos[i] -= overflow - xdelta; } tab_pos[nc] = r; } } } return selected; } /** Return space (height) in pixels usable for tabs. The calculated height is the largest space between all children and the upper and lower widget boundaries, respectively. If the space at the bottom is larger than at the top, the value will be negative and the tabs should be placed at the bottom. \returns Vertical space that can be used for the tabs. \retval >0 To put the tabs at the top of the widget. \retval <0 To put the tabs on the bottom. \retval Full height, if children() == 0. */ int Fl_Tabs::tab_height() { if (children() == 0) return h(); int H = h(); int H2 = y(); Fl_Widget*const* a = array(); for (int i=children(); i--;) { Fl_Widget* o = *a++; if (o->y() < y()+H) H = o->y()-y(); if (o->y()+o->h() > H2) H2 = o->y()+o->h(); } H2 = y()+h()-H2; if (H2 > H) return (H2 <= 0) ? 0 : -H2; else return (H <= 0) ? 0 : H; } /** Return a pointer to the child widget with a tab at the given coordinates. The Fl_Tabs::which() method returns a pointer to the child widget of the Fl_Tabs container that corresponds to the tab at the given event coordinates. If the event coordinates are outside the area of the tabs or if the Fl_Tabs container has no children, the method returns NULL. \param event_x, event_y event coordinates \returns pointer to the selected child widget, or NULL */ Fl_Widget *Fl_Tabs::which(int event_x, int event_y) { if (children() == 0) return 0; int H = tab_height(); if (H < 0) { if (event_y > y()+h() || event_y < y()+h()+H) return 0; } else { if (event_y > y()+H || event_y < y()) return 0; } if (event_x < x()) return 0; Fl_Widget *ret = 0L; const int nc = children(); tab_positions(); for (int i=0; i= tab_x) && (event_x < tab_x + (labelsize()+EXTRASPACE+EXTRAGAP)/2) ); } } return 0; } /** Determine if the coordinates are in the area of the overflow menu button. \param event_x, event_y event coordinates \return 1 if we hit the overflow menu button, and 0 otherwise */ int Fl_Tabs::hit_overflow_menu(int event_x, int event_y) { if (!has_overflow_menu) return 0; int H = tab_height(); if (event_x < x()+w()-abs(H)+OV_BORDER) return 0; if (H >= 0) { if (event_y > y()+H) return 0; } else { if (event_y < y()+h()+H) return 0; } return 1; } /** Determine if the coordinates are within the tabs area. \param event_x, event_y event coordinates \return 1 if we hit the tabs area, and 0 otherwise */ int Fl_Tabs::hit_tabs_area(int event_x, int event_y) { int H = tab_height(); if (H >= 0) { if (event_y > y()+H) return 0; } else { if (event_y < y()+h()+H) return 0; } if (has_overflow_menu && event_x > x()+w()-abs(H)+OV_BORDER) return 0; return 1; } /** Check if the tabs overflow and sets the has_overflow_menu flag accordingly. */ void Fl_Tabs::check_overflow_menu() { int nc = children(); int H = tab_height(); if (H < 0) H = -H; if (tab_pos[nc] > w()-H+OV_BORDER) { has_overflow_menu = 1; } else { has_overflow_menu = 0; } } /** Take keyboard focus if o is not NULL. \param[in] o selected tab */ void Fl_Tabs::take_focus(Fl_Widget *o) { if (o && Fl::visible_focus() && Fl::focus()!=this) { Fl::focus(this); redraw_tabs(); } } /** Set tab o as selected and call callbacks if needed. \param[in] o the newly selected tab \return 0 if o is invalid or was deleted by the callback and must no longer be used */ int Fl_Tabs::maybe_do_callback(Fl_Widget *o) { // chaeck if o is valid if ( o == NULL ) return 0; // set the new tab value int tab_changed = value(o); if ( tab_changed ) set_changed(); // do we need to call the callback? if ( tab_changed || ( when() & (FL_WHEN_NOT_CHANGED) ) ) { Fl_Widget_Tracker wp(o); // we want to know if the widget lives on do_callback(FL_REASON_SELECTED); // this may delete the tab if (wp.deleted()) return 0; // if it did, return 0 } // if o is still valid, do remaining tasks Fl_Tooltip::current(o); return 1; } /** This is called when the user clicks the overflow pulldown menu button. This method creates a menu item array that contains the titles of all tabs in the Fl_Tabs group. Visible and invisible tabs are separated by dividers to indicate their state. The menu is then presented until the user selects an item or cancels. The chosen tab is then selected and made visible. The menu item array is then deleted. */ void Fl_Tabs::handle_overflow_menu() { int nc = children(); int H = tab_height(); if (H < 0) H = -H; int i, fv=-1, lv=nc; // first and last visible tab if (nc <= 0) return; // count visible children for (i = 0; i < nc; i++) { if (tab_pos[i]+tab_offset < 0) fv = i; if (tab_pos[i]+tab_width[i]+tab_offset <= w()-H+OV_BORDER) lv = i; } // create a menu with all children Fl_Menu_Item* overflow_menu = new Fl_Menu_Item[nc+1]; memset(overflow_menu, 0, sizeof(Fl_Menu_Item)*(nc+1)); for (i = 0; i < nc; i++) { overflow_menu[i].label(child(i)->label()); overflow_menu[i].user_data(child(i)); overflow_menu[i].labelfont(labelfont()); overflow_menu[i].labelsize(labelsize()); if ( (i == fv) || (i == lv) ) overflow_menu[i].flags |= FL_MENU_DIVIDER; if (child(i)->visible()) overflow_menu[i].labelfont_ |= FL_BOLD; } // show the menu and handle the selection const Fl_Menu_Item *m = overflow_menu->popup(x()+w()-H+OV_BORDER, (tab_height()>0)?(y()+H):(y()+h()-OV_BORDER)); if (m) { Fl_Widget *o = (Fl_Widget*)m->user_data(); push(0); take_focus(o); maybe_do_callback(o); } // delete the menu until we need it next time if (overflow_menu) { delete[] overflow_menu; overflow_menu = NULL; } } /** Draw square button-like graphics with a down arrow in the top or bottom right corner. */ void Fl_Tabs::draw_overflow_menu_button() { int H = tab_height(); int X, Y; if (H > 0) { X = x() + w() - H + OV_BORDER; if (OV_BORDER > 0) fl_rectf(X, y(), H - OV_BORDER, OV_BORDER, color()); Y = y() + OV_BORDER; } else { H = -H; X = x() + w() - H + OV_BORDER; Y = y() + h() - H; if (OV_BORDER > 0) fl_rectf(X, Y + H - OV_BORDER, H - OV_BORDER, OV_BORDER, color()); } H -= OV_BORDER; draw_box(box(), X, Y, H, H, color()); Fl_Rect r(X, Y, H, H); // labelcolor() is historically used to contrast selectioncolor() and is // useless her, so we fall back to contrast the background color on the // gray ramp. Fl_Color arrow_color = fl_contrast(FL_GRAY_RAMP+0, color()); if (!active_r()) arrow_color = fl_inactive(arrow_color); fl_draw_arrow(r, FL_ARROW_CHOICE, FL_ORIENT_NONE, arrow_color); } /** Redraw all tabs (and only the tabs). This method sets the Fl_Tab's damage flags so the tab area is redrawn. */ void Fl_Tabs::redraw_tabs() { int H = tab_height(); if (H >= 0) { damage(FL_DAMAGE_EXPOSE, x(), y(), w(), H + SELECTION_BORDER); } else { H = -H; damage(FL_DAMAGE_EXPOSE, x(), y() + h() - H - SELECTION_BORDER, w(), H + SELECTION_BORDER); } } /** Handle all events in the tabs area and forward the rest to the selected child. \param[in] event handle this event \return 1 if the event was handled */ int Fl_Tabs::handle(int event) { static int initial_x = 0; static int initial_tab_offset = 0; static int forward_motion_to_group = 0; static Fl_Widget *o_push_drag = NULL; Fl_Widget *o; int i; switch (event) { case FL_MOUSEWHEEL: if ( ( (overflow_type == OVERFLOW_DRAG) || (overflow_type == OVERFLOW_PULLDOWN) ) && hit_tabs_area(Fl::event_x(), Fl::event_y()) ) { int original_tab_offset = tab_offset; tab_offset -= 2 * Fl::event_dx(); if (tab_offset > 0) tab_offset = 0; int m = 0; if (overflow_type == OVERFLOW_PULLDOWN) m = abs(tab_height()); int dw = tab_pos[children()] + tab_offset - w(); if (dw < -m) tab_offset -= dw+m; if (tab_offset != original_tab_offset) redraw_tabs(); return 1; } return Fl_Group::handle(event); case FL_PUSH: initial_x = Fl::event_x(); initial_tab_offset = tab_offset; forward_motion_to_group = 0; if (hit_overflow_menu(Fl::event_x(), Fl::event_y())) { handle_overflow_menu(); return 1; } if (!hit_tabs_area(Fl::event_x(), Fl::event_y())) { forward_motion_to_group = 1; } /* FALLTHROUGH */ case FL_DRAG: o_push_drag = which(Fl::event_x(), Fl::event_y()); case FL_RELEASE: if (forward_motion_to_group) { return Fl_Group::handle(event); } o = which(Fl::event_x(), Fl::event_y()); if (event == FL_RELEASE && o != o_push_drag) { // see issue #1075 return 1; } if ( (overflow_type == OVERFLOW_DRAG) || (overflow_type == OVERFLOW_PULLDOWN) ) { if (tab_pos[children()] < w() && tab_offset == 0) { // fall through } else if (!Fl::event_is_click()) { tab_offset = initial_tab_offset + Fl::event_x() - initial_x; int m = 0; if (overflow_type == OVERFLOW_PULLDOWN) m = abs(tab_height()) - OV_BORDER; if (tab_offset > 0) { initial_tab_offset -= tab_offset; tab_offset = 0; } else { int dw = tab_pos[children()] + tab_offset - w(); if (dw < -m) { initial_tab_offset -= dw+m; tab_offset -= dw+m; } } redraw_tabs(); return 1; } } if (event == FL_RELEASE) { push(0); take_focus(o); if (o && (o->when() & FL_WHEN_CLOSED) && hit_close(o, Fl::event_x(), Fl::event_y())) { o->do_callback(FL_REASON_CLOSED); return 1; // o may be deleted at this point } maybe_do_callback(o); } else { push(o); } return 1; case FL_MOVE: { int ret = Fl_Group::handle(event); Fl_Widget *tooltip_widget = Fl_Tooltip::current(); Fl_Widget *n; // initialized later int H = tab_height(); if ( (H >= 0) && (Fl::event_y() > y()+H) ) return ret; else if ( (H < 0) && (Fl::event_y() < y()+h()+H) ) return ret; else { n = which(Fl::event_x(), Fl::event_y()); if (!n) n = this; } if (n != tooltip_widget) Fl_Tooltip::enter(n); return ret; } case FL_FOCUS: case FL_UNFOCUS: if (!Fl::visible_focus()) return Fl_Group::handle(event); if (Fl::event() == FL_RELEASE || Fl::event() == FL_SHORTCUT || Fl::event() == FL_KEYBOARD || Fl::event() == FL_FOCUS || Fl::event() == FL_UNFOCUS) { redraw_tabs(); if (Fl::event() == FL_FOCUS) return Fl_Group::handle(event); if (Fl::event() == FL_UNFOCUS) return 0; else return 1; } else return Fl_Group::handle(event); case FL_KEYBOARD: switch (Fl::event_key()) { case FL_Left: if (!children()) return 0; if (child(0)->visible()) return 0; for (i = 1; i < children(); i ++) if (child(i)->visible()) break; value(child(i - 1)); set_changed(); do_callback(FL_REASON_SELECTED); return 1; case FL_Right: if (!children()) return 0; if (child(children() - 1)->visible()) return 0; for (i = 0; i < children()-1; i++) if (child(i)->visible()) break; value(child(i + 1)); set_changed(); do_callback(FL_REASON_SELECTED); return 1; case FL_Down: redraw(); return Fl_Group::handle(FL_FOCUS); default: break; } return Fl_Group::handle(event); case FL_SHORTCUT: for (i = 0; i < children(); ++i) { Fl_Widget *c = child(i); if (c->test_shortcut(c->label())) { char sc = !c->visible(); value(c); if (sc) { set_changed(); do_callback(FL_REASON_SELECTED); } else { do_callback(FL_REASON_RESELECTED); } return 1; } } return Fl_Group::handle(event); case FL_SHOW: value(); // update visibilities and fall through default: return Fl_Group::handle(event); } } /** This is called by the tab widget's handle() method to set the tab group widget the user last FL_PUSH'ed on. Set back to zero on FL_RELEASE. As of this writing, the value is mainly used by draw_tab() to determine whether or not to draw a 'down' box for the tab when it's clicked, and to turn it off if the user drags off it. \see push(). */ int Fl_Tabs::push(Fl_Widget *o) { if (push_ == o) return 0; if ( (push_ && !push_->visible()) || (o && !o->visible()) ) redraw_tabs(); push_ = o; return 1; } /** Gets the currently visible widget/tab. The Fl_Tabs::value() method returns a pointer to the currently visible child widget of the Fl_Tabs container. The visible child is the first child that is currently being displayed, or the last child if none of the children are being displayed. If child widgets have been added, moved, or deleted, this method ensures that only one tab is visible at a time. \return a pointer to the currently visible child */ Fl_Widget* Fl_Tabs::value() { Fl_Widget* v = 0; Fl_Widget*const* a = array(); for (int i=children(); i--;) { Fl_Widget* o = *a++; if (v) o->hide(); else if (o->visible()) v = o; else if (!i) {o->show(); v = o;} } return v; } /** Sets the widget to become the currently visible widget/tab. The Fl_Tabs::value() method allows you to set a particular child widget of the Fl_Tabs container to be the currently visible widget. If the specified widget is a child of the Fl_Tabs container, it will be made visible and all other children will be hidden. The method returns 1 if the value was changed, and 0 if the specified value was already set. \param[in] newvalue a poiner to a child widget \return 1 if a different tab was chosen \return 0 if there was no change (new value already set) */ int Fl_Tabs::value(Fl_Widget *newvalue) { Fl_Widget*const* a = array(); int ret = 0; int selected = -1; for (int i=children(); i--;) { Fl_Widget* o = *a++; if (o == newvalue) { if (!o->visible()) ret = 1; o->show(); selected = children()-i-1; } else { o->hide(); } } // always make sure that the selected tab is visible if ( (selected >= 0) && ( (overflow_type == OVERFLOW_DRAG) || (overflow_type == OVERFLOW_PULLDOWN) ) ) { int m = MARGIN; if ( (selected == 0) || (selected == children()-1) ) m = BORDER; int mr = m; tab_positions(); if (overflow_type == OVERFLOW_PULLDOWN) mr += abs(tab_height() - OV_BORDER); if (tab_pos[selected]+tab_width[selected]+tab_offset+mr > w()) { tab_offset = w() - tab_pos[selected] - tab_width[selected] - mr; } else if (tab_pos[selected]+tab_offset-m < 0) { tab_offset = -tab_pos[selected]+m; } } redraw_tabs(); return ret; } /** Draw the tabs area, the optional pulldown button, and all children. */ void Fl_Tabs::draw() { // // FL_DAMAGE_CHILD : this is set if any of the children asked for a redraw // Fl_Tabs forwards this by calling `update_child(v)` // FL_DAMAGE_EXPOSE : this is set if some setting in a widget changed // Fl_Tabs uses this to indicate that the tabs area needs a full redraw // FL_DAMAGE_SCROLL : this is used as a custom flag in various widgets // Fl_Tabs uses FL_DAMAGE_EXPOSE to indicate that the // tabs bar needs repositioning and teh tabs must be // redrawn // FL_DAMAGE_ALL : just recalculate and redraw everything // Anatomy of tabs on top: // +------+ <<-- selected tabs start at y() // | text | +------+ +---+ <-- other tabs are offset down by BORDER // | | | text | | ▼ | <-- the pulldown button width equals H - OV_BORDER // ++ +-------------+---+ <-- tab_height() to tab_height + Fl::box_dx(box()) // +-------------------------+ <-- tab_height + SELECTION_BORDER // | | // ↑____↑ this area within the SELECTION_BORDER is called "stem" // // tab_height() calculates the distance from y() to the "highest" child. // Note that the SELECTION_BORDER bleeds into the child area! // Note that the clear area under the selected tab also bleeds into the child. // Note that children have FL_NO_BOX and Fl_Tabs must draw the background. // // Horizontally, we start tabs at x() + Fl::box_dx() // When uncompressed, the space between tabs is EXTRASPACE // EXTRAGAP is the space between the close cross and the label // MARGIN is the minimal distance to the left and right edge of Fl_Tabs for // the selected tabs if the overflow mode allows scrolling if (children() == 0) { fl_rectf(x(), y(), w(), h(), color()); if (align() & FL_ALIGN_INSIDE) draw_label(); clear_damage(); return; } Fl_Widget *selected_child = value(); // return the first visible child and hide all others tab_positions(); int selected = find(selected_child); // find that child in the list and return 0..children()-1 if (selected == children()) selected = -1; // if anything fails, selected is -1 and int H = tab_height(); Fl_Color selected_tab_color = selected_child ? selected_child->color() : color(); bool tabs_at_top = (H > 0); bool colored_selection_border = (selection_color() != selected_tab_color); int tabs_y, tabs_h; int child_area_y, child_area_h; int clipped_child_area_y, clipped_child_area_h; int selection_border_y, selection_border_h; selection_border_h = colored_selection_border ? SELECTION_BORDER : Fl::box_dx(box()); if (tabs_at_top) { tabs_h = H; tabs_y = y(); selection_border_y = y() + tabs_h; child_area_y = y() + tabs_h; child_area_h = h() - tabs_h; clipped_child_area_y = y() + tabs_h + selection_border_h; clipped_child_area_h = h() - tabs_h - selection_border_h; } else { tabs_h = -H; tabs_y = y() + h() - tabs_h; selection_border_y = tabs_y - selection_border_h; child_area_y = y(); child_area_h = h() - tabs_h; clipped_child_area_y = y(); clipped_child_area_h = h() - tabs_h - selection_border_h; } // ---- recalculate the tabs so that the selected tab is visible if (damage() & (FL_DAMAGE_ALL|FL_DAMAGE_SCROLL)) { Fl_Widget *selected_tab = value(); if (selected_tab) value(selected_tab); } // ---- draw the tabs and the selection border if (damage() & (FL_DAMAGE_ALL|FL_DAMAGE_EXPOSE|FL_DAMAGE_SCROLL)) { // -- draw tabs background if (parent()) { Fl_Widget *p = parent(); fl_push_clip(x(), tabs_y, w(), tabs_h); if (Fl_Window *win = p->as_window()) { fl_draw_box(p->box(), 0, 0, p->w(), p->h(), p->color()); win->draw_backdrop(); } else { fl_draw_box(p->box(), p->x(), p->y(), p->w(), p->h(), p->color()); } fl_pop_clip(); } else { fl_rectf(x(), tabs_y, w(), tabs_h, color()); } // -- draw selection border fl_push_clip(x(), selection_border_y, w(), selection_border_h); if (colored_selection_border) { draw_box(box(), x(), y(), w(), h(), selected_tab_color); draw_box(box(), x(), selection_border_y, w(), selection_border_h, selection_color()); } else { draw_box(box(), x(), child_area_y, w(), child_area_h, selected_tab_color); } // draw the stem, the area that reaches from the tab into the selection border if (selected != -1) { int stem_x = x() + tab_pos[selected] + tab_offset; int stem_w = fl_min(tab_pos[selected+1] - tab_pos[selected], tab_width[selected]); if (colored_selection_border) { if (tabs_at_top) fl_rectf(stem_x, selection_border_y, stem_w, selection_border_h/2, selection_color()); else fl_rectf(stem_x, selection_border_y+selection_border_h-selection_border_h/2, stem_w, selection_border_h/2, selection_color()); } else { fl_rectf(stem_x, child_area_y-tabs_h, stem_w, child_area_h+2*tabs_h, selection_color()); } } fl_pop_clip(); // -- draw all tabs fl_push_clip(x(), tabs_y, w(), tabs_h); int i, clip_left, clip_right; int safe_selected = selected == -1 ? children() : selected; // draw all tabs from the leftmost up to the selected one, stacking them // visually as needed. The clipping assures that no tabs shine through gaps // between tabs. clip_left = x(); for (i=0; i safe_selected; i--) { clip_left = (i>0) ? (tab_offset+tab_pos[i]-tab_width[i-1]/2) : x(); fl_push_clip(clip_left, tabs_y, clip_right-clip_left, tabs_h); draw_tab(x()+tab_pos[i], x()+tab_pos[i+1], tab_width[i], H, child(i), tab_flags[i], RIGHT); fl_pop_clip(); } // if there is a selected tab, draw it last over all other tabs if (selected > -1) draw_tab(x()+tab_pos[selected], x()+tab_pos[selected+1], tab_width[selected], H, selected_child, tab_flags[selected], SELECTED); fl_pop_clip(); // -- draw the overflow menu button if (overflow_type == OVERFLOW_PULLDOWN) check_overflow_menu(); if (has_overflow_menu) draw_overflow_menu_button(); } // ---- draw the child area if (damage() & (FL_DAMAGE_ALL|FL_DAMAGE_CHILD)) { // clip to area below selection border fl_push_clip(x(), clipped_child_area_y, w(), clipped_child_area_h); if (damage() & (FL_DAMAGE_ALL)) { // draw the box and background around the child if (colored_selection_border) draw_box(box(), x(), y(), w(), h(), selected_tab_color); else draw_box(box(), x(), child_area_y, w(), child_area_h, selected_tab_color); // force draw the selected child if (selected_child) draw_child(*selected_child); } else if (damage() & (FL_DAMAGE_CHILD)) { // draw the selected child if (selected_child) update_child(*selected_child); } // stop clipping fl_pop_clip(); } clear_damage(); } /** Draw a tab in the top or bottom tabs area. Tabs can be selected, or on the left or right side of the selected tab. If overlapping, left tabs are drawn bottom to top using clipping. The selected tab is then the topmost, followed by the right side tabs drawn top to bottom. Tabs with the FL_WHEN_CLOSE bit set will draw a cross on their left side only if they are not compressed/overlapping. \param[in] x1 horizontal position of the left visible edge of the tab \param[in] x2 horizontal position of the following tab \param[in] W, H width and height of the tab \param[in] o the child widget that corresponds to this tab \param[in] flags if bit 1 is set, this tab is overlapped by another tab \param[in] what can be LEFT, SELECTED, or RIGHT to indicate if the tab is to the left side or the right side of the selected tab, or the selected tab itself */ void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int flags, int what) { x1 += tab_offset; x2 += tab_offset; int sel = (what == SELECTED); int dh = Fl::box_dh(box()); int wc = 0; // width of "close" button if drawn, or 0 char prev_draw_shortcut = fl_draw_shortcut; fl_draw_shortcut = 1; Fl_Boxtype bt = (o == push_ && !sel) ? fl_down(box()) : box(); Fl_Color bc = sel ? selection_color() : o->selection_color(); // Save the label color and label type Fl_Color oc = o->labelcolor(); Fl_Labeltype ot = o->labeltype(); // Set a labeltype that really draws a label if (ot == FL_NO_LABEL) o->labeltype(FL_NORMAL_LABEL); // compute offsets to make selected tab look bigger int yofs = sel ? 0 : BORDER; if ((x2 < x1+W) && what == RIGHT) x1 = x2 - W; if (H >= 0) { H += dh; draw_box(bt, x1, y() + yofs, W, H + 10 - yofs, bc); // Draw the label using the current color... o->labelcolor(sel ? labelcolor() : o->labelcolor()); // Draw the "close" button if requested if ( (o->when() & FL_WHEN_CLOSED) && !(flags & 1) ) { int sz = labelsize()/2, sy = (H - sz)/2; Fl_Color close_color = fl_contrast(FL_GRAY_RAMP+0, bc); if (!active_r()) close_color = fl_inactive(close_color); fl_draw_symbol("@3+", x1 + EXTRASPACE/2, y() + yofs/2 + sy, sz, sz, close_color); wc = sz + EXTRAGAP; } // Draw the label text o->draw_label(x1 + wc, y() + yofs, W - wc, H - yofs, tab_align()); // Draw the focus box if (Fl::focus() == this && o->visible()) draw_focus(bt, x1, y(), W, H, bc); } else { H = -H; H += dh; draw_box(bt, x1, y() + h() - H - 10, W, H + 10 - yofs, bc); // Draw the label using the current color... o->labelcolor(sel ? labelcolor() : o->labelcolor()); // Draw the "close" button if requested if ( (o->when() & FL_WHEN_CLOSED) && (x1+W < x2) ) { int sz = labelsize()/2, sy = (H - sz)/2; Fl_Color close_color = fl_contrast(FL_GRAY_RAMP+0, bc); if (!active_r()) close_color = fl_inactive(close_color); fl_draw_symbol("@3+", x1 + EXTRASPACE/2, y() + h() - H -yofs/2 + sy, sz, sz, close_color); wc = sz + EXTRAGAP; } // Draw the label text o->draw_label(x1 + wc, y() + h() - H, W - wc, H - yofs, tab_align()); // Draw the focus box if (Fl::focus() == this && o->visible()) draw_focus(bt, x1, y()+h()-H+1, W, H, bc); } fl_draw_shortcut = prev_draw_shortcut; // Restore the original label color and label type o->labelcolor(oc); o->labeltype(ot); } /** Creates a new Fl_Tabs widget using the given position, size, and label string. The default boxtype is FL_THIN_UP_BOX. Use add(Fl_Widget*) to add each child, which are usually Fl_Group widgets. The children should be sized to stay away from the top or bottom edge of the Fl_Tabs widget, which is where the tabs will be drawn. All children of Fl_Tabs should have the same size and exactly fit on top of each other. They should only leave space above or below where the tabs will go, but not on the sides. If the first child of Fl_Tabs is set to "resizable()", the riders will not resize when the tabs are resized. The destructor also deletes all the children. This allows a whole tree to be deleted at once, without having to keep a pointer to all the children in the user code. A kludge has been done so the Fl_Tabs and all of its children can be automatic (local) variables, but you must declare the Fl_Tabs widget first so that it is destroyed last. */ Fl_Tabs::Fl_Tabs(int X, int Y, int W, int H, const char *L) : Fl_Group(X,Y,W,H,L) { box(FL_THIN_UP_BOX); push_ = 0; overflow_type = OVERFLOW_COMPRESS; tab_offset = 0; tab_pos = 0; tab_width = 0; tab_flags = NULL; tab_count = 0; tab_align_ = FL_ALIGN_CENTER; has_overflow_menu = 0; } /** Delete allocated resources and destroy all children. */ Fl_Tabs::~Fl_Tabs() { clear_tab_positions(); } /** Returns the position and size available to be used by its children. If there isn't any child yet the \p tabh parameter will be used to calculate the return values. This assumes that the children's labelsize is the same as the Fl_Tabs' labelsize and adds a small border. If there are already children, the values of child(0) are returned, and \p tabh is ignored. \note Children should always use the same positions and sizes. \note This function requires access to the display drivers to determine the selected font height. If `client_area` is invoked before the first window is displayed, ensure that `fl_open_display()` is called beforehand. \p tabh can be one of \li 0: calculate label size, tabs on top \li -1: calculate label size, tabs on bottom \li > 0: use given \p tabh value, tabs on top (height = tabh) \li < -1: use given \p tabh value, tabs on bottom (height = -tabh) \param[in] tabh position and optional height of tabs (see above) \param[out] rx,ry,rw,rh (x,y,w,h) of client area for children \since FLTK 1.3.0 */ void Fl_Tabs::client_area(int &rx, int &ry, int &rw, int &rh, int tabh) { if (children()) { // use existing values rx = child(0)->x(); ry = child(0)->y(); rw = child(0)->w(); rh = child(0)->h(); } else { // calculate values int y_offset; int label_height = fl_height(labelfont(), labelsize()) + BORDER*2; if (tabh == 0) // use default (at top) y_offset = label_height; else if (tabh == -1) // use default (at bottom) y_offset = -label_height; else y_offset = tabh; // user given value rx = x(); rw = w(); if (y_offset >= 0) { // labels at top ry = y() + y_offset; rh = h() - y_offset; } else { // labels at bottom ry = y(); rh = h() + y_offset; } } } /** Clear internal array of tab positions and widths. \see tab_positions(). */ void Fl_Tabs::clear_tab_positions() { if (tab_pos) { free(tab_pos); tab_pos = 0; } if (tab_width){ free(tab_width); tab_width = 0; } if (tab_flags){ free(tab_flags); tab_flags = NULL; } } /** Set a method to handle an overflowing tab bar. The Fl_Tabs widget allows you to specify how to handle the situation where there are more tabs than can be displayed at once. The available options are: - \c OVERFLOW_COMPRESS: Tabs will be compressed and overlaid on top of each other. - \c OVERFLOW_CLIP: Only the first tabs that fit will be displayed. - \c OVERFLOW_PULLDOWN: Tabs that do not fit will be placed in a pull-down menu. - \c OVERFLOW_DRAG: The tab bar can be dragged horizontally to reveal additional tabs. You can set the desired behavior using the overflow() method. \param ov overflow type \see OVERFLOW_COMPRESS, OVERFLOW_CLIP, OVERFLOW_PULLDOWN, OVERFLOW_DRAG */ void Fl_Tabs::handle_overflow(int ov) { overflow_type = ov; tab_offset = 0; has_overflow_menu = 0; damage(FL_DAMAGE_SCROLL); redraw(); } fltk-1.4.3/src/Fl_System_Driver.H0000644000175000017500000002541515004135251016734 0ustar albrechtalbrecht// // A base class for platform specific system calls // for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \addtogroup DriverDeveloper \{ */ /** \file Fl_System_Driver.H \brief declaration of class Fl_System_Driver. */ /* Class hierarchy + Fl_System_Driver | + Fl_Posix_System_Driver | | + Fl_Unix_System_Driver | | + Fl_Darwin_System_Driver | + Fl_WinAPI_System_Driver */ #ifndef FL_SYSTEM_DRIVER_H #define FL_SYSTEM_DRIVER_H #include #include #include #include #include #include #include #include #include class Fl_File_Icon; class Fl_File_Browser; class Fl_Pixmap; class Fl_Widget; class Fl_Sys_Menu_Bar_Driver; /** \brief A base class for platform-specific system operations. This class is only for internal use by the FLTK library. Each supported platform implements several of the virtual methods of this class. */ class Fl_System_Driver { friend class Fl; protected: // implement once for each platform static Fl_System_Driver *newSystemDriver(); Fl_System_Driver(); static bool awake_ring_empty(); public: virtual ~Fl_System_Driver(); static int command_key; static int control_key; // implement if the system adds unwanted program argument(s) virtual int single_arg(const char *) { return 0; } // implement if the system adds unwanted program argument pair(s) virtual int arg_and_value(const char * /*name*/, const char * /*value*/) { return 0; } static void warning(const char* format, ...); // implement to set the default effect of Fl::warning() virtual void warning(const char* format, va_list args); static void error(const char* format, ...); // implement to set the default effect of Fl::error() virtual void error(const char* format, va_list args); static void fatal(const char* format, ...); // implement to set the default effect of Fl::error() virtual void fatal(const char* format, va_list args); // implement these to support cross-platform file operations virtual char *utf2mbcs(const char *s) {return (char*)s;} virtual char *getenv(const char*) {return NULL;} virtual int putenv(const char *) {return -1;} virtual int open(const char* /*f*/, int /*oflags*/, int /*pmode*/) {return -1;} // implement these to support cross-platform string operations virtual char *strdup(const char *) {return NULL;} // Note: the default implementation ignores the 'binary' argument. // Some platforms (notably Windows) may use this argument. virtual int open_ext(const char* f, int /*binary*/, int oflags, int pmode) { return this->open(f, oflags, pmode); } virtual FILE *fopen(const char* f, const char *mode); virtual int system(const char*) {return -1;} virtual int execvp(const char * /*file*/, char *const * /*argv*/) {return -1;} virtual int chmod(const char* /*f*/, int /*mode*/) {return -1;} virtual int access(const char* /*f*/, int /*mode*/) { return -1;} virtual int flstat(const char* /*f*/, struct stat *) { return -1;} virtual char *getcwd(char* /*b*/, int /*l*/) {return NULL;} virtual int chdir(const char*) {return -1;} virtual int unlink(const char*) {return -1;} virtual int mkdir(const char* /*f*/, int /*mode*/) {return -1;} virtual int rmdir(const char*) {return -1;} virtual int rename(const char* /*f*/, const char * /*n*/) {return -1;} // Windows commandline argument conversion to UTF-8. // Default implementation: no-op, overridden only on Windows virtual int args_to_utf8(int argc, char ** &argv) { return argc; } // the default implementation of these utf8... functions should be enough virtual unsigned utf8towc(const char* src, unsigned srclen, wchar_t* dst, unsigned dstlen); virtual unsigned utf8fromwc(char* dst, unsigned dstlen, const wchar_t* src, unsigned srclen); virtual int utf8locale() {return 1;} virtual unsigned utf8to_mb(const char* src, unsigned srclen, char* dst, unsigned dstlen); virtual unsigned utf8from_mb(char* dst, unsigned dstlen, const char* src, unsigned srclen); // implement to shield fprintf() from locale changes in decimal point virtual int clocale_vprintf(FILE *output, const char *format, va_list args); virtual int clocale_vsnprintf(char *output, size_t output_size, const char *format, va_list args); virtual int clocale_vsscanf(const char *input, const char *format, va_list args); // implement scandir-like function virtual int filename_list(const char * /*d*/, dirent ***, int (* /*sort*/)(struct dirent **, struct dirent **), char *errmsg=NULL, int errmsg_sz=0) { (void)errmsg; (void)errmsg_sz; return -1; } // the default implementation of filename_expand() may be enough virtual int filename_expand(char *to, int tolen, const char *from); // to implement virtual const char *getpwnam(const char *) {return NULL;} // the default implementation of filename_relative() is in src/filename_absolute.cxx and may be enough virtual int filename_relative(char *to, int tolen, const char *from, const char *base); // the default implementation of filename_absolute() is in src/filename_absolute.cxx and may be enough virtual int filename_absolute(char *to, int tolen, const char *from, const char *base); // the default implementation of filename_isdir() is in src/filename_isdir.cxx and may be enough virtual int filename_isdir(const char* n); // the default implementation of filename_isdir_quick() is in src/filename_isdir.cxx and may be enough virtual int filename_isdir_quick(const char* n); // the default implementation of filename_ext() is in src/filename_ext.cxx and may be enough virtual const char *filename_ext(const char *buf); // implement to support fl_filename_name() virtual const char *filename_name(const char *buf) {return buf;} // implement to support fl_open_uri() virtual int open_uri(const char * /*uri*/, char * /*msg*/, int /*msglen*/) {return 0;} // the default implementation of use_tooltip_timeout_condition() may be enough virtual int use_tooltip_timeout_condition() {return 0;} // the default implementation of use_recent_tooltip_fix() may be enough virtual int use_recent_tooltip_fix() {return 0;} // the default implementation of need_test_shortcut_extra() may be enough virtual int need_test_shortcut_extra() {return 0;} // implement to support Fl_File_Browser::load() virtual int file_browser_load_filesystem(Fl_File_Browser *, char * /*filename*/, int /*lname*/, Fl_File_Icon *) {return 0;} // the default implementation of file_browser_load_directory() should be enough virtual int file_browser_load_directory(const char *directory, char *filename, size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort, char *errmsg=NULL, int errmsg_sz=0); // implement to support Fl_Preferences virtual void newUUID(char *uuidBuffer) { uuidBuffer[0] = 0; } // implement to support Fl_Preferences virtual char *preference_rootnode(Fl_Preferences *, Fl_Preferences::Root, const char * /*vendor*/, const char * /*application*/) {return NULL;} // the default implementation of preferences_need_protection_check() may be enough virtual int preferences_need_protection_check() {return 0;} // implement to support Fl_Plugin_Manager::load() virtual void *load(const char *) {return NULL;} // the default implementation is most probably enough virtual void png_extra_rgba_processing(unsigned char * /*array*/, int /*w*/, int /*h*/) {} // the default implementation is most probably enough virtual const char *next_dir_sep(const char *start) { return strchr(start, '/');} // implement to support threading virtual void awake(void*) {} virtual int lock() {return 1;} virtual void unlock() {} virtual void* thread_message() {return NULL;} // implement to support Fl_File_Icon virtual int file_type(const char *filename); // implement to return the user's home directory name virtual const char *home_directory_name() { return ""; } // the default implementation is most probably enough virtual const char *filesystems_label() { return "File Systems"; } // return TRUE means \ same as / in file names virtual int backslash_as_slash() {return 0;} // return TRUE means : indicates a drive letter in file names virtual int colon_is_drive() {return 0;} // return TRUE means that files whose name begins with dot are hidden virtual int dot_file_hidden() {return 0;} // return TRUE when file names are case insensitive virtual int case_insensitive_filenames() {return 0;} // the implementations of local_to_latin1() and latin1_to_local() are in fl_encoding_latin1.cxx virtual const char *local_to_latin1(const char *t, int n); virtual const char *latin1_to_local(const char *t, int n); // the implementations of local_to_mac_roman() and mac_roman_to_local() are in fl_encoding_mac_roman.cxx virtual const char *local_to_mac_roman(const char *t, int n); virtual const char *mac_roman_to_local(const char *t, int n); // draw default tree view expando button virtual void tree_draw_expando_button(int x, int y, bool state, bool active); // the default implementation of tree_connector_style() is in Fl_Tree_Prefs.cxx and can be enough virtual int tree_connector_style(); virtual void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0); virtual void add_fd(int fd, Fl_FD_Handler cb, void* = 0); virtual void remove_fd(int, int when); virtual void remove_fd(int); // the default implementation of open_callback() may be enough virtual void open_callback(void (*)(const char *)); // The default implementation may be enough. virtual void gettime(time_t *sec, int *usec); // The default implementation of the next 4 functions may be enough. virtual const char *shift_name() { return "Shift"; } virtual const char *meta_name() { return "Meta"; } virtual const char *alt_name() { return "Alt"; } virtual const char *control_name() { return "Ctrl"; } virtual Fl_Sys_Menu_Bar_Driver *sys_menu_bar_driver() { return NULL; } virtual void lock_ring() {} virtual void unlock_ring() {} virtual double wait(double); // must FL_OVERRIDE virtual int ready() { return 0; } // must FL_OVERRIDE virtual int close_fd(int) {return -1;} // to close a file descriptor }; #endif // FL_SYSTEM_DRIVER_H /** \} \endcond */ fltk-1.4.3/src/Fl_Paged_Device.cxx0000644000175000017500000001231715004135251017044 0ustar albrechtalbrecht// // implementation of Fl_Paged_Device class for the Fast Light Tool Kit (FLTK). // // Copyright 2010-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_Paged_Device.cxx \brief implementation of class Fl_Paged_Device. */ #include #include #include /** \brief Begins a print job. \param[in] pagecount the total number of pages of the job (or 0 if you don't know the number of pages) \param[out] frompage if non-null, *frompage is set to the first page the user wants printed \param[out] topage if non-null, *topage is set to the last page the user wants printed \param[out] perr_message if non-null and if the returned value is ≥ 2, *perr_message is set to a string describing the error. That string can be delete[]'d after use. \return 0 if OK, 1 if user cancelled the job, ≥ 2 if any error. */ int Fl_Paged_Device::begin_job(int pagecount, int *frompage, int *topage, char **perr_message) {return 1;} /** \brief Begins a new printed page The page coordinates are initially in points, i.e., 1/72 inch, and with origin at the top left of the printable page area. This function also makes this surface the current drawing surface with Fl_Surface_Device::push_current(). \note begin_page() calls Fl_Surface_Device::push_current() and leaves this device as the active surface. If any calls between begin_page() and end_page() open dialog boxes or will otherwise draw into FLTK windows, those calls must be put between a call to Fl_Surface_Device::pop_current() and a call to Fl_Surface_Device::push_current(), or the content of the dialog box will be rendered to the printer instead of the screen. \return 0 if OK, non-zero if any error */ int Fl_Paged_Device::begin_page (void) {return 1;} /** \brief Computes the dimensions of margins that lie between the printable page area and the full page. Values are in the same unit as that used by FLTK drawing functions. They are changed by scale() calls. \param[out] left If non-null, *left is set to the left margin size. \param[out] top If non-null, *top is set to the top margin size. \param[out] right If non-null, *right is set to the right margin size. \param[out] bottom If non-null, *bottom is set to the bottom margin size. */ void Fl_Paged_Device::margins(int *left, int *top, int *right, int *bottom) {} /** \brief Changes the scaling of page coordinates. This function also resets the origin of graphics functions at top left of printable page area. After a scale() call, do a printable_rect() call to get the new dimensions of the printable page area. Successive scale() calls don't combine their effects. \param scale_x Horizontal dimensions of plot are multiplied by this quantity. \param scale_y Same as above, vertically. The value 0. is equivalent to setting \p scale_y = \p scale_x. Thus, scale(factor); is equivalent to scale(factor, factor); */ void Fl_Paged_Device::scale (float scale_x, float scale_y) {} /** \brief Rotates the graphics operations relatively to paper. The rotation is centered on the current graphics origin. Successive rotate() calls don't combine their effects. \param angle Rotation angle in counter-clockwise degrees. */ void Fl_Paged_Device::rotate(float angle) {} /** \brief To be called at the end of each page. This function also stops this surface from being the current drawing surface with Fl_Surface_Device::pop_current(). \note end_page() calls Fl_Surface_Device::pop_current(). If any calls between begin_page() and end_page() open dialog boxes or will otherwise draw into FLTK windows, those calls must be put between a call to Fl_Surface_Device::pop_current() and a call to Fl_Surface_Device::push_current(). \return 0 if OK, non-zero if any error. */ int Fl_Paged_Device::end_page (void) {return 1;} /** \brief To be called at the end of a print job. */ void Fl_Paged_Device::end_job (void) {} const Fl_Paged_Device::page_format Fl_Paged_Device::page_formats[NO_PAGE_FORMATS] = { // order of enum Page_Format // comes from appendix B of 5003.PPD_Spec_v4.3.pdf // A* // index(Ai) = i {2384, 3370, "A0"}, {1684, 2384, "A1"}, {1191, 1684, "A2"}, { 842, 1191, "A3"}, { 595, 842, "A4"}, { 420, 595, "A5"}, { 297, 420, "A6"}, { 210, 297, "A7"}, { 148, 210, "A8"}, { 105, 148, "A9"}, // B* // index(Bi) = i+10 {2920, 4127, "B0(JIS)"}, {2064, 2920, "B1(JIS)"}, {1460, 2064, "B2(JIS)"}, {1032, 1460, "B3(JIS)"}, { 729, 1032, "B4(JIS)"}, { 516, 729, "B5(JIS)"}, { 363, 516, "B6(JIS)"}, { 258, 363, "B7(JIS)"}, { 181, 258, "B8(JIS)"}, { 127, 181, "B9(JIS)"}, { 91, 127, "B10(JIS)"}, // others { 459, 649, "EnvC5"}, // envelope { 312, 624, "EnvDL"}, // envelope { 522, 756, "Executive"}, { 595, 935, "Folio"}, {1224, 792, "Ledger"}, // landscape { 612, 1008, "Legal"}, { 612, 792, "Letter"}, { 792, 1224, "Tabloid"}, { 297, 684, "Env10"} // envelope }; fltk-1.4.3/src/Fl_Help_Dialog_Dox.cxx0000644000175000017500000000760515004135251017532 0ustar albrechtalbrecht// // Fl_Help_Dialog dialog for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Fl_Help_Dialog (autogenerated class) doxygen documentation placeholder /** \class Fl_Help_Dialog The Fl_Help_Dialog widget displays a standard help dialog window using the Fl_Help_View widget. The Fl_Help_Dialog class is not part of the FLTK core library, but instead of \em fltk_images. Use \c --use-images when compiling with \c fltk-config . \image html Fl_Help_Dialog.png

\image latex Fl_Help_Dialog.png "Fl_Help_Dialog" width=8cm */ /** \fn Fl_Help_Dialog::Fl_Help_Dialog() The constructor creates the dialog pictured above.*/ /** \fn Fl_Help_Dialog::~Fl_Help_Dialog() The destructor destroys the widget and frees all memory that has been allocated for the current file. */ /** \fn void Fl_Help_Dialog::hide() Hides the Fl_Help_Dialog window.*/ /** \fn int Fl_Help_Dialog::load(const char *f) \brief Loads the specified HTML file into the Fl_Help_View widget. The filename can also contain a target name ("filename.html#target"). Always use forward slashes as path delimiters, Windows-style backslashes are not supported here. \param[in] f the name and path of an HTML file \return 0 on success, -1 on error \see Fl_Help_View::load(), fl_load_uri() */ /** \fn void Fl_Help_Dialog::position(int x, int y) Set the screen position of the dialog.*/ /** \fn void Fl_Help_Dialog::resize(int xx, int yy, int ww, int hh) Change the position and size of the dialog.*/ /** \fn void Fl_Help_Dialog::show() Shows the Fl_Help_Dialog window.*/ /** \fn void Fl_Help_Dialog::textsize(Fl_Fontsize s) Sets or gets the default text size for the help view.*/ /** \fn uchar Fl_Help_Dialog::textsize() Sets or gets the default text size for the help view.*/ /** \fn void Fl_Help_Dialog::topline(const char *n) Sets the top line in the Fl_Help_View widget to the named or numbered line. */ /** \fn void Fl_Help_Dialog::topline(int n) Sets the top line in the Fl_Help_View widget to the named or numbered line. */ /** \fn void Fl_Help_Dialog::value(const char *v) The first form sets the current buffer to the string provided and reformats the text. It also clears the history of the "back" and "forward" buttons. The second form returns the current buffer contents. */ /** \fn const char *Fl_Help_Dialog::value() const The first form sets the current buffer to the string provided and reformats the text. It also clears the history of the "back" and "forward" buttons. The second form returns the current buffer contents. */ /** \fn int Fl_Help_Dialog::visible() Returns 1 if the Fl_Help_Dialog window is visible.*/ /** \fn int Fl_Help_Dialog::x() Returns the position and size of the help dialog.*/ /** \fn int Fl_Help_Dialog::y() Returns the position and size of the help dialog.*/ /** \fn int Fl_Help_Dialog::w() Returns the position and size of the help dialog.*/ /** \fn int Fl_Help_Dialog::h() Returns the position and size of the help dialog.*/ /** \fn void Fl_Help_Dialog::show() Shows the main Help Dialog Window Delegates call to encapsulated window_ void Fl_Window::show() method */ /** \fn void Fl_Help_Dialog::show(int argc, char **argv) Shows the main Help Dialog Window Delegates call to encapsulated window_ void Fl_Window::show(int argc, char **argv) instance method */ /** \fn void Fl_Help_Dialog::textsize(Fl_Fontsize s) Sets the internal Fl_Help_View instance text size. Delegates call to encapsulated view_ void Fl_Help_View::textsize(Fl_Fontsize s) instance method */ fltk-1.4.3/src/fl_call_main.c0000644000175000017500000001317715004135251016151 0ustar albrechtalbrecht/* * Copyright 1998-2023 by Bill Spitzak and others. * * fl_call_main() calls main() for you Windows people. Needs to be done in C * because Borland C++ won't let you call main() from C++. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ /* * This WinMain() function can be overridden by an application and * is provided for compatibility with programs written for other * operating systems that conform to the ANSI standard entry point * "main()". This will allow you to build a Windows Application * without any special settings. * * You cannot have this WinMain() function in a DLL because it would have * to call \c main() outside the DLL. Thus, this nifty feature is only * available if you link to the static library. * * However, it is possible to build this module separately so you can * use it in progams that link to the shared library. * * Currently the debug version of this library will create a console window * for your application so you can put printf() statements for debugging or * informational purposes. Ultimately we want to update this to always use * the parent's console, but at present we have not identified a function * or API in Microsoft(r) Windows(r) that allows for it. */ /* * Notes for FLTK developers: * * 1) Since FLTK 1.4.0 this file is compiled only on Windows, hence we don't * need to test the _WIN32 macro. * 2) This file must not call any FLTK library functions because this would * not work with /both/ the DLL /and/ the static library (linkage stuff). * 3) Converting the commandline arguments to UTF-8 is therefore implemented * here *and* in the library but this seems to be an acceptable compromise. * 4) (Unless someone finds a better solution, of course. Albrecht) * 5) The condition "!defined(FL_DLL)" prevents building this in the shared * library, i.e. "WinMain()" will not be defined in the shared lib (DLL). * 6) The condition "!defined (__GNUC__)" prevents compilation of this * module with MinGW, MSYS, and Cygwin which don't use WinMain(). * 7) It is unclear if there are other build systems on Windows that need a * WinMain() entry point. Earlier comments and code seem to indicate that * Borland C++ would require it. */ #if !defined(FL_DLL) && !defined (__GNUC__) #include #include #include #include extern int main(int, char *[]); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int rc; int i; int argc = 0; char** argv = NULL; /* * If we are compiling in debug mode, open a console window so * we can see any printf's, etc... * * While we can detect if the program was run from the command-line - * look at the CMDLINE environment variable, it will be "WIN" for * programs started from the GUI - the shell seems to run all Windows * applications in the background anyways... */ #ifdef _DEBUG AllocConsole(); freopen("conin$", "r", stdin); freopen("conout$", "w", stdout); freopen("conout$", "w", stderr); #endif /* _DEBUG */ /* Get the command line arguments as Windows Wide Character strings */ LPWSTR *wideArgv = CommandLineToArgvW(GetCommandLineW(), &argc); /* Allocate an array of 'argc + 1' string pointers */ argv = (char **)malloc((argc + 1) * sizeof(char *)); /* Convert the command line arguments to UTF-8 */ for (i = 0; i < argc; i++) { /* find the required size of the buffer */ int u8size = WideCharToMultiByte(CP_UTF8, /* CodePage */ 0, /* dwFlags */ wideArgv[i], /* lpWideCharStr */ -1, /* cchWideChar */ NULL, /* lpMultiByteStr */ 0, /* cbMultiByte */ NULL, /* lpDefaultChar */ NULL); /* lpUsedDefaultChar */ if (u8size > 0) { char *strbuf = (char *)malloc(u8size); int ret = WideCharToMultiByte(CP_UTF8, /* CodePage */ 0, /* dwFlags */ wideArgv[i], /* lpWideCharStr */ -1, /* cchWideChar */ strbuf, /* lpMultiByteStr */ u8size, /* cbMultiByte */ NULL, /* lpDefaultChar */ NULL); /* lpUsedDefaultChar */ if (ret) { argv[i] = strbuf; } else { argv[i] = _strdup(""); free(strbuf); } } else { argv[i] = _strdup(""); } } argv[argc] = NULL; /* required by C standard at end of list */ /* Free the wide character string array */ LocalFree(wideArgv); /* Call the program's entry point main() */ rc = main(argc, argv); /* Cleanup allocated memory for argv */ for (int i = 0; i < argc; ++i) { free((void *)argv[i]); } free((void *)argv); /* Close the console in debug mode */ #ifdef _DEBUG fclose(stdin); fclose(stdout); fclose(stderr); #endif /* _DEBUG */ return rc; } #else /* STR# 2973: solves "empty translation unit" error */ typedef int dummy; #endif /* !defined(FL_DLL) && !defined (__GNUC__) */ fltk-1.4.3/src/fl_open_uri.cxx0000644000175000017500000000743515004135251016432 0ustar albrechtalbrecht// // fl_open_uri() code for FLTK. // // Test with: // // gcc -I/fltk/dir -I/fltk/dir/src -DTEST -o fl_open_uri fl_open_uri.cxx -lfltk // // Copyright 2003-2010 by Michael R Sweet // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // Include necessary headers... // #include #include #include #include "Fl_System_Driver.H" #include #include #include "flstring.h" /** \addtogroup filenames \{ */ /** Opens the specified Uniform Resource Identifier (URI). Uses an operating-system dependent program or interface. For URIs using the "ftp", "http", or "https" schemes, the system default web browser is used to open the URI, while "mailto" and "news" URIs are typically opened using the system default mail reader and "file" URIs are opened using the file system navigator. On success, the (optional) msg buffer is filled with the command that was run to open the URI; on Windows, this will always be "open uri". On failure, the msg buffer is filled with an English error message. \note \b Platform \b Specific \b Issues: \b Windows \n With "file:" based URIs on Windows, you may encounter issues with anchors being ignored. Example: "file:///c:/some/index.html#anchor" may open in the browser without the "#anchor" suffix. The behavior seems to vary across different Windows versions. Workaround: open a link to a separate html file that redirects to the desired "file:" URI. \b Example \code #include [..] char errmsg[512]; if ( !fl_open_uri("http://google.com/", errmsg, sizeof(errmsg)) ) { char warnmsg[768]; sprintf(warnmsg, "Error: %s", errmsg); fl_alert(warnmsg); } \endcode \param uri The URI to open \param msg Optional buffer which contains the command or error message \param msglen Length of optional buffer \return 1 on success, 0 on failure */ int fl_open_uri(const char *uri, char *msg, int msglen) { // Supported URI schemes... static const char * const schemes[] = { "file://", "ftp://", "http://", "https://", "mailto:", "news://", NULL }; // Validate the URI scheme... int i; for (i = 0; schemes[i]; i ++) if (!strncmp(uri, schemes[i], strlen(schemes[i]))) break; if (!schemes[i]) { if (msg) { char scheme[255]; if (sscanf(uri, "%254[^:]", scheme) == 1) { snprintf(msg, msglen, "URI scheme \"%s\" not supported.", scheme); } else { snprintf(msg, msglen, "Bad URI \"%s\"", uri); } } return 0; } return Fl::system_driver()->open_uri(uri, msg, msglen); } /** Decodes a URL-encoded string. In a Uniform Resource Identifier (URI), all non-ASCII bytes and several others (e.g., '<', '%', ' ') are URL-encoded using 3 bytes by "%XY" where XY is the hexadecimal value of the byte. This function decodes the URI restoring its original UTF-8 encoded content. Decoding is done in-place. */ void fl_decode_uri(char *uri) { char *last = uri + strlen(uri); while (uri < last-2) { if (*uri == '%') { int h; if ( sscanf(uri+1, "%2X", &h) != 1 ) break; *uri = h; memmove(uri+1, uri+3, last - (uri+2)); last -= 2; } uri++; } } /** @} */ #ifdef TEST // // Test code... // // Open the URI on the command-line... int main(int argc, char **argv) { char msg[1024]; if (argc != 2) { puts("Usage: fl_open_uri URI"); return 1; } if (!fl_open_uri(argv[1], msg, sizeof(msg))) { puts(msg); return 1; } else return 0; } #endif // TEST fltk-1.4.3/src/Fl_Tree.cxx0000644000175000017500000027353315004135251015455 0ustar albrechtalbrecht// #include #include #include #include #include #include ////////////////////// // Fl_Tree.cxx ////////////////////// // // Fl_Tree -- This file is part of the Fl_Tree widget for FLTK // Copyright (C) 2009-2010 by Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // INTERNAL: scroller callback (hor+vert scroll) static void scroll_cb(Fl_Widget*,void *data) { ((Fl_Tree*)data)->redraw(); } // INTERNAL: Parse elements from 'path' into an array of null terminated strings // Handles escape characters, ignores multiple /'s. // Path="/aa/bb", returns arr[0]="aa", arr[1]="bb", arr[2]=0. // Caller must call free_path(arr). // static char **parse_path(const char *path) { size_t len = strlen(path); char *cp = new char[(len+1)], *word = cp, *s = cp; // freed below or in free_path() char **ap = new char*[(len+1)], **arr = ap; // overallocates arr[] while (1) { if (*path =='/' || *path == 0) { // handle path sep or eos if (word != s) { *s++ = 0; *arr++= word; word = s; } if ( !*path++) break; else continue; // eos? done, else cont } else if ( *path == '\\' ) { // handle escape if ( *(++path) ) { *s++ = *path++; } else continue; } else { *s++ = *path++; } // handle normal char } *arr = 0; if ( arr == ap ) delete[] cp; // empty arr[]? delete since free_path() can't return ap; } // INTERNAL: Free an array 'arr' returned by parse_path() static void free_path(char **arr) { if ( arr ) { if ( arr[0] ) { delete[] arr[0]; } // deletes cp in parse_path delete[] arr; // deletes ptr array } } #if 0 /* unused code -- STR #3169 */ // INTERNAL: Recursively descend 'item's tree hierarchy // accumulating total child 'count' // static int find_total_children(Fl_Tree_Item *item, int count=0) { count++; for ( int t=0; tchildren(); t++ ) { count = find_total_children(item->child(t), count); } return(count); } #endif /// Constructor. Fl_Tree::Fl_Tree(int X, int Y, int W, int H, const char *L) : Fl_Group(X,Y,W,H,L) { _root = new Fl_Tree_Item(this); _root->parent(0); // we are root of tree _root->label("ROOT"); _item_focus = 0; _callback_item = 0; _callback_reason = FL_TREE_REASON_NONE; _scrollbar_size = 0; // 0: uses Fl::scrollbar_size() _lastselect = 0; box(FL_DOWN_BOX); color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR); when(FL_WHEN_CHANGED); int scrollsize = _scrollbar_size ? _scrollbar_size : Fl::scrollbar_size(); _vscroll = new Fl_Scrollbar(X+W-scrollsize,Y,scrollsize,H); _vscroll->hide(); _vscroll->type(FL_VERTICAL); _vscroll->step(1); _vscroll->callback(scroll_cb, (void*)this); _hscroll = new Fl_Scrollbar(X,Y+H-scrollsize,W,scrollsize); _hscroll->hide(); _hscroll->type(FL_HORIZONTAL); _hscroll->step(1); _hscroll->callback(scroll_cb, (void*)this); _tox = _tix = X + Fl::box_dx(box()); _toy = _tiy = Y + Fl::box_dy(box()); _tow = _tiw = W - Fl::box_dw(box()); _toh = _tih = H - Fl::box_dh(box()); _tree_w = -1; _tree_h = -1; end(); } /// Destructor. Fl_Tree::~Fl_Tree() { if ( _root ) { delete _root; _root = 0; } } /// Extend the selection between and including \p 'from' and \p 'to' /// depending on direction \p 'dir', \p 'val', and \p 'visible'. /// /// Efficient: does not walk entire tree; starts with \p 'from' and stops /// at \p 'to' while moving in direction \p 'dir'. Dir must be specified though. /// /// If dir cannot be known in advance, such as during SHIFT-click operations, /// the method extend_selection(Fl_Tree_Item*,Fl_Tree_Item*,int,bool) /// should be used. /// /// Handles calling redraw() if anything changed. /// /// \param[in] from Starting item /// \param[in] to Ending item /// \param[in] dir Direction to extend selection (FL_Up or FL_Down) /// \param[in] val 0=deselect, 1=select, 2=toggle /// \param[in] visible true=affect only open(), visible items,
/// false=affect open or closed items (default) /// \returns The number of items whose selection states were changed, if any. /// \version 1.3.3 /// int Fl_Tree::extend_selection_dir(Fl_Tree_Item *from, Fl_Tree_Item *to, int dir, int val, bool visible ) { int changed = 0; for (Fl_Tree_Item *item=from; item; item = next_item(item, dir, visible) ) { switch (val) { case 0: if ( deselect(item, when()) ) ++changed; break; case 1: if ( select(item, when()) ) ++changed; break; case 2: select_toggle(item, when()); ++changed; // toggle always involves a change break; } if ( item==to ) break; } return(changed); } /// Extend a selection between \p 'from' and \p 'to' depending on \p 'visible'. /// /// Similar to the more efficient /// extend_selection_dir(Fl_Tree_Item*,Fl_Tree_Item*,int dir,int val,bool vis) /// method, but direction (up or down) doesn't need to be known.
/// We're less efficient because we search the tree for to/from, then operate /// on items in between. The more efficient method avoids the "search", /// but necessitates a direction to be specified to find \p 'to'.
/// Used by SHIFT-click to extend a selection between two items inclusive.
/// Handles calling redraw() if anything changed. /// /// \param[in] from Starting item /// \param[in] to Ending item /// \param[in] val Select or deselect items (0=deselect, 1=select, 2=toggle) /// \param[in] visible true=affect only open(), visible items,
/// false=affect open or closed items (default) /// \returns The number of items whose selection states were changed, if any. /// \version 1.3.3 ABI feature int Fl_Tree::extend_selection(Fl_Tree_Item *from, Fl_Tree_Item *to, int val, bool visible) { int changed = 0; if ( from == to ) { if ( visible && !from->is_visible() ) return(0); // do nothing switch (val) { case 0: if ( deselect(from, when()) ) ++changed; break; case 1: if ( select(from, when()) ) ++changed; break; case 2: select_toggle(from, when()); ++changed; // always changed break; } return(changed); } char on = 0; for ( Fl_Tree_Item *item = first(); item; item = item->next_visible(_prefs) ) { if ( visible && !item->is_visible() ) continue; if ( on || (item == from) || (item == to) ) { switch (val) { case 0: if ( deselect(item, when()) ) ++changed; break; case 1: if ( select(item, when()) ) ++changed; break; case 2: select_toggle(item, when()); ++changed; // toggle always involves a change break; } if ( (item == from) || (item == to) ) { on ^= 1; if ( !on ) break; // done } } } return(changed); } enum { PUSHED_NONE=0, PUSHED_OPEN_CLOSE, PUSHED_USER_ICON, PUSHED_LABEL }; /// Standard FLTK event handler for this widget. /// \todo add Fl_Widget_Tracker (see Fl_Browser_.cxx::handle()) int Fl_Tree::handle(int e) { if (e == FL_NO_EVENT) return(0); // XXX: optimize to prevent slow resizes on large trees! int ret = 0; char is_shift = Fl::event_state() & FL_SHIFT ? 1 : 0; char is_ctrl = Fl::event_state() & FL_CTRL ? 1 : 0; char is_command = Fl::event_state() & FL_COMMAND ? 1 : 0; // ctrl on win/lin, 'Command' on mac // Developer note: Fl_Browser_::handle() used for reference here.. // #include // for event debugging // fprintf(stderr, "DEBUG: %s (%d)\n", fl_eventnames[e], e); if (e == FL_ENTER || e == FL_LEAVE) return(1); switch (e) { case FL_FOCUS: { // FLTK tests if we want focus. // If a nav key was used to give us focus, and we've got no saved // focus widget, determine which item gets focus depending on nav key. // if ( ! _item_focus ) { // no focus established yet? switch (Fl::event_key()) { // determine if focus was navigated.. case FL_Tab: { // received focus via TAB? int updown = is_shift ? FL_Up : FL_Down; // SHIFT-TAB similar to Up, TAB similar to Down set_item_focus(next_visible_item(0, updown)); break; } case FL_Left: // received focus via LEFT or UP? case FL_Up: { // XK_ISO_Left_Tab set_item_focus(next_visible_item(0, FL_Up)); break; } case FL_Right: // received focus via RIGHT or DOWN? case FL_Down: default: { set_item_focus(next_visible_item(0, FL_Down)); break; } } } if ( visible_focus() ) redraw(); // draw focus change return(1); } case FL_UNFOCUS: { // FLTK telling us some other widget took focus. if ( visible_focus() ) redraw(); // draw focus change return(1); } case FL_KEYBOARD: { // keyboard shortcut // Do shortcuts first or scrollbar will get them... if ( (Fl::focus() == this) && // tree has focus? _prefs.selectmode() > FL_TREE_SELECT_NONE ) { // select mode that supports kb events? if ( !_item_focus ) { // no current focus item? set_item_focus(first_visible_item()); // use first vis item if ( Fl::event_key() == FL_Up || // Up or down? Fl::event_key() == FL_Down ) // ..if so, already did 'motion' return(1); // ..so just return. } if ( _item_focus ) { int ekey = Fl::event_key(); switch (ekey) { case FL_Enter: // ENTER: toggle open/close case FL_KP_Enter: { open_toggle(_item_focus, when()); // toggle item in focus return(1); // done, we handled key } case ' ': // SPACE: change selection state switch ( _prefs.selectmode() ) { case FL_TREE_SELECT_NONE: break; // ignore, let group have shot at event case FL_TREE_SELECT_SINGLE: case FL_TREE_SELECT_SINGLE_DRAGGABLE: if ( is_ctrl ) { // CTRL-SPACE: (single mode) toggle if ( ! _item_focus->is_selected() ) { select_only(_item_focus, when()); } else { deselect_all(0, when()); } } else { select_only(_item_focus, when()); // SPACE: (single mode) select only } _lastselect = _item_focus; return(1); // done, we handled key case FL_TREE_SELECT_MULTI: if ( is_ctrl ) { select_toggle(_item_focus, when()); // CTRL-SPACE: (multi mode) toggle selection } else { select(_item_focus, when()); // SPACE: (multi-mode) select } _lastselect = _item_focus; return(1); // done, we handled key } break; case FL_Right: // RIGHT: open children (if any) case FL_Left: { // LEFT: close children (if any) if ( _item_focus ) { if ( ekey == FL_Right && _item_focus->is_close() ) { open(_item_focus); // open closed item ret = 1; } else if ( ekey == FL_Left && _item_focus->is_open() ) { close(_item_focus); // close open item ret = 1; } return(1); } break; } case FL_Up: // UP: next item up, or extend selection up case FL_Down: { // DOWN: next item down, or extend selection down set_item_focus(next_visible_item(_item_focus, ekey)); // next item up|dn if ( _item_focus ) { // item in focus? // Autoscroll int itemtop = _item_focus->y(); int itembot = _item_focus->y()+_item_focus->h(); if ( itemtop < y() ) { show_item_top(_item_focus); } if ( itembot > y()+h() ) { show_item_bottom(_item_focus); } // Extend selection if ( _prefs.selectmode() == FL_TREE_SELECT_MULTI && // multiselect on? is_shift && // shift key? ! _item_focus->is_selected() ) { // not already selected? select(_item_focus, when()); // extend selection.. _lastselect = _item_focus; } return(1); } break; } case 'a': case 'A': { if ( is_command ) { // ^A (win/linux), Meta-A (mac) switch ( _prefs.selectmode() ) { case FL_TREE_SELECT_NONE: case FL_TREE_SELECT_SINGLE: case FL_TREE_SELECT_SINGLE_DRAGGABLE: break; case FL_TREE_SELECT_MULTI: // Do a 'select all' select_all(); _lastselect = first_visible_item(); take_focus(); return(1); } } break; } } } } break; } } // Let Fl_Group take a shot at handling the event if (Fl_Group::handle(e)) { return(1); // handled? don't continue below } // Handle events the child FLTK widgets didn't need // fprintf(stderr, "Fl_Tree::handle(): Event was %s (%d)\n", fl_eventnames[e], e); // DEBUGGING if ( ! _root ) return(ret); static int last_my = 0; switch ( e ) { case FL_PUSH: { // clicked on tree last_my = Fl::event_y(); // save for dragging direction.. if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); Fl_Tree_Item *item = find_clicked(0); // Tell FL_DRAG what was pushed _lastpushed = item ? item->event_on_collapse_icon(_prefs) ? PUSHED_OPEN_CLOSE // open/close icon clicked : item->event_on_user_icon(_prefs) ? PUSHED_USER_ICON // usericon clicked : PUSHED_LABEL // label clicked : PUSHED_NONE; // none of the above if ( !item ) { // clicked, but not on an item? _lastselect = 0; switch ( _prefs.selectmode() ) { case FL_TREE_SELECT_NONE: break; case FL_TREE_SELECT_SINGLE: case FL_TREE_SELECT_SINGLE_DRAGGABLE: case FL_TREE_SELECT_MULTI: deselect_all(); break; } break; } set_item_focus(item); // becomes new focus widget, calls redraw() if needed ret |= 1; // handled if ( Fl::event_button() == FL_LEFT_MOUSE ) { if ( item->event_on_collapse_icon(_prefs) ) { // collapse icon clicked? open_toggle(item); // toggle open (handles redraw) } else if ( !item->widget() || !Fl::event_inside(item->widget()) ) { // not inside widget() switch ( _prefs.selectmode() ) { case FL_TREE_SELECT_NONE: break; case FL_TREE_SELECT_SINGLE: case FL_TREE_SELECT_SINGLE_DRAGGABLE: select_only(item, when()); // select only this item (handles redraw) _lastselect = item; break; case FL_TREE_SELECT_MULTI: { if ( is_shift ) { // SHIFT+PUSH? if ( _lastselect ) { int val = is_ctrl ? 2 : 1; bool visible = true; extend_selection(_lastselect, item, val, visible); } else { select(item); // add to selection } } else if ( is_ctrl ) { // CTRL+PUSH? select_toggle(item, when()); // toggle selection state } else { select_only(item, when()); } _lastselect = item; break; } } } } break; } case FL_DRAG: { // FL_PUSH outside item or on open/close? // Ignore drag to prevent unexpected selections (STR #3527) // if ( _lastpushed == PUSHED_NONE || _lastpushed == PUSHED_OPEN_CLOSE ) return 0; // Do scrolling first // Detect up/down dragging int my = Fl::event_y(); int dir = (my>last_my) ? FL_Down : FL_Up; last_my = my; // Handle autoscrolling if ( my < y() ) { // Above top? dir = FL_Up; // ..going up int p = vposition()-(y()-my); // ..position above us if ( p < 0 ) p = 0; // ..don't go above 0 vposition(p); // ..scroll to new position } else if ( my > (y()+h()) ) { // Below bottom? dir = FL_Down; // ..going down int p = vposition()+(my-y()-h()); // ..position below us if ( p > (int)_vscroll->maximum() ) // ..don't go below bottom p = (int)_vscroll->maximum(); vposition(p); // ..scroll to new position } // Now handle the event.. // During drag, only interested in left-mouse operations. // if ( Fl::event_button() != FL_LEFT_MOUSE ) break; Fl_Tree_Item *item = find_clicked(1); // item we're on, vertically if ( !item ) break; // not near item? ignore drag event ret |= 1; // acknowledge event if (_prefs.selectmode() != FL_TREE_SELECT_SINGLE_DRAGGABLE) set_item_focus(item); // becomes new focus item if (item==_lastselect) break; // same item as before? avoid reselect // Handle selection behavior switch ( _prefs.selectmode() ) { case FL_TREE_SELECT_NONE: break; // no selection changes case FL_TREE_SELECT_SINGLE: { select_only(item, when()); // select only this item (handles redraw) break; } case FL_TREE_SELECT_SINGLE_DRAGGABLE: { item = _lastselect; // Keep the source intact redraw(); break; } case FL_TREE_SELECT_MULTI: { Fl_Tree_Item *from = next_visible_item(_lastselect, dir); // avoid reselecting item Fl_Tree_Item *to = item; int val = is_ctrl ? 2 : 1; // toggle_select() or just select()? bool visible = true; extend_selection_dir(from, to, dir, val, visible); break; } } _lastselect = item; // save current item for later break; } case FL_RELEASE: if (_prefs.selectmode() == FL_TREE_SELECT_SINGLE_DRAGGABLE && Fl::event_button() == FL_LEFT_MOUSE) { Fl_Tree_Item *item = find_clicked(1); // item mouse is over (vertically) if (item && // mouse over valid item? _lastselect && // item being dragged is valid? item != _lastselect) { // item we're over not same as drag item? // Are we dropping above or below the target item? const int h = Fl::event_y() - item->y(); // mouse relative to item's top/left const int mid = item->h() / 2; // middle of item relative to item's top/left const bool is_above = h < mid; // is mouse above middle of item? //printf("Dropping %s target item\n", is_above ? "above" : "below"); Fl_Tree_Item *target = is_above ? prev(item) : next(item); // target item if ( target != _lastselect ) { // Don't drop on self Fl_Tree_Item *parent = item->parent(); // find parent for item mouse is over if ( !parent ) { // no parent (root)? // Special case for root; Drop as first child _lastselect->move_into(root(), 0); } else { // Not root.. if (item->children() && item->is_open() && !is_above) { // Special case: Drop onto open folder below midline? // Drop as first child (pos=0) // _lastselect->move_into(item, 0); // STR #3432 } else if (_lastselect->parent() == parent) { // If we're moving inside same parent, use the below/above methods if (is_above) _lastselect->move_above(item); else _lastselect->move_below(item); } else { // Moving to different parent.. int pos = parent->find_child(item); // find position of item in parent if (!is_above) pos++; // below? next position down _lastselect->move_into(parent, pos); // move item into parent at position } } redraw(); do_callback_for_item(_lastselect, FL_TREE_REASON_DRAGGED); } } redraw(); } // End single-drag check ret |= 1; break; } return(ret); } /// Recalculate widget dimensions and scrollbar visibility, /// normally managed automatically. /// /// Low overhead way to update the tree widget's outer/inner dimensions /// and re-determine scrollbar visibility based on these changes without /// recalculating the entire size of the tree data. /// /// Assumes that either the tree's size in _tree_w/_tree_h are correct /// so that scrollbar visibility can be calculated easily, or are both /// zero indicating scrollbar visibility can't be calculated yet. /// /// This method is called when the widget is resize()ed or if the /// scrollbar's sizes are changed (affects tree widget's inner dimensions /// tix/y/w/h), and also used by calc_tree(). /// \version 1.3.3 ABI feature /// void Fl_Tree::calc_dimensions() { // Calc tree outer xywh // Area of the tree widget /outside/ scrollbars // _tox = x() + Fl::box_dx(box()); _toy = y() + Fl::box_dy(box()); _tow = w() - Fl::box_dw(box()); _toh = h() - Fl::box_dh(box()); // Scrollbar visiblity + positions // Calc this ONLY if tree_h and tree_w have been calculated. // Zero values for these indicate calc in progress, but not done yet. // if ( _tree_h >= 0 && _tree_w >= 0 ) { int scrollsize = _scrollbar_size ? _scrollbar_size : Fl::scrollbar_size(); int vshow = _tree_h > _toh ? 1 : 0; int hshow = _tree_w > _tow ? 1 : 0; // See if one scroller's appearance affects the other's visibility if ( hshow && !vshow && (_tree_h > (_toh-scrollsize)) ) vshow = 1; if ( vshow && !hshow && (_tree_w > (_tow-scrollsize)) ) hshow = 1; // vertical scrollbar visibility if ( vshow ) { _vscroll->show(); _vscroll->resize(_tox+_tow-scrollsize, _toy, scrollsize, h()-Fl::box_dh(box()) - (hshow ? scrollsize : 0)); } else { _vscroll->hide(); _vscroll->value(0); } // horizontal scrollbar visibility if ( hshow ) { _hscroll->show(); _hscroll->resize(_tox, _toy+_toh-scrollsize, _tow - (vshow ? scrollsize : 0), scrollsize); } else { _hscroll->hide(); _hscroll->value(0); } // Calculate inner dimensions // The area the tree occupies inside the scrollbars and margins // _tix = _tox; _tiy = _toy; _tiw = _tow - (_vscroll->visible() ? _vscroll->w() : 0); _tih = _toh - (_hscroll->visible() ? _hscroll->h() : 0); // Scrollbar tab sizes _vscroll->slider_size(float(_tih) / float(_tree_h)); _vscroll->range(0.0, _tree_h - _tih); _hscroll->slider_size(float(_tiw) / float(_tree_w)); _hscroll->range(0.0, _tree_w - _tiw); } else { // Best we can do without knowing tree_h/tree_w _tix = _tox; _tiy = _toy; _tiw = _tow; _tih = _toh; } } /// Recalculates the tree's sizes and scrollbar visibility, /// normally managed automatically. /// /// On return: /// - _tree_w will be the overall pixel width of the entire viewable tree /// - _tree_h will be the overall pixel height "" /// - scrollbar visibility and pan sizes are updated /// - internal _tix/_tiy/_tiw/_tih dimensions are updated /// /// _tree_w/_tree_h include the tree's margins (e.g. marginleft()), /// whether items are open or closed, label contents and font sizes, etc. /// /// The tree hierarchy's size is managed separately from the widget's /// size as an optimization; this way resize() on the widget doesn't /// involve recalculating the tree's hierarchy needlessly, as widget /// size has no bearing on the tree hierarchy. /// /// The tree hierarchy's size only changes when items are added/removed, /// open/closed, label contents or font sizes changed, margins changed, etc. /// /// This calculation involves walking the *entire* tree from top to bottom, /// potentially a slow calculation if the tree has many items (potentially /// hundreds of thousands), and should therefore be called sparingly. /// /// For this reason, recalc_tree() is used as a way to /schedule/ /// calculation when changes affect the tree hierarchy's size. /// /// Apps may want to call this method directly if the app makes changes /// to the tree's geometry, then immediately needs to work with the tree's /// new dimensions before an actual redraw (and recalc) occurs. (This /// use by an app should only rarely be needed) /// void Fl_Tree::calc_tree() { // Set tree width and height to zero, and recalc just _tox/_toy/_tow/_toh for now. _tree_w = _tree_h = -1; calc_dimensions(); if ( !_root ) return; // Walk the tree to determine its width and height. // We need this to compute scrollbars.. // By the end, 'Y' will be the lowest point on the tree // int X = _tix + _prefs.marginleft() + _hscroll->value(); int Y = _tiy + _prefs.margintop() - _vscroll->value(); int W = _tiw; // Adjust root's X/W if connectors off if (_prefs.connectorstyle() == FL_TREE_CONNECTOR_NONE) { X -= _prefs.openicon_w(); W += _prefs.openicon_w(); } int xmax = 0, render = 0, ytop = Y; fl_font(_prefs.labelfont(), _prefs.labelsize()); _root->draw(X, Y, W, 0, xmax, 1, render); // descend into tree without drawing (render=0) // Save computed tree width and height _tree_w = _prefs.marginleft() + xmax - X; // include margin in tree's width _tree_h = _prefs.margintop() + Y - ytop; // include margin in tree's height // Calc tree dims again; now that tree_w/tree_h are known, scrollbars are calculated. calc_dimensions(); } void Fl_Tree::resize(int X,int Y,int W, int H) { fix_scrollbar_order(); Fl_Group::resize(X,Y,W,H); calc_dimensions(); init_sizes(); } /// Standard FLTK draw() method, handles drawing the tree widget. void Fl_Tree::draw() { fix_scrollbar_order(); // Has tree recalc been scheduled? If so, do it if ( _tree_w == -1 ) calc_tree(); else calc_dimensions(); // Let group draw box+label but *NOT* children. // We handle drawing children ourselves by calling each item's draw() { // Draw group's bg + label if ( damage() & ~FL_DAMAGE_CHILD) { // redraw entire widget? Fl_Group::draw_box(); Fl_Group::draw_label(); } if ( ! _root ) return; // These values are changed during drawing // By end, 'Y' will be the lowest point on the tree int X = _tix + _prefs.marginleft() - _hscroll->value(); int Y = _tiy + _prefs.margintop() - _vscroll->value(); int W = _tiw - X + _tix; // Adjust root's X/W if connectors off if (_prefs.connectorstyle() == FL_TREE_CONNECTOR_NONE) { X -= _prefs.openicon_w(); W += _prefs.openicon_w(); } // Draw entire tree, starting with root fl_push_clip(_tix,_tiy,_tiw,_tih); { int xmax = 0; fl_font(_prefs.labelfont(), _prefs.labelsize()); _root->draw(X, Y, W, // descend into tree here to draw it (Fl::focus()==this)?_item_focus:0, // show focus item ONLY if Fl_Tree has focus xmax, 1, 1); } fl_pop_clip(); } // Draw scrollbars last draw_child(*_vscroll); draw_child(*_hscroll); // That little tile between the scrollbars if ( _vscroll->visible() && _hscroll->visible() ) { fl_color(_vscroll->color()); fl_rectf(_hscroll->x()+_hscroll->w(), _vscroll->y()+_vscroll->h(), _vscroll->w(), _hscroll->h()); } // Draw dragging line if (_prefs.selectmode() == FL_TREE_SELECT_SINGLE_DRAGGABLE && // drag mode? Fl::pushed() == this) { // item clicked is the one we're drawing? Fl_Tree_Item *item = find_clicked(1); // item we're on, vertically if (item && // we're over a valid item? item != _item_focus) { // item doesn't have keyboard focus? // Are we dropping above or below the target item? const int h = Fl::event_y() - item->y(); // mouse relative to item's top/left const int mid = item->h() / 2; // middle of item relative to item's top/left const bool is_above = h < mid; // is mouse above middle of item? fl_color(FL_BLACK); int tgt = item->y() + (is_above ? 0 : item->h()); fl_line(item->x(), tgt, item->x() + item->w(), tgt); } } } /// Print the tree as 'ascii art' to stdout. /// Used mainly for debugging. /// \todo should be const /// \version 1.3.0 /// void Fl_Tree::show_self() { if ( ! _root ) return; _root->show_self(); } /// Set the label for the root item to \p 'new_label'. /// /// Makes an internally managed copy of 'new_label'. /// void Fl_Tree::root_label(const char *new_label) { if ( ! _root ) return; _root->label(new_label); } /// Returns the root item. Fl_Tree_Item* Fl_Tree::root() { return(_root); } /// Sets the root item to \p 'newitem'. /// /// If a root item already exists, clear() is called first to clear it /// before replacing it with newitem. /// /// Use this to install a custom item (derived from Fl_Tree_Item) as the root /// of the tree. This allows the derived class to implement custom drawing /// by overriding Fl_Tree_Item::draw_item_content(). /// /// \version 1.3.3 /// void Fl_Tree::root(Fl_Tree_Item *newitem) { if ( _root ) clear(); _root = newitem; } /** Adds a new item, given a menu style \p 'path'. Any parent nodes that don't already exist are created automatically. Adds the item based on the value of sortorder(). If \p 'item' is NULL, a new item is created. To specify items or submenus that contain slashes ('/' or '\') use an escape character to protect them, e.g. \par \code : tree->add("/Holidays/Photos/12\\/25\\/2010"); // Adds item "12/25/2010" tree->add("/Pathnames/c:\\\\Program Files\\\\MyApp"); // Adds item "c:\Program Files\MyApp" : \endcode \param[in] path The path to the item, e.g. "Flintstone/Fred". \param[in] item The new item to be added. If NULL, a new item is created with a name that is the last element in \p 'path'. \returns The new item added, or 0 on error. \version 1.3.3 */ Fl_Tree_Item* Fl_Tree::add(const char *path, Fl_Tree_Item *item) { // Tree has no root? make one if ( ! _root ) { _root = new Fl_Tree_Item(this); _root->parent(0); _root->label("ROOT"); } // Find parent item via path char **arr = parse_path(path); item = _root->add(_prefs, arr, item); free_path(arr); return(item); } /// Add a new child item labeled \p 'name' to the specified \p 'parent_item'. /// /// \param[in] parent_item The parent item the new child item will be added to. /// Must not be NULL. /// \param[in] name The label for the new item /// \returns The new item added. /// \version 1.3.0 release /// Fl_Tree_Item* Fl_Tree::add(Fl_Tree_Item *parent_item, const char *name) { return(parent_item->add(_prefs, name)); } /** Inserts a new item \p 'name' above the specified Fl_Tree_Item \p 'above'. Example: \par \code : tree->add("Aaa/000"); // "000" is index 0 in Aaa's children tree->add("Aaa/111"); // "111" is index 1 in Aaa's children tree->add("Aaa/222"); // "222" is index 2 in Aaa's children .. // How to use insert_above() to insert a new item above Aaa/222 Fl_Tree_Item *item = tree->find_item("Aaa/222"); // get item Aaa/222 if (item) tree->insert_above(item, "New item"); // insert new item above it : \endcode \param[in] above -- the item above which to insert the new item. Must not be NULL. \param[in] name -- the name of the new item \returns The new item added, or 0 if 'above' could not be found. \see insert() */ Fl_Tree_Item* Fl_Tree::insert_above(Fl_Tree_Item *above, const char *name) { return(above->insert_above(_prefs, name)); } /** Insert a new item \p 'name' into \p 'item's children at position \p 'pos'. If \p pos is out of range the new item is - prepended if \p pos \< 0 or - appended if \p pos \> item->children(). Note: \p pos == children() is not considered out of range: the item is appended to the child list. Example: \par \code : tree->add("Aaa/000"); // "000" is index 0 in Aaa's children tree->add("Aaa/111"); // "111" is index 1 in Aaa's children tree->add("Aaa/222"); // "222" is index 2 in Aaa's children : // How to use insert() to insert a new item between Aaa/111 + Aaa/222 Fl_Tree_Item *item = tree->find_item("Aaa"); // get parent item Aaa if (item) tree->insert(item, "New item", 2); // insert as a child of Aaa at index #2 : \endcode \param[in] item The existing item to insert new child into. Must not be NULL. \param[in] name The label for the new item \param[in] pos The position of the new item in the child list \returns The new item added. \see insert_above() */ Fl_Tree_Item* Fl_Tree::insert(Fl_Tree_Item *item, const char *name, int pos) { return(item->insert(_prefs, name, pos)); } /// Remove the specified \p 'item' from the tree. /// \p item may not be NULL. /// If it has children, all those are removed too. /// If item being removed has focus, no item will have focus. /// \returns 0 if done, -1 if 'item' not found. /// int Fl_Tree::remove(Fl_Tree_Item *item) { // Item being removed is focus item? zero focus if ( item == _item_focus ) _item_focus = 0; if ( item == _lastselect ) _lastselect = 0; if ( item == _root ) { clear(); } else { Fl_Tree_Item *parent = item->parent(); // find item's parent if ( ! parent ) return(-1); parent->remove_child(item); // remove child + children } return(0); } /// Clear the entire tree's children, including the root. /// The tree will be left completely empty. /// void Fl_Tree::clear() { if ( ! _root ) return; _root->clear_children(); delete _root; _root = 0; _item_focus = 0; _lastselect = 0; } /// Clear all the children for \p 'item'. /// Item may not be NULL. /// void Fl_Tree::clear_children(Fl_Tree_Item *item) { if ( item->has_children() ) { item->clear_children(); redraw(); // redraw only if there were children to clear } } /** Find the item, given a menu style path, e.g. "/Parent/Child/item". There is both a const and non-const version of this method. Const version allows pure const methods to use this method to do lookups without causing compiler errors. To specify items or submenus that contain slashes ('/' or '\') use an escape character to protect them, e.g. \par \code : tree->add("/Holidays/Photos/12\\/25\\/2010"); // Adds item "12/25/2010" tree->add("/Pathnames/c:\\\\Program Files\\\\MyApp"); // Adds item "c:\Program Files\MyApp" : \endcode \param[in] path -- the tree item's pathname to be found (e.g. "Flintstones/Fred") \returns The item, or NULL if not found. \see item_pathname() */ const Fl_Tree_Item *Fl_Tree::find_item(const char *path) const { if ( ! _root ) return(NULL); char **arr = parse_path(path); const Fl_Tree_Item *item = _root->find_item(arr); free_path(arr); return(item); } /// Non-const version of Fl_Tree::find_item(const char *path) const Fl_Tree_Item *Fl_Tree::find_item(const char *path) { // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. return(const_cast( static_cast(*this).find_item(path))); } // Handle safe 'reverse string concatenation'. // In the following we build the pathname from right-to-left, // since we start at the child and work our way up to the root. // #define SAFE_RCAT(c) { \ slen += 1; if ( slen >= pathnamelen ) { pathname[0] = '\0'; return(-2); } \ *s-- = c; \ } /// Return \p 'pathname' of size \p 'pathnamelen' for the specified \p 'item'. /// /// If \p 'item' is NULL, root() is used.
/// The tree's root will be included in the pathname if showroot() is on.
/// Menu items or submenus that contain slashes ('/' or '\') in their names /// will be escaped with a backslash. This is symmetrical with the add() /// function which uses the same escape pattern to set names. /// /// \param[out] pathname The string to use to return the pathname /// \param[in] pathnamelen The maximum length of the string (including NULL). Must not be zero. /// \param[in] item The item whose pathname is to be returned. /// \returns /// - 0 : OK (\p pathname returns the item's pathname) /// - -1 : item not found (pathname="") /// - -2 : pathname not large enough (pathname="") /// \see find_item() /// int Fl_Tree::item_pathname(char *pathname, int pathnamelen, const Fl_Tree_Item *item) const { pathname[0] = '\0'; item = item ? item : _root; if ( !item ) return(-1); // Build pathname starting at end char *s = (pathname+pathnamelen-1); int slen = 0; // length of string compiled so far (including NULL) SAFE_RCAT('\0'); while ( item ) { if ( item->is_root() && showroot() == 0 ) break; // don't include root in path if showroot() off // Find name of current item const char *name = item->label() ? item->label() : "???"; // name for this item int len = (int) strlen(name); // Add name to end of pathname[] for ( --len; len>=0; len-- ) { SAFE_RCAT(name[len]); // rcat name of item if ( name[len] == '/' || name[len] == '\\' ) { SAFE_RCAT('\\'); // escape front or back slashes within name } } SAFE_RCAT('/'); // rcat leading slash item = item->parent(); // move up tree (NULL==root) } if ( *(++s) == '/' ) { ++s; --slen; } // leave off leading slash from pathname if ( s != pathname ) memmove(pathname, s, slen); // Shift down right-aligned string return(0); } /// Find the item that was last clicked on. /// You should use callback_item() instead, which is fast, /// and is meant to be used within a callback to determine the item clicked. /// /// This method walks the entire tree looking for the first item that is /// under the mouse. (The value of the \p 'yonly' flag affects whether /// both x and y events are checked, or just y) /// /// Use this method /only/ if you've subclassed Fl_Tree, and are receiving /// events before Fl_Tree has been able to process and update callback_item(). /// /// \param[in] yonly -- 0: check both event's X and Y values. /// -- 1: only check event's Y value, don't care about X. /// \returns The item clicked, or NULL if no item was under the current event. /// \version 1.3.0 /// \version 1.3.3 ABI feature: added yonly parameter /// const Fl_Tree_Item* Fl_Tree::find_clicked(int yonly) const { if ( ! _root ) return(NULL); return(_root->find_clicked(_prefs, yonly)); } /// Non-const version of Fl_Tree::find_clicked(int yonly) const. Fl_Tree_Item *Fl_Tree::find_clicked(int yonly) { // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. return(const_cast( static_cast(*this).find_clicked(yonly))); } /// Set the item that was last clicked. /// Should only be used by subclasses needing to change this value. /// Normally Fl_Tree manages this value. /// /// \deprecated in 1.3.3 ABI -- use callback_item() instead. /// void Fl_Tree::item_clicked(Fl_Tree_Item* item) { _callback_item = item; } /// Return the item that was last clicked. /// /// Valid only from within the callback(). /// /// \returns The item clicked, or 0 if none. /// 0 may also be used to indicate several items were clicked/changed. /// \deprecated in 1.3.3 ABI -- use callback_item() instead. /// Fl_Tree_Item* Fl_Tree::item_clicked() { return(_callback_item); } /** Returns next open(), visible item above (\p dir==FL_Up) or below (\p dir==FL_Down) the specified \p 'item', or 0 if no more items. If \p 'item' is 0, returns last() if \p 'dir' is FL_Up, or first() if \p dir is FL_Down. \par \code : // Walk down the tree (forwards) for ( Fl_Tree_Item *i=tree->first_visible_item(); i; i=tree->next_visible_item(i, FL_Down) ) printf("Item: %s\n", i->label()); // Walk up the tree (backwards) for ( Fl_Tree_Item *i=tree->last_visible_item(); i; i=tree->next_visible_item(i, FL_Up) ) printf("Item: %s\n", i->label()); : \endcode \param[in] item The item above/below which we'll find the next visible item \param[in] dir The direction to search. Can be FL_Up or FL_Down. \returns The item found, or 0 if there's no visible items above/below the specified \p item. \version 1.3.3 */ Fl_Tree_Item *Fl_Tree::next_visible_item(Fl_Tree_Item *item, int dir) { return next_item(item, dir, true); } /** Returns the first item in the tree, or 0 if none. Use this to walk the tree in the forward direction, e.g. \par \code : for ( Fl_Tree_Item *item = tree->first(); item; item = tree->next(item) ) printf("Item: %s\n", item->label()); : \endcode \returns First item in tree, or 0 if none (tree empty). \see first(), next(), last(), prev() */ Fl_Tree_Item* Fl_Tree::first() { return(_root); // first item always root } /// Returns the first open(), visible item in the tree, or 0 if none. /// \deprecated in 1.3.3 ABI -- use first_visible_item() instead. /// Fl_Tree_Item* Fl_Tree::first_visible() { return(first_visible_item()); } /// Returns the first open(), visible item in the tree, or 0 if none. /// \returns First visible item in tree, or 0 if none. /// \see first_visible_item(), last_visible_item(), next_visible_item() /// \version 1.3.3 /// Fl_Tree_Item* Fl_Tree::first_visible_item() { Fl_Tree_Item *i = showroot() ? first() : next(first()); while ( i ) { if ( i->visible() ) return(i); i = next(i); } return(0); } /** Return the next item after \p 'item', or 0 if no more items. Use this code to walk the entire tree: \par \code : for ( Fl_Tree_Item *i = tree->first(); i; i = tree->next(i) ) printf("Item: %s\n", i->label()); : \endcode \param[in] item The item to use to find the next item. If NULL, returns 0. \returns Next item in tree, or 0 if at last item. \see first(), next(), last(), prev() */ Fl_Tree_Item *Fl_Tree::next(Fl_Tree_Item *item) { if ( ! item ) return(0); return(item->next()); } /** Return the previous item before \p 'item', or 0 if no more items. This can be used to walk the tree in reverse, e.g. \par \code : for ( Fl_Tree_Item *item = tree->first(); item; item = tree->prev(item) ) printf("Item: %s\n", item->label()); : \endcode \param[in] item The item to use to find the previous item. If NULL, returns 0. \returns Previous item in tree, or 0 if at first item. \see first(), next(), last(), prev() */ Fl_Tree_Item *Fl_Tree::prev(Fl_Tree_Item *item) { if ( ! item ) return(0); return(item->prev()); } /** Returns the last item in the tree. This can be used to walk the tree in reverse, e.g. \par \code for ( Fl_Tree_Item *item = tree->last(); item; item = tree->prev() ) printf("Item: %s\n", item->label()); \endcode \returns Last item in the tree, or 0 if none (tree empty). \see first(), next(), last(), prev() */ Fl_Tree_Item* Fl_Tree::last() { if ( ! _root ) return(0); Fl_Tree_Item *item = _root; while ( item->has_children() ) { item = item->child(item->children()-1); } return(item); } /// Returns the last open(), visible item in the tree. /// \deprecated in 1.3.3 -- use last_visible_item() instead. /// Fl_Tree_Item* Fl_Tree::last_visible() { return(last_visible_item()); } /// Returns the last open(), visible item in the tree. /// \returns Last visible item in the tree, or 0 if none. /// \see first_visible_item(), last_visible_item(), next_visible_item() /// \version 1.3.3 /// Fl_Tree_Item* Fl_Tree::last_visible_item() { Fl_Tree_Item *item = last(); while ( item ) { if ( item->visible_r() ) { if ( item == _root && !showroot() ) { return(0); } else { return(item); } } item = prev(item); } return(item); } /** Returns the first selected item in the tree. Use this to walk the tree from top to bottom looking for all the selected items, e.g. \par \code : // Walk tree forward, from top to bottom for ( Fl_Tree_Item *i=tree->first_selected_item(); i; i=tree->next_selected_item(i) ) printf("Selected item: %s\n", i->label()); : \endcode \returns The first selected item, or 0 if none. \see first_selected_item(), last_selected_item(), next_selected_item() */ Fl_Tree_Item *Fl_Tree::first_selected_item() { return(next_selected_item(0)); } /** Returns the last selected item in the tree. Use this to walk the tree in reverse from bottom to top looking for all the selected items, e.g. \par \code : // Walk tree in reverse, from bottom to top for ( Fl_Tree_Item *i=tree->last_selected_item(); i; i=tree->next_selected_item(i, FL_Up) ) printf("Selected item: %s\n", i->label()); : \endcode \returns The last selected item, or 0 if none. \see first_selected_item(), last_selected_item(), next_selected_item() \version 1.3.3 */ Fl_Tree_Item *Fl_Tree::last_selected_item() { return(next_selected_item(0, FL_Up)); } /** Returns next item after \p 'item' in direction \p 'dir' depending on \p 'visible'. Next item will be above (if dir==FL_Up) or below (if dir==FL_Down). If \p 'visible' is true, only items whose parents are open() will be returned. If \p 'visible' is false, even items whose parents are close()ed will be returned. If \p item is 0, the return value will be the result of this truth table:
                        visible=true           visible=false
                        -------------------    -------------
          dir=FL_Up:    last_visible_item()    last()
        dir=FL_Down:    first_visible_item()   first()
 
Example use: \par \code : // Walk down the tree showing open(), visible items for ( Fl_Tree_Item *i=tree->first_visible_item(); i; i=tree->next_item(i, FL_Down, true) ) printf("Item: %s\n", i->label()); // Walk up the tree showing open(), visible items for ( Fl_Tree_Item *i=tree->last_visible_item(); i; i=tree->next_item(i, FL_Up, true) ) printf("Item: %s\n", i->label()); // Walk down the tree showing all items (open or closed) for ( Fl_Tree_Item *i=tree->first(); i; i=tree->next_item(i, FL_Down, false) ) printf("Item: %s\n", i->label()); // Walk up the tree showing all items (open or closed) for ( Fl_Tree_Item *i=tree->last(); i; i=tree->next_item(i, FL_Up, false) ) printf("Item: %s\n", i->label()); : \endcode \param[in] item The item to use to find the next item. If NULL, returns 0. \param[in] dir Can be FL_Up or FL_Down (default=FL_Down or 'next') \param[in] visible true=return only open(), visible items,
false=return open or closed items (default) \returns Next item in tree in the direction and visibility specified, or 0 if no more items of specified visibility in that direction. \see first(), last(), next(),
first_visible_item(), last_visible_item(), next_visible_item(),
first_selected_item(), last_selected_item(), next_selected_item() \version 1.3.3 */ Fl_Tree_Item *Fl_Tree::next_item(Fl_Tree_Item *item, int dir, bool visible) { if ( ! item ) { // no start item? if ( visible ) { item = ( dir == FL_Up ) ? last_visible_item() : // wrap to bottom first_visible_item(); // wrap to top } else { item = ( dir == FL_Up ) ? last() : // wrap to bottom first(); // wrap to top } if ( ! item ) return(0); if ( item->visible_r() ) return(item); // return first/last visible item } switch (dir) { case FL_Up: if ( visible ) return(item->prev_visible(_prefs)); else return(item->prev()); case FL_Down: if ( visible ) return(item->next_visible(_prefs)); else return(item->next()); } return(0); // unknown dir } /** Returns the next selected item above or below \p 'item', depending on \p 'dir'. If \p 'item' is 0, search starts at either first() or last(), depending on \p 'dir': first() if \p 'dir' is FL_Down (default), last() if \p 'dir' is FL_Up. Use this to walk the tree looking for all the selected items, e.g. \par \code : // Walk down the tree (forwards) for ( Fl_Tree_Item *i=tree->first_selected_item(); i; i=tree->next_selected_item(i, FL_Down) ) printf("Item: %s\n", i->label()); // Walk up the tree (backwards) for ( Fl_Tree_Item *i=tree->last_selected_item(); i; i=tree->next_selected_item(i, FL_Up) ) printf("Item: %s\n", i->label()); : \endcode \param[in] item The item above or below which we'll find the next selected item. If NULL, first() is used if FL_Down, last() if FL_Up. (default=NULL) \param[in] dir The direction to go. FL_Up for moving up the tree, FL_Down for down the tree (default) \returns The next selected item, or 0 if there are no more selected items. \see first_selected_item(), last_selected_item(), next_selected_item() \version 1.3.3 */ Fl_Tree_Item *Fl_Tree::next_selected_item(Fl_Tree_Item *item, int dir) { switch (dir) { case FL_Down: if ( ! item ) { if ( ! (item = first()) ) return(0); if ( item->is_selected() ) return(item); } while ( (item = item->next()) ) if ( item->is_selected() ) return(item); return(0); case FL_Up: if ( ! item ) { if ( ! (item = last()) ) return(0); if ( item->is_selected() ) return(item); } while ( (item = item->prev()) ) if ( item->is_selected() ) return(item); return(0); } return(0); } /** Returns the currently selected items as an array of \p 'ret_items'. Example: \par \code : // Get selected items as an array Fl_Tree_Item_Array items; tree->get_selected_items(items); // Manipulate the returned array for ( int t=0; t /// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] item -- the item to be opened. Must not be NULL. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - callback() is not invoked /// - 1 - callback() is invoked if item changed (default), /// callback_reason() will be FL_TREE_REASON_OPENED /// \returns /// - 1 -- item was opened /// - 0 -- item was already open, no change /// /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() /// int Fl_Tree::open(Fl_Tree_Item *item, int docallback) { if ( item->is_open() ) return(0); item->open(); // handles recalc_tree() redraw(); if ( docallback ) { do_callback_for_item(item, FL_TREE_REASON_OPENED); } return(1); } /// Opens the item specified by \p 'path'. /// /// This causes the item's children (if any) to be shown.
/// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. open("Holidays/12\\/25\\/2010"). /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred") /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - callback() is not invoked /// - 1 - callback() is invoked if item changed (default), /// callback_reason() will be FL_TREE_REASON_OPENED /// \returns /// - 1 -- OK: item opened /// - 0 -- OK: item was already open, no change /// - -1 -- ERROR: item was not found /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() /// int Fl_Tree::open(const char *path, int docallback) { Fl_Tree_Item *item = find_item(path); if ( ! item ) return(-1); return(open(item, docallback)); // handles recalc_tree() } /// Toggle the open state of \p 'item'. /// /// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] item -- the item whose open state is to be toggled. Must not be NULL. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - callback() is not invoked /// - 1 - callback() is invoked (default), callback_reason() will be either /// FL_TREE_REASON_OPENED or FL_TREE_REASON_CLOSED /// /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() /// void Fl_Tree::open_toggle(Fl_Tree_Item *item, int docallback) { if ( item->is_open() ) { close(item, docallback); // handles recalc_tree() } else { open(item, docallback); // handles recalc_tree() } } /// Closes the specified \p 'item'. /// /// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] item -- the item to be closed. Must not be NULL. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - callback() is not invoked /// - 1 - callback() is invoked if item changed (default), /// callback_reason() will be FL_TREE_REASON_CLOSED /// \returns /// - 1 -- item was closed /// - 0 -- item was already closed, no change /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() /// int Fl_Tree::close(Fl_Tree_Item *item, int docallback) { if ( item->is_close() ) return(0); item->close(); // handles recalc_tree() redraw(); if ( docallback ) { do_callback_for_item(item, FL_TREE_REASON_CLOSED); } return(1); } /// Closes the item specified by \p 'path'. /// /// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. close("Holidays/12\\/25\\/2010"). /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred") /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - callback() is not invoked /// - 1 - callback() is invoked if item changed (default), /// callback_reason() will be FL_TREE_REASON_CLOSED /// \returns /// - 1 -- OK: item closed /// - 0 -- OK: item was already closed, no change /// - -1 -- ERROR: item was not found /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() /// int Fl_Tree::close(const char *path, int docallback) { Fl_Tree_Item *item = find_item(path); if ( ! item ) return(-1); return(close(item, docallback)); // handles recalc_tree() } /// See if \p 'item' is open. /// /// Items that are 'open' are themselves not necessarily visible; /// one of the item's parents might be closed. /// /// \param[in] item -- the item to be tested. Must not be NULL. /// \returns /// - 1 : item is open /// - 0 : item is closed /// int Fl_Tree::is_open(Fl_Tree_Item *item) const { return(item->is_open()?1:0); } /// See if item specified by \p 'path' is open. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. is_open("Holidays/12\\/25\\/2010"). /// /// Items that are 'open' are themselves not necessarily visible; /// one of the item's parents might be closed. /// /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred") /// \returns /// - 1 - OK: item is open /// - 0 - OK: item is closed /// - -1 - ERROR: item was not found /// \see Fl_Tree_Item::visible_r() /// int Fl_Tree::is_open(const char *path) const { const Fl_Tree_Item *item = find_item(path); if ( ! item ) return(-1); return(item->is_open()?1:0); } /// See if the specified \p 'item' is closed. /// /// \param[in] item -- the item to be tested. Must not be NULL. /// \returns /// - 1 : item is closed /// - 0 : item is open /// int Fl_Tree::is_close(Fl_Tree_Item *item) const { return(item->is_close()); } /// See if item specified by \p 'path' is closed. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. is_close("Holidays/12\\/25\\/2010"). /// /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred") /// \returns /// - 1 - OK: item is closed /// - 0 - OK: item is open /// - -1 - ERROR: item was not found /// int Fl_Tree::is_close(const char *path) const { const Fl_Tree_Item *item = find_item(path); if ( ! item ) return(-1); return(item->is_close()?1:0); } /// Select the specified \p 'item'. Use 'deselect()' to deselect it. /// /// Invokes the callback depending on the value of optional parameter \p docallback.
/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] item -- the item to be selected. Must not be NULL. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked /// - 1 - the callback() is invoked if item changed state, /// callback_reason() will be FL_TREE_REASON_SELECTED /// \returns /// - 1 - item's state was changed /// - 0 - item was already selected, no change was made /// int Fl_Tree::select(Fl_Tree_Item *item, int docallback) { int alreadySelected = item->is_selected(); if ( !alreadySelected ) { item->select(); set_changed(); if ( docallback ) { do_callback_for_item(item, FL_TREE_REASON_SELECTED); } redraw(); return(1); } // NEW if ( alreadySelected ) { if ( (item_reselect_mode() == FL_TREE_SELECTABLE_ALWAYS) && docallback ) { do_callback_for_item(item, FL_TREE_REASON_RESELECTED); } } return(0); } /// Select the item specified by \p 'path'. /// /// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. select("Holidays/12\\/25\\/2010"). /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred") /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked /// - 1 - the callback() is invoked if item changed state (default), /// callback_reason() will be FL_TREE_REASON_SELECTED /// \returns /// - 1 : OK: item's state was changed /// - 0 : OK: item was already selected, no change was made /// - -1 : ERROR: item was not found /// int Fl_Tree::select(const char *path, int docallback) { Fl_Tree_Item *item = find_item(path); if ( ! item ) return(-1); return(select(item, docallback)); } /// Toggle the select state of the specified \p 'item'. /// /// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] item -- the item to be selected. Must not be NULL. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked /// - 1 - the callback() is invoked (default), callback_reason() will be /// either FL_TREE_REASON_SELECTED or FL_TREE_REASON_DESELECTED /// void Fl_Tree::select_toggle(Fl_Tree_Item *item, int docallback) { item->select_toggle(); set_changed(); if ( docallback ) { do_callback_for_item(item, item->is_selected() ? FL_TREE_REASON_SELECTED : FL_TREE_REASON_DESELECTED); } redraw(); } /// Deselect the specified \p item. /// /// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] item -- the item to be deselected. Must not be NULL. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked /// - 1 - the callback() is invoked if item changed state (default), /// callback_reason() will be FL_TREE_REASON_DESELECTED /// \returns /// - 0 - item was already deselected, no change was made /// - 1 - item's state was changed /// int Fl_Tree::deselect(Fl_Tree_Item *item, int docallback) { if ( item->is_selected() ) { item->deselect(); set_changed(); if ( docallback ) { do_callback_for_item(item, FL_TREE_REASON_DESELECTED); } redraw(); return(1); } return(0); } /// Deselect an item specified by \p 'path'. /// /// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. deselect("Holidays/12\\/25\\/2010"). /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred") /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked /// - 1 - the callback() is invoked if item changed state (default), /// callback_reason() will be FL_TREE_REASON_DESELECTED /// \returns /// - 1 - OK: item's state was changed /// - 0 - OK: item was already deselected, no change was made /// - -1 - ERROR: item was not found /// int Fl_Tree::deselect(const char *path, int docallback) { Fl_Tree_Item *item = find_item(path); if ( ! item ) return(-1); return(deselect(item, docallback)); } /// Deselect \p 'item' and all its children. /// /// If item is NULL, first() is used.
/// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] item The item that will be deselected (along with all its children). /// If NULL, first() is used. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked /// - 1 - the callback() is invoked for each item that changed state (default), /// callback_reason() will be FL_TREE_REASON_DESELECTED /// \returns Count of how many items were actually changed to the deselected state. /// int Fl_Tree::deselect_all(Fl_Tree_Item *item, int docallback) { item = item ? item : first(); // NULL? use first() if ( ! item ) return(0); int count = 0; // Deselect item if ( item->is_selected() ) if ( deselect(item, docallback) ) ++count; // Deselect its children for ( int t=0; tchildren(); t++ ) { count += deselect_all(item->child(t), docallback); // recurse } return(count); } /// Select only the specified item, deselecting all others that might be selected. /// /// If \p 'selitem' is 0, first() is used.
/// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] selitem The item to be selected. If NULL, first() is used. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked /// - 1 - the callback() is invoked for each item that changed state (default), /// callback_reason() will be either FL_TREE_REASON_SELECTED or /// FL_TREE_REASON_DESELECTED /// \returns The number of items whose selection states were changed, if any. /// int Fl_Tree::select_only(Fl_Tree_Item *selitem, int docallback) { selitem = selitem ? selitem : first(); // NULL? use first() if ( ! selitem ) return(0); int changed = 0; // Deselect everything first. // Prevents callbacks from seeing more than one item selected. // for ( Fl_Tree_Item *item = first(); item; item = item->next() ) { if ( item == selitem ) continue; // don't do anything to selitem yet.. if ( item->is_selected() ) { deselect(item, docallback); ++changed; } } // Should we 'reselect' item if already selected? if ( selitem->is_selected() && (item_reselect_mode()==FL_TREE_SELECTABLE_ALWAYS) ) { // Selection unchanged, so no ++changed select(selitem, docallback); // do callback with reason=reselect } else if ( !selitem->is_selected() ) { // Item was not already selected, select and indicate changed select(selitem, docallback); ++changed; } return(changed); } /// Select \p 'item' and all its children. /// /// If item is NULL, first() is used.
/// Invokes the callback depending on the value of optional /// parameter \p 'docallback'.
/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. /// /// \param[in] item The item that will be selected (along with all its children). /// If NULL, first() is used. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked /// - 1 - the callback() is invoked for each item that changed state (default), /// callback_reason() will be FL_TREE_REASON_SELECTED /// \returns Count of how many items were actually changed to the selected state. /// int Fl_Tree::select_all(Fl_Tree_Item *item, int docallback) { item = item ? item : first(); // NULL? use first() if ( ! item ) return(0); int count = 0; // Select item if ( !item->is_selected() ) if ( select(item, docallback) ) ++count; // Select its children for ( int t=0; tchildren(); t++ ) { count += select_all(item->child(t), docallback); // recurse } return(count); } /// Get the item that currently has keyboard focus. Fl_Tree_Item* Fl_Tree::get_item_focus() const { return(_item_focus); } /// Set the item that currently should have keyboard focus. /// /// Handles calling redraw() to update the focus box (if it is visible). /// /// \param[in] item The item that should take focus. If NULL, none will have focus. /// void Fl_Tree::set_item_focus(Fl_Tree_Item *item) { if ( _item_focus != item ) { // changed? _item_focus = item; // update if ( visible_focus() ) redraw(); // redraw to update focus box } } /// See if the specified \p 'item' is selected. /// /// \param[in] item -- the item to be tested. Must not be NULL. /// /// \return /// - 1 : item selected /// - 0 : item deselected /// int Fl_Tree::is_selected(Fl_Tree_Item *item) const { return(item->is_selected()?1:0); } /// See if item specified by \p 'path' is selected. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. is_selected("Holidays/12\\/25\\/2010"). /// /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred") /// \returns /// - 1 : item selected /// - 0 : item deselected /// - -1 : item was not found /// int Fl_Tree::is_selected(const char *path) { Fl_Tree_Item *item = find_item(path); if ( ! item ) return(-1); return(is_selected(item)); } /// Get the default label fontsize used for creating new items. Fl_Fontsize Fl_Tree::item_labelsize() const { return(_prefs.labelsize()); } /// Set the default label font size used for creating new items. /// To change the font size on a per-item basis, use Fl_Tree_Item::labelsize(Fl_Fontsize) /// void Fl_Tree::item_labelsize(Fl_Fontsize val) { _prefs.labelsize(val); } /// Get the default font face used for creating new items. Fl_Font Fl_Tree::item_labelfont() const { return(_prefs.labelfont()); } /// Set the default font face used for creating new items. /// To change the font face on a per-item basis, use Fl_Tree_Item::labelfont(Fl_Font) /// void Fl_Tree::item_labelfont(Fl_Font val) { _prefs.labelfont(val); } /// Get the default label foreground color used for creating new items. Fl_Color Fl_Tree::item_labelfgcolor(void) const { return(_prefs.labelfgcolor()); } /// Set the default label foreground color used for creating new items. /// To change the foreground color on a per-item basis, use Fl_Tree_Item::labelfgcolor(Fl_Color) /// void Fl_Tree::item_labelfgcolor(Fl_Color val) { _prefs.labelfgcolor(val); } /// Get the default label background color used for creating new items. /// If the color is 0xffffffff, it is 'transparent'. Fl_Color Fl_Tree::item_labelbgcolor(void) const { return(_prefs.labelbgcolor()); } /// Set the default label background color used for creating new items. /// A special case is made for color 0xffffffff (default) which is treated as 'transparent'. /// To change the background color on a per-item basis, use Fl_Tree_Item::labelbgcolor(Fl_Color) /// void Fl_Tree::item_labelbgcolor(Fl_Color val) { _prefs.labelbgcolor(val); } /// Get the connector color used for tree connection lines. Fl_Color Fl_Tree::connectorcolor() const { return(_prefs.connectorcolor()); } /// Set the connector color used for tree connection lines. void Fl_Tree::connectorcolor(Fl_Color val) { _prefs.connectorcolor(val); } /// Get the amount of white space (in pixels) that should appear /// between the widget's left border and the tree's contents. /// int Fl_Tree::marginleft() const { return(_prefs.marginleft()); } /// Set the amount of white space (in pixels) that should appear /// between the widget's left border and the left side of the tree's contents. /// void Fl_Tree::marginleft(int val) { _prefs.marginleft(val); redraw(); recalc_tree(); } /// Get the amount of white space (in pixels) that should appear /// between the widget's top border and the top of the tree's contents. /// int Fl_Tree::margintop() const { return(_prefs.margintop()); } /// Sets the amount of white space (in pixels) that should appear /// between the widget's top border and the top of the tree's contents. /// void Fl_Tree::margintop(int val) { _prefs.margintop(val); redraw(); recalc_tree(); } /// Get the amount of white space (in pixels) that should appear /// below the last visible item when the vertical scroller is scrolled to the bottom. /// int Fl_Tree::marginbottom() const { return(_prefs.marginbottom()); } /// Sets the amount of white space (in pixels) that should appear /// below the last visible item when the vertical scroller is scrolled to the bottom. /// void Fl_Tree::marginbottom(int val) { _prefs.marginbottom(val); redraw(); recalc_tree(); } /// Get the amount of white space (in pixels) that should appear /// between items in the tree. /// int Fl_Tree::linespacing() const { return(_prefs.linespacing()); } /// Sets the amount of white space (in pixels) that should appear /// between items in the tree. /// void Fl_Tree::linespacing(int val) { _prefs.linespacing(val); redraw(); recalc_tree(); } /// Get the amount of white space (in pixels) that should appear /// below an open child tree's contents. /// int Fl_Tree::openchild_marginbottom() const { return(_prefs.openchild_marginbottom()); } /// Set the amount of white space (in pixels) that should appear /// below an open child tree's contents. /// void Fl_Tree::openchild_marginbottom(int val) { _prefs.openchild_marginbottom(val); redraw(); recalc_tree(); } /// Get the amount of white space (in pixels) that should appear /// to the left of the usericon. int Fl_Tree::usericonmarginleft() const { return(_prefs.usericonmarginleft()); } /// Set the amount of white space (in pixels) that should appear /// to the left of the usericon. void Fl_Tree::usericonmarginleft(int val) { _prefs.usericonmarginleft(val); redraw(); recalc_tree(); } /// Get the amount of white space (in pixels) that should appear /// to the left of the label text. int Fl_Tree::labelmarginleft() const { return(_prefs.labelmarginleft()); } /// Set the amount of white space (in pixels) that should appear /// to the left of the label text. void Fl_Tree::labelmarginleft(int val) { _prefs.labelmarginleft(val); redraw(); recalc_tree(); } /// Get the amount of white space (in pixels) that should appear /// to the left of the child fltk widget (if any). int Fl_Tree::widgetmarginleft() const { return(_prefs.widgetmarginleft()); } /// Set the amount of white space (in pixels) that should appear /// to the left of the child fltk widget (if any). void Fl_Tree::widgetmarginleft(int val) { _prefs.widgetmarginleft(val); redraw(); recalc_tree(); } /// Gets the width of the horizontal connection lines (in pixels) /// that appear to the left of each tree item's label. /// int Fl_Tree::connectorwidth() const { return(_prefs.connectorwidth()); } /// Sets the width of the horizontal connection lines (in pixels) /// that appear to the left of each tree item's label. /// void Fl_Tree::connectorwidth(int val) { _prefs.connectorwidth(val); redraw(); recalc_tree(); } /// Returns the Fl_Image being used as the default user icon for all /// newly created items. /// Returns zero if no icon has been set, which is the default. /// Fl_Image* Fl_Tree::usericon() const { return(_prefs.usericon()); } /// Sets the Fl_Image to be used as the default user icon for all /// newly created items. /// /// If you want to specify user icons on a per-item basis, /// use Fl_Tree_Item::usericon() instead. /// /// \param[in] val -- The new image to be used, or /// zero to disable user icons. /// void Fl_Tree::usericon(Fl_Image *val) { _prefs.usericon(val); redraw(); recalc_tree(); } /// Returns the icon to be used as the 'open' icon. /// If none was set, the internal default is returned, /// a simple '[+]' icon. /// Fl_Image* Fl_Tree::openicon() const { return(_prefs.openicon()); } /// Sets the icon to be used as the 'open' icon. /// This overrides the built in default '[+]' icon. /// /// \param[in] val -- The new image, or zero to use the default [+] icon. /// void Fl_Tree::openicon(Fl_Image *val) { _prefs.openicon(val); redraw(); recalc_tree(); } /// Returns the icon to be used as the 'close' icon. /// If none was set, the internal default is returned, /// a simple '[-]' icon. /// Fl_Image* Fl_Tree::closeicon() const { return(_prefs.closeicon()); } /// Sets the icon to be used as the 'close' icon. /// This overrides the built in default '[-]' icon. /// /// \param[in] val -- The new image, or zero to use the default [-] icon. /// void Fl_Tree::closeicon(Fl_Image *val) { _prefs.closeicon(val); redraw(); recalc_tree(); } /// Returns 1 if the collapse icon is enabled, 0 if not. /// \see showcollapse(int) int Fl_Tree::showcollapse() const { return(_prefs.showcollapse()); } /// Set if we should show the collapse icon or not. /// If collapse icons are disabled, the user will not be able /// to interactively collapse items in the tree, unless the application /// provides some other means via open() and close(). /// /// \param[in] val 1: shows collapse icons (default),\n /// 0: hides collapse icons. /// void Fl_Tree::showcollapse(int val) { _prefs.showcollapse(val); redraw(); recalc_tree(); } /// Returns 1 if the root item is to be shown, or 0 if not. int Fl_Tree::showroot() const { return(_prefs.showroot()); } /// Set if the root item should be shown or not. /// \param[in] val 1 -- show the root item (default)\n /// 0 -- hide the root item. /// void Fl_Tree::showroot(int val) { _prefs.showroot(val); redraw(); recalc_tree(); } /// Returns the line drawing style for inter-connecting items. Fl_Tree_Connector Fl_Tree::connectorstyle() const { return(_prefs.connectorstyle()); } /// Sets the line drawing style for inter-connecting items. /// See ::Fl_Tree_Connector for possible values. /// void Fl_Tree::connectorstyle(Fl_Tree_Connector val) { _prefs.connectorstyle(val); redraw(); } /// Set the default sort order used when items are added to the tree. /// See ::Fl_Tree_Sort for possible values. /// Fl_Tree_Sort Fl_Tree::sortorder() const { return(_prefs.sortorder()); } /// Gets the sort order used to add items to the tree. void Fl_Tree::sortorder(Fl_Tree_Sort val) { _prefs.sortorder(val); // no redraw().. only affects new add()itions } /// Sets the style of box used to draw selected items. /// This is an fltk ::Fl_Boxtype. /// The default is influenced by FLTK's current Fl::scheme() /// Fl_Boxtype Fl_Tree::selectbox() const { return(_prefs.selectbox()); } /// Gets the style of box used to draw selected items. /// This is an fltk ::Fl_Boxtype. /// The default is influenced by FLTK's current Fl::scheme() /// void Fl_Tree::selectbox(Fl_Boxtype val) { _prefs.selectbox(val); redraw(); } /// Gets the tree's current selection mode. /// See ::Fl_Tree_Select for possible values. /// Fl_Tree_Select Fl_Tree::selectmode() const { return(_prefs.selectmode()); } /// Sets the tree's selection mode. /// See ::Fl_Tree_Select for possible values. /// void Fl_Tree::selectmode(Fl_Tree_Select val) { _prefs.selectmode(val); } /// Returns the current item re/selection mode. /// \version 1.3.1 ABI feature /// Fl_Tree_Item_Reselect_Mode Fl_Tree::item_reselect_mode() const { return(_prefs.item_reselect_mode()); } /// Sets the item re/selection mode. /// See ::Fl_Tree_Item_Reselect_Mode for possible values. /// \version 1.3.1 ABI feature /// void Fl_Tree::item_reselect_mode(Fl_Tree_Item_Reselect_Mode mode) { _prefs.item_reselect_mode(mode); } /// Get the 'item draw mode' used for the tree. /// \version 1.3.1 ABI feature /// Fl_Tree_Item_Draw_Mode Fl_Tree::item_draw_mode() const { return(_prefs.item_draw_mode()); } /// Set the 'item draw mode' used for the tree to \p 'mode'. /// /// This affects how items in the tree are drawn, /// such as when a widget() is defined. /// See ::Fl_Tree_Item_Draw_Mode for possible values. /// \version 1.3.1 ABI feature /// void Fl_Tree::item_draw_mode(Fl_Tree_Item_Draw_Mode mode) { _prefs.item_draw_mode(mode); } /// Set the 'item draw mode' used for the tree to integer \p 'mode'. /// /// This affects how items in the tree are drawn, /// such as when a widget() is defined. /// See ::Fl_Tree_Item_Draw_Mode for possible values. /// \version 1.3.1 ABI feature /// void Fl_Tree::item_draw_mode(int mode) { _prefs.item_draw_mode(Fl_Tree_Item_Draw_Mode(mode)); } /// See if \p 'item' is currently displayed on-screen (visible within the widget). /// /// This can be used to detect if the item is scrolled off-screen. /// Checks to see if the item's vertical position is within the top and bottom /// edges of the display window. This does NOT take into account the hide() / show() /// or open() / close() status of the item. /// /// \param[in] item The item to be checked. If NULL, first() is used. /// \returns 1 if displayed, 0 if scrolled off screen or no items are in tree. /// int Fl_Tree::displayed(Fl_Tree_Item *item) { item = item ? item : first(); if (!item) return(0); return( (item->y() >= y()) && (item->y() <= (y()+h()-item->h())) ? 1 : 0); } /// Adjust the vertical scrollbar so that \p 'item' is visible /// \p 'yoff' pixels from the top of the Fl_Tree widget's display. /// /// For instance, yoff=0 will position the item at the top. /// /// If yoff is larger than the vertical scrollbar's limit, /// the value will be clipped. So if yoff=100, but scrollbar's max /// is 50, then 50 will be used. /// /// \param[in] item The item to be shown. If NULL, first() is used. /// \param[in] yoff The pixel offset from the top for the displayed position. /// /// \see show_item_top(), show_item_middle(), show_item_bottom() /// void Fl_Tree::show_item(Fl_Tree_Item *item, int yoff) { item = item ? item : first(); if (!item) return; int newval = item->y() - y() - yoff + (int)_vscroll->value(); if ( newval < _vscroll->minimum() ) newval = (int)_vscroll->minimum(); if ( newval > _vscroll->maximum() ) newval = (int)_vscroll->maximum(); _vscroll->value(newval); redraw(); } /// Adjust the vertical scrollbar to show \p 'item' at the top /// of the display IF it is currently off-screen (for instance show_item_top()). /// If it is already on-screen, no change is made. /// /// \param[in] item The item to be shown. If NULL, first() is used. /// /// \see show_item_top(), show_item_middle(), show_item_bottom() /// void Fl_Tree::show_item(Fl_Tree_Item *item) { item = item ? item : first(); if (!item) return; if ( displayed(item) ) return; show_item_top(item); } /// Adjust the vertical scrollbar so that \p 'item' is at the top of the display. /// /// \param[in] item The item to be shown. If NULL, first() is used. /// void Fl_Tree::show_item_top(Fl_Tree_Item *item) { item = item ? item : first(); if (item) show_item(item, 0); } /// Adjust the vertical scrollbar so that \p 'item' is in the middle of the display. /// /// \param[in] item The item to be shown. If NULL, first() is used. /// void Fl_Tree::show_item_middle(Fl_Tree_Item *item) { item = item ? item : first(); if (item) show_item(item, (_tih/2)-(item->h()/2)); } /// Adjust the vertical scrollbar so that \p 'item' is at the bottom of the display. /// /// \param[in] item The item to be shown. If NULL, first() is used. /// void Fl_Tree::show_item_bottom(Fl_Tree_Item *item) { item = item ? item : first(); if (item) show_item(item, _tih-item->h()); } /// Displays \p 'item', scrolling the tree as necessary. /// \param[in] item The item to be displayed. If NULL, first() is used. /// void Fl_Tree::display(Fl_Tree_Item *item) { item = item ? item : first(); if (item) show_item_middle(item); } /// Returns the vertical scroll position as a pixel offset. /// The position returned is how many pixels of the tree are scrolled off the top edge /// of the screen. /// \see vposition(int), hposition(), hposition(int) /// int Fl_Tree::vposition() const { return((int)_vscroll->value()); } /// Sets the vertical scroll offset to position \p 'pos'. /// The position is how many pixels of the tree are scrolled off the top edge /// of the screen. /// \param[in] pos The vertical position (in pixels) to scroll the tree to. /// \see vposition(), hposition(), hposition(int) /// void Fl_Tree::vposition(int pos) { if (pos < 0) pos = 0; if (pos > _vscroll->maximum()) pos = (int)_vscroll->maximum(); if (pos == _vscroll->value()) return; _vscroll->value(pos); redraw(); } /// Returns the horizontal scroll position as a pixel offset. /// The position returned is how many pixels of the tree are scrolled off the left edge /// of the screen. /// \see hposition(int), vposition(), vposition(int) /// \note Must be using FLTK ABI 1.3.3 or higher for this to be effective. /// int Fl_Tree::hposition() const { return((int)_hscroll->value()); } /// Sets the horizontal scroll offset to position \p 'pos'. /// The position is how many pixels of the tree are scrolled off the left edge /// of the screen. /// \param[in] pos The vertical position (in pixels) to scroll the tree to. /// \see hposition(), vposition(), vposition(int) /// \note Must be using FLTK ABI 1.3.3 or higher for this to be effective. /// void Fl_Tree::hposition(int pos) { if (pos < 0) pos = 0; if (pos > _hscroll->maximum()) pos = (int)_hscroll->maximum(); if (pos == _hscroll->value()) return; _hscroll->value(pos); redraw(); } /** See if widget \p 'w' is one of the Fl_Tree widget's scrollbars. Use this to skip over the scrollbars when walking the child() array. Example: \par \code : for ( int i=0; ichildren(); i++ ) { // walk children Fl_Widget *w = tree->child(i); if ( tree->is_scrollbar(w) ) continue; // skip scrollbars ..do work here.. } : \endcode \param[in] w Widget to test \returns 1 if \p w is a scrollbar, 0 if not. \todo should be const */ int Fl_Tree::is_scrollbar(Fl_Widget *w) { return( (w==_vscroll || w==_hscroll) ? 1 : 0 ); } /// Gets the default size of scrollbars' troughs for this widget /// in pixels. /// /// If this value is zero (default), this widget will use the global /// Fl::scrollbar_size() value as the scrollbar's width. /// /// \returns Scrollbar size in pixels, or 0 if the global Fl::scrollbar_size() is being used. /// \see Fl::scrollbar_size(int) /// int Fl_Tree::scrollbar_size() const { return(_scrollbar_size); } /// Sets the pixel size of the scrollbars' troughs to \p 'size' /// for this widget, in pixels. /// /// Normally you should not need this method, and should use the global /// Fl::scrollbar_size(int) instead to manage the size of ALL /// your widgets' scrollbars. This ensures your application /// has a consistent UI, and is the default behavior. Normally /// this is what you want. /// /// Only use this method if you really need to override just THIS /// instance of the widget's scrollbar size. (This need should be rare.) /// /// Setting \p size to the special value of 0 causes the widget to /// track the global Fl::scrollbar_size(), which is the default. /// /// \param[in] size Sets the scrollbar size in pixels.\n /// If 0 (default), scrollbar size tracks the global Fl::scrollbar_size() /// \see Fl::scrollbar_size() /// void Fl_Tree::scrollbar_size(int size) { _scrollbar_size = size; int scrollsize = _scrollbar_size ? _scrollbar_size : Fl::scrollbar_size(); if ( _vscroll->w() != scrollsize ) { _vscroll->resize(x()+w()-scrollsize, h(), scrollsize, _vscroll->h()); } if ( _hscroll->h() != scrollsize ) { _hscroll->resize(x(), y()+h()-scrollsize, _hscroll->w(), scrollsize); } // Changing scrollbar size affects _tiw/_tih + may affect scrollbar visibility calc_dimensions(); } /// See if the vertical scrollbar is currently visible. /// \returns 1 if scrollbar visible, 0 if not. /// int Fl_Tree::is_vscroll_visible() const { return(_vscroll->visible() ? 1 : 0); } /// See if the horizontal scrollbar is currently visible. /// \returns 1 if scrollbar visible, 0 if not. /// \note Must be using FLTK ABI 1.3.3 or higher for this to be effective. /// int Fl_Tree::is_hscroll_visible() const { return(_hscroll->visible() ? 1 : 0); } /// Do the callback for the specified \p 'item' using \p 'reason', /// setting the callback_item() and callback_reason(). /// void Fl_Tree::do_callback_for_item(Fl_Tree_Item* item, Fl_Tree_Reason reason) { callback_reason(reason); callback_item(item); do_callback((Fl_Widget*)this, user_data(), (Fl_Callback_Reason)reason); } /// Sets the item that was changed for this callback. /// Used internally to pass the item that invoked the callback. /// void Fl_Tree::callback_item(Fl_Tree_Item* item) { _callback_item = item; } /// Gets the item that caused the callback. /// The callback() can use this value to see which item changed. /// Fl_Tree_Item* Fl_Tree::callback_item() { return(_callback_item); } /// Sets the reason for this callback. /// Used internally to pass the reason the callback was invoked. /// void Fl_Tree::callback_reason(Fl_Tree_Reason reason) { _callback_reason = reason; } /** Gets the reason for this callback. The callback() can use this value to see why it was called. Example: \par \code : void MyTreeCallback(Fl_Widget *w, void *userdata) { Fl_Tree *tree = (Fl_Tree*)w; Fl_Tree_Item *item = tree->callback_item(); // the item changed (can be NULL if more than one item was changed!) switch ( tree->callback_reason() ) { // reason callback was invoked case FL_TREE_REASON_OPENED: ..item was opened.. case FL_TREE_REASON_CLOSED: ..item was closed.. case FL_TREE_REASON_SELECTED: ..item was selected.. case FL_TREE_REASON_RESELECTED: ..item was reselected (double-clicked, etc).. case FL_TREE_REASON_DESELECTED: ..item was deselected.. } } : \endcode \see item_reselect_mode() -- enables FL_TREE_REASON_RESELECTED events */ Fl_Tree_Reason Fl_Tree::callback_reason() const { return(_callback_reason); } /** Read a preferences database into the tree widget. A preferences database is a hierarchical collection of data which can be directly loaded into the tree view for inspection. \param[in] prefs the Fl_Preferences database */ void Fl_Tree::load(Fl_Preferences &prefs) { int i, j, n, pn = (int) strlen(prefs.path()); char *p; const char *path = prefs.path(); if (strcmp(path, ".")==0) path += 1; // root path is empty else path += 2; // child path starts with "./" n = prefs.groups(); for (i=0; i #include #include #include class Fl_X; class Fl_Image; class Fl_RGB_Image; class Fl_Image_Surface; /** \brief A base class for platform specific window handling code. This class is only for internal use by the FLTK library. When porting FLTK to a new platform, many methods in this class provide a minimal default implementation. Some methods must be overridden to make sure that the Graphics Driver will draw into the bitmap associated with this window. */ class Fl_Window_Driver { friend class Fl_Window; private: static bool is_a_rescale_; // true when a top-level window is being rescaled protected: Fl_Window *pWindow; int screen_num_; // number of screen where window is mapped public: Fl_Window_Driver(Fl_Window *); virtual ~Fl_Window_Driver(); static Fl_Window_Driver *newWindowDriver(Fl_Window *); static fl_uintptr_t xid(const Fl_Window *win); static Fl_Window *find(fl_uintptr_t xid); int wait_for_expose_value; Fl_Image_Surface *other_xid; // offscreen bitmap (overlay and double-buffered windows) int screen_num(); void screen_num(int n) { screen_num_ = n; } // --- frequently used accessors to public window data /** returns the x coordinate of the window. */ int x() const { return pWindow->x(); } /** returns the y coordinate of the window. */ int y() const { return pWindow->y(); } /** returns the width of the window. */ int w() const { return pWindow->w(); } /** returns the height of the window. */ int h() const { return pWindow->h(); } /** returns whether the window has a border. */ int border() const { return pWindow->border(); } /** returns whether the window itself is visible(). */ int visible() const { return pWindow->visible(); } /** returns whether the window and all its parents are visible(). */ int visible_r() const { return pWindow->visible_r(); } /** returns whether the window is shown(). */ int shown() const { return pWindow->shown(); } /** returns the parent of the window. */ Fl_Group *parent() const { return pWindow->parent(); } // --- accessors to private window data int is_resizable() { return pWindow->is_resizable(); } void is_a_rescale(bool b) { is_a_rescale_ = b;} int fullscreen_screen_top(); int fullscreen_screen_bottom(); int fullscreen_screen_left(); int fullscreen_screen_right(); int* no_fullscreen_x() { return &pWindow->no_fullscreen_x; } int* no_fullscreen_y() { return &pWindow->no_fullscreen_y; } int* no_fullscreen_w() { return &pWindow->no_fullscreen_w; } int* no_fullscreen_h() { return &pWindow->no_fullscreen_h; } int force_position(); void force_position(int c); void x(int X); void y(int Y); void current(Fl_Window *c); char show_iconic() { return Fl_Window::show_next_window_iconic(); } void show_iconic(char c) { Fl_Window::show_next_window_iconic(c); } void flx(Fl_X *x) { pWindow->flx_ = x; } Fl_Cursor cursor_default() { return pWindow->cursor_default; } void destroy_double_buffer(); /** for an Fl_Overlay_Window, returns the value of its overlay_ member variable */ Fl_Window *overlay() { return pWindow->as_overlay_window() ? pWindow->as_overlay_window()->overlay_ : NULL; } /** for an Fl_Overlay_Window, sets the value of its overlay_ member variable */ void overlay(Fl_Window *o) { if (pWindow->as_overlay_window()) pWindow->as_overlay_window()->overlay_ = o; } void resize_after_scale_change(int ns, float old_f, float new_f); void set_popup_window() { pWindow->set_flag(Fl_Window::POPUP); } bool popup_window() const {return pWindow->flags() & Fl_Window::POPUP;} // --- window data virtual int decorated_w() { return w(); } // default, should be overidden by driver virtual int decorated_h() { return h(); } virtual const Fl_Image* shape() { return NULL; } // --- window management virtual void take_focus(); virtual void flush(); // the default implementation may be enough virtual void flush_double(); virtual void flush_overlay(); /** Usable for platform-specific code executed before the platform-independent part of Fl_Window::draw() */ virtual void draw_begin(); /** Usable for platform-specific code executed after the platform-independent part of Fl_Window::draw() */ virtual void draw_end(); void draw(); virtual void make_current(); virtual void label(const char *name, const char *mininame); virtual void makeWindow() {} virtual void wait_for_expose(); virtual void show(); virtual void resize(int /*X*/, int /*Y*/, int /*W*/, int /*H*/) {} virtual void hide() {} int hide_common(); virtual void map() {} virtual void unmap() {} virtual void fullscreen_on() {} virtual void fullscreen_off(int /*X*/, int /*Y*/, int /*W*/, int /*H*/) {} virtual void fullscreen_screens(bool /*on_off*/) {} virtual void maximize(); virtual void un_maximize(); virtual bool maximize_needs_hide() { return false; } void is_maximized(bool b) { pWindow->is_maximized_(b); } virtual void use_border(); virtual void size_range(); virtual void iconize() {} virtual void decoration_sizes(int *top, int *left, int *right, int *bottom) { *top = *left = *right = *bottom = 0; } virtual void show_with_args_begin() {} virtual void show_with_args_end(int /*argc*/, char ** /*argv*/) {} virtual int can_do_overlay(); virtual void redraw_overlay(); // --- window cursor stuff virtual int set_cursor(Fl_Cursor); virtual int set_cursor(const Fl_RGB_Image*, int, int); // --- window shape stuff void shape_pixmap_(Fl_Image* pixmap); // platform-independent, support function virtual void shape(const Fl_Image*) {} virtual void shape_alpha_(Fl_Image*, int /*offset*/) {} // --- window icon stuff virtual void icons(const Fl_RGB_Image* /*icons*/[], int /*count*/) {} virtual const void *icon() const {return NULL;} virtual void icon(const void *) {} virtual void free_icons() {} // --- window printing/drawing helper virtual void capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right); virtual int scroll(int /*src_x*/, int /*src_y*/, int /*src_w*/, int /*src_h*/, int /*dest_x*/, int /*dest_y*/, void (*)(void*, int,int,int,int), void*) { return 0; } static inline Fl_Window_Driver* driver(const Fl_Window *win) {return win->pWindowDriver;} // --- support for menu windows // The default implementation of next 2 virtual members is enough if the // position of a window in a screen is known. Next static members may be useful // when that's not the case, as with Wayland. virtual void reposition_menu_window(int x, int y); virtual void menu_window_area(int &X, int &Y, int &W, int &H, int nscreen = -1); static Fl_Window *menu_parent(int *display_height = NULL); static Fl_Window *menu_leftorigin(Fl_Window*); static Fl_Window *menu_title(Fl_Window*); static int menu_itemheight(Fl_Window*); static int menu_bartitle(Fl_Window*); static int menu_selected(Fl_Window*); static int *menu_offset_y(Fl_Window*); static bool is_floating_title(Fl_Window *); static void scroll_to_selected_item(Fl_Window *); virtual fl_uintptr_t os_id() { return 0; } virtual void allow_expand_outside_parent() {} }; #endif // FL_WINDOW_DRIVER_H /** \} \endcond */ fltk-1.4.3/src/Fl_File_Browser.cxx0000644000175000017500000003421515004135251017130 0ustar albrechtalbrecht// // Fl_File_Browser routines. // // Copyright 1999-2010 by Michael Sweet. // Copyright 2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // Fl_File_Browser::full_height() - Return the height of the list. // Fl_File_Browser::item_height() - Return the height of a list item. // Fl_File_Browser::item_width() - Return the width of a list item. // Fl_File_Browser::item_draw() - Draw a list item. // Fl_File_Browser::Fl_File_Browser() - Create a Fl_File_Browser widget. // Fl_File_Browser::load() - Load a directory into the browser. // Fl_File_Browser::filter() - Set the filename filter. // // // Include necessary header files... // #include #include #include "Fl_System_Driver.H" #include #include #include #include // icon #include #include #include "flstring.h" // // FL_BLINE definition from "Fl_Browser.cxx"... // #define SELECTED 1 #define NOTDISPLAYED 2 // TODO -- Warning: The definition of FL_BLINE here is a hack. // Fl_File_Browser should not do this. PLEASE FIX. // FL_BLINE should be private to Fl_Browser, and not re-defined here. // For now, make sure this struct is precisely consistent with Fl_Browser.cxx. // struct FL_BLINE // data is in a linked list of these { FL_BLINE *prev; // Previous item in list FL_BLINE *next; // Next item in list void *data; // Pointer to data (function) Fl_Image *icon; // Pointer to optional icon short length; // sizeof(txt)-1, may be longer than string char flags; // selected, displayed char txt[1]; // start of allocated array }; // // 'Fl_File_Browser::full_height()' - Return the height of the list. // int // O - Height in pixels Fl_File_Browser::full_height() const { int i, // Looping var th; // Total height of list. for (i = 0, th = 0; i < size(); i ++) th += item_height(find_line(i)) + linespacing(); return (th); } // // 'Fl_File_Browser::item_height()' - Return the height of a list item. // int // O - Height in pixels Fl_File_Browser::item_height(void *p) const // I - List item data { FL_BLINE *line; // Pointer to line char *t; // Pointer into text int height; // Width of line int textheight; // Height of text // Figure out the standard text height... fl_font(textfont(), textsize()); textheight = fl_height(); // We always have at least 1 line... height = textheight; // Scan for newlines... line = (FL_BLINE *)p; if (line != NULL) for (t = line->txt; *t != '\0'; t ++) if (*t == '\n') height += textheight; // If we have enabled icons then add space for them... if (Fl_File_Icon::first() != NULL && height < iconsize_) height = iconsize_; // Add space for the selection border.. height += 2; // Return the height return (height); } // // 'Fl_File_Browser::item_width()' - Return the width of a list item. // int // O - Width in pixels Fl_File_Browser::item_width(void *p) const // I - List item data { int i; // Looping var FL_BLINE *line; // Pointer to line char *t, // Pointer into text *ptr, // Pointer into fragment fragment[10240]; // Fragment of text int width, // Width of line tempwidth; // Width of fragment int column; // Current column const int *columns; // Columns // Scan for newlines... line = (FL_BLINE *)p; columns = column_widths(); // Set the font and size... if (line->txt[strlen(line->txt) - 1] == '/') fl_font(textfont() | FL_BOLD, textsize()); else fl_font(textfont(), textsize()); if (strchr(line->txt, '\n') == NULL && strchr(line->txt, column_char()) == NULL) { // Do a fast width calculation... width = (int)fl_width(line->txt); } else { // More than 1 line or have columns; find the maximum width... width = 0; tempwidth = 0; column = 0; for (t = line->txt, ptr = fragment; *t != '\0'; t ++) if (*t == '\n') { // Newline - nul terminate this fragment and get the width... *ptr = '\0'; tempwidth += (int)fl_width(fragment); // Update the max width as needed... if (tempwidth > width) width = tempwidth; // Point back to the start of the fragment... ptr = fragment; tempwidth = 0; column = 0; } else if (*t == column_char()) { // Advance to the next column... column ++; if (columns) { for (i = 0, tempwidth = 0; i < column && columns[i]; i ++) tempwidth += columns[i]; } else tempwidth = column * (int)(fl_height() * 0.6 * 8.0); if (tempwidth > width) width = tempwidth; ptr = fragment; } else *ptr++ = *t; if (ptr > fragment) { // Nul terminate this fragment and get the width... *ptr = '\0'; tempwidth += (int)fl_width(fragment); // Update the max width as needed... if (tempwidth > width) width = tempwidth; } } // If we have enabled icons then add space for them... if (Fl_File_Icon::first() != NULL) width += iconsize_ + 8; // Add space for the selection border.. width += 2; // Return the width return (width); } // // 'Fl_File_Browser::item_draw()' - Draw a list item. // void Fl_File_Browser::item_draw(void *p, // I - List item data int X, // I - Upper-lefthand X coordinate int Y, // I - Upper-lefthand Y coordinate int W, // I - Width of item int H) const// I - Height of item { int i; // Looping var FL_BLINE *line; // Pointer to line Fl_Color c; // Text color char *t, // Pointer into text *ptr, // Pointer into fragment fragment[10240]; // Fragment of text int width, // Width of line height; // Height of line int column; // Current column const int *columns; // Columns // Draw the list item text... line = (FL_BLINE *)p; if (line->txt[strlen(line->txt) - 1] == '/') fl_font(textfont() | FL_BOLD, textsize()); else fl_font(textfont(), textsize()); if (line->flags & SELECTED) c = fl_contrast(textcolor(), selection_color()); else c = textcolor(); if (Fl_File_Icon::first() == NULL) { // No icons, just draw the text... X ++; W -= 2; } else { // Draw the icon if it is set... if (line->data) ((Fl_File_Icon *)line->data)->draw(X, Y + (H - iconsize_) / 2, iconsize_, iconsize_, (line->flags & SELECTED) ? FL_YELLOW : FL_LIGHT2, active_r()); // Draw the text offset to the right... X += iconsize_ + 9; W -= iconsize_ - 10; } // Center the text vertically... height = fl_height(); for (t = line->txt; *t != '\0'; t ++) if (*t == '\n') height += fl_height(); Y += (H - height) / 2; // Draw the text... line = (FL_BLINE *)p; columns = column_widths(); width = 0; column = 0; if (active_r()) fl_color(c); else fl_color(fl_inactive(c)); for (t = line->txt, ptr = fragment; *t != '\0'; t ++) { if (*t == '\n') { // Newline - nul terminate this fragment and draw it... *ptr = '\0'; fl_draw(fragment, X + width, Y, W - width, fl_height(), (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP), 0, 0); // Point back to the start of the fragment... ptr = fragment; width = 0; Y += fl_height(); column = 0; } else if (*t == column_char()) { // Tab - nul terminate this fragment and draw it... *ptr = '\0'; int cW = W - width; // Clip width... if (columns) { // Try clipping inside this column... for (i = 0; i < column && columns[i]; i ++) { ; } if (columns[i]) cW = columns[i]; } fl_draw(fragment, X + width, Y, cW, fl_height(), (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP), 0, 0); // Advance to the next column... column ++; if (columns) { for (i = 0, width = 0; i < column && columns[i]; i ++) width += columns[i]; } else width = column * (int)(fl_height() * 0.6 * 8.0); ptr = fragment; } else *ptr++ = *t; } if (ptr > fragment) { // Nul terminate this fragment and draw it... *ptr = '\0'; fl_draw(fragment, X + width, Y, W - width, fl_height(), (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_CLIP), 0, 0); } } /** The constructor creates the Fl_File_Browser widget at the specified position and size. The destructor destroys the widget and frees all memory that has been allocated. */ Fl_File_Browser::Fl_File_Browser(int X, // I - Upper-lefthand X coordinate int Y, // I - Upper-lefthand Y coordinate int W, // I - Width in pixels int H, // I - Height in pixels const char *l) // I - Label text : Fl_Browser(X, Y, W, H, l) { // Initialize the filter pattern, current directory, and icon size... pattern_ = "*"; directory_ = ""; iconsize_ = (uchar)(3 * textsize() / 2); filetype_ = FILES; errmsg_ = NULL; } // DTOR Fl_File_Browser::~Fl_File_Browser() { errmsg(NULL); // free()s prev errmsg, if any } /** Sets OS error message to a string, which can be NULL. Frees previous if any. void errmsg(const char *emsg); */ void Fl_File_Browser::errmsg(const char* emsg) { if ( errmsg_ ) { free((void*)errmsg_); errmsg_ = NULL; } errmsg_ = emsg ? fl_strdup(emsg) : NULL; } /** Loads the specified directory into the browser. If icons have been loaded then the correct icon is associated with each file in the list. If directory is "", all mount points (unix) or drive letters (Windows) are listed. The sort argument specifies a sort function to be used with fl_filename_list(). Return value is the number of filename entries, or 0 if none. On error, 0 is returned, and errmsg() has OS error string if non-NULL. */ int // O - Number of files loaded Fl_File_Browser::load(const char *directory,// I - Directory to load Fl_File_Sort_F *sort) // I - Sort function to use { int i; // Looping var int num_files; // Number of files in directory int num_dirs; // Number of directories in list char filename[4096]; // Current file Fl_File_Icon *icon; // Icon to use errmsg(NULL); // clear errors first // printf("Fl_File_Browser::load(\"%s\")\n", directory); clear(); directory_ = directory; if (!directory) { errmsg("NULL directory specified"); return 0; } if (directory_[0] == '\0') { // // No directory specified; for UNIX list all mount points. For DOS // list all valid drive letters... // if ((icon = Fl_File_Icon::find("any", Fl_File_Icon::DEVICE)) == NULL) icon = Fl_File_Icon::find("any", Fl_File_Icon::DIRECTORY); num_files = Fl::system_driver()->file_browser_load_filesystem(this, filename, (int)sizeof(filename), icon); } else { dirent **files; // Files in in directory char emsg[1024] = ""; // Build the file list, check for errors num_files = Fl::system_driver()->file_browser_load_directory(directory_, filename, sizeof(filename), &files, sort, emsg, sizeof(emsg)); // printf("Fl_File_Browser::load(dir='%s',filename='%s'): failed, emsg='%s'\n", directory_, filename, emsg); if (num_files <= 0) { errmsg(emsg); return 0; } for (i = 0, num_dirs = 0; i < num_files; i ++) { if (strcmp(files[i]->d_name, "./")) { fl_snprintf(filename, sizeof(filename), "%s/%s", directory_, files[i]->d_name); icon = Fl_File_Icon::find(filename); if ((icon && icon->type() == Fl_File_Icon::DIRECTORY) || Fl::system_driver()->filename_isdir_quick(filename)) { num_dirs ++; insert(num_dirs, files[i]->d_name, icon); } else if (filetype_ == FILES && fl_filename_match(files[i]->d_name, pattern_)) { add(files[i]->d_name, icon); } } free(files[i]); } free(files); } return (num_files); } // // 'Fl_File_Browser::filter()' - Set the filename filter. // void Fl_File_Browser::filter(const char *pattern) // I - Pattern string { // If pattern is NULL set the pattern to "*"... if (pattern) pattern_ = pattern; else pattern_ = "*"; } fltk-1.4.3/src/Fl_String.cxx0000644000175000017500000003670315004135251016020 0ustar albrechtalbrecht// // Basic Fl_String class for the Fast Light Tool Kit (FLTK). // // Copyright 2021-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include "Fl_String.H" #include #include #include #include /** \file src/Fl_String.cxx Basic Fl_String class for FLTK. */ /* If buffer_ is NULL, c_str() and buffer() will point here. */ const char Fl_String::NUL = 0; /** Indicate a maximum value or error. This value is generally used as end of string indicator or as the error indicator by the functions that return a string index. */ const int Fl_String::npos = INT_MAX; /** Initialise the class instance. */ void Fl_String::init_() { buffer_ = NULL; size_ = 0; capacity_ = 0; } /** Grow the buffer to a capacity of at least n bytes. This method will always grow the buffer size, or keep it as is, but never shrink it. Use shrink_to_fit() to shrink the buffer as much as possible. \param[in] n number of bytes needed, not counting the trailing NUL */ void Fl_String::grow_(int n) { if (n <= capacity_) return; int alloc_size_ = n + 1; // trailing NUL // round n up so we can grow in chunks if (alloc_size_ <= 24) { // allocate at least 24 bytes alloc_size_ = 24; } else if (alloc_size_ < 1024 + 8) { alloc_size_ = ((alloc_size_+128-8) & ~127) + 8; // allocate in 128 byte chunks } else { alloc_size_ = ((alloc_size_+2048-8) & ~2047) + 8; // allocate in 2k chunks // adding 8 keeps the buffer 64-bit aligned while generating a space for // the trailing NUL without jumping to the next chunk size for common // allocations like 1024 or 2048 (FL_PATH_MAX). } // allocate now char *new_buffer = (char*)::malloc(alloc_size_); if (buffer_ && (size_ > 0)) { memcpy(new_buffer, buffer_, size_); ::free(buffer_); } if (size_ >= 0) new_buffer[size_] = 0; // trailing NUL buffer_ = new_buffer; capacity_ = alloc_size_-1; // trailing NUL } /** Shrink the buffer to n bytes, or size, if size > n. Shrink the buffer as much as possible. If \p n is 0 and the string is empty, the buffer will be released. \param[in] n shrink buffer to n bytes, not counting the trailing NUL */ void Fl_String::shrink_(int n) { if (n < size_) n = size_; if (n == capacity_) return; if (n == 0) { if (buffer_) ::free(buffer_); buffer_ = NULL; } else { buffer_ = (char*)::realloc(buffer_, n+1); // NUL buffer_[size_] = 0; // trailing NUL } capacity_ = n; } /** Remove \p n_del bytes at \p at and insert \p n_ins bytes from \p src. String will remain NUL terminated. Data in \p ins may contain NULs. \param[in] at remove and insert bytes at this index \param[in] n_del number of bytes to remove \param[in] ins insert bytes from here, can be NULL if \p n_ins is also 0 \param[in] n_ins number of bytes to insert \return self */ Fl_String &Fl_String::replace_(int at, int n_del, const char *ins, int n_ins) { if (at > size_) at = size_; if (n_del > size_ - at) n_del = size_ - at; int diff = n_ins - n_del, new_size = size_ + diff; if (diff) { int src = at + n_del, dst = at + n_ins, n = size_ - src; grow_(new_size); if (n > 0) ::memmove(buffer_+dst, buffer_+src, n); } if (n_ins > 0) { ::memmove(buffer_+at, ins, n_ins); } size_ = new_size; if (buffer_) buffer_[size_] = 0; return *this; } // ---- Assignment ----------------------------------------------------- MARK: - /** Allocate an empty string. */ Fl_String::Fl_String() { init_(); } /** Copy constructor. \param[in] str copy from another Fl_String */ Fl_String::Fl_String(const Fl_String &str) { init_(); assign(str); } /** Constructor from a C-style string. \param[in] cstr a NUL terminated C-style string */ Fl_String::Fl_String(const char *cstr) { init_(); assign(cstr); } /** Constructor from data of \p size bytes. \param[in] str a block of data that may contain NUL characters \param[in] size number of bytes to copy */ Fl_String::Fl_String(const char *str, int size) { init_(); assign(str, size); } /** Destructor. */ Fl_String::~Fl_String() { if (buffer_) ::free(buffer_); } /** Copy assignment operator \param[in] str copy from another Fl_String \return self */ Fl_String &Fl_String::operator=(const Fl_String &str) { return assign(str); } /** Assign a C-style string. \param[in] cstr a NUL terminated C-style string \return self */ Fl_String &Fl_String::operator=(const char *cstr) { return assign(cstr); } /** Copy another string. \param[in] str copy from another Fl_String \return self */ Fl_String &Fl_String::assign(const Fl_String &str) { if (&str == this) return *this; return assign(str.data(), str.size()); } /** Assign a C-style string. \param[in] cstr a NUL terminated C-style string \return self */ Fl_String &Fl_String::assign(const char *cstr) { if (cstr && *cstr) { int len = (int)::strlen(cstr); return assign(cstr, len); } else { resize(0); } return *this; } /** Assign a data block of \p size bytes. \param[in] str a block of data that may contain NUL characters \param[in] size number of bytes to copy \return self */ Fl_String &Fl_String::assign(const char *str, int size) { if (size > 0) { grow_(size); memcpy(buffer_, str, size); buffer_[size] = 0; size_ = size; } else { resize(0); } return *this; } // ---- Element Access ------------------------------------------------- MARK: - /** Returns the character at specified bounds checked location. \param[in] n index of character \return character at that index, or NUL if out of bounds */ char Fl_String::at(int n) const { if ((n < 0) || (n >= size_)) return 0; return operator[](n); } /** Returns the character at specified location. \param[in] n index of character \return character at that index */ char Fl_String::operator[](int n) const { if (buffer_) return buffer_[n]; else return 0; } /** Returns a reference to the character at specified location. \param[in] n index of character \return reference to that character, so it can be used as lvalue */ char &Fl_String::operator[](int n) { if (!buffer_) reserve(1); return buffer_[n]; } /** Return a pointer to the NUL terminated string. \return reference to non-mutable string */ const char *Fl_String::data() const { if (buffer_) return buffer_; else return &NUL; } /** Return a pointer to the writable NUL terminated string. \return reference to mutable string */ char *Fl_String::data() { if (!buffer_) reserve(1); return buffer_; } /** Return a pointer to the NUL terminated string. \return reference to non-mutable string \note same as Fl_String::data() const */ const char *Fl_String::c_str() const { return data(); } // ---- Capacity ------------------------------------------------------- MARK: - /** Checks if the string is empty. \return true if string contains no data */ bool Fl_String::empty() const { return (size_ == 0); } /** Returns the number of bytes in the string. \return number of bytes in string, not counting trailing NUL */ int Fl_String::size() const { return size_; } /** Reserve n bytes for storage. If n is less or equal than size, the capacity is set to size. \param[in] n requested minimum size, not counting trailing NUL */ void Fl_String::reserve(int n) { grow_(n); } /** Return the number of chars that are allocated for storage. \return string capacity, not counting trailing NUL */ int Fl_String::capacity() const { return capacity_; } /** Shrink the capacity to fit the current size. */ void Fl_String::shrink_to_fit() { shrink_(size_); } // ---- Operations ----------------------------------------------------- MARK: - /** Set an empty string. */ void Fl_String::clear() { resize(0); } /** Insert a C-style string or data. \param[in] at insert at this index \param[in] src copy bytes from here \param[in] n_ins optional number of bytes to copy - if not set, copy C-style string \return self */ Fl_String &Fl_String::insert(int at, const char *src, int n_ins) { if (n_ins == npos) n_ins = src ? (int)::strlen(src) : 0; return replace_(at, 0, src, n_ins); } /** Insert another string. \param[in] at insert at this index \param[in] src copy string from here \return self */ Fl_String &Fl_String::insert(int at, const Fl_String &src) { return replace_(at, 0, src.buffer_, src.size_); } /** Erase some bytes within a string. \param[in] at erase at this index \param[in] n_del number of bytes to erase \return self */ Fl_String &Fl_String::erase(int at, int n_del) { return replace_(at, n_del, NULL, 0); } /** Append a single character. \param[in] c append this byte */ void Fl_String::push_back(char c) { replace_(size_, 0, &c, 1); } /** Remove the last character. */ void Fl_String::pop_back() { replace_(size_-1, 1, NULL, 0); } /** Append a C-style string or data. \param[in] src copy bytes from here \param[in] n_ins optional number of bytes to copy - if not set, copy C-style string \return self */ Fl_String &Fl_String::append(const char *src, int n_ins) { if (n_ins == npos) n_ins = src ? (int)::strlen(src) : 0; return replace_(size_, 0, src, n_ins); } /** Append another string. \param[in] src copy string from here \return self */ Fl_String &Fl_String::append(const Fl_String &src) { return replace_(size_, 0, src.buffer_, src.size_); } /** Append a single byte. \param[in] c single byte character \return self */ Fl_String &Fl_String::append(char c) { push_back(c); return *this; } /** Append a C-style string or data. \param[in] src copy C-style string from here \return self */ Fl_String &Fl_String::operator+=(const char *src) { return append(src); } /** Append another string. \param[in] src copy string from here \return self */ Fl_String &Fl_String::operator+=(const Fl_String &src) { return append(src); } /** Append a single byte. \param[in] c single byte character \return self */ Fl_String &Fl_String::operator+=(char c) { return append(c); } /** Find a string inside this string. \param[in] needle find this string \param[in] start_pos start looking at this position \return the offset of the text inside this string, if it was found \return Fl_String::npos if the needle was not found */ int Fl_String::find(const Fl_String &needle, int start_pos) const { if ((start_pos < 0) || (start_pos >= size_)) return npos; const char *haystack = data() + start_pos; const char *found = strstr(haystack, needle.c_str()); if (!found) return npos; return (int)(found - data()); } /** Replace part of the string with a C-style string or data. \param[in] at erase and insert at this index \param[in] n_del number of bytes to erase \param[in] src copy bytes from here \param[in] n_ins optional number of bytes to copy - if not set, copy C-style string \return self */ Fl_String &Fl_String::replace(int at, int n_del, const char *src, int n_ins) { if (n_ins == npos) n_ins = src ? (int)::strlen(src) : 0; return replace_(at, n_del, src, n_ins); } /** Replace part of the string with another string. \param[in] at erase and insert at this index \param[in] n_del number of bytes to erase \param[in] src copy string from here \return self */ Fl_String &Fl_String::replace(int at, int n_del, const Fl_String &src) { return replace_(at, n_del, src.buffer_, src.size_); } /** Return a substring from a string. \param[in] pos copy string from here - if omitted, copy from start \param[in] n number of bytes - if omitted, copy all bytes \return a new string */ Fl_String Fl_String::substr(int pos, int n) const { if (n > size_) n = size_; int first = pos, last = pos + n; if ((first < 0) || (first > size_) || (last <= first)) return Fl_String(); if (last > size_) last = size_; return Fl_String(buffer_+first, last-first); } /** Resizes the string to n characters. If \p n is less than the current size, the string will be cropped. If \p n is more than the current size, the new space will be filled with NUL characters. \param[in] n new size of string */ void Fl_String::resize(int n) { if (n == size_) return; if (n < size_) { size_ = n; if (buffer_) buffer_[size_] = 0; } else { grow_(n); if (buffer_) ::memset(buffer_+size_, 0, n-size_+1); } size_ = n; } // --- Non Standard ---------------------------------------------------- MARK: - /** Returns the number of bytes until the first NUL byte. \return number of bytes in C-style string */ int Fl_String::strlen() const { if (!buffer_) return 0; return (int)::strlen(buffer_); } /** Write some details about the string to stdout. Nothing at all is written if \p info is NULL, otherwise the short info string and details are written to stdout. The \p info string should not be longer than 20 characters to align the debug output of several strings. \param[in] info short info string or NULL */ void Fl_String::debug(const char *info) const { if (info) { printf("Fl_String '%-20s': %p, value = %p (%d/%d):\n%s\n", info, this, buffer_, size_, capacity_, buffer_ ? buffer_ : ""); } } /** Write some details about the string to stdout, followed by a hex dump of the string. The first part is the same as written by Fl_String::debug(). The following part is a hexadecimal dump of all bytes of the string. Embedded \p nul bytes are possible and will be dumped as well. \param[in] info short info string or NULL \see Fl_String::debug(const char *info) const */ void Fl_String::hexdump(const char *info) const { debug(info); if (size_ == 0) return; for (int i = 0; i < size_; i++) { if ((i & 15) == 0) { if (i > 0) printf("\n"); printf(" [%04x %4d] ", i, i); // position } else if ((i & 3) == 0) { // separator after 4 bytes printf(" "); } printf(" %02x", (unsigned char)buffer_[i]); } printf("\n"); } // ---- Non-member functions ------------------------------------------- MARK: - /** Concatenate two strings. \param[in] lhs first string \param[in] rhs second string \return self */ Fl_String operator+(const Fl_String &lhs, const Fl_String &rhs) { Fl_String ret = lhs; return ret += rhs; } /** Concatenate two strings. \param[in] lhs first string \param[in] rhs second C-style string \return self */ Fl_String operator+(const Fl_String &lhs, const char *rhs) { Fl_String ret = lhs; return ret += rhs; } /** Compare two strings. \param[in] lhs first string \param[in] rhs second string \return true if strings are the same size and have the same content */ bool operator==(const Fl_String &lhs, const Fl_String &rhs) { if (lhs.size() == rhs.size()) { int sz = lhs.size(); if (sz == 0) return true; if (memcmp(lhs.data(), rhs.data(), sz) == 0) return true; } return false; } /** Compare two strings for inequality. \param[in] lhs first string \param[in] rhs second string \return true if strings differ in size or content */ bool operator!=(const Fl_String &lhs, const Fl_String &rhs) { if (lhs.size() != rhs.size()) return true; int sz = lhs.size(); // same size for both if (memcmp(lhs.data(), rhs.data(), sz) != 0) return true; return false; } /** \} \endcond */ fltk-1.4.3/src/fl_rounded_box.cxx0000644000175000017500000000515315004135251017115 0ustar albrechtalbrecht// // Rounded box drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2020 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include // Global parameters for rounded corner drawing algorithm: // // RN = number of segments per corner (must match offset array size) // RS = max. corner radius // BW = box shadow width #define RS (Fl::box_border_radius_max()) #define BW (Fl::box_shadow_width()) static void rbox(int fill, int x, int y, int w, int h) { int rs, rsy; rs = w*2/5; rsy = h*2/5; if (rs > rsy) rs = rsy; // use smaller radius if (rs > RS) rs = RS; if (fill) fl_rounded_rectf(x, y, w, h, rs); else fl_rounded_rect(x, y, w, h, rs); } static void fl_rflat_box(int x, int y, int w, int h, Fl_Color c) { Fl::set_box_color(c); rbox(1, x, y, w, h); rbox(0, x, y, w, h); } static void fl_rounded_frame(int x, int y, int w, int h, Fl_Color c) { Fl::set_box_color(c); rbox(0, x, y, w, h); } static void fl_rounded_box(int x, int y, int w, int h, Fl_Color c) { Fl::set_box_color(c); rbox(1, x, y, w, h); fl_color(FL_BLACK); rbox(0, x, y, w, h); } static void fl_rshadow_box(int x, int y, int w, int h, Fl_Color c) { // draw shadow: fl_color(FL_DARK3); rbox(1, x+BW, y+BW, w, h); rbox(0, x+BW, y+BW, w, h); // draw the box: fl_rounded_box(x, y, w, h, c); } void fl_rounded_focus(Fl_Boxtype bt, int x, int y, int w, int h, Fl_Color fg, Fl_Color bg) { x += Fl::box_dx(bt); y += Fl::box_dy(bt); w -= Fl::box_dw(bt)+1; h -= Fl::box_dh(bt)+1; Fl_Color savecolor = fl_color(); fl_color(fl_contrast(fg, bg)); fl_line_style(FL_DOT); rbox(0, x+1, y+1, w-1, h-1); fl_line_style(FL_SOLID); fl_color(savecolor); } extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*, Fl_Box_Draw_Focus_F* =NULL); Fl_Boxtype fl_define_FL_ROUNDED_BOX() { fl_internal_boxtype(_FL_ROUNDED_FRAME, fl_rounded_frame, fl_rounded_focus); fl_internal_boxtype(_FL_ROUNDED_BOX, fl_rounded_box, fl_rounded_focus); return _FL_ROUNDED_BOX; } Fl_Boxtype fl_define_FL_RFLAT_BOX() { fl_internal_boxtype(_FL_RFLAT_BOX, fl_rflat_box, fl_rounded_focus); return _FL_RFLAT_BOX; } Fl_Boxtype fl_define_FL_RSHADOW_BOX() { fl_internal_boxtype(_FL_RSHADOW_BOX, fl_rshadow_box, fl_rounded_focus); return _FL_RSHADOW_BOX; } fltk-1.4.3/src/Fl_File_Chooser.cxx0000644000175000017500000003761415004135251017115 0ustar albrechtalbrecht// // Fl_File_Chooser dialog for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // ======================================================================= // DO NOT EDIT FL/Fl_File_Chooser.H and src/Fl_File_Chooser.cxx !!! // ======================================================================= // Please use fluid to change src/Fl_File_Chooser.fl interactively // and then use fluid to "write code" or edit and use fluid -c . // ======================================================================= // // generated by Fast Light User Interface Designer (fluid) version 1.0403 #include "../FL/Fl_File_Chooser.H" #include void Fl_File_Chooser::cb_window_i(Fl_Double_Window*, void*) { fileName->value(""); fileList->deselect(); hide(); } void Fl_File_Chooser::cb_window(Fl_Double_Window* o, void* v) { ((Fl_File_Chooser*)(o->user_data()))->cb_window_i(o,v); } void Fl_File_Chooser::cb_showChoice_i(Fl_Choice*, void*) { showChoiceCB(); } void Fl_File_Chooser::cb_showChoice(Fl_Choice* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_showChoice_i(o,v); } void Fl_File_Chooser::cb_favoritesButton_i(Fl_Menu_Button*, void*) { favoritesButtonCB(); } void Fl_File_Chooser::cb_favoritesButton(Fl_Menu_Button* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favoritesButton_i(o,v); } void Fl_File_Chooser::cb_newButton_i(Fl_Button*, void*) { newdir(); } void Fl_File_Chooser::cb_newButton(Fl_Button* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_newButton_i(o,v); } #include static const unsigned char idata_new[] = {0,0,120,0,132,0,2,1,1,254,1,128,49,128,49,128,253,128,253,128,49,128,49, 128,1,128,1,128,255,255,0,0}; static Fl_Image *image_new() { static Fl_Image *image = NULL; if (!image) image = new Fl_Bitmap(idata_new, 32, 16, 16); return image; } void Fl_File_Chooser::cb__i(Fl_Tile*, void*) { update_preview(); } void Fl_File_Chooser::cb_(Fl_Tile* o, void* v) { ((Fl_File_Chooser*)(o->parent()->user_data()))->cb__i(o,v); } void Fl_File_Chooser::cb_fileList_i(Fl_File_Browser*, void*) { fileListCB(); } void Fl_File_Chooser::cb_fileList(Fl_File_Browser* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_fileList_i(o,v); } void Fl_File_Chooser::cb_previewButton_i(Fl_Check_Button*, void*) { preview(previewButton->value()); } void Fl_File_Chooser::cb_previewButton(Fl_Check_Button* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->parent()->user_data()))->cb_previewButton_i(o,v); } void Fl_File_Chooser::cb_showHiddenButton_i(Fl_Check_Button*, void*) { showHidden(showHiddenButton->value()); } void Fl_File_Chooser::cb_showHiddenButton(Fl_Check_Button* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->parent()->user_data()))->cb_showHiddenButton_i(o,v); } void Fl_File_Chooser::cb_fileName_i(Fl_File_Input*, void*) { fileNameCB(); } void Fl_File_Chooser::cb_fileName(Fl_File_Input* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_fileName_i(o,v); } void Fl_File_Chooser::cb_okButton_i(Fl_Return_Button*, void*) { hide(); // Do any callback that is registered... if (callback_) (*callback_)(this, data_); } void Fl_File_Chooser::cb_okButton(Fl_Return_Button* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->parent()->user_data()))->cb_okButton_i(o,v); } void Fl_File_Chooser::cb_cancelButton_i(Fl_Button*, void*) { fileName->value(""); fileList->deselect(); hide(); } void Fl_File_Chooser::cb_cancelButton(Fl_Button* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->parent()->user_data()))->cb_cancelButton_i(o,v); } void Fl_File_Chooser::cb_favList_i(Fl_File_Browser*, void*) { favoritesCB(favList); } void Fl_File_Chooser::cb_favList(Fl_File_Browser* o, void* v) { ((Fl_File_Chooser*)(o->parent()->user_data()))->cb_favList_i(o,v); } void Fl_File_Chooser::cb_favUpButton_i(Fl_Button*, void*) { favoritesCB(favUpButton); } void Fl_File_Chooser::cb_favUpButton(Fl_Button* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favUpButton_i(o,v); } void Fl_File_Chooser::cb_favDeleteButton_i(Fl_Button*, void*) { favoritesCB(favDeleteButton); } void Fl_File_Chooser::cb_favDeleteButton(Fl_Button* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favDeleteButton_i(o,v); } void Fl_File_Chooser::cb_favDownButton_i(Fl_Button*, void*) { favoritesCB(favDownButton); } void Fl_File_Chooser::cb_favDownButton(Fl_Button* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favDownButton_i(o,v); } void Fl_File_Chooser::cb_favCancelButton_i(Fl_Button*, void*) { favWindow->hide(); } void Fl_File_Chooser::cb_favCancelButton(Fl_Button* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favCancelButton_i(o,v); } void Fl_File_Chooser::cb_favOkButton_i(Fl_Return_Button*, void*) { favoritesCB(favOkButton); } void Fl_File_Chooser::cb_favOkButton(Fl_Return_Button* o, void* v) { ((Fl_File_Chooser*)(o->parent()->parent()->user_data()))->cb_favOkButton_i(o,v); } Fl_File_Chooser::Fl_File_Chooser(const char *pathname, const char *pattern, int type_val, const char *title) { if (!prefs_) { prefs_ = new Fl_Preferences(Fl_Preferences::CORE_USER, "fltk.org", "filechooser"); } Fl_Group *prev_current = Fl_Group::current(); { window = new Fl_Double_Window(490, 380, "Choose File"); window->callback((Fl_Callback*)cb_window, (void*)(this)); { Fl_Group* o = new Fl_Group(10, 10, 470, 25); { showChoice = new Fl_Choice(65, 10, 215, 25, "Show:"); showChoice->down_box(FL_BORDER_BOX); showChoice->labelfont(1); showChoice->callback((Fl_Callback*)cb_showChoice); Fl_Group::current()->resizable(showChoice); showChoice->label(show_label); } // Fl_Choice* showChoice { favoritesButton = new Fl_Menu_Button(290, 10, 155, 25, "Favorites"); favoritesButton->down_box(FL_BORDER_BOX); favoritesButton->callback((Fl_Callback*)cb_favoritesButton); favoritesButton->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); favoritesButton->label(favorites_label); } // Fl_Menu_Button* favoritesButton { Fl_Button* o = newButton = new Fl_Button(455, 10, 25, 25); newButton->image( image_new() ); newButton->labelsize(8); newButton->callback((Fl_Callback*)cb_newButton); o->tooltip(new_directory_tooltip); } // Fl_Button* newButton o->end(); } // Fl_Group* o { Fl_Tile* o = new Fl_Tile(10, 45, 470, 225); o->callback((Fl_Callback*)cb_); { fileList = new Fl_File_Browser(10, 45, 295, 225); fileList->type(2); fileList->box(FL_DOWN_BOX); fileList->callback((Fl_Callback*)cb_fileList); fileList->window()->hotspot(fileList); } // Fl_File_Browser* fileList { errorBox = new Fl_Box(10, 45, 295, 225, "dynamic error display"); errorBox->box(FL_DOWN_BOX); errorBox->color(FL_BACKGROUND2_COLOR); errorBox->labelsize(18); errorBox->labelcolor((Fl_Color)1); errorBox->align(Fl_Align(133|FL_ALIGN_INSIDE)); errorBox->hide(); } // Fl_Box* errorBox { previewBox = new Fl_Box(305, 45, 175, 225, "?"); previewBox->box(FL_DOWN_BOX); previewBox->labelsize(100); previewBox->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); } // Fl_Box* previewBox o->end(); Fl_Group::current()->resizable(o); } // Fl_Tile* o { Fl_Group* o = new Fl_Group(10, 275, 470, 95); { Fl_Group* o = new Fl_Group(10, 275, 470, 20); { previewButton = new Fl_Check_Button(10, 275, 105, 20, "Preview"); previewButton->shortcut(FL_ALT|'p'); previewButton->down_box(FL_DOWN_BOX); previewButton->value(1); previewButton->callback((Fl_Callback*)cb_previewButton); previewButton->label(preview_label); } // Fl_Check_Button* previewButton { showHiddenButton = new Fl_Check_Button(115, 275, 140, 20, "Show hidden files"); showHiddenButton->down_box(FL_DOWN_BOX); showHiddenButton->callback((Fl_Callback*)cb_showHiddenButton); showHiddenButton->label(hidden_label); } // Fl_Check_Button* showHiddenButton { Fl_Box* o = new Fl_Box(255, 275, 225, 20); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o { fileName = new Fl_File_Input(115, 300, 365, 35); fileName->labelfont(1); fileName->callback((Fl_Callback*)cb_fileName); fileName->when(FL_WHEN_ENTER_KEY); Fl_Group::current()->resizable(fileName); fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY_ALWAYS); } // Fl_File_Input* fileName { Fl_Box* o = new Fl_Box(10, 310, 105, 25, "Filename:"); o->labelfont(1); o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE)); o->label(filename_label); } // Fl_Box* o { Fl_Group* o = new Fl_Group(10, 345, 470, 25); { okButton = new Fl_Return_Button(313, 345, 85, 25, "OK"); okButton->callback((Fl_Callback*)cb_okButton); okButton->label(fl_ok); } // Fl_Return_Button* okButton { Fl_Button* o = cancelButton = new Fl_Button(408, 345, 72, 25, "Cancel"); cancelButton->callback((Fl_Callback*)cb_cancelButton); o->label(fl_cancel); } // Fl_Button* cancelButton { Fl_Box* o = new Fl_Box(10, 345, 30, 25); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o o->end(); } // Fl_Group* o window->set_modal(); if (title) window->label(title); window->end(); } // Fl_Double_Window* window { favWindow = new Fl_Double_Window(355, 150, "Manage Favorites"); favWindow->user_data((void*)(this)); { favList = new Fl_File_Browser(10, 10, 300, 95); favList->type(2); favList->callback((Fl_Callback*)cb_favList); Fl_Group::current()->resizable(favList); } // Fl_File_Browser* favList { Fl_Group* o = new Fl_Group(320, 10, 25, 95); { favUpButton = new Fl_Button(320, 10, 25, 25, "@8>"); favUpButton->callback((Fl_Callback*)cb_favUpButton); } // Fl_Button* favUpButton { favDeleteButton = new Fl_Button(320, 45, 25, 25, "X"); favDeleteButton->labelfont(1); favDeleteButton->callback((Fl_Callback*)cb_favDeleteButton); Fl_Group::current()->resizable(favDeleteButton); } // Fl_Button* favDeleteButton { favDownButton = new Fl_Button(320, 80, 25, 25, "@2>"); favDownButton->callback((Fl_Callback*)cb_favDownButton); } // Fl_Button* favDownButton o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(10, 113, 335, 29); { favCancelButton = new Fl_Button(273, 115, 72, 25, "Cancel"); favCancelButton->callback((Fl_Callback*)cb_favCancelButton); favCancelButton->label(fl_cancel); } // Fl_Button* favCancelButton { favOkButton = new Fl_Return_Button(181, 115, 79, 25, "Save"); favOkButton->callback((Fl_Callback*)cb_favOkButton); favOkButton->label(save_label); } // Fl_Return_Button* favOkButton { Fl_Box* o = new Fl_Box(10, 115, 161, 25); Fl_Group::current()->resizable(o); } // Fl_Box* o o->end(); } // Fl_Group* o favWindow->set_modal(); favWindow->size_range(181, 150); favWindow->label(manage_favorites_label); favWindow->end(); } // Fl_Double_Window* favWindow callback_ = 0; data_ = 0; directory_[0] = 0; window->size_range(window->w(), window->h()); type(type_val); filter(pattern); update_favorites(); value(pathname); type(type_val); int e; prefs_->get("preview", e, 1); preview(e); Fl_Group::current(prev_current); ext_group=(Fl_Widget*)0; } Fl_File_Chooser::~Fl_File_Chooser() { Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this); if(ext_group)window->remove(ext_group); delete window; delete favWindow; } void Fl_File_Chooser::callback(void (*cb)(Fl_File_Chooser *, void *), void *d ) { callback_ = cb; data_ = d; } void Fl_File_Chooser::color(Fl_Color c) { fileList->color(c); } Fl_Color Fl_File_Chooser::color() { return (fileList->color()); } char * Fl_File_Chooser::directory() { return directory_; } const char * Fl_File_Chooser::filter() { return (fileList->filter()); } int Fl_File_Chooser::filter_value() { return showChoice->value(); } void Fl_File_Chooser::filter_value(int f) { showChoice->value(f); showChoiceCB(); } void Fl_File_Chooser::iconsize(uchar s) { fileList->iconsize(s); } uchar Fl_File_Chooser::iconsize() { return (fileList->iconsize()); } void Fl_File_Chooser::label(const char *l) { window->label(l); } const char * Fl_File_Chooser::label() { return (window->label()); } void Fl_File_Chooser::ok_label(const char *l) { if (l) okButton->label(l); int w=0, h=0; okButton->measure_label(w, h); okButton->resize(cancelButton->x() - 50 - w, cancelButton->y(), w + 40, 25); okButton->parent()->init_sizes(); } const char * Fl_File_Chooser::ok_label() { return (okButton->label()); } int Fl_File_Chooser::shown() { return window->shown(); } void Fl_File_Chooser::textcolor(Fl_Color c) { fileList->textcolor(c); } Fl_Color Fl_File_Chooser::textcolor() { return (fileList->textcolor()); } void Fl_File_Chooser::textfont(Fl_Font f) { fileList->textfont(f); } Fl_Font Fl_File_Chooser::textfont() { return (fileList->textfont()); } void Fl_File_Chooser::textsize(Fl_Fontsize s) { fileList->textsize(s); } Fl_Fontsize Fl_File_Chooser::textsize() { return (fileList->textsize()); } void Fl_File_Chooser::type(int t) { type_ = t; if (t & MULTI) fileList->type(FL_MULTI_BROWSER); else fileList->type(FL_HOLD_BROWSER); if (t & CREATE) newButton->activate(); else newButton->deactivate(); if (t & DIRECTORY) fileList->filetype(Fl_File_Browser::DIRECTORIES); else fileList->filetype(Fl_File_Browser::FILES); } int Fl_File_Chooser::type() { return (type_); } void * Fl_File_Chooser::user_data() const { return (data_); } void Fl_File_Chooser::user_data(void *d) { data_ = d; } int Fl_File_Chooser::visible() { return window->visible(); } void Fl_File_Chooser::position(int x, int y) { window->position(x, y); } int Fl_File_Chooser::x() const { return window->x(); } int Fl_File_Chooser::y() const { return window->y(); } int Fl_File_Chooser::w() const { return window->w(); } int Fl_File_Chooser::h() const { return window->h(); } void Fl_File_Chooser::size(int w, int h) { window->size(w, h); } void Fl_File_Chooser::resize(int x, int y, int w, int h) { window->resize(x, y, w, h); } Fl_Widget* Fl_File_Chooser::add_extra(Fl_Widget* gr) { Fl_Widget* ret=ext_group; if (gr==ext_group) { return ret; } if (ext_group) { int sh=ext_group->h()+4; Fl_Widget* svres=window->resizable(); window->resizable(NULL); window->size(window->w(),window->h()-sh); window->remove(ext_group); ext_group=NULL; window->resizable(svres); } if (gr) { int nh=window->h()+gr->h()+4; Fl_Widget* svres=window->resizable(); window->resizable(NULL); window->size(window->w(),nh); gr->position(2,okButton->y()+okButton->h()+2); window->add(gr); ext_group=gr; window->resizable(svres); } return ret; } /** Show error box if val=1, hide if val=0 */ void Fl_File_Chooser::show_error_box(int val) { if ( val ) { errorBox->color(fileList->color()); // inherit fileList's bg color errorBox->show(); fileList->hide(); } else { errorBox->hide(); fileList->show(); } } fltk-1.4.3/src/Fl_Pixmap.cxx0000644000175000017500000002611415004135251016003 0ustar albrechtalbrecht// // Pixmap drawing code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Draws X pixmap data, keeping it stashed in a server pixmap so it // redraws fast. // See fl_draw_pixmap.cxx for code used to get the actual data into pixmap. // Implemented without using the xpm library (which I can't use because // it interferes with the color cube used by fl_draw_image). #include #include #include #include #include #include #include #include "flstring.h" #include void Fl_Pixmap::measure() { int W, H; // ignore empty or bad pixmap data: if (w()<0 && data()) { fl_measure_pixmap(data(), W, H); w(W); h(H); cache_w_ = cache_h_ = 0; } } void Fl_Pixmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { fl_graphics_driver->draw_pixmap(this, XP, YP, WP, HP, cx, cy); } /** The destructor frees all memory and server resources that are used by the pixmap. */ Fl_Pixmap::~Fl_Pixmap() { uncache(); delete_data(); } void Fl_Pixmap::uncache() { if (id_) { Fl_Graphics_Driver::default_driver().uncache_pixmap(id_); id_ = 0; } if (mask_) { Fl_Graphics_Driver::default_driver().delete_bitmask(mask_); mask_ = 0; } } void Fl_Pixmap::label(Fl_Widget* widget) { widget->image(this); } void Fl_Pixmap::label(Fl_Menu_Item* m) { m->label(FL_IMAGE_LABEL, (const char*)this); } void Fl_Pixmap::copy_data() { if (alloc_data) return; char **new_data, // New data array **new_row; // Current row in image int i, // Looping var ncolors, // Number of colors in image chars_per_pixel,// Characters per color chars_per_line; // Characters per line // Figure out how many colors there are, and how big they are... sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel); chars_per_line = chars_per_pixel * data_w() + 1; // Allocate memory for the new array... if (ncolors < 0) new_data = new char *[data_h() + 2]; else new_data = new char *[data_h() + ncolors + 1]; new_data[0] = new char[strlen(data()[0]) + 1]; strcpy(new_data[0], data()[0]); // Copy colors... if (ncolors < 0) { // Copy FLTK colormap values... ncolors = -ncolors; new_row = new_data + 1; *new_row = new char[ncolors * 4]; memcpy(*new_row, data()[1], ncolors * 4); ncolors = 1; new_row ++; } else { // Copy standard XPM colormap values... for (i = 0, new_row = new_data + 1; i < ncolors; i ++, new_row ++) { *new_row = new char[strlen(data()[i + 1]) + 1]; strcpy(*new_row, data()[i + 1]); } } // Copy image data... for (i = 0; i < data_h(); i ++, new_row ++) { *new_row = new char[chars_per_line]; memcpy(*new_row, data()[i + ncolors + 1], chars_per_line); } // Update pointers... data((const char **)new_data, data_h() + ncolors + 1); alloc_data = 1; } Fl_Image *Fl_Pixmap::copy(int W, int H) const { Fl_Pixmap *new_image; // New pixmap if (!data()) { // happens with bad pixmap data return new Fl_Pixmap((char *const*)0); } // Optimize the simple copy where the width and height are the same... if (W == data_w() && H == data_h()) { // Make an exact copy of the image and return it... new_image = new Fl_Pixmap(data()); new_image->copy_data(); return new_image; } if (W <= 0 || H <= 0) return 0; // OK, need to resize the image data; allocate memory and char **new_data, // New array for image data **new_row, // Pointer to row in image data *new_ptr, // Pointer into new array new_info[255]; // New information line const char *old_ptr; // Pointer into old array int i, // Looping var c, // Channel number sy, // Source coordinate dx, dy, // Destination coordinates xerr, yerr, // X & Y errors xmod, ymod, // X & Y moduli xstep, ystep; // X & Y step increments int ncolors, // Number of colors in image chars_per_pixel,// Characters per color chars_per_line; // Characters per line // Figure out how many colors there are, and how big they are... sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel); chars_per_line = chars_per_pixel * W + 1; snprintf(new_info, sizeof(new_info), "%d %d %d %d", W, H, ncolors, chars_per_pixel); // Figure out Bresenham step/modulus values... xmod = data_w() % W; xstep = (data_w() / W) * chars_per_pixel; ymod = data_h() % H; ystep = data_h() / H; // Allocate memory for the new array... if (ncolors < 0) new_data = new char *[H + 2]; else new_data = new char *[H + ncolors + 1]; new_data[0] = new char[strlen(new_info) + 1]; strcpy(new_data[0], new_info); // Copy colors... if (ncolors < 0) { // Copy FLTK colormap values... ncolors = -ncolors; new_row = new_data + 1; *new_row = new char[ncolors * 4]; memcpy(*new_row, data()[1], ncolors * 4); ncolors = 1; new_row ++; } else { // Copy standard XPM colormap values... for (i = 0, new_row = new_data + 1; i < ncolors; i ++, new_row ++) { *new_row = new char[strlen(data()[i + 1]) + 1]; strcpy(*new_row, data()[i + 1]); } } // Scale the image using a nearest-neighbor algorithm... for (dy = H, sy = 0, yerr = H; dy > 0; dy --, new_row ++) { *new_row = new char[chars_per_line]; new_ptr = *new_row; for (dx = W, xerr = W, old_ptr = data()[sy + ncolors + 1]; dx > 0; dx --) { for (c = 0; c < chars_per_pixel; c ++) *new_ptr++ = old_ptr[c]; old_ptr += xstep; xerr -= xmod; if (xerr <= 0) { xerr += W; old_ptr += chars_per_pixel; } } *new_ptr = '\0'; sy += ystep; yerr -= ymod; if (yerr <= 0) { yerr += H; sy ++; } } new_image = new Fl_Pixmap((char*const*)new_data); new_image->alloc_data = 1; return new_image; } void Fl_Pixmap::color_average(Fl_Color c, float i) { // Delete any existing pixmap/mask objects... uncache(); // Allocate memory as needed... copy_data(); // Get the color to blend with... uchar r, g, b; unsigned ia, ir, ig, ib; Fl::get_color(c, r, g, b); if (i < 0.0f) i = 0.0f; else if (i > 1.0f) i = 1.0f; ia = (unsigned)(256 * i); ir = r * (256 - ia); ig = g * (256 - ia); ib = b * (256 - ia); // Update the colormap to do the blend... char line[255]; // New colormap line int color, // Looping var ncolors, // Number of colors in image chars_per_pixel;// Characters per color sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel); if (ncolors < 0) { // Update FLTK colormap... ncolors = -ncolors; uchar *cmap = (uchar *)(data()[1]); for (color = 0; color < ncolors; color ++, cmap += 4) { cmap[1] = (ia * cmap[1] + ir) >> 8; cmap[2] = (ia * cmap[2] + ig) >> 8; cmap[3] = (ia * cmap[3] + ib) >> 8; } } else { // Update standard XPM colormap... for (color = 0; color < ncolors; color ++) { // look for "c word", or last word if none: const char *p = data()[color + 1] + chars_per_pixel + 1; const char *previous_word = p; for (;;) { while (*p && isspace(*p)) p++; char what = *p++; while (*p && !isspace(*p)) p++; while (*p && isspace(*p)) p++; if (!*p) {p = previous_word; break;} if (what == 'c') break; previous_word = p; while (*p && !isspace(*p)) p++; } if (fl_parse_color(p, r, g, b)) { r = (ia * r + ir) >> 8; g = (ia * g + ig) >> 8; b = (ia * b + ib) >> 8; if (chars_per_pixel > 1) snprintf(line, sizeof(line), "%c%c c #%02X%02X%02X", data()[color + 1][0], data()[color + 1][1], r, g, b); else snprintf(line, sizeof(line), "%c c #%02X%02X%02X", data()[color + 1][0], r, g, b); delete[] (char *)data()[color + 1]; ((char **)data())[color + 1] = new char[strlen(line) + 1]; strcpy((char *)data()[color + 1], line); } } } } void Fl_Pixmap::delete_data() { if (alloc_data) { for (int i = 0; i < count(); i ++) delete[] (char *)data()[i]; delete[] (char **)data(); } } void Fl_Pixmap::set_data(const char * const * p) { int height, // Number of lines in image ncolors; // Number of colors in image if (p) { sscanf(p[0],"%*d%d%d", &height, &ncolors); if (ncolors < 0) data(p, height + 2); else data(p, height + ncolors + 1); } } void Fl_Pixmap::desaturate() { // Delete any existing pixmap/mask objects... uncache(); // Allocate memory as needed... copy_data(); // Update the colormap to grayscale... char line[255]; // New colormap line int i, // Looping var ncolors, // Number of colors in image chars_per_pixel;// Characters per color uchar r, g, b; sscanf(data()[0],"%*d%*d%d%d", &ncolors, &chars_per_pixel); if (ncolors < 0) { // Update FLTK colormap... ncolors = -ncolors; uchar *cmap = (uchar *)(data()[1]); for (i = 0; i < ncolors; i ++, cmap += 4) { g = (uchar)((cmap[1] * 31 + cmap[2] * 61 + cmap[3] * 8) / 100); cmap[1] = cmap[2] = cmap[3] = g; } } else { // Update standard XPM colormap... for (i = 0; i < ncolors; i ++) { // look for "c word", or last word if none: const char *p = data()[i + 1] + chars_per_pixel + 1; const char *previous_word = p; for (;;) { while (*p && isspace(*p)) p++; char what = *p++; while (*p && !isspace(*p)) p++; while (*p && isspace(*p)) p++; if (!*p) {p = previous_word; break;} if (what == 'c') break; previous_word = p; while (*p && !isspace(*p)) p++; } if (fl_parse_color(p, r, g, b)) { g = (uchar)((r * 31 + g * 61 + b * 8) / 100); if (chars_per_pixel > 1) { snprintf(line, sizeof(line), "%c%c c #%02X%02X%02X", data()[i + 1][0], data()[i + 1][1], g, g, g); } else { snprintf(line, sizeof(line), "%c c #%02X%02X%02X", data()[i + 1][0], g, g, g); } delete[] (char *)data()[i + 1]; ((char **)data())[i + 1] = new char[strlen(line) + 1]; strcpy((char *)data()[i + 1], line); } } } } fltk-1.4.3/src/Fl_display.cxx0000644000175000017500000000173615004135251016215 0ustar albrechtalbrecht// // Display function for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Startup method to set what display to use. // Using setenv makes programs that are exec'd use the same display. #include #include "Fl_Screen_Driver.H" /** Sets the X or Wayland display to use for all windows. This sets the environment variable $DISPLAY or $WAYLAND_DISPLAY to the passed string, so this only works before you show() the first window or otherwise open the display. This does nothing on other platforms. */ void Fl::display(const char *d) { screen_driver()->display(d); } fltk-1.4.3/src/Fl_Image_Reader.h0000644000175000017500000000622115004135251016473 0ustar albrechtalbrecht// // Internal (Image) Reader class for the Fast Light Tool Kit (FLTK). // // Copyright 2020-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /* This internal (undocumented) class reads data chunks from a file or from memory in LSB-first byte order. This class is used in Fl_GIF_Image and Fl_BMP_Image to avoid code duplication and may be extended to be used in similar cases. Future options might be to read data in MSB-first byte order or to add more methods. */ #ifndef FL_IMAGE_READER_H #define FL_IMAGE_READER_H #include class Fl_Image_Reader { public: // Create the reader. Fl_Image_Reader() : is_file_(0) , is_data_(0) , file_(0L) , data_(0L) , start_(0L) , end_((const unsigned char *)(-1L)) , name_(0L) , error_(0) {} // Initialize the reader to access the file system, filename is copied // and stored. int open(const char *filename); // Initialize the reader for memory access, name is copied and stored int open(const char *imagename, const unsigned char *data, const size_t datasize); // Deprecated, DO NOT USE! int open(const char *imagename, const unsigned char *data); // Close and destroy the reader ~Fl_Image_Reader(); // Read a single byte from memory or a file unsigned char read_byte(); // Read a 16-bit unsigned integer, LSB-first unsigned short read_word(); // Read a 32-bit unsigned integer, LSB-first unsigned int read_dword(); // Read a 32-bit signed integer, LSB-first int read_long() { return (int)read_dword(); } // Move the current read position to a byte offset from the beginning // of the file or the original start address in memory void seek(unsigned int n); // Get the current file or memory offset from the beginning // of the file or the original start address in memory long tell() const; // Get the current EOF or error status of the file or data block int error() const { return error_; } // return the name or filename for this reader const char *name() const { return name_; } // skip a given number of bytes void skip(unsigned int n) { seek((unsigned int)tell() + n); } private: // open() sets this if we read from a file char is_file_; // open() sets this if we read from memory char is_data_; // a pointer to the opened file FILE *file_; // a pointer to the current byte in memory const unsigned char *data_; // a pointer to the start of the image data const unsigned char *start_; // a pointer to the end of image data if reading from memory, otherwise undefined // note: currently (const unsigned char *)(-1L) if end of memory is not available // ... which means "unlimited" const unsigned char *end_; // a copy of the name associated with this reader char *name_; // a flag to store EOF or error status int error_; }; #endif // FL_IMAGE_READER_H fltk-1.4.3/src/Fl_Light_Button.cxx0000644000175000017500000001225315004135251017146 0ustar albrechtalbrecht// // Lighted button widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Subclass of Fl_Button where the "box" indicates whether it is // pushed or not, and the "down box" is drawn small and square on // the left to indicate the current state. // The default down_box of zero draws a rectangle designed to look // just like Flame's buttons. #include #include #include #include #include "flstring.h" void Fl_Light_Button::draw() { if (box()) draw_box(this==Fl::pushed() ? fl_down(box()) : box(), color()); Fl_Color col = value() ? (active_r() ? selection_color() : fl_inactive(selection_color())) : color(); // determine the color of the check mark or radio button (circle) Fl_Color check_color = selection_color(); // default = selection color if (Fl::is_scheme("gtk+")) check_color = FL_SELECTION_COLOR; // exception for gtk+ if (!active_r()) check_color = fl_inactive(check_color); // select a color with enough contrast check_color = fl_contrast(check_color, FL_BACKGROUND2_COLOR); int W = labelsize(); // check mark box size if (W > 25) W = 25; // limit box size int bx = Fl::box_dx(box()); // box frame width int dx = bx + 2; // relative position of check mark box int dy = (h() - W) / 2; // neg. offset o.k. for vertical centering int lx = 0; // relative label position (STR #3237) int cx = x() + dx; // check mark box x-position int cy = y() + dy; // check mark box y-position int cw = 0; // check mark box width and height // FIXME: the *box type* of the widget determines the drawing style: // (a) down_box() == 0: Fl_Light_Button style // (b) down_box() != 0: other button styles if (down_box()) { // draw "other" button styles (b): switch (down_box()) { case FL_DOWN_BOX : case FL_UP_BOX : case _FL_PLASTIC_DOWN_BOX : case _FL_PLASTIC_UP_BOX : // Check box... draw_box(down_box(), cx, cy, W, W, FL_BACKGROUND2_COLOR); if (value()) { // Check mark... // Calculate box position and size cx += Fl::box_dx(down_box()); cy += Fl::box_dy(down_box()); cw = W - Fl::box_dw(down_box()); fl_draw_check(Fl_Rect(cx, cy, cw, cw), check_color); } break; case _FL_ROUND_DOWN_BOX : case _FL_ROUND_UP_BOX : // Radio button... draw_box(down_box(), x()+dx, y()+dy, W, W, FL_BACKGROUND2_COLOR); if (value()) { // Draw round check mark of radio button int tW = (W - Fl::box_dw(down_box())) / 2 + 1; if ((W - tW) & 1) tW++; // Make sure difference is even to center int tdx = dx + (W - tW) / 2; int tdy = dy + (W - tW) / 2; fl_draw_radio(x() + tdx - 1, y() + tdy - 1, tW + 2, check_color); } // Radio button: if (value()) break; default : draw_box(down_box(), x()+dx, y()+dy, W, W, col); break; } lx = dx + W + 2; } else { // if down_box() is zero, draw light button style (a): int hh = h()-2*dy - 2; int ww = W/2+1; int xx = dx; if (w() #include "Fl_Screen_Driver.H" // ----------------------------------------------------------------------------- // all driver code is now in drivers/XXX/Fl_XXX_Graphics_Driver_xyz.cxx // ----------------------------------------------------------------------------- double fl_width(const char* c) { if (c) return fl_width(c, (int) strlen(c)); else return 0.0f; } void fl_draw(const char* str, int x, int y) { fl_draw(str, (int) strlen(str), x, y); } void fl_draw(int angle, const char* str, int x, int y) { fl_draw(angle, str, (int) strlen(str), x, y);//must be fixed! } void fl_text_extents(const char *c, int &dx, int &dy, int &w, int &h) { if (c) fl_text_extents(c, (int) strlen(c), dx, dy, w, h); else { w = 0; h = 0; dx = 0; dy = 0; } } // fl_text_extents void fl_draw(const char* str, int l, float x, float y) { fl_graphics_driver->draw(str, l, x, y); } void fl_set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) { Fl::screen_driver()->set_spot(font, size, X, Y, W, H, win); } void fl_reset_spot() { Fl::screen_driver()->reset_spot(); } /** Related to text input methods under X11. This function is presently used only by the \c utf8 test application and only for the X11 platform. This function is apparently not indispensable for text input to work correctly as suggested by other apps that don't use it (e.g., editor). */ void fl_set_status(int X, int Y, int W, int H) { Fl::screen_driver()->set_status(X, Y, W, H); } fltk-1.4.3/src/Fl_GIF_Image.cxx0000644000175000017500000006406615004135251016264 0ustar albrechtalbrecht// // Fl_GIF_Image routines. // // Copyright 1997-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // Reference: GIF89a Specification (links valid as of Jan 05, 2019): // // "GRAPHICS INTERCHANGE FORMAT(sm), Version 89a" (authoritative): // https://www.w3.org/Graphics/GIF/spec-gif89a.txt // // HTML version (non-authoritative): // https://web.archive.org/web/20160304075538/http://qalle.net/gif89a.php // // // Include necessary header files... // #include #include #include "Fl_Image_Reader.h" #include #include "flstring.h" #include #include // Read a .gif file and convert it to a "xpm" format (actually my // modified one with compressed colormaps). // Extensively modified from original code for gif2ras by // Patrick J. Naughton of Sun Microsystems. The original // copyright notice follows: /* gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image. * * Copyright (c) 1988 by Patrick J. Naughton * * Author: Patrick J. Naughton * naughton@wind.sun.com * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * * Comments and additions should be sent to the author: * * Patrick J. Naughton * Sun Microsystems, Inc. * 2550 Garcia Ave, MS 14-40 * Mountain View, CA 94043 * (415) 336-1080 */ /* Internally used structure to hold GIF color map data during decoding. */ struct ColorMap { uchar Red[256]; uchar Green[256]; uchar Blue[256]; }; /* This small helper function checks for read errors or end of file and does some cleanup if an error was found. It returns true (1) on error, false (0) otherwise. */ static int gif_error(Fl_Image_Reader &rdr, int line, uchar *Image) { if (rdr.error()) { if (Image) delete[] Image; // delete temporary image array Fl::error("[%d] Fl_GIF_Image: %s - unexpected EOF or read error at offset %ld", line, rdr.name(), rdr.tell()); return 1; } return 0; } /* This macro is used to check for end of file (EOF) or other read errors. In case of a read error or EOF an error message is issued and the image loading is terminated with error code ERR_FORMAT. This calls gif_error (see above) to avoid code duplication. */ #define CHECK_ERROR \ if (gif_error(rdr, __LINE__, Image)) { \ ld(ERR_FORMAT); \ return; \ } /** This constructor loads a GIF image from the given file. If a GIF image is animated, Fl_GIF_Image will only read and display the first frame of the animation. The destructor frees all memory and server resources that are used by the image. Use Fl_Image::fail() to check if Fl_GIF_Image failed to load. fail() returns ERR_FILE_ACCESS if the file could not be opened or read, ERR_FORMAT if the GIF format could not be decoded, and ERR_NO_IMAGE if the image could not be loaded for another reason. \param[in] filename a full path and name pointing to a GIF image file. \see Fl_GIF_Image::Fl_GIF_Image(const char *imagename, const unsigned char *data, const long length) */ Fl_GIF_Image::Fl_GIF_Image(const char *filename) : Fl_Pixmap((char *const*)0) { Fl_Image_Reader rdr; if (rdr.open(filename) == -1) { Fl::error("Fl_GIF_Image: Unable to open %s!", filename); ld(ERR_FILE_ACCESS); } else { load_gif_(rdr); } } /** This constructor loads a GIF image from memory. Construct an image from a block of memory inside the application. Fluid offers "binary data" chunks as a great way to add image data into the C++ source code. \p imagename can be \c NULL. If a name is given, the image is added to the list of shared images and will be available by that name. If a GIF image is animated, Fl_GIF_Image will only read and display the first frame of the animation. The destructor frees all memory and server resources that are used by the image. The third parameter \p length is used to test for buffer overruns, i.e. truncated images. Use Fl_Image::fail() to check if Fl_GIF_Image failed to load. fail() returns ERR_FILE_ACCESS if the file could not be opened or read, ERR_FORMAT if the GIF format could not be decoded, and ERR_NO_IMAGE if the image could not be loaded for another reason. \param[in] imagename A name given to this image or NULL \param[in] data Pointer to the start of the GIF image in memory. \param[in] length Length of the GIF image in memory. \see Fl_GIF_Image::Fl_GIF_Image(const char *filename) \see Fl_Shared_Image \since 1.4.0 */ Fl_GIF_Image::Fl_GIF_Image(const char *imagename, const unsigned char *data, const size_t length) : Fl_Pixmap((char *const*)0) { Fl_Image_Reader rdr; if (rdr.open(imagename, data, length) == -1) { ld(ERR_FILE_ACCESS); } else { load_gif_(rdr); } } /** This constructor loads a GIF image from memory (deprecated). \deprecated Please use Fl_GIF_Image(const char *imagename, const unsigned char *data, const size_t length) instead. \note Buffer overruns will not be checked. This constructor should not be used because the caller can't supply the memory size and the image reader can't check for "end of memory" errors. \note A new constructor with parameter \p length is available since FLTK 1.4.0. \param[in] imagename A name given to this image or NULL \param[in] data Pointer to the start of the GIF image in memory. \see Fl_GIF_Image(const char *filename) \see Fl_GIF_Image(const char *imagename, const unsigned char *data, const size_t length) */ Fl_GIF_Image::Fl_GIF_Image(const char *imagename, const unsigned char *data) : Fl_Pixmap((char *const*)0) { Fl_Image_Reader rdr; if (rdr.open(imagename, data) == -1) { ld(ERR_FILE_ACCESS); } else { load_gif_(rdr); } } Fl_GIF_Image::Fl_GIF_Image(const char *filename, bool anim) : Fl_Pixmap((char *const*)0) { Fl_Image_Reader rdr; if (rdr.open(filename) == -1) { Fl::error("Fl_GIF_Image: Unable to open %s!", filename); ld(ERR_FILE_ACCESS); } else { load_gif_(rdr, anim); } } Fl_GIF_Image::Fl_GIF_Image(const char *imagename, const unsigned char *data, const size_t length, bool anim) : Fl_Pixmap((char *const*)0) { Fl_Image_Reader rdr; if (rdr.open(imagename, data, length) == -1) { ld(ERR_FILE_ACCESS); } else { load_gif_(rdr, anim); } } /** The default constructor creates an empty GIF image. */ Fl_GIF_Image::Fl_GIF_Image() : Fl_Pixmap((char *const*)0) { } /* Internally used method to read from the LZW compressed data stream 'rdr' and decode it to 'Image' buffer. NOTE: This methode has been extracted from load_gif_() in order to make the code more read/hand-able. */ void Fl_GIF_Image::lzw_decode(Fl_Image_Reader &rdr, uchar *Image, int Width, int Height, int CodeSize, int ColorMapSize, int Interlace) { int YC = 0, Pass = 0; /* Used to de-interlace the picture */ uchar *p = Image; uchar *eol = p+Width; int InitCodeSize = CodeSize; int ClearCode = (1 << (CodeSize-1)); int EOFCode = ClearCode + 1; int FirstFree = ClearCode + 2; int FinChar = 0; int ReadMask = (1< 7) { if (blocklen <= 0) { blocklen = rdr.read_byte(); CHECK_ERROR if (blocklen <= 0) break; } thisbyte = rdr.read_byte(); blocklen--; CHECK_ERROR CurCode |= thisbyte<<8; } if (frombit+CodeSize > 15) { if (blocklen <= 0) { blocklen = rdr.read_byte(); CHECK_ERROR if (blocklen <= 0) break; } thisbyte = rdr.read_byte(); blocklen--; CHECK_ERROR CurCode |= thisbyte<<16; } CurCode = (CurCode>>frombit)&ReadMask; frombit = (frombit+CodeSize)%8; if (CurCode == ClearCode) { CodeSize = InitCodeSize; ReadMask = (1<= ColorMapSize) { if (i < FreeCode) { *tp++ = Suffix[i]; i = Prefix[i]; } else { // FIXME - should never happen (?) Fl::error("Fl_GIF_Image: %s - i(%d) >= FreeCode (%d) at offset %ld", rdr.name(), i, FreeCode, rdr.tell()); // NOTREACHED i = FreeCode - 1; // fix broken index ??? break; } } *tp++ = FinChar = i; do { *p++ = *--tp; if (p >= eol) { if (!Interlace) YC++; else switch (Pass) { case 0: YC += 8; if (YC >= Height) {Pass++; YC = 4;} break; case 1: YC += 8; if (YC >= Height) {Pass++; YC = 2;} break; case 2: YC += 4; if (YC >= Height) {Pass++; YC = 1;} break; case 3: YC += 2; break; } if (YC>=Height) YC=0; /* cheap bug fix when excess data */ p = Image + YC*Width; eol = p+Width; } } while (tp > OutCode); if (OldCode != ClearCode) { if (FreeCode < 4096) { Prefix[FreeCode] = (short)OldCode; Suffix[FreeCode] = FinChar; FreeCode++; } if (FreeCode > ReadMask) { if (CodeSize < 12) { CodeSize++; ReadMask = (1 << CodeSize) - 1; } } } OldCode = CurCode; } } /* Internally used function to convert raw 'Image' data to XPM format in an allocated buffer 'new_data'. NOTE: This function has been extracted from load_gif_() in order to make the code more read/hand-able. */ static char ** convert_to_xpm(uchar *Image, int Width, int Height, ColorMap &CMap, int ColorMapSize, int transparent_pixel) { // allocate line pointer arrays: char **new_data = new char*[Height+2]; // transparent pixel must be zero, swap if it isn't: if (transparent_pixel > 0) { // swap transparent pixel with zero uchar *p = Image+Width*Height; while (p-- > Image) { if (*p==transparent_pixel) *p = 0; else if (!*p) *p = transparent_pixel; } uchar t; t = CMap.Red[0]; CMap.Red[0] = CMap.Red[transparent_pixel]; CMap.Red[transparent_pixel] = t; t = CMap.Green[0]; CMap.Green[0] = CMap.Green[transparent_pixel]; CMap.Green[transparent_pixel] = t; t = CMap.Blue[0]; CMap.Blue[0] = CMap.Blue[transparent_pixel]; CMap.Blue[transparent_pixel] = t; } // find out what colors are actually used: uchar used[256]; uchar remap[256]; int i; for (i = 0; i < ColorMapSize; i++) used[i] = 0; uchar *p = Image+Width*Height; while (p-- > Image) used[*p] = 1; // remap them to start with printing characters: int base = transparent_pixel >= 0 && used[0] ? ' ' : ' '+1; int numcolors = 0; for (i = 0; i < ColorMapSize; i++) if (used[i]) { remap[i] = (uchar)(base++); numcolors++; } // write the first line of xpm data (use suffix as temp array): uchar Suffix[4096]; int length = snprintf((char*)(Suffix), sizeof(Suffix), "%d %d %d %d",Width,Height,-numcolors,1); new_data[0] = new char[length+1]; strcpy(new_data[0], (char*)Suffix); // write the colormap new_data[1] = (char*)(p = new uchar[4*numcolors]); for (i = 0; i < ColorMapSize; i++) if (used[i]) { *p++ = remap[i]; *p++ = CMap.Red[i]; *p++ = CMap.Green[i]; *p++ = CMap.Blue[i]; } // remap the image data: p = Image+Width*Height; while (p-- > Image) *p = remap[*p]; // split the image data into lines: for (i=0; i'9' || b[5]!= 'a') Fl::warning("%s is version %c%c%c.",rdr.name(),b[3],b[4],b[5]); } int ScreenWidth = rdr.read_word(); int ScreenHeight = rdr.read_word(); int Width = ScreenWidth; int Height = ScreenHeight; uchar ch = rdr.read_byte(); CHECK_ERROR char HasColormap = ((ch & 0x80) != 0); HasGlobalColorTable = HasColormap; memset(GlobalColorTable, 0, sizeof(GlobalColorTable)); int BitsPerPixel = (ch & 7) + 1; int ColorMapSize = HasColormap ? 2 << (ch & 7) : 0; // int OriginalResolution = ((ch>>4)&7)+1; // int SortedTable = (ch&8)!=0; background_color_index = rdr.read_byte(); // Background Color index ch = rdr.read_byte(); // Aspect ratio is N/64 CHECK_ERROR // Read in global colormap: uchar transparent_pixel = 0; char has_transparent = 0; char user_input = 0; int delay = 0; int dispose = 0; int XPos = 0; int YPos = 0; struct ColorMap CMap; /* color map */ if (HasColormap) { for (int i=0; i < ColorMapSize; i++) { CMap.Red[i] = rdr.read_byte(); CMap.Green[i] = rdr.read_byte(); CMap.Blue[i] = rdr.read_byte(); // store away for reading of further images in file (Fl_Anim_GIF_Image) // because the values are changed during processing. GlobalColorTable[i].r = CMap.Red[i]; GlobalColorTable[i].g = CMap.Green[i]; GlobalColorTable[i].b = CMap.Blue[i]; } } CHECK_ERROR char Interlace = 0; // Main parser loop: parse "blocks" until an image is found or error for (;;) { int i = rdr.read_byte(); CHECK_ERROR int blocklen = 0; if (i == 0x21) { // a "gif extension" ch = rdr.read_byte(); // extension type blocklen = rdr.read_byte(); CHECK_ERROR if (ch == 0xF9 && blocklen == 4) { // Graphic Control Extension // printf("Graphic Control Extension at offset %ld\n", rdr.tell()-2); uchar bits = rdr.read_byte(); // Packed Fields xxxDDDUT dispose = (bits >> 2) & 7; delay = rdr.read_word(); // Delay Time transparent_pixel = rdr.read_byte(); // Transparent Color Index blocklen = rdr.read_byte(); // Block Terminator (must be zero) CHECK_ERROR has_transparent = (bits & 1) ? 1 : 0; user_input = (bits & 2) ? 1 : 0; } else if (ch == 0xFF) { // Application Extension // printf("Application Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen); uchar buf[512]; memset(buf, 0, sizeof(buf)); for (i=0; i 8) { // though invalid, other decoders accept an use it Fl::warning("Fl_GIF_Image: %s invalid LZW-initial code size %d.\n", rdr.name(), CodeSize); } CodeSize++; // Fix images w/o color table. The standard allows this and lets the // decoder choose a default color table. The standard recommends the // first two color table entries should be black and white. if (ColorMapSize == 0) { // no global and no local color table Fl::warning("%s does not have a color table, using default.\n", rdr.name()); BitsPerPixel = CodeSize - 1; ColorMapSize = 1 << BitsPerPixel; CMap.Red[0] = CMap.Green[0] = CMap.Blue[0] = 0; // black CMap.Red[1] = CMap.Green[1] = CMap.Blue[1] = 255; // white for (int i = 2; i < ColorMapSize; i++) { CMap.Red[i] = CMap.Green[i] = CMap.Blue[i] = (uchar)(255 * i / (ColorMapSize - 1)); } } // Workaround for broken GIF files... BitsPerPixel = CodeSize - 1; if (1 << BitsPerPixel <= 256) ColorMapSize = 1 << BitsPerPixel; // Fix transparent pixel index outside ColorMap (Issue #271) if (has_transparent && transparent_pixel >= ColorMapSize) { for (int k = ColorMapSize; k <= transparent_pixel; k++) CMap.Red[k] = CMap.Green[k] = CMap.Blue[k] = 0xff; // white (color is irrelevant) ColorMapSize = transparent_pixel + 1; } #if (0) // TEST/DEBUG: fill color table to maximum size for (int i = ColorMapSize; i < 256; i++) { CMap.Red[i] = CMap.Green[i] = CMap.Blue[i] = 0; // black } #endif CHECK_ERROR // now read the LZW compressed image data Image = new uchar[Width*Height]; lzw_decode(rdr, Image, Width, Height, CodeSize, ColorMapSize, Interlace); if (ld()) return; // CHECK_ERROR aborted already // Notify derived class on loaded image data GIF_FRAME gf(frame, ScreenWidth, ScreenHeight, XPos, YPos, Width, Height, Image); gf.disposal(dispose, user_input ? -delay - 1 : delay); gf.colors(ColorMapSize, background_color_index, has_transparent ? transparent_pixel : -1); GIF_FRAME::CPAL cpal[256] = { { 0 } }; if (HasLocalColorTable) gf.cpal = LocalColorTable; else if (HasGlobalColorTable) gf.cpal = GlobalColorTable; else { for (i=0; i < ColorMapSize; i++) { cpal[i].r = CMap.Red[i]; cpal[i].g = CMap.Green[i]; cpal[i].b = CMap.Blue[i]; } gf.cpal = cpal; } #if (0) // TEST/DEBUG: output palette values printf("palette:\n"); for (i=0; i ScreenWidth) xmax = ScreenWidth; int ymax = YPos + Height; if (ymax > ScreenHeight) ymax = ScreenHeight; for (int y = ystart; y 0) { rdr.skip(blocklen); blocklen = rdr.read_byte(); } // printf("End of data (sub)blocks at offset %ld\n", rdr.tell()); } } // load_gif_() /** The protected load() methods are used by Fl_Anim_GIF_Image to request loading of animated GIF's. */ void Fl_GIF_Image::load(const char* filename, bool anim) { Fl_Image_Reader rdr; if (rdr.open(filename) == -1) { Fl::error("Fl_GIF_Image: Unable to open %s!", filename); ld(ERR_FILE_ACCESS); } else { load_gif_(rdr, anim); } } void Fl_GIF_Image::load(const char *imagename, const unsigned char *data, const size_t len, bool anim) { Fl_Image_Reader rdr; if (rdr.open(imagename, data, len) == -1) { ld(ERR_FILE_ACCESS); } else { load_gif_(rdr, anim); } } fltk-1.4.3/src/fl_scroll_area.cxx0000644000175000017500000000572415004135251017077 0ustar albrechtalbrecht// // Scrolling routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Drawing function to move the contents of a rectangle. This is passed // a "callback" which is called to draw rectangular areas that are moved // into the drawing area. #include "Fl_Window_Driver.H" #include // scroll a rectangle and redraw the newly exposed portions: /** Scroll a rectangle and draw the newly exposed portions. \param[in] X,Y position of top-left of rectangle \param[in] W,H size of rectangle \param[in] dx,dy pixel offsets for shifting rectangle \param[in] draw_area callback function to draw rectangular areas \param[in] data pointer to user data for callback The contents of the rectangular area is first shifted by \p dx and \p dy pixels. The \p draw_area callback is then called for every newly exposed rectangular area. \warning With FLTK 1.4 and above, it's recommended to put graphical elements in an Fl_Scroll widget rather than use function fl_scroll() to update those elements. That's because fl_scroll() may not produce a pixel-accurate result when the GUI scaling factor value is not a multiple of 100%. Alternatively, use fl_scroll() when the scaling factor value is a multiple of 100% and perform a full redraw of the graphical elements otherwise. Statement float s = Fl::screen_scale(win->screen_num()); gives the current scaling factor value given Fl_Window *win. */ void fl_scroll(int X, int Y, int W, int H, int dx, int dy, void (*draw_area)(void*, int,int,int,int), void* data) { if (!dx && !dy) return; if (dx <= -W || dx >= W || dy <= -H || dy >= H) { // no intersection of old an new scroll draw_area(data,X,Y,W,H); return; } int src_x, src_w, dest_x, clip_x, clip_w; if (dx > 0) { src_x = X; dest_x = X+dx; src_w = W-dx; clip_x = X; clip_w = dx; } else { src_x = X-dx; dest_x = X; src_w = W+dx; clip_x = X+src_w; clip_w = W-src_w; } int src_y, src_h, dest_y, clip_y, clip_h; if (dy > 0) { src_y = Y; dest_y = Y+dy; src_h = H-dy; clip_y = Y; clip_h = dy; } else { src_y = Y-dy; dest_y = Y; src_h = H+dy; clip_y = Y+src_h; clip_h = H-src_h; } int retval = Fl_Window_Driver::driver(Fl_Window::current())->scroll(src_x, src_y, src_w, src_h, dest_x, dest_y, draw_area, data); if (retval) { draw_area(data,X,Y,W,H); return; } if (dx) draw_area(data, clip_x, dest_y, clip_w, src_h); if (dy) draw_area(data, X, clip_y, W, clip_h); } fltk-1.4.3/src/Fl_get_system_colors.cxx0000644000175000017500000003327415004135251020316 0ustar albrechtalbrecht// // System color support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \file Fl_get_system_colors.cxx \brief System color support */ #include #include "Fl_Screen_Driver.H" #include "Fl_System_Driver.H" #include #include #include #include #include #include "flstring.h" #include #include #include #include #include "tile.xpm" /** Changes fl_color(FL_BACKGROUND_COLOR) to the given color, and changes the gray ramp from 32 to 56 to black to white. These are the colors used as backgrounds by almost all widgets and used to draw the edges of all the boxtypes. */ void Fl::background(uchar r, uchar g, uchar b) { Fl_Screen_Driver::bg_set = 1; // replace the gray ramp so that FL_GRAY is this color if (!r) r = 1; else if (r==255) r = 254; double powr = log(r/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); if (!g) g = 1; else if (g==255) g = 254; double powg = log(g/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); if (!b) b = 1; else if (b==255) b = 254; double powb = log(b/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); for (int i = 0; i < FL_NUM_GRAY; i++) { double gray = i/(FL_NUM_GRAY-1.0); Fl::set_color(fl_gray_ramp(i), uchar(pow(gray,powr)*255+.5), uchar(pow(gray,powg)*255+.5), uchar(pow(gray,powb)*255+.5)); } } /** Changes fl_color(FL_FOREGROUND_COLOR). */ void Fl::foreground(uchar r, uchar g, uchar b) { Fl_Screen_Driver::fg_set = 1; Fl::set_color(FL_FOREGROUND_COLOR,r,g,b); } /** Changes the alternative background color. This color is used as a background by Fl_Input and other text widgets.

This call may change fl_color(FL_FOREGROUND_COLOR) if it does not provide sufficient contrast to FL_BACKGROUND2_COLOR. */ void Fl::background2(uchar r, uchar g, uchar b) { Fl_Screen_Driver::bg2_set = 1; Fl::set_color(FL_BACKGROUND2_COLOR,r,g,b); Fl::set_color(FL_FOREGROUND_COLOR, get_color(fl_contrast(FL_FOREGROUND_COLOR,FL_BACKGROUND2_COLOR))); } // these are set by Fl::args() and override any system colors: const char *fl_fg = NULL; const char *fl_bg = NULL; const char *fl_bg2 = NULL; /** Parse a string containing a description of a color and write r, g, and b. This call is used by the Pixmap file format interpreter and by the command line arguments parser to set UI colors. RGB color triplets usually start with a '#' character, but it can be omitted if it does not conflict with the later rules. Color components are defined in hexadecimal notation with 1, 2, 3, or four hex digits per component, making color triplets 3, 6, 9, or 12 characters long. The interpreter is case insensitive. Valid code examples include "FF0000" for red, "#0F0" for green, and "000000004444" for a dark blue. On the X11 platform, color values can also be given a color name like "red". The list of accepted color names is provided by the X11 server. If none of the color interpretations work, \ref fl_parse_color returns 0. The Pixmap reader interprets those as transparent, and are usually written as "None", "#transparent", or "bg". \param[in] p a C-string describing the color \param[out] r, g, b the color components in the 0...255 range \return 0 if the color cannot be interpreted, 1 otherwise */ int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b) { return Fl::screen_driver()->parse_color(p, r, g, b); } /** \fn Fl::get_system_colors() Read the user preference colors from the system and use them to call Fl::foreground(), Fl::background(), and Fl::background2(). This is done by Fl_Window::show(argc,argv) before applying the -fg and -bg switches. On X this reads some common values from the Xdefaults database. KDE users can set these values by running the "krdb" program, and newer versions of KDE set this automatically if you check the "apply style to other X programs" switch in their control panel. */ void Fl::get_system_colors() { Fl::screen_driver()->get_system_colors(); } //// Simple implementation of 2.0 Fl::scheme() interface... #define D1 BORDER_WIDTH #define D2 (BORDER_WIDTH+BORDER_WIDTH) extern void fl_up_box(int, int, int, int, Fl_Color); extern void fl_down_box(int, int, int, int, Fl_Color); extern void fl_thin_up_box(int, int, int, int, Fl_Color); extern void fl_thin_down_box(int, int, int, int, Fl_Color); extern void fl_round_up_box(int, int, int, int, Fl_Color); extern void fl_round_down_box(int, int, int, int, Fl_Color); extern void fl_round_focus(Fl_Boxtype, int, int, int, int, Fl_Color, Fl_Color); extern void fl_up_frame(int, int, int, int, Fl_Color); extern void fl_down_frame(int, int, int, int, Fl_Color); extern void fl_thin_up_frame(int, int, int, int, Fl_Color); extern void fl_thin_down_frame(int, int, int, int, Fl_Color); #ifndef FL_DOXYGEN const char *Fl::scheme_ = (const char *)0; // current scheme Fl_Image *Fl::scheme_bg_ = (Fl_Image *)0; // current background image for the scheme #endif static Fl_Pixmap tile(tile_xpm); /** Sets the current widget scheme. NULL will use the scheme defined in the FLTK_SCHEME environment variable or the scheme resource under X11. Otherwise, any of the following schemes can be used: - "none" - This is the default look-n-feel which resembles old Windows (95/98/Me/NT/2000) and old GTK/KDE - "base" - This is an alias for "none" - "plastic" - This scheme is inspired by the Aqua user interface on macOS - "gtk+" - This scheme is inspired by the Red Hat Bluecurve theme - "gleam" - This scheme is inspired by the Clearlooks Glossy scheme. (Colin Jones and Edmanuel Torres). - "oxy" - This is a subset of Dmitrij K's oxy scheme (STR 2675, 3477) If the given scheme name is unknown, the default scheme will be used. Setting the scheme (name) is case insensitive, but the stored scheme name will always be lowercase and Fl::scheme() will return this lowercase name or \p NULL if no scheme or the default scheme ("none" or "base") was set. \param[in] s Scheme name of NULL \retval 0 if the scheme has not been set or is the default scheme \retval 1 if a scheme other than "none"/"base" was set \see Fl::scheme() to get the name of the current scheme \see Fl::is_scheme(const char*) to test if the specified scheme is set */ int Fl::scheme(const char *s) { if (!s) { s = screen_driver()->get_system_scheme(); } if (s) { if (!fl_ascii_strcasecmp(s, "none") || !fl_ascii_strcasecmp(s, "base") || !*s) s = NULL; else if (!fl_ascii_strcasecmp(s, "gtk+")) s = fl_strdup("gtk+"); else if (!fl_ascii_strcasecmp(s, "plastic")) s = fl_strdup("plastic"); else if (!fl_ascii_strcasecmp(s, "gleam")) s = fl_strdup("gleam"); else if (!fl_ascii_strcasecmp(s, "oxy")) s = fl_strdup("oxy"); else s = NULL; } if (scheme_) free((void*)scheme_); scheme_ = s; // Save the new scheme in the FLTK_SCHEME env var so that child processes // inherit it... static char e[1024]; strcpy(e, "FLTK_SCHEME="); if (s) strlcat(e, s, sizeof(e)); Fl::system_driver()->putenv(e); // Load the scheme... reload_scheme(); return (s != NULL); } /** Called internally when setting a new scheme according to scheme name. Loads or reloads the current scheme selection. \return Always 1 (this may change in the future) See void Fl::scheme(const char *name) \internal \note Internal: Should this method be private? */ int Fl::reload_scheme() { Fl_Window *win; if (scheme_ && !fl_ascii_strcasecmp(scheme_, "plastic")) { // Update the tile image to match the background color... uchar r, g, b; int nr, ng, nb; int i; // static uchar levels[3] = { 0xff, 0xef, 0xe8 }; // OSX 10.3 and higher use a background with less contrast... static uchar levels[3] = { 0xff, 0xf8, 0xf4 }; get_color(FL_GRAY, r, g, b); // printf("FL_GRAY = 0x%02x 0x%02x 0x%02x\n", r, g, b); for (i = 0; i < 3; i ++) { nr = levels[i] * r / 0xe8; if (nr > 255) nr = 255; ng = levels[i] * g / 0xe8; if (ng > 255) ng = 255; nb = levels[i] * b / 0xe8; if (nb > 255) nb = 255; snprintf(tile_cmap[i], sizeof(tile_cmap[0]), "%c c #%02x%02x%02x", "Oo."[i], nr, ng, nb); // puts(tile_cmap[i]); } tile.uncache(); if (!scheme_bg_) scheme_bg_ = new Fl_Tiled_Image(&tile, 0, 0); // Load plastic buttons, etc... set_boxtype(FL_UP_FRAME, FL_PLASTIC_UP_FRAME); set_boxtype(FL_DOWN_FRAME, FL_PLASTIC_DOWN_FRAME); set_boxtype(FL_THIN_UP_FRAME, FL_PLASTIC_UP_FRAME); set_boxtype(FL_THIN_DOWN_FRAME, FL_PLASTIC_DOWN_FRAME); set_boxtype(FL_UP_BOX, FL_PLASTIC_UP_BOX); set_boxtype(FL_DOWN_BOX, FL_PLASTIC_DOWN_BOX); set_boxtype(FL_THIN_UP_BOX, FL_PLASTIC_THIN_UP_BOX); set_boxtype(FL_THIN_DOWN_BOX, FL_PLASTIC_THIN_DOWN_BOX); set_boxtype(_FL_ROUND_UP_BOX, FL_PLASTIC_ROUND_UP_BOX); set_boxtype(_FL_ROUND_DOWN_BOX, FL_PLASTIC_ROUND_DOWN_BOX); // Use standard size scrollbars... Fl::scrollbar_size(16); } else if (scheme_ && !fl_ascii_strcasecmp(scheme_, "gtk+")) { // Use a GTK+ inspired look-n-feel... if (scheme_bg_) { delete scheme_bg_; scheme_bg_ = (Fl_Image *)0; } set_boxtype(FL_UP_FRAME, FL_GTK_UP_FRAME); set_boxtype(FL_DOWN_FRAME, FL_GTK_DOWN_FRAME); set_boxtype(FL_THIN_UP_FRAME, FL_GTK_THIN_UP_FRAME); set_boxtype(FL_THIN_DOWN_FRAME, FL_GTK_THIN_DOWN_FRAME); set_boxtype(FL_UP_BOX, FL_GTK_UP_BOX); set_boxtype(FL_DOWN_BOX, FL_GTK_DOWN_BOX); set_boxtype(FL_THIN_UP_BOX, FL_GTK_THIN_UP_BOX); set_boxtype(FL_THIN_DOWN_BOX, FL_GTK_THIN_DOWN_BOX); set_boxtype(_FL_ROUND_UP_BOX, FL_GTK_ROUND_UP_BOX); set_boxtype(_FL_ROUND_DOWN_BOX, FL_GTK_ROUND_DOWN_BOX); // Use slightly thinner scrollbars... Fl::scrollbar_size(15); } else if (scheme_ && !fl_ascii_strcasecmp(scheme_, "gleam")) { // Use a GTK+ inspired look-n-feel... if (scheme_bg_) { delete scheme_bg_; scheme_bg_ = (Fl_Image *)0; } set_boxtype(FL_UP_FRAME, FL_GLEAM_UP_FRAME); set_boxtype(FL_DOWN_FRAME, FL_GLEAM_DOWN_FRAME); set_boxtype(FL_THIN_UP_FRAME, FL_GLEAM_UP_FRAME); set_boxtype(FL_THIN_DOWN_FRAME, FL_GLEAM_DOWN_FRAME); set_boxtype(FL_UP_BOX, FL_GLEAM_UP_BOX); set_boxtype(FL_DOWN_BOX, FL_GLEAM_DOWN_BOX); set_boxtype(FL_THIN_UP_BOX, FL_GLEAM_THIN_UP_BOX); set_boxtype(FL_THIN_DOWN_BOX, FL_GLEAM_THIN_DOWN_BOX); set_boxtype(_FL_ROUND_UP_BOX, FL_GLEAM_ROUND_UP_BOX); set_boxtype(_FL_ROUND_DOWN_BOX, FL_GLEAM_ROUND_DOWN_BOX); // Use slightly thinner scrollbars... Fl::scrollbar_size(15); } else if (scheme_ && !fl_ascii_strcasecmp(scheme_, "oxy")) { // Oxy scheme if (scheme_bg_) { delete scheme_bg_; scheme_bg_ = (Fl_Image *)0; } set_boxtype(FL_UP_FRAME, FL_OXY_UP_FRAME); set_boxtype(FL_DOWN_FRAME, FL_OXY_DOWN_FRAME); set_boxtype(FL_THIN_UP_FRAME, FL_OXY_THIN_UP_FRAME); set_boxtype(FL_THIN_DOWN_FRAME, FL_OXY_THIN_DOWN_FRAME); set_boxtype(FL_UP_BOX, FL_OXY_UP_BOX); set_boxtype(FL_DOWN_BOX, FL_OXY_DOWN_BOX); set_boxtype(FL_THIN_UP_BOX, FL_OXY_THIN_UP_BOX); set_boxtype(FL_THIN_DOWN_BOX, FL_OXY_THIN_DOWN_BOX); set_boxtype(_FL_ROUND_UP_BOX, FL_OXY_ROUND_UP_BOX); set_boxtype(_FL_ROUND_DOWN_BOX, FL_OXY_ROUND_DOWN_BOX); // Use slightly thinner scrollbars... Fl::scrollbar_size(15); } else { // Use the standard FLTK look-n-feel... if (scheme_bg_) { delete scheme_bg_; scheme_bg_ = (Fl_Image *)0; } set_boxtype(FL_UP_FRAME, fl_up_frame, D1, D1, D2, D2); set_boxtype(FL_DOWN_FRAME, fl_down_frame, D1, D1, D2, D2); set_boxtype(FL_THIN_UP_FRAME, fl_thin_up_frame, 1, 1, 2, 2); set_boxtype(FL_THIN_DOWN_FRAME, fl_thin_down_frame, 1, 1, 2, 2); set_boxtype(FL_UP_BOX, fl_up_box, D1, D1, D2, D2); set_boxtype(FL_DOWN_BOX, fl_down_box, D1, D1, D2, D2); set_boxtype(FL_THIN_UP_BOX, fl_thin_up_box, 1, 1, 2, 2); set_boxtype(FL_THIN_DOWN_BOX, fl_thin_down_box, 1, 1, 2, 2); set_boxtype(_FL_ROUND_UP_BOX, fl_round_up_box, 3, 3, 6, 6, fl_round_focus); set_boxtype(_FL_ROUND_DOWN_BOX, fl_round_down_box, 3, 3, 6, 6, fl_round_focus); // Use standard size scrollbars... Fl::scrollbar_size(16); } // Set (or clear) the background tile for all windows... // FIXME: This makes it impossible to assign a background image // and/or a label to a window. IMHO we should be able to assign a // background image to a window. Currently (as of FLTK 1.3.3) there // is the workaround to use a group inside the window to achieve this. // See also STR #3075. // AlbrechtS, 01 Mar 2015 // // If there is already an image assigned that is not the scheme_bg_, // then don't change the labeltype or assign another image. Will that // fix it? for (win = first_window(); win; win = next_window(win)) { win->labeltype(scheme_bg_ ? FL_NORMAL_LABEL : FL_NO_LABEL); win->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); win->image(scheme_bg_); win->redraw(); } return 1; } fltk-1.4.3/src/Fl_File_Icon2.cxx0000644000175000017500000007411115004135251016456 0ustar albrechtalbrecht// // Fl_File_Icon system icon routines. // // KDE icon code donated by Maarten De Boer. // // Copyright 1999-2010 by Michael Sweet. // Copyright 2011-2019 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Contents: // // Fl_File_Icon::load() - Load an icon file... // Fl_File_Icon::load_fti() - Load an SGI-format FTI file... // Fl_File_Icon::load_image() - Load an image icon file... // Fl_File_Icon::load_system_icons() - Load the standard system icons/filetypes. // load_kde_icons() - Load KDE icon files. // load_kde_mimelnk() - Load a KDE "mimelnk" file. // kde_to_fltk_pattern() - Convert a KDE pattern to a FLTK pattern. // get_kde_val() - Get a KDE value. // // // Include necessary header files... // #include #include #include #include "flstring.h" #include #include #include #include #include #include #include #include #ifndef F_OK # define F_OK 0 #endif // // Local functions... // static void load_kde_icons(const char *directory, const char *icondir); static void load_kde_mimelnk(const char *filename, const char *icondir); static char *kde_to_fltk_pattern(const char *kdepattern); static char *get_kde_val(char *str, const char *key); // // Local globals... // static const char *kdedir = NULL; /** Loads the specified icon image. The format is deduced from the filename. \param[in] f filename */ void Fl_File_Icon::load(const char *f) // I - File to read from { int i; // Load status... const char *ext; // File extension ext = fl_filename_ext(f); if (ext && strcmp(ext, ".fti") == 0) i = load_fti(f); else i = load_image(f); if (i) { Fl::warning("Fl_File_Icon::load(): Unable to load icon file \"%s\".", f); return; } } /** Loads an SGI icon file. \param[in] fti icon filename \return 0 on success, non-zero on error */ int // O - 0 on success, non-zero on error Fl_File_Icon::load_fti(const char *fti) // I - File to read from { FILE *fp; // File pointer int ch; // Current character char command[255], // Command string ("vertex", etc.) params[255], // Parameter string ("10.0,20.0", etc.) *ptr; // Pointer into strings int outline; // Outline polygon // Try to open the file... if ((fp = fl_fopen(fti, "rb")) == NULL) { Fl::error("Fl_File_Icon::load_fti(): Unable to open \"%s\" - %s", fti, strerror(errno)); return -1; } // Read the entire file, adding data as needed... outline = 0; while ((ch = getc(fp)) != EOF) { // Skip whitespace if (isspace(ch)) continue; // Skip comments starting with "#"... if (ch == '#') { while ((ch = getc(fp)) != EOF) if (ch == '\n') break; if (ch == EOF) break; else continue; } // OK, this character better be a letter... if (!isalpha(ch)) { Fl::error("Fl_File_Icon::load_fti(): Expected a letter at file position %ld (saw '%c')", ftell(fp) - 1, ch); break; } // Scan the command name... ptr = command; *ptr++ = ch; while ((ch = getc(fp)) != EOF) { if (ch == '(') break; else if (ptr < (command + sizeof(command) - 1)) *ptr++ = ch; } *ptr++ = '\0'; // Make sure we stopped on a parenthesis... if (ch != '(') { Fl::error("Fl_File_Icon::load_fti(): Expected a ( at file position %ld (saw '%c')", ftell(fp) - 1, ch); break; } // Scan the parameters... ptr = params; while ((ch = getc(fp)) != EOF) { if (ch == ')') break; else if (ptr < (params + sizeof(params) - 1)) *ptr++ = ch; } *ptr++ = '\0'; // Make sure we stopped on a parenthesis... if (ch != ')') { Fl::error("Fl_File_Icon::load_fti(): Expected a ) at file position %ld (saw '%c')", ftell(fp) - 1, ch); break; } // Make sure the next character is a semicolon... if ((ch = getc(fp)) != ';') { Fl::error("Fl_File_Icon::load_fti(): Expected a ; at file position %ld (saw '%c')", ftell(fp) - 1, ch); break; } // Now process the command... if (strcmp(command, "color") == 0) { // Set the color; for negative colors blend the two primaries to // produce a composite color. Also, the following symbolic color // names are understood: // // name FLTK color // ------------- ---------- // iconcolor FL_ICON_COLOR; mapped to the icon color in // Fl_File_Icon::draw() // shadowcolor FL_DARK3 // outlinecolor FL_BLACK if (strcmp(params, "iconcolor") == 0) add_color(FL_ICON_COLOR); else if (strcmp(params, "shadowcolor") == 0) add_color(FL_DARK3); else if (strcmp(params, "outlinecolor") == 0) add_color(FL_BLACK); else { int c = atoi(params); // Color value if (c < 0) { // Composite color; compute average... c = -c; add_color(fl_color_average((Fl_Color)(c >> 4), (Fl_Color)(c & 15), 0.5f)); } else add_color((Fl_Color)c); } } else if (strcmp(command, "bgnline") == 0) add(LINE); else if (strcmp(command, "bgnclosedline") == 0) add(CLOSEDLINE); else if (strcmp(command, "bgnpolygon") == 0) add(POLYGON); else if (strcmp(command, "bgnoutlinepolygon") == 0) { add(OUTLINEPOLYGON); outline = int(add(0) - data_); add(0); } else if (strcmp(command, "endoutlinepolygon") == 0 && outline) { unsigned cval; // Color value // Set the outline color; see above for valid values... if (strcmp(params, "iconcolor") == 0) cval = FL_ICON_COLOR; else if (strcmp(params, "shadowcolor") == 0) cval = FL_DARK3; else if (strcmp(params, "outlinecolor") == 0) cval = FL_BLACK; else { int c = atoi(params); // Color value if (c < 0) { // Composite color; compute average... c = -c; cval = fl_color_average((Fl_Color)(c >> 4), (Fl_Color)(c & 15), 0.5f); } else cval = c; } // Store outline color... data_[outline] = cval >> 16; data_[outline + 1] = cval; outline = 0; add(END); } else if (strncmp(command, "end", 3) == 0) add(END); else if (strcmp(command, "vertex") == 0) { float x, y; // Coordinates of vertex if (sscanf(params, "%f,%f", &x, &y) != 2) break; add_vertex((short)(int)rint(x * 100.0), (short)(int)rint(y * 100.0)); } else { Fl::error("Fl_File_Icon::load_fti(): Unknown command \"%s\" at file position %ld.", command, ftell(fp) - 1); break; } } // Close the file and return... fclose(fp); #ifdef DEBUG printf("Icon File \"%s\":\n", fti); for (int i = 0; i < num_data_; i ++) printf(" %d,\n", data_[i]); #endif /* DEBUG */ return 0; } /** Load an image icon file from an image filename. \param[in] ifile image filename \return 0 on success, non-zero on error */ int Fl_File_Icon::load_image(const char *ifile) // I - File to read from { Fl_Shared_Image *img; // Image file img = Fl_Shared_Image::get(ifile); if (!img || !img->count() || !img->w() || !img->h()) return -1; if (img->count() == 1) { int x, y; // X & Y in image int startx; // Starting X coord Fl_Color c, // Current color temp; // Temporary color const uchar *row; // Pointer into image const int extra_data = img->ld() ? (img->ld()-img->w()*img->d()) : 0; // Loop through grayscale or RGB image... for (y = 0, row = (const uchar *)(*(img->data())); y < img->h(); y ++, row += extra_data) { for (x = 0, startx = 0, c = (Fl_Color)-1; x < img->w(); x ++, row += img->d()) { switch (img->d()) { case 1 : temp = fl_rgb_color(row[0], row[0], row[0]); break; case 2 : if (row[1] > 127) temp = fl_rgb_color(row[0], row[0], row[0]); else temp = (Fl_Color)-1; break; case 3 : temp = fl_rgb_color(row[0], row[1], row[2]); break; default : if (row[3] > 127) temp = fl_rgb_color(row[0], row[1], row[2]); else temp = (Fl_Color)-1; break; } if (temp != c) { if (x > startx && c != (Fl_Color)-1) { add_color(c); add(POLYGON); add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); add(END); } c = temp; startx = x; } } if (x > startx && c != (Fl_Color)-1) { add_color(c); add(POLYGON); add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); add(END); } } } else { int i, j; // Looping vars int ch; // Current character int newch; // New character int bg; // Background color char val[16]; // Color value const char *lineptr, // Pointer into line *const*ptr; // Pointer into data array int ncolors, // Number of colors chars_per_color; // Characters per color Fl_Color *colors; // Colors int red, green, blue; // Red, green, and blue values int x, y; // X & Y in image int startx; // Starting X coord // Get the pixmap data... ptr = img->data(); sscanf(*ptr, "%*d%*d%d%d", &ncolors, &chars_per_color); colors = new Fl_Color[int(1 << (chars_per_color * 8))]; // Read the colormap... memset(colors, 0, sizeof(Fl_Color) << (chars_per_color * 8)); bg = ' '; ptr ++; if (ncolors < 0) { // Read compressed colormap... const uchar *cmapptr; ncolors = -ncolors; for (i = 0, cmapptr = (const uchar *)*ptr; i < ncolors; i ++, cmapptr += 4) colors[cmapptr[0]] = fl_rgb_color(cmapptr[1], cmapptr[2], cmapptr[3]); ptr ++; } else { for (i = 0; i < ncolors; i ++, ptr ++) { // Get the color's character lineptr = *ptr; ch = *lineptr++; if (chars_per_color > 1) ch = (ch << 8) | *lineptr++; // Get the color value... if ((lineptr = strstr(lineptr, "c ")) == NULL) { // No color; make this black... colors[ch] = FL_BLACK; } else if (lineptr[2] == '#') { // Read the RGB triplet... lineptr += 3; for (j = 0; j < 12; j ++) if (!isxdigit(lineptr[j])) break; switch (j) { case 0 : bg = ch; default : red = green = blue = 0; break; case 3 : val[0] = lineptr[0]; val[1] = '\0'; red = 255 * (int)strtol(val, NULL, 16) / 15; val[0] = lineptr[1]; val[1] = '\0'; green = 255 * (int)strtol(val, NULL, 16) / 15; val[0] = lineptr[2]; val[1] = '\0'; blue = 255 * (int)strtol(val, NULL, 16) / 15; break; case 6 : case 9 : case 12 : j /= 3; val[0] = lineptr[0]; val[1] = lineptr[1]; val[2] = '\0'; red = (int)strtol(val, NULL, 16); val[0] = lineptr[j + 0]; val[1] = lineptr[j + 1]; val[2] = '\0'; green = (int)strtol(val, NULL, 16); val[0] = lineptr[2 * j + 0]; val[1] = lineptr[2 * j + 1]; val[2] = '\0'; blue = (int)strtol(val, NULL, 16); break; } colors[ch] = fl_rgb_color((uchar)red, (uchar)green, (uchar)blue); } else { // Read a color name... if (strncasecmp(lineptr + 2, "white", 5) == 0) colors[ch] = FL_WHITE; else if (strncasecmp(lineptr + 2, "black", 5) == 0) colors[ch] = FL_BLACK; else if (strncasecmp(lineptr + 2, "none", 4) == 0) { colors[ch] = FL_BLACK; bg = ch; } else colors[ch] = FL_GRAY; } } } // Read the image data... for (y = 0; y < img->h(); y ++, ptr ++) { lineptr = *ptr; startx = 0; ch = bg; for (x = 0; x < img->w(); x ++) { newch = *lineptr++; if (chars_per_color > 1) newch = (newch << 8) | *lineptr++; if (newch != ch) { if (ch != bg) { add_color(colors[ch]); add(POLYGON); add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); add(END); } ch = newch; startx = x; } } if (ch != bg) { add_color(colors[ch]); add(POLYGON); add_vertex(startx * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); add_vertex(x * 9000 / img->w() + 1000, 9500 - y * 9000 / img->h()); add_vertex(x * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); add_vertex(startx * 9000 / img->w() + 1000, 9500 - (y + 1) * 9000 / img->h()); add(END); } } // Free the colormap... delete[] colors; } img->release(); #ifdef DEBUG { int i; printf("Icon File \"%s\":\n", ifile); for (i = 0; i < num_data_; i ++) { printf(" %d,\n", data_[i]); } } #endif // DEBUG return 0; } /** Loads all system-defined icons. This call is useful when using the FileChooser widget and should be used when the application starts: \code Fl_File_Icon::load_system_icons(); \endcode */ void Fl_File_Icon::load_system_icons(void) { int i; // Looping var Fl_File_Icon *icon; // New icons char filename[FL_PATH_MAX + 60]; // Filename char icondir[FL_PATH_MAX]; // Icon directory static int init = 0; // Have the icons been initialized? const char * const icondirs[] = { "Bluecurve", // Icon directories to look for, in order "crystalsvg", "default.kde", "hicolor", NULL }; static short plain[] = { // Plain file icon COLOR, -1, -1, OUTLINEPOLYGON, 0, FL_GRAY, VERTEX, 2000, 1000, VERTEX, 2000, 9000, VERTEX, 6000, 9000, VERTEX, 8000, 7000, VERTEX, 8000, 1000, END, OUTLINEPOLYGON, 0, FL_GRAY, VERTEX, 6000, 9000, VERTEX, 6000, 7000, VERTEX, 8000, 7000, END, COLOR, 0, FL_BLACK, LINE, VERTEX, 6000, 7000, VERTEX, 8000, 7000, VERTEX, 8000, 1000, VERTEX, 2000, 1000, END, LINE, VERTEX, 3000, 7000, VERTEX, 5000, 7000, END, LINE, VERTEX, 3000, 6000, VERTEX, 5000, 6000, END, LINE, VERTEX, 3000, 5000, VERTEX, 7000, 5000, END, LINE, VERTEX, 3000, 4000, VERTEX, 7000, 4000, END, LINE, VERTEX, 3000, 3000, VERTEX, 7000, 3000, END, LINE, VERTEX, 3000, 2000, VERTEX, 7000, 2000, END, END }; static short image[] = { // Image file icon COLOR, -1, -1, OUTLINEPOLYGON, 0, FL_GRAY, VERTEX, 2000, 1000, VERTEX, 2000, 9000, VERTEX, 6000, 9000, VERTEX, 8000, 7000, VERTEX, 8000, 1000, END, OUTLINEPOLYGON, 0, FL_GRAY, VERTEX, 6000, 9000, VERTEX, 6000, 7000, VERTEX, 8000, 7000, END, COLOR, 0, FL_BLACK, LINE, VERTEX, 6000, 7000, VERTEX, 8000, 7000, VERTEX, 8000, 1000, VERTEX, 2000, 1000, END, COLOR, 0, FL_RED, POLYGON, VERTEX, 3500, 2500, VERTEX, 3000, 3000, VERTEX, 3000, 4000, VERTEX, 3500, 4500, VERTEX, 4500, 4500, VERTEX, 5000, 4000, VERTEX, 5000, 3000, VERTEX, 4500, 2500, END, COLOR, 0, FL_GREEN, POLYGON, VERTEX, 5500, 2500, VERTEX, 5000, 3000, VERTEX, 5000, 4000, VERTEX, 5500, 4500, VERTEX, 6500, 4500, VERTEX, 7000, 4000, VERTEX, 7000, 3000, VERTEX, 6500, 2500, END, COLOR, 0, FL_BLUE, POLYGON, VERTEX, 4500, 3500, VERTEX, 4000, 4000, VERTEX, 4000, 5000, VERTEX, 4500, 5500, VERTEX, 5500, 5500, VERTEX, 6000, 5000, VERTEX, 6000, 4000, VERTEX, 5500, 3500, END, END }; static short dir[] = { // Directory icon COLOR, -1, -1, POLYGON, VERTEX, 1000, 1000, VERTEX, 1000, 7500, VERTEX, 9000, 7500, VERTEX, 9000, 1000, END, POLYGON, VERTEX, 1000, 7500, VERTEX, 2500, 9000, VERTEX, 5000, 9000, VERTEX, 6500, 7500, END, COLOR, 0, FL_WHITE, LINE, VERTEX, 1500, 1500, VERTEX, 1500, 7000, VERTEX, 9000, 7000, END, COLOR, 0, FL_BLACK, LINE, VERTEX, 9000, 7500, VERTEX, 9000, 1000, VERTEX, 1000, 1000, END, COLOR, 0, FL_GRAY, LINE, VERTEX, 1000, 1000, VERTEX, 1000, 7500, VERTEX, 2500, 9000, VERTEX, 5000, 9000, VERTEX, 6500, 7500, VERTEX, 9000, 7500, END, END }; // Add symbols if they haven't been added already... if (!init) { // This method requires the images library... fl_register_images(); if (!kdedir) { // Figure out where KDE is installed... if ((kdedir = fl_getenv("KDEDIR")) == NULL) { if (!fl_access("/opt/kde", F_OK)) kdedir = "/opt/kde"; else if (!fl_access("/usr/local/share/mimelnk", F_OK)) kdedir = "/usr/local"; else kdedir = "/usr"; } } snprintf(filename, sizeof(filename), "%s/share/mimelnk", kdedir); if (!fl_access(filename, F_OK)) { // Load KDE icons... icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN); for (i = 0; icondirs[i]; i ++) { snprintf(icondir, sizeof(icondir), "%s/share/icons/%s", kdedir, icondirs[i]); if (!fl_access(icondir, F_OK)) break; } if (icondirs[i]) { snprintf(filename, sizeof(filename), "%s/16x16/mimetypes/unknown.png", icondir); } else { snprintf(filename, sizeof(filename), "%s/share/icons/unknown.xpm", kdedir); } if (!fl_access(filename, F_OK)) icon->load_image(filename); icon = new Fl_File_Icon("*", Fl_File_Icon::LINK); snprintf(filename, sizeof(filename), "%s/16x16/filesystems/link.png", icondir); if (!fl_access(filename, F_OK)) icon->load_image(filename); snprintf(filename, sizeof(filename), "%s/share/mimelnk", kdedir); load_kde_icons(filename, icondir); } else if (!fl_access("/usr/share/icons/folder.xpm", F_OK)) { // Load GNOME icons... icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN); icon->load_image("/usr/share/icons/page.xpm"); icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY); icon->load_image("/usr/share/icons/folder.xpm"); } else if (!fl_access("/usr/dt/appconfig/icons", F_OK)) { // Load CDE icons... icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN); icon->load_image("/usr/dt/appconfig/icons/C/Dtdata.m.pm"); icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY); icon->load_image("/usr/dt/appconfig/icons/C/DtdirB.m.pm"); icon = new Fl_File_Icon("core", Fl_File_Icon::PLAIN); icon->load_image("/usr/dt/appconfig/icons/C/Dtcore.m.pm"); icon = new Fl_File_Icon("*.{bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN); icon->load_image("/usr/dt/appconfig/icons/C/Dtimage.m.pm"); icon = new Fl_File_Icon("*.{eps|pdf|ps}", Fl_File_Icon::PLAIN); icon->load_image("/usr/dt/appconfig/icons/C/Dtps.m.pm"); icon = new Fl_File_Icon("*.ppd", Fl_File_Icon::PLAIN); icon->load_image("/usr/dt/appconfig/icons/C/DtPrtpr.m.pm"); } else if (!fl_access("/usr/lib/filetype", F_OK)) { // Load SGI icons... icon = new Fl_File_Icon("*", Fl_File_Icon::PLAIN); icon->load_fti("/usr/lib/filetype/iconlib/generic.doc.fti"); icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY); icon->load_fti("/usr/lib/filetype/iconlib/generic.folder.closed.fti"); icon = new Fl_File_Icon("core", Fl_File_Icon::PLAIN); icon->load_fti("/usr/lib/filetype/default/iconlib/CoreFile.fti"); icon = new Fl_File_Icon("*.{bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN); icon->load_fti("/usr/lib/filetype/system/iconlib/ImageFile.fti"); if (!fl_access("/usr/lib/filetype/install/iconlib/acroread.doc.fti", F_OK)) { icon = new Fl_File_Icon("*.{eps|ps}", Fl_File_Icon::PLAIN); icon->load_fti("/usr/lib/filetype/system/iconlib/PostScriptFile.closed.fti"); icon = new Fl_File_Icon("*.pdf", Fl_File_Icon::PLAIN); icon->load_fti("/usr/lib/filetype/install/iconlib/acroread.doc.fti"); } else { icon = new Fl_File_Icon("*.{eps|pdf|ps}", Fl_File_Icon::PLAIN); icon->load_fti("/usr/lib/filetype/system/iconlib/PostScriptFile.closed.fti"); } if (!fl_access("/usr/lib/filetype/install/iconlib/html.fti", F_OK)) { icon = new Fl_File_Icon("*.{htm|html|shtml}", Fl_File_Icon::PLAIN); icon->load_fti("/usr/lib/filetype/iconlib/generic.doc.fti"); icon->load_fti("/usr/lib/filetype/install/iconlib/html.fti"); } if (!fl_access("/usr/lib/filetype/install/iconlib/color.ps.idle.fti", F_OK)) { icon = new Fl_File_Icon("*.ppd", Fl_File_Icon::PLAIN); icon->load_fti("/usr/lib/filetype/install/iconlib/color.ps.idle.fti"); } } else { // Create the default icons... new Fl_File_Icon("*", Fl_File_Icon::PLAIN, sizeof(plain) / sizeof(plain[0]), plain); new Fl_File_Icon("*.{bm|bmp|bw|gif|jpg|pbm|pcd|pgm|ppm|png|ras|rgb|tif|xbm|xpm}", Fl_File_Icon::PLAIN, sizeof(image) / sizeof(image[0]), image); new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY, sizeof(dir) / sizeof(dir[0]), dir); } // Mark things as initialized... init = 1; #ifdef DEBUG int count; Fl_File_Icon *temp; for (count = 0, temp = first_; temp; temp = temp->next_, count ++); printf("count of Fl_File_Icon's is %d...\n", count); #endif // DEBUG } } // // 'load_kde_icons()' - Load KDE icon files. // static void load_kde_icons(const char *directory, // I - Directory to load const char *icondir) { // I - Location of icons int i; // Looping var int n; // Number of entries in directory dirent **entries; // Entries in directory char full[FL_PATH_MAX]; // Full name of file entries = (dirent **)0; n = fl_filename_list(directory, &entries); for (i = 0; i < n; i ++) { if (entries[i]->d_name[0] != '.') { snprintf(full, sizeof(full), "%s/%s", directory, entries[i]->d_name); if (fl_filename_isdir(full)) load_kde_icons(full, icondir); else load_kde_mimelnk(full, icondir); } free((void *)entries[i]); } free((void*)entries); } // // 'load_kde_mimelnk()' - Load a KDE "mimelnk" file. // static void load_kde_mimelnk(const char *filename, // I - mimelnk filename const char *icondir) { // I - Location of icons FILE *fp; char tmp[1024]; char iconfilename[FL_PATH_MAX]; char pattern[1024]; char mimetype[1024]; char *val; char full_iconfilename[2 * FL_PATH_MAX]; Fl_File_Icon *icon; mimetype[0] = '\0'; pattern[0] = '\0'; iconfilename[0] = '\0'; if ((fp = fl_fopen(filename, "rb")) != NULL) { while (fgets(tmp, sizeof(tmp), fp)) { if ((val = get_kde_val(tmp, "Icon")) != NULL) strlcpy(iconfilename, val, sizeof(iconfilename)); else if ((val = get_kde_val(tmp, "MimeType")) != NULL) strlcpy(mimetype, val, sizeof(mimetype)); else if ((val = get_kde_val(tmp, "Patterns")) != NULL) strlcpy(pattern, val, sizeof(pattern)); } fclose(fp); #ifdef DEBUG printf("%s: Icon=\"%s\", MimeType=\"%s\", Patterns=\"%s\"\n", filename, iconfilename, mimetype, pattern); #endif // DEBUG if (!pattern[0] && strncmp(mimetype, "inode/", 6)) return; if (iconfilename[0]) { if (iconfilename[0] == '/') { strlcpy(full_iconfilename, iconfilename, sizeof(full_iconfilename)); } else if (!fl_access(icondir, F_OK)) { // KDE 3.x and 2.x icons int i; // Looping var static const char *paths[] = { // Subdirs to look in... "16x16/actions", "16x16/apps", "16x16/devices", "16x16/filesystems", "16x16/mimetypes", /* "20x20/actions", "20x20/apps", "20x20/devices", "20x20/filesystems", "20x20/mimetypes", "22x22/actions", "22x22/apps", "22x22/devices", "22x22/filesystems", "22x22/mimetypes", "24x24/actions", "24x24/apps", "24x24/devices", "24x24/filesystems", "24x24/mimetypes", */ "32x32/actions", "32x32/apps", "32x32/devices", "32x32/filesystems", "32x32/mimetypes", /* "36x36/actions", "36x36/apps", "36x36/devices", "36x36/filesystems", "36x36/mimetypes", "48x48/actions", "48x48/apps", "48x48/devices", "48x48/filesystems", "48x48/mimetypes", "64x64/actions", "64x64/apps", "64x64/devices", "64x64/filesystems", "64x64/mimetypes", "96x96/actions", "96x96/apps", "96x96/devices", "96x96/filesystems", "96x96/mimetypes" */ }; for (i = 0; i < (int)(sizeof(paths) / sizeof(paths[0])); i ++) { snprintf(full_iconfilename, sizeof(full_iconfilename), "%s/%s/%s.png", icondir, paths[i], iconfilename); if (!fl_access(full_iconfilename, F_OK)) break; } if (i >= (int)(sizeof(paths) / sizeof(paths[0]))) return; } else { // KDE 1.x icons snprintf(full_iconfilename, sizeof(full_iconfilename), "%s/%s", tmp, iconfilename); if (fl_access(full_iconfilename, F_OK)) return; } if (strncmp(mimetype, "inode/", 6) == 0) { if (!strcmp(mimetype + 6, "directory")) icon = new Fl_File_Icon("*", Fl_File_Icon::DIRECTORY); else if (!strcmp(mimetype + 6, "blockdevice")) icon = new Fl_File_Icon("*", Fl_File_Icon::DEVICE); else if (!strcmp(mimetype + 6, "fifo")) icon = new Fl_File_Icon("*", Fl_File_Icon::FIFO); else return; } else { icon = new Fl_File_Icon(kde_to_fltk_pattern(pattern), Fl_File_Icon::PLAIN); } icon->load(full_iconfilename); } } } // // 'kde_to_fltk_pattern()' - Convert a KDE pattern to a FLTK pattern. // static char * kde_to_fltk_pattern(const char *kdepattern) { char *pattern, *patptr; pattern = (char *)malloc(strlen(kdepattern) + 3); strcpy(pattern, "{"); strcpy(pattern + 1, kdepattern); if (pattern[strlen(pattern) - 1] == ';') pattern[strlen(pattern) - 1] = '\0'; strcat(pattern, "}"); for (patptr = pattern; *patptr; patptr ++) { if (*patptr == ';') *patptr = '|'; } return (pattern); } // // 'get_kde_val()' - Get a KDE value. // static char * get_kde_val(char *str, const char *key) { while (*str == *key) { str ++; key ++; } if (*key == '\0' && *str == '=') { if (str[strlen(str) - 1] == '\n') str[strlen(str) - 1] = '\0'; return (str + 1); } return ((char *)0); } fltk-1.4.3/src/Fl_Table_Row.cxx0000644000175000017500000002475515004135251016434 0ustar albrechtalbrecht// // Fl_Table_Row -- A row oriented table widget // // A class specializing in a table of rows. // Handles row-specific selection behavior. // // Copyright 2002 by Greg Ercolano. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // // TODO: // o Row headings (only column headings supported currently) // #include #include #include #include // for debugging... // #define DEBUG 1 #ifdef DEBUG #include #include // fprintf() #define PRINTEVENT \ fprintf(stderr,"TableRow %s: ** Event: %s --\n", (label()?label():"none"), fl_eventnames[event]); #else #define PRINTEVENT #endif // An STL-ish vector without templates (private to Fl_Table_Row) void Fl_Table_Row::CharVector::copy(char *newarr, int newsize) { size(newsize); memcpy(arr, newarr, newsize * sizeof(char)); } Fl_Table_Row::CharVector::~CharVector() { // DTOR if (arr) free(arr); arr = 0; } void Fl_Table_Row::CharVector::size(int count) { if (count <= 0 ) { // Same state as init() - (issue #296) if ( arr ) free(arr); arr = 0; _size = 0; return; } if (count != _size) { arr = (char*)realloc(arr, (unsigned)count * sizeof(char)); _size = count; } } /** Checks to see if 'row' is selected. Returns 1 if selected, 0 if not. You can change the selection of a row by clicking on it, or by using select_row(row, flag) \p row \b should be a valid row. If the row is out of range the return value is 0 (zero). \param[in] row row to be checked \return whether given row is selected \retval 1 row is selected \retval 0 row is not selected or \p row is out of range */ int Fl_Table_Row::row_selected(int row) { if (row < 0 || row >= rows()) return 0; return _rowselect[row]; } // Change row selection type void Fl_Table_Row::type(TableRowSelectMode val) { _selectmode = val; switch ( _selectmode ) { case SELECT_NONE: { for ( int row=0; row 1 ) { // only one allowed _rowselect[row] = 0; } } } redraw(); break; } case SELECT_MULTI: break; } } /** Changes the selection state for \p 'row', depending on the value of \p 'flag'. The optional \p flag can be: - 0: clear selection - 1: set selection (default) - 2: toggle selection \param[in] row row to be selected, deselected, or toggled \param[in] flag change mode, see description \return result of modification, see description \retval 0: selection state did not change \retval 1: selection state changed \retval -1: row out of range or incorrect selection mode (\p flag) */ int Fl_Table_Row::select_row(int row, int flag) { int ret = 0; if ( row < 0 || row >= rows() ) { return(-1); } switch ( _selectmode ) { case SELECT_NONE: return(-1); case SELECT_SINGLE: { int oldval; for ( int t=0; t= toprow && row <= botrow ) { // row visible? // Extend partial redraw range redraw_range(row, row, leftcol, rightcol); } ret = 1; } } } return(ret); } // Select all rows to a known state void Fl_Table_Row::select_all_rows(int flag) { switch ( _selectmode ) { case SELECT_NONE: return; case SELECT_SINGLE: if ( flag != 0 ) return; //FALLTHROUGH case SELECT_MULTI: { char changed = 0; if ( flag == 2 ) { for ( int row=0; row<(int)_rowselect.size(); row++ ) { _rowselect[row] ^= 1; } changed = 1; } else { for ( int row=0; row<(int)_rowselect.size(); row++ ) { changed |= (_rowselect[row] != flag)?1:0; _rowselect[row] = flag; } } if ( changed ) { redraw(); } } } } // Set number of rows void Fl_Table_Row::rows(int val) { while ( val > (int)_rowselect.size() ) { _rowselect.push_back(0); } // enlarge Fl_Table::rows(val); while ( val < (int)_rowselect.size() ) { _rowselect.pop_back(); } // shrink } // Handle events int Fl_Table_Row::handle(int event) { PRINTEVENT; // Make snapshots of realtime event states *before* we service user's cb, // which may do things like post popup menus that return with unexpected button states. int _event_button = Fl::event_button(); //int _event_clicks = Fl::event_clicks(); // uncomment if needed int _event_x = Fl::event_x(); int _event_y = Fl::event_y(); //int _event_key = Fl::event_key(); // uncomment if needed int _event_state = Fl::event_state(); //Fl_Widget *_focus = Fl::focus(); // uncomment if needed // Let base class handle event // Note: base class may invoke user callbacks that post menus, // so from here on use event state snapshots (above). // int ret = Fl_Table::handle(event); // The following code disables cell selection.. why was it added? -erco 05/18/03 // if ( ret ) { _last_y = Fl::event_y(); return(1); } // base class 'handled' it (eg. column resize) int shiftstate = (_event_state & FL_CTRL) ? FL_CTRL : (_event_state & FL_SHIFT) ? FL_SHIFT : 0; // Which row/column are we over? int R, C; // row/column being worked on ResizeFlag resizeflag; // which resizing area are we over? (0=none) TableContext context = cursor2rowcol(R, C, resizeflag); switch ( event ) { case FL_PUSH: if ( _event_button == 1 ) { _last_push_x = _event_x; // save regardless of context _last_push_y = _event_y; // " " // Handle selection in table. // Select cell under cursor, and enable drag selection mode. // if ( context == CONTEXT_CELL ) { // Ctrl key? Toggle selection state switch ( shiftstate ) { case FL_CTRL: select_row(R, 2); // toggle break; case FL_SHIFT: { select_row(R, 1); if ( _last_row > -1 ) { int srow = R, erow = _last_row; if ( srow > erow ) { srow = _last_row; erow = R; } for ( int row = srow; row <= erow; row++ ) { select_row(row, 1); } } break; } default: select_all_rows(0); // clear all previous selections select_row(R, 1); break; } _last_row = R; _dragging_select = 1; ret = 1; // FL_PUSH handled (ensures FL_DRAG will be sent) // redraw(); // redraw() handled by select_row() } } break; case FL_DRAG: { if ( _dragging_select ) { // Dragged off table edges? Handle scrolling int offtop = toy - _last_y; // >0 if off top of table int offbot = _last_y - (toy + toh); // >0 if off bottom of table if ( offtop > 0 && row_position() > 0 ) { // Only scroll in upward direction int diff = _last_y - _event_y; if ( diff < 1 ) { ret = 1; break; } row_position(row_position() - diff); context = CONTEXT_CELL; C = 0; R = row_position(); // HACK: fake it if ( R < 0 || R > rows() ) { ret = 1; break; } // HACK: ugly } else if ( offbot > 0 && botrow < rows() ) { // Only scroll in downward direction int diff = _event_y - _last_y; if ( diff < 1 ) { ret = 1; break; } row_position(row_position() + diff); context = CONTEXT_CELL; C = 0; R = botrow; // HACK: fake it if ( R < 0 || R > rows() ) { ret = 1; break; } // HACK: ugly } if ( context == CONTEXT_CELL ) { switch ( shiftstate ) { case FL_CTRL: if ( R != _last_row ) { // toggle if dragged to new row select_row(R, 2); // 2=toggle } break; case FL_SHIFT: default: select_row(R, 1); if ( _last_row > -1 ) { int srow = R, erow = _last_row; if ( srow > erow ) { srow = _last_row; erow = R; } for ( int row = srow; row <= erow; row++ ) { select_row(row, 1); } } break; } ret = 1; // drag handled _last_row = R; } } break; } case FL_RELEASE: if ( _event_button == 1 ) { _dragging_select = 0; ret = 1; // release handled // Clicked off edges of data table? // A way for user to clear the current selection. // int databot = tiy + table_h, dataright = tix + table_w; if ( ( _last_push_x > dataright && _event_x > dataright ) || ( _last_push_y > databot && _event_y > databot ) ) { select_all_rows(0); // clear previous selections } } break; default: break; } _last_y = _event_y; return(ret); } fltk-1.4.3/src/Fl_Text_Buffer.cxx0000644000175000017500000015511115004135251016762 0ustar albrechtalbrecht// // Copyright 2001-2023 by Bill Spitzak and others. // Original code Copyright Mark Edel. Permission to distribute under // the LGPL for the FLTK library granted by Mark Edel. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include "flstring.h" #include #include #include #include /* This file is based on a port of NEdit to FLTK many years ago. NEdit at that point was already stretched beyond the task it was designed for which explains why the source code is sometimes pretty convoluted. It still is a very useful widget for FLTK, and we are thankful that the nedit team allowed us to integrate their code. With the introduction of Unicode and UTF-8, Fl_Text_... has to go into a whole new generation of code. Originally designed for monospaced fonts only, many features make less sense in the multibyte and multiwidth world of UTF-8. Columns are a good example. There is simply no such thing. The new Fl_Text_... widget converts columns to pixels by multiplying them with the average character width for a given font. Rectangular selections were rarely used (if at all) and make little sense when using variable width fonts. They have been removed. Using multiple spaces to emulate tab stops has been replaced by pixel counting routines. They are slower, but give the expected result for proportional fonts. And constantly recalculating character widths is just much too expensive. Lines of text are now subdivided into blocks of text which are measured at once instead of individual characters. */ #ifndef min static int max(int i1, int i2) { return i1 >= i2 ? i1 : i2; } static int min(int i1, int i2) { return i1 <= i2 ? i1 : i2; } #endif /* Undo/Redo is handled with Fl_Text_Undo_Action. The names of the class members relate to the original action. Deleting text will store the number of bytes deleted in `undocut`, and store the deleted text in `undobuffer`. `undoat` is the insertion position. Inserting text will store the number of bytes inserted in `undoinsert` and `undoat` will point after the inserted text. If text is deleted first and then text is inserted at the same position, it's called a yankcut, and the number of bytes that were deleted is stored in `undoyankcut`, again storing the deleted text in `undobuffer`. If an undo action is run, text is deleted and inserted via the normal Fl_Text_Editor methods, generating the inverse undo action (redo) in mUndo. */ class Fl_Text_Undo_Action { public: Fl_Text_Undo_Action() : undobuffer(NULL), undobufferlength(0), undoat(0), undocut(0), undoinsert(0), undoyankcut(0) { } ~Fl_Text_Undo_Action() { if (undobuffer) ::free(undobuffer); } char *undobuffer; int undobufferlength; int undoat; // points after insertion int undocut; // number of characters deleted there int undoinsert; // number of characters inserted int undoyankcut; // length of valid contents of buffer, even if undocut=0 /* Resize the undo buffer to match at least the requested size. */ void undobuffersize(int n) { if (n > undobufferlength) { undobufferlength = n + 128; undobuffer = (char *)realloc(undobuffer, undobufferlength); } } void clear() { undocut = undoinsert = 0; } bool empty() const { return (!undocut && !undoinsert); } }; /* Undo events are stored in a Last In - First Out stack. Any insertion or deletion of text will either add to the current undo event in mUndo, or generate a new undo event if cursor positions are not consecutive. The previously current undo event will then be pushed to the undo list and the redo event list is purged. If the user calls undo(), the current undo event in mUndo will be run, generating a matching redo event in mUndo. The redo event is then pushed into the redo list, and the next undo event is popped from the undo list and made current. A list can be locked to be protected from purging while running an undo event. */ class Fl_Text_Undo_Action_List { Fl_Text_Undo_Action** list_; int list_size_; int list_capacity_; bool locked_; public: Fl_Text_Undo_Action_List() : list_(NULL), list_size_(0), list_capacity_(0), locked_(false) { } ~Fl_Text_Undo_Action_List() { unlock(); clear(); } int size() const { return list_size_; } void push(Fl_Text_Undo_Action* action) { if (list_size_ == list_capacity_) { list_capacity_ += 25; list_ = (Fl_Text_Undo_Action**)realloc(list_, list_capacity_ * sizeof(Fl_Text_Undo_Action*)); } list_[list_size_++] = action; } Fl_Text_Undo_Action* pop() { if (list_size_ > 0) { return list_[--list_size_]; } else { return NULL; } } void clear() { if (locked_) return; if (list_) { for (int i=0; ifile_encoding_warning_message); } /* Initialize all variables. */ Fl_Text_Buffer::Fl_Text_Buffer(int requestedSize, int preferredGapSize) { mLength = 0; mPreferredGapSize = preferredGapSize; mBuf = (char *) malloc(requestedSize + mPreferredGapSize); mGapStart = 0; mGapEnd = requestedSize + mPreferredGapSize; mTabDist = 8; mPrimary.mSelected = 0; mPrimary.mStart = mPrimary.mEnd = 0; mSecondary.mSelected = 0; mSecondary.mStart = mSecondary.mEnd = 0; mHighlight.mSelected = 0; mHighlight.mStart = mHighlight.mEnd = 0; mModifyProcs = NULL; mCbArgs = NULL; mNModifyProcs = 0; mNPredeleteProcs = 0; mPredeleteProcs = NULL; mPredeleteCbArgs = NULL; mCursorPosHint = 0; mCanUndo = 1; mUndo = new Fl_Text_Undo_Action(); mUndoList = new Fl_Text_Undo_Action_List(); mRedoList = new Fl_Text_Undo_Action_List(); input_file_was_transcoded = 0; transcoding_warning_action = def_transcoding_warning_action; } /* Free all resources. */ Fl_Text_Buffer::~Fl_Text_Buffer() { free(mBuf); if (mNModifyProcs != 0) { delete[]mModifyProcs; delete[]mCbArgs; } if (mNPredeleteProcs > 0) { delete[] mPredeleteProcs; delete[] mPredeleteCbArgs; } delete mUndo; delete mUndoList; delete mRedoList; } /* This function copies verbose whatever is in front and after the gap into a single buffer. */ char *Fl_Text_Buffer::text() const { char *t = (char *) malloc(mLength + 1); memcpy(t, mBuf, mGapStart); memcpy(t+mGapStart, mBuf+mGapEnd, mLength - mGapStart); t[mLength] = '\0'; return t; } /* Set the text buffer to a new string. */ void Fl_Text_Buffer::text(const char *t) { IS_UTF8_ALIGNED(t) // if t is null then substitute it with an empty string // then don't return so that internal cleanup can happen if (!t) t=""; call_predelete_callbacks(0, length()); /* Save information for redisplay, and get rid of the old buffer */ const char *deletedText = text(); int deletedLength = mLength; free((void *) mBuf); /* Start a new buffer with a gap of mPreferredGapSize at the end */ int insertedLength = (int) strlen(t); mBuf = (char *) malloc(insertedLength + mPreferredGapSize); mLength = insertedLength; mGapStart = insertedLength; mGapEnd = mGapStart + mPreferredGapSize; memcpy(mBuf, t, insertedLength); /* Zero all of the existing selections */ update_selections(0, deletedLength, 0); /* Call the saved display routine(s) to update the screen */ call_modify_callbacks(0, deletedLength, insertedLength, 0, deletedText); free((void *) deletedText); if (mCanUndo) { mUndo->clear(); mUndoList->clear(); mRedoList->clear(); } } /* Creates a range of text to a new buffer and copies verbose from around the gap. */ char *Fl_Text_Buffer::text_range(int start, int end) const { IS_UTF8_ALIGNED2(this, (start)) IS_UTF8_ALIGNED2(this, (end)) char *s = NULL; /* Make sure start and end are ok, and allocate memory for returned string. If start is bad, return "", if end is bad, adjust it. */ if (start < 0 || start > mLength) { s = (char *) malloc(1); s[0] = '\0'; return s; } if (end < start) { int temp = start; start = end; end = temp; } if (end > mLength) end = mLength; int copiedLength = end - start; s = (char *) malloc(copiedLength + 1); /* Copy the text from the buffer to the returned string */ if (end <= mGapStart) { memcpy(s, mBuf + start, copiedLength); } else if (start >= mGapStart) { memcpy(s, mBuf + start + (mGapEnd - mGapStart), copiedLength); } else { int part1Length = mGapStart - start; memcpy(s, mBuf + start, part1Length); memcpy(s + part1Length, mBuf + mGapEnd, copiedLength - part1Length); } s[copiedLength] = '\0'; return s; } /* Return a UCS-4 character at the given index. Pos must be at a character boundary. */ unsigned int Fl_Text_Buffer::char_at(int pos) const { if (pos < 0 || pos >= mLength) return '\0'; IS_UTF8_ALIGNED2(this, (pos)) const char *src = address(pos); return fl_utf8decode(src, 0, 0); } /* Return the raw byte at the given index. This function ignores all unicode encoding. */ char Fl_Text_Buffer::byte_at(int pos) const { if (pos < 0 || pos >= mLength) return '\0'; const char *src = address(pos); return *src; } /* Insert some text at the given index. Pos must be at a character boundary. */ void Fl_Text_Buffer::insert(int pos, const char *text, int insertedLength) { IS_UTF8_ALIGNED2(this, (pos)) IS_UTF8_ALIGNED(text) /* check if there is actually any text */ if (!text || !*text) return; /* if pos is not contiguous to existing text, make it */ if (pos > mLength) pos = mLength; if (pos < 0) pos = 0; /* Even if nothing is deleted, we must call these callbacks */ call_predelete_callbacks(pos, 0); /* insert and redisplay */ int nInserted = insert_(pos, text, insertedLength); mCursorPosHint = pos + nInserted; IS_UTF8_ALIGNED2(this, (mCursorPosHint)) call_modify_callbacks(pos, 0, nInserted, 0, NULL); } /** Can be used by subclasses that need their own printf() style functionality. \note The expanded string is currently limited to 1024 characters. \param[in] fmt is a printf format string for the message text. \param[in] ap is a va_list created by va_start() and closed with va_end(), which the caller is responsible for handling. */ void Fl_Text_Buffer::vprintf(const char *fmt, va_list ap) { char buffer[1024]; // XXX: 1024 should be user configurable ::vsnprintf(buffer, 1024, fmt, ap); buffer[1024-1] = 0; // XXX: MICROSOFT append(buffer); } /** Appends printf formatted messages to the end of the buffer. Example: \code #include int main(..) { : // Create a text display widget and assign it a text buffer Fl_Text_Display *tdsp = new Fl_Text_Display(..); Fl_Text_Buffer *tbuf = new Fl_Text_Buffer(); tdsp->buffer(tbuf); : // Append three lines of formatted text to the buffer tbuf->printf("The current date is: %s.\nThe time is: %s\n", date_str, time_str); tbuf->printf("The current PID is %ld.\n", (long)getpid()); : \endcode \note The expanded string is currently limited to 1024 characters. \param[in] fmt is a printf format string for the message text. */ void Fl_Text_Buffer::printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); Fl_Text_Buffer::vprintf(fmt,ap); va_end(ap); } /* Replace a range of text with new text. Start and end must be at a character boundary. */ void Fl_Text_Buffer::replace(int start, int end, const char *text, int insertedLength) { // Range check... if (!text) return; if (start < 0) start = 0; if (end > mLength) end = mLength; IS_UTF8_ALIGNED2(this, (start)) IS_UTF8_ALIGNED2(this, (end)) IS_UTF8_ALIGNED(text) call_predelete_callbacks(start, end - start); const char *deletedText = text_range(start, end); remove_(start, end); int nInserted = insert_(start, text, insertedLength); mCursorPosHint = start + nInserted; call_modify_callbacks(start, end - start, nInserted, 0, deletedText); free((void *) deletedText); } /* Remove a range of text. Start and End must be at a character boundary. */ void Fl_Text_Buffer::remove(int start, int end) { /* Make sure the arguments make sense */ if (start > end) { int temp = start; start = end; end = temp; } if (start > mLength) start = mLength; if (start < 0) start = 0; if (end > mLength) end = mLength; if (end < 0) end = 0; IS_UTF8_ALIGNED2(this, (start)) IS_UTF8_ALIGNED2(this, (end)) if (start == end) return; call_predelete_callbacks(start, end - start); /* Remove and redisplay */ const char *deletedText = text_range(start, end); remove_(start, end); mCursorPosHint = start; call_modify_callbacks(start, end - start, 0, 0, deletedText); free((void *) deletedText); } /* Copy a range of text from another text buffer. fromStart, fromEnd, and toPos must be at a character boundary. */ void Fl_Text_Buffer::copy(Fl_Text_Buffer * fromBuf, int fromStart, int fromEnd, int toPos) { IS_UTF8_ALIGNED2(fromBuf, fromStart) IS_UTF8_ALIGNED2(fromBuf, fromEnd) IS_UTF8_ALIGNED2(this, (toPos)) int copiedLength = fromEnd - fromStart; /* Prepare the buffer to receive the new text. If the new text fits in the current buffer, just move the gap (if necessary) to where the text should be inserted. If the new text is too large, reallocate the buffer with a gap large enough to accomodate the new text and a gap of mPreferredGapSize */ if (copiedLength > mGapEnd - mGapStart) reallocate_with_gap(toPos, copiedLength + mPreferredGapSize); else if (toPos != mGapStart) move_gap(toPos); /* Insert the new text (toPos now corresponds to the start of the gap) */ if (fromEnd <= fromBuf->mGapStart) { memcpy(&mBuf[toPos], &fromBuf->mBuf[fromStart], copiedLength); } else if (fromStart >= fromBuf->mGapStart) { memcpy(&mBuf[toPos], &fromBuf->mBuf[fromStart + (fromBuf->mGapEnd - fromBuf->mGapStart)], copiedLength); } else { int part1Length = fromBuf->mGapStart - fromStart; memcpy(&mBuf[toPos], &fromBuf->mBuf[fromStart], part1Length); memcpy(&mBuf[toPos + part1Length], &fromBuf->mBuf[fromBuf->mGapEnd], copiedLength - part1Length); } mGapStart += copiedLength; mLength += copiedLength; update_selections(toPos, 0, copiedLength); } /** Apply the current undo/redo operation, called from undo() or redo(). */ int Fl_Text_Buffer::apply_undo(Fl_Text_Undo_Action* action, int* cursorPos) { if (action->empty()) return 0; mRedoList->lock(); int ilen = action->undocut; int xlen = action->undoinsert; int b = action->undoat - xlen; if (xlen && action->undoyankcut && !ilen) { ilen = action->undoyankcut; } if (xlen && ilen) { action->undobuffersize(ilen + 1); action->undobuffer[ilen] = 0; char *tmp = fl_strdup(action->undobuffer); replace(b, action->undoat, tmp); if (cursorPos) *cursorPos = mCursorPosHint; free(tmp); } else if (xlen) { remove(b, action->undoat); if (cursorPos) *cursorPos = mCursorPosHint; } else if (ilen) { action->undobuffersize(ilen + 1); action->undobuffer[ilen] = 0; insert(action->undoat, action->undobuffer); if (cursorPos) *cursorPos = mCursorPosHint; action->undoyankcut = 0; } mRedoList->unlock(); return 1; } /** Take the previous changes and undo them. Return the previous cursor position in cursorPos. Returns 1 if the undo was applied. CursorPos will be at a character boundary. */ int Fl_Text_Buffer::undo(int *cursorPos) { if (!mCanUndo || mUndo->empty()) return 0; // save the current undo action and add an empty action to avoid generating yankcuts Fl_Text_Undo_Action* action = mUndo; mUndo = new Fl_Text_Undo_Action(); int ret = apply_undo(action, cursorPos); delete action; if (ret) { // push the generated undo action to the redo list mRedoList->push(mUndo); // drop the empty action we previously created mUndo = mUndoList->pop(); if (mUndo) { delete mUndo; // pop the undo action before that and make it the current undo action mUndo = mUndoList->pop(); if (!mUndo) mUndo = new Fl_Text_Undo_Action(); } } return ret; } /* Check if undo is anabled and if the last action can be undone. */ bool Fl_Text_Buffer::can_undo() const { return (mCanUndo && mUndo && !mUndo->empty()); } /** Redo previous undo action. */ int Fl_Text_Buffer::redo(int *cursorPos) { if (!mCanUndo) return 0; Fl_Text_Undo_Action *redo_action = mRedoList->pop(); if (!redo_action) return 0; // running the redo action will also generate a new undo action // Note: there is a slight chance that the current undo action and the // generated action merge into one. int ret = apply_undo(redo_action, cursorPos); delete redo_action; return ret; } /** Check if undo is anabled and if the last undo action can be redone. \see canUndo() */ bool Fl_Text_Buffer::can_redo() const { return (mCanUndo && mRedoList->size()); } /* Set a flag if undo function will work. */ void Fl_Text_Buffer::canUndo(char flag) { if (flag) { if (!mCanUndo) { mUndo = new Fl_Text_Undo_Action(); } } else { if (mCanUndo) { delete mUndo; mUndo = NULL; } } mCanUndo = flag; } /* Change the tab width. This will cause a couple of callbacks and a complete redisplay. Matt: I am not entirely sure why we need to trigger callbacks because tabs are only a graphical hint, not changing any text at all, but I leave this in here for back compatibility. */ void Fl_Text_Buffer::tab_distance(int tabDist) { /* First call the pre-delete callbacks with the previous tab setting still active. */ call_predelete_callbacks(0, mLength); /* Change the tab setting */ mTabDist = tabDist; /* Force any display routines to redisplay everything (unfortunately, this means copying the whole buffer contents to provide "deletedText" */ const char *deletedText = text(); call_modify_callbacks(0, mLength, mLength, 0, deletedText); free((void *) deletedText); } /* Select a range of text. Start and End must be at a character boundary. */ void Fl_Text_Buffer::select(int start, int end) { IS_UTF8_ALIGNED2(this, (start)) IS_UTF8_ALIGNED2(this, (end)) Fl_Text_Selection oldSelection = mPrimary; mPrimary.set(start, end); redisplay_selection(&oldSelection, &mPrimary); } /* Clear the primary selection. */ void Fl_Text_Buffer::unselect() { Fl_Text_Selection oldSelection = mPrimary; mPrimary.mSelected = 0; redisplay_selection(&oldSelection, &mPrimary); } /* Return the primary selection range. */ int Fl_Text_Buffer::selection_position(int *start, int *end) { return mPrimary.selected(start, end); } /* Return a copy of the selected text. */ char *Fl_Text_Buffer::selection_text() { return selection_text_(&mPrimary); } /* Remove the selected text. */ void Fl_Text_Buffer::remove_selection() { remove_selection_(&mPrimary); } /* Replace the selected text. */ void Fl_Text_Buffer::replace_selection(const char *text) { replace_selection_(&mPrimary, text); } /* Select text. Start and End must be at a character boundary. */ void Fl_Text_Buffer::secondary_select(int start, int end) { Fl_Text_Selection oldSelection = mSecondary; mSecondary.set(start, end); redisplay_selection(&oldSelection, &mSecondary); } /* Deselect text. */ void Fl_Text_Buffer::secondary_unselect() { Fl_Text_Selection oldSelection = mSecondary; mSecondary.mSelected = 0; redisplay_selection(&oldSelection, &mSecondary); } /* Return the selected range. */ int Fl_Text_Buffer::secondary_selection_position(int *start, int *end) { return mSecondary.selected(start, end); } /* Return a copy of the text in this selection. */ char *Fl_Text_Buffer::secondary_selection_text() { return selection_text_(&mSecondary); } /* Remove the selected text. */ void Fl_Text_Buffer::remove_secondary_selection() { remove_selection_(&mSecondary); } /* Replace selected text. */ void Fl_Text_Buffer::replace_secondary_selection(const char *text) { replace_selection_(&mSecondary, text); } /* Highlight a range of text. Start and End must be at a character boundary. */ void Fl_Text_Buffer::highlight(int start, int end) { Fl_Text_Selection oldSelection = mHighlight; mHighlight.set(start, end); redisplay_selection(&oldSelection, &mHighlight); } /* Remove text highlighting. */ void Fl_Text_Buffer::unhighlight() { Fl_Text_Selection oldSelection = mHighlight; mHighlight.mSelected = 0; redisplay_selection(&oldSelection, &mHighlight); } /* Return position of highlight. */ int Fl_Text_Buffer::highlight_position(int *start, int *end) { return mHighlight.selected(start, end); } /* Return a copy of highlighted text. */ char *Fl_Text_Buffer::highlight_text() { return selection_text_(&mHighlight); } /* Add a callback that is called whenever text is modified. */ void Fl_Text_Buffer::add_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void *cbArg) { Fl_Text_Modify_Cb *newModifyProcs = new Fl_Text_Modify_Cb[mNModifyProcs + 1]; void **newCBArgs = new void *[mNModifyProcs + 1]; for (int i = 0; i < mNModifyProcs; i++) { newModifyProcs[i + 1] = mModifyProcs[i]; newCBArgs[i + 1] = mCbArgs[i]; } if (mNModifyProcs != 0) { delete[]mModifyProcs; delete[]mCbArgs; } newModifyProcs[0] = bufModifiedCB; newCBArgs[0] = cbArg; mNModifyProcs++; mModifyProcs = newModifyProcs; mCbArgs = newCBArgs; } /* Remove a callback. */ void Fl_Text_Buffer::remove_modify_callback(Fl_Text_Modify_Cb bufModifiedCB, void *cbArg) { int i, toRemove = -1; /* find the matching callback to remove */ for (i = 0; i < mNModifyProcs; i++) { if (mModifyProcs[i] == bufModifiedCB && mCbArgs[i] == cbArg) { toRemove = i; break; } } if (toRemove == -1) { Fl::error ("Fl_Text_Buffer::remove_modify_callback(): Can't find modify CB to remove"); return; } /* Allocate new lists for remaining callback procs and args (if any are left) */ mNModifyProcs--; if (mNModifyProcs == 0) { mNModifyProcs = 0; delete[]mModifyProcs; mModifyProcs = NULL; delete[]mCbArgs; mCbArgs = NULL; return; } Fl_Text_Modify_Cb *newModifyProcs = new Fl_Text_Modify_Cb[mNModifyProcs]; void **newCBArgs = new void *[mNModifyProcs]; /* copy out the remaining members and free the old lists */ for (i = 0; i < toRemove; i++) { newModifyProcs[i] = mModifyProcs[i]; newCBArgs[i] = mCbArgs[i]; } for (; i < mNModifyProcs; i++) { newModifyProcs[i] = mModifyProcs[i + 1]; newCBArgs[i] = mCbArgs[i + 1]; } delete[]mModifyProcs; delete[]mCbArgs; mModifyProcs = newModifyProcs; mCbArgs = newCBArgs; } /* Add a callback that is called before deleting text. */ void Fl_Text_Buffer::add_predelete_callback(Fl_Text_Predelete_Cb bufPreDeleteCB, void *cbArg) { Fl_Text_Predelete_Cb *newPreDeleteProcs = new Fl_Text_Predelete_Cb[mNPredeleteProcs + 1]; void **newCBArgs = new void *[mNPredeleteProcs + 1]; for (int i = 0; i < mNPredeleteProcs; i++) { newPreDeleteProcs[i + 1] = mPredeleteProcs[i]; newCBArgs[i + 1] = mPredeleteCbArgs[i]; } if (mNPredeleteProcs > 0) { delete[] mPredeleteProcs; delete[] mPredeleteCbArgs; } newPreDeleteProcs[0] = bufPreDeleteCB; newCBArgs[0] = cbArg; mNPredeleteProcs++; mPredeleteProcs = newPreDeleteProcs; mPredeleteCbArgs = newCBArgs; } /* Remove a callback. */ void Fl_Text_Buffer::remove_predelete_callback(Fl_Text_Predelete_Cb bufPreDeleteCB, void *cbArg) { int i, toRemove = -1; /* find the matching callback to remove */ for (i = 0; i < mNPredeleteProcs; i++) { if (mPredeleteProcs[i] == bufPreDeleteCB && mPredeleteCbArgs[i] == cbArg) { toRemove = i; break; } } if (toRemove == -1) { Fl::error ("Fl_Text_Buffer::remove_predelete_callback(): Can't find pre-delete CB to remove"); return; } /* Allocate new lists for remaining callback procs and args (if any are left) */ mNPredeleteProcs--; if (mNPredeleteProcs == 0) { delete[]mPredeleteProcs; mPredeleteProcs = NULL; delete[]mPredeleteCbArgs; mPredeleteCbArgs = NULL; return; } Fl_Text_Predelete_Cb *newPreDeleteProcs = new Fl_Text_Predelete_Cb[mNPredeleteProcs]; void **newCBArgs = new void *[mNPredeleteProcs]; /* copy out the remaining members and free the old lists */ for (i = 0; i < toRemove; i++) { newPreDeleteProcs[i] = mPredeleteProcs[i]; newCBArgs[i] = mPredeleteCbArgs[i]; } for (; i < mNPredeleteProcs; i++) { newPreDeleteProcs[i] = mPredeleteProcs[i + 1]; newCBArgs[i] = mPredeleteCbArgs[i + 1]; } delete[] mPredeleteProcs; delete[] mPredeleteCbArgs; mPredeleteProcs = newPreDeleteProcs; mPredeleteCbArgs = newCBArgs; } /* Return a copy of the line that contains a given index. Pos must be at a character boundary. */ char *Fl_Text_Buffer::line_text(int pos) const { return text_range(line_start(pos), line_end(pos)); } /* Find the beginning of the line. */ int Fl_Text_Buffer::line_start(int pos) const { if (!findchar_backward(pos, '\n', &pos)) return 0; return pos + 1; } /* Find the end of the line. */ int Fl_Text_Buffer::line_end(int pos) const { if (!findchar_forward(pos, '\n', &pos)) pos = mLength; return pos; } /** Returns whether character at position \p pos is a word separator. Pos must be at a character boundary. */ bool Fl_Text_Buffer::is_word_separator(int pos) const { int c = char_at(pos); if (c < 128) { return !(isalnum(c) || c == '_'); // non alphanumeric ASCII } return (c == 0xA0 || // NO-BREAK SPACE (c >= 0x3000 && c <= 0x301F) // IDEOGRAPHIC punctuation ); } /* Find the beginning of a word. */ int Fl_Text_Buffer::word_start(int pos) const { while (pos > 0 && !is_word_separator(pos)) { pos = prev_char(pos); } if (is_word_separator(pos)) pos = next_char(pos); return pos; } /* Find the end of a word. */ int Fl_Text_Buffer::word_end(int pos) const { while (pos < length() && !is_word_separator(pos)) { pos = next_char(pos); } return pos; } /* Count the number of characters between two positions. */ int Fl_Text_Buffer::count_displayed_characters(int lineStartPos, int targetPos) const { IS_UTF8_ALIGNED2(this, (lineStartPos)) IS_UTF8_ALIGNED2(this, (targetPos)) int charCount = 0; int pos = lineStartPos; while (pos < targetPos) { pos = next_char(pos); charCount++; } return charCount; } /* Skip ahead a number of characters from a given index. This function breaks early if it encounters a newline character. */ int Fl_Text_Buffer::skip_displayed_characters(int lineStartPos, int nChars) { IS_UTF8_ALIGNED2(this, (lineStartPos)) int pos = lineStartPos; for (int charCount = 0; charCount < nChars && pos < mLength; charCount++) { unsigned int c = char_at(pos); if (c == '\n') return pos; pos = next_char(pos); } return pos; } /* Count the number of newline characters between start and end. startPos and endPos must be at a character boundary. This function is optimized for speed by not using UTF-8 calls. */ int Fl_Text_Buffer::count_lines(int startPos, int endPos) const { IS_UTF8_ALIGNED2(this, (startPos)) IS_UTF8_ALIGNED2(this, (endPos)) int gapLen = mGapEnd - mGapStart; int lineCount = 0; int pos = startPos; while (pos < mGapStart) { if (pos == endPos) return lineCount; if (mBuf[pos++] == '\n') lineCount++; } while (pos < mLength) { if (pos == endPos) return lineCount; if (mBuf[pos++ + gapLen] == '\n') lineCount++; } return lineCount; } /** Estimate the number of newlines between \p startPos and \p endPos in buffer. This call takes line wrapping into account. It assumes a line break at every `lineLen` characters after the beginning of a line. */ int Fl_Text_Buffer::estimate_lines(int startPos, int endPos, int lineLen) const { IS_UTF8_ALIGNED2(this, (startPos)) IS_UTF8_ALIGNED2(this, (endPos)) int gapLen = mGapEnd - mGapStart; int lineCount = 0; int softLineBreaks = 0, softLineBreakCount = lineLen; int pos = startPos; while (pos < mGapStart) { if (pos == endPos) return lineCount + softLineBreaks; if (mBuf[pos++] == '\n') { softLineBreakCount = lineLen; lineCount++; } if (--softLineBreakCount == 0) { softLineBreakCount = lineLen; softLineBreaks++; } } while (pos < mLength) { if (pos == endPos) return lineCount + softLineBreaks; if (mBuf[pos++ + gapLen] == '\n') { softLineBreakCount = lineLen; lineCount++; } if (--softLineBreakCount == 0) { softLineBreakCount = lineLen; softLineBreaks++; } } return lineCount + softLineBreaks; } /* Skip to the first character, n lines ahead. StartPos must be at a character boundary. This function is optimized for speed by not using UTF-8 calls. */ int Fl_Text_Buffer::skip_lines(int startPos, int nLines) { IS_UTF8_ALIGNED2(this, (startPos)) if (nLines == 0) return startPos; int gapLen = mGapEnd - mGapStart; int pos = startPos; int lineCount = 0; while (pos < mGapStart) { if (mBuf[pos++] == '\n') { lineCount++; if (lineCount == nLines) { IS_UTF8_ALIGNED2(this, (pos)) return pos; } } } while (pos < mLength) { if (mBuf[pos++ + gapLen] == '\n') { lineCount++; if (lineCount >= nLines) { IS_UTF8_ALIGNED2(this, (pos)) return pos; } } } IS_UTF8_ALIGNED2(this, (pos)) return pos; } /* Skip to the first character, n lines back. StartPos must be at a character boundary. This function is optimized for speed by not using UTF-8 calls. */ int Fl_Text_Buffer::rewind_lines(int startPos, int nLines) { IS_UTF8_ALIGNED2(this, (startPos)) int pos = startPos - 1; if (pos <= 0) return 0; int gapLen = mGapEnd - mGapStart; int lineCount = -1; while (pos >= mGapStart) { if (mBuf[pos + gapLen] == '\n') { if (++lineCount >= nLines) { IS_UTF8_ALIGNED2(this, (pos+1)) return pos + 1; } } pos--; } while (pos >= 0) { if (mBuf[pos] == '\n') { if (++lineCount >= nLines) { IS_UTF8_ALIGNED2(this, (pos+1)) return pos + 1; } } pos--; } return 0; } /* Find a matching string in the buffer. */ int Fl_Text_Buffer::search_forward(int startPos, const char *searchString, int *foundPos, int matchCase) const { IS_UTF8_ALIGNED2(this, (startPos)) IS_UTF8_ALIGNED(searchString) if (!searchString) return 0; int bp; const char *sp; if (matchCase) { while (startPos < length()) { bp = startPos; sp = searchString; for (;;) { char c = *sp; // we reached the end of the "needle", so we found the string! if (!c) { *foundPos = startPos; return 1; } int l = fl_utf8len1(c); if (memcmp(sp, address(bp), l)) break; sp += l; bp += l; } startPos = next_char(startPos); } } else { while (startPos < length()) { bp = startPos; sp = searchString; for (;;) { // we reached the end of the "needle", so we found the string! if (!*sp) { *foundPos = startPos; return 1; } int l; unsigned int b = char_at(bp); unsigned int s = fl_utf8decode(sp, 0, &l); if (fl_tolower(b)!=fl_tolower(s)) break; sp += l; bp = next_char(bp); } startPos = next_char(startPos); } } return 0; } int Fl_Text_Buffer::search_backward(int startPos, const char *searchString, int *foundPos, int matchCase) const { IS_UTF8_ALIGNED2(this, (startPos)) IS_UTF8_ALIGNED(searchString) if (!searchString) return 0; int bp; const char *sp; if (matchCase) { while (startPos >= 0) { bp = startPos; sp = searchString; for (;;) { char c = *sp; // we reached the end of the "needle", so we found the string! if (!c) { *foundPos = startPos; return 1; } int l = fl_utf8len1(c); if (memcmp(sp, address(bp), l)) break; sp += l; bp += l; } startPos = prev_char(startPos); } } else { while (startPos >= 0) { bp = startPos; sp = searchString; for (;;) { // we reached the end of the "needle", so we found the string! if (!*sp) { *foundPos = startPos; return 1; } int l; unsigned int b = char_at(bp); unsigned int s = fl_utf8decode(sp, 0, &l); if (fl_tolower(b)!=fl_tolower(s)) break; sp += l; bp = next_char(bp); } startPos = prev_char(startPos); } } return 0; } /* Insert a string into the buffer. Pos must be at a character boundary. Text must be a correct UTF-8 string. */ int Fl_Text_Buffer::insert_(int pos, const char *text, int insertedLength) { if (!text || !*text) return 0; if (insertedLength == -1) insertedLength = (int) strlen(text); /* Prepare the buffer to receive the new text. If the new text fits in the current buffer, just move the gap (if necessary) to where the text should be inserted. If the new text is too large, reallocate the buffer with a gap large enough to accomodate the new text and a gap of mPreferredGapSize */ if (insertedLength > mGapEnd - mGapStart) reallocate_with_gap(pos, insertedLength + mPreferredGapSize); else if (pos != mGapStart) move_gap(pos); /* Insert the new text (pos now corresponds to the start of the gap) */ memcpy(&mBuf[pos], text, insertedLength); mGapStart += insertedLength; mLength += insertedLength; update_selections(pos, 0, insertedLength); if (mCanUndo) { if (mUndo->undoat == pos && mUndo->undoinsert) { // continue inserting text at the given cursor position mUndo->undoinsert += insertedLength; } else { int yankcut = (mUndo->undoat == pos) ? mUndo->undocut : 0; if (!yankcut) { // insert text at a new position, so generate a new undo action mRedoList->clear(); mUndoList->push(mUndo); mUndo = new Fl_Text_Undo_Action(); } else { // we deleted and inserted at the same position, making this a yankcut } mUndo->undoinsert = insertedLength; mUndo->undoyankcut = yankcut; } mUndo->undoat = pos + insertedLength; mUndo->undocut = 0; } return insertedLength; } /* Remove a string from the buffer. Unicode safe. Start and end must be at a character boundary. Start must be less than end. */ void Fl_Text_Buffer::remove_(int start, int end) { if (start >= end) return; if (mCanUndo) { if (mUndo->undoat == end && mUndo->undocut) { // continue to remove text at the same cursor position mUndo->undobuffersize(mUndo->undocut + end - start + 1); memmove(mUndo->undobuffer + end - start, mUndo->undobuffer, mUndo->undocut); mUndo->undocut += end - start; } else { // remove text at a new position, so generate a new undo action mRedoList->clear(); mUndoList->push(mUndo); mUndo = new Fl_Text_Undo_Action(); mUndo->undocut = end - start; mUndo->undobuffersize(mUndo->undocut); } mUndo->undoat = start; mUndo->undoinsert = 0; mUndo->undoyankcut = 0; } if (start > mGapStart) { if (mCanUndo) memcpy(mUndo->undobuffer, mBuf + (mGapEnd - mGapStart) + start, end - start); move_gap(start); } else if (end < mGapStart) { if (mCanUndo) memcpy(mUndo->undobuffer, mBuf + start, end - start); move_gap(end); } else { int prelen = mGapStart - start; if (mCanUndo) { memcpy(mUndo->undobuffer, mBuf + start, prelen); memcpy(mUndo->undobuffer + prelen, mBuf + mGapEnd, end - start - prelen); } } /* expand the gap to encompass the deleted characters */ mGapEnd += end - mGapStart; mGapStart = start; /* update the length */ mLength -= end - start; /* fix up any selections which might be affected by the change */ update_selections(start, end - start, 0); } /** \brief Sets the selection range. \p startpos and \p endpos must be at a character boundary. If \p startpos != \p endpos selected() is set to true, else to false. If \p startpos is greater than \p endpos they are swapped so that \p startpos \<= \p endpos. \param[in] startpos byte offset to first selected character \param[in] endpos byte offset pointing after last selected character */ void Fl_Text_Selection::set(int startpos, int endpos) { mSelected = (startpos != endpos); mStart = min(startpos, endpos); mEnd = max(startpos, endpos); } /** \brief Returns the status and the positions of this selection. This method returns the same as \p selected() as an \p int (0 or 1) in its return value and the offsets to the start of the selection in \p startpos and to the byte after the last selected character in \p endpos, if selected() is \p true. If selected() is \p false, both offsets are set to 0. \note In FLTK 1.3.x \p startpos and \p endpos were \b not \b modified if selected() was false. \param startpos return byte offset to first selected character \param endpos return byte offset pointing after last selected character \return whether the selection is active (selected()) or not \retval 0 if not selected \retval 1 if selected \see selected(), start(), end() */ int Fl_Text_Selection::selected(int *startpos, int *endpos) const { if (!mSelected) { *startpos = 0; *endpos = 0; return 0; } *startpos = mStart; *endpos = mEnd; return 1; } /** Returns true if position \p pos is in the Fl_Text_Selection. \p pos must be at a character boundary. */ int Fl_Text_Selection::includes(int pos) const { return (selected() && pos >= start() && pos < end() ); } /* Return a duplicate of the selected text, or an empty string. Unicode safe. */ char *Fl_Text_Buffer::selection_text_(Fl_Text_Selection * sel) const { int start, end; /* If there's no selection, return an allocated empty string */ if (!sel->selected(&start, &end)) { char *s = (char *) malloc(1); *s = '\0'; return s; } /* Return the selected range */ return text_range(start, end); } /* Remove the selected text. Unicode safe. */ void Fl_Text_Buffer::remove_selection_(Fl_Text_Selection * sel) { int start, end; if (!sel->selected(&start, &end)) return; remove(start, end); //undoyankcut = undocut; } /* Replace selection with text. Unicode safe. */ void Fl_Text_Buffer::replace_selection_(Fl_Text_Selection * sel, const char *text) { Fl_Text_Selection oldSelection = *sel; /* If there's no selection, return */ int start, end; if (!sel->selected(&start, &end)) return; /* Do the appropriate type of replace */ replace(start, end, text); /* Unselect (happens automatically in BufReplace, but BufReplaceRect can't detect when the contents of a selection goes away) */ sel->mSelected = 0; redisplay_selection(&oldSelection, sel); } /* Call all callbacks. Unicode safe. */ void Fl_Text_Buffer::call_modify_callbacks(int pos, int nDeleted, int nInserted, int nRestyled, const char *deletedText) const { IS_UTF8_ALIGNED2(this, pos) for (int i = 0; i < mNModifyProcs; i++) (*mModifyProcs[i]) (pos, nInserted, nDeleted, nRestyled, deletedText, mCbArgs[i]); } /* Call all callbacks. Unicode safe. */ void Fl_Text_Buffer::call_predelete_callbacks(int pos, int nDeleted) const { for (int i = 0; i < mNPredeleteProcs; i++) (*mPredeleteProcs[i]) (pos, nDeleted, mPredeleteCbArgs[i]); } /* Redisplay a new selected area. Unicode safe. */ void Fl_Text_Buffer::redisplay_selection(Fl_Text_Selection * oldSelection, Fl_Text_Selection * newSelection) const { int oldStart, oldEnd, newStart, newEnd, ch1Start, ch1End, ch2Start, ch2End; /* If either selection is rectangular, add an additional character to the end of the selection to request the redraw routines to wipe out the parts of the selection beyond the end of the line */ oldStart = oldSelection->mStart; newStart = newSelection->mStart; oldEnd = oldSelection->mEnd; newEnd = newSelection->mEnd; /* If the old or new selection is unselected, just redisplay the single area that is (was) selected and return */ if (!oldSelection->mSelected && !newSelection->mSelected) return; if (!oldSelection->mSelected) { call_modify_callbacks(newStart, 0, 0, newEnd - newStart, NULL); return; } if (!newSelection->mSelected) { call_modify_callbacks(oldStart, 0, 0, oldEnd - oldStart, NULL); return; } /* If the selections are non-contiguous, do two separate updates and return */ if (oldEnd < newStart || newEnd < oldStart) { call_modify_callbacks(oldStart, 0, 0, oldEnd - oldStart, NULL); call_modify_callbacks(newStart, 0, 0, newEnd - newStart, NULL); return; } /* Otherwise, separate into 3 separate regions: ch1, and ch2 (the two changed areas), and the unchanged area of their intersection, and update only the changed area(s) */ ch1Start = min(oldStart, newStart); ch2End = max(oldEnd, newEnd); ch1End = max(oldStart, newStart); ch2Start = min(oldEnd, newEnd); if (ch1Start != ch1End) call_modify_callbacks(ch1Start, 0, 0, ch1End - ch1Start, NULL); if (ch2Start != ch2End) call_modify_callbacks(ch2Start, 0, 0, ch2End - ch2Start, NULL); } /* Move the gap around without changing buffer content. Unicode safe. Pos must be at a character boundary. */ void Fl_Text_Buffer::move_gap(int pos) { int gapLen = mGapEnd - mGapStart; if (pos > mGapStart) memmove(&mBuf[mGapStart], &mBuf[mGapEnd], pos - mGapStart); else memmove(&mBuf[pos + gapLen], &mBuf[pos], mGapStart - pos); mGapEnd += pos - mGapStart; mGapStart += pos - mGapStart; } /* Create a larger gap. Unicode safe. Start must be at a character boundary. */ void Fl_Text_Buffer::reallocate_with_gap(int newGapStart, int newGapLen) { char *newBuf = (char *) malloc(mLength + newGapLen); int newGapEnd = newGapStart + newGapLen; if (newGapStart <= mGapStart) { memcpy(newBuf, mBuf, newGapStart); memcpy(&newBuf[newGapEnd], &mBuf[newGapStart], mGapStart - newGapStart); memcpy(&newBuf[newGapEnd + mGapStart - newGapStart], &mBuf[mGapEnd], mLength - mGapStart); } else { /* newGapStart > mGapStart */ memcpy(newBuf, mBuf, mGapStart); memcpy(&newBuf[mGapStart], &mBuf[mGapEnd], newGapStart - mGapStart); memcpy(&newBuf[newGapEnd], &mBuf[mGapEnd + newGapStart - mGapStart], mLength - newGapStart); } free((void *) mBuf); mBuf = newBuf; mGapStart = newGapStart; mGapEnd = newGapEnd; } /* Update selection range if characters were inserted. Unicode safe. Pos must be at a character boundary. */ void Fl_Text_Buffer::update_selections(int pos, int nDeleted, int nInserted) { mPrimary.update(pos, nDeleted, nInserted); mSecondary.update(pos, nDeleted, nInserted); mHighlight.update(pos, nDeleted, nInserted); } /** \brief Updates a selection after text was modified. Updates an individual selection for changes in the corresponding text. \param pos byte offset into text buffer at which the change occurred \param nDeleted number of bytes deleted from the buffer \param nInserted number of bytes inserted into the buffer */ // unicode safe, assuming the arguments are on character boundaries void Fl_Text_Selection::update(int pos, int nDeleted, int nInserted) { if (!mSelected || pos > mEnd) return; if (pos + nDeleted <= mStart) { mStart += nInserted - nDeleted; mEnd += nInserted - nDeleted; } else if (pos <= mStart && pos + nDeleted >= mEnd) { mStart = pos; mEnd = pos; mSelected = 0; } else if (pos <= mStart && pos + nDeleted < mEnd) { mStart = pos; mEnd = nInserted + mEnd - nDeleted; } else if (pos < mEnd) { mEnd += nInserted - nDeleted; if (mEnd <= mStart) mSelected = 0; } } /* Find a UCS-4 character. StartPos must be at a character boundary, searchChar is UCS-4 encoded. */ int Fl_Text_Buffer::findchar_forward(int startPos, unsigned searchChar, int *foundPos) const { if (startPos >= mLength) { *foundPos = mLength; return 0; } if (startPos<0) startPos = 0; for ( ; startPos mLength) startPos = mLength; for (startPos = prev_char(startPos); startPos>=0; startPos = prev_char(startPos)) { if (searchChar == char_at(startPos)) { *foundPos = startPos; return 1; } } *foundPos = 0; return 0; } //#define EXAMPLE_ENCODING // shows how to process any encoding for which a decoding function exists #ifdef EXAMPLE_ENCODING // returns the UCS equivalent of *p in CP1252 and advances p by 1 unsigned cp1252toucs(char* &p) { // Codes 0x80..0x9f from the Microsoft CP1252 character set, translated // to Unicode static unsigned cp1252[32] = { 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f, 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178 }; unsigned char uc = *(unsigned char*)p; p++; return (uc < 0x80 || uc >= 0xa0 ? uc : cp1252[uc - 0x80]); } // returns the UCS equivalent of *p in UTF-16 and advances p by 2 (or more for surrogates) unsigned utf16toucs(char* &p) { union { #if WORDS_BIGENDIAN struct { unsigned char a, b;} chars; #else struct { unsigned char b, a;} chars; #endif U16 short_val; } u; u.chars.a = *(unsigned char*)p++; u.chars.b = *(unsigned char*)p++; return u.short_val; } // filter that produces, from an input stream fed by reading from fp, // a UTF-8-encoded output stream written in buffer. // Input can be any (e.g., 8-bit, UTF-16) encoding. // Output is true UTF-8. // p_trf points to a function that transforms encoded byte(s) into one UCS // and that increases the pointer by the adequate quantity static int general_input_filter(char *buffer, int buflen, char *line, int sline, char* &endline, unsigned (*p_trf)(char* &), FILE *fp) { char *p, *q, multibyte[5]; int lq, r, offset; p = line; q = buffer; while (q < buffer + buflen) { if (p >= endline) { r = fread(line, 1, sline, fp); endline = line + r; if (r == 0) return q - buffer; p = line; } if (q + 4 /*max width of UTF-8 char*/ > buffer + buflen) { memmove(line, p, endline - p); endline -= (p - line); return q - buffer; } lq = fl_utf8encode( p_trf(p), multibyte ); memcpy(q, multibyte, lq); q += lq; } memmove(line, p, endline - p); endline -= (p - line); return q - buffer; } #endif // EXAMPLE_ENCODING /* filter that produces, from an input stream fed by reading from fp, a UTF-8-encoded output stream written in buffer. Returns #bytes read into 'buffer'. Input can be UTF-8. If it is not, it is decoded with CP1252. Output is UTF-8. *input_was_changed returns true if input was not strict UTF-8, so output differs from input. */ static int utf8_input_filter(char *buffer, // result buffer we fill with utf8 encoded text int buflen, // max size of buffer from caller char *line, // file line buffer caller wants us to use int sline, // max size of line buffer char* &endline, // keeps track of leftovers in line[] buffer between calls FILE *fp, // open file we're reading data from int *input_was_changed) // returned flag: 'true' if buffer[] different from file due to utf8 encoding { // p - work pointer to line[] // q - work pointer to buffer[] // l - length of utf8 sequence being worked on // lp - fl_utf8decode() length of utf8 sequence being worked on // lq - fl_utf8encode() length of utf8 sequence being worked on // r - bytes read from last fread() // u - utf8 decoded sequence as a single multibyte unsigned integer char *p, *q, multibyte[5]; int l, lp, lq, r; unsigned u; p = line; q = buffer; while (q < buffer + buflen) { if (p >= endline) { // walked off end of input file's line buffer? r = (int) fread(line, 1, sline, fp); // read another block of sline bytes from file endline = line + r; if (r == 0) return (int) (q - buffer); // EOF? return bytes read into buffer[] p = line; } // Predict length of utf8 sequence // See if utf8 seq we're working on would extend off end of line buffer, // and if so, adjust + load more data so that it doesn't. // l = fl_utf8len1(*p); // anticipate length of utf8 sequence if (p + l > endline) { // would walk off end of line buffer? memmove(line, p, endline - p); // re-jigger line buffer to get some room endline -= (p - line); r = (int) fread(endline, 1, sline - (endline - line), fp); // re-fill line buffer endline += r; p = line; if (endline - line < l) break; // sequence *still* extends past end? stop loop } while ( l > 0) { u = fl_utf8decode(p, p+l, &lp); // get single utf8 encoded char as a Unicode value lq = fl_utf8encode(u, multibyte); // re-encode Unicode value to utf8 in multibyte[] if (lp != l || lq != l) *input_was_changed = true; if (q + lq > buffer + buflen) { // encoding would walk off end of buffer[]? memmove(line, p, endline - p); // re-jigger line[] buffer for next call endline -= (p - line); // adjust end of line[] buffer for next call return (int) (q - buffer); // return what's decoded so far, caller will consume buffer } memcpy(q, multibyte, lq); q += lq; p += lp; l -= lp; } } memmove(line, p, endline - p); endline -= (p - line); return (int) (q - buffer); } const char *Fl_Text_Buffer::file_encoding_warning_message = "Displayed text contains the UTF-8 transcoding\n" "of the input file which was not UTF-8 encoded.\n" "Some changes may have occurred."; /* Insert text from a file. Input file can be of various encodings according to what input fiter is used. utf8_input_filter accepts UTF-8 or CP1252 as input encoding. Output is always UTF-8. */ int Fl_Text_Buffer::insertfile(const char *file, int pos, int buflen) { FILE *fp; if (!(fp = fl_fopen(file, "r"))) return 1; char *buffer = new char[buflen + 1]; char *endline, line[100]; int l; input_file_was_transcoded = false; endline = line; while (true) { #ifdef EXAMPLE_ENCODING // example of 16-bit encoding: UTF-16 l = general_input_filter(buffer, buflen, line, sizeof(line), endline, utf16toucs, // use cp1252toucs to read CP1252-encoded files fp); input_file_was_transcoded = true; #else l = utf8_input_filter(buffer, buflen, line, sizeof(line), endline, fp, &input_file_was_transcoded); #endif if (l == 0) break; buffer[l] = 0; insert(pos, buffer); pos += l; } int e = ferror(fp) ? 2 : 0; fclose(fp); delete[]buffer; if ( (!e) && input_file_was_transcoded && transcoding_warning_action) { transcoding_warning_action(this); } return e; } /* Write text to file. Unicode safe. */ int Fl_Text_Buffer::outputfile(const char *file, int start, int end, int buflen) { FILE *fp; if (!(fp = fl_fopen(file, "w"))) return 1; for (int n; (n = min(end - start, buflen)); start += n) { const char *p = text_range(start, start + n); int r = (int) fwrite(p, 1, n, fp); free((void *) p); if (r != n) break; } int e = ferror(fp) ? 2 : 0; fclose(fp); return e; } /* Return the previous character position. Unicode safe. */ int Fl_Text_Buffer::prev_char_clipped(int pos) const { if (pos<=0) return 0; IS_UTF8_ALIGNED2(this, (pos)) char c; do { pos--; if (pos==0) return 0; c = byte_at(pos); } while ( (c&0xc0) == 0x80); IS_UTF8_ALIGNED2(this, (pos)) return pos; } /* Return the previous character position. Returns -1 if the beginning of the buffer is reached. */ int Fl_Text_Buffer::prev_char(int pos) const { if (pos==0) return -1; return prev_char_clipped(pos); } /* Return the next character position. Returns length() if the end of the buffer is reached. */ int Fl_Text_Buffer::next_char(int pos) const { IS_UTF8_ALIGNED2(this, (pos)) int n = fl_utf8len1(byte_at(pos)); pos += n; if (pos>=mLength) return mLength; IS_UTF8_ALIGNED2(this, (pos)) return pos; } /* Return the next character position. If the end of the buffer is reached, it returns the current position. */ int Fl_Text_Buffer::next_char_clipped(int pos) const { return next_char(pos); } /* Align an index to the current UTF-8 boundary. */ int Fl_Text_Buffer::utf8_align(int pos) const { char c = byte_at(pos); while ( (c&0xc0) == 0x80) { pos--; c = byte_at(pos); } return pos; } fltk-1.4.3/src/Fl_arg.cxx0000644000175000017500000002623415004135251015321 0ustar albrechtalbrecht// // Optional argument initialization code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // OPTIONAL initialization code for a program using FLTK. // You do not need to call this! Feel free to make up your own switches. #include #include #include #include "Fl_Window_Driver.H" #include "Fl_System_Driver.H" #include "Fl_Screen_Driver.H" #include static int fl_match(const char *a, const char *s, int atleast = 1) { const char *b = s; while (*a && (*a == *b || tolower(*a) == *b)) {a++; b++;} return !*a && b >= s+atleast; } // flags set by previously parsed arguments: static char arg_called; static char return_i; static const char *name; static const char *geometry; static const char *title; // these are in Fl_get_system_colors and are set by the switches: extern const char *fl_fg; extern const char *fl_bg; extern const char *fl_bg2; /** Parse a single switch from \p argv, starting at word \p i. Returns the number of words eaten (1 or 2, or 0 if it is not recognized) and adds the same value to \p i. This is the default argument handler used internally by Fl::args(...), but you can use this function if you prefer to step through the standard FLTK switches yourself. All standard FLTK switches except -bg2 may be abbreviated to just one letter and case is ignored: \li -bg color or -background color
Sets the background color using Fl::background(). \li -bg2 color or -background2 color
Sets the secondary background color using Fl::background2(). \li -display host:n.n
Sets the X display to use; this option is silently ignored under Windows and MacOS. \li -dnd and -nodnd
Enables or disables drag and drop text operations using Fl::dnd_text_ops(). \li -fg color or -foreground color
Sets the foreground color using Fl::foreground(). \li -geometry WxH+X+Y
Sets the initial window position and size according to the standard X geometry string. \li -iconic
Iconifies the window using Fl_Window::iconize(). \li -kbd and -nokbd
Enables or disables visible keyboard focus for non-text widgets using Fl::visible_focus(). \li -name string
Sets the window class using Fl_Window::xclass(). \li -scheme string
Sets the widget scheme using Fl::scheme(). \li -title string
Sets the window title using Fl_Window::label(). \li -tooltips and -notooltips
Enables or disables tooltips using Fl_Tooltip::enable(). Color values are commonly given as three digit or six digit hex numbers. - The order of fg, bg, and bg2 in the command line does not matter - There is no way at the moment to set the selection color. - Setting the bg2 color also changes the fg color to have sufficient contrast - Explicitly setting fg color overrides the bg2/contrast constraint. - Setting the bg color will update the color lookup table for the gray ramp, so color index values can stay the same for all apps, it's just mapped to different RGB values. - The calculation of the gray ramp is only based on the bg color, so there is no way at the moment to create an inverted (dark mode) ramp. - Consequently, setting bg to black creates a an all-black ramp, setting a somewhat dark bg color creates a extremely dark ramp. - Setting the bg has no influence on bg2 or fg. If your program requires other switches in addition to the standard FLTK options, you will need to pass your own argument handler to Fl::args(int,char**,int&,Fl_Args_Handler) explicitly. \see \ref fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b) to see how color values can be defined */ int Fl::arg(int argc, char **argv, int &i) { arg_called = 1; const char *s = argv[i]; if (!s) {i++; return 1;} // something removed by calling program? // a word that does not start with '-', or a word after a '--', or // the word '-' by itself all start the "non-switch arguments" to // a program. Return 0 to indicate that we don't understand the // word, but set a flag (return_i) so that args() will return at // that point: if (s[0] != '-' || s[1] == '-' || !s[1]) {return_i = 1; return 0;} s++; // point after the dash if (fl_match(s, "iconic")) { Fl_Window::show_next_window_iconic(1); i++; return 1; } else if (fl_match(s, "kbd")) { Fl::visible_focus(1); i++; return 1; } else if (fl_match(s, "nokbd", 3)) { Fl::visible_focus(0); i++; return 1; } else if (fl_match(s, "dnd", 2)) { Fl::dnd_text_ops(1); i++; return 1; } else if (fl_match(s, "nodnd", 3)) { Fl::dnd_text_ops(0); i++; return 1; } else if (fl_match(s, "tooltips", 2)) { Fl_Tooltip::enable(); i++; return 1; } else if (fl_match(s, "notooltips", 3)) { Fl_Tooltip::disable(); i++; return 1; } else if (Fl::system_driver()->single_arg(s)) { i++; return 1; } const char *v = argv[i+1]; if (i >= argc-1 || !v) return 0; // all the rest need an argument, so if missing it is an error if (fl_match(s, "geometry")) { int flags, gx, gy; unsigned int gw, gh; flags = Fl::screen_driver()->XParseGeometry(v, &gx, &gy, &gw, &gh); if (!flags) return 0; geometry = v; } else if (fl_match(s, "display", 2)) { Fl::screen_driver()->display(v); } else if (Fl::system_driver()->arg_and_value(s, v)) { // nothing to do } else if (fl_match(s, "title", 2)) { title = v; } else if (fl_match(s, "name", 2)) { name = v; } else if (fl_match(s, "bg2", 3) || fl_match(s, "background2", 11)) { fl_bg2 = v; } else if (fl_match(s, "bg", 2) || fl_match(s, "background", 10)) { fl_bg = v; } else if (fl_match(s, "fg", 2) || fl_match(s, "foreground", 10)) { fl_fg = v; } else if (fl_match(s, "scheme", 1)) { Fl::scheme(v); } else { return 0; // unrecognized } i += 2; return 2; } /** Parse command line switches using the \p cb argument handler. Returns 0 on error, or the number of words processed. FLTK provides this as an entirely optional command line switch parser. You don't have to call it if you don't want to. Everything it can do can be done with other calls to FLTK. To use the switch parser, call Fl::args(...) near the start of your program. This does \b not open the display, instead switches that need the display open are stashed into static variables. Then you \b must display your first window by calling window->show(argc,argv), which will do anything stored in the static variables. Providing an argument handler callback \p cb lets you define your own switches. It is called with the same \p argc and \p argv, and with \p i set to the index of the switch to be processed. The \p cb handler should return zero if the switch is unrecognized, and not change \p i. It should return non-zero to indicate the number of words processed if the switch is recognized, i.e. 1 for just the switch, and more than 1 for the switch plus associated parameters. \p i should be incremented by the same amount. The \p cb handler is called \b before any other tests, so you can also override any standard FLTK switch (this is why FLTK can use very short switches instead of the long ones all other toolkits force you to use). See Fl::arg() for descriptions of the standard switches. On return \p i is set to the index of the first non-switch. This is either: \li The first word that does not start with '-'. \li The word '-' (used by many programs to name stdin as a file) \li The first unrecognized switch (return value is 0). \li \p argc The return value is \p i unless an unrecognized switch is found, in which case it is zero. If your program takes no arguments other than switches you should produce an error if the return value is less than \p argc. A usage string is displayed if Fl::args() detects an invalid argument on the command-line. You can change the message by setting the Fl::help pointer. A very simple command line parser can be found in examples/howto-parse-args.cxx The simpler Fl::args(int argc, char **argv) form is useful if your program does not have command line switches of its own. */ int Fl::args(int argc, char** argv, int& i, Fl_Args_Handler cb) { arg_called = 1; i = 1; // skip argv[0] while (i < argc) { if (cb && cb(argc,argv,i)) continue; if (!arg(argc,argv,i)) return return_i ? i : 0; } return i; } // show a main window, use any parsed arguments void Fl_Window::show(int argc, char **argv) { if (argc && !arg_called) Fl::args(argc,argv); Fl::get_system_colors(); pWindowDriver->show_with_args_begin(); // note: background_pixel is no longer used since 1.4.0, but anyway ... // set colors first, so background_pixel is correct: static char beenhere = 0; if (!beenhere) { if (geometry) { int fl = 0, gx = x(), gy = y(); unsigned int gw = w(), gh = h(); fl = Fl::screen_driver()->XParseGeometry(geometry, &gx, &gy, &gw, &gh); if (fl & Fl_Screen_Driver::fl_XNegative) gx = Fl::w()-w()+gx; if (fl & Fl_Screen_Driver::fl_YNegative) gy = Fl::h()-h()+gy; // int mw,mh; minsize(mw,mh); // if (mw > gw) gw = mw; // if (mh > gh) gh = mh; Fl_Widget *r = resizable(); if (!r) resizable(this); // for Windows we assume window is not mapped yet: if (fl & (Fl_Screen_Driver::fl_XValue | Fl_Screen_Driver::fl_YValue)) x(-1), resize(gx,gy,gw,gh); else size(gw,gh); resizable(r); } } // set the class, which is used by X version of get_system_colors: if (name) {xclass(name); name = 0;} else if (!xclass() || !strcmp(xclass(),"FLTK")) xclass(fl_filename_name(argv[0])); if (title) {label(title); title = 0;} else if (!label()) label(xclass()); if (!beenhere) { beenhere = 1; Fl::scheme(Fl::scheme()); // opens display! May call Fl::fatal() } // Show the window AFTER we have set the colors and scheme. show(); pWindowDriver->show_with_args_end(argc, argv); } // Calls useful for simple demo programs, with automatic help message: static const char * const helpmsg = "options are:\n" " -bg2 color\n" " -bg color\n" " -di[splay] host:n.n\n" " -dn[d]\n" " -fg color\n" " -g[eometry] WxH+X+Y\n" " -i[conic]\n" " -k[bd]\n" " -na[me] classname\n" " -nod[nd]\n" " -nok[bd]\n" " -not[ooltips]\n" " -s[cheme] scheme\n" " -ti[tle] windowtitle\n" " -to[oltips]"; const char * const Fl::help = helpmsg+13; /** Parse all command line switches matching standard FLTK options only. It parses all the switches, and if any are not recognized it calls Fl::abort(Fl::help), i.e. unlike the long form, an unrecognized switch generates an error message and causes the program to exit. */ void Fl::args(int argc, char **argv) { int i; if (Fl::args(argc,argv,i) < argc) Fl::error(helpmsg); } fltk-1.4.3/src/fl_labeltype.cxx0000644000175000017500000001116515004135251016566 0ustar albrechtalbrecht// // Label drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Drawing code for the (one) common label types. // Other label types (symbols) are in their own source files // to avoid linking if not used. #include #include #include #include #include void fl_no_label(const Fl_Label*,int,int,int,int,Fl_Align) {} void fl_normal_label(const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align) { fl_font(o->font, o->size); fl_color((Fl_Color)o->color); fl_draw(o->value, X, Y, W, H, align, o->image, 1, o->spacing); } void fl_normal_measure(const Fl_Label* o, int& W, int& H) { fl_font(o->font, o->size); fl_measure(o->value, W, H); if (o->image) { int iw = o->image->w(), ih = o->image->h(); if (o->align_ & FL_ALIGN_IMAGE_BACKDROP) { // backdrop: ignore // ignore backdrop image for calculation } else if (o->align_ & FL_ALIGN_IMAGE_NEXT_TO_TEXT) { // text and image side by side W += iw + o->spacing; if (ih > H) H = ih; } else { if (iw > W) W = iw; H += ih + o->spacing; } } } #define MAX_LABELTYPE 16 static Fl_Label_Draw_F* table[MAX_LABELTYPE] = { fl_normal_label, fl_no_label, fl_normal_label, // _FL_SHADOW_LABEL, fl_normal_label, // _FL_ENGRAVED_LABEL, fl_normal_label, // _FL_EMBOSSED_LABEL, fl_no_label, // _FL_MULTI_LABEL, fl_no_label, // _FL_ICON_LABEL, // FL_FREE_LABELTYPE+n: fl_no_label, fl_no_label, fl_no_label, fl_no_label, fl_no_label, fl_no_label, fl_no_label, fl_no_label, fl_no_label }; static Fl_Label_Measure_F* measure[MAX_LABELTYPE]; /** Sets the functions to call to draw and measure a specific labeltype. */ void Fl::set_labeltype(Fl_Labeltype t,Fl_Label_Draw_F* f,Fl_Label_Measure_F*m) { table[t] = f; measure[t] = m; } //////////////////////////////////////////////////////////////// /** Draws a label with arbitrary alignment in an arbitrary box. */ void Fl_Label::draw(int X, int Y, int W, int H, Fl_Align align) const { if (!value && !image) return; switch (align&(FL_ALIGN_TOP|FL_ALIGN_BOTTOM)) { case 0: Y += v_margin_; H -= 2*v_margin_; break; case FL_ALIGN_TOP: Y += v_margin_; H -= v_margin_; break; case FL_ALIGN_BOTTOM: H -= v_margin_; break; } switch (align&(FL_ALIGN_LEFT|FL_ALIGN_RIGHT)) { case 0: X += h_margin_; W -= 2*h_margin_; break; case FL_ALIGN_LEFT: X += h_margin_; W -= h_margin_; break; case FL_ALIGN_RIGHT: W -= h_margin_; break; } table[type](this, X, Y, W, H, align); } /** Measures the size of the label. \param[in,out] W, H : this is the requested size for the label text plus image; on return, this will contain the size needed to fit the label */ void Fl_Label::measure(int& W, int& H) const { if (!value && !image) { W = H = 0; return; } // if (W > 0) W -= h_margin_; Fl_Label_Measure_F* f = ::measure[type]; if (!f) f = fl_normal_measure; f(this, W, H); } /** Draws the widget's label at the defined label position. This is the normal call for a widget's draw() method. */ void Fl_Widget::draw_label() const { int X = x_+Fl::box_dx(box()); int W = w_-Fl::box_dw(box()); if (W > 11 && align()&(FL_ALIGN_LEFT|FL_ALIGN_RIGHT)) {X += 3; W -= 6;} draw_label(X, y_+Fl::box_dy(box()), W, h_-Fl::box_dh(box())); } /** Draws the label in an arbitrary bounding box. draw() can use this instead of draw_label(void) to change the bounding box */ void Fl_Widget::draw_label(int X, int Y, int W, int H) const { // quit if we are not drawing a label inside the widget: if ((align()&15) && !(align() & FL_ALIGN_INSIDE)) return; draw_label(X,Y,W,H,align()); } /** Draws the label in an arbitrary bounding box with an arbitrary alignment. Anybody can call this to force the label to draw anywhere. */ void Fl_Widget::draw_label(int X, int Y, int W, int H, Fl_Align a) const { if (flags()&SHORTCUT_LABEL) fl_draw_shortcut = 1; Fl_Label l1 = label_; if (!active_r()) { l1.color = fl_inactive((Fl_Color)l1.color); if (l1.deimage) l1.image = l1.deimage; } l1.draw(X,Y,W,H,a); fl_draw_shortcut = 0; } // include these vars here so they can be referenced without including // Fl_Input_ code: #include fltk-1.4.3/src/fl_draw_pixmap.cxx0000644000175000017500000001603715004135251017123 0ustar albrechtalbrecht// // Pixmap drawing code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2018 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // NOTE: I believe many of the following comments (between the dash markers) // are no longer accurate: // -------------------------------------------------------------------- // Implemented without using the xpm library (which I can't use because // it interferes with the color cube used by fl_draw_image). // Current implementation is cheap and slow, and works best on a full-color // display. Transparency is not handled, and colors are dithered to // the color cube. Color index is achieved by adding the id // characters together! Also mallocs a lot of temporary memory! // Notice that there is no pixmap file interface. This is on purpose, // as I want to discourage programs that require support files to work. // All data needed by a program ui should be compiled in!!! // -------------------------------------------------------------------- // The above comments were checked in as r2, and much has changed since then; // transparency added, color cube not required, etc. -erco Oct 20 2013 #include #include #include "Fl_System_Driver.H" #include #include #include #include "flstring.h" static int ncolors, chars_per_pixel; typedef struct { uchar r; uchar g; uchar b; } UsedColor; static UsedColor *used_colors; static int color_count; // # of non-transparent colors used in pixmap /** Get the dimensions of a pixmap. An XPM image contains the dimensions in its data. This function returns the width and height. \param[in] data pointer to XPM image data. \param[out] w,h width and height of image \returns non-zero if the dimensions were parsed OK \returns 0 if there were any problems */ int fl_measure_pixmap(/*const*/ char* const* data, int &w, int &h) { return fl_measure_pixmap((const char*const*)data,w,h); } /** Get the dimensions of a pixmap. \see fl_measure_pixmap(char* const* data, int &w, int &h) */ int fl_measure_pixmap(const char * const *cdata, int &w, int &h) { int i = sscanf(cdata[0],"%d%d%d%d",&w,&h,&ncolors,&chars_per_pixel); if (i<4 || w<=0 || h<=0 || (chars_per_pixel!=1 && chars_per_pixel!=2) ) return w=0; return 1; } int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg) { int w, h; const uchar*const* data = (const uchar*const*)(cdata+1); uchar *transparent_c = (uchar *)0; // such that transparent_c[0,1,2] are the RGB of the transparent color if (!fl_measure_pixmap(cdata, w, h)) return 0; if ((chars_per_pixel < 1) || (chars_per_pixel > 2)) return 0; typedef uchar uchar4[4]; uchar4 *colors = new uchar4[ int(1<<(chars_per_pixel*8)) ]; if (Fl_Graphics_Driver::need_pixmap_bg_color) { color_count = 0; used_colors = (UsedColor*)malloc(abs(ncolors) * sizeof(UsedColor)); } if (ncolors < 0) { // FLTK (non standard) compressed colormap ncolors = -ncolors; const uchar *p = *data++; // if first color is ' ' it is transparent (put it later to make // it not be transparent): if (*p == ' ') { uchar* c = colors[(int)' ']; Fl::get_color(bg, c[0], c[1], c[2]); c[3] = 0; if (Fl_Graphics_Driver::need_pixmap_bg_color) transparent_c = c; p += 4; ncolors--; } // read all the rest of the colors: for (int i=0; i < ncolors; i++) { uchar* c = colors[*p++]; if (Fl_Graphics_Driver::need_pixmap_bg_color) { used_colors[color_count].r = *(p+0); used_colors[color_count].g = *(p+1); used_colors[color_count].b = *(p+2); color_count++; } *c++ = *p++; *c++ = *p++; *c++ = *p++; *c = 255; } } else { // normal XPM colormap with names for (int i=0; i1) ind = (ind<<8)|*p++; c = colors[ind]; // look for "c word", or last word if none: const uchar *previous_word = p; for (;;) { while (*p && isspace(*p)) p++; uchar what = *p++; while (*p && !isspace(*p)) p++; while (*p && isspace(*p)) p++; if (!*p) {p = previous_word; break;} if (what == 'c') break; previous_word = p; while (*p && !isspace(*p)) p++; } int parse = fl_parse_color((const char*)p, c[0], c[1], c[2]); c[3] = 255; if (parse) { if (Fl_Graphics_Driver::need_pixmap_bg_color) { used_colors[color_count].r = c[0]; used_colors[color_count].g = c[1]; used_colors[color_count].b = c[2]; color_count++; } } else { // assume "None" or "#transparent" for any errors // "bg" should be transparent... Fl::get_color(bg, c[0], c[1], c[2]); //uchar **m = fl_graphics_driver->mask_bitmap(); c[3] = /*(m && !*m) ? 255 :*/ 0; if (Fl_Graphics_Driver::need_pixmap_bg_color) transparent_c = c; } // if parse } // for ncolors } // if ncolors if (Fl_Graphics_Driver::need_pixmap_bg_color) { if (transparent_c) { fl_graphics_driver->make_unused_color_(transparent_c[0], transparent_c[1], transparent_c[2], color_count, (void**)&used_colors); } else { uchar r, g, b; fl_graphics_driver->make_unused_color_(r, g, b, color_count, (void**)&used_colors); } } U32 *q = (U32*)out; for (int Y = 0; Y < h; Y++) { const uchar* p = data[Y]; if (chars_per_pixel <= 1) { for (int X = 0; X < w; X++) memcpy(q++, colors[*p++], 4); } else { for (int X = 0; X < w; X++) { int ind = (*p++)<<8; ind |= *p++; memcpy(q++, colors[ind], 4); } } } delete[] colors; return 1; } int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) { int w, h; if (!fl_measure_pixmap(cdata, w, h)) return 0; uchar *buffer = new uchar[w*h*4]; if (!fl_convert_pixmap(cdata, buffer, bg)) { delete[] buffer; return 0; } // build the mask bitmap used by Fl_Pixmap: uchar **p = fl_graphics_driver->mask_bitmap(); if (p && *p) { int W = (w+7)/8; uchar* bitmap = new uchar[W * h]; *p = bitmap; const uchar *alphaPtr = &buffer[3]; uchar b = 0; for (int Y = 0; Y < h; Y++) { b = 0; for (int X = 0, bit = 1; X < w; X++, alphaPtr += 4) { if (*alphaPtr > 127) b |= bit; bit <<= 1; if (bit > 0x80 || X == w-1) { *bitmap++ = b; bit = 1; b = 0; } } // if chars_per_pixel } // for Y } fl_graphics_driver->draw_image(buffer, x, y, w, h, 4); delete[] buffer; return 1; } fltk-1.4.3/src/Fl_Help_Dialog.fl0000644000175000017500000001530115004135251016507 0ustar albrechtalbrecht# data file for the Fltk User Interface Designer (fluid) version 1.0403 header_name {../FL/Fl_Help_Dialog.H} code_name {.cxx} comment {// // Fl_Help_Dialog dialog for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // ======================================================================== // DO NOT EDIT FL/Fl_Help_Dialog.H and src/Fl_Help_Dialog.cxx !!! // ======================================================================== // Please use fluid to change src/Fl_Help_Dialog.fl interactively // and then use fluid to "write code" or edit and use fluid -c . // ======================================================================== // } {in_source in_header } decl {\#include } {private local } decl {\#include "flstring.h"} {private local } decl {\#include } {private local } class FL_EXPORT Fl_Help_Dialog {open } { decl {int index_;} {private local } decl {int max_;} {private local } decl {int line_[100]; // FIXME: we must remove those static numbers} {private local } decl {char file_[100][FL_PATH_MAX]; // FIXME: we must remove those static numbers} {private local } decl {int find_pos_;} {private local } Function {Fl_Help_Dialog()} {} { Fl_Window window_ { label {Help Dialog} open private xywh {398 64 530 385} type Double hide resizable size_range {260 150 0 0} } { Fl_Group {} {open xywh {10 10 511 25} } { Fl_Button back_ { label {@<-} callback {if (index_ > 0) index_ --; if (index_ == 0) back_->deactivate(); forward_->activate(); int l = line_[index_]; if (strcmp(view_->filename(), file_[index_]) != 0) view_->load(file_[index_]); view_->topline(l);} private tooltip {Show the previous help page.} xywh {10 10 25 25} shortcut 0xff51 labelcolor 2 } Fl_Button forward_ { label {@->} callback {if (index_ < max_) index_ ++; if (index_ >= max_) forward_->deactivate(); back_->activate(); int l = view_->topline(); if (strcmp(view_->filename(), file_[index_]) != 0) view_->load(file_[index_]); view_->topline(l);} private tooltip {Show the next help page.} xywh {45 10 25 25} shortcut 0xff53 labelcolor 2 } Fl_Button smaller_ { label F callback {if (view_->textsize() > 8) view_->textsize(view_->textsize() - 2); if (view_->textsize() <= 8) smaller_->deactivate(); larger_->activate();} private tooltip {Make the help text smaller.} xywh {80 10 25 25} labelfont 1 labelsize 10 } Fl_Button larger_ { label F callback {if (view_->textsize() < 18) view_->textsize(view_->textsize() + 2); if (view_->textsize() >= 18) larger_->deactivate(); smaller_->activate();} private tooltip {Make the help text larger.} xywh {115 10 25 25} labelfont 1 labelsize 16 } Fl_Group {} {open xywh {350 10 171 25} box DOWN_BOX color 7 } { Fl_Input find_ { label {@search} callback {find_pos_ = view_->find(find_->value(), find_pos_);} private tooltip {find text in document} xywh {375 12 143 21} box FLAT_BOX labelsize 13 when 10 textfont 4 } } Fl_Box {} { xywh {150 10 190 25} resizable } } Fl_Help_View view_ { callback {if (view_->filename()) { if (view_->changed()) { index_ ++; if (index_ >= 100) { memmove(line_, line_ + 10, sizeof(line_[0]) * 90); memmove(file_, file_ + 10, sizeof(file_[0]) * 90); index_ -= 10; } max_ = index_; strlcpy(file_[index_], view_->filename(),sizeof(file_[0])); line_[index_] = view_->topline(); if (index_ > 0) back_->activate(); else back_->deactivate(); forward_->deactivate(); window_->label(view_->title()); } else // if ! view_->changed() { strlcpy(file_[index_], view_->filename(), sizeof(file_[0])); line_[index_] = view_->topline(); } } else { // if ! view_->filename() index_ = 0; // hitting an internal page will disable the back/fwd buffer file_[index_][0] = 0; // unnamed internal page line_[index_] = view_->topline(); back_->deactivate(); forward_->deactivate(); }} private xywh {10 45 510 330} box DOWN_BOX resizable } } code {back_->deactivate(); forward_->deactivate(); index_ = -1; max_ = 0; find_pos_ = 0; fl_register_images();} {} } Function {~Fl_Help_Dialog()} {} { code {delete window_;} {} } Function {h()} {return_type int } { code {return (window_->h());} {} } Function {hide()} {return_type void } { code {window_->hide();} {} } Function {load(const char *f)} {open return_type int } { code {view_->set_changed(); int ret = view_->load(f); window_->label(view_->title()); return ret;} {} } Function {position(int xx, int yy)} {return_type void } { code {window_->position(xx, yy);} {} } Function {resize(int xx, int yy, int ww, int hh)} {return_type void } { code {window_->resize(xx, yy, ww, hh);} {} } Function {show()} {return_type void } { code {window_->show();} {} } Function {show(int argc, char **argv)} {return_type void } { code {window_->show(argc, argv);} {} } Function {textsize(Fl_Fontsize s)} {return_type void } { code {view_->textsize(s); if (s <= 8) smaller_->deactivate(); else smaller_->activate(); if (s >= 18) larger_->deactivate(); else larger_->activate();} {} } Function {textsize()} {return_type Fl_Fontsize } { code {return (view_->textsize());} {} } Function {topline(const char *n)} {return_type void } { code {view_->topline(n);} {} } Function {topline(int n)} {selected return_type void } { code {view_->topline(n);} {} } Function {value(const char *f)} {return_type void } { code {view_->set_changed(); view_->value(f); window_->label(view_->title());} {} } Function {value() const} {return_type {const char *} } { code {return view_->value();} {} } Function {visible()} {return_type int } { code {return (window_->visible());} {} } Function {w()} {return_type int } { code {return (window_->w());} {} } Function {x()} {return_type int } { code {return (window_->x());} {} } Function {y()} {return_type int } { code {return (window_->y());} {} } } fltk-1.4.3/src/fl_file_dir.cxx0000644000175000017500000001465315004135251016367 0ustar albrechtalbrecht// // File chooser widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2015 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include "flstring.h" #include #include #include static Fl_File_Chooser *fc = (Fl_File_Chooser *)0; static void (*current_callback)(const char*) = 0; static const char *current_label = fl_ok; // Do a file chooser callback... static void callback(Fl_File_Chooser *, void*) { if (current_callback && fc->value()) (*current_callback)(fc->value()); } // Pop up a file chooser dialog window and wait until it is closed... static void popup(Fl_File_Chooser *filechooser) { filechooser->show(); // deactivate Fl::grab(), because it is incompatible with modal windows Fl_Window* g = Fl::grab(); if (g) Fl::grab(0); while (filechooser->shown()) Fl::wait(); if (g) // regrab the previous popup menu, if there was one Fl::grab(g); } /** \addtogroup group_comdlg @{ */ /** Set the file chooser callback \note \#include \relates Fl_File_Chooser */ void fl_file_chooser_callback(void (*cb)(const char*)) { current_callback = cb; } /** Set the "OK" button label \note \#include \relates Fl_File_Chooser */ void fl_file_chooser_ok_label(const char *l) { if (l) current_label = l; else current_label = fl_ok; } /** Shows a file chooser dialog and gets a filename. \note \#include \image html Fl_File_Chooser.jpg \image latex Fl_File_Chooser.jpg "Fl_File_Chooser" width=12cm \param[in] message text in title bar \param[in] pat filename pattern filter \param[in] fname initial/default filename selection \param[in] relative 0 for absolute path name, relative path name otherwise \return the user selected filename, in absolute or relative format or NULL if user cancels \relates Fl_File_Chooser */ char * // O - Filename or NULL fl_file_chooser(const char *message, // I - Message in titlebar const char *pat, // I - Filename pattern const char *fname, // I - Initial filename selection int relative) { // I - 0 for absolute path static char retname[FL_PATH_MAX]; // Returned filename if (!fc) { // first time, so create file chooser, remember pointer, // and if no filename given, set it to current directory if (!fname || !*fname) fname = "."; fc = new Fl_File_Chooser(fname, pat, Fl_File_Chooser::CREATE, message); fc->callback(callback, 0); } else { // file chooser exists, so check old/new directory, pattern, filename fc->type(Fl_File_Chooser::CREATE); // see, if we use the same pattern between calls char same_pattern = 0; const char *fcf = fc->filter(); if ( fcf && pat && strcmp(fcf, pat)==0) same_pattern = 1; else if ( (fcf==0L || *fcf==0) && (pat==0L || *pat==0) ) same_pattern = 1; // now set the pattern to the new pattern (even if they are the same) fc->filter(pat); fc->label(message); if (!fname) { // new filename is null, so reuse old one if pattern unchanged if (!same_pattern && fc->value()) { // if pattern is different, remove name but leave old directory: strlcpy(retname, fc->value(), sizeof(retname)); char *p = strrchr(retname, '/'); if (p) { // If old filename as "/foo", then directory will be "/", not "" if (p == retname) retname[1] = '\0'; else *p = '\0'; } // Set the directory... fc->value(retname); } else { // re-use the previously selected name } } else if (!*fname) { // new filename is empty, so reuse old directory with empty file const char *fcv = fc->value(); if (fcv) strlcpy(retname, fc->value(), sizeof(retname)); else *retname = 0; const char *n = fl_filename_name(retname); if (n) *((char*)n) = 0; // retname is either old directory, or empty if user cancelled if (*retname) { fc->value(""); fc->directory(retname); // reset old directory } else { char dirsave[FL_PATH_MAX]; strlcpy(dirsave, fc->directory(), sizeof(dirsave)); fc->value(""); // also resets directory to "system default" fc->directory(dirsave); // so reset directory back where we were } } else { fc->value(fname); } } // end [re]initialization fc->ok_label(current_label); popup(fc); if (fc->value() && relative) { fl_filename_relative(retname, sizeof(retname), fc->value()); return retname; } else if (fc->value()) return (char *)fc->value(); else return 0; } /** Shows a file chooser dialog and gets a directory. \note \#include \param[in] message title bar text \param[in] fname initial/default directory name \param[in] relative 0 for absolute path return, relative otherwise \return the directory path string chosen by the user or NULL if user cancels \relates Fl_File_Chooser */ char * // O - Directory or NULL fl_dir_chooser(const char *message, // I - Message for titlebar const char *fname, // I - Initial directory name int relative) // I - 0 for absolute { static char retname[FL_PATH_MAX]; // Returned directory name if (!fc) { if (!fname || !*fname) fname = "."; fc = new Fl_File_Chooser(fname, "*", Fl_File_Chooser::CREATE | Fl_File_Chooser::DIRECTORY, message); fc->callback(callback, 0); } else { fc->type(Fl_File_Chooser::CREATE | Fl_File_Chooser::DIRECTORY); fc->filter("*"); if (fname && *fname) fc->value(fname); fc->label(message); } popup(fc); if (fc->value() && relative) { fl_filename_relative(retname, sizeof(retname), fc->value()); return retname; } else if (fc->value()) return (char *)fc->value(); else return 0; } /** @} */ fltk-1.4.3/src/fl_overlay.cxx0000644000175000017500000001171615004135251016270 0ustar albrechtalbrecht// // Overlay support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Extremely limited "overlay" support. You can use this to drag out // a rectangle in response to mouse events. It is your responsibility // to erase the overlay before drawing anything that might intersect // it. #include #include #include static int px,py,pw,ph; #include #include "Fl_Screen_Driver.H" #include static Fl_RGB_Image *s_bgN = 0, *s_bgS = 0, *s_bgE = 0, *s_bgW = 0; static int bgx, bgy, bgw, bgh; static void draw_current_rect() { if (s_bgN) { delete s_bgN; s_bgN = 0; } if (s_bgS) { delete s_bgS; s_bgS = 0; } if (s_bgE) { delete s_bgE; s_bgE = 0; } if (s_bgW) { delete s_bgW; s_bgW = 0; } if (pw>0 && ph>0) { s_bgE = Fl::screen_driver()->read_win_rectangle( px+pw-1, py, 1, ph, Fl_Window::current()); if(s_bgE && s_bgE->w() && s_bgE->h()) { s_bgE->scale(1, ph,0,1); } s_bgW = Fl::screen_driver()->read_win_rectangle( px, py, 1, ph, Fl_Window::current()); if(s_bgW && s_bgW->w() && s_bgW->h()) { s_bgW->scale(1, ph,0,1); } s_bgS = Fl::screen_driver()->read_win_rectangle( px, py+ph-1, pw, 1, Fl_Window::current()); if(s_bgS && s_bgS->w() && s_bgS->h()) { s_bgS->scale(pw, 1,0,1); } s_bgN = Fl::screen_driver()->read_win_rectangle( px, py, pw, 1, Fl_Window::current()); if(s_bgN && s_bgN->w() && s_bgN->h()) { s_bgN->scale(pw, 1,0,1); } bgx = px; bgy = py; bgw = pw; bgh = ph; } fl_color(FL_WHITE); fl_line_style(FL_SOLID); fl_graphics_driver->overlay_rect(px, py, pw, ph); fl_color(FL_BLACK); fl_line_style(FL_DOT); fl_graphics_driver->overlay_rect(px, py, pw, ph); fl_line_style(FL_SOLID); } static void erase_current_rect() { if (s_bgN) s_bgN->draw(bgx, bgy); if (s_bgS) s_bgS->draw(bgx, (bgy+bgh-1)); if (s_bgW) s_bgW->draw(bgx, bgy); if (s_bgE) s_bgE->draw((bgx+bgw-1), bgy); } /** Erase a selection rectangle without drawing a new one. \see fl_overlay_rect(int x, int y, int w, int h) */ void fl_overlay_clear() { if (pw > 0) {erase_current_rect(); pw = 0;} } /** Draw a transient dotted selection rectangle. This function saves the current screen content and then draws a dotted selection rectangle into the front screen buffer. If another selection rectangle was drawn earlier, the previous screen graphics are restored first. To clear the selection rectangle, call `fl_overlay_clear()`. The typical (and only) use for this function is to draw a selection rectangle during a mouse drag event sequence without having to redraw the entire content of the widget. Your event handle should look similar to this (also see `test/mandelbrot.cxx`): ``` int MyWidget::handle(int event) { static int ix, iy; switch (event) { case FL_PUSH: ix = Fl::event_x(); iy = Fl::event_y(); return 1; case FL_DRAG: this->make_current(); fl_overlay_rect(ix, iy, ix-Fl::event_x(), iy-Fl::event_y()); return 1; case FL_RELEASE: this->make_current(); fl_overlay_clear(); // select the element under the rectangle return 1; } return MySuperWidget::handle(event); } ``` \note Between drawing an overlay rect and clearing it, the content of the widget must not change. \note fl_overlay_rect() and fl_overlay_clear() should be called when the actual event occurs, and *not* within `MyWidget::draw()`. \note fl_overlay_rect() and fl_overlay_clear() should not be mixed with Fl_Overlay_Window. Fl_Overlay_Window provides an entirely different way of drawing selection outlines and is not limited to rectangles. \param x, y, w, h position and size of the overlay rectangle. \see fl_overlay_clear() */ void fl_overlay_rect(int x, int y, int w, int h) { // If there is already another overlay rect, erase it now if (pw > 0) { if (x==px && y==py && w==pw && h==ph) return; erase_current_rect(); } // Width and hight must be positive, swap with coordinates if needed if (w < 0) {x += w; w = -w;} if (h < 0) {y += h; h = -h;} // Clip the overlay to the window rect, or reading the background will fail Fl_Window *win = Fl_Window::current(); if (win) { int d; d = -x; if (d>0) { x += d; w -= d; } d = (x+w)-win->w(); if (d>0) { w -= d; } d = -y; if (d>0) { y += d; h -= d; } d = (y+h)-win->h(); if (d>0) { h -= d; } } // if (w<1) w = 1; if (h<1) h = 1; // Store the rect in global variables so we can erase it later px = x; py = y; pw = w; ph = h; // Draw it draw_current_rect(); } fltk-1.4.3/src/ew.xbm0000644000175000017500000000047415004135251014524 0ustar albrechtalbrecht#define ew_width 16 #define ew_height 16 #define ew_x_hot 8 #define ew_y_hot 8 static unsigned char ew_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; fltk-1.4.3/src/d1_mask.xbm0000644000175000017500000000044515004135251015426 0ustar albrechtalbrecht#define d1_mask_width 16 #define d1_mask_height 16 static unsigned char d1_mask_bits[] = { 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}; fltk-1.4.3/src/Fl_Native_File_Chooser_Zenity.cxx0000644000175000017500000000750715004135251021763 0ustar albrechtalbrecht// // FLTK native file chooser widget : Zenity version // // Copyright 2021-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // /** \cond DriverDev \addtogroup DriverDeveloper \{ */ #include #include "Fl_Native_File_Chooser_Zenity.H" #include #include #include // Fl_Zenity_Native_File_Chooser_Driver : file chooser based on the "zenity" command bool Fl_Zenity_Native_File_Chooser_Driver::did_find_zenity = false; bool Fl_Zenity_Native_File_Chooser_Driver::have_looked_for_zenity = false; Fl_Zenity_Native_File_Chooser_Driver::Fl_Zenity_Native_File_Chooser_Driver(int val) : Fl_Kdialog_Native_File_Chooser_Driver(val) { } void Fl_Zenity_Native_File_Chooser_Driver::append_filter(Fl_String& ret_command) { // TODO: This could probably be simplified + toughened with Fl_String -erco 1/10/24 int l; int lcommand = 10000; char *command = new char[lcommand]; command[0] = 0; char *parsed_filter_copy = strdup(_parsedfilt); // keep _parsedfilt unchanged for re-use char *p = strtok(parsed_filter_copy, "\n"); while (p) { char *op = strchr(p, '('); l = strlen(command); snprintf(command+l, lcommand-l, " --file-filter='%s|", p); char *cp = strchr(p, ')'); *cp = 0; char *ob = strchr(op+1, '['); if (ob) { // process [xyz] patterns *ob = 0; char *cb = strchr(ob+1, ']'); char aux[100]; for (char *q = ob+1; q < cb; q++) { strcpy(aux, op+1); int la = strlen(aux); aux[la++] = *q; if (cb < cp-1) { strcpy(aux+la, cb+1); la += strlen(cb+1); } aux[la] = 0; l = strlen(command); snprintf(command+l, lcommand-l, " %s", aux); } strcat(command, "'"); } else { l = strlen(command); snprintf(command+l, lcommand-l, "%s'", op+1); } p = strtok(NULL, "\n"); } free(parsed_filter_copy); ret_command += command; // append to parent's Fl_String delete [] command; } void Fl_Zenity_Native_File_Chooser_Driver::build_command(Fl_String& command) { const char *option; switch (_btype) { case Fl_Native_File_Chooser::BROWSE_DIRECTORY: case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: option = "--file-selection --directory"; break; case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: if (options() & Fl_Native_File_Chooser::SAVEAS_CONFIRM) option = "--file-selection --save --confirm-overwrite"; else option = "--file-selection --save"; break; case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: option = "--file-selection --multiple --separator='\n'"; break; default: option = "--file-selection"; } // Build preset Fl_String preset; if (_preset_file) { Fl_String quoted_filename = _preset_file; shell_quote(quoted_filename); preset = "--filename="; preset += quoted_filename; } else if (_directory) { // This doesn't actually seem to do anything, but supply it anyway. Fl_String quoted_dir = _directory; shell_quote(quoted_dir); preset = "--filename="; preset += quoted_dir; } // Build command command = "zenity"; if (_title) { Fl_String quoted_title = _title; shell_quote(quoted_title); command += " --title "; command += quoted_title; } command += " "; command += option; if (preset != "") { command += " "; command += preset; } if (_parsedfilt) append_filter(command); command += " 2> /dev/null"; // get rid of stderr //printf("command = %s\n", command.c_str()); } /** \} \endcond */ fltk-1.4.3/src/Fl_Menu_global.cxx0000644000175000017500000000262115004135251016766 0ustar albrechtalbrecht// // Global menu shortcut code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2010 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // Make all the shortcuts in this menu global. // Currently only one menu at a time and you cannot destruct the menu, // is this sufficient? #include #include static Fl_Menu_* the_widget; static int handler(int e) { if (e != FL_SHORTCUT || Fl::modal()) return 0; Fl::first_window(the_widget->window()); return the_widget->handle(e); } /** Make the shortcuts for this menu work no matter what window has the focus when you type it. This is done by using Fl::add_handler(). This Fl_Menu_ widget does not have to be visible (ie the window it is in can be hidden, or it does not have to be put in a window at all).

Currently there can be only one global()menu. Setting a new one will replace the old one. There is no way to remove the global() setting (so don't destroy the widget!) */ void Fl_Menu_::global() { if (!the_widget) Fl::add_handler(handler); the_widget = this; } fltk-1.4.3/src/Fl_File_Chooser2.cxx0000644000175000017500000014435115004135251017174 0ustar albrechtalbrecht// // More Fl_File_Chooser routines. // // Copyright 1999-2007 by Michael Sweet. // Copyright 2008-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // // The following documentation is placed here because the implementation and // header files FL/Fl_File_Chooser.H and src/Fl_File_Chooser.cxx are generated // by fluid from src/Fl_File_Chooser.fl. // *** BEGIN OUT OF SOURCE DOCUMENTATION *** /** \defgroup group_comdlg Common Dialog Classes and Functions \brief Common dialog functions for file selection, message output, and more. @{ */ /** \class Fl_File_Chooser The Fl_File_Chooser widget displays a standard file selection dialog that supports various selection modes. \image html Fl_File_Chooser.jpg \image latex Fl_File_Chooser.jpg "Fl_File_Chooser" width=12cm Features include: - Multiple filter patterns can be specified, with parenthesis around filters, and tabs to separate each pattern, e.g.: \code char pattern[] = "Image Files (*.{bmp,gif,jpg,png,xbm,xpm})\t" "Web Files (*.{htm,html,php})\t" "All Files (*)"; \endcode - If no "*" pattern is provided, then an entry for "All Files (*)" is automatically added. - An optional file preview box is provided which can be toggled by programmer or user showing images, or the first 2048 bytes of printable text. - Preview image loading functions can be registered to provide custom file previews. - The favorites button shows up to 100 user-saved favorite directories, the user's home directory, and a filesystems item. - A simple dialog is provided for managing saved directories. - Shortcut keys are provided:

ShortcutDescription
Alt+aAdds a directory to the favorites list
Alt+mManages the favorites list
Alt+fShows the filesystem list
Alt+hGo to the home directory
Alt+0..9going to any of the first 10 favorites
The Fl_File_Chooser widget transmits UTF-8 encoded filenames to its user. It is recommended to open files that may have non-ASCII names with the fl_fopen() or fl_open() utility functions that handle these names in a cross-platform way (whereas the standard fopen()/open() functions fail on the Windows platform to open files with a non-ASCII name). The Fl_File_Chooser class also exports several static values that may be used to localize or customize the appearance of all file chooser dialogs:
Member Default value
add_favorites_label "Add to Favorites"
all_files_label "All Files (*)"
custom_filter_label "Custom Filter"
existing_file_label "Please choose an existing file!"
favorites_label "Favorites"
filename_label "Filename:"
filesystems_label "My Computer" (Windows)
"File Systems" (all others)
hidden_label "Show hidden files:"
manage_favorites_label "Manage Favorites"
new_directory_label "New Directory?"
new_directory_tooltip "Create a new directory."
preview_label "Preview"
save_label "Save"
show_label "Show:"
sort fl_numericsort
The Fl_File_Chooser::sort member specifies the sort function that is used when loading the contents of a directory and can be customized at run-time. The Fl_File_Chooser class also exports the Fl_File_Chooser::newButton and Fl_File_Chooser::previewButton widgets so that application developers can control their appearance and use. */ /** @} */ /** \fn Fl_File_Chooser::Fl_File_Chooser(const char *pathname, const char *pattern, int type_val, const char *title) The constructor creates the Fl_File_Chooser dialog shown. - The \p pathname argument can be a directory name or a complete file name (in which case the corresponding file is highlighted in the list and in the filename input field.) - The \p pattern argument can be a NULL string or "*" to list all files, or it can be a series of descriptions and filter strings separated by tab characters (\\t). The format of filters is either "Description text (patterns)" or just "patterns". A file chooser that provides filters for HTML and image files might look like: \code "HTML Files (*.html)\tImage Files (*.{bmp,gif,jpg,png})" \endcode The file chooser will automatically add the "All Files (*)" pattern to the end of the string you pass if you do not provide one. The first filter in the string is the default filter. \p See the FLTK documentation on fl_filename_match() for the kinds of pattern strings that are supported. - The \p type_val argument can be one of the Fl_File_Chooser::Type values. - The \p title argument is used to set the title bar text for the Fl_File_Chooser window. */ /** \var Fl_File_Chooser::newButton The "new directory" button is exported so that application developers can control the appearance and use. */ /** \var Fl_File_Chooser::previewButton The "preview" button is exported so that application developers can control the appearance and use. */ /** \var Fl_File_Chooser::showHiddenButton When checked, hidden files (i.e., filename begins with dot) are displayed. The "showHiddenButton" button is exported so that application developers can control its appearance. */ /** \fn Fl_File_Chooser::~Fl_File_Chooser() Destroys the widget and frees all memory used by it.*/ /** \fn void Fl_File_Chooser::color(Fl_Color c) Sets the background color of the Fl_File_Browser list.*/ /** \fn Fl_Color Fl_File_Chooser::color() Gets the background color of the Fl_File_Browser list.*/ /** \fn void Fl_File_Chooser::directory(const char *pathname) Sets the current directory.*/ /** \fn const char *Fl_File_Chooser::directory() Gets the current directory.*/ /** \fn const char *Fl_File_Chooser::filter() Gets the current filename filter patterns.*/ /** \fn void Fl_File_Chooser::filter_value(int f) Sets the current filename filter selection.*/ /** \fn int Fl_File_Chooser::filter_value() Gets the current filename filter selection.*/ /** \fn void Fl_File_Chooser::hide() Hides the Fl_File_Chooser window.*/ /** \fn void Fl_File_Chooser::iconsize(uchar s) Sets the size of the icons in the Fl_File_Browser. By default the icon size is set to 1.5 times the textsize(). */ /** \fn uchar Fl_File_Chooser::iconsize() Gets the size of the icons in the Fl_File_Browser. By default the icon size is set to 1.5 times the textsize(). */ /** \fn void Fl_File_Chooser::label(const char *l) Sets the title bar text for the Fl_File_Chooser.*/ /** \fn const char *Fl_File_Chooser::label() Gets the title bar text for the Fl_File_Chooser.*/ /** \fn void Fl_File_Chooser::ok_label(const char *l) Sets the label for the "ok" button in the Fl_File_Chooser. */ /** \fn const char *Fl_File_Chooser::ok_label() Gets the label for the "ok" button in the Fl_File_Chooser. */ /** \fn int Fl_File_Chooser::preview() const Returns the current state of the preview box. */ /** \fn void Fl_File_Chooser::textcolor(Fl_Color c) Sets the current Fl_File_Browser text color.*/ /** \fn Fl_Color Fl_File_Chooser::textcolor() Gets the current Fl_File_Browser text color.*/ /** \fn void Fl_File_Chooser::textfont(Fl_Font f) Sets the current Fl_File_Browser text font.*/ /** \fn Fl_Font Fl_File_Chooser::textfont() Gets the current Fl_File_Browser text font.*/ /** \fn void Fl_File_Chooser::textsize(Fl_Fontsize s) Sets the current Fl_File_Browser text size.*/ /** \fn Fl_Fontsize Fl_File_Chooser::textsize() Gets the current Fl_File_Browser text size.*/ /** \fn void Fl_File_Chooser::type(int t) Sets the current type of Fl_File_Chooser.*/ /** \fn int Fl_File_Chooser::type() Gets the current type of Fl_File_Chooser.*/ /** \fn int Fl_File_Chooser::visible() Returns 1 if the Fl_File_Chooser window is visible.*/ /** \fn Fl_Widget *Fl_File_Chooser::add_extra(Fl_Widget *extra) Adds an extra widget at the bottom of the Fl_File_Chooser window. You can use any Fl_Widget or Fl_Group. If you use an Fl_Group, set its (x, y) coordinates to (0, 0) and position its children relative to (0, 0) inside the Fl_Group container widget. Make sure that all child widgets of the Fl_Group are entirely included inside the bounding box of their parents, i.e. the Fl_Group widget, and the Fl_File_Chooser window, respectively. \note The width of the Fl_File_Chooser window is an undocumented implementation detail and may change in the future. If \p extra is NULL any previous extra widget is removed. \param[in] extra Custom widget or group to be added to the Fl_File_Chooser window. \returns Pointer to previous extra widget or NULL if not set previously. \note Fl_File_Chooser does \b not delete the extra widget in its destructor! The extra widget is removed from the Fl_File_Chooser window before the Fl_File_Chooser widget gets destroyed. To prevent memory leakage, don't forget to delete unused extra widgets. */ /** \fn int Fl_File_Chooser::shown() Returns non-zero if the file chooser main window show() has been called, but not hide(). \see Fl_Window::shown() */ /** \fn void Fl_File_Chooser::callback(void (*cb)(Fl_File_Chooser *, void *), void *d = 0) Sets the file chooser callback cb and associated data \p d */ /** \fn void Fl_File_Chooser::user_data(void *d) Sets the file chooser user data \p d */ /** \fn void * Fl_File_Chooser::user_data() const Gets the file chooser user data. */ // *** END OF OUT OF SOURCE DOCUMENTATION *** // Contents: // // Fl_File_Chooser::count() - Return the number of selected files. // Fl_File_Chooser::directory() - Set the directory in the file chooser. // Fl_File_Chooser::filter() - Set the filter(s) for the chooser. // Fl_File_Chooser::newdir() - Make a new directory. // Fl_File_Chooser::value() - Return a selected filename. // Fl_File_Chooser::rescan() - Rescan the current directory. // Fl_File_Chooser::favoritesButtonCB() - Handle favorites selections. // Fl_File_Chooser::fileListCB() - Handle clicks (and double-clicks) // in the Fl_File_Browser. // Fl_File_Chooser::fileNameCB() - Handle text entry in the FileBrowser. // Fl_File_Chooser::showChoiceCB() - Handle show selections. // compare_dirnames() - Compare two directory names. // quote_pathname() - Quote a pathname for a menu. // unquote_pathname() - Unquote a pathname from a menu. // // Fl_File_Chooser::add_extra() - add custom extra widget or group // // // Include necessary headers. // #include #include "Fl_System_Driver.H" #include #include #include #include #include #include #include #include #include #include "flstring.h" #include #include // // File chooser label strings and sort function... // Fl_Preferences* Fl_File_Chooser::prefs_ = NULL; const char *Fl_File_Chooser::add_favorites_label = "Add to Favorites"; const char *Fl_File_Chooser::all_files_label = "All Files (*)"; const char *Fl_File_Chooser::custom_filter_label = "Custom Filter"; const char *Fl_File_Chooser::existing_file_label = "Please choose an existing file!"; const char *Fl_File_Chooser::favorites_label = "Favorites"; const char *Fl_File_Chooser::filename_label = "Filename:"; const char *Fl_File_Chooser::filesystems_label = Fl::system_driver()->filesystems_label(); const char *Fl_File_Chooser::manage_favorites_label = "Manage Favorites"; const char *Fl_File_Chooser::new_directory_label = "New Directory?"; const char *Fl_File_Chooser::new_directory_tooltip = "Create a new directory."; const char *Fl_File_Chooser::preview_label = "Preview"; const char *Fl_File_Chooser::save_label = "Save"; const char *Fl_File_Chooser::show_label = "Show:"; const char *Fl_File_Chooser::hidden_label = "Show hidden files"; Fl_File_Sort_F *Fl_File_Chooser::sort = fl_numericsort; // // Local functions... // static int compare_dirnames(const char *a, const char *b); static void quote_pathname(char *, const char *, int); static void unquote_pathname(char *, const char *, int); /** Returns the number of selected files.*/ int // O - Number of selected files Fl_File_Chooser::count() { int i; // Looping var int fcount; // Number of selected files const char *filename; // Filename in input field or list filename = fileName->value(); if (!(type_ & MULTI)) { // Check to see if the file name input field is blank... if (!filename || !filename[0]) return 0; else return 1; } for (i = 1, fcount = 0; i <= fileList->size(); i ++) if (fileList->selected(i)) { // See if this file is a directory... // matt: why would we do that? It is perfectly legal to select multiple // directories in a DIR chooser. They are visually selected and value(i) // returns all of them as expected //filename = (char *)fileList->text(i); //if (filename[strlen(filename) - 1] != '/') fcount ++; } if (fcount) return fcount; else if (!filename || !filename[0]) return 0; else return 1; } /** Sets the current directory.*/ void Fl_File_Chooser::directory(const char *d)// I - Directory to change to { char *dirptr; // Pointer into directory char fixpath[FL_PATH_MAX]; // Path with slashes converted // printf("Fl_File_Chooser::directory(\"%s\")\n", d == NULL ? "(null)" : d); // NULL == current directory if (d == NULL) d = "."; if (Fl::system_driver()->backslash_as_slash()) { // See if the filename contains backslashes... char *slash; // Pointer to slashes if (strchr(d, '\\')) { // Convert backslashes to slashes... strlcpy(fixpath, d, sizeof(fixpath)); for (slash = strchr(fixpath, '\\'); slash; slash = strchr(slash + 1, '\\')) *slash = '/'; d = fixpath; } } if (d[0] != '\0') { // Make the directory absolute... if (d[0] != '/' && d[0] != '\\' && ( !Fl::system_driver()->colon_is_drive() || d[1] != ':' ) ) fl_filename_absolute(directory_, d); else strlcpy(directory_, d, sizeof(directory_)); // Strip any trailing slash... dirptr = directory_ + strlen(directory_) - 1; if ((*dirptr == '/' || *dirptr == '\\') && dirptr > directory_) *dirptr = '\0'; // See if we have a trailing .. or . in the filename... dirptr = directory_ + strlen(directory_) - 3; if (dirptr >= directory_ && strcmp(dirptr, "/..") == 0) { // Yes, we have "..", so strip the trailing path... *dirptr = '\0'; while (dirptr > directory_) { if (*dirptr == '/') break; dirptr --; } if (dirptr >= directory_ && *dirptr == '/') *dirptr = '\0'; } else if ((dirptr + 1) >= directory_ && strcmp(dirptr + 1, "/.") == 0) { // Strip trailing "."... dirptr[1] = '\0'; } } else directory_[0] = '\0'; if (shown()) { // Rescan the directory... rescan(); } } // // 'Fl_File_Chooser::favoritesButtonCB()' - Handle favorites selections. // void Fl_File_Chooser::favoritesButtonCB() { int v; // Current selection char pathname[FL_PATH_MAX], // Pathname menuname[FL_PATH_MAX]; // Menu name v = favoritesButton->value(); if (!v) { // Add current directory to favorites... if (Fl::system_driver()->home_directory_name()) v = favoritesButton->size() - 5; else v = favoritesButton->size() - 4; snprintf(menuname, FL_PATH_MAX, "favorite%02d", v); prefs_->set(menuname, directory_); prefs_->flush(); update_favorites(); // adds item to favorites with Alt-n shortcut if (favoritesButton->size() > 104) { ((Fl_Menu_Item *)favoritesButton->menu())[0].deactivate(); } } else if (v == 1) { // Manage favorites... favoritesCB(0); } else if (v == 2) { // Filesystems/My Computer directory(""); } else { unquote_pathname(pathname, favoritesButton->text(v), sizeof(pathname)); directory(pathname); } } // // 'Fl_File_Chooser::favoritesCB()' - Handle favorites dialog. // void Fl_File_Chooser::favoritesCB(Fl_Widget *w) // I - Widget { int i; // Looping var char name[32], // Preference name pathname[1024]; // Directory in list if (!w) { // Load the favorites list... favList->clear(); favList->deselect(); for (i = 0; i < 100; i ++) { // Get favorite directory 0 to 99... snprintf(name, sizeof(name), "favorite%02d", i); prefs_->get(name, pathname, "", sizeof(pathname)); // Stop on the first empty favorite... if (!pathname[0]) break; // Add the favorite to the list... favList->add(pathname, Fl_File_Icon::find(pathname, Fl_File_Icon::DIRECTORY)); } favUpButton->deactivate(); favDeleteButton->deactivate(); favDownButton->deactivate(); favOkButton->deactivate(); favWindow->hotspot(favList); favWindow->show(); } else if (w == favList) { i = favList->value(); if (i) { if (i > 1) favUpButton->activate(); else favUpButton->deactivate(); favDeleteButton->activate(); if (i < favList->size()) favDownButton->activate(); else favDownButton->deactivate(); } else { favUpButton->deactivate(); favDeleteButton->deactivate(); favDownButton->deactivate(); } } else if (w == favUpButton) { i = favList->value(); favList->insert(i - 1, favList->text(i), favList->data(i)); favList->remove(i + 1); favList->select(i - 1); if (i == 2) favUpButton->deactivate(); favDownButton->activate(); favOkButton->activate(); } else if (w == favDeleteButton) { i = favList->value(); favList->remove(i); if (i > favList->size()) i --; favList->select(i); if (i < favList->size()) favDownButton->activate(); else favDownButton->deactivate(); if (i > 1) favUpButton->activate(); else favUpButton->deactivate(); if (!i) favDeleteButton->deactivate(); favOkButton->activate(); } else if (w == favDownButton) { i = favList->value(); favList->insert(i + 2, favList->text(i), favList->data(i)); favList->remove(i); favList->select(i + 1); if ((i + 1) == favList->size()) favDownButton->deactivate(); favUpButton->activate(); favOkButton->activate(); } else if (w == favOkButton) { // Copy the new list over... for (i = 0; i < favList->size(); i ++) { // Set favorite directory 0 to 99... snprintf(name, sizeof(name), "favorite%02d", i); prefs_->set(name, favList->text(i + 1)); } // Clear old entries as necessary... for (; i < 100; i ++) { // Clear favorite directory 0 to 99... snprintf(name, sizeof(name), "favorite%02d", i); prefs_->get(name, pathname, "", sizeof(pathname)); if (pathname[0]) prefs_->set(name, ""); else break; } update_favorites(); prefs_->flush(); favWindow->hide(); } } // // 'Fl_File_Chooser::fileListCB()' - Handle clicks (and double-clicks) in the // Fl_File_Browser. // void Fl_File_Chooser::fileListCB() { char *filename, // New filename pathname[FL_PATH_MAX + 4]; // Full pathname to file filename = (char *)fileList->text(fileList->value()); if (!filename) return; if (!directory_[0]) { strlcpy(pathname, filename, sizeof(pathname)); } else if (strcmp(directory_, "/") == 0) { snprintf(pathname, sizeof(pathname), "/%s", filename); } else { snprintf(pathname, sizeof(pathname), "%s/%s", directory_, filename); } if (Fl::event_clicks()) { int condition = 0; if (Fl::system_driver()->colon_is_drive() && strlen(pathname) == 2 && pathname[1] == ':') condition = 1; if (!condition) condition = Fl::system_driver()->filename_isdir_quick(pathname); if (condition) { // Change directories... directory(pathname); // Reset the click count so that a click in the same spot won't // be treated as a triple-click. We use a value of -1 because // the next click will increment click count to 0, which is what // we really want... Fl::event_clicks(-1); } else { // Hide the window - picked the file... window->hide(); if (callback_) (*callback_)(this, data_); } } else { // Check if the user clicks on a directory when picking files; // if so, make sure only that item is selected... filename = pathname + strlen(pathname) - 1; if ((type_ & MULTI) && !(type_ & DIRECTORY)) { if (*filename == '/') { // Clicked on a directory, deselect everything else... int i = fileList->value(); fileList->deselect(); fileList->select(i); } else { // Clicked on a file - see if there are other directories selected... int i; const char *temp; for (i = 1; i <= fileList->size(); i ++) { if (i != fileList->value() && fileList->selected(i)) { temp = fileList->text(i); temp += strlen(temp) - 1; if (*temp == '/') break; // Yes, selected directory } } if (i <= fileList->size()) { i = fileList->value(); fileList->deselect(); fileList->select(i); } } } // Strip any trailing slash from the directory name... if (*filename == '/') *filename = '\0'; // puts("Setting fileName from fileListCB..."); fileName->value(pathname); // Update the preview box... Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this); Fl::add_timeout(1.0, (Fl_Timeout_Handler)previewCB, this); // Do any callback that is registered... if (callback_) (*callback_)(this, data_); // Activate the OK button as needed... if (!Fl::system_driver()->filename_isdir_quick(pathname) || (type_ & DIRECTORY)) okButton->activate(); else okButton->deactivate(); } } // // 'Fl_File_Chooser::fileNameCB()' - Handle text entry in the FileBrowser. // void Fl_File_Chooser::fileNameCB() { char *filename, // New filename *slash, // Pointer to trailing slash pathname[FL_PATH_MAX], // Full pathname to file matchname[FL_PATH_MAX]; // Matching filename int i, // Looping var min_match, // Minimum number of matching chars max_match, // Maximum number of matching chars num_files, // Number of files in directory first_line; // First matching line const char *file; // File from directory // puts("fileNameCB()"); // printf("Event: %s\n", fl_eventnames[Fl::event()]); // Get the filename from the text field... filename = (char *)fileName->value(); if (!filename || !filename[0]) { okButton->deactivate(); return; } // Expand ~ and $ variables as needed... if (strchr(filename, '~') || strchr(filename, '$')) { fl_filename_expand(pathname, sizeof(pathname), filename); filename = pathname; value(pathname); } // Make sure we have an absolute path... int dirIsRelative = directory_[0] != '\0' && filename[0] != '/'; if (dirIsRelative && Fl::system_driver()->colon_is_drive()) dirIsRelative = !(isalpha(filename[0] & 255) && (!filename[1] || filename[1] == ':')); if (dirIsRelative) { fl_filename_absolute(pathname, sizeof(pathname), filename); value(pathname); int flen = (int)strlen(pathname); fileName->insert_position(flen, flen); // no selection after expansion } else if (filename != pathname) { // Finally, make sure that we have a writable copy... strlcpy(pathname, filename, sizeof(pathname)); } filename = pathname; // Now process things according to the key pressed... if (Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter) { // Enter pressed - select or change directory... int condition = 0; if (Fl::system_driver()->colon_is_drive()) condition = isalpha(pathname[0] & 255) && pathname[1] == ':' && !pathname[2]; if (!condition) condition = ( Fl::system_driver()->filename_isdir_quick(pathname) && compare_dirnames(pathname, directory_) ); if (condition) { directory(pathname); } else if ((type_ & CREATE) || fl_access(pathname, 0) == 0) { if (!Fl::system_driver()->filename_isdir_quick(pathname) || (type_ & DIRECTORY)) { // Update the preview box... update_preview(); // Do any callback that is registered... if (callback_) (*callback_)(this, data_); // Hide the window to signal things are done... window->hide(); } } else { // File doesn't exist, so beep at and alert the user... fl_alert("%s",existing_file_label); } } else if (Fl::event_key() != FL_Delete && Fl::event_key() != FL_BackSpace) { // Check to see if the user has entered a directory... if ((slash = strrchr(pathname, '/')) == NULL) slash = strrchr(pathname, '\\'); if (!slash) return; // Yes, change directories if necessary... *slash++ = '\0'; filename = slash; int condition = Fl::system_driver()->case_insensitive_filenames() ? strcasecmp(pathname, directory_) : strcmp(pathname, directory_); if (condition && (pathname[0] || strcmp("/", directory_))) { int p = fileName->insert_position(); int m = fileName->mark(); directory(pathname); if (filename[0]) { char tempname[FL_PATH_MAX + 4]; snprintf(tempname, sizeof(tempname), "%s/%s", directory_, filename); fileName->value(tempname); strlcpy(pathname, tempname, sizeof(pathname)); } fileName->insert_position(p, m); } // Other key pressed - do filename completion as possible... num_files = fileList->size(); min_match = (int) strlen(filename); max_match = min_match + 1; first_line = 0; for (i = 1; i <= num_files && max_match > min_match; i ++) { file = fileList->text(i); if ( (Fl::system_driver()->case_insensitive_filenames()? strncasecmp(filename, file, min_match) : strncmp(filename, file, min_match)) == 0) { // OK, this one matches; check against the previous match if (!first_line) { // First match; copy stuff over... strlcpy(matchname, file, sizeof(matchname)); max_match = (int) strlen(matchname); if (matchname[max_match - 1] == '/' && // Strip trailing /, if any... matchname[1] != 0 ) { // unless entire path is root ("/") -- STR #3500 max_match --; matchname[max_match] = '\0'; } // And then make sure that the item is visible fileList->topline(i); first_line = i; } else { // Succeeding match; compare to find maximum string match... while (max_match > min_match) if ( (Fl::system_driver()->case_insensitive_filenames()? strncasecmp(file, matchname, max_match) : strncmp(file, matchname, max_match)) == 0) break; else max_match --; // Truncate the string as needed... matchname[max_match] = '\0'; } } } // If we have any matches, add them to the input field... if (first_line > 0 && min_match == max_match && max_match == (int)strlen(fileList->text(first_line))) { // This is the only possible match... fileList->deselect(0); fileList->select(first_line); fileList->redraw(); } else if (max_match > min_match && first_line) { // Add the matching portion... fileName->replace( (int) (filename - pathname), (int) (filename - pathname + min_match), matchname); // Highlight it with the cursor at the end of the selection so // s/he can press the right arrow to accept the selection // (Tab and End also do this for both cases.) fileName->insert_position( (int) (filename - pathname + max_match), (int) (filename - pathname + min_match)); } else if (max_match == 0) { fileList->deselect(0); fileList->redraw(); } // See if we need to enable the OK button... if (((type_ & CREATE) || !fl_access(fileName->value(), 0)) && (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) { okButton->activate(); } else { okButton->deactivate(); } } else { // FL_Delete or FL_BackSpace fileList->deselect(0); fileList->redraw(); if (((type_ & CREATE) || !fl_access(fileName->value(), 0)) && (!fl_filename_isdir(fileName->value()) || (type_ & DIRECTORY))) { okButton->activate(); } else { okButton->deactivate(); } } } /** Sets the current filename filter patterns. The filter patterns use fl_filename_match(). Multiple patterns can be used by separating them with tabs, like "*.jpg\t*.png\t*.gif\t*". In addition, you can provide human-readable labels with the patterns inside parenthesis, like "JPEG Files (*.jpg)\tPNG Files (*.png)\tGIF Files (*.gif)\tAll Files (*)" . Use filter(NULL) to show all files. */ void Fl_File_Chooser::filter(const char *p) // I - Pattern(s) { char *copyp, // Copy of pattern *start, // Start of pattern *end; // End of pattern int allfiles; // Do we have a "*" pattern? char temp[FL_PATH_MAX]; // Temporary pattern string // Make sure we have a pattern... if (!p || !*p) p = "*"; // Copy the pattern string... copyp = fl_strdup(p); // Separate the pattern string as necessary... showChoice->clear(); for (start = copyp, allfiles = 0; start && *start; start = end) { end = strchr(start, '\t'); if (end) *end++ = '\0'; if (strcmp(start, "*") == 0) { showChoice->add(all_files_label); allfiles = 1; } else { quote_pathname(temp, start, sizeof(temp)); showChoice->add(temp); if (strstr(start, "(*)") != NULL) allfiles = 1; } } free(copyp); if (!allfiles) showChoice->add(all_files_label); showChoice->add(custom_filter_label); showChoice->value(0); showChoiceCB(); } // // 'Fl_File_Chooser::newdir()' - Make a new directory. // void Fl_File_Chooser::newdir() { const char *dir; // New directory name char pathname[FL_PATH_MAX + 4]; // Full path of directory // Get a directory name from the user if ((dir = fl_input("%s", NULL, new_directory_label)) == NULL) return; // Make it relative to the current directory as needed... if (dir[0] != '/' && dir[0] != '\\' && (!Fl::system_driver()->colon_is_drive() || dir[1] != ':') ) snprintf(pathname, sizeof(pathname), "%s/%s", directory_, dir); else strlcpy(pathname, dir, sizeof(pathname)); // Create the directory; ignore EEXIST errors... if (fl_mkdir(pathname, 0777)) if (errno != EEXIST) { fl_alert("%s", strerror(errno)); return; } // Show the new directory... directory(pathname); } /** Enable or disable the preview tile. 1 = enable preview, 0 = disable preview. */ void Fl_File_Chooser::preview(int e) { previewButton->value(e); prefs_->set("preview", e); prefs_->flush(); Fl_Group *p = previewBox->parent(); if (e) { int w = p->w() * 2 / 3; fileList->resize(fileList->x(), fileList->y(), w, fileList->h()); errorBox->resize(errorBox->x(), errorBox->y(), w, errorBox->h()); previewBox->resize(fileList->x()+w, previewBox->y(), p->w()-w, previewBox->h()); previewBox->show(); update_preview(); } else { fileList->resize(fileList->x(), fileList->y(), p->w(), fileList->h()); errorBox->resize(errorBox->x(), errorBox->y(), p->w(), errorBox->h()); previewBox->resize(p->x()+p->w(), previewBox->y(), 0, previewBox->h()); previewBox->hide(); } p->init_sizes(); fileList->parent()->redraw(); } // // 'Fl_File_Chooser::previewCB()' - Timeout handler for the preview box. // void Fl_File_Chooser::previewCB(Fl_File_Chooser *fc) { // I - File chooser fc->update_preview(); } /** Reloads the current directory in the Fl_File_Browser.*/ void Fl_File_Chooser::rescan() { char pathname[FL_PATH_MAX]; // New pathname for filename field // Clear the current filename strlcpy(pathname, directory_, sizeof(pathname)); if (pathname[0] && pathname[strlen(pathname) - 1] != '/') { strlcat(pathname, "/", sizeof(pathname)); } // puts("Setting fileName in rescan()"); fileName->value(pathname); if (type_ & DIRECTORY) okButton->activate(); else okButton->deactivate(); // Build the file list... if ( fileList->load(directory_, sort) <= 0 ) { if ( fileList->errmsg() ) errorBox->label(fileList->errmsg()); // show OS errormsg when possible else errorBox->label("No files found..."); show_error_box(1); } else { show_error_box(0); } if (Fl::system_driver()->dot_file_hidden() && !showHiddenButton->value()) remove_hidden_files(); // Update the preview box... update_preview(); } /** Rescan the current directory without clearing the filename, then select the file if it is in the list */ void Fl_File_Chooser::rescan_keep_filename() { // if no filename was set, this is likely a diretory browser const char *fn = fileName->value(); if (!fn || !*fn || fn[strlen(fn) - 1]=='/') { rescan(); return; } int i; char pathname[FL_PATH_MAX]; // New pathname for filename field strlcpy(pathname, fn, sizeof(pathname)); // Build the file list... if (fileList->load(directory_, sort) <= 0) { if ( fileList->errmsg() ) errorBox->label(fileList->errmsg()); // show OS errormsg when possible else errorBox->label("No files found..."); show_error_box(1); } else { show_error_box(0); } if (Fl::system_driver()->dot_file_hidden() && !showHiddenButton->value()) remove_hidden_files(); // Update the preview box... update_preview(); // and select the chosen file char found = 0; char *slash = strrchr(pathname, '/'); if (slash) slash++; else slash = pathname; for (i = 1; i <= fileList->size(); i ++) if ( (Fl::system_driver()->case_insensitive_filenames() ? strcasecmp(fileList->text(i), slash) : strcmp(fileList->text(i), slash)) == 0) { fileList->topline(i); fileList->select(i); found = 1; break; } // update OK button activity if (found || type_ & CREATE) okButton->activate(); else okButton->deactivate(); } // // 'Fl_File_Chooser::showChoiceCB()' - Handle show selections. // void Fl_File_Chooser::showChoiceCB() { const char *item, // Selected item *patstart; // Start of pattern char *patend; // End of pattern char temp[FL_PATH_MAX]; // Temporary string for pattern item = showChoice->text(showChoice->value()); if (strcmp(item, custom_filter_label) == 0) { if ((item = fl_input("%s", pattern_, custom_filter_label)) != NULL) { strlcpy(pattern_, item, sizeof(pattern_)); quote_pathname(temp, item, sizeof(temp)); showChoice->add(temp); showChoice->value(showChoice->size() - 2); } } else if ((patstart = strchr(item, '(')) == NULL) { strlcpy(pattern_, item, sizeof(pattern_)); } else { strlcpy(pattern_, patstart + 1, sizeof(pattern_)); if ((patend = strrchr(pattern_, ')')) != NULL) *patend = '\0'; } fileList->filter(pattern_); if (shown()) { // Rescan the directory... rescan_keep_filename(); } } // // 'Fl_File_Chooser::update_favorites()' - Update the favorites menu. // void Fl_File_Chooser::update_favorites() { int i; // Looping var char pathname[FL_PATH_MAX], // Pathname menuname[2048]; // Menu name const char *home; // Home directory favoritesButton->clear(); favoritesButton->add("bla"); favoritesButton->clear(); favoritesButton->add(add_favorites_label, FL_ALT + 'a', 0); favoritesButton->add(manage_favorites_label, FL_ALT + 'm', 0, 0, FL_MENU_DIVIDER); favoritesButton->add(filesystems_label, FL_ALT + 'f', 0); if ((home = Fl::system_driver()->home_directory_name()) != NULL) { quote_pathname(menuname, home, sizeof(menuname)); favoritesButton->add(menuname, FL_ALT + 'h', 0); } for (i = 0; i < 100; i ++) { snprintf(menuname, sizeof(menuname), "favorite%02d", i); prefs_->get(menuname, pathname, "", sizeof(pathname)); if (!pathname[0]) break; quote_pathname(menuname, pathname, sizeof(menuname)); if (i < 10) favoritesButton->add(menuname, FL_ALT + '0' + i, 0); else favoritesButton->add(menuname); } if (i == 100) ((Fl_Menu_Item *)favoritesButton->menu())[0].deactivate(); } // // 'Fl_File_Chooser::update_preview()' - Update the preview box... // void Fl_File_Chooser::update_preview() { const char *filename; // Current filename const char *newlabel = 0; // New label text Fl_Shared_Image *image = 0, // New image *oldimage; // Old image int pbw, pbh; // Width and height of preview box int w, h; // Width and height of preview image int set = 0; // Set this flag as soon as a decent preview is found if (!previewButton->value()) return; filename = value(); if (filename == NULL) { // no file name at all, so we have an empty preview set = 1; } else if (fl_filename_isdir(filename)) { // filename is a directory, show a folder icon newlabel = "@fileopen"; set = 1; } else { struct stat s; if (fl_stat(filename, &s)==0) { if ((s.st_mode & S_IFREG) == 0) { // this is no regular file, probably some kind of device newlabel = "@-3refresh"; // a cross set = 1; } else if (s.st_size==0) { // this file is empty newlabel = ""; set = 1; } else { // if this file is an image, try to load it window->cursor(FL_CURSOR_WAIT); Fl::check(); image = Fl_Shared_Image::get(filename); if (image) { window->cursor(FL_CURSOR_DEFAULT); Fl::check(); set = 1; } } } } oldimage = (Fl_Shared_Image *)previewBox->image(); if (oldimage) oldimage->release(); previewBox->image(0); if (!set) { FILE *fp; int bytes; char *ptr; if (filename) fp = fl_fopen(filename, "rb"); else fp = NULL; if (fp != NULL) { // Try reading the first 1k of data for a label... bytes = (int) fread(preview_text_, 1, sizeof(preview_text_) - 1, fp); preview_text_[bytes] = '\0'; fclose(fp); } else { // Assume we can't read any data... preview_text_[0] = '\0'; } window->cursor(FL_CURSOR_DEFAULT); Fl::check(); // Scan the buffer for printable UTF-8 chars... for (ptr = preview_text_; *ptr; ptr++) { uchar c = uchar(*ptr); if ( (c&0x80)==0 ) { if (!isprint(c&255) && !isspace(c&255)) break; } else if ( (c&0xe0)==0xc0 ) { if (ptr[1] && (ptr[1]&0xc0)!=0x80) break; ptr++; } else if ( (c&0xf0)==0xe0 ) { if (ptr[1] && (ptr[1]&0xc0)!=0x80) break; ptr++; if (ptr[1] && (ptr[1]&0xc0)!=0x80) break; ptr++; } else if ( (c&0xf8)==0xf0 ) { if (ptr[1] && (ptr[1]&0xc0)!=0x80) break; ptr++; if (ptr[1] && (ptr[1]&0xc0)!=0x80) break; ptr++; if (ptr[1] && (ptr[1]&0xc0)!=0x80) break; ptr++; } } // *ptr && (isprint(*ptr & 255) || isspace(*ptr & 255)); // ptr ++); // Scan the buffer for printable characters in 8 bit if (*ptr || ptr == preview_text_) { for (ptr = preview_text_; *ptr && (isprint(*ptr & 255) || isspace(*ptr & 255)); ptr ++) {/*empty*/} } if (*ptr || ptr == preview_text_) { // Non-printable file, just show a big ?... previewBox->label(filename ? "?" : 0); previewBox->align(FL_ALIGN_CLIP); previewBox->labelsize(75); previewBox->labelfont(FL_HELVETICA); } else { // Show the first 1k of text... int size = previewBox->h() / 20; if (size < 6) size = 6; else if (size > FL_NORMAL_SIZE) size = FL_NORMAL_SIZE; previewBox->label(preview_text_); previewBox->align((Fl_Align)(FL_ALIGN_CLIP | FL_ALIGN_INSIDE | FL_ALIGN_LEFT | FL_ALIGN_TOP)); previewBox->labelsize(size); previewBox->labelfont(FL_COURIER); } } else if (image && ( (image->w() <= 0) || (image->h() <= 0) || (image->d() < 0) || (image->count() <= 0))) { image->release(); // Image has errors? Show big 'X' previewBox->label("X"); previewBox->align(FL_ALIGN_CLIP); previewBox->labelsize(70); previewBox->labelfont(FL_HELVETICA); previewBox->redraw(); } else if (image) { pbw = previewBox->w() - 20; pbh = previewBox->h() - 20; if (image->w() > pbw || image->h() > pbh) { w = pbw; h = w * image->h() / image->w(); if (h > pbh) { h = pbh; w = h * image->w() / image->h(); } oldimage = (Fl_Shared_Image *)image->copy(w, h); previewBox->image((Fl_Image *)oldimage); image->release(); } else { previewBox->image((Fl_Image *)image); } previewBox->align(FL_ALIGN_CLIP); previewBox->label(0); } else if (newlabel) { previewBox->label(newlabel); previewBox->align(FL_ALIGN_CLIP); previewBox->labelsize(newlabel[0]=='@'?75:12); previewBox->labelfont(FL_HELVETICA); } previewBox->redraw(); } /** Gets the current value of the selected file(s). \p f is a \c 1-based index into a list of file names. The number of selected files is returned by Fl_File_Chooser::count(). This sample code loops through all selected files: \code // Get list of filenames user selected from a MULTI chooser for ( int t=1; t<=chooser->count(); t++ ) { const char *filename = chooser->value(t); ... } \endcode */ const char * // O - Filename or NULL Fl_File_Chooser::value(int f) // I - File number { int i; // Looping var int fcount; // Number of selected files const char *name; // Current filename static char pathname[FL_PATH_MAX + 4]; // Filename + directory name = fileName->value(); if (!(type_ & MULTI)) { // Return the filename in the filename field... if (!name || !name[0]) return NULL; else return name; } // Return a filename from the list... for (i = 1, fcount = 0; i <= fileList->size(); i ++) if (fileList->selected(i)) { // See if this file is a selected file/directory... name = fileList->text(i); fcount ++; if (fcount == f) { if (directory_[0]) { snprintf(pathname, sizeof(pathname), "%s/%s", directory_, name); } else { strlcpy(pathname, name, sizeof(pathname)); } return pathname; } } // If nothing is selected, use the filename field... if (!name || !name[0]) return NULL; else return name; } /** Sets the current value of the selected file. If a relative path is provided in \c filename it is converted to an absolute path. If \c NULL or an empty string is provided, the working directory is changed to the user's current directory and the filename is set to "". After assigning the filename the entire string (if any) is selected, i.e. - insert_position() is 0 (zero) - mark() is strlen(\). \note The selection of the entire string may not always be desired but it is kept for backwards compatibility. \param[in] filename relative or absolute filename, may be NULL or "" */ void Fl_File_Chooser::value(const char *filename) // I - Filename + directory { int i, // Looping var fcount; // Number of items in list char *slash; // Directory separator char pathname[FL_PATH_MAX]; // Local copy of filename // printf("Fl_File_Chooser::value(\"%s\")\n", filename == NULL ? "(null)" : filename); // See if the filename is the "My System" directory... if (filename == NULL || !filename[0]) { // Yes, just change the current directory... directory(filename); fileName->value(""); okButton->deactivate(); return; } char fixpath[FL_PATH_MAX]; // Path with slashes converted if (Fl::system_driver()->backslash_as_slash()) { // See if the filename contains backslashes... if (strchr(filename, '\\')) { // Convert backslashes to slashes... strlcpy(fixpath, filename, sizeof(fixpath)); for (slash = strchr(fixpath, '\\'); slash; slash = strchr(slash + 1, '\\')) *slash = '/'; filename = fixpath; } } // See if there is a directory in there... fl_filename_absolute(pathname, sizeof(pathname), filename); if ((slash = strrchr(pathname, '/')) != NULL) { // Yes, change the display to the directory... if (!fl_filename_isdir(pathname)) *slash++ = '\0'; directory(pathname); if (*slash == '/') slash = pathname; } else { directory("."); slash = pathname; } // Set the input field to the absolute path... if (slash > pathname) slash[-1] = '/'; fileName->value(pathname); fileName->insert_position(0, (int) strlen(pathname)); okButton->activate(); // Then find the file in the file list and select it... fcount = fileList->size(); fileList->deselect(0); fileList->redraw(); for (i = 1; i <= fcount; i ++) if ( ( Fl::system_driver()->case_insensitive_filenames() ? strcasecmp(fileList->text(i), slash) : strcmp(fileList->text(i), slash)) == 0) { // printf("Selecting line %d...\n", i); fileList->topline(i); fileList->select(i); break; } } /** Shows the Fl_File_Chooser window.*/ void Fl_File_Chooser::show() { window->hotspot(fileList); window->show(); Fl::flush(); fl_cursor(FL_CURSOR_WAIT); rescan_keep_filename(); fl_cursor(FL_CURSOR_DEFAULT); fileName->take_focus(); if (!Fl::system_driver()->dot_file_hidden()) showHiddenButton->hide(); } void Fl_File_Chooser::hide() { Fl::remove_timeout((Fl_Timeout_Handler)previewCB, this); Fl_Shared_Image *oldimage = (Fl_Shared_Image*)previewBox->image(); if (oldimage) oldimage->release(); previewBox->image(NULL); window->hide(); } void Fl_File_Chooser::showHidden(int value) { if (value) { fileList->load(directory()); } else { remove_hidden_files(); fileList->redraw(); } } void Fl_File_Chooser::remove_hidden_files() { int count = fileList->size(); for(int num = count; num >= 1; num--) { const char *p = fileList->text(num); if (*p == '.' && strcmp(p, "../") != 0) fileList->remove(num); } fileList->topline(1); } // // 'compare_dirnames()' - Compare two directory names. // static int compare_dirnames(const char *a, const char *b) { int alen, blen; // Get length of each string... alen = (int) (strlen(a) - 1); blen = (int) (strlen(b) - 1); if (alen < 0 || blen < 0) return alen - blen; // Check for trailing slashes... if (a[alen] != '/') alen ++; if (b[blen] != '/') blen ++; // If the lengths aren't the same, then return the difference... if (alen != blen) return alen - blen; // Do a comparison of the first N chars (alen == blen at this point)... return Fl::system_driver()->case_insensitive_filenames() ? strncasecmp(a, b, alen) : strncmp(a, b, alen); } // // 'quote_pathname()' - Quote a pathname for a menu. // static void quote_pathname(char *dst, // O - Destination string const char *src, // I - Source string int dstsize) // I - Size of destination string { dstsize--; // prepare for trailing zero while (*src && dstsize > 1) { if (*src == '\\') { // Convert backslash to forward slash... *dst++ = '\\'; *dst++ = '/'; dstsize -= 2; src ++; } else { if (*src == '/') { *dst++ = '\\'; dstsize--; } *dst++ = *src++; dstsize--; } } *dst = '\0'; } // // 'unquote_pathname()' - Unquote a pathname from a menu. // static void unquote_pathname(char *dst, // O - Destination string const char *src, // I - Source string int dstsize) // I - Size of destination string { dstsize--; // prepare for trailing zero while (*src && dstsize > 0) { if (*src == '\\') src++; *dst++ = *src++; dstsize--; } *dst = '\0'; } fltk-1.4.3/src/tile.xpm0000644000175000017500000001071315004135251015061 0ustar albrechtalbrecht/* XPM */ static char tile_cmap[3][32] = { "O c #FFFFFF", "o c #EFEFEF", ". c #E8E8E8" }; static const char * const tile_xpm[] = { "64 64 3 1", tile_cmap[0], tile_cmap[1], tile_cmap[2], "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "................................................................", "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"}; fltk-1.4.3/src/Fl_Image.cxx0000644000175000017500000005763215004135251015600 0ustar albrechtalbrecht// // Image drawing code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #include #include #include #include #include #include "flstring.h" #include void fl_restore_clip(); // from fl_rect.cxx // // Base image class... // Fl_RGB_Scaling Fl_Image::RGB_scaling_ = FL_RGB_SCALING_NEAREST; Fl_RGB_Scaling Fl_Image::scaling_algorithm_ = FL_RGB_SCALING_BILINEAR; /** The constructor creates an empty image with the specified width, height, and depth. The width and height are in pixels. The depth is 0 for bitmaps, 1 for pixmap (colormap) images, and 1 to 4 for color images. */ Fl_Image::Fl_Image(int W, int H, int D) : w_(W), h_(H), d_(D), ld_(0), count_(0), data_w_(W), data_h_(H), data_(0L) {} /** The destructor is a virtual method that frees all memory used by the image. */ Fl_Image::~Fl_Image() { } /** If the image has been cached for display, delete the cache data. This allows you to change the data used for the image and then redraw it without recreating an image object. */ void Fl_Image::uncache() { } void Fl_Image::draw(int XP, int YP, int, int, int, int) { draw_empty(XP, YP); } /** The protected method draw_empty() draws a box with an X in it. It can be used to draw any image that lacks image data. */ void Fl_Image::draw_empty(int X, int Y) { if (w() > 0 && h() > 0) { fl_color(FL_FOREGROUND_COLOR); fl_rect(X, Y, w(), h()); fl_line(X, Y, X + w() - 1, Y + h() - 1); fl_line(X, Y + h() - 1, X + w() - 1, Y); } } /** Creates a resized copy of the image. It is recommended not to call this member function to reduce the size of an image to the size of the area where this image will be drawn, and to use Fl_Image::scale() instead. The new image should be released when you are done with it. Note: since FLTK 1.4.0 you can use Fl_Image::release() for all types of images (i.e. all subclasses of Fl_Image) instead of operator \em delete for Fl_Image's and Fl_Image::release() for Fl_Shared_Image's. The new image data will be converted to the requested size. RGB images are resized using the algorithm set by Fl_Image::RGB_scaling(). For the new image the following equations are true: - w() == data_w() == \p W - h() == data_h() == \p H \param[in] W,H Requested width and height of the new image \note The returned image can be safely cast to the same image type as that of the source image provided this type is one of Fl_RGB_Image, Fl_SVG_Image, Fl_Pixmap, Fl_Bitmap, Fl_Tiled_Image, Fl_Anim_GIF_Image and Fl_Shared_Image. Returned objects copied from images of other, derived, image classes belong to the parent class appearing in this list. For example, the copy of an Fl_GIF_Image is an object of class Fl_Pixmap. \note Since FLTK 1.4.0 this method is 'const'. If you derive your own class from Fl_Image or any subclass your overridden methods of 'Fl_Image::copy() const' and 'Fl_Image::copy(int, int) const' \b must also be 'const' for inheritance to work properly. This is different than in FLTK 1.3.x and earlier where these methods have not been 'const'. */ Fl_Image *Fl_Image::copy(int W, int H) const { return new Fl_Image(W, H, d()); } /** The color_average() method averages the colors in the image with the provided FLTK color value. The first argument specifies the FLTK color to be used. The second argument specifies the amount of the original image to combine with the color, so a value of 1.0 results in no color blend, and a value of 0.0 results in a constant image of the specified color. An internal copy is made of the original image data before changes are applied, to avoid modifying the original image data in memory. */ void Fl_Image::color_average(Fl_Color, float) { } /** The desaturate() method converts an image to grayscale. If the image contains an alpha channel (depth = 4), the alpha channel is preserved. An internal copy is made of the original image data before changes are applied, to avoid modifying the original image data in memory. */ void Fl_Image::desaturate() { } // Doxygen documentation in FL/Enumerations.H Fl_Labeltype fl_define_FL_IMAGE_LABEL() { return Fl_Image::define_FL_IMAGE_LABEL(); } Fl_Labeltype Fl_Image::define_FL_IMAGE_LABEL() { Fl::set_labeltype(_FL_IMAGE_LABEL, Fl_Image::labeltype, Fl_Image::measure); return _FL_IMAGE_LABEL; } /** This method is an obsolete way to set the image attribute of a widget or menu item. \deprecated Please use Fl_Widget::image() or Fl_Widget::deimage() instead. */ void Fl_Image::label(Fl_Widget* widget) { widget->image(this); } /** This method is an obsolete way to set the image attribute of a menu item. \deprecated Please use Fl_Menu_Item::image() instead. */ void Fl_Image::label(Fl_Menu_Item* m) { m->label(FL_IMAGE_LABEL, (const char*)this); } /** Returns a value that is not 0 if there is currently no image available. Example use: \code // [..] Fl_Box box(X, Y, W, H); Fl_JPEG_Image jpg("/tmp/foo.jpg"); switch (jpg.fail()) { case Fl_Image::ERR_NO_IMAGE: case Fl_Image::ERR_FILE_ACCESS: fl_alert("/tmp/foo.jpg: %s", strerror(errno)); // shows actual os error to user exit(1); case Fl_Image::ERR_FORMAT: fl_alert("/tmp/foo.jpg: couldn't decode image"); exit(1); } box.image(jpg); \endcode \returns Image load failure if non-zero \retval 0 the image was loaded successfully \retval ERR_NO_IMAGE no image was found \retval ERR_FILE_ACCESS there was a file access related error (errno should be set) \retval ERR_FORMAT image decoding failed \retval ERR_MEMORY_ACCESS image decoder tried to access memory outside of given memory block */ int Fl_Image::fail() const { // if no image exists, ld_ may contain a simple error code if ((w_ <= 0) || (h_ <= 0) || (d_ <= 0)) { if (ld_ == 0) return ERR_NO_IMAGE; else return ld_; } return 0; } void Fl_Image::labeltype(const Fl_Label *lo, // I - Label int lx, // I - X position int ly, // I - Y position int lw, // I - Width of label int lh, // I - Height of label Fl_Align la) { // I - Alignment Fl_Image *img; // Image pointer int cx, cy; // Image position img = (Fl_Image *)(lo->value); if (la & FL_ALIGN_LEFT) cx = 0; else if (la & FL_ALIGN_RIGHT) cx = img->w() - lw; else cx = (img->w() - lw) / 2; if (la & FL_ALIGN_TOP) cy = 0; else if (la & FL_ALIGN_BOTTOM) cy = img->h() - lh; else cy = (img->h() - lh) / 2; fl_color((Fl_Color)lo->color); img->draw(lx, ly, lw, lh, cx, cy); } void Fl_Image::measure(const Fl_Label *lo, // I - Label int &lw, // O - Width of image int &lh) { // O - Height of image Fl_Image *img; // Image pointer img = (Fl_Image *)(lo->value); lw = img->w(); lh = img->h(); } /** Sets the RGB image scaling method used for copy(int, int). Applies to all RGB images, defaults to FL_RGB_SCALING_NEAREST. */ void Fl_Image::RGB_scaling(Fl_RGB_Scaling method) { RGB_scaling_ = method; } /** Returns the currently used RGB image scaling method. */ Fl_RGB_Scaling Fl_Image::RGB_scaling() { return RGB_scaling_; } /** Sets the drawing size of the image. This function controls the values returned by member functions w() and h() which in turn control how the image is drawn: the full image data (whose size is given by data_w() and data_h()) are drawn scaled to an area of the drawing surface sized at w() x h() FLTK units. This can make a difference if the drawing surface has more than 1 pixel per FLTK unit because the image can be drawn at the full resolution of the drawing surface. Examples of such drawing surfaces: HiDPI displays, laser printers, PostScript files, PDF printers. \param width,height maximum values, in FLTK units, that w() and h() should return \param proportional if not null, keep the values returned by w() and h() proportional to data_w() and data_h() \param can_expand if null, the values returned by w() and h() will not be larger than data_w() and data_h(), respectively \note This function generally changes the values returned by the w() and h() member functions. In contrast, the values returned by data_w() and data_h() remain unchanged. \version 1.4 (1.3.4 and FL_ABI_VERSION for Fl_Shared_Image only) Example code: scale an image to fit in a box \code Fl_Box *b = ... // a box Fl_Image *img = new Fl_PNG_Image("/path/to/picture.png"); // read a picture file // set the drawing size of the image to the size of the box keeping its aspect ratio img->scale(b->w(), b->h()); b->image(img); // use the image as the box image \endcode */ void Fl_Image::scale(int width, int height, int proportional, int can_expand) { if ((width <= data_w() && height <= data_h()) || can_expand) { w_ = width; h_ = height; } if (fail()) return; if (!proportional && can_expand) return; if (!proportional && width <= data_w() && height <= data_h()) return; float fw = data_w() / float(width); float fh = data_h() / float(height); if (proportional) { if (fh > fw) fw = fh; else fh = fw; } if (!can_expand) { if (fw < 1) fw = 1; if (fh < 1) fh = 1; } w_ = int((data_w() / fw) + 0.5); h_ = int((data_h() / fh) + 0.5); } /** Draw the image to the current drawing surface rescaled to a given width and height. Intended for internal use by the FLTK library. \param X,Y position of the image's top-left \param W,H width and height for the drawn image \return 1 \deprecated Only for API compatibility with FLTK 1.3.4. */ int Fl_Image::draw_scaled(int X, int Y, int W, int H) { // transiently set image drawing size to WxH int width = w(), height = h(); scale(W, H, 0, 1); draw(X, Y, W, H, 0, 0); scale(width, height, 0, 1); return 1; } /** True after fl_register_images() was called, false before */ bool Fl_Image::register_images_done = false; // // RGB image class... // size_t Fl_RGB_Image::max_size_ = ~((size_t)0); int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg); /** The constructor creates a new image from the specified data. The data array \p bits must contain sufficient data to provide \p W * \p H * \p D image bytes and optional line padding, see \p LD. \p W and \p H are the width and height of the image in pixels, resp. \p D is the image depth and can be: - D=1: each uchar in \p bits[] is a grayscale pixel value - D=2: each uchar pair in \p bits[] is a grayscale + alpha pixel value - D=3: each uchar triplet in \p bits[] is an R/G/B pixel value - D=4: each uchar quad in \p bits[] is an R/G/B/A pixel value \p LD specifies the line data size of the array, see Fl_Image::ld(int). If \p LD is zero, then \p W * \p D is assumed, otherwise \p LD must be greater than or equal to \p W * \p D to account for (unused) extra data per line (padding). The caller is responsible that the image data array \p bits persists as long as the image is used. This constructor sets Fl_RGB_Image::alloc_array to 0. To have the image object control the deallocation of the data array \p bits, set alloc_array to non-zero after construction. \param[in] bits The image data array. \param[in] W The width of the image in pixels. \param[in] H The height of the image in pixels. \param[in] D The image depth, or 'number of channels' (default=3). \param[in] LD Line data size (default=0). \see Fl_Image::data(), Fl_Image::w(), Fl_Image::h(), Fl_Image::d(), Fl_Image::ld(int) */ Fl_RGB_Image::Fl_RGB_Image(const uchar *bits, int W, int H, int D, int LD) : Fl_Image(W,H,D), array(bits), alloc_array(0), id_(0), mask_(0), cache_w_(0), cache_h_(0) { data((const char **)&array, 1); ld(LD); } /** The constructor creates a new image from the specified data. If the provided array is too small to contain all the image data, the constructor will not generate the image to avoid illegal memory read access and instead set \c data to NULL and \c ld to \c ERR_MEMORY_ACCESS. \param bits image data \param bits_length length of the \p bits array in bytes \param W image width in pixels \param H image height in pixels \param D image depth in bytes, 1 for gray scale, 2 for gray with alpha, 3 for RGB, and 4 for RGB plus alpha \param LD line length in bytes, or 0 to use W*D. \see Fl_RGB_Image(const uchar *bits, int W, int H, int D, int LD) */ Fl_RGB_Image::Fl_RGB_Image(const uchar *bits, int bits_length, int W, int H, int D, int LD) : Fl_Image(W,H,D), array(bits), alloc_array(0), id_(0), mask_(0), cache_w_(0), cache_h_(0) { if (D == 0) D = 3; if (LD == 0) LD = W*D; int min_length = LD*(H-1) + W*D; if (bits_length >= min_length) { data((const char **)&array, 1); ld(LD); } else { array = NULL; data(NULL, 0); ld(ERR_MEMORY_ACCESS); } } /** The constructor creates a new RGBA image from the specified Fl_Pixmap. The RGBA image is built fully opaque except for the transparent area of the pixmap that is assigned the \p bg color with full transparency. This constructor creates a new internal data array and sets Fl_RGB_Image::alloc_array to 1 so the data array is deleted when the image is destroyed. */ Fl_RGB_Image::Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg): Fl_Image(pxm->data_w(), pxm->data_h(), 4), array(0), alloc_array(0), id_(0), mask_(0), cache_w_(0), cache_h_(0) { if (pxm && pxm->data_w() > 0 && pxm->data_h() > 0) { array = new uchar[data_w() * data_h() * d()]; alloc_array = 1; fl_convert_pixmap(pxm->data(), (uchar*)array, bg); } data((const char **)&array, 1); scale(pxm->w(), pxm->h(), 0, 1); } /** The destructor frees all memory and server resources that are used by the image. */ Fl_RGB_Image::~Fl_RGB_Image() { uncache(); if (alloc_array) delete[] (uchar *)array; } void Fl_RGB_Image::uncache() { Fl_Graphics_Driver::default_driver().uncache(this, id_, mask_); } Fl_Image *Fl_RGB_Image::copy(int W, int H) const { Fl_RGB_Image *new_image; // New RGB image uchar *new_array; // New array for image data // Optimize the simple copy where the width and height are the same, // or when we are copying an empty image... if ((W == data_w() && H == data_h()) || !w() || !h() || !d() || !array) { if (array) { // Make a copy of the image data and return a new Fl_RGB_Image... new_array = new uchar[((long)W) * H * d()]; if (ld() && (ld() != W*d())) { const uchar *src = array; uchar *dst = new_array; int dy, dh = H, wd = W*d(), wld = ld(); for (dy=0; dyalloc_array = 1; } else { new_image = new Fl_RGB_Image(array, W, H, d(), ld()); } return new_image; } if (W <= 0 || H <= 0) return 0; // OK, need to resize the image data; allocate memory and create new image uchar *new_ptr; // Pointer into new array const uchar *old_ptr; // Pointer into old array int dx, dy, // Destination coordinates line_d; // stride from line to line // Allocate memory for the new image... new_array = new uchar [((long)W) * H * d()]; new_image = new Fl_RGB_Image(new_array, W, H, d()); new_image->alloc_array = 1; line_d = ld() ? ld() : data_w() * d(); if (Fl_Image::RGB_scaling() == FL_RGB_SCALING_NEAREST) { int c, // Channel number sy, // Source coordinate xerr, yerr, // X & Y errors xmod, ymod, // X & Y moduli xstep, ystep; // X & Y step increments // Figure out Bresenham step/modulus values... xmod = data_w() % W; xstep = (data_w() / W) * d(); ymod = data_h() % H; ystep = data_h() / H; // Scale the image using a nearest-neighbor algorithm... for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) { for (dx = W, xerr = W, old_ptr = array + ((long)sy) * line_d; dx > 0; dx --) { for (c = 0; c < d(); c ++) *new_ptr++ = old_ptr[c]; old_ptr += xstep; xerr -= xmod; if (xerr <= 0) { xerr += W; old_ptr += d(); } } sy += ystep; yerr -= ymod; if (yerr <= 0) { yerr += H; sy ++; } } } else { // Bilinear scaling (FL_RGB_SCALING_BILINEAR) const float xscale = (data_w() - 1) / (float) W; const float yscale = (data_h() - 1) / (float) H; for (dy = 0; dy < H; dy++) { float oldy = dy * yscale; if (oldy >= data_h()) oldy = float(data_h() - 1); const float yfract = oldy - (unsigned) oldy; for (dx = 0; dx < W; dx++) { new_ptr = new_array + ((long)dy) * W * d() + dx * d(); float oldx = dx * xscale; if (oldx >= data_w()) oldx = float(data_w() - 1); const float xfract = oldx - (unsigned) oldx; const unsigned leftx = (unsigned)oldx; const unsigned lefty = (unsigned)oldy; const unsigned rightx = (unsigned)(oldx + 1 >= data_w() ? oldx : oldx + 1); const unsigned righty = (unsigned)oldy; const unsigned dleftx = (unsigned)oldx; const unsigned dlefty = (unsigned)(oldy + 1 >= data_h() ? oldy : oldy + 1); const unsigned drightx = (unsigned)rightx; const unsigned drighty = (unsigned)dlefty; uchar left[4], right[4], downleft[4], downright[4]; memcpy(left, array + ((long)lefty) * line_d + leftx * d(), d()); memcpy(right, array + ((long)righty) * line_d + rightx * d(), d()); memcpy(downleft, array + ((long)dlefty) * line_d + dleftx * d(), d()); memcpy(downright, array + ((long)drighty) * line_d + drightx * d(), d()); int i; if (d() == 4) { for (i = 0; i < 3; i++) { left[i] = (uchar)(left[i] * left[3] / 255.0f); right[i] = (uchar)(right[i] * right[3] / 255.0f); downleft[i] = (uchar)(downleft[i] * downleft[3] / 255.0f); downright[i] = (uchar)(downright[i] * downright[3] / 255.0f); } } const float leftf = 1 - xfract; const float rightf = xfract; const float upf = 1 - yfract; const float downf = yfract; for (i = 0; i < d(); i++) { new_ptr[i] = (uchar)((left[i] * leftf + right[i] * rightf) * upf + (downleft[i] * leftf + downright[i] * rightf) * downf); } if (d() == 4 && new_ptr[3]) { for (i = 0; i < 3; i++) { new_ptr[i] = (uchar)(new_ptr[i] / (new_ptr[3] / 255.0f)); } } } } } return new_image; } void Fl_RGB_Image::color_average(Fl_Color c, float i) { // Don't average an empty image... if (!w() || !h() || !d() || !array) return; // Delete any existing pixmap/mask objects... uncache(); // Allocate memory as needed... uchar *new_array, *new_ptr; if (!alloc_array) new_array = new uchar[data_h() * data_w() * d()]; else new_array = (uchar *)array; // Get the color to blend with... uchar r, g, b; unsigned ia, ir, ig, ib; Fl::get_color(c, r, g, b); if (i < 0.0f) i = 0.0f; else if (i > 1.0f) i = 1.0f; ia = (unsigned)(256 * i); ir = r * (256 - ia); ig = g * (256 - ia); ib = b * (256 - ia); // Update the image data to do the blend... const uchar *old_ptr; int x, y; int line_i = ld() ? ld() - (data_w()*d()) : 0; // increment from line end to beginning of next line if (d() < 3) { ig = (r * 31 + g * 61 + b * 8) / 100 * (256 - ia); for (new_ptr = new_array, old_ptr = array, y = 0; y < data_h(); y ++, old_ptr += line_i) for (x = 0; x < data_w(); x ++) { *new_ptr++ = (*old_ptr++ * ia + ig) >> 8; if (d() > 1) *new_ptr++ = *old_ptr++; } } else { for (new_ptr = new_array, old_ptr = array, y = 0; y < data_h(); y ++, old_ptr += line_i) for (x = 0; x < data_w(); x ++) { *new_ptr++ = (*old_ptr++ * ia + ir) >> 8; *new_ptr++ = (*old_ptr++ * ia + ig) >> 8; *new_ptr++ = (*old_ptr++ * ia + ib) >> 8; if (d() > 3) *new_ptr++ = *old_ptr++; } } // Set the new pointers/values as needed... if (!alloc_array) { array = new_array; alloc_array = 1; ld(0); } } void Fl_RGB_Image::desaturate() { // Don't desaturate an empty image... if (!w() || !h() || !d() || !array) return; // Can only desaturate color images... if (d() < 3) return; // Delete any existing pixmap/mask objects... uncache(); // Allocate memory for a grayscale image... uchar *new_array, *new_ptr; int new_d; new_d = d() - 2; new_array = new uchar[data_h() * data_w() * new_d]; // Copy the image data, converting to grayscale... const uchar *old_ptr; int x, y; int line_i = ld() ? ld() - (data_w()*d()) : 0; // increment from line end to beginning of next line for (new_ptr = new_array, old_ptr = array, y = 0; y < data_h(); y ++, old_ptr += line_i) for (x = 0; x < data_w(); x ++, old_ptr += d()) { *new_ptr++ = (uchar)((31 * old_ptr[0] + 61 * old_ptr[1] + 8 * old_ptr[2]) / 100); if (d() > 3) *new_ptr++ = old_ptr[3]; } // Free the old array as needed, and then set the new pointers/values... if (alloc_array) delete[] (uchar *)array; array = new_array; alloc_array = 1; ld(0); d(new_d); } #define fl_max(a,b) ((a) > (b) ? (a) : (b)) #define fl_min(a,b) ((a) < (b) ? (a) : (b)) typedef struct {int x; int y; int width; int height;} rectangle_int_t; static void crect_intersect(rectangle_int_t *to, rectangle_int_t *with) { int x = fl_max(to->x, with->x); to->width = fl_min(to->x + to->width, with->x + with->width) - x; if (to->width < 0) to->width = 0; int y = fl_max(to->y, with->y); to->height = fl_min(to->y + to->height, with->y + with->height) - y; if (to->height < 0) to->height = 0; to->x = x; to->y = y; } void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) { float s = fl_graphics_driver->scale(); if (s != int(s) && (cx || cy || WP != w() || HP != h()) && w() == data_w() && h() == data_h()) { // See issue #1128: clipping to a part of the image while the scaling // has a fractional value creates problems rectangle_int_t r1 = { XP-cx, YP-cy, w(), h() }; rectangle_int_t r2 = { XP, YP, WP, HP }; crect_intersect(&r1, &r2); if (!r1.width || !r1.height) return; // After this, r1.x,r1.y = position of top-left of drawn image part; // r1.width,r1.height = size of drawn image part, in FLTK units; // fl_max(cx, 0),fl_max(cy, 0) = top-left of drawn part in image. int l = (ld() ? ld() : d() * w()); const uchar *p = array + fl_max(cy, 0) * l + fl_max(cx, 0) * d(); fl_graphics_driver->draw_image(p, r1.x, r1.y, r1.width, r1.height, d(), l); } else fl_graphics_driver->draw_rgb(this, XP, YP, WP, HP, cx, cy); } void Fl_RGB_Image::label(Fl_Widget* widget) { widget->image(this); } void Fl_RGB_Image::label(Fl_Menu_Item* m) { m->label(FL_IMAGE_LABEL, (const char*)this); } fltk-1.4.3/install-sh0000755000175000017500000001123415004135251014612 0ustar albrechtalbrecht#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. # # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" tranformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 fltk-1.4.3/Makefile0000644000175000017500000000702215004135251014246 0ustar albrechtalbrecht# # Top-level Makefile for the Fast Light Tool Kit (FLTK). # # Copyright 1998-2024 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # include makeinclude DIRS = $(IMAGEDIRS) $(LIBDECORDIR) src $(CAIRODIR) $(FLUIDDIR) fltk-options $(TESTDIR) \ documentation all: makeinclude fltk-config for dir in $(DIRS); do\ echo "=== making $$dir ===";\ (cd $$dir; $(MAKE) $(MFLAGS)) || exit 1;\ done # Build test programs (and 'all') if FLTK was configured with '--disable-test' test: all echo "=== making test ===";\ (cd test; $(MAKE) $(MFLAGS)) || exit 1 install: makeinclude -mkdir -p "$(DESTDIR)$(bindir)" $(RM) "$(DESTDIR)$(bindir)/fltk-config" $(INSTALL_SCRIPT) fltk-config "$(DESTDIR)$(bindir)" for dir in FL $(DIRS); do\ echo "=== installing $$dir ===";\ (cd $$dir; $(MAKE) $(MFLAGS) install) || exit 1;\ done install-desktop: makeinclude cd documentation; $(MAKE) $(MFLAGS) $(INSTALL_DESKTOP) cd fluid; $(MAKE) $(MFLAGS) $(INSTALL_DESKTOP) cd fltk-options; $(MAKE) $(MFLAGS) $(INSTALL_DESKTOP) cd test; $(MAKE) $(MFLAGS) $(INSTALL_DESKTOP) uninstall: makeinclude $(RM) "$(DESTDIR)$(bindir)/fltk-config" for dir in FL $(DIRS); do\ echo "=== uninstalling $$dir ===";\ (cd $$dir; $(MAKE) $(MFLAGS) uninstall) || exit 1;\ done uninstall-desktop: makeinclude cd documentation; $(MAKE) $(MFLAGS) $(UNINSTALL_DESKTOP) cd fluid; $(MAKE) $(MFLAGS) $(UNINSTALL_DESKTOP) cd fltk-options; $(MAKE) $(MFLAGS) $(UNINSTALL_DESKTOP) cd test; $(MAKE) $(MFLAGS) $(UNINSTALL_DESKTOP) depend: makeinclude for dir in $(DIRS); do\ echo "=== making dependencies in $$dir ===";\ (cd $$dir; $(MAKE) $(MFLAGS) depend) || exit 1;\ done clean: -$(RM) core *.o for dir in examples $(DIRS); do\ echo "=== cleaning $$dir ===";\ (cd $$dir; $(MAKE) $(MFLAGS) clean) || exit 1;\ done distclean: clean $(RM) config.h config.log config.status $(RM) fltk-config fltk.list makeinclude $(RM) fltk.spec $(RM) FL/Makefile $(RM) FL/fl_config.h $(RM) documentation/*.$(CAT1EXT) $(RM) documentation/*.$(CAT3EXT) $(RM) documentation/*.$(CAT6EXT) $(RM) documentation/fltk.ps $(RM) -r documentation/fltk.d for file in test/*.fl; do\ $(RM) test/`basename $$file .fl`.cxx; \ $(RM) test/`basename $$file .fl`.h; \ done $(RM) -rf autom4te.cache/ $(RM) configure fltk-config: configure configh.in fltk-config.in if test -f config.status; then \ ./config.status --recheck; \ ./config.status; \ else \ ./configure; \ fi touch config.h chmod +x fltk-config makeinclude: configure configh.in makeinclude.in if test -f config.status; then \ ./config.status --recheck; \ ./config.status; \ else \ ./configure; \ fi touch config.h chmod +x fltk-config configure: configure.ac autoconf portable-dist: epm -v -s fltk.xpm fltk native-dist: epm -v -f native fltk etags: etags FL/*.H FL/*.h src/*.cxx src/*.c src/*.h src/xutf8/*.h src/xutf8/*.c cairo/*.c fluid/*.h fluid/*.cxx test/*.h test/*.cxx # # Run the clang.llvm.org static code analysis tool on the C sources. # (at least checker-231 is required for scan-build to work this way) # .PHONY: clang clang-changes clang: $(RM) -r clang scan-build -V -k -o `pwd`/clang $(MAKE) $(MFLAGS) clean all clang-changes: scan-build -V -k -o `pwd`/clang $(MAKE) $(MFLAGS) all fltk-1.4.3/mac_endianness.h0000644000175000017500000000115615004135251015730 0ustar albrechtalbrecht/* * Mac-specific configuration file for the Fast Light Tool Kit (FLTK). * * Copyright 1998-2011 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this * file is missing or damaged, see the license at: * * https://www.fltk.org/COPYING.php * * Please see the following page on how to report bugs and issues: * * https://www.fltk.org/bugs.php */ #ifdef __APPLE__ # ifdef __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # else # define WORDS_BIGENDIAN 0 # endif #endif fltk-1.4.3/CHANGES_1.1.txt0000644000175000017500000034033015004135251015000 0ustar albrechtalbrechtChanges in FLTK 1.1, up to FLTK 1.1.10 (December 27, 2009) CHANGES IN FLTK 1.1.10 RELEASED: Dec 27, 2009 - Widgets now remove stale entries from the default callback queue when they are deleted (STR #2302) - Fixed selection bug in Fl_Int_Input (STR #2292) - Fixed character set conversion functions (STR #2268) - Fixed image lib configure and fltk-config issues by backporting the image lib and zlib configure code from FLTK 1.3 (STR #2203) - Updated the bundled libpng to v1.2.40 (released Sep. 10, 2009) - Fixed Fl_Choice contrast with light-on-dark settings (STR #2219) - Added Xft2 font lookup table (STR #2215) - Fixed X server "lock", if a modal dialog window is opened while a menu is active (STR #1986) - Updated mirror sites in documentation (STR #2220) - Setting a default font for Xft (STR #2216) - Temporarily limited builds to 32-bit on OX S to stay compatible to Snow Leopard - Fixed Windows compile bug with "#define USE_COLORMAP 0" (STR #2241) - Fixed glibc 2.10 compiler problems (Fedora 11 and others) with scandir() and strchr() (STR #2222) - Fixed OpenGL shared context handling (STR #2135) - Fixed gray-scale images with alpha channel (STR #2105) - Fixed unexpected shortcut behavior for Win32 (STR #2199) - Added cast to Fl_Color in all Fluid code (STR #2206) - Fixed wrong identifier for special keys combined with modifier (STR #2196) - Fixed documentation for Fl_Progress (STR #2209) - Fix for multiple popups, when dragging and calling fl_alert() and friends from the callback (STR #2159) - Avoiding crashes for recursive common dialogs (this does not fix the issue at hand yet) (STR 2150) - Fluid printing used wrong colors under Windows (STR #2195) - Fixed bad system menu hadling in OS X (STR #2153) - Fixed File Input mouse pointer dragging (STR #2181) - Added Fl_Scroll::bbox() documentation (STR #1893) - Fixed static linking of image libraries (STR #1962) - Fixed callback would not be called when shortcut was used with radio and toggle buttons in default FL_RELEASE mode. - Fixed a problem with TrackMouseEvent() (Windows only) that would generate wrong FL_LEAVE events with subwindows. TrackMouseEvent is now enabled by default (it was disabled for GNU compilers). It can be disabled by defining NO_TRACK_MOUSE. Improved test/subwindow.cxx (STR #2079) - Fixed RGB colors for round box (STR #2097) - Fixed documentation (added missing COMCTRL32.LIB dependency) - Fl_Group::clip_children() is now public (STR #2017) - Fixed first modifier key event (STR #1952) - Fixed wrong default value of Fl_Spinner in Fluid (STR #1991) - Fixed Fluid textcolor output (STR #1992) - Added clarification to Fl_GL_Window mode function (STR #1945) - Fl_Group and Fl_Scroll now resize themselves before resizing their children (STR #2032) - Fixed adding an idle handler during a draw() call (STR #1950) - Improved stability of fl_read_image (STR #2021) - Fixed menu position close to screen border (STR #2057) CHANGES IN FLTK 1.1.9 RELEASED: Apr 27 2008 - Improved color contrast in secondary selection blocks of Fl_Text_Display (STR #1917) - Fixed regression in callback handling (STR #1918) - Fixed wrong relative path when absolute path has a trailing slash in fl_filename_relative (STR #1920) - Fixed multiple selection of files and directories in Fl_File_Chooser (STR #1913) - Fixed MSWindows crash when selecting umlauts in Fl_Help_View (STR #1912) CHANGES IN FLTK 1.1.8 RELEASED: Mar 27 2008 - Documentation fixes (STR #1454, STR #1455, STR #1456, STR #1457, STR #1458, STR #1460, STR #1481, STR #1578, STR #1639, STR #1645, STR #1644, STR #1792, STR #1793, STR #1742, STR #1777, STR #1794, STR #1827, STR #1843, STR #1796, STR #1815, STR #1726, STR #1753, STR #1855, STR #1862, STR #1867, STR #1874, STR #1888) - Fixed library path in Makefile (STR #1885) - Fixed image read for partial regions on X11 (STR #1716) - Fixed KDE/Gnome icon paths (STR #1795) - Fixed Tab key to wrap around menu bars (STR #1877) - Fixed possible timer leak in Scrollbar (STR #1880) - Added documentation about the potential limitations of Fl::grab on newer operating systems (STR #1747) - Fixed lockout when mixing popups and alerts (STR # 1869) - Fixed recursion crash in event handling (STR #1873) - Fixed missing return code in 'fltk-config' (STR #1875) - Fixed inconsistencies with CHANGED flags (STR #1719) - Fixed message sent to hidden widgets (STR #1849) - Fixed width calculation in Fl_Help_View (STR #1868) - Fixed offset bug in OS X pixmap code (STR #1856) - Fixed potential buffer overrun in Fl_Preferences (STR #1853) - Fixed method attributes in consecutive class declarations in FLUID (STR #1741) - FLUID checks for seperately declared callbacks to avoid a bogus "extern" declaration (STR #1776) - Added "protected" class memebrs in FLUID - Double-clicking a widget in a FLUID layout will show the item in the widget browser - Fixed color highlighting in Text_Display - Fixed 16 bit PNM image support (STR #1847) - Fixed exposure event on zero size windows (STR #1824) - Fixed overlay offset for OS X Quartz (STR #1729) - gl_font() support for Xft+X11 (STR #1809) - Fl_Gl_Window::mode() needed to hide and show the window when toggling stereo mode (STR #1846) - Fl_Gl_Window::show() did not work reliably on Mac OS X (STR #1707) - Added Fl_Group::clip_children() methods to support automatic clipping of child widget drawing (STR #1844) - Fl_Browser_ and friends now support FL_WHEN_ENTER_KEY for both Enter/Return and double-clicks (STR #1818) - Fl_Help_View did not release the images it used (STR #1817) - Shared libraries would not build on 64-bit Linux systems with an existing non-PIC FLTK installation (STR #1791) - Fl_Browser::hide() and Fl_Browser::show() did not correctly update the scrollbar (STR #1724) - The configure script now shows a summry of the configuration results (STR #1810) - "fltk-config --use-* --libs" did not list all of the dependent libraries (STR #1799) - Hiding a nested window on WIN32 caused 100% CPU (STR #1748) - Changing the window size in FLUID would not mark the project as modified (STR #1751) - Fixed fl_filename_isdir for "/"-path (STR #1761) - Fixed Fl_Chart drawing (STR #1756) - Fixed mapping of subwindows with unmapped parent windows (STR #1706) - Fixed rendering of grayscale images with alpha channel (STR #1703) - Fixed occasional incomplete refresh (STR #1681) - Improved fl_down, fl_frame, added fl_box (STR #1678) - Fixed selection of submenu items in input_choice (STR #1676) - Fixed calculation of stride for image scaling and color manipulation (STR #1673) - Made -O3 the default optimization on Cygwin/Mingw since -Os currently creates bad code (STR #1656) - OSF/Tru64 now uses 'install-sh' instead of 'install' to accomodate for a missing '-d' option (STR #1632) - New option in Fluid project settings to translate all shortcut modifiers from FL_META or FL_CTRL to FL_COMMAND - Made icon size fixed (50x50) in fl_message etc. (STR #1626) - Fixed selection of first word in Fl_Help_View - Fixed endless loop in Fl_Text_Display (STR #1655) - Allowing shortcuts in Tabs (STR #1652) - Fixed Makefile "make clean" (STR #1642, STR #1643, STR #1641) - The sample RPM spec file now enables large file support and threading support (STR #1603) - Changed minimum contrast between background and text to 99 and added more weight to the blue component to improve readability for certain color combinations (STR #1625) - Fixed VCNet OpenGL project file (STR #1617) - Fixed scrolling of clipped areas in MSWindows (STR #1601) - Fixed clipping in OS X Quartz offscreen buffers (STR #1595) - Now flush file chooser preferences after every change to avoid data loss (STR #1609) - The Fl_File_Chooser constructor now saves and restores the current group (STR #1611) - Added Fl::awake(fn*,void*) to set a handler for thread messages (STR #1536) - Added "mute sound" option to Sudoku game. - Updated the bundled zlib to v1.2.3. - Updated the bundled libpng to v1.2.16. - "make install" now uses the install command (or the included install-sh script) to copy files to the install directories, to ensure that permissions are correct. - Fixed DLL generation via MingW/Cygwin (STR #1546) - FLUID incorrectly opened the display when generating source code for Fl_Help_View widgets (STR #1318) - Fl_Double_Window did not always show the scheme background image. - Fixed first window behavior in OS X (STR #1548) - Fixed calculation of character widths for OS X Quartz rendering (no STR) - Fixed OS X mouse click handling (STR #1504) - Added missing GLUT functions so that FLTK can be used as a fairly complete C++ replacement for the original GLUT library (STR #1522) - Fl::awake() could block on X11 and OSX (STR #1537) - Updated recursive mutex code to run on platforms other than Linux and to do a run-time check to determine whether they are supported by the kernel (STR #1575) - WIN32 did check callbacks after the event processing instead of before as documented (STR #1535) - Fl_File_Chooser now hides the window before doing a callback when the user clicks on the OK button (STR #1565) - Fixed indentation of nested HTML elements (STR #1549) - Made layout of Fl_Help_Dialog consistent with other help windows and web browsers. - Improved GTK+ schemed round box (STR #1531) - Fluid avoids writing unsupported combinations of the "when()" flags (STR #1501) - Fl_Browser_ would allow keyboard callbacks even though "when()" was set to "never" (STR #1501) - Added automated little helpers to Sudoku - Added example code for Wizard with the Tabs demo (STR #1564) - Optimized Fl_Tabs drawing for speed (STR #1520) - OS X resource fork now obsolete (STR #1453) - Added chapter 10 about multithreading (STR #1532, 1533) - OS X system menu bar top level attribute support improved (STR #1505) - Fixed Quartz image drawing bug (STR #1438) - Fixed Quartz fl_read_image - Overlay drawing is now avoiding XOR mode (STR #1438) - Fixed Scroll crash in Fluid Live Mode (STR #1524) - Fixed mousewheel event propagation (STR #1521) - Fixed drawing issues of a tile in a scroll (STR #1507) - Fixed dismissing buttons in menu bars (STR #1494) - Making a child group visible in a Fl_Tabs or Fl_Wizard group now shows that tab or pane. - Added fl_open_uri() function as proposed on fltk.coredev. - Added Fl::has_check() which previously was prototyped and documented, but not implemented (STR #1542) - Enabled Fl::add_check() on OS X (STR #1534) - Documented tooltip inheritance (STR #1467) - Better event mouse handling fixing detached menus and sticky tooltips (STR #1463, STR #449) - Added Fl::scrollbar_size() methods that are used by all of the scrollbar-using widgets (STR #1500) - fl_read_image() was broken on Intel-based Macs (STR #1490) - Fl_Progress was using the wrong width to calculate progress (STR #1492) - Fl::x(), Fl::y(), Fl::w(), and Fl::h() did not report the desktop work area on X11 (STR #1482) - Shortcut events could be sent to the wrong window (STR #1451) - Fl_Spinner did not handle the arrow keys properly (STR #1476) - Fl_File_Browser did not calculate the width of directory items correctly (STR #1469, STR #1470) - Fl_Pack incorrectly started widgets at an offset of 1/2 the spacing value. - FLUID did not generate correct window class code if the class name was not a standard FLTK window class. - FLUID incorrectly included for widget classes that were not subclassed from a standard FLTK widget class. - The demo master test program now supports scheme selection and all demos use it (STR #1459) - fl_arc() and fl_pie() did not draw properly on WIN32 when the start and end points were identical (STR #1461) - Fl_Input and Fl_Text_Editor now hide the mouse pointer when typing into them (STR #1466) - Implemented alpha blending for Quartz, WIN32, and X11 - Check buttons did not redraw properly with box() set to FL_NO_BOX (STR #1440) - Added the Bluecurve-inspired scheme "gtk+". - Updated documentation (STR #1420, STR #1421) - Fixed font caching issue (STR #1415) - Fixed crash in fl_file_chooser (STR #1410) - Fixed Fluid hotspot bug (STR #1416) - Fixed image copy code (STR #1412) - Fixed latin-to-roman text conversion (STR #1411) - Fixed Cygwin timeout for "select" calls (STR #1151) - Improved Mac OS X subwindow handling (STR #1402) - Fixed more inconsistencies between fl_draw and fl_measure (STR #1408) - Fixed fl_measure which mistook a trailing '@@' for a symbol (STR #1406) - Fixed GLUT behavior on window creation (STR #1403) - Fixed OS X bug that would hide tooltips before they were shown (STR #1392) - Fixed Fl_Tabs tooltip reappearing (STR #1324) - Added a new demo game called "Block Attack!" - Updated the Sudoku game to show a notice about Hard and Impossible puzzles having multiple solutions which are not a bug or error (STR #1361) - Fixed filechooser to behave as documented when file pattern changes (STR #1359) - Completed the global function index and added an alphabetical list of all methods (STR #1319) - Avoiding problems with some platforms that don't implement hypot() (STR #1366) - Fixed floating point value formatting for Fl_Spinner (STR #1331) - Fixed Fl_Positioner callback when released (STR #1387) - Fixed WIN32 zero size window issue (STR #1387) - Fixed Sudoku window positioning (STR #1398) - Fluid Code Declarations can now handle C++ style comments (STR #1383) - Fixed uninitialized data in OS X and WIN32 timeout functions (STR #1374). - Fixed speed issues when measuring text on OS X with Quartz (STR #1386). - Fixed focus issues on OS X (STR #1377) - Optional precision argument when storing floats or doubles in a Preferences file (STR #1381) - Fixed callback not called when using arrow keys in Fl_Slider (STR #1333) - Changing the shortcut of a widget in fluid now marks the document as dirty (STR #1382) - Fl_Text_Editor now correctly handles middle mouse clicks (STR #1384) - Added some GLUT4 functions (STR #1370) - Added "context_changed()" function for OpenGL windows which allows efficient texture loading (STR #1372) - Added missing "const" to GLUT call (STR #1371) - Fixed stray FL_RELEASE events after clicking system areas on OS X (STR #1376) - FLUID now only writes definitions of "o" and "w" variables as needed, reducing the number of "variable is shadowed" warnings from GCC. - Added access to Xft font pointer (STR #1328) - Fixed endianness in OS X mouse cursor graphics (STR #1348) - Fixed crash on mixed use of keyboard and mouse for Fl_Menu_Button (STR #1356) - Fixed Fl_Window::visible() and shown() for OS X (STR #1341) - Fixed Fl_Window::copy_label() losing copy (STR #1332) - Documentation fixes (STR #1336, STR #1329, STR #1339, STR #1340) - Added support for floating point Fl_Spinner in the API, documentation, and Fluid (STR #1331) - Repeat button now cancels timeout if it should get deactivated during a callback (STR #1330) - Added support for assigning Fl_Menu_Items to array variables in Fluid (STR #1280) - Added --with-archflags configure option to allow passing of specific architecture-selection options to the compiler and linker. - Fixed WIN32 window stacking bug (STR #1296) - Fixed wrong code generated by FLUID for Scrollbars (STR #1287) - Loading a file would not update the Widget Properties dialog in FLUID (STR #1326) - Fixed key compose sequences for shifted keys (STR #1194) - Added text selection and copy to Fl_Help_View. - Fixed position of popup menu titles (STR #1322) - Showing any window will disable the current tooltip so it won't pop over menus (STR #1321) - Updated documentation to reflect limitation of Fl::delete_widget() (STR #1306) - Fixed line wrapping in Fl_Text_Display (STR #1227) - New function Fl::event_original_key() returns key code before NumLock handling. - Many OS X Quartz fixes (STR #1310, etc.) - Fixed shortcut and default focus for message dialogs (STR #1298) - Fixed focus issues (STR #1286, STR #1289, STR #1296) - Fixed window resizing in OS X (STR #1297) - In FLUID, declarations starting with the keyword 'typedef', 'class', or 'struct' are now treated correctly if inside a class (STR #1283) - Tabs now show the correct tooltip (STR #1282) - Included fltk.spec in configure.in (STR #1274) - Fixed insufficiently invalidated cache in Fl_Browser (STR #1265) - Attempt to fix multi monitor issues (STR #1153) - Fixed warnings when compiling w/Cygwin (STR #1152) - Fixed missing reset of flag in FLUID (STR #1187) - Fixed maximizing in OS X (STR #1221) - Fixed 'make distclean' to remove binaries inside MacOS app packages (STR #1169) - FLUID Code Viewer is now truly a viewer, not a text editor because edited text can not be saved. - Fl_Spinner is now fully supported by FLUID (STR #1158) - Fixed usage of deleted object after menu pulldown (STR #1162) - Calling fl_font(0, 0) under Xft would access a NULL pointer (STR #1205) - Setting a new value in Fl_Input_ wil now actually move cursor to the end of the input field as documented (STR #1161) - FLUID crashed on WIN32 with international characters (STR #1176) - Fl_Check_Browser did not allow the user to toggle the check boxes (STR #1232) - Fl_Help_View crashed on WIN32 with international characters (STR #1228) - Fl::run() no longer clears resources on WIN32 (STR #1231) - Fl::add_timeout() leaked resources on OSX (STR #1233) - Accented characters could not be entered on OSX (STR #1195) - The caret key lookup was missing for OS X - FLUID didn't handle loading .fl files with international characters properly with all compilers (STR #1150) - Fl_Spinner's minimum() and maximum() "get" methods were misspelled (STR #1146) - The largefile support changes in 1.1.7 broke binary compability for fl_filename_list(); you must now use "--enable-largefile" when configuring to get large file support, and the large file support definitions are added to the output of "fltk-config --cflags" (STR #1159) CHANGES IN FLTK 1.1.7 RELEASED: Jan 17 2006 - Documentation fixes (STR #571, STR #648, STR #692, STR #730, STR #744, STR #745, STR #931, STR #942, STR #960, STR #969) - Various menu widget fixes (STR #1140, STR #1143, STR #1144) - The threads demo would display negative prime numbers on MacOS X; this appears to be a MacOS X bug, but we added a workaround to "fix" this (STR #1138) - Fl::dnd() now sets the content type of the drag to "text/uri-list" when it sees the dragged text is composed of URIs. - Fixed keyboard shortcut handling in FLUID and shortcut labeling in FLTK (STR #1129) - Fixed include path for CMake build (STR #1123) - Fixed unnecessary delay in WIN32 event handling (STR #1104) - Fixed handling of Ctrl-C in Fl_Text_Display (STR #1122) - OS X Quartz version now draw a nice resize control (STR #1099) - FLTK now enables large file support when available (STR #1087) - Fl_Clock_Output depended on a time value that was the same as an unsigned long, which is incorrect for WIN64 and VC++ 2005 (STR #1079) - Fl_Text_Display::wrap_mode() would crash if no buffer was associated with the widget (STR #1069) - Updated the default label and text colors of all widgets to use FL_FOREGROUND_COLOR instead of FL_BLACK (STR #1052) - Fl::set_fonts() now works with Xft (STR #1012) - Fl_Value_Input now uses the screen-absolute position instead of the window-relative position when dragging the value; this avoids some jumping conditions (STR #1037) - Menus now pop up fully inside the screen if possible (STR #973) - Fixed illegal access in Preferences (STR #1025) - Fixed x-offset problem in Help_Widget (STR #998) - Clipboard will persist if owner window is hidden (STR #1019) - Fixed handling of Win32 Device Contexts (STR #1007) - Fixed C++ style comments in C files (STR #997) - Fixed signedness of scanf() argument (STR #996) - Fixed cross-compiling problem (STR #995). - FLUID now knows if a static callback is already declared in a class and won't declare it 'extern' (STR #776) - Some actions in FLUID would not set the "changed" flag (STR #984, STR #999) - fl_filename_list now always appends a forward slash to directory names (STR #874) - Multiline Input will update right if a space character is inserted in word wrap mode (STR #981) - FLUID group labels redraw correctly (STR #959) - FLUID now updates color of Fl_Tabs children (STR #979) - FLUID now supports 'size_range()' (STR #851) - FLUID selection boxes now synchronised (STR #964) - fl_filename_list() now recognizes pathnames without trailing slash as directions (STR #854) - Fl_Text_Display now auto-scrolls in all directions (STR #915) - Borderless windows will not show in the taskbar anymore on X11 (STR #933) - Fixed event_text() field on FL_DND_* event on OS X and WIN32 (STR #968) - The fltk-config utility now supports "--cc" and "--cxx" options to get the C and C++ compilers that were used to compile FLTK (STR #868) - Fl_Valuator-derived widgets could show more digits than were necessary (STR #971) - Fl_GIF_Image did not handle images with an incorrect number of data bits (STR #914) - Fixed some plastic drawing artifacts (STR #906) - Fl_Help_View now draws the box outside the scrollbars, like the other scrollable widgets (STR #871) - The fltk-config script now handles invocation via a symlink (STR #869) - Updated WIN32 cut/paste code to consistently handle DOS text (STR #961) - Added shared library support for Cygwin and MingW (STR #893) - Fl_File_Chooser did not implement the user_data() methods (STR #970) - Compilation could fail if a previous installation of FLTK was in the same (non-standard) directory as an image library (STR #926) - Fixed OSX compilation problems with non-HFS filesystems (STR #972) - Problems with CMake on MinGW have been solved, thanks to Mr. "fltk.x0", who submitted the patch. (STR #863) - Fixed memory leak in Fl_Check_Browser reported by "miguel2i". (STR #967) - Fl_File_Input could draw in the wrong window (STR #958) - WIN32: Internal WM_PAINT message now ignored (STR #831) - Added Windows support for Fl_Window::xclass() (STR #848) - Floating point input field allows characters from current locale (STR #903) - Fixed integration of Fl_Input_Choice into FLUID (STR #879) - New windows touching the right screen border would be positioned all the way to the left (STR #898) - Made pie drawing size for WIN32 and OS X the same as X11 (STR #905) - Fixed OS X issue with OpenGL windows inside of Tabs (STR #602) - FLUID Code Editor would occasionally not draw the last character in the buffer (STR #798) - FLUID Declaration private flag fixed (STR #799) - FLUID overlay now shows a seperate bounding box of selected items with correct handles and a dotted boundig box for all labels (STR #790) - Fixed left overhang of large chracters in Fl_Input_ (STR #941) - Fixed button resizing in File Chooser (STR #884) - Fixed FLUID redraw issue (STR #912) - Added 32bit BMP Image file format support (STR #918) - Value Sliders would not receive focus when clicked on (STR #911) - Added redraw of some widgets to show focus change (STR #910) - Fl::set_font would not clear 'pretty' name (STR #902) - Fixed unescaped '@' in fonts demo (STR #867) - FLUID should not open the Display connection anymore if creating code only (STR #904) - Improved hidden copy / ctor implementation (STR #860) - Increased matrix stack depth and added over/underflow error (STR #924) - Reverted Mac Carbon Clipping simplification that broke subwindow clipping (STR #908, SVN r4386) - Fixed bitmap scaling code - Fixed tiny memory leak (STR #878) - Fixed hang on corrupt jpeg (STR #915) - Fixed static allocation of font buffer in demo (STR #909) - Added symbols 'refresh', 'reload', 'undo', and 'redo'. - Fixed focus loss on Fl_Window:resize() - Fl::delete_widget would hang fl_wait after deleting the window (STR #679) - Fl::paste would sometimes not recoginze external changes of the clipboard (STR #722) - Clipping fixes for OSX - Removed attempt to find items via Fl_Menu_::find_item() in linked submenus - FLUID interactive window resizing fixes (STR #873, 791) - FLUID panel resize and alignment fixes (STR #891) - Fl_Window::show(argc, argv) now sets the scheme before showing the window; this should eliminate any flickering between the standard and plastic schemes on startup (STR #886) - Selected tabs are now drawn slightly larger than unselected tabs so they stand out more (STR #882) - Round Plastic boxes now draw round (STR #841) - FL_PLASTIC_DOWN_BOX drew with artifacts (STR #852) - Changed initializations on WIN32 (STR #862) - Fl_Preferences::getUserdataPath() didn't work for sub-groups (STR #872) - Fixed some redraw issues on Windows XP. - FLUID didn't set the initial size of widgets properly (STR #850) - Fl_Tabs would steal focus away from its children on a window focus change (STR #870) - filename_relative() now converts the current directory to forward slashes as needed on WIN32 (STR #816) - Fl_File_Chooser::value() and ::directory() now handle paths with backslashes on WIN32 (STR #811) - Added the standard rgb.txt file from X11 to the test directory, allowing all platforms to try the colbrowser demo (STR #843) - Resizing of OpenGL subwindows was broken on OSX (STR #804) - The fltk-config script now supports running from a source directory (STR #840) - Fl_Browser_ didn't update the position properly when an item was deleted (STR #839) - fl_contrast() now compares the luminosity of each color (STR #837) - Fl_Input_ crashed on some platforms when wrapping international text characters (STR #836) - Fixed some BMP images loading bugs (STR #825) - Fl_File_Chooser now returns directory names with a trailing slash to avoid problems with relative filenames (STR #819) - Fl_Help_View now supports the FONT and U elements (STR #815) - OpenGL windows that were completely off-screen caused problems with some graphics cards on WIN32 (STR #831) - Multiple screen support didn't work on Windows NT and 95 (STR #821) - Fl_Scrollbar didn't compute the correct knob size when using the "nice" types (STR #845) - fl_draw() would segfault on WIN32 if no font was set; it now uses the default font (STR #828) - Fl_Browser_ was calling the callback multiple times for a single selection change with FL_WHEN_CHANGED (STR #834) - Added "filenew", "fileopen", "filesave", "filesaveas", and "fileprint" symbols with standard toolbar symbology. - Updated Fl_Tabs to check the contrast of the label color against the tab background, and to highlight the top 5 lines of the tab pane with the selection color so that selected tabs stand out more. - The example programs can now compile separate from the FLTK source distribution (STR #809) - The example programs are now installed with the documentation (STR #809) - Fixed the drawing of the Fl_Browser_ selection box (STR #786) - Dropped Codewarrier project files and support. - The FLTK string functions are now compiled in on all systems (STR #774) - Fixed symbol demo label bug (STR #777) - Fixed position of menu titles (STR #795) - Added missing Fl_Window::copy_label() method. - Fixed wrong tooltip in FLUID (STR #784) - Added zlib path to FLUID (STR #783) - Menus and other pop-up windows now obey screen boundaries on multi-screen displays (STR #781) - Fl_Chart would draw outside its bounding box (STR #780) - Added Fl::screen_count() and Fl::screen_xywh() APIs to support multi-screen displays. - FLUID now supports direct creation of widget classes. - Fl_File_Chooser now correctly handles multiple selections that are a mix of files and directories. - Fl_File_Chooser no longer resets the type() when choosing a single file, and it now works when selecting multiple directories (STR #747) - Fl_File_Icon::load_system_icons() now only loads 16x16 and 32x32 icon images to improve startup performance. - Pressing Enter in the file chooser when selecting a directory will choose that directory if it is currently shown (STR #746) - Added a fl_file_chooser_ok_label() function to set the "OK" button label for the fl_file_chooser() and fl_dir_chooser() functions. - Added Fl_File_Chooser::ok_label() methods to set the "OK" button label. - The fl_ask() function is now deprecated since it does not conform to the FLTK Human Interface Guidelines. - The Fl_File_Chooser window now properly resizes its controls (STR #766) - The Fl_Help_Dialog window now properly resizes its controls (STR #768) - The Fl_File_Chooser favorites window is now resizable (STR #770) - Now provide FL_PLASTIC_ROUND_UP/DOWN_BOX box types which are used by the plastic scheme. - FLUID windows that are resized through the widget panel now remain resizable by the window manager. - Increased the size of the background image used by the plastic scheme to reduce the CPU load of redraws (STR #769) - Fixed a syntax highlighting bug in the editor demo. - Fl_Progress now contrasts the label color with the bar color, so labels will be readable at all times. - fl_read_image() didn't use the right red, green, and blue masks on XFree86. - Fixed Quickdraw drawing of 3 and 4 sided polygons (STR #765) - Fixed fl_message() code so that it does not get accidentaly addded to the current group (STR #253) - FLUID now highlights code in the widget callback and code editors. - FLUID now supports printing of windows. - Fixed inactive drawing of border, embossed, and engraved box types. - Added Fl_Spinner widget (another combination of existing widgets in a header file) - FLUID now provides support for UI templates. - fl_not_clipped() incorrectly used the current window dimensions for gross clipping, which interfered with off-screen rendering. - Fl_Window::draw() and Fl_Window::iconlabel() could leak memory if copy_label() was used on the window. - fl_shortcut_label() now shows letter shortcuts in uppercase, e.g. "Ctrl+N" instead of "Ctrl+n" to be consistent with other toolkits. - FLUID now provides unlimited undo/redo support. - FLUID now provides an option to choose which scheme (default, none, plastic) to display. - Fixed scheme background issue with windows in FLUID. - In FLUID, new widgets are now created with the ideal size by default, and menu bars are positioned to use the entire width of the window. - Added Layout/Widget Size submenu to select default label and text size (Tiny, Small, and Normal). - Added Edit/Duplicate command to FLUID to duplicate the current selection. - FLUID now tracks the current state of the widget bin and overlays. - Now fill the widget image paths with relative filenames. - Fixed frame drawing of Fl_Text_Display (STR #762) - Fl_Clock_Output::value() did not return the previously set value (STR #748) - Added comment type to FLUID. This is useful for generating copyright notices in the source and header files. - Fl_Valuator would not format text output with decimal point when the step value was fractional, but above 1. - fl_filename_relative() didn't compare drive letters in a case-insensitive way (STR #741) - Fixed menu item width calculations with symbols (STR #740) - The keyboard shortcut handling code did not handle 8-bit characters properly (STR #731) - Fl_JPEG_Image could still crash an app with a corrupt JPEG file (STR #739) - Using the layout alignment controls on a menu widget would cause FLUID to crash (STR #742) - Added QNX bug workaround for menu handling (STR #704) - Added Greg Ercolano's simple Fl_Input_Choice widget which is a combination of the Fl_Input and Fl_Menu_Button widgets (STR #650) - Fl_Multiline_Input now scrolls the full height of the widget instead of 5 lines when the user presses PageUp or PageDown (STR #727) - CMake build fixes (STR #724) - Fl_Browser::swap() didn't handle redraws properly when the swapped lines had different heights (STR #729) - FL_MOUSEWHEEL events are now sent first to the widget under the mouse pointer and then to the first widget which accepts them. This is similar to the way shortcut events are handled and is consistent with the way the mouse wheel is handled by other toolkits. - Fl::wait() could block on WIN32 if the window was deleted via Fl::delete_widget() (STR #679) - Fl_Preferences::RootNode did not find the user's home directory on some non-US versions of Windows (STR #720) - Fl_Window::hide() didn't delete the current clipping region on WIN32, causing a GDI resource leak in some situations (STR #723) - Removed a few warnings when compiling on OS X - Fl_Menu now draws the arrow more like other toolkits and 2.0 (STR #651) - Fixed a VC++ compiler error in Fl_JPEG_Image.cxx (STR #676) - FL_SHADOW_BOX/FRAME drew outside of the bounding box (STR #694) - Fl_Widget::copy_label(NULL) didn't work (STR #707) - Fl_Choice now allows click selection like Fl_Menu_Button and Fl_Menubar (STR #706) - Updated cmake support (STR #645) - Fl_Check_Browser didn't draw properly when inactive (STR #681) - Removed some redundant code in Fl_Group::handle() (STR #669) - The file chooser didn't always deactivate the OK button when necessary (STR #653) - Image drawing on OSX changed the current drawing colors (STR #662) - Fixed some compiler errors on WIN32 (STR #647, STR #726) - FLUID didn't update the widget panel X/Y/W/H values when moving the selected window (STR #701) - FLUID didn't use the label type constant names for menu items, causing them to be drawn using the normal label type (STR #668) - Fl_File_Chooser was slow with large directories (STR #654) - FLUID didn't add xclass() calls to windows (STR #718) - The X11 DND code did not correctly select a text format for incoming data (STR #711) - Fixes to Fl_JPEG_Image error handler. - Fl_Menu::popup() and ::pulldown() would crash an application if a callback created widgets before they returned (STR #685) - Fl_Double_Window would cause a full redraw, even if only small parts of the UI were changed on Mac OS X. - Fl_JPEG_Image did not correctly handle errors reported by the JPEG library (STR #652) - Fl_Menu now draws sub-menu arrows like other toolkits and FLTK 2.0 (STR #651) - Fixed a compiler warning in Fl_Window.H (STR #641) - Tooltips disabled shortcut processing (STR #643) - Fl::event_number() didn't always match the value sent to the handle() method (STR #634) - Fl_Shared_Image::reload() didn't set the image_ pointer properly in all cases (STR #632) - Fl_Help_View::topline() incorrectly set the changed() flag (STR #631) - Fl_Choice::value() now supports NULL or -1 to deselect the current item (STR #637) - More VC++ 6 project file fixes (STR #638) - Added missing Watcom makefile in the test directory (STR #636) - Fl_Text_Display::word_left would hang if the cursor was at position 0 (STR #635) CHANGES IN FLTK 1.1.6 RELEASED: Nov 23 2004 - Documentation updates (STR #552, STR #608) - Added the 2.0 Fl_Widget::copy_label() method to allow FLTK 1.x applications to have their label strings managed by FLTK (STR #630) - Added Fl::delete_widget() method to safely delete widgets in callback methods (STR #629) - Fl_Widget::damage(uchar,int,int,int,int) didn't clip the bounding box properly (STR #626) - Windows could appear on the wrong screen on OSX (STR #628) - Fl_Double_Window produced an error on resize with X11 - FLUID didn't display menu items using images properly (STR #564) - Fl_Sys_Menu_Bar didn't compile on case-sensitive file-systems (STR #622) - FLUID didn't handle default function parameters properly (STR #579) - Moving or resizing widgets in FLUID didn't always update the widget panel (STR #600) - FLTK windows could appear off-screen on X11 (STR #586) - The configure script did not support --disable-localfoo to completely disable image file support (STR #582) - The Visual C++ 6.0 project files still listed the old JPEG, PNG, and ZLIB library names (STR #577) - Fixed the scandir() conditional code for HP-UX 11i (STR #585) - Fl_Text_Display didn't support CTRL/CMD-A/C (STR #601) - Watcom fixes (STR #581, STR #584, STR #594, STR #595, STR #623, STR #627) - Fixed library include order when building DSOs on MacOS X (STR #596) - fl_xid() could cause a WIN32 application to crash (STR #560, STR #576, STR #618) - Fl_Browser::remove_() removed the item from the list before computing the item height, which caused problems with some programs (STR #613) CHANGES IN FLTK 1.1.5 RELEASED: Oct 19 2004 - Documentation updates (STR #568, STR #570) - Shortcuts were incorrectly underlined in multi-line labels (STR #566) - More CMake updates (STR #499) - The Watcom C++ compiler needed a small change (STR #567) - Added DESTDIR support and now remove all man pages for the "uninstall" target (STR #545) - Fix PNG drawing on buggy WIN32 graphics cards (STR #548) - The configure script didn't propagate the CPPFLAGS environment variable (STR #549) - The numpad keys didn't work properly on WIN32 (STR #502) - fl_input() and friends now set the input focus to the text field when the dialog is shown (STR #553) - Fixed background color mixup when drawing Fl_Choice menus (STR #544) - Fixed MingW makefiles (STR #550) - More VC++ project file tweaking (STR #559) - Fl_PNG_Image didn't use the png_set_trns_to_alpha function when available (STR #547) - The FL_UNFOCUS event wasn't always sent when switching tabs (STR #558) CHANGES IN FLTK 1.1.5rc3 - Documentation updates (STR #505, STR #513) - Updated PNG library source to 1.2.7. - Updated ZLIB library source to 1.2.1. - Fixed VC++ project file problems (STR #476, STR #478, STR #520, STR #527, STR #537) - Now look for 8 bits of alpha when the developer has requested FL_RGB8 (STR #541) - The last line in an Fl_Help_View widget was not aligned properly (STR #536) - The "search" symbol looked like a Q (STR #536) - Changed Fl_Help_View::get_color() to use a lookup table to avoid serious Borland C++ 5.5 compiler bugs (STR #533) - Fixed Watcom compiler warnings with FL/Fl_Widget.H (STR #540) - The image class copy() methods did not always make a separate copy of the image data (STR #539) - Fixed an edge case in fl_old_shortcut() that could cause it to read beyond then end of the shortcut string (used for XForms named shortcuts) - Added (unsupported) CMake files (STR #499) - Tooltips would not reappear on the same widget, and the initial tooltip delay was not used after a tooltip was shown (STR #465) - Fixed a compile problem with the Linux 2.6 threading support (STR #483) - Fixed problems with 2-byte Xpm files on 64-bit platforms (STR #525) - FLTK didn't handle the ReparentNotify event on X11 (STR #524) - The old source file "fl_set_gray.cxx" is not needed (STR #516) - Fl_Text_Display still called delete[] instead of free() in one place (STR #503) - The symbol test program did not handle the @+ symbol properly (STR #490) - Fl_File_Chooser didn't correctly call isprint() and isspace() when checking to see if the current file was text that can be previewed (STR #517) - FLUID didn't compile with Borland C++ due to a compiler bug (STR #496) - Fl_Positioner did not handle reversed min and max values (STR #510) - fl_descent(), fl_height(), and fl_width() would crash a program if you didn't call fl_font() first; they now return -1 if no font is set (STR #500) - Added test/unittests to verify pixel drawing and alignment across platforms - Fl_Menu_::find_item() didn't determine the menu path properly (STR #481) - The build system now installs image library header files in FL/images/filename.h so that FLTK programs will use the same header files as the FLTK image libraries. - The build system now creates image libraries named "libfltk_name.a" instead of "libname.a" to avoid clobbering an existing installed library (STR #480) CHANGES IN FLTK 1.1.5rc2 - Documentation updates (STR #365, STR #399, STR #407, STR #412, STR #414, STR #452, STR #462) - Fl_Text_Display did not handle drawing of overlapping text (italic next to plain, etc.) properly (STR #381) - All of the core widgets now consistently set changed() before calling the callback function for a change in value; this allows programs to check the changed() state in a callback to see why they are being called (STR #475) - Fl_File_Chooser did not handle some cases for filename completion (STR #376) - Fl_Help_View didn't properly compute the default maximum width of the page properly, resulting in non-wrapped text in table cells (STR #464) - Fl_Text_Editor no longer tries to emulate the Emacs CTRL-A shortcut to move to the first column, since there is a key for that and the widget does not emulate any other Emacs keys (STR #421) - Fl_File_Chooser always disabled the OK button when the user pressed DELETE or BACKSPACE (STR #397) - Added Fl_Browser::swap() methods (STR #459) - Fl_Counter didn't use a thin down box for the text field if the box type was set to FL_THIN_UP_BOX (STR #467) - Fl_Help_View now resets the scrollbars if they go outside the current view (STR #464) - fl_dir_chooser() did not show the previous selection as documented (STR #443) - Fl_Text_Display used delete[] instead of free() in some places (STR #466) - FLTK now includes copies of the PNG, JPEG, and ZLIB libraries for platforms that do not have them (STR #441) - The fltk-config script did not include the "-mno-cygwin" option under CygWin (STR #434) - Fl_Help_View::find() did not check for a NULL value (STR #442) - Added search symbol to the search field of Fl_Help_Dialog (STR #417) - Added two new symbols, @search and @FLTK, which can be used in labels. - MacOS X: fixed NumLock mixup, added support for FL_Menu and FL_Delete keys on external (PC) keyboards (STR #445) - Fl_File_Icon::draw() did not support drawing of complex polygons in icon descriptions (STR #474) - The configure script now offers options for JPEG, PNG, and ZLIB libraries (STR #416) - The first menu item in a list would not go invisible (STR #406) - Fl_Text_Buffer::replace() now range checks its input (STR #385) - FLTK now builds with the current release of MinGW (STR #325, STR #401, STR #402) - FLTK now honors the numlock key state (STR #369) - The Fl_Text_Display widget did not redraw selections when focus changed (STR #390) - The plastic background image is now less contrasty (STR #394) - Fl_Scroll now uses a full redraw when the scheme is set to plastic and the box type is a frame (STR #205) - Fl_Window::resize() did not work properly with KDE 3.2 (STR #356) - FLTK didn't delete font bitmaps when the last OpenGL window was deleted, preventing future text from displaying (STR #310) - FLUID didn't include a full initialization record for the trailing NULL menu items (STR #375) - Fl_Browser::item_width() did not properly handle format modifiers (STR #372) - Fl_Browser::item_height() did not handle columns properly (STR #371) - Fl_Gl_Window's on WIN32 now prefer accelerated pixel formats over generic formats (STR #382) - Fl_Window::resize() did not work on some systems if the window was not shown (STR #373) - FLUID did not write the user_data type if the user_data field was empty (STR #374) - The value(const Fl_Menu_Item*) method was not implemented for Fl_Choice (STR #366) - Fl_Pack didn't draw child widget labels the same way as Fl_Group, causing display problems (STR #360) - fl_read_image() didn't work when reading from an offscreen buffer with some X11 servers (STR #364) CHANGES IN FLTK 1.1.5rc1 - Documentation updates (STR #186, STR #245, STR #250, STR #277, STR #281, STR #328, STR #338) - fl_scroll() did not handle scrolling from off-screen on WIN32 (STR #315) - Fl_File_Chooser did not allow manual entry of a drive letter (STR #339) - Fl_Menu now uses the boxtype to redraw the menu background (STR #204) - Fl_Scroll now shows the background image when a framed box type is used and the Fl_Scroll is a direct decendent of a window (STR #205) - Added a new_directory_tooltip string pointer to allow localization of the file chooser's new directory button (STR #340) - Added Fl_Menu_::find_item() method (STR #316) - The Fl_Widget copy operator definitions were not conditionally compiled properly (STR #329) - FLUID's Layout functionality did not move child widgets when laying out group widgets (STR #319) - FLUID's Layout->Center In Group functionality did not properly handle widgets that were children of a Fl_Window widget (STR #318) - The Fl_Text_Display destructor did not remove the predelete callback associated with the current buffer (STR #332) - Fixed several bugs in the MacOS X Fl::add_fd() handling (STR #333, STR #337) - The Fl_Text_Display widget did not display selections set by the application (STR #322) - FLUID crashed if you did layout with a window widget (STR #317) - Fl_Scroll::clear() didn't remove the child widget from the Fl_Scroll widget (STR #327) - Fl_Value_Slider::draw_bg() didn't always apply the clipping rectangle (STR #235) - fl_filename_relative() returned the wrong string if the absolute pathname was equal to the current working directory (STR #224) - Fl_Help_Dialog didn't correctly restore the scroll position when going forward/back in the link history if the file changed (STR #218) - glutGetModifiers() did not mask off extra state bits, confusing some GLUT-based applications (STR #213) - Fixed mouse capture problems on MacOS X (STR #209, STR #229) - Fl_Sys_Menu_Bar is now built into the library for MacOS X (STR #229) - Fl_Menu_ now provides item_pathname() methods to get the "pathname" of a menu item, e.g. "File/Quit" (STR #283) - Fl_Text_Display now provides cursor_color() methods to get and set the cursor color (STR #271) - Fl_Scroll didn't honor FL_NO_BOX (STR #305) - FLUID declaration blocks didn't support public/private definitions (STR #301) - Fl_Preferences incorrectly created the preferences directory before necessary (STR #247) - The WIN32 project files still defined the (obsolete) FL_STATIC constant (STR #279) - Fl_Text_Display::buffer() did not support NULL values, making it impossible to clean up text buffers from a subclass (STR #295) - Fl_Text_Display did not support a NULL unfinishedStyleCB function (STR #241) - Fl::background2() incorrectly marked the foreground color as initialized (STR #255) - Fixed the X11 CTRL + "-" detection code to properly track the state of the CTRL key (STR #264) - Fl_File_Icon::load_system_icons() didn't support KDE 3.x (STR #299) - WIN32's scandir() emulation did not allocate enough memory for directory names (STR #263) - Fl::compose() did not handle special keys like backspace properly (STR #293) - Fl_Choice did not clip its text when drawing using the plastic scheme (STR #287) - Fl_Group incorrectly mapped the emacs CTRL keys to keyboard navigation (STR #228) - Fl_File_Browser::load() didn't handle a NULL directory name (STR #266) - 64-bit library fixes (STR #261) - The Fl_Valuator::format() function did not limit the size of the number buffer (STR #268) - The keypad Enter key works as the normal Enter/Return key in common widgets (STR #191) - Fixed some OS/2-specific build problems (STR #185, STR #197) - Calling Fl_Text_Display::buffer() with the same buffer would cause an application to lockup (STR #196) - Some of the widgets could crash an application if the cursor was changed after a window was deleted (STR #181) - The Fl_Gl_Window WIN32 pixel format code did not choose the pixel format with the largest depth buffer (STR #175) - The configure script didn't leave space between the CFLAGS/CXXFLAGS and X_CFLAGS variables (STR #174) - The Fl_JPEG_Image and Fl_PNG_Image classes did not trap errors from the corresponding image libraries (STR #168) - Added "--with-links" configure option to control whether symlinks are created for the FLTK header files (STR #164) - Added new hoverdelay() to Fl_Tooltip to control how quickly recent tooltips appear (STR #126) - FLUID now sets the size range when a window is shown. This seems to be necessary with some window managers (STR #166) CHANGES IN FLTK 1.1.4 RELEASED: Sep 08 2003 - The fl_read_image() function was not implemented on OSX (STR #161) - VC++ 7.1 didn't like how the copy operators were disabled for the Fl_Widget class; now include inline code which will never be used but makes VC++ happy (STR #156) - Fixed an IRIX compile problem caused by a missing #include (STR #157) - FLUID didn't write color/selection_color() calls using the symbolic names when possible, nor did it cast integer colors to Fl_Color (STR #146) - Fl_File_Chooser was very close for multiple file selection in large directories (STR #140) - Fl_Text_Display/Editor did not disable the current selection when focus was shifted to another widget (STR #131) - Fl_Choice didn't use the normal focus box when the plastic scheme was in use (STR #129) - Fl_Text_Editor didn't use selection_color() consistently (STR #130) - The fltk_forms, fltk_gl, and fltk_images DSO's and HP-UX shared libraries are now linked against the fltk shared library to provide complete dependency resolution (STR #118) - The configure.in file did not work with autoconf 2.57. - FLUID didn't redraw widgets when changing the X, Y, W, or H values in the widget panel (STR #120) - Fl_Window::show(argc, argv) wasn't calling Fl::get_system_colors() as documented (STR #119) - DSO (shared library) building wasn't quite right for some platforms (STR #118) - OSX: some changes to make ProjectBuilder compiles possible. - OSX: FLTK would not know where a window was positioned by the OS. As a result, popup menus could open at wrong positions. CHANGES IN FLTK 1.1.4rc2 - Fl_Window::show(argc,argv) incorrectly opened the display prior to parsing the arguments; this prevented the "-display foo" option from working (STR #111) - Images were not clipped properly on MacOS X (STR #114) - Fl::reload_scheme() and Fl::scheme("foo") incorrectly called Fl::get_system_colors(). This prevented an application from setting its own color preferences (STR #115) - The 'Enter' key event on OS X would not set Fl::e_text. - Changed behaviour of FLUID to always paste into a selected group (STR #88) - Menuitem now changes font, even if fontsize is not set (STR #110) - Swapped shortcut labels in OS X (STR #86) - Non-square Fl_Dial would calculate angle from user input wrong (STR #101) - Updated documentatiopn of fl_draw (STR #94) and Fl_Menu_::add() (STR #99) - FLUID collapse triangle events were not offset by horizontal scroll (STR #106) - QuitAppleEvent now correctly returns from Fl::run() instead of just exiting (STR #87) - Hiding the first created OpenGL context was not possible. FLTK now manages a list of contexts (STR #77) - FLUID didn't keep the double/single buffer type for windows. - FLTK didn't work with Xft2. - OSX window resizing didn't work (STR #64) - Fixed MacOS X shared library generation (STR #51) - Several widgets defined their own size() method but didn't provide an inline method that mapped to the Fl_Widget::size() method (STR #62) - Fl_Scroll didn't provide its own clear() method, so calling clear() on a Fl_Scroll widget would also destroy the scrollbars (STR #75) - Fl::event_text() was sometimes initialized to NULL instead of an empty string (STR #70) - fl_draw() didn't properly handle a trailing escaped "@" character (STR #84) - Added documentation for all forms of Fl_Widget::damage() (STR #61) - Fl_Double_Window now has a type() value of FL_DOUBLE_WINDOW, to allow double-buffered windows to process redraws properly on WIN32 (STR #46) - Added FL_DAMAGE_USER1 and FL_DAMAGE_USER2 damage bits for use by widget developers (STR #57) - Fl_Help_View didn't support numeric character entities (STR #66) - Menu shortcuts didn't use the Mac key names under MacOS X (STR #71) - CodeWarrior Mac OS X updated to work with current CW8.3 (STR #34) - Apple-C/X/V/Z didn't work in the Fl_Input widget due to a bad mapping to control keys (STR #79) - Added the OSX-specific fl_open_callback() function to handle Open Documents messages from the Finder (STR #80) - The configure script contained erroneous whitespace in various tests which caused errors on some platforms (STR #60) - The fltk-config script still supported the deprecated --prefix and --exec-prefix options; dropped them since they serve no useful purpose and would never have worked for the intended purpose anyways... (STR #56) - fl_filename_list returned 0 on Win32 if no directory existed (STR #54) - Pressing 'home' after the last letter in a Text_Editor would move the cursor to pos 0 (STR #39) - Fl::get_key(x) would mix up Ctrl and Meta on OS X (STR #55) - The configure script used the wrong dynamic library linking command for OSX (STR #51) - The Fl_Text_Editor widget did not set changed() nor did it call the widget's callback function for FL_WHEN_CHANGED when processing characters that Fl::compose() handles (STR #52) CHANGES IN FLTK 1.1.4rc1 - The file chooser did not reset the click count when changing directories; if you clicked on a file in the same position after changing directories with a double-click, the chooser treated it as a triple click (STR #27) - Symbols with outlines did not get drawn inactive. - The Fl_Help_View widget now provides a find() method to search for text within the page. - The Fl_Help_Dialog widget now provides a search box for entering text to search for. - The default font encoding on OSX did not match the default on WIN32 or X11. - Menu items were not drawn using the font specified in the Fl_Menu_Item structure (STR #30) - Long menus that were aligned such that the top of an item was exactly at the top of the screen would not scroll (STR #33) - The OS issues appendix incorrectly stated that MacOS 8.6 and 9 were supported; they are not (STR #28) - Fixed handling of nested double-buffered windows (STR #1) - Showing a subwindow inside a hidden window would crash the application (STR #23) - OSX users couldn't enter some special chars when using some foreign key layouts (STR #32) - Hiding subwindows on OSX would hide the parent window (STR #22) - Added thin plastic box types. - Fl_Pack ignored the box() setting and cleared any unused areas to the widget color; it now only does so if the box() is set to something other than FL_NO_BOX. - Updated the Fl_Tabs widget to offset the first tab by the box dx value to avoid visual errors. - Updated the plastic up box to draw only a single border frame instead of the old double one for improved appearance. - Updated the default background color on OSX to provide better contrast. - Fl_Text_Display and friends now look for the next non-punctuation/space character for word boundaries (STR #26) - gl_font() didn't work properly for X11 when Xft was used (STR #12) - Fl_File_Browser incorrectly included "." on WIN32 (STR #9) - Include shellapi.h instead of ShellAPI.h in the WIN32 drag-n-drop code in order to work with the MingW cross compiler (STR #6) - The cursor was not properly restored when doing drag-n-drop on X11 (STR #4) - Fl::remove_fd() didn't recalculate the highest file descriptor properly (STR #20) - Fl_Preferences::deleteGroup() didn't work properly (STR #13) - Fixed the fl_show_file_selector() function - it was copying using the wrong string size (STR #14) - fl_font() and fl_size() were not implemented on MacOS X. - Sorted the icon menu bar in FLUID. - Fixed minor memory access complaints from Valgrind - Compiling src/flstring.h on OS X with BSD header would fail. - Fl_Text_Editor didn't scroll the buffer when the user pressed Ctrl+End or Ctrl+Home. - Fl_Text_Editor didn't show its cursor when the mouse was moved inside the window. - FLUID now uses an Fl_Text_Display widget for command output, which allows you to copy and paste text from command output into other windows. - Fl_Gl_Window could cause a bus error on MacOS X if the parent window was not yet shown. - FLUID could crash after displaying a syntax error dialog for the callback code. - FLUID would reset the callback code if you opened the widget panel for multiple widgets. - Added a NULL check to Fl_Text_Display (SF Bug #706921). - The fltk-config script placed the LDFLAGS at the wrong place in the linker options. - Fl_Text_Display didn't draw the outer box in the right dimensions, so it was invisible. - Fl_Help_Dialog used the same color for links as for the background, causing links to be invisible on pages without a background color set. CHANGES IN FLTK 1.1.3 RELEASED: Feb 13 2003 - Documentation updates. - FLTK now ignores KeyRelease events when X11 sends them for repeating keys. - FLUID now supports up to two additional qualifiers before a class name (FL_EXPORT, etc.) to aide in developing DLL interfaces for WIN32. - Additional NULL checks in Fl_Button, fl_draw_boxtype(), Fl_File_Chooser, and Fl_Window::hotspot(). - The Fl_Preferences header file needed to FL_EXPORT all of the nested classes for WIN32. - Fl_Double_Window couldn't be nested on WIN32. [SF Bug #658219] - Fl_Slider didn't call the callback function when the user changed the value using the keyboard and the "when" condition was FL_WHEN_RELEASE. [SF Bug #647072] - Lines with less than 2 unique vertices and polygons with less the 3 unique vertices were not drawn properly. [SF Bug #647067] - The size_range() values were not honored under MacOS X. [SF Bug #647074] - OpenGL windows didn't resize correctly on MacOS X. [SF Bug #667855] - The menus incorrectly used the overlay visual when one or more menu items contained an image. [SF Bug #653846] - Changed some error messages to use Fl::error() instead of fprintf()... - Fl_Text_Buffer and Fl_Text_Display used free to free memory that was allocated using the new operator. - Tweeked the plastic scheme under MacOSX to better match the colors. - The Fl_Image.H always included the x.H header file, which included many system headers that could interfere with normal GUI applications. It now uses the corresponding based types for the image id and mask to avoid this. - The FLUID widget panel wasn't sorted, so keyboard navigation was strange. [SF Bug #647069] - Fl_Scroll didn't compute the location of labels to the right or below when determining the area to erase. - Added backward-compatibility macro for filename_setext(). - Fl_Bitmap::copy(), Fl_Pixmap::copy(), and Fl_RGB_Image::copy() all could overflow the source image when scaling the image. - Double/triple clicks in Fl_Input fields didn't copy the expanded selection to the clipboard. - Fl_Glut_Window and Fl_Gl_Window didn't always initialize the OpenGL context on MacOS. CHANGES IN FLTK 1.1.2 RELEASED: Nov 25 2002 - Fl_Menu_Bar now supports drawing vertical dividers between menu items and submenus in the menu bar. - Fl_File_Chooser::value() didn't return NULL when the user clicked Cancel while selecting a directory. This bug also affected fl_dir_chooser(). - Fl_Menu_::add(const char *) used too small a menu item label buffer and didn't do bounds checking. - Eliminate some compiler warnings with CodeWarrier under WIN32 (Paul Chambers) - Fl_Gl_Window widgets did not resize properly under MacOS X. - The cursor could be set for the wrong window in the text widgets. - Fl_Check_Browser didn't provide const char * add methods as documented. - Fl_Check_Browser didn't draw the same style of check marks at the other widgets. - Fl_Button, Fl_Choice, and Fl_Menu_Button incorrectly activated the button/menu when the spacebar was pressed in conjunction with shift, control, alt, or meta. - FLTK should now compile with Xft 2.0. - Some versions of Tru64 4.0 have snprintf and vnsprintf, but don't have the prototypes for those functions. - FLTK had trouble doing character composition with some keyboard layouts under X11 (in particular, Belgian). - Fl_Text_Editor would cause a segfault if the user pressed CTRL-V (paste) without having any data in the clipboard... - The tab key moved backwards in menus instead of forwards. Shift-tab still moves backwards. - The redraw_label() method didn't damage the parent window when the label was outside the widget's bounding box. - Added a "draw_children()" method to Fl_Group to make subclassing Fl_Group with a custom draw() function easier. - Fl_Text_Editor now supports basic undo functionality. - FLUID now uses Fl_Text_Editor widgets for all multi-line code fields. - Added new widget bin and icons to FLUID. - FLUID would try running multiple commands in parallel, even though it wasn't capable of handling it. - FLUID didn't generate code for some attributes when using custom/named widget classes. - Added a new FL_COMMAND state bit which maps to FL_CTRL on X11 and WIN32 and FL_META on MacOS. - MacOS keyboard modifiers mapping corrections. Cmd and Control are no longer swapped, event_key and event_text return (mostly) the same values as on other platforms. - The Fl_Tabs widget should no longer be a focus hog; previously it would take focus from child widgets. - The file chooser now activates the OK button when opening a directory in directory selection mode. - Fixed a bug in the file chooser when entering an absolute path. - Back-ported some FLTK 2.0 tooltip changes to eliminate erroneous tooltip display. - MacOS windows were resizable, even when size_range would not allow for resizing. - Fl_Text_Editor now supports Shift+Delete, Ctrl+Insert, and Shift+Insert for cut, copy, and paste, respectively. - Fl_Text_Display didn't restore the mouse pointer when hidden. - Fl::arg() now ignores the MacOS X -psn_N_NNNNN option. - Added another change to the WIN32 redraw handling for the MingW compilers. - Fl_File_Chooser didn't handle WIN32 home directories that used backslashes instead of forward slashes. - Fl_Text_Display didn't limit the resize height to 1 line. - Fl_Scrollbar widgets incorrectly took keyboard focus when clicked on. This caused widgets such as Fl_Text_Display to hide the cursor when you scrolled the text. CHANGES IN FLTK 1.1.1 RELEASED: ??? ?? 2002 - Fl_Text_Display didn't always show the cursor. - Fl_Tabs now only redraws the tabs themselves when making focus changes. This reduces flicker in tabbed interfaces. - The WIN32 redraw handler now correctly merges the FLTK and Windows redraw regions. - The Fl_Text_* widgets use the C++ bool type, which is not supported by older C++ compilers. Added a configure check and workaround code for this. - Fl_X::set_xid() didn't initialize the backbuffer_bad element that was used with XDBE. - Fl_Shared_Image::uncache() was not implemented. - Fl::set_font() didn't 0-initialize all font descriptor data. - Some OpenGL implementations don't support single- buffered visuals. The Fl_Gl_Window class now emulates single-buffered windows using double-buffered windows. - Added a workaround for a compiler bug in Borland C++ that prevented Fl_Help_View.cxx from compiling. - Checkmarks didn't scale properly; copied the 2.0 check mark code over. - Replaced several memcpy's with memmove's for portability (memmove allows for overlapping copies, memcpy does not) - Bug #621737: Fl_Bitmap::copy(), Fl_Pixmap::copy(), and Fl_RGB_Image::copy() now range-check the new width and height to make sure they are positive integers. - Bug #621740: the WIN32 port needed to handle WM_MOUSELEAVE events in order to avoid problems with tooltips. - Fl_PNM_Image didn't set the "alloc" flag for the data, which could lead to a memory leak. - fl_filename_match() was inconsistently doing case- insensitive matching. - Fl_Button redraw fix for bug #620979 (focus boxes and check buttons). - Fl_Text_Display fix for bug #620633 (crash on redisplay). - Fl_Output now calls its callback when the user clicks or drags in the widget. - Shortcuts now cause buttons to take focus when visible focus is enabled. - fl_filename_relative() didn't check that the path was absolute under WIN32. - fl_filename_relative() didn't check that the path was on the current drive under WIN32. - The Fl_BMP_Image class now handles 16-bit BMP files and BMP files with a transparency mask. - The fltk-config script didn't add the required include path, if any, when compiling a program. - Added a license clarification that the FLTK manual is covered by the same license as FLTK itself. - Fl_Check_Browser wasn't documented. - Fl_Preferences::Node::addChild(), deleteEntry(), and remove() didn't set the "dirty" flag. - The "no change" button didn't work in the FLUID widget panel. - Vertical scrollbars did not draw the arrows inactive when the scrollbar was inactive. CHANGES IN FLTK 1.1.0 RELEASED: ??? ?? 2002 - Documentation updates. - Added a Fl_Widget::redraw_label() method which flags a redraw of the appropriate area. This helps to eliminate flicker when updating the value of a widget. - Fl_Wizard::value() now resets the mouse cursor to the window's default cursor. - Fl_File_Chooser::type() didn't enable/disable the new directory button correctly. - Fl_Preferences::entryExists() did not work properly. - FLUID's image file chooser pattern was incorrect. - Fl_File_Icon::load_system_icons() now detects KDE icons in /opt/kde, /usr/local, and /usr automatically, and supports the KDEDIR environment variable as well. - Submenus now display to the left of the parent menu if they won't fit to the right. Previously they would display right on top of the parent menu... - Fl_Menu_:add() didn't handle a trailing "\" character gracefully. - Clicking/dragging the middle mouse button in a scrollbar now moves directly to that scroll position, matching the behavior of other toolkits. - Added some more range checking to the Fl_Text_Display widget. - The editor demo did not correctly update the style (syntax highlighting) information. CHANGES IN FLTK 1.1.0rc7 CANDIDATE: ??? ?? 2002 - Updated the Fl_Text_Buffer and Fl_Text_Display classes to be based on NEdit 5.3 (patch from George Garvey). - Fixed a problem with Fl::wait(0.0) on MacOS X 10.2; this affected the fractals demo and other OpenGL applications. - Fl_Glut_Window now takes keyboard focus and handles shortcut events. - The MacOS X implementation of fl_ready() now checks the event queue for events. - Fl_PNM_Image now supports the XV/GIMP thumbnail format (P7). - Fl_Preferences would not find groups inside the root group. - Small bug fixes for Fl_Chart, Fl_Scrollbar, Fl_Tabs, and FLUID from Matthew Morrise. - Fl_Chart didn't have its own destructor, so data in the chart wasn't freed. - Fl_Menu_Button no longer responds to focus or keyboard events when box() is FL_NO_BOX. - FLTK convenience dialogs put the buttons in the wrong order. - Fl_BMP_Image didn't load 4-bit BMP files properly. - Minor tweeks to the WIN32 DLL support. - Fl_Text_Display::resize() could go into an infinite loop if the buffer is emptied. - Fl::handle() didn't pass FL_RELEASE events to the grab() widget if pushed() was set (for proper menu handling...) - DND events were being sent to the target window instead of the target widget under WIN32. - The newest Cygwin needs the same scandir() handling as HP-UX. - FLUID didn't register the image formats in the fltk_images library, and had some other image management problems. - Fixed one more redraw bug in Fl_Browser_ where we weren't using the box function to erase empty space in the list. - Fl_Text_Display::buffer() now calls resize() to show the buffer. - Fl_Help_View didn't support HTML comments. - Fl_Help_View didn't include the extra cellpadding when handling colspan attributes in cells. - Fl_Help_View didn't support table alignment. CHANGES IN FLTK 1.1.0rc6 CANDIDATE: ??? ?? 2002 - Documentation updates. - Fl::handle() didn't apply the modal tests for FL_RELEASE events, which caused Fl_Tabs to allow users to change tabs even when a modal window was open. - Fl_Browser_, Fl_Input_, Fl_Slider now use the box function to erase the background. This fixes some long-standing redraw problems. - More snprintf/strlcpy/strlcat changes where needed. - Fl::get_font_name() would leak 128 bytes. - Eliminated most of the "shadowed" variables to avoid potential problems with using the wrong copy of "foo" in a class method. - Moved Fl_BMP_Image, Fl_GIF_Image, and Fl_PNM_Image to the fltk_images library, so the only image formats that are supported by the core library are XBM and XPM files. This reduces the size of the FLTK core library by about 16k... - The Fl_Text_Display::resize() method was incorrectly flagged as protected. - Fixed some memory/initialization bugs in Fl_File_Chooser that valgrind caught. - The PNG library png_read_destroy() is deprecated and does not free all of the memory allocated by png_create_read_struct(). This caused a memory leak in FLTK apps that loaded PNG images. - Added uncache() method to Fl_Image and friends. - Added image() methods to Fl_Menu_Item. - Added default_cursor() method and data to Fl_Window. - Fl_Group would send FL_ENTER events before FL_LEAVE events, causing problems with adjacent widgets. - Fixed filename problems with Fl_File_Chooser - changing the filename field directly or choosing files from the root directory could yield interesting filenames. - Fl_Input_ could crash if it received an empty paste event. - The mouse pointer now changes to the I beam (FL_CURSOR_INSERT) when moved over an input field or text widget. - "make install" didn't automatically (re)compile the FLUID executable. - Added an Fl::get_boxtype() method to get the current drawing function for a specific box type. - Fl_Output and Fl_Multiline_Output didn't prevent middle-mouse pastes. - Fl_JPEG_Image didn't compile out-of-the-box with Cygwin due to a bug in the Cygwin JPEG library headers. - Fl_BMP_Image still didn't work with some old BMP files. - "make distclean" didn't really clean out everything. - Tweeked the look of the check button with a patch from Albrecht Schlosser. CHANGES IN FLTK 1.1.0rc5 CANDIDATE: ??? ?? 2002 - Added "wrap" type bit to Fl_Input_, so you can now have a multiline text field that wraps text. - Setting the value() of an output text field no longer selects the text in it. - Output text fields now show a caret for the cursor instead of the vertical bar. - The newButton and previewButton widgets are now public members of the Fl_File_Chooser class. This allows developers to disable or hide the "new directory" and "preview" buttons as desired. - Added new visible focus flag bit and methods to Fl_Widget, so it is now possible to do both global and per-widget keyboard focus control. - Removed extra 3 pixel border around input fields. - No longer quote characters from 0x80 to 0x9f in input fields. - Improved speed of Fl_Browser_::display() method with large lists (patch from Stephen Davies.) - Fl_Help_View didn't properly handle NULL from the link callback (the original filename/directory name were not preserved...) - Fl_Help_View didn't use the boxtype border values when clipping the page that was displayed. - Added first steps to CodeWarrior/OS_X support (see fltk-1.1.x/CodeWarrior/OS_X.sit) - Cleaned up the WIN32 export definitions for some of the widget classes. - Fixed a filename completion bug when changing directories. - Fl_File_Chooser::value() would return directories with a trailing slash, but would not accept a directory without a trailing slash. - When installing shared libraries, FLUID is now linked against the shared libraries. - MacOS: missing compile rule for .dylib files. - Fl_Group::current(), Fl_Group::begin(), and Fl_Group::end() are no longer inlined so that they are properly exported in DLLs under WIN32. Similar changes for all static inline methods in other classes. - MacOS: support for Mac system menu (Fl_Sys_Menu_Bar) - MacOS: wait(0) would not handle all pending events - Added new makeinclude file for MingW using GCC 3.1.x. - Fl_Choice::value(n) didn't range check "n". - The MingW and OS/2 makeinclude files didn't have the new fltk_images library definitions. - Fl_Text_Editor didn't scroll the text in the widget when dragging text. - Config header file changes for Borland C++. - FLTK didn't provide a Fl::remove_handler() method. CHANGES IN FLTK 1.1.0rc4 CANDIDATE: Jul 02 2002 - Added new filter_value() methods to Fl_File_Chooser to get and set the current file filters. - Added support for custom filters to Fl_File_Chooser. - Added Borland C++ Builder IDE project files from Alexey Parshin. - Resource leak fixes under WIN32 from Ori Berger. - Now register a WIN32 message for thread messages. - Fl_Window didn't initialize the min and max window size fields. - The JPEG and PNG image classes have been moved to the fltk_images library, a la FLTK 2.0. You can register all image file formats provided in fltk_images using the new fl_register_images() function. - Fl_XBM_Image didn't correctly load XBM files. - MacOS: Added Greg Ercolano's file descriptor support. - MacOS: Fixed text width bug. - A change in fl_fix_focus() broken click-focus in FLWM. - Cygwin with -mnocygwin didn't like the FL/math.h header file. - Fl_Browser_ cleared the click count unnecessarily. - MacOS: Pixmap draw fix, gl_font implemented FL_FOCUS fix, window type fix for modal and nonmodal windows, glut uninitialised 'display' proc fix - Now support FLTK_1_0_COMPAT symbol to define compatibility macros for the old FLTK 1.0.x function names to the 1.1.x names. - Now translate the window coordinates when a window is shown, moved, or resized. This should fix the "menus showing up at the wrong position" bug under XFree86. - Fixed some more problems with the Fl_BMP_Image file loader. - BC++ fixes. - The pixmap_browser demo didn't check for a NULL image pointer. - Fl_File_Icon::find() now uses fl_filename_isdir() under WIN32 to check for directories. - Fl_File_Chooser's preview code called refcount() on the deleted image's object. - Fixed another problem with the Fl_BMP_Image loader. - The fl_file_chooser() callback was being called with a NULL filename. - Documented that fl_push_clip() is preferred over fl_clip(), with a corresponding source change. - Minor changes to the MacOS X event handling code. - Added syntax highlighting example code to the editor test program. - Fl_Text_Display didn't range check style buffer values. - Added "dark" color constants (FL_DARK_RED, etc.) - The MacOS font code was missing definitions for fl_font_ and fl_size_. CHANGES IN FLTK 1.1.0rc3 CANDIDATE: ??? ?? ???? - Documentation updates. - New file chooser from design contest. - Did some testing with Valgrind and fixed some memory problems in Fl_Help_View::Fl_HelpView, Fl_Menu_::remove(), Fl_Text_Display::draw_vline(), and resizeform() (convenience dialogs). - Fixed some redraw() bugs, and now redraw portions of the parent widget when the label appears outside the widget. - The boolean (char) value methods in Fl_Preferences have been removed since some C++ compilers can't handle char and int value methods with the same name. - Added fl_read_image() function. - Fixed Fl_Valuator::format() so that the correct format type is used when step == 1.0. - Fl_Help_View didn't support the TT markup. - Fl_Shared_Image used a double-pointer to the image handler functions, which was unnecessary and unintuitive. - Fl_PNM_Image didn't load the height of the image properly. - Fl_BMP_Image, Fl_JPEG_Image, Fl_PNG_Image, and Fl_Shared_Image didn't delete image data that was allocated. - Enabled the OpenGL and threads demos when compiling for MingW. - Fl_File_Input didn't update the directory buttons if a callback was registered with the widget. - The file chooser would return the last selected file(s) when cancel was pressed. - The file chooser limited the resizing of the chooser window unnecessarily. - Fixed WM_PAINT handling under WIN32. - Minor tweeks to MingW and OS/2 config headers. - Fl_Value_Input now correctly determines if step() specifies an integer value. - Fl_Help_View didn't add links inside PRE elements. - OS/2 build fixes from Alexander Mai. - Now use strlcat() instead of strncat() which could cause buffer overflows. - Now use of strlcpy() instead of strncpy() to simplify the code. - Drag-n-drop under WIN32 now shows a [+] cursor instead of the link cursor. - Fixed widget width tooltip and default argument handling code in FLUID. - Fixed colors used when drawing antialiased text using Xft. - Fl_Preferences::makePath() now uses access() instead of stat() when checking to see if the destination directory already exists. - Fl_BMP_Image now supports older BMP files with the 12 byte header. - Optimized the redrawing of tabs and radio/check buttons when the keyboard focus changes. - More tooltip fixes. - DND text operations would loop under X11. CHANGES IN FLTK 1.1.0rc2 CANDIDATE: ??? ?? ???? - Portability fixes. - Backported 2.0 tooltip changes. - Several of the valuators did not support tooltips. - The last menu item in a menu didn't pick up on font changes. - FLUID now properly handles default argument parameters properly. - Fixed WM_PAINT handling under WIN32 - didn't validate the correct region that was drawn. - Fl_Multiline_Output would insert the enter key. - Fl_File_Browser didn't clip items to the column width. - Fl_Window::draw() cleared the window label but didn't restore it, so windows could lose their titles. - Eliminated multiple definitions of dirent structure when compiling under WIN32. - Adjusted the size of the circle that is drawn inside radio buttons to scale better for larger labels. - FLUID was opening the display when it shouldn't have. - Fl_File_Chooser.cxx defined the file chooser functions again; they should only be defined in the header file. - Wide arcs would draw with "teeth". - The preferences demo included Fl/Fl_Preferences.H instead of FL/Fl_Preferences.H. CHANGES IN FLTK 1.1.0rc1 CANDIDATE: ??? ?? ???? - The fl_file_chooser() and fl_dir_chooser() functions now support an optional "relative" argument to get relative pathnames; the default is to return absolute pathnames. - The backspace and delete keys now work as expected in the file chooser when doing filename completion. - FLUID now supports running shell commands. - New Fl_File_Input widget that shows directory separators with filename in input field. - The Fl_File_Chooser dialog now shows the absolute path in the filename field using the Fl_File_Input widget. - FLUID now keeps track of grid, tooltip, and other GUI options, along with the last 10 files opened. - Tooltip windows would show up in the task bar under WIN32. - Now append trailing slash to directory names in names in WIN32 version of scandir(). This takes care of a file chooser performance problem with large directories. - Added Fl_Preferences class from Matthias Melcher, including binary data support. - FLUID now recognizes the "using" keyword in declarations. - fl_file_chooser() didn't highlight the requested file the second time the file chooser dialog was shown. - Fixed rendering of Fl_Light_Button with the plastic scheme. - Fixed a bug in the MacOS font enumeration code. - Now show a "locked" icon next to static/private elements in FLUID, and "unlocked" icon next to global/public elements. - Implemented Fl_Menu_Item image labels using older 1.0.x labeltype method. - Updated the PNG library check to support both png.h and libpng/png.h. - Fixed a recursion bug in tooltips that was causing random crashes. - fl_file_chooser() could cause a segfault when passed a NULL filename parameter in some situations. - Added a "-g" option to fltk-config to support quick compiling with debugging enabled. - Fixed redraw problem with Fl_Input and anti-aliased text. - Added threading support for MacOS X and Darwin. - The filesystem list in the file chooser now works under MacOS X and Darwin. - The fl_msg structure now contains all data passed to the WndProc function under WIN32. - Fixed some window focus/positioning problems under MacOS X. - Added fl_create_alphamask() function to create an alpha mask from 8-bit data; currently this always generates a 1-bit screen-door bitmask, however in the future it will allow us to generate N-bit masks as needed by various OS's. - Fl_File_Browser::load() didn't properly show drives when compiled in Cygwin mode. - Now pass correctly pass keyboard and mouse events to widget under tooltip as needed... - Added new Fl::dnd_text_ops() methods to enable/disable drag-and-drop text operations. - Fl_Input now supports clicking inside a selection to set the new text position when drag-and-drop is enabled. - Added support of X resources for scheme, dnd_text_ops, tooltips, and visible_focus... - Fixed some case problems in includes for the MacOS X code. - Fl_Widget::handle() returned 1 for FL_ENTER and FL_LEAVE events, which caused some compatibility problems with 1.0 code. - Fl_Box::handle() now returns 1 for FL_ENTER and FL_LEAVE events so that tooltips will work with Fl_Box widgets. - Some source files still defined strcasecmp and strncasecmp under WIN32. - Some source files still used the "false" and "true" C++ keywords, even though several of our "supported" C++ compilers don't support them. Using 0 and 1 until FLTK 2.0 (which uses the bool type instead of int for any boolean values...) - Minor Fl_Color revamping, so that color constants map to the color cube and FL_FOREGROUND_COLOR, FL_BACKGROUND_COLOR, FL_BACKGROUND2_COLOR, FL_INACTIVE_COLOR, and FL_SELECTION_COLOR map to the user-defined colors. CHANGES IN FLTK 1.1.0b13 BETA: ??? ?? ???? - Fixed a bug in the Xft support in Fl_Window::hide() (the config header wasn't included, so the Xft code wasn't getting called) - Xdbe support must now be enabled explicitly using --enable-xdbe due to inconsistent bugs in XFree86 and others. - Windows resized by a program would revert to their original size when moved under WIN32. - Cygwin can only compile the new WIN32 drag-n-drop code using GCC 3.x. - Tooltips now appear for inactive and output widgets. - Tooltips no longer steal keyboard events other than ESCape. - Tooltips are no longer delayed when moving between adjacent widgets. - fl_beep(FL_BEEP_DEFAULT) now uses the PC speaker under Windows (0xFFFFFFFF) rather than an event sound. - The configure script didn't include the -mwindows or -DWIN32 compiler options in the output of fltk-config when using the Cygwin tools. - Fl_Output didn't take input focus when needed, so it was unable to support CTRL-C for copying text in the field and did not unhighlight selections when the widget lost focus. - The fl_filename_name() function didn't handle a NULL input string. - The input field used by the fl_input() and fl_password() functions was resized too small in 1.1.0b12. - Added casts in fl_set_fonts_win32.cxx for VC++ 5.0. - Fl_File_Icon::find() did not check the basename of a filename for a match; this caused matches for a specific filename (e.g. "fluid") to fail. - The Fl_Shared_Image class now supports additional image handling functions - this allows you to support additional image file formats transparently. CHANGES IN FLTK 1.1.0b12 BETA: ??? ?? ???? - Documentation updates. - Fl_Choice didn't clip the current value properly - it wasn't accounting for the box border width. - The forms compatibility functions are now placed in a "fltk_forms" library to match FLTK 2.0. - Renamed down() and frame() to fl_down() and fl_frame(), filename_xyz() to fl_filename_xyz(), and all of the define_FL_FOO() functions for the custom boxtypes to fl_define_FL_FOO() to avoid namespace clashes. - Stereo OpenGL support (patch from Stuart Levy) - All of the convenience functions defined in fl_ask.H now resize the widgets and dialog window as needed for the labels and prompt. - Backported FLTK 2.0 dual cut/paste buffer code. - Added support for Xft library to provide anti-aliased text on X11. - Fl_Help_View didn't keep track of the background color of cells properly. - Fl_Browser::item_width() didn't compute the width of the item properly when column_widths() was set. - Fl_Button didn't check to see if the widget could accept focus before taking input focus. - Fl_Help_View didn't preserve target names (e.g. "filename.html#target") when following links. - Drag-and-drop support for MacOS. - Updated MacOS issues documentation. CHANGES IN FLTK 1.1.0b11 BETA: ??? ?? ???? - Now conditionally use the WIN32 TrackMouseEvent API (default is no...) - Fixed a table rendering bug in the Fl_Help_View widget. - The fltk-config script now recognizes all common C++ extensions. - The menu code was using overlay visuals when the scheme was set to "plastic". - Fixed some drawing problems with Fl_Light_Button and its subclasses. - Fixed a minor event propagation bug in Fl_Group that caused mousewheel events to be passed to scrollbars that were not visible. - The fl_file_chooser() function did not preserve the old file/directory like the old file chooser did. - The prototypes for fl_input() and fl_password() did not default the "default value" to NULL. - Fl_Tabs now draws tabs using the selection_color() of the child groups; this allows the tabs to be colored separately from the body. Selected tabs are a mix of the Fl_Tabs selection_color() and the child group's selection_color(). - Fl_Tabs didn't include images in the measurement of the tabs if no label text was defined. - The WIN32 code didn't return 0 from the window procedure after handling WM_PAINT messages. - fl_draw() would incorrectly test the clipping of labels the lay outside the bounding box. - filename_relative() didn't always return the correct relative path. - Updated the test makefile to work with more versions of "make". - Added new "--with-optim" configure option to set the optimization flags to use when compiling FLTK. - The fltk-config script no longer reports the optimization flags that were used to compile FLTK. - Initial port of FLTK 2.0 drag-and-drop support. CHANGES IN FLTK 1.1.0b10 BETA: ??? ?? ???? - Fixed the new WIN32 TrackMouseEvent code. - Fixed the VC++ project files to link against comctl32.lib. CHANGES IN FLTK 1.1.0b9 BETA: ??? ?? ???? - Better FL_LEAVE event handling for WIN32. - The alpha mask was bit-reversed. - Fl::scheme() applied the scheme tile image to overlay and menu windows, which caused problems when the overlay planes were in use. - Fixed Fl::event_button() value when hiding tooltip on some systems. - Added Fl_BMP_Image class to support loading of Windows bitmap (BMP) files. - The shiny demo didn't work on some systems (no single-buffered OpenGL visual), and the new box types were reset when show(argc, argv) was called. - Fl::scheme() didn't update windows that were not shown. - The fractals demo would get far ahead of the UI with some Linux OpenGL drivers. Now use glFinish() instead of glFlush() so we are at most 1 frame ahead. - The fractals demo Y axis controls were backwards for the "flying" mode. - MacOS: cleaned up src/Fl_mac.cxx - MacOS: fixed Fl::wait(0.0), fixed Cmd-Q handling - Update CygWin support for Fl::add_fd(). - Update the plastic scheme to not override the default colors - move the color code to the MacOS-specific code. Also updates the tile image colormap to match the current background color. - Add fl_parse_color() to X11 as well, removing a bunch of conditional code and providing a common interface for looking up color values. - Fixed the make problems in the test directory - some make programs had trouble handling the recursive dependencies on the FLUID files... - Now use rint() to round floating-point coordinates. - Demo cleanup - made sure they all worked with schemes. - Fl_Tabs no longer clears the unused area of the tab bar. - Added show(argc, argv) method to Fl_Help_Dialog. - MacOS: implemented cut/copy/paste. - MacOS: improved keyboard handling, fixed keyboard focus handling, fixed get_key, modified 'keyboard' demo to show second mouse wheel and additional keys 'help' and FL_NK+'=' CHANGES IN FLTK 1.1.0b8 BETA: ??? ?? ???? - OS/2 build fixes. - fl_draw() didn't ignore symbol escapes properly for the browsers... - New Fl::scheme() methods from FLTK 2.0; currently only the standard ("") and plastic ("plastic") methods are supported. Schemes can be set on the command-line ("-scheme plastic") or using the FLTK_SCHEME environment variable. - MacOS: fixed iBook keyboard handling, moved remaining message handling to Carbon, added mouse capture support, added timer support, added overlay support, fixed double-buffering side effects. - The configure script wasn't using the -fpermissive or -fno-exceptions options with GCC. - Fl_JPEG_Image and friends didn't set the depth if the image file couldn't be loaded; since Fl_RGB_Image didn't check for this, it could fail when displaying or copying these images. - filename_absolute() did not always free its temporary buffer. - filename_relative() did not do a case-insensitive comparison under MacOS, OS/2, and Windows. - filename_isdir() didn't properly handle "D:L" under WIN32. - Fl_Shared_Image::get() did not check to see if the image could not be loaded. - Fl_Help_View didn't clear the line array in the Fl_Help_Block structure; this causes erratic formatting for some pages. - The font and size members of Fl_Help_Block were never used. - The threading functions (Fl::lock() and friends) were not exported under WIN32. - The Fl_Text_Display destructor deleted the scrollbars twice... - Fl_Help_View didn't reset the horizontal scroll position when showing a new page. - Fl_Pack now allows any child widget to be the resizable() widget, not just the last one. - MacOS: opaque window resizing, all events except Mac menus are now handled using Carbon, window activation fixed, GL_SWAP_TYPE default changed to make gl_overlay work. - Fl_Help_View::resize() didn't resize the horizontal scrollbar. - MacOS: list all fonts, fixed clipping and mouse pointer bugs. - The Fl_File_Chooser widget now uses hotspot() to position the dialog under the mouse pointer prior to showing it. - Added a configure check for *BSD - use -pthread option instead of -lpthread. - Fl_Text_Display could get in an infinite loop when redrawing a portion of the screen. Added a check for the return value from fl_clip_box() so that the correct bounding box is used. - Removed the Fl_Mutex and Fl_Signal_Mutex classes from the threads example, since they weren't being used and apparently are not very portable. - Fl_Help_View now ignores links when the link callback returns NULL, and displays a sensible error message when an unhandled URI scheme is used (e.g. http:, ftp:) - Fl_File_Icon::load_system_icons() no longer complains about missing icon files, just files that exist but can't be loaded. - FLUID didn't list the plastic box and frame types. - Now hide the tooltip window whenever a window is hidden. Otherwise a tooltip window could keep an application running. - Updated FLUID to only append a trailing semicolon to code lines in a callback (so "#include" and friends will work...) - The Fl_Color_Chooser widget now supports keyboard navigation. - Fixed button and valuator widgets to call Fl::focus() instead of take_focus(). - Tweeked the radio button drawing code for better circles with different boxtypes. - The Fl_File_Chooser widget did not provide a shown() method, and fl_file_chooser() and fl_dir_chooser() did not wait on shown(); this would cause them to return prematurely if you switched desktops/workspaces. - Cosmetic changes to plastic boxtypes. Now look much better for large areas and the buttons now have a much greater "3D" feeling to them. - Added new Fl::draw_box_active() method so that boxtypes can find out if the widget they are drawing for is active or not. - Fl_Button and its subclasses did not redraw the parent when the boxtype was FL_NO_BOX and they lost keyboard focus (the parent redraw clears the focus box.) - Fixed the example program makefile - wasn't building the mandelbrot and shiny demos right. - Fl::set_font(Fl_Font, Fl_Font) was not implemented. - Fixed the documentation Makefile commands; was not using the fltk.book file for some reason... CHANGES IN FLTK 1.1.0b7 BETA: ??? ?? ???? - More documentation updates... - Mac OS X support works 95% - The Fl_Window::hotspot() off-screen avoidance code was commented out. - Mac OS X uses mostly Carbon event handling to support Mousewheel, three buttons, all modifier keys, etc. - Updated paragraph 4 of the FLTK license exceptions; there was some question about the requirement to show that a program uses FLTK, which is required by section 6 of the LGPL. The new exemption specifies that inclusion of the FLTK license is not required, just a statement that the program uses FLTK. - Fl_Button::handle() was calling take_focus() for both FL_PUSH and FL_DRAG. - File and memory fixes for Fl_GIF_Image, Fl_PNG_Image, Fl_PNM_Image, Fl_Shared_Image, Fl_Tiled_Image, and Fl_XBM_Image. - filename_match() didn't handle backslashes properly under WIN32, and didn't use a case-insensitive comparison under MacOS X. - The Fl class was missing access methods for the FL_MOUSEWHEEL event values - Fl::event_dx() and Fl::event_dy(). - The default help string didn't include the -nokbd option. - "make uninstall" didn't uninstall the static OpenGL widget library. - Mac cursor shapes added... - Fl_Text_Display would lockup when all text was deleted; for example, when running the editor demo, you couldn't load a second file. - Added Fl::lock() and friends from FLTK 2.0 to support multi-threaded applications; see the "threads" demo for an example of this. - Fl_Check_Button and Fl_Round_Button now use the FL_NO_BOX box type to show the background of the parent widget. - Tweeked the plastic boxtype code to draw with the right shading for narrow, but horizontal buttons. - Fl_Progress now shades the bounding box instead of drawing a polygon inside it. - Fl::warning() under WIN32 defaults to no action. This avoids warning dialogs when an image file cannot be loaded. - Some Win32 drivers would draw into wrong buffers after OpenGL mode change - The file chooser would cause a segfault if you clicked in an empty area of the file list. - Fl_File_Icon::labeltype() would cause a segfault if the value pointer was NULL. - Fl_File_Icon::load_image() could cause segfaults (NULL data and incrementing the data pointer too often.) - Fl_File_Icon::load_image() now handles 2-byte per color XPM files. - Some Win32 drivers would draw into wrong buffers after OpenGL mode change. - Message handling and Resources for MacOS port. - Fl_Help_View could get in an infinitely loop when determining the maximum width of the page; this was due to a bug in the get_length() method with percentages (100% width would cause the bug.) - Don't need -lgdi32 for CygWin, since -mwindows does this for us. - The WIN32 event handler did not properly handle WM_SYNCPAINT messages. - Fl_Tabs now uses the boxtype exclusively to draw both the tabs and surrounding box, so alternate box types actually work and the look is a little nicer. - Fixed the drawing of large areas with the new plastic boxtypes. - Updated the Visual C++ demo projects to use FLUID to generate the GUI files as needed. - The demo program didn't load the right menu file when compiled for debugging under WIN32. - Added plastic box types to forms demo. - Added mousewheel to keyboard demo. - The Fl_Text_Editor widget caused an infinite loop when it received keyboard focus. - filename_isdir() didn't properly handle drive letters properly; WIN32 needs a trailing slash for drive letters by themselves, but cannot have a trailing slash for directory names, go figure... - The Fl_Text_Buffer and Fl_Text_Display classes did not initialize all of their members. - fl_normal_label() had a totally redundant set of if/else tests, which the new code handles all from fl_draw(). - The Fl_File_Chooser dialog contained two hotspots. - The fl_draw_pixmap() function didn't free the 2-byte color lookup table properly (delete instead of delete[]). - fl_draw() reset the text color under WIN32, causing bitmaps to draw incorrectly. - Fl::get_font_sizes() is now implemented under WIN32. - Fl_Text_Display now uses the same default colors for selection and text as Fl_Input_ and friends. - Changed the default line scrolling in Fl_Text_Display to 3 lines for the mouse wheel and scrollbar arrows. CHANGES IN FLTK 1.1.0b6 BETA: ??? ?? ???? - Documentation updates... - The configure script now works within the CygWin environment. - Tooltips are now enabled by default, but are not re-enabled when calling the Fl_Widget::tooltip() method. - Added new Fl::version() method to get the current FLTK library version (for shared libraries/DLLs) - Added new Fl::event() method to get the current event that is being processed. - Added new fl_beep() function to do audible notifications of various types. - Added new Fl_GIF_Image, Fl_JPEG_Image, Fl_PNG_Image, Fl_PNM_Image, Fl_XBM_Image, and Fl_XPM_Image classes. - Added new Fl_Shared_Image class, a la FLTK 2.0. - Added new Fl_Tiled_Image class for tiled backgrounds. - Added new copy(), desaturate(), inactive(), and color_average() methods to the Fl_Image classes. - Added a horizontal scrollbar to the Fl_Help_View widget. - Added new FL_PLASTIC_{UP/DOWN}_{BOX/FRAME} boxtypes for a more "modern" look (sort of a cross between KDE 2.2 and Aqua.) - Fl_Float_Input and Fl_Int_Input no longer accept pasted text that is not a floating point or integer value. Pasted numbers now replace text in these widgets. - Implemented the Fl_File_Icon::load_png() method. - The Fl_File_Icon::load_system_icons() method now supports KDE 2.x icons. - Fixed PNG support in Fl_Help_View. - Removed the "Microsoft" mode button from the menubar demo. - The browser demo now makes sure that the input field contains a number. - The Fl_Browser::make_visible() method now range checks the input. - Updated the fl_draw() and fl_measure() methods to accept an optional draw_symbols argument, which controls whether symbols are drawn in the text. - Added new Fl::visible_focus() methods to control whether the focus box is drawn. - The focus box is now drawn using the contrast color. - Fl_Repeat_Button didn't accept keyboard focus. - Added new Fl::visible_focus() method and standard "-kbd" and "-nokbd" options in Fl::args() processing to control whether keyboard focus is shown and handled by non-text widgets. - The wrong tooltip could be shown if the user moved the mouse over adjacent widgets with tooltips. - The drop-down button on Fl_Choice widgets was not limited in width. - Tooltips could appear off the screen. - Mouse wheel events are now sent to the focus widget first, then to any other interested widget. - The Fl_RGB_Image class now supports images with an alpha channel. Images are currently drawn using "screen door" transparency... See the "image" demo for an example. - Added new fl_create_bitmask() and fl_delete_bitmask() functions that create bitmap objects for masking and bitmap drawing. - Was sending FL_RELEASE events for buttons 4 and 5 under X11, which are only for FL_MOUSEWHEEL. - Fl_Help_View now supports the EM and STRONG elements. - Didn't do callbacks when changing tabs via keyboard. - FLUID didn't write tooltip strings to the message catalog file. - Fl_File_Icon now uses Fl_Shared_Image to load icon images; the load_png() and load_xpm() methods have been replaced by a single load_image() method. - Fl_File_Icon::load_system_icons() now does a better job of finding KDE icons. - Now use Fl::warning() and Fl::error() in place of printf's in some of the newer widgets. - The default behavior of Fl::error() is now to display an error but not to exit; Fl::fatal() still exits. - FLUID now uses the Fl_Shared_Image class, so FLUID- generated GUIs can embed any of the supported image file formats. - New filename_relative() function to convert an absolute filename to a relative one. - Updated the filename_absolute(), filename_expand(), and filename_setext() functions to take the destination string size, with inline functions for the old FL_PATH_MAX size. - fl_file_chooser() and fl_dir_chooser() now return a relative path. - Fl_Help_View now supports all ampersand escapes. CHANGES IN FLTK 1.1.0b5 BETA: ??? ?? ???? **** NOTE: DUE TO CHANGES IN THE WIDGET CLASSES, **** **** YOU MUST RECOMPILE ALL SOURCE FILES **** **** THAT USE FLTK!!! **** - All FLTK color values are now 32-bits and support both the legacy 8-bit color values as well as 24-bit RGB values (0xRRGGBB00 for 24-bit RGB, 0x000000II for indexed color). - Fl::set_boxtype() and fl_internal_boxtype() now keep track of when a boxtype is changed; this allows you to override the "special" boxtypes without references to those boxtypes causing them to be reset. - Fl_Help_Func now takes a Fl_Widget pointer as well as a pathname. - Added code to support FL_KEYUP events. - Focus did not return to the Fl_Text_Display and Editor widgets when scrolling and then clicking inside the editor window. - Now set the line size of the vertical scrollbar in the text editor to 1. - The symbols demo didn't show the strings needed to show the corresponding symbol (the label string was not quoted...) - FLTK should now compile with Cygwin cleanly. - Shortcut changes were not being saved by FLUID. - FLUID didn't write the deimage() static data. CHANGES IN FLTK 1.1.0b4 BETA: ??? ?? ???? **** NOTE: DUE TO CHANGES IN THE FL_WIDGET CLASS, **** **** YOU MUST RECOMPILE ALL SOURCE FILES **** **** THAT USE FLTK!!! **** - Updated the flags_ member of Fl_Widget to be an integer instead of uchar, to support the new FL_OVERRIDE flag for Fl_Window. - The parent() method of Fl_Widget now uses pointers to Fl_Group instead of Fl_Widget. - Fl_Window now provides the FLTK 2.0 "override()" and "set_override()" methods for windows. - Added a configure check (and warning) for GCC 3.0.x. - Updated the configure script to check for the png_set_tRNS_to_alpha() function. - Updated the config.h files for all platforms for the image and FLTK documentation defines. - Updated the makeinclude files for all platforms to match the current makeinclude.in file. - FLUID would crash if you cleared an image for a widget. - Fl_Help_View::add_image() did not initialize the image member of the base (unscaled) image. - Fl_Help_View didn't support A elements with both a NAME and HREF attribute - the HREF was ignored. - Miscellaneous compile warning fixes. - Tooltips were being reset by Fl::belowmouse(), which caused problems with the FLUID main window (flashing tooltip windows and serious problems with KDE 2.2) - The editor demo had the save and discard button actions reversed. - The Fl_Help_View widget now uses png_destroy_read_struct() if the older png_read_destroy() function is not available. - The WIN32 DLL library now includes the OpenGL widgets. This is a simpler solution for the export/import dillemma under WIN32, as OpenGL and non-OpenGL symbols need to be exported at different times with the separate library scheme. Since OpenGL is standard under Windows, this is less of a problem than under UNIX... CHANGES IN FLTK 1.1.0b3 BETA: ??? ?? ???? - The top-level makefile did not include the makeinclude file, causing the fltk-config installation commands to fail. - The fl_file_chooser.cxx source file conflicted with Fl_File_Chooser.cxx under Windows. Similarly, the fl_file_chooser.H header file conflicts with the Fl_File_Chooser.H header file. - Now save and restore the GDI pen object when responding to WIN32 paint messages. - Documentation updates from A. Suatoni. CHANGES IN FLTK 1.1.0b2 BETA: ??? ?? ???? - New fltk-config script. - Fixed image/text label handling; in b1 the label needed a non-blank text string to display the image. This bug also caused all sorts of crashes and display problems. - Added new filetype() method to Fl_FileBrowser to allow for file or directory browsing. - Fixed the drawing of the focus box around Fl_Return_Button. - Fixed menu item measurement bug (wasn't initializing image pointers to 0...) - Radio and checkbox menu items now draw with the new style (round radio buttons with dots and square check buttons with check marks.) - Improved the appearance of Fl_Check_Button. - Improved the Fl_HelpView table formatting code; now dynamically sizes the table columns, and supports COLSPAN. - The FLUID keyboard shortcuts now work as expected (CTRL-C copies, SHIFT-CTRL-C writes code, etc.) - The FLTK_DOCDIR environment variable can now be used to tell FLUID where to find the on-line documentation files. - FLUID now supports image labels in addition to text labels + text over image alignment. - FLUID now supports tooltips. - The widget panel in FLUID is now tabbed, a la FLTK 2.0. - The FLUID pixmap destructor tried to free 1 too many lines of image data. - FLUID now provides on-line help. - Changed Fl_FileXYZ to Fl_File_XYZ. - Changed Fl_HelpXYZ to Fl_Help_XYZ. - Tooltip fixes for Fl_Browser_, Fl_Choice, and Fl_Input_. - Added tooltips to FLUID, help dialog, and file chooser. - Now load system icons in FLUID. CHANGES IN FLTK 1.1.0b1 - Added new image() and deimage() methods to support image + text labels more easily. - Added new alignment bit FL_ALIGN_TEXT_OVER_IMAGE. - Added tooltip support using Jacques Tremblay's tooltip patch. - Added keyboard navigation to all widgets. - Added support for mouse wheels using the new FL_MOUSEWHEEL event type. Get the mouse wheel movement values from Fl::e_dx (horizontal) and Fl::e_dy (vertical). - Added the Fl_Check_Browser, Fl_FileBrowser, Fl_FileChooser, Fl_FileIcon, Fl_HelpDialog, Fl_HelpView, Fl_Progress, and Fl_Wizard widgets from the bazaar. - Added 2.0 Fl_Text_Display and Fl_Text_Editor widgets based on NEdit. - The Fl_Choice widget now looks more line a combo box than a Motif option menu. - Moved the OpenGL widgets into a separate library called fltkgl - this eliminates shared library dependencies on OpenGL when no OpenGL functionality is used/required. - FLUID now supports the new Fl_CheckBrowser, Fl_FileBrowser, Fl_FileIcon, Fl_HelpView, Fl_Text_Display, Fl_Text_Editor, and Fl_Wizard widgets. - Updated configure stuff to support shared libraries under AIX (link to -lfltk_s) - Symbol labels can now contain regular text. - FLUID now supports relative filenames for the source and header files you generate. - Fl_Menu_Item::add() didn't use the flags that were passed in. - Fixed a bug in Fl_Scrollbar - clicking in the "trough" of the scrollbar would move the scroller in the wrong direction. - Made the Forms pixmap parameter const to match the Fl_Pixmap.H definitions. - Changed the Fl_Pixmap constructor to use the explicit keyword which should work for all C++ compilers. - Fl_Menu_add of a menu item with the same name as an existing submenu title would mess up by replacing that menu title, it now adds a new item. - Fl_Menu::add() of text starting with '/' to a menu is assumed to be a filename. So "/foo/bar" creates a single menu item. You can also put filenames into submenus by doing "submenu//foo/bar", this will create a submenu called "submenu" with an item "/foo/bar". Menu items starting with "\_" will insert an item starting with '_' rather than a divider line. These changes make the menus compatable with fltk 2.0. - Another little fix for the BoXX OpenGL overlays. - Fl_Gl_Window no longer blanks the mouse pointer on WIN32 unless an OpenGL overlay is being used. This should make non-overlay displays faster when a cursor is set. fltk-1.4.3/lib/0000755000175000017500000000000015004135251013353 5ustar albrechtalbrechtfltk-1.4.3/lib/README.txt0000644000175000017500000000177215004135251015060 0ustar albrechtalbrechtlib/README.txt -------------- This README file is a placeholder for FLTK library files on your system if FLTK is built using 'configure' and 'make'. Building FLTK with CMake If FLTK is built using CMake all static and shared libraries are created in the 'lib' subdirectory of the build tree. We strongly recommend to build with CMake outside the source tree ("out-of-tree") as described in README.CMake.txt in the root folder of the FLTK distribution. If FLTK is built out-of-tree as recommended this folder will not be touched. Building FLTK with configure + make Under UNIX/Linux and other systems that support 'configure' and 'make' (e.g. MinGW, MSYS) a single set of library files will be built, with or without debug information depending on the options you provided to the configure script. The FLTK build system based on configure does not support out-of-tree builds, hence the static libraries will be built in this 'lib' folder and the shared libraries (if enabled) can be found in the 'src' folder. fltk-1.4.3/configure.ac0000644000175000017500000017435615004135251015113 0ustar albrechtalbrechtdnl -*- sh -*- dnl the "configure" script is made from this by running GNU "autoconf" dnl dnl Configuration script for the Fast Light Tool Kit (FLTK). dnl dnl Copyright 1998-2025 by Bill Spitzak and others. dnl dnl This library is free software. Distribution and use rights are outlined in dnl the file "COPYING" which should have been included with this file. If this dnl file is missing or damaged, see the license at: dnl dnl https://www.fltk.org/COPYING.php dnl dnl Please see the following page on how to report bugs and issues: dnl dnl https://www.fltk.org/bugs.php dnl dnl We need at least autoconf 2.50... AC_PREREQ([2.50]) dnl Package name and version AC_INIT([fltk], [1.4.3], [https://github.com/fltk/fltk/issues], [fltk], [https://www.fltk.org/]) FLTK_VERSION="AC_PACKAGE_VERSION" FLTK_VERSION_MAJOR=$(echo AC_PACKAGE_VERSION | awk -F. '{print $1}') FLTK_VERSION_MINOR=$(echo AC_PACKAGE_VERSION | awk -F. '{print $2}') FLTK_VERSION_PATCH=$(echo AC_PACKAGE_VERSION | awk -F. '{print $3}') FL_DSO_VERSION="${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR}" FL_ABI_VERSION="${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR}.0" AC_SUBST(FLTK_VERSION) AC_SUBST(FLTK_VERSION_MAJOR) AC_SUBST(FLTK_VERSION_MINOR) AC_SUBST(FLTK_VERSION_PATCH) AC_SUBST(FL_DSO_VERSION) AC_SUBST(FL_ABI_VERSION) dnl Required file in package... AC_CONFIG_SRCDIR([src/Fl.cxx]) AC_CANONICAL_HOST dnl determine whether we're cross-compiling AS_IF([test "$host" != "$build"], [ fltk_cross_compiling="yes" ], [ fltk_cross_compiling="no" ]) dnl Do not automatically add "-g" to compiler options... dnl This must be _before_ "Find compiler commands..." CFLAGS="${CFLAGS:=}" CPPFLAGS="${CPPFLAGS:=}" CXXFLAGS="${CXXFLAGS:=}" DSOFLAGS="${DSOFLAGS:=}" LDFLAGS="${LDFLAGS:=}" LIBS="${LDFLAGS:=}" dnl Find common commands... AC_PROG_CC AC_PROG_CXX AC_PATH_TOOL(PKGCONFIG, pkg-config) dnl Architecture and optimization options... ARCHFLAGS="${ARCHFLAGS:=}" AC_ARG_WITH([archflags], AS_HELP_STRING([--with-archflags="flags"], [use custom architecture flags (default=none, macOS values include "-arch arm64", "-arch i386", "-arch ppc", and "-arch x86_64")]), [ ARCHFLAGS="$withval" ]) AC_SUBST(ARCHFLAGS) OPTIM="${OPTIM:=}" AC_ARG_WITH(optim, AS_HELP_STRING([--with-optim="flags"], [use custom optimization flags]), [ OPTIM="$withval" ]) AC_SUBST(OPTIM) dnl Other options AC_ARG_ENABLE([cairo], AS_HELP_STRING([--enable-cairo], [add support for Fl_Cairo_Window])) AC_ARG_ENABLE([cairoext], AS_HELP_STRING([--enable-cairoext], [use FLTK code instrumentation for Cairo extended use])) AC_ARG_ENABLE([cp936], AS_HELP_STRING([--enable-cp936], [turn on CP936])) AS_IF([test x$enable_cp936 = xyes], [ CFLAGS="$CFLAGS -DCP936" ]) AC_ARG_ENABLE([cygwin], AS_HELP_STRING([--enable-cygwin], [use the Cygwin DLL (default=no)])) AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [turn on debugging])) AS_IF([test x$enable_debug = xyes], [ DEBUGFLAG="-g " ], [ DEBUGFLAG="" ]) AC_ARG_ENABLE([test], AS_HELP_STRING([--disable-test], [build test programs (default=yes)])) AS_IF([test x$enable_test = xno], [ TESTDIR="" ], [ TESTDIR="test" ]) AC_SUBST(TESTDIR) AC_ARG_ENABLE([forms], AS_HELP_STRING([--disable-forms], [build Forms compatibility library (default=yes)])) AC_ARG_ENABLE([gl], AS_HELP_STRING([--disable-gl], [turn off OpenGL support])) AC_ARG_ENABLE([localjpeg], AS_HELP_STRING([--enable-localjpeg], [use local JPEG library (default=auto)])) AC_ARG_ENABLE([localpng], AS_HELP_STRING([--enable-localpng], [use local PNG library (default=auto)])) AC_ARG_ENABLE([localzlib], AS_HELP_STRING([--enable-localzlib], [use local ZLIB library (default=auto)])) AC_ARG_ENABLE([pango], AS_HELP_STRING([--enable-pango], [turn on Pango support])) AC_ARG_ENABLE([wayland], AS_HELP_STRING([--disable-wayland], [turn off hybrid Wayland/X11 support])) AC_ARG_ENABLE([usecairo], AS_HELP_STRING([--enable-usecairo], [all drawing to X11 windows uses Cairo])) AC_ARG_ENABLE([use_std], AS_HELP_STRING([--enable-use_std], [allow FLTK to use std::string etc.])) AC_ARG_ENABLE([print], AS_HELP_STRING([--disable-print], [turn off print support (X11)])) AS_IF([test x$enable_print = xno], [ AC_DEFINE([FL_NO_PRINT_SUPPORT], [Disable X11 print support?]) ]) AC_ARG_ENABLE([shared], AS_HELP_STRING([--enable-shared], [turn on shared libraries])) AC_ARG_ENABLE([svg], AS_HELP_STRING([--disable-svg], [disable SVG support])) AS_IF([test x$enable_svg != xno], [ AC_DEFINE([FLTK_USE_SVG], 1, [SVG image support]) ]) AC_ARG_ENABLE([threads], AS_HELP_STRING([--disable-threads], [turn off multi-threading support])) AC_ARG_ENABLE([x11], AS_HELP_STRING([--enable-x11], [use X11 with Cygwin or macOS (default=no)])) AC_ARG_ENABLE([xcursor], AS_HELP_STRING([--disable-xcursor], [turn off Xcursor support])) AC_ARG_ENABLE([xfixes], AS_HELP_STRING([--disable-xfixes], [turn off Xfixes support])) AC_ARG_ENABLE([xft], AS_HELP_STRING([--disable-xft], [turn off Xft support])) AC_ARG_ENABLE([xinerama], AS_HELP_STRING([--disable-xinerama], [turn off Xinerama support])) AC_ARG_ENABLE([xrender], AS_HELP_STRING([--disable-xrender], [turn off Xrender support])) AC_ARG_ENABLE([fluid], AS_HELP_STRING([--disable-fluid], [turn off fluid building])) AS_CASE([$host_os], [cygwin* | mingw*], [ AC_ARG_ENABLE([gdiplus], AS_HELP_STRING([--disable-gdiplus], [don't use GDI+ for antialiased graphics])) gdiplus_found=no AS_IF([test x$enable_gdiplus != xno], [ AC_CHECK_HEADERS([wtypes.h gdiplus.h], [ AC_DEFINE([USE_GDIPLUS]) LIBS="-lgdiplus $LIBS" gdiplus_found=yes ], [], [[#include ]]) ]) ]) AS_IF([test x$enable_pango = xyes -a x$enable_xft = xno], [ AC_MSG_ERROR([--disable-xft and --enable-pango are incompatible because Xft is necessary for Pango.]) ]) dnl So --with-archflags option is used during "checking size of long" # TODO: Fix long long test AS_IF([test "x$with_archflags" != x], [ CFLAGS="$CFLAGS $with_archflags" ]) dnl FLTK build options to be used in Makefiles (defined in makeinclude) BUILD="" dnl OS-specific pre-tests... dnl host_os_gui equals $host_os unless we target Cygwin or Darwin in combination with X11. host_os_gui=$host_os AS_CASE([$host_os], [cygwin*], [ # Handle Cygwin option *first*, before all other tests. AS_IF([test x$enable_cygwin = xyes], [ # we target Cygwin in combination with X11 AS_IF([test x$enable_x11 = xyes], [ host_os_gui="X11$host_os" ]) ]) ], [darwin*], [ AS_IF([test x$enable_x11 = xyes], [ host_os_gui="X11" macosversion=$(sw_vers -productVersion | cut -d. -f2) macosversion_maj=$(sw_vers -productVersion | cut -d. -f1) AS_IF([test $macosversion_maj -ge 11 -o $macosversion -ge 13], [ CXXFLAGS="$CXXFLAGS -mmacosx-version-min=10.9 -D_LIBCPP_HAS_THREAD_API_PTHREAD" ]) ]) ]) dnl Define the libraries and link options we will need. LINKFLTK="../lib/libfltk.a" LINKFLTKGL="../lib/libfltk_gl.a" LINKFLTKIMG="../lib/libfltk_images.a" GLDEMOS="gldemos" LIBEXT=".a" LIBNAME="../lib/libfltk.a" GLLIBNAME="../lib/libfltk_gl.a" IMGLIBNAME="../lib/libfltk_images.a" CAIROLIBNAME="../lib/libfltk_cairo.a" LIBBASENAME="libfltk.a" GLLIBBASENAME="libfltk_gl.a" IMGLIBBASENAME="libfltk_images.a" CAIROLIBBASENAME="libfltk_cairo.a" dnl set library names etc. for the optional forms library and set 'build_forms' dnl to make conditional code independent of the default value of 'enable_forms' dnl which is 'yes' (enabled) in 1.4.0 (default may be changed later) AS_IF([test x$enable_forms != xno], [ build_forms="yes" LINKFLTKFORMS="../lib/libfltk_forms.a" FLLIBNAME="../lib/libfltk_forms.a" FLLIBBASENAME="libfltk_forms.a" AC_DEFINE([FLTK_HAVE_FORMS]) ], [ build_forms="no" LINKFLTKFORMS="" FLLIBNAME="" FLLIBBASENAME="" ]) dnl Check for Cairo library unless disabled... CAIRODIR="" CAIROFLAGS="" LINKFLTKCAIRO="" FLTKCAIROOPTION="" CAIROLIBS="" AS_IF([test x$enable_cairoext = xyes], [ AS_IF([$PKGCONFIG --exists cairo], [ AC_DEFINE([FLTK_HAVE_CAIROEXT]) AC_DEFINE([FLTK_HAVE_CAIRO]) CAIRODIR="cairo" CAIROFLAGS="$($PKGCONFIG --cflags cairo)" CAIROLIBS="$($PKGCONFIG --libs cairo)" CXXFLAGS="$CAIROFLAGS $CXXFLAGS" LINKFLTKCAIRO="../lib/libfltk_cairo.a" FLTKCAIROOPTION="-L ../cairo -lfltk_cairo$SHAREDSUFFIX" LIBS="$CAIROLIBS $LIBS" LINKFLTK="$LINKFLTK $LINKFLTKCAIRO" ], [ AC_MSG_ERROR([Cairo requested but not found.]) ]) ], [test x$enable_cairo = xyes], [ AS_IF([$PKGCONFIG --exists cairo], [ AC_DEFINE(FLTK_HAVE_CAIRO) CAIRODIR="cairo" CAIROFLAGS="$($PKGCONFIG --cflags cairo)" CAIROLIBS="$($PKGCONFIG --libs cairo)" CXXFLAGS="$CAIROFLAGS $CXXFLAGS" LINKFLTKCAIRO="../lib/libfltk_cairo.a" FLTKCAIROOPTION="-L ../cairo -lfltk_cairo$SHAREDSUFFIX" ], [ AC_MSG_ERROR([Cairo requested but not found.]) ]) ]) AC_SUBST(CAIRODIR) AC_SUBST(CAIROFLAGS) AC_SUBST(CAIROLIBS) AC_SUBST(LINKFLTKCAIRO) AC_SUBST(FLTKCAIROOPTION) AC_SUBST(GLDEMOS) AC_SUBST(GLLIBNAME) AC_SUBST(IMGLIBNAME) AC_SUBST(CAIROLIBNAME) AC_SUBST(LIBEXT) AC_SUBST(LIBNAME) AC_SUBST(LINKFLTK) AC_SUBST(LINKFLTKGL) AC_SUBST(LINKFLTKIMG) AC_SUBST(LIBBASENAME) AC_SUBST(GLLIBBASENAME) AC_SUBST(IMGLIBBASENAME) AC_SUBST(CAIROLIBBASENAME) AC_ARG_WITH([abiversion], AS_HELP_STRING([--with-abiversion], [Build with FL_ABI_VERSION, e.g. 10304 for FLTK 1.3.4])) has_abiversion="$with_abiversion" AS_IF([test "x$has_abiversion" = xyes -o "x$has_abiversion" = xno], [ has_abiversion="" ]) AS_IF([test "x$has_abiversion" != x], [ AC_DEFINE_UNQUOTED([FL_ABI_VERSION], [$has_abiversion], [ABI version number]) ]) dnl Handle compile-time options... AS_IF([test "x$enable_shared" = xyes], [ PICFLAG=1 SHAREDSUFFIX="" FLUID="fluid-shared" FLTK_OPTIONS="fltk-options-shared" AS_CASE([$host_os], [darwin*], [ DSONAME="libfltk.$FL_DSO_VERSION.dylib" FLDSONAME="libfltk_forms.$FL_DSO_VERSION.dylib" GLDSONAME="libfltk_gl.$FL_DSO_VERSION.dylib" IMGDSONAME="libfltk_images.$FL_DSO_VERSION.dylib" CAIRODSONAME="libfltk_cairo.$FL_DSO_VERSION.dylib" DSOCOMMAND="\$(CXX) \$(ARCHFLAGS) \$(DSOFLAGS) -dynamiclib -lc -o" ], [solaris*], [ DSONAME="libfltk.so.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.so.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.so.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.so.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.so.$FL_DSO_VERSION" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-soname,\$@ \$(LDLIBS) -shared -fPIC $DEBUGFLAG -o" AS_IF([test "x$libdir" != "x/usr/lib"], [ DSOLINK="-R$libdir" ]) ], [hpux*], [ DSONAME="libfltk.sl.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.sl.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.sl.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.sl.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.sl.$FL_DSO_VERSION" DSOCOMMAND="ld \$(DSOFLAGS) -b -z +h \$@ $DEBUGFLAG -o" AS_IF([test "x$libdir" != "x/usr/lib"], [ DSOLINK="-Wl,-rpath,$libdir" ]) ], [irix*], [ DSONAME="libfltk.so.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.so.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.so.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.so.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.so.$FL_DSO_VERSION" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-soname,\$@,-set_version,sgi1.1 \$(LDLIBS) -shared $DEBUGFLAG -o" AS_IF([test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/usr/lib32" -a "x$libdir" != "x/usr/lib64"], [ DSOLINK="-Wl,-rpath,$libdir" ]) ], [osf*], [ DSONAME="libfltk.so.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.so.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.so.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.so.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.so.$FL_DSO_VERSION" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-soname,\$@ \$(LDLIBS) -shared $DEBUGFLAG -o" AS_IF([test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/usr/lib32"], [ DSOLINK="-Wl,-rpath,$libdir" ]) ], [linux*|*bsd*], [ DSONAME="libfltk.so.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.so.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.so.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.so.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.so.$FL_DSO_VERSION" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-soname,\$@ \$(LDLIBS) -shared -fPIC $DEBUGFLAG -o" # See if the compiler supports -fvisibility... AC_CACHE_CHECK([if the compiler supports -fvisibility], ac_cv_cxx_fvisibility, [ OLDCXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -fvisibility=hidden" AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[]], [[]])], [ac_cv_cxx_fvisibility=yes], [ac_cv_cxx_fvisibility=no]) CXXFLAGS="$OLDCXXFLAGS" AC_LANG_POP([]) ]) AS_IF([test x"$ac_cv_cxx_fvisibility" = xyes], [ OPTIM="$OPTIM -fvisibility=hidden" ]) # See if the compiler supports -fvisibility-inlines-hidden... AC_CACHE_CHECK([if the compiler supports -fvisibility-inlines-hidden], [ac_cv_cxx_fvisibility_inlines], [ OLDCXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden" AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[]], [[]])], [ac_cv_cxx_fvisibility_inlines=yes], [ac_cv_cxx_fvisibility_inlines=no]) CXXFLAGS="$OLDCXXFLAGS" AC_LANG_POP([]) ]) AS_IF([test x"$ac_cv_cxx_fvisibility_inlines" = xyes], [ CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden" ]) AS_IF([test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/usr/lib64"], [ DSOLINK="-Wl,-rpath,$libdir" ]) ], [aix*], [ DSONAME="libfltk_s.a" FLDSONAME="libfltk_forms_s.a" GLDSONAME="libfltk_gl_s.a" IMGDSONAME="libfltk_images_s.a" CAIRODSONAME="libfltk_cairo_s.a" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-bexpall,-bM:SRE,-bnoentry -o" SHAREDSUFFIX="_s" ], [cygwin* | mingw*], [ PICFLAG=0 AS_IF([test x$enable_cygwin != xyes], [ DSONAME="mgwfltknox-$FL_DSO_VERSION.dll" FLDSONAME="mgwfltknox_forms-$FL_DSO_VERSION.dll" GLDSONAME="mgwfltknox_gl-$FL_DSO_VERSION.dll" IMGDSONAME="mgwfltknox_images-$FL_DSO_VERSION.dll" CAIRODSONAME="mgwfltknox_cairo-$FL_DSO_VERSION.dll" ], [test x$enable_x11 = xyes], [ DSONAME="cygfltk-$FL_DSO_VERSION.dll" FLDSONAME="cygfltk_forms-$FL_DSO_VERSION.dll" GLDSONAME="cygfltk_gl-$FL_DSO_VERSION.dll" IMGDSONAME="cygfltk_images-$FL_DSO_VERSION.dll" CAIRODSONAME="cygfltk_cairo-$FL_DSO_VERSION.dll" ], [ DSONAME="cygfltknox-$FL_DSO_VERSION.dll" FLDSONAME="cygfltknox_forms-$FL_DSO_VERSION.dll" GLDSONAME="cygfltknox_gl-$FL_DSO_VERSION.dll" IMGDSONAME="cygfltknox_images-$FL_DSO_VERSION.dll" CAIRODSONAME="cygfltknox_cairo-$FL_DSO_VERSION.dll" ]) #----------------------------------------------------------- # -Wl,--enable-runtime-pseudo-reloc: See str 1585 # appears to be necessary for older binutils versions < 2.16 #----------------------------------------------------------- LDFLAGS="$LDFLAGS -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -shared -Wl,--whole-archive -Wl,--export-all-symbols -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-auto-import -Wl,--enable-auto-image-base -o \$@" ], [*], [ AC_MSG_WARN([Shared libraries may not be supported. Trying -shared option with compiler.]) DSONAME="libfltk.so.$FL_DSO_VERSION" FLDSONAME="libfltk_forms.so.$FL_DSO_VERSION" GLDSONAME="libfltk_gl.so.$FL_DSO_VERSION" IMGDSONAME="libfltk_images.so.$FL_DSO_VERSION" CAIRODSONAME="libfltk_cairo.so.$FL_DSO_VERSION" DSOCOMMAND="\$(CXX) \$(DSOFLAGS) -Wl,-soname,\$@ \$(LDLIBS) -shared $DEBUGFLAG -o" ]) LINKSHARED="-L../src $FLTKCAIROOPTION -lfltk_images$SHAREDSUFFIX -lfltk$SHAREDSUFFIX" ], [ DSOCOMMAND="echo" DSOLINK="" DSONAME="" FLDSONAME="" GLDSONAME="" IMGDSONAME="" CAIRODSONAME="" PICFLAG=0 SHAREDSUFFIX="" FLUID="fluid" FLTK_OPTIONS="fltk-options" LINKSHARED="$LINKFLTKCAIRO ../lib/libfltk_images.a ../lib/libfltk.a" ]) dnl reset FLDSONAME if the Forms compatibility library is disabled (not built): dnl overwrite the variable because this is easier than adding conditional code above AS_IF([test x$build_forms = xno], [ FLDSONAME="" ]) AC_SUBST([FLLIBNAME]) AC_SUBST([FLLIBBASENAME]) AC_SUBST([FLDSONAME]) AC_SUBST([LINKFLTKFORMS]) AC_SUBST([LINKSHARED]) dnl Define the fluid executable used when building the test programs. dnl In a native build we use the fluid executable created during the build, dnl in a cross-compilation we use "fluid" which must exist on the build system dnl and must be in the PATH, i.e. executable as 'fluid' (w/o $EXEEXT). AS_IF([test "x$fltk_cross_compiling" = xyes], [ FLUID_BUILD="fluid" ], [ FLUID_BUILD="../fluid/fluid$EXEEXT" ]) AC_SUBST([DSOCOMMAND]) AC_SUBST([DSOFLAGS]) AC_SUBST([DSOLINK]) AC_SUBST([DSONAME]) AC_SUBST([GLDSONAME]) AC_SUBST([IMGDSONAME]) AC_SUBST([CAIRODSONAME]) AC_SUBST([SHAREDSUFFIX]) AC_SUBST([FLUID]) AC_SUBST([FLUID_BUILD]) AC_SUBST([FLTK_OPTIONS]) dnl Find commands... AC_PROG_INSTALL AS_CASE([$host_os], [osf*], [ INSTALL="$(pwd)/install-sh -c" ]) AS_IF([test "x$INSTALL" = "x$ac_install_sh"], [ # Use full path to install-sh script... INSTALL="$(pwd)/install-sh -c" ]) AC_PATH_PROGS([NROFF], [nroff groff], [echo]) AC_PATH_PROG([DOXYDOC], [doxygen]) dnl How do we make libraries? AC_PROG_RANLIB AC_PATH_TOOL([AR], [ar]) AS_IF([test "x$AR" = "x:"], [ AC_MSG_ERROR([Configure could not find the library archiver, aborting.]) ]) AS_IF([test "x$RANLIB" != "x:"], [ LIBCOMMAND="$AR cr" ], [ LIBCOMMAND="$AR crs" ]) AC_SUBST(LIBCOMMAND) dnl how to compile (Windows) resource files dnl this will only be used to compile resources for Windows .exe files AC_PATH_TOOL(RC,windres) dnl Architecture checks... AC_CHECK_SIZEOF(short, 2) AC_CHECK_SIZEOF(int, 4) AC_CHECK_SIZEOF(long, 4) AS_IF([test $ac_cv_sizeof_short -eq 2], [ AC_DEFINE([U16], [unsigned short]) ]) AS_IF([test $ac_cv_sizeof_int -eq 4], [ AC_DEFINE([U32], [unsigned]) ], [test $ac_cv_sizeof_long -eq 4], [ AC_DEFINE([U32],[unsigned long]) ]) AS_CASE([$host_os], [darwin*], [ ], [*], [ AC_C_BIGENDIAN AS_IF([test $ac_cv_sizeof_int -eq 8], [ AC_DEFINE([U64], [unsigned]) ], [test $ac_cv_sizeof_long -eq 8], [ AC_DEFINE([U64], [unsigned long]) ]) ]) dnl Standard headers and functions... AC_HEADER_DIRENT AC_CHECK_HEADERS([sys/select.h sys/stdtypes.h]) dnl Do we have the POSIX compatible scandir() prototype? AC_CACHE_CHECK([whether we have the POSIX compatible scandir() prototype], ac_cv_cxx_scandir_posix,[ AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include int func (const char *d, dirent ***list, void *sort) { int n = scandir(d, list, 0, (int(*)(const dirent **, const dirent **))sort); return n; } ]], [[ ]])], [ac_cv_cxx_scandir_posix=yes], [ac_cv_cxx_scandir_posix=no]) AC_LANG_POP([]) ]) dnl Define both HAVE_SCANDIR... macros, if the POSIX compatible function is dnl available. Otherwise: check, whether any scandir prototype is available, dnl but dont use it on SunOS and QNX because of an incompatibility in pre-Y2K dnl SunOS scandir versions. We assume, though, that the POSIX compatible dnl version on newer SunOS/Solaris versions works as expected. AS_IF([test "x$ac_cv_cxx_scandir_posix" = xyes], [ AC_DEFINE([HAVE_SCANDIR]) AC_DEFINE([HAVE_SCANDIR_POSIX]) ], [ AC_CHECK_FUNC([scandir], [ AS_CASE([$host_os], [solaris* | *qnx*], [ AC_MSG_WARN([Not using $host_os scandir emulation function.]) ], [*], [ AC_DEFINE([HAVE_SCANDIR]) ]) ]) ]) AC_CHECK_FUNC([vsnprintf], [ AS_CASE([$host_os], [hpux1020], [ AC_MSG_WARN([Not using built-in vsnprintf function because you are running HP-UX 10.20.]) ], [osf4], [ AC_MSG_WARN([Not using built-in vsnprintf function because you are running Tru64 4.0.]) ], [*], [ AC_DEFINE([HAVE_VSNPRINTF]) ]) ]) AC_CHECK_FUNC([snprintf], [ AS_CASE([$host_os], [hpux1020], [ AC_MSG_WARN([Not using built-in snprintf function because you are running HP-UX 10.20.]) ], [osf4], [ AC_MSG_WARN([Not using built-in snprintf function because you are running Tru64 4.0.]) ], [*], [ AC_DEFINE([HAVE_SNPRINTF]) ]) ]) AC_CHECK_HEADERS([strings.h]) AC_CHECK_FUNCS([strcasecmp strlcat strlcpy]) AC_CHECK_HEADERS([locale.h]) AC_CHECK_FUNCS([localeconv]) dnl HP-UX 11.11 does not provide setenv() AC_CHECK_FUNCS([setenv]) dnl FLTK library uses math library functions... AC_SEARCH_LIBS([pow], [m]) AC_CHECK_HEADERS([math.h]) AC_CHECK_FUNCS([trunc]) dnl Check for largefile support... AC_SYS_LARGEFILE LARGEFILE="" AS_IF([test x$enable_largefile != xno], [ LARGEFILE="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE" AS_IF([test x$ac_cv_sys_large_files = x1], [ LARGEFILE="$LARGEFILE -D_LARGE_FILES" ]) AS_IF([test x$ac_cv_sys_file_offset_bits = x64], [ LARGEFILE="$LARGEFILE -D_FILE_OFFSET_BITS=64" ]) ]) AC_SUBST(LARGEFILE) dnl Check for "long long" support... AC_CACHE_CHECK([for long long int], [ac_cv_c_long_long], [ AS_IF([test "$GCC" = yes], [ ac_cv_c_long_long=yes ], [ AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[]], [[long long int i;]])], [ac_cv_c_long_long=yes], [ac_cv_c_long_long=no]) ]) ]) AS_IF([test $ac_cv_c_long_long = yes], [ AC_DEFINE([HAVE_LONG_LONG]) ]) dnl Check for dlopen/dlsym... AC_SEARCH_LIBS([dlsym], [dl], AC_DEFINE([HAVE_DLSYM])) AC_CHECK_HEADER([dlfcn.h], AC_DEFINE([HAVE_DLFCN_H])) dnl Check for audio libraries... AUDIOLIBS="" AS_CASE([$host_os], [cygwin* | mingw*], [ dnl Cygwin environment... AUDIOLIBS="-lwinmm" ], [darwin*], [ AUDIOLIBS="-framework CoreAudio" ], [*], [ AC_CHECK_HEADER([alsa/asoundlib.h], [ AC_DEFINE([HAVE_ALSA_ASOUNDLIB_H]) AUDIOLIBS="-lasound" ]) ]) AC_SUBST(AUDIOLIBS) dnl Check for image libraries... SAVELIBS="$LIBS" IMAGELIBS="" STATICIMAGELIBS="" AC_SUBST([IMAGELIBS]) AC_SUBST([STATICIMAGELIBS]) # Handle the JPEG lib linking mode (use fltk local or system lib) # If --enable-(resp. --disable-)localjpeg parameter is not set by user # Then we check the JPEG lib usability, with result in sysjpeglib_ok variable # Check for System lib use if automatic mode or --disable-localjpeg is requested sysjpeglib_ok=no sysjpeginc_ok=no AS_IF([test x$enable_localjpeg != xyes], [ AC_CHECK_LIB([jpeg], [jpeg_CreateCompress], [ AC_CHECK_HEADER([jpeglib.h], [sysjpeginc_ok=yes]) AS_IF([test x$sysjpeginc_ok = xyes], [ sysjpeglib_ok=yes ]) ]) ]) # Now set the jpeg lib and include flags according to the requested mode and availability AS_IF([test x$enable_localjpeg = xyes -o x$sysjpeglib_ok = xno], [ JPEGINC="-I../jpeg" JPEG="jpeg" IMAGELIBS="-lfltk_jpeg $IMAGELIBS" STATICIMAGELIBS="\$libdir/libfltk_jpeg.a $STATICIMAGELIBS" AC_DEFINE([HAVE_LIBJPEG]) # Finally, warn user if system lib was requested but not found AS_IF([test x$enable_localjpeg = xno], [ AC_MSG_WARN([Cannot find system jpeg lib or header: choosing the local lib mode.]) ]) ], [ JPEGINC="" JPEG="" IMAGELIBS="-ljpeg $IMAGELIBS" STATICIMAGELIBS="-ljpeg $STATICIMAGELIBS" AC_DEFINE([HAVE_LIBJPEG]) ]) # Handle the ZLIB lib linking mode (use fltk local or system lib) # If --enable-(resp. --disable-)localzlib parameter is not set by user # Then we check the ZLIB lib usability, with result in syszlib_ok variable # Check for System lib use if automatic mode or --disable-localzlib is requested syszlib_ok=no syszinc_ok=no AS_IF([test x$enable_localzlib != xyes], [ AC_CHECK_LIB([z], [gzgets], [ AC_CHECK_HEADER([zlib.h], [syszinc_ok=yes]) AS_IF([test x$syszinc_ok = xyes], [ syszlib_ok=yes ]) ]) ]) # Handle the PNG lib linking mode (use fltk local or system lib) # If --enable-(resp. --disable-)localpng parameter is not set by user # Then we check the png lib usability with result in syspng_lib variable # Now check if system lib is usable, we check Lib AND include availability with inc variant, # but only, if the builtin lib is not requested syspnglib_ok=no syspnginc_ok=no AS_IF([test x$enable_localpng != xyes -a x$PKGCONFIG != x], [ AC_MSG_CHECKING([for libpng-1.6.x]) AS_IF([$PKGCONFIG --exists libpng16], [ AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_PNG_H], 1, [Have PNG library?]) syspnginc_ok=yes syspnglib_ok=yes PNGINC="$($PKGCONFIG --cflags libpng16)" IMAGELIBS="$($PKGCONFIG --libs libpng16) $IMAGELIBS" STATICIMAGELIBS="$($PKGCONFIG --libs libpng16) $STATICIMAGELIBS" ], [ AC_MSG_RESULT([no]) ]) ]) AS_IF([test x$enable_localpng != xyes -a $syspnglib_ok = no], [ AC_CHECK_LIB([png], [png_read_info], [ AC_CHECK_HEADER([png.h], [ AC_DEFINE([HAVE_PNG_H]) syspnginc_ok=yes ]) AC_CHECK_HEADER([libpng/png.h], [ syspnginc_ok=yes ]) AS_IF([test x$syspnginc_ok = xyes], [ syspnglib_ok=yes ]) ]) ]) # If we use the system zlib, we must also use the system png lib and vice versa. # If either of them is not available, we fall back to using both local libraries AS_IF([test x$syspnglib_ok = xyes -a x$syszlib_ok != xyes], [ syspnglib_ok=no enable_localpng=yes AC_MSG_WARN([Local z lib selected: overriding png lib to local for compatibility.]) ]) AS_IF([test x$syszlib_ok = xyes -a x$syspnglib_ok != xyes], [ syszlib_ok=no enable_localzlib=yes AC_MSG_WARN([Local png lib selected: overriding z lib to local for compatibility.]) ]) # Now set the Z lib and include flags according to the requested mode and availability AS_IF([test x$enable_localzlib = xyes -o x$syszlib_ok = xno], [ ZLIBINC="-I../zlib" ZLIB="zlib" LIBS="-lfltk_z $LIBS" IMAGELIBS="-lfltk_z $IMAGELIBS" STATICIMAGELIBS="\$libdir/libfltk_z.a $STATICIMAGELIBS" AC_DEFINE([HAVE_LIBZ]) ac_cv_lib_z_gzgets=no # fc: is still necessary ? # Finally, warn user if system lib was requested but not found AS_IF([test x$enable_localzlib = xno], [ AC_MSG_WARN([Cannot find system z lib or header: choosing the local lib mode.]) ]) ], [ ZLIBINC="" ZLIB="" LIBS="-lz $LIBS" IMAGELIBS="-lz $IMAGELIBS" STATICIMAGELIBS="-lz $STATICIMAGELIBS" AC_DEFINE([HAVE_LIBZ]) ]) # The following is executed if the png lib was not found usable or if local lib is required explicitly AS_IF([test x$enable_localpng = xyes -o x$syspnglib_ok = xno], [ PNGINC="-I../png" PNG="png" IMAGELIBS="-lfltk_png $IMAGELIBS" STATICIMAGELIBS="\$libdir/libfltk_png.a $STATICIMAGELIBS" AC_DEFINE([HAVE_LIBPNG]) AC_DEFINE([HAVE_PNG_H]) AC_DEFINE([HAVE_PNG_GET_VALID]) AC_DEFINE([HAVE_PNG_SET_TRNS_TO_ALPHA]) # Finally, warn user if system lib was requested but not found AS_IF([test x$enable_localpng = xno], [ AC_MSG_WARN([Cannot find system png lib or header: choosing the local lib mode.]) ]) ], [ PNGINC="" PNG="" IMAGELIBS="-lpng $IMAGELIBS" STATICIMAGELIBS="-lpng $STATICIMAGELIBS" AC_DEFINE([HAVE_LIBPNG]) AC_CHECK_LIB([png], [png_get_valid], [ AC_DEFINE([HAVE_PNG_GET_VALID]) ]) AC_CHECK_LIB([png], [png_set_tRNS_to_alpha], [ AC_DEFINE([HAVE_PNG_SET_TRNS_TO_ALPHA]) ]) ]) AC_SUBST([JPEG]) AC_SUBST([JPEGINC]) AC_SUBST([PNG]) AC_SUBST([PNGINC]) AC_SUBST([HAVE_PNG_H]) AC_SUBST([ZLIB]) AC_SUBST([ZLIBINC]) # Control the usage of the nanosvg lib and SVG output dnl Restore original LIBS settings... LIBS="$SAVELIBS" dnl See if we need a .exe extension on executables... AC_EXEEXT dnl Check for pthreads for multi-threaded apps... have_pthread=no PTHREAD_FLAGS="" dnl Test whether we want to check for pthreads. We must not do it on Windows dnl unless we run under Cygwin with --enable-cygwin, since we always use dnl native threads on Windows (even if libpthread is available) check_pthread=yes AS_CASE([$host_os], [mingw*], [ check_pthread=no ], [cygwin*], [ AS_IF([test "x$enable_cygwin" != xyes], [ check_pthread=no ]) ]) AS_IF([test "x$enable_threads" != xno -a x$check_pthread = xyes], [ AC_CHECK_HEADERS([pthread.h]) AS_IF([test x$ac_cv_header_pthread_h = xyes], [ dnl Check various threading options for the platforms we support for flag in -lpthreads -lpthread -pthread; do AC_MSG_CHECKING([for pthread_create using $flag]) SAVELIBS="$LIBS" LIBS="$flag $LIBS" AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[pthread_create(0, 0, 0, 0);]])], [have_pthread=yes], [LIBS="$SAVELIBS"]) AC_MSG_RESULT([$have_pthread]) AS_IF([test $have_pthread = yes], [ AC_DEFINE([HAVE_PTHREAD]) PTHREAD_FLAGS="-D_THREAD_SAFE -D_REENTRANT" # Solaris requires -D_POSIX_PTHREAD_SEMANTICS to # be POSIX-compliant... :( AS_CASE([$host_os], [solaris*], [ PTHREAD_FLAGS="$PTHREAD_FLAGS -D_POSIX_PTHREAD_SEMANTICS" ]) ]) done dnl Check if we have PTHREAD_MUTEX_RECURSIVE AC_CACHE_CHECK([whether we have PTHREAD_MUTEX_RECURSIVE], ac_cv_pthread_mutex_recursive,[ AC_LANG_PUSH([C]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[ return PTHREAD_MUTEX_RECURSIVE; ]])], [ac_cv_pthread_mutex_recursive=yes], [ac_cv_pthread_mutex_recursive=no]) AC_LANG_POP([]) ]) AS_IF([test x$ac_cv_pthread_mutex_recursive = xyes], [ AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE]) ]) ]) ]) AC_SUBST([PTHREAD_FLAGS]) AC_SUBST([HAVE_PTHREAD_MUTEX_RECURSIVE]) dnl Define OS-specific stuff... HLINKS= OSX_ONLY=: THREADS= LIBDECORDIR="" LIBDECORDBUS="" FLUIDDIR="" AC_ARG_WITH([links], AS_HELP_STRING([--with-links], [make header links for common misspellings (default=no)])) INSTALL_DESKTOP="" UNINSTALL_DESKTOP="" AS_IF([test x$enable_fluid != xno], [FLUIDDIR="fluid"]) dnl Option use_std - allow std::string and maybe more AS_IF([test x$enable_use_std = xyes], [ AC_DEFINE([FLTK_USE_STD]) ] ) dnl Platform specific Processing AS_CASE([$host_os_gui], [cygwin* | mingw*], [ dnl Cygwin environment, using windows GDI ... # Recent versions of Cygwin are seriously broken and the size # checks don't work because the shell puts out \r\n instead of # \n. Here we just force U32 to be defined to "unsigned"... AC_DEFINE([U32], [unsigned]) # We do no longer define WIN32 or _WIN32 (since FLTK 1.4.0) # and we don't need to define USE_OPENGL32 (added in svn r6657 # but never used, see STR #2147) # CFLAGS="-mwindows -D_WIN32 -DUSE_OPENGL32 $CFLAGS" # CXXFLAGS="-mwindows -D_WIN32 -DUSE_OPENGL32 $CXXFLAGS" LDFLAGS="-mwindows $LDFLAGS" DSOFLAGS="-mwindows $DSOFLAGS" LIBS="$LIBS -lole32 -luuid -lcomctl32 -lws2_32 -lwinspool" BUILD="WIN" AS_IF([test "x$with_optim" = x], [ dnl Avoid -Os optimization on Cygwin/MinGW with_optim="-O3" ]) AS_IF([test x$enable_gl != xno], [ AC_CHECK_HEADER([GL/gl.h], [ AC_DEFINE([HAVE_GL]) GLLIBS="-lopengl32" ]) AC_CHECK_HEADER([GL/glu.h], [ AC_DEFINE([HAVE_GL_GLU_H]) GLLIBS="-lglu32 $GLLIBS" ]) ], [ LINKFLTKGL="" GLLIBNAME="" GLDSONAME="" GLDEMOS="" ]) AS_IF([test "x$enable_threads" != xno -a x$have_pthread = xyes], [ AC_DEFINE([HAVE_PTHREAD]) ]) THREADS="threads$EXEEXT" # Don't make symlinks since Windows is not case sensitive. AS_IF([test "x$with_links" != xyes], [ HLINKS="#" ]) ], [darwin*], [ BUILD="OSX" # MacOS X uses Cocoa for graphics. LIBS="$LIBS -framework Cocoa" # Add weak-linked additional frameworks for increasingly high macOS versions AC_LANG_PUSH([C]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include #if __MAC_OS_X_VERSION_MAX_ALLOWED < 110000 #error __MAC_OS_X_VERSION_MAX_ALLOWED < 110000 #endif ]], [[ ]])], [LIBS="$LIBS -weak_framework UniformTypeIdentifiers"], []) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include #if __MAC_OS_X_VERSION_MAX_ALLOWED < 150000 #error __MAC_OS_X_VERSION_MAX_ALLOWED < 150000 #endif ]], [[ ]])], [LIBS="$LIBS -weak_framework ScreenCaptureKit"], []) AC_LANG_POP([]) AS_IF([test x$have_pthread = xyes], [ AC_DEFINE([HAVE_PTHREAD]) THREADS="threads$EXEEXT" ]) AS_IF([test x$enable_gl != xno], [ AC_DEFINE([HAVE_GL]) AC_DEFINE([HAVE_GL_GLU_H]) GLLIBS="-framework OpenGL" ], [ LINKFLTKGL="" GLLIBNAME="" GLDSONAME="" GLDEMOS="" ]) # Don't make symlinks because HFS+ is not case sensitive... AS_IF([test "x$with_links" != xyes], [ HLINKS="#" ]) # Some steps are only done for OS X package management OSX_ONLY= # Install/Uninstall FLUID application INSTALL_DESKTOP="install-osx" UNINSTALL_DESKTOP="uninstall-osx" ], [*], [ # All others are UNIX/X11... # This includes Cygwin target combined with X11 AS_IF([test x$have_pthread = xyes], [ AC_DEFINE([HAVE_PTHREAD]) THREADS="threads$EXEEXT" ]) AS_IF([test x$enable_wayland != xno], [ AS_IF([test x$PKGCONFIG = x], [ dnl pkg-config is not available, issue warning and possibly abort... AS_IF([test x$enable_wayland = xyes], [ AC_MSG_WARN([--enable-wayland: please install pkg-config.]) AC_MSG_ERROR([Aborting.]) ],[ AC_MSG_WARN([pkg-config is not found. Continuing with --disable-wayland]) enable_wayland="no" ]) ],[ missing="no" AS_IF([$PKGCONFIG --exists 'wayland-client >= 1.18'],[],[missing="yes"]) AS_IF([$PKGCONFIG --exists 'wayland-protocols >= 1.15'],[],[missing="yes"]) AS_IF([$PKGCONFIG --exists wayland-cursor],[],[missing="yes"]) AS_IF([$PKGCONFIG --exists xkbcommon],[],[missing="yes"]) AS_IF([$PKGCONFIG --exists pangocairo],[],[missing="yes"]) AS_IF([test x$missing = xyes], [ AC_MSG_WARN([These packages 'wayland-client>=1.18 wayland-protocols>=1.15 wayland-cursor xkbcommon pangocairo' are required to build FLTK for wayland.]) AC_MSG_WARN([At least one of them is missing.]) AS_IF([test x$enable_wayland = xyes], [ AC_MSG_ERROR([Building for Wayland is not possible. Aborting.]) ],[ AC_MSG_WARN([Continuing with --disable-wayland]) enable_wayland="no" ]) ]) ]) ]) AS_IF([test x$enable_wayland != xno], [ dnl Prepare for Wayland... dnl Turn option usecairo ON AC_DEFINE([FLTK_USE_CAIRO]) AC_MSG_NOTICE([Turning on the usecairo option]) BUILD="WAYLAND" AC_DEFINE([FLTK_USE_WAYLAND]) graphics="Wayland" AS_IF([test x$enable_x11 != xno], [ AC_DEFINE([FLTK_USE_X11]) # to build a hybrid Wayland/X11 library BUILD="WAYLANDX11" graphics="Wayland or X11 with cairo" ]) AS_IF([$PKGCONFIG --exists 'libdecor-0 >= 0.2.0'], [ libdecor="system" plugin_dir="$($PKGCONFIG --variable=libdir libdecor-0)/libdecor/plugins-1" CFLAGS="$CFLAGS -DUSE_SYSTEM_LIBDECOR" CXXFLAGS="$CXXFLAGS -DUSE_SYSTEM_LIBDECOR" CFLAGS="$CFLAGS -DLIBDECOR_PLUGIN_DIR=\\\"$plugin_dir\\\" " LIBS="$LIBS $($PKGCONFIG --libs libdecor-0)" ], [ libdecor="bundled" CFLAGS="$CFLAGS -DUSE_SYSTEM_LIBDECOR=0 -DLIBDECOR_PLUGIN_DIR=\\\"\\\" " CXXFLAGS="$CXXFLAGS -DUSE_SYSTEM_LIBDECOR=0" ] ) LIBS="$LIBS $($PKGCONFIG --libs wayland-cursor) $($PKGCONFIG --libs wayland-client) $($PKGCONFIG --libs xkbcommon) $($PKGCONFIG --libs pangocairo) " AS_IF([test x$enable_x11 != xno], [LIBS="$LIBS $($PKGCONFIG --libs x11)"] ) LIBS="$LIBS -ldl" DSOFLAGS="$LIBS $DSOFLAGS" enable_pango=yes LIBDECORDIR="libdecor/build" AS_IF([$PKGCONFIG --exists dbus-1], [LIBDECORDBUS="-DHAS_DBUS $($PKGCONFIG --cflags dbus-1)" LIBS="$LIBS $($PKGCONFIG --libs dbus-1)"] ) LDFLAGS="$LDFLAGS -rdynamic" AC_SEARCH_LIBS([dlopen], [dl]) AS_IF([test x$enable_gl != xno], [ AS_IF([$PKGCONFIG --exists gl], [ AS_IF([$PKGCONFIG --exists egl], [ AS_IF([$PKGCONFIG --exists wayland-egl], [ AC_DEFINE([HAVE_GL]) GLLIBS="$($PKGCONFIG --libs wayland-egl) $($PKGCONFIG --libs egl) $($PKGCONFIG --libs gl) $GLLIBS" ])])]) AS_IF([$PKGCONFIG --exists glu], [ AC_DEFINE([HAVE_GL_GLU_H]) GLLIBS="$($PKGCONFIG --libs glu) $GLLIBS" ]) AC_CHECK_LIB([GL], [glXGetProcAddressARB], [AC_DEFINE([HAVE_GLXGETPROCADDRESSARB]) ],, [-lm]) ], [ LINKFLTKGL="" GLLIBNAME="" GLDSONAME="" GLDEMOS="" ]) AS_IF([test x$libdecor = xbundled], [ dnl Check for GTK-3 ... gtk_found=no CFLAGS="$($PKGCONFIG --cflags gtk+-3.0) $CFLAGS" AC_CHECK_HEADERS([gtk/gtk.h], [ CFLAGS="$CFLAGS -DHAVE_GTK" LIBS="$LIBS $($PKGCONFIG --libs gtk+-3.0)" gtk_found=yes ]) ]) dnl Check for the Pango library ... pango_found=no CFLAGS="$($PKGCONFIG --cflags pangocairo) $CFLAGS" CXXFLAGS="$($PKGCONFIG --cflags pangocairo) $CXXFLAGS" LIBS="$LIBS $($PKGCONFIG --libs pangocairo)" AC_CHECK_HEADERS([pango/pangocairo.h], [ AC_DEFINE([USE_PANGO]) AC_DEFINE([USE_XFT]) pango_found=yes ]) dnl Early abort if Pango could not be found AS_IF([test x$pango_found != xyes], [ AC_MSG_NOTICE([--enable-wayland: Pango libs and/or headers could not be found.]) AC_MSG_ERROR([Aborting.]) ]) dnl check for Xinerama, Xcursor, Xfixes, Xrender, Xregion.h AS_IF([test x$enable_x11 != xno], [ xinerama_found=no AS_IF([$PKGCONFIG --exists xinerama], [ AC_DEFINE(HAVE_XINERAMA) LIBS="$LIBS $($PKGCONFIG --libs xinerama)" xinerama_found=yes ]) xcursor_found=no AS_IF([$PKGCONFIG --exists xcursor], [ AC_DEFINE(HAVE_XCURSOR) LIBS="$LIBS $($PKGCONFIG --libs xcursor)" xcursor_found=yes ]) xfixes_found=no AS_IF([$PKGCONFIG --exists xfixes], [ AC_DEFINE(HAVE_XFIXES) LIBS="$LIBS $($PKGCONFIG --libs xfixes)" xfixes_found=yes ]) xrender_found=no AS_IF([$PKGCONFIG --exists xrender], [ AC_DEFINE(HAVE_XRENDER) LIBS="$LIBS $($PKGCONFIG --libs xrender)" xrender_found=yes ]) AC_CHECK_HEADER([X11/Xregion.h], [ AC_DEFINE([HAVE_X11_XREGION_H]) ], [], [#include ]) ]) ], [ dnl Check for X11... AC_PATH_XTRA AS_IF([test x$no_x = xyes], [ AC_MSG_ERROR([Configure could not find required X11 libraries, aborting.]) ]) AS_IF([test "x$X_PRE_LIBS" != x], [ AC_MSG_WARN([Ignoring libraries "$X_PRE_LIBS" requested by configure.]) ]) LIBS="$LIBS -lX11 $X_EXTRA_LIBS" CFLAGS="$CFLAGS $X_CFLAGS" CXXFLAGS="$CXXFLAGS $X_CFLAGS" AS_CASE([$host_os], [darwin*], [ DARWIN_LDFLAGS="$LDFLAGS" ]) LDFLAGS="$X_LIBS $LDFLAGS" DSOFLAGS="$X_LIBS $DSOFLAGS" AC_DEFINE([FLTK_USE_X11]) BUILD="X11" AS_IF([test "x$x_includes" != x], [ ac_cpp="$ac_cpp -I$x_includes" ]) dnl Check for OpenGL unless disabled... GLLIBS= AS_IF([test x$enable_gl != xno], [ AC_SEARCH_LIBS([dlopen], [dl]) AC_CHECK_HEADER([GL/gl.h], [ AC_CHECK_LIB([GL], [glXMakeCurrent], [ AC_DEFINE([HAVE_GL]) GLLIBS="-lGL" ], [ AC_CHECK_LIB([MesaGL], [glXMakeCurrent], [ AC_DEFINE([HAVE_GL]) GLLIBS="-lMesaGL" ],, [-lm]), ], [-lm]) AC_CHECK_LIB([GL], [glXGetProcAddressARB], [ AC_DEFINE([HAVE_GLXGETPROCADDRESSARB]) ],, [-lm]) ]) AC_CHECK_HEADER([GL/glu.h], [ AC_DEFINE([HAVE_GL_GLU_H]) AS_IF([test x$ac_cv_lib_GL_glXMakeCurrent = xyes], [ GLLIBS="-lGLU $GLLIBS" ]) AS_IF([test x$ac_cv_lib_MesaGL_glXMakeCurrent = xyes], [ GLLIBS="-lMesaGLU $GLLIBS" ]) ]) AS_IF([test x$ac_cv_lib_GL_glXMakeCurrent != xyes -a x$ac_cv_lib_MesaGL_glXMakeCurrent != xyes], [ LINKFLTKGL="" GLLIBNAME="" GLDSONAME="" GLDEMOS="" ]) ], [ LINKFLTKGL="" GLLIBNAME="" GLDSONAME="" GLDEMOS="" ]) xinerama_found=no AS_IF([test x$enable_xinerama != xno], [ AC_CHECK_LIB([Xinerama], [XineramaIsActive], [ AC_DEFINE([HAVE_XINERAMA]) LIBS="-lXinerama $LIBS" xinerama_found=yes ]) ]) dnl Check for the Xft library unless disabled... xft_found=no AS_IF([test x$enable_xft != xno -a x$enable_wayland = xno], [ # Try pkg-config first (freetype2 deprecated freetype-config from some version on) FT_FLAGS="" AS_IF([test "x$PKGCONFIG" != x], [ FT_FLAGS="$($PKGCONFIG --cflags xft)" AS_IF([test "x$FT_FLAGS" = x], [ FT_FLAGS="$($PKGCONFIG --cflags freetype2)" ]) ]) # if that failed, try freetype-config AS_IF([test "x$FT_FLAGS" = x], [ AC_PATH_PROG([FTCONFIG], [freetype-config]) AS_IF([test "x$FTCONFIG" != x], [ FT_FLAGS="$($FTCONFIG --cflags)" ], [ # abort if both methods failed AC_MSG_NOTICE([please install pkg-config or use 'configure --disable-xft'.]) AC_MSG_ERROR([Aborting.]) ]) ]) CPPFLAGS="$FT_FLAGS $CPPFLAGS" CXXFLAGS="$FT_FLAGS $CXXFLAGS" CFLAGS="$FT_FLAGS $CFLAGS" AC_CHECK_LIB([fontconfig], [FcPatternCreate]) AC_CHECK_HEADER([X11/Xft/Xft.h], [ AC_CHECK_LIB([Xft], [XftDrawCreate], [ AC_DEFINE([USE_XFT]) LIBS="-lXft $LIBS" BUILD="XFT" xft_found=yes ]) ]) ]) dnl Issue a warning message if Xft was not found, abort configure dnl if Xft was requested explicitly (but not found) AS_IF([test x$enable_xft != xno -a x$xft_found != xyes], [ AC_MSG_WARN([could not find the required Xft headers and/or libraries.]) AC_MSG_NOTICE([please install Xft headers and libraries or use 'configure --disable-xft'.]) AS_IF([test x$enable_xft = xyes], [ AC_MSG_ERROR([Aborting.]) ]) ]) dnl Option usecairo AS_IF([test x$enable_usecairo = xyes], [ enable_pango=yes BUILD="CAIRO" AC_DEFINE([FLTK_USE_CAIRO]) AC_MSG_NOTICE([Processing usecairo option]) ] ) dnl test if Pango is asked but xft was not found AS_IF([test x$enable_pango = xyes -a x$xft_found = xno], [ AC_MSG_WARN([could not find the Xft headers and/or libraries required for Pango.]) AC_MSG_NOTICE([please install Xft headers and libraries or don't use configure with '--enable-pango'.]) AC_MSG_ERROR([Aborting.]) ]) dnl Check for the Pango library unless disabled... pango_found=no AS_IF([test x$enable_pango = xyes], [ AS_IF([test x$PKGCONFIG != x], [ dnl pkg-config is available, use it... dnl AC_MSG_NOTICE([--enable-pango: using pkg-config ...]) CXXFLAGS="$($PKGCONFIG --cflags pangocairo) $CXXFLAGS" AS_CASE([$host_os], [darwin*], [], [*], [ CXXFLAGS="$($PKGCONFIG --cflags pangoxft) $CXXFLAGS" ]) AS_CASE([$host_os], [darwin*], [ DARWIN_SAVE_LIBS=$LIBS DARWIN_PANGO_LIBS="$($PKGCONFIG --libs pangocairo)" LIBS="$($PKGCONFIG --libs pangocairo) $LIBS" ], [*], [ LIBS="$($PKGCONFIG --libs pangocairo --libs pangoxft) $LIBS" ]) ], [ dnl pkg-config is not available, issue warning and continue... AC_MSG_WARN([--enable-pango: please install pkg-config. Continuing anyway.]) ]) CPPFLAGS="$CXXFLAGS" AS_CASE([$host_os], [darwin*], [AC_CHECK_HEADERS([pango/pango.h], [ AC_CHECK_LIB([pango-1.0], [pango_layout_new], [ AC_DEFINE([USE_PANGO]) pango_found=yes LIBS=$DARWIN_SAVE_LIBS ]) ]) ],[*], [ AC_CHECK_HEADERS([pango/pango.h pango/pangoxft.h], [ AC_CHECK_LIB([pango-1.0], [pango_layout_new], [ AC_CHECK_LIB([pangoxft-1.0], [pango_xft_render_layout], [ AC_DEFINE([USE_PANGO]) pango_found=yes ]) ]) ]) ]) dnl Early abort if --enable-pango was requested but Pango could not be found AS_IF([test x$pango_found != xyes], [ AC_MSG_NOTICE([--enable-pango: Pango libs and/or headers could not be found.]) AC_MSG_ERROR([Aborting.]) ]) ]) dnl Check for the Xfixes extension unless disabled... xfixes_found=no AS_IF([test x$enable_xfixes != xno], [ AC_CHECK_HEADER([X11/extensions/Xfixes.h], [ AC_CHECK_LIB([Xfixes], [XFixesQueryExtension], [ AC_DEFINE([HAVE_XFIXES]) LIBS="-lXfixes $LIBS" xfixes_found=yes ]) ], [], [#include ]) ]) dnl Check for the Xcursor library unless disabled... xcursor_found=no AS_IF([test x$enable_xcursor != xno], [ AC_CHECK_HEADER([X11/Xcursor/Xcursor.h], [ AC_CHECK_LIB([Xcursor], [XcursorImageCreate], [ AC_DEFINE([HAVE_XCURSOR]) LIBS="-lXcursor $LIBS" xcursor_found=yes ]) ], [], [#include ]) ]) dnl Check for the Xrender library unless disabled... xrender_found=no AS_IF([test x$enable_xrender != xno], [ AC_CHECK_HEADER([X11/extensions/Xrender.h], [ AC_CHECK_LIB([Xrender], [XRenderQueryVersion], [ AC_DEFINE([HAVE_XRENDER]) LIBS="-lXrender $LIBS" xrender_found=yes ]) ], [], [#include ]) ]) AS_CASE([$host_os], [darwin*], [ AS_IF([test x$pango_found = xyes], [ #place X_LIBS after homebrew's pango libs LIBS="$DARWIN_PANGO_LIBS $X_LIBS $LIBS" #remove X_LIBS from LDFLAGS while keeping its initial content LDFLAGS="$DARWIN_LDFLAGS" ]) ]) dnl Check for the X11/Xregion.h header file... AC_CHECK_HEADER([X11/Xregion.h], [ AC_DEFINE([HAVE_X11_XREGION_H]) ], [], [#include ]) ]) # Make symlinks since UNIX/Linux is case sensitive, # but Cygwin in general not. AS_CASE([$host_os], [cygwin*], [ HLINKS="#" ]) # Make symlinks since UNIX/Linux is case sensitive, # but only if explicitly configured (default=no) AS_IF([test "x$with_links" != xyes], [ HLINKS="#" ]) # Install/Uninstall FLUID application support files INSTALL_DESKTOP="install-linux" UNINSTALL_DESKTOP="uninstall-linux" ]) dnl End of platform specific Processing AC_SUBST([GLDEMOS]) AC_SUBST([GLLIBS]) AC_SUBST([HLINKS]) AC_SUBST([OSX_ONLY]) AC_SUBST([THREADS]) AC_SUBST([FLUIDDIR]) AC_SUBST([LIBDECORDIR]) AC_SUBST([LIBDECORDBUS]) AC_SUBST([INSTALL_DESKTOP]) AC_SUBST([UNINSTALL_DESKTOP]) AC_SUBST([BUILD]) dnl Figure out the appropriate formatted man page extension... AS_CASE(["$host_os"], [*bsd* | darwin*], [ # *BSD CAT1EXT=0 CAT3EXT=0 CAT6EXT=0 ], [irix*], [ # SGI IRIX CAT1EXT=z CAT3EXT=z CAT6EXT=z ], [*], [ # All others CAT1EXT=1 CAT3EXT=3 CAT6EXT=6 ]) AC_SUBST([CAT1EXT]) AC_SUBST([CAT3EXT]) AC_SUBST([CAT6EXT]) dnl Fix "mandir" variable... AS_IF([test "$mandir" = "\${prefix}/man" -a "$prefix" = "/usr"], [ AS_CASE(["$host_os"], [*bsd* | darwin* | linux*], [ # *BSD, Darwin, and Linux mandir="\${prefix}/share/man" ], [irix*], [ # SGI IRIX mandir="\${prefix}/share/catman" ]) ]) dnl Fix "libdir" variable... AS_IF([test "$prefix" = NONE], [ prefix=/usr/local ]) AS_IF([test "$exec_prefix" = NONE], [ exec_prefix="\${prefix}" ]) AS_CASE([$host_os], [irix[1-5]*], [ ], [irix*], [ AS_IF([test "$libdir" = "\${exec_prefix}/lib" -a "$exec_prefix" = "\${prefix}" -a "$prefix" = "/usr"], [ libdir="/usr/lib32" ]) ]) dnl Define the command used to update the dependencies (this option dnl mainly for FLTK core developers - not necessary for users) MAKEDEPEND="\$(CXX) -M" AC_SUBST([MAKEDEPEND]) dnl Add warnings to compiler switches: dnl do this last so messing with switches does not break tests AS_IF([test -n "$GCC"], [ # Show all standard warnings + unused variables, conversion errors, # and inlining problems when compiling... OPTIM="-Wall -Wunused -Wno-format-y2k $OPTIM" # The following additional warnings are useful for tracking down problems... #OPTIM="-Wshadow -Wconversion $OPTIM" # We know that Carbon is deprecated on OS X 10.4. To avoid hundreds of warnings # we will temporarily disable 'deprecated' warnings on OS X. AS_CASE([$host_os], [darwin[1-7]], [ ], [darwin*], [ OPTIM="-Wno-deprecated-declarations $OPTIM" ]) # Set the default compiler optimizations... AS_IF([test -z "$DEBUGFLAG"], [ # # Note: Can't use -fomit-frame-pointer - prevents tools like # libsafe from working! # # Don't use -fforce-mem, -fforce-addr, or -fcaller-saves. # They all seem to make either no difference or enlarge # the code by a few hundred bytes. # # "-Os" seems to be the best compromise between speed and # code size. "-O3" and higher seem to make no effective # difference in the speed of the code, but does bloat the # library 10+%. # AS_IF([test "x$with_optim" != x], [ OPTIM="$with_optim $OPTIM" ], [ OPTIM="-Os $OPTIM" ]) ]) # Generate position-independent code when needed... AS_IF([test $PICFLAG = 1], [ OPTIM="$OPTIM -fPIC" ]) # See if GCC supports -fno-exceptions... AC_MSG_CHECKING([if GCC supports -fno-exceptions]) OLDCFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-exceptions" AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[]], [[]])], [OPTIM="$OPTIM -fno-exceptions" AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)]) CFLAGS="$OLDCFLAGS" # See if GCC supports -fno-strict-aliasing... AC_MSG_CHECKING([if GCC supports -fno-strict-aliasing]) OLDCFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-strict-aliasing" AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[]], [[]])], [OPTIM="$OPTIM -fno-strict-aliasing" AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)]) CFLAGS="$OLDCFLAGS" dnl Make sure that shared libraries don't have undefined references # See if ld supports -no-undefined... AC_MSG_CHECKING([if ld supports -no-undefined]) OLDLDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -Wl,-no-undefined" AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[]])], [DSOFLAGS="$DSOFLAGS -Wl,-no-undefined" AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)]) LDFLAGS="$OLDLDFLAGS" # See if ld supports -Bsymbolic-functions... AC_MSG_CHECKING([if ld supports -Bsymbolic-functions]) OLDLDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -Wl,-Bsymbolic-functions" AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[]])], [DSOFLAGS="$DSOFLAGS -Wl,-Bsymbolic-functions" AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)]) LDFLAGS="$OLDLDFLAGS" # See if toolchain supports a sectioned build... AC_MSG_CHECKING([if toolchain supports sections]) OLDLDFLAGS="$LDFLAGS" OLDCFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS -Wl,-gc-sections" CFLAGS="$CFLAGS -ffunction-sections -fdata-sections" AC_LINK_IFELSE( [AC_LANG_PROGRAM([[]], [[]])], [DSOFLAGS="$DSOFLAGS -Wl,-gc-sections" OPTIM="$OPTIM -ffunction-sections -fdata-sections" AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)]) LDFLAGS="$OLDLDFLAGS" CFLAGS="$OLDCFLAGS" # See if we are running Solaris; if so, try the -fpermissive option... # This option is required on some versions of Solaris to work around # bugs in the X headers up through Solaris 7. # # Unlike the other compiler/optimization settings, this one is placed # in CFLAGS and CXXFLAGS so that fltk-config will provide the option # to clients - otherwise client apps will not compile properly... AS_CASE([$host_os], [solaris*], [ AC_MSG_CHECKING([if GCC supports -fpermissive]) OLDCFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fpermissive" AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[]], [[]])], [CXXFLAGS="$CXXFLAGS -fpermissive" AC_MSG_RESULT(yes)], [CFLAGS="$OLDCFLAGS" AC_MSG_RESULT(no)]) ]) ], [ AS_CASE(["$host_os"], [irix*], [ # Running some flavor of IRIX; see which version and # set things up according... AS_IF([test "$uversion" -ge 62], [ # We are running IRIX 6.2 or higher; uncomment the following # lines if you don't have IDO 7.2 or higher: # # CXX="CC -n32 -mips3" # CC="cc -n32 -mips3" # LD="ld -n32 -mips3" # MAKEDEPEND="CC -M" AS_IF([test "x`grep abi=n32 /etc/compiler.defaults`" = x], [ AC_MSG_WARN([FOR BEST RESULTS BEFORE COMPILING: setenv SGI_ABI "-n32 -mips3"]) ]) OPTIM="-fullwarn $OPTIM" ]) AS_IF([test -z "$DEBUGFLAG"], [ AS_IF([test "x$with_optim" != x], [ OPTIM="$with_optim $OPTIM" ], [ OPTIM="-O2 $OPTIM" AS_IF([test $uversion -gt 62], [ OPTIM="-OPT:Olimit=4000 $OPTIM" ]) ]) ]) ], [hpux*], [ # Running HP-UX; these options should work for the HP compilers. AS_IF([test -z "$DEBUGFLAG"], [ AS_IF([test "x$with_optim" != x], [ OPTIM="$with_optim $OPTIM" ], [ OPTIM="+O2 $OPTIM" ]) ]) AS_IF([test $PICFLAG = 1], [ OPTIM="+z $OPTIM" ]) CXXFLAGS="$CXXFLAGS +W336,501,736,740,749,829" ], [OSF1*], [ # Running Digital/Tru64 UNIX; these options should work for the # Digital/Compaq/NewHP compilers. AS_IF([test -z "$DEBUGFLAG"], [ AS_IF([test "x$with_optim" != x], [ OPTIM="$with_optim $OPTIM" ], [ OPTIM="-O2 $OPTIM" ]) ]) ], [solaris*], [ # Solaris AS_IF([test -z "$DEBUGFLAG"], [ AS_IF([test "x$with_optim" != x], [ OPTIM="$with_optim $OPTIM" ], [ OPTIM="-xO3 $OPTIM" ]) ]) AS_IF([test $PICFLAG = 1], [ OPTIM="-KPIC $OPTIM" ]) ], [aix*], [ AS_IF([test -z "$DEBUGFLAG"], [ AS_IF([test "x$with_optim" != x], [ OPTIM="$with_optim $OPTIM" ], [ OPTIM="-O2 $OPTIM" ]) ]) AC_MSG_WARN([The AIX C and C++ compilers are known not to correctly compile the FLTK library.]) ], [*], [ # Running some other operating system; inform the user they # should contribute the necessary options via the STR form.. AC_MSG_WARN([Building FLTK with default compiler optimizations]) AC_MSG_WARN([Send the FLTK developers your uname and compiler options via https://www.fltk.org/bugs.php]) ]) ]) OPTIM="$DEBUGFLAG $OPTIM" dnl Take archflags away from CFLAGS (makefiles use ARCHFLAGS explicitly) AS_CASE([$host_os], [darwin*], [ AS_IF([test "x$with_archflags" != x], [ CFLAGS="$(echo $CFLAGS | sed -e 's/$with_archflags//g')" ]) ]) dnl Define the FLTK documentation directory... AS_CASE([$host_os], [mingw*], [ # Determine the path where MSys has /usr installed msyspath="$(mount | grep '/usr ' | cut -d ' ' -f -1 | sed -e's,\\,/, g')" # Then substitute that in the Windows path instead of /usr AC_DEFINE_UNQUOTED([FLTK_DOCDIR], "$msyspath/local/share/doc/fltk") ], [*], [ AS_IF([test x$prefix = xNONE], [ AC_DEFINE_UNQUOTED([FLTK_DOCDIR], "/usr/local/share/doc/fltk") ], [ AC_DEFINE_UNQUOTED([FLTK_DOCDIR], "$prefix/share/doc/fltk") ]) ]) dnl Define the FLTK data directory... AS_IF([test x$prefix = xNONE], [ AC_DEFINE_UNQUOTED([FLTK_DATADIR], "/usr/local/share/fltk") ], [ AC_DEFINE_UNQUOTED([FLTK_DATADIR], "$prefix/share/fltk") ]) dnl Summarize results of configure tests... echo "" echo "Configuration Summary" echo "-------------------------------------------------------------------------" AS_CASE([$host_os_gui], [cygwin* | mingw*], [ AS_IF([test x$gdiplus_found = xyes], [graphics="GDI+"], [graphics="GDI"]) ], [darwin*], [ graphics="Quartz" ], [*], [ AS_IF([test x$enable_wayland = xno], [ graphics="X11" ]) AS_IF([test x$xft_found = xyes], [ graphics="$graphics + Xft" ]) AS_IF([test x$xfixes_found = xyes], [ graphics="$graphics + Xfixes" ]) AS_IF([test x$xinerama_found = xyes], [ graphics="$graphics + Xinerama" ]) AS_IF([test x$xcursor_found = xyes], [ graphics="$graphics + Xcursor" ]) AS_IF([test x$xrender_found = xyes], [ graphics="$graphics + Xrender" ]) AS_IF([test x$enable_usecairo = xyes], [ graphics="$graphics + Cairo" ]) AS_IF([test x$pango_found = xyes], [ graphics="$graphics + Pango" ]) ]) echo " Directories: prefix=$prefix" echo " bindir=$bindir" echo " datadir=$datadir" echo " datarootdir=$datarootdir" echo " exec_prefix=$exec_prefix" echo " includedir=$includedir" echo " libdir=$libdir" echo " mandir=$mandir" AS_CASE([$host_os], [mingw*], [ echo " MSys docpath=$msyspath/local/share/doc/fltk" ]) AS_IF([test x$enable_fluid != xno], [ echo " Build fluid: YES" ],[ echo " Build fluid: NO" ]) AS_IF([test x$enable_test != xno], [ echo " Build tests: YES" ],[ echo " Build tests: NO" ]) AS_IF([test "$fltk_cross_compiling" = "yes"], [ echo "Cross-compiling: YES" echo " Build: $build -> Host: $host" ], [ echo "Cross-compiling: NO" ]) echo " Graphics: $graphics" dnl AS_IF([test x$JPEG = x], [ echo "Image Libraries: JPEG=System" ], [ echo "Image Libraries: JPEG=Builtin" ]) AS_IF([test x$PNG = x], [ echo " PNG=System" ], [ echo " PNG=Builtin" ]) AS_IF([test x$ZLIB = x], [ echo " ZLIB=System" ], [ echo " ZLIB=Builtin" ]) AS_IF([test x$build_forms = xyes], [ echo "Forms library: YES" ], [ echo "Forms library: NO" ]) AS_IF([test x$enable_cairo = xyes], [ echo " CAIRO=lib" ]) AS_IF([test x$enable_cairoext = xyes], [ echo " CAIRO=internal_use" ]) AS_IF([test x$enable_largefile != xno], [ echo " Large Files: YES" ], [ echo " Large Files: NO" ]) AS_IF([test x$GLDEMOS = x], [ echo " OpenGL: NO" ], [ echo " OpenGL: YES" ]) AS_IF([test x$THREADS = x], [ echo " Threads: NO" ], [ echo " Threads: YES" ]) AS_IF([test x$enable_use_std != xyes], [ echo " Allow std:: : NO" ], [ echo " Allow std:: : YES" ]) dnl Set empty BINARY_DIR variable for fltk-config.in (CMake compatibility) BINARY_DIR= AC_SUBST([BINARY_DIR]) dnl Write all of the files... AC_CONFIG_HEADERS([config.h:configh.in]) AC_CONFIG_HEADERS([FL/fl_config.h:fl_config.in]) AC_CONFIG_FILES([makeinclude fltk.list fltk-config fltk.spec FL/Makefile]) AC_OUTPUT dnl Make sure the fltk-config script is executable... chmod +x fltk-config echo "" echo "-------------------------------------------------------------------------" echo " IMPORTANT NOTE:" echo "-------------------------------------------------------------------------" echo "" echo " FLTK 1.4.x will be the last version(s) of FLTK supporting" echo " autotools (configure + provided Makefiles) to build FLTK." echo " FLTK 1.5.0 and higher will only support FLTK builds using CMake." echo "" echo " We suggest to explore and use the CMake build system generators" echo " for your own FLTK builds as soon as possible. Some new FLTK build" echo " options will only be supported by CMake based builds." echo " Please see README.CMake.txt for details and instructions." echo "" echo " User projects that use CMake for their own build can benefit" echo " substantially if the FLTK library has been built using CMake." echo "" echo "-------------------------------------------------------------------------" echo "" fltk-1.4.3/fltk-config.in0000644000175000017500000002702315004135251015344 0ustar albrechtalbrecht#!/bin/sh # # FLTK configuration utility. # # Copyright 2000-2025 by Bill Spitzak and others. # Original version Copyright 2000 by James Dean Palmer # Adapted by Vincent Penne and Michael Sweet # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # # Variables and constants generated by CMake: # version numbers MAJOR_VERSION=@FLTK_VERSION_MAJOR@ MINOR_VERSION=@FLTK_VERSION_MINOR@ PATCH_VERSION=@FLTK_VERSION_PATCH@ VERSION="$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION" APIVERSION="$MAJOR_VERSION.$MINOR_VERSION" # compiler names CC="@CC@" CXX="@CXX@" # flags for C++ compiler: ARCHFLAGS="@ARCHFLAGS@" CFLAGS="@CFLAGS@ @LARGEFILE@ @PTHREAD_FLAGS@" CXXFLAGS="@CXXFLAGS@ @LARGEFILE@ @PTHREAD_FLAGS@" LDFLAGS="@LDFLAGS@" LDLIBS="@LIBS@" OPTIM="@OPTIM@" CAIROFLAGS="@CAIROFLAGS@" # BINARY_DIR: this is only set for CMake builds in the CMake build directory, # otherwise it is an empty string (for instance in the install directory) BINARY_DIR=@BINARY_DIR@ prefix="@prefix@" exec_prefix="@exec_prefix@" exec_prefix_set=no includedir="@includedir@" libdir="@libdir@" srcdir="@srcdir@" # BEGIN fltk-config code # Check for local invocation (in FLTK source folder), and update paths accordingly... selfdir=`dirname "$0"` if test -f "$selfdir/FL/Fl_Window.H"; then includedir="$selfdir" libdir="$selfdir/lib" fi # Libraries to link with (must be after 'prefix' stuff and after check for local invocation) LIBNAME="@LIBNAME@" DSONAME="@DSONAME@" DSOLINK="@DSOLINK@" IMAGELIBS="@IMAGELIBS@" STATICIMAGELIBS="@STATICIMAGELIBS@" SHAREDSUFFIX="@SHAREDSUFFIX@" CAIROLIBS="@CAIROLIBS@" GLLIBS="@GLLIBS@" # Check bundled image libraries in source tree if test -f "$libdir/libfltk_jpeg.a" -a -d $includedir/jpeg; then CFLAGS="-I$includedir/jpeg $CFLAGS" CXXFLAGS="-I$includedir/jpeg $CXXFLAGS" fi if test -f "$libdir/libfltk_z.a" -a -d $includedir/zlib; then CFLAGS="-I$includedir/zlib $CFLAGS" CXXFLAGS="-I$includedir/zlib $CXXFLAGS" fi if test -f "$libdir/libfltk_png.a" -a -d $includedir/png; then CFLAGS="-I$includedir/png $CFLAGS" CXXFLAGS="-I$includedir/png $CXXFLAGS" fi # Check bundled image libraries in installation folder. # Note: jpeg, png, and zlib headers are installed in FL/images if test -d "$includedir/FL/images"; then CFLAGS="-I$includedir/FL/images $CFLAGS" CXXFLAGS="-I$includedir/FL/images $CXXFLAGS" fi # Cairo support: *append* CAIROFLAGS if test -n "$CAIROFLAGS"; then CFLAGS="$CFLAGS $CAIROFLAGS" CXXFLAGS="$CXXFLAGS $CAIROFLAGS" fi usage () { echo "Usage: fltk-config [OPTIONS] Options: [--version] [--api-version] Options telling what we are doing: [--use-gl] use GL [--use-images] use extra image formats (PNG, JPEG) [--use-glut] use glut compatibility layer [--use-forms] use forms compatibility layer [--use-cairo] use cairo graphics lib Options telling what information we request: [--cc] return C compiler used to compile FLTK [--cxx] return C++ compiler used to compile FLTK [--optim] return compiler optimization used to compile FLTK [--cflags] return flags to compile C using FLTK [--cxxflags] return flags to compile C++ using FLTK [--ldflags] return flags to link against FLTK [--ldstaticflags] return flags to link against static FLTK library even if there are DSOs installed [--libs] return FLTK libraries full path for dependencies [--prefix] return FLTK install time --prefix directory [--includedir] return FLTK install time include directory Options to compile and link an application: [-g] compile the program with debugging information [-Dname[=value]] compile the program with the given define [--compile program.cxx ..] compile and link the program with optional .. compiler flags, source files, and libraries [--link flags and libs] additional linker flags and libraries .. for --compile, added after all other libs [--post program] prepare the program for desktop use (macOS) " exit $1 } if test $# -eq 0; then usage 1 fi # variables for parsing and generation of the commandline compile= post= debug= flags= files= use_link= link= # Parse command line options while test $# -gt 0 do case $1 in --version) echo $VERSION ;; --api-version) echo $APIVERSION ;; --cc) echo $CC ;; --cxx) echo $CXX ;; --optim) echo_optim=yes ;; --use-gl | --use-glut) use_gl=yes ;; --use-forms) use_forms=yes ;; --use-images) use_images=yes ;; --use-cairo) use_cairo=yes ;; --cflags) echo_cflags=yes ;; --cxxflags) echo_cxxflags=yes ;; --ldflags) echo_ldflags=yes ;; --ldstaticflags) echo_ldstaticflags=yes ;; --libs) echo_libs=yes ;; --prefix) echo_prefix=yes ;; --includedir) echo_includedir=yes ;; -g) debug=-g ;; -D*) CXXFLAGS="$CXXFLAGS $1" ;; --compile) compile="$2" shift ;; --post) post="$2" shift ;; --link) # linker flags and libs, allowed only after "--compile" if test -n "$compile"; then use_link=yes else echo_help=yes fi ;; -*) # additional compiler flags, allowed only after "--compile" if test -n "$compile"; then if test -n "$use_link"; then link="$link $1" # flags and libs after "--link" else flags="$flags $1" # compiler flags like "-I..." fi else echo_help=yes fi ;; *) # additional source files or libs, allowed only after "--compile" if test -n "$compile"; then if test -n "$use_link"; then link="$link $1" # linker flag or library else files="$files $1" # other (source) files fi else echo_help=yes fi ;; esac shift done if test "$includedir" != /usr/include; then includes="-I$includedir" else includes= fi # prepend build directory for fltk-config in CMake build folder if test -n "$BINARY_DIR"; then includes="-I$BINARY_DIR $includes" fi if test "$libdir" != /usr/lib -a "$libdir" != /usr/lib32; then libs="-L$libdir" else libs= fi # Calculate needed libraries LDSTATIC="$libdir/libfltk.a $LDLIBS" LDLIBS="-lfltk$SHAREDSUFFIX $LDLIBS" if test x$use_forms = xyes; then LDLIBS="-lfltk_forms$SHAREDSUFFIX $LDLIBS" LDSTATIC="$libdir/libfltk_forms.a $LDSTATIC" fi if test x$use_gl = xyes; then LDLIBS="-lfltk_gl$SHAREDSUFFIX $GLLIBS $LDLIBS" LDSTATIC="$libdir/libfltk_gl.a $GLLIBS $LDSTATIC" fi if test x$use_images = xyes; then LDLIBS="-lfltk_images$SHAREDSUFFIX $IMAGELIBS $LDLIBS" LDSTATIC="$libdir/libfltk_images.a $STATICIMAGELIBS $LDSTATIC" fi if test x$use_cairo = xyes -a -n "$CAIROLIBS"; then LDLIBS="$CAIROLIBS $LDLIBS" LDSTATIC="$CAIROLIBS $LDSTATIC" fi LDLIBS="$DSOLINK $LDFLAGS $libs $LDLIBS" LDSTATIC="$LDFLAGS $LDSTATIC" # Answer to user requests if test -n "$echo_help"; then usage 1 fi if test -n "$compile"; then case "$compile" in *.cxx) prog="`basename \"$compile\" .cxx`" ;; *.cpp) prog="`basename \"$compile\" .cpp`" ;; *.cc) prog="`basename \"$compile\" .cc`" ;; *.C) prog="`basename \"$compile\" .C`" ;; *) echo "ERROR: Unknown/bad C++ source file extension on \"$compile\"!" exit 1 ;; esac post="$prog" command="$CXX $ARCHFLAGS $includes $CXXFLAGS $debug -o $prog $flags $compile $files $LDSTATIC $link" echo $command $command || exit 1 fi if test -n "$post"; then running=`uname` if test "$running" = "Darwin"; then # if FLTK targets macOS + X11, apps need not be bundled if test `echo $LDLIBS | fgrep -c -e " -lX11"` = 1; then running="" fi fi case $running in Darwin) echo Creating "'$post.app'" bundle for desktop... id=`echo $post | tr ' ' '_'` # Make the bundle directory and move the executable there rm -rf "$post.app/Contents/MacOS" mkdir -p "$post.app/Contents/MacOS" mv "$post" "$post.app/Contents/MacOS" # Make a shell script that runs the bundled executable echo "#!/bin/sh" >"$post" echo 'dir="`dirname \"$0\"`"' >>"$post" echo 'exec "$dir/'"$post.app/Contents/MacOS/$post"'" "$@"' >>"$post" chmod +x "$post" # Make the simplest Info.plist needed for an application cat >"$post.app/Contents/Info.plist" < CFBundleInfoDictionaryVersion 6.0 CFBundleExecutable $post CFBundleIdentifier org.fltk.$id CFBundleName $post CFBundlePackageType APPL NSHighResolutionCapable EOF ;; esac fi if test "$echo_cflags" = "yes"; then echo $includes $CFLAGS fi if test "$echo_cxxflags" = "yes"; then echo $includes $CXXFLAGS fi if test "$echo_optim" = "yes"; then echo $OPTIM fi if test "$echo_ldflags" = "yes"; then my_libs= libdirs="$libs" for i in $LDLIBS ; do if test $i != "-L$libdir" ; then if test -z "$my_libs" ; then my_libs="$i" else my_libs="$my_libs $i" fi fi done echo $libdirs $my_libs fi if test "$echo_ldstaticflags" = "yes"; then echo $LDSTATIC fi if test "$echo_libs" = "yes"; then USELIBS="$libdir/libfltk.a" if test x$use_forms = xyes; then USELIBS="$libdir/libfltk_forms.a $USELIBS" fi if test x$use_gl = xyes; then USELIBS="$libdir/libfltk_gl.a $USELIBS" fi if test x$use_images = xyes; then USELIBS="$libdir/libfltk_images.a $USELIBS" for lib in fltk_jpeg fltk_png fltk_z; do if test -f "$libdir/lib$lib.a"; then USELIBS="$libdir/lib$lib.a $USELIBS" fi done fi echo $USELIBS fi if test "$echo_prefix" = "yes"; then echo $prefix fi if test "$echo_includedir" = "yes"; then echo $includedir fi fltk-1.4.3/README.IDE.txt0000644000175000017500000000352215004135251014705 0ustar albrechtalbrecht----------------------------------------- HOW TO BUILD AND USE FLTK WITH AN IDE ----------------------------------------- Since FLTK 1.4 we do no longer include IDE [1] solution files in our source distribution. If you want to build the FLTK library with an IDE you need to use CMake [2] to generate the IDE files from the source distribution. The FLTK team will officially support generation of selected IDE projects, particularly Visual C++ and Xcode. Older version support of these IDE projects will be limited to the versions that are supported by and can be generated with CMake. Other IDE solutions generated with CMake may or may not work. The FLTK team will try to support as many IDE solutions as possible, but we may need help to adjust the CMake files to fit a particular IDE project. Using CMake to generate IDE project files ------------------------------------------------------------------------ IDE files can easily be created using CMake and the provided CMake files. For more informations about using CMake to build FLTK please read the file README.CMake.txt in the root directory of the FLTK distribution. Current Status as of Nov 2016: ------------------------------------- Xcode: Supported Known to work. Visual C++: Supported Visual C++ 2015 generator known to work. Other IDE's: Not supported Status unknown. Note: "Not supported" doesn't mean that a particular generator does not work, but the FLTK team does not put much effort into making this IDE work, hence it may work for you or not. Contributions welcome. -------------------------------------------------------------------------------- [1] IDE = Integrated Development Environment, for instance Visual Studio, Xcode, Eclipse, ... https://en.wikipedia.org/wiki/Integrated_development_environment [2] https://cmake.org/ fltk-1.4.3/README.CMake.txt0000644000175000017500000012221515004135251015265 0ustar albrechtalbrechtREADME.CMake.txt - Building and using FLTK with CMake ------------------------------------------------------ CONTENTS ========== 1 Introduction to CMake 2 Using CMake to Build FLTK 2.1 Prerequisites 2.2 Options 2.2.1 CMake Specific Configuration Options 2.2.2 FLTK Specific Configuration Options 2.2.3 Documentation Options 2.2.4 Special Options 2.2.5 Other CMake Cache Variables 2.3 Building FLTK with CMake (all Platforms) 2.4 Building under Linux with Unix Makefiles 2.5 Building under Windows with Visual Studio and/or NMake 2.5.1 Building under Windows with Visual Studio 2.5.2 Building under Windows with NMake 2.6 Building under Windows with MinGW using Makefiles 2.7 Building under Windows WSL with Clang using Makefiles 2.8 Building under macOS with Xcode 2.9 Crosscompiling 3 Using CMake with FLTK 3.1 Library Names 3.2 Library Aliases 3.3 Exported and Imported Targets 3.4 Building a Simple "Hello World" Program with FLTK 3.5 Building a Program Using Fluid Files 3.6 Building a Program Using CMake's FetchContent Module 4 FindFLTK.cmake and find_package(FLTK) 1. Introduction to CMake =========================== CMake was designed to let you create build files for a project once and then compile the project on multiple platforms. Using it on any platform consists of the same steps. Create the CMakeLists.txt build file(s). Run one of the CMake executables, picking your source directory, build directory, and build target. The "cmake" executable is a one-step process with everything specified on the command line. The others let you select options interactively, then configure and generate your platform-specific target. You then run the resulting Makefile / project file / solution file as you normally would. CMake can be run in up to three ways, depending on your platform. "cmake" is the basic command line tool. "ccmake" is the curses based interactive tool. "cmake-gui" is the gui-based interactive tool. Each of these will take command line options in the form of -DOPTION=VALUE. ccmake and cmake-gui will also let you change options interactively. CMake not only supports, but works best with out-of-tree builds. This means that your build directory is not the same as your source directory or with a complex project, not the same as your source root directory. Note that the build directory is where, in this case, FLTK will be built, not its final installation point. If you want to build for multiple targets, such as VC++ and MinGW on Windows, or do some cross-compiling you must use out-of-tree builds exclusively. In-tree builds will gum up the works by putting a CMakeCache.txt file in the source root. More information on CMake can be found on its web site https://www.cmake.org. 2. Using CMake to Build FLTK =============================== 2.1 Prerequisites -------------------- The prerequisites for building FLTK with CMake are staightforward: CMake 3.15 or later and a recent FLTK release, snapshot, or Git download (working copy). Installation of CMake is covered on its web site. This howto will cover building FLTK with the default options using CMake under Linux and MinGW with Unix Makefiles. Chapter 2.5 shows how to use a MinGW cross compiling toolchain to build a FLTK library for Windows under Linux. Other platforms are just as easy to use. 2.2 Options -------------- Options can be specified to CMake with the -D flag: cmake -D = Example: cmake -D CMAKE_BUILD_TYPE=Debug Notes: the space between '-D' and the option name can be omitted. Option values must be quoted if they contain spaces. Other CMake tools are `ccmake` and `cmake-gui` but these are not described here. All options have sensible defaults so you won't usually need to specify them explicitly. 2.2.1 CMake Specific Configuration Options --------------------------------------------- There are only three CMake options that you may want to specify: CMAKE_BUILD_TYPE This specifies what kind of build this is i.e. Release, Debug... Platform specific compile/link flags/options are automatically selected by CMake depending on this value. CMAKE_INSTALL_PREFIX Where everything will go on install. Defaults are /usr/local for Unix and C:\Program Files\FLTK for Windows. CMAKE_OSX_ARCHITECTURES (macOS only, ignored on other platforms) Set this to either "arm64", "x86_64", or a list of both "arm64;x86_64". The latter will build "universal apps" on macOS, whereas the former will either build Intel (x86_64) or Apple Silicon aka M1 (arm64) apps. The default is to build for the host processor architecture. Note: the CMake variable BUILD_SHARED_LIBS is ignored by FLTK. FLTK builds static libs by default and can optionally build shared libs as well. Please see FLTK_BUILD_SHARED_LIBS instead. 2.2.2 FLTK Specific Configuration Options -------------------------------------------- Following are the FLTK specific options. Platform specific options are ignored on other platforms. For convenience the list of options is ordered alphabetically except "Documentation Options" and "Special Options" that follow in their own sections below. FLTK_ABI_VERSION - default EMPTY Use a numeric value corresponding to the FLTK ABI version you want to build in the form 1xxyy for FLTK 1.x.y (xx and yy with leading zeroes). The default ABI version is 1xx00 (the stable ABI throughout all patch releases of one minor FLTK version). The highest ABI version you may choose is 1xxyy for FLTK 1.x.y (again with leading zeroes). Please see README.abi-version.txt for more information about which ABI version to select. FLTK_ARCHFLAGS - default EMPTY Extra "architecture" flags used as C and C++ compiler flags. These flags are also "exported" to fltk-config. FLTK_BACKEND_WAYLAND - default ON (only Unix/Linux) Enable the Wayland backend for all window operations, Cairo for all graphics and Pango for text drawing (Linux+FreeBSD only). Resulting FLTK apps use Wayland when a Wayland compositor is available at runtime, and use X11 for their window operations otherwise (unless FLTK_BACKEND_X11 is OFF), but keep using Cairo and Pango - see README.Wayland.txt. If FLTK_BACKEND_X11 has been turned OFF and there is no Wayland compositor at runtime, then FLTK programs fail to start. FLTK_BACKEND_X11 - default ON on Unix/Linux, OFF elsewhere (Windows, macOS). Enable or disable the X11 backend on platforms that support it. - Unix/Linux: enable or disable the X11 backend when building with Wayland (FLTK_BACKEND_WAYLAND), otherwise this option must be ON. - macOS: enable the X11 backend instead of standard system graphics. This requires XQuartz or a similar X11 installation. This option is tested only with XQuartz by the FLTK team. Use this only if you know what you do and if you have installed X11. - Windows/Cygwin: enable X11 backend for Cygwin platforms. This option is currently (as of FLTK 1.4.0) not supported on Windows. Note: On platforms that support Wayland you may set FLTK_BACKEND_WAYLAND=ON (this is the default) and FLTK_BACKEND_X11=OFF to build a Wayland-only library or vice versa for an X11-only library. FLTK_BUILD_EXAMPLES - default OFF Build the example programs in the 'examples' directory. FLTK_BUILD_FLTK_OPTIONS - default ON Build the FLTK options editor ("fltk-options"). FLTK_BUILD_FLUID - default ON Build the Fast Light User-Interface Designer ("fluid"). FLTK_BUILD_FORMS - default ON Build the (X)Forms compatibility library. This option is ON by default for backwards compatibility but can safely be turned OFF if you don't need (X)Forms compatibility. FLTK_BUILD_GL - default ON Build the OpenGL support library fltk_gl (fltk::gl) and enable OpenGL support in user programs using fltk_gl. FLTK_BUILD_SHARED_LIBS - default OFF Normally FLTK is built as static libraries which makes more portable binaries. If you want to use shared libraries, this will build them too. You can use shared FLTK libs in your own CMake projects by appending "-shared" to FLTK target names as described in section 3.1 and 3.2. FLTK_BUILD_TEST - default ON in top-level build, OFF in sub-build Build the test and demo programs in the 'test' directory. The default is ON if the FLTK build is in a top-level project so all test and demo programs are built. If FLTK is built as a subproject only the Library and the tools (fluid and fltk-config) are built by default. FLTK_GRAPHICS_CAIRO - default OFF (Unix/Linux: X11 + Wayland only). Make all drawing operations use the Cairo library (rather than Xlib), producing antialiased graphics (X11 platform: implies FLTK_USE_PANGO). When using Wayland this option is ignored (Wayland uses Cairo). FLTK_GRAPHICS_GDIPLUS - default ON (Windows only). Make FLTK use GDI+ to draw oblique lines and curves resulting in antialiased graphics. If this option is OFF standard GDI is used. FLTK_MSVC_RUNTIME_DLL - default ON (Windows: Visual Studio, NMake, clang). Select whether the build uses the MS runtime DLL (ON) or not (OFF). Default is ON: either /MD or /MDd for Release or Debug, respectively. Select OFF for either /MT or /MTd for Release or Debug, respectively. If this variable is defined on other platforms it is silently ignored. FLTK_OPTION_CAIRO_EXT - default OFF Enable extended libcairo support - see README.Cairo.txt. FLTK_OPTION_CAIRO_WINDOW - default OFF Enable support of class Fl_Cairo_Window (all platforms, requires the Cairo library) - see README.Cairo.txt. FLTK_OPTION_FILESYSTEM_SUPPORT - default ON FLTK_OPTION_LARGE_FILE - default ON Enables large file (>2G) support. FLTK_OPTION_OPTIM - default EMPTY Extra optimization flags for the C and C++ compilers, for instance "-Wall -Wno-deprecated-declarations". Example: cmake -D FLTK_BUILD_EXAMPLES=on -D FLTK_OPTION_OPTIM="-Wall -Wextra -pedantic" .. FLTK_OPTION_PRINT_SUPPORT - default ON When turned off, the Fl_Printer class does nothing and the Fl_PostScript_File_Device class cannot be used, but the FLTK library is somewhat smaller. This option makes sense only on the Unix/Linux platform or on macOS when FLTK_BACKEND_X11 is ON. FLTK_OPTION_STD - default OFF This option allows FLTK to use some specific features of modern C++ like std::string in the public API of FLTK 1.4.x. Users turning this option ON can benefit from some new functions and methods that return std::string or use std::string as input parameters. Note: This option will be removed in the next minor (1.5.0) or major release which will use std::string and other modern C++ features. FLTK_OPTION_SVG - default ON FLTK has a built-in SVG library and can create (write) SVG image files. Turning this option off disables SVG (read and write) support. FLTK_USE_LIBDECOR_GTK - default ON (Wayland only). Meaningful only under Wayland and if FLTK_USE_SYSTEM_LIBDECOR is 'OFF'. Allows to use libdecor's GTK plugin to draw window titlebars. Otherwise FLTK does not use GTK and apps will not need linking to GTK. FLTK_USE_PANGO - default OFF (see note below) This option is highly recommended under X11 if FLTK is expected to draw text that does not use the latin alphabet. Enables use of the Pango library for drawing text. Pango supports all unicode-defined scripts and gives FLTK limited support of right-to-left scripts. This option makes sense only under X11 or Wayland, and also requires Xft. This option is ignored (always enabled) if Wayland or FLTK_GRAPHICS_CAIRO is ON. FLTK_USE_POLL - default OFF Deprecated: don't turn this option ON. FLTK_USE_PTHREADS - default ON except on Windows. Enables multithreaded support with pthreads if available. This option is ignored (switched OFF internally) on Windows except when using Cygwin. FLTK_USE_SYSTEM_LIBDECOR - default ON (Wayland only) This option makes FLTK use package libdecor-0-dev to draw window titlebars under Wayland. When OFF or when this package has a version < 0.2.0, FLTK uses its bundled copy of libdecor to draw window titlebars. FLTK_USE_SYSTEM_LIBJPEG - default ON (macOS and Windows: OFF) FLTK_USE_SYSTEM_LIBPNG - default ON (macOS and Windows: OFF) FLTK_USE_SYSTEM_ZLIB - default ON (macOS and Windows: OFF) FLTK has built in jpeg, zlib, and png libraries. These options let you use system libraries instead, unless CMake can't find them. If you set any of these options to OFF, then the built in library will be used. The default is ON on Linux/Unix platforms but OFF on Windows and macOS because of potential incompatibilities on Windows and macOS whereas the system libraries can typically be used on Linux/Unix. Note: if any one of libpng or zlib is not found on the system, both libraries are built using the bundled ones and a warning is issued. FLTK_USE_XCURSOR - default ON FLTK_USE_XFIXES - default ON FLTK_USE_XFT - default ON FLTK_USE_XINERAMA - default ON FLTK_USE_XRENDER - default ON These are X11 extended libraries. These libs are used if found on the build system unless the respective option is turned off. 2.2.3 Documentation Options ------------------------------ These options are only available if `doxygen' is installed and found. PDF related options require also `latex'. FLTK_BUILD_HTML_DOCS - default ON FLTK_BUILD_PDF_DOCS - default ON These options can be used to enable HTML documentation generation with doxygen. If these are ON the build targets 'html', 'pdf', and 'docs' are generated but must be built explicitly. Technically the build targets are generated but excluded from 'ALL'. You can safely leave these two options ON if you want to save build time because the docs are not built automatically. FLTK_BUILD_FLUID_DOCS - default OFF If this option is ON, the FLUID user documentation will be built. If FLTK_BUILD_PDF_DOCS is ON, the FLUID documentation will be generated in PDF form. To generate the screen shots used in the handbook, the CMake build mode must be set to "Debug". FLTK_INCLUDE_DRIVER_DOCS - default OFF This option adds driver documentation to HTML and PDF docs (if ON). This option is marked as "advanced" since it is only useful for FLTK developers and advanced users. It is only used if at least one of the documentation options above is ON as well. FLTK_INSTALL_HTML_DOCS - default OFF FLTK_INSTALL_FLUID_DOCS - default OFF FLTK_INSTALL_PDF_DOCS - default OFF If these options are ON then the HTML, FLUID, and/or PDF docs are installed when the 'install' target is executed, e.g. with `make install'. You need to select above options FLTK_BUILD_*_DOCS as well. 2.2.4 Special Options ------------------------ FLTK_INSTALL_LINKS - default OFF Deprecated: install "compatibility" links to compensate for typos in include statements (for case sensitive file systems only). You should not use this option, please fix the sources instead for better cross-platform compatibility. 2.2.5 Other CMake Cache Variables ------------------------------------ The following CMake cache variables can be used to view their computed values in the CMake cache or to change the build behavior in special cases. To view the variables - use `cmake -LA` or - use `cmake-gui` (switch 'Advanced' view ON) or - use `ccmake` (hit 't' to "Toggle advanced mode") - search the CMake cache 'CMakeCache.txt' with your favorite tool. Use either the `cmake` commandline, `cmake-gui`, or `ccmake` to change these variables if needed. CMake cache variables can also be preset using a toolchain file (see below) and on the commandline. FLTK_FLUID_EXECUTABLE - default = fltk::fluid (see exceptions below) This represents the `fluid` executable or CMake target that is used to "compile" fluid `.fl` files to source (.cxx) and header (.h) files. The default `fltk::fluid` is used when `fluid` is built and not cross-compiled, i.e. the fluid executable that is built can be used. On Windows and macOS `fltk::fluid-cmd` (the console program) is used instead. When cross-compiling this variable should be a compatible `fluid` executable on the build host. For details see chapter 2.9. FLTK_FLUID_HOST - default = fluid executable on the build host This variable is used if `fluid` is not built (FLTK_BUILD_FLUID=OFF) or if cross-compiling. It can be preset by the CMake commandline to point the build at a compatible `fluid` executable. FLUID_PATH - obsolete (FLTK 1.3.x): predecessor of FLTK_FLUID_HOST This variable can safely be deleted from the CMake cache if it exists. 2.3 Building FLTK with CMake (all Platforms) ----------------------------------------------- CMake is used to generate a build system that will subsequently be used to build and install the FLTK library and test and demo applications. Note that "installing" FLTK is optional: you can skip this step if you like to build your own applications directly from the FLTK build tree. This has advantages if you are building FLTK with different options or are developing FLTK (changing sources) or if you pull new FLTK versions from git frequently. The following generic commands may need some changes on Windows where you may not have an adequate (POSIX) shell (command window). (1) Generate the build system in the FLTK root directory: cmake -B build [ -G "Generator" -D "Options" … ] This command creates the 'build' subdirectory if it does not exist yet and generates the build (project) files in the 'build' directory. See above for usable options. Note: Although this 'build' directory is part of the source tree it is considered an out-of-source build because CMake does not create any files in source directories. You can also use CMake to build FLTK in an arbitrary build folder elsewhere on the system: cmake -B /path/to/my-fltk-build [ -G "Generator" -D "Options" … ] Commandline elements in […] are optional. Use `cmake --help` to find out which generators are available on your platform. The default generator is marked with '*'. (2) Build FLTK with the generated build system: No matter which generator you selected in (1), the following CMake command can always be used to build the library: cmake --build build This uses the previously generated build system in the 'build' folder. This works even with Visual Studio where the build will be executed without opening the Visual Studio GUI, similar to NMake. Instead of using the above command you can also `cd build` and run the native build command, for instance `make -j7` or `ninja`, or you can open the IDE project (Xcode, Visual Studio, ...). (3) Install FLTK (optional): cmake --install build This command installs the previously built library and headers in the installation folder. On Unix/Linux/macOS systems this requires root privileges if the target is a system directory. The following chapters describe some special cases in more detail. Skip chapters you don't need... 2.4 Building under Linux with Unix Makefiles ----------------------------------------------- After unpacking the FLTK source, go to the root of the FLTK tree and type the following. cmake -B build -G "Unix Makefiles" [options] cd build make [ -j 3 ] sudo make install (optional) This will build and optionally install a default configuration FLTK. Some flags can be changed during the 'make' command, such as: make VERBOSE=on which builds in verbose mode, so you can see all the compile/link commands. Hint: if you intend to build several different versions of FLTK, e.g. a Debug and a Release version, or multiple libraries with different ABI versions or options, then use subdirectories in the build directory, like this: mkdir build cd build mkdir debug cd debug cmake -D 'CMAKE_BUILD_TYPE=Debug' ../.. make sudo make install (optional) 2.5 Building under Windows with Visual Studio and/or NMake ------------------------------------------------------------- Building with CMake under Visual Studio may require to specify the CMake generator with the -G"Visual Studio ..." command line switch, or the generator can be selected interactively in the GUI (cmake-gui). If you are not sure which one to select use `cmake --help` which lists all generators known to CMake on your system. 2.5.1 Building under Windows with Visual Studio ------------------------------------------------- CMake often finds an installed Visual Studio generator and uses it w/o using the commandline switch, particularly if you are using a special "Visual Studio Command Prompt": - Hit the "Windows" key - Type "developer command ..." ... until you see something like "Developer Command Prompt for VS xxxx" (replace 'xxxx' with your installed Visual Studio version) - Activate the "app" to execute the command prompt (like an old "DOS" shell) - Inside this command prompt window, run your installed `cmake` (command line) or `cmake-gui` (GUI) program. You may need to specify the full path to this program. If you use `cmake-gui` you can select the source and the build folders in the GUI, otherwise change directory to where you downloaded and installed the FLTK sources and execute: `cmake` -G "Visual Studio xxx..." -B build cd build This creates the Visual Studio project files (FLTK.sln and more) in the 'build' directory. Open Visual Studio, choose File -> Open -> Project, and pick the "FLTK.sln" created in the previous step. (Or, if only one version of the Visual Studio compiler is installed, you can just run from DOS: .\FLTK.sln) Make sure the pulldown menu has either "Release" or "Debug" selected in the "Solution Configurations" pulldown menu. In the "Solution Explorer", right click on: Solution 'FLTK' (## projects) ... and in the popup menu, choose "Build Solution" or choose 'Build/Build Solution' or 'Build/Rebuild Solution' from the menu at the top of the window. That's it, that should build FLTK. The test programs (*.exe) can be found relative to the 'build' folder in build\bin\test\Release\*.exe build\bin\test\Debug\*.exe ... and the FLTK include files (*.H & *.h) your own apps can compile with can be found in: build\FL *and* [1] in the source folder where you downloaded FLTK, e.g. in C:\fltk-1.4.x\FL ... and the FLTK library files (*.lib) which your own apps can link with can be found in: Release: build\lib\Release\*.lib Debug: build\lib\Debug\*.lib [1] If you want to build your own FLTK application directly using the build directories (i.e. without "installation") you need to include both the build tree (first) and then the FLTK source tree in the compiler's header search list. 2.5.2 Building under Windows with NMake ----------------------------------------- This example uses cmake to generate + build FLTK in Release mode using nmake, using purely the command line (never need to open the Visual Studio IDE) using the static Multithreaded runtime (/MT): mkdir build-nmake cd build-nmake cmake -G "NMake Makefiles" -D CMAKE_BUILD_TYPE=Release -D FLTK_MSVC_RUNTIME_DLL=off .. nmake which results in a colorful percentage output crawl similar to what we see with unix 'make'. Instead of running `nmake` directly you can also use cmake to build: cmake --build . 2.6 Building under Windows with MinGW using Makefiles -------------------------------------------------------- Building with CMake under MinGW requires you to specify the CMake Generator with the -G command line switch. Using cmake -G "Unix Makefiles" /path/to/fltk is recommended by the FLTK team if you have installed MinGW with the MSYS environment. You can use the stock Windows CMake executables, but you must run the CMake executables from within the MinGW environment so CMake can use your MinGW PATH to find the compilers and build tools. Example: alias cmake='/c/CMake/bin/cmake' alias cmake-gui='/c/CMake/bin/cmake-gui' mkdir build cd build cmake -G "Unix Makefiles" -D 'CMAKE_BUILD_TYPE=Debug' .. Note the path to FLTK ".." in the last command line. Depending on where you installed CMake you may need to adjust the path's in the alias commands. 2.7 Building under Windows WSL with Clang and Makefiles ---------------------------------------------------------- WSL, the Windows Subsystem for Linux allows developers to run a Linux environment without the need for a separate virtual machine or dual booting. WSL 2 runs inside a managed virtual machine that implements the full Linux kernel. WSL requires Windows 11. FLTK apps generated using WSL are Linux compatible binaries. To run those binaries on Windows, WSL comes with a limited built-in X11 server. Third party X11 servers can be installed that better support all features of FLTK. 1) Install WSL from PowerShell with admin privileges: > wsl --install 2) Reboot and open the Linux terminal. You will need to install the following Linux packages to compile FLTK > sudo apt update > sudo apt install clang cmake freeglut3-dev 3) Change to the directory containing the FLTK project. For example: > cd ~/dev/fltk-1.4.x 4) Use CMake to configure the build system > cmake -B build 5) Use CMake to build the demo app and all dependencies > cmake --build build 6) Run the demo app > ./build/bin/test/demo 2.8 Building under macOS with Xcode ------------------------------------- Building with CMake under Xcode requires the CMake generator with the -G command line switch. This step need to be done only once. If any of the CMake related files are updated, Xcode will rerun CMake for you. 1) Open the macOS Terminal 2) Change to the directory containing the FLTK project. For example: > cd ~/dev/fltk-1.4.x 3) Create a build directory > mkdir build > cd build 4) If you plan different build versions, it is useful to create another subdirectory level > mkdir Xcode > cd Xcode 5) Let CMake create the required IDE files > cmake -G Xcode ../.. This step should end in the message: -- Build files have been written to: .../dev/fltk-1.4.x/build/Xcode 5a) To build the Release version of FLTK, use > cmake -G Xcode -D CMAKE_BUILD_TYPE=Release ../.. 6) Launch Xcode from the Finder or from the Terminal: > open ./FLTK.xcodeproj When Xcode starts, it asks if it should "Autocreate Schemes". Click on "Automatically Create Schemes" to confirm. 7) To build and test FLTK, select the scheme "ALL_BUILD" and hit Cmd-B to build. Then select the scheme "demo" and hit Cmd-R to run the FLTK Demo. 8) The interactive user interface tool "Fluid" will be located in build/Xcode/bin/Debug. The example apps are in .../bin/examples/Debug. Static libraries are in .../lib/Debug/. Replace 'Debug' with 'Release' for a Release build. 9) The "install" Scheme may fail because it is run with user permissions. You may want to configure the build to install in a folder below your home directory. 2.9 Crosscompiling --------------------- Once you have a crosscompiler going, to use CMake to build FLTK you need two more things. You need a toolchain file which tells CMake where your build tools are. The CMake website is a good source of information on this file. Here's one for MinGW (64-bit) under Linux. ---- # CMake Toolchain File for MinGW-w64 (64-bit) Cross Compilation # the name of the target operating system set(CMAKE_SYSTEM_NAME Windows) # which tools to use set(CMAKE_C_COMPILER /usr/bin/x86_64-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-g++) set(CMAKE_RC_COMPILER /usr/bin/x86_64-w64-mingw32-windres) # here is where the target environment located set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) # adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search headers and libraries in the target environment set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_INSTALL_PREFIX ${CMAKE_FIND_ROOT_PATH}/usr CACHE FILEPATH "install path prefix") # initialize required linker flags to build compatible Windows programs set(CMAKE_EXE_LINKER_FLAGS_INIT "-static-libgcc -static-libstdc++") # end of toolchain file ---- Not too tough. The other thing you need is a native installation of FLTK on your build platform. This is to supply the fluid executable which will compile the *.fl into C++ source and header files. This is only needed if the test/* and/or example/* demo programs are built. CMake finds the fluid executable on the build host automatically when cross-compiling if it exists and is in the user's PATH. On systems that provide multiple fluid versions (e.g. 1.3.x and 1.4.x) or if only an older version is installed (e.g. 1.3.x) you can set the variable `FLTK_FLUID_HOST` on the cmake commandline like cmake -B mingw -S . [ -G "Ninja" ] \ -D CMAKE_BUILD_TYPE=Debug \ -D CMAKE_TOOLCHAIN_FILE= \ -D FLTK_FLUID_HOST=/path/to/fluid [.. more parameters ..] Note: replace '-G "Ninja" ' with the build tool of your choice or omit this argument to use the default generator of your platform. Theoretically the variable FLTK_FLUID_HOST can also be set in a toolchain file. This has been tested successfully but is not recommended because the toolchain file should be independent of the project using it. After generating the build system (above), build and optionally install the library: cmake --build mingw [sudo] cmake --install mingw # optional This will create a default configuration FLTK suitable for mingw/msys and install it in the /usr/x86_64-w64-mingw32/usr tree. Note: replace 'x86_64-w64-mingw32' with your cross toolchain location as required. 3. Using CMake with FLTK =========================== The CMake Export/Import facility can be thought of as an automated fltk-config. For example, if you link your program to the FLTK library, it will automatically link in all of its dependencies. This includes any special flags, i.e. on Linux it includes the -lpthread flag. This howto assumes that you have FLTK libraries which were built using CMake, installed. Building them with CMake generates some CMake helper files which are installed in standard locations, making FLTK easy to find and use. If FLTK is not installed in a standard system location where it is found automatically, you may need to set a CMake variable to point CMake to the right location. In the following examples we set the CMake cache variable 'FLTK_DIR' so CMake knows where to find the FLTK configuration file 'FLTKConfig.cmake'. It is important (recommended practice) to set this as a CMake cache variable which enables the user executing 'cmake' to override this path either on the commandline or interactively using the CMake GUI 'cmake-gui' or 'ccmake' on Unix/Linux, for instance like this: $ cd my-project $ mkdir build $ cd build $ cmake -G "Unix Makefiles" -S.. -D "FLTK_DIR=/home/me/fltk" 3.1 Library Names -------------------- When you use the target_link_libraries() command, CMake uses its own internal "target names" for libraries. The original fltk library names in the build tree are: fltk fltk_forms fltk_images fltk_gl The bundled image and zlib libraries (if built): fltk_jpeg fltk_png fltk_z Append suffix "-shared" for shared libraries (Windows: DLL's). These library names are used to construct the filename on disk with system specific prefixes and postfixes. For instance, on Linux/Unix 'fltk' is libfltk.a and the shared library (fltk-shared) is libfltk.so.1.4.0 (in FLTK 1.4.0) with additional system specific links. Note: since FLTK 1.4.0 the library fltk_cairo is no longer necessary and should be removed from CMake files of user projects. fltk_cairo is now an empty library solely for backwards compatibility and will be removed in the future. 3.2 Library Aliases ---------------------- Since FLTK 1.4.0 "aliases" for all libraries in the FLTK build tree are created in the namespace "fltk::". These aliases should always be used by consumer projects (projects that use FLTK) for several reasons which are beyond the scope of this README file. The following table shows the FLTK libraries and their aliases in the FLTK build tree. Library Name Alias Shared Library Alias Notes -------------------------------------------------------------- fltk fltk::fltk fltk::fltk-shared [1] fltk_forms fltk::forms fltk::forms-shared [2] fltk_gl fltk::gl fltk::gl-shared [2] fltk_images fltk::images fltk::images-shared [2] fltk_jpeg fltk::jpeg fltk::jpeg-shared [3] fltk_png fltk::png fltk::png-shared [3] fltk_z fltk::z fltk::z-shared [3] [1] The basic FLTK library. Use this if you don't need any of the other libraries for your application. [2] Use one or more of these libraries if you have specific needs, e.g. if you need to read images (fltk::images), OpenGL (fltk::gl), or (X)Forms compatibility (fltk::forms). If you use one of these libraries in your CMakeLists.txt then fltk::fltk will be included automatically. [3] The bundled libraries are only built if requested and are usually not needed in user projects. They are linked in with fltk::images automatically if they were built together with FLTK. The only reason you may need them would be if you used libpng, libjpeg, or zlib functions directly in your application and need to use the bundled FLTK libs (e.g. on Windows). 3.3 Exported and Imported Targets ------------------------------------ CMake terminology is to "export" and "import" library "targets". FLTK's CMake files export targets and its CONFIG module FLTKConfig.cmake imports targets so user projects can use them. Hence, if you use CMake's CONFIG mode to find FLTK all library targets will be defined using the namespace convention listed above in the "Alias" column. This is what user projects are recommended to use. In addition to the library targets FLTK defines the "imported target" 'fltk::fluid' which can be used to generate source (.cxx) and header (.h) files from fluid (.fl) files. Another target fltk::fltk-config can be used to set (e.g.) system or user specific FLTK options. This would usually be executed in the installation process of a user project but should rarely be needed and is beyound the scope of this documentation. 3.4 Building a Simple "Hello World" Program with FLTK -------------------------------------------------------- Here is a basic CMakeLists.txt file using FLTK. It is important that this file can only be used as simple as it is if you use find_package() in `CONFIG` mode as shown below. This requires that the FLTK library itself has been built with CMake. --- cmake_minimum_required(VERSION 3.15) project(hello) # optional (see below): set(FLTK_DIR "/path/to/fltk" CACHE FILEPATH "FLTK installation or build directory") find_package(FLTK 1.4 CONFIG REQUIRED) add_executable (hello WIN32 MACOSX_BUNDLE hello.cxx) target_link_libraries(hello PRIVATE fltk::fltk) --- We recommend to use `cmake_minimum_required(VERSION 3.15)` or higher for building projects that use FLTK. Lower CMake versions may work for user projects but this is not tested by FLTK developers. The optional `set(FLTK_DIR ...)` command is a superhint to the find_package command. This is useful if you don't install FLTK or have a non-standard install location. The path you give to it must be that of a directory that contains the file FLTKConfig.cmake. You can omit this statement if CMake finds the required FLTK version without it. This variable is stored in the CMake Cache so users can change it with the ususal CMake GUI interfaces (ccmake, cmake-gui) or on the CMake commandline (-D FLTK_DIR=...). The find_package command tells CMake to find the package FLTK, '1.4' says that we want FLTK 1.4.x: any patch version of 1.4 will match. 'REQUIRED' means that it is an error if it's not found. 'CONFIG' tells it to search only for the FLTKConfig.cmake file, not using the FindFLTK.cmake "module" supplied with CMake, which doesn't work with this version of FLTK. Since we specify a version (1.4) the file 'FLTKConfigVersion.cmake' must also be found. This file is created since FLTK 1.3.10. "WIN32 MACOSX_BUNDLE" in the add_executable() command tells CMake that this is a GUI app. It is ignored on other platforms than Windows or macOS, respectively, and should always be present with FLTK GUI programs for better portability - unless you explicitly need to build a "console program" on Windows. Once the package is found (in CONFIG mode, as described above) all built FLTK libraries are "imported" as CMake "targets" or aliases and can be used directly. These CMake library targets contain all necessary informations to be used without having to know about additional include directories or other library dependencies. This is what is called "Modern CMake". Older FLTK versions required to use the variables FLTK_INCLUDE_DIRS and FLTK_LIBRARIES (among others). These variables and related commands are no longer necessary if your project (CMakeLists.txt) uses CMake's CONFIG mode as described in this file. The target_link_libraries() command is used to specify all necessary FLTK libraries. Thus you may use fltk::fltk, fltk::images, fltk::gl, fltk::forms, or any combination. fltk::fltk is linked automatically if any of the other libs is included. 3.5 Building a Program Using Fluid Files ------------------------------------------- CMake has a command named fltk_wrap_ui which helps deal with fluid *.fl files. Unfortunately it is broken in CMake 3.4.x but it seems to work in 3.5 and later CMake versions. We recommend to use add_custom_command() to achieve the same result in a more explicit and well-defined way. This is a more basic approach and should work for all CMake versions. It is described below. Here is a sample CMakeLists.txt which compiles the CubeView example from a directory you've copied the test/Cube* files to. --- cmake_minimum_required(VERSION 3.15) project(CubeView) # change this to your fltk build directory set(FLTK_DIR "/path/to/fltk" CACHE FILEPATH "FLTK installation or build directory") find_package(FLTK 1.4 CONFIG REQUIRED) # run fluid -c to generate CubeViewUI.cxx and CubeViewUI.h files add_custom_command( OUTPUT "CubeViewUI.cxx" "CubeViewUI.h" COMMAND fltk::fluid -c ${CMAKE_CURRENT_SOURCE_DIR}/CubeViewUI.fl ) add_executable(CubeView WIN32 MACOSX_BUNDLE CubeMain.cxx CubeView.cxx CubeViewUI.cxx) target_include_directories(CubeView PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(CubeView PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries (CubeView PRIVATE fltk::gl) --- You can repeat the add_custom_command for each fluid file or if you have a large number of them see the fltk_run_fluid() function in CMake/FLTK-Functions.cmake for an example of how to run it in a loop. The two lines target_include_directories(CubeView PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(CubeView PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) add the current build ("binary") and source directories as include directories. This is necessary for the compiler to find the local header files since the fluid-generated files (CubeViewUI.cxx and CubeViewUI.h) are created in the current build directory and other header files may be in the source directory (depending on your project). 3.6 Building a Program Using CMake's FetchContent Module ----------------------------------------------------------- FLTK can be downloaded and built within a user project using CMake's FetchContent module. A sample CMakeLists.txt file follows. You may need to adjust it to your configuration. --- cmake_minimum_required(VERSION 3.15) project(hello) include(FetchContent) FetchContent_Declare(FLTK GIT_REPOSITORY https://github.com/fltk/fltk GIT_TAG master GIT_SHALLOW TRUE ) message(STATUS "Download and build FLTK if necessary, please wait...") FetchContent_MakeAvailable(FLTK) message(STATUS "Download and build FLTK - done.") add_executable (hello WIN32 MACOSX_BUNDLE hello.cxx) target_link_libraries(hello PRIVATE fltk::fltk) --- This is as simple as it can be. The CMake FetchContent module is used to download the FLTK sources from their Git repository and to build them. Note that this will download and build the FLTK library during the CMake configure phase which can take some time. Therefore the statement `FetchContent_MakeAvailable()` is wrapped in `message(STATUS "...")` commands to let the user know what's going on. 4 FindFLTK.cmake and find_package(FLTK) ========================================== The FindFLTK.cmake module provided by CMake which is also used in the CMake command find_package(FLTK) does not yet support FLTK's new "Modern CMake" features. Unfortunately this module has to be used if the FLTK library wasn't built with CMake and thus CONFIG mode can't be used. In this case CMake falls back to MODULE mode and find_package() uses this old CMake module. There are plans to provide a FindFLTK.cmake module with a later FLTK release. Look here for further info if you need it... fltk-1.4.3/README.Windows.txt0000644000175000017500000005015715004135251015744 0ustar albrechtalbrecht README.Windows.txt - Building FLTK under Microsoft Windows ------------------------------------------------------------ –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– *** CAUTION: This file is outdated. This needs a major rework! *** –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– CONTENTS ========== 1 INTRODUCTION 2 HOW TO BUILD FLTK USING MinGW AND Cygwin 2.1 The Tools 2.2 Recommended Command Line Build Environment 2.3 Prerequisites 2.4 Downloading and Unpacking 2.5 Configuring FLTK 2.6 Building FLTK 2.7 Testing FLTK 2.8 Installing FLTK 2.9 Creating new Projects 3 HOW TO BUILD FLTK USING MICROSOFT VISUAL STUDIO 3.1 Prerequisites 3.2 Downloading and Unpacking 3.3 Configuring FLTK 3.4 Building FLTK 3.5 Testing FLTK 3.6 Installing FLTK 3.7 Creating new Projects 4 FREQUENTLY ASKED QUESTIONS 5 LINKS 6 DOCUMENT HISTORY 1 INTRODUCTION ================== FLTK 1.3 and later is officially supported on Windows (2000,) 2003, XP, and later. Older Windows versions are not officially supported, but may still work. The main reason is that the OS version needs to support UTF-8. FLTK 1.3 is known to work on Windows Vista, Windows 7, Windows 8/8.1, and Windows 10. FLTK 1.4 and later versions may require Windows 10 or later. FLTK currently supports the following development environments on the Windows platform: - Free Microsoft "Visual C++ 2008 Express" or later or "Visual Studio Community 2013" or later. The Visual Studio project files must be generated using CMake. Visual Studio 2017 includes CMake support: "Visual Studio 2017 introduces built-in support for handling CMake projects. This makes it a lot simpler to develop C++ projects built with CMake without the need to generate VS projects and solutions from the command line. This post gives you an overview of the CMake support, how to easily get started and stay productive in Visual Studio." Citation from: https://devblogs.microsoft.com/cppblog/cmake-support-in-visual-studio/ As of this writing (07/2017) the FLTK team did not yet test and verify the functionality of Microsoft's included CMake features. - GNU toolsets (Cygwin or MinGW) hosted on Windows. CAUTION: Libraries built by any one of these environments can not be mixed with object files from any other environment! 2 HOW TO BUILD FLTK USING MinGW AND Cygwin ============================================== This chapter of this document gives a brief overview of compiling and using FLTK with the Cygwin and MinGW compiler toolkits. Both toolkits provide a build environment based around the GNU C/C++ compiler. Further information is available from the FLTK website at https://www.fltk.org, such as this Howto note: https://www.fltk.org/articles.php?L598 The Cygwin build environment supplies a library (the Cygwin DLL) that is primarily intended to provide a number of Unix-like POSIX facilities for programs being ported to the Windows environment (Win32 or WinNT). Cygwin also supplies a very Unix-like build environment for Windows, including the "BASH" Bourne-compatible shell and all of the standard Unix file utilities (ls, cat, grep, etc.). Cygwin is developed by Cygnus (now part of RedHat, Inc). Although provided for free download under the GPL, distributing programs that require the Cygwin DLL under a license other than the GPL requires a commercial license for the Cygwin DLL. Native Windows programs that do not require the Cygwin DLL (cross-compiled and linked with the MinGW gcc/g++ cross compilers supplied with Cygwin) may be released under any license freely. Currently you would have to install mingw64-i686-gcc-g++ for 32-bit Windows applications (despite its name!), and/or mingw64-x86_64-gcc-g++ for 64-bit applications. You may also need to install the corresponding '-headers' packages as well. Currently these tools support gcc 4.5 or newer. The setup for FLTK is somewhat more complicated because you must configure this as a cross compiler, but it works well. The MinGW distribution (Minimalist GNU for Windows) provides a similar toolset but geared solely towards native Windows development without the Unix-like POSIX library. The lack of any libraries under the GPL or any other restrictive license means that programs built with the MinGW environment may always be released under any license freely. MinGW also supplies a Unix-like build environment for Windows, including MSYS (a Bourne-compatible shell) and the standard Unix file utilities (ls, cat, grep, etc.) If you are not familiar with these GNU-like toolkits please refer to the links section later in this note. In particular, check out their license conditions carefully before use. The Tools ----------- There are currently four main configurations supported by FLTK with the GNU tools: 1. Cygwin: Built using the Cygwin toolset and using the Unix-like POSIX compatibility layer provided by the Cygwin DLL. License: GPL or non-free commercial license (ask Redhat). Note: no longer tested by the FLTK team. 2. Cygwin using the MinGW cross compiler suite: Built using the Cygwin tools but not using the Cygwin DLL. License: freely distributable on all Windows systems. Note: no longer tested by the FLTK team. 3. MinGW: Built using the MinGW utilities, compiler and tools. This is, in many aspects, analogous to (2.). This is the recommended one if you want to build native Windows programs only. License: freely distributable on all Windows systems. 4. MSYS2/Mingw-w64: Built using the MSYS2 utilities, compiler and tools. This similar to (3.) but may need some fiddling with the setup if you want to build native Windows programs only because the built executables *may* depend on some MSYS2 dll's. License: freely distributable on all Windows systems. Recommended Command Line Build Environment -------------------------------------------- Our recommendation is to: 1. Get the current Cygwin toolset. This can either produce executables that do or do not rely on the Cygwin DLL (check licensing) at your choice. 2. Get the latest MinGW toolset. It is recommended that you also get the MSYS shell and the msysDTK developer toolset. This will only produce normal Windows native executables without any Unix or POSIX compatibility layer. 3. Get the latest MSYS2/Mingw-w64 toolset. See the links section below for more information. Either option can generate Windows native executables and option 1 can provide a Unix-like POSIX portability layer that is reliant on a GPLed library. See the later sections for detailed information about using one of these configurations. Prerequisites --------------- In order to build FLTK from the command line, you need to install the MinGW environment. The graphical installer "mingw-get-inst" can be downloaded for free. NOTE: as of Dec 07, 2024 MinGW development seems to be dormant or dead. According to Wikipedia (https://en.wikipedia.org/wiki/MinGW) "MinGW migrated to OSDN". See link section below. Launch the installer and follow the instructions. In the "Select Components" dialog, add "C++ Compiler", "MSYS Basic System", and "MinGW Developer Toolkit". Wait for the installer to finish. After downloading and installing, you need to launch the MinGW Shell through the Start menu. Downloading and Unpacking --------------------------- Download FLTK from here: https://www.fltk.org/software.php into your home folder. The default location as seen from Windows is similar to C:\MinGW\msys\1.0\home\matt\ If you are familiar with "git" and like to stay current with your version, you will find the git access parameters at the bottom of that page. Unpack FLTK into a convenient location. I like to have everything in my dev directory: cd mkdir dev cd dev tar xvzf fltk-1.x.y-source.tar.gz cd fltk-1.x.y Configuring FLTK ------------------ If you got FLTK via git then you need one extra step. Otherwise skip over this part. Stay in your FLTK source-code directory and type the following: autoconf Now configure your FLTK installation: ./configure Hint: Instead of executing `autoconf` and `configure` followed by `make` to build FLTK (see next section) you can also run `make` directly which will create and execute the 'configure' script with default parameters and build FLTK with the default configuration. ADVANCED: type "./configure --help" to get a complete list of optional configuration parameters. These should be pretty self-explanatory. Some more details can be found in README. :END_ADVANCED The configuration script will check your machine for the required resources which should all have been part of your MinGW installation. Review the Configuration Summary, maybe take some notes. ADVANCED: some versions of MinGW/Msys are broken and complain about a missing --enable-auto-import. The solution is to upgrade to the current release. If that is not possible, you can include the --enable-auto-import flag when linking: ./configure LDFLAGS=-Wl,--enable-auto-import :END_ADVANCED Known Problems: There is a known incompatibility with some Windows git tools that may not set the correct line endings for autoconf. If you get strange error messages when running ./configure or make, you may need to convert configh.in to "Unix line endings" (LF-only). These error messages are unspecific, e.g. compilation errors like: error: 'U32' does not name a type error: 'bmibuffer' was not declared in this scope You can fix the line endings with the MinGW/msys tool 'unix2dos' (u2d) or with your favorite editor, if it allows to change the line endings, then run autoconf and ./configure again. We don't know if this issue is still relevant with current Git tools. It has been reported when we were still using Subversion (svn). For further information see this bug report (regarding svn) https://www.fltk.org/newsgroups.php?gfltk.bugs+v:10197 Building FLTK --------------- Now this is easy. Stay in your FLTK source-code directory and type: make The entire FLTK toolkit including many test programs will be built for you. No warnings should appear. Testing FLTK -------------- After a successful build, you can test FLTK's capabilities: test/demo Installing FLTK ----------------- If you did not change any of the configuration settings, FLTK will be installed in "/usr/local/include" and "/usr/local/lib" by typing make install It is possible to install FLTK in user space by changing the installation path to a location within the user account by adding the "--prefix=PREFIX" parameter to the "./configure" command. Creating new Projects ----------------------- FLTK provides a neat script named "fltk-config" that can provide all the flags needed to build FLTK applications using the same flags that were used to build the library itself. Running "fltk-config" without arguments will print a list of options. The easiest call to compile an FLTK application from a single source file is: fltk-config --compile myProgram.cxx "fltk-config" and "fluid" will be installed in "/usr/local/bin/" by default. We recommend that you add it to the command search path. 3 HOW TO BUILD FLTK USING MICROSOFT VISUAL STUDIO ===================================================== Prerequisites --------------- In order to build FLTK from within Visual Studio, you need to install the Visual C++ developer environment from the Microsoft web site. The "Express" or "Community" edition is free of charge and sufficient to develop FLTK applications: https://visualstudio.microsoft.com/free-developer-offers/ If you intend to use an older (maybe commercial) version you need at least a version that is supported by the version of CMake you are using to generate the project files. You should make sure that all available service packs are installed or building FLTK may fail. As of Juli 2017 the FLTK team recommend at least Visual Studio 2008 with current service packs. Visual Studio 2008, 2010, 2013, 2015, and 2017 are known to work with FLTK 1.4.0 (Git master, as of Juli 2017). For development of FLTK 1.4 or higher Visual Studio 2019 Community or later versions are highly recommended. You may also need to install CMake (cmake-gui) from: https://cmake.org/download/ Visual Studio 2017 (and later) has internal CMake support (so you may not need to install CMake separately). There is an option to "open a folder" with a CMakeLists.txt file - in our case the FLTK root folder. You may want to try this. Note that this has not yet been tested thoroughly by the FLTK team. Downloading and Unpacking FLTK -------------------------------- Download FLTK from here: https://www.fltk.org/software.php If you are familiar with "git" and like to stay current with your version, you will find the git access parameters at the bottom of that page. Unpack FLTK by using an appropriate unpacker and copy the new folder into a convenient location, for instance a "dev" folder in your home folder. Configuring FLTK ------------------ Note: Configuration with Visual Studio 2017's internal CMake support is not yet included in this document. You may try yourself... Please refer to README.CMake.txt for how to configure FLTK with CMake. Once you have followed the instructions you should have created a new build directory with the Visual Studio Solution (project files) for FLTK. Launch Visual Studio and open the project file (FLTK.sln) or double-click on FLTK.sln in the Windows Explorer. Choose "Debug" or "Release" mode from the "Solution Configurations" menu. Building FLTK --------------- Use the context menu of the "demo" project to "Set as StartUp Project". Then select "Build Solution" from the "Build" menu or press F7 to build all libraries. Testing FLTK -------------- Select "Start Debugging" from the "Debug" menu or just press F5 to run the Demo program. Use "Demo" to explore all test programs. Installing FLTK ----------------- ******************************************************************************** The information in this chapter is NO LONGER RECOMMENDED by the FLTK team. ******************************************************************************** The default location for VisualC 2008 libraries and headers is here: C:\Program Files\Microsoft Visual Studio 9.0\VC\ It is possible to move the FLTK libraries, headers, and Fluid into the respective subdirectories, so that they are available for future development without adding link and include paths to the solution. copy the entire FL directory into the include path add /FL/fl_config.h copy all .lib files from the fltk build directory to the VC lib directory copy fluid.exe in the fluid directory to the bin directory We highly discourage using dll's (dynamically linking libraries) on Windows because they will require an installation process and likely cause version conflicts. Use the static .lib libraries instead. Creating new Projects ----------------------- ******************************************************************************** The information in this chapter is NO LONGER RECOMMENDED by the FLTK team. ******************************************************************************** This chapter assumes that libraries and headers were copied into C:\Program Files\Microsoft Visual Studio 9.0\VC\ Create a new project of type "General", "Empty Project" and add a simple "C++" file to it. The FLTK "hello" source code is a good base. Now open the Project Properties dialog and add "Comctl32.lib" and all the FLTK libraries that you want to use (at least "fltk.lib") to Additional Dependencies (Configuration Properties > Linker > Additional Dependencies). Compile and run your test program with F5. You can also include .fl resources: add a new Header file to your project, but let the name end in .fl. Right-click and select "Open with...". Add "fluid.exe" from the "bin" directory and set it as the default editor. To automatically compile .fl files, open the Properties editor and set the Custom Build Steps to: Command Line: fluid.exe -c $(InputPath) Description: Compiling Fluid .fl file Outputs: $(InputDir)$(InputName).cxx; $(InputDir)$(InputName).h Now add the generated .cxx file to your project as well. Whenever the .fl file is changed, the corresponding .cxx file will be recompiled. 4 FREQUENTLY ASKED QUESTIONS ================================ Why does a console window appear when I run my program? --------------------------------------------------------- Windows has a flag that determines whether an application runs in the foreground with a console or in the background without a console. If you're using gcc (i.e. MinGW or Cygwin), then use the linker option "-mwindows" to make your application run in the background and "-mconsole" to run in the foreground. Use fltk-config --ldflags to see appropriate linker flags, or use fltk-config --compile to compile a single source file. If you're using MS VC++, then you must set the linker option "/subsystem:windows" to create a "Windows" program (w/o console window), or set the linker option "/subsystem:console" for a console program, i.e. with a console window. These options are set differently in the FLTK project files, depending on whether you select a "Debug" or "Release" build. Other compilers and build systems may have different options. Keep in mind that a windows application cannot send output to stdout, even if you run it from an existing console application. (Note: A special case of this exists if running a MinGW application from the command line of an MSYS shell, when an application is able to write to stdout, even if compiled with "-mwindows". The same applies to Cygwin.) How do I get OpenGL to work? ------------------------------ Both builds should automatically support OpenGL. The configuration file config.h has a number of settings which control compile-time compilation. One such setting is "HAVE_GL". This may be set to 0 to disable Open GL operation. Changing the line in config.h to #define HAVE_GL 1 will change this to compile and link in OpenGL. 5 LINKS =========== The following links may be of use: 1. Cygwin Homepage: https://www.cygwin.com/ 2. MinGW Homepage - see Wikipedia: https://en.wikipedia.org/wiki/MinGW (English) https://de.wikipedia.org/wiki/MinGW (German, see links) -------------------------------------------------------------------- IMPORTANT: As of Dec 07, 2024 the links below could not be verified: -------------------------------------------------------------------- Repository : https://osdn.net/projects/mingw/scm/ Website (1): https://osdn.net/projects/mingw/ Website (2): https://mingw.osdn.io/ 3. MSYS2/Mingw-w64 Wikipedia and Homepage: https://en.wikipedia.org/wiki/Mingw-w64 https://mingw-w64.org/ https://www.msys2.org/ 4. Check out the FLTK newsgroups at the FLTK homepage: https://www.fltk.org/ Its archival search facilities are EXTREMELY useful to check back through previous problems with this sort of configuration before posting new questions. 5. GNU Compiler Collection (GCC) compiler homepage: https://gcc.gnu.org/ 6. OpenGL page - for OpenGL and GLUT libs https://www.opengl.org/ 7. CMake homepage: https://cmake.org/ Note 1: all links in this document have been checked and verified on Dec 07, 2024 except where noted above. Note 2: We can't guarantee that these links will be valid any time later. 6 DOCUMENT HISTORY ====================== The document history is no longer maintained in this document. Please consult the Git history instead. Examples: git log -- README.Windows.txt git log -- README.MSWindows.txt (previous, renamed version) gitk -- README.Windows.txt fltk-1.4.3/.clang-format0000644000175000017500000001205115004135251015157 0ustar albrechtalbrecht# # clang-format control file for the FLTK project. # # Copyright 2017-2022 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this # file is missing or damaged, see the license at: # # https://www.fltk.org/COPYING.php # # Please see the following page on how to report bugs and issues: # # https://www.fltk.org/bugs.php # # # Important notes: # # This is a preliminary, experimental version of a clang-format control file. # To use all options including embedded comments to switch formatting # temporarily off and on in source files (see below) clang-format 3.6 # or later is required. # # DO NOT USE WITHOUT CHECKING THE RESULT OF FORMATTING FOR CORRECTNESS # AND COMPATIBILITY WITH THE FLTK CMP! # https://www.fltk.org/cmp.php#CODING_STANDARDS # # For more information about clang-format please refer to the online docs at: # https://clang.llvm.org/docs/ClangFormat.html # https://clang.llvm.org/docs/ClangFormatStyleOptions.html # # Embedded comments ("clang-format pragma's") in the source code: # // clang-format off # // clang-format on # /* clang-format off */ # /* clang-format on */ # can be used to switch clang-format(ting) temporarily off in a source file. # This is particularly useful for embedded pixmaps and other tables # like menu arrays that are pre-formatted for better readability. # The options used for FLTK are based on predefined style options of LLVM, # which are also the default settings of clang-format. # For a full list of LLVM settings please use # clang-format -style=llvm -dump-config # FLTK settings (currently experimental). BasedOnStyle: LLVM # The Language tag marks C++ options # Language: Cpp # The following options override the LLVM style definitions, if set. # Uncomment one of the following option lines if indenting with tabs # shall be used. Note: tab spacing is still 8 columns, tabs are only # used for indents of 8 columns or more. # # Option "Always" seems to fail counting columns: comments may not be # adjusted as expected (as of clang-format 3.6 and 3.8). # This applies only if "AlignTrailingComments: true" is also set (default). # # UseTab can be set to 'Never' (default) or 'ForIndentation' to avoid # this annoying bug of clang-format. # # UseTab: Always UseTab: Never # Should we extend code lines beyond 80 columns ? # Default: 80 ColumnLimit: 100 # The FLTK CMP requires that case labels are indented (LLVM: false) IndentCaseLabels: true # Should we keep two or more consecutive empty lines ? # LLVM default is 1. MaxEmptyLinesToKeep: 2 # Present FLTK source code contains some short blocks and if statements # in one line, but we should better make it consistent and NOT use the # following "Allow..." statements (leave them commented out): # # LLVM default values: # # AllowShortBlocksOnASingleLine: false # AllowShortFunctionsOnASingleLine: All # AllowShortIfStatementsOnASingleLine: false # AllowShortLoopsOnASingleLine: false # # FLTK values: # AllowShortBlocksOnASingleLine: true # AllowShortIfStatementsOnASingleLine: true # Short inline functions in header files are an exception to the above "rule": AllowShortFunctionsOnASingleLine: Inline # The following is particularly useful for macros with continuation lines. # LLVM default: AlignEscapedNewlinesLeft: false AlignEscapedNewlinesLeft: true # Include files should be left as-is until we *know* we can # sort them without bad side effects. # LLVM default: true SortIncludes: false # Multiple constructor initializers must be on consecutive lines. # Note: this is NOT (always) true in current FLTK code! BreakConstructorInitializersBeforeComma: true # Constructor initializers will be indented by 2 spaces. # LLVM default: 4 ConstructorInitializerIndentWidth: 2 # Continuation lines (if automatically wrapped) may be indented differently. # This does not apply to function call arguments which are aligned to the # opening bracket. # LLVM default: 4 # ContinuationIndentWidth: 2 # Most of FLTK's code uses 'void *p' as opposed to 'void* p'. # This is particularly useful in combined declarations like: # int var, var2, *pv, **pp; # Note: clang-format uses "Right" in such combined declarations anyway, # so to be consistent the best setting appears to be "Right". # clang-format can try to derive the setting from code in the file, but this # is error-prone and can lead to inconsistent settings in different files. # Note: this also applies to references like 'int &w, int &h', for instance # in function parameter lists. DerivePointerAlignment: false PointerAlignment: Right fltk-1.4.3/fltk.xpm0000644000175000017500000010402515004135251014275 0ustar albrechtalbrecht/* XPM */ static const char * const fltk_xpm[] = { "229 70 152 2", " c None", ". c #000066", "+ c #68689A", "@ c #9292AF", "# c #232377", "$ c #CCCCCC", "% c #31317E", "& c #7878A2", "* c #5D5D95", "= c #1F1F76", "- c #31317F", "; c #11116F", "> c #B4B4C0", ", c #ADADBC", "' c #4C4C8C", ") c #595993", "! c #3A3A83", "~ c #7373A0", "{ c #51518E", "] c #A1A1B6", "^ c #49498B", "/ c #8989AA", "( c #020267", "_ c #050568", ": c #444488", "< c #71719F", "[ c #1A1A73", "} c #5E5E95", "| c #9E9EB5", "1 c #252578", "2 c #A4A4B8", "3 c #666699", "4 c #2B2B7C", "5 c #8383A7", "6 c #10106E", "7 c #6D6D9D", "8 c #0B0B6B", "9 c #CBCBCB", "0 c #010166", "a c #7979A2", "b c #6E6E9D", "c c #0A0A6B", "d c #7676A1", "e c #C9C9CA", "f c #2A2A7B", "g c #9696B1", "h c #6A6A9B", "i c #262679", "j c #49498A", "k c #C2C2C7", "l c #47478A", "m c #BCBCC4", "n c #424287", "o c #4A4A8B", "p c #C5C5C9", "q c #454588", "r c #BBBBC3", "s c #434388", "t c #69699B", "u c #535390", "v c #5B5B93", "w c #73739F", "x c #CACACB", "y c #8888AA", "z c #050569", "A c #7F7FA5", "B c #7575A0", "C c #8C8CAC", "D c #8A8AAB", "E c #13136F", "F c #09096B", "G c #C8C8CA", "H c #040468", "I c #7474A0", "J c #8F8FAD", "K c #12126F", "L c #08086A", "M c #70709E", "N c #C7C7CA", "O c #0D0D6C", "P c #07076A", "Q c #8B8BAC", "R c #8787AA", "S c #6F6F9D", "T c #0F0F6E", "U c #7575A1", "V c #8787A9", "W c #CBCBCC", "X c #11116E", "Y c #7777A2", "Z c #8585A9", "` c #8B8BAB", " . c #8383A8", ".. c #030367", "+. c #070769", "@. c #8484A8", "#. c #0F0F6D", "$. c #0D0D6D", "%. c #0C0C6C", "&. c #8181A7", "*. c #ABABBC", "=. c #B5B5C0", "-. c #1E1E75", ";. c #A3A3B7", ">. c #242478", ",. c #A8A8BA", "'. c #141470", "). c #A5A5B8", "!. c #252579", "~. c #A5A5B9", "{. c #191973", "]. c #B5B5C1", "^. c #161671", "/. c #B7B7C1", "(. c #A3A3B8", "_. c #212177", ":. c #B2B2BF", "<. c #B0B0BE", "[. c #232378", "}. c #AEAEBD", "|. c #B6B6C1", "1. c #212176", "2. c #C3C3C8", "3. c #ABABBB", "4. c #151570", "5. c #414186", "6. c #BBBBC4", "7. c #B9B9C2", "8. c #1D1D75", "9. c #464689", "0. c #BFBFC6", "a. c #A7A7B9", "b. c #28287A", "c. c #010167", "d. c #BDBDC5", "e. c #B9B9C3", "f. c #454589", "g. c #BDBDC4", "h. c #A9A9BB", "i. c #414187", "j. c #C0C0C6", "k. c #27277A", "l. c #3E3E85", "m. c #A6A6B9", "n. c #C3C3C7", "o. c #151571", "p. c #030368", "q. c #0B0B6C", "r. c #B1B1BF", "s. c #404086", "t. c #C7C7C9", "u. c #0E0E6D", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ : < @ @ @ @ @ @ @ @ @ @ @ @ [ . . . . . . . . . . . . . . . . . . . . . t @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ u . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . . c w x $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ y z . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . 0 B $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ C z . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . h $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ D E . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . F < G $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ y F . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . H I $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ J . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . 7 $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ y K . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . L M N $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 9 / O . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . P I $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ Q . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . M $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ R 6 . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . z S N $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 9 D T . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . F U $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ y . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ & * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * = $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ * * * * * * * * * * * * * * * * * * * * * * * * 2 $ $ $ $ $ $ $ $ $ $ $ $ $ 3 * * * * * * * * * * * * * * * * * * * * * * * 4 | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . ~ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ V O . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . ( 7 G $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ W C X . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . 8 Y $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ Z . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . d $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ R F . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . 7 x $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ` ; . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . 8 & 9 $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ .... . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . 0 a $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ / _ . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . b $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ y ; . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 c d e $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 5 +.. . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ f & $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ D . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ g $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ Z 6 . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 9 @.c . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ R . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @.#.. . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ > , , , , , , , , , , , , , , , , , , , , , , , , , , , ' . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ x Z $.. . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @.%.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 9 V #.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ &.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @.L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ *.$.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ =.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ;.>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ,.'.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ > [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ).!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ) . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ~.{.. . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ > , , , , , , , , , , , , , , , , , , , , , , , , , , , ' . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ].^.. . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ,.!.. . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ h $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 2 -.. . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ i j k $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ /.X . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . l m $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ *.1 . . . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . n $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ (._.. . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . o p $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ :.; . . . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . q r $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ <.[.. . . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . s G $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 2 >.. . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . o x $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ }.K . . . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . n r $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ |.1.. . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . q 2.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ).i . . . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . l $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 3.4.. . . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . 0 5.6.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 7.8.. . . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ( . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . 9.0.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ a.b.. . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . : $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ,.[ . . . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . c.n d.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ e.{.. . . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . f.g.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ h.b.. . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . i.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ a.= . . . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . c.: j.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ r '.. . . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . : r $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ , k.. . . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . l.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ m.[.. . . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . . q n.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ |.o.. . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . . . n e.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ r.i . . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . . . . s.N $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ m.i . . ", ". . @ $ $ $ $ $ $ $ $ $ $ $ $ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ _ . . . . . . . . . . . . . . . . . . . . 5 $ $ $ $ $ $ $ $ $ $ $ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . | $ $ $ $ $ $ $ $ $ $ $ $ 1 . . . . . . . . . . . . . . . . . . . . . . q t.$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ r.T . ", ". . + @ @ @ @ @ @ @ @ @ @ @ @ [.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . %.@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ p.. . . . . . . . . . . . . . . . . . . . } @ @ @ @ @ @ @ @ @ @ @ @ @ q.. . . . . . . . . . . . . . . . . . . . . . . . < @ @ @ @ @ @ @ @ @ @ @ @ [ . . . . . . . . . . . . . . . . . . . . . . . s.@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ u.. ", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "}; fltk-1.4.3/documentation/0000755000175000017500000000000015004135251015456 5ustar albrechtalbrechtfltk-1.4.3/documentation/copyright.dox.in0000644000175000017500000000007315004135251020607 0ustar albrechtalbrechtCopyright © 1998 - @YEAR@ by Bill Spitzak and others. fltk-1.4.3/documentation/Doxyfile.in0000644000175000017500000032716115004135251017603 0ustar albrechtalbrecht# Doxyfile 1.8.14 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See # https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "FLTK @FLTK_VERSION@" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = NO # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines (in the resulting output). You can put ^^ in the value part of an # alias to insert a newline as if a physical newline was in the original file. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. # Minimum value: 0, maximum value: 99, default value: 0. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 0 # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = YES # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = @DRIVER_DOCS@ # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = NO # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src/index.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/preface.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/intro.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/basics.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/common.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/coordinates.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/resize.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/editor.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/Fl_Terminal.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/drawing.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/events.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/subclassing.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/opengl.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/fltk-options.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/advanced.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/unicode.dox \ @FLTK_SOURCE_DIR@/FL \ @FLTK_SOURCE_DIR@/src \ @CMAKE_CURRENT_SOURCE_DIR@/src/enumerations.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/glut.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/forms.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/osissues.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/migration_1_4.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/development.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/license.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/examples.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/faq.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/wayland.dox \ @CMAKE_CURRENT_SOURCE_DIR@/src/bundled-libs.dox # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: https://www.gnu.org/software/libiconv/) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. FILE_PATTERNS = *.H \ *.h \ *.c \ *.cxx \ *.dox # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = @FLTK_SOURCE_DIR@/src/drivers/ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = */src/*_win32.cxx \ */src/*_mac.cxx \ */src/*_x.cxx \ */src/xdg* \ */src/text-input* \ */src/*-client-protocol.h # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/../test \ @CMAKE_CURRENT_SOURCE_DIR@/../examples \ @CMAKE_CURRENT_BINARY_DIR@ \ @CMAKE_CURRENT_SOURCE_DIR@ # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = *.cxx \ *.h \ *.H \ *.fl # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/src # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = fl_ \ FL_ \ Fl_ #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = @GENERATE_HTML@ # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE tag can be used to specify if the generated HTML output # should be rendered with a dark or light theme. # Possible values are: LIGHT always generate light mode output, DARK always # generate dark mode output, AUTO_LIGHT automatically set the mode according to # the user preference, use light mode if no preference is set (the default), # AUTO_DARK automatically set the mode according to the user preference, use # dark mode if no preference is set and TOGGLE allow to user to switch between # light and dark mode via a button. # The default value is: AUTO_LIGHT. # This tag requires that the tag GENERATE_HTML is set to YES. # Note: since doxygen 1.9.5 HTML_COLORSTYLE = TOGGLE # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via Javascript. If disabled, the navigation index will # consists of multiple levels of tabs that are statically embedded in every HTML # page. Disable this option to support browsers that do not have Javascript, # like the Qt help browser. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_MENUS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: https://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = YES # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # https://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from https://www.mathjax.org before deployment. # The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/ # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /